Index: config.php.sample
===================================================================
--- config.php.sample	(revision 1152)
+++ config.php.sample	(working copy)
@@ -32,7 +32,10 @@
 // Slashes at both ends.
 define("IA_URL_PREFIX", "--write-me-IA_URL_PREFIX--");
 
+// Define the place the avatars are being stored
+define("IA_AVATAR_FOLDER", "--write-me-IA_AVATAR_FOLDER--");
 
+
 // Congratulations! You're done with the essential configuration.
 // --------------------------------------------------------------
 // There are some more settings to adjust but they are optional.
Index: db.sql
===================================================================
--- db.sql	(revision 1152)
+++ db.sql	(working copy)
@@ -1,8 +1,8 @@
--- MySQL dump 10.13  Distrib 5.1.37, for debian-linux-gnu (i486)
+-- MySQL dump 10.13  Distrib 5.1.54, for debian-linux-gnu (i686)
 --
 -- Host: localhost    Database: infoarena2
 -- ------------------------------------------------------
--- Server version	5.1.37-1ubuntu5.1
+-- Server version	5.1.54-1ubuntu4
 
 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
 /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
@@ -34,7 +34,7 @@
   PRIMARY KEY (`id`),
   UNIQUE KEY `name_page_index` (`name`,`page`),
   KEY `remote_ip_info` (`remote_ip_info`)
-) ENGINE=MyISAM AUTO_INCREMENT=52192 DEFAULT CHARSET=utf8;
+) ENGINE=MyISAM AUTO_INCREMENT=52193 DEFAULT CHARSET=utf8;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -1130,7 +1130,7 @@
 
 LOCK TABLES `ia_smf_members` WRITE;
 /*!40000 ALTER TABLE `ia_smf_members` DISABLE KEYS */;
-INSERT INTO `ia_smf_members` VALUES (2,'fluffy',1077052570,146,1,'',1263065043,'Dan-Leonard Crestez',23,2,'','7b1045aac728fec00a86a68aba993d6d85a74529','fluffy@example.com','',1,'0001-01-01','','','','','','crestez_leonard','',0,1,'','',0,'http://nobody.devnet.ro/pr0n.jpg',1,9,76,'',1,1,'','','',1,1,'',34704,'','',13,288783,'d98b','','',0,2,''),(3,'domino',1077054064,1321,1,'',1272143901,'Mircea Pasoi',154,0,'','6bd0a33ee98c8bf6aed56c6fe710002bde6048b3','domino@example.com','',1,'0001-01-01','http://infoarena.devnet.ro','http://infoarena.devnet.ro','','324694544','','bogdanpasoi','mircea_pasoi',0,1,'','',0,'',1,185,430,'',1,1,'','','',1,1,'',40559,'','',18,2129658,'ba10','','',0,2,''),(10,'svalentin',1077384310,675,1,'',1272121256,'Valentin Stanciu - UPB',49,0,'','dfdfb51287c0b7472c0c501394f0440f9dcf14c9','svalentin@example.com','',1,'0001-01-01','','','','','','','',1,1,'%d-%m-%Y, %H:%M:%S','',0,'',1,134,212,'',1,1,'','','',1,1,'',40410,'','',18,456179,'c918','','',1,2,''),(27,'Cosmin',1077805323,1245,1,'',1272150352,'Cosmin Negruseri',80,0,'','95ddb1caf1d978e1cce9074bb1affbea2dcb7421','Cosmin@example.com','',0,'0001-01-01','','','','','','','',1,1,'','',0,'',1,198,355,'',1,1,'','','',1,1,'',40584,'','',18,1628032,'6561','','',0,2,''),(33,'ste_fanus',1078046877,5,0,'',1252654248,'Gheorghe Stefan',0,0,'','3622116a73d425b915f5922435acc25654c451be','ste_fanus@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,1,1,'',1,1,'','','',1,1,'',35239,'','',9,3839,'','','',0,2,''),(37,'amadaeus',1078087693,91,0,'',1242572550,'Lucian Boca',15,0,'','3586acf9cf25ded897d9aadf0855feab8592f462','amadaeus@example.com','',0,'0001-01-01','','','','','','','',1,1,'','&quot;one of these days I\'m going to cut you into little pieces...&quot;',0,'',1,23,50,'',1,1,'','','',1,1,'',32067,'','',11,180887,'10a4','','',0,2,''),(43,'greco',1078267126,434,1,'',1248428530,'Tiberiu-Lucian Florea',29,2,'','aaf53667e069463f8c21f09642e068e526cad665','greco@example.com','',0,'0001-01-01','','','','','','','',1,1,'','Jump in the cockpit and start up the engines\r<br />Remove all the wheelblocks there\'s no time to waste\r<br />Gathering speed as we head down the runway\r<br />Gotta get airborne before it\'s too late.',0,'',1,63,197,'',1,1,'','','',1,1,'',32918,'','',18,165933,'72fd','','',0,2,''),(47,'wickedman',1078654068,661,1,'',1272049192,'Cristian George Strat',86,0,'','63e05201f16771dd6d4694b502a4fb0dbdac0780','wickedman@example.com','',1,'0001-01-01','http://cristian.infoarena.ro/','http://cristian.infoarena.ro/','','','','','',1,1,'','Whatever happened to people I used to care about?',0,'',1,50,260,'',1,1,'','','',1,1,'',40556,'','',18,463833,'555a','','',0,2,''),(69,'silviug',1080394491,484,1,'',1269718857,'Silviu-Ionut Ganceanu',100,2,'','9678b7723d81d9a0eab85832847123c6cfc0dda4','silviug@example.com','',1,'0001-01-01','','','','','','private','private',1,1,'','&quot;Don&#039;t gain the world and lose your soul, wisdom is better than silver or gold.&quot; [Bob Marley - Jamaican reggae musician &amp; singer (1945 - 1981)]',0,'',1,35,219,'',1,1,'','','',1,1,'',35081,'','',18,376806,'22fd','','',0,2,''),(79,'filipb',1080409243,887,1,'',1272100145,'Filip Cristian Buruiana UPB',142,0,'','811bbf59e81ca6425274da0ef63e29dffd48d9a1','filipb@example.com','',1,'0001-01-01','','','','','','','',1,1,'','',0,'',1,89,295,'',1,1,'','','',1,1,'',40558,'','',18,1084916,'a792','','',0,2,''),(103,'fireatmyself',1083148315,500,0,'',1266852405,'Bogdan A. Stoica',25,1,'','cf86af8a0a30f5e088b37e4903f5b45f06d1c34f','fireatmyself@example.com','',1,'0001-01-01','','','','','','fireatmyself','',1,1,'','Viata e scurta. Daca nu o putem lungi, macar s-o facem lata.',0,'',1,326,358,'',1,1,'','','',1,1,'e0e6524541',38382,'','',18,359463,'4b60','','',0,2,''),(121,'azotlichid',1094553845,232,1,'',1272154682,'Adrian Vladu',30,0,'','c2e30bcb9a5615e5934d178c6fd7ebc15ac54006','azotlichid@example.com','',0,'0001-01-01','','','','','','','',1,1,'','',0,'',1,42,80,'',1,1,'','','',1,1,'',40582,'','',18,650596,'224d','','',0,2,''),(150,'rake',1105796010,2,0,'',1113593462,'Popa Tudor Iulian',0,0,'','fcd0eb35de617a413cdf2902cbdd8195bd875ff3','rake@example.com','',0,'0001-01-01','','','','','','','',1,1,'','&quot;Most people don\'t dance if they don\'t know who\'s singing,/Why ask your head? It\'s your hips that are swinging!&quot; (Propellerheads)',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',9,0,'','','',0,2,''),(154,'bogdan2412',1106323789,842,1,'',1272146727,'Bogdan-Cristian Tataroiu',103,0,'','502a034d392375d878a486dd851084462a9e6273','bogdan2412@example.com','',1,'0001-01-01','','','','','','','',0,1,'','',0,'',1,117,399,'',1,1,'','','',1,1,'',40567,'','',18,3854333,'64f2','','',1,1,''),(221,'victorsb',1109101822,1,1,'',1270170896,'Victor Rusu',4,1,'','4f6c786b29acccb5052902481fa24cccd4c9635c','victorsb@example.com','',0,'0001-01-01','','','','','','','',1,1,'','',0,'',1,1,6,'',1,1,'','','',1,1,'',40178,'','',9,125591,'','','',0,2,''),(250,'gogu',1109170639,85,0,'',1262873773,'Gogu Marian',1,0,'*','4a87b47b961aeea7a19349350cb40c13b688d95d','gogu@example.com','',0,'0001-01-01','','','','','','','',0,0,'','',0,'',1,37,67,'',0,0,'','','',1,1,'',35970,'','',11,123314,'cf25','','',0,2,''),(257,'tm_radu',1109177334,140,0,'',1236166427,'Toma Radu',16,2,'','a44856f0bd0907c5425d9f120b5d3e25c2ac6e21','tm_radu@example.com','',1,'0001-01-01','','','','','','radu_thekid','',1,1,'','Daca nu merge o preblema, depaneaz-o, si abia apoi arunci calculatoru pe geam',0,'',1,30,43,'',1,1,'','','',1,1,'',29764,'','',13,310709,'57f1','','',0,2,''),(303,'geo88',1109694397,0,0,'',1139571424,'george arion',0,0,'','f55140815c163b9241f99e2d408125617f87cc43','geo88@example.com','',0,'0001-01-01','','','','','','','',1,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(308,'alexthero',1109936951,125,1,'',1271150473,'Tandrau Alexandru',13,0,'','8bf4a0ca7f0b84427894f3b90e6786b6fef376c7','alexthero@example.com','',1,'0001-01-01','','','','','','alexthero','',0,1,'','Tine minte ca mintea conduce pumnu, nu invers',0,'',1,29,145,'',1,1,'','','',1,1,'',39471,'','',13,584310,'dc54','','',0,2,''),(312,'efer',1110024516,19,0,'',1233776447,'Liviu Ciortea',3,1,'','f831d7a53887b6b1df443a8394298512b5473e90','efer@example.com','',0,'0001-01-01','','','','','liviuefer','liviuefer','',1,1,'','',0,'',1,2,10,'',1,1,'','','',1,1,'',28805,'','',9,23057,'3c40','','',0,2,''),(335,'gcosmin',1111250221,231,1,'',1272101521,'Gheorghe Cosmin',20,0,'','bb4b40f220ae2f69cb0db74a0622c94039448c60','gcosmin@example.com','',0,'0001-01-01','','','','','','','',1,1,'','',0,'',1,41,205,'',1,1,'','','',1,1,'',40558,'','',18,702962,'c4d6','','',0,2,''),(343,'stef2n',1111314179,613,1,'',1272154541,'Stefan Istrate',16,0,'','6750b2965c97de05c5dac1328ac45045d425361f','stef2n@example.com','',1,'0001-01-01','','','','','','stef2n','',0,1,'','Exista 10 categorii de oameni: cei care inteleg sistemul binar si cei care nu il inteleg.',0,'',1,123,329,'',1,0,'','','',1,1,'',40514,'','',18,2729764,'6fbc','','',0,2,''),(353,'danielp',1111485673,187,1,'',1271521943,'Daniel Pasaila',6,0,'','da35f7052906a790a80177483e34a86f358fa609','danielp@example.com','',0,'0001-01-01','','','','','','danielpasaila','',1,1,'','I can\'t get a life if my heart\'s not in it',0,'',0,4,32,'',1,1,'','','',1,1,'',40469,'','',17,91109,'ad40','','',0,2,''),(370,'wefgef',1113062923,2013,1,'',1272207594,'Andrei Grigorean',181,0,'','0245bd4df4bca0ce6bf2ef6ee7c594a9ab415182','wefgef@example.com','razboinicu&#039; luminii',1,'1988-03-15','','','','','','grigo014','',1,1,'','omului i-au fost date instinctele pentru a supravietui, nu pentru a fi sclavul lor.',0,'41646657943ec708c18ff3.jpg',1,540,1066,'',1,1,'','','',1,1,'',40584,'','',18,2613605,'c85b','','',0,2,''),(394,'pauldb',1114676651,1296,1,'',1272147619,'Paul-Dan Baltescu',69,0,'','41dc2ea737a312def66bc07c8f75a2448c1d288f','pauldb@example.com','',1,'0001-01-01','','','','','','paudlb89','',0,1,'','Am zis :mrgreen:',0,'',1,419,931,'',1,1,'','','',1,1,'',40542,'','',18,3245504,'c7b2','','',0,3,''),(412,'cos_min',1115493373,493,0,'',1272051184,'Bondane Cosmin',42,0,'','315b43c450406cd055cb98a12a355433648c804c','cos_min@example.com','live',1,'0001-01-01','','','','','','cosminexe','',1,1,'','vid...',0,'',1,101,146,'',1,1,'','','',1,1,'',40536,'','',18,1858671,'3a5c','','',0,2,''),(416,'Dark_Raxvan',1115815885,13,0,'',1116826191,'raxvan oprea',0,0,'','2ca59770edc525bfda7c72c016667a0b174ce25e','Dark_Raxvan@example.com','',0,'0001-01-01','','','','','','','',1,1,'','',0,'',1,14,0,'',1,1,'','','',1,1,'',0,'','',9,0,'','','',0,2,''),(441,'tudalex',1120679321,41,0,'',1269771866,'Tudorica Constantin Alexandru',0,0,'','f68d244814d2f5cbf1db4cf55a6b142d097d40c8','tudalex@example.com','',1,'0001-01-01','','','','','','yudalex','',1,1,'','&quot;Doua lucruri sunt infinite: universul si prostia omeneasca, dar de prima inca nu sunt sigur&quot; Albert Einstein',0,'',1,34,26,'',1,1,'','','',1,1,'',38858,'','',10,78681,'7267','Gigi','',0,2,''),(454,'devilkind',1126265740,951,1,'',1272015815,'Savin Tiberiu',24,0,'','50a65e44c032a717ae567563130a47342095c611','devilkind@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,449,608,'',1,1,'','','',1,1,'',40545,'','',18,2893280,'8e12','','',0,2,''),(461,'CezarMocan',1127146102,356,20,'',1272109420,'Cezar Mocan',87,0,'','f6e653a8929eb4c24eb8d6a47326ff4e3f9fc61a','CezarMocan@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,292,370,'',1,1,'','','',1,1,'',40545,'','',18,1134229,'','','',0,2,''),(465,'cezar305',1128760617,10,20,'',1269969924,'.com 2009',3,0,'','3cbf27c81af14c79fb60124bdc3528566e3ab21b','cezar305@example.com','',1,'0001-01-01','','','','','','mocancezar@yahoo.com','',0,1,'','Limpede nu vezi decat cu inima. Ochii nu pot patrunde in adancul lucrurilor',0,'',1,3,9,'',1,1,'','','',1,1,'',39381,'','',9,113257,'295e','','',0,2,''),(467,'mugurelionut',1128975344,79,0,'',1269165696,'Mugurel Ionut Andreica',19,2,'','e2c649f0bdfacfb8ff945c4a78f70ee61687e31e','mugurelionut@example.com','',0,'0001-01-01','','','','','????','mugurel_ionut','????',1,1,'','',0,'',1,12,123,'',1,1,'','','',1,1,'',37717,'','',11,60711,'a6ef','','',0,2,''),(497,'blasterz',1132074221,154,2,'',1272136754,'Mircea Dima',21,0,'','99c18f05be18480f7763c373d2bf1618a03c6882','blasterz@example.com','',0,'0001-01-01','','','','','','mirceapcman','',0,1,'','',0,'',1,69,109,'',1,1,'','','',1,1,'',40503,'','',17,739381,'','','',0,2,''),(505,'Marius',1132411816,514,1,'',1272094703,'Marius Stroe',73,0,'','5568ecf604d7f90895ed6e8affb4f7adfe64ca97','Marius@example.com','',1,'0001-01-01','','','','','','stroe_marius_laurentiu','',1,1,'','Faceti lucrurile simplu: pe cat de simplu posibil, dar nu mai simplu.',0,'',1,115,252,'',1,1,'','','',1,1,'',40558,'','',18,1062769,'1c01','','',0,2,''),(506,'Prostu',1132416551,277,1,'',1271841250,'Filip Stefan A.',26,0,'','0a140d6d788cb7a2b30e6d7bd9dad0eadff03d6f','Prostu@example.com','',1,'0001-01-01','','','','','','','',1,1,'','',0,'',1,32,147,'',1,1,'','','',1,1,'',40533,'','',18,843285,'2410','','',0,2,''),(558,'marcelcodrea',1140362976,191,0,'',1271886610,'Codrea Marcel',50,0,'','3d1021b12ac29a3659f065711feb2c0505fed023','marcelcodrea@example.com','',0,'0001-01-01','','','','','','','',1,1,'','Imperiile coloniale au murit...<br />Germania Nazistä a murit...<br />Uniunea Sovieticä a murit...<br />Si nici Uniunea Europeanä nu se simte prea bine',0,'',1,75,182,'',1,1,'','','',1,1,'',40543,'','',17,764120,'e0ec','','',0,2,''),(611,'crawler',1145199974,115,0,'',1271578765,'Puni Andrei Paul',21,0,'','97f43e6f2819685e6e98aa38f29f7aced84f5cfb','crawler@example.com','',1,'0001-01-01','','','','','','','',0,1,'','',0,'',1,65,122,'',1,1,'','','',1,1,'',35807,'','',13,424313,'73f9','','',0,2,''),(671,'mariusdrg',1154690120,56,0,'',1269172611,'dragus marius',3,1,'','d427d5a94f0100d55972f908565782fe91edfcb5','mariusdrg@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,12,76,'',1,1,'','','',1,1,'',39656,'','',11,147286,'fff4','','',0,2,''),(775,'rus',1162801444,0,0,'',1173348870,'Rus Sergiu',0,0,'','94086a103570c65d9b2b158aa92e711df1f58dfa','rus@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',13450,'','',0,9335,'beeb','','',0,2,''),(814,'koosy',1164253107,0,0,'',0,'Koosy',0,0,'','7c031f9e05db9e7fdc85707b3a09c559745cb1ee','koosy@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(903,'oanam',1164253107,0,0,'',0,'Mihai Oana',0,0,'','d9d932e1a8a63fdf873a129e58c7aace82c49072','oanam@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(924,'florinr1',1164253107,0,0,'',0,'florin racila',0,0,'','229f7c1cfe7fe285a41aab496a862d54164e2997','florinr1@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(984,'mars',1164253108,1,0,'',1243319703,'Marius Andrei',0,0,'','0bbd71555a7e3e5c2d777281ac999ecc759d1eeb','mars@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,1,'',1,1,'','','',1,1,'',33460,'','',9,1942,'','','',0,2,''),(1183,'miZ',1164253108,0,0,'',0,'Micu Florin',0,0,'','535b5c08cf6e5aa9db329233a5193d787ea98e84','miZ@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(1196,'vasile_gales',1164253108,0,0,'',0,'Gales Vasile',0,0,'','daf16591af759f9ef96bc4b677bbfe3a7ee875ca','vasile_gales@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(1360,'sssilviu',1164253108,0,0,'',0,'straliciuc silviu',0,0,'','f1b3662b501e6c32b471365037388a45ce32cc7d','sssilviu@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(1482,'MASTER',1164253109,0,0,'',0,'lUCA CRISTIAN',0,0,'','fc51178eb39740810f9642b24fb541ab10bf36a9','MASTER@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(1567,'DITzoneC',1164253109,957,1,'',1272135558,'Adrian Diaconu',3,0,'','bd0c869fdf51f004a547ad0a1a002be83c677b52','DITzoneC@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,68,349,'',1,1,'','','',1,1,'',40543,'','',18,1175522,'','','',0,2,''),(1570,'filosofie12',1164253109,0,0,'',0,'Dorneanu',0,0,'','f2f905c448c706acc1e0c580629cc3e365e1afd9','filosofie12@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(1598,'chiru_ramona',1164253109,0,0,'',0,'Chiru Ramona',0,0,'','24c664f061b3f51b961094450aa00902ec9fe709','chiru_ramona@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(1619,'Tabara',1164253109,215,0,'',1272139732,'Tabara Mihai',45,0,'','9639c299c429eaeb1c3df24e38690246aec5ca04','Tabara@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,88,107,'',1,1,'','','',1,1,'',40538,'','',18,822105,'','','',0,2,''),(1838,'fucker',1164253109,0,0,'',0,'euu',0,0,'','6c7b36cd576ec9b8bdd3085dba175ea9c02cb4a6','fucker@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(1877,'Deni',1164253109,0,0,'',0,'Bica Denisa',0,0,'','12a0e3d3f30254e0e68dcb359fa597c60215de12','Deni@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(2156,'bianca_ig',1164253110,0,0,'',0,'bianca ignat',0,0,'','ca982f853d8c4f43892743903daf82f0907f9a0d','bianca_ig@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(2366,'BlitzKrieg',1164253110,0,0,'',0,'Victor Popescu',0,0,'','f17b8587bbe4da49042348db1c95edc2ca541eb4','BlitzKrieg@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(2527,'astronomy',1164253111,468,1,'',1272145838,'Airinei Adrian',21,0,'','b796ebf62bc3cfea237ef0eb21e77051f436f3bb','astronomy@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,49,231,'',1,1,'','','',1,1,'',40584,'','',18,1948362,'','','',0,2,''),(2556,'martinica1',1164253111,0,0,'',0,'ionblagu',0,0,'','b75566b0aed418c90a2ffaeac531708d242137cf','martinica1@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(2709,'uniquee',1164253111,0,0,'',0,'Pacurar Alexandru',0,0,'','3c29eb2296eaa71ab155e1db7e9c302e379cb453','uniquee@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(2740,'stancosti',1164253111,0,0,'',0,'costi stan',0,0,'','66e8ca8a628afa6998552b1e7e8fef9d3d232f4b','stancosti@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(2744,'elutza',1164253111,0,0,'',0,'tetcu liana mihaela',0,0,'','5234d966a6f635370244e21f87801913c7f396cb','elutza@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(2836,'C1506',1164253111,0,0,'',0,'Blidisel Alin',0,0,'','a2627f822db462cb71f2df0f388fe5d8272cca18','C1506@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3081,'paula',1164253112,0,0,'',0,'muresan gabriela',0,0,'','093fea29edb166fc685e6e072d295d15b429c20e','paula@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3170,'con_lena',1164253112,0,0,'',0,'constantin elena',0,0,'','df3500baea05ebcbe0f9aeab40ca9d64a17675fa','con_lena@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3174,'abcd',1164253112,0,0,'',0,'Giurgea Anca',0,0,'','e0378e12d7ac5f9af37052d8763be4f3e8d13041','abcd@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3241,'colt2005',1164253112,0,0,'',0,'chitic stefan',0,0,'','d07667a4169dc7e34e744959012567b89266e742','colt2005@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3448,'judy_k',1164253112,4,1,'',1271968554,'Cristina Petrovici',5,0,'','5db219b80356b3ca6359f92bd3e33e85d9229182','judy_k@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,9,'',1,1,'','','',1,1,'',40546,'','',9,40936,'','','',0,2,''),(3449,'Diana_C',1164253112,0,0,'',1169366140,'Ciocea Diana Cristina',0,0,'','14a03f48222a2173dba8cca3e1cdd7f649d0e4a8','Diana_C@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',11573,'','',0,1112,'','','',0,2,''),(3464,'zait',1164253112,0,0,'',0,'paul filimon',0,0,'','1b0c6fdf525f50904551852a2858cefe04a2cca1','zait@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3511,'marius_Dumitran',1164253112,0,0,'',0,'Marius Dumitran',0,0,'','5d731b387fb78b7859af5f27f98b513bcf6e463e','marius_Dumitran@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3539,'exist3nz',1164253112,0,0,'',0,'Ionescu Cristina',0,0,'','4c4d0c3824b7a58458cf1397b05327e5aaa88820','exist3nz@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3547,'claustan',1164253112,0,0,'',0,'Stan Claudiu',0,0,'','0b8d1588b480e874a2214e0eb85dcd86eba331d4','claustan@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3636,'sima_cotizo',1164253113,539,2,'',1272147035,'Sima Cotizo',85,0,'','234d80ce23b6abecf9d0c20e8eebe7da6356d63d','sima_cotizo@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,105,301,'',1,1,'','','',1,1,'',40558,'','',18,1744288,'','','',0,2,''),(3784,'inkriptor_scn',1164253113,0,0,'',0,'maran tiberiu',0,0,'','8ad8a27931c9f44275f5f95b8f00ee7210544bf4','inkriptor_scn@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3948,'Chici',1164253113,0,0,'',0,'Han Bogos Adamita',0,0,'','3d32226afbef251504acc8c8fb42d3bb4a3fe600','Chici@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4061,'lilix0202',1164253113,0,0,'',0,'nesu liliana',0,0,'','7ee8a275b96b49b554a89577a88133d9c4754261','lilix0202@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4074,'laiurita88',1164253113,0,0,'',0,'laura',0,0,'','03616513e0a3574b164c8a13e00673f82484045d','laiurita88@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4075,'lupu',1164253113,0,0,'',0,'lupulescu',0,0,'','b9a1c42de0d4b32e352660b9ee55117d1943e4b5','lupu@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4179,'mfuqm31',1164253114,0,0,'',0,'Mitarca Mihai',0,0,'','7da5d690d4df7d931a14e2d960da3d780bd300cc','mfuqm31@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4320,'raduzer',1164253114,71,20,'',1271175241,'Radu Zernoveanu',18,0,'','775fe49c1e6a614be5597dcfe0e8f5cbea239978','raduzer@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,88,150,'',1,1,'','','',1,1,'',40365,'','',11,176123,'','','',0,2,''),(4354,'danutzul_05',1164253114,0,0,'',0,'vicol daniel-ionut',0,0,'','80efe069545b56e83a633f1fb3215c5f56c4b6e9','danutzul_05@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4376,'tmir',1164253114,0,0,'',0,'nam',0,0,'','3853df7a2732206a606ff50400a3f3bfca168c7d','tmir@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4432,'Ioana_bomboana',1164253114,0,0,'',0,'Popescu Ioana',0,0,'','65f64a63156100f3d6a4fe8e655e5d429d946bca','Ioana_bomboana@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4492,'bianca_bya',1164253115,0,0,'',0,'boeriu bianca',0,0,'','c2543b05b39660ea5e0d8942604dfd8a43b4e397','bianca_bya@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4603,'andras',1164253115,0,0,'',0,'Halalai Tudor Andrei',0,0,'','68f52bf8ce39bbcca1b4cc75fec66bced04b0aca','andras@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4626,'IcemaN_ro',1164253115,0,0,'',0,'Alex Moldovan',0,0,'','a86f4a79e36d5da244ac0f4da2ed31cb274a3103','IcemaN_ro@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4707,'bc_costy',1164253115,0,0,'',0,'Blindu Constantin',0,0,'','834a817e64d8d9674c76f4c25bca162214fc77f3','bc_costy@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4767,'vic_and',1164253115,0,0,'',0,'Victor Andrei',2,2,'','45bccb08e9c96f1f1a8b24075a82091f5b000c95','vic_and@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4798,'Alexus',1164253115,0,0,'',0,'Stoica Alexandru',0,0,'','b184946119b11a9af04fb50b7a08ce96d66a4dbb','Alexus@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4830,'claudia',1164253115,0,0,'',0,'Simon Claudia Mihaela',0,0,'','c37f4d9d68d19869f97921ed28bb83c2bb873183','claudia@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4882,'Dastas',1164253116,169,0,'',1271979061,'Ionescu Vlad',18,0,'','9a2d2412661e555626ae21142b17706acd3d85a6','Dastas@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,28,38,'',1,1,'','','',1,1,'',40546,'','',17,3196564,'','','',0,2,''),(4913,'nirvanablue25',1164253116,0,0,'',0,'rosoiu cristina mihaela',0,0,'','c939433eeb276fc38604e442b628dd1f6d7d8bab','nirvanablue25@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4932,'onu_flo',1164253116,0,0,'',0,'Pirvu Ionelia',0,0,'','568df585fe71aac584f29fc87eea1ff73a3fcc9c','onu_flo@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4975,'manu_deutza',1164253116,0,0,'',0,'cojocaru andreea',0,0,'','00236c908b681930e15067c0267c57f5f57ea77f','manu_deutza@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5084,'cocoru',1164253116,0,0,'',0,'agarici',0,0,'','983614aa65064093aab7a84c3b9d96b477851e9d','cocoru@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5087,'savim',1164253116,72,20,'',1272109768,'Serban Andrei Stan',18,0,'','da9e6f0eff30aaa361b619b870c0b9faa3d42edf','savim@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,93,140,'',1,1,'','','',1,1,'',40266,'','',11,404406,'','','',0,2,''),(5118,'lemne',1164253116,0,0,'',1201508577,'Lemne Lemne',0,0,'','999d42e0b834887e1d239e793c30538ef814c648','lemne@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',13947,'','',0,1005,'','','',0,2,''),(5154,'xanthe',1164253116,0,0,'',1165824143,'Teodora',0,0,'','f36a84999ece82cc1f76d44bc38a8acafc8a1f87','xanthe@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',11108,'','',0,0,'','','',0,2,''),(5169,'mlegs',1164253116,0,0,'',0,'nec',0,0,'','4090c05e00e6914c0e66f8cce9a5999891b3490e','mlegs@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5298,'root',1164253116,0,0,'',0,'/boot/vmlinuz',0,0,'','33a485cb146e1153c69b588c671ab474f2e5b800','root@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5486,'ankutsa',1164253117,0,0,'',0,'Lasc Anca',0,0,'','bcbacf1bb317e73f1f149e56061f783295664718','ankutsa@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5513,'AndreiDumi',1164253117,0,0,'',0,'Andrei',0,0,'','fe86a8eef0b11608cfbdf38ade3dc6f5cb9a2d9a','AndreiDumi@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5601,'Dany_perfect',1164253117,0,0,'',0,'Moldoveanu Daniel-Stefan',0,0,'','d51f6ee42a9f638a22e443dca72844d5b14e2815','Dany_perfect@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5616,'ge_ronimo17',1164253117,0,0,'',0,'george ionutz',0,0,'','2119b9f4d33de86012b9baeee17fa886f4b9ac7c','ge_ronimo17@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5628,'eval',1165175672,0,0,'',0,'Evaluatorul infoarena',0,0,'','99f84d9f2e99cba220e37d9e293f295da6e5c3f4','eval@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5656,'armasanea',1165908138,0,0,'',0,'Sanea Prodan',0,0,'','838c875337361dc5f9acc4d1630cbf59ebf49e92','armasanea@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5720,'kana',1166087956,0,0,'',1166089438,'Preda Mihai',0,0,'','3fd4b994292b78fc431bb0e216c2ec1706b19803','kana@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',11192,'','',0,0,'','','',0,2,''),(5772,'kezman',1166462141,0,0,'',0,'adrian',0,0,'','9d07edd26624176d3b8dea8354350c0ece476fb1','kezman@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5864,'fish',1168595905,0,0,'',0,'bogdan negrila',0,0,'','c0dd43cd1855a421dcfc03644ab1c50d6d0424db','fish@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5889,'floringh06',1168776794,5,0,'',1271085045,'Florin - Cristian Ghesu',11,0,'','cd71e4a11e8a3ea4472485c775e484a229d37c5e','floringh06@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,6,5,'',1,1,'','','',1,1,'',40320,'','',9,135717,'','','',0,2,''),(5895,'cavin',1168873674,0,0,'',0,'Gosman Catalin',0,0,'','0f4a9d7c5dd2e2b6420097dc3b2f1c207f016e75','cavin@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5959,'razvan_varnita',1169545158,0,0,'',0,'dragomir razvan',0,0,'','d6184148615b2a64ad228dd52a88c5343afbcc89','razvan_varnita@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5984,'Florian',1169645768,793,0,'',1272129520,'Marcu Florian',94,0,'','321cf8f0b3166041d167aa30bb112180fbc28b7a','Florian@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,244,336,'',1,1,'','','',1,1,'',40556,'','',18,2716485,'','','',0,2,''),(6298,'toni2007',1171741549,505,20,'',1272147610,'Pripoae Teodor Anton',113,0,'','621a55b6f1da52ee5809a53cce92ace3847632ec','toni2007@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,277,363,'',1,1,'','','',0,1,'',40545,'','',18,900431,'','','',0,2,''),(6349,'reSpawn',1172270177,0,0,'',1223556716,'Rosia Nicolae',0,0,'','e58eb6300925f62b67ad8fc27c02824d4269784a','reSpawn@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',12799,'','',0,17214,'','','',0,2,''),(6409,'gabitzish1',1172837361,709,2,'',1272142790,'Gabriel Bitis',90,0,'','a832fc848ecf51556b1d9fd31279c5f35341200b','gabitzish1@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,260,475,'',1,1,'','','',0,1,'',40558,'','',18,4731324,'','','',0,2,''),(6461,'ln_anila',1173247948,0,0,'',1173294576,'Alina Nitu',0,0,'','ef27061cef8a23e8ce81ac6c53fd0f79d4a073bd','ln_anila@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',13411,'','',0,0,'','','',0,2,''),(6432,'nistaman',1173021355,0,0,'',0,'Bogdan Komen',0,0,'','1e31816150493a262ace01243e854c5d55c1fbbf','nistaman@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(6454,'Nebhotep',1173182046,0,0,'',1175614648,'Metes Alexandru',0,0,'','06a1a04fcd17c0b07a1f39ff4eb28eb5a866d3aa','Nebhotep@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',13399,'','',0,1986,'','','',0,2,''),(6543,'lebappe',1174152232,0,0,'',0,'Bogdan Popa',0,0,'','e430f6209550892dbbc3aa0d441a394a68b06b96','lebappe@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(6570,'Mishu91',1174552826,640,0,'',1272145513,'Andrei Misarca',53,0,'','e5f53468610c31c7f4549b0f3a4e1e05a8dbfac6','Mishu91@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,69,161,'',1,1,'','','',0,1,'',40558,'','',18,3574693,'','','',0,2,''),(6658,'cristi_c',1176196073,1,0,'',1237192394,'Chirac Cristian',1,1,'','13ab03f0f890e7057ea125e07714b95d6ae40bc9','cristi_c@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',14921,'','',9,1939,'','','',0,2,''),(6680,'ada_s',1176830489,4,0,'',1271222025,'Ada-Mihaela Solcan',0,0,'','b550dafed22cb780059a3679bf31db5ad387d9b7','ada_s@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,6,11,'',1,1,'','','',0,1,'',40382,'','',9,296455,'','','',0,2,''),(6720,'danciac',1177595784,0,0,'',1207671067,'Cracan Dan',0,0,'','cc693af8be52ba184ae0652b87dea4b16a712693','danciac@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',15344,'','',0,594,'','','',0,2,''),(6806,'hardvirus',1180077671,0,0,'',1246388763,'Ardelean Horia',0,0,'','4bc045de6294ff37e35b2203076b01e6ed4b4d19','hardvirus@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',15900,'','',0,4922,'','','',0,2,''),(6931,'alexandru.mosoi',1186311176,12,0,'',1221296734,'Alexandru Mosoi',5,5,'','f4a5a1b6904da106c3166cdbd68cd3ad58a5ba32','alexandru.mosoi@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,9,9,'',1,1,'','','',0,1,'',20529,'','',9,10221,'','','',0,2,''),(6965,'marsamg',1187591575,0,0,'',1187594150,'Marius Andrei',0,0,'','fa58f34a947a006629cbbff3a97da9e967c22818','marsamg@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',17393,'','',0,73,'','','',0,2,''),(6997,'100puncte',1189085060,1,0,'',0,'Ionut Popa',0,0,'','c60ed642c05f833d7d6dedbfd2e305e119af01af','100puncte@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,2,1,'',1,1,'','','',0,1,'',0,'','',9,0,'','','',0,2,''),(7037,'GavrilaVlad',1190376463,22,0,'',1271878504,'Gavrila Vlad',1,0,'','c30cd987e7a86566146af8bf13ff0c79468ad6a6','GavrilaVlad@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,245,271,'',1,1,'','','',0,1,'',40488,'','',9,353487,'','','',0,2,''),(7104,'unubou',1191510929,0,0,'',0,'Isac Razvan Alexandru',0,0,'','d9de0cd9da371ee646517699c78f1d33b79f9ab8','unubou@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(7111,'kaya',1191511315,0,0,'',0,'Marina Mihailescu',0,0,'','2f91874fe8105df9519fac90ee525314efa6a519','kaya@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(7249,'gabi_bobocel',1194076286,0,0,'',0,'Boboc Costin Gabriel',0,0,'','92a168802fae6aade88c7c6585f0ac79e94c7922','gabi_bobocel@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(7260,'COstel',1194117725,0,0,'',1194254729,'Petrea Constantin',0,0,'','40be77057e797da09f2067c7ae7be368f69f9284','COstel@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',19175,'','',0,132,'','','',0,2,''),(7337,'corinabolfa',1195046308,0,0,'',0,'bolfa corina',0,0,'','15e9b87bef3a054dd82e533e0531436bd0b581cd','corinabolfa@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(7353,'paulrusu',1195160343,0,0,'',1197018777,'paul rusu',1,0,'','a32d9703ad2cfffe8be751d4e80eda2f03c2de97','paulrusu@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',19493,'','',0,1272,'','','',0,2,''),(7385,'GheorgheMihai',1195635207,5,20,'',1272098539,'Gheorghe Mihai',0,0,'','0ad371d724545ea4dc4e865f950846844e7c7c53','GheorgheMihai@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,4,'',1,1,'','','',0,1,'',40226,'','',9,172669,'','','',0,2,''),(7383,'roxyshor',1195588901,0,0,'',0,'Leonte Roxana',0,0,'','d2878f85428d7427406150f4b570b7541eb94bef','roxyshor@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(7508,'andrei-alpha',1196698412,80,0,'',1272128910,'Andrei-Bogdan Antonescu',38,0,'','fbb177aae061688fbcc8bfe0e4d6c7d739b25aee','andrei-alpha@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,32,123,'',1,1,'','','',0,1,'',40422,'','',11,1022990,'','','',0,2,''),(7517,'DanielG',1196860405,10,0,'',1271696237,'Glodeanu Ioan Daniel',3,0,'','d606ee4e75fceba83f8d6793c19f27a8ff7eeba4','DanielG@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,3,5,'',1,1,'','','',0,1,'',40498,'','',9,183508,'','','',0,2,''),(7527,'login',1196875999,0,0,'',1271835228,'Anca Login',8,0,'','a12c2ca48c890306edbe99637ad2c62195edabb1','login@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,2,'',1,1,'','','',0,1,'',40169,'','',0,4512,'','','',0,2,''),(7557,'123456789',1197210028,0,0,'',0,'ghita gheorghita',0,0,'','3175de158db24c987b7ced3bf65d46c1fcfb3c5f','123456789@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(7570,'cosser',1197306166,39,0,'',1251132387,'Bula Ionut',3,0,'','6a0ca20a9b887058821f2f57f1d4d378b0e15107','cosser@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,9,13,'',1,1,'','','',0,1,'',35085,'','',10,79703,'','','',0,2,''),(7632,'BigMazilu',1199339751,13,0,'',1250781635,'Mazilu Victor',6,0,'','33292d8b3415e02363e365267a3b865616bcd6d0','BigMazilu@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,42,10,'',1,1,'','','',0,1,'',35024,'','',9,33614,'','','',0,2,''),(7661,'ruxandra_enus',1200054038,0,0,'',0,'ruxandra enus',0,0,'','0e52889b5505e7fa7be545d01f821dd6d5dcb085','ruxandra_enus@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(7685,'radoo',1200316623,0,0,'',1200318048,'Miron Radu Emanuel',0,0,'','15362d1446de569734aaf038ba3367a22e74637f','radoo@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',21176,'','',0,0,'','','',0,2,''),(7905,'andrici_cezar',1203506110,98,0,'',1261039234,'Andrici Cezar',21,0,'','cf2d97908f0e321da3b95d650a98d150a9923b9b','andrici_cezar@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,78,24,'',1,1,'','','',0,1,'',36529,'','',11,120709,'','','',0,2,''),(7969,'petro',1204111269,3,0,'',1271093437,'Milut Petronela',8,0,'','0d33b789ef661e7bb834127c987fa3e5ab20f8d5','petro@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',35623,'','',9,11549,'','','',0,2,''),(8057,'shmecheru',1205149367,0,0,'',1205217368,'Shmecheru',0,0,'','52b97657e7d5e2f13341263caf0c5887947985f9','shmecheru@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',23036,'','',0,0,'','','',0,2,''),(8078,'darkdude',1205301906,0,0,'',1238429179,'Andrei Barsan',2,2,'','b24005dd227f3e9e0752522204855940b4399534','darkdude@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',24268,'','',0,602,'','','',0,2,''),(8142,'1gnition',1205592925,2,0,'',1228911521,'Strambu George',0,0,'','128c3fa831fd5d8cdd668819fb527a7ec50f809a','1gnition@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,4,2,'',1,1,'','','',0,1,'',25698,'','',9,2284,'','','',0,2,''),(8191,'chryss13',1206066751,0,0,'',1237369215,'cristina',0,0,'','7a5e23a60f47e906f300220ac91d69fe3a2ba32f','chryss13@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',31677,'','',0,434,'','','',0,2,''),(8264,'stocarul',1207131819,130,20,'',1272122433,'Cosmin Mihai Tutunaru',17,0,'','82e18cdc5a097c42077618756441f74a84923809','stocarul@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,38,53,'',1,1,'','','',0,1,'',40469,'','',13,372987,'','','',0,2,''),(8355,'andreiparau',1208274731,0,0,'',1229464441,'Andrei Parau',0,0,'','4e93e748d7c464196802ba7f926ad4d58dedcb49','andreiparau@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',28867,'','',0,70,'','','',0,2,''),(8368,'Leka',1208328397,0,0,'',0,'Pascu Alexandra',0,0,'','4a50c6898738ef0f180f41626db50bbc9d5ecf3b','Leka@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(8418,'stelistul',1209923031,0,0,'',0,'Bora Calin',1,1,'','8660b97240b081ee83613b1a0c12594f23314a3b','stelistul@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(8438,'Torque',1210156059,0,0,'',0,'Paducel Vladut Emil',0,0,'','552b96247f8493d1cb090a61c8886c60d1991de9','Torque@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(8497,'cata00',1211840138,5,0,'',1267428108,'Catalin Francu',3,1,'','ce60b3655f53a236ff1ea89aacd312fb4a17df1f','cata00@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,12,'',1,1,'','','',0,1,'',38638,'','',9,7685,'','','',0,2,''),(8536,'dexterelu',1212429647,0,0,'',1212432304,'Paul Raetchi',0,0,'','4504f99dfafd5a1f0646d04c592362fa3f121463','dexterelu@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',26199,'','',0,0,'','','',0,2,''),(8698,'upb_sdv',1221188984,0,0,'',0,'Gravity',0,0,'','25adbf3092e901992eeae04246fc249968b75c61','upb_sdv@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(8752,'cristi.oprea',1222099999,0,0,'',1222100555,'oprea cristi',0,0,'','fbdcfe6d36c4a5050924fcb312db126b03be8bd6','cristi.oprea@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',27339,'','',0,290,'','','',0,2,''),(8874,'lorincziisti',1224073260,0,0,'',0,'Lorinczi Istvan',0,0,'','b1e9445fb1222c08207ee991aa29cc2041f30ba9','lorincziisti@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(8927,'motty',1224839332,6,0,'',1272121866,'Matei-Dan Epure',6,0,'','58208a97c63a99a24cd7dde25e9582d776108dbf','motty@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,4,4,'',1,1,'','','',0,1,'',39838,'','',9,32617,'','','',0,2,''),(9021,'monocrom133',1226130296,0,0,'',0,'andreea raluca turcu',0,0,'','d1a5d6940189817f2a74cfdcb1c10e96f6a2cd1a','monocrom133@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(9045,'dragosldf',1226414757,0,0,'',0,'lazar dragos',0,0,'','e2e4a82e1fab10e648f0e38eb72128a4292cd309','dragosldf@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(9374,'mjoska',1229163501,0,0,'',1229163863,'Miklos Jozsef',0,0,'','8c09006a91113a9dd97183ee6c548105dd1ce522','mjoska@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',28874,'','',0,0,'','','',0,2,''),(9398,'FlorinOv',1229248530,0,0,'',0,'florin',0,0,'','f2b9a76834c716253c842439f0a1a504f59bb734','FlorinOv@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(9469,'mathboy',1230144217,79,0,'',1272132202,'Dragos-Alin Rotaru',23,0,'','beaa1c3d7b3705d3fda0f91df952d8582ec94b75','mathboy@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,13,34,'',1,1,'','','',0,1,'',40579,'','',11,1085257,'','','',0,2,''),(9593,'miculprogramator',1232132816,313,0,'',1272143282,'ALbulescu Cosmina',70,0,'','b3e87bcb19c906e85e934d7f77acc157b2916293','miculprogramator@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,180,220,'',1,1,'','','',0,1,'',40564,'','',18,1021358,'','important','',0,2,''),(9691,'oana_enusoiu',1233159134,0,0,'',0,'oana enusoiu',0,0,'','81c1689411c90ae9205dba7a35c61dbb6aec9d32','oana_enusoiu@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(9730,'AlexandruB',1233559263,0,0,'',1233560496,'Bordea Alexandru',0,0,'','c9d1722589c775c41e155532d5432795247a2b88','AlexandruB@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',30076,'','',0,799,'','','',0,2,''),(9740,'metalkitten',1233761175,0,0,'',1271603935,'Georgiana Arhip',6,0,'','3964e69d383e24b8549a3aca7424228b87c11a5c','metalkitten@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',40477,'','',0,5238,'','','',0,2,''),(9834,'SergiuC',1234956834,0,0,'',0,'Corneanu Sergiu',0,0,'','b5f1121fb6d026f8063ecd9a3bb51ef0b1541e7c','SergiuC@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(9976,'zerobarat',1235993464,0,0,'',0,'alexandra',0,0,'','cfcae2b48dcc797a9dbe58cbec465bb17ce22e3d','zerobarat@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(10067,'v_vero_93',1236761893,0,0,'',0,'Velciu Veronica Mihaela',0,0,'','a3af29b10f55b85246b4a8c41be35bec455e95c8','v_vero_93@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(10128,'GMF92',1237135352,0,0,'',1249343721,'numele meu',0,0,'','ed80bd077629ae0ef847c1e13b91c74a38a9ade1','GMF92@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',34742,'','',0,0,'','','',0,2,''),(10384,'pcinfo',1240328349,5,0,'',1269607752,'Carmen Popescu',0,0,'','0ddd510b2c62570a1fa0e2a4a32aeb6b3ebe3acc','pcinfo@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,1,4,'',1,1,'','','',0,1,'',34837,'','',9,9126,'','','',0,2,''),(10328,'pufuleti_sange',1239017967,0,0,'',1239018062,'pufuleica sange bors',0,0,'','987feb6b67df74fa21c5317f7913225e0968ae25','pufuleti_sange@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',32511,'','',0,230,'','','',0,2,''),(10537,'Sergiu_92',1243107732,0,0,'',1243185899,'Sergiu Savin',0,0,'','b1de5bb378237d37cec06a31ee6feb59c384cef9','Sergiu_92@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',33439,'','',0,0,'','','',0,2,''),(10784,'thesvcoolman',1247904857,0,0,'',1255542866,'Lucian Bicsi',0,0,'','620aa74ecf32743442e2ab93ded6fbee200b52e7','thesvcoolman@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',35646,'','',0,0,'','','',0,2,''),(10967,'andreii_93',1254114642,0,0,'',1255593868,'andrei ion',0,0,'','853cbb0bfb2ad7236dcd9dccff86dba4541363ea','andreii_93@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',35648,'','',0,88,'','','',0,2,''),(11020,'BringitON',1254572918,0,0,'',1254573331,'Breban Andrei',0,0,'','d47695c76fcf2ee4b2b9a9c5f374af5cda9368c7','BringitON@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',35538,'','',0,0,'','','',0,2,''),(11125,'Andrei29',1255675513,0,0,'',1255675721,'Andrei Paduraru',0,0,'','8fbd8a0c533044d1dc95be02839ecf69cfb1f876','Andrei29@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',35658,'','',0,0,'','','',0,2,''),(11261,'leva',1256812910,0,0,'',0,'Leva Ionut',0,0,'','e05d06dc7bb6d0f8c69c0f0c7520478f0686542d','leva@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(11283,'maoo',1257016932,0,0,'',0,'Bompa Mario',0,0,'','c9b9afb8b7cff6be3603edfdbef2afeb8e175458','maoo@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(11559,'ionut.pic',1258895892,0,0,'',1258896146,'popa ionut cristian',0,0,'','c3f7b847bada7b4675f7212fed19e120c6958ebb','ionut.pic@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',36353,'','',0,171,'','','',0,2,''),(11586,'petru000',1259311007,0,0,'',1259311052,'petru sorin',0,0,'','f43ab6cb7086dc9d1c9d7e02a44c48ac1b8f34e4','petru000@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',36414,'','',0,0,'','','',0,2,''),(11593,'AlecSs',1259403658,0,0,'',0,'Hulpe Alexandru',0,0,'','de3e0f7f79025a58e86666f8fda7ff0ea4a4bb72','AlecSs@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(11674,'VyperBoy',1260367227,0,0,'',1260376712,'Marin P',0,0,'','aad65a6286c65f89b9e1b311830aef6292dfcd31','VyperBoy@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',36638,'','',0,0,'','','',0,2,''),(11811,'cristialexandru',1262999238,0,0,'',0,'Cristi Alexandru',0,0,'','1763f7661feb6665cc1888e5c51839010f13d034','cristialexandru@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(11825,'u2tommyf',1263139127,0,0,'',1263139356,'Toma Florina',0,0,'','c01245a3db435642c2b633027eaf700f4a073f28','u2tommyf@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',37228,'','',0,164,'','','',0,2,''),(12036,'alexandrul',1265560536,0,0,'',0,'Alexandru Mihai',0,0,'','467f6e577fb3aaf448618aa5446815a63269888c','alexandrul@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(12056,'verdecrud',1265797182,0,0,'',0,'PensiuneaVerdeCrud',0,0,'','d3883703eafccac1260e40c7f9d16ef9d6362d60','verdecrud@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(12133,'hexor',1266395273,0,0,'',1266395599,'Serban Dragos',0,0,'','303dc13dfd3083a6df451fb884fce363d504b7ed','hexor@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',38159,'','',0,289,'','','',0,2,''),(12143,'bogdanelu006',1266430631,0,0,'',0,'bogdan',0,0,'','056cbfd58d9b31ab51f5ffff07a8f4748ae92186','bogdanelu006@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(12315,'Aleks10',1267604357,0,0,'',0,'Petrache Alex',0,0,'','207974a77e61353d2e5e3be9f0e799d723ce8271','Aleks10@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(12471,'Mihai-Daniel',1268814636,0,0,'',0,'Mihai-Daniel',0,0,'','7d75d164955f9c0428ce32c1c1f096d4057dfe91','Mihai-Daniel@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(12689,'SITZ',1270603556,0,0,'',0,'Sitesh Shrivastava',0,0,'','8ba3d09541382c1200f9b667ece67f6119fc43b1','SITZ@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(12738,'Bogdan.Cirstea',1270761650,0,0,'',1271148090,'Cirstea Bogdan-Ionut',0,0,'','70e3f4cf8afc1f6623d468dc2200b4d11e55067c','Bogdan.Cirstea@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',40350,'','',0,0,'','','',0,2,''),(12808,'jenniferlmartin',1271229666,0,0,'',0,'jennifer martin',0,0,'','494b1771479e4ce4f0cc6ec2a6910e1c30b62d15','jenniferlmartin@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(12813,'Andrei1998',1271263113,0,0,'',1271266835,'Constantinescu Andrei Costin',0,0,'','aab484e89badc20dcba053ded737bb155a94aa74','Andrei1998@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',40413,'','',0,0,'','','',0,2,''),(12839,'IonelaD',1271512613,0,0,'',1271718523,'Dinica Ionela',0,0,'','e02c5550e542734e5c324a76314c4f04e59e55d3','IonelaD@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',40469,'','',0,0,'','','',0,2,'');
+INSERT INTO `ia_smf_members` VALUES (2,'fluffy',1077052570,146,1,'',1263065043,'Dan-Leonard Crestez',23,2,'','7b1045aac728fec00a86a68aba993d6d85a74529','fluffy@example.com','',1,'0001-01-01','','','','','','crestez_leonard','',0,1,'','',0,'http://nobody.devnet.ro/pr0n.jpg',1,9,76,'',1,1,'','','',1,1,'',34704,'','',13,288783,'d98b','','',0,2,''),(3,'domino',1077054064,1321,1,'',1272143901,'Mircea Pasoi',154,0,'','6bd0a33ee98c8bf6aed56c6fe710002bde6048b3','domino@yahoo.com','',1,'0001-01-01','http://infoarena.devnet.ro','http://infoarena.devnet.ro','','324694544','','bogdanpasoi','mircea_pasoi',0,1,'','',0,'',1,185,430,'',1,1,'','','',1,1,'',40559,'','',18,2129658,'ba10','','',0,2,''),(10,'svalentin',1077384310,675,1,'',1272121256,'Valentin Stanciu - UPB',49,0,'','dfdfb51287c0b7472c0c501394f0440f9dcf14c9','svalentin@example.com','',1,'0001-01-01','','','','','','','',1,1,'%d-%m-%Y, %H:%M:%S','',0,'',1,134,212,'',1,1,'','','',1,1,'',40410,'','',18,456179,'c918','','',1,2,''),(27,'Cosmin',1077805323,1245,1,'',1272150352,'Cosmin Negruseri',80,0,'','95ddb1caf1d978e1cce9074bb1affbea2dcb7421','Cosmin@example.com','',0,'0001-01-01','','','','','','','',1,1,'','',0,'',1,198,355,'',1,1,'','','',1,1,'',40584,'','',18,1628032,'6561','','',0,2,''),(33,'ste_fanus',1078046877,5,0,'',1252654248,'Gheorghe Stefan',0,0,'','3622116a73d425b915f5922435acc25654c451be','ste_fanus@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,1,1,'',1,1,'','','',1,1,'',35239,'','',9,3839,'','','',0,2,''),(37,'amadaeus',1078087693,91,0,'',1242572550,'Lucian Boca',15,0,'','3586acf9cf25ded897d9aadf0855feab8592f462','amadaeus@example.com','',0,'0001-01-01','','','','','','','',1,1,'','&quot;one of these days I\'m going to cut you into little pieces...&quot;',0,'',1,23,50,'',1,1,'','','',1,1,'',32067,'','',11,180887,'10a4','','',0,2,''),(43,'greco',1078267126,434,1,'',1248428530,'Tiberiu-Lucian Florea',29,2,'','aaf53667e069463f8c21f09642e068e526cad665','greco@example.com','',0,'0001-01-01','','','','','','','',1,1,'','Jump in the cockpit and start up the engines\r<br />Remove all the wheelblocks there\'s no time to waste\r<br />Gathering speed as we head down the runway\r<br />Gotta get airborne before it\'s too late.',0,'',1,63,197,'',1,1,'','','',1,1,'',32918,'','',18,165933,'72fd','','',0,2,''),(47,'wickedman',1078654068,661,1,'',1272049192,'Cristian George Strat',86,0,'','63e05201f16771dd6d4694b502a4fb0dbdac0780','wickedman@example.com','',1,'0001-01-01','http://cristian.infoarena.ro/','http://cristian.infoarena.ro/','','','','','',1,1,'','Whatever happened to people I used to care about?',0,'',1,50,260,'',1,1,'','','',1,1,'',40556,'','',18,463833,'555a','','',0,2,''),(69,'silviug',1080394491,484,1,'',1269718857,'Silviu-Ionut Ganceanu',100,2,'','9678b7723d81d9a0eab85832847123c6cfc0dda4','silviug@example.com','',1,'0001-01-01','','','','','','private','private',1,1,'','&quot;Don&#039;t gain the world and lose your soul, wisdom is better than silver or gold.&quot; [Bob Marley - Jamaican reggae musician &amp; singer (1945 - 1981)]',0,'',1,35,219,'',1,1,'','','',1,1,'',35081,'','',18,376806,'22fd','','',0,2,''),(79,'filipb',1080409243,887,1,'',1272100145,'Filip Cristian Buruiana UPB',142,0,'','811bbf59e81ca6425274da0ef63e29dffd48d9a1','filipb@example.com','',1,'0001-01-01','','','','','','','',1,1,'','',0,'',1,89,295,'',1,1,'','','',1,1,'',40558,'','',18,1084916,'a792','','',0,2,''),(103,'fireatmyself',1083148315,500,0,'',1266852405,'Bogdan A. Stoica',25,1,'','cf86af8a0a30f5e088b37e4903f5b45f06d1c34f','fireatmyself@example.com','',1,'0001-01-01','','','','','','fireatmyself','',1,1,'','Viata e scurta. Daca nu o putem lungi, macar s-o facem lata.',0,'',1,326,358,'',1,1,'','','',1,1,'e0e6524541',38382,'','',18,359463,'4b60','','',0,2,''),(121,'azotlichid',1094553845,232,1,'',1272154682,'Adrian Vladu',30,0,'','c2e30bcb9a5615e5934d178c6fd7ebc15ac54006','azotlichid@example.com','',0,'0001-01-01','','','','','','','',1,1,'','',0,'',1,42,80,'',1,1,'','','',1,1,'',40582,'','',18,650596,'224d','','',0,2,''),(150,'rake',1105796010,2,0,'',1113593462,'Popa Tudor Iulian',0,0,'','fcd0eb35de617a413cdf2902cbdd8195bd875ff3','rake@example.com','',0,'0001-01-01','','','','','','','',1,1,'','&quot;Most people don\'t dance if they don\'t know who\'s singing,/Why ask your head? It\'s your hips that are swinging!&quot; (Propellerheads)',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',9,0,'','','',0,2,''),(154,'bogdan2412',1106323789,842,1,'',1272146727,'Bogdan-Cristian Tataroiu',103,0,'','502a034d392375d878a486dd851084462a9e6273','bogdan2412@example.com','',1,'0001-01-01','','','','','','','',0,1,'','',0,'',1,117,399,'',1,1,'','','',1,1,'',40567,'','',18,3854333,'64f2','','',1,1,''),(221,'victorsb',1109101822,1,1,'',1270170896,'Victor Rusu',4,1,'','4f6c786b29acccb5052902481fa24cccd4c9635c','victorsb@example.com','',0,'0001-01-01','','','','','','','',1,1,'','',0,'',1,1,6,'',1,1,'','','',1,1,'',40178,'','',9,125591,'','','',0,2,''),(250,'gogu',1109170639,85,0,'',1262873773,'Gogu Marian',1,0,'*','4a87b47b961aeea7a19349350cb40c13b688d95d','gogu@example.com','',0,'0001-01-01','','','','','','','',0,0,'','',0,'',1,37,67,'',0,0,'','','',1,1,'',35970,'','',11,123314,'cf25','','',0,2,''),(257,'tm_radu',1109177334,140,0,'',1236166427,'Toma Radu',16,2,'','a44856f0bd0907c5425d9f120b5d3e25c2ac6e21','tm_radu@example.com','',1,'0001-01-01','','','','','','radu_thekid','',1,1,'','Daca nu merge o preblema, depaneaz-o, si abia apoi arunci calculatoru pe geam',0,'',1,30,43,'',1,1,'','','',1,1,'',29764,'','',13,310709,'57f1','','',0,2,''),(303,'geo88',1109694397,0,0,'',1139571424,'george arion',0,0,'','f55140815c163b9241f99e2d408125617f87cc43','geo88@example.com','',0,'0001-01-01','','','','','','','',1,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(308,'alexthero',1109936951,125,1,'',1271150473,'Tandrau Alexandru',13,0,'','8bf4a0ca7f0b84427894f3b90e6786b6fef376c7','alexthero@example.com','',1,'0001-01-01','','','','','','alexthero','',0,1,'','Tine minte ca mintea conduce pumnu, nu invers',0,'',1,29,145,'',1,1,'','','',1,1,'',39471,'','',13,584310,'dc54','','',0,2,''),(312,'efer',1110024516,19,0,'',1233776447,'Liviu Ciortea',3,1,'','f831d7a53887b6b1df443a8394298512b5473e90','efer@example.com','',0,'0001-01-01','','','','','liviuefer','liviuefer','',1,1,'','',0,'',1,2,10,'',1,1,'','','',1,1,'',28805,'','',9,23057,'3c40','','',0,2,''),(335,'gcosmin',1111250221,231,1,'',1272101521,'Gheorghe Cosmin',20,0,'','bb4b40f220ae2f69cb0db74a0622c94039448c60','gcosmin@example.com','',0,'0001-01-01','','','','','','','',1,1,'','',0,'',1,41,205,'',1,1,'','','',1,1,'',40558,'','',18,702962,'c4d6','','',0,2,''),(343,'stef2n',1111314179,613,1,'',1272154541,'Stefan Istrate',16,0,'','6750b2965c97de05c5dac1328ac45045d425361f','stef2n@example.com','',1,'0001-01-01','','','','','','stef2n','',0,1,'','Exista 10 categorii de oameni: cei care inteleg sistemul binar si cei care nu il inteleg.',0,'',1,123,329,'',1,0,'','','',1,1,'',40514,'','',18,2729764,'6fbc','','',0,2,''),(353,'danielp',1111485673,187,1,'',1271521943,'Daniel Pasaila',6,0,'','da35f7052906a790a80177483e34a86f358fa609','danielp@example.com','',0,'0001-01-01','','','','','','danielpasaila','',1,1,'','I can\'t get a life if my heart\'s not in it',0,'',0,4,32,'',1,1,'','','',1,1,'',40469,'','',17,91109,'ad40','','',0,2,''),(370,'wefgef',1113062923,2013,1,'',1272207594,'Andrei Grigorean',181,0,'','0245bd4df4bca0ce6bf2ef6ee7c594a9ab415182','wefgef@example.com','razboinicu&#039; luminii',1,'1988-03-15','','','','','','grigo014','',1,1,'','omului i-au fost date instinctele pentru a supravietui, nu pentru a fi sclavul lor.',0,'41646657943ec708c18ff3.jpg',1,540,1066,'',1,1,'','','',1,1,'',40584,'','',18,2613605,'c85b','','',0,2,''),(394,'pauldb',1114676651,1296,1,'',1272147619,'Paul-Dan Baltescu',69,0,'','41dc2ea737a312def66bc07c8f75a2448c1d288f','pauldb@example.com','',1,'0001-01-01','','','','','','paudlb89','',0,1,'','Am zis :mrgreen:',0,'',1,419,931,'',1,1,'','','',1,1,'',40542,'','',18,3245504,'c7b2','','',0,3,''),(412,'cos_min',1115493373,493,0,'',1272051184,'Bondane Cosmin',42,0,'','315b43c450406cd055cb98a12a355433648c804c','cos_min@example.com','live',1,'0001-01-01','','','','','','cosminexe','',1,1,'','vid...',0,'',1,101,146,'',1,1,'','','',1,1,'',40536,'','',18,1858671,'3a5c','','',0,2,''),(416,'Dark_Raxvan',1115815885,13,0,'',1116826191,'raxvan oprea',0,0,'','2ca59770edc525bfda7c72c016667a0b174ce25e','Dark_Raxvan@example.com','',0,'0001-01-01','','','','','','','',1,1,'','',0,'',1,14,0,'',1,1,'','','',1,1,'',0,'','',9,0,'','','',0,2,''),(441,'tudalex',1120679321,41,0,'',1269771866,'Tudorica Constantin Alexandru',0,0,'','f68d244814d2f5cbf1db4cf55a6b142d097d40c8','tudalex@example.com','',1,'0001-01-01','','','','','','yudalex','',1,1,'','&quot;Doua lucruri sunt infinite: universul si prostia omeneasca, dar de prima inca nu sunt sigur&quot; Albert Einstein',0,'',1,34,26,'',1,1,'','','',1,1,'',38858,'','',10,78681,'7267','Gigi','',0,2,''),(454,'devilkind',1126265740,951,1,'',1272015815,'Savin Tiberiu',24,0,'','50a65e44c032a717ae567563130a47342095c611','devilkind@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,449,608,'',1,1,'','','',1,1,'',40545,'','',18,2893280,'8e12','','',0,2,''),(461,'CezarMocan',1127146102,356,20,'',1272109420,'Cezar Mocan',87,0,'','f6e653a8929eb4c24eb8d6a47326ff4e3f9fc61a','CezarMocan@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,292,370,'',1,1,'','','',1,1,'',40545,'','',18,1134229,'','','',0,2,''),(465,'cezar305',1128760617,10,20,'',1269969924,'.com 2009',3,0,'','3cbf27c81af14c79fb60124bdc3528566e3ab21b','cezar305@example.com','',1,'0001-01-01','','','','','','mocancezar@yahoo.com','',0,1,'','Limpede nu vezi decat cu inima. Ochii nu pot patrunde in adancul lucrurilor',0,'',1,3,9,'',1,1,'','','',1,1,'',39381,'','',9,113257,'295e','','',0,2,''),(467,'mugurelionut',1128975344,79,0,'',1269165696,'Mugurel Ionut Andreica',19,2,'','e2c649f0bdfacfb8ff945c4a78f70ee61687e31e','mugurelionut@example.com','',0,'0001-01-01','','','','','????','mugurel_ionut','????',1,1,'','',0,'',1,12,123,'',1,1,'','','',1,1,'',37717,'','',11,60711,'a6ef','','',0,2,''),(497,'blasterz',1132074221,154,2,'',1272136754,'Mircea Dima',21,0,'','99c18f05be18480f7763c373d2bf1618a03c6882','blasterz@example.com','',0,'0001-01-01','','','','','','mirceapcman','',0,1,'','',0,'',1,69,109,'',1,1,'','','',1,1,'',40503,'','',17,739381,'','','',0,2,''),(505,'Marius',1132411816,514,1,'',1272094703,'Marius Stroe',73,0,'','5568ecf604d7f90895ed6e8affb4f7adfe64ca97','Marius@example.com','',1,'0001-01-01','','','','','','stroe_marius_laurentiu','',1,1,'','Faceti lucrurile simplu: pe cat de simplu posibil, dar nu mai simplu.',0,'',1,115,252,'',1,1,'','','',1,1,'',40558,'','',18,1062769,'1c01','','',0,2,''),(506,'Prostu',1132416551,277,1,'',1271841250,'Filip Stefan A.',26,0,'','0a140d6d788cb7a2b30e6d7bd9dad0eadff03d6f','Prostu@example.com','',1,'0001-01-01','','','','','','','',1,1,'','',0,'',1,32,147,'',1,1,'','','',1,1,'',40533,'','',18,843285,'2410','','',0,2,''),(558,'marcelcodrea',1140362976,191,0,'',1271886610,'Codrea Marcel',50,0,'','3d1021b12ac29a3659f065711feb2c0505fed023','marcelcodrea@example.com','',0,'0001-01-01','','','','','','','',1,1,'','Imperiile coloniale au murit...<br />Germania Nazistä a murit...<br />Uniunea Sovieticä a murit...<br />Si nici Uniunea Europeanä nu se simte prea bine',0,'',1,75,182,'',1,1,'','','',1,1,'',40543,'','',17,764120,'e0ec','','',0,2,''),(611,'crawler',1145199974,115,0,'',1271578765,'Puni Andrei Paul',21,0,'','97f43e6f2819685e6e98aa38f29f7aced84f5cfb','crawler@example.com','',1,'0001-01-01','','','','','','','',0,1,'','',0,'',1,65,122,'',1,1,'','','',1,1,'',35807,'','',13,424313,'73f9','','',0,2,''),(671,'mariusdrg',1154690120,56,0,'',1269172611,'dragus marius',3,1,'','d427d5a94f0100d55972f908565782fe91edfcb5','mariusdrg@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,12,76,'',1,1,'','','',1,1,'',39656,'','',11,147286,'fff4','','',0,2,''),(775,'rus',1162801444,0,0,'',1173348870,'Rus Sergiu',0,0,'','94086a103570c65d9b2b158aa92e711df1f58dfa','rus@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',13450,'','',0,9335,'beeb','','',0,2,''),(814,'koosy',1164253107,0,0,'',0,'Koosy',0,0,'','7c031f9e05db9e7fdc85707b3a09c559745cb1ee','koosy@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(903,'oanam',1164253107,0,0,'',0,'Mihai Oana',0,0,'','d9d932e1a8a63fdf873a129e58c7aace82c49072','oanam@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(924,'florinr1',1164253107,0,0,'',0,'florin racila',0,0,'','229f7c1cfe7fe285a41aab496a862d54164e2997','florinr1@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(984,'mars',1164253108,1,0,'',1243319703,'Marius Andrei',0,0,'','0bbd71555a7e3e5c2d777281ac999ecc759d1eeb','mars@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,1,'',1,1,'','','',1,1,'',33460,'','',9,1942,'','','',0,2,''),(1183,'miZ',1164253108,0,0,'',0,'Micu Florin',0,0,'','535b5c08cf6e5aa9db329233a5193d787ea98e84','miZ@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(1196,'vasile_gales',1164253108,0,0,'',0,'Gales Vasile',0,0,'','daf16591af759f9ef96bc4b677bbfe3a7ee875ca','vasile_gales@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(1360,'sssilviu',1164253108,0,0,'',0,'straliciuc silviu',0,0,'','f1b3662b501e6c32b471365037388a45ce32cc7d','sssilviu@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(1482,'MASTER',1164253109,0,0,'',0,'lUCA CRISTIAN',0,0,'','fc51178eb39740810f9642b24fb541ab10bf36a9','MASTER@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(1567,'DITzoneC',1164253109,957,1,'',1272135558,'Adrian Diaconu',3,0,'','bd0c869fdf51f004a547ad0a1a002be83c677b52','DITzoneC@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,68,349,'',1,1,'','','',1,1,'',40543,'','',18,1175522,'','','',0,2,''),(1570,'filosofie12',1164253109,0,0,'',0,'Dorneanu',0,0,'','f2f905c448c706acc1e0c580629cc3e365e1afd9','filosofie12@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(1598,'chiru_ramona',1164253109,0,0,'',0,'Chiru Ramona',0,0,'','24c664f061b3f51b961094450aa00902ec9fe709','chiru_ramona@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(1619,'Tabara',1164253109,215,0,'',1272139732,'Tabara Mihai',45,0,'','9639c299c429eaeb1c3df24e38690246aec5ca04','Tabara@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,88,107,'',1,1,'','','',1,1,'',40538,'','',18,822105,'','','',0,2,''),(1838,'fucker',1164253109,0,0,'',0,'euu',0,0,'','6c7b36cd576ec9b8bdd3085dba175ea9c02cb4a6','fucker@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(1877,'Deni',1164253109,0,0,'',0,'Bica Denisa',0,0,'','12a0e3d3f30254e0e68dcb359fa597c60215de12','Deni@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(2156,'bianca_ig',1164253110,0,0,'',0,'bianca ignat',0,0,'','ca982f853d8c4f43892743903daf82f0907f9a0d','bianca_ig@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(2366,'BlitzKrieg',1164253110,0,0,'',0,'Victor Popescu',0,0,'','f17b8587bbe4da49042348db1c95edc2ca541eb4','BlitzKrieg@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(2527,'astronomy',1164253111,468,1,'',1272145838,'Airinei Adrian',21,0,'','b796ebf62bc3cfea237ef0eb21e77051f436f3bb','astronomy@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,49,231,'',1,1,'','','',1,1,'',40584,'','',18,1948362,'','','',0,2,''),(2556,'martinica1',1164253111,0,0,'',0,'ionblagu',0,0,'','b75566b0aed418c90a2ffaeac531708d242137cf','martinica1@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(2709,'uniquee',1164253111,0,0,'',0,'Pacurar Alexandru',0,0,'','3c29eb2296eaa71ab155e1db7e9c302e379cb453','uniquee@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(2740,'stancosti',1164253111,0,0,'',0,'costi stan',0,0,'','66e8ca8a628afa6998552b1e7e8fef9d3d232f4b','stancosti@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(2744,'elutza',1164253111,0,0,'',0,'tetcu liana mihaela',0,0,'','5234d966a6f635370244e21f87801913c7f396cb','elutza@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(2836,'C1506',1164253111,0,0,'',0,'Blidisel Alin',0,0,'','a2627f822db462cb71f2df0f388fe5d8272cca18','C1506@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3081,'paula',1164253112,0,0,'',0,'muresan gabriela',0,0,'','093fea29edb166fc685e6e072d295d15b429c20e','paula@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3170,'con_lena',1164253112,0,0,'',0,'constantin elena',0,0,'','df3500baea05ebcbe0f9aeab40ca9d64a17675fa','con_lena@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3174,'abcd',1164253112,0,0,'',0,'Giurgea Anca',0,0,'','e0378e12d7ac5f9af37052d8763be4f3e8d13041','abcd@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3241,'colt2005',1164253112,0,0,'',0,'chitic stefan',0,0,'','d07667a4169dc7e34e744959012567b89266e742','colt2005@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3448,'judy_k',1164253112,4,1,'',1271968554,'Cristina Petrovici',5,0,'','5db219b80356b3ca6359f92bd3e33e85d9229182','judy_k@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,9,'',1,1,'','','',1,1,'',40546,'','',9,40936,'','','',0,2,''),(3449,'Diana_C',1164253112,0,0,'',1169366140,'Ciocea Diana Cristina',0,0,'','14a03f48222a2173dba8cca3e1cdd7f649d0e4a8','Diana_C@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',11573,'','',0,1112,'','','',0,2,''),(3464,'zait',1164253112,0,0,'',0,'paul filimon',0,0,'','1b0c6fdf525f50904551852a2858cefe04a2cca1','zait@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3511,'marius_Dumitran',1164253112,0,0,'',0,'Marius Dumitran',0,0,'','5d731b387fb78b7859af5f27f98b513bcf6e463e','marius_Dumitran@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3539,'exist3nz',1164253112,0,0,'',0,'Ionescu Cristina',0,0,'','4c4d0c3824b7a58458cf1397b05327e5aaa88820','exist3nz@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3547,'claustan',1164253112,0,0,'',0,'Stan Claudiu',0,0,'','0b8d1588b480e874a2214e0eb85dcd86eba331d4','claustan@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3636,'sima_cotizo',1164253113,539,2,'',1272147035,'Sima Cotizo',85,0,'','234d80ce23b6abecf9d0c20e8eebe7da6356d63d','sima_cotizo@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,105,301,'',1,1,'','','',1,1,'',40558,'','',18,1744288,'','','',0,2,''),(3784,'inkriptor_scn',1164253113,0,0,'',0,'maran tiberiu',0,0,'','8ad8a27931c9f44275f5f95b8f00ee7210544bf4','inkriptor_scn@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(3948,'Chici',1164253113,0,0,'',0,'Han Bogos Adamita',0,0,'','3d32226afbef251504acc8c8fb42d3bb4a3fe600','Chici@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4061,'lilix0202',1164253113,0,0,'',0,'nesu liliana',0,0,'','7ee8a275b96b49b554a89577a88133d9c4754261','lilix0202@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4074,'laiurita88',1164253113,0,0,'',0,'laura',0,0,'','03616513e0a3574b164c8a13e00673f82484045d','laiurita88@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4075,'lupu',1164253113,0,0,'',0,'lupulescu',0,0,'','b9a1c42de0d4b32e352660b9ee55117d1943e4b5','lupu@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4179,'mfuqm31',1164253114,0,0,'',0,'Mitarca Mihai',0,0,'','7da5d690d4df7d931a14e2d960da3d780bd300cc','mfuqm31@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4320,'raduzer',1164253114,71,20,'',1271175241,'Radu Zernoveanu',18,0,'','775fe49c1e6a614be5597dcfe0e8f5cbea239978','raduzer@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,88,150,'',1,1,'','','',1,1,'',40365,'','',11,176123,'','','',0,2,''),(4354,'danutzul_05',1164253114,0,0,'',0,'vicol daniel-ionut',0,0,'','80efe069545b56e83a633f1fb3215c5f56c4b6e9','danutzul_05@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4376,'tmir',1164253114,0,0,'',0,'nam',0,0,'','3853df7a2732206a606ff50400a3f3bfca168c7d','tmir@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4432,'Ioana_bomboana',1164253114,0,0,'',0,'Popescu Ioana',0,0,'','65f64a63156100f3d6a4fe8e655e5d429d946bca','Ioana_bomboana@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4492,'bianca_bya',1164253115,0,0,'',0,'boeriu bianca',0,0,'','c2543b05b39660ea5e0d8942604dfd8a43b4e397','bianca_bya@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4603,'andras',1164253115,0,0,'',0,'Halalai Tudor Andrei',0,0,'','68f52bf8ce39bbcca1b4cc75fec66bced04b0aca','andras@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4626,'IcemaN_ro',1164253115,0,0,'',0,'Alex Moldovan',0,0,'','a86f4a79e36d5da244ac0f4da2ed31cb274a3103','IcemaN_ro@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4707,'bc_costy',1164253115,0,0,'',0,'Blindu Constantin',0,0,'','834a817e64d8d9674c76f4c25bca162214fc77f3','bc_costy@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4767,'vic_and',1164253115,0,0,'',0,'Victor Andrei',2,2,'','45bccb08e9c96f1f1a8b24075a82091f5b000c95','vic_and@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4798,'Alexus',1164253115,0,0,'',0,'Stoica Alexandru',0,0,'','b184946119b11a9af04fb50b7a08ce96d66a4dbb','Alexus@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4830,'claudia',1164253115,0,0,'',0,'Simon Claudia Mihaela',0,0,'','c37f4d9d68d19869f97921ed28bb83c2bb873183','claudia@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4882,'Dastas',1164253116,169,0,'',1271979061,'Ionescu Vlad',18,0,'','9a2d2412661e555626ae21142b17706acd3d85a6','Dastas@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,28,38,'',1,1,'','','',1,1,'',40546,'','',17,3196564,'','','',0,2,''),(4913,'nirvanablue25',1164253116,0,0,'',0,'rosoiu cristina mihaela',0,0,'','c939433eeb276fc38604e442b628dd1f6d7d8bab','nirvanablue25@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4932,'onu_flo',1164253116,0,0,'',0,'Pirvu Ionelia',0,0,'','568df585fe71aac584f29fc87eea1ff73a3fcc9c','onu_flo@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(4975,'manu_deutza',1164253116,0,0,'',0,'cojocaru andreea',0,0,'','00236c908b681930e15067c0267c57f5f57ea77f','manu_deutza@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5084,'cocoru',1164253116,0,0,'',0,'agarici',0,0,'','983614aa65064093aab7a84c3b9d96b477851e9d','cocoru@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5087,'savim',1164253116,72,20,'',1272109768,'Serban Andrei Stan',18,0,'','da9e6f0eff30aaa361b619b870c0b9faa3d42edf','savim@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,93,140,'',1,1,'','','',1,1,'',40266,'','',11,404406,'','','',0,2,''),(5118,'lemne',1164253116,0,0,'',1201508577,'Lemne Lemne',0,0,'','999d42e0b834887e1d239e793c30538ef814c648','lemne@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',13947,'','',0,1005,'','','',0,2,''),(5154,'xanthe',1164253116,0,0,'',1165824143,'Teodora',0,0,'','f36a84999ece82cc1f76d44bc38a8acafc8a1f87','xanthe@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',11108,'','',0,0,'','','',0,2,''),(5169,'mlegs',1164253116,0,0,'',0,'nec',0,0,'','4090c05e00e6914c0e66f8cce9a5999891b3490e','mlegs@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5298,'root',1164253116,0,0,'',0,'/boot/vmlinuz',0,0,'','33a485cb146e1153c69b588c671ab474f2e5b800','root@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5486,'ankutsa',1164253117,0,0,'',0,'Lasc Anca',0,0,'','bcbacf1bb317e73f1f149e56061f783295664718','ankutsa@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5513,'AndreiDumi',1164253117,0,0,'',0,'Andrei',0,0,'','fe86a8eef0b11608cfbdf38ade3dc6f5cb9a2d9a','AndreiDumi@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5601,'Dany_perfect',1164253117,0,0,'',0,'Moldoveanu Daniel-Stefan',0,0,'','d51f6ee42a9f638a22e443dca72844d5b14e2815','Dany_perfect@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5616,'ge_ronimo17',1164253117,0,0,'',0,'george ionutz',0,0,'','2119b9f4d33de86012b9baeee17fa886f4b9ac7c','ge_ronimo17@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5628,'eval',1165175672,0,0,'',0,'Evaluatorul infoarena',0,0,'','99f84d9f2e99cba220e37d9e293f295da6e5c3f4','eval@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5656,'armasanea',1165908138,0,0,'',0,'Sanea Prodan',0,0,'','838c875337361dc5f9acc4d1630cbf59ebf49e92','armasanea@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5720,'kana',1166087956,0,0,'',1166089438,'Preda Mihai',0,0,'','3fd4b994292b78fc431bb0e216c2ec1706b19803','kana@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',11192,'','',0,0,'','','',0,2,''),(5772,'kezman',1166462141,0,0,'',0,'adrian',0,0,'','9d07edd26624176d3b8dea8354350c0ece476fb1','kezman@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5864,'fish',1168595905,0,0,'',0,'bogdan negrila',0,0,'','c0dd43cd1855a421dcfc03644ab1c50d6d0424db','fish@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5889,'floringh06',1168776794,5,0,'',1271085045,'Florin - Cristian Ghesu',11,0,'','cd71e4a11e8a3ea4472485c775e484a229d37c5e','floringh06@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,6,5,'',1,1,'','','',1,1,'',40320,'','',9,135717,'','','',0,2,''),(5895,'cavin',1168873674,0,0,'',0,'Gosman Catalin',0,0,'','0f4a9d7c5dd2e2b6420097dc3b2f1c207f016e75','cavin@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5959,'razvan_varnita',1169545158,0,0,'',0,'dragomir razvan',0,0,'','d6184148615b2a64ad228dd52a88c5343afbcc89','razvan_varnita@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',1,1,'',0,'','',0,0,'','','',0,2,''),(5984,'Florian',1169645768,793,0,'',1272129520,'Marcu Florian',94,0,'','321cf8f0b3166041d167aa30bb112180fbc28b7a','Florian@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,244,336,'',1,1,'','','',1,1,'',40556,'','',18,2716485,'','','',0,2,''),(6298,'toni2007',1171741549,505,20,'',1272147610,'Pripoae Teodor Anton',113,0,'','621a55b6f1da52ee5809a53cce92ace3847632ec','toni2007@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,277,363,'',1,1,'','','',0,1,'',40545,'','',18,900431,'','','',0,2,''),(6349,'reSpawn',1172270177,0,0,'',1223556716,'Rosia Nicolae',0,0,'','e58eb6300925f62b67ad8fc27c02824d4269784a','reSpawn@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',12799,'','',0,17214,'','','',0,2,''),(6409,'gabitzish1',1172837361,709,2,'',1272142790,'Gabriel Bitis',90,0,'','a832fc848ecf51556b1d9fd31279c5f35341200b','gabitzish1@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,260,475,'',1,1,'','','',0,1,'',40558,'','',18,4731324,'','','',0,2,''),(6461,'ln_anila',1173247948,0,0,'',1173294576,'Alina Nitu',0,0,'','ef27061cef8a23e8ce81ac6c53fd0f79d4a073bd','ln_anila@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',13411,'','',0,0,'','','',0,2,''),(6432,'nistaman',1173021355,0,0,'',0,'Bogdan Komen',0,0,'','1e31816150493a262ace01243e854c5d55c1fbbf','nistaman@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(6454,'Nebhotep',1173182046,0,0,'',1175614648,'Metes Alexandru',0,0,'','06a1a04fcd17c0b07a1f39ff4eb28eb5a866d3aa','Nebhotep@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',13399,'','',0,1986,'','','',0,2,''),(6543,'lebappe',1174152232,0,0,'',0,'Bogdan Popa',0,0,'','e430f6209550892dbbc3aa0d441a394a68b06b96','lebappe@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(6570,'Mishu91',1174552826,640,0,'',1272145513,'Andrei Misarca',53,0,'','e5f53468610c31c7f4549b0f3a4e1e05a8dbfac6','Mishu91@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,69,161,'',1,1,'','','',0,1,'',40558,'','',18,3574693,'','','',0,2,''),(6658,'cristi_c',1176196073,1,0,'',1237192394,'Chirac Cristian',1,1,'','13ab03f0f890e7057ea125e07714b95d6ae40bc9','cristi_c@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',14921,'','',9,1939,'','','',0,2,''),(6680,'ada_s',1176830489,4,0,'',1271222025,'Ada-Mihaela Solcan',0,0,'','b550dafed22cb780059a3679bf31db5ad387d9b7','ada_s@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,6,11,'',1,1,'','','',0,1,'',40382,'','',9,296455,'','','',0,2,''),(6720,'danciac',1177595784,0,0,'',1207671067,'Cracan Dan',0,0,'','cc693af8be52ba184ae0652b87dea4b16a712693','danciac@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',15344,'','',0,594,'','','',0,2,''),(6806,'hardvirus',1180077671,0,0,'',1246388763,'Ardelean Horia',0,0,'','4bc045de6294ff37e35b2203076b01e6ed4b4d19','hardvirus@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',15900,'','',0,4922,'','','',0,2,''),(6931,'alexandru.mosoi',1186311176,12,0,'',1221296734,'Alexandru Mosoi',5,5,'','f4a5a1b6904da106c3166cdbd68cd3ad58a5ba32','alexandru.mosoi@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,9,9,'',1,1,'','','',0,1,'',20529,'','',9,10221,'','','',0,2,''),(6965,'marsamg',1187591575,0,0,'',1187594150,'Marius Andrei',0,0,'','fa58f34a947a006629cbbff3a97da9e967c22818','marsamg@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',17393,'','',0,73,'','','',0,2,''),(6997,'100puncte',1189085060,1,0,'',0,'Ionut Popa',0,0,'','c60ed642c05f833d7d6dedbfd2e305e119af01af','100puncte@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,2,1,'',1,1,'','','',0,1,'',0,'','',9,0,'','','',0,2,''),(7037,'GavrilaVlad',1190376463,22,0,'',1271878504,'Gavrila Vlad',1,0,'','c30cd987e7a86566146af8bf13ff0c79468ad6a6','GavrilaVlad@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,245,271,'',1,1,'','','',0,1,'',40488,'','',9,353487,'','','',0,2,''),(7104,'unubou',1191510929,0,0,'',0,'Isac Razvan Alexandru',0,0,'','d9de0cd9da371ee646517699c78f1d33b79f9ab8','unubou@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(7111,'kaya',1191511315,0,0,'',0,'Marina Mihailescu',0,0,'','2f91874fe8105df9519fac90ee525314efa6a519','kaya@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(7249,'gabi_bobocel',1194076286,0,0,'',0,'Boboc Costin Gabriel',0,0,'','92a168802fae6aade88c7c6585f0ac79e94c7922','gabi_bobocel@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(7260,'COstel',1194117725,0,0,'',1194254729,'Petrea Constantin',0,0,'','40be77057e797da09f2067c7ae7be368f69f9284','COstel@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',19175,'','',0,132,'','','',0,2,''),(7337,'corinabolfa',1195046308,0,0,'',0,'bolfa corina',0,0,'','15e9b87bef3a054dd82e533e0531436bd0b581cd','corinabolfa@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(7353,'paulrusu',1195160343,0,0,'',1197018777,'paul rusu',1,0,'','a32d9703ad2cfffe8be751d4e80eda2f03c2de97','paulrusu@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',19493,'','',0,1272,'','','',0,2,''),(7385,'GheorgheMihai',1195635207,5,20,'',1272098539,'Gheorghe Mihai',0,0,'','0ad371d724545ea4dc4e865f950846844e7c7c53','GheorgheMihai@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,4,'',1,1,'','','',0,1,'',40226,'','',9,172669,'','','',0,2,''),(7383,'roxyshor',1195588901,0,0,'',0,'Leonte Roxana',0,0,'','d2878f85428d7427406150f4b570b7541eb94bef','roxyshor@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(7508,'andrei-alpha',1196698412,80,0,'',1272128910,'Andrei-Bogdan Antonescu',38,0,'','fbb177aae061688fbcc8bfe0e4d6c7d739b25aee','andrei-alpha@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,32,123,'',1,1,'','','',0,1,'',40422,'','',11,1022990,'','','',0,2,''),(7517,'DanielG',1196860405,10,0,'',1271696237,'Glodeanu Ioan Daniel',3,0,'','d606ee4e75fceba83f8d6793c19f27a8ff7eeba4','DanielG@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,3,5,'',1,1,'','','',0,1,'',40498,'','',9,183508,'','','',0,2,''),(7527,'login',1196875999,0,0,'',1271835228,'Anca Login',8,0,'','a12c2ca48c890306edbe99637ad2c62195edabb1','login@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,2,'',1,1,'','','',0,1,'',40169,'','',0,4512,'','','',0,2,''),(7557,'123456789',1197210028,0,0,'',0,'ghita gheorghita',0,0,'','3175de158db24c987b7ced3bf65d46c1fcfb3c5f','123456789@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(7570,'cosser',1197306166,39,0,'',1251132387,'Bula Ionut',3,0,'','6a0ca20a9b887058821f2f57f1d4d378b0e15107','cosser@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,9,13,'',1,1,'','','',0,1,'',35085,'','',10,79703,'','','',0,2,''),(7632,'BigMazilu',1199339751,13,0,'',1250781635,'Mazilu Victor',6,0,'','33292d8b3415e02363e365267a3b865616bcd6d0','BigMazilu@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,42,10,'',1,1,'','','',0,1,'',35024,'','',9,33614,'','','',0,2,''),(7661,'ruxandra_enus',1200054038,0,0,'',0,'ruxandra enus',0,0,'','0e52889b5505e7fa7be545d01f821dd6d5dcb085','ruxandra_enus@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(7685,'radoo',1200316623,0,0,'',1200318048,'Miron Radu Emanuel',0,0,'','15362d1446de569734aaf038ba3367a22e74637f','radoo@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',21176,'','',0,0,'','','',0,2,''),(7905,'andrici_cezar',1203506110,98,0,'',1261039234,'Andrici Cezar',21,0,'','cf2d97908f0e321da3b95d650a98d150a9923b9b','andrici_cezar@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,78,24,'',1,1,'','','',0,1,'',36529,'','',11,120709,'','','',0,2,''),(7969,'petro',1204111269,3,0,'',1271093437,'Milut Petronela',8,0,'','0d33b789ef661e7bb834127c987fa3e5ab20f8d5','petro@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',35623,'','',9,11549,'','','',0,2,''),(8057,'shmecheru',1205149367,0,0,'',1205217368,'Shmecheru',0,0,'','52b97657e7d5e2f13341263caf0c5887947985f9','shmecheru@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',23036,'','',0,0,'','','',0,2,''),(8078,'darkdude',1205301906,0,0,'',1238429179,'Andrei Barsan',2,2,'','b24005dd227f3e9e0752522204855940b4399534','darkdude@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',24268,'','',0,602,'','','',0,2,''),(8142,'1gnition',1205592925,2,0,'',1228911521,'Strambu George',0,0,'','128c3fa831fd5d8cdd668819fb527a7ec50f809a','1gnition@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,4,2,'',1,1,'','','',0,1,'',25698,'','',9,2284,'','','',0,2,''),(8191,'chryss13',1206066751,0,0,'',1237369215,'cristina',0,0,'','7a5e23a60f47e906f300220ac91d69fe3a2ba32f','chryss13@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',31677,'','',0,434,'','','',0,2,''),(8264,'stocarul',1207131819,130,20,'',1272122433,'Cosmin Mihai Tutunaru',17,0,'','82e18cdc5a097c42077618756441f74a84923809','stocarul@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,38,53,'',1,1,'','','',0,1,'',40469,'','',13,372987,'','','',0,2,''),(8355,'andreiparau',1208274731,0,0,'',1229464441,'Andrei Parau',0,0,'','4e93e748d7c464196802ba7f926ad4d58dedcb49','andreiparau@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',28867,'','',0,70,'','','',0,2,''),(8368,'Leka',1208328397,0,0,'',0,'Pascu Alexandra',0,0,'','4a50c6898738ef0f180f41626db50bbc9d5ecf3b','Leka@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(8418,'stelistul',1209923031,0,0,'',0,'Bora Calin',1,1,'','8660b97240b081ee83613b1a0c12594f23314a3b','stelistul@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(8438,'Torque',1210156059,0,0,'',0,'Paducel Vladut Emil',0,0,'','552b96247f8493d1cb090a61c8886c60d1991de9','Torque@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(8497,'cata00',1211840138,5,0,'',1267428108,'Catalin Francu',3,1,'','ce60b3655f53a236ff1ea89aacd312fb4a17df1f','cata00@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,12,'',1,1,'','','',0,1,'',38638,'','',9,7685,'','','',0,2,''),(8536,'dexterelu',1212429647,0,0,'',1212432304,'Paul Raetchi',0,0,'','4504f99dfafd5a1f0646d04c592362fa3f121463','dexterelu@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',26199,'','',0,0,'','','',0,2,''),(8698,'upb_sdv',1221188984,0,0,'',0,'Gravity',0,0,'','25adbf3092e901992eeae04246fc249968b75c61','upb_sdv@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(8752,'cristi.oprea',1222099999,0,0,'',1222100555,'oprea cristi',0,0,'','fbdcfe6d36c4a5050924fcb312db126b03be8bd6','cristi.oprea@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',27339,'','',0,290,'','','',0,2,''),(8874,'lorincziisti',1224073260,0,0,'',0,'Lorinczi Istvan',0,0,'','b1e9445fb1222c08207ee991aa29cc2041f30ba9','lorincziisti@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(8927,'motty',1224839332,6,0,'',1272121866,'Matei-Dan Epure',6,0,'','58208a97c63a99a24cd7dde25e9582d776108dbf','motty@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,4,4,'',1,1,'','','',0,1,'',39838,'','',9,32617,'','','',0,2,''),(9021,'monocrom133',1226130296,0,0,'',0,'andreea raluca turcu',0,0,'','d1a5d6940189817f2a74cfdcb1c10e96f6a2cd1a','monocrom133@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(9045,'dragosldf',1226414757,0,0,'',0,'lazar dragos',0,0,'','e2e4a82e1fab10e648f0e38eb72128a4292cd309','dragosldf@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(9374,'mjoska',1229163501,0,0,'',1229163863,'Miklos Jozsef',0,0,'','8c09006a91113a9dd97183ee6c548105dd1ce522','mjoska@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',28874,'','',0,0,'','','',0,2,''),(9398,'FlorinOv',1229248530,0,0,'',0,'florin',0,0,'','f2b9a76834c716253c842439f0a1a504f59bb734','FlorinOv@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(9469,'mathboy',1230144217,79,0,'',1272132202,'Dragos-Alin Rotaru',23,0,'','beaa1c3d7b3705d3fda0f91df952d8582ec94b75','mathboy@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,13,34,'',1,1,'','','',0,1,'',40579,'','',11,1085257,'','','',0,2,''),(9593,'miculprogramator',1232132816,313,0,'',1272143282,'ALbulescu Cosmina',70,0,'','b3e87bcb19c906e85e934d7f77acc157b2916293','miculprogramator@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,180,220,'',1,1,'','','',0,1,'',40564,'','',18,1021358,'','important','',0,2,''),(9691,'oana_enusoiu',1233159134,0,0,'',0,'oana enusoiu',0,0,'','81c1689411c90ae9205dba7a35c61dbb6aec9d32','oana_enusoiu@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(9730,'AlexandruB',1233559263,0,0,'',1233560496,'Bordea Alexandru',0,0,'','c9d1722589c775c41e155532d5432795247a2b88','AlexandruB@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',30076,'','',0,799,'','','',0,2,''),(9740,'metalkitten',1233761175,0,0,'',1271603935,'Georgiana Arhip',6,0,'','3964e69d383e24b8549a3aca7424228b87c11a5c','metalkitten@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',40477,'','',0,5238,'','','',0,2,''),(9834,'SergiuC',1234956834,0,0,'',0,'Corneanu Sergiu',0,0,'','b5f1121fb6d026f8063ecd9a3bb51ef0b1541e7c','SergiuC@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(9976,'zerobarat',1235993464,0,0,'',0,'alexandra',0,0,'','cfcae2b48dcc797a9dbe58cbec465bb17ce22e3d','zerobarat@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(10067,'v_vero_93',1236761893,0,0,'',0,'Velciu Veronica Mihaela',0,0,'','a3af29b10f55b85246b4a8c41be35bec455e95c8','v_vero_93@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(10128,'GMF92',1237135352,0,0,'',1249343721,'numele meu',0,0,'','ed80bd077629ae0ef847c1e13b91c74a38a9ade1','GMF92@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',34742,'','',0,0,'','','',0,2,''),(10384,'pcinfo',1240328349,5,0,'',1269607752,'Carmen Popescu',0,0,'','0ddd510b2c62570a1fa0e2a4a32aeb6b3ebe3acc','pcinfo@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,1,4,'',1,1,'','','',0,1,'',34837,'','',9,9126,'','','',0,2,''),(10328,'pufuleti_sange',1239017967,0,0,'',1239018062,'pufuleica sange bors',0,0,'','987feb6b67df74fa21c5317f7913225e0968ae25','pufuleti_sange@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',32511,'','',0,230,'','','',0,2,''),(10537,'Sergiu_92',1243107732,0,0,'',1243185899,'Sergiu Savin',0,0,'','b1de5bb378237d37cec06a31ee6feb59c384cef9','Sergiu_92@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',33439,'','',0,0,'','','',0,2,''),(10784,'thesvcoolman',1247904857,0,0,'',1255542866,'Lucian Bicsi',0,0,'','620aa74ecf32743442e2ab93ded6fbee200b52e7','thesvcoolman@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',35646,'','',0,0,'','','',0,2,''),(10967,'andreii_93',1254114642,0,0,'',1255593868,'andrei ion',0,0,'','853cbb0bfb2ad7236dcd9dccff86dba4541363ea','andreii_93@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',35648,'','',0,88,'','','',0,2,''),(11020,'BringitON',1254572918,0,0,'',1254573331,'Breban Andrei',0,0,'','d47695c76fcf2ee4b2b9a9c5f374af5cda9368c7','BringitON@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',35538,'','',0,0,'','','',0,2,''),(11125,'Andrei29',1255675513,0,0,'',1255675721,'Andrei Paduraru',0,0,'','8fbd8a0c533044d1dc95be02839ecf69cfb1f876','Andrei29@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',35658,'','',0,0,'','','',0,2,''),(11261,'leva',1256812910,0,0,'',0,'Leva Ionut',0,0,'','e05d06dc7bb6d0f8c69c0f0c7520478f0686542d','leva@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(11283,'maoo',1257016932,0,0,'',0,'Bompa Mario',0,0,'','c9b9afb8b7cff6be3603edfdbef2afeb8e175458','maoo@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(11559,'ionut.pic',1258895892,0,0,'',1258896146,'popa ionut cristian',0,0,'','c3f7b847bada7b4675f7212fed19e120c6958ebb','ionut.pic@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',36353,'','',0,171,'','','',0,2,''),(11586,'petru000',1259311007,0,0,'',1259311052,'petru sorin',0,0,'','f43ab6cb7086dc9d1c9d7e02a44c48ac1b8f34e4','petru000@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',36414,'','',0,0,'','','',0,2,''),(11593,'AlecSs',1259403658,0,0,'',0,'Hulpe Alexandru',0,0,'','de3e0f7f79025a58e86666f8fda7ff0ea4a4bb72','AlecSs@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(11674,'VyperBoy',1260367227,0,0,'',1260376712,'Marin P',0,0,'','aad65a6286c65f89b9e1b311830aef6292dfcd31','VyperBoy@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',36638,'','',0,0,'','','',0,2,''),(11811,'cristialexandru',1262999238,0,0,'',0,'Cristi Alexandru',0,0,'','1763f7661feb6665cc1888e5c51839010f13d034','cristialexandru@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(11825,'u2tommyf',1263139127,0,0,'',1263139356,'Toma Florina',0,0,'','c01245a3db435642c2b633027eaf700f4a073f28','u2tommyf@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',37228,'','',0,164,'','','',0,2,''),(12036,'alexandrul',1265560536,0,0,'',0,'Alexandru Mihai',0,0,'','467f6e577fb3aaf448618aa5446815a63269888c','alexandrul@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(12056,'verdecrud',1265797182,0,0,'',0,'PensiuneaVerdeCrud',0,0,'','d3883703eafccac1260e40c7f9d16ef9d6362d60','verdecrud@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(12133,'hexor',1266395273,0,0,'',1266395599,'Serban Dragos',0,0,'','303dc13dfd3083a6df451fb884fce363d504b7ed','hexor@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',38159,'','',0,289,'','','',0,2,''),(12143,'bogdanelu006',1266430631,0,0,'',0,'bogdan',0,0,'','056cbfd58d9b31ab51f5ffff07a8f4748ae92186','bogdanelu006@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(12315,'Aleks10',1267604357,0,0,'',0,'Petrache Alex',0,0,'','207974a77e61353d2e5e3be9f0e799d723ce8271','Aleks10@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(12471,'Mihai-Daniel',1268814636,0,0,'',0,'Mihai-Daniel',0,0,'','7d75d164955f9c0428ce32c1c1f096d4057dfe91','Mihai-Daniel@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(12689,'SITZ',1270603556,0,0,'',0,'Sitesh Shrivastava',0,0,'','8ba3d09541382c1200f9b667ece67f6119fc43b1','SITZ@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(12738,'Bogdan.Cirstea',1270761650,0,0,'',1271148090,'Cirstea Bogdan-Ionut',0,0,'','70e3f4cf8afc1f6623d468dc2200b4d11e55067c','Bogdan.Cirstea@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',40350,'','',0,0,'','','',0,2,''),(12808,'jenniferlmartin',1271229666,0,0,'',0,'jennifer martin',0,0,'','494b1771479e4ce4f0cc6ec2a6910e1c30b62d15','jenniferlmartin@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',0,'','',0,0,'','','',0,2,''),(12813,'Andrei1998',1271263113,0,0,'',1271266835,'Constantinescu Andrei Costin',0,0,'','aab484e89badc20dcba053ded737bb155a94aa74','Andrei1998@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',40413,'','',0,0,'','','',0,2,''),(12839,'IonelaD',1271512613,0,0,'',1271718523,'Dinica Ionela',0,0,'','e02c5550e542734e5c324a76314c4f04e59e55d3','IonelaD@example.com','',0,'0001-01-01','','','','','','','',0,1,'','',0,'',1,0,0,'',1,1,'','','',0,1,'',40469,'','',0,0,'','','',0,2,'');
 /*!40000 ALTER TABLE `ia_smf_members` ENABLE KEYS */;
 UNLOCK TABLES;
 
@@ -1678,7 +1678,7 @@
 
 LOCK TABLES `ia_textblock` WRITE;
 /*!40000 ALTER TABLE `ia_textblock` DISABLE KEYS */;
-INSERT INTO `ia_textblock` VALUES ('preoni-2005/runda-1','preONI 2005 (Runda 1)','2006-11-24 23:48:25','2006-11-25 03:08:57','h1. preONI 2005 (Runda 1)\r\n\r\nConcursul s-a desfasurat Duminica, 23 ianuarie 2005, ora 15:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nSolutiile problemelor le puteti gasi \"aici\":preoni-2005/runda-1/solutii\r\n\r\nh2. Clasele 9-10 (\'Clasament\':preoni-2005/runda-1/clasament-9-10)\r\n\r\n!>preoni-2005/runda-1?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni51a\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2005/runda-1/clasament-11-12)\r\n\r\n!>preoni-2005/runda-1?logo2.gif!\r\n\r\n== Tasks(round_id=\"preoni51b\" pager_style=\"none\") ==',961,'protected',NULL,NULL),('preoni-2005/runda-2','preONI 2005 (Runda 2)','2006-11-24 23:57:04','2006-11-25 03:09:10','h1. preONI 2005 (Runda 2)\r\n\r\nConcursul s-a desfasurat Miercuri, 23 februarie, ora 16:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nSolutiile problemelor le puteti gasi \"aici\":preoni-2005/runda-2/solutii\r\n\r\nh2. Clasele 9-10 (\'Clasament\':preoni-2005/runda-2/clasament-9-10)\r\n\r\n!>preoni-2005/runda-2?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni52a\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2005/runda-2/clasament-11-12)\r\n\r\n!>preoni-2005/runda-2?logo2.gif!\r\n\r\n== Tasks(round_id=\"preoni52b\" pager_style=\"none\") ==',961,'protected',NULL,NULL),('preoni-2005/runda-3','preONI 2005 (Runda 3)','2006-11-25 00:02:20','2006-11-25 03:09:36','h1. preONI 2005 (Runda 3)\r\n\r\nConcursul s-a desfasurat Duminica, 20 martie la ora 10:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nSolutiile problemelor le puteti gasi \"aici\":preoni-2005/runda-3/solutii\r\n\r\nh2. Clasele 9-10 (\'Clasament\':preoni-2005/runda-3/clasament-9-10)\r\n\r\n!>preoni-2005/runda-3?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni53a\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2005/runda-3/clasament-11-12)\r\n\r\n!>preoni-2005/runda-3?logo2.gif!\r\n\r\n== Tasks(round_id=\"preoni53b\" pager_style=\"none\") ==',961,'protected',NULL,NULL),('usaco-oct-2005-divizia-gold','USACO oct 2005, divizia GOLD','2005-11-21 00:00:00','2006-11-22 02:29:02','h1. USACO oct 2005, divizia GOLD\r\n\r\n(Categoria _Competitii_, autor(i) _Florea Tiberiu_)\r\n\r\nCa de obicei, USACO debuteaza in luna octombrie cu un concurs prin care oricine se poate califica la o divizie superioara celei in care se afla.\r\n\r\nRomania a avut $8$ concurenti care s-au calificat (sau recalificat) la divizia GOLD, fiind depasita in acest clasament doar de China ({$16$}) si SUA ({$10$}). Bineinteles, acest clasament nu este foarte relevant, deoarece multi dintre cei calificati deja au preferat sa nu participe sau sa nu ia concursul foarte in serios.\r\n\r\nElevii romani care au obtinut punctajul necesar pentru (re)calificare sunt:\r\n\r\n* Andrei Teodorescu (andreit1)\r\n* Vladu Adrian (azotlic1)\r\n* Andrei Blanaru (blanaru1)\r\n* Sorin Fagateanu (cyronon1)\r\n* Ionel Corneliu Gog (gogione1)\r\n* Tiberiu Florea (greco2)\r\n* Pasoi Mircea (mircea_1)\r\n* Vlad Berteanu (vladcyb1)\r\n\r\nProba a constat in $2$ probleme de nivel mediu care trebuiau rezolvate in $2$ ore.\r\n\r\nh2. Skiing\r\n\r\nPrima rezolvare care ne vine in minte citind o astfel de problema este transformarea matricii intr-un graf cu R * C noduri si calcularea drumului minim dintre nodurile ({$1, 1$}) si ({$R, C$}). O observatie destul de evidenta este ca toate muchiile care intra intr-un nod (a, b) vor avea acelasi cost, adica {$V * 2 ^ H{~1,1~} - H{~a,b~}^$}. Deoarece implementarea obisnuita a algoritmului Dijkstra are complexitatea $O (N^2^ + M)$ considerand $N$ = numarul de pozitii si $M$ numarul de muchii dintre acestea ({$N = R * C, M = 4 * R * C - 2 * (R + C)$}) va trebui implementata varianta in care se foloseste o coada de prioritate pentru nodurile care nu au fost explorate deja: implementand varianta cu heap-uri vom obtine complexitatea {$O((N + M) * lg N)$}, care se incadreaza in timp.\r\n\r\nPentru cei care nu sunt familiari cu aceasta varianta a algoritmului, ea arata cam asa:\r\n\r\np(pre). D{~sursa~} <- 0\r\nheap_sz = 1\r\nheap{~heap_sz~} <- sursa\r\npentru $i$ de la $1$ la $N$\r\n    daca i != sursa\r\n        D{~i~} <- oo\r\n        heap_sz <- heap_sz + 1\r\n        heap[heap_sz] <- i\r\ncat timp heap_sz > 0\r\n    x <- extrage_min (heap)\r\n    daca x = destinatie\r\n        returneaza D{~x~}\r\n    altfel\r\n        pentru i de la 1 la N\r\n            daca D{~i~} > D{~x~} + cost (x, i)\r\n                descreste_cheie (i, D{~x~} + cost (x,i))\r\n\r\nFiecare nod este extras cel mult o data din heap, si pentru fiecare muchie este apelata cel mult o data functia descreste_cheie. Fiecare dintre aceste operatii se efectueaza in {$O(lg N)$}, de aici rezultand complexitatea dorita.\r\n\r\nDe asemenea, putea fi aplicata o alta varianta a algoritmului Dijkstra, care profita mai mult de specificul problemei: In afara de vectorul estimarilor distantelor pana la fiecare nod, se memoreaza si nodul cu estimarea minima de pe fiecare din cele $R$ linii. Astfel, in momentul in care se extrage fiecare nod, cautam minimul in acest vector de dimensiune {$R$}, iar apoi reactualizam valoarea liniei pe care se afla nodul curent. Complexitatea acestui algoritm este {$O(N * R)$}, adica {$O(R^2^ * C)$}.\r\n\r\nIn implementarea oricaruia dintre acesti algoritmi trebuiau avute in vedere eventualele probleme cu precizia calculelor; o idee buna era ca numai costul final sa se inmulteasca cu {$V$}.\r\n\r\nh2. Flying right\r\n\r\nAceasta problema poate fi rezolvata cu ajutorul unui algoritm greedy, ideea nu este greu de gasit sau demonstrat, insa la implementare pot aparea unele probleme. In primul rand trebuie sa remarcam ca cele doua parti ale problemei se vor rezolva independent una de cealalta, drumurile se vor imparti in $2$ multimi (cele de dimineata, si cele de seara), si se va aplica aceeasi rezolvare pentru fiecare din cele doua multimi, raspunsul final fiind suma celor doua rezultate partiale. Rezolvarea urmatoare trateaza calcularea rezultatului optim pentru drumurile de dimineata.\r\n\r\nPentru fiecare din cele $N$ ferme tinem o lista de grupuri care doresc sa plece din orasul respectiv si sortam aceste liste crescator dupa indicele destinatiei fiecarui grup. Parcurgem in ordine cele $N$ ferme, memorand numarul si destinatiile vacilor care se afla la un moment dat in avion, sortate in ordine descrescatoare. In momentul in care am ajuns la ferma {$i$}, primul lucru pe care trebuie sa il facem este sa dam jos vacile care au ajuns la destinatie, incrementand corespunzator solutia de pana atunci. Evident, vacile care coboara la ferma respectiva se vor afla pe ultimele pozitii in ordinea descrisa din avion. Urmatorul pas este sa luam in avion din vacile care pleaca de la ferma $i$ pana cand acestea sunt epuizate sau capacitatea avionului este saturata. Daca au mai ramas vaci care nu au avut loc in avion, atata timp cat putem lua o vaca a carei destinatie este mai apropiata decat cea mai departata dintre destinatiile vacilor care se afla deja in avion, consideram ca vaca respectiva din avion nu a fost luata deloc, si ca alocam locul ei noii vaci, care va cobori mai repede.\r\n\r\nEste usor de vazut ca algoritmul de mai sus produce o solutie optima, insa implementarea sa nu este foarte lejera. Putem folosi urmatoarea metoda ({$v$} este un vector in care retinem destinatiile vacilor care se afla in avion, sortate descrescator):\r\n\r\np(pre). sol = 0, nr <- 0\r\npentru i de la 1 la N\r\n    cat timp nr > 0 si v{~nr~} = i\r\n        sol <- sol + 1\r\n        nr <- nr - 1\r\n        pentru j <- 1, j &le; C si j &le; nr vaci ce asteapta sa plece de la ferma i\r\n            nr <- nr + 1\r\n        v{~nr + 1~} = distanta celei de-a j-a vaci (in ordinea crescatoare a destinatiilor) de la ferma i\r\n        sorteaza v\r\n        pastreaza primele maxim C pozitii din v\r\n\r\nLa fiecare pas, vectorul $v$ poate fi sortat folosind {@qsort (stdlib.h)@} sau {@sort (algorithm)@}. Este necesar sa adaugam in $v$ doar primele $C$ vaci de la ferma {$i$}, deoarece daca o vaca nu este intre primele $C$ din multimea vacilor de la ferma {$i$}, este evident ca nu va fi nici intre primele $C$ din reuniunea acestei multimi cu multimea vacilor aflate deja in avion.\r\n\r\nSa recapitulam pasii algoritmului, alaturi de complexitatea fiecaruia dintre ei:\r\n\r\n* sortarea tuturor grupurilor dupa destinatie: $O(K * lg K)$\r\n* parcurgerea grupurilor si inserarea in listele corespunzatoare: $O(K)$\r\n* parcurgerea fermelor de la 1 la N, aplicand procedeul descris: $O(N * C * lg C)$\r\n\r\nAsadar, complexitatea totala a algoritmului este de {$O(K * lg K + N * C * lg C)$}, dand un timp de rulare rezonabil si o implementare fara mari batai de cap.\r\n\r\n',1,'public',NULL,NULL),('template/newuser','Profil %user_id%','2006-11-05 14:50:02','2006-12-04 00:32:37','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',13,'protected',NULL,NULL),('preoni-2006/comisie','Organizatori, preONI 2006','2006-11-26 04:47:24','2006-11-27 16:14:08','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Organizatori\r\n\r\nEchipa care se ocupa de organizarea si desfasurarea concursului *preONI 2006* este \'echipa infoarena\':echipa-infoarena (faceti click pe link pentru a afla mai multe detalii despre echipa)\r\n\r\nh2. Organizare \r\n\r\n* \'Cristian George Strat\':utilizator/wickedman : coordonator, promovare concurs\r\n* Prof. Emil Onea : organizator \'finala in tabara\':preoni-2006/finala\r\n* \'Leonard Crestez\':utilizator/fluffy : asigura buna desfasurare a concursului din punct de vedere tehnic (site-ul, evaluatorul etc.)\r\n\r\nh2. Echipa stiintifica \r\n\r\nCei care se vor ocupa de buna desfasurarea a concursului din punct de vedere stiintific (redactarea si compunerea problemelor, realizarea testelor, clarificarea intrebarilor, etc.) sunt:\r\n\r\n* \'Mircea Pasoi\':utilizator/domino \r\n* \'Cosmin Negruseri\':utilizator/cosmin\r\n* \'Silviu Ganceanu\':utilizator/silviug\r\n* \'Adrian Diaconu\':utilizator/ditzonec\r\n* \'Daniel Pasaila\':utilizator/danielp\r\n* \'Tiberiu Florea\':utilizator/greco\r\n* \'Adrian Vladu\':utilizator/azotlichid\r\n\r\nh2. Colaboratori \r\n\r\n* Dan Burzo: sigla oficiala preONI 2006\r\n* \'Cristina Stancu-Mara\':utilizator/cimi : logo-uri runde preONI 2006\r\n* \'Filip Buruiana\':utilizator/filipb : propunator probleme\r\n\r\n==include(page=\"template/preoni-2006/footer\")==',13,'protected',NULL,NULL),('preoni-2006/info','Informatii generale, preONI 2006','2006-11-26 04:43:42','2006-11-27 16:13:59','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Informatii generale\r\n\r\nh2. Motivatia \r\n\r\nIndiferent de domeniul de activitate, concursurile reprezinta un element important in pregatirea indivizilor *competenti* deoarece promoveaza spiritul de *\"performer\"* si ajuta cu mult la perfectionarea cunostintelor acestora.\r\n\r\nIdeea care sta la baza proiectului _infoarena_ este aceea de a oferi tinerilor elevi sansa de a dobandi usor cunostinte valoroase si experienta in domeniul informaticii si al tehnologiei informatiei prin programe de pregatire eficiente. Proiectul s-a materializat intr-o platforma software ce permite *evaluarea automata* a mii de programe trimise de utilizatori si intr-o comunitate online aparte, devenind un adevarat motor de promovare si dezvoltare a performantei in informatica la cele mai inalte standarde. Nevoia de oameni bine pregatiti in acest domeniu este din ce in ce mai mare in societatea de azi. Asadar, pregatirea in acens sens pentru dezvoltarea unei gandiri algoritmice si a unor ablitati de programator devine necesara.\r\n\r\nComunitatea _infoarena_ cuprinde aproape totii elevii romani ce participa la concursuri de informatica nationale si internationale. Calitatea si valoarea concursurilor noastre precum si a materialelor educationale ce le punem la dispozitie este recunoscuta atat de elevi si studenti, cat si de profesori de renume in informatica. Suntem bucurosi ca am reusit sa contribuim la promovarea excelentei in randurile elevilor si ca am facut parte din programul de antrenament a celor mai de seama olimpici ai Romaniei. Ne mandrim cu reactiile pozitive pe care le-am primit de la elevi, studenti si profesori.\r\n\r\nDaca inca nu te-ai convins, afla mai multe detalii de pe pagina \'Despre infoarena\':despre-infoarena.\r\n\r\nh2. Ce a fost *preONI?*\r\n\r\nAnul 2005 a fost prima data cand concursul *preONI* a fost structurat in mai multe runde, pe parcursul a mai multor luni. Acesta a adunat, pe parcursul a 3 runde, un numar de participanti intre *1500* si *2700* la fiecare runda. Ultimele doua runde au fost sponsorizate de _Microsoft Romania_ care a oferit permii constand in carti de informatica primilor trei concurenti de la fiecare grupa (au existat grupa de clase 9-10 si grupa 11-12)\r\n\r\nh2. Ce este *preONI?* \r\n\r\nIn pragul inceperii olimpiadelor, alaturi de noi contribuitori, suntem determinati sa ducem _infoarena_ la urmatorul nivel. Ca si in anii anteriori \'echipa infoarena\':echipa-infoarena  vine in sprijinul elevilor din toata tara ce se pregatesc pentru olimpiada de informatica, in special _Olimpiada Judeteana de Informatica_ (OJI) si _Olimpiada Nationala de Informatica_ (ONI). Pornind de la aceasta idee ne-am asumat responsabilitatea sa organizam un concurs de pregatire, numit *preONI*. Acest concurs se afla deja la a 5-a editie, aceasta fiind a 3-a editie organizata de \'echipa infoarena\':echipa-infoarena.\r\n\r\nSelctionarea problemelor a fost atent facuta astfel incat nivelul de dificultate sa fie apropiat de cel de la concursuri asemanatoare, cu intentia de a acoperi cat mai bine materia de concurs si a evalua complet concuretii folosind probleme de dificultati gradate. Formatul concursului este asemanator cu acela al concursurilor nationale si internationale pentru a oferi participantilor o experienta realista.\r\n\r\nCum in fiecare an \'echipa infoarena\':echipa-infoarena  doreste sa imbunatateasca eficienta programelor sale de pregatire, noul format al concursului *preONI* de anul acesta este mult mai complex decat oricare din editiile anterioare, lucru cu siguranta imbucurator pentru toti utilizatorii. Asadar, navigheaza prin meniul din dreapta-sus daca vrei sa aflii ce suprize ti-au fost pregatite!\r\n\r\n==include(page=\"template/preoni-2006/footer\")==',13,'public',NULL,NULL),('preoni-2006/regulament','Regulament, preONI 2006','2006-11-25 18:16:40','2006-11-27 16:15:05','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Regulament\r\n\r\nSe recomanda, pe langa citirea acestui regulament, citirea \"regulamentului\":regulament general infoarena.\r\n\r\nEchipa infoarena isi rezerva dreptul de a modifica prezentul regulament pe parcursul desfasurarii concursului. Daca apar prevederi noi sau daca anumite prevederi ale regulamentului sunt modificate sau eliminate, atunci acestea vor fi anuntate pe site-ul concursului. Orice modificare a regulamentului va intra in vigoare, in functie de situatie, fie din momentul publicarii ei, fie dupa incheierea rundei aflate in desfasurare. In momentul anuntarii modificarii va fi precizat si momentul din care aceasta intra in vigoare.\r\n\r\nh2. Dreptul de participare\r\n\r\nPersoanele care fac parte din echipa infoarena cat si alti contribuitorii\r\nimplicati direct in organizarea concursului *preONI 2006* nu au dreptul de a participa. De asemenea, orice concurent care are un comportament considerat inadecvat fata de echipa infoarena sau fata de alti concurenti va fi descalificat. Un concurent se poate califica la finala doar daca se incadreaza in grupa la care a concurat (aceasta verificare se va face prin prezentarea unei dovezi legale care il incadreaza pe concurent la aceea grupa).\r\n\r\nh2. Repartizarea\r\n\r\nToti participantii vor fi repartizati in 3 grupe, in concordanta cu varsta lor. Repartizarii este asemanatoare cu acea facuta la olimpiadele de informatica.\r\n\r\n* Clasa a 9a (si gimnaziu)\r\n* Clasa a 10a\r\n* Clasele 11-12 \r\n\r\nOricine poate participa la o alta grupa decat cea la care se incadreaza, dar calificarea la finala cat si impartirea premiilor se va face conform regulamentului respectiv, fara nici o exceptie.\r\n\r\nh2. Inscriere\r\n\r\nTot ce trebuie sa faceti pentru a participa la concursul *preONI 2006* este sa aveti un cont la infoarena. Inregistrarea se poate face pe site-ul infoarena. Acelasi cont va fi folosit pentru a accesa forum-ul.\r\n\r\nh2. Runde\r\n\r\nVor exista 4 runde de calficare, iar in urma clasamentului stabilit primii de la fiecare grupa vor fi selectati pentru etapa finala desfasurata in cadrul unei tabere. Cele 4 runde vor avea loc sambata incepand cu ora 9:00, desi pot interveni exceptii. Durata lor va fi de 4 ore. Pentru un program detaliat al concursului \"click aici\":preoni-2006/program.\r\n\r\nh2. Intrebari\r\n\r\nIn prima ora vor putea fi formulate eventualele intrebari, pe forum, in topicurile special create. Orice intrebare pusa in alt mod (primita ca personal message, pe mail, etc.) va fi ignorata. Raspunsuri vor fi oferite doar la intrebarile puse in prima ora . Intrebarile trebuie formulate astfel incat sa se poate raspunda cu DA sau NU. In caz contrar sau in cazul in care raspunsul se afla in textul problemei se va raspunde cu NO COMMENT. Nu vor exista exceptii de la aceaste reguli. Daca echipa va considera ca raspunsul la o anumita intrebare este de interes general si clarifica anumite aspecte, atunci se va face un anunt general care va aparea atat pe forum cat si in sectiunea Mesaje de la organizatori a grupei respective. Fiecare grupa va avea doi administratori care se vor ocupa de raspunsul acestor intrebari.\r\n\r\nh2. Trimiterea solutiilor\r\n\r\nTrimitrea solutiile se va face prin intermediul interfetei site-ului infoarena.\r\nOdata logati in contul vostru, veti putea selecta arhiva la care doriti sa\r\nlucrati (in cazul acesta una din arhivele {*preONI 2006*}) si veti putea folosi link-ul trimite solutii.\r\n\r\nh2. Evaluare\r\n\r\nDupa expirarea timpului de trimitere a solutiilor acestea vor fi evaluate (\"mai multe detalii aici\":documentatie/evaluator). In mod normal, evaluarea se va face imediat dupa concurs, desi exista posibilitatea ca echipa infoarena sa amane evaluarea din motive obiective. Veti putea vizualiza pozitia ocupata in clasament dupa evaluarea in rubrica Clasamente si alte statistici.\r\n\r\nSe recomanda sa instalati pe calculatorul vostru aceleasi versiuni de compilatoare ca cele specificate la link-ul de mai sus. Echipa infoarena nu este responsabila pentru diferentele intre versiuni de compilatoare si nu va efectua reevaluaari in astfel de cazuri.\r\n\r\nh2. Contestatii\r\n\r\nEchipa infoarena isi rezerva dreptul de a reevalua orice problema in situatia in care se detecteaza erori in teste sau in programul de verificare dupa evaluare. Cum testele problemelor nu vor fi facute publice, posiblitatile de a contesta sunt limitate. Pentru a asigura o evaluarea corecta, echipa infoarena va garanteaza ca va testa intens toate problemele inainte de concurs si ca va verifica corectitudinea procesului de evaluare dupa terminare. In caz ca totusi aveti o contestatie, aceasta trebuie trimisa pe mail la adresa preONI2006 -at- gmail.com in termen de 24 de ore de la afisarea rezultatelor rundei curente pe site. Ele vor fi rezolvate in termen de maxim 5 zile, iar dupa rezolvarea lor rezultatele vor fi declarate finale.\r\n\r\nh2. Solutii\r\n\r\nLa scurt timp dupa terminarea evaluarii se va publica un articol cu solutiile pentru problemele rundei respective. Testele utilizate pentru evaluare nu vor fi facute publice.\r\n\r\nh2. Transferul problemelor\r\n\r\nProblemele vor fi mutate dupa evaluare in Arhiva de probleme infoarena, avand astfel la dispozitie un evaluator 24 din 24 si posiblitatea de a finisa solutiile la problemele nerezolvate in timpul concursului.\r\n\r\nh2. Trisare\r\n\r\n*preONI 2006* este un concurs individual, asadar orice tentativa de colaborare va aduce descalificarea celor implicati. echipa infoarena isi rezerva dreptul de a verifica sursele concurentilor, iar in caz ca se descopera surse aproximativ identice, concurentii respectivi vor fi descalificati din concurs iar user-ul lor de pe infoarena eliminat. Tentativele de frauda (concurarea sub un alt nume decat cel adevarat, etc.) sau orice atac asupra sistemului de evaluare sau asupra paginilor infoarena vor fi pedepsite in aceeasi masura. \r\n',13,'public',NULL,NULL),('problema/party','Party','2006-11-11 11:23:36','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"party\")==\r\n\r\nGeorge vrea sa isi organizeze majoratul, si vrea ca petrecerea sa fie de neuitat, mancarea, bautura, locatia si sonorizarea sunt deja asigurate, si mai ramane problema chemarii prietenilor. El si cu prietenul lui cel mai bun Lucian au preferinte diferite si pentru a nu se certa au pus la punct o lista de cerinte care vor trebui sa fie indeplinite toate astfel incat cheful sa se desfasoare in cele mai bune conditii! Pentru usurinta, prietenii lui George vor fi indentificati prin numere intregi de la $1$ la $N$ si cerintele vor fi de tipurile $0, 1, 2$ sau $3$.\r\nO cerinta de genul $x y 0$ are semnificatia ca $x$ sau $y$ trebuie sa participe la petrecere ; $x y 1$ are semnificatia ca daca $x$ participa nu exista nici o restrictie pentru $y$, dar daca $x$ nu participa atunci nici $y$ nu participa ; $x y 2$ are semnificatia simetrica cu cerinta $1$ ; iar cerinta $x y 3$ are semnificatia ca cel putin unul dintre $x$ si $y$ nu participa la petrecere. Scrieti un program care sa-i ajute pe cei doi sa determine care persoane vor fi invitate la petrecere ; se garanteaza ca va fi posibila intotdeauna organizarea unei petreceri !\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie se vor afisa numerele $N$ si $M$ care reprezinta numarul de prieteni si numarul de cerinte de indeplinit. Pe urmatoarele $M$ linii vor fi cerinte de forma $x y z$ unde $1<=x,y<=N$ iar $0<=z<=3$.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie va fi un numar $Nr$ ce reprezinta numarul de invitati la petrecere, iar pe urmatoarele $Nr$ linii cate un invitat pe linie.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; N &le; 100$\r\n* $1 &le; M &le; 1.000$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. party.in |_. party.out |\r\n| 4 4            \r\n1 4 3          \r\n2 3 3\r\n1 2 1\r\n2 4 1\r\n|2\r\n 1\r\n3 |\r\n| 3 7          \r\n3 2 1          \r\n3 1 1          \r\n2 1 1          \r\n2 3 1\r\n3 1 1\r\n3 2 1\r\n2 3 2\r\n| 3\r\n1\r\n2\r\n3 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"party\")==\n\n\n',1490,'task: party',96,NULL),('agora-finala','Bursele agora, editia 6, finala online','2006-11-24 16:38:15','2006-12-28 02:00:59','h1. Bursele agora, editia 6, finala online\r\n\r\nAceasta este runda finala online a concursului \"Bursele Agora\", editia 6. Concursul a fost organizat de catre redactia revistei GInfo si Editura Agora Media. Concursul s-a desfasurat pe 9 iulie 2005. Puteti vedea \'clasamentul\':agora-finala/clasament, cat si un articol cu \'solutii\':agora-finala/solutii.\r\n\r\n!>agora-finala?logo.gif!\r\n\r\n== Tasks(round_id=\"ba6\" pager_style=\"none\")==',1142,'protected',NULL,NULL),('preoni-2006/clasament-10','Clasament preONI 2006, Clasa a X-a','2006-11-25 03:30:05','2006-12-01 18:13:59','== include(page=\"template/preoni-2006/rankings\") ==\r\n\r\nh2. Clasa a X-a\r\n\r\n==Rankings(rounds = \"preoni61b|preoni62b|preoni63b|preoni64b\")==',13,'protected',NULL,NULL),('preoni-2006/clasament-9','Clasament preONI 2006, Clasa a IX-a si gimnaziu','2006-11-25 03:59:30','2006-12-01 18:13:42','== include(page=\"template/preoni-2006/rankings\") ==\r\n\r\nh2. Clasa a IX-a si gimnaziu\r\n\r\n==Rankings(rounds = \"preoni61a|preoni62a|preoni63a|preoni64a\")==',13,'protected',NULL,NULL),('happy-coding-2005-2','Happy Coding 2','2006-11-23 21:08:55','2006-11-24 17:38:43','h1. Happy Coding 2\r\n\r\nCum un lucru bun nu vine niciodata singur, la insistentele publicului se organizeaza Happy Coding 2 - programare cu zambetul pe buze, pace, idei, distractie!\r\n\r\nConcursul s-a desfasurat incepand cu 10:00, 22 octombrie 2005 pana la ora 22:00 pe data de 23 octombrie. Concurentii au avut spre rezolvare 10 probleme.\r\n\r\nh2. \'Clasament\':happy-coding-2005-2/clasament\r\n\r\n!>happy-coding-2005-2?logo.jpeg!\r\n\r\n== Tasks(round_id=\"hc2\" pager_style=\"none\") ==\r\n',961,'protected',NULL,NULL),('happy-coding-2005-2/clasament','Clasament hc2','2006-11-23 21:08:55','2006-11-24 17:46:35','h1. Clasament ==roundparam(round_id=\"hc2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"hc2\")==',961,'protected',NULL,NULL),('happy-coding-2005-1/clasament','Clasament happy','2006-11-23 21:08:55','2006-11-24 17:46:59','h1. Clasament ==roundparam(round_id=\"happy\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"happy\")==',961,'protected',NULL,NULL),('happy-coding-2005-1','Happy Coding 2005','2006-11-23 21:08:54','2006-11-24 17:38:35','h1. Happy Coding 2005 \r\n\r\nHappy Coding inseamna programare cu zambetul pe buze, placere si distractie pura! :) \r\n\r\nConcursul s-a desfasurat incepand cu 10:00, 10 septembrie 2005 pana la ora 22:00 pe data de 11 septembrie. Concurentii au avut spre rezolvare 6 probleme.\r\n\r\nh2. \'Clasament\':happy-coding-2005-1/clasament\r\n\r\n!>happy-coding-2005-1?logo.jpeg!\r\n\r\n== Tasks(round_id=\"happy\" pager_style=\"none\") ==\r\n',961,'protected',NULL,NULL),('bacalaureat-2005/clasament','Clasament bac2005','2006-11-23 21:08:54','2006-11-24 18:30:13','h1. Clasament ==roundparam(round_id=\"bac2005\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"bac2005\")==',961,'protected',NULL,NULL),('agora-finala/clasament','Clasament ba6','2006-11-23 21:08:54','2006-11-24 17:47:59','h1. Clasament ==roundparam(round_id=\"ba6\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"ba6\")==',961,'protected',NULL,NULL),('preoni-2006/runda-2/clasament-10','Clasament preoni62b','2006-11-25 01:34:44','2006-11-25 01:34:44','h1. Clasament ==roundparam(round_id=\"preoni62b\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni62b\")==',961,'protected',NULL,NULL),('preoni-2006/runda-2','Runda 2, preONI 2006','2006-11-25 01:33:08','2006-11-27 16:16:04','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Runda 2\r\n\r\nConcursul s-a desfasurat sambata, 17 decembrie, la ora 09:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nh2. Comisii\r\n\r\nh3. Stiintific\r\n\r\n* clasa a 9-a (si gimnaziu)\r\n** Mircea Pasoi\r\n** Adrian Vladu \r\n* clasa a 10-a\r\n** Adrian Diaconu\r\n** Daniel Pasaila \r\n* clasele 11-12\r\n** Cosmin Negruseri\r\n** Tiberiu Florea \r\n\r\nh3. Organizatoric\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* Cristian Strat\r\n* Crestez Leonard \r\n\r\nh2. Solutii\r\n\r\nSolutiile problemelor le puteti gasi \"aici\":preoni-2006/runda-2/solutii\r\n\r\nh2. Clasa a 9-a si gimnaziu (\'Clasament\':preoni-2006/runda-2/clasament-9)\r\n\r\n!>preoni-2006/runda-2?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni62a\" pager_style=\"none\") ==\r\n\r\nh2. Clasa a 10-a(\'Clasament\':preoni-2006/runda-2/clasament-10)\r\n\r\n!>preoni-2006/runda-2?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni62b\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2006/runda-2/clasament-11-12)\r\n\r\n!>preoni-2006/runda-2?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni62c\" pager_style=\"none\") ==\r\n\r\n==include(page=\"template/preoni-2006/footer\")==',13,'protected',NULL,NULL),('preoni-2006/runda-2/clasament-11-12','Clasament preoni62c','2006-11-25 01:34:37','2006-11-25 01:34:37','h1. Clasament ==roundparam(round_id=\"preoni62c\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni62c\")==',961,'protected',NULL,NULL),('preoni-2004','Preoni 2004','2006-11-25 00:25:00','2006-11-25 00:30:13','h1. preONI 2004\r\n\r\nConcursul preONI 2004 s-a desfasurat in 2 zile avand ca principal scop pregatirea participantilor pentru olimpiada nationala de informatica ONI2004.\r\n\r\nFormatul concursului: 2 grupe (clasele IX-X, XI-XII), 3 probleme in fiecare grupa si un timp de lucru de 4h.\r\n\r\nh2. Runde\r\n\r\n* \"Ziua 1\":preoni-2004/runda-1 :Sambata, 27 martie, ora 16:00\r\n* \"Ziua 2\":preoni-2004/runda-2 :Duminica, 28 martie, ora 16:00\r\n\r\nh2. \"Clasament IX-X\":preoni-2004/clasament-9-10\r\n\r\nh2. \"Clasament XI-XII\":preoni-2004/clasament-11-12',961,'protected',NULL,NULL),('preoni-2004/clasament-9-10','Clasament preoni4a','2006-11-25 00:26:15','2006-11-25 00:27:18','h1.  Clasament global preONI 2004 (Clasele IX-X)\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni1|preoni3\")==',961,'protected',NULL,NULL),('preoni-2004/clasament-11-12','Clasament preoni4b','2006-11-25 00:28:17','2006-11-25 00:28:57','h1.  Clasament global preONI 2004 (Clasele XI-XII)\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2|preoni4\")==',961,'protected',NULL,NULL),('preoni-2004/runda-1','preONI 2004 (Runda 1)','2006-11-25 00:31:25','2006-11-25 03:08:19','h1. preONI 2004 (Runda 1)\r\n\r\nConcursul s-a desfasurat Sambata, 27 martie, ora 16:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nh2. Clasele 9-10 (\'Clasament\':preoni-2004/runda-1/clasament-9-10)\r\n\r\n!>preoni-2004/runda-1?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni1\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2004/runda-1/clasament-11-12)\r\n\r\n!>preoni-2004/runda-1?logo2.gif!\r\n\r\n== Tasks(round_id=\"preoni2\" pager_style=\"none\") ==',961,'protected',NULL,NULL),('preoni-2004/runda-2','preONI 2004 (Runda 2)','2006-11-25 00:34:23','2006-11-25 03:08:34','h1. preONI 2004 (Runda 2)\r\n\r\nConcursul s-a desfasurat Duminica, 28 martie, ora 16:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nh2. Clasele 9-10 (\'Clasament\':preoni-2004/runda-2/clasament-9-10)\r\n\r\n!>preoni-2004/runda-2?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni3\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2004/runda-2/clasament-11-12)\r\n\r\n!>preoni-2004/runda-2?logo2.gif!\r\n\r\n== Tasks(round_id=\"preoni4\" pager_style=\"none\") ==',961,'protected',NULL,NULL),('preoni-2004/runda-2/clasament-9-10','Clasament preoni42a','2006-11-25 00:36:19','2006-11-25 00:37:32','h1. Clasament ==roundparam(round_id=\"preoni3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni3\")==',961,'protected',NULL,NULL),('preoni-2004/runda-2/clasament-11-12','Clasament preoni42b','2006-11-25 00:37:13','2006-11-25 00:37:13','h1. Clasament ==roundparam(round_id=\"preoni4\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni4\")==',961,'protected',NULL,NULL),('preoni-2004/runda-1/clasament-11-12','Clasament preoni41b','2006-11-25 00:39:04','2006-11-25 00:39:04','h1. Clasament ==roundparam(round_id=\"preoni2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2\")==',961,'protected',NULL,NULL),('preoni-2004/runda-1/clasament-9-10','Clasament preoni41a','2006-11-25 00:39:13','2006-11-25 00:39:13','h1. Clasament ==roundparam(round_id=\"preoni1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni1\")==',961,'protected',NULL,NULL),('warm-up-2004/clasament-11-12','Clasament filip2','2006-11-23 21:08:52','2006-11-24 17:46:10','h1. Clasament ==roundparam(round_id=\"filip2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"filip2\")==',961,'protected',NULL,NULL),('warm-up-2004/clasament-9-10','Clasament filip1','2006-11-23 21:08:51','2006-11-24 17:45:54','h1. Clasament ==roundparam(round_id=\"filip1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"filip1\")==',961,'protected',NULL,NULL),('preoni-2006/runda-1/clasament-9','Clasament preoni61a','2006-11-25 01:17:19','2006-11-25 01:17:19','h1. Clasament ==roundparam(round_id=\"preoni61a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni61a\")==',961,'protected',NULL,NULL),('preoni-2006/finala/cronica','preoni-2006/finala/cronica','2006-11-23 23:28:15','2006-11-27 16:05:09','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Cronica preONI 2006, Runda Finala\r\n\r\n09:30 Incepe concursul.\r\n09:34 Dam drumu la a 9-a\r\n09:35 Intram pe Messenger\r\n09:40 Cosmin doarme, nu raspunde la intrebari\r\n09:41 Gheorghe Cosmin baga DivK, restul inca mai citesc\r\n09:42 Skipy baga PScNv, scrisese gresite out-ul\r\n09:43 Cosmin este online\r\n09:43 Tiseanu se joaca cu culorile in DJGPP , iar Marmotel codeaza de ceva vreme\r\n09:44 Marin Radu citeste Pedefe si isi freaca ingrozit capul\r\n09:44 Fluf e uimit de Marmotel care face in vim\r\n09:47 Exemeplul la Overlap e prost formamtat, ups\r\n09:48 Sobolanul face BF la PScNv\r\n09:50 Tataroiu a submitat DivK\r\n09:51 Cimi coloreaza grafuri (avem poza)\r\n09:53 Mort vine la laptop sa faca treaba\r\n\r\n10:00 Mort ii zice \"da\" lui Cosmin pentru a 8-a oara la aceeasi intrebare\r\n10:08 Pentru a 10-a oara, DA!\r\n10:10 Skipy inca nu a inteles `arbore`\r\n10:12 svn: strat.cristian@gmail.com: rsae now supports evaluation priority field per user\r\n10:15 Sobolanul nu stie sa se faca inteles\r\n10:17 Marin Radu si-a scos ciocolata\r\n10:20 gcosmin s-a prins de heap-uri\r\n10:21 varu nu se prinde la DivK\r\n10:35\r\nazotlichid: care esti acolo?\r\nbogdanpasoi: skipy si sobolanul\r\nbogdanpasoi: citim niste solutii\r\nbogdanpasoi: vrei sa-l chem pe mircea?\r\n10:39 Vladu, oripilat, il suna pe Mircea\r\nazotlichid: bhooooooot\r\n10:46 Tiseanu se plictiseste\r\n\r\n11:05 Emil Onea soseste (la timp) cu sandwiches\r\n11:18 Cosmin Gheorghe afla si intelege ce inseamna operatia de `translatie`\r\n11:19 Silviu si Marina se duc la baie\r\n11:20 Cezar Mocan salveaza Lupul_Ala_Mare.pas\r\n11:22 Tataroiu incepe sa rescrie DivK - brute force\r\n11:23 Silviu si Marina se intorc dupa numai 4 minute\r\n11:25 Soseste apa; Marin Radu fuge la baie\r\n11:28 Fluf si Marin Radu se intorc de la baie\r\n11:29 Tiseanu iar la baie.. heavy\r\n11:38 Varu il ia pe Fluf la baie .. Tiseanu a cam stat ceva\r\n11:40 Gata Varu. Sobolanu iar vrea la baie, dar Fluf il trece la loc\r\n11:43 Rapid Sobolanu.\r\n\r\n12:03 Toata lumea vrea la baie.\r\n12:12 gcosmin face calcule pentru complexitate la overlap.. ii da cam mult, iar Marmotel are probleme cu lupul\r\n12:13 Silviu citeste o carte (Maestrul si Margareta)\r\n12:15 Spatarel \"Terminate batch job ? (Y/N)\".. da nervos in tastatura si isi unduieste mustata )\r\n12:17 Cotizo cauta instructiuni de folosire la memcpy().. parca era cu pascalul el\r\n12:21 Adi isi face griji pentru Cimi.. how cute\r\n12:22 Ne uitam la Family Guy\r\n12:23 Fluf Senior si Fluf Junior (a.k.a Marmota) pleaca la baie\r\n12:28 S-au intors Flufii\r\n12:32 Marmotel face back la overlap iar varul inca scrie la DivK.. rupere\r\n12:42 Marin se balanseaza spre baie, ca un magnat\r\n12:45 Marin simte ca ia 100 la Pedefe\r\n12:59 Nimic nou.\r\n\r\n13:11 Cimi se uita dezamagita la Pedefe\r\n13:13 Fluf ii zambeste lu ala mic si-l duce la baie.. Super Adventure\r\n13:15 Facem tabel de feedback\r\n13:17 Suntem pe plus cu bugetul , in seara asta bem\r\n13:27 Suparat, suparat Tiseanu\r\n13:44 Sobolanul se uita la program, vrea sa vada la cat incepe teatrul si cand e premierea\r\n13:45 Sobolanul admira echipa infoarena in cautare de inspiratie\r\n13:46 Sobolanul isi cauta poza pe site\r\n13:46 Greco joaca Starship Seven iar Fluf se uita mirat la el\r\n13:47 Cristi spune ca probleme sunt prea simple, am dat banii degeaba\r\n13:47 Cristi se apuca sa implementeze problemele a la Chuck Norris\r\n13:48 Cristi ia 300\r\n13:58 Sobolanul se uita de 5 minute in monitorul de evaluare\r\n13:59 A venit admin-ul\r\n\r\n14:00 Marinei i s-a blocat.. programul\r\n14:05 Crapa Word-ul\r\n14:10 Sobolanul joaca carti si Adi mananca un mar\r\n14:11 Adi ii tine pumnii lui Cimi iar Tiseanu e stresat de timp\r\n14:12 A venit Corleone\r\n14:16 Tataroiu se roaga\r\n14:18 Chuck Norris trece la laptop\r\n14:18 Soarele apune \r\n',13,'public',NULL,NULL),('12-ponturi-pentru-programatorii-cc','12 ponturi pentru programatorii C/C++','2004-11-08 00:00:00','2009-02-19 23:48:07','h1. 12 ponturi pentru programatorii C/C++\r\n\r\n(Categoria _Limbaje de programare_, Autor _Alexandru Mosoi_)\r\n\r\nIn urmatoarele cateva randuri am sa incerc sa va arat cateva metode de a scrie.... mai bine. Cea mai mare parte este pentru programatorii C.\r\n\r\nInainte ati putea citi si \"Documentation/CodingStyle\" aflat in sursa de kernel a Linux-ului. Scuzati-ma daca ma inspir putin. Manualul gcc este si el binevenit.\r\n\r\n\r\nh2. Pont #0\r\n\r\nPrefer C in loc de C++: e mai robust putin ceea ce ma fereste cateodata de greseli. Incercati sa nu folositi un IDE cu debugging inclus (cum ar fi RHIDE sau Borland C++ 3.1). La inceput o sa va vina greu, dar va obisnuiti... si deveniti mai atenti cand scrieti surse. Puteti sa folositi Kate, un editor de text asemanator lui EditPlus de sub Windows. Vim este deasemenea un editor foarte puternic, dar pentru cine stie sa-l foloseasca.\r\n\r\nh2. Pont #1\r\n\r\nImpartiti programul dumneavoastra in functii, fiecare sa nu depaseasca mai mult de 30-50 de linii (aproximativ 2 ecrane ANSI 80x25). Este important sa aveti mereu o viziune asupra intregii functii. Regula este: complexitatea unei functii trebuie sa fie invers proportionala cu lungimea ei. Puteti sa declarati functiile \"inline\" (nu pe toate !) pentru a nu pierde din viteza.\r\n\r\nh2. Pont #2\r\n\r\nMacro-urile nu le recomand. Daca le folositi ca functii aveti grija. Unul dintre colegii mei de la lot a pierdut multe puncte pentru ceva asemanator.\r\n\r\n== code(cpp) |#define MAX(a, b) ((a) < (b) ? (b) : (a))\r\n\r\nint query(int a, int b)\r\n{\r\n    int k, l, r;\r\n    ...\r\n    res = MAX(k, query(l, r));\r\n    ....\r\n    return res;\r\n}\r\n==\r\n\r\nDaca observati, exista cazuri cand $query(l, r)$ era apelata de $2$ ori, ceea ce nu se doreste. In schimb, putea sa declare $MAX$ ca o functie inline.\r\n\r\n== code(cpp)|inline int MAX(int a, int b)\r\n{\r\n    if(a > b) \r\n        return a;\r\n    return b;\r\n}\r\n==\r\n\r\nh2. Pont #3\r\n\r\nCand accesati un element din memorie, procesorul citeste de fapt $32$ bytes (sau cat de mare e linia de cache, dar o putere a lui {$2$}). Recomand ca structurile voastre sa aiba de asemenea ca dimensiune o putere a lui $2$ pentru a nu forta procesorul sa citeasca de $2$ ori. O extensie GNU a standardului ANSI C sunt atributele. Pentru structuri, una din cele mai folosite (de mine) este packed ce instruieste compilatorul se nu mai adauge \"padding bytes\".\r\n\r\n== code(cpp) |struct foo { int a; char b; int c; };\r\n/* sizeof(struct foo) == 12 */\r\nstruct bla { int a; char b; int c; }\r\n\r\n__attribute__((packed));\r\n/* sizeof(struct bla) == 9 */\r\n==\r\n\r\nPentru mai multe informatii executati consultati manualul gcc. (\"info gcc\").\r\n\r\nDe asemenea, e bine sa nu spargeti aceasta line de cache prea des. Uitati un exemplu:\r\n\r\n== code(cpp) |#define maxN 1000\r\n#define maxM 1000\r\n\r\nint t[maxN][maxM];\r\n\r\nint f(void)\r\n{\r\n    int i, j;\r\n    int s = 0;\r\n    for(i = 0; i < maxM; ++ i)\r\n        for(j = 0; j < maxN; ++ j)\r\n            s += t[j][i];\r\n    return s;\r\n}\r\n==\r\n\r\nPentru $1024$ de apelari, pe calculatorul meu, acesta functie consuma cam {$18.85$}s. In schimb, daca as fi scris\r\n\r\n== code(cpp)|for(i = 0; i < maxN; ++ i)\r\n    for(j = 0; j < maxM; ++ j)\r\n        s += t[i][j];\r\n==\r\n\r\n... functia s-ar fi executat de ~{$3$} ori mai repede (doar {$6.05$}s) iar rezultatul era acelasi. De ce? pentru ca in primul caz la fiecare accesare a $t[j][i]$ procesorul era nevoit sa acceseze memoria, iar in cazul al doilea cand citea {$t[i][j]$}, erau citite de fapt si {$t[i][j+1]$}, {$t[i][j+2]$}, {$t[i][j+3]$}. Si sa nu uitam viteza memoriei este mult mai mica decat cea a procesorului.\r\n\r\nh2. Pont #4\r\n\r\nVariabilele globale sa nu fie folosite in scop local. Daca as modifica functia astfel\r\n\r\n== code(cpp) |int i, j;\r\n\r\nint f(void)\r\n{\r\n    int s = 0;\r\n    for(i = 0; i < maxM; ++ i)\r\n        for(j = 0; j < maxN; ++ j)\r\n            s += t[i][j];\r\n    return s;\r\n}\r\n==\r\n\r\n... timpul de executie s-ar fi marit la {$6.44$}s. Nu e prea mult... dar se aduna.\r\n\r\nh2. Pont #5\r\n\r\nStack-ul (locul unde se pastreaza toate variabilele locale) este foarte rapid. Modificam acelasi program astfel:\r\n\r\n== code(cpp) |#define maxN 1000\r\n#define maxM 1000\r\n\r\nint main(void)\r\n{\r\n    int i, j, k;\r\n    int N, M, t[maxN][maxM];\r\n    N = maxN; M = maxM;\r\n    for(k = 0; k < 1024; ++ k) {\r\n        int s;\r\n        for(i = 0; i < N; ++ i)\r\n            for(j = 0; j < M; ++ j)\r\n                s += t[i][j];\r\n    }\r\n    return 0;\r\n}\r\n==\r\n\r\nIgnorand faptul ca $t$ nu este initializat (e doar un program de test, nici inainte nu era :D) timpul de executie scade la {$1.2$}s, Wow! Insa aveti grija sa nu o luati pe urmele lui Silviu: {$sizeof(t)$} ~= {$4$}Mb care e mult peste limita de {$1$}Mb ce se impune de obicei in concursuri (si asta daca folositi gcc). Cel mai probabil veti primi \"Killed by signal 11\".\r\n\r\nh2. Pont #6\r\n\r\nh3. 6.a\r\n\r\n{$++i$} e preferabil {$i ++$} (unde nu complica lucrurile).\r\n\r\nh3. 6.b\r\n\r\nNu va feriti sa folositi \"{$const$}\" si \"{$static$}\". \"{$const$}\" chiar poate sa faca diferenta ca timp si vizibilitate.\r\n\r\nh3. 6.c\r\n\r\nUtilizati si literele mari pentru anumite variabile mai importante (poate si macro-uri).\r\n\r\nh2. Pont #7\r\n\r\nO alta extensie GNU sunt \"zero-length arrays\". Se folosesc in general la skiplist-uri pentru a declara un array de dimensiune variabila intr-o structura.\r\n\r\n== code(cpp) |typedef struct bla bla;\r\nstruct bla {\r\n    int levels;\r\n    bla *next[0];\r\n};\r\n...\r\nbla *temp = (bla *)malloc(sizeof(bla) + no_levels*sizeof(bla *));\r\n==\r\n\r\nh2. Pont #8\r\n\r\nh3. 8.a\r\n\r\nFolositi-va de utilitarele puse la dispozitie de sistemul de operare (linux in cazul meu). RTFM :)\r\n\r\n* $bc$ - pentru calcule cu numere cu precizie multipla (eg. {$2^1024^$}).\r\n* $octave$ - pentru calcule matematice mai complicate.\r\n* $gprof$ - determina cat timp a necesitat executia fiecarei functii sau linii.\r\n* $gcov$ - determina de cateori a fost apelata o anumita linie.\r\n* $time$ - pentru aflarea timpului executiei unui program.\r\n* $factor$ - descompune in factori un numar (eg. factor {$666$}).\r\n* $splint$ - o versiune free a programului lint: va da foarte multe warning-uri.\r\n* $bash$ - putin scripting\r\n\r\nh3. 8.b\r\n\r\nCompilati-va sursele cu {$-W -Wall$} (tot pentru warning-uri)\r\n\r\nh3. 8.c\r\n\r\nGeneratorul de teste si sursa dumneavoastra trebuie sa fie doua programe diferite !\r\n\r\nh3. 8.d\r\n\r\nPentru debugging folositi {$fprintf(stderr, ...)$}. Daca se intampla sa uitati, macar nu primiti \"wrong answer\" din cauza unui {$printf$}.\r\n\r\nh2. Pont #9\r\n\r\nh3. 9.a\r\n\r\n== code(cpp)|int t[666];\r\n/* toate elementele lui t vor fi -1 */\r\nmemset(t, 0xff, sizeof(t));\r\n==\r\n\r\nh3. 9.b\r\n\r\nPentru valoarea infinit folosesc o constanta\r\n\r\n== code(cpp)|#define INFI 0x3f3f3f3f\r\n==\r\n\r\ndin mai multe motive:\r\n\r\n* $INFI + INFI$ ramane pozitiv\r\n* in general e destul de mare\r\n\r\n== code(cpp)|/* toate elementele lui t devin INFI */\r\nmemset(t, 0x3f, sizeof(t));\r\n==\r\n\r\nh3. 9.c\r\n\r\nDaca avem de comparat doua siruri ({$s{~1~}, s{~2~}$}) a caror lungime o stim ({$len_s{~1~}$}, respectiv {$len_s{~2~}$}) este mai rapid\r\n\r\n== code(cpp) |memcmp(s1, s2, MIN(len_s1, len_s2)+1)\r\n==\r\n\r\ndecat\r\n\r\n== code(cpp) |strcmp(s1, s2);\r\n==\r\n\r\nh3. 9.d\r\n\r\n== code(cpp)|scanf(\" %c\", &ch)\r\n==\r\n\r\nciteste primul caracter dupa spatiile albe (daca exista).\r\n\r\n\r\n\r\nh2. Pont #10\r\n\r\nDaca programati in C++ fara sa folositi STL incercati sa renuntati la C++. Unul dintre motive: clasele (implicit iostream: cin, cout, cerr) incetinesc mult executia programului.\r\n\r\nh2. Pont #11\r\n\r\nIn final, o intrebare pentru cei ce folosesc C++ (asta e un hint). Cum se calculeaza factorial la compilare? (fara a scrie efectiv {$1*2*3...*n$})\r\nRaspuns: Utilizand templaturi. Avem nevoie doar de o constanta {$N$}.\r\n\r\n== code(cpp) |#include <stdio.h>\r\n\r\ntemplate<int N>\r\nstruct Factorial {\r\n    enum {\r\n        value = Factorial<N-1>::value * N\r\n    };\r\n};\r\n\r\ntemplate<>\r\nstruct Factorial<0> {\r\n    enum { value = 1 };\r\n};\r\n\r\nint main(void)\r\n{\r\n    int i = Factorial<4>::value;\r\n    char c[Factorial<5>::value];\r\n    printf(\"%d \",i);\r\n    printf(\"%d \",sizeof(c));\r\n}\r\n==\r\n\r\nPS: nu dau $2.56 pentru fiecare greseala descoperita in acest articol.\r\n',2044,'public',3674,NULL),('preoni-2006/runda-1/clasament-10','Clasament preoni61b','2006-11-25 01:17:13','2006-11-25 01:17:13','h1. Clasament ==roundparam(round_id=\"preoni61b\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni61b\")==',961,'protected',NULL,NULL),('preoji-2004/clasament-11-12','Clasament preOJI 2004, clasele 11-12','2006-11-23 21:08:49','2006-11-24 17:48:27','h1. Clasament \'preOJI 2004\':preoji-2004, clasele 11-12\r\n\r\n==Rankings(rounds = \"preoji2\")==',961,'protected',NULL,NULL),('template/trimite-solutii','template/trimite-solutii','2006-11-27 05:42:46','2006-11-27 06:05:06','h2. Evaluatorul infoarena\r\n\r\n\"Afla detalii despre evaluator\":documentatie/evaluator: cum functioneaza, ce versiuni de compilatoare folosim, parametri de compilare, memorie disponibila, configuratie hardware etc.\r\n\r\nh2. Ceva nu functioneaza?\r\n\r\n* Citeste din \"ghidul utilizatorului\":documentatie/trimiterea-solutiilor.\r\n* Daca tot nu e bine, ==SmfLink(caption=\"contacteaza-ne pe forum\" link=\"board\" board=\"33\")==!',13,'protected',NULL,NULL),('template/login','template/login','2006-11-27 05:56:40','2006-12-04 01:56:03','h2. Ceva nu functioneaza?\r\n\r\n* Mai intai citeste pagina cu \"*probleme frecvente la autentificare*\":documentatie/probleme-frecvente-la-autentificare.\r\n* Daca tot nu e bine, ==SmfLink(caption=\"contacteaza-ne pe forum\" link=\"board\" board=\"33\")==!',13,'protected',NULL,NULL),('template/resetarea-parolei','template/resetarea-parolei','2006-11-27 06:06:06','2006-11-27 06:08:35','h2. Ceva nu functioneaza?\r\n\r\n* ==SmfLink(caption=\"Contacteaza-ne pe forum\" link=\"board\" board=\"33\")==',13,'protected',NULL,NULL),('template/borderou','template/borderou','2006-11-27 06:20:43','2006-12-29 14:50:35','h2. Ceva nu functioneaza?\r\n\r\n* Citeste despre \"borderoul de evaluare\":documentatie/borderoul-de-evaluare.\r\n* Daca tot nu e bine, ==SmfLink(caption=\"contacteaza-ne pe forum\" link=\"board\" board=\"33\")== !\r\n',1142,'protected',NULL,NULL),('favicon.ico','favicon.ico','2006-11-28 00:00:22','2006-12-01 19:07:01','000001111',1858,'public',NULL,NULL),('template/userinfo/header','Informatii despre %user_id%','2006-11-28 02:10:50','2006-11-28 02:10:50','table(compact). |/4. !utilizator/%user_id%?avatar 150x150! |_. Nume | == userinfo(user=\"%user_id%\" info=\"fullname\")== |\r\n| |_. Cont infoarena | == userinfo(user=\"%user_id%\" info=\"username\")== |\r\n| |_. Statut infoarena | == userinfo(user=\"%user_id%\" info=\"security\")== |\r\n|_. Forum | ==SmfLink(user=\"%user_id%\" link=\"pm\" caption=\"trimite mesaj privat\")==, ==SmfLink(user=\"%user_id%\" link=\"stats\" caption=\"vezi activitate\")== |\r\n',1142,'public',NULL,NULL),('template/userinfo/main','Informatii despre %user_id%','2006-11-28 02:14:47','2006-11-28 02:14:47','h1. == userinfo(user=\"%user_id%\" info=\"fullname\") ==\r\n\r\n== include(page=\"template/userinfo\" user_id=\"%user_id%\") ==\r\n\r\n== include(page=\"template/userstats\" user_id=\"%user_id%\") ==\r\n\r\nVezi si \'profilul personalizat\':utilizator/%user_id% al acestui user.',1142,'protected',NULL,NULL),('preoni-2006/clasament','Clasament, preONI 2006','2006-11-25 03:57:02','2006-12-01 18:11:55','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Clasament preONI 2006\r\n\r\nh2. Rundele online\r\n\r\n* \'Clasament clasa a 9-a (si gimnaziu)\':preoni-2006/clasament-9\r\n* \'Clasament clasa a 10-a\':preoni-2006/clasament-10\r\n* \'Clasament clasele 11-12\':preoni-2006/clasament-11-12\r\n\r\nh2. Runda finala\r\n\r\n* \'Clasament clasa a 9-a (si gimnaziu)\':preoni-2006/finala/clasament-9\r\n* \'Clasament clasa a 10-a\':preoni-2006/finala/clasament-10\r\n* \'Clasament clasele 11-12\':preoni-2006/finala/clasament-11-12\r\n',13,'protected',NULL,NULL),('preoni-2006/finala/clasament-9','Clasament Finala preONI 2006, Clasa a IX-a si gimnaziu','2006-11-23 21:08:59','2006-12-01 18:14:52','== include(page=\"template/preoni-2006/finalrankings\") ==\r\n\r\nh2. Clasa a IX-a si gimnaziu\r\n\r\n==Rankings(rounds = \"preoni65a\")==',13,'protected',NULL,NULL),('preoni-2006/finala/clasament-11-12','Clasament Finala preONI 2006, Clasele XI-XII','2006-11-23 21:09:00','2006-12-01 18:16:17','== include(page=\"template/preoni-2006/finalrankings\") ==\r\n\r\nh2. Clasele XI-XII\r\n\r\n==Rankings(rounds = \"preoni65c\")==',13,'protected',NULL,NULL),('template/preoni-2006/finalrankings','template/preoni-2006/finalrankings','2006-12-01 18:10:32','2006-12-01 18:15:33','==include(page=\"template/preoni-2006/header\")==\r\n\r\np{font-weight: bold}. &larr; \"preONI 2006 Homepage\":preoni-2006\r\n\r\nh1. Clasament Finala preONI 2006\r\n\r\np={font-weight: bold}. \"Clasa a IX-a si gimnaziu\":preoni-2006/finala/clasament-9 | \"Clasa a X-a \":preoni-2006/finala/clasament-10 | \"Clasele XI-XII\":preoni-2006/finala/clasament-11-12\r\n\r\n',13,'protected',NULL,NULL),('template/raw','template/raw','2006-11-11 11:25:13','2006-11-11 20:49:09','{color:red}|_=. Aceasta pagina a fost importata din infoarena1 si nu este inca prelucrata. \r\nSterge @==Include(file=\"template/raw\")==@ cand esti multumit cu continutul paginii.|',15,'protected',NULL,NULL),('runda/preoni2007_runda3_9','runda/preoni2007_runda3_9','2007-03-02 18:09:27','2007-03-02 18:09:27','begin\r\n   writeln (\'Salutare lume pt toti iubitori de anime\');\r\nend',5889,'public',NULL,NULL),('ciclu-hamiltonian-in-graf-dens','Ciclu hamiltonian in graf dens','2004-11-09 00:00:00','2009-02-20 00:52:02','h1. Ciclu hamiltonian in graf dens\r\n\r\n(Categoria _Algoritmi_, Autor _Leonard Crestez_)\r\n\r\nIn acest articol va voi prezenta un algoritm pentru gasirea unui ciclu hamiltonian intr-un graf neorientat dens - in care fiecare nod are macar $(N + 1) / 2$ muchii.\r\n\r\nIn general, gasirea unui ciclu hamiltonian intr-un graf neorientat este un exemplu clasic de problema NP - completa. Insa, daca graful este dens - fiecare nod are cel putin $(N+1) / 2$ muchii incidente ({$N$} este numarul de noduri) - se poate gasi o solutie de complexitate {$O(N^2^)$}.\r\n\r\nh2. Algoritm\r\n\r\nLa inceput formam un ciclu la intamplare, fara a tine cont daca muchiile luate in considerare chiar exista in graf. Astfel, putem alege chiar ciclul {$1, 2, 3, 4, ... N$}. Daca acest ciclu este valid, atunci avem noroc si solutia a fost gasita. Altfel, trebuie sa incercam sa \"umplem gaurile\" din ciclu (adica muchiile pe care le-am ales la intamplare si care nu exista in graf).\r\n\r\nGasim prima muchie de acest fel, fie ea ({$A, B$}). Cautam apoi doua alte noduri adiacente in ciclul nostru, notate cu $C$ si {$D$}, astfel incat sa avem muchie de la $A$ la $C$ si de la $B$ la {$D$}. Se poate demonstra ca vom gasi mereu $C$ si {$D$}. Acum vom \"incrucisa\" $A B$ cu {$C D$}. Prin \"incrucisare\" se intelege transfromarea unui ciclu $...AB...CD...$ in $...AC...BD...$ (sau $...CD...AB...$ in $...CA...DB...$) . Atentie, secventa de la $B$ la $C$ (respectiv de la $D$ la {$A$}) va fi inversata complet!\r\n\r\nSe observa ca a scazut numarul de \"gauri\" din sir, $AB$ a fost eliminata si nu au fost adaugate \"gauri\" noi. Repetam \"umplerea gaurilor\" pana nu mai avem ce umple, deci am gasit solutie.\r\n\r\nDesi suna complicat, \"umplerea unei gauri\" necesita doar $O(N)$ timp pentru cautarea nodurile {$AB$}, {$CD$}, si incrucisare. Avand in vedere ca sunt maxim $N$ gauri la inceput, algoritmul necesita $O(N^2^)$ ca timp de executie.\r\n\r\nMai sus am folosit o afirmatie fara a o demonstra. Demonstratia e relativ intuitiva. Daca nu o descoperiti singuri, puteti sa intrebati pe \"forum\":http://infoarena.ro/forum.\r\n\r\nProblema luata in discutie este propusa pe lista \"sgu\":http://acm.sgu.ru/, nr. \"122\":http://acm.sgu.ru/problem.php?contest=0&problem=122, unde exista si evaluator online. Atentie la implementare! Citirea si scrierea folosind functii standard pot iesi din timp!\r\n\r\n',2044,'public',3693,NULL),('blog/rezultate-ioi-2004','Rezultate IOI 2004','2004-11-10 00:00:00','2004-11-10 00:00:00','h1. Rezultate IOI 2004\r\n\r\n\"IOI 2004\":http://www.ioi2004.org/ - a 16-a editie a Olimpiadei Internationale de Informatica s-a desfasurat la Atena, Grecia, in perioada 11-18 septembrie.\r\n\r\nIn cadrul acestei competitii, lotul roman a fost insotit de:\r\n\r\n* Prof. Emanuela Cerchez\r\n* Prof. Ovidiu Domsa\r\n\r\nh2. Medalii\r\n\r\n* Ganceanu Silviu Ionut, aur\r\n* Crestez Dan-Leonard, argint\r\n* Vladu Adrian, argint\r\n* Stancu-Mara Sorin, bronz\r\n\r\nIi felicitam pe ei si pe toti cei ce s-au implicat si se implica in continuare in pregatirea lor.',1142,'protected',NULL,NULL),('preoni-2006','preONI 2006','2006-11-22 23:02:20','2008-02-14 15:57:04','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. preONI 2006\r\n\r\n*Editia 2006 a concursului preONI s-a incheiat cu succes la Focsani in perioada 24-26 martie!*\r\nFinala a fost ... \"Super. Super\", \"Super tare\", \"mda...a mers\" o spun concurentii. A fost grozav, intr-adevar, si ne-a facut mare placere sa va vedem prezenti intr-un numar atat de mare si veniti atat de departe. Va multumim pentru participare si speram ca ati petrecut un week-end pe cinste cu noi la Focsani. Toata echipa infoarena merita felicitata pentru organizarea si efortul depus de-a lungul campaniei. Inca odata multimim domnului profesor Onea pentru organizarea \"fara cusur\".\r\n\r\np={font-weight: bold}. \"Cronica\":preoni-2006/finala/cronica | \"Feedback\":preoni-2006/finala/feedback | \"Poze!\":preoni-2006/finala/poze\r\n\r\nh2. Noutati\r\n\r\nSponsorii finalei sunt:\r\n\r\n\"!preoni-2006?oracle_ro.gif!\":http://www.oracle.com/global/ro/index.html\r\n\r\n\"Colegiul National Unirea, Focsani\":http://cnu.lufo.ro/\r\n\r\n*Hotel Unirea, Focsani*\r\n\r\nViziteaza \"Pagina rundei finale\":preoni-2006/finala.\r\n\r\nh2. preONI 2006 pe scurt\r\n\r\nConcursul este destinat elevilor de liceu ce se pregatesc pentru competitii de informatica (in special ONI).\r\n\r\npreONI 2006 este impartit pe 3 grupe (Clasa a 9-a si gimnaziu, Clasa a 10-a, Clasele 11-12), iar concurentii vor avea de rezolvat 3 probleme in 4 ore. Primele 4 runde online se vor desfasura in zile de sambata, incepand de la ora 09:00, iar in urma acestora cei mai buni de la fiecare grupa vor participa la o runda finala care se va desfasura intr-o \"tabara\":preoni-2006/finala, la sfarsit acordandu-se \"premii\":preoni-2006/premii. In continuare veti gasi un tabel cu datele provizorii ale rundelor: \r\n\r\n|_. Runda|_. Data|_. Pagina cu detalii|\r\n|#1|19 noiembrie 2005|\"Runda 1 preONI 2006\":preoni-2006/runda-1|\r\n|#2|17 decembrie 2005|\"Runda 2 preONI 2006\":preoni-2006/runda-2|\r\n|#3|21 ianuarie 2006|\"Runda 3 preONI 2006\":preoni-2006/runda-3|\r\n|#4|19 februarie 2006|\"Runda 4 preONI 2006\":preoni-2006/runda-4|\r\n|Finala|24 - 26 martie 2006|\"Runda finala (Focsani)\":preoni-2006/finala|\r\n\r\n\r\n==include(page=\"template/preoni-2006/footer\")==',1,'public',NULL,NULL),('template/preoni-2006/footer','template/preoni-2006/footer','2006-11-27 16:13:42','2008-10-12 20:43:50','h2. Sponsori\r\n\r\n\"!preoni-2006?softwin.gif!\":http://www.softwin.ro/ \"!preoni-2006?microsoft.jpg!\":http://www.microsoft.com/romania/ \"!preoni-2006?totalsoft.gif!\":http://www.totalsoft.ro/\r\n',1490,'protected',NULL,NULL),('blog/rezultate-ceoi-2004','Rezultate CEOI 2004','2004-11-09 00:00:00','2004-11-09 00:00:00','h1. Rezultate CEOI 2004\r\n\r\nCEOI 2004 s-a incheiat. Lotul olimpic roman a obtinut rezultate remarcabile aducand acasa nu mai putin de 4 medalii.\r\n\r\nRomania a fost reprezentata de:\r\n\r\n* Prof. insotitor Stelian Ciurea\r\n* Prof. insotitor Doru Anastasiu Popescu\r\n* Mircea Digulescu\r\n* Mosoi Alexandru\r\n* Dan-Constantin Spatarel\r\n* Stancu Mara Sorin\r\n\r\nh2. Medalii\r\n\r\n* Argint - Mosoi Alexandru\r\n* Argint - Spatarel Dan-Constantin\r\n* Bronz - Stancu Mara Sorin\r\n* Bronz - Digulescu Mircea',1142,'protected',NULL,NULL),('blog/rezultate-boi-2004','Rezultate BOI 2004','2004-11-08 00:00:00','2004-11-08 00:00:00','h1. Rezultate BOI 2004\r\n\r\n\"BOI 2004\":http://www.boi2004-plovdiv.org/ - a 12-a editie a Olimpiadei Balcanice de Informatica s-a desfasurat in Plovdiv, Bulgaria, in perioada 3-9 iulie.\r\n\r\nIn cadrul acestei competitii, lotul roman a fost format din :\r\n\r\n* Prof. Marinel Serban\r\n* Prof. Daniel Popa\r\n* Adrian Vladu\r\n* Mircea Pasoi\r\n* Silviu Ganceanu\r\n* Marius Dumitran\r\n\r\nEchipa noastra a obtinut 3 medalii:\r\n\r\n* Pasoi Mircea, argint\r\n* Vladu Adrian, bronz\r\n* Ganceanu Silviu, bronz\r\n\r\nIi felicitam pe ei si pe toti cei ce s-au implicat si se implica in continuare in pregatirea lor.\r\n\r\n',1142,'protected',NULL,NULL),('template/userstats','template/userstats','2006-11-26 22:39:30','2006-12-08 04:29:55','h2. Statistici pentru %user%\r\n\r\nh3. Probleme rezolvate\r\n\r\n==SolvedTasks(user=\"%user%\")==\r\n\r\nh3. Probleme incercate\r\n\r\n==FailedTasks(user=\"%user%\")==\r\n\r\nh3. Participant la&hellip;\r\n\r\n==Rounds(user=\"%user%\")==',13,'protected',NULL,NULL),('blog/lansare-portal-info.devnet.ro','Lansare portal info.devNet!','2004-11-11 00:00:00','2004-11-11 00:00:00','h1. Lansare portal info.devNet!\r\n\r\ninfo.devNet este un portal de informatica dedicat tuturor celor pasionati de acest domeniu. Portalul prezinta articole despre algoritmi, structuri de date, limbaje de programare, probleme si competitii de informatica, o lista comprehensiva de resurse web, downloads si sustine o comunitate activa formata, in special, din elevi si studenti, fosti sau actuali olimpici la informatica.\r\n\r\nScopul acestui portal este de a oferi elevilor si studentilor ce se pregatesc pentru competitii de informatica acces usor si rapid la materiale valoroase de pregatire, de a-i tine la curent cu ultimele noutati legate de acest domeniu si de a facilita comunicarea intre acestia.\r\n\r\nMaterialele prezente pe acest site sunt scrise 100% prin voluntariat de catre fosti sau actuali olimpici la informatica. Unii dintre ei au fost medaliati la competii internationale, altii au fost selectionati in lotul national de informatica sau au castigat locuri fruntase la ONI. Indiferent de autor, vom incerca sa verificam si sa imbunatatim constant articolele publicate. Incurajam din plin discutiile, comentariile si sugestiile pe marginea lor in cadrul \"forumului\":http://forum.infoarena.ro/.\r\n\r\nIi rugam pe cei care doresc sa contribuie la construirea acestui \"knowledge-base\" sa ne contacteze prin intermediul forumului!\r\n\r\n',1142,'protected',NULL,NULL),('warm-up-2004/solutii','Solutiile oficiale pentru Concursul \"de incalzire\"','2004-11-15 00:00:00','2007-10-09 13:16:27','h1. Solutiile oficiale pentru Concursul \"de incalzire\"\r\n\r\n(Categoria _Competitii_, autor(i) _Mircea Pasoi_)\r\n\r\nIn acest articol voi prezenta cateva idei de rezolvare pentru problemele din concursul \"de incalzire\" de la clasele 9-10 si 11-12.\r\n\r\nIncep prin a recunoaste faptul ca setul de probleme a fost unul foarte dur, comparabil cu unul de la nationale, chiar baraje. Pe viitor vom incerca sa facem concursurile mai gradate. Reversul medaliei este ca aveti acum probleme dure cu care sa va pregatiti si la care voi prezenta idei de solutie avand astfel ce invata! Nu voi incerca sa dau solutii foarte explicite, ci doar voi schita ideile de baza deoarece este important sa incercati sa intelegi si sa implementati singuri solutiile! ;)\r\n\r\nh2. Clasele 9-10\r\n\r\nh3. **Coins**\r\n\r\nPrimul fapt care trebuie observat este numarul destul de mic al starilor de joc si anume {$2^22^ = 4.194.304$}. Recomand \"cartea doamnei Cerchez\":http://www.liis.ro/%7eema/ despre arbori pentru a citi capitolul despre Arbori de Joc. Ideea principala este ca se exploreaza intregul arbore de joc format de starile tablei de $22$ de patralele si se retine intr-un vector boolean pentru fiecare configuratie daca jucatorul care incepe cu acea configuratie castiga sau nu. Astfel, se va raspunde la fiecare din cele $N$ teste in $O(1)$ dupa preprocesarea in $O(22 * 2^22^) = O(1)$ :).\r\n\r\nh3. **Zaharel**\r\n\r\nSolutia se bazeaza pe proprietatea foarte importanta (subliniata si in enunt) ca pe fiecare linie exista un punct rosu si pe fiecare coloana un punct albastru. Presupunem ca tinem o lista cu puncte. Initial bagam un punct rosu oarecare. Pe coloana punctului rosu respectiv exista un punct albastru (din proprietatea de mai sus). Inseram acel punct albastru in lista. Pe linia punctul albastru va exista un punct rosu , pe care il vom insera in lista. Repetand acest procedeu vom ajunge la un moment dat la un punct care a mai fost in lista ,deci la un ciclu (acest lucru este evident deoarece numarul punctelor este finit). Punctele rosii de pe ciclu vor reprezenta primul poligon, iar punctele albastre al doilea poligon. Este evident ca vor avea acelasi numar de varfuri, vom arata in continuare ca au si acelasi centru de greutate. Fie primul punct (acela rosu) ({$x{~1~}, y{~1~}$}). Al doilea va fi ({$x{~2~}, y{~1~}$}), al treilea ({$x{~2~}, y{~2~}$}), al patrulea ({$x{~3~}, y{~2~}$}) .. penultimul ({$x{~k~}, y{~k-1~}$}), ultimul ({$x{~k~}, y{~k~}$}) (care va coincide cu un alt punct ({$x{~p~}, y{~p~}$}), {$p < k$}). Se observa ca poligonul rosu va avea ca centru de greutate punctul ({$(x{~p~}&#0043;x{~p+1~}&#0043;...&#0043;x{~k-1~})/(k-p)$}, {$(y{~p~}&#0043;y{~p+1~}&#0043;...&#0043;y{~k-1~})/(k-p)$}), iar cel albastru {$(x{~p+1~}&#0043;x{~p+2~}&#0043;...&#0043;x{~k~})/(k-p)$}, {$(y{~p+1~}&#0043;y{~p+2~}&#0043;...&#0043;y{~k~})/(k-p)$}), care coincid deoarece ({$x{~p~},y{~p~}$}) = ({$x{~k~}, y{~k~}$}).\r\n\r\nh3. **Sobo**\r\n\r\nProblema se rezolva prin programare dinamica. Se retine in $A{~i~}$ = costul minim in cazul cel mai defavorabil pentru a recunoaste sobolanul inteligent din multimea de sobolani cu numerele de ordine pozitiile bitilor de $1$ in reprezentarea binara a lui {$i$}. Astfel, $A$ va avea valori pentru $i$ intre $0$ si {$2^N^-1$}. Raspunsul va fi {$A{~2^N^-1~}$}. Este evident ca graful format de aceste stari este aciclic deoarece fiecare raspuns imparte o multime in doua multimi mai mici. Astfel pentru a calcula un $A{~i~}$ vom lua fiecare raspuns care imparte in doua multimi nevide multimea curenta, vom vedea in care multime costul este mai mare (cazul cel mai defavorabil) , adaugam pretul raspunsului si actualizam in $A{~i~}$ daca valoarea aceasta este mai mica decat cea curenta (sa nu uitam ca vrem cost minim in cazul cel mai defavorabil). Cea mai simpla metoda de a implementa acest mecanism este cu memoizare. Complexitatea finala {$O(2^N^ * L * N)$}. Se poate optimiza la {$O(2^N^ * L)$} folosind operatii pe biti.\r\n\r\n\r\n\r\nh2. Clasele 11-12\r\n\r\nh3. **Xor Max**\r\n\r\nFie {$X{~i~} = A{~1~} xor A{~2~} xor ... xor A{~i~}$}. Pentru fiecare $X{~i~}$ vom incearca sa gasim un $X{~j~}$ ({$j < i$}) astfel incat $X{~i~} xor X{~j~}$ sa fie maxim. Pentru a realiza aceasta operatie eficient vom mentine un *trie* (vezi in CLR varianta in romana la pagina 223 - capitolul \"Arbori binari de cautare\" problema 13-2 - se asemana cu \"suffix trees/tries\" doar ca vom lucra cu siruri binare). Fie $b$ numarul maxim de biti pe care ii are un element din vector. Vom realiza operatia de gasire a lui $X{~j~}$ in {$O(b)$}. Structura de date mentionata mai sus va memora sirurile de biti formate de vectorul {$X$}. Vom parcurge bitii lui $X{~i~}$ de la cel mai semnificativ la cel mai nesemnificativ. Astfel daca bitul curent este {$1$}, vom incerca sa gasim un sir de biti care are acest bit $0$ (pentru a maxima xor-ul), iar daca bitul curent este $0$ vom proceda invers. Complexitatea finala a algoritmului este {$O(N*b)$}.\r\n\r\nh3. **Boom**\r\n\r\nVom construi un graf din cele $2^N^$ stari posibile. Prin stare intelegem un numar binar in care bitii de $1$ reprezinta locurile in care s-ar putea afla sobolanul. Pentru fiecare astfel de nod, exista $M$ muchii la alte noduri, care se obtin aplicand bomba asupra pozitiilor si avansarea pozitiilor ramase. Deoarece muchiile au costuri numere naturale, iar graful nu este neaparat aciclic vom aplica algoritmul Dijkstra, pentru a determina drumul de cost minim de la nodul $2^N^-1$ la nodul {$0$}. Pentru a se incadra in timp era necesara implementarea cozii de prioritate cu heap-uri. Complexitate finala {$O(2^N^ * N * M)$}.\r\n\r\nh3. **PetSoft**\r\n\r\nIn fiecare nod din arbore vom retine doua valori $A{~i, 0~}$ = costul maxim pentru a cupla subarborele cu radacina in {$i$}, fara a cupla nodul $i$ cu cineva, si $A{~i, 1~}$ acelasi lucru, dar cupland nodul $i$ cu cineva. Pentru a calcula aceste valori in fiecare nod, luam numerele de ordine a fiilor, le sortam si aplicam o alta dinamica pentru a obtine echipe cu cost maxim. Astfel determinam {$A{~i, 0~}$}. Pentru a calcula {$A{~i, 1~}$}, inseram si nodul $i$ in lista fiilor, sortam din nou si aplicam aceeasi dinamica (atentie la detalii de implementare!). Dinamica se face astfel: retinem in $C{~i, j~}$ = costul maxim pentru a forma echipe de cost maxim cu valorile de pe pozitiile {$i, i+1 ... j-1, j$}. Este evident ca $C{~i, j~}$ se obtine din {$C{~i+1, j~}$}, $C{~i, j-1~}$ si {$C{~i+1, j-1~}$}. Complexitatea finala este {$O(N^2^)$}.\r\n\r\n',1231,'public',NULL,NULL),('algoritmul-lui-euclid','Algoritmul lui Euclid','2004-11-16 00:00:00','2009-02-20 00:06:26','h1. Algoritmul lui Euclid\r\n\r\n(Categoria _Matematica_, Autor _Leonard Crestez_)\r\n\r\nO prezentare a variantei extinse a algoritmului lui Euclid, care rezolva ecuatie de forma {$A * X + B * Y = D$}, unde $D$ este cel mai mare divizor comun al lui $A$ si {$B$}. De asemenea este prezentata o aplicatie \"interesanta\": impartirea modulara.\r\n\r\nProbabil ca multi stiti algoritmul lui Euclid de prin clasa a 5-a, cand invatati la matematica divizibilitate. Varianta simplista a algoritmului lui Euclid este cunoscuta de multa lume, dar fara prea multe explicatii despre functionarea lui.\r\n\r\nh2. Euclid simplu\r\n\r\nIn cuvinte, algoritmul pur si simplu imparte deimpartitul la rest pana cand impartitorul este {$0$}, apoi returneaza deimpartitul. Poate fi usor implementat iterativ in C. Probabil ca aceasta forma este si cea mai rapida, si este de preferat cand nu e necesar Euclid extins.\r\n\r\n== code(c) | int euclid(int a, int b)\r\n{\r\n    int c;\r\n    while (b) {\r\n        c = a % b;\r\n        a = b;\r\n        b = c;\r\n    }\r\n    return a;\r\n}\r\n==\r\n\r\nPentru a fi inteles mai usor si eventual extins, este mai bine sa il punem sub forma recursiva\r\n\r\n== code(c) | void euclid(int a, int b, int *d)\r\n{\r\n    if (b == 0) {\r\n        *d = a;\r\n    } else\r\n        euclid(b, a % b, d);\r\n}\r\n==\r\n\r\nSa vedem cum functioneaza algoritmul lui Euclid. Se observa ca daca {$a<b$}, atunci $euclid(b, a % b)$ este de fapt {$euclid(b, a)$}.\r\n\r\nVom demonstra ca {$cmmdc(a, b) = cmmdc(b, a % b)$}. Notam $cmmdc(a, b)$ cu {$d$}. Scriem $a%b$ drept {$a - b * c$}, unde $c$ este parte intreaga din {$a / b$}. Cum $a$ si $b$ sunt divizibile cu {$d$}, atunci orice combinatie liniara a lor este divizibila cu {$d$}, inclusiv {$a - b * c = a%b$}.\r\nAsta insa nu este de ajuns, putem aveam {$Z > d$}, $Z$ divizibil cu {$d$}, care sa fie {$cmmdc(b, a % b)$}. Insa atunci ar rezulta similar ca a e divizibil cu {$Z$}, deci {$Z = d = cmmdc(a, b)$}, Incalcand {$Z > d$}.\r\n\r\nAstfel, algoritmul lucreaza reducand problema la numere din ce in ce mai mici, pana cand {$a % b = 0$}. Ca sa finalizam recurenta, daca $a$ este divizibil cu {$b$}, atunci este evident ca {$cmmdc(a, b)$} este {$b$}. In cod este un pic mai \"ciudat\", prindem acest caz doar dupa inca un apel recurent, cand {$b = 0$}. De fapt cred ca $cmmdc$ este definit pe numere strict pozitive, dar in informatica putem ocoli un pic matematica.\r\n\r\nh2. Euclid extins\r\n\r\nAcest algoritm poate fi extins, in sensul gasirii $x$ si $y$ astfel incat {$a * x + b * y = d$}. In acest articol vom incerca sa deducem modul de calculare al lui $x$ si {$y$}. Cei grabiti sau certati cu matematica pot sari direct la codul sursa, dar vor avea probleme in a tine minte algoritmul pe viitor.\r\n\r\nVom extinde procedura recursiva de calculare a $cmmdc$ pentru a include si $x$ si {$y$}. Calculam $x$ si $y$ incepand de la \"capatul recurentei\". Daca {$b = 0$}, atunci $a * 1 + b * 0 = a(cmmdc)$ evident, asa ca initial $x = 1$ si {$y = 0$}. Incercam sa calculam {$x$}, $y$ in functie de {$x0$}, $y0$ obtinuti pentru {$b$}, {$a % b$}. Noi stim urmatoarele:\r\n\r\n* $b * x0 + (a % b) * y0 = d$\r\n* $a * x + b * y = d$\r\n\r\nTrebuie sa aflam o solutie pentru $x$ si {$y$}. Vom nota ca mai sus parte intreaga din $a / b$ cu {$c$}.\r\n\r\n* $b * x0 + (a - b * c) * y0 = a * x + b * y$\r\n* $b * (x0 - c * y0 - y) = a * (x - y0)$\r\n\r\nO solutie este acum evidenta (Una, sunt o infinitate de perechi {$x, y$})\r\n\r\n* {$x0 - c * y0 - y = 0$}, De unde rezulta $y = x0 - c * y0$\r\n* {$x - y0 = 0$}, De unde rezulta $x = y0$\r\n\r\nAcum nu mai pare asa de \"magic\", nu?\r\n\r\nSursa modificata pentru a calcula si $x$ si $y$ nu este mult mai complexa. Acum intelegeti de ce am trimis $d$ ca pointer mai sus, si de ce am folosit varianta recursiva a algoritmului lui euclid. Implementat iterativ, este nevoie de un vector care sa tina toate valorile $c$ ({$a / b$}) obtinute pe parcurs.\r\n\r\nNota pentru pascalisti: in C nu exista div, impartirea intre int-uri este automat si impartire intreaga (div din pascal).\r\n\r\n== code(c) | void euclid(int a, int b, int *d, int *x, int *y)\r\n{\r\n    if (b == 0) {\r\n        *d = a;\r\n        *x = 1;\r\n        *y = 0;\r\n    } else {\r\n        int x0, y0;\r\n        euclid(b, a % b, d, &x0, &y0);\r\n        *x = y0;\r\n        *y = x0 - (a / b) * y0;\r\n    }\r\n}\r\n==\r\n\r\nh2. Impartire modulara\r\n\r\nAcum pentru o aplicatie interesanta, impartirea modulara. Nu voi intra in detalii, pe scurt aritmetica modulara este aritmetica in care toate valorile se iau modulo un anumit numar {$n$}. Spre exemplu, in {@modulo 7@}, {$3 = 10$}. Similar, rezultatele tuturor operatiilor se iau in modul: {$4 + 5 = 2$}, {$3 * 5 = 1$} etc.\r\n\r\nCum putem defini insa impartirea in modulo? Evident, {$6 / 2$} este tot {$3$}, dar $3 / 4$ cu cat este egal? De obicei impartirea este definita ca operatia inversa a inmultirii, similar cum scaderea este operatia inversa a adunarii. Astfel, daca {$a / b = c$} atunci {$b * c = a$}. Prin algoritmul lui Euclid putem afla $x$ si $y$ astfel incat {$n * x + b * y = cmmdc(n, b)$}, unde $n$ este modulul. Totul e modulo {$n$}, asa ca putem ignora {$x * n$}. Atunci {$c = y * a / cmmdc(n, b)$}. Daca $a$ nu este divizibil cu {$cmmdc(n, b)$}, atunci $c$ nu exista. Intradevar, nu exista $c$ pentru care $3 * c = 4$ modulo {$6$}.\r\n\r\nh2. Tema pentru acasa\r\n\r\nCateva probleme care se rezolva intr-un mod sau altul folosing algoritmul lui Euclid sau algoritmul lui Euclid extins:\r\n\r\n* Sgu 106: \"The Equation\":http://acm.sgu.ru/problem.php?contest=0&problem=106\r\n* Sgu 137: \"Funny Strings\":http://acm.sgu.ru/problem.php?contest=0&problem=137\r\n* Sgu 141: \"Jumping Joe\":http://acm.sgu.ru/problem.php?contest=0&problem=141\r\n* Sgu 248: \"Integer Linear Programming\":http://acm.sgu.ru/problem.php?contest=0&problem=248\r\n\r\nO sursa interesanta pentru Algoritmul lui Euclid este cea din cartea lui Knuth Arta Programarii Calculatoarelor Vol. 2 Algoritmi Seminumerici care descrie stransa legatura intre algoritm si fractiile continue (Cap. 4.5.3)',2044,'public',3681,NULL),('agora-finala/solutii','Concursul Agora - Etapa Finala - Solutii','2005-07-12 00:00:00','2008-04-03 22:07:13','h1. Concursul Agora - Etapa Finala - Solutii\r\n\r\n(Categoria _Competitii_, autor(i) _Cosmin_)\r\n\r\nArticolul contine cateva idei de solutionare a problemelor de la etapa finala a concursului Agora. Concursul s-a desfasurat la Cluj in 9 iulie pentru concurentii ce s-au calificat in finala, dar s-a desfasurat si online pentru cei care doreau sa isi incerce puterile.\r\n\r\nh2. Problema 1: Drumuri\r\n\r\nProblema cerea determinarea unei partitionari a muchiilor dintr-un graf conex in perechi disjuncte astfel ca in fiecare pereche de muchii cele doua muchii sa aiba un capat comun. Pentru orice graf conex cu numar par de muchii exista o asemenea partitionare a muchiilor. Algoritmul ce solutioneaza problema ne demonstreaza acest lucru. Putem determina pentru graful nostru un arbore partial (arbore DFS sau BFS sau care mai vreti voi). Putem lua o frunza din arborele nostru, daca ea are grad par atunci o putem elimina din arbore si toate muchiile ce aveau un capat in ea sa le imperechem doua cate doua. Daca in schimb frunza are grad impar atunci eliminam toate muchiile mai putin cea din arbore si eliminam nodul virtual din graf, dar nu si muchia asociata care devine o muchie oarecare si va putea fi eliminata cand procesam tata frunzei actuale. Singura problema ce poate aparea este cand ajungem la radacina, dar cum dintr-un graf cu numar par de muchii am eliminat la fiecare pas un numar par de muchii inseamna\r\nca radacina are grad par, deci problema noastra este rezolvata. Complexitatea algoritmului este $O(N + M)$ si ca timp si ca memorie, acest algoritm poate fi foarte usor implementat ca o parcurgere DFS care dupa ce viziteaza un nod si fii sai il elimina din graf.\r\n\r\nh2. Problema 2: Colectie\r\n\r\nProblema se imparte in doua bucati: Prima este determinarea numarului de cifre $i$ care apar in scrierea numerelor de la $1$ la $K$ unde $i$ este intre $0$ si {$9$}. Aceasta problema se poate rezolva in $O(log K)$ cu programare dinamica, o rezolvare eficienta a fost ceruta la bacalaureat in anul 2001 deci nu e asa grea :) , o rezolvare care lua putin timp ar fi fost metoda constantelor, adica putem tine minte din $100.000$ in $100.000$ rezultatele partiale (aceasta abordare a fost luata de Patcas Csaba la etapa finala).\r\nAcum avem de rezolvat o problema de obtinere a unui vector dimensiune $10$ ca suma unei submultimi de vectori dati la intrare. Aceasta problema o putem rezolva cu o tehnica intalnita pe la concursuri de programare, dar care nu a devenit inca clasica. Impartim multimea de vector in doua multimi de dimensiuni $n / 2$ si {$n - n /2$}. Pentru prima multime determinam toate submultimile si sumele vectoriale asociate acelor submultimi, si sortam submultimile dupa acele sume. Acum pentru fiecare submultime de vectori din a doua multime obtinem o suma vectoriala {$sum$}, noi vrem sa mai adaugam ceva elemente la aceasta suma pentru a obtine un vector $target$ ce reprezinta pentru fiecare cifra numarul de etichete necesare pentru a eticheta toate numerele de la $1$ la {$K$}. Deci vom cauta binar in primul sir vectorul {$target - sum$}. Faza de sortare dureaza $O(n^2^ * 2^n^)$ si faza de cautare binara tot atat.Astfel rezolvare are complexitatea $O(2^n^ * n^2^ + log K)$ ca timp si $O(2^n^ * n)$ ca spatiu.\r\n\r\nh2. Problema 3: Heroes of Might and Magic\r\n\r\nProblema cerea determinarea numarului de drumuri de la un punct ({$start_x, start_y$}) dintr-o matrice pana la un punct ({$end_x, end_y$}) din aceiasi matrice, drum care sa aiba cel mult $K$ pasi. Problema se rezolva usor folosind metoda programarii dinamice. Vom folosi o matrice tridimensionala unde $num_ways{~i,j,k~}$ are semnificatia: numarul de drumuri ce incep in ({$start_x, start_y$}), se termina in ({$i, j$}) si au fix $k$ pasi. Solutia se va afla in {$num_ways{~end_x,end_y,0~} &#0043; num_ways{~end_x,end_y,1~} &#0043; ... &#0043; num_ways{~end_x,end_y,K~}$}. Formula de recurenta pentru problema este usor de determinat:\r\n{$num_ways{~i,j,k~} = num_ways{~i+1,j,k-1~} &#0043; num_ways{~i-1,j,k-1~} &#0043; num_ways{~i,j-1,k-1~} &#0043; num_ways{~i,j+1,k-1~}$}. Se observa ca pentru a determina valorile corespunzatoare lui $k$ avem nevoie doar de valorile corespunzatoare lui {$k - 1$}, deci putem folosi doua matrici bidimensionale in loc de una tridimensionala. Complexitatea solutiei ca si timp este $O(N * M * K)$ iar ca si spatiu este {$O(N * M)$}.\r\n\r\n',6756,'public',NULL,NULL),('al-k-lea-drum-minim','Al K-lea drum minim','2004-11-29 00:00:00','2009-02-20 01:11:37','h1. Al K-lea drum minim\r\n\r\n(Categoria _Algoritmi_, Autor _Leonard Crestez_)\r\n\r\nExista un numar mare de algoritmi pentru a calcula cel mai scurt drum intre $2$ noduri intr-un graf, dar chiar si al {$2$}-lea cel mai scurt drum este o extindere non-triviala. Pentru a afla al {$k$}-lea drum minim se foloseste un algoritm total diferit fata de cei pentru drum minim. Algoritmul este dificil de implementat, iar sursa rezultata este de obicei voluminoasa, asa ca acest algoritm nu prea intervine in problemele de concurs. Am considerat totusi ca este destul de interesant, si merita prezentat.\r\n\r\nO nota importanta este ca nu se determina drumul cu al {$k$}-lea cost. Doua drumuri se considera diferita daca au noduri diferite, nu neaparat si cost diferit. Astfel, daca exista $5$ drumuri distincte de cost minim, oricare dintre ele poate fi solutie pentru al {$4$}-lea sau al {$5$}-lea drum minim. Astfel, aceasta problema are de fapt mai multe solutii posibile.\r\n\r\nExista $2$ cazuri pentru aceasta problema, iar algoritmul prezentat necesita mici modificari pentru a se adapta, dar ideea de baza ramane aceeasi. Cele doua cazuri sunt daca drumul trebuie neaparat sa fie elementar sau nu. Cazul in care se accepta doar drumuri elementare este mai restrictiv, si, astfel, un pic mai dificil.\r\n\r\nh2. Mod de functionare\r\n\r\nDaca pentru drumul minim intre $2$ noduri de obicei se calculeaza drumul minim dintre primul nod si celelalte noduri din graf, pentru a afla al {$k$}-lea drum minim se calculeaza toate primele $k - 1$ drumuri minime, in ordine. Un pas al algortimului consta in aflarea celul de-al {$k$}-lea drum minim cand primele $k$ sunt cunoscute. Drumul minim este folosit de mai multe ori in algoritm, pentru a intelege acest algoritm este necesara o anumita familiaritate cu algoritmul lui Dijkstra.\r\n\r\nDrumurile minime pana la $k-1$ sunt stocate compactate intr-un arbore de drumuri. Fiecarui nod din acel arbore ii corespunde un nod din graf, dar nu si invers, un nod din graf poate aparea de mai multe ori in arbore. Radacina arborelui corespunde nodului de start, iar toate frunzele arborelui corespund nodului de final, iar drumurile de la radacina catre frunze reprezinta fiecare cate un drum minim. Vezi in figura cum se compacteaza drumurile ({$1, 7, 4, 5$}), ({$1, 7, 3, 5$}), ({$1, 2, 4, 5$}) si ({$1, 2, 6, 4, 5$}). Drumurile sunt primele $4$ drumuri din graful desenat mai sus si luat drept exemplu.\r\n\r\n!Al-K-lea-drum-minim?kshortest_graph.png!\r\n!Al-K-lea-drum-minim?kshortest_tree.png!\r\n\r\nAl {$k$}-lea drum minim trebuie sa corespund pana intr-un anumit punct cu un drum aflat deja in arbore, chiar daca punctul acela este de fapt nodul de start. Pentru a gasi urmatorul drum minim, incercam sa \"deviem\" din fiecare nod din arbore. Un drum de deviatie pentru un anume nod $X$ este un drum identic cu drumul de la radacina pana la nodul {$X$}, care apoi continua (deviaza) pe cel mai scurt drum pana la destinatie care nu a fost inca luat in cosiderare. Spre exemplu pentru nodul $4$ din drumul ({$1, 2, 4, 5$}) putem sa deviem din $4$ prin ({$7, 3, 5$}), formand drumul ({$1, 2, 4, 7, 3, 5$}). Este intuitiv ca, la fiecare pas, pentru fiecare nod din arbore este interesant doar cel mai scurt drum de deviatie.\r\n\r\nAlgoritmul mentine o multime, eventual ca un heap, de deviatii. Se tine pentru fiecare drum de deviatie nodul din care deviaza si lungimea drumului. La fiecare pas extragem drumul de deviatie minim si reconstituim drumul. Sa zicem ca drumul scos din heap este ({$a{~1~} a{~2~} ... a{~d~}, a{~d+1~} ... a{~n~}$}), unde $a{~d~}$ este nodul de unde s-a facut deviatia. Introducem acest drum in arborele de drumuri, si pentru fiecare nod de la $a{~d~}$ la $a{~n-1~}$ calculam deviatia minima si o introducem in heap. Pentru restul nodurilor este evident ca deviatia minima nu se modifica.\r\n\r\nAlgoritmul odata inteles este relativ logic. Al {$k$}-lea drum minim trebuie sa coincida cu unul dintre cele $k-1$ drumuri deja existente pana intr-un anumit punct, dupa care \"ia un viraj\" nevizitat si continua cel mai scurt drumul inca neparcurs.\r\n\r\nDupa cum am zis mai sus, algoritmul are $2$ variante, daca este necesar ca drumurile sa fie elementare sau nu. Pentru cele $2$ variante se modifica modul in care se calculeaza deviatia minima dintr-un nod. Cazul cel mai simplu este atunci cand nu este necesar ca drumurile sa fie elementare. Pentru nodul $X$ din care trebuie sa deviem, vom lua cel mai scurt drum care inca nu este in arbore. Putem sa calculam de dinainte un arbore de drumuri inversat, de la toate nodurile la destinatie, si sa luam minimul de la nodurile adiacente care NU sunt printre copii in arbore. Pentru arborele din desen, daca ar fi sa deviem din ({$1, 2$}) am putea lua in considerare doar nodul {$1$}.\r\n\r\nDaca trebuie sa luam in considerare doar drumurile elementare, algoritmul simplu de mai sus da erori. Spre exemplu, daca ar fi sa deviem din ({$1, 7$}) in desen, drumul optim ar fi prin {$1$}, adica ({$1, 7, 1, 7, 4, 5$}), care drum nu este elementar. Pentru a genera doar drumurile elementare, este nevoie sa marcam nodurile de la radacina pana la deviatie ca \"ocupate\" si sa rulam un algoritm de drum minim pana la destinatie. Acest lucru creste foarte mult complexitatea in timp si in implementare.\r\n\r\nh2. Exemplu\r\n\r\nAlgoritmul prezentat este destul de complex, asa ca vom detalia rularea algoritmului pe graful din desen. Vom incerca sa calculam toate cele mai scurte $5$ drumuri elementare intre nodurile $1$ si {$5$}. Punem si conditia ca drumurile sa fie elementare (cazul mai dificil).\r\n\r\n* Primul drum minim este ({$1, 7, 4, 5$}), de lungime {$9$}.\r\n* Incercam sa deviem din {$1$}. Drumul minim de la $1$ la $5$ care nu trece imediat prin $7$ este ({$1, 2, 4, 5$}), cu cost {$10$}.\r\n* Incercam sa deviem din {$7$}. Drumul minim de la $7$ la $5$ care nu trece imediat prin $4$ este ({$7, 3, 5$}), cu cost {$10$}. Atentie, adaugam si costul de la $1$ la {$7$}.\r\n* Incercam sa deviem din {$4$}. Nu exista alt drum de la {$4$} la {$5$}. Ar putea fi drumul ({$4, 7, 3, 5$}), dar nu ar fi elementar, deoarece avem prefixul ({$1, 7$}), noduri pe care le-am marcat blocate.\r\n* Din $5$ nu are sens sa deviem, asa ca..\r\n* Al doilea drum minim este ({$1, 2, 4, 5$}), de lungime {$10$}.\r\n* Incercam sa deviem din {$1$}, dar nu exista drum de la $1$ la $5$ care sa nu o ia imediat nici prin $2$ si nici prin {$7$}.\r\n* Incercam sa deviem din {$2$}. Drumul minim de la $2$ la $5$ care nu trece imediat prin $4$ este ({$2, 6, 4, 5$}), cu cost {$10$}. Atentie, drumul trece prin {$4$}, dar nu imediat.\r\n* Incercam sa deviam din {$4$}. Drumul minim de la $4$ la $5$ care nu trece imediat prin $5$ este ({$4, 7, 3, 5$}), cu cost {$15$}. Acest drum nu a fost valid mai inainte, dar acum prefixul lui $4$ este ({$1, 2$}), asa ca drumul e valid.\r\n* Al treilea drum minim este ({$1, 7, 3, 5$}), tot de lungime {$10$}. Al doilea si al treilea drum minim sunt interschimbabile.\r\n* Acest drum a fost derivat din {$7$}, asa ca nu trebie incercam sa derivam din {$1$}.\r\n* Incercam sa deviem din {$7$}, dar nu exista drum de la $7$ la $5$ care sa nu treaca imediat nici prin $3$ nici prin {$4$}. Ar fi ({$7, 1, 2, 4, 5$}), dar avem $1$ ca prefix si marcat blocat. Astfel, evitam un drum neelementar.\r\n* Incercam sa deviem din {$3$}, fara succes(si fara explicatii kilometrice.).\r\n* Al patrulea drum minim este ({$1, 2, 6, 4, 5$}), de lungime {$11$}.\r\n* Incercam sa deviem din {$2$}, dar fara succes.\r\n* Incercam sa deviem din {$6$}, dar tot fara succes.\r\n* Incercam sa deviam din {$4$}. Drumul minim de la $4$ la $5$ care nu trece imediat prin $5$ este ({$4, 7, 3, 5$}), cu cost {$16$}. Noi am mai gasit odata acest drum, dar de data asta e cu un alt prefix, si alt cost. Drumul complet este ({$1, 2, 6, 4, 7, 3, 5$}), nu ({$1, 2, 4, 7, 3, 5$}).\r\n* Al cincilea drum minim este ({$1, 2, 4, 7, 3, 5$}), de lungime {$15$}.\r\n* Astfel se termina exemplul nostru. Puteti sa incercati, nu mai exista deviatii posibile. Al {$6$}-lea si ultimul drum este ({$1, 2, 6, 4, 7, 3, 5$}) , care se intample sa fie si cel mai lung drum, si hamiltonian.\r\n\r\nh2. Analiza complexitatii\r\n\r\nComplexitatea algoritmului este diferita in cele $2$ variante. In ambele cazuri putem considera la lugimea fiecarui drum este de {$O(n)$}, si ca heap-ul contine $O(k * n)$ valori. Luam cazul cel mai defavorabil, cu graf complet, si consideram ca un algoritm de drumuri minime necesita timp {$O(n * n)$}. Astfel, daca nu este nevoie ca drumurile sa fie elementare:\r\n\r\n* Precalculam drumurile de la orice nod la destinatie, {$O(n * n)$}.\r\n* La fiecare dintre cei k pasi.\r\n** Extragem din heap, $O(log(k * n))$\r\n** Reconstituim drumul, $O(n)$\r\n** Pentru fiecare dintre cele maxim $n$ noduri din drum:\r\n*** Vedem cel mai scurt drum de continuare, $O(n)$\r\n*** Il adaugam in heap, $O(log(k * n))$\r\n\r\nComplexitatea ajunge astfel la {$O(k * n * (n + log(k * n)))$}. Trebuie avut in vedere ca in general drumurile minime vor avea noduri relativ putine, asa ca algorimtul e mai rapid decat pare. Daca punem conditia ca drumurile determinate sa fie elementare, complexitatea creste:\r\n\r\n* La fiecare dintre cei $k$ pasi.\r\n** Extragem din heap, $O(log(k * n))$\r\n** Reconstituim drumul, $O(n * n)$ (il calculam iarasi)\r\n** Blocam nodurile de la start pana la nodul de deviatie, $O(n)$\r\n** Pentru fiecare dintre cele maxim $n$ noduri din drum:\r\n*** Vedem cel mai scurt drum de continuare, $O(n * n)$\r\n*** Il adaugam in heap, $O(log(k * n))$\r\n\r\nComplexitatea ajunge acum la {$O(k * n * (n * n + log(k * n)))$}, aproximativ {$O(k * n^3^)$}. Iarasi, algoritmul se comporta mai bine in practica decat pare in complexitate.\r\n\r\nh2. Observatii, indicatii, completari\r\n\r\nAlgoritmul poate fi mai incet sau mai rapid. Se poate folosi ceva mai simplu de implementat in loc de heap, sau un algoritm de drumuri minime mai evoluat. Daca va intrebati daca algoritmul poate fi folosit pentru a determina un drum hamiltonian, raspunsul este da, dar asta necesita determinarea tuturor drumurile lor dintre $2$ muchii, care este exponential in functie de {$n$}.\r\n\r\nDaca sunteti interesati si, bineinteles, daca \"va tine\", incercati se rezolvati problema \"SGU 145\":http://acm.sgu.ru/problem.php?contest=0&problem=145 , de unde a pornit de fapt acest articol. Se cere cazul cel dificil, cu drumuri elementare.\r\n\r\n',2044,'public',3695,NULL),('blog/oji-oni-2005','OJI & ONI 2005','2005-01-31 00:00:00','2005-01-31 00:00:00','h1. OJI & ONI 2005\r\n\r\nOlimpiada de Informatica, faza judeteana va avea loc pe data de 26-27 februarie 2005. Pe 26 februarie clasele 5, 6, 9 si 10 iar pe 27 februarie clasele 11, 12, 7 si 8.\r\n\r\nOlimpiada Nationala de Informatica de anul acesta se va desfasura in orasul Galati in perioada 25 martie-1 aprilie. Pentru mai multe detalii intrati vizitati \"olimpiada.info\":http://olimpiada.info si \"infogl.ro\":http://www.infogl.ro !\r\n\r\nMult succes!\r\n\r\n',1142,'protected',NULL,NULL),('template/preoni-2006','template/preoni-2006','2006-11-26 03:41:53','2006-11-27 16:01:52','==include(page=\"template/preoni-2006/header\")==\r\n\r\n(vmenu)*(section) \'preONI 2006\':preoni-2006\r\n* \'Informatii generale\':preoni-2006/info\r\n* \'Organizatori\':preoni-2006/comisie\r\n* \'Sponsori si premii\':preoni-2006/premii\r\n* \'Program\':preoni-2006/program\r\n* \'Regulament\':preoni-2006/regulament\r\n* \'Aparitii in presa\':preoni-2006/presa\r\n* \'Clasament\':preoni-2006/clasament\r\n*(section) Runde\r\n* \'Runda 1\':preoni-2006/runda-1\r\n* \'Runda 2\':preoni-2006/runda-2\r\n* \'Runda 3\':preoni-2006/runda-3\r\n* \'Runda 4\':preoni-2006/runda-4\r\n* \'Runda finala\':preoni-2006/finala\r\n\r\n\r\n',13,'protected',NULL,NULL),('template/preoni-2006/header','template/preoni-2006/header','2006-11-27 15:56:21','2006-11-27 16:08:54','table{margin: 0; width: 99%; background-image: url(/template/preoni-2006?action=download&file=hbk.gif); background-repeat: repeat-x; background-position: bottom left;}. |{border: 0px;}. !template/preoni-2006?hlogo.gif!:/preoni-2006 |{border: 0px; text-align: right; vertical-align: bottom}. !template/preoni-2006?ipdevel.gif!:http://www.ipdevel.ro/ !template/preoni-2006?oracle_ro.gif!:http://www.oracle.ro/ |\r\n',13,'protected',NULL,NULL),('blog/preoni-2005-runda-1','preONI, runda #1','2005-01-19 00:00:00','2005-01-19 00:00:00','h1. preONI 2005, runda #1\r\n\r\nNe mai despart doua luni de Olimpiada Nationala de Informatica (18-27 martie, Galati / Drobeta Turnu Severin)! Pentru a veni in sprijinul elevilor ce se pregatesc pentru aceasta competitie, echipa info.devNet organizeaza un concurs de pregatire (preONI) in 3 runde.\r\n\r\nDuminica, 23 ianuarie, ora 15:00 va avea loc prima runda preONI.\r\n\r\nFormatul concursului: 2 grupe (clasele IX-X, XI-XII), 3 probleme in fiecare grupa si un timp de lucru de 4h. Evaluarea va incepe la 15min dupa terminarea timpului de lucru si va putea fi urmarita in timp real la sectiunea \"statistici\".\r\n\r\nSpre deosebire de ultimul concurs de pregatire (din 14 nov 2004), cele 3 probleme propuse vor avea de aceasta data o dificultate gradata, fiind accesibile unui public mult mai larg.\r\n\r\nPropunatorii problemelor din runda #1 sunt:\r\n\r\n* Mircea Pasoi\r\n* Adrian Vladu\r\n* Cosmin Negruseri\r\n\r\nAsteptam intrebarile / sugestiile tale pe \'forum\':http://forum.infoarena.ro.\r\n\r\n*Mult succes!*',961,'protected',NULL,NULL),('moisil-by-net-2006/clasament-9','Clasament moisil2','2006-11-23 21:09:01','2006-11-24 18:24:57','h1. Clasament ==roundparam(round_id=\"moisil2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil2\")==',961,'protected',NULL,NULL),('preoji-2004','preOJI 2004','2006-11-23 21:08:49','2006-11-24 16:25:38','h1. preOJI 2004\r\n\r\n!>preoji-2004?logo!\r\n\r\nConcursul s-a desfasurat pe 22/2/2004 intre orele 9 si 12 dimineata.\r\n\r\nAu fost 2 grupe cu cate 2 probleme, in similar OJI.\r\n\r\nh2. Grupa mica, clasele 9-10 (\'Clasament\':preoji-2004/clasament-9-10)\r\n\r\n== Tasks(round_id=\"preoji1\" pager_style=\"none\")==\r\n\r\nh2. Grupa mare, clasele 11-12 (\'Clasament\':preoji-2004/clasament-11-12)\r\n\r\n== Tasks(round_id=\"preoji2\" pager_style=\"none\")==\r\n\r\n',1,'protected',NULL,NULL),('summer-challenge-2/clasament','Clasament summer2','2006-11-23 21:09:02','2006-11-24 17:47:15','h1. Clasament ==roundparam(round_id=\"summer2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer2\")==',961,'protected',NULL,NULL),('summer-challenge-3','Summer Challenge Trei','2006-11-23 21:09:02','2006-11-24 17:38:27','h1. Summer challenge 3\r\n\r\nConcursul s-a desfasurat pe 27 august 2006, ora 10:00 pe o durata de 5h. S-au propus spre rezolvare 3 probleme care au fost adaugate in \'arhiva\':arhiva.\r\n\r\nSolutiile problemelor le puteti gasi \"aici\":summer-challenge-3/solutii.\r\n\r\nh2. \'Clasament\':summer-challenge-3/clasament\r\n\r\n!>summer-challenge-3?logo.jpg!\r\n\r\n== Tasks(round_id=\"summer3\" pager_style=\"none\") ==',961,'protected',NULL,NULL),('warm-up-2006','Autumn WarmUp 2006','2006-11-23 21:09:03','2007-09-16 00:41:06','h1. Autumn WarmUp 2006\r\n\r\nConcursul s-a desfasurat incepand cu ora 14:00 pe data de 8 septembrie 2006.\r\n\r\nA fost un concurs facut de utilizatori pentru utilizatori, cu 5 subiecte cu grade diferite de dificultate, de la accesibil la dificil. Evaluatorul a fost pornit pe toata durata concursului.\r\n\r\nSolutiile problemelor le puteti gasi \"aici\":warm-up-2006/solutii.\r\n\r\nh2. Propunatori\r\n\r\n* Paul Dan Baltescu (PaulDB)\r\n* Vlad Berteanu (vladcyb1)\r\n* Vlad Dumitriu (vladut.forum)\r\n* Tiberiu Savin (devilkind)\r\n* Vlad Saveluc (VladS)\r\n\r\nh2. \'Clasament\':warm-up-2006/clasament\r\n\r\n!>warm-up-2006?logo.jpeg!\r\n\r\n== Tasks(round_id=\"autumn06\" pager_style=\"none\") ==\r\n',2028,'protected',NULL,NULL),('summer-challenge-3/clasament','Clasament summer3','2006-11-23 21:09:02','2006-11-24 17:47:06','h1. Clasament ==roundparam(round_id=\"summer3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer3\")==',961,'protected',NULL,NULL),('warm-up-2006/clasament','Clasament autumn06','2006-11-23 21:09:03','2006-11-24 18:25:27','h1. Clasament ==roundparam(round_id=\"autumn06\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"autumn06\")==',961,'protected',NULL,NULL),('happy-coding-2006/clasament','Clasament happy2006','2006-11-23 21:09:03','2006-11-24 17:49:02','h1. Clasament ==roundparam(round_id=\"happy2006\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"happy2006\")==',961,'protected',NULL,NULL),('blog/final-preoni-2005-runda-1','preONI runda #1 s-a incheiat','2005-01-27 00:00:00','2005-01-27 00:00:00','h1. preONI 2005 runda #1 s-a incheiat\r\n\r\npreONI runda #1 s-a incheiat, rezultatele finale au fost publicate iar problemele au fost mutate in arhiva.\r\n\r\nMircea Pasoi a publicat un \'articol\':preoni-2005/runda-1/solutii despre aceasta runda.\r\n\r\nAsteptam parerile si sugestiile voastre pe \'forum\':http://forum.infoarena.ro',961,'protected',NULL,NULL),('usaco-ian-2005-divizia-gold','Usaco ianuarie 2005, divizia GOLD','2005-03-03 00:00:00','2008-11-17 21:09:48','h1. Usaco ianuarie 2005, divizia GOLD\r\n\r\n(Categoria _Competitii_, autor(i) _Silviu Ganceanu, Mircea Pasoi_)\r\n\r\n\r\nAcest set de probleme a fost considerat unul dintre cele mai grele, daca nu cel mai greu, de pana acum. Problemele au fost intr-adevar dure cu atat mai mult cu cat timpul de lucru a fost mic (3 ore). In ciuda acestui fapt concurentii din Romania s-au comportat bine, concursul marcand primul succes de pe anul acesta al tarii noastre: locul 5 obtinut de Adrian Vladu.\r\n\r\nDesi rezultatele i-au determinat pe antrenorii americani sa considere setul de probleme cel mai greu de pana acum, pentru multi dintre elevii Romaniei problemele nu au fost in totalitate noi: cover a fost propusa (sub o forma un pic diferita) la CEOI, o varinta ceva mai blanda a problemei juice (cu limite mai mici) am putut vedea si in finala rundei .Campion de anul trecut iar ideea de rezolvare pentru naptime nu era noua (o problema din concursul $\"Stelele Informaticii\"$ de anul trecut se pare ca semana mult cu aceasta).\r\n\r\nCu toate aceastea problemele au fost deosebit de dificile necesitand concentrare maxima. Rezultatele elevilor din Romania s-au imbunatatit semnificativ fata de concursul precedent, acestia obtinand locuri mai bune. O parte din succesul acestora indraznesc sa o pun si pe seama faptului ca problema cea mai grea din concurs era cunoscuta la noi in tara. Avem astfel urmatorul clasament:\r\n\r\ntable. |_. 1. | Adrian Vladu | $958$ puncte |\r\n|_. 2. | Sorin Stancu-Mara | $703$ puncte |\r\n|_. 3. | Mircea Pasoi | $700$ puncte |\r\n|_. 4. | Andrei Teodorescu | $640$ puncte |\r\n|_. 5. | Dan-Ionut Fechete | $547$ puncte |\r\n|_. 6. | Adrian Diaconu | $502$ puncte |\r\n\r\nRestul concurentilor au obtinut punctaje frumoase dar mai mici de $400$ de puncte. Sunt de remarcat comportarile bune de pana acum ale lui Andrei Teodorescu care reuseste sa se \"tina\" de mult mai titratii elevi ai Romaniei care au deja in palmares cel putin o medalie internationala.\r\n\r\nSetul de probleme, impreuna cu testele si clasamentul, se gaseste in cadrul \"sectiunii download\":downloads. In continuare vom prezenta solutiile:\r\n\r\nh2(#cover). Cover\r\n\r\nProblema nu era foarte dificila, cu atat mai mult cu cat ideea de rezolvare a problemei guards din concursul CEOI 2002 era aceeasi: se construieste un graf bipartit avand intr-o multime barele orizontale (set maximal de pozitii de pe o linie din matrice in care avem noroi) si in cealalta multime barele verticale (definite analog dar pentru coloane). Intre doua noduri din acest graf bipartit vom avea muchie doar daca barele corespunzatoare lor au o celula comuna. Pentru exemplificare vom lucra cu exemplul din enunt:\r\n@*.*.@\r\n@.***@\r\n@***.@\r\n@..*.@\r\nIata cum vom construi prima multime a grafului bipartit (vom pune numarul nodului din graf corespunzator fiecarei celule):\r\n@1.2.@\r\n@.333@\r\n@444.@\r\n@..5.@\r\nA doua multime a grafului bipartit va arata astfel (nodurile vor fi numerotate incepand tot cu 1):\r\n@1.2.@\r\n@.324@\r\n@532.@\r\n@..2.@\r\nMuchiile din graful bipartit vor fi urmatoarele:\r\n$(1, 1) (2, 2) (3, 3) (3, 2) (3, 4) (4, 5) (4, 3) (4, 2) (5, 2)$\r\n\r\nAsadar fiecarei celule din harta terenului ii corespunde o singura muchie in acest graf bipartit. Avand construit graful trebuie sa aflam numarul minim de noduri selectate astfel incat orice muchie sa aiba cel putin un capat intre nodurile selectate (in literatura de specialitate aceasta problema se numeste {$Minimum Vertex Cover$}). Explicatia acestui lucru este simpla: orice muchie, fiind de fapt o celula, ea trebuie sa fie \"acoperita\" de cel putin un nod din graf (adica o placa orizontala sau verticala utilizata de FJ). Problema acesta este NP-completa pentru grafuri generale dar in cazul grafurilor bipartite ea se poate rezolva in timp polinomial. De asemenea s-a demonstrat ca numarul minim de noduri dintr-un astfel de set este egal cu cardinalul cuplajului maximal din graful bipartit. De aici nu mai e decat un pas spre solutia finala. Avem, astfel, urmatorii pasi in algoritmul de rezolvare a problemei:\r\n==code(cpp) |\r\n* PAS 1: Construirea grafului bipartit\r\n* PAS 2: Aflarea cuplajului maximal\r\n==\r\n\r\nPrimul pas este banal si consta din simple parcurgeri ale matricii. Pentru aflarea cuplajului maximal se poate afla utilizand un algoritm de aflarea a fluxului maxim in reteaua asociata grafului bipartit sau se poate algoritmul bazat pe gasirea succesiva a drumurilor in crestere in graf.\r\nComplexitatea finala a algoritmului va fi $O(N^2^*M^2^)$ deoarece in graful bipartit avem maxim $N*M$ muchii si vom $N*M$ noduri. Cum algoritmul pentru aflarea cuplajului maximal are complexitatea $V*E$ ({$V$} = numarul de noduri din graf, $E$ = numarul de muchii din graf) concluzia este evidenta.\r\nCa tema, recomand rezolvarea urmatoarelor probleme a caror solutie se bazeaza pe aflarea cuplajului maximal intr-un graf bipartit (in unele cazuri acest lucru insa nu este de ajuns):\r\n\r\n# $guards (CEOI 2002)$\r\n# $knigths (Baltica 2001)$ - in solutia oficiala a acestei probleme gasiti mai multe informatii despre notiunea de cuplaj maximal intr-un graf bipartit si problemele inrudite\r\n# Problema \"Paznici\":http://algoritmus.org/probleme/probleme_runda04.php din runda a patra a concursului Algoritmus (gasiti pe pagina si explicatia solutiei)\r\n# \"http://acm.timus.ru/problem.aspx?space=1&num=1106\":http://acm.timus.ru/problem.aspx?space=1&num=1106\r\n# \"http://acm.sgu.ru/problem.php?contest=0&problem=234\":http://acm.sgu.ru/problem.php?contest=0&problem=234\r\n# \"http://acm.sgu.ru/problem.php?contest=0&problem=210\":http://acm.sgu.ru/problem.php?contest=0&problem=210\r\n# \"http://acm.sgu.ru/problem.php?contest=0&problem=218\":http://acm.sgu.ru/problem.php?contest=0&problem=218\r\n# \"http://online-judge.uva.es/p/v107/10735.html\":http://online-judge.uva.es/p/v107/10735.html\r\n# \"http://online-judge.uva.es/p/v108/10804.html\":http://online-judge.uva.es/p/v108/10804.html\r\n# \"http://online-judge.uva.es/board/viewtopic.php?t=7462\":http://online-judge.uva.es/board/viewtopic.php?t=7462\r\n\r\nMentionez ca problema 8 m-a impresionat in mod placut fiind una dintre cele mai frumoase probleme pe care le-am intalnit in ultimele cateva luni.\r\n\r\nh2. Juice\r\n\r\nFie $A{~i,j~}$ inaltimea blocului aflat in pozitia $(i, j)$. Aflam inaltimea maxima la care poate urca nivelul sucului in fiecare celula. Daca notam aceasta inaltime cu B{~i,j~} solutia problemei va fi $suma( B{~i,j~} - A{~i,j~} )$.\r\n\r\nVom numi celula turn o celula $(i, j)$ care are propietatea ca $B{~i,j~} = A{~i,j~}$ (nu putem pune suc in ea pentru ca ar curge in afara matricei). Componenta conexa a unei celule turn $(i, j)$ este compusa din acele celule $(x, y)$ pentru care avem $B{~x,y~} = A{~i,j~}$. Definim inaltimea componentei conexe ca fiind inaltimea comuna a tuturor celulelor componente. Facem urmatoarele observatii utile in rezolvarea problemei:\r\n\r\n# Celulele de pe marginea matricei sunt celule turn\r\n# Celula $(x, y)$ devine celula turn daca este vecina unei celule $(i, j)$ ce face parte dintr-o componenta conexa si are propietatea ca $B{~i,j~} < A{~x,y~}$.\r\n\r\nIncet, incet se contureaza solutia problemei observand ca, pentru a declara o celula ca fiind turn, trebuie sa aflam componentele conexe ale celulelor turn mai joase decat ea. Acest lucru ne aduce la ideea de procesa aceste celule turn in ordinea inaltimii lor afland pentru fiecare componenta conexa corespunzatoare. In acelasi timp aflam si celule ce devin turn si sunt mai inalte. Pentru aceasta utilizam o coada de prioritati (un heap) in care pastram toate celule turn neprocesate inca ordonate descrescator dupa inaltime. Ajungem astfel la nimic altceva decat un algoritm de tip $FILL$ modificat corespunzator cerintelor acestei probleme. Iata o descriere a acestuia:\r\n\r\n==code(cpp) |\r\nPAS 1: Se introduc in coada de prioritati pozitiile de pe margine\r\nPAS 2: Cat timp heapul nu este gol:\r\n* se selecteaza celula turn cea mai joasa\r\n* se afla componenta conexa a acesteia\r\n* se introduc in coada de prioritati celulele vecine cu componenta conexa construita,\r\n  care au inaltimea mai mare decat inaltimea componentei\r\n==\r\n\r\nSe poate modifica usor algoritmul $FILL$ pentru a rezolva toate aceste cerinte. Complexitatea finala a algoritmului va fi $O(N^2^*logN)$ deoarece, in cazul cel mai defavorabil, toate celulele sunt turn (un exemplu este cand matricea este piramidala) si in consecinta toate celulele vor fi introduse si scoase din heap necesitand logN pentru fiecare operatie. Aflarea componentelor conexe va necesita $O(N^2^)$ timp in total fiindca o celula va fi selectata o singura data intr-o componenta conexa si va fi accesata de maxim 4 ori de algoritmul $FILL$. Ca detalii de implementare, programatorii in $C++$ pot folosi cozile de prioritati din $STL$ ({$priority_queue$} ce se gaseste in headerul {$&#0060;queue&#0062;$}) pentru a reduce din complexitatea implementarii. Totusi, trebuie acordata atentie utilizarii acestora deoarece este posibil ca sursa sa depasesca timpul de executie.\r\n\r\nh2. Naptime\r\n\r\nVom incerca sa rezolvam problema, ignorand la inceput faptul ca sirul este circular. Astfel, problema se transforma intr-una relativ usoara, abordabila cu programare dinamica. O prima incercare ar fi sa realizam o astfel de rezolvare: $A{~i,j~}$ = utilitatea de somn maxima care se poate obtine alegand $j$ perioade din primele $i$.\r\nRelatia de recurenta care se obtine este $A{~i,j~}=max(A{~i-k,j-k~}+suma U{~i-k+2~}...U{~i~})$ unde $U$ este vectorul de utilitati. Din pacate aceasta abordare are dezavantajul ca are complexitatea de timp $O(N*B^2^)$ si de memorie $O(N*B)$, neincadrandu-se nici in timp si nici in spatiu de memorie. Astfel, vom incerca sa imbunatatim aceasta dinamica modificand un pic semnificatia matricei A bazandu-ne pe faptul ca alegerea unei secvente continue de perioade aduca ca utilitate suma lor, mai putin prima perioada folosita:\r\n$A{~i,j,0~}$ = utilitatea de somn maxima care se poate obtine alegand $j$ perioade din primele $i$ si ultima perioada folosita sa fie $j$\r\n$A{~i,j,1~}$ = utilitatea de somn maxima care se poate obtine alegand $j$ perioade din primele $i$ si ultima perioada folosita sa *NU* fie $j$\r\nObtinem relatiile de recurenta:\r\n$A{~i,j,1~} = max({~i-1,j-1,1~} + U{~i~}, A{~i-1,j-1,0~})$\r\n$A{~i,j,0~} = max(A{~i-1,j,0~}, A{~i-1,j,1~})$\r\nAm redus complexitatea la $O(N*B)$ si memoria la $O(N)$, o imbunatatire substantiala.\r\n\r\nDeoarece sirul este circular, putem rezolva problema aplicand de $N$ ori dinamica de mai sus considerand sirul liniar si alegand fiecare pozitie ca fiind pozitia initiala, dar aceasta solutie depaseste cu mult limita de timp pe cazul cel mai defavorabil. Totusi, aceasta idee ar fi adus $10$ teste din cele $14$. Cu un mic truc, si anume alegerea aleatorie a pozitiei de start cat timp nu s-a depasit timpul de executie, s-ar mai fi putut obtine inca $2$ teste, in total $12$ (desi aceasta rezolvare nu obtine solutia optima pe testele foarte mari).\r\n\r\nPutem scapa de faptul ca sirul este circular mult mai elegant, aplicand de 2 ori dinamica: odata cum am zis mai sus (acoperind cazul cand pozitiile $N$ si $1$ nu sunt in aceeasi secventa de pozitii consecutive) si inca odata fortand sa existe o secventa de utilitati aleasa care contine pozitiile $N$ si $1$. A doua dinamica se poate obtine exact ca mai sus, aplicand aceeasi idee doar ca se initializeaza $A{~1,1,1~}=U{~1~}$ in loc de 0, si apoi pentru fiecare $i$ se verifica rezultatul curent cu $max(A{~i,B-(N-i),0~}, A{~i,B-(N-i),1~} + suma U{~i+2~}...U{~N~})$. Pentru a se incadara in limita de 0.3s trebuie acordata o mare grija la implementare, de exemplu, optimizand dinamica de mai sus de la $2*N$ memorie (ultimele doua linii din matricea $A$) la doar $N$ pastrand doar ultima linie si parcurgand indicele $j$ descrescator.',3146,'public',NULL,NULL),('blog/sarbatori-fericite','Sarbatori fericite!','2004-12-25 00:00:00','2004-12-25 00:00:00','Echipa infoarena ureaza Sarbatori fericite tuturor vizitatorilor si spor la treaba in continuare!\r\n',1142,'protected',NULL,NULL),('preoni-2005-runda-3','preONI, runda #3','2005-03-17 00:00:00','2006-11-25 15:35:37','h1. preONI 2005, runda #3\r\n\r\nSuntem bucurosi sa te anuntam ca runda #3 a concursului preONI se va desfasura Duminica, 20 martie la ora 10:00 - vezi mai jos informatii detaliate. Aceasta este ultima runda a concursului preONI 2005, runda ce va decide castigatorii premiilor oferite de Microsoft.\r\n\r\nClasamentul final se va calcula pe baza punctajelor obtinute in runda #2 si #3, punctajele din runda #1 fiind folosite doar pentru departajare in caz de egalitate.\r\n\r\nOricine este invitat sa participe, insa, eligibili pentru premii sunt doar acei concurenti din ciclul de invatamant pre-universitar care nu fac parte din echipa infoarena.\r\n\r\nh2. preONI 2005, runda #3\r\n\r\nDuminica, 20 marie, ora 10:00 va avea loc a treia (ultima) runda preONI. Ca de obicei, concursul se va desfasura online la adresa \'infoareana.devnet.ro\':http://infoarena.devnet.ro/ Formatul concursului: 2 grupe (clasele IX-X, XI-XII), 3 probleme in fiecare grupa si un timp de lucru de 4h. Evaluarea va incepe la 15min dupa terminarea timpului de lucru si va putea fi urmarita in timp real la sectiunea \"statistici\".\r\n\r\nPropunatorii problemelor din runda #2 sunt:\r\n\r\n* clasele IX - X: Mircea Pasoi, Adrian Vladu\r\n* clasele XI - XII: Silviu Ganceanu, Cosmin Negruseri, Mircea Pasoi\r\n\r\nAsteptam intrebarile / sugestiile tale pe \'forum\':http://info.devnet.ro/forum.php\r\n\r\nh2. Premii pentru preONI 2005\r\n\r\nSe vor acorda premii primilor 3 concurenti de la fiecare grupa. Premiile constau in carti valoroase de programare si sunt oferite de Microsoft Romania, prin intermediul programului \'\"Parteneri pentru Educatie\"\':http://www.microsoft.com/romania/educatie/pil/default.mspx.\r\n\r\n* Premiul 1\r\n** \"Arta programarii calculatoarelor\", vol. 3, Donald E. Knuth,\r\n** \"POO cu Visual Basic.Net si Visual C#.Net\", R. Reynolds Haertle\r\n* Premiul 2\r\n** \"Limbajul C Kernighan, Ritchie\", Brian Kernighan, Dennis Ritchie\r\n** \"POO cu Visual Basic.Net si Visual C#.Net\", R. Reynolds Haertle\r\n* Premiul 3\r\n** \"STL - Biblioteca programatorului\", Scott Meyers\r\n** \"POO cu Visual Basic.Net si Visual C#.Net\", R. Reynolds Haertle\r\n\r\nToate cartile sunt publicate de editura Teora.\r\n\r\nh2. ONI 2005\r\n\r\nAsa cum bine stii, ne mai despart 8 zile de ONI! Site-ul oficial al olimpiadei de informatica este \'http://olimpiada.info/\':http://olimpiada.info/ . Gasesti acolo tot ce doresti sa afli despre ONI, OJI si ONI by NET.\r\n\r\nDaca nu te-ai calificat la ONI, ai ocazia sa participi virtual la olimpiada! Afla mai multe la \'http://olimpiada.info/bynet/\':http://olimpiada.info/bynet/. Inscrierile au inceput deja!\r\n\r\nEchipa info.devNet iti ureaza mult succes!',1,'public',NULL,NULL),('blog/concursul-bitwise','Concursul BitWise','2005-02-07 00:00:00','2005-02-07 00:00:00','h1. Concursul BitWise\r\n\r\nConcurs de programare pe echipe. Dureaza 12 ore, are zece probleme, pot participa echipe de cate doi. Problemele se pot submita de maxim 10 ori, se evalueaza dupa submit, si sunt punctaje partiale. Mai multe detalii gasiti \"aici\":http://www.bitwise.iitkgp.ernet.in/ si va puteti inregistra pana in 7 februarie. Concursul se desfasoara pe data de 13 februarie. Inainte de inregistrare cititi FAQ si regulile concursului.\r\n',1142,'protected',NULL,NULL),('documentatie/pagina-de-fil','dsfdsfdsfdsina-de-fil','2006-11-26 22:14:35','2006-11-26 22:14:35','Scrie aici desfdsfdsfdsfds',1142,'public',NULL,NULL),('blog/iopc-international-online-programming-contest','IOPC - The International Online Programming Contest','2005-02-07 00:00:00','2005-02-07 00:00:00','h1. IOPC - The International Online Programming Contest\r\n\r\nConcurs de programare pe echipe, pare similar cu bitwise, diferenta fiind ca echipele sunt de cate trei, sunt 12 probleme si concursul dureaza 24 de ore. Limbajele de programare sunt C/C++/Java. Adresa este: \"[1]\":http://www.techkriti.org/competitions.php?eid=2&subid=2. Pentru a participa trebuie mai intai sa va inregistrati echipa. Concursul se desfasoara pe data de 20 Februarie.\r\n\r\n\r\n',1142,'protected',NULL,NULL),('preoni-2006/presa','Aparitii in presa, preONI 2006','2006-11-26 04:50:22','2006-11-27 14:42:55','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Aparitii in presa\r\n\r\n\'Comunicat de presa IP Devel\':http://www.ipdevel.ro/index.php?mid=137&rid=22&pg=268',1,'protected',NULL,NULL),('preoni-2006/runda-1','Runda 1, preONI 2006','2006-11-25 01:13:10','2008-02-02 15:09:18','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Runda 1\r\n\r\nConcursul s-a desfasurat sambata, 19 noiembrie, la ora 09:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nh2. Comisii\r\n\r\nh3. Stiintific\r\n\r\n* clasa a 9-a (si gimnaziu)\r\n** Tiberiu Florea\r\n** Silviu Ganceanu \r\n* clasa a 10-a\r\n** Cosmin Negruseri\r\n** Adrian Diaconu \r\n* clasele 11-12\r\n** Mircea Pasoi\r\n** Daniel Pasaila \r\n\r\nh3. Organizatoric\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* Cristian Strat\r\n* Crestez Leonard \r\n\r\nh2. Solutii\r\n\r\nSolutiile problemelor le puteti gasi \"aici\":preoni-2006/runda-1/solutii\r\n\r\nh2. Clasa a 9-a si gimnaziu (\'Clasament\':preoni-2006/runda-1/clasament-9)\r\n\r\n!>preoni-2006/runda-1?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni61a\" pager_style=\"none\") ==\r\n\r\nh2. Clasa a 10-a(\'Clasament\':preoni-2006/runda-1/clasament-10)\r\n\r\n!>preoni-2006/runda-1?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni61b\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2006/runda-1/clasament-11-12)\r\n\r\n!>preoni-2006/runda-1?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni61c\" pager_style=\"none\") ==\r\n\r\n==include(page=\"template/preoni-2006/footer\")==\r\n',1,'protected',NULL,NULL),('blog/preoni-2005-runda-2','preONI, runda #2','2005-02-21 00:00:00','2005-02-21 00:00:00','h1. preONI 2005, runda #2\r\n\r\nAvem doua vesti bune pentru tine:\r\n\r\n# runda #2 a concursului preONI se va desfasura Miercuri, 23 februarie ora 16:00 - vezi mai jos informatii detaliate.\r\n# Microsoft Romania ofera PREMII SURPRIZA (yay!) primilor trei concurenti de la fiecare grupa!\r\n\r\nDorim sa multumim mult celor care ne-au ajutat in aceasta directie:\r\n\r\n* Microsoft Romania, programul \'\"Parteneri pentru Educatie\"\':http://www.microsoft.com/romania/educatie/pil/default.mspx\r\n* prof. Emil Onea\r\n* Octavian Costache\r\n\r\nNu iti face griji daca nu ai participat la prima runda preONI. Clasamentul final se va calcula pe baza punctajelor obtinute in runda #2 si #3, punctajele din runda #1 fiind folosite doar pentru departajare in caz de egalitate.\r\n\r\nOricine este invitat sa participe, insa, eligibili pentru premii sunt doar acei concurenti din ciclul de invatamant pre-universitar care nu fac parte din echipa infoarena.\r\n\r\nMiercuri, 23 februarie, ora 16:00 va avea loc a doua runda preONI. Formatul concursului: 2 grupe (clasele IX-X, XI-XII), 3 probleme in fiecare grupa si un timp de lucru de 4h. Evaluarea va incepe la 15min dupa terminarea timpului de lucru si va putea fi urmarita in timp real la sectiunea \"statistici\".\r\n\r\nPropunatorii problemelor din runda #2 sunt:\r\n\r\n* clasele IX - X: Dan Popovici, Cosmin Negruseri\r\n* clasele XI - XII: Silviu Ganceanu, Adrian Vladu, Dan Fechete\r\n\r\nNoteaza-ti! :)\r\nMiercuri la ora 16:00 ai concurs cu premii Microsoft pe infoarena!\r\n\r\nPana la inceperea concursului, te invitam sa citesti ultimele articole publicate pe portalul info.devNet. Printre acestea, se numara:\r\n\r\n* Skiplists, Stancu Mara Sorin\r\n* preONI 2005 runda #1 - solutii, Mircea Pasoi\r\n\r\nAsa cum bine stii, mai e aproape o saptamana pana la\r\nOlimpiada Judeteana de Informatica (26/27 februarie)!\r\n\r\nIti uram mult succes!\r\n\r\nAsteptam intrebarile / sugestiile tale pe \'forum\':http://forum.infoarena.ro/',1,'protected',NULL,NULL),('summer-challenge-unu/clasament','Clasament Summer Challenge Unu','2006-11-23 00:53:44','2006-11-24 17:47:39','h1. Clasament \'Summer Challenge Unu\':summer-challenge-unu\r\n\r\n==Rankings(rounds=\"summer06\")==',961,'protected',NULL,NULL),('blog/final-preoni-2005-runda-2','preONI 2005, runda #2 s-a incheiat','2005-02-26 00:00:00','2005-02-26 00:00:00','h1. preONI 2005, runda #2 s-a incheiat\r\n\r\nRunda #2 a concursului preONI s-a incheiat. Rezultatele sunt disponibile in sectiunea \"statistici\" a site-ului si problemele au fost mutate in arhiva.\r\n\r\nAutorii problemelor au scris un \'articol\':preoni-2005/runda-2/solutii despre aceasta runda - rezultate si idei de rezolvare.\r\n\r\nFelicitari tuturor participantilor!\r\n\r\nPana la urmatoarea runda, *BAFTA LA OJI*!',961,'protected',NULL,NULL),('preoni-2006/premii','Sponsori si premii, preONI 2006','2006-11-25 18:08:17','2006-11-27 16:14:16','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Sponsori si premii\r\n\r\nh2. Sponsori\r\n\r\n*Mesaj din partea IP Devel*\r\n\r\nLa IP Devel incurajam elevii si studentii talentati in dezvoltarea de solutii informatice. Incurajam talentul si il ajutam prin programe de dezvoltare special concepute.\r\n\r\nStudentii pot astfel sa isi continue studiile si in acelasi timp sa se formeaze profesional, implicindu-se in proiecte interesante, intr-un mediu de lucru tinar si dinamic.\r\n\r\nMai multe detalii puteti vizualiza pe pagina noastra unde va si puteti inregistra pentru a lua parte la un astfel de program.\r\n\r\nh2. Premii\r\n\r\nConcursul *preONI* este recunoscut ca o initiativa indrazneata a catorva elevi si studenti pasionati de informatica, menita sa ii ajute pe cei la fel de pasionati ca si ei in pregatirea pentru performnta. Succesul acestei initiative este dovedit prin complexitatea concursului de la an la an, astfel incat anul acesta, datorita generozitatii sponsorilor, echipa infoarena ofera concurentilor ceva mai mult decat satisfactia rezolvarii problemelor.\r\n\r\nPentru fiecare dintre cele trei grupe, primii 10 elevi din clasament in urma desfasurarilor probelor online vor fi premiati cu o diploma de finalist al concursului *preONI 2006* si o \"tabara\":preoni-2006/finala de pregatire cu cazare si masa asigurate.\r\n\r\nCei 30 de elevi vor avea sansa sa interactioneze cu membrii echipei infoarena si cu ceilalti membrii ai comunitatii infoarena si sa invete de la si impreuna cu acestia. Tabara va fi de asenemea un prilej de a ii rasplati pe cei mai buni dintre cei mai buni. Acest lucru se va face prin organizarea unei runde finale, asemanatoare cu rundele online. Punctajele din acesta runda vor fi independente de cele acumulate la rundele online, iar primii 3 clasati vor avea parte de urmatoarele premii:\r\n\r\n|_. Grupa|_. Locul I|_. Locul II|_. Locul III|\r\n|_. Clasa a IX-a(si gimnaziu)|300 RON|200 RON|100 RON|\r\n|_. Clasa a X-a|300 RON|200 RON|100 RON|\r\n|_. Clasele XI -XII|300 RON|200 RON|100 RON|\r\n\r\n==include(page=\"template/preoni-2006/footer\")==',13,'public',NULL,NULL),('template/preoni-2006/rankings','template/preoni-2006/rankings','2006-11-27 15:54:36','2006-12-01 18:13:27','==include(page=\"template/preoni-2006/header\")==\r\n\r\np{font-weight: bold}. &larr; \"preONI 2006 Homepage\":preoni-2006\r\n\r\nh1. Clasament preONI 2006, rundele de online de calificare\r\n\r\np={font-weight: bold}. \"Clasa a IX-a si gimnaziu\":preoni-2006/clasament-9 | \"Clasa a X-a \":preoni-2006/clasament-10 | \"Clasele XI-XII\":preoni-2006/clasament-11-12\r\n\r\n',13,'protected',NULL,NULL),('blog/aparitie-editoriala','Aparitie editoriala','2005-03-17 00:00:00','2005-03-17 00:00:00','h1. Aparitie editoriala\r\n\r\nEchipa devNet va recomanda cartea \"Fundamentele programarii, clasa a IX-a\" , autori \"Dana Lica\":mailto:danal182001@yahoo.com si \"Mircea Pasoi\":mailto:bogdanpasoi@yahoo.com. Culegerea respecta programa scolara a claselor a IX-a de informatica si isi propune sa reprezinte un instrument util atat in munca de initiere in programare cat si in cea de performanta, cuprinzand peste 100 de probleme pentru concursuri si olimpiade.\r\n\r\nPentru detalii suplimentare privind cartea puteti contacta pe oricare dintre autori (faceti click pe nume pentru adresa de mail).\r\n\r\nh2. Cuprins\r\n\r\n# Capitol 1 \r\nProgramarea structurata si instructiuni in limbajul de programare Pascal/C/C ++\r\n## Structura liniara si alternativa - Instructiunea de atribuire si conditionala\r\n### Teste cu alegere multipla si duala\r\n### Teste cu itemi semiobiectivi\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Structuri repetitive - instructiuni repetitive\r\n### Teste cu alegere multipla si duala\r\n### Teste cu itemi semiobiectivi\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Probleme de concurs ce proceseaza date simple\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n# Capitol 2 \r\nTipuri de date structurate\r\n## Tabloul unidimensional\r\n### Teste cu alegere multipla si duala\r\n### Teste cu itemi semiobiectivi\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Tabloul bidimensional\r\n### Teste cu alegere multipla si duala\r\n### Teste cu itemi semiobiectivi\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Fisiere text\r\n### Teste cu alegere multipla si duala\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Probleme de concurs ce proceseaza date structurate\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Indicatii si raspunsuri\r\n',961,'protected',NULL,NULL),('blog/concurs-microsoft-you-can-make-a-difference','Concurs Microsoft: You Can Make a Difference','2005-03-19 00:00:00','2005-03-19 00:00:00','h1. Concurs Microsoft: You Can Make a Difference\r\n\r\n\"You Can Make a Difference\" este o competitie pentru elevii de liceu care propun proiecte de aplicatii software adresate entitatilor cu obiect de activitate caritabil. Microsoft pune la dispozitia celor interesati software-ul necesar si suportul tehnic (conectare cu dezvoltatori Microsoft).\r\n\r\nBanii acordati prin acest concurs vor fi folositi in trei directii:\r\n\r\n* bursa pentru elevul/eleva premiat(a).\r\n* resurse financiare pentru implementarea proiectului.\r\n* actualizare, din punct de vedere tehnologic, a scolii din care face parte elevul/eleva premiat(a).\r\n\r\nDead line de inscriere este 30 aprilie. Mai multe informatii gasiti la:\r\n\r\n* \'http://ro.theSpoke.net\':http://ro.theSpoke.net\r\n* \'http://ro.thespoke.net/ycmd/info.aspx\':http://ro.thespoke.net/ycmd/info.aspx\r\n* \'http://ro.thespoke.net/BlogReader/SingleEntry.aspx?ID=1455\':http://ro.thespoke.net/BlogReader/SingleEntry.aspx?ID=1455',1142,'protected',NULL,NULL),('preoni-2005/runda-3/solutii','preONI 2005 runda #3 - solutii','2005-03-20 00:00:00','2008-08-13 13:20:40','h1. preONI 2005 runda #3 - solutii\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa devNet_)\r\n\r\nArticolul contine ideile de rezolvare ale problemelor propuse la ultima runda a concursului preONI ce s-a desfasurat pe data de 20 martie 2005, cat si comentarii legate de concurs. Si de aceasta data numarul de participanti a fost impresionat, cu siguranta datorita faptului ca in numai 5 zile incepe ONI!\r\n\r\nSetul de probleme a fost mai greu de data aceasta, special pentru a testa concurentii cu probleme cat mai asemanatoare cu stilul ONI. Speram ca fiecare participant a invatat cate ceva in urma acestui concurs si asteptam pareri si sugestii pentru viitor pe \"forum\":http://http://forum.infoarena.ro/.\r\n\r\nh2. Clasele 9-10\r\n\r\nh3. Clasament\r\n\r\n==Rankings(rounds=\"preoni53a\" display_entries=\"6\" pager_style=\"none\")==\r\n\r\nh3. Barman\r\n\r\n(solutie corecta oferita de ==user(user=\"spatarel\" type=\"tiny\")==, 20 noiembrie 2005)\r\n\r\nMetoda folosita este una brute-force si se bazeaza pe cateva observatii. Pentru a determina solutia optima sortam sirul valorilor bauturilor si ii generam toate permutarile circulare in vectorul obt. De aici, problema noastra ramane transformarea de cost minim a vectorului initial a in vectorul obt folosind operatiile permise. Dintre toate permutarile circulare, evident o vom alege pe cea care cere un cost minim al operatiilor. In primul rand se observa ca nu are nici un rost sa deranjam camerele care au bautura ceruta ({$a{~i~} = obt{~i~}$}), deci pe Paftenie nu il vor preocupa acestea. In al doilea rand este de remarcat ca ar fi inutil ca Paftenie sa deplaseze mai mult de un pahar intre doua camere deoarece am considera un caz redundant. De ce? Ar fi libere numai camerele $c{~1~}$ si {$c{~2~}$}, din care provin cele doua pahare de pe tava. Cu doua pahare pe tava ar putea sa mearga intr-o camera $c{~3~}$ diferita de $c{~1~}$ si {$c{~2~}$}, dar ar fi inutil, caci nici pe tava nici in camera nu mai poate depozita vreun pahar.\r\n\r\nAstfel, problema se reduce la a gasi, pentru fiecare bautura care nu se afla pe locul ei, o pozitie optima, pe care daca o asezam, vom obtine un cost global minim. Pentru simplitate, in continuare voi numi \"cuplaj\" mutarea unei bauturi pe o alta masa. Se poate oberva ca problema se poate imparti in mai multe sub-probleme independente: fiecare sub-problema va calcula cuplajul optim pentru toate bauturile de aceeasi valoare. Problemele sunt independente, deoarece pentru a pastra solutia optima globala, trebuie sa cuplam o bautura cu o masa pe care trebuie plasata acelasi tip de bautura.\r\n\r\nO metoda ar fi greedy: pentru fiecare bautura care nu e la locul ei, cautam cea mai apropiata masa pe care se poate pune - insa aceasta metoda este gresita.\r\n\r\nO alta metoda este cuplajul intr-un graf bipatit. Desi aceasta rezolvare este corecta, nu se incadreaza in timpul de executie. Deoarece trebuie efectuate $N$ cuplaje cu cate $2*N$ noduri fiecare, vom obtine o complexitate de {$O(N^5^)$}, supraestimata. Este posibil, totusi, ca in urma unor optimizari puternice, si aceasta metoda sa obtina punctaj mare.\r\n\r\nTotusi, mai exista si o alta metoda mult mai simpla si mai rapida, care se bazeaza pe cateva observatii suplimentare: datorita sortarii pe care am efecutat-o la inceputul algoritmului si a permutarilor circulare, mesele pe care trebuie plasata aceeasi bautura, sunt plasate fie secvential, fie in doua secvente, de la $1$ la $k$ si de la $l$ la {$N$}. De asemenea, deoarece am eliminat cazurile in care {$a{~i~} = obt{~i~}$}, cele doua cazuri, fara a pirde dingeneralitate, se reduc la unul singur: in intervalul $1$ - $k$ exista numai bauturi care trebuie cuplate; in intervalul $k+1$ - $l$ exista numai mese care trebuie cuplate; in intervalul $l+1$ - $N$ exista numai bauturi care trebuie cuplate. (Al doilea caz este simetric, si deoarece mesele pot fi privite ca bauturi, si invers, putem reduce al doilea caz la primmul.)\r\n\r\nProblema se rezolva partitionand multimea meselor in doua secvente: mesele din prima secventa se vor cupla cu bauturile din intervalul $1$ - {$k$}, iar mesele din a doua secventa cu bauturile din intervalul $l+1$ - {$N$}. Se poate observa ca oricum s-ar realiza cele doua cuplaje, costul golbal va fi acelasi. In plus, orice alt cuplaj global care nu tine cont de aceasta impartire va obtine un const global mai mare. Astfel, se garanteaza ca aceasta metoda va calcula corect costul minim global.\r\n\r\nAlgoritmul care impleneteaza acest cuplaj este foarte simplu: pentru fiecare bautura care nu se alfa la locul ei ({$a{~i~} = obt{~i~}$}), se cauta prima masa necuplata pe care se poate plasa bautura.\r\n\r\nh3. Cifre\r\n\r\nPentru a afla probabilitatea ceruta trebuie sa aflat cate numere exista in intervalul [{$A..B$}] cu cel putin $K$ cifre de {$C$}. Pentru asta vom construi o functia $f(x)$ care va returna cate numere sunt in intervalul [{$0..x-1$}] care au cel putin $K$ cifre de {$C$}. Astfel rezultatul va fi {$f(B+1)-f(A)$}. Functia $f(x)$ va rula in complexitate $O(lg x)$ parcurgand numarul $x$ cifra cu cifra. Ca sa realizam acest lucru avem nevoie de urmatoarele informatii:\r\n$cnt(i, j)$ = cate numere intre $0$ si $10^i^-1$ contin $j$ cifre de $C$ (vom considera ca numerele pot avea {$0$}-uri in fata, de exemplu: $0003$ are $3$ cifre de {$0$})\r\nAcest numar se poate calcula fie printr-o formula matematica folosind combinari sau cu o relatia de recurenta (independenta de variabila {$C$}):\r\n\r\n* $cnt(i, j) = 9 * cnt(i-1, j) + cnt(i-1, j-1)$\r\n\r\nDe asemenea mai avem nevoie de urmatoarele informatii:\r\n$cnt0(i, j)$ = cate numere care nu au {$0$}-uri in fata intre $0$ si $10^i^-1$ contin $j$ cifre de {$C$}. Relatia de recurenta va fi in functie de {$C$}:\r\n\r\n* daca $C=0$ atunci $cnt0(i, j) = cnt0(i-1, j) + 9 * cnt(i-1, j)$\r\n* altfel $cnt0(i, j) = cnt0(i-1, j) + 8 * cnt(i-1, j) + cnt(i-1, j-1)$\r\n\r\nCele doua matrici au marimi $lgB*K$ deci construirea lor va avea complexitate {$O(lg B*K)$}. Odata disponibile aceste informatii se poate realiza destul de usor functia {$f(x)$}. Nu voi prezenta aici toate detaliile deoarecere apar mai multe cazuri (in special cand {$C = 0$}), lasand ca exercitiu pentru cititor. \r\n\r\nO alta rezolvare posibila ar fi calcularea functiei $f(x)$ in $O(2^lg10(x)^*lg10(x))$ astfel: pe fiecare pozitie intre $0$ si $lg10(x)$ avem doua variante, fie punem cifra {$C$}, fie alta cifra. Pentru fiecare astfel de configuratie cu cel putin $K$ cifre de $C$ se poate determina dintr-o parcurgere cate numere exista $< x$ care au cifre de $C$ in pozitiile respective.\r\n\r\nh3. Farfurii\r\n\r\nProblema cere construirea unei permutari de lungime $N$ cu $K$ inversiuni, minima lexicografic. O prima rezolvare de complexitate $O(N^2^)$ ar fi construirea permutarii element cu element. Cu cat un element este mai mare pe o anumita pozitie cu atat formeaza mai multe inversiuni, astfel ca incercam sa punem pe fiecare pozitie un element cat mai mic astfel: pe pozitia {$i$}, daca $K &le; (N-i)*(N-i-1)/2$ putem pune cel mai mic element disponibil (pentru ca in bucata de $N-i$ ramasa putem construi cel putin {$(N-i)&#0042;(N-i-1)/2$} inversiuni), altfel punem al {$K-(N-i)&#0042;(N-i-1)/2$} element disponibil. Aceasta modalitate de constructie garanteaza ca permutarea este minima lexicografic. O implementare directa, cum am zis, are complexitate $O(N^2)$ si ia {$40-60p$}. Pentru $100p$ se poate folosi un arbore de intervale (ca la problema \"concurs\":http://campion.edu.ro/problems.php?mode=view_round&group_number=3&year=2004&round_number=9 de la .campion 2004, runda 9) reducand complexitatea la {$O(N*lg N)$}. O asemenea solutie, desi ia {$100p$}, necesita cunostiinte de structuri de date avansate care depasesc nivelul de cunostiinte general al unui concurent pentru clasele {$9-10$}. O rezolvare $O(N)$ mult mai simpla se bazeaza pe urmatoarea observatie:\r\nO permutare de lungime $i$ are cel mult $i*(i-1)/2$ inversiuni cand numerele sunt in ordine descrescatoare.\r\nAstfel, daca $K$ e de forma $M*(M-1)/2$ permutarea minima lexicografic cu $K$ inversiuni va fi:\r\n\r\n$1, 2, 3, ... N-M, N, N-1, N-2, ... N-M+1$\r\n\r\nCele $K$ inversiuni apar in ultimele $M$ elemente. Daca in aceasta permutare mutam un element $N-x$ imediat inaintea lui $N$ numarul de inversiuni scade cu {$x$}. Astfel, daca $K>M*(M-1)/2$ construim permutarea\r\n\r\n$1, 2, 3, ... N-M-1, N, N-1, N-2, ... N-M$\r\n\r\n(care are $(M+1)*M/2$ inversiuni) si mutam elementul {$N-((M+1)*M/2-K$}) imediat inaintea lui {$N$}, astfel scadem numarul de inversiuni la {$K$}. Este evident ca permutarea astfel construita este minima lexicografic. Algoritmul descris are complexitate {$O(N)$}.\r\n\r\nh2. Clasele 11-12\r\n\r\nh3. Clasament\r\n\r\n==Rankings(rounds=\"preoni53b\" display_entries=\"5\" pager_style=\"none\")==\r\n\r\nSetul de probleme, mai greu de data aceasta, se pare ca a pus in dificultate majoritatea concurentilor. Desi problemele Critice si Poligon nu erau foarte dificile in faza de concepere a algoritmului se pare ca implementarea a fost cea care i-a speriat pe multi dintre participanti. \r\n\r\nh3. Critice\r\n\r\nProblema este o aplicatie a algoritmului de aflare a fluxului maxim dintr-o retea. Se construieste o retea, nodurile fiind adaposturile iar capacitatile muchiilor fiind egale cu rezistentele tunelurilor. Prima solutie, care trece $~ 50%$ din teste, este urmatoarea:\r\n\r\n# Se calculeaza fluxul maxim in reteau construita\r\n# Pentru fiecare muchie (separat) se creste capacitatea ei cu o unitate si se mai ruleaza inca o data algoritmul de flux maximi. Daca fluxul maxim a crescut atunci muchia este critica.\r\n\r\nSe observa ca acest algoritm are o complexitate considerabila si trebuie sa ne gandim la ceva mai bun. Primul lucru inteligent pe care il putem observa este ca muchiile critice sunt muchiile care, dupa ce am rulat odata algoritmul de flux maxim, sunt saturate (am folosit toata capacitatea ei intr-o directie sau cealalta). Totusi nu toate muchiile saturate sunt si critice. Pentru a fi mai exacti, muchiile critice sunt acele muchii saturate care au propietatea ca de la sursa retelei (nodul {$1$}) este drum in graful rezidual (adica graful care ne ramane daca eliminam muchiile saturate) la unul din capetele ei si respectiv de la destinatie (nodul {$N$}) la celalalt capat. Asadar se contureaza algoritmul:\r\n\r\n# Se ruleaza odata algoritmul de flux maxim\r\n# Cu ajutorul a doua parcurgeri a grafului rezidual stabilim pentru fiecare muchie critica daca propietatea este adevarata\r\n\r\nComplexitatea (teoretica) va fi $O(M^2^*N + M)$ dar este supraestimata algoritmul de flux ruland mult mai rapid.\r\n\r\nh3. Ferma\r\n\r\nLa prima vedere, problema pare abordabila cu programare dinamica. O simpla rezolvare care nu tine cont de faptul ca sirul este circular este urmatoarea: $A{~i,j~}$ = productivitatea maxima pentru a face $i$ strangeri din primele $j$ sectoare; evident raspunsul va fi {$A(K, N)$}. Relatia de recurenta:\r\n\r\n* $A{~i,j~}$ = $max (A{~i,j-1~}, A{~i-1,k~} + suma (P{~k~},P{~k+1~}..P{~j~})$ pentru fiecare {$k<j$}, iar $P$ reprezinta vectorul de productivitati.\r\n\r\nO astfel de implementare are complexitate $O(N^2^*K)$ si nu se va incadra in timp. Fie {$S{~i~} = P{~1~}&#0043;P{~2~}&#0043;...&#0043;P{~i~}$}, atunci putem rescrie relatia de recurenta astfel:\r\n\r\n* {$A{~i,j~} = max(A{~i,j-1~}, A{~i-1,k~} + S{~j~} - S{~k~})$}, pentru fiecare $k<j$\r\n\r\nAl doilea termen este de forma $A{~i-1,k~} - S{~k~}$ (termen independent de {$j$}) + {$S{~j~}$}. Astfel din linia $i-1$ a matricii de dinamica pentru fiecare $j$ ne trebuie valoarea maxima $A{~i-1,k~}-S{~k~}$ cu {$k<j$}. O prima idee ar fi ca pe masura ce construim linia i sa inseram elementele din linia $i-1$ intr-un max-heap astfel reducand complexitatea la {$O(N*lgN*K)$}.\r\n\r\nCei care au rezolvat probleme precum \"secventa\":problema/secventa de pe infoarena, \"trans\":problema/trans de la barajul de la ONI 2004 sau divide de la USACO Ianuarie 2005 vor realiza imediat ca putem reduce complexitatea la $O(N*K)$ folosind structura necesara in rezolvarea acelor probleme si anume o coada (in literatura de specialitate se intalneste ca \"deque with heap order\"). Aceasta structura a mai fost tratata si in solutiilor problemelor prezentate mai sus, deci nu voi intra in detalii. Este evident ca un algoritm de complexitate $O(N*K)$ se incadreaza in timp, dar mai apare in calcul faptul ca sirul este circular. Un algoritm $O(N*K)$ care nu trateaza acest lucru ia $40$ de puncte. O prima idee ar fi sa aplicam acelasi algoritm pe fiecare permutare circulara dar se ridica complexitatea iar la {$O(N^2^*K)$}. Aceasta abordare ar trebui sa obtina intre $50$ si $60$ de puncte. Putem trata circularitatea sirului tot in $O(N*K)$ incercand sa obtinem o secventa care contine elemente $N$ si {$1$}. Putem realiza acest lucru astfel:\r\n\r\n* dupa ce realizam prima data dinamica, reinitializam linia $1$ astfel $A{~1,i~} = S{~i~}$\r\n* aplicam din nou dinamica -> de data aceasta algoritmul va fi obligat sa intoarca rezultate care contin neaparat elementul $1$ intr-o secventa din cauza initializarii\r\n* pentru fiecare pozitie $i &le; N$ comparam rezultatul $A{~i,K~}+S{~N~}-S{~i~}$ (adaugam la secventa care il contine pe $1$ o bucata care il contine pe {$N$}) cu cel mai bun obtinut\r\n\r\nAstfel, problema este rezolvabila in complexitate {$O(N*K)$}.\r\n\r\nh3. Poligon\r\n\r\nProblema cere sa determinam cate puncte din cele $M$ sunt in interiorul poligonului. O abordare imediata a acestei probleme ar fi sa determinam pentru fiecare punct in $O(N)$ daca este sau nu in interiorul poligonului. Exista mai multe moduri de a rezolva acest lucru. Un mod ar fi sa ducem o semidreapta pornind din punctul nostru si sa vedem de cate ori intersecteaza laturile poligonului: daca intersecteaza poligonul de un numar par de ori atunci inseamna ca punctul este in exterior, iar daca ea intersecteaza de un numar impar de ori laturile poligonului inseamna ca punctul este in interior. O alta modalitate: calculam suma unghiurilor pe care le fac extremele laturilor cu punctul nostru (unghiurile sunt luate pozitive sau negative dupa cum cele $3$ puncte ce formeaza unghiul sunt in sens trigonometric sau orar), daca suma unghiurilor pentru toate laturile e $0$ atunci punctul e in exteriorul poligonului, iar daca suma unghiurilor e $2*Pi$ atunci punctul e in interiorul poligonului, pentru mai multe detalii puteti\r\nsa va uitati pe urmatoarele pagini: \"[1]\":http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html \"[2]\":http://softsurfer.com/Archive/algorithm_0103/algorithm_0103.htm\r\n\r\nDimensiunile datelor de intrare ne sugereaza ca trebuie sa acceleram determinarea pozitiei punctelor fata de poligon. Daca poligonul ar fi convex, este usor sa facem acest test in {$O(log N)$}: consideram un varf al poligonului si semidrepte ce pleaca din el spre celelalte varfuri, cu cautare binara gasim in ce sector determinat de doua semidrepte intra punctul pentru care vrem sa determinam incluziunea in poligon, dupa ce gasim sectorul testul de incluziune se reduce la determinarea incluziunii intr-un triunghi. Aceasta metoda eleganta si simpla merge pentru poligon convex, dar pentru unul oarecare trebuie sa gasim o alta abordare.\r\n\r\nPentru poligoane concave, mergand pe aceeasi idee, impartirea in zone pentru care este mai usor sa determinam incluziunea se va face un pic diferit. Sortam coordonatele $x$ ale punctelor poligonului si ducem prin fiecare coordonata $x$ distincta cate o dreapta verticala. Se formeaza astfel niste benzi verticale intersectate de laturile poligonului. Pentru fiecare banda tinem minte ce laturi ale poligonului intersecteaza aceasta banda si sortam aceste laturi pe verticala dupa mijlocul segmentului de intersectie al laturii cu banda. Acum pentru a determina daca un punct e in interiorul poligonului, determinam cu cautare binara mai intai banda din care face parte si apoi pentru banda respectiva deasupra cator segmente se afla, daca punctul e deasupra unui numar par de segmente atunci punctul e in exterior si daca e deasupra unui numar impar e interior. Astfel rezolvarea noastra are complexitatea $O(N^2^ log N)$ in faza de preprocesare si $O(log N)$ pentru a determina pentru fiecare punct daca este interior sau\r\nexterior poligonului. Complexitatea totala va fi {$O(N^2^ log N + M log N)$}.\r\n\r\n',6756,'public',NULL,NULL),('blog/final-preoni-2005','preONI 2005 s-a incheiat!','2005-03-21 00:00:00','2005-03-21 00:00:00','h1. preONI 2005 s-a incheiat!\r\n\r\nRunda #3 a concursului preONI s-a incheiat, impreuna cu intreg concursul preONI 2005! Rezultatele finale au fost publicate si problemele au fost mutate in arhiva dupa ~1h de la expirarea timpului de lucru. ;) Autorii problemelor au publicat un \'articol\':preoni-2005/runda-3/solutii despre aceasta runda, rezultate si idei de rezolvare: . Asteptam parerile si sugestiile tale pe \'forum\':http://forum.infoarena.ro!\r\n\r\nAceasta a fost ultima runda a concursului preONI, editia 2005. Speram ca efortul nostru si al sponsorilor nostri ti-a fost de folos in vreun fel.\r\n\r\nMicrosoft Romania ofera premii primilor 3 participanti de la fiecare grupa. Clasamentul se calculeaza pe baza punctajelor acumulate in runda #2 si #3, punctajele din runda #1 fiind folosite pentru departajare in caz de egalitate.\r\n\r\nh2. Castigatorii editei 2005 sunt...\r\n\r\nh3. Clasele IX - X (\'clasament complet\':preoni-2005/clasament-9-10)\r\n\r\n==Rankings(rounds=\"preoni52a|preoni53a\" display_entries=\"3\" pager_style=\"none\")==\r\n\r\nh3. Clasele XI - XII (\'clasament complet\':preoni-2005/clasament-11-12)\r\n\r\n==Rankings(rounds=\"preoni52b|preoni53b\" display_entries=\"3\" pager_style=\"none\")==\r\n\r\nFelicitari castigatorilor editei 2005! Acestia vor fi contactati prin email in vederea inmanarii premiilor Microsoft. Felicitari tuturor participantilor! Dorim sa multumim sponsorului nostru - Microsoft Romania - precum si D-lui. Prof. Emil Onea, studentului Octavian Costache si tuturor celor care ne-au oferit sugestii si ne-au sprijinit in organizarea editiei 2005 a concursului preONI!\r\n\r\nIti uram mult succes la ONI (by NET) si in continuare!',961,'protected',NULL,NULL),('warm-up-2004','Concurs de incalzire','2006-11-24 16:12:38','2006-11-24 16:41:40','h1. Concurs de incalzire\r\n\r\nConcursul s-a desfasurat pe 14/11/2004 si a avut 2 grupe si 3 probleme pentru fiecare grupa. Problemele au fost adaugate in \'arhiva\':arhiva, iar un articol cu solutiile este disponibil \'aici\':warm-up-2004/solutii.\r\n\r\nh2. Grupa mica, clasele 9-10 (\'Clasament\':warm-up-2004/clasament-9-10)\r\n\r\n!>warm-up-2004?logo.gif!\r\n\r\n== Tasks(round_id=\"filip1\" pager_style=\"none\") ==\r\n\r\nh2. Grupa mare, clasele 11-12 (\'Clasament\':warm-up-2004/clasament-11-12)\r\n\r\n!>warm-up-2004?logo2.gif!\r\n\r\n== Tasks(round_id=\"filip2\" pager_style=\"none\") ==',1,'protected',NULL,NULL),('summer-challenge-2','Summer challenge 2','2006-11-24 16:34:20','2007-03-19 10:53:57','h1. Summer challenge 2\r\n\r\nConcursul s-a desfasurat  Vineri, 11 august 2006, ora 12:00 pe o durata de 5h. S-au propus spre rezolvare 3 probleme. Problemele au fost adaugate in \'arhiva\':arhiva.\r\n\r\nSolutiile problemelor le puteti gasi \"aici\":summer-challenge-2/solutii.\r\n\r\nh2. \'Clasament\':summer-challenge-2/clasament\r\n\r\n!>summer-challenge-2?logo.jpeg!\r\n\r\n== Tasks(round_id=\"summer2\" pager_style=\"none\") ==',1,'protected',NULL,NULL),('pregatire-online-pentru-bacalaureatul-la-informatica','Pregatire online pentru bacalaureatul la informatica','2005-04-27 00:00:00','2006-11-24 00:34:01','h1. Pregatire online pentru bacalaureatul la informatica\r\n\r\nIncepand de astazi, site-ul \"infoarena\":http://infoarena.ro/ vine in sprijinul elevilor de liceu gazduind un amplu program de pregatire online la disciplina informatica din cadrul examenului de bacalaureat.\r\n\r\nIn cadrul acestui program de pregatire, profesori prestigiosi de informatica din tara vor pune la dispozitia elevilor o lista de subiecte de bacalaureat de doua tipuri:\r\n\r\n# Probleme de informatica; Pentru aceste subiecte, elevii vor trebui sa conceapa si sa redacteze solutii complete intr-un limbaj de programare la alegere. Site-ul dispune de un evaluator automat capabil sa noteze instantaneu solutiile propuse de elevi.\r\n# Teste de tip grila de informatica; Elevii au posibilitatea sa rezolve astfel de teste de tip grila. Ca si la problemele de informatica, raspunsurile trimise se evalueaza pe loc.\r\n\r\nLista de probleme si de teste grila se va imbogati saptamanal iar pe parcursul pregatirii se va construi un clasament al rezolvitorilor de probleme / teste grila.\r\n\r\nMentionam ca participantii le pregatire au posibilitatea sa discute pe marginea materialelor de pregatire si sa solicite explicatii prin intermediul \"forumului\":http://forum.infoarena.ro/.\r\n\r\nSponsorul principal al acestui proiect este \"Microsoft Romania\":http://www.microsoft.com/romania/ - prin intermediul programului \"Parteneri pentru educatie\":http://www.microsoft.com/romania/educatie/.\r\n\r\n',1142,'public',NULL,NULL),('preoni-2006/clasament-11-12','Clasament preONI 2006, Clasele XI-XII','2006-11-25 03:30:58','2006-12-01 18:14:13','== include(page=\"template/preoni-2006/rankings\") ==\r\n\r\nh2. Clasele XI-XII\r\n\r\n==Rankings(rounds = \"preoni61c|preoni62c|preoni63c|preoni64c\")==',13,'protected',NULL,NULL),('articole/template-matematica','articole/template-matematica','2008-12-13 15:03:37','2009-04-11 14:12:15','* !>articole/template-matematica?cercuri.png! \'Probleme cu puncte laticiale\':probleme-cu-puncte-laticiale\r\n* \'Teoria jocurilor: numerele Sprague-Grundy\':numerele-sprague-grundy\r\n* \'Coduri Gray\':coduri-gray\r\n* \'Teorema chineza a resturilor\':teorema-chineza-a-resturilor\r\n* \'Minimal enclosing circle\':minimal-enclosing-circle\r\n* \'The Monty Hall Problem\':the-monty-hall-problem\r\n* \'Ciurul lui Eratostene\':ciurul-lui-eratostene\r\n*{display: %display%} \'Algoritmul lui Euclid\':algoritmul-lui-euclid',3146,'protected',NULL,NULL),('blog/rezultate-ioi','Rezultate IOI','2006-08-19 00:00:00','2006-08-19 00:00:00','h1. Rezultate IOI\r\n\r\nIata rezultatele de la Olimpiada Internationala de Informatica din Mexic:\r\n\r\n|{background-color:gold}. Mircea Pasoi |{background-color:gold}. aur |\r\n|{background-color:gold}. Codrut Grosu |{background-color:gold}. aur |\r\n|{background-color:silver}. Tiberiu Florea |{background-color:silver}. argint |\r\n|{background-color:#9C6963}. Adrian Vladu |{background-color:#9C6963}. bronz |\r\n\r\nFelicitari echipei Romaniei si multe succese in continuare!',18,'protected',NULL,NULL),('usaco-nov-2005-divizia-gold','USACO nov 2005, divizia GOLD','2005-11-21 00:00:00','2006-11-22 02:29:35','h1. USACO nov 2005, divizia GOLD\r\n\r\n(Categoria _Competitii_, autor(i) _Adrian Diaconu_)\r\n\r\nEtapa din noiembria a fost una destul de usoara cu $17$ punctaje maxime printre care si $3$ romani:\r\n\r\n* Tiberiu Florea\r\n* Catalin Tiseanu \r\n* Adrian Vladu\r\n\r\n\"Teste si enunturile\":http://www.infoarena.ro/downloads?action=download&file=usaco_nov05.zip problemelor sunt disponibile in sectiunea Download.\r\n\r\nh2. Asteroids\r\n\r\nVom rezolva aceasta problema folosind un algoritm de cuplaj maxim. Se va construi un graf bipartit in care vom avea pe o parte coloanele matricii ({$1..n$}) pe cealalta liniile matricii ({$1..m$}). Vom avea muchie de la o linie la o coloana daca in pozitia respectiva se afla un bolovan ce trebuie distrus. Graful astfel construit va avea $n+m$ noduri si $k$ muchii (locurile unde sunt plasati bolovanii). Problema se reduce astfel la determinarea unui suport minim pe un graf bipartit care este echivalenta cu gasirea cuplajului maxim pe acest graf. Suportul minim inseamna o multime de noduri de cardinal minim astfel incat fiecare muchie are cel putin un capat in multime.\r\n\r\nPentru cei care nu sunt familiarizati cu algoritmul de cuplaj pot folosi un algoritm de flux maxim adaugand o sursa virtuala legata de toate nodurile ce reprezinta coloanele si o destinatie legata de toate nodurile ce reprezinta liniile. Capacitatile vor fi toate {$1$}. Fluxul maxim astfel determinat va fi egal cu cuplajul maxim. Complexitatea algoritmului de flux este $O(Flux*(nr_noduri+nr_muchii))$ si avand in vedere faptul ca fluxul poate fi maxim $n$ (deoarece o coloana nu se poate cupla de doua ori) se ajunge la {$O(n*(n+m+k))$}.\r\n\r\nh2. Grazing on the Run\r\n\r\nRezolvarea acestei probleme se face folosind metoda programarii dinamice. Se vor sorta coordonatele la care se afla lucrurile pe care doreste Bessie sa le culeaga apoi se vor construi matricile $min{~i,j,k~}$ si $timp{~i,j,k~}$ care vor avea urmatoarele semnificatii:\r\n\r\n* $min{~i,j,k~}$ - va retine costul necesar culegerii lucrurilor de pe pozitiile $i, i+1, ... , j$ la care se adauga timpul la care s-s terminat culesul acstor lucruri inmultit cu numarul de obiecte ramase ( $N - i + j - 1$ ) deoarece la acestea se va ajunge minim la timpul respectiv. $K$ va avea valoare $0$ sau $1$ in functie de capatul la care se afla Bessie la final ( stanga respectiv dreapta)\r\n* $timp{~i,j,k~}$ - va retine timpul necesar culegerii obiectelor $i, i+1, ..., j$ pentru a obtine minimul din $min{~i,j,k~}$\r\n\r\nSe observa ca in configuratia ({$i,j,k$}) se ajunge din starile ({$i,j-1,1$}), ({$i,j-1,0$}), ({$i+1,j,1$}), ({$i+1,j,0$}). Complexitatea de completare a matricii va fi {$O(n^2^)$}, in finala afisad minimul dintre {$min{~1,n,0~}$},{$min{~1,n,1~}$}. Memoria necesara va fi de $O(n)$ deoarece procesand matricea in ordinea cresterii lungimii intervalului ({$i,j$}) ne va fi necesara doar coloana precedenta.\r\n\r\nh2. Walk the Talk\r\n\r\nVom rezolva independent problema pentru fiecare cuvant aflat in dictionar. Vom nota $a{~i,j~}$ matricea cu litere, iar s{~i~} cuvantul pe care il analizam la un anumit moment, acesta avand lungimea {$L$}. Vom construi matricea $sum{~i,j,k~}$ in care se va retine numarul de moduri in care se obtine secventa $s{~1~}, s{~2~}, ... , s{~k~}$ folosind doar dreptungiul cu colturile in ({$1,1$}) si ({$i,j$}) din matricea de litere. Pentru a calcula configuratia ({$i,j,k$}) se numara intai cate se obtin pentru secventa $1..k$ pentru dreptunghiul respectiv fara a considera casuta $(i,j)$ ({$sum{~i-1,j,k~}+sum{~i,j-1,k~}-sum{~i-1,j-1,k~}$}) apoi daca avem $a{~i,j~}=s{~k~}$ adunam cate solutii avem pentru secventa $1..k-1$ pentru dreptunghiul respectiv mai putin casuta $(i,j)$ ({$sum{~i-1,j,k-1~}+sum{~i,j-1,k-1~}-sum{~i-1,j-1,k-1~}$}). In final solutia se va afla in {$sum{~n,m,L~}$}. Complexitatea construirii fiecare configuratii in parte este $O(1)$ deci in total va fi {$O(n*m*L)$}. Memoria necesara este {$O(n*m*L)$}, dar aceasta se poate reduce la $O(n*m)$ daca luam in considerare faptul ca la fiecare moment ne este necesar doar numarul de solutii pentru o secventa cu $1$ mai mica.\r\n\r\n',1,'public',NULL,NULL),('usaco-dec-2005-divizia-gold','USACO dec 2005, divizia GOLD','2006-01-05 00:00:00','2006-11-22 02:30:30','h1. USACO dec 2005, divizia GOLD\r\n\r\n(Categoria _Concursuri_, autor(i) _Daniel Pasaila, Mircea Pasoi_)\r\n\r\nIn acest articol veti gasi solutiile pentru problemele propuse la concursul USACO, editia din luna decembrie 2005, divizia GOLD. \"Teste si enunturile\":http://www.infoarena.ro/downloads?action=download&file=usaco.zip problemelor sunt disponibile in sectiunea Download.\r\n\r\nh2. Cow Patterns\r\n\r\nSolutia propusa in acest articol foloseste un algoritm de genul Rabin Karp. In aceasta problema alfabetul folosit este {$Sigma = {1, 2, ... S}$}, deci putem privi un sir de $K$ caractere consecutive ca reprezentand un numar in baza $S$ de lungime {$K$}. Spunem ca modelul este vectorul $P[1..K]$ iar textul dat este {$T[1..N]$}.\r\n\r\nFiind dat modelul $P[1..K]$ notam cu $p$ valoarea sa corespunzatoare in baza {$S$}. Intr-o maniera similara, fiind dat textul {$T[1..N]$}, notam cu $t{~s~}$ valoarea in baza $S$ a subsirului convertit {$T[s + 1...s + m]$}. In cazul in care gasim un subsir cu valoarea $t{~s~} = p$ atunci am gasit o potrivire a modelului pe text. Dificultatile care apar in rezolvarea problemei tin de convertirea sirului $T$ in timp real, dupa conditiile impuse de enuntul problemei. Astfel, ne deplasam cu un sablon de lungime $K$ spre dreapta. Pentru fiecare deplasament trebuie sa modificam valoarea $t{~s~}$ corespunzator. La deplasarea cu o pozitie apar urmatoarele cazuri:\r\n\r\n# din sablon iese o valoare unica sau intra o valoare care nu exista in deplasamentul curent.\r\n# din sablon iese o valoare care va exista si in deplasamentul urmator, si intra o valoare care exista deja in deplasamentul curent\r\n\r\nVom rezolva cazul $1$ in {$O(K)$}, convertind subsirul curent dupa regulile din enunt. Observam ca in cazul $2$ dupa efectuarea deplasamentului sablonul va contine aceleasi cifre. Aceasta operatie este deci doar o deplasare, deci o putem efectua in $O(1)$ exact ca la Rabin Karp.\r\n\r\nDesi complexitatea algoritmului pare ca este {$O(N * K)$}, la o analiza mai atenta ne dam seama ca ea este de fapt {$O(N * S)$}. Sa incercam sa calculam de cate ori poate aparea cazul $1$ in deplasare. Trebuie sa observam ca un element odata intrat in sablon mai poate genera cazul $1$ abia dupa $K$ elemente, deci numarul total in cel mai defavorabil caz este {$N/K * S$}. Complexitatea algoritmului devine acum $O(K * N/K * S + N)$ deci {$O(N * S)$}.\r\n\r\nLa implementare, toate operatiile se fac modulo $Q$ (unde $Q$ este un numar prim destul de mare). Acum poate vi se pare ca de fiecare data cand $t{~s~} = p$ ar trebui sa comparam in $O(K)$ cele doua subsiruri, complexitatea totala crescand. O analiza probabilistica ne arata ca pentru $Q$ prim si destul de mare sansele ca doua subsiruri diferite de lungime $K$ sa fie echivalente modulo $Q$ sunt foarte mici, deci o solutie care compara doar modulele numerelor va lua punctajul maxim fara probleme.\r\n\r\nh2. Barn expansion\r\n\r\nDupa cum au aratat-o si rezultatele, aceasta problema a fost cea mai simpla din concurs. Trebuie sa determinam numarul de dreptunghiuri a caror laturi nu intalnsesc laturile altor dreptunghiuri. De asemenea, sa nu uitam ca dreptunghiurile nu se pot suprapune. In aceste conditii observam ca daca doua dreptunghiuri se intersecteaza atunci se vor intersecta si $2$ segmente verticale sau $2$ segmente orizontale. Putem astfel sa luam mai intai toate segmentele verticale, vedem care dintre acestea se intersecteaza cu altele si marcam dreptunghiurile lor ca fiind rele. Repetam algoritmul si pentru segmentele orizontale, iar la sfarsit numaram cate dreptunghiuri bune ne-au ramas.\r\n\r\nProblema pe care trebuie sa o rezolvam acum este urmatoarea: avand $K$ segmente paralele cu axa Oy trebuie sa determinam care dintre acestea se intersecteaza cu altele. Pentru aceasta sortam segmentele in primul rand dupa coordonata $x$ si in al 2-lea rand dupa coordonata $y$ minima. Dupa aceasta sortare putem determina in $O(K)$ segmentele care se intersecteaza. Parcurgem vectorul de la stanga la dreapta, si pentru fiecare pas vedem daca segmentul curent se intersecteaza cu un segment precedent. Pentru aceasta trebuie sa tinem o variabila ls care reprezinta coordonata $y$ maxima atinsa pana la un moment dat. Pentru segmentul $i$ fie {$ymin{~i~}$}, $ymax{~i~}$ si $x{~i~}$ coordonatele lui. Pentru un $i$ daca $x{~i~} != x{~i-1~}$ sau $ymin{~i~} > ls$ initializam $ls$ cu {$ymax{~i~}$}. Altfel marcam segmentul $i$ si segmentul cu care am obtinut maximul $ls$ ca fiind rele, iar $ls$ devine {$MAX (ls, ymax{~i~})$}.\r\n\r\nProblema se rezolva similar si pentru segmentele orizontale. Complexitatea algoritmului este {$O(N logN)$}.\r\n\r\nh2. Layout\r\n\r\nVom nota pozitiile celor $N$ vaci cu $x{~1~}, x{~2~} ... x{~N~}$ si vom transforma fiecare relatie care se da intr-o constrangere de forma {$x{~i~} - x{~j~} &le; C$}. Cum se impune din enunt ca {$x{~1~} &le; x{~2~} &le; ... &le; x{~N~}$}, vom introduce initial constrangeri de forma {$x{~i~} - x{~i+1~} &le; 0$} ({$i < N$}). Apoi, pentru fiecare perechi de vaci $i < j$ care trebuie sa fie la distanta maxim {$D$}, vom introduce constrangerea {$x{~j~} - x{~i~} &le; D$}, iar pentru fiecare pereche $i < j$ care trebuie sa fie la distanta de minim {$D$}, vom introduce constrangerea {$x{~i~} - x{~j~} &le; -D$}. Trebuie acum sa rezolvam acest sistem de constrangeri.\r\n\r\nMotivul pentru toate constrangerile sunt de forma {$x{~i~} - x{~j~} &le; C$} , este pentru a modela aceasta problema folosind teoria grafurilor. Vom considera vacile ca fiind noduri de la $1$ la {$N$}, iar fiecare constrangere {$x{~i~} - x{~j~} &le; C$} va reprezenta o muchia de la $j$ la $i$ cu costul {$C$}. In acest graf vom determina distantele minime de la $1$ la fiecare nod intr-un vector {$D$}. Din definitia distantelor minime in grafuri , pentru o muchie ({$j, i$}) de cost $C$ se respecta relatia {$D{~i~} &le; D{~j~} + C$}, echivalenta cu {$D{~i~} - D{~j~} &le; C$}. Asadar vectorul $D$ va respecta fiecare constrangere formulata anterior pentru vectorul {$x$}. \r\n\r\nFiindca graful este rar ({$MD+ML+N-1$} muchii), se va folosi algoritmul Bellman-Ford pentru determinarea distantelor mimine, avand complexitatea O({$N*(MD+ML+N)$}). Modul in care lucreaza algoritmul Bellman-Ford asigura ca distanta dintre vaca $1$ si vaca $N$ este maximizata. Cazul cand vacile puteau fi asezate oricat de departe se putea detecta verificand daca distanta pana la vaca $N$ este infinit. De asemenea, cazul cand problema nu avea solutie putea fi detectat tot cu Bellman Ford, verificand daca exista un ciclu de cost negative accesibil din nodul {$1$}. Demonstratia ca atunci cand graful contine un ciclu negativ nu exista solutie o lasam pe seama cititorului.\r\n\r\n',1,'public',NULL,NULL),('blog/rezultate-summer-challenge-doi','Rezultate Summer Challenge Doi','2006-08-11 00:00:00','2006-08-11 00:00:00','h1. Rezultate Summer Challenge Doi\r\n\r\nIata ca s-a incheiat si \'Summer Challenge Doi\':summer-challenge-doi. Desi este vara si majoritatea petrec pe la munte sau pe la mare s-au gasit destui concurenti care sa isi faca timp si pentru acest antrenament.\r\n\r\nIata primii 6 clasati in urma evaluarii:\r\n\r\n==Rankings(rounds=\"summer2\" display_entries=\"6\" pager_style=\"none\")==\r\n\r\nFelicitari tuturor participantilor si va asteptam la concursurile viitoare de pe infoarena. Intre timp va puteti antrena cu problemele din {\"arhiva\":http://infoarena.ro/arhiva-probleme}.\r\n\r\nSolutiile oficiale le gasiti {\"aici\":http://www.infoarena.ro/Solutii_Summer_Challenge_Doi}.',1142,'protected',NULL,NULL),('preoni-2006/runda-4/solutii','Solutii preONI 2006, Runda a 4-a','2006-02-19 00:00:00','2008-12-28 09:11:06','h1. Solutii preONI 2006, Runda a 4-a\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa infoarena_)\r\n\r\nSuntem bucurosi sa va anuntam ca Runda a 4-a concursului preONI 2006 s-a incheiat. In acest articol va vom prezenta solutiile oficiale ale celor 7 probleme propuse precum si cateva aprecieri dupa cele patru probe de foc.\r\n\r\nS-a consumat si al patrulea act al bataliei si odata cu el si etapa on-line a concursului preONI. S-a tras linia si s-au desemnat \"fericitii calificati in runda finala\":preoni-2006/clasament (atentie! verificarea inca nu a fost facuta, dar cu asta ne vom ocupa in urmatoarea perioada).\r\n\r\nAruncandu-ne ochii pe clasamentele Rundei 4, constatam ca participantii au tras tare pe ultima suta de metri vrand sa ne contrazica previziunile sumbre dupa Runda 3. Desi nivelul de dificultate al problemelor a fost un pic mai scazut fata de runda precedenta, concurentii s-au dovedit mult mai conectati la concurs - suspectam ca apropierea olimpiadelor ar fi cauza. Asadar am avut punctaje aproape maxime $(275, 255)$ obtinute in viteza maxima de primii doi clasati la clasa a 9-a - $Bogdan Tataroiu$ si $Sima Mihai Cotizo$, un punctaj maxim la clasa a 12-a realizat de $Costea Andrei$ care a reusit, dupa un start mai putin reusit in rundele precedente, sa treaca la pas pe langa ceilalti info-atleti, unii dintre ei deja nume mari. De data aceasta, concurentii de la clasa a 10-a nu s-au lasat mai prejos fata de celelalte grupe de varsta si, avand un set clar mai usor decat precedentul, au adunat in ritm de maraton punctaje frumoase care au atins si depasit limita (legal admisa) de $200$. Felicitari pentru aceasta realizare lui $Vlad Dumitriu$ si $Bogdan Stoica$. In concluzie, am asistat la un concurs bine organizat (felicitari comisiei!) si la un sprint de sanatate din partea concurentilor (felicitari mai ales lor!) care ne-au convins inca o data ca tinerii nostri sunt pregatiti sa fuga mancand pamantul pentru gloria si renumele olimpiadelor nationale si internationale.\r\n\r\nUna peste alta, s-a incheiat o etapa frumoasa a concursului in care am pus mult suflet. Normal, pot fi doar 30 de participanti fericiti de rezultate. Ii felicitam pe cei calificati si abia asteptam sa-i vedem in finala. Ii felicitam si pe ceilalti care nu au putut sa-si tina suflul pana in final, pierzand locurile calificabile. Noi le uram cat mai multe succese, sa mai alerge vreo cateva sute de probleme (incepand cu cele din Arhiva noastra) si sa ne intalnim cu ei mult mai pregatiti la startul urmatorului preONI.\r\n\r\nIn urmatoarele pagini vom incerca sa explicam solutiile problemelor. Asa cum v-ati obisnuit, va puteti lamuri orice vi se pare neclar sau vag explicat intreband pe \"forum\":http://forum.infoarena.ro/, unde vom incerca sa raspundem cat mai promt. Va asteptam cu intrebari si sugestii (asigurati-va ca pareririle va sunt auzite!)\r\n\r\nh2. NextSeq\r\n(problema simpla clasa a 9-a)\r\n\r\nEste usor de observat ca cele doua siruri pot fi interpretate ca numere in baza $N$ (numarul de elemente din setul $X$). Acest lucru se poate efectua sortand numerele din setul $X$ si asociind fiecaruia o valoare intre $0$ si $N-1$ (procedeul poarta numele de normalizare). Stiind acest lucru, doua solutii sunt posibile.\r\n\r\nCea mai usoara dintre ele este sa calculam sirul ce il urmeaza pe $A$ (numarand in baza $N$) pana cand obtinem sirul $B$. Deoarece se garanta faptul ca sunt mai putin de $100$ de siruri intre $A$ si $B$, acest pas se va executa de maxim $100$ de ori. Ne punem problema calcularii sirului care urmeaza dupa sirul $A$. Putem afla sirul care-l urmeaza pe $A$ in complexitate $O(M)$ - $M$ este lungimea sirului $A$ - simuland operatia de adunare cu $1$ in urmatorul mod: parcurgem sirul $A$ incepand cu ultimul element pana cand gasim un element mai mic decat $N-1$ (interpretandu-l in baza $N$); incrementam acel numar si numerele egale cu $N-1$ intalnite pana la la el, le egalam cu $0$ (cea mai mica valoare). Singurul caz interesant este acela cand $A$ are toate elementele egale cu valoarea maxima dar este usor de tratat. Complexitatea finala va fi $O(D*P)$ - $P$ este lungimea sirului $B$ iar $D$ este numarul de siruri aflate intre $A$ si $B$.\r\n\r\nSolutia mai rapida, dar ceva mai dificil de implementat, se baza pe operatia de scadere pe numere mari. Astfel, dupa ce am calculat reprezentarile sirurilor $A$ si $B$ in baza $N$, putem efectua o scadere pe numere mari pentru a afla numarul de siruri cuprinse intre $A$ si $B$. Complexitatea solutiei este $O(P)$ - $P$ este lungimea sirului $B$.\r\n\r\nAmbele solutii obtin punctaj maxim, prima fiind ceva mai usoara, putandu-se ajunge la ea si prin abordari care nu tin cont de reprezentarea sirurilor in baza $N$.\r\n\r\nh2. GFact\r\n(problema medie clasa a 9-a)\r\n\r\nPrimul pas in rezolvarea problemei il reprezinta factorizarea numarului $P$. Acest lucru se poate realiza intr-o complexitate $O(&#8730;P)$. Odata obtinuta factorizarea, vom avea o relatie de forma:\r\n$P = T{~1~}^R1^ * ... * T{~K~}^RK^$\r\nImediat rezulta:\r\n$A = T{~1~}^R1 * Q^ * ... * T{~K~}^RK * Q^$\r\nAl doilea pas este sa observam ca daca aflam pentru fiecare $T{~i~}$, $B{~i~}$ astfel incat $B{~i~}!$ se divide la $T{~i~}^Ri * Q^$ atunci $B$ (numarul cautat in problema) este maximul dintre $B{~i~}$. Implicatia imediata e ca putem sa ne ocupam de fiecare numar prim in parte fara sa tinem cont de celelalte.\r\n\r\nAl treilea pas consta in determinarea $B{~i~}$-urilor cu ajutorul cautarii binare. Pentru o valoare candidata $X$ (din cautarea binara) trebuie sa calculam puterea lui $T{~i~}$ in descompunerea lui $X!$. Acest lucru se afla simplu ca fiind $[X/T{~i~}] + [X/T{~i~}^2^] + ...$ (unde prin $[x]$ intelegem partea intreaga a lui $x$). Cautarea binara se poate optimiza observand ca $B{~i~}$ este intotdeauna divizibil cu $T{~i~}$, ba mai mult nu va fi mai mare decat $(R{~i~} * Q) * T{~i~}$ (observatie necesara obtinerii punctajului maxim). In concluzie, vom cauta binar o valoare intreaga $K$ in intervalul $[1, R{~i~} * Q]$ astfel incat $B{~i~} = K * T{~i~}$ sa aiba propietata ca $B{~i~}!$ se divide la $T{~i~}^Ri * Q^$. Va puteti intreba de ce putem cauta binar. Este simplu: daca o valoare $X$ are propietatea ca $X!$ se divide la $Y$ (unde lui $X$ si $Y$ le putem da semnificatiile dorite de noi) atunci, evident, si $(X + 1)!$ se divide la $Y$.\r\n\r\nSolutia finala va avea complexitatea $O(&#8730;P * log Q * log Q)$. Exista o serie de solutii intermediare care permiteau obtinerea de punctaje suficient de mari si de aceea problema a fost considerata medie desi rezolvarea completa este destul de dificila.\r\n\r\n\r\nh2. Matrix\r\n(problema grea clasa a 9-a, problema medie clasa a 10-a)\r\n\r\nPrimul pas al algoritmului este calcularea numarului de aparitii ale fiecarei litere in matricea de $N*N$. Prima idee care ne vine in minte este ca pentru toate submatricile posibile sa calculam numarul de aparitii ale fiecarei litere si sa comparam cu valorile care trebuie obtinute. Acest algoritm are complexitatea $O(M^2^*(N+S))$, unde $S$ este dimensiunea alfabetului. Aceasta abordare obtine $50$ de puncte. \r\nVom verifica pentru toate cele {@(M-N)@}$^2^$ matrici posibile daca sunt sau nu permutari ale matricii-template. Apoi, pentru fiecare litera a alfabetului, efectuam urmatoarea preprocesare pentru a putea calcula in $O(1)$ numarul de aparitii ale literei din orice submatrice: $T{~i,j~}$ = numarul de aparitii pe pozitii $(x, y)$ cu $1 &le; x &le; i$ si $1 &le; y &le; j$.\r\n\r\nRelatia de recurenta este $T{~i,j~} = T{~i-1,j~}+T{~i,j-1~}-T{~i-1,j-1~}$, la care se adauga $1$ daca si numai daca pe pozitia $(i, j)$ se afla litera pe care o cautam. In aceste conditii, numarul de aparitii ale literei curente in submatricea cu colturile in $(i-N+1, j-N+1)$ si $(i, j)$ este $T{~i,j~}-T{~i-N,j~}-T{~i,j-N~}+T{~i-N,j-N~}$. Aceasta solutie are complexitatea $O(M^2^*S)$. Daca se foloseste $O(M^2^*S)$ memorie se obtin $70-80$ de puncte, iar pentru punctaj maxim este necesara reducerea la $O(M^2^)$. Acest lucru poate fi realizat folosind doua matrici, una in care tinem minte daca pentru o anumita pozitie s-a gasit vreo litera pentru care numarul de aparitii nu coincide cu cel dorit, si una in care se efectueaza preprocesarea pentru litera curenta. O alta optimizare, mult mai nesimnificativa, si care nu este necesara pentru $100$ de puncte, este renuntarea la verificarea pentru ultima litera, deoarece daca primele $25$ de litere s-au potrivit, iar numarul de litere este constant, e clar ca si cea de-a $26$-a litera se va potrivi.\r\n\r\n\r\nh2. Lista lui Andrei\r\n(problema usoara clasa a 10-a)\r\n\r\nProblema se rezolva folosind programare dinamica. Putem tine o matrice $V{~1..N~}{~1..26~}$ unde $V{~i,j~}$ reprezinta numarul de siruri de lungime $i$ ce contin ultima litera $j$. Incepem completarea matricii in ordine crescatoare a lungimii sirurilor, iar $V{~i,j~}$ se obtine prin insumarea valorilor $V{~i-1,k~}$, pentru orice $k$ a.i perechea $(k, j)$ sau $(j, k)$ sa nu se regaseasca in lista. Acest rationament conduce la un algoritm in $O(N * &#931;^2^)$, unde $&#931;$ reprezinta marimea alfabetului (in cazul nostru $26$).\r\n\r\nh2. Calcul\r\n(problema grea clasa a 10-a, problema medie clasele 11-12)\r\n\r\nDeoarece se cer doar ultimele $C$ cifre se va lucra modulo $10^C^$. Asadar, la primul pas se va calcula $A$ modulo $10^C^$, adica ne intereseaza doar ultimele $C$ cifre din $A$.\r\nO prima solutie pentru a calcula $A^1^ + A^2^ + ... + A^B^$ este de calcula $A^i^$ in $O(lg i)$ pentru fiecare $i$ folosind algoritmul clasic de ridicare la o putere in numar logaritmic de pasi (Cormen, capitolul 33). Aceasta solutie ar fi adus doar $20p$.\r\n\r\nSuma prezentata este o progresie geometrica clasica, si se poate calcula folosind formula $(A^B+1^-A) / (A-1)$. Calculul lui $A^(B+1)^$ se face folosind acelasi algoritm mentionat mai sus in $O(lg B)$ ({$lg$} = logaritm in baza 2). Pentru a efectua impartirea modulo $10^C^$, trebuie sa existe un invers multiplicativ pentru $A-1$ , modulo $10^C^$, lucru garantat doar pentru $50%$ din teste $(cmmdc(A-1, 10^C^) = 1)$. Inversul multiplicativ poate fi calculat folosind algoritmul Euclid extins sau teorema lui Fermat: $X^phi(N)^ = 1 (mod N)$ pentru $cmmdc(X, N) = 1$ si $phi(N)$ = indicatorul lui Euler, cate numere < $N$ sunt prime cu $N$. Din teorema reiese ca $X^phi(N)-1^ = X^-1^ (mod N)$, asadar inversul poate fi calculat algoritmul de ridicare la o putere mentionat mai sus ({$phi(10^C^)$} poate fi calculat usor). Un caz special la aceasta solutie apare atunci cand $A = 1$. Aceasta solutie n-ar fi adus decat $50p$ si necesita cunostiinte de matematica de clasa a 12-a. \r\n\r\nExista o solutie mult mai accesibila pentru clasele a 10-a si a 11-a, folosind\r\nrelatiile:\r\n$S(A,2*B) = S(A,B) * (1+A^B^)$\r\n$S(A,2*B+1) = A * (1+S(A,2*B))$\r\nCum numarul $B$ este dat in baza $16$, parcurgerea bitilor acestuia se face usor, simuland algoritmul de mai sus. Daca $A^B^$ se calculeaza la fiecare pas, complexitatea va fi $O(lg^2^ B)$, obtinand $60p$. O solutie $O(lg B)$ de $100$ de puncte se poate obtine calculand in paralel valorile $S(A,B)$ si $A^B^$. O ultima \"problema\" care ar fi putut exista este faptul ca se cer ultimele $C$ cifre, nu rezultatul modulo $10^C^$; spre exemplu, daca $C = 4$ si rezultatul modulo $10^4^$ ar fi fost $\"123\"$, in fisierul de iesire trebuia afisat $\"0123\"$.\r\n\r\nh2. Distante minime\r\n(problema usoara clasele 11-12)\r\n\r\nProblema se rezolva folosind algoritmul lui Dijkstra pornind din nodul $1$. Astfel pe langa vectorul $D{~1..N~}$ in care tinem distantele minime vom mai folosi un vector $P{~1..N~}$ in care tinem pentru fiecare nod $i$ numarul de drumuri de lungime $D{~i~}$. Cand relaxam o muchie vom face update, daca este cazul, atat in vectorul $D$ cat si in vectorul $P$.\r\n\r\nDeoarece costul drumurilor a fost definit ca produs de muchii, in vectorul $D$ putem ajunge sa avem numere cu mii de cifre. O implementare cu numere mari a algoritmului descris mai sus nu este destul de eficienta, ea obtinand aproximativ $75$ de puncte. Pentru a obtine punctajul maxim este necesara logaritmarea costului fiecarei muchii intr-o baza oarecare. Astfel putem transforma produsul in suma, folosind o proprietate a logaritmilor, fapt ce duce la o implementare simpla si rapida, folosind doar date de tip $double$.\r\n\r\nh2. Popandai\r\n(problema grea clasele 11-12)\r\n\r\nMai intai vom calcula, pentru fiecare pereche de puncte $A$ si $B$ din punctele ce reprezinta vizuinele, in sirul $sub{~AB~}$ cate puncte din restul de $n$ se afla sub segmentul de dreapta determinat de $A$ si $B$. Aceasta preprocesare poate fi efectuata in $O(n^2^ log n)$ cu un algoritm inteligent sau poate fi efectuata in $O(n^3^)$ cu metoda naiva care verifica pentru fiecare punct daca este situat pe intervalul $[A.x, B.x]$ si este sub dreapta determinata de cele doua puncte. Preprocesare vom putea pentru fiecare triunghi $ABC$ sa aflam in timp $O(1)$ cate puncte are in interior: presupunem fara a restrange generalitatea ca $A.x &le; B.x &le; C.x$, daca punctul $B$ e deasupra dreptei $AC$ atunci numarul de puncte din interiorul lui $ABC$ este $sub{~AB~} + sub{~BC~} - sub{~AC~}$, iar daca $B$ este sub dreapta $AC$ atunci numarul de puncte este $sub{~AC~} - sub{~AB~} - sub{~BC~} - 1$.\r\n\r\nOrice patrulater, fie el concav sau convex, are o diagonala interna. Daca fixam un segment $PQ$ ca fiind diagonala interna putem sa incercam sa gasim pentru fiecare $x$ triunghiul $PQR$ de arie minima pentru care punctul $R$ este deasupra dreptei $PQ$ si care contine in interior cel putin $x$ puncte, iar apoi sa gasim un triunghi $PQS$ de arie minima cu varful $S$ sub dreapta $PQ$ ce contine in interior cel putin $k-x$ puncte. Ariile minime ale acestor triunghiuri se pastreaza in doua siruri over si under iar aria minima a unui patrulater cu o diagonala $PQ$ va fi $min(over{~x~} + under{~k-x~} | unde x ia toate valorile de la 0 la k)$. Folosind artificiul explicat mai sus putem determina in $O(1)$ numarul de puncte ce se afla in interiorul unui triunghi, si astfel sirurile $over$ si $under$ pot fi calculate in $O(n)$. Complexitatea totala a algoritmului este $O(n^3^)$ pentru ca avem $O(n^3^)$ calcule in faza de preprocesare si pentru fiecare $n(n-1)/2$ diagonale vom efectua $O(n)$ calcule.\r\n',1430,'public',NULL,NULL),('blog/bursele-agora','Bursele Agora','2005-05-20 00:00:00','2005-05-20 00:00:00','h1. Bursele Agora\r\n\r\nPrin intermediul site-ului \"infoarena\":http://infoarena.ro/ veti putea participa online la finala concursului Bursele Agora! Mai multe detalii puteti gasi pe site-ul oficial al \"concursului\":http://www.ginfo.ro.\r\n',1142,'protected',NULL,NULL),('blog/lansare-preoni-2006','Lansare preONI 2006','2005-11-15 00:00:00','2005-11-15 00:00:00','h1. Lansare preONI 2006\r\n\r\nDaca e prima data cand auzi de preONI, te lamurim indata. Daca ai participat pana acum la un concurs preONI, afla ca anul acesta avem PREMII SERIOASE puse in joc, o finala live intr-o tabara si 5 runde minunate de probleme!\r\n\r\nPe scurt, preONI este un concurs cu premii destinat elevilor de liceu ce se pregatesc pentru competitii de informatica - in special ONI.\r\n\r\nAm construit o \"sectiune speciala\":preONI-2006 in site-ul infoarena pentru acest concurs. TOT CE VREI sa afli despre preONI 2006 se gaseste intr-un singur loc: premii, regulament, program, sponsori, forum, comisie si organizatori, finala in tabara etc.\r\n\r\nATENTIE! Prima runda incepe in curand - Sambata, 19 noiembrie. Intra pe pagina oficiala preONI 2006 pentru mai multe informatii. Te asteptam !\r\n\r\nEditia 2006 a concursului preONI se datoreaza sponsorilor nostri, carora le multumim pe aceasta cale:\r\n\r\n* \"IP Devel\":http://www.ipdevel.ro/\r\n* \"ORACLE Romania\":http://www.oracle.ro/\r\n* \"SOFTWIN\":http://www.softwin.ro/\r\n* \"Microsoft Romania\":http://www.microsoft.ro/\r\n* \"TotalSoft\":http://www.totalsoft.ro/\r\n',961,'protected',NULL,NULL),('blog/noutati-infoarena','Noutati infoarena','2005-11-15 00:00:00','2005-11-15 00:00:00','h1. Noutati infoarena\r\n\r\nDupa cum ti s-a promis inca din vara asta, anul acesta echipa infoarena ti-a pregatit un numar foarte mare de surprize! Cateva din ele s-au materializat, pentru a afla mai multe citeste in continuare.\r\n\r\nh2. \'preONI 2006\':preONI-2006\r\n\r\nBinecunoscutul concurs organizat de infoarena vine anul acesta intr-un format nou! Mai multe detalii gasesti pe pagina oficiale a acestui concurs accesibila de pe infoarena.\r\n\r\nh2. \'Evaluator (foarte) stabil\':Despre-Evaluator\r\n\r\nPuteti sa va luati adio de la perioadele cand evaluatorul nu functiona din cauza conexiunii la Internet. De acum incolo sistemul de evaluare ruleaza pe o conexiune garantata.\r\n\r\nh2. \'Despre infoarena\':Despre-infoarena\r\n\r\nComunitatea infoarena este intr-o expansiune continua. Aceasta pagina contine o privire generala dar si informatii detaliate despre infoarena impreuna cu un regulament imbunatit, venind in ajutorul utlizatorilor noi dar si celor vechi. De asemenea, am decis sa oferim o mica rasplata tuturor celor care au contribuit la dezvoltarea proiectului infoarena, si am creat o pagina cu echipa & colaboratorii infoarena, poze si palmares.',1142,'protected',NULL,NULL),('preoni-2006/runda-4','Runda 4, preONI 2006','2006-11-25 02:50:29','2006-11-27 16:16:47','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Runda 4\r\n\r\nConcursul s-a desfasurat duminica, 19 februarie, la ora 14:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nh2. Comisii\r\n\r\nh3. Stiintific\r\n\r\n* clasa a 9-a (si gimnaziu)\r\n** Cosmin Negruseri\r\n** Silviu Ganceanu \r\n* clasa a 10-a\r\n** Daniel Pasaila\r\n** Tiberiu Florea \r\n* clasele 11-12\r\n** Adrian Vladu\r\n** Adrian Diaconu\r\n** Mircea Pasoi \r\n\r\nh3. Organizatoric\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* Cristian Strat\r\n* Crestez Leonard \r\n\r\nh2. Solutii\r\n\r\nSolutiile problemelor le puteti gasi \"aici\":preoni-2006/runda-4/solutii\r\n\r\nh2. Clasa a 9-a si gimnaziu (\'Clasament\':preoni-2006/runda-4/clasament-9)\r\n\r\n!>preoni-2006/runda-4?logo.jpg!\r\n\r\n== Tasks(round_id=\"preoni64a\" pager_style=\"none\") ==\r\n\r\nh2. Clasa a 10-a(\'Clasament\':preoni-2006/runda-4/clasament-10)\r\n\r\n!>preoni-2006/runda-4?logo.jpg!\r\n\r\n== Tasks(round_id=\"preoni64b\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2006/runda-4/clasament-11-12)\r\n\r\n!>preoni-2006/runda-4?logo.jpg!\r\n\r\n== Tasks(round_id=\"preoni64c\" pager_style=\"none\") ==\r\n\r\n\r\n==include(page=\"template/preoni-2006/footer\")==',13,'protected',NULL,NULL),('blog/final-preoni-2006-runda-1','Runda 1 preONI 2006 s-a incheiat','2005-11-19 00:00:00','2005-11-19 00:00:00','h1. Runda 1 preONI 2006 s-a incheiat\r\n\r\nPrima runda online a concursului preONI 2006 s-a incheiat. Totul a decurs normal, singurul lucru care ne-a dezamagit fiind comportarea elevilor de clasele 9-10, care au obtinut punctaje sub asteptari.\r\n\r\nFiecare grupa a avut spre rezolvare 3 probleme, fiecare fiind catalogata de catre comisie ca fiind usoara, medie sau grea. Batalia pentru calificarea la finala este abia la inceput!\r\n\r\nPentru mai multe detalii despre finala, cat si despre concursul preONI 2006 si sponsorii nostri va rugam sa consultati \'pagina concursului\':preONI-2006. S-a publicat rezultatele finale:\r\n\r\n* \'Clasa a IX-a\':preoni-2006/runda-1/clasament-9\r\n* \'Clasa a X-a\':preoni-2006/runda-1/clasament-10\r\n* \'Clasele XI-XII\':preoni-2006/runda-1/clasament-11-12\r\n\r\nDin pacate, punctajele la clasele a 9-a si a 10-a sunt sub asteptarile comisiei. Pentru discutii despre dificultate problemelor si despre concursul preONI 2006 in general va invitam sa intrati pe \'forum\':http:forum/infoarena.ro.\r\n\r\nSolutiile problemelor au fost publicate \'aici\':preoni-2006/runda-1/solutii\r\n\r\n',961,'protected',NULL,NULL),('preoni-2006/runda-1/solutii','Solutii preONI 2006 - Runda 1','2005-11-19 00:00:00','2008-09-23 21:02:13','h1. Solutii preONI 2006 - Runda 1\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa infoarena_)\r\n\r\nRunda 1 a concursului preONI 2006 s-a incheiat. Acest articol contine solutiile oficiale pentru toate probleme propuse spre rezolvare, cat si comentarii referitoare la concurs.\r\n\r\nFiecare grupa a avut spre rezolvare 3 probleme, fiecare fiind catalogata de catre comisie ca fiind usoara, medie sau grea. Batalia pentru calificarea la finala este abia la inceput!\r\n\r\nPentru mai multe detalii despre finala, cat si despre concursul preONI 2006 si sponsorii nostri va rugam sa consultati \"pagina preONI-2006\":preONI-2006.\r\n\r\nRezultatele finale sunt disponibile la:\r\n\r\n* \"Clasa a 9-a\":http://infoarena.devnet.ro/index.php?page=stats&conid=preoni61a&smod=top\r\n* \"Clasa a 10-a\":http://infoarena.devnet.ro/index.php?page=stats&conid=preoni61b&smod=top\r\n* \"Clasele 11-12\":http://infoarena.devnet.ro/index.php?page=stats&conid=preoni61c&smod=top\r\n\r\nDin pacate, punctajele la clasele a 9-a si a 10-a sunt sub asteptarile comisiei. Pentru discutii despre dificultate problemelor si despre concursul preONI 2006 in general va invitam sa intrati pe \"forum\":http://forum.infoarena.ro/index.php/board,20.0.html.\r\n\r\nInainte de a va prezenta solutiile va invitam sa rezolvati problemele propuse la acest concurs in \"Arhiva de probleme infoarena\":http://infoarena.ro/arhiva-probleme, si va asteptam in forta la runda a 2-a a concursului! (17 decembrie 2005)\r\n\r\nh2. Reuniune\r\n\r\nh3. (clasa a 9-a problema usoara)\r\n\r\nVom considera cazul simplificat cu $2$ dreptunghiuri $A$ si {$B$}, pentru care putem obtine formulele:\r\n\r\n* $Arie(A + B) = Arie(A) + Arie(B) - Arie(A x B)$\r\n* $Perim(A + B) = Permi(A) + Perim(B) - Perim(A x B)$\r\n\r\n({$A+B$} reprezinta reuniunea multimilor $A$ si {$B$}, iar $AxB$ intersectia.)\r\n\r\nCazul cu $3$ dreptunghiuri {$A$}, {$B$}, $C$ se rezolva similar. Cea mai simpla metoda este de a \"vizualiza\" formula facand un desen. Mai jos aveti un astfel de desen ajutator.\r\n\r\n!preoni-2006/runda-1/solutii?reuniune.png!\r\n\r\nAsadar, obtinem formula:\r\n\r\n* $Arie(A+B+C) = Arie(A) + Arie(B) + Arie&#40;C&#41; - Arie(AxB) - Arie(BxC) - Arie(AxC) + Arie(AxBxC)$\r\n\r\n(pentru perimetru formula este asemanatoare)\r\n\r\nAstfel rezolvarea este {$O(1)$}, deoarece intersectia a $2$ sau $3$ dreptunghiuri poate fi calculata usor in timp constant. Mentionam ca formula de mai sus poate fi gasita si pe cale algebrica, si reprezinta un caz particular al principiului includerii si excluderii.\r\n\r\nh2. Patrate 2\r\n\r\nh3. (clasa a 9-a problema medie)\r\n\r\nMai intai sa completam matricea doar cu $1$ si $5$ astfel incat produsul elementelor de pe fiecare linie sau coloana sa fie {$5$}. Observam ca pe fiecare linie si pe fiecare coloana se plaseaza exact un {$5$}, restul matricii fiind completata cu {$1$}. Este evident ca fiecare permutare a multimii ({$1, 2 * N$}) reprezinta de fapt o posibilitate de aranjare a numarului $5$ in matrice, iar de aici deducem ca numarul de posibilitati de a completa matricea doar cu $1$ si $5$ este $P{~N~}$ (adica {$N!$}). Cum putem folosi si $-1$ si {$-5$}, rezultatul final va fi $2^N*N^*N!$\r\n\r\nLa implementare trebuie sa se efectueze operatii cu numere mari. De asemenea, se recomanda ca baza in care se lucreaza trebuie sa fie destul de mare pentru a se obtine eficienta dorita.\r\n\r\nh2. Invers (solutie oferita de Bogdan Tataroiu)\r\n\r\nh3. (clasa a 9-a problema grea, clasa a 10-a problema usoara)\r\n\r\nRezolvarea acestei probleme presupune parcurgerea numarului ce trebuie verificat (il vom nota cu {$v$}) din exterior spre interior. Notam cu s pozitia extremitatii stangi al numarului, iar cu $d$ pozitia extremitatii drepte. Astfel numarul $v$ este format prin adunarea unor numere de forma\r\n\r\n* $a{~1~} a{~2~} a{~3~} ... a{~n-2~} a{~n-1~} a{~n~}$\r\n* $a{~n~} a{~n-1~} a{~n-2~} ... a{~3~} a{~2~} a{~1~}$\r\n\r\nAsadar, prin adunarea cifrelor $a{~i~}$ si $a{~n-i+1~}$ se poate obtine un transport care va afecta cifrele anterioare. Deoarece sirul este parcurs de la extremitati spre interior $s$ va fi egal cu {$i$}, iar $d$ va fi egal cu {$n - i + 1$}, deci cifrele $v{~s~}$ si $v{~d~}$ sunt formate prin adunarea cifrelor $a{~i~}$ si {$a{~n-i+1~}$}.\r\nIn parcurgerea sirului de la extremitati catre interior cazul ideal este atunci cand $v{~s~}$ este egal cu {$v{~d~}$}, caz in care cifra $v{~s~}$ nici nu primeste si nici nu trimite transport la cifrele aflate pe pozitii anterioare.\r\n\r\nUn alt caz este cel in care $v{~s~}$ primeste transport prin adunarea cifrelor $a{~s+1~}$ si $a{~d-1~}$ (vezi schema de mai sus pentru a intelege acest lucru). In acest caz $v{~s~}$ este egal cu $v{~d~}+1$ si, pentru a tine cont de faptul ca pozitia $s+1$ a generat transport, adaugam la $v{~s+1~}$ valoarea {$10$}.\r\n\r\nUn al treilea caz este acela in care $v{~s~}$ da transport pentru cifra $v{~s-1~}$ si nu primeste transport de la {$s+1$}, in acest caz $v{~s~}$ fiind egal cu $v{~d~}+10$ (acel $10$ fiind adaugat la pasul anterior). Deoarece atat $v{~s~}$ cat si $v{~d~}$ sunt obtinute prin adunarea cifrelor $a{~s~}$ si {$a{~d~}$}, iar $v{~s~}$ da transport cifrelor anterioare, atunci si $v{~d~}$ da transport cifrelor anterioare. Pentru a corecta acest lucru cifra $v{~d-1~}$ trebuie decrementata, avand grija la cazurile in care $v{~d-1~}$ este egal cu {$0$}. De asemenea trebuie luat in calcul cazul in care $v{~d~}$ este egal cu $9$ si {$v{~s~}=19$}. Acest lucru este imposibil deoarece suma maxima a doua cifre este $18$ si, evident, va trebui sa se afiseze raspunsul {$NU$}.\r\n\r\nAl patrulea si ultimul caz este acela in care $v{~s~}$ da transport cifrei $v{~s-1~}$ si, in acelasi timp, primeste transport de la cifrele aflate pe pozitia {$s+1$}. In acest caz $v{~s~}=v{~d~}+11$ si trebuie executate atat operatiile pt cazul {$v{~s~}=v{~d~}+1$}, cat si cele pentru cazul {$v{~s~}=v{~d~}+10$}.\r\nDaca diferenta $v{~s~}-v{~d~}$ este diferita de {$0$}, {$1$}, $10$ si $11$ atunci numarul $v$ nu poate fi obtinut prin adunarea unui numar $a$ cu inversul sau.\r\nAlgoritmul se repeta pana cand $s$ devine egal cu {$d$}, caz in care cifra $v{~s~}=v{~d~}$ trebuie sa fie para pentru ca numarul $v$ sa indeplineasca conditia din enunt sau pana cand {$d=s+1$}, caz in care trebuie ca $v{~s~}=v{~d~}$ sau $v{~s~}=v{~d~}+11$ pentru ca numarul $v$ sa aiba proprietatea ceruta. \r\n\r\nSe mai considera cazul cand {$a{~1~}=0$}, iar {$v{~1~}=1$},obtinut printr-un transport : se aduna $10$ la {$v{~2~}$} si se considera numarul incepand de la pozitia a doua, caruia i se verifica validitatea. Atentie la cazuri particulare!\r\n\r\nPentru a intelege mai bine algoritmul general vom analiza urmatorul exemplu: {$7 2 2 3 2 6$}.\r\nObservand ca $7=6+1$ tragem concluzia ca prima cifra va trebui sa primeasca transport, deci vom analiza {$12 2 3 2$}. Observam din nou ca {$12=2+10$} ceea ce inseamna ca $12$ trebuie sa trimita transport in fata, deci si $2$ din coada va fi de fapt {$12$}. Vom lua inapoi transportul de la {$3$}, deci vom analiza in continuare {$2 2$}. Acestea fiind egale nu se primeste si nu se da transport. Deoarce nu sa dat peste nici o contradictie raspunsul va fi {$DA$}.\r\n\r\nComplexitatea acestui algoritm este $O(nr)$ pe test, unde $nr$ este numarul de cifre al numarului {$v$}.\r\n\r\nh2. Dreptunghi\r\n\r\nh3. (clasa a 10-a problema medie)\r\n\r\nUn dreptunghi care apare in grila de puncte laticiale e marginit de doua drepte verticale la stanga si la dreapta, si de doua drepte orizontale in sus si in jos. Acum, daca vrem pentru patru drepte fixate sa stim cate dreptunghiuri marginesc ele, ne putem uita la urmatorul desen.\r\n\r\n!preoni-2006/runda-1/solutii?drept.jpg!\r\n\r\nDaca dreptunghiul determinat de cele patru drepte are laturile $H$ si $W$ atunci un dreptunghi inscris va imparti laturile lui in bucatile {$A$}, $B$ si {$C$}, {$D$}. Acum folosind teorema lui Pitagora avem ca:\r\n\r\n* $A^2^ + D^2^ = Galben^2^$\r\n* $B^2^ + C^2^ = Verde^2^$\r\n* $Galben^2^ + Verde^2^ = Roz^2^$\r\n* $(A + B)^2^ = Rosu^2^$\r\n* $(C $-$ D)^2^ = Albastru^2^$\r\n* $Rosu^2^ + Albastru^2^ = Roz^2^$\r\n\r\nDe aici avem ca {$(A + B)^2^ + (C - D)^2^ = A^2^ + B^2^ + C^2^ + D^2^$}, astfel obtinem {$AB = CD$}, dar {$B = H - A$}, iar {$D = W - C$} deci avem ca {$C^2^ - WC + A(H - A) = 0$}. Daca il fixam pe $A$ atunci trebuie sa rezolvam o ecuatie de gradul doi in necunoscuta {$C$}, solutia trebuie sa fie intreaga intre $0$ si {$W$}.\r\n\r\nAstfel in $O(H)$ vom sti numarul de dreptunghiuri inscrise intr-un dreptunghi de dimensiuni {$H * W$}. Acest dreptunghi poate fi pus in $(N - H + 1) * (M - W + 1)$ locatii pe o grila de dimensiune {$N * M$}. Deci solutia are complexitate {$O(N*M^2^)$}, pentru fiecare dreptunghi de dimensiuni $1 &le; H &le; N$ si $1 &le; W &le; M$ calculandu-se numarul de dreptunghiuri inscrise.\r\n\r\nO rezolvare de complexitate $O(N^2^*M^2^)$ in care se cautau solutiile ecuatiei printr-un for ar fi luat $60$ de puncte. Rezolvarea directa folosind ecuatia de gradul doi ia in jur de $80$ de puncte. Algoritmul poate fi optimizat la factorii constanti, de exemplu avem nevoie de functia radical care este cam inceata, precalculand-o obtinem o accelerare a vitezei, alta idee ar fi ca numarul de solutii cu $A &le; H/2$ este egal cu numarul de solutii cu $A &ge; H - H/2$ si a treia idee de optimizare este ca numarul de dreptunghiuri inscrise intr-un dreptunghi de dimensiuni {$H$}, $W$ este acelasi cu numarul de dreptunghiuri inscrise intr-un dreptunghi de dimensiuni {$W$}, {$H$}.\r\n\r\nh2. Zebughil\r\n\r\nh3. (clasa a 10 problema grea, clasele 11-12 problema medie)\r\n\r\nSe poate aborda o rezolvare bazata pe parcurgerea numerelor de la $1$ la $3^n^-1$ in ordine. Pastram matricea best in care retinem numarul minim de camioane in care pot fi transportate blocurile date de bitii de $1$ din {$i$}. Completarea acestei matrici se face in {$O(3^n^)$}. Descompunerea in baza $3$ va avea urmatoarea semnificatie: $0$ - blocul nu e in multimea curenta, $1$ - blocul se afla in ultimul camion sau $2$ - blocul se afla intr-un camion anterior in care nu se mai poate aduaga.\r\n\r\nAceasta idee aduce $90$ de puncte daca este implementata corect. O alta solutie se poate obtine daca avem in vedere faptul ca avem limita superioara $500$ pentru capacitatea unui camion putem face o rezolvare ce foloseste principiul programrii dinamice. Vom folosi o matrice $best{~i,j~}$ care retine numarul minim de camioane astfel incat sa putem transporta blocurile identificate de bitii de $1$ din reprezentarea in baza $2$ a lui {$i$}, iar ultimul camion sa fie plin pana la capacitatea {$j$}. Aceasta solutie ar fi obtinut $70$ de puncte.\r\n\r\nDeoarece fie folosim maxim $n$ camioane fie nu avem solutie putem incerca construirea unei matrici {$best{~i,j~}$} cu semnificatia cat mai este liber in ultimul camion ca sa avem transportati bitii de $1$ din $i$ si sa folosim maxim $j$ camioane. Completarea acestei matrici se face in {$O(2^n^*n^2^)$}, aducand 100 de puncte.\r\n\r\nAnalizand mai departe observam ca nu este nevoie sa retinem pentru o configuratie decat solutia folosind numar minim de camioane deoarece daca am folosi mai multe putem pur si simplu sa incepem unul nou acuma care va avea capacitate {$G$}. Astfel complexitatea de memorie se reduce la {$O(2^n^)$} iar cea de timp la $O(2^n^*n)$\r\n\r\nO alta abordare interesanta a problemei dar care nu ducea la obtinerea unui punctaj maxim este generarea permutarilor prin backtracking si testarea greedy a solutiei. Parcurgem permutarea si cand avem nevoie de un camion nou il deschidem. Aceasta ar avea o complexitatea {$O(n!*n)$}. Putem insa retine pe parcurs costul pana in acel moment si la sfarsit sa nu trebuiasca sa mai parcurgem din nou. Pentru generarea permutarilor se poate retine o lista cu elementele care nu au fost inca puse in permutare lista in care un element se va adauga si se va scoate in {$O(1)$}. Aceasta tehnica se numeste dancing links si duce la o complexitate totala de $O(n!)$\r\n\r\nO abordare neortodoxa ar fi fost generarea aleatoare a permutarilor, astfel pornim de la o permutare initiala si luam doua elemente din permutare in mod aleator pe care le interschimbam, daca solutia obtinuta e mai buna sau cel putin egala cu solutia initiala (valoarea unei solutii o vedem folosind un algoritm greedy care baga in ordine elementele in camioane) atunci pastram solutia curenta, iar daca nu interschimbam elementele la loc. O asemenea tehnica de optimizare a solutiei ar fi dus la un punctaj de aproximativ $60$ de puncte.\r\n\r\nh2. Distante\r\n\r\nh3. (clasele 11-12, problema usoara)\r\n\r\nFoarte multi concurenti au incercat sa rezolve aceasta problema folosind algoritmul Dijkstra cu heap-uri sau cu arbori de intervale. Aceasta solutie ar fi obtinut de la $70$ pana la $100$ de puncte (in cazul in care se optimiza algoritmul). O alta metoda de a obtine $100$ de puncte ar fi fost folosirea algoritmul Bellman Ford cu coada (vezi OJI 2004, problema \"Lanterna\":http://infoarena.ro/problema/lanterna).\r\n\r\nSolutia oficiala (care este de fapt si cea mai simpla si cea mai usor de implementat) are complexitate $O(N+M)$ ca timp si $O(N)$ ca memorie. Ea poate fi dedusa din modul de functionare a algoritmilor Dijkstra sau Bellman Ford. Asadar, conditile suficiente si necesare ca distantele minime date sa fie corecte sunt:\r\n\r\n* $D{~S~} = 0$\r\n* $D{~x~} + cost(x, y) &ge; D{~y~}$ pentru orice muchie ({$x, y$})\r\n* exista pentru fiecare $y$ (diferit de {$S$}) un $x$ astfel incat $D{~x~} + cost(x, y) = D{~y~}$\r\n\r\nStudiati modul in care functioneaza Dijkstra sau Bellman Ford si veti vedea ca logica acestor conditii devine evidenta. Verificarea acestor conditii se poate face in complexitatea mentionata mai sus.\r\n\r\nh2. Balans\r\n\r\nh3. (clasele 11-12, problema grea)\r\n\r\nProblema a fost gandita sa rasplateasca pe \"fanii infoarena\" si anume pe aceea care au rezolvat corect problemele \"Secventa 1\":http://infoarena.ro/problema/secventa, \"Secventa 2\":http://infoarena.ro/problema/secv2, \"Secventa 3\":http://infoarena.ro/problema/secv3. Pentru a trata circularitatea matricii o vom extinde intr-o matrice $2N*2M$, lipind matrii initiale o copie la dreapta, sub ea, si la dreapta-jos.\r\n\r\nRezolvarea acum se va baza pe cautarea binara a balansului maxim (idee folosita si la rezolvarea problemei \"Secventa 3\":http://infoarena.ro/problema/secv3). Fie acesta {$X$}, trebuie sa verificam daca exista o submatrice cu balans cel putin {$X$}, adica:\r\n\r\n* $Suma / Numar &ge; X$\r\n* $Suma &ge; X*Numar$\r\n* $Suma - X*Numar &ge; 0$\r\n\r\nFolosind cele scrise mai sus, putem observa ca, daca fiecare element nr din matricea intiala este inlocuit cu {$nr-X$}, atunci problema se reduce la a determina o submatrice din matricea modificata in care suma elementelor este {$&ge; 0$}. Aceasta problema se poate rezolva determinand submatricea de suma maxima din matricea modificata, verificand apoi daca este {$&ge; 0$}.\r\n\r\nAsadar, problema s-a redus la a determina o submatrice de cel putin $R$ linii si $C$ coloane de suma maxima dintr-o matrice. Intai vom fixa $2$ linii la distanta cel putin $R$ si cel mult {$N$}, si vom calcula sumele pe coloane intre cele doua linii (acest lucru se poate face in $O(M)$ precalculand anumite sume la inceput). Pe vectorul de sume pe coloane obtinut va trebui sa rezolvam acum problema \"secventei de suma maxima de lungime intre {$C$} si {$M$}\" (necesara si la rezolvarea problemei \"Secventa 3\":http://infoarena.ro/problema/secv3). Fie $A$ vectorul pe care vrem sa rezolvam acesta problema, si {$S{~i~} = A{~1~}&#0043;A{~2~}&#0043;...&#0043;A{~i~}$}. Pentru fiecare $i$ va trebui sa gasim un $j$ astfel incat:\r\n\r\n* $S[i] - S[j]$ = maxim\r\n* $i-M &le; j &le; i-C$\r\n\r\nAcest lucru se poate face in $O(M)$ per total folosind structura \"deque\" , prezentata pe scurt si in articolul cu solutii de la preONI 2005, runda 3. Lasam detalierea modului in care se va folosi aceasta structura in rezolvare ca exercitiu pentru cititor. Astfel, problema poate fi rezolva in complexitatea $O(N^2^*M*lg MAX)$ unde $MAX$ este valoarea maxima din matricea. Mentionam ca pentru o solutie relativ rapida si care sa evite erori de precizie se recomanda lucrul cu numere intregi (inmultind totul cu {$1000$}).\r\n\r\n',2044,'public',NULL,NULL),('blog/probleme-noi','Probleme noi!','2005-05-24 00:00:00','2005-05-24 00:00:00','h1. Probleme noi!\r\n\r\nS-au adaugat 8 probleme noi in \"Arhiva de probleme\":http://infoarena.ro/arhiva-probleme si 3 probleme noi pentru Bacalaureat 2005 pe site-ul \"infoarena\":http://infoarena.ro/. Asteptam parerile voastre pe forum despre noile probleme si va invitam sa le rezolvati. More to come...\r\n\r\n',1142,'protected',NULL,NULL),('blog/info-educatie-2005','InfoEducatie 2005','2005-08-12 00:00:00','2005-08-12 00:00:00','h1. InfoEducatie 2005\r\n\r\nConcursul InfoEducatie 2005 a ajuns la final si am vrea sa va invitam sa cititi \"povestea\":http://www.infoeducatie.ro/povestea_2005.php editiei de anul acesta a concursului. Acolo gasiti atat poze cat si mici filmulete interesante din tabara.\r\n\r\nCred ca sunt in asentimentul tuturor, al organizatorilor, sponsorilor si al participantilor cand spun ca aceasta a fost cea mai reusita editie InfoEducatie de pana acum. Este important de stiut ca anul acesta a adus si o crestere spectaculoasa in calitatea lucrarilor aflate in competitie si a seriozitatii cu care elevii si-au prezentat productiile.\r\n\r\nPremiile au fost mari (valoare totala de peste $7000, valoarea unui premiu 1 fiind de peste $800 !!!), jurizarea corecta, juriul format numai din specialisti. S-a organizat concurs open la toate sectiunile (o noutate a acestei editii), discutii libere si seminarii si toate au contribuit la succesul editiei 2005.\r\n\r\nDe mare succes s-au bucurat cele doua sectiuni OPEN pe teme de programre si creatie web. Concursul a fost condus in cea mai mare parte de studenti, laureati din anii anteriori ai concursului (Octavian Costache, Liviu Valsan, Razvan si Bogdan Hobeanu, Cristian Strat).\r\n\r\nConsideram InfoEducatie, un eveniment care aduce un pasaport catre o afacere proprie in domeniul IT&C. In plus, InfoEducatie inseamna mai mult decat un concurs de succes cu premii foarte mari. El este un loc al pasiunilor si al initiativelor, un concurs unde toata lumea gandeste liber si discuta, o tabara a tinerelor talente. Este un concurs independent pentru oameni independenti, organizat cu pasiune si daruire pentru elevi.\r\n\r\nFirmele care au sponsorizat sau au oferit cursuri si consultanta au deja angajati \"produsi\" de InfoEducatie si spun ca vor veni oricand la concurs pentru ca este unic si productiv pentru cei care vor sa-si aleaga ca profesiune programarea: GreenPixel - Marius Deak, GrapefruitDesign - 2 anganjati ce au trecut prin InfoEducatie, Viorel Stan - companie internationala, Octavian Costache - angajat Google NY si exemplele pot continua.',1142,'protected',NULL,NULL),('blog/rezultate-agora-2005','Concursul Agora s-a incheiat!','2005-07-13 00:00:00','2005-07-13 00:00:00','h1. Concursul Agora s-a incheiat!\r\n\r\nConcursul Bursele Agora 2005 s-a incheiat, atat varianta online cat si cea on-site. Rezultatele finale au fost publicate si problemele au fost mutate in arhiva. Cosmin Negruseri, autorul a doua din probleme, a publicat un \"articol despre solutiile problemelor\":http://infoarena.ro/Concursul_Agora_Etapa_Finala_Solutii\r\n\r\nAsteptam parerile si sugestiile tale pe forum legate de acest concurs pe \"forum\":http://forum.infoarena.ro/index.php/topic,414.0.html.\r\n\r\nh2. Castigatorii Online\r\n\r\n==Rankings(rounds=\"ba6\" display_entries=\"3\" pager_style=\"none\")==\r\n\r\nh2. Castigatorii Onsite\r\n\r\n* Locul I Mugurel Ionut Andreica 290 puncte\r\n* Locul II Patcas Csaba 170 puncte\r\n* Locul II Constantin Dolghier 170 puncte\r\n\r\nFelicitari tuturor participantilor si va asteptam sa participati la urmatorul concurs organizat de devNet care va fi in luna august!',13,'protected',NULL,NULL),('blog/ioi-by-net','IOI by net !','2005-08-15 00:00:00','2005-08-15 00:00:00','h1. IOI by net !\r\n\r\nAnul acesta se organizeaza si varianta _\"by net\"_ a Olimpiadei Internationale de informatica. \"Pagina concursului\":http://sio.mimuw.edu.pl/ioi2005/.\r\n\r\nMult succes celor ce vor participa!',1142,'protected',NULL,NULL),('blog/concursul-happy-coding','Concursul Happy Coding','2005-09-09 00:00:00','2005-09-09 00:00:00','h1. Concursul Happy Coding\r\n\r\nSuntem bucurosi sa anuntam concursul Happy Coding, o competitie inedita gazduita de infoarena!\r\n\r\nUn amplu studiu efectuat in laboratoarele infoarena releva un fapt socant: strictetea evaluatorului si necesitatea de a preda o singura solutie buna per problema provoaca riduri vizibile concurentilor dupa numai 2h de competitie, fiind de departe cele mai semnificative surse de stres si hipertensiune pentru concurenti. :)\r\n\r\nh2. Happy Coding si de ce ii spunem noi asa\r\n\r\nConcursul se va desfasura online incepand cu ora 10:00, Sambata (10 septembrie) pana Duminica la ora 22:00 (11 septembrie). Timpul disponibil este asadar de 36h. Timpul recomandat (dar nu obligatoriu!) de lucru este de 4h.\r\n\r\nSe vor propune 6 probleme de dificultate medie ce acopera intreaga programa de informatica pentru clasele 9 - 12. Problemele presupun aplicarea tehnicilor clasice de programare si implementarea unor solutii simple, fara greseli. Propunator unic pentru setul de probleme este Mugurel Ionut Andreica, student la Univsersitatea Politehnica Bucuresti, Facultatea de Automatizari si Calculatoare.\r\n\r\nInedit la Happy Coding este prezenta evaluatorului on-line pe tot parcursul concursului. In alte cuvinte, poti testa mai multe solutii pana esti multumit de punctajul obtinut! Nu mai trebuie sa iti faci griji daca daca programul compileaza pe Linux, daca te incadrezi in limita de memorie sau daca solutia ta e suficient de rapida..\r\n\r\nHappy Coding inseamna programare cu zambetul pe buze, pace, idei, placere si distractie pura! :)\r\n\r\nTe asteptam asadar pe infoarena incepand cu ora 10:00, Sambata (10 septembrie). Si daca tot vorbim de distractie, nu uita sa-ti inviti si prietenii! Avem conturi pentru toata lumea. :)\r\n\r\nAsteptam intrebarile si sugestiile tale pe \"forum\":http://forum.infoarena.ro/',961,'protected',NULL,NULL),('blog/happy-coding-2','Happy Coding 2','2005-10-20 00:00:00','2008-11-26 18:49:02','A trecut mai bine de o luna de la ultimul concurs infoarena.\r\n\"Happy Coding\" a fost un succes total! :) Si cum un lucru bun nu vine niciodata singur, la insistentele publicului am decis sa organizam Happy Coding 2!\r\n\r\n!blog/happy-coding-2?hc2.jpg 50%!\r\n\r\nh2. Happy Coding 2 si de ce ii spunem noi asa\r\n\r\nConcursul se va desfasura incepand cu ora 10:00, Sambata (22 oct.) pana Duminica la ora 22:00. Timpul disponibil este asadar de 36h. Timpul recomandat (dar nu obligatoriu!) de lucru este de 8h.\r\n\r\nSe vor propune 10 probleme de dificultate medie ce acopera intreaga programa de informatica pentru clasele 9 - 12. Problemele presupun aplicarea tehnicilor clasice de programare si implementarea unor solutii simple, fara greseli. Propunator unic pentru setul de probleme este Mugurel Ionut Andreica, student la Universitatea Politehnica Bucuresti, Facultatea de Automatizari si Calculatoare. Inedit la \"Happy Coding 2\" este prezenta evaluatorului on-line pe TOT parcursul concursului. In alte cuvinte, poti testa mai multe solutii pana esti multumit de punctajul obtinut! Nu mai trebuie sa iti faci griji daca daca programul compileaza pe Linux, daca te incadrezi in limita de memorie sau daca solutia ta e suficientde rapida ...\r\n\r\n\"Happy Coding\" inseamna programare cu zambetul pe buze, pace, idei, distractie!\r\n\r\nTe asteptam asadar pe infoarena incepand cu ora 10:00, Sambata (22 oct.).\r\nAsteptam intrebarile si sugestiile tale pe \"forum\":http://forum.infoarena.ro/\r\n',1,'protected',NULL,NULL),('blog/cautari-ortogonale','Cautari Ortogonale','2005-10-29 00:00:00','2005-10-29 00:00:00','h1. Cautari Ortogonale\r\n\r\nUn \'articol\':downloads?Cautari_Ortogonale.doc folosit la pregatirea lotului din anul 2005 care discuta algoritmi de cautari ortogonale si aplicatii ale acestora a fost adaugat la sectiunea \'Download\':Downloads.',1142,'protected',NULL,NULL),('blog/noua-aparitie-editoriala','O noua aparitie editoriala!','2005-09-21 00:00:00','2005-09-21 00:00:00','h1. O noua aparitie editoriala!\r\n\r\nEchipa devNet va recomanda cartea \"Fundamentele programarii, clasa a X-a\" , autori \"Dana Lica\":mailto:danal182001@yahoo.com si \"Mircea Pasoi\":mailto:bogdanpasoi@yahoo.com. Culegerea respecta programa scolara a claselor a X-a de informatica si isi propune sa reprezinte un instrument util atat in munca de initiere in programare cat si in cea de performanta, cuprinzand peste 90 de probleme pentru concursuri si olimpiade.\r\n\r\nCartile le puteti gasi in Bucuresti la:\r\n\r\n* Libraria 88 (Langa Universitate, in spatele librariei Eminescu)\r\n* Libraria Papirus (in Piata Romana)\r\n* Libraria 74 In Piata Romana, la coloane\r\n* Libraria Mihail Sadoveanu (langa cinema Scala)\r\n\r\nh2. Cuprins\r\n\r\n# Capitolul 1: Tipuri structurate de date\r\n## Sir de caractere\r\n### Teste cu alegere multipla si duala\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Inregistrare - structura\r\n### Teste cu alegere multipla si duala\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Probleme de concurs ce proceseaza date structurate\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n# Capitolul 2: Subprograme definite de utilizator\r\n## Subprograme implementate in maniera iterativa\r\n### Teste cu alegere multipla si duala\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Subprograme implementate in maniera recursiva\r\n### Teste cu alegere multipla si duala\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Probleme de concurs\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n\r\n',1142,'protected',NULL,NULL),('preoni-2006/finala/feedback','preONI 2006 Feedback','2006-11-25 00:55:39','2006-11-27 16:05:37','==Include(page=\"template/preoni-2006/header\")==\r\n\r\nh1. Feedback preONI 2006\r\n\r\n|_. &nbsp;|_. Medie |_. Procent |\r\n|_. Concurs | | |\r\n| Cazarea | 4,00 | 80% |\r\n| Mancarea | 4,22 | 84% |\r\n| Distractia | 3,15 | 63% |\r\n| Lifturile de la hotel | 3,52 | 70% |\r\n| Organizarea | 4,61 | 92% |\r\n| Premii | 3,52 | 70% |\r\n| Teatrul | 3,87 | 77% |\r\n|_. Mediul de lucru| | |\r\n|Hardware|3,74|75%|\r\n|Software|3,87|77%|\r\n|Ambient|3,22|64%|\r\n|Sistem de submit|4,70|94%|\r\n|Parola de administrator|3,78|76%|\r\n|_. Evaluarea| | |\r\n|Corectitudine|4,48|90%|\r\n|Promptitudine|4,09|82%|\r\n|Show|3,74|75%|\r\n\r\n&nbsp;\r\n\r\n|_. Probleme|_. Fun|_. Claritate|_. Dificultate|_. Implementare|\r\n|DivK|3,07|4,86|2,93|2,71|\r\n|Lupul Urias si Rau|3,71|4,29|3,00|4,43|\r\n|Overlap|2,14|3,43|4,71|4,14|\r\n|Iv|2,63|4,13|4,50|3,63|\r\n|Robotei|2,88|3,13|4,38|3,38|\r\n|Problema simpla cu nivele|3,44|4,44|2,22|3,11|\r\n|Arbore|3,33|4,22|4,11|3,22|\r\n|Pedefe|2,11|4,22|4,44|4,33|\r\n',13,'protected',NULL,NULL),('preoni-2006/finala/clasament-10','Clasament Finala preONI 2006, Clasa a X-a','2006-11-23 21:08:59','2006-12-01 18:16:00','== include(page=\"template/preoni-2006/finalrankings\") ==\r\n\r\nh2. Clasa a X-a\r\n\r\n==Rankings(rounds = \"preoni65b\")==',13,'protected',NULL,NULL),('blog/final-preoni-2006-runda-2','Runda 2 preONI 2006 s-a incheiat','2005-12-17 00:00:00','2005-12-17 00:00:00','h1. Runda 2 preONI 2006 s-a incheiat\r\n\r\nRunda a doua s-a incheiat. Dificultatea problemelor nu a lasat nici de aceasta data de dorit. Desi ne-am fi asteptat la punctaje mai mari, rezultatele concurentilor au fost decente. Provocarile oferite de infoarena sunt intr-adevar dificile, iar obtinerea unui punctaj apropiat de cel maxim nu este usor de realizat. In editiile ce vor urma vom tine cont de acest aspect. Fiecare grupa a avut spre rezolvare 3 probleme, fiecare fiind catalogata de catre comisie ca fiind usoara, medie sau grea. Batalia pentru calificarea la finala continua!\r\n\r\nPentru mai multe detalii despre finala, cat si despre concursul preONI 2006 si sponsorii nostri va rugam sa consultati \'pagina oficiala\':preONI-2006. S-au publicat rezultatele finale:\r\n\r\n* \'Clasa a IX-a\':preoni-2006/runda-2/clasament-9\r\n* \'Clasa a X-a\':preoni-2006/runda-2/clasament-10\r\n* \'Clasele XI-XII\':preoni-2006/runda-2/clasament-11-12\r\n\r\nSolutiile problemelor se gasesc \'aici\':preoni-2006/runda-2/solutii, va asteptam pe \'forum\':http://forum.infoarena.ro pentru discutii.\r\n\r\n\r\nVa asteptam cu forte noi in noul an la runda a 3-a!',961,'protected',NULL,NULL),('moisil-by-net-2006','Grigore Moisil By net 2006','2006-11-24 18:10:20','2006-11-24 18:24:27','h1. Grigore Moisil By net 2006\r\n\r\nConcursul s-a desfasurat incepand cu ora 16:00, joi, 30 martie 2006. \r\n\r\nAu existat 4 grupe fiecare avand de rezolvat cate 2 probleme mai putin grupa 11-12 care a avut de rezolvat 3 probleme.\r\n\r\nh2. Clasele 7-8 (\'Clasament\':moisil-by-net-2006/clasament-7-8)\r\n\r\n!>moisil-by-net-2007?logo.gif!\r\n\r\n== Tasks(round_id=\"moisil1\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 9 (\'Clasament\':moisil-by-net-2006/clasament-9)\r\n\r\n!>moisil-by-net-2007?logo.gif!\r\n\r\n== Tasks(round_id=\"moisil2\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 10 (\'Clasament\':moisil-by-net-2006/clasament-10)\r\n\r\n!>moisil-by-net-2007?logo.gif!\r\n\r\n== Tasks(round_id=\"moisil3\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':moisil-by-net-2006/clasament-11-12)\r\n\r\n!>moisil-by-net-2007?logo.gif!\r\n\r\n== Tasks(round_id=\"moisil4\" pager_style=\"none\") ==\r\n',961,'protected',NULL,NULL),('blog/final-preoni-2006-runda-3','Runda 3 preONI 2006 s-a incheiat','2006-01-24 00:00:00','2006-01-24 00:00:00','h1. Runda 3 preONI 2006 s-a incheiat\r\n\r\nFiecare grupa a avut spre rezolvare 3 probleme, fiecare fiind catalogata de catre comisie ca fiind usoara, medie sau grea.\r\n\r\nBatalia pentru calificarea la finala se pare ca se va incheia in runda a 4a. Mult succes in continuare!\r\n\r\nPentru mai multe detalii despre finala, cat si despre concursul preONI 2006 si sponsorii nostri va rugam sa consultati \'pagina oficiala\':preONI-2006. S-au publicat rezultatele finale:\r\n\r\n* \'Clasa a IX-a\':preONI-2006/runda-3/clasament-9\r\n* \'Clasa a X-a\':preONI-2006/runda-3/clasament-10\r\n* \'Clasele XI-XII\':preONI-2006/runda-3/clasament-11-12\r\n\r\nSolutiile problemelor se gasesc \'aici\':preONI-2006/runda-3/solutii.\r\n\r\nPentru discutia lor va asteptam pe \'forum\':http://forum.infoarena.ro.',961,'protected',NULL,NULL),('blog/articole-noi','Articole noi','2006-02-02 00:00:00','2006-02-02 00:00:00','h1. Articole noi\r\n\r\nDoua noi articole care au aparut in Gazeta de Informatica in 2005 au fost publicate la sectiunea \"Download\":downloads de catre ==user(user=\"domino\" type=\"tiny\")==. Acestea sunt disponibile si in format PDF.\r\n\r\nAsteptam feedback-ul vostru pe \'forum\':http://forum.infoarena.ro/\r\n\r\n',1142,'protected',NULL,NULL),('blog/topcoder-pentru-liceeni','Liceenii - TopCoderi (legali) incepand din iunie 2006 !','2006-02-07 00:00:00','2006-02-07 00:00:00','h1. Liceenii - TopCoderi (legali) incepand din iunie 2006 !\r\n\r\n\"Topcoder\":http://topcoder.com/tc a anuntat lansarea unei competitii pentru liceeni. Multe din detalii nu sunt inca stabilite, de aceea va incurajam sa intrati pe site si sa discutati pe forum pe baza regulamentului (pentru asta va trebuie un cont pe site). Anuntul se gaseste \"aici\":http://www.topcoder.com/tc?module=Static&d1=hs&d2=home. \r\n',1142,'protected',NULL,NULL),('blog/data-finalei-preoni-2006','ATENTIE! Data finalei preONI: 24-26 martie','2006-03-10 00:00:00','2006-03-10 00:00:00','h1. *ATENTIE!* Data finalei preONI: 24-26 martie\r\n\r\nSuntem nevoiti sa decalam concursul cu o zi. Astfel, vom astepta sosirea celor 30 de finalisti la Focsani oricand in decursul zilei de vineri, 24 martie, iar concursul se va desfasura in data de 25 martie, atat la Focsani, cat si online! Plecarea se va face duminica, iar luni veti putea ajunge la timp la scoala!',1142,'protected',NULL,NULL),('usaco-dec-2004-divizia-gold','USACO decembrie 2004, divizia GOLD - idei de solutii','2004-12-18 00:00:00','2006-11-25 15:31:57','h1. USACO decembrie 2004, divizia GOLD - idei de solutii\r\n\r\n(Categoria _Competitii_, autor(i) _Silviu Ganceanu_)\r\n\r\n\"Setul de probleme\":downloads?gold_dec04.zip pe marginea caruia voi discuta in urmatoarele randuri se afla disponibil in sectiunea download impreuna cu datele de test si rezultatele finale ale concursului (cei care nu stiu setul de probleme si vor sa citeasca articolul sunt rugati sa parcurga mai intai textele problemelor).\r\n\r\nVoi incepe prin cateva observatii in legatura cu evolutia concurentilor din Romania in acest concurs. Asadar un clasament (neoficial) alcatuit intre acestia ar arata in urmatorul mod:\r\n\r\ntable. |_. 1 | Vladu Adrian | 783 puncte|\r\n|_. 2 | Stancu-Mara Sorin | 782 puncte |\r\n|_. 3 | Andrei-Marius Teodorescu | 710 puncte |\r\n|_. 4 | Fechete Dan Ionut | 490 puncte |\r\n|_. 5 | Pasaila Daniel | 436 puncte |\r\n|_. 6 | Paul Diac | 406 puncte |\r\n\r\nRestul concurentilor au avut punctaje sub $400$ de puncte. Primii doi din clasamentul \"nostru\" au reusit sa se strecoare intre primele $20$ de locuri din clasamentul final dar, din nou, remarc lipsa unui roman in topul celor mai buni. Sper mai multe de la concursurile viitore! Mai vreau sa precizez ca Romania nu a dispus de tot arsenalul avut in dotare si concurenti cu rezultate in competiile internationale anterioare precum Dan Crestez si Dan Spatarel nu au fost prezenti in concurs (cel putin nu cu numele lor!). Ei sunt rugati sa participe in viitoarele concursuri (sau sa renunte la pseudonime - daca e cazul), spre binele lor si spre prestigiul Romaniei!\r\n\r\nSetul de probleme a fost unul dificil dar deosebit de frumos, necesitand cunostinte avansate de programare dinamica, structuri de date si teoria grafurilor. Totusi, pentru un concurent experimentat, problemele nu erau in totalitate noi. Spun asta pentru ca toate problemele aveau in substrat idei deja folosite in alte concursuri (CEOI, IOI si chiar barajele noastre).\r\n\r\nLasand comentariile deoparte sa trecem la ce ne intereseaza cel mai mult: solutiile.\r\n\r\nh2. Divide\r\n\r\nProblema se rezolva prin programare dinamica. Prima idee, destul de intuitiva de altfel, este o solutie de complexitate {$O(L * B)$}. Sa notam cu $BST{~l~}$ = numar minim de stropitori de care avem nevoie pentru a acoperi complet intervalul [{$0, l$}] cu $l$ par. Avem urmatoarea recurenta:\r\n\r\n* $BST{~l~}$ = $INFINIT$ daca $l$ este inclus intr-un interval al unei vaci\r\n* $BST{~l~}$ = {$minim(BST{~l - 2 * x~}) + 1$}, cu $x$ intre $A$ si $B$ astfel incat $2 * x$ este mai mic sau egal cu $l$\r\n\r\nPrintr-o implementare directa a recurentei de mai sus obtinem o solutie care foloseste $O(L)$ memorie si $O(L * B)$ operatii (cu observatia ca spatiul de memorie se poate reduce la {$O(B)$}).\r\n\r\nPentru a reduce complexitatea la $O(L)$ operatii se utilizeaza o coada care pastreaza valorile $BST{~x~}$ cu $x$ in intervalul [{$i - 2*B, i - 2*A$}] sortate crescator. Se observa cum se modifica coada cand se trece de la pozitia $i$ la pozitia $i + 2$ (practic \"intra\" valoarea $BST{~i + 2 - 2*A~}$ si \"iese\" valoarea {$BST{~i - 2*B~}$}. Nu voi intra in detalii despre modul cum lucreaza aceasta coada. Pe aceeasi idee (utilizarea acestei cozi) se rezolva si problema \"secventa\":problema/secventa (preOJI 2004 - infoarena) si \"trans\":problema/trans (prima proba a selectiei lotului national largit, Buzau 2004).\r\n\r\nh2. Obstacle\r\n\r\nSi aceasta problema se rezolva tot programare dinamica. Asadar avem $BST{~i, 0~}$ = distanta minima parcursa pentru a ajunge la capatul din stanga al gardului numarul $i$ si $BST{~i, 1~}$ = distanta minima parcursa pentru a ajunge la capatul din dreapta al gardului numarul {$i$}. De asemenea notam cu $Cap{~i, 0~}$ = pozitia capatului din stanga al gardului $i$ in sistemul de coordonte si $Cap{~i, 1~}$ = analog pentru capatul din dreapta. Avem urmatoarele recurenta:\r\n\r\n* $BST{~i, j~}$ = $minim(BST{~k, l~} + dst(Cap{~k, l~}, Cap{~i, j~})$ cu $k$ de la $i + 1$ la {$N$}, $l$ si $j$ fiind $0$ sau $1$ si cu proprietatea ca drumul pe Oy dintre $Cap{~k, l~} la gardul $i$ nu se interpune nici un alt gard.\r\n\r\nAceasta recurenta implementata direct ne da o solutie $O(N^2^)$ care, putin optimizata, ar fi putut obtine punctajul maxim. Totusi exista o solutie $O(N log N)$ care utilizeaza o structura de date numita arbori de intervale. Practic noi trebuie sa aflam pentru fiecare gard $i$ care este gardul pe care cade o bila lasata libera din capatul din stanga si din capatul din dreapta. Aceste informatii ne permit reducerea complexitatii recurentei de mai sus la $O(N)$ (nu va mai spun cum, ganditi si voi!). Pentru a afla informatiile despre care vorbeam se parcurg cele $N$ garduri de la $1$ la $N$ (in ordinea asta!) si se proiecteaza, pe rand, pe axa Ox. Practic se pastreaza axa Ox ca un interval [{$-200.000, 200.000$}] si, pentru un gard {$i$}, se egaleaza toate pozitiile din intervalul [{$Cap{~i, 0~}, Cap{~i, 1~}$}] cu {$i$}. Pentru un afla gardul pe care cade bila se interogheaza arborele pentru fiecare capat al gardului {$i$}. Explicatiile mele nu dezvaluie modul in care lucreaza acest arbore de intervale (mi-ar lua cateva zeci de randuri bune daca as intra in detalii). Pentru cei care nu au idee cum functioneaza acest \"monstru informatic\" le recomand citirea \"articolului\":downloads?arbori_de_interval.zip scris pe tema aceasta din sectiunea \"Download\":downloads.\r\n\r\nh2. Skiarea\r\n\r\nProblema se poate rezolva utilizand cunostinte de teoria grafurilor. Mai intai se contruiesc componentele conexe ale fiecarei celule printr-un algoritm de tipul {$FLOOD FILL$}. Prin componenta conexa intelegem set de celule din matrice cu aceeasi valoarea si care indeplineste propietatea ca intre oricare doua celule exista drum (dupa regulile din enunt). Odata aflate aceste componente conexe se construieste un graf asociat lor in urmatorul mod:\r\n\r\n* fiecare componenta conexa are asociat un nod\r\n* intre doua noduri $x$ si $y$ exista drum daca componenta conexa asociata lui $x$ este \"vecina\" cu componenta conexa a lui $y$ (este usor de intuit ce inseamna \"vecina\") si daca valoarea celulelor din $x$ este mai mare decat valoarea celulelor din {$y$}.\r\n\r\nGraful astfel construit este aciclic (acesta se demostreaza usor). In acest graf aflam nodurile in care nu intra nici o muchie - noduri \"sursa\" - (fie numarul lor {$P$}) si toate nodurile din care nu iese nici o muchie - noduri \"destinatie\" - (fie numarul lor {$Q$}). Solutia pentru problema noastra va fi:\r\n\r\n* maxim dintre $P$ si {$Q$}, daca graful are doua sau mai multe noduri\r\n* {$0$}, daca graful are un singur nod.\r\n\r\nToate cele trei etape ({$FLOOD FILL-ul$}, construirea grafului, aflarea nodurilor \"sursa\" si \"destinatie\") se pot realiza in $O(N*M)$ operatii utilizand $O(N*M)$ spatiu de memorie. Mare atentie insa: nici unul dintre pasi nu trebuie realizat recursiv!! (pentru ca altfel se iese din segmentul de stiva pe testele mari).\r\n\r\n\r\n',1,'public',NULL,NULL),('blog/grigore-moisil-by-net','Concursul interjudetean \"Grigore Moisil\" byNet','2006-03-21 00:00:00','2006-03-21 00:00:00','h1. Concursul interjudetean \"Grigore Moisil\" byNet\r\n\r\nLuni 27 martie, intre orele 16-19, site-ul infoarena va sustine varianta _by net_ a concursului intejudetean de informatica \"Grigore Moisil\", organizat la Bistrita. Subiectele vor avea patru categorii: clasele VII/VIII, clasa a IX-a, clasa a X-a si clasele XI/XII. Problemele vor fi propuse de doamna profesoara Clara Ionescu, Patcas Csaba, Mihai Pantis si Negruseri Cosmin. Va uram succes!\r\n\r\n',961,'protected',NULL,NULL),('moisil-by-net-2006/clasament-7-8','Clasament moisil1','2006-11-23 21:09:00','2006-11-24 18:24:49','h1. Clasament ==roundparam(round_id=\"moisil1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil1\")==',961,'protected',NULL,NULL),('blog/finala-preoni-2006','Finala preONI 2006','2006-03-22 00:00:00','2006-03-22 00:00:00','h1. Finala preONI 2006\r\n\r\nSuntem bucurosi sa anuntam marea runda finala a concursului preONI 2006! Aceasta va incepe in curand, mai exact Sambata, 25 martie, ora 09:00. Durata va fi de 5 ore. Finala se desfasoara la Focsani, in judetul Vrancea, fiind gazduita de Colegiul National \"Unirea\". Aici au fost invitati primii 10 de elevi clasati de la fiecare grupa.\r\n\r\nDesi batalia pentru premii se da intre concurentii de la finala, runda se va desfasura online si va fi deschisa tuturor, in stilul obisnuit infoarena! Ai ocazia sa concurezi cot la cot cu cei din finala!\r\n\r\nInformatii suplimentare (comisii, intrebari, tutorial, cum particip?) gasesti pe \'pagina dedicata acestei runde\':preoni-2006/finala.\r\n\r\nSponsorii rundei finale sunt Oracle Romania, Colegiul National \"Unirea\" si Hotelul \"Unirea\" din Focsani.\r\n\r\nClasamentele si solutiile rundei trecute (runda 4) s-au publicat imediat dupa terminarea timpului de lucru la \'adresa\':preoni-2006/runda-4/solutii.\r\n\r\nClasamentul complet, in urma celor 4 runde de calificare se gaseste \'aici\':preoni-2006/clasament.\r\n\r\nFinalistii preONI sunt primii 10 clasati de la fiecare grupa. Acestia vor concura pentru premii in bani si obiecte, la Focsani. Felicitari!\r\n\r\nh2. Clasa a IX-a (si gimnaziu)\r\n\r\n==Rankings(rounds=\"preoni61a|preoni62a|preoni63a|preoni64a\" display_entries=\"10\" pager_style=\"none\")==\r\n\r\nh2. Clasa a X-a\r\n\r\n==Rankings(rounds=\"preoni61b|preoni62b|preoni63b|preoni64b\" display_entries=\"10\" pager_style=\"none\")==\r\n\r\n\r\nh2. Clasele XI-XII\r\n\r\n==Rankings(rounds=\"preoni61c|preoni62c|preoni63c|preoni64c\" display_entries=\"10\" pager_style=\"none\")==\r\n',961,'protected',NULL,NULL),('blog/probleme-de-hosting-si-grigore-moisil-bynet','Probleme cu site-ul, concursul Grigore Moisil by Net','2006-03-29 00:00:00','2006-03-29 00:00:00','h1. Probleme cu site-ul, concursul Grigore Moisil by Net\r\n\r\nSite-ul infoarena a fost inaccesibil in ultimele doua zile! :( Site-ul a fost mutat (fortat) pe un nou server de webhosting. Dupa mult efort si insistente am reusit sa-l repunem pe picioare. Momentul a fost foarte nefast. A trebuit sa amanam concursul _Grigore Moisil by Net_. Ne pare sincer rau pentru inconveniente! Stim ca au fost utilizatori care s-au straduit si au pierdut timp ca sa fie prezenti in ziua si la ora respectiva. Nu noi am ales momentul. Din fericire, exista si o parte buna... suntem pe un server nou, performant, avem la dispozitie software up-to-date.\r\n\r\nIn sfarsit, putem indica data si ora exacta la care concursul pe care multi l-au asteptat chiar se va desfasura: Joi, 30 martie, ora 16:00. Subiectele vor avea patru categorii: clasele VII/VIII, a IX-a, a X-a si XI-XII. Problemele vor fi propuse de Prof. Clara Ionescu, Patcas Csaba, Pantis Mihai, Negruseri Cosmin. Informatii suplimentare gasesti pe \'pagina oficiala a concursului\':Moisil-by-net-2006.\r\n\r\nTe asteptam!',961,'protected',NULL,NULL),('blog/forum-nou','Forum nou!','2006-04-02 00:00:00','2006-04-02 00:00:00','h1. Forum nou!\r\n\r\nForum-ul infoarena s-a mutat la adresa \'infoarena.devnet.ro/forum\':http://forum.infoarena.ro. Ne pare rau pentru mesajele care s-au pierdut in timpul schimbarii, si asteptam parerile voastre despre noul forum si despre noile optiuni pe care acesta le ofera!',1,'protected',NULL,NULL),('summer-challenge-unu/solutii','Solutii - Summer Challenge Unu','2006-08-03 00:00:00','2007-01-14 13:24:56','h1. Solutii - Summer Challenge Unu\r\n\r\n(Categoria _Competitii_, autor(i) _Cosmin_)\r\n\r\nConcursul a fost unul reusit, adunand un numar respectabil de participanti.\r\nConcurentii ce vor participa la IOI au fost in forma azi ocupand primele trei pozitii ale clasamentului. greco a impresionat placut fiind singurul ce a rezolvat perfect problema de idee a concursului. Il remarcam pozitiv si pe wefgef care se tine aproape de ei, de asemenea o remarca negativa ar fi la adresa lui Adrian Vladu care nu a participat la aceasta pregatire ,desi ea a fost adresata direct lotului olimpic.\r\n\r\nUrmeaza primii 10 clasati:\r\n\r\n==Rankings(rounds=\"summer06\" display_entries=\"10\" pager_style=\"none\")==\r\n\r\nVa invitam mai departe sa va uitati peste schitele solutiilor problemelor propuse.\r\n\r\nh2. Free\r\n\r\nAceasta problema a fost considerata cea mai simpla din concurs, in special pentru ca realizarea unui program experimental care simula pasii din problema ne arata ca usile ce raman inchise au ca index un patrat perfect.\r\n\r\nPentru a demonstra aceasta afirmatie avem nevie de cateva cunostinte minore de teoria numerelor.\r\n\r\nLa fiecare pas $i$ directorul va vizita toti multiplii lui {$i$}, ceea ce inseamna ca un anumit numar $X4 va fi vizitat la pasii ai caror indecsi il divid pe {$X$}. Deci pentru a afla cate usi vor fi deschise in final va trebui sa numaram cate numere au un numar par de divizori. Pentru acest lucru ne va si mai usor sa numaram cate au un numar impar de divizori urmand sa le scadem din {$N$}. Stim ca daca descompunem un numar $X$ in factori primi: {$X=F{~1~}^P{~1~}^*F{~2~}^P{~2~}^*...*F{~t~}^P{~t~}^$} numarul de divizori ai sai va fi {$D=(P{~1~}+1)*(P{~2~}+1)*...*(P{~t~}+1)$}. Pentru ca $D$ sa fie impar trebuie ca fiecare factor al produsului sa fie deci $P{~i~}+1$ impar ceea ce inseamna ca exponentii factorilor primi din descompunere vor fi pari. {$X=F{~1~}^2*P\'{~1~}^*F{~2~}^2*P\'{~2~}^*...*F{~t~}^2*P\'{~t~}^ = (F{~1~}^P\'{~1~}^*F{~2~}^P\'{~2~}^*...*F{~t~}^P\'{~t~}^)^2^$}. Inseamna ca $X$ va fi patrat pefrect.\r\n\r\nAlta demonstratie mai intuitiva ar fi ca pentru usa $X$ putem imperechea actiunea $i$ cu actiunea $X/i$ daca $i$ este divizor al lui $X$ si astfel cele doua isi anuleaza efectul. Daca $X$ este patrat perfect atunci actiunea $[sqrt(X)]$ ramane neimperecheata, deci usa ramane deschisa.\r\n\r\nAstfel solutia problemei va fi {$N-[sqrt(N)]$}.\r\n\r\nOperatiile trebuie implementate pe numere mari. Operatia radical se poate implementa folosind o cautare binara.\r\n\r\nh2. Patrol\r\n\r\nAceasta problema a fost considerata una medie, pentru ca algoritmii de drum minim in grafuri sunt foarte frecvent folositi la concursurile de programare.\r\n\r\nObsevam ca fiecare paznic va fi la orasul de unde a pornit la timpii multipli de {$2*(l{~i~}-1)$} (din cauza miscarii dute-vino). Astfel toti paznicii vor fi in acelasi timp la orasul initial al fiecaruia la toti timpii multipli de {$cmmmc(2*(l{~1~}-1), 2*(l{~2~}-1), ..., 2*(l{~n~}-1))$}. Din cauza ca $l{~i~} < 8$ cel mai mic multiplu comun maxim posibil al numerelor din problema poate fi {$cmmmc(2*4, 2*3, 2*5) = 120$}, astfel pozitiile paznicilor pe reteaua noastra de orase cicleaza si perioada ciclului este $120$ sau un divizor al sau. Vom crea un graf in care nodurile sunt stari ale problemei ({$oras$}, {$timp &#0037; 120$}). Acum am redus problema la determinarea drumului de cost minim de la ({$1, 0$}) la ({$N, timp &#0037; 120$}), putem folosi un algoritm de drum minim la alegere Dijkstra cu heapuri sau bellman ford.\r\n\r\nh2. Pscpld\r\n\r\nAceasta problema se vroia a fi cea mai grea din concurs. O solutie bazata pe siruri de sufixe poate fi gasita in articolul \"Siruri de sufixe\" Adrian Vladu, Negruseri Cosmin, GInfo. Aceasta rezolvare nu ar fi luat punctaj maxim, o solutie similara in $O(n)$ foloseste arbori de sufixe. Denumirea problemei a fost aleasa pentru a sugera ca rezolvarea greoaie cu arbori de sufixe nu este cea cautata. Problema are o solutie simpla in $O(n)$ care urmeaza ideea rezolvarii in {$O(n^2^)$}.\r\n\r\nIn rezolvarea brute force fixam un centru pentru un palindrom si incercam sa marim palindromul cat mai mult. Solutia va pastra un sir $LUNG$ unde $LUNG{~2*i-1~}$ reprezinta lungimea palindromului maxim centrat in caracterul $i$ al sirului si $LUNG{~2*i~}$ lungimea palindromului centrat intre caracterul $i$ si $i + 1$ al sirului. Vom parcurge sirul de caractere de la stanga la dreapta si vom afla in ordine valorile din sirul {$LUNG$}.\r\nSa luam un exemplu:\r\n\r\n== code(cpp) |sirul:  a   b   a   a   b    a     c\r\nLUNG:   1 0 3 0 1 6 1 0 x\r\nindice: 1 2 3 4 5 6 7 8 9 10 11 12 13\r\n==\r\n\r\nAcum daca vrem sa calculam $LUNG{~9~}$ ar trebui sa ne extindem cat putem in lateral fata de {$b$}, dar observam ca centrul palindromului curent este continut in palindromul centrat la {$6$}. Din faptul ca palindromul contine doua subsecvente oglindite, noi nu trebuie sa mai iteram prin literele palindromului nostru pentru ca avem deja rezolvata problema oglindita, si continuam comparatiile cu caractere noi (in cazul nostru avem deja rezolvata problema {$a b a$} in secventa [{$1..5$}] si nu mai trebuie sa o rezolvam inca o data). Am obtinut astfel o rezolvare simpla de complexitate {$O(N)$}. Mentionam ca sursa oficiala nu are mai mult de $50$ de linii.\r\n\r\nExista si alte rezolvari optime posibile si ii rugam pe cei care au luat $100$ de puncte sa le explice in cadrul \"forumului\":http://infoarena.ro/forum/index.php/board,25.0.html.\r\n\r\n',1490,'public',NULL,NULL),('blog/summer-challenge-doi','Summer Challenge Doi','2006-08-06 00:00:00','2006-08-06 00:00:00','h1. Summer Challenge Doi\r\n\r\nConcursul _Summer Challenge Doi_ este continuarea celui de saptamana trecuta. Ne-au motivat reactiile pozitive primite din partea participantilor.\r\n\r\nConcursul se va desfasura vineri, 11 august, ora 12:00. Durata concursului va fi de 5 ore.\r\n\r\n_Summer Challenge Doi_ este o ocazie de antrenament pentru membrii inraiti ai comunitatii infoarena. Se vor propune spre rezolvare $3$ subiecte cu grade diferite de dificultate, de la accesibil la dificil, comparabile cu cele de la Summer Challenge.\r\n\r\nPregatirea problemelor va fi realizata de de Adrian Diaconu, Cosmin Negruseri, Ionut Fechete si Emilian Miron.\r\n\r\nPentru intrebari si sugestii, te asteptam pe \"forum\":http://forum.infoarena.ro/index.php/board,26.0.html.\r\n',1,'protected',NULL,NULL),('moisil-by-net-2006/clasament-10','Clasament moisil3','2006-11-23 21:09:00','2006-11-24 18:25:05','h1. Clasament ==roundparam(round_id=\"moisil3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil3\")==',961,'protected',NULL,NULL),('warm-up-2006/solutii','Solutii Autumn WarmUp 2006','2006-09-07 00:00:00','2007-07-04 18:11:08','h1. Solutii Autumn WarmUp 2006\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa Infoarena_)\r\n\r\nAici puteti gasi solutiile oficiale la cele 5 probleme propuse in concurs. De precizat si ca aceasta initiativa infoarena a fost un succes, adunand un numar respectabil de participanti. Punctajele au fost mai mici decat cele asteptate, fapt ce a confirmat ca setul de probleme a fost unul capabil sa puna in dificultate nume cunoscute la olimpiadele de informatica. Iata si solutiile:\r\n\r\nh2. poly\r\n\r\nProblema este una de programare dinamica si are complexitatea $O(N)$, de constanta $2^7^ = 128$. Sa notam cu $M{~i,j~}$ lungimea celui mai lung subsir utilizand primele $i$ numere din vector astfel incat ultimul element din subsirul optim sa aiba ca divizori numerele din multimea data corespunzatoare bitilor de $1$ din $j$. Mai intai $M{~i,j~}$ = $M{~i-1,j~}$ ( nu folosim numarul al $i$-lea ). Daca dorim sa folosim si numarul al $i$-lea, atunci $M{~i,config~} = maxim(M{~i,config~}$, $M{~i-1,k~} + 1)$, cu $k and config = 0$, unde $config$ are bitii de $1$ corespunzatori numerelor din multimea data cu care se divide acest al $i$-lea numar din sirul initial. Conditia $k and config$ ne asigura ca penultimul si ultimul numar din subsir nu au amandoua vreun divizor comun din multimea data (operatia $and$ in acest context este o operatie pe biti). Rezultatul va fi $max(M{~n,0~}$, $M{~n,1~}$... $M{~n,127~})$. Memoria folosita poate fi $O(1)$, retinand doar ultimele doua linii ale matricei.\r\n\r\nUn algoritm de complexitate patratica in $N$ folosind tot programarea dinamica ar fi obtinut $30-40$ de puncte.\r\n\r\nh2. bridge\r\n\r\nUn algoritm de complexitate $O(M + N * K)$ folosind programarea dinamica nu este foarte greu de gasit. Daca notam cu $M{~i,j~}$ numarul de moduri (modulo $666013$) de a ajunge in $i$ pasi pe scandura $j$ din pozitia initiala, atunci mai trebuie avut grija doar la relatiile de recurenta. In cazul de fata vom utiliza metoda inainte si vom trata cazurile: daca scandura $j$ este lipsa atunci $M{~i,j~} = 0$, daca scandura $j$ este teleportoare incrementam $M{~i+1,unde{~j~}~}$ cu $M{~i,j~}$ daca si numai daca {$unde{~j~}$} nu este lipsa sau subreda ({$unde{~j~}$} este destinatia teleportarii de pe scandura $j$),daca $j$ este scandura buna, incrementam $M{~i+1,j+1~}$ cu $M{~i,j~}$ si $M{~i+1,j+2~}$ cu $M{~i,j~}$ doar daca $j+2$ nu e lipsa sau subreda, etc.\r\n\r\nAvand construita matricea $M$, pentru fiecare query putem raspunde acum in $O(1)$. Exista diferite optimizari care pot fi facute si care sporesc substantial timpul de executie.\r\n\r\n\r\nh2. secv4\r\n\r\nDeoarece logaritmul unui produs de numere este egal cu suma logaritmilor fiecarui numar din produs, si in ipoteza ca toate numerele din sir sunt pozitive, logaritmam fiecare numar si notam cu $S{~i~}$ suma primilor $i$ logaritmi. Astfel, pentru a afla secventa de produs maxim care se termina pe pozitia $i$, este suficient sa determinam, pentru $k$ intre $i-y$ si $i-x$ care este $S{~k~}$ minim (astfel, $S{~i~} - S{~k~}$ va fi maxim, deci si produsul maxim, iar secventa va incepe pe pozitia $k+1$). Putem folosi un arbore de intervale si obtinem un algoritm $O(NlogN)$, sau o coada prin care scoatem elementele prin ambele parti (structura de date numita deque - double ended queue), obtinand complexitatea $O(N)$. Daca exista si numere negative, in momentul logaritmarii numerelor negative logaritmam opusul lor. Aplicand procedeul descris mai sus, stim sigur la final ca produsul obtinut are modulul maxim. Pentru a fi cu adevarat maxim (deci pozitiv), notam cu $semn{~i~}$ semnul produsului primelor $i$ numere. Ca secventa {@<j+1, i>@} sa aiba produs maxim trebuie in plus $semn{~i~} = semn{~j~}$. Vom retine doua deque-uri, unul pentru {$+$} si unul pt {@-@}, conform vectorului semn. Astfel, in final, suntem siguri ca produsul are semnul {$+$} si, cum are si modulul maxim, are valoarea maxima ceruta.\r\n\r\n\r\nh2. parcare\r\n\r\nProblema este exponentiala in dimensiunea matricii, dar polinomiala in numarul total de posibilitati de pozitionare al masinilor. Astfel, vom folosi un algoritm de tip BFS care garanteaza ca se ajunge la solutie intr-un numar minim de miscari. Plecam de la matricea initiala, si expandam pe rand toate starile posibile, miscand din starea curenta cate o masina pana cand nu mai exista nici o varianta noua de pozitionare a masinilor sau pana cand am scos masina A din parcare. Starile problemei le putem codifica intr-un intreg de $64$ de biti. Singurele variabile sunt pozitiile masinilor. Dupa ce eliminam zidurile inconjuratoare, coordonatele nu sunt mai mari decat $7$ ( $3$ biti ), deci pentru pozitia unei masini vom folosi $6$ biti. Concatenam pozitiile masinilor si, cum sunt maxim $10$ masini, codificarea nu va avea mai mult de $60$ de biti.\r\nPentru a memora starile explorate vom folosi o tabela de hash. De precizat si ca numarul total de posibilitati pornind de la starea initiala este destul de redus, deci problema va rula aproape instantaneu.\r\n\r\nh2. easy query\r\n\r\nUn algoritm simplu de complexitate $O(N*M)$ obtine $30-50$ de puncte. Algoritmul de $100$ de puncte are complexitatea $O(MlogN)$ si foloseste arbori de intervale. Considerand o secventa $x{~i~} x{~i+1~}... x{~j~}$ este evident ca pentru ca elementele sirurilor $y$ si $z$ sa fie maxime, respectiv minime, ele trebuiesc construite astfel:\r\n\r\n* $y{~t~} = x{~t~}- min(x{~k~}) + max(x{~p~}), i &le; t &le; j, t &le; k, p &le; j$\r\n* $z{~t~} = x{~t~} - max(x{~k~}) + min(x{~p~}), i &le; t &le; j, t &le; k, p &le; j$\r\n\r\nPentru a calcula in timp optim valoarea $P = max(y) + min(z)$ ne vom folosi de un arbore de intervale in urmatorul mod: fiecare nod al acestuia va constitui o secventa $x{~st~}, x{~st+1~}... x{~dr~}$ ( unde $st$ si $dr$ sunt marginile intervalului din nodul arborelui ) pe care o vom rezolva prin metoda brute force de la inceput, avand grija sa precalculam si alte valori necesare mai tarziu, cum ar fi :\r\n\r\n* $min = minim(x{~st~}, x{~st+1~}... x{~dr~})$\r\n* $max = maxim(x{~st~}, x{~st+1~}... x{~dr~})$\r\n* $x_max_max = maxim(x{~t~} + maxim(x{~p~}) ),st &le; t &le; dr si t &le; p &le; dr$\r\n* $x_max_min = minim(x{~t~} - maxim(x{~p~}) ),st &le; t &le; dr si t &le; p &le; dr$\r\n* $x_min_max = maxim(x{~t~} - minim(x{~p~}) ),st &le; t &le; dr si t &le; p &le; dr$\r\n* $x_min_min = minim(x{~t~} + minim(x{~p~}) ),st &le; t &le; dr si t &le; p &le; dr$\r\n* $y_max = maximul din sirul y corespunzator secventei x{~st~}, x{~st+1~}... x{~dr~}$\r\n* $z_min = minimul din sirul z corespunzator secventei x{~st~}, x{~st+1~}... x{~dr~}$\r\n\r\nAvand precalculate valorile de mai sus pentru fiecare nod al arborelui in parte vom putea raspunde in timp $O(logN)$ pentru fiecare din cele $M$ intrebari. Fiecare subsecventa data $x{~i~}, x{~i+1~}... x{~j~}$ va putea fi compusa din reuniunea mai multor noduri din arborele de intervale. Acum parcurgem nodurile ce compun subsecventa data de la dreapta la stanga si vom gasi rapid valorile $maxim(y)$ si $minim(z)$. Presupunand ca am ajuns la nodul $Q$ valoarea $maxim(y)$ pana aici se calculeaza astfel:\r\n\r\n* @MAX(Y) = maxim (y_max(Q) ; y_max_max(Q) - min(W) ; x_min_max(Q)+max(W) ; max(Q)+max(W)-min(W))@\r\n\r\nAnalog se calculeaza si $minim(z)$.',4772,'public',NULL,NULL),('preoni-2005/runda-2/solutii','preONI 2005 runda #2 - solutii','2005-02-25 00:00:00','2008-01-17 13:04:59','h1. preONI 2005 runda #2 - solutii\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa devNet_)\r\n\r\nDesi s-a desfasurat intr-o zi de miercuri, runda a doua a concursului preONI a avut un numar aproape dublu de accesari fata de runda 1. Acest lucru se datoreaza probabil atat faptului ca olimpiada judeteana \"bate la usa\" cat si prezentei premiilor oferite de sponsorul nostru, Microsoft Romania.\r\n\r\nIn continuarea acestui articol vom descrie solutiile oficiale ale problemelor. Daca aveti nelamuriri puteti sa puneti intrebari pe \"forum\":http://infoarena.ro/forum.\r\n\r\nScopul principal al concursului preONI 2005 este antrenamentul pentru ONI. Nivelul problemelor a fost corespunzator, asa ca nu fiti descurajati la OJI daca n-ati facut foarte bine acum! ;)\r\n\r\nPunctajele sunt multumitoare, fiindca de data asta nu s-au mai acordat cel putin $50p$ pentru solutii \"brute force\". Raportul de dificultate al problemelor a fost pastrat ca la runda {$1$}.\r\n\r\nIn continuare vom prezenta solutiile oficiale ale autorilor problemelor.\r\n\r\nh2. Clasele 9-10\r\n\r\nh3. Clasament\r\n\r\n==Rankings(rounds=\"preoni52a\" display_entries=\"8\" pager_style=\"none\")==\r\n\r\nSub pseudonimele ==user(user=\"arhirel\" type=\"tiny\")== si ==user(user=\"macarie\" type=\"tiny\")== se \"ascunde\", ca si la prima runda, echipa care va reprezenta Romania la finala ACM, formata din Mugurel Andreica, Marius Andrei si Ghinea Dan. Ei au concurat pe un singur calculator pentu a simula un concurs ACM. Stati linistit, premiile se dau doar concurentilor din ciclul de invatamant pre-universitar! De asemenea, se pare ca unii concurenti simt nevoia sa-si creeze mai multe conturi, Sorin Fagateanu avand 3 conturi in top 5 (cele 2 pe numele lui si contul cu numele \"Ion Iliescu\")... Tineti minte ca la un concurs \"standard\" nu aveti voie cu mai multe surse!\r\n\r\nh3. Pascal\r\n\r\nCa sa calculam puterea la care apare factorul prim $p$ in descompunerea lui $n!$ se poate folosi urmatoare formula $f = [n/p] + [n/p^2^] + [n/p^3^] +$ ... ({$[]$} reprezinta partea intrega). Avand acesta formula putem traversa un anumit rand din triunghiul lui Pascal si pt fiecare element ({$r,c$}) putem calcula puterea la care apare $d$ in descompunerea lui $r ! / ((r-c) ! * c!)$ . Atunci cand $d$ nu este prim trebuie sa avem grija sa verificam daca respectivul element ({$r,c$}) are in descompunerea sa toti factori primi a lui {$d$}. Daca $d=6$ , elementul din ({$r,c$}) trebuie sa contina $2$ si $3$ in descompunerea sa, iar daca {$d = 4$}, trebuie sa contina $2$ de cel putin doua ori.\r\n\r\nO alta modalitate sa calculam puterea la care apare un factor prim $p$ in descompunerea lui este: fie {$A{~c~}$} = puterea la care apare $p$ in decompunrea lui ({$r,c$}). $A{~c+1~}$ = {$A{~c~}$} + puterea lui $p$ in ({$r-c$}) - puterea lui $p$ in ({$c+1$}). Acesta relatie se poate deduce din modul din care putem calcula elementul ({$r,c+1$}) din ({$r,c$}) folosind formula ({$r,c$}) = $r ! / ((r-c)! * c !)$\r\n\r\nAceasta a fost cea mai simpla problema de la clasele {$9-10$}, oricare din cele doua idei prezentate mai sus aducand punctaj maxim.\r\n\r\nh3. Secv\r\n\r\nSubsirul trebuie sa contina toate elementele din sirul original in ordine crescatoare asa ca primul pas este sa ne formam acest subsir {$C$}. Avand acest subsir, parcurgem vectorul initial pentru a gasi pozitia de start a noii subsecvente. Dupa ce am gasit o posibila pozitie de start s incercam sa gasim subsirul $C$ avand ca pozitie de start {$s$}. Din toate aceste subsecvente o alegem pe aceea cu lungimea minima. Asftel, complexitatea algoritmului ajunge la {$O(N*M)$}, unde $N$ este lungimea secventei initiale si $M$ lungimea subsirului {$C$}. Problema se poate rezolva in aceeasi complexitate si cu programare dinamica, lasam acesta rezolvare ca exercitiu pentru concurenti!\r\n\r\nh3. Car\r\n\r\nLa prima vedere problema pare simpla si abordabila cu o cautare in latime, dar la o citire mai atenta problema se dovedeste putin mai grea. Cerinta e una de gasire a drumului minim intr-un graf in care nodurile sunt reprezentate de trei intregi ({$i,j,dir$}), $i$ si $j$ avand semnificatia liniei si coloanei din matrice iar $dir$ reprezinta directia cu care am intrat pe pozitia curenta. Muchiile din graful nostru au costurile dupa cum s-a explicat in enunt. Pentru gasirea drumului putem folosi algoritmul Dijkstra care foloseste un heap pentru expandarea nodurilor, complexitatea unei astfel de rezolvari ar fi fost $O(N*M lg (N*M))$ dar un asemenea algoritm nu ar fi luat punctaj maxim. O observatie care ne poate reduce constanta algoritmului ar fi ca nu are rost sa folosim curbe de $180$ sau de $135$ de grade, pentru ca am fi ajuns in aceeiasi pozitie mai repede. Pentru a nu folosi memorie prea multa pentru reprezentarea nodurilor in coada noastra de prioritati am putea folosi un singur intreg in loc de trei astfel:\r\n\r\n== code(cpp) |x = ((i - 1) * m + (j - 1)) * 8 + dir\r\n==\r\n\r\nsi decodificarea ar fi\r\n\r\n== code(cpp) |dir = x % 8; x /= 8;\r\nj = (x % m) + 1;\r\ni = (x / m) + 1;\r\n==\r\n\r\nPentru a avea o viteza mai mare la codificare si decodificare putem folosi operatii pe biti: $dir$ sa fie reprezentat pe $3$ biti {$i$}, pe urmatorii $9$ biti, iar $j$ pe urmatorii $9$ biti ({$i,j &le; 500 < 2^9^=512$}), astfel codificarea si decodificarea devin\r\n\r\n== code(cpp) |x = (i << 9) + j + (dir << 18);\r\ndir = x >> 18;\r\nj = (x & 511);\r\ni = (x >> 9) & 511;\r\n==\r\n\r\nCosturile muchiilor in graful nostru sunt mici si un algoritm ca cel\r\nal lui Dijkstra nu tine cont de aceasta proprietate. Daca aceste costuri sunt mici atunci si costul final al drumului de la sursa la destinatie va fi mic deci ne permitem sa folosim pentru fiecare valoare posibila a costului unui drum de la sursa la destinatie cate o lista. Cand am determinat pentru un nod distanta minima de la sursa la el, il inseram intr-o astfel de lista, observam ca expandarea unui astfel de nod poate afecta numai urmatoarele $4$ liste (prin expandare ne referim la actualizarea distantei minime de la sursa a vecinilor nodului curent). O astfel de rezolvare ar arata cam asa (pseudo-C):\r\n\r\n== code(cpp) |for (dir =0; dir < 8; dir++)\r\n    lst[0].add(starti,startj,dir,0);\r\ncurrent_cost = 0;\r\nwhile (lst[0].size()+lst[1].size()+lst[2].size>0){\r\n    while (lst[curent_cost % 3].size()>0) {\r\n        x = lst[curent_cost % 3].pop();\r\n        expand(x);\r\n    }\r\n    curent_cost++;\r\n}\r\n==\r\n\r\nAm folosit numai trei liste pentru ca am tinut cont de optimizarea precizata mai sus de a nu folosi numai curbele la $0$ grade, $45$ grade si $90$ grade. Fiecare nod poate fi expandat o singura data, si poate fi introdus in liste de cel mult trei ori, deci o astfel de solutie are complexitatea ca timp si ca spatiu {$O(N*M)$}. Mergand mai departe pe aceasta idee putem obtine o rezolvare putin mai buna care injumatateste timpul de executie. Costurile au fost alese intr-un mod particular permitand ca o curba de $90$ de grade sa aiba acelasi cost cu doua curbe de {$45$}, una de $135$ acelasi cost ca trei de $45$ si una de $180$ acelasi cost ca si patru de {$45$}. Astfel putem modifica rezolvarea noastra si sa facem numai miscarile urmatoare: rotiri de $45$ de grade pe loc si miscari in fata pe directia de mers. Astfel procedura de expandare actualizeaza numai trei noduri si in cursul procedurii de actualizare putem sa lucram numai cu lista curenta si cu lista urmatoare, pentru ca efectuam numai miscari de cost zero si unu. Aceasta observatie a micsorat numarul de liste si a micsorat numarul de calcule din metoda expand, cea mai frecvent utilizata in algoritm. O astfel de rezolvare ar fi adus punctajul maxim pe aceasta problema. Mentionam ca toate observatiile facute nu ar fi fost neaparat necesare pentru obtinerea unui punctaj maxim. Testele au fost facute in vederea obtinerii a $50$ de puncte folosind cautare in latime simpla, $60-70$ de puncte folosind Dijkstra cu heapuri si $90-100$ de puncte folosind penultima rezolvare.\r\n\r\nh2. Clasele 11-12\r\n\r\nh3. Clasament\r\n\r\n==Rankings(rounds=\"preoni52b\" display_entries=\"7\" pager_style=\"none\")==\r\n\r\nClasamentul la 11-12 este dominat de echipa ACM care a reusit sa rezolve toate cele 3 probleme (pe unul din cele doua conturi). Este de remarcat faptul ca primii $5$ clasati au punctaje peste $200$ de puncte.\r\n\r\nh3. Indep\r\n\r\nProblema se poate rezolva in mai multe moduri. Limitele au fost alese astfel incat problema sa fie cat mai usoara. Vom prezenta cele doua solutii pe care le puteti gasi interesante:\r\n\r\nh4. Solutia 1\r\n\r\nPrima solutie, si cea mai simpla, utilizeaza principiul programarii dinamice. Se calculeaza numarul de subsiruri din primele $i$ elemente care sunt divizibile cu un numar $j$ intre $1$ si {$1000$}. Sa notam acest numar cu {$Cnt{@[@}i{@][@}j{@]@}$}. Se obtine urmatoare recurenta pentru calculul acestor valori:\r\n\r\n== code(cpp) |Cnt[i][cmmdc(j, A[i])] = Cnt[i - 1][j] + Cnt[i - 1][cmmdc(j, A[i])]\r\n==\r\n\r\nOdata calculate aceste valori solutia o vom avea in {$Cnt{@[@}N{@][@}1{@]@}$}. Numerele depasesc orice tip de date predefinit si trebuie utilizate numere mari. Limitele fiind destul de mari, folosirea bazei $10$ este periculoasa, pe unele teste fiind necesar folosirea bazei $10^9^$ pentru a reduce timpul de executie. De asemenea si memoria se poate reduce, observand faptul ca pentru a calcula {$Cnt{@[@}i{@][@}j{@]@}$} ne sunt necesare doar valorile pentru {$Cnt{@[@}i-1{@][@}k{@]@}$} (ultimele doua linii). Complexitatea acestei solutiei va fi $O(N * K * L)$ unde $K$ reprezinta valoarea maxima din sir si $L$ lungimea maxima a numerelor mari.\r\n\r\nh4. Solutia 2\r\n\r\nCea de-a doua solutie, cu mult mai interesanta decat prima, foloseste principiul includerii se excluderii. Fie $D(x)$ multimea numerelor din sir care sunt divizibile cu un anumit numar {$x$}, atunci numarul de submultimi formate doar din astfel de numere este {$Z(x) = 2^card(D(x))^-1$}. Multimile pentru principiul includerii si excluderii sunt chiar {$D(p)$}, unde $p$ este un numar prim. Intersectia {$D(p{~1~})$}, {$D(p{~2~})$}, {$D(p{~3~})$}.. este {$D(p{~1~} * p{~2~} * p{~3~}...)$}, oarecum evident, pentru $p$ distincte. Rezultatul este de forma:\r\n\r\n== code(cpp) |Rezultat = Z(1) - Z(2) - Z(3) - Z(5)... +\r\n           Z(2 * 3) + Z(2 * 5) + Z(3 * 5)... -\r\n           Z(2 * 3 * 5) ...\r\n==\r\n\r\nAcesta se deduce din principiul includerii si al excluderii. Pentru a-l calcula efectiv, luam toate numerele {$x < 1000$}, produs de numere prime distincte, si vom adauga sau scadea $Z(x)$ in functie de paritatea numarului de factori ai acestuia. Nu ne intereseaza decat produsele de numere prime distincte, care pot fi obtinute ca un produs {$p{~1~}*p{~2~}*p{~3~}$}... Complexitatea finala este sub {$O(N*K + N*L)$}, unde $K$ si $L$ au semnificatia de mai sus. Folosim $O(N*K)$ pentru a calcula $D(x)$ pentru fiecare {$x$}, dar pentru fiecare $x$ adunam sau scadem $Z(x)$ o singura data, asa ca facem doar $N$ operatii pe numere mari, o imbunatatire majora asupra primei rezolvari. Pentru a obtine aceasta complexitate este nevoie sa precalculam valorile lui $2^x^$ in {$O(N * L)$}, altfel ca sa calculam $Z(x)$ pentru fiecare ar fi nevoie de $O(L * X)$ timp.\r\n\r\nh3. Cerere\r\n\r\nProblema este de dificultate medie. O rezolvare $O(N*lg(N))$ este usor de gasit, fiind asemanatoare cu una deja exista in arhiva, \"Stramosi\":http://infoarena.ro/problema/stramosi. Dar o astfel de rezolvare n-ar fi adus punctaj maxim in mod normal. Problema se poate rezolva printr-o simpla parcurgere in adancime din radacina implementand manual stiva DF-ului. Cand vom pune un nod $n$ pe pozitia $p$ in stiva, al {$K$}-lea stramos va fi nodul de pe pozitia $p-K$ din stiva, pentru care s-a procesat deja valoarea ceruta. Complexitatea finala a algoritmului va fi {$O(N)$}.\r\n\r\nh3. Rubarba\r\n\r\nAceasta problema e clasica in geometria computationala. O prima observatie care ne ajuta in rezolvare este ca numai punctele de pe infasuratoarea convexa influenteaza forma dreptunghiului minim. Deci primul pas in rezolvarea problemei este sa gasim infasuratoarea convexa a punctelor in {$O(N*lg(N))$}. Daca avem fixata o directie atunci e usor sa determinam in $O(h)$ (unde $h$ e numarul de puncte de pe infasuratoarea convexa) cele patru puncte ce marginesc dreptunghiul dupa directia aleasa si dupa directia perpendiculara. Folosind cautare binara pentru a determina cele patru puncte extreme, reducem astfel complexitatea la {$O(lg(h))$}. Observatia finala este ca un dreptunghi de arie minima ce contine o multime de puncte in interior trebuie sa aiba o latura paralela cu una din laturile infasuratorii convexe, aceasta idee este intuitiva dar demonstratia ei nu este foarte simpla. Complexitatea algoritmului ce rezolva problema poate fi $O(N*lg(N) + h^2^)$ sau $O(n*lg(n) + h*lg(h))$ daca folosim cautarea binara. Testele folosite au fost generate aleator, generand aleator puncte in plan infasuratoarea convexa va avea cardinalul $h$ teoretic egal cu {$&#920;(lg(N))$}, deci rezolvarea $O(N*lg(N) + h^2^)$ ar fi luat fara probleme punctaj maxim. Mentionam ca exista o tehnica numita \"Rotating Calipers\" care rezolva aceasta problema si altele similare in {$O(N*lg(N) + h)$}, daca vreti sa cititi despre aceasta tehnica accesati \"pagina\":http://cgm.cs.mcgill.ca/~orm/rotcal.html. Idei de acolo v-ar fi ajutat sa rezolvati problema propusa recent la \".campion\":http://campion.edu.ro/index.php, care cerea separarea a doua poligoane convexe cu o dreapta, si o prolema propusa anul trecut la Bursele Agora care cerea determinarea distantei maxime ce exista intre oricare doua puncte dintr-o multime, si tot pe acea pagina gasiti demonstratia matematica a faptului ca dreptunghiul de arie minima ce contine in interior o multime de puncte are o latura paralela cu o latura a infasuratorii convexe.\r\n\r\nh2. Incheiere\r\n\r\nPana la urmatorul concurs, BAFTA LA OJI!\r\n\r\n',3997,'public',NULL,NULL),('template/infoarena','template/infoarena','2006-11-27 00:34:41','2006-11-27 00:35:58','Special infoarena template\r\n\r\n== Gallery(page=\"template/infoarena\" file=\"%\") ==',13,'protected',NULL,NULL),('preoni-2006/program','Program, preONI 2006','2006-11-26 04:45:25','2006-11-27 16:14:30','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Program\r\n\r\nConcursul este structurat in 3 grupe dupa cum este precizat si in regulament. Acest lucru se datoreaza structurarii similare care se practica la Olimpiada Nationala de Informatica. Concursul va fi impartit in 4 etape online si la sfarsit primii 10 participanti la fiecare grupa conform clasamentului se vor califica la etapa finala on-site a concursului.\r\n\r\nh2. Etapele Online\r\n\r\nSubiectele vor fi atent alese de o echipa de specialisti in domeniu cu experienta vasta in concursuri. Acestea vor fi similare ca dificultate cu cele date la ONI in anii prcedenti. Fiecare grupa va avea spre rezolvare cate 3 probleme in 4 ore, oferindu-se un sfert de ora suplimentar pentru ca toti concurentii sa isi trimita sursele.\r\n\r\nIn continuare va vom prezenta programul celor 5 runde ale concursului, cu mentiunea ca pot interveni schimbari in orice moment.\r\n\r\n|_. Runda  |_. Logo |_. Data |_. Pagina rundei, cu detalii |\r\n| #1 | !preoni-2006/program?runda1.jpg 50%! | 19 noiembrie 2005 | \"Runda 1\":preoni-2006/runda-1 |\r\n| #2 | !preoni-2006/program?runda2.jpg 50%! | 17 decembrie 2005 | \"Runda 2\":preoni-2006/runda-2 |\r\n| #3 | !preoni-2006/program?runda3.jpg 50%! | 21 ianuarie 2006  | \"Runda 3\":preoni-2006/runda-3 |\r\n| #4 | !preoni-2006/program?runda4.jpg 50%! | 19 februarie 2006 | \"Runda 4\":preoni-2006/runda-4 |\r\n|Finala| !preoni-2006/program?runda5.jpg 50%! | 24-26 martie 2006 | \"Runda finala\":preoni-2006/finala |\r\n\r\nh2. Runda finala\r\n\r\nEtapa finala se va desfasura in cadrul unei tabere intr-o locatie care va fi stabilita in curand. Cei care nu se vor califica la runda finala vor putea participa on-line pe info-arena la aceasta proba. Pentru mai multe detalii faceti click aici. \r\n\r\n==include(page=\"template/preoni-2006/footer\")==\r\n',13,'public',NULL,NULL),('colaboratori-infoarena','Colaboratori infoarena','2006-11-27 08:32:10','2006-11-27 08:32:10','h1. Colaboratori\r\n\r\n==include(page=\"template/todo\")==\r\n\r\n_(aici trebuie sa punem un macro cu atribute/tags de utilizatori)_\r\n',13,'public',NULL,NULL),('contact','Contact','2006-11-27 08:42:57','2010-02-16 19:12:23','h1. Contact\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nCel mai usor poti lua legatura cu noi pe ==SmfLink(link=\"forum\" caption=\"forum\")==. Aici ne gasesti pentru intrebari, sugestii, probleme.\r\nPe forum discutam despre articolele si despre problemele de pe site. *Chiar si in timpul concursurilor online, intrebarile catre comisie se adreseaza pe forum*.\r\n\r\nPentru sponsorizari, detalii despre activitatea noastra etc. trimite un e-mail la @contact@infoarena.ro@ .',1490,'public',NULL,NULL),('summer-challenge-3/solutii','Solutii - Summer Challenge Trei','2006-08-27 00:00:00','2007-06-04 18:14:54','h1. Solutii - Summer Challenge Trei\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa Infoarena_)\r\n\r\nh2. ABC\r\n\r\nProblema se reduce la $3$ cazuri, in functie de cum este $C$ fata de suma termenilor sirului {$A$}. Daca aceste numere sunt egale, sirul $D$ cautat este chiar sirul {$A$}. In caz contrar, vom rezolva problema pentru $C$ mai mare, celalalt caz fiind analog. Va trebui deci sa marim cateva dintre elementele lui {$A$}. O observatie este utila in acest moment: daca {$A{~i~}<A{~j~}$}, atunci exista o solutie optima cu {$D{~i~}<D{~j~}$}. Pentru a demonstra aceasta afirmatie, observati ca in caz contrar, interschimband valorile $D{~i~}$ si $D{~j~}$ se obtine o solutie pentru care suma termenilor lui $D$ este aceeasi, dar valoarea maxima a sirului din enunt (pe care o vom numi in continuare {$delta$}) este mai mica, sau in cel mai rau caz egala.\r\n\r\nSa incercam acum sa obtinem un sir $D$ pentru o valoare fixata a lui {$delta$}. Pornim cu sirul $D$ egal cu cel initial, {$A$}. Atat timp cat suma termenilor lui $D$ este mai mica decat $C$ vom aplica urmatoarea operatie: vom mari cu o unitate un termen al lui {$D$}. Mai trebuie avut grija ca tot timpul sa fie respectata conditia {$D{~i~} &le; A{~i~}+delta$}. Daca nu mai putem aplica nici o operatie (toti termenii au atins valoarea maxima posibila, sau prin marire am obtine o diferenta mai mare decat {$delta$}), si inca nu am obtinut {$C$}, nu putem gasi nici un sir $D$ pentru acest {$delta$}, si in plus am obtinut un sir $D$ cu suma termenilor maxima posibila pentru valoarea curenta a lui {$delta$}. Se poate demonstra ca nici nu conteaza ce termen marim, atat timp cat respectam observatia din paragraful anterior. Pentru a obtine insa o complexitate liniara la acest pas, vom mari termenii in ordine descrescatoare (evident dupa o sortare initiala). Bineinteles, nu este nevoie sa aplicam fiecare operatie in parte, ele vor fi aplicate toate in acelasi timp. Pentru cazul analog din paragraful precedent, o operatie va consta din scaderea unui termen cu o unitate, pornind de data aceasta de la cel mai mic.\r\n\r\nIn plus, daca marim valoarea lui $delta$ la {$delta+1$}, putem aplica in continuare operatii asupra lui {$D$}, de unde am ramas la pasul precedent, obtinand deci sume mai mari. Se contureaza acum o rezolvare: putem cauta binar valoarea lui {$delta$}. Daca am obtinut un sir $D$ care sa respecte conditiile din enunt, putem cauta un $delta$ mai mic, daca nu, trebuie sa marim {$delta$}. Complexitatea algoritmului rezultat este {$O( N log N)$}.\r\n\r\nDupa sortarea sirului {$A$}, putem obtine un algoritm liniar rafinand solutia de mai sus. Aceasta afirmatie se bazeaza pe urmatoarea observatie (presupunem sirul $A$ sortat in ordine descrescatoare): daca putem creste $A{~i~}$ cu valoarea {$d$}, atunci putem creste cu valoarea $d$ orice {$A{~j~}$}, cu {$j > i$}. Vom parcurge valorile lui $A$ in ordine crescatoare a indicilor. La pasul $i$ ({$i$} ia valori intre $1$ si {$N$}) ne folosim de valorile {$D{~i-1~}$}(convenim ca {$D{~0~}=B$}) si $S$ (numarul de unitati cu care mai trebuie marita suma in continuare) si vom creste pe $A{~i~}$ cu valoarea {$d=min(D{~i-1~}-A{~i~}, ceil(S/(N-i+1)))$}. Bineinteles, la pasul urmator si $S$ va scadea corespunzator.\r\n\r\nh2. Oras\r\n\r\nSa presupunem ca avem o solutie pentru $N-2$ noduri. Acum adaugam la solutie nodurile {$N-1$}, si {$N$}. Fara a restrange generalitatea putem orienta strada ({$N-1, N$}) de la {$N-1$}, la {$N$}. Acum oricare ar fi un nod $X$ de la $1$ la $N-2$ trebuie sa fie pe un circuit de $3$ noduri cu nodurile $N-1$ si {$N$}. Astfel putem fixa ca de la nodurile ${1, 2, ..., N-2}$ sa plece arce inspre nodul {$N-1$}, si de la nodul $N$ sa plece arce inspre nodurile {${1, 2, ..., N-2}$}. Daca graful initial cu $N - 2$ noduri satisfacea conditiile problemei, atunci si graful obtinut este valid. Pentru $N = 3$ exista o solutie triviala, pentru $N = 4$ putem demonstra ca nu exista solutie (demonstratia trebuind sa ia in calcul mai multe cazuri), sau putem sa generam exhaustiv toate grafurile turneu cu $N = 4$ si sa observam ca nici unul nu e valid. Gasirea unei solutii pentru $N = 6$ este destul de facila (autorului i-a luat $2$ minute). Astfel am aratat ca avem solutie pentru toate cazurile din problema, inafara cazului {$N = 4$}. Complexitatea acestei solutii este {$O(N^2^)$}.\r\n\r\nh2. Gold\r\n\r\nSolutia triviala este {$O(N^3^)$}: se aleg doua puncte si se verifica suma cantitatilor din ambele parti ale dreptei printr-o parcurgere noua a punctelor. O astfel de solutie obtine $30-40$ de puncte. Pornind de la aceasta idee se poate rafina ajungand la o complexitate de {$O(N^2^logN)$}. Pentru fiecare punct $P$ sortam celelalte $N-1$ puncte dupa unghiul polar ( unghiul format de punctul curent cu axa Ox, daca consideram originea in punctul {$P$}) in {$O(NlogN)$}. Notam cu {$S{~i~}$} suma cantitatilor din primele $i$ mine in ordinea ordonarii dupa unghi. Vom fixa o dreapta de baleiere care sa treaca prin punctul $P$ si prin primul punct in ordinea sortarii. Daca am calculat la un anumit pas toate punctele aflate de o parte a dreptei de baleiere, in momentul in care rotim dreapta de baleiere pana ajunge in dreptul urmatorului punct (in ordinea sortarii) toate aceste puncte raman de aceeasi parte mai putin cel aflat pe dreapta si eventual se vor adauga unele noi. De aceea vom incepe cautarea ultimului punct aflat in sensul $+$ al dreptei de baleiere de la punctul calculat la pasul anterior( toti indicii vor fi calculati modulo {$N$}). Fiecare punct va fi parcurs de cel mult doua ori, deci complexitatea acestui pas este {$O(N)$}. Astfel vom putea calcula in $O(1)$ sumele de o parte si de alta a dreptei folosindu-ne de vectorul {$S$}.\r\n\r\n',4452,'public',NULL,NULL),('blog/autumn-warmup-2006','Autumn WarmUp 2006','2006-09-05 00:00:00','2007-01-27 19:55:02','h1. Autumn WarmUp 2006\r\n\r\nInfoarena organizeaza inca un concurs vacanta asta pentru a te mentine in forma. De data aceasta, echipa infoarena \"a predat stafeta\", si da o sansa celor mai dedicati utilizatori sa realizeze propriul lor concurs - un concurs facut de utilizatori pentru utilizatori.\r\n\r\nSe vor propune spre rezolvare $5$ subiecte cu grade diferite de dificultate, de la accesibil la dificil. Evaluatorul va fi pornit pe toata durata concursului.\r\n\r\nProblemele vor fi propuse de:\r\n\r\n* ==user(user=\"PaulDB\" type=\"tiny\")==\r\n* ==user(user=\"vladcyb1\" type=\"tiny\")==\r\n* ==user(user=\"vladut\"  type=\"tiny\")==\r\n* ==user(user=\"devilkind\"  type=\"tiny\")== \r\n* ==user(user=\"VladSaveluc\"  type=\"tiny\")==\r\n\r\nSperam ca si acest concurs va fi un succes si va asteptam in numar cat mai mare.',75,'protected',NULL,NULL),('template/newround/clasament','Clasament %round_id%','2006-11-23 00:06:53','2010-03-28 09:13:40','h1. Clasament ==roundparam(round_id=\"%round_id%\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"%round_id%\" detail_task=\"true\")==',1490,'protected',NULL,NULL),('aplicatii-ale-cautarii-binare','Aplicatii ale cautarii binare','2004-12-20 00:00:00','2009-02-20 01:14:39','h1. Aplicatii ale cautarii binare\r\n\r\n(Categoria _Tehnici de programare_, Autor _Andrei Teodorescu_)\r\n\r\nVoi prezenta in articolul care urmeaza cateva aplicatii ale cautarii binare. Algoritmii descrisi nu sunt intotdeauna optimi insa prezinta avantajul implementarii mult mai rapide, lucru care constituie un avantaj pe timp de concurs.\r\n\r\n# Sa se gaseasca (daca exista) cel mai mic numar natural $N$ astfel incat {$N!$} sa se termine in exact $p$ cifre de {$0$}, {$p &le; 10^18^$}\r\n# Se considera un teren de forma dreptunghiulara reprezentat de o matrice {$NxN$} care contine in pozitia ({$i,j)$} $1$ daca aceasta este accesibila sau {$0$}, altfel. Se dau $2$ puncte (x{~1~},y{~1~}) si (x{~2~},y{~2~}). Sa se afisize latura maxima a unui patrat care poate fi deplasat intre cele 2 puncte astfel incat acesta sa se afle in orice moment al deplasarii numai pe teren _bun_ (numai cu cifre de {$1$}).\r\n# Sa se calculeze cel mai lung subsir crescator al unui sir de $N$ numere.\r\n# Sa se calculeze cu precizie de $Z$ zecimale: \r\n## radicalul unui numar mare\r\n## catul a $2$ numerere mari (consideram un numar mare un numar cu cel putin $20$ de cifre, care nu poate fi stocat in tipuri de date conventionale)\r\n\r\nIn prima problema trebuie sa observam prima oara ca numarul de zerouri in care se termina {$N!$} creste odata cu {$N$}, observatie evidenta datorita definitiei lui {$N!$}. Atunci, putem cauta binar valoarea lui $N$ pentru care se verifca relatia din enunt. Recomand problema \"Factorial\" din arhiva de probleme InfoArena celor interesati de implementarea algoritmului.\r\n\r\nPentru a doua problema este usor de aratat ca daca daca se poate deplasa intre cele $2$ puncte un patrat de latura {$l$}({$l &ge; 2$}), atunci sigur se va putea deplasa si unul de latura $l-1,l-2...1$ iar daca nu putem deplasa un patrat de latura {$l$}, atunci nu putem deplasa nici unul de latura {$l+1,l+2...n$}. Astfel avem de cautat o valoare $l$ astfel incat putem deplasa un patrat de latura $l$ insa nu si unul de latura {$l+1$}. Numarul $l$ va fi chiar rezultatul cautat. Pentru a face verificarea daca putem deplasa un patrat de o latura data putem folosi algoritmul lui Lee, care implementat atent va avea o complexitate de {$O(n^2^)$}.\r\n\r\nNu voi insista prea mult asupra algoritmului de aflare a celui mai lung subsir crescator al unui sir, problema fiind cunoscuta, de asemenea se gaseste si in cartea \"Psihologia concursurilor de informatica\" de Catalin Francu. Idee de baza este sa se caute binar de fiecare data pozitia fiecarui element intr-un subsir crescator cat mai lung.\r\n\r\nPentru calcularea radicalului unui numar sau calcularea catului a doua numere se cunosc inca din gimnaziu algoritmi! :) Insa acesti algoritmi sunt destul de greu de implemantat(si oricum ajung la un moment dat la folosirea cautarii binare). Asadar in loc de a calcula rezultatul il putem cauta. De exemplu, in primul caz vom cauta o valoare a lui $n$ pentru care $n*n$ sa nu depaseasca numarul dat, insa $(n+1)*(n+1)$ sa depaseasca. Asemanator se procedeaza si in cazul impartirii.\r\n\r\nPentru utilizarea acestor doi algoritmi trebuie ca cel care ii scrie sa stapaneasa foarte bine inmultirea, adunarea, compararea si, eventual, impartirea la $10$ a numerelor mari (vezi articolul de pe site :D). Pentru a obtine o precizie de $z$ zecimale se inmulteste numarul dat(in primul caz)cu $10^2*z^$ si deimpartitul(in al doilea caz) cu $10^z^$ iar in rezultatul obtinut ultimle z cifre vor fi zecimalele iar restul, partea intreaga.\r\n\r\nCa observatie, trebuie sa aveti grija intotdeauna cand alegeti intervalul in care se face cautarea pentru a fi siguri ca algoritmul va produce rezultatlul dorit!\r\n\r\nIn final invit cititorii sa rezolve cateva probleme cu ajutorul cautarii binare:\r\n\r\n* problema \"Proc\":http://www.infoarena.ro/problema/proc, ONI 2003, clasele XI-XII\r\n* problema \"Stramosi\":http://www.infoarena.ro/problema/stramosi din arhiva de probleme InfoArena ( indicatie: se realizeaza o parcurgere Euler si o parcurgere in latime a arborelui iar apoi se cauta ficare nod cerut pe nivelul pe care se afla)\r\n* problema \"Loto\":http://www.infoarena.ro/problema/loto din arhiva de probleme InfoArena\r\n* problema \"Secventa 3\":http://www.infoarena.ro/problema/secv3 din arhiva de probleme InfoArena\r\n* problema \"Tabara\":http://www.liis.ro/~campion/problems/2/96/tabara.htm\r\n* problema \"Multiplu\":http://www.liis.ro/~campion/problems/1/172/multiplu.htm\r\n* problema \"Impartire in trei\":http://www.algoritmus.org/probleme/Probleme_Runda02.php (Algoritmus, Runda 2, Problema 1)\r\n* problema \"Suma\":http://www.algoritmus.org/probleme/Probleme_Runda05.php (Algoritmus, Runda 5, Problema 5)\r\n\r\n',2044,'public',3697,NULL),('blog/bits-n-bytes','Bits \'n\' Bytes ','2005-02-07 00:00:00','2005-02-07 00:00:00','h1. Bits \'n\' Bytes \r\n\r\nInca un consurs de programare indian. Concursul se desfasoara pe 2 martie si dureaza 24 de ore, si e individual. Detalii mai multe pe \"site-ul oficial\":http://showcase.csa.iisc.ernet.in/bitsnbytes/index.html.\r\n',1142,'protected',NULL,NULL),('bacalaureat-2005','Bacalaureat 2005','2006-11-23 21:08:54','2006-11-25 01:47:12','h1. Bacalaureat 2005\r\n\r\nArhiva contine subiecte de bacalaureat propuse de mai multi profesori de informatica din tara. \r\n\r\nToate subiectele dispun de un evaluator online 24/7!\r\n\r\nSucces!\r\n\r\nh2. \'Clasament\':bacalaureat-2005/clasament\r\n\r\n!>bacalaureat-2005?logo.gif!\r\n\r\n== Tasks(round_id=\"bac2005\" pager_style=\"none\") ==\r\n',961,'protected',NULL,NULL),('preoni-2006/finala/poze','Poze finala preONI 2006','2006-11-25 15:01:34','2006-11-27 16:09:06','==Include(page=\"template/preoni-2006/header\")==\r\n\r\nh1. Poze finala preONI 2006\r\n\r\n== Gallery(page=\"preoni-2006/finala/poze\" file=\"%.jpg\") ==',13,'protected',NULL,NULL),('preoni-2006/runda-1/clasament-11-12','Clasament preoni61c','2006-11-25 01:17:08','2006-11-25 01:17:08','h1. Clasament ==roundparam(round_id=\"preoni61c\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni61c\")==',961,'protected',NULL,NULL),('template/cleanup','template/cleanup','2006-11-11 15:05:08','2008-02-04 20:59:07','table{margin:0.5em auto;}. |={background-color:#FFFFCC;border:1px solid FFCC66;}. !<template/cleanup?cleanup.png! _Continutul acestei pagini nu este formatat conform_ \'*recomandarilor de formatare*\':documentatie/conventii-de-formatare.\r\n_Daca aveti permisiunile necesare, va rugam sa il imbunatatiti._  |\r\n\r\n',1,'protected',NULL,NULL),('testgal','Test Gallery','2006-12-04 09:12:05','2006-12-04 09:15:12','h1. Test Gallery\r\n\r\n==gallery(page=\"testgal\" file=\"%.jpg\")==',13,'public',NULL,NULL),('doua-probleme-de-la-runda-6-a-concursului-algoritmus','Doua probleme de la runda 6 a concursului Algoritmus','2005-01-13 00:00:00','2006-11-22 02:18:26','h1. Doua probleme de la runda 6 a concursului Algoritmus\r\n\r\n(Categoria _Competitii_, autor(i) _Cosmin_)\r\n\r\nDupa incheierea brusca a concursului Algoritmus, ideile de rezolvare ale rundei 6 nu au mai aparut pe site. In acest articol va voi prezenta ideile de rezolvare la problemele la care eu am realizat solutiile oficiale.\r\n\r\nh2. Problema 1: Suprafata\r\n\r\nPentru a rezolva problema folosim paradigma liniei de baleiere folosita mult in rezolvarea problemelor de geometrie computationala (vezi si articolul arbori de intervale din sectiunea download pt alte exemple de probleme in care se foloseste linia de baleiere). Vom considera ca puncte eveniment toate punctele de intersectie intre oricare doua cercuri si punctele de $y maxim$ si de $y minim$ pentru un cerc. Noi avem nevoie numai de coordonata $y$ a acestor puncte pe care o punem intr-un sir. Sortam acest sir ce are maxim $n*(n-1) + 2*n$ coordonate distincte ( $n*(n-1)$ provin din intersectii a cate doua cercuri iar celelalte $2*n$ din $y maxim$ si $y minim$ pentru fiecare cerc). Intre doua coordonate $Y$ consecutive din vectorul sortat nu exista nici o intersectie intre cercuri. Intersectia unui cerc cu o banda determinata de $Y{~i~}$ si $Y{~i+1~}$ este un fel de trapez curbat pe care ni-l putem imagina ca o paranteza deschisa si una inchisa. Pentru a determina aria intersectiei multimii de cercuri cu banda determinata de $Y{~i~}$ si $Y{~i+1~}$ putem sa facem un algoritm care sorteaza intai \"parantezele\" si dupa aceea parcurge sirul sortat al parantezelor. Cand nivelul de imbricare e $0$ inseamna ca tocmai am iesit din cercuri iar nivel de imbricare mai mare ca $0$ inseamna ca suntem in interiorul intersectiei. De aici scoatem un algoritm liniar care ne determina intersectia cercurilor cu aceasta banda. Pentru a determina aria ocupata de un trapez curbat trebuie sa putem determina aria dintre coarda si arcul de cerc corespunzator, aceasta arie se poate gasi daca stim unghiul $alfa$ ce se opune coardei pentru ca aceasta arie e diferenta dintre aria sectorului de cerc ( {$r*r*alpha/2$}) si aria triunghiului format dintre centrul cercului si coarda ({$r*r*sin alpha /2$}), unghiul $alpha$ il aflam folosind functia $arccos$ si $cos alpha$ il determinam cu ajutorul teoremei lui Pitagora generalizate. O mica problema apare in sortarea parantezelor pentru ca daca parantezele provin din cercuri diferite dar le corespunde aceeiasi coarda atunci trebuie sa fim atenti la ordinea in care punem parantezele. Aceasta problema e rezolvata daca gasim un $X3$ pentru fiecare coarda numar ce reprezinta coordonata $X$ a intersectiei parantezei repsective cu linia orizontala de ordonata {$(Y{~i~} + Y{~i+1~}) / 2$}. Am aratat astfel cum se realizeaza determinarea ariei reuniunii cercurilor cu o banda ce nu contine nici o intersectie in {$O(n log n)$}. Din cauza faptului ca sunt in total maxim $O(n^2^)$ benzi repetand algoritmul pe fiecare banda obtinem aria reuniunii\r\ncercurilor in timp {$O(n^3^ log n)$}.\r\n\r\nh2. Problema 4: Joc\r\n\r\nProblema cere determinarea numarului maxim de drumuri disjuncte relativ la noduri pornind de la nodul $A$ si terminandu-se in nodul {$B$}. Daca ar fi restrictia numai pentru muchii nu si pentru noduri atunci raspunsul ar fi egal cu fluxul maxim in reteaua de transport formata astfel: sursa e nodul {$A$}, destinatia e nodul $B$ iar orice muchie ({$i,j$}) din graful initial e dublata in reteaua de transport ({$i,j$}) si ({$j,i$}) fiecare muchie avand capacitate {$1$}. Acesta afirmatie e intiutiva, o demonstratie matematica a ei ar fi aplicarea teoremei clasice: fluxul maxim intr-o retea reziduala este egala cu taietura minima in acea retea si a teoremei lui Menger: numarul maxim de drumuri disjuncte relativ la muchii de la $S$ la $T$ este egal cu taietura minima.\r\n\r\nProblema noastra mai are insa o dificultate, aceea ca trebuie sa nu avem acelasi nod in doua drumuri diferite. Aceasta problema o rezolvam dubland fiecare nod si muchiile ce intrau in nod intra acum in primul dintre cele doua noduri, muchiile ce ieseau ies acum din al doilea nod si mai adaugam o muchie intre primul nod si al doilea nod. Acum drumurile disjuncte relativ la muchii din aceasta retea corespund unor drumuri disjuncte relativ la noduri in prima retea.\r\n\r\nAstfel am redus problema initiala la una de flux in graf pe graful transformat. Complexitatea algoritmului e {$O(n*m)$}. Implementarea nu mai dubleaza nodurile la propriu ci foloseste {$c{~i,i~}$} pentru a reprezenta muchia intre cele doua noduri ce reprezinta nodul $i$ din graful initial.\r\n\r\n',1,'public',NULL,NULL),('moisil-by-net-2006/clasament-11-12','Clasament moisil4','2006-11-23 21:09:01','2006-11-24 18:25:13','h1. Clasament ==roundparam(round_id=\"moisil4\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil4\")==',961,'protected',NULL,NULL),('utilizator/eval','Profil eval','2006-12-03 21:54:32','2007-02-11 19:35:29','h2. Despre mine\r\n\r\nbq. Vorbesc putin dar \"fac multe\":monitor.\r\n\r\nNu-mi trimite PM-uri ca nu-ti raspund.\r\n\r\nh2. Distinctii -primite- date\r\n\r\nToate punctele pe care le-ati primit pe infoarena vi le-am dat eu.\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n* ==User(user=\"fluffy\" type=\"tiny\")==\r\n* ==User(user=\"azotlichid\" type=\"tiny\")==\r\n* ==User(user=\"chucknorris\" type=\"tiny\")==',18,'protected',NULL,NULL),('blog/articol-taietura-minima','Articol nou: \"Taietura minima in graf cu costuri\"','2007-02-04 08:16:00','2007-02-09 18:21:27','A aparut un articol nou despre \'Taietura minima in graf cu costuri\':taietura-minima scris de Andrei Grigorean.',13,'public',NULL,NULL),('noul-infoarena','Noul site infoarena','2007-02-04 18:59:37','2007-02-04 19:01:59','h1. Noul site infoarena \r\n\r\ntable(layout3). | *infoarena este un wiki*\r\nSchimba continutul paginilor sau sa creaza pagini noi.\r\n\'Afla mai multe&hellip;\':documentatie/wiki\r\n| *infoarena iti da rating*\r\nIti calculam rating-ul: un numar care reflecta performantele tale.\r\n\'Afla mai multe&hellip;\':documentatie/rating\r\n| *Forum integrat*\r\nAm avut grija ca forum-ul sa fie bine integrat in experienta infoarena.\r\n\'Afla mai multe&hellip;\':documentatie/forum |\r\n| *Fa-ti pagina personala*\r\nPrezinta-te comunitatii infoarena: cine esti, de unde vii, distinctii primite etc.\r\n\'Afla mai multe&hellip;\':documentatie/pagina-de-profil\r\n| *Un nou evaluator*\r\nEvaluatorul nou masoara mai exact timpii de executie si suporta tipuri noi de probleme si concursuri.\r\n\'Afla mai multe&hellip;\':documentatie/evaluator\r\n| *Mai usor de folosit*\r\nNoul infoarena este mai usor de navigat si de folosit.\r\n\'Afla mai multe&hellip;\':documentatie/pentru-utilizatori |\r\n\r\nh1. Ne trebuie feedback!\r\n\r\nNe asteptam sa gasim multe bug-uri si deficiente in noua versiune. Ajuta-ne sa facem o infoarena ca _Soarele sfant de pe cer_ :)\r\nAsteptam bug reports, sugestii, intrebari pe forum. Iata niste topic-uri de feedback:\r\n\r\n==SmfTopics(board_id=\"33\")==',1,'protected',NULL,NULL),('preoji-2004/clasament-9-10','Clasament preOJI 2004, clasele 9-10','2006-11-23 21:08:49','2006-11-24 00:12:20','h1. Clasament \'preOJI 2004\':preoji-2004, clasele 9-10\r\n\r\n==Rankings(rounds = \"preoji1\")==',1142,'protected',NULL,NULL),('documentatie/macro-uri','Macro-uri','2006-11-22 20:48:39','2009-01-05 16:33:25','h1. Macro-uri\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\n== include(page=\"template/todo\")==\r\n\r\nMacro-uri sunt niste blocuri speciale de text care sunt tratate \'special\' de wiki-ul infoarena. Cu macro-uri se pot face foarte multe lucruri, de la linkuri catre utilizatori pana la tabele de scoruri.\r\n\r\nh2. Sintaxa\r\n\r\nMacro-uri sunt introduse cu o sintaxa de genul @==User(user=\"domino\" type=\"tiny\")==@, si se obtine ==User(user = \"domino\" type=\"tiny\")==. Momentan sintaxa de macro-uri este *foarte* stricta, dar poate cu timpul va fi \"relaxata\". Atentie:\r\n\r\n* Numele macro-urilor nu sunt case-sensitive.\r\n* Parantezele, egalul si ghilimele sunt obligatorii.\r\n* Nu se accepta parameteri dubli sau virgule intre parametetri.\r\n\r\nh2. Macro-uri comune:\r\n\r\n* debug\r\n* gallery\r\n* grep\r\n* hello\r\n* image?\r\n* include\r\n* rankings\r\n* tableofcontents\r\n* tasks\r\n* user\r\n* SmfTopic\r\n* SmfTopics\r\n\r\n*todo* Cum se folosesc / ce fac macro-urile de mai sus? Care dintre ele chiar exista? :)\r\n\r\nh2. Propune si tu un macro!\r\n\r\nDaca iti doresti un macro nu trebuie decat sa ne ceri si vom incerca sa rezolvam. Poti face o cerere de macro \'aici\':http://hackers.devnet.ro/newticket (\'explicatii\':development).',2934,'public',NULL,NULL),('happy-coding-2006','Happy Coding 2006','2006-11-23 21:09:03','2006-11-24 17:44:58','h1. Happy Coding 2006\r\n\r\nConcursul s-a desfasurat incepand cu ora 10:00, Luni 9 Ocombrie 2006, pana Duminica la ora 22:00, 15 Octombrie 2006. Concurentii au avut la dispozitie o saptamana pentru rezolvarea celor 20 de probleme propuse.\r\n\r\nProblemele au fost propuse in mare parte de Mugurel Ionut Andreica, un set de probleme folosite pentru selectia echipe de ACM a Universitatii Politehnica Bucuresti. La acestea s-au adaugat cateva probleme ale lui Mircea Pasoi, Adrian Vladu si Daniel Pasaila.\r\n\r\nh2. \'Clasament\':happy-coding-2006/clasament\r\n\r\n!>happy-coding-2006?logo.jpeg!\r\n\r\n== Tasks(round_id=\"happy2006\" pager_style=\"none\") ==\r\n',961,'protected',NULL,NULL),('utilizator/koosy','Profil koosy','2006-11-24 20:56:14','2007-02-12 20:39:58','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',35,'protected',NULL,NULL),('utilizator/efer','Profil efer','2006-11-24 20:56:20','2007-02-12 20:39:58','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',83,'protected',NULL,NULL),('utilizator/cavin','Profil cavin','2007-01-15 15:07:54','2007-02-12 20:40:13','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5659,'public',NULL,NULL),('utilizator/oanam','Profil oanam','2006-11-24 20:56:30','2007-02-12 20:39:58','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',165,'protected',NULL,NULL),('utilizator/florinr1','Profil florinr1','2006-11-24 20:56:33','2007-02-12 20:39:58','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',192,'protected',NULL,NULL),('utilizator/mars','Profil mars','2006-11-24 20:56:43','2007-02-12 20:39:58','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',272,'protected',NULL,NULL),('utilizator/amadaeus','Profil amadaeus','2006-11-24 20:56:53','2007-02-12 20:39:59','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',354,'protected',NULL,NULL),('utilizator/rus','Profil Rus','2006-11-24 20:57:08','2007-02-12 20:39:59','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',477,'protected',NULL,NULL),('utilizator/miz','Profil miZ','2006-11-24 20:57:15','2007-02-12 20:39:59','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',530,'protected',NULL,NULL),('utilizator/vasile_gales','Profil vasile_gales','2006-11-24 20:57:17','2007-02-12 20:39:59','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',547,'protected',NULL,NULL),('utilizator/dark_raxvan','Profil Dark_Raxvan','2006-11-24 20:57:26','2007-02-12 20:39:59','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',621,'protected',NULL,NULL),('utilizator/sssilviu','Profil sssilviu','2006-11-24 20:57:40','2007-02-12 20:40:00','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',730,'protected',NULL,NULL),('utilizator/gogu','Profil gogu','2006-11-24 20:57:41','2007-02-12 20:40:00','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',735,'protected',NULL,NULL),('utilizator/fluffy','Profil fluffy','2006-11-24 20:58:35','2009-07-21 08:35:19','h2. Despre mine\r\n\r\nNimic!',1142,'protected',NULL,NULL),('utilizator/master','Profil MASTER','2006-11-24 20:57:58','2007-02-12 20:40:00','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',866,'protected',NULL,NULL),('utilizator/filosofie12','Profil filosofie12','2006-11-24 20:58:11','2007-02-12 20:40:00','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',965,'protected',NULL,NULL),('utilizator/chiru_ramona','Profil chiru_ramona','2006-11-24 20:58:16','2007-02-12 20:40:00','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',999,'protected',NULL,NULL),('utilizator/tm_radu','Profil tm_radu','2006-11-24 20:58:25','2007-02-12 20:40:00','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',1072,'protected',NULL,NULL),('utilizator/fireatmyself','Profil fireatmyself','2006-11-24 20:58:47','2007-03-25 12:36:59','h2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',1231,'protected',NULL,NULL),('utilizator/fucker','Profil fucker','2006-11-24 20:58:53','2007-02-12 20:40:01','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',1277,'protected',NULL,NULL),('utilizator/deni','Profil Deni','2006-11-24 20:58:59','2007-02-12 20:40:01','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',1323,'protected',NULL,NULL),('utilizator/rake','Profil rake','2006-11-24 20:59:19','2007-02-12 20:40:01','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',1452,'protected',NULL,NULL),('utilizator/bianca_ig','Profil bianca_ig','2006-11-24 20:59:47','2007-02-12 20:40:02','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',1654,'protected',NULL,NULL),('utilizator/blitzkrieg','Profil BlitzKrieg','2006-11-24 21:00:22','2007-02-12 20:40:02','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',1900,'protected',NULL,NULL),('utilizator/geo88','Profil geo88','2006-11-24 21:00:29','2007-02-12 20:40:03','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',1944,'protected',NULL,NULL),('utilizator/martinica1','Profil martinica1','2006-11-24 21:00:56','2007-02-12 20:40:03','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2126,'protected',NULL,NULL),('utilizator/uniquee','Profil uniquee','2006-11-24 21:01:30','2007-02-12 20:40:04','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2291,'protected',NULL,NULL),('utilizator/stancosti','Profil stancosti','2006-11-24 21:01:35','2007-02-12 20:40:04','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2324,'protected',NULL,NULL),('utilizator/elutza','Profil elutza','2006-11-24 21:01:35','2007-02-12 20:40:04','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2328,'protected',NULL,NULL),('utilizator/c1506','Profil C1506','2006-11-24 21:01:48','2007-02-12 20:40:04','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2421,'protected',NULL,NULL),('utilizator/paula','Profil paula','2006-11-24 21:02:25','2007-02-12 20:40:05','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2676,'protected',NULL,NULL),('utilizator/con_lena','Profil con_lena','2006-11-24 21:02:38','2007-02-12 20:40:05','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2766,'protected',NULL,NULL),('utilizator/abcd','Profil abcd','2006-11-24 21:02:39','2007-02-12 20:40:05','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2773,'protected',NULL,NULL),('utilizator/colt2005','Profil colt2005','2006-11-24 21:02:49','2007-02-12 20:40:05','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2842,'protected',NULL,NULL),('utilizator/judy_k','Profil judy_k','2006-11-24 21:03:23','2007-02-12 20:40:06','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3065,'protected',NULL,NULL),('utilizator/diana_c','Profil Diana_C','2006-11-24 21:03:23','2007-02-12 20:40:06','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3066,'protected',NULL,NULL),('utilizator/zait','Profil zait','2006-11-24 21:03:26','2007-02-12 20:40:06','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3086,'protected',NULL,NULL),('utilizator/marius_dumitran','Profil marius_Dumitran','2006-11-24 21:03:34','2007-02-12 20:40:06','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3134,'protected',NULL,NULL),('utilizator/exist3nz','Profil exist3nz','2006-11-24 21:03:39','2007-02-12 20:40:06','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3166,'protected',NULL,NULL),('utilizator/claustan','Profil claustan','2006-11-24 21:03:40','2007-02-12 20:40:06','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3174,'protected',NULL,NULL),('utilizator/mariusdrg','Profil mariusdrg','2006-11-24 21:03:46','2007-02-12 20:40:06','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3219,'protected',NULL,NULL),('utilizator/inkriptor_scn','Profil inkriptor_scn','2006-11-24 21:04:19','2007-02-12 20:40:07','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3434,'protected',NULL,NULL),('voronoi','voronoi','2007-04-18 11:38:16','2008-11-16 12:26:44','h1. Diagrame Voronoi\r\n\r\n(Categoria _Algoritmi_, autor _Catalin Francu_)\r\n\r\nMultumiri lui Mihai Popa care a cotrobait prin arhiva de mesaje si a gasit mesajul de mai jos. El se refera la principiul dualitatii si am adaugat o bucata despre diagramele Voronoi.\r\n\r\nh2. Principiul dualitatii\r\n\r\nDaca tot n-am mai prea trimis probleme, hai sa va impartasesc si voua ceva din adanca intelepciune care mi-a fost bagata cu pompa pe gat la MIT. Scriu sub impulsul momentului, asa ca nu va asteptati la prea multa coerenta.\r\n\r\nIncep cu observatia ca \"Geometrie Computationala\" nu suna prea romaneste, insa pe de alta parte \"Geometrie Analitica\" nu suna prea corect, fiindca nu e totuna cu ce se face (facea?) in clasa a XI-a de liceu.\r\n\r\nSa pornim de la urmatoarea problema: Avem o colectie de N drepte in plan, oricare doua neconfundate, astfel incat nici una din ele nu trece prin origine. Sa se indice care din drepte sunt vizibile din origine.\r\n\r\nUn algoritm decent functioneaza in O(N^2^), astfel: ia fiecare dreapta d~i~, si o intersecteaaza cu fiecare din celelalte drepte d~j~. In acest fel, d~i~ se imparte in doua semidrepte, din care numai una este vizibila din origine, cealalta fiind obturata de catre d~j~. In felul acesta tot intersectam semidrepte peste semidrepte, si vedem daca in final ramanem cu vreun segment vizibil din origine. Desigur, pe parcurs apare tot tacamul de cazuri particulare: drepte verticale, drepte orizontale, erori de calcul, radicali, distante etc. Sper ca v-am scarbit destul ca sa vreti sa aflati si o implementare mai eleganta.\r\n\r\nVom prezenta un algoritm foarte dragut si foarte cunoscut (in final) care rezolva problema in O(N log N). Facem intai urmatoarea conventie. De vreme ce dreptele nu trec prin origine, ele au ecuatii de forma !voronoi?ec1.bmp!, cu !voronoi?ec2.bmp!. Atunci le vom aduce pe toate la forma !voronoi?img1.bmp! (evident, impartind prin c).\r\n\r\nSi-acum sa vedem ce este principiul dualitatii. El asociaza fiecarei drepte de forma !voronoi?img1.bmp! un punct de coordonate (a,b) in plan. Vom numi spatiul dreptelor \"spatiu primal\", iar spatiul punctelor corespunzatoare \"spatiu dual\". De aici decurg o multime de observatii foarte interesante, din care nici eu nu-mi aduc aminte decat cateva:\r\n\r\n# Oricarui punct din spatiul dual ii corespunde o dreapta in spatiul primal, si ce este mai interesant, oricaror doua puncte distincte din spatiul dual le corespund drepte distincte in spatiul primal\r\n# Oricarei drepte din spatiul primal ii corespunde un punct in spatiul dual. Exceptia o constituie dreptele care trec prin origine, pentru ca ele au c=0 si nu pot fi normalizate. Totusi, daca extindem spatiul dual ca sa contina si puncte de la infinit, atunci fiecarei drepte care trece prin origine in spatiul primal ii corespunde un punct de la infinit in spatiul dual. Cu asta, bijectia intre cele doua spatii este completa.\r\n# Sa ne inchipuim acum doua drepte in spatiul primal, care se intersecteaza intr-un punct:\r\n!voronoi?img1.bmp!\r\n!voronoi?img2.bmp!\r\nFie (p,q) punctul lor de intersectie, care are proprietatile:\r\n!voronoi?img3.bmp!\r\n!voronoi?img4.bmp!\r\nSa dualizam acum cele doua drepte. Obtinem punctele (a,b) si (d,e). Sa analizam ecuatia dreptei care trece prin aceste doua puncte:\r\n!voronoi?ec52.bmp!(*)\r\nDar\r\n!voronoi?img8.bmp!\r\nInlocuind asta in (*) si reducand numitorul (e-b) deducem:\r\n!voronoi?img9.bmp!\r\ndar \r\n!voronoi?img10.bmp!\r\ndeci ecuatia dreptei este:\r\n!voronoi?img11.bmp! !!!\r\nCu alte cuvinte, daca dreptele d1 si d2 se taie in punctul P, atunci dualizand totul obtinem punctele dual(d1) si dual(d2), care determina tocmai dreapta dual(P). Asta mai arata si ca nu e obligatoriu ca in spatiul primal sa avem drepte si in spatiul dual sa avem puncte, ci putem dualiza orice, oriunde :).\r\n# La fel se demonstreaza reciproca: doua puncte care determina o dreapta se dualizeaza in doua drepte care se intersecteaza intr-un punct.\r\n# Generalizarea este si mai draguta: Un fascicol de drepte (pentru cei care nu prea dau pe la mate, asta inseamna o colectie de drepte care se intalnesc in acelasi punct) se dualizeaza intr-o multime de puncte, toate coliniare. Se demonstreaza folosind acelasi punct (p,q) pentru toate dreptele.\r\n# Dar o colectie de drepte paralele? O sa radeti, dar se dualizeaza tot intr-o multime de puncte coliniare. Daca nu ma-nsel, dreapta care contine aceste puncte coliniare inteapa originea. Demonstratia se poate face fie prin calcul direct, fie observand ca in fond o colectie de\r\ndrepte paralele este un fascicol de drepte care se intalnesc la infinit (Euclid sa traiasca!)\r\n# Sa luam dreapta !voronoi?img1.bmp!. Daca normalizam dreapta (impartind prin !voronoi?img12.bmp!), aflam ca distanta de la dreapta la origine este !voronoi?img13.bmp!. Dualizand dreapta, obtinem punctul (a,b), care este situat la distanta !voronoi?img12.bmp! de origine. Mai expresiv, daca dreapta este la distanta d de origine, punctul dual este la distanta 1/d de origine. Mai interesant este ca punctul dual, originea si piciorul perpendicularei din origine pe dreapta sunt coliniare. E destul de usor de demonstrat, daca nu v-ati luat inca un creion si o hartie e cazul sa o faceti, altfel cred si eu ca va plictisiti :).\r\n\r\nSi-acum momentul picant, problema de la care am pornit. Luati o multime de drepte care definesc un poligon in jurul originii, deci sunt vizibile din origine. Luati si alte drepte care nu intersecteaza acest poligon, deci nu sunt vizibile din origine. Asemanator figurii de mai sus, dualizati toate aceste drepte. Pentru fiecare dreapta, veti obtine un punct in partea opusa relativ la origine. Punctul este cu atat mai aproape de origine, cu cat dreapta este mai departe de origine.\r\n\r\nDorim sa separam acum dreptele vizibile din origine de celelalte drepte. Sa vedem daca nu putem lucra cumva cu punctele duale. Intuitiv, ce inseamna o dreapta INvizibila din origine? Inseamna o dreapta \"departata\" de origine (in sensul ca alte drepte vor fi mai aproape decat ea si o vor obtura). In limbaj dual, asta inseamna ca punctul dual va fi mai aproape de origine, in sensul ca vor fi alte puncte mai departe decat el.\r\nAsta cred ca deja va sugereaza ideea de rezolvare. Daca v-ati gandit la infasuratoare convexa, ati pus punctul pe y. Algoritmul este urmatorul:\r\n\r\n* Se da multimea de drepte !voronoi?img14.bmp!\r\n* Aducem toate dreptele la forma !voronoi?img15.bmp!, impartind prin c~i~\r\n* Aflam infasuratoarea convexa a multimii de puncte (a~i~,b~i~)\r\n* Punctele de pe aceasta infasuratoare convexa corespund dreptelor vizibile din origine.\r\n\r\nDe ce asa? Pentru ca punctele de pe infasuratoarea convexa sunt cele mai departate de origine, deci dreptele lor duale sunt cele mai apropiate de origine. Va las placerea de a analiza cazurile particulare, de exemplu cele in care multimea de drepte nu defineste un poligon inchis in jurul originii, ci unul deschis (hint: originea nu apartine infasuratorii convexe a punctelor duale).\r\n\r\nO alta tema de gandire este: ce se intampla in cazul limita cand trei sau mai multe puncte sunt coliniare pe infasuratoarea convexa?\r\n\r\nh2. Diagrame Voronoi\r\n\r\nIn primul rand ce sunt alea. Sa consideram un poligon convex (pentru simplitate vom lua un dreptunghi) si n puncte P~1~, P~2~, ..., P~n~ in acel dreptunghi. Poligonul Voronoi al unui punct P~i~ este format din multimea acelor puncte P din dreptunghi care sunt mai aproape de P~i~ decat de orice alt punct P~j~. Impartirea dreptunghiului in poligoane se numeste diagrama Voronoi.\r\n\r\nExemple: \r\nPentru n=1, exista un singur poligon Voronoi care este intregul dreptunghi. \r\nPentru n=2, ducem mediatoarea lui P ~1~ si P ~2~ si o intersectam cu dreptunghiul, obtinand doua poligoane. Punctele din poligonul lui P ~1~ sunt mai aproape de P ~1~ decat de P ~2~ si invers. \r\nPentru n=3, ducem cele trei mediatoare ale segmentelor P ~1~ P ~2~, P ~2~ P ~3~ si P ~3~ P ~1~ . Mediatoarele se intalnesc intr-un punct (cercul cercului circumscris) si le prelungim pana intersecteaza dreptunghiul. Pentru n=3, cand P ~1~ P ~2~ si P ~3~ sunt coliniare, dreptunghiul este sectionat in trei \"felii\".\r\n\r\nSe poate defini diagrama Voronoi si fara constrangerile dreptunghiului, adica pe intregul plan xOy, dar in acest caz poligoanele sunt \"deschise\" (se duc la infinit). In orice caz, nu este greu de demonstrat ca poligoanele Voronoi sunt convexe.\r\n\r\nO metoda \"barbara\" de a afla poligoanele Voronoi porneste de la observatia ca daca duc mediatoarea dintre P ~i~ si P ~j~ , atunci in mod sigur punctele de partea lui P ~j~ nu au cum sa fie in poligonul lui P ~i~ , pentru ca sunt mai aproape de P ~j~ decat de P ~i~ . Dec algoritmul este:\r\n\r\n* Pentru fiecare i afla poligonul lui P ~i~ astfel:\r\n* Porneste cu un poligon egal cu intregul dreptunghi\r\n* Pentru fiecare j<>i\r\n* Intersecteaza poligonul cu mediatoarea lui P ~i~ P ~j~ si \"arunca\" bucata din partea lui P ~j~\r\n* Poligonul ramas este poligonul lui P ~i~\r\n\r\nComplexitatea este O(N^3^), iar numarul de cazuri particulare este mare. In continuare revenim la principiul dualitatii si la problema de mai sus, a vizibilitatii unor drepte dintr-un punct.\r\n\r\nSa ne imaginam punctul Pi inconjurat de n+3 drepte: cele n-1 mediatoare ale segmentelor PiPj si cele 4 laturi ale dreptunghiului. Atunci poligonul Voronoi al lui Pi are drept laturi exact segmentele \"vizibile\" din Pi ale acestor n+3 drepte. Si dupa cum am vazut mai sus, aceasta problema se reduce la infasuratoare convexa. Trebuie avut grija pentru ca in rezolvarea de mai sus a problemei vizibilitatii am presupus ca punctul de observare este originea. Deci in cazul general va trebui sa translatam totul in asa fel incat Pi sa ajunga in origine, pentru a putea aplica principiul dualitatii. Un ultim aspect care trebuie abordat este acela ca problema de mai sus indica numai care drepte sunt vizibile, nu exact ce segmente din acele drepte.\r\n\r\nAlgoritmul pentru aflarea poligonului Voronoi al lui Pi este:\r\n\r\n* Translateaza tot sistemul pentru a suprapune Pi peste origine (**)\r\n* Construieste colectia de n+3 drepte D1, D2, ..., Dn+3\r\n* Rezolva infasuratoarea convexa si afla colectia de drepte vizibile din origine, fie ele V1, V2, ..., Vk (in ordine trigonometrica)\r\n* Calculeaza varfurile poligonului Voronoi: Wi = Vi-1 int. cu Vi\r\n* Retranslateaza originea si {Wi} pentru a duce Pi in pozitia originala\r\n\r\n(**) Cum se translateaza colectia de puncte este clar: din fiecare Pj.x se scade Pi.x si din fiecare Pj.y se scade Pi.y; in acest fel Pi.x si pi.y devin 0. Cum translatam laturile dreptunghiului (sau in cazul general o dreapta oarecare) ? Daca ecuatia originala era ax+by+c=0, scriem aceasta ecuatie relativ la Pi.x si Pi.y:\r\n\r\nFie !voronoi?img16.bmp!\r\n!voronoi?img17.bmp!\r\n\r\nDeci noua ecuatie este\r\n!voronoi?img18.bmp!\r\n\r\nCu alte cuvine, pentru a translata dreapta cu -Pi.x si -Pi.y, scadem din c valoarea a*Pi.x + b*Pi.y.\r\n\r\nComplexitatea noului algoritm este (pentru un singur poligon):\r\n\r\n* O(N) translatia\r\n* O(N) constructia dreptelor\r\n* O(N) dualizarea\r\n* O(N log N) infasuratoarea convexa\r\n* O(N) constructia poligonului Voronoi\r\n* O(N) translatia inapoi\r\n\r\nPentru intreaga diagrama complexitatea este O(N^2^ log N).\r\nProgramul este implementat si testat. Nu este chiar scurt daca il construiti de la 0, dar daca puteti scrie fara greseala rutinele pentru infasuratoare convexa, intersectii de drepte si asa mai departe, cam in 1.5 - 2 ore ar trebui sa puteti programa toata povestea asta.\r\n\r\n*Cosmin* de fapt complexitatea e O(N^2^) daca folosim algoritmul naiv de infasuratoare convexa care dureaza O(N h) unde h e numarul de puncte de pe infasuratoarea convexa. Pentru ca numarul total de puncte de pe infasuratoarele convexe va fi egal cu 2 * nr de muchii din diagrama Voronoi care are maxim 3n -6 muchii.',2028,'public',NULL,NULL),('blog/alt-demo-de-la-microsoft','Alt demo de la Microsoft','2007-11-28 05:00:49','2008-11-16 12:39:39','Inca un demo foarte tare de la Microsoft Research. Imi plac ideile astea istete si foarte simplu de pus in practica.\r\n\r\n==youtubevideo(id=\"AtmwQnUlEmc\" width=\"425\" height=\"355\")==\r\n',1851,'protected',2423,NULL),('utilizator/chici','Profil Chici','2006-11-24 21:04:45','2007-02-12 20:40:08','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3604,'protected',NULL,NULL),('utilizator/lilix0202','Profil lilix0202','2006-11-24 21:05:03','2007-02-12 20:40:08','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3726,'protected',NULL,NULL),('utilizator/laiurita88','Profil laiurita88','2006-11-24 21:05:05','2007-02-12 20:40:08','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3739,'protected',NULL,NULL),('utilizator/lupu','Profil lupu','2006-11-24 21:05:06','2007-02-12 20:40:08','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3740,'protected',NULL,NULL),('utilizator/mfuqm31','Profil mfuqm31','2006-11-24 21:05:23','2007-02-12 20:40:08','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3851,'protected',NULL,NULL),('utilizator/danutzul_05','Profil danutzul_05','2006-11-24 21:05:52','2007-02-12 20:40:09','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4032,'protected',NULL,NULL),('utilizator/tmir','Profil tmir','2006-11-24 21:05:56','2007-02-12 20:40:09','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4057,'protected',NULL,NULL),('utilizator/ioana_bomboana','Profil Ioana_bomboana','2006-11-24 21:06:06','2007-02-12 20:40:09','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4118,'protected',NULL,NULL),('utilizator/bianca_bya','Profil bianca_bya','2006-11-24 21:06:17','2007-02-12 20:40:09','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4184,'protected',NULL,NULL),('preoni-2007/clasament/runda-4/11-12','Clasament preONI 2007, Runda 4, Clasele 11-12','2007-03-07 12:18:12','2007-03-07 12:18:12','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda4_1112\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-4\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/runda-4/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-4/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-4/10\r\n*(active) \'Clasele 11-12\':preoni-2007/clasament/runda-4/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda4_1112\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('utilizator/andras','Profil andras','2006-11-24 21:06:36','2007-02-12 20:40:09','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4304,'protected',NULL,NULL),('utilizator/iceman_ro','Profil IcemaN_ro','2006-11-24 21:06:40','2007-02-12 20:40:10','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4327,'protected',NULL,NULL),('utilizator/bc_costy','Profil bc_costy','2006-11-24 21:06:54','2007-02-12 20:40:10','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4414,'protected',NULL,NULL),('utilizator/vic_and','Profil vic_and','2006-11-24 21:07:06','2007-02-12 20:40:10','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4484,'protected',NULL,NULL),('utilizator/alexus','Profil Alexus','2006-11-24 21:07:11','2007-02-12 20:40:10','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4516,'protected',NULL,NULL),('utilizator/claudia','Profil claudia','2006-11-24 21:07:17','2007-02-12 20:40:10','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4550,'protected',NULL,NULL),('utilizator/nirvanablue25','Profil nirvanablue25','2006-11-24 21:07:32','2007-02-12 20:40:10','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4635,'protected',NULL,NULL),('utilizator/onu_flo','Profil onu_flo','2006-11-24 21:07:35','2007-02-12 20:40:10','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4655,'protected',NULL,NULL),('utilizator/manu_deutza','Profil manu_deutza','2006-11-24 21:07:43','2007-02-12 20:40:11','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4699,'protected',NULL,NULL),('utilizator/cocoru','Profil cocoru','2006-11-24 21:08:04','2007-02-12 20:40:11','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4823,'protected',NULL,NULL),('utilizator/lemne','Profil lemne','2006-11-24 21:08:11','2007-02-12 20:40:11','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4860,'protected',NULL,NULL),('utilizator/xanthe','Profil xanthe','2006-11-24 21:08:18','2007-02-12 20:40:11','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4905,'protected',NULL,NULL),('utilizator/mlegs','Profil mlegs','2006-11-24 21:08:21','2007-02-12 20:40:11','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4920,'protected',NULL,NULL),('blog/problema-saptamanii-produs','Problema saptamanii - Produs','2008-06-01 09:32:06','2008-11-15 13:41:14','Sa se determine produsul maxim a unor numere reale pozitive a caror suma e 100.\r\n\r\n_Trimiteti-mi solutiile pe privat sau pe cosminn at gmail.com_',1490,'protected',3117,NULL),('ciclu-de-cost-mediu-minim','cliclu-de-cost-mediu-minim','2008-03-20 07:10:56','2008-03-20 07:10:56','\'Problema Ciclu a lui Radu Berinde\':http://www.ginfo.ro/revista/14_1/solutii2.pdf\r\n\r\n\'Gasiti aici solutia\':http://www.ginfo.ro/revista/14_1/solutii2.pdf\r\n\r\nUn truc similar:\r\n\'SGU 236 greedy path\':http://acm.sgu.ru/problem.php?contest=0&problem=236',58,'public',NULL,NULL),('utilizator/root','Profil root','2006-11-24 21:08:45','2007-02-12 20:40:11','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5054,'protected',NULL,NULL),('utilizator/ankutsa','Profil ankutsa','2006-11-24 21:09:21','2007-02-12 20:40:12','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5247,'protected',NULL,NULL),('utilizator/andreidumi','Profil AndreiDumi','2006-11-24 21:09:25','2007-02-12 20:40:12','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5274,'protected',NULL,NULL),('utilizator/dany_perfect','Profil Dany_perfect','2006-11-24 21:09:42','2007-02-12 20:40:12','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5364,'protected',NULL,NULL),('utilizator/ge_ronimo17','Profil ge_ronimo17','2006-11-24 21:09:46','2007-02-12 20:40:12','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5382,'protected',NULL,NULL),('preoni-2005/clasament-9-10','Clasament preoni5a','2006-11-24 23:36:40','2006-11-25 13:48:16','h1.  Clasament global preONI 2005 (Clasele IX-X)\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni52a|preoni53a\")==',961,'protected',NULL,NULL),('preoni-2005/clasament-11-12','Clasament preoni5b','2006-11-24 23:40:21','2006-11-25 13:48:12','h1.  Clasament global preONI 2005 (Clasele XI-XII)\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni52b|preoni53b\")==',961,'protected',NULL,NULL),('preoni-2005/runda-1/clasament-9-10','Clasament preoni51a','2006-11-24 23:52:21','2006-11-24 23:52:21','h1. Clasament ==roundparam(round_id=\"preoni51a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni51a\")==',961,'protected',NULL,NULL),('preoni-2005/runda-1/clasament-11-12','Clasament preoni51b','2006-11-24 23:53:42','2006-11-24 23:53:42','h1. Clasament ==roundparam(round_id=\"preoni51b\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni51b\")==',961,'protected',NULL,NULL),('preoni-2005/runda-2/clasament-9-10','Clasament preoni52a','2006-11-24 23:59:16','2006-11-24 23:59:16','h1. Clasament ==roundparam(round_id=\"preoni52a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni52a\")==',961,'protected',NULL,NULL),('preoni-2005/runda-2/clasament-11-12','Clasament preoni52b','2006-11-25 00:00:04','2006-11-25 00:00:04','h1. Clasament ==roundparam(round_id=\"preoni52b\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni52b\")==',961,'protected',NULL,NULL),('preoni-2005/runda-3/clasament-9-10','Clasament preoni53a','2006-11-25 00:03:54','2006-11-25 00:04:11','h1. Clasament ==roundparam(round_id=\"preoni53a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni53a\")==',961,'protected',NULL,NULL),('preoni-2005/runda-3/clasament-11-12','Clasament preoni53b','2006-11-25 00:05:25','2006-11-25 00:05:25','h1. Clasament ==roundparam(round_id=\"preoni53b\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni53b\")==',961,'protected',NULL,NULL),('preoni-2006/runda-2/clasament-9','Clasament preoni62a','2006-11-25 01:34:53','2006-11-25 01:34:53','h1. Clasament ==roundparam(round_id=\"preoni62a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni62a\")==',961,'protected',NULL,NULL),('preoni-2006/runda-3','Runda 3, preONI 2006','2006-11-25 01:39:09','2006-11-27 16:16:11','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Runda 3\r\n\r\nConcursul s-a desfasurat sambata, 21 ianuarie, la ora 09:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nh2. Comisii\r\n\r\nh3. Stiintific\r\n\r\n* clasa a 9-a (si gimnaziu)\r\n** Adrian Diaconu\r\n** Daniel Pasaila \r\n* clasa a 10-a\r\n** Mircea Pasoi\r\n** Tiberiu Florea \r\n* clasele 11-12\r\n** Cosmin Negruseri\r\n** Adrian Vladu\r\n** Silviu Ganceanu\r\n\r\nh3. Organizatoric\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* Cristian Strat\r\n* Crestez Leonard \r\n\r\nh2. Solutii\r\n\r\nSolutiile problemelor le puteti gasi \"aici\":preoni-2006/runda-3/solutii\r\n\r\nh2. Clasa a 9-a si gimnaziu (\'Clasament\':preoni-2006/runda-3/clasament-9)\r\n\r\n!>preoni-2006/runda-3?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni63a\" pager_style=\"none\") ==\r\n\r\nh2. Clasa a 10-a(\'Clasament\':preoni-2006/runda-3/clasament-10)\r\n\r\n!>preoni-2006/runda-3?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni63b\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2006/runda-3/clasament-11-12)\r\n\r\n!>preoni-2006/runda-3?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni63c\" pager_style=\"none\") ==\r\n\r\n==include(page=\"template/preoni-2006/footer\")==',13,'protected',NULL,NULL),('preoni-2006/runda-3/clasament-11-12','Clasament preoni63c','2006-11-25 01:42:55','2006-11-25 01:42:55','h1. Clasament ==roundparam(round_id=\"preoni63c\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni63c\")==',961,'protected',NULL,NULL),('preoni-2006/runda-3/clasament-10','Clasament preoni63b','2006-11-25 01:43:01','2006-11-25 01:43:01','h1. Clasament ==roundparam(round_id=\"preoni63b\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni63b\")==',961,'protected',NULL,NULL),('preoni-2006/runda-3/clasament-9','Clasament preoni63a','2006-11-25 01:43:07','2006-11-25 01:43:07','h1. Clasament ==roundparam(round_id=\"preoni63a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni63a\")==',961,'protected',NULL,NULL),('preoni-2006/runda-4/clasament-11-12','Clasament preoni64c','2006-11-25 02:53:06','2006-11-25 02:53:06','h1. Clasament ==roundparam(round_id=\"preoni64c\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni64c\")==',961,'protected',NULL,NULL),('preoni-2006/runda-4/clasament-10','Clasament preoni64b','2006-11-25 02:53:12','2006-11-25 02:53:12','h1. Clasament ==roundparam(round_id=\"preoni64b\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni64b\")==',961,'protected',NULL,NULL),('preoni-2006/runda-4/clasament-9','Clasament preoni64a','2006-11-25 02:53:20','2006-11-25 02:53:20','h1. Clasament ==roundparam(round_id=\"preoni64a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni64a\")==',961,'protected',NULL,NULL),('preoni-2006/finala','Finala in Focsani, preONI 2006','2006-11-25 02:52:41','2006-12-01 18:28:26','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Finala in Focsani \r\n\r\n*Primii 10* concurenti de la fiecare grupa din clasamentul rundelor online (#1 + #2 + #3 + #4) sunt invitati la runda finala. Aceasta se va desfasura in *Focsani*, mai exact:\r\n\r\n* cazare + mic dejun la *Hotel Unirea, Focsani*\r\n* concursul on-site la *{\'Colegiul National Unirea\':http://cnu.lufo.ro/}*\r\n\r\n\'Premiile concursului\':preoni-2006/premii preONI se vor acorda in functie de rezultatele rundei finale. Punctajele obtinute in perioada de calificare vor servi doar la departajare.\r\nPentru concurentii care nu s-au calificat in finala, vom gazdui si o varianta online. Aveti ocazia sa va comparati performanta cu cei care au ajuns in finala! ;)\r\n\r\nh2. Probleme\r\n\r\nSolutiile problemelor le puteti gasi \"aici\":preoni-2006/finala/solutii.\r\n\r\nh3. Clasa a 9-a si gimnaziu (\'Clasament\':preoni-2006/finala/clasament-9)\r\n\r\n!>preoni-2006/finala?logo.jpg!\r\n\r\n== Tasks(round_id=\"preoni65a\" pager_style=\"none\") ==\r\n\r\nh3. Clasa a 10-a(\'Clasament\':preoni-2006/finala/clasament-10)\r\n\r\n!>preoni-2006/finala?logo.jpg!\r\n\r\n== Tasks(round_id=\"preoni65b\" pager_style=\"none\") ==\r\n\r\nh3. Clasele 11-12 (\'Clasament\':preoni-2006/finala/clasament-11-12)\r\n\r\n!>preoni-2006/finala?logo.jpg!\r\n\r\n== Tasks(round_id=\"preoni65c\" pager_style=\"none\") ==\r\n\r\nh2. Sponsori finala\r\n\r\nSponsorii finalei sunt:\r\n\r\n\"!preoni-2006?Oracle_ro.gif!\":http://www.oracle.com/global/ro/index.html\r\n\r\n\"Colegiul National Unirea, Focsani\":http://cnu.lufo.ro/\r\n\r\n*Hotel Unirea, Focsani*\r\n\r\nMultumim d-lui *Prof. Emil Onea* pentru ca a facut posibila organizarea acestei finale!\r\n\r\nh2. Calificare \r\n\r\nCalificarea in aceasta etapa se face exclusiv pe baza clasamentului din primele 4 runde. De la fiecare grupa vor fi selectati ocupantii primelor *10* pozitii. Mentionam ca o persoana se poate califica la finala doar la grupa destinata lui si ca se va face si o identificare prin intermediul Cartii de Identiate (Buletin) pentru a evita frauda. Daca aveti nelamuriri revedeti si \'regulamentul\':preoni-2006/regulament. \r\nConcurentiilor li se vor asigura cazarea si *masa integral*. Costul transportului pana la locul unde se va desfasura finala va fi suportat de catre concurenti. Pentru motivarea absentelor pe perioada finalei se va elibera un document oficial.\r\n\r\nh2. Program \r\n\r\nIntrucat programul elevilor este in general incarcat in aceasta perioada, durata rundei finale este de numai *3 zile*. Perioada de desfasurare: *24-26 martie 2006* (vineri, sambata, duminica). Teoretic, luni sunteti inapoi la scoala :) Va rugam sa vizitati aceasta sectiune periodic pentru a fi la curent. Programul provizoriu al finalei este:\r\n\r\n|_. Ziua |_. Actvitate |\r\n| *24 martie 2006* | Sosirea participantilor\r\nDeschidere oficiala\r\nAcomodare |\r\n| *25 martie 2006* | Concurs (dimineata)\r\nPrezentare ORACLE\r\nEvaluare si contestatii\r\nPremiere\r\nCina festiva |\r\n| *26 martie 2006* | Excursie la _Valea Putnei_\r\nPlecare |\r\n\r\nConcursul va dura *5* ore in care concurentii vor primi spre rezolvare *3* probleme cu grad de dificultate un pic mai ridicat decat cel de la etapele anterioare. Programul nu este fix, si asteptam sugestii din partea voastra.\r\nCei care nu s-au calificat in runda finala vor putea sa participe in paralel on-line pe _infoarena_. Modul de desfasurare va fi identic cu acela al primelor patru. Participantii online nu vor primii premii.\r\n\r\nh2. Mediul de lucru \r\n\r\nRunda finala se desfasoara in laboratoarele de informatica ale *{\'Colegiului National Unirea\':http://cnu.lufo.ro/}* din Focsani. Vom incerca sa punem la dispozitia concurentilor aceleasi versiuni de compilatoare ca cele folosite pe site in timpul rundei. Asteptam sugestiile voastre in privinta soft-ului care doriti sa fie instalat pe calculatoare.\r\n\r\nh2. Regulament \r\n\r\nPe langa \'regulamentul concursului\':preoni-2006/regulament, la editia finala vor exista urmatoarele adaugiri la regulament pentru cei calificati. \'Echipa infoarena\':echipa-infoarena isi rezerva dreptul de a modifica acest regulament in orice fel pana la data desfasurarii finalei.\r\n\r\n* Concurentii vor fi prezenti in salile de concurs la orele anuntate\r\n* Fiecare concurent va primi subiectele in forma listata si foi pentru ciorne (pix nu este inclus)\r\n* Timp de 1 ora dupa primirea subiectelor concurentii pot formula intrebari referitoare la enunturile problemelor; intrebarile se vor formula in scris, pe foaia cu intrebari fiind precizate numele problemei si al concurentului; modalitate de formulare a intrebarile este identica cu cea de la primele 4 runde\r\n* In timpul probelor de concurs, concurentii:\r\n** nu vor avea asupra lor telefoane mobile sau alte mijloace de comunicatie\r\n** nu vor utiliza suporturi externe proprii (dischete/CD/flash-disk)\r\n** nu vor utiliza alte surse de documentare decat cele prezente pe calculator\r\n** nu vor incerca sa interfereze in nici un mod cu activitatile altui concurent\r\n** nu vor deteriora mediile de lucru\r\n** nu vor incerca sa interfereze cu sistemul de evaluare\r\n* In programele concurentilor nu sunt permise urmatoarele:\r\n** schimbarea drepturilor de acces la fisiere\r\n** atacul asupra securitatii sistemului sau evaluatorului\r\n** accesarea informatiilor despre sistemul de fisiere\r\n** executarea unor alte programe\r\n\r\nOrice incercare de frauda sau de a sabota desfasurarea corecta a concursului va fi urmata imediat de eliminarea elevului respectiv din concurs, cat si de pe _infoarena_.\r\n\r\nh2. Participanti \r\n\r\n\'Click aici\':preoni-2006/clasament pentru clasamentul rundelor online.\r\nLista oficiala a participantilor va fi anuntata dupa ce validam identitatea celor calificati online.\r\n\r\nh2. Divertisment :p \r\n\r\nCa sa nu ne plictisim vom pleca intr-o excursie la _Valea Putnei_ pentru a discuta informatica si calculatoare intr-un cadru aparte. :)',1142,'protected',NULL,NULL),('blog/alta-problema-misto-solutie','Alta problema misto - solutie','2007-10-22 08:00:03','2008-11-16 12:58:53','Problema cu lanternele a fost rezolvata de Radu Cebanu, Dumitru Daniliuc, \'Stefan Istrate\':http://infoarena.ro/utilizator/stef2n , Catalin Francu si Stefan Ciobaca.\r\n\r\nVa prezint in continuare solutiile. Este interesant de urmarit cum sunt gandite solutiile, care desi sunt echivalente sunt prezentate putin diferit.\r\n\r\n*Stefan Ciobaca* generalizeaza problema:\r\nEu as fi propus generalizarea: ai <tex>2^n</tex> triedre drepte in n dimensiuni.\r\n\r\nRezolvarea prin divide et impera: iei cele <tex>2^n</tex> puncte si le separi printr-un hiperplan astfel incat jumate sa fie de-o parte, jumate de cealalta parte s.a.m.d., avand in vedere ca toate hiperplanele sa fie perpendiculare intre ele. Evident, chestia asta se poate. Apoi, fiecare triedru il orientezi spre semisemisemi...semi spatiul total opus si cu marginile paralele cu axele de coordonate q.e.d.\r\nImi place cum se vede defectul profesional de programator citind demonstratia.\r\n\r\nSolutia lui *Radu*:\r\n\r\nRezolvam prin inductie dupa nr de dimensiuni.\r\n\r\nIn primul rand: fixezi o directie pt primul plan, il muti paralelel cu el insusi astfel incat sa separe punctele in 2 parti egale, 4 de o parte, 4 de alta (daca stau mai multe pe planul ala exact,nu conteaza, alegi cateva si le declari de o parte, sa fie 4 si restul de cealalta). \r\nApoi sa zicem ca le luam pe alea de deasupra:\r\n proiectiile lor pe planul respectiv sunt 4 puncte care conform inductiei (pt doua dimensiuni) acopera planul. Cu diedrele din plan faci triedre cu a 3-a dreapta in jos ca sa acopere semispatiul inferior. La fel pt alea de sub plan, pui dreapta a 3-a din triedru in sus ca sa acopere semispatiul superior.\r\nRadu a lasat demonstratia putin incompleta avand incredere ca ma prind singur de cazul 2d si 1d.\r\n\r\nSolutia lui *Catalin*:\r\nIdeea mea e sa gasesc o solutie in care triedrele au laturile orientate paralel cu axele, pentru simplitate.\r\n\r\n- Rotim sistemul astfel incat sa nu existe doua lanterne cu coordonate X, Y sau Z egale (pentru a scapa de cazuri particulare).\r\n\r\n- Parcurgem lanternele in ordine crescatoare a coordonatei x. Pe primele 4 le marcam cu X+, pe ultimele 4 cu X-.\r\n\r\n- Parcurgem cele patru lanterne X+ in ordine crescatoare a coordonatei y. Pe primele doua le marcam cu Y+, pe celelalte doua cu Y-. La fel si\r\npentru cele patru lanterne X-.\r\n\r\n- Parcurgem cele doua lanterne X+Y+ in ordine crescatoare a coordonatei z. Pe prima o marcam cu Z+, pe a doua cu Z-. La fel si pentru celelalte 6 lanterne marcate cu X+Y-, X-Y+, X-Y-.\r\n\r\nAvem opt lanterne marcate cu X+Y+Z+, X+Y+Z-, pana la X-Y-Z-. Acum le pozitionam paralel cu axele Ox, Oy, Oz si in sensurile indicate de semne. De exemplu, lanterna X+Y-Z- \r\n\r\nva lumina catre sensul pozitiv al axei Ox si catre sensurile negative ale axelor Oy si Oz; cu alte cuvinte, ea va lumina punctul de coordonate (+inf, -inf, -inf).\r\n\r\nDandu-se un punct P(x,y,z), trebuie demonstrat ca exista o lanterna care il lumineaza. Analizam coordonata x. Datorita constructiei, x va fi fie mai mare decat toate coordonatele x ale lanternelor marcate cu X+, fie mai mic decat toate coordonatele x ale lanternelor marcate cu X- (fie ambele, daca x este situat intre cele doua grupuri de 4 lanterne). Alegem acel set de 4 lanterne si reluam rationamentul pe axele Oy si Oz. in final, obtinem minim o lanterna care lumineaza punctul P.\r\n\r\nSi la Catalin se vede programatorul din spatele solutiei. Se observa cum structura rezolvarii este bazata pe vectorii de cate 3 elemente in baza 2.\r\n\r\n*Stefan Istrate* are o solutie foarte misto, cu desene dragute, pe care o gasiti pe \'forum\':http://infoarena.ro/forum/index.php?topic=2218.0 . Merita sa o cititi!\r\n\r\nSolutia lui *Dumitru* nu o am scrisa.\r\n\r\nLa solutia lui Stefan Ciobaca si cea a lui Catalin Francu nu e demonstrata ipoteza ca _putem gasi un sistem de coordonate in care toate punctele au coordonatele x1, x2, .. respectiv diferite_ . Va incurajez sa va incercati puterile pe aceasta subproblema in sectiunea de \'comentarii\':http://infoarena.ro/forum/index.php?topic=2222.0\r\n\r\nO problema similara a fost propusa la un ACM in regiunea din Nord Estul Europei: _Se cere iluminarea planului cu n lanterne (n <= 30) de coordonate date, ce pot fi rotite, al caror fascicul emite lumina sub un unghi de marime 2pi/n. Pentru fiecare lanterna trebuie returnata orientarea ei._ La aceasta problema, pe langa solutia ei, e interesant si algoritmul folosit pentru evaluarea corectitudinii unui rezultat.\r\n\r\nPentru mai multe probleme interesante cu lanterne puteti citi urmatoarele lucrari:\r\n\r\nBose, J., L. Guibas, A. Lubiw, M. Overmars, D. Souvaine and J. Urrutia, \'\"The floodlight illumination problem\"\':blog/alta-problema-misto-solutie?TheFloodProb.ps\r\nCzyzowicz, J., E. Rivera-Campo and J. Urrutia, \'\"Optimal floodlight illumination of stages\"\':blog/alta-problema-misto-solutie?OptFloStages.ps',2028,'protected',2222,NULL),('template/userrating','template/userrating','2006-12-02 18:13:34','2009-03-12 20:35:17','h2. Rating %user%\r\n\r\n==RatingChart(user=\"%user%\")==\r\n\r\nh3. Concursuri cu rating la care a participat\r\n\r\n==Rounds(user=\"%user%\" only_rated=\"1\")==\r\n\r\n==DistributionChart(user=\"%user%\")==\r\n\r\n*{\"Ce inseamna si cum se calculeaza rating-ul?\":documentatie/rating}*',1490,'protected',NULL,NULL),('blog/unirea-2007','Concursul Unirea 2007','2007-01-24 01:31:16','2007-01-24 01:31:16','infoarena organizeaza concursul de informatica Unirea 2007.\r\n\r\nConcursul, la care castigatorii vor primi diplome si premii, incepe *Sambata, 27 ianuarie la ora 14^00^* si dureaza *3h*.\r\n\r\nInformatii se gasesc pe \'pagina concursului\':unirea-2007.',13,'public',NULL,NULL),('documentatie/pentru-propunatori','Pentru propunatori','2006-12-10 17:39:32','2007-04-01 19:28:39','h1. Pentru propunatori.\r\n\r\nUnul dintre principalele motive pentru care noi am rescris infoarena este ca sa facem mai usor sa propui probleme. Momentan aceste facilitati nu sunt gata, dar vor fi in curand.\r\n\r\nDaca stii sa programezi in php/mysql (sau vrei sa inveti) poti sa ne ajuti si pe partea de \'web-development\':http://infoarena.ro/implica-te/development.',15,'public',NULL,NULL),('despre-infoarena','Despre infoarena','2006-11-27 07:32:22','2009-08-04 12:57:48','h1. Despre infoarena\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\n*infoarena ajuta elevi si studenti sa invete informatica si programare.* Organizam concursuri de informatica, scriem articole, dezvoltam software, facem schimb de experienta si idei.\r\n\r\nSuntem viitorii specialisti IT ai Romaniei! Ne-am organizat pe acest site deoarece impreuna invatam mai bine.\r\n\r\nh2. Cu ce ne ocupam?\r\n\r\n* Concursuri online de informatica pentru studenti si elevi\r\n* Stiri si articole despre informatica\r\n* Discutam pe forum tot despre informatica\r\n* Dezvoltam software open source\r\n\r\ninfoarena functioneaza din 2003 si este dezvoltata de \'echipa infoarena\':echipa-infoarena, cu sprijinul a zeci de colaboratori ajutandu-ne pe diferite \'proiecte\':implica-te.\r\nComunitatea noastra cuprinde elevi si studenti romani ce participa la concursuri de informatica nationale si internationale.\r\n\r\n*Citeste {\'prezentarea infoarena\':prezentare}*.\r\n\r\nbq. People have been known to achieve more as a result of working with others than against them.\r\n\r\n*Dr. Allan Fromme*\r\n\r\nbq. infoarena este un proiect remarcabil, realizat cu entuziasm, generozitate si profesionalism. Este locul in care tinerii pasionati de informatica se pot intalni, atat de o parte, cat si de cealalta parte a baricadei, ca propunatori sau ca rezolvitori de probleme, isi pot impartasi experienta competitionala, pot constitui modele, pot ajuta la formarea a noi si noi generatii de performanta.\r\n\r\n*Emanuela Cerchez*\r\nCoordonator stiintific in Comisia Nationala de Informatica, Prof. grad I - Lic. de Informatica \"Grigore Moisil\" Iasi\r\n\r\nbq. infoarena e plin de energie, e dinamic si riguros, gratie unei echipe curajoase. Site-ul infoarena reprezinta cea mai originala forma de pregatire pe net a performerilor in informatica din Romania. Mecanism de lucru excelent, probleme propuse, fara cusur. Felicitari!\r\n\r\n*Emil Onea*\r\nInspector scolar informatica, Comisia Nationala de Informatica pentru Invatamant Preuniversitar\r\n',75,'protected',NULL,NULL),('okr/20091/devel-ia3','okr/20091/devel-ia3','2009-01-26 14:47:14','2009-01-26 14:52:35','(okr)* comunitate functionala de developeri\r\n** crestem numarul de contribuitori: sa avem macar 2-3 oameni activi\r\n** folosim best practices: documentatie si tutoriale pentru incepatori, code review, tickets, documentation, setup script,  unit tests, benchmarks, regression tests',13,'public',NULL,NULL),('okr/20091/downloads','okr/20091/downloads','2009-01-26 14:47:28','2009-01-26 18:56:23','',1,'public',NULL,NULL),('documentatie/forum','Forum infoarena','2006-12-11 01:55:16','2007-04-07 18:08:35','h1. Forum infoarena\r\n\r\n==include(page=\"template/todo\")==\r\n\r\nSite-ul infoarena integreaza un forum \'SMF\':http://www.simplemachines.org.\r\n\r\nAtunci cand iti creezi cont pe infoarena, ti se creaza automat un cont de acces si pe forum.\r\n\r\nAcceseaza forum-ul cu click pe tab-ul _forum_ din bara principala de navigare.\r\nPoti sa trimiti si sa primesti mesaje personale de la alti utilizatori. Click pe _mesaje_ in bara principala de navigare.\r\n\r\nUnele pagini precum \'prima pagina\':home sau \'arhiva de probleme\':arhiva afiseaza liste cu ultimelor discutii / mesaje aparute pe forum. Facand click in aceste link-uri poti sa ajungi direct pe forum.',5748,'public',NULL,NULL),('termeni-si-conditii','Termeni si conditii de utilizare a site-ului infoarena','2006-11-27 08:53:18','2006-12-11 03:27:51','h1. Termeni si conditii de utilizare a site-ului infoarena\r\n\r\n==include(page=\"template/todo\")==\r\n\r\nPentru a folosi site-ul infoarena trebuie sa fii de acord cu urmatoarele conditii:\r\n\r\n* Vei respecta \'regulamentul\':regulament.\r\n* *Nu ne asumam responsabilitatea fata de continutul pe care utilizatorii il adauga pe site!* Ne straduim sa filtram si sa moderam ceea ce utilizatorii adauga / editeaza pe site dar nu garantam ca o vom face in timp util pentru tine.\r\n* Cu exceptia cazurilor in care se specifica altfel, continutul acestui site este sub licenta \'Creative Commons Attribution-NonCommercial 2.5.\':http://creativecommons.org/licenses/by-nc/2.5/.\r\n* Conditiile de utilizare se pot schimba in timp fara a fi informat in prealabil.',13,'protected',NULL,NULL),('blog/lansare-infoarena-2','Am lansat infoarena 2!','2006-12-11 03:39:58','2006-12-14 13:03:44','h1. Am lansat infoarena 2!\r\n\r\nAm lansat infoarena 2!\r\nVechiul site (infoarena.devnet.ro), care ne-a servit timp de aproape 3 ani, a fost inchis.\r\n\r\nAfla mai multe despre noul infoarena vizitand pagina indicata mai sus.\r\n',4439,'public',NULL,NULL),('ia_in_ie7','Cum arata infoarena in internet explorer 7','2006-12-05 23:12:50','2007-02-22 20:24:47','Momentan, nici un bug vizibil in IE7.\r\n\r\n* FIXED -footer afisat prost-\r\n* FIXED -vezi partea din stanga, problema cu casuta cu utilizatorul pare rezolvata-\r\n\r\n* FIXED -inca un bug chiar pe pagina asta - ce se intampla ca daca imaginea nu incape in fereastra -- a se observa spatiul liber intre textul \'footer afisat prost\' si poza; daca fereastra este destul de mare sa incapa poza, spatiul dispare-\r\n',2934,'public',NULL,NULL),('summer-challenge-unu','Summer Challenge Unu','2006-11-23 21:09:02','2006-12-11 15:55:43','h1. Summer Challenge Unu\r\n\r\nConcursul s-a desfasurat pe 3/8/2006.\r\n\r\nConcursul a avut 3 probleme, care au fost adaugate in \'arhiva\':arhiva.\r\n\r\nArticolul cu solutii se gaseste \'aici\':summer-challenge-unu/solutii.\r\n\r\nh2. \'Clasament\':summer-challenge-unu/clasament\r\n\r\n!>summer-challenge-unu?logo!\r\n\r\n== Tasks(round_id=\"summer06\" pager_style=\"none\") ==',961,'protected',NULL,NULL),('utilizator/armasanea','Profil armasanea','2006-12-12 05:22:18','2007-02-12 20:40:12','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5420,'public',NULL,NULL),('summer-challenge-2007/solutii/runda-1','Solutii Summer Challenge, Runda 1','2007-07-30 12:37:45','2007-08-11 07:10:08','h1. Solutii Runda 1\r\n\r\nh2. \'Imagine\':problema/imagine\r\n\r\nObservam ca fiecare din operatiile {$S$} {$D$} {$O$} {$V$} nu face decat sa permute intre ele cele $4$ cadrane. De exemplu initial cadranele se afiseaza in ordinea {$1,2,3,4$} iar dupa o operatie {$O$} vor trebui afisate {$3,4,1,2$}, apoi dupa aplicarea unei operatii $V$ va trebui afisat {$4,3,2,1$}. Pentru operatiile $I$ va trebui sa retinem doar paritatea si in cazul in care numarul acestor operatii este impar va trebui sa afisam $n$ in loc de $a$ si invers. De aceea nu trebuie decat sa retinem in ce ordine vom prezenta cadranele si daca acestea vor fi sau nu negate.\r\n\r\nProblema care se ridica este lipsa memoriei. Vom reprezenta imaginea ca un arbore in care fiecare nod fie este frunza fie are $4$ fii(cate unul pentru fiecare cadran). O parcurgere a arborelui in care fii oricarui nod sunt parcursi in ordinea permutarii noastre va fi exact codificarea cautata. Observam ca nu putem avea mai mult de $N/5$ noduri interne deci maxim {$2.000.000$}. Pentru fiecare nod vom retine primul fiul si fratele nodului curent. Din felul in care vom construi arborele (cu ajutorul unei stive) se vede ca primul fiu al unui nod in cazul in care exista va fi exact {$nodul curent + 1$} de aceea nu va mai fi necesara si retinerea fiului. In plus in fiecare nod vom mai retine 8 biti grupati cate 2 pentru a retine pentru fiecare din cei $4$ fii daca este sau nu o frunza si in cazul in care este o frunza retinem si culoarea ei. In total se poate folosi cu usurinta sub $16M$ memorie.\r\n\r\nh2. \'Strigat\':problema/strigat\r\n\r\nVom construi un \"automat finit\":Automate-finite-si-KMP ce va contine cuvintele din intrare. Fiecarei stari din automat ii vom asocia o valoare egala cu suma gradelor de spaima ale cuvintelor acceptate de acea stare. Pentru a determina sirul cu grad maxim de spaima vom construi matricea $A[i][j]$ cu semnificatia care este gradul de spaima maxim pentru un sir de lungime $i$, aflandu-ne la sfarsit in starea $j$ a automatului. Aflandu-ne pe linia $i$ a matricei vom folosi matricea de tranzitie a automatului $&#0948;$ pentru a calcula valorile de pe linia $i + 1$.\r\n\r\n$A[i + 1][ &#0948;{~j, c~} ] = max( A[i + 1][ &#0948;{~j, c~} ], A[i][j] + ValoareStare[ &#0948;{~j, c~} ] )$, $c &isin; &#0931;$\r\n\r\nConstructia automatului are complexitatea $O(L * |&#0931;|)$, unde $L$ reprezinta suma lungimilor cuvintelor de la intrare si $&#0931;$ reprezinta alfabetul.\r\nCalcularea matricei are complexitatea $O(N * L * |&#0931;|)$.\r\n\r\nh2. \'Flux\':problema/flux\r\n\r\nVom forma un sistem de ecuatii in care necunoscutele {$X{~i~}$} vor fi suma fluxurilor de pe drumul de la $0$ la nodul {$i$} (care se garanteaza ca este aceeasi indiferent de drum). Fluxul trimis de la $i$ la $j$ va fi exact {$n{~i,j~}*(X{~j~}-X{~i~})$} unde n{~i,j~} este numarul de muchii dintre $i$ si {$j$}. Vom pune conditiile de conservare a fluxului pentru fiecare nod {$i$}: suma fluxurilor care intra sa fie egala cu suma fluxurilor care ies. Pentru nodul $1$ nu este necesar sa scriem ecuatia deoarece se stie {$X{~1~}=0$}, iar pentru nodul $N$ vom pune ecuatia suma fluxurilor care intra in el sa fie $1$. Sistemul de {$N-1$} ecuatii cu {$N-1$} necunoscute se rezolva folosind Gauss.\r\n\r\nPana acum am satisfacut conditiile de flux si restrictia impusa de enunt, mai avem doar de satisfacut restrictiile de capacitate de pe fiecare muchie. Observam ca daca pentru ecuatia pentru nodul $N$ in loc de $1$ fixam o valoare $S$ fluxurile trimise pe fiecare muchie se vor inmulti cu $S$. Asadar pentru a satisface conditiile de capacitate trebuie doar sa inmultim fluxurile de pe fiecare muchie cu minimul dintre {$C{~i,j~} / F{~i,j~}$} unde {$F{~i,j~}$} este fluxul trimis pe muchie {$(i,j)$} si {$C{~i,j~}$} este capacitatea muchiei {$(i,j)$}.',1490,'public',NULL,NULL),('utilizator/kana','Profil kana','2006-12-14 07:19:16','2007-02-12 20:40:13','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5484,'public',NULL,NULL),('utilizator/kezman','Profil kezman','2006-12-18 15:15:41','2007-02-12 20:40:13','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5536,'public',NULL,NULL),('blog/surse-deschise','Surse deschise','2008-01-29 08:08:06','2008-11-15 13:41:14','Mircea a terminat implementarea proiectului \'IAP5\':http://infoarena.ro/propuneri/5-open-surse . Si Adrian Diaconu a selectat 50 de probleme care sa faca parte din proiect. Acum orice vizitator al siteului va putea vedea toate sursele trimise la oricare dintre cele 50 de probleme selectate. Problemele din arhiva cu \"surse deschise\" au cate o carte desenata in dreptul lor. Pentru a vedea o sursa puteti intra la monitor, de acolo la evaluare completa, iar apoi la vezi sursa.\r\nProblemele au fost alese de Adi pentru diversitatea lor. Sper ca acest pas facut de infoarena sa fie urmat si de alte proiecte legate de olimpiadele de informatica. Tin minte cum in liceu invatam foarte mult citind din sursele elevilor mai mari. Cred ca problemele cu sursele deschise de pe infoarena se vor dovedi un material foarte bun de pregatire.\r\n\r\nMai avem inca o \'initiativa\':propuneri/6-arhiva-educationala interesanta, si cred ca impreuna cele doua proiecte vor spori cu mult utilitatea siteului.\r\n\r\nVa astept cu comentarii si sugestii!',1490,'protected',2645,NULL),('utilizator/fish','Profil fish','2007-01-12 09:58:25','2007-02-12 20:40:13','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5628,'public',NULL,NULL),('task/proc','task/proc','2007-01-11 10:37:47','2007-01-11 10:37:47','Scrie aici despre task/proc',2215,'public',NULL,NULL),('preoni-2005','Preoni 2005','2006-11-24 23:25:20','2007-01-13 21:42:49','h1. preONI 2005\r\n\r\nConcursul preONI 2005 s-a desfasurat in 3 runde avand ca principal scop pregatirea participantilor pentru olimpiada nationala de informatica ONI2005.\r\n\r\nFormatul concursului: 2 grupe (clasele IX-X, XI-XII), 3 probleme in fiecare grupa si un timp de lucru de 4h.\r\n\r\nh2. Runde\r\n\r\n* \"Runda 1\":preoni-2005/runda-1 :Duminica, 23 ianuarie, ora 15:00\r\n* \"Runda 2\":preoni-2005/runda-2 :Miercuri, 23 februarie ora 16:00\r\n* \"Runda 3\":preoni-2005/runda-3 :Duminica, 20 martie la ora 10:00\r\n\r\nh2. \"Clasament IX-X\":preoni-2005/clasament-9-10\r\n\r\nh2. \"Clasament XI-XII\":preoni-2005/clasament-11-12',1,'round: preoni-2005',NULL,NULL),('preoni_2006','preoni_2006','2007-01-18 13:56:41','2007-01-18 13:56:41','Scrie aici despre preoni_2006',5685,'public',NULL,NULL),('preoni-2007/comisie','Organizatori preONI 2007','2007-01-15 15:46:22','2007-01-31 19:52:13','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Organizatori\r\n\r\n\'Echipa infoarena\':echipa-infoarena se ocupa de organizarea si desfasurarea concursului *preONI 2007*.\r\n\r\nh2. Organizare \r\n\r\n* == user(user=\"wickedman\" type=\"tiny\") == : coordonator, promovare concurs\r\n* == user(user=\"fluffy\" type=\"tiny\") == : coordonator tehnic (site-ul, evaluatorul etc.)\r\n* == user(user=\"svalentin\" type=\"tiny\") == : suport tehnic\r\n\r\nh2. Echipa stiintifica\r\n\r\nCei care se vor ocupa de buna desfasurarea a concursului din punct de vedere stiintific (redactarea si compunerea problemelor, realizarea testelor, clarificarea intrebarilor, etc.) sunt:\r\n\r\n* == user(user=\"domino\" type=\"tiny\") ==\r\n* == user(user=\"Cosmin\" type=\"tiny\") ==\r\n* == user(user=\"ditzoneC\" type=\"tiny\") ==\r\n* == user(user=\"silviug\" type=\"tiny\") ==\r\n* == user(user=\"filipb\" type=\"tiny\") ==\r\n* == user(user=\"danielp\" type=\"tiny\") ==\r\n* == user(user=\"azotlichid\" type=\"tiny\") ==\r\n* == user(user=\"greco\" type=\"tiny\") ==\r\n\r\nh2. Multumim\r\n\r\n* &hellip; lui Radu Lupaescu pentru noua sigla preONI 2007\r\n* &hellip; lui Alexandru Marinescu pentru sigla preONI 2007\r\n\r\n==include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('preoni-2007/program','Program preONI 2007','2007-01-15 15:51:59','2007-01-15 15:57:51','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Program\r\n\r\n_in curand_\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('preoni-2007/regulament','Regulament preONI 2007','2007-01-15 15:52:52','2007-01-18 18:24:07','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Regulament\r\n\r\nSe recomanda, pe langa citirea acestui regulament, citirea \"regulamentului\":regulament general infoarena.\r\n\r\n\'Echipa infoarena\':echipa-infoarena isi rezerva dreptul de a modifica prezentul regulament pe parcursul desfasurarii concursului. Daca apar prevederi noi sau daca anumite prevederi ale regulamentului sunt modificate sau eliminate, atunci acestea vor fi anuntate pe site-ul concursului. Orice modificare a regulamentului va intra in vigoare, in functie de situatie, fie din momentul publicarii ei, fie dupa incheierea rundei aflate in desfasurare. In momentul anuntarii modificarii va fi precizat si momentul din care aceasta intra in vigoare.\r\n\r\nh2. Dreptul de participare\r\n\r\nPersoanele care fac parte din \'echipa infoarena\':echipa-infoarena cat si alti contribuitorii implicati direct in organizarea concursului *preONI 2007* nu au dreptul de a participa. De asemenea, orice concurent care are un comportament considerat inadecvat fata de echipa infoarena sau fata de alti concurenti va fi descalificat. Un concurent se poate califica la finala doar daca se incadreaza in grupa la care a concurat (aceasta verificare se va face prin prezentarea unei dovezi legale care il incadreaza pe concurent la aceea grupa).\r\n\r\nh2. Repartizarea\r\n\r\nToti participantii vor fi repartizati in 3 grupe, in concordanta cu varsta lor. Repartizarii este asemanatoare cu acea facuta la olimpiadele de informatica.\r\n\r\n* Clasa a 9a si gimnaziu\r\n* Clasa a 10a\r\n* Clasele 11-12 \r\n\r\nOricine poate participa la o alta grupa decat cea la care se incadreaza, dar calificarea la finala cat si impartirea premiilor se va face conform regulamentului respectiv, fara nici o exceptie.\r\n\r\nh2. Inscriere\r\n\r\nTot ce trebuie sa faceti pentru a participa la concursul *preONI 2007* este sa aveti un cont la infoarena. Inregistrarea se poate face pe site-ul infoarena. Acelasi cont va fi folosit pentru a accesa forum-ul.\r\n\r\nh2. Runde\r\n\r\nVor exista 4 runde de calficare, iar in urma clasamentului stabilit primii de la fiecare grupa vor fi selectati pentru etapa finala desfasurata in cadrul unei tabere. Cele 4 runde vor avea loc sambata si duminica, incepand cu ora 9:00, desi pot interveni exceptii. Durata lor va fi de 4 ore. Pentru un program detaliat al concursului \"click aici\":preoni-2007/program.\r\n\r\nh2. Intrebari\r\n\r\nIn prima ora vor putea fi formulate eventualele intrebari, pe forum, in topicurile special create. Orice intrebare pusa in alt mod (primita ca personal message, pe mail, etc.) va fi ignorata. Raspunsuri vor fi oferite doar la intrebarile puse in prima ora . Intrebarile trebuie formulate astfel incat sa se poate raspunda cu DA sau NU. In caz contrar sau in cazul in care raspunsul se afla in textul problemei se va raspunde cu NO COMMENT. Nu vor exista exceptii de la aceaste reguli. Daca echipa va considera ca raspunsul la o anumita intrebare este de interes general si clarifica anumite aspecte, atunci se va face un anunt general care va aparea atat pe forum cat si in sectiunea Mesaje de la organizatori a grupei respective. Fiecare grupa va avea doi administratori care se vor ocupa de raspunsul acestor intrebari.\r\n\r\nh2. Trimiterea solutiilor\r\n\r\nTrimitrea solutiile se va face prin intermediul interfetei site-ului infoarena.\r\nOdata logati in contul vostru, veti putea selecta arhiva la care doriti sa lucrati (in cazul acesta una din arhivele {*preONI 2007*}) si veti putea folosi link-ul trimite solutii.\r\n\r\nh2. Evaluare\r\n\r\nDupa expirarea timpului de trimitere a solutiilor acestea vor fi evaluate (\"mai multe detalii aici\":documentatie/evaluator). In mod normal, evaluarea se va face imediat dupa concurs, desi exista posibilitatea ca echipa infoarena sa amane evaluarea din motive obiective. Veti putea vizualiza pozitia ocupata in clasament dupa evaluarea in rubrica Clasament.\r\n\r\nSe recomanda sa instalati pe calculatorul vostru aceleasi versiuni de compilatoare ca cele specificate la link-ul de mai sus. \'Echipa infoarena\':echipa-infoarena nu este responsabila pentru diferentele intre versiuni de compilatoare si nu va efectua reevaluaari in astfel de cazuri.\r\n\r\nh2. Contestatii\r\n\r\nEchipa infoarena isi rezerva dreptul de a reevalua orice problema in situatia in care se detecteaza erori in teste sau in programul de verificare dupa evaluare. Cum testele problemelor nu vor fi facute publice, posiblitatile de a contesta sunt limitate. Pentru a asigura o evaluarea corecta, echipa infoarena va garanteaza ca va testa intens toate problemele inainte de concurs si ca va verifica corectitudinea procesului de evaluare dupa terminare. In caz ca totusi aveti o contestatie, aceasta trebuie trimisa pe mail la adresa _mircea.pasoi -at- gmail.com_ in termen de 24 de ore de la afisarea rezultatelor rundei curente pe site. Ele vor fi rezolvate in termen de maxim 5 zile, iar dupa rezolvarea lor rezultatele vor fi declarate finale.\r\n\r\nh2. Solutii\r\n\r\nLa scurt timp dupa terminarea evaluarii se va publica un articol cu solutiile pentru problemele rundei respective. Testele utilizate pentru evaluare nu vor fi facute publice.\r\n\r\nh2. Transferul problemelor\r\n\r\nProblemele vor fi mutate dupa evaluare in Arhiva de probleme infoarena, avand astfel la dispozitie un evaluator 24 din 24 si posiblitatea de a finisa solutiile la problemele nerezolvate in timpul concursului.\r\n\r\nh2. Trisare\r\n\r\n*preONI 2007* este un concurs individual, asadar orice tentativa de colaborare va aduce descalificarea celor implicati. \'echipa infoarena\':echipa-infoarena isi rezerva dreptul de a verifica sursele concurentilor, iar in caz ca se descopera surse aproximativ identice, concurentii respectivi vor fi descalificati din concurs iar user-ul lor de pe infoarena eliminat. Tentativele de frauda (concurarea sub un alt nume decat cel adevarat, etc.) sau orice atac asupra sistemului de evaluare sau asupra paginilor infoarena vor fi pedepsite in aceeasi masura. \r\n',1,'protected',NULL,NULL),('newsletter/2007-01-18','preONI 2007, Runda #1','2007-01-18 14:19:01','2009-01-20 00:55:46','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nIncepe o noua editie preONI, concursul cu premii care te pregateste\r\npentru Olimpiada Nationala de Informatica.\r\n\nPrima runda a concursului va avea loc ...\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Duminica, 21 ianuarie 2007, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPagina rundei: \'preoni-2007/runda-1\':preoni-2007/runda-1\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la aceasta runda iti va afecata rating-ul pe infoarena.\r\nO prestatie buna te poate aduce mai aproape te varful clasamentului.\r\n==NewsletterRating(username=\"%username%\")==\r\nRating-ul este un indicator al performantei tale in conditii de\r\nconcurs. Despre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Despre preONI \n\npreONI, concursul de marca al comunitatii infoarena, este dedicat\r\nelevilor de liceu ce se pregatesc pentru ONI (Olimpiada Nationala de\r\nInformatica).\r\n\nConcursul este impartit in 3 grupe: clasa a IX-a si gimnaziu, clasa\r\na X-a si clasele XI-XII. Se organizeaza 4 runde online de calificare.\r\nIn urma acestora, cei mai buni de la fiecare grupa sunt invitati la\r\no runda finala.\r\n\nIn cadrul unei runde, vei avea de rezolvat 3 probleme in 4h.\r\nCastigatorii rundei finale sunt premiati cu bani si/sau obiecte.\r\n\nPe pagina concursului ( \'preoni-2007\':preoni-2007 ) vei gasi\r\ninformatii despre cum participi, cine propune probleme, premii si\r\nsponsori, regulamentul concursului samd.\r\n\nh2.  Prima data la infoarena? \n\ninfoarena ajuta elevi si studenti sa devina excelenti in informatica!\r\nGratuit ;)\r\n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nGhidul utilizatorului: \'documentatie/pentru-utilizatori\':documentatie/pentru-utilizatori\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('runda/preoni-2007/clasament','Clasament preoni-2007','2007-01-19 23:27:51','2007-01-19 23:27:51','h1. Clasament ==roundparam(round_id=\"preoni-2007\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni-2007\")==',1,'round: preoni-2007',NULL,NULL),('runda/preoni2007_runda1_9/clasament','Clasament preoni2007_runda1_9','2007-01-20 21:42:53','2007-01-20 21:42:53','h1. Clasament ==roundparam(round_id=\"preoni2007_runda1_9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda1_9\")==',1,'round: preoni2007_runda1_9',NULL,NULL),('runda/preoni2007_runda1_10/clasament','Clasament preoni2007_runda1_10','2007-01-20 22:41:46','2007-01-20 22:41:46','h1. Clasament ==roundparam(round_id=\"preoni2007_runda1_10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda1_10\")==',1,'round: preoni2007_runda1_10',NULL,NULL),('runda/preoni2007_runda1_1112/clasament','Clasament preoni2007_runda1_1112','2007-01-20 22:47:03','2007-01-20 22:47:03','h1. Clasament ==roundparam(round_id=\"preoni2007_runda1_1112\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda1_1112\")==',1,'round: preoni2007_runda1_1112',NULL,NULL),('preoni-2007/clasament/runda-1/9','Clasament preONI 2007, Runda 1, Clasa a 9-a si gimnaziu','2007-01-20 22:51:55','2007-01-21 11:49:39','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda1_9\" param=\"title\") ==\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-1/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-1/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda1_9\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',13,'protected',NULL,NULL),('preoni-2007/clasament/runda-1/10','Clasament preONI 2007, Runda 1, Clasa a 10-a','2007-01-20 22:54:12','2007-01-21 11:49:27','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda1_10\" param=\"title\") ==\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-1/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/clasament/runda-1/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-1/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda1_10\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',13,'protected',NULL,NULL),('preoni-2007/clasament/runda-1/11-12','Clasament preONI 2007, Runda 1, Clasele 11-12','2007-01-20 22:54:56','2007-01-21 11:48:44','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda1_1112\" param=\"title\") ==\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-1/10\r\n*(active) \'Clasele 11-12\':preoni-2007/clasament/runda-1/11-12\r\n\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda1_1112\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',13,'protected',NULL,NULL),('lowest-common-ancestor','LCA: Lowest common ancestor','2004-11-08 00:00:00','2009-02-20 01:22:07','h1. LCA: Lowest common ancestor\r\n\r\n(Categoria _Algoritmi_, Autor _Emilian Miron_)\r\n\r\nProblema luata in discutie este ca, avand un arbore dat, sa putem raspunde rapid la multe intrebari de genul: _\"Care este stramosul comun cel mai apropiat dintre doua noduri din arbore?\"_.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Exemplu\':lowest-common-ancestor#exemplu\r\n* \'Aplicabilitate\':lowest-common-ancestor#aplicabilitate\r\n* \'Mod de calcul\':lowest-common-ancestor#calcul\r\n\r\n!> Lowest-common-ancestor?euler.jpg 80%!\r\n\r\nh2(#exemplu). Exemplu\r\n\r\nPentru arborele din imagine, avem ca exemplu urmatoarele query-uri:\r\n\r\n* $lca(2,3) = 1$\r\n* $lca(4,5) = 1$\r\n* $lca(5,6) = 3$\r\n* $lca(1,5) = 1$\r\n* $lca(5,3) = 3$\r\n\r\nh2(#aplicabilitate). Aplicabilitate\r\n\r\nDandu-se un arbore cu costuri sa se raspunda rapid la intrebari de genul: _\"care este distanta minima intre doua noduri date?\"_. O solutie pentru problema de fata ar fi:\r\n\r\n* agatam arborele intr-un nod oarecare si obtinem un arbore cu radacina\r\n* pentru fiecare nod $i$ precalculam {$dist{~i~}$}, reprezentand distanta sa pana la radacina\r\n* precalculam cele necesare pentru algoritmul de _Lowest Common Ancestor_\r\n* distanta dintre doua noduri oarecare $i$ si $j$ va fi egala cu {$dist{~i~} + dist{~j~} - 2*dist{~lca(i,j)~}$}\r\n\r\nh2(#calcul). Mod de calcul\r\n\r\nIn prima etapa a algoritmului facem o parcurgere euleriana a arborelui dat. O parcurgere euleriana este o parcurgere a arborelui in ordinea din figura: se parcurg fiii si se intercaleaza intre ei tatal, obtinand o parcurgere continua.\r\n\r\nMai exact pentru fiecare nod procedam astfel, incepand cu radacina:\r\n\r\n* daca nodul curent este frunza il adaugam la parcurgere\r\n* daca are fii atunci il punem la inceput, la sfarsit si intre parcurgerile euler ale fiilor\r\n\r\nCand facem aceasta parcurgere retinem de asemenea si urmatoarele informatii suplimentare:\r\n\r\n* adancimea fiecarui nod din parcurgere, obtinand un sir de adancimi\r\n* una din pozitiile pe care fiecare nod apare in parcurgere\r\n\r\nIdeea este ca {$lca(i, j)$} este chiar nodul cu cea mai mica adancime intre pozitiile lui $i$ si a lui $j$ in parcurgere. Pentru graful din figura de mai sus avem:\r\n\r\ntable(example). |_. Euler|_. Adancimi|\r\n|12421353631|12321232321|\r\n\r\nPentru perechea de noduri ({$4, 3$}), avem {$lca(4, 3)$} egal cu nodul care se gaseste intre {$poz{~4~}$} si {$poz{~3~}$} in parcurgerea euler si are adancimea minima. Acest nod este $1$, deci {$lca(4, 3) = 1$}.\r\n\r\nAm redus problema la aflarea minimului intre doua pozitii ale unui sir ({_Range Minimum Query_}). Aceasta subproblema o putem rezolva optim folosind arbori de intervale, sau o metoda folosind spatiu supraliniar ({$Nlog{~2~}N$}) a minimelor pe intervale de puteri ale lui {$2$}, incepand de la pozitia {$i$}. Timpul de preprocesare este {$O(N)$} pentru arbori de intervale si {$O(Nlog{~2~}N)$} pentru a doua metoda. In ambele variante timpul de interogare este {$O(log{~2~}N)$}.\r\n\r\nVom prezenta in continuare metoda cu spatiu supraliniar. Calculam minimele inductiv, pastrand:\r\n\r\n* {$min{~i,k~}$} = minimul pe intervalul {$[i...i+2^k^-1]$} (de lungime {$2^k^$}), si\r\n* {$minpos{~i,k~}$} = pozitia minimului de pe intervalul {$[i...i+2^k^-1]$}.\r\n\r\nAcest tablou va fi construit recursiv astfel: pentru $k = 0$ avem {$min{~i,0~} = a{~i~}$} si {$minpos{~i,0~} = i$}, iar pentru k > 0 avem:\r\n\r\n* {$min{~i,k~}$} = minim({$min{~i,k-1~}$}, {$min{~i+2^k-1^,k-1~}$})\r\n* {$minpos{~i,k~}$} = pozitia minimului ({$minpos{~i,k-1~}$} sau {$minpos{~i+2{^k-1^},k-1~}$})\r\n\r\nPentru _query_ intre pozitiile $l$ si $r$ procedam astfel: fie $k$ cel mai mare numar astfel incat {$2^k^$} &le; lungimea intervalului {$(l, r)$}.\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp; {$min(l, r)$} = minim( {$min{~l,k~}$}, {$minimul pe intervalul (l+2^k^, r)$})\r\n&nbsp;&nbsp;&nbsp;&nbsp; {$pozmin(l, r)$} = pozitia minimului intre $l$ si $r$\r\n\r\nDaca {$l = pos{~i~}$} si {$r = pos{~j~}$} ({$pos{~i~} < pos{~j~}$}) la sfarsitul _query_-ului {$euler{~pozmin~}$} este chiar {$lca(i, j)$}.\r\n',2044,'public',3699,NULL),('preoni-2007/runda-1/9','preONI 2007, Runda 1, Clasa a 9-a si gimnaziu','2007-01-20 21:44:57','2007-01-21 14:12:45','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda1_9\" param=\"title\") ==\r\n\r\n==roundregister(round_id=\"preoni2007_runda1_9\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-1/9.\r\n\r\nRunda s-a desfasurat Duminica 21 ianuarie, la ora {*09^30^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda1_9\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',13,'protected',NULL,NULL),('preoni-2007/runda-1/10','preONI 2007, Runda 1, Clasa a 10-a','2007-01-20 22:43:46','2007-01-21 14:13:37','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda1_10\" param=\"title\") ==\r\n\r\n==roundregister(round_id=\"preoni2007_runda1_10\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-1/10.\r\n\r\nRunda s-a desfasurat Duminica 21 ianuarie, la ora {*09^30^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda1_10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',13,'protected',NULL,NULL),('preoni-2007/runda-1/11-12','preONI 2007, Runda 1, Clasele 11-12','2007-01-20 22:50:14','2007-01-21 14:14:30','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda1_1112\" param=\"title\") ==\r\n\r\n==roundregister(round_id=\"preoni2007_runda1_1112\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-1/11-12.\r\n\r\nRunda s-a desfasurat Duminica 21 ianuarie, la ora {*09^30^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda1_1112\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',13,'protected',NULL,NULL),('blog/preoni-2007-runda-1','S-a incheiat Runda din preONI 2007!','2007-01-22 22:04:00','2007-01-22 22:04:00','h1. S-a incheiat Runda din preONI 2007!\r\n\r\nPrima runda a concursului \'preONI 2007\':preoni-2007 s-a incheiat. Gasiti pe \'pagina rundei\':preoni-2007/runda-1 problemele , clasamentele si articolul cu solutii.',1,'public',NULL,NULL),('preoni-2007/runda-1','Runda 1 preONI 2007','2007-01-15 15:59:43','2007-01-22 22:04:38','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Runda 1\r\n\r\nRunda 1 s-a incheiat.\r\n\r\nRunda a inceput Duminica 21 ianuarie, la ora {*09^30^*} si a durat 4h. Participantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np{color:red}. *ATENTIE!* Ca sa poata participa la aceasta runda, concurentii au trebuit sa se inscrie *inainte de ora 09^30^* la grupa de varsta corespunzatoare! *Nu au putut participa* elevii care nu s-au inscris la o grupa de varsta *inainte de ora 09^30^*.\r\n\r\nAceeasi procedura se va urma la fiecare runda preONI. Timp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, concurentii nu pot participa daca nu s-au inscris.\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta&hellip;\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-1/10\r\n* \'Clasele 11-12\':preoni-2007/runda-1/11-12\r\n\r\nPoti vedea solutiile problemelor \'aici\':preoni-2007/runda-1/solutii\r\n\r\nh2. Clasament Runda 1\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-1/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-1/11-12\r\n\r\nh2. Discutii preONI pe forum\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\nh2. Organizatori\r\n\r\n* Subiectele vor fi propuse de:\r\n==User(user=\"danielp\" type=\"tiny\")==\r\n==User(user=\"ditzonec\" type=\"tiny\")==\r\n==User(user=\"domino\" type=\"tiny\")==\r\n==User(user=\"filipb\" type=\"tiny\")==\r\n==User(user=\"greco\" type=\"tiny\")==\r\n\r\n* Pentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n==User(user=\"fluffy\" type=\"tiny\")==\r\n==User(user=\"svalentin\" type=\"tiny\")==\r\n==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('template/preoni-2007/clasament-header','template/preoni-2007/clasament-header','2007-01-21 11:47:40','2007-01-22 22:01:54','&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;',1,'protected',NULL,NULL),('template/userheader','template/userheader','2006-12-02 18:14:52','2007-01-21 14:06:01','h1. ==UserInfo(user=\"%user%\" info=\"fullname\")== (%user%)\r\n\r\n== include(page=\"template/userinfo\" user=\"%user%\") ==\r\n',13,'protected',NULL,NULL),('runda/unirea9-10/clasament','Clasament unirea9-10','2007-01-22 16:12:12','2007-01-22 16:12:12','h1. Clasament ==roundparam(round_id=\"unirea9-10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"unirea9-10\")==',1,'round: unirea9-10',NULL,NULL),('runda/unirea11-12/clasament','Clasament unirea11-12','2007-01-22 16:31:00','2007-01-22 16:31:00','h1. Clasament ==roundparam(round_id=\"unirea11-12\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"unirea11-12\")==',1,'round: unirea11-12',NULL,NULL),('preoni-2007/runda-1/solutii','Solutii preONI 2007, Runda 1','2007-01-21 08:46:01','2007-02-21 18:28:09','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Solutii Runda 1\r\n\r\nh2. Aprindere \r\n\r\nh3. (problema usoara, clasa a 9-a)\r\n\r\nEste evident ca nu are rost sa actionam un intrerupator de mai multe ori. In aceste conditii, solutia este unica, deoarece nu putem avea doua intrerupatoare intr-o singura camera. Cu alte cuvinte, daca parcurgem camerele de la stanga la dreapta si intalnim o camera cu becul inchis, va trebui sa actionam intrerupatorul unic din camera respectiva. Daca am fi permis ca o camera sa aiba mai multe intrerupatoare, problema s-ar fi complicat semnificativ.\r\nSe pot afla usor intrerupatoarele care trebuie actionate astfel: se parcurg camerele de la stanga la dreapta, iar in momentul in care ajungem la o camera cu becul inchis trebuie sa actionam intrerupatorul din camera respectiva (daca nu exista intrerupator, atunci nu avem solutie). Cum intrerupatorul respectiv actioneaza becuri din camere &ge; $i$, nu vom modifica nimic din becurile precedente. De asemenea, vom aduna costul lor la rezultat. \r\n\r\nh2. Patrate3 \r\n\r\nh3. (problema medie, clasa a 9-a)\r\n\r\nMai intai sortam punctele crescator dupa abscisa, iar pentru abscise egale dupa ordonata. Acum, folosind cautarea binara putem cauta orice punct in timp logaritmic. Pentru fiecare pereche de puncte vom forma patratul care are o diagonala formata din perechea respectiva. Dupa ce calculam si celelalte 2 puncte, le cautam binar in vectorul sortat. Daca le gasim, inseamna ca am mai gasit un patrat. Complexitatea solutiei este $O(N^2^ log N)$. Precizia recomandata este de $10^-4^$.\r\nSingura problema care ramane de rezolvat acum e calcularea punctelor patratului daca stim doar o diagonala. O metoda simpla de gasire a lor, ce nu necesita cunostiinte avansate de geometrie, este observarea simetriilor care se formeaza fata de centrul patratului. Fie $x0, y0$ si $x1, y1$ coordonatele diagonalei cunoscute iar $x2, y2$ si $x3, y3$ coordonatele necunoscute. Centrul patratului este mijlocul unei diagonale, deci coordonatele lui sunt $mijx = (x0 + x1) / 2$ si $mijy = (y0 + y1) / 2$. Sa notam $dx = abs(mijx - x0)$ si $dy = abs(mijy - y0)$. Se observa ca daca $y0 < y1$ atunci $x2 = mijx + dy, y2 = mijy - dx, x3 = mijx - dy$ iar $y3 = mijy + dx$. In caz contrar, avem $x2 = mijx - dy, y2 = mijy - dx, x3 = mijx + dy$ iar $y3 = mijy + dx$.\r\n\r\nh2. Elimin \r\n\r\nh3. (problema grea, clasa a 9-a / problema medie, clasa a 10-a)\r\n\r\nDaca $S$ este suprafata ( aria ) matricii, este evident ca {$minim(M, N) &le; sqrt(S)$}. Pentru primele $3$ teste se observa ca cel putin o dimensiune este &le; 10. Pentru celelalte teste avem:\r\n\r\n* 266 = 2 * 7 * 19\r\n* 539 = 7 * 7 * 11\r\n* 1630 = 2 * 5 * 163\r\n* 3495 = 3 * 5 * 233\r\n* 3653 = 13 * 281\r\n* 5866 = 2 * 7 * 419\r\n* 7294 = 2 * 7 * 521\r\n\r\nSe observa ca in toate cazurile de mai sus, oricum am grupa numerele prime pentru a obtine dimensiunile matricii, cea mai mica dintre dimensiuni nu poate depasi {$15$}. Deci, in toate testele, stim sigur ca {$min(M, N) &le; 15$}. Sa presupunem ca aceasta dimensiune este numarul coloanelor, {$N$}, celalalt caz rezolvandu-se identic, rotind matricea.\r\nPutem genera toate posibilitatile de a elimina exact {$C$} coloane din numarul total de {$N$}. Pentru fiecare caz generat, calculam suma elementelor ramase pentru fiecare linie in parte, si sortam aceste sume. Evident, vom elimina cele mai mici {$R$} sume.\r\nComplexitatea unui astfel de algoritm este deci {$O(2^N^  * (M log M + M*N))$}.\r\n\r\nh2. Triplete\r\n\r\nh3. (problema usoara, clasa a 10-a)\r\n\r\nPutem considera cele $N$ animale ca fiind noduri ale unui graf neorientat si o relatie de forma $i j$ ca fiind muchie intre nodurile $i$ si {$j$}. Problema cere determinarea numarului de triunghiuri in graful astfel construit ( numarul de triplete de noduri astfel incat intre oricare doua noduri din triplet exista muchie ). O solutie imediata are complexitatea {$O(N^3^)$}, prin generarea tuturor tripletelor. O solutie mai buna se bazeaza pe urmatorul rationament: pentru fiecare muchie din graf $a b$ trebuie sa vedem cate noduri adiacente cu $a$ si $b$ exista in graf ( adica cate triunghiuri care contin nodurile $a$ si $b$ se pot forma ). Pentru o muchie fixata este suficienta iterarea prin lista de adiacenta a nodurilor $a$ si $b$ si adunarea la numarul total de solutii a numarului de noduri comune. Acest algoritm are complexitatea {$O(M * N)$}, pentru ca parcurgerea unei liste de adiacenta se realizeaza in $O(N)$. Algoritmul de mai sus poate fi optimizat prin tinerea pe grupuri de biti a listei de adiacenta. Astfel, pentru orice nod {$i$}, primii $B$ biti din lista lui de adiacenta vor reprezenta legaturile cu primele $B$ noduri din cele {$N$} ( bit 1 pentru legatura si 0 altfel ), urmatorii $B$ biti legaturile cu nodurile $B+1...2*B$, etc. Pentru a vedea cate noduri adiacente comune au $a$ si $b$ este suficient sa realizam o operatie AND intre grupurile corespunzatoare de biti din listele de adiacenta ale lui $a$ si ale lui $b$ si sa adunam la numarul total de solutii numarul de biti de 1 din acest numar. Complexitatea acestui algoritm este {$O(M*N/B)$}, unde $B$ este numarul de biti dintr-un grup.\r\n\r\nh2. Pachete\r\n\r\nh3. (problema grea, clasa a 10-a)\r\n\r\nSa consideram initial ca oficiul postal este in punctul de coordonate {$(0, 0)$} si restul oraselor au coordonate pozitive ( sunt toate in primul cadran ). Se sorteaza orasele dupa abscisa {$X$}. Dupa sortare, acestea trebuie partitionate intr-un numar minim de subsiruri astfel incat intr-un subsir coordonatele punctelor ({$Y$}) sa fie crescatoare. Un astfel de subsir reprezinta drumul unui postas (este de cost minim deoarece mereu merge in dreapta si in sus). Algoritmul optim pentru aflarea numarului minim de subsiruri crescatoare in care poate fi partitionat un sir are complexitatea {$O(NlogN)$}. Primul element va face parte din primul subsir. La pasul {$i$}, {$i>1$}, elementul al $i$-lea va fi introdus in acel subsir care se termina intr-un element cu valoare mai mica decat elementul curent si care are valoarea maxima dintre toate elementele de acest tip. Cautarea se poate face cu o cautare binara in raport cu ultimele pozitii pentru fiecare subsir, pentru ca se observa ca printr-un astfel de procedeu ultimile valori vor fi intotdeauna sortate descrescator.\r\nDaca oficiul postal se afla in {$(Px, Py)$}, acest punct imparte planul in {$4$} cadrane, si se aplica aceeasi rezolvare de mai sus pentru fiecare cadran.\r\n\r\n\r\nh2. 1-sir\r\n\r\nh3. (problema usoara, clasele 11-12)\r\n\r\nPrima observatie este aceea ca valoarea maxima pe care o poate lua $S$ este {$N * (N-1) / 2$}, sirul {$s$} fiind egal cu {$(0, 1, 2... N-1)$}, iar valoarea minima {${@-N * (N-1) / 2@}$}, caz in care sirul este egal cu {$(0, {@-1@}, {@-2@}... {@-(N-1)@})$}. Daca notam cu {$D[N][S]$} numarul de 1-siruri cu $N$ termeni care au suma elementelor $S$, atunci se observa ca {$D[N][S] = D[N-1][S-(N-1)] + D[N-1][S+(N-1)]$}, deoarece avem doua posibilitati de alegere pentru al doilea element (1 sau -1), si fiecare alegere poate fi interpreta ca o translatie pentru fiecare din elementele urmatoare cu 1 sau -1 ( deci in total o translatie in functie de suma de {$N-1$}, cu plus sau cu minus ). Pentru a evita folosirea indicilor negativi pentru suma este suficient sa observam ca {$D[N][S] = D[N][-S]$}, pentru orice {$S > 0$}, relatie evidenta din faptul ca se poate forma o bijectie intre 1-sirurile cu suma {$S$} si cele cu suma {${@-S@}$} printr-o simpla inmultire cu -1. Pentru ca algoritmul sa se incadreze in limita de memorie este suficient sa retinem doar ultimele doua linii din tabloul $D$. Un astfel de algoritm are complexitate $O(N^3^)$ si obtine punctajul maxim.\r\n\r\nh2. Diviz\r\n\r\nh3. (problema medie, clasele 11-12)\r\n\r\nProblema se rezolva prin metoda programarii dinamice. Fie {$M[j][i]{@[r]@}$} numarul de moduri de a alege subsiruri distincte de lungime $j$ care contin ca ultima cifra cea de-a $i$-a cifra a numarului {$N$}, subsiruri care sa dea restul $r$ la impartirea {$K$}. Daca ne aflam in starea {$(j, i, r)$} putem sa actualizam starea {$(j+1, first[cif][i+1], (r*10+cif) mod K)$}, considerand ca am adaugat la sfarsitul fiecarui subsir definit de {$(j, i, r)$} cifra {$cif$}. Prin {$first[cif][i]$} se defineste prima aparitie in numarul $N$ a cifrei $cif$ dupa pozitia {$i$}. Tabloul $first$ va fi, evident, preprocesat. Pentru a nu numara subsirurile egale de doua ori, trebuie sa initializam pentru lungimea 1 doar pozitiile care contin pentru prima oara o cifra. Astfel initializam starile {$(1, @first[cif][0]@, cif mod K)$} cu 1, pentru cif = 1..9 (ca nu cumva un subsir sa inceapa cu 0). Pe parcurs, adunam la solutie starile care au lungimea cuprinsa intre $A$ si $B$ si care au $r$ egal cu 0.\r\n\r\nComplexitatea finala a algoritmului este {$O(K * L^2^)$}, unde L este numarul de cifre ale numarului {$N$}.\r\n\r\nh2. Radiatie\r\n\r\nh3. (problema grea, clasele 11-12)\r\n\r\nPrimul pas in rezolvarea problemei este construirea arborelui partial de cost minim a grafului dat in {$O(M*logM)$}, folosind unul din algoritmii clasici precum Kruskal sau Prim. Se poate demonstra ca o interogare in graful initial este echivalenta cu o interogare in arborele partial minim.\r\nPentru a determina cea mai mare valoare a unei muchii pe drumul unic din arbore intre nodurile $i$ si $j$ procedam astfel: pentru orice nod $i$ din arbore si pentru orice $j$, fie {$A[i][j]$} = al {$2^j^$}-lea stramos al nodului $i$ in drumul spre radacina ( aleasa aleator la inceput ) si {$B[i][j]$} = muchia de cost maxim dintre cei {$2^j^$} stramosi ai nodului {$i$}. Precalculand aceste matrici in {$O(N*logN)$} se poate raspunde la un query in {$O(log N)$}, mergand inspre radacina simultan din $x$ si $y$ pe stramosi pe baza puterilor lui 2 pana cand intalnim primul nod care este stramos al ambelor noduri. La fiecare pas vom actualiza raspunsul prin compararea cu valorea elementelor corespunzatoare din tabloul $B$.\r\nO solutie si mai simpla de implementat este folosirea arborelui care rezulta in urma algoritmului lui Kruskal, renuntand la euristica de compresie a drumului, si folosind doar euristica dupa rang. Se poate demonstra ca o interogare in arborele partial minim este echivalenta cu o interogare in arborele de multimi disjuncte obtinut din algoritmul lui Kruskal. Cum acest arbore are inaltimea {$O(logN)$}, se poate folosi o parcurgere triviala pentru a raspunde la orice query.\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1931,'public',NULL,NULL),('utilizator/razvan_varnita','Profil razvan_varnita','2007-01-23 09:39:18','2007-02-12 20:40:13','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5723,'public',NULL,NULL),('unirea-2007','Unirea 2007','2007-01-24 00:49:02','2007-02-09 20:28:11','h1. Unirea 2007\r\n\r\n(htabs)*(active) \'*Home*\':unirea-2007\r\n* \'Clasele IX-X\':unirea-2007/clasele-9-10\r\n* \'Clasele XI-XII\':unirea-2007/clasele-11-12\r\n* \'Rezultate\':unirea-2007/rezultate-9-10\r\n\r\n parte din cadrul manifestarilor _Zilele Unirii_, infoarena gazduieste un concurs de informatica online - *cu premii si diplome* - la care sunt invitati elevi din toata tara.\r\n\r\nConcursul incepe *Sambata, 27 ianuarie la ora 14^00^* si dureaza *3h*.\r\n\r\np{color:red}. *ATENTIE!* Pentru a participa la acest concurs, trebuie sa te inscrii inainte de ora 14^00^, 27 ian. la grupa de varsta corespunzatoare! Nu pot participa elevii care nu se inscriu la grupa lor de varsta inainte de ora 14^00^, 27 ian.\r\n\r\nInscrierea se face printr-un simplu click. Nu trebuie sa te inregistrezi din nou pe site!\r\n\r\nh2. Alege-ti grupa de varsta\r\n\r\n* \'*Clasele IX si X*\':unirea-2007/clasele-9-10\r\n* \'*Clasele XI si XII*\':unirea-2007/clasele-11-12\r\n\r\nSolutiile oficiale la probleme se gasesc \'aici\':unirea-2007/solutii.\r\n\r\nh2. Despre Unirea 2007\r\n\r\nIn perioada 26 - 28 ianuarie 2007, Colegiul National Unirea, Primaria Focsani, Inspectoratul Scolar Vrancea si Microsoft Romania organizeaza, in cadrul manifestarilor _Zilele Unirii_, intalnirea cu tema Resurse IT&amp;C in educatie.\r\n\r\nCele doua zile dedicate acestei intalniri vor cuprinde:\r\n\r\n* concurs online de informatica gazduit de infoarena.ro\r\n* concurs de proiecte realizate de elevi in domeniile: pagini web, software educational &amp; utilitar, multimedia\r\n* concurs de matematica\r\n\r\n&rarr; \'Vezi pagina oficiala a acestei manifestari\':http://unirea.lufo.ro/\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru.\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti probleme, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nh2. Prima data pe infoarena?\r\n\r\ninfoarena ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi.\r\n\r\nVezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n',1,'protected',NULL,NULL),('newsletter/2007-01-24','Concursul de informatica Unirea','2007-01-24 02:00:54','2009-01-20 00:55:46','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nTe invitam sa participi la Unirea 2007, un concurs de informatica\r\ngazduit de infoarena. Castigatorii vor primi diplome si premii din\r\npartea organizatorilor.\r\n\nConcursul se va desfasura ...\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Sambata, 27 ianuarie 2007, orele 14:00 - 17:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPe acesta pagina gasesti informatii detaliate despre concursul Unirea:\r\n\'unirea-2007\':unirea-2007\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la acest concurs iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te poate aduce mai aproape te varful clasamentului.\r\n==NewsletterRating(username=\"%username%\")==\r\nDespre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Prima data la infoarena? \n\ninfoarena ajuta elevi si studenti sa devina excelenti in informatica!\r\nGratuit ;)\r\n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nGhidul utilizatorului: \'documentatie/pentru-utilizatori\':documentatie/pentru-utilizatori\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nClick pe acest link ca sa nu mai primesti instiintari:\r\n\'account/%username%\':account/%username%\r\n\ninfoarena nu trimite mesaje nesolicitate!\r\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\n\n',13,'protected',NULL,NULL),('template/userinfo','template/userinfo','2006-11-12 18:39:53','2008-12-08 20:38:36','table(compact). |=/5. !utilizator/%user%?avatar 150x150!:/utilizator/%user%?action=download&file=avatar \r\n{\'Vezi solutiile trimise\':monitor?user=%user%}\r\n|_. Nume | == userinfo(user=\"%user%\" info=\"fullname\")== |\r\n| |_. Cont | ==userinfo(user=\"%user%\" info=\"username\")== |\r\n| |_. Rating | ==userinfo(user=\"%user%\" info=\"rating\")== |\r\n| |_. Statut | ==userinfo(user=\"%user%\" info=\"security\")== |\r\n|_. Forum | ==SmfLink(user=\"%user%\" link=\"pm\" caption=\"trimite mesaj privat\")==, ==SmfLink(user=\"%user%\" link=\"stats\" caption=\"vezi activitate\")== |\r\n\r\n\r\n',1490,'protected',NULL,NULL),('unirea-2007/clasele-9-10','Unirea 2007, Clasele IX - X','2007-01-22 16:12:12','2007-02-09 20:27:58','h1. Unirea 2007\r\n\r\n(htabs)* \'*Home*\':unirea-2007\r\n*(active) \'Clasele IX-X\':unirea-2007/clasele-9-10\r\n* \'Clasele XI-XII\':unirea-2007/clasele-11-12\r\n* \'Rezultate\':unirea-2007/rezultate-9-10\r\n\r\n== roundregister(round_id=\"unirea9-10\") ==\r\n\r\nConcursul incepe *Sambata, 27 ianuarie, ora 14^00^* si dureaza *3 ore*.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"unirea9-10\" score=\"1\") ==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"36\" count=\"10\")==\r\n\r\nh2. Organizatori\r\n\r\n* Subiectele vor fi propuse de:\r\n==User(user=\"danielp\" type=\"tiny\")==\r\n==User(user=\"azotlichid\" type=\"tiny\")==\r\n\r\n* Pentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n',1,'round: unirea9-10',NULL,NULL),('unirea-2007/clasele-11-12','Unirea 2007, clasele 11-12','2007-01-22 16:31:00','2007-02-09 20:27:26','h1. Unirea 2007\r\n\r\n(htabs)* \'*Home*\':unirea-2007\r\n* \'Clasele IX-X\':unirea-2007/clasele-9-10\r\n*(active) \'Clasele XI-XII\':unirea-2007/clasele-11-12\r\n* \'Rezultate\':unirea-2007/rezultate-9-10\r\n\r\n== roundregister(round_id=\"unirea11-12\") ==\r\n\r\nConcursul incepe *Sambata, 27 ianuarie, ora 14^00^* si dureaza *3 ore*.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"unirea11-12\" score=\"1\") ==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"36\" count=\"10\")==\r\n\r\nh2. Organizatori\r\n\r\n* Subiectele vor fi propuse de:\r\n==User(user=\"ditzonec\" type=\"tiny\")==\r\n==User(user=\"domino\" type=\"tiny\")==\r\n\r\n* Pentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n',1,'round: unirea11-12',NULL,NULL),('unirea-2007/rezultate-11-12','Unirea 2007, Clasament pentru clasele XI-XII','2007-01-27 15:34:41','2007-01-27 15:36:37','(htabs)* \'*Home*\':unirea-2007\r\n* \'Clasele IX-X\':unirea-2007/clasele-9-10\r\n* \'Clasele XI-XII\':unirea-2007/clasele-11-12\r\n*(active) \'Rezultate\':unirea-2007/rezultate-11-12\r\n\r\np=. \'*Clasele IX-X*\':unirea-2007/rezultate-9-10 | *Clasele XI-XII*\r\n\r\nh2. Clasament XI-XII\r\n\r\n== Rankings(rounds=\"unirea11-12\") == \r\n',13,'protected',NULL,NULL),('blog/s-a-incheiat-unirea-2007','S-a incheiat concursul Unirea 2007','2007-01-27 16:48:30','2007-02-09 19:53:01','h1. S-a incheiat Unirea 2007\r\n\r\nEvaluarea a inceput imediat dupa terminarea timpului de lucru. \'Rezultatele au fost publicate\':unirea-2007/rezultate-9-10 iar problemele au fost adaugate in \'arhiva\':arhiva.\r\n\r\nLa acest concurs s-au inscris *342 de concurenti*. 237 concurenti au trimis cel putin o solutie. In total au fost evaluate *545 de solutii*.\r\n\r\nFelicitari tuturor concurentilor si in special castigatorilor :)\r\n\r\n\'*Vezi clasamentul Unirea 2007*\':unirea-2007/rezultate-9-10\r\n\r\nDe asemenea, in urma concursului au fost recalculate \'rating-urile\':documentatie/rating utilizatorilor. Vezi si \'cei mai bine cotati\':clasament-rating utilizatori infoarena.',13,'protected',NULL,NULL),('unirea-2007/solutii','Solutii Unirea 2007','2007-01-27 20:37:17','2008-01-30 17:43:18','h1. Solutii\r\n\r\n\r\nh2. Maxsecv\r\n\r\nh3. (clasele 9-10)\r\n\r\nSe observa ca secventa maxima de $1$ care se poate obtine are lungimea egala cu suma primelor doua secvente maxime din vectorul original. Printr-o operatie descrisa se pot alatura cu usurinta cele doua secvente. \r\nPentru obtinerea unei solutii liniare e suficient sa parcurgem vectorul de la stanga la dreapta si sa updatam la fiecare pas lungimea secventei curente de $1$. In momentul in care ajungem la capatul unei astfel de secvente facem un update pentru primul si al 2-lea maxim, dupa caz.\r\n\r\n\r\nh2. Chernel\r\n\r\nh3. (clasele 9-10)\r\n\r\nConsiderandu-se sirul $a{~1~} a{~2~} ... a{~N~}$ pentru un $N$ fixat, se observa ca dupa $N-1$ transformari, acesta devine $a{~1~} * C{~N-1~}^0^ + a{~2~} * C{~N-1~}^1^ + a{~3~} * C{~N-1~}^2^ + ... + a{~N~} * C{~N-1~}^N-1^$ . De aici reiese ca elementele sirului initial a calor valoare nu influenteaza numarul caracteristic (numarul din ultimul sir obtinut $modulo M$) sunt cele ai caror coeficienti sunt multipli ai lui $M$. Astfel problema se reduce la numararea combinarilor de $N-1$ luate cate $i$ (cu $i$ intre $0$ si $N-1$) care sunt multipli de $M$. Aceasta se realizeaza simplu \"generand\" combinarile respective: ne bazam pe recurenta $C{~N~}^k+1^ = C{~N~}^k^ * (n-k) / (k+1)$ si verificam cate dintre acestea sunt divizibile cu $M$. Problema este ca aceste valori vor deveni uriase destul de rapid, iar stocarea lor in memoria calculatorului este ineficienta. Din acest motiv nu se vor retine numerele propriu zise, ci doar exponentii factorilor primi ai lui $M$, (numarul maxim de factori primi ai lui fiind aproximat la $O(ln ln M)$, si $9$ pentru datele de test ale problemei) care se vor actualiza pentru fiecare combinare procesata.\r\nComplexitatea finala a algoritmului devine astfel $O(N * ln ln M)$.\r\n\r\nh2. Amenzi\r\n\r\nh3. (clasele 11-12)\r\n\r\nProblema se poate rezolva folosind metoda programarii dinamice. Se construieste matricea $A{~t,i~}$ in care se retine valoarea totala a amenzilor ce poate fi data pana la momentul $t$ astfel incat la momentul $t$ sa fim in intersectia {$i$}. Pentru toate muchiile ({$j,i$}) de cost $c$ vom compara {$A{~t,i~}$} cu {$A{~t-c,j~}$} alegand maximul dintre aceste valori. De fapt ar trebui inspectate toate valorile {$A{~t-c,j~}$} {$A{~t-c-1,j~}$} ... {$A{~1,j~}$} {$A{~0,j~}$} dar este clar ca maximul acestor valori se afla in {$A{~t-c,j~}$}. Deasemenea trebuie considerat cazul cand politistul sta pe loc deci ne vom uita si la valoarea din {$A{~t-1,i~}$}. Apoi politistul va da toate amenzile posibile la momentul respectiv in intersectia respectiva deci vom aduna respectiva suma la {$A{~t,i~}$}.\r\nAvand construita aceasta matrice se poate raspunde in $O(1)$ la fiecare intrebare.\r\nComplexitatea totala va fi $O(Tmax * M)$ ca timp si $O(Tmax * N)$ ca memorie. \r\n\r\nh2. Secventa 5\r\n\r\nh3. (clasele 11-12)\r\n\r\nVom construi o procedura cu ajutorul careia vom numara cate secvente exista care contin cel mult $X$ elemente distincte. Folosind aceasta procedura, rezultatul problemei va fi: numarul de secvente cu cel mult $U$ elemente distincte - numarul de secvente cu cel mult $L-1$ elemente distincte. \r\nLa primul pas, vom normaliza valorile din sirul de intrare, inlocuind fiecare valoare cu un numar de la $1$ la $N$ (spre exemplu sirul $13 13 47 9 9$ devine $1 1 2 3 3$). Aceasta normalizare se poate face in $O(N*lg N)$ cu o sortare, dar aceasta solutie va obtine doar $80$ de puncte. Pentru $100$ de puncte normalizarea trebuie facuta folosind o tabela \'hash\':tabele-hash-scurta-prezentare.\r\nFie $L{~i~}$ cel mai mic indice astfel incat secventa cu elementele $L{~i~}...i$ contine cel mult $X$ elemente distincte (cu alte cuvinte cea mai lunga secventa cu maxim $X$ elemente distincte care se termina pe pozitia $i$). Numarul total de subsecvente va fi $(1-L{~1~}+1) + (2-L{~2~}+1) + (3-L{~3~}+1) + ... + (N-L{~N~}+1)$.\r\nEste usor de aratat ca $L{~i~} &le; L{~i+1~}$ pentru orice $i$. Asadar, pe masura ce trecem de la $i$ la $i+1$ vom incepe calculul lui $L{~i+1~}$ de la valoarea $L{~i~}$. Pentru a stii la fiecare moment cate elemente distincte sunt in secventa $L{~i~}...i$ vom mentine un vector $V$ cu proprietatea ca $V{~x~}$ = de cate ori apare $x$ in secventa si o variabila $Nr$ reprezentand numarul de valori distincte din secventa. Valorea lui $Nr$ va creste doar cand $V{~x~}$ se schimba din $0$ in $1$, si va scade doar cand $V{~x~}$ se schimba din $1$ in $0$ (pentru un $x$ oarecare). Complexitatea totala a algoritmului este $O(N)$.',2044,'public',NULL,NULL),('sandbox/usermacrobug','sandbox/usermacrobug','2007-02-03 11:12:48','2007-04-18 07:23:27','\"Articol\":minimal-enclosing-circle scris de ==user(user=\"bogdan2412\" type=\"tiny\")==.\r\n',1,'public',NULL,NULL),('minimal-enclosing-circle','Minimal Enclosing Circle','2007-01-30 17:54:51','2010-04-01 18:59:37','h1. Minimal enclosing circle\r\n\r\n(Categoria _Geometrie_, Autor _Bogdan Tataroiu_)\r\n\r\nIn cadrul acestui articol vom analiza problema determinarii unui cerc de raza minima ce contine in interior sau pe circumferinta toate punctele dintr-un set dat. Aceasta problema mai poate fi gasita si sub denumirea de _Smallest Enclosing Circle_ sau _Mininum Spanning Circle_.\r\n\r\nh2. Algoritm naiv\r\n\r\nEste clar ca cercul de raza minima ce include toate punctele din setul dat trebuie sa aiba pe circumferinta cel putin 2 puncte, altfel am putea micsora raza cercului pana cand am atinge si al doilea punct. Daca pe cerc exista 2 puncte consecutive ce formeaza un arc de cerc mai mare de {$&pi;$}, atunci cercul poate fi micsorat, ducand centrul cercului inspre segmentul format de cele 2 puncte. Astfel, singurul caz in care cercul de raza minima contine doar 2 puncte pe circumferinta este atunci cand diametrul cercului este egal cu segmentul ce uneste cele 2 puncte, in celelalte cazuri cercul este determinat de 3 (sau posibil mai multe puncte) din set.\r\n\r\nDe aici este destul de usor de formulat un algoritm:\r\n\r\n* Se considera cercurile determinate de fiecare pereche de puncte din set, cu diametrul egal cu segmentul ce uneste cele 2 puncte, alaturi de cele determinate de oricare 3 puncte din set.\r\n* Se verifica care dintre acestea contin in interior toate punctele din set si se alege cel de raza minima.\r\n\r\nAlgoritmul descris are complexitate {$O(N^3^)$} pentru generarea cercurilor si inca {$O(N)$} pentru fiecare cerc pentru verificare, in total avand {$O(N^4^)$}.\r\n\r\nh2. Algoritm {$O(N^2^)$} !>minimal-enclosing-circle?schema.gif!\r\n\r\nAlgoritmul acesta se bazeaza pe aceleasi observatii ca mai sus. Se porneste de la un cerc mare care sigur cuprinde toate punctele si se micsoreaza la fiecare pas raza cercului cat mai mult posibil.\r\n\r\n# Se construieste un cerc de raza suficient de mare incat sa cuprinda toate punctele in mod sigur (raza infinit) si un centru ales aleator.\r\n# Se gaseste punctul cel mai departat de centrul cercului, notat cu {$A$}, si se micsoreaza raza cercului pana cand acesta atinge punctul.\r\nPractic raza cercului devine egala cu distanta dintre punctul {$A$} si centrul ales.\r\n# In cazul in care cercul trece deja prin 2 sau mai multe puncte trecem la pasul numarul 4. In caz contrar, se apropie centrul cercului de punctul {$A$}, determinat la punctul 2, pana cand cercul intersecteaza un nou punct. Acest lucru se poate implementa printr-o parcurgere a punctelor din set. Pentru fiecare punct {$B$} din set se calculeaza raza cercului astfel incat centrul cercului sa ramana pe aceeasi axa fata de puncutl {$A$} si {$B$} sa se afle pe cerc ( se formeaza un triunghi isoscel, care are ca baza segmentul AB si celelalte muchii egale cu raza. Se poate calcula raza cercului folosind teorema cosinusului. )\r\n# In acest moment avem un cerc determinat de cel putin 2 puncte. Dupa cum am zis mai sus, un cerc de raza minima nu trebuie sa contina 2 puncte consecutive ce formeaza un arc de cerc mai mare de {$&pi;$}. Daca cercul nostru nu contine un astfel de arc de cerc, atunci am determinat cercul de raza minima pentru setul de puncte. In caz contrar, notam cu {$D$} si {$E$} aceste 2 puncte. Pentru a micsora lungimea arcului dintre cele doua puncte, translatam centrul cercului pe directia perpendiculara cu segmentul {$DE$}, inspre acest segment pana cand:\r\n## centrul cercului ajunge pe segmentul {$DE$}. In acest moment {$DE$} a devenit diametru in cerc si am determinat cercul de raza minima\r\n## cercul intalneste un alt punct {$F$}. Daca mai exista 2 puncte consecutive pe cerc care se formeaza un arc de cerc cu lungime mai mare de {$&pi;$}, atunci trebuie sa repetam pasul 4. In caz contrar, am ajuns la solutie.\r\n\r\nAlgoritmul este destul de usor de vizualizat, dar destul de dificil de implementat ( trebuie cateva cunostinte de geometrie ). Fiecare pas din algoritm are complexitate {$O(N)$}, dar pasul 4 poate fi repetat de maxim {$N - 2$} ori, ceea ce duce in final la o complexitate {$O(N^2^)$}.\r\n\r\nh2. Algoritm {$O(N)$}\r\n\r\nAlgoritmul acesta construieste cercul in mod incremental, adaugand pe rand puncte in cercul de raza minima.\r\n\r\nNotam cu {$C{~I~}$} cercul de raza minima ce contine in interior punctele din setul {$I$}.\r\n\r\nPentru fiecare punct {$P$}, putem determina in timp constant daca punctul se afla in interiorului cercului {$C{~I~}$}. In cazul in care {$P$} este inclus in {$C{~I~}$}, atunci {$C{~I &#8746; {P}~}$} va fi egal cu {$C{~I~}$}. In caz contrar, trebuie sa schimbam cercul {$C{~I~}$} pentru a cuprinde si acest punct. Cercul ce cuprinde toate punctele va fi evident {$C{~S~}$}, unde {$S$} este setul de puncte dat. Singura problema este cum determinam acel cerc modificat.\r\n\r\nVom demonstra in continuare ca daca punctul {$P$} se afla in exteriorul cercului {$C{~I~}$}, atunci el trebuie sa fie pe circumferinta cercului {$C{~I &#8746; {P}~}$}.\r\n\r\n* {!>minimal-enclosing-circle?figura.png 40%!} Dandu-se doua cercuri de raza {$R{~1~}$} si {$R{~2~}$}, avand {$R{~1~} < R{~2~}$}, atunci intersectia cercului de raza {$R{~2~}$} cu interiorul cercului de raza {$R{~1~}$} formeaza un arc de cerc de lungime mai mica decat {$&pi;$} (cel albastru in poza alaturata). Daca arcul de cerc ar avea o lungime mai mare ca {$&pi;$} atunci acesta ar trebui sa contina 2 puncte diametral opuse, aflate la o distanta de {$2R{~2~}$}, insa in cercul de raza {$R{~1~}$} cea mai mare distanta intre 2 puncte din interiorul sau poate fi maxim {$2R{~1~}$}. Cum {$R{~1~} < R{~2~}$}, acest lucru este imposibil.\r\n* Presupunem prin reducere la absurd ca {$P$} nu apartine circumferintei cercului {$C{~I &#8746; {P}~}$}. Este usor de vazut ca raza cercului {$C{~I~}$} este mai mica ca cea a cercului {$C{~I &#8746; {P}~}$}, deoarece {$C{~I &#8746; {P}~}$} cuprinde un punct care nu este cuprins de {$C{~I~}$}. Daca notam cu {$R{~1~}$} raza cercului {$C{~I~}$} si cu {$R{~2~}$} raza cercului {$C{~I &#8746; {P}~}$}, atunci intersectia cercului {$C{~I &#8746; {P}~}$} cu interiorul cercului {$C{~I~}$} este un arc de cerc de lungime mai mica ca {$&pi;$}.\r\n* Datorita faptului ca {$P$} nu apartine circumferintei cercului {$C{~I &#8746; {P}~}$}, punctele care definesc cercul {$C{~I &#8746; {P}~}$} se afla printre punctele din setul {$I$}. Cum toate aceste puncte se afla in interiorul cercului {$C{~I~}$} si intersectia cercului {$C{~I &#8746; {P}~}$} cu interiorul cercului {$C{~I~}$} este un arc de cerc de lungime mai mica decat {$&pi;$}, punctele care determina cercul {$C{~I &#8746; {P}~}$} trebuie sa se afle pe acest arc de cerc. Astfel avem cel putin 2 puncte consecutive pe circumferinta cercului {$C{~I &#8746; {P}~}$} care formeaza un arc de cerc de lungime mai mare {$&pi;$} (cel rosu in poza alaturata).\r\n* Acest lucru intra in contradictie cu faptul ca cercul are raza minima. Astfel {$P$} trebuie sa se afle pe circumferinta cercului {$C{~I &#8746; {P}~}$}.\r\n\r\nAcum trebuie doar sa calculam cel mai mic cerc care contine punctele din setul I in interior si care are punctul {$P$} pe circumferinta. Vom extinde {$C{~I~}$} adaugand un nou parametru. Astfel notam cu {$C{~I,B~}$} cercul de raza minima ce contine setul {$I$} de puncte in interior si punctele din setul {$B$} pe circumferinta (pot exista si alte puncte pe circumferinta, dar cele din setul {$B$} sunt fortate). Cercul de raza minima care contine toate punctele va fi {$C{~S,&#216;~}$}.\r\n\r\nCalcularea lui {$C{~I,B~}$} se va face in mod recursiv. Mai jos voi prezenta un pseudocod pentru functia respectiva:\r\n\r\n==code(c) |\r\nCerc MINCIRCLE( Set I, Set B )\r\n    Daca |I| == 0 sau |B| >= 3\r\n        returneaza cercul format de punctele din B\r\n    P = punct random apartinand setului I\r\n    C = MINCIRCLE( I - {P}, B )\r\n    Daca P nu este inclus in C\r\n        returneaza MINCIRCLE( I - {P}, B + {P} )\r\n    returneaza C\r\n==\r\n\r\nSingurul lucru care mai ramane de demonstrat este _de ce_ complexitatea este {$O(N)$}.\r\n\r\nPentru {$|B|$} egal cu 3, cercul este foarte usor de determinat in complexitate {$O(1)$}.\r\n\r\nPentru {$|B|$} egal cu 2, complexitatea este evident {$O(N)$}, deoarece calcularea cercului de raza minima pentru setul {$B + {P}$} se rezolva in {$O(1)$}.\r\n\r\nPentru {$|B|$} egal cu 1, notam cu {$T(N)$} numarul mediu de operatii folosite pentru a calcula {$C{~S,B~}$}, unde {$|S|$} este egal cu {$N$}.\r\n\r\nDin setul {$I$} vom scoate un element la fiecare apelare a functiei MINCIRCLE, deci pentru a calcula numarul mediu de operatii pentru {$N$} elemente, adunam numarul mediu de operatii pentru {$N - 1$} elemente ({$T(N - 1)$}). \r\nFiecare punct din {$I$} are probabilitatea {$^1^/{~N~}$} de a fi ales in cadrul functiei. Din aceasta cauza, functia MINCIRCLE{$(I - {P}, B &#8746; {P})$} va fi apelata cu o probabilitate egala cu (numarul de puncte {$P$} care nu apartin cercului {$C{~I - {P},B~}$}) / {$N$}. De asemenea, fiecare apel al acestei functii are complexitatea {$O(N)$}, dupa cum am demonstrat mai sus pentru {$|B|$} egal cu 2.\r\n\r\nAstfel {$T(N)$} respecta relatia: \r\n\r\n* {$T(N) <= T(N - 1) + Probabilitatea( P &notin; C{~I - {P},B~} ) * O(N) + O(1)$}\r\n\r\nDatorita faptului ca cercul de raza minima care cuprinde toate punctele din setul {$I$} este determinat de 2 sau 3 puncte, la fiecare apel al functiei exista maxim 3 puncte pentru care cercul {$C{~I - {P},B~}$} va trebui marit. Astfel probabilitatea ca {$P$} sa nu apartina cercului {$C{~I - {P},B~}$} este egala cu {$^3^/{~N~}$}. Inegalitatea devine:\r\n\r\n* {$T(N) <= T(N - 1) + ^3^/{~N~}*O(N) + O(1)$}\r\nceea ce este echivalent cu\r\n* {$T(N) <= T(N - 1) + O(1)$}\r\n\r\nAstfel complexitatea devine {$O(N)$}. Demonstratia pentru {$|B|$} egal cu 0 se face in mod asemanator.\r\n\r\n\r\nCa o ultima precizare, exista si un algoritm de complexitate {$O(N log N)$} pentru aceasta problema, ce foloseste diagrame voronoi.\r\n\r\nExercitii: \"SPOJ ALIENS\":http://www.spoj.pl/problems/ALIENS/',5433,'public',3684,NULL),('template/preoni-2007/header','template/preoni-2007/header','2007-01-13 23:35:51','2007-06-22 17:01:36','table{margin: 2em 0 0 0; width: 99%; background-image: url(/template/preoni-2007/header?action=download&file=hbk.png); background-repeat: repeat-x; background-position: 0 0;}. |{border: 0px;}. !template/preoni-2007/header/?logo.jpg!:/preoni-2007 |{border: 0px; text-align: right; vertical-align: middle}. !{border: 1px solid silver}preoni-2007?hostway.png!:http://www.hostwaylab.ro/ !{border: 1px solid silver}preoni-2007?ichb.png!:http://www.ichb.ro/ !{border: 1px solid silver}preoni-2007?irealsoft.png!:http://www.irealsoft.ro/ |\r\n',13,'protected',NULL,NULL),('blog/articol-minimal-enclosing-circle','Articol nou: \"Minimal enclosing circle\"','2007-02-01 20:42:20','2007-02-06 20:01:58','A aparut un articol nou despre problema \'Minimal enclosing circle\':minimal-enclosing-circle scris de Bogdan Tataroiu.',1,'public',NULL,NULL),('suffix-array-liniar','Suffix array in O(N)','2007-02-05 11:01:04','2009-02-20 00:39:57','h1. Suffix array in {$O(N)$}\r\n\r\n(Categoria _Structuri de date_, Autor _Cosmin Gheorghe_)\r\n\r\nIn articolul ce urmeaza voi prezenta o metoda de sortare lexicografica a tuturor sufixelor unui sir in timp liniar. \r\n\r\nh2. Obiectiv\r\n\r\nFie {$S$} un sir de caractere pe alfabetul {$[1, N]$}  ({$S$} este o secventa de numere din intervalul {$[1, N]$}). Restrictia de fata pe un alfabet {$[1, N]$} nu este foarte serioasa. Caracterele din sir se pot sorta initial si inlocui cu numere (normalizare).\r\n\r\nDorim obtinerea unui vector care contine toate sufixele sortate lexicografic. Structura rezultata se numeste suffix array si este foarte utila atat in aplicatii practice cat si la concursuri :).\r\n\r\n\r\nExecutia algoritmului va fi explicata pe sirul {$S = \"yabbadabbado\"$}\r\n{$0   1   2   3   4   5   6   7   8   9   10  11$}\r\n{$y   a   b   b   a   d   a   b   b   a    d   o$}\r\n\r\nCautam sa obtinem vectorul {$SS = {1, 6, 4, 9, 3, 8, 2, 7, 5, 10, 11, 0}$} (fiecare sufix este codificat cu pozitia sa de inceput in sir)\r\n\r\nh3. Notatii: \r\n\r\n* numim sufix de tip {$k$}, un sufix a carui pozitie de inceput da restul {$k$} prin impartire la {$3 (0 <= k < 3)$}\r\n* {$S{~i~}$} -> sufixul care incepe pe pozitia {$i$}\r\n* {$S[~k,i~]$} -> sufixul de tip {$k$} care incepe pe pozitia {$i$}\r\n* {$C[~i~]$} -> caracterul de pe pozitia {$i$} din sirul {$S$}\r\n\r\nh2. Algoritm\r\n\r\nh3. Pas {$0$}:\r\n\r\nImpartim sirul in bucati de cate trei astfel:\r\n{$[0 &nbsp;1 &nbsp;2][3 &nbsp;4 &nbsp;5][6 &nbsp;7 &nbsp;8][9 10 11]$}\r\n{$[y &nbsp;a &nbsp;b][b &nbsp;a &nbsp;d][a &nbsp;b &nbsp;b][a &nbsp;d &nbsp;o]$}\r\n\r\n(in functie de restul impartirii la 3 al pozitiilor sufixelor)\r\n\r\nh3. Pas {$1$}:\r\n\r\nSortam sufixele de tip {$1$} si {$2$}\r\n\r\nPentru aceasta formam sirul \r\n{$R = abbadabbado0bbadabbado00$}\r\nale carui caractere sunt tripletele:\r\n{$R = [abb][ada][bba][do0][bba][dab][bad][o00]$} (fiecare grup de {$3$} litere este luat ca un singur caracter)\r\n\r\nMai explicit vom imparti sirul {$S$} in felul urmator:\r\n{$( [C1 C2 C3][C4 C5 C6][C7 C8 C9] ... )$} + {$( [C2 C3 C4][C5 C6 C7][C8 C9 C10] ... )$} (unde {$A$} + {$B$} este concatenarea sirului {$A$} cu sirul {$B$})\r\nPentru {$C{~i~}$} cu {$i$} mai mare ca lungimea sirului {$C{~i~}$} este un caracter minim din punct de vedere lexicografic cu celelalte caractere (in cazul de fata {$0$}).\r\n\r\n\r\nPentru codificarea tripletelor in caractere, se poate folosi radix sort pentru sortarea tripletelor si apoi inlocuirea fiecaruia cu numarul care corespunde cu pozitia lui in sortare (se normalizeaza). Se obtine astfel sirul {$R\'$}.\r\n\r\n\r\nSe observa usor ca prin sortarea sufixelor din {$R\'$} se obtine ordinea relativa a sufixelor din {$S$} de tip {$1$} si {$2$}. Aceasta se face prin aplicarea aceluiasi algoritm recursiv pana la cazuri elementare.\r\n\r\n**Exemplu:**\r\n\r\n{$R\' &nbsp;= { 1, 2, 4, 6, 4, 5, 3, 7 }$}\r\n{$SR\' = { 0, 1, 6, 4, 2, 5, 3, 7 }$}\r\n\r\nh3. Pas {$2$}:\r\n\r\nSortam sufixele de tip {$0$}.\r\n\r\nPentru aceasta ne folosim de rezultatele obtinute la pasul anterior.\r\nOrice sufix de tip {$0$} poate fi considerat ca o pereche (caracter, sufix de tip {$1$}): {$S[~0,i~]$} = [$C{~i~}$] + {$S{~1,i+1~}$}\r\nSe poate folosi radix sort pentru a sorta aceste perechi.\r\n\r\nh3. Pas {$3$}:\r\n\r\nInterclasam cei doi vectori sortati de sufixe. Avem doua cazuri la comparare. Acestea pot fi reduse la compararea sufixelor de tip {$1$} cu sufixe de tip {$2$} astfel: \r\n\r\n# sufix de tip {$0$} ({$S{~i~}$}) cu sufix de tip {$1$} ({$S[~j~]$}) -> (caracter, sufix de tip {$1$}) - (caracter, sufix de tip {$2$}) : ({$C{~i~}$} + {$S{~1,i+1~}$}) - ({$C{~j~}$} + {$S{~2,j+1~}$})\r\n# sufix de tip {$0$} ({$S{~i~}$}) cu sufix de tip {$2$} ({$S{~j~}$}) -> (caracter, caracter, sufix de tip {$2$}) - (caracter, caracter, sufix de tip {$1$}) : ({$C{~i~}$} + {$C{~i+1~}$} + {$S{~2,i+2~}$}) - ({$C{~j~}$} + {$C{~j+1~}$} + {$S{~1,j+2~}$})\r\n\r\nh2. Analiza complexitatii:\r\n\r\nSe observa ca fiecare pas poate fi efectuat in timp liniar. \r\nAlgoritmul se repeta pe un sir de lungime {$2N / 3$}. De aici complexitatea poate fi data de recurenta {$T(N) = T(2N / 3) + O(N) => T(N) = O(N)$}.\r\n',2044,'public',3690,NULL),('newsletter','Newsletter Index','2007-02-09 17:49:55','2007-02-09 17:49:55','h1. Newsletter Index\r\n\r\n== Grep(page=\"newsletter/%\" substr=\"%\") ==',13,'public',NULL,NULL),('blog/articol-suffix-array','Articol nou: \"Suffix array in timp liniar\"','2007-02-06 20:01:39','2007-02-09 18:21:18','A aparut un articol nou despre \'constructia unui suffix array in timp liniar\':suffix-array-liniar scris de Gheorghe Cosmin.',13,'public',NULL,NULL),('winter-challenge-1/11-12/clasament','Clasament winter11-12','2007-02-09 17:50:16','2007-02-09 17:50:16','h1. Clasament ==roundparam(round_id=\"winter11-12\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"winter11-12\")==',1,'round: winter11-12',NULL,NULL),('winter-challenge-1/9-10/clasament','Clasament winter9-10','2007-02-09 17:44:30','2007-02-09 17:44:30','h1. Clasament ==roundparam(round_id=\"winter9-10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"winter9-10\")==',1,'round: winter9-10',NULL,NULL),('clubcampioni/arbori','Arbori','2007-02-08 10:55:54','2007-02-08 10:55:54','*Definitie*\r\n\r\n_Un graf neorientat, conex si aciclic se numeste arbore._\r\n\r\n\r\n*Definitie* \r\n\r\n_Fie G un graf. Numim arbore partial al grafului G un graf partial al lui G care este arbore._\r\n\r\nPrincipalele proprietatii ale arborilor pot fi sintetizate prin urmatoarele afirmatii echivalente:\r\n\r\n* G este un arbore cu _n_ noduri;\r\n* G este un graf conex cu _n_-1 muchii;\r\n* G este un graf aciclic cu _n_-1 muchii;\r\n* G este un graf conex minimal (prin suprimarea unei muchii, graful obtinut devine neconex);\r\n* G este un graf aciclic maximal (prin adauugarea unei muchii, graful obtinut va contine cicluri);\r\n* oricare doua varfuri din G sunt unite printr-un lant unic.\r\n\r\nIn majoritatea problemelor, arborii sunt folositi pentru ierarhizarea informatiilor ce corespund varfurilor arborelui. De aceea au fost introdusi arborii cu radacina.\r\n\r\n\r\n*Definitie*\r\n\r\n_Un arbore cu radacina este o multime finita A de noduri astfel incat:_ \r\n\r\n* _exista un nod numit radacina;_\r\n* _toate celelalte noduri sunt repartizate in _m_ multimi disjuncte A ~1~, A ~2~,.... A ~m~, fiecare multime fiind la randul sau arbore. Intre radacina arborelui si radacinile arborilor A ~1~, A ~2~,.... A ~m~ exista cate o muchie._\r\n\r\nObservam ca un arbore oarecare poate fi transformat intr-un arbore cu radacina prin alegerea arbitrara a unui nod din arbore drept radacina.\r\n\r\n\r\nIn ceea ce priveste arborii, majoritatea termenilor folositi aici deriva din vocabularul arborelui genealogic. Astfel afirmam ca radacina este _tatal_ radacinilor arborilor _A ~1~, A ~2~, ..., A ~m~_, iar acestea din urma sunt _fii_ ai radacinii arborelui. Nodurile cu acelasi tata (parinte) sunt numite _frati_. In mod similar sunt folositi termenii de _bunic, nepot, descendent, ascendent_ etc.\r\n\r\nUn arbore cu radacina poate fi etajat (ierarhizat). Consideram radacina ca aflandu-se pe nivelul 0, descendentii directi ai acesteia (fiii) pe nivelul 1, descendentii directi ai acestora din urma pe nivelul 2 etc. De exemplu, pentru arborele din figura 2, nodul 5 se afla pe nivelul 0, nodurile 1 si 7 pe nivelul 1, nodurile 3, 8, 4, 2 si 9 pe nivelul 2, iar nodul 6 pe nivelul 3.',1507,'public',NULL,NULL),('newsletter/winter-challenge-1','Concursul Winter Challenge','2007-02-09 17:58:33','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\ninfoarena organizeaza un nou concurs pentru tine.\r\nTe invitam sa participi la Winter Challenge!\r\n\nConcursul se va desfasura ...\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Duminica, 11 februarie 2007, orele 14:00 - 18:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPentru informatii detaliate despre concursul\r\nWinter Challenge, acceseaza: \'winter-challenge-1\':winter-challenge-1\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la acest concurs iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te poate aduce mai aproape de varful clasamentului.\r\n==NewsletterRating(username=\"%username%\")==\r\nDespre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Noutati \n\nAvem trei articole noi pentru tine, scrise de membrii\r\ninfoarena.\r\n\np{padding-left: 0.5em;}. * Suffix array in O(N) (Cosmin Gheorghe)\r\n   \'suffix-array-liniar\':suffix-array-liniar\r\n\np{padding-left: 0.5em;}. * Minimal enclosing circle (Bogdan Tataroiu)\r\n   \'minimal-enclosing-circle\':minimal-enclosing-circle\r\n \r\n * Taietura minima in graf cu costuri (Andrei Grigorean)\r\n   \'taietura-minima\':taietura-minima\r\n\nNu uita ca infoarena este un wiki!\r\nPoti chiar tu sa imbunatatesti articolele de mai sus,\r\nsau sa creezi altele noi.\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nGhidul utilizatorului: \'documentatie/pentru-utilizatori\':documentatie/pentru-utilizatori\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nClick pe acest link ca sa nu mai primesti instiintari:\r\n\'account/%username%\':account/%username%\r\n\ninfoarena nu trimite mesaje nesolicitate!\r\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\n\n',13,'protected',NULL,NULL),('utilizator/prostu','Profil Prostu','2006-11-24 21:03:08','2009-05-17 19:16:33','h2. Studii\r\n\r\n* Student la Universitatea Bucuresti, \"Facultatea de Matematica si Informatica\":http://fmi.unibuc.ro/ro/, sectia Informatica\r\n* Absolvent al \"Colegiului National de Informatica {@\"Tudor Vianu\"@}\":http://www.lbi.ro/, Bucuresti\r\n\r\nh2. Distinctii primite\r\n\r\n* 2008 - Premiul I la Olimpiada Nationala de Informatica; medalie de bronz la Olimpiada Central Europeana; tabara in Egipt\r\n* 2007 - Tabara in Cehia\r\n* 2004-2006 - Mentiuni la Olimpiada Nationala de Informatica\r\n\r\nh2. Dusmani pe infoarena\r\n\r\n* == User(user=\"eval\" type=\"normal\") == \r\n* == User(user=\"zuzi\" type=\"normal\") ==',2970,'protected',NULL,NULL),('winter-challenge-1','Concursul Winter Challenge','2007-02-09 17:43:38','2007-02-13 13:16:24','h1. Winter Challenge\r\n\r\n(htabs)*(active) \'*Home*\':winter-challenge-1\r\n* \'Clasele IX-X\':winter-challenge-1/9-10\r\n* \'Clasele XI-XII\':winter-challenge-1/11-12\r\n* \'Rezultate\':winter-challenge-1/rezultate-9-10\r\n\r\n*Concursul s-a incheiat. Felicitari castigatorilor!* \"*Vezi rezultatele*\":winter-challenge-1/rezultate-9-10\r\n\r\n&nbsp;\r\n\r\nOlimpiada de informatica bate la usa. Tu esti pregatit sa-i deschizi? Infoarena te ajuta sa-ti raspunzi la aceasta intrebare lansand o noua provocare (de iarna, de data aceasta). Duminica, 11 februarie, orele 14:00 participa la Winter Challenge si dovedeste ca stii unde-ti sunt cheile.\r\n\r\np{color:red}. *ATENTIE!* Pentru a participa la acest concurs, trebuie sa te inscrii inainte de ora 14^00^, 11 februarie la grupa de varsta corespunzatoare! Nu pot participa elevii care nu se inscriu la grupa lor de varsta inainte de ora 14^00^, 11 februarie!\r\n\r\nInscrierea se face printr-un simplu click. Nu trebuie sa te inregistrezi din nou pe site!\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru.\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti probleme, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"37\" count=\"10\")==\r\n\r\nh2. Prima data pe infoarena?\r\n\r\ninfoarena ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi.\r\n\r\nVezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n',1,'protected',NULL,NULL),('winter-challenge-1/9-10','Concursul Winter Challenge, Clasele IX - X','2007-02-09 17:44:30','2007-02-11 18:05:04','h1. Winter Challenge\r\n\r\n(htabs)* \'*Home*\':winter-challenge-1\r\n*(active) \'Clasele IX-X\':winter-challenge-1/9-10\r\n* \'Clasele XI-XII\':winter-challenge-1/11-12\r\n* \'Rezultate\':winter-challenge-1/rezultate-9-10\r\n\r\n*Concursul s-a incheiat.* \"*Vezi rezultatele*\":winter-challenge-1/rezultate-9-10\r\n\r\n&nbsp;\r\n\r\n== roundregister(round_id=\"winter9-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"winter9-10\" param=\"start_time\")== si dureaza ==roundparam(round_id=\"winter9-10\" param=\"duration\")== ore.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"winter9-10\" score=\"1\") ==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"37\" count=\"10\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse de:\r\n\r\n* ==User(user=\"fireatmyself\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!',13,'protected',NULL,NULL),('unirea-2007/rezultate-9-10','Unirea 2007, Clasament pentru clasele IX-X','2007-01-27 15:37:34','2007-02-09 20:27:04','h1. Unirea 2007\r\n\r\n(htabs)* \'*Home*\':unirea-2007\r\n* \'Clasele IX-X\':unirea-2007/clasele-9-10\r\n* \'Clasele XI-XII\':unirea-2007/clasele-11-12\r\n*(active) \'Rezultate\':unirea-2007/rezultate-11-12\r\n\r\np=. *Clasele IX-X* | \'*Clasele XI-XII*\':unirea-2007/rezultate-11-12\r\n\r\nh2. Clasament IX-X\r\n\r\n== Rankings(rounds=\"unirea9-10\") == \r\n',1,'protected',NULL,NULL),('blog/winter-challenge-1','Concursul Winter Challenge','2007-02-09 19:55:59','2007-02-11 14:20:48','h1. Winter Challenge\r\n\r\nInfoarena organizeaza concursul de informatica Winter Challenge. Acesta va avea loc *Duminica, 11 februarie la ora 14^00^* si dureaza *4h*.\r\n\r\nInformatii se gasesc pe \'pagina concursului\':winter-challenge-1.',13,'public',NULL,NULL),('winter-challenge-1/rezultate-11-12','Winter Challenge, Clasele XI - XII','2007-02-09 18:13:07','2007-02-11 16:57:20','h1. Winter Challenge\r\n\r\n(htabs)* \'*Home*\':winter-challenge-1\r\n* \'Clasele IX-X\':winter-challenge-1/9-10\r\n* \'Clasele XI-XII\':winter-challenge-1/11-12\r\n*(active) \'Rezultate\':winter-challenge-1/rezultate-9-10\r\n\r\np=. \'*Clasele IX-X*\':winter-challenge-1/rezultate-9-10 | *Clasele XI-XII*\r\n\r\nh2. Clasament XI-XII\r\n\r\n== Rankings(rounds=\"winter11-12\") == \r\n',13,'protected',NULL,NULL),('winter-challenge-1/11-12','Concursul Winter Challenge, Clasele XI - XII','2007-02-09 17:50:16','2007-02-11 17:11:32','h1. Winter Challenge\r\n\r\n(htabs)* \'*Home*\':winter-challenge-1\r\n* \'Clasele IX-X\':winter-challenge-1/9-10\r\n*(active) \'Clasele XI-XII\':winter-challenge-1/11-12\r\n* \'Rezultate\':winter-challenge-1/rezultate-9-10\r\n\r\n*Concursul s-a incheiat.* \"*Vezi rezultatele*\":winter-challenge-1/rezultate-11-12\r\n\r\n&nbsp;\r\n\r\n== roundregister(round_id=\"winter11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"winter11-12\" param=\"start_time\")== si dureaza ==roundparam(round_id=\"winter11-12\" param=\"duration\")== ore.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"winter11-12\" score=\"1\") ==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"37\" count=\"10\")==\r\n\r\nh2. Organizatori\r\n\r\n* Subiectele vor fi propuse de:\r\n==User(user=\"maxdamage\" type=\"tiny\")==\r\n==User(user=\"mugurelionut\" type=\"tiny\")==\r\n==User(user=\"fireatmyself\" type=\"tiny\")==\r\n\r\n* Pentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n',13,'protected',NULL,NULL),('winter-challenge-1/rezultate-9-10','Winter Challenge, Clasament pentru clasele IX-X','2007-02-09 18:12:53','2007-02-11 18:05:56','h1. Winter Challenge\r\n\r\n(htabs)* \'*Home*\':winter-challenge-1\r\n* \'Clasele IX-X\':winter-challenge-1/9-10\r\n* \'Clasele XI-XII\':winter-challenge-1/11-12\r\n*(active) \'Rezultate\':winter-challenge-1/rezultate-9-10\r\n\r\np=. *Clasele IX-X* | \'*Clasele XI-XII*\':winter-challenge-1/rezultate-11-12\r\n\r\nh2. Clasament IX-X\r\n\r\n== Rankings(rounds=\"winter9-10\") == \r\n',13,'protected',NULL,NULL),('runda/preoni2007_runda2_9/clasament','Clasament preoni2007_runda2_9','2007-02-13 12:54:19','2007-02-13 12:54:19','h1. Clasament ==roundparam(round_id=\"preoni2007_runda2_9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda2_9\")==',1,'round: preoni2007_runda2_9',NULL,NULL),('preoni-2007/runda-2','Runda 2 preONI 2007','2007-01-15 16:00:23','2007-02-18 14:50:50','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. preONI 2007, Runda 2\r\n\r\n(htabs)*(active) \'Despre...\':preoni-2007/runda-2\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/runda-2/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-2/9\r\n\r\n*Runda 2 s-a incheiat!*\r\n\r\nRunda a inceput Duminica 18 februarie, la ora {*09^00^*} si a durat *4h*. Participantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np{color:red}. *ATENTIE!* Ca sa poata participa la aceasta runda, concurentii au trebuie sa se inscrie *inainte de ora 09^00^* la grupa de varsta corespunzatoare! *Cei care nu s-au inscris* la o grupa de varsta nu li s-a modificat \'rating-ul\':documentatie/rating!\r\n\r\nAceeasi procedura se va urma la fiecare runda preONI. Timp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta&hellip;\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/runda-2/11-12\r\n\r\nPoti vedea solutiile problemelor \'aici\':preoni-2007/runda-2/solutii.\r\n\r\nh2. Clasament Runda 2\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-2/11-12\r\n\r\nh2. Discutii preONI pe forum\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\nh2. Organizatori\r\n\r\n* Subiectele au fost propuse de:\r\n==User(user=\"azotlichid\" type=\"tiny\")==\r\n==User(user=\"domino\" type=\"tiny\")==\r\n==User(user=\"filipb\" type=\"tiny\")==\r\n==User(user=\"greco\" type=\"tiny\")==\r\n\r\n* Pentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n==User(user=\"fluffy\" type=\"tiny\")==\r\n==User(user=\"svalentin\" type=\"tiny\")==\r\n==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('preoni-2007/runda-2/9','preONI 2007, Runda 2, Clasa a 9-a si gimnaziu','2007-02-13 12:54:19','2007-02-18 14:51:57','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda2_9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-2\r\n*(active) \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/runda-2/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-2/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda2_9\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-2/9.\r\n\r\nRunda s-a desfasurat Duminica 18 februarie, la ora {*09^00^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda2_9\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda2_9',NULL,NULL),('preoni-2007/clasament/runda-2/9','Clasament preONI 2007, Runda 2, Clasa a 9-a si gimnaziu','2007-02-13 13:15:58','2007-02-13 13:41:07','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda2_9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-2\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/runda-2/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-2/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-2/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda2_9\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('runda/preoni2007_runda2_10/clasament','Clasament preoni2007_runda2_10','2007-02-13 13:38:20','2007-02-13 13:38:20','h1. Clasament ==roundparam(round_id=\"preoni2007_runda2_10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda2_10\")==',1,'round: preoni2007_runda2_10',NULL,NULL),('preoni-2007/clasament/runda-2/10','Clasament preONI 2007, Runda 2, Clasa a 10-a','2007-02-13 13:41:00','2007-02-13 13:41:00','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda2_10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-2\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/runda-2/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-2/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-2/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/clasament/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-2/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda2_10\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('runda/preoni2007_runda2_1112/clasament','Clasament preoni2007_runda2_1112','2007-02-13 13:48:03','2007-02-13 13:48:03','h1. Clasament ==roundparam(round_id=\"preoni2007_runda2_1112\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda2_1112\")==',1,'round: preoni2007_runda2_1112',NULL,NULL),('preoni-2007/clasament/runda-2/11-12','Clasament preONI 2007, Runda 2, Clasele 11-12','2007-02-13 13:50:18','2007-02-13 13:50:18','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda2_1112\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-2\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/runda-2/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-2/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-2/10\r\n*(active) \'Clasele 11-12\':preoni-2007/clasament/runda-2/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda2_1112\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/clasament/10','Clasament preONI 2007, Clasa a 10-a','2007-02-13 14:04:48','2007-03-07 11:56:26','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Clasament total, Clasa a 10-a\r\n\r\n(htabs)* \'Pe runde...\':preoni-2007/clasament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/clasament/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/11-12\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda1_10|preoni2007_runda2_10|preoni2007_runda3_10|preoni2007_runda4_10\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/clasament/9','Clasament preONI 2007, Clasa a 9-a si gimnaziu','2007-02-13 14:07:17','2007-03-07 11:56:13','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Clasament total, Clasa a 9-a si gimnaziu\r\n\r\n(htabs)* \'Pe runde...\':preoni-2007/clasament\r\n*(active) \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/11-12\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda1_9|preoni2007_runda2_9|preoni2007_runda3_9|preoni2007_runda4_9\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/clasament/11-12','Clasament preONI 2007, Clasele 11-12','2007-02-13 14:08:01','2007-03-07 11:56:39','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Clasament total, Clasele 11-12\r\n\r\n(htabs)* \'Pe runde...\':preoni-2007/clasament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/10\r\n*(active) \'Clasele 11-12\':preoni-2007/clasament/11-12\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda1_1112|preoni2007_runda2_1112|preoni2007_runda3_1112|preoni2007_runda4_1112\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/runda-2/10','preONI 2007, Runda 2, Clasa a 10-a','2007-02-13 13:38:20','2007-02-18 14:52:11','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda2_10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-2\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-2/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/runda-2/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-2/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda2_10\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-2/10.\r\n\r\nRunda s-a desfasurat Duminica 18 februarie, la ora {*09^00^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda2_10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda2_10',NULL,NULL),('preoni-2007/runda-2/11-12','preONI 2007, Runda 2, Clasele 11-12','2007-02-13 13:48:03','2007-02-18 14:52:28','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda2_1112\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-2\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-2/10\r\n*(active) \'Clasele 11-12\':preoni-2007/runda-2/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-2/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda2_1112\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-2/11-12.\r\n\r\nRunda s-a desfasurat Duminica 18 februarie, la ora {*09^00^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda2_1112\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda2_1112',NULL,NULL),('rhide_pe_linux','Rhide_pe_linux','2007-02-15 19:06:05','2007-02-15 19:06:31','nu e gata inca , il termin cand am timp.\r\nSunt doua variante de instalare.\r\nh2. The Easy Way 2\r\nVarianta de a lua pachete precompilate ( metoda cea mai *rapida* )\r\npentru platforme i86 - luati pachetul de \"aici\":http://infoarena.ro/downloads?action=download&file=rhide-1.5.20050823.tbz2\r\nh2. The Hard Way 2\r\ncd $HOME;\r\nexport DIR_INSTALARE=\"rhide\";\r\nmkdir $DIR_INSTALARE;\r\ncd $DIR_INSTALARE;\r\necho \"Install path: $HOME/$DIR_INSTALARE\"\r\nwget http://dev.gentoo.org/~azarah/rhide/setedit-0.5.5.20050828.tar.bz2;\r\nwget http://dev.gentoo.org/~azarah/rhide/tvision-2.10.20050824.tar.bz2;\r\nwget http://dev.gentoo.org/~azarah/rhide/rhide-1.5.20050823.tar.bz2;\r\nwget http://ftp.gnu.org/gnu/gdb/gdb-6.1.1.tar.bz2;\r\necho \"Downloaded files; press enter.\"\r\nread;\r\n\r\ntar -xvjf setedit-0.5.5.20050828.tar.bz2;\r\ntar -xvjf tvision-2.10.20050824.tar.bz2;\r\ntar -xvjf rhide-1.5.20050823.tar.bz2;\r\ntar -xvjf gdb-6.1.1.tar.bz2;\r\n\r\necho \"Unpacked files; press enter.\";\r\nread;\r\n\r\nmv rhide-1.5.20050823 rhide;\r\nmv gdb-6.1.1 gdb;\r\n\r\ncd tvision/ ;\r\n./configure --prefix=\"/usr\" --x-include=\"/usr/include\" --x-lib=\"/usr/lib\" --fhs --without-dynamic ;\r\nmake;\r\n\r\necho \"Tvision installed; press enter.\";\r\nread;\r\n\r\ncd ..;\r\ncd setedit;\r\n./configure --prefix=\"/usr\" --fhs --libset --static --without-mp3 --without-mixer --without-migdb;\r\nmake;\r\n\r\necho \"Setedit installed; press enter.\";\r\nread;\r\n\r\nexport RHIDESRC=\"$HOME/$DIR_INSTALARE/rhide\";\r\nexport SETSRC=\"$HOME/$DIR_INSTALARE/setedit\";\r\nexport SETOBJ=\"$HOME/$DIR_INSTALARE/setedit/makes\";\r\nexport TVSRC=\"$HOME/$DIR_INSTALARE/tvision\";\r\nexport TVOBJ=\"$HOME/$DIR_INSTALARE/tvision/makes\";\r\nexport GDB_SRC=\"$HOME/$DIR_INSTALARE/gdb\";\r\nexport GDB_OBJ=\"$HOME/$DIR_INSTALARE/gdb\";\r\n\r\necho \"$RHIDESRC\";\r\necho \"$SETSRC\";\r\necho \"$SETOBJ\";\r\necho \"$TVSRC\";\r\necho \"$TVOBJ\";\r\necho \"$GDB_SRC\";\r\necho \"$GDB_OBJ\";\r\n\r\necho \"Are these ok?\";\r\nread;\r\n\r\ncd ..;\r\ncd rhide;\r\n./configure;\r\nmake;\r\nmake install;',332,'public',NULL,NULL),('newsletter/preoni-2007-runda-2','preONI 2007, Runda #2','2007-02-16 11:30:34','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nTe invitam la runda #2 a concursului preONI, concursul cu premii\r\ncare te pregateste pentru Olimpiada Nationala de Informatica.\r\n\nRunda #2 a concursului va avea loc ...\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Duminica, 18 februarie 2007, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPagina rundei: \'preoni-2007/runda-2\':preoni-2007/runda-2\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la aceasta runda iti va afecata rating-ul pe infoarena.\r\nO prestatie buna te poate aduce mai aproape te varful clasamentului.\r\n==NewsletterRating(username=\"%username%\")==\r\nRating-ul este un indicator al performantei tale in conditii de\r\nconcurs. Despre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Noutati la infoarena \n\nAvem trei articole noi pentru tine, scrise de membrii\r\ninfoarena.\r\n\np{padding-left: 0.5em;}. * Suffix array in O(N) (Cosmin Gheorghe)\r\n   \'suffix-array-liniar\':suffix-array-liniar\r\n\np{padding-left: 0.5em;}. * Minimal enclosing circle (Bogdan Tataroiu)\r\n   \'minimal-enclosing-circle\':minimal-enclosing-circle\r\n \r\n * Taietura minima in graf cu costuri (Andrei Grigorean)\r\n   \'taietura-minima\':taietura-minima\r\n\nNu uita ca infoarena este un wiki!\r\nPoti chiar tu sa imbunatatesti articolele de mai sus,\r\nsau sa creezi altele noi.\r\n\nh2.  Despre preONI \n\npreONI, concursul de marca al comunitatii infoarena, este dedicat\r\nelevilor de liceu ce se pregatesc pentru ONI (Olimpiada Nationala\r\nde Informatica).\r\n\nConcursul este impartit in 3 grupe: clasa a IX-a si gimnaziu, clasa\r\na X-a si clasele XI-XII. Se organizeaza 4 runde online de calificare.\r\nIn urma acestora, cei mai buni de la fiecare grupa sunt invitati la\r\no runda finala.\r\n\nIn cadrul unei runde, vei avea de rezolvat 3 probleme in 4h.\r\nCastigatorii rundei finale sunt premiati cu bani si/sau obiecte.\r\n\nPe pagina concursului ( \'preoni-2007\':preoni-2007 ) vei gasi\r\ninformatii despre cum participi, cine propune probleme, premii si\r\nsponsori, regulamentul concursului samd.\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nGhidul utilizatorului: \'documentatie/pentru-utilizatori\':documentatie/pentru-utilizatori\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('planificare/sedinta_20070507','Sedinta 2007-05-07','2007-04-26 18:05:59','2007-05-15 09:06:58','h1. Sedinta 2007-05-07\r\n\r\n_ora 19:00, locatie: Piranha_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Mircea Pasoi\r\n* Diaconu Adrian\r\n* Silviu Ganceanu\r\n* Valentin Stanciu\r\n* Adrian Vladu\r\n* Tiberiu Florea\r\n\r\nh2. Invitati speciali\r\n\r\n* -Sergiu Strat-\r\n* Claudia Cardei\r\n* Diana Pastor\r\n* -??? - studenta la PR, invitata de Vali- --> Teo nu e interesata si nici timp nu prea are\r\n\r\nh2. Agenda\r\n\r\n# preONI 2007\r\n## grafic\r\n## plan cheltuieli\r\n## sponsori\r\n### prezentare, dosar\r\n### hit list\r\n# Fonduri\r\n## Proiectul 2%\r\n## irealsoft\r\n## Retea sponsori\r\n# Asociatie\r\n## cont bancar\r\n## stampila\r\n# Comunitate infoarena\r\n## Cei cu 100 sa poata vedea sursele la problema respectiva => mai multa responsabilitate\r\n## \"Implica-te\". Niste idei:\r\n### Directionam cum trebuie energia comunitatii?\r\n### Unde mai avem nevoie de ajutor?\r\n### Tabara de training pe PHP + alte tehnlogii folosite in infoarena cu tickete ca aplicatii la vara? :D\r\n# infoarena software\r\n## Tag-uri reloaded\r\n### Argument 1: Clasament per tag; Exemplu: daca sunt la gimnaziu vreau sa fiu primu la sectiune de \"elementare\"\r\n### Argument 2: Gasesti rapid probleme de o anumita dificultate (fie ea si aproximativa)\r\n## ultimate data grids\r\n\r\nh2. Rezolutii adoptate\r\n\r\nh3. Despre preONI \r\n\r\n* desfasurare in perioada 8, 9, 10 iunie\r\n* suntem nevoiti - din cauza sesiunii - sa il facem la Bucuresti. Cristi il intreaba pe Emil daca ne poate ajuta in Bucuresti.\r\n* buget\r\n** 1800 lei: premii\r\n** (50 lei / zi / persoana) 25 * 50 * 2 = 2500 lei: cazare si mancare 25 persoane, restul pana la 50 stau in Bucuresti\r\n** plata propunatori: ~5000 lei\r\n** subtotal: 9300 lei\r\n** + marja: 30%\r\n** TOTAL: 12090 lei (adica 3619 EUR)\r\n** impreuna cu alte cheltuieli despre care nu stim inca (transport, materiale promotionale): *avem nevoie de 4000 EUR*\r\n* Silviu vorbeste la ICHB: intreaba de laboratoare info, cazare si mancare. Pentru cazare si mancare suntem dispusi sa dam bani.\r\n%{color: red}*UPDATE*%:\r\nLaboratoare: OK (fara bani)\r\nMancare: Se poate rezolva. Voi afla pretul concret saptamana viitoare.\r\nCazare: Ali Yuksel: \"Cate locuri sunt disponibile pe toate vi le dau la pretul pietii\" (pretul pietii = ~ca la Nichita)\r\nBonus: Transport cu microbuzele liceului (Nu stiu daca moca sau nu).\r\nConditii: Domnul Ali mi-a spus sa venim cu detalii din timp, dupa Infomatrix, cand va fi mai liber (adica pe la sfarsitul saptamanii viitoare). Toate treburile de mai sus (exceptand laboratoarele) trebuie sa treaca si prin aprobarile scolii despre care Ali zice ca nu vor fi probleme. Ali ne sugereaza sa punem finala dupa ce se termina scoala (15-17 iunie) ca atunci vor fi mai multe sanse ca internatul sa fie liber si vom avea la dispozitie toate resursele scolii.\r\n* Vali vorbeste la emag\r\n* Silviu face forward la email-urile introductive catre Diana si Vali\r\n* Diana si Claudia intreaba despre cazare, mancare si conditii la:\r\n** -Nichita Stanescu- -> ne-au rejectat din prima, au zis ca nu se poate\r\n** -Iulia Hasdeu- -> nu au locuri in perioada aia\r\n** Hoteluri de 2 stele\r\n%{color: red}*UPDATE*%:\r\n*** La \"Colegiul Tehnic Media\" ne primesc in internat cu 25lei/zi/persoana care includ cazare si 3 mese pe zi. Au zi ca putem folosi si laboratoarele. Mai trebuie sa vedem care sunt condtiile de cazare si in laburi. Camerele erau de 4 persoane.\r\n*** La Scoala gen. nr 17 \"Pia Bratianu\" au cazare pentru 15lei/zi/persoana dar nu servesc masa in weekend. Camerele sunt cam de 10-11 persoane, dar nu sunt rele. E un singur lab si din cate imi aduc eu aminte, calculatoarele erau cam infecte si putine. Dar ma gandesc ca daca turcii n-au locuri in internat, cazarea se poate face aici, iar transportul intre cele doua scolii cu microbuzele alea.\r\n\r\nh3. Despre fonduri\r\n\r\n* prezentare preONI: Silviu si Cristi\r\n* Copy sponsor network si 2%: Silviu si Cristi\r\n* Diana si Claudia vor primi prezentarea infoarena & preONI pana luni 14 mai\r\n* Cristi discuta cu Fluf despre datorie\r\n\r\nh3. Asociatia infoarena\r\n\r\n* Open Source: *Toata lumea cu punctaj max la o problema poate vedea sursele altora de la aceeasi problema.*  (s-a votat 100% - din cei prezenti - pentru)\r\n\r\nh3. infoarena software\r\n\r\n* Coding camp pe 26-27 mai: Cristi, Fluf, Mircea (nu stie sigur), Adi (1 zi), Vladu (daca e in Bucuresti), Ganci (maybe), Vali (s-ar putea)\r\n* Coding camp cu prioritati: tag-uri, datagrids, unattended evals\r\n',15,'public',NULL,NULL),('runda/preoni2007_runda2_10','runda/preoni2007_runda2_10','2007-02-16 20:29:03','2007-02-16 20:29:03','Scrie aici despre runda/preoni2007_runda2_10',5748,'public',NULL,NULL),('runda/preoni2007_runda2_1112','runda/preoni2007_runda2_1112','2007-02-17 12:37:26','2007-02-17 12:37:26','Scrie aici despre runda/preoni2007_runda2_1112',1002,'public',NULL,NULL),('planificare/sedinta-20061101','Sedinta 2006-11-01','2007-02-17 15:15:45','2007-02-17 15:27:05','h1. Sedinta 2006-11-01\r\n\r\n_ora 20:00, locatia Cafenescu_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Silviu Ganceanu\r\n* Mircea Pasoi\r\n* Valentin Stanciu\r\n\r\nh2. Agenda\r\n\r\n* 1. preONI 2007\r\n* 2. _hei-rup_ in week-end\r\n* 3. deadlines pentru infoarena 2.0\r\n* 4. asociatia info-arena\r\n* 5. preONI booklet\r\n\r\nh2. Notite\r\n\r\nh3. 1. preONI 2007\r\n\r\n* incepe aproximativ pe 10 ianuarie 2007\r\n* vom avea 6 runde de calificare on-line, cate o runda la 2 saptamani\r\n* pe ~20 martie 2007 vom fi terminat cu rundele on-line\r\n* undeva prin aprilie facem finala on-site\r\n* *Sponsori*\r\n** Cristi va face o prezentare a ofertei info-arena pana pe 15 nov.\r\n** renuntam la booklet in favoarea unei prezentari destepte\r\n** sponsori potentiali pentru care avem oameni de legatura: Intel, Microsoft, Softwin, IP Devel, ORACLE, UPB\r\n** sponsori potentiali: Totalsoft, UNIBUC ...\r\n** dupa 15 nov. luam legatura cu sponsorii\r\n** voluntari pentru cautare/intelegeri cu sponsori:\r\n*** Cristi\r\n*** Silviu\r\n*** Mircea\r\n** formatul ideal al concursului este de 3 grupe x 3 probleme\r\n** costul _orientativ_ al unei probleme: intre 35 si 50 EUR\r\n\r\nh3. 2. _hei-rup_ in week-end\r\n\r\n* organizam un hei-rup pentru infoarena 2.0 intr-un laborator de informatica pus la dispozitie de ICHB\r\n* se desfasoare pe 4 si 5 nov. 2006\r\n* in noaptea de sambata spre duminica vom dormi la Mircea. Mircea trebuie sa ne dea un raspuns sigur\r\n* Cristi va discuta cu Rax/Greco (maine, 2 nov.) pentru a stabili cum vom intra in posesia cheii\r\n* din cadrul ICHB, Silviu a obtinut acordul lui Ali\r\n* voluntari confirmati la acest hei-rup:\r\n** Cristi\r\n** Leo\r\n** Mircea (lipseste sambata dimineata; vine sambata seara)\r\n** Vali (vine duminica)\r\n** Marinescu Alex (program limitat)\r\n* voluntari ne-confirmati:\r\n** Adi\r\n** Greco\r\n** _Sobolanu_\r\n** Malex\r\n** Cristi Gologan\r\n* vom veni cu laptop-urile personale. Nu stim ce gasim acolo. \r\n* Vali cunoaste setarile/echipamentele de retea de acolo\r\n* nu ne putem baza pe legatura la internet de acolo intrucat e limitata. Cristi va aduce un Zapp pentru back-up\r\n\r\nh3. 3. deadlines pentru infoarena 2.0 (noul website)\r\n\r\n* 2006-12-01: versiune online functionala, gata pentru teste real-life\r\n* 2007-01-01: versiune stabila\r\n* in functie de stadiul in care ne aflam, noua versiune ar putea fi testata la concursul Stelele Informaticii de la sfarsitul lunii noiembrie\r\n\r\nh3. 4. asociatia infoarena\r\n\r\n_Nu s-a mai discutat despre asociatie (a inceput meciul :P ...)_\r\n\r\nh3. 5. preONI booklet\r\n\r\nAm renuntat la ideea de booklet intrucat o prezentare scurta si condensata serveste mai bine scopului nostru: acela de a transmite mesajul/oferta sponsorilor.\r\n',13,'public',NULL,NULL),('planificare/sedinta_20061121','Sedinta 2006-11-21','2007-02-17 15:28:21','2007-02-17 15:28:21','h1. Sedinta 2006-11-21\r\n\r\n_ora 18:00, locatia ICHB_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Silviu Ganceanu\r\n* Mircea Pasoi\r\n* Diaconu Adrian\r\n\r\nh2. Agenda\r\n\r\n* 1. infoarena 2.0\r\n\r\nh2. Notite\r\n\r\nh3. 1. infoarena 2.0\r\n\r\n* Mircea: 7 articole pana pe 24\r\n* Mircea: ultimele 3 news-uri\r\n* news-urile vechi nu ne intereseaza deocamdata (in 2.0 norris)\r\n* Mircea: regulament / despre / evaluator / echipa\r\n* Fluffy: #104: arde template de user\r\n* Mircea intreaba pe mama lui daca face asociatie. Avem deja statut.\r\n',13,'public',NULL,NULL),('planificare/sedinta_20061214','Sedinta 2006-12-14','2007-02-17 15:30:55','2007-02-17 15:30:55','h1. Sedinta 2006-12-14\r\n\r\n_ora 20:00, locatia Carrefour Grozavesti_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Silviu Ganceanu\r\n* Mircea Pasoi\r\n* Diaconu Adrian\r\n* Stanciu Valentin\r\n\r\nh2. Agenda\r\n\r\n* 1. infoarena 2.1\r\n* 2. asociatie\r\n\r\nh2. Notite\r\n\r\n* Se vor baga la prasit:\r\n** Cristian George Strat: fara numar\r\n** Mircea Pasoi: fara numar\r\n** Stanciu Valentin: programare, instruire recruti\r\n** Ganceanu Silviu: praseala la documentatie\r\n** Crestez Leonard: fara numar\r\n** Adrian Diaconu: invata PHP. Il ajuta Valentin sa-si dea drumul.\r\n* asociatie\r\n** mergem la notar luni la 12\r\n',13,'public',NULL,NULL),('planificare/sedinta_20070104','Sedinta 2007-01-04','2007-02-17 15:33:12','2007-02-17 15:33:12','h1. Sedinta 2007-01-04\r\n\r\n_ora 20:00, locatia Carrefour Grozavesti_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Mircea Pasoi\r\n* Diaconu Adrian\r\n\r\nh2. Agenda\r\n\r\n* 1. infoarena 2.1\r\n* 2. preONI 2007\r\n* 3. Unirea 2007\r\n* 4. Acte\r\n\r\nh2. Notite\r\n\r\n* 1. infoarena 2.1\r\n** Ne trebuie un deadline de la Dan Burzo\r\n** Ce ne trebuie sa facem concursuri? Asigura-te ca sunt tichete\r\n* 2. preONI 2007:\r\n** Mircea e sef de probleme la preONI 2007\r\n** Facem 4 runde de calificare si una finala\r\n** Prima runda este pe 20 ianuarie 2007\r\n* 3. Unirea 2007\r\n** Facem Unirea 2007 pe infoarena. Mircea face rost de probleme.\r\n* 4. Acte\r\n** Vineri (pe 5 jan) la ora 13:00 ne intalnim la Piata Natiunilor Unite ca sa bagam un notar\r\n',13,'public',NULL,NULL),('planificare/sedinta_20070215','Sedinta 2007-02-15','2007-02-17 15:35:30','2007-02-17 15:35:30','h1. Sedinta 2007-02-15\r\n\r\n_ora 21:00, locatia Carrefour Grozavesti_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Mircea Pasoi\r\n* Diaconu Adrian\r\n\r\nh2. Agenda\r\n\r\n* 1. Acte Asociatie. Ne intalnim vineri?\r\n* 2. infoarena code repository\r\n** 2.1 hei-rup?\r\n** 2.2 politica de update pe server-ul live. Branch de fall-back.\r\n** 2.3 reorganizare tichete\r\n** 2.4 -tichete assigned cu deadline.-\r\n** 2.5 -roadmap detaliat pe saptamana, in wiki.-\r\n* 3. Mai multe despre preONI 2007\r\n** 3.1 Premii, Sponsori\r\n** 3.2 Bani pentru propunatori\r\n** 3.3 Finala\r\n* 4. Posibile proiecte cu bani. Cum consumam fonduri?\r\n** 4.1 Tichetu\' si berea, pentru new people.\r\n** 4.2 Infoarena development love day.\r\n\r\nh2. Notite\r\n\r\n* Silviu poate sa vina maine dupa examen la o intalnire de acte. Dupa aceea va pleca acasa si se intoarce dupa vacanta.\r\n* 2.1: \r\n* 2.2: facem branch de fallback la care facem revert imediat cum constatam bug. In plus, cu 3 zile inainte de concurs se lucreaza numai cu branch stabil pe live. Regulat vom pune tag-uri pe cele mai noi revizii stabile.\r\n* *ne trebuie un installer pentru windows*\r\n* o idee de scazut nivelul de intrare: facem screencast-uri cu instalare & hacking\r\n* infoarena love day: o zi \"foarte anuntata\" public in care core development team se intalneste, si, filmati de un webcam public codeaza la infoarena. Este ziua optima in care se pot baga in seama noi coders pentru ca ii initiem.\r\n* un tichet = o bere :)\r\n',13,'public',NULL,NULL),('planificare/karate-kids','Karate Kids Coding Camp','2007-02-17 15:38:19','2007-02-17 15:47:10','h1. Karate Kids Coding Camp\r\n\r\nProiectul \'infoarena 2.0\':planificare/infoarena-2 se apropie de lansarea oficiala. Tehnic, site-ul este functional insa *ne lipseste continutul*! Mai exact, continutul importat din info-arena 1 (probleme, evaluatoare, articole, pagini wiki) trebuie organizat, clasificat, testat, imbunatatit, pieptanat si pupat.\r\n\r\nEste si de programat (bugfixes) insa grosul de munca vizeaza continutul noului website. Din acest motiv *avem nevoie de cat mai multe minti si maini*!\r\n\r\nh2. Mai exact, ce-o sa facem?\r\n\r\nVezi \'planificare infoarena 2\':planificare/infoarena-2 precum si \'lista de tichete\':http://hackers.devnet.ro/report/3 pentru acest milestone.\r\n\r\nPrelucrarea/organizarea/testarea samd. continutului info-arena 1 inseamna cam asa:\r\n\r\n* infoarena 2.0 are la baza un sistem wiki. Articolele despre info (luate de pe _vechiul_ info.devnet.ro) trebuie impartite pe categorii\r\n* link-uri intre probleme, articole, autori, concursuri, utilizatori\r\n* conversie plain text / html in textile (wiki markup)\r\n* testarea problemelor pe noul evaluator\r\n* regulament\r\n* ajutor / ghid de folosire\r\n* re-organizarea forum-ului\r\n\r\nIn paralel cu transformarea continutului vom repara bug-urile cunoscute sau cele care ies la suprafata.\r\n\r\nh2. Cand?\r\n\r\nIn week-end-ul *11-12 nov. 2006*.\r\n\r\nIncepem Sambata dimineata la ora 9 si terminam Duminica noaptea. Nu toti vom veni de la inceput pana la sfarsit.\r\n\r\nh2. Unde?\r\n\r\nIn laboratoarele de info ale \'ICHB\':http://www.ichb.ro (zona Dristor).\r\n\r\nLaboratoarele au calculatoare cu linux/windows si sunt conectate la internet. Daca iti poti aduce un laptop, cu atat mai bine.\r\n\r\nh2. Cine vine?\r\n\r\nDaca vii la KKCC, inscrie-te in lista de mai jos. Nu uita sa specifici cand poti veni si cat vei sta.\r\n\r\n* Cristian George Strat, fara numar\r\n* Cristez Leonard, the whole nine yards\r\n* Mircea Pasoi, fara numar\r\n* Ganceanu Silviu, FIXME\r\n* Vladu Adrian, ?\r\n* Adrian Diaconu, ?\r\n\r\nVor participa _virtual_ (de acasa):\r\n\r\n* Filip Buruiana\r\n* Daniel Pasaila\r\n\r\nh2. Quick Facts\r\n\r\n* Fiecare isi aduce pachet / bani de mancare\r\n* In noaptea de Sambata spre Duminica *probabil* ca putem dormi la Mircea. *CONFIRMED*\r\n* Cu cat poti sta (lucra) mai mult, cu atat mai bine! Totusi, daca nu poti chiar de la inceput si pana la sfarsit, nu e bai. Chiar si cateva ore de munca sunt de mare folos.\r\n* Ce trebuie facut a fost deja planificat si impartit: \'vezi aici\':http://hackers.devnet.ro/report/3\r\n* Adu-ti casti!\r\n\r\nh2. To Do\r\n\r\n_(chestii de pregatit ca sa iasa treaba)_\r\n\r\n* *Ia cheia de la laborator* ( *Mircea:* Got the key! )\r\n',13,'public',NULL,NULL),('planificare/camp-noname','Coding Camp Noname','2007-02-17 19:41:58','2007-02-17 19:41:58','h1. Coding Camp Noname\r\n\r\n_(pagina creata pentru arhiva / din considerente istorice)_\r\n\r\nCoding camp de 2 zile si gazduit in laboratoarele ICHB cu scopul de a continua proiectul infoarena v2.\r\n\r\nOrganizarea evenimentului s-a facut \'intr-o sedinta la Cafenescu\':planificare/sedinta-20061101.\r\n\r\nSe cheama \'\'Noname\'\' pentru ca nu i-am dat nume.',13,'public',NULL,NULL),('planificare/camp-chuckie','Coding Camp Chuckie','2007-02-17 19:46:22','2009-07-04 12:29:36','h1. Coding Camp Chuckie\r\n\r\n_(pagina creata pentru arhiva / din considerente istorice)_\r\n\r\nCoding camp organizat la Valenii de Munte (Stanciu Valentin) cu scopul de a porni proiectul infoarena v2.\r\n\r\nOrganizarea s-a facut \'direct pe wiki-ul infoarena.devnet.ro\':http://infoarena.devnet.ro/wiki/index.php/Coding_Camp_2006.\r\n\r\n\'Iata si cateva poze (multumim, Vali!) \':http://picasaweb.google.com/valentin.stanciu/IACodingCamp.',75,'public',NULL,NULL),('mozaic','Mozaic','2007-02-18 11:27:26','2007-07-22 11:11:32','h1. Mozaic\r\n\r\n== Gallery(page=\"%\" file=\"avatar\" display_entries=\"48\")==',58,'public',NULL,NULL),('preoni-2007/clasament','Clasament preONI 2007','2007-01-15 15:59:02','2007-03-07 11:55:50','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Clasament \r\n\r\n(htabs)*(active) \'Pe runde...\':preoni-2007/clasament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/11-12\r\n\r\nh2. Clasament Runda 1\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-1/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-1/11-12\r\n\r\nh2. Clasament Runda 2\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-2/11-12\r\n\r\nh2. Clasament Runda 3\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-3/11-12\r\n\r\nh2. Clasament Runda 4\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-4/11-12\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('runda/preoni2007_runda3_9/clasament','Clasament preoni2007_runda3_9','2007-02-18 14:28:21','2007-02-18 14:28:21','h1. Clasament ==roundparam(round_id=\"preoni2007_runda3_9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda3_9\")==',1,'round: preoni2007_runda3_9',NULL,NULL),('preoni-2007/runda-3/9','preONI 2007, Runda 3, Clasa a 9-a si gimnaziu','2007-02-18 14:28:21','2007-03-07 12:23:32','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda3_9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-3\r\n*(active) \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/runda-3/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-3/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda3_9\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-3/9.\r\n\r\nRunda s-a desfasurat *Duminica 4 martie*, la ora {*09^00^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda3_9\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda3_9',NULL,NULL),('preoni-2007/runda-3/10','preONI 2007, Runda 3, Clasa a 10-a','2007-02-18 14:30:53','2007-03-07 12:23:46','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda3_10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-3\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-3/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/runda-3/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-3/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda3_10\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-3/10.\r\n\r\nRunda s-a desfasurat *Duminica 4 martie*, la ora {*09^00^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda3_10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda3_10',NULL,NULL),('runda/preoni2007_runda3_10/clasament','Clasament preoni2007_runda3_10','2007-02-18 14:30:53','2007-02-18 14:30:53','h1. Clasament ==roundparam(round_id=\"preoni2007_runda3_10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda3_10\")==',1,'round: preoni2007_runda3_10',NULL,NULL),('runda/preoni2007_runda3_1112/clasament','Clasament preoni2007_runda3_1112','2007-02-18 14:33:26','2007-02-18 14:33:26','h1. Clasament ==roundparam(round_id=\"preoni2007_runda3_1112\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda3_1112\")==',1,'round: preoni2007_runda3_1112',NULL,NULL),('preoni-2007/runda-3/11-12','preONI 2007, Runda 3, Clasele 11-12','2007-02-18 14:33:26','2007-03-07 12:23:58','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda3_1112\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-3\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-3/10\r\n*(active) \'Clasele 11-12\':preoni-2007/runda-3/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-3/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda3_1112\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-3/11-12.\r\n\r\nRunda s-a desfasurat *Duminica 4 martie*, la ora {*09^00^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda3_1112\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda3_1112',NULL,NULL),('preoni-2007/clasament/runda-3/9','Clasament preONI 2007, Runda 3, Clasa a 9-a si gimnaziu','2007-02-18 14:43:06','2007-02-18 14:43:06','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda3_9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-3\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/runda-3/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-3/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasa a 9-a si gimnaziu\':preoani-2007/clasament/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-3/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda3_9\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/clasament/runda-3/10','Clasament preONI 2007, Runda 3, Clasa a 10-a','2007-02-18 14:43:57','2007-02-18 14:43:57','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda3_10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-3\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/runda-3/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-3/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-3/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/clasament/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-3/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda3_10\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/clasament/runda-3/11-12','Clasament preONI 2007, Runda 3, Clasele 11-12','2007-02-18 14:44:56','2007-02-18 14:44:56','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda3_1112\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-3\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/runda-3/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-3/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-3/10\r\n*(active) \'Clasele 11-12\':preoni-2007/clasament/runda-3/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda3_1112\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('documentatie/evaluator','Evaluatorul infoarena','2006-11-27 05:18:35','2009-05-18 20:39:12','h1. Evaluatorul infoarena\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\n... este responsabil de evaluarea solutiilor trimise de utilizator.\r\n\r\nh2. Cum se evalueaza o problema\r\n\r\nMai intai, codul sursa trimis de concurent se compileaza (vezi tabelul de mai jos). Apoi, solutia se _evalueaza_: se ruleaza programul compilat pentru diferite date de intrare (teste). In urma rularii, un program specializat decide daca raspunsul dat de solutia concurentului este corect si acord un punctaj pe masura.\r\n\r\nFiecare program compilat are dreptul de a rula doar un anumit interval de timp (specificat in descrierea problemei). in cazul in care timpul de executie este depasit, programul este terminat automat de sistem. Analog, se pot impune si limite de memorie.\r\n\r\nEvaluarea se face intr-un mediu restrictionat. Programele compilate pot citi/scrie fisiere doar din/in directorul curent si nu au acces la unele functii sistem.\r\n\r\nh2. Compilatoare folosite\r\n\r\nIata *lista oficiala* de compilatoare folosite de evaluatorul infoarena:\r\n\r\ntable{width:50%}. |_. Compilator si versiune|_. Comanda de compilare |_. Extensie implicita |\r\n| GNU GCC 4.2.4 | $gcc -Wall -O2 -static &hellip; -lm$ | c |\r\n| GNU G++ 4.2.4 | $g++ -Wall -O2 -static &hellip; -lm$ | cpp |\r\n| FreePascal Compiler 2.2.0 | $fpc -O2 -Xs &hellip;$               | pas |\r\n\r\nh2. Configuratia sistemului de evaluare\r\n\r\nEvaluatorul ruleaza pe un calculator dedicat, oferit de ==User(user=\"fluffy\")==. (Multumim, Leo!)\r\n\r\n* Sistem de operare: Debian stable(sarge)\r\n* Procesor: Pentium IV, $2.0 GHz$\r\n* Memorie: $512 MB RAM$\r\n\r\nh2. Gazduire !>documentatie/evaluator?hqn.png!\r\n\r\nEvaluatorul infoarena este gazduit cu placere de catre \"HQN (High Quality Networks)\":http://hqn.ro/.\r\n\r\nh2. Mesaje de evaluare\r\n\r\nPentru cei care nu sunt familiari cu sistemele unix sau sunt incepatori in programare, multe dintre mesajele evaluatorului pot parea oarecum criptice.\r\n\r\n* Eroare de sistem: Daca ai obtinut aceast mesaj te rugam sa ne contactezi, preferabil pe \'forum\':forum. Te rugam sa mentionezi si id-ul job-ului.\r\n* OK: Totul a functionat perfect.\r\n* Memory limit exceeded: Ai depasit limita de memorie. Majoritatea problemelor au o limita de 64 de mega, pe care noi o consideram destul de generoasa.\r\n* Time limit exceeded: Programul tau a depasit limita de timp. Asta inseamna ca programul tau nu este destul de rapid.\r\n* Wall time limit exceeded: Evaluarea a durat prea mult si a fost abandonata. Evaluatorul infoarena masoara doar timpul folosit de programul tau pentru a determina daca iti da TLE, dar exista si o limita fata de \"ceasul de perete\". Acest mesaj poti sa il obtii daca faci sleep, scanf de la stdin si alte functii care stau degeaba fara sa consume efectiv procesorul.\r\n* Blocked system call: Ai accesat o functie la care nu ai access. Nu ar trebui sa primesti aceasta functie decat daca incerci explicit sa faci ceva interzis.\r\n* Killed by signal: Cea mai frecventa eroare cand ai un bug in program. Cand un program incalca anumite conventii in UNIX acel program primeste un \"semnal\" care de cele mai multe ori il opreste. Cateva semnale comune:\r\n** 11(SIGSEGV): Segmentation fault. Asta in 99% din cazuri inseamna ca ai probleme cu accesul la memorie. Ai iesit din limitele unui vector, ai facut stack overflow, etc.\r\n** 8(SIGFPE): Floating point error. Cauzat cel mai frecvent de impartiri la 0.\r\n* Non-zero exit status: Programul tau a returnat o valoare diferita de 0. Cel mai probabil ai uitat return 0; sau ceva similar. Poti primi acest mesaj si in loc de mesajul \"Killed by signal\": verifica si dupa erorile mentionate deasupra.\r\n\r\nEvaluatoarele problemelor iti vor da si ele un mesaj scurt, cel mai frecvent ceva de genul \"OK\" sau \"Wrong Answer\", dar unii propunatorii au umor :).\r\n\r\nh2. Troubleshooting\r\n\r\nPentru programatorii in Borland C/Pascal este important de tinut minte ca evaluatorul infoarena este un mediu *foarte* diferit fata de dos. Cateva erori comune si cum pot fi rezolvate\r\n\r\n* Pe infoarena se face I/O din fisiere, nu de la stdin, stdout. Daca faci scanf de la stdin vezi obtine cel mai probabil \"Wall time limit exceeded\" (vezi mai sus) iar daca faci printf la stdout rezultatul tau va fi ignorat.\r\n* tipul int din GCC este pe 32 de biti, nu 16 ca in Borland C/C++, char - 8 biti, short - 16 biti, long - 32, long long - 64\r\n* folositi sprintf in loc de itoa sau ltoa.\r\n* programul de evaluare ruleaza pe un sistem de operare UNIX. Folositi \"\\n\" pentru terminarea liniei curente, nu \"\\r\\n\"\r\n* aveti grija ca functia main sa fie de tip int si sa intoarca 0 (return 0;)\r\n* nu folositi librarii dependente de sistemul de operare (ex. dos.h, graphics.h in C sau dos, crt, graph in pascal). Aceste librarii nu sunt necesare pentru a rezolva problemele de pe infoarena.\r\n* nu folositi modificatorii far, huge, _huge, __huge pentru ca nu exista in GCC. De asemenea, nu exista nici functiile care folosesc aceste tipuri de date (de ex. farmalloc, farfree etc.) si nici conceptul de memory model (tiny, small, medium, large, huge). De toate acestea nu mai e nevoie intrucat puteti avea acces la toata memoria prin functii standard si pointer-i standard - new, delete, malloc etc.',1142,'protected',NULL,NULL),('utilizator/respawn','Profil reSpawn','2007-02-23 22:36:17','2007-02-23 22:36:17','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6112,'public',NULL,NULL),('runda/preoni2007_runda3_1112','runda/preoni2007_runda3_1112','2007-02-18 21:54:00','2007-02-18 21:54:00','Scrie aici despre runda/preoni2007_runda3_1112',5868,'public',NULL,NULL),('planificare/sedinta_20070615','planificare/sedinta_20070615','2007-06-20 13:56:34','2007-06-20 13:56:34','h1. Sedinta 2007-06-15\r\n\r\n_ora 20:00, locatie: Piranha_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Mircea Pasoi\r\n* Valentin Stanciu\r\n* Claudia Cardei\r\n\r\nh2. Agenda\r\n\r\n* buget finala preONI 2007\r\n* probleme de info\r\n* diplome\r\n* pliante, badges, tricouri\r\n* pagina finalei preONI + stire + newsletter\r\n* card-uri infoarena de la banca\r\n* gestiune bani\r\n* tichete pentru finala preONI\r\n\r\nh2. Rezolutii adoptate\r\n\r\nh3. Despre finala preONI 2007\r\n\r\n* buget:\r\n** 15 lei x 2 nopti x 25 persoane = 750 lei cazare\r\n** 3 grupe x 60 lei = 1800 lei pentru premii\r\n** 30 x 1 lei = 30 lei pentru imprimare diplome\r\n** 15 x 4 = 60 lei pentru racoritoare\r\n** 80 lei pentru alte chestii de protocol\r\n** total: 2740 lei\r\n** padding +30%: 3560 lei\r\n* Vali cauta oferte de tricouri\r\n* bani propunatori: sa se prezinte propunatorii la o sedinta ca sa discutam despre bani. Ideea de baza este ca ori platim pe toti (nu doar propunatorii de probleme) ori pe nimeni.\r\n* Leonard scoate extrase de cont periodic direct de la Raiffeisen.\r\n* Trebuie sa-i amintim lui Ali ca avem si fete de cazat.\r\n* Leonard face pagina finalei si baga stire.\r\n',13,'public',NULL,NULL),('newsletter/preoni-2007-runda-3','preONI 2007, Runda #3','2007-03-02 09:38:27','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nTi-am pregatit o noua provocare!\r\nEste vorba de runda #3 a concursului preONI. Te invitam sa\r\nparticipi, chiar daca nu ai concurat la rundele anterioare.\r\n\npreONI este concursul cu premii care te pregateste pentru\r\nOlimpiada Nationala de Informatica.\r\n\nRunda #3 a concursului va avea loc ...\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Duminica, 4 martie 2007, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPagina rundei: \'preoni-2007/runda-3\':preoni-2007/runda-3\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la aceasta runda iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te va aduce mai aproape de varful clasamentul.\r\n==NewsletterRating(username=\"%username%\")==\r\nRating-ul este un indicator al performantei tale in conditii de\r\nconcurs. Afla mai multe: \'documentatie/rating\':documentatie/rating.\r\n\nIti tinem pumnii!\r\n\nh2.  Despre preONI \n\npreONI, concursul de marca al comunitatii infoarena, este dedicat\r\nelevilor de liceu ce se pregatesc pentru ONI (Olimpiada Nationala\r\nde Informatica).\r\n\npreONI se imparte in 3 grupe: clasa a IX-a si gimnaziu, clasa\r\na X-a si clasele XI-XII. Se organizeaza 4 runde online de calificare.\r\nIn urma acestora, cei mai buni de la fiecare grupa sunt invitati la\r\no runda finala.\r\n\nIn cadrul unei runde, vei avea de rezolvat 3 probleme in 4h.\r\nCastigatorii rundei finale sunt premiati cu bani si/sau obiecte.\r\n\nPe pagina concursului ( \'preoni-2007\':preoni-2007 ) vei gasi\r\ninformatii despre cum participi, cine propune probleme, premii si\r\nsponsori, regulamentul concursului samd.\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('planificare/sedinta_20070303','Sedinta 2007-03-03','2007-03-03 15:35:52','2007-03-03 17:39:40','h1. Sedinta 2007-03-03\r\n\r\n_ora 17:00, locatia Carrefour Grozavesti_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Mircea Pasoi\r\n* Diaconu Adrian\r\n* Silviu Ganceanu\r\n* Valentin Stanciu\r\n* Ofiteru Andreea\r\n\r\nh2. Agenda\r\n\r\n* 1. Acte asociatie\r\n* 2. Articol Adevarul\r\n* 3. preONI Finala\r\n** 3.1. Sponsori\r\n** 3.2. Data desfasurare\r\n* 4. Filme\r\n* 5. hei-rup?\r\n* 6. Tichete\r\n\r\nh2. Notite\r\n\r\n* 1: pe 5 Cristi are audiere. S-ar putea sa trebuiasca cazier\r\n* 3.1: Vorbim despre sponsori dupa ce aflam mai multe despre finala.\r\n* 3.2: -Runda 4-a o facem pe 18 iar- runda finala o facem dupa ONI. Emil ne zice cand poate.\r\n* 4: ramane in aer\r\n* 5: hei-rup pe 17-18 martie\r\n* 5.1: mircea, cristi, fluf, vali, adi, vladu\r\n* 5.2: screencast de development\r\n* 5.3: webcam public\r\n* *fluf face revert la ultimul stable revision*\r\n',13,'public',NULL,NULL),('documentatie/probleme-frecvente-la-autentificare','Cum gasesc problemele','2006-11-27 05:57:42','2007-04-19 20:32:04','h1. Probleme frecvente la autentificare\r\n\r\nDaca nu te poti autentifica la infoarena sau daca site-ul se comporta ciudat - spre exemplu apari autentificat intr-o sectiune insa in alta esti anonim - atunci aceasta pagina este pentru tine.\r\n\r\nh2. No cookies, no infoarena\r\n\r\nSite-ul nostru foloseste cookie-uri (si nimic altceva) pentru autentificare. Daca browser-ul tau nu suporta sau este configurat sa blocheze cookie-urile atunci nu te poti autentifica.\r\n\r\nCum poti verifica asta? *FIXME*\r\n\r\nAtentie! Cookie-urile pot fi blocate si de un firewall / antivirus.\r\n\r\nh2. Clear cookies\r\n\r\nCel mai probabil este necesar va trebui sa stergi cookie-urile stocate in browser. Cum se face asta?\r\n\r\n* Mozilla Firefox: $Tools > Clear Private Data$\r\n* Internet Explorer: $Tools > Internet Options > Delete Cookies$\r\n* Opera 9: $Tools > Delete Private Data$\r\n* Safari: *FIXME*\r\n* Konqueror: $Settings > Configure Konqueror > Cookies > Management > Delete All$\r\n\r\nDupa ce stergi cookie-urile incearca din nou sa te autentifici.\r\n\r\nh2. Ora calculatorului tau?\r\n\r\nAsigura-te ca ora calculatorului tau este corecta. Daca dai data inapoi cu mai mult de 5 zile, cookie-urile de pe infoarena.ro sunt ignorate de browser.\r\n\r\nh2. Incearca alt browser\r\n\r\ninfoarena a fost testat pe urmatoarele browser-e: Mozilla FireFox 1.5, Mozilla Firefox 2.0, Microsoft Internet Explorer 6, Opera 9.20, Konqueror 3.5.5 . Daca browser-ul tau nu se afla printre acestea, iti recomandam sa incerci altul.\r\n\r\nh2. Tot nu merge?\r\n\r\nDaca nici una din recomandarile de mai sus nu rezolva problema, \"contacteaza-ne pe e-mail\":contact. Vom incerca sa-ti raspundem cat mai repede.\r\n',3270,'public',NULL,NULL),('preoni-2007/prelungiri','template/preoni-2007/runda-3/prelungiri','2007-03-04 10:19:36','2007-03-04 10:22:54','table{width: 50%}. |_={background-color: red; color: white;}. Timpul de lucru se extinde cu 15min. Astfel, solutiile se pot trimite pana la ora 13^15^. Ne cerem scuze pentru inconveniente. |',13,'protected',NULL,NULL),('preoni-2007/presa','Aparitii in presa preONI 2007','2007-01-15 15:58:34','2007-03-07 12:02:19','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Aparitii in presa\r\n\r\n_infoarena_ a aparut in \'Adevarul\':http://adevarulonline.ro pe \'prima pagina\':http://www.adevarulonline.ro/articole/fostii-olimpici-ii-antreneaza-pe-concurentii-de-la-olimpiade/305061.\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('preoni-2007/runda-4/10','preONI 2007, Runda 4, Clasa a 10-a','2007-03-07 12:06:10','2007-03-25 06:22:02','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda4_10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-4\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-4/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/runda-4/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-4/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda4_10\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\n==include(page=\"preoni-2007/prelungiri\")==\r\n\r\nRunda se desfasoara *Duminica 25 martie*, la ora {*09^00^*} si va dura *{color:red}4h 15min*.\r\n\r\nParticipantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2007/clasament/runda-4/10.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda4_10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda4_10',NULL,NULL),('runda/preoni2007_runda4_9/clasament','Clasament preoni2007_runda4_9','2007-03-07 12:02:53','2007-03-07 12:02:53','h1. Clasament ==roundparam(round_id=\"preoni2007_runda4_9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda4_9\")==',1,'round: preoni2007_runda4_9',NULL,NULL),('runda/preoni2007_runda4_10/clasament','Clasament preoni2007_runda4_10','2007-03-07 12:06:10','2007-03-07 12:06:10','h1. Clasament ==roundparam(round_id=\"preoni2007_runda4_10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda4_10\")==',1,'round: preoni2007_runda4_10',NULL,NULL),('utilizator/nistaman','Profil nistaman','2007-03-04 15:15:55','2007-03-04 15:15:55','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6195,'public',NULL,NULL),('preoni-2007/clasament/runda-4/9','Clasament preONI 2007, Runda 4, Clasa a 9-a si gimnaziu','2007-03-07 12:15:49','2007-03-07 12:16:04','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda4_9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-4\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/runda-4/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-4/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasa a 9-a si gimnaziu\':preoani-2007/clasament/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-4/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda4_9\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/clasament/runda-4/10','Clasament preONI 2007, Runda 4, Clasa a 10-a','2007-03-07 12:17:19','2007-03-07 12:17:19','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda4_10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-4\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/runda-4/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-4/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-4/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/clasament/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-4/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda4_10\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('multe-smenuri-de-programare-in-cc-si-nu-numai','Multe \"smenuri\" de programare in C/C++... si nu numai!','2004-11-10 00:00:00','2010-02-27 10:50:30','h1. Multe \"smenuri\" de programare in C/C++... si nu numai!\r\n\r\n(Categoria _Limbaje de programare_, Autor _Mircea Pasoi_)\r\n\r\nAcest articol vine ca o completare a articolului scris de Alexandru Mosoi, prezentand noi trucuri care le-am folosit si m-au ajutat mult. O mare parte din acestea le-am invatat din sursele lui Radu Berinde (cred ca stiti cu totii cine este), asadar ii multumesc!\r\n\r\nh2. Array-uri neindexate de la 0\r\n\r\nUn dezavantaj fata de Pascal este faptul ca in C nu putem avea expresii de genul {@A[-100]@} unde $A$ este un vector. Dar acest lucru se poate remedia. Spre exemplu, daca vrem sa facem un vector $A$ cu elemente de la $-100$ la $100$ procedam astfel:\r\n\r\n== code(c) |\r\nint A[201];\r\n#define A (A + 100)\r\n==\r\n\r\nh2. Fisiere de intrare si iesire\r\n\r\nFolositi {@freopen()@} in loc de {@fopen()@} deoarece este mai comod, in special la concursurile in care intrare si iesirea sunt standard.\r\n\r\n== code(c) |\r\nfreopen(\"in.txt\", \"r\", stdin);\r\nfreopen(\"out.txt\", \"w\", stdout);\r\n==\r\n\r\nh2. Cautare binara (ideea originala de la Mihai Patrascu)\r\n\r\nUrmatorul cod este de aproximativ $4$ ori mai rapid (am testat cu cautare binara ca in manual) , mai usor de inteles, mai flexibil si mai scurt... ce ati putea dori mai mult?\r\n\r\n== code(c) |\r\nint N, A[N];\r\n\r\nint binary_search(int val)\r\n{\r\n    int i, step;\r\n    for (step = 1; step < N; step <<= 1);\r\n    for (i = 0; step; step >>= 1)\r\n        if (i + step < N && A[i + step] <= val)\r\n           i += step;\r\n    return i;\r\n}\r\n==\r\n\r\nProcedura de mai sus face cautarea binara folosind puteri a lui $2$ in ordine descrescatoare, practic incerc sa determin fiecare bit al rezultatului.\r\n\r\nh2. Impartire in bucati de marime $sqrt(n)$ (cunoscut si ca \"smenul lui Bogdan Batog\")\r\n\r\nSa presupunem ca avem un vector de lungime n cu numere reale pe care se fac urmatoarele operatii:\r\n{@ADUNA(st, dr, x)@} - toate elementele cu indicii intre $st$ si $dr$ isi cresc valoarea cu $x$\r\n{@SUMA(st, dr)@} - returneaza suma elementelor cu indicii intre $st$ si $dr$\r\n\r\nPentru cei ce cunosc arbori de intervale, rezolvarea acestei probleme in $O(lg n)$ per operatie este o munca usoara, dar presupunand ca nu stim aceasta structura putem folosi urmatorul truc: vom construi un al doilea vector de lungime $sqrt(n)$ care retine suma elementelor pe bucati de lungime {$sqrt(n)$}. Pentru a face o operatie pe un interval [{$st, dr$}] vom imparti acest interval in bucati de $sqrt(n)$ a caror actualizare o facem in vectorul $B$ si elementele care raman in margine in vectorul {$A$}. De exemplu pe vectorul {$A{~0..15~}$} vom avea vectorul {$B{~0..3~}$}. Pentru a actualiza de exemplu [{$2, 12$}] vom actualiza {$B{~1~}$} (care corespunde lui [{$4..7$}]), {$B{~2~}$} (pentru [{$8..11$}]) si {$A{~2~}$}, {$A{~3~}$}, {$A{~12~}$} (elementele din margini). Cum sunt maxim $sqrt(n)$ elemente de actualizat in $B$ si pe margini nu vom actualiza niciodata mai mult de $2 * sqrt(n)$ elemente putem concluziona ca operatiile vor avea complexitate {$O(sqrt(n))$}.\r\n\r\nDaca am avea aceeasi problema dar in doua dimensiuni, am putea face acelasi \"smen\" pentru fiecare linie pentru o complexitate $O(n*sqrt(n))$ per operatie, sau cu arbori de intervale pe fiecare linie {$O(n*lg n)$}. Putem, de asemenea obtine o complexitate $O(n)$ folosind urmatoarea impartire:\r\n$A$ - pentru bucati $1 * 1$\r\n$B$ - pentru bucati $sqrt(n) * sqrt(n)$\r\n$C$ - pentru bucati $1 * sqrt(n)$\r\n$D$ - pentru bucati $sqrt(n) * 1$\r\nAcest mod de reprezentare este o extindere directa a aceluiasi smen in doua dimensiuni. Aceasta idee poate fi folosita si pentru alte operatii: inmultire, minim, maxim, etc. In general, orice se poate rezolva cu acest \"smen\" se poate obtine la o complexitate mai buna cu arbori de intervale, dar merita sa stiti si aceasta ideea deoarece de multe ori scuteste din efortul de implementare, desi se pierde din viteza... alegerea voastra! ;)\r\n\r\nh2. LCA in $O(sqrt(n))$ (ideea originala de la Radu Berinde)\r\n\r\nDaca nu stiti ce este LCA, va recomand sa cititi \'articolul\':lowest-common-ancestor lui Emilian Miron din cadrul site-ului pentru a va documenta. In continuare vom prezenta un algoritm mai ineficient, dar foarte usor de implementat. Consideram arborele si atribuim fiecarui nod o inaltime. Vom imparti arborele in $sqrt(H)$ intervale in functie de inaltime, unde $H$ e inaltimea maxima (de exemplu la $H=9$ nodurile cu inaltimi intre $0$ si $2$ vor forma un interval, [{$3..5$}] alt interval si ultimul interval de inaltimi [{$6..8$}]). Astfel, pentru fiecare nod, pe langa tatal sau, vom retine si tatal din intervalul de mai sus, printr-o parcurgere DF. In continuare, codul:\r\n\r\n$H$ se calculeaza inainte sau poate fi constant\r\n$T$ sunt tatii nodului si $N$ numarul de noduri\r\n\r\n== code(c) |\r\nvoid DF(int n, int t2, int lev)\r\n{\r\n    int i;\r\n    T2[n] = t2, Lev[n] = lev;\r\n    if (lev % H == 0) t2 = n;\r\n    for (i = 0; i < N; i++)\r\n        if (T[i] == n) DF(i, t2, lev+1);\r\n}\r\n==\r\n\r\nOperatia de LCA se va realiza apoi foarte usor, urcand pe tatii din intervale, pana se ajunge la doua noduri in acelasi interval, apoi folosindu-se metoda clasica. Cod:\r\n\r\n== code(c) |\r\nint LCA(int x, int y)\r\n{\r\n    while (T2[x] != T2[y])\r\n        if (Lev[x] > Lev[y])\r\n            x = T2[x];\r\n        else\r\n            y = T2[y];\r\n    while (x != y)\r\n        if (Lev[x] > Lev[y])\r\n            x = T[x];\r\n        else\r\n            y = T[y];\r\n    return x;\r\n}\r\n==\r\n\r\n\r\nh2. LCA in $O(lg^2^ n)$\r\n\r\nAceeasi problema, dar o alta rezolvare. Vom construi o matrice $A{~i,j~}$ cu semnificatia $A{~i,j~}$ = al {$2^i^$}-lea tata al nodului {$j$}. Folosind aceasta matrice putem cauta binar ({$O(lg n)$}) nivelul pe care s-ar putea afla LCA-ul a doua noduri si sa determinam daca nodul ales este corect - adica daca nodul situat la acel nivel este acelasi pentru cele doua noduri pentru care se face LCA ({$O(lg n)$} cu matricea de mai sus). Complexitate finala $O(lg^2^ n)$ si $O(n*lg n)$ memorie.\r\n\r\nh2. For-uri \"complicate\"\r\n\r\nfor-ul in C/C++ este foarte flexibil si poate ajuta foarte mult in compactarea codului, deci si a timpului de implementare. In continuare vom prezenta algoritmul merge sort (sortare prin interclasare) scris in cateva linii (putine, zic eu!):\r\n\r\n== code(c) |\r\nint N, A[N], B[N];\r\nvoid merge_sort(int l, int r)\r\n{\r\n    int m = (l + r) >> 1, i, j, k;\r\n    if (l == r) return;\r\n    merge_sort(l, m);\r\n    merge_sort(m + 1, r);\r\n    for (i=l, j=m+1, k=l; i<=m || j<=r; )\r\n        if (j > r || (i <= m && A[i] < A[j]))\r\n            B[k++] = A[i++];\r\n        else\r\n            B[k++] = A[j++];\r\n    for (k = l; k <= r; k++) A[k] = B[k];\r\n}\r\n==\r\n\r\nh2. Recomandari generale\r\n\r\n# Programare dinamica cu memoizare: mult mai simplu si uneori chiar mai rapida cand nu ne trebuie tot array-ul\r\n# Algoritmi randomizati: de multe ori mai usor de implementat si mai eficienti, mai bine decat cei euristici, dar necesita o analiza mult mai atenta a performantei. Exemple calsice: quicksort, statistici de ordine\r\n\r\nh2. \"Smenul lui Mars\" (Marius Andrei)\r\n\r\nConsideram urmatoarea problema: se da un vector $A$ de $N$ elemente pe care se fac $M$ astfel de operatii: {@ADUNA(st, dr, x)@} - toate elementele cu indicii intre $st$ si $dr$ ({$0 &le; st &le; dr &lt; N$}) isi cresc valoarea cu {$x$} . La sfarsit trebuie sa se afiseze vectorul rezultat. In continuarea vom descrie o metoda care ne da un timp de rulare de $O(1)$ pentru operatia $ADUNA$ si $O(N)$ pentru a determina toate elementele din vector. Vom construi un al doilea vector $B$ de $N+1$ elemente, cu proprietatea ca {$A{~i~} = B{~0~} + B{~1~} + ... B{~i~}$}. Astfel, o operatie {@ADUNA(st, dr, x)@} devine:\r\n\r\n== code(c) |B[st] += x;\r\nB[dr + 1] -= x;\r\n==\r\n\r\nDa, este chiar asa de simplu! Pentru a determina un element A{~i~} vom aduna pur si simplu {$B{~0~} + B{~1~} + ... B{~i~}$}. Incercati pe foaie sa vedeti cum funtioneaza. Aceasta ideea poate fi extinsa si in doua dimensiuni, construind $B$ astfel incat $A{~i,j~}$ = suma subtabloului din $B$ cu coltul in ({$0, 0$}) si ({$i, j$}), astfel (pt. {@ADUNA(x1,y1,x2,y2,v)@}):\r\n\r\n== code(c) |B[x1][y1] += v;\r\nB[x1][y2 + 1] -= v;\r\nB[x2 + 1][y1] -= v;\r\nB[x2 + 1][y2 + 1] += v;\r\n==\r\n\r\nPe cazul general, daca vrem sa facem operatii in $d$ dimensiuni vom avea o complexitate {$O(2^d^)$}. Reamintesc ca aceasta metoda este eficienta doar cand se vrea afisata vectorul/matricea/etc. doar la sfarsitul operatiilor sau sunt foarte putine interogari ale valorilor elementelor, deoarece aflarea unui element este o operatie foarte ineficienta: {$O(i)$} pentru a afla valorile elementelor pana la pozitia $i$.\r\n\r\nh2. Grafuri cu liste de adiacenta (ideea originala de la Radu Berinde)\r\n\r\nSe stie (sau ar trebui sa se stie!) ca lucrul cu pointerii este foarte incet... astfel, cand retinem un graf rar (numar mare de noduri, numar mic de muchii) cu pointeri (vezi mai jos) incetinim foarte mult programul.\r\n\r\n== code(c) |\r\nstruct list\r\n{\r\n    int n;\r\n    struct list *next;\r\n}\r\ntypedef struct list list;\r\n==\r\n\r\nIn contiuare vom prezenta o metoda care este de $3-4$ ori mai rapida (adica parcurgerile DF , BF sau altii algoritmi ruleaza de $3-4$ ori mai rapid cand graful este stocat astfel), dar are ca dezavantaj necesitatea de a citi de doua ori fisierul de intrare.\r\n\r\n== code(c) |\r\n#include <stdlib.h>\r\n#include <stdio.h>\r\n\r\nint N, M, *G[N], Deg[N];\r\n\r\nint main(void)\r\n{\r\n    int i, j;\r\n \r\n    freopen(\"in.txt\", \"r\", stdin);\r\n    scanf(\"%d %d\", &N, &M);\r\n    for (; M > 0; M--)\r\n    {\r\n        scanf(\"%d %d\", &i, &j);\r\n        Deg[i - 1]++, Deg[j - 1]++;\r\n    }\r\n    for (i = 0; i < N; Deg[i++] = 0)\r\n        G[i] = (int *) malloc(Deg[i]*sizeof(int));\r\n    fseek(stdin, 0, SEEK_SET);\r\n    scanf(\"%d %d\", &N, &M);\r\n    for (; M > 0; M--)\r\n    {\r\n        scanf(\"%d %d\", &i, &j);\r\n        i--, j--;\r\n        G[i][Deg[i]++] = j,\r\n            G[j][Deg[j]++] = i;\r\n    }\r\n\r\n    return 0;\r\n}\r\n==\r\n\r\nSporul de viteza se datoreaza faptului ca se folosesc vectori in loc de pointeri si struct-uri. Daca ne permite memoria putem evita citirea de doua ori a fisierul prin pastrarea muchiilor intr-o lista de muchii si apoi, dupa calcularea gradelor, inserarea muchiilor in liste. Pentru a demonstra eficienta acestei metode faceti urmatorul test: implementati o sursa cu pointeri si struct si implementati un BF, apoi scrieti codul de mai sus cu urmatoarele modificari:\r\n\r\n== code(c) |\r\n...\r\nfor (i = 0; i < N; i++)\r\n{\r\n      G[i] = (int *) malloc((Deg[i]+1)*sizeof(int));\r\n      G[i][Deg[i]] = -1;\r\n      Deg[i] = 0;\r\n}\r\n...\r\n==\r\n\r\nsi implementati BF astfel:\r\n\r\n== code(c) |\r\nvoid BF()\r\n{\r\n      int Q[N], ql, qr, *p;\r\n      char U[N];\r\n      memset(U, 0, sizeof(U));\r\n      U[Q[ql = qr = 0] = n] = 1;\r\n      for (; ql <= qr; ql++)\r\n              for (p = G[Q[ql]]; *p != -1; p++)\r\n                      if (!U[*p]) U[Q[++qr] = *p] = 1;\r\n}\r\n==\r\n\r\nApoi, incercati sa vedeti diferenta de timp intre cele doua programe... impresionant, nu?\r\n\r\n\r\n\r\nh2. Numere mari (ideea originala de la Radu Berinde)\r\n\r\nIn continuare voi prezenta cum se pot realiza operatii pe numere mari cu foarte putine linii de cod. In general, multi programatori se complica la aceste operatii, desi nu este nevoie! Vom considera ca numerele mari sunt vectori in care elementul de indice $0$ indica lungimea numarului, iar cifrele sunt retinute in ordinea inversa decat cea a citirii.\r\n\r\nh3. Suma a doua numere mari\r\n\r\n== code(c) |\r\nvoid add(int A[], int B[])\r\n{\r\n      int i, t = 0;\r\n      for (i=1; i<=A[0] || i<=B[0] || t; i++, t/=10)\r\n              A[i] = (t += A[i] + B[i]) % 10;\r\n      A[0] = i - 1;\r\n}\r\n==\r\n\r\nh3. Inmultirea unui numar mare cu un numar mic\r\n\r\n== code(c) |\r\nvoid mul(int A[], int B)\r\n{\r\n      int i, t = 0;\r\n      for (i = 1; i <= A[0] || t; i++, t /= 10)\r\n              A[i] = (t += A[i] * B) % 10;\r\n      A[0] = i - 1;\r\n}\r\n==\r\n\r\nh3. Inmultirea unui numar mare cu un numar mare\r\n\r\n== code(c) |\r\nvoid mul(int A[], int B[])\r\n{\r\n      int i, j, t, C[NR_CIFRE];\r\n      memset(C, 0, sizeof(C));\r\n      for (i = 1; i <= A[0]; i++)\r\n      {\r\n              for (t=0, j=1; j <= B[0] || t; j++, t/=10)\r\n                      C[i+j-1]=(t+=C[i+j-1]+A[i]*B[j])%10;\r\n              if (i + j - 2 > C[0]) C[0] = i + j - 2;\r\n      }\r\n      memcpy(A, C, sizeof(C));\r\n}\r\n==\r\n\r\nh3. Scaderea a doua numere mari\r\n\r\n== code(c) |\r\nvoid sub(int A[], int B[])\r\n{\r\n      int i, t = 0;\r\n      for (i = 1; i <= A[0]; i++)\r\n              A[i] += (t = (A[i] -= ((i <= B[0]) ? B[i] : 0) + t) < 0) * 10;\r\n      for (; A[0] > 1 && !A[A[0]]; A[0]--);\r\n}\r\n==\r\n\r\nh3. Impartirea unui numar mare la un numar mic\r\n\r\n== code(c) |\r\nvoid div(int A[], int B)\r\n{\r\n      int i, t = 0;\r\n      for (i = A[0]; i > 0; i--, t %= B)\r\n              A[i] = (t = t * 10 + A[i]) / B;\r\n      for (; A[0] > 1 && !A[A[0]]; A[0]--);\r\n}\r\n==\r\n\r\nh3. Restul unui numar mare la un numar mic\r\n\r\n== code(c) |\r\nint mod(int A[], int B)\r\n{\r\n      int i, t = 0;\r\n      for (i = A[0]; i > 0; i--)\r\n              t = (t * 10 + A[i]) % B;\r\n      return t;\r\n}\r\n==\r\n\r\nh2(#AVL). AVL-uri (ideea originala de la Radu Berinde - again)\r\n\r\nAVL-urile sunt arbori de cautare echilibrati care au complexitate O(lg n) pe operatiile de inserare, stergere si cautare. Pentru mai multe detalii cautati cartea \"Arbori\" pe [2]site-ul doamnei profesoare Emanuela Cerchez. In continuare voi prezenta o metoda destul de simpla de a implementa aceastra structura de date in timp de concurs. Enjoy!\r\n\r\n== code(c) |\r\n#define max(a, b) ((a) > (b) ? (a) : (b))\r\n#define geth(n) (n->h = 1 + max(n->l->h, n->r->h))\r\n\r\nstruct node\r\n{\r\n      int key, h;\r\n      struct node *l, *r;\r\n} *R, *NIL;\r\ntypedef struct node node;\r\n\r\nvoid init(void)\r\n{\r\n      R = NIL = (node *) malloc(sizeof(node));\r\n      NIL->key = NIL->h = 0,\r\n              NIL->l = NIL->r = NULL;\r\n}\r\n\r\nnode* rotleft(node *n)\r\n{\r\n      node *t = n->l;\r\n\r\n      n->l = t->r, t->r = n,\r\n              geth(n), geth(t);\r\n      return t;\r\n}\r\n\r\nnode* rotright(node *n)\r\n{\r\n      node *t = n->r;\r\n \r\n      n->r = t->l, t->l = n,\r\n              geth(n), geth(t);\r\n      return t;\r\n}\r\n\r\nnode* balance(node *n)\r\n{\r\n      geth(n);\r\n      if (n->l->h > n->r->h + 1)\r\n      {\r\n              if (n->l->r->h > n->l->l->h)\r\n                      n->l = rotright(n->l);\r\n              n = rotleft(n);\r\n      }\r\n      else\r\n              if (n->r->h > n->l->h + 1)\r\n              {\r\n                      if (n->r->l->h > n->r->r->h)\r\n                              n->r = rotleft(n->r);\r\n                      n = rotright(n);\r\n              }\r\n      return n;\r\n}\r\n\r\nnode* insert(node *n, int key)\r\n{\r\n      if (n == NIL)\r\n      {\r\n              n = (node *) malloc(sizeof(node));\r\n              n->key = key, n->h = 1, n->l = n->r = NIL;\r\n              return n;\r\n      }\r\n      if (key < n->key)\r\n              n->l = insert(n->l, key);\r\n      else\r\n              n->r = insert(n->r, key);\r\n      return balance(n);\r\n}\r\n\r\nnode* erase(node *n, int key)\r\n{\r\n      node *t;\r\n      if (n == NIL) return n;\r\n      if (n->key == key)\r\n      {\r\n              if (n->l == NIL || n->r == NIL)\r\n              {\r\n                      t = n->l == NIL ? n->r : n->l;\r\n                      free(n); return t;\r\n              }\r\n              else\r\n              {\r\n                      for (t = n->r; t->l != NIL; t = t->l);\r\n                      n->key = t->key,\r\n                              n->r = erase(n->r, t->key);\r\n                      return balance(n);\r\n              }\r\n      }\r\n      if (key < n->key)\r\n              n->l = erase(n->l, key);\r\n      else\r\n              n->r = erase(n->r, key);\r\n      return balance(n);\r\n}\r\n\r\nint search(node *n, int key)\r\n{\r\n      if (n == NIL) return 0;\r\n      if (n->key == key) return 1;\r\n      if (key < n->key)\r\n              return search(n->l, key);\r\n      else\r\n              return search(n->r, key);\r\n}\r\n==\r\n\r\nAici se termina acest articol. Am incercat sa pun accentul pe simplitate si eficienta, si cred ca am reusit acest lucru. Sper ca ati invatat cate ceva din el si recomand sa luati fiecare bucata in parte si sa incercati sa implementati efectiv ca sa intelegi mai bine. Bafta la concursuri tuturor! ;)\r\n',3997,'public',3673,NULL),('documentatie/development','Development','2006-11-22 21:02:23','2009-07-27 14:53:57','h1. Development\r\n\r\nPagina a fost mutata \'aici\':development.',1,'public',NULL,NULL),('development','Development','2007-03-10 12:40:49','2007-12-16 20:07:31','h1. Development\r\n\r\nCodul sursa din spatele site-ului infoarena este \'liber disponibil\':http://hackers.devnet.ro/browser iar dezvoltarea se face in mod \'public\':http://hackers.devnet.ro. Oricine poate sa-si instaleze o varianta \"locala\" de infoarena2, sa adauge feature-uri si sa-si trimita modificarile inapoi.\r\n\r\nSite-ul curent (infoarena2) este scris in php folosind mysql ca baza de date si apache ca server de web. Am incercat sa mentinem codul cat mai simplu pentru a fi usor de modificat si pentru incepatori. Din pacate dezvoltarea la infoarena2 nu s-a miscat de ceva vreme. Momentan ne gandim sa rescriem site-ul folosind tehnologii moderne si experienta acumulata din infoarena2. Avem o \'propunere\':propuneri/3-infoarena3 pentru rescriere.\r\n\r\nMulta vreme am folosit wiki-ul din trac de pe hackers.devnet.ro pentru development. In spiritul de \"dogfooding\" am decis sa folosim trac doar pentru tichete, si sa scrie documentatia de development pe propriul wiki. Momentan scriem in romana, desi engleza ar fi o alegere mai naturala.\r\n\r\nh2. Alte pagini de development\r\n\r\n* \'IAP #3\':propuneri/3-infoarena3 : Propunerea initiala pentru infoarena3\r\n* \'Cerinte\':development/cerinte : Ce trebuie sa implementam in infoarena3\r\n\r\n',1142,'public',NULL,NULL),('preoni-2007/runda-3/solutii','Solutii preONI 2007, Runda 3','2007-03-04 13:00:05','2007-03-07 23:54:33','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Solutii Runda 3\r\n\r\nh2. \'Buline\':problema/buline \r\n\r\nh3. (problema usoara, clasa a 9-a)\r\n\r\nProblema este o variatie a unei probleme clasice: dandu-se un sir de $N$ numere intregi sa se determine o secventa de suma maxima. Singura modificare este ca in aceasta problema sirul este circular. In prima parte a solutiei nu vom lua in considerare faptul ca sirul este circular. Pentru a rezolva problema pentru un sir normal exista o solutie clasica $O(N)$. Se calculeaza pentru fiecare $i$ secventa de suma maxima care se termina cu elementul $i$: este fie secventa de suma maxima care se termina la elementul $i-1$, la care se adauga elementul $i$, fie doar elementul $i$. O scurta descriere in pseudocod a acestui algoritm:\r\n\r\n== code(c) |\r\ns = smax = 0;\r\npentru i = 1, n executa\r\n   s = max(s+A[i], A[i]);\r\n   smax = max(smax, s);\r\nsfarsit pentru\r\n==\r\n\r\nO prezentare detaila a acestei probleme si metode de rezolvare gasiti \'aici\':http://www.ginfo.ro/revista/11_2/focus2.pdf. \r\nVom trata acum si faptul ca sirul este circular. Astfel, trebuie verificate si secventele de forma $i,i+1,...N-1,N,1,2,...j-1,j$. Pentru a realiza acest lucru eficient precalculam un sir de sume partiale $S{~i~} = A{~1~} + A{~2~} + ... + A{~i~} = S{~i-1~}+A{~i~}$ si un al doilea sir $T{~i~} = max(S{~1~}, S{~2~},..., S{~i~}) = max(T{~i-1~}, S{~i~})$. Pentru un $i$ fixat, cea mai buna secventa de forma $i,i+1,...N-1,N,1,2,...j-1,j$ se poate calcula in $O(1)$ astfel: $T{~i-1~}+S{~N~}-S{~i-1~}$.\r\n\r\nUn alt mod de a verifica secventele de forma $i,i+1,...N-1,N,1,2,...j-1,j$ este daca observam ca suma acestei secvente este de fapt suma tuturor elementelor din care se scade secventa $j+1, j+2, ... i-2, i-1$. Astfel ne intereseaza o secventa de suma minima pe care sa o scadem din suma totala. Aceasta se poate determina cu o mica modificare a alogirtmului pentru suma maxima sau inmultind elementele cu $-1$ si cautand o secventa de suma maxima.\r\n\r\nComplexitatea rezolvarii este $O(N)$, iar pentru reconstituirea solutiei sunt necesare  doar cateva variabile aditionale pentru pozitie si lungime.\r\n\r\nh2. \'Zero 2\':problema/zero2\r\n\r\nh3. (problema medie, clasa a 9-a)\r\n\r\nFie $E(N) = 1!*2!*...*N!$. Numarul de zerouri terminale in scrierea lui $E(N)$ in baza $B$ este egal cu numarul de ori $E(N)$ se imparte la $B$. Pentru a determinarea puterea la care apare $B$ in $E(N)$ vom descompune numarul $B$ in factori primi $B = p{~1~}^e{~1~}^*p{~2~}^e{~2~}^*...*p{~k~}^e{~k~}^$. Fie $Nr(N, p)$ puterea la care apare numarul prim $p$ in descompunerea in factori primi a lui $E(N)$. Rezultatul va fi $min([Nr(N, p{~1~})/e{~1~}], [Nr(N, p{~2~})/e{~2~}], ..., [Nr(N, p{~k~})/e{~k~}])$. \r\nAsadar problema se va reduce la a calcula $Nr(N, p)$ in mod eficient. O prima rezolvare de complexitate $O(N*lg N)$ este de parcurge toate numerele de la $1$ la $N$ si de a determina puterea la care apare $p$ in $x!$ ({$1 &le; x &le; N$}) folosind formula $[x/p]+[x/p^2^]+[x/p^3^]+...$ care a fost prezentata si \'aici\':http://infoarena.ro/preoni-2006/runda-4/solutii. Astfel:\r\n$Nr(N, p) = [N/p]+[N/p^2^]+[N/p^3^]+... + [(N-1)/p]+[(N-1)/p^2^]+[(N-1)/p^3^]+... + [1/p]+[1/p^2^]+[1/p^3^]+... =$\r\n$= [N/p]+[(N-1)/p]+...+[1/p] + [N/p^2^]+[(N-1)/p^2^]+...+[1/p^2^] + [N/p^3^]+[(N-1)/p^3^]+...+[1/p^3^] + ...$.\r\n\r\nFie $S(N, p) = [N/p]+[(N-1)/p]+...+[1/p]$. Putem scrie $Nr(N, p) = S(N, p) + S(N, p^2^) + S(N, p^3^) + ...$.\r\nVom arata in continuare ca se poate calcula $S(N, p)$ in $O(1)$ astfel:\r\nTermenii $[1/p],[2/p]...[(p-1)/p]$ au valoarea $0$\r\nTermenii $[p/p],[(p+1)/p]...[(2*p-1)/p]$ au valoarea $1$\r\nTermenii $[(2*p)/p],[(2*p+1)/p]...[(3*p-1)/p]$ au valoarea $2$\r\n...\r\nTermenii $[(k*p)/p],[(k*p+1)/p]...[((k+1)*p-1)/p]$ au valoarea $k$\r\nTermenii $[((k+1)*p)/p]...[N/p]$ au valoarea $k+1$\r\nAstfel $k = [N/p]-1$ iar $S(N, p) = k*(k+1)/2*p + (k+1)*(N-(k+1)*p+1)$. Putem acum calcula $Nr(N, p)$ in $O(log{~p~} N)$. Factorizarea numarului $B$ se poate face in $O(&radic;B)$, iar numarul mediu al factorilor primi din descompunerea lui $B$ este $ln ln B$, complexitatea finala a rezolvarii fiind $O(&radic;B + lnlnB*log{~p~}N)$.\r\n\r\nh2. \'Puteri\':problema/puteri\r\n\r\nh3. (problema grea, clasa a 9-a, problema medie, clasa a 10-a)\r\n\r\nNotam $A{~i~}$ multimea perechilor al caror produs se scrie sub forma {$x^i^$} cu {$x$} numar natural. Problema ne cere calcularea cardinalului reuniunii multimilor $A{~i~}$.\r\n\r\nIn continuare vom arata un mod de a calcula cardinalul unei multimi {$A{~i~}$}. Se observa ca o pereche $(a,b,c) (x,y,z)$ apartine multimii {$A{~i~}$} daca {$a+x=0$},{$b+y=0$} si {$c+z=0$} (mod {$i$}). Vom construi un tablou {$Nr[r1][r2][r3]$} care reprezinta numarul de triplete $(x,y,z)$ cu proprietatea {$r1=x$},{$r2=y$},{$r3=z$} (mod {$i$}). Vom adauga la cardinalul multimii {$A{~i~}$} produse de forma {$Nr[a][b][{@c@}]*Nr[i-a][i-b][i-c]$} ({$i-a,i-b,i-c$} se calculeaza tot mod {$i$}). Deasemenea trebuie avut grija la numerele pentru care {$2*a=0$} {$2*b=0$} si {$2*c=0$} (mod {$i$}), deoarece trebuie adunat $Nr[a][b][{@c@}]*(Nr[a][b][{@c@}]-1)/2$ pentru a nu numara aceeasi pereche de mai multe ori.\r\n\r\nO observatie care ne va ajuta sa calculam cardinalul reununiunii este faptul ca daca un numar se scrie de forma $x^i*j^$ el se poate scrie si sub forma {$y^i^$}, unde $y$ va fi chiar $x^j^$. Asadar $A{~i*j~}$ este inclusa in {$A{~i~}$}. Deci ne va interesa reuniunea multimilor {$A{~i~}$} pentru $i$ numar prim. Cardinalul acestei reuniunii se va calcula folosind principiul includerii si excluderii:\r\n\r\n==code(cpp) |\r\n|S| = |A[2]| + |A[3]| + |A[5]| + ...\r\n    - |A[6]| - |A[10]| - |A[15]| + ...\r\n    + |A[30]| + ...\r\n    - ...\r\n==\r\n\r\nCardinalul multimii $A{~i~}$ se adauga la solutie in cazul in care $i$ are un numar impar de divizori primi si se va scadea din solutie daca are un numar par de divizori. Termenii pentru care in descompunerea lui $i$ apare un factor la putere mai mare de $1$ vor fi ignorati. Datorita limitarilor din enunt nu va trebui sa verificam decat multimile $A{~i~}$ cu {$i &le; 128$}.\r\n\r\n\r\nh2. \'Balanta\':problema/balanta\r\n\r\nh3. (problema usoara, clasa a 10-a)\r\n\r\nProblema se rezolva mentinand doua multimi $H$ si $L$ continand monedele candidate pentru moneda mai grea, respectiv cele candidate pentru moneda mai usoara. Initial $H$ si $L$ contin fiecare toate elementele multimii @{1..N}@. Cele doua multimi se vor actualiza dupa fiecare cantarire. Notand cu $A$ multimea monedelor asezate pe bratul stang si cu $B$ multimea monedelor asezate pe bratul drept al balantei, vom proceda in felul urmator:\r\n\r\n* talerele sunt echilibrate - este clar ca nici una din monedele din $A$ sau $B$ nu poate fi mai grea/mai usoara, deci $H$ va deveni $H - A - B$, iar $L$ va deveni $L - A - B$\r\n\r\n* talerul stang este mai greu - moneda falsa, in caz ca este mai grea, se va afla cu siguranta in multimea $A$ sau, in caz ca este mai usoara, se va afla in multimea $B$. Astfel, $H$ devine $H &#8745; A$, iar $L$ devine $L &#8745; B$\r\n\r\n* talerul drept este mai greu - caz simetric cu cel anterior, $H$ devine $H &#8745; B$, iar $L$ devine $L &#8745; A$.\r\n\r\nLa final vom avea solutie daca si numai daca $|H| = 1 si |L| = 0$, caz in care moneda falsa este mai grea, sau $|H| = 0 si |L| = 1$, cand moneda falsa este mai usoara. \r\n\r\nComplexitatea algoritmului care rezolva problema este $O(M*N)$\r\n\r\nh2. \'Expresii 2\':problema/expresii2\r\n\r\nh3. (problema grea, clasa a 10-a)\r\n\r\nProblema se rezolva folosind programarea dinamica. Mai intai calculam o matrice $V$, unde $V[i, j]$ reprezinta numarul de sfarsituri valabile de expresii ce se pot forma ce necesita adaugarea a $j$ variabile la inceput pentru a se forma o expresie corecta de lungime $i$. Relatiile de recurenta se determina usor urmarind cu atentie in ce configuratii putem ajunge din configuratia actuala (putem pune o variabila, $+$, $*$ sau $!$).\r\nRezolvarea celei de-a 2-a parti a problemei implica folosirea matricei $V$. Avand valorile calculate putem afla caracterul pe care trebuie sa il punem pe o anumita pozitie. Este evident ca la fiecare pas indicele expresiei cautate scade cu numarul de expresii peste care \"sarim\".\r\n\r\nO alta solutie este determinarea expresiei cu numarul $P$, caracter cu caracter folosind o functie care determina cate expresii de o lungime fixata exista care incep cu un prefix dat (prefixul fiind un sir de caractere). Pentru a implementa eficient acesta functie se memoizeaza rezultatele intermediare folosind o tabela hash. Prezentam o scurta descriere a acestei proceduri in pesudocod:\r\n\r\n==code(cpp) |\r\nintreg numara(lungime, prefix)\r\n   daca numara(lungime, prefix) a mai fost apelat returneaza rezultatul stocat in hash; \r\n   daca lungime = 1 si prefix = \"\" returneaza K;\r\n   daca lungime = 1 si prefix = \"A\" sau \"B\" ... sau \"Z\" returneaza 1;\r\n   daca lungime = 1 returneaza 0; \r\n \r\n   rez = 0;\r\n   daca |prefix| < lungime sau (|prefix| = lungime si prefix se termina cu \"!\")\r\n      rez += numara(lungime-1, prefix[1..lungime-1]);\r\n\r\n   daca |prefix| < lungime sau (|prefix| = lungime si prefix se termina cu \"*\")\r\n      pentru i = 1, n-2 executa\r\n         rez += numara(i, prefix[1..i])*numara(n-i-1, prefix[i+1..n-i-1]);\r\n\r\n   daca |prefix| < lungime sau (|prefix| = lungime si prefix se termina cu \"+\")\r\n      pentru i = 1, n-2 executa\r\n         rez += numara(i, prefix[1..i])*numara(n-i-1, prefix[i+1..n-i-1]);\r\n\r\n   pastreaza valoarea rez in hash pentru numara(lungime, prefix);\r\n   returneaza rez;\r\nsfarsit functie\r\n==\r\n\r\nh2. \'Ograzi\':problema/ograzi\r\n\r\nh3. (problema usoara, clasele 11-12)\r\n\r\nProblema este una clasica de cautari ortogonale si se poate face usor o solutie in care se sorteaza dreptunghiurile si punctele dupa coordonata $x$, iar apoi se foloseste o linie de baleiere. Se proceseaza updateuri si querieruri pe un arbore de intervale in o dimensiune. Aceasta solutie are complexitate $O(M*lg N + N*lg N)$. S-au obtinut in jur de $70$ de puncte folosind asemenea abordari.\r\nPentru a obtine o solutie mai eficienta trebuia exploatata particularitatea problemei, adica faptul ca toate dreptunghiurile erau egale. Solutia autorului continea doi pasi: \r\n\r\n* Intai folosim grila de puncte de coordonate $(i*W+0.5, j*H+0.5)$ unde $i$ si $j$ sunt numere intregi. Orice dreptunghi din enunt contine exact un punct din aceasta grila. Vom folosi o tabela de dispersie (hash) ce grupeaza in perechi dreptunghiurile din intrare si punctele din grila interioare lor. \r\n* Pentru a determina daca un punct din cele $M$ este continut in vreun dreptunghi, ne uitam care sunt cele patru puncte din grila vecine acestuia, si vom gasi maxim patru dreptunghiuri asociate acelor 4 puncte din grila. Apoi testam incluziunea punctului nostru in fiecare dintre cele patru dreptunghiuri, astfel putem raspunde la orice test de incluziune in $O(1)$. \r\n\r\nComplexitatea toatala a algoritmului este $O(N + M)$. Felicitam pe Berzan Constantin care a folosit aceasta abordare si a fost singurul ce a luat punctaj maxim pe aceasta problema.\r\n\r\nh2. \'KPerm\':problema/kperm\r\n\r\nh3. (problema medie, clasele 11-12)\r\n\r\nFie $sigma$ o {$K$}-permutare cu $N$ elemente => pentru orice {$i$}, {$1 &le; i &le; N-K$} avem relatiile:\r\n\r\n* {$sigma{~i~} + sigma{~i~} + ... sigma{~i+K-1~}$} congruent cu $0$ ( mod $K$ )\r\n* {$sigma{~i+1~} + sigma{~i+2~} + ... sigma{~i+K~}$} congruent cu $0$ ( mod $K$ )\r\n\r\nScazand cele doua relatii, obtinem $sigma{~i~}$ congruent cu $sigma{~i+K~}$ ( mod {$K$} ).\r\nFie $N$ = {$C * K + R$}, {$0 &le; r < K$}.\r\nSe observa ca intr-o {$K$}-permutare nu conteaza decat resturile numerelor la impartirea cu $K$, si nu numerele propriu-zise. Deci putem privi o permutare in functie de cate resturi r sunt in permutare, pentru orice {$r$} de la $0$ la {$K-1$}. Se observa ca resturile de la $1$ la $R$ apar de exact {$C+1$} ori, in timp ce toate celelalte resturi apar de exact $C$ ori.\r\n\r\nI. {$N &ge; 2 * K$}, sau, echivalent {$C &ge; 2$}. Se observa ca in primele $C$ numere din permutarea care constituie o solutie nu putem pune acelasi rest de cel putin $2$ ori. Observatia este evidenta, deoarece, cum avem relatia $sigma{~i~}$ congruent cu $sigma{~i+K~}$ ( mod {$K$} ), atunci restul care ar aparea de 2 ori in primele $C$ numere ar aparea de cel putin {$2*C$} ori ( pe primele {$C*K$} pozitii ), dar avem maxim {$C+1$} resturi disponibile egale, si cum {$2*C > C+1$}, am ajuns la o contradictie.\r\nII. {$K &le; N < 2*K$}. In acest caz, resturile de la $1$ la $R$ apar de $2$ ori fiecare, iar toate celelalte resturi apar o singura data. Cum doar pozitiile de la $R+1$ la $C$ au un rest unic in permutare ( toate celelalte resturi apar pe exact doua pozitii de forma $i$ si $i + K$ ) => pe aceste pozitii trebuie sa punem toate resturile care apar o singura data. Este evident si ca in primele $R$ pozitii trebuie sa punem resturile diferite doua cate doua, pentru ca fiecare rest apare de doua ori si trebuie pus pe doua pozitii.\r\n\r\nDin ambele cazuri a rezultat ca pentru orice valori ale numerelor $N$ si $K$, o {$K$}-permutare trebuie sa respecte urmatoarele proprietati: \r\n\r\n* pe primele $K$ pozitii din permutare trebuie sa se gaseasca toate resturile {$0$}, {$1$}, ... {$K-1$}\r\n* resturile de la $1$ la $R$ trebuie sa fie asezate pe primele $R$ pozitii\r\n* pe fiecare pozitie $i$ incepand cu $K+1$ trebuie sa punem un numar care sa aiba restul din impartirea la $K$ egal cu restul impartii numarului de pe pozitia $i-K$ la {$K$}\r\n\r\nPentru $K$ par, {$K = 2p$}, cum {$0+1...+(2p-1)$} = {$p*(2p-1)$} si acest numar nu se divide cu {$2p$} pentru ca {$2p-1$} este impar => raspunsul este 0.\r\n\r\nPentru $K$ impar, {$K = 2p+1$}, cum {$0+1...+2p$} = {$p*(2p+1)$}, care este dizibil la {$(2p+1)$}, vom construi permutarea astfel:\r\n\r\n* fixam ordinea primelor $R$ resturi ( in total {$R!$} variante )\r\n* fixam ordinea celorlalte $K-R$ resturi ( in total {${@(K-R)!@}$} variante )\r\n* pentru fiecare rest din primele $R$ sunt $C+1$ pozitii pe care trebuie sa il asezam. Pentru fiecare rest putem pozitiona numerele atasate in {$(C+1)!$} variante, si, cum sunt $R$ resturi, avem {$[(C+1)!]^R^$} variante\r\n* pentru fiecare din celelalte resturi sunt $C$ pozitii pe care trebuie sa le asezam. Pentru fiecare rest putem deci pozitiona numerele atasate in {$C!$} variante, si, cum sunt $K-R$ resturi, avem {$(C!)^K-R^$} variante.\r\n\r\nPentru $K$ impar raspunsul este, dupa cum am demonstrat mai sus, {$(R!)$} * {${@(K-R)!@}$} * {$[(C+1)!]^R^$} * {$(C!)^K-R^$}.\r\n\r\nOBS. In relatia de mai sus nu are importanta daca {$R = 0$}, caci {$0! = 1$} si {$A^0^ = 1$}, pentru orice {$A$}. Deci demonstratia a fost facuta fara a restrange generalitatea.\r\n\r\n\r\nh2. \'Magazin\':problema/magazin\r\n\r\nh3. (problema grea, clasele 11-12)\r\n\r\nProblema se rezolva folosind metoda programarii dinamice. Ca prim pas vom precalcula niste informatii pentru fiecare culoar care vor fi folosite apoi in algoritmul de programare dinamica. Astfel pentru un culoar $i$ exista 4 scenarii care ne intereseaza:\r\n\r\n* se face un pas de distanta $D$ din coltul de sus al unui culoar adiacent la coltul de sus al culoarului $i$, se iau toate produsele de pe culoar incepand de sus si se revine la coltul de jos al culoarului $i$\r\n* se face un pas de distanta $D$ din coltul de sus al unui culoar adiacent la coltul de sus al culoarului $i$, se iau toate produsele de pe culoar incepand de sus si se revine la coltul de sus al culoarului $i$\r\n* se face un pas de distanta $D$ din coltul de jos al unui culoar adiacent la coltul de jos al culoarului $i$, se iau toate produsele de pe culoar incepand de jos si se revine la coltul de jos al culoarului $i$\r\n* se face un pas de distanta $D$ din coltul de jos al unui culoar adiacent la coltul de jos al culoarului $i$, se iau primele $k$ produse de pe culoar incepand de jos si se revine la coltul de jos al culoarului $i$, se face un pas de distanta $D$ din coltul de sos al unui culoar adiacent la coltul de sos al culoarului $i$, se ia restul de produse de pe culoar incepand de sus si se revine la coltul de sus al culoarului $i$\r\n\r\nSe observa ca primul tip de scenariu (cat si cel simetric) are mereu un cost constant, si anume $D+M+1$. Asadar, se vor precalcula informatii doar pentru ultimele 3 tipuri. Aceste informatii se pot calcula usor sortand produsele de pe fiecare culoar si parcurgandu-le (in cazul ultimului scenariu). Complexitatea acestui pas este $O(P*lgP + N)$.\r\nVom realiza acum algoritmul de programare dinamica construind traseul optim culoar cu culoar, de la $1$ la $N$. Se observa ca exista $6$ stari care ne intereseaza la un culoar $i$:\r\n\r\n* $0$ - costul unui traseul optim care trece prin coltul de sus al culoarului $i$, fara a trece prin coltul de jos al culoarului $i$\r\n* $1$ - costul unui traseul optim care trece prin coltul de sus al culoarului $i$, care trece prin coltul de jos al culoarului $i$, iar traseul este conex\r\n* $2$ - costul unui traseul optim care trece prin coltul de sus al culoarului $i$, care trece prin coltul de jos al culoarului $i$, iar traseul *nu* este conex, adica este format din doua trasee care se vor uni la un moment dat (la un culoar $> i$)\r\n* $3$ - costul unui traseul optim care trece prin coltul de jos al culoarului $i$, fara a trece prin coltul de sus al culoarului $i$\r\n* $4$ - costul unui traseul optim care trece prin coltul de jos al culoarului $i$, care trece prin coltul de sus al culoarului $i$, iar traseul este conex\r\n* $5$ - costul unui traseul optim care trece prin coltul de jos al culoarului $i$, care trece prin coltul de sus al culoarului $i$, iar traseul *nu* este conex, adica este format din doua trasee care se vor uni la un moment dat (la un culoar $> i$)\r\n\r\nPentru a calcula oricare din cele $6$ stari ne uitam la cele $6$ stari ale culoarului $i-1$. In total, vor exista $6*6 = 36$ de tranzitii; fiecare se poate calcula in $O(1)$ folosind informatiile precalculate la primul pas. Cele $36$ de tranzitii se pot determina usor pe foaie, trasand cateva exemple. Complexitatea acestui pas este $O(N)$, deci rezolvare este in final $O(P*lg P + N)$.\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',961,'public',NULL,NULL),('blog/infoarena-in-adevarul','infoarena in Adevarul','2007-03-06 08:41:15','2009-02-02 23:45:21','A aparut un \'articol\':http://www.adevarulonline.ro/articole/fostii-olimpici-ii-antreneaza-pe-concurentii-de-la-olimpiade/305061 despre infoarena in ziarul \'Adevarul\':http://www.adevarulonline.ro.\r\n\r\nVezi si \'prima pagina\':doi-la-suta?infoarena-adevarul-prima-pagina.pdf.',13,'public',NULL,NULL),('utilizator/nebhotep','Profil Nebhotep','2007-03-06 11:54:06','2007-03-06 11:54:06','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6217,'public',NULL,NULL),('runda/preoni2007_runda4_1112/clasament','Clasament preoni2007_runda4_1112','2007-03-07 12:12:40','2007-03-07 12:12:40','h1. Clasament ==roundparam(round_id=\"preoni2007_runda4_1112\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda4_1112\")==',1,'round: preoni2007_runda4_1112',NULL,NULL),('utilizator/ln_anila','Profil ln_anila','2007-03-07 06:12:28','2007-03-07 06:12:28','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6224,'public',NULL,NULL),('blog/am-recalculat-rating-urile','Am recalculat rating-urile','2007-02-22 04:20:53','2007-02-22 04:23:11','Am recalculat rating-urile, ca urmare a punctajelor obtinute la ultimele concursuri: \'Winter Challenge\':winter-challenge-1 si \'Runda #2 din preONI\':preoni-2007/runda-2.\r\n\r\n*{\'Vezi clasamentul\':clasament-rating}*\r\nCiteste \'despre rating\':documentatie/rating',13,'protected',NULL,NULL),('preoni-2006/runda-3/solutii','Solutii preONI 2006 - Runda a 3-a','2006-01-21 00:00:00','2007-12-14 23:32:17','h1. Solutii preONI 2006 - Runda a 3-a\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa infoarena_)\r\n\r\nRunda a 3-a concursului preONI 2006 s-a incheiat. Acest articol va prezinta solutiile oficiale ale celor 7 probleme propuse precum si cateva aprecieri pe marginea concursului.\r\n\r\nS-a incheiat si cea de-a treia runda a concursului preONI 2006. Ca de obicei, la fiecare grupa au existat 3 probleme cu nivele diferite de dificultate: usor, mediu, greu. Spre deosebire de runda precedenta, problemele au fost ceva mai accesibile facand mai usoara obtinerea unui punctaj mediu pentru participantii de la toate cele trei grupe. Salutam primul punctaj maxim realizat de Cosmin Gheorghe, participant la clasa a IX-a. Desi nivelul de dificultate al problemelor este unul ridicat (comparativ cu cel de la nationale), nu putem sa nu remarcam faptul ca, la clasa a X-a, nivelul de pregatire al concurentilor este ceva mai scazut fata de celelalte grupe, in conditiile in care olimpiadele se apropie. Ii sfatuim pe toti participantii sa se pregateasca si mai consistent de acum incolo, utilizand si platforma pe care le-o pune la dispozitie InfoArena.\r\n\r\nInainte de ultima runda, la clasa a IX-a, avem deja doi concurenti care s-au detasat de pluton in persoana lui Gheorghe Cosmin si Tataroiu Bogdan, lupta fiind inca acerba pentru ultimele locuri calificabile. La clasa a X-a avem un clasament destul de echilibrat, cu elevii clasati primii fara prea mari emotii inainte de ultima runda, dar cu multe semne de intrebare pentru cei clasati pe locurile 8-10. La clasele XI-XII avem o batalie frumoasa, cu multe punctaje peste $300$ si o situatia foarte confuza catre ultimele locuri calificabile.\r\n\r\nLe uram tutoror succes si fie ca cei mai buni sa mearga in finala!\r\n\r\nh2. Numarare triunghiuri\r\n\r\nh3. (problema simpla, clasa a 9a)\r\n\r\nPentru a rezolva problema trebuie cunoscuta conditia de existenta a unui triunghi cand avem lungimile segmentelor. Fie {$a$}, {$b$}, $c$ lungimile laturilor in ordine nedescrescatoare. Se poate forma un triunghi cu ele doar daca $a + b &ge; c$ (este usor de intuit de ce).\r\n\r\nAcum putem rezolva problema in $O(N^3^)$ verificand toate triunghiurile posibile care s-ar putea forma si numarandu-le doar pe cele ce respecta conditia de mai sus. Aceasta solutie ar trebui sa ia in jur de $75$ de puncte.\r\n\r\nPentru a rezolva mai eficient problema este necesar sa sortam nedescrescator vectorul cu lungimile segmentelor. Acum putem fixa segmentele $a$ si $b$ si putem cauta binar pozitia maxima din vector a segmentului $c$ care respecta {$a + b &ge; c$}. Deci numarul de triunghiuri care se pot forma avand primele doua laturi $a$ si $b$ este egal cu numarul de elemente din vector de dupa $b$ si pana la $c$ (pentru fiecare triunghi luam segmentele {$a$}, {$b$}, $c$ in ordine crescatoare dupa indicii din vector, evitand astfel numararea unui triunghi de doua ori). Deci complexitatea acestei solutii este $O(N^2^ log N)$ si ar fi luat fara probleme punctajul maxim.\r\n\r\nPutem imbunatati solutia de mai sus la o complexitate {$O(N^2^)$}, eliminand cautarea binara. Aceasta solutie va lasam sa o descoperiti voi.\r\n\r\nh2. Divizori primi\r\n\r\nh3. (problema medie, clasa a 9a)\r\n\r\nFiind vorba de maxim $1.000.000$ numere se poate calcula pentru fiecare in parte cati divizori primi are. Pentru acest lucru se foloseste ciurul lui Erathostene si se construieste vectorul {$ndp{~i~}$} - numarul de divizori primi ai lui {$i$}. Parcurgem numerele din $1$ in $1$ si in momentul in care am dat peste un numar care are $0$ divizori primi pana in acest moment inseamna ca am gasit un nou numar prim si vom actualiza vectorul $ndp$ pentru toti multiplii lui si implicit pentru el (numarul fiind propriul sau divizor). Apoi se construieste o matrice $sol{~i,j~}$ care retine care este cel mai mare numar mai mic sau egal cu $i$ cu $j$ divizori primi (adica exact raspunsurile pentru problema noastra). Pentru a construi linia $i$ se copiaza linia $i-1$ si se actualizeaza {$sol{~i,ndp{~i~}~}=i$}.\r\n\r\nPentru mai multe detalii despre cum functioneaza ciurul lui Erathostene puteti accesa \"articolul\":http://infoarena.ro/Ciurul-lui-Erathostene.\r\n\r\nh2. Subsir 2\r\n\r\nh3. (problema grea clasa a 9a, problema medie clasa a 10a, problema usoara clasele 11-12)\r\n\r\nProblema poate fi considerata asemanatoare cu cea a celui mai lung subsir crescator, avand o rezolvare similara de complexitatea $O(N^2^)$ folosind metoda programarii dinamice.\r\n\r\nSe vor construi doi vectori:\r\n\r\n* $A{~i~}$ = lungimea celui mai scurt subsir crescator maximal care incepe cu pozitia $i$\r\n* $T{~i~}$ = urmatorul element dupa pozitia $i$ in cel mai scurt subsir crescator maximal care incepe cu $i$ (pentru reconstiutire)\r\n\r\nPentru fiecare {$i$}, se va cauta un $j > i$ astfel incat {$V{~i~} &le; V{~j~}$} (unde $V$ este vectorul de numere) si se alege acela cu $A{~j~}$ minim, $A{~i~}$ devenind {$A{~j~}+1$}, iar $T{~i~}$ devine {$j$}. Daca nu exista nici un {$j$}, $A{~i~}$ se initializeaza cu $1$ si $T{~i~}$ cu {$i$}.\r\n\r\nCa sirul construit sa fie maximal trebuie ca atunci cand verificam {$j$}-urile pentru un $i$ fixat, {$j$}-ul respectiv sa fie \"dominant\", in sensul ca sa nu existe un $i < k < j$ astfel incat {$V{~i~} &le; V{~k~} &le; V{~j~}$}, deoarece sirul construit cu primul element in $i$ si al doilea in $j$ ar putea fi extins inserand $k$ intre $i$ si {$j$}. Verificarea pentru acest $k$ se poate face in {$O(N)$}, obtinand o solutie $O(N^3^)$ care ar fi adus {$50-60p$}. Pentru a face verificarea in {$O(1)$}, facem observatia ca ne intereseaza doar acel $V{~k~}$ minim care este &ge; {$V{~i~}$}. Pe masura ce se avanseaza cu variabila {$j$}, se pastreaza o variabila {$min$}, reprezentand minimul dintre valorile $V{~j~}$ parcurse pana acum, care sunt &ge; {$V{~i~}$}.\r\n\r\nAstfel, cand se ajunge la un {$j$}, se verifica inainte daca {$V{~j~} < min$} (conditie necesara pentru a construi un sir maximal). Un ultim detaliu in solutie este obtinerea solutiei minime din punct de vedere lexicografic. Cand se selecteaza {$j$}-ul pentru fiecare {$i$}, pe langa faptul ca se alege acela cu $A{~j~}$ minim, in caz de egalitate se va alege acela cu valoarea $V{~j~}$ minima. Selectarea este corecta deoarece nu vor exista {$j1$}, $j2$ cu $A{~j1~}$ si $A{~j2~}$ minim , iar {$V{~j1~} = V{~j2~}$}.\r\nProblema se poate rezolva mai bine intr-o complexitate $O(N*lg^2^ N)$ folosind structuri de date avansate, astfel transformandu-se intr-o problema de clasele 11-12 grea, sau chiar o problema de finala. Lasam aceasta rezolvare ca exercitiu pentru cititor.\r\n\r\nh2. Sum\r\n\r\nh3. (problema usoara, clasa a 10a)\r\n\r\nVom face o prima observatie:\r\n\r\n* $(n, d) = 1 <=> (n, n - d) = 1, (n, n + d) = 1$\r\n\r\nFie {$a = phi (n)$}, indicatorul lui Euler. Fie $b$ numarul de numere prime cu $n$ cuprinse intre $n$ si {$2 * n$}.\r\nDeoarece {$(n, d) = 1 <=> (n, n + d) = 1, a &le; b$}. Deoarece {$(n, d) = 1 <=> (n, n - d) = 1, b &le; a => b = a$}. Fie {$x{~1~}, x{~2~}, .. x{~a~}$} numerele $< n$ si prime cu $n$ => numerele cuprinse intre $n$ si $2 * n$ si prime cu $n$ vor fi {$x{~1~} + n, x{~2~} + n, .. x{~a~} + n$}.\r\n\r\nConform observatiei facute, $(n, n - x{~1~}) = 1, (n, n - x{~2~}) = 1, .. (n, n - x{~a~}) = 1$ =>\r\n\r\n$x{~a~} = n - x{~1~} <=> x{~1~} + x{~a~} = n$\r\n$x{~a-1~} = n - x{~2~} <=> x{~2~} + x{~a-1~} = n$\r\n...\r\n$x{~1~} = n - x{~a~} <=> x{~a~} + x{~1~} = n$\r\n\r\nFie $S1$ suma numerelor prime cu $n$ si mai mici ca {$n$}, fie $S2$ suma numerelor prime cu {$n$}, cuprinse intre $n$ si {$2 * n$}.\r\nAdunand cele a egalitati, obtinem $2 * S1 = a * n$ => {$S1 = (a * n) / 2$}.\r\n\r\n$S2 = a * n + S1$ => {$S1 + S2 = 2 * a * n$}.\r\n\r\nSe foloseste o singura data ciurul lui Erathostene pentru a determina functia phi pentru toate intrebarile. Se poate consulta \"articolul\":http://infoarena.ro/Ciurul-lui-Erathostene despre cirulul lui Erathostene.\r\n\r\nO alta solutie, propusa de Bogdan A. Stoica, se bazeaza pe principul includerii si excluderii. Din enuntul problemei ne dam seama ca suma ceruta este suma tuturor numerelor $z$ cu proprietatea ca {$cmmdc(z, x) = 1$}. Pentru a afla aceste numere este de ajuns sa observam ca $cmmdc(z, x) != 1$ daca si numai daca exista cel putin un $p{~i~} = q{~j~}$ unde {$z = p{~1~}^e{~1~}^&#0042; ... &#0042;p{~n~}^e{~n~}^$}, iar {$x = q{~1~}^f{~1~}^&#0042; ... &#0042;q{~m~}^f{~m~}^$}. Fie doua astfel de numere {$p{~i~} = q{~j~}$}. Noi trebuie sa afla suma tuturor numerelor care se divid cu $p{~i~}$ si sunt in intervalul [{$0, 2*x$}]. Aceste numere sunt : {$p{~i~}, 2&#0042;p{~i~}, ..., k&#0042;p{~i~}$}, {$0 < k &le; [2&#0042;x/p{~i~}]$}. Suma acestor numere se poate scrie ca {$p{~i~} + ... + k&#0042;p{~i~}$}, adica pi(1+...+k) adica {$p{~i~}&#0042;k(k+1)/2$}. De aici suntem tentati sa credem ca suma ceruta (fie aceasta {$S$}) este $S$ = {$x(2&#0042;x-1) - p{~1~}&#0042;k{~1~}&#0042;(k{~1~}+1)/2 - .... - p{~n~}&#0042;k{~n~}&#0042;(k{~n~}+1)/2$}. La o citire mai atenta observam ca am scazut unele de doua ori (cele care se divid si cu $p{~1~}$ si cu {$p{~2~}$}, de exemplu) si nu am scazut deloc alte numere care au un divizor comun cu $x$ mai mare decat $1$ (cele care se divid simultan cu {$p{~1~}$}, $p{~2~}$ si {$p{~3~}$}, de exemplu). Astfel, aplicand principiul includerii si excluderii putem schita formula finala : {$S = x&#0042;(2x-1) - p{~1~}&#0042;k{~1~}&#0042;(k{~1~}+1)/2 - ... + p{~1~}&#0042;p{~2~}&#0042;k\'{~1~}(k\'{~1~}+1)/2 + ... - p{~1~}&#0042;p{~2~}&#0042;p{~3~}&#0042;k\'\'{~1~}(k\'\'{~1~}+1)/2 + ...$}, adica vom scadea toti termenii care se obtin prin inmultirea a unui numar impar de factori primi si vom aduna restul. Aceasta solutie obtine in jur de $80$ de puncte pe restul testelor depasind timpul de executie.\r\n\r\nh2. Pavare 2\r\n\r\nh3. (problema grea, clasa a 10a)\r\n\r\nProblema se rezolva cu programare dinamica. Utilizam urmatoare structura de date:\r\n\r\n* $V[i][j]&#0091;0]$ = numarul de posibilitati pentru a pava $i$ metri astfel incat primele $j$ placi sa fie albe\r\n* $V[i][j]&#0091;1]$ = numarul de posibilitati pentru a pava $i$ metri astfel incat primele $j$ placi sa fie negre\r\n\r\nRelatiile de recurenta sunt acum usor de dedus. Odata calculata matricea putem raspunde foarte usor primei cerinte, facand suma $V[N][i]&#0091;0]$ (pentru {$1 &le; i &le; A$}) si $V[N][i]&#0091;1]$ pentru ({$1 &le; i &le; B$}).\r\n\r\nPentru a 2-a cerinta incercam sa construim a {$K$}-a segventa lexicografica de la inceput catre sfarsit. Astfel, la fiecare pas incercam sa punem o segventa de tipul \'{$0...01$}\' care sa contina un numar maxim de \'{$0$}\'. Daca la pasul curent nu putem pune nici un \'{$0$}\' atunci vom pune o secventa de tipul \'{$1..1$}\' care sa contina un numar minim de {$1$}. Numarul de \'{$0$}\'-uri sau de \'{$1$}\' pe care il punem il vom calcula cu ajutorul matricei precalculate la prima cerinta. Astfel, daca putem pune $p$ de \'{$0$}\' inseamna ca numarul de posibilitati pentru a completa restul solutiei daca punem cel putin $p$ de \'{$0$}\' la inceput este mai mare sau egal cu {$K$}. Alegem cel mai mare numar $p$ cu proprietatea de mai sus. Daca $p$ nu exista, incercam sa punem cat mai putini \'{$1$}\' in aceeasi maniera. Continuam apoi cu restul secventei, iar din $K$ scadem numarul de solutii peste care am \"sarit\".\r\n\r\nh2. Count\r\n\r\nh3. (problema medie, clasele 11-12)\r\n\r\nInainte de a prezenta solutia, enumeram cateva propietati ale grafurilor planare care se vor dovedi utile mai departe:\r\n\r\n# Orice graf planar contine un nod cu grad mai mic decat $6$\r\n# Numarul maxim de muchii pe care il poate avea un graf planar este {$3 * N - 6$}, unde $N$ este numarul de noduri. Asadar $O(M)=O(N)$ ({$M$} fiind numarul de muchii).\r\n# Grafurile planare nu contin clici (subgrafuri complete) cu mai mult de $4$ noduri (nu se poate desena in plan o clica de $5$ noduri fara a intersecta muchiile acesteia).\r\n\r\nConsecinta imediata a propietatii numarul $3$ este ca intr-un graf planar vom avea clici de maxim $4$ noduri. Cum cazurile in care clica cu numar maxim de noduri este compusa dintr-unul sau doua noduri este banal, ne vom concentra atentia pe cazurile in care avem clici de $3$ sau $4$ noduri.\r\n\r\nStiind acest lucru, un algoritm $O(N^2^)$ este usor de obtinut (si multi dintre concurenti au reusit acest lucru pentru $~70$ de puncte). Ideea este urmatoarea:\r\n\r\n* Cazul clicilor de $3$ noduri: se numara toate clicile care includ o anumita muchie incercand sa construim un triunghi impreuna cu fiecare nod din graf. Asadar pentru fiecare muchie, incercam cu fiecare nod (mai putin cele doua capete ale muchiei) sa construim o clica de $3$ noduri. Complexitatea este $O(M*N) = O(N^2^)$ (folosindu-ne de propietatea {$2$}). De altfel problema determinarii numarului de triunghiuri (clici de $3$ noduri) intr-un graf, de aceasta data general, este cunoscuta si cea mai rapida rezolvare cunoscuta de noi este $O(M*N / 32)$ daca pastram matricea de adiacenta pe biti - in total $O(N^2^ / 32)$ memorie. Va lasam pe voi sa descoperiti aceasta solutie iar daca nu reusiti cereti ajutor pe forum si vom completa acest articol.\r\n* In cazul clicilor de $4$ noduri, tot ce avem de facut este sa selectam doua muchii si sa vedem daca cele $4$ capete ale lor formeaza o clica (presupunda ca avem $4$ capete distincte). Acest algoritm are complexitatea $O(M^2^) = O(N^2^)$\r\n\r\nCum determinam, rapid, daca doua noduri sunt vecine? Solutia cea mai usoara este sa pastram matricea de adiacenta (eventual pe biti) si putem raspunde in $O(1)$ la astfel de intrebari dar memoria este {$O(N^2^)$}. O alta idee care reduce marimea memoriei la $O(M)$ este sa pastram listele de adicenta sub forma de hash-uri in loc de liste simple inlantuite (pentru cei care nu sunt familiari cu aceasta structura de date ii sfatuim sa citeasca articolele de pe devnet - sunt interesante si educative). Asadar, folosind hash-urile, memoria ramane $O(M)$ dar putem afla rapid (aproape {$O(1)$}) daca doua noduri sunt vecine. In C++ aceasta structura de date este deja implementata sub numele de map, desi un query are complexitate logaritmica.\r\n\r\nSa trecem la solutia {$O(N)$}. Evident, vom folosi propietatea $1$ (singura nefolosita pana acum). Din moment ce avem un nod cu grad mai mic decat {$6$}, il identificam, generam toate clicile care il contin printr-un backtracking (dat fiind faptul ca sunt maxim $5$ vecini) si il scoatem din graf. Graful rezultat este si el planar si cautam iar nodul cu grad mai mic decat {$6$}, etc. Evident, nu vom face cautarea nodului de fiecare data - asta ar duce la un {$O(N^2^)$}, ci in momentul in care stergem un nod, verificam daca gradele vecinilor sai au scazut sub $6$ si apelam o procedura recursiva cand gasim un astfel de vecin (un soi de $DFS$ in graful dat). Dat fiind faptul ca backtracking-ul ruleaza in timp constant (desi e mare constanta) algoritmul acesta va avea complexitatea $O(N)$ - presupunand ca putem raspunde in $O(1)$ folosind hashurile daca doua noduri sunt vecine. Solutia noastra foloseste map-urile din STL asadar are complexitatea $O(N*logN)$ cu o constanta considerabila {$(~100)$}.\r\n\r\nSolutia de mai sus suporta multiple optimizari asupra factorului constant daca efectuam niste prepocesari inainte de algoritmul descris. Asadar, putem prepocesa pentru toate grafurile de maxim $6$ noduri in care exista un nod conectat la toate celelalte, care este clica maxima si cate sunt. Nu sunt mai mult de $2^12^$ asemenea grafuri, deci prepocesarea va rula instantaneu. Avand aceasta informatie prepocesata, cand eliminam un nod din graful planar, in loc sa facem backtracking pentru a afla clicile maximale, interogam tabelul cu valorile prepocesate, optimizand factorul constant foarte mult (ajunge {$~6$}). Totusi, nu era necesara implementarea acestor optimizari, din moment ce problema era media setului.\r\n\r\nh2. Cowfood\r\n\r\nh3. (problema grea, clasele 11-12)\r\n\r\nProblema este bazata pe principiul includerii si excluderii. Constrangerile relativ mici ale problemei nu ar fi trebuit sa va pacaleasca sa incercati o cautare exhaustiva, intrucat aceasta ar fi obtinut numai $20-30%$ din punctaj.\r\n\r\nInainte de a trece la explicarea problemei, sa ne amintim principiul includerii si excluderii.\r\n\r\n{$&#0124;A{~1~} U A{~2~} U ... U A{~n~}&#0124; =$}\r\n{$&#0124;A{~1~}&#0124; + &#0124;A{~2~}&#0124; + ... + &#0124;A{~n~}&#0124;$}\r\n{$- &#0124;A{~1~} &#8745; A{~2~}| - |A{~2~} &#8745; A{~3~}| - ...$} (toate perechile)\r\n{$+ &#0124;A{~1~} &#8745; A{~2~} &#8745; A{~3~}| + ...$} (toate tripletele)\r\n{$...$}\r\n{$+ (-1)^(n-1)^ &#0124;A{~1~} &#8745; A{~2~} &#8745; ... &#8745; A{~n~}&#0124;$}\r\n\r\nCum va fi folosit acesta? Vom calcula solutia ca fiind &#0124;multimea tuturor experimentelor valide&#0124; - &#0124;multimea experimentelor valide care sigur vor esua&#0124;. Sa notam aceasta multime de experimente cu {$F$}. Pentru orice experiment {$X$}, vom nota $f{~X~}$ = multimea tutoror experimentelor care vor esua conform experimentului {$X$}.\r\n\r\nAstfel, pentru un experiment $A$ de forma ({$a{~1~}, a{~2~}, ..., a{~K~}$}) si orice experiment $B$ = ({$b{~1~}, b{~2~}, ..., b{~K~}$}) cu {$a{~1~} &le; b{~1~}$}, {$a{~2~} &le; b{~2~}$}, ..., {$a{~K~} &le; b{~K~}$}, $B$ apartine {$f{~A~}$}.\r\n\r\nIn acest moment putem sa ne dam seama de solutie\r\n$&#0124;F&#0124; = &#0124;f{~E{~1~}~} U f{~E{~2~}~} U ... U f{~E{~N~}~}&#0124;$, care - conform principiului includerii si excluderii - este egal cu\r\n\r\n{$&#0124;f{~E{~1~}~}&#0124; + &#0124;f{~E{~2~}~}&#0124; + ... + &#0124;f{~E{~N~}~}&#0124;$}\r\n{$- &#0124;f{~E{~1~}~} &#8745; f{~E{~2~}~}| - |f{~E{~1~}~} &#8745; f{~E{~3~}~}| - ...$} (toate perechile)\r\n{$+&#0124;f{~E{~1~}~} &#8745; f{~E{~2~}~} &#8745; f{~E{~3~}~}&#0124; ...$}(toate tripletele)\r\n{$...$}\r\n{$+(-1)^n-1^ &#0124;f{~E{~1~}~} &#8745; f{~E{~2~}~} &#8745; ... &#8745; f{~E{~N~}~}&#0124;$}\r\n\r\nCe reprezinta intersectia (\"&#8745;\") in acest context?\r\nDaca $A = (a{~1~}, a{~2~}, ..., a{~K~})$ si {$B = (b{~1~}, b{~2~}, ..., b{~K~})$}, $A &#8745; B$ va fi multimea ce contine toate experimentele despre care se stie cu siguranta ca vor esua, atat conform lui $A$ cat si lui {$B$}. Altfel spus, $A &#8745; B$ = multimea experimentelor care vor esua conform {$(max(a{~1~}, b{~1~}), max(a{~2~}, b{~2~}), ..., max(a{~K~}, b{~K~}))$}.\r\n\r\nUn ultim lucru care trebuie obinut este calcularea lui |f{~X~}| pentru orice {$X = (x{~1~}, x{~2~}, ... x{~K~})$}. Pentru a obtine un experiment esuat, putem incrementa toate valorile x{~i~} atata timp cat suma lor este &le; {$S$}. Astfel avem |f{~X~}| = {$m(S - (x{~1~} + x{~2~} + ... + x{~K~}), K)$}, unde $m(i, j)$ reprezinta numarul de posibilitati de a aranja cel mult $i$ bile identice in $j$ cutii diferite.\r\n\r\nAceasta se calculeaza simplu folosind recurenta care nu va fi demonstrata aici\r\n\r\n$m(i, j - 1) = p(i, j) = p(i - 1, j) + p(i, j - 1), i, j > 0$\r\n$m(i, 0) = 1$\r\n$m(0,j) = 1$ \r\n\r\ncu $p(i, j)$ = numarul de posibilitati de a aranja exact $i$ bile identice in $j$ cutii diferite. Valorile $m(i, j)$ se preproceseaza la inceput intr-o matrice, in timp {$O(K*S)$}.\r\n\r\nO implementare bruta a problemei va duce la complexitatea $O(K*S + 2^N^*N*K)$, dar aceasta ar obtine numai $60%$ din punctajul maxim. O implementare inteligenta folosind preferabil o functie recursiva care exploreaza toate submultimile celor $N$ experimente si la fiecare pas actualizeaza solutia in $O(K)$ obtine cu usurinta $100$ de puncte. Complexitatea sa este {$O(K*S + 2^N^*K)$}.\r\n\r\n',1,'public',NULL,NULL),('documentatie/imbunatatire-teste','Imbunatatire teste','2007-02-19 01:41:36','2007-03-10 14:04:08','h1. Imbunatatire teste\r\n\r\nPagina a fost mutata \'aici\':implica-te/imbunatatire-teste.',13,'public',NULL,NULL),('preoni-2007/runda-2/solutii','Solutii preONI 2007, Runda 2','2007-02-18 14:08:40','2007-06-27 21:33:46','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Solutii Runda 2\r\n\r\nh2. \'Amlei\':problema/amlei \r\n\r\nh3. (problema usoara, clasa a 9-a, clasa a 10-a)\r\n\r\nPrimul pas al algoritmului este eliminarea conjunctiilor elementare care se repeta, deoarece $A$ OR $A$ = $A$. In continuare, se observa usor ca daca o conjunctie elementara apare doar intr-una din formule, distributia variabilelor care o face adevarata va conduce la rezultate diferite. Asadar, formulele sunt echivalente daca si numai daca contin aceleasi conjunctii elementare, facand abstractie de ordinea termenilor.\r\n\r\nProblema se poate rezolva astfel sortand termenii fiecarei conjunctii si conjunctiile dupa un criteriu oarecare.\r\n\r\nh2. \'Tricouri\':problema/tricouri\r\n\r\nh3. (problema medie, clasa a 9-a)\r\n\r\nDupa ce citim cele $N$ numere din fisierul de intrare, vom realiza o preprocesare ({_filtrare_}) in urmatorul mod: \r\n{$M{~i, j~}$} va fi o lista ( implementata fie ca vector, fie ca lista liniara simplu inlantuita ) care va retine in ordine descrescatoare numerele din fisierul de intrare care dau restul $j$ la impartirea cu {$i$}. Deoarece pentru fiecare interogare numarul de termeni este cel mult 5, este suficient ca aceasta lista sa retina cel mult 5 termeni. Astfel, in momentul in care citim un element de valoare {$x$}, pentru fiecare $i$ de la 2 la 20, vom introduce elementul in lista {$M{~i, x mod i~}$} daca si numai daca aceasta lista nu contine inca 5 termeni sau $x$ este mai mare decat minimul din lista ( in acest ultim caz $x$ va fi copiat peste acest minim, asigurand ca in lista vor ramane cele mai mari numere posibile ).\r\nIn momentul in care citim o interogare de forma {$K P$}, vom genera toate posibilitatile de resturi la impartirea cu $P$ ale primelor $K-1$ numere din suma, al {$K$}-lea rest fiind unic determinat. Pentru o astfel de configuratie de resturi stim in timp {$O(1)$} care este cea mai mare suma ( daca exista ) a unor elemente care sa aiba resturile astfel stabilite, prin utilizarea informatiilor din tabloul {$M$}. \r\nDe exemplu, daca $K = 3$ si {$P = 4$}, pentru primele doua resturi stabilite ale primelor doua numere ( sa zicem ca aceste resturi au valoarea $3$ si respectiv {$2$}), restul celui de-al treilea numar la impartirea cu $4$ nu poate fi decat $3$. Acum, folosind tabloul {$M$} calculat anterior, trebuie sa stim care sunt cele mai mari doua numere care dau la impartirea cu $4$ restul $3$ si care este cel mai mare numar care la impartirea cu $4$ da restul {$2$}. Aceasta suma poate fi calculata deci in {$O(1)$}. Vom genera ( prin metoda backtracking sau folosind mai multe for-uri imbricate ) toate configuratiile posibile de resturi, si o vom retine pe cea care genereaza suma cea mai mare, suma pe care ulterior o vom afisa. Complexitatea finala este deci {$O(N + M * P^K-1^)$}, care asigura punctajul maxim, folosind nivelul cunostintelor de clasa a IX-a.\r\n\r\nO alta solutie mai eleganta dar care depaseste cunostintele de clasa a IX-a ar fi cea care foloseste programarea dinamica in modul urmator: se noteaza cu {$D{~i,j,r~}$} care este suma maxima folosind $i$ numere din primele $j$ resturi posibile la impartirea cu $P$ si pana in momentul curent sa avem format restul {$r$}. Se construieste acest tablou in mod {_bottom-up_}. Raspunsul se va afla in {$D{~K,P-1,0~}$}. Complexitatea unui astfel de algoritm este {$O(N + M * K^2^ * P^2^)$}, care de asemenea obtine 100 de puncte.\r\n\r\nh2. \'Zone\':problema/zone\r\n\r\nh3. (problema grea, clasa a 9-a)\r\n\r\nSe observa ca daca stim linia {$L{~1~}$} si suma asociata zonei {$1$}, coloana {$C{~1~}$} este unic determinata deoarece elementele matricii initiale erau pozitive: pornind cu submatricea de colturi {$(1, 1)$} si {$(L, 1)$}, va trebui sa crestem $C{~1~}$ pana cand suma submatricii de colturi {$(1, 1)$} si {$(L{~1~}, C{~1~})$} va deveni cat am stabilit initial. Cum suma submatricii de colturi {$(1, 1)$} si {$(L{~1~}, X)$} este mai mica decat suma submatricii de colturi {$(1, 1)$} si {$(L{~1~}, X+1)$}, cautarea coloanei {$C{~1~}$} poate fi realizata prin cautare binara. Dupa ce am determinat {$C{~1~}$}, stabilim care dintre cele 8 sume ramase este valoarea zonei {$2$} si determinam in mod similar valoarea coloanei {$C{~2~}$}. Apoi stabilim care dintre cele 7 sume ramase este valoarea pe care o vom asocia zonei {$4$} si determinam si {$L{~2~}$}. Pentru un cvadruplu astfel determinat, {$L{~1~}$}, {$C{~1~}$}, {$L{~2~}$} si {$C{~2~}$}, vom determina toate cele 9 sume care se formeaza si daca ele sunt egale cu sumele impuse initial, atunci inseamna ca avem o solutie. Dintre toate solutiile posibile o vom afisa in final pe cea care respecta conditiile de minimalitate enuntate.\r\n\r\nIn momentul in care cautam binar o linie sau o coloana va trebui sa aflam suma pentru o anumita submatrice. Pentru a realiza acest lucru eficient, vom construi de la inceput matricea de sume partiale {$S$}, unde {$S{~i,j~}$} reprezinta suma elementelor din submatricea care are coltul stanga-sus in {$(1, 1)$} si coltul dreapta-jos in {$(i, j)$}. Astfel, suma submatricii de colturi {$(x{~1~}, y{~1~})-(x{~2~}, y{~2~})$} va fi egala cu {$S{~x2,y2~}$} - {$S{~x1-1,y2~}$} - {$S{~x2,y1-1~}$} + {$S{~x1-1,y1-1~}$}.\r\n\r\nProblema este astfel rezolvata in intregime. Complexitatea algoritmului este {$O(N^2^)$}.\r\n\r\nh2. \'Plantatie\':problema/plantatie\r\n\r\nh3. (problema medie, clasa a 10-a)\r\n\r\nO prima idee de solutie ar fi sa construim o matrice $A[i][j][k]$ = elementul de valoare maxima dintr-un patrat cu coltul stanga-sus pe linia $i$ si coloana $j$ si latura $k$. Aceasta  matrice se poate calcula in $O(N^3^)$ astfel:\r\n$A[i][j][k] = max(A[i][j][k-1], A[i+1][j][k-1], A[i][j+1][k-1], A[i+1][j+1][k-1])$\r\nFiecare intrebare poate fi rezolvata in $O(1)$, dar constructia matricei $A$ nu se va incadra in timp pentru testele mari. \r\nProblema poate fi consideranta o varianta clasica a problemei de $RMQ$ in $2D$. Un articol foarte detaliat (in engleza) despre problema $RMQ$ gasiti \'aici\':http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=lowestCommonAncestor. Asadar, pentru a rezolva cazul $2D$ vom folosi ideile care se folosesc in rezolvarea cazului $1D$. Astfel, vom calcula matricea $A$ dar doar pentru laturi puteri ale lui $2$. $A[i][j][k]$ va fi elementul de valoare maxima dintr-un patrat cu coltul stanga-sus pe linia $i$ si coloana $j$ si latura $2^k^$.\r\n$A[i][j][k] = max(A[i][j][k-1], A[i][j+2^k-1^][k-1], A[i+2^k-1^][j][k-1], A[i+2^k-1^][j+2^k-1^][k-1])$\r\nPentru o raspunde la o intrebare $i j k$ in $O(1)$ vom determina cea mai mare putere $p$ a lui $2$ astfel incat $2^p^ &le; k$, si vom lua maximul din $4$ patrate cu colturile in patratul din intrebare si latura $2^p^$. Astfel, raspunsul pentru o intrebare $i j k$ este $max(A[i][j][p], A[i][j+k-2^p^][p], A[i+k-2^p^][j][p], A[i+k-2^p^][j+k-2^p^][p])$.\r\n\r\nh2. \'Culori\':problema/culori\r\n\r\nh3. (problema grea, clasa a 10-a, problema medie, clasele 11-12)\r\n\r\nObservam ca algoritmul de parcurgere al lui Bob reprezinta de fapt parcurgerea Euler a arborelui. Singura diferenta consta in faptul ca el nu noteaza nodurile prin care trece, ci doar culorile acestora. \r\n\r\nFie un arbore cu radacina in $T$, aceasta avand fii $F{~1~}$, $F{~2~}$, ... $F{~k~}$. Notand cu $[T]$ vectorul de culori generat de arborele de radacina $T$, obtinem $[T] = T$, daca arborele contine un singur nod si $[T] = T + [F{~1~}] + T + [F{~2~}] ... [F{~k~}] + T$ altfel (unde $\"+\"$ este operatorul de concatenare).\r\n\r\nDe aici se contureaza repede ideea de programare dinamica. Construim matricea $A{~i,j~} = numarul de arbori care ar fi putut genera subsecventa i..j a sirului initial de culori$.\r\n\r\nDin constructia sirului de culori reiese ca are sens sa calculam $A{~i,j~}$ numai daca $C{~i~} = C{~j~}$ (unde $C$ este vectorul de culori). In acest caz subarborele determinat de primul fiu al radacinii curente va genera sirul de culori cuprins $i+1$ si un indice $k$. Fixandu-l pe acesta, problema se reduce la numararea posibilitatilor de a forma arbori care sa corespunda intervalului $i+1..k$ si cea de a forma arbori pentru intervalul $k+1..j$\r\n\r\nAstfel avem $A{~i,i~} = 1$ si $A{~i,j~} = Suma(A{~i+1,k~} * A{~k+1,j~} | i < k < j si C{~i+1~} = C{~k~})$.\r\n\r\nComplexitatea algoritmului este $O(N^3^)$, dar daca este implementat cu grija poate fi facut sa ruleze in aprox. 0.5 secunde pentru oricare din testele folosite la evaluare. O ultima optimizare (mica, dar care imbunatateste codul in mod simtitor) consta in faptul ca, deoarece orice parcurgere euler este de lungime impara, are rost sa calculam $A{~i,j~}$ numai daca $i+j$ este numar par.\r\n\r\nh2. \'Reguli\':problema/reguli\r\n\r\nh3. (problema usoara, clasele 11-12)\r\n\r\nProblema se rezolva folosind cunostinte de potrivire a sirurilor. Fie sirul $D$ sirul diferentelor dintre termeni consecutivi ai sirului {$x$}. Astfel, trebuie sa determinam cea mai scurta perioada a acestui sir. Pentru a calcula aceasta informatie in {$O(N)$}, vom calcula functia prefix corespunzatoare sirului conform algoritmului de potrivire Knuth-Morris-Prat (KMP). Avand aceasta functie calculata, putem determina in {$O(1)$} daca primele $L$ elemente din $D$ reprezinta o perioada astfel: fie $r$ restul impartirii lui $N$ la {$L$} ( cate elemente raman la sfarsit intr-o posibila perioada incompleta ) si $c$ catul acestui rest ( numarul de perioade ). $L$ poate fi deci lungimea unei perioade daca si numai daca sunt indeplinite simultan conditiile:\r\n\r\n* $PI{~N-r~}$ > 0\r\n* {$(N-r)$} divizibil la {$(N-r-PI{~N-r~})$}\r\n* {$(N-r)$} / {$(N-r-PI{~N-r~})$} = $c$,\r\n* {$ok{~r~}$} este $adevarat$ ( adica ultimele $r$ caractere se potrivesc ),\r\n\r\nunde $PI{~i~}$ este vectorul reprezentat de functia prefix si {$ok{~i~}$} este adevarat daca si numai daca sufixul de lungime $i$ din sir este egal cu prefixul de lungime $i$. Acest vector se poate construi tot in complexitate liniara, tinand cont de faptul ca toate sufixele care sunt si prefix pentru sirul initial au lungimile de forma $PI[N]$, $PI[PI[N]]$, $PI[PI[PI[N]]]$, etc.\r\n\r\nDintre toate lungimile $L$ care indeplinesc conditiile de mai sus se alege cea care are lungimea minima. Aceasta abordare nu este unica abordare optima. Algoritmul mentionat obtine 100 de puncte. \r\n\r\nh2. \'Ghiozdan\':problema/ghiozdan\r\n\r\nh3. (problema grea, clasele 11-12)\r\n\r\nO prima solutie clasica ar fi folosind metoda programarii dinamice. Se construieste o matrice $A[i][j]$ = numarul minim de obiecte necesare din primele $i$ obiecte pentru a obtine o greutate $j$. Relatia de recurenta este:\r\n$A[i][j] = min(A[i-1][j], A[i-1][j-V[i]]+1)$ unde $V[i]$ este greutatea obiectului $i$ ({$i &le; N, j &le; G$}).\r\nAceasta solutie are complexitate $O(N*G)$ si nu se incadreaza in timp datorila limitelor mari pentru $N$ si $G$. De asemenea, pentru reconstructie trebuie pastrata o matrice $T$ de dimensiune $N*G$, care nu incape in memorie. Deoarece avem numai greutati intre $1$ si $200$, putem folosi o alta abordare: $A[i][j]$ = numarul minim de obiecte necesare cu greutate $&le; i$ pentru a obtine o greutate $j$. Relatia de recurenta este:\r\n$A[i][j] = min(A[i-1][j], A[i-1][j-i]+1, A[i-1][j-2*i]+2 ... A[i-1][j-C[i]*i]+C[i])$ unde $C[i]$ este numarul de obiecte de greutate $i$ care exista ({$i &le; 200, j &le; G$}). \r\nO implementare triviala ar avea aceeasi complexitate $O(N*G)$, dar putem imbunatati solutia folosind o structura de date numita _deque_. Puteti citi mai mult despre aceasta structura \'aici\':http://infoarena.ro/USACO-dec-2004-divizia-GOLD (problema Divide), \'aici\':http://infoarena.ro/preoni-2005/runda-3/solutii (problema Ferma) si \'aici\':http://infoarena.ro/preoni-2006/runda-2/solutii (problema Struti). \r\nVom calcula elemente din linia $i$ a matricei astfel: intai elementele de forma $k*i$, apoi elementele $k*i+1$, $k*i+2$, ... $k*i+(k-1)$. Cand calculam $A[i][j]$ cu $j = k*i+r$ , vom avea in deque toate elementele $A[i-1][x*i+r] + (k-x)$ cu $k-C[i] &le; x &le; k$. Astfel $A[i][j]$ se determina in $O(1)$ folosind capatul stanga al deque-ului. Cand se trece la calculul elementului $(k+1)*i+r$ se elimina din deque elementul $A[i-1][(k-C[i])*i+r]+...$ , si se insereaza elementul $A[i-1][(k+1)*i+r]$. Conform relatiei, inainte de inserare toate elementele din deque ar trebui marite cu $1$, dar acest lucru este echivalent cu a scadea $1$ din elementul care se insereaza. Astfel, se poate determina matricea $A$ in timp $O(200*G)$. Deoarece se pot retine doar ultimele doua linii din matricea $A$ , memoria folosita este $O(G)$. \r\nDesigur, pentru reconstituire ar trebui retinuta o alta matrice $T$ de dimensiuni $200*G$ ,dar nu este destula memorie pentru a construi o astfel de matrice. O solutie ar fi pastrarea liniilor din matricea $A$ din $&radic;200$ in $&radic;200$. O scurta descriere despre aceasta metoda gasiti \'aici\':http://infoarena.ro/winter-challenge-1/solutii (problema Smen). Memoria folosita ar fi fost $O(&radic;200*G)$. \r\nDin fericire existe o metoda _divide et impera_ mult mai usor de implementat pentru a reconstitui solutia folosind doar $O(G)$ memorie. Presupunem ca rezolvam problema initiala folosind dinamica de mai sus si pastrand doar ultimele doua linii din matrice. Stim acum ca greutatea maxima care se poate obtine este $H &le; G$. Consideram o solutie optima (cu numar minim de obiecte) de a lua obiecte in ghiozdan de greutate $H$. Putem imparti aceasta solutie in doua bucati: sa determinam o solutie optima de a obtine greutatea $X$ folosind obiecte cu greutati $&le; 100$ si o solutie optima de a obtine greutatea $H-X$ folosind obiecte cu greutati $> 100$. Putem determina aceasta valoare $X$ in timp ce facem dinamica initiala (folosind inca o matrice $B$ si pastrand ultimele doua linii) si apoi putem rezolva recursiv cele doua subprobleme. Asfel, la fiecare pas avem un interval $[st...dr]$ in care sunt greutatile pe care le folosim si o valoare $H$ care reprezinta greutatea pe care vrem s-o obtinem. La fiecare apel putem folosi aceleasi matrici, deci necesarul de memorie nu va depasi $O(G)$. Vom face si o analiza a complexitatii. Fie $T(st, dr, H)$ complexitatea pentru a rezolva o subproblema.\r\n$T(st, dr, H) = O((dr-st+1)*H) + T(st, (st+dr)/2, X) + T((st+dr)/2+1, dr, H-X)$\r\nSe poate demonstra prin inductie ca $T(st, dr, H) = O((dr-st+1)*H)$.\r\nO prezentarea mult mai detaliata a acestei metoda si despre cum aceasta se poate aplica pentru a determina cel mai lung subsir comun a doua siruri folosind memorie liniara gasiti \'aici\':http://www.ics.uci.edu/~eppstein/161/960229.html.\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'public',NULL,NULL),('runda/lame.contest','lame.contest','2009-03-27 22:18:25','2009-03-27 22:18:25','h1. == roundparam(round_id=\"lame.contest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"lame.contest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"lame.contest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"lame.contest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/lame.contest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"lame.contest\" score=\"1\")==',9714,'round: lame.contest',NULL,NULL),('screencast','Screencast','2007-02-25 12:41:25','2007-02-25 12:41:25','h1. Screencast\r\n\r\nA screencast is a recording of computer screen output, usually containing audio narration typically published as a video file. However, the technology has existed for much longer. Screencasts are typically created to produce software and web application demonstrations. This was mostly done within corporations as a way to facilitate employee training. However, further interest has been sparked through the increased blogging trend, which has eased content publishing. ...\r\n',13,'public',NULL,NULL),('screencast/contul-meu','Contul meu, Screencast','2007-02-25 12:44:58','2007-02-26 20:44:42','h1. Contul meu la infoarena\r\n\r\nInca lucram la \"tehnologia\" asta :) We\'re not there yet...\r\n\r\n== GoogleVideo(id=\"2535789311422139569\" width=\"425\" height=\"350\") == \r\n\r\n\r\nDin screencast-ul acesta, utilizatorii vor invata cum se pot inregistra pe site si cum isi pot edita optiunile contului.\r\n\r\nGuidelines de \"filmare\":\r\n\r\n* Prezinta-te\r\n* Descrie pe scurt scopul screencast-ului. Mentioneaza ca un utilizator are nevoie de cont ca sa poata participa la concursurile infoarena si ca sa poata trimite solutii la problemele din arhiva. Pentru a citi articole si probleme nu este nevoie de cont.\r\n* Demonstreaza inregistrare unui cont nou. \r\n** Se va atrage atentia asupra faptului ca inregistrarea se face doar daca nu ai cont deja. In caz ca ti-ai uitat parola si/sau contul, se va folosi optiunea de \"reset password\".\r\n*** Arata sectiunea de reset password si explica ce trebuie completat si cum functioneaza. Nu este nevoie sa mergi pana la capat (i.e. sa resetezi pe bune parola unui cont). E de ajuns sa explici ce face ecranul de reset password si sa treci mai departe.\r\n** Se va explica semnificatia campului de newsletter (Ma abonez la newsletter. Sunt de acord sa primesc pe e-mail noutati despre infoarena. Ma pot dezabona oricand.) Aici trebuie mentionat ca, de obicei, pe email se primesc instiintari atunci cand apar concursuri noi. Se trimit in medie cam 3-4 email-uri pe luna.\r\n** Pentru inregistrarea demonstrativa se vor folosi date fictive dar naturale. In alte cuvinte, fara `idutilizator`, `nume complet` samd.\r\n* Demonstreaza autentificarea, din casuta de autentificare din stanga.\r\n** Se va explica semnificatia casutei \"Pastreaza-ma autentificat\"\r\n* Demonstreaza cum se editeaza optiunile contului.\r\n** Arata cum se uploadeaza poza personala. Mentioneaza faptul ca poza este redimensionata automat.\r\n** Mentioneaza cam pe unde apare poza pe site.\r\n** Mentioneaza ca de aici te poti dezabona la newsletter.\r\n* Demonstreaza logout.\r\n',13,'public',NULL,NULL),('screencast/rezolva-probleme','Cum se rezolva probleme din arhiva','2007-02-25 21:34:55','2007-02-26 07:45:20','h1. Cum se rezolva probleme din arhiva\r\n\r\nDin screencast-ul acesta, utilizatorii vor invata cum se citesc probleme din arhiva, cum se trimit solutii si cum se urmareste evaluarea lor.\r\n\r\n\"Script de filmare\"\r\n\r\n* Prezinta-te\r\n* Descrie pe scurt scopul screencast-ului. Mentioneaza ca un utilizator are nevoie de cont ca sa poata participa la concursurile infoarena si ca sa poata trimite solutii la problemele din arhiva.\r\n* Autentifica-te\r\n* Alege o problema din arhiva\r\n** Mentioneaza ca in acest moment arhiva are peste 320 de probleme\r\n* Vizualizeaza problema A+B\r\n** Mentioneaza ca cerintele problemei trebuie respectate cu exactitate intrucat evaluarea se face automat.\r\n** Descrie capul de tabel de la o problema\r\n*** Atentie la numele fisierului de intrare/iesire. Se va respecta case-ul.\r\n*** Despre limita de timp si de memorie\r\n** Citeste despre input si output in problema A+B. Mentioneaza ca output-ul trebuie facut exact asa cum apare in enunt. Daca se print-eaza informatii in plus sau daca se asteapta apasarea unei taste, evaluatorul va acorda 0 puncte.\r\n* Trimite o solutie corecta la problema A+B folosind formularul din pagina de problema\r\n** Inainte sa submitezi afiseaza sursa pe ecran (notepad?)\r\n** Mentioneaza ca sursele trebuie compilate si testate pe calculator inainte sa fie trimise.\r\n* Prezinta monitorul de evaluare\r\n** Ce face in general\r\n** Prezinta job details despre sursa pe care am trimis-o.\r\n* Demonstreaza trimiterea unei surse ce contine erori de compilare.\r\n** Modifica sursa tocmai trimisa. Adauga #include <conio.h>\r\n*** Mentioneaza ca acest header este specific MSDOS nu face parte din limbajul C standard. Programul nu va compila.\r\n** Trimite sursa\r\n** Afiseaza job details cu eroarea de compilare.\r\n** Afiseaza o cutie cu adresa http://infoarena.ro/documentatie/evaluator in care se gasesc informatii aditionale despre compilatoarele folosite de infoarena, ce merge si ce nu.\r\n* Prezinta sectiunea de statistici din cadrul paginei de profil.\r\n** Arata cum problema `adunare` apare acum ca rezolvata.\r\n** Arata pagina de statistici a altui utilizator mai \"harnic\"\r\n\r\n',13,'public',NULL,NULL),('preoni-2007/runda-3','Runda 3 preONI 2007','2007-01-15 16:00:43','2007-03-07 12:22:22','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. preONI 2007, Runda 3\r\n\r\n(htabs)*(active) \'Despre...\':preoni-2007/runda-3\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/runda-3/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-3/9\r\n\r\n*Runda 3 s-a incheiat!*\r\n\r\nRunda a inceput *Duminica 4 martie*, la ora {*09^00^*} si a durat *4h*. Participantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Ca sa poata participa la aceasta runda, concurentii au trebuie sa se inscrie *inainte de ora 09^00^* la grupa de varsta corespunzatoare! *Cei care nu s-au inscris* la o grupa de varsta nu li s-a modificat \'rating-ul\':documentatie/rating!\r\n\r\nAceeasi procedura se va urma la fiecare runda preONI. Timp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta&hellip;\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/runda-3/11-12\r\n\r\nPoti vedea solutiile problemelor \'aici\':preoni-2007/runda-3/solutii.\r\n\r\nh2. Clasament Runda 3\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-3/11-12\r\n\r\nh2. Discutii preONI pe forum\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\nh2. Organizatori\r\n\r\n* Subiectele vor fi propuse de:\r\n==User(user=\"azotlichid\" type=\"tiny\")==\r\n==User(user=\"cosmin\" type=\"tiny\")==\r\n==User(user=\"danielp\" type=\"tiny\")==\r\n==User(user=\"ditzonec\" type=\"tiny\")==\r\n==User(user=\"domino\" type=\"tiny\")==\r\n==User(user=\"filipb\" type=\"tiny\")==\r\n\r\n* Pentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n==User(user=\"fluffy\" type=\"tiny\")==\r\n==User(user=\"svalentin\" type=\"tiny\")==\r\n==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('utilizator/lebappe','Profil lebappe','2007-03-17 17:23:52','2007-03-17 17:23:52','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6306,'public',NULL,NULL),('preoni-2007/runda-4','Runda 4 preONI 2007','2007-01-15 16:01:16','2007-03-21 11:07:33','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. preONI 2007, Runda 4\r\n\r\n(htabs)*(active) \'Despre...\':preoni-2007/runda-4\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/runda-4/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-4/9\r\n\r\nRunda va incepe *Duminica 25 martie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Ca sa poata participa la aceasta runda, concurentii trebuie sa se inscrie *inainte de ora 09^00^* la grupa de varsta corespunzatoare! *Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating!\r\n\r\nAceeasi procedura se va urma la fiecare runda preONI. Timp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta&hellip;\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/runda-4/11-12\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':preoni-2007/runda-4/solutii.\r\n\r\nh2. Clasament Runda 4\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-4/11-12\r\n\r\nh2. Discutii preONI pe forum\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\nh2. Organizatori\r\n\r\n* Subiectele vor fi propuse de:\r\n==User(user=\"cosmin\" type=\"tiny\")==\r\n==User(user=\"ditzonec\" type=\"tiny\")==\r\n==User(user=\"domino\" type=\"tiny\")==\r\n==User(user=\"filipb\" type=\"tiny\")==\r\n==User(user=\"greco\" type=\"tiny\")==\r\n\r\n* Pentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n==User(user=\"wickedman\" type=\"tiny\")==\r\n==User(user=\"fluffy\" type=\"tiny\")==\r\n==User(user=\"svalentin\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('djgpp-instalarea-de-la-a-la-z','DJGPP - instalarea de la A la Z','2006-03-12 00:00:00','2009-02-20 00:02:00','h1. DJGPP - instalarea de la A la Z\r\n\r\n(Categoria _Diverse_, Autor _Tudor Aursulesei_)\r\n\r\nProbabil ca ai auzit de puternicul compilator $Gnu C$. Este acela folosit pe la mai toate competitiile mai mari de nationala (inclusiv). Avantaje:\r\n\r\n* lucreaza pe 32 de biti; asta inseamna ca programele compilate cu el vor merge mult mai repede!\r\n* stiva mai mare &#8658; erorile gen $stack overflow$ vor apare mult mai rar.\r\n* memorie mai mare &#8658; @long x[10000000]@ chiar exista\r\n\r\nAcest ghid este valabil pentru $Windows XP$.\r\nInainte sa incepem, trebuie sa raspundem la cateva intrebari:\r\n\r\nh2. Ce este DJGPP?\r\n\r\nO colectie de programe de $UNIX$ portate pentru $DOS$. Vizitati \"http://delorie.com/djgpp\":http://delorie.com/djgpp pentru detalii. Cel mai important, dupa ce veti instala corect $DJGPP$, veti putea scrie din linia de comanda in $DOS$ comenzi gen $gcc test.c *o test.exe$.\r\n\r\nh2. Ce este RHIDE?\r\n\r\nEste un $IDE (Integrated Development Environment)$ pentru $DJGPP$. Deosebit de puternic si seamana cu $Borland C 3.1$ la culoare ${:)}$. Se impaca de minune cu $GCC$! Important; ${NU}$ vom folosi versiunea de ${RHIDE}$ pe care ne-o ofera ${DJGPP}$, ci vom folosi una mai noua, dezvoltata de \"SET\":http://setedit.sourceforge.net. Are propriul lui editor, $Setedit$, dar a dezvoltat si $RHIDE$, eliminand o parte din buguri.\r\n\r\nVersiunea lui se gaseste la \"http://sourceforge.net/project/showfiles.php?group_id=32835\":http://sourceforge.net/project/showfiles.php?group_id=32835 , sectiunea extra! Recomand sa o luati acum: $pachetul RHIDE 1.5 + Ed 0.5.4 + gdb 6.1.1$ \r\n\r\nh2. Sa incepem\r\n\r\nAccesam link-ul \"http://www.delorie.com/djgpp/zip-picker.html\":http://www.delorie.com/djgpp/zip-picker.html si alegem optiunile (pe rand)\r\n\r\n* Build and run programs with DJGPP\r\n* Windows 2000/XP\r\n* Yes\r\n* C si C++\r\n\r\nLa $Integrated Development Environments and Tools$ aveti grija sa nu fie selectat $RHIDE$ (dupa cum am zis si mai sus, vom folosi o alta versiune).\r\n\r\nDe asemenea, alegem $No$ la Optiunea $Would you like GDB?$ (daca folositi GDB, atunci luati si acest pachet). Contiunam cu $\"Tell me which files I need\"$\r\n\r\nAr trebui sa obtinem urmatoarea lista:\r\n\r\n* unzip32.exe to unzip the zip files 95kb\r\n* v2/copying.dj Copyright info 3kb\r\n* v2/djdev203.zip Basic Development Kit 1.5mb\r\n* v2/faq230b.zip F.A.Q. 664kb\r\n* v2/readme.1st Installation instructions 22kb\r\n* v2gnu/bnu2161b.zip Basic assembler, linker 3.3mb\r\n* v2gnu/gcc401b.zip Basic GCC compiler 4.0mb\r\n* v2gnu/gdb611b.zip GNU debugger 1.5mb\r\n* v2gnu/gpp401b.zip C++ compiler 4.4mb\r\n* v2gnu/mak3791b.zip Make (processes makefiles)267b\r\n* v2gnu/txi48b.zip Info file viewer 779kb\r\n\r\nDownloadati-le!\r\n\r\nIncercati sa le puneti pe toate intr-un director gen $c:\\djgpp\\$ (de altfel, pe acesta il folosesc eu si vi-l recomand; articolul presupune in continuare ca aceasta este calea unde ati instalat programul). Deschideti o fereastra de $Explorer$ si faceti drag-n-drop la fiecare arhiva peste executabilul $unzip32.exe$. Ar trebui sa va apara directoare gen $bin$ si $include$. Sa nu uitam de versiunea de $RHIDE$ pe care am mentionat-o mai sus. Despachetati-o si pe aceasta in acelasi mod!\r\n\r\nVom contiuna cu setarea variabilei de mediu $DJGPP$. (foarte important)\r\nClick dreapta pe $My Computer &#8594; Properties &#8594; Advanced &#8594; Environment Variables$. In sectiunea System variables, editati variabila $PATH$ astfel incat aceasta sa arate si spre calea $C:\\DJGPP\\BIN$. Separati caile cu $;$ (ex: $C:\\DJGPP\\BIN;C:\\WINDOWS\\system32;...$. De asemenea, creeati o variabila noua numita $DJGPP$ care aibe valoarea $C:\\DJGPP\\DJGPP.ENV$ (daca ati instalat in alta parte, modificati caile dupa caz). Dupa ce ati modificat variabilele de sistem, calculatorul trebuie restartat.\r\n\r\nDaca nu doriti sa modificati variabilele de sistem, se recomanda crearea unui fisier batch care sa lanseze $RHIDE$. Va prezint un exemplu:\r\n\r\n== code(c) |@echo off\r\nset PATH=c:/djgpp/bin;%PATH%\r\nset DJGPP=c:/djgpp/djgpp.env\r\nchdir c:/djgpp/lucru\r\nc:/djgpp/bin/rhide.exe\r\n==\r\n\r\nRulati batch-ul. Ar trebui *sa nu dati* de o eroare care zice ceva de variabila $PATH$ pusa gresit sau de variabila $DJGPP$. Daca va apare, recititi partea de variabile de sistem din articol sau cititi fisierul $readme.1st$ (deschideti-l cu $Word$, nu cu $Notepad$). Daca nu aveti nici o eroare, ar trebui sa fiti intampinati de o fereastra in care se zice ceva de $Robert Hohne (RH din RHIDE) si Salvador Eduardo Tropea (omul care a imbunatatit RHIDE)$. Creeati un fisier nou in care sa bagati cateva linii de test.\r\n\r\n== code(c) |#include <stdio.h>\r\nint main()\r\n{\r\n    printf(\"%d %d %d\" , 1, 2, 3);\r\n    return 0;\r\n}\r\n==\r\n\r\n$Ctrl+F9$ ca sa compilati. $Ctrl+F2$ reset la program. $Shift + F4 $ruleaza pana la linia la care se afla cursorul. $Shift+F8$ e $Step Over$ fara sa se schimbe modul monitorului (fara flick la monitor). $Shift+F7$ e $Run Into$ fara sa se schimbe modul monitorului. $Shift+F2$ e $GREP$ (utilitar UNIX portat). $Alt + F5$ arata rezultatul rularii programului (in versiunea de $RHIDE$ de pe $DJGPP$, nu prea mergea aceasta functie). Recomand optiunile din $Options &#8594; Environment &#8594; Preferences$.\r\n\r\n* Screen Mode 80 x 50\r\n* Syntax highlighting\r\n\r\nIar tot din $Options &#8594; Environment &#8594; Editor &#8594; Editor Options$\r\n\r\n* Autoindent\r\n* Use Tabs\r\n* Intelligent C indent\r\n* Match pair on the fly\r\n\r\n...Si altele , pe care va las sa le descoperiti singuri.\r\n\r\nAvertizare. Desi aceasta versiune de $RHIDE$ este mai stabila decat cea de pe $DJGPP$, este sansa sa se prabuseasca la $Debugging$ ceva mai complex (crash ${:)}$). Nimic nu este perfect. De aceea este recomandat sa salvati din 15 in 15 minute.\r\nPuteti incerca si alte versiuni de RHIDE de la http://rhide.sourceforge.net/snapshots/index.html Unele dau eroare intr-un loc, altele in alt loc. Puteti sa le incercati pe rand.\r\n\r\nAmintiti-va totusi sa salvati cat mai des si sa nu urmariti evolutia unor variabile prea mari gen @x[10000000]@ ${:)}$. De asemenea nu incercati sa afisati pe ecran si sa vedeti ce rezultat a iesit cu $Alt+F5$. S-ar putea sa nu mearga. Daca aveti probleme $MARI$ cu programul, stergeti fisierele\r\n\r\n* rh_opt.gpr\r\n* rh_opt.gdt\r\n\r\nAsta o sa il faca ca nou, in caz ca refuza sa porneasca sau e mai instabil decat era cand l-ati instalat.\r\n\r\nRecomand de asemenea sa explorati fiecare meniu si scurtatura a programului, deoarece eu v-am prezentat sumar aproximativ $30%$ din functii si $30%$ din optiunile lui optime de functionare! Insist sa verificati sistematic si metodic optiunile; Nu o sa regretati! De asemenea, poate lucra cu $FPC (Free Pascal Compiler)$ , insa va recomand $IDE$-ul din $Free Pascal$. Este o opera de arta pentru pascalisti!\r\n',2044,'public',3679,NULL),('newsletter/preoni-2007-runda-4','preONI 2007, Runda #4','2007-03-23 13:25:29','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nTe invitam la runda #4 a concursului preONI, ultima runda\r\nde calificare la finala preONI.\r\n\npreONI este concursul cu premii care te pregateste pentru\r\nOlimpiada Nationala de Informatica.\r\n\nRunda #4 va avea loc ...\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Duminica, 25 martie 2007, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPagina rundei: \'preoni-2007/runda-4\':preoni-2007/runda-4\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la aceasta runda iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te va aduce mai aproape de varful clasamentul.\r\n==NewsletterRating(username=\"%username%\")==\r\nRating-ul este un indicator al performantei tale in conditii de\r\nconcurs. Afla mai multe: \'documentatie/rating\':documentatie/rating\r\n\nIti tinem pumnii!\r\n\nh2.  Despre preONI \n\npreONI, concursul de marca al comunitatii infoarena, este dedicat\r\nelevilor de liceu ce se pregatesc pentru ONI (Olimpiada Nationala\r\nde Informatica).\r\n\npreONI se imparte in 3 grupe: clasa a IX-a si gimnaziu, clasa\r\na X-a si clasele XI-XII. Se organizeaza 4 runde online de calificare.\r\nIn urma acestora, cei mai buni de la fiecare grupa sunt invitati la\r\no runda finala.\r\n\nIn cadrul unei runde, vei avea de rezolvat 3 probleme in 4h.\r\nCastigatorii rundei finale sunt premiati cu bani si/sau obiecte.\r\n\nPe pagina concursului ( \'preoni-2007\':preoni-2007 ) vei gasi\r\ninformatii despre cum participi, cine propune probleme, premii si\r\nsponsori, regulamentul concursului samd.\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('preoni-2005/runda-1/solutii','preONI 2005 runda #1 - solutii','2005-01-24 00:00:00','2010-01-20 14:38:02','h1. preONI 2005 runda #1 - solutii\r\n\r\n(Categoria _Competitii_, autor(i) _Mircea Pasoi_)\r\n\r\nArticolul contine ideile de rezolvare ale problemelor propuse la prima runda a concursului preONI ce s-a desfasurat pe data de 23 ianuarie 2005, cat si comentarii legate de concurs.\r\n\r\nCum s-a si promis, setul de probleme de data aceasta n-a fost dur, problemele fiind mult mai accesibile, fapt care se vede imediat din punctaje. Spre deosebire de concursurile anterioare in care problemele erau toate de acelasi nivel, de data aceasta a existat o problema usoara, una medie si una grea la fiecare grupa (gen TopCoder).\r\n\r\nToti care am participat la compunerea problemelor suntem de parere ca probleme au fost de nivelul ONI, chiar un pic mai usoare. De asemenea, testele au fost create astfel incat sa se poata obtine 190-200p in mod usor de un concurent cu cunostiinte medii care implementeaza solutii corecte dar care nu se incadreaza complet in limita de timp. Din pacate rezultatele sunt un pic sub nivelul asteptarilor, dar speram ca se vor inbunatati in rundele urmatoare! ;)\r\n\r\nh2. Clasele 9-10\r\n\r\nPrimele $5$ locuri din clasamentul de la $9-10$ arata astfel:\r\n\r\n==Rankings(rounds=\"preoni51a\" display_entries=\"6\" pager_style=\"none\")==\r\n\r\nEste de mentionat faptul ca sub pseudonimul ==user(user=\"macarie\" type=\"tiny\")== se \"ascunde\" echipa care va reprezenta Romania la finala ACM, formata din Mugurel Andreica, Marius Andrei si Ghinea Dan. Ei au concurat pe un singur calculator si au rezolvat toate cele $6$ probleme propuse pentu a simula un concurs ACM. De asemenea, un lucru remarcabil, concurentul clasat pe locul {$2$}, Tataroiu Bogdan este abia clasa a {$7$}-a! Probabil ca va reprezenta Romania la multe IOI-uri :)\r\n\r\nh3. Text\r\n\r\nProblema a fost cea mai usoara din cele $3$ probleme din grupa si rezolvarea nu ar trebui sa ridice mari dificultati nici macar unui elev de a {$9$}-a incepator. Fie $N$ numarul de caractere din fisierul de intrare - voi prezenta o solutie {$O(N)$}. Se parcurge fisierul caracter cu caracter (nu este necesara stocarea datelor de intrare intr-un vector) si se mentin doua variabile care indica pozitia de inceput si sfarsit a ultimului cuvant detectat pana in prezent, daca s-a gasit vreunul. De asemenea se pastreaza si doua variabile pentru suma lungimilor cuvintelor si numarul de cuvinte pentru a calcula rezultatul. Atentie insa ca la sfarsitul parcurgerii fisierului de iesire, daca ultimul caracter citit a fost o litera mare sau mica, sa se actualizeze numarul de cuvinte si suma lungimilor.\r\n\r\nh3. Trapez\r\n\r\nProblema a fost cea de nivel mediu din cele $3$ si face apel la cunostiinte minime de geometrie. Conditia ca oricare trei puncte nu sunt coliniare simplifica mult rezolvarea. Din definitie, un trapez are cel putin doua laturi paralele deci se poate construi urmatorul algoritm: se iau toate perechile de puncte - acestea determina cate un segment - si sorteaza in functie de unghiul cu axa OX (panta dreptei). Pentru fiecare $k$ segmente cu acelasi unghi se pot forma {$Comb(k,2)$} trapeze. Pentru a evita calculele cu reale (care pot cauza erori de precizie), se tin pantele ca perechi de numere intregi ({$y, x$}), fara a efectua efectiv impartirea {$y/x$}. Pentru compararea a doua astfel de perechi sunt necesare tipuri de date pe $64$ de biti. Algoritmul descris are complexitate {$O(N^2^*lg N)$}. Las ca exercitiu rezolvarea acestei probleme folosind un algoritm $O(N^2^)$ care foloseste \"hashing\":tabele-hash-scurta-prezentare (vezi articolul de pe site). Se puteau obtine $40-50p$ cu un algoritm brut {$O(N^4^)$}.\r\n\r\nh3. Subsir\r\n\r\nAceasta problema, care a fost si cea mai grea, a fost prezenta si la CEOI 2003, dar intr-o forma mai simpla. Acolo se cerea generarea efectiva a tuturor subsirurilor , nu numararea lor, si se garanta ca numarul lor este sub {$1000$}. Orice solutie care ar fi luat $100p$ la problema de la CEOI ar fi obtinut $50p$ la aceasta (primele $5$ teste fiind de fapt preluate de la CEOI 2003). Cum multi probabil au intuit, rezolvarea se bazeaza pe programare dinamica. Voi numi cele doua siruri $A$ si {$B$}, de lungime {$N$}, respectiv $M$ si voi construi initial matricea $C{~i,j~}$ = lungimea celui mai lung subsir comun al sirurilor {$A{~1..i~}$} si {$B{~1..j~}$}. Acest lucru se poate face in $O(N*M)$ si este o aplicatie clasica a programarii dinamice (se gaseste in foarte multe carti explicata ideea). In continuare voi numara sirurile folosind un algoritm $O(N*M*Sigma)$ unde $Sigma$ este numarul litere din care pot fi formate sirurile, adica {$26$}. Se va calcula o matrice $Nr{~i,j~}$ = cate subsiruri comune de lungime maxima existe pentru sirurile $A{~1..i~}$ si\r\n$B{~1..j~}$ (evident modulo {$666013$}). Se calculeaza $Nr{~i,j~}$ doar atunci cand {$A{~i~} = B{~j~}$}, astfel: pentru fiecare caracter $c$ intre \'{$a$}\' si \'{$z$}\' se cauta ultima sa aparitie in sirul $A{~1..i-1~}$ (fie aceasta pozitia {$ii$}) si ultima sa aparitie in sirul $B{~1..j-1~}$ (fie aceasta pozitia {$jj$}). Acest lucru se poate face in $O(1)$ daca se preproceseaza inainte aceste informatii in {$O((N+M)*Sigma)$}. Daca $C{~i,j~} = C{~ii,jj~}+1$ se va aduna $Nr{~ii,jj~}$ la $Nr{~i,j~}$ - aceasta conditie ne garanteaza ca subsirurile adaugate au lungime maxima, iar faptul ca $ii$ si $jj$ reprezinta ultima aparitie a caracterului garanteaza ca nu se vor numara subsiruri identice. Pentru a gasi rezultatul final se aduna toate valorile $Nr{~i,j~}$ calculate, cu urmatoarea exceptie: daca exista pozitiile $x$ si $y$ astfel incat {$A{~x~} = A{~i~} = B{~y~} = B{~j~}$}, se aduna $Nr{~i,j~}$ doar daca $x < i$ si $y < j$ (pentru a asigura ca nu se numara subsiruri identice de mai multe ori).\r\n\r\nh2. Clasele 11-12\r\n\r\nPrimele 5 locuri din clasamentul de la 11-12 arata astfel:\r\n\r\n==Rankings(rounds=\"preoni51b\" display_entries=\"6\" pager_style=\"none\")==\r\n\r\nh3. Iepuri\r\n\r\nProblema a fost cea mai usoara din cel $3$ si necesita cunostiine elementare de matematica de clasa a 11-a. Daca se noteaza cu $I{~n~}$ cati iepuri sunt in ziua $n$ se deduc urmatoarele relatii din enunt:\r\n\r\n* $I{~0~}=X, I{~1~}=Y, I{~2~}=Z$\r\n* $I{~n~}=A*I{~n-1~} + B*I{~n-2~} + C*I{~n-3~}$ pt 3 &le; n\r\n\r\nRezultatul cerut este $I{~N~}$ modulo $666013$ pentru fiecare test.\r\nO prima rezolvare, si cea mai simpla, este implementarea directa a relatiei de recurenta si conduce la o complexitate $O(N)$ pe set de date. Aceasta abordare ar fi obtinut {$50p$}.In continuare voi descrie o rezolvare $O(lg N)$ care foloseste matrici. Se construieste matricea:\r\n\r\np(pre). \r\n    [0 1 0]\r\nM = [0 0 1]\r\n    [C B A]\r\n\r\ncare sta la baza relatiei:\r\n\r\np(pre). \r\n    [I{~0~}]   [I{~1~}]\r\nM * [I{~1~}] = [I{~2~}]\r\n    [I{~2~}]   [I{~3~}]\r\n\r\nDin asta se deduce:\r\n\r\np(pre). \r\n&nbsp;&nbsp;&nbsp;&nbsp; [I{~0~}]   [I{~N&nbsp;&nbsp;~}]\r\nM^N^ * [I{~1~}] = [I{~N+1~}]\r\n&nbsp;&nbsp;&nbsp;&nbsp; [I{~2~}]   [I{~N+2~}]\r\n\r\n\r\nastfel problema se reduce la a calcula $M^N^$ in {$O(lg N)$}. Algoritmul de ridicare la putere in timp logaritmic este clasic si nu-l mai mentionez aici.\r\n\r\nh3. Barbar\r\n\r\nProblema este de nivel mediu si necesita cunostiinte elementare de teoria grafurilor. Se considera matricea initiala un graf cu $R*C$ noduri, mai putin zidurile. Se face o parcurgere BF pentru a determina pentru fiecare casuta din matrice distanta pana la cel mai apropiat dragon. Astfel, se incepe BF-ul cu toate nodurile care corespund dragonilor inserate in coada (deci nu va fi doar un nod in coada la inceput). Complexitatea acestui pas este {$O(R*C)$}. Se observa daca exista un traseu valid care trece prin casute situate la distanta $&ge;x$ fata de cel mai apropiat dragon, atunci exista in mod evident un traseu valid care trece prin casute situate la distanta $&ge;x-1$ fata de cel mai apropiat dragon. Aceasta observatie duce la folosirea cautarii binare a rezultatului (vezi articolul de pe site pentru alte aplicatii). Pentru a verifica daca exista un traseu valid care trece doar prin casute situate la o anumita distanta fata de cel mai apropiat dragon se foloseste tot o parcurgere BF, astfel rezolvarea fiind\r\n{$O(R*C*lg(R*C))$}.\r\n\r\nh3. ADN\r\n\r\nLa primul pas se elimina toate cuvintele incluse in alte cuvinte mai mari (pentru a cauta daca exista un cuvant in alt cuvant se foloseste algoritmul KMP pentru incadrarea in timp - vezi articolul de pe site). Apoi, se construieste un graf cu noduri cuvintele si muchii intre oricare doua cuvinte. Costul unei muchii ({$i, j$}) va fi cel mai lung sufix al cuvantului $i$ care este prefix al cuvantului $j$ (informatie care se poate determina cu KMP), adica cate litere sunt \"inutile\" daca lipim cuvantul $i$ cu cuvantul {$j$}. Aceasta prima etapa are complexitate {$O(N^2^*L)$}, unde $L$ e lungimea maxima a unui cuvant. Deoarece trebuie sa existe fiecar cuvant in sirul rezultat, iar sirul sa fie de lungime minima problema se reduce la determinarea unui lant hamiltonian de cost maxim, problema care este binecunoscuta ca fiind {$NP$}. Un algoritm care incearca toate cele $n!$ permutari are complexitate $O(n!)$ si va obtine {$50p$}. Pentru punctaj maxim vom folosi programare dinamica astfel: fie {$A[i][(n{~1~}, n{~2~}.. n{~k~})]$} = costul unui lant hamiltonian de cost maxim care incepe din nodul $i$ si trece prin nodurile {$n{~1~}, n{~2~} .. n{~k~}$}. Relatia de recurenta este: {$A[i][n{~1~},n{~2~}..n{~k~})]$ = {$max cost(i, n{~j~}) + A[n{~j~}][(n{~1~},n{~2~},n{~j-1~},n{~j+1~}..n{~k~})]$} pentru fiecare {$j$}. Dinamica se initializeaza cu $A[i][(i)] = 0$ pentru fiecare {$i$}. Reprezentarea multimilor de noduri se face folosind un numar binar cu $N$ biti, astfel complexitatea acestei etape fiind {$O(N^2^*2^N^)$}. Mentionez ca aceasta rezolvare nu produce solutia minim lexicografic, fapt observat in timpul concursului si astfel s-a reevaluat problema dandu-se puncte pentru orice solutie valida, nu neaparat minim lexicografic. Rezolvarea problemei cu cerinta de minim lexicografic este posibila, dar pentru realizarea ei trebuie folosite structuri de date avansate ca Suffix Arrays sau Suffix Trees si nivelul de dificultate ar fi mult mai mare. Alta observarie este ca matricea cost ar putea fi calculata mai repede daca am folosi structurile mentionate mai devreme. Folosind prima structura am avea complexitatea $O( N*L log (N*L))$ iar a folosind a doua structura am avea complexitatea $O(N*L)$ . De asemenea mentionam posibilitatea folositii algoritmului randomizat de potrivire a sirurilor de caractere numit Rabin Karp pentru calcularea matricii cost ceea ce ar fi dus la o solutie mai scurta si la un cod mai clar. Ne cerem scuze pentru eventualele neplaceri cauzate de aceasta situatie.\r\n\r\nBafta la urmatorul concurs! (undeva prin februarie...)\r\n',9258,'public',NULL,NULL),('preoni-2007/runda-4/9','preONI 2007, Runda 4, Clasa a 9-a si gimnaziu','2007-03-07 12:02:53','2007-03-25 06:21:45','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda4_9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-4\r\n*(active) \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/runda-4/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-4/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda4_9\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\n==include(page=\"preoni-2007/prelungiri\")==\r\n\r\nRunda se desfasoara *Duminica 25 martie*, la ora {*09^00^*} si va dura *{color:red}4h 15min*.\r\nParticipantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2007/clasament/runda-4/9.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda4_9\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda4_9',NULL,NULL),('preoni-2007/runda-4/11-12','preONI 2007, Runda 4, Clasele 11-12','2007-03-07 12:12:40','2007-03-25 06:22:21','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda4_1112\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-4\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-4/10\r\n*(active) \'Clasele 11-12\':preoni-2007/runda-4/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-4/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda4_1112\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\n==include(page=\"preoni-2007/prelungiri\")==\r\n\r\nRunda se desfasoara *Duminica 25 martie*, la ora {*09^00^*} si va dura *{color:red}4h 15min*.\r\nParticipantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2007/clasament/runda-4/11-12.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda4_1112\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda4_1112',NULL,NULL),('rotatie-lexicografic-minima','Rotatie lexicografic minima','2007-03-30 07:38:31','2009-02-20 01:12:57','h1. Rotatie lexicografic minima\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"m_dersidan\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Mircea Pasoi_)\r\n\r\nAcest articol reprezinta un studiu de caz al unei probleme care poate fi considerata \"clasica\", fiind studiata inclusiv de cunoscutul profesor Edsger Wybe Dijkstra. Deoarece problema a aparut recent la diverse concursuri de informatica, prezinta interes pentru cei care se pregatesc pentru participarea la acestea.\r\n\r\nh2. Enunt\r\n\r\nIn continuare vom prezenta doua formulari ale acestei probleme care au aparut recent la concursuri:\r\n\r\nCateodata programatorii au metode din cele mai diverse pentru a-si ascunde parolele. De exemplu, sa vedem cum Billy \"Hacker\" Geits isi ascunde propriile parole. Billy isi alege un sir de caractere de lungime $L < 100.000$ format din litere mici ale alfabetului latin. Pentru acest sir de caractere Billy face toate cele $L-1$ deplasari circulare la stanga cu o pozitie si le pune unele sub altele. Dintre aceste $L-1$ siruri astfel obtinute, inaintea carora se trece sirul initial, se alege cel care este primul in ordine lexicografica, parola constituind-o un prefix al acestuia.\r\nScrieti un program care pentru un sir $S$ dat determina pozitia celei \"mai mici\" (primei) deplasari in ordine lexicografica. Daca cel mai mic sir de caractere apare de mai multe ori, se se cere cea mai mica pozitie pe care acesta incepe.\r\n(ACM $2003-2004$, regionala Europei de sud-est)\r\n\r\nIntr-un seif se afla niste documente pe care trebuie sa le extrageti. Problema este ca seiful este prevazut cu un terminal care necesita introducerea unei parole pentru a putea deschide seiful. La accesarea seifului, pe ecranul terminalului este afisat un cuvant cheie format din litere mici ale alfabetului englezesc. Parola este data de cea mai mica rotatie la stanga (in ordine lexicografica) a cuvantului cheie.\r\nFisierul de intrare $_password.in_$ contine pe prima linie un sir de caractere format din litere mici ale alfabetului englezesc. Lungimea sirului din fisierul de intrare este un numar intreg cuprins intre $1$ si $100 000$.\r\nFisierul de iesire $_password.out_$ trebuie sa contina un singur numar care reprezinta numarul de deplasari circulare la stanga ale sirului din fisierul de intrare necesare pentru a obtine parola de acces ceruta. Daca exista mai multe solutii va fi aleasa cea care necesita un numar minim de deplasari circulare la stanga.\r\n(Bursele Agora $2003-2004$, Runda $44$)\r\n\r\nh2. Solutia naiva\r\n\r\nO solutie triviala de complexitate $O(N^2^)$ poate fi obtinuta parcurgand succesiv rotatiile si tinand cont de faptul ca compararea a doua siruri are complexitatea $O(N)$ in cel mai defavorabil caz. Prezentam in continuare pseudocodul:\r\n\r\n== code(c) |\r\n\r\nmin <- 0; R0 <- S;\r\n\r\npentru i = 1, N-1 executa\r\n    construieste Ri in functie de Ri-1\r\n    daca Rmin > Ri atunci min <-i;\r\nsfarsit pentru\r\nscrie min\r\n==\r\n\r\nh2. Solutia $O(N*log N)$\r\n\r\nPrecizam intai ca atat o solutie $O(N*lg^2^ N)$ cat si una $O(N*lg N)$ pot fi obtinute folosind structura de date \"siruri de sufixe\" $(1)$. Din pacate aceste solutii nu sunt foarte usor de implementat, iar constanta din notatia $O$ este destul de mare cat sa merite cautarea unei solutii alternative. Vom prezenta in continuare o solutie de complexitate $O(N*lg N)$, mult mai usor de implementat odata ce este inteleasa.\r\n\r\nPrimul pas pentru obtinerea acestei solutii este folosirea unei strategii de tip \"turneu\", si anume la fiecare iteratie se pastreaza o lista cu rotatiile care ar putea fi minime. Initial lista va avea toate cele $N$ rotatii, iar de fiecare data se iau rotatiile doua cate doua din lista si se elimina cea mai mare dintre cele doua din punct de vedere lexicografic. Procesul se reia pana cand se obtine o lista cu un singur element, reprezentand rotatia minima. Cum la fiecare pas numarul de elemente din lista se injumateste, este usor de vazut ca procesul nu se va repeta de mai mult de $[log ~2~ N]$ ori. Desi la prima vedere acest algoritm are timpul de rulare $O(N^2^*lg N)$, vom arata in continuare ca sunt suficiente $O(N)$ comparatii de caractere per total la fiecare repetare:\r\nFie $R ~i~$ si $R ~j~$ doua rotatii (presupunem fara a restrange generalitatea ca $i < j$) aflate pe pozitii consecutive in lista, care urmeaza sa fie comparate, una din fiind aleasa pentru eliminare. Vom demonstra in continuare ca este suficienta compararea acestor rotatii folosindu-ne doar de primele $j - i$ caractere.\r\n\r\ntable{border:1px solid black}.\r\n|_=. $i$|_=. $*...*$|_=. $*j-1*$|=. $*j*$|=. $*...*$|=. $*2j-i-1*$|={background:gray}. $*2j-i*$|={background:gray}. $*...*$|={background:gray}. $*0*$|={background:gray}. $*...*$|={background:gray}. $*i-1*$|\r\n\r\n$*A = i...j-1*$\r\n$*B = j...2j-i-1*$\r\n$*C = 2j-i...i-1*$ (indicii sunt considerati $modulo N$ )\r\n\r\nFie sirul $R ~i~$ impartit in trei bucati $A$, $B$, $C$, ca in figura de mai sus. Conform figurii, $R ~i~ = ABC$, iar $R ~j~ = BCA$, bucatile $A$ si $B$ avand fiecare $j-i$ caractere. Comparand doar primele $j-i$ caractere, vom compara bucatile $A$ si $B$, astfel:\r\n\r\n* $A < B -> R ~i~ < R ~j~ -> se elimina R ~j~$\r\n* $A > B -> R ~i~ > R ~j~ -> se elimina R ~i~$\r\n* $A = B -> se elimina R ~j~ ( se presupune ca R ~i~ < R ~j~ )$\r\n\r\nEste evident ca in primele doua cazuri decizia de eliminare este corecta. Daca $A = B$ , iar decizia luata de eliminare a fost gresita, anume $R ~i~ > R ~j~$, cum $R ~i~ = ABC = AAC$ si $R ~j~ = BCA = ACA$, inseamna ca $A > C$ (daca $A$ ar fi fost egal cu $C$ atunci $R ~i~ = R ~j~$, si nu ar mai fi contat ce element se elimina), deci elementul pastrat va fi oricum eliminat de rotatia $R ~2j-i~ = CAA$ sau de o alta rotatie care s-a dovedit a fi mai mica decat $CAA$ la pasii anteriori. La a i-a parcurgere a listei, distanta intre doua rotatii aflate pe pozitii consecutive in lista este maxim $2^i-1^$, iar in lista sunt cel mult $[ n / 2^i-1^ ]$ elemente, astfel facandu-se $O(N)$ comparatii. In acest mod obtinem un algoritm corect de complexitate $O(N * log N)$.\r\n\r\n==code(c) |\r\nL <- {0,1,2,...,N-1};\r\ncat timp |L|>1 executa\r\n    pentru k <- 1, |L|-1, +2 executa\r\n    i <- L[k]; j <- L[k+1];\r\n    A <- S[i..j-1]; B <- S[j..2j-i-1];\r\n    daca A <= B atunci elimina L[k+1];\r\n        altfel elimina L[k];\r\n    sfarsit pentru\r\nsfarsit cat timp\r\nscrie L[1]\r\n==\r\n\r\nSpre exemplu, pentru sirul $S = (\"m\", \"i\", \"s\", \"s\", \"i\", \"s\", \"s\", \"i\", \"p\", \"p\", \"i\")$ lista va contine initial elementele ${0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}$\r\nLa primul pas se efectueaza (caracterele ingrosate sunt cele ce se vor compara):\r\n$R0 = mississippi > R1 = ississippim$\r\n$R2 = ssissippimi = R3 = sissippimis$\r\n$R4 = issippimiss < R5 = ssippimissi$\r\n$R6 = sippimissis > R7 = ippimississ$\r\n$R8 = ppimississi = R9 = pimississip$\r\nLista va fi acum ${1, 2, 4, 7, 8, 10}$\r\nPasii urmatori sunt:\r\n$R1 = ississippim < R2 = ssissippimi$\r\n$R4 = issippimiss > R7 = ippimississ$\r\n$R8 = ppimississi > R10 = imississipp$\r\n$L = {1, 7, 10}$\r\n$R1 = ississippim > R7 = ippimississ$\r\n$L = {7, 10}$\r\n$R7 = ippimississ > R10 = imississipp$\r\n$L = {10}$\r\n\r\np=. !rotatie-lexicografic-minima?image1.jpg!\r\n\r\nh2. Solutia $O(N)$\r\n\r\nVom incerca acum sa obtinem un algoritm de complexitate liniara folosind alte idei de rezolvare. Algoritmul pe care il vom propune in continuare functioneaza ca si algoritmul trivial mentionat mai sus, anume parcurgand rotatiile succesiv. La fiecare pas se vor pastra trei variabile $min, p, l$ cu semnificatia ca rotatiile $R ~0~, R ~1~, ... R ~p-1~$ au fost parcurse pana acum, iar $R ~min~$ este o rotatie dintre acestea care ar putea fi cea lexicografic minima (toate celelalte din cele parcurse sigur nu pot fi solutia finala). De asemenea, variabila $l$ va semnifica ca primele $l$ caractere din $R ~min~$ sunt egale cu primele $l$ caractere din $R ~p~$, $R ~p~$ fiind urmatoarea rotatie ce va fi procesata. Cunoscand aceste informatii, la fiecare pas se va compara al $l+1-lea$ caracter din $R ~min~$ $(S[min+l])$ cu al $l+1-lea$ din $R ~p~ (S[(p+l) mod N])$, iar in functie de rezultat se va lua o decizie:\r\n\r\n* $*S[min+l] = S[(p+l) mod N]* ->$ se va incrementa variabila $l$ cu o unitate deoarece inca o pereche de caractere se potrivesc\r\n* $*S[min+l] < S[(p+l) mod N]* ->$ putem trage imediat concluzia ca $R ~min~ < R ~p~$ , iar mai mult, din faptul ca primele $l$ caractere se potrivesc putem spune ca $R ~min+i~ < R ~p+i~$ pentru $0 <= i <= l$; cum $R ~min~$ era rotatia \"candidata\" la solutia finala dintre $R ~0~, R ~1~, ... R ~p-1~$ si este mai mica ca $R ~p~$, iar pentru orice $R ~p+i~ (1 <= i <= l)$ exista $R ~min+i~ < R ~p+i~$, despre care se stie ca nu poate fi solutia finala, $R ~min~$ va repezenta in continuare rotatia candidata la solutie dintre $R ~0~, R ~1~, ... R ~p-1~, R ~p~, R ~p+1~, ... R ~p+l~$. Asadar $p$ va deveni $p+l+1$, iar $l$ va deveni $0$ (deoarece nu se cunosc inca informatii despre $R ~min~$ si $R ~p+l+1~$)\r\n* $*S[min+l] > S[(p+l) mod N]* ->$ asemanator cu cazul anterior putem concluziona ca $R ~min+i~ > R ~p+i~$ pentru $0 &le; i &le; l$; asadar putem face doua observatii:\r\n$1) R ~min+i~ (0 <= i <= l)$ nu poate candida la solutie, si cum se stia dinainte ca nici $R ~0~, R ~1~, ... R ~min-1~$ nu pot, primul candidat posibil este $R ~min+l+1~$; \r\n$2) Cum R ~min~$ era candidatul pana in prezent, iar $R ~p~ < R ~min~$, din $R ~0~, R ~1~, ... R ~p~$ singurul candidat posibil este $R ~p~$.\r\nVariabila $min$ va deveni $max(min+l+1, p)$, $p$ va deveni $max(min+l+1, p)+1$, iar $l$ va fi egal cu $0$.\r\n\r\nUn aspect al acestui algoritm care ar putea parea \"misterios\" este motivul pentru care complexitatea este liniara. Vom considera $T = min+p+l$ si putem observa ca dupa fiecare comparatie $T$ creste cu cel putin o unitate. Cum niciuna din cele trei variabile nu poate depasi valoarea $N$, numarul de iteratii este proportional cu $N$ (se poate arata ca nu va depasi $2*N-3$), de unde si complexitatea $O(N)$.\r\n\r\n==code(c) |\r\nmin <- 0; p <- 1; l <- 1;\r\ncat timp (p < N) AND (min+l+1 < N) executa\r\n    daca S[min+l] = S[(p+l) mod N] atunci l <- l+1;\r\n    daca S[min+l] < S[(p+l) mod N] atunci p <- p+l+1; l <- 0;\r\n    daca S[min+l] > S[(p+l) mod N] atunci min <- max(min+l+1, p); p <- min+1; l <- 0;\r\nsfarsit cat timp\r\nscrie min\r\n==\r\n\r\nVom simula algoritmul pentru sirul $S = (\"m\", \"i\", \"s\", \"s\", \"i\", \"s\", \"s\", \"i\", \"p\", \"p\", \"i\").$\r\n\r\ntable{example}.\r\n|_=. $pas$|_=. $min$|_=. $p$|_=. $l$|_=. $S[min+l]$|_=. $S[p+l]$|_=. $caz$|\r\n| $1$ | $0$ | $1$ | $0$ | $m$ | $i$ | $S[min+l] > S[p+l]$ |\r\n| $2$ | $1$ | $2$ | $0$ | $i$ | $s$ | $S[min+l] < S[p+l]$ |\r\n| $3$ | $1$ | $3$ | $0$ | $i$ | $s$ | $S[min+l] < S[p+l]$ |\r\n| $4$ | $1$ | $4$ | $0$ | $i$ | $i$ | $S[min+l] = S[p+l]$ |\r\n| $5$ | $1$ | $4$ | $1$ | $s$ | $s$ | $S[min+l] = S[p+l]$ |\r\n| $6$ | $1$ | $4$ | $2$ | $s$ | $s$ | $S[min+l] = S[p+l]$ |\r\n| $7$ | $1$ | $4$ | $3$ | $i$ | $i$ | $S[min+l] = S[p+l]$ |\r\n| $8$ | $1$ | $4$ | $4$ | $s$ | $p$ | $S[min+l] > S[p+l]$ |\r\n| $9$ | $6$ | $7$ | $0$ | $s$ | $i$ | $S[min+l] > S[p+l]$ |\r\n| $10$ | $7$ | $8$ | $0$ | $i$ | $p$ | $S[min+l] < S[p+l]$ |\r\n| $11$ | $7$ | $9$ | $0$ | $i$ | $p$ | $S[min+l] < S[p+l]$ |\r\n| $12$ | $7$ | $10$ | $0$ | $i$ | $i$ | $S[min+l] = S[p+l]$ |\r\n| $13$ | $7$ | $10$ | $1$ | $p$ | $m$ | $S[min+l] > S[p+l]$ |\r\n| $14$ | $10$ | 0 | 0 | 0 | 0 | 0 |\r\n\r\nsi, in final, $min = 10$\r\n\r\nh2. Aplicatii\r\n\r\n$Problema 1 (\"acm.sgu.ru\":http://acm.sgu.ru, \"Infinite fraction\":http://acm.sgu.ru/problem.php?contest=0&problem=232)$\r\n\r\nSe dau doua numere naturale $N<=150000$ si $K<=10^9^$ si un vector de cifre $D[0...N-1]$. Se va considera un sir $A$ de numere reale cu partea intreaga $0$, iar partea fractionara a elementului $A[i]$ va fi sirul infinit format din $D[(i+0*K) mod N], D[(i+1*K) mod N], D[(i+2*K) mod N]$ etc. Spre exemplu, pentru $N = 3, K = 2 si D = \'194\'$ se obtine:\r\n$A[ 1 ] = 0.1491491491...$\r\n$A[ 2 ] = 0.9149149149...$\r\n$A[ 3 ] = 0.4914914914...$\r\nSa se gaseasca cel mai mare element ca valoare din sirul $A$, si sa se tipareasca primele $N$ zecimale ale sale.\r\n\r\n$Problema 2 (Selectia lotului national, 2004)$\r\n\r\nSe considera un sir $c ~1~ c ~2~ ...c ~n~$ format din $n &le; 30.000$ caractere din multimea ${A, B}$. Concatenam sirul cu el insusi si obtinem un sir de lungime $2n$. Pentru un indice $k (1&le;k&le;2n)$ consideram subsecventele de lungime cel mult $n$, care se termina pe pozitia $k$, iar dintre acestea fie $s(k)$ subsecventa cea mai mica in ordine lexicografica. Determinati indicele $k$ pentru care $s(k)$ are lungimea cea mai mare.\r\n\r\n$Problema 3$\r\n\r\nSe dau doua poligoane in plan fiecare avand $n &le; 1 000 000$ varfuri. Poligoanele sunt date prin coordonatele varfurilor lor in ordine trigonometrica. Sa se verifice daca cele doua poligoane sunt asemenea.\r\n\r\n$Problema 4$\r\n\r\nProblema \"password\":problema/password de pe \"infoarena\":http://infoarena.ro.\r\n\r\nh2. Bibliografie\r\n\r\n# \"Siruri de sufixe\" (Cosmin Negruseri, Adrian Vladu), GInfo 15/7, noiembrie 2005\r\n# \"Solutii rundele 41-50\" (Cosmin Negruseri), GInfo 14/5\r\n# \"E.W.Dijkstra Archive: Home page\":http://www.cs.utexas.edu/users/EWD/',2044,'public',3696,NULL),('blog/arenainfo','infoarena are un nou nume: arenainfo','2007-04-01 00:00:00','2007-04-01 00:00:00','Dupa lungi dezbateri, echipa infoarena a decis sa schimbe denumirea site-ului _infoarena_ in _arenainfo_.\r\n\r\nSuntem nevoiti sa schimbam denumirea site-ului nostru din cauza unui proces intentat de catre grupul croat _Infoarena_, detinator al  marcilor _Infoarena_, _Infoarena Business Journal_ si _Infoarena Business TV_. Grupul croat considera ca site-ul nostru aduce prejudicii materiale semnificative imaginii companiei. De altfel, ca parte a deciziei tribunalului Bucuresti, Asociatia infoarena va plati daune in valoare de $1,407,000 pe parcursul a 4 ani.\r\n\r\nAm inceput procesul de rebranding cu noua sigla _arenainfo_ (coiful cu ochelari privind spre trecut).\r\nIn curand vom transfera activitatile pe domeniul arenainfo.ro.\r\n\r\n!stiri/arenainfo?arenainfo2.png!\r\n\r\nEchipa _arenainfo_\r\n',13,'protected',NULL,NULL),('preoni-2007/runda-4/solutii','Solutii preONI 2007, Runda 4','2007-03-25 08:10:31','2008-01-06 16:03:15','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Solutii Runda 4\r\n\r\nh2. \'Next\':problema/next\r\n\r\nh3. (problema usoara, clasa a 9-a)\r\n\r\nFolosind operatii pe numere mari se calculeaza restul lui $N$ la numarul $D$. Fie $R$ acest rest, se va aduna la numarul $N$ valoarea $(D-R) mod D$ ({$a mod b$} reprezinta restul numarului $a$ la impartirea cu $b$). Numarul astfel obtinut va reprezenta primul numar mai mare sau egal decat $N$ divizibil cu $D$. O prezentare detaliata a modului in care se pot implementa operatiile cu numere mari necesare se gaseste \'aici\':http://infoarena.ro/Multe-smenuri-de-programare-in-CC-si-nu-numai. Complexitatea rezolvarii este $O(lg N)$.\r\n\r\nh2. \'Shop\':problema/shop\r\n\r\nh3. (problema medie, clasa a 9-a)\r\n\r\nLa prima vedere, problema este asemanatoare cu problema \'rucsacului\':http://en.wikipedia.org/wiki/Knapsack_problem, deci se poate aborda folosind metoda programarii dinamice. Avand in vedere limita mare pentru numarul $L$ o astfel de abordare nu ar fi obtinut punctaj maxim.   Avand in vedere ca toate monezile sunt puteri ale numarului $C$, exista o rezolvare greedy: se determina cel mai mare tip de moneda $C^A{~i~}^$ disponibil si se foloseste un numar maxim posibil de astfel de monede (minimul dintre $L/C^A{~i~}^$ si $B{~i~}$). Complexitatea unei astfel de solutii este $O(log{~C~} L)$. O solutie care ar fi efectuat scaderi repetate ale cele mai mari monezi ar fi obtinut de asemenea punctaj maxim.\r\n\r\nh2. \'Dezastru\':problema/dezastru\r\n\r\nh3. (problema grea, clasa a 9-a)\r\n\r\nDaca o problema de probabilitati ar fi putut incurca o parte a concurentilor de clasa a 9-a, exemplele date in enunt reprezinta un indiciu destul de clar in legatura cu modalitatea de rezolvare. Din moment ce evenimentele pot aparea in orice ordine, avem $N!$ posibilitati. Ar trebui, deci, sa generam toate permutarile, sa calculam pentru fiecare permutare produsul primelor $K$ valori, si sa facem media aritmetica a rezultatelor obtinute. Problema se reduce succesiv la aranjamente si apoi la combinari, fiind suficient sa consideram toate modurile de a alege $K$ evenimente, indiferent de ordine. Solutiile cu permutari si aranjamente obtin punctaje partiale, in functie de grija acordata implementarii.\r\n\r\nProblema se poate rezolva si folosind programarea dinamica. Se construieste matricea $A{~i,j~}$ cu semnificatia suma tuturor produselor de $j$ factori alesi din primele $i$ numere. Recurenta se poate calcula usor {$A{~i,j~}=A{~i-1,j~}+A{~i-1,j-1~}*P{~i~}$}. Probabilitatea ceruta va fi $A{~n,k~}$ impartita la $C{~n,k~}$ (combinari de $n$ luate cate {$k$}). Complexitate $O(n*k)$.\r\n\r\nh2. \'Bowling\':problema/bowling\r\n\r\nh3. (problema usoara, clasa a 10-a)\r\n\r\nIn primul rand, pentru a intelege solutia acestei probleme si altor probleme asemanatoare se recomanda citirea urmatoarelor documente despre teoria jocurilor:\r\n\r\n* \'Teoria jocurilor: numerele Sprague-Grundy\':http://www.ginfo.ro/revista/14_5/mate.pdf, \'GInfo Mai 2004\':http://www.ginfo.ro, Cosmin Negruseri\r\n* \'Game Theory Text: Impartial Combinatorial Games\':http://www.math.ucla.edu/~tom/Game_Theory/comb.pdf, Thomas Ferguson\r\n\r\nAceasta problema se regaseste in literatura de specialitate si cu titlul de _Kayles_. Rezultatul pentru un joc se poate calcula in functie de $XOR$-ul numerelor _Grundy_ pentru fiecare secventa de popice din sir. Cum $N &le; 50.000$, trebuie calculate valorile Grundy pentru fiecare secventa de $i$ popice cu $i &le; 50.000$. Acestea se pot calcula in complexitate patratica si se pot pune in sursa ca un sir de constante. O alta solutie se foloseste de observatia ca incepand cu $i = 72$ sirul de valori se repeta cu perioada $12$. Pentru fiecare test din fisier, complexitatea rezolvarii este $O(N)$.\r\n\r\nh2. \'Regiuni\':problema/regiuni\r\n\r\nh3. (problema medie, clasa a 10-a, problema usoara, clasele 11-12)\r\n\r\nAceasta problema a aparut din cauza faptului ca autorul a inteles gresit problema Druizi de la concursul .campion. Dupa ce am discutat problema cu mai multe persoane am observat ca majoritatea pornesc de la problema mai simpla de a vedea daca doua puncte sunt sau nu in acelasi grup. Ideea mea initiala este putin diferita: rezolvam problema adaugand pas cu pas cate o dreapta si mentinand informatia despre grupuri. Cand adaugam o dreapta iteram peste toate grupurile. Un grup va fi impartit in alte doua: punctele din stanga dreptei si punctele din dreapta. E posibil ca unul din aceste doua grupuri sa fie vid si atunci nu il mai retinem. Un grup il impartim in doua in $O(a)$ operatii unde a este numarul de elemente din grup. Toate grupurile vor avea in total $a1 + a2 + ... + ai + ... = M$ elemente, deci pentru a actualiza grupurile adaugand o dreapta facem $O(M)$ pasi. Astfel solutia are complexitatea finala $O(N * M)$, si este foarte usor de implementat.\r\n\r\nAlte solutii ar fi determinarea pentru fiecare punct a unui vector ce ne spune pentru fiecare dreapta in ce parte e situat punctul. Daca doi astfel de vectori asociati la doua puncte sunt egali, atunci cele doua puncte sunt situate in aceiasi regiune. Pentru determinarea egalitatii vectorilor s-ar fi putut folosi o sortare naiva si astfel am fi avut o solutie de complexitate $O(MN log M)$ sau am fi putut folosi radix sort pentru a o aduce la $O(MN)$. Aceste doua solutii folosesc $O(MN)$ memorie. Alta solutie ar fi sa obtinem un cod hash pentru fiecare vector, aceasta solutie are complexitatea $O(MN)$ ca timp si $O(M + N)$. memorie. Pentru a face probabilitatea de coliziune cat mai mica putem folosi cate doua coduri diferite pentru fiecare vector. Alta observatie ar fi ca vectorii sunt binari si pastrand informatia pe biti folosim mai putina memorie si avem mult mai putine operatii la comparare daca vrem sa folosim solutia in $O(MN log M)$.\r\n\r\nh2. \'Elimin 2\':problema/elimin2\r\n\r\nh3. (problema grea, clasa a 10-a)\r\n\r\nPentru a afla numarul maxim palindrom care este subsir al numarului $N$ vom utiliza metoda programarii dinamice. Fie {$L{~i,j~}$} lungimea maxima a unui numar palindrom care se gaseste intre pozitiile $i$ si $j$ din numarul {$N$}. In momentul in care construim tabloul $L$ consideram ca un numar poate incepe si cu cifra {$0$}. Initial, {$L{~i,i~}$} = 1, pentru orice $i$ de la $1$ la numarul de cifre ale lui {$N$}. Vom calcula elementele tabloului $L$ crescator in functie de marimea intervalelor {$(i,j)$}. Daca consideram ca {$LEFT{~c,i~}$} este cea mai mica pozitie {$&ge; i$} in care apare cifra $c$ in numarul $N$ si {$RIGHT{~c,i~}$} cea mai mare pozitie {$&le; i$} in care apare $c$ in numarul $N$, avem urmatoarea relatie de recurenta:\r\n{$L{~i,j~}$} = maxim({$L{~i+1,j~}$}, {$L{~i,j-1~}$}, {$L{~i+1, RIGHT[N[i]][j]-1~} + 2$}, {$L{~LEFT[N[j]][i]+1, j-1~} + 2$}), unde prin {$N{~i~}$} s-a notat a $i$-a cifra a numarului {$N$}. Relatia de recurenta trateaza urmatoarele cazuri: \r\n\r\n* nu folosim cifra a $i$-a in solutia optima\r\n* nu folosim cifra a $j$-a in solutia optima\r\n* folosim cifra a $i$-a ( notata $c$ ) in solutia optima. Pentru ca numarul intre $i$ si $j$ sa fie palindrom, este suficient sa aflam ultima pozitie $p$ inainte de $j$ a cifrei c, solutia optima intre $i$ si $j$ obtinandu-se din solutia optima intre $i+1$ si $p-1$ la care adaugam 2 cifre ( cele din capete ).\r\n* folosim cifra a $j$-a ( notata $c$ ) in solutia optima. Se trateaza similar. \r\n\r\nDaca tablourile $LEFT$ si $RIGHT$ sunt construite inainte de a incepe programarea dinamica ( preprocesare ), putem construi tabloul $L$ in complexitate {$O(NR_CIF^2^)$}, unde $NR_CIF$ este numarul de cifre ale lui {$N$}. Dupa ce am construit acest tablou, putem reconstitui solutia optima. Sa presupunem ca solutia optima incepe cu cifra nenula {$c$}. Fie $x$ prima aparitie a cifrei $c$ in numarul $N$, si $y$ ultima aparitie. Vom selecta acea cifra $c$ pentru care valoarea {$L{~x,y~}$} este maxima. Pentru valori egale se alege cifra maxima. Dupa ce am determinat valoarea primei cifre, putem presupune ca dorim sa cautam solutia optima intre pozitiile {$i$} si {$j$} si {$L{~i,j~}$} = {$X$}. Vom pune la capetele solutiei cea mai mare cifra $c$ care indeplineste: {$L{~LEFT[c,i]+1,RIGHT{@[c,j]@}-1~}$} = {$X-2$}.\r\n\r\nDe precizat ca un algoritm de complexitate {$O(NR_CIF^2^)$} si constanta $10$ ar fi obtinut in jur de 50 de puncte.\r\n\r\nh2. \'Distincte\':problema/distincte\r\n\r\nh3. (problema medie, clasele 11-12)\r\n\r\nVom calcula in timp liniar urmatorul vector:\r\n$urm{~i~} = min { j / i < j AND A{~j~} = A{~i~}}$\r\nAstfel, $urm{~i~}$ va fi prima pozitie din dreapta egala ca valoare cu elementul de pe pozitia $i$ (daca nu exista $urm{~i~}$ consideram ca $urm{~i~}$ este egal cu $N+1$). Considerand $N$ puncte in plan cu coordonatele $(i, urm{~i~})$ la care se ataseaza valoarea $A{~i~}$, o intrebare $st &le; dr$ se rezolva facand un query in dreptunghiul $[st..dr] x [dr+1..N]$, adica suma acelor elemente care se afla in interval, iar urmatoarea aparitie la dreapta este in afara intervalului. Acest query ne garanteaza ca se va face doar suma elementelor distincte din intervalul $st..dr$. O rezolvare care imparte vectorul in bucati de $&radic;N$ si rezolva intrebarile in $O(&radic;N)$ ar fi obtinut cel putin $50$ de puncte, desi este probabil sa obtina si punctaj maxim optimizand codul. O rezolvare mai buna din punct de vedere al complexitatii este folosirea arborilor de intervale, tehnica descrisa \'aici\':downloads?action=download&file=arbori_de_intervale.zip si care poate fi folosita si la rezolvarea problemei \'Zoo\':problema/zoo. Din pacate, aceasta solutie este greu de implementat, iar solutia in $O(lg^2^ N)$ probabil ar fi fost prea inceata pentru a obtine punctaj maxim.\r\nRezolvarea problemei se simplifica mult daca se sorteaza intervalele care se dau ca intrebari dupa capatul dreapta, si se proceseaza in aceasta ordine, apoi se afiseaza in ordinea initiala. Parcurgand intervalele descrescator dupa capatul dreapta se poate mentine suma punctelor care au coordonata $y$ in afara capatului dreapta curent, si se pot calcula raspunsurile pentru intervale in timp $O(log N)$ folosind fie un arbore de intervale, fie, si mai simplu, cu un arbore indexat binar.\r\n\r\nh2. \'Laser\':problema/laser\r\n\r\nh3. (problema grea, clasele 11-12)\r\n\r\nVom considera semidreptele ce pleaca din origine si trec printr-un capat al unui segment. Vor exista $2*N$ astfel de semidrepte. Pentru fiecare din cele $2*N$ unghiuri formate consideram bisectoarea sa. Orice alta semidreapta ce pleaca din origine va intersecta aceleasi segmente cu una din cele $2*N$ bisectoare. Deci Gigel nu trebuie sa traga decat in unele din aceste bisectoare. In loc de bisectoare se putea considera orice alta semidreapta strict in interiorul unghiului, dar bisectoarea este mai usor de calculat. Avand maxim $2*N$ bisectoare ne vom incadra in limitarea de $10.000$ de trageri.\r\n\r\nVom forma un sistem cu $N$ ecuatii si $2*N$ necunoscute astfel: pentru un segment $i$ se formeaza o ecuatie de forma\r\n\r\n* $B{~i~} = X{~1~} * A{~i,1~} + X{~2~} * A{~i,2~} + ... + X{~2*N~} * A{~i,2*N~}$\r\n** $B{~i~}$ este starea initiala a neonului $i$ \r\n** $X{~1~}, X{~2~}, ..., X{~2*N~}$ sunt cele $2*N$ necunoscute care semnifica faptul ca se trage pe directia respectivei bisectoare\r\n** $A{~i,j~} = 1$ in caz ca bisectoarea $j$ intersecteaza segmentul {$i$}, $0$ in caz contrar.\r\n\r\nSistemul se va rezolva modulo $2$ folosind algoritmul lui \'Gauss\':http://en.wikipedia.org/wiki/Gauss_algorithm.\r\n\r\nPentru calcularea valorilor $A{~i,j~}$ se calculeaza unghiul format de semidreptele ce trec prin capetele segmentului $j$ si se testeaza daca semidreapta i se afla in interiorul sau. Trebuie avut grija la eventualele cazuri care apar, in special cand unghiul are o semidreapta in cadranul $4$ si alta in cadranul {$1$}.\r\n\r\nComplexitate $O(n^3^)$\r\n\r\nO optimizare, care insa nu era necesara pentru obtinerea punctajului maxim, ar fi reprezentarea sistemului format pe biti reducand complexitatea la {$O(n^3^ / log n)$}.\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'public',NULL,NULL),('template/implica-te/scrie-articole','template/implica-te/scrie-articole','2007-03-30 16:28:52','2008-12-26 19:09:33','table{margin:0.5em auto;}. |={background-color:#EFEFFF;border:1px solid #9F9FFF}. !<template/implica-te/scrie-articole?icon_pow_community.gif! Acest articol a fost adăugat de ==user(user=\"%user_id%\" type=\"tiny\") ==\r\n\'*Intră aici*\':implica-te/scrie-articole _dacă doreşti să scrii articole sau află cum te poţi_ \'*implica*\':implica-te _în celelalte proiecte infoarena!_ |',15,'protected',NULL,NULL),('template/todo','template/todo','2006-11-12 18:37:46','2008-02-04 20:59:45','table{margin:0.5em auto;}. |={background-color:rgb(241, 245, 252);border:1px solid rgb(171, 213, 245);}. !{vertical-align:middle;}template/todo?progress2.gif! *Aceasta pagina nu este finalizata. Te rugam sa o imbunatatesti.*   |\r\n',1,'protected',NULL,NULL),('acm-icpc-upb-2008/solutii/pkinv','Solutie Pkinv','2008-10-04 14:29:53','2008-11-01 23:41:42','h2(#pkinv). \'Pkinv\':problema/pkinv\r\n\r\nProblema este asemanatoare cu problema \'Perm6\':/problema/perm6 si ne duce cu gandul, in prima faza, la o dinamica de forma $c[i][j]$ = numarul de permutari de $i$ elemente cu $j$ inversiuni. Recurenta iese usor, gandindu-ne cu cat creste numarul de inversiuni in functie de ultimul numar adaugat in permutare: $c[i][j] = c[i-1][j] + c[i-1][j-1] + ... + c[i-1][max(j-i+1, 0)]$. Din pacate, aceasta dinamica are complexitatea $O(N*K^2^)$. Desi dinamica se poate reduce la complexitate $O(N*K)$ folosind sume partiale, ar insemna sa ne indepartam ca idee de solutia optima a problemei. Observam in dinamica de mai sus, ca pentru $K < i &le; N$, functia $max$ va returna mereu valoarea $0$, deci recurenta nu mai variaza in functie de $i$. Astfel, putem considera trecerea de la pasul $i$ la pasul $i+1$ o inmultire de matrici:\r\n<tex>\\begin{pmatrix} c[i][0] & c[i][1] & ... & c[i][k] \\end{pmatrix} * \\begin{pmatrix} 1 & 1 & ... & 1 \\\\0 & 1 & ... & 1 \\\\... \\\\0 & 0 & ... & 1 \\end{pmatrix} = \\begin{pmatrix} c[i+1][0] & c[i+1][1] & ... & c[i+1][k]\\end{pmatrix}</tex>.\r\nFolosind proprietatea de asociativitate a inmultirii matricilor, putem deduce:\r\n<tex>\\begin{pmatrix} c[k+1][0] & c[k+1][1] & ... & c[k+1][k] \\end{pmatrix} * \\begin{pmatrix} 1 & 1 & ... & 1 \\\\0 & 1 & ... & 1 \\\\... \\\\0 & 0 & ... & 1 \\end{pmatrix}^{n-k-1} = \\begin{pmatrix} c[n][0] & c[n][1] & ... & c[n][k]\\end{pmatrix}</tex>.\r\nInmultirea a doua matrici $K x K$ are complexitate $O(K^3^)$, iar ridicarea la putere are nevoie de $O(logN)$ astfel de inmultiri. Pentru a calcula dinamica pana la pozitia $K+1$, putem aplica recurenta de mai sus avand o complexitate $O(K^3^)$. Complexitatea finala este $O(K^3^*logN)$.',2044,'public',NULL,NULL),('blog/problema-saptamanii-2007-10-30','Problema saptamanii','2007-10-30 03:01:49','2008-11-15 13:41:14','Dupa feedbackul pozitiv de la primele doua probleme, m-am decis sa postez cate o problema draguta cam la doua saptamani.\r\n\r\nProblema curenta: _Un terorist se afla pe o axa infinita la pozitia X0 in momentul T = 0. La fiecare secunda teroristul se muta la dreapta cu Y unitati (Y poate fi si negativ). X0 si Y sunt numere intregi fixate pe care noi nu le stim. La fiecare secunda putem verifica exact o coordonata de pe axa si vom afla daca teroristul e sau nu acolo. Se cere determinarea unei modalitati de a il descoperi pe terorist si de a ii putea prezice pozitiile urmatoare._\r\n\r\nPentru intrebari referitoare la enunt folositi sectiunea de comentarii. Solutiile complete trimiteti-mi-le ca mesaj privat.\r\n\r\n',1490,'protected',2244,NULL),('automate-finite-si-kmp','Automate finite si KMP','2005-01-12 00:00:00','2010-02-04 11:20:30','h1. Automate finite si KMP\r\n\r\n(Categoria _Algoritmi_, Autor _Adrian Vladu_)\r\n\r\nIn acest articol vom aborda cele mai comune probleme legate de pattern matching si vom oferi suportul teoretic necesar intelegerii algoritmului Knuth-Morris-Pratt, pornind de la potrivirea standard cu automate finite si rafinand-o treptat pana la un algoritm de complexitate {$O(n + m)$}. Toate acestea intr-o maniera usor de inteles ;)\r\n\r\nh2. Automate finite\r\n\r\nh3. Ce sunt automatele finite ?\r\n\r\nUn automat finit este definit ca un cvintuplu {@<@}{$Q, q{~0~}, A, &#0931;, &#0948;$}{@>@} unde $Q$ este o multime finita de stari {$Q = {q{~0~}, q{~1~}, ... q{~n~}}$}, $q{~0~}$ apartine $Q$ ({$q{~0~}$} = stare initiala), $A$ inclus in $Q$ ({$A$} = multimea starilor de acceptare), $&#0931;$ este un alfabet, iar functia {$&#0948; : Q x &#0931; -> Q$} este functia de tranzitie a automatului.\r\n\r\nAceasta este definitia matematica si foarte abstractizata a automatelor. Pentru a le intelege mai usor, sa luam un exemplu concret\r\n\r\n!Automate-finite-si-KMP?dfa.jpg!\r\n\r\n* $Q = {q{~0~}, q{~1~}, q{~2~}, q{~3~}}$\r\n* $A = {q{~3~}}$\r\n* $&#0931; = {a, b}$\r\n* &#0948; = \r\n\r\ntable. | &#0948; | a | b |\r\n| 0&nbsp; | 1 | 2 |\r\n| 1 | 3 | 1 |\r\n| 2 | 3 | 0&nbsp; |\r\n| 3 | 3 | 3 |\r\n\r\n\r\nCe inseamna asta? Sa spunem ca automatul primeste un string $s$ = *bbaba*\r\nInitial ne aflam in {$q{~0~}$}. Pentru fiecare element al stringului $s{~i~}$ facem tranzitia {$&#0948;(q{~k~}, s{~i~})$}.\r\n\r\nPornim din {$k = 0$}. Vom avea :\r\n\r\n* $k = 0; &#0948;(0, b) = 2;$\r\n* $k = 2; &#0948;(2, b) = 0;$\r\n* $k = 0; &#0948;(0, a) = 1;$\r\n* $k = 1; &#0948;(1, b) = 1;$\r\n* $k = 2; &#0948;(1, a) = 3;$\r\n\r\nDaca ultima stare obtinuta $q{~k~}$ apartine {$A$}, atunci spunem ca automatul accepta stringul. Altfel spus, daca avem stringul {$s$}, {$lungime(s) = n$}, automatul accepta stringul daca si numai daca $&#0948;( ... &#0948;( &#0948;(0, s{~1~}), s{~2~} ) ..., s{~n~} )$ apartine {$A$}.\r\n\r\nStringurile \'{$aa$}\', \'{$aaaaaaa$}\', \'{$aabababab$}\', \'{$aaaba$}\', \'{$ba$}\', \'{$aba$}\' sunt acceptate de automat, dar \'{$abbbbbb$}\', \'{$bba$}\' nu.\r\n\r\nh3. La ce folosesc ?\r\n\r\n# Inteligenta artificiala (prima si cea mai involuata stare a inteligentei artificiale)\r\n# Aplicatii teoretice si probleme de matematica :)\r\n# Pattern matching\r\n\r\nSe dau stringurile $M$ si {$N$}. Se cere sa gasim toate aparitiile lui $N$ in {$M$}.\r\nVom numi {$M{~i~}$} prefixul lui $M$ de lungime {$i$}. Presupunand ca avem construit automatul care accepta stringul {$N$}, vom cauta toate prefixele lui $M$ acceptate de automat, deci toate numerele $1 &le; i &le; lungime(M)$ cu proprietatea ca automatul accepta stringul {$M{~i~}$}.\r\n\r\nh3. Algoritm_potrivire_cu_automat_finit\r\n\r\n== code(c) | \r\nn = lungime(N)\r\nm = lungime(M)\r\nq = 0;\r\npt i <- 1, m\r\n    q = d(q, M[i])\r\n    daca q apartine A\r\n        scrie \"potrivire la pozitia \" i - n + 1\r\n==\r\n\r\n* Complexitate : $O(n)$\r\n\r\nSa vedem cum se construieste automatul de potrivire pentru un string {$N$}. Fie {$m = lungime(M)$}. Construim un automat cu $m + 1$ stari {{$q{~0~}, q{~1~}, ... q{~m~}$}}, $A = {q{~m~}}$ . Faptul ca ne aflam in starea $x$ inseamna ca au fost acceptate primele $x$ caractere din sirul de intrare.\r\nDin fiecare stare $q{~x~}$ apartine $Q$ si pt fiecare $c$ apartine $S$ construim $&#0948;(x, c) = y$ cu proprietatea ca $M{~y~}$ este cel mai lung prefix al lui $M$ care este sufix al lui $M{~x~}c$ (prefixul de lungime $x$ al lui {$M$}, concatenat cu caracterul {$c$}).\r\n\r\n\r\n\r\nh3. Algoritm_constructie_automat_finit\r\n\r\n== code(c) |\r\nm <- lungime(M)\r\npt q <- 0, m\r\n    pt c apartine S\r\n        gaseste M[i] = cel mai lung prefix al lui M cu M[i] sufix al lui M[q]c\r\n            d(q, c) = i\r\n==\r\n\r\n* Complexitate : linia $4$ are complexitatea $O(m^2^)$ (implementata in maniera bruta) si se executa de $(m + 1) * |&#0931;|$ ori => complexitate totala $O(m^3^ * |&#0931;|)$\r\n\r\nPractic, algoritmul calculeaza pentru toate {$0 &le; i &le; m$}, $c$ apartine $S$ cat de mult putem lua de la sfarsitul lui $M{~i~}c$ astfel incat acesta sa fie un \"inceput\" de {$N$}.\r\n\r\nAcesta se poate rafina, eliminand operatii redundante, dupa cum vom vedea in cele ce urmeaza.\r\n\r\nh2. Algoritmul KMP\r\n\r\nGaseste toate aparitiile unui string $N$ in $M$ in timp {$O(n + m)$}, unde {$n = lungime(N)$}, {$m = lungime(M)$}. O parte esentiala a sa este functia prefix $&pi; : {1..n} -> {0..n-1}$ unde $&pi;{~i~}$ = cel mai lung prefix al lui $M$ care este sufix al lui {$M{~i~}$}. Evident, $M{~&pi;{~i~}~}$ (prefixul de lungime $&pi;{~i~}$ al lui {$M$}) este prefix al lui {$M{~i~}$}, deci {$&pi;{~i~} < i$}.\r\n\r\nh3. Algoritm_calcul_functie_prefix\r\n\r\n== code(c) |\r\nn <- lungime(N)\r\nk <- 0\r\npi[1] <- 0\r\npt i <- 2, n\r\n    cat timp (k > 0) si (N[k + 1] != N[i])\r\n        k <- pi[k]\r\n    daca N[k + 1] = N[i]\r\n        k <- k + 1\r\n    pi[i] <- k\r\n==\r\n\r\nh4.  Analiza complexitatii :\r\n\r\n* la fiecare pas ({$i = 2, n$}) $k$ se incrementeaza cel mult o data, deci pe parcursul algoritmului $k$ se va incrementa de cel mult $n - 1$ ori (linia {$8$})\r\n* in linia {$5$}, $k$ se decrementeaza cel mult pana devine {$0$}, deci se va decrementa de cel\r\nmult $n - 1$ ori pe parcursul algoritmului\r\n* {=>} Complexitate : $O(n)$\r\n\r\nAlgoritmul este similar cu constructia automatului de acceptare. Din fiecare stare $i$ in care s-a acceptat {$N{~i~}$}, vedem cat de mult putem lua de la sfarsitul lui {$N{~i~}$} astfel incat sufixul respectiv sa fie prefix pentru {$N$}. De remarcat ca in cazul in care starea candidata $k$ nu este buna, nu mergem in {$k - 1$}, ci in {$&pi;{~k~}$}. Aceasta este de fapt \"magia\" care ofera complexitate liniara.\r\n\r\nAlgoritmul de potrivire este similar celui al calculului functiei prefix, numai ca aici la fiecare pas $i$ cautam cel mai lung prefix al lui $N$ care este sufix al lui {$M{~i~}$}.\r\n\r\n\r\n\r\nh3. Algoritm_potrivire_KMP\r\n\r\n== code(c) |\r\nm <- lungime(M), n <- lungime(N)\r\nq <- 0\r\npt i <- 1, m\r\n    cat timp (q > 0) si (N[q + 1] != M[i])\r\n        q <- pi[q]\r\n    daca N[q + 1] = M[i]\r\n        q <- q + 1\r\n    daca q = n\r\n        scrie \"potrivire la pozitia \" i - n + 1\r\n==\r\n\r\nAnalog Algoritm_Calcul_Functie_Prefix, complexitatea algoritmului efectiv de potrivire este {$O(m)$}. Astfel rezulta complexitatea liniara a algoritmului KMP $O(n + m)$\r\n\r\nh2. Teme pentru acasa:\r\n\r\n* folosind functia prefix, rafinati constructia automatului finit de acceptare pentru un string, aducand-o la complexitatea $O(m^2^ * |&#0931;|)$\r\n* problema \"Microvirus\":http://www.liis.ro/%7ecampion/problems/2/64/microvirus.htm (hint : construiti automatul de potrivire pentru stringul dat)\r\n* Timus 1158: \"Censored!\":http://acm.timus.ru/problem.aspx?space=1&num=1158\r\n\r\n',2970,'public',3698,NULL),('runda/summer_camp_5','summer_camp_5','2009-08-16 18:06:43','2009-08-16 18:06:43','h1. == roundparam(round_id=\"summer_camp_5\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"summer_camp_5\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"summer_camp_5\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"summer_camp_5\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/summer_camp_5/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"summer_camp_5\" score=\"1\")==',6957,'round: summer_camp_5',NULL,NULL),('runda/summer_camp_5/clasament','Clasament summer_camp_5','2009-08-16 18:06:43','2009-08-16 18:06:43','h1. Clasament ==roundparam(round_id=\"summer_camp_5\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer_camp_5\")==',6957,'round: summer_camp_5',NULL,NULL),('blog/oni-by-net-2007','ONI by NET 2007','2007-04-04 15:50:14','2007-04-04 15:52:56','Elevii care nu s-au calificat la Olimpiada Nationala de Informatica pot participa prin internet la _ONI by NET_. Participantii la _ONI by NET_ sunt evaluati in aceleasi conditii ca si cei de la ONI.\r\n\r\n*Castigatorii au ocazia de a se califica la proba de baraj a olimpiadei nationale!*\r\n\r\nMai multe detalii la \"http://olimpiada.info/bynet/\":http://olimpiada.info/bynet/\r\n\r\n',13,'public',NULL,NULL),('autumn-warmup-2007/solutii/runda-3','Solutii Autumn Warmup, Runda 3','2007-10-08 13:12:36','2007-10-18 21:41:49','h2. \'Dk\':problema/dk\r\n\r\nPentru problema existau diverse rezolvari brute-force, care in functie de calitatea implementarii af fi obtinut pana la $50$ de puncte. \r\nAlgoritmul folosit in rezolvarea pentru $100$ de puncte este Miller-Rabin. Este un algoritm probabilistic care verifica primalitatea unui numar in complexitate $O(c*log Nr)$, unde c este numarul de baze folosite pentru verificare. \r\nDorim sa verificam daca numarul $Nr$ este prim. Primul pas care trebuie efectuat este acela de a-l scrie pe $Nr-1$ ca numar de forma <tex>2^s^ * d</tex>, unde s trebuie sa fie maxim. Pasul urmator este sa verificam 2 relatii:\r\n1. <tex> a^{d}\\ mod\\ n\\ \\neq\\ 1 </tex>  \r\n2. <tex> a^{2^r*d}\\ mod\\ n\\ \\neq\\ -1</tex>, pentru $0 &le; r &le; s-1$ \r\n\r\nDaca ambele relatii sunt simultan indeplinite pentru un numar $a$, atunci stim ca numarul $Nr$ este compus. Daca cel putin una dintre conditii nu este indeplinita se continua verificarile pentru un alt numar $a$. Numerele $a$ cu care se vor face verificarile pot fi, de exemplu, primele 6 numere prime sau o multime de numere prime alese aleator (mai mult de $3$, dar nu mai mult de $7$, pentru ca solutia sa se incadreze in timp).    \r\nComplexitatea logaritmica a algoritmului provine de la faptul ca ridicarile la putere se vor efectua in $O(log n)$. Pentru mai multe detalii consultati CLR-ul sau \'Wikipedia\':http://en.wikipedia.org/wiki/Miller-Rabin_primality_test.\r\n\r\n\r\nh2. \'Kcity\':problema/kcity\r\n\r\nh3. \"Bandwidth\"-ul si \"Pathwidth\"-ul unui graf\r\n\r\nSa consideram ca nodurile unui graf sunt renumerotate cu numere de la $1$ la $N$ si sa notam cu $BMAX$ valoarea maxima a diferentei (in modul) dintre numerele asociate a doua noduri adiacente. \"Bandwidth\"-ul $B$ al unui graf este valoarea minima a lui $BMAX$ dintre toate renumerotarile posibile ale nodurilor. Determinarea acestei valori $B$ nu se poate realiza in timp polinomial. In cadrul problemei date, nodurile au fost deja numerotate corespunzator, astfel incat graful sa aiba un \"bandwidth\" mic, egal cel mult cu valoarea $K$ data.\r\n\r\n\"Pathwidth\"-ul unui graf este un numar ce reflecta cat de mult structura grafului este asemanatoare cu cea a unui drum. Daca un graf $G$ are un \"pathwidth\" $P$, atunci exista un graf-drum $D$, cu nodurile $D{~1~}, D{~2~}, ..., D{~X~}$, avand urmatoarele proprietati:\r\n\r\n* fiecare nod $D{~i~}$ corespunde unei submultimi de cel mult $P$ noduri ale grafului $G$\r\n* oricare doua noduri adiacente ale grafului $G$, $u$ si $v$, se afla impreuna in cel putin una din submultimile $D{~1~},...,D{~X~}$\r\n* orice nod $u$ al grafului $G$ apartine unor multimi $D{~i~}$ care formeaza un sub-drum al grafului $D$ (mai exact, niciun nod $u$ al lui $G$ nu poate sa apartina unui submultimi $D{~i~}$, sa nu apartina unei submultimi $D{~j~}$ {$(j &gt; i)$} si apoi sa apartina din nou unei alte submultimi $D{~k~}$ $(k &gt; j)$\r\n\r\nDaca avem o renumerotare a unui graf $G$ corespunzatoare unui \"bandwidth\" mic, atunci putem obtine si o descompunere cu \"pathwidth\" mic a grafului G, care ne va ajuta sa rezolvam problema.\r\n\r\nh3. Solutie de complexitate $O(N * numar_stari * K^3^)$\r\n\r\nElementele teoretice prezentate mai sus nu sunt neaparat necesare pentru a rezolva problema. Se \"ghiceste\" usor ca problema se rezolva folosind programare dinamica pe un numar exponential de stari, care depinde, insa, numai de $K$, care este o valoare mica.\r\n\r\nVom calcula urmatoarele valori:\r\n\r\n* $minp[i][S]$ = numarul minim de drumuri cu care se pot acoperi nodurile $1,2,...,i$, iar starea la pasul $i$ sa fie $S$\r\n* $minc[i][S]$ = numarul minim de cicluri cu care se pot acoperi nodurile $1,2,...,i$, iar starea la pasul $i$ sa fie $S$ (nu trebuie sa apartina neaparat unui ciclu inchis si nodurile din cadrul starii curente sau cele care apartin deja unor drumuri care au capetele in cadrul starii curente)\r\n\r\nO stare $S$ la pasul $i$ este reprezentata de starea ultimelor $K$ noduri $(i-K+1, i-K+2, ..., i)$. O prima idee de definire a starii este urmatoarea: fiecare nod se poate afla in una din urmatoarele $3$ stari:\r\n\r\n* are gradul $0$ (este un drum ce consta doar din nodul respectiv)\r\n* are gradul $1$ (este un capat al unui drum)\r\n* are gradul $2$ (se afla in interiorul unui drum sau al unui ciclu (in orice caz, daca un nod are gradul $2$, el nu mai prezinta interes in algoritmul nostru)\r\n\r\nDefinind o stare astfel, ar exista $3^K^$ stari in total. La fiecare pas $i$, am considera toate starile $S\'$ de la pasul $i-1$ si, adaugand nodul $i$, impreuna cu unele muchii, la starea $S\'$, am obtine niste stari $S$, pentru pasul $i$. Avem urmatoarele optiuni:\r\n\r\n* pentru cazul acoperii cu drumuri\r\n** nodul $i$ formeaza un drum nou (are gradul $0$) => numarul de drumuri creste cu $1$\r\n** nodul $i$ extinde un drum deja existent (il legam de un nod $j$ de grad $0$ sau $1$, cu conditia sa existe muchia $i-j$) => numarul de drumuri ramane acelasi\r\n** nodul $i$ leaga doua drumuri diferite (il legam de nodurile $j$ si $k$ de grad $0$ sau $1$, unind astfel doua drumuri) => numarul de drumuri scade cu $1$\r\n* pentru cazul acoperirii cu cicluri\r\n** nodul $i$ formeaza un drum nou (are gradul $0$) => numarul de cicluri ramane la fel\r\n** nodul $i$ extinde un drum deja existent (il legam de un nod $j$ de grad $0$ sau $1$, cu conditia sa existe muchia $i-j$) => numarul de cicluri ramane la fel\r\n** nodul $i$ leaga doua drumuri diferite (il legam de nodurile $j$ si $k$ de grad $0$ sau $1$, unind astfel doua drumuri) => numarul de cicluri ramane la fel\r\n** nodul $i$ leaga cele $2$ capete ale unui drum => numarul de cicluri creste cu $1$\r\n** daca nodul $i &gt; K$, trebuie sa ne asiguram, inainte de a trece mai departe, ca nodul $i-K$ are gradul $2$ (se afla in interiorul unui drum sau al unui ciclu) => optiunile de mai sus nu sunt valide decat daca, in urma aplicarii lor, nodul $i-K$ are gradul $2$\r\n\r\nObservam o dificultate in cazul in care nodul $i$ trebuie sa uneasca doua drumuri de grad $1$. In cazul acoperirii cu drumuri, trebuie sa ne asiguram ca el nu leaga capetele aceluiasi drum (inchizand, de fapt, un ciclu, in timp ce noi credeam ca a unit $2$ drumuri). In cazul acoperii cu cicluri trebuie sa putem realiza aceeasi distinctie. Asadar, modul in care am definit starea nu este corect, desi era, poate, cel mai intuitiv.\r\n\r\nO stare va trebui definita in felul urmator: fiecare din cele $K$ noduri ale starii se poate afla in una din urmatoarele situatii:\r\n\r\n* are gradul $0$ (este un drum ce consta doar din nodul respectiv) - se codifica prin $0$\r\n* are gradul $1$ si este capatul unui drum care are un identificator bine specificat - se codifica prin identificatorul drumului\r\n* are gradul $2$ (se afla in interiorul unui drum sau al unui ciclu) - se codifica prin $-1$\r\n\r\nDe exemplu, pentru $K=6$, starea $S=(-1, 1, 0, 2, -1, 1)$ specifica faptul ca primul si al cincilea nod au gradul $2$, al treilea nod are gradul $0$, al doilea si al saselea nod sunt capetele aceluiasi drum, care are identificatorul $1$, iar al patrulea nod este capatul unui drum ce are identificatorul $2$ (celalalt capat fiind ramas undeva in urma).\r\n\r\nConform noii definitii a starilor, acestea trebuie generate explicit. Observam ca doar doua noduri pot fi capetele aceluiasi drum, ca identificatorii drumurilor ii putem genera de la $1$ pana la cate drumuri pot exista intr-o stare (maxim $K$) si ca putem considera identificatorii drumurilor sortati in ordinea in care apar in cadrul starii nodurile ce sunt capetele acestora. De exemplu, starea $S=(-1, 2, 0, 1, -1, 2)$ nu ar avea sens, fiind echivalenta cu cea prezentata mai sus, schimband doar identificatorii drumurilor intre ei. Pentru $K=6$ exista $2364$ astfel de stari.\r\n\r\nRaspunsul dorit il gasim intr-una din starile de la pasul $N$:\r\n\r\n* pentru acoperirea cu drumuri se alege minimul dintre toate valorile $minp[N][S]$\r\n* pentru acoperirea cu cicluri se alege valoarea $minc[N][S]$, unde $S$ este starea in care toate nodurile au gradul $2$ ; daca aceasta valoare este infinit, atunci rezultatul este $-1$\r\n\r\nh2. \'Consir\':problema/consir\r\n\r\nSa presupunem ca dorim sa aflam rezultatul pentru secventa maxima $1, 2 ... M$. Fie $F{~1~}, F{~2~}, ... F{~M~}$ frecventele numerelor de la $1$ la $M$ (numarul de aparitii). Sa construim acum un vector $P$ cu semnificatia $P{~i~} = F{~1~}* F{~2~} * ... * F{~i~}$. Datoria faptului ca rezultatul este mai mic decat $2^63^$ este clar ca nu avem mai mult de 63 de pozitii pentru care $F{~i~}>1$, deci la fiecare pas trebuie sa updatam subsecventele care se termina intr-o pozitie cu $F{~i~}>1$. Algoritmul in pseudocod pentru a calcula vectorul $Res$ cu semnificatia $Res{~i~}$ egal cu numarul de consiruri de lungime $i$ devine\r\n\r\n== code(c) |\r\nRes[M] = P[M];\r\npentru i = n-1, 1 executa\r\n   Res[i] = Res[i+1] + P[M]/P[M-i];\r\n   pentru j astfel incat F[j] >= 2 si j >= i+1\r\n       Res[i] = Res[i] - P[j]/P[j-i-1] + P[j-1]/P[j-i-1];\r\n   sfarsit pentru\r\nsfarsit pentru\r\n==\r\n\r\nh2. \'Polig\':problema/polig\r\n\r\nExista mai multe solutii care se incadreaza in timp pentru limitele date, o idee ar fi ca punctele sa fie sortate dupa unghiul cu axa $Ox$. Apoi, folosind programare dinamica vom construi o matrice cu semnificatia $a[i][j]$ = costul maxim astfel incat sa plecam din orginea planului si sa construim un drum care are ultimele puncte $i$ si $j$. In total, memoria este $O(n^2^)$ si complexitatea in timp $O(n^3^)$. Exista o solutie $O(n^2^ lg{~2~}n)$ propusa de Mugurel Ionut Andreica, gasirea ei o lasam ca un exercitiu pentru cititori :-). Daca aveti nelamuriri nu ezitati sa folositi forumul.',2044,'public',NULL,NULL),('blog/o-problema-misto-solutie','O problema misto - solutie','2007-10-16 06:23:58','2008-11-15 13:41:14','Din dorinta de a face enuntul problemei cat mai simplu am lasat cateva cerinte ale problemei nespecificate. De aici au aparut si cele trei updateuri la text.\r\n\r\nCei care au rezolvat problema sunt: \'Teodorescu Andrei-Marius\':http://infoarena.ro/utilizator/andreitheo87 , Adrian Sandor si Radu Cebanu. \r\n\r\nV-am promis si o solutie:\r\n Impartim planul in patrate de latura unu. Suprapunem toate patratele unul peste celalalt, si cum aria totala a petelor este strict mai mica ca unu rezulta ca va exista un punct care nu este acoperit de vreo pata. Marcam acest punct in toate patratele. Cand le punem inapoi in plan, punctul marcat se transforma in o grila de puncte. Acum putem selecta ca origine oricare dintre aceste puncte si ca axe dreptele paralele cu abscisa respectiv ordonata din sistemul initial, care trec prin punctul ales ca origine.\r\n\r\nSper ca v-a placut, chiar daca e o problema de mate.\r\n\r\n',1490,'protected',2207,NULL),('utilizator/cristi_c','Profil cristi_c','2007-04-10 09:07:53','2007-07-10 10:38:34','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\nOdata cu clasa a V-a am inceput sa studiez informatica la Colegiul National Vasile Alecsandri Galati, obtinand mai multe distinctii ...\r\n\r\nh2. Distinctii primite:\r\n\r\nClasa a V-a (2006-2007) :-Premiul I la olimpiada judeteana de informatica;\r\n                         -Mentiune la olimpiada nationala de informatica;\r\n                         -Premiul I la clasele V-VI la concursul Micul Gates de la Ramnicu-Valcea (site-ul concursului www.miculgates.ro)\r\n\r\n\r\n\r\n',6421,'public',NULL,NULL),('utilizator/ada_s','Profil ada_s','2007-04-17 17:21:29','2008-03-08 12:58:02','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6443,'public',NULL,NULL),('arbori-de-intervale','Arbori de intervale si aplicatii in geometria computationala','2007-04-17 20:24:45','2009-02-20 00:38:02','h1. Arbori de intervale si aplicatii in geometria computationala\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"sima_cotizo\") ==\r\n\r\n(Categoria _Structuri de date_, Autor _Dana Lica_)\r\n\r\nh2. Problema 1\r\n\r\np<>. Se considera $N (N &le; 50 000)$ segmente in plan, dispuse paralel cu axele $OX$ si $OY$. Sa se determine care este numarul total de intersectii dintre segmente.\r\n\r\np<>. In fisierul $_segment.in_$ se gaseste pe prima linie numarul $N$ de segmente, iar pe fiecare dintre urmatoarele $N$ linii cate patru numere naturale mai mici decat $50 000$, reprezentand coordonatele carteziene ale extremitatilor fiecarui segment. Rezultatul se va scrie in $_segment.out_$.\r\n\r\np<>. _Timp de executie: $1 secunda/test$_.\r\n\r\ntable(example). |_. segment.in |_. segment.out |_. Figura |\r\n|^. 5\r\n2 9 13 9\r\n4 6 12 6\r\n1 2 6 2\r\n5 0 5 8\r\n7 5 7 11  |^. 4 |=. !arbori-de-intervale?figure-1.jpg! |\r\n\r\nh2. Algoritmi de \"baleiere\" _(line sweeping)_\r\n\r\np<>. Folosind cunostinte generale de geometrie analitica se poate obtine un algoritm $O(N^2^)$ dar acesta nu se va incadra in limita de timp. \r\n\r\np<>. Pentru rezolvarea acestei probleme vom folosi o tehnica cunoscuta sub numele de \"baleiere\" _(sweeping)_ care este comuna multor algoritmi de geometrie computationala. In baleiere, o dreapta de baleiere verticala, imaginara, traverseaza multimea obiectelor geometrice, de obicei de la stanga la dreapta.  Baleierea ofera o metoda pentru ordonarea obiectelor geometrice, plasandu-le intr-o structura de date, pentru obtinerea relatiilor dintre ele.\r\n\r\nAlgoritmii de baleiere gestioneaza doua multimi de date: \r\n\r\n# _Starea liniei_ de baleiere da relatia dintre obiectele intersectate de linia de baleiere \r\n# _Lista punct-eveniment_ este o secventa de coordonate $x$, ordonate de la stanga la dreapta de obicei, care definesc pozitiile de oprire ale dreptei de baleiere; fiecare astfel de pozitie de oprire se numeste _punct eveniment_; numai in punctele eveniment se intalnesc modificari ale starii liniei de baleiere; pentru unii algoritmi, lista punct-eveniment este determinata dinamic in timpul executiei algoritmului. \r\n\r\np<>. Pentru a rezolva problema, vom deplasa o dreapta de baleiere verticala, imaginara de la stanga la dreapta. Lista punct-eveniment va contine capetele segmentelor orizontale, ce fel de tip sunt (cap stanga sau cap dreapta) si segmentele verticale. Pe masura ce ne deplasam de la stanga la dreapta vom efectua urmatoarele operatii:\r\n\r\n* cand intalnim un capat stang, inseram capatul in starile dreptei de baleiere; \r\n* cand intalnim un capat drept, stergem capatul din starile dreptei de baleiere; \r\n* cand intalnim un segment vertical, numarul de intersectii ale acestui segment cu alte segmente orizontale va fi dat de numarul capetelor de intervale care se afla in starile dreptei de baleiere cuprinse intre coordonatele $y$ ale segmentului vertical. \r\n\r\np<>. Astfel, starile dreptei de baleiere sunt o structura de date pentru care avem nevoie de urmatoarele operatii:\r\n\r\n* _INSEREAZA&#40; y &#41;_ : insereaza capatul $y$;\r\n* _STERGE&#40; y &#41;_ : sterge capatul $y$;\r\n* _INTEROGARE&#40; y1, y2 &#41;_ : intoarce numarul de capete cuprinse in intervalul $[y{~1~}, y{~2~}]$.\r\n\r\np<>. Fie $MAXC$ valoarea maxima a coordonatelor capetelor de segmente. Folosind un vector pentru a implementa aceste operatiile descrise mai sus vom obtine o complexitate $O(1)$ pentru primele doua operatii si $O(MAXC)$ pentru cea de-a treia. Astfel, complexitatea  va fi $O(N*MAXC)$ in cazul cel mai defavorabil. Putem comprima spatiul $[0...MAXC]$ observand ca doar maxim $N$ din valori din acest interval conteaza, si anume capetele segmentelor orizontale, astfel reducand a treia operatie la $O(N)$, dar algoritmul va avea complexitatea $O(N^2^)$, ceea ce nu aduce nici o imbunatatire fata de algoritmul trivial. \r\n\r\np<>. Aceasta situatie ne indeamna sa cautam o structura de date mai eficienta. O prima varianta ar fi impartirea vectorului in bucati de $sqrt(N)$ reducand complexitatea totala la $O(N*&radic;N)$. In continuare vom prezenta o structura de date care ofera o complexitate logaritmica pentru operatiile descrise mai sus.\r\n\r\nh2. Arbori de intervale\r\n\r\np<>. Un _arbore de intervale_ este un arbore binar in care fiecare nod poate avea asociata o structura auxiliara (anumite informatii). Dandu-se doua numere intregi $st$ si $dr$, cu $st < dr$, atunci arborele de intervale $T(st, dr)$ se construieste recursiv astfel:\r\n\r\n* consideram radacina $nod$ avand asociat intervalul $[st, dr]$;\r\n* daca $st < dr$ atunci vom avea asociat subarborele stang $T(st, mij)$, respectiv subarborele drept $T(mij + 1, dr)$, unde $mij$ este mijlocul intervalului $[st, dr]$.\r\n\r\np<>. Intervalul $[st, dr]$ asociat unui nod se numeste interval standard. Frunzele arborelui sunt considerate intervale elementare, ele avand lungimea $1$.\r\n\r\nh3. Proprietate: \r\n\r\np<>. Un arbore de intervale este un arbore binar echilibrat (diferenta absoluta intre adancimea subarborelui stang si cea a subarborelui drept este cel mult $1$). Astfel, adancimea unui arbore de intervale care contine $N$ intervale este $[log{~2~}N] + 1$.\r\n\r\np=. !arbori-de-intervale?figure2.jpg!\r\n\r\nh2. Operatii efectuate asupra unui arbore de intervale:\r\n\r\nAsupra unui arbore de intervale se pot face doua operatii semnificative: actualizarea, respectiv interogarea unui interval.\r\n\r\nh3. Actualizare unui interval intr-un arbore de intervale\r\n\r\np<>. Vom prezenta pseudocodul unei proceduri recursive care insereaza un interval $[a, b]$ intr-un arbore de intervale $T(st,dr)$ cu radacina in nodul $nod$. Cea mai eficienta metoda de stocare in memorie a unui arbore de intervale este sub forma unui vector folosind aceeasi codificare a nodurilor precum la heap-uri :\r\n\r\n==code(c) |\r\nprocedura ACTUALIZARE(nod, st, dr, a, b)\r\n   daca (a <= st) si (dr <= b) atunci\r\n      modifica structura auxiliara din nod \r\n   altfel \r\n      mij = (st + dr) / 2\r\n      daca (a <= mij) atunci \r\n          ACTUALIZARE(2 * nod, st, mij, a, b)\r\n      daca (b > mij) atunci \r\n          ACTUALIZARE(2 * nod + 1, mij + 1, dr, a, b)\r\n      actualizeaza structura auxiliara din nodul nod\r\n==\r\n\r\nh3. Interogarea unui interval intr-un arbore de intervale\r\n\r\np<>. Vom prezenta pseudocodul unei proceduri recursive care returneaza informatiile asociate unui interval $[a, b]$ intr-un arbore de intervale $T(st,dr)$ cu radacina in nodul $nod$.\r\n\r\n==code(c) |\r\nprocedura INTEROGARE(nod, st, dr, a, b)\r\n   daca (a <= st) si (dr <= b) atunci\r\n      returneaza structura auxiliara din nod \r\n   altfel \r\n      mij = (st + dr) / 2\r\n      daca (a <= mij) atunci \r\n          INTEROGARE(2 * nod, st, mij, a, b)\r\n      daca (b > mij) atunci \r\n          INTEROGARE(2 * nod + 1, mij + 1, dr, a, b)\r\n      returneaza structura auxiliara din fiul stang combinata cu cea din fiul drept\r\n==\r\n\r\np<>. Vom demonstra in continuare ca operatiile prezentate mai sus au complexitatea $O(log{~2~} N)$ pentru un arbore de $N$ intervale. Este posibil ca intr-un nod sa aiba loc apel atat in fiul stang cat si in cel drept. Acest lucru produce un cost aditional doar prima data cand are loc. Dupa prima \"rupere in doua\", oricare astfel de \"rupere\" nu va aduce cost aditional, deoarece unul din fii va fi mereu inclus complet in intervalul $[a, b]$. Cum inaltimea arborelui, pentru $N$ intervale, este $[log{~2~}N] + 1$, complexitatea operatiilor va fi tot $O(log{~2~} N)$.\r\n\r\np<>. Pentru a retine in memorie un arbore de intervale pentru $N$ valori, vom aveam de nevoie de $N + N/2 + N/4 + N/8 + ... = 2*N-1$ locatii de memorie (sunt $2*N-1$ noduri). Deoarece arborele nu este complet, trebuie verificat de fiecare data daca fiii unui nod exista in arbore (aceasta verificare a fost omisa in pseudocodul de mai sus), altfel s-ar incerca accesarea de valori din vector care nu exista. Daca memorie disponibila in timpul concursului este suficienta, se poate declara vectorul care retine arborele de intervale de lungime $2^K^$ astfel incat $2^K^ &ge; 2*N-1$, simuland astfel un arbore complet si nefiind necesare verificarile mentionate mai sus.\r\n\r\np<>. Pentru a rezolva in continuare problema, vom folosi un arbore de intervale pentru a simula in timp logaritmic operatiile facute inainte pe un vector obisnuit. Astfel, in fiecare nod din arborele din intervale vom retine cate capete exista in acel interval. Primele doua operatii vor fi implementate folosind procedura _ACTUALIZARE&#40;&#41;_ de mai sus pentru intervalul $[y, y]$ in arborele $T(0, MAXC)$ si adunand $1$, respectiv scazand $1$ la fiecare nod actualizat. Cea de-a treia operatie poate fi realizata folosind procedura _INTEROGARE&#40;&#41;_ pe intervalul $[y{~1~}, y{~2~}]$. Astfel complexitatea se reduce la $O(N * log{~2~}MAXC)$  Folosind aceeasi tehnica de \"comprimare\" a coordonatelor se poate obtine o complexitate $O(N * log{~2~}N)$.\r\n\r\nIn figura urmatoare este descrisa structura arborelui de intervale, dupa actualizarea pentru intervalele $[2, 2]$, $[6, 6]$ si $[9, 9]$. Sunt marcate intervalele care conduc la obtinerea numarului de segmente intersectate de primul segment vertical, obtinute in urma interogarii pe intervalul $[0, 8]$.\r\n\r\np=. !arbori-de-intervale?figure3.jpg!\r\n\r\nh2. Problema 2 (Preluata de la IOI 1998, Ziua 2)\r\n\r\np<>. Se considera $N &le; 50 000$ dreptunghiuri in plan, fiecare avand laturile paralele cu axele $OX$, $OY$. Lungimea marginilor (contururilor) reuniunii tuturor dreptunghiurilor se va numi \"perimetru\". Sa se calculeze perimetrul celor $N$ dreptunghiuri. \r\n\r\np<>. In fisierul $_drept.in_$ se gaseste pe prima linie numarul $N$ de dreptunghiuri, iar pe fiecare din urmatoarele $N$ linii cate patru numere naturale mai mici ca $50 000$, reprezentand coordonatele carteziene ale coltului stanga sus, respectiv dreapta jos ale fiecarui dreptunghi. Rezultatul se va scrie in fisierul $_drept.out_$.\r\n\r\np<>. _Timp maxim de executie: $1 secunda/test$_.\r\n\r\ntable(example). |_. drept.in |_. drept.out |_. Figura |\r\n|^. 3\r\n3 8 8 3\r\n6 10 12 6\r\n12 4 15 1 |^. 44 |=. !arbori-de-intervale?figure4.jpg! |\r\n\r\nFolosind un rationament asemanator ca si la prima problema, constatam necesitatea unui algoritm de baleiere. Vom descompune problema in doua parti: prima data calculam perimetrul folosind doar laturile stanga si dreapta ale dreptunghiurilor pentru a calcula perimetrul pe $OY$; apoi putem sa rotim dreptunghiurile si folosind aceeasi procedura pt a calcula perimetrul pe $OX$, folosind doar laturile sus si jos ale dreptunghiurilor. \r\n\r\nFiecare latura (stanga sau dreapta) va fi un punct eveniment. Sortam laturile crescator dupa coordonata $x$ si parcurgem de la stanga la dreapta. Cand intalnim o latura stanga adaugam in starile dreptei de baleiere, intervalul de unitati ocupat de latura pe $OY$, iar cand intalnim o latura dreapta, eliminam din starile dreptei de baleiere intervalul de unitati ocupat de latura. Intre oricare doua puncte eveniment consecutive are loc o modificare a perimetrului total pe $OY$. Astfel, dupa fiecare actualizare a starilor dreptei de baleiere se va retine care este numarul de unitati adaugate pana in prezent (nu se tine cont daca o unitate este adaugata de mai multe ori). Vom aduna la perimetrul pe $OY$ total de fiecare data, diferenta absoluta intre numarul de unitati adaugate pana in prezent si valoarea imediat anterioara (dinaintea actualizarii). Asadar, este necesara o structura de date care se efectueze urmatoarele operatii in timp eficient (preferabil logaritmic):\r\n\r\n* _MARCHEAZA&#40;a, b&#41;_ : adauga intervalul $[a, b]$;\r\n* _DEMARCHEAZA&#40;a, b&#41;_ : elimina intervalul $[a, b]$;\r\n* _INTEROGARE&#40;&#41;_ : returneaza numarul total de coordonate adaugate pana in prezent.\r\n\r\np<>. Putem folosi un arbore de intervale pentru a obtine o complexitate $O(log{~2~} MAXC)$ sau $O(log{~2~} N)$ pentru primele doua operatii si $O(1)$ pentru ce-a de treia. In fiecare nod din arbore retinem de cate ori a fost marcat intervalul respectiv si cate unitati din intervalul respectiv au fost marcate. Primele doua operatii pot fi implementate folosind procedura _ACTUALIZARE&#40;&#41;_ iar a treia operatie va returna valoarea numarul de unitati care au fost marcate din radacina arborelui de intervale. \r\n\r\np<>. In figura urmatoare este descrisa structura arborelui de intervale, dupa adaugarea intervalelor $[3, 8]$ si $[6, 10]$ (un interval $[y{~1~}, y{~2~}]$ reprezinta intervalul de unitati $[y{~1~}, y{~2~} - 1]$ din arbore). \r\n\r\np=. !arbori-de-intervale?figure-8.jpg!\r\n\r\nh2. Problema 3\r\n\r\np<>. Se dau $N &le; 100 000$ puncte in plan de coordonate numere naturale mai mici ca $2 000 000 000$. Sa se raspunda la $M &le; 1 000 000$ intrebari de forma \"cate puncte din cele $N$ exista in dreptunghiul cu coltul stanga sus in $(x{~1~}, y{~1~})$ si coltul dreapta jos in $(x{~2~}, y{~2~})$?\".\r\n\r\np<>. In fisierul $_puncte.in_$ se vor gasi pe prima linie numerele $N$ si $M$. Pe urmatoarele $N$ linii se vor gasi coordonatele punctelor. Pe urmatoarele $M$ linii se vor gasi cate patru numere naturale reprezentand coordonatele colturilor dreptunghiurilor. In fisierul $_puncte.out_$ se vor gasi $M$ numere naturale reprezentand raspunsurile la intrebari.\r\n\r\np<>. _Timp maxim de executie: $1 secunda/test$_.\r\n\r\ntable(example). |_. puncte.in |_. puncte.out |_. Figura |\r\n|^. 6 1\r\n2 8\r\n5 3\r\n6 5\r\n8 7\r\n8 1\r\n10 10\r\n4 8 9 4 |^. 2 |=. !arbori-de-intervale?figure5.jpg! |\r\n\r\np<>. Problema determinarii numarului de puncte din interiorul unui dreptunghi este o particularizare bidimensionala pentru problema numita in literatura de specialitate _Orthogonal Range Search_. Varianta aleasa pentru acest caz consta intr-un arbore de intervale, care permite determinarea numarului de puncte din interiorul unui dreptunghi cu o complexitate $O(log{~2~}^2^ N)$. \r\n\r\np<>. Astfel, se sorteaza coordonatele $x$ ale punctelor si se construieste un arbore de intervale. Primul nivel al arborelui va contine toate coordonatele $x$. Cei doi fii ai lui vor contine prima jumatate, respectiv a doua jumatate a punctelor (sortate dupa coordonata $x$) si asa mai departe. Pentru fiecare interval de coordonate $x$, se mentin sortate coordonatele $y$ corespunzatoare punctelor care au coordonatele $x$ in intervalul respectiv. Astfel, memoria folosita este $O(N * log{~2~}N)$. Pentru a construi efectiv se foloseste o abordare asemanatoare algoritmului de sortare prin interclasare: in fiecare nod, pentru a obtine lista de coordonate $y$ ordonate, se interclaseaza listelele celor doi fii (deja ordonate). Cand se ajunge intr-o frunza, lista nodului este formata dintr-un singur punct.\r\n\r\np=. !arbori-de-intervale?figure6.jpg!\r\n\r\np<>. Pentru fiecare dreptunghi, se executa cautarea in arborele de intervale pentru segmentul $[x1, x2]$ (deoarece se folosesc doar cele $N$ coordonate $x$ ale punctelor, se vor potrivi capetele acestui interval folosind cautarea binara la cea mai apropiata coordonata $x$ de fiecare capat). Pentru fiecare interval din arbore atins, se executa doua cautari binare printre coordonatele y corespunzatoare coordonatelor x din acel interval, pentru a determina cate puncte din intervalul respectiv se afla in intervalul $[y{~1~}, y{~2~}]$ (adica in interiorul dreptunghiului).\r\n\r\np<>. Complexitatea $O(log{~2~}^2^ N)$ poate fi redusa, folosind o metoda descoperita independent de Willard si Lueker in anul $1978$. Se observa ca pentru fiecare coordonata $y$ dintr-un nod, daca presupunem ca se efectueaza o cautare binara, atunci putem determina in timpul interclasarii pozitia din fiecare fiu pe care o va returna cautarea binara pentru aceeasi valoare. Este evident ca pentru o valoare $y$ dintr-un nod care a provenit dintr-un fiu in timpul interclasarii, exista o unica valoare maxima $y\'$ din celalalt fiu astfel incat $y\' &le; y$. Asadar, tinem pentru fiecare valoare $y$ dintr-un nod doi indici care identifica pozitiile corespunzatoare efectuarii unei cautari binare in fii pentru valoarea $y$. Astfel, in timpul cautarii, in loc sa se efectueze cautari binare, se pot parcurge acesti indici, care ofera in $O(1)$ pozitia in lista cautata, reducand complexitatea totala la $O(log{~2~} N)$.\r\n\r\np=. !arbori-de-intervale?figure7.jpg!\r\n\r\nh2. Probleme propuse \r\n\r\nh3. 1. Preluata de la Olimpiada Baltica de Informatica, Polonia  2001\r\n\r\np<>. Se considera $N &le; 50 000$ dreptunghiuri in plan, fiecare avand laturile paralele cu axele $OX$, $OY$. Sa se calculeze aria ocupata de reuniunea celor $N$ dreptunghiuri. \r\n\r\np<>. In fisierul $_drept2.in_$ se gaseste pe prima linie numarul $N$ de dreptunghiuri, iar pe fiecare din urmatoarele $N$ linii cate patru numere naturale mai mici ca $50 000$, reprezentand coordonatele carteziene ale coltului stanga sus, respectiv dreapta jos ale fiecarui dreptunghi. Rezultatul se va scrie in fisierul $_drept2.out_$.\r\n\r\np<>. _Timp maxim de executie: $1 secunda/test$_.\r\n\r\nh3. 2. Preluata de la Olimpiada Nationala de Informatica, Polonia 2001\r\n\r\np<>. Se considera $N &le; 50 000$ puncte in plan de coordonate numere naturale mai mici ca $50 000$. Sa se determine unde se poate aseza un dreptunghi de lungime $DX$ si latime $DY$ astfel incat numarul de puncte incluse in dreptunghi sa fie maxim.\r\n\r\np<>. In fisierul $_puncte.in_$ se gasesc pe prima linie numerele $N$, $DX$ si $DY$. Pe urmatoarele $N$ linii se gasesc coordonatele punctelor. In fisierul $_puncte.out_$ se vor gasi cinci numere naturale reprezentand coordonatele colturilor stanga sus si dreapta jos ale asezarii dreptunghiului si numarul maxim de puncte din dreptunghi.\r\n\r\np<>. _Timp maxim de executie: $1 secunda/test$_.\r\n\r\nh3. 3. Preluata de la Barajul pentru Lotul National, Romania 2003\r\n\r\np<>. Se considera $N &le; 100 000$ puncte in plan de coordonate numere naturale mai mici ca $100 000$. Sa se determine unde se pot aseza doua dreptunghiuri de lungime $DX$ si latime $DY$, fara sa se intersecteze, astfel incat numarul de puncte incluse in cele doua dreptunghiuri sa fie maxim. \r\n\r\np<>. In fisierul $_puncte2.in_$ se gasesc pe prima linie numerele $N$, $DX$ si $DY$. Pe urmatoarele $N$ linii se gasesc coordonatele punctelor. In fisierul $_puncte2.out_$ se vor gasi $9$ numere naturale reprezentand coordonatele colturilor stanga sus si dreapta jos ale asezarii primului dreptunghi, respectiv a celui de-al doilea, cat si numarul maxim de puncte incluse in ambele dreptunghiuri.\r\n\r\np<>. _Timp maxim de executie: $1 secunda/test$_.\r\n\r\nh3. 4. Preluata de la concursul international USACO January Open, 2004\r\n\r\np<>. Se considera $N &le; 250 000$ dreptunghiuri in plan, fiecare avand laturile paralele cu axele $OX$, $OY$, care nu se intersecteaza si nu se ating, dar pot fi incluse unul in altul. Se numeste \"inchisoare\" un dreptunghi inconjurat de alte dreptunghiuri. Sa se determine numarul maxim de dreptunghiuri de care poate fi inconjurata o \"inchisoare\" si cate astfel de \"inchisori\" maxime exista. \r\n\r\np<>. In fisierul $_inchis.in_$ se gaseste pe prima linie numarul $N$ de dreptunghiuri, iar pe fiecare din urmatoarele $N$ linii cate patru numere naturale mai mici ca $1 000 000 000$, reprezentand coordonatele carteziene ale coltului stanga sus, respectiv dreapta jos ale fiecarui dreptunghi. In fisierul $_inchis.out_$ se gasesc doua numere naturale: numarul maxim de dreptunghiuri de care poate fi inconjurata o \"inchisoare\" si cate astfel de \"inchisori\" maxime exista. \r\n\r\np<>. _Timp maxim de executie: $1 secunda/test$_.\r\n\r\nh3. Nota\r\n\r\np<>. Au fost adaugate si implementarile in limbaj Pascal, C ale catorva dintre problemele explicate in articol. Acestea pot fi accesate prin intermediul optiunii \"Listeaza atasamente\".',2044,'public',3689,NULL),('planificare/sedinta_20070424','Sedinta 2007-04-24','2007-04-24 14:28:52','2007-04-26 17:56:40','h1. Sedinta 2007-04-24\r\n\r\n_ora 18:30, la Cafenescu_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Mircea Pasoi\r\n* Diaconu Adrian\r\n* Silviu Ganceanu\r\n* Valentin Stanciu\r\n* Adrian Vladu\r\n\r\nh2. Agenda\r\n\r\n_Imi cer scuze pentru aceasta agenda IMENSA! Am detaliat mult mai mult decat este necesar._\r\n\r\n# Asociatia infoarena\r\n## scopul Asociatiei infoarena\r\n## statut, structura si roluri\r\n## desfasurarea sedintelor, luarea deciziilor\r\n### frecventa\r\n### conferinte by net\r\n## lista cu membri consilieri\r\n## despre motivatie si voluntariat\r\n### ce are de oferit infoarena\r\n### ce vrem si ce planuri avem noi in raport cu infoarena\r\n### cum recrutam oameni noi\r\n# preONI\r\n## cum vrem sa fie preONI 2007?\r\n### numar participanti\r\n### premii\r\n### numar de probe, probleme, grupe\r\n### conditii cazare\r\n### dotare\r\n## ce stiu de la Emil\r\n### intre 1 si 10 iunie\r\n### poate acoperi costurile pentru 30 persoane x 3 zile\r\n### se va organiza cel mai probabil la Panciu sau Vidra\r\n### va *incerca* sa ne asigure internet\r\n### este loc si de mai multe persoane dar suntem pe barba noastra\r\n## alternative\r\n## grafic desfasurare (sesiune, terminarea anului scolar, bac, lot etc.)\r\n## plan cheltuieli\r\n## sponsori\r\n### Mircea are o idee\r\n### HOSTWAY e in deliberare, nu e de bine\r\n# Fonduri\r\n## o problema importanta, necesita o solutie permanenta\r\n### donatii din partea companiilor\r\n#### companii la care avem contacte\r\n#### companii la care avem acces prin membrii nostri\r\n### donatii din partea utilizatorilor si a persoanelor fizice\r\n#### 2% din impozit pe salar\r\n#### prin card\r\n#### prin banca\r\n#### micro payments (SMS / MMS cu rating badge :)\r\n### cursuri platite\r\n### research\r\n### job board\r\n### advertising\r\n## plan de atac\r\n# Proiecte curente\r\n## despre sectiunea \'implica-te\'. Ce e de imbuntatit?\r\n## infoarena software development\r\n### ce ne trebuie pentru preONI\r\n## Extinde arhiva\r\n## Scrie articole\r\n## Imbunatatire teste probleme\r\n## Raspandeste vestea\r\n### despre 648.ro\r\n# Propuneri proiecte noi\r\n## cursuri platite\r\n## job board\r\n## infoarena screencasts\r\n## cursuri video\r\n# Strategie si planificare pe termen mediu\r\n## Obiective pentru urmatorul an\r\n## Ce se intampla la vara?\r\n\r\n\r\n\r\nh2. Rezolutii aprobate\r\n\r\nh3. Asociatia infoarena\r\n\r\n* Cristi se ocupa de activarea contului in banca si de facut stampila.\r\n* Scopul infoarena se extinde\r\n** la studenti\r\n** la professionals: Desi vom aborda si chestiuni mai tehnice / practice, ne vom feri de trivialitati precum tutoriale de folosit tehnologia X.\r\n* Consiliul director se va intruni live cel putin o data pe luna.\r\n* *Se desemneaza urmatorii consilieri (activi)*:\r\n** Valentin Stanciu\r\n** Adrian Diaconu\r\n** Vladu Adrian\r\n** Pasaila Daniel\r\n** Buruiana Filip\r\n* *Se desemneaza urmatorii consileri emeritus*:\r\n** Negruseri Cosmin\r\n** Florea Tiberiu\r\n* Vali invita un om de PR la urmatorul meeting.\r\n* Se propun spre recrutare: wefgef, gcomin, airinei, pauldb, bogdan, dumitru, marmota, valentin bora, alex tandrau.\r\n* Cristi va scrie un letter oficial de invitatie. Silviu se ocupa de inmanarea (transmiterea) invitatiilor.\r\n\r\nh3. preONI 2007\r\n\r\n* se desfasoara intre 1 si 10 iunie\r\n* Mircea face planul de cheltuieli\r\n* Cautam sponsorizare la\r\n** Oracle, prin Mircea\r\n** Hostway, prin Cristi\r\n** intel, Mircea va da telefon si va intreba daca sunt interesati, Cristi e dispus sa poarte discutiile cu ei.\r\n** Emil\r\n* fond minim de premii: 1800 lei\r\n\r\nh3. Fonduri\r\n\r\n* Cristi face research pe legea cu 2%\r\n* Silviu face copy la contact companii prin membri\r\n* 648 va face logo+tricou, pe care il putem folosi la strangere fonduri\r\n\r\nh2. Note remarcabile\r\n\r\nh3. Asociatia infoarena\r\n\r\n* De studiat cazul in care un consilier nu poate sa se prezinte in persoana la sedinte. Cum vor vota?\r\n* Ce ofera infoarena celor care se implica?\r\n** ocazia de a invata pe altii ce stii\r\n** pe partea de software development, ai ocazia sa inveti sa programezi\r\n** autoritate si posibilitatea de a dezvolta proiecte proprii\r\n** special perks: free drinks\r\n** ca regula generala, ii putem pune in contact cu mentori. Pe partea de info, mentorii suntem noi B-) insa pentru alte domenii, precum PR, putem sa le platim participarea workshop-uri, training-uri, conferinte samd. (e si un mod de a filtra oamenii buni si talentati de cei care pur si simplu vor niste bani).\r\n* Vom recruta oameni pentru echipa infoarena (nu doar de informatica) in mod activ.\r\n* Il trimitem pe Leo la InfoEducatie\r\n\r\nh3. preONI 2007\r\n\r\n* Varianta pe care ne-o dorim:\r\n** 50 participanti (10+11+10+noi10+profi9)\r\n** 1 proba\r\n** 3 zile\r\n** internet, tastaturi si mice standard \r\n** cel putin ca anul trecut\r\n* alternativa\r\n** locatie Bucuresti\r\n** 25 participanti\r\n** laborator turci\r\n** trebuie sa-l facem in weekend\r\n** cazare la internate (gen Nichita Stanescu). Pret de la 35 lei in sus.\r\n',13,'public',NULL,NULL),('utilizator/marcelcodrea','Profil marcelcodrea','2006-11-24 21:04:57','2009-03-12 17:05:07','== include(page=\"template/noprofile\") ==\r\n\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distictii primite\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n\r\n\r\n',3680,'protected',NULL,NULL),('utilizator/danciac','Profil danciac','2007-04-26 13:56:24','2007-04-26 13:56:24','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6483,'public',NULL,NULL),('template/meeting-under-construction','template/meeting-under-construction','2007-04-26 18:08:02','2008-02-04 20:59:57','table{margin:0.5em auto;}. |={background-color:#FDD017;border:1px solid #F88017;}. !<template/todo?progress.gif! *Detaliile acestei intalniri NU au fost stabilite. Lista de invitati este orientativa. Agenda este in constructie. Daca vrei sa propui un subiect spre discutie, adauga-l in agenda.* |\r\n\r\n',1,'protected',NULL,NULL),('simulare-27-04-2007','Probleme simulare','2007-04-26 20:47:09','2007-04-27 06:24:52','* \'Salvare\':simulare-27-04-2007?salvare.htm\r\n* \'Zapezi\':simulare-27-04-2007?zapezi.html\r\n* \'Cabane\':simulare-27-04-2007?cabane.doc\r\n\r\nBackup:\r\n\r\n* \'Ajutor\':simulare-27-04-2007?ajutor.doc\r\n* \'Galerie\':simulare-27-04-2007?galerie.doc\r\n',1,'public',NULL,NULL),('template/noprofile','template/noprofile','2006-11-26 22:20:18','2008-02-04 20:59:22','&nbsp;\r\n\r\ntable{margin:0.5em auto;}. |={background-color:#CCCCFF;border:1px solid #3366CC;}. !{vertical-align:middle;}template/noprofile?wrench.png! _Acest utilizator nu si-a personalizat inca pagina de profil._ \'*Click aici*\':documentatie/pagina-de-profil _sa afli cum iti poti personaliza pagina de profil._ |',1,'protected',NULL,NULL),('blog/algoritmiada-in-cautare-de-sigla','Algoritmiada in cautare de sigla','2008-12-01 07:21:26','2008-12-01 08:29:39','Anul acesta am decis sa facem putin rebrading si sa schimbam formatul concursului principal organizat de infoarena care pana acum s-a numit preOni. Noul nume ales este Algoritmiada. Mai avem putin timp pana la inceperea rundelor si nu avem inca o sigla. Ca si \'anul trecut\':http://infoarena.ro/blog/preoni-2008-in-cautare-de-sigla facem apel la comunitate pentru a gasi o sigla misto.',2028,'protected',3422,NULL),('winter-challenge-1/solutii','Winter Challenge, Solutii','2007-02-11 20:45:38','2008-08-14 19:06:30','h1. Solutii\r\n\r\nIn numele echipei Winter Challenge 2007 felicit toti participantii si le urez succes in viitoare confruntari. Totodata, tin sa multumesc lui Mugurel Ionut Andreica si lui Sorin Stancu-Mara pentru ca au acceptat sa propuna subiecte alaturi de mine. Nu in ultimul rand multumesc intregii \"echipe infoarena\":echipa-infoarena pentru suportul tehnic acordat si ii rog sa ma ierte daca i-am stresat (prea tare).\r\n\r\nMult noroc in continuare, \r\nBogdan A. Stoica\r\n\r\nh2. Chiftea \r\n\r\nh3. problema usoara, clasele 9-10\r\n\r\nVom nota cu P{~k~}, perimetrul minim al figurii ce contine $k$ patratele de latura unitate. In mod evident, acesta depinde numai de patratelele ce formeaza marginea figurii.\r\nVom trata intai cazul in care $N$ este patrat perfect pornind de la $N = 1$, cu $P{~1~} = 4$. Pentru $N = 4$, construind toate figurile posibile se observa ca cea de perimetru minim are forma unui patrat cu latura $2$, deci $P{~4~} = 4*2 = 8$. Continuand procedeul, se demonstreaza cu ajutorul principiului inducitei matematice ca $P{~t~} = 4*[radical(t)]$ (cu $[x]$ s-a notat partea intreaga a lui $x$), oricare ar fi $t$ patrat perfect.\r\nPentru al doilea caz, cel in care $N$ nu este patrat perfect, figura noastra porneste tot de la un patrat de latura $[radical(N)]$. Este evident faptul ca pentru ca $P{~N~}$ sa fie minim, trebuie sa avem cat mai putine patratele (pe margine) carora li se aduna mai mult de o latura la perimetru (cu alte cuvinte trebuie sa avem cat mai putine patratele care sa formeze colturi). Va trebui, deci, sa adaugam pe marginile patratului format $N-[radical(N)]*[radical(N)]$ patratele. Astfel solutia devine $4*[radical(N)]$ pentru $N$ patrat perfect, $4*[radical(N)]+2$ pentru cazul in care acoperim maxim o latura cu patratele sau $4*[radical(N)]+4$ pentru cazul in care acoperim maxim 2 laturi cu patratele.\r\nO solutie care calcula aceste valori in O({$N$}) nu ar fi obtinut punctaj maxim.\r\n\r\nh2. Mall \r\n\r\nh3. problema medie, clasele 9-10\r\n\r\nCalculam $A[i, j]$ = castigul maxim pe care-l obtine Varu daca repartizeaza $j$ ingrijitori primelor $i$ firme, unde \r\n$A[i, j]$ = $maxim(A[l, j-k]+Castig[l, k])$ ({$0 < l < i$}, {$0 &le; k &le; j$}), unde $Castig[i, j]$ = castigul pe care-l obtine Varu de la firma $i$ daca acesteia ii repratizaza exact $j$ ingrijitori. \r\nO solutie care calcula in O({$N^4^$}) aceasta recurenta ar fi obtinut $16$ puncte.\r\nO solutie care calcula in O({$N^3^$}), folosind matricea $V[i, j]$ = $maxim(A[k, j]+Castig[k, j])$ ({$0 <  k < i$}), obtinea $32$ de puncte.\r\nO solutie care calcula in O({$N^2^$}), folosind un deque ce calcula in O({$1$}) maximul (pentru linia $i$ si coloana $j$) dintre $V[i, 1]$, $V[i, 2]$, ..., $V[i, j-1]$, obtinea $100$ de puncte.\r\n\r\nh2. Smen \r\n\r\nh3. problema grea, clasele 9-10 - problema medie, clasele 11-12\r\n\r\nIncepem prin a normaliza toate numerele din sir si pe $A$ si $B$, adunand tuturor valoarea $200$. Astfel vom lucra numai cu numere pozitive. Apoi problema se rezolva prin programare dinamica. Sortam in ordine crescatoare elementele si apoi calculam $A[i, j, k]$ = numarul minim de operatii ce se efectueaza asupra primelor $i$ numere a.i. sa obtinem exact $j$ elemente distincte iar ultimul element sa nu depaseasca valoarea $k$. \r\n$A[i, j, k]$ se poate obtine ca fiind maximul dinntre:\r\n\r\n# $A[i-1, j, k-1]$ + $|Val_initiala[i]-k|$ (daca vrem ca valoarea initiala a celui de-al $i$-lea element sa fie $k$, dar sa nu-mi creeze un alt element distinct).\r\n# $A[i-1, j-1, k-1]+|Val_initiala[i]-k|$ (daca vrem ca valoarea initiala a celui de-al $i$-lea element sa fie $k$ si sa-mi creez inca un element dinstinct)\r\n# $A[i-1, j, k-1]$ (nu cresc nici valoarea elementului $i$, nici numarul de elemente distincte)\r\n\r\nPentru reconstituire vom lucra cu o matrice $B[i, j, k]$ care ia valori din multimea {$0$, $1$, $2$}, semnificand conditia din care a provenit starea ({$i$}, {$j$}, {$k$}). Se observa ca aceasta solutie ar fi obtinut foloseste foarte multa memorie (O({$N*K*$}({$B$}-{$A$})) si ar fi obtinut doar $40%$ din punctaj.\r\n\r\nSolutia $100$ de puncte incepe prin a observa ca, la un pas, nu sunt folosite decat \"linia\" curenta si \"linia\" anterioara din matricea $A$. Pentru reconstituire se poate folosi urmatorul smen: retinem din $14$ in $14$ \"linii\" informatiile din matricea $A$ (cea de la prima solutie), adica $R[1, j, k]$ =  {$A[1, j, k]$} ({$1 &le; j &le; K$} si {$A+200 &le; k &le; B+200$}), $R[2, j, k]$ = $A[15, j, k]$ ({$1 &le; j &le; K$} si {$A+200 &le; k &le; B+200$}), $R[3, j, k]$ = $A[29, j, k]$ ({$1 &le; j &le; K$} si {$A+200 &le; k &le; B+200$}), etc. Dupa ce am completat matricea $R$, reluam dinamica de la coada la cap si ne vom folosi doar de matricea $R$. Astfel la pasul $i$ vom reconstitui doar liniile care se afla intre liniile $R[i, j, k]$ si $R[i-1, j, k]$ ({$1 &le; j &le; K$} si {$A+200 &le; k &le; B+200$}), adica intre ({$i-1$})*{$14+1$} si $i*14+1$ in matricea de la prima solutie. Astfel o sa avem o memorie de O({$14*K*$}({$B$}-{$A$})).\r\n\r\nO alta solutie care obtinea punctaj maxim este transformarea problemei intr-una de cuplaj de cost minim. Cele doua multimi de noduri se construiau in felul urmator: prima multime era reprezentata de sirul initial, iar cea de-a doua era reprezentata de valorile intregi cuprinse in intervalul $[A, B]$. Se introduc $N*$({$B-A$}) muchii de capacitate $1$, o muchie de la un nod ce leaga elementul $X$ din prima multime si elementul $Y$ din a doua multime avand costul $|X-Y|$. Prima multime se leaga de o sursa fictiva prin muchii de cost $0$ si capacitate $1$, iar cea de-a doua multime de o destinatie fictive prin muchii de cost $0$ si capacitate $1$. Tinandu-se cont ca in destinatie trebuie sa se obtina fluxul minim $K$, se aplica acest algoritm avand grija sa minimizam costul.\r\n\r\nh2. Fear \r\n\r\nh3. problema usoara, clasele 11-12\r\n\r\nIn ciuda proprietatii un pic nenaturale care priveste valoarea fricii dintr-o intersectie, problema se reduce la aflarea fluxului maxim avand orasul $1$ ca sursa si orasul $N$ ca destinatie. Pentru realizarea acestui lucru vom logaritma (in baza $2$, $e$ sau $10$) costurile muchiilor ce se dau in fisierul de intrare. Dintre toate aceste noi costuri o vom lua pe cea maxima ({$vmax$}). Algoritmul va fi urmatorul: \r\n\r\n# vom trimite frica (din orasul $1$) cu o valoare $V$ (initial, $V$ = $vmax$) pana cand frica nu va mai putea ajunge la destinatie. \r\n# injumatatim pe $V$ si reluam algoritmul de la pasul $1$.\r\n\r\nAceasta metoda poarta denumirea de \"Flux maxim prin scalare\". O alta abordare care ar fi mers la fel de bine este cea folosind algoritmul de flux maxim Ford Fulkerson.\r\n\r\nh2. Doipe \r\n\r\nh3. problema grea, clasele 11-12\r\n\r\n	Prima solutie corecta este de complexitate O(N*2^N^). Se calculeaza o matrice $P[i, R]$ = numarul de permutari cu $i$ elemente, care respecta sirul de relatii $R$ ({$R$} este un numar binar de $i - 1$ biti, care codifica un sir de relatii). Putem calcula aceste valori pe baza valorilor calculate pentru $P[i - 1, R\']$, variind pozitia in care este asezat in cadrul permutarii cel de-al $i$-lea element. Aceasta solutie nu se incadreaza, insa, nici in limita de timp, nici in cea de memorie.\r\n	Ideea solutiei de punctaj maxim este urmatoarea: Vom calcula $P[i, j]$ = numarul de permutari ale multimii {{$1$},{$2$},..,{$i$}} care respecta primele $i-1$ relatii ale sirului de relatii si in care ultimul numar al permutarii este numarul $j$. In mod evident, rezultatul dorit va fi dat de suma $P[N, 1]$ + $P[N, 2]$ + ... + $P[N, N]$.\r\n	Pentru calculul lui $P[i, j]$ vom observa ca, eliminand numarul $j$ din permutare, obtinem $i-1$ numere distincte care pot fi renumerotate pentru a forma o permutare a multimii {{$1$},{$2$},..,{$i-1$}}. Mai exact, orice numar $x$ mai mare decat $j$ este renumerotat cu valoarea $x-1$. In conditiile acestei renumerotari, avem urmatoarele $2$ cazuri:\r\n\r\n* daca relatia $i-1$ este \"$<$\", atunci $P[i, j]$ = $P[i-1, 1]$ + $P[i-1, 2]$ + ... + $P[i-1, j-1]$\r\n* daca relatia $i-1$ este \"$>$\", atunci $P[i, j]$ = $P[i-1, j]$ + $P[i-1, j+1]$ +... + $P[i-1, i-1]$\r\n\r\nCazul \"de baza\" este $P[1, 1]$ = $1$. Relatiile date sunt corecte, deoarece pentru orice permutare ce corespunde lui $P[i-1, x]$ se poate aplica operatia de renumerotare inversa (relativ la $j$), obtinand un sir de $i-1$ numere distincte din multimea {{$1$},{$2$},..,{$i$}}\\{{$j$}} care respecta primele $i-2$ relatii. La sfarsitul acestui sir se poate adauga numarul $j$, obtinand o permutare cu $i$ elemente care respecta primele $i-1$ relatii.\r\n	Implementarea imediata a relatiilor de recurenta mentionate se poate realiza foarte usor in complexitate O({$N^3^$}). Memorand sumele partiale $SP[x]$ = $P[i-1, 1]$ + $P[i-1, 2]$ + ... +  {$P[i-1, x]$} putem calcula $P[i, j]$ in timp O({$1$}), reducand complexitatea la O({$N^2^$}).\r\n',6756,'public',NULL,NULL),('template/newsletter/doi-la-suta-call','template/newsletter/doi-la-suta','2009-04-01 16:19:12','2009-04-01 16:26:15','h2{font-size: 12pt}. Sprijină Asociaţia infoarena!\r\n\r\nConform \'Codului Fiscal\':http://www.edex.ro/articol_cod_fiscal_16661_Art.%2084:%20Stabilirea%20si%20plata%20impozitului%20pe%20venitul%20net%20anual%20impozabil.html, ai dreptul să direcţionezi către Asociaţia infoarena 2% din impozitul pe venit datorat la stat. Aceste contribuţii ne ajută enorm să ne desfăşurăm activitatea. În plus, ne bucurăm să vedem că munca pe care o depunem este apreciată.\r\n\r\nProcedura este simplă si nu te costă nimic!\r\n\r\n&rarr; \'*Vezi cum se face*\':doi-la-suta\r\n\r\nTermenul limită este *15 mai 2009*.\r\n',13,'protected',NULL,NULL),('utilizator/dastas','Profil Dastas','2006-11-24 21:07:26','2007-05-14 16:53:28','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite:\r\n\r\n* _Campion pe sate_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4603,'protected',NULL,NULL),('blog/648-sustine-infoarena','648 sustine infoarena','2007-05-24 08:57:53','2007-05-24 08:59:12','Dorim sa multumim agentiei de web SixtyFourEights Group (\'www.648.ro\':http://www.648.ro/) pentru realizarea \'acestor materiale grafice\':materiale-promotionale menite sa ajute la dezvoltarea comunitatii infoarena.\r\n\r\nbq. infoarena are un rol deosebit in mobilizarea tinerilor informaticieni si de aceea ne face placere sa sustinem aceasta initiativa.\r\nEste o oportunitate pentru toti cei care doresc sa isi creasca performantele si sa aiba o baza fundamentata inainte de a incepe lucrul intr-o companie IT.\r\n\r\nbq. 648 isi propune sa creasca nivelul produselor de web romanesti prin implicarea comunitatilor de dezvoltatori. Ne plac oamenii motivati, care doresc sa inoveze si ii incurajam sa progreseze. Cresc si ei, crestem si noi.\r\n\r\np. \'648 Group\':http://www.648.ro/\r\n',13,'protected',NULL,NULL),('materiale-promotionale','Materiale promotionale','2007-05-24 09:02:05','2009-02-06 08:24:48','h1. Materiale promotionale\r\n\r\nPe aceasta pagina vom pune materiale promotionale pe care le puteti folosi sa promovati infoarena in scoala, in cluburi sau in randul prietenilor.\r\n\r\n\r\ntable{width: auto; vertical-align: top}. | \'!materiale-promotionale?concept-afis.jpg 200x200!\':materiale-promotionale?concept-afis.jpg | Concept afis infoarena \r\nAutor: \'648 Group\':http://www.648.ro/ |\r\n| \'Coiful infoarena\':materiale-promotionale?coif-infoarena-transparent.png | Autor: Dan Burzo |\r\n| \'Sigla infoarena, fundal transparent\':materiale-promotionale?sigla-infoarena-fundal-transparent.png | Autor: Dan Burzo |\r\n',2044,'public',NULL,NULL),('utilizator/hardvirus','Profil hardvirus','2007-05-25 07:21:11','2007-05-27 18:52:52','== include(page=\"template/noprofile\") ==\r\n\r\nDespre mine\r\n\r\nSalut!Sunt Ardelean Horia elev in clasa a 7-a la Colegiul National Dragos-Voda din Sighetu Marmatiei.Am studii in turbo pascal,profesorul meu pregatitor e Raluca Bobosan\r\n\r\nDistinctii primite\r\n\r\nLocul 27 la ONI 2005 in clasa a 5-a,locul 34 la ONI 2006,locul 4 la concursul centrelor de excelenta\r\n2007\r\n\r\nPrieteni pe infoarena\r\n\r\nDeocamdata nu stiu pe nimeni dar vreau sa va cunosc.\r\n',6569,'public',NULL,NULL),('asociatia-infoarena','Asociatia infoarena','2006-11-27 07:21:15','2008-03-14 09:21:33','h1. Asociatia infoarena\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nAsociatia infoarena este o organizatie non-profit si ofera comunitatii infoarena personalitate juridica. Asociatia infoarena ne ajuta sa&hellip;\r\n\r\n* protejam drepturile de autor ale materialelor contribuite de comunitate. Cu exceptia cazurilor in care se specifica altfel, continutul infoarena apartine Asociatiei infoarena si poate fi distribuit sub licenta \'Creative Commons Attribution-NonCommercial 2.5\':http://creativecommons.org/licenses/by-nc/2.5/.\r\n* protejam brand-ul infoarena\r\n* rasplatim cei mai activi membri ai comunitatii - pentru timpul pe care l-au investit, acestia primesc functii oficiale si drept de vot in Adunarea Generala.\r\n* obtinem sponsorizari din partea companiilor private\r\n\r\nh2. Membri\r\n\r\nVezi \'echipa infoarena\':echipa-infoarena si \'colaboratori\':colaboratori.\r\n\r\nh2(#date). Date\r\n\r\n* CUI: 2175&nbsp;2294\r\n* Cont RON\r\n** IBAN: RO15&nbsp;RZBR&nbsp;0000&nbsp;0600&nbsp;0919&nbsp;4268\r\n** Deschis la: Raiffeisen, Ag. Unirea, Bucuresti\r\n* Adresa sediu social: Str. Dragos Voda Nr. 49, Bl. P9, Ap. 11, Barlad, Jud. Vaslui\r\n\r\nh2. Documente\r\n\r\n* \'Statutul Asociatiei infoarena\':asociatia-infoarena?statut.pdf\r\n* \'Actul constitutiv al Asociatiei infoarena\':asociatia-infoarena?act-constitutiv.pdf\r\n\r\nIntrucat asociatia este proaspat infiintata (aprilie 2007), nu avem inca bilanturi sau declaratii financiare de publicat.',13,'protected',NULL,NULL),('runda/preoni2007_runda5_11-12','runda/preoni2007_runda5_11-12','2007-06-24 18:33:54','2007-06-24 18:33:54','Scrie aici despre runda/preoni2007_runda5_11-12',986,'public',NULL,NULL),('preoni-2007/runda-finala/regulament','Finala preONI 2007, Bucuresti, Regulament','2007-06-22 11:09:32','2007-06-23 20:39:18','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2007/runda-finala\r\n* \'Program\':preoni-2007/runda-finala/program\r\n*(active) \'Regulament\':preoni-2007/runda-finala/regulament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-finala/9\r\n\r\nh1. Finala preONI 2007, Bucuresti, Regulament\r\n\r\nParticipantii la runda finala - atat cei calificati in finala de la Bucuresti cat si cei care participa online - se obliga sa respecte \'regulamentul concursului preONI\':preoni-2007/regulament.\r\n\r\nIn plus, finala de la Bucuresti se desfasoara sub urmatoarele reguli:\r\n\r\n* Concurentii vor fi prezenti in salile de concurs la orele anuntate\r\n* Fiecare concurent va primi subiectele in forma listata si foi pentru ciorne (pix nu este inclus)\r\n* Timp de 1 ora dupa primirea subiectelor concurentii pot formula intrebari referitoare la enunturile problemelor; intrebarile se vor formula in scris, pe foaia cu intrebari fiind precizate numele problemei si al concurentului; modalitate de formulare a intrebarile este identica cu cea de la primele 4 runde\r\n* In timpul probelor de concurs, concurentii:\r\n** nu vor avea asupra lor telefoane mobile sau alte mijloace de comunicatie\r\n** nu vor utiliza suporturi externe proprii (dischete/CD/flash-disk)\r\n** nu vor utiliza alte surse de documentare decat cele prezente pe calculator\r\n** nu vor incerca sa interfereze in nici un mod cu activitatile altui concurent\r\n** nu vor deteriora mediile de lucru\r\n** nu vor incerca sa interfereze cu sistemul de evaluare\r\n* In programele concurentilor nu sunt permise urmatoarele:\r\n** schimbarea drepturilor de acces la fisiere\r\n** atacul asupra securitatii sistemului sau evaluatorului\r\n** accesarea informatiilor despre sistemul de fisiere\r\n** executarea unor alte programe\r\n\r\nOrice incercare de frauda sau de a sabota desfasurarea corecta a concursului va fi urmata imediat de eliminarea elevului respectiv din concurs, cat si de pe _infoarena_.\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('runda/preoni2007_runda5_10','runda/preoni2007_runda5_10','2007-06-25 06:01:02','2007-06-25 06:01:08','Scrie aici despre runda/preoni2007_runda5_10',6502,'public',NULL,NULL),('preoni-2007/runda-finala/program','Finala preONI 2007, Program de desfasurare','2007-06-22 11:11:10','2007-06-23 20:39:31','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2007/runda-finala\r\n*(active) \'Program\':preoni-2007/runda-finala/program\r\n* \'Regulament\':preoni-2007/runda-finala/regulament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-finala/9\r\n\r\nh1. Finala preONI 2007, Bucuresti, Program de desfasurare\r\n\r\nProgramul de mai jos este deschis la sugestii si se poate modifica pe parcursul desfasurarii concursului.\r\n\r\ntable{width:50%}. |_. Data |_. Activitati |\r\n| Duminica, 24 iunie 2007 | * 12:00 - 18:00 Sosire si cazare participanti la internatul \'ICHB\':http://www.ichb.ro/\r\n* 18:00 - 19:00 Deschidere oficiala\r\n* 19:00 - 20:00 Cina\r\n* 20:00 - 21:00 Acomodare, testarea statiilor de lucru |\r\n| Luni, 25 iunie 2007 | * 08:00 - 08:30 Mic dejun\r\n* *09:00 - 14:00 Proba de concurs*\r\n* 14:00 - 15:00 Pranz\r\n* 16:00 - 17:00 Evaluare live (pe retroproiector)\r\n* 17:00 - 19:00 Seminar despre infoarena\r\n* 19:00 - 20:00 Festivitatea de premiere\r\n* 20:00 - 21:00 Cina\r\n* 21:00 - ... Party :) | \r\n| Marti, 26 iunie 2007 | * 08:00 - 09:00 Mic dejun\r\n* Plecare |\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('template/preoni-2007/footer','template/preoni-2007/footer','2007-01-15 15:14:53','2007-06-22 17:01:50','h2. Sponsori\r\n\r\nOrganizarea finalei preONI este posibila datorita generosilor nostri sponsori:\r\n\r\n!{border: 1px solid silver}preoni-2007?hostway.png!:http://www.hostwaylab.ro/ !{border: 1px solid silver}preoni-2007?ichb.png!:http://www.ichb.ro/ !{border: 1px solid silver}preoni-2007?irealsoft.png!:http://www.irealsoft.ro/\r\n\r\n',13,'protected',NULL,NULL),('newsletter/preoni-2007-runda-finala','preONI 2007, Runda Finala','2007-06-22 20:48:17','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nSuntem bucurosi sa anuntam marea runda finala a concursului\r\npreONI 2007! Aceasta va incepe in curand, mai exact:\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Luni, 25 martie 2007, orele 09:00 - 14:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPagina rundei: \'preoni-2007/runda-finala\':preoni-2007/runda-finala\r\n\nFinala se desfasoara la Bucuresti, fiind gazduita de Liceul\r\nInternational de Informatica (www.ichb.ro). Aici au fost invitati\r\nprimii 10 de elevi clasati de la fiecare grupa.\r\n\nDesi batalia pentru premii se da intre concurentii de la finala,\r\n   >>> runda se va desfasura online si va fi deschisa tuturor <<<\r\nin stilul obisnuit infoarena.\r\nAi ocazia sa concurezi cot la cot cu cei din finala!\r\n\nInformatii suplimentare (comisii, intrebari, tutorial, cum particip)\r\ngasesti in pagina dedicata acestei runde:\r\n\np{padding-left: 1.5em;}. \'preoni-2007/runda-finala\':preoni-2007/runda-finala\r\n\np{padding-left: 1.5em;}. Multimim sponsorilor nostri!\r\n\np{padding-left: 0.5em;}. HOSTWAY Romania (\'http://www.hostwaylab.ro/\':http://www.hostwaylab.ro/)\r\n	ICHB            (\'http://www.ichb.ro/\':http://www.ichb.ro/)\r\n	iRealSoft       (\'http://www.irealsoft.ro/\':http://www.irealsoft.ro/)\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la aceasta runda iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te va aduce mai aproape de varful clasamentul.\r\n==NewsletterRating(username=\"%username%\")==\r\nRating-ul este un indicator al performantei tale in conditii de\r\nconcurs. Afla mai multe: \'documentatie/rating\':documentatie/rating\r\n\nIti tinem pumnii!\r\n\nh2.  Despre Runda Finala \n\nClasamentul complet, in urma celor 4 runde de calificare se gaseste\r\naici: \'preoni-2007/clasament/9\':preoni-2007/clasament/9\r\n\nFinalistii preONI sunt primii 10 clasati de la fiecare grupa. Acestia\r\nvor concura pentru premii in bani si obiecte, la Bucuresti. Felicitari!\r\n\np{padding-left: 1.5em;}. Clasa a IX-a (si gimnaziu)\r\n   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n    1  1100  Bogdan Tataroiu\r\n    2   620  Adriana Sperlea\r\n    3   415  Cezar Mocan\r\n    4   360  Ionescu Victor\r\n    5   357  Purice Andrei\r\n    6   331  Tudorica Constantin Alexandru\r\n    7   315  Victor Popescu\r\n    8   240  Adrian Velicu\r\n    9   235  Casu-Pop Bogdan\r\n   10   200  Parcalabescu Daniela Maria\r\n\np{padding-left: 1.5em;}. Clasa a X-a\r\n   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n    1  1110  Gheorghe Cosmin\r\n    2  574   Dragus Marius\r\n    3  384   Sanduleac Dan\r\n    4  330   Puni Andrei Paul\r\n    5  300   Savin Tiberiu\r\n    6  286   Duta Vlad\r\n    7  280   Chis Raoul\r\n    7  280   Ozorchevici Ana Maria\r\n    8  274   Achim Ioan Alexandru\r\n    9  270   Lica Adela\r\n    9  270   Victor Savu\r\n\np{padding-left: 1.5em;}. Clasele XI-XII\r\n   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n    1  668  Andrei Grigorean\r\n    2  655  Airinei Adrian\r\n    3  620  Cristina Stancu-Mara\r\n    4  610  Victor Rusu\r\n    5  596  Stefan Istrate\r\n    6  560  Sorin Fagateanu\r\n    7  510  Paul-Dan Baltescu\r\n    8  495  Alexandru Simion\r\n    8  495  Marius Stroe\r\n   10  475  Costea Andrei\r\n\nh2.  Mesaj din partea HOSTWAY Romania \n\np{padding-left: 1em;}. . De cand a aparut pe piata in Romania anul trecut, Hostway si-a\r\n  . dorit sa poata participa la un astfel de eveniment. Aceasta nu\r\n  . este doar o declaratie de complezenta, la noi in companie,\r\n  . creativitatea, dorinta de a invata si flexibilitatea abordarilor\r\n  . fiind incurajate si sustinute permanent.\r\n  .\r\n  . Hostway Romania are trei departamente \"de productie\":\r\n  . web development, web hosting, software research & development.\r\n  .\r\n  . [...]\r\n  .\r\n  . Fondata in 1998, Hostway este una dintre primele 5 companii de\r\n  . Hosting din lume, cu birouri in Illinois, Florida, Texas,\r\n  . Columbia, Anglia, Franta, Olanda, Belgia, Germania, Romania,\r\n  . Australia si India.\r\n  .\r\n  . Ne simtim onorati sa putem sprijini cea mai mare comunitate de\r\n  . programatori din tara, credem ca initiativa noastra va avea un\r\n  . impact pozitiv la dezvoltarea proiectului infoarena, si dorim sa\r\n  . ne implicam si in viitoarele initiative.\r\n  .\r\n  . Va dorim mult success in continuare!\r\n  .\r\n  . Flaviu Radulescu\r\n  . General Manager\r\n\nCiteste intregul mesaj si afla mai multe despre HOSTWAY Romania:\r\n\'preoni-2007/premii\':preoni-2007/premii\r\n\nh2.  Despre preONI \n\npreONI, concursul de marca al comunitatii infoarena, este dedicat\r\nelevilor de liceu ce se pregatesc pentru ONI (Olimpiada Nationala\r\nde Informatica).\r\n\npreONI se imparte in 3 grupe: clasa a IX-a si gimnaziu, clasa\r\na X-a si clasele XI-XII. Se organizeaza 4 runde online de calificare.\r\nIn urma acestora, cei mai buni de la fiecare grupa sunt invitati la\r\no runda finala.\r\n\nIn cadrul unei runde, vei avea de rezolvat 3 probleme in 4h.\r\nCastigatorii rundei finale sunt premiati cu bani si/sau obiecte.\r\n\nPe pagina concursului ( \'preoni-2007\':preoni-2007 ) vei gasi\r\ninformatii despre cum participi, cine propune probleme, premii si\r\nsponsori, regulamentul concursului samd.\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('newsletter/preoni-2007-runda-finala-rectificare','preONI 2007, Runda Finala - Rectificare','2007-06-23 13:33:41','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nS-a strecurat o greseala in ultimul e-mail.\r\nImi cer scuze pentru neatentie!\r\n\nIata rectificarea:\r\n\nProba de concurs a finalei preONI se desfasoara\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Luni, 25 iunie 2007, orele 09:00 - 14:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\n(adica peste 2 zile)\r\n\nViziteaza pagina rundei finale pentru mai multe informatii:\r\n\'preoni-2007/runda-finala\':preoni-2007/runda-finala\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('runda/preoni2007_runda5_9/clasament','Clasament preoni2007_runda5_9','2007-06-23 20:13:06','2007-06-23 20:13:06','h1. Clasament ==roundparam(round_id=\"preoni2007_runda5_9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda5_9\")==',1,'round: preoni2007_runda5_9',NULL,NULL),('preoni-2007/runda-finala/9','preONI 2007, Runda Finala, Clasa a 9-a si gimnaziu','2007-06-23 20:13:06','2007-06-25 10:41:47','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2007/runda-finala\r\n* \'Program\':preoni-2007/runda-finala/program\r\n* \'Regulament\':preoni-2007/runda-finala/regulament\r\n*(active) \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-finala/9\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda5_9\" param=\"title\") ==\r\n\r\n==roundregister(round_id=\"preoni2007_runda5_9\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nRunda se desfasoara *Luni 25 iunie*, la ora {*09^10^*} si va dura *{color:red}5h*.\r\nParticipantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2007/clasament/runda-finala/9.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda5_9\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda5_9',NULL,NULL),('runda/preoni2007_runda5_10/clasament','Clasament preoni2007_runda5_10','2007-06-23 20:19:14','2007-06-23 20:19:14','h1. Clasament ==roundparam(round_id=\"preoni2007_runda5_10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda5_10\")==',1,'round: preoni2007_runda5_10',NULL,NULL),('runda/preoni2007_runda5_11-12/clasament','Clasament preoni2007_runda5_11-12','2007-06-23 20:35:35','2007-06-23 20:35:35','h1. Clasament ==roundparam(round_id=\"preoni2007_runda5_11-12\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda5_11-12\")==',1,'round: preoni2007_runda5_11-12',NULL,NULL),('preoni-2007/runda-finala','Finala preONI 2007','2007-06-20 14:13:49','2007-06-28 13:30:44','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)*(active) \'Despre&hellip;\':preoni-2007/runda-finala\r\n* \'Program\':preoni-2007/runda-finala/program\r\n* \'Regulament\':preoni-2007/runda-finala/regulament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-finala/9\r\n\r\nh1. Finala preONI 2007, Bucuresti\r\n\r\n*preONI 2007 s-a incheiat!*\r\n\r\np={font-weight: bold}. \"Rezulate\":preoni-2007/clasament/runda-finala/9 | ==smflink(link=\"topic\" topic=\"1961\" caption=\"Feedback\")== | \"Poze!\":preoni-2007/runda-finala/poze\r\n\r\nh2. Detalii\r\n\r\nFinala concursului preONI 2007 se desfasoara in *Bucuresti*, mai exact la \'Liceul international de Informatica\':http://www.ichb.ro in perioada *24 - 26 iunie 2007*.\r\n\r\n\'Premiile concursului\':preoni-2007/premii preONI se vor acorda in functie de rezultatele rundei finale. Punctajele obtinute in perioada de calificare vor servi doar la departajare. \r\n\r\nConcurentiilor li se vor asigura cazarea si masa integral. Costul transportului pana la locul unde se va desfasura finala va fi suportat de catre concurenti.\r\n\r\nh2. Calificare\r\n\r\nCalificarea in aceasta etapa se face exclusiv pe baza \'clasamentului din primele 4 runde\':preoni-2007/clasament. De la fiecare grupa vor fi selectati ocupantii primelor *10* pozitii. Mentionam ca o persoana se poate califica la finala doar la grupa de varsta destinata lui si ca se va face si o identificare prin intermediul Cartii de Identiate (Buletin) sau Carnet de Note vizat si cu poza (pentru cei care nu au inca buletin) pentru a evita frauda. Daca aveti nelamuriri revedeti si \'regulamentul\':preoni-2007/regulament. \r\n\r\n*Pentru concurentii care nu s-au calificat in finala, vom gazdui si o varianta online a concursului in paralel cu finala de la Bucuresti!* Aveti ocazia sa va comparati performanta cu cei care au ajuns in finala. ;) Nu se acorda premii participantilor online.\r\n\r\nStudiati \'programul de desfasurare\':preoni-2007/runda-finala/program pentru mai multe informatii.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',75,'protected',NULL,NULL),('preoni-2007/runda-finala/11-12','preONI 2007, Runda Finala, Clasele 11-12','2007-06-23 20:35:35','2007-06-25 10:41:16','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2007/runda-finala\r\n* \'Program\':preoni-2007/runda-finala/program\r\n* \'Regulament\':preoni-2007/runda-finala/regulament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n*(active) \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-finala/9\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda5_11-12\" param=\"title\") ==\r\n\r\n==roundregister(round_id=\"preoni2007_runda5_11-12\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nRunda se desfasoara *Luni 25 iunie*, la ora {*09^10^*} si va dura *{color:red}5h*.\r\nParticipantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2007/clasament/runda-finala/11-12.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda5_11-12\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==',1,'round: preoni2007_runda5_11-12',NULL,NULL),('preoni-2007/clasament/runda-finala/9','Clasament preONI 2007, Runda Finala, Clasa a 9-a si gimnaziu','2007-06-23 20:46:11','2007-06-23 20:49:03','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2007/runda-finala\r\n* \'Program\':preoni-2007/runda-finala/program\r\n* \'Regulament\':preoni-2007/runda-finala/regulament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-finala/9\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda5_9\" param=\"title\") ==\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-finala/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda5_9\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/runda-finala/10','preONI 2007, Runda Finala, Clasa a 10-a','2007-06-23 20:19:14','2007-06-25 10:41:32','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2007/runda-finala\r\n* \'Program\':preoni-2007/runda-finala/program\r\n* \'Regulament\':preoni-2007/runda-finala/regulament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-finala/10\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda5_10\" param=\"title\") ==\r\n\r\n==roundregister(round_id=\"preoni2007_runda5_10\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nRunda se desfasoara *Luni 25 iunie*, la ora {*09^10^*} si va dura *{color:red}5h*.\r\nParticipantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2007/clasament/runda-finala/10.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda5_10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==',1,'round: preoni2007_runda5_10',NULL,NULL),('preoni-2007/clasament/runda-finala/10','Clasament preONI 2007, Runda Finala, Clasa a 10-a','2007-06-23 20:48:11','2007-06-23 20:50:35','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2007/runda-finala\r\n* \'Program\':preoni-2007/runda-finala/program\r\n* \'Regulament\':preoni-2007/runda-finala/regulament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-finala/9\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda5_10\" param=\"title\") ==\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-finala/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/clasament/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-finala/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda5_10\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/clasament/runda-finala/11-12','Clasament preONI 2007, Runda Finala, Clasele 11-12','2007-06-23 20:50:15','2007-06-23 20:50:46','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2007/runda-finala\r\n* \'Program\':preoni-2007/runda-finala/program\r\n* \'Regulament\':preoni-2007/runda-finala/regulament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-finala/9\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda5_11-12\" param=\"title\") ==\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-finala/10\r\n*(active) \'Clasele 11-12\':preoni-2007/clasament/runda-finala/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda5_11-12\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/premii','Sponsori si premii preONI 2007','2007-01-15 15:51:08','2007-06-26 10:24:04','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Sponsori si premii\r\n\r\nh2. Premii\r\n\r\nSe vor acorda premii in bani castigatorilor \'rundei finale\':preoni-2007/runda-finala. Pentru fiecare grupa de varsta se acorda urmatoarele premii:\r\n\r\n* Locul I: 400 lei\r\n* Locul II: 200 lei\r\n* Locul III: 100 lei\r\n\r\n*In plus, \'HOSTWAY Romania\':http://www.hostwaylab.ro/ ofera cate un domeniu la alegere si un pachet de webhosting pe un an de zile  participantilor la finala preONI!*\r\n\r\n&nbsp;\r\n\r\nh3. Mesaj de la Flaviu Radulescu, General Manager \'HOSTWAY Romania\':http://www.hostwaylab.ro/\r\n\r\n!{border:1px solid silver; float: right}preoni-2007?hostway.png!:http://www.hostwaylab.ro/\r\n\r\nDe cand a aparut pe piata in Romania anul trecut, Hostway si-a dorit sa poata participa la un astfel de eveniment. Aceasta nu este doar o declaratie de complezenta, la noi in companie, creativitatea, dorinta de a invata si flexibilitatea abordarilor fiind incurajate si sustinute permanent.\r\n\r\nHostway Romania are trei departamente \"de productie\":\r\n\r\n* web development\r\n* web hosting\r\n* software research & development\r\n\r\nSite-urile dezvoltate in departamentul de web development sunt produse in exclusivitate pentru clienti din Statele Unite.\r\n\r\nDepartamentul de Web hosting este dedicat pietei din Romania. Solutiile de hosting oferite de noi includ planuri pentru persoane fizice si companii mici sau medii, cat si suite de servicii dedicate nevoilor specifice ale companiilor de tip \"enterprise\".\r\n\r\nDepartamentul de Research & Development construieste azi internetul de maine, directia principala de dezvoltare fiind \"software as a service\". Daca doriti sa aflati mai multe puteti vizita site-ul nostru, la adresa \'www.hostwaylab.ro\':http://www.hostwaylab.ro/.\r\n\r\nCompania Hostway Corporation asigura servicii de gazduire Web, inregistrare de domenii, Web design, si campanii online pentru peste 600.000 de clienti din toata lumea. Hostway detine 14 data-centere de ultima generatie puse in slujba unei prezente globale. Fondata in 1998, Hostway este una dintre primele 5 companii de Hosting din lume, cu birouri in Chicago, Illinois; Tampa, Florida; Austin, Texas; Vancouver, British Columbia; Londra, Anglia; Paris, Franta; Amsterdam, Olanda; Antwerp, Belgia; Frankfurt, Hanovra, Germania; Bucuresti, Romania; Sydney, Australia si Mumbai, India.\r\n\r\nNe simtim onorati sa putem sprijini cea mai mare comunitate de programatori din tara, credem ca initiativa noastra va avea un impact pozitiv la dezvoltarea proiectului Infoarena, si dorim sa ne implicam si in viitoarele initiative.\r\n\r\nVa dorim mult success in continuare!\r\n\r\n&nbsp;\r\n\r\nh3. Mesaj de la Dragos Ciobanescu, Director Executiv iReal Soft\r\n\r\n!{border:1px solid silver; float: right}preoni-2007?irealsoft.png!:http://www.irealsoft.ro/\r\n\r\nFelicitari tuturor participantilor!\r\n\r\niReal Soft ofera solutii complete pentru optimizarea profitului companiilor care ofera servicii financiare (banci, asigurari, retail, IFN, etc.). Solutiile includ consultanta, analiza afacerilor, optimizarea proceselor si implementari si integrari software.\r\n\r\nProdusele iReal Soft: RBDS (Rule-Based Decision System), Collection System, Front-End System, Billing System, Universal Reporting Database, etc.\r\n\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==\r\n',13,'protected',NULL,NULL),('preoni-2007/runda-finala/poze/deschidere','Poze preONI 2007 - deschidere','2007-06-27 08:15:39','2007-06-27 14:11:16','==include(page=\"template/preoni-2007/header\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)* \'Poze\':preoni-2007/runda-finala/poze\r\n* \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n*(active) \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n* \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n* \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n* \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n* \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n* \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n* \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\n== Gallery(page=\"preoni-2007/runda-finala/poze/deschidere\" file=\"%.jpg\") ==\r\n\r\n\'Download them all\':http://infoarena.ro/preoni-2007/runda-finala/poze/deschidere?action=download&file=1-deschidere.zip',75,'public',NULL,NULL),('preoni-2007/runda-finala/poze/pregatiri','Poze preONI 2007 - pregatiri','2007-06-27 08:17:24','2007-06-27 14:10:31','==include(page=\"template/preoni-2007/header\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)* \'Poze\':preoni-2007/runda-finala/poze\r\n*(active) \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n* \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n* \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n* \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n* \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n* \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n* \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n* \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\n== Gallery(page=\"preoni-2007/runda-finala/poze/pregatiri\" file=\"%.jpg\") ==\r\n\r\n\'Download them all\':http://infoarena.ro/preoni-2007/runda-finala/poze/pregatiri?action=download&file=0-pregatiri.zip',75,'public',NULL,NULL),('preoni-2007/runda-finala/poze','Poze finala preONI 2007','2007-06-27 08:11:08','2007-06-27 13:49:15','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)*(active) \'Poze\':preoni-2007/runda-finala/poze\r\n* \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n* \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n* \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n* \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n* \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n* \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n* \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n* \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\nAici gasiti o galerie de poze facute la finala concursului preONI 2007. Enjoy!\r\n\r\nDaca mai aveti poze, puteti sa ne contactati sa le punem pe site.',75,'public',NULL,NULL),('preoni-2007/runda-finala/poze/la-masa','Poze preONI 2007 - masa','2007-06-27 08:18:35','2007-06-27 14:12:47','==include(page=\"template/preoni-2007/header\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)* \'Poze\':preoni-2007/runda-finala/poze\r\n* \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n* \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n*(active) \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n* \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n* \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n* \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n* \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n* \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\n== Gallery(page=\"preoni-2007/runda-finala/poze/la-masa\" file=\"%.jpg\") ==\r\n\r\n\'Download them all\':http://infoarena.ro/preoni-2007/runda-finala/poze/la-masa?action=download&file=3-la-masa.zip',75,'public',NULL,NULL),('preoni-2007/runda-finala/poze/concurs','Poze preONI 2007 - concurs','2007-06-27 08:19:36','2007-06-27 14:15:52','==include(page=\"template/preoni-2007/header\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)* \'Poze\':preoni-2007/runda-finala/poze\r\n* \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n* \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n* \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n* \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n*(active) \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n* \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n* \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n* \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\n== Gallery(page=\"preoni-2007/runda-finala/poze/concurs\" file=\"%.jpg\") ==\r\n\r\n\'Download them all\':http://infoarena.ro/preoni-2007/runda-finala/poze/concurs?action=download&file=4-concurs.zip',75,'public',NULL,NULL),('preoni-2007/runda-finala/poze/evaluare','Poze preONI 2007 - evaluare','2007-06-27 08:20:26','2007-06-27 14:16:14','==include(page=\"template/preoni-2007/header\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)* \'Poze\':preoni-2007/runda-finala/poze\r\n* \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n* \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n* \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n* \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n* \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n*(active) \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n* \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n* \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\n\r\n== Gallery(page=\"preoni-2007/runda-finala/poze/evaluare\" file=\"%.jpg\") ==\r\n\r\n\'Download them all\':http://infoarena.ro/preoni-2007/runda-finala/poze/evaluare?action=download&file=5-evaluare.zip',75,'public',NULL,NULL),('preoni-2007/runda-finala/poze/premiere','Poze preONI 2007 - premiere','2007-06-27 08:21:25','2007-06-27 14:16:50','==include(page=\"template/preoni-2007/header\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)* \'Poze\':preoni-2007/runda-finala/poze\r\n* \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n* \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n* \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n* \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n* \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n* \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n*(active) \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n* \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\n== Gallery(page=\"preoni-2007/runda-finala/poze/premiere\" file=\"%.jpg\") ==\r\n\r\n\'Download them all\':http://infoarena.ro/preoni-2007/runda-finala/poze/premiere?action=download&file=6-premiere.zip',75,'public',NULL,NULL),('template/preoni-2007','template/preoni-2007','2007-01-13 23:36:26','2007-06-27 13:39:39','==include(page=\"template/preoni-2007/header\")==\r\n\r\n(vmenu)*(section) \'Home\':preoni-2007\r\n* \'Clasament\':preoni-2007/clasament\r\n* \'Organizatori\':preoni-2007/comisie\r\n* \'Sponsori si premii\':preoni-2007/premii\r\n* \'Regulament\':preoni-2007/regulament\r\n* \'Aparitii in presa\':preoni-2007/presa\r\n*(section) Runde\r\n* \'Runda 1\':preoni-2007/runda-1\r\n* \'Runda 2\':preoni-2007/runda-2\r\n* \'Runda 3\':preoni-2007/runda-3\r\n* \'Runda 4\':preoni-2007/runda-4\r\n* \'Runda Finala\':preoni-2007/runda-finala\r\n',75,'protected',NULL,NULL),('preoni-2007/runda-finala/poze/gratar','Poze preONI 2007 - gratar','2007-06-27 08:22:32','2007-06-27 14:17:11','==include(page=\"template/preoni-2007/header\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)* \'Poze\':preoni-2007/runda-finala/poze\r\n* \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n* \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n* \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n* \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n* \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n* \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n* \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n*(active) \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\n== Gallery(page=\"preoni-2007/runda-finala/poze/gratar\" file=\"%.jpg\") ==\r\n\r\n\'Download them all\':http://infoarena.ro/preoni-2007/runda-finala/poze/gratar?action=download&file=7-gratar.zip',75,'public',NULL,NULL),('preoni-2007','preONI 2007','2007-01-15 15:12:34','2009-01-19 15:25:14','==Include(page=\"template/preoni-2007\")==\r\n\r\n*preONI 2007 s-a incheiat!*\r\n\r\np={font-weight: bold}. \"Rezultate\":preoni-2007/clasament/runda-finala/9 | ==smflink(link=\"topic\" topic=\"1961\" caption=\"Feedback\")== | \"Poze!\":preoni-2007/runda-finala/poze\r\n\r\nh2. Detalii\r\n\r\n*preONI*, concursul de pregatire pentru Olimpiada Nationala de Informatica, a ajuns la a patra editie.\r\n\r\n*preONI 2007* incepe cu 4 runde online de calificare. Cei mai buni de la fiecare grupa sunt invitati la finala on-site. Castigatorii rundei finale sunt premiati in bani si obiecte.\r\n\r\np. &rarr; \'Remember preONI 2006\':preoni-2006\r\n\r\nh2. Program concurs\r\n\r\ntable{width: 50%}. |_. Runda|_. Data |_. Ora |\r\n|\"*Runda 1*\":preoni-2007/runda-1|*Duminica, 21 ianuarie 2007*| *09^30^ - 13^30^* |\r\n|\"*Runda 2*\":preoni-2007/runda-2|*Duminica, 18 februarie 2007*|*09^00^ - 13^00^* |\r\n|\"*Runda 3*\":preoni-2007/runda-3|*Duminica, 4 martie 2007*| *09^00^ - 13^15^* |\r\n|\"*Runda 4*\":preoni-2007/runda-4|*Duminica, 25 martie 2007*| *09^00^ - 13^00^* |\r\n|\"*Runda finala*\":preoni-2007/runda-finala| *Luni, 26 iunie 2007* | *09^00^ - 14^00^* |\r\n\r\nClick pe titlul unei runde pentru informatii detaliate.\r\n\r\nDatele scrise _inclinat_ sunt provizorii. Este posibil sa le schimbam pe parcurs.\r\n\r\nh2. Despre preONI\r\n\r\n*preONI*, concursul de marca al comunitatii infoarena, este dedicat elevilor de liceu ce se pregatesc pentru ONI (\'Olimpiada Nationala de Informatica\':http://olimpiada.info/).\r\n\r\nConcursul este impartit in 3 grupe: clasa a IX-a si gimnaziu, clasa a X-a si clasele XI-XII. Se organizeaza 4 runde online de calificare. In urma acestora, cei mai buni de la fiecare grupa sunt invitati la o \'runda finala\':preoni-2007/runda-finala.\r\n\r\nIn cadrul unei runde, concurentii au de rezolvat 3 probleme in 4 ore. Castigatorii rundei finale sunt premiati cu bani si/sau obiecte.\r\n\r\nVezi \'preONI 2006\':preoni-2006, \'preONI 2005\':preoni-2005.\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru.\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti probleme, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nPoti sa rezolvi probleme de la orice grupa de varsta. Totusi, te vei califica la runda finala numai daca te incadrezi in grupa la care ai concurat.\r\n\r\nh2. Prima data pe infoarena?\r\n\r\ninfoarena ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi.\r\n\r\nVezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',13,'protected',NULL,NULL),('preoni-2007/runda-finala/poze/wii-play','Poze preONI 2007 - wii-play','2007-06-27 08:25:04','2007-06-27 14:15:22','==include(page=\"template/preoni-2007/header\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)* \'Poze\':preoni-2007/runda-finala/poze\r\n* \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n* \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n* \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n*(active) \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n* \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n* \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n* \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n* \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\n== Gallery(page=\"preoni-2007/runda-finala/poze/wii-play\" file=\"%.jpg\") ==\r\n\r\n\'Download them all\':http://infoarena.ro/preoni-2007/runda-finala/poze/wii-play?action=download&file=x-wii-play.zip\r\n\'Filmulet mulgand vaca\':http://infoarena.ro/preoni-2007/runda-finala/poze/wii-play?action=download&file=mov01766.mpg',75,'public',NULL,NULL),('preoni-2007/runda-finala/solutii','Solutii preONI 2007, Runda Finala','2007-06-25 12:07:40','2007-12-14 23:10:11','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Solutii Runda Finala\r\n\r\nh2. \'Orase\':problema/orase\r\n\r\nh3. (problema usoara, clasa a 9-a)\r\n\r\nLa primul pas se vor sorta orasele crescator dupa $D{~i~}$. Renumerotand orasele in ordinea sortarii, putem calcula distanta care trebuie parcursa intre doua orase $j < i$: $L{~i~}+D{~i~}+L{~j~}-D{~j~}$. Pentru fiecare $i$ vrem sa determinam un oras $j < i$ astfel incat sa se maximizeze aceasta distanta. Alegerea optima va fi un oras $j$ cu valoarea $L{~j~}-D{~j~}$ maxima; astfel, pe masura ce se avanseaza cu indicele $i$ se pastreaza si un indice $j$ maxim pana in prezent. Complexitatea rezolvarii este $O(N*lg N)$ datorita sortarii.\r\n\r\nh2. \'Sarpe\':problema/sarpe\r\n\r\nh3. (problema medie, clasa a 9-a)\r\n\r\nVom calcula intai numarul de posibilitati pentru cazul in care $1$ se afla in unul din colturi. Sa presupunem ca l-am asezat in coltul stanga sus. Distingem doua cazuri:\r\n\r\n* $2$ este asezat la dreapta lui $1$ caz in care exista un singur mod de completare\r\n\r\ntable(example). | 1 | 2 | 3 | ... |\r\n| 2N | 2N-1 | 2N-2 | ... |\r\n\r\n* $2$ este asezat in coltul din stanga jos caz in care vom avea de completat tabla ramasa cu numerele {$3$}, {$4$}, ... {$2N$} punand $3$ la dreapta lui $2$ lucru care este echivalent cu completarea unei table cu $N-1$ coloane cu $1$ fixat in unul din colturi.\r\n\r\ntable(example). | 1 | &nbsp; | ... |\r\n| 2 | 3 | ... |\r\n\r\nIn concluzie numarul de moduri in care se poate completa tabla de dimensiune $N$ cu $1$ pus intr-un colt fixat este {$N$}. Analizam acum cazul in care $1$ este pus pe una din coloanele {$2, 3 , ... N-1$}. $2$ nu poate fi pus sub $1$ deoarece tabla s-ar imparti in doua bucati care nu sunt conexe si nu se poate completa comform cerintei. Daca 2 este pozitionat in stanga lui 1 toate coloanele {$1, 2, ... i$} se vor completa in mod unic.\r\n\r\ntable(example). |i | ... | 2 | 1 | ... |\r\n| i+1 | ... | 2*i - 1  | 2*i | ... |\r\n\r\nDeci vor ramane de completat $N-i$ coloane care trebuie completate cu $2*i+1$ pus intr-un colt fixat. Deci vom avea in total $N-i$ posibilitati. In mod analog daca $2$ se afla in dreapta vom avea $i-1$ posibilitati. Numarul total de posibilitati cand $1$ se afla pe una din coloanele {$2, 3, ... N-1$} va fi suma de la $2$ la $N-1$ din {$2(N-i+i-1)$} adica {$2(N-2)(N-1)$} deoarece se poate incepe de sus sau de jos. Raspunsul cautat va fi {$4N + 2(N-1)(N-2)$}, {$N > 1$}. Operatiile trebuiau efectuate pe numere mari.\r\n\r\nh2. \'Sate\':problema/sate\r\n\r\nh3. (problema grea, clasa a 9-a, problema usoara, clasa a 10-a)\r\n\r\nPutem considera $N$ puncte coliniare {$A{~1~}$}, {$A{~2~}$}... {$A{~N~}$}. Problema cere, daca cunoastem lungimile a exact $M$ segmente, sa determinam lungimea segmentului {$A{~X~}$}{$A{~Y~}$}. O rezolvare {$O(N^3^)$} nu este dificil de gasit. Vom afla lungimea tuturor segmentelor care se pot forma. Vom retine intr-o coada toate acele segmente carora le stim lungimea. Initial, in coada se afla doar cele $M$ segmente. Cand suntem pe un element in coada si vrem sa aflam ce noi segmente putem introduce, iteram un punct \"de rupere\" {$K$}. Sa presupunem ca stim lungimea segmentului {$A{~i~}A{~j~}$}. Distingem urmatoarele cazuri:\r\n\r\n* {$K < i$} si stim lungimea segmentului {$A{~K~}A{~i~}$} => inseram in coada segmentul {$A{~K~}A{~j~}$} cu lungimea egala cu suma lungimilor segmentelor {$A{~K~}A{~i~}$} si {$A{~i~}A{~j~}$}\r\n* {$i < K < j$}\r\n** stim lungimea segmentului {$A{~i~}A{~K~}$} => inseram in coada segmentul {$A{~K~}A{~j~}$} cu lungimea egala cu diferenta dintre lungimilor segmentelor {$A{~i~}A{~j~}$} si {$A{~i~}A{~K~}$}\r\n** stim lungimea segmentului {$A{~K~}A{~j~}$} => inseram in coada segmentul {$A{~i~}A{~K~}$} cu lungimea egala cu diferenta dintre lungimilor segmentelor {$A{~i~}A{~j~}$} si {$A{~K~}A{~j~}$}\r\n* {$K > j$} si stim lungimea segmentului {$A{~j~}A{~K~}$} => inseram in coada segmentul {$A{~i~}A{~K~}$} cu lungimea egala cu suma lungimilor segmentelor {$A{~i~}A{~j~}$} si {$A{~j~}A{~K~}$}\r\n\r\nDaca in final segmentul {$A{~X~}A{~Y~}$} a fost inserat in coada, atunci afisam lungimea acestuia.\r\n\r\nRezolvarea {$O(N+M)$} se bazeaza pe faptul ca nu avem nevoie sa stim lungimile tuturor segmentelor, ci doar a celor care au unul din capete punctul {$A{~X~}$}. Notam cu {$D{~i~}$} lungimea segmentului {$A{~X~}A{~i~}$}. Fiecare punct va fi identificat printr-un nod intr-un graf. Lungimea muchiei intre intre doua noduri va fi lungimea segmentului dat de punctele corespunzatoare nodurilor. Acum putem aplica o parcurgere BF din nodul $X$ si respectam toate cazurile care apar. In final, in {$D{~Y~}$} se afla lungimea segmentului {$A{~X~}A{~Y~}$}.\r\n\r\nh2. \'Branza\':problema/branza\r\n\r\nh3. (problema medie, clasa a 10-a)\r\n\r\nAceasta problema se rezolva folosind metoda programarii dinamice. O solutie triviala are complexitatea $O(N*T)$ si se realizeaza calculand vectorul $m[i] = costul minim pentru a obtine un kg de branza in saptamana i$. Acesta se obtine folosind formula $m[i] = min{C[j] + (i-j)*S | i-j &le; T}$.\r\nPentru a reduce complexitatea la $O(N)$ se observa ca pentru calculul lui $m[i]$ avem nevoie doar de valorile lui $C$ cuprinse intre $max(1, i-T)$ si $i$, interval a carei dimensiuni nu poate decat sa creasca sau sa ramana constanta. Se foloseste un deque in care se introduc pe rand valorile din $C$ modificate corespunzator pentru a asigura gasirea minimului cerut la fiecare pas. Astfel la pasul $i$ se va introduce in deque valoarea $C[i] + (N-i)*S$, pentru a mentine relatia de ordine corespunzatoare relatiei de recurenta intre elementele structurii. La pasul $i$ se considera elementul din coada deque-ului (fie acela provenit de la $C[j]$) din care se scade @(N-j)*S@ pentru a obtine pe $m[i]$.\r\nSolutia ceruta este @m[1]@ $* P{~1~} +$ @m[2]@ $* P{~2~} + ... + m[N] * P{~N~}$\r\n\r\nh2. \'Gradina\':problema/gradina\r\n\r\nh3. (problema grea, clasa a 10-a)\r\n\r\nEste evident ca cele doua poligoane convexe pot fi separate de o dreapta care sa treaca printr-un varf $A$ de pe primul poligon si un varf $B$ de pe cel de-al doilea. Astfel, dreapta imparte planul in doua semiplane si in fiecare din cele doua semiplane se afla cate un poligon convex.\r\nDintre cele $N$ puncte alegem toate perechile de puncte {$(X Y)$} si presupunem ca dreapta determinata de aceste doua puncte separa cele doua poligoane, iar punctul $X$ este varf pentru primul poligon si punctul $Y$ pentru cel de-al doilea. Pentru o dreapta fixata, putem aplica pentru fiecare din cele semiplane un algoritm de infasuratoare convexa ( verificand apoi daca infasuratoarea convexa contine toate punctele din semiplanul respectiv ) in {$O(N log N)$}, rezultand o complexitate totala de {$O(N^3^ log N)$}. Pentru a obtine complexitatea {$O(N^3^)$}, putem sorta punctele in functie de ordonata si apoi in functie de abscisa de la inceput. Astfel, in algoritmul Graham pentru poligoane convexe nu mai este necesara resortarea punctelor si algoritmul, pentru o dreapta fixata, dureaza {$O(h1) + O(h2)$}, unde $h1$ si $h2$ sunt numarul de puncte din cele doua semiplane. Cum {$O(h1 + h2)$} = {$O(N)$}, complexitatea algoritmului este {$O(N^3)$}.\r\n\r\nh2. \'P-Sir\':problema/psir\r\n\r\nh3. (problema usoara, clasele 11-12)\r\n\r\nProblema se rezolva prin metoda programarii dinamice. Conditia din enunt se poate enunta astfel: elementul $a{~i~}$ dintr-un p-sir trebuie sa fie inclus strict in intervalul determinat de $a{~i-1~}$ si $a{~i-2~}$. Vom calcula $Nr[i][j]$ numarul de p-subsiruri care au ultimiii doi termeni $P{~i~}$ si $P{~j~} (i < j)$. \r\nVom presupune ca $P{~i~} < P{~j~}$, cazul $P{~i~} > P{~j~}$ putand fi tratat asemanator. $Nr[i][j]$ se va calcula ca suma de $Nr[k][i]$ cu proprietatea $P{~i~} < P{~j~} < P{~k~}$. O implementare directa a acestei rezolvari are complexitatea $O(N^3^)$ si ar fi obtinut $30$ de puncte. Daca sortam vectorul $P$ dat la intrare, valorile $k < i$ care respecta conditia $P{~j~} < P{~k~}$ vor forma un interval continuu ca indici. Vom calcula sume partiale pentru coloana $i$ din matricea $Nr$ parcurgand liniile matricii in ordinea sortarii. Astfel, calculul lui $Nr[i][j]$ se reduce la scaderea a doua sume partiale. Pentru a identifica exact ce sume se scad se poate folosi o cautare binara, reducand astfel rezolvarea la $O(N^2^*lg N)$. \r\nMentionam ca se poate obtine si o solutie $O(N^2^)$ daca se calculeaza valorile de pe linia $i$ din matricea $Nr$ in ordinea sortarii. Putem astfel renunta la cautare binara, deoarece indicele in care se face scaderea sumelor partiale va fi monoton.\r\nCa o ultima precizare, nu era necesar folosirea tipurilor de date pe $64$ de biti pentru a efectua operatii modulo $2^32^$. Mai mult, nu este necesar nici macar folosirea operatiei modulo. Daca se foloseste un tip intreg pe $32$ fara semn ({$unsigned$} in $C/C++$) orice operatie cu variabile de acest tip este automat modulo $2^32^$.\r\n\r\n\r\nh2. \'Eval\':problema/eval\r\n\r\nh3. (problema medie, clasele 11-12)\r\n\r\nEste evident ca o solutie care simula evaluarea expresiei nu s-ar fi incadrat ca timp sau ca memorie, deoarece rezultatele obtinute pe parcurs pot fi foarte mari, desi rezultatul final este limitat de $10^1000^$. Pentru rezolvarea acestei probleme este necesara \'teorema chineza a resturilor\':http://en.wikipedia.org/wiki/Chinese_remainder_theorem :\r\nFie $K$ numere prime distincte $P{~1~}, P{~2~},... ,P{~K~}$ si $K$ resturi $R{~1~}, R{~2~},... R{~K~}$. \r\nExista un numar natural unic $N$ mai mic decat produsul celor $K$ numere prime care satisface relatiile $N = R{~i~} (mod P{~i~})$.\r\nVom rezolva intai problema de $70%$, adica variabilele si rezultatul sunt numere naturale. Daca alegem un numar suficient de numere prime astfel incat produsul lor sa fie mai mare decat $10^1000^$, putem calcula rezultatul expresiei modulo fiecare numar prim in timp liniar si putem reconstitui rezultatul (care va fi unic) folosind teorema chineza a resturilor. O prezentare detaliata a acestei teoreme se gaseste si in \'acest articol\':downloads?action=download&file=mate.pdf.\r\nPutem reduce varianta cu numere intregi la problema initiala cu numere naturale adunand constanta $10^1000^$ la expresie. Astfel se garanteaza ca rezultatul expresiei este in intervalul $[0, 2*10^1000^]$.\r\nDeoarece lungimea expresiei este de $100.000$ trebuiau se se foloseasca numere prime relativ mari. Solutia oficiala foloste aproximativ $120$ de numere prime din intervalul $[10^9^, 2*10^9^]$.\r\n\r\nh2. \'Obiective\':problema/obiective\r\n\r\nh3. (problema grea, clasele 11-12)\r\n\r\nPutem asocia problemei un graf orientat care are proprietatea:\r\n\r\n(*): Oricum am alege 3 noduri {$A$}, {$B$}, {$C$} din graf astfel incat sa existe drum de la {$A$} la {$C$} si de la {$B$} la {$C$}, atunci exista drum de la {$A$} la {$B$} sau de la {$B$} la {$A$} ( posibil ambele ).\r\n\r\nUn query {$(x y)$} cere determinarea numarului minim de arce care trebuiesc reorientate astfel incat sa avem drum de la $x$ la {$y$}. Problema se poate rezolva optim in complexitate {$O(N + M + T)$}, dar in concurs o solutie {$O( (N + T) log N + M log M )$} era suficienta pentru obtinerea punctajului maxim.\r\n\r\nGraful initial se transforma intr-un graf aciclic, graful componentelor tare conexe, pe care il vom nota {$G*$}. In continuare, cand ne referim la nodul $x$ in {$G*$} ne referim la nodul componentei tari conexe care il contine pe {$x$}. Numim radacina pentru {$G*$} acel nod care are gradul intern $0$ ( nodul in care nu intra nici o muchie ). Exista un singur astfel de nod, deoarece, daca ar exista cel putin doua, conditia (*), impreuna cu proprietatea de conexitate a grafului suport, nu ar mai fi respectata. \r\nCum {$G*$} este aciclic, putem sorta nodurile lui astfel incat daca exista muchie de la $x$ la $y$ in {$G*$}, $x$ va aparea inaintea lui $y$ in sortare ( sortare topologica ). Pentru fiecare nod din {$G*$} sortam lista lui de adiacenta conform ordinii din sortarea topologica. Sortarea se poate face liniar, cu radixsort, sau cu algoritmul quicksort.\r\n\r\nDupa sortarea listelor de adiacenta, se efectueaza o parcurgere DF din radacina lui {$G*$}.\r\n\r\n\r\n* _Propozitie 1_: Arborele DF rezultat din parcurgerea de mai sus contine numai muchii de arbore sau muchii inainte.\r\n\r\n\r\nCum {$G*$} este aciclic, nu pot exista muchii de intoarcere ( inapoi ). Vom demonstra ca nu exista muchii transversale. Definim {$nivel{~x~}$} ca fiind numarul de noduri de la $x$ la radacina pe drumul format din numai muchii de arbore.\r\nPresupunem prin reducere la absurd ca exista o muchie transversala {$x->y$}. Selectam acea muchie transversala {$x->y$} pentru care {$nivel{~y~}$} este minim. $Y$ nu poate fi radacina lui {$G*$}, pentru ca, in caz contrar, muchia {$x->y$} ar fi muchie de intoarcere si ar forma un ciclu, dar {$G*$} este aciclic. Deci exista un nod $u$ care este tatal lui {$y$}. Demonstram ca pentru tripletul {$(x u y)$} conditia (*) nu este indeplinita.\r\nExista drum de la $x$ la $y$ si de la $u$ la {$y$}. Drum de la $x$ la $u$ nu poate exista deoarece $u$ se afla in alt subarbore si, pentru a trece dintr-un subarbore in altul, trebuie se parcurgem muchii transversale. Dar {$x->y$} era muchia transversala pentru care {$nivel{~y~}$} era minim, si cum {$nivel{~u~}$} < {$nivel{~y~}$} si nu exista muchii de intoarcere => nu putem ajunge din $x$ in {$u$}. Nu putem ajunge nici din $u$ in $x$ datorita modului in care au fost sortate listele de adiacenta. Sa presupunem ca putem ajunge din {$u$} in {$x$}. Cum avem muchia {$x->y$}, $x$ apare inaintea lui $y$ in sortarea topologica, deci va aparea in listele de adiacenta mai devreme. Cand facem parcurgerea DF din nodul {$u$}, vom trece mai intai prin nodul $x$ si de abia dupa aceea prin nodul {$y$}, iar muchia {$x->y$} nu mai este muchie transversala.\r\nPropozitia a fost demonstrata.\r\n\r\n\r\n* _Propozitie 2_: Orice arbore DF care are doar muchii de arbore si muchii inainte indeplineste proprietatea (*).\r\n\r\n\r\nDaca exista numai muchii de arbore si avem un triplet {$(A B C)$} care respecta ca exista drum de la $A$ la $C$ si de la $B$ la {$C$}, atunci si $A$ si $B$ se afla in lista predecesorilor lui {$C$}. Unul din nodurile $A$ sau $B$ trebuie sa apara primul in aceasta lista, deci vom avea drum fie de la $A$ la {$B$}, fie de la $B$ la {$A$}.\r\nCand inseram muchiile inainte nu apar triplete noi pentru care sa existe drum de la $A$ la $C$ si de la {$B$} la {$C$}, deci propozitia a fost demonstrata.\r\n\r\n\r\nArborele DF contine deci numai muchii de arbore si muchii inainte. Pentru un query {$(x y)$} vom aplica o strategie de tip greedy. Fie {$L$} = {$Lowest_Common_Ancestor(x, y)$}. Pentru a reorienta un numar minim de muchii, trebuie sa reorientam acele muchii care ne duc cat mai aproape de radacina. Astfel, trebuie sa ajungem intr-un nod {$u$}, stramos al lui {$x$}, pentru care {$nivel{~u~}$} &le; {$nivel{~L~}$}. Daca putem ajunge din $x$ in {$u$}, putem cobori in arbore pana in {$y$}. Pentru acest pas vom folosi un algoritm liniar, de genul celui folosit in determinarea muchiilor critice in grafuri neorientate.\r\nFie {$low{~x~}$} nodul cel mai apropiat de radacina in care se poate ajunge din $x$ prin reorientarea a exact unei singure muchii si {$level{~x~}$} nivelul lui {$low{~x~}$}. Relatia de recurenta este:\r\n\r\n{$level{~x~}$} = minim({$level{~parinte[x]~}$}; {$level{~y~}$} | y fiu al lui x; {$level{~u~}$} | {$u->x$} muchie inainte )\r\n\r\nSimultan cu vectorul {$level$} construim si vectorul {$low$}.\r\n\r\nPe baza informatiilor astfel calculate, construim un arbore cu $N$ noduri in care tatal nodului {$i$}, $i$ de la $1$ la {$N$}, va fi {$low{~i~}$}. Acum trebuie sa aflam nodul $u$ din acest arbore care indeplineste {$nivel{~u~}$} &le; {$nivel{~L~}$} si {$u$} se afla cat mai aproape de {$x$}. Raspunsul pe query va fi dat de diferenta de nivel dintre $u$ si {$x$}.\r\nPentru a afla nodul $u$ in timp logaritmic ne putem intoarce pe stramosi ai lui $x$ pe baza de puteri ale lui 2 sau putem afla nodul $u$ in {$O(1)$}, demonstrand ca nodul cautat $u$ este fie {$L$}, fie {$parinte{~L~}$} in acest arbore.\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'public',NULL,NULL),('documentatie/acces-email','Email @infoarena.ro','2007-11-01 13:36:19','2009-03-02 17:24:04','h1. Email @infoarena.ro\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nUnii utilizatori, în special membrii \'echipei infoarena\':echipa-infoarena, primesc o adresă de email @infoarena.ro. Dacă vrei şi tu una, contactează-l pe ==User(type=\"tiny\" user=\"wickedman\")== sau pe ==User(type=\"tiny\" user=\"domino\")==.\r\n\r\nServiciul de email este asigurat de \'Google Apps for infoarena.ro\':http://m.infoarena.ro/.\r\n',13,'public',NULL,NULL),('documentatie/administrare','Administrare','2009-09-23 16:57:24','2009-09-23 16:57:24','h1. Administrarea site-ului\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nh2. Resurse\r\n\r\n* \'Pagină de administrare protejată\':admin\r\n* \'email@infoarena.ro\':documentatie/acces-email\r\n* \'Backup infoarena\':documentatie/backup\r\n\r\nh2. Probleme si runde\r\n\r\nExista un numar de pagini speciale pentru management de probleme si runde.\r\n\r\n* \'admin/problema-noua\':admin/problema-noua : propunere problema noua\r\n* _admin/problema/nume-problema_ : editare detalii probleme\r\n* \'admin/runda-noua\':admin/runda-noua : creare concurs nou\r\n* _admin/runda/nume-concurs_ : editare detalii concurs\r\n\r\nDoar pentru admini, in monitor apare un buton de reevaluare. Nu puteti reevalua decat $512$ job-uri odata, si se pot folosi \'filtre\':documentatie/monitorul-de-evaluare in monitor pentru a alege job-urile.\r\n\r\nh2. Securitate\r\n\r\nOrice pagina din \'wiki\':documentatie/wiki are un \"descriptor de securitate\" care poate fi manipulat doar de catre administratori. Acel descriptor de securitate este un string free-form.\r\n\r\nPentru pagini oarecare exista 3 nivele de securitate:\r\n\r\n* $public$ : vizibila pentru toata lumea, o poate edita orice user logat.\r\n* $protected$ : vizibila pentru toata lumea, o pot edita doar adminii.\r\n* $private$: vizibila doar pentru admini, o pot edita doar adminii.\r\n\r\nMajoritatea paginilor ar trebui sa aiba sa fie publice pentru ca in general putem avea incredere in utilizator. Pagini foarte vizibile de genul home sau preoni probabil ca o sa fie facute protected. Pentru a prinde vandalii avem o \'pagina de modificari\':changes cu \'rss\':changes?format=rss. Editarea anonima nu este suportata.\r\n\r\nh3. Securitate pentru probleme si runde\r\n\r\nPaginile care apartin de un task/round au ca descriptor de securitate ceva de genul $task: gigi$, unde gigi este numele task-ului. *Nu* este neaparat necesar ca paginile acelea sa inceapa cu problema/ sau runda/, dar asa facem prin conventie.',1142,'protected',NULL,NULL),('templates/junior_head','template/junior_head','2007-06-29 19:58:49','2007-06-30 09:44:53','table{margin: 0; width: 99%; background-image: url(/templates/junior_head?action=download&file=star.jpg); background-position: bottom left;}. |{border: 0px;}. !templates/junior_head?logo3.jpg!:/junior-challenge |{border: 0px; text-align: right; vertical-align: bottom}. |\r\n',256,'public',NULL,NULL),('runda/preoni2007_runda4_9','runda/preoni2007_runda4_9','2007-03-13 21:01:37','2007-06-30 14:29:10','',5748,'public',NULL,NULL),('newsletter/junior-challenge','Junior Challenge','2007-06-30 17:02:48','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\ninfoarena organizeaza un nou concurs pentru tine.\r\nTe invitam sa participi la Junior Challenge, \r\nconcurs destinat in principal incepatorilor in programare.\r\nConcursul este totodata o ocazie de antrenament pentru\r\nechipa ce va reprezenta Romania la Olimpiada Balcanica de Juniori.\r\n\nConcursul se va desfasura ...\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n     Miercuri, 4 iulie 2007, orele 09:00 - 12:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPentru informatii detaliate despre concursul\r\nJunior Challenge, acceseaza: \'junior-challenge\':junior-challenge\r\n\nh2.  Concurs fara rating! \n\nParticiparea la acest concurs nu iti va afecta rating-ul pe infoarena.\r\nDespre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nGhidul utilizatorului: \'documentatie/pentru-utilizatori\':documentatie/pentru-utilizatori\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nClick pe acest link ca sa nu mai primesti instiintari:\r\n\'account/%username%\':account/%username%\r\n\ninfoarena nu trimite mesaje nesolicitate!\r\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\n\n',75,'public',NULL,NULL),('ghid-complet-pentru-concursurile-de-informatica','Ghid complet pentru concursurile de informatica','2007-06-30 09:09:40','2009-02-20 00:03:30','h1. Ghid complet pentru concursurile de informatica\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"sims_gl\") ==\r\n\r\n(Categoria _Diverse_, Autor _Mircea Pasoi_)\r\n\r\n**Acest articol se adreseaza pasionatilor de informatica si celor care au de gand sa participe la concursurile si olimpiadele de informatica. Observatiile din cadrul acestui articol sunt, in mare parte, rezultatul experientei autorului.**\r\n\r\nh2. 1. Ce sunt concursurile?\r\n\r\nConcursurile de informatica, ca la orice alta disciplina, vor sa fie o metoda de clasificare a participantilor in functie de abilitatile de programare si de cunostintele de algoritmica. In plus, exista unele concursuri in care cei mai buni concurenti sunt rasplatiti. Probabil cel mai important aspect, concursul include aparitia unui factor suplimentar care rastoarna multe din obisnuintele programarii \"la domiciliu\" sau \"la locul de munca\" (de obicei programatorii care lucreaza in firme au perioade mult mai lungi de timp pentru a-si duce la final sarcina): **timpul**. Autorul a avut la dispozitie mai mult de sapte ani ca sa descopere pe propria piele importanta foarte mare a acestui factor; si, mai mult decat durata de timp in sine a concursului, care este aceeasi pentru toti concurentii, conteaza capacitatea fiecaruia de a gestiona bine acest timp. Daca in fata calculatorului de acasa, cu o sticla de suc alaturi si cu muzica mergand, este intr-adevar un lucru laudabil sa justificam matematic fiecare pas al algoritmului, sa nu ne lasam inselati de intuitie si sa scriem programul fara sa ne grabim, alocandu-ne o mare parte din timp numai pentru depanarea lui, in schimb, in timp de concurs lucrurile  stau tocmai invers: de demonstratii riguroase din punct de vedere matematic rar are timp cineva, intuitia fiind la mare pret si de nenumarate ori fiind criteriul care aduce victoria; iar timpul la un concurs serios este suficient doar pentru implementarea tuturor programelor, pentru depanare alocandu-se de obicei o perioada destul de mica.\r\n\r\nIn multe cazuri, cele doua etape principale ale programarii - conceperea si implementare algoritmului - incep sa se bata cap in cap. Exista situatii in care avem la dispozitie un algoritm foarte eficient, dar implementarea acestuia este extrem de dificila, alteori algoritmul ales nu va face fata volumului maxim de date de intrare, iar alteori ne dam seama ca am putea foarte usor sa scriem un program, dar nu suntem in stare sa demonstram ca el merge sigur pe orice set de date de intrare. Foarte des se renunta la implementarea algoritmilor de complexitate optima, care in multe cazuri constituie adevarate focare de \"bug\"-uri, preferandu-se un algoritm mai lent dar care sa se poate implementa mai rapid si fara dureri de cap. Multi concurenti pierd primii ani de concursuri descoperind aceste lucruri. Desigur, aceste lucruri variaza foarte mult in functie de viteza fiecaruia de a implementa in limbajul preferat (atentie, viteza mare de tastare a unui text normal nu garanteaza neaparat o viteza mare de tastare a unui program!), cat si de abilitatea de a te concentra la toate detaliile care apar in implementare (acest lucru depinde foarte mult de cat de antrenata este mintea fiecaruia). De fapt, concurentii care ies pe primele locuri de obicei, sunt cei care au reusit sa formeze un echilibru intre cele doua etape ale programarii: pot sa conceapa algoritmi eficienti, care sa se incadreze in limitele de timp si memorie, cat si sa implementeze acesti algoritmi intr-un timp acceptabil, depanand foarte putin.\r\n\r\nO intrebare pe care cineva, care citeste aceste randuri, si-o poate pune este urmatoarea: _De ce sa particip la astfel de concursuri?_ Principalele avantaje sunt formarea unei gandiri algoritmice, intelegerea metodelor de rezolvare pentru anumite probleme (care pot aparea si in cadrul dezvoltarii de aplicatii), dezvoltarea capacitatii de a reactiona rapid intr-un timp scurt. In timp, experienta acumulata in cadrul pregatirii si a concursurilor va conduce la eficienta mai mare in cadrul proiectelor de dezvoltare de software si, de ce nu, la obtinerea unor salarii mai mari la angajare. Exista multe companii care iau in considerare participarile la concursuri la interviurile pentru angajare, cat si multe facultati din strainatate care le considera un criteriu pentru primirea unei burse (asta nu inseamna ca o astfel de participare garanteaza neaparat o bursa!). Un alt avantaj ce nu este de neglijat este reprezentat de premiile puse in joc, atat cele materiale (calculatoare, diferite componente hardware, excursii in strainatate, carti, etc.), cat si intrarea fara examen la facultate, in cazut obtinerii unor rezultate bune la olimpiadele nationale sau internationale.\r\n\r\nh2. 2. Care sunt concursurile?\r\n\r\nO alta intrebare la care doresc sa afle raspunsul cei care vor sa participe la concursurile de informatica este: _Care sunt cele mai importante concursuri de programare?_ Se pot clasifica doua mari tipuri de concursuri: cele pentru gimnaziu si liceeni si cele pentru studenti.\r\n\r\nh3. Concursuri pentru liceu\r\n\r\n* **Olimpiada Locala de Informatica** - Se desfasoara in fiecare judet de obicei la inceputul anului (lunile ianuarie-februarie) si, in general, nivelul de dificultate este foarte redus (exceptie facand poate Bucuresti si alte cateva judete), subiectele fiind propuse de profesorii din judetul respectiv.\r\n* **Olimpiada Judeteana de Informatica** - Incepand cu anul 2003 subiectele pentru olimpiada judeteana au fost aceleasi in toata tara; de obicei se desfasoara cu o luna dupa olimpiada locala si cu cel putin o luna inainte de olimpiada nationala; subiectele sunt de un nivel mediu in general.\r\n* \"**Olimpiada Nationala de Informatica**\":http://olimpiada.info - Se organizeaza o data pe an, de obicei in prima vacanta din semestrul II al anului scolar; probele pentru liceu se desfasoara timp de 2 zile, in fiecare zi concurentii avand de rezolvat 3 probleme in 4 ore, iar probele pentru gimnaziu dureaza doar o zi, cate 2 probleme in 3 ore. De asemenea, prima jumatate din clasamentul pentru fiecare clasa de liceu participa la barajele pentru selectia lotului largit de informatica - aici, toti concurentii, indiferent de varsta, au de rezolvat aceleasi probleme. Primii ~20 selectati in urma acestei probe (care se desfasoara tot timp de 2 zile) vor forma lotul national largit; acestia vor participa la mai multe pregatiri, in cadrul carora sunt incluse baraje pentru selectarea echipelor de cate 4 elevi care vor reprezenta Romania la BOI, CEOI si IOI.\r\n* **Balcaniada de Informatica** (BOI) - Prima editie a avut loc la Constanta in anul 1993. Standardele acestui concurs nu erau foarte ridicate, iar concurentii romani se claseaza foarte des pe primele locuri. Cel mai concludent exemplu in acest sens este faptul ca la editia din anul 2001 toate cele patru medalii de aur au fost obtinute de reprezentantii nostri, iar in 2005 ambele medalii de aur acordate au revenit iarasi romanilor. Exista si ani cand nivelul de dificultate al problemelor este mai ridicat, spre exemplu in 2003(Romania) si 2004(Bulgaria).\r\n* **Olimpiada de Informatica a Europei Centrale** (CEOI) - Prima editie a avut loc la Cluj-Napoca in anul 1994. Editia din 2000 a acestui concurs a avut loc tot la Cluj-Napoca si foarte probabil editia din 2009 va fi tot in Romania. Standardele acestui concurs sunt mai ridicate decat cele de la BOI, deoarece elevii din tarile participante sunt intotdeauna foarte bine pregatiti.\r\n* **Olimpiada Internationala de Informatica** (IOI) - Acest concurs reuneste anual elevi din ~80 tari ale lumii. Fiecare tara este reprezentata de cel mult patru concurenti, iar numarul tarilor participante creste in fiecare an. Organizarea concursului este asemanatoare cu cea a celorlalte concursuri internationale mentionate. Concursul este individual si se desfasoara sub forma a doua probe. La fiecare proba concurentii au la dispozitie 5 ore pentru a rezolva 3 probleme cu un grad ridicat de dificultate. Dupa fiecare proba, programele concurentilor sunt evaluate automat, cu ajutorul unor programe de evaluare. Dupa cele doua zile de concurs se stabileste clasamentul final si se acorda medaliile. Rezultatele sunt secrete pana in momentul decernarii premiilor. La aproape toate editiile acestui concurs, echipa Romaniei a avut rezultate excelente. Astfel, incepand din anul 1993, cu doar doua exceptii, toti cei patru componenti ai echipei tarii noastre au obtinut medalii; conform punctajelor individuale, s-au obtinut doua locuri I (1993 si 1998) cu punctaj maxim si un loc II (2001), iar in clasamentul pe natiuni Romania este o prezenta constanta in primele 10 locuri.\r\n\r\nMai exista si alte concursuri internationale, cum ar fi **Olimpiada Tarilor Baltice**, la care Romania nu participa. Puteti gasi detalii mai multe despre aceste concursuri, cat si problemele propuse, folosind \"Google\":http://www.google.com. De asemenea problemele si solutiile din ultimii ani pentru concursurile importante pot fi gasite la sectiunea \"Downloads\":http://infoarena.ro/downloads a site-ului \"infoarena\":http://infoarena.ro, acesta fiind actualizat periodic.\r\n\r\nExista cateva concursuri regionale si nationale similare olimpiadelor (difera timpul de concurs, numarul de probe si dificultatea problemelor). Cateva dintre acestea sunt:\r\n\r\n* **Marele Premiu al Palatului Copiilor** - concurs organizat la Palatul National al Copiilor din Bucuresti; participa echipe ale Cluburilor Copiilor din mai multe judete ale tarii\r\n* **Concursul \"Grigore C. Moisil\"** - organizat anual la Lugoj; are o desfasurare similara\r\n* diferite concursuri interjudetene organizate in anumite regiuni ale tarii; mai multe astfel de concursuri poarta numele lui Grigore Moisil; alte concursuri sunt **Info-Oltenia**, **LInfo@SV**, **Urmasii lui Moisil**, etc.\r\n* Stelele Informaticii - concurs cu organizare asemanatoare cu Olimpiada Nationala de Informatica; participarea la acesta se face doar pe baza de invitatie.\r\n\r\nDe obicei aceste manifestari sunt mai ample; la aceste concursuri exista si alte sectiuni, cum ar fi cele dedicate dezvoltarii de aplicatii software sau de pagini web.\r\n\r\nExista de asemenea numeroase concursuri on-line, la care concurentii participa de acasa si isi trimit solutiile prin intermediul internetului. Desigur, nu se pot acoperi integral toate concursurile disponibile pe internet in acest articol. Este foarte importanta citirea regulamentului inainte de rezolvarea problemelor, deoarece pot exista restrictii care difera de la caz la caz. Datorita faptului ca majoritatea acestor concursuri sunt internationale, cunoasterea limbii engleze devine o necesitate pentru a putea participa. Pentru o pregatire cat mai eficienta, se recomanda participarea la acest tip de concursuri, atat pentru valoarea premiilor puse in joc, cat si ca modalitate de antrenament.\r\n\r\n* \"**preONI**\":http://infoarena.ro - Un concurs organizat in scopul pregatirii pentru Olimpiada Nationala de Informatica, organizat de catre studenti si elevi, actuali si fosti olimpici nationali si internationali. In ultimii 3 ani acest concurs a fost organizat de \"echipa infoarena\":http://infoarena.ro/echipa-infoarena, un grup de olimpici care administreaza primul (si singurul la momentul acesta) site din Romania cu evaluator disponibil 24 din 24. Acest concurs este intr-o continua expansiune, devenind din ce in ce mai complex de la an la an. Pe langa preONI, echipa infoarena organizeaza si alte concursuri; calitatea si valoarea concursurilor organizate precum si a materialelor educationale ce sunt puse la dispozitie este recunoscuta atat de elevi cat si de profesori de renume in informatica.\r\n* \"**.campion**\":http://campion.edu.ro - Problemele de pe acest site sunt propuse de membri ai Comisiei Olimpiadei Nationale; concursul este structurat in runde de pregatire care dureaza in mod normal 10 zile, si in runde de concurs, care dureaza doar 3 ore; tipul rundei alterneaza. Primii clasati se intalnesc la \"marea finala\", care se desfasoara sub forma unei probe de concurs, similara cu olimpiadele - castigatorii primesc premii.\r\n* \"**Bursele Agora**\":http://www.ginfo.ro - Printre cele mai vechi concursuri care inca se desfasoara, este organizat de redactia GInfo; formatul acestuia difera de la an la an, in ultimii doi ani fiind structurat in 50 de runde normale + o runda finala. La acest concurs se acorda burse pentru primii doi clasati in valoare de 50$ si 30$\r\n* \"**USACO**\":http://www.usaco.org - Un concurs prin intermediul caruia se selecteaza lotul national largit al SUA. Concursul consta in mai multe faze, desfasurate pe parcursul anului. Prin bunavointa organizatorilor, concursul a devenit international, iar ultimele editii au adus ca noutate traducerea problemelor in mai multe limbi, printre care, uneori, si limba romana.\r\n* **site-uri ACM** - exista site-uri care va pun la dispozitie si cate o arhiva foarte bogata de probleme si pot fi folosite cu succes in pregatirea pentru olimpiade, si care organizeaza concursuri, mai ales in perioada dinaintea concursurilor regionale ACM: astfel de site-uri sunt: http://acm.uva.es, http://acm.timus.ru, http://acm.sgu.ru, http://spoj.sphere.pl, http://acm.pku.edu.cn, http://acm.zju.edu.cn. Pentru o lista mai mare de site-uri de pregatire accesati sectiunea \"Links\":http://infoarena.ro/links, o lista permanent actualizata.\r\n* \"**Internet Problem Solving Contest**\":http://ipsc.ksp.sk - concurs organizat o data pe an. In cadrul acestui concurs se pun la dispozitie enunturile problemelor si fisierele de intrare si se asteapta fisierele de iesire corespunzatoare, fara a se cere si programele care rezolva problemele.\r\n\r\nAlte concursuri de programare, dar pe echipe, sunt **Bits\'n\'Bytes**, **BitWise** si **International Online Programming Contest**; la acestea pot participa si studenti. In anii precedenti au mai fost organizate si alte concursuri la noi in tara asemanatoare cu cele precizate mai sus precum **Lista lui Francu**, **Cupa Compaq**, **Cupa Fujitsu-Siemens**, **OlimpiadaOnline**, **Algoritmus**.\r\n\r\nh3. Concursuri pentru studenti\r\n\r\n* \"**ACM**\":http://www.acm.ro - un concurs organizat pentru studenti, de natura algoritmica. Diferentele majore fata de concursurile de liceu sunt reprezentate de faptul ca un program trebuie sa rezolve toate seturile de date de intrare prezentate pentru a se acorda puncte (nu se mai acorda punctaje partiale) si viteza cu care se rezolva problemele conteaza, iar evaluarea programelor este imediata. Concursul este pe echipe de cate 3 persoane, toate la un singur calculator. Concursul are loc pe regiuni initial (Centrul Europei, Sudul Europei, etc.) iar echipele calificate se intalnesc la marea finala.\r\n* \"**TopCoder**\":http://www.topcoder.com - un site care organizeaza concursuri saptamanal, cat si turnee. Formatul este diferit fata de orice concurs intalnit pana acum, si anume fiecare concurent are de rezolvat 3 probleme in 75 de minute: o problema usoara de 250 puncte, una medie de 500 puncte si una grea de 1000 puncte. Punctajul efectiv pentru o problema se da in functie de viteza cu care aceasta este rezolvata. De asemenea, exista si o etapa de \"challenge\", in care concurentii pot vedea sursele celorlalti si, in caz ca determina un bug intr-o sursa, pot sa ruleze sursa respectiva, iar daca da raspuns gresit concurentul primeste 50 de puncte, altfel este penalizat cu 25 de puncte. Aceste concursuri sunt diferite fata de cele din liceu in care accentul este pe realizarea unui algoritm eficient, deoarece aici se pune accentul mai mult pe o implementare rapida si corecta a unor probleme care folosesc variatii ale unor algoritmi destul de cunoscuti, dar fiind necesara tratarea diferitelor cazuri speciale ce pot aparea. Ca avantaje, premiile la turnee sunt foarte mari (20.000$ pentru primul clasat), iar intregul sistem de punctare este mult mai complex si mai eficient. Google organizeaza impreuna cu TopCoder concursul \"**Google Code Jam**\":http://www.google.com/codejam.\r\n\r\nh2. 3. Inainte de concurs\r\n\r\nDin fericire pentru unii si din nefericire pentru altii, majoritatea examenelor iti cer sa dovedesti nu ca esti bine pregatit, ci ca esti mai bine pregatit decat altii. Aceasta inseamna ca si la olimpiada de informatica se aplica legea concurentei. Valoarea absoluta a fiecaruia nu conteaza chiar in totalitate, ceea ce constituie sarea si piperul concursului. Intr-adevar, ce farmec ar avea sa mergi la un concurs la care sa se stie inca dinainte cine este cel mai bun? Este destul de amuzant sa observi cum fiecare spera sa prinda \"o zi buna\", iar adversarii sai \"o zi proasta\". Expresia \"de la extaz la agonie\" se potriveste foarte bine uneori cu ceea ce se poate intampla la concursurile de informatica.\r\n\r\nExperienta demonstreaza ca, oricat de mare ar fi bagajul de cunostinte acumulat de un elev, mai e nevoie de ceva pentru a-i asigura succesul la olimpiada de informatica. Aceasta deoarece in timp de concurs lucrurile stau cu totul altfel decat in fata calculatorului de acasa sau de la scoala. Reusita depinde, desigur, in cea mai mare masura de puterea fiecaruia de a pune in practica ceea ce a invatat acasa. Numai ca in acest proces intervin o serie de factori care tin de temperament, de experienta individuala, de numarul de ore dormite in noaptea dinaintea concursului (care in taberele nationale este ingrijorator de mic) si asa mai departe. Trebuie spus ca un concurs de informatica presupune mai mult decat un simplu act de prezenta la locul desfasurarii ostilitatilor. Este chiar trist de remarcat cum spiritul competitiv capata de multe ori tente malitioase.\r\n\r\nPrimul si cel mai de seama lucru pe care trebuie sa il stiti este ca e important si sa participi, dar e si mai important sa participi onorabil, sa dai dovada de fair-play, iar daca se poate, sa si castigi! :) Nu trebuie sa porniti la drum cu ingamfare; modestia e buna, dar nu trebuie in nici un caz sa duca la neincredere in sine! Fiecare trebuie sa stie clar de ce e in stare si, mai presus de toate, sa se gandeasca ca la urma urmei nu dificultatea concursului conteaza, caci concursul, greu sau usor, este acelasi pentru toti. Mult mai importanta este valoarea individuala si nu in ultimul rand pregatirea psihologica. Fiecare concurs reprezinta de asemenea un prilej de perfectionare: fiecare concurent trebuie sa-si analizeze comportamentul din timpul concursului, si sa determine ce aspecte pot fi imbunatatite pentru a obtine performante mai bune la urmatoarele concursuri. Pregatirea psihologica este de multe ori neglijata si reprezinta pentru unii exact acel lucru care il impiedica sa obtina performantele dorite. Exista destui concurenti care uita faptul ca aceste concursuri sunt doar niste concursuri, si ajung sa creada ca cel mai important lucru din viata lor este performanta lor la concursuri - fapt care poate fi foarte daunator in cazul unor esecuri. Asadar, recomand tuturor concurentilor sa adopte o atitudine relaxata si optimista la concursuri, sa realizeze ca acestea reprezinta doar o mica parte din viata, si nu in ultimul rand sa se distreze!\r\n\r\nO pregatire intensa inaintea unui concurs este foarte importanta deoarece imbunatateste viteza de implementare si reduce riscul aparitie erorilor, dar nu poate rezolva anumite lacune teoretice. Formula pentru succes poate fi descrisa ca \"90% munca, 10% talent\". Pentru a obtine performante mari trebuie neaparat o pregatire intensa adecvata. Exista mai multe aspecte ale pregatirii:\r\n\r\n* Pregatirea teoretica\r\n* Pregatirea psihica\r\n* Organizarea globala a pregatirii\r\n* Simularea unor probe de concurs\r\n* Discutiile cu alti elevi si profesori referitor la anumite probleme\r\n* Pregatirea de la locul desfasurarii probei\r\n\r\nDesigur, un alt aspect care trebuie luat in considerare este supra-antrenamentul! Da, acest concept exista si in concursurile de informatica. Se intampla de obicei ca dupa un antrenament prea greu, mintea sa nu reactioneze la fel de bine ca inainte, fiindca este obosita. De aceea, se si recomanda minim o saptamana de pauza si relaxare totala inainte de orice concurs major.\r\n\r\nh3. Pregatirea teoretica\r\n\r\nMajoritatea problemelor propuse spre rezolvare la concursuri depasesc cu mult nivelul manualelor de informatica. De exemplu, desi se propun o multime de probleme a caror rezolvare implica detinerea de cunostinte din domeniul teoriei grafurilor, nu toti algoritmii necesari sunt cuprinsi in programa de invatamant. Pentru a rezolva lacunele teoretice, este necesara studierea unor carti care sa acopere un spatiu teoretic cat mai vast.\r\n\r\nUnele carti isi propun sa initieze cititorul in tainele diverselor limbaje de programare, altele pun accentul mai cu seama pe tehnicile de programare si structurile de date folosite in rezolvarea problemelor. In general, cele din prima categorie contin exemple cu caracter didactic si exercitii cu un grad nu foarte ridicat de dificultate, iar celelalte demonstreaza matematic fiecare algoritm prezentat, insa neglijeaza partea de implementare, considerand scrierea codului drept un ultim pas lipsit de orice dificultate. Desigur, fiecare din aceste carti isi are rostul ei in formarea unui elev bine pregatit in domeniul informaticii. Totusi, trebuie considerata observatia ca scrierea unui program impune atat conceperea algoritmului si demonstrarea corectitudinii, cat si implementarea lui, ambele etape fiind complexe si nu lipsite de obstacole.\r\n\r\nCateva dintre cartile care ar trebui parcurse sunt in special cele scrise de fosti olimpici; prin intermediul acestora, autorii va impartasesc o parte din experienta acumulata. Cele mai folositoare carti (unele nu se mai gasesc) pentru pregatire sunt (unele nu sunt disponibile in Romania):\r\n\r\n* **Introducere in Algoritmi (Cormen, Leiserson, Rivest)** - \"Biblia\" algoritmilor; mai este numita si CLR. Traducerea in limba romana a primei editii a acestei carti este disponibila la editura Agora Computer Libris si acum oricine este interesat o poate achizitiona. Contine o descriere amanuntita a tuturor algoritmilor de baza care pot fi folositi in rezolvarea problemelor de concurs.\r\n* **Arta Programarii Calculatoarelor Vol. 1-3 (Donald Knuth)** - Donald E. Knuth este celebru datorita muncii sale de pionierat in domeniul algoritmilor si al tehnicilor de programare; \"Daca te crezi un bun programator... citeste Arta Programarii Calculatoarelor de Knuth... Daca poti citi toata cartea, trimite-mi neaparat un C.V.\" - Bill Gates. Cartile se pot gasi la noi in tara la editura Teora\r\n* **Proiectarea si implementarea algoritmilor (Mihai Oltean)** - aparuta la editura Computer Libris Agora din Cluj-Napoca; este o resursa foarte buna pentru programare dinamica\r\n* **Culegere de probleme si programe PASCAL (Mihai Stroe, Cristian Cadar)** - aparuta la editura Petrion din Bucuresti, contine un capitol introductiv bun despre geometrie, cat si diverse solutii interesante la probleme din concursuri\r\n* **Psihologia concursurilor de informatica (Catalin Francu)** - aparuta la editura L&S din Bucuresti; de asemenea contine solutii interesante la anumite probleme\r\n* **Informatica - culegere de probleme pentru liceu (Emanuela Cerchez)** - aparuta la editura Polirom, contine diverse aplicatii pentru metodele principale de programare\r\n* **Probleme de informatica date la concursurile internationale (Radu Berinde, Dan Ghinea, Horia Andrei Ciochina, Cornel Margine)** - aparuta la editura Fundatiei Pro, contine rezolvari pentru problemele de la principalele concursuri internationale din ultimii ani\r\n* **Fundamentele programarii - Culegere de probleme pentru clasa a IX-a / clasa a X-a (Dana Lica, Mircea Pasoi)** - aparute la editura L&S din Bucuresti, ambele contin un capitol mare de probleme propuse pe la concursuri impreuna cu solutii\r\n* **Arbori (Emanuela Cerchez)** - aparuta la editura Tara Fagilor, trateaza in detaliu arborii\r\n* **Probleme de combinatorica si teoria grafurilor (Ioan Tomescu)** - desi este o carte in principal de matematica multe probleme de acolo au aparut la concursurile romanesti\r\n* **Provocarea algoritmilor (Victor Mitrana)** - aparuta la editura Agni, Bucuresti\r\n* **Computational Geometry: An Introduction (Shamos, Preparata)** - o carte de baza pentru geometria computationala\r\n* **Computational Geometry in C (Joseph O\'Rourke)** - alta carte de baza pentru geometria computationala\r\n* **Algorithms (Robert Sedgewick)** - contine informatii despre algoritmii clasici si despre structurile de date cele mai folosite\r\n* **The Algorithm Design Manual (Steven Skiena)** - o carte de referinta, continand implementari ale unui numar mare de algoritmi\r\n* **Programming Challenges: The Programming Contest Training Manual (Steven Skiena, Miguel Revilla)** - o carte folositoare mai ales pentru concursurile ACM\r\n\r\nIn afara de cartile mentionate, internetul se dovedeste din nou o resursa foarte importanta. O cautare pe internet poate localiza informatii interesante: descrierea unor anumiti algoritmi impreuna cu performantele lor, tratari ale unor probleme clasice prin mai multe metode etc. Desigur pe langa carti este recomandat sa se si lucreze cat mai multe probleme de la editiile anterioare ale concursurilor principale si de pe site-urile cu evaluator disponibil 24 din 24. Astfel de site-uri sunt:\r\n\r\n* \"infoarena\":http://infoarena.ro\r\n* http://acm.timus.ru\r\n* http://acm.sgu.ru\r\n* http://spoj.sphere.pl\r\n* http://acm.pku.edu.cn\r\n* http://acm.zju.edu.cn\r\n* http://ace.delos.com/usacogate\r\n* http://www.oi.edu.pl/php/show.php?ac=e100000 (Site cu problemele polonezilor - o resursa foarte buna de pregatire, desi nu detine evaluator online)\r\n\r\nh3. Pregatirea psihica\r\n\r\nDupa cum s-a mai zis, este cunoscut faptul ca o atitudine mentala pozitiva este cheia succesului in cele mai multe situatii. Din nefericire, unii concurenti incep proba cu un moral nu tocmai ridicat. Iata cateva din falsele probleme cu care se confrunta anumiti concurenti:\r\n\r\n* _Participa si X, care e mai bun ca mine, deci nu am nici o sansa sa castig!_\r\nFals! Nu s-a demonstrat ca X este mai bun, cel mult a obtinut rezultate mai bune pana acum si poate avea sanse mai mari. Problemele din concursul curent sunt aceleasi pentru toti, conditiile de desfasurare sunt aceleasi si antecedentele nu conteaza. Totul se reia de la zero. In plus, participarea la un concurs puternic poate aduce mai multa experienta pentru viitor. Pentru a ajunge la valoarea necesara castigarii unor concursuri, trebuie sa participati la cat mai multe si sa le tratati cu seriozitate.\r\n* _Am obtinut prea putine puncte in prima zi, nu mai am nici o sansa la premii!_\r\nProblemele de la concursurile cu mai multe probe sunt, in general, destul de dificile. De multe ori, la Olimpiada Nationala sau la concursurile internationale, obtinerea a jumatate din punctele puse in joc inseamna castigarea unui premiu. Daca in prima zi rezultatele obtinute sunt nesatisfacatoare, un rezultat foarte bun in ziua a doua poate aduce premiul dorit. In ultimii ani pentru intrarea in lotul national largit, la barajele de selectie, a fost suficienta obtinerea a mai putin de 200 puncte, dintre cele 600 posibile.\r\n* _Nu sunt suficient de bine pregatit!_\r\nAceasta apreciere este, uneori, mai realista. Totusi, trebuie sa stiti ca o foarte mare importanta o are inspiratia de moment sau norocul (poate problemele vor fi similare cu unele rezolvate anterior). Evident, optimismul exagerat poate, la randul sau, sa fie daunator. Cel mai bine ar fi sa adoptati atitudinea cea mai potrivita pentru propria personalitate. Veti observa, in timp, care este aceasta.\r\n* _Problema asta e grea si n-am s-o pot rezolva perfect, asa ca nu ma mai apuc deloc de ea!_\r\nEste usor sa fii printre cei mai buni atunci cand concursul este usor. Mai greu e sa fii cel mai bun atunci cand concursul este dur, pentru ca atunci intervine - inevitabil - dramul de noroc al fiecaruia. Niciodata insa nu se poate invoca greutatea concursului drept o scuza pentru un eventual esec. Concursul este la fel de greu pentru toti. Se poate intampla, mai ales daca probele dureaza mai multe zile (2-3) ca nici unul din concurenti sa nu acumuleze mai mult de 50-60% din punctajul maxim. Totusi, aceasta nu inseamna ca ei nu sunt bine pregatiti; mai mult, unul dintre ei trebuie sa fie primul. Asadar, niciodata nu trebuie adoptata o strategie de genul acesta. Nu trebuie sa va impacientati daca vi se intampla sa nu aveti o idee geniala de rezolvare a unei probleme. Nu va cere nimeni sa faceti perfect o problema, ci numai sa prezentati o solutie care sa acumuleze cat mai multe puncte. Evident, prima varianta este intotdeauna preferabila, dar nu obligatorie. De multe ori se intampla ca un elev sa gaseasca o solutie cat de cat buna la o problema si, macar ca stie ca nu va lua punctajul maxim, ci doar o parte, sa renunte sa caute o solutie mai eficienta, deoarece timpul pierdut astfel ar aduce un castig prea mic si ar putea fi folosit la rezolvarea altor probleme. Desigur, daca nu faci toate problemele perfect, nu mai poti fi sigur de locul I, pentru ca altcineva poate sa te intreaca. Dar pe de alta parte, locul pe care te clasezi conteaza numai la etapa nationala a olimpiadei sau la concursurile internationale. In rest, important e numai sa te califici, adica sa intri in primele cateva locuri.\r\n\r\nPregatirea psihica nu are legatura numai cu concursul propriu-zis. O atitudine mentala pozitiva, de invingator, este utila pe tot timpul pregatirii pentru concursuri.\r\n\r\nh3. Organizarea globala a pregatirii\r\n\r\nAcest aspect poate contribui la obtinerea unor rezultate excelente. O parte foarte importanta a unei pregatiri sistematice consta in elaborarea unei liste cu metodele si tehnicile cunoscute si necunoscute, punctele slabe, etc. Lista trebuie sa contina algoritmii care apar in mod frecvent in cadrul problemelor de concurs, problemele care apar la implementare, la organizarea timpului in concurs, etc. Continului listei se modifica in timp; o parte din algoritmii necunoscuti sunt invatati si devin cunoscuti, se descopera noi puncte slabe, se evidentiaza existenta unor algoritmi necunoscuti care trebuie invatati, etc. Aceasta este o modalitate excelenta de a masura progresul si de a gasi noi directii de urmat in pregatire.\r\n\r\nh3. Simularea unor probe de concurs\r\n\r\nCea mai potrivita modalitate de pregatire pentru a face fata unei situatii este simularea ei, adica tratarea unei situatii asemanatoare. Acest principiu este valabil in orice tip de competitie, aplicandu-se si in domeniul concursurilor de programare. Daca va pregatiti pentru un concurs, citirea unor carti nu este suficienta! Trebuie sa va analizati comportamentul in situatii similare. Situatia cea mai asemanatoare unui anumit concurs este un alt concurs de acelasi tip. Participarea la N concursuri creste sansele obtinerii unui rezultat mai bun la al N+1-lea.\r\n\r\nConcursurile de pe internet sunt destul de dese si sunt organizate foarte bine. Din nefericire, nivelul de dificultate al acestor concursuri nu este intotdeauna cel dorit de cel care se pregateste. O posibilitate de simulare a unui concurs este rezolvarea problemelor de la o editie precedenta! De exemplu, cineva care se pregateste pentru Olimpiada Nationala ar trebui sa rezolve problemele date la Olimpiada Nationala din anul anterior la clasa respectiva (exista si cazuri in care simulari de acest tip nu sunt foarte concludente; de exemplu, intre 2000 si 2001 programa scolara a suferit cateva variatii, care s-au reflectat in tipul problemelor de la clasa a X-a). Pentru ca simularea sa reflecte cat mai bine realitatea, problemele se rezolva in timpul stabilit, fara pauze, la prima citire (sau, daca au fost citite anterior, nu se recitesc in zilele premergatoare simularii). Experienta obtinuta este apropiata de cea a concursului propriu-zis, dar lipseste stresul care apare, inevitabil, in timpul competitiei. Este important ca, dupa fiecare simulare sau concurs real, sa va analizati comportarea si sa invatati din eventualele greseli de abordare (de exemplu, puteti ajunge la concluzii de genul _Aceasta problema trebuia abordata prima_ sau _Nu am citit integral enuntul si am rezolvat o alta problema_). Concluziile analizei duc la detectarea actiunilor necesare pentru a imbunatati situatia.\r\n\r\nIn plus, se recomanda notarea celor mai frecvente greseli de implementare si examinarea periodica a listei (inclusiv in timpul depanarii programelor, in cadrul simularii concursurilor); in acest fel, greselile respective vor disparea in timp.\r\n\r\nh3. Discutiile cu alti elevi si profesori\r\n\r\nPuteti invata foarte mult de la profesori, si in special de la elevi mai experimentati! Exista foarte multe exemple de elevi pentru care a contat foarte mult pregatirea individuala, dar exista unii care au fost ajutati de pregatirea organizata, in grupuri de elevi, sub indrumarea unor profesori cu preocupari de acest gen. In cadrul pregatirilor de acest tip se discuta algoritmi, se propun probleme spre rezolvare, se discuta diversele modalitati de rezolvare, se obtin mai multe informatii despre concursuri, etc. In plus, elevii aduc in discutie diverse probleme cu care s-au intalnit in cadrul pregatirii individuale. Daca doriti sa participati la astfel de pregatiri, trebuie sa luati legatura cu alti elevi interesati de concursuri, sau cu profesori care se ocupa de pregatirea elevilor pentru olimpiade. In prezent se organizeaza pregatiri la nivel de liceu, oras, judet, etc. in anumite zone. Astfel de pregatiri cresc valoarea tuturor participantilor, deci sunt foarte importante. Pregatirile organizate au luat amploare odata cu infiintarea centrelor de excelenta. Pentru a intra in contact cu alti elevi interesati puteti folosi \"forumul infoarena\":http://infoarena.ro/forum si \"forumul revistei GInfo\":http://ba.toptalent.ro/forum.\r\n\r\nh3. Pregatirea de la locul desfasurarii probei\r\n\r\nDesi ar putea parea bizar, acest aspect este foarte important, dar este neglijat de multe ori de catre concurenti. Aceasta pregatire consta in:\r\n\r\n* somn odihnitor in noaptea care precede ziua concursului **(foarte important!)**\r\n* obtinerea atitudinii mentale dorite\r\n* prezentarea la timp in sala, cu toate obiectele necesare\r\n\r\nExista cateva obiecte pe care ar trebui sa le aveti la voi. In timpul concursului trebuie tinuta o evidenta drastica a timpului scurs si a celui ramas. E drept ca in general supraveghetorii anunta din cand in cand timpul care a trecut, dar e bine sa nu va bazati pe nimeni si nimic altceva decat pe voi insiva. Unii pot spune _Ei, ce nevoie am de ceas, oricum am ceasul calculatorului la indemana_. Asa e, dar e incomod sa te opresti mereu la jumatatea unei idei si sa verifici cat e ceasul schimband consola sau minimizand fereastra de lucru. In ceea ce priveste hartia de scris, ea este in mod sigur necesara. De fapt, o parte importanta a rezolvarii unei probleme este proiectarea matematica a algoritmului, lucru care nu se poate face decat cu creionul pe hartie. Pe langa aceasta, majoritatea problemelor opereaza cu vectori, matrice, arbori, grafuri, etc., iar exemplele pe care este testat programul realizat trebuie neaparat verificate \"de mana\". Este recomandat sa aveti mereu si hartie de matematica; este foarte folositoare pentru problemele de geometrie analitica, precum si pentru reprezentarea matricelor. Nu in ultimul rand, ar fi bine sa aveti o sticla de suc si o ciocolata; din nefericire, concursul incepe deseori cu intarziere si este bine ca foamea sau setea sa nu va preocupe in timpul rezolvarii problemelor.\r\n\r\nh2. 4. In timpul concursului\r\n\r\nImediat ce primiti problemele, cititi toate enunturile si faceti-va o idee aproximativa despre gradul de dificultate al fiecarei probleme. Neaparat verificati daca se dau limite pentru datele de intrare (numarul maxim de elemente ale unui vector si valoarea maxima a acestora, numarul maxim de noduri dintr-un graf, etc.) si pentru timpii de executie pentru fiecare test. Dimensiunea input-ului poate schimba radical dificultatea problemei. Spre exemplu, pentru un vector cu N &le; 200 elemente, un algoritm O(N^3^) merge rezonabil, pe cand pentru N &le; 2000 acelasi algoritm ar depasi cu mult cele cateva sutimi de secunda care se acorda de obicei. In primele zece minute (sau mai mult) nu se atinge calculatorul. Intotdeauna, cand cititi o problema, este indicat sa intoarceti foaia pentru a vedea daca enuntul continua si pe verso. De obicei, in primele 30 sau 60 de minute ale concursului pot fi adresate intrebari comisiei, pentru a clarifica eventualele ambiguitati din enunturi. Acestea sunt redactate in scris, foile sunt preluate de supraveghetorul din sala si trimise la comisie. Raspunsul s-ar putea sa intarzie, deci este indicat sa nu irositi timpul asteptand raspunsul fara a mai face nimic altceva. Puteti fie sa va ganditi la rezolvarea unei probleme, fie sa incepeti sa implementati (daca exista ceva usor de implementat, cum ar fi o problema simpla sau o rutina pentru citirea datelor de intrare). In majoritatea situatiilor, intrebarile trebuie formulate in asa fel incat raspunsul sa fie _Da_ sau _Nu_. Daca intrebarea nu este astfel exprimata sau daca raspunsul se gaseste in textul problemei, veti primi raspunsul _Fara comentarii_, caz in care va trebui mai intai sa studiati corectitudinea intrebarii si, daca aceasta este corect formulata, sa recititi enuntul problemei. Concurentii trebuie sa profite cat mai mult de aceasta perioada, pentru a clarifica eventualele nelamuriri. Un lucru important este ca nu trebuie sa acceptati raspunsuri daca acestea nu sunt insotite de semnatura unui membru al comisiei.\r\n\r\nFaceti o impartire a timpului pentru problemele ramase proportional cu dificultatea aparenta a fiecarei probleme. In general problemele au punctaje egale. Incercati sa nu depasiti niciodata limitele de timp pe care le-ati fixat. Daca in schimb reusiti sa economisiti timp fata de cat v-ati propus, cu atat mai bine, veti face o realocare a timpului si veti avea mai mult pentru celelalte probleme. Apucati-va de problema **cea mai simpla**. Mai bine sa duceti la bun sfarsit o problema usoara, decat sa va apucati de o problema grea si sa nu terminati nici una. Daca toate problemele par grele, alegeti-o pe cea din domeniul care va este cel mai familiar, in care ati lucrat cel mai mult. Daca va este indiferent si acest lucru, alegeti o problema unde simtiti ca aveti o idee simpla de rezolvare.\r\n\r\nIncepeti sa va ganditi la algoritmi cat mai buni, estimand in acelasi timp si cat v-ar lua ca sa-i implementati. Faceti, pentru fiecare idee care va vine, calculul complexitatii. Nu trebuie neaparat sa gasiti cel mai eficient algoritm, ci numai unul suficient de bun. In general, trebuie ca, dintre toti algoritmii care se incadreaza in timpul de rulare, sa-l alegeti pe cel care este cel mai usor de implementat. Daca algoritmul gasit este greu de implementat, mai cautati altul o vreme. Trebuie insa ca timpul petrecut pentru gasirea unui nou algoritm plus timpul necesar pentru scrierea programului sa nu depaseasca timpul necesar pentru implementarea primului algoritm, altfel nu castigati nimic. Deci nu exagerati cu cautarile si nu incercati sa reduceti dincolo de limita imposibilului complexitatea algoritmului. Mai ales, nu uitati ca programul nu poate avea o complexitate mai mica decat dimensiunea input-ului sau a output-ului. De exemplu, daca programul citeste sau scrie matrice de dimensiune N*N, nu are sens sa va bateti capul ca sa gasiti un algoritm mai bun decat O(N^2^). Dintre toate ideile de implementare gasite (care se incadreaza fara probleme in timp), o veti alege pe cea mai scurta ca lungime de cod.\r\n\r\nIn general, pentru orice problema exista cel putin o solutie, fie si una slaba. Sunt numeroase cazurile cand nu va vine alta idee de rezolvare decat cea slaba. De regula, cand nu aveti in minte decat o rezolvare neeficienta a problemei, care stiti ca nu o sa treaca toate testele (un backtracking, sau un O(N^5^), O(N^6^), etc.) e bine sa incercati urmatorul lucru:\r\n\r\n* Calculati cam cat timp v-ar trebui ca sa implementati rezolvarea slaba. In acest calcul trebuie sa includeti si un timp estimativ de depanare a programului (care variaza de la persoana la persoana) si pe cel de testare. Daca sunteti foarte siguri pe voi, puteti sa neglijati timpul de testare, dar orice program trebuie testat cel putin pe exemplul de pe foaie.\r\n* Pentru a avea sanse mai mari sa gasiti o alta solutie, este indicat sa incercati sa ignorati complet solutia slaba, sa nu o luati ca punct de plecare. Incercati sa va \"goliti\" mintea si sa gasiti ceva nou, altfel va veti invarti mereu in cerc.\r\n* Daca va vine vreo idee mai buna, ati scapat de griji si va apucati de implementare (daca aveti timpul necesar).\r\n\r\nDin acest moment, pentru varianta aleasa veti scrie programul, fara a va mai gandi la altceva, chiar daca pe parcurs va vin alte idei. Iata unele lucruri pe care e bine sa le stiti despre scrierea unui program:\r\n\r\n* Datele de intrare se presupun a fi corecte. Aceasta este o regula nescrisa (uneori) a concursului de informatica.\r\n* Efectul optiunilor de compilare asupra vitezei este semnificativ.\r\n* Daca se poate, evitati lucrul cu pointeri. Programele care ii folosesc sunt mai greu de depanat si se pot bloca mult mai usor.\r\n* Evitati lucrul cu numere reale (comparatii, impartiri, etc.), daca puteti. Operatiile in virgula mobila sunt mult mai lente.\r\n* Alegeti-va numele de variabile in asa fel incat programul sa fie clar. Sunt permise mai mult de doua litere! Numele fiecarei proceduri, functii, variabile trebuie sa-i explice clar utilitatea. E drept, lungimea programului creste, dar codul devine mult mai limpede si timpul de depanare scade foarte mult. Ca o regula generala, claritatea programelor face mult mai usoara intelegerea lor chiar si dupa o perioada mai indelungata de timp (luni, ani). Nu trebuie nici sa cadeti in cealalta extrema. De exemplu, nu depasiti 10 caractere pentru un nume de variabila.\r\n* Salvati programul cat mai des. Daca va obisnuiti, chiar la fiecare 2-3 linii. Dupa ce o sa va intre in reflex n-o sa va mai incomodeze  cu nimic acest obicei. Au fost cazuri in care o pana de curent prindea pe picior gresit multi concurenti, iar dupa aceea nu mai este absolut nimic de facut, pentru ca nimeni nu va va crede pe cuvant ca ati facut programul si ca el mergea.\r\n* Obisnuiti-va sa programati modular. Faceti proceduri separate pentru citirea si initializarea datelor, pentru sortare, pentru afisarea rezultatelor, etc. In general nu se recomanda sa scrieti proceduri in alte proceduri (adica e bine ca toate procedurile sa apartina direct de programul principal). Procedurile, acolo unde e posibil, nu trebuie sa depaseasca un ecran, pentru a putea avea o viziune de ansamblu asupra fiecareia in parte. Acest lucru ajuta mult la depanare.\r\n* Rulati programul cat mai des, daca timpul va permite. In primul rand dupa ce scrieti procedura de citire a datelor. Daca e nevoie de sortarea datelor de intrare, nu strica sa va convingeti ca programul sorteaza bine, ruland 2-3 teste oarecare. E pacat sa pierdeti puncte dintr-o greseala copilareasca.\r\n* O situatie mai delicata apare cand fisierul de intrare contine mai multe seturi de date (teste). In acest caz, atentia trebuie sporita, deoarece daca la primul sau al doilea test programul vostru da eroare si se opreste din executie, veti pierde automat si toate celelalte teste care urmeaza. Daca in fisierul de intrare exista un singur set de date, atunci pierderea din vedere a unui caz particular al problemei nu putea duce, in cel mai rau caz, decat la picarea unui test. Asa insa, picarea unui test poate atrage dupa sine picarea tuturor celor care il urmeaza. Pe langa corectitudinea strict necesara, programul trebuie sa se incadreze si in timp pentru orice fel de test. Daca la primul sau al doilea test din suita programul depaseste timpul (sau, si mai rau, se blocheaza), e foarte probabil sa fie oprit din executie de catre comisie, deci din nou veti pierde toate testele care au ramas neexecutate.\r\n* Tot in situatia in care exista mai multe seturi de date in fisierul de intrare, daca iesirea se face intr-un fisier, este bine ca dupa afisarea rezultatului pentru fiecare test sa actualizati fisierul de iesire. In felul acesta, chiar daca la unul din teste programul se blocheaza sau da eroare, rezultatele deja scrise raman scrise. Altfel, e posibil ca rezultatele de la testele anterioare sa ramana intr-un buffer in memorie, fara a fi \"varsate\" pe disc.\r\n\r\nTot la partea de implementare, este bine ca codul sa fie cat mai scurt si cat mai optimizat - dar, despre scrierea unui cod cat mai eficient se poate face un articol cam la fel de mare cat acesta, deci nu se va trata acest subiect aici - metoda cea mai buna in acest sens este sa invatati din sursele altora. Puteti incepe cu articolele \"_12 ponturi pentru programatorii C/C++_\":http://infoarena.ro/12-ponturi-pentru-programatorii-CC si \"_Multe smenuri de programare in C/C++... si nu numai!_\":http://infoarena.ro/Multe-smenuri-de-programare-in-CC-si-nu-numai si sectiunea \"Links\":http://infoarena.ro/links.\r\n\r\nMai ramane doar partea de depanare. O metoda buna de depanare este urmatoarea:\r\n\r\n* Incepeti cu un test nici prea simplu, nici prea complicat (si usor de urmarit cu creionul pe hartie) si executati-l de la cap la coada. Daca merge perfect, treceti la teste mai complexe (se recomanda **minim** 4 test si maxim 7-8). Daca le trece si pe acestea, puteti zambi. Totusi, daca programul vostru a mers perfect pe 7-8 teste date la intamplare, exista sanse (dar nu extrem de mari!) sa mearga pe majoritatea testelor comisiei, sau chiar pe toate.\r\n* Exemplul dat in enunt nu are in general nici o semnificatie deosebita (de fapt, are mai curand darul de a semana confuzie printre concurenti), iar daca programul merge pe acest test particular, nu inseamna ca o sa mearga si pe alte teste.\r\n* Daca la unul din teste programul nu merge corespunzator, rulati din nou testul , dar de data aceasta procedura cu procedura. Dupa fiecare procedura evaluati variabilele si vedeti daca au valorile asteptate. In felul acesta puteti localiza cu precizie procedura, apoi linia unde se afla eroarea. Corectati in aceasta maniera toate erorile, pana cand testul este trecut.\r\n* In acest moment, luati de la capat toate testele pe care programul le-a trecut deja. In urma depanarii, s-ar putea ca alte greseli sa iasa la suprafata si programul sa nu mai mearga pe vechile teste.\r\n* Repetati procedeul de mai sus pana cand toate testele merg. Daca va obisnuiti sa programati modular si ingrijit, depanarea si testarea n-ar trebui sa dureze mai mult de 5-25 minute. Din acest moment, nu mai modificati nici macar o litera in program, sau daca o faceti pastrati-va in prealabil o copie. Nu va bazati pe faptul ca puteti sa tineti minte modificarile facute si sa refaceti oricand forma initiala a programului in caz ca noua versiune nu va fi buna.\r\n* Daca totusi nu-i puteti \"da de cap\" programului, iar timpul alocat problemei respective expira, aduceti programul la o forma in care sa mearga macar pe o parte din teste si treceti la problema urmatoare.\r\n\r\nFeriti-va ca de foc de criza de timp. E mare pacat sa ratezi o problema intreaga pentru ca n-ai avut timp sa scrii procedura de afisare a solutiei, sau lucruri asemanatoare. Rezervati-va intotdeauna timpul pe care il socotiti necesar pentru implementare si depanare. De asemenea, chiar daca concursul este usor, nu e recomandat sa iesiti din sala de concurs inainte de expirarea timpului. Oricat ati fi de convinsi ca ati facut totul perfect, mai verificati-va; veti avea de furca cu remuscarile daca descoperiti dupa aceea ca ceva, totusi, nu a mers bine. Puteti face o multime de lucruri daca mai aveti timp (desi acest lucru se intampla rar). Iata o serie de metode de a exploata timpul:\r\n\r\n* Verificati-va programul cu cat mai multe teste de mici dimensiuni. Sa presupunem ca programul vostru lucreaza cu vectori de maxim 10.000 de elemente. E o idee buna sa il rulati pentru vectori de unul sau doua elemente.\r\n* Treceti la polul opus si creati-va un test de dimensiune maxima, dar cu o structura particulara, pentru care este usor de calculat rezultatul si de mana. De exemplu, vectori de 10.000 de elemente cu toate elementele egale, sau vectori de forma (1, 2, ..., 9999, 10000). Daca nu puteti sa editati un asemenea fisier de mana, copiind si multiplicand blocuri, puteti scrie un program care sa-l genereze.\r\n* Daca inca v-a mai ramas timp, creati-va un program care sa genereze teste aleatoare. Spre exemplu, un program care sa citeasca N si sa creeze un fisier in care sa scrie N numere aleatoare. Intr-o prima faza, puteti folosi aceste teste pentru a verifica daca nu cumva la valori mai mari programul nu da eroare, nu se blocheaza (la alocarea unor zone mari de memorie) sau nu depaseste limita de timp, caz in care mai aveti de lucru.\r\n* Daca tot nu va da nimeni afara din sala, puteti scrie un alt program auxiliar care, primind fisierul de intrare si fisierul de iesire produs de programul vostru, verifica daca iesirea este corecta. Aceasta deoarece, de obicei, este mult mai usor de verificat o solutie decat de produs una. Folosind \"generatorul\" de teste si \"verificatorul\", puteti testa programul mult mai bine. De altfel, la multe probleme chiar testele rulate de comisia de corectare sunt create tot aleator.\r\n\r\nh2. 5. Dupa concurs\r\n\r\nDupa ce ati terminat problemele (se intampla destul de rar) nu iesiti din sala! Este momentul ultimelor teste. La iesirea din sala trebuie sa fiti convinsi ca ati facut tot ce era posibil in conditiile date. Concursul nu s-a terminat inca! Urmeaza corectarea. Va trebui sa verificati punctajul obtinut si sa fiti pregatit sa depuneti o contestatie daca aveti impresia ca ceva nu este in regula. La unele concursuri, corectarea se face in prezenta concurentului; aici aveti ocazia sa solicitati sa vi se arate testele si iesirile furnizate de programul vostru, sa cereti testarea din afara mediului de evaluare, etc. La alte concursuri, comisia ofera, mai tarziu, testele si raspunsurile corecte pentru autoevaluare. Nu ratati ocazia de a va evalua rezolvarile si nu depuneti contestatii decat daca in urma autoevaluarii obtineti un punctaj mai mare. Fiecare concurs este o experienta in plus! Discutati, dupa proba, cu alti concurenti, aflati cum ar fi trebuit rezolvate problemele pe care nu le-ati stiut aborda si ce au gresit ceilalti (este bine sa invatati si din greselile altora).\r\n\r\nDe multe ori, primul an de participare la olimpiada se soldeaza cu un rezultat cel mult mediu, deoarece, oricat ar spune cineva _Ei, nu-i asa mare lucru sa mergi la un concurs_, experienta acumulata conteaza mult. De aceea, abia de la a doua participare si uneori chiar de mai tarziu incep sa apara rezultatele. Intentia autorului a fost sa va usureze misiunea si sa va dezvaluie cateva din dificultatile de toate felurile care apar la orice concurs, pentru a nu va da ocazia sa le descoperiti pe propria piele. Speram ca aceste ponturi va vor fi de folos!\r\n\r\nh2. Bibliografie\r\n\r\n# **Psihologia concursurilor de informatica**, Catalin Francu, Editura L&S Bucuresti\r\n# \"**Despre Concursuri**\":http://www.ginfo.ro/revista/13_4/babel.pdf, Mihai Stroe, Gazeta de Informatica, numarul 13/4, anul 2003\r\n# \"infoarena\":http://infoarena.ro\r\n# \"Google\":http://www.google.com',2044,'public',3680,NULL),('junior-challenge','Junior Challenge','2007-06-29 19:07:40','2009-03-02 14:42:35','h1. == roundparam(round_id=\"junior_challenge\" param=\"title\") ==\r\n\r\n==include(page=\"templates/junior_head\")==\r\n\r\n_Junior Challenge_ este un concurs dedicat incepatorilor in programare si este o ocazie de antrenament oferita lotului de juniori ce va reprezenta Romania la Olimpiada Balcanica ({_JBOI_}). Runda se desfasoara *Miercuri 4 iulie*, la ora {*09^00^*} si va dura *{color:red}3h*.\r\nParticipantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':junior-challenge/clasament.\r\n\r\nh2. Propunatori\r\n\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")==\r\n* ==user(user=\"crawler\" type=\"tiny\")==\r\n\r\nh2. Organizare \r\n\r\n* == user(user=\"svalentin\" type=\"tiny\") ==\r\n* == user(user=\"filipb\" type=\"tiny\")==\r\n\r\nCu ajutor din partea\r\n\r\n* == user(user=\"fluffy\" type=\"tiny\") ==\r\n* == user(user=\"wickedman\" type=\"tiny\") ==\r\n* ==user(user=\"crawler\" type=\"tiny\")== : sigla\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"junior_challenge\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nPoti citi ultimele mesaje in legatura cu concursul pe forum.\r\n\r\n==SmfTopics(board_id=\"44\" count=\"10\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n',1490,'protected',NULL,NULL),('junior-challenge/clasament','junior_challenge/clasament','2007-06-29 20:09:04','2009-03-02 14:42:17','h1. == roundparam(round_id=\"junior_challenge\" param=\"title\") ==\r\n\r\n==include(page=\"templates/junior_head\")==\r\n\r\nAici este clasamentul pentru concursul _Junior Challenge_. Mai multe detalii despre concurs gasiti \'aici\':junior-challenge.\r\n\r\np<. == Rankings(rounds=\"junior_challenge\") == ',1490,'protected',NULL,NULL),('junior-challenge/solutii','junior-challenge/solutii','2007-07-04 09:09:53','2009-08-14 17:23:25','==include(page=\"templates/junior_head\")==\r\n\r\nh1. Rezolvarile problemelor date in concurs\r\n\r\nh2. \'Teams\':problema/teams\r\n\r\nh3. ( problema usoara )\r\n\r\nrezolvarea $O(n^2^)$:\r\n - se ia fiecare pereche de pokemoni $(i,j)$ cu $i<j$ si se verifica daca este valida\r\n - o astfel de solutia ar fi adus $50-70%$ din punctaj in functie de implementare\r\n\r\nrezolvarea $O(n log n)$:\r\n\r\n - se sorteaza sirul \r\n - pentru fiecare pokemon se cauta binar intervalul de pokemoni cu care poate forma o echipa \r\n\r\nrezolvarea $O(n)$:\r\n\r\n - se calculeaza $v[i]$ = numarul de pokemoni cu forte mai mici sau egale cu $i$\r\n - pentru fiecare pokemon se adauga la solutie numarul de pokemoni din intervalul cu care poate forma o echipa (atentie, un pokemon nu poate forma o echipa cu el insusi)\r\n\r\n\r\nh2. \'Panou\':problema/panou\r\n\r\nh3. ( problema medie )\r\n\r\nIn primul rand observam ca nu are sens sa actionam un comutator de 2 sau mai multe ori. Plecam de pe linia $N$, coloana $N$ a panoului $A$. Daca $A[N][N]!=B[N][N]$ este clar ca trebuie sa actionam comutatorul situat pe aceasta pozitie. Apoi ne uitam la pozitiile $(N, N-1)$ $(N, N-2)$ .. $(N, 1)$ in ordinea aceasta si procedam similar (unele comutari vor fi fortate). Apoi ne uitam la pozitiile $(N-1, N)$ $(N-2, N)$ .. $(1, N)$ si iarasi unele dintre aceste pozitii vor trebui comutate neaparat. Continuam acest algoritm pentru fiecare pozitie $(i, i)$ din panoul $A$, variabila $i$ fiind parcursa descrescator. O implementare directa a algoritmului are complexitate $O(N^3^)$, pentru a reduce complexitatea la $O(N^2^)$ observam ca la un moment dat, noi trebuie sa stim in ce stare se afla becul situat pe o pozitie $(i, j)$. Starea in care se afla acest bec este $(A[i][j]+L[i]+C[j])%2$, unde $A[i][j]$ reprezinta starea initiala a becului, $L[i]$ numarul de comutari efectuate pe linia $i$ pana in prezent, iar $C[j]$ numarul de comutari efectuate pe coloana $j$ pana in prezent. Cum am efectuat doar acele comutari care trebuiau neaparat efectuate acesta este si numarul minim de comutari necesare.\r\n\r\nh2. \'Ordini\':problema/ordini\r\n\r\nh3. ( problema grea )\r\n\r\nSa presupunem ca dorim sa aflam suma numerelor care se pot forma cu cifrele date in care ignoram conditia care impune ca prima cifra sa fie nenula. Fie $N$ numarul total de cifre ( din restrictiile problemei $N < 1001$ ). Folosind descompunerea in baza 10, rezultatul se va scrie sub forma {$c{~N-1~} * 10^N-1^ + c{~N-2~} * 10^N-2^ + ... c{~0~} * 10^0^$}. Daca stim coeficientii {$c{~0~}$}, {$c{~1~}$}, ... {$c{~N-1~}$}, atunci stim si rezultatul ( toate calculele vor fi facute modulo $M$ ). Se observa ca daca intr-un numar format cifra $x$ apare pe pozitia $i$, atunci trebuie sa adunam la coeficientul {$c{~i~}$} numarul {$x * Res$}, unde $Res$ este numarul de numere care se pot forma si in care cifra $x$ apare pe pozitia {$i$} - daca descompunem fiecare numar in baza 10 ca mai sus si dam factor comun {$10^i^$} obtine exact aceasta relatie. Coeficientii c{~0~}, c{~1~}... c{~N-1~} vor fi deci toti egali pentru ca fiecare cifra $x$ poate fi pusa pe orice pozitie.\r\nDaca frecventele cifrelor sunt {$f{~0~}$}, {$f{~1~}$}... {$f{~9~}$}, atunci cifra $x$ poate aparea pe o pozitie in exact !junior-challenge/solutii?formula.jpg! numere, formula care rezulta din calculul numarului de anagrame pentru un cuvant dat, care este dat de factorialul lungimii cuvantului supra produsul factorialelor frecventelor fiecarei litere in parte. Pentru a calcula efectiv acest numar, vom face toate simplificarile posibile ( impartind prin cel mai mare divizor comun dintre doua numere, primul de la numarator si al doilea de la numitor ) si vom obtine in final un sir de numere care trebuie inmultite ( modulo $M$ ).\r\nDaca prima cifra poate fi {$0$}, rezultatul este deci:\r\n!junior-challenge/solutii?formula2.jpg!, unde numarul de $1$ este dat de suma frecventelor cifrelor.\r\nDesi formula pare la prima vedere complicata, ea rezulta destul de usor din formula numarului de anagrame ale unui cuvant dat si din scrierea numerelor in baza $10$.\r\n\r\nDaca prima cifra nu poate fi $0$ procedam in felul urmator: fixam prima cifra $C$ ( de la $1$ la $9$ ), scadem cu $1$ frecventa cifrei selectate si calculam conform rezultatului de mai sus la care mai adaugam {$C * Res * 10^N^$}. In final vom aduna ( tot modulo $M$ ) cele $9$ numere obtinute si afisam rezultatul.\r\n\r\nAceasta este una din solutii care obtinea punctajul maxim in concurs. Exista si solutii mai rapide care folosesc combinari, insa s-a considerat ca aceste cunostinte depasesc nivelul claselor 7-9.\r\n',6234,'public',NULL,NULL),('jboi-2007/prob4-6','jboi-2007/prob4-6','2007-07-04 17:58:46','2007-07-06 09:11:41','h1. Problemele 4-6 pentru pregatirea LOT-ului\r\n\r\n\"Inapoi la pagina\":jboi-2007\r\n\r\nh2. 4.Cow Yahtzee\r\n\r\nIn their usual clumsy way, the cows are play a version of Yahtzee,\r\nthe dice-rolling game.  They roll N (1 <= N <= 20) dice, each having\r\nS (1 <= S <= 8) sides.  They are curious as to the number of ways\r\na dice roll can meet a particular criterion (like \"contains three\r\n2\'s\" or \"contains one 2 and two 3\'s\").\r\n\r\nHelp them learn about probability. Write a program that reads not\r\nonly N and S but also some expressions that describe their criteria.\r\nCount the number ways the expression can be satisfied over the\r\nentire set of all possible dice rolls (the entire set of rolls for\r\nthree two-sided dice is: {1,1,1; 1,1,2; 1,2,1; 1,2,2; 2,1,1; 2,1,2;\r\n2,2,1; 2,2,2};\r\n\r\nExpressions comprise combinations of a basic form that expresses\r\nthe thought \"want at least W copies of result R\". It looks like this:\r\n\r\nWxR\r\n\r\nwhere (0 <= W <= N and 1 <= R <= S). Each test run will supply E\r\nexpressions (1 <= E <= 20), each of which contains a number 1..10\r\nof the basic forms separated by a \'+\', which means \'and\' (see below).\r\nThe set of lines expresses the thought that is the \'inclusive or\'\r\nof each of the lines individually. Thus the pair of expressions\r\nshown below means \"at least three rolls of five OR both at least\r\none roll of 3 and also at least two rolls of 4\":\r\n\r\n3x5\r\n1x3+2x4\r\n\r\nHere are some of the combinations of four five-sided dice that\r\nsatisfy the above expression: 5,5,5,1; 4,5,5,5; 3,4,4,2; 3,4,4,3;\r\n3,4,4,5; 4,4,5,3.\r\n\r\nProgramming note: Be sure to verify that you can read in two integers\r\nfrom one line and a string from the next line. In some languages\'\r\nI/O schema, this is harder than it looks!\r\n\r\nAlso note that the total number of dice combinations will never\r\nexceed 1,512,768 in the supplied test data.\r\n\r\nPROBLEM NAME: cowyotz\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Three space-separated integers: N, S, and E\r\n\r\n* Lines 2..E+1: Line i+1 describes expression i as above.\r\n\r\nSAMPLE INPUT (file cowyotz.in):\r\n\r\n4 5 2\r\n3x5\r\n1x3+2x4\r\n\r\nINPUT DETAILS:\r\n\r\nThis is the encoding of the expression used as an example in the task text.\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: A single integer that is the number of ways the\r\n        expression(s) can be satisfied by rolling the dice in all\r\n        combinations.\r\n\r\nSAMPLE OUTPUT (file cowyotz.out):\r\n\r\n63\r\n\r\nOUTPUT DETAILS:\r\n\r\n63 rolls satisfy the expression.\r\n\r\n\r\nh2. 5.Making Change\r\n\r\nPoor Bessie has taken a job in the convenience store located just\r\nover the border in Slobbovia. Slobbovians use different coinages\r\nthan the USA; their coin values change day-by-day!\r\n \r\nHelp Bessie make optimal change for Slobbovian shoppers. You will\r\nneed to create C (1 <= C <= 1000) cents of change using N (1 <= N\r\n<= 10) coins of various values. All test cases will be solvable\r\nusing the supplied coins.\r\n\r\nIf 5 coins of values 50, 25, 10, 5, and 1 were available, Bessie\r\nwould make optimum change (minimal coins) of 93 cents by using 1 x\r\n50, 1 x 25, 1 x 10, 1 x 5, and 3 x 1 coins (a total of 7 coins).\r\n \r\nHow hard could it be? The final two test cases will be challenging.\r\n\r\nPROBLEM NAME: change\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Two space-separate integers: C and N\r\n\r\n* Lines 2..N+1: Each line contains a single unique integer that is a\r\n        coin value that can be used to create change\r\n\r\nSAMPLE INPUT (file change.in):\r\n\r\n93 5\r\n25\r\n50\r\n10\r\n1\r\n5\r\n\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: A single integer that is the minimum number of coins to\r\n        create C cents\r\n\r\nSAMPLE OUTPUT (file change.out):\r\n\r\n7\r\n\r\nh2. 6.The Bale Tower\r\n\r\nAlways bored with cud-chewing, the cows have invented a new game.\r\nOne cow retrieves a set of N (3 <= N <= 20) hay bales from the shed\r\neach of which is one unit high. Each bale also has some unique width\r\nand unique breadth.\r\n\r\nA second cow tries to choose a set of bales to make the tallest\r\nstack of bales in which each bale can be placed only on a bale whose\r\nown width and breadth are smaller than the width and breadth of the\r\nbale below. Bales can not be rotated to interchange the width and\r\nbreadth.\r\n\r\nHelp the cows determine the highest achievable tower that can be\r\nlegally built form a set of bales.\r\n\r\nPROBLEM NAME: btwr\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: A single integer, N\r\n\r\n* Lines 2..N+1: Each line describes a bale with two space-separated\r\n        integers,respectively the width and breadth\r\n\r\nSAMPLE INPUT (file btwr.in):\r\n\r\n6\r\n6 9\r\n10 12\r\n9 11\r\n8 10\r\n7 8\r\n5 3\r\n\r\n\r\nINPUT DETAILS:\r\n\r\nSix bales of various widths and breadths\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: The height of the tallest possible tower that can legally be\r\n        built from the bales.\r\n\r\nSAMPLE OUTPUT (file btwr.out):\r\n\r\n5\r\n\r\nOUTPUT DETAILS:\r\n\r\nThese bales can be stacked for a total height of 5:\r\n10 12\r\n9 11\r\n8 10\r\n6 9\r\n5 3\r\n[another stacking exists, too]\r\n',1507,'public',NULL,NULL),('jboi-2007/prob7-9','jboi-2007/prob7-9','2007-07-04 18:06:55','2007-07-06 09:11:58','h1. Problemele 7-9 pentru pregatirea LOT-ului\r\n\r\n\"Inapoi la pagina\":jboi-2007\r\n\r\nh2. 7.Wonderprime Brands\r\n\r\nThe cows are forever competing to see who has the best brand. The\r\nlatest rage is brands that are \'Wonderprimes\'. You probably already\r\nknow that a brand consists of a sequence of digits that does not\r\nbegin with 0; brands actually look a lot like positive integers.\r\n\r\nA wonderprime is a number that can be partitioned into two prime\r\nnumbers, each of which has at least D digits and, of course, doesn\'t\r\nstart with 0. When D=2, the number 11329 is a wonderprime (since it\r\nconnects 113 and 29, both of which are prime).\r\n\r\nOnly a few of the cows have wonderprime brands, but they all want\r\none. Your job is to find the first wonderprime greater than or equal\r\nto a supplied integer N (1 <= N <= 2,000,000,000). No integer greater\r\nthan 2,000,000,000 will be required.\r\n\r\nPROBLEM NAME: wpb\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Two space-separated integers: D and N\r\n\r\nSAMPLE INPUT (file wpb.in):\r\n\r\n2 11328\r\n\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: A line that contains the first wonderprime no smaller than\r\n        N.\r\n\r\nSAMPLE OUTPUT (file wpb.out):\r\n\r\n11329\r\n\r\nh2. 8.The Eating Puzzle\r\n\r\nBessie is on a diet where she can eat no more than C (10 <= C <=\r\n35,000) calories per day. Farmer John is teasing her by putting out\r\nB (1 <= B <= 21) buckets of feed, each with some (potentially\r\nnon-unique) number of calories (range: 1..35,000). Bessie has no\r\nself-control: once she starts on a feed bucket, she consumes all\r\nof it.\r\n\r\nBessie is not so good at combinatorics. Determine the optimal\r\ncombination of feed buckets that gives Bessie as many calories\r\nwithout exceeding the limit C.\r\n\r\nAs an example, consider a limit of 40 calories and 6 buckets with\r\n7, 13, 17, 19, 29, and 31 calories. Bessie could eat 7 + 31 = 38\r\ncalories but could eat even more by consuming three buckets: 7 +\r\n13 + 19 = 39 calories. She can find no better combination.\r\n\r\nPROBLEM NAME: eatpuz\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Two space-separated integers: C and B\r\n\r\n* Line 2: B space-separated integers that respectively name the number\r\n        of calories in bucket 1, 2, etc.\r\n\r\nSAMPLE INPUT (file eatpuz.in):\r\n\r\n40 6\r\n7 13 17 19 29 31\r\n\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: A single line with a single integer that is largest number\r\n        of calories Bessie can consume and still stay on her diet.\r\n\r\nSAMPLE OUTPUT (file eatpuz.out):\r\n\r\n39\r\n\r\nh2. 9.Dream Counting\r\n\r\nBessie was daydreaming one day as she drifted between wakefulness\r\nand that delicious drowsiness that we all feel when we are tired.\r\nFor a moment, she counted sheep as couldn\'t quite sleep. Bessie\'s\r\nmind is razor sharp and visualizes the numbers as she counts. She\r\nstarted noticing the digits and wondered: how many instances of\r\neach digit appear in a counting sequence?\r\n\r\nWrite a program to answer this question. Given two integers M and\r\nN (1 <= M <= N <= 2,000,000,000 and N-M <= 500,000), how many of\r\noccurences of each digit appear?\r\n\r\nConsider the sequence 129..137: 129, 130, 131, 132, 133, 134, 135, 136,\r\n137. Count the digits to find:\r\n   1x0      1x5\r\n  10x1      1x6\r\n   2x2      1x7\r\n   9x3      0x8\r\n   1x4      1x9\r\n\r\nPROBLEM NAME: dream\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Two space-separated integers: M and N\r\n\r\nSAMPLE INPUT (file dream.in):\r\n\r\n129 137\r\n\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: Ten space-separated integers that are the counts of the\r\n        number of each digit (0..9) that appears while counting\r\n        through the sequence.\r\n\r\nSAMPLE OUTPUT (file dream.out):\r\n\r\n1 10 2 9 1 1 1 1 0 1\r\n\r\nOUTPUT DETAILS:\r\n\r\nOne zero, ten ones, etc.\r\n',1507,'public',NULL,NULL),('jboi-2007/clasament','JBOI 2007 - Clasament','2007-07-04 18:14:05','2008-02-25 19:59:18','h1. Clasamentul rundelor de pregatire\r\n\r\n\"Inapoi la pagina\":jboi-2007\r\n\r\n# ==User(user=\"vanila_cpp\" type=\"tiny\")== - 1500 pt\r\n# ==User(user=\"cezarmocan\" type=\"tiny\")== - 1300 pt\r\n# ==User(user=\"tvlad\" type=\"tiny\")== - 1240 pt\r\n# ==User(user=\"raduzer\" type=\"tiny\")== - 1220 pt',6679,'public',NULL,NULL),('jboi-2007','JBOI 2007','2007-07-04 17:39:30','2008-10-12 20:45:32','h1. 1st Junior Balkan Olympiad in Informatics \r\n\r\n!jboi-2007?boij.jpg!\r\n\r\nAceasta pagina este dedicata primei editii a Olimpiadei Balcanice de Informatica pentru Juniori. Aici se vor gasi materiale necesare lotului Romaniei.\r\n\"Site-ul oficial al JBOI\":http://www.jboi2007.org/\r\n\r\nh2. Componenti ai lotului\r\n\r\n* ==User(user=\"vanila_cpp\" type=\"normal\")==\r\n* ==User(user=\"cezarmocan\" type=\"normal\")==\r\n* ==User(user=\"tvlad\" type=\"normal\")==\r\n* ==User(user=\"raduzer\" type=\"normal\")==\r\n\r\n\"Clasamentul rundelor de pregatire\":jboi-2007/clasament\r\n\r\nh2. Problemele de la rundele de pregatire\r\n\r\n* \"Probleme 1-3 -> Runda 1\":jboi-2007/prob1-3\r\n* \"Probleme 4-6 -> Runda 2\":jboi-2007/prob4-6\r\n* \"Probleme 7-9 -> Runda 3\":jboi-2007/prob7-9\r\n* \"Probleme 10-12 -> Runda 4\":jboi-2007/prob10-12\r\n* \"Probleme 13-15 -> Runda 5\":jboi-2007/prob13-15\r\n\r\nh2. Evaluator from ==User(user=\"crawler\" type=\"tiny\")==\r\n\r\n\"Download evaluator\":jboi-2007?action=download&file=eval.exe\r\n\r\n',1490,'public',NULL,NULL),('jboi-2007/prob1-3','jboi-2007/prob1-3','2007-07-05 12:34:56','2007-07-06 09:11:22','h1. Problemele 1-3 pentru pregatirea LOT-ului\r\n\r\n\"Inapoi la pagina\":jboi-2007\r\n\r\nh2. Buy One Get One Free\r\n\r\n\r\n\r\nFarmer John has discovered the Internet is buying bales of hay\r\nonline when he notices a special deal. For every bale of hay of\r\nsize A (1 <= A <= 1,000,000) he buys, he can get a bale of hay of\r\nsize B (1 <= B < A) for free!\r\n\r\nThe deal, however, is restricted: the larger bale must be high\r\nquality hay and the smaller one must be low quality hay. FJ, being\r\na frugal and thrifty fellow, does not care: any quality of hay will\r\ndo as long as he saves some money.\r\n\r\nGiven a list of the sizes of N (1 <= N <= 10,000) bales of high\r\nquality hay and M (1 <= M <= 10,000) bales of low quality hay, find\r\nthe maximum number of bales of hay Farmer John can purchase.  He\r\ncan buy bales of high quality hay without getting the free bale of\r\nlow quality hay, but he cannot buy bales of low quality hay (i.e.,\r\nhe must get them for free in the deal).\r\n\r\nPROBLEM NAME: buyfree\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Two space-separated integers: N and M.\r\n\r\n* Lines 2..N+1: Line i+1 contains a single integer which is the size\r\n        of the ith bale of high quality hay.\r\n\r\n* Lines N+2..N+M+1: Line i+N+1 contains a single integer which is the\r\n        size of the ith bale of low quality hay.\r\n\r\nSAMPLE INPUT (file buyfree.in):\r\n\r\n3 4\r\n6\r\n1\r\n3\r\n1\r\n5\r\n3\r\n4\r\n\r\nINPUT DETAILS:\r\n\r\nThere are 3 bales of high quality hay, with sizes 6, 1, and 3, and 4 bales\r\nof low quality hay, with sizes 1, 5, 3, and 4.\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: The maximum total number of bales of hay Farmer John can\r\n        obtain.\r\n\r\nSAMPLE OUTPUT (file buyfree.out):\r\n\r\n5\r\n\r\nOUTPUT DETAILS:\r\n\r\nObviously, Farmer John can buy all the bales of high quality hay.\r\nWhen he buys the size 6 high quality bale, he can get any low quality\r\nbale for free (say, the bale of size 3). When he buys the size 3\r\nhigh quality bale, he can get the size 1 low quality bale for free.\r\nWhen he buys the size 1 high quality bale, however, he cannot get\r\nany low quality bales for free (since the size must be strictly\r\nless). The total, no matter how clever FJ is, comes to five bales.\r\n\r\n\r\n\r\n\r\n\r\n\r\nh2. Qualified Primes\r\n\r\n\r\nFarmer John has begun branding the cows with sequential prime\r\nnumbers. Bessie has noticed this and is curious about the occurrence\r\nof various digits in those brands.\r\n \r\nHelp Bessie determine the number of primes in the inclusive range\r\nA..B (1 <= A <= B <= 4,000,000; B <= A + 1,000,000; one test case\r\nhas B <= A + 2,000,000 ) that contain a supplied digit D.\r\n\r\nA prime is a positive integer with exactly two divisors (1 and\r\nitself). The first primes are 2, 3, 5, 7, 11, 13, 17, 19, 23, and,\r\n29.\r\n\r\nPROBLEM NAME: qprime\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Three space-separated integers: A, B, and D\r\n\r\nSAMPLE INPUT (file qprime.in):\r\n\r\n10 15 3\r\n\r\n\r\nINPUT DETAILS:\r\n\r\nHow many primes in the range 10..15 contain the digit 3?\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: The count of primes in the range that contain the digit D.\r\n\r\nSAMPLE OUTPUT (file qprime.out):\r\n\r\n1\r\n\r\nOUTPUT DETAILS:\r\n\r\nJust 13 in this range contains a \'3\'.\r\n\r\n\r\n\r\n\r\nh2. Lilypad Pond\r\n\r\n\r\n\r\n\r\nFarmer John has installed a beautiful pond for his cows\' esthetic\r\nenjoyment and exercise. The rectangular pond has been partitioned\r\ninto square cells of M rows and N columns (1 <= M <= 30; 1 <= N <=\r\n30). Some of the cells have astonishingly sturdy lilypads; others\r\nhave rocks; the remainder are just beautiful, cool, blue water.\r\n\r\nBessie is practising her ballet moves by jumping from one lilypad\r\nto another and is currently located at one of the lilypads (see the\r\ninput data for the location\'s specifier). She wants to travel to\r\nanother lilypad in the pond by jumping from one lilypad to another.\r\nShe can jump neither into the water nor onto a rock.\r\n\r\nSurprising only to the uninitiated, Bessie\'s jumps between lilypads\r\nalways appear as a sort of chess-knight\'s move: move M1 (1 <= M1\r\n<= 30) \'squares\' in one direction and then M2 (1 <= M2 <= 30; M1\r\n!= M2) more in an orthogonal direction (or perhaps M2 in one direction\r\nand then M1 in an orthogonal direction). Bessie sometimes might\r\nhave as many as eight choices for her jump.\r\n\r\nGiven the pond layout and the format of Bessie\'s jumps, determine\r\nthe smallest number of leaps that Bessie must make to move from her\r\nstarting location to her final destination, a feat which is always\r\npossible for the given test data.\r\n\r\nPROBLEM NAME: bronlily\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Four space-separated integers: M, N, M1, and M2\r\n\r\n* Lines 2..M+1: Line i+1 describes row i of the pond using N\r\n        space-separated integers with these values: 0 indicates empty\r\n        water; 1 indicates a lilypad; 2 indicates a rock; 3 indicates\r\n        the lilypad Bessie upon which she starts; 4 indicates the\r\n        lilypad that is Bessie\'s destination.\r\n\r\nSAMPLE INPUT (file bronlily.in):\r\n\r\n4 5 1 2\r\n1 0 1 0 1\r\n3 0 2 0 4\r\n0 1 2 0 0\r\n0 0 0 1 0\r\n\r\nINPUT DETAILS:\r\n\r\nBessie starts on the left in row 2; her destination is on the right in row\r\n2. Several lilypads and rocks occupy the pond.\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: A single integer that is the minimum number of jumps between\r\n        lilypads that Bessie must make to travel from her starting\r\n        place to her destination.\r\n\r\nSAMPLE OUTPUT (file bronlily.out):\r\n\r\n2\r\n\r\nOUTPUT DETAILS:\r\n\r\nBessie cleverly hops onto the pad at row 1, column 3 on her way to the\r\nright hand side.\r\n',1507,'public',NULL,NULL),('implica-te/extinde-arhiva/autor-necunoscut','Autor necunoscut','2007-07-09 19:24:32','2007-08-13 20:13:47','h1. Autor necunoscut\r\n\r\nPentru aceasta problema nu am reusit sa identificam autorul. Daca ne poti ajuta sa aflam cine a compus aceasta problema te rugam sa trimiti un mail unuia din membrii \'echipei infoarena\':echipa-infoarena.\r\n\r\nInfoarena foloseste problemele in scopuri educationale. Printre cei care beneficiaza de arhiva de probleme se numara elevi si studenti din toata tara. Totusi daca unul dintre autori doreste ca problemele sale sa NU fie folosite in arhiva noastra, le putem retrage la cererea acestuia.',15,'public',NULL,NULL),('jboi-2007/prob10-12','jboi-2007/prob10-12','2007-07-10 09:28:02','2007-07-10 09:28:26','h1. Problemele 10-12 pentru pregatirea LOT-ului\r\n\r\n\"Inapoi la pagina\":jboi-2007\r\n\r\nh2. New Cow Brands\r\n\r\nThe cows are beside themselves: Farmer John has decided to use RFID\r\ntags instead of branding the cows with red-hot irons that cause\r\nintense pain.\r\n\r\nThe RFID tags contain a code that is N (3 <= N <= 15) characters\r\n(each in the range \'A\'..\'Z\') in length. No character appears twice\r\nin the code. The character chosen for any given position in the\r\ncode is chosen from a supplied set for that position. The set is\r\nalways given in alphabetical order.\r\n\r\nA machine generates the codes in alphabetical order. Each new batch\r\nof cows uses the next unused set of codes. FJ keeps track of the\r\nnumber of codes he has already used.\r\n\r\nHelp FJ confirm the RFID brands to be used for the next set of cows.\r\nGiven the count of the starting and finishing brands (1 <= start < finish\r\n<= 22,000,000 and finish-start < 2000), print (in alphabetical order) the\r\nbrands that will be used. See the I/O specifications for an example.\r\n\r\nPROBLEM NAME: brand3\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Three space-separated integers, respectively: N, start, and\r\nfinish.\r\n\r\n* Lines 2..N+1: Line i+1 contains a number (1..26) of characters that\r\nare the valid characters for position i in the RFID code\r\n\r\nSAMPLE INPUT (file brand3.in):\r\n\r\n4 6 13\r\nABC\r\nCDELQ\r\nCFH\r\nABC\r\n\r\nINPUT DETAILS:\r\n\r\nFour positions in the RFID code; print the 6th through 13th codes.\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Lines 1..finish-start+1: Line i contains RFID code # start+i-1\r\n\r\nSAMPLE OUTPUT (file brand3.out):\r\n\r\nADHB\r\nADHC\r\nAECB\r\nAEFB\r\nAEFC\r\nAEHB\r\nAEHC\r\nALCB\r\n\r\nOUTPUT DETAILS:\r\n\r\nHere are the first 20 codes:\r\n1 ACFB 5 ADFC 9 AEFB 13 ALCB 17 ALHC\r\n2 ACHB 6 ADHB 10 AEFC 14 ALFB 18 AQCB\r\n3 ADCB 7 ADHC 11 AEHB 15 ALFC 19 AQFB\r\n4 ADFB 8 AECB 12 AEHC 16 ALHB 20 AQFC\r\n\r\n\r\n\r\n\r\n\r\nh2. Word Games\r\n\r\nThe cows are playing Scrabble but, sad to say, they do not have the\r\nvocabulary to play at the tournament level. Bessie wants your help\r\nfor just the first move. Given her rack (a \"rack\" is a holder of\r\nScrabble letters) of N (3 <= N <= 10) letters (which might or might\r\nnot be unique and might include one or more blank \"wild card\" tiles)\r\nalong with a scrabble dictionary of D (10 <= D <= 50000) words,\r\nprint the words she might use (by searching the dictionary).\r\n\r\nThe 27 possible letters are upper-case \'A\'..\'Z\' and the \'#\' symbol,\r\nwhich represents a \"wildcard\" and can stand for any letter. If two\r\n\'#\'s appear in one rack, each can represent a different letter when\r\nplayed.\r\n\r\nThe dictionary words can be read, one per line, from file whose\r\nname is \'scrbl.txt\' (the file name is all lower case letters, unlike\r\nthe file\'s contents). The letters in Bessie\'s rack can always be\r\nused to make at least one word. Each word in the dictionary is\r\nunique. Remember that you are running on Linux: each input line\r\nends with a \'\\n\' character; no \'return\' characters are present.\r\n\r\nPROBLEM NAME: scrbl\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Two space-separated integers, N and D.\r\n\r\n* Line 2: N letters (with no intervening blanks) that are the letters\r\nin Bessie\'s Scrabble rack.\r\n\r\nSAMPLE INPUT (file scrbl.in):\r\n\r\n4 49891\r\nIAFR\r\n\r\nINPUT DETAILS:\r\n\r\nFour letters: I, A, F, and R.\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Lines 1..??: Each line contains a single word that appears in the\r\nscrbl.txt dictionary. Print the output in the order the words\r\nappear in the dictionary.\r\n\r\nSAMPLE OUTPUT (file scrbl.out):\r\n\r\nAIR\r\nFAIR\r\nFAR\r\nFIR\r\nIF\r\n\r\nOUTPUT DETAILS:\r\n\r\nThese words do actually appear in the real dictionary used for this\r\nproblem.\r\n\r\n\r\n\r\n\r\n\r\nh2. Serious Cow Tag\r\n\r\nFarmer John\'s N (1 <= N <= 1000) cows (conveniently numbered 1..N)\r\nare going to play a game of Serious Cow Tag. In Serious Cow Tag,\r\neach cow chooses a grid point in the pasture (-7500 <= X <= 7500,\r\n-7500 <= Y <= 7500) such that the distances between all pairs of\r\ncows are unique.\r\n\r\nThe cows play in turn, starting with cow #1 and continuing with\r\ncows #2, #3, and so on (as long as the cow is still in the game).\r\nWhen it is a cow\'s turn to play, she finds the nearest cow still\r\nplaying, ambles over to that cow to tag her, and then returns to\r\nher original location. As soon as a cow is tagged, she is out of\r\nthe game.\r\n\r\nThe game ends when only one cow remains, and she is declared the\r\nwinner.\r\n\r\nFarmer John is taking bets with neighboring farmers as to which cow\r\nwill win, so he would like to know the winner in advance. Write a\r\nprogram that will read a description of the cows\' positions and\r\ndetermine the winner.\r\n\r\nPROBLEM NAME: cowtag\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: A single integer N, the number of cows\r\n\r\n* Lines 2..N+1: Line i+1 contains two space-separated integers that\r\ndescribe the location of cow i.\r\n\r\nSAMPLE INPUT (file cowtag.in):\r\n\r\n3\r\n0 0\r\n0 3\r\n4 3\r\n\r\nINPUT DETAILS:\r\n\r\nThree cows at (0, 0), (0, 3) and (4, 3).\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: The number of the winning cow.\r\n\r\nSAMPLE OUTPUT (file cowtag.out):\r\n\r\n3\r\n\r\nOUTPUT DETAILS:\r\n\r\nCow 1 goes first and tags the nearest cow, cow 2. Cow 2 is eliminated\r\nso she does not get a turn. Cow 3 then tags the only remaining cow,\r\ncow 1. She is the last cow left, so she wins.',1507,'public',NULL,NULL),('jboi-2007/prob13-15','jboi-2007/prob13-15','2007-07-11 10:54:51','2007-07-11 10:54:51','h1. Problemele 13-15 pentru pregatirea LOT-ului\r\n\r\n\"Inapoi la pagina\":jboi-2007\r\n\r\nh2. The Moronic Cowmpouter\r\n\r\nInexperienced in the digital arts, the cows tried to build a\r\ncalculating engine (yes, it\'s a cowmpouter) using binary numbers\r\n(base 2) but instead built one based on base negative 2!  They were\r\nquite pleased since numbers expressed in base -2 do not have a sign\r\nbit.\r\n\r\nYou know number bases have place values that start at 1 (base to\r\nthe 0 power) and proceed right-to-left to base^1, base^2, and so\r\non. In base -2, the place values are 1, -2, 4, -8, 16, -32, ...\r\n(reading from right to left). Thus, counting from 1 goes like this:\r\n1, 110, 111, 100, 101, 11010, 11011, 11000, 11001, and so on.\r\n\r\nEerily, negative numbers are also represented with 1\'s and 0\'s but\r\nno sign. Consider counting from -1 downward: 11, 10, 1101, 1100,\r\n1111, and so on.\r\n \r\nPlease help the cows convert ordinary decimal integers (range\r\n-2,000,000,000..2,000,000,000) to their counterpart representation\r\nin base -2.\r\n\r\nPROBLEM NAME: neg2\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: A single integer to be converted to base -2\r\n\r\nSAMPLE INPUT (file neg2.in):\r\n\r\n-13\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: A single integer with no leading zeroes that is the input\r\n        integer converted to base -2. The value 0 is expressed as 0,\r\n        with exactly one 0.\r\n\r\nSAMPLE OUTPUT (file neg2.out):\r\n\r\n110111\r\n\r\nOUTPUT DETAILS:\r\n\r\nReading from right-to-left:\r\n1*1 + 1*-2 + 1*4 + 0*-8 +1*16 + 1*-32 = -13\r\n\r\n\r\n\r\n\r\n\r\n\r\nh2. DNA Assembly\r\n\r\n\r\nFarmer John has performed DNA sequencing on his prize milk-producing\r\ncow, Bessie DNA sequences are ordered lists (strings) containing\r\nthe letters \'A\', \'C\', \'G\', and \'T\'.\r\n\r\nAs is usual for DNA sequencing, the results are a set of strings\r\nthat are sequenced fragments of DNA, not entire DNA strings. A pair\r\nof strings like \'GATTA\' and \'TACA\' most probably represent the\r\nstring \'GATTACA\' as the overlapping characters are merged, since\r\nthey were probably duplicated in the sequencing process.\r\n\r\nMerging a pair of strings requires finding the greatest overlap\r\nbetween the two and then eliminating it as the two strings are\r\nconcatenated together. Overlaps are between the end of one string\r\nand beginning of another string, NOT IN THE MIDDLE OF A STRING.\r\n\r\nBy way of example, the strings \'GATTACA\' and \'TTACA\' overlap\r\ncompletely. On the other hand, the strings \'GATTACA\' and \'TTA\' have\r\nno overlap at all, since the matching characters of one appear in\r\nthe middle of the other, not at one end or the other. Here are some\r\nexamples of merging strings, including those with no overlap:\r\n\r\n	GATTA + TACA -> GATTACA\r\n	TACA + GATTA -> TACAGATTA\r\n	TACA + ACA -> TACA\r\n	TAC + TACA -> TACA\r\n	ATAC + TACA -> ATACA\r\n	TACA + ACAT -> TACAT\r\n\r\nGiven a set of N (2 <= N <= 7) DNA sequences all of whose lengths\r\nare in the range 1..7, find and print length of the shortest\r\npossible sequence obtainable by repeatedly merging all N strings\r\nusing the procedure described above. All strings must be merged\r\ninto the resulting sequence.\r\n\r\nPROBLEM NAME: dna\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: A single integer N\r\n\r\n* Lines 2..N+1: Each line contains a single DNA subsequence\r\n\r\nSAMPLE INPUT (file dna.in):\r\n\r\n4\r\nGATTA\r\nTAGG\r\nATCGA\r\nCGCAT\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: Length of the shortest possible string obtained by merging\r\n        the subsequences. It is always possible -- and required -- to\r\n        merge all the input strings to obtain this string.\r\n\r\nSAMPLE OUTPUT (file dna.out):\r\n\r\n13\r\n\r\nOUTPUT DETAILS:\r\n\r\nSuch string is \"CGCATCGATTAGG\".\r\n\r\n\r\n\r\n\r\n\r\n\r\nh2. Cow Phrasebook\r\n\r\n\r\nEver the innovator, Farmer John is teaching cows to speak some\r\nphrases in human language. He writes each new phrase the cows learn\r\nin his phrase book, a total of M (1 <= M <= 1,000) so far.\r\n\r\nWhen Farmer John is on a vacation, he can only communicate with his\r\ncows by telephone. Being an active vacationer, FJ visits beaches\r\nand fine restaurants when away from the farm. When he returns, his\r\nanswering machine is full of N (1 <= N <= 10,000) messages, many\r\npotentially from the cows.\r\n\r\nFJ vacations frugally and thus gets poor telephone service. Many\r\nof the recorded messages cut off before they are complete. Help FJ\r\ndetermine whether the recorded messages are from the phrasebook by\r\ndetermining if the message begins a phrase.\r\n\r\nYou will be given the phrasebook and a set of texts of the recorded\r\nmessages. Count the number of recorded messages that are the beginning\r\n(prefix) of a phrase from the phrase book.\r\n\r\nComplete phrases are from 1 to 60 characters in length, each of which\r\nis either a letter (upper or lower case), a period (.), comma (,),\r\nquestion mark (?) or space. There are no leading spaces, trailing\r\nspaces, or double spaces in a phrase. Comparisons are case-sensitive,\r\nand a phrase is in fact, considered to be prefix of itself.\r\n\r\nPROBLEM NAME: phrase\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Two space-separated integers, M and N\r\n\r\n* Lines 2..M+1: Phrases from the phrase book, one per line.\r\n\r\n* Lines M+2..M+N+1: Phrases spoken by cows, one per line.\r\n\r\nSAMPLE INPUT (file phrase.in):\r\n\r\n3 4\r\nI will not buy this record, it is scratched.\r\nMy hovercraft is full of eels.\r\nDo you want to come back to my place? Bouncy, bouncy.\r\nI will not buy this rec\r\nMy helicopter is\r\nDo you want to come back\r\nI will not buy this cat.\r\n\r\nINPUT DETAILS:\r\n\r\nThree input phrases (record, eels, bouncy); four query phrases\r\n(buy, helicopter, come back, cat).\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: A single integer that is the count of the number of messages\r\n        that were proper prefixes of the phrasebook.\r\n\r\nSAMPLE OUTPUT (file phrase.out):\r\n\r\n2\r\n\r\nOUTPUT DETAILS:\r\n\r\nThe messages \'I will not buy this rec\' and \'Do you want to come back\'\r\nare valid prefixes of the phrasebook.',1507,'public',NULL,NULL),('utilizator/danielp','Profil danielp','2006-11-24 20:56:16','2007-07-17 14:50:29','h2. Despre mine\r\n\r\n* scoala generala nr. 3, Suceava (1994 - 2002)\r\n* Colegiul National Petru Rares, Suceava (2002 - 2006)\r\n* Facultatea de Informatica, Iasi (2006 - present)\r\n\r\nh2. Distinctii primite\r\n\r\n* Locul 12 la ACM, Southeastern Europe Region (2006)\r\n* Bronz, IOI (2005)\r\n* locul 2, ONI (2004)\r\n* aur absolut, \"Tuymaada olympiad\", Yakutia (2004)\r\n* multe alte premii si mentiuni la concursuri nationale\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* echipa infoarena \r\n* ==user(user=\"unholyfrozen\" type=\"normal\")== \r\n* ==user(user=\"astronomy\" type=\"normal\")==',48,'protected',NULL,NULL),('summer-challenge-2007/clasament/runda-1','Clasament Summer Challenge 2007, Runda 1','2007-07-25 10:29:51','2007-08-10 19:17:36','h1. Clasament \'Summer Challenge 2007, Runda 1\':summer-challenge-2007/runda-1\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2007/\r\n*(active) \'Runda 1\':summer-challenge-2007/runda-1\r\n* \'Runda 2\':summer-challenge-2007/runda-2\r\n* \'Runda 3\':summer-challenge-2007/runda-3\r\n*(active) \'Clasament\':summer-challenge-2007/clasament\r\n\r\n== Rankings(rounds=\"summer2007-runda1\") == ',1,'protected',NULL,NULL),('runda/summer2007-runda1/clasament','Clasament summer2007-runda1','2007-07-25 10:30:35','2007-07-25 10:30:35','h1. Clasament ==roundparam(round_id=\"summer2007-runda1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer2007-runda1\")==',961,'round: summer2007-runda1',NULL,NULL),('intrebari','intrebari','2007-07-28 11:47:41','2007-07-30 22:30:27','h2. Intrebari pt programatori bazati sau fosti olimpici\r\n\r\n* cele mai interesante 5 carti\r\n* limbajul de programare preferat\r\n* editorul preferat\r\n* cum ai inceput cu informatica\r\n* siteuri preferate\r\n* bloguri preferate\r\n* proiectul mai interesant la care ai lucrat\r\n* planuri de viitor\r\n* alte pasiuni inafara de informatica\r\n* algoritmul preferat\r\n* vreun warstory interesant?\r\n* de ce ai ales scoala pe care ai ales-o\r\n* tii vreo problema de concurs minte, vre-un brainteaser \r\n* tehnica de programare / jmen / tehnologie\r\n* best practice\r\n* cum ataci o problema un proiect prin ce faze treci\r\n* ce structuri de date folosesti, algoritmi\r\n* sfaturi pt cei ce vreau sa inceapa cu programarea\r\n* sistem de operare\r\n* cum lucrezi? in salturi sau putin in fiecare zi\r\n* cat timp petreci in fata calculatorului\r\n* inspiratie/transpiratie, factor motivator\r\n* ba da voi cum va distrati\r\n* muzica filme\r\n* ce faci in primele minute cand ajungi la munca/servici\r\n* cum iti mentii cunostintele la zi\r\n* gasirea unui bug, metode de atac\r\n* mod de munca, intervale compacte, iteratii directe, tehnologii noi sau tehnici bine cunoscute\r\n* impartirea timpului',6686,'public',NULL,NULL),('newsletter/summer-challenge-2007/runda-1','Summer Challenge, Romania la olimpiadele internationale','2007-07-29 10:53:03','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nIn toiul vacantei de vara, feriti de canicula, la umbra monitoarelor,\r\ninfoarena se gandeste la tine! :)\r\n\nTe invitam sa participi la seria de concursuri Summer Challenge 2007. \r\nVom organiza 3 runde online, de cate 5h fiecare, cu probleme de\r\ndificultate variata.\r\n\nSummer Challenge este o ocazie buna de antrenament pentru tine\r\n(daca nu esti deja la mare :) dar si un ultim test pentru delegatia\r\nRomaniei la Olimpiada Internationala de Informatica 2007 (Croatia).\r\n\nAi ocazia sa concurezi cu lotul Romaniei la IOI 2007!\r\n\nRunda 1 a concursului Summer Challenge 2007 se desfasoara...\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Luni, 30 iulie 2007, orele 10:00 - 15:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPagina rundei: \'summer-challenge-2007/runda-1\':summer-challenge-2007/runda-1\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la acest concurs iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te va aduce mai aproape de varful clasamentul.\r\n==NewsletterRating(username=\"%username%\")==\r\nAfla mai multe despre rating: \'documentatie/rating\':documentatie/rating\r\n\nh2.  Despre Summer Challenge 2007 \n\nOrganizatorul primei runde online SC07 este Adrian Diaconu:\r\n\'utilizator/\':utilizator/DITzoneC\r\n\nPentru informatii suplimentare (cum particip, intrebari etc.)\r\nviziteaza pagina concursului: \'summer-challenge-2007\':summer-challenge-2007\r\n\nh2.  Rezultatele Romaniei la olimpiadele internationale \n\nIn luna iulie s-au desfasurat BOI si CEOI, doua competitii\r\ninternationale la care participa Romania in mod traditional.\r\n\nAnul 2007 a adus in premiera concursul JBOI (Junior Balkan Olympiad\r\nin Informatics). La JBOI participa elevi din tarile balcanice sub\r\nvarsta de 15-16 ani.\r\n\nIata un rezumat al acestor competitii:\r\n\np{padding-left: 2em;}. *   Junior Balkan Olympiad in Informatics, 1st Edition (2007)\r\n        Belgrad, Serbia\r\n        \'http://www.jboi2007.org/\':http://www.jboi2007.org/\r\n\np{padding-left: 4em;}. La prima editie a JBOI, juniorii Romaniei au obtinut rezultate\r\n        exceptionale, aducand Romania pe locul I in clasamentul\r\n        pe natiuni. Felicitari!\r\n\np{padding-left: 4em;}. Victor-Cristian Ionescu,    locul 1,    AUR\r\n        Vlad-Bogdan Tataranu,       locul 3,    AUR\r\n        Radu Zernoveanu,            locul 5,    ARGINT\r\n        Cezar Mocan,                locul 13,   MENTIUNE\r\n\np{padding-left: 4em;}. Lotul JBOI a fost condus de catre Prof. Univ. Stelian Ciurea\r\n        si Prof. Dana Lica.\r\n\np{padding-left: 4em;}. infoarena a organizat pe 4 iulie un mic concurs de pregatire\r\n        pentru juniori: \'junior-challenge\':junior-challenge\r\n    \r\n    *   Central European Olympiad in Informatics 2007\r\n        Brno, Cehia,\r\n        \'http://www.fi.muni.cz/ceoi/index.xhtml.en\':http://www.fi.muni.cz/ceoi/index.xhtml.en\r\n\np{padding-left: 4em;}. Victor Rusu,                locul 10,   BRONZ\r\n        Cosmin Gheorghe,            locul 19\r\n        Stefan-Alexandru Filip,     locul 24\r\n        Andrei Grigorean,           locul 25\r\n\np{padding-left: 4em;}. Lotul Romaniei a fost condus de catre Prof. Emanuela Cerchez\r\n        si Prof. Constantin Galatan.\r\n\np{padding-left: 2em;}. *   Balkan Olympiad in Informatics 2007\r\n        Chisinau, Moldova\r\n        \'http://boi2007.edu.md/\':http://boi2007.edu.md/\r\n\np{padding-left: 4em;}. Felicitari delegatiei romane! In clasamentul pe natiuni,\r\n        Romania a obtinut locul I.\r\n\np{padding-left: 4em;}. Ionescu Bogdan,             AUR\r\n        Airinei Adrian,             AUR\r\n        Tataroiu Bogdan,            ARGINT\r\n        Dragus Marius,              BRONZ\r\n\np{padding-left: 4em;}. Lotul Romaniei a fost condus de catre Prof. Marinel Serban si\r\n        Prof. Doru Popescu Anastasiu.\r\n\nh2.  IOI 2007 \n\nA 19-a editie a Olimpiadei Internationale de Informatica este gazduita\r\nde Croatia (in Zagreb) si se desfasoara in perioada 15-22 august.\r\n\nPagina web: \'http://www.hsin.hr/ioi2007/\':http://www.hsin.hr/ioi2007/\r\n\nUram succes delegatiei Romaniei la IOI 2007! Speram sa faca ce stiu ei\r\nmai bine, sa obtina rezultate exceptionale.\r\n\nLotul Romaniei este condus de catre Prof. Emanuela Cerchez.\r\nParticipanti:\r\n\np{padding-left: 2em;}. Andrei Grigorean\r\n    Cosmin Gheorghe\r\n    Adrian Airinei\r\n    Bogdan Tataroiu\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('cautari-ortogonale','Cautari ortogonale','2007-06-01 06:07:08','2010-01-20 16:55:56','h1. Cautari ortogonale: Structuri de date si aplicatii\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"alecman\") ==\r\n\r\n(Categoria _Structuri de date_, Autor _Cosmin Negruseri_)\r\n\r\nh2. Introducere\r\n\r\nIn acest articol voi discuta despre cateva structuri de date folositoare pentru probleme de geometrie, in special pentru probleme ortogonale. **Problema de baza** ce va fi rezolvata suna in felul urmator: avem $n$ puncte in plan si pentru un anumit dreptunghi ne intereseaza numarul de puncte din acel dreptunghi, sau diverse alte operatii pentru punctele din interiorul sau, cum ar fi suma cheilor punctelor, minimul sau maximul cheilor (daca punctele au asociate cate o cheie). Folosind arbori de intervale putem rezolva aceasta problema, dar vreau sa exemplific ce alte variante mai avem si avantajele lor, precum si aplicatii practice pentru cautarea pe domenii ortogonale. In general, abordarile prezentate mai jos se pot extinde de la cazul unidimensional sau bidimensional, cu usurinta, la cazuri N-dimensionale.\r\nPentru a intelege cat mai bine ideile si structurile de date prezentate mai departe recomand citirea articolelor [1] si [2].\r\nStructurile prezentate sunt in general statice, adica formam intai structura si apoi rezolvam problema. Structurile de date se pot modifica pentru a suporta inserari si stergeri de puncte, devenind dinamice, dar astfel implementarea se complica. Pentru a simula dinamismul putem insera toate datele de la inceput si sa mai avem un camp boolean in care marcam cu true daca data a fost logic inserata si cu false daca data din nodul respectiv nu a fost inca logic inserata. Aceasta pastreaza complexitatea operatiilor pe structura si ne ajuta in echilibrarea structurilor pentru o eficienta buna a operatiilor.\r\n\r\nh2. QuadTree\r\n\r\n_QuadTree_ este o structura care organizeaza informatii pentru date multidimensionale, fiind folosita in cartografie, procesarea imaginilor, grafica pe calculator etc. Structura este un arbore ce reprezinta o zona din spatiul N-dimensional (in cazul in care suntem noi interesati, $N=2$), fiecare nod al arborelui pastreaza o informatie pentru o zona din spatiu, iar nodul are $2^N^$ fii care reprezinta fiecare o zona de $2^N^$ ori mai mica decat zona parintelui. Zonele fiilor sunt **disjuncte**, iar reuniunea lor formeaza zona parintelui.\r\n\r\nPentru un _QuadTree_ radacina reprezinta un patrat, iar fii reprezinta cele patru patrate **disjuncte si congruente** in care se poate imparti patratul initial. Din cate am prezentat pana acum, un _QuadTree_ este infinit, dar pe noi ne intereseaza de obicei intervale foarte mici din plan, si atunci putem sa folosim numai cateva nivele din _QuadTree_. Cateodata unele noduri din _QuadTree_ nu contin insa nici o informatie si atunci nu avem nevoie sa le folosim pentru ca am folosi memorie in plus.\r\n\r\nIn +problema 3+ a zilei 2 a **Balcaniadei de Informatica** din 1997, se da un _QuadTree_ care reprezinta o imagine colorata alb-negru, de dimensiune $2^N^ * 2^N^$. Daca patratul reprezentat de informatia dintr-un nod al arborelui era de aceeasi culoare, in nod se pastra informatia culorii si nodul nu avea nici un fiu, altfel nodul avea starea indecisa/nedeterminata si avea patru fii.\r\n\r\np=. !cautari-ortogonale?pic1.jpg!\r\n!cautari-ortogonale?pic2.jpg!\r\n!cautari-ortogonale?pic5.jpg!\r\n\r\nPrima imagine prezinta ordinea in care fii reprezinta patratele, a doua imagine reprezinta o imagine alb-negru, iar a treia este reprezentarea sub forma de _QuadTree_ a acelei imagini.\r\n\r\nPentru a reprezenta $n$ puncte de coordonate intregi in plan cu ajutorul structurii de _QuadTree_, vom insera care un punct pe rand in _QuadTree_. Pornim de la un _QuadTree_ gol si inseram un nod recursiv, vedem pentru fiecare patrat care nu are latura de dimensiune unu in care din cele patru patrate din interiorul lui intra punctul nostru. Daca nu exista nod care sa reprezinte acel patrat, il creem noi.\r\n\r\nAvantajul pentru structura de _QuadTree_ este usurinta implementarii, dezavantajul este ca structura lui si timpul de raspuns la intrebari depind si de configuratia punctelor, nu numai de numarul total de puncte.\r\n\r\nh2. kD-Tree\r\n\r\n_kD-Tree_ este o structura de date care organizeaza o multime de puncte in $k$ dimensiuni, imparte spatiul in semispatii astfel ca fiecare nod din arbore reprezinta un paralelipiped si contine in el un punct. Noi suntem interesati de arbori 2D in special. Pentru cazul 2D, primului nod ii va fi asociat intreg planul. Se duce o linie verticala de abscisa $x$ care imparte planul in doua si punctele in doua multimi de cardinal egal. Subarborele din stanga va contine toate punctele din stanga acestei drepte verticale, iar subarborele din dreapta va contine toate punctele din dreapta acestei drepte verticale. Radacinei arborelui din stanga ii va fi asociat semiplanul stang determinat de dreapta verticala, si va contine punctul median dintre punctele din semiplanul stang sortate dupa $y$. Astfel, la nivel impar punctele vor fi mediane din sirul punctelor sortat dupa $x$, iar la nivel par punctele vor fi mediane din sirul punctelor sortat dupa $y$. Pentru mai multe dimensiuni ale spatiului ciclam dupa $d{~1~}$, $d{~2~}$,..., $d{~n~}$ si apoi iar $d{~1~}$ ca sa punem elementul median pe nivelul curent. In cazul 2D complexitatea crearii unui asemenea arbore e $O(n log n)$. Pentru a raspunde la query-uri pe un dreptunghi coboram in arbore in fii pentru care domeniul asociat se intersecteaza cu dreptunghiul nostru. Se poate demonstra ca aceasta operatie are timpul de executie in cel mai rau caz $O(sqrt(n))$.\r\n\r\np=. !cautari-ortogonale?pic7.jpg!\r\n\r\nUnele implementari tin puncte numai in frunze, si in nodurile care nu sunt frunze tin numai informatia despre coordonata dreptei care imparte regiunea in doua. Dimensiunile regiunii asociate unui nod pot fi tinute in nod sau pot fi calculate la fiecare operatie pentru a salva spatiu. O alta idee pentru a mari viteza de cautare in arbori kD ar fi sa nu alegem ciclic pe ce directie impartim punctele, ci sa alegem la fiecare pas directia pe care punctele sunt cele mai imprastiate.\r\n\r\nPseudocod pentru constructie:\r\n\r\n== code(cpp) |\r\nNod-kD construiesteArbore(puncte, directie) \r\n   daca puncte e vida returneaza null\r\n   altfel daca puncte contine un singur punct returneaza Nod-kD(puncte[0])\r\n   altfel\r\n      x = gasesteMediana(puncte, directie) \r\n      // aceasta functie poate fi implementata folosind selectie randomizata\r\n     stanga = puncte cu directie <= x;\r\n     dreapta = puncte cu directie > x;\r\n     t = Nod-kD(x)\r\n     t.stanga = construiesteArbore(stanga, (directie + 1) % 2);\r\n     t.dreapta = construiesteArbore(dreapta, (directie + 1) % 2);\r\n     returneaza t\r\n==\r\n\r\nPentru a nu face de fiecare data selectie randomizata putem pleca de la inceput cu doua liste de puncte, una sortata dupa $x$ si cealalta sortata dupa $y$.\r\n\r\nPseudocod pentru cautare pe domeniu ortogonal (Notam cu Q un dreptunghi):\r\n\r\n== code(cpp) |\r\npuncte cauta(nod-kD, Q)\r\n  daca Q intersectat cu Nod-kD.domeniu e vid atunci returneaza multimea vida\r\n  altfel daca Nod-kD.domeniu e inclus in Q atunci \r\n                returneaza punctele din subarborele cu radacina nod-kD\r\n  altfel returneaza cauta(nod-kD.stanga, Q) reunita cu cauta(nod-kD.dreapta, Q)\r\n==\r\n\r\nSa vedem care e complexitatea operatiei **cauta**. Nodurile care sunt total in afara dreptunghiului sau total inauntrul dreptunghiului Q pot cel mult fi de doua ori mai multe decat nodurile care intersecteaza dreptunghiul Q intr-o cautare, pentru ca vizitarea unui nod total in afara dreptunghiului sau unui nod dinauntrul dreptunghiului a pornit de la un nod al carui domeniu intersecteaza dreptunghiul. Pentru analiza ne putem ocupa numai de noduri ale caror domenii intersecteaza dreptunghiul. Pentru a obtine o limita superioara a numarului de zone intersectate putem considera numarul maxim de zone intersectate de o latura a dreptunghiului si sa inmultim acel numar cu patru. Pentru a mai simplifica analiza putem considera nu numarul maxim de zone intersectate de un segment, ci numarul maxim de zone intersectate de o dreapta verticala sau orizontala. Consideram o dreapta verticala, pentru un nod, daca directia de impartire a zonei asociate e verticala atunci dreapta verticala taie sau zona fiului stang sau zona fiului drept, dar nu pe amandoua deodata. Daca dreapta verticala nu intersecteaza zona asociata unui fiu atunci nu va mai intersecta zona nici unui urmas al fiului. In caz contrar intersecteaza ambii fii. Daca coboram la nivelul nepotilor cel mult patru noduri sunt intersectate. In cel mai rau caz intersectam domeniul reprezentat de radacina si putem intersecta cel mult $2^i^$ noduri pana la nivelul $2i$. Deci in total maxim $O(sqrt(n))$ noduri sunt parcurse la o operatie cauta.\r\n\r\nAvantajul arborilor kD ar fi usurinta in implementare si spatiul de memorie $O(n)$ folosit, dezavantajul ar fi timpul $O(sqrt(n))$ pentru cautare, dar avand in vedere ca arborii de intervale sau arborii indexati binar au complexitatea $O(log^2^ n)$ la cautare, timpii sunt comparabili.\r\n\r\nArborii de intervale au fost prezentati in articolul [1] deci nu mai insist asupra lor.\r\n\r\nArborii indexati binar sunt si ei folositori si au fost prezentati [2]. Dezavantajul arborilor indexati binar este ca ei pot fi folositi la numarare si la sume, dar nu la aflarea minimului sau maximului pe un interval. Singura posibilitate cand maximul sau minimul pot fi aflate este atunci cand intervalele pe care facem cautarea sunt nemarginite in sus sau in jos. In schimb la toate structurile despre care am discutat  pana acuma putem raspunde in timp subliniar la intrebari despre maxim si minim. Alt dezavantaj este ca daca trebuie sa pastram in spatiul cu $n$ dimensiuni de la $0$ pana la $N$ atunci trebuie sa folosim $N^n^$ spatiu, insa acest neajuns il putem evita folosind impreuna cu arborele indexat binar si o tabela de dispersie. Facand aceasta folosim numai $O(nr log^2^ N)$ spatiu pentru $nr$ puncte in plan inserate in structura, pentru cazul unidimensional folosim $O(nr * log N)$ spatiu. Daca folosim structura _hash_map_ sau _map_ din STL obtinem o implementare foarte simpla si memoria folosita este putina.\r\n\r\nIn continuare, pentru exemplificarea folosirii stucturilor de date voi prezenta niste probleme care voiam sa le propun la concursul de programare Algoritmus, din pacate acest concurs s-a incheiat prematur pentru ca sponsorul nu a mai continuat finantarea premiilor pentru concurenti.\r\n\r\nh2. Problema 1\r\n\r\nSe dau $1<=n<=30 000$ triunghiuri dreptunghice in plan, ele se dau prin trei parametrii $x,y,m$. Varfurile triunghiurilor o sa fie ( $x, y$ ) ( $x + m, y$ ) si ( $x, y + m$ ). Sa se determine cate perechi de triunghiuri exista, astfel ca primul triunghi din pereche sa fie inclus in al doilea triunghi. ( $0<= x, y, m <= 60 000$ )\r\n\r\nTimp de executie: $0.5 secunde$\r\n\r\nTriunghiul determinat de parametrii ( $x{~1~},y{~1~},m{~1~}$ ) e inclus in triunghiul determinat de parametrii ( $x{~2~},y{~2~},m{~2~}$ ) daca si numai daca $x{~2~} <= x{~1~}$, $y{~2~} <= y{~1~}$ si $x{~1~} + y{~1~} + m{~1~} <= x{~2~} + y{~2~} + m{~2~}$. Deci daca facem transformarea ( $x{~1~}, y{~1~}, m{~1~}$ ) -> ( $x{~1~}, y{~1~}, -x{~1~} - y{~1~} - m{~1~}$ ) si notam cu ( $x{~1~}, y{~1~}, z{~1~}$) atunci avem ca triunghiul reprezentat de ( $x{~1~}, y{~1~}, z{~1~}$ ) e inclus in triunghiul reprezentat de ( $x{~2~}, y{~2~}, z{~2~}$ ) daca si numai daca $x{~2~} <= x{~1~}, y{~2~} <= y{~1~}, z{~2~} <= z{~1~}$. Astfel am transformat triunghiurile dreptunghice in puncte din spatiul 3D si perechile de triunghiuri cerute in problema in relatii de dominanta, pentru a afla cate triunghiuri includ triunghiul  reprezentat de ( $x{~1~}, y{~1~}, z{~1~}$ ) trebuie sa vedem cate puncte sunt cuprinse in $(-oo, x{~1~}] x (-oo, y{~1~}]  x (-oo, z{~1~}]$. Pentru a face acest lucru am putea folosi un arbore de intervale 3D care ocupa O(n log^2^ n) spatiu si are complexitatea $O(log^3^ n)$ pentru query, dar observatia banala ca putem sorta sirul triunghiurilor dupa coordonata $z$ si abia apoi sa rezolvam problema ne va ajuta. Vom folosi un arbore de intervale 2D sau un _quadtree_ sau un 2D tree ({_kD tree_}) in care vom insera ( $x{~i~},y{~i~}$ ) in ordinea data de $z{~i~}$. Evident ca la momentul inserarii lui ( $x{~i~},y{~i~}$ ) in structura de date toate punctele deja inserate ( $x{~j~},y{~j~}$ ) vor proveni din un punct ( $x{~j~}, y{~j~}, z{~j~}$ ) cu $z{~j~} <= z{~i~}$, deci nu avem nevoie sa pastram coordonata $z$ a punctelor pentru comparatie. In cazul care implementam problema folosind {_kd trees_} vom avea complexitatea $O(n log n)$ la crearea structurii de date si $O(sqrt(n))$ pentru query, memoria folosita va fi $O(n)$, complexitatea totala a algoritmului $O(n log n + n sqrt(n))$. Daca folosim arbore de intervale atunci vom folosi $O(n log n)$ timp la crearea structurii si vom avea $O(log^2^ n)$ pentru query, memoria folosita va fi $O(n log n)$, complexitatea totala va fi $O(n log n + n log^2^ n)$. Daca folosim tehnica numita \"fractional cascading\" pentru arbori de intervale atunci reducem complexitatea la $O(n log n)$ pentru intreaga problema.\r\n\r\nO alta abordare a problemei bazata tot pe transformarea din triunghiuri in puncte in plan ar fi bazata pe metoda divide si stapaneste. Se impart punctele in doua multimi de dimensiuni egale dupa coordonata $z$, $n/2$ puncte au $z<=ZMID$ si celelalte $n-n/2$ puncte au $z>=ZMID$, dupa ce s-au numarat relatiile de dominanta din cele doua submultimi, trebuie sa gasim numarul de relatii de dominanta in care un punct e in prima multime si al doilea e in a doua multime. Evident oricare ar fi  ( $x{~1~},  y{~1~}, z{~1~}$ ) in prima multime si ( $x{~2~}, y{~2~}, z{~2~}$ ) in a doua multime avem ca $z{~1~} <= ZMID <= z{~2~}$ deci mai trebuie sa verificam doar daca $x{~1~} <= x{~2~}$ si $y{~1~} <= y{~2~}$. Daca tinem sirul sortat dupa $y$ si folosim un arbore indexat binar pentru a insera coordonate $x$ in arbore atunci cand in sirul interclasat ordonat dupa $y$ intalnim un punct din prima multime inseram $x{~1~}$ in arborele indexat binar iar cand intalnim un punct din a doua multime atunci intrebam cate coordonate $x<=x{~2~}$ au fost deja inserate in arborele indexat binar daca $x <= x{~2~} => si y <= y{~2~}$ pentru ca a fost inserat in multime mai devreme, in total faza stapaneste a algoritmului ia $O(n log n)$ timp pentru sortarea dupa $y$ si $O(n log n)$ pentru inserarea in arborele indexat binar deci in totalitate algoritmul dureaza $O(n log^2^ n)$.\r\n\r\nA doua metoda poate fi extinsa la numararea incluziunilor de dreptunghiuri. Dreptunghiurile se vor transforma in puncte in 4D, iar cand vom fi la pasul de stapaneste din algoritm vom sorta dupa $z$ si ne va ramane sa determinam cate perechi $x{~1~} <= x{~2~}$ si $y{~1~} <= y{~2~}$, aceasta o vom rezolva folosind un arbore de intervale rafinat prin \"fractional cascading\", si astfel s-a pastrat complexitatea pasului stapaneste la $O(n log n)$, deci complexitatea totala pentru dreptunghiuri ar fi $O(n log^2^ n)$. Problema cu dreptunghiuri s-a dat la regionala ACM cu $N = 5 000$, atunci o singura echipa a rezolvat problema si solutia lor era $O(N^2^)$.\r\n\r\nh2. Problema 2\r\n\r\nSe dau doua multimi de puncte de coordonate intregi in plan cu $N$ si $M$ puncte. Punctele din prima multime sunt colorate rosu si punctele din a doua multime sunt colorate albastru. Se cere sa se determine o pereche de puncte, unul rosu si unul albastru, intre care distanta manhattan e minima. Coordonatele punctelor sunt cuprinse intre $0$ si $60 000$. $1 <= M <= 30 000$ si $1 <= N <= 30 000$\r\n\r\nTimp de executie: $0.5 secunde$\r\n\r\nPentru fiecare punct rosu vrem sa stim punctul albastru cel mai apropiat, impartim planul in 4 cadrane cu originea in punctul rosu, vrem sa aflam punctul albastru cel mai apropiat din fiecare cadran. Pentru un punct rosu si un punct albastru din cadranul 1 distanta dintre ele e $(x{~a~} - x{~r~}) + (y{~a~} - y{~r~})$ pentru ca $x{~r~} < x{~a~}$ si $y{~r~} < y{~a~}$, regrupand avem $(x{~a~} + y{~a~}) - (x{~r~} + y{~r~})$. Deci vrem sa gasim punctul $(x{~a~}, y{~a~})$ cu proprietatea ca $x{~r~} <= x{~a~}$ si $y{~r~} <= y{~a~}$ si suma $x{~a~} + y{~a~}$ e minima. O solutie ar fi sa folosim un arbore de intervale bidimensional, dar observam ca ambele margini pe domeniul pe care cautam sunt infinite, deci am putea sorta sirurile de puncte descrescator dupa $x$. Cand punctul $(x,y)$ e albastru inseram in arborele indexat binar la pozitia $y$ cheia $x+y$, iar cand punctul este rosu facem un query al elementului minim pe intervalul $[y, +oo)$ (evident toate punctele deja inserate in arbore au ordonata mai mare decat $y$-ul actual). Facem la fel pentru fiecare din cele patru cadrane.\r\n\r\nh2. Problema 3 \r\n\r\nSe dau $1<= N <= 50 000$ de dreptunghiuri in plan si se cere sa se determine numarul de perechi de dreptunghiuri care se intersecteaza. Coordonatele varfurilor dreptunghiurilor sunt intregi si cuprinse intre $0$ si $60 000$.\r\n\r\nTimp de executie: $0.5 secunde$\r\n\r\np=. !cautari-ortogonale?pic6.jpg!\r\n\r\nRezolvam aceasta problema folosind paradigma liniei de baleiere. Sortam dreptunghiurile dupa coordonata $x$ a coltului din dreapta. Dupa cum observam in figura alaturata exista trei pozitii relative ale doua dreptunghiuri care se intersecteaza. Cazurile 1, 2, 4, 5 si 6 se reduc la intersectia laturii verticale din stanga a unui dreptunghi cu latura orizontala de sus a celuilalt dreptunghi, deci acest gen de intersectii pot fi numarate numarand intersectiile intre segmentele orizontale si verticale (aceasta problema a fost deja tratata in articolul [1]). Mai raman cazurile 3 si 7 in care coltul din stanga sus al celui de al doilea dreptunghi e in interiorul primului, acest tip de query il rezolvam cu ajutorul arborilor de intervale, intai inseram in structura toate punctele din dreapta sus ale dreptunghiurilor si apoi pentru fiecare dreptunghi facem query pentru a afla numarul de puncte din interiorul lui.\r\n\r\nh2. Problema 4\r\n\r\nSe dau $1<= N <= 60 000$ de dreptunghiuri in plan, sa se determine un punct care are proprietatea ca este inclus in un numar maxim de dreptunghiuri. Coordonatele varfurilor dreptunghiurilor sunt cuprinse intre $0 si 60 000$.\r\n\r\nTimp de executie: $0.5 secunde$\r\n\r\nReducem problema din plan pe dreapta, daca se da o multime de segmente pe o linie cum determinam un punct care e  acoperit de numar maxim de segmente? O sortare a segmentelor dupa primul capat ar rezolva problema, dar solutia aceasta nu e flexibila daca vrem sa adaugam sau sa stergem segmente. Vom folosi un arbore de intervale unidimensional. Numim acoperire canonica a unui interval, intervalele asociate lui in arborele de intervale (stim din articolul [1] ca numarul acestor intervale este maxim $log n$). In nodurile arborelui de intervale pastram doua atribute: $nr$ si $max$, $nr$ reprezinta numarul de intervale pentru care intervalul asociat nodului face parte din acoperirea canonica, iar $max$ reprezinta intersectia de intervale nevida inclusa strict in intervalul asociat nodului, cu cardinal maxim. Pentru un nod $x$, $x.max$ e egal cu maximul dintre $x.stanga.max + x.stanga.nr$ sau $x.dreapta.max + x.dreapta.nr$. La inserarea sau stergerea din arbore a unui interval avem grija la actualizarea atributelor $max$ si $nr$. Pentru a determina numarul maxim de segmente ce se intersecteaza putem returna $radacina.nr + radacina$.\r\n\r\nAcum ca putem rezolva problema pe dreapta in mod dinamic sa revenim la problema initiala in plan, vom folosi din nou paradigma liniei de baleiere. Folosim numai segmentele verticale si le ignoram pe cele orizontale. Sortam segmentele verticale dupa $x$ si cand intalnim un segment vertical ce a fost initial latura stanga de dreptunghi atunci adaugam acest segment in arborele de intervale si actualizam daca e nevoie cardinalul intersectiei maxime, daca intalnim un segment vertical care initial era latura din dreapta a unui dreptunghi atunci scoatem acest segment din arborele de intervale. Solutia problemei va avea complexitate $O(n log n)$, $O(n log n)$ in faza de sortare a segmentelor si $O(n log n)$ in faza de inserare in arbore si stergere din arbore.\r\n\r\nh2. Alte probleme propuse spre rezolvare\r\n\r\n* \'Evantai\':problema/evantai\r\n* \'Schi\':problema/schi\r\n* \'Cutii\':problema/cutii\r\n* \'Order\':problema/order\r\n* \'Nestable\':http://www.topcoder.com/stat?c=problem_statement&pm=1986\r\n* \'Mobiles\':http://olympiads.win.tue.nl/ioi/ioi2001/contest/day1/mobiles/mobiles.pdf\r\n* \'ZJU 2112\':http://acm.zju.edu.cn/show_problem.php?pid=2112\r\n* \'ZJU 2118\':http://acm.zju.edu.cn/show_problem.php?pid=2118\r\n* \'ZJU 2119\':http://acm.zju.edu.cn/show_problem.php?pid=2119\r\n* \'Wys\':http://www.oi.edu.pl/php/show.php?ac=e180811&module=show&file=zadania/oi11/wys\r\n* \'MIPT 43\':http://acm.mipt.ru/judge/bin/problems.pl?problem=043&sort=ID&lang=en\r\n\r\nh2. Bibliografie\r\n\r\n# \'Arbori de intervale (\"segment trees\") si aplicatii in Geometria Computationala, Dana Lica\':arbori-de-intervale\r\n# \'Arbori Indexati Binar, Mihai Scortaru, GInfo\':http://www.ginfo.ro/revista/13_1/focus.pdf \r\n# \'Kd-Trees, Andrew W. Moore\':http://www.autonlab.org/autonweb/14665/version/2/part/5/data/moore-tutorial.pdf?branch=main&language=en',7271,'public',3692,NULL),('utilizator/alexandru.mosoi','Profil alexandru.mosoi','2007-08-05 10:52:56','2007-08-05 10:52:56','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6694,'public',NULL,NULL),('template/autor-necunoscut','template/autor-necunoscut','2007-08-07 21:35:58','2008-02-04 21:01:12','table{margin:0.5em auto;}. |={background-color:#bedbf4}. !<template/autor-necunoscut?unknown.png! _Din pacate nu am reusit sa identificam autorul acestei probleme._\r\n\'*Intra aici*\':implica-te/extinde-arhiva/autor-necunoscut _pentru a afla cum poti sa ne ajuti_ |',1,'public',NULL,NULL),('runda/summer2007-runda2/clasament','Clasament summer2007-runda2','2007-08-07 21:52:10','2007-08-07 21:52:10','h1. Clasament ==roundparam(round_id=\"summer2007-runda2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer2007-runda2\")==',961,'round: summer2007-runda2',NULL,NULL),('blogideas','blogideas','2007-08-08 00:15:20','2007-08-08 00:15:20','h2. Intrebari pt programatori bazati sau fosti olimpici\r\n\r\n* cele mai interesante 5 carti\r\n* limbajul de programare preferat\r\n* editorul preferat\r\n* cum ai inceput cu informatica\r\n* siteuri preferate\r\n* bloguri preferate\r\n* proiectul mai interesant la care ai lucrat\r\n* planuri de viitor\r\n* alte pasiuni inafara de informatica\r\n* algoritmul preferat\r\n* vreun warstory interesant?\r\n* de ce ai ales scoala pe care ai ales-o\r\n* tii vreo problema de concurs minte, vre-un brainteaser \r\n* tehnica de programare / jmen / tehnologie\r\n* best practice\r\n* cum ataci o problema un proiect prin ce faze treci\r\n* ce structuri de date folosesti, algoritmi\r\n* sfaturi pt cei ce vreau sa inceapa cu programarea\r\n* sistem de operare\r\n* cum lucrezi? in salturi sau putin in fiecare zi\r\n* cat timp petreci in fata calculatorului\r\n* inspiratie/transpiratie, factor motivator\r\n* ba da voi cum va distrati\r\n* muzica filme\r\n* ce faci in primele minute cand ajungi la munca/servici\r\n* cum iti mentii cunostintele la zi\r\n* gasirea unui bug, metode de atac\r\n* mod de munca, intervale compacte, iteratii directe, tehnologii noi sau tehnici bine cunoscute\r\n* impartirea timpului\r\n\r\ntop 5 research papers\r\n\r\ntop 5 programming contest problems\r\n\r\nwebsite statistics',58,'public',NULL,NULL),('dinic','Algoritmul lui Dinic','2007-08-05 10:57:35','2008-01-29 09:43:49','h1. Algoritmul lui Dinic\r\n\r\n(Categoria _Grafuri_, autor(i) _Alexandru Mosoi_)\r\n\r\nTODO:\r\n* ancore la pasi\r\n* poze si exemplificare\r\n* analiza complexitatii\r\n\r\nh2. Introducere\r\n\r\nAcest articol presupune o familiarizare anterioara cu grafuri si retele de transport. Pentru a elimina neclaritati vom da urmatoarea definitie: _O **retea de transport** este un graf orientat in care avem un nod **sursa**, un nod **destinatie**, iar fiecarei muchii ii este asociata o capacitate superioara_. Problema este clasica: cat flux putem baga de la sursa la destinatie fara a depasi capacitatea fiecarei muchii. Algoritmul pe care probabil deja il cunoasteti poarta numele \"Edmonds-Karp\":http://en.wikipedia.org/wiki/Edmonds-Karp_algorithm si are complexitatea O(N*M*M). Algoritmul **Dinic**, prezentat in acest articol, are complexitatea O(N*N*M). Am folosit notatiile obisnuite: $N$ - numarul de noduri, $M$ - numarul de muchii.\r\n\r\nh2. Exemplu\r\n\r\nPentru o mai buna intelegere a articolului vom lucra cu urmatorul exemplu (imagine preluata de pe \"Wikipedia\":http://en.wikipedia.org):\r\n\r\n!dinic?Dinic_flow_example_1.png!\r\n\r\nh2. Descriere\r\n\r\nh3. Pasul 1\r\n\r\nAlgoritmul Edmonds-Karp presupune gasirea, cat timp exista, a unui drum de crestere in reteaua reziduala si marirea fluxului total. Evident, la fiecare pas pot exista mai multe drumuri de crestere (care au luO observatie importanta este ca la fiecare pas in reteua reziduala exista mai multe drumuri de crestere de lungime minima.\r\n\r\nPrimul pas este sa construim din reteua reziduala un graf orientat aciclic in care sa regasim toate drumurile de lungime minima de la sursa la destinatie. Evident in acest dag toate muchiile vor avea capacitatea cel putin 1. Cum construim acest graf? Destul de simplu. Modificam putin bfs-ul de la Edmonds-Karp precum urmeaza. Pentru fiecare nod, calculam distanta (ca numar de muchii) de la sursa pana la el. O muchie $(u, v)$ cu capacitatea $c &gt; 0$ in reteaua reziduala este adaugata la graful construit doar daca distanta de la sursa la $u$ _plus_ $1$ este egala cu distanta de la sursa la nodul $v$ (pe scurt, daca muchia $(u, v)$ apartine unui drum de lungime minima de la sursa la destinatie).\r\n\r\nIn exemplul de mai jos noul graf este construit odata cu parcurgerea in latime. _flow_ reprezinta matricea de adiacenta pentru reteaua reziduala, iar _edges_ memoreaza pentru fiecare nod lista de vecini in graful construit (atentie: muchiile inverse nu apar). \r\n\r\n== code(c) |\r\nwhile (!que.empty()) {\r\n	int node = que.front();\r\n	que.pop();\r\n\r\n	if (node == N-1)\r\n		break;\r\n\r\n	for (int i = 0; i < N; ++i) {\r\n		if (flow[node][i] == 0)\r\n			continue;\r\n\r\n		if (dist[i] == -1) {\r\n			que.push(i);\r\n			dist[i] = dist[node]+1;\r\n			edges[node][++edges[node][0]] = i;\r\n		} else if (dist[i] == dist[node]+1) {\r\n			edges[node][++edges[node][0]] = i;\r\n		}\r\n	}\r\n}\r\n==\r\n\r\nNota: Scriind acest articol, mi-am dat seama ca se putea un pic mai simplu, fara sa tin cont de distanta. Cand se expandeaza nodul _u_, muchia _(u, v)_ se adauga la graf doar daca _v_ este nevizitat. Un nod este **vizitat** daca a fost expandat (scos din coada).\r\n\r\nh3. Pasul 2\r\n\r\nUrmatorul pas este sa bagam flux in graful creat (subraf a retelei reziduale). Acesta operatie se poate face usor cautand drumuri de crestere si pompand flux pe aceste drumuri pana cand nu mai gasim nici un drum. Dupa ce s-a gasit un drum *NU* se face o reactualizare a formei grafului creat la pasul 1, ci doar asupra capacitatilor muchiilor.\r\n\r\nObservatie: daca am gasit un drum de la sursa la destinatie atunci fluxul maxim pe care il pot pompa prin acest drum de crestere este maximul dintre capacitatile muchiilor de pe drum.\r\n\r\nO imbunatatire semnificativa este sa se tina cont ca unele drumuri au un inceput comun. Sa presupunem drumurile $sursa -> ...(drum)... -> nod -> ...(drum 1)... -> destinatie$ si $sursa -> ...(drum)... -> nod -> ...(drum 2)... -> destinatie$. Cele doua drumuri au in comun portiunea $sursa -> ...(drum)... -> nod$. Sa cautam drumurile cu un DFS recursiv. Daca drumurile sunt cautate cu un DFS recursiv, atunci dupa ce se ajunge in $nod$ cu posibilitatea de a pompa maxim $C$ flux, si dupa ce introduc $B$ flux pe primul drum, pe al doilea drum mai pot baga cel mult $C-B$ flux.\r\n\r\n== code(c) |\r\nint do_df(int node, int cap) {\r\n	if (cap == 0)\r\n		return 0;\r\n	if (node == D)\r\n		return cap;\r\n\r\n	int bag = 0;\r\n	for (int i = 1; i <= edges[node][0]; ++i) {\r\n		const int next = edges[node][i];\r\n		if (flow[node][next] == 0)\r\n			continue;\r\n\r\n		const int r = do_df(next, min(cap-bag, flow[node][next]));\r\n		if (r) {\r\n			flow[node][next] -= r;\r\n			flow[next][node] += r;\r\n			bag += r;\r\n		}\r\n	}\r\n\r\n	return bag;\r\n}\r\n==\r\n\r\nFunctia do_df() pompeaza fluxul maxim in graful construit la **pasul 1**. Datorita formei particulare a grafului si ca forma sa nu se schimba dupa fiecare drum de crestere algoritmul nu are deficienta intalnita la algoritmul Ford-Fulkerson. \r\n\r\nh3. Pasul 3\r\n\r\nCat timp mai exista drum de crestere (sau fluxul introdus la pasul anterior este strict pozitiv) reiau algoritmul de la **Pasul 1**.\r\n\r\n\r\nh2. Comentarii\r\n\r\n==user(user=\"vlad_popa\" type=\"tiny\")== : Nu stiu de voi, dar mie mi se pare algoritmul foarte folositor, mai ales in cazuri in care trebuie sa implementezi un algoritm de flux in care ai limite destul de mari... Bravo Alex and... Keep up the good work!',15,'public',NULL,NULL),('summer-challenge-2007/clasament/runda-3','Clasament Summer Challenge 2007, Runda 3','2007-08-09 08:57:40','2007-08-10 19:26:10','h1. Clasament \'Summer Challenge 2007, Runda 3\':summer-challenge-2007/runda-3\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2007\r\n* \'Runda 1\':summer-challenge-2007/runda-1\r\n* \'Runda 2\':summer-challenge-2007/runda-2\r\n*(active) \'Runda 3\':summer-challenge-2007/runda-3\r\n*(active) \'Clasament\':summer-challenge-2007/clasament\r\n\r\n== Rankings(rounds=\"summer2007-runda3\") == ',1,'protected',NULL,NULL),('runda/summer2007-runda3/clasament','Clasament summer2007-runda3','2007-08-10 14:00:55','2007-08-10 14:00:55','h1. Clasament ==roundparam(round_id=\"summer2007-runda3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer2007-runda3\")==',961,'round: summer2007-runda3',NULL,NULL),('summer-challenge-2007/solutii/runda-2','Solutii Summer Challenge, Runda 2','2007-08-10 07:48:31','2009-06-09 15:05:26','h1. Solutii Runda 2\r\n\r\nh2. \'Euclid\':problema/euclid\r\n\r\nProblema se poate rezolva calculand gcd-ul patratelor ce au lungimile laturilor puteri ale lui $2$. Astfel tinem o matrice $V[0..LOGM][0..LOGN][1..M][1..N]$, unde $V[di][dj][i][j]$ reprezinta gcd-ul numerelor din dreptunghiul cu colturile in $(i, j), (i + 2^di^ - 1, j + 2^dj^ - 1)$. Aceasta matrice se poate calcula cu usurinta in $O(logM * logN * M * N)$ incepand cu puterile mai mici ale lui $2$, in stil bottom-up. Putem apoi vedea in $O(1)$ care este gcd-ul elementelor din dreptunghiul cu colturile in $(i, j), (i + w - 1, j + h - 1)$. Pentru aceasta, mai intai sa luam $di = [log h]$ si $dj = [log w]$. Numarul cautat este $gcd(V[di][dj][i][j], V[di][dj][i][j + w - 2^dj^], V[di][dj][i + h - 2^di^][dj], V[di][dj][i + h - 2^di^][j + w - 2^dj^ ])$. Nu mai ramane decat sa luam maximul dintre toate dreptunghiurile posibile. Aceasta solutie foloseste $O(logN * logM * N * M)$ spatiu si timp.\r\n\r\nDesi solutia de mai sus ar fi obtinut punctaj maxim, problema se poate rezolva si mai elegant. Astfel, in loc sa tinem tabela cu toate puterile lui $2$ putem calcula $A[1..M][1..N]$ unde $A[i][j]$ e gcd-ul elementelor din dreptunghiul cu colturile in $(i, j), (i, j + w - 1)$. Aceasta matrice poate fi calculata in $O(logN * N * M)$ folosind acelasi rationament ca mai sus. De asemenea, trebuie sa mai calculam o matrice $B[1..M][1..N]$ unde $B[i][j]$ tine gcd-ul elementelor din $A$ din dreptunghiul $(i, j), (i + h - 1, j)$. Aceasta matrice se calculeaza analog cu matricea A. Rezultatul este $max(B[i][j])$, pentru toate perechile $i, j$ a.i $i + h - 1 &le; M$ si $j + w - 1 &le; N$. Acest algoritm ruleaza in $O((logN + logM) * N * M)$ timp si $O(N * M)$ memorie.\r\n\r\nh2. \'Gbc\':problema/gbc\r\n\r\nSunt in total combinari de $k$ luate cate $n$ in care putem alege nodurile multimii {$A$}. Pentru fiecare din aceste modalitati se face un $AND$ intre toate liniile din matricea de adianceta corespunzatoare nodurilor alese. Nodurile ramase cu $1$ in urma {$AND$}-ului sunt noduri care pot fi alese in multimea {$B$}, avand drumuri catre toate nodurile din multimea {$A$}. Pentru o selectie a multimii $A$ vom avea combinari de $X$ luate cate $M$ posibilitati de a alege multimea {$B$}, unde $X$ este numarul de $1$ ramas in urma {$AND$}-ului. Matricea de adiacenta se va retine codificata pe biti, deci {$AND$} pe linii se reduce la {$AND$} intre numere. Pentru a numara usor cati de $1$ avem intr-un numar se preproceseaza {$nbit[i]$} numarul de biti ai numarului $i$ pentru toate numerele pana la {$2^15^$}. Numerele noastre fiind pana la {$2^30^$} numarul de biti se va calula pe bucati: {$nbit[i&32767] + nbit[i>>15]$} ( $&$ este operatia {$AND$}, $>>$ este operatia de shiftare).\r\n\r\nh2. \'Hypernet\':problema/hypernet\r\n\r\nVom sorta planetele crescator, in functie de numarul de locuitori. Practic, vom considera o renumerotare a planetelor astfel incat {$Q{~1~} &le; Q{~2~} &le; ... &le; Q{~N~}$}. Sa calculam acum o limita inferioara pentru costul  retelei cerute. Vom defini costul unei muchii ({$i,j$}) ca fiind valoare {$Q{~i~}+Q{~j~}$}. Reteaua consta dintr-un arbore avand $N-1$ muchii si inca {$K-(N-1)$} muchii suplimentare. Vom privi arborele ca avand radacina in nodul {$N$}. In acest fel, fiecare nod de la $1$ la $N-1$ va fi legat de o muchie catre tatal lui. Aceasta muchie are un cost de cel mult {$Q{~i~}+Q{~N~}$}. Asadar, o limita superioara pentru costul arborelui este {$CARB=Q{~1~} + Q{~N~} + Q{~2~} + Q{~N~} + ... + Q{~N-1~} + Q{~N~} = (Q{~1~} + ... + Q{~N-1~}) + (N-1) * Q{~N~}$}. O limita superioara pentru costul tuturor celor $K$ muchii este data de $CARB$ + costul celor mai mari $K-(N-1)$ muchii din cele ramase (fara muchiile {$i - N$}). Sa consideram aceasta limita superioara pentru costul celor $K$ muchii ale retelei ca fiind {$CK$}.\r\n\r\nAcum, costul retelei are o limita inferioara data de {$CK + 2 * (suma_totala_a_costurilor_muchiilor - CK) = 2 * suma_totala_a_costurilor_muchiilor - CK$}. Este clar ca doar $K$ perechi de noduri au distanat $1$ intre ele, celelalte perechi avand distanta de cel putin {$2$}. Si din formula se observa ca este de dorit sa avem un cost cat mai mare pentru cele $K$ muchii alese ca facand parte din retea.\r\n Cu aceste considerente, reteaua va fi reprezentata  de muchiile {$(1,N), (2,N), .., (N-1,N)$} si cele mai mari {$K-(N-1)$} muchii din cele ramase. Aceasta retea are distanta $2$ intre oricare pereche de noduri care nu sunt legate direct si are costul egal chiar cu limita inferioara precizata mai sus.\r\n\r\n\r\nAsadar, problema ramasa este aceea de a alege cele mai mari {$K-(N-1)$} muchii avand ambele capete in multimea {${1,2,..,N-1}$}. Doua variante simple au complexitate $O(N*K)$ si {$O(K*logN)$}, insa vor depasi limita de timp.\r\n\r\nO solutie acceptabila ar consta in a cauta binar valoarea celei mai mici muchii din cele $K-(N-1)$ pe care mai dorim sa le alegem si sa calculam in $O(N)$ cate perechi de noduri au costul mai mare sau egal cu valoarea fixata in cautarea binara. Vom alege cea mai mare valoare pentru care exista {$X >= K-(N-1)$} muchii cu cost mai mare sau egal cu ea.\r\n Daca {$X=K-(N-1)$}, am gasit muchiile cautate. Daca $X>K-(N-1)$ este din cauza ca exista prea multe muchii cu acelasi cost maxim gasit. In aceasta situatie, putem scadea din costul total al muchiilor gasite {$costul_maxim_gasit * (X - (K - (N-1)))$} pentru a obtine costul total al celor mai mari $K-(N-1)$ muchii.\r\n\r\nSolutia finala afisata va fi {$CK + 2 * (suma_totala_a_costurilor_muchiilor - CK)$}, unde $CK$ a fost definit anterior. Complexitatea algoritmului este {$O(N * log(N) * log(CMAX))$}.\r\n',5748,'public',NULL,NULL),('summer-challenge-2007/clasament/general','Clasament General Summer Challenge 2007','2007-08-10 16:19:02','2007-08-10 16:28:38','h1. Clasament \'Summer Challenge 2007\':summer-challenge-2007/\r\n\r\n== Rankings(rounds=\"summer2007-runda1 | summer2007-runda2 | summer2007-runda3\") ==',4772,'public',NULL,NULL),('summer-challenge-2007/runda-3','Summer Challenge 2007, Runda 3','2007-08-09 08:56:34','2007-08-10 19:24:35','h1. Summer Challenge 2007, Runda 3\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2007\r\n* \'Runda 1\':summer-challenge-2007/runda-1\r\n* \'Runda 2\':summer-challenge-2007/runda-2\r\n*(active) \'Runda 3\':summer-challenge-2007/runda-3\r\n* \'Clasament\':summer-challenge-2007/clasament\r\n\r\nRunda se va desfasura Duminica, 12 august, la ora {*10^00^*} si va dura *3h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"summer2007-runda3\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"summer2007-runda3\" score=\"1\")==\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 3\':summer-challenge-2007/clasament/runda-3\r\n\r\nh2. Organizatori\r\n\r\n* ==User(user=\"ditzonec\" type=\"tiny\")==\r\n* ==User(user=\"silviug\" type=\"tiny\")==\r\n* ==User(user=\"cosmin\" type=\"tiny\")==\r\n* ==User(user=\"danielp\" type=\"tiny\")==\r\n* ==User(user=\"alexandru.mosoi\" type=\"tiny\")==\r\n',1,'protected',NULL,NULL),('summer-challenge-2007','Summer Challenge 2007','2007-07-25 10:04:21','2007-08-10 19:18:14','h1. Summer Challenge 2007\r\n\r\n(htabs)*(active) \'Detalii\':summer-challenge-2007/\r\n* \'Runda 1\':summer-challenge-2007/runda-1\r\n* \'Runda 2\':summer-challenge-2007/runda-2\r\n* \'Runda 3\':summer-challenge-2007/runda-3\r\n* \'Clasament\':summer-challenge-2007/clasament\r\n\r\nIn toiul vacantei de vara, feriti de canicula, la umbra monitoarelor, infoarena se gandeste la tine!\r\n\r\nTe invitam sa participi la seria de concursuri {*Summer Challenge 2007*}. Vom organiza 3 runde online, de cate -5h fiecare- 5 sau 3 ore fiecare, cu probleme de dificultate variata.\r\n\r\nSummer Challenge este o ocazie buna de antrenament pentru tine (daca nu esti deja la mare :) dar si un ultim test pentru delegatia\r\nRomaniei la Olimpiada Internationala de Informatica 2007 (Croatia).\r\n\r\nAi ocazia sa concurezi cu lotul Romaniei la IOI 2007!\r\n\r\nh2. Program concurs\r\n\r\ntable{width: 50%}. |_. Runda|_. Data |_. Ora |\r\n|\"*Runda 1*\":summer-challenge-2007/runda-1|*Luni, 30 iulie 2007*| *10^00^ - 15^00^* |\r\n|\"*Runda 2*\":summer-challenge-2007/runda-2|*Vineri, 10 august 2007*| *10^00^ - 15^00^* |\r\n|\"*Runda 3*\":summer-challenge-2007/runda-3| *Duminica, 12 august 2007* | *10^00^ - 13^00^* |\r\n\r\nClick pe titlul unei runde pentru informatii detaliate.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"51\" count=\"10\")==\r\n\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru.\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti probleme, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nh2. Prima data pe infoarena?\r\n\r\ninfoarena ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi.\r\n\r\nVezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n',1,'protected',NULL,NULL),('summer-challenge-2007/runda-1','Summer Challenge 2007, Runda 1','2007-07-25 10:21:15','2007-08-12 10:22:25','h1. Summer Challenge 2007, Runda 1\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2007\r\n*(active) \'Runda 1\':summer-challenge-2007/runda-1\r\n* \'Runda 2\':summer-challenge-2007/runda-2\r\n* \'Runda 3\':summer-challenge-2007/runda-3\r\n* \'Clasament\':summer-challenge-2007/clasament\r\n\r\nRunda se va desfasura Luni 30 iulie, la ora {*10^00^*} si va dura *5h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"summer2007-runda1\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"summer2007-runda1\" score=\"1\")==\r\n\r\nSolutiile le gasiti \'aici\':summer-challenge-2007/solutii/runda-1\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 1\':summer-challenge-2007/clasament/runda-1\r\n\r\nh2. Organizatori\r\n\r\n==User(user=\"ditzonec\" type=\"tiny\")==',13,'protected',NULL,NULL),('summer-challenge-2007/clasament/runda-2','Clasament Summer Challenge 2007, Runda 2','2007-08-07 21:49:26','2007-08-10 19:24:26','h1. Clasament \'Summer Challenge 2007, Runda 2\':summer-challenge-2007/runda-2\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2007\r\n* \'Runda 1\':summer-challenge-2007/runda-1\r\n*(active) \'Runda 2\':summer-challenge-2007/runda-2\r\n* \'Runda 3\':summer-challenge-2007/runda-3\r\n*(active) \'Clasament\':summer-challenge-2007/clasament\r\n\r\n== Rankings(rounds=\"summer2007-runda2\") == ',1,'protected',NULL,NULL),('summer-challenge-2007/clasament','Clasament Summer Challenge 2007','2007-08-10 19:21:28','2007-08-12 10:39:55','h1. Clasament \'Summer Challenge 2007\':summer-challenge-2007/\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2007\r\n* \'Runda 1\':summer-challenge-2007/runda-1\r\n* \'Runda 2\':summer-challenge-2007/runda-2\r\n* \'Runda 3\':summer-challenge-2007/runda-3\r\n*(active) \'Clasament\':summer-challenge-2007/clasament\r\n\r\nAcesta este clasamentul cumulat pe cele 3 runde online.\r\n\r\n== Rankings(rounds=\"summer2007-runda1 | summer2007-runda2 | summer2007-runda3\") ==',13,'public',NULL,NULL),('summer-challenge-2007/runda-2','Summer Challenge 2007, Runda 2','2007-08-07 21:47:27','2007-08-10 20:19:17','h1. Summer Challenge 2007, Runda 2\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2007\r\n* \'Runda 1\':summer-challenge-2007/runda-1\r\n*(active) \'Runda 2\':summer-challenge-2007/runda-2\r\n* \'Runda 3\':summer-challenge-2007/runda-3\r\n* \'Clasament\':summer-challenge-2007/clasament\r\n\r\nRunda se va desfasura Vineri, 10 august, la ora {*10^00^*} si va dura *5h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"summer2007-runda2\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"summer2007-runda2\" score=\"1\")==\r\n\r\nSolutiile le gasiti \'aici\':summer-challenge-2007/solutii/runda-2\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 2\':summer-challenge-2007/clasament/runda-2\r\n\r\nh2. Organizatori\r\n\r\n* ==User(user=\"ditzonec\" type=\"tiny\")==\r\n* ==User(user=\"silviug\" type=\"tiny\")==\r\n* ==User(user=\"cosmin\" type=\"tiny\")==\r\n* ==User(user=\"danielp\" type=\"tiny\")==\r\n* ==User(user=\"alexandru.mosoi\" type=\"tiny\")==\r\n',961,'protected',NULL,NULL),('blog/summer-challenge-2007/incheiere','Summer Challenge 2007 s-a incheiat','2007-08-12 10:37:58','2007-08-12 10:39:32','Concursul online _Summer Challenge_ organizat de infoarena s-a incheiat.\r\nFelicitari participantilor si, mai ales, castigatorilor!\r\n\r\n&rarr; \'*Clasamentul cumulat*\':summer-challenge-2007/clasament pe cele 3 runde\r\n&rarr; \'Pagina concursului\':summer-challenge-2007\r\n\r\nSperam ca a fost o experienta utila pentru lotul Romaniei la IOI 2007 (care incepe peste numai 3 zile!). \r\nVa tinem pumnii!\r\n',13,'protected',NULL,NULL),('implica-te/extinde-arhiva','Extinde arhiva','2007-03-12 22:59:26','2010-04-24 23:52:37','h1. Extinde arhiva ==Stars(rating=\"3\")==\r\n\r\nArhiva este una dintre cele mai folositoare sectiuni _infoarena_ pentru utilizatorii nostri. Ea contine probleme pentru multe gusturi. Dar nu pentru toate! Vrem sa o imbunatatim cu probleme cat mai diverse si cu grade de dificultate cat mai variate. La fiecare olimpiada sau concurs national important apar noi \"creatii\" pe care ne straduim sa le punem la dispozitia tuturor intr-un timp cat mai scurt. Ajuta-ne in acest demers!\r\n\r\nh2. De ce m-as baga?\r\n\r\n# Vei afla cum se propune si cum se corecteaza o problema. Vei sti cum sa propui propriile probleme pe _infoarena_.\r\n# Intreaga comunitate iti va multumi pentru noul \"material\" de pregatire.\r\n# Vei fi si tu \"de partea cealalta a baricadei\".\r\n# Pentru unele probleme vei putea scrie enuntul personalizat (cu numele simpatiei tale, spre exemplu).\r\n# Unde-s multi, puterea creste! :P\r\n\r\nh2. Ce pot sa fac?\r\n\r\n# Contacteaza-l pe ==user(user=\"stef2n\" type=\"tiny\")== pe \'forum\':forum/index.php/board,42.0.html sau e-mail.\r\n# Alege-ti problemele pe care vrei sa le pui in arhiva si *verifica* daca exista \'acordul\':implica-te/extinde-arhiva/acord autorului pentru a pune problemele respective. \r\n*{color:red}Atentie!* Comunica acest lucru lui Stefan cat mai repede pentru a evita suprapunerile si pentru a putea aparea in tabelul cu voluntarii activi ;)\r\n# *{color:red}Foarte important:* Citeste despre \'cum se adauga o problema\':documentatie/editare-de-probleme, \"conventii de formatare\":documentatie/conventii-de-formatare si \'textile\':documentatie/textile si intreaba pe forum daca ai nelamuriri.\r\n# Abia dupa ce ai terminat de citit documentatia, cere drepturi de helper pentru a putea pune probleme pe infoarena.\r\n# Scrie enuntul unei probleme folosind \'textile\':http://infoarena.ro/documentatie/textile si gandeste-te la solutii alternative.\r\n# Imbunatateste testele si creeaza altele noi, astfel incat problema sa devina de actualitate.\r\nToate bulanelile/ciucuielile care s-au facut in concursul respectiv trebuie facute sa pice.\r\n# Stabileste limitele de timp si memorie conform cu mediul infoarena de evaluare.\r\n\r\nh2. Problemele la care se lucreaza acum\r\n\r\nTODO\r\n\r\ntable. |_. Sursa de probleme |_. Voluntar |_. Progres |\r\n| Probleme baraje | ==User(user=\"astronomy\" type=\"tiny\")== ==User(user=\"toni2007\" type=\"tiny\")== | ?/? |\r\n| Probleme Cosmin Negruseri | ==User(user=\"bogdan2412\" type=\"tiny\")== | 3/4 |\r\n\r\nh2. Probleme de pus in arhiva \r\n\r\n* \"preONI 2003\":downloads?action=download&file=preoni2.zip\r\n* Probleme de orice autor din \'lista de propunatori infoarena-friendly\':implica-te/extinde-arhiva/acord\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"42.0\")==\r\n',2028,'protected',NULL,NULL),('implica-te/scrie-articole','Scrie articole','2007-03-28 22:23:46','2010-02-15 12:27:54','h1. Scrie articole ==Stars(rating=\"4\")==\r\n\r\nFolosind modelul de \'wiki\':documentatie/wiki, infoarena oferă şansa tuturor membrilor săi să contribuie la realizarea de articole sau la îmbunătăţirea celor existente. Dacă vrei să afli mai multe despre conceptul de wiki intră \'aici\':http://en.wikipedia.org/wiki/Wiki, iar dacă vrei să contribui la această iniţiativă citeşte mai jos ce trebuie sa faci.\r\n\r\nh2. De ce m-aş băga?\r\n\r\n* O carieră în cercetare în informatică poate debuta cu nişte articole online!\r\n* Vei învăţa care sunt elementele cheie pentru a scrie un articol.\r\n* Vei învăţa pe alţii ceea ce ştii, aşa cum probabil şi tu ai învăţat din articolele deja \'existente\':articole.\r\n\r\nh2. Ce pot să fac?\r\n\r\nDe-a lungul timpului, utilizatorii infoarena şi-au manifestat interesul în a scrie articole pentru întreaga comunitate. În momentul de faţă ne concentrăm eforturile atât pe completarea şi aducerea la o formă prezentabilă a acestor articole vechi, cât şi pe scrierea de articole noi. Sunt 3 moduri în care poţi contribui:\r\n\r\nh3. 1. Ajută-ne la ce lucrăm acum\r\n\r\nÎn tabelul de mai jos poţi găsi articolele începute, împreună cu stadiul în care se găseşte fiecare. Dacă eşti dornic să ne ajuţi, alege-ţi unul din articolele de care nu se ocupă nimeni şi ia legătura cu coordonatorul proiectului ca să afli ce mai e de făcut la el.\r\n\r\ntable. |_. Titlu |_. Autor |_. Stadiu |_. Voluntar(i) |\r\n| \'Transformari geometrice\':transformari-geometrice | ==user(user=\"Cosmin\" type=\"tiny\")== | ÎN LUCRU | ==user(user=\"Marius\" type=\"tiny\")== |\r\n| \'Arbori indexaţi binar\':arbori-indexati-binar | ==user(user=\"skortzy\" type=\"tiny\")== | ÎN LUCRU | ? |\r\n| \'Arborele componentelor biconexe şi al nodurilor critice\':http://infoarena.ro/downloads?action=download&file=arborele_componentelor_biconexe_si_al_nodurilor_critice.doc&safe_only=false | ==user(user=\"mugurelionut\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Algoritmi de flux maxim în reţele\':http://infoarena.ro/downloads?action=download&file=flux_maxim_in_retele.doc&safe_only=false | ==user(user=\"mugurelionut\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Tehnici avansate de programare dinamică\':pd | ==user(user=\"Zeus\" type=\"tiny\")== | ÎN LUCRU | ==user(user=\"Zeus\" type=\"tiny\")== |\r\n| \'Flux si cuplaj\':flux-si-cuplaj | ==user(user=\"blasterz\" type=\"tiny\")== | ÎN LUCRU | ==user(user=\"blasterz\" type=\"tiny\")== |\r\n\r\nh3. 2. Preia şi dezvoltă un subiect mai vechi\r\n\r\nAi nevoie de un impuls pentru a-ţi da drumul la scris? Sunt câteva articole pe infoarena începute, dar abandonate, precum şi nişte schiţe. Poţi folosi ideile de start ale autorului şi îl poţi transforma într-un articol bine documentat. În plus, poţi lua legătura cu autorul iniţial şi poţi afla viziunea sa asupra subiectului. Iată o listă de articole abandonate şi de schiţe:\r\n\r\ntable. |_. Titlu |_. Autor initial |\r\n| Programare dinamica / memoizare (trading space for time): \'link1\':programare-dinamica | ==user(user=\"Zeus\" type=\"tiny\")== |\r\n| \'Arbori indexati binar\':aib | ==user(user=\"Skipy\" type=\"tiny\")== |\r\n| \'Dinic\':dinic | ==user(user=\"alexandru.mosoi\" type=\"tiny\")== |\r\n| \'Probleme de geometrie si solutii\':downloads?geometrie.zip | ==user(user=\"Cosmin\" type=\"tiny\")== |\r\n| \'Teoria jocurilor\':teoria-jocurilor | ==user(user=\"filipb\" type=\"tiny\")== |\r\n| \'Psihologia concursurilor de informatica - Lucrul cu numere mari\':lucrul-cu-nr-mari | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| Psihologia concursurilor de informatica - Lucrul cu structuri mari de date | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| Psihologia concursurilor de informatica - Probleme de concurs | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| \'Notiuni de geometrie analitica si aplicatii\':notiuni-de-geometrie-si-aplicatii | ==user(user=\"devilkind\" type=\"tiny\")== \r\n==user(user=\"sima_cotizo\" type=\"tiny\")== |\r\n| \'Diagrame Voronoi\':voronoi | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| \'Algoritmi de baleiere\':algoritmi-de-baleiere | ==user(user=\"stef2n\" type=\"tiny\")== |\r\n\r\nh3. 3. Creează ceva nou\r\n\r\nAi o idee nouă de articol? Sau pur şi simplu vrei să te apuci de la 0 de un subiect? Ia legătura cu coordonatorul proiectului sau anunţă pe \'forum\':forum. Este posibil să primeşti ajutor şi de la alţi utilizatori infoarena. În plus, noi îţi propunem o listă de articole pe care ni le-am dori scrise, în caz că nu te-ai decis asupra temei:\r\n\r\ntable. |_. Titlu |\r\n| Depanarea programelor C/C++ cu gdb in Linux |\r\n| Testarea surselor in timp de concurs sau Cum sa reduci buselile |\r\n| Tutorial LaTeX |\r\n| Probleme cu becuri |\r\n| Punct în interiorul unui poligon neconvex |\r\n| Automate |\r\n\r\nNe rezervam dreptul să nu acceptăm sau să ştergem articolele care nu se potrivesc cu tema şi target-ul site-ului.\r\n\r\nh2. Cu cine iau legătura?\r\n\r\nCu coordonatorul proiectului:\r\n\r\n* ==user(user=\"Marius\" type=\"tiny\")==\r\n\r\nSau dacă vrei să contribui la un articol la care se lucrează deja, poţi vorbi direct cu voluntarii care se ocupă de el.\r\n\r\nh2. Discuţii pe forum\r\n\r\n==SmfTopics(board_id=\"43\")==',3146,'protected',NULL,NULL),('utilizator/marsamg','Profil marsamg','2007-08-20 06:32:55','2007-08-20 06:32:55','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6728,'public',NULL,NULL),('utilizator/azotlichid','Profil azotlichid','2006-11-23 20:29:26','2007-08-23 07:39:25','h2. Despre mine\r\n\r\n* Membru al comisiei la Stelele Informaticii 2006, ONI 2007, Lot Alba 2007\r\n* In 2007 am tinut cateva cursuri de informatica la ICHB\r\n\r\nh2. Studii\r\n\r\n* Student la Brown University (2007-2011)\r\n* Absolvent al Colegiului National de Informatica {@\"Tudor Vianu\"@}, Bucuresti (2002-2006)\r\n\r\nh2. Distinctii primite (cele mai importante)\r\n\r\n* IOI: argint (Grecia, 2004), bronz (Mexic, 2006)\r\n* CEOI: argint (Croatia, 2006)\r\n* BOI: bronz (Bulgaria, 2004)\r\n* ONI: locurile 8 (2003), 2 (2004), 4 (2005), 4 (2006)\r\n* Stelele Informaticii: locurile 4 (2003), 2 (2005)\r\n* PACO: locurile 2 (2004), 1 (2006)\r\n\r\nh2. Articole\r\n\r\n* Siruri de sufixe (impreuna cu Cosmin Negruseri), GInfo 15/10\r\n* Teorema chineza a resturilor - generalizari si aplicatii, GInfo 16/1\r\n\r\n',18,'protected',NULL,NULL),('development-roadmap','infoarena Development Roadmap','2007-08-30 22:22:59','2007-08-31 00:45:49','h1. infoarena Development Roadmap\r\n\r\nAici vom discuta despre viitorul site-ului infoarena din punct de vedere al development-ului. Daca vrei sa aflii mai multe despre cum te poti implica in development intra \'aici\':implica-te/development. De asemenea poti vedea proiectele si sedintele asociatiei infoarena \'aici\':planificare. \r\n\r\nh2. Etapa 1 (no more _beta_)\r\n\r\n_Deadline: pana la sfarsitul anului 2007_\r\n\r\nh3. Agenda\r\n\r\nScopul principal al developmentului ar trebui sa fie imbunatatirea site-ului in vederea organizarii urmatorului preONI, atat din punct de vedere al utilizatorului cat si al administratorului. Trebuie sa:\r\n\r\n# asiguram functionalitatea care exista deja in infoarena 1.0.\r\n# reparam \'bug-urile\':forum/index.php?topic=1359.0 raportate\r\n# investigam \'feature request-urile\':forum/index.php?board=33.0 primite\r\n# implementam feature-uri *2.0*:\r\n## posibilitatea de a rula concursuri automat\r\n## tipuri noi de probleme (output-only, reactive, ACM, etc.)\r\n\r\nh3.  Milestone-uri\r\n\r\n* \'2.1.5 Bells of Innocence\':http://hackers.devnet.ro/milestone/2.1.5%20Bells%20of%20Innocence\r\n* \'2.1.6 Code of Silence\':http://hackers.devnet.ro/milestone/2.1.6%20Code%20of%20Silence\r\n\r\nh2. Etapa 2 (2.0+)\r\n\r\nh3. Agenda\r\n\r\nScopul principal este sa marim target-ul site-ului infoarena si functionalitatea pe care acesta o ofera. Be creative! De-a lungul anilor am avut mai multe \'proiecte\':forum/index.php?board=18.0 si \'idei\':forum/index.php?board=21.0 care nu s-au materializat. Acum e momentul sa punem in practica toate ideile pe care le-am avut! Trebuie sa:\r\n\r\n# adaugam un blog\r\n# fim \"open-source\" din punct de vedere al surselor trimise de concurenti\r\n# implementam \"training path\"-uri\r\n# implementam noi tipuri de concursuri (de viteza, de debug, etc.)\r\n# _more to come_\r\n\r\nh3.  Milestone-uri\r\n\r\n_Atentie, listele de tickete sunt incomplete!_\r\n\r\n* \'2.2 Firewalker\':http://hackers.devnet.ro/milestone/2.2%20Firewalker\r\n* \'2.3 Sons of Thunder\':http://hackers.devnet.ro/milestone/2.3%20Sons%20of%20Thunder\r\n',1,'public',NULL,NULL),('runda/autumn2007-runda1/clasament','Clasament autumn2007-runda1','2007-09-03 20:19:03','2007-09-03 20:19:03','h1. Clasament ==roundparam(round_id=\"autumn2007-runda1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"autumn2007-runda1\")==',961,'round: autumn2007-runda1',NULL,NULL),('autumn-warmup-2007/clasament/runda-1','Clasament Runda 1','2007-09-03 20:22:15','2007-10-06 20:04:26','h1. Clasament \'Autumn Warmup 2007, Runda 1\':autumn-warmup-2007/runda-1\r\n\r\n(htabs)* \'Detalii\':autumn-warmup-2007/\r\n*(active) \'Runda 1\':autumn-warmup-2007/runda-1\r\n* \'Runda 2\':autumn-warmup-2007/runda-2\r\n* \'Runda 3\':autumn-warmup-2007/runda-3\r\n*(active) \'Clasament\':autumn-warmup-2007/clasament\r\n\r\n== Rankings(rounds=\"autumn2007-runda1\") == ',961,'public',NULL,NULL),('utilizator/100puncte','Profil 100puncte','2007-09-06 13:24:20','2007-09-06 13:24:20','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6760,'public',NULL,NULL),('warm-up-2007','warmup2007','2007-09-05 19:13:17','2007-09-05 19:13:17','Scrie aici despre warm-up-2007',4374,'public',NULL,NULL),('blog/autumn-warmup-2007/runda-1','Autumn Warm-Up 2007, Runda 1','2007-09-09 18:53:37','2007-09-09 18:54:59','Vacanta de vara a ajuns la sfarsit.  E timpul sa te revezi cu vechii tai prieteni de la concursurile de info si sa le demonstrezi ca ai ramas in forma.  :)\r\nTe invitam sa participi la runda 1 a concursului Autumn Warm Up cu probleme propuse de utilizatori infoarena.\r\n\r\nRunda 1 se desfasoara *Marti, 11 septembrie 2007, orele 10^00^ - 15^00^*.\r\n\r\n&rarr; \'Autumn Warm Up, Runda 1\':autumn-warmup-2007/runda-1\r\n',13,'public',NULL,NULL),('autumn-warmup-2007/solutii/runda-1','Solutii Autumn Warmup, Runda 1','2007-09-11 11:37:55','2009-02-04 13:14:55','h1. Solutii runda 1\r\n\r\nh2. \'Banuti\':problema/banuti\r\n\r\nNotam cu $min$ valoarea minima. Se observa ca pentru o suma oarecare $s$, daca toate sumele din intervalul $(s,s+min]$ pot fi obtinute, atunci toate sumele $> s$ pot fi obtinute la randul lor. (Pentru a va convinge, in caz ca aveti neclaritati, simulati un knapsack). Se construieste un graf cu $min$ noduri, nodul $x$ semnificand restul $x$ la impartirea cu $min$. Se defineste $cost[x]$, suma minima care poate fi obtinuta $(s)$, cu proprietatea ca $s%min=x$ (restul impartirii sumei la $min$ este $x$); @cost[0]=0@. Se observa ca daca putem obtine o suma $s$, atunci putem obtine toate sumele $s+k*min$ (care au acelasi rest), unde $k>0$. In acest graf fiecare bancnota (de valoare $v$), formeaza o muchie intre nodul $y$ si nodul $(y+v)%min$, cu costul $v$, unde $y$ apartine $[0,min)$. Daca acest graf nu este conex atunci nu avem solutie. Daca este conex, atunci solutia se afla in $max(cost[x])-min$, $x$ apartine $[0,min)$, care poate fi aflata cu Dijkstra. Mentionez faptul ca graful ar avea teoretic $N*min$ muchii. Pe cazul general, $N>min$, deci unele muchii sunt in plus (conform principiului cutiei). Graful pe care se face rezolvarea ar trebui sa aiba $&#8776;min^2^$ muchii. Complexitatea finala este $O(min^2^)$. \r\n\r\n\r\nh2. \'Renovare\':problema/renovare\r\n\r\nVom reduce problema la flux maxim de cost minim astfel: pentru fiecare muchie $a b c cst$ cu semnificatia din enunt vom adauga $2$ muchii in retea, una de capacitate $c$ si cost $0$ si inca una de capacitate infinit si cost $cst$. De asemenea vom conecta nodul $1$ la o sursa auxiliara printr-o muchie de capacitate $x$ si cost $0$. Apoi se ruleaza algoritmul de flux maxim de cost minim in reteaua noua.\r\n\r\nh2. \'Plan\':problema/plan\r\n\r\nConstruim graful componentelor tare conexe si in continuare ne vom referi numai la acest graf. Plasam in multimea $X$ nodurile cu grad de intrare 0, iar in multimea $Y$ nodurile cu grad de iesire 0. Vom gasi in continuare un mod de a construi $max(cardX, cardY)$ sosele si este clar ca acest numar e minim deoarece din fiecare nod din $X$ trebuie sa intre macar o muchie, iar din fiecare nod din $Y$ trebuie sa iasa macar o muchie. In continuare ne vom construi un set maximal (atentie, maximal != maxim) de perechi $(x{~1~}, y{~1~}), (x{~2~}, y{~2~}) ... (x{~k~}, y{~k~})$ astfel incat $x{~1~}, x{~2~} .. x{~k~}$ apartin lui $X$ iar $y{~1~}, y{~2~}.. y{~k~}$ apartin lui $Y$. Mai mult exista drum in graf de la $x{~i~}$ la $y{~i~}$. Acest set se poate construi simplu efectuand cate o parcurgere din fiecare nod a lui $X$. Adaugam muchie de la $y{~1~}$ la $x{~2~}$, $y{~2~}$ la $x{~3~}$ ... $y{~k~}$ la $x{~1~}$. In continuare adaugam muchii de la fiecare nod ramas din $Y$ la un nod ramas din $X$ pana cand vom avea noduri doar in $X$ sau doar in $Y$. Pentru acele noduri adaugam o muchie de la ele la $x{~1~}$ sa zicem, sau de la $x{~1~}$ la ele in functie daca sunt din $X$ sau din $Y$. Am adaugat cate muchii ne-am propus, acum sa vedem daca respecta proprietatea ca avem un drum de la orice nod la orice nod. Dupa ce am construit acel set maximal si practic am construit un ciclu adaugand muchiile, nodurile care au mai ramas din multimea $X$ au drum de la ele la un nod din ciclu, iar cele din multimea $Y$ ramase au drum de la un nod din ciclu la ele. Deci cand consideram doua noduri $A$ si $B$, cu $A$ din $X$ si $B$ din $Y$ si dintre cele care au ramas dupa alegerea nodurilor din setul maximal, si tragem muchie de la $B$ la $A$ vom avea drum de la nodurile din ciclu la $A$, la $B$ si de la ele la nodurile din ciclu. Acelasi lucru se intampla si in momentul cand raman noduri doar din $X$ sau doar din $Y$, vom avea drum de la un nod din ciclu la ele si invers. Deci daca consideram un nod oarecare $P$, acest nod fie este pe ciclu, fie exista drum de la el la ciclu si invers, adica exista drum de la el spre toate nodurile si de la toate nodurile spre el. Pentru nodurile care nu sunt din $X$ sau din $Y$ avem macar un drum de la ele la un nod din $Y$ si de la un nod din $X$ la ele, deci respecta proprietatea.\r\n\r\nh2. \'Numar de Divizori\':problema/ndiv\r\n\r\nSe afla solutia pentru intervalul $[1, A-1]$ si $[1, B]$ si se face diferenta. Pentru un interval $[1, N]$ si un numar $X$, se afla numarul de numere din interval care se divid la $X$ prin aflarea catului $N / X$. O simpla solutie ar fi pentru fiecare $X = 1 2 ... N$ se face suma lui $N/X$. Evident nu intra in timp. Daca se scrie sirul $N/X$ cu $X$ de la $1$ la $N$ se observa ca termenii sirului sunt in ordine descrescatoare. De exemplu sa vedem pentru $N = 12$, vom avea sirul $N/X$ : $12/1$, $12/2$, $12/3$ ... $12/12$ care este $12, 6, 4, 3, 2, 2, 1, 1, 1, 1, 1, 1$. Solutia se bazeaza pe faptul ca aceste numere se repeta pe anumite intervale. Astfel se iau toate numerele $i$ de la $1$ la $sqrt(N)$ si se vor tine intr-un vector sortate valorile: $i$ si $N/i$. Acum pentru doua pozitii consecutive in acest vector vom avea doua valori: $X1$ si $X2$ si $N/X1$ = $N/X2$. Si orice numar din intervalul $[X1, X2]$, sa zicem $Y$ va avea $N/Y$ = $N/X1$. Acum se iau toate pozitiile consecutive in vectorul format si se aduna la solutie $(N/X1)*(X2-X1+1)$ (lungimea intervalului). Corectitudinea acestei solutii se bazeaza pe faptul ca daca ar fi sa imparti numarul $N$ la toate numerele de la $1$ la $N$, se obtin $2*sqrt(N)$ diferite caturi. De exemplu nu poti sa imparti $12$ la ceva mai mic egal cu $12$ si sa obtii catul $11$. Complexitatea va fi $O(sqrt(N))$. ',6172,'public',NULL,NULL),('implica-te/extinde-arhiva/lista-lu-francu','Lista lu\' Francu','2007-08-11 11:04:25','2009-05-09 13:01:21','h1. Lista lu\' Francu\r\n\r\nObiectivul nostru este sa reinviem \"Lista lu\' Francu\":http://voronet.francu.com/probleme/rom/probleme.html. :)\r\n\r\nMandri voluntari: \r\n==User(user=\"cos_min\" type=\"tiny\")==  \r\n==User(user=\"devilkind\" type=\"tiny\")==\r\n==User(user=\"florian\" type=\"tiny\")==\r\n==User(user=\"gabitzish1\" type=\"tiny\")==\r\n==User(user=\"pauldb\" type=\"tiny\")==\r\n\r\nIn caz ca mai sunt si altii dornici sa ni se alature, contactati-l pe Paul sau pe Silviu pe forum.\r\n\r\nUrmatoarele de pe Lista lu\' Francu au fost deja puse in arhiva (puteti sa le luati ca model de adaptare al problemelor pentru arhiva noastra).\r\n\r\ntable(example). |_. Indice si nume pe infoarena |_. Indice si nume pe Lista lu\' Francu |\r\n| \"478. Maimute\":problema/maimute | \"-4. Arborii contraataca\":http://voronet.francu.com/probleme/arhiva/R00-4/enunt.html|\r\n| \"254. Senat\":problema/senat | \"4. Presedinti de comisii\":http://voronet.francu.com/probleme/arhiva/R0004/enunt.html |\r\n| \"257. Catun\":problema/catun |  \"5. Diagrame Voronoi pe grafuri\":http://voronet.francu.com/probleme/arhiva/R0005/enunt.html |\r\n| \"255. Vila\":problema/vila |  \"8. Vila de senator\":http://voronet.francu.com/probleme/arhiva/R0008/enunt.html |\r\n| \"260. Note\":problema/note |  \"9. Scherzo\":http://voronet.francu.com/probleme/arhiva/R0009/enunt.html |\r\n| \"259. Euler\":problema/euler |  \"11. Parcurgere Euler\":http://voronet.francu.com/probleme/arhiva/R0011/enunt.html |\r\n| \"256. Puternic\":problema/puternic |  \"12. Numere puternice\":http://voronet.francu.com/probleme/arhiva/R0012/enunt.html |\r\n| \"258. Alpin\":problema/alpin |  \"14. Alpinism\":http://voronet.francu.com/probleme/arhiva/R0014/enunt.html |\r\n| \"261. Bilete\":problema/bilete |  \"15. Blatistul\":http://voronet.francu.com/probleme/arhiva/R0015/enunt.html |\r\n| \"463. Conserve\":problema/conserve | \"24. Alpinistul contraataca III \":http://voronet.francu.com/probleme/arhiva/R0024/enunt.html |\r\n| \"479. Order2\":problema/order2 | \"28. Ordonare\":http://voronet.francu.com/probleme/arhiva/R0028/enunt.html|\r\n| \"409. Secvente\":problema/secvente | \"32. Secvente\":http://voronet.francu.com/probleme/arhiva/R0032/enunt.html |\r\n| \"538. Impartire\":problema/impartire  | \"-8. Impartire\":http://voronet.francu.com/probleme/arhiva/R00-8/enunt.html | | \r\n| \"537. Capitala\":problema/capitala | \"-7. Capitala\":http://voronet.francu.com/probleme/arhiva/R00-7/enunt.html |   \r\n| \"535. Drum\":problema/drum | \"-6. Jocul Drumului\":http://voronet.francu.com/probleme/arhiva/R00-6/enunt.html| \r\n| \"536. Razboi 2\":problema/razboi2 | \"-3. In vreme de razboi...\":http://voronet.francu.com/probleme/arhiva/R00-3/enunt.html| \r\n| \"539. Permutari 6\":problema/perm6 | \"-2. Permutari\":http://voronet.francu.com/probleme/arhiva/R00-2/enunt.html |\r\n| \"533. Retele\":problema/retele | \"1. Retele de telefonie\":http://voronet.francu.com/probleme/arhiva/R0001/enunt.html |\r\n| \"550. Logic 2\":problema/logic2 | \"16. Insula logicii\":http://voronet.francu.com/probleme/arhiva/R0016/enunt.html | \r\n| \"532. Functii\":problema/functii | \"18. Numarare functii\":http://voronet.francu.com/probleme/arhiva/R0018/enunt.html | \r\n| \"540. Examene\":problema/examene | \"19. Programa subtirica\":http://voronet.francu.com/probleme/arhiva/R0019/enunt.html |\r\n| \"534. Tablite\":problema/tablite | \"35. Numere\":http://voronet.francu.com/probleme/arhiva/R0035/enunt.html | \r\n| \"524. Cinema\":problema/cinema | \"34. Secventa\":http://voronet.francu.com/probleme/arhiva/R0034/enunt.html | \r\n| \"528. Cod\":problema/cod | \"36. Coduri\":http://voronet.francu.com/probleme/arhiva/R0036/enunt.html | \r\n| \"551. Triticale\":problema/triticale | \"37. Turn de triticale\":http://voronet.francu.com/probleme/arhiva/R0037/enunt.html |\r\n| \"530. Interclasare\":problema/interclasare | \"39. Interclasare\":http://voronet.francu.com/probleme/arhiva/R0039/enunt.html | \r\n| \"542. Modulo\":problema/modulo | \"31. Modulo\":http://voronet.francu.com/probleme/arhiva/R0031/enunt.html |\r\n| \"543. Tetris\":problema/tetris | \"22. Tetris\":http://voronet.francu.com/probleme/arhiva/R0022/enunt.html |\r\n| \"541. Pastila\":problema/pastila | \"45. Balanta medicinala\":http://voronet.francu.com/probleme/arhiva/R0045/enunt.html |\r\n\r\nCei mai harnici voluntari (incepand cu 9 august 2007):\r\n\r\n|_. Utilizator |_. Numarul de probleme bagate |\r\n| ==User(user=\"cos_min\" type=\"tiny\")== | 2 |\r\n| ==User(user=\"devilkind\" type=\"tiny\")== | 3 |\r\n| ==User(user=\"gabitzish1\" type=\"tiny\")== | 6 |\r\n| ==User(user=\"florian\" type=\"tiny\")== | 3 |\r\n| ==User(user=\"pauldb\" type=\"tiny\")== | 3 |\r\n\r\nModificati singuri tabelul, dar doar atunci cand ati terminat de bagat o problema (enunt, teste, sursa, eval). \r\n\r\nAici aveti o lista cu probleme de pe lista lui Francu. Problemele care au statusul %{color:red}Trebuie adaugata% sunt cele care ne intereseaza in acest moment. Problemele care nu apar in acest tabel ori nu se potrivesc cu sistemul infoarena ori linkul de pe lista nu mai merge. Cand v-ati decis asupra unei probleme adaugati linkul problemei in tabel ca fiind %{color:green}Adaugata% (linkul se inverzeste singur) iar in coloana de informatii treceti id-ul vostru, in felul acesta daca cineva are o super-idee la o problema care a fost adaugata de altcineva se poate uita in tabel si contacta pe cel care a introdus problema. De asemenea daca o problema vi se pare prea simpla o puteti modifica (in limitele bunului simt).\r\nUnele din problemele de pe lista se regasesc complet in alte probleme de pe infoarena. Nu are rost sa mai punem si aceste probleme. Acele probleme au statusul %{color:green}Inclusa%, avand linkul la status.\r\n\r\ntable(example). |_. Problema de pe lista |_. Status |_. Informatii|\r\n| \"-5. Robotul si gaura\":http://voronet.francu.com/probleme/arhiva/R00-5/enunt.html| %{color:blue}Interactiva% | - |\r\n| \"-1. Observabile\":http://voronet.francu.com/probleme/arhiva/R00-1/enunt.html | %{color:green}Adaugata-link lipsa% | ==User(user=\"alexthero\" type=\"tiny\")== |\r\n| \"2. Sah\":http://voronet.francu.com/probleme/arhiva/R0002/enunt.html | %{color:blue}Interactiva% | - |\r\n| \"3. Fractali\":http://voronet.francu.com/probleme/arhiva/R0003/enunt.html | %{color:red}Trebuie adaugata% | - |\r\n| \"6. Baza de date\":http://voronet.francu.com/probleme/arhiva/R0006/enunt.html | \"Inclusa\":problema/prefix |\r\n| \"7. Jocul vietii 1D\":http://voronet.francu.com/probleme/arhiva/R0007/enunt.html| %{color:green}Adaugata-link lipsa% | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| \"13. Ghisee\":http://voronet.francu.com/probleme/arhiva/R0013/enunt.html | %{color:blue}Interactiva% | - |\r\n| \"20. Alpinistul is coming back\":http://voronet.francu.com/probleme/arhiva/R0020/enunt.html | %{color:red}Trebuie adaugata% | - |\r\n| \"21. Puzzle\":http://voronet.francu.com/probleme/arhiva/R0021/enunt.html | %{color:red}Trebuie adaugata% | Rezolvare dubioasa |\r\n| \"23. Nim\":http://voronet.francu.com/probleme/arhiva/R0023/enunt.html | \"Inclusa\":problema/joc3 | - |\r\n| \"26. Turnu Eiffel\":http://voronet.francu.com/probleme/rom/probleme.html| %{color:red}Trebuie adaugata% | Facuta o solutie a comisiei, si punctajul in functie de solutia comisiei |\r\n| \"27. Poker American\":http://voronet.francu.com/probleme/arhiva/R0027/enunt.html | %{color:blue}Interactiva% | - |\r\n| \"29. Amestecand..amestecuri\":http://voronet.francu.com/probleme/arhiva/R0029/enunt.html | %{color:red}Trebuie adaugata% | - |\r\n| \"30. Reciclarea sticlei\":http://voronet.francu.com/probleme/arhiva/R0030/enunt.html| %{color:green}Adaugata-link lipsa% | ==User(user=\"Florian\" type=\"tiny\")==  |\r\n| \"33. Din mosi stramosi\":http://voronet.francu.com/probleme/arhiva/R0033/enunt.html | \"Inclusa\":problema/concurs | \r\n| \"38. The matrix has you\":http://voronet.francu.com/probleme/arhiva/R0038/enunt.html | %{color:red}Trebuie adaugata% | \r\n| \"40. Straturi\":http://voronet.francu.com/probleme/arhiva/R0040/enunt.html | %{color:red}Trebuie adaugata% | - |\r\n| \"42. Soarecele si pisica\":http://voronet.francu.com/probleme/arhiva/R0042/enunt.html | %{color:red}Trebuie adaugata% | - |\r\n| \"43. Vechea masina de calcul\":http://voronet.francu.com/probleme/arhiva/R0043/enunt.html | %{color:red}Trebuie adaugata% | - |\r\n| \"44. Verigi\":http://voronet.francu.com/probleme/arhiva/R0044/enunt.html | %{color:red}Trebuie adaugata% | - |\r\n',5748,'public',NULL,NULL),('despre-blog','Despre Blog','2007-11-04 14:57:37','2008-02-10 23:22:38','h1. Despre Blog\r\n\r\ninfoarena.ro este un site creat de fosti olimpici la informatica pentru viitorii olimpici. El are probleme ale caror solutii pot fi evaluate online, articole educationale, un forum foarte activ si este inconjurat de o comunitate vibranta. Puteti vedea cateva marturii \'aici\':marturii si mai multe despre site \'aici\':despre-infoarena.\r\n\r\nBlogul infoarena a aparut ca o nevoie de a comunica pe un canal mai bun decat forumul, cu programatorii in general si cu membrii comunitatii infoarena in particular.\r\n\r\nEu sunt Cosmin Negruseri, membrul \'echipei\':echipa-infoarena care se ocupa de blog. Am facut facultatea la sectia Informatica din Universitatea Babes Bolyai - Cluj, am participat la concursuri de programare atat in postura de concurent cat si in cea de membru al comisiei, am fost editor al \'gazetei de informatica\':http://www.ginfo.ro pe perioada unui an, publicand 15 articole. Dupa terminarea facultatii m-am angajat la Google inc. ca software engineer in sediul din Mountain View.\r\n\r\n*shameless plug:* Daca esti un programator foarte bun sau daca cunosti programatori foarte buni care sunt interesati de un job la Google spuneti-le sa ma contacteze la cosminn ~ at ~ gmail.com.',58,'protected',NULL,NULL),('utilizator/greco','Profil greco','2006-11-24 20:56:18','2008-03-21 21:38:13','h2. Site personal\r\n\r\n* \'greco.ro\':www.greco.ro\r\n\r\nh2. Competitii\r\n\r\n* 2006 - locul 2 - ACM-ICPC Europa de Sud-Est, impreuna cu domino si DitzoneC in echipa \"infoarena coders\"\r\n* 2006 - medalie de argint - Olimpiada Internationala de Informatica, Merida, Mexic\r\n* 2006 - medalie de argint - Olimpiada de Informatica a Europei Centrale, Vrsar, Croatia\r\n* 2006 - mentiune - Olimpiada Nationala de Informatica\r\n* 2006 - locul 2 - .campion\r\n* 2005 - medalie de aur - Olimpiada Balcanica de Informatica, Rodos, Grecia\r\n* 2005 - mentiune - Olimpiada Nationala de Informatica\r\n* 2005-2006 - membru al lotului national de informatica\r\n\r\nh2. Articole\r\n\r\n* Algoritmul lui Kuhn\r\n\r\nh2. Membru in comisii\r\n\r\n* 2007 - ONI\r\n* 2007 - .campion\r\n* 2007 - preONI\r\n* 2007 - Stelele Informaticii\r\n* 2006 - preONI\r\n\r\nh2. Stiati ca...\r\n\r\n* Creata in 1688 la initiativa stolnicului Constantin Cantacuzino, Academia Domneasca, institutie de invatamant superior, lacas de inalta cultura al Tarii Romanesti, si-a inceput activitatea in Bucuresti la manastirea Sfantul Sava, fiind de-a lungul timpului cea mai importanta scoala din Tarile Romane.\r\n\r\nh2. Despre mine\r\n\r\n* Sunt membru al Asociatiei Independente a Suporterilor Stelisti.\r\n* Am convenit cu wefgef ca Deep Purple, Iron Maiden si Led Zeppelin (nu neaparat in aceasta ordine) sunt cele mai tari 3 formatii din toate timpurile.\r\n* Ma simt cel mai bine la o sticla de Stejar pe Calea Grivitei, aproape de Sava si de Piata Romana.\r\n* Incerc sa-mi fac timp sa invat invat italiana, galiciana, catalana, napoletana, portugheza, rusa, croata si poloneza si imi fac planuri de calatorie in America Latina.\r\n* Mi-am facut acest profil doar pentru ca m-a batut Cosmin la cap in repetate randuri.\r\n\r\nh2. Povesti\r\n\r\n* Am primit primul meu calculator, un HP Vectra Pentium I @ 100 Mhz, 16 MB RAM, 611 MB HDD scos din uz, in anul 2001. Inca functioneaza la parametri optimi cu ajutorul sistemului de operare Slackware Linux 12.\r\n* Parintii mi-au cumparat primul calculator nou la inceputul clasei a IX-a. Primele luni a rulat intensiv jocul Return to Castle Wolfenstein si programul mIRC, dupa orele 22:00, pe Xnet (\"internetul la puterea X\").\r\n* Tot in clasa a IX-a au inceput sa ma intereseze concursurile de informatica. In ciuda pregatirii pe cont propriu, nu am reusit sa trec de faza pe sector. :-) Lucrurile s-au schimbat multumita orelor de sambata tinute de Rodica Pintea la Liceul Grigore Moisil, unde i-am cunoscut pe DitzoneC, azotlichid si altii... La recomandarea lui azotlichid, mi-am cumparat cartile \"Introducere in algoritmi\" si \"Arta programarii calculatoarelor\". Ii multumesc pentru sfat.\r\n* Modul in care interactionez cu calculatorul a fost schimbat de renuntarea la Xnet (abonament la Astral) si cumpararea numarului special al revistei Chip despre Fedora Core 1. Cel mai util program pe care mi-l puteam imagina se numea Kazaa. O adevarata colectie muzicala era pe punctul de a incepe.\r\n* In clasa a X-a m-am straduit din greu sa ajung in prima pagina a clasamentului celui mai smecher site de info... infoarena.\r\n* Tot in clasa a X-a m-am calificat la Olimpiada Nationala de Informatica si am obtinut 60/600 puncte. Acolo l-am cunoscut pe domino. DitzoneC a fost foarte mirat de faptul ca nu auzisem de Fornetti. A fost la fel de mirat cand i-am spus ca la problema lui Mars nu trebuiau numere mari. :-)\r\n* Un an mai tarziu m-am calificat pentru prima oara in lotul national de informatica. In prima zi de baraj, m-am prins de singura problema pe care am rezolvat-o cand mai erau 3 minute din concurs. In a doua zi de baraj, am salvat in ultimul moment pe partitia pe care trebuia de fapt sa salvam. Cele 30 de puncte au fost decisive pentru calificare. In anul acela am cunoscut noi membri ai comunitatii infoarena: Zeus, danielp, andreitheo...\r\n\r\nh2. Legaturi:\r\n\r\n\"www.fcsteaua.ro\":http://www.fcsteaua.ro\r\n\"www.licsfsava.ro\":http://www.licsfsava.ro\r\n\"www.maidenfans.com\":http://www.maidenfans.com\r\n\"www.linux360.ro\":http://www.linux360.ro\r\n\"www.slackware.com\":http://www.slackware.com\r\n\"www.slashdot.org\":http://www.slashdot.org\r\n\"fmi.unibuc.ro\":http://fmi.unibuc.ro\r\n\r\nh2. Prieteni infoarena:\r\n\r\n(scuze celor pe care i-am uitat)\r\n\r\n* == User(user=\"domino\" type=\"tiny\") ==\r\n* == User(user=\"DitzoneC\" type=\"tiny\") ==\r\n* == User(user=\"bogdan2412\" type=\"tiny\") ==\r\n* == User(user=\"pauldb\" type=\"tiny\") ==\r\n* == User(user=\"astronomy\" type=\"tiny\") ==\r\n* == User(user=\"wefgef\" type=\"tiny\") ==\r\n* == User(user=\"gcosmin\" type=\"tiny\") ==\r\n* == User(user=\"filipb\" type=\"tiny\") ==\r\n* == User(user=\"azotlichid\" type=\"tiny\") ==\r\n* == User(user=\"andreitheo87\" type=\"tiny\") ==\r\n* == User(user=\"Prostu\" type=\"tiny\") ==\r\n* == User(user=\"Zeus\" type=\"tiny\") ==\r\n* == User(user=\"icg\" type=\"tiny\") ==\r\n* == User(user=\"Adriana_S\" type=\"tiny\") ==\r\n* == User(user=\"danielp\" type=\"tiny\") ==\r\n* == User(user=\"cimi\" type=\"tiny\") ==\r\n* == User(user=\"wickedman\" type=\"tiny\") ==\r\n* == User(user=\"georgiana\" type=\"tiny\") ==\r\n* == User(user=\"rss1987\" type=\"tiny\") ==\r\n* == User(user=\"mugurelionut\" type=\"tiny\") ==\r\n* == User(user=\"marius135\" type=\"tiny\") ==\r\n* == User(user=\"Cosmin\" type=\"tiny\") ==\r\n* == User(user=\"efer\" type=\"tiny\") ==\r\n* == User(user=\"svalentin\" type=\"tiny\") ==\r\n* == User(user=\"fluffy\" type=\"tiny\") ==\r\n* == User(user=\"raduzer\" type=\"tiny\") ==\r\n* == User(user=\"ira\" type=\"tiny\") ==\r\n* == User(user=\"dany\" type=\"tiny\") ==\r\n* == User(user=\"adal\" type=\"tiny\") ==\r\n* == User(user=\"druid\" type=\"tiny\") ==\r\n* == User(user=\"cyber\" type=\"tiny\") ==\r\n* == User(user=\"lexx\" type=\"tiny\") ==\r\n* == User(user=\"adona\" type=\"tiny\") ==',66,'protected',NULL,NULL),('summer-challenge-2007/solutii/runda-3','Solutii Summer Challenge 2007, Runda 3','2007-08-26 17:46:55','2008-11-16 12:10:54','h1. Solutii Runda 3\r\n\r\nh2. \'Ndap\':problema/ndap\r\n\r\nPentru fiecare submultime $V\'$ a lui $V$, notam cu $E\'$ multimea muchiilor care au ambele capete in $V\'$, cu $NeConex[V\']$ numarul subgrafurilor neconexe ale lui $V\'$, iar cu $Conex[V\']$ numarul subgrafurilor conexe ale lui $V\'$. Se cunoaste faptul ca numarul total al subgrafurilor unui graf este egal cu $2^|E|^$, de aici rezultand egalitatea $Conex[V\']$ = $2^|E\'|^ - NeConex[V\']$. Pentru fiecare sumbultime $V\'$, vom incerca sa calculam {$NeConex[V\']$}. Gasim un nod oarecare $X$ din $V\'$. Pentru ca un subgraf al lui $V\'$ sa fie neconex, componenta conexa din care face parte nodul $X$ trebuie sa fie diferita de $V\'$. Vom genera toate submultimile $V$~$1$~ ale lui $V\'$ din care face parte $X$ $(V$~$1$~ != $V\'$). Consideram ca multimea $V$~$1$~ reprezinta componenta conexa din care face parte nodul $X$. Numarul de subgrafuri ale lui $V\'$ avand fixata multimea $V$~$1$~ este egal cu produsul dintre numarul de subgrafuri conexe ale lui $V$~$1$~ si numarul total de subgrafuri ale lui $V$~$2$~ = $V\'-V$~$1$~. Astfel, relatia de recurenta devine <tex> NeConex[V\'] = \\displaystyle\\sum_{V_{1} \\subset V\'} Conex[V_{1}] * 2^{|E_{2}|} </tex>. Rezultatul il vom gasi in $Conex[V]$.\r\n\r\n\r\nh2. \'Alinuta\':problema/alinuta\r\n\r\nProblema este o generalizare a cazului cand $K$ este egal mereu cu $0$ (problema \'pietre\':problema/pietre). In cazul cand $K$ este $0$ stim ca exista anumite perechi $(a, b)$ de pietre care sunt pierzatoare. Primele perechi de acest gen sunt : $(1, 2)$, $(3, 5)$, $(4, 7)$, $(6, 10)$. Puteti sa verificati ca pentru aceste configuratii initiale primul jucator este pierzator orice ar face. Aceste perechi se pot genera dupa cateva observatii simple:\r\n\r\n* diferenta intre termeni creste intodeauna cu $1$ ({$2 - 1 = 1$}; $3 - 5 = 2$; $7 - 4 = 3$; $6 - 10 = 4$)\r\n* primul numar din fiecare pereche este cel mai mic numar natural strict pozitiv nefolosit inca in perechile anterioare ( $() -> 1$; $(1, 2) -> 3$; $(1, 2, 3, 5) -> 4$; $(1, 2, 3, 5, 4, 7) -> 6$).\r\n\r\nPe cazul general unde $K$ poate fi oricat ceea ce se schimba este diferenta intre termeni care creste cu $K + 1$ in loc de $1$ (primul subpunct) (cand $K$ este $0$ se verifica);\r\nTot ce ramane de facut este ca la inceput sa precalculam toate perechile $(a, b)$ pierzatoare pentru $K$-ul dat si sa vedem dupa aceea daca o anumita pereche data in fisierul de intrare se afla sau nu printre cele pierzatoare. Cum $A$, $B$ <= $100 000$ este clar ca pot fi cel mult $100 000$ de perechi. Ceea ce ne duce la o complexitate de $O(B)$ precalculare si apoi $O(1)$ pe query (pentru fiecare numar $x$ tinem minte perechea lui $y$ astfel incat $(x, y)$ este pierzator sau $0$ in caz ca nu exista acest $y$).\r\n\r\nIn general pentru problemele de acest tip in timpul concursului se observa regula cu ajutorul unei solutii brute force. In cazul acestei probleme solutia brute force presupunea calcularea unei matrici Win[x][y] = 1 daca (x, y) este castigatoare pentru primul jucator, 0 altfel.\r\n\r\nTotusi, pentru cei care vor sa demonstreze ca algoritmul de mai sus functioneaza iata cateva observatii care va pot ajuta:\r\n\r\n* $(a, b)$ si $(b, a)$ sunt echivalente\r\n* daca $(a, b)$ este configuratie pierzatoare atunci orice $(a, c)$ cu $c > b$ este configuratie castigatoare; de aici rezulta imediat ca pentru un $a$ fixat avem un singur $b$ pentru care $(a, b)$ e pierzatoare restul configuratiilor de forma $(a, x)$ fiind castigatoare\r\n\r\nh2. \'Dame 2\':problema/dame2\r\n\r\nProblema se rezolva prin metoda backtracking. Se iau toate posibilitatile de a aseza damele pe tabla de sah astfel incat oricare doua dame sa nu se atace. Ca sa intre in timp trebuiesc facute unele optimizari cum ar fi:\r\n\r\n* atunci cand punem o dama marcam linia, coloana, prima diagonala si a doua dioagonala pe care este dama ca fiind ocupate pentru ca mai tarziu sa stim ca pe acestea nu putem pune alta dama (optimizam verificarea pentru a vedea daca putem sa punem o dama pe o anumita pozitie sau nu)\r\n* tinem minte numarul minim de dame necesar gasit pana acum si in backtracking daca cumva trecem de acel numar cand cautam o solutie nu mai continuam pentru ca nu are sens (sigur am gasit o solutie cu numar de dame mai mic inainte) (initial acest numar este infinit)\r\n* dupa ce am gasit o solutie cu un anumit numar de dame verificam daca fiecare patratel este atacat de o dama in $O(1)$ folosindu-ne de informatiile stiute de la primul subpunct, si anume: un patratel $(x, y)$ este atacat de o dama daca cel putin una din linia, coloana, prima diagonala, a doua diagonala sunt marcate ca fiind o dama pe ele.\r\n',2028,'public',NULL,NULL),('preoni-2006/finala/solutii','Solutii preONI 2006, Runda finala','2006-03-26 00:00:00','2007-12-14 23:14:33','h1. Solutii preONI 2006, Runda finala\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa Infoarena_)\r\n\r\nSi iata-ne ajunsi in situatia de a trage concluziile dupa tot ce a insemnat preONI 2006. Toata comisia infoArena merita felicitata pentru organizarea si efortul depus de-a lungul campaniei. Inca odata multimim domnului profesor Onea pentru organizarea \"fara cusur\" :).\r\n\r\nFinala a fost ... \"Super. Super\", \"Super tare\", \"mda...a mers\" o spun concurentii. A fost grozav, intr-adevar, si ne-a facut mare placere sa va vedem prezenti intr-un numar atat de mare si veniti atat de departe. Va multumim pentru participare si speram ca ati petrecut un week-end pe cinste cu noi la Focsani.\r\n\r\nDupa cele patru runde online de concurs cu adevarat dure, cei 29 de concurenti si-au facut aparatia, de prin toate ungherele tarii, pe terenul de lupta. Desi in prima seara, la deschiderea ne-scortoasa si informala, concurentii isi zambeau sincer si fara vreun resentiment, in aer plutea \"emotia, tracul, tensiunea, stress-ul\".. Calmul dinaintea furtunii.. Venea marea confruntarea, batalia bataliilor, in urma careia trebuiau alesi castigatorii preONI 2006.\r\n\r\nConcursul s-a dovedit a fi o adevarata proba de foc, o batalie cu fum de creiere din plin si cu multe iesiri la toaleta (vezi \"Cronica\":preoni-2006/finala/cronica). Problemele, la limita imposibilului. Comisia a nascocit cele mai nastrusnice provocari pentru o finala in care participau concurenti adevarati, gata sa dea peste cap toate topurile Olimpiadelor ce vor voni. Muschi incordati, \"trac, tensiune, stress\". La sfarsit, punctaje reflectand truda demna de admirat a unor campioni alergand pe ultima suta de metri a unei curse in 5 acte. Castigatorii au fost sa fie, de acesta data, Cosmin Gheorghe la clasa a IX a, Simion Alexandru la clasa a X a si Marin Radu la clasele XI-XII. Ii felicitam pe ei si, in aceeasi masura, pe toti participantii care, desi au ratat premiile, cu siguranta au castigat prieteni noi.\r\n\r\nSa trecem la analiza problemelor cu care cei 29 concurenti nazdravani au avut de-a face in cele 5 ore ale finalei. Orice sugestie sau corectie privind articolul, solutiile problemelor v-o puteti exprima pe \"forum\":forum.\r\n\r\nh2. DivK\r\n\r\nh3. (problema usoara clasa a IX-a, problema usoara clasa a X-a)\r\n\r\nExista solutii evidente $O(N * (A-B))$ si $O(N * K)$ care obtin punctaje partiale si asupra carora nu se va insista in acest articol. Solutia care obtine insa $100$ de puncte este $O(N)$ si nu este greu de gasit, bazandu-se pe cateva observatii. Sa notam cu $S{~i~}$ suma primelor $i$ numere din sir. Pentru ca subsecventa intre pozitiile $i$ si $j$ sa aiba suma elementelor divizibila cu $K$, atunci $S{~j~}-S{~i-1~}$ trebuie sa fie divizibil cu $K$, sau altfel spus, $S{~i-1~}$ si $S{~j~}$ sa aiba acelasi rest la impartirea cu $K$. Daca stim sa aflam raspunsul problemei pentru subsecvente de lungime maxim $L$ si minim {$1$}, aplicand de doua ori algoritmul pentru $B$ si pentru $A-1$ si scazand cele doua valori obtinute vom obtine numarul de subsecvente cu proprietatea ceruta intre $A$ si $B$ inclusiv. Pentru a afla raspunsul pentru lungimea maxim $L$ procedam astfel: introducem in lista $LISTA{~r~}$ alocata dinamic pozitiile $i$ pentru care $S{~i~}$ da restul $r$ la impartirea cu $K$, in ordine crescatoare. Pentru fiecare rest de la $0$ la $K-1$ parcurgem lista corespunzatoarea, si, daca ne aflam pe un element cu valoarea $p2$ si elementul cel mai din stanga din lista curenta are valoarea $p1$ astfel incat $p2-p1 &le; L$, atunci cand avansam in lista nu mai este necesar sa incepem iterarea listei de la inceput pentru aflarea valorii cea mai din stanga, fiind suficient sa reluam cautarea din dreptul valorii $p1$. Astfel complexitatea algoritmului pentru o lista este $O(LUNGIME)$, unde $LUNGIME$ este lungimea unei liste, deci complexitatea intregului algoritm va fi $O(N)$, pentru ca lungimea tuturor listelor este $N$.\r\nO alta solutie de aceeasi complexitate dar mai rapida este urmatoarea: daca notam cu @v[r]@ de cate ori apare restul $r$ in numerele $S{~i-B~}...S{~i-A+1~}$ pentru pasul curent $i$, atunci la pasul $i+1$ este suficient sa decrementam $v[S{~i-B+1~}%K]$ si sa incrementam $v[S{~i-A+2~}%K]$. La fiecare pas $i$ vom aduna la solutia finala numarul $v[S{~i~}%K]$.\r\n\r\nh2. Lupul Urias si Rau\r\n\r\nh3. (problema medie clasa a IX-a)\r\n\r\nSe construieste vectorul $T{~i~}$ care retine timpul maxim la care oaia $i$ poate fi aleasa si notam $T_max$ valoarea maxima din {$T$}.\r\n\r\nO abordare care insa nu conduce la punctaj maxim este programarea dinamica, calculand $sol{~i,j~}$ cantitatea maxima de lana care se poate alege cu primele $i$ oi pana la momentul {$j$}. Raspunsul se va gasi in {$sol{~n,T_max~}$}. Complexitatea este $O(n^2^)$ si ar obtine aproximativ $50-60$ de puncte.\r\n\r\nO rezolvare ce aduce 100 de puncte se bazeaza pe metoda greedy. Pentru fiecare valoare $j$ de la $T_max$ la $1$ se adauga intr-o multime toate cantitatile de lana $A{~i~}$ pentru oile cu {$T{~i~}=j$}, apoi se extrage valoarea maxima care se adauga la solutie, restul valorilor pastrandu-se in multime pentru pasul urmator. Atentie, se va extrage valoarea maxima chiar daca la acest pas nu s-au introdus valori noi in multime. Pentru a implementa eficient aceste operatii ne vom folosi un heap care suporta operatiile de extragere maxim si adaugare element in {$O(log n)$}. Complexitatea finala a algoritmului va fi de {$O(n log n)$}. Demonstratia intuitiva a faptului ca algoritmul conduce la solutie optima este ca la fiecare pas $j$ se alege valoarea maxima dintre cele care nu vor mai putea fi alese la pasul {$j+1$}.\r\n\r\nO alta solutie tot greedy a problemei este sortarea descrescatoare dupa cantitatile de lana. Pentru fiecare valoare apoi se vede cel mai mare timp mai mic sau egal cu {$T{~i~}$} si la care nu a mai fost aleasa nici o alta oaie. Daca exista un astfel de timp se adauga valoare respectiva la solutie. Acest lucru se poate realiza cu o cautare binara a acestui timp. O alternativa la acest lucru ar fi folosirea multimilor disjuncte. Initial se considera fiecare moment de timp o multime. Notam $X$ = minimul din multimea care il contine pe {$T{~i~}$}. Daca alegem $A{~i~}$ pentru a-l adauga la solutie se va reuni multimea care il contine pe $X$ cu multimea care il contine pe {$X-1$}. Aceasta rezolvare insa este considerata peste nivelul mediu al clasei a 9-a.\r\n\r\nh2. Overlap\r\n\r\nh3. (problema grea clasa a IX-a)\r\n\r\nObservam ca exista doar $4$ rotatii posibile ale planului, facand abstractie de translatii. Daca $CMAX$ este coordonata maxima, atunci punctul ({$i, j$}) se transforma in ({$CMAX-j, i$}), iar dupa $4$ aplicari ale acestei transformari se ajunge din nou la punctul initial. Asadar, vom incerca pe rand fiecare dintre aceste posibilitati. Avand fixata o rotatie, stim ca punctul $1$ se transforma intr-un alt punct $i$ ({$i > 1$}), sau ca un punct $i$ se transforma in el. Cel de-al doilea caz este redundant, deoarece aplicand transformarea {$P{~i~} -> P{~1~}$}, vom lua in considerare si transformarea inversa. De exemplu, daca rotind planul cu $k*90$ de grade si translatandu-l cu $shift_X$ si $shift_y$ obtinem $P{~i~}$ din {$P{~j~}$}, atunci rotind planul cu $(4-k)*90$ grade si translatandu-l cu {$-shift_x$}, {$-shift_y$} vom obtine $P{~j~}$ din {$P{~i~}$}.\r\nOdata fixata rotatia pe care o consideram (inclusiv cea de $0$ grade), presupunem pe rand pentru fiecare punct $i > 1$ ca $P{~1~}$ se transforma in {$P{~i~}$}, si verificam daca aceasta presupunere conduce la o solutie valida. Presupunerea facuta stabileste in mod unic care este translatia efectuata. Retinem un vector $P{~i~}$ = punctul in care se transforma al {$i$}-lea punct dupa aplicarea rotatiei fixate si a translatiei determinate, sau $-1$ daca punctul transformat nu se regaseste printre cele initiale. Pentru a realiza in mod eficient aceasta operatie, la inceputul algoritmului punctele se sorteaza cu o functie de comparare oarecare si la fiecare pas punctul dorit se cauta binar in acest vector, in {$O(log N)$}. Eventual s-ar putea folosi un tabel de dispersie, insa consideram ca aceasta structura de date este prea complicata pentru nivelul clasei a 9-a si nu era necesara pentru obtinerea punctajului maxim.\r\n\r\nAvand vectorul {$P$}, va exista o structura de lanturi si cicluri rezultata in urma aplicarii repetate {$P[P[..P[i]]]$} asupra diverselor puncte. Se poate demonstra usor ca exista solutie daca si numai daca toate lanturile si toate ciclurile au lungime para; in acest caz solutia se poate obtine etichetand alternativ punctele consecutive dintr-un lant sau ciclu.\r\nComplexitatea algoritmului este $O(N^2^ * log N)$ pe cazul defavorabil folosind cautari binare pentru gasirea punctelor, sau $O(N^2^)$ pe cazul mediu folosind un hash (tabel de dispersie).\r\n\r\nh2. Iv\r\n\r\nh3. (problema medie clasa a X-a)\r\n\r\nSolutia simpla, calculata prin metoda programarii dinamice, se bazeaza pe mentinerea starilor ce asigura obtinerea solutiilor distincte. Astfel interclasarea celor doua siruri se va face in acelasi timp atat din stanga cat si din dreapta pentru a garanta pastrarea proprietatii de palindrom. Notand cele doua siruri $A$ si {$B$}, pastram $4$ indici: {$p{~1~}$}, {$p{~2~}$}, {$q{~1~}$}, {$q{~2~}$}, reprezentand pozitia ultimului caracter luat din stanga sirului {$A$}, ultimului luat din dreapta sirului {$A$}, ultimului din stanga sirului {$B$}, respectiv ultimului luat din dreapta sirului {$B$}.\r\n\r\nSe iau 4 cazuri de tranzitie intre stari:\r\n\r\n* ({$p{~1~}, q{~1~}, p{~2~}, q{~2~}$}) => ({$p{~1~}+1, q{~1~}-1, p{~2~}, q{~2~}$}), daca {$A[p{~1~} + 1] = A[q{~1~} - 1]$}\r\n* ({$p{~1~}, q{~1~}, p{~2~}, q{~2~}$}) => ({$p{~1~}+1, q{~1~}, p{~2~}, q{~2~}-1$}), daca {$A[p{~1~} + 1] = B[q{~2~} - 1]$}\r\n* ({$p{~1~}, q{~1~}, p{~2~}, q{~2~}$}) => ({$p{~1~}, q{~1~}-1, p{~2~}+1, q{~2~}$}), daca {$B[p{~2~} + 1] = A[q{~1~} - 1]$}\r\n* ({$p{~1~}, q{~1~}, p{~2~}, q{~2~}$}) => ({$p{~1~}, q{~1~}, p{~2~}+1, q{~2~}-1$}), daca {$B[p{~2~} + 1] = B[q{~2~} - 1]$}\r\n\r\nAceasta ne duce la un algoritm de complexitate {$O(|A|^2^ * |B|^2^)$}, ce ar fi asigurat obtinerea a $60%$ din punctaj. Simpla observare a faptului ca este suficienta pastrarea a numai trei indici, in loc de patru, pentru a pastra o stare completa (deoarece {$p{~1~} + p{~2~} = |A| - q{~1~} + 1 + |B| - q{~2~} + 1$}), duce la un algoritm de complexitate $O(|A|^2^ * |B|)$ ce ar fi obtinut punctaj maxim.\r\n\r\nh2. Robotei\r\n\r\nh3. (problema grea clasa a X-a)\r\n\r\nPentru a afla de cate ori trece un robotel prin pozitia (X Y) avem nevoie de urmatoarele informatii:\r\n\r\n# Cate mutari efectuam daca pornim din pozitia ({$X Y$}) si ajungem tot in ({$X Y$}) - lungimea ciclului care cuprinde pozitia ({$X Y$}). Daca pozitia ({$X Y$}) nu se afla pe un ciclu atunci lucrurile se simplifica (acesta este un caz special care se trateaza separat).\r\n# Cate mutari efectueaza fiecare robot pana ajunge in ({$X Y$}). Desigur, pot exista si roboti care nu ajung niciodata in ({$X Y$}).\r\n\r\nAflarea lungimii ciclului (punctul 1.) se face usor, pornind din pozitia ({$X Y$}), efectuand mutari pana se ajunge din nou in pozitia ({$X Y$}). Daca numarul de mutari depaseste $modX*modY$ si nu am atins inca pozitia ({$X, Y$}), atunci aceasta nu se afla pe un ciclu. Complexitatea acestui pas va fi {$O(modX * modY)$}.\r\nPentru a afla, pentru fiecare robot, numarul de mutari pentru a ajunge in ({$X Y$}), putem asocia un graf caroiajului, fiecarei celule din cele $N*N$ corespunzandu-i un nod in graful orientat construit. Pentru fiecare celula ({$i j$}) vom adauga o muchie orientata in acest graf intre nodul corespunzator celulei ({$i j$}) si nodul corespunzator celulei ( {$[i*i + offsetX] modulo modX , [j*j + offsetY] modulo modY$}). Fiecare nod din acest graf va avea gradul de iesire {$1$}, in consecinta, vor fi atatea muchii cate noduri sunt (adica {$N*N$}).\r\nPornind din pozitia ({$X Y$}), efectuam o parcurgere BFS a grafului INVERSAT si vom afla, pentru fiecare nod, care este numarul de mutari pe care trebuie sa le efectuam, pornind din celula corespunzatoare nodului, pentru a ajunge in pozitia ({$X Y$}). Nodurile care nu pot fi vizitate in aceasta parcurgere corespund unor celule din care nu se poate atinge pozitia ({$X Y$}).\r\nComplexitatea acestui algoritm este $O(N*N)$ si obtine $70%$ din punctaj. Pentru a obtine punctaj maxim, observam ca, dupa prima mutare toti roboteii se afla in caroiajul de dimensiuni ({$modX modY$}), si aplicam acelasi algoritm ignorand pozitiile care sunt in afara acestuia. Observatia precedenta ne permite sa afirmam ca daca un robot pleaca din pozitia ({$i, j$}) e ca si cum ar pleca, imaginar, din pozitia ({$i modX, j modY$}). Putem determina cati roboti pleaca (considerandu-i si pe cei care pleaca imaginar) dintr-o celula ({$i j$}) a caroiajului redus, determinand cate solutii au ecuatiile $x {@%@} modX = i$ si $y {@%@} modY = j$ ({$x$} si $y$ necunoscute) in intervalul [{$0..N-1$}].\r\n\r\nh2. PScNv\r\n\r\nh3. (problema simpla clasele XI-XII)\r\n\r\nAceasta problema a fost aleasa asa cum spune si textul pentru faptul ca sunt mai multe abordari ce rezolva problema. O prima abordare ar fi pentru un $k$ fixat sa vedem daca putem ajunge de la nodul start pana la nodul destinatie folosind doar muchii cu cost mai mic sau egal cu {$k$}. Verificarea acestui fapt o facem folosind o cautare in latime. Cat timp nu putem ajunge de la nodul start la nodul destinatie incrementam pe {$k$} si apoi aplicam o cautare in latime. Astfel aflam valoarea {$k$} minima ceruta in problema. Complexitatea acestui algoritm este {$O(kmax (n + m))$}. Daca notam $kmin$ valoarea ceruta in problema, atunci daca fixam un $k$ si nodul destinatie este accesibil din nodul start folosind doar muchii de pondere mai mica sau egale cu $k$ atunci este evident ca {$kmin &le; k$}, iar daca nodul destinatie nu este accesibil atunci {$kmin > k$}. Pe baza acestei observatii putem dezvolta un algoritm ce cauta binar valoarea $kmin$ ce are complexitatea {$O(log kmax (n + m))$}. O alta abordare se bazeaza pe o modificare usoara a algoritmului Dijkstra de drum minim, in care in loc sa pastram drumuri minime, pastram drumuri pt care muchia maxima are valoare cat mai mica. O implementare cu heapuri a acestui algoritm are complexitate {$O(m log n)$}. De asemenea algoritmul Bellman Ford poate fi modificat usor pentru a ne rezolva problema, chiar daca acest algoritm are complexitatea $O(n*m)$ in practica implementarea lui ce foloseste o lista se comporta cu mult mai bine. Ultimele trei rezolvari ar fi luat in jur de $70$ de puncte.\r\n\r\nSolutia oficiala se bazeaza tot pe o varianta a algoritmului Dijkstra, dar care in loc sa foloseasca un heap pentru a determina nodul $i$ inca neexpandat cu drumul de la sursa la el de cost minim, foloseste niste liste. Aceasta abordare este identica cu cea din problema \"Car\":http://infoarena.ro/task/car, si comisia se astepta ca multi concurenti sa rezolve perfect problema, asteptare infirmata de rezultatele din concurs. Cum ponderile muchiilor sunt numere de la $1$ pana la $1000$ inseamna ca in $d[i]$ oricare ar fi nodul $i$ va fi intotdeauna mai mica sau egala cu {$1000$}. Vom folosi astfel $1000$ de liste dublu inlantuite. In lista $i$ vom tine minte nodurile $x$ pentru care {$d[x] = i$}. Cand $d[x]$ se micsoreaza inseram pe $x$ intr-o lista mai mica, dar pentru a il sterge din lista veche vom folosi \"lazy deletion\". Adica atunci cand ajungem la lista $i$ si vrem sa expandam nodul $x$ verificam mai intai daca {$d[x] = i$}, daca nu inseamna ca $d[x] < i$ si nodul $x$ a fost expandat mai devreme, deci putem sa il ignoram. Acest algoritm are complexitate {$O(kmax + n + m)$}.\r\n\r\nComisia a mai discutat posibilitatea de a propune problema folosind un graf neorientat. Atunci o solutie similara algoritmului Kruskal ar fi avut complexitate aproape de cea optima. Am fi putut folosi un radix sort pentru a sorta muchiile, iar apoi sa adaugam muchii in ordine crescatoare la graf pana cand nodul start si nodul destinatie ar fi fost in aceiasi componenta conexa. Pentru a gestiona componentele conexe am fi folosit structuri de multimi disjuncte. Aceasta solutie ar fi avut complexitatea {$O(kmax + m log*n)$}.\r\n\r\nh2. Arbore\r\n\r\nh3. (problema medie clasele XI-XII)\r\n\r\nO prima idee de rezolvare a problemei are o complexitate de $O(1)$ la operatiile de tip update si $O(n)$ la operatiile de tip query. Cand intalnim o operatie de tip 1 este necesar sa folosim un vector $S[1..N]$ in care marcam aceste modificari. Astfel, adunand valoarea $s$ la elementul $S[p]$ vom observa ca suma pe care a primit-o un nod $X$ este de fapt suma valorilor $S[nod]$ unde $nod$ reprezinta indicele nodurilor din drumul lui $X$ pana la radacina arborelui. Deci, pentru o operatie de tipul 1 vom face o singura adunare, iar pentru o operatie de tipul 2 vom efectua o parcurgere in adancime pentru a cauta suma ceruta. Aceasta solutie obtine in jur de $30$ de puncte.\r\n\r\nO alta abordare ar fi reducerea problemei la nivel de vector. Am putea renumerota nodurile arborelui astfel incat subarborele fiecarui nod sa aiba id-uri consecutive. Acest lucru se poate face cu o parcurgere in adancime. Acum trebuie sa efectuam adunari pe intervale compacte de pe un vector, si trebuie sa gasim un element din vector ce are o anumita suma. Acest lucru se poate face, de asemenea in $O(1)$ pentru update si $O(N)$ pentru query usor. Aceasta solutie este mai rapida decat prima, deoarece nu foloseste apeluri recursive ale functiilor si efectueaza un numar mic de operatii. Asa s-ar fi luat $50-60$ de puncte In cazul in care problema s-ar fi redus la nivel de vector dar atat update-ul cat si querry-ul s-ar fi efectuat in $O(n)$ s-ar fi obtinut $30-40$ de puncte..\r\n\r\nSolutia care ar fi obtinut punctajul maxim se bazeaza pe reducerea problemei la nivel de vector, descrisa in paragraful precedent. Fie {$SEC = sqrt(N)$}. Putem imparti vectorul de lungime $N$ in $SEC$ secvente de lungime {$SEC$}. Vom mai folosi 3 vectori $A[1..N]$ reprezentand sumele pe fiecare element ce au fost adunate la inceputul secventelor de lungime {$SEC$}, $C[1..SEC]$ reprezinta sumele ce s-au adunat pe intregile secvente, iar $P[1..SEC][1..1 000 000]$ este o matrice binara unde $P[i][j] = 1$ daca exista un element din secventa $i$ astfel incat {$A[element] = j$}. Aceasta idee ne ajuta sa rezolvam problema intr-o complexitate de $O(sqrt(n))$ atat pentru query cat si pentru update. Pentru ca memoria folosita sa fie rezonabila implementarea matricii $P$ se face pe biti.\r\n\r\nh2. Pedefe\r\n\r\nh3. (problema grea clasele XI-XII)\r\n\r\nProblema cere determinarea numarului de subsiruri comune crescatoare al sirurilor $S1$ si $S2$ , care-l contin pe $S3$ ca subsir. Pentru a rezolva vom folosi metoda programarii dinamice. Se va construi un tabel $A$ cu semnificatia:\r\n$A[k,i,j]$ = cate subsiruri comune crescatoare exista tinand cont doar de primele $i$ valori ale lui {$S1$}, primele $j$ valori ale lui {$S2$}, si care sa contina ca subsir primele $k$ caractere din {$S3$}, iar ultima valoare din aceste subsiruri sa fie {$S1[i]$}. Valorile din tablou se vor calcula doar atunci cand {$S1[i] = S2[j]$}, in rest valorile vor fi {$0$}. In implementare, se vor pastra doar ultimele doua linii din tabloul {$A$}, {$A[k-1]$} si {$A[k]$}.\r\n\r\nIn continuare se vor prezenta mai multe implementari bazate pe aceasta idee cu diferite complexitati si care aduc punctaje diferite.\r\n\r\nh3. Solutia O(N^2^*M^2^*P) - 30 puncte\r\n\r\nPentru a calcula {$A[k, i, j]$} ne vom uita fie in {$A[k-1]$} daca {$S1[i] = S2[j] = S3[k]$}, fie in {$A[k]$} ({$S1[i] = S2[j]$}, {$S1[i] != S3[k]$}). Se vor aduna valorile {$A[k (sau k-1), p, q]$} cu {$p<i$}, {$q<j$} si {$S1[p] &le; S1[i]$}.\r\n\r\nh3. Solutia O(N*M^2^*P) - 50 puncte\r\n\r\nSe porneste de la solutia anterioara si se observa faptul ca pentru fiecare $q$ care se considera se poate preprocesa suma {$A[k (sau k-1), p, q]$} pentru $p < i$ intr-un tablou {$S$}. Dupa ce se calculeaza {$A[k, i, j]$} considerand doar acele $q$ pentru care {$S2[q] &le; S2[j]$}, se actualizeza {$S[k, j]$}.\r\n\r\nh3. Solutia O(N*M*P*Sigma) - 75 puncte\r\n\r\nIn cazul cel mai devaforabil numarul de valori distincte din siruri este {$min(N, M)$}, dar se garanteaza in enunt ca $Sigma$ (numarul de valori distincte) este $&le; 20$ pentru inca $25%$ din teste. Pornind de la solutia anterioara, se observa ca , parcurgand {$j$}-ul de la $1$ la {$M$}, nu este necesar sa consideram de fiecare data toate valorile {$q < j$}, aceste informatii putand fi actualizate in {$O(1)$}. Deoarece trebuie sa numaram doar valorile cu {$S2[q] &le; S2[j]$}, se pastreaza intr-un vector {$V[x]$} , suma {$q$}-urilor {$< j$} , cu {$S2[q] &le; x$}. Calculul lui {$A[k,i,j]$} se face in {$O(Sigma)$}, iar dupa aceasta se actualizeaza vectorul $V$ in {$O(1)$}.\r\n\r\nh3. Solutia O(N*M*P*lgSigma) - 100 puncte\r\n\r\nSolutia de $100$ este asemantoare cu solutia de $75$ de puncte, singura diferenta fiind folosirea unui arbore indexat binar pentru a face in $O(lg Sigma)$ operatiile desccrise mai sus.\r\n',1,'public',NULL,NULL),('autumn-warmup-2007/runda-2','Autumn Warm Up 2007','2007-09-20 13:11:23','2007-10-04 17:45:21','h1. Autumn Warm Up 2007\r\n\r\n(htabs)* \'Despre concurs\':autumn-warmup-2007/\r\n* \'Runda 1\':autumn-warmup-2007/runda-1\r\n*(active) \'Runda 2\':autumn-warmup-2007/runda-2\r\n* \'Runda 3\':autumn-warmup-2007/runda-3\r\n* \'Clasament\':autumn-warmup-2007/clasament\r\n\r\nRunda se va desfasura Duminica, 23 septembrie, la ora {*10^00^*} si va dura *5h*. Participantii vor avea de rezolvat 4 probleme de natura algoritmica. Evaluarea se va face la sfarsitul concursului.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"autumn2007-runda2\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"autumn2007-runda2\" score=\"1\")==\r\n\r\nSolutiile le gasiti \'aici\':autumn-warmup-2007/solutii/runda-2\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 2\':autumn-warmup-2007/clasament/runda-2\r\n\r\nh2. Organizatori\r\n\r\n* ==User(user=\"domino\" type=\"tiny\")==\r\n* ==User(user=\"svalentin\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"devilkind\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"mugurelionut\" type=\"tiny\")==',2092,'public',NULL,NULL),('blog/summer-challenge-2007/runda-1','Summer Challenge 2007, Runda 1','2007-07-29 21:58:55','2007-10-01 19:53:09','Te invitam sa participi la seria de concursuri \'Summer Challenge 2007\':summer-challenge-2007. Vom organiza 3 runde online, de cate 5h fiecare, cu probleme de dificultate variata.\r\n\r\nSummer Challenge este o ocazie buna de antrenament pentru tine (daca nu esti deja la mare :) dar si un ultim test pentru delegatia\r\nRomaniei la Olimpiada Internationala de Informatica 2007 (Croatia).\r\n\r\nAi ocazia sa concurezi cu lotul Romaniei la IOI 2007!\r\n\r\n&rarr; \'*Pagina concursului*\':summer-challenge-2007',1,'protected',NULL,NULL),('blog/summer-challenge-2007/runda-2-si-3','Summer Challenge 2007, Rundele 2 si 3','2007-08-09 09:04:49','2007-10-01 19:49:44','Rundele 2 si 3 ale concursului Summer Challenge se vor desfasura la 2 zile distanta. Mai exact:\r\n\r\n* \"Runda 2\":summer-challenge-2007/runda-2: Vineri, 10 august 2007, intre orele 10^00^ - 15^00^\r\n* \"Runda 3\":summer-challenge-2007/runda-3: Duminica, 12 august 2007, intre orele 10^00^ - 13^00^\r\n\r\nAi ocazia sa concurezi cu lotul Romaniei la IOI 2007!\r\nSucces!\r\n \r\n&rarr; \'*Pagina concursului*\':summer-challenge-2007',1,'protected',NULL,NULL),('autumn-warmup-2007/clasament','Autumn Warm Up 2007','2007-09-03 20:04:21','2007-10-04 17:45:38','h1. Autumn Warm Up 2007\r\n\r\n(htabs)* \'Despre concurs\':autumn-warmup-2007/\r\n* \'Runda 1\':autumn-warmup-2007/runda-1\r\n* \'Runda 2\':autumn-warmup-2007/runda-2\r\n* \'Runda 3\':autumn-warmup-2007/runda-3\r\n*(active) \'Clasament\':autumn-warmup-2007/clasament\r\n\r\nAcesta este clasamentul cumulat pe cele 3 runde online.\r\n\r\n== Rankings(rounds=\"autumn2007-runda1 | autumn2007-runda2 | autumn2007-runda3\") ==',2092,'public',NULL,NULL),('autumn-warmup-2007/runda-1','Autumn Warm Up 2007','2007-09-03 20:03:28','2007-10-04 17:45:05','h1. Autumn Warm Up 2007\r\n\r\n(htabs)* \'Despre concurs\':autumn-warmup-2007/\r\n*(active) \'Runda 1\':autumn-warmup-2007/runda-1\r\n* \'Runda 2\':autumn-warmup-2007/runda-2\r\n* \'Runda 3\':autumn-warmup-2007/runda-3\r\n* \'Clasament\':autumn-warmup-2007/clasament\r\n\r\nRunda se va desfasura Marti 11 septembrie, la ora {*10^00^*} si va dura *5h*. Participantii vor avea de rezolvat 4 probleme de natura algoritmica. Spre deosebire de anul trecut, evaluarea se va face la sfarsitul concursului.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"autumn2007-runda1\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"autumn2007-runda1\" score=\"1\")==\r\n\r\nSolutiile le gasiti \'aici\':autumn-warmup-2007/solutii/runda-1\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 1\':autumn-warmup-2007/clasament/runda-1\r\n\r\nh2. Organizatori\r\n\r\n* ==User(user=\"ditzonec\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"devilkind\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n* ==User(user=\"vlad_D\" type=\"tiny\")==\r\n',2092,'public',NULL,NULL),('autumn-warmup-2007/clasament/runda-2','Clasament autumn2007-runda2','2007-09-20 13:08:43','2007-10-06 20:02:56','h1. Clasament ==roundparam(round_id=\"autumn2007-runda2\" param=\"title\") ==\r\n\r\n(htabs)* \'Detalii\':autumn-warmup-2007/\r\n* \'Runda 1\':autumn-warmup-2007/runda-1\r\n*(active) \'Runda 2\':autumn-warmup-2007/runda-2\r\n* \'Runda 3\':autumn-warmup-2007/runda-3\r\n*(active) \'Clasament\':autumn-warmup-2007/clasament\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"autumn2007-runda2\")==',961,'round: autumn2007-runda2',NULL,NULL),('blog/romanii-la-disneyworld-partea-a-doua','Romanii la DisneyWorld - partea a doua','2007-12-04 18:18:14','2008-11-15 13:41:14','_Continuam seria de interviuri cu romanii ce au participat la finala concursului TopCoder Collegiate Challenge din toamna asta. Puteti citi prima parte \'aici\':blog/romanii-la-disneyworld-partea-intai . In aceasta parte Lucian Codrut Lazar ne va povesti despre concursurile de componente software si in special despre concursul de design software la care el s-a calificat in finala. Lucian are multa experienta cu aceste concursuri, a participat la 49 de competitii, a fost reviewer (membu al comisiei de corectori) la mai mult de 50 de componente, si a fost de doua ori reviewer la faza finala a concursului. In toamna asta a participat ca si concurent._\r\n\r\nh1. Lazar Codrut Lucian\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/romanii-la-disneyworld-partea-a-doua?luca.jpg! *Poti sa ne spui cate ceva despre concursul de software design? In ce consta el? Care sunt criteriile de notare, si care e partea dificila la un asemenea concurs?*\r\nIn fiecare saptamana (de obicei joi) sunt puse mai multe componente (Java sau C#) pentru care trebuie facut design (sau development) intr-o saptamana. La design se da un document cu cerinte si trebuie facuta diagrama de clase, o diagrama de use case si diagrame de secventa pentru metodele mai complexe. Diagrama de clase contine toate clasele de care e nevoie pentru a implementa cerintele, cu toate metodele si campurile folosite. Toti pasii si toate constrangerile trebuie documentate (documentatia e orientata spre developeri). Mai trebuie un document Word, cu diverse discutii: thread-safety, algoritmi, demo, ... Design-urile sunt corectate de 3 review-eri. Sunt sectiuni pentru abordarea folosita (sabloane folosite, componente reutilizate, class scope, easy-to-use) - asta e partea faina dintr-un design; sectiuni pentru documentatie - aici e mai multa munca patriotica; si sectiuni pentru modul de prezentare. Sa gandesti strucura componentei poate fi mai greu la inceput, dar asta e partea faina a concursului. Apoi intervine partea de documentatie, care ia mult timp si devine enervanta, fiindca stii ce vrei sa faca fiecare entitate sau ce sa scrii in documentul Word, doar ca trebuie sa explici complet si asta ia mult timp.\r\nLa development sunt implementate design-urile de pe locul 1. Se face unit testing si se scrie documentatie orientata utilizator.\r\n\r\n*De ce software design si nu oricare dintre celelalte sectiuni (algoritmica, software development, marathon ...)?*\r\nImi erau familiare sabloanele de proiectare si lucram la un framework pentru desenare de diagrame UML, deci stiam destul de bine UML. Sa incep la development mi-ar fi fost mai greu fiindca trebuia sa invat JUnit (sau NUnit) si parca nici nu prea am spor la implementare. La algoritmica am cam renuntat de cand am intrat la facultate, si oricum eram mult in urma ca nivel de cunostinte (plus ca tastez incet). \r\n\r\n*Cum ai recomanda cuiva sa inceapa sa participe la aceste competitii?*\r\nSa citeasca \'GoF\':http://www.google.com/search?hl=en&q=gang+of+four&btnG=Google+Search (cateva sabloane trebuie stiute: Strategy, Template Method, Abstract Factory, Observer, Adapter, Facade, Decorator). Trebuie intelese diagramele UML de care am zis mai sus. Un tutorial cred ca ajunge. Apoi intervine practica. In plus mai sunt forumuri publice, sau private pentru fiecare componenta. E bine sa intrebi orice nu e clar (despre sistem, despre componenta, despre diagrame, ...), fara frica de a parea penibil. In principiu, daca intrebi ceva cat de cat rezonabil, iti raspunde cineva repede si treci peste neclaritati.\r\n\r\n*Cum se ajunge la nivelul la care te poti califica la o faza finala pentru un asemenea concurs? Citesti carti? Proiecte facute de altii? Care e metoda de invatare?*\r\nInceputul e mai greu - asta poate e valabil la orice tip de competitie. Pe masura ce faci mai multe componente devii mai sigur pe tine, plus ca inveti pe parcurs si din greseli. E bine sa te uiti pe componentele facute de altii. Cel mai bine e sa alegi componente facute de cei cu rating mare, ca sa nu dai peste abordari dubioase, care mai mult te baga in ceata. In cateva luni ajungi aproape de potentialu propriu, si poti incerca oricand sa te califici la turnee. Doar ca trebuie mai multa munca.\r\n\r\n*Ce programe software se folosesc in software design in general si la topcoder in particular?*\r\nSe lucra in Poseidon, dar acum se trece pe TC UML Tool - utilitar UML facut de TopCoder special pentru concursurile lor. Si un editor de documente in format .rtf.\r\n\r\n*Care a fost proiectul facut la TopCoder care ti-a placut cel mai mult?*\r\nTC UML Tool ;-)\r\nDaca e vorba de componente, nu stiu ce sa zic. Mai recent - Graph Framework de la TCCC a fost interesanta, fiindca am avut libertate. Componentele in care sunt constrangeri de interfete sunt urate, fiindca nu prea e loc de o alta abordare si se rezuma doar la munca pentru documentatie.\r\n\r\n*De cate ore crezi ca ai nevoie pentru a face un design bun pentru o asemenea competitie?*\r\n16-20 ore efectiv. Plus mult timp petrecut citind cerintele, intreband pe forumuri si gandindu-te la componenta in timp ce mergi pe strada sau stai la o cafea.\r\n\r\n*Stiu ca in primavara ai fost in comisia ce evalua proiectele concurentilor la sectiunea software design pentru concursul TopCoder Open in Las Vegas. Cum e sa fi de partea cealalta a baricadei?*\r\nE aproape ca si cum ai face munca acasa, doar ca mergi acolo. Proiectele sunt mult mai de calitate (cel putin cele din top) decat ce vezi de obicei. Si iti ia mult mai mult timp sa la corectezi. Plus ca exista presiunea de a nu face vreo pozna sa dai scor prea mare sau prea mic si sa influentezi rezultatele. Asa ca trebuie sa insisti mai mult sa fii sigur ca ce au facut bine e intr-adevar bine si ce greseli ai gasit sunt intr-adevar greseli. Mie mi-a fost mai mult frica sa nu dau scor prea mare, fiindca la  appeal-uri nu poti micsora scorul. Pe review-eri ne-au izolat de concurenti, intr-o camera. Ne-a dat cafea si ceva de rontait. Deci a fost bine.\r\n\r\n*Ce caracteristici crezi ca trebuie sa aiba un designer bun?*\r\nMi-e cam greu sa raspund la intrebarea asta. Sa poata sa transforme cerinte textuale intr-o structura de clase care lucreaza impreuna pentru a atinge un scop. Nu stiu cum se numeste abilitatea asta. Trebuie sa ai o viziune de ansamblu, sa intelegi cum comunica mai multe componente, sa poti depista ce anume introduce limitari intr-o componenta, la fel cum ai depista unde se produce dead-lock intr-o aplicatie  multi-threaded, doar ca lucrezi numai cu diagrame si nu cu cod, deci nu poti scrie teste.\r\n\r\n_Mersi Luci ca ti-ai facut timp sa raspunzi la intrebari. Maine voi pune online interviul cu Mircea Pasoi._\r\n\r\n',1490,'protected',2447,NULL),('utilizator/unubou','Profil unubou','2007-10-04 15:15:29','2007-10-04 15:15:29','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6867,'public',NULL,NULL),('utilizator/kaya','Profil kaya','2007-10-04 15:21:55','2007-10-04 15:21:55','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6874,'public',NULL,NULL),('autumn-warmup-2007/clasament/runda-3','Clasament autumn2007-runda3','2007-10-04 17:26:08','2007-10-06 20:03:24','h1. Clasament ==roundparam(round_id=\"autumn2007-runda3\" param=\"title\") ==\r\n\r\n(htabs)* \'Detalii\':autumn-warmup-2007/\r\n* \'Runda 1\':autumn-warmup-2007/runda-1\r\n* \'Runda 2\':autumn-warmup-2007/runda-2\r\n*(active) \'Runda 3\':autumn-warmup-2007/runda-3\r\n*(active) \'Clasament\':autumn-warmup-2007/clasament\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"autumn2007-runda3\")==',961,'round: autumn2007-runda3',NULL,NULL),('autumn-warmup-2007','Autumn Warm Up 2007','2007-09-03 19:57:38','2007-10-04 17:45:53','h1. Autumn Warm Up 2007\r\n\r\n(htabs)*(active) \'Despre concurs\':autumn-warmup-2007/\r\n* \'Runda 1\':autumn-warmup-2007/runda-1\r\n* \'Runda 2\':autumn-warmup-2007/runda-2\r\n* \'Runda 3\':autumn-warmup-2007/runda-3\r\n* \'Clasament\':autumn-warmup-2007/clasament\r\n\r\nInainte sa dati piept cu greutatile scolare care va vor priva probabil de mult timp in care ati vrea sa va pregatiti la informatica :D, infoarena mai organizeaza un concurs de adio al vacantei si incalzire pentru un nou an scolar. Astfel concursul \"Autumn Warmup\" ajunge la editia a II-a, iar pentru cei care nu au participat anul trecut, acest concurs are si un factor mai interesant in ceea ce priveste organizarea: in loc sa fie organizat, ca de obicei, de membrii echipei infoarena, este organizat de niste membri obisnuiti.\r\n\r\nVa asteptam in numar cat mai mare, have fun :).\r\n\r\nh2. Program concurs\r\n\r\ntable{width: 50%}. |_. Runda|_. Data |_. Ora |\r\n|\"*Runda 1*\":autumn-warmup-2007/runda-1|*Marti, 11 septembrie 2007*| *10^00^ - 15^00^* |\r\n|\"*Runda 2*\":autumn-warmup-2007/runda-2|*Duminica, 23 septembrie 2007*| *10^00^ - 15^00^* |\r\n|\"*Runda 3*\":autumn-warmup-2007/runda-3|*Duminica, 7 octombrie 2007*| *10^00^ - 15^00^* |\r\n\r\nClick pe titlul unei runde pentru informatii detaliate.\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru.\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti probleme, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':/documentatie/evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nh2. Prima data pe infoarena?\r\n\r\ninfoarena ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi.\r\n\r\nVezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n\r\n\r\n',2092,'public',NULL,NULL),('blog/infoarena-isi-trage-blog','infoarea si-a tras blog','2007-10-10 00:00:11','2007-10-10 00:00:11','Ultimul feature adaugat la site este un \'blog\':blog. Va invitam sa il folositi si speram sa fie interesant si util.',58,'public',NULL,NULL),('problema/homm','Heroes of Might & Magic','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"homm\")==\r\n\r\nHarta Erathiei este data sub forma unui caroiaj cu $M$ linii si $N$ coloane. Terenul este impartit in celule care pot fi accesibile (au valoarea 0) sau inaccesibile (au valoare diferita de 0). Sir Christian doreste sa ajunga din celula de coordonate $(x{~1~}, y{~1~})$ unde a avut loc ultima batalie in celula $(x{~2~}, y{~2~})$ unde se afla Capitala regatului sau. Pentru aceasta el are la dispozitie $K$ mutari. O mutare consta in deplasarea din celula curenta intr-o celula invecinata (pe orizontala sau verticala, nu si pe diagonala).\r\nVa trebui sa determinati numarul variantelor pe care le poate alege Sir Christian. Un drum trebuie sa contina cel mult $K$ mutari, iar Sir Christian poate trece de oricate ori prin aceeasi celula, inclusiv prin celulele $(x{~1~}, y{~1~})$ si $(x{~2~}, y{~2~})$.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $homm.in$ se afla doua numere naturale $M, N$ si $K$, reprezentand numarul liniilor si coloanelor caroiajului, respectiv numarul mutarilor pe care Sir Christian le are la dispozitie; aceste numere sunt separate printr-un spatiu. Urmatoarele $M$ linii contin cate $N$ numere intregi, separate printr-un spatiu, reprezentand elementele caroiajului. Pe ultima linie se vor afla patru numere intregi, reprezentand valorile $x{~1~}, y{~1~}, x{~2~}$ si $y{~2~}$.\r\n\r\nh2. Date de Iesire\r\n\r\nIn fisierul de iesire $homm.out$ se va scrie un singur numar care va reprezenta numarul total al drumurilor posibile.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; M, N &le; 100$\r\n* $1 &le; K &le; 20$\r\n* Numarul total al drumurilor este intotdeauna mai mic decat $1.000.000.000$\r\n* Toate coordonatele sunt date in ordinea linie ({$x$}), coloana ({$y$}).\r\n\r\nExemple\r\n\r\ntable(example). |_. homm.in |_. homm.out |\r\n| 5 5 10 \r\n0 0 0 0 0\r\n0 2 0 3 0\r\n0 0 1 0 0\r\n0 2 0 0 0\r\n0 0 0 0 0\r\n1 1 5 5 | 34 |\r\n| 5 5 10 \r\n0 0 4 0 0\r\n0 2 0 3 0\r\n4 0 1 0 0\r\n0 2 0 0 0\r\n0 0 0 0 0\r\n1 1 5 5 | 0&nbsp; |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"homm\")==\n\n\n',1490,'task: homm',416,NULL),('problema/colectie','Colectie','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"colectie\")==\r\n\r\nTudor s-a gandit ca, deja, colectia lui de CD-uri si DVD-uri a devenit destul de impresionanta si, pentru a organiza mai usor discurile, vrea sa le numeroteze cu etichete. El vrea sa cumpere cutii care contin etichete cu cifre.\r\n\r\nLa magazinul din apropiere se gasesc k asemenea pachete care contin etichete cu cateva cifre de $0$, cateva cifre de $1$ si asa mai departe (pachete diferite pot avea continut diferit).\r\n\r\nTudor ar vrea sa cumpere cateva dintre pachete si sa poata forma din etichete toate numerele de la $1$ la $K$ ({$K$} fiind numarul de CD-uri si DVD-uri din colectie).\r\n\r\nO conditie pentru a realiza etichetarea este ar fi sa nu ramana etichete care nu sunt folosite pentru ca Tudor nu ar avea ce face cu ele. Acest lucru nu este tot timpul posibil. Daca este posibil, atunci ne intereseaza solutia care foloseste un numar minim de pachete.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $colectie.in$ se afla doua numere naturale $N$ si $K$, reprezentand numarul de pachete de la magazin, respectiv numarul de CD-uri si DVD-uri din colectia lui Tudor. Pe urmatoarele $N$ linii se vor afla cate zece numere intregi separate prin spatii; linia $i + 1$ contine numarul de etichete cu cifrele $0, 1, ... 9$ din pachetul $i$.\r\n\r\nh2. Date de Iesire\r\n\r\nIn fisierul de iesire colectie.out se va scrie pe prima linie valoarea $1$ daca exista o solutie, sau valoarea $0$ daca problema nu are solutie. Daca problema are solutie atunci pe urmatoarea linie va fi scris numarul $L$ al pachetelor folosite intr-o solutie optima, iar urmatoarea linie va contine $L$ numere intregi, reprezentand pachetele alese.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; N &le; 32$\r\n* $1 &le; K &le; 100.000.000$\r\n\r\nh2. Exemplu\r\n\r\n\r\ntable(example). |_. colectie.in |_. colectie.out |\r\n|4 11\r\n0 1 0 0 0 0 1 1 0 0\r\n1 2 1 1 1 1 0 0 0 0\r\n0 1 0 0 0 0 0 0 1 1\r\n0 2 0 0 0 0 1 1 1 1\r\n| 1\r\n2\r\n2 4 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"colectie\")==\n\n\n',1490,'task: colectie',417,NULL),('problema/frac','Frac','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"frac\")==\r\n\r\nPatratel este mare pasionat de fractii. Intr-o zi el se gandeste sa scrie pe o foaie de hartie, in ordine crescatoare, toate fractiile ireductibile cu numitorul $N$. Observand insa la timp ca sunt o infinitate de astfel de fractii, el nu se mai oboseste si doreste sa afle doar a $P$-a fractie din sirul la care s-a gandit.\r\n\r\nh2. Cerinta\r\n\r\nSa se determine numaratorul celei de a $P$-a fractii din sirul construit dupa regulile de mai sus.\r\n\r\nh2. Date de Intrare\r\n\r\nPrima linie a fisierului $frac.in$ contine doua numere intregi $N$ si $P$, separate prin cate un spatiu, avand semnificatia descrisa in enunt.\r\n\r\nh2. Date de Iesire\r\n\r\nPrima linie a fisierului $frac.out$ contine un numar natural care reprezinta numaratorul celei de a $P$-a fractii din sirul fractiilor ireductibile cu numitorul $N$.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 12 000 000 000$ ( $12$ miliarde )\r\n* $1 &le; P &le; 10^14^$\r\n* Se garanteaza ca rezultatul nu depaseste $2^61^$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. frac.in |_. frac.out |\r\n| 12 5 | 13 |\r\n\r\nh3. Explicatie\r\n\r\nFractiile sirului sunt: $1/12, 5/12, 7/12, 11/12, 13/12, 17/12$, etc. A $5$-a fractie din acest sir este $13/12$ si are numaratorul $13$.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"frac\")==\n\n\n',1490,'task: frac',421,NULL),('problema/pal','Pal','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"pal\")==\r\n\r\nPrintul Algorel este in incurcatura din nou: a fost prins de Spanul cel Negru in incercarea sa de a o salva pe printesa si acum este inchis in Turnul cel Mare. Algorel poate evada daca gaseste combinatia magica cu care poate deschide poarta turnului. Printul stie cum se formeaza aceasta combinatie magica: trebuie sa utilizeze toate cifrele scrise pe usa turnului pentru a obtine doua numere palindroame, astfel incat suma lor sa fie minima, iar aceasta suma este combinatia magica ce va deschide usa. Primul numar palindrom trebuie sa aiba cel putin $L$ cifre, iar cel de-al doilea poate avea orice lungime diferita de $0$. Numerele palindroame formate nu pot incepe cu cifra $0$. Acum interveniti dumneavoastra in poveste, fiind prietenul sau cel mai priceput in algoritmi. Prin noul super-telefon al sau, printul transmite numarul de aparitii a fiecarei cifre de pe usa turnului precum si lungimea minima $L$ a primului numar, iar dumneavoastra trebuie sa-i trimiteti cat mai repede numerele cu care poate obtine combinatia magica.\r\n\r\nh2. Cerinta\r\n\r\nAvand datele necesare, aflati doua numere palindroame cu care se poate obtine combinatia magica.\r\n\r\nh2. Date de Intrare\r\n\r\nPrima linie a fisierului $pal.in$ contine un numar intreg $L$ reprezentand lungimea minima a primului numar. Urmeaza 10 linii: pe linia $i+2$ se va afla un numar intreg reprezentand numarul de aparitii ale cifrei $i$, pentru $i$ cu valori de la $0$ la $9$.\r\n\r\nh2. Date de Iesire\r\n\r\nPrima linie a fisierului de iesire $pal.out$ contine primul numar palidrom, iar cea de-a doua linie contine cel de-al doilea numar palindrom. Daca exista mai multe solutii se va scrie doar una dintre ele.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* In total vor fi cel mult $100$ de cifre\r\n* $1 &le; L < 100$ si $L$ va fi mai mic decat numarul total de cifre\r\n* Pentru datele de test va exista intotdeauna solutie: se vor putea forma din cifrele scrise pe usa turnului doua numere care incep cu o cifra diferita de $0$, iar primul numar sa aiba cel putin $L$ cifre\r\n* Un numar este palindrom daca el coincide cu rasturnatul sau. De exemplu $12321$ si $7007$ sunt numere palindroame, in timp ce $109$ si $35672$ nu sunt.\r\n* Pentru $30%$ dintre teste, numarul total de cifre va fi cel mult $7$; pentru alte $40%$ din teste numarul total de cifre va fi cel mult $18$, iar pentru restul de $30%$ din teste numarul total de cifre va fi mai mare sau egal cu $30$\r\n* Fiecare linie din fisierul de intrare si din fisierul de iesire se termina cu marcaj de sfarsit de linie.\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. pal.in |_. pal.out |\r\n| 5 \r\n  3\r\n  2\r\n  3\r\n  0\r\n  0\r\n  0\r\n  0\r\n  0\r\n  0\r\n  0\r\n| 10001\r\n  222 |\r\n\r\nh3. Explicatii\r\n\r\nPentru acest exemplu avem L = 5, 3 cifre de 0, 2 cifre de 1 si 3 cifre de 2. Cifrele de la 3 la 9 lipsesc de pe usa turnului.\r\nCele doua palindroame cu care se genereaza combinatia magica sunt 10001 si 222. Combinatia magica va fi suma acestora si anume 10223 (care este suma minima pe care o putem obtine).\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"pal\")==\r\n\r\n\r\n',1490,'task: pal',424,NULL),('problema/camion','Camion','2006-11-11 11:23:41','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"camion\")==\r\n\r\nLa firma la care lucreaza Gigel exista $M$ tipuri de camioane, din fiecare tip existand $N$ exemplare. Gigel aseaza camioanele firmei pe $N$ randuri, asezand pe fiecare coloana numai camioane de acelasi tip. Se formeaza astfel o matrice in care liniile sunt numerotate de sus in jos de la $1$ la $N$, iar coloanele sunt numerotate de la stanga la dreapta de la $1$ la $M$.\r\n\r\nIn fiecare noapte vine o banda de hoti. Seful bandei anunta: \"in noaptea aceasta vom fura toate camioanele care se afla in zona dreptunghiulara avand coltul stanga-sus pe linia $x{~1~}$ si coloana $y{~1~}$, iar coltul opus pe linia $x{~2~}$ si coloana $y{~2~}$.\r\n\r\nIn dimineata urmatoare, Gigel vede acest lucru, si \"acopera\" furtul: pe fiecare linie in care exista spatii libere deplaseaza spre stanga toate camioanele care se afla in dreapta locului liber ramas.\r\n\r\nDe exemplu, pentru $N = 3$ si $M = 5$ initial avem urmatoarea amplasare:\r\n$1 2 3 4 5$\r\n$1 _*2 3*_ 4 5$\r\n$1 _*2 3*_ 4 5$\r\n\r\nIn prima noapte hotii fura camioane, din dreptunghiul cu coltul stanga-sus in linia $2$,coloana $2$ si coltul dreapta-jos linia $3$ coloana $3$. Astfel, in ziua urmatoare, dupa ce Gigel deplaseaza camioanele, amplasarea este urmatoarea:\r\n$_*1 2*_ 3 4 5$\r\n$_*1 4*_ 5$\r\n$_*1 4*_ 5$\r\n\r\nDaca in a doua noapte hotii fura din nou din dreptunghiul cu coltul stanga-sus in linia $1$, coloana $1$ si coltul dreapta-jos in linia $3$, coloana $2$, dupa deplasarile facute ziua de Gigel, amplasarea este urmatoarea:\r\n$3 4 5$\r\n$5$\r\n$5$\r\n\r\nh2. Cerinta\r\n\r\nCunoscand cate tipuri de camioane exista la firma initial, pe cate randuri au fost asezate, numarul $K$ de zile in care au loc furturi si coordonatele dreptunghiurilor din care fura hotii in fiecare noapte, determinati ce tipuri de camioane se afla pe o anumita coloana din amplasarea finala.\r\n\r\nh2. Date de Intrare\r\n\r\nFisierul de intrare $camion.in$ contine pe prima linie $4$ numere naturale: $N M K$ si $C$, reprezentand numarul de randuri pe care au fost asezate camioanele, numarul de coloane, numarul de nopti in care vor fura hotii camioane, respectiv numarul coloanei pentru care se doreste sa se afle ce tipuri de camioane contine la final. Pe fiecare dintre urmatoarele $K$ linii se vor afla cate $4$ numere naturale. Pe linia $i+1$ se afla $x{~1~} y{~1~} x{~2~} y{~2~}$, {$(x{~1~},y{~1~})$} reprezentand linia si coloana coltului stanga-sus, iar {$(x{~2~},y{~2~})$} linia si coloana coltului dreapta-jos al dreptunghiului din care fura hotii in noaptea $i$. Numerele situate pe aceeasi linie sunt separate prin cate un spatiu.\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul de iesire $camion.out$ va contine $N$ linii, pe fiecare cate un numar intreg. Numarul de pe linia $i$ va reprezenta tipul camionului de pe linia $i$ si coloana $C$, dupa $K$ zile. In caz ca pe linia $i$ nu se gaseste nici un camion, se va afisa valoarea $0$ pe linia respectiva.\r\n\r\nh2. Restrictii si observatii\r\n\r\n* $1 &le; N &le; 600$\r\n* $1 &le; C &le; M &le; 600$\r\n* $0 &le; K &le; 30000$\r\n\r\nNu este obligatoriu ca dreptunghiul din care se va efectua un furt sa contina camioane in fiecare loc.\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. camion.in |_. camion.out |\r\n| 3 5 3 1\r\n2 2 3 3\r\n1 1 3 2\r\n1 2 3 4\r\n| 3\r\n5\r\n5 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"camion\")==\n\n\n',1490,'task: camion',428,NULL),('problema/perle','Perle','2006-11-11 11:23:35','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"perle\")==\r\n\r\nGranita nu se trece usor. Asta pentru ca Balaurul Arhirel (mare pasionat de informatica) nu lasa pe nimeni sa treaca decat dupa ce raspunde la niste intrebari!\r\n\r\nIn acea tara exista $3$ tipuri de perle normale (le vom nota cu {$1$}, {$2$} si {$3$}) si $3$ tipuri de perle magice (le vom nota cu {$A$}, {$B$} si {$C$}). Perlele magice sunt deosebite prin faptul ca se pot transforma in alte perle (una sau mai multe, normale sau magice).\r\n\r\nPerla magica de tipul $A$ se poate transforma in orice perla normala (una singura).\r\n\r\nPerla magica de tipul $B$ se poate transforma intr-o perla normala de tipul $2$ si una magica de tipul {$B$}, sau intr-o perla normala de tipul {$1$}, una magica de tipul {$A$}, una normala de tipul {$3$}, una magica de tipul {$A$} si una magica de tipul {$C$}.\r\n\r\nPerla magica de tipul {$C$} se poate transforma intr-o perla normala de tipul {$2$} sau intr-o perla normala de tipul {$3$}, una magica de tipul {$B$} si una magica de tipul {$C$} sau intr-o perla normala de tipul {$1$}, una normala de tipul {$2$} si una magica de tipul {$A$}.\r\n\r\nCa sa rezumam cele de mai sus putem scrie:\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {$A -> 1 | 2 | 3$}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {$B -> 2B | 1A3AC$}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {$C -> 2 | 3BC | 12A$}\r\n\r\nBalaurul Arhirel ne lasa la inceput sa ne alegem o perla magica (una singura), iar apoi folosind numai transformarile de mai sus trebuie sa obtinem un anumit sir de perle normale. Cand o perla magica se transforma, perlele din stanga si din dreapta ei raman la fel (si in aceeasi ordine). De asemenea ordinea perlelor rezultate din transformare este chiar cea prezentata mai sus.\r\n\r\nDe exemplu, daca balaurul ne cere sa facem sirul de perle {$21132123$}, putem alege o perla magica de tipul {$B$} si urmatorul sir de transformari: {$B$} -> {$2B$} -> {$21A3AC$} -> {$21A3A12A$} -> {$21132123$}.\r\n\r\nDeoarece Balaurul nu are prea multa rabdare, el nu ne cere decat sa spunem daca se poate sau nu obtine sirul respectiv de perle.\r\n\r\nh2. Cerinta\r\n\r\nSa se determine pentru fiecare sir de intrare daca se poate obtine prin transformarile de mai sus sau nu (alegand orice prima perla magica, la fiecare sir).\r\n\r\nh2. Date de intrare\r\n\r\nFisierul de intrare $perle.in$ are urmatoarea structura: pe prima linie numarul {$N$}, reprezentand numarul de siruri din fisierul de intrare. Urmeaza $N$ linii; a $i$-a linie dintre cele $N$ descrie sirul {$i$}, printr-o succesiune de numere naturale despartite de cate un spatiu. Primul numar reprezinta lungimea sirului, {$L{~i~}$}, iar urmatoarele {$L{~i~}$} numere sunt tipurile de perle normale, in ordine, de la stanga la dreapta.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $perle.out$ va contine $N$ linii. Pe linia $i$ se va scrie un singur numar $1$ sau $0$ ({$1$} daca se poate obtine sirul al $i$-lea si $0$ daca nu se poate).\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $0 < N < 11$\r\n* $0 < L{~i~} < 10 001$, pentru $i$ de la $1$ la $N$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. perle.in|_. perle.out|\r\n|3\r\n8 2 1 1 3 2 1 2 3\r\n2 2 2\r\n1 3\r\n|1\r\n0\r\n1|\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"perle\")==\n\n\n',1490,'task: perle',688,NULL),('problema/proc','Proc','2006-11-11 11:23:42','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"proc\")==\r\n\r\n\r\nO aplicatie ce trebuie executata pe un calculator multi-procesor consta din $N$ fragmente de cod independente, ce pot fi rulate in paralel. Fiecare fragment trebuie executat in totalitate pe un singur procesor. Din dorinta de a paraleliza cat mai mult aplicatia, fragmentele de cod au dimensiuni mici si, in consecinta, timpi de executie mici. Mai precis, executia fiecarui fragment dureaza UNUL sau DOUA cicluri de ceas pe un procesor de tipul Pentium IV.\r\n\r\nSistemul pe care urmeaza sa fie executata aplicatia consta din $P$ procesoare. Spre deosebire de majoritatea sistemelor de acest fel, insa, cele $P$ procesoare au viteze de executie diferite. Primul procesor este un Pentium IV si este cel mai rapid. Al doilea procesor este de doua ori mai lent decat primul, al treilea de trei ori mai lent ... al $i$-lea procesor este de $i$ ori mai incet decat primul. In aceste conditii, timpul de executie al fiecarui fragment de cod difera, in functie de procesorul pe care va fi executat. Sa prespunem ca un segment de cod are timpul de executie $T$ (unde $T$ este $1$ sau {$2$}) pe primul procesor. Atunci pe un procesor $i$, timpul sau de executie va fi $i*T$.\r\n\r\nh2. Cerinta\r\n\r\nStiind ca fragmentele de cod pot fi executate in orice ordine si pe orice procesor si ca orice procesor poate executa, la un moment dat, un singur fragment de cod, determinati timpul minim dupa care se va termina executia aplicatiei (adica a tuturor fragmentelor de cod). Timpul dupa care se termina aplicatia este egal cu maximul dintre timpii dupa care fiecare procesor redevine disponibil. Timpul dupa care un procesor redevine disponibil este egal cu suma timpilor de executie a fragmentelor de cod rulate pe procesorul respectiv.\r\n\r\nh2. Date de intrare\r\n\r\nPrima (si singura) linie a fisierului de intrare $proc.in$ contine trei numere intregi, separate prin spatii: $N$ - numarul de fragmente de cod, $K$ - numarul de fragmente de cod care au timpul de executie pe un Pentium IV egal cu $1$ (implicit, $N-K$ au timpul de executie egal cu $2$) si $P$ - numarul de procesoare ale sistemului.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul $proc.out$ va contine o singura linie pe care se afla timpul minim dupa care se termina de executat aplicatia.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $0 &le; K &le; N &le; 1.000.000.000$\r\n* $1 &le; P &le; 65.535$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. proc.in |_. proc.out |\r\n| 4 3 2 | 4 |\r\n\r\nh3. Explicatie\r\n\r\nPe primul procesor se executa un fragment de cod cu timpul de executie (calculat pe un Pentium IV) egal cu $1$ si un fragment de cod cu timpul de executie egal cu $2$ => timpul dupa care acest procesor devine disponibil este $1*1 + 1*2 = 3$. Pe al doilea procesor se executa doua fragmente de cod cu timpul de executie (calculat pe un Pentium IV) egal cu $1$ => timpul dupa care acest procesor devine disponibil este $2$ [numarul de fragmente] * $(2*1)$ [timpul de executie al fiecarui fragment pe procesorul $2$] = $4$.\r\n==Include(page=\"template/taskfooter\" task_id=\"proc\")==\n\n\n',1490,'task: proc',465,NULL),('problema/delay','Delay','2006-11-11 11:23:41','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"delay\")==\r\n\r\n==include(page=\"template/badtests\")==\r\n\r\nGigel a cumparat $N$ calculatoare cu care vrea sa deschida un Internet Cafe. Pentru aceasta, el trebuie sa conecteze toate calculatoarele in retea, in asa fel incat oricare doua calculatoare sa poata comunica intre ele, direct sau indirect. Comunicatia dintre calculatoare se realizeaza prin intermediul cablurilor de legatura. Un cablu leaga doua calculatoare, iar transferul de date prin cablu se poate realiza in ambele sensuri. Fiind la inceput si neavand prea multi bani, Gigel a legat calculatoarele intre ele astfel incat intre oricare doua calculatoare exista un singur traseu pe care se pot transmite date.\r\nCurand si-a dat seama ca transferul de date se realizeaza cu viteza foarte mica. Acest lucru se datoreaza faptului ca fiecare pachet de date care trece prin calculatorul $i$ este pus sa astepte un timp {$T{~i~}$}. In aceste conditii, timpul dupa care un pachet de date ajunge de la un calculator la altul este egal cu suma timpilor de asteptare ai fiecarui calculator de pe traseu (inclusiv ai calculatoarelor sursa si destinatie).\r\nDin cand in cand, configuratia anumitor calculatoare este modificata si timpii de asteptare corespunzatori acelor calculatoare se schimba. Cum Gigel are grija foarte mare de calculatoarele sale, el trebuie sa fie mereu informat in legatura cu starea retelei. Mai precis, el trebuie sa poata afla repede care este timpul de transmitere a unui pachet de date intre oricare doua calculatoare din reteaua sa.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care trateaza in mod eficient urmatoarele doua tipuri de operatii:\r\n\r\n* tipul 1: modificarea timpului de asteptare al unui calculator\r\n* tipul 2: determinarea timpului de transmitere a unui pachet de date intre doua calculatoare specificate.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $delay.in$ se afla numarul $N$ de calculatoare. Pe fiecare dintre urmatoarele $N$ linii se afla cate un numar intreg {$T{~i~}$}, reprezentand timpul initial de asteptare al calculatorului corespunzator. Pe urmatoarele $N-1$ linii se afla cate doua numere intregi $a$ si {$b$}, reprezentand numerele a doua calculatoare legate printr-un cablu direct. Pe urmatoarea linie se afla numarul intreg {$M$}, reprezentand numarul de operatii descrise in continuare. Fiecare dintre urmatoarele $M$ linii contine cate $3$ numere intregi separate prin spatii: {$a b c$}.\r\n\r\n* Daca {$a=1$}, atunci $b$ reprezinta numarul de ordine al unui calculator nou configurat, iar $c$ reprezinta noul timp de asteptare al calculatorului $b$\r\n* Daca {$a=2$}, atunci $b$ si $c$ reprezinta numerele de ordine a doua calculatoare diferite, iar programul va trebui sa afiseze in fisierul de iesire timpul de transmitere a unui pachet de date intre calculatoarele $b$ si $c$\r\n\r\nh2. Date de Iesire\r\n\r\nIn fisierul $delay.out$ veti afisa, pe cate o linie separata, timpii determinati in cazul fiecarei operatii de tipul {$2$}, in ordinea in care sunt intalnite in fisierul de intrare. Atunci cand calculati timpul de transmitere a unui pachet de date intre doua calculatoare, trebuie sa considerati timpii de asteptare de la momentul respectiv (care sunt determinati de valorile initiale sau de operatiile de tipul $1$ descrise in fisierul de intrare inaintea operatiei curente).\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $2 &le; N &le; 16.000$\r\n* $0 &le; T{~i~} &le; 1.000$\r\n* $2 &le; M &le; 200.000$\r\n* Calculatoarele sunt numerotate de la $1$ la $N$\r\n* In fisierul de intrare va exista cel putin o operatie de tipul $2$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. delay.in |_. delay.out |\r\n| 5\r\n1\r\n2\r\n3\r\n4\r\n5\r\n1 2\r\n1 3\r\n2 4\r\n3 5\r\n6\r\n2 1 4\r\n2 3 1\r\n1 1 100\r\n2 1 4\r\n2 2 4\r\n2 2 3\r\n| 7\r\n4\r\n106\r\n6\r\n105 |\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"delay\")==\r\n\r\n\r\n',1490,'task: delay',456,NULL),('problema/gard3','Gard3','2006-11-11 11:23:41','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"gard3\")==\r\n\r\nFermierul Ion mai avea o ferma in forma de poligon convex cu $N$ laturi. Intr-o buna zi, el se hotaraste s-o imparta in $K$ regiuni, de asemenea poligoane convexe. Dupa impartire, el va folosi fiecare zona intr-un anumit scop (de exemplu, in zona $1$ va planta vita de vie, in zona $2$ va creste vaci etc.) Pentru aceasta, el va construi $K-1$ garduri. Fiecare gard va fi un segment care va uni doua varfuri din poligon. Gardurile nu se vor intersecta decat, eventual, in varfurile poligonului.\r\nInainte de a se apuca de treaba, fermierul Ion doreste sa afle in cate moduri poate imparti ferma sa in $K$ regiuni (pentru a le examina si a alege un anumit mod de impartire).\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care, pentru valorile $N$ si $K$ date, va afisa numarul de moduri in care fermierul Ion poate imparti ferma sa in $K$ regiuni.\r\n\r\nh2. Date de Intrare\r\n\r\nFisierul $gard3.in$ contine pe prima linie numerele naturale $N$ si {$K$}, separate printr-un spatiu.\r\n\r\nh2. Date de Iesire\r\n\r\nIn fisierul de iesire $gard3.out$ se va afisa numarul de moduri in care se poate imparti ferma in $K$ regiuni.\r\n\r\nh2. Restrictii\r\n\r\n* $3 &le; N &le; 50$\r\n* $1 &le; K &le; N-2$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. gard3.in |_. gard3.out |\r\n| 5 2 | 5 |\r\n\r\nh3. Explicatie\r\n\r\nSe construieste un singur gard. Acesta va uni una dintre  perechile de varfuri: \r\n$(1, 3) (1, 4) (2, 4) (2, 5) (3, 5)$.\r\n\r\ntable(example). |_. gard3.in |_. gard3.out |\r\n| 10 7 | 5005 |\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"gard3\")==\n\n\n',1490,'task: gard3',458,NULL),('problema/sistem','Sistem','2006-11-11 11:23:41','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"sistem\")==\r\n\r\nIntr-un judet exista $N$ orase, numerotate de la $1$ la $N$. Fiecare dintre cele $N$ orase ale judetului este legat de exact alte 2 orase, prin strazi bidirectionale. Si mai ciudat este faptul ca, in cadrul acestui sistem stradal, nu este intotdeauna posibil sa ajungi din orice oras in oricare alt oras mergand pe strazi. Oricum, locuitorii judetului sunt mandri de acest sistem al lor si sunt de parere ca nu mai exista altul la fel. Dumneavoastra vreti sa le demonstrati contrariul si pentru aceasta vreti sa calculati cate sisteme stradale distincte cu proprietatea de mai sus exista. Doua sisteme sunt considerate distincte daca exista cel putin o strada intre o pereche de orase $i$ si $j$ in cadrul primului sistem, care nu exista in cadrul celui de-al doilea.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care sa calculeze cate sisteme stradale distincte exista.\r\n\r\nh2. Date de intrare\r\n\r\nDin fisierul $sistem.in$ veti citi valoarea intreaga $N$, reprezentand numarul de orase ale judetului.\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul $sistem.out$ veti afisa o valoare intreaga, reprezentand numarul de sisteme stradale distincte, cu proprietatea ca orice oras este legat prin strazi directe de exact alte 2 orase.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $3 &le; N &le; 100$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. sistem.in|_. sistem.out|_. sistem.in|_. sistem.out|\r\n|4|3|6|70|\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"sistem\")==\n\n\n',1490,'task: sistem',459,NULL),('problema/doipatru','DoiPatru','2006-11-11 11:23:42','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"doipatru\")==\r\n\r\n\r\nMembrii Lotului National de Informatica sunt foarte mandri de noul joc inventat de ei, pe care l-au denumit asemanator cu o problema de la Olimpiada Internationala de Informatica din anul 2001, care le-a placut foarte mult. Astfel, jocul se numeste DoiPatru.\r\n\r\nPentru acest joc se folosesc $N$ gramezi, fiecare continand cel putin $0$ si cel mult $4$ bile. Numarul total de bile din toate gramezile este $2N$. Doi jucatori muta alternativ. Atunci cand ii vine randul, fiecare jucator este obligat sa efectueze o mutare valida.\r\n\r\nO mutare valida consta din alegerea a doua gramezi, dintre care prima gramada are mai multe bile decat cea de a doua. Jucatorul ia o bila din prima gramada si o muta in cealalta. Mutarea se considera valida, doar daca numarul de bile rezultat in a doua gramada dupa mutarea bilei nu este mai mare decat numarul de bile ramas in prima gramada.\r\n\r\nJocul se termina atunci cand nu mai poate fi efectuata nici o mutare valida (daca va ganditi putin, veti constata ca acest lucru se intampla atunci cand fiecare gramada contine doua bile).\r\n\r\nCastigatorul jocului este desemnat cel care detine mai multe gramezi la sfarsitul jocului. Bineinteles, daca cei doi jucatori detin un numar egal de gramezi, jocul se considera a fi remiza.\r\n\r\nUn jucator detine o gramada daca gramada are doua bile, iar acest numar (de doua bile) a rezultat in urma unei mutari efectuate de jucatorul respectiv. De exemplu, daca un jucator alege o gramada cu $4$ bile si una cu o bila, in urma efectuarii mutarii, el va detine cea de-a doua gramada (care va avea doua bile), dar prima nu va apartine deocamdata nici unuia dintre jucatori. Daca alege o gramada cu $3$ bile si una cu $0$ bile, jucatorul va deveni proprietarul primei gramezi, deoarece, in urma mutarii efectuate, gramada respectiva va ramane cu doua bile. In cazul in care alege o gramada cu $3$ bile si una cu o bila, dupa efectuarea mutarii, el va detine ambele gramezi (amandoua au acum doua bile).\r\n\r\nDaca un jucator este proprietarul unei gramezi la un moment dat in timpul jocului, nu inseamna ca aceasta gramada va ramane in posesia lui pana la sfarsit. De exemplu, sa presupunem ca jucatorul $1$ detine o gramada cu doua bile si este randul jucatorului $2$ sa mute. Daca acesta alege o gramada cu $4$ bile si gramada cu doua bile ce apartine jucatorului $1$, dupa efectuarea mutarii, ambele gramezi vor avea $3$ bile, iar numarul de gramezi aflate in posesia jucatorului $1$ va scadea cu $1$ (gramada detinuta de el anterior nu mai apartine nici unuia din cei doi jucatori, caci nu mai are doua bile).\r\n\r\nDaca la inceputul jocului exista unele gramezi avand doua bile, acestea sunt distribuite in mod egal celor doi jucatori. Daca numarul de gramezi cu doua bile este impar, atunci jucatorul $2$ va primi cu o gramada mai mult decat jucatorul $1$. Jucatorul $1$ este cel care efectueaza prima mutare.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care, pentru un $N$ dat si un set de configuratii initiale ale jocului cu $N$ gramezi, decide rezultatul fiecarei configuratii de joc.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare $doipatru.in$ se afla doi intregi: $N$ si $S$, reprezentand numarul de gramezi folosite in joc, respectiv numarul de configuratii initiale ale jocului, descrise in continuare. Pe urmatoarele $S$ linii se afla cate $N$ valori intregi din intervalul $[0, 4]$, a caror suma este egala cu $2N$, reprezentand cate o configuratie initiala a jocului.\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul de iesire $doipatru.out$, pentru fiecare configuratie initiala a jocului descrisa in fisierul de intrare, in ordinea in care sunt descrise acestea, afisati rezultatul final al jocului, in conditiile in care ambii jucatori joaca optim. Veti afisa valoarea $1$, daca jocul este castigat de primul jucator, valoarea $2$, daca jocul este castigat de cel de-al doilea sau valoarea $0$, daca jocul se termina remiza.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $3 &le; N &le; 30$\r\n* $1 &le; S &le; 1000$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. doipatru.in |_. doipatru.out |\r\n| 5 4\r\n0 3 4 1 2\r\n2 2 2 2 2\r\n1 1 2 2 4\r\n4 3 2 1 0\r\n| 1\r\n2\r\n1\r\n1 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"doipatru\")==\n\n\n',1490,'task: doipatru',460,NULL),('problema/hotel','Hotel','2006-11-11 11:23:42','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"hotel\")==\r\n\r\n\r\nHotelul \"Informatica\" este unul dintre cele mai luxoase hoteluri din Galaciuc. De-a lungul anului multe grupuri de turisti sosesc la acest hotel sau il parasesc la sfarsitul sejurului, asa ca situatia exacta a camerelor libere si ocupate este destul de greu de aflat, mai ales ca hotelul are un numar mare de camere. Dar anul acesta proprietarul hotelului s-a decis ca are nevoie de o schimbare. De aceea v-a angajat pe dumneavoastra pentru a scrie un program eficient, care sa raspunda necesitatilor sale.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care sa trateze in mod eficient urmatoarele $3$ tipuri de instructiuni:\r\n\r\n* tipul $1$: sosirea unui grup nou de turisti\r\n\r\nUn grup de turisti avand $M$ membri vrea sa ocupe $M$ camere libere numerotate consecutiv. Programului $i$ se va furniza numarul $i$ al camerei de inceput al secventei de camere ocupate de grup si numarul $M$ de membri ai grupului. Se garanteaza ca oricare din camerele $i,i+1,.., i+M-1$ este libera la momentul respectiv.\r\n\r\n* tipul $2$: plecarea unui grup de turisti\r\n\r\nAtunci cand pleaca, turistii pleaca in grupuri (nu neaparat cele cu care au venit). Un grup care pleaca si care are $M$ membri paraseste $M$ camere (anterior ocupate) numerotate consecutiv. Programului $i$ se va furniza numarul $i$ al camerei de inceput al secventei de camere eliberate, precum si numarul $M$ de membri ai grupului. Se garanteaza ca toate camerele cu numerele de ordine $i,i+1,..,i+M-1$ sunt deja ocupate de turisti.\r\n\r\n* tipul $3$: intrebarea proprietarului\r\n\r\nProprietarul hotelului poate sa intrebe, din cand in cand, care este lungimea maxima a unei secvente de camere libere numerotate consecutiv. El are nevoie de acest numar pentru a putea sti care este numarul maxim posibil de membri ai unui grup care ar putea fi cazati la hotelul \"Informatica\".\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului $hotel.in$ se vor afla numerele $N$ si $P$, reprezentand numarul de camere ale hotelului (numerotate de la $1$ la {$N$}), respectiv numarul de instructiuni care urmeaza. Pe fiecare din urmatoarele $P$ linii se va afla un numar $c$, reprezentand tipul instructiunii ce va fi descrisa pe linia respectiva:\r\n\r\n* daca $c$ are valoarea $1$, atunci el va fi urmat (pe aceeasi linie) de alte $2$ numere, $i$ si $M$, reprezentand numarul primei camere distribuite grupului abia sosit si numarul de membri ai grupului\r\n* daca $c$ are valoarea $2$, atunci el va fi urmat (pe aceeasi linie) de alte $2$ numere, $i$ si $M$, reprezentand numarul primei camere care va fi eliberata de grupul care tocmai pleaca, precum si numarul de membri ai grupului care paraseste hotelul\r\n* daca $c$ are valoarea $3$, el nu va fi urmat de nici un alt numar pe linia respectiva; programul va trebui, insa, sa afiseze in fisierul de iesire lungimea maxima a unei secvente de camere libere numerotate consecutiv.\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul hotel.out veti afisa, pentru fiecare instructiune de tipul 3, pe cate o linie separata, lungimea maxima a unei secvente de camere libere numerotate consecutiv, luand in considerare instructiunile de tipul 1 si 2 aflate in fisierul de intrare inaintea instructiunii de tip 3 la care se raspunde. Inaintea primei instructiuni, toate camerele sunt libere.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $3 &le; N &le; 100.000$\r\n* $3 &le; P &le; 200.000$\r\n* In orice camera poate fi cazat la un moment dat un singur turist.\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. hotel.in |_. hotel.out |\r\n| 12 10\r\n3\r\n1 2 3\r\n1 9 4\r\n3\r\n2 2 1\r\n3\r\n2 9 2\r\n3\r\n2 3 2\r\n3\r\n| 12\r\n4\r\n4\r\n6\r\n10 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"hotel\")==\n\n\n',1490,'task: hotel',462,NULL),('problema/asmin','Asmin','2006-11-11 11:23:42','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"asmin\")==\r\n\r\nSe considera un arbore (graf conex aciclic) cu $N$ varfuri, fara radacina fixata. Drept radacina, poate fi ales oricare dintre varfuri. Sa presupunem ca a fost ales varful cu numarul {$T$}. Intre oricare varf si $T$ exista un drum unic care contine fiecare varf al arborelui cel mult o singura data (un drum intre varfurile $i$ si $j$ este o secventa de varfuri, care incepe cu {$i$}, se termina cu {$j$}, iar intre oricare doua varfuri consecutive exista o muchie in arbore). Fiecarui varf {$i$}(inclusiv {$T$}) trebuie sa i se asocieze o valoare {$V{~i~}$}, mai mare sau egala cu {$0$}, astfel incat suma valorilor varfurilor de pe drumul dintre $i$ si radacina {$T$}, impartita la {$K$}, sa dea restul {$R{~i~}$}. Se defineste costul arborelui cu radacina fixata in {$T$}, {$C{~T~}$}, ca fiind suma valorilor asociate fiecarui nod. Dintre toate posibilitatile de alegere a valorilor $V{~i~}$ care respecta conditia precizata anterior, se va alege aceea pentru care $C{~T~}$ este minim.\r\nSe constata usor ca alegand alt varf drept radacina, de exemplu, varful {$S$}(diferit de {$T$}), $C{~S~}$ nu este neaparat egal cu {$C{~T~}$}.\r\n\r\nh2. Cerinta\r\n\r\nDandu-se un arbore cu $N$ varfuri, un numar intreg $K$ si valorile {$R{~i~}$}, {$i=1,2,..,N$}, corespunzatoare fiecarui varf, determinati acele varfuri $T$ care pot fi alese drept radacina, pentru care costul $C{~T~}$ este minim (adica {$C{~T~} &le; C{~S~}$}, oricare ar fi $S$ diferit de {$T$}), precum si costul respectiv.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $asmin.in$ se afla doua valori intregi: $N$ si {$K$}. Pe urmatoarele $N-1$ linii se afla cate doua numere intregi {$a b$}, separate printr-un spatiu, avand semnificatia ca exista muchie intre varfurile $a$ si {$b$}. Varfurile sunt numerotate de la $1$ la {$N$}. Pe urmatoarea linie se afla $N$ numere intregi, reprezentand valorile {$R{~i~}$}, {$i=1,2,..,N$}.\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie a fisierului de iesire $asmin.out$ se vor afisa doua valori intregi: $C$ si {$M$}. $C$ reprezinta costul minim posibil al arborelui. $M$ reprezinta numarul de varfuri care pot fi alese drept radacina si pentru care se obtine costul {$C$}. Pe a doua linie se afla $M$ numere intregi separate prin cate un spatiu, scrise in ordine crescatoare, reprezentand numerele varfurilor ce pot fi alese ca radacina astfel incat sa se obtina costul {$C$}.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $2 &le; N &le; 16.000$\r\n* $2 &le; K &le; 1.000$\r\n* $0 &le; R{~i~} &le; K-1$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. asmin.in |_. asmin.out |\r\n| 5 3\r\n1 2\r\n1 3\r\n2 4\r\n2 5\r\n0 1 2 1 0\r\n| 5 2\r\n1 5\r\n| \r\n\r\nh3. Explicatii\r\n\r\nValorile asociate varfurilor celor doi arbori sunt urmatoarele:\r\n$V{~1~}=0   V{~2~}=1  V{~3~}=2   V{~4~}=0   V{~5~}=2$\r\n$V{~1~}=2   V{~2~}=1  V{~3~}=2   V{~4~}=0   V{~5~}=0$\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"asmin\")==\n\n\n',1490,'task: asmin',464,NULL),('problema/parcele','Parcele','2006-11-11 11:23:42','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"parcele\")==\r\n\r\nPe o campie intinsa se afla $N$ copaci situati in puncte de coordonate intregi. Fermierul Ion doreste sa cumpere cateva parcele pe acea campie. Ion poate cumpara numai parcele de forma dreptunghiulara, cu laturile paralele cu axele de coordonate de pe harta zonei, cu dimensiunile intregi fixate ({$DX$} pentru axa $OX$ si $DY$ pentru axa $OY$) si avand colturile situate in puncte de coordonate intregi. Cumpararea unei parcele va trece in proprietatea lui Ion interiorul ei (se considera ca laturile parcelei fac parte din interior).\r\nNumarandu-si banii, Ion s-a hotarat sa cumpere exact DOUA parcele care, evident, sa nu aiba nici un punct comun. Deoarece lui Ion ii plac foarte mult copacii, el isi va alege o modalitate de amplasare a celor doua parcele astfel incat in interiorul lor (inclusiv pe laturi) sa se afle cat mai multi copaci. In acest scop, Ion va cere ajutorul.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care sa determine o modalitate de amplasare a parcelelor, astfel incat Ion sa detina cat mai multi copaci!\r\n\r\nh2. Date de intrare\r\n\r\nFisierul de intrare $parcele.in$ contine:\r\n- pe prima linie doua numere intregi $DX$ si $DY$, reprezentand dimensiunile unei parcele;\r\n- pe cea de a doua linie un numar intreg $N$, reprezentand numarul de copaci;\r\n- pe fiecare dintre urmatoarele $N$ linii cate doua numere intregi $X{~i~}$ si $Y{~i~}$, reprezentand coordonatele copacului cu numarul $i$.\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul de iesire $parcele.out$ veti afisa pe prima linie numarul maxim de copaci pe care ii poate detine Ion.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; DX, DY &le; 99.999$\r\n* $1 &le; N &le; 100.000$\r\n* coordonatele copacilor sunt numere intregi intre $0$ si $99999$ inclusiv\r\n* nu exista doi copaci situati in acelasi punct\r\n* parcelele pot fi plasate oriunde, cu conditia ca sa nu se intersecteze\r\n\r\nh2. Exemplu\r\n\r\n\r\ntable(example). |_. parcele.in |_. parcele.out |\r\n| 2 1\r\n7\r\n0 0\r\n1 0\r\n1 1\r\n3 0\r\n3 1\r\n4 0\r\n1000 1000\r\n| 6 |\r\n\r\nh3. Explicatii\r\n\r\nO solutie posibila este: prima parcela are colturile $(-1, 0)$ si $(1, 1)$ iar a doua parcela are colturile $(3, 0)$ si $(5, 1)$\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"parcele\")==\n\n\n',1490,'task: parcele',466,NULL),('problema/bifo','Bifo','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"bifo\")==\r\n\r\nPentru a-si vindeca rana provocata de Spanul cel Negru, printul Algorel are nevoie de leacul miraculos aflat in posesia vrajitoarei din padurea intunecata. Aceasta i-a promis leacul daca ii rezolva urmatoarea problema, la care ea s-a gandit zadarnic o mie de ani: pornind de la doua cuvinte initiale $A{~1~}$ si $A{~2~}$ si aplicand \"formula bifo\" $A{~n~} = A{~n-2~}A{~n-1~}$ pentru {$3 &le; n$}, se obtin cuvintele $A{~3~}, A{~4~}, A{~5~}$ s.a.m.d. Prin $A{~n-2~}A{~n-1~}$ intelegem concatenarea cuvintelor $A{~n-2~}$ si $A{~n-1~}$ in aceasta ordine. Toate aceste cuvinte ({$A{~1~} A{~2~}, A{~3~} A{~4~}, A{~5~}$} s.a.m.d), sunt la randul lor concatenate, in ordine, formand un sir de caractere infinit denumit sir magic. Formula leacului miraculos are $M$ caractere, pe care vrajitoarea nu le stie. Se stiu insa cele $M$ pozitii din sirul magic in care apar, in ordine, caracterele din formula.\r\n\r\nh2. Cerinta\r\n\r\nCu toata inteligenta lui, Algorel nu poate rezolva aceasta problema. Ajutati-l pe print sa iasa din incurcatura afland formula leacului magic.\r\n\r\nh2. Date de Intrare\r\n\r\nPrimele doua linii ale fisierului $bifo.in$ contin fiecare cate un sir de cel mult $100$ de caractere reprezentand cuvintele $A{~1~}$ (pe prima linie) si respectiv $A{~2~}$ (pe a doua linie). A treia linie contine un numar intreg {$M$}, reprezentand numarul de caractere din formula leacului miraculos. Urmeaza $M$ linii descriind, in ordine, pozitiile din sirul magic unde se gasesc caracterele din formula.\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul de iesire $bifo.out$ va contine pe prima linie un sir de $M$ caractere reprezentand formula leacului miraculos.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; M &le; 100$\r\n* $A{~1~}$ si $A{~2~}$ contin doar litere mici ale alfabetului englez\r\n* Numerotarea pozitiilor din sirul infinit incepe cu $1$\r\n* Cele $M$ pozitii vor fi numere intregi (nu neaparat distincte) de maxim $100$ de cifre\r\n* Pentru $60%$ din teste pozitiile vor fi numere intregi intre $1$ si $1.000.000.000$\r\n* Fiecare linie din fisierul de intrare si din fisierul de iesire se termina cu marcaj de sfarsit de linie\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. bifo.in |_. bifo.out |\r\n| ab\r\ncdx\r\n3\r\n10\r\n4\r\n15\r\n| xdb |\r\n\r\nh3. Explicatii\r\n\r\nPrimele 5 siruri de caractere ob&#254;inute folosind formula bifo sunt:\r\n*ab, cdx, abcdx, cdxabcdx, abcdxcdxabcdx*\r\nConcatenand aceste siruri se ob&#254;ine sirul magic:\r\n{*abcdxabcdxcdxabcdxabcdxcdxabcdx*}...\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"bifo\")==\n\n\n',1490,'task: bifo',425,NULL),('problema/car','Car','2006-11-11 11:23:38','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"car\")==\r\n\r\nIonel a implinit 18 ani si a luat permisul de conducere, azi vrea sa mearga de la el acasa pana la scoala cu masina si singura conditie pe care i-a impus-o tatal sau e aceea de a nu lua foarte multe curbe! Pentru a primi masina si alta data, Ionel vrea sa il impresioneze pe tatal sau si sa mearga pe drumul cel mai putin costisitor din punct de vedere al curbelor. Orasul e reprezentat de o matrice de $N$ linii si $M$ coloane, un element al matricii fiind $0$ daca pe acolo poate trece masina si $1$ daca nu. Masina se poate misca dintr-o celula a matricii in toate cele $8$ celule adiacente, daca ele sunt libere. Costul unui drum de la pozitia initiala la pozitia finala este data de suma costurilor miscarilor. O miscare in directia de mers are costul {$0$}, o miscare la $45$ de grade fata de directia de mers are costul {$1$}, o miscare la $90$ de grade are costul {$2$}, una la $135$ de grade are costul $3$ iar una la $180$ de grade are costul {$4$}. La momentul initial masina poate porni in oricare dintre cele $8$ directii, daca celula din directia respectiva este marcata cu {$0$}.\r\n\r\nh2. Cerinta\r\n\r\nDeterminati pentru Ionel costul minim din punct de vedere al curbelor de la o pozitie initiala la o pozitie finala.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $car.in$ se gasesec doua numere naturale: $N$ (numarul de linii al matricii) si $M$ (numarul de coloane al matricii). Pe urmatoarea linie sunt numerele $Si$ - linia pozitiei initiale a masinii lui Ionel, $Sj$ - coloana pozitiei initiale ale masinii lui Ionel, $Fi$ - linia pozitiei finale, $Fj$ - coloana pozitiei finale. Pe urmatoarele $N$ linii sunt cate $M$ numere de $0$ sau {$1$}.\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie a fisierului de iesire $car.out$ se va gasi costul minim al unui drum de la pozitia initiala la pozitia finala. Daca nu exista nici un drum se va afisa {$-1$}.\r\n\r\nh2. Restrictii\r\n\r\n* $0 &le; N, M &le; 500$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. car.in |_. car.out |\r\n| 5 5\r\n1 1 1 4\r\n0 1 1 0 1\r\n1 0 1 0 1\r\n0 1 1 1 0\r\n1 0 1 0 1\r\n1 1 0 1 1\r\n| 9 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"car\")==\n\n\n',1490,'task: car',243,NULL),('problema/trapeze','Trapeze','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"trapeze\")==\r\n\r\nDaca te joci cu $N$ obiecte identice de forma rotunda si incerci sa formezi diferite forme cu toate obiectele, apar figuri interesante. Una dintre figurile cele mai frumoase este trapezul. El este format din mai multe linii (cel putin una). Pe prima linie stau $A$ obiecte ({$A &ge; 1$}). Pe urmatoarea linie (daca exista) stau $A+1$ obiecte, si tot asa pana se folosesc toate obiectele. De exemplu, cu $15$ obiecte putem forma $4$ trapeze distincte:\r\n\r\n# {$&nbsp;&nbsp;&nbsp;&nbsp;*$}\r\n{$&nbsp;&nbsp;&nbsp;* *$}\r\n{$&nbsp;&nbsp;* * *$}\r\n{$&nbsp;* * * *$}\r\n{$* * * * *$}\r\n# {$&nbsp;&nbsp;* * * *$}\r\n{$&nbsp;* * * * *$}\r\n{$* * * * * *$}\r\n# {$&nbsp;&nbsp;* * * * * * *$}\r\n{$&nbsp;* * * * * * * *$}\r\n# {$* * * * * * * * * * * * * * *$}\r\n\r\nEste important ca toate piesele sa fie folosite in constructia oricarui trapez si toate liniile sa fie complete. Este foarte usor sa determini pentru un numar dat de obiecte care este numarul total de trapeze distincte ce se pot forma. De exemplu, pentru $15$ obiecte numarul total de trapeze este $4$. Mai greu este sa determini care este numarul minim de obiecte necesare pentru a putea forma in total exact $K$ trapeze distincte.\r\n\r\nh2. Cerinta\r\n\r\nPentru valoarea lui $K$ data, determinati numarul minim de obiecte necesare pentru a forma exact $K$ trapeze.\r\n\r\nh2. Date de intrare\r\n\r\nFisierul de intrare $trapeze.in$ va contine pe prima linie numarul natural $K$.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $trapeze.out$ va contine o singura linie pe care va fi scris numarul minim de obiecte necesare pentru a forma in total exact $K$ trapeze.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; K &le; 100$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. trapeze.in |_. trapeze.out |\r\n|4|15|\r\n|5|81|\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"trapeze\")==\n\n\n',1490,'task: trapeze',420,NULL),('problema/barman','Barman','2006-11-11 11:23:38','2009-09-10 08:13:30','==Include(page=\"template/taskheader\" task_id=\"barman\")==\r\n\r\nPaftenie a decis sa se faca barman. Inainte de asta trebuie sa dovedeasca abilitate in manevrarea bauturilor. Barul lui Paftenie este alcatuit din $N$ camere aliniate in cerc. In fiecare camera se afla un pahar cu bautura, fiecare bautura avand o anumita valoare (cuprinsa intre $1$ si $2.000.000.000$). El trebuie sa mute bauturile dintr-o camera in alta astfel incat la sfarsit, bauturile sa fie sortate dupa camere. Daca la sfarsit in camera $i$ se afla o bautura cu valoarea $a{~i~}$, sirul valorilor $a{~1~},a{~2~}...a{~N~}$ se considera sortat daca exista $1 &le; i &le; N$ astfel incat $a{~i~} &le; a{~i+1~} &le; ... &le; a{~N~} &le; a{~1~} &le; ... &le; a{~i-1~}$ (sirul este circular). In orice moment, Paftenie poate tine pe tava cel mult doua pahare. Pentru deplasarea bauturilor, poate efectua urmatoarele mutari:\r\n\r\n* poate lua un pahar din camera in care se afla si sa il aseze pe tava (il costa $10$ secunde)\r\n* poate lasa un pahar intr-o camera in care nu se afla nici o bautura (il costa $10$ secunde)\r\n* se poate deplasa din camera $i$ in camera $j$ avand pe tava $c$ pahare ({$0 &le; c &le; 2$}) (il costa $c*|i-j|$ secunde)\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l pe Paftenie sa sorteze paharele intr-un timp minim!\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $barman.in$ este dat numarul $N$ al bauturilor. Pe urmatoarea linie se afla $N$ intregi reprezentand valorile bauturilor - al $i$-lea numar reprezinta valoarea bauturii aflate initial in camera $i$ ({$a{~i~}$}).\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul $barman.out$ va contine pe prima linie un singur numar reprezentand timpul minim de sortare a bauturilor.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 600$\r\n* In orice moment, in afara de paharele care le are Paftenie pe tava, intr-o camera poate exista maxim un pahar\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. barman.in |_. barman.out |\r\n| 4\r\n1 5 2 2\r\n| 42 |\r\n\r\nh3. Explicatii\r\n\r\n$o 5 2 2$ merge in camera $1$ si pune paharul de acolo pe tava ({$10$}s)\r\n$o 5 2 2$ merge din camera $1$ in camera $2$ cu un pahar pe tava ({$1$}s)\r\n$o o 2 2$ pune pe tava paharul din camera $2$ ({$10$}s)\r\n$o 1 2 2$ asaza pe masa din camera $2$ paharul cu bautura de valoare $1$ ({$10$}s)\r\n$o 1 2 2$ se intoarce in camera $1$ cu un pahar pe tava ({$1$}s)\r\n$5 1 2 2$ asaza pe masa din camera $1$ paharul cu bautura de valoare $5$ ({$10$}s)\r\n&#8594; $42$ de secunde\r\nsirul este sortat deoarece {$1 &le; 2 &le; 2 &le; 5 (a2 &le; a3 &le; a4 &le; a1)$}\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"barman\")==\r\n\r\n\r\n',1490,'task: barman',303,NULL),('problema/stramosi','Stramosi','2006-11-11 11:23:34','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"stramosi\")==\r\n\r\nFamilia lui Gigel este foarte numeroasa, avand exact $N$ membri. Fiecare membru stie cine este stramosul lui direct, mai putin cativa membri care sunt foarte batrani si nu mai tin minte nici macar cine a fost stramosul lor direct. Gigel, fiind o fire curioasa a facut un inventar al familiei sale, in sensul ca a numerotat fiecare membru cu un numar distinct intre 1 si $N$ si stie de asemenea pentru fiecare membru, care este stramosul lui direct (daca acesta exista). Curiozitatea lui este si mai mare, in sensul ca isi pune $M$ intrebari de forma: _\"Care este al $P$-lea stramos al membrului cu numarul $Q$?\"_.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care raspunde corect la toate cele M intrebari ale lui Gigel.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linia a fisierului $stramosi.in$ se afla numerele $N$ si $M$. Pe a doua linie se afla $N$ numere intregi, reprezentand stramosii tuturor membrilor, incepand cu membrul $1$ si terminand cu membrul $N$. Daca un membru nu are stramos, atunci in fisier se va afla numarul $0$. Pe urmatoarele $M$ linii se afla perechi de numere $Q$ si $P$, reprezentand o intrebare de forma: _\"Care este al $P$-lea stramos al membrului cu numarul $Q$?\"_.\r\n\r\nh2. Date de iesire\r\n\r\nPe fiecare din cele $M$ linii ale fisierului $stramosi.out$ se vor afla raspunsurile la intrebari, adica numerele de ordine al stramosilor (sau $0$ daca identitatea stramosului nu este cunoscuta)\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 250 000$\r\n* $1 &le; M &le; 300 000$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. stramosi.in |_. stramosi.out |\r\n|13 7\r\n0 1 2 2 4 1 6 0 8 8 10 10 12\r\n5 2\r\n3 2\r\n7 1\r\n1 3\r\n13 3\r\n9 2\r\n11 1\r\n|2\r\n1\r\n6\r\n0\r\n8\r\n0\r\n10\r\n|\r\n\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"stramosi\")==\n\n\n',1490,'task: stramosi',37,NULL),('problema/joc','Joc','2006-11-11 11:23:34','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"joc\")==\r\n\r\nGicu si Nicu, olimpici la informatica si buni prieteni, mereu incearca sa imbine activitatile lor cu informatica. Spre exemplu, cand se plictisesc in ore ei joaca un joc, bazat pe urmatoarele reguli:\r\n\r\n* fie o matrice cu numere intregi cu $N$ linii si $M$ coloane\r\n* fiecare jucator muta alternativ un jeton plasat pe un element din matrice\r\n* o mutare consta in plasarea jetonului pe o alta pozitie si adaugarea valorii din matrice de pe pozitia respectiva la scorul jucatorului care a facut mutarea; odata plasat jetonul pe o pozitie, jucatorul urmator poate sa mute jetonul doar pe o alta pozitie din dreptunghiul format de coltul stanga-sus si pozitia curenta a matricei\r\n* jocul se termina cand un jucator ajunge cu jetonul in coltul stanga-sus al matricei\r\n* la inceputul jocului, ambii jucatori au scor {$0$}, iar jucatorul care incepe alege pozitia initiala a jetonului\r\n\r\nh2. Cerinta\r\n\r\nPresupunand ca fiecare din cei doi joaca optim, si ca Gicu va incepe jocul, determinati pozitia initiala a jetonului, astfel incat diferenta de scor intre Gicu si Nicu sa fie maxima!\r\n\r\nh2. Date de Intrare\r\n\r\nPrima linie a fisierului $joc.in$ contine doua numere intregi $N$ si {$M$}, separate prin cate un spatiu, care reprezinta numarul de linii si coloane ale matricii. Urmatoarele $N$ linii contin cate $M$ numere intregi, separate prin cate un spatiu, care descriu matricea.\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul $joc.out$ va contine trei numere intregi separate prin cate un spatu: diferenta maxima de scor intre Gicu si Nicu si linia si coloana unde se va plasa jetonul la inceputul jocului.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N, M &le; 1.000$\r\n* Valorile din matrice sunt cuprinse in intervalul [{$-1.000, 1.000$}]\r\n* Liniile sunt numerotate de la $1$ la {$N$}, iar coloanele de la $1$ la $M$\r\n* Prin joc optim se intelege ca Gicu va incerca sa maximizeze diferenta de scor, in timp ce Nicu va incerca sa o minimizeze\r\n* Daca exista mai multe pozitii initiale pentru care se obtine diferenta maxima, atunci se va alege cea in care numarul liniei este cel mai mic, iar in caz de egalitate cea in care numarul coloanei este cel mai mic\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. joc.in |_. joc.out |\r\n| 1 6\r\n2 1 3 4 0 5\r\n| 3 1 6 | \r\n\r\nh3. Explicatii \r\n\r\nIncepand din ({$1, 6$}) jocul optim este: Gicu ia {$5$}, Nicu ia {$4$}, Gicu ia {$2$}. \r\nOrice alta pozitie initiala a jetonului ar fi dus la obtinerea unei diferente de scor mai mica.\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"joc\")==\n\n\n',1490,'task: joc',43,NULL),('problema/biti','Biti','2006-11-11 11:23:33','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"biti\")==\r\n\r\nGigel este pasionat de informatica, si mai ales de cifrele $0$ si {$1$}; asa de mult, incat a atribuit fiecarui din cei $2^N^$ prieteni ai lui cate o eticheta, sub forma unui sir de biti de lungime {$N$}. Toate etichetele sunt distincte intre ele.\r\nGigel s-a gandit intr-o zi ca vrea sa construiasca o eticheta pentru el insusi, de lungime cat mai mica, care sa contina o singura data, ca o subsecventa, fiecare din cele $2^N^$ etichete ale prietenilor lui.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care determina eticheta lui Gigel, de lungime minima.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $biti.in$ se va gasi numarul $N$\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie a fisierului de iesire $biti.out$ se va gasi lungimea sirului. Pe a doua linie se va afisa un sir de biti $0$ sau $1$ care vor reprezenta eticheta gasita.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 20$\r\n* Daca exista mai multe solutii de lungime minima, se va afisa cea minima din punct de vedere lexicografic\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. biti.in |_. biti.out |\r\n| 3\r\n| 10\r\n0001011100 |\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"biti\")==\n\n\n',1490,'task: biti',30,NULL),('problema/zero','Zero','2006-11-11 11:23:35','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"zero\")==\r\n\r\nSe considera numai numerele de $L$ cifre scrise intr-o baza $B$ ({$2 &le; B < L &le; 20$}), in care prima cifra (cea mai semnificativa) este diferita de $0$.\r\n\r\nh2. Cerinta:\r\n\r\nDandu-se doua numere $P$ si $Q$ ({$2 &le; P,Q &le; L-1$}), se cere:\r\n\r\na) cate numere exista cu cel mult $P$ cifre $0$ (zero) consecutive.\r\n\r\nb) cate numere exista cu cel putin $Q$ cifre $0$ (zero) consecutive.\r\n\r\nh2. Date de intrare\r\n\r\nPrima linie a fisierului de intrare $zero.in$ contine numerele $L$, $B$, $P$ si $Q$, separate prin spatii.\r\n\r\nh2. Date de iesire\r\n\r\nPrima linie a fisierului de iesire $zero.out$ contine numarul cerut la punctul a), in timp ce pe a doua linie a fisierului se va afla numarul cerut la punctul b).\r\n\r\nh2. Exemplu:\r\n\r\ntable(example). |_. zero.in |_. zero.out |\r\n|3 2 1 2\r\n|3\r\n1|\r\n\r\n\r\nPentru cel mult o cifra de zero avem numerele $101$, $110$ si $111$, iar pentru cel putin 2 de 0 consecutivi avem numarul $100$.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"zero\")==\r\n\r\n\r\n',1490,'task: zero',48,NULL),('problema/cmmdc','CMMDC','2006-11-11 11:23:33','2008-11-15 16:19:39','==Include(page=\"template/taskheader\" task_id=\"cmmdc\")==\r\n\r\nh2. Date de intrare\r\n\r\nDatele de intrare se citesc din fisierul $cmmdc.in$:\r\n\r\n* pe prima linie: un numar natural, $a$\r\n* pe a doua linie: un numar natural, $b$\r\n\r\nh2. Date de iesire\r\n\r\nDatele de iesire se tiparesc in fisierul $cmmdc.out$\r\n\r\n* pe prima linie: cel mai mare divizor comun pentru $a$ si $b$. Daca $a$ si $b$ sunt numere prime intre ele, atunci se va tipari $0$\r\n\r\nh2. Restrictii\r\n\r\n* Rezultatul nu va depasi niciodata valoarea 30000\r\n\r\nh2. Exemplu\r\n\r\n\r\ntable(example). |_. cmmdc.in |_. cmmdc.out |\r\n|8 12| 4 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"cmmdc\")==\n\n\n',1490,'task: cmmdc',28,NULL),('problema/flip','Jocul Flip','2006-11-11 11:23:33','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"flip\")==\r\n\r\nGigel a descoperit un nou joc pe care l-a numit \"Flip\". Acesta se joaca pe o tabla dreptunghiulara de dimensiuni $N*M$ care contine numere intregi. Fiecare linie si fiecare coloana are un comutator care schimba starea tuturor elementelor de pe acea linie sau coloana, inmultindu-le cu {$-1$}. Scopul jocului este ca pentru o configuratie data a tablei de joc sa se actioneze asupra liniilor si coloanelor astfel incat sa se obtina o tabla cu suma elementelor cat mai mare.\r\n\r\nh2. Cerinta\r\n\r\nDandu-se o configuratie pentru tabla \"Flip\", realizati un program care sa determine suma maxima pe care Gigel o poate obtine.\r\n\r\nh2. Date de Intrare\r\n\r\nPrima linie a fisierului $flip.in$ contine doua numere intregi $N$ si {$M$}, separate prin cate un spatiu, care reprezinta dimensiunea tablei. Urmatoarele $N$ linii contin cate $M$ numere intregi seperate prin cate un spatiu care descriu configuratia tablei de joc.\r\n\r\nh2. Date de Iesire\r\n\r\nPrima linie a fisierului $flip.out$ contine un numar care va reprezenta suma maxima pe care Gigel o poate obtine comutand liniile si coloanele tablei de joc.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N, M &le; 16$\r\n* Tabla de joc contine numere intregi din intervalul [{$-1.000.000,1.000.000$}]\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. flip.in |_. flip.out |\r\n| 5 3\r\n4 -2 2\r\n3 -1 5\r\n2 0 -3\r\n4 1 -3\r\n5 -3 2\r\n| 28 |\r\n\r\nh3. Explicatie\r\n\r\nSe comuta coloana a doua si linia a treia.\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"flip\")==\n\n\n',1490,'task: flip',29,NULL),('problema/fractii','Fractii','2006-11-11 11:23:33','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"fractii\")==\r\n\r\n\r\n\r\nGigel, intr-o zi cand isi facea temele la matematica, s-a apucat sa scrie pe o foaie de hartie, un sir de fractii ireductibile de forma $^P^/{~Q~}$ cu $1 &le; P,Q &le; N$, unde $N$ este un numar natural ales de el. De exemplu, pentru $N = 4$ el a obtinut urmatorul sir:\r\n\r\np=. $^1^/{~1~}  ^1^/{~2~}  ^1^/{~3~}  ^1^/{~4~}  ^2^/{~1~}  ^2^/{~3~}  ^3^/{~1~}  ^3^/{~2~}  ^3^/{~4~}  ^4^/{~1~}  ^4^/{~3~}$\r\n\r\nGigel s-a apucat apoi sa numere cate fractii a obtinut pentru $N = 4$ si a vazut ca sunt $11$.\r\n\r\nh2. Cerinta\r\n\r\nFiind dat un numar natural $N$, sa se determine cate fractii sunt in sirul de fractii construit dupa regulile de mai sus.\r\n\r\nh2. Date de intrare\r\n\r\nFisierul de intrare $fractii.in$ contine pe prima linie numarul natural $N$.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $fractii.out$ trebuie sa contina un numar natural pe prima linie care reprezinta cate fractii sunt in sir.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 1.000.000$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. fractii.in |_. fractii.out |\r\n| 3 | 7 |\r\n| 4 | 11 |\r\n| 5 | 19 |\r\n| 10| 63 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"fractii\")==\r\n\r\n',1490,'task: fractii',33,NULL),('problema/perm','Permutari','2006-11-11 11:23:33','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"perm\")==\r\n\r\nO permutare de lungime $N$ este un sir de elemente distincte din multimea {${1,2,3 ... N}$}. Spunem ca o permutare are $K$ maxime daca exista fix $K$ pozitii distincte in permutare, pentru care elementul curent este mai mare decat toate elementele din stanga lui.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care determina cate permutari de lungime $N$ cu $K$ maxime exista.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierul $perm.in$ se vor gasi numerele $N$ si {$K$}, separate prin cate un spatiu.\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie a fisierul $perm.out$ se va gasi numarul de permutari de lungime $N$ cu $K$ maxime.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; K &le; N &le; 200$\r\n\r\nExemple\r\n\r\ntable(example). |_. perm.in |_. perm.out |\r\n| 3 2 | 3 |\r\n| 5 3 | 35 |\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"perm\")==\n\n\n',1490,'task: perm',31,NULL),('problema/fact','Factorial','2006-11-11 11:23:34','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"fact\")==\r\n\r\nSe da un numar intreg $P$. Sa se gaseasca cel mai mic numar natural strict pozitiv $N$ pentru care $N!$ are exact $P$ cifre de $0$ la sfarsit.\r\n\r\nSe stie ca {$N! = 1 * 2 * 3 * .... * (N - 1) * N$}.\r\n\r\nh2. Date de intrare\r\n\r\nFisierul $fact.in$ va contine pe prima linie numarul intreg $P$.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie a fisierului $fact.out$ se va scrie acel numar $N$ care indeplineste condiitle impuse sau $-1$ daca nu exista un astfel de $N$.\r\n\r\nh2. Restrictii\r\n\r\n* $0$ &le; $P$ &le; $10^8^$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. fact.in |_. fact.out |\r\n| 0&nbsp; | 1  |\r\n| 2 | 10 |\r\n|10 | 45 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"fact\")==\n\n\n',1490,'task: fact',32,NULL),('problema/datorii','Datorii','2006-11-11 11:23:34','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"datorii\")==\r\n\r\nTatal si mama lui Gigel se ocupa cu vanzarea de sisteme de calcul. Afacerea s-a dovedit a fi foarte profitabila datorita unui sistem incredibil de creditare a clientilor: un client care cumpara un calculator in ziua $X$ (in acest moment au trecut $N$ zile de la infiintarea magazinului, zilele se numeroteaza de la 1 la $N$, {$0<X&le;N$}) poate returna banii oricand doreste acesta, neexistand o limita de timp impusa. Astfel, aproape in fiecare zi, la magazinul familiei se prezinta diversi clienti care achita integral sau partial un sistem de calcul cumparat in zilele anterioare. Deoarece vor sa inceapa o noua afacere, Mama si Tata doresc sa il insarcineze pe Gigel cu administrarea magazinului de calculatoare. Pentru aceasta Gigel trebuie sa indeplineasca o conditie esentiala: in orice moment al sederii lui la magazin el poate fi solicitat prin telefon de catre tatal sa raspunda cat mai repede la urmatoarea familie de intrebari: ce suma de bani a ramas inca neachitata luand in considerare achizitiile facute de clienti in zilele $P$, $P+1$, {$P+2$}... {$Q-1$}, {$Q$} ({$0<P&le;Q&le;N$}). Se stie ca niciodata nu s-au cumparat doua calculatoare in aceeasi zi. Ajuta-l pe Gigel sa demonstreze parintilor ca poate administra magazinul.\r\n\r\nh2. Cerinta\r\n\r\nSe dau: $N$, $M$, un sir de numere {$A{~1~}$}, {$A{~2~}$}... {$A{~N~}$} si $M$ operatii. {$A{~i~}$} ({$1&le;A{~i~}&le;1000$}, {$1&le;i&le;N$}) reprezinta suma de bani inca neachitata pentru o comanda efectuata in ziua $i$. O operatie poate fi de doua feluri:\r\n\r\n* $A$ (achitare - se scade o valoare din suma restanta a unei zile anume)\r\n* $B$ (interogare - se cere suma tuturor sumelor restante ale unui interval de zile). Programul trebuie sa scrie in fisierul de iesire suma ceruta de fiecare operatie de tip $B$ in momentul interogarii.\r\n\r\nh2. Date de intrare\r\n\r\nFisierul $datorii.in$ va contine pe prima linie numerele $N$ si $M$. Pe urmatoarea linie se afla valorile sirului {$A{~1~}$}, {$A{~2~}$}... {$A{~N~}$} separate prin cate un spatiu. Urmatoarele $M$ linii descriu operatiile (achitari sau interogari) efectuate in ordinea data. Fiecare linie care descrie o operatie incepe cu un cod binar (un numar intreg cu valoarea 0 sau 1) si continua cu 2 numere intregi.\r\n\r\n* Un cod 0 urmat de doua numere intregi $T$, $V$ ({$1&le;T&le;N$}, {$1&le;V&le;1000$}) reprezinta o operatie de tip $A$ (in momentul respectiv s-a achitat o valoare $V$ din suma restanta a zilei $T$)\r\n* Un cod 1 urmat de doua numere intregi $P$, $Q$ ({$1&le;P&le;Q&le;N$}) o operatie de tip $B$ (se cere suma tuturor sumelor restante din zilele $P$, {$P+1$}, {$P+2$}... $Q$ in momentul respectiv).\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul $datorii.out$ se vor scrie pe cate o linie sumele cerute de fiecare operatie de tip $B$ (sumele se cer in ordinea aparitiei operatiilor in fisierul de intrare).\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 15 000$\r\n* {$0 < M &le; 100 000$}\r\n* In orice moment, {$A{~i~}$} ({$1&le;i&le;N$}) este nenegativ.\r\n\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. datorii.in|_. datorii.out|\r\n|6 6\r\n1 3 2 0 0 10\r\n1 3 6\r\n1 1 4\r\n0 3 1\r\n1 1 6\r\n0 6 2\r\n1 1 6\r\n|12\r\n6\r\n15\r\n13|\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"datorii\")==\n\n\n',1490,'task: datorii',34,NULL);
+INSERT INTO `ia_textblock` VALUES ('preoni-2005/runda-1','preONI 2005 (Runda 1)','2006-11-24 23:48:25','2006-11-25 03:08:57','h1. preONI 2005 (Runda 1)\r\n\r\nConcursul s-a desfasurat Duminica, 23 ianuarie 2005, ora 15:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nSolutiile problemelor le puteti gasi \"aici\":preoni-2005/runda-1/solutii\r\n\r\nh2. Clasele 9-10 (\'Clasament\':preoni-2005/runda-1/clasament-9-10)\r\n\r\n!>preoni-2005/runda-1?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni51a\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2005/runda-1/clasament-11-12)\r\n\r\n!>preoni-2005/runda-1?logo2.gif!\r\n\r\n== Tasks(round_id=\"preoni51b\" pager_style=\"none\") ==',961,'protected',NULL,NULL),('preoni-2005/runda-2','preONI 2005 (Runda 2)','2006-11-24 23:57:04','2006-11-25 03:09:10','h1. preONI 2005 (Runda 2)\r\n\r\nConcursul s-a desfasurat Miercuri, 23 februarie, ora 16:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nSolutiile problemelor le puteti gasi \"aici\":preoni-2005/runda-2/solutii\r\n\r\nh2. Clasele 9-10 (\'Clasament\':preoni-2005/runda-2/clasament-9-10)\r\n\r\n!>preoni-2005/runda-2?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni52a\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2005/runda-2/clasament-11-12)\r\n\r\n!>preoni-2005/runda-2?logo2.gif!\r\n\r\n== Tasks(round_id=\"preoni52b\" pager_style=\"none\") ==',961,'protected',NULL,NULL),('preoni-2005/runda-3','preONI 2005 (Runda 3)','2006-11-25 00:02:20','2006-11-25 03:09:36','h1. preONI 2005 (Runda 3)\r\n\r\nConcursul s-a desfasurat Duminica, 20 martie la ora 10:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nSolutiile problemelor le puteti gasi \"aici\":preoni-2005/runda-3/solutii\r\n\r\nh2. Clasele 9-10 (\'Clasament\':preoni-2005/runda-3/clasament-9-10)\r\n\r\n!>preoni-2005/runda-3?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni53a\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2005/runda-3/clasament-11-12)\r\n\r\n!>preoni-2005/runda-3?logo2.gif!\r\n\r\n== Tasks(round_id=\"preoni53b\" pager_style=\"none\") ==',961,'protected',NULL,NULL),('usaco-oct-2005-divizia-gold','USACO oct 2005, divizia GOLD','2005-11-21 00:00:00','2006-11-22 02:29:02','h1. USACO oct 2005, divizia GOLD\r\n\r\n(Categoria _Competitii_, autor(i) _Florea Tiberiu_)\r\n\r\nCa de obicei, USACO debuteaza in luna octombrie cu un concurs prin care oricine se poate califica la o divizie superioara celei in care se afla.\r\n\r\nRomania a avut $8$ concurenti care s-au calificat (sau recalificat) la divizia GOLD, fiind depasita in acest clasament doar de China ({$16$}) si SUA ({$10$}). Bineinteles, acest clasament nu este foarte relevant, deoarece multi dintre cei calificati deja au preferat sa nu participe sau sa nu ia concursul foarte in serios.\r\n\r\nElevii romani care au obtinut punctajul necesar pentru (re)calificare sunt:\r\n\r\n* Andrei Teodorescu (andreit1)\r\n* Vladu Adrian (azotlic1)\r\n* Andrei Blanaru (blanaru1)\r\n* Sorin Fagateanu (cyronon1)\r\n* Ionel Corneliu Gog (gogione1)\r\n* Tiberiu Florea (greco2)\r\n* Pasoi Mircea (mircea_1)\r\n* Vlad Berteanu (vladcyb1)\r\n\r\nProba a constat in $2$ probleme de nivel mediu care trebuiau rezolvate in $2$ ore.\r\n\r\nh2. Skiing\r\n\r\nPrima rezolvare care ne vine in minte citind o astfel de problema este transformarea matricii intr-un graf cu R * C noduri si calcularea drumului minim dintre nodurile ({$1, 1$}) si ({$R, C$}). O observatie destul de evidenta este ca toate muchiile care intra intr-un nod (a, b) vor avea acelasi cost, adica {$V * 2 ^ H{~1,1~} - H{~a,b~}^$}. Deoarece implementarea obisnuita a algoritmului Dijkstra are complexitatea $O (N^2^ + M)$ considerand $N$ = numarul de pozitii si $M$ numarul de muchii dintre acestea ({$N = R * C, M = 4 * R * C - 2 * (R + C)$}) va trebui implementata varianta in care se foloseste o coada de prioritate pentru nodurile care nu au fost explorate deja: implementand varianta cu heap-uri vom obtine complexitatea {$O((N + M) * lg N)$}, care se incadreaza in timp.\r\n\r\nPentru cei care nu sunt familiari cu aceasta varianta a algoritmului, ea arata cam asa:\r\n\r\np(pre). D{~sursa~} <- 0\r\nheap_sz = 1\r\nheap{~heap_sz~} <- sursa\r\npentru $i$ de la $1$ la $N$\r\n    daca i != sursa\r\n        D{~i~} <- oo\r\n        heap_sz <- heap_sz + 1\r\n        heap[heap_sz] <- i\r\ncat timp heap_sz > 0\r\n    x <- extrage_min (heap)\r\n    daca x = destinatie\r\n        returneaza D{~x~}\r\n    altfel\r\n        pentru i de la 1 la N\r\n            daca D{~i~} > D{~x~} + cost (x, i)\r\n                descreste_cheie (i, D{~x~} + cost (x,i))\r\n\r\nFiecare nod este extras cel mult o data din heap, si pentru fiecare muchie este apelata cel mult o data functia descreste_cheie. Fiecare dintre aceste operatii se efectueaza in {$O(lg N)$}, de aici rezultand complexitatea dorita.\r\n\r\nDe asemenea, putea fi aplicata o alta varianta a algoritmului Dijkstra, care profita mai mult de specificul problemei: In afara de vectorul estimarilor distantelor pana la fiecare nod, se memoreaza si nodul cu estimarea minima de pe fiecare din cele $R$ linii. Astfel, in momentul in care se extrage fiecare nod, cautam minimul in acest vector de dimensiune {$R$}, iar apoi reactualizam valoarea liniei pe care se afla nodul curent. Complexitatea acestui algoritm este {$O(N * R)$}, adica {$O(R^2^ * C)$}.\r\n\r\nIn implementarea oricaruia dintre acesti algoritmi trebuiau avute in vedere eventualele probleme cu precizia calculelor; o idee buna era ca numai costul final sa se inmulteasca cu {$V$}.\r\n\r\nh2. Flying right\r\n\r\nAceasta problema poate fi rezolvata cu ajutorul unui algoritm greedy, ideea nu este greu de gasit sau demonstrat, insa la implementare pot aparea unele probleme. In primul rand trebuie sa remarcam ca cele doua parti ale problemei se vor rezolva independent una de cealalta, drumurile se vor imparti in $2$ multimi (cele de dimineata, si cele de seara), si se va aplica aceeasi rezolvare pentru fiecare din cele doua multimi, raspunsul final fiind suma celor doua rezultate partiale. Rezolvarea urmatoare trateaza calcularea rezultatului optim pentru drumurile de dimineata.\r\n\r\nPentru fiecare din cele $N$ ferme tinem o lista de grupuri care doresc sa plece din orasul respectiv si sortam aceste liste crescator dupa indicele destinatiei fiecarui grup. Parcurgem in ordine cele $N$ ferme, memorand numarul si destinatiile vacilor care se afla la un moment dat in avion, sortate in ordine descrescatoare. In momentul in care am ajuns la ferma {$i$}, primul lucru pe care trebuie sa il facem este sa dam jos vacile care au ajuns la destinatie, incrementand corespunzator solutia de pana atunci. Evident, vacile care coboara la ferma respectiva se vor afla pe ultimele pozitii in ordinea descrisa din avion. Urmatorul pas este sa luam in avion din vacile care pleaca de la ferma $i$ pana cand acestea sunt epuizate sau capacitatea avionului este saturata. Daca au mai ramas vaci care nu au avut loc in avion, atata timp cat putem lua o vaca a carei destinatie este mai apropiata decat cea mai departata dintre destinatiile vacilor care se afla deja in avion, consideram ca vaca respectiva din avion nu a fost luata deloc, si ca alocam locul ei noii vaci, care va cobori mai repede.\r\n\r\nEste usor de vazut ca algoritmul de mai sus produce o solutie optima, insa implementarea sa nu este foarte lejera. Putem folosi urmatoarea metoda ({$v$} este un vector in care retinem destinatiile vacilor care se afla in avion, sortate descrescator):\r\n\r\np(pre). sol = 0, nr <- 0\r\npentru i de la 1 la N\r\n    cat timp nr > 0 si v{~nr~} = i\r\n        sol <- sol + 1\r\n        nr <- nr - 1\r\n        pentru j <- 1, j &le; C si j &le; nr vaci ce asteapta sa plece de la ferma i\r\n            nr <- nr + 1\r\n        v{~nr + 1~} = distanta celei de-a j-a vaci (in ordinea crescatoare a destinatiilor) de la ferma i\r\n        sorteaza v\r\n        pastreaza primele maxim C pozitii din v\r\n\r\nLa fiecare pas, vectorul $v$ poate fi sortat folosind {@qsort (stdlib.h)@} sau {@sort (algorithm)@}. Este necesar sa adaugam in $v$ doar primele $C$ vaci de la ferma {$i$}, deoarece daca o vaca nu este intre primele $C$ din multimea vacilor de la ferma {$i$}, este evident ca nu va fi nici intre primele $C$ din reuniunea acestei multimi cu multimea vacilor aflate deja in avion.\r\n\r\nSa recapitulam pasii algoritmului, alaturi de complexitatea fiecaruia dintre ei:\r\n\r\n* sortarea tuturor grupurilor dupa destinatie: $O(K * lg K)$\r\n* parcurgerea grupurilor si inserarea in listele corespunzatoare: $O(K)$\r\n* parcurgerea fermelor de la 1 la N, aplicand procedeul descris: $O(N * C * lg C)$\r\n\r\nAsadar, complexitatea totala a algoritmului este de {$O(K * lg K + N * C * lg C)$}, dand un timp de rulare rezonabil si o implementare fara mari batai de cap.\r\n\r\n',1,'public',NULL,NULL),('template/newuser','Profil %user_id%','2006-11-05 14:50:02','2006-12-04 00:32:37','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',13,'protected',NULL,NULL),('preoni-2006/comisie','Organizatori, preONI 2006','2006-11-26 04:47:24','2006-11-27 16:14:08','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Organizatori\r\n\r\nEchipa care se ocupa de organizarea si desfasurarea concursului *preONI 2006* este \'echipa infoarena\':echipa-infoarena (faceti click pe link pentru a afla mai multe detalii despre echipa)\r\n\r\nh2. Organizare \r\n\r\n* \'Cristian George Strat\':utilizator/wickedman : coordonator, promovare concurs\r\n* Prof. Emil Onea : organizator \'finala in tabara\':preoni-2006/finala\r\n* \'Leonard Crestez\':utilizator/fluffy : asigura buna desfasurare a concursului din punct de vedere tehnic (site-ul, evaluatorul etc.)\r\n\r\nh2. Echipa stiintifica \r\n\r\nCei care se vor ocupa de buna desfasurarea a concursului din punct de vedere stiintific (redactarea si compunerea problemelor, realizarea testelor, clarificarea intrebarilor, etc.) sunt:\r\n\r\n* \'Mircea Pasoi\':utilizator/domino \r\n* \'Cosmin Negruseri\':utilizator/cosmin\r\n* \'Silviu Ganceanu\':utilizator/silviug\r\n* \'Adrian Diaconu\':utilizator/ditzonec\r\n* \'Daniel Pasaila\':utilizator/danielp\r\n* \'Tiberiu Florea\':utilizator/greco\r\n* \'Adrian Vladu\':utilizator/azotlichid\r\n\r\nh2. Colaboratori \r\n\r\n* Dan Burzo: sigla oficiala preONI 2006\r\n* \'Cristina Stancu-Mara\':utilizator/cimi : logo-uri runde preONI 2006\r\n* \'Filip Buruiana\':utilizator/filipb : propunator probleme\r\n\r\n==include(page=\"template/preoni-2006/footer\")==',13,'protected',NULL,NULL),('preoni-2006/info','Informatii generale, preONI 2006','2006-11-26 04:43:42','2006-11-27 16:13:59','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Informatii generale\r\n\r\nh2. Motivatia \r\n\r\nIndiferent de domeniul de activitate, concursurile reprezinta un element important in pregatirea indivizilor *competenti* deoarece promoveaza spiritul de *\"performer\"* si ajuta cu mult la perfectionarea cunostintelor acestora.\r\n\r\nIdeea care sta la baza proiectului _infoarena_ este aceea de a oferi tinerilor elevi sansa de a dobandi usor cunostinte valoroase si experienta in domeniul informaticii si al tehnologiei informatiei prin programe de pregatire eficiente. Proiectul s-a materializat intr-o platforma software ce permite *evaluarea automata* a mii de programe trimise de utilizatori si intr-o comunitate online aparte, devenind un adevarat motor de promovare si dezvoltare a performantei in informatica la cele mai inalte standarde. Nevoia de oameni bine pregatiti in acest domeniu este din ce in ce mai mare in societatea de azi. Asadar, pregatirea in acens sens pentru dezvoltarea unei gandiri algoritmice si a unor ablitati de programator devine necesara.\r\n\r\nComunitatea _infoarena_ cuprinde aproape totii elevii romani ce participa la concursuri de informatica nationale si internationale. Calitatea si valoarea concursurilor noastre precum si a materialelor educationale ce le punem la dispozitie este recunoscuta atat de elevi si studenti, cat si de profesori de renume in informatica. Suntem bucurosi ca am reusit sa contribuim la promovarea excelentei in randurile elevilor si ca am facut parte din programul de antrenament a celor mai de seama olimpici ai Romaniei. Ne mandrim cu reactiile pozitive pe care le-am primit de la elevi, studenti si profesori.\r\n\r\nDaca inca nu te-ai convins, afla mai multe detalii de pe pagina \'Despre infoarena\':despre-infoarena.\r\n\r\nh2. Ce a fost *preONI?*\r\n\r\nAnul 2005 a fost prima data cand concursul *preONI* a fost structurat in mai multe runde, pe parcursul a mai multor luni. Acesta a adunat, pe parcursul a 3 runde, un numar de participanti intre *1500* si *2700* la fiecare runda. Ultimele doua runde au fost sponsorizate de _Microsoft Romania_ care a oferit permii constand in carti de informatica primilor trei concurenti de la fiecare grupa (au existat grupa de clase 9-10 si grupa 11-12)\r\n\r\nh2. Ce este *preONI?* \r\n\r\nIn pragul inceperii olimpiadelor, alaturi de noi contribuitori, suntem determinati sa ducem _infoarena_ la urmatorul nivel. Ca si in anii anteriori \'echipa infoarena\':echipa-infoarena  vine in sprijinul elevilor din toata tara ce se pregatesc pentru olimpiada de informatica, in special _Olimpiada Judeteana de Informatica_ (OJI) si _Olimpiada Nationala de Informatica_ (ONI). Pornind de la aceasta idee ne-am asumat responsabilitatea sa organizam un concurs de pregatire, numit *preONI*. Acest concurs se afla deja la a 5-a editie, aceasta fiind a 3-a editie organizata de \'echipa infoarena\':echipa-infoarena.\r\n\r\nSelctionarea problemelor a fost atent facuta astfel incat nivelul de dificultate sa fie apropiat de cel de la concursuri asemanatoare, cu intentia de a acoperi cat mai bine materia de concurs si a evalua complet concuretii folosind probleme de dificultati gradate. Formatul concursului este asemanator cu acela al concursurilor nationale si internationale pentru a oferi participantilor o experienta realista.\r\n\r\nCum in fiecare an \'echipa infoarena\':echipa-infoarena  doreste sa imbunatateasca eficienta programelor sale de pregatire, noul format al concursului *preONI* de anul acesta este mult mai complex decat oricare din editiile anterioare, lucru cu siguranta imbucurator pentru toti utilizatorii. Asadar, navigheaza prin meniul din dreapta-sus daca vrei sa aflii ce suprize ti-au fost pregatite!\r\n\r\n==include(page=\"template/preoni-2006/footer\")==',13,'public',NULL,NULL),('preoni-2006/regulament','Regulament, preONI 2006','2006-11-25 18:16:40','2006-11-27 16:15:05','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Regulament\r\n\r\nSe recomanda, pe langa citirea acestui regulament, citirea \"regulamentului\":regulament general infoarena.\r\n\r\nEchipa infoarena isi rezerva dreptul de a modifica prezentul regulament pe parcursul desfasurarii concursului. Daca apar prevederi noi sau daca anumite prevederi ale regulamentului sunt modificate sau eliminate, atunci acestea vor fi anuntate pe site-ul concursului. Orice modificare a regulamentului va intra in vigoare, in functie de situatie, fie din momentul publicarii ei, fie dupa incheierea rundei aflate in desfasurare. In momentul anuntarii modificarii va fi precizat si momentul din care aceasta intra in vigoare.\r\n\r\nh2. Dreptul de participare\r\n\r\nPersoanele care fac parte din echipa infoarena cat si alti contribuitorii\r\nimplicati direct in organizarea concursului *preONI 2006* nu au dreptul de a participa. De asemenea, orice concurent care are un comportament considerat inadecvat fata de echipa infoarena sau fata de alti concurenti va fi descalificat. Un concurent se poate califica la finala doar daca se incadreaza in grupa la care a concurat (aceasta verificare se va face prin prezentarea unei dovezi legale care il incadreaza pe concurent la aceea grupa).\r\n\r\nh2. Repartizarea\r\n\r\nToti participantii vor fi repartizati in 3 grupe, in concordanta cu varsta lor. Repartizarii este asemanatoare cu acea facuta la olimpiadele de informatica.\r\n\r\n* Clasa a 9a (si gimnaziu)\r\n* Clasa a 10a\r\n* Clasele 11-12 \r\n\r\nOricine poate participa la o alta grupa decat cea la care se incadreaza, dar calificarea la finala cat si impartirea premiilor se va face conform regulamentului respectiv, fara nici o exceptie.\r\n\r\nh2. Inscriere\r\n\r\nTot ce trebuie sa faceti pentru a participa la concursul *preONI 2006* este sa aveti un cont la infoarena. Inregistrarea se poate face pe site-ul infoarena. Acelasi cont va fi folosit pentru a accesa forum-ul.\r\n\r\nh2. Runde\r\n\r\nVor exista 4 runde de calficare, iar in urma clasamentului stabilit primii de la fiecare grupa vor fi selectati pentru etapa finala desfasurata in cadrul unei tabere. Cele 4 runde vor avea loc sambata incepand cu ora 9:00, desi pot interveni exceptii. Durata lor va fi de 4 ore. Pentru un program detaliat al concursului \"click aici\":preoni-2006/program.\r\n\r\nh2. Intrebari\r\n\r\nIn prima ora vor putea fi formulate eventualele intrebari, pe forum, in topicurile special create. Orice intrebare pusa in alt mod (primita ca personal message, pe mail, etc.) va fi ignorata. Raspunsuri vor fi oferite doar la intrebarile puse in prima ora . Intrebarile trebuie formulate astfel incat sa se poate raspunda cu DA sau NU. In caz contrar sau in cazul in care raspunsul se afla in textul problemei se va raspunde cu NO COMMENT. Nu vor exista exceptii de la aceaste reguli. Daca echipa va considera ca raspunsul la o anumita intrebare este de interes general si clarifica anumite aspecte, atunci se va face un anunt general care va aparea atat pe forum cat si in sectiunea Mesaje de la organizatori a grupei respective. Fiecare grupa va avea doi administratori care se vor ocupa de raspunsul acestor intrebari.\r\n\r\nh2. Trimiterea solutiilor\r\n\r\nTrimitrea solutiile se va face prin intermediul interfetei site-ului infoarena.\r\nOdata logati in contul vostru, veti putea selecta arhiva la care doriti sa\r\nlucrati (in cazul acesta una din arhivele {*preONI 2006*}) si veti putea folosi link-ul trimite solutii.\r\n\r\nh2. Evaluare\r\n\r\nDupa expirarea timpului de trimitere a solutiilor acestea vor fi evaluate (\"mai multe detalii aici\":documentatie/evaluator). In mod normal, evaluarea se va face imediat dupa concurs, desi exista posibilitatea ca echipa infoarena sa amane evaluarea din motive obiective. Veti putea vizualiza pozitia ocupata in clasament dupa evaluarea in rubrica Clasamente si alte statistici.\r\n\r\nSe recomanda sa instalati pe calculatorul vostru aceleasi versiuni de compilatoare ca cele specificate la link-ul de mai sus. Echipa infoarena nu este responsabila pentru diferentele intre versiuni de compilatoare si nu va efectua reevaluaari in astfel de cazuri.\r\n\r\nh2. Contestatii\r\n\r\nEchipa infoarena isi rezerva dreptul de a reevalua orice problema in situatia in care se detecteaza erori in teste sau in programul de verificare dupa evaluare. Cum testele problemelor nu vor fi facute publice, posiblitatile de a contesta sunt limitate. Pentru a asigura o evaluarea corecta, echipa infoarena va garanteaza ca va testa intens toate problemele inainte de concurs si ca va verifica corectitudinea procesului de evaluare dupa terminare. In caz ca totusi aveti o contestatie, aceasta trebuie trimisa pe mail la adresa preONI2006 -at- gmail.com in termen de 24 de ore de la afisarea rezultatelor rundei curente pe site. Ele vor fi rezolvate in termen de maxim 5 zile, iar dupa rezolvarea lor rezultatele vor fi declarate finale.\r\n\r\nh2. Solutii\r\n\r\nLa scurt timp dupa terminarea evaluarii se va publica un articol cu solutiile pentru problemele rundei respective. Testele utilizate pentru evaluare nu vor fi facute publice.\r\n\r\nh2. Transferul problemelor\r\n\r\nProblemele vor fi mutate dupa evaluare in Arhiva de probleme infoarena, avand astfel la dispozitie un evaluator 24 din 24 si posiblitatea de a finisa solutiile la problemele nerezolvate in timpul concursului.\r\n\r\nh2. Trisare\r\n\r\n*preONI 2006* este un concurs individual, asadar orice tentativa de colaborare va aduce descalificarea celor implicati. echipa infoarena isi rezerva dreptul de a verifica sursele concurentilor, iar in caz ca se descopera surse aproximativ identice, concurentii respectivi vor fi descalificati din concurs iar user-ul lor de pe infoarena eliminat. Tentativele de frauda (concurarea sub un alt nume decat cel adevarat, etc.) sau orice atac asupra sistemului de evaluare sau asupra paginilor infoarena vor fi pedepsite in aceeasi masura. \r\n',13,'public',NULL,NULL),('problema/party','Party','2006-11-11 11:23:36','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"party\")==\r\n\r\nGeorge vrea sa isi organizeze majoratul, si vrea ca petrecerea sa fie de neuitat, mancarea, bautura, locatia si sonorizarea sunt deja asigurate, si mai ramane problema chemarii prietenilor. El si cu prietenul lui cel mai bun Lucian au preferinte diferite si pentru a nu se certa au pus la punct o lista de cerinte care vor trebui sa fie indeplinite toate astfel incat cheful sa se desfasoare in cele mai bune conditii! Pentru usurinta, prietenii lui George vor fi indentificati prin numere intregi de la $1$ la $N$ si cerintele vor fi de tipurile $0, 1, 2$ sau $3$.\r\nO cerinta de genul $x y 0$ are semnificatia ca $x$ sau $y$ trebuie sa participe la petrecere ; $x y 1$ are semnificatia ca daca $x$ participa nu exista nici o restrictie pentru $y$, dar daca $x$ nu participa atunci nici $y$ nu participa ; $x y 2$ are semnificatia simetrica cu cerinta $1$ ; iar cerinta $x y 3$ are semnificatia ca cel putin unul dintre $x$ si $y$ nu participa la petrecere. Scrieti un program care sa-i ajute pe cei doi sa determine care persoane vor fi invitate la petrecere ; se garanteaza ca va fi posibila intotdeauna organizarea unei petreceri !\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie se vor afisa numerele $N$ si $M$ care reprezinta numarul de prieteni si numarul de cerinte de indeplinit. Pe urmatoarele $M$ linii vor fi cerinte de forma $x y z$ unde $1<=x,y<=N$ iar $0<=z<=3$.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie va fi un numar $Nr$ ce reprezinta numarul de invitati la petrecere, iar pe urmatoarele $Nr$ linii cate un invitat pe linie.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; N &le; 100$\r\n* $1 &le; M &le; 1.000$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. party.in |_. party.out |\r\n| 4 4            \r\n1 4 3          \r\n2 3 3\r\n1 2 1\r\n2 4 1\r\n|2\r\n 1\r\n3 |\r\n| 3 7          \r\n3 2 1          \r\n3 1 1          \r\n2 1 1          \r\n2 3 1\r\n3 1 1\r\n3 2 1\r\n2 3 2\r\n| 3\r\n1\r\n2\r\n3 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"party\")==\n\n\n',1490,'task: party',96,NULL),('agora-finala','Bursele agora, editia 6, finala online','2006-11-24 16:38:15','2006-12-28 02:00:59','h1. Bursele agora, editia 6, finala online\r\n\r\nAceasta este runda finala online a concursului \"Bursele Agora\", editia 6. Concursul a fost organizat de catre redactia revistei GInfo si Editura Agora Media. Concursul s-a desfasurat pe 9 iulie 2005. Puteti vedea \'clasamentul\':agora-finala/clasament, cat si un articol cu \'solutii\':agora-finala/solutii.\r\n\r\n!>agora-finala?logo.gif!\r\n\r\n== Tasks(round_id=\"ba6\" pager_style=\"none\")==',1142,'protected',NULL,NULL),('preoni-2006/clasament-10','Clasament preONI 2006, Clasa a X-a','2006-11-25 03:30:05','2006-12-01 18:13:59','== include(page=\"template/preoni-2006/rankings\") ==\r\n\r\nh2. Clasa a X-a\r\n\r\n==Rankings(rounds = \"preoni61b|preoni62b|preoni63b|preoni64b\")==',13,'protected',NULL,NULL),('preoni-2006/clasament-9','Clasament preONI 2006, Clasa a IX-a si gimnaziu','2006-11-25 03:59:30','2006-12-01 18:13:42','== include(page=\"template/preoni-2006/rankings\") ==\r\n\r\nh2. Clasa a IX-a si gimnaziu\r\n\r\n==Rankings(rounds = \"preoni61a|preoni62a|preoni63a|preoni64a\")==',13,'protected',NULL,NULL),('happy-coding-2005-2','Happy Coding 2','2006-11-23 21:08:55','2006-11-24 17:38:43','h1. Happy Coding 2\r\n\r\nCum un lucru bun nu vine niciodata singur, la insistentele publicului se organizeaza Happy Coding 2 - programare cu zambetul pe buze, pace, idei, distractie!\r\n\r\nConcursul s-a desfasurat incepand cu 10:00, 22 octombrie 2005 pana la ora 22:00 pe data de 23 octombrie. Concurentii au avut spre rezolvare 10 probleme.\r\n\r\nh2. \'Clasament\':happy-coding-2005-2/clasament\r\n\r\n!>happy-coding-2005-2?logo.jpeg!\r\n\r\n== Tasks(round_id=\"hc2\" pager_style=\"none\") ==\r\n',961,'protected',NULL,NULL),('happy-coding-2005-2/clasament','Clasament hc2','2006-11-23 21:08:55','2006-11-24 17:46:35','h1. Clasament ==roundparam(round_id=\"hc2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"hc2\")==',961,'protected',NULL,NULL),('happy-coding-2005-1/clasament','Clasament happy','2006-11-23 21:08:55','2006-11-24 17:46:59','h1. Clasament ==roundparam(round_id=\"happy\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"happy\")==',961,'protected',NULL,NULL),('happy-coding-2005-1','Happy Coding 2005','2006-11-23 21:08:54','2006-11-24 17:38:35','h1. Happy Coding 2005 \r\n\r\nHappy Coding inseamna programare cu zambetul pe buze, placere si distractie pura! :) \r\n\r\nConcursul s-a desfasurat incepand cu 10:00, 10 septembrie 2005 pana la ora 22:00 pe data de 11 septembrie. Concurentii au avut spre rezolvare 6 probleme.\r\n\r\nh2. \'Clasament\':happy-coding-2005-1/clasament\r\n\r\n!>happy-coding-2005-1?logo.jpeg!\r\n\r\n== Tasks(round_id=\"happy\" pager_style=\"none\") ==\r\n',961,'protected',NULL,NULL),('bacalaureat-2005/clasament','Clasament bac2005','2006-11-23 21:08:54','2006-11-24 18:30:13','h1. Clasament ==roundparam(round_id=\"bac2005\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"bac2005\")==',961,'protected',NULL,NULL),('agora-finala/clasament','Clasament ba6','2006-11-23 21:08:54','2006-11-24 17:47:59','h1. Clasament ==roundparam(round_id=\"ba6\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"ba6\")==',961,'protected',NULL,NULL),('preoni-2006/runda-2/clasament-10','Clasament preoni62b','2006-11-25 01:34:44','2006-11-25 01:34:44','h1. Clasament ==roundparam(round_id=\"preoni62b\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni62b\")==',961,'protected',NULL,NULL),('preoni-2006/runda-2','Runda 2, preONI 2006','2006-11-25 01:33:08','2006-11-27 16:16:04','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Runda 2\r\n\r\nConcursul s-a desfasurat sambata, 17 decembrie, la ora 09:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nh2. Comisii\r\n\r\nh3. Stiintific\r\n\r\n* clasa a 9-a (si gimnaziu)\r\n** Mircea Pasoi\r\n** Adrian Vladu \r\n* clasa a 10-a\r\n** Adrian Diaconu\r\n** Daniel Pasaila \r\n* clasele 11-12\r\n** Cosmin Negruseri\r\n** Tiberiu Florea \r\n\r\nh3. Organizatoric\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* Cristian Strat\r\n* Crestez Leonard \r\n\r\nh2. Solutii\r\n\r\nSolutiile problemelor le puteti gasi \"aici\":preoni-2006/runda-2/solutii\r\n\r\nh2. Clasa a 9-a si gimnaziu (\'Clasament\':preoni-2006/runda-2/clasament-9)\r\n\r\n!>preoni-2006/runda-2?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni62a\" pager_style=\"none\") ==\r\n\r\nh2. Clasa a 10-a(\'Clasament\':preoni-2006/runda-2/clasament-10)\r\n\r\n!>preoni-2006/runda-2?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni62b\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2006/runda-2/clasament-11-12)\r\n\r\n!>preoni-2006/runda-2?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni62c\" pager_style=\"none\") ==\r\n\r\n==include(page=\"template/preoni-2006/footer\")==',13,'protected',NULL,NULL),('preoni-2006/runda-2/clasament-11-12','Clasament preoni62c','2006-11-25 01:34:37','2006-11-25 01:34:37','h1. Clasament ==roundparam(round_id=\"preoni62c\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni62c\")==',961,'protected',NULL,NULL),('preoni-2004','Preoni 2004','2006-11-25 00:25:00','2006-11-25 00:30:13','h1. preONI 2004\r\n\r\nConcursul preONI 2004 s-a desfasurat in 2 zile avand ca principal scop pregatirea participantilor pentru olimpiada nationala de informatica ONI2004.\r\n\r\nFormatul concursului: 2 grupe (clasele IX-X, XI-XII), 3 probleme in fiecare grupa si un timp de lucru de 4h.\r\n\r\nh2. Runde\r\n\r\n* \"Ziua 1\":preoni-2004/runda-1 :Sambata, 27 martie, ora 16:00\r\n* \"Ziua 2\":preoni-2004/runda-2 :Duminica, 28 martie, ora 16:00\r\n\r\nh2. \"Clasament IX-X\":preoni-2004/clasament-9-10\r\n\r\nh2. \"Clasament XI-XII\":preoni-2004/clasament-11-12',961,'protected',NULL,NULL),('preoni-2004/clasament-9-10','Clasament preoni4a','2006-11-25 00:26:15','2006-11-25 00:27:18','h1.  Clasament global preONI 2004 (Clasele IX-X)\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni1|preoni3\")==',961,'protected',NULL,NULL),('preoni-2004/clasament-11-12','Clasament preoni4b','2006-11-25 00:28:17','2006-11-25 00:28:57','h1.  Clasament global preONI 2004 (Clasele XI-XII)\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2|preoni4\")==',961,'protected',NULL,NULL),('preoni-2004/runda-1','preONI 2004 (Runda 1)','2006-11-25 00:31:25','2006-11-25 03:08:19','h1. preONI 2004 (Runda 1)\r\n\r\nConcursul s-a desfasurat Sambata, 27 martie, ora 16:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nh2. Clasele 9-10 (\'Clasament\':preoni-2004/runda-1/clasament-9-10)\r\n\r\n!>preoni-2004/runda-1?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni1\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2004/runda-1/clasament-11-12)\r\n\r\n!>preoni-2004/runda-1?logo2.gif!\r\n\r\n== Tasks(round_id=\"preoni2\" pager_style=\"none\") ==',961,'protected',NULL,NULL),('preoni-2004/runda-2','preONI 2004 (Runda 2)','2006-11-25 00:34:23','2006-11-25 03:08:34','h1. preONI 2004 (Runda 2)\r\n\r\nConcursul s-a desfasurat Duminica, 28 martie, ora 16:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nh2. Clasele 9-10 (\'Clasament\':preoni-2004/runda-2/clasament-9-10)\r\n\r\n!>preoni-2004/runda-2?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni3\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2004/runda-2/clasament-11-12)\r\n\r\n!>preoni-2004/runda-2?logo2.gif!\r\n\r\n== Tasks(round_id=\"preoni4\" pager_style=\"none\") ==',961,'protected',NULL,NULL),('preoni-2004/runda-2/clasament-9-10','Clasament preoni42a','2006-11-25 00:36:19','2006-11-25 00:37:32','h1. Clasament ==roundparam(round_id=\"preoni3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni3\")==',961,'protected',NULL,NULL),('preoni-2004/runda-2/clasament-11-12','Clasament preoni42b','2006-11-25 00:37:13','2006-11-25 00:37:13','h1. Clasament ==roundparam(round_id=\"preoni4\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni4\")==',961,'protected',NULL,NULL),('preoni-2004/runda-1/clasament-11-12','Clasament preoni41b','2006-11-25 00:39:04','2006-11-25 00:39:04','h1. Clasament ==roundparam(round_id=\"preoni2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2\")==',961,'protected',NULL,NULL),('preoni-2004/runda-1/clasament-9-10','Clasament preoni41a','2006-11-25 00:39:13','2006-11-25 00:39:13','h1. Clasament ==roundparam(round_id=\"preoni1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni1\")==',961,'protected',NULL,NULL),('warm-up-2004/clasament-11-12','Clasament filip2','2006-11-23 21:08:52','2006-11-24 17:46:10','h1. Clasament ==roundparam(round_id=\"filip2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"filip2\")==',961,'protected',NULL,NULL),('warm-up-2004/clasament-9-10','Clasament filip1','2006-11-23 21:08:51','2006-11-24 17:45:54','h1. Clasament ==roundparam(round_id=\"filip1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"filip1\")==',961,'protected',NULL,NULL),('preoni-2006/runda-1/clasament-9','Clasament preoni61a','2006-11-25 01:17:19','2006-11-25 01:17:19','h1. Clasament ==roundparam(round_id=\"preoni61a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni61a\")==',961,'protected',NULL,NULL),('preoni-2006/finala/cronica','preoni-2006/finala/cronica','2006-11-23 23:28:15','2006-11-27 16:05:09','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Cronica preONI 2006, Runda Finala\r\n\r\n09:30 Incepe concursul.\r\n09:34 Dam drumu la a 9-a\r\n09:35 Intram pe Messenger\r\n09:40 Cosmin doarme, nu raspunde la intrebari\r\n09:41 Gheorghe Cosmin baga DivK, restul inca mai citesc\r\n09:42 Skipy baga PScNv, scrisese gresite out-ul\r\n09:43 Cosmin este online\r\n09:43 Tiseanu se joaca cu culorile in DJGPP , iar Marmotel codeaza de ceva vreme\r\n09:44 Marin Radu citeste Pedefe si isi freaca ingrozit capul\r\n09:44 Fluf e uimit de Marmotel care face in vim\r\n09:47 Exemeplul la Overlap e prost formamtat, ups\r\n09:48 Sobolanul face BF la PScNv\r\n09:50 Tataroiu a submitat DivK\r\n09:51 Cimi coloreaza grafuri (avem poza)\r\n09:53 Mort vine la laptop sa faca treaba\r\n\r\n10:00 Mort ii zice \"da\" lui Cosmin pentru a 8-a oara la aceeasi intrebare\r\n10:08 Pentru a 10-a oara, DA!\r\n10:10 Skipy inca nu a inteles `arbore`\r\n10:12 svn: strat.cristian@gmail.com: rsae now supports evaluation priority field per user\r\n10:15 Sobolanul nu stie sa se faca inteles\r\n10:17 Marin Radu si-a scos ciocolata\r\n10:20 gcosmin s-a prins de heap-uri\r\n10:21 varu nu se prinde la DivK\r\n10:35\r\nazotlichid: care esti acolo?\r\nbogdanpasoi: skipy si sobolanul\r\nbogdanpasoi: citim niste solutii\r\nbogdanpasoi: vrei sa-l chem pe mircea?\r\n10:39 Vladu, oripilat, il suna pe Mircea\r\nazotlichid: bhooooooot\r\n10:46 Tiseanu se plictiseste\r\n\r\n11:05 Emil Onea soseste (la timp) cu sandwiches\r\n11:18 Cosmin Gheorghe afla si intelege ce inseamna operatia de `translatie`\r\n11:19 Silviu si Marina se duc la baie\r\n11:20 Cezar Mocan salveaza Lupul_Ala_Mare.pas\r\n11:22 Tataroiu incepe sa rescrie DivK - brute force\r\n11:23 Silviu si Marina se intorc dupa numai 4 minute\r\n11:25 Soseste apa; Marin Radu fuge la baie\r\n11:28 Fluf si Marin Radu se intorc de la baie\r\n11:29 Tiseanu iar la baie.. heavy\r\n11:38 Varu il ia pe Fluf la baie .. Tiseanu a cam stat ceva\r\n11:40 Gata Varu. Sobolanu iar vrea la baie, dar Fluf il trece la loc\r\n11:43 Rapid Sobolanu.\r\n\r\n12:03 Toata lumea vrea la baie.\r\n12:12 gcosmin face calcule pentru complexitate la overlap.. ii da cam mult, iar Marmotel are probleme cu lupul\r\n12:13 Silviu citeste o carte (Maestrul si Margareta)\r\n12:15 Spatarel \"Terminate batch job ? (Y/N)\".. da nervos in tastatura si isi unduieste mustata )\r\n12:17 Cotizo cauta instructiuni de folosire la memcpy().. parca era cu pascalul el\r\n12:21 Adi isi face griji pentru Cimi.. how cute\r\n12:22 Ne uitam la Family Guy\r\n12:23 Fluf Senior si Fluf Junior (a.k.a Marmota) pleaca la baie\r\n12:28 S-au intors Flufii\r\n12:32 Marmotel face back la overlap iar varul inca scrie la DivK.. rupere\r\n12:42 Marin se balanseaza spre baie, ca un magnat\r\n12:45 Marin simte ca ia 100 la Pedefe\r\n12:59 Nimic nou.\r\n\r\n13:11 Cimi se uita dezamagita la Pedefe\r\n13:13 Fluf ii zambeste lu ala mic si-l duce la baie.. Super Adventure\r\n13:15 Facem tabel de feedback\r\n13:17 Suntem pe plus cu bugetul , in seara asta bem\r\n13:27 Suparat, suparat Tiseanu\r\n13:44 Sobolanul se uita la program, vrea sa vada la cat incepe teatrul si cand e premierea\r\n13:45 Sobolanul admira echipa infoarena in cautare de inspiratie\r\n13:46 Sobolanul isi cauta poza pe site\r\n13:46 Greco joaca Starship Seven iar Fluf se uita mirat la el\r\n13:47 Cristi spune ca probleme sunt prea simple, am dat banii degeaba\r\n13:47 Cristi se apuca sa implementeze problemele a la Chuck Norris\r\n13:48 Cristi ia 300\r\n13:58 Sobolanul se uita de 5 minute in monitorul de evaluare\r\n13:59 A venit admin-ul\r\n\r\n14:00 Marinei i s-a blocat.. programul\r\n14:05 Crapa Word-ul\r\n14:10 Sobolanul joaca carti si Adi mananca un mar\r\n14:11 Adi ii tine pumnii lui Cimi iar Tiseanu e stresat de timp\r\n14:12 A venit Corleone\r\n14:16 Tataroiu se roaga\r\n14:18 Chuck Norris trece la laptop\r\n14:18 Soarele apune \r\n',13,'public',NULL,NULL),('12-ponturi-pentru-programatorii-cc','12 ponturi pentru programatorii C/C++','2004-11-08 00:00:00','2009-02-19 23:48:07','h1. 12 ponturi pentru programatorii C/C++\r\n\r\n(Categoria _Limbaje de programare_, Autor _Alexandru Mosoi_)\r\n\r\nIn urmatoarele cateva randuri am sa incerc sa va arat cateva metode de a scrie.... mai bine. Cea mai mare parte este pentru programatorii C.\r\n\r\nInainte ati putea citi si \"Documentation/CodingStyle\" aflat in sursa de kernel a Linux-ului. Scuzati-ma daca ma inspir putin. Manualul gcc este si el binevenit.\r\n\r\n\r\nh2. Pont #0\r\n\r\nPrefer C in loc de C++: e mai robust putin ceea ce ma fereste cateodata de greseli. Incercati sa nu folositi un IDE cu debugging inclus (cum ar fi RHIDE sau Borland C++ 3.1). La inceput o sa va vina greu, dar va obisnuiti... si deveniti mai atenti cand scrieti surse. Puteti sa folositi Kate, un editor de text asemanator lui EditPlus de sub Windows. Vim este deasemenea un editor foarte puternic, dar pentru cine stie sa-l foloseasca.\r\n\r\nh2. Pont #1\r\n\r\nImpartiti programul dumneavoastra in functii, fiecare sa nu depaseasca mai mult de 30-50 de linii (aproximativ 2 ecrane ANSI 80x25). Este important sa aveti mereu o viziune asupra intregii functii. Regula este: complexitatea unei functii trebuie sa fie invers proportionala cu lungimea ei. Puteti sa declarati functiile \"inline\" (nu pe toate !) pentru a nu pierde din viteza.\r\n\r\nh2. Pont #2\r\n\r\nMacro-urile nu le recomand. Daca le folositi ca functii aveti grija. Unul dintre colegii mei de la lot a pierdut multe puncte pentru ceva asemanator.\r\n\r\n== code(cpp) |#define MAX(a, b) ((a) < (b) ? (b) : (a))\r\n\r\nint query(int a, int b)\r\n{\r\n    int k, l, r;\r\n    ...\r\n    res = MAX(k, query(l, r));\r\n    ....\r\n    return res;\r\n}\r\n==\r\n\r\nDaca observati, exista cazuri cand $query(l, r)$ era apelata de $2$ ori, ceea ce nu se doreste. In schimb, putea sa declare $MAX$ ca o functie inline.\r\n\r\n== code(cpp)|inline int MAX(int a, int b)\r\n{\r\n    if(a > b) \r\n        return a;\r\n    return b;\r\n}\r\n==\r\n\r\nh2. Pont #3\r\n\r\nCand accesati un element din memorie, procesorul citeste de fapt $32$ bytes (sau cat de mare e linia de cache, dar o putere a lui {$2$}). Recomand ca structurile voastre sa aiba de asemenea ca dimensiune o putere a lui $2$ pentru a nu forta procesorul sa citeasca de $2$ ori. O extensie GNU a standardului ANSI C sunt atributele. Pentru structuri, una din cele mai folosite (de mine) este packed ce instruieste compilatorul se nu mai adauge \"padding bytes\".\r\n\r\n== code(cpp) |struct foo { int a; char b; int c; };\r\n/* sizeof(struct foo) == 12 */\r\nstruct bla { int a; char b; int c; }\r\n\r\n__attribute__((packed));\r\n/* sizeof(struct bla) == 9 */\r\n==\r\n\r\nPentru mai multe informatii executati consultati manualul gcc. (\"info gcc\").\r\n\r\nDe asemenea, e bine sa nu spargeti aceasta line de cache prea des. Uitati un exemplu:\r\n\r\n== code(cpp) |#define maxN 1000\r\n#define maxM 1000\r\n\r\nint t[maxN][maxM];\r\n\r\nint f(void)\r\n{\r\n    int i, j;\r\n    int s = 0;\r\n    for(i = 0; i < maxM; ++ i)\r\n        for(j = 0; j < maxN; ++ j)\r\n            s += t[j][i];\r\n    return s;\r\n}\r\n==\r\n\r\nPentru $1024$ de apelari, pe calculatorul meu, acesta functie consuma cam {$18.85$}s. In schimb, daca as fi scris\r\n\r\n== code(cpp)|for(i = 0; i < maxN; ++ i)\r\n    for(j = 0; j < maxM; ++ j)\r\n        s += t[i][j];\r\n==\r\n\r\n... functia s-ar fi executat de ~{$3$} ori mai repede (doar {$6.05$}s) iar rezultatul era acelasi. De ce? pentru ca in primul caz la fiecare accesare a $t[j][i]$ procesorul era nevoit sa acceseze memoria, iar in cazul al doilea cand citea {$t[i][j]$}, erau citite de fapt si {$t[i][j+1]$}, {$t[i][j+2]$}, {$t[i][j+3]$}. Si sa nu uitam viteza memoriei este mult mai mica decat cea a procesorului.\r\n\r\nh2. Pont #4\r\n\r\nVariabilele globale sa nu fie folosite in scop local. Daca as modifica functia astfel\r\n\r\n== code(cpp) |int i, j;\r\n\r\nint f(void)\r\n{\r\n    int s = 0;\r\n    for(i = 0; i < maxM; ++ i)\r\n        for(j = 0; j < maxN; ++ j)\r\n            s += t[i][j];\r\n    return s;\r\n}\r\n==\r\n\r\n... timpul de executie s-ar fi marit la {$6.44$}s. Nu e prea mult... dar se aduna.\r\n\r\nh2. Pont #5\r\n\r\nStack-ul (locul unde se pastreaza toate variabilele locale) este foarte rapid. Modificam acelasi program astfel:\r\n\r\n== code(cpp) |#define maxN 1000\r\n#define maxM 1000\r\n\r\nint main(void)\r\n{\r\n    int i, j, k;\r\n    int N, M, t[maxN][maxM];\r\n    N = maxN; M = maxM;\r\n    for(k = 0; k < 1024; ++ k) {\r\n        int s;\r\n        for(i = 0; i < N; ++ i)\r\n            for(j = 0; j < M; ++ j)\r\n                s += t[i][j];\r\n    }\r\n    return 0;\r\n}\r\n==\r\n\r\nIgnorand faptul ca $t$ nu este initializat (e doar un program de test, nici inainte nu era :D) timpul de executie scade la {$1.2$}s, Wow! Insa aveti grija sa nu o luati pe urmele lui Silviu: {$sizeof(t)$} ~= {$4$}Mb care e mult peste limita de {$1$}Mb ce se impune de obicei in concursuri (si asta daca folositi gcc). Cel mai probabil veti primi \"Killed by signal 11\".\r\n\r\nh2. Pont #6\r\n\r\nh3. 6.a\r\n\r\n{$++i$} e preferabil {$i ++$} (unde nu complica lucrurile).\r\n\r\nh3. 6.b\r\n\r\nNu va feriti sa folositi \"{$const$}\" si \"{$static$}\". \"{$const$}\" chiar poate sa faca diferenta ca timp si vizibilitate.\r\n\r\nh3. 6.c\r\n\r\nUtilizati si literele mari pentru anumite variabile mai importante (poate si macro-uri).\r\n\r\nh2. Pont #7\r\n\r\nO alta extensie GNU sunt \"zero-length arrays\". Se folosesc in general la skiplist-uri pentru a declara un array de dimensiune variabila intr-o structura.\r\n\r\n== code(cpp) |typedef struct bla bla;\r\nstruct bla {\r\n    int levels;\r\n    bla *next[0];\r\n};\r\n...\r\nbla *temp = (bla *)malloc(sizeof(bla) + no_levels*sizeof(bla *));\r\n==\r\n\r\nh2. Pont #8\r\n\r\nh3. 8.a\r\n\r\nFolositi-va de utilitarele puse la dispozitie de sistemul de operare (linux in cazul meu). RTFM :)\r\n\r\n* $bc$ - pentru calcule cu numere cu precizie multipla (eg. {$2^1024^$}).\r\n* $octave$ - pentru calcule matematice mai complicate.\r\n* $gprof$ - determina cat timp a necesitat executia fiecarei functii sau linii.\r\n* $gcov$ - determina de cateori a fost apelata o anumita linie.\r\n* $time$ - pentru aflarea timpului executiei unui program.\r\n* $factor$ - descompune in factori un numar (eg. factor {$666$}).\r\n* $splint$ - o versiune free a programului lint: va da foarte multe warning-uri.\r\n* $bash$ - putin scripting\r\n\r\nh3. 8.b\r\n\r\nCompilati-va sursele cu {$-W -Wall$} (tot pentru warning-uri)\r\n\r\nh3. 8.c\r\n\r\nGeneratorul de teste si sursa dumneavoastra trebuie sa fie doua programe diferite !\r\n\r\nh3. 8.d\r\n\r\nPentru debugging folositi {$fprintf(stderr, ...)$}. Daca se intampla sa uitati, macar nu primiti \"wrong answer\" din cauza unui {$printf$}.\r\n\r\nh2. Pont #9\r\n\r\nh3. 9.a\r\n\r\n== code(cpp)|int t[666];\r\n/* toate elementele lui t vor fi -1 */\r\nmemset(t, 0xff, sizeof(t));\r\n==\r\n\r\nh3. 9.b\r\n\r\nPentru valoarea infinit folosesc o constanta\r\n\r\n== code(cpp)|#define INFI 0x3f3f3f3f\r\n==\r\n\r\ndin mai multe motive:\r\n\r\n* $INFI + INFI$ ramane pozitiv\r\n* in general e destul de mare\r\n\r\n== code(cpp)|/* toate elementele lui t devin INFI */\r\nmemset(t, 0x3f, sizeof(t));\r\n==\r\n\r\nh3. 9.c\r\n\r\nDaca avem de comparat doua siruri ({$s{~1~}, s{~2~}$}) a caror lungime o stim ({$len_s{~1~}$}, respectiv {$len_s{~2~}$}) este mai rapid\r\n\r\n== code(cpp) |memcmp(s1, s2, MIN(len_s1, len_s2)+1)\r\n==\r\n\r\ndecat\r\n\r\n== code(cpp) |strcmp(s1, s2);\r\n==\r\n\r\nh3. 9.d\r\n\r\n== code(cpp)|scanf(\" %c\", &ch)\r\n==\r\n\r\nciteste primul caracter dupa spatiile albe (daca exista).\r\n\r\n\r\n\r\nh2. Pont #10\r\n\r\nDaca programati in C++ fara sa folositi STL incercati sa renuntati la C++. Unul dintre motive: clasele (implicit iostream: cin, cout, cerr) incetinesc mult executia programului.\r\n\r\nh2. Pont #11\r\n\r\nIn final, o intrebare pentru cei ce folosesc C++ (asta e un hint). Cum se calculeaza factorial la compilare? (fara a scrie efectiv {$1*2*3...*n$})\r\nRaspuns: Utilizand templaturi. Avem nevoie doar de o constanta {$N$}.\r\n\r\n== code(cpp) |#include <stdio.h>\r\n\r\ntemplate<int N>\r\nstruct Factorial {\r\n    enum {\r\n        value = Factorial<N-1>::value * N\r\n    };\r\n};\r\n\r\ntemplate<>\r\nstruct Factorial<0> {\r\n    enum { value = 1 };\r\n};\r\n\r\nint main(void)\r\n{\r\n    int i = Factorial<4>::value;\r\n    char c[Factorial<5>::value];\r\n    printf(\"%d \",i);\r\n    printf(\"%d \",sizeof(c));\r\n}\r\n==\r\n\r\nPS: nu dau $2.56 pentru fiecare greseala descoperita in acest articol.\r\n',2044,'public',3674,NULL),('preoni-2006/runda-1/clasament-10','Clasament preoni61b','2006-11-25 01:17:13','2006-11-25 01:17:13','h1. Clasament ==roundparam(round_id=\"preoni61b\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni61b\")==',961,'protected',NULL,NULL),('preoji-2004/clasament-11-12','Clasament preOJI 2004, clasele 11-12','2006-11-23 21:08:49','2006-11-24 17:48:27','h1. Clasament \'preOJI 2004\':preoji-2004, clasele 11-12\r\n\r\n==Rankings(rounds = \"preoji2\")==',961,'protected',NULL,NULL),('template/trimite-solutii','template/trimite-solutii','2006-11-27 05:42:46','2006-11-27 06:05:06','h2. Evaluatorul infoarena\r\n\r\n\"Afla detalii despre evaluator\":documentatie/evaluator: cum functioneaza, ce versiuni de compilatoare folosim, parametri de compilare, memorie disponibila, configuratie hardware etc.\r\n\r\nh2. Ceva nu functioneaza?\r\n\r\n* Citeste din \"ghidul utilizatorului\":documentatie/trimiterea-solutiilor.\r\n* Daca tot nu e bine, ==SmfLink(caption=\"contacteaza-ne pe forum\" link=\"board\" board=\"33\")==!',13,'protected',NULL,NULL),('template/login','template/login','2006-11-27 05:56:40','2006-12-04 01:56:03','h2. Ceva nu functioneaza?\r\n\r\n* Mai intai citeste pagina cu \"*probleme frecvente la autentificare*\":documentatie/probleme-frecvente-la-autentificare.\r\n* Daca tot nu e bine, ==SmfLink(caption=\"contacteaza-ne pe forum\" link=\"board\" board=\"33\")==!',13,'protected',NULL,NULL),('template/resetarea-parolei','template/resetarea-parolei','2006-11-27 06:06:06','2006-11-27 06:08:35','h2. Ceva nu functioneaza?\r\n\r\n* ==SmfLink(caption=\"Contacteaza-ne pe forum\" link=\"board\" board=\"33\")==',13,'protected',NULL,NULL),('template/borderou','template/borderou','2006-11-27 06:20:43','2006-12-29 14:50:35','h2. Ceva nu functioneaza?\r\n\r\n* Citeste despre \"borderoul de evaluare\":documentatie/borderoul-de-evaluare.\r\n* Daca tot nu e bine, ==SmfLink(caption=\"contacteaza-ne pe forum\" link=\"board\" board=\"33\")== !\r\n',1142,'protected',NULL,NULL),('favicon.ico','favicon.ico','2006-11-28 00:00:22','2006-12-01 19:07:01','000001111',1858,'public',NULL,NULL),('template/userinfo/header','Informatii despre %user_id%','2006-11-28 02:10:50','2006-11-28 02:10:50','table(compact). |/4. !utilizator/%user_id%?avatar 150x150! |_. Nume | == userinfo(user=\"%user_id%\" info=\"fullname\")== |\r\n| |_. Cont infoarena | == userinfo(user=\"%user_id%\" info=\"username\")== |\r\n| |_. Statut infoarena | == userinfo(user=\"%user_id%\" info=\"security\")== |\r\n|_. Forum | ==SmfLink(user=\"%user_id%\" link=\"pm\" caption=\"trimite mesaj privat\")==, ==SmfLink(user=\"%user_id%\" link=\"stats\" caption=\"vezi activitate\")== |\r\n',1142,'public',NULL,NULL),('template/userinfo/main','Informatii despre %user_id%','2006-11-28 02:14:47','2006-11-28 02:14:47','h1. == userinfo(user=\"%user_id%\" info=\"fullname\") ==\r\n\r\n== include(page=\"template/userinfo\" user_id=\"%user_id%\") ==\r\n\r\n== include(page=\"template/userstats\" user_id=\"%user_id%\") ==\r\n\r\nVezi si \'profilul personalizat\':utilizator/%user_id% al acestui user.',1142,'protected',NULL,NULL),('preoni-2006/clasament','Clasament, preONI 2006','2006-11-25 03:57:02','2006-12-01 18:11:55','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Clasament preONI 2006\r\n\r\nh2. Rundele online\r\n\r\n* \'Clasament clasa a 9-a (si gimnaziu)\':preoni-2006/clasament-9\r\n* \'Clasament clasa a 10-a\':preoni-2006/clasament-10\r\n* \'Clasament clasele 11-12\':preoni-2006/clasament-11-12\r\n\r\nh2. Runda finala\r\n\r\n* \'Clasament clasa a 9-a (si gimnaziu)\':preoni-2006/finala/clasament-9\r\n* \'Clasament clasa a 10-a\':preoni-2006/finala/clasament-10\r\n* \'Clasament clasele 11-12\':preoni-2006/finala/clasament-11-12\r\n',13,'protected',NULL,NULL),('preoni-2006/finala/clasament-9','Clasament Finala preONI 2006, Clasa a IX-a si gimnaziu','2006-11-23 21:08:59','2006-12-01 18:14:52','== include(page=\"template/preoni-2006/finalrankings\") ==\r\n\r\nh2. Clasa a IX-a si gimnaziu\r\n\r\n==Rankings(rounds = \"preoni65a\")==',13,'protected',NULL,NULL),('preoni-2006/finala/clasament-11-12','Clasament Finala preONI 2006, Clasele XI-XII','2006-11-23 21:09:00','2006-12-01 18:16:17','== include(page=\"template/preoni-2006/finalrankings\") ==\r\n\r\nh2. Clasele XI-XII\r\n\r\n==Rankings(rounds = \"preoni65c\")==',13,'protected',NULL,NULL),('template/preoni-2006/finalrankings','template/preoni-2006/finalrankings','2006-12-01 18:10:32','2006-12-01 18:15:33','==include(page=\"template/preoni-2006/header\")==\r\n\r\np{font-weight: bold}. &larr; \"preONI 2006 Homepage\":preoni-2006\r\n\r\nh1. Clasament Finala preONI 2006\r\n\r\np={font-weight: bold}. \"Clasa a IX-a si gimnaziu\":preoni-2006/finala/clasament-9 | \"Clasa a X-a \":preoni-2006/finala/clasament-10 | \"Clasele XI-XII\":preoni-2006/finala/clasament-11-12\r\n\r\n',13,'protected',NULL,NULL),('template/raw','template/raw','2006-11-11 11:25:13','2006-11-11 20:49:09','{color:red}|_=. Aceasta pagina a fost importata din infoarena1 si nu este inca prelucrata. \r\nSterge @==Include(file=\"template/raw\")==@ cand esti multumit cu continutul paginii.|',15,'protected',NULL,NULL),('runda/preoni2007_runda3_9','runda/preoni2007_runda3_9','2007-03-02 18:09:27','2007-03-02 18:09:27','begin\r\n   writeln (\'Salutare lume pt toti iubitori de anime\');\r\nend',5889,'public',NULL,NULL),('ciclu-hamiltonian-in-graf-dens','Ciclu hamiltonian in graf dens','2004-11-09 00:00:00','2009-02-20 00:52:02','h1. Ciclu hamiltonian in graf dens\r\n\r\n(Categoria _Algoritmi_, Autor _Leonard Crestez_)\r\n\r\nIn acest articol va voi prezenta un algoritm pentru gasirea unui ciclu hamiltonian intr-un graf neorientat dens - in care fiecare nod are macar $(N + 1) / 2$ muchii.\r\n\r\nIn general, gasirea unui ciclu hamiltonian intr-un graf neorientat este un exemplu clasic de problema NP - completa. Insa, daca graful este dens - fiecare nod are cel putin $(N+1) / 2$ muchii incidente ({$N$} este numarul de noduri) - se poate gasi o solutie de complexitate {$O(N^2^)$}.\r\n\r\nh2. Algoritm\r\n\r\nLa inceput formam un ciclu la intamplare, fara a tine cont daca muchiile luate in considerare chiar exista in graf. Astfel, putem alege chiar ciclul {$1, 2, 3, 4, ... N$}. Daca acest ciclu este valid, atunci avem noroc si solutia a fost gasita. Altfel, trebuie sa incercam sa \"umplem gaurile\" din ciclu (adica muchiile pe care le-am ales la intamplare si care nu exista in graf).\r\n\r\nGasim prima muchie de acest fel, fie ea ({$A, B$}). Cautam apoi doua alte noduri adiacente in ciclul nostru, notate cu $C$ si {$D$}, astfel incat sa avem muchie de la $A$ la $C$ si de la $B$ la {$D$}. Se poate demonstra ca vom gasi mereu $C$ si {$D$}. Acum vom \"incrucisa\" $A B$ cu {$C D$}. Prin \"incrucisare\" se intelege transfromarea unui ciclu $...AB...CD...$ in $...AC...BD...$ (sau $...CD...AB...$ in $...CA...DB...$) . Atentie, secventa de la $B$ la $C$ (respectiv de la $D$ la {$A$}) va fi inversata complet!\r\n\r\nSe observa ca a scazut numarul de \"gauri\" din sir, $AB$ a fost eliminata si nu au fost adaugate \"gauri\" noi. Repetam \"umplerea gaurilor\" pana nu mai avem ce umple, deci am gasit solutie.\r\n\r\nDesi suna complicat, \"umplerea unei gauri\" necesita doar $O(N)$ timp pentru cautarea nodurile {$AB$}, {$CD$}, si incrucisare. Avand in vedere ca sunt maxim $N$ gauri la inceput, algoritmul necesita $O(N^2^)$ ca timp de executie.\r\n\r\nMai sus am folosit o afirmatie fara a o demonstra. Demonstratia e relativ intuitiva. Daca nu o descoperiti singuri, puteti sa intrebati pe \"forum\":http://infoarena.ro/forum.\r\n\r\nProblema luata in discutie este propusa pe lista \"sgu\":http://acm.sgu.ru/, nr. \"122\":http://acm.sgu.ru/problem.php?contest=0&problem=122, unde exista si evaluator online. Atentie la implementare! Citirea si scrierea folosind functii standard pot iesi din timp!\r\n\r\n',2044,'public',3693,NULL),('blog/rezultate-ioi-2004','Rezultate IOI 2004','2004-11-10 00:00:00','2004-11-10 00:00:00','h1. Rezultate IOI 2004\r\n\r\n\"IOI 2004\":http://www.ioi2004.org/ - a 16-a editie a Olimpiadei Internationale de Informatica s-a desfasurat la Atena, Grecia, in perioada 11-18 septembrie.\r\n\r\nIn cadrul acestei competitii, lotul roman a fost insotit de:\r\n\r\n* Prof. Emanuela Cerchez\r\n* Prof. Ovidiu Domsa\r\n\r\nh2. Medalii\r\n\r\n* Ganceanu Silviu Ionut, aur\r\n* Crestez Dan-Leonard, argint\r\n* Vladu Adrian, argint\r\n* Stancu-Mara Sorin, bronz\r\n\r\nIi felicitam pe ei si pe toti cei ce s-au implicat si se implica in continuare in pregatirea lor.',1142,'protected',NULL,NULL),('preoni-2006','preONI 2006','2006-11-22 23:02:20','2008-02-14 15:57:04','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. preONI 2006\r\n\r\n*Editia 2006 a concursului preONI s-a incheiat cu succes la Focsani in perioada 24-26 martie!*\r\nFinala a fost ... \"Super. Super\", \"Super tare\", \"mda...a mers\" o spun concurentii. A fost grozav, intr-adevar, si ne-a facut mare placere sa va vedem prezenti intr-un numar atat de mare si veniti atat de departe. Va multumim pentru participare si speram ca ati petrecut un week-end pe cinste cu noi la Focsani. Toata echipa infoarena merita felicitata pentru organizarea si efortul depus de-a lungul campaniei. Inca odata multimim domnului profesor Onea pentru organizarea \"fara cusur\".\r\n\r\np={font-weight: bold}. \"Cronica\":preoni-2006/finala/cronica | \"Feedback\":preoni-2006/finala/feedback | \"Poze!\":preoni-2006/finala/poze\r\n\r\nh2. Noutati\r\n\r\nSponsorii finalei sunt:\r\n\r\n\"!preoni-2006?oracle_ro.gif!\":http://www.oracle.com/global/ro/index.html\r\n\r\n\"Colegiul National Unirea, Focsani\":http://cnu.lufo.ro/\r\n\r\n*Hotel Unirea, Focsani*\r\n\r\nViziteaza \"Pagina rundei finale\":preoni-2006/finala.\r\n\r\nh2. preONI 2006 pe scurt\r\n\r\nConcursul este destinat elevilor de liceu ce se pregatesc pentru competitii de informatica (in special ONI).\r\n\r\npreONI 2006 este impartit pe 3 grupe (Clasa a 9-a si gimnaziu, Clasa a 10-a, Clasele 11-12), iar concurentii vor avea de rezolvat 3 probleme in 4 ore. Primele 4 runde online se vor desfasura in zile de sambata, incepand de la ora 09:00, iar in urma acestora cei mai buni de la fiecare grupa vor participa la o runda finala care se va desfasura intr-o \"tabara\":preoni-2006/finala, la sfarsit acordandu-se \"premii\":preoni-2006/premii. In continuare veti gasi un tabel cu datele provizorii ale rundelor: \r\n\r\n|_. Runda|_. Data|_. Pagina cu detalii|\r\n|#1|19 noiembrie 2005|\"Runda 1 preONI 2006\":preoni-2006/runda-1|\r\n|#2|17 decembrie 2005|\"Runda 2 preONI 2006\":preoni-2006/runda-2|\r\n|#3|21 ianuarie 2006|\"Runda 3 preONI 2006\":preoni-2006/runda-3|\r\n|#4|19 februarie 2006|\"Runda 4 preONI 2006\":preoni-2006/runda-4|\r\n|Finala|24 - 26 martie 2006|\"Runda finala (Focsani)\":preoni-2006/finala|\r\n\r\n\r\n==include(page=\"template/preoni-2006/footer\")==',1,'public',NULL,NULL),('template/preoni-2006/footer','template/preoni-2006/footer','2006-11-27 16:13:42','2008-10-12 20:43:50','h2. Sponsori\r\n\r\n\"!preoni-2006?softwin.gif!\":http://www.softwin.ro/ \"!preoni-2006?microsoft.jpg!\":http://www.microsoft.com/romania/ \"!preoni-2006?totalsoft.gif!\":http://www.totalsoft.ro/\r\n',1490,'protected',NULL,NULL),('blog/rezultate-ceoi-2004','Rezultate CEOI 2004','2004-11-09 00:00:00','2004-11-09 00:00:00','h1. Rezultate CEOI 2004\r\n\r\nCEOI 2004 s-a incheiat. Lotul olimpic roman a obtinut rezultate remarcabile aducand acasa nu mai putin de 4 medalii.\r\n\r\nRomania a fost reprezentata de:\r\n\r\n* Prof. insotitor Stelian Ciurea\r\n* Prof. insotitor Doru Anastasiu Popescu\r\n* Mircea Digulescu\r\n* Mosoi Alexandru\r\n* Dan-Constantin Spatarel\r\n* Stancu Mara Sorin\r\n\r\nh2. Medalii\r\n\r\n* Argint - Mosoi Alexandru\r\n* Argint - Spatarel Dan-Constantin\r\n* Bronz - Stancu Mara Sorin\r\n* Bronz - Digulescu Mircea',1142,'protected',NULL,NULL),('blog/rezultate-boi-2004','Rezultate BOI 2004','2004-11-08 00:00:00','2004-11-08 00:00:00','h1. Rezultate BOI 2004\r\n\r\n\"BOI 2004\":http://www.boi2004-plovdiv.org/ - a 12-a editie a Olimpiadei Balcanice de Informatica s-a desfasurat in Plovdiv, Bulgaria, in perioada 3-9 iulie.\r\n\r\nIn cadrul acestei competitii, lotul roman a fost format din :\r\n\r\n* Prof. Marinel Serban\r\n* Prof. Daniel Popa\r\n* Adrian Vladu\r\n* Mircea Pasoi\r\n* Silviu Ganceanu\r\n* Marius Dumitran\r\n\r\nEchipa noastra a obtinut 3 medalii:\r\n\r\n* Pasoi Mircea, argint\r\n* Vladu Adrian, bronz\r\n* Ganceanu Silviu, bronz\r\n\r\nIi felicitam pe ei si pe toti cei ce s-au implicat si se implica in continuare in pregatirea lor.\r\n\r\n',1142,'protected',NULL,NULL),('template/userstats','template/userstats','2006-11-26 22:39:30','2006-12-08 04:29:55','h2. Statistici pentru %user%\r\n\r\nh3. Probleme rezolvate\r\n\r\n==SolvedTasks(user=\"%user%\")==\r\n\r\nh3. Probleme incercate\r\n\r\n==FailedTasks(user=\"%user%\")==\r\n\r\nh3. Participant la&hellip;\r\n\r\n==Rounds(user=\"%user%\")==',13,'protected',NULL,NULL),('blog/lansare-portal-info.devnet.ro','Lansare portal info.devNet!','2004-11-11 00:00:00','2004-11-11 00:00:00','h1. Lansare portal info.devNet!\r\n\r\ninfo.devNet este un portal de informatica dedicat tuturor celor pasionati de acest domeniu. Portalul prezinta articole despre algoritmi, structuri de date, limbaje de programare, probleme si competitii de informatica, o lista comprehensiva de resurse web, downloads si sustine o comunitate activa formata, in special, din elevi si studenti, fosti sau actuali olimpici la informatica.\r\n\r\nScopul acestui portal este de a oferi elevilor si studentilor ce se pregatesc pentru competitii de informatica acces usor si rapid la materiale valoroase de pregatire, de a-i tine la curent cu ultimele noutati legate de acest domeniu si de a facilita comunicarea intre acestia.\r\n\r\nMaterialele prezente pe acest site sunt scrise 100% prin voluntariat de catre fosti sau actuali olimpici la informatica. Unii dintre ei au fost medaliati la competii internationale, altii au fost selectionati in lotul national de informatica sau au castigat locuri fruntase la ONI. Indiferent de autor, vom incerca sa verificam si sa imbunatatim constant articolele publicate. Incurajam din plin discutiile, comentariile si sugestiile pe marginea lor in cadrul \"forumului\":http://forum.infoarena.ro/.\r\n\r\nIi rugam pe cei care doresc sa contribuie la construirea acestui \"knowledge-base\" sa ne contacteze prin intermediul forumului!\r\n\r\n',1142,'protected',NULL,NULL),('warm-up-2004/solutii','Solutiile oficiale pentru Concursul \"de incalzire\"','2004-11-15 00:00:00','2007-10-09 13:16:27','h1. Solutiile oficiale pentru Concursul \"de incalzire\"\r\n\r\n(Categoria _Competitii_, autor(i) _Mircea Pasoi_)\r\n\r\nIn acest articol voi prezenta cateva idei de rezolvare pentru problemele din concursul \"de incalzire\" de la clasele 9-10 si 11-12.\r\n\r\nIncep prin a recunoaste faptul ca setul de probleme a fost unul foarte dur, comparabil cu unul de la nationale, chiar baraje. Pe viitor vom incerca sa facem concursurile mai gradate. Reversul medaliei este ca aveti acum probleme dure cu care sa va pregatiti si la care voi prezenta idei de solutie avand astfel ce invata! Nu voi incerca sa dau solutii foarte explicite, ci doar voi schita ideile de baza deoarece este important sa incercati sa intelegi si sa implementati singuri solutiile! ;)\r\n\r\nh2. Clasele 9-10\r\n\r\nh3. **Coins**\r\n\r\nPrimul fapt care trebuie observat este numarul destul de mic al starilor de joc si anume {$2^22^ = 4.194.304$}. Recomand \"cartea doamnei Cerchez\":http://www.liis.ro/%7eema/ despre arbori pentru a citi capitolul despre Arbori de Joc. Ideea principala este ca se exploreaza intregul arbore de joc format de starile tablei de $22$ de patralele si se retine intr-un vector boolean pentru fiecare configuratie daca jucatorul care incepe cu acea configuratie castiga sau nu. Astfel, se va raspunde la fiecare din cele $N$ teste in $O(1)$ dupa preprocesarea in $O(22 * 2^22^) = O(1)$ :).\r\n\r\nh3. **Zaharel**\r\n\r\nSolutia se bazeaza pe proprietatea foarte importanta (subliniata si in enunt) ca pe fiecare linie exista un punct rosu si pe fiecare coloana un punct albastru. Presupunem ca tinem o lista cu puncte. Initial bagam un punct rosu oarecare. Pe coloana punctului rosu respectiv exista un punct albastru (din proprietatea de mai sus). Inseram acel punct albastru in lista. Pe linia punctul albastru va exista un punct rosu , pe care il vom insera in lista. Repetand acest procedeu vom ajunge la un moment dat la un punct care a mai fost in lista ,deci la un ciclu (acest lucru este evident deoarece numarul punctelor este finit). Punctele rosii de pe ciclu vor reprezenta primul poligon, iar punctele albastre al doilea poligon. Este evident ca vor avea acelasi numar de varfuri, vom arata in continuare ca au si acelasi centru de greutate. Fie primul punct (acela rosu) ({$x{~1~}, y{~1~}$}). Al doilea va fi ({$x{~2~}, y{~1~}$}), al treilea ({$x{~2~}, y{~2~}$}), al patrulea ({$x{~3~}, y{~2~}$}) .. penultimul ({$x{~k~}, y{~k-1~}$}), ultimul ({$x{~k~}, y{~k~}$}) (care va coincide cu un alt punct ({$x{~p~}, y{~p~}$}), {$p < k$}). Se observa ca poligonul rosu va avea ca centru de greutate punctul ({$(x{~p~}&#0043;x{~p+1~}&#0043;...&#0043;x{~k-1~})/(k-p)$}, {$(y{~p~}&#0043;y{~p+1~}&#0043;...&#0043;y{~k-1~})/(k-p)$}), iar cel albastru {$(x{~p+1~}&#0043;x{~p+2~}&#0043;...&#0043;x{~k~})/(k-p)$}, {$(y{~p+1~}&#0043;y{~p+2~}&#0043;...&#0043;y{~k~})/(k-p)$}), care coincid deoarece ({$x{~p~},y{~p~}$}) = ({$x{~k~}, y{~k~}$}).\r\n\r\nh3. **Sobo**\r\n\r\nProblema se rezolva prin programare dinamica. Se retine in $A{~i~}$ = costul minim in cazul cel mai defavorabil pentru a recunoaste sobolanul inteligent din multimea de sobolani cu numerele de ordine pozitiile bitilor de $1$ in reprezentarea binara a lui {$i$}. Astfel, $A$ va avea valori pentru $i$ intre $0$ si {$2^N^-1$}. Raspunsul va fi {$A{~2^N^-1~}$}. Este evident ca graful format de aceste stari este aciclic deoarece fiecare raspuns imparte o multime in doua multimi mai mici. Astfel pentru a calcula un $A{~i~}$ vom lua fiecare raspuns care imparte in doua multimi nevide multimea curenta, vom vedea in care multime costul este mai mare (cazul cel mai defavorabil) , adaugam pretul raspunsului si actualizam in $A{~i~}$ daca valoarea aceasta este mai mica decat cea curenta (sa nu uitam ca vrem cost minim in cazul cel mai defavorabil). Cea mai simpla metoda de a implementa acest mecanism este cu memoizare. Complexitatea finala {$O(2^N^ * L * N)$}. Se poate optimiza la {$O(2^N^ * L)$} folosind operatii pe biti.\r\n\r\n\r\n\r\nh2. Clasele 11-12\r\n\r\nh3. **Xor Max**\r\n\r\nFie {$X{~i~} = A{~1~} xor A{~2~} xor ... xor A{~i~}$}. Pentru fiecare $X{~i~}$ vom incearca sa gasim un $X{~j~}$ ({$j < i$}) astfel incat $X{~i~} xor X{~j~}$ sa fie maxim. Pentru a realiza aceasta operatie eficient vom mentine un *trie* (vezi in CLR varianta in romana la pagina 223 - capitolul \"Arbori binari de cautare\" problema 13-2 - se asemana cu \"suffix trees/tries\" doar ca vom lucra cu siruri binare). Fie $b$ numarul maxim de biti pe care ii are un element din vector. Vom realiza operatia de gasire a lui $X{~j~}$ in {$O(b)$}. Structura de date mentionata mai sus va memora sirurile de biti formate de vectorul {$X$}. Vom parcurge bitii lui $X{~i~}$ de la cel mai semnificativ la cel mai nesemnificativ. Astfel daca bitul curent este {$1$}, vom incerca sa gasim un sir de biti care are acest bit $0$ (pentru a maxima xor-ul), iar daca bitul curent este $0$ vom proceda invers. Complexitatea finala a algoritmului este {$O(N*b)$}.\r\n\r\nh3. **Boom**\r\n\r\nVom construi un graf din cele $2^N^$ stari posibile. Prin stare intelegem un numar binar in care bitii de $1$ reprezinta locurile in care s-ar putea afla sobolanul. Pentru fiecare astfel de nod, exista $M$ muchii la alte noduri, care se obtin aplicand bomba asupra pozitiilor si avansarea pozitiilor ramase. Deoarece muchiile au costuri numere naturale, iar graful nu este neaparat aciclic vom aplica algoritmul Dijkstra, pentru a determina drumul de cost minim de la nodul $2^N^-1$ la nodul {$0$}. Pentru a se incadra in timp era necesara implementarea cozii de prioritate cu heap-uri. Complexitate finala {$O(2^N^ * N * M)$}.\r\n\r\nh3. **PetSoft**\r\n\r\nIn fiecare nod din arbore vom retine doua valori $A{~i, 0~}$ = costul maxim pentru a cupla subarborele cu radacina in {$i$}, fara a cupla nodul $i$ cu cineva, si $A{~i, 1~}$ acelasi lucru, dar cupland nodul $i$ cu cineva. Pentru a calcula aceste valori in fiecare nod, luam numerele de ordine a fiilor, le sortam si aplicam o alta dinamica pentru a obtine echipe cu cost maxim. Astfel determinam {$A{~i, 0~}$}. Pentru a calcula {$A{~i, 1~}$}, inseram si nodul $i$ in lista fiilor, sortam din nou si aplicam aceeasi dinamica (atentie la detalii de implementare!). Dinamica se face astfel: retinem in $C{~i, j~}$ = costul maxim pentru a forma echipe de cost maxim cu valorile de pe pozitiile {$i, i+1 ... j-1, j$}. Este evident ca $C{~i, j~}$ se obtine din {$C{~i+1, j~}$}, $C{~i, j-1~}$ si {$C{~i+1, j-1~}$}. Complexitatea finala este {$O(N^2^)$}.\r\n\r\n',1231,'public',NULL,NULL),('algoritmul-lui-euclid','Algoritmul lui Euclid','2004-11-16 00:00:00','2009-02-20 00:06:26','h1. Algoritmul lui Euclid\r\n\r\n(Categoria _Matematica_, Autor _Leonard Crestez_)\r\n\r\nO prezentare a variantei extinse a algoritmului lui Euclid, care rezolva ecuatie de forma {$A * X + B * Y = D$}, unde $D$ este cel mai mare divizor comun al lui $A$ si {$B$}. De asemenea este prezentata o aplicatie \"interesanta\": impartirea modulara.\r\n\r\nProbabil ca multi stiti algoritmul lui Euclid de prin clasa a 5-a, cand invatati la matematica divizibilitate. Varianta simplista a algoritmului lui Euclid este cunoscuta de multa lume, dar fara prea multe explicatii despre functionarea lui.\r\n\r\nh2. Euclid simplu\r\n\r\nIn cuvinte, algoritmul pur si simplu imparte deimpartitul la rest pana cand impartitorul este {$0$}, apoi returneaza deimpartitul. Poate fi usor implementat iterativ in C. Probabil ca aceasta forma este si cea mai rapida, si este de preferat cand nu e necesar Euclid extins.\r\n\r\n== code(c) | int euclid(int a, int b)\r\n{\r\n    int c;\r\n    while (b) {\r\n        c = a % b;\r\n        a = b;\r\n        b = c;\r\n    }\r\n    return a;\r\n}\r\n==\r\n\r\nPentru a fi inteles mai usor si eventual extins, este mai bine sa il punem sub forma recursiva\r\n\r\n== code(c) | void euclid(int a, int b, int *d)\r\n{\r\n    if (b == 0) {\r\n        *d = a;\r\n    } else\r\n        euclid(b, a % b, d);\r\n}\r\n==\r\n\r\nSa vedem cum functioneaza algoritmul lui Euclid. Se observa ca daca {$a<b$}, atunci $euclid(b, a % b)$ este de fapt {$euclid(b, a)$}.\r\n\r\nVom demonstra ca {$cmmdc(a, b) = cmmdc(b, a % b)$}. Notam $cmmdc(a, b)$ cu {$d$}. Scriem $a%b$ drept {$a - b * c$}, unde $c$ este parte intreaga din {$a / b$}. Cum $a$ si $b$ sunt divizibile cu {$d$}, atunci orice combinatie liniara a lor este divizibila cu {$d$}, inclusiv {$a - b * c = a%b$}.\r\nAsta insa nu este de ajuns, putem aveam {$Z > d$}, $Z$ divizibil cu {$d$}, care sa fie {$cmmdc(b, a % b)$}. Insa atunci ar rezulta similar ca a e divizibil cu {$Z$}, deci {$Z = d = cmmdc(a, b)$}, Incalcand {$Z > d$}.\r\n\r\nAstfel, algoritmul lucreaza reducand problema la numere din ce in ce mai mici, pana cand {$a % b = 0$}. Ca sa finalizam recurenta, daca $a$ este divizibil cu {$b$}, atunci este evident ca {$cmmdc(a, b)$} este {$b$}. In cod este un pic mai \"ciudat\", prindem acest caz doar dupa inca un apel recurent, cand {$b = 0$}. De fapt cred ca $cmmdc$ este definit pe numere strict pozitive, dar in informatica putem ocoli un pic matematica.\r\n\r\nh2. Euclid extins\r\n\r\nAcest algoritm poate fi extins, in sensul gasirii $x$ si $y$ astfel incat {$a * x + b * y = d$}. In acest articol vom incerca sa deducem modul de calculare al lui $x$ si {$y$}. Cei grabiti sau certati cu matematica pot sari direct la codul sursa, dar vor avea probleme in a tine minte algoritmul pe viitor.\r\n\r\nVom extinde procedura recursiva de calculare a $cmmdc$ pentru a include si $x$ si {$y$}. Calculam $x$ si $y$ incepand de la \"capatul recurentei\". Daca {$b = 0$}, atunci $a * 1 + b * 0 = a(cmmdc)$ evident, asa ca initial $x = 1$ si {$y = 0$}. Incercam sa calculam {$x$}, $y$ in functie de {$x0$}, $y0$ obtinuti pentru {$b$}, {$a % b$}. Noi stim urmatoarele:\r\n\r\n* $b * x0 + (a % b) * y0 = d$\r\n* $a * x + b * y = d$\r\n\r\nTrebuie sa aflam o solutie pentru $x$ si {$y$}. Vom nota ca mai sus parte intreaga din $a / b$ cu {$c$}.\r\n\r\n* $b * x0 + (a - b * c) * y0 = a * x + b * y$\r\n* $b * (x0 - c * y0 - y) = a * (x - y0)$\r\n\r\nO solutie este acum evidenta (Una, sunt o infinitate de perechi {$x, y$})\r\n\r\n* {$x0 - c * y0 - y = 0$}, De unde rezulta $y = x0 - c * y0$\r\n* {$x - y0 = 0$}, De unde rezulta $x = y0$\r\n\r\nAcum nu mai pare asa de \"magic\", nu?\r\n\r\nSursa modificata pentru a calcula si $x$ si $y$ nu este mult mai complexa. Acum intelegeti de ce am trimis $d$ ca pointer mai sus, si de ce am folosit varianta recursiva a algoritmului lui euclid. Implementat iterativ, este nevoie de un vector care sa tina toate valorile $c$ ({$a / b$}) obtinute pe parcurs.\r\n\r\nNota pentru pascalisti: in C nu exista div, impartirea intre int-uri este automat si impartire intreaga (div din pascal).\r\n\r\n== code(c) | void euclid(int a, int b, int *d, int *x, int *y)\r\n{\r\n    if (b == 0) {\r\n        *d = a;\r\n        *x = 1;\r\n        *y = 0;\r\n    } else {\r\n        int x0, y0;\r\n        euclid(b, a % b, d, &x0, &y0);\r\n        *x = y0;\r\n        *y = x0 - (a / b) * y0;\r\n    }\r\n}\r\n==\r\n\r\nh2. Impartire modulara\r\n\r\nAcum pentru o aplicatie interesanta, impartirea modulara. Nu voi intra in detalii, pe scurt aritmetica modulara este aritmetica in care toate valorile se iau modulo un anumit numar {$n$}. Spre exemplu, in {@modulo 7@}, {$3 = 10$}. Similar, rezultatele tuturor operatiilor se iau in modul: {$4 + 5 = 2$}, {$3 * 5 = 1$} etc.\r\n\r\nCum putem defini insa impartirea in modulo? Evident, {$6 / 2$} este tot {$3$}, dar $3 / 4$ cu cat este egal? De obicei impartirea este definita ca operatia inversa a inmultirii, similar cum scaderea este operatia inversa a adunarii. Astfel, daca {$a / b = c$} atunci {$b * c = a$}. Prin algoritmul lui Euclid putem afla $x$ si $y$ astfel incat {$n * x + b * y = cmmdc(n, b)$}, unde $n$ este modulul. Totul e modulo {$n$}, asa ca putem ignora {$x * n$}. Atunci {$c = y * a / cmmdc(n, b)$}. Daca $a$ nu este divizibil cu {$cmmdc(n, b)$}, atunci $c$ nu exista. Intradevar, nu exista $c$ pentru care $3 * c = 4$ modulo {$6$}.\r\n\r\nh2. Tema pentru acasa\r\n\r\nCateva probleme care se rezolva intr-un mod sau altul folosing algoritmul lui Euclid sau algoritmul lui Euclid extins:\r\n\r\n* Sgu 106: \"The Equation\":http://acm.sgu.ru/problem.php?contest=0&problem=106\r\n* Sgu 137: \"Funny Strings\":http://acm.sgu.ru/problem.php?contest=0&problem=137\r\n* Sgu 141: \"Jumping Joe\":http://acm.sgu.ru/problem.php?contest=0&problem=141\r\n* Sgu 248: \"Integer Linear Programming\":http://acm.sgu.ru/problem.php?contest=0&problem=248\r\n\r\nO sursa interesanta pentru Algoritmul lui Euclid este cea din cartea lui Knuth Arta Programarii Calculatoarelor Vol. 2 Algoritmi Seminumerici care descrie stransa legatura intre algoritm si fractiile continue (Cap. 4.5.3)',2044,'public',3681,NULL),('agora-finala/solutii','Concursul Agora - Etapa Finala - Solutii','2005-07-12 00:00:00','2008-04-03 22:07:13','h1. Concursul Agora - Etapa Finala - Solutii\r\n\r\n(Categoria _Competitii_, autor(i) _Cosmin_)\r\n\r\nArticolul contine cateva idei de solutionare a problemelor de la etapa finala a concursului Agora. Concursul s-a desfasurat la Cluj in 9 iulie pentru concurentii ce s-au calificat in finala, dar s-a desfasurat si online pentru cei care doreau sa isi incerce puterile.\r\n\r\nh2. Problema 1: Drumuri\r\n\r\nProblema cerea determinarea unei partitionari a muchiilor dintr-un graf conex in perechi disjuncte astfel ca in fiecare pereche de muchii cele doua muchii sa aiba un capat comun. Pentru orice graf conex cu numar par de muchii exista o asemenea partitionare a muchiilor. Algoritmul ce solutioneaza problema ne demonstreaza acest lucru. Putem determina pentru graful nostru un arbore partial (arbore DFS sau BFS sau care mai vreti voi). Putem lua o frunza din arborele nostru, daca ea are grad par atunci o putem elimina din arbore si toate muchiile ce aveau un capat in ea sa le imperechem doua cate doua. Daca in schimb frunza are grad impar atunci eliminam toate muchiile mai putin cea din arbore si eliminam nodul virtual din graf, dar nu si muchia asociata care devine o muchie oarecare si va putea fi eliminata cand procesam tata frunzei actuale. Singura problema ce poate aparea este cand ajungem la radacina, dar cum dintr-un graf cu numar par de muchii am eliminat la fiecare pas un numar par de muchii inseamna\r\nca radacina are grad par, deci problema noastra este rezolvata. Complexitatea algoritmului este $O(N + M)$ si ca timp si ca memorie, acest algoritm poate fi foarte usor implementat ca o parcurgere DFS care dupa ce viziteaza un nod si fii sai il elimina din graf.\r\n\r\nh2. Problema 2: Colectie\r\n\r\nProblema se imparte in doua bucati: Prima este determinarea numarului de cifre $i$ care apar in scrierea numerelor de la $1$ la $K$ unde $i$ este intre $0$ si {$9$}. Aceasta problema se poate rezolva in $O(log K)$ cu programare dinamica, o rezolvare eficienta a fost ceruta la bacalaureat in anul 2001 deci nu e asa grea :) , o rezolvare care lua putin timp ar fi fost metoda constantelor, adica putem tine minte din $100.000$ in $100.000$ rezultatele partiale (aceasta abordare a fost luata de Patcas Csaba la etapa finala).\r\nAcum avem de rezolvat o problema de obtinere a unui vector dimensiune $10$ ca suma unei submultimi de vectori dati la intrare. Aceasta problema o putem rezolva cu o tehnica intalnita pe la concursuri de programare, dar care nu a devenit inca clasica. Impartim multimea de vector in doua multimi de dimensiuni $n / 2$ si {$n - n /2$}. Pentru prima multime determinam toate submultimile si sumele vectoriale asociate acelor submultimi, si sortam submultimile dupa acele sume. Acum pentru fiecare submultime de vectori din a doua multime obtinem o suma vectoriala {$sum$}, noi vrem sa mai adaugam ceva elemente la aceasta suma pentru a obtine un vector $target$ ce reprezinta pentru fiecare cifra numarul de etichete necesare pentru a eticheta toate numerele de la $1$ la {$K$}. Deci vom cauta binar in primul sir vectorul {$target - sum$}. Faza de sortare dureaza $O(n^2^ * 2^n^)$ si faza de cautare binara tot atat.Astfel rezolvare are complexitatea $O(2^n^ * n^2^ + log K)$ ca timp si $O(2^n^ * n)$ ca spatiu.\r\n\r\nh2. Problema 3: Heroes of Might and Magic\r\n\r\nProblema cerea determinarea numarului de drumuri de la un punct ({$start_x, start_y$}) dintr-o matrice pana la un punct ({$end_x, end_y$}) din aceiasi matrice, drum care sa aiba cel mult $K$ pasi. Problema se rezolva usor folosind metoda programarii dinamice. Vom folosi o matrice tridimensionala unde $num_ways{~i,j,k~}$ are semnificatia: numarul de drumuri ce incep in ({$start_x, start_y$}), se termina in ({$i, j$}) si au fix $k$ pasi. Solutia se va afla in {$num_ways{~end_x,end_y,0~} &#0043; num_ways{~end_x,end_y,1~} &#0043; ... &#0043; num_ways{~end_x,end_y,K~}$}. Formula de recurenta pentru problema este usor de determinat:\r\n{$num_ways{~i,j,k~} = num_ways{~i+1,j,k-1~} &#0043; num_ways{~i-1,j,k-1~} &#0043; num_ways{~i,j-1,k-1~} &#0043; num_ways{~i,j+1,k-1~}$}. Se observa ca pentru a determina valorile corespunzatoare lui $k$ avem nevoie doar de valorile corespunzatoare lui {$k - 1$}, deci putem folosi doua matrici bidimensionale in loc de una tridimensionala. Complexitatea solutiei ca si timp este $O(N * M * K)$ iar ca si spatiu este {$O(N * M)$}.\r\n\r\n',6756,'public',NULL,NULL),('al-k-lea-drum-minim','Al K-lea drum minim','2004-11-29 00:00:00','2009-02-20 01:11:37','h1. Al K-lea drum minim\r\n\r\n(Categoria _Algoritmi_, Autor _Leonard Crestez_)\r\n\r\nExista un numar mare de algoritmi pentru a calcula cel mai scurt drum intre $2$ noduri intr-un graf, dar chiar si al {$2$}-lea cel mai scurt drum este o extindere non-triviala. Pentru a afla al {$k$}-lea drum minim se foloseste un algoritm total diferit fata de cei pentru drum minim. Algoritmul este dificil de implementat, iar sursa rezultata este de obicei voluminoasa, asa ca acest algoritm nu prea intervine in problemele de concurs. Am considerat totusi ca este destul de interesant, si merita prezentat.\r\n\r\nO nota importanta este ca nu se determina drumul cu al {$k$}-lea cost. Doua drumuri se considera diferita daca au noduri diferite, nu neaparat si cost diferit. Astfel, daca exista $5$ drumuri distincte de cost minim, oricare dintre ele poate fi solutie pentru al {$4$}-lea sau al {$5$}-lea drum minim. Astfel, aceasta problema are de fapt mai multe solutii posibile.\r\n\r\nExista $2$ cazuri pentru aceasta problema, iar algoritmul prezentat necesita mici modificari pentru a se adapta, dar ideea de baza ramane aceeasi. Cele doua cazuri sunt daca drumul trebuie neaparat sa fie elementar sau nu. Cazul in care se accepta doar drumuri elementare este mai restrictiv, si, astfel, un pic mai dificil.\r\n\r\nh2. Mod de functionare\r\n\r\nDaca pentru drumul minim intre $2$ noduri de obicei se calculeaza drumul minim dintre primul nod si celelalte noduri din graf, pentru a afla al {$k$}-lea drum minim se calculeaza toate primele $k - 1$ drumuri minime, in ordine. Un pas al algortimului consta in aflarea celul de-al {$k$}-lea drum minim cand primele $k$ sunt cunoscute. Drumul minim este folosit de mai multe ori in algoritm, pentru a intelege acest algoritm este necesara o anumita familiaritate cu algoritmul lui Dijkstra.\r\n\r\nDrumurile minime pana la $k-1$ sunt stocate compactate intr-un arbore de drumuri. Fiecarui nod din acel arbore ii corespunde un nod din graf, dar nu si invers, un nod din graf poate aparea de mai multe ori in arbore. Radacina arborelui corespunde nodului de start, iar toate frunzele arborelui corespund nodului de final, iar drumurile de la radacina catre frunze reprezinta fiecare cate un drum minim. Vezi in figura cum se compacteaza drumurile ({$1, 7, 4, 5$}), ({$1, 7, 3, 5$}), ({$1, 2, 4, 5$}) si ({$1, 2, 6, 4, 5$}). Drumurile sunt primele $4$ drumuri din graful desenat mai sus si luat drept exemplu.\r\n\r\n!Al-K-lea-drum-minim?kshortest_graph.png!\r\n!Al-K-lea-drum-minim?kshortest_tree.png!\r\n\r\nAl {$k$}-lea drum minim trebuie sa corespund pana intr-un anumit punct cu un drum aflat deja in arbore, chiar daca punctul acela este de fapt nodul de start. Pentru a gasi urmatorul drum minim, incercam sa \"deviem\" din fiecare nod din arbore. Un drum de deviatie pentru un anume nod $X$ este un drum identic cu drumul de la radacina pana la nodul {$X$}, care apoi continua (deviaza) pe cel mai scurt drum pana la destinatie care nu a fost inca luat in cosiderare. Spre exemplu pentru nodul $4$ din drumul ({$1, 2, 4, 5$}) putem sa deviem din $4$ prin ({$7, 3, 5$}), formand drumul ({$1, 2, 4, 7, 3, 5$}). Este intuitiv ca, la fiecare pas, pentru fiecare nod din arbore este interesant doar cel mai scurt drum de deviatie.\r\n\r\nAlgoritmul mentine o multime, eventual ca un heap, de deviatii. Se tine pentru fiecare drum de deviatie nodul din care deviaza si lungimea drumului. La fiecare pas extragem drumul de deviatie minim si reconstituim drumul. Sa zicem ca drumul scos din heap este ({$a{~1~} a{~2~} ... a{~d~}, a{~d+1~} ... a{~n~}$}), unde $a{~d~}$ este nodul de unde s-a facut deviatia. Introducem acest drum in arborele de drumuri, si pentru fiecare nod de la $a{~d~}$ la $a{~n-1~}$ calculam deviatia minima si o introducem in heap. Pentru restul nodurilor este evident ca deviatia minima nu se modifica.\r\n\r\nAlgoritmul odata inteles este relativ logic. Al {$k$}-lea drum minim trebuie sa coincida cu unul dintre cele $k-1$ drumuri deja existente pana intr-un anumit punct, dupa care \"ia un viraj\" nevizitat si continua cel mai scurt drumul inca neparcurs.\r\n\r\nDupa cum am zis mai sus, algoritmul are $2$ variante, daca este necesar ca drumurile sa fie elementare sau nu. Pentru cele $2$ variante se modifica modul in care se calculeaza deviatia minima dintr-un nod. Cazul cel mai simplu este atunci cand nu este necesar ca drumurile sa fie elementare. Pentru nodul $X$ din care trebuie sa deviem, vom lua cel mai scurt drum care inca nu este in arbore. Putem sa calculam de dinainte un arbore de drumuri inversat, de la toate nodurile la destinatie, si sa luam minimul de la nodurile adiacente care NU sunt printre copii in arbore. Pentru arborele din desen, daca ar fi sa deviem din ({$1, 2$}) am putea lua in considerare doar nodul {$1$}.\r\n\r\nDaca trebuie sa luam in considerare doar drumurile elementare, algoritmul simplu de mai sus da erori. Spre exemplu, daca ar fi sa deviem din ({$1, 7$}) in desen, drumul optim ar fi prin {$1$}, adica ({$1, 7, 1, 7, 4, 5$}), care drum nu este elementar. Pentru a genera doar drumurile elementare, este nevoie sa marcam nodurile de la radacina pana la deviatie ca \"ocupate\" si sa rulam un algoritm de drum minim pana la destinatie. Acest lucru creste foarte mult complexitatea in timp si in implementare.\r\n\r\nh2. Exemplu\r\n\r\nAlgoritmul prezentat este destul de complex, asa ca vom detalia rularea algoritmului pe graful din desen. Vom incerca sa calculam toate cele mai scurte $5$ drumuri elementare intre nodurile $1$ si {$5$}. Punem si conditia ca drumurile sa fie elementare (cazul mai dificil).\r\n\r\n* Primul drum minim este ({$1, 7, 4, 5$}), de lungime {$9$}.\r\n* Incercam sa deviem din {$1$}. Drumul minim de la $1$ la $5$ care nu trece imediat prin $7$ este ({$1, 2, 4, 5$}), cu cost {$10$}.\r\n* Incercam sa deviem din {$7$}. Drumul minim de la $7$ la $5$ care nu trece imediat prin $4$ este ({$7, 3, 5$}), cu cost {$10$}. Atentie, adaugam si costul de la $1$ la {$7$}.\r\n* Incercam sa deviem din {$4$}. Nu exista alt drum de la {$4$} la {$5$}. Ar putea fi drumul ({$4, 7, 3, 5$}), dar nu ar fi elementar, deoarece avem prefixul ({$1, 7$}), noduri pe care le-am marcat blocate.\r\n* Din $5$ nu are sens sa deviem, asa ca..\r\n* Al doilea drum minim este ({$1, 2, 4, 5$}), de lungime {$10$}.\r\n* Incercam sa deviem din {$1$}, dar nu exista drum de la $1$ la $5$ care sa nu o ia imediat nici prin $2$ si nici prin {$7$}.\r\n* Incercam sa deviem din {$2$}. Drumul minim de la $2$ la $5$ care nu trece imediat prin $4$ este ({$2, 6, 4, 5$}), cu cost {$10$}. Atentie, drumul trece prin {$4$}, dar nu imediat.\r\n* Incercam sa deviam din {$4$}. Drumul minim de la $4$ la $5$ care nu trece imediat prin $5$ este ({$4, 7, 3, 5$}), cu cost {$15$}. Acest drum nu a fost valid mai inainte, dar acum prefixul lui $4$ este ({$1, 2$}), asa ca drumul e valid.\r\n* Al treilea drum minim este ({$1, 7, 3, 5$}), tot de lungime {$10$}. Al doilea si al treilea drum minim sunt interschimbabile.\r\n* Acest drum a fost derivat din {$7$}, asa ca nu trebie incercam sa derivam din {$1$}.\r\n* Incercam sa deviem din {$7$}, dar nu exista drum de la $7$ la $5$ care sa nu treaca imediat nici prin $3$ nici prin {$4$}. Ar fi ({$7, 1, 2, 4, 5$}), dar avem $1$ ca prefix si marcat blocat. Astfel, evitam un drum neelementar.\r\n* Incercam sa deviem din {$3$}, fara succes(si fara explicatii kilometrice.).\r\n* Al patrulea drum minim este ({$1, 2, 6, 4, 5$}), de lungime {$11$}.\r\n* Incercam sa deviem din {$2$}, dar fara succes.\r\n* Incercam sa deviem din {$6$}, dar tot fara succes.\r\n* Incercam sa deviam din {$4$}. Drumul minim de la $4$ la $5$ care nu trece imediat prin $5$ este ({$4, 7, 3, 5$}), cu cost {$16$}. Noi am mai gasit odata acest drum, dar de data asta e cu un alt prefix, si alt cost. Drumul complet este ({$1, 2, 6, 4, 7, 3, 5$}), nu ({$1, 2, 4, 7, 3, 5$}).\r\n* Al cincilea drum minim este ({$1, 2, 4, 7, 3, 5$}), de lungime {$15$}.\r\n* Astfel se termina exemplul nostru. Puteti sa incercati, nu mai exista deviatii posibile. Al {$6$}-lea si ultimul drum este ({$1, 2, 6, 4, 7, 3, 5$}) , care se intample sa fie si cel mai lung drum, si hamiltonian.\r\n\r\nh2. Analiza complexitatii\r\n\r\nComplexitatea algoritmului este diferita in cele $2$ variante. In ambele cazuri putem considera la lugimea fiecarui drum este de {$O(n)$}, si ca heap-ul contine $O(k * n)$ valori. Luam cazul cel mai defavorabil, cu graf complet, si consideram ca un algoritm de drumuri minime necesita timp {$O(n * n)$}. Astfel, daca nu este nevoie ca drumurile sa fie elementare:\r\n\r\n* Precalculam drumurile de la orice nod la destinatie, {$O(n * n)$}.\r\n* La fiecare dintre cei k pasi.\r\n** Extragem din heap, $O(log(k * n))$\r\n** Reconstituim drumul, $O(n)$\r\n** Pentru fiecare dintre cele maxim $n$ noduri din drum:\r\n*** Vedem cel mai scurt drum de continuare, $O(n)$\r\n*** Il adaugam in heap, $O(log(k * n))$\r\n\r\nComplexitatea ajunge astfel la {$O(k * n * (n + log(k * n)))$}. Trebuie avut in vedere ca in general drumurile minime vor avea noduri relativ putine, asa ca algorimtul e mai rapid decat pare. Daca punem conditia ca drumurile determinate sa fie elementare, complexitatea creste:\r\n\r\n* La fiecare dintre cei $k$ pasi.\r\n** Extragem din heap, $O(log(k * n))$\r\n** Reconstituim drumul, $O(n * n)$ (il calculam iarasi)\r\n** Blocam nodurile de la start pana la nodul de deviatie, $O(n)$\r\n** Pentru fiecare dintre cele maxim $n$ noduri din drum:\r\n*** Vedem cel mai scurt drum de continuare, $O(n * n)$\r\n*** Il adaugam in heap, $O(log(k * n))$\r\n\r\nComplexitatea ajunge acum la {$O(k * n * (n * n + log(k * n)))$}, aproximativ {$O(k * n^3^)$}. Iarasi, algoritmul se comporta mai bine in practica decat pare in complexitate.\r\n\r\nh2. Observatii, indicatii, completari\r\n\r\nAlgoritmul poate fi mai incet sau mai rapid. Se poate folosi ceva mai simplu de implementat in loc de heap, sau un algoritm de drumuri minime mai evoluat. Daca va intrebati daca algoritmul poate fi folosit pentru a determina un drum hamiltonian, raspunsul este da, dar asta necesita determinarea tuturor drumurile lor dintre $2$ muchii, care este exponential in functie de {$n$}.\r\n\r\nDaca sunteti interesati si, bineinteles, daca \"va tine\", incercati se rezolvati problema \"SGU 145\":http://acm.sgu.ru/problem.php?contest=0&problem=145 , de unde a pornit de fapt acest articol. Se cere cazul cel dificil, cu drumuri elementare.\r\n\r\n',2044,'public',3695,NULL),('blog/oji-oni-2005','OJI & ONI 2005','2005-01-31 00:00:00','2005-01-31 00:00:00','h1. OJI & ONI 2005\r\n\r\nOlimpiada de Informatica, faza judeteana va avea loc pe data de 26-27 februarie 2005. Pe 26 februarie clasele 5, 6, 9 si 10 iar pe 27 februarie clasele 11, 12, 7 si 8.\r\n\r\nOlimpiada Nationala de Informatica de anul acesta se va desfasura in orasul Galati in perioada 25 martie-1 aprilie. Pentru mai multe detalii intrati vizitati \"olimpiada.info\":http://olimpiada.info si \"infogl.ro\":http://www.infogl.ro !\r\n\r\nMult succes!\r\n\r\n',1142,'protected',NULL,NULL),('template/preoni-2006','template/preoni-2006','2006-11-26 03:41:53','2006-11-27 16:01:52','==include(page=\"template/preoni-2006/header\")==\r\n\r\n(vmenu)*(section) \'preONI 2006\':preoni-2006\r\n* \'Informatii generale\':preoni-2006/info\r\n* \'Organizatori\':preoni-2006/comisie\r\n* \'Sponsori si premii\':preoni-2006/premii\r\n* \'Program\':preoni-2006/program\r\n* \'Regulament\':preoni-2006/regulament\r\n* \'Aparitii in presa\':preoni-2006/presa\r\n* \'Clasament\':preoni-2006/clasament\r\n*(section) Runde\r\n* \'Runda 1\':preoni-2006/runda-1\r\n* \'Runda 2\':preoni-2006/runda-2\r\n* \'Runda 3\':preoni-2006/runda-3\r\n* \'Runda 4\':preoni-2006/runda-4\r\n* \'Runda finala\':preoni-2006/finala\r\n\r\n\r\n',13,'protected',NULL,NULL),('template/preoni-2006/header','template/preoni-2006/header','2006-11-27 15:56:21','2006-11-27 16:08:54','table{margin: 0; width: 99%; background-image: url(/template/preoni-2006?action=download&file=hbk.gif); background-repeat: repeat-x; background-position: bottom left;}. |{border: 0px;}. !template/preoni-2006?hlogo.gif!:/preoni-2006 |{border: 0px; text-align: right; vertical-align: bottom}. !template/preoni-2006?ipdevel.gif!:http://www.ipdevel.ro/ !template/preoni-2006?oracle_ro.gif!:http://www.oracle.ro/ |\r\n',13,'protected',NULL,NULL),('blog/preoni-2005-runda-1','preONI, runda #1','2005-01-19 00:00:00','2005-01-19 00:00:00','h1. preONI 2005, runda #1\r\n\r\nNe mai despart doua luni de Olimpiada Nationala de Informatica (18-27 martie, Galati / Drobeta Turnu Severin)! Pentru a veni in sprijinul elevilor ce se pregatesc pentru aceasta competitie, echipa info.devNet organizeaza un concurs de pregatire (preONI) in 3 runde.\r\n\r\nDuminica, 23 ianuarie, ora 15:00 va avea loc prima runda preONI.\r\n\r\nFormatul concursului: 2 grupe (clasele IX-X, XI-XII), 3 probleme in fiecare grupa si un timp de lucru de 4h. Evaluarea va incepe la 15min dupa terminarea timpului de lucru si va putea fi urmarita in timp real la sectiunea \"statistici\".\r\n\r\nSpre deosebire de ultimul concurs de pregatire (din 14 nov 2004), cele 3 probleme propuse vor avea de aceasta data o dificultate gradata, fiind accesibile unui public mult mai larg.\r\n\r\nPropunatorii problemelor din runda #1 sunt:\r\n\r\n* Mircea Pasoi\r\n* Adrian Vladu\r\n* Cosmin Negruseri\r\n\r\nAsteptam intrebarile / sugestiile tale pe \'forum\':http://forum.infoarena.ro.\r\n\r\n*Mult succes!*',961,'protected',NULL,NULL),('moisil-by-net-2006/clasament-9','Clasament moisil2','2006-11-23 21:09:01','2006-11-24 18:24:57','h1. Clasament ==roundparam(round_id=\"moisil2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil2\")==',961,'protected',NULL,NULL),('preoji-2004','preOJI 2004','2006-11-23 21:08:49','2006-11-24 16:25:38','h1. preOJI 2004\r\n\r\n!>preoji-2004?logo!\r\n\r\nConcursul s-a desfasurat pe 22/2/2004 intre orele 9 si 12 dimineata.\r\n\r\nAu fost 2 grupe cu cate 2 probleme, in similar OJI.\r\n\r\nh2. Grupa mica, clasele 9-10 (\'Clasament\':preoji-2004/clasament-9-10)\r\n\r\n== Tasks(round_id=\"preoji1\" pager_style=\"none\")==\r\n\r\nh2. Grupa mare, clasele 11-12 (\'Clasament\':preoji-2004/clasament-11-12)\r\n\r\n== Tasks(round_id=\"preoji2\" pager_style=\"none\")==\r\n\r\n',1,'protected',NULL,NULL),('summer-challenge-2/clasament','Clasament summer2','2006-11-23 21:09:02','2006-11-24 17:47:15','h1. Clasament ==roundparam(round_id=\"summer2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer2\")==',961,'protected',NULL,NULL),('summer-challenge-3','Summer Challenge Trei','2006-11-23 21:09:02','2006-11-24 17:38:27','h1. Summer challenge 3\r\n\r\nConcursul s-a desfasurat pe 27 august 2006, ora 10:00 pe o durata de 5h. S-au propus spre rezolvare 3 probleme care au fost adaugate in \'arhiva\':arhiva.\r\n\r\nSolutiile problemelor le puteti gasi \"aici\":summer-challenge-3/solutii.\r\n\r\nh2. \'Clasament\':summer-challenge-3/clasament\r\n\r\n!>summer-challenge-3?logo.jpg!\r\n\r\n== Tasks(round_id=\"summer3\" pager_style=\"none\") ==',961,'protected',NULL,NULL),('warm-up-2006','Autumn WarmUp 2006','2006-11-23 21:09:03','2007-09-16 00:41:06','h1. Autumn WarmUp 2006\r\n\r\nConcursul s-a desfasurat incepand cu ora 14:00 pe data de 8 septembrie 2006.\r\n\r\nA fost un concurs facut de utilizatori pentru utilizatori, cu 5 subiecte cu grade diferite de dificultate, de la accesibil la dificil. Evaluatorul a fost pornit pe toata durata concursului.\r\n\r\nSolutiile problemelor le puteti gasi \"aici\":warm-up-2006/solutii.\r\n\r\nh2. Propunatori\r\n\r\n* Paul Dan Baltescu (PaulDB)\r\n* Vlad Berteanu (vladcyb1)\r\n* Vlad Dumitriu (vladut.forum)\r\n* Tiberiu Savin (devilkind)\r\n* Vlad Saveluc (VladS)\r\n\r\nh2. \'Clasament\':warm-up-2006/clasament\r\n\r\n!>warm-up-2006?logo.jpeg!\r\n\r\n== Tasks(round_id=\"autumn06\" pager_style=\"none\") ==\r\n',2028,'protected',NULL,NULL),('summer-challenge-3/clasament','Clasament summer3','2006-11-23 21:09:02','2006-11-24 17:47:06','h1. Clasament ==roundparam(round_id=\"summer3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer3\")==',961,'protected',NULL,NULL),('warm-up-2006/clasament','Clasament autumn06','2006-11-23 21:09:03','2006-11-24 18:25:27','h1. Clasament ==roundparam(round_id=\"autumn06\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"autumn06\")==',961,'protected',NULL,NULL),('happy-coding-2006/clasament','Clasament happy2006','2006-11-23 21:09:03','2006-11-24 17:49:02','h1. Clasament ==roundparam(round_id=\"happy2006\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"happy2006\")==',961,'protected',NULL,NULL),('blog/final-preoni-2005-runda-1','preONI runda #1 s-a incheiat','2005-01-27 00:00:00','2005-01-27 00:00:00','h1. preONI 2005 runda #1 s-a incheiat\r\n\r\npreONI runda #1 s-a incheiat, rezultatele finale au fost publicate iar problemele au fost mutate in arhiva.\r\n\r\nMircea Pasoi a publicat un \'articol\':preoni-2005/runda-1/solutii despre aceasta runda.\r\n\r\nAsteptam parerile si sugestiile voastre pe \'forum\':http://forum.infoarena.ro',961,'protected',NULL,NULL),('usaco-ian-2005-divizia-gold','Usaco ianuarie 2005, divizia GOLD','2005-03-03 00:00:00','2008-11-17 21:09:48','h1. Usaco ianuarie 2005, divizia GOLD\r\n\r\n(Categoria _Competitii_, autor(i) _Silviu Ganceanu, Mircea Pasoi_)\r\n\r\n\r\nAcest set de probleme a fost considerat unul dintre cele mai grele, daca nu cel mai greu, de pana acum. Problemele au fost intr-adevar dure cu atat mai mult cu cat timpul de lucru a fost mic (3 ore). In ciuda acestui fapt concurentii din Romania s-au comportat bine, concursul marcand primul succes de pe anul acesta al tarii noastre: locul 5 obtinut de Adrian Vladu.\r\n\r\nDesi rezultatele i-au determinat pe antrenorii americani sa considere setul de probleme cel mai greu de pana acum, pentru multi dintre elevii Romaniei problemele nu au fost in totalitate noi: cover a fost propusa (sub o forma un pic diferita) la CEOI, o varinta ceva mai blanda a problemei juice (cu limite mai mici) am putut vedea si in finala rundei .Campion de anul trecut iar ideea de rezolvare pentru naptime nu era noua (o problema din concursul $\"Stelele Informaticii\"$ de anul trecut se pare ca semana mult cu aceasta).\r\n\r\nCu toate aceastea problemele au fost deosebit de dificile necesitand concentrare maxima. Rezultatele elevilor din Romania s-au imbunatatit semnificativ fata de concursul precedent, acestia obtinand locuri mai bune. O parte din succesul acestora indraznesc sa o pun si pe seama faptului ca problema cea mai grea din concurs era cunoscuta la noi in tara. Avem astfel urmatorul clasament:\r\n\r\ntable. |_. 1. | Adrian Vladu | $958$ puncte |\r\n|_. 2. | Sorin Stancu-Mara | $703$ puncte |\r\n|_. 3. | Mircea Pasoi | $700$ puncte |\r\n|_. 4. | Andrei Teodorescu | $640$ puncte |\r\n|_. 5. | Dan-Ionut Fechete | $547$ puncte |\r\n|_. 6. | Adrian Diaconu | $502$ puncte |\r\n\r\nRestul concurentilor au obtinut punctaje frumoase dar mai mici de $400$ de puncte. Sunt de remarcat comportarile bune de pana acum ale lui Andrei Teodorescu care reuseste sa se \"tina\" de mult mai titratii elevi ai Romaniei care au deja in palmares cel putin o medalie internationala.\r\n\r\nSetul de probleme, impreuna cu testele si clasamentul, se gaseste in cadrul \"sectiunii download\":downloads. In continuare vom prezenta solutiile:\r\n\r\nh2(#cover). Cover\r\n\r\nProblema nu era foarte dificila, cu atat mai mult cu cat ideea de rezolvare a problemei guards din concursul CEOI 2002 era aceeasi: se construieste un graf bipartit avand intr-o multime barele orizontale (set maximal de pozitii de pe o linie din matrice in care avem noroi) si in cealalta multime barele verticale (definite analog dar pentru coloane). Intre doua noduri din acest graf bipartit vom avea muchie doar daca barele corespunzatoare lor au o celula comuna. Pentru exemplificare vom lucra cu exemplul din enunt:\r\n@*.*.@\r\n@.***@\r\n@***.@\r\n@..*.@\r\nIata cum vom construi prima multime a grafului bipartit (vom pune numarul nodului din graf corespunzator fiecarei celule):\r\n@1.2.@\r\n@.333@\r\n@444.@\r\n@..5.@\r\nA doua multime a grafului bipartit va arata astfel (nodurile vor fi numerotate incepand tot cu 1):\r\n@1.2.@\r\n@.324@\r\n@532.@\r\n@..2.@\r\nMuchiile din graful bipartit vor fi urmatoarele:\r\n$(1, 1) (2, 2) (3, 3) (3, 2) (3, 4) (4, 5) (4, 3) (4, 2) (5, 2)$\r\n\r\nAsadar fiecarei celule din harta terenului ii corespunde o singura muchie in acest graf bipartit. Avand construit graful trebuie sa aflam numarul minim de noduri selectate astfel incat orice muchie sa aiba cel putin un capat intre nodurile selectate (in literatura de specialitate aceasta problema se numeste {$Minimum Vertex Cover$}). Explicatia acestui lucru este simpla: orice muchie, fiind de fapt o celula, ea trebuie sa fie \"acoperita\" de cel putin un nod din graf (adica o placa orizontala sau verticala utilizata de FJ). Problema acesta este NP-completa pentru grafuri generale dar in cazul grafurilor bipartite ea se poate rezolva in timp polinomial. De asemenea s-a demonstrat ca numarul minim de noduri dintr-un astfel de set este egal cu cardinalul cuplajului maximal din graful bipartit. De aici nu mai e decat un pas spre solutia finala. Avem, astfel, urmatorii pasi in algoritmul de rezolvare a problemei:\r\n==code(cpp) |\r\n* PAS 1: Construirea grafului bipartit\r\n* PAS 2: Aflarea cuplajului maximal\r\n==\r\n\r\nPrimul pas este banal si consta din simple parcurgeri ale matricii. Pentru aflarea cuplajului maximal se poate afla utilizand un algoritm de aflarea a fluxului maxim in reteaua asociata grafului bipartit sau se poate algoritmul bazat pe gasirea succesiva a drumurilor in crestere in graf.\r\nComplexitatea finala a algoritmului va fi $O(N^2^*M^2^)$ deoarece in graful bipartit avem maxim $N*M$ muchii si vom $N*M$ noduri. Cum algoritmul pentru aflarea cuplajului maximal are complexitatea $V*E$ ({$V$} = numarul de noduri din graf, $E$ = numarul de muchii din graf) concluzia este evidenta.\r\nCa tema, recomand rezolvarea urmatoarelor probleme a caror solutie se bazeaza pe aflarea cuplajului maximal intr-un graf bipartit (in unele cazuri acest lucru insa nu este de ajuns):\r\n\r\n# $guards (CEOI 2002)$\r\n# $knigths (Baltica 2001)$ - in solutia oficiala a acestei probleme gasiti mai multe informatii despre notiunea de cuplaj maximal intr-un graf bipartit si problemele inrudite\r\n# Problema \"Paznici\":http://algoritmus.org/probleme/probleme_runda04.php din runda a patra a concursului Algoritmus (gasiti pe pagina si explicatia solutiei)\r\n# \"http://acm.timus.ru/problem.aspx?space=1&num=1106\":http://acm.timus.ru/problem.aspx?space=1&num=1106\r\n# \"http://acm.sgu.ru/problem.php?contest=0&problem=234\":http://acm.sgu.ru/problem.php?contest=0&problem=234\r\n# \"http://acm.sgu.ru/problem.php?contest=0&problem=210\":http://acm.sgu.ru/problem.php?contest=0&problem=210\r\n# \"http://acm.sgu.ru/problem.php?contest=0&problem=218\":http://acm.sgu.ru/problem.php?contest=0&problem=218\r\n# \"http://online-judge.uva.es/p/v107/10735.html\":http://online-judge.uva.es/p/v107/10735.html\r\n# \"http://online-judge.uva.es/p/v108/10804.html\":http://online-judge.uva.es/p/v108/10804.html\r\n# \"http://online-judge.uva.es/board/viewtopic.php?t=7462\":http://online-judge.uva.es/board/viewtopic.php?t=7462\r\n\r\nMentionez ca problema 8 m-a impresionat in mod placut fiind una dintre cele mai frumoase probleme pe care le-am intalnit in ultimele cateva luni.\r\n\r\nh2. Juice\r\n\r\nFie $A{~i,j~}$ inaltimea blocului aflat in pozitia $(i, j)$. Aflam inaltimea maxima la care poate urca nivelul sucului in fiecare celula. Daca notam aceasta inaltime cu B{~i,j~} solutia problemei va fi $suma( B{~i,j~} - A{~i,j~} )$.\r\n\r\nVom numi celula turn o celula $(i, j)$ care are propietatea ca $B{~i,j~} = A{~i,j~}$ (nu putem pune suc in ea pentru ca ar curge in afara matricei). Componenta conexa a unei celule turn $(i, j)$ este compusa din acele celule $(x, y)$ pentru care avem $B{~x,y~} = A{~i,j~}$. Definim inaltimea componentei conexe ca fiind inaltimea comuna a tuturor celulelor componente. Facem urmatoarele observatii utile in rezolvarea problemei:\r\n\r\n# Celulele de pe marginea matricei sunt celule turn\r\n# Celula $(x, y)$ devine celula turn daca este vecina unei celule $(i, j)$ ce face parte dintr-o componenta conexa si are propietatea ca $B{~i,j~} < A{~x,y~}$.\r\n\r\nIncet, incet se contureaza solutia problemei observand ca, pentru a declara o celula ca fiind turn, trebuie sa aflam componentele conexe ale celulelor turn mai joase decat ea. Acest lucru ne aduce la ideea de procesa aceste celule turn in ordinea inaltimii lor afland pentru fiecare componenta conexa corespunzatoare. In acelasi timp aflam si celule ce devin turn si sunt mai inalte. Pentru aceasta utilizam o coada de prioritati (un heap) in care pastram toate celule turn neprocesate inca ordonate descrescator dupa inaltime. Ajungem astfel la nimic altceva decat un algoritm de tip $FILL$ modificat corespunzator cerintelor acestei probleme. Iata o descriere a acestuia:\r\n\r\n==code(cpp) |\r\nPAS 1: Se introduc in coada de prioritati pozitiile de pe margine\r\nPAS 2: Cat timp heapul nu este gol:\r\n* se selecteaza celula turn cea mai joasa\r\n* se afla componenta conexa a acesteia\r\n* se introduc in coada de prioritati celulele vecine cu componenta conexa construita,\r\n  care au inaltimea mai mare decat inaltimea componentei\r\n==\r\n\r\nSe poate modifica usor algoritmul $FILL$ pentru a rezolva toate aceste cerinte. Complexitatea finala a algoritmului va fi $O(N^2^*logN)$ deoarece, in cazul cel mai defavorabil, toate celulele sunt turn (un exemplu este cand matricea este piramidala) si in consecinta toate celulele vor fi introduse si scoase din heap necesitand logN pentru fiecare operatie. Aflarea componentelor conexe va necesita $O(N^2^)$ timp in total fiindca o celula va fi selectata o singura data intr-o componenta conexa si va fi accesata de maxim 4 ori de algoritmul $FILL$. Ca detalii de implementare, programatorii in $C++$ pot folosi cozile de prioritati din $STL$ ({$priority_queue$} ce se gaseste in headerul {$&#0060;queue&#0062;$}) pentru a reduce din complexitatea implementarii. Totusi, trebuie acordata atentie utilizarii acestora deoarece este posibil ca sursa sa depasesca timpul de executie.\r\n\r\nh2. Naptime\r\n\r\nVom incerca sa rezolvam problema, ignorand la inceput faptul ca sirul este circular. Astfel, problema se transforma intr-una relativ usoara, abordabila cu programare dinamica. O prima incercare ar fi sa realizam o astfel de rezolvare: $A{~i,j~}$ = utilitatea de somn maxima care se poate obtine alegand $j$ perioade din primele $i$.\r\nRelatia de recurenta care se obtine este $A{~i,j~}=max(A{~i-k,j-k~}+suma U{~i-k+2~}...U{~i~})$ unde $U$ este vectorul de utilitati. Din pacate aceasta abordare are dezavantajul ca are complexitatea de timp $O(N*B^2^)$ si de memorie $O(N*B)$, neincadrandu-se nici in timp si nici in spatiu de memorie. Astfel, vom incerca sa imbunatatim aceasta dinamica modificand un pic semnificatia matricei A bazandu-ne pe faptul ca alegerea unei secvente continue de perioade aduca ca utilitate suma lor, mai putin prima perioada folosita:\r\n$A{~i,j,0~}$ = utilitatea de somn maxima care se poate obtine alegand $j$ perioade din primele $i$ si ultima perioada folosita sa fie $j$\r\n$A{~i,j,1~}$ = utilitatea de somn maxima care se poate obtine alegand $j$ perioade din primele $i$ si ultima perioada folosita sa *NU* fie $j$\r\nObtinem relatiile de recurenta:\r\n$A{~i,j,1~} = max({~i-1,j-1,1~} + U{~i~}, A{~i-1,j-1,0~})$\r\n$A{~i,j,0~} = max(A{~i-1,j,0~}, A{~i-1,j,1~})$\r\nAm redus complexitatea la $O(N*B)$ si memoria la $O(N)$, o imbunatatire substantiala.\r\n\r\nDeoarece sirul este circular, putem rezolva problema aplicand de $N$ ori dinamica de mai sus considerand sirul liniar si alegand fiecare pozitie ca fiind pozitia initiala, dar aceasta solutie depaseste cu mult limita de timp pe cazul cel mai defavorabil. Totusi, aceasta idee ar fi adus $10$ teste din cele $14$. Cu un mic truc, si anume alegerea aleatorie a pozitiei de start cat timp nu s-a depasit timpul de executie, s-ar mai fi putut obtine inca $2$ teste, in total $12$ (desi aceasta rezolvare nu obtine solutia optima pe testele foarte mari).\r\n\r\nPutem scapa de faptul ca sirul este circular mult mai elegant, aplicand de 2 ori dinamica: odata cum am zis mai sus (acoperind cazul cand pozitiile $N$ si $1$ nu sunt in aceeasi secventa de pozitii consecutive) si inca odata fortand sa existe o secventa de utilitati aleasa care contine pozitiile $N$ si $1$. A doua dinamica se poate obtine exact ca mai sus, aplicand aceeasi idee doar ca se initializeaza $A{~1,1,1~}=U{~1~}$ in loc de 0, si apoi pentru fiecare $i$ se verifica rezultatul curent cu $max(A{~i,B-(N-i),0~}, A{~i,B-(N-i),1~} + suma U{~i+2~}...U{~N~})$. Pentru a se incadara in limita de 0.3s trebuie acordata o mare grija la implementare, de exemplu, optimizand dinamica de mai sus de la $2*N$ memorie (ultimele doua linii din matricea $A$) la doar $N$ pastrand doar ultima linie si parcurgand indicele $j$ descrescator.',3146,'public',NULL,NULL),('blog/sarbatori-fericite','Sarbatori fericite!','2004-12-25 00:00:00','2004-12-25 00:00:00','Echipa infoarena ureaza Sarbatori fericite tuturor vizitatorilor si spor la treaba in continuare!\r\n',1142,'protected',NULL,NULL),('preoni-2005-runda-3','preONI, runda #3','2005-03-17 00:00:00','2006-11-25 15:35:37','h1. preONI 2005, runda #3\r\n\r\nSuntem bucurosi sa te anuntam ca runda #3 a concursului preONI se va desfasura Duminica, 20 martie la ora 10:00 - vezi mai jos informatii detaliate. Aceasta este ultima runda a concursului preONI 2005, runda ce va decide castigatorii premiilor oferite de Microsoft.\r\n\r\nClasamentul final se va calcula pe baza punctajelor obtinute in runda #2 si #3, punctajele din runda #1 fiind folosite doar pentru departajare in caz de egalitate.\r\n\r\nOricine este invitat sa participe, insa, eligibili pentru premii sunt doar acei concurenti din ciclul de invatamant pre-universitar care nu fac parte din echipa infoarena.\r\n\r\nh2. preONI 2005, runda #3\r\n\r\nDuminica, 20 marie, ora 10:00 va avea loc a treia (ultima) runda preONI. Ca de obicei, concursul se va desfasura online la adresa \'infoareana.devnet.ro\':http://infoarena.devnet.ro/ Formatul concursului: 2 grupe (clasele IX-X, XI-XII), 3 probleme in fiecare grupa si un timp de lucru de 4h. Evaluarea va incepe la 15min dupa terminarea timpului de lucru si va putea fi urmarita in timp real la sectiunea \"statistici\".\r\n\r\nPropunatorii problemelor din runda #2 sunt:\r\n\r\n* clasele IX - X: Mircea Pasoi, Adrian Vladu\r\n* clasele XI - XII: Silviu Ganceanu, Cosmin Negruseri, Mircea Pasoi\r\n\r\nAsteptam intrebarile / sugestiile tale pe \'forum\':http://info.devnet.ro/forum.php\r\n\r\nh2. Premii pentru preONI 2005\r\n\r\nSe vor acorda premii primilor 3 concurenti de la fiecare grupa. Premiile constau in carti valoroase de programare si sunt oferite de Microsoft Romania, prin intermediul programului \'\"Parteneri pentru Educatie\"\':http://www.microsoft.com/romania/educatie/pil/default.mspx.\r\n\r\n* Premiul 1\r\n** \"Arta programarii calculatoarelor\", vol. 3, Donald E. Knuth,\r\n** \"POO cu Visual Basic.Net si Visual C#.Net\", R. Reynolds Haertle\r\n* Premiul 2\r\n** \"Limbajul C Kernighan, Ritchie\", Brian Kernighan, Dennis Ritchie\r\n** \"POO cu Visual Basic.Net si Visual C#.Net\", R. Reynolds Haertle\r\n* Premiul 3\r\n** \"STL - Biblioteca programatorului\", Scott Meyers\r\n** \"POO cu Visual Basic.Net si Visual C#.Net\", R. Reynolds Haertle\r\n\r\nToate cartile sunt publicate de editura Teora.\r\n\r\nh2. ONI 2005\r\n\r\nAsa cum bine stii, ne mai despart 8 zile de ONI! Site-ul oficial al olimpiadei de informatica este \'http://olimpiada.info/\':http://olimpiada.info/ . Gasesti acolo tot ce doresti sa afli despre ONI, OJI si ONI by NET.\r\n\r\nDaca nu te-ai calificat la ONI, ai ocazia sa participi virtual la olimpiada! Afla mai multe la \'http://olimpiada.info/bynet/\':http://olimpiada.info/bynet/. Inscrierile au inceput deja!\r\n\r\nEchipa info.devNet iti ureaza mult succes!',1,'public',NULL,NULL),('blog/concursul-bitwise','Concursul BitWise','2005-02-07 00:00:00','2005-02-07 00:00:00','h1. Concursul BitWise\r\n\r\nConcurs de programare pe echipe. Dureaza 12 ore, are zece probleme, pot participa echipe de cate doi. Problemele se pot submita de maxim 10 ori, se evalueaza dupa submit, si sunt punctaje partiale. Mai multe detalii gasiti \"aici\":http://www.bitwise.iitkgp.ernet.in/ si va puteti inregistra pana in 7 februarie. Concursul se desfasoara pe data de 13 februarie. Inainte de inregistrare cititi FAQ si regulile concursului.\r\n',1142,'protected',NULL,NULL),('documentatie/pagina-de-fil','dsfdsfdsfdsina-de-fil','2006-11-26 22:14:35','2006-11-26 22:14:35','Scrie aici desfdsfdsfdsfds',1142,'public',NULL,NULL),('blog/iopc-international-online-programming-contest','IOPC - The International Online Programming Contest','2005-02-07 00:00:00','2005-02-07 00:00:00','h1. IOPC - The International Online Programming Contest\r\n\r\nConcurs de programare pe echipe, pare similar cu bitwise, diferenta fiind ca echipele sunt de cate trei, sunt 12 probleme si concursul dureaza 24 de ore. Limbajele de programare sunt C/C++/Java. Adresa este: \"[1]\":http://www.techkriti.org/competitions.php?eid=2&subid=2. Pentru a participa trebuie mai intai sa va inregistrati echipa. Concursul se desfasoara pe data de 20 Februarie.\r\n\r\n\r\n',1142,'protected',NULL,NULL),('preoni-2006/presa','Aparitii in presa, preONI 2006','2006-11-26 04:50:22','2006-11-27 14:42:55','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Aparitii in presa\r\n\r\n\'Comunicat de presa IP Devel\':http://www.ipdevel.ro/index.php?mid=137&rid=22&pg=268',1,'protected',NULL,NULL),('preoni-2006/runda-1','Runda 1, preONI 2006','2006-11-25 01:13:10','2008-02-02 15:09:18','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Runda 1\r\n\r\nConcursul s-a desfasurat sambata, 19 noiembrie, la ora 09:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nh2. Comisii\r\n\r\nh3. Stiintific\r\n\r\n* clasa a 9-a (si gimnaziu)\r\n** Tiberiu Florea\r\n** Silviu Ganceanu \r\n* clasa a 10-a\r\n** Cosmin Negruseri\r\n** Adrian Diaconu \r\n* clasele 11-12\r\n** Mircea Pasoi\r\n** Daniel Pasaila \r\n\r\nh3. Organizatoric\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* Cristian Strat\r\n* Crestez Leonard \r\n\r\nh2. Solutii\r\n\r\nSolutiile problemelor le puteti gasi \"aici\":preoni-2006/runda-1/solutii\r\n\r\nh2. Clasa a 9-a si gimnaziu (\'Clasament\':preoni-2006/runda-1/clasament-9)\r\n\r\n!>preoni-2006/runda-1?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni61a\" pager_style=\"none\") ==\r\n\r\nh2. Clasa a 10-a(\'Clasament\':preoni-2006/runda-1/clasament-10)\r\n\r\n!>preoni-2006/runda-1?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni61b\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2006/runda-1/clasament-11-12)\r\n\r\n!>preoni-2006/runda-1?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni61c\" pager_style=\"none\") ==\r\n\r\n==include(page=\"template/preoni-2006/footer\")==\r\n',1,'protected',NULL,NULL),('blog/preoni-2005-runda-2','preONI, runda #2','2005-02-21 00:00:00','2005-02-21 00:00:00','h1. preONI 2005, runda #2\r\n\r\nAvem doua vesti bune pentru tine:\r\n\r\n# runda #2 a concursului preONI se va desfasura Miercuri, 23 februarie ora 16:00 - vezi mai jos informatii detaliate.\r\n# Microsoft Romania ofera PREMII SURPRIZA (yay!) primilor trei concurenti de la fiecare grupa!\r\n\r\nDorim sa multumim mult celor care ne-au ajutat in aceasta directie:\r\n\r\n* Microsoft Romania, programul \'\"Parteneri pentru Educatie\"\':http://www.microsoft.com/romania/educatie/pil/default.mspx\r\n* prof. Emil Onea\r\n* Octavian Costache\r\n\r\nNu iti face griji daca nu ai participat la prima runda preONI. Clasamentul final se va calcula pe baza punctajelor obtinute in runda #2 si #3, punctajele din runda #1 fiind folosite doar pentru departajare in caz de egalitate.\r\n\r\nOricine este invitat sa participe, insa, eligibili pentru premii sunt doar acei concurenti din ciclul de invatamant pre-universitar care nu fac parte din echipa infoarena.\r\n\r\nMiercuri, 23 februarie, ora 16:00 va avea loc a doua runda preONI. Formatul concursului: 2 grupe (clasele IX-X, XI-XII), 3 probleme in fiecare grupa si un timp de lucru de 4h. Evaluarea va incepe la 15min dupa terminarea timpului de lucru si va putea fi urmarita in timp real la sectiunea \"statistici\".\r\n\r\nPropunatorii problemelor din runda #2 sunt:\r\n\r\n* clasele IX - X: Dan Popovici, Cosmin Negruseri\r\n* clasele XI - XII: Silviu Ganceanu, Adrian Vladu, Dan Fechete\r\n\r\nNoteaza-ti! :)\r\nMiercuri la ora 16:00 ai concurs cu premii Microsoft pe infoarena!\r\n\r\nPana la inceperea concursului, te invitam sa citesti ultimele articole publicate pe portalul info.devNet. Printre acestea, se numara:\r\n\r\n* Skiplists, Stancu Mara Sorin\r\n* preONI 2005 runda #1 - solutii, Mircea Pasoi\r\n\r\nAsa cum bine stii, mai e aproape o saptamana pana la\r\nOlimpiada Judeteana de Informatica (26/27 februarie)!\r\n\r\nIti uram mult succes!\r\n\r\nAsteptam intrebarile / sugestiile tale pe \'forum\':http://forum.infoarena.ro/',1,'protected',NULL,NULL),('summer-challenge-unu/clasament','Clasament Summer Challenge Unu','2006-11-23 00:53:44','2006-11-24 17:47:39','h1. Clasament \'Summer Challenge Unu\':summer-challenge-unu\r\n\r\n==Rankings(rounds=\"summer06\")==',961,'protected',NULL,NULL),('blog/final-preoni-2005-runda-2','preONI 2005, runda #2 s-a incheiat','2005-02-26 00:00:00','2005-02-26 00:00:00','h1. preONI 2005, runda #2 s-a incheiat\r\n\r\nRunda #2 a concursului preONI s-a incheiat. Rezultatele sunt disponibile in sectiunea \"statistici\" a site-ului si problemele au fost mutate in arhiva.\r\n\r\nAutorii problemelor au scris un \'articol\':preoni-2005/runda-2/solutii despre aceasta runda - rezultate si idei de rezolvare.\r\n\r\nFelicitari tuturor participantilor!\r\n\r\nPana la urmatoarea runda, *BAFTA LA OJI*!',961,'protected',NULL,NULL),('preoni-2006/premii','Sponsori si premii, preONI 2006','2006-11-25 18:08:17','2006-11-27 16:14:16','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Sponsori si premii\r\n\r\nh2. Sponsori\r\n\r\n*Mesaj din partea IP Devel*\r\n\r\nLa IP Devel incurajam elevii si studentii talentati in dezvoltarea de solutii informatice. Incurajam talentul si il ajutam prin programe de dezvoltare special concepute.\r\n\r\nStudentii pot astfel sa isi continue studiile si in acelasi timp sa se formeaze profesional, implicindu-se in proiecte interesante, intr-un mediu de lucru tinar si dinamic.\r\n\r\nMai multe detalii puteti vizualiza pe pagina noastra unde va si puteti inregistra pentru a lua parte la un astfel de program.\r\n\r\nh2. Premii\r\n\r\nConcursul *preONI* este recunoscut ca o initiativa indrazneata a catorva elevi si studenti pasionati de informatica, menita sa ii ajute pe cei la fel de pasionati ca si ei in pregatirea pentru performnta. Succesul acestei initiative este dovedit prin complexitatea concursului de la an la an, astfel incat anul acesta, datorita generozitatii sponsorilor, echipa infoarena ofera concurentilor ceva mai mult decat satisfactia rezolvarii problemelor.\r\n\r\nPentru fiecare dintre cele trei grupe, primii 10 elevi din clasament in urma desfasurarilor probelor online vor fi premiati cu o diploma de finalist al concursului *preONI 2006* si o \"tabara\":preoni-2006/finala de pregatire cu cazare si masa asigurate.\r\n\r\nCei 30 de elevi vor avea sansa sa interactioneze cu membrii echipei infoarena si cu ceilalti membrii ai comunitatii infoarena si sa invete de la si impreuna cu acestia. Tabara va fi de asenemea un prilej de a ii rasplati pe cei mai buni dintre cei mai buni. Acest lucru se va face prin organizarea unei runde finale, asemanatoare cu rundele online. Punctajele din acesta runda vor fi independente de cele acumulate la rundele online, iar primii 3 clasati vor avea parte de urmatoarele premii:\r\n\r\n|_. Grupa|_. Locul I|_. Locul II|_. Locul III|\r\n|_. Clasa a IX-a(si gimnaziu)|300 RON|200 RON|100 RON|\r\n|_. Clasa a X-a|300 RON|200 RON|100 RON|\r\n|_. Clasele XI -XII|300 RON|200 RON|100 RON|\r\n\r\n==include(page=\"template/preoni-2006/footer\")==',13,'public',NULL,NULL),('template/preoni-2006/rankings','template/preoni-2006/rankings','2006-11-27 15:54:36','2006-12-01 18:13:27','==include(page=\"template/preoni-2006/header\")==\r\n\r\np{font-weight: bold}. &larr; \"preONI 2006 Homepage\":preoni-2006\r\n\r\nh1. Clasament preONI 2006, rundele de online de calificare\r\n\r\np={font-weight: bold}. \"Clasa a IX-a si gimnaziu\":preoni-2006/clasament-9 | \"Clasa a X-a \":preoni-2006/clasament-10 | \"Clasele XI-XII\":preoni-2006/clasament-11-12\r\n\r\n',13,'protected',NULL,NULL),('blog/aparitie-editoriala','Aparitie editoriala','2005-03-17 00:00:00','2005-03-17 00:00:00','h1. Aparitie editoriala\r\n\r\nEchipa devNet va recomanda cartea \"Fundamentele programarii, clasa a IX-a\" , autori \"Dana Lica\":mailto:danal182001@yahoo.com si \"Mircea Pasoi\":mailto:bogdanpasoi@yahoo.com. Culegerea respecta programa scolara a claselor a IX-a de informatica si isi propune sa reprezinte un instrument util atat in munca de initiere in programare cat si in cea de performanta, cuprinzand peste 100 de probleme pentru concursuri si olimpiade.\r\n\r\nPentru detalii suplimentare privind cartea puteti contacta pe oricare dintre autori (faceti click pe nume pentru adresa de mail).\r\n\r\nh2. Cuprins\r\n\r\n# Capitol 1 \r\nProgramarea structurata si instructiuni in limbajul de programare Pascal/C/C ++\r\n## Structura liniara si alternativa - Instructiunea de atribuire si conditionala\r\n### Teste cu alegere multipla si duala\r\n### Teste cu itemi semiobiectivi\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Structuri repetitive - instructiuni repetitive\r\n### Teste cu alegere multipla si duala\r\n### Teste cu itemi semiobiectivi\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Probleme de concurs ce proceseaza date simple\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n# Capitol 2 \r\nTipuri de date structurate\r\n## Tabloul unidimensional\r\n### Teste cu alegere multipla si duala\r\n### Teste cu itemi semiobiectivi\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Tabloul bidimensional\r\n### Teste cu alegere multipla si duala\r\n### Teste cu itemi semiobiectivi\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Fisiere text\r\n### Teste cu alegere multipla si duala\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Probleme de concurs ce proceseaza date structurate\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Indicatii si raspunsuri\r\n',961,'protected',NULL,NULL),('blog/concurs-microsoft-you-can-make-a-difference','Concurs Microsoft: You Can Make a Difference','2005-03-19 00:00:00','2005-03-19 00:00:00','h1. Concurs Microsoft: You Can Make a Difference\r\n\r\n\"You Can Make a Difference\" este o competitie pentru elevii de liceu care propun proiecte de aplicatii software adresate entitatilor cu obiect de activitate caritabil. Microsoft pune la dispozitia celor interesati software-ul necesar si suportul tehnic (conectare cu dezvoltatori Microsoft).\r\n\r\nBanii acordati prin acest concurs vor fi folositi in trei directii:\r\n\r\n* bursa pentru elevul/eleva premiat(a).\r\n* resurse financiare pentru implementarea proiectului.\r\n* actualizare, din punct de vedere tehnologic, a scolii din care face parte elevul/eleva premiat(a).\r\n\r\nDead line de inscriere este 30 aprilie. Mai multe informatii gasiti la:\r\n\r\n* \'http://ro.theSpoke.net\':http://ro.theSpoke.net\r\n* \'http://ro.thespoke.net/ycmd/info.aspx\':http://ro.thespoke.net/ycmd/info.aspx\r\n* \'http://ro.thespoke.net/BlogReader/SingleEntry.aspx?ID=1455\':http://ro.thespoke.net/BlogReader/SingleEntry.aspx?ID=1455',1142,'protected',NULL,NULL),('preoni-2005/runda-3/solutii','preONI 2005 runda #3 - solutii','2005-03-20 00:00:00','2008-08-13 13:20:40','h1. preONI 2005 runda #3 - solutii\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa devNet_)\r\n\r\nArticolul contine ideile de rezolvare ale problemelor propuse la ultima runda a concursului preONI ce s-a desfasurat pe data de 20 martie 2005, cat si comentarii legate de concurs. Si de aceasta data numarul de participanti a fost impresionat, cu siguranta datorita faptului ca in numai 5 zile incepe ONI!\r\n\r\nSetul de probleme a fost mai greu de data aceasta, special pentru a testa concurentii cu probleme cat mai asemanatoare cu stilul ONI. Speram ca fiecare participant a invatat cate ceva in urma acestui concurs si asteptam pareri si sugestii pentru viitor pe \"forum\":http://http://forum.infoarena.ro/.\r\n\r\nh2. Clasele 9-10\r\n\r\nh3. Clasament\r\n\r\n==Rankings(rounds=\"preoni53a\" display_entries=\"6\" pager_style=\"none\")==\r\n\r\nh3. Barman\r\n\r\n(solutie corecta oferita de ==user(user=\"spatarel\" type=\"tiny\")==, 20 noiembrie 2005)\r\n\r\nMetoda folosita este una brute-force si se bazeaza pe cateva observatii. Pentru a determina solutia optima sortam sirul valorilor bauturilor si ii generam toate permutarile circulare in vectorul obt. De aici, problema noastra ramane transformarea de cost minim a vectorului initial a in vectorul obt folosind operatiile permise. Dintre toate permutarile circulare, evident o vom alege pe cea care cere un cost minim al operatiilor. In primul rand se observa ca nu are nici un rost sa deranjam camerele care au bautura ceruta ({$a{~i~} = obt{~i~}$}), deci pe Paftenie nu il vor preocupa acestea. In al doilea rand este de remarcat ca ar fi inutil ca Paftenie sa deplaseze mai mult de un pahar intre doua camere deoarece am considera un caz redundant. De ce? Ar fi libere numai camerele $c{~1~}$ si {$c{~2~}$}, din care provin cele doua pahare de pe tava. Cu doua pahare pe tava ar putea sa mearga intr-o camera $c{~3~}$ diferita de $c{~1~}$ si {$c{~2~}$}, dar ar fi inutil, caci nici pe tava nici in camera nu mai poate depozita vreun pahar.\r\n\r\nAstfel, problema se reduce la a gasi, pentru fiecare bautura care nu se afla pe locul ei, o pozitie optima, pe care daca o asezam, vom obtine un cost global minim. Pentru simplitate, in continuare voi numi \"cuplaj\" mutarea unei bauturi pe o alta masa. Se poate oberva ca problema se poate imparti in mai multe sub-probleme independente: fiecare sub-problema va calcula cuplajul optim pentru toate bauturile de aceeasi valoare. Problemele sunt independente, deoarece pentru a pastra solutia optima globala, trebuie sa cuplam o bautura cu o masa pe care trebuie plasata acelasi tip de bautura.\r\n\r\nO metoda ar fi greedy: pentru fiecare bautura care nu e la locul ei, cautam cea mai apropiata masa pe care se poate pune - insa aceasta metoda este gresita.\r\n\r\nO alta metoda este cuplajul intr-un graf bipatit. Desi aceasta rezolvare este corecta, nu se incadreaza in timpul de executie. Deoarece trebuie efectuate $N$ cuplaje cu cate $2*N$ noduri fiecare, vom obtine o complexitate de {$O(N^5^)$}, supraestimata. Este posibil, totusi, ca in urma unor optimizari puternice, si aceasta metoda sa obtina punctaj mare.\r\n\r\nTotusi, mai exista si o alta metoda mult mai simpla si mai rapida, care se bazeaza pe cateva observatii suplimentare: datorita sortarii pe care am efecutat-o la inceputul algoritmului si a permutarilor circulare, mesele pe care trebuie plasata aceeasi bautura, sunt plasate fie secvential, fie in doua secvente, de la $1$ la $k$ si de la $l$ la {$N$}. De asemenea, deoarece am eliminat cazurile in care {$a{~i~} = obt{~i~}$}, cele doua cazuri, fara a pirde dingeneralitate, se reduc la unul singur: in intervalul $1$ - $k$ exista numai bauturi care trebuie cuplate; in intervalul $k+1$ - $l$ exista numai mese care trebuie cuplate; in intervalul $l+1$ - $N$ exista numai bauturi care trebuie cuplate. (Al doilea caz este simetric, si deoarece mesele pot fi privite ca bauturi, si invers, putem reduce al doilea caz la primmul.)\r\n\r\nProblema se rezolva partitionand multimea meselor in doua secvente: mesele din prima secventa se vor cupla cu bauturile din intervalul $1$ - {$k$}, iar mesele din a doua secventa cu bauturile din intervalul $l+1$ - {$N$}. Se poate observa ca oricum s-ar realiza cele doua cuplaje, costul golbal va fi acelasi. In plus, orice alt cuplaj global care nu tine cont de aceasta impartire va obtine un const global mai mare. Astfel, se garanteaza ca aceasta metoda va calcula corect costul minim global.\r\n\r\nAlgoritmul care impleneteaza acest cuplaj este foarte simplu: pentru fiecare bautura care nu se alfa la locul ei ({$a{~i~} = obt{~i~}$}), se cauta prima masa necuplata pe care se poate plasa bautura.\r\n\r\nh3. Cifre\r\n\r\nPentru a afla probabilitatea ceruta trebuie sa aflat cate numere exista in intervalul [{$A..B$}] cu cel putin $K$ cifre de {$C$}. Pentru asta vom construi o functia $f(x)$ care va returna cate numere sunt in intervalul [{$0..x-1$}] care au cel putin $K$ cifre de {$C$}. Astfel rezultatul va fi {$f(B+1)-f(A)$}. Functia $f(x)$ va rula in complexitate $O(lg x)$ parcurgand numarul $x$ cifra cu cifra. Ca sa realizam acest lucru avem nevoie de urmatoarele informatii:\r\n$cnt(i, j)$ = cate numere intre $0$ si $10^i^-1$ contin $j$ cifre de $C$ (vom considera ca numerele pot avea {$0$}-uri in fata, de exemplu: $0003$ are $3$ cifre de {$0$})\r\nAcest numar se poate calcula fie printr-o formula matematica folosind combinari sau cu o relatia de recurenta (independenta de variabila {$C$}):\r\n\r\n* $cnt(i, j) = 9 * cnt(i-1, j) + cnt(i-1, j-1)$\r\n\r\nDe asemenea mai avem nevoie de urmatoarele informatii:\r\n$cnt0(i, j)$ = cate numere care nu au {$0$}-uri in fata intre $0$ si $10^i^-1$ contin $j$ cifre de {$C$}. Relatia de recurenta va fi in functie de {$C$}:\r\n\r\n* daca $C=0$ atunci $cnt0(i, j) = cnt0(i-1, j) + 9 * cnt(i-1, j)$\r\n* altfel $cnt0(i, j) = cnt0(i-1, j) + 8 * cnt(i-1, j) + cnt(i-1, j-1)$\r\n\r\nCele doua matrici au marimi $lgB*K$ deci construirea lor va avea complexitate {$O(lg B*K)$}. Odata disponibile aceste informatii se poate realiza destul de usor functia {$f(x)$}. Nu voi prezenta aici toate detaliile deoarecere apar mai multe cazuri (in special cand {$C = 0$}), lasand ca exercitiu pentru cititor. \r\n\r\nO alta rezolvare posibila ar fi calcularea functiei $f(x)$ in $O(2^lg10(x)^*lg10(x))$ astfel: pe fiecare pozitie intre $0$ si $lg10(x)$ avem doua variante, fie punem cifra {$C$}, fie alta cifra. Pentru fiecare astfel de configuratie cu cel putin $K$ cifre de $C$ se poate determina dintr-o parcurgere cate numere exista $< x$ care au cifre de $C$ in pozitiile respective.\r\n\r\nh3. Farfurii\r\n\r\nProblema cere construirea unei permutari de lungime $N$ cu $K$ inversiuni, minima lexicografic. O prima rezolvare de complexitate $O(N^2^)$ ar fi construirea permutarii element cu element. Cu cat un element este mai mare pe o anumita pozitie cu atat formeaza mai multe inversiuni, astfel ca incercam sa punem pe fiecare pozitie un element cat mai mic astfel: pe pozitia {$i$}, daca $K &le; (N-i)*(N-i-1)/2$ putem pune cel mai mic element disponibil (pentru ca in bucata de $N-i$ ramasa putem construi cel putin {$(N-i)&#0042;(N-i-1)/2$} inversiuni), altfel punem al {$K-(N-i)&#0042;(N-i-1)/2$} element disponibil. Aceasta modalitate de constructie garanteaza ca permutarea este minima lexicografic. O implementare directa, cum am zis, are complexitate $O(N^2)$ si ia {$40-60p$}. Pentru $100p$ se poate folosi un arbore de intervale (ca la problema \"concurs\":http://campion.edu.ro/problems.php?mode=view_round&group_number=3&year=2004&round_number=9 de la .campion 2004, runda 9) reducand complexitatea la {$O(N*lg N)$}. O asemenea solutie, desi ia {$100p$}, necesita cunostiinte de structuri de date avansate care depasesc nivelul de cunostiinte general al unui concurent pentru clasele {$9-10$}. O rezolvare $O(N)$ mult mai simpla se bazeaza pe urmatoarea observatie:\r\nO permutare de lungime $i$ are cel mult $i*(i-1)/2$ inversiuni cand numerele sunt in ordine descrescatoare.\r\nAstfel, daca $K$ e de forma $M*(M-1)/2$ permutarea minima lexicografic cu $K$ inversiuni va fi:\r\n\r\n$1, 2, 3, ... N-M, N, N-1, N-2, ... N-M+1$\r\n\r\nCele $K$ inversiuni apar in ultimele $M$ elemente. Daca in aceasta permutare mutam un element $N-x$ imediat inaintea lui $N$ numarul de inversiuni scade cu {$x$}. Astfel, daca $K>M*(M-1)/2$ construim permutarea\r\n\r\n$1, 2, 3, ... N-M-1, N, N-1, N-2, ... N-M$\r\n\r\n(care are $(M+1)*M/2$ inversiuni) si mutam elementul {$N-((M+1)*M/2-K$}) imediat inaintea lui {$N$}, astfel scadem numarul de inversiuni la {$K$}. Este evident ca permutarea astfel construita este minima lexicografic. Algoritmul descris are complexitate {$O(N)$}.\r\n\r\nh2. Clasele 11-12\r\n\r\nh3. Clasament\r\n\r\n==Rankings(rounds=\"preoni53b\" display_entries=\"5\" pager_style=\"none\")==\r\n\r\nSetul de probleme, mai greu de data aceasta, se pare ca a pus in dificultate majoritatea concurentilor. Desi problemele Critice si Poligon nu erau foarte dificile in faza de concepere a algoritmului se pare ca implementarea a fost cea care i-a speriat pe multi dintre participanti. \r\n\r\nh3. Critice\r\n\r\nProblema este o aplicatie a algoritmului de aflare a fluxului maxim dintr-o retea. Se construieste o retea, nodurile fiind adaposturile iar capacitatile muchiilor fiind egale cu rezistentele tunelurilor. Prima solutie, care trece $~ 50%$ din teste, este urmatoarea:\r\n\r\n# Se calculeaza fluxul maxim in reteau construita\r\n# Pentru fiecare muchie (separat) se creste capacitatea ei cu o unitate si se mai ruleaza inca o data algoritmul de flux maximi. Daca fluxul maxim a crescut atunci muchia este critica.\r\n\r\nSe observa ca acest algoritm are o complexitate considerabila si trebuie sa ne gandim la ceva mai bun. Primul lucru inteligent pe care il putem observa este ca muchiile critice sunt muchiile care, dupa ce am rulat odata algoritmul de flux maxim, sunt saturate (am folosit toata capacitatea ei intr-o directie sau cealalta). Totusi nu toate muchiile saturate sunt si critice. Pentru a fi mai exacti, muchiile critice sunt acele muchii saturate care au propietatea ca de la sursa retelei (nodul {$1$}) este drum in graful rezidual (adica graful care ne ramane daca eliminam muchiile saturate) la unul din capetele ei si respectiv de la destinatie (nodul {$N$}) la celalalt capat. Asadar se contureaza algoritmul:\r\n\r\n# Se ruleaza odata algoritmul de flux maxim\r\n# Cu ajutorul a doua parcurgeri a grafului rezidual stabilim pentru fiecare muchie critica daca propietatea este adevarata\r\n\r\nComplexitatea (teoretica) va fi $O(M^2^*N + M)$ dar este supraestimata algoritmul de flux ruland mult mai rapid.\r\n\r\nh3. Ferma\r\n\r\nLa prima vedere, problema pare abordabila cu programare dinamica. O simpla rezolvare care nu tine cont de faptul ca sirul este circular este urmatoarea: $A{~i,j~}$ = productivitatea maxima pentru a face $i$ strangeri din primele $j$ sectoare; evident raspunsul va fi {$A(K, N)$}. Relatia de recurenta:\r\n\r\n* $A{~i,j~}$ = $max (A{~i,j-1~}, A{~i-1,k~} + suma (P{~k~},P{~k+1~}..P{~j~})$ pentru fiecare {$k<j$}, iar $P$ reprezinta vectorul de productivitati.\r\n\r\nO astfel de implementare are complexitate $O(N^2^*K)$ si nu se va incadra in timp. Fie {$S{~i~} = P{~1~}&#0043;P{~2~}&#0043;...&#0043;P{~i~}$}, atunci putem rescrie relatia de recurenta astfel:\r\n\r\n* {$A{~i,j~} = max(A{~i,j-1~}, A{~i-1,k~} + S{~j~} - S{~k~})$}, pentru fiecare $k<j$\r\n\r\nAl doilea termen este de forma $A{~i-1,k~} - S{~k~}$ (termen independent de {$j$}) + {$S{~j~}$}. Astfel din linia $i-1$ a matricii de dinamica pentru fiecare $j$ ne trebuie valoarea maxima $A{~i-1,k~}-S{~k~}$ cu {$k<j$}. O prima idee ar fi ca pe masura ce construim linia i sa inseram elementele din linia $i-1$ intr-un max-heap astfel reducand complexitatea la {$O(N*lgN*K)$}.\r\n\r\nCei care au rezolvat probleme precum \"secventa\":problema/secventa de pe infoarena, \"trans\":problema/trans de la barajul de la ONI 2004 sau divide de la USACO Ianuarie 2005 vor realiza imediat ca putem reduce complexitatea la $O(N*K)$ folosind structura necesara in rezolvarea acelor probleme si anume o coada (in literatura de specialitate se intalneste ca \"deque with heap order\"). Aceasta structura a mai fost tratata si in solutiilor problemelor prezentate mai sus, deci nu voi intra in detalii. Este evident ca un algoritm de complexitate $O(N*K)$ se incadreaza in timp, dar mai apare in calcul faptul ca sirul este circular. Un algoritm $O(N*K)$ care nu trateaza acest lucru ia $40$ de puncte. O prima idee ar fi sa aplicam acelasi algoritm pe fiecare permutare circulara dar se ridica complexitatea iar la {$O(N^2^*K)$}. Aceasta abordare ar trebui sa obtina intre $50$ si $60$ de puncte. Putem trata circularitatea sirului tot in $O(N*K)$ incercand sa obtinem o secventa care contine elemente $N$ si {$1$}. Putem realiza acest lucru astfel:\r\n\r\n* dupa ce realizam prima data dinamica, reinitializam linia $1$ astfel $A{~1,i~} = S{~i~}$\r\n* aplicam din nou dinamica -> de data aceasta algoritmul va fi obligat sa intoarca rezultate care contin neaparat elementul $1$ intr-o secventa din cauza initializarii\r\n* pentru fiecare pozitie $i &le; N$ comparam rezultatul $A{~i,K~}+S{~N~}-S{~i~}$ (adaugam la secventa care il contine pe $1$ o bucata care il contine pe {$N$}) cu cel mai bun obtinut\r\n\r\nAstfel, problema este rezolvabila in complexitate {$O(N*K)$}.\r\n\r\nh3. Poligon\r\n\r\nProblema cere sa determinam cate puncte din cele $M$ sunt in interiorul poligonului. O abordare imediata a acestei probleme ar fi sa determinam pentru fiecare punct in $O(N)$ daca este sau nu in interiorul poligonului. Exista mai multe moduri de a rezolva acest lucru. Un mod ar fi sa ducem o semidreapta pornind din punctul nostru si sa vedem de cate ori intersecteaza laturile poligonului: daca intersecteaza poligonul de un numar par de ori atunci inseamna ca punctul este in exterior, iar daca ea intersecteaza de un numar impar de ori laturile poligonului inseamna ca punctul este in interior. O alta modalitate: calculam suma unghiurilor pe care le fac extremele laturilor cu punctul nostru (unghiurile sunt luate pozitive sau negative dupa cum cele $3$ puncte ce formeaza unghiul sunt in sens trigonometric sau orar), daca suma unghiurilor pentru toate laturile e $0$ atunci punctul e in exteriorul poligonului, iar daca suma unghiurilor e $2*Pi$ atunci punctul e in interiorul poligonului, pentru mai multe detalii puteti\r\nsa va uitati pe urmatoarele pagini: \"[1]\":http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html \"[2]\":http://softsurfer.com/Archive/algorithm_0103/algorithm_0103.htm\r\n\r\nDimensiunile datelor de intrare ne sugereaza ca trebuie sa acceleram determinarea pozitiei punctelor fata de poligon. Daca poligonul ar fi convex, este usor sa facem acest test in {$O(log N)$}: consideram un varf al poligonului si semidrepte ce pleaca din el spre celelalte varfuri, cu cautare binara gasim in ce sector determinat de doua semidrepte intra punctul pentru care vrem sa determinam incluziunea in poligon, dupa ce gasim sectorul testul de incluziune se reduce la determinarea incluziunii intr-un triunghi. Aceasta metoda eleganta si simpla merge pentru poligon convex, dar pentru unul oarecare trebuie sa gasim o alta abordare.\r\n\r\nPentru poligoane concave, mergand pe aceeasi idee, impartirea in zone pentru care este mai usor sa determinam incluziunea se va face un pic diferit. Sortam coordonatele $x$ ale punctelor poligonului si ducem prin fiecare coordonata $x$ distincta cate o dreapta verticala. Se formeaza astfel niste benzi verticale intersectate de laturile poligonului. Pentru fiecare banda tinem minte ce laturi ale poligonului intersecteaza aceasta banda si sortam aceste laturi pe verticala dupa mijlocul segmentului de intersectie al laturii cu banda. Acum pentru a determina daca un punct e in interiorul poligonului, determinam cu cautare binara mai intai banda din care face parte si apoi pentru banda respectiva deasupra cator segmente se afla, daca punctul e deasupra unui numar par de segmente atunci punctul e in exterior si daca e deasupra unui numar impar e interior. Astfel rezolvarea noastra are complexitatea $O(N^2^ log N)$ in faza de preprocesare si $O(log N)$ pentru a determina pentru fiecare punct daca este interior sau\r\nexterior poligonului. Complexitatea totala va fi {$O(N^2^ log N + M log N)$}.\r\n\r\n',6756,'public',NULL,NULL),('blog/final-preoni-2005','preONI 2005 s-a incheiat!','2005-03-21 00:00:00','2005-03-21 00:00:00','h1. preONI 2005 s-a incheiat!\r\n\r\nRunda #3 a concursului preONI s-a incheiat, impreuna cu intreg concursul preONI 2005! Rezultatele finale au fost publicate si problemele au fost mutate in arhiva dupa ~1h de la expirarea timpului de lucru. ;) Autorii problemelor au publicat un \'articol\':preoni-2005/runda-3/solutii despre aceasta runda, rezultate si idei de rezolvare: . Asteptam parerile si sugestiile tale pe \'forum\':http://forum.infoarena.ro!\r\n\r\nAceasta a fost ultima runda a concursului preONI, editia 2005. Speram ca efortul nostru si al sponsorilor nostri ti-a fost de folos in vreun fel.\r\n\r\nMicrosoft Romania ofera premii primilor 3 participanti de la fiecare grupa. Clasamentul se calculeaza pe baza punctajelor acumulate in runda #2 si #3, punctajele din runda #1 fiind folosite pentru departajare in caz de egalitate.\r\n\r\nh2. Castigatorii editei 2005 sunt...\r\n\r\nh3. Clasele IX - X (\'clasament complet\':preoni-2005/clasament-9-10)\r\n\r\n==Rankings(rounds=\"preoni52a|preoni53a\" display_entries=\"3\" pager_style=\"none\")==\r\n\r\nh3. Clasele XI - XII (\'clasament complet\':preoni-2005/clasament-11-12)\r\n\r\n==Rankings(rounds=\"preoni52b|preoni53b\" display_entries=\"3\" pager_style=\"none\")==\r\n\r\nFelicitari castigatorilor editei 2005! Acestia vor fi contactati prin email in vederea inmanarii premiilor Microsoft. Felicitari tuturor participantilor! Dorim sa multumim sponsorului nostru - Microsoft Romania - precum si D-lui. Prof. Emil Onea, studentului Octavian Costache si tuturor celor care ne-au oferit sugestii si ne-au sprijinit in organizarea editiei 2005 a concursului preONI!\r\n\r\nIti uram mult succes la ONI (by NET) si in continuare!',961,'protected',NULL,NULL),('warm-up-2004','Concurs de incalzire','2006-11-24 16:12:38','2006-11-24 16:41:40','h1. Concurs de incalzire\r\n\r\nConcursul s-a desfasurat pe 14/11/2004 si a avut 2 grupe si 3 probleme pentru fiecare grupa. Problemele au fost adaugate in \'arhiva\':arhiva, iar un articol cu solutiile este disponibil \'aici\':warm-up-2004/solutii.\r\n\r\nh2. Grupa mica, clasele 9-10 (\'Clasament\':warm-up-2004/clasament-9-10)\r\n\r\n!>warm-up-2004?logo.gif!\r\n\r\n== Tasks(round_id=\"filip1\" pager_style=\"none\") ==\r\n\r\nh2. Grupa mare, clasele 11-12 (\'Clasament\':warm-up-2004/clasament-11-12)\r\n\r\n!>warm-up-2004?logo2.gif!\r\n\r\n== Tasks(round_id=\"filip2\" pager_style=\"none\") ==',1,'protected',NULL,NULL),('summer-challenge-2','Summer challenge 2','2006-11-24 16:34:20','2007-03-19 10:53:57','h1. Summer challenge 2\r\n\r\nConcursul s-a desfasurat  Vineri, 11 august 2006, ora 12:00 pe o durata de 5h. S-au propus spre rezolvare 3 probleme. Problemele au fost adaugate in \'arhiva\':arhiva.\r\n\r\nSolutiile problemelor le puteti gasi \"aici\":summer-challenge-2/solutii.\r\n\r\nh2. \'Clasament\':summer-challenge-2/clasament\r\n\r\n!>summer-challenge-2?logo.jpeg!\r\n\r\n== Tasks(round_id=\"summer2\" pager_style=\"none\") ==',1,'protected',NULL,NULL),('pregatire-online-pentru-bacalaureatul-la-informatica','Pregatire online pentru bacalaureatul la informatica','2005-04-27 00:00:00','2006-11-24 00:34:01','h1. Pregatire online pentru bacalaureatul la informatica\r\n\r\nIncepand de astazi, site-ul \"infoarena\":http://infoarena.ro/ vine in sprijinul elevilor de liceu gazduind un amplu program de pregatire online la disciplina informatica din cadrul examenului de bacalaureat.\r\n\r\nIn cadrul acestui program de pregatire, profesori prestigiosi de informatica din tara vor pune la dispozitia elevilor o lista de subiecte de bacalaureat de doua tipuri:\r\n\r\n# Probleme de informatica; Pentru aceste subiecte, elevii vor trebui sa conceapa si sa redacteze solutii complete intr-un limbaj de programare la alegere. Site-ul dispune de un evaluator automat capabil sa noteze instantaneu solutiile propuse de elevi.\r\n# Teste de tip grila de informatica; Elevii au posibilitatea sa rezolve astfel de teste de tip grila. Ca si la problemele de informatica, raspunsurile trimise se evalueaza pe loc.\r\n\r\nLista de probleme si de teste grila se va imbogati saptamanal iar pe parcursul pregatirii se va construi un clasament al rezolvitorilor de probleme / teste grila.\r\n\r\nMentionam ca participantii le pregatire au posibilitatea sa discute pe marginea materialelor de pregatire si sa solicite explicatii prin intermediul \"forumului\":http://forum.infoarena.ro/.\r\n\r\nSponsorul principal al acestui proiect este \"Microsoft Romania\":http://www.microsoft.com/romania/ - prin intermediul programului \"Parteneri pentru educatie\":http://www.microsoft.com/romania/educatie/.\r\n\r\n',1142,'public',NULL,NULL),('preoni-2006/clasament-11-12','Clasament preONI 2006, Clasele XI-XII','2006-11-25 03:30:58','2006-12-01 18:14:13','== include(page=\"template/preoni-2006/rankings\") ==\r\n\r\nh2. Clasele XI-XII\r\n\r\n==Rankings(rounds = \"preoni61c|preoni62c|preoni63c|preoni64c\")==',13,'protected',NULL,NULL),('articole/template-matematica','articole/template-matematica','2008-12-13 15:03:37','2009-04-11 14:12:15','* !>articole/template-matematica?cercuri.png! \'Probleme cu puncte laticiale\':probleme-cu-puncte-laticiale\r\n* \'Teoria jocurilor: numerele Sprague-Grundy\':numerele-sprague-grundy\r\n* \'Coduri Gray\':coduri-gray\r\n* \'Teorema chineza a resturilor\':teorema-chineza-a-resturilor\r\n* \'Minimal enclosing circle\':minimal-enclosing-circle\r\n* \'The Monty Hall Problem\':the-monty-hall-problem\r\n* \'Ciurul lui Eratostene\':ciurul-lui-eratostene\r\n*{display: %display%} \'Algoritmul lui Euclid\':algoritmul-lui-euclid',3146,'protected',NULL,NULL),('blog/rezultate-ioi','Rezultate IOI','2006-08-19 00:00:00','2006-08-19 00:00:00','h1. Rezultate IOI\r\n\r\nIata rezultatele de la Olimpiada Internationala de Informatica din Mexic:\r\n\r\n|{background-color:gold}. Mircea Pasoi |{background-color:gold}. aur |\r\n|{background-color:gold}. Codrut Grosu |{background-color:gold}. aur |\r\n|{background-color:silver}. Tiberiu Florea |{background-color:silver}. argint |\r\n|{background-color:#9C6963}. Adrian Vladu |{background-color:#9C6963}. bronz |\r\n\r\nFelicitari echipei Romaniei si multe succese in continuare!',18,'protected',NULL,NULL),('usaco-nov-2005-divizia-gold','USACO nov 2005, divizia GOLD','2005-11-21 00:00:00','2006-11-22 02:29:35','h1. USACO nov 2005, divizia GOLD\r\n\r\n(Categoria _Competitii_, autor(i) _Adrian Diaconu_)\r\n\r\nEtapa din noiembria a fost una destul de usoara cu $17$ punctaje maxime printre care si $3$ romani:\r\n\r\n* Tiberiu Florea\r\n* Catalin Tiseanu \r\n* Adrian Vladu\r\n\r\n\"Teste si enunturile\":http://www.infoarena.ro/downloads?action=download&file=usaco_nov05.zip problemelor sunt disponibile in sectiunea Download.\r\n\r\nh2. Asteroids\r\n\r\nVom rezolva aceasta problema folosind un algoritm de cuplaj maxim. Se va construi un graf bipartit in care vom avea pe o parte coloanele matricii ({$1..n$}) pe cealalta liniile matricii ({$1..m$}). Vom avea muchie de la o linie la o coloana daca in pozitia respectiva se afla un bolovan ce trebuie distrus. Graful astfel construit va avea $n+m$ noduri si $k$ muchii (locurile unde sunt plasati bolovanii). Problema se reduce astfel la determinarea unui suport minim pe un graf bipartit care este echivalenta cu gasirea cuplajului maxim pe acest graf. Suportul minim inseamna o multime de noduri de cardinal minim astfel incat fiecare muchie are cel putin un capat in multime.\r\n\r\nPentru cei care nu sunt familiarizati cu algoritmul de cuplaj pot folosi un algoritm de flux maxim adaugand o sursa virtuala legata de toate nodurile ce reprezinta coloanele si o destinatie legata de toate nodurile ce reprezinta liniile. Capacitatile vor fi toate {$1$}. Fluxul maxim astfel determinat va fi egal cu cuplajul maxim. Complexitatea algoritmului de flux este $O(Flux*(nr_noduri+nr_muchii))$ si avand in vedere faptul ca fluxul poate fi maxim $n$ (deoarece o coloana nu se poate cupla de doua ori) se ajunge la {$O(n*(n+m+k))$}.\r\n\r\nh2. Grazing on the Run\r\n\r\nRezolvarea acestei probleme se face folosind metoda programarii dinamice. Se vor sorta coordonatele la care se afla lucrurile pe care doreste Bessie sa le culeaga apoi se vor construi matricile $min{~i,j,k~}$ si $timp{~i,j,k~}$ care vor avea urmatoarele semnificatii:\r\n\r\n* $min{~i,j,k~}$ - va retine costul necesar culegerii lucrurilor de pe pozitiile $i, i+1, ... , j$ la care se adauga timpul la care s-s terminat culesul acstor lucruri inmultit cu numarul de obiecte ramase ( $N - i + j - 1$ ) deoarece la acestea se va ajunge minim la timpul respectiv. $K$ va avea valoare $0$ sau $1$ in functie de capatul la care se afla Bessie la final ( stanga respectiv dreapta)\r\n* $timp{~i,j,k~}$ - va retine timpul necesar culegerii obiectelor $i, i+1, ..., j$ pentru a obtine minimul din $min{~i,j,k~}$\r\n\r\nSe observa ca in configuratia ({$i,j,k$}) se ajunge din starile ({$i,j-1,1$}), ({$i,j-1,0$}), ({$i+1,j,1$}), ({$i+1,j,0$}). Complexitatea de completare a matricii va fi {$O(n^2^)$}, in finala afisad minimul dintre {$min{~1,n,0~}$},{$min{~1,n,1~}$}. Memoria necesara va fi de $O(n)$ deoarece procesand matricea in ordinea cresterii lungimii intervalului ({$i,j$}) ne va fi necesara doar coloana precedenta.\r\n\r\nh2. Walk the Talk\r\n\r\nVom rezolva independent problema pentru fiecare cuvant aflat in dictionar. Vom nota $a{~i,j~}$ matricea cu litere, iar s{~i~} cuvantul pe care il analizam la un anumit moment, acesta avand lungimea {$L$}. Vom construi matricea $sum{~i,j,k~}$ in care se va retine numarul de moduri in care se obtine secventa $s{~1~}, s{~2~}, ... , s{~k~}$ folosind doar dreptungiul cu colturile in ({$1,1$}) si ({$i,j$}) din matricea de litere. Pentru a calcula configuratia ({$i,j,k$}) se numara intai cate se obtin pentru secventa $1..k$ pentru dreptunghiul respectiv fara a considera casuta $(i,j)$ ({$sum{~i-1,j,k~}+sum{~i,j-1,k~}-sum{~i-1,j-1,k~}$}) apoi daca avem $a{~i,j~}=s{~k~}$ adunam cate solutii avem pentru secventa $1..k-1$ pentru dreptunghiul respectiv mai putin casuta $(i,j)$ ({$sum{~i-1,j,k-1~}+sum{~i,j-1,k-1~}-sum{~i-1,j-1,k-1~}$}). In final solutia se va afla in {$sum{~n,m,L~}$}. Complexitatea construirii fiecare configuratii in parte este $O(1)$ deci in total va fi {$O(n*m*L)$}. Memoria necesara este {$O(n*m*L)$}, dar aceasta se poate reduce la $O(n*m)$ daca luam in considerare faptul ca la fiecare moment ne este necesar doar numarul de solutii pentru o secventa cu $1$ mai mica.\r\n\r\n',1,'public',NULL,NULL),('usaco-dec-2005-divizia-gold','USACO dec 2005, divizia GOLD','2006-01-05 00:00:00','2006-11-22 02:30:30','h1. USACO dec 2005, divizia GOLD\r\n\r\n(Categoria _Concursuri_, autor(i) _Daniel Pasaila, Mircea Pasoi_)\r\n\r\nIn acest articol veti gasi solutiile pentru problemele propuse la concursul USACO, editia din luna decembrie 2005, divizia GOLD. \"Teste si enunturile\":http://www.infoarena.ro/downloads?action=download&file=usaco.zip problemelor sunt disponibile in sectiunea Download.\r\n\r\nh2. Cow Patterns\r\n\r\nSolutia propusa in acest articol foloseste un algoritm de genul Rabin Karp. In aceasta problema alfabetul folosit este {$Sigma = {1, 2, ... S}$}, deci putem privi un sir de $K$ caractere consecutive ca reprezentand un numar in baza $S$ de lungime {$K$}. Spunem ca modelul este vectorul $P[1..K]$ iar textul dat este {$T[1..N]$}.\r\n\r\nFiind dat modelul $P[1..K]$ notam cu $p$ valoarea sa corespunzatoare in baza {$S$}. Intr-o maniera similara, fiind dat textul {$T[1..N]$}, notam cu $t{~s~}$ valoarea in baza $S$ a subsirului convertit {$T[s + 1...s + m]$}. In cazul in care gasim un subsir cu valoarea $t{~s~} = p$ atunci am gasit o potrivire a modelului pe text. Dificultatile care apar in rezolvarea problemei tin de convertirea sirului $T$ in timp real, dupa conditiile impuse de enuntul problemei. Astfel, ne deplasam cu un sablon de lungime $K$ spre dreapta. Pentru fiecare deplasament trebuie sa modificam valoarea $t{~s~}$ corespunzator. La deplasarea cu o pozitie apar urmatoarele cazuri:\r\n\r\n# din sablon iese o valoare unica sau intra o valoare care nu exista in deplasamentul curent.\r\n# din sablon iese o valoare care va exista si in deplasamentul urmator, si intra o valoare care exista deja in deplasamentul curent\r\n\r\nVom rezolva cazul $1$ in {$O(K)$}, convertind subsirul curent dupa regulile din enunt. Observam ca in cazul $2$ dupa efectuarea deplasamentului sablonul va contine aceleasi cifre. Aceasta operatie este deci doar o deplasare, deci o putem efectua in $O(1)$ exact ca la Rabin Karp.\r\n\r\nDesi complexitatea algoritmului pare ca este {$O(N * K)$}, la o analiza mai atenta ne dam seama ca ea este de fapt {$O(N * S)$}. Sa incercam sa calculam de cate ori poate aparea cazul $1$ in deplasare. Trebuie sa observam ca un element odata intrat in sablon mai poate genera cazul $1$ abia dupa $K$ elemente, deci numarul total in cel mai defavorabil caz este {$N/K * S$}. Complexitatea algoritmului devine acum $O(K * N/K * S + N)$ deci {$O(N * S)$}.\r\n\r\nLa implementare, toate operatiile se fac modulo $Q$ (unde $Q$ este un numar prim destul de mare). Acum poate vi se pare ca de fiecare data cand $t{~s~} = p$ ar trebui sa comparam in $O(K)$ cele doua subsiruri, complexitatea totala crescand. O analiza probabilistica ne arata ca pentru $Q$ prim si destul de mare sansele ca doua subsiruri diferite de lungime $K$ sa fie echivalente modulo $Q$ sunt foarte mici, deci o solutie care compara doar modulele numerelor va lua punctajul maxim fara probleme.\r\n\r\nh2. Barn expansion\r\n\r\nDupa cum au aratat-o si rezultatele, aceasta problema a fost cea mai simpla din concurs. Trebuie sa determinam numarul de dreptunghiuri a caror laturi nu intalnsesc laturile altor dreptunghiuri. De asemenea, sa nu uitam ca dreptunghiurile nu se pot suprapune. In aceste conditii observam ca daca doua dreptunghiuri se intersecteaza atunci se vor intersecta si $2$ segmente verticale sau $2$ segmente orizontale. Putem astfel sa luam mai intai toate segmentele verticale, vedem care dintre acestea se intersecteaza cu altele si marcam dreptunghiurile lor ca fiind rele. Repetam algoritmul si pentru segmentele orizontale, iar la sfarsit numaram cate dreptunghiuri bune ne-au ramas.\r\n\r\nProblema pe care trebuie sa o rezolvam acum este urmatoarea: avand $K$ segmente paralele cu axa Oy trebuie sa determinam care dintre acestea se intersecteaza cu altele. Pentru aceasta sortam segmentele in primul rand dupa coordonata $x$ si in al 2-lea rand dupa coordonata $y$ minima. Dupa aceasta sortare putem determina in $O(K)$ segmentele care se intersecteaza. Parcurgem vectorul de la stanga la dreapta, si pentru fiecare pas vedem daca segmentul curent se intersecteaza cu un segment precedent. Pentru aceasta trebuie sa tinem o variabila ls care reprezinta coordonata $y$ maxima atinsa pana la un moment dat. Pentru segmentul $i$ fie {$ymin{~i~}$}, $ymax{~i~}$ si $x{~i~}$ coordonatele lui. Pentru un $i$ daca $x{~i~} != x{~i-1~}$ sau $ymin{~i~} > ls$ initializam $ls$ cu {$ymax{~i~}$}. Altfel marcam segmentul $i$ si segmentul cu care am obtinut maximul $ls$ ca fiind rele, iar $ls$ devine {$MAX (ls, ymax{~i~})$}.\r\n\r\nProblema se rezolva similar si pentru segmentele orizontale. Complexitatea algoritmului este {$O(N logN)$}.\r\n\r\nh2. Layout\r\n\r\nVom nota pozitiile celor $N$ vaci cu $x{~1~}, x{~2~} ... x{~N~}$ si vom transforma fiecare relatie care se da intr-o constrangere de forma {$x{~i~} - x{~j~} &le; C$}. Cum se impune din enunt ca {$x{~1~} &le; x{~2~} &le; ... &le; x{~N~}$}, vom introduce initial constrangeri de forma {$x{~i~} - x{~i+1~} &le; 0$} ({$i < N$}). Apoi, pentru fiecare perechi de vaci $i < j$ care trebuie sa fie la distanta maxim {$D$}, vom introduce constrangerea {$x{~j~} - x{~i~} &le; D$}, iar pentru fiecare pereche $i < j$ care trebuie sa fie la distanta de minim {$D$}, vom introduce constrangerea {$x{~i~} - x{~j~} &le; -D$}. Trebuie acum sa rezolvam acest sistem de constrangeri.\r\n\r\nMotivul pentru toate constrangerile sunt de forma {$x{~i~} - x{~j~} &le; C$} , este pentru a modela aceasta problema folosind teoria grafurilor. Vom considera vacile ca fiind noduri de la $1$ la {$N$}, iar fiecare constrangere {$x{~i~} - x{~j~} &le; C$} va reprezenta o muchia de la $j$ la $i$ cu costul {$C$}. In acest graf vom determina distantele minime de la $1$ la fiecare nod intr-un vector {$D$}. Din definitia distantelor minime in grafuri , pentru o muchie ({$j, i$}) de cost $C$ se respecta relatia {$D{~i~} &le; D{~j~} + C$}, echivalenta cu {$D{~i~} - D{~j~} &le; C$}. Asadar vectorul $D$ va respecta fiecare constrangere formulata anterior pentru vectorul {$x$}. \r\n\r\nFiindca graful este rar ({$MD+ML+N-1$} muchii), se va folosi algoritmul Bellman-Ford pentru determinarea distantelor mimine, avand complexitatea O({$N*(MD+ML+N)$}). Modul in care lucreaza algoritmul Bellman-Ford asigura ca distanta dintre vaca $1$ si vaca $N$ este maximizata. Cazul cand vacile puteau fi asezate oricat de departe se putea detecta verificand daca distanta pana la vaca $N$ este infinit. De asemenea, cazul cand problema nu avea solutie putea fi detectat tot cu Bellman Ford, verificand daca exista un ciclu de cost negative accesibil din nodul {$1$}. Demonstratia ca atunci cand graful contine un ciclu negativ nu exista solutie o lasam pe seama cititorului.\r\n\r\n',1,'public',NULL,NULL),('blog/rezultate-summer-challenge-doi','Rezultate Summer Challenge Doi','2006-08-11 00:00:00','2006-08-11 00:00:00','h1. Rezultate Summer Challenge Doi\r\n\r\nIata ca s-a incheiat si \'Summer Challenge Doi\':summer-challenge-doi. Desi este vara si majoritatea petrec pe la munte sau pe la mare s-au gasit destui concurenti care sa isi faca timp si pentru acest antrenament.\r\n\r\nIata primii 6 clasati in urma evaluarii:\r\n\r\n==Rankings(rounds=\"summer2\" display_entries=\"6\" pager_style=\"none\")==\r\n\r\nFelicitari tuturor participantilor si va asteptam la concursurile viitoare de pe infoarena. Intre timp va puteti antrena cu problemele din {\"arhiva\":http://infoarena.ro/arhiva-probleme}.\r\n\r\nSolutiile oficiale le gasiti {\"aici\":http://www.infoarena.ro/Solutii_Summer_Challenge_Doi}.',1142,'protected',NULL,NULL),('preoni-2006/runda-4/solutii','Solutii preONI 2006, Runda a 4-a','2006-02-19 00:00:00','2008-12-28 09:11:06','h1. Solutii preONI 2006, Runda a 4-a\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa infoarena_)\r\n\r\nSuntem bucurosi sa va anuntam ca Runda a 4-a concursului preONI 2006 s-a incheiat. In acest articol va vom prezenta solutiile oficiale ale celor 7 probleme propuse precum si cateva aprecieri dupa cele patru probe de foc.\r\n\r\nS-a consumat si al patrulea act al bataliei si odata cu el si etapa on-line a concursului preONI. S-a tras linia si s-au desemnat \"fericitii calificati in runda finala\":preoni-2006/clasament (atentie! verificarea inca nu a fost facuta, dar cu asta ne vom ocupa in urmatoarea perioada).\r\n\r\nAruncandu-ne ochii pe clasamentele Rundei 4, constatam ca participantii au tras tare pe ultima suta de metri vrand sa ne contrazica previziunile sumbre dupa Runda 3. Desi nivelul de dificultate al problemelor a fost un pic mai scazut fata de runda precedenta, concurentii s-au dovedit mult mai conectati la concurs - suspectam ca apropierea olimpiadelor ar fi cauza. Asadar am avut punctaje aproape maxime $(275, 255)$ obtinute in viteza maxima de primii doi clasati la clasa a 9-a - $Bogdan Tataroiu$ si $Sima Mihai Cotizo$, un punctaj maxim la clasa a 12-a realizat de $Costea Andrei$ care a reusit, dupa un start mai putin reusit in rundele precedente, sa treaca la pas pe langa ceilalti info-atleti, unii dintre ei deja nume mari. De data aceasta, concurentii de la clasa a 10-a nu s-au lasat mai prejos fata de celelalte grupe de varsta si, avand un set clar mai usor decat precedentul, au adunat in ritm de maraton punctaje frumoase care au atins si depasit limita (legal admisa) de $200$. Felicitari pentru aceasta realizare lui $Vlad Dumitriu$ si $Bogdan Stoica$. In concluzie, am asistat la un concurs bine organizat (felicitari comisiei!) si la un sprint de sanatate din partea concurentilor (felicitari mai ales lor!) care ne-au convins inca o data ca tinerii nostri sunt pregatiti sa fuga mancand pamantul pentru gloria si renumele olimpiadelor nationale si internationale.\r\n\r\nUna peste alta, s-a incheiat o etapa frumoasa a concursului in care am pus mult suflet. Normal, pot fi doar 30 de participanti fericiti de rezultate. Ii felicitam pe cei calificati si abia asteptam sa-i vedem in finala. Ii felicitam si pe ceilalti care nu au putut sa-si tina suflul pana in final, pierzand locurile calificabile. Noi le uram cat mai multe succese, sa mai alerge vreo cateva sute de probleme (incepand cu cele din Arhiva noastra) si sa ne intalnim cu ei mult mai pregatiti la startul urmatorului preONI.\r\n\r\nIn urmatoarele pagini vom incerca sa explicam solutiile problemelor. Asa cum v-ati obisnuit, va puteti lamuri orice vi se pare neclar sau vag explicat intreband pe \"forum\":http://forum.infoarena.ro/, unde vom incerca sa raspundem cat mai promt. Va asteptam cu intrebari si sugestii (asigurati-va ca pareririle va sunt auzite!)\r\n\r\nh2. NextSeq\r\n(problema simpla clasa a 9-a)\r\n\r\nEste usor de observat ca cele doua siruri pot fi interpretate ca numere in baza $N$ (numarul de elemente din setul $X$). Acest lucru se poate efectua sortand numerele din setul $X$ si asociind fiecaruia o valoare intre $0$ si $N-1$ (procedeul poarta numele de normalizare). Stiind acest lucru, doua solutii sunt posibile.\r\n\r\nCea mai usoara dintre ele este sa calculam sirul ce il urmeaza pe $A$ (numarand in baza $N$) pana cand obtinem sirul $B$. Deoarece se garanta faptul ca sunt mai putin de $100$ de siruri intre $A$ si $B$, acest pas se va executa de maxim $100$ de ori. Ne punem problema calcularii sirului care urmeaza dupa sirul $A$. Putem afla sirul care-l urmeaza pe $A$ in complexitate $O(M)$ - $M$ este lungimea sirului $A$ - simuland operatia de adunare cu $1$ in urmatorul mod: parcurgem sirul $A$ incepand cu ultimul element pana cand gasim un element mai mic decat $N-1$ (interpretandu-l in baza $N$); incrementam acel numar si numerele egale cu $N-1$ intalnite pana la la el, le egalam cu $0$ (cea mai mica valoare). Singurul caz interesant este acela cand $A$ are toate elementele egale cu valoarea maxima dar este usor de tratat. Complexitatea finala va fi $O(D*P)$ - $P$ este lungimea sirului $B$ iar $D$ este numarul de siruri aflate intre $A$ si $B$.\r\n\r\nSolutia mai rapida, dar ceva mai dificil de implementat, se baza pe operatia de scadere pe numere mari. Astfel, dupa ce am calculat reprezentarile sirurilor $A$ si $B$ in baza $N$, putem efectua o scadere pe numere mari pentru a afla numarul de siruri cuprinse intre $A$ si $B$. Complexitatea solutiei este $O(P)$ - $P$ este lungimea sirului $B$.\r\n\r\nAmbele solutii obtin punctaj maxim, prima fiind ceva mai usoara, putandu-se ajunge la ea si prin abordari care nu tin cont de reprezentarea sirurilor in baza $N$.\r\n\r\nh2. GFact\r\n(problema medie clasa a 9-a)\r\n\r\nPrimul pas in rezolvarea problemei il reprezinta factorizarea numarului $P$. Acest lucru se poate realiza intr-o complexitate $O(&#8730;P)$. Odata obtinuta factorizarea, vom avea o relatie de forma:\r\n$P = T{~1~}^R1^ * ... * T{~K~}^RK^$\r\nImediat rezulta:\r\n$A = T{~1~}^R1 * Q^ * ... * T{~K~}^RK * Q^$\r\nAl doilea pas este sa observam ca daca aflam pentru fiecare $T{~i~}$, $B{~i~}$ astfel incat $B{~i~}!$ se divide la $T{~i~}^Ri * Q^$ atunci $B$ (numarul cautat in problema) este maximul dintre $B{~i~}$. Implicatia imediata e ca putem sa ne ocupam de fiecare numar prim in parte fara sa tinem cont de celelalte.\r\n\r\nAl treilea pas consta in determinarea $B{~i~}$-urilor cu ajutorul cautarii binare. Pentru o valoare candidata $X$ (din cautarea binara) trebuie sa calculam puterea lui $T{~i~}$ in descompunerea lui $X!$. Acest lucru se afla simplu ca fiind $[X/T{~i~}] + [X/T{~i~}^2^] + ...$ (unde prin $[x]$ intelegem partea intreaga a lui $x$). Cautarea binara se poate optimiza observand ca $B{~i~}$ este intotdeauna divizibil cu $T{~i~}$, ba mai mult nu va fi mai mare decat $(R{~i~} * Q) * T{~i~}$ (observatie necesara obtinerii punctajului maxim). In concluzie, vom cauta binar o valoare intreaga $K$ in intervalul $[1, R{~i~} * Q]$ astfel incat $B{~i~} = K * T{~i~}$ sa aiba propietata ca $B{~i~}!$ se divide la $T{~i~}^Ri * Q^$. Va puteti intreba de ce putem cauta binar. Este simplu: daca o valoare $X$ are propietatea ca $X!$ se divide la $Y$ (unde lui $X$ si $Y$ le putem da semnificatiile dorite de noi) atunci, evident, si $(X + 1)!$ se divide la $Y$.\r\n\r\nSolutia finala va avea complexitatea $O(&#8730;P * log Q * log Q)$. Exista o serie de solutii intermediare care permiteau obtinerea de punctaje suficient de mari si de aceea problema a fost considerata medie desi rezolvarea completa este destul de dificila.\r\n\r\n\r\nh2. Matrix\r\n(problema grea clasa a 9-a, problema medie clasa a 10-a)\r\n\r\nPrimul pas al algoritmului este calcularea numarului de aparitii ale fiecarei litere in matricea de $N*N$. Prima idee care ne vine in minte este ca pentru toate submatricile posibile sa calculam numarul de aparitii ale fiecarei litere si sa comparam cu valorile care trebuie obtinute. Acest algoritm are complexitatea $O(M^2^*(N+S))$, unde $S$ este dimensiunea alfabetului. Aceasta abordare obtine $50$ de puncte. \r\nVom verifica pentru toate cele {@(M-N)@}$^2^$ matrici posibile daca sunt sau nu permutari ale matricii-template. Apoi, pentru fiecare litera a alfabetului, efectuam urmatoarea preprocesare pentru a putea calcula in $O(1)$ numarul de aparitii ale literei din orice submatrice: $T{~i,j~}$ = numarul de aparitii pe pozitii $(x, y)$ cu $1 &le; x &le; i$ si $1 &le; y &le; j$.\r\n\r\nRelatia de recurenta este $T{~i,j~} = T{~i-1,j~}+T{~i,j-1~}-T{~i-1,j-1~}$, la care se adauga $1$ daca si numai daca pe pozitia $(i, j)$ se afla litera pe care o cautam. In aceste conditii, numarul de aparitii ale literei curente in submatricea cu colturile in $(i-N+1, j-N+1)$ si $(i, j)$ este $T{~i,j~}-T{~i-N,j~}-T{~i,j-N~}+T{~i-N,j-N~}$. Aceasta solutie are complexitatea $O(M^2^*S)$. Daca se foloseste $O(M^2^*S)$ memorie se obtin $70-80$ de puncte, iar pentru punctaj maxim este necesara reducerea la $O(M^2^)$. Acest lucru poate fi realizat folosind doua matrici, una in care tinem minte daca pentru o anumita pozitie s-a gasit vreo litera pentru care numarul de aparitii nu coincide cu cel dorit, si una in care se efectueaza preprocesarea pentru litera curenta. O alta optimizare, mult mai nesimnificativa, si care nu este necesara pentru $100$ de puncte, este renuntarea la verificarea pentru ultima litera, deoarece daca primele $25$ de litere s-au potrivit, iar numarul de litere este constant, e clar ca si cea de-a $26$-a litera se va potrivi.\r\n\r\n\r\nh2. Lista lui Andrei\r\n(problema usoara clasa a 10-a)\r\n\r\nProblema se rezolva folosind programare dinamica. Putem tine o matrice $V{~1..N~}{~1..26~}$ unde $V{~i,j~}$ reprezinta numarul de siruri de lungime $i$ ce contin ultima litera $j$. Incepem completarea matricii in ordine crescatoare a lungimii sirurilor, iar $V{~i,j~}$ se obtine prin insumarea valorilor $V{~i-1,k~}$, pentru orice $k$ a.i perechea $(k, j)$ sau $(j, k)$ sa nu se regaseasca in lista. Acest rationament conduce la un algoritm in $O(N * &#931;^2^)$, unde $&#931;$ reprezinta marimea alfabetului (in cazul nostru $26$).\r\n\r\nh2. Calcul\r\n(problema grea clasa a 10-a, problema medie clasele 11-12)\r\n\r\nDeoarece se cer doar ultimele $C$ cifre se va lucra modulo $10^C^$. Asadar, la primul pas se va calcula $A$ modulo $10^C^$, adica ne intereseaza doar ultimele $C$ cifre din $A$.\r\nO prima solutie pentru a calcula $A^1^ + A^2^ + ... + A^B^$ este de calcula $A^i^$ in $O(lg i)$ pentru fiecare $i$ folosind algoritmul clasic de ridicare la o putere in numar logaritmic de pasi (Cormen, capitolul 33). Aceasta solutie ar fi adus doar $20p$.\r\n\r\nSuma prezentata este o progresie geometrica clasica, si se poate calcula folosind formula $(A^B+1^-A) / (A-1)$. Calculul lui $A^(B+1)^$ se face folosind acelasi algoritm mentionat mai sus in $O(lg B)$ ({$lg$} = logaritm in baza 2). Pentru a efectua impartirea modulo $10^C^$, trebuie sa existe un invers multiplicativ pentru $A-1$ , modulo $10^C^$, lucru garantat doar pentru $50%$ din teste $(cmmdc(A-1, 10^C^) = 1)$. Inversul multiplicativ poate fi calculat folosind algoritmul Euclid extins sau teorema lui Fermat: $X^phi(N)^ = 1 (mod N)$ pentru $cmmdc(X, N) = 1$ si $phi(N)$ = indicatorul lui Euler, cate numere < $N$ sunt prime cu $N$. Din teorema reiese ca $X^phi(N)-1^ = X^-1^ (mod N)$, asadar inversul poate fi calculat algoritmul de ridicare la o putere mentionat mai sus ({$phi(10^C^)$} poate fi calculat usor). Un caz special la aceasta solutie apare atunci cand $A = 1$. Aceasta solutie n-ar fi adus decat $50p$ si necesita cunostiinte de matematica de clasa a 12-a. \r\n\r\nExista o solutie mult mai accesibila pentru clasele a 10-a si a 11-a, folosind\r\nrelatiile:\r\n$S(A,2*B) = S(A,B) * (1+A^B^)$\r\n$S(A,2*B+1) = A * (1+S(A,2*B))$\r\nCum numarul $B$ este dat in baza $16$, parcurgerea bitilor acestuia se face usor, simuland algoritmul de mai sus. Daca $A^B^$ se calculeaza la fiecare pas, complexitatea va fi $O(lg^2^ B)$, obtinand $60p$. O solutie $O(lg B)$ de $100$ de puncte se poate obtine calculand in paralel valorile $S(A,B)$ si $A^B^$. O ultima \"problema\" care ar fi putut exista este faptul ca se cer ultimele $C$ cifre, nu rezultatul modulo $10^C^$; spre exemplu, daca $C = 4$ si rezultatul modulo $10^4^$ ar fi fost $\"123\"$, in fisierul de iesire trebuia afisat $\"0123\"$.\r\n\r\nh2. Distante minime\r\n(problema usoara clasele 11-12)\r\n\r\nProblema se rezolva folosind algoritmul lui Dijkstra pornind din nodul $1$. Astfel pe langa vectorul $D{~1..N~}$ in care tinem distantele minime vom mai folosi un vector $P{~1..N~}$ in care tinem pentru fiecare nod $i$ numarul de drumuri de lungime $D{~i~}$. Cand relaxam o muchie vom face update, daca este cazul, atat in vectorul $D$ cat si in vectorul $P$.\r\n\r\nDeoarece costul drumurilor a fost definit ca produs de muchii, in vectorul $D$ putem ajunge sa avem numere cu mii de cifre. O implementare cu numere mari a algoritmului descris mai sus nu este destul de eficienta, ea obtinand aproximativ $75$ de puncte. Pentru a obtine punctajul maxim este necesara logaritmarea costului fiecarei muchii intr-o baza oarecare. Astfel putem transforma produsul in suma, folosind o proprietate a logaritmilor, fapt ce duce la o implementare simpla si rapida, folosind doar date de tip $double$.\r\n\r\nh2. Popandai\r\n(problema grea clasele 11-12)\r\n\r\nMai intai vom calcula, pentru fiecare pereche de puncte $A$ si $B$ din punctele ce reprezinta vizuinele, in sirul $sub{~AB~}$ cate puncte din restul de $n$ se afla sub segmentul de dreapta determinat de $A$ si $B$. Aceasta preprocesare poate fi efectuata in $O(n^2^ log n)$ cu un algoritm inteligent sau poate fi efectuata in $O(n^3^)$ cu metoda naiva care verifica pentru fiecare punct daca este situat pe intervalul $[A.x, B.x]$ si este sub dreapta determinata de cele doua puncte. Preprocesare vom putea pentru fiecare triunghi $ABC$ sa aflam in timp $O(1)$ cate puncte are in interior: presupunem fara a restrange generalitatea ca $A.x &le; B.x &le; C.x$, daca punctul $B$ e deasupra dreptei $AC$ atunci numarul de puncte din interiorul lui $ABC$ este $sub{~AB~} + sub{~BC~} - sub{~AC~}$, iar daca $B$ este sub dreapta $AC$ atunci numarul de puncte este $sub{~AC~} - sub{~AB~} - sub{~BC~} - 1$.\r\n\r\nOrice patrulater, fie el concav sau convex, are o diagonala interna. Daca fixam un segment $PQ$ ca fiind diagonala interna putem sa incercam sa gasim pentru fiecare $x$ triunghiul $PQR$ de arie minima pentru care punctul $R$ este deasupra dreptei $PQ$ si care contine in interior cel putin $x$ puncte, iar apoi sa gasim un triunghi $PQS$ de arie minima cu varful $S$ sub dreapta $PQ$ ce contine in interior cel putin $k-x$ puncte. Ariile minime ale acestor triunghiuri se pastreaza in doua siruri over si under iar aria minima a unui patrulater cu o diagonala $PQ$ va fi $min(over{~x~} + under{~k-x~} | unde x ia toate valorile de la 0 la k)$. Folosind artificiul explicat mai sus putem determina in $O(1)$ numarul de puncte ce se afla in interiorul unui triunghi, si astfel sirurile $over$ si $under$ pot fi calculate in $O(n)$. Complexitatea totala a algoritmului este $O(n^3^)$ pentru ca avem $O(n^3^)$ calcule in faza de preprocesare si pentru fiecare $n(n-1)/2$ diagonale vom efectua $O(n)$ calcule.\r\n',1430,'public',NULL,NULL),('blog/bursele-agora','Bursele Agora','2005-05-20 00:00:00','2005-05-20 00:00:00','h1. Bursele Agora\r\n\r\nPrin intermediul site-ului \"infoarena\":http://infoarena.ro/ veti putea participa online la finala concursului Bursele Agora! Mai multe detalii puteti gasi pe site-ul oficial al \"concursului\":http://www.ginfo.ro.\r\n',1142,'protected',NULL,NULL),('blog/lansare-preoni-2006','Lansare preONI 2006','2005-11-15 00:00:00','2005-11-15 00:00:00','h1. Lansare preONI 2006\r\n\r\nDaca e prima data cand auzi de preONI, te lamurim indata. Daca ai participat pana acum la un concurs preONI, afla ca anul acesta avem PREMII SERIOASE puse in joc, o finala live intr-o tabara si 5 runde minunate de probleme!\r\n\r\nPe scurt, preONI este un concurs cu premii destinat elevilor de liceu ce se pregatesc pentru competitii de informatica - in special ONI.\r\n\r\nAm construit o \"sectiune speciala\":preONI-2006 in site-ul infoarena pentru acest concurs. TOT CE VREI sa afli despre preONI 2006 se gaseste intr-un singur loc: premii, regulament, program, sponsori, forum, comisie si organizatori, finala in tabara etc.\r\n\r\nATENTIE! Prima runda incepe in curand - Sambata, 19 noiembrie. Intra pe pagina oficiala preONI 2006 pentru mai multe informatii. Te asteptam !\r\n\r\nEditia 2006 a concursului preONI se datoreaza sponsorilor nostri, carora le multumim pe aceasta cale:\r\n\r\n* \"IP Devel\":http://www.ipdevel.ro/\r\n* \"ORACLE Romania\":http://www.oracle.ro/\r\n* \"SOFTWIN\":http://www.softwin.ro/\r\n* \"Microsoft Romania\":http://www.microsoft.ro/\r\n* \"TotalSoft\":http://www.totalsoft.ro/\r\n',961,'protected',NULL,NULL),('blog/noutati-infoarena','Noutati infoarena','2005-11-15 00:00:00','2005-11-15 00:00:00','h1. Noutati infoarena\r\n\r\nDupa cum ti s-a promis inca din vara asta, anul acesta echipa infoarena ti-a pregatit un numar foarte mare de surprize! Cateva din ele s-au materializat, pentru a afla mai multe citeste in continuare.\r\n\r\nh2. \'preONI 2006\':preONI-2006\r\n\r\nBinecunoscutul concurs organizat de infoarena vine anul acesta intr-un format nou! Mai multe detalii gasesti pe pagina oficiale a acestui concurs accesibila de pe infoarena.\r\n\r\nh2. \'Evaluator (foarte) stabil\':Despre-Evaluator\r\n\r\nPuteti sa va luati adio de la perioadele cand evaluatorul nu functiona din cauza conexiunii la Internet. De acum incolo sistemul de evaluare ruleaza pe o conexiune garantata.\r\n\r\nh2. \'Despre infoarena\':Despre-infoarena\r\n\r\nComunitatea infoarena este intr-o expansiune continua. Aceasta pagina contine o privire generala dar si informatii detaliate despre infoarena impreuna cu un regulament imbunatit, venind in ajutorul utlizatorilor noi dar si celor vechi. De asemenea, am decis sa oferim o mica rasplata tuturor celor care au contribuit la dezvoltarea proiectului infoarena, si am creat o pagina cu echipa & colaboratorii infoarena, poze si palmares.',1142,'protected',NULL,NULL),('preoni-2006/runda-4','Runda 4, preONI 2006','2006-11-25 02:50:29','2006-11-27 16:16:47','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Runda 4\r\n\r\nConcursul s-a desfasurat duminica, 19 februarie, la ora 14:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nh2. Comisii\r\n\r\nh3. Stiintific\r\n\r\n* clasa a 9-a (si gimnaziu)\r\n** Cosmin Negruseri\r\n** Silviu Ganceanu \r\n* clasa a 10-a\r\n** Daniel Pasaila\r\n** Tiberiu Florea \r\n* clasele 11-12\r\n** Adrian Vladu\r\n** Adrian Diaconu\r\n** Mircea Pasoi \r\n\r\nh3. Organizatoric\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* Cristian Strat\r\n* Crestez Leonard \r\n\r\nh2. Solutii\r\n\r\nSolutiile problemelor le puteti gasi \"aici\":preoni-2006/runda-4/solutii\r\n\r\nh2. Clasa a 9-a si gimnaziu (\'Clasament\':preoni-2006/runda-4/clasament-9)\r\n\r\n!>preoni-2006/runda-4?logo.jpg!\r\n\r\n== Tasks(round_id=\"preoni64a\" pager_style=\"none\") ==\r\n\r\nh2. Clasa a 10-a(\'Clasament\':preoni-2006/runda-4/clasament-10)\r\n\r\n!>preoni-2006/runda-4?logo.jpg!\r\n\r\n== Tasks(round_id=\"preoni64b\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2006/runda-4/clasament-11-12)\r\n\r\n!>preoni-2006/runda-4?logo.jpg!\r\n\r\n== Tasks(round_id=\"preoni64c\" pager_style=\"none\") ==\r\n\r\n\r\n==include(page=\"template/preoni-2006/footer\")==',13,'protected',NULL,NULL),('blog/final-preoni-2006-runda-1','Runda 1 preONI 2006 s-a incheiat','2005-11-19 00:00:00','2005-11-19 00:00:00','h1. Runda 1 preONI 2006 s-a incheiat\r\n\r\nPrima runda online a concursului preONI 2006 s-a incheiat. Totul a decurs normal, singurul lucru care ne-a dezamagit fiind comportarea elevilor de clasele 9-10, care au obtinut punctaje sub asteptari.\r\n\r\nFiecare grupa a avut spre rezolvare 3 probleme, fiecare fiind catalogata de catre comisie ca fiind usoara, medie sau grea. Batalia pentru calificarea la finala este abia la inceput!\r\n\r\nPentru mai multe detalii despre finala, cat si despre concursul preONI 2006 si sponsorii nostri va rugam sa consultati \'pagina concursului\':preONI-2006. S-a publicat rezultatele finale:\r\n\r\n* \'Clasa a IX-a\':preoni-2006/runda-1/clasament-9\r\n* \'Clasa a X-a\':preoni-2006/runda-1/clasament-10\r\n* \'Clasele XI-XII\':preoni-2006/runda-1/clasament-11-12\r\n\r\nDin pacate, punctajele la clasele a 9-a si a 10-a sunt sub asteptarile comisiei. Pentru discutii despre dificultate problemelor si despre concursul preONI 2006 in general va invitam sa intrati pe \'forum\':http:forum/infoarena.ro.\r\n\r\nSolutiile problemelor au fost publicate \'aici\':preoni-2006/runda-1/solutii\r\n\r\n',961,'protected',NULL,NULL),('preoni-2006/runda-1/solutii','Solutii preONI 2006 - Runda 1','2005-11-19 00:00:00','2008-09-23 21:02:13','h1. Solutii preONI 2006 - Runda 1\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa infoarena_)\r\n\r\nRunda 1 a concursului preONI 2006 s-a incheiat. Acest articol contine solutiile oficiale pentru toate probleme propuse spre rezolvare, cat si comentarii referitoare la concurs.\r\n\r\nFiecare grupa a avut spre rezolvare 3 probleme, fiecare fiind catalogata de catre comisie ca fiind usoara, medie sau grea. Batalia pentru calificarea la finala este abia la inceput!\r\n\r\nPentru mai multe detalii despre finala, cat si despre concursul preONI 2006 si sponsorii nostri va rugam sa consultati \"pagina preONI-2006\":preONI-2006.\r\n\r\nRezultatele finale sunt disponibile la:\r\n\r\n* \"Clasa a 9-a\":http://infoarena.devnet.ro/index.php?page=stats&conid=preoni61a&smod=top\r\n* \"Clasa a 10-a\":http://infoarena.devnet.ro/index.php?page=stats&conid=preoni61b&smod=top\r\n* \"Clasele 11-12\":http://infoarena.devnet.ro/index.php?page=stats&conid=preoni61c&smod=top\r\n\r\nDin pacate, punctajele la clasele a 9-a si a 10-a sunt sub asteptarile comisiei. Pentru discutii despre dificultate problemelor si despre concursul preONI 2006 in general va invitam sa intrati pe \"forum\":http://forum.infoarena.ro/index.php/board,20.0.html.\r\n\r\nInainte de a va prezenta solutiile va invitam sa rezolvati problemele propuse la acest concurs in \"Arhiva de probleme infoarena\":http://infoarena.ro/arhiva-probleme, si va asteptam in forta la runda a 2-a a concursului! (17 decembrie 2005)\r\n\r\nh2. Reuniune\r\n\r\nh3. (clasa a 9-a problema usoara)\r\n\r\nVom considera cazul simplificat cu $2$ dreptunghiuri $A$ si {$B$}, pentru care putem obtine formulele:\r\n\r\n* $Arie(A + B) = Arie(A) + Arie(B) - Arie(A x B)$\r\n* $Perim(A + B) = Permi(A) + Perim(B) - Perim(A x B)$\r\n\r\n({$A+B$} reprezinta reuniunea multimilor $A$ si {$B$}, iar $AxB$ intersectia.)\r\n\r\nCazul cu $3$ dreptunghiuri {$A$}, {$B$}, $C$ se rezolva similar. Cea mai simpla metoda este de a \"vizualiza\" formula facand un desen. Mai jos aveti un astfel de desen ajutator.\r\n\r\n!preoni-2006/runda-1/solutii?reuniune.png!\r\n\r\nAsadar, obtinem formula:\r\n\r\n* $Arie(A+B+C) = Arie(A) + Arie(B) + Arie&#40;C&#41; - Arie(AxB) - Arie(BxC) - Arie(AxC) + Arie(AxBxC)$\r\n\r\n(pentru perimetru formula este asemanatoare)\r\n\r\nAstfel rezolvarea este {$O(1)$}, deoarece intersectia a $2$ sau $3$ dreptunghiuri poate fi calculata usor in timp constant. Mentionam ca formula de mai sus poate fi gasita si pe cale algebrica, si reprezinta un caz particular al principiului includerii si excluderii.\r\n\r\nh2. Patrate 2\r\n\r\nh3. (clasa a 9-a problema medie)\r\n\r\nMai intai sa completam matricea doar cu $1$ si $5$ astfel incat produsul elementelor de pe fiecare linie sau coloana sa fie {$5$}. Observam ca pe fiecare linie si pe fiecare coloana se plaseaza exact un {$5$}, restul matricii fiind completata cu {$1$}. Este evident ca fiecare permutare a multimii ({$1, 2 * N$}) reprezinta de fapt o posibilitate de aranjare a numarului $5$ in matrice, iar de aici deducem ca numarul de posibilitati de a completa matricea doar cu $1$ si $5$ este $P{~N~}$ (adica {$N!$}). Cum putem folosi si $-1$ si {$-5$}, rezultatul final va fi $2^N*N^*N!$\r\n\r\nLa implementare trebuie sa se efectueze operatii cu numere mari. De asemenea, se recomanda ca baza in care se lucreaza trebuie sa fie destul de mare pentru a se obtine eficienta dorita.\r\n\r\nh2. Invers (solutie oferita de Bogdan Tataroiu)\r\n\r\nh3. (clasa a 9-a problema grea, clasa a 10-a problema usoara)\r\n\r\nRezolvarea acestei probleme presupune parcurgerea numarului ce trebuie verificat (il vom nota cu {$v$}) din exterior spre interior. Notam cu s pozitia extremitatii stangi al numarului, iar cu $d$ pozitia extremitatii drepte. Astfel numarul $v$ este format prin adunarea unor numere de forma\r\n\r\n* $a{~1~} a{~2~} a{~3~} ... a{~n-2~} a{~n-1~} a{~n~}$\r\n* $a{~n~} a{~n-1~} a{~n-2~} ... a{~3~} a{~2~} a{~1~}$\r\n\r\nAsadar, prin adunarea cifrelor $a{~i~}$ si $a{~n-i+1~}$ se poate obtine un transport care va afecta cifrele anterioare. Deoarece sirul este parcurs de la extremitati spre interior $s$ va fi egal cu {$i$}, iar $d$ va fi egal cu {$n - i + 1$}, deci cifrele $v{~s~}$ si $v{~d~}$ sunt formate prin adunarea cifrelor $a{~i~}$ si {$a{~n-i+1~}$}.\r\nIn parcurgerea sirului de la extremitati catre interior cazul ideal este atunci cand $v{~s~}$ este egal cu {$v{~d~}$}, caz in care cifra $v{~s~}$ nici nu primeste si nici nu trimite transport la cifrele aflate pe pozitii anterioare.\r\n\r\nUn alt caz este cel in care $v{~s~}$ primeste transport prin adunarea cifrelor $a{~s+1~}$ si $a{~d-1~}$ (vezi schema de mai sus pentru a intelege acest lucru). In acest caz $v{~s~}$ este egal cu $v{~d~}+1$ si, pentru a tine cont de faptul ca pozitia $s+1$ a generat transport, adaugam la $v{~s+1~}$ valoarea {$10$}.\r\n\r\nUn al treilea caz este acela in care $v{~s~}$ da transport pentru cifra $v{~s-1~}$ si nu primeste transport de la {$s+1$}, in acest caz $v{~s~}$ fiind egal cu $v{~d~}+10$ (acel $10$ fiind adaugat la pasul anterior). Deoarece atat $v{~s~}$ cat si $v{~d~}$ sunt obtinute prin adunarea cifrelor $a{~s~}$ si {$a{~d~}$}, iar $v{~s~}$ da transport cifrelor anterioare, atunci si $v{~d~}$ da transport cifrelor anterioare. Pentru a corecta acest lucru cifra $v{~d-1~}$ trebuie decrementata, avand grija la cazurile in care $v{~d-1~}$ este egal cu {$0$}. De asemenea trebuie luat in calcul cazul in care $v{~d~}$ este egal cu $9$ si {$v{~s~}=19$}. Acest lucru este imposibil deoarece suma maxima a doua cifre este $18$ si, evident, va trebui sa se afiseze raspunsul {$NU$}.\r\n\r\nAl patrulea si ultimul caz este acela in care $v{~s~}$ da transport cifrei $v{~s-1~}$ si, in acelasi timp, primeste transport de la cifrele aflate pe pozitia {$s+1$}. In acest caz $v{~s~}=v{~d~}+11$ si trebuie executate atat operatiile pt cazul {$v{~s~}=v{~d~}+1$}, cat si cele pentru cazul {$v{~s~}=v{~d~}+10$}.\r\nDaca diferenta $v{~s~}-v{~d~}$ este diferita de {$0$}, {$1$}, $10$ si $11$ atunci numarul $v$ nu poate fi obtinut prin adunarea unui numar $a$ cu inversul sau.\r\nAlgoritmul se repeta pana cand $s$ devine egal cu {$d$}, caz in care cifra $v{~s~}=v{~d~}$ trebuie sa fie para pentru ca numarul $v$ sa indeplineasca conditia din enunt sau pana cand {$d=s+1$}, caz in care trebuie ca $v{~s~}=v{~d~}$ sau $v{~s~}=v{~d~}+11$ pentru ca numarul $v$ sa aiba proprietatea ceruta. \r\n\r\nSe mai considera cazul cand {$a{~1~}=0$}, iar {$v{~1~}=1$},obtinut printr-un transport : se aduna $10$ la {$v{~2~}$} si se considera numarul incepand de la pozitia a doua, caruia i se verifica validitatea. Atentie la cazuri particulare!\r\n\r\nPentru a intelege mai bine algoritmul general vom analiza urmatorul exemplu: {$7 2 2 3 2 6$}.\r\nObservand ca $7=6+1$ tragem concluzia ca prima cifra va trebui sa primeasca transport, deci vom analiza {$12 2 3 2$}. Observam din nou ca {$12=2+10$} ceea ce inseamna ca $12$ trebuie sa trimita transport in fata, deci si $2$ din coada va fi de fapt {$12$}. Vom lua inapoi transportul de la {$3$}, deci vom analiza in continuare {$2 2$}. Acestea fiind egale nu se primeste si nu se da transport. Deoarce nu sa dat peste nici o contradictie raspunsul va fi {$DA$}.\r\n\r\nComplexitatea acestui algoritm este $O(nr)$ pe test, unde $nr$ este numarul de cifre al numarului {$v$}.\r\n\r\nh2. Dreptunghi\r\n\r\nh3. (clasa a 10-a problema medie)\r\n\r\nUn dreptunghi care apare in grila de puncte laticiale e marginit de doua drepte verticale la stanga si la dreapta, si de doua drepte orizontale in sus si in jos. Acum, daca vrem pentru patru drepte fixate sa stim cate dreptunghiuri marginesc ele, ne putem uita la urmatorul desen.\r\n\r\n!preoni-2006/runda-1/solutii?drept.jpg!\r\n\r\nDaca dreptunghiul determinat de cele patru drepte are laturile $H$ si $W$ atunci un dreptunghi inscris va imparti laturile lui in bucatile {$A$}, $B$ si {$C$}, {$D$}. Acum folosind teorema lui Pitagora avem ca:\r\n\r\n* $A^2^ + D^2^ = Galben^2^$\r\n* $B^2^ + C^2^ = Verde^2^$\r\n* $Galben^2^ + Verde^2^ = Roz^2^$\r\n* $(A + B)^2^ = Rosu^2^$\r\n* $(C $-$ D)^2^ = Albastru^2^$\r\n* $Rosu^2^ + Albastru^2^ = Roz^2^$\r\n\r\nDe aici avem ca {$(A + B)^2^ + (C - D)^2^ = A^2^ + B^2^ + C^2^ + D^2^$}, astfel obtinem {$AB = CD$}, dar {$B = H - A$}, iar {$D = W - C$} deci avem ca {$C^2^ - WC + A(H - A) = 0$}. Daca il fixam pe $A$ atunci trebuie sa rezolvam o ecuatie de gradul doi in necunoscuta {$C$}, solutia trebuie sa fie intreaga intre $0$ si {$W$}.\r\n\r\nAstfel in $O(H)$ vom sti numarul de dreptunghiuri inscrise intr-un dreptunghi de dimensiuni {$H * W$}. Acest dreptunghi poate fi pus in $(N - H + 1) * (M - W + 1)$ locatii pe o grila de dimensiune {$N * M$}. Deci solutia are complexitate {$O(N*M^2^)$}, pentru fiecare dreptunghi de dimensiuni $1 &le; H &le; N$ si $1 &le; W &le; M$ calculandu-se numarul de dreptunghiuri inscrise.\r\n\r\nO rezolvare de complexitate $O(N^2^*M^2^)$ in care se cautau solutiile ecuatiei printr-un for ar fi luat $60$ de puncte. Rezolvarea directa folosind ecuatia de gradul doi ia in jur de $80$ de puncte. Algoritmul poate fi optimizat la factorii constanti, de exemplu avem nevoie de functia radical care este cam inceata, precalculand-o obtinem o accelerare a vitezei, alta idee ar fi ca numarul de solutii cu $A &le; H/2$ este egal cu numarul de solutii cu $A &ge; H - H/2$ si a treia idee de optimizare este ca numarul de dreptunghiuri inscrise intr-un dreptunghi de dimensiuni {$H$}, $W$ este acelasi cu numarul de dreptunghiuri inscrise intr-un dreptunghi de dimensiuni {$W$}, {$H$}.\r\n\r\nh2. Zebughil\r\n\r\nh3. (clasa a 10 problema grea, clasele 11-12 problema medie)\r\n\r\nSe poate aborda o rezolvare bazata pe parcurgerea numerelor de la $1$ la $3^n^-1$ in ordine. Pastram matricea best in care retinem numarul minim de camioane in care pot fi transportate blocurile date de bitii de $1$ din {$i$}. Completarea acestei matrici se face in {$O(3^n^)$}. Descompunerea in baza $3$ va avea urmatoarea semnificatie: $0$ - blocul nu e in multimea curenta, $1$ - blocul se afla in ultimul camion sau $2$ - blocul se afla intr-un camion anterior in care nu se mai poate aduaga.\r\n\r\nAceasta idee aduce $90$ de puncte daca este implementata corect. O alta solutie se poate obtine daca avem in vedere faptul ca avem limita superioara $500$ pentru capacitatea unui camion putem face o rezolvare ce foloseste principiul programrii dinamice. Vom folosi o matrice $best{~i,j~}$ care retine numarul minim de camioane astfel incat sa putem transporta blocurile identificate de bitii de $1$ din reprezentarea in baza $2$ a lui {$i$}, iar ultimul camion sa fie plin pana la capacitatea {$j$}. Aceasta solutie ar fi obtinut $70$ de puncte.\r\n\r\nDeoarece fie folosim maxim $n$ camioane fie nu avem solutie putem incerca construirea unei matrici {$best{~i,j~}$} cu semnificatia cat mai este liber in ultimul camion ca sa avem transportati bitii de $1$ din $i$ si sa folosim maxim $j$ camioane. Completarea acestei matrici se face in {$O(2^n^*n^2^)$}, aducand 100 de puncte.\r\n\r\nAnalizand mai departe observam ca nu este nevoie sa retinem pentru o configuratie decat solutia folosind numar minim de camioane deoarece daca am folosi mai multe putem pur si simplu sa incepem unul nou acuma care va avea capacitate {$G$}. Astfel complexitatea de memorie se reduce la {$O(2^n^)$} iar cea de timp la $O(2^n^*n)$\r\n\r\nO alta abordare interesanta a problemei dar care nu ducea la obtinerea unui punctaj maxim este generarea permutarilor prin backtracking si testarea greedy a solutiei. Parcurgem permutarea si cand avem nevoie de un camion nou il deschidem. Aceasta ar avea o complexitatea {$O(n!*n)$}. Putem insa retine pe parcurs costul pana in acel moment si la sfarsit sa nu trebuiasca sa mai parcurgem din nou. Pentru generarea permutarilor se poate retine o lista cu elementele care nu au fost inca puse in permutare lista in care un element se va adauga si se va scoate in {$O(1)$}. Aceasta tehnica se numeste dancing links si duce la o complexitate totala de $O(n!)$\r\n\r\nO abordare neortodoxa ar fi fost generarea aleatoare a permutarilor, astfel pornim de la o permutare initiala si luam doua elemente din permutare in mod aleator pe care le interschimbam, daca solutia obtinuta e mai buna sau cel putin egala cu solutia initiala (valoarea unei solutii o vedem folosind un algoritm greedy care baga in ordine elementele in camioane) atunci pastram solutia curenta, iar daca nu interschimbam elementele la loc. O asemenea tehnica de optimizare a solutiei ar fi dus la un punctaj de aproximativ $60$ de puncte.\r\n\r\nh2. Distante\r\n\r\nh3. (clasele 11-12, problema usoara)\r\n\r\nFoarte multi concurenti au incercat sa rezolve aceasta problema folosind algoritmul Dijkstra cu heap-uri sau cu arbori de intervale. Aceasta solutie ar fi obtinut de la $70$ pana la $100$ de puncte (in cazul in care se optimiza algoritmul). O alta metoda de a obtine $100$ de puncte ar fi fost folosirea algoritmul Bellman Ford cu coada (vezi OJI 2004, problema \"Lanterna\":http://infoarena.ro/problema/lanterna).\r\n\r\nSolutia oficiala (care este de fapt si cea mai simpla si cea mai usor de implementat) are complexitate $O(N+M)$ ca timp si $O(N)$ ca memorie. Ea poate fi dedusa din modul de functionare a algoritmilor Dijkstra sau Bellman Ford. Asadar, conditile suficiente si necesare ca distantele minime date sa fie corecte sunt:\r\n\r\n* $D{~S~} = 0$\r\n* $D{~x~} + cost(x, y) &ge; D{~y~}$ pentru orice muchie ({$x, y$})\r\n* exista pentru fiecare $y$ (diferit de {$S$}) un $x$ astfel incat $D{~x~} + cost(x, y) = D{~y~}$\r\n\r\nStudiati modul in care functioneaza Dijkstra sau Bellman Ford si veti vedea ca logica acestor conditii devine evidenta. Verificarea acestor conditii se poate face in complexitatea mentionata mai sus.\r\n\r\nh2. Balans\r\n\r\nh3. (clasele 11-12, problema grea)\r\n\r\nProblema a fost gandita sa rasplateasca pe \"fanii infoarena\" si anume pe aceea care au rezolvat corect problemele \"Secventa 1\":http://infoarena.ro/problema/secventa, \"Secventa 2\":http://infoarena.ro/problema/secv2, \"Secventa 3\":http://infoarena.ro/problema/secv3. Pentru a trata circularitatea matricii o vom extinde intr-o matrice $2N*2M$, lipind matrii initiale o copie la dreapta, sub ea, si la dreapta-jos.\r\n\r\nRezolvarea acum se va baza pe cautarea binara a balansului maxim (idee folosita si la rezolvarea problemei \"Secventa 3\":http://infoarena.ro/problema/secv3). Fie acesta {$X$}, trebuie sa verificam daca exista o submatrice cu balans cel putin {$X$}, adica:\r\n\r\n* $Suma / Numar &ge; X$\r\n* $Suma &ge; X*Numar$\r\n* $Suma - X*Numar &ge; 0$\r\n\r\nFolosind cele scrise mai sus, putem observa ca, daca fiecare element nr din matricea intiala este inlocuit cu {$nr-X$}, atunci problema se reduce la a determina o submatrice din matricea modificata in care suma elementelor este {$&ge; 0$}. Aceasta problema se poate rezolva determinand submatricea de suma maxima din matricea modificata, verificand apoi daca este {$&ge; 0$}.\r\n\r\nAsadar, problema s-a redus la a determina o submatrice de cel putin $R$ linii si $C$ coloane de suma maxima dintr-o matrice. Intai vom fixa $2$ linii la distanta cel putin $R$ si cel mult {$N$}, si vom calcula sumele pe coloane intre cele doua linii (acest lucru se poate face in $O(M)$ precalculand anumite sume la inceput). Pe vectorul de sume pe coloane obtinut va trebui sa rezolvam acum problema \"secventei de suma maxima de lungime intre {$C$} si {$M$}\" (necesara si la rezolvarea problemei \"Secventa 3\":http://infoarena.ro/problema/secv3). Fie $A$ vectorul pe care vrem sa rezolvam acesta problema, si {$S{~i~} = A{~1~}&#0043;A{~2~}&#0043;...&#0043;A{~i~}$}. Pentru fiecare $i$ va trebui sa gasim un $j$ astfel incat:\r\n\r\n* $S[i] - S[j]$ = maxim\r\n* $i-M &le; j &le; i-C$\r\n\r\nAcest lucru se poate face in $O(M)$ per total folosind structura \"deque\" , prezentata pe scurt si in articolul cu solutii de la preONI 2005, runda 3. Lasam detalierea modului in care se va folosi aceasta structura in rezolvare ca exercitiu pentru cititor. Astfel, problema poate fi rezolva in complexitatea $O(N^2^*M*lg MAX)$ unde $MAX$ este valoarea maxima din matricea. Mentionam ca pentru o solutie relativ rapida si care sa evite erori de precizie se recomanda lucrul cu numere intregi (inmultind totul cu {$1000$}).\r\n\r\n',2044,'public',NULL,NULL),('blog/probleme-noi','Probleme noi!','2005-05-24 00:00:00','2005-05-24 00:00:00','h1. Probleme noi!\r\n\r\nS-au adaugat 8 probleme noi in \"Arhiva de probleme\":http://infoarena.ro/arhiva-probleme si 3 probleme noi pentru Bacalaureat 2005 pe site-ul \"infoarena\":http://infoarena.ro/. Asteptam parerile voastre pe forum despre noile probleme si va invitam sa le rezolvati. More to come...\r\n\r\n',1142,'protected',NULL,NULL),('blog/info-educatie-2005','InfoEducatie 2005','2005-08-12 00:00:00','2005-08-12 00:00:00','h1. InfoEducatie 2005\r\n\r\nConcursul InfoEducatie 2005 a ajuns la final si am vrea sa va invitam sa cititi \"povestea\":http://www.infoeducatie.ro/povestea_2005.php editiei de anul acesta a concursului. Acolo gasiti atat poze cat si mici filmulete interesante din tabara.\r\n\r\nCred ca sunt in asentimentul tuturor, al organizatorilor, sponsorilor si al participantilor cand spun ca aceasta a fost cea mai reusita editie InfoEducatie de pana acum. Este important de stiut ca anul acesta a adus si o crestere spectaculoasa in calitatea lucrarilor aflate in competitie si a seriozitatii cu care elevii si-au prezentat productiile.\r\n\r\nPremiile au fost mari (valoare totala de peste $7000, valoarea unui premiu 1 fiind de peste $800 !!!), jurizarea corecta, juriul format numai din specialisti. S-a organizat concurs open la toate sectiunile (o noutate a acestei editii), discutii libere si seminarii si toate au contribuit la succesul editiei 2005.\r\n\r\nDe mare succes s-au bucurat cele doua sectiuni OPEN pe teme de programre si creatie web. Concursul a fost condus in cea mai mare parte de studenti, laureati din anii anteriori ai concursului (Octavian Costache, Liviu Valsan, Razvan si Bogdan Hobeanu, Cristian Strat).\r\n\r\nConsideram InfoEducatie, un eveniment care aduce un pasaport catre o afacere proprie in domeniul IT&C. In plus, InfoEducatie inseamna mai mult decat un concurs de succes cu premii foarte mari. El este un loc al pasiunilor si al initiativelor, un concurs unde toata lumea gandeste liber si discuta, o tabara a tinerelor talente. Este un concurs independent pentru oameni independenti, organizat cu pasiune si daruire pentru elevi.\r\n\r\nFirmele care au sponsorizat sau au oferit cursuri si consultanta au deja angajati \"produsi\" de InfoEducatie si spun ca vor veni oricand la concurs pentru ca este unic si productiv pentru cei care vor sa-si aleaga ca profesiune programarea: GreenPixel - Marius Deak, GrapefruitDesign - 2 anganjati ce au trecut prin InfoEducatie, Viorel Stan - companie internationala, Octavian Costache - angajat Google NY si exemplele pot continua.',1142,'protected',NULL,NULL),('blog/rezultate-agora-2005','Concursul Agora s-a incheiat!','2005-07-13 00:00:00','2005-07-13 00:00:00','h1. Concursul Agora s-a incheiat!\r\n\r\nConcursul Bursele Agora 2005 s-a incheiat, atat varianta online cat si cea on-site. Rezultatele finale au fost publicate si problemele au fost mutate in arhiva. Cosmin Negruseri, autorul a doua din probleme, a publicat un \"articol despre solutiile problemelor\":http://infoarena.ro/Concursul_Agora_Etapa_Finala_Solutii\r\n\r\nAsteptam parerile si sugestiile tale pe forum legate de acest concurs pe \"forum\":http://forum.infoarena.ro/index.php/topic,414.0.html.\r\n\r\nh2. Castigatorii Online\r\n\r\n==Rankings(rounds=\"ba6\" display_entries=\"3\" pager_style=\"none\")==\r\n\r\nh2. Castigatorii Onsite\r\n\r\n* Locul I Mugurel Ionut Andreica 290 puncte\r\n* Locul II Patcas Csaba 170 puncte\r\n* Locul II Constantin Dolghier 170 puncte\r\n\r\nFelicitari tuturor participantilor si va asteptam sa participati la urmatorul concurs organizat de devNet care va fi in luna august!',13,'protected',NULL,NULL),('blog/ioi-by-net','IOI by net !','2005-08-15 00:00:00','2005-08-15 00:00:00','h1. IOI by net !\r\n\r\nAnul acesta se organizeaza si varianta _\"by net\"_ a Olimpiadei Internationale de informatica. \"Pagina concursului\":http://sio.mimuw.edu.pl/ioi2005/.\r\n\r\nMult succes celor ce vor participa!',1142,'protected',NULL,NULL),('blog/concursul-happy-coding','Concursul Happy Coding','2005-09-09 00:00:00','2005-09-09 00:00:00','h1. Concursul Happy Coding\r\n\r\nSuntem bucurosi sa anuntam concursul Happy Coding, o competitie inedita gazduita de infoarena!\r\n\r\nUn amplu studiu efectuat in laboratoarele infoarena releva un fapt socant: strictetea evaluatorului si necesitatea de a preda o singura solutie buna per problema provoaca riduri vizibile concurentilor dupa numai 2h de competitie, fiind de departe cele mai semnificative surse de stres si hipertensiune pentru concurenti. :)\r\n\r\nh2. Happy Coding si de ce ii spunem noi asa\r\n\r\nConcursul se va desfasura online incepand cu ora 10:00, Sambata (10 septembrie) pana Duminica la ora 22:00 (11 septembrie). Timpul disponibil este asadar de 36h. Timpul recomandat (dar nu obligatoriu!) de lucru este de 4h.\r\n\r\nSe vor propune 6 probleme de dificultate medie ce acopera intreaga programa de informatica pentru clasele 9 - 12. Problemele presupun aplicarea tehnicilor clasice de programare si implementarea unor solutii simple, fara greseli. Propunator unic pentru setul de probleme este Mugurel Ionut Andreica, student la Univsersitatea Politehnica Bucuresti, Facultatea de Automatizari si Calculatoare.\r\n\r\nInedit la Happy Coding este prezenta evaluatorului on-line pe tot parcursul concursului. In alte cuvinte, poti testa mai multe solutii pana esti multumit de punctajul obtinut! Nu mai trebuie sa iti faci griji daca daca programul compileaza pe Linux, daca te incadrezi in limita de memorie sau daca solutia ta e suficient de rapida..\r\n\r\nHappy Coding inseamna programare cu zambetul pe buze, pace, idei, placere si distractie pura! :)\r\n\r\nTe asteptam asadar pe infoarena incepand cu ora 10:00, Sambata (10 septembrie). Si daca tot vorbim de distractie, nu uita sa-ti inviti si prietenii! Avem conturi pentru toata lumea. :)\r\n\r\nAsteptam intrebarile si sugestiile tale pe \"forum\":http://forum.infoarena.ro/',961,'protected',NULL,NULL),('blog/happy-coding-2','Happy Coding 2','2005-10-20 00:00:00','2008-11-26 18:49:02','A trecut mai bine de o luna de la ultimul concurs infoarena.\r\n\"Happy Coding\" a fost un succes total! :) Si cum un lucru bun nu vine niciodata singur, la insistentele publicului am decis sa organizam Happy Coding 2!\r\n\r\n!blog/happy-coding-2?hc2.jpg 50%!\r\n\r\nh2. Happy Coding 2 si de ce ii spunem noi asa\r\n\r\nConcursul se va desfasura incepand cu ora 10:00, Sambata (22 oct.) pana Duminica la ora 22:00. Timpul disponibil este asadar de 36h. Timpul recomandat (dar nu obligatoriu!) de lucru este de 8h.\r\n\r\nSe vor propune 10 probleme de dificultate medie ce acopera intreaga programa de informatica pentru clasele 9 - 12. Problemele presupun aplicarea tehnicilor clasice de programare si implementarea unor solutii simple, fara greseli. Propunator unic pentru setul de probleme este Mugurel Ionut Andreica, student la Universitatea Politehnica Bucuresti, Facultatea de Automatizari si Calculatoare. Inedit la \"Happy Coding 2\" este prezenta evaluatorului on-line pe TOT parcursul concursului. In alte cuvinte, poti testa mai multe solutii pana esti multumit de punctajul obtinut! Nu mai trebuie sa iti faci griji daca daca programul compileaza pe Linux, daca te incadrezi in limita de memorie sau daca solutia ta e suficientde rapida ...\r\n\r\n\"Happy Coding\" inseamna programare cu zambetul pe buze, pace, idei, distractie!\r\n\r\nTe asteptam asadar pe infoarena incepand cu ora 10:00, Sambata (22 oct.).\r\nAsteptam intrebarile si sugestiile tale pe \"forum\":http://forum.infoarena.ro/\r\n',1,'protected',NULL,NULL),('blog/cautari-ortogonale','Cautari Ortogonale','2005-10-29 00:00:00','2005-10-29 00:00:00','h1. Cautari Ortogonale\r\n\r\nUn \'articol\':downloads?Cautari_Ortogonale.doc folosit la pregatirea lotului din anul 2005 care discuta algoritmi de cautari ortogonale si aplicatii ale acestora a fost adaugat la sectiunea \'Download\':Downloads.',1142,'protected',NULL,NULL),('blog/noua-aparitie-editoriala','O noua aparitie editoriala!','2005-09-21 00:00:00','2005-09-21 00:00:00','h1. O noua aparitie editoriala!\r\n\r\nEchipa devNet va recomanda cartea \"Fundamentele programarii, clasa a X-a\" , autori \"Dana Lica\":mailto:danal182001@yahoo.com si \"Mircea Pasoi\":mailto:bogdanpasoi@yahoo.com. Culegerea respecta programa scolara a claselor a X-a de informatica si isi propune sa reprezinte un instrument util atat in munca de initiere in programare cat si in cea de performanta, cuprinzand peste 90 de probleme pentru concursuri si olimpiade.\r\n\r\nCartile le puteti gasi in Bucuresti la:\r\n\r\n* Libraria 88 (Langa Universitate, in spatele librariei Eminescu)\r\n* Libraria Papirus (in Piata Romana)\r\n* Libraria 74 In Piata Romana, la coloane\r\n* Libraria Mihail Sadoveanu (langa cinema Scala)\r\n\r\nh2. Cuprins\r\n\r\n# Capitolul 1: Tipuri structurate de date\r\n## Sir de caractere\r\n### Teste cu alegere multipla si duala\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Inregistrare - structura\r\n### Teste cu alegere multipla si duala\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Probleme de concurs ce proceseaza date structurate\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n# Capitolul 2: Subprograme definite de utilizator\r\n## Subprograme implementate in maniera iterativa\r\n### Teste cu alegere multipla si duala\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Subprograme implementate in maniera recursiva\r\n### Teste cu alegere multipla si duala\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n## Probleme de concurs\r\n### Probleme rezolvate\r\n### Probleme propuse\r\n\r\n',1142,'protected',NULL,NULL),('preoni-2006/finala/feedback','preONI 2006 Feedback','2006-11-25 00:55:39','2006-11-27 16:05:37','==Include(page=\"template/preoni-2006/header\")==\r\n\r\nh1. Feedback preONI 2006\r\n\r\n|_. &nbsp;|_. Medie |_. Procent |\r\n|_. Concurs | | |\r\n| Cazarea | 4,00 | 80% |\r\n| Mancarea | 4,22 | 84% |\r\n| Distractia | 3,15 | 63% |\r\n| Lifturile de la hotel | 3,52 | 70% |\r\n| Organizarea | 4,61 | 92% |\r\n| Premii | 3,52 | 70% |\r\n| Teatrul | 3,87 | 77% |\r\n|_. Mediul de lucru| | |\r\n|Hardware|3,74|75%|\r\n|Software|3,87|77%|\r\n|Ambient|3,22|64%|\r\n|Sistem de submit|4,70|94%|\r\n|Parola de administrator|3,78|76%|\r\n|_. Evaluarea| | |\r\n|Corectitudine|4,48|90%|\r\n|Promptitudine|4,09|82%|\r\n|Show|3,74|75%|\r\n\r\n&nbsp;\r\n\r\n|_. Probleme|_. Fun|_. Claritate|_. Dificultate|_. Implementare|\r\n|DivK|3,07|4,86|2,93|2,71|\r\n|Lupul Urias si Rau|3,71|4,29|3,00|4,43|\r\n|Overlap|2,14|3,43|4,71|4,14|\r\n|Iv|2,63|4,13|4,50|3,63|\r\n|Robotei|2,88|3,13|4,38|3,38|\r\n|Problema simpla cu nivele|3,44|4,44|2,22|3,11|\r\n|Arbore|3,33|4,22|4,11|3,22|\r\n|Pedefe|2,11|4,22|4,44|4,33|\r\n',13,'protected',NULL,NULL),('preoni-2006/finala/clasament-10','Clasament Finala preONI 2006, Clasa a X-a','2006-11-23 21:08:59','2006-12-01 18:16:00','== include(page=\"template/preoni-2006/finalrankings\") ==\r\n\r\nh2. Clasa a X-a\r\n\r\n==Rankings(rounds = \"preoni65b\")==',13,'protected',NULL,NULL),('blog/final-preoni-2006-runda-2','Runda 2 preONI 2006 s-a incheiat','2005-12-17 00:00:00','2005-12-17 00:00:00','h1. Runda 2 preONI 2006 s-a incheiat\r\n\r\nRunda a doua s-a incheiat. Dificultatea problemelor nu a lasat nici de aceasta data de dorit. Desi ne-am fi asteptat la punctaje mai mari, rezultatele concurentilor au fost decente. Provocarile oferite de infoarena sunt intr-adevar dificile, iar obtinerea unui punctaj apropiat de cel maxim nu este usor de realizat. In editiile ce vor urma vom tine cont de acest aspect. Fiecare grupa a avut spre rezolvare 3 probleme, fiecare fiind catalogata de catre comisie ca fiind usoara, medie sau grea. Batalia pentru calificarea la finala continua!\r\n\r\nPentru mai multe detalii despre finala, cat si despre concursul preONI 2006 si sponsorii nostri va rugam sa consultati \'pagina oficiala\':preONI-2006. S-au publicat rezultatele finale:\r\n\r\n* \'Clasa a IX-a\':preoni-2006/runda-2/clasament-9\r\n* \'Clasa a X-a\':preoni-2006/runda-2/clasament-10\r\n* \'Clasele XI-XII\':preoni-2006/runda-2/clasament-11-12\r\n\r\nSolutiile problemelor se gasesc \'aici\':preoni-2006/runda-2/solutii, va asteptam pe \'forum\':http://forum.infoarena.ro pentru discutii.\r\n\r\n\r\nVa asteptam cu forte noi in noul an la runda a 3-a!',961,'protected',NULL,NULL),('moisil-by-net-2006','Grigore Moisil By net 2006','2006-11-24 18:10:20','2006-11-24 18:24:27','h1. Grigore Moisil By net 2006\r\n\r\nConcursul s-a desfasurat incepand cu ora 16:00, joi, 30 martie 2006. \r\n\r\nAu existat 4 grupe fiecare avand de rezolvat cate 2 probleme mai putin grupa 11-12 care a avut de rezolvat 3 probleme.\r\n\r\nh2. Clasele 7-8 (\'Clasament\':moisil-by-net-2006/clasament-7-8)\r\n\r\n!>moisil-by-net-2007?logo.gif!\r\n\r\n== Tasks(round_id=\"moisil1\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 9 (\'Clasament\':moisil-by-net-2006/clasament-9)\r\n\r\n!>moisil-by-net-2007?logo.gif!\r\n\r\n== Tasks(round_id=\"moisil2\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 10 (\'Clasament\':moisil-by-net-2006/clasament-10)\r\n\r\n!>moisil-by-net-2007?logo.gif!\r\n\r\n== Tasks(round_id=\"moisil3\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':moisil-by-net-2006/clasament-11-12)\r\n\r\n!>moisil-by-net-2007?logo.gif!\r\n\r\n== Tasks(round_id=\"moisil4\" pager_style=\"none\") ==\r\n',961,'protected',NULL,NULL),('blog/final-preoni-2006-runda-3','Runda 3 preONI 2006 s-a incheiat','2006-01-24 00:00:00','2006-01-24 00:00:00','h1. Runda 3 preONI 2006 s-a incheiat\r\n\r\nFiecare grupa a avut spre rezolvare 3 probleme, fiecare fiind catalogata de catre comisie ca fiind usoara, medie sau grea.\r\n\r\nBatalia pentru calificarea la finala se pare ca se va incheia in runda a 4a. Mult succes in continuare!\r\n\r\nPentru mai multe detalii despre finala, cat si despre concursul preONI 2006 si sponsorii nostri va rugam sa consultati \'pagina oficiala\':preONI-2006. S-au publicat rezultatele finale:\r\n\r\n* \'Clasa a IX-a\':preONI-2006/runda-3/clasament-9\r\n* \'Clasa a X-a\':preONI-2006/runda-3/clasament-10\r\n* \'Clasele XI-XII\':preONI-2006/runda-3/clasament-11-12\r\n\r\nSolutiile problemelor se gasesc \'aici\':preONI-2006/runda-3/solutii.\r\n\r\nPentru discutia lor va asteptam pe \'forum\':http://forum.infoarena.ro.',961,'protected',NULL,NULL),('blog/articole-noi','Articole noi','2006-02-02 00:00:00','2006-02-02 00:00:00','h1. Articole noi\r\n\r\nDoua noi articole care au aparut in Gazeta de Informatica in 2005 au fost publicate la sectiunea \"Download\":downloads de catre ==user(user=\"domino\" type=\"tiny\")==. Acestea sunt disponibile si in format PDF.\r\n\r\nAsteptam feedback-ul vostru pe \'forum\':http://forum.infoarena.ro/\r\n\r\n',1142,'protected',NULL,NULL),('blog/topcoder-pentru-liceeni','Liceenii - TopCoderi (legali) incepand din iunie 2006 !','2006-02-07 00:00:00','2006-02-07 00:00:00','h1. Liceenii - TopCoderi (legali) incepand din iunie 2006 !\r\n\r\n\"Topcoder\":http://topcoder.com/tc a anuntat lansarea unei competitii pentru liceeni. Multe din detalii nu sunt inca stabilite, de aceea va incurajam sa intrati pe site si sa discutati pe forum pe baza regulamentului (pentru asta va trebuie un cont pe site). Anuntul se gaseste \"aici\":http://www.topcoder.com/tc?module=Static&d1=hs&d2=home. \r\n',1142,'protected',NULL,NULL),('blog/data-finalei-preoni-2006','ATENTIE! Data finalei preONI: 24-26 martie','2006-03-10 00:00:00','2006-03-10 00:00:00','h1. *ATENTIE!* Data finalei preONI: 24-26 martie\r\n\r\nSuntem nevoiti sa decalam concursul cu o zi. Astfel, vom astepta sosirea celor 30 de finalisti la Focsani oricand in decursul zilei de vineri, 24 martie, iar concursul se va desfasura in data de 25 martie, atat la Focsani, cat si online! Plecarea se va face duminica, iar luni veti putea ajunge la timp la scoala!',1142,'protected',NULL,NULL),('usaco-dec-2004-divizia-gold','USACO decembrie 2004, divizia GOLD - idei de solutii','2004-12-18 00:00:00','2006-11-25 15:31:57','h1. USACO decembrie 2004, divizia GOLD - idei de solutii\r\n\r\n(Categoria _Competitii_, autor(i) _Silviu Ganceanu_)\r\n\r\n\"Setul de probleme\":downloads?gold_dec04.zip pe marginea caruia voi discuta in urmatoarele randuri se afla disponibil in sectiunea download impreuna cu datele de test si rezultatele finale ale concursului (cei care nu stiu setul de probleme si vor sa citeasca articolul sunt rugati sa parcurga mai intai textele problemelor).\r\n\r\nVoi incepe prin cateva observatii in legatura cu evolutia concurentilor din Romania in acest concurs. Asadar un clasament (neoficial) alcatuit intre acestia ar arata in urmatorul mod:\r\n\r\ntable. |_. 1 | Vladu Adrian | 783 puncte|\r\n|_. 2 | Stancu-Mara Sorin | 782 puncte |\r\n|_. 3 | Andrei-Marius Teodorescu | 710 puncte |\r\n|_. 4 | Fechete Dan Ionut | 490 puncte |\r\n|_. 5 | Pasaila Daniel | 436 puncte |\r\n|_. 6 | Paul Diac | 406 puncte |\r\n\r\nRestul concurentilor au avut punctaje sub $400$ de puncte. Primii doi din clasamentul \"nostru\" au reusit sa se strecoare intre primele $20$ de locuri din clasamentul final dar, din nou, remarc lipsa unui roman in topul celor mai buni. Sper mai multe de la concursurile viitore! Mai vreau sa precizez ca Romania nu a dispus de tot arsenalul avut in dotare si concurenti cu rezultate in competiile internationale anterioare precum Dan Crestez si Dan Spatarel nu au fost prezenti in concurs (cel putin nu cu numele lor!). Ei sunt rugati sa participe in viitoarele concursuri (sau sa renunte la pseudonime - daca e cazul), spre binele lor si spre prestigiul Romaniei!\r\n\r\nSetul de probleme a fost unul dificil dar deosebit de frumos, necesitand cunostinte avansate de programare dinamica, structuri de date si teoria grafurilor. Totusi, pentru un concurent experimentat, problemele nu erau in totalitate noi. Spun asta pentru ca toate problemele aveau in substrat idei deja folosite in alte concursuri (CEOI, IOI si chiar barajele noastre).\r\n\r\nLasand comentariile deoparte sa trecem la ce ne intereseaza cel mai mult: solutiile.\r\n\r\nh2. Divide\r\n\r\nProblema se rezolva prin programare dinamica. Prima idee, destul de intuitiva de altfel, este o solutie de complexitate {$O(L * B)$}. Sa notam cu $BST{~l~}$ = numar minim de stropitori de care avem nevoie pentru a acoperi complet intervalul [{$0, l$}] cu $l$ par. Avem urmatoarea recurenta:\r\n\r\n* $BST{~l~}$ = $INFINIT$ daca $l$ este inclus intr-un interval al unei vaci\r\n* $BST{~l~}$ = {$minim(BST{~l - 2 * x~}) + 1$}, cu $x$ intre $A$ si $B$ astfel incat $2 * x$ este mai mic sau egal cu $l$\r\n\r\nPrintr-o implementare directa a recurentei de mai sus obtinem o solutie care foloseste $O(L)$ memorie si $O(L * B)$ operatii (cu observatia ca spatiul de memorie se poate reduce la {$O(B)$}).\r\n\r\nPentru a reduce complexitatea la $O(L)$ operatii se utilizeaza o coada care pastreaza valorile $BST{~x~}$ cu $x$ in intervalul [{$i - 2*B, i - 2*A$}] sortate crescator. Se observa cum se modifica coada cand se trece de la pozitia $i$ la pozitia $i + 2$ (practic \"intra\" valoarea $BST{~i + 2 - 2*A~}$ si \"iese\" valoarea {$BST{~i - 2*B~}$}. Nu voi intra in detalii despre modul cum lucreaza aceasta coada. Pe aceeasi idee (utilizarea acestei cozi) se rezolva si problema \"secventa\":problema/secventa (preOJI 2004 - infoarena) si \"trans\":problema/trans (prima proba a selectiei lotului national largit, Buzau 2004).\r\n\r\nh2. Obstacle\r\n\r\nSi aceasta problema se rezolva tot programare dinamica. Asadar avem $BST{~i, 0~}$ = distanta minima parcursa pentru a ajunge la capatul din stanga al gardului numarul $i$ si $BST{~i, 1~}$ = distanta minima parcursa pentru a ajunge la capatul din dreapta al gardului numarul {$i$}. De asemenea notam cu $Cap{~i, 0~}$ = pozitia capatului din stanga al gardului $i$ in sistemul de coordonte si $Cap{~i, 1~}$ = analog pentru capatul din dreapta. Avem urmatoarele recurenta:\r\n\r\n* $BST{~i, j~}$ = $minim(BST{~k, l~} + dst(Cap{~k, l~}, Cap{~i, j~})$ cu $k$ de la $i + 1$ la {$N$}, $l$ si $j$ fiind $0$ sau $1$ si cu proprietatea ca drumul pe Oy dintre $Cap{~k, l~} la gardul $i$ nu se interpune nici un alt gard.\r\n\r\nAceasta recurenta implementata direct ne da o solutie $O(N^2^)$ care, putin optimizata, ar fi putut obtine punctajul maxim. Totusi exista o solutie $O(N log N)$ care utilizeaza o structura de date numita arbori de intervale. Practic noi trebuie sa aflam pentru fiecare gard $i$ care este gardul pe care cade o bila lasata libera din capatul din stanga si din capatul din dreapta. Aceste informatii ne permit reducerea complexitatii recurentei de mai sus la $O(N)$ (nu va mai spun cum, ganditi si voi!). Pentru a afla informatiile despre care vorbeam se parcurg cele $N$ garduri de la $1$ la $N$ (in ordinea asta!) si se proiecteaza, pe rand, pe axa Ox. Practic se pastreaza axa Ox ca un interval [{$-200.000, 200.000$}] si, pentru un gard {$i$}, se egaleaza toate pozitiile din intervalul [{$Cap{~i, 0~}, Cap{~i, 1~}$}] cu {$i$}. Pentru un afla gardul pe care cade bila se interogheaza arborele pentru fiecare capat al gardului {$i$}. Explicatiile mele nu dezvaluie modul in care lucreaza acest arbore de intervale (mi-ar lua cateva zeci de randuri bune daca as intra in detalii). Pentru cei care nu au idee cum functioneaza acest \"monstru informatic\" le recomand citirea \"articolului\":downloads?arbori_de_interval.zip scris pe tema aceasta din sectiunea \"Download\":downloads.\r\n\r\nh2. Skiarea\r\n\r\nProblema se poate rezolva utilizand cunostinte de teoria grafurilor. Mai intai se contruiesc componentele conexe ale fiecarei celule printr-un algoritm de tipul {$FLOOD FILL$}. Prin componenta conexa intelegem set de celule din matrice cu aceeasi valoarea si care indeplineste propietatea ca intre oricare doua celule exista drum (dupa regulile din enunt). Odata aflate aceste componente conexe se construieste un graf asociat lor in urmatorul mod:\r\n\r\n* fiecare componenta conexa are asociat un nod\r\n* intre doua noduri $x$ si $y$ exista drum daca componenta conexa asociata lui $x$ este \"vecina\" cu componenta conexa a lui $y$ (este usor de intuit ce inseamna \"vecina\") si daca valoarea celulelor din $x$ este mai mare decat valoarea celulelor din {$y$}.\r\n\r\nGraful astfel construit este aciclic (acesta se demostreaza usor). In acest graf aflam nodurile in care nu intra nici o muchie - noduri \"sursa\" - (fie numarul lor {$P$}) si toate nodurile din care nu iese nici o muchie - noduri \"destinatie\" - (fie numarul lor {$Q$}). Solutia pentru problema noastra va fi:\r\n\r\n* maxim dintre $P$ si {$Q$}, daca graful are doua sau mai multe noduri\r\n* {$0$}, daca graful are un singur nod.\r\n\r\nToate cele trei etape ({$FLOOD FILL-ul$}, construirea grafului, aflarea nodurilor \"sursa\" si \"destinatie\") se pot realiza in $O(N*M)$ operatii utilizand $O(N*M)$ spatiu de memorie. Mare atentie insa: nici unul dintre pasi nu trebuie realizat recursiv!! (pentru ca altfel se iese din segmentul de stiva pe testele mari).\r\n\r\n\r\n',1,'public',NULL,NULL),('blog/grigore-moisil-by-net','Concursul interjudetean \"Grigore Moisil\" byNet','2006-03-21 00:00:00','2006-03-21 00:00:00','h1. Concursul interjudetean \"Grigore Moisil\" byNet\r\n\r\nLuni 27 martie, intre orele 16-19, site-ul infoarena va sustine varianta _by net_ a concursului intejudetean de informatica \"Grigore Moisil\", organizat la Bistrita. Subiectele vor avea patru categorii: clasele VII/VIII, clasa a IX-a, clasa a X-a si clasele XI/XII. Problemele vor fi propuse de doamna profesoara Clara Ionescu, Patcas Csaba, Mihai Pantis si Negruseri Cosmin. Va uram succes!\r\n\r\n',961,'protected',NULL,NULL),('moisil-by-net-2006/clasament-7-8','Clasament moisil1','2006-11-23 21:09:00','2006-11-24 18:24:49','h1. Clasament ==roundparam(round_id=\"moisil1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil1\")==',961,'protected',NULL,NULL),('blog/finala-preoni-2006','Finala preONI 2006','2006-03-22 00:00:00','2006-03-22 00:00:00','h1. Finala preONI 2006\r\n\r\nSuntem bucurosi sa anuntam marea runda finala a concursului preONI 2006! Aceasta va incepe in curand, mai exact Sambata, 25 martie, ora 09:00. Durata va fi de 5 ore. Finala se desfasoara la Focsani, in judetul Vrancea, fiind gazduita de Colegiul National \"Unirea\". Aici au fost invitati primii 10 de elevi clasati de la fiecare grupa.\r\n\r\nDesi batalia pentru premii se da intre concurentii de la finala, runda se va desfasura online si va fi deschisa tuturor, in stilul obisnuit infoarena! Ai ocazia sa concurezi cot la cot cu cei din finala!\r\n\r\nInformatii suplimentare (comisii, intrebari, tutorial, cum particip?) gasesti pe \'pagina dedicata acestei runde\':preoni-2006/finala.\r\n\r\nSponsorii rundei finale sunt Oracle Romania, Colegiul National \"Unirea\" si Hotelul \"Unirea\" din Focsani.\r\n\r\nClasamentele si solutiile rundei trecute (runda 4) s-au publicat imediat dupa terminarea timpului de lucru la \'adresa\':preoni-2006/runda-4/solutii.\r\n\r\nClasamentul complet, in urma celor 4 runde de calificare se gaseste \'aici\':preoni-2006/clasament.\r\n\r\nFinalistii preONI sunt primii 10 clasati de la fiecare grupa. Acestia vor concura pentru premii in bani si obiecte, la Focsani. Felicitari!\r\n\r\nh2. Clasa a IX-a (si gimnaziu)\r\n\r\n==Rankings(rounds=\"preoni61a|preoni62a|preoni63a|preoni64a\" display_entries=\"10\" pager_style=\"none\")==\r\n\r\nh2. Clasa a X-a\r\n\r\n==Rankings(rounds=\"preoni61b|preoni62b|preoni63b|preoni64b\" display_entries=\"10\" pager_style=\"none\")==\r\n\r\n\r\nh2. Clasele XI-XII\r\n\r\n==Rankings(rounds=\"preoni61c|preoni62c|preoni63c|preoni64c\" display_entries=\"10\" pager_style=\"none\")==\r\n',961,'protected',NULL,NULL),('blog/probleme-de-hosting-si-grigore-moisil-bynet','Probleme cu site-ul, concursul Grigore Moisil by Net','2006-03-29 00:00:00','2006-03-29 00:00:00','h1. Probleme cu site-ul, concursul Grigore Moisil by Net\r\n\r\nSite-ul infoarena a fost inaccesibil in ultimele doua zile! :( Site-ul a fost mutat (fortat) pe un nou server de webhosting. Dupa mult efort si insistente am reusit sa-l repunem pe picioare. Momentul a fost foarte nefast. A trebuit sa amanam concursul _Grigore Moisil by Net_. Ne pare sincer rau pentru inconveniente! Stim ca au fost utilizatori care s-au straduit si au pierdut timp ca sa fie prezenti in ziua si la ora respectiva. Nu noi am ales momentul. Din fericire, exista si o parte buna... suntem pe un server nou, performant, avem la dispozitie software up-to-date.\r\n\r\nIn sfarsit, putem indica data si ora exacta la care concursul pe care multi l-au asteptat chiar se va desfasura: Joi, 30 martie, ora 16:00. Subiectele vor avea patru categorii: clasele VII/VIII, a IX-a, a X-a si XI-XII. Problemele vor fi propuse de Prof. Clara Ionescu, Patcas Csaba, Pantis Mihai, Negruseri Cosmin. Informatii suplimentare gasesti pe \'pagina oficiala a concursului\':Moisil-by-net-2006.\r\n\r\nTe asteptam!',961,'protected',NULL,NULL),('blog/forum-nou','Forum nou!','2006-04-02 00:00:00','2006-04-02 00:00:00','h1. Forum nou!\r\n\r\nForum-ul infoarena s-a mutat la adresa \'infoarena.devnet.ro/forum\':http://forum.infoarena.ro. Ne pare rau pentru mesajele care s-au pierdut in timpul schimbarii, si asteptam parerile voastre despre noul forum si despre noile optiuni pe care acesta le ofera!',1,'protected',NULL,NULL),('summer-challenge-unu/solutii','Solutii - Summer Challenge Unu','2006-08-03 00:00:00','2007-01-14 13:24:56','h1. Solutii - Summer Challenge Unu\r\n\r\n(Categoria _Competitii_, autor(i) _Cosmin_)\r\n\r\nConcursul a fost unul reusit, adunand un numar respectabil de participanti.\r\nConcurentii ce vor participa la IOI au fost in forma azi ocupand primele trei pozitii ale clasamentului. greco a impresionat placut fiind singurul ce a rezolvat perfect problema de idee a concursului. Il remarcam pozitiv si pe wefgef care se tine aproape de ei, de asemenea o remarca negativa ar fi la adresa lui Adrian Vladu care nu a participat la aceasta pregatire ,desi ea a fost adresata direct lotului olimpic.\r\n\r\nUrmeaza primii 10 clasati:\r\n\r\n==Rankings(rounds=\"summer06\" display_entries=\"10\" pager_style=\"none\")==\r\n\r\nVa invitam mai departe sa va uitati peste schitele solutiilor problemelor propuse.\r\n\r\nh2. Free\r\n\r\nAceasta problema a fost considerata cea mai simpla din concurs, in special pentru ca realizarea unui program experimental care simula pasii din problema ne arata ca usile ce raman inchise au ca index un patrat perfect.\r\n\r\nPentru a demonstra aceasta afirmatie avem nevie de cateva cunostinte minore de teoria numerelor.\r\n\r\nLa fiecare pas $i$ directorul va vizita toti multiplii lui {$i$}, ceea ce inseamna ca un anumit numar $X4 va fi vizitat la pasii ai caror indecsi il divid pe {$X$}. Deci pentru a afla cate usi vor fi deschise in final va trebui sa numaram cate numere au un numar par de divizori. Pentru acest lucru ne va si mai usor sa numaram cate au un numar impar de divizori urmand sa le scadem din {$N$}. Stim ca daca descompunem un numar $X$ in factori primi: {$X=F{~1~}^P{~1~}^*F{~2~}^P{~2~}^*...*F{~t~}^P{~t~}^$} numarul de divizori ai sai va fi {$D=(P{~1~}+1)*(P{~2~}+1)*...*(P{~t~}+1)$}. Pentru ca $D$ sa fie impar trebuie ca fiecare factor al produsului sa fie deci $P{~i~}+1$ impar ceea ce inseamna ca exponentii factorilor primi din descompunere vor fi pari. {$X=F{~1~}^2*P\'{~1~}^*F{~2~}^2*P\'{~2~}^*...*F{~t~}^2*P\'{~t~}^ = (F{~1~}^P\'{~1~}^*F{~2~}^P\'{~2~}^*...*F{~t~}^P\'{~t~}^)^2^$}. Inseamna ca $X$ va fi patrat pefrect.\r\n\r\nAlta demonstratie mai intuitiva ar fi ca pentru usa $X$ putem imperechea actiunea $i$ cu actiunea $X/i$ daca $i$ este divizor al lui $X$ si astfel cele doua isi anuleaza efectul. Daca $X$ este patrat perfect atunci actiunea $[sqrt(X)]$ ramane neimperecheata, deci usa ramane deschisa.\r\n\r\nAstfel solutia problemei va fi {$N-[sqrt(N)]$}.\r\n\r\nOperatiile trebuie implementate pe numere mari. Operatia radical se poate implementa folosind o cautare binara.\r\n\r\nh2. Patrol\r\n\r\nAceasta problema a fost considerata una medie, pentru ca algoritmii de drum minim in grafuri sunt foarte frecvent folositi la concursurile de programare.\r\n\r\nObsevam ca fiecare paznic va fi la orasul de unde a pornit la timpii multipli de {$2*(l{~i~}-1)$} (din cauza miscarii dute-vino). Astfel toti paznicii vor fi in acelasi timp la orasul initial al fiecaruia la toti timpii multipli de {$cmmmc(2*(l{~1~}-1), 2*(l{~2~}-1), ..., 2*(l{~n~}-1))$}. Din cauza ca $l{~i~} < 8$ cel mai mic multiplu comun maxim posibil al numerelor din problema poate fi {$cmmmc(2*4, 2*3, 2*5) = 120$}, astfel pozitiile paznicilor pe reteaua noastra de orase cicleaza si perioada ciclului este $120$ sau un divizor al sau. Vom crea un graf in care nodurile sunt stari ale problemei ({$oras$}, {$timp &#0037; 120$}). Acum am redus problema la determinarea drumului de cost minim de la ({$1, 0$}) la ({$N, timp &#0037; 120$}), putem folosi un algoritm de drum minim la alegere Dijkstra cu heapuri sau bellman ford.\r\n\r\nh2. Pscpld\r\n\r\nAceasta problema se vroia a fi cea mai grea din concurs. O solutie bazata pe siruri de sufixe poate fi gasita in articolul \"Siruri de sufixe\" Adrian Vladu, Negruseri Cosmin, GInfo. Aceasta rezolvare nu ar fi luat punctaj maxim, o solutie similara in $O(n)$ foloseste arbori de sufixe. Denumirea problemei a fost aleasa pentru a sugera ca rezolvarea greoaie cu arbori de sufixe nu este cea cautata. Problema are o solutie simpla in $O(n)$ care urmeaza ideea rezolvarii in {$O(n^2^)$}.\r\n\r\nIn rezolvarea brute force fixam un centru pentru un palindrom si incercam sa marim palindromul cat mai mult. Solutia va pastra un sir $LUNG$ unde $LUNG{~2*i-1~}$ reprezinta lungimea palindromului maxim centrat in caracterul $i$ al sirului si $LUNG{~2*i~}$ lungimea palindromului centrat intre caracterul $i$ si $i + 1$ al sirului. Vom parcurge sirul de caractere de la stanga la dreapta si vom afla in ordine valorile din sirul {$LUNG$}.\r\nSa luam un exemplu:\r\n\r\n== code(cpp) |sirul:  a   b   a   a   b    a     c\r\nLUNG:   1 0 3 0 1 6 1 0 x\r\nindice: 1 2 3 4 5 6 7 8 9 10 11 12 13\r\n==\r\n\r\nAcum daca vrem sa calculam $LUNG{~9~}$ ar trebui sa ne extindem cat putem in lateral fata de {$b$}, dar observam ca centrul palindromului curent este continut in palindromul centrat la {$6$}. Din faptul ca palindromul contine doua subsecvente oglindite, noi nu trebuie sa mai iteram prin literele palindromului nostru pentru ca avem deja rezolvata problema oglindita, si continuam comparatiile cu caractere noi (in cazul nostru avem deja rezolvata problema {$a b a$} in secventa [{$1..5$}] si nu mai trebuie sa o rezolvam inca o data). Am obtinut astfel o rezolvare simpla de complexitate {$O(N)$}. Mentionam ca sursa oficiala nu are mai mult de $50$ de linii.\r\n\r\nExista si alte rezolvari optime posibile si ii rugam pe cei care au luat $100$ de puncte sa le explice in cadrul \"forumului\":http://infoarena.ro/forum/index.php/board,25.0.html.\r\n\r\n',1490,'public',NULL,NULL),('blog/summer-challenge-doi','Summer Challenge Doi','2006-08-06 00:00:00','2006-08-06 00:00:00','h1. Summer Challenge Doi\r\n\r\nConcursul _Summer Challenge Doi_ este continuarea celui de saptamana trecuta. Ne-au motivat reactiile pozitive primite din partea participantilor.\r\n\r\nConcursul se va desfasura vineri, 11 august, ora 12:00. Durata concursului va fi de 5 ore.\r\n\r\n_Summer Challenge Doi_ este o ocazie de antrenament pentru membrii inraiti ai comunitatii infoarena. Se vor propune spre rezolvare $3$ subiecte cu grade diferite de dificultate, de la accesibil la dificil, comparabile cu cele de la Summer Challenge.\r\n\r\nPregatirea problemelor va fi realizata de de Adrian Diaconu, Cosmin Negruseri, Ionut Fechete si Emilian Miron.\r\n\r\nPentru intrebari si sugestii, te asteptam pe \"forum\":http://forum.infoarena.ro/index.php/board,26.0.html.\r\n',1,'protected',NULL,NULL),('moisil-by-net-2006/clasament-10','Clasament moisil3','2006-11-23 21:09:00','2006-11-24 18:25:05','h1. Clasament ==roundparam(round_id=\"moisil3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil3\")==',961,'protected',NULL,NULL),('warm-up-2006/solutii','Solutii Autumn WarmUp 2006','2006-09-07 00:00:00','2007-07-04 18:11:08','h1. Solutii Autumn WarmUp 2006\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa Infoarena_)\r\n\r\nAici puteti gasi solutiile oficiale la cele 5 probleme propuse in concurs. De precizat si ca aceasta initiativa infoarena a fost un succes, adunand un numar respectabil de participanti. Punctajele au fost mai mici decat cele asteptate, fapt ce a confirmat ca setul de probleme a fost unul capabil sa puna in dificultate nume cunoscute la olimpiadele de informatica. Iata si solutiile:\r\n\r\nh2. poly\r\n\r\nProblema este una de programare dinamica si are complexitatea $O(N)$, de constanta $2^7^ = 128$. Sa notam cu $M{~i,j~}$ lungimea celui mai lung subsir utilizand primele $i$ numere din vector astfel incat ultimul element din subsirul optim sa aiba ca divizori numerele din multimea data corespunzatoare bitilor de $1$ din $j$. Mai intai $M{~i,j~}$ = $M{~i-1,j~}$ ( nu folosim numarul al $i$-lea ). Daca dorim sa folosim si numarul al $i$-lea, atunci $M{~i,config~} = maxim(M{~i,config~}$, $M{~i-1,k~} + 1)$, cu $k and config = 0$, unde $config$ are bitii de $1$ corespunzatori numerelor din multimea data cu care se divide acest al $i$-lea numar din sirul initial. Conditia $k and config$ ne asigura ca penultimul si ultimul numar din subsir nu au amandoua vreun divizor comun din multimea data (operatia $and$ in acest context este o operatie pe biti). Rezultatul va fi $max(M{~n,0~}$, $M{~n,1~}$... $M{~n,127~})$. Memoria folosita poate fi $O(1)$, retinand doar ultimele doua linii ale matricei.\r\n\r\nUn algoritm de complexitate patratica in $N$ folosind tot programarea dinamica ar fi obtinut $30-40$ de puncte.\r\n\r\nh2. bridge\r\n\r\nUn algoritm de complexitate $O(M + N * K)$ folosind programarea dinamica nu este foarte greu de gasit. Daca notam cu $M{~i,j~}$ numarul de moduri (modulo $666013$) de a ajunge in $i$ pasi pe scandura $j$ din pozitia initiala, atunci mai trebuie avut grija doar la relatiile de recurenta. In cazul de fata vom utiliza metoda inainte si vom trata cazurile: daca scandura $j$ este lipsa atunci $M{~i,j~} = 0$, daca scandura $j$ este teleportoare incrementam $M{~i+1,unde{~j~}~}$ cu $M{~i,j~}$ daca si numai daca {$unde{~j~}$} nu este lipsa sau subreda ({$unde{~j~}$} este destinatia teleportarii de pe scandura $j$),daca $j$ este scandura buna, incrementam $M{~i+1,j+1~}$ cu $M{~i,j~}$ si $M{~i+1,j+2~}$ cu $M{~i,j~}$ doar daca $j+2$ nu e lipsa sau subreda, etc.\r\n\r\nAvand construita matricea $M$, pentru fiecare query putem raspunde acum in $O(1)$. Exista diferite optimizari care pot fi facute si care sporesc substantial timpul de executie.\r\n\r\n\r\nh2. secv4\r\n\r\nDeoarece logaritmul unui produs de numere este egal cu suma logaritmilor fiecarui numar din produs, si in ipoteza ca toate numerele din sir sunt pozitive, logaritmam fiecare numar si notam cu $S{~i~}$ suma primilor $i$ logaritmi. Astfel, pentru a afla secventa de produs maxim care se termina pe pozitia $i$, este suficient sa determinam, pentru $k$ intre $i-y$ si $i-x$ care este $S{~k~}$ minim (astfel, $S{~i~} - S{~k~}$ va fi maxim, deci si produsul maxim, iar secventa va incepe pe pozitia $k+1$). Putem folosi un arbore de intervale si obtinem un algoritm $O(NlogN)$, sau o coada prin care scoatem elementele prin ambele parti (structura de date numita deque - double ended queue), obtinand complexitatea $O(N)$. Daca exista si numere negative, in momentul logaritmarii numerelor negative logaritmam opusul lor. Aplicand procedeul descris mai sus, stim sigur la final ca produsul obtinut are modulul maxim. Pentru a fi cu adevarat maxim (deci pozitiv), notam cu $semn{~i~}$ semnul produsului primelor $i$ numere. Ca secventa {@<j+1, i>@} sa aiba produs maxim trebuie in plus $semn{~i~} = semn{~j~}$. Vom retine doua deque-uri, unul pentru {$+$} si unul pt {@-@}, conform vectorului semn. Astfel, in final, suntem siguri ca produsul are semnul {$+$} si, cum are si modulul maxim, are valoarea maxima ceruta.\r\n\r\n\r\nh2. parcare\r\n\r\nProblema este exponentiala in dimensiunea matricii, dar polinomiala in numarul total de posibilitati de pozitionare al masinilor. Astfel, vom folosi un algoritm de tip BFS care garanteaza ca se ajunge la solutie intr-un numar minim de miscari. Plecam de la matricea initiala, si expandam pe rand toate starile posibile, miscand din starea curenta cate o masina pana cand nu mai exista nici o varianta noua de pozitionare a masinilor sau pana cand am scos masina A din parcare. Starile problemei le putem codifica intr-un intreg de $64$ de biti. Singurele variabile sunt pozitiile masinilor. Dupa ce eliminam zidurile inconjuratoare, coordonatele nu sunt mai mari decat $7$ ( $3$ biti ), deci pentru pozitia unei masini vom folosi $6$ biti. Concatenam pozitiile masinilor si, cum sunt maxim $10$ masini, codificarea nu va avea mai mult de $60$ de biti.\r\nPentru a memora starile explorate vom folosi o tabela de hash. De precizat si ca numarul total de posibilitati pornind de la starea initiala este destul de redus, deci problema va rula aproape instantaneu.\r\n\r\nh2. easy query\r\n\r\nUn algoritm simplu de complexitate $O(N*M)$ obtine $30-50$ de puncte. Algoritmul de $100$ de puncte are complexitatea $O(MlogN)$ si foloseste arbori de intervale. Considerand o secventa $x{~i~} x{~i+1~}... x{~j~}$ este evident ca pentru ca elementele sirurilor $y$ si $z$ sa fie maxime, respectiv minime, ele trebuiesc construite astfel:\r\n\r\n* $y{~t~} = x{~t~}- min(x{~k~}) + max(x{~p~}), i &le; t &le; j, t &le; k, p &le; j$\r\n* $z{~t~} = x{~t~} - max(x{~k~}) + min(x{~p~}), i &le; t &le; j, t &le; k, p &le; j$\r\n\r\nPentru a calcula in timp optim valoarea $P = max(y) + min(z)$ ne vom folosi de un arbore de intervale in urmatorul mod: fiecare nod al acestuia va constitui o secventa $x{~st~}, x{~st+1~}... x{~dr~}$ ( unde $st$ si $dr$ sunt marginile intervalului din nodul arborelui ) pe care o vom rezolva prin metoda brute force de la inceput, avand grija sa precalculam si alte valori necesare mai tarziu, cum ar fi :\r\n\r\n* $min = minim(x{~st~}, x{~st+1~}... x{~dr~})$\r\n* $max = maxim(x{~st~}, x{~st+1~}... x{~dr~})$\r\n* $x_max_max = maxim(x{~t~} + maxim(x{~p~}) ),st &le; t &le; dr si t &le; p &le; dr$\r\n* $x_max_min = minim(x{~t~} - maxim(x{~p~}) ),st &le; t &le; dr si t &le; p &le; dr$\r\n* $x_min_max = maxim(x{~t~} - minim(x{~p~}) ),st &le; t &le; dr si t &le; p &le; dr$\r\n* $x_min_min = minim(x{~t~} + minim(x{~p~}) ),st &le; t &le; dr si t &le; p &le; dr$\r\n* $y_max = maximul din sirul y corespunzator secventei x{~st~}, x{~st+1~}... x{~dr~}$\r\n* $z_min = minimul din sirul z corespunzator secventei x{~st~}, x{~st+1~}... x{~dr~}$\r\n\r\nAvand precalculate valorile de mai sus pentru fiecare nod al arborelui in parte vom putea raspunde in timp $O(logN)$ pentru fiecare din cele $M$ intrebari. Fiecare subsecventa data $x{~i~}, x{~i+1~}... x{~j~}$ va putea fi compusa din reuniunea mai multor noduri din arborele de intervale. Acum parcurgem nodurile ce compun subsecventa data de la dreapta la stanga si vom gasi rapid valorile $maxim(y)$ si $minim(z)$. Presupunand ca am ajuns la nodul $Q$ valoarea $maxim(y)$ pana aici se calculeaza astfel:\r\n\r\n* @MAX(Y) = maxim (y_max(Q) ; y_max_max(Q) - min(W) ; x_min_max(Q)+max(W) ; max(Q)+max(W)-min(W))@\r\n\r\nAnalog se calculeaza si $minim(z)$.',4772,'public',NULL,NULL),('preoni-2005/runda-2/solutii','preONI 2005 runda #2 - solutii','2005-02-25 00:00:00','2008-01-17 13:04:59','h1. preONI 2005 runda #2 - solutii\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa devNet_)\r\n\r\nDesi s-a desfasurat intr-o zi de miercuri, runda a doua a concursului preONI a avut un numar aproape dublu de accesari fata de runda 1. Acest lucru se datoreaza probabil atat faptului ca olimpiada judeteana \"bate la usa\" cat si prezentei premiilor oferite de sponsorul nostru, Microsoft Romania.\r\n\r\nIn continuarea acestui articol vom descrie solutiile oficiale ale problemelor. Daca aveti nelamuriri puteti sa puneti intrebari pe \"forum\":http://infoarena.ro/forum.\r\n\r\nScopul principal al concursului preONI 2005 este antrenamentul pentru ONI. Nivelul problemelor a fost corespunzator, asa ca nu fiti descurajati la OJI daca n-ati facut foarte bine acum! ;)\r\n\r\nPunctajele sunt multumitoare, fiindca de data asta nu s-au mai acordat cel putin $50p$ pentru solutii \"brute force\". Raportul de dificultate al problemelor a fost pastrat ca la runda {$1$}.\r\n\r\nIn continuare vom prezenta solutiile oficiale ale autorilor problemelor.\r\n\r\nh2. Clasele 9-10\r\n\r\nh3. Clasament\r\n\r\n==Rankings(rounds=\"preoni52a\" display_entries=\"8\" pager_style=\"none\")==\r\n\r\nSub pseudonimele ==user(user=\"arhirel\" type=\"tiny\")== si ==user(user=\"macarie\" type=\"tiny\")== se \"ascunde\", ca si la prima runda, echipa care va reprezenta Romania la finala ACM, formata din Mugurel Andreica, Marius Andrei si Ghinea Dan. Ei au concurat pe un singur calculator pentu a simula un concurs ACM. Stati linistit, premiile se dau doar concurentilor din ciclul de invatamant pre-universitar! De asemenea, se pare ca unii concurenti simt nevoia sa-si creeze mai multe conturi, Sorin Fagateanu avand 3 conturi in top 5 (cele 2 pe numele lui si contul cu numele \"Ion Iliescu\")... Tineti minte ca la un concurs \"standard\" nu aveti voie cu mai multe surse!\r\n\r\nh3. Pascal\r\n\r\nCa sa calculam puterea la care apare factorul prim $p$ in descompunerea lui $n!$ se poate folosi urmatoare formula $f = [n/p] + [n/p^2^] + [n/p^3^] +$ ... ({$[]$} reprezinta partea intrega). Avand acesta formula putem traversa un anumit rand din triunghiul lui Pascal si pt fiecare element ({$r,c$}) putem calcula puterea la care apare $d$ in descompunerea lui $r ! / ((r-c) ! * c!)$ . Atunci cand $d$ nu este prim trebuie sa avem grija sa verificam daca respectivul element ({$r,c$}) are in descompunerea sa toti factori primi a lui {$d$}. Daca $d=6$ , elementul din ({$r,c$}) trebuie sa contina $2$ si $3$ in descompunerea sa, iar daca {$d = 4$}, trebuie sa contina $2$ de cel putin doua ori.\r\n\r\nO alta modalitate sa calculam puterea la care apare un factor prim $p$ in descompunerea lui este: fie {$A{~c~}$} = puterea la care apare $p$ in decompunrea lui ({$r,c$}). $A{~c+1~}$ = {$A{~c~}$} + puterea lui $p$ in ({$r-c$}) - puterea lui $p$ in ({$c+1$}). Acesta relatie se poate deduce din modul din care putem calcula elementul ({$r,c+1$}) din ({$r,c$}) folosind formula ({$r,c$}) = $r ! / ((r-c)! * c !)$\r\n\r\nAceasta a fost cea mai simpla problema de la clasele {$9-10$}, oricare din cele doua idei prezentate mai sus aducand punctaj maxim.\r\n\r\nh3. Secv\r\n\r\nSubsirul trebuie sa contina toate elementele din sirul original in ordine crescatoare asa ca primul pas este sa ne formam acest subsir {$C$}. Avand acest subsir, parcurgem vectorul initial pentru a gasi pozitia de start a noii subsecvente. Dupa ce am gasit o posibila pozitie de start s incercam sa gasim subsirul $C$ avand ca pozitie de start {$s$}. Din toate aceste subsecvente o alegem pe aceea cu lungimea minima. Asftel, complexitatea algoritmului ajunge la {$O(N*M)$}, unde $N$ este lungimea secventei initiale si $M$ lungimea subsirului {$C$}. Problema se poate rezolva in aceeasi complexitate si cu programare dinamica, lasam acesta rezolvare ca exercitiu pentru concurenti!\r\n\r\nh3. Car\r\n\r\nLa prima vedere problema pare simpla si abordabila cu o cautare in latime, dar la o citire mai atenta problema se dovedeste putin mai grea. Cerinta e una de gasire a drumului minim intr-un graf in care nodurile sunt reprezentate de trei intregi ({$i,j,dir$}), $i$ si $j$ avand semnificatia liniei si coloanei din matrice iar $dir$ reprezinta directia cu care am intrat pe pozitia curenta. Muchiile din graful nostru au costurile dupa cum s-a explicat in enunt. Pentru gasirea drumului putem folosi algoritmul Dijkstra care foloseste un heap pentru expandarea nodurilor, complexitatea unei astfel de rezolvari ar fi fost $O(N*M lg (N*M))$ dar un asemenea algoritm nu ar fi luat punctaj maxim. O observatie care ne poate reduce constanta algoritmului ar fi ca nu are rost sa folosim curbe de $180$ sau de $135$ de grade, pentru ca am fi ajuns in aceeiasi pozitie mai repede. Pentru a nu folosi memorie prea multa pentru reprezentarea nodurilor in coada noastra de prioritati am putea folosi un singur intreg in loc de trei astfel:\r\n\r\n== code(cpp) |x = ((i - 1) * m + (j - 1)) * 8 + dir\r\n==\r\n\r\nsi decodificarea ar fi\r\n\r\n== code(cpp) |dir = x % 8; x /= 8;\r\nj = (x % m) + 1;\r\ni = (x / m) + 1;\r\n==\r\n\r\nPentru a avea o viteza mai mare la codificare si decodificare putem folosi operatii pe biti: $dir$ sa fie reprezentat pe $3$ biti {$i$}, pe urmatorii $9$ biti, iar $j$ pe urmatorii $9$ biti ({$i,j &le; 500 < 2^9^=512$}), astfel codificarea si decodificarea devin\r\n\r\n== code(cpp) |x = (i << 9) + j + (dir << 18);\r\ndir = x >> 18;\r\nj = (x & 511);\r\ni = (x >> 9) & 511;\r\n==\r\n\r\nCosturile muchiilor in graful nostru sunt mici si un algoritm ca cel\r\nal lui Dijkstra nu tine cont de aceasta proprietate. Daca aceste costuri sunt mici atunci si costul final al drumului de la sursa la destinatie va fi mic deci ne permitem sa folosim pentru fiecare valoare posibila a costului unui drum de la sursa la destinatie cate o lista. Cand am determinat pentru un nod distanta minima de la sursa la el, il inseram intr-o astfel de lista, observam ca expandarea unui astfel de nod poate afecta numai urmatoarele $4$ liste (prin expandare ne referim la actualizarea distantei minime de la sursa a vecinilor nodului curent). O astfel de rezolvare ar arata cam asa (pseudo-C):\r\n\r\n== code(cpp) |for (dir =0; dir < 8; dir++)\r\n    lst[0].add(starti,startj,dir,0);\r\ncurrent_cost = 0;\r\nwhile (lst[0].size()+lst[1].size()+lst[2].size>0){\r\n    while (lst[curent_cost % 3].size()>0) {\r\n        x = lst[curent_cost % 3].pop();\r\n        expand(x);\r\n    }\r\n    curent_cost++;\r\n}\r\n==\r\n\r\nAm folosit numai trei liste pentru ca am tinut cont de optimizarea precizata mai sus de a nu folosi numai curbele la $0$ grade, $45$ grade si $90$ grade. Fiecare nod poate fi expandat o singura data, si poate fi introdus in liste de cel mult trei ori, deci o astfel de solutie are complexitatea ca timp si ca spatiu {$O(N*M)$}. Mergand mai departe pe aceasta idee putem obtine o rezolvare putin mai buna care injumatateste timpul de executie. Costurile au fost alese intr-un mod particular permitand ca o curba de $90$ de grade sa aiba acelasi cost cu doua curbe de {$45$}, una de $135$ acelasi cost ca trei de $45$ si una de $180$ acelasi cost ca si patru de {$45$}. Astfel putem modifica rezolvarea noastra si sa facem numai miscarile urmatoare: rotiri de $45$ de grade pe loc si miscari in fata pe directia de mers. Astfel procedura de expandare actualizeaza numai trei noduri si in cursul procedurii de actualizare putem sa lucram numai cu lista curenta si cu lista urmatoare, pentru ca efectuam numai miscari de cost zero si unu. Aceasta observatie a micsorat numarul de liste si a micsorat numarul de calcule din metoda expand, cea mai frecvent utilizata in algoritm. O astfel de rezolvare ar fi adus punctajul maxim pe aceasta problema. Mentionam ca toate observatiile facute nu ar fi fost neaparat necesare pentru obtinerea unui punctaj maxim. Testele au fost facute in vederea obtinerii a $50$ de puncte folosind cautare in latime simpla, $60-70$ de puncte folosind Dijkstra cu heapuri si $90-100$ de puncte folosind penultima rezolvare.\r\n\r\nh2. Clasele 11-12\r\n\r\nh3. Clasament\r\n\r\n==Rankings(rounds=\"preoni52b\" display_entries=\"7\" pager_style=\"none\")==\r\n\r\nClasamentul la 11-12 este dominat de echipa ACM care a reusit sa rezolve toate cele 3 probleme (pe unul din cele doua conturi). Este de remarcat faptul ca primii $5$ clasati au punctaje peste $200$ de puncte.\r\n\r\nh3. Indep\r\n\r\nProblema se poate rezolva in mai multe moduri. Limitele au fost alese astfel incat problema sa fie cat mai usoara. Vom prezenta cele doua solutii pe care le puteti gasi interesante:\r\n\r\nh4. Solutia 1\r\n\r\nPrima solutie, si cea mai simpla, utilizeaza principiul programarii dinamice. Se calculeaza numarul de subsiruri din primele $i$ elemente care sunt divizibile cu un numar $j$ intre $1$ si {$1000$}. Sa notam acest numar cu {$Cnt{@[@}i{@][@}j{@]@}$}. Se obtine urmatoare recurenta pentru calculul acestor valori:\r\n\r\n== code(cpp) |Cnt[i][cmmdc(j, A[i])] = Cnt[i - 1][j] + Cnt[i - 1][cmmdc(j, A[i])]\r\n==\r\n\r\nOdata calculate aceste valori solutia o vom avea in {$Cnt{@[@}N{@][@}1{@]@}$}. Numerele depasesc orice tip de date predefinit si trebuie utilizate numere mari. Limitele fiind destul de mari, folosirea bazei $10$ este periculoasa, pe unele teste fiind necesar folosirea bazei $10^9^$ pentru a reduce timpul de executie. De asemenea si memoria se poate reduce, observand faptul ca pentru a calcula {$Cnt{@[@}i{@][@}j{@]@}$} ne sunt necesare doar valorile pentru {$Cnt{@[@}i-1{@][@}k{@]@}$} (ultimele doua linii). Complexitatea acestei solutiei va fi $O(N * K * L)$ unde $K$ reprezinta valoarea maxima din sir si $L$ lungimea maxima a numerelor mari.\r\n\r\nh4. Solutia 2\r\n\r\nCea de-a doua solutie, cu mult mai interesanta decat prima, foloseste principiul includerii se excluderii. Fie $D(x)$ multimea numerelor din sir care sunt divizibile cu un anumit numar {$x$}, atunci numarul de submultimi formate doar din astfel de numere este {$Z(x) = 2^card(D(x))^-1$}. Multimile pentru principiul includerii si excluderii sunt chiar {$D(p)$}, unde $p$ este un numar prim. Intersectia {$D(p{~1~})$}, {$D(p{~2~})$}, {$D(p{~3~})$}.. este {$D(p{~1~} * p{~2~} * p{~3~}...)$}, oarecum evident, pentru $p$ distincte. Rezultatul este de forma:\r\n\r\n== code(cpp) |Rezultat = Z(1) - Z(2) - Z(3) - Z(5)... +\r\n           Z(2 * 3) + Z(2 * 5) + Z(3 * 5)... -\r\n           Z(2 * 3 * 5) ...\r\n==\r\n\r\nAcesta se deduce din principiul includerii si al excluderii. Pentru a-l calcula efectiv, luam toate numerele {$x < 1000$}, produs de numere prime distincte, si vom adauga sau scadea $Z(x)$ in functie de paritatea numarului de factori ai acestuia. Nu ne intereseaza decat produsele de numere prime distincte, care pot fi obtinute ca un produs {$p{~1~}*p{~2~}*p{~3~}$}... Complexitatea finala este sub {$O(N*K + N*L)$}, unde $K$ si $L$ au semnificatia de mai sus. Folosim $O(N*K)$ pentru a calcula $D(x)$ pentru fiecare {$x$}, dar pentru fiecare $x$ adunam sau scadem $Z(x)$ o singura data, asa ca facem doar $N$ operatii pe numere mari, o imbunatatire majora asupra primei rezolvari. Pentru a obtine aceasta complexitate este nevoie sa precalculam valorile lui $2^x^$ in {$O(N * L)$}, altfel ca sa calculam $Z(x)$ pentru fiecare ar fi nevoie de $O(L * X)$ timp.\r\n\r\nh3. Cerere\r\n\r\nProblema este de dificultate medie. O rezolvare $O(N*lg(N))$ este usor de gasit, fiind asemanatoare cu una deja exista in arhiva, \"Stramosi\":http://infoarena.ro/problema/stramosi. Dar o astfel de rezolvare n-ar fi adus punctaj maxim in mod normal. Problema se poate rezolva printr-o simpla parcurgere in adancime din radacina implementand manual stiva DF-ului. Cand vom pune un nod $n$ pe pozitia $p$ in stiva, al {$K$}-lea stramos va fi nodul de pe pozitia $p-K$ din stiva, pentru care s-a procesat deja valoarea ceruta. Complexitatea finala a algoritmului va fi {$O(N)$}.\r\n\r\nh3. Rubarba\r\n\r\nAceasta problema e clasica in geometria computationala. O prima observatie care ne ajuta in rezolvare este ca numai punctele de pe infasuratoarea convexa influenteaza forma dreptunghiului minim. Deci primul pas in rezolvarea problemei este sa gasim infasuratoarea convexa a punctelor in {$O(N*lg(N))$}. Daca avem fixata o directie atunci e usor sa determinam in $O(h)$ (unde $h$ e numarul de puncte de pe infasuratoarea convexa) cele patru puncte ce marginesc dreptunghiul dupa directia aleasa si dupa directia perpendiculara. Folosind cautare binara pentru a determina cele patru puncte extreme, reducem astfel complexitatea la {$O(lg(h))$}. Observatia finala este ca un dreptunghi de arie minima ce contine o multime de puncte in interior trebuie sa aiba o latura paralela cu una din laturile infasuratorii convexe, aceasta idee este intuitiva dar demonstratia ei nu este foarte simpla. Complexitatea algoritmului ce rezolva problema poate fi $O(N*lg(N) + h^2^)$ sau $O(n*lg(n) + h*lg(h))$ daca folosim cautarea binara. Testele folosite au fost generate aleator, generand aleator puncte in plan infasuratoarea convexa va avea cardinalul $h$ teoretic egal cu {$&#920;(lg(N))$}, deci rezolvarea $O(N*lg(N) + h^2^)$ ar fi luat fara probleme punctaj maxim. Mentionam ca exista o tehnica numita \"Rotating Calipers\" care rezolva aceasta problema si altele similare in {$O(N*lg(N) + h)$}, daca vreti sa cititi despre aceasta tehnica accesati \"pagina\":http://cgm.cs.mcgill.ca/~orm/rotcal.html. Idei de acolo v-ar fi ajutat sa rezolvati problema propusa recent la \".campion\":http://campion.edu.ro/index.php, care cerea separarea a doua poligoane convexe cu o dreapta, si o prolema propusa anul trecut la Bursele Agora care cerea determinarea distantei maxime ce exista intre oricare doua puncte dintr-o multime, si tot pe acea pagina gasiti demonstratia matematica a faptului ca dreptunghiul de arie minima ce contine in interior o multime de puncte are o latura paralela cu o latura a infasuratorii convexe.\r\n\r\nh2. Incheiere\r\n\r\nPana la urmatorul concurs, BAFTA LA OJI!\r\n\r\n',3997,'public',NULL,NULL),('template/infoarena','template/infoarena','2006-11-27 00:34:41','2006-11-27 00:35:58','Special infoarena template\r\n\r\n== Gallery(page=\"template/infoarena\" file=\"%\") ==',13,'protected',NULL,NULL),('preoni-2006/program','Program, preONI 2006','2006-11-26 04:45:25','2006-11-27 16:14:30','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Program\r\n\r\nConcursul este structurat in 3 grupe dupa cum este precizat si in regulament. Acest lucru se datoreaza structurarii similare care se practica la Olimpiada Nationala de Informatica. Concursul va fi impartit in 4 etape online si la sfarsit primii 10 participanti la fiecare grupa conform clasamentului se vor califica la etapa finala on-site a concursului.\r\n\r\nh2. Etapele Online\r\n\r\nSubiectele vor fi atent alese de o echipa de specialisti in domeniu cu experienta vasta in concursuri. Acestea vor fi similare ca dificultate cu cele date la ONI in anii prcedenti. Fiecare grupa va avea spre rezolvare cate 3 probleme in 4 ore, oferindu-se un sfert de ora suplimentar pentru ca toti concurentii sa isi trimita sursele.\r\n\r\nIn continuare va vom prezenta programul celor 5 runde ale concursului, cu mentiunea ca pot interveni schimbari in orice moment.\r\n\r\n|_. Runda  |_. Logo |_. Data |_. Pagina rundei, cu detalii |\r\n| #1 | !preoni-2006/program?runda1.jpg 50%! | 19 noiembrie 2005 | \"Runda 1\":preoni-2006/runda-1 |\r\n| #2 | !preoni-2006/program?runda2.jpg 50%! | 17 decembrie 2005 | \"Runda 2\":preoni-2006/runda-2 |\r\n| #3 | !preoni-2006/program?runda3.jpg 50%! | 21 ianuarie 2006  | \"Runda 3\":preoni-2006/runda-3 |\r\n| #4 | !preoni-2006/program?runda4.jpg 50%! | 19 februarie 2006 | \"Runda 4\":preoni-2006/runda-4 |\r\n|Finala| !preoni-2006/program?runda5.jpg 50%! | 24-26 martie 2006 | \"Runda finala\":preoni-2006/finala |\r\n\r\nh2. Runda finala\r\n\r\nEtapa finala se va desfasura in cadrul unei tabere intr-o locatie care va fi stabilita in curand. Cei care nu se vor califica la runda finala vor putea participa on-line pe info-arena la aceasta proba. Pentru mai multe detalii faceti click aici. \r\n\r\n==include(page=\"template/preoni-2006/footer\")==\r\n',13,'public',NULL,NULL),('colaboratori-infoarena','Colaboratori infoarena','2006-11-27 08:32:10','2006-11-27 08:32:10','h1. Colaboratori\r\n\r\n==include(page=\"template/todo\")==\r\n\r\n_(aici trebuie sa punem un macro cu atribute/tags de utilizatori)_\r\n',13,'public',NULL,NULL),('contact','Contact','2006-11-27 08:42:57','2010-02-16 19:12:23','h1. Contact\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nCel mai usor poti lua legatura cu noi pe ==SmfLink(link=\"forum\" caption=\"forum\")==. Aici ne gasesti pentru intrebari, sugestii, probleme.\r\nPe forum discutam despre articolele si despre problemele de pe site. *Chiar si in timpul concursurilor online, intrebarile catre comisie se adreseaza pe forum*.\r\n\r\nPentru sponsorizari, detalii despre activitatea noastra etc. trimite un e-mail la @contact@infoarena.ro@ .',1490,'public',NULL,NULL),('summer-challenge-3/solutii','Solutii - Summer Challenge Trei','2006-08-27 00:00:00','2007-06-04 18:14:54','h1. Solutii - Summer Challenge Trei\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa Infoarena_)\r\n\r\nh2. ABC\r\n\r\nProblema se reduce la $3$ cazuri, in functie de cum este $C$ fata de suma termenilor sirului {$A$}. Daca aceste numere sunt egale, sirul $D$ cautat este chiar sirul {$A$}. In caz contrar, vom rezolva problema pentru $C$ mai mare, celalalt caz fiind analog. Va trebui deci sa marim cateva dintre elementele lui {$A$}. O observatie este utila in acest moment: daca {$A{~i~}<A{~j~}$}, atunci exista o solutie optima cu {$D{~i~}<D{~j~}$}. Pentru a demonstra aceasta afirmatie, observati ca in caz contrar, interschimband valorile $D{~i~}$ si $D{~j~}$ se obtine o solutie pentru care suma termenilor lui $D$ este aceeasi, dar valoarea maxima a sirului din enunt (pe care o vom numi in continuare {$delta$}) este mai mica, sau in cel mai rau caz egala.\r\n\r\nSa incercam acum sa obtinem un sir $D$ pentru o valoare fixata a lui {$delta$}. Pornim cu sirul $D$ egal cu cel initial, {$A$}. Atat timp cat suma termenilor lui $D$ este mai mica decat $C$ vom aplica urmatoarea operatie: vom mari cu o unitate un termen al lui {$D$}. Mai trebuie avut grija ca tot timpul sa fie respectata conditia {$D{~i~} &le; A{~i~}+delta$}. Daca nu mai putem aplica nici o operatie (toti termenii au atins valoarea maxima posibila, sau prin marire am obtine o diferenta mai mare decat {$delta$}), si inca nu am obtinut {$C$}, nu putem gasi nici un sir $D$ pentru acest {$delta$}, si in plus am obtinut un sir $D$ cu suma termenilor maxima posibila pentru valoarea curenta a lui {$delta$}. Se poate demonstra ca nici nu conteaza ce termen marim, atat timp cat respectam observatia din paragraful anterior. Pentru a obtine insa o complexitate liniara la acest pas, vom mari termenii in ordine descrescatoare (evident dupa o sortare initiala). Bineinteles, nu este nevoie sa aplicam fiecare operatie in parte, ele vor fi aplicate toate in acelasi timp. Pentru cazul analog din paragraful precedent, o operatie va consta din scaderea unui termen cu o unitate, pornind de data aceasta de la cel mai mic.\r\n\r\nIn plus, daca marim valoarea lui $delta$ la {$delta+1$}, putem aplica in continuare operatii asupra lui {$D$}, de unde am ramas la pasul precedent, obtinand deci sume mai mari. Se contureaza acum o rezolvare: putem cauta binar valoarea lui {$delta$}. Daca am obtinut un sir $D$ care sa respecte conditiile din enunt, putem cauta un $delta$ mai mic, daca nu, trebuie sa marim {$delta$}. Complexitatea algoritmului rezultat este {$O( N log N)$}.\r\n\r\nDupa sortarea sirului {$A$}, putem obtine un algoritm liniar rafinand solutia de mai sus. Aceasta afirmatie se bazeaza pe urmatoarea observatie (presupunem sirul $A$ sortat in ordine descrescatoare): daca putem creste $A{~i~}$ cu valoarea {$d$}, atunci putem creste cu valoarea $d$ orice {$A{~j~}$}, cu {$j > i$}. Vom parcurge valorile lui $A$ in ordine crescatoare a indicilor. La pasul $i$ ({$i$} ia valori intre $1$ si {$N$}) ne folosim de valorile {$D{~i-1~}$}(convenim ca {$D{~0~}=B$}) si $S$ (numarul de unitati cu care mai trebuie marita suma in continuare) si vom creste pe $A{~i~}$ cu valoarea {$d=min(D{~i-1~}-A{~i~}, ceil(S/(N-i+1)))$}. Bineinteles, la pasul urmator si $S$ va scadea corespunzator.\r\n\r\nh2. Oras\r\n\r\nSa presupunem ca avem o solutie pentru $N-2$ noduri. Acum adaugam la solutie nodurile {$N-1$}, si {$N$}. Fara a restrange generalitatea putem orienta strada ({$N-1, N$}) de la {$N-1$}, la {$N$}. Acum oricare ar fi un nod $X$ de la $1$ la $N-2$ trebuie sa fie pe un circuit de $3$ noduri cu nodurile $N-1$ si {$N$}. Astfel putem fixa ca de la nodurile ${1, 2, ..., N-2}$ sa plece arce inspre nodul {$N-1$}, si de la nodul $N$ sa plece arce inspre nodurile {${1, 2, ..., N-2}$}. Daca graful initial cu $N - 2$ noduri satisfacea conditiile problemei, atunci si graful obtinut este valid. Pentru $N = 3$ exista o solutie triviala, pentru $N = 4$ putem demonstra ca nu exista solutie (demonstratia trebuind sa ia in calcul mai multe cazuri), sau putem sa generam exhaustiv toate grafurile turneu cu $N = 4$ si sa observam ca nici unul nu e valid. Gasirea unei solutii pentru $N = 6$ este destul de facila (autorului i-a luat $2$ minute). Astfel am aratat ca avem solutie pentru toate cazurile din problema, inafara cazului {$N = 4$}. Complexitatea acestei solutii este {$O(N^2^)$}.\r\n\r\nh2. Gold\r\n\r\nSolutia triviala este {$O(N^3^)$}: se aleg doua puncte si se verifica suma cantitatilor din ambele parti ale dreptei printr-o parcurgere noua a punctelor. O astfel de solutie obtine $30-40$ de puncte. Pornind de la aceasta idee se poate rafina ajungand la o complexitate de {$O(N^2^logN)$}. Pentru fiecare punct $P$ sortam celelalte $N-1$ puncte dupa unghiul polar ( unghiul format de punctul curent cu axa Ox, daca consideram originea in punctul {$P$}) in {$O(NlogN)$}. Notam cu {$S{~i~}$} suma cantitatilor din primele $i$ mine in ordinea ordonarii dupa unghi. Vom fixa o dreapta de baleiere care sa treaca prin punctul $P$ si prin primul punct in ordinea sortarii. Daca am calculat la un anumit pas toate punctele aflate de o parte a dreptei de baleiere, in momentul in care rotim dreapta de baleiere pana ajunge in dreptul urmatorului punct (in ordinea sortarii) toate aceste puncte raman de aceeasi parte mai putin cel aflat pe dreapta si eventual se vor adauga unele noi. De aceea vom incepe cautarea ultimului punct aflat in sensul $+$ al dreptei de baleiere de la punctul calculat la pasul anterior( toti indicii vor fi calculati modulo {$N$}). Fiecare punct va fi parcurs de cel mult doua ori, deci complexitatea acestui pas este {$O(N)$}. Astfel vom putea calcula in $O(1)$ sumele de o parte si de alta a dreptei folosindu-ne de vectorul {$S$}.\r\n\r\n',4452,'public',NULL,NULL),('blog/autumn-warmup-2006','Autumn WarmUp 2006','2006-09-05 00:00:00','2007-01-27 19:55:02','h1. Autumn WarmUp 2006\r\n\r\nInfoarena organizeaza inca un concurs vacanta asta pentru a te mentine in forma. De data aceasta, echipa infoarena \"a predat stafeta\", si da o sansa celor mai dedicati utilizatori sa realizeze propriul lor concurs - un concurs facut de utilizatori pentru utilizatori.\r\n\r\nSe vor propune spre rezolvare $5$ subiecte cu grade diferite de dificultate, de la accesibil la dificil. Evaluatorul va fi pornit pe toata durata concursului.\r\n\r\nProblemele vor fi propuse de:\r\n\r\n* ==user(user=\"PaulDB\" type=\"tiny\")==\r\n* ==user(user=\"vladcyb1\" type=\"tiny\")==\r\n* ==user(user=\"vladut\"  type=\"tiny\")==\r\n* ==user(user=\"devilkind\"  type=\"tiny\")== \r\n* ==user(user=\"VladSaveluc\"  type=\"tiny\")==\r\n\r\nSperam ca si acest concurs va fi un succes si va asteptam in numar cat mai mare.',75,'protected',NULL,NULL),('template/newround/clasament','Clasament %round_id%','2006-11-23 00:06:53','2010-03-28 09:13:40','h1. Clasament ==roundparam(round_id=\"%round_id%\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"%round_id%\" detail_task=\"true\")==',1490,'protected',NULL,NULL),('aplicatii-ale-cautarii-binare','Aplicatii ale cautarii binare','2004-12-20 00:00:00','2009-02-20 01:14:39','h1. Aplicatii ale cautarii binare\r\n\r\n(Categoria _Tehnici de programare_, Autor _Andrei Teodorescu_)\r\n\r\nVoi prezenta in articolul care urmeaza cateva aplicatii ale cautarii binare. Algoritmii descrisi nu sunt intotdeauna optimi insa prezinta avantajul implementarii mult mai rapide, lucru care constituie un avantaj pe timp de concurs.\r\n\r\n# Sa se gaseasca (daca exista) cel mai mic numar natural $N$ astfel incat {$N!$} sa se termine in exact $p$ cifre de {$0$}, {$p &le; 10^18^$}\r\n# Se considera un teren de forma dreptunghiulara reprezentat de o matrice {$NxN$} care contine in pozitia ({$i,j)$} $1$ daca aceasta este accesibila sau {$0$}, altfel. Se dau $2$ puncte (x{~1~},y{~1~}) si (x{~2~},y{~2~}). Sa se afisize latura maxima a unui patrat care poate fi deplasat intre cele 2 puncte astfel incat acesta sa se afle in orice moment al deplasarii numai pe teren _bun_ (numai cu cifre de {$1$}).\r\n# Sa se calculeze cel mai lung subsir crescator al unui sir de $N$ numere.\r\n# Sa se calculeze cu precizie de $Z$ zecimale: \r\n## radicalul unui numar mare\r\n## catul a $2$ numerere mari (consideram un numar mare un numar cu cel putin $20$ de cifre, care nu poate fi stocat in tipuri de date conventionale)\r\n\r\nIn prima problema trebuie sa observam prima oara ca numarul de zerouri in care se termina {$N!$} creste odata cu {$N$}, observatie evidenta datorita definitiei lui {$N!$}. Atunci, putem cauta binar valoarea lui $N$ pentru care se verifca relatia din enunt. Recomand problema \"Factorial\" din arhiva de probleme InfoArena celor interesati de implementarea algoritmului.\r\n\r\nPentru a doua problema este usor de aratat ca daca daca se poate deplasa intre cele $2$ puncte un patrat de latura {$l$}({$l &ge; 2$}), atunci sigur se va putea deplasa si unul de latura $l-1,l-2...1$ iar daca nu putem deplasa un patrat de latura {$l$}, atunci nu putem deplasa nici unul de latura {$l+1,l+2...n$}. Astfel avem de cautat o valoare $l$ astfel incat putem deplasa un patrat de latura $l$ insa nu si unul de latura {$l+1$}. Numarul $l$ va fi chiar rezultatul cautat. Pentru a face verificarea daca putem deplasa un patrat de o latura data putem folosi algoritmul lui Lee, care implementat atent va avea o complexitate de {$O(n^2^)$}.\r\n\r\nNu voi insista prea mult asupra algoritmului de aflare a celui mai lung subsir crescator al unui sir, problema fiind cunoscuta, de asemenea se gaseste si in cartea \"Psihologia concursurilor de informatica\" de Catalin Francu. Idee de baza este sa se caute binar de fiecare data pozitia fiecarui element intr-un subsir crescator cat mai lung.\r\n\r\nPentru calcularea radicalului unui numar sau calcularea catului a doua numere se cunosc inca din gimnaziu algoritmi! :) Insa acesti algoritmi sunt destul de greu de implemantat(si oricum ajung la un moment dat la folosirea cautarii binare). Asadar in loc de a calcula rezultatul il putem cauta. De exemplu, in primul caz vom cauta o valoare a lui $n$ pentru care $n*n$ sa nu depaseasca numarul dat, insa $(n+1)*(n+1)$ sa depaseasca. Asemanator se procedeaza si in cazul impartirii.\r\n\r\nPentru utilizarea acestor doi algoritmi trebuie ca cel care ii scrie sa stapaneasa foarte bine inmultirea, adunarea, compararea si, eventual, impartirea la $10$ a numerelor mari (vezi articolul de pe site :D). Pentru a obtine o precizie de $z$ zecimale se inmulteste numarul dat(in primul caz)cu $10^2*z^$ si deimpartitul(in al doilea caz) cu $10^z^$ iar in rezultatul obtinut ultimle z cifre vor fi zecimalele iar restul, partea intreaga.\r\n\r\nCa observatie, trebuie sa aveti grija intotdeauna cand alegeti intervalul in care se face cautarea pentru a fi siguri ca algoritmul va produce rezultatlul dorit!\r\n\r\nIn final invit cititorii sa rezolve cateva probleme cu ajutorul cautarii binare:\r\n\r\n* problema \"Proc\":http://www.infoarena.ro/problema/proc, ONI 2003, clasele XI-XII\r\n* problema \"Stramosi\":http://www.infoarena.ro/problema/stramosi din arhiva de probleme InfoArena ( indicatie: se realizeaza o parcurgere Euler si o parcurgere in latime a arborelui iar apoi se cauta ficare nod cerut pe nivelul pe care se afla)\r\n* problema \"Loto\":http://www.infoarena.ro/problema/loto din arhiva de probleme InfoArena\r\n* problema \"Secventa 3\":http://www.infoarena.ro/problema/secv3 din arhiva de probleme InfoArena\r\n* problema \"Tabara\":http://www.liis.ro/~campion/problems/2/96/tabara.htm\r\n* problema \"Multiplu\":http://www.liis.ro/~campion/problems/1/172/multiplu.htm\r\n* problema \"Impartire in trei\":http://www.algoritmus.org/probleme/Probleme_Runda02.php (Algoritmus, Runda 2, Problema 1)\r\n* problema \"Suma\":http://www.algoritmus.org/probleme/Probleme_Runda05.php (Algoritmus, Runda 5, Problema 5)\r\n\r\n',2044,'public',3697,NULL),('blog/bits-n-bytes','Bits \'n\' Bytes ','2005-02-07 00:00:00','2005-02-07 00:00:00','h1. Bits \'n\' Bytes \r\n\r\nInca un consurs de programare indian. Concursul se desfasoara pe 2 martie si dureaza 24 de ore, si e individual. Detalii mai multe pe \"site-ul oficial\":http://showcase.csa.iisc.ernet.in/bitsnbytes/index.html.\r\n',1142,'protected',NULL,NULL),('bacalaureat-2005','Bacalaureat 2005','2006-11-23 21:08:54','2006-11-25 01:47:12','h1. Bacalaureat 2005\r\n\r\nArhiva contine subiecte de bacalaureat propuse de mai multi profesori de informatica din tara. \r\n\r\nToate subiectele dispun de un evaluator online 24/7!\r\n\r\nSucces!\r\n\r\nh2. \'Clasament\':bacalaureat-2005/clasament\r\n\r\n!>bacalaureat-2005?logo.gif!\r\n\r\n== Tasks(round_id=\"bac2005\" pager_style=\"none\") ==\r\n',961,'protected',NULL,NULL),('preoni-2006/finala/poze','Poze finala preONI 2006','2006-11-25 15:01:34','2006-11-27 16:09:06','==Include(page=\"template/preoni-2006/header\")==\r\n\r\nh1. Poze finala preONI 2006\r\n\r\n== Gallery(page=\"preoni-2006/finala/poze\" file=\"%.jpg\") ==',13,'protected',NULL,NULL),('preoni-2006/runda-1/clasament-11-12','Clasament preoni61c','2006-11-25 01:17:08','2006-11-25 01:17:08','h1. Clasament ==roundparam(round_id=\"preoni61c\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni61c\")==',961,'protected',NULL,NULL),('template/cleanup','template/cleanup','2006-11-11 15:05:08','2008-02-04 20:59:07','table{margin:0.5em auto;}. |={background-color:#FFFFCC;border:1px solid FFCC66;}. !<template/cleanup?cleanup.png! _Continutul acestei pagini nu este formatat conform_ \'*recomandarilor de formatare*\':documentatie/conventii-de-formatare.\r\n_Daca aveti permisiunile necesare, va rugam sa il imbunatatiti._  |\r\n\r\n',1,'protected',NULL,NULL),('testgal','Test Gallery','2006-12-04 09:12:05','2006-12-04 09:15:12','h1. Test Gallery\r\n\r\n==gallery(page=\"testgal\" file=\"%.jpg\")==',13,'public',NULL,NULL),('doua-probleme-de-la-runda-6-a-concursului-algoritmus','Doua probleme de la runda 6 a concursului Algoritmus','2005-01-13 00:00:00','2006-11-22 02:18:26','h1. Doua probleme de la runda 6 a concursului Algoritmus\r\n\r\n(Categoria _Competitii_, autor(i) _Cosmin_)\r\n\r\nDupa incheierea brusca a concursului Algoritmus, ideile de rezolvare ale rundei 6 nu au mai aparut pe site. In acest articol va voi prezenta ideile de rezolvare la problemele la care eu am realizat solutiile oficiale.\r\n\r\nh2. Problema 1: Suprafata\r\n\r\nPentru a rezolva problema folosim paradigma liniei de baleiere folosita mult in rezolvarea problemelor de geometrie computationala (vezi si articolul arbori de intervale din sectiunea download pt alte exemple de probleme in care se foloseste linia de baleiere). Vom considera ca puncte eveniment toate punctele de intersectie intre oricare doua cercuri si punctele de $y maxim$ si de $y minim$ pentru un cerc. Noi avem nevoie numai de coordonata $y$ a acestor puncte pe care o punem intr-un sir. Sortam acest sir ce are maxim $n*(n-1) + 2*n$ coordonate distincte ( $n*(n-1)$ provin din intersectii a cate doua cercuri iar celelalte $2*n$ din $y maxim$ si $y minim$ pentru fiecare cerc). Intre doua coordonate $Y$ consecutive din vectorul sortat nu exista nici o intersectie intre cercuri. Intersectia unui cerc cu o banda determinata de $Y{~i~}$ si $Y{~i+1~}$ este un fel de trapez curbat pe care ni-l putem imagina ca o paranteza deschisa si una inchisa. Pentru a determina aria intersectiei multimii de cercuri cu banda determinata de $Y{~i~}$ si $Y{~i+1~}$ putem sa facem un algoritm care sorteaza intai \"parantezele\" si dupa aceea parcurge sirul sortat al parantezelor. Cand nivelul de imbricare e $0$ inseamna ca tocmai am iesit din cercuri iar nivel de imbricare mai mare ca $0$ inseamna ca suntem in interiorul intersectiei. De aici scoatem un algoritm liniar care ne determina intersectia cercurilor cu aceasta banda. Pentru a determina aria ocupata de un trapez curbat trebuie sa putem determina aria dintre coarda si arcul de cerc corespunzator, aceasta arie se poate gasi daca stim unghiul $alfa$ ce se opune coardei pentru ca aceasta arie e diferenta dintre aria sectorului de cerc ( {$r*r*alpha/2$}) si aria triunghiului format dintre centrul cercului si coarda ({$r*r*sin alpha /2$}), unghiul $alpha$ il aflam folosind functia $arccos$ si $cos alpha$ il determinam cu ajutorul teoremei lui Pitagora generalizate. O mica problema apare in sortarea parantezelor pentru ca daca parantezele provin din cercuri diferite dar le corespunde aceeiasi coarda atunci trebuie sa fim atenti la ordinea in care punem parantezele. Aceasta problema e rezolvata daca gasim un $X3$ pentru fiecare coarda numar ce reprezinta coordonata $X$ a intersectiei parantezei repsective cu linia orizontala de ordonata {$(Y{~i~} + Y{~i+1~}) / 2$}. Am aratat astfel cum se realizeaza determinarea ariei reuniunii cercurilor cu o banda ce nu contine nici o intersectie in {$O(n log n)$}. Din cauza faptului ca sunt in total maxim $O(n^2^)$ benzi repetand algoritmul pe fiecare banda obtinem aria reuniunii\r\ncercurilor in timp {$O(n^3^ log n)$}.\r\n\r\nh2. Problema 4: Joc\r\n\r\nProblema cere determinarea numarului maxim de drumuri disjuncte relativ la noduri pornind de la nodul $A$ si terminandu-se in nodul {$B$}. Daca ar fi restrictia numai pentru muchii nu si pentru noduri atunci raspunsul ar fi egal cu fluxul maxim in reteaua de transport formata astfel: sursa e nodul {$A$}, destinatia e nodul $B$ iar orice muchie ({$i,j$}) din graful initial e dublata in reteaua de transport ({$i,j$}) si ({$j,i$}) fiecare muchie avand capacitate {$1$}. Acesta afirmatie e intiutiva, o demonstratie matematica a ei ar fi aplicarea teoremei clasice: fluxul maxim intr-o retea reziduala este egala cu taietura minima in acea retea si a teoremei lui Menger: numarul maxim de drumuri disjuncte relativ la muchii de la $S$ la $T$ este egal cu taietura minima.\r\n\r\nProblema noastra mai are insa o dificultate, aceea ca trebuie sa nu avem acelasi nod in doua drumuri diferite. Aceasta problema o rezolvam dubland fiecare nod si muchiile ce intrau in nod intra acum in primul dintre cele doua noduri, muchiile ce ieseau ies acum din al doilea nod si mai adaugam o muchie intre primul nod si al doilea nod. Acum drumurile disjuncte relativ la muchii din aceasta retea corespund unor drumuri disjuncte relativ la noduri in prima retea.\r\n\r\nAstfel am redus problema initiala la una de flux in graf pe graful transformat. Complexitatea algoritmului e {$O(n*m)$}. Implementarea nu mai dubleaza nodurile la propriu ci foloseste {$c{~i,i~}$} pentru a reprezenta muchia intre cele doua noduri ce reprezinta nodul $i$ din graful initial.\r\n\r\n',1,'public',NULL,NULL),('moisil-by-net-2006/clasament-11-12','Clasament moisil4','2006-11-23 21:09:01','2006-11-24 18:25:13','h1. Clasament ==roundparam(round_id=\"moisil4\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil4\")==',961,'protected',NULL,NULL),('utilizator/eval','Profil eval','2006-12-03 21:54:32','2007-02-11 19:35:29','h2. Despre mine\r\n\r\nbq. Vorbesc putin dar \"fac multe\":monitor.\r\n\r\nNu-mi trimite PM-uri ca nu-ti raspund.\r\n\r\nh2. Distinctii -primite- date\r\n\r\nToate punctele pe care le-ati primit pe infoarena vi le-am dat eu.\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n* ==User(user=\"fluffy\" type=\"tiny\")==\r\n* ==User(user=\"azotlichid\" type=\"tiny\")==\r\n* ==User(user=\"chucknorris\" type=\"tiny\")==',18,'protected',NULL,NULL),('blog/articol-taietura-minima','Articol nou: \"Taietura minima in graf cu costuri\"','2007-02-04 08:16:00','2007-02-09 18:21:27','A aparut un articol nou despre \'Taietura minima in graf cu costuri\':taietura-minima scris de Andrei Grigorean.',13,'public',NULL,NULL),('noul-infoarena','Noul site infoarena','2007-02-04 18:59:37','2007-02-04 19:01:59','h1. Noul site infoarena \r\n\r\ntable(layout3). | *infoarena este un wiki*\r\nSchimba continutul paginilor sau sa creaza pagini noi.\r\n\'Afla mai multe&hellip;\':documentatie/wiki\r\n| *infoarena iti da rating*\r\nIti calculam rating-ul: un numar care reflecta performantele tale.\r\n\'Afla mai multe&hellip;\':documentatie/rating\r\n| *Forum integrat*\r\nAm avut grija ca forum-ul sa fie bine integrat in experienta infoarena.\r\n\'Afla mai multe&hellip;\':documentatie/forum |\r\n| *Fa-ti pagina personala*\r\nPrezinta-te comunitatii infoarena: cine esti, de unde vii, distinctii primite etc.\r\n\'Afla mai multe&hellip;\':documentatie/pagina-de-profil\r\n| *Un nou evaluator*\r\nEvaluatorul nou masoara mai exact timpii de executie si suporta tipuri noi de probleme si concursuri.\r\n\'Afla mai multe&hellip;\':documentatie/evaluator\r\n| *Mai usor de folosit*\r\nNoul infoarena este mai usor de navigat si de folosit.\r\n\'Afla mai multe&hellip;\':documentatie/pentru-utilizatori |\r\n\r\nh1. Ne trebuie feedback!\r\n\r\nNe asteptam sa gasim multe bug-uri si deficiente in noua versiune. Ajuta-ne sa facem o infoarena ca _Soarele sfant de pe cer_ :)\r\nAsteptam bug reports, sugestii, intrebari pe forum. Iata niste topic-uri de feedback:\r\n\r\n==SmfTopics(board_id=\"33\")==',1,'protected',NULL,NULL),('preoji-2004/clasament-9-10','Clasament preOJI 2004, clasele 9-10','2006-11-23 21:08:49','2006-11-24 00:12:20','h1. Clasament \'preOJI 2004\':preoji-2004, clasele 9-10\r\n\r\n==Rankings(rounds = \"preoji1\")==',1142,'protected',NULL,NULL),('documentatie/macro-uri','Macro-uri','2006-11-22 20:48:39','2009-01-05 16:33:25','h1. Macro-uri\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\n== include(page=\"template/todo\")==\r\n\r\nMacro-uri sunt niste blocuri speciale de text care sunt tratate \'special\' de wiki-ul infoarena. Cu macro-uri se pot face foarte multe lucruri, de la linkuri catre utilizatori pana la tabele de scoruri.\r\n\r\nh2. Sintaxa\r\n\r\nMacro-uri sunt introduse cu o sintaxa de genul @==User(user=\"domino\" type=\"tiny\")==@, si se obtine ==User(user = \"domino\" type=\"tiny\")==. Momentan sintaxa de macro-uri este *foarte* stricta, dar poate cu timpul va fi \"relaxata\". Atentie:\r\n\r\n* Numele macro-urilor nu sunt case-sensitive.\r\n* Parantezele, egalul si ghilimele sunt obligatorii.\r\n* Nu se accepta parameteri dubli sau virgule intre parametetri.\r\n\r\nh2. Macro-uri comune:\r\n\r\n* debug\r\n* gallery\r\n* grep\r\n* hello\r\n* image?\r\n* include\r\n* rankings\r\n* tableofcontents\r\n* tasks\r\n* user\r\n* SmfTopic\r\n* SmfTopics\r\n\r\n*todo* Cum se folosesc / ce fac macro-urile de mai sus? Care dintre ele chiar exista? :)\r\n\r\nh2. Propune si tu un macro!\r\n\r\nDaca iti doresti un macro nu trebuie decat sa ne ceri si vom incerca sa rezolvam. Poti face o cerere de macro \'aici\':http://hackers.devnet.ro/newticket (\'explicatii\':development).',2934,'public',NULL,NULL),('happy-coding-2006','Happy Coding 2006','2006-11-23 21:09:03','2006-11-24 17:44:58','h1. Happy Coding 2006\r\n\r\nConcursul s-a desfasurat incepand cu ora 10:00, Luni 9 Ocombrie 2006, pana Duminica la ora 22:00, 15 Octombrie 2006. Concurentii au avut la dispozitie o saptamana pentru rezolvarea celor 20 de probleme propuse.\r\n\r\nProblemele au fost propuse in mare parte de Mugurel Ionut Andreica, un set de probleme folosite pentru selectia echipe de ACM a Universitatii Politehnica Bucuresti. La acestea s-au adaugat cateva probleme ale lui Mircea Pasoi, Adrian Vladu si Daniel Pasaila.\r\n\r\nh2. \'Clasament\':happy-coding-2006/clasament\r\n\r\n!>happy-coding-2006?logo.jpeg!\r\n\r\n== Tasks(round_id=\"happy2006\" pager_style=\"none\") ==\r\n',961,'protected',NULL,NULL),('utilizator/koosy','Profil koosy','2006-11-24 20:56:14','2007-02-12 20:39:58','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',35,'protected',NULL,NULL),('utilizator/efer','Profil efer','2006-11-24 20:56:20','2007-02-12 20:39:58','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',83,'protected',NULL,NULL),('utilizator/cavin','Profil cavin','2007-01-15 15:07:54','2007-02-12 20:40:13','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5659,'public',NULL,NULL),('utilizator/oanam','Profil oanam','2006-11-24 20:56:30','2007-02-12 20:39:58','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',165,'protected',NULL,NULL),('utilizator/florinr1','Profil florinr1','2006-11-24 20:56:33','2007-02-12 20:39:58','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',192,'protected',NULL,NULL),('utilizator/mars','Profil mars','2006-11-24 20:56:43','2007-02-12 20:39:58','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',272,'protected',NULL,NULL),('utilizator/amadaeus','Profil amadaeus','2006-11-24 20:56:53','2007-02-12 20:39:59','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',354,'protected',NULL,NULL),('utilizator/rus','Profil Rus','2006-11-24 20:57:08','2007-02-12 20:39:59','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',477,'protected',NULL,NULL),('utilizator/miz','Profil miZ','2006-11-24 20:57:15','2007-02-12 20:39:59','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',530,'protected',NULL,NULL),('utilizator/vasile_gales','Profil vasile_gales','2006-11-24 20:57:17','2007-02-12 20:39:59','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',547,'protected',NULL,NULL),('utilizator/dark_raxvan','Profil Dark_Raxvan','2006-11-24 20:57:26','2007-02-12 20:39:59','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',621,'protected',NULL,NULL),('utilizator/sssilviu','Profil sssilviu','2006-11-24 20:57:40','2007-02-12 20:40:00','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',730,'protected',NULL,NULL),('utilizator/gogu','Profil gogu','2006-11-24 20:57:41','2007-02-12 20:40:00','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',735,'protected',NULL,NULL),('utilizator/fluffy','Profil fluffy','2006-11-24 20:58:35','2009-07-21 08:35:19','h2. Despre mine\r\n\r\nNimic!',1142,'protected',NULL,NULL),('utilizator/master','Profil MASTER','2006-11-24 20:57:58','2007-02-12 20:40:00','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',866,'protected',NULL,NULL),('utilizator/filosofie12','Profil filosofie12','2006-11-24 20:58:11','2007-02-12 20:40:00','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',965,'protected',NULL,NULL),('utilizator/chiru_ramona','Profil chiru_ramona','2006-11-24 20:58:16','2007-02-12 20:40:00','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',999,'protected',NULL,NULL),('utilizator/tm_radu','Profil tm_radu','2006-11-24 20:58:25','2007-02-12 20:40:00','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',1072,'protected',NULL,NULL),('utilizator/fireatmyself','Profil fireatmyself','2006-11-24 20:58:47','2007-03-25 12:36:59','h2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',1231,'protected',NULL,NULL),('utilizator/fucker','Profil fucker','2006-11-24 20:58:53','2007-02-12 20:40:01','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',1277,'protected',NULL,NULL),('utilizator/deni','Profil Deni','2006-11-24 20:58:59','2007-02-12 20:40:01','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',1323,'protected',NULL,NULL),('utilizator/rake','Profil rake','2006-11-24 20:59:19','2007-02-12 20:40:01','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',1452,'protected',NULL,NULL),('utilizator/bianca_ig','Profil bianca_ig','2006-11-24 20:59:47','2007-02-12 20:40:02','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',1654,'protected',NULL,NULL),('utilizator/blitzkrieg','Profil BlitzKrieg','2006-11-24 21:00:22','2007-02-12 20:40:02','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',1900,'protected',NULL,NULL),('utilizator/geo88','Profil geo88','2006-11-24 21:00:29','2007-02-12 20:40:03','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',1944,'protected',NULL,NULL),('utilizator/martinica1','Profil martinica1','2006-11-24 21:00:56','2007-02-12 20:40:03','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2126,'protected',NULL,NULL),('utilizator/uniquee','Profil uniquee','2006-11-24 21:01:30','2007-02-12 20:40:04','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2291,'protected',NULL,NULL),('utilizator/stancosti','Profil stancosti','2006-11-24 21:01:35','2007-02-12 20:40:04','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2324,'protected',NULL,NULL),('utilizator/elutza','Profil elutza','2006-11-24 21:01:35','2007-02-12 20:40:04','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2328,'protected',NULL,NULL),('utilizator/c1506','Profil C1506','2006-11-24 21:01:48','2007-02-12 20:40:04','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2421,'protected',NULL,NULL),('utilizator/paula','Profil paula','2006-11-24 21:02:25','2007-02-12 20:40:05','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2676,'protected',NULL,NULL),('utilizator/con_lena','Profil con_lena','2006-11-24 21:02:38','2007-02-12 20:40:05','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2766,'protected',NULL,NULL),('utilizator/abcd','Profil abcd','2006-11-24 21:02:39','2007-02-12 20:40:05','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2773,'protected',NULL,NULL),('utilizator/colt2005','Profil colt2005','2006-11-24 21:02:49','2007-02-12 20:40:05','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',2842,'protected',NULL,NULL),('utilizator/judy_k','Profil judy_k','2006-11-24 21:03:23','2007-02-12 20:40:06','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3065,'protected',NULL,NULL),('utilizator/diana_c','Profil Diana_C','2006-11-24 21:03:23','2007-02-12 20:40:06','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3066,'protected',NULL,NULL),('utilizator/zait','Profil zait','2006-11-24 21:03:26','2007-02-12 20:40:06','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3086,'protected',NULL,NULL),('utilizator/marius_dumitran','Profil marius_Dumitran','2006-11-24 21:03:34','2007-02-12 20:40:06','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3134,'protected',NULL,NULL),('utilizator/exist3nz','Profil exist3nz','2006-11-24 21:03:39','2007-02-12 20:40:06','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3166,'protected',NULL,NULL),('utilizator/claustan','Profil claustan','2006-11-24 21:03:40','2007-02-12 20:40:06','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3174,'protected',NULL,NULL),('utilizator/mariusdrg','Profil mariusdrg','2006-11-24 21:03:46','2007-02-12 20:40:06','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3219,'protected',NULL,NULL),('utilizator/inkriptor_scn','Profil inkriptor_scn','2006-11-24 21:04:19','2007-02-12 20:40:07','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3434,'protected',NULL,NULL),('voronoi','voronoi','2007-04-18 11:38:16','2008-11-16 12:26:44','h1. Diagrame Voronoi\r\n\r\n(Categoria _Algoritmi_, autor _Catalin Francu_)\r\n\r\nMultumiri lui Mihai Popa care a cotrobait prin arhiva de mesaje si a gasit mesajul de mai jos. El se refera la principiul dualitatii si am adaugat o bucata despre diagramele Voronoi.\r\n\r\nh2. Principiul dualitatii\r\n\r\nDaca tot n-am mai prea trimis probleme, hai sa va impartasesc si voua ceva din adanca intelepciune care mi-a fost bagata cu pompa pe gat la MIT. Scriu sub impulsul momentului, asa ca nu va asteptati la prea multa coerenta.\r\n\r\nIncep cu observatia ca \"Geometrie Computationala\" nu suna prea romaneste, insa pe de alta parte \"Geometrie Analitica\" nu suna prea corect, fiindca nu e totuna cu ce se face (facea?) in clasa a XI-a de liceu.\r\n\r\nSa pornim de la urmatoarea problema: Avem o colectie de N drepte in plan, oricare doua neconfundate, astfel incat nici una din ele nu trece prin origine. Sa se indice care din drepte sunt vizibile din origine.\r\n\r\nUn algoritm decent functioneaza in O(N^2^), astfel: ia fiecare dreapta d~i~, si o intersecteaaza cu fiecare din celelalte drepte d~j~. In acest fel, d~i~ se imparte in doua semidrepte, din care numai una este vizibila din origine, cealalta fiind obturata de catre d~j~. In felul acesta tot intersectam semidrepte peste semidrepte, si vedem daca in final ramanem cu vreun segment vizibil din origine. Desigur, pe parcurs apare tot tacamul de cazuri particulare: drepte verticale, drepte orizontale, erori de calcul, radicali, distante etc. Sper ca v-am scarbit destul ca sa vreti sa aflati si o implementare mai eleganta.\r\n\r\nVom prezenta un algoritm foarte dragut si foarte cunoscut (in final) care rezolva problema in O(N log N). Facem intai urmatoarea conventie. De vreme ce dreptele nu trec prin origine, ele au ecuatii de forma !voronoi?ec1.bmp!, cu !voronoi?ec2.bmp!. Atunci le vom aduce pe toate la forma !voronoi?img1.bmp! (evident, impartind prin c).\r\n\r\nSi-acum sa vedem ce este principiul dualitatii. El asociaza fiecarei drepte de forma !voronoi?img1.bmp! un punct de coordonate (a,b) in plan. Vom numi spatiul dreptelor \"spatiu primal\", iar spatiul punctelor corespunzatoare \"spatiu dual\". De aici decurg o multime de observatii foarte interesante, din care nici eu nu-mi aduc aminte decat cateva:\r\n\r\n# Oricarui punct din spatiul dual ii corespunde o dreapta in spatiul primal, si ce este mai interesant, oricaror doua puncte distincte din spatiul dual le corespund drepte distincte in spatiul primal\r\n# Oricarei drepte din spatiul primal ii corespunde un punct in spatiul dual. Exceptia o constituie dreptele care trec prin origine, pentru ca ele au c=0 si nu pot fi normalizate. Totusi, daca extindem spatiul dual ca sa contina si puncte de la infinit, atunci fiecarei drepte care trece prin origine in spatiul primal ii corespunde un punct de la infinit in spatiul dual. Cu asta, bijectia intre cele doua spatii este completa.\r\n# Sa ne inchipuim acum doua drepte in spatiul primal, care se intersecteaza intr-un punct:\r\n!voronoi?img1.bmp!\r\n!voronoi?img2.bmp!\r\nFie (p,q) punctul lor de intersectie, care are proprietatile:\r\n!voronoi?img3.bmp!\r\n!voronoi?img4.bmp!\r\nSa dualizam acum cele doua drepte. Obtinem punctele (a,b) si (d,e). Sa analizam ecuatia dreptei care trece prin aceste doua puncte:\r\n!voronoi?ec52.bmp!(*)\r\nDar\r\n!voronoi?img8.bmp!\r\nInlocuind asta in (*) si reducand numitorul (e-b) deducem:\r\n!voronoi?img9.bmp!\r\ndar \r\n!voronoi?img10.bmp!\r\ndeci ecuatia dreptei este:\r\n!voronoi?img11.bmp! !!!\r\nCu alte cuvinte, daca dreptele d1 si d2 se taie in punctul P, atunci dualizand totul obtinem punctele dual(d1) si dual(d2), care determina tocmai dreapta dual(P). Asta mai arata si ca nu e obligatoriu ca in spatiul primal sa avem drepte si in spatiul dual sa avem puncte, ci putem dualiza orice, oriunde :).\r\n# La fel se demonstreaza reciproca: doua puncte care determina o dreapta se dualizeaza in doua drepte care se intersecteaza intr-un punct.\r\n# Generalizarea este si mai draguta: Un fascicol de drepte (pentru cei care nu prea dau pe la mate, asta inseamna o colectie de drepte care se intalnesc in acelasi punct) se dualizeaza intr-o multime de puncte, toate coliniare. Se demonstreaza folosind acelasi punct (p,q) pentru toate dreptele.\r\n# Dar o colectie de drepte paralele? O sa radeti, dar se dualizeaza tot intr-o multime de puncte coliniare. Daca nu ma-nsel, dreapta care contine aceste puncte coliniare inteapa originea. Demonstratia se poate face fie prin calcul direct, fie observand ca in fond o colectie de\r\ndrepte paralele este un fascicol de drepte care se intalnesc la infinit (Euclid sa traiasca!)\r\n# Sa luam dreapta !voronoi?img1.bmp!. Daca normalizam dreapta (impartind prin !voronoi?img12.bmp!), aflam ca distanta de la dreapta la origine este !voronoi?img13.bmp!. Dualizand dreapta, obtinem punctul (a,b), care este situat la distanta !voronoi?img12.bmp! de origine. Mai expresiv, daca dreapta este la distanta d de origine, punctul dual este la distanta 1/d de origine. Mai interesant este ca punctul dual, originea si piciorul perpendicularei din origine pe dreapta sunt coliniare. E destul de usor de demonstrat, daca nu v-ati luat inca un creion si o hartie e cazul sa o faceti, altfel cred si eu ca va plictisiti :).\r\n\r\nSi-acum momentul picant, problema de la care am pornit. Luati o multime de drepte care definesc un poligon in jurul originii, deci sunt vizibile din origine. Luati si alte drepte care nu intersecteaza acest poligon, deci nu sunt vizibile din origine. Asemanator figurii de mai sus, dualizati toate aceste drepte. Pentru fiecare dreapta, veti obtine un punct in partea opusa relativ la origine. Punctul este cu atat mai aproape de origine, cu cat dreapta este mai departe de origine.\r\n\r\nDorim sa separam acum dreptele vizibile din origine de celelalte drepte. Sa vedem daca nu putem lucra cumva cu punctele duale. Intuitiv, ce inseamna o dreapta INvizibila din origine? Inseamna o dreapta \"departata\" de origine (in sensul ca alte drepte vor fi mai aproape decat ea si o vor obtura). In limbaj dual, asta inseamna ca punctul dual va fi mai aproape de origine, in sensul ca vor fi alte puncte mai departe decat el.\r\nAsta cred ca deja va sugereaza ideea de rezolvare. Daca v-ati gandit la infasuratoare convexa, ati pus punctul pe y. Algoritmul este urmatorul:\r\n\r\n* Se da multimea de drepte !voronoi?img14.bmp!\r\n* Aducem toate dreptele la forma !voronoi?img15.bmp!, impartind prin c~i~\r\n* Aflam infasuratoarea convexa a multimii de puncte (a~i~,b~i~)\r\n* Punctele de pe aceasta infasuratoare convexa corespund dreptelor vizibile din origine.\r\n\r\nDe ce asa? Pentru ca punctele de pe infasuratoarea convexa sunt cele mai departate de origine, deci dreptele lor duale sunt cele mai apropiate de origine. Va las placerea de a analiza cazurile particulare, de exemplu cele in care multimea de drepte nu defineste un poligon inchis in jurul originii, ci unul deschis (hint: originea nu apartine infasuratorii convexe a punctelor duale).\r\n\r\nO alta tema de gandire este: ce se intampla in cazul limita cand trei sau mai multe puncte sunt coliniare pe infasuratoarea convexa?\r\n\r\nh2. Diagrame Voronoi\r\n\r\nIn primul rand ce sunt alea. Sa consideram un poligon convex (pentru simplitate vom lua un dreptunghi) si n puncte P~1~, P~2~, ..., P~n~ in acel dreptunghi. Poligonul Voronoi al unui punct P~i~ este format din multimea acelor puncte P din dreptunghi care sunt mai aproape de P~i~ decat de orice alt punct P~j~. Impartirea dreptunghiului in poligoane se numeste diagrama Voronoi.\r\n\r\nExemple: \r\nPentru n=1, exista un singur poligon Voronoi care este intregul dreptunghi. \r\nPentru n=2, ducem mediatoarea lui P ~1~ si P ~2~ si o intersectam cu dreptunghiul, obtinand doua poligoane. Punctele din poligonul lui P ~1~ sunt mai aproape de P ~1~ decat de P ~2~ si invers. \r\nPentru n=3, ducem cele trei mediatoare ale segmentelor P ~1~ P ~2~, P ~2~ P ~3~ si P ~3~ P ~1~ . Mediatoarele se intalnesc intr-un punct (cercul cercului circumscris) si le prelungim pana intersecteaza dreptunghiul. Pentru n=3, cand P ~1~ P ~2~ si P ~3~ sunt coliniare, dreptunghiul este sectionat in trei \"felii\".\r\n\r\nSe poate defini diagrama Voronoi si fara constrangerile dreptunghiului, adica pe intregul plan xOy, dar in acest caz poligoanele sunt \"deschise\" (se duc la infinit). In orice caz, nu este greu de demonstrat ca poligoanele Voronoi sunt convexe.\r\n\r\nO metoda \"barbara\" de a afla poligoanele Voronoi porneste de la observatia ca daca duc mediatoarea dintre P ~i~ si P ~j~ , atunci in mod sigur punctele de partea lui P ~j~ nu au cum sa fie in poligonul lui P ~i~ , pentru ca sunt mai aproape de P ~j~ decat de P ~i~ . Dec algoritmul este:\r\n\r\n* Pentru fiecare i afla poligonul lui P ~i~ astfel:\r\n* Porneste cu un poligon egal cu intregul dreptunghi\r\n* Pentru fiecare j<>i\r\n* Intersecteaza poligonul cu mediatoarea lui P ~i~ P ~j~ si \"arunca\" bucata din partea lui P ~j~\r\n* Poligonul ramas este poligonul lui P ~i~\r\n\r\nComplexitatea este O(N^3^), iar numarul de cazuri particulare este mare. In continuare revenim la principiul dualitatii si la problema de mai sus, a vizibilitatii unor drepte dintr-un punct.\r\n\r\nSa ne imaginam punctul Pi inconjurat de n+3 drepte: cele n-1 mediatoare ale segmentelor PiPj si cele 4 laturi ale dreptunghiului. Atunci poligonul Voronoi al lui Pi are drept laturi exact segmentele \"vizibile\" din Pi ale acestor n+3 drepte. Si dupa cum am vazut mai sus, aceasta problema se reduce la infasuratoare convexa. Trebuie avut grija pentru ca in rezolvarea de mai sus a problemei vizibilitatii am presupus ca punctul de observare este originea. Deci in cazul general va trebui sa translatam totul in asa fel incat Pi sa ajunga in origine, pentru a putea aplica principiul dualitatii. Un ultim aspect care trebuie abordat este acela ca problema de mai sus indica numai care drepte sunt vizibile, nu exact ce segmente din acele drepte.\r\n\r\nAlgoritmul pentru aflarea poligonului Voronoi al lui Pi este:\r\n\r\n* Translateaza tot sistemul pentru a suprapune Pi peste origine (**)\r\n* Construieste colectia de n+3 drepte D1, D2, ..., Dn+3\r\n* Rezolva infasuratoarea convexa si afla colectia de drepte vizibile din origine, fie ele V1, V2, ..., Vk (in ordine trigonometrica)\r\n* Calculeaza varfurile poligonului Voronoi: Wi = Vi-1 int. cu Vi\r\n* Retranslateaza originea si {Wi} pentru a duce Pi in pozitia originala\r\n\r\n(**) Cum se translateaza colectia de puncte este clar: din fiecare Pj.x se scade Pi.x si din fiecare Pj.y se scade Pi.y; in acest fel Pi.x si pi.y devin 0. Cum translatam laturile dreptunghiului (sau in cazul general o dreapta oarecare) ? Daca ecuatia originala era ax+by+c=0, scriem aceasta ecuatie relativ la Pi.x si Pi.y:\r\n\r\nFie !voronoi?img16.bmp!\r\n!voronoi?img17.bmp!\r\n\r\nDeci noua ecuatie este\r\n!voronoi?img18.bmp!\r\n\r\nCu alte cuvine, pentru a translata dreapta cu -Pi.x si -Pi.y, scadem din c valoarea a*Pi.x + b*Pi.y.\r\n\r\nComplexitatea noului algoritm este (pentru un singur poligon):\r\n\r\n* O(N) translatia\r\n* O(N) constructia dreptelor\r\n* O(N) dualizarea\r\n* O(N log N) infasuratoarea convexa\r\n* O(N) constructia poligonului Voronoi\r\n* O(N) translatia inapoi\r\n\r\nPentru intreaga diagrama complexitatea este O(N^2^ log N).\r\nProgramul este implementat si testat. Nu este chiar scurt daca il construiti de la 0, dar daca puteti scrie fara greseala rutinele pentru infasuratoare convexa, intersectii de drepte si asa mai departe, cam in 1.5 - 2 ore ar trebui sa puteti programa toata povestea asta.\r\n\r\n*Cosmin* de fapt complexitatea e O(N^2^) daca folosim algoritmul naiv de infasuratoare convexa care dureaza O(N h) unde h e numarul de puncte de pe infasuratoarea convexa. Pentru ca numarul total de puncte de pe infasuratoarele convexe va fi egal cu 2 * nr de muchii din diagrama Voronoi care are maxim 3n -6 muchii.',2028,'public',NULL,NULL),('blog/alt-demo-de-la-microsoft','Alt demo de la Microsoft','2007-11-28 05:00:49','2008-11-16 12:39:39','Inca un demo foarte tare de la Microsoft Research. Imi plac ideile astea istete si foarte simplu de pus in practica.\r\n\r\n==youtubevideo(id=\"AtmwQnUlEmc\" width=\"425\" height=\"355\")==\r\n',1851,'protected',2423,NULL),('utilizator/chici','Profil Chici','2006-11-24 21:04:45','2007-02-12 20:40:08','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3604,'protected',NULL,NULL),('utilizator/lilix0202','Profil lilix0202','2006-11-24 21:05:03','2007-02-12 20:40:08','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3726,'protected',NULL,NULL),('utilizator/laiurita88','Profil laiurita88','2006-11-24 21:05:05','2007-02-12 20:40:08','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3739,'protected',NULL,NULL),('utilizator/lupu','Profil lupu','2006-11-24 21:05:06','2007-02-12 20:40:08','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3740,'protected',NULL,NULL),('utilizator/mfuqm31','Profil mfuqm31','2006-11-24 21:05:23','2007-02-12 20:40:08','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',3851,'protected',NULL,NULL),('utilizator/danutzul_05','Profil danutzul_05','2006-11-24 21:05:52','2007-02-12 20:40:09','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4032,'protected',NULL,NULL),('utilizator/tmir','Profil tmir','2006-11-24 21:05:56','2007-02-12 20:40:09','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4057,'protected',NULL,NULL),('utilizator/ioana_bomboana','Profil Ioana_bomboana','2006-11-24 21:06:06','2007-02-12 20:40:09','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4118,'protected',NULL,NULL),('utilizator/bianca_bya','Profil bianca_bya','2006-11-24 21:06:17','2007-02-12 20:40:09','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4184,'protected',NULL,NULL),('preoni-2007/clasament/runda-4/11-12','Clasament preONI 2007, Runda 4, Clasele 11-12','2007-03-07 12:18:12','2007-03-07 12:18:12','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda4_1112\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-4\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/runda-4/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-4/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-4/10\r\n*(active) \'Clasele 11-12\':preoni-2007/clasament/runda-4/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda4_1112\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('utilizator/andras','Profil andras','2006-11-24 21:06:36','2007-02-12 20:40:09','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4304,'protected',NULL,NULL),('utilizator/iceman_ro','Profil IcemaN_ro','2006-11-24 21:06:40','2007-02-12 20:40:10','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4327,'protected',NULL,NULL),('utilizator/bc_costy','Profil bc_costy','2006-11-24 21:06:54','2007-02-12 20:40:10','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4414,'protected',NULL,NULL),('utilizator/vic_and','Profil vic_and','2006-11-24 21:07:06','2007-02-12 20:40:10','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4484,'protected',NULL,NULL),('utilizator/alexus','Profil Alexus','2006-11-24 21:07:11','2007-02-12 20:40:10','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4516,'protected',NULL,NULL),('utilizator/claudia','Profil claudia','2006-11-24 21:07:17','2007-02-12 20:40:10','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4550,'protected',NULL,NULL),('utilizator/nirvanablue25','Profil nirvanablue25','2006-11-24 21:07:32','2007-02-12 20:40:10','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4635,'protected',NULL,NULL),('utilizator/onu_flo','Profil onu_flo','2006-11-24 21:07:35','2007-02-12 20:40:10','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4655,'protected',NULL,NULL),('utilizator/manu_deutza','Profil manu_deutza','2006-11-24 21:07:43','2007-02-12 20:40:11','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4699,'protected',NULL,NULL),('utilizator/cocoru','Profil cocoru','2006-11-24 21:08:04','2007-02-12 20:40:11','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4823,'protected',NULL,NULL),('utilizator/lemne','Profil lemne','2006-11-24 21:08:11','2007-02-12 20:40:11','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4860,'protected',NULL,NULL),('utilizator/xanthe','Profil xanthe','2006-11-24 21:08:18','2007-02-12 20:40:11','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4905,'protected',NULL,NULL),('utilizator/mlegs','Profil mlegs','2006-11-24 21:08:21','2007-02-12 20:40:11','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4920,'protected',NULL,NULL),('blog/problema-saptamanii-produs','Problema saptamanii - Produs','2008-06-01 09:32:06','2008-11-15 13:41:14','Sa se determine produsul maxim a unor numere reale pozitive a caror suma e 100.\r\n\r\n_Trimiteti-mi solutiile pe privat sau pe cosminn at gmail.com_',1490,'protected',3117,NULL),('ciclu-de-cost-mediu-minim','cliclu-de-cost-mediu-minim','2008-03-20 07:10:56','2008-03-20 07:10:56','\'Problema Ciclu a lui Radu Berinde\':http://www.ginfo.ro/revista/14_1/solutii2.pdf\r\n\r\n\'Gasiti aici solutia\':http://www.ginfo.ro/revista/14_1/solutii2.pdf\r\n\r\nUn truc similar:\r\n\'SGU 236 greedy path\':http://acm.sgu.ru/problem.php?contest=0&problem=236',58,'public',NULL,NULL),('utilizator/root','Profil root','2006-11-24 21:08:45','2007-02-12 20:40:11','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5054,'protected',NULL,NULL),('utilizator/ankutsa','Profil ankutsa','2006-11-24 21:09:21','2007-02-12 20:40:12','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5247,'protected',NULL,NULL),('utilizator/andreidumi','Profil AndreiDumi','2006-11-24 21:09:25','2007-02-12 20:40:12','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5274,'protected',NULL,NULL),('utilizator/dany_perfect','Profil Dany_perfect','2006-11-24 21:09:42','2007-02-12 20:40:12','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5364,'protected',NULL,NULL),('utilizator/ge_ronimo17','Profil ge_ronimo17','2006-11-24 21:09:46','2007-02-12 20:40:12','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5382,'protected',NULL,NULL),('preoni-2005/clasament-9-10','Clasament preoni5a','2006-11-24 23:36:40','2006-11-25 13:48:16','h1.  Clasament global preONI 2005 (Clasele IX-X)\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni52a|preoni53a\")==',961,'protected',NULL,NULL),('preoni-2005/clasament-11-12','Clasament preoni5b','2006-11-24 23:40:21','2006-11-25 13:48:12','h1.  Clasament global preONI 2005 (Clasele XI-XII)\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni52b|preoni53b\")==',961,'protected',NULL,NULL),('preoni-2005/runda-1/clasament-9-10','Clasament preoni51a','2006-11-24 23:52:21','2006-11-24 23:52:21','h1. Clasament ==roundparam(round_id=\"preoni51a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni51a\")==',961,'protected',NULL,NULL),('preoni-2005/runda-1/clasament-11-12','Clasament preoni51b','2006-11-24 23:53:42','2006-11-24 23:53:42','h1. Clasament ==roundparam(round_id=\"preoni51b\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni51b\")==',961,'protected',NULL,NULL),('preoni-2005/runda-2/clasament-9-10','Clasament preoni52a','2006-11-24 23:59:16','2006-11-24 23:59:16','h1. Clasament ==roundparam(round_id=\"preoni52a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni52a\")==',961,'protected',NULL,NULL),('preoni-2005/runda-2/clasament-11-12','Clasament preoni52b','2006-11-25 00:00:04','2006-11-25 00:00:04','h1. Clasament ==roundparam(round_id=\"preoni52b\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni52b\")==',961,'protected',NULL,NULL),('preoni-2005/runda-3/clasament-9-10','Clasament preoni53a','2006-11-25 00:03:54','2006-11-25 00:04:11','h1. Clasament ==roundparam(round_id=\"preoni53a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni53a\")==',961,'protected',NULL,NULL),('preoni-2005/runda-3/clasament-11-12','Clasament preoni53b','2006-11-25 00:05:25','2006-11-25 00:05:25','h1. Clasament ==roundparam(round_id=\"preoni53b\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni53b\")==',961,'protected',NULL,NULL),('preoni-2006/runda-2/clasament-9','Clasament preoni62a','2006-11-25 01:34:53','2006-11-25 01:34:53','h1. Clasament ==roundparam(round_id=\"preoni62a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni62a\")==',961,'protected',NULL,NULL),('preoni-2006/runda-3','Runda 3, preONI 2006','2006-11-25 01:39:09','2006-11-27 16:16:11','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Runda 3\r\n\r\nConcursul s-a desfasurat sambata, 21 ianuarie, la ora 09:00. Pe parcursul celor 4 ore de concurs participantii au avut de rezolvat 3 probleme. \r\n\r\nh2. Comisii\r\n\r\nh3. Stiintific\r\n\r\n* clasa a 9-a (si gimnaziu)\r\n** Adrian Diaconu\r\n** Daniel Pasaila \r\n* clasa a 10-a\r\n** Mircea Pasoi\r\n** Tiberiu Florea \r\n* clasele 11-12\r\n** Cosmin Negruseri\r\n** Adrian Vladu\r\n** Silviu Ganceanu\r\n\r\nh3. Organizatoric\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* Cristian Strat\r\n* Crestez Leonard \r\n\r\nh2. Solutii\r\n\r\nSolutiile problemelor le puteti gasi \"aici\":preoni-2006/runda-3/solutii\r\n\r\nh2. Clasa a 9-a si gimnaziu (\'Clasament\':preoni-2006/runda-3/clasament-9)\r\n\r\n!>preoni-2006/runda-3?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni63a\" pager_style=\"none\") ==\r\n\r\nh2. Clasa a 10-a(\'Clasament\':preoni-2006/runda-3/clasament-10)\r\n\r\n!>preoni-2006/runda-3?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni63b\" pager_style=\"none\") ==\r\n\r\nh2. Clasele 11-12 (\'Clasament\':preoni-2006/runda-3/clasament-11-12)\r\n\r\n!>preoni-2006/runda-3?logo.gif!\r\n\r\n== Tasks(round_id=\"preoni63c\" pager_style=\"none\") ==\r\n\r\n==include(page=\"template/preoni-2006/footer\")==',13,'protected',NULL,NULL),('preoni-2006/runda-3/clasament-11-12','Clasament preoni63c','2006-11-25 01:42:55','2006-11-25 01:42:55','h1. Clasament ==roundparam(round_id=\"preoni63c\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni63c\")==',961,'protected',NULL,NULL),('preoni-2006/runda-3/clasament-10','Clasament preoni63b','2006-11-25 01:43:01','2006-11-25 01:43:01','h1. Clasament ==roundparam(round_id=\"preoni63b\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni63b\")==',961,'protected',NULL,NULL),('preoni-2006/runda-3/clasament-9','Clasament preoni63a','2006-11-25 01:43:07','2006-11-25 01:43:07','h1. Clasament ==roundparam(round_id=\"preoni63a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni63a\")==',961,'protected',NULL,NULL),('preoni-2006/runda-4/clasament-11-12','Clasament preoni64c','2006-11-25 02:53:06','2006-11-25 02:53:06','h1. Clasament ==roundparam(round_id=\"preoni64c\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni64c\")==',961,'protected',NULL,NULL),('preoni-2006/runda-4/clasament-10','Clasament preoni64b','2006-11-25 02:53:12','2006-11-25 02:53:12','h1. Clasament ==roundparam(round_id=\"preoni64b\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni64b\")==',961,'protected',NULL,NULL),('preoni-2006/runda-4/clasament-9','Clasament preoni64a','2006-11-25 02:53:20','2006-11-25 02:53:20','h1. Clasament ==roundparam(round_id=\"preoni64a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni64a\")==',961,'protected',NULL,NULL),('preoni-2006/finala','Finala in Focsani, preONI 2006','2006-11-25 02:52:41','2006-12-01 18:28:26','==Include(page=\"template/preoni-2006\")==\r\n\r\nh1. Finala in Focsani \r\n\r\n*Primii 10* concurenti de la fiecare grupa din clasamentul rundelor online (#1 + #2 + #3 + #4) sunt invitati la runda finala. Aceasta se va desfasura in *Focsani*, mai exact:\r\n\r\n* cazare + mic dejun la *Hotel Unirea, Focsani*\r\n* concursul on-site la *{\'Colegiul National Unirea\':http://cnu.lufo.ro/}*\r\n\r\n\'Premiile concursului\':preoni-2006/premii preONI se vor acorda in functie de rezultatele rundei finale. Punctajele obtinute in perioada de calificare vor servi doar la departajare.\r\nPentru concurentii care nu s-au calificat in finala, vom gazdui si o varianta online. Aveti ocazia sa va comparati performanta cu cei care au ajuns in finala! ;)\r\n\r\nh2. Probleme\r\n\r\nSolutiile problemelor le puteti gasi \"aici\":preoni-2006/finala/solutii.\r\n\r\nh3. Clasa a 9-a si gimnaziu (\'Clasament\':preoni-2006/finala/clasament-9)\r\n\r\n!>preoni-2006/finala?logo.jpg!\r\n\r\n== Tasks(round_id=\"preoni65a\" pager_style=\"none\") ==\r\n\r\nh3. Clasa a 10-a(\'Clasament\':preoni-2006/finala/clasament-10)\r\n\r\n!>preoni-2006/finala?logo.jpg!\r\n\r\n== Tasks(round_id=\"preoni65b\" pager_style=\"none\") ==\r\n\r\nh3. Clasele 11-12 (\'Clasament\':preoni-2006/finala/clasament-11-12)\r\n\r\n!>preoni-2006/finala?logo.jpg!\r\n\r\n== Tasks(round_id=\"preoni65c\" pager_style=\"none\") ==\r\n\r\nh2. Sponsori finala\r\n\r\nSponsorii finalei sunt:\r\n\r\n\"!preoni-2006?Oracle_ro.gif!\":http://www.oracle.com/global/ro/index.html\r\n\r\n\"Colegiul National Unirea, Focsani\":http://cnu.lufo.ro/\r\n\r\n*Hotel Unirea, Focsani*\r\n\r\nMultumim d-lui *Prof. Emil Onea* pentru ca a facut posibila organizarea acestei finale!\r\n\r\nh2. Calificare \r\n\r\nCalificarea in aceasta etapa se face exclusiv pe baza clasamentului din primele 4 runde. De la fiecare grupa vor fi selectati ocupantii primelor *10* pozitii. Mentionam ca o persoana se poate califica la finala doar la grupa destinata lui si ca se va face si o identificare prin intermediul Cartii de Identiate (Buletin) pentru a evita frauda. Daca aveti nelamuriri revedeti si \'regulamentul\':preoni-2006/regulament. \r\nConcurentiilor li se vor asigura cazarea si *masa integral*. Costul transportului pana la locul unde se va desfasura finala va fi suportat de catre concurenti. Pentru motivarea absentelor pe perioada finalei se va elibera un document oficial.\r\n\r\nh2. Program \r\n\r\nIntrucat programul elevilor este in general incarcat in aceasta perioada, durata rundei finale este de numai *3 zile*. Perioada de desfasurare: *24-26 martie 2006* (vineri, sambata, duminica). Teoretic, luni sunteti inapoi la scoala :) Va rugam sa vizitati aceasta sectiune periodic pentru a fi la curent. Programul provizoriu al finalei este:\r\n\r\n|_. Ziua |_. Actvitate |\r\n| *24 martie 2006* | Sosirea participantilor\r\nDeschidere oficiala\r\nAcomodare |\r\n| *25 martie 2006* | Concurs (dimineata)\r\nPrezentare ORACLE\r\nEvaluare si contestatii\r\nPremiere\r\nCina festiva |\r\n| *26 martie 2006* | Excursie la _Valea Putnei_\r\nPlecare |\r\n\r\nConcursul va dura *5* ore in care concurentii vor primi spre rezolvare *3* probleme cu grad de dificultate un pic mai ridicat decat cel de la etapele anterioare. Programul nu este fix, si asteptam sugestii din partea voastra.\r\nCei care nu s-au calificat in runda finala vor putea sa participe in paralel on-line pe _infoarena_. Modul de desfasurare va fi identic cu acela al primelor patru. Participantii online nu vor primii premii.\r\n\r\nh2. Mediul de lucru \r\n\r\nRunda finala se desfasoara in laboratoarele de informatica ale *{\'Colegiului National Unirea\':http://cnu.lufo.ro/}* din Focsani. Vom incerca sa punem la dispozitia concurentilor aceleasi versiuni de compilatoare ca cele folosite pe site in timpul rundei. Asteptam sugestiile voastre in privinta soft-ului care doriti sa fie instalat pe calculatoare.\r\n\r\nh2. Regulament \r\n\r\nPe langa \'regulamentul concursului\':preoni-2006/regulament, la editia finala vor exista urmatoarele adaugiri la regulament pentru cei calificati. \'Echipa infoarena\':echipa-infoarena isi rezerva dreptul de a modifica acest regulament in orice fel pana la data desfasurarii finalei.\r\n\r\n* Concurentii vor fi prezenti in salile de concurs la orele anuntate\r\n* Fiecare concurent va primi subiectele in forma listata si foi pentru ciorne (pix nu este inclus)\r\n* Timp de 1 ora dupa primirea subiectelor concurentii pot formula intrebari referitoare la enunturile problemelor; intrebarile se vor formula in scris, pe foaia cu intrebari fiind precizate numele problemei si al concurentului; modalitate de formulare a intrebarile este identica cu cea de la primele 4 runde\r\n* In timpul probelor de concurs, concurentii:\r\n** nu vor avea asupra lor telefoane mobile sau alte mijloace de comunicatie\r\n** nu vor utiliza suporturi externe proprii (dischete/CD/flash-disk)\r\n** nu vor utiliza alte surse de documentare decat cele prezente pe calculator\r\n** nu vor incerca sa interfereze in nici un mod cu activitatile altui concurent\r\n** nu vor deteriora mediile de lucru\r\n** nu vor incerca sa interfereze cu sistemul de evaluare\r\n* In programele concurentilor nu sunt permise urmatoarele:\r\n** schimbarea drepturilor de acces la fisiere\r\n** atacul asupra securitatii sistemului sau evaluatorului\r\n** accesarea informatiilor despre sistemul de fisiere\r\n** executarea unor alte programe\r\n\r\nOrice incercare de frauda sau de a sabota desfasurarea corecta a concursului va fi urmata imediat de eliminarea elevului respectiv din concurs, cat si de pe _infoarena_.\r\n\r\nh2. Participanti \r\n\r\n\'Click aici\':preoni-2006/clasament pentru clasamentul rundelor online.\r\nLista oficiala a participantilor va fi anuntata dupa ce validam identitatea celor calificati online.\r\n\r\nh2. Divertisment :p \r\n\r\nCa sa nu ne plictisim vom pleca intr-o excursie la _Valea Putnei_ pentru a discuta informatica si calculatoare intr-un cadru aparte. :)',1142,'protected',NULL,NULL),('blog/alta-problema-misto-solutie','Alta problema misto - solutie','2007-10-22 08:00:03','2008-11-16 12:58:53','Problema cu lanternele a fost rezolvata de Radu Cebanu, Dumitru Daniliuc, \'Stefan Istrate\':http://infoarena.ro/utilizator/stef2n , Catalin Francu si Stefan Ciobaca.\r\n\r\nVa prezint in continuare solutiile. Este interesant de urmarit cum sunt gandite solutiile, care desi sunt echivalente sunt prezentate putin diferit.\r\n\r\n*Stefan Ciobaca* generalizeaza problema:\r\nEu as fi propus generalizarea: ai <tex>2^n</tex> triedre drepte in n dimensiuni.\r\n\r\nRezolvarea prin divide et impera: iei cele <tex>2^n</tex> puncte si le separi printr-un hiperplan astfel incat jumate sa fie de-o parte, jumate de cealalta parte s.a.m.d., avand in vedere ca toate hiperplanele sa fie perpendiculare intre ele. Evident, chestia asta se poate. Apoi, fiecare triedru il orientezi spre semisemisemi...semi spatiul total opus si cu marginile paralele cu axele de coordonate q.e.d.\r\nImi place cum se vede defectul profesional de programator citind demonstratia.\r\n\r\nSolutia lui *Radu*:\r\n\r\nRezolvam prin inductie dupa nr de dimensiuni.\r\n\r\nIn primul rand: fixezi o directie pt primul plan, il muti paralelel cu el insusi astfel incat sa separe punctele in 2 parti egale, 4 de o parte, 4 de alta (daca stau mai multe pe planul ala exact,nu conteaza, alegi cateva si le declari de o parte, sa fie 4 si restul de cealalta). \r\nApoi sa zicem ca le luam pe alea de deasupra:\r\n proiectiile lor pe planul respectiv sunt 4 puncte care conform inductiei (pt doua dimensiuni) acopera planul. Cu diedrele din plan faci triedre cu a 3-a dreapta in jos ca sa acopere semispatiul inferior. La fel pt alea de sub plan, pui dreapta a 3-a din triedru in sus ca sa acopere semispatiul superior.\r\nRadu a lasat demonstratia putin incompleta avand incredere ca ma prind singur de cazul 2d si 1d.\r\n\r\nSolutia lui *Catalin*:\r\nIdeea mea e sa gasesc o solutie in care triedrele au laturile orientate paralel cu axele, pentru simplitate.\r\n\r\n- Rotim sistemul astfel incat sa nu existe doua lanterne cu coordonate X, Y sau Z egale (pentru a scapa de cazuri particulare).\r\n\r\n- Parcurgem lanternele in ordine crescatoare a coordonatei x. Pe primele 4 le marcam cu X+, pe ultimele 4 cu X-.\r\n\r\n- Parcurgem cele patru lanterne X+ in ordine crescatoare a coordonatei y. Pe primele doua le marcam cu Y+, pe celelalte doua cu Y-. La fel si\r\npentru cele patru lanterne X-.\r\n\r\n- Parcurgem cele doua lanterne X+Y+ in ordine crescatoare a coordonatei z. Pe prima o marcam cu Z+, pe a doua cu Z-. La fel si pentru celelalte 6 lanterne marcate cu X+Y-, X-Y+, X-Y-.\r\n\r\nAvem opt lanterne marcate cu X+Y+Z+, X+Y+Z-, pana la X-Y-Z-. Acum le pozitionam paralel cu axele Ox, Oy, Oz si in sensurile indicate de semne. De exemplu, lanterna X+Y-Z- \r\n\r\nva lumina catre sensul pozitiv al axei Ox si catre sensurile negative ale axelor Oy si Oz; cu alte cuvinte, ea va lumina punctul de coordonate (+inf, -inf, -inf).\r\n\r\nDandu-se un punct P(x,y,z), trebuie demonstrat ca exista o lanterna care il lumineaza. Analizam coordonata x. Datorita constructiei, x va fi fie mai mare decat toate coordonatele x ale lanternelor marcate cu X+, fie mai mic decat toate coordonatele x ale lanternelor marcate cu X- (fie ambele, daca x este situat intre cele doua grupuri de 4 lanterne). Alegem acel set de 4 lanterne si reluam rationamentul pe axele Oy si Oz. in final, obtinem minim o lanterna care lumineaza punctul P.\r\n\r\nSi la Catalin se vede programatorul din spatele solutiei. Se observa cum structura rezolvarii este bazata pe vectorii de cate 3 elemente in baza 2.\r\n\r\n*Stefan Istrate* are o solutie foarte misto, cu desene dragute, pe care o gasiti pe \'forum\':http://infoarena.ro/forum/index.php?topic=2218.0 . Merita sa o cititi!\r\n\r\nSolutia lui *Dumitru* nu o am scrisa.\r\n\r\nLa solutia lui Stefan Ciobaca si cea a lui Catalin Francu nu e demonstrata ipoteza ca _putem gasi un sistem de coordonate in care toate punctele au coordonatele x1, x2, .. respectiv diferite_ . Va incurajez sa va incercati puterile pe aceasta subproblema in sectiunea de \'comentarii\':http://infoarena.ro/forum/index.php?topic=2222.0\r\n\r\nO problema similara a fost propusa la un ACM in regiunea din Nord Estul Europei: _Se cere iluminarea planului cu n lanterne (n <= 30) de coordonate date, ce pot fi rotite, al caror fascicul emite lumina sub un unghi de marime 2pi/n. Pentru fiecare lanterna trebuie returnata orientarea ei._ La aceasta problema, pe langa solutia ei, e interesant si algoritmul folosit pentru evaluarea corectitudinii unui rezultat.\r\n\r\nPentru mai multe probleme interesante cu lanterne puteti citi urmatoarele lucrari:\r\n\r\nBose, J., L. Guibas, A. Lubiw, M. Overmars, D. Souvaine and J. Urrutia, \'\"The floodlight illumination problem\"\':blog/alta-problema-misto-solutie?TheFloodProb.ps\r\nCzyzowicz, J., E. Rivera-Campo and J. Urrutia, \'\"Optimal floodlight illumination of stages\"\':blog/alta-problema-misto-solutie?OptFloStages.ps',2028,'protected',2222,NULL),('template/userrating','template/userrating','2006-12-02 18:13:34','2009-03-12 20:35:17','h2. Rating %user%\r\n\r\n==RatingChart(user=\"%user%\")==\r\n\r\nh3. Concursuri cu rating la care a participat\r\n\r\n==Rounds(user=\"%user%\" only_rated=\"1\")==\r\n\r\n==DistributionChart(user=\"%user%\")==\r\n\r\n*{\"Ce inseamna si cum se calculeaza rating-ul?\":documentatie/rating}*',1490,'protected',NULL,NULL),('blog/unirea-2007','Concursul Unirea 2007','2007-01-24 01:31:16','2007-01-24 01:31:16','infoarena organizeaza concursul de informatica Unirea 2007.\r\n\r\nConcursul, la care castigatorii vor primi diplome si premii, incepe *Sambata, 27 ianuarie la ora 14^00^* si dureaza *3h*.\r\n\r\nInformatii se gasesc pe \'pagina concursului\':unirea-2007.',13,'public',NULL,NULL),('documentatie/pentru-propunatori','Pentru propunatori','2006-12-10 17:39:32','2007-04-01 19:28:39','h1. Pentru propunatori.\r\n\r\nUnul dintre principalele motive pentru care noi am rescris infoarena este ca sa facem mai usor sa propui probleme. Momentan aceste facilitati nu sunt gata, dar vor fi in curand.\r\n\r\nDaca stii sa programezi in php/mysql (sau vrei sa inveti) poti sa ne ajuti si pe partea de \'web-development\':http://infoarena.ro/implica-te/development.',15,'public',NULL,NULL),('despre-infoarena','Despre infoarena','2006-11-27 07:32:22','2009-08-04 12:57:48','h1. Despre infoarena\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\n*infoarena ajuta elevi si studenti sa invete informatica si programare.* Organizam concursuri de informatica, scriem articole, dezvoltam software, facem schimb de experienta si idei.\r\n\r\nSuntem viitorii specialisti IT ai Romaniei! Ne-am organizat pe acest site deoarece impreuna invatam mai bine.\r\n\r\nh2. Cu ce ne ocupam?\r\n\r\n* Concursuri online de informatica pentru studenti si elevi\r\n* Stiri si articole despre informatica\r\n* Discutam pe forum tot despre informatica\r\n* Dezvoltam software open source\r\n\r\ninfoarena functioneaza din 2003 si este dezvoltata de \'echipa infoarena\':echipa-infoarena, cu sprijinul a zeci de colaboratori ajutandu-ne pe diferite \'proiecte\':implica-te.\r\nComunitatea noastra cuprinde elevi si studenti romani ce participa la concursuri de informatica nationale si internationale.\r\n\r\n*Citeste {\'prezentarea infoarena\':prezentare}*.\r\n\r\nbq. People have been known to achieve more as a result of working with others than against them.\r\n\r\n*Dr. Allan Fromme*\r\n\r\nbq. infoarena este un proiect remarcabil, realizat cu entuziasm, generozitate si profesionalism. Este locul in care tinerii pasionati de informatica se pot intalni, atat de o parte, cat si de cealalta parte a baricadei, ca propunatori sau ca rezolvitori de probleme, isi pot impartasi experienta competitionala, pot constitui modele, pot ajuta la formarea a noi si noi generatii de performanta.\r\n\r\n*Emanuela Cerchez*\r\nCoordonator stiintific in Comisia Nationala de Informatica, Prof. grad I - Lic. de Informatica \"Grigore Moisil\" Iasi\r\n\r\nbq. infoarena e plin de energie, e dinamic si riguros, gratie unei echipe curajoase. Site-ul infoarena reprezinta cea mai originala forma de pregatire pe net a performerilor in informatica din Romania. Mecanism de lucru excelent, probleme propuse, fara cusur. Felicitari!\r\n\r\n*Emil Onea*\r\nInspector scolar informatica, Comisia Nationala de Informatica pentru Invatamant Preuniversitar\r\n',75,'protected',NULL,NULL),('okr/20091/devel-ia3','okr/20091/devel-ia3','2009-01-26 14:47:14','2009-01-26 14:52:35','(okr)* comunitate functionala de developeri\r\n** crestem numarul de contribuitori: sa avem macar 2-3 oameni activi\r\n** folosim best practices: documentatie si tutoriale pentru incepatori, code review, tickets, documentation, setup script,  unit tests, benchmarks, regression tests',13,'public',NULL,NULL),('okr/20091/downloads','okr/20091/downloads','2009-01-26 14:47:28','2009-01-26 18:56:23','',1,'public',NULL,NULL),('documentatie/forum','Forum infoarena','2006-12-11 01:55:16','2007-04-07 18:08:35','h1. Forum infoarena\r\n\r\n==include(page=\"template/todo\")==\r\n\r\nSite-ul infoarena integreaza un forum \'SMF\':http://www.simplemachines.org.\r\n\r\nAtunci cand iti creezi cont pe infoarena, ti se creaza automat un cont de acces si pe forum.\r\n\r\nAcceseaza forum-ul cu click pe tab-ul _forum_ din bara principala de navigare.\r\nPoti sa trimiti si sa primesti mesaje personale de la alti utilizatori. Click pe _mesaje_ in bara principala de navigare.\r\n\r\nUnele pagini precum \'prima pagina\':home sau \'arhiva de probleme\':arhiva afiseaza liste cu ultimelor discutii / mesaje aparute pe forum. Facand click in aceste link-uri poti sa ajungi direct pe forum.',5748,'public',NULL,NULL),('termeni-si-conditii','Termeni si conditii de utilizare a site-ului infoarena','2006-11-27 08:53:18','2006-12-11 03:27:51','h1. Termeni si conditii de utilizare a site-ului infoarena\r\n\r\n==include(page=\"template/todo\")==\r\n\r\nPentru a folosi site-ul infoarena trebuie sa fii de acord cu urmatoarele conditii:\r\n\r\n* Vei respecta \'regulamentul\':regulament.\r\n* *Nu ne asumam responsabilitatea fata de continutul pe care utilizatorii il adauga pe site!* Ne straduim sa filtram si sa moderam ceea ce utilizatorii adauga / editeaza pe site dar nu garantam ca o vom face in timp util pentru tine.\r\n* Cu exceptia cazurilor in care se specifica altfel, continutul acestui site este sub licenta \'Creative Commons Attribution-NonCommercial 2.5.\':http://creativecommons.org/licenses/by-nc/2.5/.\r\n* Conditiile de utilizare se pot schimba in timp fara a fi informat in prealabil.',13,'protected',NULL,NULL),('blog/lansare-infoarena-2','Am lansat infoarena 2!','2006-12-11 03:39:58','2006-12-14 13:03:44','h1. Am lansat infoarena 2!\r\n\r\nAm lansat infoarena 2!\r\nVechiul site (infoarena.devnet.ro), care ne-a servit timp de aproape 3 ani, a fost inchis.\r\n\r\nAfla mai multe despre noul infoarena vizitand pagina indicata mai sus.\r\n',4439,'public',NULL,NULL),('ia_in_ie7','Cum arata infoarena in internet explorer 7','2006-12-05 23:12:50','2007-02-22 20:24:47','Momentan, nici un bug vizibil in IE7.\r\n\r\n* FIXED -footer afisat prost-\r\n* FIXED -vezi partea din stanga, problema cu casuta cu utilizatorul pare rezolvata-\r\n\r\n* FIXED -inca un bug chiar pe pagina asta - ce se intampla ca daca imaginea nu incape in fereastra -- a se observa spatiul liber intre textul \'footer afisat prost\' si poza; daca fereastra este destul de mare sa incapa poza, spatiul dispare-\r\n',2934,'public',NULL,NULL),('summer-challenge-unu','Summer Challenge Unu','2006-11-23 21:09:02','2006-12-11 15:55:43','h1. Summer Challenge Unu\r\n\r\nConcursul s-a desfasurat pe 3/8/2006.\r\n\r\nConcursul a avut 3 probleme, care au fost adaugate in \'arhiva\':arhiva.\r\n\r\nArticolul cu solutii se gaseste \'aici\':summer-challenge-unu/solutii.\r\n\r\nh2. \'Clasament\':summer-challenge-unu/clasament\r\n\r\n!>summer-challenge-unu?logo!\r\n\r\n== Tasks(round_id=\"summer06\" pager_style=\"none\") ==',961,'protected',NULL,NULL),('utilizator/armasanea','Profil armasanea','2006-12-12 05:22:18','2007-02-12 20:40:12','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5420,'public',NULL,NULL),('summer-challenge-2007/solutii/runda-1','Solutii Summer Challenge, Runda 1','2007-07-30 12:37:45','2007-08-11 07:10:08','h1. Solutii Runda 1\r\n\r\nh2. \'Imagine\':problema/imagine\r\n\r\nObservam ca fiecare din operatiile {$S$} {$D$} {$O$} {$V$} nu face decat sa permute intre ele cele $4$ cadrane. De exemplu initial cadranele se afiseaza in ordinea {$1,2,3,4$} iar dupa o operatie {$O$} vor trebui afisate {$3,4,1,2$}, apoi dupa aplicarea unei operatii $V$ va trebui afisat {$4,3,2,1$}. Pentru operatiile $I$ va trebui sa retinem doar paritatea si in cazul in care numarul acestor operatii este impar va trebui sa afisam $n$ in loc de $a$ si invers. De aceea nu trebuie decat sa retinem in ce ordine vom prezenta cadranele si daca acestea vor fi sau nu negate.\r\n\r\nProblema care se ridica este lipsa memoriei. Vom reprezenta imaginea ca un arbore in care fiecare nod fie este frunza fie are $4$ fii(cate unul pentru fiecare cadran). O parcurgere a arborelui in care fii oricarui nod sunt parcursi in ordinea permutarii noastre va fi exact codificarea cautata. Observam ca nu putem avea mai mult de $N/5$ noduri interne deci maxim {$2.000.000$}. Pentru fiecare nod vom retine primul fiul si fratele nodului curent. Din felul in care vom construi arborele (cu ajutorul unei stive) se vede ca primul fiu al unui nod in cazul in care exista va fi exact {$nodul curent + 1$} de aceea nu va mai fi necesara si retinerea fiului. In plus in fiecare nod vom mai retine 8 biti grupati cate 2 pentru a retine pentru fiecare din cei $4$ fii daca este sau nu o frunza si in cazul in care este o frunza retinem si culoarea ei. In total se poate folosi cu usurinta sub $16M$ memorie.\r\n\r\nh2. \'Strigat\':problema/strigat\r\n\r\nVom construi un \"automat finit\":Automate-finite-si-KMP ce va contine cuvintele din intrare. Fiecarei stari din automat ii vom asocia o valoare egala cu suma gradelor de spaima ale cuvintelor acceptate de acea stare. Pentru a determina sirul cu grad maxim de spaima vom construi matricea $A[i][j]$ cu semnificatia care este gradul de spaima maxim pentru un sir de lungime $i$, aflandu-ne la sfarsit in starea $j$ a automatului. Aflandu-ne pe linia $i$ a matricei vom folosi matricea de tranzitie a automatului $&#0948;$ pentru a calcula valorile de pe linia $i + 1$.\r\n\r\n$A[i + 1][ &#0948;{~j, c~} ] = max( A[i + 1][ &#0948;{~j, c~} ], A[i][j] + ValoareStare[ &#0948;{~j, c~} ] )$, $c &isin; &#0931;$\r\n\r\nConstructia automatului are complexitatea $O(L * |&#0931;|)$, unde $L$ reprezinta suma lungimilor cuvintelor de la intrare si $&#0931;$ reprezinta alfabetul.\r\nCalcularea matricei are complexitatea $O(N * L * |&#0931;|)$.\r\n\r\nh2. \'Flux\':problema/flux\r\n\r\nVom forma un sistem de ecuatii in care necunoscutele {$X{~i~}$} vor fi suma fluxurilor de pe drumul de la $0$ la nodul {$i$} (care se garanteaza ca este aceeasi indiferent de drum). Fluxul trimis de la $i$ la $j$ va fi exact {$n{~i,j~}*(X{~j~}-X{~i~})$} unde n{~i,j~} este numarul de muchii dintre $i$ si {$j$}. Vom pune conditiile de conservare a fluxului pentru fiecare nod {$i$}: suma fluxurilor care intra sa fie egala cu suma fluxurilor care ies. Pentru nodul $1$ nu este necesar sa scriem ecuatia deoarece se stie {$X{~1~}=0$}, iar pentru nodul $N$ vom pune ecuatia suma fluxurilor care intra in el sa fie $1$. Sistemul de {$N-1$} ecuatii cu {$N-1$} necunoscute se rezolva folosind Gauss.\r\n\r\nPana acum am satisfacut conditiile de flux si restrictia impusa de enunt, mai avem doar de satisfacut restrictiile de capacitate de pe fiecare muchie. Observam ca daca pentru ecuatia pentru nodul $N$ in loc de $1$ fixam o valoare $S$ fluxurile trimise pe fiecare muchie se vor inmulti cu $S$. Asadar pentru a satisface conditiile de capacitate trebuie doar sa inmultim fluxurile de pe fiecare muchie cu minimul dintre {$C{~i,j~} / F{~i,j~}$} unde {$F{~i,j~}$} este fluxul trimis pe muchie {$(i,j)$} si {$C{~i,j~}$} este capacitatea muchiei {$(i,j)$}.',1490,'public',NULL,NULL),('utilizator/kana','Profil kana','2006-12-14 07:19:16','2007-02-12 20:40:13','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5484,'public',NULL,NULL),('utilizator/kezman','Profil kezman','2006-12-18 15:15:41','2007-02-12 20:40:13','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5536,'public',NULL,NULL),('blog/surse-deschise','Surse deschise','2008-01-29 08:08:06','2008-11-15 13:41:14','Mircea a terminat implementarea proiectului \'IAP5\':http://infoarena.ro/propuneri/5-open-surse . Si Adrian Diaconu a selectat 50 de probleme care sa faca parte din proiect. Acum orice vizitator al siteului va putea vedea toate sursele trimise la oricare dintre cele 50 de probleme selectate. Problemele din arhiva cu \"surse deschise\" au cate o carte desenata in dreptul lor. Pentru a vedea o sursa puteti intra la monitor, de acolo la evaluare completa, iar apoi la vezi sursa.\r\nProblemele au fost alese de Adi pentru diversitatea lor. Sper ca acest pas facut de infoarena sa fie urmat si de alte proiecte legate de olimpiadele de informatica. Tin minte cum in liceu invatam foarte mult citind din sursele elevilor mai mari. Cred ca problemele cu sursele deschise de pe infoarena se vor dovedi un material foarte bun de pregatire.\r\n\r\nMai avem inca o \'initiativa\':propuneri/6-arhiva-educationala interesanta, si cred ca impreuna cele doua proiecte vor spori cu mult utilitatea siteului.\r\n\r\nVa astept cu comentarii si sugestii!',1490,'protected',2645,NULL),('utilizator/fish','Profil fish','2007-01-12 09:58:25','2007-02-12 20:40:13','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5628,'public',NULL,NULL),('task/proc','task/proc','2007-01-11 10:37:47','2007-01-11 10:37:47','Scrie aici despre task/proc',2215,'public',NULL,NULL),('preoni-2005','Preoni 2005','2006-11-24 23:25:20','2007-01-13 21:42:49','h1. preONI 2005\r\n\r\nConcursul preONI 2005 s-a desfasurat in 3 runde avand ca principal scop pregatirea participantilor pentru olimpiada nationala de informatica ONI2005.\r\n\r\nFormatul concursului: 2 grupe (clasele IX-X, XI-XII), 3 probleme in fiecare grupa si un timp de lucru de 4h.\r\n\r\nh2. Runde\r\n\r\n* \"Runda 1\":preoni-2005/runda-1 :Duminica, 23 ianuarie, ora 15:00\r\n* \"Runda 2\":preoni-2005/runda-2 :Miercuri, 23 februarie ora 16:00\r\n* \"Runda 3\":preoni-2005/runda-3 :Duminica, 20 martie la ora 10:00\r\n\r\nh2. \"Clasament IX-X\":preoni-2005/clasament-9-10\r\n\r\nh2. \"Clasament XI-XII\":preoni-2005/clasament-11-12',1,'round: preoni-2005',NULL,NULL),('preoni_2006','preoni_2006','2007-01-18 13:56:41','2007-01-18 13:56:41','Scrie aici despre preoni_2006',5685,'public',NULL,NULL),('preoni-2007/comisie','Organizatori preONI 2007','2007-01-15 15:46:22','2007-01-31 19:52:13','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Organizatori\r\n\r\n\'Echipa infoarena\':echipa-infoarena se ocupa de organizarea si desfasurarea concursului *preONI 2007*.\r\n\r\nh2. Organizare \r\n\r\n* == user(user=\"wickedman\" type=\"tiny\") == : coordonator, promovare concurs\r\n* == user(user=\"fluffy\" type=\"tiny\") == : coordonator tehnic (site-ul, evaluatorul etc.)\r\n* == user(user=\"svalentin\" type=\"tiny\") == : suport tehnic\r\n\r\nh2. Echipa stiintifica\r\n\r\nCei care se vor ocupa de buna desfasurarea a concursului din punct de vedere stiintific (redactarea si compunerea problemelor, realizarea testelor, clarificarea intrebarilor, etc.) sunt:\r\n\r\n* == user(user=\"domino\" type=\"tiny\") ==\r\n* == user(user=\"Cosmin\" type=\"tiny\") ==\r\n* == user(user=\"ditzoneC\" type=\"tiny\") ==\r\n* == user(user=\"silviug\" type=\"tiny\") ==\r\n* == user(user=\"filipb\" type=\"tiny\") ==\r\n* == user(user=\"danielp\" type=\"tiny\") ==\r\n* == user(user=\"azotlichid\" type=\"tiny\") ==\r\n* == user(user=\"greco\" type=\"tiny\") ==\r\n\r\nh2. Multumim\r\n\r\n* &hellip; lui Radu Lupaescu pentru noua sigla preONI 2007\r\n* &hellip; lui Alexandru Marinescu pentru sigla preONI 2007\r\n\r\n==include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('preoni-2007/program','Program preONI 2007','2007-01-15 15:51:59','2007-01-15 15:57:51','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Program\r\n\r\n_in curand_\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('preoni-2007/regulament','Regulament preONI 2007','2007-01-15 15:52:52','2007-01-18 18:24:07','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Regulament\r\n\r\nSe recomanda, pe langa citirea acestui regulament, citirea \"regulamentului\":regulament general infoarena.\r\n\r\n\'Echipa infoarena\':echipa-infoarena isi rezerva dreptul de a modifica prezentul regulament pe parcursul desfasurarii concursului. Daca apar prevederi noi sau daca anumite prevederi ale regulamentului sunt modificate sau eliminate, atunci acestea vor fi anuntate pe site-ul concursului. Orice modificare a regulamentului va intra in vigoare, in functie de situatie, fie din momentul publicarii ei, fie dupa incheierea rundei aflate in desfasurare. In momentul anuntarii modificarii va fi precizat si momentul din care aceasta intra in vigoare.\r\n\r\nh2. Dreptul de participare\r\n\r\nPersoanele care fac parte din \'echipa infoarena\':echipa-infoarena cat si alti contribuitorii implicati direct in organizarea concursului *preONI 2007* nu au dreptul de a participa. De asemenea, orice concurent care are un comportament considerat inadecvat fata de echipa infoarena sau fata de alti concurenti va fi descalificat. Un concurent se poate califica la finala doar daca se incadreaza in grupa la care a concurat (aceasta verificare se va face prin prezentarea unei dovezi legale care il incadreaza pe concurent la aceea grupa).\r\n\r\nh2. Repartizarea\r\n\r\nToti participantii vor fi repartizati in 3 grupe, in concordanta cu varsta lor. Repartizarii este asemanatoare cu acea facuta la olimpiadele de informatica.\r\n\r\n* Clasa a 9a si gimnaziu\r\n* Clasa a 10a\r\n* Clasele 11-12 \r\n\r\nOricine poate participa la o alta grupa decat cea la care se incadreaza, dar calificarea la finala cat si impartirea premiilor se va face conform regulamentului respectiv, fara nici o exceptie.\r\n\r\nh2. Inscriere\r\n\r\nTot ce trebuie sa faceti pentru a participa la concursul *preONI 2007* este sa aveti un cont la infoarena. Inregistrarea se poate face pe site-ul infoarena. Acelasi cont va fi folosit pentru a accesa forum-ul.\r\n\r\nh2. Runde\r\n\r\nVor exista 4 runde de calficare, iar in urma clasamentului stabilit primii de la fiecare grupa vor fi selectati pentru etapa finala desfasurata in cadrul unei tabere. Cele 4 runde vor avea loc sambata si duminica, incepand cu ora 9:00, desi pot interveni exceptii. Durata lor va fi de 4 ore. Pentru un program detaliat al concursului \"click aici\":preoni-2007/program.\r\n\r\nh2. Intrebari\r\n\r\nIn prima ora vor putea fi formulate eventualele intrebari, pe forum, in topicurile special create. Orice intrebare pusa in alt mod (primita ca personal message, pe mail, etc.) va fi ignorata. Raspunsuri vor fi oferite doar la intrebarile puse in prima ora . Intrebarile trebuie formulate astfel incat sa se poate raspunda cu DA sau NU. In caz contrar sau in cazul in care raspunsul se afla in textul problemei se va raspunde cu NO COMMENT. Nu vor exista exceptii de la aceaste reguli. Daca echipa va considera ca raspunsul la o anumita intrebare este de interes general si clarifica anumite aspecte, atunci se va face un anunt general care va aparea atat pe forum cat si in sectiunea Mesaje de la organizatori a grupei respective. Fiecare grupa va avea doi administratori care se vor ocupa de raspunsul acestor intrebari.\r\n\r\nh2. Trimiterea solutiilor\r\n\r\nTrimitrea solutiile se va face prin intermediul interfetei site-ului infoarena.\r\nOdata logati in contul vostru, veti putea selecta arhiva la care doriti sa lucrati (in cazul acesta una din arhivele {*preONI 2007*}) si veti putea folosi link-ul trimite solutii.\r\n\r\nh2. Evaluare\r\n\r\nDupa expirarea timpului de trimitere a solutiilor acestea vor fi evaluate (\"mai multe detalii aici\":documentatie/evaluator). In mod normal, evaluarea se va face imediat dupa concurs, desi exista posibilitatea ca echipa infoarena sa amane evaluarea din motive obiective. Veti putea vizualiza pozitia ocupata in clasament dupa evaluarea in rubrica Clasament.\r\n\r\nSe recomanda sa instalati pe calculatorul vostru aceleasi versiuni de compilatoare ca cele specificate la link-ul de mai sus. \'Echipa infoarena\':echipa-infoarena nu este responsabila pentru diferentele intre versiuni de compilatoare si nu va efectua reevaluaari in astfel de cazuri.\r\n\r\nh2. Contestatii\r\n\r\nEchipa infoarena isi rezerva dreptul de a reevalua orice problema in situatia in care se detecteaza erori in teste sau in programul de verificare dupa evaluare. Cum testele problemelor nu vor fi facute publice, posiblitatile de a contesta sunt limitate. Pentru a asigura o evaluarea corecta, echipa infoarena va garanteaza ca va testa intens toate problemele inainte de concurs si ca va verifica corectitudinea procesului de evaluare dupa terminare. In caz ca totusi aveti o contestatie, aceasta trebuie trimisa pe mail la adresa _mircea.pasoi -at- gmail.com_ in termen de 24 de ore de la afisarea rezultatelor rundei curente pe site. Ele vor fi rezolvate in termen de maxim 5 zile, iar dupa rezolvarea lor rezultatele vor fi declarate finale.\r\n\r\nh2. Solutii\r\n\r\nLa scurt timp dupa terminarea evaluarii se va publica un articol cu solutiile pentru problemele rundei respective. Testele utilizate pentru evaluare nu vor fi facute publice.\r\n\r\nh2. Transferul problemelor\r\n\r\nProblemele vor fi mutate dupa evaluare in Arhiva de probleme infoarena, avand astfel la dispozitie un evaluator 24 din 24 si posiblitatea de a finisa solutiile la problemele nerezolvate in timpul concursului.\r\n\r\nh2. Trisare\r\n\r\n*preONI 2007* este un concurs individual, asadar orice tentativa de colaborare va aduce descalificarea celor implicati. \'echipa infoarena\':echipa-infoarena isi rezerva dreptul de a verifica sursele concurentilor, iar in caz ca se descopera surse aproximativ identice, concurentii respectivi vor fi descalificati din concurs iar user-ul lor de pe infoarena eliminat. Tentativele de frauda (concurarea sub un alt nume decat cel adevarat, etc.) sau orice atac asupra sistemului de evaluare sau asupra paginilor infoarena vor fi pedepsite in aceeasi masura. \r\n',1,'protected',NULL,NULL),('newsletter/2007-01-18','preONI 2007, Runda #1','2007-01-18 14:19:01','2009-01-20 00:55:46','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nIncepe o noua editie preONI, concursul cu premii care te pregateste\r\npentru Olimpiada Nationala de Informatica.\r\n\nPrima runda a concursului va avea loc ...\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Duminica, 21 ianuarie 2007, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPagina rundei: \'preoni-2007/runda-1\':preoni-2007/runda-1\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la aceasta runda iti va afecata rating-ul pe infoarena.\r\nO prestatie buna te poate aduce mai aproape te varful clasamentului.\r\n==NewsletterRating(username=\"%username%\")==\r\nRating-ul este un indicator al performantei tale in conditii de\r\nconcurs. Despre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Despre preONI \n\npreONI, concursul de marca al comunitatii infoarena, este dedicat\r\nelevilor de liceu ce se pregatesc pentru ONI (Olimpiada Nationala de\r\nInformatica).\r\n\nConcursul este impartit in 3 grupe: clasa a IX-a si gimnaziu, clasa\r\na X-a si clasele XI-XII. Se organizeaza 4 runde online de calificare.\r\nIn urma acestora, cei mai buni de la fiecare grupa sunt invitati la\r\no runda finala.\r\n\nIn cadrul unei runde, vei avea de rezolvat 3 probleme in 4h.\r\nCastigatorii rundei finale sunt premiati cu bani si/sau obiecte.\r\n\nPe pagina concursului ( \'preoni-2007\':preoni-2007 ) vei gasi\r\ninformatii despre cum participi, cine propune probleme, premii si\r\nsponsori, regulamentul concursului samd.\r\n\nh2.  Prima data la infoarena? \n\ninfoarena ajuta elevi si studenti sa devina excelenti in informatica!\r\nGratuit ;)\r\n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nGhidul utilizatorului: \'documentatie/pentru-utilizatori\':documentatie/pentru-utilizatori\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('runda/preoni-2007/clasament','Clasament preoni-2007','2007-01-19 23:27:51','2007-01-19 23:27:51','h1. Clasament ==roundparam(round_id=\"preoni-2007\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni-2007\")==',1,'round: preoni-2007',NULL,NULL),('runda/preoni2007_runda1_9/clasament','Clasament preoni2007_runda1_9','2007-01-20 21:42:53','2007-01-20 21:42:53','h1. Clasament ==roundparam(round_id=\"preoni2007_runda1_9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda1_9\")==',1,'round: preoni2007_runda1_9',NULL,NULL),('runda/preoni2007_runda1_10/clasament','Clasament preoni2007_runda1_10','2007-01-20 22:41:46','2007-01-20 22:41:46','h1. Clasament ==roundparam(round_id=\"preoni2007_runda1_10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda1_10\")==',1,'round: preoni2007_runda1_10',NULL,NULL),('runda/preoni2007_runda1_1112/clasament','Clasament preoni2007_runda1_1112','2007-01-20 22:47:03','2007-01-20 22:47:03','h1. Clasament ==roundparam(round_id=\"preoni2007_runda1_1112\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda1_1112\")==',1,'round: preoni2007_runda1_1112',NULL,NULL),('preoni-2007/clasament/runda-1/9','Clasament preONI 2007, Runda 1, Clasa a 9-a si gimnaziu','2007-01-20 22:51:55','2007-01-21 11:49:39','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda1_9\" param=\"title\") ==\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-1/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-1/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda1_9\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',13,'protected',NULL,NULL),('preoni-2007/clasament/runda-1/10','Clasament preONI 2007, Runda 1, Clasa a 10-a','2007-01-20 22:54:12','2007-01-21 11:49:27','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda1_10\" param=\"title\") ==\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-1/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/clasament/runda-1/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-1/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda1_10\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',13,'protected',NULL,NULL),('preoni-2007/clasament/runda-1/11-12','Clasament preONI 2007, Runda 1, Clasele 11-12','2007-01-20 22:54:56','2007-01-21 11:48:44','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda1_1112\" param=\"title\") ==\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-1/10\r\n*(active) \'Clasele 11-12\':preoni-2007/clasament/runda-1/11-12\r\n\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda1_1112\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',13,'protected',NULL,NULL),('lowest-common-ancestor','LCA: Lowest common ancestor','2004-11-08 00:00:00','2009-02-20 01:22:07','h1. LCA: Lowest common ancestor\r\n\r\n(Categoria _Algoritmi_, Autor _Emilian Miron_)\r\n\r\nProblema luata in discutie este ca, avand un arbore dat, sa putem raspunde rapid la multe intrebari de genul: _\"Care este stramosul comun cel mai apropiat dintre doua noduri din arbore?\"_.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Exemplu\':lowest-common-ancestor#exemplu\r\n* \'Aplicabilitate\':lowest-common-ancestor#aplicabilitate\r\n* \'Mod de calcul\':lowest-common-ancestor#calcul\r\n\r\n!> Lowest-common-ancestor?euler.jpg 80%!\r\n\r\nh2(#exemplu). Exemplu\r\n\r\nPentru arborele din imagine, avem ca exemplu urmatoarele query-uri:\r\n\r\n* $lca(2,3) = 1$\r\n* $lca(4,5) = 1$\r\n* $lca(5,6) = 3$\r\n* $lca(1,5) = 1$\r\n* $lca(5,3) = 3$\r\n\r\nh2(#aplicabilitate). Aplicabilitate\r\n\r\nDandu-se un arbore cu costuri sa se raspunda rapid la intrebari de genul: _\"care este distanta minima intre doua noduri date?\"_. O solutie pentru problema de fata ar fi:\r\n\r\n* agatam arborele intr-un nod oarecare si obtinem un arbore cu radacina\r\n* pentru fiecare nod $i$ precalculam {$dist{~i~}$}, reprezentand distanta sa pana la radacina\r\n* precalculam cele necesare pentru algoritmul de _Lowest Common Ancestor_\r\n* distanta dintre doua noduri oarecare $i$ si $j$ va fi egala cu {$dist{~i~} + dist{~j~} - 2*dist{~lca(i,j)~}$}\r\n\r\nh2(#calcul). Mod de calcul\r\n\r\nIn prima etapa a algoritmului facem o parcurgere euleriana a arborelui dat. O parcurgere euleriana este o parcurgere a arborelui in ordinea din figura: se parcurg fiii si se intercaleaza intre ei tatal, obtinand o parcurgere continua.\r\n\r\nMai exact pentru fiecare nod procedam astfel, incepand cu radacina:\r\n\r\n* daca nodul curent este frunza il adaugam la parcurgere\r\n* daca are fii atunci il punem la inceput, la sfarsit si intre parcurgerile euler ale fiilor\r\n\r\nCand facem aceasta parcurgere retinem de asemenea si urmatoarele informatii suplimentare:\r\n\r\n* adancimea fiecarui nod din parcurgere, obtinand un sir de adancimi\r\n* una din pozitiile pe care fiecare nod apare in parcurgere\r\n\r\nIdeea este ca {$lca(i, j)$} este chiar nodul cu cea mai mica adancime intre pozitiile lui $i$ si a lui $j$ in parcurgere. Pentru graful din figura de mai sus avem:\r\n\r\ntable(example). |_. Euler|_. Adancimi|\r\n|12421353631|12321232321|\r\n\r\nPentru perechea de noduri ({$4, 3$}), avem {$lca(4, 3)$} egal cu nodul care se gaseste intre {$poz{~4~}$} si {$poz{~3~}$} in parcurgerea euler si are adancimea minima. Acest nod este $1$, deci {$lca(4, 3) = 1$}.\r\n\r\nAm redus problema la aflarea minimului intre doua pozitii ale unui sir ({_Range Minimum Query_}). Aceasta subproblema o putem rezolva optim folosind arbori de intervale, sau o metoda folosind spatiu supraliniar ({$Nlog{~2~}N$}) a minimelor pe intervale de puteri ale lui {$2$}, incepand de la pozitia {$i$}. Timpul de preprocesare este {$O(N)$} pentru arbori de intervale si {$O(Nlog{~2~}N)$} pentru a doua metoda. In ambele variante timpul de interogare este {$O(log{~2~}N)$}.\r\n\r\nVom prezenta in continuare metoda cu spatiu supraliniar. Calculam minimele inductiv, pastrand:\r\n\r\n* {$min{~i,k~}$} = minimul pe intervalul {$[i...i+2^k^-1]$} (de lungime {$2^k^$}), si\r\n* {$minpos{~i,k~}$} = pozitia minimului de pe intervalul {$[i...i+2^k^-1]$}.\r\n\r\nAcest tablou va fi construit recursiv astfel: pentru $k = 0$ avem {$min{~i,0~} = a{~i~}$} si {$minpos{~i,0~} = i$}, iar pentru k > 0 avem:\r\n\r\n* {$min{~i,k~}$} = minim({$min{~i,k-1~}$}, {$min{~i+2^k-1^,k-1~}$})\r\n* {$minpos{~i,k~}$} = pozitia minimului ({$minpos{~i,k-1~}$} sau {$minpos{~i+2{^k-1^},k-1~}$})\r\n\r\nPentru _query_ intre pozitiile $l$ si $r$ procedam astfel: fie $k$ cel mai mare numar astfel incat {$2^k^$} &le; lungimea intervalului {$(l, r)$}.\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp; {$min(l, r)$} = minim( {$min{~l,k~}$}, {$minimul pe intervalul (l+2^k^, r)$})\r\n&nbsp;&nbsp;&nbsp;&nbsp; {$pozmin(l, r)$} = pozitia minimului intre $l$ si $r$\r\n\r\nDaca {$l = pos{~i~}$} si {$r = pos{~j~}$} ({$pos{~i~} < pos{~j~}$}) la sfarsitul _query_-ului {$euler{~pozmin~}$} este chiar {$lca(i, j)$}.\r\n',2044,'public',3699,NULL),('preoni-2007/runda-1/9','preONI 2007, Runda 1, Clasa a 9-a si gimnaziu','2007-01-20 21:44:57','2007-01-21 14:12:45','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda1_9\" param=\"title\") ==\r\n\r\n==roundregister(round_id=\"preoni2007_runda1_9\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-1/9.\r\n\r\nRunda s-a desfasurat Duminica 21 ianuarie, la ora {*09^30^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda1_9\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',13,'protected',NULL,NULL),('preoni-2007/runda-1/10','preONI 2007, Runda 1, Clasa a 10-a','2007-01-20 22:43:46','2007-01-21 14:13:37','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda1_10\" param=\"title\") ==\r\n\r\n==roundregister(round_id=\"preoni2007_runda1_10\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-1/10.\r\n\r\nRunda s-a desfasurat Duminica 21 ianuarie, la ora {*09^30^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda1_10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',13,'protected',NULL,NULL),('preoni-2007/runda-1/11-12','preONI 2007, Runda 1, Clasele 11-12','2007-01-20 22:50:14','2007-01-21 14:14:30','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda1_1112\" param=\"title\") ==\r\n\r\n==roundregister(round_id=\"preoni2007_runda1_1112\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-1/11-12.\r\n\r\nRunda s-a desfasurat Duminica 21 ianuarie, la ora {*09^30^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda1_1112\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',13,'protected',NULL,NULL),('blog/preoni-2007-runda-1','S-a incheiat Runda din preONI 2007!','2007-01-22 22:04:00','2007-01-22 22:04:00','h1. S-a incheiat Runda din preONI 2007!\r\n\r\nPrima runda a concursului \'preONI 2007\':preoni-2007 s-a incheiat. Gasiti pe \'pagina rundei\':preoni-2007/runda-1 problemele , clasamentele si articolul cu solutii.',1,'public',NULL,NULL),('preoni-2007/runda-1','Runda 1 preONI 2007','2007-01-15 15:59:43','2007-01-22 22:04:38','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Runda 1\r\n\r\nRunda 1 s-a incheiat.\r\n\r\nRunda a inceput Duminica 21 ianuarie, la ora {*09^30^*} si a durat 4h. Participantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np{color:red}. *ATENTIE!* Ca sa poata participa la aceasta runda, concurentii au trebuit sa se inscrie *inainte de ora 09^30^* la grupa de varsta corespunzatoare! *Nu au putut participa* elevii care nu s-au inscris la o grupa de varsta *inainte de ora 09^30^*.\r\n\r\nAceeasi procedura se va urma la fiecare runda preONI. Timp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, concurentii nu pot participa daca nu s-au inscris.\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta&hellip;\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-1/10\r\n* \'Clasele 11-12\':preoni-2007/runda-1/11-12\r\n\r\nPoti vedea solutiile problemelor \'aici\':preoni-2007/runda-1/solutii\r\n\r\nh2. Clasament Runda 1\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-1/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-1/11-12\r\n\r\nh2. Discutii preONI pe forum\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\nh2. Organizatori\r\n\r\n* Subiectele vor fi propuse de:\r\n==User(user=\"danielp\" type=\"tiny\")==\r\n==User(user=\"ditzonec\" type=\"tiny\")==\r\n==User(user=\"domino\" type=\"tiny\")==\r\n==User(user=\"filipb\" type=\"tiny\")==\r\n==User(user=\"greco\" type=\"tiny\")==\r\n\r\n* Pentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n==User(user=\"fluffy\" type=\"tiny\")==\r\n==User(user=\"svalentin\" type=\"tiny\")==\r\n==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('template/preoni-2007/clasament-header','template/preoni-2007/clasament-header','2007-01-21 11:47:40','2007-01-22 22:01:54','&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;',1,'protected',NULL,NULL),('template/userheader','template/userheader','2006-12-02 18:14:52','2007-01-21 14:06:01','h1. ==UserInfo(user=\"%user%\" info=\"fullname\")== (%user%)\r\n\r\n== include(page=\"template/userinfo\" user=\"%user%\") ==\r\n',13,'protected',NULL,NULL),('runda/unirea9-10/clasament','Clasament unirea9-10','2007-01-22 16:12:12','2007-01-22 16:12:12','h1. Clasament ==roundparam(round_id=\"unirea9-10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"unirea9-10\")==',1,'round: unirea9-10',NULL,NULL),('runda/unirea11-12/clasament','Clasament unirea11-12','2007-01-22 16:31:00','2007-01-22 16:31:00','h1. Clasament ==roundparam(round_id=\"unirea11-12\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"unirea11-12\")==',1,'round: unirea11-12',NULL,NULL),('preoni-2007/runda-1/solutii','Solutii preONI 2007, Runda 1','2007-01-21 08:46:01','2007-02-21 18:28:09','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Solutii Runda 1\r\n\r\nh2. Aprindere \r\n\r\nh3. (problema usoara, clasa a 9-a)\r\n\r\nEste evident ca nu are rost sa actionam un intrerupator de mai multe ori. In aceste conditii, solutia este unica, deoarece nu putem avea doua intrerupatoare intr-o singura camera. Cu alte cuvinte, daca parcurgem camerele de la stanga la dreapta si intalnim o camera cu becul inchis, va trebui sa actionam intrerupatorul unic din camera respectiva. Daca am fi permis ca o camera sa aiba mai multe intrerupatoare, problema s-ar fi complicat semnificativ.\r\nSe pot afla usor intrerupatoarele care trebuie actionate astfel: se parcurg camerele de la stanga la dreapta, iar in momentul in care ajungem la o camera cu becul inchis trebuie sa actionam intrerupatorul din camera respectiva (daca nu exista intrerupator, atunci nu avem solutie). Cum intrerupatorul respectiv actioneaza becuri din camere &ge; $i$, nu vom modifica nimic din becurile precedente. De asemenea, vom aduna costul lor la rezultat. \r\n\r\nh2. Patrate3 \r\n\r\nh3. (problema medie, clasa a 9-a)\r\n\r\nMai intai sortam punctele crescator dupa abscisa, iar pentru abscise egale dupa ordonata. Acum, folosind cautarea binara putem cauta orice punct in timp logaritmic. Pentru fiecare pereche de puncte vom forma patratul care are o diagonala formata din perechea respectiva. Dupa ce calculam si celelalte 2 puncte, le cautam binar in vectorul sortat. Daca le gasim, inseamna ca am mai gasit un patrat. Complexitatea solutiei este $O(N^2^ log N)$. Precizia recomandata este de $10^-4^$.\r\nSingura problema care ramane de rezolvat acum e calcularea punctelor patratului daca stim doar o diagonala. O metoda simpla de gasire a lor, ce nu necesita cunostiinte avansate de geometrie, este observarea simetriilor care se formeaza fata de centrul patratului. Fie $x0, y0$ si $x1, y1$ coordonatele diagonalei cunoscute iar $x2, y2$ si $x3, y3$ coordonatele necunoscute. Centrul patratului este mijlocul unei diagonale, deci coordonatele lui sunt $mijx = (x0 + x1) / 2$ si $mijy = (y0 + y1) / 2$. Sa notam $dx = abs(mijx - x0)$ si $dy = abs(mijy - y0)$. Se observa ca daca $y0 < y1$ atunci $x2 = mijx + dy, y2 = mijy - dx, x3 = mijx - dy$ iar $y3 = mijy + dx$. In caz contrar, avem $x2 = mijx - dy, y2 = mijy - dx, x3 = mijx + dy$ iar $y3 = mijy + dx$.\r\n\r\nh2. Elimin \r\n\r\nh3. (problema grea, clasa a 9-a / problema medie, clasa a 10-a)\r\n\r\nDaca $S$ este suprafata ( aria ) matricii, este evident ca {$minim(M, N) &le; sqrt(S)$}. Pentru primele $3$ teste se observa ca cel putin o dimensiune este &le; 10. Pentru celelalte teste avem:\r\n\r\n* 266 = 2 * 7 * 19\r\n* 539 = 7 * 7 * 11\r\n* 1630 = 2 * 5 * 163\r\n* 3495 = 3 * 5 * 233\r\n* 3653 = 13 * 281\r\n* 5866 = 2 * 7 * 419\r\n* 7294 = 2 * 7 * 521\r\n\r\nSe observa ca in toate cazurile de mai sus, oricum am grupa numerele prime pentru a obtine dimensiunile matricii, cea mai mica dintre dimensiuni nu poate depasi {$15$}. Deci, in toate testele, stim sigur ca {$min(M, N) &le; 15$}. Sa presupunem ca aceasta dimensiune este numarul coloanelor, {$N$}, celalalt caz rezolvandu-se identic, rotind matricea.\r\nPutem genera toate posibilitatile de a elimina exact {$C$} coloane din numarul total de {$N$}. Pentru fiecare caz generat, calculam suma elementelor ramase pentru fiecare linie in parte, si sortam aceste sume. Evident, vom elimina cele mai mici {$R$} sume.\r\nComplexitatea unui astfel de algoritm este deci {$O(2^N^  * (M log M + M*N))$}.\r\n\r\nh2. Triplete\r\n\r\nh3. (problema usoara, clasa a 10-a)\r\n\r\nPutem considera cele $N$ animale ca fiind noduri ale unui graf neorientat si o relatie de forma $i j$ ca fiind muchie intre nodurile $i$ si {$j$}. Problema cere determinarea numarului de triunghiuri in graful astfel construit ( numarul de triplete de noduri astfel incat intre oricare doua noduri din triplet exista muchie ). O solutie imediata are complexitatea {$O(N^3^)$}, prin generarea tuturor tripletelor. O solutie mai buna se bazeaza pe urmatorul rationament: pentru fiecare muchie din graf $a b$ trebuie sa vedem cate noduri adiacente cu $a$ si $b$ exista in graf ( adica cate triunghiuri care contin nodurile $a$ si $b$ se pot forma ). Pentru o muchie fixata este suficienta iterarea prin lista de adiacenta a nodurilor $a$ si $b$ si adunarea la numarul total de solutii a numarului de noduri comune. Acest algoritm are complexitatea {$O(M * N)$}, pentru ca parcurgerea unei liste de adiacenta se realizeaza in $O(N)$. Algoritmul de mai sus poate fi optimizat prin tinerea pe grupuri de biti a listei de adiacenta. Astfel, pentru orice nod {$i$}, primii $B$ biti din lista lui de adiacenta vor reprezenta legaturile cu primele $B$ noduri din cele {$N$} ( bit 1 pentru legatura si 0 altfel ), urmatorii $B$ biti legaturile cu nodurile $B+1...2*B$, etc. Pentru a vedea cate noduri adiacente comune au $a$ si $b$ este suficient sa realizam o operatie AND intre grupurile corespunzatoare de biti din listele de adiacenta ale lui $a$ si ale lui $b$ si sa adunam la numarul total de solutii numarul de biti de 1 din acest numar. Complexitatea acestui algoritm este {$O(M*N/B)$}, unde $B$ este numarul de biti dintr-un grup.\r\n\r\nh2. Pachete\r\n\r\nh3. (problema grea, clasa a 10-a)\r\n\r\nSa consideram initial ca oficiul postal este in punctul de coordonate {$(0, 0)$} si restul oraselor au coordonate pozitive ( sunt toate in primul cadran ). Se sorteaza orasele dupa abscisa {$X$}. Dupa sortare, acestea trebuie partitionate intr-un numar minim de subsiruri astfel incat intr-un subsir coordonatele punctelor ({$Y$}) sa fie crescatoare. Un astfel de subsir reprezinta drumul unui postas (este de cost minim deoarece mereu merge in dreapta si in sus). Algoritmul optim pentru aflarea numarului minim de subsiruri crescatoare in care poate fi partitionat un sir are complexitatea {$O(NlogN)$}. Primul element va face parte din primul subsir. La pasul {$i$}, {$i>1$}, elementul al $i$-lea va fi introdus in acel subsir care se termina intr-un element cu valoare mai mica decat elementul curent si care are valoarea maxima dintre toate elementele de acest tip. Cautarea se poate face cu o cautare binara in raport cu ultimele pozitii pentru fiecare subsir, pentru ca se observa ca printr-un astfel de procedeu ultimile valori vor fi intotdeauna sortate descrescator.\r\nDaca oficiul postal se afla in {$(Px, Py)$}, acest punct imparte planul in {$4$} cadrane, si se aplica aceeasi rezolvare de mai sus pentru fiecare cadran.\r\n\r\n\r\nh2. 1-sir\r\n\r\nh3. (problema usoara, clasele 11-12)\r\n\r\nPrima observatie este aceea ca valoarea maxima pe care o poate lua $S$ este {$N * (N-1) / 2$}, sirul {$s$} fiind egal cu {$(0, 1, 2... N-1)$}, iar valoarea minima {${@-N * (N-1) / 2@}$}, caz in care sirul este egal cu {$(0, {@-1@}, {@-2@}... {@-(N-1)@})$}. Daca notam cu {$D[N][S]$} numarul de 1-siruri cu $N$ termeni care au suma elementelor $S$, atunci se observa ca {$D[N][S] = D[N-1][S-(N-1)] + D[N-1][S+(N-1)]$}, deoarece avem doua posibilitati de alegere pentru al doilea element (1 sau -1), si fiecare alegere poate fi interpreta ca o translatie pentru fiecare din elementele urmatoare cu 1 sau -1 ( deci in total o translatie in functie de suma de {$N-1$}, cu plus sau cu minus ). Pentru a evita folosirea indicilor negativi pentru suma este suficient sa observam ca {$D[N][S] = D[N][-S]$}, pentru orice {$S > 0$}, relatie evidenta din faptul ca se poate forma o bijectie intre 1-sirurile cu suma {$S$} si cele cu suma {${@-S@}$} printr-o simpla inmultire cu -1. Pentru ca algoritmul sa se incadreze in limita de memorie este suficient sa retinem doar ultimele doua linii din tabloul $D$. Un astfel de algoritm are complexitate $O(N^3^)$ si obtine punctajul maxim.\r\n\r\nh2. Diviz\r\n\r\nh3. (problema medie, clasele 11-12)\r\n\r\nProblema se rezolva prin metoda programarii dinamice. Fie {$M[j][i]{@[r]@}$} numarul de moduri de a alege subsiruri distincte de lungime $j$ care contin ca ultima cifra cea de-a $i$-a cifra a numarului {$N$}, subsiruri care sa dea restul $r$ la impartirea {$K$}. Daca ne aflam in starea {$(j, i, r)$} putem sa actualizam starea {$(j+1, first[cif][i+1], (r*10+cif) mod K)$}, considerand ca am adaugat la sfarsitul fiecarui subsir definit de {$(j, i, r)$} cifra {$cif$}. Prin {$first[cif][i]$} se defineste prima aparitie in numarul $N$ a cifrei $cif$ dupa pozitia {$i$}. Tabloul $first$ va fi, evident, preprocesat. Pentru a nu numara subsirurile egale de doua ori, trebuie sa initializam pentru lungimea 1 doar pozitiile care contin pentru prima oara o cifra. Astfel initializam starile {$(1, @first[cif][0]@, cif mod K)$} cu 1, pentru cif = 1..9 (ca nu cumva un subsir sa inceapa cu 0). Pe parcurs, adunam la solutie starile care au lungimea cuprinsa intre $A$ si $B$ si care au $r$ egal cu 0.\r\n\r\nComplexitatea finala a algoritmului este {$O(K * L^2^)$}, unde L este numarul de cifre ale numarului {$N$}.\r\n\r\nh2. Radiatie\r\n\r\nh3. (problema grea, clasele 11-12)\r\n\r\nPrimul pas in rezolvarea problemei este construirea arborelui partial de cost minim a grafului dat in {$O(M*logM)$}, folosind unul din algoritmii clasici precum Kruskal sau Prim. Se poate demonstra ca o interogare in graful initial este echivalenta cu o interogare in arborele partial minim.\r\nPentru a determina cea mai mare valoare a unei muchii pe drumul unic din arbore intre nodurile $i$ si $j$ procedam astfel: pentru orice nod $i$ din arbore si pentru orice $j$, fie {$A[i][j]$} = al {$2^j^$}-lea stramos al nodului $i$ in drumul spre radacina ( aleasa aleator la inceput ) si {$B[i][j]$} = muchia de cost maxim dintre cei {$2^j^$} stramosi ai nodului {$i$}. Precalculand aceste matrici in {$O(N*logN)$} se poate raspunde la un query in {$O(log N)$}, mergand inspre radacina simultan din $x$ si $y$ pe stramosi pe baza puterilor lui 2 pana cand intalnim primul nod care este stramos al ambelor noduri. La fiecare pas vom actualiza raspunsul prin compararea cu valorea elementelor corespunzatoare din tabloul $B$.\r\nO solutie si mai simpla de implementat este folosirea arborelui care rezulta in urma algoritmului lui Kruskal, renuntand la euristica de compresie a drumului, si folosind doar euristica dupa rang. Se poate demonstra ca o interogare in arborele partial minim este echivalenta cu o interogare in arborele de multimi disjuncte obtinut din algoritmul lui Kruskal. Cum acest arbore are inaltimea {$O(logN)$}, se poate folosi o parcurgere triviala pentru a raspunde la orice query.\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1931,'public',NULL,NULL),('utilizator/razvan_varnita','Profil razvan_varnita','2007-01-23 09:39:18','2007-02-12 20:40:13','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',5723,'public',NULL,NULL),('unirea-2007','Unirea 2007','2007-01-24 00:49:02','2007-02-09 20:28:11','h1. Unirea 2007\r\n\r\n(htabs)*(active) \'*Home*\':unirea-2007\r\n* \'Clasele IX-X\':unirea-2007/clasele-9-10\r\n* \'Clasele XI-XII\':unirea-2007/clasele-11-12\r\n* \'Rezultate\':unirea-2007/rezultate-9-10\r\n\r\n parte din cadrul manifestarilor _Zilele Unirii_, infoarena gazduieste un concurs de informatica online - *cu premii si diplome* - la care sunt invitati elevi din toata tara.\r\n\r\nConcursul incepe *Sambata, 27 ianuarie la ora 14^00^* si dureaza *3h*.\r\n\r\np{color:red}. *ATENTIE!* Pentru a participa la acest concurs, trebuie sa te inscrii inainte de ora 14^00^, 27 ian. la grupa de varsta corespunzatoare! Nu pot participa elevii care nu se inscriu la grupa lor de varsta inainte de ora 14^00^, 27 ian.\r\n\r\nInscrierea se face printr-un simplu click. Nu trebuie sa te inregistrezi din nou pe site!\r\n\r\nh2. Alege-ti grupa de varsta\r\n\r\n* \'*Clasele IX si X*\':unirea-2007/clasele-9-10\r\n* \'*Clasele XI si XII*\':unirea-2007/clasele-11-12\r\n\r\nSolutiile oficiale la probleme se gasesc \'aici\':unirea-2007/solutii.\r\n\r\nh2. Despre Unirea 2007\r\n\r\nIn perioada 26 - 28 ianuarie 2007, Colegiul National Unirea, Primaria Focsani, Inspectoratul Scolar Vrancea si Microsoft Romania organizeaza, in cadrul manifestarilor _Zilele Unirii_, intalnirea cu tema Resurse IT&amp;C in educatie.\r\n\r\nCele doua zile dedicate acestei intalniri vor cuprinde:\r\n\r\n* concurs online de informatica gazduit de infoarena.ro\r\n* concurs de proiecte realizate de elevi in domeniile: pagini web, software educational &amp; utilitar, multimedia\r\n* concurs de matematica\r\n\r\n&rarr; \'Vezi pagina oficiala a acestei manifestari\':http://unirea.lufo.ro/\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru.\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti probleme, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nh2. Prima data pe infoarena?\r\n\r\ninfoarena ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi.\r\n\r\nVezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n',1,'protected',NULL,NULL),('newsletter/2007-01-24','Concursul de informatica Unirea','2007-01-24 02:00:54','2009-01-20 00:55:46','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nTe invitam sa participi la Unirea 2007, un concurs de informatica\r\ngazduit de infoarena. Castigatorii vor primi diplome si premii din\r\npartea organizatorilor.\r\n\nConcursul se va desfasura ...\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Sambata, 27 ianuarie 2007, orele 14:00 - 17:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPe acesta pagina gasesti informatii detaliate despre concursul Unirea:\r\n\'unirea-2007\':unirea-2007\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la acest concurs iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te poate aduce mai aproape te varful clasamentului.\r\n==NewsletterRating(username=\"%username%\")==\r\nDespre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Prima data la infoarena? \n\ninfoarena ajuta elevi si studenti sa devina excelenti in informatica!\r\nGratuit ;)\r\n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nGhidul utilizatorului: \'documentatie/pentru-utilizatori\':documentatie/pentru-utilizatori\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nClick pe acest link ca sa nu mai primesti instiintari:\r\n\'account/%username%\':account/%username%\r\n\ninfoarena nu trimite mesaje nesolicitate!\r\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\n\n',13,'protected',NULL,NULL),('template/userinfo','template/userinfo','2006-11-12 18:39:53','2011-10-16 23:16:22','table(compact). |=/5. ==UserImage(user=\"%user%\" size=\"big\")==\r\n{\'Vezi solutiile trimise\':monitor?user=%user%}\r\n|_. Nume | == userinfo(user=\"%user%\" info=\"fullname\")== |\r\n| |_. Cont | ==userinfo(user=\"%user%\" info=\"username\")== |\r\n| |_. Rating | ==userinfo(user=\"%user%\" info=\"rating\")== |\r\n| |_. Statut | ==userinfo(user=\"%user%\" info=\"security\")== |\r\n|_. Forum | ==SmfLink(user=\"%user%\" link=\"pm\" caption=\"trimite mesaj privat\")==, ==SmfLink(user=\"%user%\" link=\"stats\" caption=\"vezi activitate\")== |\r\n\r\n\r\n',1,'protected',NULL,'127.0.0.1'),('unirea-2007/clasele-9-10','Unirea 2007, Clasele IX - X','2007-01-22 16:12:12','2007-02-09 20:27:58','h1. Unirea 2007\r\n\r\n(htabs)* \'*Home*\':unirea-2007\r\n*(active) \'Clasele IX-X\':unirea-2007/clasele-9-10\r\n* \'Clasele XI-XII\':unirea-2007/clasele-11-12\r\n* \'Rezultate\':unirea-2007/rezultate-9-10\r\n\r\n== roundregister(round_id=\"unirea9-10\") ==\r\n\r\nConcursul incepe *Sambata, 27 ianuarie, ora 14^00^* si dureaza *3 ore*.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"unirea9-10\" score=\"1\") ==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"36\" count=\"10\")==\r\n\r\nh2. Organizatori\r\n\r\n* Subiectele vor fi propuse de:\r\n==User(user=\"danielp\" type=\"tiny\")==\r\n==User(user=\"azotlichid\" type=\"tiny\")==\r\n\r\n* Pentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n',1,'round: unirea9-10',NULL,NULL),('unirea-2007/clasele-11-12','Unirea 2007, clasele 11-12','2007-01-22 16:31:00','2007-02-09 20:27:26','h1. Unirea 2007\r\n\r\n(htabs)* \'*Home*\':unirea-2007\r\n* \'Clasele IX-X\':unirea-2007/clasele-9-10\r\n*(active) \'Clasele XI-XII\':unirea-2007/clasele-11-12\r\n* \'Rezultate\':unirea-2007/rezultate-9-10\r\n\r\n== roundregister(round_id=\"unirea11-12\") ==\r\n\r\nConcursul incepe *Sambata, 27 ianuarie, ora 14^00^* si dureaza *3 ore*.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"unirea11-12\" score=\"1\") ==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"36\" count=\"10\")==\r\n\r\nh2. Organizatori\r\n\r\n* Subiectele vor fi propuse de:\r\n==User(user=\"ditzonec\" type=\"tiny\")==\r\n==User(user=\"domino\" type=\"tiny\")==\r\n\r\n* Pentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n',1,'round: unirea11-12',NULL,NULL),('unirea-2007/rezultate-11-12','Unirea 2007, Clasament pentru clasele XI-XII','2007-01-27 15:34:41','2007-01-27 15:36:37','(htabs)* \'*Home*\':unirea-2007\r\n* \'Clasele IX-X\':unirea-2007/clasele-9-10\r\n* \'Clasele XI-XII\':unirea-2007/clasele-11-12\r\n*(active) \'Rezultate\':unirea-2007/rezultate-11-12\r\n\r\np=. \'*Clasele IX-X*\':unirea-2007/rezultate-9-10 | *Clasele XI-XII*\r\n\r\nh2. Clasament XI-XII\r\n\r\n== Rankings(rounds=\"unirea11-12\") == \r\n',13,'protected',NULL,NULL),('blog/s-a-incheiat-unirea-2007','S-a incheiat concursul Unirea 2007','2007-01-27 16:48:30','2007-02-09 19:53:01','h1. S-a incheiat Unirea 2007\r\n\r\nEvaluarea a inceput imediat dupa terminarea timpului de lucru. \'Rezultatele au fost publicate\':unirea-2007/rezultate-9-10 iar problemele au fost adaugate in \'arhiva\':arhiva.\r\n\r\nLa acest concurs s-au inscris *342 de concurenti*. 237 concurenti au trimis cel putin o solutie. In total au fost evaluate *545 de solutii*.\r\n\r\nFelicitari tuturor concurentilor si in special castigatorilor :)\r\n\r\n\'*Vezi clasamentul Unirea 2007*\':unirea-2007/rezultate-9-10\r\n\r\nDe asemenea, in urma concursului au fost recalculate \'rating-urile\':documentatie/rating utilizatorilor. Vezi si \'cei mai bine cotati\':clasament-rating utilizatori infoarena.',13,'protected',NULL,NULL),('unirea-2007/solutii','Solutii Unirea 2007','2007-01-27 20:37:17','2008-01-30 17:43:18','h1. Solutii\r\n\r\n\r\nh2. Maxsecv\r\n\r\nh3. (clasele 9-10)\r\n\r\nSe observa ca secventa maxima de $1$ care se poate obtine are lungimea egala cu suma primelor doua secvente maxime din vectorul original. Printr-o operatie descrisa se pot alatura cu usurinta cele doua secvente. \r\nPentru obtinerea unei solutii liniare e suficient sa parcurgem vectorul de la stanga la dreapta si sa updatam la fiecare pas lungimea secventei curente de $1$. In momentul in care ajungem la capatul unei astfel de secvente facem un update pentru primul si al 2-lea maxim, dupa caz.\r\n\r\n\r\nh2. Chernel\r\n\r\nh3. (clasele 9-10)\r\n\r\nConsiderandu-se sirul $a{~1~} a{~2~} ... a{~N~}$ pentru un $N$ fixat, se observa ca dupa $N-1$ transformari, acesta devine $a{~1~} * C{~N-1~}^0^ + a{~2~} * C{~N-1~}^1^ + a{~3~} * C{~N-1~}^2^ + ... + a{~N~} * C{~N-1~}^N-1^$ . De aici reiese ca elementele sirului initial a calor valoare nu influenteaza numarul caracteristic (numarul din ultimul sir obtinut $modulo M$) sunt cele ai caror coeficienti sunt multipli ai lui $M$. Astfel problema se reduce la numararea combinarilor de $N-1$ luate cate $i$ (cu $i$ intre $0$ si $N-1$) care sunt multipli de $M$. Aceasta se realizeaza simplu \"generand\" combinarile respective: ne bazam pe recurenta $C{~N~}^k+1^ = C{~N~}^k^ * (n-k) / (k+1)$ si verificam cate dintre acestea sunt divizibile cu $M$. Problema este ca aceste valori vor deveni uriase destul de rapid, iar stocarea lor in memoria calculatorului este ineficienta. Din acest motiv nu se vor retine numerele propriu zise, ci doar exponentii factorilor primi ai lui $M$, (numarul maxim de factori primi ai lui fiind aproximat la $O(ln ln M)$, si $9$ pentru datele de test ale problemei) care se vor actualiza pentru fiecare combinare procesata.\r\nComplexitatea finala a algoritmului devine astfel $O(N * ln ln M)$.\r\n\r\nh2. Amenzi\r\n\r\nh3. (clasele 11-12)\r\n\r\nProblema se poate rezolva folosind metoda programarii dinamice. Se construieste matricea $A{~t,i~}$ in care se retine valoarea totala a amenzilor ce poate fi data pana la momentul $t$ astfel incat la momentul $t$ sa fim in intersectia {$i$}. Pentru toate muchiile ({$j,i$}) de cost $c$ vom compara {$A{~t,i~}$} cu {$A{~t-c,j~}$} alegand maximul dintre aceste valori. De fapt ar trebui inspectate toate valorile {$A{~t-c,j~}$} {$A{~t-c-1,j~}$} ... {$A{~1,j~}$} {$A{~0,j~}$} dar este clar ca maximul acestor valori se afla in {$A{~t-c,j~}$}. Deasemenea trebuie considerat cazul cand politistul sta pe loc deci ne vom uita si la valoarea din {$A{~t-1,i~}$}. Apoi politistul va da toate amenzile posibile la momentul respectiv in intersectia respectiva deci vom aduna respectiva suma la {$A{~t,i~}$}.\r\nAvand construita aceasta matrice se poate raspunde in $O(1)$ la fiecare intrebare.\r\nComplexitatea totala va fi $O(Tmax * M)$ ca timp si $O(Tmax * N)$ ca memorie. \r\n\r\nh2. Secventa 5\r\n\r\nh3. (clasele 11-12)\r\n\r\nVom construi o procedura cu ajutorul careia vom numara cate secvente exista care contin cel mult $X$ elemente distincte. Folosind aceasta procedura, rezultatul problemei va fi: numarul de secvente cu cel mult $U$ elemente distincte - numarul de secvente cu cel mult $L-1$ elemente distincte. \r\nLa primul pas, vom normaliza valorile din sirul de intrare, inlocuind fiecare valoare cu un numar de la $1$ la $N$ (spre exemplu sirul $13 13 47 9 9$ devine $1 1 2 3 3$). Aceasta normalizare se poate face in $O(N*lg N)$ cu o sortare, dar aceasta solutie va obtine doar $80$ de puncte. Pentru $100$ de puncte normalizarea trebuie facuta folosind o tabela \'hash\':tabele-hash-scurta-prezentare.\r\nFie $L{~i~}$ cel mai mic indice astfel incat secventa cu elementele $L{~i~}...i$ contine cel mult $X$ elemente distincte (cu alte cuvinte cea mai lunga secventa cu maxim $X$ elemente distincte care se termina pe pozitia $i$). Numarul total de subsecvente va fi $(1-L{~1~}+1) + (2-L{~2~}+1) + (3-L{~3~}+1) + ... + (N-L{~N~}+1)$.\r\nEste usor de aratat ca $L{~i~} &le; L{~i+1~}$ pentru orice $i$. Asadar, pe masura ce trecem de la $i$ la $i+1$ vom incepe calculul lui $L{~i+1~}$ de la valoarea $L{~i~}$. Pentru a stii la fiecare moment cate elemente distincte sunt in secventa $L{~i~}...i$ vom mentine un vector $V$ cu proprietatea ca $V{~x~}$ = de cate ori apare $x$ in secventa si o variabila $Nr$ reprezentand numarul de valori distincte din secventa. Valorea lui $Nr$ va creste doar cand $V{~x~}$ se schimba din $0$ in $1$, si va scade doar cand $V{~x~}$ se schimba din $1$ in $0$ (pentru un $x$ oarecare). Complexitatea totala a algoritmului este $O(N)$.',2044,'public',NULL,NULL),('sandbox/usermacrobug','sandbox/usermacrobug','2007-02-03 11:12:48','2007-04-18 07:23:27','\"Articol\":minimal-enclosing-circle scris de ==user(user=\"bogdan2412\" type=\"tiny\")==.\r\n',1,'public',NULL,NULL),('minimal-enclosing-circle','Minimal Enclosing Circle','2007-01-30 17:54:51','2010-04-01 18:59:37','h1. Minimal enclosing circle\r\n\r\n(Categoria _Geometrie_, Autor _Bogdan Tataroiu_)\r\n\r\nIn cadrul acestui articol vom analiza problema determinarii unui cerc de raza minima ce contine in interior sau pe circumferinta toate punctele dintr-un set dat. Aceasta problema mai poate fi gasita si sub denumirea de _Smallest Enclosing Circle_ sau _Mininum Spanning Circle_.\r\n\r\nh2. Algoritm naiv\r\n\r\nEste clar ca cercul de raza minima ce include toate punctele din setul dat trebuie sa aiba pe circumferinta cel putin 2 puncte, altfel am putea micsora raza cercului pana cand am atinge si al doilea punct. Daca pe cerc exista 2 puncte consecutive ce formeaza un arc de cerc mai mare de {$&pi;$}, atunci cercul poate fi micsorat, ducand centrul cercului inspre segmentul format de cele 2 puncte. Astfel, singurul caz in care cercul de raza minima contine doar 2 puncte pe circumferinta este atunci cand diametrul cercului este egal cu segmentul ce uneste cele 2 puncte, in celelalte cazuri cercul este determinat de 3 (sau posibil mai multe puncte) din set.\r\n\r\nDe aici este destul de usor de formulat un algoritm:\r\n\r\n* Se considera cercurile determinate de fiecare pereche de puncte din set, cu diametrul egal cu segmentul ce uneste cele 2 puncte, alaturi de cele determinate de oricare 3 puncte din set.\r\n* Se verifica care dintre acestea contin in interior toate punctele din set si se alege cel de raza minima.\r\n\r\nAlgoritmul descris are complexitate {$O(N^3^)$} pentru generarea cercurilor si inca {$O(N)$} pentru fiecare cerc pentru verificare, in total avand {$O(N^4^)$}.\r\n\r\nh2. Algoritm {$O(N^2^)$} !>minimal-enclosing-circle?schema.gif!\r\n\r\nAlgoritmul acesta se bazeaza pe aceleasi observatii ca mai sus. Se porneste de la un cerc mare care sigur cuprinde toate punctele si se micsoreaza la fiecare pas raza cercului cat mai mult posibil.\r\n\r\n# Se construieste un cerc de raza suficient de mare incat sa cuprinda toate punctele in mod sigur (raza infinit) si un centru ales aleator.\r\n# Se gaseste punctul cel mai departat de centrul cercului, notat cu {$A$}, si se micsoreaza raza cercului pana cand acesta atinge punctul.\r\nPractic raza cercului devine egala cu distanta dintre punctul {$A$} si centrul ales.\r\n# In cazul in care cercul trece deja prin 2 sau mai multe puncte trecem la pasul numarul 4. In caz contrar, se apropie centrul cercului de punctul {$A$}, determinat la punctul 2, pana cand cercul intersecteaza un nou punct. Acest lucru se poate implementa printr-o parcurgere a punctelor din set. Pentru fiecare punct {$B$} din set se calculeaza raza cercului astfel incat centrul cercului sa ramana pe aceeasi axa fata de puncutl {$A$} si {$B$} sa se afle pe cerc ( se formeaza un triunghi isoscel, care are ca baza segmentul AB si celelalte muchii egale cu raza. Se poate calcula raza cercului folosind teorema cosinusului. )\r\n# In acest moment avem un cerc determinat de cel putin 2 puncte. Dupa cum am zis mai sus, un cerc de raza minima nu trebuie sa contina 2 puncte consecutive ce formeaza un arc de cerc mai mare de {$&pi;$}. Daca cercul nostru nu contine un astfel de arc de cerc, atunci am determinat cercul de raza minima pentru setul de puncte. In caz contrar, notam cu {$D$} si {$E$} aceste 2 puncte. Pentru a micsora lungimea arcului dintre cele doua puncte, translatam centrul cercului pe directia perpendiculara cu segmentul {$DE$}, inspre acest segment pana cand:\r\n## centrul cercului ajunge pe segmentul {$DE$}. In acest moment {$DE$} a devenit diametru in cerc si am determinat cercul de raza minima\r\n## cercul intalneste un alt punct {$F$}. Daca mai exista 2 puncte consecutive pe cerc care se formeaza un arc de cerc cu lungime mai mare de {$&pi;$}, atunci trebuie sa repetam pasul 4. In caz contrar, am ajuns la solutie.\r\n\r\nAlgoritmul este destul de usor de vizualizat, dar destul de dificil de implementat ( trebuie cateva cunostinte de geometrie ). Fiecare pas din algoritm are complexitate {$O(N)$}, dar pasul 4 poate fi repetat de maxim {$N - 2$} ori, ceea ce duce in final la o complexitate {$O(N^2^)$}.\r\n\r\nh2. Algoritm {$O(N)$}\r\n\r\nAlgoritmul acesta construieste cercul in mod incremental, adaugand pe rand puncte in cercul de raza minima.\r\n\r\nNotam cu {$C{~I~}$} cercul de raza minima ce contine in interior punctele din setul {$I$}.\r\n\r\nPentru fiecare punct {$P$}, putem determina in timp constant daca punctul se afla in interiorului cercului {$C{~I~}$}. In cazul in care {$P$} este inclus in {$C{~I~}$}, atunci {$C{~I &#8746; {P}~}$} va fi egal cu {$C{~I~}$}. In caz contrar, trebuie sa schimbam cercul {$C{~I~}$} pentru a cuprinde si acest punct. Cercul ce cuprinde toate punctele va fi evident {$C{~S~}$}, unde {$S$} este setul de puncte dat. Singura problema este cum determinam acel cerc modificat.\r\n\r\nVom demonstra in continuare ca daca punctul {$P$} se afla in exteriorul cercului {$C{~I~}$}, atunci el trebuie sa fie pe circumferinta cercului {$C{~I &#8746; {P}~}$}.\r\n\r\n* {!>minimal-enclosing-circle?figura.png 40%!} Dandu-se doua cercuri de raza {$R{~1~}$} si {$R{~2~}$}, avand {$R{~1~} < R{~2~}$}, atunci intersectia cercului de raza {$R{~2~}$} cu interiorul cercului de raza {$R{~1~}$} formeaza un arc de cerc de lungime mai mica decat {$&pi;$} (cel albastru in poza alaturata). Daca arcul de cerc ar avea o lungime mai mare ca {$&pi;$} atunci acesta ar trebui sa contina 2 puncte diametral opuse, aflate la o distanta de {$2R{~2~}$}, insa in cercul de raza {$R{~1~}$} cea mai mare distanta intre 2 puncte din interiorul sau poate fi maxim {$2R{~1~}$}. Cum {$R{~1~} < R{~2~}$}, acest lucru este imposibil.\r\n* Presupunem prin reducere la absurd ca {$P$} nu apartine circumferintei cercului {$C{~I &#8746; {P}~}$}. Este usor de vazut ca raza cercului {$C{~I~}$} este mai mica ca cea a cercului {$C{~I &#8746; {P}~}$}, deoarece {$C{~I &#8746; {P}~}$} cuprinde un punct care nu este cuprins de {$C{~I~}$}. Daca notam cu {$R{~1~}$} raza cercului {$C{~I~}$} si cu {$R{~2~}$} raza cercului {$C{~I &#8746; {P}~}$}, atunci intersectia cercului {$C{~I &#8746; {P}~}$} cu interiorul cercului {$C{~I~}$} este un arc de cerc de lungime mai mica ca {$&pi;$}.\r\n* Datorita faptului ca {$P$} nu apartine circumferintei cercului {$C{~I &#8746; {P}~}$}, punctele care definesc cercul {$C{~I &#8746; {P}~}$} se afla printre punctele din setul {$I$}. Cum toate aceste puncte se afla in interiorul cercului {$C{~I~}$} si intersectia cercului {$C{~I &#8746; {P}~}$} cu interiorul cercului {$C{~I~}$} este un arc de cerc de lungime mai mica decat {$&pi;$}, punctele care determina cercul {$C{~I &#8746; {P}~}$} trebuie sa se afle pe acest arc de cerc. Astfel avem cel putin 2 puncte consecutive pe circumferinta cercului {$C{~I &#8746; {P}~}$} care formeaza un arc de cerc de lungime mai mare {$&pi;$} (cel rosu in poza alaturata).\r\n* Acest lucru intra in contradictie cu faptul ca cercul are raza minima. Astfel {$P$} trebuie sa se afle pe circumferinta cercului {$C{~I &#8746; {P}~}$}.\r\n\r\nAcum trebuie doar sa calculam cel mai mic cerc care contine punctele din setul I in interior si care are punctul {$P$} pe circumferinta. Vom extinde {$C{~I~}$} adaugand un nou parametru. Astfel notam cu {$C{~I,B~}$} cercul de raza minima ce contine setul {$I$} de puncte in interior si punctele din setul {$B$} pe circumferinta (pot exista si alte puncte pe circumferinta, dar cele din setul {$B$} sunt fortate). Cercul de raza minima care contine toate punctele va fi {$C{~S,&#216;~}$}.\r\n\r\nCalcularea lui {$C{~I,B~}$} se va face in mod recursiv. Mai jos voi prezenta un pseudocod pentru functia respectiva:\r\n\r\n==code(c) |\r\nCerc MINCIRCLE( Set I, Set B )\r\n    Daca |I| == 0 sau |B| >= 3\r\n        returneaza cercul format de punctele din B\r\n    P = punct random apartinand setului I\r\n    C = MINCIRCLE( I - {P}, B )\r\n    Daca P nu este inclus in C\r\n        returneaza MINCIRCLE( I - {P}, B + {P} )\r\n    returneaza C\r\n==\r\n\r\nSingurul lucru care mai ramane de demonstrat este _de ce_ complexitatea este {$O(N)$}.\r\n\r\nPentru {$|B|$} egal cu 3, cercul este foarte usor de determinat in complexitate {$O(1)$}.\r\n\r\nPentru {$|B|$} egal cu 2, complexitatea este evident {$O(N)$}, deoarece calcularea cercului de raza minima pentru setul {$B + {P}$} se rezolva in {$O(1)$}.\r\n\r\nPentru {$|B|$} egal cu 1, notam cu {$T(N)$} numarul mediu de operatii folosite pentru a calcula {$C{~S,B~}$}, unde {$|S|$} este egal cu {$N$}.\r\n\r\nDin setul {$I$} vom scoate un element la fiecare apelare a functiei MINCIRCLE, deci pentru a calcula numarul mediu de operatii pentru {$N$} elemente, adunam numarul mediu de operatii pentru {$N - 1$} elemente ({$T(N - 1)$}). \r\nFiecare punct din {$I$} are probabilitatea {$^1^/{~N~}$} de a fi ales in cadrul functiei. Din aceasta cauza, functia MINCIRCLE{$(I - {P}, B &#8746; {P})$} va fi apelata cu o probabilitate egala cu (numarul de puncte {$P$} care nu apartin cercului {$C{~I - {P},B~}$}) / {$N$}. De asemenea, fiecare apel al acestei functii are complexitatea {$O(N)$}, dupa cum am demonstrat mai sus pentru {$|B|$} egal cu 2.\r\n\r\nAstfel {$T(N)$} respecta relatia: \r\n\r\n* {$T(N) <= T(N - 1) + Probabilitatea( P &notin; C{~I - {P},B~} ) * O(N) + O(1)$}\r\n\r\nDatorita faptului ca cercul de raza minima care cuprinde toate punctele din setul {$I$} este determinat de 2 sau 3 puncte, la fiecare apel al functiei exista maxim 3 puncte pentru care cercul {$C{~I - {P},B~}$} va trebui marit. Astfel probabilitatea ca {$P$} sa nu apartina cercului {$C{~I - {P},B~}$} este egala cu {$^3^/{~N~}$}. Inegalitatea devine:\r\n\r\n* {$T(N) <= T(N - 1) + ^3^/{~N~}*O(N) + O(1)$}\r\nceea ce este echivalent cu\r\n* {$T(N) <= T(N - 1) + O(1)$}\r\n\r\nAstfel complexitatea devine {$O(N)$}. Demonstratia pentru {$|B|$} egal cu 0 se face in mod asemanator.\r\n\r\n\r\nCa o ultima precizare, exista si un algoritm de complexitate {$O(N log N)$} pentru aceasta problema, ce foloseste diagrame voronoi.\r\n\r\nExercitii: \"SPOJ ALIENS\":http://www.spoj.pl/problems/ALIENS/',5433,'public',3684,NULL),('template/preoni-2007/header','template/preoni-2007/header','2007-01-13 23:35:51','2007-06-22 17:01:36','table{margin: 2em 0 0 0; width: 99%; background-image: url(/template/preoni-2007/header?action=download&file=hbk.png); background-repeat: repeat-x; background-position: 0 0;}. |{border: 0px;}. !template/preoni-2007/header/?logo.jpg!:/preoni-2007 |{border: 0px; text-align: right; vertical-align: middle}. !{border: 1px solid silver}preoni-2007?hostway.png!:http://www.hostwaylab.ro/ !{border: 1px solid silver}preoni-2007?ichb.png!:http://www.ichb.ro/ !{border: 1px solid silver}preoni-2007?irealsoft.png!:http://www.irealsoft.ro/ |\r\n',13,'protected',NULL,NULL),('blog/articol-minimal-enclosing-circle','Articol nou: \"Minimal enclosing circle\"','2007-02-01 20:42:20','2007-02-06 20:01:58','A aparut un articol nou despre problema \'Minimal enclosing circle\':minimal-enclosing-circle scris de Bogdan Tataroiu.',1,'public',NULL,NULL),('suffix-array-liniar','Suffix array in O(N)','2007-02-05 11:01:04','2009-02-20 00:39:57','h1. Suffix array in {$O(N)$}\r\n\r\n(Categoria _Structuri de date_, Autor _Cosmin Gheorghe_)\r\n\r\nIn articolul ce urmeaza voi prezenta o metoda de sortare lexicografica a tuturor sufixelor unui sir in timp liniar. \r\n\r\nh2. Obiectiv\r\n\r\nFie {$S$} un sir de caractere pe alfabetul {$[1, N]$}  ({$S$} este o secventa de numere din intervalul {$[1, N]$}). Restrictia de fata pe un alfabet {$[1, N]$} nu este foarte serioasa. Caracterele din sir se pot sorta initial si inlocui cu numere (normalizare).\r\n\r\nDorim obtinerea unui vector care contine toate sufixele sortate lexicografic. Structura rezultata se numeste suffix array si este foarte utila atat in aplicatii practice cat si la concursuri :).\r\n\r\n\r\nExecutia algoritmului va fi explicata pe sirul {$S = \"yabbadabbado\"$}\r\n{$0   1   2   3   4   5   6   7   8   9   10  11$}\r\n{$y   a   b   b   a   d   a   b   b   a    d   o$}\r\n\r\nCautam sa obtinem vectorul {$SS = {1, 6, 4, 9, 3, 8, 2, 7, 5, 10, 11, 0}$} (fiecare sufix este codificat cu pozitia sa de inceput in sir)\r\n\r\nh3. Notatii: \r\n\r\n* numim sufix de tip {$k$}, un sufix a carui pozitie de inceput da restul {$k$} prin impartire la {$3 (0 <= k < 3)$}\r\n* {$S{~i~}$} -> sufixul care incepe pe pozitia {$i$}\r\n* {$S[~k,i~]$} -> sufixul de tip {$k$} care incepe pe pozitia {$i$}\r\n* {$C[~i~]$} -> caracterul de pe pozitia {$i$} din sirul {$S$}\r\n\r\nh2. Algoritm\r\n\r\nh3. Pas {$0$}:\r\n\r\nImpartim sirul in bucati de cate trei astfel:\r\n{$[0 &nbsp;1 &nbsp;2][3 &nbsp;4 &nbsp;5][6 &nbsp;7 &nbsp;8][9 10 11]$}\r\n{$[y &nbsp;a &nbsp;b][b &nbsp;a &nbsp;d][a &nbsp;b &nbsp;b][a &nbsp;d &nbsp;o]$}\r\n\r\n(in functie de restul impartirii la 3 al pozitiilor sufixelor)\r\n\r\nh3. Pas {$1$}:\r\n\r\nSortam sufixele de tip {$1$} si {$2$}\r\n\r\nPentru aceasta formam sirul \r\n{$R = abbadabbado0bbadabbado00$}\r\nale carui caractere sunt tripletele:\r\n{$R = [abb][ada][bba][do0][bba][dab][bad][o00]$} (fiecare grup de {$3$} litere este luat ca un singur caracter)\r\n\r\nMai explicit vom imparti sirul {$S$} in felul urmator:\r\n{$( [C1 C2 C3][C4 C5 C6][C7 C8 C9] ... )$} + {$( [C2 C3 C4][C5 C6 C7][C8 C9 C10] ... )$} (unde {$A$} + {$B$} este concatenarea sirului {$A$} cu sirul {$B$})\r\nPentru {$C{~i~}$} cu {$i$} mai mare ca lungimea sirului {$C{~i~}$} este un caracter minim din punct de vedere lexicografic cu celelalte caractere (in cazul de fata {$0$}).\r\n\r\n\r\nPentru codificarea tripletelor in caractere, se poate folosi radix sort pentru sortarea tripletelor si apoi inlocuirea fiecaruia cu numarul care corespunde cu pozitia lui in sortare (se normalizeaza). Se obtine astfel sirul {$R\'$}.\r\n\r\n\r\nSe observa usor ca prin sortarea sufixelor din {$R\'$} se obtine ordinea relativa a sufixelor din {$S$} de tip {$1$} si {$2$}. Aceasta se face prin aplicarea aceluiasi algoritm recursiv pana la cazuri elementare.\r\n\r\n**Exemplu:**\r\n\r\n{$R\' &nbsp;= { 1, 2, 4, 6, 4, 5, 3, 7 }$}\r\n{$SR\' = { 0, 1, 6, 4, 2, 5, 3, 7 }$}\r\n\r\nh3. Pas {$2$}:\r\n\r\nSortam sufixele de tip {$0$}.\r\n\r\nPentru aceasta ne folosim de rezultatele obtinute la pasul anterior.\r\nOrice sufix de tip {$0$} poate fi considerat ca o pereche (caracter, sufix de tip {$1$}): {$S[~0,i~]$} = [$C{~i~}$] + {$S{~1,i+1~}$}\r\nSe poate folosi radix sort pentru a sorta aceste perechi.\r\n\r\nh3. Pas {$3$}:\r\n\r\nInterclasam cei doi vectori sortati de sufixe. Avem doua cazuri la comparare. Acestea pot fi reduse la compararea sufixelor de tip {$1$} cu sufixe de tip {$2$} astfel: \r\n\r\n# sufix de tip {$0$} ({$S{~i~}$}) cu sufix de tip {$1$} ({$S[~j~]$}) -> (caracter, sufix de tip {$1$}) - (caracter, sufix de tip {$2$}) : ({$C{~i~}$} + {$S{~1,i+1~}$}) - ({$C{~j~}$} + {$S{~2,j+1~}$})\r\n# sufix de tip {$0$} ({$S{~i~}$}) cu sufix de tip {$2$} ({$S{~j~}$}) -> (caracter, caracter, sufix de tip {$2$}) - (caracter, caracter, sufix de tip {$1$}) : ({$C{~i~}$} + {$C{~i+1~}$} + {$S{~2,i+2~}$}) - ({$C{~j~}$} + {$C{~j+1~}$} + {$S{~1,j+2~}$})\r\n\r\nh2. Analiza complexitatii:\r\n\r\nSe observa ca fiecare pas poate fi efectuat in timp liniar. \r\nAlgoritmul se repeta pe un sir de lungime {$2N / 3$}. De aici complexitatea poate fi data de recurenta {$T(N) = T(2N / 3) + O(N) => T(N) = O(N)$}.\r\n',2044,'public',3690,NULL),('newsletter','Newsletter Index','2007-02-09 17:49:55','2007-02-09 17:49:55','h1. Newsletter Index\r\n\r\n== Grep(page=\"newsletter/%\" substr=\"%\") ==',13,'public',NULL,NULL),('blog/articol-suffix-array','Articol nou: \"Suffix array in timp liniar\"','2007-02-06 20:01:39','2007-02-09 18:21:18','A aparut un articol nou despre \'constructia unui suffix array in timp liniar\':suffix-array-liniar scris de Gheorghe Cosmin.',13,'public',NULL,NULL),('winter-challenge-1/11-12/clasament','Clasament winter11-12','2007-02-09 17:50:16','2007-02-09 17:50:16','h1. Clasament ==roundparam(round_id=\"winter11-12\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"winter11-12\")==',1,'round: winter11-12',NULL,NULL),('winter-challenge-1/9-10/clasament','Clasament winter9-10','2007-02-09 17:44:30','2007-02-09 17:44:30','h1. Clasament ==roundparam(round_id=\"winter9-10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"winter9-10\")==',1,'round: winter9-10',NULL,NULL),('clubcampioni/arbori','Arbori','2007-02-08 10:55:54','2007-02-08 10:55:54','*Definitie*\r\n\r\n_Un graf neorientat, conex si aciclic se numeste arbore._\r\n\r\n\r\n*Definitie* \r\n\r\n_Fie G un graf. Numim arbore partial al grafului G un graf partial al lui G care este arbore._\r\n\r\nPrincipalele proprietatii ale arborilor pot fi sintetizate prin urmatoarele afirmatii echivalente:\r\n\r\n* G este un arbore cu _n_ noduri;\r\n* G este un graf conex cu _n_-1 muchii;\r\n* G este un graf aciclic cu _n_-1 muchii;\r\n* G este un graf conex minimal (prin suprimarea unei muchii, graful obtinut devine neconex);\r\n* G este un graf aciclic maximal (prin adauugarea unei muchii, graful obtinut va contine cicluri);\r\n* oricare doua varfuri din G sunt unite printr-un lant unic.\r\n\r\nIn majoritatea problemelor, arborii sunt folositi pentru ierarhizarea informatiilor ce corespund varfurilor arborelui. De aceea au fost introdusi arborii cu radacina.\r\n\r\n\r\n*Definitie*\r\n\r\n_Un arbore cu radacina este o multime finita A de noduri astfel incat:_ \r\n\r\n* _exista un nod numit radacina;_\r\n* _toate celelalte noduri sunt repartizate in _m_ multimi disjuncte A ~1~, A ~2~,.... A ~m~, fiecare multime fiind la randul sau arbore. Intre radacina arborelui si radacinile arborilor A ~1~, A ~2~,.... A ~m~ exista cate o muchie._\r\n\r\nObservam ca un arbore oarecare poate fi transformat intr-un arbore cu radacina prin alegerea arbitrara a unui nod din arbore drept radacina.\r\n\r\n\r\nIn ceea ce priveste arborii, majoritatea termenilor folositi aici deriva din vocabularul arborelui genealogic. Astfel afirmam ca radacina este _tatal_ radacinilor arborilor _A ~1~, A ~2~, ..., A ~m~_, iar acestea din urma sunt _fii_ ai radacinii arborelui. Nodurile cu acelasi tata (parinte) sunt numite _frati_. In mod similar sunt folositi termenii de _bunic, nepot, descendent, ascendent_ etc.\r\n\r\nUn arbore cu radacina poate fi etajat (ierarhizat). Consideram radacina ca aflandu-se pe nivelul 0, descendentii directi ai acesteia (fiii) pe nivelul 1, descendentii directi ai acestora din urma pe nivelul 2 etc. De exemplu, pentru arborele din figura 2, nodul 5 se afla pe nivelul 0, nodurile 1 si 7 pe nivelul 1, nodurile 3, 8, 4, 2 si 9 pe nivelul 2, iar nodul 6 pe nivelul 3.',1507,'public',NULL,NULL),('newsletter/winter-challenge-1','Concursul Winter Challenge','2007-02-09 17:58:33','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\ninfoarena organizeaza un nou concurs pentru tine.\r\nTe invitam sa participi la Winter Challenge!\r\n\nConcursul se va desfasura ...\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Duminica, 11 februarie 2007, orele 14:00 - 18:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPentru informatii detaliate despre concursul\r\nWinter Challenge, acceseaza: \'winter-challenge-1\':winter-challenge-1\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la acest concurs iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te poate aduce mai aproape de varful clasamentului.\r\n==NewsletterRating(username=\"%username%\")==\r\nDespre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Noutati \n\nAvem trei articole noi pentru tine, scrise de membrii\r\ninfoarena.\r\n\np{padding-left: 0.5em;}. * Suffix array in O(N) (Cosmin Gheorghe)\r\n   \'suffix-array-liniar\':suffix-array-liniar\r\n\np{padding-left: 0.5em;}. * Minimal enclosing circle (Bogdan Tataroiu)\r\n   \'minimal-enclosing-circle\':minimal-enclosing-circle\r\n \r\n * Taietura minima in graf cu costuri (Andrei Grigorean)\r\n   \'taietura-minima\':taietura-minima\r\n\nNu uita ca infoarena este un wiki!\r\nPoti chiar tu sa imbunatatesti articolele de mai sus,\r\nsau sa creezi altele noi.\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nGhidul utilizatorului: \'documentatie/pentru-utilizatori\':documentatie/pentru-utilizatori\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nClick pe acest link ca sa nu mai primesti instiintari:\r\n\'account/%username%\':account/%username%\r\n\ninfoarena nu trimite mesaje nesolicitate!\r\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\n\n',13,'protected',NULL,NULL),('utilizator/prostu','Profil Prostu','2006-11-24 21:03:08','2009-05-17 19:16:33','h2. Studii\r\n\r\n* Student la Universitatea Bucuresti, \"Facultatea de Matematica si Informatica\":http://fmi.unibuc.ro/ro/, sectia Informatica\r\n* Absolvent al \"Colegiului National de Informatica {@\"Tudor Vianu\"@}\":http://www.lbi.ro/, Bucuresti\r\n\r\nh2. Distinctii primite\r\n\r\n* 2008 - Premiul I la Olimpiada Nationala de Informatica; medalie de bronz la Olimpiada Central Europeana; tabara in Egipt\r\n* 2007 - Tabara in Cehia\r\n* 2004-2006 - Mentiuni la Olimpiada Nationala de Informatica\r\n\r\nh2. Dusmani pe infoarena\r\n\r\n* == User(user=\"eval\" type=\"normal\") == \r\n* == User(user=\"zuzi\" type=\"normal\") ==',2970,'protected',NULL,NULL),('winter-challenge-1','Concursul Winter Challenge','2007-02-09 17:43:38','2007-02-13 13:16:24','h1. Winter Challenge\r\n\r\n(htabs)*(active) \'*Home*\':winter-challenge-1\r\n* \'Clasele IX-X\':winter-challenge-1/9-10\r\n* \'Clasele XI-XII\':winter-challenge-1/11-12\r\n* \'Rezultate\':winter-challenge-1/rezultate-9-10\r\n\r\n*Concursul s-a incheiat. Felicitari castigatorilor!* \"*Vezi rezultatele*\":winter-challenge-1/rezultate-9-10\r\n\r\n&nbsp;\r\n\r\nOlimpiada de informatica bate la usa. Tu esti pregatit sa-i deschizi? Infoarena te ajuta sa-ti raspunzi la aceasta intrebare lansand o noua provocare (de iarna, de data aceasta). Duminica, 11 februarie, orele 14:00 participa la Winter Challenge si dovedeste ca stii unde-ti sunt cheile.\r\n\r\np{color:red}. *ATENTIE!* Pentru a participa la acest concurs, trebuie sa te inscrii inainte de ora 14^00^, 11 februarie la grupa de varsta corespunzatoare! Nu pot participa elevii care nu se inscriu la grupa lor de varsta inainte de ora 14^00^, 11 februarie!\r\n\r\nInscrierea se face printr-un simplu click. Nu trebuie sa te inregistrezi din nou pe site!\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru.\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti probleme, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"37\" count=\"10\")==\r\n\r\nh2. Prima data pe infoarena?\r\n\r\ninfoarena ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi.\r\n\r\nVezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n',1,'protected',NULL,NULL),('winter-challenge-1/9-10','Concursul Winter Challenge, Clasele IX - X','2007-02-09 17:44:30','2007-02-11 18:05:04','h1. Winter Challenge\r\n\r\n(htabs)* \'*Home*\':winter-challenge-1\r\n*(active) \'Clasele IX-X\':winter-challenge-1/9-10\r\n* \'Clasele XI-XII\':winter-challenge-1/11-12\r\n* \'Rezultate\':winter-challenge-1/rezultate-9-10\r\n\r\n*Concursul s-a incheiat.* \"*Vezi rezultatele*\":winter-challenge-1/rezultate-9-10\r\n\r\n&nbsp;\r\n\r\n== roundregister(round_id=\"winter9-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"winter9-10\" param=\"start_time\")== si dureaza ==roundparam(round_id=\"winter9-10\" param=\"duration\")== ore.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"winter9-10\" score=\"1\") ==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"37\" count=\"10\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse de:\r\n\r\n* ==User(user=\"fireatmyself\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!',13,'protected',NULL,NULL),('unirea-2007/rezultate-9-10','Unirea 2007, Clasament pentru clasele IX-X','2007-01-27 15:37:34','2007-02-09 20:27:04','h1. Unirea 2007\r\n\r\n(htabs)* \'*Home*\':unirea-2007\r\n* \'Clasele IX-X\':unirea-2007/clasele-9-10\r\n* \'Clasele XI-XII\':unirea-2007/clasele-11-12\r\n*(active) \'Rezultate\':unirea-2007/rezultate-11-12\r\n\r\np=. *Clasele IX-X* | \'*Clasele XI-XII*\':unirea-2007/rezultate-11-12\r\n\r\nh2. Clasament IX-X\r\n\r\n== Rankings(rounds=\"unirea9-10\") == \r\n',1,'protected',NULL,NULL),('blog/winter-challenge-1','Concursul Winter Challenge','2007-02-09 19:55:59','2007-02-11 14:20:48','h1. Winter Challenge\r\n\r\nInfoarena organizeaza concursul de informatica Winter Challenge. Acesta va avea loc *Duminica, 11 februarie la ora 14^00^* si dureaza *4h*.\r\n\r\nInformatii se gasesc pe \'pagina concursului\':winter-challenge-1.',13,'public',NULL,NULL),('winter-challenge-1/rezultate-11-12','Winter Challenge, Clasele XI - XII','2007-02-09 18:13:07','2007-02-11 16:57:20','h1. Winter Challenge\r\n\r\n(htabs)* \'*Home*\':winter-challenge-1\r\n* \'Clasele IX-X\':winter-challenge-1/9-10\r\n* \'Clasele XI-XII\':winter-challenge-1/11-12\r\n*(active) \'Rezultate\':winter-challenge-1/rezultate-9-10\r\n\r\np=. \'*Clasele IX-X*\':winter-challenge-1/rezultate-9-10 | *Clasele XI-XII*\r\n\r\nh2. Clasament XI-XII\r\n\r\n== Rankings(rounds=\"winter11-12\") == \r\n',13,'protected',NULL,NULL),('winter-challenge-1/11-12','Concursul Winter Challenge, Clasele XI - XII','2007-02-09 17:50:16','2007-02-11 17:11:32','h1. Winter Challenge\r\n\r\n(htabs)* \'*Home*\':winter-challenge-1\r\n* \'Clasele IX-X\':winter-challenge-1/9-10\r\n*(active) \'Clasele XI-XII\':winter-challenge-1/11-12\r\n* \'Rezultate\':winter-challenge-1/rezultate-9-10\r\n\r\n*Concursul s-a incheiat.* \"*Vezi rezultatele*\":winter-challenge-1/rezultate-11-12\r\n\r\n&nbsp;\r\n\r\n== roundregister(round_id=\"winter11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"winter11-12\" param=\"start_time\")== si dureaza ==roundparam(round_id=\"winter11-12\" param=\"duration\")== ore.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"winter11-12\" score=\"1\") ==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"37\" count=\"10\")==\r\n\r\nh2. Organizatori\r\n\r\n* Subiectele vor fi propuse de:\r\n==User(user=\"maxdamage\" type=\"tiny\")==\r\n==User(user=\"mugurelionut\" type=\"tiny\")==\r\n==User(user=\"fireatmyself\" type=\"tiny\")==\r\n\r\n* Pentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n',13,'protected',NULL,NULL),('winter-challenge-1/rezultate-9-10','Winter Challenge, Clasament pentru clasele IX-X','2007-02-09 18:12:53','2007-02-11 18:05:56','h1. Winter Challenge\r\n\r\n(htabs)* \'*Home*\':winter-challenge-1\r\n* \'Clasele IX-X\':winter-challenge-1/9-10\r\n* \'Clasele XI-XII\':winter-challenge-1/11-12\r\n*(active) \'Rezultate\':winter-challenge-1/rezultate-9-10\r\n\r\np=. *Clasele IX-X* | \'*Clasele XI-XII*\':winter-challenge-1/rezultate-11-12\r\n\r\nh2. Clasament IX-X\r\n\r\n== Rankings(rounds=\"winter9-10\") == \r\n',13,'protected',NULL,NULL),('runda/preoni2007_runda2_9/clasament','Clasament preoni2007_runda2_9','2007-02-13 12:54:19','2007-02-13 12:54:19','h1. Clasament ==roundparam(round_id=\"preoni2007_runda2_9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda2_9\")==',1,'round: preoni2007_runda2_9',NULL,NULL),('preoni-2007/runda-2','Runda 2 preONI 2007','2007-01-15 16:00:23','2007-02-18 14:50:50','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. preONI 2007, Runda 2\r\n\r\n(htabs)*(active) \'Despre...\':preoni-2007/runda-2\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/runda-2/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-2/9\r\n\r\n*Runda 2 s-a incheiat!*\r\n\r\nRunda a inceput Duminica 18 februarie, la ora {*09^00^*} si a durat *4h*. Participantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np{color:red}. *ATENTIE!* Ca sa poata participa la aceasta runda, concurentii au trebuie sa se inscrie *inainte de ora 09^00^* la grupa de varsta corespunzatoare! *Cei care nu s-au inscris* la o grupa de varsta nu li s-a modificat \'rating-ul\':documentatie/rating!\r\n\r\nAceeasi procedura se va urma la fiecare runda preONI. Timp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta&hellip;\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/runda-2/11-12\r\n\r\nPoti vedea solutiile problemelor \'aici\':preoni-2007/runda-2/solutii.\r\n\r\nh2. Clasament Runda 2\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-2/11-12\r\n\r\nh2. Discutii preONI pe forum\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\nh2. Organizatori\r\n\r\n* Subiectele au fost propuse de:\r\n==User(user=\"azotlichid\" type=\"tiny\")==\r\n==User(user=\"domino\" type=\"tiny\")==\r\n==User(user=\"filipb\" type=\"tiny\")==\r\n==User(user=\"greco\" type=\"tiny\")==\r\n\r\n* Pentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n==User(user=\"fluffy\" type=\"tiny\")==\r\n==User(user=\"svalentin\" type=\"tiny\")==\r\n==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('preoni-2007/runda-2/9','preONI 2007, Runda 2, Clasa a 9-a si gimnaziu','2007-02-13 12:54:19','2007-02-18 14:51:57','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda2_9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-2\r\n*(active) \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/runda-2/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-2/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda2_9\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-2/9.\r\n\r\nRunda s-a desfasurat Duminica 18 februarie, la ora {*09^00^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda2_9\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda2_9',NULL,NULL),('preoni-2007/clasament/runda-2/9','Clasament preONI 2007, Runda 2, Clasa a 9-a si gimnaziu','2007-02-13 13:15:58','2007-02-13 13:41:07','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda2_9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-2\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/runda-2/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-2/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-2/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda2_9\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('runda/preoni2007_runda2_10/clasament','Clasament preoni2007_runda2_10','2007-02-13 13:38:20','2007-02-13 13:38:20','h1. Clasament ==roundparam(round_id=\"preoni2007_runda2_10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda2_10\")==',1,'round: preoni2007_runda2_10',NULL,NULL),('preoni-2007/clasament/runda-2/10','Clasament preONI 2007, Runda 2, Clasa a 10-a','2007-02-13 13:41:00','2007-02-13 13:41:00','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda2_10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-2\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/runda-2/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-2/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-2/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/clasament/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-2/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda2_10\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('runda/preoni2007_runda2_1112/clasament','Clasament preoni2007_runda2_1112','2007-02-13 13:48:03','2007-02-13 13:48:03','h1. Clasament ==roundparam(round_id=\"preoni2007_runda2_1112\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda2_1112\")==',1,'round: preoni2007_runda2_1112',NULL,NULL),('preoni-2007/clasament/runda-2/11-12','Clasament preONI 2007, Runda 2, Clasele 11-12','2007-02-13 13:50:18','2007-02-13 13:50:18','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda2_1112\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-2\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/runda-2/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-2/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-2/10\r\n*(active) \'Clasele 11-12\':preoni-2007/clasament/runda-2/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda2_1112\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/clasament/10','Clasament preONI 2007, Clasa a 10-a','2007-02-13 14:04:48','2007-03-07 11:56:26','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Clasament total, Clasa a 10-a\r\n\r\n(htabs)* \'Pe runde...\':preoni-2007/clasament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/clasament/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/11-12\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda1_10|preoni2007_runda2_10|preoni2007_runda3_10|preoni2007_runda4_10\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/clasament/9','Clasament preONI 2007, Clasa a 9-a si gimnaziu','2007-02-13 14:07:17','2007-03-07 11:56:13','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Clasament total, Clasa a 9-a si gimnaziu\r\n\r\n(htabs)* \'Pe runde...\':preoni-2007/clasament\r\n*(active) \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/11-12\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda1_9|preoni2007_runda2_9|preoni2007_runda3_9|preoni2007_runda4_9\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/clasament/11-12','Clasament preONI 2007, Clasele 11-12','2007-02-13 14:08:01','2007-03-07 11:56:39','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Clasament total, Clasele 11-12\r\n\r\n(htabs)* \'Pe runde...\':preoni-2007/clasament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/10\r\n*(active) \'Clasele 11-12\':preoni-2007/clasament/11-12\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda1_1112|preoni2007_runda2_1112|preoni2007_runda3_1112|preoni2007_runda4_1112\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/runda-2/10','preONI 2007, Runda 2, Clasa a 10-a','2007-02-13 13:38:20','2007-02-18 14:52:11','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda2_10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-2\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-2/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/runda-2/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-2/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda2_10\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-2/10.\r\n\r\nRunda s-a desfasurat Duminica 18 februarie, la ora {*09^00^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda2_10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda2_10',NULL,NULL),('preoni-2007/runda-2/11-12','preONI 2007, Runda 2, Clasele 11-12','2007-02-13 13:48:03','2007-02-18 14:52:28','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda2_1112\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-2\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-2/10\r\n*(active) \'Clasele 11-12\':preoni-2007/runda-2/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-2/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda2_1112\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-2/11-12.\r\n\r\nRunda s-a desfasurat Duminica 18 februarie, la ora {*09^00^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda2_1112\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda2_1112',NULL,NULL),('rhide_pe_linux','Rhide_pe_linux','2007-02-15 19:06:05','2007-02-15 19:06:31','nu e gata inca , il termin cand am timp.\r\nSunt doua variante de instalare.\r\nh2. The Easy Way 2\r\nVarianta de a lua pachete precompilate ( metoda cea mai *rapida* )\r\npentru platforme i86 - luati pachetul de \"aici\":http://infoarena.ro/downloads?action=download&file=rhide-1.5.20050823.tbz2\r\nh2. The Hard Way 2\r\ncd $HOME;\r\nexport DIR_INSTALARE=\"rhide\";\r\nmkdir $DIR_INSTALARE;\r\ncd $DIR_INSTALARE;\r\necho \"Install path: $HOME/$DIR_INSTALARE\"\r\nwget http://dev.gentoo.org/~azarah/rhide/setedit-0.5.5.20050828.tar.bz2;\r\nwget http://dev.gentoo.org/~azarah/rhide/tvision-2.10.20050824.tar.bz2;\r\nwget http://dev.gentoo.org/~azarah/rhide/rhide-1.5.20050823.tar.bz2;\r\nwget http://ftp.gnu.org/gnu/gdb/gdb-6.1.1.tar.bz2;\r\necho \"Downloaded files; press enter.\"\r\nread;\r\n\r\ntar -xvjf setedit-0.5.5.20050828.tar.bz2;\r\ntar -xvjf tvision-2.10.20050824.tar.bz2;\r\ntar -xvjf rhide-1.5.20050823.tar.bz2;\r\ntar -xvjf gdb-6.1.1.tar.bz2;\r\n\r\necho \"Unpacked files; press enter.\";\r\nread;\r\n\r\nmv rhide-1.5.20050823 rhide;\r\nmv gdb-6.1.1 gdb;\r\n\r\ncd tvision/ ;\r\n./configure --prefix=\"/usr\" --x-include=\"/usr/include\" --x-lib=\"/usr/lib\" --fhs --without-dynamic ;\r\nmake;\r\n\r\necho \"Tvision installed; press enter.\";\r\nread;\r\n\r\ncd ..;\r\ncd setedit;\r\n./configure --prefix=\"/usr\" --fhs --libset --static --without-mp3 --without-mixer --without-migdb;\r\nmake;\r\n\r\necho \"Setedit installed; press enter.\";\r\nread;\r\n\r\nexport RHIDESRC=\"$HOME/$DIR_INSTALARE/rhide\";\r\nexport SETSRC=\"$HOME/$DIR_INSTALARE/setedit\";\r\nexport SETOBJ=\"$HOME/$DIR_INSTALARE/setedit/makes\";\r\nexport TVSRC=\"$HOME/$DIR_INSTALARE/tvision\";\r\nexport TVOBJ=\"$HOME/$DIR_INSTALARE/tvision/makes\";\r\nexport GDB_SRC=\"$HOME/$DIR_INSTALARE/gdb\";\r\nexport GDB_OBJ=\"$HOME/$DIR_INSTALARE/gdb\";\r\n\r\necho \"$RHIDESRC\";\r\necho \"$SETSRC\";\r\necho \"$SETOBJ\";\r\necho \"$TVSRC\";\r\necho \"$TVOBJ\";\r\necho \"$GDB_SRC\";\r\necho \"$GDB_OBJ\";\r\n\r\necho \"Are these ok?\";\r\nread;\r\n\r\ncd ..;\r\ncd rhide;\r\n./configure;\r\nmake;\r\nmake install;',332,'public',NULL,NULL),('newsletter/preoni-2007-runda-2','preONI 2007, Runda #2','2007-02-16 11:30:34','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nTe invitam la runda #2 a concursului preONI, concursul cu premii\r\ncare te pregateste pentru Olimpiada Nationala de Informatica.\r\n\nRunda #2 a concursului va avea loc ...\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Duminica, 18 februarie 2007, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPagina rundei: \'preoni-2007/runda-2\':preoni-2007/runda-2\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la aceasta runda iti va afecata rating-ul pe infoarena.\r\nO prestatie buna te poate aduce mai aproape te varful clasamentului.\r\n==NewsletterRating(username=\"%username%\")==\r\nRating-ul este un indicator al performantei tale in conditii de\r\nconcurs. Despre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Noutati la infoarena \n\nAvem trei articole noi pentru tine, scrise de membrii\r\ninfoarena.\r\n\np{padding-left: 0.5em;}. * Suffix array in O(N) (Cosmin Gheorghe)\r\n   \'suffix-array-liniar\':suffix-array-liniar\r\n\np{padding-left: 0.5em;}. * Minimal enclosing circle (Bogdan Tataroiu)\r\n   \'minimal-enclosing-circle\':minimal-enclosing-circle\r\n \r\n * Taietura minima in graf cu costuri (Andrei Grigorean)\r\n   \'taietura-minima\':taietura-minima\r\n\nNu uita ca infoarena este un wiki!\r\nPoti chiar tu sa imbunatatesti articolele de mai sus,\r\nsau sa creezi altele noi.\r\n\nh2.  Despre preONI \n\npreONI, concursul de marca al comunitatii infoarena, este dedicat\r\nelevilor de liceu ce se pregatesc pentru ONI (Olimpiada Nationala\r\nde Informatica).\r\n\nConcursul este impartit in 3 grupe: clasa a IX-a si gimnaziu, clasa\r\na X-a si clasele XI-XII. Se organizeaza 4 runde online de calificare.\r\nIn urma acestora, cei mai buni de la fiecare grupa sunt invitati la\r\no runda finala.\r\n\nIn cadrul unei runde, vei avea de rezolvat 3 probleme in 4h.\r\nCastigatorii rundei finale sunt premiati cu bani si/sau obiecte.\r\n\nPe pagina concursului ( \'preoni-2007\':preoni-2007 ) vei gasi\r\ninformatii despre cum participi, cine propune probleme, premii si\r\nsponsori, regulamentul concursului samd.\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nGhidul utilizatorului: \'documentatie/pentru-utilizatori\':documentatie/pentru-utilizatori\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('planificare/sedinta_20070507','Sedinta 2007-05-07','2007-04-26 18:05:59','2007-05-15 09:06:58','h1. Sedinta 2007-05-07\r\n\r\n_ora 19:00, locatie: Piranha_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Mircea Pasoi\r\n* Diaconu Adrian\r\n* Silviu Ganceanu\r\n* Valentin Stanciu\r\n* Adrian Vladu\r\n* Tiberiu Florea\r\n\r\nh2. Invitati speciali\r\n\r\n* -Sergiu Strat-\r\n* Claudia Cardei\r\n* Diana Pastor\r\n* -??? - studenta la PR, invitata de Vali- --> Teo nu e interesata si nici timp nu prea are\r\n\r\nh2. Agenda\r\n\r\n# preONI 2007\r\n## grafic\r\n## plan cheltuieli\r\n## sponsori\r\n### prezentare, dosar\r\n### hit list\r\n# Fonduri\r\n## Proiectul 2%\r\n## irealsoft\r\n## Retea sponsori\r\n# Asociatie\r\n## cont bancar\r\n## stampila\r\n# Comunitate infoarena\r\n## Cei cu 100 sa poata vedea sursele la problema respectiva => mai multa responsabilitate\r\n## \"Implica-te\". Niste idei:\r\n### Directionam cum trebuie energia comunitatii?\r\n### Unde mai avem nevoie de ajutor?\r\n### Tabara de training pe PHP + alte tehnlogii folosite in infoarena cu tickete ca aplicatii la vara? :D\r\n# infoarena software\r\n## Tag-uri reloaded\r\n### Argument 1: Clasament per tag; Exemplu: daca sunt la gimnaziu vreau sa fiu primu la sectiune de \"elementare\"\r\n### Argument 2: Gasesti rapid probleme de o anumita dificultate (fie ea si aproximativa)\r\n## ultimate data grids\r\n\r\nh2. Rezolutii adoptate\r\n\r\nh3. Despre preONI \r\n\r\n* desfasurare in perioada 8, 9, 10 iunie\r\n* suntem nevoiti - din cauza sesiunii - sa il facem la Bucuresti. Cristi il intreaba pe Emil daca ne poate ajuta in Bucuresti.\r\n* buget\r\n** 1800 lei: premii\r\n** (50 lei / zi / persoana) 25 * 50 * 2 = 2500 lei: cazare si mancare 25 persoane, restul pana la 50 stau in Bucuresti\r\n** plata propunatori: ~5000 lei\r\n** subtotal: 9300 lei\r\n** + marja: 30%\r\n** TOTAL: 12090 lei (adica 3619 EUR)\r\n** impreuna cu alte cheltuieli despre care nu stim inca (transport, materiale promotionale): *avem nevoie de 4000 EUR*\r\n* Silviu vorbeste la ICHB: intreaba de laboratoare info, cazare si mancare. Pentru cazare si mancare suntem dispusi sa dam bani.\r\n%{color: red}*UPDATE*%:\r\nLaboratoare: OK (fara bani)\r\nMancare: Se poate rezolva. Voi afla pretul concret saptamana viitoare.\r\nCazare: Ali Yuksel: \"Cate locuri sunt disponibile pe toate vi le dau la pretul pietii\" (pretul pietii = ~ca la Nichita)\r\nBonus: Transport cu microbuzele liceului (Nu stiu daca moca sau nu).\r\nConditii: Domnul Ali mi-a spus sa venim cu detalii din timp, dupa Infomatrix, cand va fi mai liber (adica pe la sfarsitul saptamanii viitoare). Toate treburile de mai sus (exceptand laboratoarele) trebuie sa treaca si prin aprobarile scolii despre care Ali zice ca nu vor fi probleme. Ali ne sugereaza sa punem finala dupa ce se termina scoala (15-17 iunie) ca atunci vor fi mai multe sanse ca internatul sa fie liber si vom avea la dispozitie toate resursele scolii.\r\n* Vali vorbeste la emag\r\n* Silviu face forward la email-urile introductive catre Diana si Vali\r\n* Diana si Claudia intreaba despre cazare, mancare si conditii la:\r\n** -Nichita Stanescu- -> ne-au rejectat din prima, au zis ca nu se poate\r\n** -Iulia Hasdeu- -> nu au locuri in perioada aia\r\n** Hoteluri de 2 stele\r\n%{color: red}*UPDATE*%:\r\n*** La \"Colegiul Tehnic Media\" ne primesc in internat cu 25lei/zi/persoana care includ cazare si 3 mese pe zi. Au zi ca putem folosi si laboratoarele. Mai trebuie sa vedem care sunt condtiile de cazare si in laburi. Camerele erau de 4 persoane.\r\n*** La Scoala gen. nr 17 \"Pia Bratianu\" au cazare pentru 15lei/zi/persoana dar nu servesc masa in weekend. Camerele sunt cam de 10-11 persoane, dar nu sunt rele. E un singur lab si din cate imi aduc eu aminte, calculatoarele erau cam infecte si putine. Dar ma gandesc ca daca turcii n-au locuri in internat, cazarea se poate face aici, iar transportul intre cele doua scolii cu microbuzele alea.\r\n\r\nh3. Despre fonduri\r\n\r\n* prezentare preONI: Silviu si Cristi\r\n* Copy sponsor network si 2%: Silviu si Cristi\r\n* Diana si Claudia vor primi prezentarea infoarena & preONI pana luni 14 mai\r\n* Cristi discuta cu Fluf despre datorie\r\n\r\nh3. Asociatia infoarena\r\n\r\n* Open Source: *Toata lumea cu punctaj max la o problema poate vedea sursele altora de la aceeasi problema.*  (s-a votat 100% - din cei prezenti - pentru)\r\n\r\nh3. infoarena software\r\n\r\n* Coding camp pe 26-27 mai: Cristi, Fluf, Mircea (nu stie sigur), Adi (1 zi), Vladu (daca e in Bucuresti), Ganci (maybe), Vali (s-ar putea)\r\n* Coding camp cu prioritati: tag-uri, datagrids, unattended evals\r\n',15,'public',NULL,NULL),('runda/preoni2007_runda2_10','runda/preoni2007_runda2_10','2007-02-16 20:29:03','2007-02-16 20:29:03','Scrie aici despre runda/preoni2007_runda2_10',5748,'public',NULL,NULL),('runda/preoni2007_runda2_1112','runda/preoni2007_runda2_1112','2007-02-17 12:37:26','2007-02-17 12:37:26','Scrie aici despre runda/preoni2007_runda2_1112',1002,'public',NULL,NULL),('planificare/sedinta-20061101','Sedinta 2006-11-01','2007-02-17 15:15:45','2007-02-17 15:27:05','h1. Sedinta 2006-11-01\r\n\r\n_ora 20:00, locatia Cafenescu_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Silviu Ganceanu\r\n* Mircea Pasoi\r\n* Valentin Stanciu\r\n\r\nh2. Agenda\r\n\r\n* 1. preONI 2007\r\n* 2. _hei-rup_ in week-end\r\n* 3. deadlines pentru infoarena 2.0\r\n* 4. asociatia info-arena\r\n* 5. preONI booklet\r\n\r\nh2. Notite\r\n\r\nh3. 1. preONI 2007\r\n\r\n* incepe aproximativ pe 10 ianuarie 2007\r\n* vom avea 6 runde de calificare on-line, cate o runda la 2 saptamani\r\n* pe ~20 martie 2007 vom fi terminat cu rundele on-line\r\n* undeva prin aprilie facem finala on-site\r\n* *Sponsori*\r\n** Cristi va face o prezentare a ofertei info-arena pana pe 15 nov.\r\n** renuntam la booklet in favoarea unei prezentari destepte\r\n** sponsori potentiali pentru care avem oameni de legatura: Intel, Microsoft, Softwin, IP Devel, ORACLE, UPB\r\n** sponsori potentiali: Totalsoft, UNIBUC ...\r\n** dupa 15 nov. luam legatura cu sponsorii\r\n** voluntari pentru cautare/intelegeri cu sponsori:\r\n*** Cristi\r\n*** Silviu\r\n*** Mircea\r\n** formatul ideal al concursului este de 3 grupe x 3 probleme\r\n** costul _orientativ_ al unei probleme: intre 35 si 50 EUR\r\n\r\nh3. 2. _hei-rup_ in week-end\r\n\r\n* organizam un hei-rup pentru infoarena 2.0 intr-un laborator de informatica pus la dispozitie de ICHB\r\n* se desfasoare pe 4 si 5 nov. 2006\r\n* in noaptea de sambata spre duminica vom dormi la Mircea. Mircea trebuie sa ne dea un raspuns sigur\r\n* Cristi va discuta cu Rax/Greco (maine, 2 nov.) pentru a stabili cum vom intra in posesia cheii\r\n* din cadrul ICHB, Silviu a obtinut acordul lui Ali\r\n* voluntari confirmati la acest hei-rup:\r\n** Cristi\r\n** Leo\r\n** Mircea (lipseste sambata dimineata; vine sambata seara)\r\n** Vali (vine duminica)\r\n** Marinescu Alex (program limitat)\r\n* voluntari ne-confirmati:\r\n** Adi\r\n** Greco\r\n** _Sobolanu_\r\n** Malex\r\n** Cristi Gologan\r\n* vom veni cu laptop-urile personale. Nu stim ce gasim acolo. \r\n* Vali cunoaste setarile/echipamentele de retea de acolo\r\n* nu ne putem baza pe legatura la internet de acolo intrucat e limitata. Cristi va aduce un Zapp pentru back-up\r\n\r\nh3. 3. deadlines pentru infoarena 2.0 (noul website)\r\n\r\n* 2006-12-01: versiune online functionala, gata pentru teste real-life\r\n* 2007-01-01: versiune stabila\r\n* in functie de stadiul in care ne aflam, noua versiune ar putea fi testata la concursul Stelele Informaticii de la sfarsitul lunii noiembrie\r\n\r\nh3. 4. asociatia infoarena\r\n\r\n_Nu s-a mai discutat despre asociatie (a inceput meciul :P ...)_\r\n\r\nh3. 5. preONI booklet\r\n\r\nAm renuntat la ideea de booklet intrucat o prezentare scurta si condensata serveste mai bine scopului nostru: acela de a transmite mesajul/oferta sponsorilor.\r\n',13,'public',NULL,NULL),('planificare/sedinta_20061121','Sedinta 2006-11-21','2007-02-17 15:28:21','2007-02-17 15:28:21','h1. Sedinta 2006-11-21\r\n\r\n_ora 18:00, locatia ICHB_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Silviu Ganceanu\r\n* Mircea Pasoi\r\n* Diaconu Adrian\r\n\r\nh2. Agenda\r\n\r\n* 1. infoarena 2.0\r\n\r\nh2. Notite\r\n\r\nh3. 1. infoarena 2.0\r\n\r\n* Mircea: 7 articole pana pe 24\r\n* Mircea: ultimele 3 news-uri\r\n* news-urile vechi nu ne intereseaza deocamdata (in 2.0 norris)\r\n* Mircea: regulament / despre / evaluator / echipa\r\n* Fluffy: #104: arde template de user\r\n* Mircea intreaba pe mama lui daca face asociatie. Avem deja statut.\r\n',13,'public',NULL,NULL),('planificare/sedinta_20061214','Sedinta 2006-12-14','2007-02-17 15:30:55','2007-02-17 15:30:55','h1. Sedinta 2006-12-14\r\n\r\n_ora 20:00, locatia Carrefour Grozavesti_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Silviu Ganceanu\r\n* Mircea Pasoi\r\n* Diaconu Adrian\r\n* Stanciu Valentin\r\n\r\nh2. Agenda\r\n\r\n* 1. infoarena 2.1\r\n* 2. asociatie\r\n\r\nh2. Notite\r\n\r\n* Se vor baga la prasit:\r\n** Cristian George Strat: fara numar\r\n** Mircea Pasoi: fara numar\r\n** Stanciu Valentin: programare, instruire recruti\r\n** Ganceanu Silviu: praseala la documentatie\r\n** Crestez Leonard: fara numar\r\n** Adrian Diaconu: invata PHP. Il ajuta Valentin sa-si dea drumul.\r\n* asociatie\r\n** mergem la notar luni la 12\r\n',13,'public',NULL,NULL),('planificare/sedinta_20070104','Sedinta 2007-01-04','2007-02-17 15:33:12','2007-02-17 15:33:12','h1. Sedinta 2007-01-04\r\n\r\n_ora 20:00, locatia Carrefour Grozavesti_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Mircea Pasoi\r\n* Diaconu Adrian\r\n\r\nh2. Agenda\r\n\r\n* 1. infoarena 2.1\r\n* 2. preONI 2007\r\n* 3. Unirea 2007\r\n* 4. Acte\r\n\r\nh2. Notite\r\n\r\n* 1. infoarena 2.1\r\n** Ne trebuie un deadline de la Dan Burzo\r\n** Ce ne trebuie sa facem concursuri? Asigura-te ca sunt tichete\r\n* 2. preONI 2007:\r\n** Mircea e sef de probleme la preONI 2007\r\n** Facem 4 runde de calificare si una finala\r\n** Prima runda este pe 20 ianuarie 2007\r\n* 3. Unirea 2007\r\n** Facem Unirea 2007 pe infoarena. Mircea face rost de probleme.\r\n* 4. Acte\r\n** Vineri (pe 5 jan) la ora 13:00 ne intalnim la Piata Natiunilor Unite ca sa bagam un notar\r\n',13,'public',NULL,NULL),('planificare/sedinta_20070215','Sedinta 2007-02-15','2007-02-17 15:35:30','2007-02-17 15:35:30','h1. Sedinta 2007-02-15\r\n\r\n_ora 21:00, locatia Carrefour Grozavesti_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Mircea Pasoi\r\n* Diaconu Adrian\r\n\r\nh2. Agenda\r\n\r\n* 1. Acte Asociatie. Ne intalnim vineri?\r\n* 2. infoarena code repository\r\n** 2.1 hei-rup?\r\n** 2.2 politica de update pe server-ul live. Branch de fall-back.\r\n** 2.3 reorganizare tichete\r\n** 2.4 -tichete assigned cu deadline.-\r\n** 2.5 -roadmap detaliat pe saptamana, in wiki.-\r\n* 3. Mai multe despre preONI 2007\r\n** 3.1 Premii, Sponsori\r\n** 3.2 Bani pentru propunatori\r\n** 3.3 Finala\r\n* 4. Posibile proiecte cu bani. Cum consumam fonduri?\r\n** 4.1 Tichetu\' si berea, pentru new people.\r\n** 4.2 Infoarena development love day.\r\n\r\nh2. Notite\r\n\r\n* Silviu poate sa vina maine dupa examen la o intalnire de acte. Dupa aceea va pleca acasa si se intoarce dupa vacanta.\r\n* 2.1: \r\n* 2.2: facem branch de fallback la care facem revert imediat cum constatam bug. In plus, cu 3 zile inainte de concurs se lucreaza numai cu branch stabil pe live. Regulat vom pune tag-uri pe cele mai noi revizii stabile.\r\n* *ne trebuie un installer pentru windows*\r\n* o idee de scazut nivelul de intrare: facem screencast-uri cu instalare & hacking\r\n* infoarena love day: o zi \"foarte anuntata\" public in care core development team se intalneste, si, filmati de un webcam public codeaza la infoarena. Este ziua optima in care se pot baga in seama noi coders pentru ca ii initiem.\r\n* un tichet = o bere :)\r\n',13,'public',NULL,NULL),('planificare/karate-kids','Karate Kids Coding Camp','2007-02-17 15:38:19','2007-02-17 15:47:10','h1. Karate Kids Coding Camp\r\n\r\nProiectul \'infoarena 2.0\':planificare/infoarena-2 se apropie de lansarea oficiala. Tehnic, site-ul este functional insa *ne lipseste continutul*! Mai exact, continutul importat din info-arena 1 (probleme, evaluatoare, articole, pagini wiki) trebuie organizat, clasificat, testat, imbunatatit, pieptanat si pupat.\r\n\r\nEste si de programat (bugfixes) insa grosul de munca vizeaza continutul noului website. Din acest motiv *avem nevoie de cat mai multe minti si maini*!\r\n\r\nh2. Mai exact, ce-o sa facem?\r\n\r\nVezi \'planificare infoarena 2\':planificare/infoarena-2 precum si \'lista de tichete\':http://hackers.devnet.ro/report/3 pentru acest milestone.\r\n\r\nPrelucrarea/organizarea/testarea samd. continutului info-arena 1 inseamna cam asa:\r\n\r\n* infoarena 2.0 are la baza un sistem wiki. Articolele despre info (luate de pe _vechiul_ info.devnet.ro) trebuie impartite pe categorii\r\n* link-uri intre probleme, articole, autori, concursuri, utilizatori\r\n* conversie plain text / html in textile (wiki markup)\r\n* testarea problemelor pe noul evaluator\r\n* regulament\r\n* ajutor / ghid de folosire\r\n* re-organizarea forum-ului\r\n\r\nIn paralel cu transformarea continutului vom repara bug-urile cunoscute sau cele care ies la suprafata.\r\n\r\nh2. Cand?\r\n\r\nIn week-end-ul *11-12 nov. 2006*.\r\n\r\nIncepem Sambata dimineata la ora 9 si terminam Duminica noaptea. Nu toti vom veni de la inceput pana la sfarsit.\r\n\r\nh2. Unde?\r\n\r\nIn laboratoarele de info ale \'ICHB\':http://www.ichb.ro (zona Dristor).\r\n\r\nLaboratoarele au calculatoare cu linux/windows si sunt conectate la internet. Daca iti poti aduce un laptop, cu atat mai bine.\r\n\r\nh2. Cine vine?\r\n\r\nDaca vii la KKCC, inscrie-te in lista de mai jos. Nu uita sa specifici cand poti veni si cat vei sta.\r\n\r\n* Cristian George Strat, fara numar\r\n* Cristez Leonard, the whole nine yards\r\n* Mircea Pasoi, fara numar\r\n* Ganceanu Silviu, FIXME\r\n* Vladu Adrian, ?\r\n* Adrian Diaconu, ?\r\n\r\nVor participa _virtual_ (de acasa):\r\n\r\n* Filip Buruiana\r\n* Daniel Pasaila\r\n\r\nh2. Quick Facts\r\n\r\n* Fiecare isi aduce pachet / bani de mancare\r\n* In noaptea de Sambata spre Duminica *probabil* ca putem dormi la Mircea. *CONFIRMED*\r\n* Cu cat poti sta (lucra) mai mult, cu atat mai bine! Totusi, daca nu poti chiar de la inceput si pana la sfarsit, nu e bai. Chiar si cateva ore de munca sunt de mare folos.\r\n* Ce trebuie facut a fost deja planificat si impartit: \'vezi aici\':http://hackers.devnet.ro/report/3\r\n* Adu-ti casti!\r\n\r\nh2. To Do\r\n\r\n_(chestii de pregatit ca sa iasa treaba)_\r\n\r\n* *Ia cheia de la laborator* ( *Mircea:* Got the key! )\r\n',13,'public',NULL,NULL),('planificare/camp-noname','Coding Camp Noname','2007-02-17 19:41:58','2007-02-17 19:41:58','h1. Coding Camp Noname\r\n\r\n_(pagina creata pentru arhiva / din considerente istorice)_\r\n\r\nCoding camp de 2 zile si gazduit in laboratoarele ICHB cu scopul de a continua proiectul infoarena v2.\r\n\r\nOrganizarea evenimentului s-a facut \'intr-o sedinta la Cafenescu\':planificare/sedinta-20061101.\r\n\r\nSe cheama \'\'Noname\'\' pentru ca nu i-am dat nume.',13,'public',NULL,NULL),('planificare/camp-chuckie','Coding Camp Chuckie','2007-02-17 19:46:22','2009-07-04 12:29:36','h1. Coding Camp Chuckie\r\n\r\n_(pagina creata pentru arhiva / din considerente istorice)_\r\n\r\nCoding camp organizat la Valenii de Munte (Stanciu Valentin) cu scopul de a porni proiectul infoarena v2.\r\n\r\nOrganizarea s-a facut \'direct pe wiki-ul infoarena.devnet.ro\':http://infoarena.devnet.ro/wiki/index.php/Coding_Camp_2006.\r\n\r\n\'Iata si cateva poze (multumim, Vali!) \':http://picasaweb.google.com/valentin.stanciu/IACodingCamp.',75,'public',NULL,NULL),('mozaic','Mozaic','2007-02-18 11:27:26','2007-07-22 11:11:32','h1. Mozaic\r\n\r\n== Gallery(page=\"%\" file=\"avatar\" display_entries=\"48\")==',58,'public',NULL,NULL),('preoni-2007/clasament','Clasament preONI 2007','2007-01-15 15:59:02','2007-03-07 11:55:50','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Clasament \r\n\r\n(htabs)*(active) \'Pe runde...\':preoni-2007/clasament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/11-12\r\n\r\nh2. Clasament Runda 1\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-1/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-1/11-12\r\n\r\nh2. Clasament Runda 2\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-2/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-2/11-12\r\n\r\nh2. Clasament Runda 3\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-3/11-12\r\n\r\nh2. Clasament Runda 4\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-4/11-12\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('runda/preoni2007_runda3_9/clasament','Clasament preoni2007_runda3_9','2007-02-18 14:28:21','2007-02-18 14:28:21','h1. Clasament ==roundparam(round_id=\"preoni2007_runda3_9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda3_9\")==',1,'round: preoni2007_runda3_9',NULL,NULL),('preoni-2007/runda-3/9','preONI 2007, Runda 3, Clasa a 9-a si gimnaziu','2007-02-18 14:28:21','2007-03-07 12:23:32','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda3_9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-3\r\n*(active) \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/runda-3/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-3/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda3_9\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-3/9.\r\n\r\nRunda s-a desfasurat *Duminica 4 martie*, la ora {*09^00^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda3_9\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda3_9',NULL,NULL),('preoni-2007/runda-3/10','preONI 2007, Runda 3, Clasa a 10-a','2007-02-18 14:30:53','2007-03-07 12:23:46','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda3_10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-3\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-3/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/runda-3/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-3/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda3_10\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-3/10.\r\n\r\nRunda s-a desfasurat *Duminica 4 martie*, la ora {*09^00^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda3_10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda3_10',NULL,NULL),('runda/preoni2007_runda3_10/clasament','Clasament preoni2007_runda3_10','2007-02-18 14:30:53','2007-02-18 14:30:53','h1. Clasament ==roundparam(round_id=\"preoni2007_runda3_10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda3_10\")==',1,'round: preoni2007_runda3_10',NULL,NULL),('runda/preoni2007_runda3_1112/clasament','Clasament preoni2007_runda3_1112','2007-02-18 14:33:26','2007-02-18 14:33:26','h1. Clasament ==roundparam(round_id=\"preoni2007_runda3_1112\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda3_1112\")==',1,'round: preoni2007_runda3_1112',NULL,NULL),('preoni-2007/runda-3/11-12','preONI 2007, Runda 3, Clasele 11-12','2007-02-18 14:33:26','2007-03-07 12:23:58','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda3_1112\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-3\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-3/10\r\n*(active) \'Clasele 11-12\':preoni-2007/runda-3/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-3/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda3_1112\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nAceasta runda s-a incheiat. \'*Vezi clasamentul*\':preoni-2007/clasament/runda-3/11-12.\r\n\r\nRunda s-a desfasurat *Duminica 4 martie*, la ora {*09^00^*} si a durat 4h.\r\nParticipantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda3_1112\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda3_1112',NULL,NULL),('preoni-2007/clasament/runda-3/9','Clasament preONI 2007, Runda 3, Clasa a 9-a si gimnaziu','2007-02-18 14:43:06','2007-02-18 14:43:06','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda3_9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-3\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/runda-3/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-3/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasa a 9-a si gimnaziu\':preoani-2007/clasament/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-3/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda3_9\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/clasament/runda-3/10','Clasament preONI 2007, Runda 3, Clasa a 10-a','2007-02-18 14:43:57','2007-02-18 14:43:57','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda3_10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-3\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/runda-3/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-3/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-3/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/clasament/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-3/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda3_10\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/clasament/runda-3/11-12','Clasament preONI 2007, Runda 3, Clasele 11-12','2007-02-18 14:44:56','2007-02-18 14:44:56','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda3_1112\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-3\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/runda-3/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-3/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-3/10\r\n*(active) \'Clasele 11-12\':preoni-2007/clasament/runda-3/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda3_1112\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('documentatie/evaluator','Evaluatorul infoarena','2006-11-27 05:18:35','2009-05-18 20:39:12','h1. Evaluatorul infoarena\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\n... este responsabil de evaluarea solutiilor trimise de utilizator.\r\n\r\nh2. Cum se evalueaza o problema\r\n\r\nMai intai, codul sursa trimis de concurent se compileaza (vezi tabelul de mai jos). Apoi, solutia se _evalueaza_: se ruleaza programul compilat pentru diferite date de intrare (teste). In urma rularii, un program specializat decide daca raspunsul dat de solutia concurentului este corect si acord un punctaj pe masura.\r\n\r\nFiecare program compilat are dreptul de a rula doar un anumit interval de timp (specificat in descrierea problemei). in cazul in care timpul de executie este depasit, programul este terminat automat de sistem. Analog, se pot impune si limite de memorie.\r\n\r\nEvaluarea se face intr-un mediu restrictionat. Programele compilate pot citi/scrie fisiere doar din/in directorul curent si nu au acces la unele functii sistem.\r\n\r\nh2. Compilatoare folosite\r\n\r\nIata *lista oficiala* de compilatoare folosite de evaluatorul infoarena:\r\n\r\ntable{width:50%}. |_. Compilator si versiune|_. Comanda de compilare |_. Extensie implicita |\r\n| GNU GCC 4.2.4 | $gcc -Wall -O2 -static &hellip; -lm$ | c |\r\n| GNU G++ 4.2.4 | $g++ -Wall -O2 -static &hellip; -lm$ | cpp |\r\n| FreePascal Compiler 2.2.0 | $fpc -O2 -Xs &hellip;$               | pas |\r\n\r\nh2. Configuratia sistemului de evaluare\r\n\r\nEvaluatorul ruleaza pe un calculator dedicat, oferit de ==User(user=\"fluffy\")==. (Multumim, Leo!)\r\n\r\n* Sistem de operare: Debian stable(sarge)\r\n* Procesor: Pentium IV, $2.0 GHz$\r\n* Memorie: $512 MB RAM$\r\n\r\nh2. Gazduire !>documentatie/evaluator?hqn.png!\r\n\r\nEvaluatorul infoarena este gazduit cu placere de catre \"HQN (High Quality Networks)\":http://hqn.ro/.\r\n\r\nh2. Mesaje de evaluare\r\n\r\nPentru cei care nu sunt familiari cu sistemele unix sau sunt incepatori in programare, multe dintre mesajele evaluatorului pot parea oarecum criptice.\r\n\r\n* Eroare de sistem: Daca ai obtinut aceast mesaj te rugam sa ne contactezi, preferabil pe \'forum\':forum. Te rugam sa mentionezi si id-ul job-ului.\r\n* OK: Totul a functionat perfect.\r\n* Memory limit exceeded: Ai depasit limita de memorie. Majoritatea problemelor au o limita de 64 de mega, pe care noi o consideram destul de generoasa.\r\n* Time limit exceeded: Programul tau a depasit limita de timp. Asta inseamna ca programul tau nu este destul de rapid.\r\n* Wall time limit exceeded: Evaluarea a durat prea mult si a fost abandonata. Evaluatorul infoarena masoara doar timpul folosit de programul tau pentru a determina daca iti da TLE, dar exista si o limita fata de \"ceasul de perete\". Acest mesaj poti sa il obtii daca faci sleep, scanf de la stdin si alte functii care stau degeaba fara sa consume efectiv procesorul.\r\n* Blocked system call: Ai accesat o functie la care nu ai access. Nu ar trebui sa primesti aceasta functie decat daca incerci explicit sa faci ceva interzis.\r\n* Killed by signal: Cea mai frecventa eroare cand ai un bug in program. Cand un program incalca anumite conventii in UNIX acel program primeste un \"semnal\" care de cele mai multe ori il opreste. Cateva semnale comune:\r\n** 11(SIGSEGV): Segmentation fault. Asta in 99% din cazuri inseamna ca ai probleme cu accesul la memorie. Ai iesit din limitele unui vector, ai facut stack overflow, etc.\r\n** 8(SIGFPE): Floating point error. Cauzat cel mai frecvent de impartiri la 0.\r\n* Non-zero exit status: Programul tau a returnat o valoare diferita de 0. Cel mai probabil ai uitat return 0; sau ceva similar. Poti primi acest mesaj si in loc de mesajul \"Killed by signal\": verifica si dupa erorile mentionate deasupra.\r\n\r\nEvaluatoarele problemelor iti vor da si ele un mesaj scurt, cel mai frecvent ceva de genul \"OK\" sau \"Wrong Answer\", dar unii propunatorii au umor :).\r\n\r\nh2. Troubleshooting\r\n\r\nPentru programatorii in Borland C/Pascal este important de tinut minte ca evaluatorul infoarena este un mediu *foarte* diferit fata de dos. Cateva erori comune si cum pot fi rezolvate\r\n\r\n* Pe infoarena se face I/O din fisiere, nu de la stdin, stdout. Daca faci scanf de la stdin vezi obtine cel mai probabil \"Wall time limit exceeded\" (vezi mai sus) iar daca faci printf la stdout rezultatul tau va fi ignorat.\r\n* tipul int din GCC este pe 32 de biti, nu 16 ca in Borland C/C++, char - 8 biti, short - 16 biti, long - 32, long long - 64\r\n* folositi sprintf in loc de itoa sau ltoa.\r\n* programul de evaluare ruleaza pe un sistem de operare UNIX. Folositi \"\\n\" pentru terminarea liniei curente, nu \"\\r\\n\"\r\n* aveti grija ca functia main sa fie de tip int si sa intoarca 0 (return 0;)\r\n* nu folositi librarii dependente de sistemul de operare (ex. dos.h, graphics.h in C sau dos, crt, graph in pascal). Aceste librarii nu sunt necesare pentru a rezolva problemele de pe infoarena.\r\n* nu folositi modificatorii far, huge, _huge, __huge pentru ca nu exista in GCC. De asemenea, nu exista nici functiile care folosesc aceste tipuri de date (de ex. farmalloc, farfree etc.) si nici conceptul de memory model (tiny, small, medium, large, huge). De toate acestea nu mai e nevoie intrucat puteti avea acces la toata memoria prin functii standard si pointer-i standard - new, delete, malloc etc.',1142,'protected',NULL,NULL),('utilizator/respawn','Profil reSpawn','2007-02-23 22:36:17','2007-02-23 22:36:17','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6112,'public',NULL,NULL),('runda/preoni2007_runda3_1112','runda/preoni2007_runda3_1112','2007-02-18 21:54:00','2007-02-18 21:54:00','Scrie aici despre runda/preoni2007_runda3_1112',5868,'public',NULL,NULL),('planificare/sedinta_20070615','planificare/sedinta_20070615','2007-06-20 13:56:34','2007-06-20 13:56:34','h1. Sedinta 2007-06-15\r\n\r\n_ora 20:00, locatie: Piranha_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Mircea Pasoi\r\n* Valentin Stanciu\r\n* Claudia Cardei\r\n\r\nh2. Agenda\r\n\r\n* buget finala preONI 2007\r\n* probleme de info\r\n* diplome\r\n* pliante, badges, tricouri\r\n* pagina finalei preONI + stire + newsletter\r\n* card-uri infoarena de la banca\r\n* gestiune bani\r\n* tichete pentru finala preONI\r\n\r\nh2. Rezolutii adoptate\r\n\r\nh3. Despre finala preONI 2007\r\n\r\n* buget:\r\n** 15 lei x 2 nopti x 25 persoane = 750 lei cazare\r\n** 3 grupe x 60 lei = 1800 lei pentru premii\r\n** 30 x 1 lei = 30 lei pentru imprimare diplome\r\n** 15 x 4 = 60 lei pentru racoritoare\r\n** 80 lei pentru alte chestii de protocol\r\n** total: 2740 lei\r\n** padding +30%: 3560 lei\r\n* Vali cauta oferte de tricouri\r\n* bani propunatori: sa se prezinte propunatorii la o sedinta ca sa discutam despre bani. Ideea de baza este ca ori platim pe toti (nu doar propunatorii de probleme) ori pe nimeni.\r\n* Leonard scoate extrase de cont periodic direct de la Raiffeisen.\r\n* Trebuie sa-i amintim lui Ali ca avem si fete de cazat.\r\n* Leonard face pagina finalei si baga stire.\r\n',13,'public',NULL,NULL),('newsletter/preoni-2007-runda-3','preONI 2007, Runda #3','2007-03-02 09:38:27','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nTi-am pregatit o noua provocare!\r\nEste vorba de runda #3 a concursului preONI. Te invitam sa\r\nparticipi, chiar daca nu ai concurat la rundele anterioare.\r\n\npreONI este concursul cu premii care te pregateste pentru\r\nOlimpiada Nationala de Informatica.\r\n\nRunda #3 a concursului va avea loc ...\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Duminica, 4 martie 2007, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPagina rundei: \'preoni-2007/runda-3\':preoni-2007/runda-3\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la aceasta runda iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te va aduce mai aproape de varful clasamentul.\r\n==NewsletterRating(username=\"%username%\")==\r\nRating-ul este un indicator al performantei tale in conditii de\r\nconcurs. Afla mai multe: \'documentatie/rating\':documentatie/rating.\r\n\nIti tinem pumnii!\r\n\nh2.  Despre preONI \n\npreONI, concursul de marca al comunitatii infoarena, este dedicat\r\nelevilor de liceu ce se pregatesc pentru ONI (Olimpiada Nationala\r\nde Informatica).\r\n\npreONI se imparte in 3 grupe: clasa a IX-a si gimnaziu, clasa\r\na X-a si clasele XI-XII. Se organizeaza 4 runde online de calificare.\r\nIn urma acestora, cei mai buni de la fiecare grupa sunt invitati la\r\no runda finala.\r\n\nIn cadrul unei runde, vei avea de rezolvat 3 probleme in 4h.\r\nCastigatorii rundei finale sunt premiati cu bani si/sau obiecte.\r\n\nPe pagina concursului ( \'preoni-2007\':preoni-2007 ) vei gasi\r\ninformatii despre cum participi, cine propune probleme, premii si\r\nsponsori, regulamentul concursului samd.\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('planificare/sedinta_20070303','Sedinta 2007-03-03','2007-03-03 15:35:52','2007-03-03 17:39:40','h1. Sedinta 2007-03-03\r\n\r\n_ora 17:00, locatia Carrefour Grozavesti_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Mircea Pasoi\r\n* Diaconu Adrian\r\n* Silviu Ganceanu\r\n* Valentin Stanciu\r\n* Ofiteru Andreea\r\n\r\nh2. Agenda\r\n\r\n* 1. Acte asociatie\r\n* 2. Articol Adevarul\r\n* 3. preONI Finala\r\n** 3.1. Sponsori\r\n** 3.2. Data desfasurare\r\n* 4. Filme\r\n* 5. hei-rup?\r\n* 6. Tichete\r\n\r\nh2. Notite\r\n\r\n* 1: pe 5 Cristi are audiere. S-ar putea sa trebuiasca cazier\r\n* 3.1: Vorbim despre sponsori dupa ce aflam mai multe despre finala.\r\n* 3.2: -Runda 4-a o facem pe 18 iar- runda finala o facem dupa ONI. Emil ne zice cand poate.\r\n* 4: ramane in aer\r\n* 5: hei-rup pe 17-18 martie\r\n* 5.1: mircea, cristi, fluf, vali, adi, vladu\r\n* 5.2: screencast de development\r\n* 5.3: webcam public\r\n* *fluf face revert la ultimul stable revision*\r\n',13,'public',NULL,NULL),('documentatie/probleme-frecvente-la-autentificare','Cum gasesc problemele','2006-11-27 05:57:42','2007-04-19 20:32:04','h1. Probleme frecvente la autentificare\r\n\r\nDaca nu te poti autentifica la infoarena sau daca site-ul se comporta ciudat - spre exemplu apari autentificat intr-o sectiune insa in alta esti anonim - atunci aceasta pagina este pentru tine.\r\n\r\nh2. No cookies, no infoarena\r\n\r\nSite-ul nostru foloseste cookie-uri (si nimic altceva) pentru autentificare. Daca browser-ul tau nu suporta sau este configurat sa blocheze cookie-urile atunci nu te poti autentifica.\r\n\r\nCum poti verifica asta? *FIXME*\r\n\r\nAtentie! Cookie-urile pot fi blocate si de un firewall / antivirus.\r\n\r\nh2. Clear cookies\r\n\r\nCel mai probabil este necesar va trebui sa stergi cookie-urile stocate in browser. Cum se face asta?\r\n\r\n* Mozilla Firefox: $Tools > Clear Private Data$\r\n* Internet Explorer: $Tools > Internet Options > Delete Cookies$\r\n* Opera 9: $Tools > Delete Private Data$\r\n* Safari: *FIXME*\r\n* Konqueror: $Settings > Configure Konqueror > Cookies > Management > Delete All$\r\n\r\nDupa ce stergi cookie-urile incearca din nou sa te autentifici.\r\n\r\nh2. Ora calculatorului tau?\r\n\r\nAsigura-te ca ora calculatorului tau este corecta. Daca dai data inapoi cu mai mult de 5 zile, cookie-urile de pe infoarena.ro sunt ignorate de browser.\r\n\r\nh2. Incearca alt browser\r\n\r\ninfoarena a fost testat pe urmatoarele browser-e: Mozilla FireFox 1.5, Mozilla Firefox 2.0, Microsoft Internet Explorer 6, Opera 9.20, Konqueror 3.5.5 . Daca browser-ul tau nu se afla printre acestea, iti recomandam sa incerci altul.\r\n\r\nh2. Tot nu merge?\r\n\r\nDaca nici una din recomandarile de mai sus nu rezolva problema, \"contacteaza-ne pe e-mail\":contact. Vom incerca sa-ti raspundem cat mai repede.\r\n',3270,'public',NULL,NULL),('preoni-2007/prelungiri','template/preoni-2007/runda-3/prelungiri','2007-03-04 10:19:36','2007-03-04 10:22:54','table{width: 50%}. |_={background-color: red; color: white;}. Timpul de lucru se extinde cu 15min. Astfel, solutiile se pot trimite pana la ora 13^15^. Ne cerem scuze pentru inconveniente. |',13,'protected',NULL,NULL),('preoni-2007/presa','Aparitii in presa preONI 2007','2007-01-15 15:58:34','2007-03-07 12:02:19','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Aparitii in presa\r\n\r\n_infoarena_ a aparut in \'Adevarul\':http://adevarulonline.ro pe \'prima pagina\':http://www.adevarulonline.ro/articole/fostii-olimpici-ii-antreneaza-pe-concurentii-de-la-olimpiade/305061.\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('preoni-2007/runda-4/10','preONI 2007, Runda 4, Clasa a 10-a','2007-03-07 12:06:10','2007-03-25 06:22:02','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda4_10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-4\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-4/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/runda-4/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-4/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda4_10\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\n==include(page=\"preoni-2007/prelungiri\")==\r\n\r\nRunda se desfasoara *Duminica 25 martie*, la ora {*09^00^*} si va dura *{color:red}4h 15min*.\r\n\r\nParticipantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2007/clasament/runda-4/10.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda4_10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda4_10',NULL,NULL),('runda/preoni2007_runda4_9/clasament','Clasament preoni2007_runda4_9','2007-03-07 12:02:53','2007-03-07 12:02:53','h1. Clasament ==roundparam(round_id=\"preoni2007_runda4_9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda4_9\")==',1,'round: preoni2007_runda4_9',NULL,NULL),('runda/preoni2007_runda4_10/clasament','Clasament preoni2007_runda4_10','2007-03-07 12:06:10','2007-03-07 12:06:10','h1. Clasament ==roundparam(round_id=\"preoni2007_runda4_10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda4_10\")==',1,'round: preoni2007_runda4_10',NULL,NULL),('utilizator/nistaman','Profil nistaman','2007-03-04 15:15:55','2007-03-04 15:15:55','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6195,'public',NULL,NULL),('preoni-2007/clasament/runda-4/9','Clasament preONI 2007, Runda 4, Clasa a 9-a si gimnaziu','2007-03-07 12:15:49','2007-03-07 12:16:04','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda4_9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-4\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/runda-4/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-4/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasa a 9-a si gimnaziu\':preoani-2007/clasament/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-4/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda4_9\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/clasament/runda-4/10','Clasament preONI 2007, Runda 4, Clasa a 10-a','2007-03-07 12:17:19','2007-03-07 12:17:19','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda4_10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-4\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/runda-4/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-4/9\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-4/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/clasament/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-4/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda4_10\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('multe-smenuri-de-programare-in-cc-si-nu-numai','Multe \"smenuri\" de programare in C/C++... si nu numai!','2004-11-10 00:00:00','2010-02-27 10:50:30','h1. Multe \"smenuri\" de programare in C/C++... si nu numai!\r\n\r\n(Categoria _Limbaje de programare_, Autor _Mircea Pasoi_)\r\n\r\nAcest articol vine ca o completare a articolului scris de Alexandru Mosoi, prezentand noi trucuri care le-am folosit si m-au ajutat mult. O mare parte din acestea le-am invatat din sursele lui Radu Berinde (cred ca stiti cu totii cine este), asadar ii multumesc!\r\n\r\nh2. Array-uri neindexate de la 0\r\n\r\nUn dezavantaj fata de Pascal este faptul ca in C nu putem avea expresii de genul {@A[-100]@} unde $A$ este un vector. Dar acest lucru se poate remedia. Spre exemplu, daca vrem sa facem un vector $A$ cu elemente de la $-100$ la $100$ procedam astfel:\r\n\r\n== code(c) |\r\nint A[201];\r\n#define A (A + 100)\r\n==\r\n\r\nh2. Fisiere de intrare si iesire\r\n\r\nFolositi {@freopen()@} in loc de {@fopen()@} deoarece este mai comod, in special la concursurile in care intrare si iesirea sunt standard.\r\n\r\n== code(c) |\r\nfreopen(\"in.txt\", \"r\", stdin);\r\nfreopen(\"out.txt\", \"w\", stdout);\r\n==\r\n\r\nh2. Cautare binara (ideea originala de la Mihai Patrascu)\r\n\r\nUrmatorul cod este de aproximativ $4$ ori mai rapid (am testat cu cautare binara ca in manual) , mai usor de inteles, mai flexibil si mai scurt... ce ati putea dori mai mult?\r\n\r\n== code(c) |\r\nint N, A[N];\r\n\r\nint binary_search(int val)\r\n{\r\n    int i, step;\r\n    for (step = 1; step < N; step <<= 1);\r\n    for (i = 0; step; step >>= 1)\r\n        if (i + step < N && A[i + step] <= val)\r\n           i += step;\r\n    return i;\r\n}\r\n==\r\n\r\nProcedura de mai sus face cautarea binara folosind puteri a lui $2$ in ordine descrescatoare, practic incerc sa determin fiecare bit al rezultatului.\r\n\r\nh2. Impartire in bucati de marime $sqrt(n)$ (cunoscut si ca \"smenul lui Bogdan Batog\")\r\n\r\nSa presupunem ca avem un vector de lungime n cu numere reale pe care se fac urmatoarele operatii:\r\n{@ADUNA(st, dr, x)@} - toate elementele cu indicii intre $st$ si $dr$ isi cresc valoarea cu $x$\r\n{@SUMA(st, dr)@} - returneaza suma elementelor cu indicii intre $st$ si $dr$\r\n\r\nPentru cei ce cunosc arbori de intervale, rezolvarea acestei probleme in $O(lg n)$ per operatie este o munca usoara, dar presupunand ca nu stim aceasta structura putem folosi urmatorul truc: vom construi un al doilea vector de lungime $sqrt(n)$ care retine suma elementelor pe bucati de lungime {$sqrt(n)$}. Pentru a face o operatie pe un interval [{$st, dr$}] vom imparti acest interval in bucati de $sqrt(n)$ a caror actualizare o facem in vectorul $B$ si elementele care raman in margine in vectorul {$A$}. De exemplu pe vectorul {$A{~0..15~}$} vom avea vectorul {$B{~0..3~}$}. Pentru a actualiza de exemplu [{$2, 12$}] vom actualiza {$B{~1~}$} (care corespunde lui [{$4..7$}]), {$B{~2~}$} (pentru [{$8..11$}]) si {$A{~2~}$}, {$A{~3~}$}, {$A{~12~}$} (elementele din margini). Cum sunt maxim $sqrt(n)$ elemente de actualizat in $B$ si pe margini nu vom actualiza niciodata mai mult de $2 * sqrt(n)$ elemente putem concluziona ca operatiile vor avea complexitate {$O(sqrt(n))$}.\r\n\r\nDaca am avea aceeasi problema dar in doua dimensiuni, am putea face acelasi \"smen\" pentru fiecare linie pentru o complexitate $O(n*sqrt(n))$ per operatie, sau cu arbori de intervale pe fiecare linie {$O(n*lg n)$}. Putem, de asemenea obtine o complexitate $O(n)$ folosind urmatoarea impartire:\r\n$A$ - pentru bucati $1 * 1$\r\n$B$ - pentru bucati $sqrt(n) * sqrt(n)$\r\n$C$ - pentru bucati $1 * sqrt(n)$\r\n$D$ - pentru bucati $sqrt(n) * 1$\r\nAcest mod de reprezentare este o extindere directa a aceluiasi smen in doua dimensiuni. Aceasta idee poate fi folosita si pentru alte operatii: inmultire, minim, maxim, etc. In general, orice se poate rezolva cu acest \"smen\" se poate obtine la o complexitate mai buna cu arbori de intervale, dar merita sa stiti si aceasta ideea deoarece de multe ori scuteste din efortul de implementare, desi se pierde din viteza... alegerea voastra! ;)\r\n\r\nh2. LCA in $O(sqrt(n))$ (ideea originala de la Radu Berinde)\r\n\r\nDaca nu stiti ce este LCA, va recomand sa cititi \'articolul\':lowest-common-ancestor lui Emilian Miron din cadrul site-ului pentru a va documenta. In continuare vom prezenta un algoritm mai ineficient, dar foarte usor de implementat. Consideram arborele si atribuim fiecarui nod o inaltime. Vom imparti arborele in $sqrt(H)$ intervale in functie de inaltime, unde $H$ e inaltimea maxima (de exemplu la $H=9$ nodurile cu inaltimi intre $0$ si $2$ vor forma un interval, [{$3..5$}] alt interval si ultimul interval de inaltimi [{$6..8$}]). Astfel, pentru fiecare nod, pe langa tatal sau, vom retine si tatal din intervalul de mai sus, printr-o parcurgere DF. In continuare, codul:\r\n\r\n$H$ se calculeaza inainte sau poate fi constant\r\n$T$ sunt tatii nodului si $N$ numarul de noduri\r\n\r\n== code(c) |\r\nvoid DF(int n, int t2, int lev)\r\n{\r\n    int i;\r\n    T2[n] = t2, Lev[n] = lev;\r\n    if (lev % H == 0) t2 = n;\r\n    for (i = 0; i < N; i++)\r\n        if (T[i] == n) DF(i, t2, lev+1);\r\n}\r\n==\r\n\r\nOperatia de LCA se va realiza apoi foarte usor, urcand pe tatii din intervale, pana se ajunge la doua noduri in acelasi interval, apoi folosindu-se metoda clasica. Cod:\r\n\r\n== code(c) |\r\nint LCA(int x, int y)\r\n{\r\n    while (T2[x] != T2[y])\r\n        if (Lev[x] > Lev[y])\r\n            x = T2[x];\r\n        else\r\n            y = T2[y];\r\n    while (x != y)\r\n        if (Lev[x] > Lev[y])\r\n            x = T[x];\r\n        else\r\n            y = T[y];\r\n    return x;\r\n}\r\n==\r\n\r\n\r\nh2. LCA in $O(lg^2^ n)$\r\n\r\nAceeasi problema, dar o alta rezolvare. Vom construi o matrice $A{~i,j~}$ cu semnificatia $A{~i,j~}$ = al {$2^i^$}-lea tata al nodului {$j$}. Folosind aceasta matrice putem cauta binar ({$O(lg n)$}) nivelul pe care s-ar putea afla LCA-ul a doua noduri si sa determinam daca nodul ales este corect - adica daca nodul situat la acel nivel este acelasi pentru cele doua noduri pentru care se face LCA ({$O(lg n)$} cu matricea de mai sus). Complexitate finala $O(lg^2^ n)$ si $O(n*lg n)$ memorie.\r\n\r\nh2. For-uri \"complicate\"\r\n\r\nfor-ul in C/C++ este foarte flexibil si poate ajuta foarte mult in compactarea codului, deci si a timpului de implementare. In continuare vom prezenta algoritmul merge sort (sortare prin interclasare) scris in cateva linii (putine, zic eu!):\r\n\r\n== code(c) |\r\nint N, A[N], B[N];\r\nvoid merge_sort(int l, int r)\r\n{\r\n    int m = (l + r) >> 1, i, j, k;\r\n    if (l == r) return;\r\n    merge_sort(l, m);\r\n    merge_sort(m + 1, r);\r\n    for (i=l, j=m+1, k=l; i<=m || j<=r; )\r\n        if (j > r || (i <= m && A[i] < A[j]))\r\n            B[k++] = A[i++];\r\n        else\r\n            B[k++] = A[j++];\r\n    for (k = l; k <= r; k++) A[k] = B[k];\r\n}\r\n==\r\n\r\nh2. Recomandari generale\r\n\r\n# Programare dinamica cu memoizare: mult mai simplu si uneori chiar mai rapida cand nu ne trebuie tot array-ul\r\n# Algoritmi randomizati: de multe ori mai usor de implementat si mai eficienti, mai bine decat cei euristici, dar necesita o analiza mult mai atenta a performantei. Exemple calsice: quicksort, statistici de ordine\r\n\r\nh2. \"Smenul lui Mars\" (Marius Andrei)\r\n\r\nConsideram urmatoarea problema: se da un vector $A$ de $N$ elemente pe care se fac $M$ astfel de operatii: {@ADUNA(st, dr, x)@} - toate elementele cu indicii intre $st$ si $dr$ ({$0 &le; st &le; dr &lt; N$}) isi cresc valoarea cu {$x$} . La sfarsit trebuie sa se afiseze vectorul rezultat. In continuarea vom descrie o metoda care ne da un timp de rulare de $O(1)$ pentru operatia $ADUNA$ si $O(N)$ pentru a determina toate elementele din vector. Vom construi un al doilea vector $B$ de $N+1$ elemente, cu proprietatea ca {$A{~i~} = B{~0~} + B{~1~} + ... B{~i~}$}. Astfel, o operatie {@ADUNA(st, dr, x)@} devine:\r\n\r\n== code(c) |B[st] += x;\r\nB[dr + 1] -= x;\r\n==\r\n\r\nDa, este chiar asa de simplu! Pentru a determina un element A{~i~} vom aduna pur si simplu {$B{~0~} + B{~1~} + ... B{~i~}$}. Incercati pe foaie sa vedeti cum funtioneaza. Aceasta ideea poate fi extinsa si in doua dimensiuni, construind $B$ astfel incat $A{~i,j~}$ = suma subtabloului din $B$ cu coltul in ({$0, 0$}) si ({$i, j$}), astfel (pt. {@ADUNA(x1,y1,x2,y2,v)@}):\r\n\r\n== code(c) |B[x1][y1] += v;\r\nB[x1][y2 + 1] -= v;\r\nB[x2 + 1][y1] -= v;\r\nB[x2 + 1][y2 + 1] += v;\r\n==\r\n\r\nPe cazul general, daca vrem sa facem operatii in $d$ dimensiuni vom avea o complexitate {$O(2^d^)$}. Reamintesc ca aceasta metoda este eficienta doar cand se vrea afisata vectorul/matricea/etc. doar la sfarsitul operatiilor sau sunt foarte putine interogari ale valorilor elementelor, deoarece aflarea unui element este o operatie foarte ineficienta: {$O(i)$} pentru a afla valorile elementelor pana la pozitia $i$.\r\n\r\nh2. Grafuri cu liste de adiacenta (ideea originala de la Radu Berinde)\r\n\r\nSe stie (sau ar trebui sa se stie!) ca lucrul cu pointerii este foarte incet... astfel, cand retinem un graf rar (numar mare de noduri, numar mic de muchii) cu pointeri (vezi mai jos) incetinim foarte mult programul.\r\n\r\n== code(c) |\r\nstruct list\r\n{\r\n    int n;\r\n    struct list *next;\r\n}\r\ntypedef struct list list;\r\n==\r\n\r\nIn contiuare vom prezenta o metoda care este de $3-4$ ori mai rapida (adica parcurgerile DF , BF sau altii algoritmi ruleaza de $3-4$ ori mai rapid cand graful este stocat astfel), dar are ca dezavantaj necesitatea de a citi de doua ori fisierul de intrare.\r\n\r\n== code(c) |\r\n#include <stdlib.h>\r\n#include <stdio.h>\r\n\r\nint N, M, *G[N], Deg[N];\r\n\r\nint main(void)\r\n{\r\n    int i, j;\r\n \r\n    freopen(\"in.txt\", \"r\", stdin);\r\n    scanf(\"%d %d\", &N, &M);\r\n    for (; M > 0; M--)\r\n    {\r\n        scanf(\"%d %d\", &i, &j);\r\n        Deg[i - 1]++, Deg[j - 1]++;\r\n    }\r\n    for (i = 0; i < N; Deg[i++] = 0)\r\n        G[i] = (int *) malloc(Deg[i]*sizeof(int));\r\n    fseek(stdin, 0, SEEK_SET);\r\n    scanf(\"%d %d\", &N, &M);\r\n    for (; M > 0; M--)\r\n    {\r\n        scanf(\"%d %d\", &i, &j);\r\n        i--, j--;\r\n        G[i][Deg[i]++] = j,\r\n            G[j][Deg[j]++] = i;\r\n    }\r\n\r\n    return 0;\r\n}\r\n==\r\n\r\nSporul de viteza se datoreaza faptului ca se folosesc vectori in loc de pointeri si struct-uri. Daca ne permite memoria putem evita citirea de doua ori a fisierul prin pastrarea muchiilor intr-o lista de muchii si apoi, dupa calcularea gradelor, inserarea muchiilor in liste. Pentru a demonstra eficienta acestei metode faceti urmatorul test: implementati o sursa cu pointeri si struct si implementati un BF, apoi scrieti codul de mai sus cu urmatoarele modificari:\r\n\r\n== code(c) |\r\n...\r\nfor (i = 0; i < N; i++)\r\n{\r\n      G[i] = (int *) malloc((Deg[i]+1)*sizeof(int));\r\n      G[i][Deg[i]] = -1;\r\n      Deg[i] = 0;\r\n}\r\n...\r\n==\r\n\r\nsi implementati BF astfel:\r\n\r\n== code(c) |\r\nvoid BF()\r\n{\r\n      int Q[N], ql, qr, *p;\r\n      char U[N];\r\n      memset(U, 0, sizeof(U));\r\n      U[Q[ql = qr = 0] = n] = 1;\r\n      for (; ql <= qr; ql++)\r\n              for (p = G[Q[ql]]; *p != -1; p++)\r\n                      if (!U[*p]) U[Q[++qr] = *p] = 1;\r\n}\r\n==\r\n\r\nApoi, incercati sa vedeti diferenta de timp intre cele doua programe... impresionant, nu?\r\n\r\n\r\n\r\nh2. Numere mari (ideea originala de la Radu Berinde)\r\n\r\nIn continuare voi prezenta cum se pot realiza operatii pe numere mari cu foarte putine linii de cod. In general, multi programatori se complica la aceste operatii, desi nu este nevoie! Vom considera ca numerele mari sunt vectori in care elementul de indice $0$ indica lungimea numarului, iar cifrele sunt retinute in ordinea inversa decat cea a citirii.\r\n\r\nh3. Suma a doua numere mari\r\n\r\n== code(c) |\r\nvoid add(int A[], int B[])\r\n{\r\n      int i, t = 0;\r\n      for (i=1; i<=A[0] || i<=B[0] || t; i++, t/=10)\r\n              A[i] = (t += A[i] + B[i]) % 10;\r\n      A[0] = i - 1;\r\n}\r\n==\r\n\r\nh3. Inmultirea unui numar mare cu un numar mic\r\n\r\n== code(c) |\r\nvoid mul(int A[], int B)\r\n{\r\n      int i, t = 0;\r\n      for (i = 1; i <= A[0] || t; i++, t /= 10)\r\n              A[i] = (t += A[i] * B) % 10;\r\n      A[0] = i - 1;\r\n}\r\n==\r\n\r\nh3. Inmultirea unui numar mare cu un numar mare\r\n\r\n== code(c) |\r\nvoid mul(int A[], int B[])\r\n{\r\n      int i, j, t, C[NR_CIFRE];\r\n      memset(C, 0, sizeof(C));\r\n      for (i = 1; i <= A[0]; i++)\r\n      {\r\n              for (t=0, j=1; j <= B[0] || t; j++, t/=10)\r\n                      C[i+j-1]=(t+=C[i+j-1]+A[i]*B[j])%10;\r\n              if (i + j - 2 > C[0]) C[0] = i + j - 2;\r\n      }\r\n      memcpy(A, C, sizeof(C));\r\n}\r\n==\r\n\r\nh3. Scaderea a doua numere mari\r\n\r\n== code(c) |\r\nvoid sub(int A[], int B[])\r\n{\r\n      int i, t = 0;\r\n      for (i = 1; i <= A[0]; i++)\r\n              A[i] += (t = (A[i] -= ((i <= B[0]) ? B[i] : 0) + t) < 0) * 10;\r\n      for (; A[0] > 1 && !A[A[0]]; A[0]--);\r\n}\r\n==\r\n\r\nh3. Impartirea unui numar mare la un numar mic\r\n\r\n== code(c) |\r\nvoid div(int A[], int B)\r\n{\r\n      int i, t = 0;\r\n      for (i = A[0]; i > 0; i--, t %= B)\r\n              A[i] = (t = t * 10 + A[i]) / B;\r\n      for (; A[0] > 1 && !A[A[0]]; A[0]--);\r\n}\r\n==\r\n\r\nh3. Restul unui numar mare la un numar mic\r\n\r\n== code(c) |\r\nint mod(int A[], int B)\r\n{\r\n      int i, t = 0;\r\n      for (i = A[0]; i > 0; i--)\r\n              t = (t * 10 + A[i]) % B;\r\n      return t;\r\n}\r\n==\r\n\r\nh2(#AVL). AVL-uri (ideea originala de la Radu Berinde - again)\r\n\r\nAVL-urile sunt arbori de cautare echilibrati care au complexitate O(lg n) pe operatiile de inserare, stergere si cautare. Pentru mai multe detalii cautati cartea \"Arbori\" pe [2]site-ul doamnei profesoare Emanuela Cerchez. In continuare voi prezenta o metoda destul de simpla de a implementa aceastra structura de date in timp de concurs. Enjoy!\r\n\r\n== code(c) |\r\n#define max(a, b) ((a) > (b) ? (a) : (b))\r\n#define geth(n) (n->h = 1 + max(n->l->h, n->r->h))\r\n\r\nstruct node\r\n{\r\n      int key, h;\r\n      struct node *l, *r;\r\n} *R, *NIL;\r\ntypedef struct node node;\r\n\r\nvoid init(void)\r\n{\r\n      R = NIL = (node *) malloc(sizeof(node));\r\n      NIL->key = NIL->h = 0,\r\n              NIL->l = NIL->r = NULL;\r\n}\r\n\r\nnode* rotleft(node *n)\r\n{\r\n      node *t = n->l;\r\n\r\n      n->l = t->r, t->r = n,\r\n              geth(n), geth(t);\r\n      return t;\r\n}\r\n\r\nnode* rotright(node *n)\r\n{\r\n      node *t = n->r;\r\n \r\n      n->r = t->l, t->l = n,\r\n              geth(n), geth(t);\r\n      return t;\r\n}\r\n\r\nnode* balance(node *n)\r\n{\r\n      geth(n);\r\n      if (n->l->h > n->r->h + 1)\r\n      {\r\n              if (n->l->r->h > n->l->l->h)\r\n                      n->l = rotright(n->l);\r\n              n = rotleft(n);\r\n      }\r\n      else\r\n              if (n->r->h > n->l->h + 1)\r\n              {\r\n                      if (n->r->l->h > n->r->r->h)\r\n                              n->r = rotleft(n->r);\r\n                      n = rotright(n);\r\n              }\r\n      return n;\r\n}\r\n\r\nnode* insert(node *n, int key)\r\n{\r\n      if (n == NIL)\r\n      {\r\n              n = (node *) malloc(sizeof(node));\r\n              n->key = key, n->h = 1, n->l = n->r = NIL;\r\n              return n;\r\n      }\r\n      if (key < n->key)\r\n              n->l = insert(n->l, key);\r\n      else\r\n              n->r = insert(n->r, key);\r\n      return balance(n);\r\n}\r\n\r\nnode* erase(node *n, int key)\r\n{\r\n      node *t;\r\n      if (n == NIL) return n;\r\n      if (n->key == key)\r\n      {\r\n              if (n->l == NIL || n->r == NIL)\r\n              {\r\n                      t = n->l == NIL ? n->r : n->l;\r\n                      free(n); return t;\r\n              }\r\n              else\r\n              {\r\n                      for (t = n->r; t->l != NIL; t = t->l);\r\n                      n->key = t->key,\r\n                              n->r = erase(n->r, t->key);\r\n                      return balance(n);\r\n              }\r\n      }\r\n      if (key < n->key)\r\n              n->l = erase(n->l, key);\r\n      else\r\n              n->r = erase(n->r, key);\r\n      return balance(n);\r\n}\r\n\r\nint search(node *n, int key)\r\n{\r\n      if (n == NIL) return 0;\r\n      if (n->key == key) return 1;\r\n      if (key < n->key)\r\n              return search(n->l, key);\r\n      else\r\n              return search(n->r, key);\r\n}\r\n==\r\n\r\nAici se termina acest articol. Am incercat sa pun accentul pe simplitate si eficienta, si cred ca am reusit acest lucru. Sper ca ati invatat cate ceva din el si recomand sa luati fiecare bucata in parte si sa incercati sa implementati efectiv ca sa intelegi mai bine. Bafta la concursuri tuturor! ;)\r\n',3997,'public',3673,NULL),('documentatie/development','Development','2006-11-22 21:02:23','2009-07-27 14:53:57','h1. Development\r\n\r\nPagina a fost mutata \'aici\':development.',1,'public',NULL,NULL),('development','Development','2007-03-10 12:40:49','2007-12-16 20:07:31','h1. Development\r\n\r\nCodul sursa din spatele site-ului infoarena este \'liber disponibil\':http://hackers.devnet.ro/browser iar dezvoltarea se face in mod \'public\':http://hackers.devnet.ro. Oricine poate sa-si instaleze o varianta \"locala\" de infoarena2, sa adauge feature-uri si sa-si trimita modificarile inapoi.\r\n\r\nSite-ul curent (infoarena2) este scris in php folosind mysql ca baza de date si apache ca server de web. Am incercat sa mentinem codul cat mai simplu pentru a fi usor de modificat si pentru incepatori. Din pacate dezvoltarea la infoarena2 nu s-a miscat de ceva vreme. Momentan ne gandim sa rescriem site-ul folosind tehnologii moderne si experienta acumulata din infoarena2. Avem o \'propunere\':propuneri/3-infoarena3 pentru rescriere.\r\n\r\nMulta vreme am folosit wiki-ul din trac de pe hackers.devnet.ro pentru development. In spiritul de \"dogfooding\" am decis sa folosim trac doar pentru tichete, si sa scrie documentatia de development pe propriul wiki. Momentan scriem in romana, desi engleza ar fi o alegere mai naturala.\r\n\r\nh2. Alte pagini de development\r\n\r\n* \'IAP #3\':propuneri/3-infoarena3 : Propunerea initiala pentru infoarena3\r\n* \'Cerinte\':development/cerinte : Ce trebuie sa implementam in infoarena3\r\n\r\n',1142,'public',NULL,NULL),('preoni-2007/runda-3/solutii','Solutii preONI 2007, Runda 3','2007-03-04 13:00:05','2007-03-07 23:54:33','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Solutii Runda 3\r\n\r\nh2. \'Buline\':problema/buline \r\n\r\nh3. (problema usoara, clasa a 9-a)\r\n\r\nProblema este o variatie a unei probleme clasice: dandu-se un sir de $N$ numere intregi sa se determine o secventa de suma maxima. Singura modificare este ca in aceasta problema sirul este circular. In prima parte a solutiei nu vom lua in considerare faptul ca sirul este circular. Pentru a rezolva problema pentru un sir normal exista o solutie clasica $O(N)$. Se calculeaza pentru fiecare $i$ secventa de suma maxima care se termina cu elementul $i$: este fie secventa de suma maxima care se termina la elementul $i-1$, la care se adauga elementul $i$, fie doar elementul $i$. O scurta descriere in pseudocod a acestui algoritm:\r\n\r\n== code(c) |\r\ns = smax = 0;\r\npentru i = 1, n executa\r\n   s = max(s+A[i], A[i]);\r\n   smax = max(smax, s);\r\nsfarsit pentru\r\n==\r\n\r\nO prezentare detaila a acestei probleme si metode de rezolvare gasiti \'aici\':http://www.ginfo.ro/revista/11_2/focus2.pdf. \r\nVom trata acum si faptul ca sirul este circular. Astfel, trebuie verificate si secventele de forma $i,i+1,...N-1,N,1,2,...j-1,j$. Pentru a realiza acest lucru eficient precalculam un sir de sume partiale $S{~i~} = A{~1~} + A{~2~} + ... + A{~i~} = S{~i-1~}+A{~i~}$ si un al doilea sir $T{~i~} = max(S{~1~}, S{~2~},..., S{~i~}) = max(T{~i-1~}, S{~i~})$. Pentru un $i$ fixat, cea mai buna secventa de forma $i,i+1,...N-1,N,1,2,...j-1,j$ se poate calcula in $O(1)$ astfel: $T{~i-1~}+S{~N~}-S{~i-1~}$.\r\n\r\nUn alt mod de a verifica secventele de forma $i,i+1,...N-1,N,1,2,...j-1,j$ este daca observam ca suma acestei secvente este de fapt suma tuturor elementelor din care se scade secventa $j+1, j+2, ... i-2, i-1$. Astfel ne intereseaza o secventa de suma minima pe care sa o scadem din suma totala. Aceasta se poate determina cu o mica modificare a alogirtmului pentru suma maxima sau inmultind elementele cu $-1$ si cautand o secventa de suma maxima.\r\n\r\nComplexitatea rezolvarii este $O(N)$, iar pentru reconstituirea solutiei sunt necesare  doar cateva variabile aditionale pentru pozitie si lungime.\r\n\r\nh2. \'Zero 2\':problema/zero2\r\n\r\nh3. (problema medie, clasa a 9-a)\r\n\r\nFie $E(N) = 1!*2!*...*N!$. Numarul de zerouri terminale in scrierea lui $E(N)$ in baza $B$ este egal cu numarul de ori $E(N)$ se imparte la $B$. Pentru a determinarea puterea la care apare $B$ in $E(N)$ vom descompune numarul $B$ in factori primi $B = p{~1~}^e{~1~}^*p{~2~}^e{~2~}^*...*p{~k~}^e{~k~}^$. Fie $Nr(N, p)$ puterea la care apare numarul prim $p$ in descompunerea in factori primi a lui $E(N)$. Rezultatul va fi $min([Nr(N, p{~1~})/e{~1~}], [Nr(N, p{~2~})/e{~2~}], ..., [Nr(N, p{~k~})/e{~k~}])$. \r\nAsadar problema se va reduce la a calcula $Nr(N, p)$ in mod eficient. O prima rezolvare de complexitate $O(N*lg N)$ este de parcurge toate numerele de la $1$ la $N$ si de a determina puterea la care apare $p$ in $x!$ ({$1 &le; x &le; N$}) folosind formula $[x/p]+[x/p^2^]+[x/p^3^]+...$ care a fost prezentata si \'aici\':http://infoarena.ro/preoni-2006/runda-4/solutii. Astfel:\r\n$Nr(N, p) = [N/p]+[N/p^2^]+[N/p^3^]+... + [(N-1)/p]+[(N-1)/p^2^]+[(N-1)/p^3^]+... + [1/p]+[1/p^2^]+[1/p^3^]+... =$\r\n$= [N/p]+[(N-1)/p]+...+[1/p] + [N/p^2^]+[(N-1)/p^2^]+...+[1/p^2^] + [N/p^3^]+[(N-1)/p^3^]+...+[1/p^3^] + ...$.\r\n\r\nFie $S(N, p) = [N/p]+[(N-1)/p]+...+[1/p]$. Putem scrie $Nr(N, p) = S(N, p) + S(N, p^2^) + S(N, p^3^) + ...$.\r\nVom arata in continuare ca se poate calcula $S(N, p)$ in $O(1)$ astfel:\r\nTermenii $[1/p],[2/p]...[(p-1)/p]$ au valoarea $0$\r\nTermenii $[p/p],[(p+1)/p]...[(2*p-1)/p]$ au valoarea $1$\r\nTermenii $[(2*p)/p],[(2*p+1)/p]...[(3*p-1)/p]$ au valoarea $2$\r\n...\r\nTermenii $[(k*p)/p],[(k*p+1)/p]...[((k+1)*p-1)/p]$ au valoarea $k$\r\nTermenii $[((k+1)*p)/p]...[N/p]$ au valoarea $k+1$\r\nAstfel $k = [N/p]-1$ iar $S(N, p) = k*(k+1)/2*p + (k+1)*(N-(k+1)*p+1)$. Putem acum calcula $Nr(N, p)$ in $O(log{~p~} N)$. Factorizarea numarului $B$ se poate face in $O(&radic;B)$, iar numarul mediu al factorilor primi din descompunerea lui $B$ este $ln ln B$, complexitatea finala a rezolvarii fiind $O(&radic;B + lnlnB*log{~p~}N)$.\r\n\r\nh2. \'Puteri\':problema/puteri\r\n\r\nh3. (problema grea, clasa a 9-a, problema medie, clasa a 10-a)\r\n\r\nNotam $A{~i~}$ multimea perechilor al caror produs se scrie sub forma {$x^i^$} cu {$x$} numar natural. Problema ne cere calcularea cardinalului reuniunii multimilor $A{~i~}$.\r\n\r\nIn continuare vom arata un mod de a calcula cardinalul unei multimi {$A{~i~}$}. Se observa ca o pereche $(a,b,c) (x,y,z)$ apartine multimii {$A{~i~}$} daca {$a+x=0$},{$b+y=0$} si {$c+z=0$} (mod {$i$}). Vom construi un tablou {$Nr[r1][r2][r3]$} care reprezinta numarul de triplete $(x,y,z)$ cu proprietatea {$r1=x$},{$r2=y$},{$r3=z$} (mod {$i$}). Vom adauga la cardinalul multimii {$A{~i~}$} produse de forma {$Nr[a][b][{@c@}]*Nr[i-a][i-b][i-c]$} ({$i-a,i-b,i-c$} se calculeaza tot mod {$i$}). Deasemenea trebuie avut grija la numerele pentru care {$2*a=0$} {$2*b=0$} si {$2*c=0$} (mod {$i$}), deoarece trebuie adunat $Nr[a][b][{@c@}]*(Nr[a][b][{@c@}]-1)/2$ pentru a nu numara aceeasi pereche de mai multe ori.\r\n\r\nO observatie care ne va ajuta sa calculam cardinalul reununiunii este faptul ca daca un numar se scrie de forma $x^i*j^$ el se poate scrie si sub forma {$y^i^$}, unde $y$ va fi chiar $x^j^$. Asadar $A{~i*j~}$ este inclusa in {$A{~i~}$}. Deci ne va interesa reuniunea multimilor {$A{~i~}$} pentru $i$ numar prim. Cardinalul acestei reuniunii se va calcula folosind principiul includerii si excluderii:\r\n\r\n==code(cpp) |\r\n|S| = |A[2]| + |A[3]| + |A[5]| + ...\r\n    - |A[6]| - |A[10]| - |A[15]| + ...\r\n    + |A[30]| + ...\r\n    - ...\r\n==\r\n\r\nCardinalul multimii $A{~i~}$ se adauga la solutie in cazul in care $i$ are un numar impar de divizori primi si se va scadea din solutie daca are un numar par de divizori. Termenii pentru care in descompunerea lui $i$ apare un factor la putere mai mare de $1$ vor fi ignorati. Datorita limitarilor din enunt nu va trebui sa verificam decat multimile $A{~i~}$ cu {$i &le; 128$}.\r\n\r\n\r\nh2. \'Balanta\':problema/balanta\r\n\r\nh3. (problema usoara, clasa a 10-a)\r\n\r\nProblema se rezolva mentinand doua multimi $H$ si $L$ continand monedele candidate pentru moneda mai grea, respectiv cele candidate pentru moneda mai usoara. Initial $H$ si $L$ contin fiecare toate elementele multimii @{1..N}@. Cele doua multimi se vor actualiza dupa fiecare cantarire. Notand cu $A$ multimea monedelor asezate pe bratul stang si cu $B$ multimea monedelor asezate pe bratul drept al balantei, vom proceda in felul urmator:\r\n\r\n* talerele sunt echilibrate - este clar ca nici una din monedele din $A$ sau $B$ nu poate fi mai grea/mai usoara, deci $H$ va deveni $H - A - B$, iar $L$ va deveni $L - A - B$\r\n\r\n* talerul stang este mai greu - moneda falsa, in caz ca este mai grea, se va afla cu siguranta in multimea $A$ sau, in caz ca este mai usoara, se va afla in multimea $B$. Astfel, $H$ devine $H &#8745; A$, iar $L$ devine $L &#8745; B$\r\n\r\n* talerul drept este mai greu - caz simetric cu cel anterior, $H$ devine $H &#8745; B$, iar $L$ devine $L &#8745; A$.\r\n\r\nLa final vom avea solutie daca si numai daca $|H| = 1 si |L| = 0$, caz in care moneda falsa este mai grea, sau $|H| = 0 si |L| = 1$, cand moneda falsa este mai usoara. \r\n\r\nComplexitatea algoritmului care rezolva problema este $O(M*N)$\r\n\r\nh2. \'Expresii 2\':problema/expresii2\r\n\r\nh3. (problema grea, clasa a 10-a)\r\n\r\nProblema se rezolva folosind programarea dinamica. Mai intai calculam o matrice $V$, unde $V[i, j]$ reprezinta numarul de sfarsituri valabile de expresii ce se pot forma ce necesita adaugarea a $j$ variabile la inceput pentru a se forma o expresie corecta de lungime $i$. Relatiile de recurenta se determina usor urmarind cu atentie in ce configuratii putem ajunge din configuratia actuala (putem pune o variabila, $+$, $*$ sau $!$).\r\nRezolvarea celei de-a 2-a parti a problemei implica folosirea matricei $V$. Avand valorile calculate putem afla caracterul pe care trebuie sa il punem pe o anumita pozitie. Este evident ca la fiecare pas indicele expresiei cautate scade cu numarul de expresii peste care \"sarim\".\r\n\r\nO alta solutie este determinarea expresiei cu numarul $P$, caracter cu caracter folosind o functie care determina cate expresii de o lungime fixata exista care incep cu un prefix dat (prefixul fiind un sir de caractere). Pentru a implementa eficient acesta functie se memoizeaza rezultatele intermediare folosind o tabela hash. Prezentam o scurta descriere a acestei proceduri in pesudocod:\r\n\r\n==code(cpp) |\r\nintreg numara(lungime, prefix)\r\n   daca numara(lungime, prefix) a mai fost apelat returneaza rezultatul stocat in hash; \r\n   daca lungime = 1 si prefix = \"\" returneaza K;\r\n   daca lungime = 1 si prefix = \"A\" sau \"B\" ... sau \"Z\" returneaza 1;\r\n   daca lungime = 1 returneaza 0; \r\n \r\n   rez = 0;\r\n   daca |prefix| < lungime sau (|prefix| = lungime si prefix se termina cu \"!\")\r\n      rez += numara(lungime-1, prefix[1..lungime-1]);\r\n\r\n   daca |prefix| < lungime sau (|prefix| = lungime si prefix se termina cu \"*\")\r\n      pentru i = 1, n-2 executa\r\n         rez += numara(i, prefix[1..i])*numara(n-i-1, prefix[i+1..n-i-1]);\r\n\r\n   daca |prefix| < lungime sau (|prefix| = lungime si prefix se termina cu \"+\")\r\n      pentru i = 1, n-2 executa\r\n         rez += numara(i, prefix[1..i])*numara(n-i-1, prefix[i+1..n-i-1]);\r\n\r\n   pastreaza valoarea rez in hash pentru numara(lungime, prefix);\r\n   returneaza rez;\r\nsfarsit functie\r\n==\r\n\r\nh2. \'Ograzi\':problema/ograzi\r\n\r\nh3. (problema usoara, clasele 11-12)\r\n\r\nProblema este una clasica de cautari ortogonale si se poate face usor o solutie in care se sorteaza dreptunghiurile si punctele dupa coordonata $x$, iar apoi se foloseste o linie de baleiere. Se proceseaza updateuri si querieruri pe un arbore de intervale in o dimensiune. Aceasta solutie are complexitate $O(M*lg N + N*lg N)$. S-au obtinut in jur de $70$ de puncte folosind asemenea abordari.\r\nPentru a obtine o solutie mai eficienta trebuia exploatata particularitatea problemei, adica faptul ca toate dreptunghiurile erau egale. Solutia autorului continea doi pasi: \r\n\r\n* Intai folosim grila de puncte de coordonate $(i*W+0.5, j*H+0.5)$ unde $i$ si $j$ sunt numere intregi. Orice dreptunghi din enunt contine exact un punct din aceasta grila. Vom folosi o tabela de dispersie (hash) ce grupeaza in perechi dreptunghiurile din intrare si punctele din grila interioare lor. \r\n* Pentru a determina daca un punct din cele $M$ este continut in vreun dreptunghi, ne uitam care sunt cele patru puncte din grila vecine acestuia, si vom gasi maxim patru dreptunghiuri asociate acelor 4 puncte din grila. Apoi testam incluziunea punctului nostru in fiecare dintre cele patru dreptunghiuri, astfel putem raspunde la orice test de incluziune in $O(1)$. \r\n\r\nComplexitatea toatala a algoritmului este $O(N + M)$. Felicitam pe Berzan Constantin care a folosit aceasta abordare si a fost singurul ce a luat punctaj maxim pe aceasta problema.\r\n\r\nh2. \'KPerm\':problema/kperm\r\n\r\nh3. (problema medie, clasele 11-12)\r\n\r\nFie $sigma$ o {$K$}-permutare cu $N$ elemente => pentru orice {$i$}, {$1 &le; i &le; N-K$} avem relatiile:\r\n\r\n* {$sigma{~i~} + sigma{~i~} + ... sigma{~i+K-1~}$} congruent cu $0$ ( mod $K$ )\r\n* {$sigma{~i+1~} + sigma{~i+2~} + ... sigma{~i+K~}$} congruent cu $0$ ( mod $K$ )\r\n\r\nScazand cele doua relatii, obtinem $sigma{~i~}$ congruent cu $sigma{~i+K~}$ ( mod {$K$} ).\r\nFie $N$ = {$C * K + R$}, {$0 &le; r < K$}.\r\nSe observa ca intr-o {$K$}-permutare nu conteaza decat resturile numerelor la impartirea cu $K$, si nu numerele propriu-zise. Deci putem privi o permutare in functie de cate resturi r sunt in permutare, pentru orice {$r$} de la $0$ la {$K-1$}. Se observa ca resturile de la $1$ la $R$ apar de exact {$C+1$} ori, in timp ce toate celelalte resturi apar de exact $C$ ori.\r\n\r\nI. {$N &ge; 2 * K$}, sau, echivalent {$C &ge; 2$}. Se observa ca in primele $C$ numere din permutarea care constituie o solutie nu putem pune acelasi rest de cel putin $2$ ori. Observatia este evidenta, deoarece, cum avem relatia $sigma{~i~}$ congruent cu $sigma{~i+K~}$ ( mod {$K$} ), atunci restul care ar aparea de 2 ori in primele $C$ numere ar aparea de cel putin {$2*C$} ori ( pe primele {$C*K$} pozitii ), dar avem maxim {$C+1$} resturi disponibile egale, si cum {$2*C > C+1$}, am ajuns la o contradictie.\r\nII. {$K &le; N < 2*K$}. In acest caz, resturile de la $1$ la $R$ apar de $2$ ori fiecare, iar toate celelalte resturi apar o singura data. Cum doar pozitiile de la $R+1$ la $C$ au un rest unic in permutare ( toate celelalte resturi apar pe exact doua pozitii de forma $i$ si $i + K$ ) => pe aceste pozitii trebuie sa punem toate resturile care apar o singura data. Este evident si ca in primele $R$ pozitii trebuie sa punem resturile diferite doua cate doua, pentru ca fiecare rest apare de doua ori si trebuie pus pe doua pozitii.\r\n\r\nDin ambele cazuri a rezultat ca pentru orice valori ale numerelor $N$ si $K$, o {$K$}-permutare trebuie sa respecte urmatoarele proprietati: \r\n\r\n* pe primele $K$ pozitii din permutare trebuie sa se gaseasca toate resturile {$0$}, {$1$}, ... {$K-1$}\r\n* resturile de la $1$ la $R$ trebuie sa fie asezate pe primele $R$ pozitii\r\n* pe fiecare pozitie $i$ incepand cu $K+1$ trebuie sa punem un numar care sa aiba restul din impartirea la $K$ egal cu restul impartii numarului de pe pozitia $i-K$ la {$K$}\r\n\r\nPentru $K$ par, {$K = 2p$}, cum {$0+1...+(2p-1)$} = {$p*(2p-1)$} si acest numar nu se divide cu {$2p$} pentru ca {$2p-1$} este impar => raspunsul este 0.\r\n\r\nPentru $K$ impar, {$K = 2p+1$}, cum {$0+1...+2p$} = {$p*(2p+1)$}, care este dizibil la {$(2p+1)$}, vom construi permutarea astfel:\r\n\r\n* fixam ordinea primelor $R$ resturi ( in total {$R!$} variante )\r\n* fixam ordinea celorlalte $K-R$ resturi ( in total {${@(K-R)!@}$} variante )\r\n* pentru fiecare rest din primele $R$ sunt $C+1$ pozitii pe care trebuie sa il asezam. Pentru fiecare rest putem pozitiona numerele atasate in {$(C+1)!$} variante, si, cum sunt $R$ resturi, avem {$[(C+1)!]^R^$} variante\r\n* pentru fiecare din celelalte resturi sunt $C$ pozitii pe care trebuie sa le asezam. Pentru fiecare rest putem deci pozitiona numerele atasate in {$C!$} variante, si, cum sunt $K-R$ resturi, avem {$(C!)^K-R^$} variante.\r\n\r\nPentru $K$ impar raspunsul este, dupa cum am demonstrat mai sus, {$(R!)$} * {${@(K-R)!@}$} * {$[(C+1)!]^R^$} * {$(C!)^K-R^$}.\r\n\r\nOBS. In relatia de mai sus nu are importanta daca {$R = 0$}, caci {$0! = 1$} si {$A^0^ = 1$}, pentru orice {$A$}. Deci demonstratia a fost facuta fara a restrange generalitatea.\r\n\r\n\r\nh2. \'Magazin\':problema/magazin\r\n\r\nh3. (problema grea, clasele 11-12)\r\n\r\nProblema se rezolva folosind metoda programarii dinamice. Ca prim pas vom precalcula niste informatii pentru fiecare culoar care vor fi folosite apoi in algoritmul de programare dinamica. Astfel pentru un culoar $i$ exista 4 scenarii care ne intereseaza:\r\n\r\n* se face un pas de distanta $D$ din coltul de sus al unui culoar adiacent la coltul de sus al culoarului $i$, se iau toate produsele de pe culoar incepand de sus si se revine la coltul de jos al culoarului $i$\r\n* se face un pas de distanta $D$ din coltul de sus al unui culoar adiacent la coltul de sus al culoarului $i$, se iau toate produsele de pe culoar incepand de sus si se revine la coltul de sus al culoarului $i$\r\n* se face un pas de distanta $D$ din coltul de jos al unui culoar adiacent la coltul de jos al culoarului $i$, se iau toate produsele de pe culoar incepand de jos si se revine la coltul de jos al culoarului $i$\r\n* se face un pas de distanta $D$ din coltul de jos al unui culoar adiacent la coltul de jos al culoarului $i$, se iau primele $k$ produse de pe culoar incepand de jos si se revine la coltul de jos al culoarului $i$, se face un pas de distanta $D$ din coltul de sos al unui culoar adiacent la coltul de sos al culoarului $i$, se ia restul de produse de pe culoar incepand de sus si se revine la coltul de sus al culoarului $i$\r\n\r\nSe observa ca primul tip de scenariu (cat si cel simetric) are mereu un cost constant, si anume $D+M+1$. Asadar, se vor precalcula informatii doar pentru ultimele 3 tipuri. Aceste informatii se pot calcula usor sortand produsele de pe fiecare culoar si parcurgandu-le (in cazul ultimului scenariu). Complexitatea acestui pas este $O(P*lgP + N)$.\r\nVom realiza acum algoritmul de programare dinamica construind traseul optim culoar cu culoar, de la $1$ la $N$. Se observa ca exista $6$ stari care ne intereseaza la un culoar $i$:\r\n\r\n* $0$ - costul unui traseul optim care trece prin coltul de sus al culoarului $i$, fara a trece prin coltul de jos al culoarului $i$\r\n* $1$ - costul unui traseul optim care trece prin coltul de sus al culoarului $i$, care trece prin coltul de jos al culoarului $i$, iar traseul este conex\r\n* $2$ - costul unui traseul optim care trece prin coltul de sus al culoarului $i$, care trece prin coltul de jos al culoarului $i$, iar traseul *nu* este conex, adica este format din doua trasee care se vor uni la un moment dat (la un culoar $> i$)\r\n* $3$ - costul unui traseul optim care trece prin coltul de jos al culoarului $i$, fara a trece prin coltul de sus al culoarului $i$\r\n* $4$ - costul unui traseul optim care trece prin coltul de jos al culoarului $i$, care trece prin coltul de sus al culoarului $i$, iar traseul este conex\r\n* $5$ - costul unui traseul optim care trece prin coltul de jos al culoarului $i$, care trece prin coltul de sus al culoarului $i$, iar traseul *nu* este conex, adica este format din doua trasee care se vor uni la un moment dat (la un culoar $> i$)\r\n\r\nPentru a calcula oricare din cele $6$ stari ne uitam la cele $6$ stari ale culoarului $i-1$. In total, vor exista $6*6 = 36$ de tranzitii; fiecare se poate calcula in $O(1)$ folosind informatiile precalculate la primul pas. Cele $36$ de tranzitii se pot determina usor pe foaie, trasand cateva exemple. Complexitatea acestui pas este $O(N)$, deci rezolvare este in final $O(P*lg P + N)$.\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',961,'public',NULL,NULL),('blog/infoarena-in-adevarul','infoarena in Adevarul','2007-03-06 08:41:15','2009-02-02 23:45:21','A aparut un \'articol\':http://www.adevarulonline.ro/articole/fostii-olimpici-ii-antreneaza-pe-concurentii-de-la-olimpiade/305061 despre infoarena in ziarul \'Adevarul\':http://www.adevarulonline.ro.\r\n\r\nVezi si \'prima pagina\':doi-la-suta?infoarena-adevarul-prima-pagina.pdf.',13,'public',NULL,NULL),('utilizator/nebhotep','Profil Nebhotep','2007-03-06 11:54:06','2007-03-06 11:54:06','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6217,'public',NULL,NULL),('runda/preoni2007_runda4_1112/clasament','Clasament preoni2007_runda4_1112','2007-03-07 12:12:40','2007-03-07 12:12:40','h1. Clasament ==roundparam(round_id=\"preoni2007_runda4_1112\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda4_1112\")==',1,'round: preoni2007_runda4_1112',NULL,NULL),('utilizator/ln_anila','Profil ln_anila','2007-03-07 06:12:28','2007-03-07 06:12:28','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6224,'public',NULL,NULL),('blog/am-recalculat-rating-urile','Am recalculat rating-urile','2007-02-22 04:20:53','2007-02-22 04:23:11','Am recalculat rating-urile, ca urmare a punctajelor obtinute la ultimele concursuri: \'Winter Challenge\':winter-challenge-1 si \'Runda #2 din preONI\':preoni-2007/runda-2.\r\n\r\n*{\'Vezi clasamentul\':clasament-rating}*\r\nCiteste \'despre rating\':documentatie/rating',13,'protected',NULL,NULL),('preoni-2006/runda-3/solutii','Solutii preONI 2006 - Runda a 3-a','2006-01-21 00:00:00','2007-12-14 23:32:17','h1. Solutii preONI 2006 - Runda a 3-a\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa infoarena_)\r\n\r\nRunda a 3-a concursului preONI 2006 s-a incheiat. Acest articol va prezinta solutiile oficiale ale celor 7 probleme propuse precum si cateva aprecieri pe marginea concursului.\r\n\r\nS-a incheiat si cea de-a treia runda a concursului preONI 2006. Ca de obicei, la fiecare grupa au existat 3 probleme cu nivele diferite de dificultate: usor, mediu, greu. Spre deosebire de runda precedenta, problemele au fost ceva mai accesibile facand mai usoara obtinerea unui punctaj mediu pentru participantii de la toate cele trei grupe. Salutam primul punctaj maxim realizat de Cosmin Gheorghe, participant la clasa a IX-a. Desi nivelul de dificultate al problemelor este unul ridicat (comparativ cu cel de la nationale), nu putem sa nu remarcam faptul ca, la clasa a X-a, nivelul de pregatire al concurentilor este ceva mai scazut fata de celelalte grupe, in conditiile in care olimpiadele se apropie. Ii sfatuim pe toti participantii sa se pregateasca si mai consistent de acum incolo, utilizand si platforma pe care le-o pune la dispozitie InfoArena.\r\n\r\nInainte de ultima runda, la clasa a IX-a, avem deja doi concurenti care s-au detasat de pluton in persoana lui Gheorghe Cosmin si Tataroiu Bogdan, lupta fiind inca acerba pentru ultimele locuri calificabile. La clasa a X-a avem un clasament destul de echilibrat, cu elevii clasati primii fara prea mari emotii inainte de ultima runda, dar cu multe semne de intrebare pentru cei clasati pe locurile 8-10. La clasele XI-XII avem o batalie frumoasa, cu multe punctaje peste $300$ si o situatia foarte confuza catre ultimele locuri calificabile.\r\n\r\nLe uram tutoror succes si fie ca cei mai buni sa mearga in finala!\r\n\r\nh2. Numarare triunghiuri\r\n\r\nh3. (problema simpla, clasa a 9a)\r\n\r\nPentru a rezolva problema trebuie cunoscuta conditia de existenta a unui triunghi cand avem lungimile segmentelor. Fie {$a$}, {$b$}, $c$ lungimile laturilor in ordine nedescrescatoare. Se poate forma un triunghi cu ele doar daca $a + b &ge; c$ (este usor de intuit de ce).\r\n\r\nAcum putem rezolva problema in $O(N^3^)$ verificand toate triunghiurile posibile care s-ar putea forma si numarandu-le doar pe cele ce respecta conditia de mai sus. Aceasta solutie ar trebui sa ia in jur de $75$ de puncte.\r\n\r\nPentru a rezolva mai eficient problema este necesar sa sortam nedescrescator vectorul cu lungimile segmentelor. Acum putem fixa segmentele $a$ si $b$ si putem cauta binar pozitia maxima din vector a segmentului $c$ care respecta {$a + b &ge; c$}. Deci numarul de triunghiuri care se pot forma avand primele doua laturi $a$ si $b$ este egal cu numarul de elemente din vector de dupa $b$ si pana la $c$ (pentru fiecare triunghi luam segmentele {$a$}, {$b$}, $c$ in ordine crescatoare dupa indicii din vector, evitand astfel numararea unui triunghi de doua ori). Deci complexitatea acestei solutii este $O(N^2^ log N)$ si ar fi luat fara probleme punctajul maxim.\r\n\r\nPutem imbunatati solutia de mai sus la o complexitate {$O(N^2^)$}, eliminand cautarea binara. Aceasta solutie va lasam sa o descoperiti voi.\r\n\r\nh2. Divizori primi\r\n\r\nh3. (problema medie, clasa a 9a)\r\n\r\nFiind vorba de maxim $1.000.000$ numere se poate calcula pentru fiecare in parte cati divizori primi are. Pentru acest lucru se foloseste ciurul lui Erathostene si se construieste vectorul {$ndp{~i~}$} - numarul de divizori primi ai lui {$i$}. Parcurgem numerele din $1$ in $1$ si in momentul in care am dat peste un numar care are $0$ divizori primi pana in acest moment inseamna ca am gasit un nou numar prim si vom actualiza vectorul $ndp$ pentru toti multiplii lui si implicit pentru el (numarul fiind propriul sau divizor). Apoi se construieste o matrice $sol{~i,j~}$ care retine care este cel mai mare numar mai mic sau egal cu $i$ cu $j$ divizori primi (adica exact raspunsurile pentru problema noastra). Pentru a construi linia $i$ se copiaza linia $i-1$ si se actualizeaza {$sol{~i,ndp{~i~}~}=i$}.\r\n\r\nPentru mai multe detalii despre cum functioneaza ciurul lui Erathostene puteti accesa \"articolul\":http://infoarena.ro/Ciurul-lui-Erathostene.\r\n\r\nh2. Subsir 2\r\n\r\nh3. (problema grea clasa a 9a, problema medie clasa a 10a, problema usoara clasele 11-12)\r\n\r\nProblema poate fi considerata asemanatoare cu cea a celui mai lung subsir crescator, avand o rezolvare similara de complexitatea $O(N^2^)$ folosind metoda programarii dinamice.\r\n\r\nSe vor construi doi vectori:\r\n\r\n* $A{~i~}$ = lungimea celui mai scurt subsir crescator maximal care incepe cu pozitia $i$\r\n* $T{~i~}$ = urmatorul element dupa pozitia $i$ in cel mai scurt subsir crescator maximal care incepe cu $i$ (pentru reconstiutire)\r\n\r\nPentru fiecare {$i$}, se va cauta un $j > i$ astfel incat {$V{~i~} &le; V{~j~}$} (unde $V$ este vectorul de numere) si se alege acela cu $A{~j~}$ minim, $A{~i~}$ devenind {$A{~j~}+1$}, iar $T{~i~}$ devine {$j$}. Daca nu exista nici un {$j$}, $A{~i~}$ se initializeaza cu $1$ si $T{~i~}$ cu {$i$}.\r\n\r\nCa sirul construit sa fie maximal trebuie ca atunci cand verificam {$j$}-urile pentru un $i$ fixat, {$j$}-ul respectiv sa fie \"dominant\", in sensul ca sa nu existe un $i < k < j$ astfel incat {$V{~i~} &le; V{~k~} &le; V{~j~}$}, deoarece sirul construit cu primul element in $i$ si al doilea in $j$ ar putea fi extins inserand $k$ intre $i$ si {$j$}. Verificarea pentru acest $k$ se poate face in {$O(N)$}, obtinand o solutie $O(N^3^)$ care ar fi adus {$50-60p$}. Pentru a face verificarea in {$O(1)$}, facem observatia ca ne intereseaza doar acel $V{~k~}$ minim care este &ge; {$V{~i~}$}. Pe masura ce se avanseaza cu variabila {$j$}, se pastreaza o variabila {$min$}, reprezentand minimul dintre valorile $V{~j~}$ parcurse pana acum, care sunt &ge; {$V{~i~}$}.\r\n\r\nAstfel, cand se ajunge la un {$j$}, se verifica inainte daca {$V{~j~} < min$} (conditie necesara pentru a construi un sir maximal). Un ultim detaliu in solutie este obtinerea solutiei minime din punct de vedere lexicografic. Cand se selecteaza {$j$}-ul pentru fiecare {$i$}, pe langa faptul ca se alege acela cu $A{~j~}$ minim, in caz de egalitate se va alege acela cu valoarea $V{~j~}$ minima. Selectarea este corecta deoarece nu vor exista {$j1$}, $j2$ cu $A{~j1~}$ si $A{~j2~}$ minim , iar {$V{~j1~} = V{~j2~}$}.\r\nProblema se poate rezolva mai bine intr-o complexitate $O(N*lg^2^ N)$ folosind structuri de date avansate, astfel transformandu-se intr-o problema de clasele 11-12 grea, sau chiar o problema de finala. Lasam aceasta rezolvare ca exercitiu pentru cititor.\r\n\r\nh2. Sum\r\n\r\nh3. (problema usoara, clasa a 10a)\r\n\r\nVom face o prima observatie:\r\n\r\n* $(n, d) = 1 <=> (n, n - d) = 1, (n, n + d) = 1$\r\n\r\nFie {$a = phi (n)$}, indicatorul lui Euler. Fie $b$ numarul de numere prime cu $n$ cuprinse intre $n$ si {$2 * n$}.\r\nDeoarece {$(n, d) = 1 <=> (n, n + d) = 1, a &le; b$}. Deoarece {$(n, d) = 1 <=> (n, n - d) = 1, b &le; a => b = a$}. Fie {$x{~1~}, x{~2~}, .. x{~a~}$} numerele $< n$ si prime cu $n$ => numerele cuprinse intre $n$ si $2 * n$ si prime cu $n$ vor fi {$x{~1~} + n, x{~2~} + n, .. x{~a~} + n$}.\r\n\r\nConform observatiei facute, $(n, n - x{~1~}) = 1, (n, n - x{~2~}) = 1, .. (n, n - x{~a~}) = 1$ =>\r\n\r\n$x{~a~} = n - x{~1~} <=> x{~1~} + x{~a~} = n$\r\n$x{~a-1~} = n - x{~2~} <=> x{~2~} + x{~a-1~} = n$\r\n...\r\n$x{~1~} = n - x{~a~} <=> x{~a~} + x{~1~} = n$\r\n\r\nFie $S1$ suma numerelor prime cu $n$ si mai mici ca {$n$}, fie $S2$ suma numerelor prime cu {$n$}, cuprinse intre $n$ si {$2 * n$}.\r\nAdunand cele a egalitati, obtinem $2 * S1 = a * n$ => {$S1 = (a * n) / 2$}.\r\n\r\n$S2 = a * n + S1$ => {$S1 + S2 = 2 * a * n$}.\r\n\r\nSe foloseste o singura data ciurul lui Erathostene pentru a determina functia phi pentru toate intrebarile. Se poate consulta \"articolul\":http://infoarena.ro/Ciurul-lui-Erathostene despre cirulul lui Erathostene.\r\n\r\nO alta solutie, propusa de Bogdan A. Stoica, se bazeaza pe principul includerii si excluderii. Din enuntul problemei ne dam seama ca suma ceruta este suma tuturor numerelor $z$ cu proprietatea ca {$cmmdc(z, x) = 1$}. Pentru a afla aceste numere este de ajuns sa observam ca $cmmdc(z, x) != 1$ daca si numai daca exista cel putin un $p{~i~} = q{~j~}$ unde {$z = p{~1~}^e{~1~}^&#0042; ... &#0042;p{~n~}^e{~n~}^$}, iar {$x = q{~1~}^f{~1~}^&#0042; ... &#0042;q{~m~}^f{~m~}^$}. Fie doua astfel de numere {$p{~i~} = q{~j~}$}. Noi trebuie sa afla suma tuturor numerelor care se divid cu $p{~i~}$ si sunt in intervalul [{$0, 2*x$}]. Aceste numere sunt : {$p{~i~}, 2&#0042;p{~i~}, ..., k&#0042;p{~i~}$}, {$0 < k &le; [2&#0042;x/p{~i~}]$}. Suma acestor numere se poate scrie ca {$p{~i~} + ... + k&#0042;p{~i~}$}, adica pi(1+...+k) adica {$p{~i~}&#0042;k(k+1)/2$}. De aici suntem tentati sa credem ca suma ceruta (fie aceasta {$S$}) este $S$ = {$x(2&#0042;x-1) - p{~1~}&#0042;k{~1~}&#0042;(k{~1~}+1)/2 - .... - p{~n~}&#0042;k{~n~}&#0042;(k{~n~}+1)/2$}. La o citire mai atenta observam ca am scazut unele de doua ori (cele care se divid si cu $p{~1~}$ si cu {$p{~2~}$}, de exemplu) si nu am scazut deloc alte numere care au un divizor comun cu $x$ mai mare decat $1$ (cele care se divid simultan cu {$p{~1~}$}, $p{~2~}$ si {$p{~3~}$}, de exemplu). Astfel, aplicand principiul includerii si excluderii putem schita formula finala : {$S = x&#0042;(2x-1) - p{~1~}&#0042;k{~1~}&#0042;(k{~1~}+1)/2 - ... + p{~1~}&#0042;p{~2~}&#0042;k\'{~1~}(k\'{~1~}+1)/2 + ... - p{~1~}&#0042;p{~2~}&#0042;p{~3~}&#0042;k\'\'{~1~}(k\'\'{~1~}+1)/2 + ...$}, adica vom scadea toti termenii care se obtin prin inmultirea a unui numar impar de factori primi si vom aduna restul. Aceasta solutie obtine in jur de $80$ de puncte pe restul testelor depasind timpul de executie.\r\n\r\nh2. Pavare 2\r\n\r\nh3. (problema grea, clasa a 10a)\r\n\r\nProblema se rezolva cu programare dinamica. Utilizam urmatoare structura de date:\r\n\r\n* $V[i][j]&#0091;0]$ = numarul de posibilitati pentru a pava $i$ metri astfel incat primele $j$ placi sa fie albe\r\n* $V[i][j]&#0091;1]$ = numarul de posibilitati pentru a pava $i$ metri astfel incat primele $j$ placi sa fie negre\r\n\r\nRelatiile de recurenta sunt acum usor de dedus. Odata calculata matricea putem raspunde foarte usor primei cerinte, facand suma $V[N][i]&#0091;0]$ (pentru {$1 &le; i &le; A$}) si $V[N][i]&#0091;1]$ pentru ({$1 &le; i &le; B$}).\r\n\r\nPentru a 2-a cerinta incercam sa construim a {$K$}-a segventa lexicografica de la inceput catre sfarsit. Astfel, la fiecare pas incercam sa punem o segventa de tipul \'{$0...01$}\' care sa contina un numar maxim de \'{$0$}\'. Daca la pasul curent nu putem pune nici un \'{$0$}\' atunci vom pune o secventa de tipul \'{$1..1$}\' care sa contina un numar minim de {$1$}. Numarul de \'{$0$}\'-uri sau de \'{$1$}\' pe care il punem il vom calcula cu ajutorul matricei precalculate la prima cerinta. Astfel, daca putem pune $p$ de \'{$0$}\' inseamna ca numarul de posibilitati pentru a completa restul solutiei daca punem cel putin $p$ de \'{$0$}\' la inceput este mai mare sau egal cu {$K$}. Alegem cel mai mare numar $p$ cu proprietatea de mai sus. Daca $p$ nu exista, incercam sa punem cat mai putini \'{$1$}\' in aceeasi maniera. Continuam apoi cu restul secventei, iar din $K$ scadem numarul de solutii peste care am \"sarit\".\r\n\r\nh2. Count\r\n\r\nh3. (problema medie, clasele 11-12)\r\n\r\nInainte de a prezenta solutia, enumeram cateva propietati ale grafurilor planare care se vor dovedi utile mai departe:\r\n\r\n# Orice graf planar contine un nod cu grad mai mic decat $6$\r\n# Numarul maxim de muchii pe care il poate avea un graf planar este {$3 * N - 6$}, unde $N$ este numarul de noduri. Asadar $O(M)=O(N)$ ({$M$} fiind numarul de muchii).\r\n# Grafurile planare nu contin clici (subgrafuri complete) cu mai mult de $4$ noduri (nu se poate desena in plan o clica de $5$ noduri fara a intersecta muchiile acesteia).\r\n\r\nConsecinta imediata a propietatii numarul $3$ este ca intr-un graf planar vom avea clici de maxim $4$ noduri. Cum cazurile in care clica cu numar maxim de noduri este compusa dintr-unul sau doua noduri este banal, ne vom concentra atentia pe cazurile in care avem clici de $3$ sau $4$ noduri.\r\n\r\nStiind acest lucru, un algoritm $O(N^2^)$ este usor de obtinut (si multi dintre concurenti au reusit acest lucru pentru $~70$ de puncte). Ideea este urmatoarea:\r\n\r\n* Cazul clicilor de $3$ noduri: se numara toate clicile care includ o anumita muchie incercand sa construim un triunghi impreuna cu fiecare nod din graf. Asadar pentru fiecare muchie, incercam cu fiecare nod (mai putin cele doua capete ale muchiei) sa construim o clica de $3$ noduri. Complexitatea este $O(M*N) = O(N^2^)$ (folosindu-ne de propietatea {$2$}). De altfel problema determinarii numarului de triunghiuri (clici de $3$ noduri) intr-un graf, de aceasta data general, este cunoscuta si cea mai rapida rezolvare cunoscuta de noi este $O(M*N / 32)$ daca pastram matricea de adiacenta pe biti - in total $O(N^2^ / 32)$ memorie. Va lasam pe voi sa descoperiti aceasta solutie iar daca nu reusiti cereti ajutor pe forum si vom completa acest articol.\r\n* In cazul clicilor de $4$ noduri, tot ce avem de facut este sa selectam doua muchii si sa vedem daca cele $4$ capete ale lor formeaza o clica (presupunda ca avem $4$ capete distincte). Acest algoritm are complexitatea $O(M^2^) = O(N^2^)$\r\n\r\nCum determinam, rapid, daca doua noduri sunt vecine? Solutia cea mai usoara este sa pastram matricea de adiacenta (eventual pe biti) si putem raspunde in $O(1)$ la astfel de intrebari dar memoria este {$O(N^2^)$}. O alta idee care reduce marimea memoriei la $O(M)$ este sa pastram listele de adicenta sub forma de hash-uri in loc de liste simple inlantuite (pentru cei care nu sunt familiari cu aceasta structura de date ii sfatuim sa citeasca articolele de pe devnet - sunt interesante si educative). Asadar, folosind hash-urile, memoria ramane $O(M)$ dar putem afla rapid (aproape {$O(1)$}) daca doua noduri sunt vecine. In C++ aceasta structura de date este deja implementata sub numele de map, desi un query are complexitate logaritmica.\r\n\r\nSa trecem la solutia {$O(N)$}. Evident, vom folosi propietatea $1$ (singura nefolosita pana acum). Din moment ce avem un nod cu grad mai mic decat {$6$}, il identificam, generam toate clicile care il contin printr-un backtracking (dat fiind faptul ca sunt maxim $5$ vecini) si il scoatem din graf. Graful rezultat este si el planar si cautam iar nodul cu grad mai mic decat {$6$}, etc. Evident, nu vom face cautarea nodului de fiecare data - asta ar duce la un {$O(N^2^)$}, ci in momentul in care stergem un nod, verificam daca gradele vecinilor sai au scazut sub $6$ si apelam o procedura recursiva cand gasim un astfel de vecin (un soi de $DFS$ in graful dat). Dat fiind faptul ca backtracking-ul ruleaza in timp constant (desi e mare constanta) algoritmul acesta va avea complexitatea $O(N)$ - presupunand ca putem raspunde in $O(1)$ folosind hashurile daca doua noduri sunt vecine. Solutia noastra foloseste map-urile din STL asadar are complexitatea $O(N*logN)$ cu o constanta considerabila {$(~100)$}.\r\n\r\nSolutia de mai sus suporta multiple optimizari asupra factorului constant daca efectuam niste prepocesari inainte de algoritmul descris. Asadar, putem prepocesa pentru toate grafurile de maxim $6$ noduri in care exista un nod conectat la toate celelalte, care este clica maxima si cate sunt. Nu sunt mai mult de $2^12^$ asemenea grafuri, deci prepocesarea va rula instantaneu. Avand aceasta informatie prepocesata, cand eliminam un nod din graful planar, in loc sa facem backtracking pentru a afla clicile maximale, interogam tabelul cu valorile prepocesate, optimizand factorul constant foarte mult (ajunge {$~6$}). Totusi, nu era necesara implementarea acestor optimizari, din moment ce problema era media setului.\r\n\r\nh2. Cowfood\r\n\r\nh3. (problema grea, clasele 11-12)\r\n\r\nProblema este bazata pe principiul includerii si excluderii. Constrangerile relativ mici ale problemei nu ar fi trebuit sa va pacaleasca sa incercati o cautare exhaustiva, intrucat aceasta ar fi obtinut numai $20-30%$ din punctaj.\r\n\r\nInainte de a trece la explicarea problemei, sa ne amintim principiul includerii si excluderii.\r\n\r\n{$&#0124;A{~1~} U A{~2~} U ... U A{~n~}&#0124; =$}\r\n{$&#0124;A{~1~}&#0124; + &#0124;A{~2~}&#0124; + ... + &#0124;A{~n~}&#0124;$}\r\n{$- &#0124;A{~1~} &#8745; A{~2~}| - |A{~2~} &#8745; A{~3~}| - ...$} (toate perechile)\r\n{$+ &#0124;A{~1~} &#8745; A{~2~} &#8745; A{~3~}| + ...$} (toate tripletele)\r\n{$...$}\r\n{$+ (-1)^(n-1)^ &#0124;A{~1~} &#8745; A{~2~} &#8745; ... &#8745; A{~n~}&#0124;$}\r\n\r\nCum va fi folosit acesta? Vom calcula solutia ca fiind &#0124;multimea tuturor experimentelor valide&#0124; - &#0124;multimea experimentelor valide care sigur vor esua&#0124;. Sa notam aceasta multime de experimente cu {$F$}. Pentru orice experiment {$X$}, vom nota $f{~X~}$ = multimea tutoror experimentelor care vor esua conform experimentului {$X$}.\r\n\r\nAstfel, pentru un experiment $A$ de forma ({$a{~1~}, a{~2~}, ..., a{~K~}$}) si orice experiment $B$ = ({$b{~1~}, b{~2~}, ..., b{~K~}$}) cu {$a{~1~} &le; b{~1~}$}, {$a{~2~} &le; b{~2~}$}, ..., {$a{~K~} &le; b{~K~}$}, $B$ apartine {$f{~A~}$}.\r\n\r\nIn acest moment putem sa ne dam seama de solutie\r\n$&#0124;F&#0124; = &#0124;f{~E{~1~}~} U f{~E{~2~}~} U ... U f{~E{~N~}~}&#0124;$, care - conform principiului includerii si excluderii - este egal cu\r\n\r\n{$&#0124;f{~E{~1~}~}&#0124; + &#0124;f{~E{~2~}~}&#0124; + ... + &#0124;f{~E{~N~}~}&#0124;$}\r\n{$- &#0124;f{~E{~1~}~} &#8745; f{~E{~2~}~}| - |f{~E{~1~}~} &#8745; f{~E{~3~}~}| - ...$} (toate perechile)\r\n{$+&#0124;f{~E{~1~}~} &#8745; f{~E{~2~}~} &#8745; f{~E{~3~}~}&#0124; ...$}(toate tripletele)\r\n{$...$}\r\n{$+(-1)^n-1^ &#0124;f{~E{~1~}~} &#8745; f{~E{~2~}~} &#8745; ... &#8745; f{~E{~N~}~}&#0124;$}\r\n\r\nCe reprezinta intersectia (\"&#8745;\") in acest context?\r\nDaca $A = (a{~1~}, a{~2~}, ..., a{~K~})$ si {$B = (b{~1~}, b{~2~}, ..., b{~K~})$}, $A &#8745; B$ va fi multimea ce contine toate experimentele despre care se stie cu siguranta ca vor esua, atat conform lui $A$ cat si lui {$B$}. Altfel spus, $A &#8745; B$ = multimea experimentelor care vor esua conform {$(max(a{~1~}, b{~1~}), max(a{~2~}, b{~2~}), ..., max(a{~K~}, b{~K~}))$}.\r\n\r\nUn ultim lucru care trebuie obinut este calcularea lui |f{~X~}| pentru orice {$X = (x{~1~}, x{~2~}, ... x{~K~})$}. Pentru a obtine un experiment esuat, putem incrementa toate valorile x{~i~} atata timp cat suma lor este &le; {$S$}. Astfel avem |f{~X~}| = {$m(S - (x{~1~} + x{~2~} + ... + x{~K~}), K)$}, unde $m(i, j)$ reprezinta numarul de posibilitati de a aranja cel mult $i$ bile identice in $j$ cutii diferite.\r\n\r\nAceasta se calculeaza simplu folosind recurenta care nu va fi demonstrata aici\r\n\r\n$m(i, j - 1) = p(i, j) = p(i - 1, j) + p(i, j - 1), i, j > 0$\r\n$m(i, 0) = 1$\r\n$m(0,j) = 1$ \r\n\r\ncu $p(i, j)$ = numarul de posibilitati de a aranja exact $i$ bile identice in $j$ cutii diferite. Valorile $m(i, j)$ se preproceseaza la inceput intr-o matrice, in timp {$O(K*S)$}.\r\n\r\nO implementare bruta a problemei va duce la complexitatea $O(K*S + 2^N^*N*K)$, dar aceasta ar obtine numai $60%$ din punctajul maxim. O implementare inteligenta folosind preferabil o functie recursiva care exploreaza toate submultimile celor $N$ experimente si la fiecare pas actualizeaza solutia in $O(K)$ obtine cu usurinta $100$ de puncte. Complexitatea sa este {$O(K*S + 2^N^*K)$}.\r\n\r\n',1,'public',NULL,NULL),('documentatie/imbunatatire-teste','Imbunatatire teste','2007-02-19 01:41:36','2007-03-10 14:04:08','h1. Imbunatatire teste\r\n\r\nPagina a fost mutata \'aici\':implica-te/imbunatatire-teste.',13,'public',NULL,NULL),('preoni-2007/runda-2/solutii','Solutii preONI 2007, Runda 2','2007-02-18 14:08:40','2007-06-27 21:33:46','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Solutii Runda 2\r\n\r\nh2. \'Amlei\':problema/amlei \r\n\r\nh3. (problema usoara, clasa a 9-a, clasa a 10-a)\r\n\r\nPrimul pas al algoritmului este eliminarea conjunctiilor elementare care se repeta, deoarece $A$ OR $A$ = $A$. In continuare, se observa usor ca daca o conjunctie elementara apare doar intr-una din formule, distributia variabilelor care o face adevarata va conduce la rezultate diferite. Asadar, formulele sunt echivalente daca si numai daca contin aceleasi conjunctii elementare, facand abstractie de ordinea termenilor.\r\n\r\nProblema se poate rezolva astfel sortand termenii fiecarei conjunctii si conjunctiile dupa un criteriu oarecare.\r\n\r\nh2. \'Tricouri\':problema/tricouri\r\n\r\nh3. (problema medie, clasa a 9-a)\r\n\r\nDupa ce citim cele $N$ numere din fisierul de intrare, vom realiza o preprocesare ({_filtrare_}) in urmatorul mod: \r\n{$M{~i, j~}$} va fi o lista ( implementata fie ca vector, fie ca lista liniara simplu inlantuita ) care va retine in ordine descrescatoare numerele din fisierul de intrare care dau restul $j$ la impartirea cu {$i$}. Deoarece pentru fiecare interogare numarul de termeni este cel mult 5, este suficient ca aceasta lista sa retina cel mult 5 termeni. Astfel, in momentul in care citim un element de valoare {$x$}, pentru fiecare $i$ de la 2 la 20, vom introduce elementul in lista {$M{~i, x mod i~}$} daca si numai daca aceasta lista nu contine inca 5 termeni sau $x$ este mai mare decat minimul din lista ( in acest ultim caz $x$ va fi copiat peste acest minim, asigurand ca in lista vor ramane cele mai mari numere posibile ).\r\nIn momentul in care citim o interogare de forma {$K P$}, vom genera toate posibilitatile de resturi la impartirea cu $P$ ale primelor $K-1$ numere din suma, al {$K$}-lea rest fiind unic determinat. Pentru o astfel de configuratie de resturi stim in timp {$O(1)$} care este cea mai mare suma ( daca exista ) a unor elemente care sa aiba resturile astfel stabilite, prin utilizarea informatiilor din tabloul {$M$}. \r\nDe exemplu, daca $K = 3$ si {$P = 4$}, pentru primele doua resturi stabilite ale primelor doua numere ( sa zicem ca aceste resturi au valoarea $3$ si respectiv {$2$}), restul celui de-al treilea numar la impartirea cu $4$ nu poate fi decat $3$. Acum, folosind tabloul {$M$} calculat anterior, trebuie sa stim care sunt cele mai mari doua numere care dau la impartirea cu $4$ restul $3$ si care este cel mai mare numar care la impartirea cu $4$ da restul {$2$}. Aceasta suma poate fi calculata deci in {$O(1)$}. Vom genera ( prin metoda backtracking sau folosind mai multe for-uri imbricate ) toate configuratiile posibile de resturi, si o vom retine pe cea care genereaza suma cea mai mare, suma pe care ulterior o vom afisa. Complexitatea finala este deci {$O(N + M * P^K-1^)$}, care asigura punctajul maxim, folosind nivelul cunostintelor de clasa a IX-a.\r\n\r\nO alta solutie mai eleganta dar care depaseste cunostintele de clasa a IX-a ar fi cea care foloseste programarea dinamica in modul urmator: se noteaza cu {$D{~i,j,r~}$} care este suma maxima folosind $i$ numere din primele $j$ resturi posibile la impartirea cu $P$ si pana in momentul curent sa avem format restul {$r$}. Se construieste acest tablou in mod {_bottom-up_}. Raspunsul se va afla in {$D{~K,P-1,0~}$}. Complexitatea unui astfel de algoritm este {$O(N + M * K^2^ * P^2^)$}, care de asemenea obtine 100 de puncte.\r\n\r\nh2. \'Zone\':problema/zone\r\n\r\nh3. (problema grea, clasa a 9-a)\r\n\r\nSe observa ca daca stim linia {$L{~1~}$} si suma asociata zonei {$1$}, coloana {$C{~1~}$} este unic determinata deoarece elementele matricii initiale erau pozitive: pornind cu submatricea de colturi {$(1, 1)$} si {$(L, 1)$}, va trebui sa crestem $C{~1~}$ pana cand suma submatricii de colturi {$(1, 1)$} si {$(L{~1~}, C{~1~})$} va deveni cat am stabilit initial. Cum suma submatricii de colturi {$(1, 1)$} si {$(L{~1~}, X)$} este mai mica decat suma submatricii de colturi {$(1, 1)$} si {$(L{~1~}, X+1)$}, cautarea coloanei {$C{~1~}$} poate fi realizata prin cautare binara. Dupa ce am determinat {$C{~1~}$}, stabilim care dintre cele 8 sume ramase este valoarea zonei {$2$} si determinam in mod similar valoarea coloanei {$C{~2~}$}. Apoi stabilim care dintre cele 7 sume ramase este valoarea pe care o vom asocia zonei {$4$} si determinam si {$L{~2~}$}. Pentru un cvadruplu astfel determinat, {$L{~1~}$}, {$C{~1~}$}, {$L{~2~}$} si {$C{~2~}$}, vom determina toate cele 9 sume care se formeaza si daca ele sunt egale cu sumele impuse initial, atunci inseamna ca avem o solutie. Dintre toate solutiile posibile o vom afisa in final pe cea care respecta conditiile de minimalitate enuntate.\r\n\r\nIn momentul in care cautam binar o linie sau o coloana va trebui sa aflam suma pentru o anumita submatrice. Pentru a realiza acest lucru eficient, vom construi de la inceput matricea de sume partiale {$S$}, unde {$S{~i,j~}$} reprezinta suma elementelor din submatricea care are coltul stanga-sus in {$(1, 1)$} si coltul dreapta-jos in {$(i, j)$}. Astfel, suma submatricii de colturi {$(x{~1~}, y{~1~})-(x{~2~}, y{~2~})$} va fi egala cu {$S{~x2,y2~}$} - {$S{~x1-1,y2~}$} - {$S{~x2,y1-1~}$} + {$S{~x1-1,y1-1~}$}.\r\n\r\nProblema este astfel rezolvata in intregime. Complexitatea algoritmului este {$O(N^2^)$}.\r\n\r\nh2. \'Plantatie\':problema/plantatie\r\n\r\nh3. (problema medie, clasa a 10-a)\r\n\r\nO prima idee de solutie ar fi sa construim o matrice $A[i][j][k]$ = elementul de valoare maxima dintr-un patrat cu coltul stanga-sus pe linia $i$ si coloana $j$ si latura $k$. Aceasta  matrice se poate calcula in $O(N^3^)$ astfel:\r\n$A[i][j][k] = max(A[i][j][k-1], A[i+1][j][k-1], A[i][j+1][k-1], A[i+1][j+1][k-1])$\r\nFiecare intrebare poate fi rezolvata in $O(1)$, dar constructia matricei $A$ nu se va incadra in timp pentru testele mari. \r\nProblema poate fi consideranta o varianta clasica a problemei de $RMQ$ in $2D$. Un articol foarte detaliat (in engleza) despre problema $RMQ$ gasiti \'aici\':http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=lowestCommonAncestor. Asadar, pentru a rezolva cazul $2D$ vom folosi ideile care se folosesc in rezolvarea cazului $1D$. Astfel, vom calcula matricea $A$ dar doar pentru laturi puteri ale lui $2$. $A[i][j][k]$ va fi elementul de valoare maxima dintr-un patrat cu coltul stanga-sus pe linia $i$ si coloana $j$ si latura $2^k^$.\r\n$A[i][j][k] = max(A[i][j][k-1], A[i][j+2^k-1^][k-1], A[i+2^k-1^][j][k-1], A[i+2^k-1^][j+2^k-1^][k-1])$\r\nPentru o raspunde la o intrebare $i j k$ in $O(1)$ vom determina cea mai mare putere $p$ a lui $2$ astfel incat $2^p^ &le; k$, si vom lua maximul din $4$ patrate cu colturile in patratul din intrebare si latura $2^p^$. Astfel, raspunsul pentru o intrebare $i j k$ este $max(A[i][j][p], A[i][j+k-2^p^][p], A[i+k-2^p^][j][p], A[i+k-2^p^][j+k-2^p^][p])$.\r\n\r\nh2. \'Culori\':problema/culori\r\n\r\nh3. (problema grea, clasa a 10-a, problema medie, clasele 11-12)\r\n\r\nObservam ca algoritmul de parcurgere al lui Bob reprezinta de fapt parcurgerea Euler a arborelui. Singura diferenta consta in faptul ca el nu noteaza nodurile prin care trece, ci doar culorile acestora. \r\n\r\nFie un arbore cu radacina in $T$, aceasta avand fii $F{~1~}$, $F{~2~}$, ... $F{~k~}$. Notand cu $[T]$ vectorul de culori generat de arborele de radacina $T$, obtinem $[T] = T$, daca arborele contine un singur nod si $[T] = T + [F{~1~}] + T + [F{~2~}] ... [F{~k~}] + T$ altfel (unde $\"+\"$ este operatorul de concatenare).\r\n\r\nDe aici se contureaza repede ideea de programare dinamica. Construim matricea $A{~i,j~} = numarul de arbori care ar fi putut genera subsecventa i..j a sirului initial de culori$.\r\n\r\nDin constructia sirului de culori reiese ca are sens sa calculam $A{~i,j~}$ numai daca $C{~i~} = C{~j~}$ (unde $C$ este vectorul de culori). In acest caz subarborele determinat de primul fiu al radacinii curente va genera sirul de culori cuprins $i+1$ si un indice $k$. Fixandu-l pe acesta, problema se reduce la numararea posibilitatilor de a forma arbori care sa corespunda intervalului $i+1..k$ si cea de a forma arbori pentru intervalul $k+1..j$\r\n\r\nAstfel avem $A{~i,i~} = 1$ si $A{~i,j~} = Suma(A{~i+1,k~} * A{~k+1,j~} | i < k < j si C{~i+1~} = C{~k~})$.\r\n\r\nComplexitatea algoritmului este $O(N^3^)$, dar daca este implementat cu grija poate fi facut sa ruleze in aprox. 0.5 secunde pentru oricare din testele folosite la evaluare. O ultima optimizare (mica, dar care imbunatateste codul in mod simtitor) consta in faptul ca, deoarece orice parcurgere euler este de lungime impara, are rost sa calculam $A{~i,j~}$ numai daca $i+j$ este numar par.\r\n\r\nh2. \'Reguli\':problema/reguli\r\n\r\nh3. (problema usoara, clasele 11-12)\r\n\r\nProblema se rezolva folosind cunostinte de potrivire a sirurilor. Fie sirul $D$ sirul diferentelor dintre termeni consecutivi ai sirului {$x$}. Astfel, trebuie sa determinam cea mai scurta perioada a acestui sir. Pentru a calcula aceasta informatie in {$O(N)$}, vom calcula functia prefix corespunzatoare sirului conform algoritmului de potrivire Knuth-Morris-Prat (KMP). Avand aceasta functie calculata, putem determina in {$O(1)$} daca primele $L$ elemente din $D$ reprezinta o perioada astfel: fie $r$ restul impartirii lui $N$ la {$L$} ( cate elemente raman la sfarsit intr-o posibila perioada incompleta ) si $c$ catul acestui rest ( numarul de perioade ). $L$ poate fi deci lungimea unei perioade daca si numai daca sunt indeplinite simultan conditiile:\r\n\r\n* $PI{~N-r~}$ > 0\r\n* {$(N-r)$} divizibil la {$(N-r-PI{~N-r~})$}\r\n* {$(N-r)$} / {$(N-r-PI{~N-r~})$} = $c$,\r\n* {$ok{~r~}$} este $adevarat$ ( adica ultimele $r$ caractere se potrivesc ),\r\n\r\nunde $PI{~i~}$ este vectorul reprezentat de functia prefix si {$ok{~i~}$} este adevarat daca si numai daca sufixul de lungime $i$ din sir este egal cu prefixul de lungime $i$. Acest vector se poate construi tot in complexitate liniara, tinand cont de faptul ca toate sufixele care sunt si prefix pentru sirul initial au lungimile de forma $PI[N]$, $PI[PI[N]]$, $PI[PI[PI[N]]]$, etc.\r\n\r\nDintre toate lungimile $L$ care indeplinesc conditiile de mai sus se alege cea care are lungimea minima. Aceasta abordare nu este unica abordare optima. Algoritmul mentionat obtine 100 de puncte. \r\n\r\nh2. \'Ghiozdan\':problema/ghiozdan\r\n\r\nh3. (problema grea, clasele 11-12)\r\n\r\nO prima solutie clasica ar fi folosind metoda programarii dinamice. Se construieste o matrice $A[i][j]$ = numarul minim de obiecte necesare din primele $i$ obiecte pentru a obtine o greutate $j$. Relatia de recurenta este:\r\n$A[i][j] = min(A[i-1][j], A[i-1][j-V[i]]+1)$ unde $V[i]$ este greutatea obiectului $i$ ({$i &le; N, j &le; G$}).\r\nAceasta solutie are complexitate $O(N*G)$ si nu se incadreaza in timp datorila limitelor mari pentru $N$ si $G$. De asemenea, pentru reconstructie trebuie pastrata o matrice $T$ de dimensiune $N*G$, care nu incape in memorie. Deoarece avem numai greutati intre $1$ si $200$, putem folosi o alta abordare: $A[i][j]$ = numarul minim de obiecte necesare cu greutate $&le; i$ pentru a obtine o greutate $j$. Relatia de recurenta este:\r\n$A[i][j] = min(A[i-1][j], A[i-1][j-i]+1, A[i-1][j-2*i]+2 ... A[i-1][j-C[i]*i]+C[i])$ unde $C[i]$ este numarul de obiecte de greutate $i$ care exista ({$i &le; 200, j &le; G$}). \r\nO implementare triviala ar avea aceeasi complexitate $O(N*G)$, dar putem imbunatati solutia folosind o structura de date numita _deque_. Puteti citi mai mult despre aceasta structura \'aici\':http://infoarena.ro/USACO-dec-2004-divizia-GOLD (problema Divide), \'aici\':http://infoarena.ro/preoni-2005/runda-3/solutii (problema Ferma) si \'aici\':http://infoarena.ro/preoni-2006/runda-2/solutii (problema Struti). \r\nVom calcula elemente din linia $i$ a matricei astfel: intai elementele de forma $k*i$, apoi elementele $k*i+1$, $k*i+2$, ... $k*i+(k-1)$. Cand calculam $A[i][j]$ cu $j = k*i+r$ , vom avea in deque toate elementele $A[i-1][x*i+r] + (k-x)$ cu $k-C[i] &le; x &le; k$. Astfel $A[i][j]$ se determina in $O(1)$ folosind capatul stanga al deque-ului. Cand se trece la calculul elementului $(k+1)*i+r$ se elimina din deque elementul $A[i-1][(k-C[i])*i+r]+...$ , si se insereaza elementul $A[i-1][(k+1)*i+r]$. Conform relatiei, inainte de inserare toate elementele din deque ar trebui marite cu $1$, dar acest lucru este echivalent cu a scadea $1$ din elementul care se insereaza. Astfel, se poate determina matricea $A$ in timp $O(200*G)$. Deoarece se pot retine doar ultimele doua linii din matricea $A$ , memoria folosita este $O(G)$. \r\nDesigur, pentru reconstituire ar trebui retinuta o alta matrice $T$ de dimensiuni $200*G$ ,dar nu este destula memorie pentru a construi o astfel de matrice. O solutie ar fi pastrarea liniilor din matricea $A$ din $&radic;200$ in $&radic;200$. O scurta descriere despre aceasta metoda gasiti \'aici\':http://infoarena.ro/winter-challenge-1/solutii (problema Smen). Memoria folosita ar fi fost $O(&radic;200*G)$. \r\nDin fericire existe o metoda _divide et impera_ mult mai usor de implementat pentru a reconstitui solutia folosind doar $O(G)$ memorie. Presupunem ca rezolvam problema initiala folosind dinamica de mai sus si pastrand doar ultimele doua linii din matrice. Stim acum ca greutatea maxima care se poate obtine este $H &le; G$. Consideram o solutie optima (cu numar minim de obiecte) de a lua obiecte in ghiozdan de greutate $H$. Putem imparti aceasta solutie in doua bucati: sa determinam o solutie optima de a obtine greutatea $X$ folosind obiecte cu greutati $&le; 100$ si o solutie optima de a obtine greutatea $H-X$ folosind obiecte cu greutati $> 100$. Putem determina aceasta valoare $X$ in timp ce facem dinamica initiala (folosind inca o matrice $B$ si pastrand ultimele doua linii) si apoi putem rezolva recursiv cele doua subprobleme. Asfel, la fiecare pas avem un interval $[st...dr]$ in care sunt greutatile pe care le folosim si o valoare $H$ care reprezinta greutatea pe care vrem s-o obtinem. La fiecare apel putem folosi aceleasi matrici, deci necesarul de memorie nu va depasi $O(G)$. Vom face si o analiza a complexitatii. Fie $T(st, dr, H)$ complexitatea pentru a rezolva o subproblema.\r\n$T(st, dr, H) = O((dr-st+1)*H) + T(st, (st+dr)/2, X) + T((st+dr)/2+1, dr, H-X)$\r\nSe poate demonstra prin inductie ca $T(st, dr, H) = O((dr-st+1)*H)$.\r\nO prezentarea mult mai detaliata a acestei metoda si despre cum aceasta se poate aplica pentru a determina cel mai lung subsir comun a doua siruri folosind memorie liniara gasiti \'aici\':http://www.ics.uci.edu/~eppstein/161/960229.html.\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'public',NULL,NULL),('runda/lame.contest','lame.contest','2009-03-27 22:18:25','2009-03-27 22:18:25','h1. == roundparam(round_id=\"lame.contest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"lame.contest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"lame.contest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"lame.contest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/lame.contest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"lame.contest\" score=\"1\")==',9714,'round: lame.contest',NULL,NULL),('screencast','Screencast','2007-02-25 12:41:25','2007-02-25 12:41:25','h1. Screencast\r\n\r\nA screencast is a recording of computer screen output, usually containing audio narration typically published as a video file. However, the technology has existed for much longer. Screencasts are typically created to produce software and web application demonstrations. This was mostly done within corporations as a way to facilitate employee training. However, further interest has been sparked through the increased blogging trend, which has eased content publishing. ...\r\n',13,'public',NULL,NULL),('screencast/contul-meu','Contul meu, Screencast','2007-02-25 12:44:58','2007-02-26 20:44:42','h1. Contul meu la infoarena\r\n\r\nInca lucram la \"tehnologia\" asta :) We\'re not there yet...\r\n\r\n== GoogleVideo(id=\"2535789311422139569\" width=\"425\" height=\"350\") == \r\n\r\n\r\nDin screencast-ul acesta, utilizatorii vor invata cum se pot inregistra pe site si cum isi pot edita optiunile contului.\r\n\r\nGuidelines de \"filmare\":\r\n\r\n* Prezinta-te\r\n* Descrie pe scurt scopul screencast-ului. Mentioneaza ca un utilizator are nevoie de cont ca sa poata participa la concursurile infoarena si ca sa poata trimite solutii la problemele din arhiva. Pentru a citi articole si probleme nu este nevoie de cont.\r\n* Demonstreaza inregistrare unui cont nou. \r\n** Se va atrage atentia asupra faptului ca inregistrarea se face doar daca nu ai cont deja. In caz ca ti-ai uitat parola si/sau contul, se va folosi optiunea de \"reset password\".\r\n*** Arata sectiunea de reset password si explica ce trebuie completat si cum functioneaza. Nu este nevoie sa mergi pana la capat (i.e. sa resetezi pe bune parola unui cont). E de ajuns sa explici ce face ecranul de reset password si sa treci mai departe.\r\n** Se va explica semnificatia campului de newsletter (Ma abonez la newsletter. Sunt de acord sa primesc pe e-mail noutati despre infoarena. Ma pot dezabona oricand.) Aici trebuie mentionat ca, de obicei, pe email se primesc instiintari atunci cand apar concursuri noi. Se trimit in medie cam 3-4 email-uri pe luna.\r\n** Pentru inregistrarea demonstrativa se vor folosi date fictive dar naturale. In alte cuvinte, fara `idutilizator`, `nume complet` samd.\r\n* Demonstreaza autentificarea, din casuta de autentificare din stanga.\r\n** Se va explica semnificatia casutei \"Pastreaza-ma autentificat\"\r\n* Demonstreaza cum se editeaza optiunile contului.\r\n** Arata cum se uploadeaza poza personala. Mentioneaza faptul ca poza este redimensionata automat.\r\n** Mentioneaza cam pe unde apare poza pe site.\r\n** Mentioneaza ca de aici te poti dezabona la newsletter.\r\n* Demonstreaza logout.\r\n',13,'public',NULL,NULL),('screencast/rezolva-probleme','Cum se rezolva probleme din arhiva','2007-02-25 21:34:55','2007-02-26 07:45:20','h1. Cum se rezolva probleme din arhiva\r\n\r\nDin screencast-ul acesta, utilizatorii vor invata cum se citesc probleme din arhiva, cum se trimit solutii si cum se urmareste evaluarea lor.\r\n\r\n\"Script de filmare\"\r\n\r\n* Prezinta-te\r\n* Descrie pe scurt scopul screencast-ului. Mentioneaza ca un utilizator are nevoie de cont ca sa poata participa la concursurile infoarena si ca sa poata trimite solutii la problemele din arhiva.\r\n* Autentifica-te\r\n* Alege o problema din arhiva\r\n** Mentioneaza ca in acest moment arhiva are peste 320 de probleme\r\n* Vizualizeaza problema A+B\r\n** Mentioneaza ca cerintele problemei trebuie respectate cu exactitate intrucat evaluarea se face automat.\r\n** Descrie capul de tabel de la o problema\r\n*** Atentie la numele fisierului de intrare/iesire. Se va respecta case-ul.\r\n*** Despre limita de timp si de memorie\r\n** Citeste despre input si output in problema A+B. Mentioneaza ca output-ul trebuie facut exact asa cum apare in enunt. Daca se print-eaza informatii in plus sau daca se asteapta apasarea unei taste, evaluatorul va acorda 0 puncte.\r\n* Trimite o solutie corecta la problema A+B folosind formularul din pagina de problema\r\n** Inainte sa submitezi afiseaza sursa pe ecran (notepad?)\r\n** Mentioneaza ca sursele trebuie compilate si testate pe calculator inainte sa fie trimise.\r\n* Prezinta monitorul de evaluare\r\n** Ce face in general\r\n** Prezinta job details despre sursa pe care am trimis-o.\r\n* Demonstreaza trimiterea unei surse ce contine erori de compilare.\r\n** Modifica sursa tocmai trimisa. Adauga #include <conio.h>\r\n*** Mentioneaza ca acest header este specific MSDOS nu face parte din limbajul C standard. Programul nu va compila.\r\n** Trimite sursa\r\n** Afiseaza job details cu eroarea de compilare.\r\n** Afiseaza o cutie cu adresa http://infoarena.ro/documentatie/evaluator in care se gasesc informatii aditionale despre compilatoarele folosite de infoarena, ce merge si ce nu.\r\n* Prezinta sectiunea de statistici din cadrul paginei de profil.\r\n** Arata cum problema `adunare` apare acum ca rezolvata.\r\n** Arata pagina de statistici a altui utilizator mai \"harnic\"\r\n\r\n',13,'public',NULL,NULL),('preoni-2007/runda-3','Runda 3 preONI 2007','2007-01-15 16:00:43','2007-03-07 12:22:22','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. preONI 2007, Runda 3\r\n\r\n(htabs)*(active) \'Despre...\':preoni-2007/runda-3\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/runda-3/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-3/9\r\n\r\n*Runda 3 s-a incheiat!*\r\n\r\nRunda a inceput *Duminica 4 martie*, la ora {*09^00^*} si a durat *4h*. Participantii au avut de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Ca sa poata participa la aceasta runda, concurentii au trebuie sa se inscrie *inainte de ora 09^00^* la grupa de varsta corespunzatoare! *Cei care nu s-au inscris* la o grupa de varsta nu li s-a modificat \'rating-ul\':documentatie/rating!\r\n\r\nAceeasi procedura se va urma la fiecare runda preONI. Timp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta&hellip;\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/runda-3/11-12\r\n\r\nPoti vedea solutiile problemelor \'aici\':preoni-2007/runda-3/solutii.\r\n\r\nh2. Clasament Runda 3\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-3/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-3/11-12\r\n\r\nh2. Discutii preONI pe forum\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\nh2. Organizatori\r\n\r\n* Subiectele vor fi propuse de:\r\n==User(user=\"azotlichid\" type=\"tiny\")==\r\n==User(user=\"cosmin\" type=\"tiny\")==\r\n==User(user=\"danielp\" type=\"tiny\")==\r\n==User(user=\"ditzonec\" type=\"tiny\")==\r\n==User(user=\"domino\" type=\"tiny\")==\r\n==User(user=\"filipb\" type=\"tiny\")==\r\n\r\n* Pentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n==User(user=\"fluffy\" type=\"tiny\")==\r\n==User(user=\"svalentin\" type=\"tiny\")==\r\n==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('utilizator/lebappe','Profil lebappe','2007-03-17 17:23:52','2007-03-17 17:23:52','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6306,'public',NULL,NULL),('preoni-2007/runda-4','Runda 4 preONI 2007','2007-01-15 16:01:16','2007-03-21 11:07:33','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. preONI 2007, Runda 4\r\n\r\n(htabs)*(active) \'Despre...\':preoni-2007/runda-4\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/runda-4/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-4/9\r\n\r\nRunda va incepe *Duminica 25 martie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Ca sa poata participa la aceasta runda, concurentii trebuie sa se inscrie *inainte de ora 09^00^* la grupa de varsta corespunzatoare! *Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating!\r\n\r\nAceeasi procedura se va urma la fiecare runda preONI. Timp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta&hellip;\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/runda-4/11-12\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':preoni-2007/runda-4/solutii.\r\n\r\nh2. Clasament Runda 4\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-4/11-12\r\n\r\nh2. Discutii preONI pe forum\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\nh2. Organizatori\r\n\r\n* Subiectele vor fi propuse de:\r\n==User(user=\"cosmin\" type=\"tiny\")==\r\n==User(user=\"ditzonec\" type=\"tiny\")==\r\n==User(user=\"domino\" type=\"tiny\")==\r\n==User(user=\"filipb\" type=\"tiny\")==\r\n==User(user=\"greco\" type=\"tiny\")==\r\n\r\n* Pentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n==User(user=\"wickedman\" type=\"tiny\")==\r\n==User(user=\"fluffy\" type=\"tiny\")==\r\n==User(user=\"svalentin\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('djgpp-instalarea-de-la-a-la-z','DJGPP - instalarea de la A la Z','2006-03-12 00:00:00','2009-02-20 00:02:00','h1. DJGPP - instalarea de la A la Z\r\n\r\n(Categoria _Diverse_, Autor _Tudor Aursulesei_)\r\n\r\nProbabil ca ai auzit de puternicul compilator $Gnu C$. Este acela folosit pe la mai toate competitiile mai mari de nationala (inclusiv). Avantaje:\r\n\r\n* lucreaza pe 32 de biti; asta inseamna ca programele compilate cu el vor merge mult mai repede!\r\n* stiva mai mare &#8658; erorile gen $stack overflow$ vor apare mult mai rar.\r\n* memorie mai mare &#8658; @long x[10000000]@ chiar exista\r\n\r\nAcest ghid este valabil pentru $Windows XP$.\r\nInainte sa incepem, trebuie sa raspundem la cateva intrebari:\r\n\r\nh2. Ce este DJGPP?\r\n\r\nO colectie de programe de $UNIX$ portate pentru $DOS$. Vizitati \"http://delorie.com/djgpp\":http://delorie.com/djgpp pentru detalii. Cel mai important, dupa ce veti instala corect $DJGPP$, veti putea scrie din linia de comanda in $DOS$ comenzi gen $gcc test.c *o test.exe$.\r\n\r\nh2. Ce este RHIDE?\r\n\r\nEste un $IDE (Integrated Development Environment)$ pentru $DJGPP$. Deosebit de puternic si seamana cu $Borland C 3.1$ la culoare ${:)}$. Se impaca de minune cu $GCC$! Important; ${NU}$ vom folosi versiunea de ${RHIDE}$ pe care ne-o ofera ${DJGPP}$, ci vom folosi una mai noua, dezvoltata de \"SET\":http://setedit.sourceforge.net. Are propriul lui editor, $Setedit$, dar a dezvoltat si $RHIDE$, eliminand o parte din buguri.\r\n\r\nVersiunea lui se gaseste la \"http://sourceforge.net/project/showfiles.php?group_id=32835\":http://sourceforge.net/project/showfiles.php?group_id=32835 , sectiunea extra! Recomand sa o luati acum: $pachetul RHIDE 1.5 + Ed 0.5.4 + gdb 6.1.1$ \r\n\r\nh2. Sa incepem\r\n\r\nAccesam link-ul \"http://www.delorie.com/djgpp/zip-picker.html\":http://www.delorie.com/djgpp/zip-picker.html si alegem optiunile (pe rand)\r\n\r\n* Build and run programs with DJGPP\r\n* Windows 2000/XP\r\n* Yes\r\n* C si C++\r\n\r\nLa $Integrated Development Environments and Tools$ aveti grija sa nu fie selectat $RHIDE$ (dupa cum am zis si mai sus, vom folosi o alta versiune).\r\n\r\nDe asemenea, alegem $No$ la Optiunea $Would you like GDB?$ (daca folositi GDB, atunci luati si acest pachet). Contiunam cu $\"Tell me which files I need\"$\r\n\r\nAr trebui sa obtinem urmatoarea lista:\r\n\r\n* unzip32.exe to unzip the zip files 95kb\r\n* v2/copying.dj Copyright info 3kb\r\n* v2/djdev203.zip Basic Development Kit 1.5mb\r\n* v2/faq230b.zip F.A.Q. 664kb\r\n* v2/readme.1st Installation instructions 22kb\r\n* v2gnu/bnu2161b.zip Basic assembler, linker 3.3mb\r\n* v2gnu/gcc401b.zip Basic GCC compiler 4.0mb\r\n* v2gnu/gdb611b.zip GNU debugger 1.5mb\r\n* v2gnu/gpp401b.zip C++ compiler 4.4mb\r\n* v2gnu/mak3791b.zip Make (processes makefiles)267b\r\n* v2gnu/txi48b.zip Info file viewer 779kb\r\n\r\nDownloadati-le!\r\n\r\nIncercati sa le puneti pe toate intr-un director gen $c:\\djgpp\\$ (de altfel, pe acesta il folosesc eu si vi-l recomand; articolul presupune in continuare ca aceasta este calea unde ati instalat programul). Deschideti o fereastra de $Explorer$ si faceti drag-n-drop la fiecare arhiva peste executabilul $unzip32.exe$. Ar trebui sa va apara directoare gen $bin$ si $include$. Sa nu uitam de versiunea de $RHIDE$ pe care am mentionat-o mai sus. Despachetati-o si pe aceasta in acelasi mod!\r\n\r\nVom contiuna cu setarea variabilei de mediu $DJGPP$. (foarte important)\r\nClick dreapta pe $My Computer &#8594; Properties &#8594; Advanced &#8594; Environment Variables$. In sectiunea System variables, editati variabila $PATH$ astfel incat aceasta sa arate si spre calea $C:\\DJGPP\\BIN$. Separati caile cu $;$ (ex: $C:\\DJGPP\\BIN;C:\\WINDOWS\\system32;...$. De asemenea, creeati o variabila noua numita $DJGPP$ care aibe valoarea $C:\\DJGPP\\DJGPP.ENV$ (daca ati instalat in alta parte, modificati caile dupa caz). Dupa ce ati modificat variabilele de sistem, calculatorul trebuie restartat.\r\n\r\nDaca nu doriti sa modificati variabilele de sistem, se recomanda crearea unui fisier batch care sa lanseze $RHIDE$. Va prezint un exemplu:\r\n\r\n== code(c) |@echo off\r\nset PATH=c:/djgpp/bin;%PATH%\r\nset DJGPP=c:/djgpp/djgpp.env\r\nchdir c:/djgpp/lucru\r\nc:/djgpp/bin/rhide.exe\r\n==\r\n\r\nRulati batch-ul. Ar trebui *sa nu dati* de o eroare care zice ceva de variabila $PATH$ pusa gresit sau de variabila $DJGPP$. Daca va apare, recititi partea de variabile de sistem din articol sau cititi fisierul $readme.1st$ (deschideti-l cu $Word$, nu cu $Notepad$). Daca nu aveti nici o eroare, ar trebui sa fiti intampinati de o fereastra in care se zice ceva de $Robert Hohne (RH din RHIDE) si Salvador Eduardo Tropea (omul care a imbunatatit RHIDE)$. Creeati un fisier nou in care sa bagati cateva linii de test.\r\n\r\n== code(c) |#include <stdio.h>\r\nint main()\r\n{\r\n    printf(\"%d %d %d\" , 1, 2, 3);\r\n    return 0;\r\n}\r\n==\r\n\r\n$Ctrl+F9$ ca sa compilati. $Ctrl+F2$ reset la program. $Shift + F4 $ruleaza pana la linia la care se afla cursorul. $Shift+F8$ e $Step Over$ fara sa se schimbe modul monitorului (fara flick la monitor). $Shift+F7$ e $Run Into$ fara sa se schimbe modul monitorului. $Shift+F2$ e $GREP$ (utilitar UNIX portat). $Alt + F5$ arata rezultatul rularii programului (in versiunea de $RHIDE$ de pe $DJGPP$, nu prea mergea aceasta functie). Recomand optiunile din $Options &#8594; Environment &#8594; Preferences$.\r\n\r\n* Screen Mode 80 x 50\r\n* Syntax highlighting\r\n\r\nIar tot din $Options &#8594; Environment &#8594; Editor &#8594; Editor Options$\r\n\r\n* Autoindent\r\n* Use Tabs\r\n* Intelligent C indent\r\n* Match pair on the fly\r\n\r\n...Si altele , pe care va las sa le descoperiti singuri.\r\n\r\nAvertizare. Desi aceasta versiune de $RHIDE$ este mai stabila decat cea de pe $DJGPP$, este sansa sa se prabuseasca la $Debugging$ ceva mai complex (crash ${:)}$). Nimic nu este perfect. De aceea este recomandat sa salvati din 15 in 15 minute.\r\nPuteti incerca si alte versiuni de RHIDE de la http://rhide.sourceforge.net/snapshots/index.html Unele dau eroare intr-un loc, altele in alt loc. Puteti sa le incercati pe rand.\r\n\r\nAmintiti-va totusi sa salvati cat mai des si sa nu urmariti evolutia unor variabile prea mari gen @x[10000000]@ ${:)}$. De asemenea nu incercati sa afisati pe ecran si sa vedeti ce rezultat a iesit cu $Alt+F5$. S-ar putea sa nu mearga. Daca aveti probleme $MARI$ cu programul, stergeti fisierele\r\n\r\n* rh_opt.gpr\r\n* rh_opt.gdt\r\n\r\nAsta o sa il faca ca nou, in caz ca refuza sa porneasca sau e mai instabil decat era cand l-ati instalat.\r\n\r\nRecomand de asemenea sa explorati fiecare meniu si scurtatura a programului, deoarece eu v-am prezentat sumar aproximativ $30%$ din functii si $30%$ din optiunile lui optime de functionare! Insist sa verificati sistematic si metodic optiunile; Nu o sa regretati! De asemenea, poate lucra cu $FPC (Free Pascal Compiler)$ , insa va recomand $IDE$-ul din $Free Pascal$. Este o opera de arta pentru pascalisti!\r\n',2044,'public',3679,NULL),('newsletter/preoni-2007-runda-4','preONI 2007, Runda #4','2007-03-23 13:25:29','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nTe invitam la runda #4 a concursului preONI, ultima runda\r\nde calificare la finala preONI.\r\n\npreONI este concursul cu premii care te pregateste pentru\r\nOlimpiada Nationala de Informatica.\r\n\nRunda #4 va avea loc ...\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Duminica, 25 martie 2007, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPagina rundei: \'preoni-2007/runda-4\':preoni-2007/runda-4\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la aceasta runda iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te va aduce mai aproape de varful clasamentul.\r\n==NewsletterRating(username=\"%username%\")==\r\nRating-ul este un indicator al performantei tale in conditii de\r\nconcurs. Afla mai multe: \'documentatie/rating\':documentatie/rating\r\n\nIti tinem pumnii!\r\n\nh2.  Despre preONI \n\npreONI, concursul de marca al comunitatii infoarena, este dedicat\r\nelevilor de liceu ce se pregatesc pentru ONI (Olimpiada Nationala\r\nde Informatica).\r\n\npreONI se imparte in 3 grupe: clasa a IX-a si gimnaziu, clasa\r\na X-a si clasele XI-XII. Se organizeaza 4 runde online de calificare.\r\nIn urma acestora, cei mai buni de la fiecare grupa sunt invitati la\r\no runda finala.\r\n\nIn cadrul unei runde, vei avea de rezolvat 3 probleme in 4h.\r\nCastigatorii rundei finale sunt premiati cu bani si/sau obiecte.\r\n\nPe pagina concursului ( \'preoni-2007\':preoni-2007 ) vei gasi\r\ninformatii despre cum participi, cine propune probleme, premii si\r\nsponsori, regulamentul concursului samd.\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('preoni-2005/runda-1/solutii','preONI 2005 runda #1 - solutii','2005-01-24 00:00:00','2010-01-20 14:38:02','h1. preONI 2005 runda #1 - solutii\r\n\r\n(Categoria _Competitii_, autor(i) _Mircea Pasoi_)\r\n\r\nArticolul contine ideile de rezolvare ale problemelor propuse la prima runda a concursului preONI ce s-a desfasurat pe data de 23 ianuarie 2005, cat si comentarii legate de concurs.\r\n\r\nCum s-a si promis, setul de probleme de data aceasta n-a fost dur, problemele fiind mult mai accesibile, fapt care se vede imediat din punctaje. Spre deosebire de concursurile anterioare in care problemele erau toate de acelasi nivel, de data aceasta a existat o problema usoara, una medie si una grea la fiecare grupa (gen TopCoder).\r\n\r\nToti care am participat la compunerea problemelor suntem de parere ca probleme au fost de nivelul ONI, chiar un pic mai usoare. De asemenea, testele au fost create astfel incat sa se poata obtine 190-200p in mod usor de un concurent cu cunostiinte medii care implementeaza solutii corecte dar care nu se incadreaza complet in limita de timp. Din pacate rezultatele sunt un pic sub nivelul asteptarilor, dar speram ca se vor inbunatati in rundele urmatoare! ;)\r\n\r\nh2. Clasele 9-10\r\n\r\nPrimele $5$ locuri din clasamentul de la $9-10$ arata astfel:\r\n\r\n==Rankings(rounds=\"preoni51a\" display_entries=\"6\" pager_style=\"none\")==\r\n\r\nEste de mentionat faptul ca sub pseudonimul ==user(user=\"macarie\" type=\"tiny\")== se \"ascunde\" echipa care va reprezenta Romania la finala ACM, formata din Mugurel Andreica, Marius Andrei si Ghinea Dan. Ei au concurat pe un singur calculator si au rezolvat toate cele $6$ probleme propuse pentu a simula un concurs ACM. De asemenea, un lucru remarcabil, concurentul clasat pe locul {$2$}, Tataroiu Bogdan este abia clasa a {$7$}-a! Probabil ca va reprezenta Romania la multe IOI-uri :)\r\n\r\nh3. Text\r\n\r\nProblema a fost cea mai usoara din cele $3$ probleme din grupa si rezolvarea nu ar trebui sa ridice mari dificultati nici macar unui elev de a {$9$}-a incepator. Fie $N$ numarul de caractere din fisierul de intrare - voi prezenta o solutie {$O(N)$}. Se parcurge fisierul caracter cu caracter (nu este necesara stocarea datelor de intrare intr-un vector) si se mentin doua variabile care indica pozitia de inceput si sfarsit a ultimului cuvant detectat pana in prezent, daca s-a gasit vreunul. De asemenea se pastreaza si doua variabile pentru suma lungimilor cuvintelor si numarul de cuvinte pentru a calcula rezultatul. Atentie insa ca la sfarsitul parcurgerii fisierului de iesire, daca ultimul caracter citit a fost o litera mare sau mica, sa se actualizeze numarul de cuvinte si suma lungimilor.\r\n\r\nh3. Trapez\r\n\r\nProblema a fost cea de nivel mediu din cele $3$ si face apel la cunostiinte minime de geometrie. Conditia ca oricare trei puncte nu sunt coliniare simplifica mult rezolvarea. Din definitie, un trapez are cel putin doua laturi paralele deci se poate construi urmatorul algoritm: se iau toate perechile de puncte - acestea determina cate un segment - si sorteaza in functie de unghiul cu axa OX (panta dreptei). Pentru fiecare $k$ segmente cu acelasi unghi se pot forma {$Comb(k,2)$} trapeze. Pentru a evita calculele cu reale (care pot cauza erori de precizie), se tin pantele ca perechi de numere intregi ({$y, x$}), fara a efectua efectiv impartirea {$y/x$}. Pentru compararea a doua astfel de perechi sunt necesare tipuri de date pe $64$ de biti. Algoritmul descris are complexitate {$O(N^2^*lg N)$}. Las ca exercitiu rezolvarea acestei probleme folosind un algoritm $O(N^2^)$ care foloseste \"hashing\":tabele-hash-scurta-prezentare (vezi articolul de pe site). Se puteau obtine $40-50p$ cu un algoritm brut {$O(N^4^)$}.\r\n\r\nh3. Subsir\r\n\r\nAceasta problema, care a fost si cea mai grea, a fost prezenta si la CEOI 2003, dar intr-o forma mai simpla. Acolo se cerea generarea efectiva a tuturor subsirurilor , nu numararea lor, si se garanta ca numarul lor este sub {$1000$}. Orice solutie care ar fi luat $100p$ la problema de la CEOI ar fi obtinut $50p$ la aceasta (primele $5$ teste fiind de fapt preluate de la CEOI 2003). Cum multi probabil au intuit, rezolvarea se bazeaza pe programare dinamica. Voi numi cele doua siruri $A$ si {$B$}, de lungime {$N$}, respectiv $M$ si voi construi initial matricea $C{~i,j~}$ = lungimea celui mai lung subsir comun al sirurilor {$A{~1..i~}$} si {$B{~1..j~}$}. Acest lucru se poate face in $O(N*M)$ si este o aplicatie clasica a programarii dinamice (se gaseste in foarte multe carti explicata ideea). In continuare voi numara sirurile folosind un algoritm $O(N*M*Sigma)$ unde $Sigma$ este numarul litere din care pot fi formate sirurile, adica {$26$}. Se va calcula o matrice $Nr{~i,j~}$ = cate subsiruri comune de lungime maxima existe pentru sirurile $A{~1..i~}$ si\r\n$B{~1..j~}$ (evident modulo {$666013$}). Se calculeaza $Nr{~i,j~}$ doar atunci cand {$A{~i~} = B{~j~}$}, astfel: pentru fiecare caracter $c$ intre \'{$a$}\' si \'{$z$}\' se cauta ultima sa aparitie in sirul $A{~1..i-1~}$ (fie aceasta pozitia {$ii$}) si ultima sa aparitie in sirul $B{~1..j-1~}$ (fie aceasta pozitia {$jj$}). Acest lucru se poate face in $O(1)$ daca se preproceseaza inainte aceste informatii in {$O((N+M)*Sigma)$}. Daca $C{~i,j~} = C{~ii,jj~}+1$ se va aduna $Nr{~ii,jj~}$ la $Nr{~i,j~}$ - aceasta conditie ne garanteaza ca subsirurile adaugate au lungime maxima, iar faptul ca $ii$ si $jj$ reprezinta ultima aparitie a caracterului garanteaza ca nu se vor numara subsiruri identice. Pentru a gasi rezultatul final se aduna toate valorile $Nr{~i,j~}$ calculate, cu urmatoarea exceptie: daca exista pozitiile $x$ si $y$ astfel incat {$A{~x~} = A{~i~} = B{~y~} = B{~j~}$}, se aduna $Nr{~i,j~}$ doar daca $x < i$ si $y < j$ (pentru a asigura ca nu se numara subsiruri identice de mai multe ori).\r\n\r\nh2. Clasele 11-12\r\n\r\nPrimele 5 locuri din clasamentul de la 11-12 arata astfel:\r\n\r\n==Rankings(rounds=\"preoni51b\" display_entries=\"6\" pager_style=\"none\")==\r\n\r\nh3. Iepuri\r\n\r\nProblema a fost cea mai usoara din cel $3$ si necesita cunostiine elementare de matematica de clasa a 11-a. Daca se noteaza cu $I{~n~}$ cati iepuri sunt in ziua $n$ se deduc urmatoarele relatii din enunt:\r\n\r\n* $I{~0~}=X, I{~1~}=Y, I{~2~}=Z$\r\n* $I{~n~}=A*I{~n-1~} + B*I{~n-2~} + C*I{~n-3~}$ pt 3 &le; n\r\n\r\nRezultatul cerut este $I{~N~}$ modulo $666013$ pentru fiecare test.\r\nO prima rezolvare, si cea mai simpla, este implementarea directa a relatiei de recurenta si conduce la o complexitate $O(N)$ pe set de date. Aceasta abordare ar fi obtinut {$50p$}.In continuare voi descrie o rezolvare $O(lg N)$ care foloseste matrici. Se construieste matricea:\r\n\r\np(pre). \r\n    [0 1 0]\r\nM = [0 0 1]\r\n    [C B A]\r\n\r\ncare sta la baza relatiei:\r\n\r\np(pre). \r\n    [I{~0~}]   [I{~1~}]\r\nM * [I{~1~}] = [I{~2~}]\r\n    [I{~2~}]   [I{~3~}]\r\n\r\nDin asta se deduce:\r\n\r\np(pre). \r\n&nbsp;&nbsp;&nbsp;&nbsp; [I{~0~}]   [I{~N&nbsp;&nbsp;~}]\r\nM^N^ * [I{~1~}] = [I{~N+1~}]\r\n&nbsp;&nbsp;&nbsp;&nbsp; [I{~2~}]   [I{~N+2~}]\r\n\r\n\r\nastfel problema se reduce la a calcula $M^N^$ in {$O(lg N)$}. Algoritmul de ridicare la putere in timp logaritmic este clasic si nu-l mai mentionez aici.\r\n\r\nh3. Barbar\r\n\r\nProblema este de nivel mediu si necesita cunostiinte elementare de teoria grafurilor. Se considera matricea initiala un graf cu $R*C$ noduri, mai putin zidurile. Se face o parcurgere BF pentru a determina pentru fiecare casuta din matrice distanta pana la cel mai apropiat dragon. Astfel, se incepe BF-ul cu toate nodurile care corespund dragonilor inserate in coada (deci nu va fi doar un nod in coada la inceput). Complexitatea acestui pas este {$O(R*C)$}. Se observa daca exista un traseu valid care trece prin casute situate la distanta $&ge;x$ fata de cel mai apropiat dragon, atunci exista in mod evident un traseu valid care trece prin casute situate la distanta $&ge;x-1$ fata de cel mai apropiat dragon. Aceasta observatie duce la folosirea cautarii binare a rezultatului (vezi articolul de pe site pentru alte aplicatii). Pentru a verifica daca exista un traseu valid care trece doar prin casute situate la o anumita distanta fata de cel mai apropiat dragon se foloseste tot o parcurgere BF, astfel rezolvarea fiind\r\n{$O(R*C*lg(R*C))$}.\r\n\r\nh3. ADN\r\n\r\nLa primul pas se elimina toate cuvintele incluse in alte cuvinte mai mari (pentru a cauta daca exista un cuvant in alt cuvant se foloseste algoritmul KMP pentru incadrarea in timp - vezi articolul de pe site). Apoi, se construieste un graf cu noduri cuvintele si muchii intre oricare doua cuvinte. Costul unei muchii ({$i, j$}) va fi cel mai lung sufix al cuvantului $i$ care este prefix al cuvantului $j$ (informatie care se poate determina cu KMP), adica cate litere sunt \"inutile\" daca lipim cuvantul $i$ cu cuvantul {$j$}. Aceasta prima etapa are complexitate {$O(N^2^*L)$}, unde $L$ e lungimea maxima a unui cuvant. Deoarece trebuie sa existe fiecar cuvant in sirul rezultat, iar sirul sa fie de lungime minima problema se reduce la determinarea unui lant hamiltonian de cost maxim, problema care este binecunoscuta ca fiind {$NP$}. Un algoritm care incearca toate cele $n!$ permutari are complexitate $O(n!)$ si va obtine {$50p$}. Pentru punctaj maxim vom folosi programare dinamica astfel: fie {$A[i][(n{~1~}, n{~2~}.. n{~k~})]$} = costul unui lant hamiltonian de cost maxim care incepe din nodul $i$ si trece prin nodurile {$n{~1~}, n{~2~} .. n{~k~}$}. Relatia de recurenta este: {$A[i][n{~1~},n{~2~}..n{~k~})]$ = {$max cost(i, n{~j~}) + A[n{~j~}][(n{~1~},n{~2~},n{~j-1~},n{~j+1~}..n{~k~})]$} pentru fiecare {$j$}. Dinamica se initializeaza cu $A[i][(i)] = 0$ pentru fiecare {$i$}. Reprezentarea multimilor de noduri se face folosind un numar binar cu $N$ biti, astfel complexitatea acestei etape fiind {$O(N^2^*2^N^)$}. Mentionez ca aceasta rezolvare nu produce solutia minim lexicografic, fapt observat in timpul concursului si astfel s-a reevaluat problema dandu-se puncte pentru orice solutie valida, nu neaparat minim lexicografic. Rezolvarea problemei cu cerinta de minim lexicografic este posibila, dar pentru realizarea ei trebuie folosite structuri de date avansate ca Suffix Arrays sau Suffix Trees si nivelul de dificultate ar fi mult mai mare. Alta observarie este ca matricea cost ar putea fi calculata mai repede daca am folosi structurile mentionate mai devreme. Folosind prima structura am avea complexitatea $O( N*L log (N*L))$ iar a folosind a doua structura am avea complexitatea $O(N*L)$ . De asemenea mentionam posibilitatea folositii algoritmului randomizat de potrivire a sirurilor de caractere numit Rabin Karp pentru calcularea matricii cost ceea ce ar fi dus la o solutie mai scurta si la un cod mai clar. Ne cerem scuze pentru eventualele neplaceri cauzate de aceasta situatie.\r\n\r\nBafta la urmatorul concurs! (undeva prin februarie...)\r\n',9258,'public',NULL,NULL),('preoni-2007/runda-4/9','preONI 2007, Runda 4, Clasa a 9-a si gimnaziu','2007-03-07 12:02:53','2007-03-25 06:21:45','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda4_9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-4\r\n*(active) \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-4/10\r\n* \'Clasele 11-12\':preoni-2007/runda-4/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-4/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda4_9\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\n==include(page=\"preoni-2007/prelungiri\")==\r\n\r\nRunda se desfasoara *Duminica 25 martie*, la ora {*09^00^*} si va dura *{color:red}4h 15min*.\r\nParticipantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2007/clasament/runda-4/9.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda4_9\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda4_9',NULL,NULL),('preoni-2007/runda-4/11-12','preONI 2007, Runda 4, Clasele 11-12','2007-03-07 12:12:40','2007-03-25 06:22:21','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda4_1112\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2007/runda-4\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-4/10\r\n*(active) \'Clasele 11-12\':preoni-2007/runda-4/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-4/9\r\n\r\n==roundregister(round_id=\"preoni2007_runda4_1112\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\n==include(page=\"preoni-2007/prelungiri\")==\r\n\r\nRunda se desfasoara *Duminica 25 martie*, la ora {*09^00^*} si va dura *{color:red}4h 15min*.\r\nParticipantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2007/clasament/runda-4/11-12.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda4_1112\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda4_1112',NULL,NULL),('rotatie-lexicografic-minima','Rotatie lexicografic minima','2007-03-30 07:38:31','2009-02-20 01:12:57','h1. Rotatie lexicografic minima\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"m_dersidan\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Mircea Pasoi_)\r\n\r\nAcest articol reprezinta un studiu de caz al unei probleme care poate fi considerata \"clasica\", fiind studiata inclusiv de cunoscutul profesor Edsger Wybe Dijkstra. Deoarece problema a aparut recent la diverse concursuri de informatica, prezinta interes pentru cei care se pregatesc pentru participarea la acestea.\r\n\r\nh2. Enunt\r\n\r\nIn continuare vom prezenta doua formulari ale acestei probleme care au aparut recent la concursuri:\r\n\r\nCateodata programatorii au metode din cele mai diverse pentru a-si ascunde parolele. De exemplu, sa vedem cum Billy \"Hacker\" Geits isi ascunde propriile parole. Billy isi alege un sir de caractere de lungime $L < 100.000$ format din litere mici ale alfabetului latin. Pentru acest sir de caractere Billy face toate cele $L-1$ deplasari circulare la stanga cu o pozitie si le pune unele sub altele. Dintre aceste $L-1$ siruri astfel obtinute, inaintea carora se trece sirul initial, se alege cel care este primul in ordine lexicografica, parola constituind-o un prefix al acestuia.\r\nScrieti un program care pentru un sir $S$ dat determina pozitia celei \"mai mici\" (primei) deplasari in ordine lexicografica. Daca cel mai mic sir de caractere apare de mai multe ori, se se cere cea mai mica pozitie pe care acesta incepe.\r\n(ACM $2003-2004$, regionala Europei de sud-est)\r\n\r\nIntr-un seif se afla niste documente pe care trebuie sa le extrageti. Problema este ca seiful este prevazut cu un terminal care necesita introducerea unei parole pentru a putea deschide seiful. La accesarea seifului, pe ecranul terminalului este afisat un cuvant cheie format din litere mici ale alfabetului englezesc. Parola este data de cea mai mica rotatie la stanga (in ordine lexicografica) a cuvantului cheie.\r\nFisierul de intrare $_password.in_$ contine pe prima linie un sir de caractere format din litere mici ale alfabetului englezesc. Lungimea sirului din fisierul de intrare este un numar intreg cuprins intre $1$ si $100 000$.\r\nFisierul de iesire $_password.out_$ trebuie sa contina un singur numar care reprezinta numarul de deplasari circulare la stanga ale sirului din fisierul de intrare necesare pentru a obtine parola de acces ceruta. Daca exista mai multe solutii va fi aleasa cea care necesita un numar minim de deplasari circulare la stanga.\r\n(Bursele Agora $2003-2004$, Runda $44$)\r\n\r\nh2. Solutia naiva\r\n\r\nO solutie triviala de complexitate $O(N^2^)$ poate fi obtinuta parcurgand succesiv rotatiile si tinand cont de faptul ca compararea a doua siruri are complexitatea $O(N)$ in cel mai defavorabil caz. Prezentam in continuare pseudocodul:\r\n\r\n== code(c) |\r\n\r\nmin <- 0; R0 <- S;\r\n\r\npentru i = 1, N-1 executa\r\n    construieste Ri in functie de Ri-1\r\n    daca Rmin > Ri atunci min <-i;\r\nsfarsit pentru\r\nscrie min\r\n==\r\n\r\nh2. Solutia $O(N*log N)$\r\n\r\nPrecizam intai ca atat o solutie $O(N*lg^2^ N)$ cat si una $O(N*lg N)$ pot fi obtinute folosind structura de date \"siruri de sufixe\" $(1)$. Din pacate aceste solutii nu sunt foarte usor de implementat, iar constanta din notatia $O$ este destul de mare cat sa merite cautarea unei solutii alternative. Vom prezenta in continuare o solutie de complexitate $O(N*lg N)$, mult mai usor de implementat odata ce este inteleasa.\r\n\r\nPrimul pas pentru obtinerea acestei solutii este folosirea unei strategii de tip \"turneu\", si anume la fiecare iteratie se pastreaza o lista cu rotatiile care ar putea fi minime. Initial lista va avea toate cele $N$ rotatii, iar de fiecare data se iau rotatiile doua cate doua din lista si se elimina cea mai mare dintre cele doua din punct de vedere lexicografic. Procesul se reia pana cand se obtine o lista cu un singur element, reprezentand rotatia minima. Cum la fiecare pas numarul de elemente din lista se injumateste, este usor de vazut ca procesul nu se va repeta de mai mult de $[log ~2~ N]$ ori. Desi la prima vedere acest algoritm are timpul de rulare $O(N^2^*lg N)$, vom arata in continuare ca sunt suficiente $O(N)$ comparatii de caractere per total la fiecare repetare:\r\nFie $R ~i~$ si $R ~j~$ doua rotatii (presupunem fara a restrange generalitatea ca $i < j$) aflate pe pozitii consecutive in lista, care urmeaza sa fie comparate, una din fiind aleasa pentru eliminare. Vom demonstra in continuare ca este suficienta compararea acestor rotatii folosindu-ne doar de primele $j - i$ caractere.\r\n\r\ntable{border:1px solid black}.\r\n|_=. $i$|_=. $*...*$|_=. $*j-1*$|=. $*j*$|=. $*...*$|=. $*2j-i-1*$|={background:gray}. $*2j-i*$|={background:gray}. $*...*$|={background:gray}. $*0*$|={background:gray}. $*...*$|={background:gray}. $*i-1*$|\r\n\r\n$*A = i...j-1*$\r\n$*B = j...2j-i-1*$\r\n$*C = 2j-i...i-1*$ (indicii sunt considerati $modulo N$ )\r\n\r\nFie sirul $R ~i~$ impartit in trei bucati $A$, $B$, $C$, ca in figura de mai sus. Conform figurii, $R ~i~ = ABC$, iar $R ~j~ = BCA$, bucatile $A$ si $B$ avand fiecare $j-i$ caractere. Comparand doar primele $j-i$ caractere, vom compara bucatile $A$ si $B$, astfel:\r\n\r\n* $A < B -> R ~i~ < R ~j~ -> se elimina R ~j~$\r\n* $A > B -> R ~i~ > R ~j~ -> se elimina R ~i~$\r\n* $A = B -> se elimina R ~j~ ( se presupune ca R ~i~ < R ~j~ )$\r\n\r\nEste evident ca in primele doua cazuri decizia de eliminare este corecta. Daca $A = B$ , iar decizia luata de eliminare a fost gresita, anume $R ~i~ > R ~j~$, cum $R ~i~ = ABC = AAC$ si $R ~j~ = BCA = ACA$, inseamna ca $A > C$ (daca $A$ ar fi fost egal cu $C$ atunci $R ~i~ = R ~j~$, si nu ar mai fi contat ce element se elimina), deci elementul pastrat va fi oricum eliminat de rotatia $R ~2j-i~ = CAA$ sau de o alta rotatie care s-a dovedit a fi mai mica decat $CAA$ la pasii anteriori. La a i-a parcurgere a listei, distanta intre doua rotatii aflate pe pozitii consecutive in lista este maxim $2^i-1^$, iar in lista sunt cel mult $[ n / 2^i-1^ ]$ elemente, astfel facandu-se $O(N)$ comparatii. In acest mod obtinem un algoritm corect de complexitate $O(N * log N)$.\r\n\r\n==code(c) |\r\nL <- {0,1,2,...,N-1};\r\ncat timp |L|>1 executa\r\n    pentru k <- 1, |L|-1, +2 executa\r\n    i <- L[k]; j <- L[k+1];\r\n    A <- S[i..j-1]; B <- S[j..2j-i-1];\r\n    daca A <= B atunci elimina L[k+1];\r\n        altfel elimina L[k];\r\n    sfarsit pentru\r\nsfarsit cat timp\r\nscrie L[1]\r\n==\r\n\r\nSpre exemplu, pentru sirul $S = (\"m\", \"i\", \"s\", \"s\", \"i\", \"s\", \"s\", \"i\", \"p\", \"p\", \"i\")$ lista va contine initial elementele ${0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}$\r\nLa primul pas se efectueaza (caracterele ingrosate sunt cele ce se vor compara):\r\n$R0 = mississippi > R1 = ississippim$\r\n$R2 = ssissippimi = R3 = sissippimis$\r\n$R4 = issippimiss < R5 = ssippimissi$\r\n$R6 = sippimissis > R7 = ippimississ$\r\n$R8 = ppimississi = R9 = pimississip$\r\nLista va fi acum ${1, 2, 4, 7, 8, 10}$\r\nPasii urmatori sunt:\r\n$R1 = ississippim < R2 = ssissippimi$\r\n$R4 = issippimiss > R7 = ippimississ$\r\n$R8 = ppimississi > R10 = imississipp$\r\n$L = {1, 7, 10}$\r\n$R1 = ississippim > R7 = ippimississ$\r\n$L = {7, 10}$\r\n$R7 = ippimississ > R10 = imississipp$\r\n$L = {10}$\r\n\r\np=. !rotatie-lexicografic-minima?image1.jpg!\r\n\r\nh2. Solutia $O(N)$\r\n\r\nVom incerca acum sa obtinem un algoritm de complexitate liniara folosind alte idei de rezolvare. Algoritmul pe care il vom propune in continuare functioneaza ca si algoritmul trivial mentionat mai sus, anume parcurgand rotatiile succesiv. La fiecare pas se vor pastra trei variabile $min, p, l$ cu semnificatia ca rotatiile $R ~0~, R ~1~, ... R ~p-1~$ au fost parcurse pana acum, iar $R ~min~$ este o rotatie dintre acestea care ar putea fi cea lexicografic minima (toate celelalte din cele parcurse sigur nu pot fi solutia finala). De asemenea, variabila $l$ va semnifica ca primele $l$ caractere din $R ~min~$ sunt egale cu primele $l$ caractere din $R ~p~$, $R ~p~$ fiind urmatoarea rotatie ce va fi procesata. Cunoscand aceste informatii, la fiecare pas se va compara al $l+1-lea$ caracter din $R ~min~$ $(S[min+l])$ cu al $l+1-lea$ din $R ~p~ (S[(p+l) mod N])$, iar in functie de rezultat se va lua o decizie:\r\n\r\n* $*S[min+l] = S[(p+l) mod N]* ->$ se va incrementa variabila $l$ cu o unitate deoarece inca o pereche de caractere se potrivesc\r\n* $*S[min+l] < S[(p+l) mod N]* ->$ putem trage imediat concluzia ca $R ~min~ < R ~p~$ , iar mai mult, din faptul ca primele $l$ caractere se potrivesc putem spune ca $R ~min+i~ < R ~p+i~$ pentru $0 <= i <= l$; cum $R ~min~$ era rotatia \"candidata\" la solutia finala dintre $R ~0~, R ~1~, ... R ~p-1~$ si este mai mica ca $R ~p~$, iar pentru orice $R ~p+i~ (1 <= i <= l)$ exista $R ~min+i~ < R ~p+i~$, despre care se stie ca nu poate fi solutia finala, $R ~min~$ va repezenta in continuare rotatia candidata la solutie dintre $R ~0~, R ~1~, ... R ~p-1~, R ~p~, R ~p+1~, ... R ~p+l~$. Asadar $p$ va deveni $p+l+1$, iar $l$ va deveni $0$ (deoarece nu se cunosc inca informatii despre $R ~min~$ si $R ~p+l+1~$)\r\n* $*S[min+l] > S[(p+l) mod N]* ->$ asemanator cu cazul anterior putem concluziona ca $R ~min+i~ > R ~p+i~$ pentru $0 &le; i &le; l$; asadar putem face doua observatii:\r\n$1) R ~min+i~ (0 <= i <= l)$ nu poate candida la solutie, si cum se stia dinainte ca nici $R ~0~, R ~1~, ... R ~min-1~$ nu pot, primul candidat posibil este $R ~min+l+1~$; \r\n$2) Cum R ~min~$ era candidatul pana in prezent, iar $R ~p~ < R ~min~$, din $R ~0~, R ~1~, ... R ~p~$ singurul candidat posibil este $R ~p~$.\r\nVariabila $min$ va deveni $max(min+l+1, p)$, $p$ va deveni $max(min+l+1, p)+1$, iar $l$ va fi egal cu $0$.\r\n\r\nUn aspect al acestui algoritm care ar putea parea \"misterios\" este motivul pentru care complexitatea este liniara. Vom considera $T = min+p+l$ si putem observa ca dupa fiecare comparatie $T$ creste cu cel putin o unitate. Cum niciuna din cele trei variabile nu poate depasi valoarea $N$, numarul de iteratii este proportional cu $N$ (se poate arata ca nu va depasi $2*N-3$), de unde si complexitatea $O(N)$.\r\n\r\n==code(c) |\r\nmin <- 0; p <- 1; l <- 1;\r\ncat timp (p < N) AND (min+l+1 < N) executa\r\n    daca S[min+l] = S[(p+l) mod N] atunci l <- l+1;\r\n    daca S[min+l] < S[(p+l) mod N] atunci p <- p+l+1; l <- 0;\r\n    daca S[min+l] > S[(p+l) mod N] atunci min <- max(min+l+1, p); p <- min+1; l <- 0;\r\nsfarsit cat timp\r\nscrie min\r\n==\r\n\r\nVom simula algoritmul pentru sirul $S = (\"m\", \"i\", \"s\", \"s\", \"i\", \"s\", \"s\", \"i\", \"p\", \"p\", \"i\").$\r\n\r\ntable{example}.\r\n|_=. $pas$|_=. $min$|_=. $p$|_=. $l$|_=. $S[min+l]$|_=. $S[p+l]$|_=. $caz$|\r\n| $1$ | $0$ | $1$ | $0$ | $m$ | $i$ | $S[min+l] > S[p+l]$ |\r\n| $2$ | $1$ | $2$ | $0$ | $i$ | $s$ | $S[min+l] < S[p+l]$ |\r\n| $3$ | $1$ | $3$ | $0$ | $i$ | $s$ | $S[min+l] < S[p+l]$ |\r\n| $4$ | $1$ | $4$ | $0$ | $i$ | $i$ | $S[min+l] = S[p+l]$ |\r\n| $5$ | $1$ | $4$ | $1$ | $s$ | $s$ | $S[min+l] = S[p+l]$ |\r\n| $6$ | $1$ | $4$ | $2$ | $s$ | $s$ | $S[min+l] = S[p+l]$ |\r\n| $7$ | $1$ | $4$ | $3$ | $i$ | $i$ | $S[min+l] = S[p+l]$ |\r\n| $8$ | $1$ | $4$ | $4$ | $s$ | $p$ | $S[min+l] > S[p+l]$ |\r\n| $9$ | $6$ | $7$ | $0$ | $s$ | $i$ | $S[min+l] > S[p+l]$ |\r\n| $10$ | $7$ | $8$ | $0$ | $i$ | $p$ | $S[min+l] < S[p+l]$ |\r\n| $11$ | $7$ | $9$ | $0$ | $i$ | $p$ | $S[min+l] < S[p+l]$ |\r\n| $12$ | $7$ | $10$ | $0$ | $i$ | $i$ | $S[min+l] = S[p+l]$ |\r\n| $13$ | $7$ | $10$ | $1$ | $p$ | $m$ | $S[min+l] > S[p+l]$ |\r\n| $14$ | $10$ | 0 | 0 | 0 | 0 | 0 |\r\n\r\nsi, in final, $min = 10$\r\n\r\nh2. Aplicatii\r\n\r\n$Problema 1 (\"acm.sgu.ru\":http://acm.sgu.ru, \"Infinite fraction\":http://acm.sgu.ru/problem.php?contest=0&problem=232)$\r\n\r\nSe dau doua numere naturale $N<=150000$ si $K<=10^9^$ si un vector de cifre $D[0...N-1]$. Se va considera un sir $A$ de numere reale cu partea intreaga $0$, iar partea fractionara a elementului $A[i]$ va fi sirul infinit format din $D[(i+0*K) mod N], D[(i+1*K) mod N], D[(i+2*K) mod N]$ etc. Spre exemplu, pentru $N = 3, K = 2 si D = \'194\'$ se obtine:\r\n$A[ 1 ] = 0.1491491491...$\r\n$A[ 2 ] = 0.9149149149...$\r\n$A[ 3 ] = 0.4914914914...$\r\nSa se gaseasca cel mai mare element ca valoare din sirul $A$, si sa se tipareasca primele $N$ zecimale ale sale.\r\n\r\n$Problema 2 (Selectia lotului national, 2004)$\r\n\r\nSe considera un sir $c ~1~ c ~2~ ...c ~n~$ format din $n &le; 30.000$ caractere din multimea ${A, B}$. Concatenam sirul cu el insusi si obtinem un sir de lungime $2n$. Pentru un indice $k (1&le;k&le;2n)$ consideram subsecventele de lungime cel mult $n$, care se termina pe pozitia $k$, iar dintre acestea fie $s(k)$ subsecventa cea mai mica in ordine lexicografica. Determinati indicele $k$ pentru care $s(k)$ are lungimea cea mai mare.\r\n\r\n$Problema 3$\r\n\r\nSe dau doua poligoane in plan fiecare avand $n &le; 1 000 000$ varfuri. Poligoanele sunt date prin coordonatele varfurilor lor in ordine trigonometrica. Sa se verifice daca cele doua poligoane sunt asemenea.\r\n\r\n$Problema 4$\r\n\r\nProblema \"password\":problema/password de pe \"infoarena\":http://infoarena.ro.\r\n\r\nh2. Bibliografie\r\n\r\n# \"Siruri de sufixe\" (Cosmin Negruseri, Adrian Vladu), GInfo 15/7, noiembrie 2005\r\n# \"Solutii rundele 41-50\" (Cosmin Negruseri), GInfo 14/5\r\n# \"E.W.Dijkstra Archive: Home page\":http://www.cs.utexas.edu/users/EWD/',2044,'public',3696,NULL),('blog/arenainfo','infoarena are un nou nume: arenainfo','2007-04-01 00:00:00','2007-04-01 00:00:00','Dupa lungi dezbateri, echipa infoarena a decis sa schimbe denumirea site-ului _infoarena_ in _arenainfo_.\r\n\r\nSuntem nevoiti sa schimbam denumirea site-ului nostru din cauza unui proces intentat de catre grupul croat _Infoarena_, detinator al  marcilor _Infoarena_, _Infoarena Business Journal_ si _Infoarena Business TV_. Grupul croat considera ca site-ul nostru aduce prejudicii materiale semnificative imaginii companiei. De altfel, ca parte a deciziei tribunalului Bucuresti, Asociatia infoarena va plati daune in valoare de $1,407,000 pe parcursul a 4 ani.\r\n\r\nAm inceput procesul de rebranding cu noua sigla _arenainfo_ (coiful cu ochelari privind spre trecut).\r\nIn curand vom transfera activitatile pe domeniul arenainfo.ro.\r\n\r\n!stiri/arenainfo?arenainfo2.png!\r\n\r\nEchipa _arenainfo_\r\n',13,'protected',NULL,NULL),('preoni-2007/runda-4/solutii','Solutii preONI 2007, Runda 4','2007-03-25 08:10:31','2008-01-06 16:03:15','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Solutii Runda 4\r\n\r\nh2. \'Next\':problema/next\r\n\r\nh3. (problema usoara, clasa a 9-a)\r\n\r\nFolosind operatii pe numere mari se calculeaza restul lui $N$ la numarul $D$. Fie $R$ acest rest, se va aduna la numarul $N$ valoarea $(D-R) mod D$ ({$a mod b$} reprezinta restul numarului $a$ la impartirea cu $b$). Numarul astfel obtinut va reprezenta primul numar mai mare sau egal decat $N$ divizibil cu $D$. O prezentare detaliata a modului in care se pot implementa operatiile cu numere mari necesare se gaseste \'aici\':http://infoarena.ro/Multe-smenuri-de-programare-in-CC-si-nu-numai. Complexitatea rezolvarii este $O(lg N)$.\r\n\r\nh2. \'Shop\':problema/shop\r\n\r\nh3. (problema medie, clasa a 9-a)\r\n\r\nLa prima vedere, problema este asemanatoare cu problema \'rucsacului\':http://en.wikipedia.org/wiki/Knapsack_problem, deci se poate aborda folosind metoda programarii dinamice. Avand in vedere limita mare pentru numarul $L$ o astfel de abordare nu ar fi obtinut punctaj maxim.   Avand in vedere ca toate monezile sunt puteri ale numarului $C$, exista o rezolvare greedy: se determina cel mai mare tip de moneda $C^A{~i~}^$ disponibil si se foloseste un numar maxim posibil de astfel de monede (minimul dintre $L/C^A{~i~}^$ si $B{~i~}$). Complexitatea unei astfel de solutii este $O(log{~C~} L)$. O solutie care ar fi efectuat scaderi repetate ale cele mai mari monezi ar fi obtinut de asemenea punctaj maxim.\r\n\r\nh2. \'Dezastru\':problema/dezastru\r\n\r\nh3. (problema grea, clasa a 9-a)\r\n\r\nDaca o problema de probabilitati ar fi putut incurca o parte a concurentilor de clasa a 9-a, exemplele date in enunt reprezinta un indiciu destul de clar in legatura cu modalitatea de rezolvare. Din moment ce evenimentele pot aparea in orice ordine, avem $N!$ posibilitati. Ar trebui, deci, sa generam toate permutarile, sa calculam pentru fiecare permutare produsul primelor $K$ valori, si sa facem media aritmetica a rezultatelor obtinute. Problema se reduce succesiv la aranjamente si apoi la combinari, fiind suficient sa consideram toate modurile de a alege $K$ evenimente, indiferent de ordine. Solutiile cu permutari si aranjamente obtin punctaje partiale, in functie de grija acordata implementarii.\r\n\r\nProblema se poate rezolva si folosind programarea dinamica. Se construieste matricea $A{~i,j~}$ cu semnificatia suma tuturor produselor de $j$ factori alesi din primele $i$ numere. Recurenta se poate calcula usor {$A{~i,j~}=A{~i-1,j~}+A{~i-1,j-1~}*P{~i~}$}. Probabilitatea ceruta va fi $A{~n,k~}$ impartita la $C{~n,k~}$ (combinari de $n$ luate cate {$k$}). Complexitate $O(n*k)$.\r\n\r\nh2. \'Bowling\':problema/bowling\r\n\r\nh3. (problema usoara, clasa a 10-a)\r\n\r\nIn primul rand, pentru a intelege solutia acestei probleme si altor probleme asemanatoare se recomanda citirea urmatoarelor documente despre teoria jocurilor:\r\n\r\n* \'Teoria jocurilor: numerele Sprague-Grundy\':http://www.ginfo.ro/revista/14_5/mate.pdf, \'GInfo Mai 2004\':http://www.ginfo.ro, Cosmin Negruseri\r\n* \'Game Theory Text: Impartial Combinatorial Games\':http://www.math.ucla.edu/~tom/Game_Theory/comb.pdf, Thomas Ferguson\r\n\r\nAceasta problema se regaseste in literatura de specialitate si cu titlul de _Kayles_. Rezultatul pentru un joc se poate calcula in functie de $XOR$-ul numerelor _Grundy_ pentru fiecare secventa de popice din sir. Cum $N &le; 50.000$, trebuie calculate valorile Grundy pentru fiecare secventa de $i$ popice cu $i &le; 50.000$. Acestea se pot calcula in complexitate patratica si se pot pune in sursa ca un sir de constante. O alta solutie se foloseste de observatia ca incepand cu $i = 72$ sirul de valori se repeta cu perioada $12$. Pentru fiecare test din fisier, complexitatea rezolvarii este $O(N)$.\r\n\r\nh2. \'Regiuni\':problema/regiuni\r\n\r\nh3. (problema medie, clasa a 10-a, problema usoara, clasele 11-12)\r\n\r\nAceasta problema a aparut din cauza faptului ca autorul a inteles gresit problema Druizi de la concursul .campion. Dupa ce am discutat problema cu mai multe persoane am observat ca majoritatea pornesc de la problema mai simpla de a vedea daca doua puncte sunt sau nu in acelasi grup. Ideea mea initiala este putin diferita: rezolvam problema adaugand pas cu pas cate o dreapta si mentinand informatia despre grupuri. Cand adaugam o dreapta iteram peste toate grupurile. Un grup va fi impartit in alte doua: punctele din stanga dreptei si punctele din dreapta. E posibil ca unul din aceste doua grupuri sa fie vid si atunci nu il mai retinem. Un grup il impartim in doua in $O(a)$ operatii unde a este numarul de elemente din grup. Toate grupurile vor avea in total $a1 + a2 + ... + ai + ... = M$ elemente, deci pentru a actualiza grupurile adaugand o dreapta facem $O(M)$ pasi. Astfel solutia are complexitatea finala $O(N * M)$, si este foarte usor de implementat.\r\n\r\nAlte solutii ar fi determinarea pentru fiecare punct a unui vector ce ne spune pentru fiecare dreapta in ce parte e situat punctul. Daca doi astfel de vectori asociati la doua puncte sunt egali, atunci cele doua puncte sunt situate in aceiasi regiune. Pentru determinarea egalitatii vectorilor s-ar fi putut folosi o sortare naiva si astfel am fi avut o solutie de complexitate $O(MN log M)$ sau am fi putut folosi radix sort pentru a o aduce la $O(MN)$. Aceste doua solutii folosesc $O(MN)$ memorie. Alta solutie ar fi sa obtinem un cod hash pentru fiecare vector, aceasta solutie are complexitatea $O(MN)$ ca timp si $O(M + N)$. memorie. Pentru a face probabilitatea de coliziune cat mai mica putem folosi cate doua coduri diferite pentru fiecare vector. Alta observatie ar fi ca vectorii sunt binari si pastrand informatia pe biti folosim mai putina memorie si avem mult mai putine operatii la comparare daca vrem sa folosim solutia in $O(MN log M)$.\r\n\r\nh2. \'Elimin 2\':problema/elimin2\r\n\r\nh3. (problema grea, clasa a 10-a)\r\n\r\nPentru a afla numarul maxim palindrom care este subsir al numarului $N$ vom utiliza metoda programarii dinamice. Fie {$L{~i,j~}$} lungimea maxima a unui numar palindrom care se gaseste intre pozitiile $i$ si $j$ din numarul {$N$}. In momentul in care construim tabloul $L$ consideram ca un numar poate incepe si cu cifra {$0$}. Initial, {$L{~i,i~}$} = 1, pentru orice $i$ de la $1$ la numarul de cifre ale lui {$N$}. Vom calcula elementele tabloului $L$ crescator in functie de marimea intervalelor {$(i,j)$}. Daca consideram ca {$LEFT{~c,i~}$} este cea mai mica pozitie {$&ge; i$} in care apare cifra $c$ in numarul $N$ si {$RIGHT{~c,i~}$} cea mai mare pozitie {$&le; i$} in care apare $c$ in numarul $N$, avem urmatoarea relatie de recurenta:\r\n{$L{~i,j~}$} = maxim({$L{~i+1,j~}$}, {$L{~i,j-1~}$}, {$L{~i+1, RIGHT[N[i]][j]-1~} + 2$}, {$L{~LEFT[N[j]][i]+1, j-1~} + 2$}), unde prin {$N{~i~}$} s-a notat a $i$-a cifra a numarului {$N$}. Relatia de recurenta trateaza urmatoarele cazuri: \r\n\r\n* nu folosim cifra a $i$-a in solutia optima\r\n* nu folosim cifra a $j$-a in solutia optima\r\n* folosim cifra a $i$-a ( notata $c$ ) in solutia optima. Pentru ca numarul intre $i$ si $j$ sa fie palindrom, este suficient sa aflam ultima pozitie $p$ inainte de $j$ a cifrei c, solutia optima intre $i$ si $j$ obtinandu-se din solutia optima intre $i+1$ si $p-1$ la care adaugam 2 cifre ( cele din capete ).\r\n* folosim cifra a $j$-a ( notata $c$ ) in solutia optima. Se trateaza similar. \r\n\r\nDaca tablourile $LEFT$ si $RIGHT$ sunt construite inainte de a incepe programarea dinamica ( preprocesare ), putem construi tabloul $L$ in complexitate {$O(NR_CIF^2^)$}, unde $NR_CIF$ este numarul de cifre ale lui {$N$}. Dupa ce am construit acest tablou, putem reconstitui solutia optima. Sa presupunem ca solutia optima incepe cu cifra nenula {$c$}. Fie $x$ prima aparitie a cifrei $c$ in numarul $N$, si $y$ ultima aparitie. Vom selecta acea cifra $c$ pentru care valoarea {$L{~x,y~}$} este maxima. Pentru valori egale se alege cifra maxima. Dupa ce am determinat valoarea primei cifre, putem presupune ca dorim sa cautam solutia optima intre pozitiile {$i$} si {$j$} si {$L{~i,j~}$} = {$X$}. Vom pune la capetele solutiei cea mai mare cifra $c$ care indeplineste: {$L{~LEFT[c,i]+1,RIGHT{@[c,j]@}-1~}$} = {$X-2$}.\r\n\r\nDe precizat ca un algoritm de complexitate {$O(NR_CIF^2^)$} si constanta $10$ ar fi obtinut in jur de 50 de puncte.\r\n\r\nh2. \'Distincte\':problema/distincte\r\n\r\nh3. (problema medie, clasele 11-12)\r\n\r\nVom calcula in timp liniar urmatorul vector:\r\n$urm{~i~} = min { j / i < j AND A{~j~} = A{~i~}}$\r\nAstfel, $urm{~i~}$ va fi prima pozitie din dreapta egala ca valoare cu elementul de pe pozitia $i$ (daca nu exista $urm{~i~}$ consideram ca $urm{~i~}$ este egal cu $N+1$). Considerand $N$ puncte in plan cu coordonatele $(i, urm{~i~})$ la care se ataseaza valoarea $A{~i~}$, o intrebare $st &le; dr$ se rezolva facand un query in dreptunghiul $[st..dr] x [dr+1..N]$, adica suma acelor elemente care se afla in interval, iar urmatoarea aparitie la dreapta este in afara intervalului. Acest query ne garanteaza ca se va face doar suma elementelor distincte din intervalul $st..dr$. O rezolvare care imparte vectorul in bucati de $&radic;N$ si rezolva intrebarile in $O(&radic;N)$ ar fi obtinut cel putin $50$ de puncte, desi este probabil sa obtina si punctaj maxim optimizand codul. O rezolvare mai buna din punct de vedere al complexitatii este folosirea arborilor de intervale, tehnica descrisa \'aici\':downloads?action=download&file=arbori_de_intervale.zip si care poate fi folosita si la rezolvarea problemei \'Zoo\':problema/zoo. Din pacate, aceasta solutie este greu de implementat, iar solutia in $O(lg^2^ N)$ probabil ar fi fost prea inceata pentru a obtine punctaj maxim.\r\nRezolvarea problemei se simplifica mult daca se sorteaza intervalele care se dau ca intrebari dupa capatul dreapta, si se proceseaza in aceasta ordine, apoi se afiseaza in ordinea initiala. Parcurgand intervalele descrescator dupa capatul dreapta se poate mentine suma punctelor care au coordonata $y$ in afara capatului dreapta curent, si se pot calcula raspunsurile pentru intervale in timp $O(log N)$ folosind fie un arbore de intervale, fie, si mai simplu, cu un arbore indexat binar.\r\n\r\nh2. \'Laser\':problema/laser\r\n\r\nh3. (problema grea, clasele 11-12)\r\n\r\nVom considera semidreptele ce pleaca din origine si trec printr-un capat al unui segment. Vor exista $2*N$ astfel de semidrepte. Pentru fiecare din cele $2*N$ unghiuri formate consideram bisectoarea sa. Orice alta semidreapta ce pleaca din origine va intersecta aceleasi segmente cu una din cele $2*N$ bisectoare. Deci Gigel nu trebuie sa traga decat in unele din aceste bisectoare. In loc de bisectoare se putea considera orice alta semidreapta strict in interiorul unghiului, dar bisectoarea este mai usor de calculat. Avand maxim $2*N$ bisectoare ne vom incadra in limitarea de $10.000$ de trageri.\r\n\r\nVom forma un sistem cu $N$ ecuatii si $2*N$ necunoscute astfel: pentru un segment $i$ se formeaza o ecuatie de forma\r\n\r\n* $B{~i~} = X{~1~} * A{~i,1~} + X{~2~} * A{~i,2~} + ... + X{~2*N~} * A{~i,2*N~}$\r\n** $B{~i~}$ este starea initiala a neonului $i$ \r\n** $X{~1~}, X{~2~}, ..., X{~2*N~}$ sunt cele $2*N$ necunoscute care semnifica faptul ca se trage pe directia respectivei bisectoare\r\n** $A{~i,j~} = 1$ in caz ca bisectoarea $j$ intersecteaza segmentul {$i$}, $0$ in caz contrar.\r\n\r\nSistemul se va rezolva modulo $2$ folosind algoritmul lui \'Gauss\':http://en.wikipedia.org/wiki/Gauss_algorithm.\r\n\r\nPentru calcularea valorilor $A{~i,j~}$ se calculeaza unghiul format de semidreptele ce trec prin capetele segmentului $j$ si se testeaza daca semidreapta i se afla in interiorul sau. Trebuie avut grija la eventualele cazuri care apar, in special cand unghiul are o semidreapta in cadranul $4$ si alta in cadranul {$1$}.\r\n\r\nComplexitate $O(n^3^)$\r\n\r\nO optimizare, care insa nu era necesara pentru obtinerea punctajului maxim, ar fi reprezentarea sistemului format pe biti reducand complexitatea la {$O(n^3^ / log n)$}.\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'public',NULL,NULL),('template/implica-te/scrie-articole','template/implica-te/scrie-articole','2007-03-30 16:28:52','2008-12-26 19:09:33','table{margin:0.5em auto;}. |={background-color:#EFEFFF;border:1px solid #9F9FFF}. !<template/implica-te/scrie-articole?icon_pow_community.gif! Acest articol a fost adăugat de ==user(user=\"%user_id%\" type=\"tiny\") ==\r\n\'*Intră aici*\':implica-te/scrie-articole _dacă doreşti să scrii articole sau află cum te poţi_ \'*implica*\':implica-te _în celelalte proiecte infoarena!_ |',15,'protected',NULL,NULL),('template/todo','template/todo','2006-11-12 18:37:46','2008-02-04 20:59:45','table{margin:0.5em auto;}. |={background-color:rgb(241, 245, 252);border:1px solid rgb(171, 213, 245);}. !{vertical-align:middle;}template/todo?progress2.gif! *Aceasta pagina nu este finalizata. Te rugam sa o imbunatatesti.*   |\r\n',1,'protected',NULL,NULL),('acm-icpc-upb-2008/solutii/pkinv','Solutie Pkinv','2008-10-04 14:29:53','2008-11-01 23:41:42','h2(#pkinv). \'Pkinv\':problema/pkinv\r\n\r\nProblema este asemanatoare cu problema \'Perm6\':/problema/perm6 si ne duce cu gandul, in prima faza, la o dinamica de forma $c[i][j]$ = numarul de permutari de $i$ elemente cu $j$ inversiuni. Recurenta iese usor, gandindu-ne cu cat creste numarul de inversiuni in functie de ultimul numar adaugat in permutare: $c[i][j] = c[i-1][j] + c[i-1][j-1] + ... + c[i-1][max(j-i+1, 0)]$. Din pacate, aceasta dinamica are complexitatea $O(N*K^2^)$. Desi dinamica se poate reduce la complexitate $O(N*K)$ folosind sume partiale, ar insemna sa ne indepartam ca idee de solutia optima a problemei. Observam in dinamica de mai sus, ca pentru $K < i &le; N$, functia $max$ va returna mereu valoarea $0$, deci recurenta nu mai variaza in functie de $i$. Astfel, putem considera trecerea de la pasul $i$ la pasul $i+1$ o inmultire de matrici:\r\n<tex>\\begin{pmatrix} c[i][0] & c[i][1] & ... & c[i][k] \\end{pmatrix} * \\begin{pmatrix} 1 & 1 & ... & 1 \\\\0 & 1 & ... & 1 \\\\... \\\\0 & 0 & ... & 1 \\end{pmatrix} = \\begin{pmatrix} c[i+1][0] & c[i+1][1] & ... & c[i+1][k]\\end{pmatrix}</tex>.\r\nFolosind proprietatea de asociativitate a inmultirii matricilor, putem deduce:\r\n<tex>\\begin{pmatrix} c[k+1][0] & c[k+1][1] & ... & c[k+1][k] \\end{pmatrix} * \\begin{pmatrix} 1 & 1 & ... & 1 \\\\0 & 1 & ... & 1 \\\\... \\\\0 & 0 & ... & 1 \\end{pmatrix}^{n-k-1} = \\begin{pmatrix} c[n][0] & c[n][1] & ... & c[n][k]\\end{pmatrix}</tex>.\r\nInmultirea a doua matrici $K x K$ are complexitate $O(K^3^)$, iar ridicarea la putere are nevoie de $O(logN)$ astfel de inmultiri. Pentru a calcula dinamica pana la pozitia $K+1$, putem aplica recurenta de mai sus avand o complexitate $O(K^3^)$. Complexitatea finala este $O(K^3^*logN)$.',2044,'public',NULL,NULL),('blog/problema-saptamanii-2007-10-30','Problema saptamanii','2007-10-30 03:01:49','2008-11-15 13:41:14','Dupa feedbackul pozitiv de la primele doua probleme, m-am decis sa postez cate o problema draguta cam la doua saptamani.\r\n\r\nProblema curenta: _Un terorist se afla pe o axa infinita la pozitia X0 in momentul T = 0. La fiecare secunda teroristul se muta la dreapta cu Y unitati (Y poate fi si negativ). X0 si Y sunt numere intregi fixate pe care noi nu le stim. La fiecare secunda putem verifica exact o coordonata de pe axa si vom afla daca teroristul e sau nu acolo. Se cere determinarea unei modalitati de a il descoperi pe terorist si de a ii putea prezice pozitiile urmatoare._\r\n\r\nPentru intrebari referitoare la enunt folositi sectiunea de comentarii. Solutiile complete trimiteti-mi-le ca mesaj privat.\r\n\r\n',1490,'protected',2244,NULL),('automate-finite-si-kmp','Automate finite si KMP','2005-01-12 00:00:00','2010-02-04 11:20:30','h1. Automate finite si KMP\r\n\r\n(Categoria _Algoritmi_, Autor _Adrian Vladu_)\r\n\r\nIn acest articol vom aborda cele mai comune probleme legate de pattern matching si vom oferi suportul teoretic necesar intelegerii algoritmului Knuth-Morris-Pratt, pornind de la potrivirea standard cu automate finite si rafinand-o treptat pana la un algoritm de complexitate {$O(n + m)$}. Toate acestea intr-o maniera usor de inteles ;)\r\n\r\nh2. Automate finite\r\n\r\nh3. Ce sunt automatele finite ?\r\n\r\nUn automat finit este definit ca un cvintuplu {@<@}{$Q, q{~0~}, A, &#0931;, &#0948;$}{@>@} unde $Q$ este o multime finita de stari {$Q = {q{~0~}, q{~1~}, ... q{~n~}}$}, $q{~0~}$ apartine $Q$ ({$q{~0~}$} = stare initiala), $A$ inclus in $Q$ ({$A$} = multimea starilor de acceptare), $&#0931;$ este un alfabet, iar functia {$&#0948; : Q x &#0931; -> Q$} este functia de tranzitie a automatului.\r\n\r\nAceasta este definitia matematica si foarte abstractizata a automatelor. Pentru a le intelege mai usor, sa luam un exemplu concret\r\n\r\n!Automate-finite-si-KMP?dfa.jpg!\r\n\r\n* $Q = {q{~0~}, q{~1~}, q{~2~}, q{~3~}}$\r\n* $A = {q{~3~}}$\r\n* $&#0931; = {a, b}$\r\n* &#0948; = \r\n\r\ntable. | &#0948; | a | b |\r\n| 0&nbsp; | 1 | 2 |\r\n| 1 | 3 | 1 |\r\n| 2 | 3 | 0&nbsp; |\r\n| 3 | 3 | 3 |\r\n\r\n\r\nCe inseamna asta? Sa spunem ca automatul primeste un string $s$ = *bbaba*\r\nInitial ne aflam in {$q{~0~}$}. Pentru fiecare element al stringului $s{~i~}$ facem tranzitia {$&#0948;(q{~k~}, s{~i~})$}.\r\n\r\nPornim din {$k = 0$}. Vom avea :\r\n\r\n* $k = 0; &#0948;(0, b) = 2;$\r\n* $k = 2; &#0948;(2, b) = 0;$\r\n* $k = 0; &#0948;(0, a) = 1;$\r\n* $k = 1; &#0948;(1, b) = 1;$\r\n* $k = 2; &#0948;(1, a) = 3;$\r\n\r\nDaca ultima stare obtinuta $q{~k~}$ apartine {$A$}, atunci spunem ca automatul accepta stringul. Altfel spus, daca avem stringul {$s$}, {$lungime(s) = n$}, automatul accepta stringul daca si numai daca $&#0948;( ... &#0948;( &#0948;(0, s{~1~}), s{~2~} ) ..., s{~n~} )$ apartine {$A$}.\r\n\r\nStringurile \'{$aa$}\', \'{$aaaaaaa$}\', \'{$aabababab$}\', \'{$aaaba$}\', \'{$ba$}\', \'{$aba$}\' sunt acceptate de automat, dar \'{$abbbbbb$}\', \'{$bba$}\' nu.\r\n\r\nh3. La ce folosesc ?\r\n\r\n# Inteligenta artificiala (prima si cea mai involuata stare a inteligentei artificiale)\r\n# Aplicatii teoretice si probleme de matematica :)\r\n# Pattern matching\r\n\r\nSe dau stringurile $M$ si {$N$}. Se cere sa gasim toate aparitiile lui $N$ in {$M$}.\r\nVom numi {$M{~i~}$} prefixul lui $M$ de lungime {$i$}. Presupunand ca avem construit automatul care accepta stringul {$N$}, vom cauta toate prefixele lui $M$ acceptate de automat, deci toate numerele $1 &le; i &le; lungime(M)$ cu proprietatea ca automatul accepta stringul {$M{~i~}$}.\r\n\r\nh3. Algoritm_potrivire_cu_automat_finit\r\n\r\n== code(c) | \r\nn = lungime(N)\r\nm = lungime(M)\r\nq = 0;\r\npt i <- 1, m\r\n    q = d(q, M[i])\r\n    daca q apartine A\r\n        scrie \"potrivire la pozitia \" i - n + 1\r\n==\r\n\r\n* Complexitate : $O(n)$\r\n\r\nSa vedem cum se construieste automatul de potrivire pentru un string {$N$}. Fie {$m = lungime(M)$}. Construim un automat cu $m + 1$ stari {{$q{~0~}, q{~1~}, ... q{~m~}$}}, $A = {q{~m~}}$ . Faptul ca ne aflam in starea $x$ inseamna ca au fost acceptate primele $x$ caractere din sirul de intrare.\r\nDin fiecare stare $q{~x~}$ apartine $Q$ si pt fiecare $c$ apartine $S$ construim $&#0948;(x, c) = y$ cu proprietatea ca $M{~y~}$ este cel mai lung prefix al lui $M$ care este sufix al lui $M{~x~}c$ (prefixul de lungime $x$ al lui {$M$}, concatenat cu caracterul {$c$}).\r\n\r\n\r\n\r\nh3. Algoritm_constructie_automat_finit\r\n\r\n== code(c) |\r\nm <- lungime(M)\r\npt q <- 0, m\r\n    pt c apartine S\r\n        gaseste M[i] = cel mai lung prefix al lui M cu M[i] sufix al lui M[q]c\r\n            d(q, c) = i\r\n==\r\n\r\n* Complexitate : linia $4$ are complexitatea $O(m^2^)$ (implementata in maniera bruta) si se executa de $(m + 1) * |&#0931;|$ ori => complexitate totala $O(m^3^ * |&#0931;|)$\r\n\r\nPractic, algoritmul calculeaza pentru toate {$0 &le; i &le; m$}, $c$ apartine $S$ cat de mult putem lua de la sfarsitul lui $M{~i~}c$ astfel incat acesta sa fie un \"inceput\" de {$N$}.\r\n\r\nAcesta se poate rafina, eliminand operatii redundante, dupa cum vom vedea in cele ce urmeaza.\r\n\r\nh2. Algoritmul KMP\r\n\r\nGaseste toate aparitiile unui string $N$ in $M$ in timp {$O(n + m)$}, unde {$n = lungime(N)$}, {$m = lungime(M)$}. O parte esentiala a sa este functia prefix $&pi; : {1..n} -> {0..n-1}$ unde $&pi;{~i~}$ = cel mai lung prefix al lui $M$ care este sufix al lui {$M{~i~}$}. Evident, $M{~&pi;{~i~}~}$ (prefixul de lungime $&pi;{~i~}$ al lui {$M$}) este prefix al lui {$M{~i~}$}, deci {$&pi;{~i~} < i$}.\r\n\r\nh3. Algoritm_calcul_functie_prefix\r\n\r\n== code(c) |\r\nn <- lungime(N)\r\nk <- 0\r\npi[1] <- 0\r\npt i <- 2, n\r\n    cat timp (k > 0) si (N[k + 1] != N[i])\r\n        k <- pi[k]\r\n    daca N[k + 1] = N[i]\r\n        k <- k + 1\r\n    pi[i] <- k\r\n==\r\n\r\nh4.  Analiza complexitatii :\r\n\r\n* la fiecare pas ({$i = 2, n$}) $k$ se incrementeaza cel mult o data, deci pe parcursul algoritmului $k$ se va incrementa de cel mult $n - 1$ ori (linia {$8$})\r\n* in linia {$5$}, $k$ se decrementeaza cel mult pana devine {$0$}, deci se va decrementa de cel\r\nmult $n - 1$ ori pe parcursul algoritmului\r\n* {=>} Complexitate : $O(n)$\r\n\r\nAlgoritmul este similar cu constructia automatului de acceptare. Din fiecare stare $i$ in care s-a acceptat {$N{~i~}$}, vedem cat de mult putem lua de la sfarsitul lui {$N{~i~}$} astfel incat sufixul respectiv sa fie prefix pentru {$N$}. De remarcat ca in cazul in care starea candidata $k$ nu este buna, nu mergem in {$k - 1$}, ci in {$&pi;{~k~}$}. Aceasta este de fapt \"magia\" care ofera complexitate liniara.\r\n\r\nAlgoritmul de potrivire este similar celui al calculului functiei prefix, numai ca aici la fiecare pas $i$ cautam cel mai lung prefix al lui $N$ care este sufix al lui {$M{~i~}$}.\r\n\r\n\r\n\r\nh3. Algoritm_potrivire_KMP\r\n\r\n== code(c) |\r\nm <- lungime(M), n <- lungime(N)\r\nq <- 0\r\npt i <- 1, m\r\n    cat timp (q > 0) si (N[q + 1] != M[i])\r\n        q <- pi[q]\r\n    daca N[q + 1] = M[i]\r\n        q <- q + 1\r\n    daca q = n\r\n        scrie \"potrivire la pozitia \" i - n + 1\r\n==\r\n\r\nAnalog Algoritm_Calcul_Functie_Prefix, complexitatea algoritmului efectiv de potrivire este {$O(m)$}. Astfel rezulta complexitatea liniara a algoritmului KMP $O(n + m)$\r\n\r\nh2. Teme pentru acasa:\r\n\r\n* folosind functia prefix, rafinati constructia automatului finit de acceptare pentru un string, aducand-o la complexitatea $O(m^2^ * |&#0931;|)$\r\n* problema \"Microvirus\":http://www.liis.ro/%7ecampion/problems/2/64/microvirus.htm (hint : construiti automatul de potrivire pentru stringul dat)\r\n* Timus 1158: \"Censored!\":http://acm.timus.ru/problem.aspx?space=1&num=1158\r\n\r\n',2970,'public',3698,NULL),('runda/summer_camp_5','summer_camp_5','2009-08-16 18:06:43','2009-08-16 18:06:43','h1. == roundparam(round_id=\"summer_camp_5\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"summer_camp_5\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"summer_camp_5\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"summer_camp_5\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/summer_camp_5/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"summer_camp_5\" score=\"1\")==',6957,'round: summer_camp_5',NULL,NULL),('runda/summer_camp_5/clasament','Clasament summer_camp_5','2009-08-16 18:06:43','2009-08-16 18:06:43','h1. Clasament ==roundparam(round_id=\"summer_camp_5\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer_camp_5\")==',6957,'round: summer_camp_5',NULL,NULL),('blog/oni-by-net-2007','ONI by NET 2007','2007-04-04 15:50:14','2007-04-04 15:52:56','Elevii care nu s-au calificat la Olimpiada Nationala de Informatica pot participa prin internet la _ONI by NET_. Participantii la _ONI by NET_ sunt evaluati in aceleasi conditii ca si cei de la ONI.\r\n\r\n*Castigatorii au ocazia de a se califica la proba de baraj a olimpiadei nationale!*\r\n\r\nMai multe detalii la \"http://olimpiada.info/bynet/\":http://olimpiada.info/bynet/\r\n\r\n',13,'public',NULL,NULL),('autumn-warmup-2007/solutii/runda-3','Solutii Autumn Warmup, Runda 3','2007-10-08 13:12:36','2007-10-18 21:41:49','h2. \'Dk\':problema/dk\r\n\r\nPentru problema existau diverse rezolvari brute-force, care in functie de calitatea implementarii af fi obtinut pana la $50$ de puncte. \r\nAlgoritmul folosit in rezolvarea pentru $100$ de puncte este Miller-Rabin. Este un algoritm probabilistic care verifica primalitatea unui numar in complexitate $O(c*log Nr)$, unde c este numarul de baze folosite pentru verificare. \r\nDorim sa verificam daca numarul $Nr$ este prim. Primul pas care trebuie efectuat este acela de a-l scrie pe $Nr-1$ ca numar de forma <tex>2^s^ * d</tex>, unde s trebuie sa fie maxim. Pasul urmator este sa verificam 2 relatii:\r\n1. <tex> a^{d}\\ mod\\ n\\ \\neq\\ 1 </tex>  \r\n2. <tex> a^{2^r*d}\\ mod\\ n\\ \\neq\\ -1</tex>, pentru $0 &le; r &le; s-1$ \r\n\r\nDaca ambele relatii sunt simultan indeplinite pentru un numar $a$, atunci stim ca numarul $Nr$ este compus. Daca cel putin una dintre conditii nu este indeplinita se continua verificarile pentru un alt numar $a$. Numerele $a$ cu care se vor face verificarile pot fi, de exemplu, primele 6 numere prime sau o multime de numere prime alese aleator (mai mult de $3$, dar nu mai mult de $7$, pentru ca solutia sa se incadreze in timp).    \r\nComplexitatea logaritmica a algoritmului provine de la faptul ca ridicarile la putere se vor efectua in $O(log n)$. Pentru mai multe detalii consultati CLR-ul sau \'Wikipedia\':http://en.wikipedia.org/wiki/Miller-Rabin_primality_test.\r\n\r\n\r\nh2. \'Kcity\':problema/kcity\r\n\r\nh3. \"Bandwidth\"-ul si \"Pathwidth\"-ul unui graf\r\n\r\nSa consideram ca nodurile unui graf sunt renumerotate cu numere de la $1$ la $N$ si sa notam cu $BMAX$ valoarea maxima a diferentei (in modul) dintre numerele asociate a doua noduri adiacente. \"Bandwidth\"-ul $B$ al unui graf este valoarea minima a lui $BMAX$ dintre toate renumerotarile posibile ale nodurilor. Determinarea acestei valori $B$ nu se poate realiza in timp polinomial. In cadrul problemei date, nodurile au fost deja numerotate corespunzator, astfel incat graful sa aiba un \"bandwidth\" mic, egal cel mult cu valoarea $K$ data.\r\n\r\n\"Pathwidth\"-ul unui graf este un numar ce reflecta cat de mult structura grafului este asemanatoare cu cea a unui drum. Daca un graf $G$ are un \"pathwidth\" $P$, atunci exista un graf-drum $D$, cu nodurile $D{~1~}, D{~2~}, ..., D{~X~}$, avand urmatoarele proprietati:\r\n\r\n* fiecare nod $D{~i~}$ corespunde unei submultimi de cel mult $P$ noduri ale grafului $G$\r\n* oricare doua noduri adiacente ale grafului $G$, $u$ si $v$, se afla impreuna in cel putin una din submultimile $D{~1~},...,D{~X~}$\r\n* orice nod $u$ al grafului $G$ apartine unor multimi $D{~i~}$ care formeaza un sub-drum al grafului $D$ (mai exact, niciun nod $u$ al lui $G$ nu poate sa apartina unui submultimi $D{~i~}$, sa nu apartina unei submultimi $D{~j~}$ {$(j &gt; i)$} si apoi sa apartina din nou unei alte submultimi $D{~k~}$ $(k &gt; j)$\r\n\r\nDaca avem o renumerotare a unui graf $G$ corespunzatoare unui \"bandwidth\" mic, atunci putem obtine si o descompunere cu \"pathwidth\" mic a grafului G, care ne va ajuta sa rezolvam problema.\r\n\r\nh3. Solutie de complexitate $O(N * numar_stari * K^3^)$\r\n\r\nElementele teoretice prezentate mai sus nu sunt neaparat necesare pentru a rezolva problema. Se \"ghiceste\" usor ca problema se rezolva folosind programare dinamica pe un numar exponential de stari, care depinde, insa, numai de $K$, care este o valoare mica.\r\n\r\nVom calcula urmatoarele valori:\r\n\r\n* $minp[i][S]$ = numarul minim de drumuri cu care se pot acoperi nodurile $1,2,...,i$, iar starea la pasul $i$ sa fie $S$\r\n* $minc[i][S]$ = numarul minim de cicluri cu care se pot acoperi nodurile $1,2,...,i$, iar starea la pasul $i$ sa fie $S$ (nu trebuie sa apartina neaparat unui ciclu inchis si nodurile din cadrul starii curente sau cele care apartin deja unor drumuri care au capetele in cadrul starii curente)\r\n\r\nO stare $S$ la pasul $i$ este reprezentata de starea ultimelor $K$ noduri $(i-K+1, i-K+2, ..., i)$. O prima idee de definire a starii este urmatoarea: fiecare nod se poate afla in una din urmatoarele $3$ stari:\r\n\r\n* are gradul $0$ (este un drum ce consta doar din nodul respectiv)\r\n* are gradul $1$ (este un capat al unui drum)\r\n* are gradul $2$ (se afla in interiorul unui drum sau al unui ciclu (in orice caz, daca un nod are gradul $2$, el nu mai prezinta interes in algoritmul nostru)\r\n\r\nDefinind o stare astfel, ar exista $3^K^$ stari in total. La fiecare pas $i$, am considera toate starile $S\'$ de la pasul $i-1$ si, adaugand nodul $i$, impreuna cu unele muchii, la starea $S\'$, am obtine niste stari $S$, pentru pasul $i$. Avem urmatoarele optiuni:\r\n\r\n* pentru cazul acoperii cu drumuri\r\n** nodul $i$ formeaza un drum nou (are gradul $0$) => numarul de drumuri creste cu $1$\r\n** nodul $i$ extinde un drum deja existent (il legam de un nod $j$ de grad $0$ sau $1$, cu conditia sa existe muchia $i-j$) => numarul de drumuri ramane acelasi\r\n** nodul $i$ leaga doua drumuri diferite (il legam de nodurile $j$ si $k$ de grad $0$ sau $1$, unind astfel doua drumuri) => numarul de drumuri scade cu $1$\r\n* pentru cazul acoperirii cu cicluri\r\n** nodul $i$ formeaza un drum nou (are gradul $0$) => numarul de cicluri ramane la fel\r\n** nodul $i$ extinde un drum deja existent (il legam de un nod $j$ de grad $0$ sau $1$, cu conditia sa existe muchia $i-j$) => numarul de cicluri ramane la fel\r\n** nodul $i$ leaga doua drumuri diferite (il legam de nodurile $j$ si $k$ de grad $0$ sau $1$, unind astfel doua drumuri) => numarul de cicluri ramane la fel\r\n** nodul $i$ leaga cele $2$ capete ale unui drum => numarul de cicluri creste cu $1$\r\n** daca nodul $i &gt; K$, trebuie sa ne asiguram, inainte de a trece mai departe, ca nodul $i-K$ are gradul $2$ (se afla in interiorul unui drum sau al unui ciclu) => optiunile de mai sus nu sunt valide decat daca, in urma aplicarii lor, nodul $i-K$ are gradul $2$\r\n\r\nObservam o dificultate in cazul in care nodul $i$ trebuie sa uneasca doua drumuri de grad $1$. In cazul acoperirii cu drumuri, trebuie sa ne asiguram ca el nu leaga capetele aceluiasi drum (inchizand, de fapt, un ciclu, in timp ce noi credeam ca a unit $2$ drumuri). In cazul acoperii cu cicluri trebuie sa putem realiza aceeasi distinctie. Asadar, modul in care am definit starea nu este corect, desi era, poate, cel mai intuitiv.\r\n\r\nO stare va trebui definita in felul urmator: fiecare din cele $K$ noduri ale starii se poate afla in una din urmatoarele situatii:\r\n\r\n* are gradul $0$ (este un drum ce consta doar din nodul respectiv) - se codifica prin $0$\r\n* are gradul $1$ si este capatul unui drum care are un identificator bine specificat - se codifica prin identificatorul drumului\r\n* are gradul $2$ (se afla in interiorul unui drum sau al unui ciclu) - se codifica prin $-1$\r\n\r\nDe exemplu, pentru $K=6$, starea $S=(-1, 1, 0, 2, -1, 1)$ specifica faptul ca primul si al cincilea nod au gradul $2$, al treilea nod are gradul $0$, al doilea si al saselea nod sunt capetele aceluiasi drum, care are identificatorul $1$, iar al patrulea nod este capatul unui drum ce are identificatorul $2$ (celalalt capat fiind ramas undeva in urma).\r\n\r\nConform noii definitii a starilor, acestea trebuie generate explicit. Observam ca doar doua noduri pot fi capetele aceluiasi drum, ca identificatorii drumurilor ii putem genera de la $1$ pana la cate drumuri pot exista intr-o stare (maxim $K$) si ca putem considera identificatorii drumurilor sortati in ordinea in care apar in cadrul starii nodurile ce sunt capetele acestora. De exemplu, starea $S=(-1, 2, 0, 1, -1, 2)$ nu ar avea sens, fiind echivalenta cu cea prezentata mai sus, schimband doar identificatorii drumurilor intre ei. Pentru $K=6$ exista $2364$ astfel de stari.\r\n\r\nRaspunsul dorit il gasim intr-una din starile de la pasul $N$:\r\n\r\n* pentru acoperirea cu drumuri se alege minimul dintre toate valorile $minp[N][S]$\r\n* pentru acoperirea cu cicluri se alege valoarea $minc[N][S]$, unde $S$ este starea in care toate nodurile au gradul $2$ ; daca aceasta valoare este infinit, atunci rezultatul este $-1$\r\n\r\nh2. \'Consir\':problema/consir\r\n\r\nSa presupunem ca dorim sa aflam rezultatul pentru secventa maxima $1, 2 ... M$. Fie $F{~1~}, F{~2~}, ... F{~M~}$ frecventele numerelor de la $1$ la $M$ (numarul de aparitii). Sa construim acum un vector $P$ cu semnificatia $P{~i~} = F{~1~}* F{~2~} * ... * F{~i~}$. Datoria faptului ca rezultatul este mai mic decat $2^63^$ este clar ca nu avem mai mult de 63 de pozitii pentru care $F{~i~}>1$, deci la fiecare pas trebuie sa updatam subsecventele care se termina intr-o pozitie cu $F{~i~}>1$. Algoritmul in pseudocod pentru a calcula vectorul $Res$ cu semnificatia $Res{~i~}$ egal cu numarul de consiruri de lungime $i$ devine\r\n\r\n== code(c) |\r\nRes[M] = P[M];\r\npentru i = n-1, 1 executa\r\n   Res[i] = Res[i+1] + P[M]/P[M-i];\r\n   pentru j astfel incat F[j] >= 2 si j >= i+1\r\n       Res[i] = Res[i] - P[j]/P[j-i-1] + P[j-1]/P[j-i-1];\r\n   sfarsit pentru\r\nsfarsit pentru\r\n==\r\n\r\nh2. \'Polig\':problema/polig\r\n\r\nExista mai multe solutii care se incadreaza in timp pentru limitele date, o idee ar fi ca punctele sa fie sortate dupa unghiul cu axa $Ox$. Apoi, folosind programare dinamica vom construi o matrice cu semnificatia $a[i][j]$ = costul maxim astfel incat sa plecam din orginea planului si sa construim un drum care are ultimele puncte $i$ si $j$. In total, memoria este $O(n^2^)$ si complexitatea in timp $O(n^3^)$. Exista o solutie $O(n^2^ lg{~2~}n)$ propusa de Mugurel Ionut Andreica, gasirea ei o lasam ca un exercitiu pentru cititori :-). Daca aveti nelamuriri nu ezitati sa folositi forumul.',2044,'public',NULL,NULL),('blog/o-problema-misto-solutie','O problema misto - solutie','2007-10-16 06:23:58','2008-11-15 13:41:14','Din dorinta de a face enuntul problemei cat mai simplu am lasat cateva cerinte ale problemei nespecificate. De aici au aparut si cele trei updateuri la text.\r\n\r\nCei care au rezolvat problema sunt: \'Teodorescu Andrei-Marius\':http://infoarena.ro/utilizator/andreitheo87 , Adrian Sandor si Radu Cebanu. \r\n\r\nV-am promis si o solutie:\r\n Impartim planul in patrate de latura unu. Suprapunem toate patratele unul peste celalalt, si cum aria totala a petelor este strict mai mica ca unu rezulta ca va exista un punct care nu este acoperit de vreo pata. Marcam acest punct in toate patratele. Cand le punem inapoi in plan, punctul marcat se transforma in o grila de puncte. Acum putem selecta ca origine oricare dintre aceste puncte si ca axe dreptele paralele cu abscisa respectiv ordonata din sistemul initial, care trec prin punctul ales ca origine.\r\n\r\nSper ca v-a placut, chiar daca e o problema de mate.\r\n\r\n',1490,'protected',2207,NULL),('utilizator/cristi_c','Profil cristi_c','2007-04-10 09:07:53','2007-07-10 10:38:34','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\nOdata cu clasa a V-a am inceput sa studiez informatica la Colegiul National Vasile Alecsandri Galati, obtinand mai multe distinctii ...\r\n\r\nh2. Distinctii primite:\r\n\r\nClasa a V-a (2006-2007) :-Premiul I la olimpiada judeteana de informatica;\r\n                         -Mentiune la olimpiada nationala de informatica;\r\n                         -Premiul I la clasele V-VI la concursul Micul Gates de la Ramnicu-Valcea (site-ul concursului www.miculgates.ro)\r\n\r\n\r\n\r\n',6421,'public',NULL,NULL),('utilizator/ada_s','Profil ada_s','2007-04-17 17:21:29','2008-03-08 12:58:02','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6443,'public',NULL,NULL),('arbori-de-intervale','Arbori de intervale si aplicatii in geometria computationala','2007-04-17 20:24:45','2009-02-20 00:38:02','h1. Arbori de intervale si aplicatii in geometria computationala\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"sima_cotizo\") ==\r\n\r\n(Categoria _Structuri de date_, Autor _Dana Lica_)\r\n\r\nh2. Problema 1\r\n\r\np<>. Se considera $N (N &le; 50 000)$ segmente in plan, dispuse paralel cu axele $OX$ si $OY$. Sa se determine care este numarul total de intersectii dintre segmente.\r\n\r\np<>. In fisierul $_segment.in_$ se gaseste pe prima linie numarul $N$ de segmente, iar pe fiecare dintre urmatoarele $N$ linii cate patru numere naturale mai mici decat $50 000$, reprezentand coordonatele carteziene ale extremitatilor fiecarui segment. Rezultatul se va scrie in $_segment.out_$.\r\n\r\np<>. _Timp de executie: $1 secunda/test$_.\r\n\r\ntable(example). |_. segment.in |_. segment.out |_. Figura |\r\n|^. 5\r\n2 9 13 9\r\n4 6 12 6\r\n1 2 6 2\r\n5 0 5 8\r\n7 5 7 11  |^. 4 |=. !arbori-de-intervale?figure-1.jpg! |\r\n\r\nh2. Algoritmi de \"baleiere\" _(line sweeping)_\r\n\r\np<>. Folosind cunostinte generale de geometrie analitica se poate obtine un algoritm $O(N^2^)$ dar acesta nu se va incadra in limita de timp. \r\n\r\np<>. Pentru rezolvarea acestei probleme vom folosi o tehnica cunoscuta sub numele de \"baleiere\" _(sweeping)_ care este comuna multor algoritmi de geometrie computationala. In baleiere, o dreapta de baleiere verticala, imaginara, traverseaza multimea obiectelor geometrice, de obicei de la stanga la dreapta.  Baleierea ofera o metoda pentru ordonarea obiectelor geometrice, plasandu-le intr-o structura de date, pentru obtinerea relatiilor dintre ele.\r\n\r\nAlgoritmii de baleiere gestioneaza doua multimi de date: \r\n\r\n# _Starea liniei_ de baleiere da relatia dintre obiectele intersectate de linia de baleiere \r\n# _Lista punct-eveniment_ este o secventa de coordonate $x$, ordonate de la stanga la dreapta de obicei, care definesc pozitiile de oprire ale dreptei de baleiere; fiecare astfel de pozitie de oprire se numeste _punct eveniment_; numai in punctele eveniment se intalnesc modificari ale starii liniei de baleiere; pentru unii algoritmi, lista punct-eveniment este determinata dinamic in timpul executiei algoritmului. \r\n\r\np<>. Pentru a rezolva problema, vom deplasa o dreapta de baleiere verticala, imaginara de la stanga la dreapta. Lista punct-eveniment va contine capetele segmentelor orizontale, ce fel de tip sunt (cap stanga sau cap dreapta) si segmentele verticale. Pe masura ce ne deplasam de la stanga la dreapta vom efectua urmatoarele operatii:\r\n\r\n* cand intalnim un capat stang, inseram capatul in starile dreptei de baleiere; \r\n* cand intalnim un capat drept, stergem capatul din starile dreptei de baleiere; \r\n* cand intalnim un segment vertical, numarul de intersectii ale acestui segment cu alte segmente orizontale va fi dat de numarul capetelor de intervale care se afla in starile dreptei de baleiere cuprinse intre coordonatele $y$ ale segmentului vertical. \r\n\r\np<>. Astfel, starile dreptei de baleiere sunt o structura de date pentru care avem nevoie de urmatoarele operatii:\r\n\r\n* _INSEREAZA&#40; y &#41;_ : insereaza capatul $y$;\r\n* _STERGE&#40; y &#41;_ : sterge capatul $y$;\r\n* _INTEROGARE&#40; y1, y2 &#41;_ : intoarce numarul de capete cuprinse in intervalul $[y{~1~}, y{~2~}]$.\r\n\r\np<>. Fie $MAXC$ valoarea maxima a coordonatelor capetelor de segmente. Folosind un vector pentru a implementa aceste operatiile descrise mai sus vom obtine o complexitate $O(1)$ pentru primele doua operatii si $O(MAXC)$ pentru cea de-a treia. Astfel, complexitatea  va fi $O(N*MAXC)$ in cazul cel mai defavorabil. Putem comprima spatiul $[0...MAXC]$ observand ca doar maxim $N$ din valori din acest interval conteaza, si anume capetele segmentelor orizontale, astfel reducand a treia operatie la $O(N)$, dar algoritmul va avea complexitatea $O(N^2^)$, ceea ce nu aduce nici o imbunatatire fata de algoritmul trivial. \r\n\r\np<>. Aceasta situatie ne indeamna sa cautam o structura de date mai eficienta. O prima varianta ar fi impartirea vectorului in bucati de $sqrt(N)$ reducand complexitatea totala la $O(N*&radic;N)$. In continuare vom prezenta o structura de date care ofera o complexitate logaritmica pentru operatiile descrise mai sus.\r\n\r\nh2. Arbori de intervale\r\n\r\np<>. Un _arbore de intervale_ este un arbore binar in care fiecare nod poate avea asociata o structura auxiliara (anumite informatii). Dandu-se doua numere intregi $st$ si $dr$, cu $st < dr$, atunci arborele de intervale $T(st, dr)$ se construieste recursiv astfel:\r\n\r\n* consideram radacina $nod$ avand asociat intervalul $[st, dr]$;\r\n* daca $st < dr$ atunci vom avea asociat subarborele stang $T(st, mij)$, respectiv subarborele drept $T(mij + 1, dr)$, unde $mij$ este mijlocul intervalului $[st, dr]$.\r\n\r\np<>. Intervalul $[st, dr]$ asociat unui nod se numeste interval standard. Frunzele arborelui sunt considerate intervale elementare, ele avand lungimea $1$.\r\n\r\nh3. Proprietate: \r\n\r\np<>. Un arbore de intervale este un arbore binar echilibrat (diferenta absoluta intre adancimea subarborelui stang si cea a subarborelui drept este cel mult $1$). Astfel, adancimea unui arbore de intervale care contine $N$ intervale este $[log{~2~}N] + 1$.\r\n\r\np=. !arbori-de-intervale?figure2.jpg!\r\n\r\nh2. Operatii efectuate asupra unui arbore de intervale:\r\n\r\nAsupra unui arbore de intervale se pot face doua operatii semnificative: actualizarea, respectiv interogarea unui interval.\r\n\r\nh3. Actualizare unui interval intr-un arbore de intervale\r\n\r\np<>. Vom prezenta pseudocodul unei proceduri recursive care insereaza un interval $[a, b]$ intr-un arbore de intervale $T(st,dr)$ cu radacina in nodul $nod$. Cea mai eficienta metoda de stocare in memorie a unui arbore de intervale este sub forma unui vector folosind aceeasi codificare a nodurilor precum la heap-uri :\r\n\r\n==code(c) |\r\nprocedura ACTUALIZARE(nod, st, dr, a, b)\r\n   daca (a <= st) si (dr <= b) atunci\r\n      modifica structura auxiliara din nod \r\n   altfel \r\n      mij = (st + dr) / 2\r\n      daca (a <= mij) atunci \r\n          ACTUALIZARE(2 * nod, st, mij, a, b)\r\n      daca (b > mij) atunci \r\n          ACTUALIZARE(2 * nod + 1, mij + 1, dr, a, b)\r\n      actualizeaza structura auxiliara din nodul nod\r\n==\r\n\r\nh3. Interogarea unui interval intr-un arbore de intervale\r\n\r\np<>. Vom prezenta pseudocodul unei proceduri recursive care returneaza informatiile asociate unui interval $[a, b]$ intr-un arbore de intervale $T(st,dr)$ cu radacina in nodul $nod$.\r\n\r\n==code(c) |\r\nprocedura INTEROGARE(nod, st, dr, a, b)\r\n   daca (a <= st) si (dr <= b) atunci\r\n      returneaza structura auxiliara din nod \r\n   altfel \r\n      mij = (st + dr) / 2\r\n      daca (a <= mij) atunci \r\n          INTEROGARE(2 * nod, st, mij, a, b)\r\n      daca (b > mij) atunci \r\n          INTEROGARE(2 * nod + 1, mij + 1, dr, a, b)\r\n      returneaza structura auxiliara din fiul stang combinata cu cea din fiul drept\r\n==\r\n\r\np<>. Vom demonstra in continuare ca operatiile prezentate mai sus au complexitatea $O(log{~2~} N)$ pentru un arbore de $N$ intervale. Este posibil ca intr-un nod sa aiba loc apel atat in fiul stang cat si in cel drept. Acest lucru produce un cost aditional doar prima data cand are loc. Dupa prima \"rupere in doua\", oricare astfel de \"rupere\" nu va aduce cost aditional, deoarece unul din fii va fi mereu inclus complet in intervalul $[a, b]$. Cum inaltimea arborelui, pentru $N$ intervale, este $[log{~2~}N] + 1$, complexitatea operatiilor va fi tot $O(log{~2~} N)$.\r\n\r\np<>. Pentru a retine in memorie un arbore de intervale pentru $N$ valori, vom aveam de nevoie de $N + N/2 + N/4 + N/8 + ... = 2*N-1$ locatii de memorie (sunt $2*N-1$ noduri). Deoarece arborele nu este complet, trebuie verificat de fiecare data daca fiii unui nod exista in arbore (aceasta verificare a fost omisa in pseudocodul de mai sus), altfel s-ar incerca accesarea de valori din vector care nu exista. Daca memorie disponibila in timpul concursului este suficienta, se poate declara vectorul care retine arborele de intervale de lungime $2^K^$ astfel incat $2^K^ &ge; 2*N-1$, simuland astfel un arbore complet si nefiind necesare verificarile mentionate mai sus.\r\n\r\np<>. Pentru a rezolva in continuare problema, vom folosi un arbore de intervale pentru a simula in timp logaritmic operatiile facute inainte pe un vector obisnuit. Astfel, in fiecare nod din arborele din intervale vom retine cate capete exista in acel interval. Primele doua operatii vor fi implementate folosind procedura _ACTUALIZARE&#40;&#41;_ de mai sus pentru intervalul $[y, y]$ in arborele $T(0, MAXC)$ si adunand $1$, respectiv scazand $1$ la fiecare nod actualizat. Cea de-a treia operatie poate fi realizata folosind procedura _INTEROGARE&#40;&#41;_ pe intervalul $[y{~1~}, y{~2~}]$. Astfel complexitatea se reduce la $O(N * log{~2~}MAXC)$  Folosind aceeasi tehnica de \"comprimare\" a coordonatelor se poate obtine o complexitate $O(N * log{~2~}N)$.\r\n\r\nIn figura urmatoare este descrisa structura arborelui de intervale, dupa actualizarea pentru intervalele $[2, 2]$, $[6, 6]$ si $[9, 9]$. Sunt marcate intervalele care conduc la obtinerea numarului de segmente intersectate de primul segment vertical, obtinute in urma interogarii pe intervalul $[0, 8]$.\r\n\r\np=. !arbori-de-intervale?figure3.jpg!\r\n\r\nh2. Problema 2 (Preluata de la IOI 1998, Ziua 2)\r\n\r\np<>. Se considera $N &le; 50 000$ dreptunghiuri in plan, fiecare avand laturile paralele cu axele $OX$, $OY$. Lungimea marginilor (contururilor) reuniunii tuturor dreptunghiurilor se va numi \"perimetru\". Sa se calculeze perimetrul celor $N$ dreptunghiuri. \r\n\r\np<>. In fisierul $_drept.in_$ se gaseste pe prima linie numarul $N$ de dreptunghiuri, iar pe fiecare din urmatoarele $N$ linii cate patru numere naturale mai mici ca $50 000$, reprezentand coordonatele carteziene ale coltului stanga sus, respectiv dreapta jos ale fiecarui dreptunghi. Rezultatul se va scrie in fisierul $_drept.out_$.\r\n\r\np<>. _Timp maxim de executie: $1 secunda/test$_.\r\n\r\ntable(example). |_. drept.in |_. drept.out |_. Figura |\r\n|^. 3\r\n3 8 8 3\r\n6 10 12 6\r\n12 4 15 1 |^. 44 |=. !arbori-de-intervale?figure4.jpg! |\r\n\r\nFolosind un rationament asemanator ca si la prima problema, constatam necesitatea unui algoritm de baleiere. Vom descompune problema in doua parti: prima data calculam perimetrul folosind doar laturile stanga si dreapta ale dreptunghiurilor pentru a calcula perimetrul pe $OY$; apoi putem sa rotim dreptunghiurile si folosind aceeasi procedura pt a calcula perimetrul pe $OX$, folosind doar laturile sus si jos ale dreptunghiurilor. \r\n\r\nFiecare latura (stanga sau dreapta) va fi un punct eveniment. Sortam laturile crescator dupa coordonata $x$ si parcurgem de la stanga la dreapta. Cand intalnim o latura stanga adaugam in starile dreptei de baleiere, intervalul de unitati ocupat de latura pe $OY$, iar cand intalnim o latura dreapta, eliminam din starile dreptei de baleiere intervalul de unitati ocupat de latura. Intre oricare doua puncte eveniment consecutive are loc o modificare a perimetrului total pe $OY$. Astfel, dupa fiecare actualizare a starilor dreptei de baleiere se va retine care este numarul de unitati adaugate pana in prezent (nu se tine cont daca o unitate este adaugata de mai multe ori). Vom aduna la perimetrul pe $OY$ total de fiecare data, diferenta absoluta intre numarul de unitati adaugate pana in prezent si valoarea imediat anterioara (dinaintea actualizarii). Asadar, este necesara o structura de date care se efectueze urmatoarele operatii in timp eficient (preferabil logaritmic):\r\n\r\n* _MARCHEAZA&#40;a, b&#41;_ : adauga intervalul $[a, b]$;\r\n* _DEMARCHEAZA&#40;a, b&#41;_ : elimina intervalul $[a, b]$;\r\n* _INTEROGARE&#40;&#41;_ : returneaza numarul total de coordonate adaugate pana in prezent.\r\n\r\np<>. Putem folosi un arbore de intervale pentru a obtine o complexitate $O(log{~2~} MAXC)$ sau $O(log{~2~} N)$ pentru primele doua operatii si $O(1)$ pentru ce-a de treia. In fiecare nod din arbore retinem de cate ori a fost marcat intervalul respectiv si cate unitati din intervalul respectiv au fost marcate. Primele doua operatii pot fi implementate folosind procedura _ACTUALIZARE&#40;&#41;_ iar a treia operatie va returna valoarea numarul de unitati care au fost marcate din radacina arborelui de intervale. \r\n\r\np<>. In figura urmatoare este descrisa structura arborelui de intervale, dupa adaugarea intervalelor $[3, 8]$ si $[6, 10]$ (un interval $[y{~1~}, y{~2~}]$ reprezinta intervalul de unitati $[y{~1~}, y{~2~} - 1]$ din arbore). \r\n\r\np=. !arbori-de-intervale?figure-8.jpg!\r\n\r\nh2. Problema 3\r\n\r\np<>. Se dau $N &le; 100 000$ puncte in plan de coordonate numere naturale mai mici ca $2 000 000 000$. Sa se raspunda la $M &le; 1 000 000$ intrebari de forma \"cate puncte din cele $N$ exista in dreptunghiul cu coltul stanga sus in $(x{~1~}, y{~1~})$ si coltul dreapta jos in $(x{~2~}, y{~2~})$?\".\r\n\r\np<>. In fisierul $_puncte.in_$ se vor gasi pe prima linie numerele $N$ si $M$. Pe urmatoarele $N$ linii se vor gasi coordonatele punctelor. Pe urmatoarele $M$ linii se vor gasi cate patru numere naturale reprezentand coordonatele colturilor dreptunghiurilor. In fisierul $_puncte.out_$ se vor gasi $M$ numere naturale reprezentand raspunsurile la intrebari.\r\n\r\np<>. _Timp maxim de executie: $1 secunda/test$_.\r\n\r\ntable(example). |_. puncte.in |_. puncte.out |_. Figura |\r\n|^. 6 1\r\n2 8\r\n5 3\r\n6 5\r\n8 7\r\n8 1\r\n10 10\r\n4 8 9 4 |^. 2 |=. !arbori-de-intervale?figure5.jpg! |\r\n\r\np<>. Problema determinarii numarului de puncte din interiorul unui dreptunghi este o particularizare bidimensionala pentru problema numita in literatura de specialitate _Orthogonal Range Search_. Varianta aleasa pentru acest caz consta intr-un arbore de intervale, care permite determinarea numarului de puncte din interiorul unui dreptunghi cu o complexitate $O(log{~2~}^2^ N)$. \r\n\r\np<>. Astfel, se sorteaza coordonatele $x$ ale punctelor si se construieste un arbore de intervale. Primul nivel al arborelui va contine toate coordonatele $x$. Cei doi fii ai lui vor contine prima jumatate, respectiv a doua jumatate a punctelor (sortate dupa coordonata $x$) si asa mai departe. Pentru fiecare interval de coordonate $x$, se mentin sortate coordonatele $y$ corespunzatoare punctelor care au coordonatele $x$ in intervalul respectiv. Astfel, memoria folosita este $O(N * log{~2~}N)$. Pentru a construi efectiv se foloseste o abordare asemanatoare algoritmului de sortare prin interclasare: in fiecare nod, pentru a obtine lista de coordonate $y$ ordonate, se interclaseaza listelele celor doi fii (deja ordonate). Cand se ajunge intr-o frunza, lista nodului este formata dintr-un singur punct.\r\n\r\np=. !arbori-de-intervale?figure6.jpg!\r\n\r\np<>. Pentru fiecare dreptunghi, se executa cautarea in arborele de intervale pentru segmentul $[x1, x2]$ (deoarece se folosesc doar cele $N$ coordonate $x$ ale punctelor, se vor potrivi capetele acestui interval folosind cautarea binara la cea mai apropiata coordonata $x$ de fiecare capat). Pentru fiecare interval din arbore atins, se executa doua cautari binare printre coordonatele y corespunzatoare coordonatelor x din acel interval, pentru a determina cate puncte din intervalul respectiv se afla in intervalul $[y{~1~}, y{~2~}]$ (adica in interiorul dreptunghiului).\r\n\r\np<>. Complexitatea $O(log{~2~}^2^ N)$ poate fi redusa, folosind o metoda descoperita independent de Willard si Lueker in anul $1978$. Se observa ca pentru fiecare coordonata $y$ dintr-un nod, daca presupunem ca se efectueaza o cautare binara, atunci putem determina in timpul interclasarii pozitia din fiecare fiu pe care o va returna cautarea binara pentru aceeasi valoare. Este evident ca pentru o valoare $y$ dintr-un nod care a provenit dintr-un fiu in timpul interclasarii, exista o unica valoare maxima $y\'$ din celalalt fiu astfel incat $y\' &le; y$. Asadar, tinem pentru fiecare valoare $y$ dintr-un nod doi indici care identifica pozitiile corespunzatoare efectuarii unei cautari binare in fii pentru valoarea $y$. Astfel, in timpul cautarii, in loc sa se efectueze cautari binare, se pot parcurge acesti indici, care ofera in $O(1)$ pozitia in lista cautata, reducand complexitatea totala la $O(log{~2~} N)$.\r\n\r\np=. !arbori-de-intervale?figure7.jpg!\r\n\r\nh2. Probleme propuse \r\n\r\nh3. 1. Preluata de la Olimpiada Baltica de Informatica, Polonia  2001\r\n\r\np<>. Se considera $N &le; 50 000$ dreptunghiuri in plan, fiecare avand laturile paralele cu axele $OX$, $OY$. Sa se calculeze aria ocupata de reuniunea celor $N$ dreptunghiuri. \r\n\r\np<>. In fisierul $_drept2.in_$ se gaseste pe prima linie numarul $N$ de dreptunghiuri, iar pe fiecare din urmatoarele $N$ linii cate patru numere naturale mai mici ca $50 000$, reprezentand coordonatele carteziene ale coltului stanga sus, respectiv dreapta jos ale fiecarui dreptunghi. Rezultatul se va scrie in fisierul $_drept2.out_$.\r\n\r\np<>. _Timp maxim de executie: $1 secunda/test$_.\r\n\r\nh3. 2. Preluata de la Olimpiada Nationala de Informatica, Polonia 2001\r\n\r\np<>. Se considera $N &le; 50 000$ puncte in plan de coordonate numere naturale mai mici ca $50 000$. Sa se determine unde se poate aseza un dreptunghi de lungime $DX$ si latime $DY$ astfel incat numarul de puncte incluse in dreptunghi sa fie maxim.\r\n\r\np<>. In fisierul $_puncte.in_$ se gasesc pe prima linie numerele $N$, $DX$ si $DY$. Pe urmatoarele $N$ linii se gasesc coordonatele punctelor. In fisierul $_puncte.out_$ se vor gasi cinci numere naturale reprezentand coordonatele colturilor stanga sus si dreapta jos ale asezarii dreptunghiului si numarul maxim de puncte din dreptunghi.\r\n\r\np<>. _Timp maxim de executie: $1 secunda/test$_.\r\n\r\nh3. 3. Preluata de la Barajul pentru Lotul National, Romania 2003\r\n\r\np<>. Se considera $N &le; 100 000$ puncte in plan de coordonate numere naturale mai mici ca $100 000$. Sa se determine unde se pot aseza doua dreptunghiuri de lungime $DX$ si latime $DY$, fara sa se intersecteze, astfel incat numarul de puncte incluse in cele doua dreptunghiuri sa fie maxim. \r\n\r\np<>. In fisierul $_puncte2.in_$ se gasesc pe prima linie numerele $N$, $DX$ si $DY$. Pe urmatoarele $N$ linii se gasesc coordonatele punctelor. In fisierul $_puncte2.out_$ se vor gasi $9$ numere naturale reprezentand coordonatele colturilor stanga sus si dreapta jos ale asezarii primului dreptunghi, respectiv a celui de-al doilea, cat si numarul maxim de puncte incluse in ambele dreptunghiuri.\r\n\r\np<>. _Timp maxim de executie: $1 secunda/test$_.\r\n\r\nh3. 4. Preluata de la concursul international USACO January Open, 2004\r\n\r\np<>. Se considera $N &le; 250 000$ dreptunghiuri in plan, fiecare avand laturile paralele cu axele $OX$, $OY$, care nu se intersecteaza si nu se ating, dar pot fi incluse unul in altul. Se numeste \"inchisoare\" un dreptunghi inconjurat de alte dreptunghiuri. Sa se determine numarul maxim de dreptunghiuri de care poate fi inconjurata o \"inchisoare\" si cate astfel de \"inchisori\" maxime exista. \r\n\r\np<>. In fisierul $_inchis.in_$ se gaseste pe prima linie numarul $N$ de dreptunghiuri, iar pe fiecare din urmatoarele $N$ linii cate patru numere naturale mai mici ca $1 000 000 000$, reprezentand coordonatele carteziene ale coltului stanga sus, respectiv dreapta jos ale fiecarui dreptunghi. In fisierul $_inchis.out_$ se gasesc doua numere naturale: numarul maxim de dreptunghiuri de care poate fi inconjurata o \"inchisoare\" si cate astfel de \"inchisori\" maxime exista. \r\n\r\np<>. _Timp maxim de executie: $1 secunda/test$_.\r\n\r\nh3. Nota\r\n\r\np<>. Au fost adaugate si implementarile in limbaj Pascal, C ale catorva dintre problemele explicate in articol. Acestea pot fi accesate prin intermediul optiunii \"Listeaza atasamente\".',2044,'public',3689,NULL),('planificare/sedinta_20070424','Sedinta 2007-04-24','2007-04-24 14:28:52','2007-04-26 17:56:40','h1. Sedinta 2007-04-24\r\n\r\n_ora 18:30, la Cafenescu_\r\n\r\nh2. Participanti\r\n\r\n* Crestez Leonard\r\n* Cristian George Strat\r\n* Mircea Pasoi\r\n* Diaconu Adrian\r\n* Silviu Ganceanu\r\n* Valentin Stanciu\r\n* Adrian Vladu\r\n\r\nh2. Agenda\r\n\r\n_Imi cer scuze pentru aceasta agenda IMENSA! Am detaliat mult mai mult decat este necesar._\r\n\r\n# Asociatia infoarena\r\n## scopul Asociatiei infoarena\r\n## statut, structura si roluri\r\n## desfasurarea sedintelor, luarea deciziilor\r\n### frecventa\r\n### conferinte by net\r\n## lista cu membri consilieri\r\n## despre motivatie si voluntariat\r\n### ce are de oferit infoarena\r\n### ce vrem si ce planuri avem noi in raport cu infoarena\r\n### cum recrutam oameni noi\r\n# preONI\r\n## cum vrem sa fie preONI 2007?\r\n### numar participanti\r\n### premii\r\n### numar de probe, probleme, grupe\r\n### conditii cazare\r\n### dotare\r\n## ce stiu de la Emil\r\n### intre 1 si 10 iunie\r\n### poate acoperi costurile pentru 30 persoane x 3 zile\r\n### se va organiza cel mai probabil la Panciu sau Vidra\r\n### va *incerca* sa ne asigure internet\r\n### este loc si de mai multe persoane dar suntem pe barba noastra\r\n## alternative\r\n## grafic desfasurare (sesiune, terminarea anului scolar, bac, lot etc.)\r\n## plan cheltuieli\r\n## sponsori\r\n### Mircea are o idee\r\n### HOSTWAY e in deliberare, nu e de bine\r\n# Fonduri\r\n## o problema importanta, necesita o solutie permanenta\r\n### donatii din partea companiilor\r\n#### companii la care avem contacte\r\n#### companii la care avem acces prin membrii nostri\r\n### donatii din partea utilizatorilor si a persoanelor fizice\r\n#### 2% din impozit pe salar\r\n#### prin card\r\n#### prin banca\r\n#### micro payments (SMS / MMS cu rating badge :)\r\n### cursuri platite\r\n### research\r\n### job board\r\n### advertising\r\n## plan de atac\r\n# Proiecte curente\r\n## despre sectiunea \'implica-te\'. Ce e de imbuntatit?\r\n## infoarena software development\r\n### ce ne trebuie pentru preONI\r\n## Extinde arhiva\r\n## Scrie articole\r\n## Imbunatatire teste probleme\r\n## Raspandeste vestea\r\n### despre 648.ro\r\n# Propuneri proiecte noi\r\n## cursuri platite\r\n## job board\r\n## infoarena screencasts\r\n## cursuri video\r\n# Strategie si planificare pe termen mediu\r\n## Obiective pentru urmatorul an\r\n## Ce se intampla la vara?\r\n\r\n\r\n\r\nh2. Rezolutii aprobate\r\n\r\nh3. Asociatia infoarena\r\n\r\n* Cristi se ocupa de activarea contului in banca si de facut stampila.\r\n* Scopul infoarena se extinde\r\n** la studenti\r\n** la professionals: Desi vom aborda si chestiuni mai tehnice / practice, ne vom feri de trivialitati precum tutoriale de folosit tehnologia X.\r\n* Consiliul director se va intruni live cel putin o data pe luna.\r\n* *Se desemneaza urmatorii consilieri (activi)*:\r\n** Valentin Stanciu\r\n** Adrian Diaconu\r\n** Vladu Adrian\r\n** Pasaila Daniel\r\n** Buruiana Filip\r\n* *Se desemneaza urmatorii consileri emeritus*:\r\n** Negruseri Cosmin\r\n** Florea Tiberiu\r\n* Vali invita un om de PR la urmatorul meeting.\r\n* Se propun spre recrutare: wefgef, gcomin, airinei, pauldb, bogdan, dumitru, marmota, valentin bora, alex tandrau.\r\n* Cristi va scrie un letter oficial de invitatie. Silviu se ocupa de inmanarea (transmiterea) invitatiilor.\r\n\r\nh3. preONI 2007\r\n\r\n* se desfasoara intre 1 si 10 iunie\r\n* Mircea face planul de cheltuieli\r\n* Cautam sponsorizare la\r\n** Oracle, prin Mircea\r\n** Hostway, prin Cristi\r\n** intel, Mircea va da telefon si va intreba daca sunt interesati, Cristi e dispus sa poarte discutiile cu ei.\r\n** Emil\r\n* fond minim de premii: 1800 lei\r\n\r\nh3. Fonduri\r\n\r\n* Cristi face research pe legea cu 2%\r\n* Silviu face copy la contact companii prin membri\r\n* 648 va face logo+tricou, pe care il putem folosi la strangere fonduri\r\n\r\nh2. Note remarcabile\r\n\r\nh3. Asociatia infoarena\r\n\r\n* De studiat cazul in care un consilier nu poate sa se prezinte in persoana la sedinte. Cum vor vota?\r\n* Ce ofera infoarena celor care se implica?\r\n** ocazia de a invata pe altii ce stii\r\n** pe partea de software development, ai ocazia sa inveti sa programezi\r\n** autoritate si posibilitatea de a dezvolta proiecte proprii\r\n** special perks: free drinks\r\n** ca regula generala, ii putem pune in contact cu mentori. Pe partea de info, mentorii suntem noi B-) insa pentru alte domenii, precum PR, putem sa le platim participarea workshop-uri, training-uri, conferinte samd. (e si un mod de a filtra oamenii buni si talentati de cei care pur si simplu vor niste bani).\r\n* Vom recruta oameni pentru echipa infoarena (nu doar de informatica) in mod activ.\r\n* Il trimitem pe Leo la InfoEducatie\r\n\r\nh3. preONI 2007\r\n\r\n* Varianta pe care ne-o dorim:\r\n** 50 participanti (10+11+10+noi10+profi9)\r\n** 1 proba\r\n** 3 zile\r\n** internet, tastaturi si mice standard \r\n** cel putin ca anul trecut\r\n* alternativa\r\n** locatie Bucuresti\r\n** 25 participanti\r\n** laborator turci\r\n** trebuie sa-l facem in weekend\r\n** cazare la internate (gen Nichita Stanescu). Pret de la 35 lei in sus.\r\n',13,'public',NULL,NULL),('utilizator/marcelcodrea','Profil marcelcodrea','2006-11-24 21:04:57','2009-03-12 17:05:07','== include(page=\"template/noprofile\") ==\r\n\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distictii primite\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n\r\n\r\n',3680,'protected',NULL,NULL),('utilizator/danciac','Profil danciac','2007-04-26 13:56:24','2007-04-26 13:56:24','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6483,'public',NULL,NULL),('template/meeting-under-construction','template/meeting-under-construction','2007-04-26 18:08:02','2008-02-04 20:59:57','table{margin:0.5em auto;}. |={background-color:#FDD017;border:1px solid #F88017;}. !<template/todo?progress.gif! *Detaliile acestei intalniri NU au fost stabilite. Lista de invitati este orientativa. Agenda este in constructie. Daca vrei sa propui un subiect spre discutie, adauga-l in agenda.* |\r\n\r\n',1,'protected',NULL,NULL),('simulare-27-04-2007','Probleme simulare','2007-04-26 20:47:09','2007-04-27 06:24:52','* \'Salvare\':simulare-27-04-2007?salvare.htm\r\n* \'Zapezi\':simulare-27-04-2007?zapezi.html\r\n* \'Cabane\':simulare-27-04-2007?cabane.doc\r\n\r\nBackup:\r\n\r\n* \'Ajutor\':simulare-27-04-2007?ajutor.doc\r\n* \'Galerie\':simulare-27-04-2007?galerie.doc\r\n',1,'public',NULL,NULL),('template/noprofile','template/noprofile','2006-11-26 22:20:18','2008-02-04 20:59:22','&nbsp;\r\n\r\ntable{margin:0.5em auto;}. |={background-color:#CCCCFF;border:1px solid #3366CC;}. !{vertical-align:middle;}template/noprofile?wrench.png! _Acest utilizator nu si-a personalizat inca pagina de profil._ \'*Click aici*\':documentatie/pagina-de-profil _sa afli cum iti poti personaliza pagina de profil._ |',1,'protected',NULL,NULL),('blog/algoritmiada-in-cautare-de-sigla','Algoritmiada in cautare de sigla','2008-12-01 07:21:26','2008-12-01 08:29:39','Anul acesta am decis sa facem putin rebrading si sa schimbam formatul concursului principal organizat de infoarena care pana acum s-a numit preOni. Noul nume ales este Algoritmiada. Mai avem putin timp pana la inceperea rundelor si nu avem inca o sigla. Ca si \'anul trecut\':http://infoarena.ro/blog/preoni-2008-in-cautare-de-sigla facem apel la comunitate pentru a gasi o sigla misto.',2028,'protected',3422,NULL),('winter-challenge-1/solutii','Winter Challenge, Solutii','2007-02-11 20:45:38','2008-08-14 19:06:30','h1. Solutii\r\n\r\nIn numele echipei Winter Challenge 2007 felicit toti participantii si le urez succes in viitoare confruntari. Totodata, tin sa multumesc lui Mugurel Ionut Andreica si lui Sorin Stancu-Mara pentru ca au acceptat sa propuna subiecte alaturi de mine. Nu in ultimul rand multumesc intregii \"echipe infoarena\":echipa-infoarena pentru suportul tehnic acordat si ii rog sa ma ierte daca i-am stresat (prea tare).\r\n\r\nMult noroc in continuare, \r\nBogdan A. Stoica\r\n\r\nh2. Chiftea \r\n\r\nh3. problema usoara, clasele 9-10\r\n\r\nVom nota cu P{~k~}, perimetrul minim al figurii ce contine $k$ patratele de latura unitate. In mod evident, acesta depinde numai de patratelele ce formeaza marginea figurii.\r\nVom trata intai cazul in care $N$ este patrat perfect pornind de la $N = 1$, cu $P{~1~} = 4$. Pentru $N = 4$, construind toate figurile posibile se observa ca cea de perimetru minim are forma unui patrat cu latura $2$, deci $P{~4~} = 4*2 = 8$. Continuand procedeul, se demonstreaza cu ajutorul principiului inducitei matematice ca $P{~t~} = 4*[radical(t)]$ (cu $[x]$ s-a notat partea intreaga a lui $x$), oricare ar fi $t$ patrat perfect.\r\nPentru al doilea caz, cel in care $N$ nu este patrat perfect, figura noastra porneste tot de la un patrat de latura $[radical(N)]$. Este evident faptul ca pentru ca $P{~N~}$ sa fie minim, trebuie sa avem cat mai putine patratele (pe margine) carora li se aduna mai mult de o latura la perimetru (cu alte cuvinte trebuie sa avem cat mai putine patratele care sa formeze colturi). Va trebui, deci, sa adaugam pe marginile patratului format $N-[radical(N)]*[radical(N)]$ patratele. Astfel solutia devine $4*[radical(N)]$ pentru $N$ patrat perfect, $4*[radical(N)]+2$ pentru cazul in care acoperim maxim o latura cu patratele sau $4*[radical(N)]+4$ pentru cazul in care acoperim maxim 2 laturi cu patratele.\r\nO solutie care calcula aceste valori in O({$N$}) nu ar fi obtinut punctaj maxim.\r\n\r\nh2. Mall \r\n\r\nh3. problema medie, clasele 9-10\r\n\r\nCalculam $A[i, j]$ = castigul maxim pe care-l obtine Varu daca repartizeaza $j$ ingrijitori primelor $i$ firme, unde \r\n$A[i, j]$ = $maxim(A[l, j-k]+Castig[l, k])$ ({$0 < l < i$}, {$0 &le; k &le; j$}), unde $Castig[i, j]$ = castigul pe care-l obtine Varu de la firma $i$ daca acesteia ii repratizaza exact $j$ ingrijitori. \r\nO solutie care calcula in O({$N^4^$}) aceasta recurenta ar fi obtinut $16$ puncte.\r\nO solutie care calcula in O({$N^3^$}), folosind matricea $V[i, j]$ = $maxim(A[k, j]+Castig[k, j])$ ({$0 <  k < i$}), obtinea $32$ de puncte.\r\nO solutie care calcula in O({$N^2^$}), folosind un deque ce calcula in O({$1$}) maximul (pentru linia $i$ si coloana $j$) dintre $V[i, 1]$, $V[i, 2]$, ..., $V[i, j-1]$, obtinea $100$ de puncte.\r\n\r\nh2. Smen \r\n\r\nh3. problema grea, clasele 9-10 - problema medie, clasele 11-12\r\n\r\nIncepem prin a normaliza toate numerele din sir si pe $A$ si $B$, adunand tuturor valoarea $200$. Astfel vom lucra numai cu numere pozitive. Apoi problema se rezolva prin programare dinamica. Sortam in ordine crescatoare elementele si apoi calculam $A[i, j, k]$ = numarul minim de operatii ce se efectueaza asupra primelor $i$ numere a.i. sa obtinem exact $j$ elemente distincte iar ultimul element sa nu depaseasca valoarea $k$. \r\n$A[i, j, k]$ se poate obtine ca fiind maximul dinntre:\r\n\r\n# $A[i-1, j, k-1]$ + $|Val_initiala[i]-k|$ (daca vrem ca valoarea initiala a celui de-al $i$-lea element sa fie $k$, dar sa nu-mi creeze un alt element distinct).\r\n# $A[i-1, j-1, k-1]+|Val_initiala[i]-k|$ (daca vrem ca valoarea initiala a celui de-al $i$-lea element sa fie $k$ si sa-mi creez inca un element dinstinct)\r\n# $A[i-1, j, k-1]$ (nu cresc nici valoarea elementului $i$, nici numarul de elemente distincte)\r\n\r\nPentru reconstituire vom lucra cu o matrice $B[i, j, k]$ care ia valori din multimea {$0$, $1$, $2$}, semnificand conditia din care a provenit starea ({$i$}, {$j$}, {$k$}). Se observa ca aceasta solutie ar fi obtinut foloseste foarte multa memorie (O({$N*K*$}({$B$}-{$A$})) si ar fi obtinut doar $40%$ din punctaj.\r\n\r\nSolutia $100$ de puncte incepe prin a observa ca, la un pas, nu sunt folosite decat \"linia\" curenta si \"linia\" anterioara din matricea $A$. Pentru reconstituire se poate folosi urmatorul smen: retinem din $14$ in $14$ \"linii\" informatiile din matricea $A$ (cea de la prima solutie), adica $R[1, j, k]$ =  {$A[1, j, k]$} ({$1 &le; j &le; K$} si {$A+200 &le; k &le; B+200$}), $R[2, j, k]$ = $A[15, j, k]$ ({$1 &le; j &le; K$} si {$A+200 &le; k &le; B+200$}), $R[3, j, k]$ = $A[29, j, k]$ ({$1 &le; j &le; K$} si {$A+200 &le; k &le; B+200$}), etc. Dupa ce am completat matricea $R$, reluam dinamica de la coada la cap si ne vom folosi doar de matricea $R$. Astfel la pasul $i$ vom reconstitui doar liniile care se afla intre liniile $R[i, j, k]$ si $R[i-1, j, k]$ ({$1 &le; j &le; K$} si {$A+200 &le; k &le; B+200$}), adica intre ({$i-1$})*{$14+1$} si $i*14+1$ in matricea de la prima solutie. Astfel o sa avem o memorie de O({$14*K*$}({$B$}-{$A$})).\r\n\r\nO alta solutie care obtinea punctaj maxim este transformarea problemei intr-una de cuplaj de cost minim. Cele doua multimi de noduri se construiau in felul urmator: prima multime era reprezentata de sirul initial, iar cea de-a doua era reprezentata de valorile intregi cuprinse in intervalul $[A, B]$. Se introduc $N*$({$B-A$}) muchii de capacitate $1$, o muchie de la un nod ce leaga elementul $X$ din prima multime si elementul $Y$ din a doua multime avand costul $|X-Y|$. Prima multime se leaga de o sursa fictiva prin muchii de cost $0$ si capacitate $1$, iar cea de-a doua multime de o destinatie fictive prin muchii de cost $0$ si capacitate $1$. Tinandu-se cont ca in destinatie trebuie sa se obtina fluxul minim $K$, se aplica acest algoritm avand grija sa minimizam costul.\r\n\r\nh2. Fear \r\n\r\nh3. problema usoara, clasele 11-12\r\n\r\nIn ciuda proprietatii un pic nenaturale care priveste valoarea fricii dintr-o intersectie, problema se reduce la aflarea fluxului maxim avand orasul $1$ ca sursa si orasul $N$ ca destinatie. Pentru realizarea acestui lucru vom logaritma (in baza $2$, $e$ sau $10$) costurile muchiilor ce se dau in fisierul de intrare. Dintre toate aceste noi costuri o vom lua pe cea maxima ({$vmax$}). Algoritmul va fi urmatorul: \r\n\r\n# vom trimite frica (din orasul $1$) cu o valoare $V$ (initial, $V$ = $vmax$) pana cand frica nu va mai putea ajunge la destinatie. \r\n# injumatatim pe $V$ si reluam algoritmul de la pasul $1$.\r\n\r\nAceasta metoda poarta denumirea de \"Flux maxim prin scalare\". O alta abordare care ar fi mers la fel de bine este cea folosind algoritmul de flux maxim Ford Fulkerson.\r\n\r\nh2. Doipe \r\n\r\nh3. problema grea, clasele 11-12\r\n\r\n	Prima solutie corecta este de complexitate O(N*2^N^). Se calculeaza o matrice $P[i, R]$ = numarul de permutari cu $i$ elemente, care respecta sirul de relatii $R$ ({$R$} este un numar binar de $i - 1$ biti, care codifica un sir de relatii). Putem calcula aceste valori pe baza valorilor calculate pentru $P[i - 1, R\']$, variind pozitia in care este asezat in cadrul permutarii cel de-al $i$-lea element. Aceasta solutie nu se incadreaza, insa, nici in limita de timp, nici in cea de memorie.\r\n	Ideea solutiei de punctaj maxim este urmatoarea: Vom calcula $P[i, j]$ = numarul de permutari ale multimii {{$1$},{$2$},..,{$i$}} care respecta primele $i-1$ relatii ale sirului de relatii si in care ultimul numar al permutarii este numarul $j$. In mod evident, rezultatul dorit va fi dat de suma $P[N, 1]$ + $P[N, 2]$ + ... + $P[N, N]$.\r\n	Pentru calculul lui $P[i, j]$ vom observa ca, eliminand numarul $j$ din permutare, obtinem $i-1$ numere distincte care pot fi renumerotate pentru a forma o permutare a multimii {{$1$},{$2$},..,{$i-1$}}. Mai exact, orice numar $x$ mai mare decat $j$ este renumerotat cu valoarea $x-1$. In conditiile acestei renumerotari, avem urmatoarele $2$ cazuri:\r\n\r\n* daca relatia $i-1$ este \"$<$\", atunci $P[i, j]$ = $P[i-1, 1]$ + $P[i-1, 2]$ + ... + $P[i-1, j-1]$\r\n* daca relatia $i-1$ este \"$>$\", atunci $P[i, j]$ = $P[i-1, j]$ + $P[i-1, j+1]$ +... + $P[i-1, i-1]$\r\n\r\nCazul \"de baza\" este $P[1, 1]$ = $1$. Relatiile date sunt corecte, deoarece pentru orice permutare ce corespunde lui $P[i-1, x]$ se poate aplica operatia de renumerotare inversa (relativ la $j$), obtinand un sir de $i-1$ numere distincte din multimea {{$1$},{$2$},..,{$i$}}\\{{$j$}} care respecta primele $i-2$ relatii. La sfarsitul acestui sir se poate adauga numarul $j$, obtinand o permutare cu $i$ elemente care respecta primele $i-1$ relatii.\r\n	Implementarea imediata a relatiilor de recurenta mentionate se poate realiza foarte usor in complexitate O({$N^3^$}). Memorand sumele partiale $SP[x]$ = $P[i-1, 1]$ + $P[i-1, 2]$ + ... +  {$P[i-1, x]$} putem calcula $P[i, j]$ in timp O({$1$}), reducand complexitatea la O({$N^2^$}).\r\n',6756,'public',NULL,NULL),('template/newsletter/doi-la-suta-call','template/newsletter/doi-la-suta','2009-04-01 16:19:12','2009-04-01 16:26:15','h2{font-size: 12pt}. Sprijină Asociaţia infoarena!\r\n\r\nConform \'Codului Fiscal\':http://www.edex.ro/articol_cod_fiscal_16661_Art.%2084:%20Stabilirea%20si%20plata%20impozitului%20pe%20venitul%20net%20anual%20impozabil.html, ai dreptul să direcţionezi către Asociaţia infoarena 2% din impozitul pe venit datorat la stat. Aceste contribuţii ne ajută enorm să ne desfăşurăm activitatea. În plus, ne bucurăm să vedem că munca pe care o depunem este apreciată.\r\n\r\nProcedura este simplă si nu te costă nimic!\r\n\r\n&rarr; \'*Vezi cum se face*\':doi-la-suta\r\n\r\nTermenul limită este *15 mai 2009*.\r\n',13,'protected',NULL,NULL),('utilizator/dastas','Profil Dastas','2006-11-24 21:07:26','2007-05-14 16:53:28','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite:\r\n\r\n* _Campion pe sate_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',4603,'protected',NULL,NULL),('blog/648-sustine-infoarena','648 sustine infoarena','2007-05-24 08:57:53','2007-05-24 08:59:12','Dorim sa multumim agentiei de web SixtyFourEights Group (\'www.648.ro\':http://www.648.ro/) pentru realizarea \'acestor materiale grafice\':materiale-promotionale menite sa ajute la dezvoltarea comunitatii infoarena.\r\n\r\nbq. infoarena are un rol deosebit in mobilizarea tinerilor informaticieni si de aceea ne face placere sa sustinem aceasta initiativa.\r\nEste o oportunitate pentru toti cei care doresc sa isi creasca performantele si sa aiba o baza fundamentata inainte de a incepe lucrul intr-o companie IT.\r\n\r\nbq. 648 isi propune sa creasca nivelul produselor de web romanesti prin implicarea comunitatilor de dezvoltatori. Ne plac oamenii motivati, care doresc sa inoveze si ii incurajam sa progreseze. Cresc si ei, crestem si noi.\r\n\r\np. \'648 Group\':http://www.648.ro/\r\n',13,'protected',NULL,NULL),('materiale-promotionale','Materiale promotionale','2007-05-24 09:02:05','2009-02-06 08:24:48','h1. Materiale promotionale\r\n\r\nPe aceasta pagina vom pune materiale promotionale pe care le puteti folosi sa promovati infoarena in scoala, in cluburi sau in randul prietenilor.\r\n\r\n\r\ntable{width: auto; vertical-align: top}. | \'!materiale-promotionale?concept-afis.jpg 200x200!\':materiale-promotionale?concept-afis.jpg | Concept afis infoarena \r\nAutor: \'648 Group\':http://www.648.ro/ |\r\n| \'Coiful infoarena\':materiale-promotionale?coif-infoarena-transparent.png | Autor: Dan Burzo |\r\n| \'Sigla infoarena, fundal transparent\':materiale-promotionale?sigla-infoarena-fundal-transparent.png | Autor: Dan Burzo |\r\n',2044,'public',NULL,NULL),('utilizator/hardvirus','Profil hardvirus','2007-05-25 07:21:11','2007-05-27 18:52:52','== include(page=\"template/noprofile\") ==\r\n\r\nDespre mine\r\n\r\nSalut!Sunt Ardelean Horia elev in clasa a 7-a la Colegiul National Dragos-Voda din Sighetu Marmatiei.Am studii in turbo pascal,profesorul meu pregatitor e Raluca Bobosan\r\n\r\nDistinctii primite\r\n\r\nLocul 27 la ONI 2005 in clasa a 5-a,locul 34 la ONI 2006,locul 4 la concursul centrelor de excelenta\r\n2007\r\n\r\nPrieteni pe infoarena\r\n\r\nDeocamdata nu stiu pe nimeni dar vreau sa va cunosc.\r\n',6569,'public',NULL,NULL),('asociatia-infoarena','Asociatia infoarena','2006-11-27 07:21:15','2008-03-14 09:21:33','h1. Asociatia infoarena\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nAsociatia infoarena este o organizatie non-profit si ofera comunitatii infoarena personalitate juridica. Asociatia infoarena ne ajuta sa&hellip;\r\n\r\n* protejam drepturile de autor ale materialelor contribuite de comunitate. Cu exceptia cazurilor in care se specifica altfel, continutul infoarena apartine Asociatiei infoarena si poate fi distribuit sub licenta \'Creative Commons Attribution-NonCommercial 2.5\':http://creativecommons.org/licenses/by-nc/2.5/.\r\n* protejam brand-ul infoarena\r\n* rasplatim cei mai activi membri ai comunitatii - pentru timpul pe care l-au investit, acestia primesc functii oficiale si drept de vot in Adunarea Generala.\r\n* obtinem sponsorizari din partea companiilor private\r\n\r\nh2. Membri\r\n\r\nVezi \'echipa infoarena\':echipa-infoarena si \'colaboratori\':colaboratori.\r\n\r\nh2(#date). Date\r\n\r\n* CUI: 2175&nbsp;2294\r\n* Cont RON\r\n** IBAN: RO15&nbsp;RZBR&nbsp;0000&nbsp;0600&nbsp;0919&nbsp;4268\r\n** Deschis la: Raiffeisen, Ag. Unirea, Bucuresti\r\n* Adresa sediu social: Str. Dragos Voda Nr. 49, Bl. P9, Ap. 11, Barlad, Jud. Vaslui\r\n\r\nh2. Documente\r\n\r\n* \'Statutul Asociatiei infoarena\':asociatia-infoarena?statut.pdf\r\n* \'Actul constitutiv al Asociatiei infoarena\':asociatia-infoarena?act-constitutiv.pdf\r\n\r\nIntrucat asociatia este proaspat infiintata (aprilie 2007), nu avem inca bilanturi sau declaratii financiare de publicat.',13,'protected',NULL,NULL),('runda/preoni2007_runda5_11-12','runda/preoni2007_runda5_11-12','2007-06-24 18:33:54','2007-06-24 18:33:54','Scrie aici despre runda/preoni2007_runda5_11-12',986,'public',NULL,NULL),('preoni-2007/runda-finala/regulament','Finala preONI 2007, Bucuresti, Regulament','2007-06-22 11:09:32','2007-06-23 20:39:18','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2007/runda-finala\r\n* \'Program\':preoni-2007/runda-finala/program\r\n*(active) \'Regulament\':preoni-2007/runda-finala/regulament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-finala/9\r\n\r\nh1. Finala preONI 2007, Bucuresti, Regulament\r\n\r\nParticipantii la runda finala - atat cei calificati in finala de la Bucuresti cat si cei care participa online - se obliga sa respecte \'regulamentul concursului preONI\':preoni-2007/regulament.\r\n\r\nIn plus, finala de la Bucuresti se desfasoara sub urmatoarele reguli:\r\n\r\n* Concurentii vor fi prezenti in salile de concurs la orele anuntate\r\n* Fiecare concurent va primi subiectele in forma listata si foi pentru ciorne (pix nu este inclus)\r\n* Timp de 1 ora dupa primirea subiectelor concurentii pot formula intrebari referitoare la enunturile problemelor; intrebarile se vor formula in scris, pe foaia cu intrebari fiind precizate numele problemei si al concurentului; modalitate de formulare a intrebarile este identica cu cea de la primele 4 runde\r\n* In timpul probelor de concurs, concurentii:\r\n** nu vor avea asupra lor telefoane mobile sau alte mijloace de comunicatie\r\n** nu vor utiliza suporturi externe proprii (dischete/CD/flash-disk)\r\n** nu vor utiliza alte surse de documentare decat cele prezente pe calculator\r\n** nu vor incerca sa interfereze in nici un mod cu activitatile altui concurent\r\n** nu vor deteriora mediile de lucru\r\n** nu vor incerca sa interfereze cu sistemul de evaluare\r\n* In programele concurentilor nu sunt permise urmatoarele:\r\n** schimbarea drepturilor de acces la fisiere\r\n** atacul asupra securitatii sistemului sau evaluatorului\r\n** accesarea informatiilor despre sistemul de fisiere\r\n** executarea unor alte programe\r\n\r\nOrice incercare de frauda sau de a sabota desfasurarea corecta a concursului va fi urmata imediat de eliminarea elevului respectiv din concurs, cat si de pe _infoarena_.\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('runda/preoni2007_runda5_10','runda/preoni2007_runda5_10','2007-06-25 06:01:02','2007-06-25 06:01:08','Scrie aici despre runda/preoni2007_runda5_10',6502,'public',NULL,NULL),('preoni-2007/runda-finala/program','Finala preONI 2007, Program de desfasurare','2007-06-22 11:11:10','2007-06-23 20:39:31','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2007/runda-finala\r\n*(active) \'Program\':preoni-2007/runda-finala/program\r\n* \'Regulament\':preoni-2007/runda-finala/regulament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-finala/9\r\n\r\nh1. Finala preONI 2007, Bucuresti, Program de desfasurare\r\n\r\nProgramul de mai jos este deschis la sugestii si se poate modifica pe parcursul desfasurarii concursului.\r\n\r\ntable{width:50%}. |_. Data |_. Activitati |\r\n| Duminica, 24 iunie 2007 | * 12:00 - 18:00 Sosire si cazare participanti la internatul \'ICHB\':http://www.ichb.ro/\r\n* 18:00 - 19:00 Deschidere oficiala\r\n* 19:00 - 20:00 Cina\r\n* 20:00 - 21:00 Acomodare, testarea statiilor de lucru |\r\n| Luni, 25 iunie 2007 | * 08:00 - 08:30 Mic dejun\r\n* *09:00 - 14:00 Proba de concurs*\r\n* 14:00 - 15:00 Pranz\r\n* 16:00 - 17:00 Evaluare live (pe retroproiector)\r\n* 17:00 - 19:00 Seminar despre infoarena\r\n* 19:00 - 20:00 Festivitatea de premiere\r\n* 20:00 - 21:00 Cina\r\n* 21:00 - ... Party :) | \r\n| Marti, 26 iunie 2007 | * 08:00 - 09:00 Mic dejun\r\n* Plecare |\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'protected',NULL,NULL),('template/preoni-2007/footer','template/preoni-2007/footer','2007-01-15 15:14:53','2007-06-22 17:01:50','h2. Sponsori\r\n\r\nOrganizarea finalei preONI este posibila datorita generosilor nostri sponsori:\r\n\r\n!{border: 1px solid silver}preoni-2007?hostway.png!:http://www.hostwaylab.ro/ !{border: 1px solid silver}preoni-2007?ichb.png!:http://www.ichb.ro/ !{border: 1px solid silver}preoni-2007?irealsoft.png!:http://www.irealsoft.ro/\r\n\r\n',13,'protected',NULL,NULL),('newsletter/preoni-2007-runda-finala','preONI 2007, Runda Finala','2007-06-22 20:48:17','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nSuntem bucurosi sa anuntam marea runda finala a concursului\r\npreONI 2007! Aceasta va incepe in curand, mai exact:\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Luni, 25 martie 2007, orele 09:00 - 14:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPagina rundei: \'preoni-2007/runda-finala\':preoni-2007/runda-finala\r\n\nFinala se desfasoara la Bucuresti, fiind gazduita de Liceul\r\nInternational de Informatica (www.ichb.ro). Aici au fost invitati\r\nprimii 10 de elevi clasati de la fiecare grupa.\r\n\nDesi batalia pentru premii se da intre concurentii de la finala,\r\n   >>> runda se va desfasura online si va fi deschisa tuturor <<<\r\nin stilul obisnuit infoarena.\r\nAi ocazia sa concurezi cot la cot cu cei din finala!\r\n\nInformatii suplimentare (comisii, intrebari, tutorial, cum particip)\r\ngasesti in pagina dedicata acestei runde:\r\n\np{padding-left: 1.5em;}. \'preoni-2007/runda-finala\':preoni-2007/runda-finala\r\n\np{padding-left: 1.5em;}. Multimim sponsorilor nostri!\r\n\np{padding-left: 0.5em;}. HOSTWAY Romania (\'http://www.hostwaylab.ro/\':http://www.hostwaylab.ro/)\r\n	ICHB            (\'http://www.ichb.ro/\':http://www.ichb.ro/)\r\n	iRealSoft       (\'http://www.irealsoft.ro/\':http://www.irealsoft.ro/)\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la aceasta runda iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te va aduce mai aproape de varful clasamentul.\r\n==NewsletterRating(username=\"%username%\")==\r\nRating-ul este un indicator al performantei tale in conditii de\r\nconcurs. Afla mai multe: \'documentatie/rating\':documentatie/rating\r\n\nIti tinem pumnii!\r\n\nh2.  Despre Runda Finala \n\nClasamentul complet, in urma celor 4 runde de calificare se gaseste\r\naici: \'preoni-2007/clasament/9\':preoni-2007/clasament/9\r\n\nFinalistii preONI sunt primii 10 clasati de la fiecare grupa. Acestia\r\nvor concura pentru premii in bani si obiecte, la Bucuresti. Felicitari!\r\n\np{padding-left: 1.5em;}. Clasa a IX-a (si gimnaziu)\r\n   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n    1  1100  Bogdan Tataroiu\r\n    2   620  Adriana Sperlea\r\n    3   415  Cezar Mocan\r\n    4   360  Ionescu Victor\r\n    5   357  Purice Andrei\r\n    6   331  Tudorica Constantin Alexandru\r\n    7   315  Victor Popescu\r\n    8   240  Adrian Velicu\r\n    9   235  Casu-Pop Bogdan\r\n   10   200  Parcalabescu Daniela Maria\r\n\np{padding-left: 1.5em;}. Clasa a X-a\r\n   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n    1  1110  Gheorghe Cosmin\r\n    2  574   Dragus Marius\r\n    3  384   Sanduleac Dan\r\n    4  330   Puni Andrei Paul\r\n    5  300   Savin Tiberiu\r\n    6  286   Duta Vlad\r\n    7  280   Chis Raoul\r\n    7  280   Ozorchevici Ana Maria\r\n    8  274   Achim Ioan Alexandru\r\n    9  270   Lica Adela\r\n    9  270   Victor Savu\r\n\np{padding-left: 1.5em;}. Clasele XI-XII\r\n   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n    1  668  Andrei Grigorean\r\n    2  655  Airinei Adrian\r\n    3  620  Cristina Stancu-Mara\r\n    4  610  Victor Rusu\r\n    5  596  Stefan Istrate\r\n    6  560  Sorin Fagateanu\r\n    7  510  Paul-Dan Baltescu\r\n    8  495  Alexandru Simion\r\n    8  495  Marius Stroe\r\n   10  475  Costea Andrei\r\n\nh2.  Mesaj din partea HOSTWAY Romania \n\np{padding-left: 1em;}. . De cand a aparut pe piata in Romania anul trecut, Hostway si-a\r\n  . dorit sa poata participa la un astfel de eveniment. Aceasta nu\r\n  . este doar o declaratie de complezenta, la noi in companie,\r\n  . creativitatea, dorinta de a invata si flexibilitatea abordarilor\r\n  . fiind incurajate si sustinute permanent.\r\n  .\r\n  . Hostway Romania are trei departamente \"de productie\":\r\n  . web development, web hosting, software research & development.\r\n  .\r\n  . [...]\r\n  .\r\n  . Fondata in 1998, Hostway este una dintre primele 5 companii de\r\n  . Hosting din lume, cu birouri in Illinois, Florida, Texas,\r\n  . Columbia, Anglia, Franta, Olanda, Belgia, Germania, Romania,\r\n  . Australia si India.\r\n  .\r\n  . Ne simtim onorati sa putem sprijini cea mai mare comunitate de\r\n  . programatori din tara, credem ca initiativa noastra va avea un\r\n  . impact pozitiv la dezvoltarea proiectului infoarena, si dorim sa\r\n  . ne implicam si in viitoarele initiative.\r\n  .\r\n  . Va dorim mult success in continuare!\r\n  .\r\n  . Flaviu Radulescu\r\n  . General Manager\r\n\nCiteste intregul mesaj si afla mai multe despre HOSTWAY Romania:\r\n\'preoni-2007/premii\':preoni-2007/premii\r\n\nh2.  Despre preONI \n\npreONI, concursul de marca al comunitatii infoarena, este dedicat\r\nelevilor de liceu ce se pregatesc pentru ONI (Olimpiada Nationala\r\nde Informatica).\r\n\npreONI se imparte in 3 grupe: clasa a IX-a si gimnaziu, clasa\r\na X-a si clasele XI-XII. Se organizeaza 4 runde online de calificare.\r\nIn urma acestora, cei mai buni de la fiecare grupa sunt invitati la\r\no runda finala.\r\n\nIn cadrul unei runde, vei avea de rezolvat 3 probleme in 4h.\r\nCastigatorii rundei finale sunt premiati cu bani si/sau obiecte.\r\n\nPe pagina concursului ( \'preoni-2007\':preoni-2007 ) vei gasi\r\ninformatii despre cum participi, cine propune probleme, premii si\r\nsponsori, regulamentul concursului samd.\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('newsletter/preoni-2007-runda-finala-rectificare','preONI 2007, Runda Finala - Rectificare','2007-06-23 13:33:41','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nS-a strecurat o greseala in ultimul e-mail.\r\nImi cer scuze pentru neatentie!\r\n\nIata rectificarea:\r\n\nProba de concurs a finalei preONI se desfasoara\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Luni, 25 iunie 2007, orele 09:00 - 14:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\n(adica peste 2 zile)\r\n\nViziteaza pagina rundei finale pentru mai multe informatii:\r\n\'preoni-2007/runda-finala\':preoni-2007/runda-finala\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('runda/preoni2007_runda5_9/clasament','Clasament preoni2007_runda5_9','2007-06-23 20:13:06','2007-06-23 20:13:06','h1. Clasament ==roundparam(round_id=\"preoni2007_runda5_9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda5_9\")==',1,'round: preoni2007_runda5_9',NULL,NULL),('preoni-2007/runda-finala/9','preONI 2007, Runda Finala, Clasa a 9-a si gimnaziu','2007-06-23 20:13:06','2007-06-25 10:41:47','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2007/runda-finala\r\n* \'Program\':preoni-2007/runda-finala/program\r\n* \'Regulament\':preoni-2007/runda-finala/regulament\r\n*(active) \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-finala/9\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda5_9\" param=\"title\") ==\r\n\r\n==roundregister(round_id=\"preoni2007_runda5_9\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nRunda se desfasoara *Luni 25 iunie*, la ora {*09^10^*} si va dura *{color:red}5h*.\r\nParticipantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2007/clasament/runda-finala/9.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda5_9\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'round: preoni2007_runda5_9',NULL,NULL),('runda/preoni2007_runda5_10/clasament','Clasament preoni2007_runda5_10','2007-06-23 20:19:14','2007-06-23 20:19:14','h1. Clasament ==roundparam(round_id=\"preoni2007_runda5_10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda5_10\")==',1,'round: preoni2007_runda5_10',NULL,NULL),('runda/preoni2007_runda5_11-12/clasament','Clasament preoni2007_runda5_11-12','2007-06-23 20:35:35','2007-06-23 20:35:35','h1. Clasament ==roundparam(round_id=\"preoni2007_runda5_11-12\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2007_runda5_11-12\")==',1,'round: preoni2007_runda5_11-12',NULL,NULL),('preoni-2007/runda-finala','Finala preONI 2007','2007-06-20 14:13:49','2007-06-28 13:30:44','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)*(active) \'Despre&hellip;\':preoni-2007/runda-finala\r\n* \'Program\':preoni-2007/runda-finala/program\r\n* \'Regulament\':preoni-2007/runda-finala/regulament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-finala/9\r\n\r\nh1. Finala preONI 2007, Bucuresti\r\n\r\n*preONI 2007 s-a incheiat!*\r\n\r\np={font-weight: bold}. \"Rezulate\":preoni-2007/clasament/runda-finala/9 | ==smflink(link=\"topic\" topic=\"1961\" caption=\"Feedback\")== | \"Poze!\":preoni-2007/runda-finala/poze\r\n\r\nh2. Detalii\r\n\r\nFinala concursului preONI 2007 se desfasoara in *Bucuresti*, mai exact la \'Liceul international de Informatica\':http://www.ichb.ro in perioada *24 - 26 iunie 2007*.\r\n\r\n\'Premiile concursului\':preoni-2007/premii preONI se vor acorda in functie de rezultatele rundei finale. Punctajele obtinute in perioada de calificare vor servi doar la departajare. \r\n\r\nConcurentiilor li se vor asigura cazarea si masa integral. Costul transportului pana la locul unde se va desfasura finala va fi suportat de catre concurenti.\r\n\r\nh2. Calificare\r\n\r\nCalificarea in aceasta etapa se face exclusiv pe baza \'clasamentului din primele 4 runde\':preoni-2007/clasament. De la fiecare grupa vor fi selectati ocupantii primelor *10* pozitii. Mentionam ca o persoana se poate califica la finala doar la grupa de varsta destinata lui si ca se va face si o identificare prin intermediul Cartii de Identiate (Buletin) sau Carnet de Note vizat si cu poza (pentru cei care nu au inca buletin) pentru a evita frauda. Daca aveti nelamuriri revedeti si \'regulamentul\':preoni-2007/regulament. \r\n\r\n*Pentru concurentii care nu s-au calificat in finala, vom gazdui si o varianta online a concursului in paralel cu finala de la Bucuresti!* Aveti ocazia sa va comparati performanta cu cei care au ajuns in finala. ;) Nu se acorda premii participantilor online.\r\n\r\nStudiati \'programul de desfasurare\':preoni-2007/runda-finala/program pentru mai multe informatii.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',75,'protected',NULL,NULL),('preoni-2007/runda-finala/11-12','preONI 2007, Runda Finala, Clasele 11-12','2007-06-23 20:35:35','2007-06-25 10:41:16','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2007/runda-finala\r\n* \'Program\':preoni-2007/runda-finala/program\r\n* \'Regulament\':preoni-2007/runda-finala/regulament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n*(active) \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-finala/9\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda5_11-12\" param=\"title\") ==\r\n\r\n==roundregister(round_id=\"preoni2007_runda5_11-12\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nRunda se desfasoara *Luni 25 iunie*, la ora {*09^10^*} si va dura *{color:red}5h*.\r\nParticipantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2007/clasament/runda-finala/11-12.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda5_11-12\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==',1,'round: preoni2007_runda5_11-12',NULL,NULL),('preoni-2007/clasament/runda-finala/9','Clasament preONI 2007, Runda Finala, Clasa a 9-a si gimnaziu','2007-06-23 20:46:11','2007-06-23 20:49:03','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2007/runda-finala\r\n* \'Program\':preoni-2007/runda-finala/program\r\n* \'Regulament\':preoni-2007/runda-finala/regulament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-finala/9\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda5_9\" param=\"title\") ==\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-finala/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda5_9\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/runda-finala/10','preONI 2007, Runda Finala, Clasa a 10-a','2007-06-23 20:19:14','2007-06-25 10:41:32','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2007/runda-finala\r\n* \'Program\':preoni-2007/runda-finala/program\r\n* \'Regulament\':preoni-2007/runda-finala/regulament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n* \'Rezultate\':preoni-2007/clasament/runda-finala/10\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda5_10\" param=\"title\") ==\r\n\r\n==roundregister(round_id=\"preoni2007_runda5_10\" template=\"template/preoni-2007/inscriere-runda\")==\r\n\r\nRunda se desfasoara *Luni 25 iunie*, la ora {*09^10^*} si va dura *{color:red}5h*.\r\nParticipantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2007/clasament/runda-finala/10.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2007_runda5_10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"35\" count=\"10\")==\r\n\r\n==include(page=\"template/preoni-2007/footer\")==',1,'round: preoni2007_runda5_10',NULL,NULL),('preoni-2007/clasament/runda-finala/10','Clasament preONI 2007, Runda Finala, Clasa a 10-a','2007-06-23 20:48:11','2007-06-23 20:50:35','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2007/runda-finala\r\n* \'Program\':preoni-2007/runda-finala/program\r\n* \'Regulament\':preoni-2007/runda-finala/regulament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-finala/9\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda5_10\" param=\"title\") ==\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-finala/9\r\n*(active) \'Clasa a 10-a\':preoni-2007/clasament/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/clasament/runda-finala/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda5_10\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/clasament/runda-finala/11-12','Clasament preONI 2007, Runda Finala, Clasele 11-12','2007-06-23 20:50:15','2007-06-23 20:50:46','==Include(page=\"template/preoni-2007\")==\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2007/runda-finala\r\n* \'Program\':preoni-2007/runda-finala/program\r\n* \'Regulament\':preoni-2007/runda-finala/regulament\r\n* \'Clasa a 9-a si gimnaziu\':preoni-2007/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2007/runda-finala/11-12\r\n*(active) \'Rezultate\':preoni-2007/clasament/runda-finala/9\r\n\r\nh1. == roundparam(round_id=\"preoni2007_runda5_11-12\" param=\"title\") ==\r\n\r\n==include(page=\"template/preoni-2007/clasament-header\")==\r\n\r\n(htabs)* \'Clasa a 9-a si gimnaziu\':preoni-2007/clasament/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2007/clasament/runda-finala/10\r\n*(active) \'Clasele 11-12\':preoni-2007/clasament/runda-finala/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2007_runda5_11-12\") == \r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2007/premii','Sponsori si premii preONI 2007','2007-01-15 15:51:08','2007-06-26 10:24:04','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Sponsori si premii\r\n\r\nh2. Premii\r\n\r\nSe vor acorda premii in bani castigatorilor \'rundei finale\':preoni-2007/runda-finala. Pentru fiecare grupa de varsta se acorda urmatoarele premii:\r\n\r\n* Locul I: 400 lei\r\n* Locul II: 200 lei\r\n* Locul III: 100 lei\r\n\r\n*In plus, \'HOSTWAY Romania\':http://www.hostwaylab.ro/ ofera cate un domeniu la alegere si un pachet de webhosting pe un an de zile  participantilor la finala preONI!*\r\n\r\n&nbsp;\r\n\r\nh3. Mesaj de la Flaviu Radulescu, General Manager \'HOSTWAY Romania\':http://www.hostwaylab.ro/\r\n\r\n!{border:1px solid silver; float: right}preoni-2007?hostway.png!:http://www.hostwaylab.ro/\r\n\r\nDe cand a aparut pe piata in Romania anul trecut, Hostway si-a dorit sa poata participa la un astfel de eveniment. Aceasta nu este doar o declaratie de complezenta, la noi in companie, creativitatea, dorinta de a invata si flexibilitatea abordarilor fiind incurajate si sustinute permanent.\r\n\r\nHostway Romania are trei departamente \"de productie\":\r\n\r\n* web development\r\n* web hosting\r\n* software research & development\r\n\r\nSite-urile dezvoltate in departamentul de web development sunt produse in exclusivitate pentru clienti din Statele Unite.\r\n\r\nDepartamentul de Web hosting este dedicat pietei din Romania. Solutiile de hosting oferite de noi includ planuri pentru persoane fizice si companii mici sau medii, cat si suite de servicii dedicate nevoilor specifice ale companiilor de tip \"enterprise\".\r\n\r\nDepartamentul de Research & Development construieste azi internetul de maine, directia principala de dezvoltare fiind \"software as a service\". Daca doriti sa aflati mai multe puteti vizita site-ul nostru, la adresa \'www.hostwaylab.ro\':http://www.hostwaylab.ro/.\r\n\r\nCompania Hostway Corporation asigura servicii de gazduire Web, inregistrare de domenii, Web design, si campanii online pentru peste 600.000 de clienti din toata lumea. Hostway detine 14 data-centere de ultima generatie puse in slujba unei prezente globale. Fondata in 1998, Hostway este una dintre primele 5 companii de Hosting din lume, cu birouri in Chicago, Illinois; Tampa, Florida; Austin, Texas; Vancouver, British Columbia; Londra, Anglia; Paris, Franta; Amsterdam, Olanda; Antwerp, Belgia; Frankfurt, Hanovra, Germania; Bucuresti, Romania; Sydney, Australia si Mumbai, India.\r\n\r\nNe simtim onorati sa putem sprijini cea mai mare comunitate de programatori din tara, credem ca initiativa noastra va avea un impact pozitiv la dezvoltarea proiectului Infoarena, si dorim sa ne implicam si in viitoarele initiative.\r\n\r\nVa dorim mult success in continuare!\r\n\r\n&nbsp;\r\n\r\nh3. Mesaj de la Dragos Ciobanescu, Director Executiv iReal Soft\r\n\r\n!{border:1px solid silver; float: right}preoni-2007?irealsoft.png!:http://www.irealsoft.ro/\r\n\r\nFelicitari tuturor participantilor!\r\n\r\niReal Soft ofera solutii complete pentru optimizarea profitului companiilor care ofera servicii financiare (banci, asigurari, retail, IFN, etc.). Solutiile includ consultanta, analiza afacerilor, optimizarea proceselor si implementari si integrari software.\r\n\r\nProdusele iReal Soft: RBDS (Rule-Based Decision System), Collection System, Front-End System, Billing System, Universal Reporting Database, etc.\r\n\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==\r\n',13,'protected',NULL,NULL),('preoni-2007/runda-finala/poze/deschidere','Poze preONI 2007 - deschidere','2007-06-27 08:15:39','2007-06-27 14:11:16','==include(page=\"template/preoni-2007/header\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)* \'Poze\':preoni-2007/runda-finala/poze\r\n* \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n*(active) \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n* \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n* \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n* \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n* \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n* \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n* \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\n== Gallery(page=\"preoni-2007/runda-finala/poze/deschidere\" file=\"%.jpg\") ==\r\n\r\n\'Download them all\':http://infoarena.ro/preoni-2007/runda-finala/poze/deschidere?action=download&file=1-deschidere.zip',75,'public',NULL,NULL),('preoni-2007/runda-finala/poze/pregatiri','Poze preONI 2007 - pregatiri','2007-06-27 08:17:24','2007-06-27 14:10:31','==include(page=\"template/preoni-2007/header\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)* \'Poze\':preoni-2007/runda-finala/poze\r\n*(active) \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n* \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n* \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n* \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n* \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n* \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n* \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n* \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\n== Gallery(page=\"preoni-2007/runda-finala/poze/pregatiri\" file=\"%.jpg\") ==\r\n\r\n\'Download them all\':http://infoarena.ro/preoni-2007/runda-finala/poze/pregatiri?action=download&file=0-pregatiri.zip',75,'public',NULL,NULL),('preoni-2007/runda-finala/poze','Poze finala preONI 2007','2007-06-27 08:11:08','2007-06-27 13:49:15','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)*(active) \'Poze\':preoni-2007/runda-finala/poze\r\n* \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n* \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n* \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n* \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n* \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n* \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n* \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n* \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\nAici gasiti o galerie de poze facute la finala concursului preONI 2007. Enjoy!\r\n\r\nDaca mai aveti poze, puteti sa ne contactati sa le punem pe site.',75,'public',NULL,NULL),('preoni-2007/runda-finala/poze/la-masa','Poze preONI 2007 - masa','2007-06-27 08:18:35','2007-06-27 14:12:47','==include(page=\"template/preoni-2007/header\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)* \'Poze\':preoni-2007/runda-finala/poze\r\n* \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n* \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n*(active) \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n* \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n* \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n* \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n* \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n* \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\n== Gallery(page=\"preoni-2007/runda-finala/poze/la-masa\" file=\"%.jpg\") ==\r\n\r\n\'Download them all\':http://infoarena.ro/preoni-2007/runda-finala/poze/la-masa?action=download&file=3-la-masa.zip',75,'public',NULL,NULL),('preoni-2007/runda-finala/poze/concurs','Poze preONI 2007 - concurs','2007-06-27 08:19:36','2007-06-27 14:15:52','==include(page=\"template/preoni-2007/header\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)* \'Poze\':preoni-2007/runda-finala/poze\r\n* \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n* \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n* \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n* \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n*(active) \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n* \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n* \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n* \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\n== Gallery(page=\"preoni-2007/runda-finala/poze/concurs\" file=\"%.jpg\") ==\r\n\r\n\'Download them all\':http://infoarena.ro/preoni-2007/runda-finala/poze/concurs?action=download&file=4-concurs.zip',75,'public',NULL,NULL),('preoni-2007/runda-finala/poze/evaluare','Poze preONI 2007 - evaluare','2007-06-27 08:20:26','2007-06-27 14:16:14','==include(page=\"template/preoni-2007/header\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)* \'Poze\':preoni-2007/runda-finala/poze\r\n* \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n* \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n* \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n* \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n* \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n*(active) \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n* \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n* \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\n\r\n== Gallery(page=\"preoni-2007/runda-finala/poze/evaluare\" file=\"%.jpg\") ==\r\n\r\n\'Download them all\':http://infoarena.ro/preoni-2007/runda-finala/poze/evaluare?action=download&file=5-evaluare.zip',75,'public',NULL,NULL),('preoni-2007/runda-finala/poze/premiere','Poze preONI 2007 - premiere','2007-06-27 08:21:25','2007-06-27 14:16:50','==include(page=\"template/preoni-2007/header\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)* \'Poze\':preoni-2007/runda-finala/poze\r\n* \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n* \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n* \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n* \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n* \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n* \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n*(active) \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n* \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\n== Gallery(page=\"preoni-2007/runda-finala/poze/premiere\" file=\"%.jpg\") ==\r\n\r\n\'Download them all\':http://infoarena.ro/preoni-2007/runda-finala/poze/premiere?action=download&file=6-premiere.zip',75,'public',NULL,NULL),('template/preoni-2007','template/preoni-2007','2007-01-13 23:36:26','2007-06-27 13:39:39','==include(page=\"template/preoni-2007/header\")==\r\n\r\n(vmenu)*(section) \'Home\':preoni-2007\r\n* \'Clasament\':preoni-2007/clasament\r\n* \'Organizatori\':preoni-2007/comisie\r\n* \'Sponsori si premii\':preoni-2007/premii\r\n* \'Regulament\':preoni-2007/regulament\r\n* \'Aparitii in presa\':preoni-2007/presa\r\n*(section) Runde\r\n* \'Runda 1\':preoni-2007/runda-1\r\n* \'Runda 2\':preoni-2007/runda-2\r\n* \'Runda 3\':preoni-2007/runda-3\r\n* \'Runda 4\':preoni-2007/runda-4\r\n* \'Runda Finala\':preoni-2007/runda-finala\r\n',75,'protected',NULL,NULL),('preoni-2007/runda-finala/poze/gratar','Poze preONI 2007 - gratar','2007-06-27 08:22:32','2007-06-27 14:17:11','==include(page=\"template/preoni-2007/header\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)* \'Poze\':preoni-2007/runda-finala/poze\r\n* \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n* \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n* \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n* \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n* \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n* \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n* \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n*(active) \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\n== Gallery(page=\"preoni-2007/runda-finala/poze/gratar\" file=\"%.jpg\") ==\r\n\r\n\'Download them all\':http://infoarena.ro/preoni-2007/runda-finala/poze/gratar?action=download&file=7-gratar.zip',75,'public',NULL,NULL),('preoni-2007','preONI 2007','2007-01-15 15:12:34','2009-01-19 15:25:14','==Include(page=\"template/preoni-2007\")==\r\n\r\n*preONI 2007 s-a incheiat!*\r\n\r\np={font-weight: bold}. \"Rezultate\":preoni-2007/clasament/runda-finala/9 | ==smflink(link=\"topic\" topic=\"1961\" caption=\"Feedback\")== | \"Poze!\":preoni-2007/runda-finala/poze\r\n\r\nh2. Detalii\r\n\r\n*preONI*, concursul de pregatire pentru Olimpiada Nationala de Informatica, a ajuns la a patra editie.\r\n\r\n*preONI 2007* incepe cu 4 runde online de calificare. Cei mai buni de la fiecare grupa sunt invitati la finala on-site. Castigatorii rundei finale sunt premiati in bani si obiecte.\r\n\r\np. &rarr; \'Remember preONI 2006\':preoni-2006\r\n\r\nh2. Program concurs\r\n\r\ntable{width: 50%}. |_. Runda|_. Data |_. Ora |\r\n|\"*Runda 1*\":preoni-2007/runda-1|*Duminica, 21 ianuarie 2007*| *09^30^ - 13^30^* |\r\n|\"*Runda 2*\":preoni-2007/runda-2|*Duminica, 18 februarie 2007*|*09^00^ - 13^00^* |\r\n|\"*Runda 3*\":preoni-2007/runda-3|*Duminica, 4 martie 2007*| *09^00^ - 13^15^* |\r\n|\"*Runda 4*\":preoni-2007/runda-4|*Duminica, 25 martie 2007*| *09^00^ - 13^00^* |\r\n|\"*Runda finala*\":preoni-2007/runda-finala| *Luni, 26 iunie 2007* | *09^00^ - 14^00^* |\r\n\r\nClick pe titlul unei runde pentru informatii detaliate.\r\n\r\nDatele scrise _inclinat_ sunt provizorii. Este posibil sa le schimbam pe parcurs.\r\n\r\nh2. Despre preONI\r\n\r\n*preONI*, concursul de marca al comunitatii infoarena, este dedicat elevilor de liceu ce se pregatesc pentru ONI (\'Olimpiada Nationala de Informatica\':http://olimpiada.info/).\r\n\r\nConcursul este impartit in 3 grupe: clasa a IX-a si gimnaziu, clasa a X-a si clasele XI-XII. Se organizeaza 4 runde online de calificare. In urma acestora, cei mai buni de la fiecare grupa sunt invitati la o \'runda finala\':preoni-2007/runda-finala.\r\n\r\nIn cadrul unei runde, concurentii au de rezolvat 3 probleme in 4 ore. Castigatorii rundei finale sunt premiati cu bani si/sau obiecte.\r\n\r\nVezi \'preONI 2006\':preoni-2006, \'preONI 2005\':preoni-2005.\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru.\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti probleme, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nPoti sa rezolvi probleme de la orice grupa de varsta. Totusi, te vei califica la runda finala numai daca te incadrezi in grupa la care ai concurat.\r\n\r\nh2. Prima data pe infoarena?\r\n\r\ninfoarena ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi.\r\n\r\nVezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n\r\n==include(page=\"template/preoni-2007/footer\")==\r\n',13,'protected',NULL,NULL),('preoni-2007/runda-finala/poze/wii-play','Poze preONI 2007 - wii-play','2007-06-27 08:25:04','2007-06-27 14:15:22','==include(page=\"template/preoni-2007/header\")==\r\n\r\nh1. Poze finala preONI 2007\r\n\r\n(htabs)* \'Poze\':preoni-2007/runda-finala/poze\r\n* \'Pregatiri\':preoni-2007/runda-finala/poze/pregatiri\r\n* \'Deschidere\':preoni-2007/runda-finala/poze/deschidere\r\n* \'La masa\':preoni-2007/runda-finala/poze/la-masa\r\n*(active) \'Wii play\':preoni-2007/runda-finala/poze/wii-play\r\n* \'Concurs\':preoni-2007/runda-finala/poze/concurs\r\n* \'Evaluare\':preoni-2007/runda-finala/poze/evaluare\r\n* \'Premiere\':preoni-2007/runda-finala/poze/premiere\r\n* \'Gratar\':preoni-2007/runda-finala/poze/gratar\r\n\r\n== Gallery(page=\"preoni-2007/runda-finala/poze/wii-play\" file=\"%.jpg\") ==\r\n\r\n\'Download them all\':http://infoarena.ro/preoni-2007/runda-finala/poze/wii-play?action=download&file=x-wii-play.zip\r\n\'Filmulet mulgand vaca\':http://infoarena.ro/preoni-2007/runda-finala/poze/wii-play?action=download&file=mov01766.mpg',75,'public',NULL,NULL),('preoni-2007/runda-finala/solutii','Solutii preONI 2007, Runda Finala','2007-06-25 12:07:40','2007-12-14 23:10:11','==Include(page=\"template/preoni-2007\")==\r\n\r\nh1. Solutii Runda Finala\r\n\r\nh2. \'Orase\':problema/orase\r\n\r\nh3. (problema usoara, clasa a 9-a)\r\n\r\nLa primul pas se vor sorta orasele crescator dupa $D{~i~}$. Renumerotand orasele in ordinea sortarii, putem calcula distanta care trebuie parcursa intre doua orase $j < i$: $L{~i~}+D{~i~}+L{~j~}-D{~j~}$. Pentru fiecare $i$ vrem sa determinam un oras $j < i$ astfel incat sa se maximizeze aceasta distanta. Alegerea optima va fi un oras $j$ cu valoarea $L{~j~}-D{~j~}$ maxima; astfel, pe masura ce se avanseaza cu indicele $i$ se pastreaza si un indice $j$ maxim pana in prezent. Complexitatea rezolvarii este $O(N*lg N)$ datorita sortarii.\r\n\r\nh2. \'Sarpe\':problema/sarpe\r\n\r\nh3. (problema medie, clasa a 9-a)\r\n\r\nVom calcula intai numarul de posibilitati pentru cazul in care $1$ se afla in unul din colturi. Sa presupunem ca l-am asezat in coltul stanga sus. Distingem doua cazuri:\r\n\r\n* $2$ este asezat la dreapta lui $1$ caz in care exista un singur mod de completare\r\n\r\ntable(example). | 1 | 2 | 3 | ... |\r\n| 2N | 2N-1 | 2N-2 | ... |\r\n\r\n* $2$ este asezat in coltul din stanga jos caz in care vom avea de completat tabla ramasa cu numerele {$3$}, {$4$}, ... {$2N$} punand $3$ la dreapta lui $2$ lucru care este echivalent cu completarea unei table cu $N-1$ coloane cu $1$ fixat in unul din colturi.\r\n\r\ntable(example). | 1 | &nbsp; | ... |\r\n| 2 | 3 | ... |\r\n\r\nIn concluzie numarul de moduri in care se poate completa tabla de dimensiune $N$ cu $1$ pus intr-un colt fixat este {$N$}. Analizam acum cazul in care $1$ este pus pe una din coloanele {$2, 3 , ... N-1$}. $2$ nu poate fi pus sub $1$ deoarece tabla s-ar imparti in doua bucati care nu sunt conexe si nu se poate completa comform cerintei. Daca 2 este pozitionat in stanga lui 1 toate coloanele {$1, 2, ... i$} se vor completa in mod unic.\r\n\r\ntable(example). |i | ... | 2 | 1 | ... |\r\n| i+1 | ... | 2*i - 1  | 2*i | ... |\r\n\r\nDeci vor ramane de completat $N-i$ coloane care trebuie completate cu $2*i+1$ pus intr-un colt fixat. Deci vom avea in total $N-i$ posibilitati. In mod analog daca $2$ se afla in dreapta vom avea $i-1$ posibilitati. Numarul total de posibilitati cand $1$ se afla pe una din coloanele {$2, 3, ... N-1$} va fi suma de la $2$ la $N-1$ din {$2(N-i+i-1)$} adica {$2(N-2)(N-1)$} deoarece se poate incepe de sus sau de jos. Raspunsul cautat va fi {$4N + 2(N-1)(N-2)$}, {$N > 1$}. Operatiile trebuiau efectuate pe numere mari.\r\n\r\nh2. \'Sate\':problema/sate\r\n\r\nh3. (problema grea, clasa a 9-a, problema usoara, clasa a 10-a)\r\n\r\nPutem considera $N$ puncte coliniare {$A{~1~}$}, {$A{~2~}$}... {$A{~N~}$}. Problema cere, daca cunoastem lungimile a exact $M$ segmente, sa determinam lungimea segmentului {$A{~X~}$}{$A{~Y~}$}. O rezolvare {$O(N^3^)$} nu este dificil de gasit. Vom afla lungimea tuturor segmentelor care se pot forma. Vom retine intr-o coada toate acele segmente carora le stim lungimea. Initial, in coada se afla doar cele $M$ segmente. Cand suntem pe un element in coada si vrem sa aflam ce noi segmente putem introduce, iteram un punct \"de rupere\" {$K$}. Sa presupunem ca stim lungimea segmentului {$A{~i~}A{~j~}$}. Distingem urmatoarele cazuri:\r\n\r\n* {$K < i$} si stim lungimea segmentului {$A{~K~}A{~i~}$} => inseram in coada segmentul {$A{~K~}A{~j~}$} cu lungimea egala cu suma lungimilor segmentelor {$A{~K~}A{~i~}$} si {$A{~i~}A{~j~}$}\r\n* {$i < K < j$}\r\n** stim lungimea segmentului {$A{~i~}A{~K~}$} => inseram in coada segmentul {$A{~K~}A{~j~}$} cu lungimea egala cu diferenta dintre lungimilor segmentelor {$A{~i~}A{~j~}$} si {$A{~i~}A{~K~}$}\r\n** stim lungimea segmentului {$A{~K~}A{~j~}$} => inseram in coada segmentul {$A{~i~}A{~K~}$} cu lungimea egala cu diferenta dintre lungimilor segmentelor {$A{~i~}A{~j~}$} si {$A{~K~}A{~j~}$}\r\n* {$K > j$} si stim lungimea segmentului {$A{~j~}A{~K~}$} => inseram in coada segmentul {$A{~i~}A{~K~}$} cu lungimea egala cu suma lungimilor segmentelor {$A{~i~}A{~j~}$} si {$A{~j~}A{~K~}$}\r\n\r\nDaca in final segmentul {$A{~X~}A{~Y~}$} a fost inserat in coada, atunci afisam lungimea acestuia.\r\n\r\nRezolvarea {$O(N+M)$} se bazeaza pe faptul ca nu avem nevoie sa stim lungimile tuturor segmentelor, ci doar a celor care au unul din capete punctul {$A{~X~}$}. Notam cu {$D{~i~}$} lungimea segmentului {$A{~X~}A{~i~}$}. Fiecare punct va fi identificat printr-un nod intr-un graf. Lungimea muchiei intre intre doua noduri va fi lungimea segmentului dat de punctele corespunzatoare nodurilor. Acum putem aplica o parcurgere BF din nodul $X$ si respectam toate cazurile care apar. In final, in {$D{~Y~}$} se afla lungimea segmentului {$A{~X~}A{~Y~}$}.\r\n\r\nh2. \'Branza\':problema/branza\r\n\r\nh3. (problema medie, clasa a 10-a)\r\n\r\nAceasta problema se rezolva folosind metoda programarii dinamice. O solutie triviala are complexitatea $O(N*T)$ si se realizeaza calculand vectorul $m[i] = costul minim pentru a obtine un kg de branza in saptamana i$. Acesta se obtine folosind formula $m[i] = min{C[j] + (i-j)*S | i-j &le; T}$.\r\nPentru a reduce complexitatea la $O(N)$ se observa ca pentru calculul lui $m[i]$ avem nevoie doar de valorile lui $C$ cuprinse intre $max(1, i-T)$ si $i$, interval a carei dimensiuni nu poate decat sa creasca sau sa ramana constanta. Se foloseste un deque in care se introduc pe rand valorile din $C$ modificate corespunzator pentru a asigura gasirea minimului cerut la fiecare pas. Astfel la pasul $i$ se va introduce in deque valoarea $C[i] + (N-i)*S$, pentru a mentine relatia de ordine corespunzatoare relatiei de recurenta intre elementele structurii. La pasul $i$ se considera elementul din coada deque-ului (fie acela provenit de la $C[j]$) din care se scade @(N-j)*S@ pentru a obtine pe $m[i]$.\r\nSolutia ceruta este @m[1]@ $* P{~1~} +$ @m[2]@ $* P{~2~} + ... + m[N] * P{~N~}$\r\n\r\nh2. \'Gradina\':problema/gradina\r\n\r\nh3. (problema grea, clasa a 10-a)\r\n\r\nEste evident ca cele doua poligoane convexe pot fi separate de o dreapta care sa treaca printr-un varf $A$ de pe primul poligon si un varf $B$ de pe cel de-al doilea. Astfel, dreapta imparte planul in doua semiplane si in fiecare din cele doua semiplane se afla cate un poligon convex.\r\nDintre cele $N$ puncte alegem toate perechile de puncte {$(X Y)$} si presupunem ca dreapta determinata de aceste doua puncte separa cele doua poligoane, iar punctul $X$ este varf pentru primul poligon si punctul $Y$ pentru cel de-al doilea. Pentru o dreapta fixata, putem aplica pentru fiecare din cele semiplane un algoritm de infasuratoare convexa ( verificand apoi daca infasuratoarea convexa contine toate punctele din semiplanul respectiv ) in {$O(N log N)$}, rezultand o complexitate totala de {$O(N^3^ log N)$}. Pentru a obtine complexitatea {$O(N^3^)$}, putem sorta punctele in functie de ordonata si apoi in functie de abscisa de la inceput. Astfel, in algoritmul Graham pentru poligoane convexe nu mai este necesara resortarea punctelor si algoritmul, pentru o dreapta fixata, dureaza {$O(h1) + O(h2)$}, unde $h1$ si $h2$ sunt numarul de puncte din cele doua semiplane. Cum {$O(h1 + h2)$} = {$O(N)$}, complexitatea algoritmului este {$O(N^3)$}.\r\n\r\nh2. \'P-Sir\':problema/psir\r\n\r\nh3. (problema usoara, clasele 11-12)\r\n\r\nProblema se rezolva prin metoda programarii dinamice. Conditia din enunt se poate enunta astfel: elementul $a{~i~}$ dintr-un p-sir trebuie sa fie inclus strict in intervalul determinat de $a{~i-1~}$ si $a{~i-2~}$. Vom calcula $Nr[i][j]$ numarul de p-subsiruri care au ultimiii doi termeni $P{~i~}$ si $P{~j~} (i < j)$. \r\nVom presupune ca $P{~i~} < P{~j~}$, cazul $P{~i~} > P{~j~}$ putand fi tratat asemanator. $Nr[i][j]$ se va calcula ca suma de $Nr[k][i]$ cu proprietatea $P{~i~} < P{~j~} < P{~k~}$. O implementare directa a acestei rezolvari are complexitatea $O(N^3^)$ si ar fi obtinut $30$ de puncte. Daca sortam vectorul $P$ dat la intrare, valorile $k < i$ care respecta conditia $P{~j~} < P{~k~}$ vor forma un interval continuu ca indici. Vom calcula sume partiale pentru coloana $i$ din matricea $Nr$ parcurgand liniile matricii in ordinea sortarii. Astfel, calculul lui $Nr[i][j]$ se reduce la scaderea a doua sume partiale. Pentru a identifica exact ce sume se scad se poate folosi o cautare binara, reducand astfel rezolvarea la $O(N^2^*lg N)$. \r\nMentionam ca se poate obtine si o solutie $O(N^2^)$ daca se calculeaza valorile de pe linia $i$ din matricea $Nr$ in ordinea sortarii. Putem astfel renunta la cautare binara, deoarece indicele in care se face scaderea sumelor partiale va fi monoton.\r\nCa o ultima precizare, nu era necesar folosirea tipurilor de date pe $64$ de biti pentru a efectua operatii modulo $2^32^$. Mai mult, nu este necesar nici macar folosirea operatiei modulo. Daca se foloseste un tip intreg pe $32$ fara semn ({$unsigned$} in $C/C++$) orice operatie cu variabile de acest tip este automat modulo $2^32^$.\r\n\r\n\r\nh2. \'Eval\':problema/eval\r\n\r\nh3. (problema medie, clasele 11-12)\r\n\r\nEste evident ca o solutie care simula evaluarea expresiei nu s-ar fi incadrat ca timp sau ca memorie, deoarece rezultatele obtinute pe parcurs pot fi foarte mari, desi rezultatul final este limitat de $10^1000^$. Pentru rezolvarea acestei probleme este necesara \'teorema chineza a resturilor\':http://en.wikipedia.org/wiki/Chinese_remainder_theorem :\r\nFie $K$ numere prime distincte $P{~1~}, P{~2~},... ,P{~K~}$ si $K$ resturi $R{~1~}, R{~2~},... R{~K~}$. \r\nExista un numar natural unic $N$ mai mic decat produsul celor $K$ numere prime care satisface relatiile $N = R{~i~} (mod P{~i~})$.\r\nVom rezolva intai problema de $70%$, adica variabilele si rezultatul sunt numere naturale. Daca alegem un numar suficient de numere prime astfel incat produsul lor sa fie mai mare decat $10^1000^$, putem calcula rezultatul expresiei modulo fiecare numar prim in timp liniar si putem reconstitui rezultatul (care va fi unic) folosind teorema chineza a resturilor. O prezentare detaliata a acestei teoreme se gaseste si in \'acest articol\':downloads?action=download&file=mate.pdf.\r\nPutem reduce varianta cu numere intregi la problema initiala cu numere naturale adunand constanta $10^1000^$ la expresie. Astfel se garanteaza ca rezultatul expresiei este in intervalul $[0, 2*10^1000^]$.\r\nDeoarece lungimea expresiei este de $100.000$ trebuiau se se foloseasca numere prime relativ mari. Solutia oficiala foloste aproximativ $120$ de numere prime din intervalul $[10^9^, 2*10^9^]$.\r\n\r\nh2. \'Obiective\':problema/obiective\r\n\r\nh3. (problema grea, clasele 11-12)\r\n\r\nPutem asocia problemei un graf orientat care are proprietatea:\r\n\r\n(*): Oricum am alege 3 noduri {$A$}, {$B$}, {$C$} din graf astfel incat sa existe drum de la {$A$} la {$C$} si de la {$B$} la {$C$}, atunci exista drum de la {$A$} la {$B$} sau de la {$B$} la {$A$} ( posibil ambele ).\r\n\r\nUn query {$(x y)$} cere determinarea numarului minim de arce care trebuiesc reorientate astfel incat sa avem drum de la $x$ la {$y$}. Problema se poate rezolva optim in complexitate {$O(N + M + T)$}, dar in concurs o solutie {$O( (N + T) log N + M log M )$} era suficienta pentru obtinerea punctajului maxim.\r\n\r\nGraful initial se transforma intr-un graf aciclic, graful componentelor tare conexe, pe care il vom nota {$G*$}. In continuare, cand ne referim la nodul $x$ in {$G*$} ne referim la nodul componentei tari conexe care il contine pe {$x$}. Numim radacina pentru {$G*$} acel nod care are gradul intern $0$ ( nodul in care nu intra nici o muchie ). Exista un singur astfel de nod, deoarece, daca ar exista cel putin doua, conditia (*), impreuna cu proprietatea de conexitate a grafului suport, nu ar mai fi respectata. \r\nCum {$G*$} este aciclic, putem sorta nodurile lui astfel incat daca exista muchie de la $x$ la $y$ in {$G*$}, $x$ va aparea inaintea lui $y$ in sortare ( sortare topologica ). Pentru fiecare nod din {$G*$} sortam lista lui de adiacenta conform ordinii din sortarea topologica. Sortarea se poate face liniar, cu radixsort, sau cu algoritmul quicksort.\r\n\r\nDupa sortarea listelor de adiacenta, se efectueaza o parcurgere DF din radacina lui {$G*$}.\r\n\r\n\r\n* _Propozitie 1_: Arborele DF rezultat din parcurgerea de mai sus contine numai muchii de arbore sau muchii inainte.\r\n\r\n\r\nCum {$G*$} este aciclic, nu pot exista muchii de intoarcere ( inapoi ). Vom demonstra ca nu exista muchii transversale. Definim {$nivel{~x~}$} ca fiind numarul de noduri de la $x$ la radacina pe drumul format din numai muchii de arbore.\r\nPresupunem prin reducere la absurd ca exista o muchie transversala {$x->y$}. Selectam acea muchie transversala {$x->y$} pentru care {$nivel{~y~}$} este minim. $Y$ nu poate fi radacina lui {$G*$}, pentru ca, in caz contrar, muchia {$x->y$} ar fi muchie de intoarcere si ar forma un ciclu, dar {$G*$} este aciclic. Deci exista un nod $u$ care este tatal lui {$y$}. Demonstram ca pentru tripletul {$(x u y)$} conditia (*) nu este indeplinita.\r\nExista drum de la $x$ la $y$ si de la $u$ la {$y$}. Drum de la $x$ la $u$ nu poate exista deoarece $u$ se afla in alt subarbore si, pentru a trece dintr-un subarbore in altul, trebuie se parcurgem muchii transversale. Dar {$x->y$} era muchia transversala pentru care {$nivel{~y~}$} era minim, si cum {$nivel{~u~}$} < {$nivel{~y~}$} si nu exista muchii de intoarcere => nu putem ajunge din $x$ in {$u$}. Nu putem ajunge nici din $u$ in $x$ datorita modului in care au fost sortate listele de adiacenta. Sa presupunem ca putem ajunge din {$u$} in {$x$}. Cum avem muchia {$x->y$}, $x$ apare inaintea lui $y$ in sortarea topologica, deci va aparea in listele de adiacenta mai devreme. Cand facem parcurgerea DF din nodul {$u$}, vom trece mai intai prin nodul $x$ si de abia dupa aceea prin nodul {$y$}, iar muchia {$x->y$} nu mai este muchie transversala.\r\nPropozitia a fost demonstrata.\r\n\r\n\r\n* _Propozitie 2_: Orice arbore DF care are doar muchii de arbore si muchii inainte indeplineste proprietatea (*).\r\n\r\n\r\nDaca exista numai muchii de arbore si avem un triplet {$(A B C)$} care respecta ca exista drum de la $A$ la $C$ si de la $B$ la {$C$}, atunci si $A$ si $B$ se afla in lista predecesorilor lui {$C$}. Unul din nodurile $A$ sau $B$ trebuie sa apara primul in aceasta lista, deci vom avea drum fie de la $A$ la {$B$}, fie de la $B$ la {$A$}.\r\nCand inseram muchiile inainte nu apar triplete noi pentru care sa existe drum de la $A$ la $C$ si de la {$B$} la {$C$}, deci propozitia a fost demonstrata.\r\n\r\n\r\nArborele DF contine deci numai muchii de arbore si muchii inainte. Pentru un query {$(x y)$} vom aplica o strategie de tip greedy. Fie {$L$} = {$Lowest_Common_Ancestor(x, y)$}. Pentru a reorienta un numar minim de muchii, trebuie sa reorientam acele muchii care ne duc cat mai aproape de radacina. Astfel, trebuie sa ajungem intr-un nod {$u$}, stramos al lui {$x$}, pentru care {$nivel{~u~}$} &le; {$nivel{~L~}$}. Daca putem ajunge din $x$ in {$u$}, putem cobori in arbore pana in {$y$}. Pentru acest pas vom folosi un algoritm liniar, de genul celui folosit in determinarea muchiilor critice in grafuri neorientate.\r\nFie {$low{~x~}$} nodul cel mai apropiat de radacina in care se poate ajunge din $x$ prin reorientarea a exact unei singure muchii si {$level{~x~}$} nivelul lui {$low{~x~}$}. Relatia de recurenta este:\r\n\r\n{$level{~x~}$} = minim({$level{~parinte[x]~}$}; {$level{~y~}$} | y fiu al lui x; {$level{~u~}$} | {$u->x$} muchie inainte )\r\n\r\nSimultan cu vectorul {$level$} construim si vectorul {$low$}.\r\n\r\nPe baza informatiilor astfel calculate, construim un arbore cu $N$ noduri in care tatal nodului {$i$}, $i$ de la $1$ la {$N$}, va fi {$low{~i~}$}. Acum trebuie sa aflam nodul $u$ din acest arbore care indeplineste {$nivel{~u~}$} &le; {$nivel{~L~}$} si {$u$} se afla cat mai aproape de {$x$}. Raspunsul pe query va fi dat de diferenta de nivel dintre $u$ si {$x$}.\r\nPentru a afla nodul $u$ in timp logaritmic ne putem intoarce pe stramosi ai lui $x$ pe baza de puteri ale lui 2 sau putem afla nodul $u$ in {$O(1)$}, demonstrand ca nodul cautat $u$ este fie {$L$}, fie {$parinte{~L~}$} in acest arbore.\r\n\r\n==Include(page=\"template/preoni-2007/footer\")==',1,'public',NULL,NULL),('documentatie/acces-email','Email @infoarena.ro','2007-11-01 13:36:19','2009-03-02 17:24:04','h1. Email @infoarena.ro\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nUnii utilizatori, în special membrii \'echipei infoarena\':echipa-infoarena, primesc o adresă de email @infoarena.ro. Dacă vrei şi tu una, contactează-l pe ==User(type=\"tiny\" user=\"wickedman\")== sau pe ==User(type=\"tiny\" user=\"domino\")==.\r\n\r\nServiciul de email este asigurat de \'Google Apps for infoarena.ro\':http://m.infoarena.ro/.\r\n',13,'public',NULL,NULL),('documentatie/administrare','Administrare','2009-09-23 16:57:24','2009-09-23 16:57:24','h1. Administrarea site-ului\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nh2. Resurse\r\n\r\n* \'Pagină de administrare protejată\':admin\r\n* \'email@infoarena.ro\':documentatie/acces-email\r\n* \'Backup infoarena\':documentatie/backup\r\n\r\nh2. Probleme si runde\r\n\r\nExista un numar de pagini speciale pentru management de probleme si runde.\r\n\r\n* \'admin/problema-noua\':admin/problema-noua : propunere problema noua\r\n* _admin/problema/nume-problema_ : editare detalii probleme\r\n* \'admin/runda-noua\':admin/runda-noua : creare concurs nou\r\n* _admin/runda/nume-concurs_ : editare detalii concurs\r\n\r\nDoar pentru admini, in monitor apare un buton de reevaluare. Nu puteti reevalua decat $512$ job-uri odata, si se pot folosi \'filtre\':documentatie/monitorul-de-evaluare in monitor pentru a alege job-urile.\r\n\r\nh2. Securitate\r\n\r\nOrice pagina din \'wiki\':documentatie/wiki are un \"descriptor de securitate\" care poate fi manipulat doar de catre administratori. Acel descriptor de securitate este un string free-form.\r\n\r\nPentru pagini oarecare exista 3 nivele de securitate:\r\n\r\n* $public$ : vizibila pentru toata lumea, o poate edita orice user logat.\r\n* $protected$ : vizibila pentru toata lumea, o pot edita doar adminii.\r\n* $private$: vizibila doar pentru admini, o pot edita doar adminii.\r\n\r\nMajoritatea paginilor ar trebui sa aiba sa fie publice pentru ca in general putem avea incredere in utilizator. Pagini foarte vizibile de genul home sau preoni probabil ca o sa fie facute protected. Pentru a prinde vandalii avem o \'pagina de modificari\':changes cu \'rss\':changes?format=rss. Editarea anonima nu este suportata.\r\n\r\nh3. Securitate pentru probleme si runde\r\n\r\nPaginile care apartin de un task/round au ca descriptor de securitate ceva de genul $task: gigi$, unde gigi este numele task-ului. *Nu* este neaparat necesar ca paginile acelea sa inceapa cu problema/ sau runda/, dar asa facem prin conventie.',1142,'protected',NULL,NULL),('templates/junior_head','template/junior_head','2007-06-29 19:58:49','2007-06-30 09:44:53','table{margin: 0; width: 99%; background-image: url(/templates/junior_head?action=download&file=star.jpg); background-position: bottom left;}. |{border: 0px;}. !templates/junior_head?logo3.jpg!:/junior-challenge |{border: 0px; text-align: right; vertical-align: bottom}. |\r\n',256,'public',NULL,NULL),('runda/preoni2007_runda4_9','runda/preoni2007_runda4_9','2007-03-13 21:01:37','2007-06-30 14:29:10','',5748,'public',NULL,NULL),('newsletter/junior-challenge','Junior Challenge','2007-06-30 17:02:48','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\ninfoarena organizeaza un nou concurs pentru tine.\r\nTe invitam sa participi la Junior Challenge, \r\nconcurs destinat in principal incepatorilor in programare.\r\nConcursul este totodata o ocazie de antrenament pentru\r\nechipa ce va reprezenta Romania la Olimpiada Balcanica de Juniori.\r\n\nConcursul se va desfasura ...\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n     Miercuri, 4 iulie 2007, orele 09:00 - 12:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPentru informatii detaliate despre concursul\r\nJunior Challenge, acceseaza: \'junior-challenge\':junior-challenge\r\n\nh2.  Concurs fara rating! \n\nParticiparea la acest concurs nu iti va afecta rating-ul pe infoarena.\r\nDespre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nGhidul utilizatorului: \'documentatie/pentru-utilizatori\':documentatie/pentru-utilizatori\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nClick pe acest link ca sa nu mai primesti instiintari:\r\n\'account/%username%\':account/%username%\r\n\ninfoarena nu trimite mesaje nesolicitate!\r\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\n\n',75,'public',NULL,NULL),('ghid-complet-pentru-concursurile-de-informatica','Ghid complet pentru concursurile de informatica','2007-06-30 09:09:40','2009-02-20 00:03:30','h1. Ghid complet pentru concursurile de informatica\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"sims_gl\") ==\r\n\r\n(Categoria _Diverse_, Autor _Mircea Pasoi_)\r\n\r\n**Acest articol se adreseaza pasionatilor de informatica si celor care au de gand sa participe la concursurile si olimpiadele de informatica. Observatiile din cadrul acestui articol sunt, in mare parte, rezultatul experientei autorului.**\r\n\r\nh2. 1. Ce sunt concursurile?\r\n\r\nConcursurile de informatica, ca la orice alta disciplina, vor sa fie o metoda de clasificare a participantilor in functie de abilitatile de programare si de cunostintele de algoritmica. In plus, exista unele concursuri in care cei mai buni concurenti sunt rasplatiti. Probabil cel mai important aspect, concursul include aparitia unui factor suplimentar care rastoarna multe din obisnuintele programarii \"la domiciliu\" sau \"la locul de munca\" (de obicei programatorii care lucreaza in firme au perioade mult mai lungi de timp pentru a-si duce la final sarcina): **timpul**. Autorul a avut la dispozitie mai mult de sapte ani ca sa descopere pe propria piele importanta foarte mare a acestui factor; si, mai mult decat durata de timp in sine a concursului, care este aceeasi pentru toti concurentii, conteaza capacitatea fiecaruia de a gestiona bine acest timp. Daca in fata calculatorului de acasa, cu o sticla de suc alaturi si cu muzica mergand, este intr-adevar un lucru laudabil sa justificam matematic fiecare pas al algoritmului, sa nu ne lasam inselati de intuitie si sa scriem programul fara sa ne grabim, alocandu-ne o mare parte din timp numai pentru depanarea lui, in schimb, in timp de concurs lucrurile  stau tocmai invers: de demonstratii riguroase din punct de vedere matematic rar are timp cineva, intuitia fiind la mare pret si de nenumarate ori fiind criteriul care aduce victoria; iar timpul la un concurs serios este suficient doar pentru implementarea tuturor programelor, pentru depanare alocandu-se de obicei o perioada destul de mica.\r\n\r\nIn multe cazuri, cele doua etape principale ale programarii - conceperea si implementare algoritmului - incep sa se bata cap in cap. Exista situatii in care avem la dispozitie un algoritm foarte eficient, dar implementarea acestuia este extrem de dificila, alteori algoritmul ales nu va face fata volumului maxim de date de intrare, iar alteori ne dam seama ca am putea foarte usor sa scriem un program, dar nu suntem in stare sa demonstram ca el merge sigur pe orice set de date de intrare. Foarte des se renunta la implementarea algoritmilor de complexitate optima, care in multe cazuri constituie adevarate focare de \"bug\"-uri, preferandu-se un algoritm mai lent dar care sa se poate implementa mai rapid si fara dureri de cap. Multi concurenti pierd primii ani de concursuri descoperind aceste lucruri. Desigur, aceste lucruri variaza foarte mult in functie de viteza fiecaruia de a implementa in limbajul preferat (atentie, viteza mare de tastare a unui text normal nu garanteaza neaparat o viteza mare de tastare a unui program!), cat si de abilitatea de a te concentra la toate detaliile care apar in implementare (acest lucru depinde foarte mult de cat de antrenata este mintea fiecaruia). De fapt, concurentii care ies pe primele locuri de obicei, sunt cei care au reusit sa formeze un echilibru intre cele doua etape ale programarii: pot sa conceapa algoritmi eficienti, care sa se incadreze in limitele de timp si memorie, cat si sa implementeze acesti algoritmi intr-un timp acceptabil, depanand foarte putin.\r\n\r\nO intrebare pe care cineva, care citeste aceste randuri, si-o poate pune este urmatoarea: _De ce sa particip la astfel de concursuri?_ Principalele avantaje sunt formarea unei gandiri algoritmice, intelegerea metodelor de rezolvare pentru anumite probleme (care pot aparea si in cadrul dezvoltarii de aplicatii), dezvoltarea capacitatii de a reactiona rapid intr-un timp scurt. In timp, experienta acumulata in cadrul pregatirii si a concursurilor va conduce la eficienta mai mare in cadrul proiectelor de dezvoltare de software si, de ce nu, la obtinerea unor salarii mai mari la angajare. Exista multe companii care iau in considerare participarile la concursuri la interviurile pentru angajare, cat si multe facultati din strainatate care le considera un criteriu pentru primirea unei burse (asta nu inseamna ca o astfel de participare garanteaza neaparat o bursa!). Un alt avantaj ce nu este de neglijat este reprezentat de premiile puse in joc, atat cele materiale (calculatoare, diferite componente hardware, excursii in strainatate, carti, etc.), cat si intrarea fara examen la facultate, in cazut obtinerii unor rezultate bune la olimpiadele nationale sau internationale.\r\n\r\nh2. 2. Care sunt concursurile?\r\n\r\nO alta intrebare la care doresc sa afle raspunsul cei care vor sa participe la concursurile de informatica este: _Care sunt cele mai importante concursuri de programare?_ Se pot clasifica doua mari tipuri de concursuri: cele pentru gimnaziu si liceeni si cele pentru studenti.\r\n\r\nh3. Concursuri pentru liceu\r\n\r\n* **Olimpiada Locala de Informatica** - Se desfasoara in fiecare judet de obicei la inceputul anului (lunile ianuarie-februarie) si, in general, nivelul de dificultate este foarte redus (exceptie facand poate Bucuresti si alte cateva judete), subiectele fiind propuse de profesorii din judetul respectiv.\r\n* **Olimpiada Judeteana de Informatica** - Incepand cu anul 2003 subiectele pentru olimpiada judeteana au fost aceleasi in toata tara; de obicei se desfasoara cu o luna dupa olimpiada locala si cu cel putin o luna inainte de olimpiada nationala; subiectele sunt de un nivel mediu in general.\r\n* \"**Olimpiada Nationala de Informatica**\":http://olimpiada.info - Se organizeaza o data pe an, de obicei in prima vacanta din semestrul II al anului scolar; probele pentru liceu se desfasoara timp de 2 zile, in fiecare zi concurentii avand de rezolvat 3 probleme in 4 ore, iar probele pentru gimnaziu dureaza doar o zi, cate 2 probleme in 3 ore. De asemenea, prima jumatate din clasamentul pentru fiecare clasa de liceu participa la barajele pentru selectia lotului largit de informatica - aici, toti concurentii, indiferent de varsta, au de rezolvat aceleasi probleme. Primii ~20 selectati in urma acestei probe (care se desfasoara tot timp de 2 zile) vor forma lotul national largit; acestia vor participa la mai multe pregatiri, in cadrul carora sunt incluse baraje pentru selectarea echipelor de cate 4 elevi care vor reprezenta Romania la BOI, CEOI si IOI.\r\n* **Balcaniada de Informatica** (BOI) - Prima editie a avut loc la Constanta in anul 1993. Standardele acestui concurs nu erau foarte ridicate, iar concurentii romani se claseaza foarte des pe primele locuri. Cel mai concludent exemplu in acest sens este faptul ca la editia din anul 2001 toate cele patru medalii de aur au fost obtinute de reprezentantii nostri, iar in 2005 ambele medalii de aur acordate au revenit iarasi romanilor. Exista si ani cand nivelul de dificultate al problemelor este mai ridicat, spre exemplu in 2003(Romania) si 2004(Bulgaria).\r\n* **Olimpiada de Informatica a Europei Centrale** (CEOI) - Prima editie a avut loc la Cluj-Napoca in anul 1994. Editia din 2000 a acestui concurs a avut loc tot la Cluj-Napoca si foarte probabil editia din 2009 va fi tot in Romania. Standardele acestui concurs sunt mai ridicate decat cele de la BOI, deoarece elevii din tarile participante sunt intotdeauna foarte bine pregatiti.\r\n* **Olimpiada Internationala de Informatica** (IOI) - Acest concurs reuneste anual elevi din ~80 tari ale lumii. Fiecare tara este reprezentata de cel mult patru concurenti, iar numarul tarilor participante creste in fiecare an. Organizarea concursului este asemanatoare cu cea a celorlalte concursuri internationale mentionate. Concursul este individual si se desfasoara sub forma a doua probe. La fiecare proba concurentii au la dispozitie 5 ore pentru a rezolva 3 probleme cu un grad ridicat de dificultate. Dupa fiecare proba, programele concurentilor sunt evaluate automat, cu ajutorul unor programe de evaluare. Dupa cele doua zile de concurs se stabileste clasamentul final si se acorda medaliile. Rezultatele sunt secrete pana in momentul decernarii premiilor. La aproape toate editiile acestui concurs, echipa Romaniei a avut rezultate excelente. Astfel, incepand din anul 1993, cu doar doua exceptii, toti cei patru componenti ai echipei tarii noastre au obtinut medalii; conform punctajelor individuale, s-au obtinut doua locuri I (1993 si 1998) cu punctaj maxim si un loc II (2001), iar in clasamentul pe natiuni Romania este o prezenta constanta in primele 10 locuri.\r\n\r\nMai exista si alte concursuri internationale, cum ar fi **Olimpiada Tarilor Baltice**, la care Romania nu participa. Puteti gasi detalii mai multe despre aceste concursuri, cat si problemele propuse, folosind \"Google\":http://www.google.com. De asemenea problemele si solutiile din ultimii ani pentru concursurile importante pot fi gasite la sectiunea \"Downloads\":http://infoarena.ro/downloads a site-ului \"infoarena\":http://infoarena.ro, acesta fiind actualizat periodic.\r\n\r\nExista cateva concursuri regionale si nationale similare olimpiadelor (difera timpul de concurs, numarul de probe si dificultatea problemelor). Cateva dintre acestea sunt:\r\n\r\n* **Marele Premiu al Palatului Copiilor** - concurs organizat la Palatul National al Copiilor din Bucuresti; participa echipe ale Cluburilor Copiilor din mai multe judete ale tarii\r\n* **Concursul \"Grigore C. Moisil\"** - organizat anual la Lugoj; are o desfasurare similara\r\n* diferite concursuri interjudetene organizate in anumite regiuni ale tarii; mai multe astfel de concursuri poarta numele lui Grigore Moisil; alte concursuri sunt **Info-Oltenia**, **LInfo@SV**, **Urmasii lui Moisil**, etc.\r\n* Stelele Informaticii - concurs cu organizare asemanatoare cu Olimpiada Nationala de Informatica; participarea la acesta se face doar pe baza de invitatie.\r\n\r\nDe obicei aceste manifestari sunt mai ample; la aceste concursuri exista si alte sectiuni, cum ar fi cele dedicate dezvoltarii de aplicatii software sau de pagini web.\r\n\r\nExista de asemenea numeroase concursuri on-line, la care concurentii participa de acasa si isi trimit solutiile prin intermediul internetului. Desigur, nu se pot acoperi integral toate concursurile disponibile pe internet in acest articol. Este foarte importanta citirea regulamentului inainte de rezolvarea problemelor, deoarece pot exista restrictii care difera de la caz la caz. Datorita faptului ca majoritatea acestor concursuri sunt internationale, cunoasterea limbii engleze devine o necesitate pentru a putea participa. Pentru o pregatire cat mai eficienta, se recomanda participarea la acest tip de concursuri, atat pentru valoarea premiilor puse in joc, cat si ca modalitate de antrenament.\r\n\r\n* \"**preONI**\":http://infoarena.ro - Un concurs organizat in scopul pregatirii pentru Olimpiada Nationala de Informatica, organizat de catre studenti si elevi, actuali si fosti olimpici nationali si internationali. In ultimii 3 ani acest concurs a fost organizat de \"echipa infoarena\":http://infoarena.ro/echipa-infoarena, un grup de olimpici care administreaza primul (si singurul la momentul acesta) site din Romania cu evaluator disponibil 24 din 24. Acest concurs este intr-o continua expansiune, devenind din ce in ce mai complex de la an la an. Pe langa preONI, echipa infoarena organizeaza si alte concursuri; calitatea si valoarea concursurilor organizate precum si a materialelor educationale ce sunt puse la dispozitie este recunoscuta atat de elevi cat si de profesori de renume in informatica.\r\n* \"**.campion**\":http://campion.edu.ro - Problemele de pe acest site sunt propuse de membri ai Comisiei Olimpiadei Nationale; concursul este structurat in runde de pregatire care dureaza in mod normal 10 zile, si in runde de concurs, care dureaza doar 3 ore; tipul rundei alterneaza. Primii clasati se intalnesc la \"marea finala\", care se desfasoara sub forma unei probe de concurs, similara cu olimpiadele - castigatorii primesc premii.\r\n* \"**Bursele Agora**\":http://www.ginfo.ro - Printre cele mai vechi concursuri care inca se desfasoara, este organizat de redactia GInfo; formatul acestuia difera de la an la an, in ultimii doi ani fiind structurat in 50 de runde normale + o runda finala. La acest concurs se acorda burse pentru primii doi clasati in valoare de 50$ si 30$\r\n* \"**USACO**\":http://www.usaco.org - Un concurs prin intermediul caruia se selecteaza lotul national largit al SUA. Concursul consta in mai multe faze, desfasurate pe parcursul anului. Prin bunavointa organizatorilor, concursul a devenit international, iar ultimele editii au adus ca noutate traducerea problemelor in mai multe limbi, printre care, uneori, si limba romana.\r\n* **site-uri ACM** - exista site-uri care va pun la dispozitie si cate o arhiva foarte bogata de probleme si pot fi folosite cu succes in pregatirea pentru olimpiade, si care organizeaza concursuri, mai ales in perioada dinaintea concursurilor regionale ACM: astfel de site-uri sunt: http://acm.uva.es, http://acm.timus.ru, http://acm.sgu.ru, http://spoj.sphere.pl, http://acm.pku.edu.cn, http://acm.zju.edu.cn. Pentru o lista mai mare de site-uri de pregatire accesati sectiunea \"Links\":http://infoarena.ro/links, o lista permanent actualizata.\r\n* \"**Internet Problem Solving Contest**\":http://ipsc.ksp.sk - concurs organizat o data pe an. In cadrul acestui concurs se pun la dispozitie enunturile problemelor si fisierele de intrare si se asteapta fisierele de iesire corespunzatoare, fara a se cere si programele care rezolva problemele.\r\n\r\nAlte concursuri de programare, dar pe echipe, sunt **Bits\'n\'Bytes**, **BitWise** si **International Online Programming Contest**; la acestea pot participa si studenti. In anii precedenti au mai fost organizate si alte concursuri la noi in tara asemanatoare cu cele precizate mai sus precum **Lista lui Francu**, **Cupa Compaq**, **Cupa Fujitsu-Siemens**, **OlimpiadaOnline**, **Algoritmus**.\r\n\r\nh3. Concursuri pentru studenti\r\n\r\n* \"**ACM**\":http://www.acm.ro - un concurs organizat pentru studenti, de natura algoritmica. Diferentele majore fata de concursurile de liceu sunt reprezentate de faptul ca un program trebuie sa rezolve toate seturile de date de intrare prezentate pentru a se acorda puncte (nu se mai acorda punctaje partiale) si viteza cu care se rezolva problemele conteaza, iar evaluarea programelor este imediata. Concursul este pe echipe de cate 3 persoane, toate la un singur calculator. Concursul are loc pe regiuni initial (Centrul Europei, Sudul Europei, etc.) iar echipele calificate se intalnesc la marea finala.\r\n* \"**TopCoder**\":http://www.topcoder.com - un site care organizeaza concursuri saptamanal, cat si turnee. Formatul este diferit fata de orice concurs intalnit pana acum, si anume fiecare concurent are de rezolvat 3 probleme in 75 de minute: o problema usoara de 250 puncte, una medie de 500 puncte si una grea de 1000 puncte. Punctajul efectiv pentru o problema se da in functie de viteza cu care aceasta este rezolvata. De asemenea, exista si o etapa de \"challenge\", in care concurentii pot vedea sursele celorlalti si, in caz ca determina un bug intr-o sursa, pot sa ruleze sursa respectiva, iar daca da raspuns gresit concurentul primeste 50 de puncte, altfel este penalizat cu 25 de puncte. Aceste concursuri sunt diferite fata de cele din liceu in care accentul este pe realizarea unui algoritm eficient, deoarece aici se pune accentul mai mult pe o implementare rapida si corecta a unor probleme care folosesc variatii ale unor algoritmi destul de cunoscuti, dar fiind necesara tratarea diferitelor cazuri speciale ce pot aparea. Ca avantaje, premiile la turnee sunt foarte mari (20.000$ pentru primul clasat), iar intregul sistem de punctare este mult mai complex si mai eficient. Google organizeaza impreuna cu TopCoder concursul \"**Google Code Jam**\":http://www.google.com/codejam.\r\n\r\nh2. 3. Inainte de concurs\r\n\r\nDin fericire pentru unii si din nefericire pentru altii, majoritatea examenelor iti cer sa dovedesti nu ca esti bine pregatit, ci ca esti mai bine pregatit decat altii. Aceasta inseamna ca si la olimpiada de informatica se aplica legea concurentei. Valoarea absoluta a fiecaruia nu conteaza chiar in totalitate, ceea ce constituie sarea si piperul concursului. Intr-adevar, ce farmec ar avea sa mergi la un concurs la care sa se stie inca dinainte cine este cel mai bun? Este destul de amuzant sa observi cum fiecare spera sa prinda \"o zi buna\", iar adversarii sai \"o zi proasta\". Expresia \"de la extaz la agonie\" se potriveste foarte bine uneori cu ceea ce se poate intampla la concursurile de informatica.\r\n\r\nExperienta demonstreaza ca, oricat de mare ar fi bagajul de cunostinte acumulat de un elev, mai e nevoie de ceva pentru a-i asigura succesul la olimpiada de informatica. Aceasta deoarece in timp de concurs lucrurile stau cu totul altfel decat in fata calculatorului de acasa sau de la scoala. Reusita depinde, desigur, in cea mai mare masura de puterea fiecaruia de a pune in practica ceea ce a invatat acasa. Numai ca in acest proces intervin o serie de factori care tin de temperament, de experienta individuala, de numarul de ore dormite in noaptea dinaintea concursului (care in taberele nationale este ingrijorator de mic) si asa mai departe. Trebuie spus ca un concurs de informatica presupune mai mult decat un simplu act de prezenta la locul desfasurarii ostilitatilor. Este chiar trist de remarcat cum spiritul competitiv capata de multe ori tente malitioase.\r\n\r\nPrimul si cel mai de seama lucru pe care trebuie sa il stiti este ca e important si sa participi, dar e si mai important sa participi onorabil, sa dai dovada de fair-play, iar daca se poate, sa si castigi! :) Nu trebuie sa porniti la drum cu ingamfare; modestia e buna, dar nu trebuie in nici un caz sa duca la neincredere in sine! Fiecare trebuie sa stie clar de ce e in stare si, mai presus de toate, sa se gandeasca ca la urma urmei nu dificultatea concursului conteaza, caci concursul, greu sau usor, este acelasi pentru toti. Mult mai importanta este valoarea individuala si nu in ultimul rand pregatirea psihologica. Fiecare concurs reprezinta de asemenea un prilej de perfectionare: fiecare concurent trebuie sa-si analizeze comportamentul din timpul concursului, si sa determine ce aspecte pot fi imbunatatite pentru a obtine performante mai bune la urmatoarele concursuri. Pregatirea psihologica este de multe ori neglijata si reprezinta pentru unii exact acel lucru care il impiedica sa obtina performantele dorite. Exista destui concurenti care uita faptul ca aceste concursuri sunt doar niste concursuri, si ajung sa creada ca cel mai important lucru din viata lor este performanta lor la concursuri - fapt care poate fi foarte daunator in cazul unor esecuri. Asadar, recomand tuturor concurentilor sa adopte o atitudine relaxata si optimista la concursuri, sa realizeze ca acestea reprezinta doar o mica parte din viata, si nu in ultimul rand sa se distreze!\r\n\r\nO pregatire intensa inaintea unui concurs este foarte importanta deoarece imbunatateste viteza de implementare si reduce riscul aparitie erorilor, dar nu poate rezolva anumite lacune teoretice. Formula pentru succes poate fi descrisa ca \"90% munca, 10% talent\". Pentru a obtine performante mari trebuie neaparat o pregatire intensa adecvata. Exista mai multe aspecte ale pregatirii:\r\n\r\n* Pregatirea teoretica\r\n* Pregatirea psihica\r\n* Organizarea globala a pregatirii\r\n* Simularea unor probe de concurs\r\n* Discutiile cu alti elevi si profesori referitor la anumite probleme\r\n* Pregatirea de la locul desfasurarii probei\r\n\r\nDesigur, un alt aspect care trebuie luat in considerare este supra-antrenamentul! Da, acest concept exista si in concursurile de informatica. Se intampla de obicei ca dupa un antrenament prea greu, mintea sa nu reactioneze la fel de bine ca inainte, fiindca este obosita. De aceea, se si recomanda minim o saptamana de pauza si relaxare totala inainte de orice concurs major.\r\n\r\nh3. Pregatirea teoretica\r\n\r\nMajoritatea problemelor propuse spre rezolvare la concursuri depasesc cu mult nivelul manualelor de informatica. De exemplu, desi se propun o multime de probleme a caror rezolvare implica detinerea de cunostinte din domeniul teoriei grafurilor, nu toti algoritmii necesari sunt cuprinsi in programa de invatamant. Pentru a rezolva lacunele teoretice, este necesara studierea unor carti care sa acopere un spatiu teoretic cat mai vast.\r\n\r\nUnele carti isi propun sa initieze cititorul in tainele diverselor limbaje de programare, altele pun accentul mai cu seama pe tehnicile de programare si structurile de date folosite in rezolvarea problemelor. In general, cele din prima categorie contin exemple cu caracter didactic si exercitii cu un grad nu foarte ridicat de dificultate, iar celelalte demonstreaza matematic fiecare algoritm prezentat, insa neglijeaza partea de implementare, considerand scrierea codului drept un ultim pas lipsit de orice dificultate. Desigur, fiecare din aceste carti isi are rostul ei in formarea unui elev bine pregatit in domeniul informaticii. Totusi, trebuie considerata observatia ca scrierea unui program impune atat conceperea algoritmului si demonstrarea corectitudinii, cat si implementarea lui, ambele etape fiind complexe si nu lipsite de obstacole.\r\n\r\nCateva dintre cartile care ar trebui parcurse sunt in special cele scrise de fosti olimpici; prin intermediul acestora, autorii va impartasesc o parte din experienta acumulata. Cele mai folositoare carti (unele nu se mai gasesc) pentru pregatire sunt (unele nu sunt disponibile in Romania):\r\n\r\n* **Introducere in Algoritmi (Cormen, Leiserson, Rivest)** - \"Biblia\" algoritmilor; mai este numita si CLR. Traducerea in limba romana a primei editii a acestei carti este disponibila la editura Agora Computer Libris si acum oricine este interesat o poate achizitiona. Contine o descriere amanuntita a tuturor algoritmilor de baza care pot fi folositi in rezolvarea problemelor de concurs.\r\n* **Arta Programarii Calculatoarelor Vol. 1-3 (Donald Knuth)** - Donald E. Knuth este celebru datorita muncii sale de pionierat in domeniul algoritmilor si al tehnicilor de programare; \"Daca te crezi un bun programator... citeste Arta Programarii Calculatoarelor de Knuth... Daca poti citi toata cartea, trimite-mi neaparat un C.V.\" - Bill Gates. Cartile se pot gasi la noi in tara la editura Teora\r\n* **Proiectarea si implementarea algoritmilor (Mihai Oltean)** - aparuta la editura Computer Libris Agora din Cluj-Napoca; este o resursa foarte buna pentru programare dinamica\r\n* **Culegere de probleme si programe PASCAL (Mihai Stroe, Cristian Cadar)** - aparuta la editura Petrion din Bucuresti, contine un capitol introductiv bun despre geometrie, cat si diverse solutii interesante la probleme din concursuri\r\n* **Psihologia concursurilor de informatica (Catalin Francu)** - aparuta la editura L&S din Bucuresti; de asemenea contine solutii interesante la anumite probleme\r\n* **Informatica - culegere de probleme pentru liceu (Emanuela Cerchez)** - aparuta la editura Polirom, contine diverse aplicatii pentru metodele principale de programare\r\n* **Probleme de informatica date la concursurile internationale (Radu Berinde, Dan Ghinea, Horia Andrei Ciochina, Cornel Margine)** - aparuta la editura Fundatiei Pro, contine rezolvari pentru problemele de la principalele concursuri internationale din ultimii ani\r\n* **Fundamentele programarii - Culegere de probleme pentru clasa a IX-a / clasa a X-a (Dana Lica, Mircea Pasoi)** - aparute la editura L&S din Bucuresti, ambele contin un capitol mare de probleme propuse pe la concursuri impreuna cu solutii\r\n* **Arbori (Emanuela Cerchez)** - aparuta la editura Tara Fagilor, trateaza in detaliu arborii\r\n* **Probleme de combinatorica si teoria grafurilor (Ioan Tomescu)** - desi este o carte in principal de matematica multe probleme de acolo au aparut la concursurile romanesti\r\n* **Provocarea algoritmilor (Victor Mitrana)** - aparuta la editura Agni, Bucuresti\r\n* **Computational Geometry: An Introduction (Shamos, Preparata)** - o carte de baza pentru geometria computationala\r\n* **Computational Geometry in C (Joseph O\'Rourke)** - alta carte de baza pentru geometria computationala\r\n* **Algorithms (Robert Sedgewick)** - contine informatii despre algoritmii clasici si despre structurile de date cele mai folosite\r\n* **The Algorithm Design Manual (Steven Skiena)** - o carte de referinta, continand implementari ale unui numar mare de algoritmi\r\n* **Programming Challenges: The Programming Contest Training Manual (Steven Skiena, Miguel Revilla)** - o carte folositoare mai ales pentru concursurile ACM\r\n\r\nIn afara de cartile mentionate, internetul se dovedeste din nou o resursa foarte importanta. O cautare pe internet poate localiza informatii interesante: descrierea unor anumiti algoritmi impreuna cu performantele lor, tratari ale unor probleme clasice prin mai multe metode etc. Desigur pe langa carti este recomandat sa se si lucreze cat mai multe probleme de la editiile anterioare ale concursurilor principale si de pe site-urile cu evaluator disponibil 24 din 24. Astfel de site-uri sunt:\r\n\r\n* \"infoarena\":http://infoarena.ro\r\n* http://acm.timus.ru\r\n* http://acm.sgu.ru\r\n* http://spoj.sphere.pl\r\n* http://acm.pku.edu.cn\r\n* http://acm.zju.edu.cn\r\n* http://ace.delos.com/usacogate\r\n* http://www.oi.edu.pl/php/show.php?ac=e100000 (Site cu problemele polonezilor - o resursa foarte buna de pregatire, desi nu detine evaluator online)\r\n\r\nh3. Pregatirea psihica\r\n\r\nDupa cum s-a mai zis, este cunoscut faptul ca o atitudine mentala pozitiva este cheia succesului in cele mai multe situatii. Din nefericire, unii concurenti incep proba cu un moral nu tocmai ridicat. Iata cateva din falsele probleme cu care se confrunta anumiti concurenti:\r\n\r\n* _Participa si X, care e mai bun ca mine, deci nu am nici o sansa sa castig!_\r\nFals! Nu s-a demonstrat ca X este mai bun, cel mult a obtinut rezultate mai bune pana acum si poate avea sanse mai mari. Problemele din concursul curent sunt aceleasi pentru toti, conditiile de desfasurare sunt aceleasi si antecedentele nu conteaza. Totul se reia de la zero. In plus, participarea la un concurs puternic poate aduce mai multa experienta pentru viitor. Pentru a ajunge la valoarea necesara castigarii unor concursuri, trebuie sa participati la cat mai multe si sa le tratati cu seriozitate.\r\n* _Am obtinut prea putine puncte in prima zi, nu mai am nici o sansa la premii!_\r\nProblemele de la concursurile cu mai multe probe sunt, in general, destul de dificile. De multe ori, la Olimpiada Nationala sau la concursurile internationale, obtinerea a jumatate din punctele puse in joc inseamna castigarea unui premiu. Daca in prima zi rezultatele obtinute sunt nesatisfacatoare, un rezultat foarte bun in ziua a doua poate aduce premiul dorit. In ultimii ani pentru intrarea in lotul national largit, la barajele de selectie, a fost suficienta obtinerea a mai putin de 200 puncte, dintre cele 600 posibile.\r\n* _Nu sunt suficient de bine pregatit!_\r\nAceasta apreciere este, uneori, mai realista. Totusi, trebuie sa stiti ca o foarte mare importanta o are inspiratia de moment sau norocul (poate problemele vor fi similare cu unele rezolvate anterior). Evident, optimismul exagerat poate, la randul sau, sa fie daunator. Cel mai bine ar fi sa adoptati atitudinea cea mai potrivita pentru propria personalitate. Veti observa, in timp, care este aceasta.\r\n* _Problema asta e grea si n-am s-o pot rezolva perfect, asa ca nu ma mai apuc deloc de ea!_\r\nEste usor sa fii printre cei mai buni atunci cand concursul este usor. Mai greu e sa fii cel mai bun atunci cand concursul este dur, pentru ca atunci intervine - inevitabil - dramul de noroc al fiecaruia. Niciodata insa nu se poate invoca greutatea concursului drept o scuza pentru un eventual esec. Concursul este la fel de greu pentru toti. Se poate intampla, mai ales daca probele dureaza mai multe zile (2-3) ca nici unul din concurenti sa nu acumuleze mai mult de 50-60% din punctajul maxim. Totusi, aceasta nu inseamna ca ei nu sunt bine pregatiti; mai mult, unul dintre ei trebuie sa fie primul. Asadar, niciodata nu trebuie adoptata o strategie de genul acesta. Nu trebuie sa va impacientati daca vi se intampla sa nu aveti o idee geniala de rezolvare a unei probleme. Nu va cere nimeni sa faceti perfect o problema, ci numai sa prezentati o solutie care sa acumuleze cat mai multe puncte. Evident, prima varianta este intotdeauna preferabila, dar nu obligatorie. De multe ori se intampla ca un elev sa gaseasca o solutie cat de cat buna la o problema si, macar ca stie ca nu va lua punctajul maxim, ci doar o parte, sa renunte sa caute o solutie mai eficienta, deoarece timpul pierdut astfel ar aduce un castig prea mic si ar putea fi folosit la rezolvarea altor probleme. Desigur, daca nu faci toate problemele perfect, nu mai poti fi sigur de locul I, pentru ca altcineva poate sa te intreaca. Dar pe de alta parte, locul pe care te clasezi conteaza numai la etapa nationala a olimpiadei sau la concursurile internationale. In rest, important e numai sa te califici, adica sa intri in primele cateva locuri.\r\n\r\nPregatirea psihica nu are legatura numai cu concursul propriu-zis. O atitudine mentala pozitiva, de invingator, este utila pe tot timpul pregatirii pentru concursuri.\r\n\r\nh3. Organizarea globala a pregatirii\r\n\r\nAcest aspect poate contribui la obtinerea unor rezultate excelente. O parte foarte importanta a unei pregatiri sistematice consta in elaborarea unei liste cu metodele si tehnicile cunoscute si necunoscute, punctele slabe, etc. Lista trebuie sa contina algoritmii care apar in mod frecvent in cadrul problemelor de concurs, problemele care apar la implementare, la organizarea timpului in concurs, etc. Continului listei se modifica in timp; o parte din algoritmii necunoscuti sunt invatati si devin cunoscuti, se descopera noi puncte slabe, se evidentiaza existenta unor algoritmi necunoscuti care trebuie invatati, etc. Aceasta este o modalitate excelenta de a masura progresul si de a gasi noi directii de urmat in pregatire.\r\n\r\nh3. Simularea unor probe de concurs\r\n\r\nCea mai potrivita modalitate de pregatire pentru a face fata unei situatii este simularea ei, adica tratarea unei situatii asemanatoare. Acest principiu este valabil in orice tip de competitie, aplicandu-se si in domeniul concursurilor de programare. Daca va pregatiti pentru un concurs, citirea unor carti nu este suficienta! Trebuie sa va analizati comportamentul in situatii similare. Situatia cea mai asemanatoare unui anumit concurs este un alt concurs de acelasi tip. Participarea la N concursuri creste sansele obtinerii unui rezultat mai bun la al N+1-lea.\r\n\r\nConcursurile de pe internet sunt destul de dese si sunt organizate foarte bine. Din nefericire, nivelul de dificultate al acestor concursuri nu este intotdeauna cel dorit de cel care se pregateste. O posibilitate de simulare a unui concurs este rezolvarea problemelor de la o editie precedenta! De exemplu, cineva care se pregateste pentru Olimpiada Nationala ar trebui sa rezolve problemele date la Olimpiada Nationala din anul anterior la clasa respectiva (exista si cazuri in care simulari de acest tip nu sunt foarte concludente; de exemplu, intre 2000 si 2001 programa scolara a suferit cateva variatii, care s-au reflectat in tipul problemelor de la clasa a X-a). Pentru ca simularea sa reflecte cat mai bine realitatea, problemele se rezolva in timpul stabilit, fara pauze, la prima citire (sau, daca au fost citite anterior, nu se recitesc in zilele premergatoare simularii). Experienta obtinuta este apropiata de cea a concursului propriu-zis, dar lipseste stresul care apare, inevitabil, in timpul competitiei. Este important ca, dupa fiecare simulare sau concurs real, sa va analizati comportarea si sa invatati din eventualele greseli de abordare (de exemplu, puteti ajunge la concluzii de genul _Aceasta problema trebuia abordata prima_ sau _Nu am citit integral enuntul si am rezolvat o alta problema_). Concluziile analizei duc la detectarea actiunilor necesare pentru a imbunatati situatia.\r\n\r\nIn plus, se recomanda notarea celor mai frecvente greseli de implementare si examinarea periodica a listei (inclusiv in timpul depanarii programelor, in cadrul simularii concursurilor); in acest fel, greselile respective vor disparea in timp.\r\n\r\nh3. Discutiile cu alti elevi si profesori\r\n\r\nPuteti invata foarte mult de la profesori, si in special de la elevi mai experimentati! Exista foarte multe exemple de elevi pentru care a contat foarte mult pregatirea individuala, dar exista unii care au fost ajutati de pregatirea organizata, in grupuri de elevi, sub indrumarea unor profesori cu preocupari de acest gen. In cadrul pregatirilor de acest tip se discuta algoritmi, se propun probleme spre rezolvare, se discuta diversele modalitati de rezolvare, se obtin mai multe informatii despre concursuri, etc. In plus, elevii aduc in discutie diverse probleme cu care s-au intalnit in cadrul pregatirii individuale. Daca doriti sa participati la astfel de pregatiri, trebuie sa luati legatura cu alti elevi interesati de concursuri, sau cu profesori care se ocupa de pregatirea elevilor pentru olimpiade. In prezent se organizeaza pregatiri la nivel de liceu, oras, judet, etc. in anumite zone. Astfel de pregatiri cresc valoarea tuturor participantilor, deci sunt foarte importante. Pregatirile organizate au luat amploare odata cu infiintarea centrelor de excelenta. Pentru a intra in contact cu alti elevi interesati puteti folosi \"forumul infoarena\":http://infoarena.ro/forum si \"forumul revistei GInfo\":http://ba.toptalent.ro/forum.\r\n\r\nh3. Pregatirea de la locul desfasurarii probei\r\n\r\nDesi ar putea parea bizar, acest aspect este foarte important, dar este neglijat de multe ori de catre concurenti. Aceasta pregatire consta in:\r\n\r\n* somn odihnitor in noaptea care precede ziua concursului **(foarte important!)**\r\n* obtinerea atitudinii mentale dorite\r\n* prezentarea la timp in sala, cu toate obiectele necesare\r\n\r\nExista cateva obiecte pe care ar trebui sa le aveti la voi. In timpul concursului trebuie tinuta o evidenta drastica a timpului scurs si a celui ramas. E drept ca in general supraveghetorii anunta din cand in cand timpul care a trecut, dar e bine sa nu va bazati pe nimeni si nimic altceva decat pe voi insiva. Unii pot spune _Ei, ce nevoie am de ceas, oricum am ceasul calculatorului la indemana_. Asa e, dar e incomod sa te opresti mereu la jumatatea unei idei si sa verifici cat e ceasul schimband consola sau minimizand fereastra de lucru. In ceea ce priveste hartia de scris, ea este in mod sigur necesara. De fapt, o parte importanta a rezolvarii unei probleme este proiectarea matematica a algoritmului, lucru care nu se poate face decat cu creionul pe hartie. Pe langa aceasta, majoritatea problemelor opereaza cu vectori, matrice, arbori, grafuri, etc., iar exemplele pe care este testat programul realizat trebuie neaparat verificate \"de mana\". Este recomandat sa aveti mereu si hartie de matematica; este foarte folositoare pentru problemele de geometrie analitica, precum si pentru reprezentarea matricelor. Nu in ultimul rand, ar fi bine sa aveti o sticla de suc si o ciocolata; din nefericire, concursul incepe deseori cu intarziere si este bine ca foamea sau setea sa nu va preocupe in timpul rezolvarii problemelor.\r\n\r\nh2. 4. In timpul concursului\r\n\r\nImediat ce primiti problemele, cititi toate enunturile si faceti-va o idee aproximativa despre gradul de dificultate al fiecarei probleme. Neaparat verificati daca se dau limite pentru datele de intrare (numarul maxim de elemente ale unui vector si valoarea maxima a acestora, numarul maxim de noduri dintr-un graf, etc.) si pentru timpii de executie pentru fiecare test. Dimensiunea input-ului poate schimba radical dificultatea problemei. Spre exemplu, pentru un vector cu N &le; 200 elemente, un algoritm O(N^3^) merge rezonabil, pe cand pentru N &le; 2000 acelasi algoritm ar depasi cu mult cele cateva sutimi de secunda care se acorda de obicei. In primele zece minute (sau mai mult) nu se atinge calculatorul. Intotdeauna, cand cititi o problema, este indicat sa intoarceti foaia pentru a vedea daca enuntul continua si pe verso. De obicei, in primele 30 sau 60 de minute ale concursului pot fi adresate intrebari comisiei, pentru a clarifica eventualele ambiguitati din enunturi. Acestea sunt redactate in scris, foile sunt preluate de supraveghetorul din sala si trimise la comisie. Raspunsul s-ar putea sa intarzie, deci este indicat sa nu irositi timpul asteptand raspunsul fara a mai face nimic altceva. Puteti fie sa va ganditi la rezolvarea unei probleme, fie sa incepeti sa implementati (daca exista ceva usor de implementat, cum ar fi o problema simpla sau o rutina pentru citirea datelor de intrare). In majoritatea situatiilor, intrebarile trebuie formulate in asa fel incat raspunsul sa fie _Da_ sau _Nu_. Daca intrebarea nu este astfel exprimata sau daca raspunsul se gaseste in textul problemei, veti primi raspunsul _Fara comentarii_, caz in care va trebui mai intai sa studiati corectitudinea intrebarii si, daca aceasta este corect formulata, sa recititi enuntul problemei. Concurentii trebuie sa profite cat mai mult de aceasta perioada, pentru a clarifica eventualele nelamuriri. Un lucru important este ca nu trebuie sa acceptati raspunsuri daca acestea nu sunt insotite de semnatura unui membru al comisiei.\r\n\r\nFaceti o impartire a timpului pentru problemele ramase proportional cu dificultatea aparenta a fiecarei probleme. In general problemele au punctaje egale. Incercati sa nu depasiti niciodata limitele de timp pe care le-ati fixat. Daca in schimb reusiti sa economisiti timp fata de cat v-ati propus, cu atat mai bine, veti face o realocare a timpului si veti avea mai mult pentru celelalte probleme. Apucati-va de problema **cea mai simpla**. Mai bine sa duceti la bun sfarsit o problema usoara, decat sa va apucati de o problema grea si sa nu terminati nici una. Daca toate problemele par grele, alegeti-o pe cea din domeniul care va este cel mai familiar, in care ati lucrat cel mai mult. Daca va este indiferent si acest lucru, alegeti o problema unde simtiti ca aveti o idee simpla de rezolvare.\r\n\r\nIncepeti sa va ganditi la algoritmi cat mai buni, estimand in acelasi timp si cat v-ar lua ca sa-i implementati. Faceti, pentru fiecare idee care va vine, calculul complexitatii. Nu trebuie neaparat sa gasiti cel mai eficient algoritm, ci numai unul suficient de bun. In general, trebuie ca, dintre toti algoritmii care se incadreaza in timpul de rulare, sa-l alegeti pe cel care este cel mai usor de implementat. Daca algoritmul gasit este greu de implementat, mai cautati altul o vreme. Trebuie insa ca timpul petrecut pentru gasirea unui nou algoritm plus timpul necesar pentru scrierea programului sa nu depaseasca timpul necesar pentru implementarea primului algoritm, altfel nu castigati nimic. Deci nu exagerati cu cautarile si nu incercati sa reduceti dincolo de limita imposibilului complexitatea algoritmului. Mai ales, nu uitati ca programul nu poate avea o complexitate mai mica decat dimensiunea input-ului sau a output-ului. De exemplu, daca programul citeste sau scrie matrice de dimensiune N*N, nu are sens sa va bateti capul ca sa gasiti un algoritm mai bun decat O(N^2^). Dintre toate ideile de implementare gasite (care se incadreaza fara probleme in timp), o veti alege pe cea mai scurta ca lungime de cod.\r\n\r\nIn general, pentru orice problema exista cel putin o solutie, fie si una slaba. Sunt numeroase cazurile cand nu va vine alta idee de rezolvare decat cea slaba. De regula, cand nu aveti in minte decat o rezolvare neeficienta a problemei, care stiti ca nu o sa treaca toate testele (un backtracking, sau un O(N^5^), O(N^6^), etc.) e bine sa incercati urmatorul lucru:\r\n\r\n* Calculati cam cat timp v-ar trebui ca sa implementati rezolvarea slaba. In acest calcul trebuie sa includeti si un timp estimativ de depanare a programului (care variaza de la persoana la persoana) si pe cel de testare. Daca sunteti foarte siguri pe voi, puteti sa neglijati timpul de testare, dar orice program trebuie testat cel putin pe exemplul de pe foaie.\r\n* Pentru a avea sanse mai mari sa gasiti o alta solutie, este indicat sa incercati sa ignorati complet solutia slaba, sa nu o luati ca punct de plecare. Incercati sa va \"goliti\" mintea si sa gasiti ceva nou, altfel va veti invarti mereu in cerc.\r\n* Daca va vine vreo idee mai buna, ati scapat de griji si va apucati de implementare (daca aveti timpul necesar).\r\n\r\nDin acest moment, pentru varianta aleasa veti scrie programul, fara a va mai gandi la altceva, chiar daca pe parcurs va vin alte idei. Iata unele lucruri pe care e bine sa le stiti despre scrierea unui program:\r\n\r\n* Datele de intrare se presupun a fi corecte. Aceasta este o regula nescrisa (uneori) a concursului de informatica.\r\n* Efectul optiunilor de compilare asupra vitezei este semnificativ.\r\n* Daca se poate, evitati lucrul cu pointeri. Programele care ii folosesc sunt mai greu de depanat si se pot bloca mult mai usor.\r\n* Evitati lucrul cu numere reale (comparatii, impartiri, etc.), daca puteti. Operatiile in virgula mobila sunt mult mai lente.\r\n* Alegeti-va numele de variabile in asa fel incat programul sa fie clar. Sunt permise mai mult de doua litere! Numele fiecarei proceduri, functii, variabile trebuie sa-i explice clar utilitatea. E drept, lungimea programului creste, dar codul devine mult mai limpede si timpul de depanare scade foarte mult. Ca o regula generala, claritatea programelor face mult mai usoara intelegerea lor chiar si dupa o perioada mai indelungata de timp (luni, ani). Nu trebuie nici sa cadeti in cealalta extrema. De exemplu, nu depasiti 10 caractere pentru un nume de variabila.\r\n* Salvati programul cat mai des. Daca va obisnuiti, chiar la fiecare 2-3 linii. Dupa ce o sa va intre in reflex n-o sa va mai incomodeze  cu nimic acest obicei. Au fost cazuri in care o pana de curent prindea pe picior gresit multi concurenti, iar dupa aceea nu mai este absolut nimic de facut, pentru ca nimeni nu va va crede pe cuvant ca ati facut programul si ca el mergea.\r\n* Obisnuiti-va sa programati modular. Faceti proceduri separate pentru citirea si initializarea datelor, pentru sortare, pentru afisarea rezultatelor, etc. In general nu se recomanda sa scrieti proceduri in alte proceduri (adica e bine ca toate procedurile sa apartina direct de programul principal). Procedurile, acolo unde e posibil, nu trebuie sa depaseasca un ecran, pentru a putea avea o viziune de ansamblu asupra fiecareia in parte. Acest lucru ajuta mult la depanare.\r\n* Rulati programul cat mai des, daca timpul va permite. In primul rand dupa ce scrieti procedura de citire a datelor. Daca e nevoie de sortarea datelor de intrare, nu strica sa va convingeti ca programul sorteaza bine, ruland 2-3 teste oarecare. E pacat sa pierdeti puncte dintr-o greseala copilareasca.\r\n* O situatie mai delicata apare cand fisierul de intrare contine mai multe seturi de date (teste). In acest caz, atentia trebuie sporita, deoarece daca la primul sau al doilea test programul vostru da eroare si se opreste din executie, veti pierde automat si toate celelalte teste care urmeaza. Daca in fisierul de intrare exista un singur set de date, atunci pierderea din vedere a unui caz particular al problemei nu putea duce, in cel mai rau caz, decat la picarea unui test. Asa insa, picarea unui test poate atrage dupa sine picarea tuturor celor care il urmeaza. Pe langa corectitudinea strict necesara, programul trebuie sa se incadreze si in timp pentru orice fel de test. Daca la primul sau al doilea test din suita programul depaseste timpul (sau, si mai rau, se blocheaza), e foarte probabil sa fie oprit din executie de catre comisie, deci din nou veti pierde toate testele care au ramas neexecutate.\r\n* Tot in situatia in care exista mai multe seturi de date in fisierul de intrare, daca iesirea se face intr-un fisier, este bine ca dupa afisarea rezultatului pentru fiecare test sa actualizati fisierul de iesire. In felul acesta, chiar daca la unul din teste programul se blocheaza sau da eroare, rezultatele deja scrise raman scrise. Altfel, e posibil ca rezultatele de la testele anterioare sa ramana intr-un buffer in memorie, fara a fi \"varsate\" pe disc.\r\n\r\nTot la partea de implementare, este bine ca codul sa fie cat mai scurt si cat mai optimizat - dar, despre scrierea unui cod cat mai eficient se poate face un articol cam la fel de mare cat acesta, deci nu se va trata acest subiect aici - metoda cea mai buna in acest sens este sa invatati din sursele altora. Puteti incepe cu articolele \"_12 ponturi pentru programatorii C/C++_\":http://infoarena.ro/12-ponturi-pentru-programatorii-CC si \"_Multe smenuri de programare in C/C++... si nu numai!_\":http://infoarena.ro/Multe-smenuri-de-programare-in-CC-si-nu-numai si sectiunea \"Links\":http://infoarena.ro/links.\r\n\r\nMai ramane doar partea de depanare. O metoda buna de depanare este urmatoarea:\r\n\r\n* Incepeti cu un test nici prea simplu, nici prea complicat (si usor de urmarit cu creionul pe hartie) si executati-l de la cap la coada. Daca merge perfect, treceti la teste mai complexe (se recomanda **minim** 4 test si maxim 7-8). Daca le trece si pe acestea, puteti zambi. Totusi, daca programul vostru a mers perfect pe 7-8 teste date la intamplare, exista sanse (dar nu extrem de mari!) sa mearga pe majoritatea testelor comisiei, sau chiar pe toate.\r\n* Exemplul dat in enunt nu are in general nici o semnificatie deosebita (de fapt, are mai curand darul de a semana confuzie printre concurenti), iar daca programul merge pe acest test particular, nu inseamna ca o sa mearga si pe alte teste.\r\n* Daca la unul din teste programul nu merge corespunzator, rulati din nou testul , dar de data aceasta procedura cu procedura. Dupa fiecare procedura evaluati variabilele si vedeti daca au valorile asteptate. In felul acesta puteti localiza cu precizie procedura, apoi linia unde se afla eroarea. Corectati in aceasta maniera toate erorile, pana cand testul este trecut.\r\n* In acest moment, luati de la capat toate testele pe care programul le-a trecut deja. In urma depanarii, s-ar putea ca alte greseli sa iasa la suprafata si programul sa nu mai mearga pe vechile teste.\r\n* Repetati procedeul de mai sus pana cand toate testele merg. Daca va obisnuiti sa programati modular si ingrijit, depanarea si testarea n-ar trebui sa dureze mai mult de 5-25 minute. Din acest moment, nu mai modificati nici macar o litera in program, sau daca o faceti pastrati-va in prealabil o copie. Nu va bazati pe faptul ca puteti sa tineti minte modificarile facute si sa refaceti oricand forma initiala a programului in caz ca noua versiune nu va fi buna.\r\n* Daca totusi nu-i puteti \"da de cap\" programului, iar timpul alocat problemei respective expira, aduceti programul la o forma in care sa mearga macar pe o parte din teste si treceti la problema urmatoare.\r\n\r\nFeriti-va ca de foc de criza de timp. E mare pacat sa ratezi o problema intreaga pentru ca n-ai avut timp sa scrii procedura de afisare a solutiei, sau lucruri asemanatoare. Rezervati-va intotdeauna timpul pe care il socotiti necesar pentru implementare si depanare. De asemenea, chiar daca concursul este usor, nu e recomandat sa iesiti din sala de concurs inainte de expirarea timpului. Oricat ati fi de convinsi ca ati facut totul perfect, mai verificati-va; veti avea de furca cu remuscarile daca descoperiti dupa aceea ca ceva, totusi, nu a mers bine. Puteti face o multime de lucruri daca mai aveti timp (desi acest lucru se intampla rar). Iata o serie de metode de a exploata timpul:\r\n\r\n* Verificati-va programul cu cat mai multe teste de mici dimensiuni. Sa presupunem ca programul vostru lucreaza cu vectori de maxim 10.000 de elemente. E o idee buna sa il rulati pentru vectori de unul sau doua elemente.\r\n* Treceti la polul opus si creati-va un test de dimensiune maxima, dar cu o structura particulara, pentru care este usor de calculat rezultatul si de mana. De exemplu, vectori de 10.000 de elemente cu toate elementele egale, sau vectori de forma (1, 2, ..., 9999, 10000). Daca nu puteti sa editati un asemenea fisier de mana, copiind si multiplicand blocuri, puteti scrie un program care sa-l genereze.\r\n* Daca inca v-a mai ramas timp, creati-va un program care sa genereze teste aleatoare. Spre exemplu, un program care sa citeasca N si sa creeze un fisier in care sa scrie N numere aleatoare. Intr-o prima faza, puteti folosi aceste teste pentru a verifica daca nu cumva la valori mai mari programul nu da eroare, nu se blocheaza (la alocarea unor zone mari de memorie) sau nu depaseste limita de timp, caz in care mai aveti de lucru.\r\n* Daca tot nu va da nimeni afara din sala, puteti scrie un alt program auxiliar care, primind fisierul de intrare si fisierul de iesire produs de programul vostru, verifica daca iesirea este corecta. Aceasta deoarece, de obicei, este mult mai usor de verificat o solutie decat de produs una. Folosind \"generatorul\" de teste si \"verificatorul\", puteti testa programul mult mai bine. De altfel, la multe probleme chiar testele rulate de comisia de corectare sunt create tot aleator.\r\n\r\nh2. 5. Dupa concurs\r\n\r\nDupa ce ati terminat problemele (se intampla destul de rar) nu iesiti din sala! Este momentul ultimelor teste. La iesirea din sala trebuie sa fiti convinsi ca ati facut tot ce era posibil in conditiile date. Concursul nu s-a terminat inca! Urmeaza corectarea. Va trebui sa verificati punctajul obtinut si sa fiti pregatit sa depuneti o contestatie daca aveti impresia ca ceva nu este in regula. La unele concursuri, corectarea se face in prezenta concurentului; aici aveti ocazia sa solicitati sa vi se arate testele si iesirile furnizate de programul vostru, sa cereti testarea din afara mediului de evaluare, etc. La alte concursuri, comisia ofera, mai tarziu, testele si raspunsurile corecte pentru autoevaluare. Nu ratati ocazia de a va evalua rezolvarile si nu depuneti contestatii decat daca in urma autoevaluarii obtineti un punctaj mai mare. Fiecare concurs este o experienta in plus! Discutati, dupa proba, cu alti concurenti, aflati cum ar fi trebuit rezolvate problemele pe care nu le-ati stiut aborda si ce au gresit ceilalti (este bine sa invatati si din greselile altora).\r\n\r\nDe multe ori, primul an de participare la olimpiada se soldeaza cu un rezultat cel mult mediu, deoarece, oricat ar spune cineva _Ei, nu-i asa mare lucru sa mergi la un concurs_, experienta acumulata conteaza mult. De aceea, abia de la a doua participare si uneori chiar de mai tarziu incep sa apara rezultatele. Intentia autorului a fost sa va usureze misiunea si sa va dezvaluie cateva din dificultatile de toate felurile care apar la orice concurs, pentru a nu va da ocazia sa le descoperiti pe propria piele. Speram ca aceste ponturi va vor fi de folos!\r\n\r\nh2. Bibliografie\r\n\r\n# **Psihologia concursurilor de informatica**, Catalin Francu, Editura L&S Bucuresti\r\n# \"**Despre Concursuri**\":http://www.ginfo.ro/revista/13_4/babel.pdf, Mihai Stroe, Gazeta de Informatica, numarul 13/4, anul 2003\r\n# \"infoarena\":http://infoarena.ro\r\n# \"Google\":http://www.google.com',2044,'public',3680,NULL),('junior-challenge','Junior Challenge','2007-06-29 19:07:40','2009-03-02 14:42:35','h1. == roundparam(round_id=\"junior_challenge\" param=\"title\") ==\r\n\r\n==include(page=\"templates/junior_head\")==\r\n\r\n_Junior Challenge_ este un concurs dedicat incepatorilor in programare si este o ocazie de antrenament oferita lotului de juniori ce va reprezenta Romania la Olimpiada Balcanica ({_JBOI_}). Runda se desfasoara *Miercuri 4 iulie*, la ora {*09^00^*} si va dura *{color:red}3h*.\r\nParticipantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':junior-challenge/clasament.\r\n\r\nh2. Propunatori\r\n\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")==\r\n* ==user(user=\"crawler\" type=\"tiny\")==\r\n\r\nh2. Organizare \r\n\r\n* == user(user=\"svalentin\" type=\"tiny\") ==\r\n* == user(user=\"filipb\" type=\"tiny\")==\r\n\r\nCu ajutor din partea\r\n\r\n* == user(user=\"fluffy\" type=\"tiny\") ==\r\n* == user(user=\"wickedman\" type=\"tiny\") ==\r\n* ==user(user=\"crawler\" type=\"tiny\")== : sigla\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"junior_challenge\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nPoti citi ultimele mesaje in legatura cu concursul pe forum.\r\n\r\n==SmfTopics(board_id=\"44\" count=\"10\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n',1490,'protected',NULL,NULL),('junior-challenge/clasament','junior_challenge/clasament','2007-06-29 20:09:04','2009-03-02 14:42:17','h1. == roundparam(round_id=\"junior_challenge\" param=\"title\") ==\r\n\r\n==include(page=\"templates/junior_head\")==\r\n\r\nAici este clasamentul pentru concursul _Junior Challenge_. Mai multe detalii despre concurs gasiti \'aici\':junior-challenge.\r\n\r\np<. == Rankings(rounds=\"junior_challenge\") == ',1490,'protected',NULL,NULL),('junior-challenge/solutii','junior-challenge/solutii','2007-07-04 09:09:53','2009-08-14 17:23:25','==include(page=\"templates/junior_head\")==\r\n\r\nh1. Rezolvarile problemelor date in concurs\r\n\r\nh2. \'Teams\':problema/teams\r\n\r\nh3. ( problema usoara )\r\n\r\nrezolvarea $O(n^2^)$:\r\n - se ia fiecare pereche de pokemoni $(i,j)$ cu $i<j$ si se verifica daca este valida\r\n - o astfel de solutia ar fi adus $50-70%$ din punctaj in functie de implementare\r\n\r\nrezolvarea $O(n log n)$:\r\n\r\n - se sorteaza sirul \r\n - pentru fiecare pokemon se cauta binar intervalul de pokemoni cu care poate forma o echipa \r\n\r\nrezolvarea $O(n)$:\r\n\r\n - se calculeaza $v[i]$ = numarul de pokemoni cu forte mai mici sau egale cu $i$\r\n - pentru fiecare pokemon se adauga la solutie numarul de pokemoni din intervalul cu care poate forma o echipa (atentie, un pokemon nu poate forma o echipa cu el insusi)\r\n\r\n\r\nh2. \'Panou\':problema/panou\r\n\r\nh3. ( problema medie )\r\n\r\nIn primul rand observam ca nu are sens sa actionam un comutator de 2 sau mai multe ori. Plecam de pe linia $N$, coloana $N$ a panoului $A$. Daca $A[N][N]!=B[N][N]$ este clar ca trebuie sa actionam comutatorul situat pe aceasta pozitie. Apoi ne uitam la pozitiile $(N, N-1)$ $(N, N-2)$ .. $(N, 1)$ in ordinea aceasta si procedam similar (unele comutari vor fi fortate). Apoi ne uitam la pozitiile $(N-1, N)$ $(N-2, N)$ .. $(1, N)$ si iarasi unele dintre aceste pozitii vor trebui comutate neaparat. Continuam acest algoritm pentru fiecare pozitie $(i, i)$ din panoul $A$, variabila $i$ fiind parcursa descrescator. O implementare directa a algoritmului are complexitate $O(N^3^)$, pentru a reduce complexitatea la $O(N^2^)$ observam ca la un moment dat, noi trebuie sa stim in ce stare se afla becul situat pe o pozitie $(i, j)$. Starea in care se afla acest bec este $(A[i][j]+L[i]+C[j])%2$, unde $A[i][j]$ reprezinta starea initiala a becului, $L[i]$ numarul de comutari efectuate pe linia $i$ pana in prezent, iar $C[j]$ numarul de comutari efectuate pe coloana $j$ pana in prezent. Cum am efectuat doar acele comutari care trebuiau neaparat efectuate acesta este si numarul minim de comutari necesare.\r\n\r\nh2. \'Ordini\':problema/ordini\r\n\r\nh3. ( problema grea )\r\n\r\nSa presupunem ca dorim sa aflam suma numerelor care se pot forma cu cifrele date in care ignoram conditia care impune ca prima cifra sa fie nenula. Fie $N$ numarul total de cifre ( din restrictiile problemei $N < 1001$ ). Folosind descompunerea in baza 10, rezultatul se va scrie sub forma {$c{~N-1~} * 10^N-1^ + c{~N-2~} * 10^N-2^ + ... c{~0~} * 10^0^$}. Daca stim coeficientii {$c{~0~}$}, {$c{~1~}$}, ... {$c{~N-1~}$}, atunci stim si rezultatul ( toate calculele vor fi facute modulo $M$ ). Se observa ca daca intr-un numar format cifra $x$ apare pe pozitia $i$, atunci trebuie sa adunam la coeficientul {$c{~i~}$} numarul {$x * Res$}, unde $Res$ este numarul de numere care se pot forma si in care cifra $x$ apare pe pozitia {$i$} - daca descompunem fiecare numar in baza 10 ca mai sus si dam factor comun {$10^i^$} obtine exact aceasta relatie. Coeficientii c{~0~}, c{~1~}... c{~N-1~} vor fi deci toti egali pentru ca fiecare cifra $x$ poate fi pusa pe orice pozitie.\r\nDaca frecventele cifrelor sunt {$f{~0~}$}, {$f{~1~}$}... {$f{~9~}$}, atunci cifra $x$ poate aparea pe o pozitie in exact !junior-challenge/solutii?formula.jpg! numere, formula care rezulta din calculul numarului de anagrame pentru un cuvant dat, care este dat de factorialul lungimii cuvantului supra produsul factorialelor frecventelor fiecarei litere in parte. Pentru a calcula efectiv acest numar, vom face toate simplificarile posibile ( impartind prin cel mai mare divizor comun dintre doua numere, primul de la numarator si al doilea de la numitor ) si vom obtine in final un sir de numere care trebuie inmultite ( modulo $M$ ).\r\nDaca prima cifra poate fi {$0$}, rezultatul este deci:\r\n!junior-challenge/solutii?formula2.jpg!, unde numarul de $1$ este dat de suma frecventelor cifrelor.\r\nDesi formula pare la prima vedere complicata, ea rezulta destul de usor din formula numarului de anagrame ale unui cuvant dat si din scrierea numerelor in baza $10$.\r\n\r\nDaca prima cifra nu poate fi $0$ procedam in felul urmator: fixam prima cifra $C$ ( de la $1$ la $9$ ), scadem cu $1$ frecventa cifrei selectate si calculam conform rezultatului de mai sus la care mai adaugam {$C * Res * 10^N^$}. In final vom aduna ( tot modulo $M$ ) cele $9$ numere obtinute si afisam rezultatul.\r\n\r\nAceasta este una din solutii care obtinea punctajul maxim in concurs. Exista si solutii mai rapide care folosesc combinari, insa s-a considerat ca aceste cunostinte depasesc nivelul claselor 7-9.\r\n',6234,'public',NULL,NULL),('jboi-2007/prob4-6','jboi-2007/prob4-6','2007-07-04 17:58:46','2007-07-06 09:11:41','h1. Problemele 4-6 pentru pregatirea LOT-ului\r\n\r\n\"Inapoi la pagina\":jboi-2007\r\n\r\nh2. 4.Cow Yahtzee\r\n\r\nIn their usual clumsy way, the cows are play a version of Yahtzee,\r\nthe dice-rolling game.  They roll N (1 <= N <= 20) dice, each having\r\nS (1 <= S <= 8) sides.  They are curious as to the number of ways\r\na dice roll can meet a particular criterion (like \"contains three\r\n2\'s\" or \"contains one 2 and two 3\'s\").\r\n\r\nHelp them learn about probability. Write a program that reads not\r\nonly N and S but also some expressions that describe their criteria.\r\nCount the number ways the expression can be satisfied over the\r\nentire set of all possible dice rolls (the entire set of rolls for\r\nthree two-sided dice is: {1,1,1; 1,1,2; 1,2,1; 1,2,2; 2,1,1; 2,1,2;\r\n2,2,1; 2,2,2};\r\n\r\nExpressions comprise combinations of a basic form that expresses\r\nthe thought \"want at least W copies of result R\". It looks like this:\r\n\r\nWxR\r\n\r\nwhere (0 <= W <= N and 1 <= R <= S). Each test run will supply E\r\nexpressions (1 <= E <= 20), each of which contains a number 1..10\r\nof the basic forms separated by a \'+\', which means \'and\' (see below).\r\nThe set of lines expresses the thought that is the \'inclusive or\'\r\nof each of the lines individually. Thus the pair of expressions\r\nshown below means \"at least three rolls of five OR both at least\r\none roll of 3 and also at least two rolls of 4\":\r\n\r\n3x5\r\n1x3+2x4\r\n\r\nHere are some of the combinations of four five-sided dice that\r\nsatisfy the above expression: 5,5,5,1; 4,5,5,5; 3,4,4,2; 3,4,4,3;\r\n3,4,4,5; 4,4,5,3.\r\n\r\nProgramming note: Be sure to verify that you can read in two integers\r\nfrom one line and a string from the next line. In some languages\'\r\nI/O schema, this is harder than it looks!\r\n\r\nAlso note that the total number of dice combinations will never\r\nexceed 1,512,768 in the supplied test data.\r\n\r\nPROBLEM NAME: cowyotz\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Three space-separated integers: N, S, and E\r\n\r\n* Lines 2..E+1: Line i+1 describes expression i as above.\r\n\r\nSAMPLE INPUT (file cowyotz.in):\r\n\r\n4 5 2\r\n3x5\r\n1x3+2x4\r\n\r\nINPUT DETAILS:\r\n\r\nThis is the encoding of the expression used as an example in the task text.\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: A single integer that is the number of ways the\r\n        expression(s) can be satisfied by rolling the dice in all\r\n        combinations.\r\n\r\nSAMPLE OUTPUT (file cowyotz.out):\r\n\r\n63\r\n\r\nOUTPUT DETAILS:\r\n\r\n63 rolls satisfy the expression.\r\n\r\n\r\nh2. 5.Making Change\r\n\r\nPoor Bessie has taken a job in the convenience store located just\r\nover the border in Slobbovia. Slobbovians use different coinages\r\nthan the USA; their coin values change day-by-day!\r\n \r\nHelp Bessie make optimal change for Slobbovian shoppers. You will\r\nneed to create C (1 <= C <= 1000) cents of change using N (1 <= N\r\n<= 10) coins of various values. All test cases will be solvable\r\nusing the supplied coins.\r\n\r\nIf 5 coins of values 50, 25, 10, 5, and 1 were available, Bessie\r\nwould make optimum change (minimal coins) of 93 cents by using 1 x\r\n50, 1 x 25, 1 x 10, 1 x 5, and 3 x 1 coins (a total of 7 coins).\r\n \r\nHow hard could it be? The final two test cases will be challenging.\r\n\r\nPROBLEM NAME: change\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Two space-separate integers: C and N\r\n\r\n* Lines 2..N+1: Each line contains a single unique integer that is a\r\n        coin value that can be used to create change\r\n\r\nSAMPLE INPUT (file change.in):\r\n\r\n93 5\r\n25\r\n50\r\n10\r\n1\r\n5\r\n\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: A single integer that is the minimum number of coins to\r\n        create C cents\r\n\r\nSAMPLE OUTPUT (file change.out):\r\n\r\n7\r\n\r\nh2. 6.The Bale Tower\r\n\r\nAlways bored with cud-chewing, the cows have invented a new game.\r\nOne cow retrieves a set of N (3 <= N <= 20) hay bales from the shed\r\neach of which is one unit high. Each bale also has some unique width\r\nand unique breadth.\r\n\r\nA second cow tries to choose a set of bales to make the tallest\r\nstack of bales in which each bale can be placed only on a bale whose\r\nown width and breadth are smaller than the width and breadth of the\r\nbale below. Bales can not be rotated to interchange the width and\r\nbreadth.\r\n\r\nHelp the cows determine the highest achievable tower that can be\r\nlegally built form a set of bales.\r\n\r\nPROBLEM NAME: btwr\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: A single integer, N\r\n\r\n* Lines 2..N+1: Each line describes a bale with two space-separated\r\n        integers,respectively the width and breadth\r\n\r\nSAMPLE INPUT (file btwr.in):\r\n\r\n6\r\n6 9\r\n10 12\r\n9 11\r\n8 10\r\n7 8\r\n5 3\r\n\r\n\r\nINPUT DETAILS:\r\n\r\nSix bales of various widths and breadths\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: The height of the tallest possible tower that can legally be\r\n        built from the bales.\r\n\r\nSAMPLE OUTPUT (file btwr.out):\r\n\r\n5\r\n\r\nOUTPUT DETAILS:\r\n\r\nThese bales can be stacked for a total height of 5:\r\n10 12\r\n9 11\r\n8 10\r\n6 9\r\n5 3\r\n[another stacking exists, too]\r\n',1507,'public',NULL,NULL),('jboi-2007/prob7-9','jboi-2007/prob7-9','2007-07-04 18:06:55','2007-07-06 09:11:58','h1. Problemele 7-9 pentru pregatirea LOT-ului\r\n\r\n\"Inapoi la pagina\":jboi-2007\r\n\r\nh2. 7.Wonderprime Brands\r\n\r\nThe cows are forever competing to see who has the best brand. The\r\nlatest rage is brands that are \'Wonderprimes\'. You probably already\r\nknow that a brand consists of a sequence of digits that does not\r\nbegin with 0; brands actually look a lot like positive integers.\r\n\r\nA wonderprime is a number that can be partitioned into two prime\r\nnumbers, each of which has at least D digits and, of course, doesn\'t\r\nstart with 0. When D=2, the number 11329 is a wonderprime (since it\r\nconnects 113 and 29, both of which are prime).\r\n\r\nOnly a few of the cows have wonderprime brands, but they all want\r\none. Your job is to find the first wonderprime greater than or equal\r\nto a supplied integer N (1 <= N <= 2,000,000,000). No integer greater\r\nthan 2,000,000,000 will be required.\r\n\r\nPROBLEM NAME: wpb\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Two space-separated integers: D and N\r\n\r\nSAMPLE INPUT (file wpb.in):\r\n\r\n2 11328\r\n\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: A line that contains the first wonderprime no smaller than\r\n        N.\r\n\r\nSAMPLE OUTPUT (file wpb.out):\r\n\r\n11329\r\n\r\nh2. 8.The Eating Puzzle\r\n\r\nBessie is on a diet where she can eat no more than C (10 <= C <=\r\n35,000) calories per day. Farmer John is teasing her by putting out\r\nB (1 <= B <= 21) buckets of feed, each with some (potentially\r\nnon-unique) number of calories (range: 1..35,000). Bessie has no\r\nself-control: once she starts on a feed bucket, she consumes all\r\nof it.\r\n\r\nBessie is not so good at combinatorics. Determine the optimal\r\ncombination of feed buckets that gives Bessie as many calories\r\nwithout exceeding the limit C.\r\n\r\nAs an example, consider a limit of 40 calories and 6 buckets with\r\n7, 13, 17, 19, 29, and 31 calories. Bessie could eat 7 + 31 = 38\r\ncalories but could eat even more by consuming three buckets: 7 +\r\n13 + 19 = 39 calories. She can find no better combination.\r\n\r\nPROBLEM NAME: eatpuz\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Two space-separated integers: C and B\r\n\r\n* Line 2: B space-separated integers that respectively name the number\r\n        of calories in bucket 1, 2, etc.\r\n\r\nSAMPLE INPUT (file eatpuz.in):\r\n\r\n40 6\r\n7 13 17 19 29 31\r\n\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: A single line with a single integer that is largest number\r\n        of calories Bessie can consume and still stay on her diet.\r\n\r\nSAMPLE OUTPUT (file eatpuz.out):\r\n\r\n39\r\n\r\nh2. 9.Dream Counting\r\n\r\nBessie was daydreaming one day as she drifted between wakefulness\r\nand that delicious drowsiness that we all feel when we are tired.\r\nFor a moment, she counted sheep as couldn\'t quite sleep. Bessie\'s\r\nmind is razor sharp and visualizes the numbers as she counts. She\r\nstarted noticing the digits and wondered: how many instances of\r\neach digit appear in a counting sequence?\r\n\r\nWrite a program to answer this question. Given two integers M and\r\nN (1 <= M <= N <= 2,000,000,000 and N-M <= 500,000), how many of\r\noccurences of each digit appear?\r\n\r\nConsider the sequence 129..137: 129, 130, 131, 132, 133, 134, 135, 136,\r\n137. Count the digits to find:\r\n   1x0      1x5\r\n  10x1      1x6\r\n   2x2      1x7\r\n   9x3      0x8\r\n   1x4      1x9\r\n\r\nPROBLEM NAME: dream\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Two space-separated integers: M and N\r\n\r\nSAMPLE INPUT (file dream.in):\r\n\r\n129 137\r\n\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: Ten space-separated integers that are the counts of the\r\n        number of each digit (0..9) that appears while counting\r\n        through the sequence.\r\n\r\nSAMPLE OUTPUT (file dream.out):\r\n\r\n1 10 2 9 1 1 1 1 0 1\r\n\r\nOUTPUT DETAILS:\r\n\r\nOne zero, ten ones, etc.\r\n',1507,'public',NULL,NULL),('jboi-2007/clasament','JBOI 2007 - Clasament','2007-07-04 18:14:05','2008-02-25 19:59:18','h1. Clasamentul rundelor de pregatire\r\n\r\n\"Inapoi la pagina\":jboi-2007\r\n\r\n# ==User(user=\"vanila_cpp\" type=\"tiny\")== - 1500 pt\r\n# ==User(user=\"cezarmocan\" type=\"tiny\")== - 1300 pt\r\n# ==User(user=\"tvlad\" type=\"tiny\")== - 1240 pt\r\n# ==User(user=\"raduzer\" type=\"tiny\")== - 1220 pt',6679,'public',NULL,NULL),('jboi-2007','JBOI 2007','2007-07-04 17:39:30','2008-10-12 20:45:32','h1. 1st Junior Balkan Olympiad in Informatics \r\n\r\n!jboi-2007?boij.jpg!\r\n\r\nAceasta pagina este dedicata primei editii a Olimpiadei Balcanice de Informatica pentru Juniori. Aici se vor gasi materiale necesare lotului Romaniei.\r\n\"Site-ul oficial al JBOI\":http://www.jboi2007.org/\r\n\r\nh2. Componenti ai lotului\r\n\r\n* ==User(user=\"vanila_cpp\" type=\"normal\")==\r\n* ==User(user=\"cezarmocan\" type=\"normal\")==\r\n* ==User(user=\"tvlad\" type=\"normal\")==\r\n* ==User(user=\"raduzer\" type=\"normal\")==\r\n\r\n\"Clasamentul rundelor de pregatire\":jboi-2007/clasament\r\n\r\nh2. Problemele de la rundele de pregatire\r\n\r\n* \"Probleme 1-3 -> Runda 1\":jboi-2007/prob1-3\r\n* \"Probleme 4-6 -> Runda 2\":jboi-2007/prob4-6\r\n* \"Probleme 7-9 -> Runda 3\":jboi-2007/prob7-9\r\n* \"Probleme 10-12 -> Runda 4\":jboi-2007/prob10-12\r\n* \"Probleme 13-15 -> Runda 5\":jboi-2007/prob13-15\r\n\r\nh2. Evaluator from ==User(user=\"crawler\" type=\"tiny\")==\r\n\r\n\"Download evaluator\":jboi-2007?action=download&file=eval.exe\r\n\r\n',1490,'public',NULL,NULL),('jboi-2007/prob1-3','jboi-2007/prob1-3','2007-07-05 12:34:56','2007-07-06 09:11:22','h1. Problemele 1-3 pentru pregatirea LOT-ului\r\n\r\n\"Inapoi la pagina\":jboi-2007\r\n\r\nh2. Buy One Get One Free\r\n\r\n\r\n\r\nFarmer John has discovered the Internet is buying bales of hay\r\nonline when he notices a special deal. For every bale of hay of\r\nsize A (1 <= A <= 1,000,000) he buys, he can get a bale of hay of\r\nsize B (1 <= B < A) for free!\r\n\r\nThe deal, however, is restricted: the larger bale must be high\r\nquality hay and the smaller one must be low quality hay. FJ, being\r\na frugal and thrifty fellow, does not care: any quality of hay will\r\ndo as long as he saves some money.\r\n\r\nGiven a list of the sizes of N (1 <= N <= 10,000) bales of high\r\nquality hay and M (1 <= M <= 10,000) bales of low quality hay, find\r\nthe maximum number of bales of hay Farmer John can purchase.  He\r\ncan buy bales of high quality hay without getting the free bale of\r\nlow quality hay, but he cannot buy bales of low quality hay (i.e.,\r\nhe must get them for free in the deal).\r\n\r\nPROBLEM NAME: buyfree\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Two space-separated integers: N and M.\r\n\r\n* Lines 2..N+1: Line i+1 contains a single integer which is the size\r\n        of the ith bale of high quality hay.\r\n\r\n* Lines N+2..N+M+1: Line i+N+1 contains a single integer which is the\r\n        size of the ith bale of low quality hay.\r\n\r\nSAMPLE INPUT (file buyfree.in):\r\n\r\n3 4\r\n6\r\n1\r\n3\r\n1\r\n5\r\n3\r\n4\r\n\r\nINPUT DETAILS:\r\n\r\nThere are 3 bales of high quality hay, with sizes 6, 1, and 3, and 4 bales\r\nof low quality hay, with sizes 1, 5, 3, and 4.\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: The maximum total number of bales of hay Farmer John can\r\n        obtain.\r\n\r\nSAMPLE OUTPUT (file buyfree.out):\r\n\r\n5\r\n\r\nOUTPUT DETAILS:\r\n\r\nObviously, Farmer John can buy all the bales of high quality hay.\r\nWhen he buys the size 6 high quality bale, he can get any low quality\r\nbale for free (say, the bale of size 3). When he buys the size 3\r\nhigh quality bale, he can get the size 1 low quality bale for free.\r\nWhen he buys the size 1 high quality bale, however, he cannot get\r\nany low quality bales for free (since the size must be strictly\r\nless). The total, no matter how clever FJ is, comes to five bales.\r\n\r\n\r\n\r\n\r\n\r\n\r\nh2. Qualified Primes\r\n\r\n\r\nFarmer John has begun branding the cows with sequential prime\r\nnumbers. Bessie has noticed this and is curious about the occurrence\r\nof various digits in those brands.\r\n \r\nHelp Bessie determine the number of primes in the inclusive range\r\nA..B (1 <= A <= B <= 4,000,000; B <= A + 1,000,000; one test case\r\nhas B <= A + 2,000,000 ) that contain a supplied digit D.\r\n\r\nA prime is a positive integer with exactly two divisors (1 and\r\nitself). The first primes are 2, 3, 5, 7, 11, 13, 17, 19, 23, and,\r\n29.\r\n\r\nPROBLEM NAME: qprime\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Three space-separated integers: A, B, and D\r\n\r\nSAMPLE INPUT (file qprime.in):\r\n\r\n10 15 3\r\n\r\n\r\nINPUT DETAILS:\r\n\r\nHow many primes in the range 10..15 contain the digit 3?\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: The count of primes in the range that contain the digit D.\r\n\r\nSAMPLE OUTPUT (file qprime.out):\r\n\r\n1\r\n\r\nOUTPUT DETAILS:\r\n\r\nJust 13 in this range contains a \'3\'.\r\n\r\n\r\n\r\n\r\nh2. Lilypad Pond\r\n\r\n\r\n\r\n\r\nFarmer John has installed a beautiful pond for his cows\' esthetic\r\nenjoyment and exercise. The rectangular pond has been partitioned\r\ninto square cells of M rows and N columns (1 <= M <= 30; 1 <= N <=\r\n30). Some of the cells have astonishingly sturdy lilypads; others\r\nhave rocks; the remainder are just beautiful, cool, blue water.\r\n\r\nBessie is practising her ballet moves by jumping from one lilypad\r\nto another and is currently located at one of the lilypads (see the\r\ninput data for the location\'s specifier). She wants to travel to\r\nanother lilypad in the pond by jumping from one lilypad to another.\r\nShe can jump neither into the water nor onto a rock.\r\n\r\nSurprising only to the uninitiated, Bessie\'s jumps between lilypads\r\nalways appear as a sort of chess-knight\'s move: move M1 (1 <= M1\r\n<= 30) \'squares\' in one direction and then M2 (1 <= M2 <= 30; M1\r\n!= M2) more in an orthogonal direction (or perhaps M2 in one direction\r\nand then M1 in an orthogonal direction). Bessie sometimes might\r\nhave as many as eight choices for her jump.\r\n\r\nGiven the pond layout and the format of Bessie\'s jumps, determine\r\nthe smallest number of leaps that Bessie must make to move from her\r\nstarting location to her final destination, a feat which is always\r\npossible for the given test data.\r\n\r\nPROBLEM NAME: bronlily\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Four space-separated integers: M, N, M1, and M2\r\n\r\n* Lines 2..M+1: Line i+1 describes row i of the pond using N\r\n        space-separated integers with these values: 0 indicates empty\r\n        water; 1 indicates a lilypad; 2 indicates a rock; 3 indicates\r\n        the lilypad Bessie upon which she starts; 4 indicates the\r\n        lilypad that is Bessie\'s destination.\r\n\r\nSAMPLE INPUT (file bronlily.in):\r\n\r\n4 5 1 2\r\n1 0 1 0 1\r\n3 0 2 0 4\r\n0 1 2 0 0\r\n0 0 0 1 0\r\n\r\nINPUT DETAILS:\r\n\r\nBessie starts on the left in row 2; her destination is on the right in row\r\n2. Several lilypads and rocks occupy the pond.\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: A single integer that is the minimum number of jumps between\r\n        lilypads that Bessie must make to travel from her starting\r\n        place to her destination.\r\n\r\nSAMPLE OUTPUT (file bronlily.out):\r\n\r\n2\r\n\r\nOUTPUT DETAILS:\r\n\r\nBessie cleverly hops onto the pad at row 1, column 3 on her way to the\r\nright hand side.\r\n',1507,'public',NULL,NULL),('implica-te/extinde-arhiva/autor-necunoscut','Autor necunoscut','2007-07-09 19:24:32','2007-08-13 20:13:47','h1. Autor necunoscut\r\n\r\nPentru aceasta problema nu am reusit sa identificam autorul. Daca ne poti ajuta sa aflam cine a compus aceasta problema te rugam sa trimiti un mail unuia din membrii \'echipei infoarena\':echipa-infoarena.\r\n\r\nInfoarena foloseste problemele in scopuri educationale. Printre cei care beneficiaza de arhiva de probleme se numara elevi si studenti din toata tara. Totusi daca unul dintre autori doreste ca problemele sale sa NU fie folosite in arhiva noastra, le putem retrage la cererea acestuia.',15,'public',NULL,NULL),('jboi-2007/prob10-12','jboi-2007/prob10-12','2007-07-10 09:28:02','2007-07-10 09:28:26','h1. Problemele 10-12 pentru pregatirea LOT-ului\r\n\r\n\"Inapoi la pagina\":jboi-2007\r\n\r\nh2. New Cow Brands\r\n\r\nThe cows are beside themselves: Farmer John has decided to use RFID\r\ntags instead of branding the cows with red-hot irons that cause\r\nintense pain.\r\n\r\nThe RFID tags contain a code that is N (3 <= N <= 15) characters\r\n(each in the range \'A\'..\'Z\') in length. No character appears twice\r\nin the code. The character chosen for any given position in the\r\ncode is chosen from a supplied set for that position. The set is\r\nalways given in alphabetical order.\r\n\r\nA machine generates the codes in alphabetical order. Each new batch\r\nof cows uses the next unused set of codes. FJ keeps track of the\r\nnumber of codes he has already used.\r\n\r\nHelp FJ confirm the RFID brands to be used for the next set of cows.\r\nGiven the count of the starting and finishing brands (1 <= start < finish\r\n<= 22,000,000 and finish-start < 2000), print (in alphabetical order) the\r\nbrands that will be used. See the I/O specifications for an example.\r\n\r\nPROBLEM NAME: brand3\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Three space-separated integers, respectively: N, start, and\r\nfinish.\r\n\r\n* Lines 2..N+1: Line i+1 contains a number (1..26) of characters that\r\nare the valid characters for position i in the RFID code\r\n\r\nSAMPLE INPUT (file brand3.in):\r\n\r\n4 6 13\r\nABC\r\nCDELQ\r\nCFH\r\nABC\r\n\r\nINPUT DETAILS:\r\n\r\nFour positions in the RFID code; print the 6th through 13th codes.\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Lines 1..finish-start+1: Line i contains RFID code # start+i-1\r\n\r\nSAMPLE OUTPUT (file brand3.out):\r\n\r\nADHB\r\nADHC\r\nAECB\r\nAEFB\r\nAEFC\r\nAEHB\r\nAEHC\r\nALCB\r\n\r\nOUTPUT DETAILS:\r\n\r\nHere are the first 20 codes:\r\n1 ACFB 5 ADFC 9 AEFB 13 ALCB 17 ALHC\r\n2 ACHB 6 ADHB 10 AEFC 14 ALFB 18 AQCB\r\n3 ADCB 7 ADHC 11 AEHB 15 ALFC 19 AQFB\r\n4 ADFB 8 AECB 12 AEHC 16 ALHB 20 AQFC\r\n\r\n\r\n\r\n\r\n\r\nh2. Word Games\r\n\r\nThe cows are playing Scrabble but, sad to say, they do not have the\r\nvocabulary to play at the tournament level. Bessie wants your help\r\nfor just the first move. Given her rack (a \"rack\" is a holder of\r\nScrabble letters) of N (3 <= N <= 10) letters (which might or might\r\nnot be unique and might include one or more blank \"wild card\" tiles)\r\nalong with a scrabble dictionary of D (10 <= D <= 50000) words,\r\nprint the words she might use (by searching the dictionary).\r\n\r\nThe 27 possible letters are upper-case \'A\'..\'Z\' and the \'#\' symbol,\r\nwhich represents a \"wildcard\" and can stand for any letter. If two\r\n\'#\'s appear in one rack, each can represent a different letter when\r\nplayed.\r\n\r\nThe dictionary words can be read, one per line, from file whose\r\nname is \'scrbl.txt\' (the file name is all lower case letters, unlike\r\nthe file\'s contents). The letters in Bessie\'s rack can always be\r\nused to make at least one word. Each word in the dictionary is\r\nunique. Remember that you are running on Linux: each input line\r\nends with a \'\\n\' character; no \'return\' characters are present.\r\n\r\nPROBLEM NAME: scrbl\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Two space-separated integers, N and D.\r\n\r\n* Line 2: N letters (with no intervening blanks) that are the letters\r\nin Bessie\'s Scrabble rack.\r\n\r\nSAMPLE INPUT (file scrbl.in):\r\n\r\n4 49891\r\nIAFR\r\n\r\nINPUT DETAILS:\r\n\r\nFour letters: I, A, F, and R.\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Lines 1..??: Each line contains a single word that appears in the\r\nscrbl.txt dictionary. Print the output in the order the words\r\nappear in the dictionary.\r\n\r\nSAMPLE OUTPUT (file scrbl.out):\r\n\r\nAIR\r\nFAIR\r\nFAR\r\nFIR\r\nIF\r\n\r\nOUTPUT DETAILS:\r\n\r\nThese words do actually appear in the real dictionary used for this\r\nproblem.\r\n\r\n\r\n\r\n\r\n\r\nh2. Serious Cow Tag\r\n\r\nFarmer John\'s N (1 <= N <= 1000) cows (conveniently numbered 1..N)\r\nare going to play a game of Serious Cow Tag. In Serious Cow Tag,\r\neach cow chooses a grid point in the pasture (-7500 <= X <= 7500,\r\n-7500 <= Y <= 7500) such that the distances between all pairs of\r\ncows are unique.\r\n\r\nThe cows play in turn, starting with cow #1 and continuing with\r\ncows #2, #3, and so on (as long as the cow is still in the game).\r\nWhen it is a cow\'s turn to play, she finds the nearest cow still\r\nplaying, ambles over to that cow to tag her, and then returns to\r\nher original location. As soon as a cow is tagged, she is out of\r\nthe game.\r\n\r\nThe game ends when only one cow remains, and she is declared the\r\nwinner.\r\n\r\nFarmer John is taking bets with neighboring farmers as to which cow\r\nwill win, so he would like to know the winner in advance. Write a\r\nprogram that will read a description of the cows\' positions and\r\ndetermine the winner.\r\n\r\nPROBLEM NAME: cowtag\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: A single integer N, the number of cows\r\n\r\n* Lines 2..N+1: Line i+1 contains two space-separated integers that\r\ndescribe the location of cow i.\r\n\r\nSAMPLE INPUT (file cowtag.in):\r\n\r\n3\r\n0 0\r\n0 3\r\n4 3\r\n\r\nINPUT DETAILS:\r\n\r\nThree cows at (0, 0), (0, 3) and (4, 3).\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: The number of the winning cow.\r\n\r\nSAMPLE OUTPUT (file cowtag.out):\r\n\r\n3\r\n\r\nOUTPUT DETAILS:\r\n\r\nCow 1 goes first and tags the nearest cow, cow 2. Cow 2 is eliminated\r\nso she does not get a turn. Cow 3 then tags the only remaining cow,\r\ncow 1. She is the last cow left, so she wins.',1507,'public',NULL,NULL),('jboi-2007/prob13-15','jboi-2007/prob13-15','2007-07-11 10:54:51','2007-07-11 10:54:51','h1. Problemele 13-15 pentru pregatirea LOT-ului\r\n\r\n\"Inapoi la pagina\":jboi-2007\r\n\r\nh2. The Moronic Cowmpouter\r\n\r\nInexperienced in the digital arts, the cows tried to build a\r\ncalculating engine (yes, it\'s a cowmpouter) using binary numbers\r\n(base 2) but instead built one based on base negative 2!  They were\r\nquite pleased since numbers expressed in base -2 do not have a sign\r\nbit.\r\n\r\nYou know number bases have place values that start at 1 (base to\r\nthe 0 power) and proceed right-to-left to base^1, base^2, and so\r\non. In base -2, the place values are 1, -2, 4, -8, 16, -32, ...\r\n(reading from right to left). Thus, counting from 1 goes like this:\r\n1, 110, 111, 100, 101, 11010, 11011, 11000, 11001, and so on.\r\n\r\nEerily, negative numbers are also represented with 1\'s and 0\'s but\r\nno sign. Consider counting from -1 downward: 11, 10, 1101, 1100,\r\n1111, and so on.\r\n \r\nPlease help the cows convert ordinary decimal integers (range\r\n-2,000,000,000..2,000,000,000) to their counterpart representation\r\nin base -2.\r\n\r\nPROBLEM NAME: neg2\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: A single integer to be converted to base -2\r\n\r\nSAMPLE INPUT (file neg2.in):\r\n\r\n-13\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: A single integer with no leading zeroes that is the input\r\n        integer converted to base -2. The value 0 is expressed as 0,\r\n        with exactly one 0.\r\n\r\nSAMPLE OUTPUT (file neg2.out):\r\n\r\n110111\r\n\r\nOUTPUT DETAILS:\r\n\r\nReading from right-to-left:\r\n1*1 + 1*-2 + 1*4 + 0*-8 +1*16 + 1*-32 = -13\r\n\r\n\r\n\r\n\r\n\r\n\r\nh2. DNA Assembly\r\n\r\n\r\nFarmer John has performed DNA sequencing on his prize milk-producing\r\ncow, Bessie DNA sequences are ordered lists (strings) containing\r\nthe letters \'A\', \'C\', \'G\', and \'T\'.\r\n\r\nAs is usual for DNA sequencing, the results are a set of strings\r\nthat are sequenced fragments of DNA, not entire DNA strings. A pair\r\nof strings like \'GATTA\' and \'TACA\' most probably represent the\r\nstring \'GATTACA\' as the overlapping characters are merged, since\r\nthey were probably duplicated in the sequencing process.\r\n\r\nMerging a pair of strings requires finding the greatest overlap\r\nbetween the two and then eliminating it as the two strings are\r\nconcatenated together. Overlaps are between the end of one string\r\nand beginning of another string, NOT IN THE MIDDLE OF A STRING.\r\n\r\nBy way of example, the strings \'GATTACA\' and \'TTACA\' overlap\r\ncompletely. On the other hand, the strings \'GATTACA\' and \'TTA\' have\r\nno overlap at all, since the matching characters of one appear in\r\nthe middle of the other, not at one end or the other. Here are some\r\nexamples of merging strings, including those with no overlap:\r\n\r\n	GATTA + TACA -> GATTACA\r\n	TACA + GATTA -> TACAGATTA\r\n	TACA + ACA -> TACA\r\n	TAC + TACA -> TACA\r\n	ATAC + TACA -> ATACA\r\n	TACA + ACAT -> TACAT\r\n\r\nGiven a set of N (2 <= N <= 7) DNA sequences all of whose lengths\r\nare in the range 1..7, find and print length of the shortest\r\npossible sequence obtainable by repeatedly merging all N strings\r\nusing the procedure described above. All strings must be merged\r\ninto the resulting sequence.\r\n\r\nPROBLEM NAME: dna\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: A single integer N\r\n\r\n* Lines 2..N+1: Each line contains a single DNA subsequence\r\n\r\nSAMPLE INPUT (file dna.in):\r\n\r\n4\r\nGATTA\r\nTAGG\r\nATCGA\r\nCGCAT\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: Length of the shortest possible string obtained by merging\r\n        the subsequences. It is always possible -- and required -- to\r\n        merge all the input strings to obtain this string.\r\n\r\nSAMPLE OUTPUT (file dna.out):\r\n\r\n13\r\n\r\nOUTPUT DETAILS:\r\n\r\nSuch string is \"CGCATCGATTAGG\".\r\n\r\n\r\n\r\n\r\n\r\n\r\nh2. Cow Phrasebook\r\n\r\n\r\nEver the innovator, Farmer John is teaching cows to speak some\r\nphrases in human language. He writes each new phrase the cows learn\r\nin his phrase book, a total of M (1 <= M <= 1,000) so far.\r\n\r\nWhen Farmer John is on a vacation, he can only communicate with his\r\ncows by telephone. Being an active vacationer, FJ visits beaches\r\nand fine restaurants when away from the farm. When he returns, his\r\nanswering machine is full of N (1 <= N <= 10,000) messages, many\r\npotentially from the cows.\r\n\r\nFJ vacations frugally and thus gets poor telephone service. Many\r\nof the recorded messages cut off before they are complete. Help FJ\r\ndetermine whether the recorded messages are from the phrasebook by\r\ndetermining if the message begins a phrase.\r\n\r\nYou will be given the phrasebook and a set of texts of the recorded\r\nmessages. Count the number of recorded messages that are the beginning\r\n(prefix) of a phrase from the phrase book.\r\n\r\nComplete phrases are from 1 to 60 characters in length, each of which\r\nis either a letter (upper or lower case), a period (.), comma (,),\r\nquestion mark (?) or space. There are no leading spaces, trailing\r\nspaces, or double spaces in a phrase. Comparisons are case-sensitive,\r\nand a phrase is in fact, considered to be prefix of itself.\r\n\r\nPROBLEM NAME: phrase\r\n\r\nINPUT FORMAT:\r\n\r\n* Line 1: Two space-separated integers, M and N\r\n\r\n* Lines 2..M+1: Phrases from the phrase book, one per line.\r\n\r\n* Lines M+2..M+N+1: Phrases spoken by cows, one per line.\r\n\r\nSAMPLE INPUT (file phrase.in):\r\n\r\n3 4\r\nI will not buy this record, it is scratched.\r\nMy hovercraft is full of eels.\r\nDo you want to come back to my place? Bouncy, bouncy.\r\nI will not buy this rec\r\nMy helicopter is\r\nDo you want to come back\r\nI will not buy this cat.\r\n\r\nINPUT DETAILS:\r\n\r\nThree input phrases (record, eels, bouncy); four query phrases\r\n(buy, helicopter, come back, cat).\r\n\r\nOUTPUT FORMAT:\r\n\r\n* Line 1: A single integer that is the count of the number of messages\r\n        that were proper prefixes of the phrasebook.\r\n\r\nSAMPLE OUTPUT (file phrase.out):\r\n\r\n2\r\n\r\nOUTPUT DETAILS:\r\n\r\nThe messages \'I will not buy this rec\' and \'Do you want to come back\'\r\nare valid prefixes of the phrasebook.',1507,'public',NULL,NULL),('utilizator/danielp','Profil danielp','2006-11-24 20:56:16','2007-07-17 14:50:29','h2. Despre mine\r\n\r\n* scoala generala nr. 3, Suceava (1994 - 2002)\r\n* Colegiul National Petru Rares, Suceava (2002 - 2006)\r\n* Facultatea de Informatica, Iasi (2006 - present)\r\n\r\nh2. Distinctii primite\r\n\r\n* Locul 12 la ACM, Southeastern Europe Region (2006)\r\n* Bronz, IOI (2005)\r\n* locul 2, ONI (2004)\r\n* aur absolut, \"Tuymaada olympiad\", Yakutia (2004)\r\n* multe alte premii si mentiuni la concursuri nationale\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* echipa infoarena \r\n* ==user(user=\"unholyfrozen\" type=\"normal\")== \r\n* ==user(user=\"astronomy\" type=\"normal\")==',48,'protected',NULL,NULL),('summer-challenge-2007/clasament/runda-1','Clasament Summer Challenge 2007, Runda 1','2007-07-25 10:29:51','2007-08-10 19:17:36','h1. Clasament \'Summer Challenge 2007, Runda 1\':summer-challenge-2007/runda-1\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2007/\r\n*(active) \'Runda 1\':summer-challenge-2007/runda-1\r\n* \'Runda 2\':summer-challenge-2007/runda-2\r\n* \'Runda 3\':summer-challenge-2007/runda-3\r\n*(active) \'Clasament\':summer-challenge-2007/clasament\r\n\r\n== Rankings(rounds=\"summer2007-runda1\") == ',1,'protected',NULL,NULL),('runda/summer2007-runda1/clasament','Clasament summer2007-runda1','2007-07-25 10:30:35','2007-07-25 10:30:35','h1. Clasament ==roundparam(round_id=\"summer2007-runda1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer2007-runda1\")==',961,'round: summer2007-runda1',NULL,NULL),('intrebari','intrebari','2007-07-28 11:47:41','2007-07-30 22:30:27','h2. Intrebari pt programatori bazati sau fosti olimpici\r\n\r\n* cele mai interesante 5 carti\r\n* limbajul de programare preferat\r\n* editorul preferat\r\n* cum ai inceput cu informatica\r\n* siteuri preferate\r\n* bloguri preferate\r\n* proiectul mai interesant la care ai lucrat\r\n* planuri de viitor\r\n* alte pasiuni inafara de informatica\r\n* algoritmul preferat\r\n* vreun warstory interesant?\r\n* de ce ai ales scoala pe care ai ales-o\r\n* tii vreo problema de concurs minte, vre-un brainteaser \r\n* tehnica de programare / jmen / tehnologie\r\n* best practice\r\n* cum ataci o problema un proiect prin ce faze treci\r\n* ce structuri de date folosesti, algoritmi\r\n* sfaturi pt cei ce vreau sa inceapa cu programarea\r\n* sistem de operare\r\n* cum lucrezi? in salturi sau putin in fiecare zi\r\n* cat timp petreci in fata calculatorului\r\n* inspiratie/transpiratie, factor motivator\r\n* ba da voi cum va distrati\r\n* muzica filme\r\n* ce faci in primele minute cand ajungi la munca/servici\r\n* cum iti mentii cunostintele la zi\r\n* gasirea unui bug, metode de atac\r\n* mod de munca, intervale compacte, iteratii directe, tehnologii noi sau tehnici bine cunoscute\r\n* impartirea timpului',6686,'public',NULL,NULL),('newsletter/summer-challenge-2007/runda-1','Summer Challenge, Romania la olimpiadele internationale','2007-07-29 10:53:03','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nIn toiul vacantei de vara, feriti de canicula, la umbra monitoarelor,\r\ninfoarena se gandeste la tine! :)\r\n\nTe invitam sa participi la seria de concursuri Summer Challenge 2007. \r\nVom organiza 3 runde online, de cate 5h fiecare, cu probleme de\r\ndificultate variata.\r\n\nSummer Challenge este o ocazie buna de antrenament pentru tine\r\n(daca nu esti deja la mare :) dar si un ultim test pentru delegatia\r\nRomaniei la Olimpiada Internationala de Informatica 2007 (Croatia).\r\n\nAi ocazia sa concurezi cu lotul Romaniei la IOI 2007!\r\n\nRunda 1 a concursului Summer Challenge 2007 se desfasoara...\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Luni, 30 iulie 2007, orele 10:00 - 15:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nPagina rundei: \'summer-challenge-2007/runda-1\':summer-challenge-2007/runda-1\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la acest concurs iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te va aduce mai aproape de varful clasamentul.\r\n==NewsletterRating(username=\"%username%\")==\r\nAfla mai multe despre rating: \'documentatie/rating\':documentatie/rating\r\n\nh2.  Despre Summer Challenge 2007 \n\nOrganizatorul primei runde online SC07 este Adrian Diaconu:\r\n\'utilizator/\':utilizator/DITzoneC\r\n\nPentru informatii suplimentare (cum particip, intrebari etc.)\r\nviziteaza pagina concursului: \'summer-challenge-2007\':summer-challenge-2007\r\n\nh2.  Rezultatele Romaniei la olimpiadele internationale \n\nIn luna iulie s-au desfasurat BOI si CEOI, doua competitii\r\ninternationale la care participa Romania in mod traditional.\r\n\nAnul 2007 a adus in premiera concursul JBOI (Junior Balkan Olympiad\r\nin Informatics). La JBOI participa elevi din tarile balcanice sub\r\nvarsta de 15-16 ani.\r\n\nIata un rezumat al acestor competitii:\r\n\np{padding-left: 2em;}. *   Junior Balkan Olympiad in Informatics, 1st Edition (2007)\r\n        Belgrad, Serbia\r\n        \'http://www.jboi2007.org/\':http://www.jboi2007.org/\r\n\np{padding-left: 4em;}. La prima editie a JBOI, juniorii Romaniei au obtinut rezultate\r\n        exceptionale, aducand Romania pe locul I in clasamentul\r\n        pe natiuni. Felicitari!\r\n\np{padding-left: 4em;}. Victor-Cristian Ionescu,    locul 1,    AUR\r\n        Vlad-Bogdan Tataranu,       locul 3,    AUR\r\n        Radu Zernoveanu,            locul 5,    ARGINT\r\n        Cezar Mocan,                locul 13,   MENTIUNE\r\n\np{padding-left: 4em;}. Lotul JBOI a fost condus de catre Prof. Univ. Stelian Ciurea\r\n        si Prof. Dana Lica.\r\n\np{padding-left: 4em;}. infoarena a organizat pe 4 iulie un mic concurs de pregatire\r\n        pentru juniori: \'junior-challenge\':junior-challenge\r\n    \r\n    *   Central European Olympiad in Informatics 2007\r\n        Brno, Cehia,\r\n        \'http://www.fi.muni.cz/ceoi/index.xhtml.en\':http://www.fi.muni.cz/ceoi/index.xhtml.en\r\n\np{padding-left: 4em;}. Victor Rusu,                locul 10,   BRONZ\r\n        Cosmin Gheorghe,            locul 19\r\n        Stefan-Alexandru Filip,     locul 24\r\n        Andrei Grigorean,           locul 25\r\n\np{padding-left: 4em;}. Lotul Romaniei a fost condus de catre Prof. Emanuela Cerchez\r\n        si Prof. Constantin Galatan.\r\n\np{padding-left: 2em;}. *   Balkan Olympiad in Informatics 2007\r\n        Chisinau, Moldova\r\n        \'http://boi2007.edu.md/\':http://boi2007.edu.md/\r\n\np{padding-left: 4em;}. Felicitari delegatiei romane! In clasamentul pe natiuni,\r\n        Romania a obtinut locul I.\r\n\np{padding-left: 4em;}. Ionescu Bogdan,             AUR\r\n        Airinei Adrian,             AUR\r\n        Tataroiu Bogdan,            ARGINT\r\n        Dragus Marius,              BRONZ\r\n\np{padding-left: 4em;}. Lotul Romaniei a fost condus de catre Prof. Marinel Serban si\r\n        Prof. Doru Popescu Anastasiu.\r\n\nh2.  IOI 2007 \n\nA 19-a editie a Olimpiadei Internationale de Informatica este gazduita\r\nde Croatia (in Zagreb) si se desfasoara in perioada 15-22 august.\r\n\nPagina web: \'http://www.hsin.hr/ioi2007/\':http://www.hsin.hr/ioi2007/\r\n\nUram succes delegatiei Romaniei la IOI 2007! Speram sa faca ce stiu ei\r\nmai bine, sa obtina rezultate exceptionale.\r\n\nLotul Romaniei este condus de catre Prof. Emanuela Cerchez.\r\nParticipanti:\r\n\np{padding-left: 2em;}. Andrei Grigorean\r\n    Cosmin Gheorghe\r\n    Adrian Airinei\r\n    Bogdan Tataroiu\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('cautari-ortogonale','Cautari ortogonale','2007-06-01 06:07:08','2010-01-20 16:55:56','h1. Cautari ortogonale: Structuri de date si aplicatii\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"alecman\") ==\r\n\r\n(Categoria _Structuri de date_, Autor _Cosmin Negruseri_)\r\n\r\nh2. Introducere\r\n\r\nIn acest articol voi discuta despre cateva structuri de date folositoare pentru probleme de geometrie, in special pentru probleme ortogonale. **Problema de baza** ce va fi rezolvata suna in felul urmator: avem $n$ puncte in plan si pentru un anumit dreptunghi ne intereseaza numarul de puncte din acel dreptunghi, sau diverse alte operatii pentru punctele din interiorul sau, cum ar fi suma cheilor punctelor, minimul sau maximul cheilor (daca punctele au asociate cate o cheie). Folosind arbori de intervale putem rezolva aceasta problema, dar vreau sa exemplific ce alte variante mai avem si avantajele lor, precum si aplicatii practice pentru cautarea pe domenii ortogonale. In general, abordarile prezentate mai jos se pot extinde de la cazul unidimensional sau bidimensional, cu usurinta, la cazuri N-dimensionale.\r\nPentru a intelege cat mai bine ideile si structurile de date prezentate mai departe recomand citirea articolelor [1] si [2].\r\nStructurile prezentate sunt in general statice, adica formam intai structura si apoi rezolvam problema. Structurile de date se pot modifica pentru a suporta inserari si stergeri de puncte, devenind dinamice, dar astfel implementarea se complica. Pentru a simula dinamismul putem insera toate datele de la inceput si sa mai avem un camp boolean in care marcam cu true daca data a fost logic inserata si cu false daca data din nodul respectiv nu a fost inca logic inserata. Aceasta pastreaza complexitatea operatiilor pe structura si ne ajuta in echilibrarea structurilor pentru o eficienta buna a operatiilor.\r\n\r\nh2. QuadTree\r\n\r\n_QuadTree_ este o structura care organizeaza informatii pentru date multidimensionale, fiind folosita in cartografie, procesarea imaginilor, grafica pe calculator etc. Structura este un arbore ce reprezinta o zona din spatiul N-dimensional (in cazul in care suntem noi interesati, $N=2$), fiecare nod al arborelui pastreaza o informatie pentru o zona din spatiu, iar nodul are $2^N^$ fii care reprezinta fiecare o zona de $2^N^$ ori mai mica decat zona parintelui. Zonele fiilor sunt **disjuncte**, iar reuniunea lor formeaza zona parintelui.\r\n\r\nPentru un _QuadTree_ radacina reprezinta un patrat, iar fii reprezinta cele patru patrate **disjuncte si congruente** in care se poate imparti patratul initial. Din cate am prezentat pana acum, un _QuadTree_ este infinit, dar pe noi ne intereseaza de obicei intervale foarte mici din plan, si atunci putem sa folosim numai cateva nivele din _QuadTree_. Cateodata unele noduri din _QuadTree_ nu contin insa nici o informatie si atunci nu avem nevoie sa le folosim pentru ca am folosi memorie in plus.\r\n\r\nIn +problema 3+ a zilei 2 a **Balcaniadei de Informatica** din 1997, se da un _QuadTree_ care reprezinta o imagine colorata alb-negru, de dimensiune $2^N^ * 2^N^$. Daca patratul reprezentat de informatia dintr-un nod al arborelui era de aceeasi culoare, in nod se pastra informatia culorii si nodul nu avea nici un fiu, altfel nodul avea starea indecisa/nedeterminata si avea patru fii.\r\n\r\np=. !cautari-ortogonale?pic1.jpg!\r\n!cautari-ortogonale?pic2.jpg!\r\n!cautari-ortogonale?pic5.jpg!\r\n\r\nPrima imagine prezinta ordinea in care fii reprezinta patratele, a doua imagine reprezinta o imagine alb-negru, iar a treia este reprezentarea sub forma de _QuadTree_ a acelei imagini.\r\n\r\nPentru a reprezenta $n$ puncte de coordonate intregi in plan cu ajutorul structurii de _QuadTree_, vom insera care un punct pe rand in _QuadTree_. Pornim de la un _QuadTree_ gol si inseram un nod recursiv, vedem pentru fiecare patrat care nu are latura de dimensiune unu in care din cele patru patrate din interiorul lui intra punctul nostru. Daca nu exista nod care sa reprezinte acel patrat, il creem noi.\r\n\r\nAvantajul pentru structura de _QuadTree_ este usurinta implementarii, dezavantajul este ca structura lui si timpul de raspuns la intrebari depind si de configuratia punctelor, nu numai de numarul total de puncte.\r\n\r\nh2. kD-Tree\r\n\r\n_kD-Tree_ este o structura de date care organizeaza o multime de puncte in $k$ dimensiuni, imparte spatiul in semispatii astfel ca fiecare nod din arbore reprezinta un paralelipiped si contine in el un punct. Noi suntem interesati de arbori 2D in special. Pentru cazul 2D, primului nod ii va fi asociat intreg planul. Se duce o linie verticala de abscisa $x$ care imparte planul in doua si punctele in doua multimi de cardinal egal. Subarborele din stanga va contine toate punctele din stanga acestei drepte verticale, iar subarborele din dreapta va contine toate punctele din dreapta acestei drepte verticale. Radacinei arborelui din stanga ii va fi asociat semiplanul stang determinat de dreapta verticala, si va contine punctul median dintre punctele din semiplanul stang sortate dupa $y$. Astfel, la nivel impar punctele vor fi mediane din sirul punctelor sortat dupa $x$, iar la nivel par punctele vor fi mediane din sirul punctelor sortat dupa $y$. Pentru mai multe dimensiuni ale spatiului ciclam dupa $d{~1~}$, $d{~2~}$,..., $d{~n~}$ si apoi iar $d{~1~}$ ca sa punem elementul median pe nivelul curent. In cazul 2D complexitatea crearii unui asemenea arbore e $O(n log n)$. Pentru a raspunde la query-uri pe un dreptunghi coboram in arbore in fii pentru care domeniul asociat se intersecteaza cu dreptunghiul nostru. Se poate demonstra ca aceasta operatie are timpul de executie in cel mai rau caz $O(sqrt(n))$.\r\n\r\np=. !cautari-ortogonale?pic7.jpg!\r\n\r\nUnele implementari tin puncte numai in frunze, si in nodurile care nu sunt frunze tin numai informatia despre coordonata dreptei care imparte regiunea in doua. Dimensiunile regiunii asociate unui nod pot fi tinute in nod sau pot fi calculate la fiecare operatie pentru a salva spatiu. O alta idee pentru a mari viteza de cautare in arbori kD ar fi sa nu alegem ciclic pe ce directie impartim punctele, ci sa alegem la fiecare pas directia pe care punctele sunt cele mai imprastiate.\r\n\r\nPseudocod pentru constructie:\r\n\r\n== code(cpp) |\r\nNod-kD construiesteArbore(puncte, directie) \r\n   daca puncte e vida returneaza null\r\n   altfel daca puncte contine un singur punct returneaza Nod-kD(puncte[0])\r\n   altfel\r\n      x = gasesteMediana(puncte, directie) \r\n      // aceasta functie poate fi implementata folosind selectie randomizata\r\n     stanga = puncte cu directie <= x;\r\n     dreapta = puncte cu directie > x;\r\n     t = Nod-kD(x)\r\n     t.stanga = construiesteArbore(stanga, (directie + 1) % 2);\r\n     t.dreapta = construiesteArbore(dreapta, (directie + 1) % 2);\r\n     returneaza t\r\n==\r\n\r\nPentru a nu face de fiecare data selectie randomizata putem pleca de la inceput cu doua liste de puncte, una sortata dupa $x$ si cealalta sortata dupa $y$.\r\n\r\nPseudocod pentru cautare pe domeniu ortogonal (Notam cu Q un dreptunghi):\r\n\r\n== code(cpp) |\r\npuncte cauta(nod-kD, Q)\r\n  daca Q intersectat cu Nod-kD.domeniu e vid atunci returneaza multimea vida\r\n  altfel daca Nod-kD.domeniu e inclus in Q atunci \r\n                returneaza punctele din subarborele cu radacina nod-kD\r\n  altfel returneaza cauta(nod-kD.stanga, Q) reunita cu cauta(nod-kD.dreapta, Q)\r\n==\r\n\r\nSa vedem care e complexitatea operatiei **cauta**. Nodurile care sunt total in afara dreptunghiului sau total inauntrul dreptunghiului Q pot cel mult fi de doua ori mai multe decat nodurile care intersecteaza dreptunghiul Q intr-o cautare, pentru ca vizitarea unui nod total in afara dreptunghiului sau unui nod dinauntrul dreptunghiului a pornit de la un nod al carui domeniu intersecteaza dreptunghiul. Pentru analiza ne putem ocupa numai de noduri ale caror domenii intersecteaza dreptunghiul. Pentru a obtine o limita superioara a numarului de zone intersectate putem considera numarul maxim de zone intersectate de o latura a dreptunghiului si sa inmultim acel numar cu patru. Pentru a mai simplifica analiza putem considera nu numarul maxim de zone intersectate de un segment, ci numarul maxim de zone intersectate de o dreapta verticala sau orizontala. Consideram o dreapta verticala, pentru un nod, daca directia de impartire a zonei asociate e verticala atunci dreapta verticala taie sau zona fiului stang sau zona fiului drept, dar nu pe amandoua deodata. Daca dreapta verticala nu intersecteaza zona asociata unui fiu atunci nu va mai intersecta zona nici unui urmas al fiului. In caz contrar intersecteaza ambii fii. Daca coboram la nivelul nepotilor cel mult patru noduri sunt intersectate. In cel mai rau caz intersectam domeniul reprezentat de radacina si putem intersecta cel mult $2^i^$ noduri pana la nivelul $2i$. Deci in total maxim $O(sqrt(n))$ noduri sunt parcurse la o operatie cauta.\r\n\r\nAvantajul arborilor kD ar fi usurinta in implementare si spatiul de memorie $O(n)$ folosit, dezavantajul ar fi timpul $O(sqrt(n))$ pentru cautare, dar avand in vedere ca arborii de intervale sau arborii indexati binar au complexitatea $O(log^2^ n)$ la cautare, timpii sunt comparabili.\r\n\r\nArborii de intervale au fost prezentati in articolul [1] deci nu mai insist asupra lor.\r\n\r\nArborii indexati binar sunt si ei folositori si au fost prezentati [2]. Dezavantajul arborilor indexati binar este ca ei pot fi folositi la numarare si la sume, dar nu la aflarea minimului sau maximului pe un interval. Singura posibilitate cand maximul sau minimul pot fi aflate este atunci cand intervalele pe care facem cautarea sunt nemarginite in sus sau in jos. In schimb la toate structurile despre care am discutat  pana acuma putem raspunde in timp subliniar la intrebari despre maxim si minim. Alt dezavantaj este ca daca trebuie sa pastram in spatiul cu $n$ dimensiuni de la $0$ pana la $N$ atunci trebuie sa folosim $N^n^$ spatiu, insa acest neajuns il putem evita folosind impreuna cu arborele indexat binar si o tabela de dispersie. Facand aceasta folosim numai $O(nr log^2^ N)$ spatiu pentru $nr$ puncte in plan inserate in structura, pentru cazul unidimensional folosim $O(nr * log N)$ spatiu. Daca folosim structura _hash_map_ sau _map_ din STL obtinem o implementare foarte simpla si memoria folosita este putina.\r\n\r\nIn continuare, pentru exemplificarea folosirii stucturilor de date voi prezenta niste probleme care voiam sa le propun la concursul de programare Algoritmus, din pacate acest concurs s-a incheiat prematur pentru ca sponsorul nu a mai continuat finantarea premiilor pentru concurenti.\r\n\r\nh2. Problema 1\r\n\r\nSe dau $1<=n<=30 000$ triunghiuri dreptunghice in plan, ele se dau prin trei parametrii $x,y,m$. Varfurile triunghiurilor o sa fie ( $x, y$ ) ( $x + m, y$ ) si ( $x, y + m$ ). Sa se determine cate perechi de triunghiuri exista, astfel ca primul triunghi din pereche sa fie inclus in al doilea triunghi. ( $0<= x, y, m <= 60 000$ )\r\n\r\nTimp de executie: $0.5 secunde$\r\n\r\nTriunghiul determinat de parametrii ( $x{~1~},y{~1~},m{~1~}$ ) e inclus in triunghiul determinat de parametrii ( $x{~2~},y{~2~},m{~2~}$ ) daca si numai daca $x{~2~} <= x{~1~}$, $y{~2~} <= y{~1~}$ si $x{~1~} + y{~1~} + m{~1~} <= x{~2~} + y{~2~} + m{~2~}$. Deci daca facem transformarea ( $x{~1~}, y{~1~}, m{~1~}$ ) -> ( $x{~1~}, y{~1~}, -x{~1~} - y{~1~} - m{~1~}$ ) si notam cu ( $x{~1~}, y{~1~}, z{~1~}$) atunci avem ca triunghiul reprezentat de ( $x{~1~}, y{~1~}, z{~1~}$ ) e inclus in triunghiul reprezentat de ( $x{~2~}, y{~2~}, z{~2~}$ ) daca si numai daca $x{~2~} <= x{~1~}, y{~2~} <= y{~1~}, z{~2~} <= z{~1~}$. Astfel am transformat triunghiurile dreptunghice in puncte din spatiul 3D si perechile de triunghiuri cerute in problema in relatii de dominanta, pentru a afla cate triunghiuri includ triunghiul  reprezentat de ( $x{~1~}, y{~1~}, z{~1~}$ ) trebuie sa vedem cate puncte sunt cuprinse in $(-oo, x{~1~}] x (-oo, y{~1~}]  x (-oo, z{~1~}]$. Pentru a face acest lucru am putea folosi un arbore de intervale 3D care ocupa O(n log^2^ n) spatiu si are complexitatea $O(log^3^ n)$ pentru query, dar observatia banala ca putem sorta sirul triunghiurilor dupa coordonata $z$ si abia apoi sa rezolvam problema ne va ajuta. Vom folosi un arbore de intervale 2D sau un _quadtree_ sau un 2D tree ({_kD tree_}) in care vom insera ( $x{~i~},y{~i~}$ ) in ordinea data de $z{~i~}$. Evident ca la momentul inserarii lui ( $x{~i~},y{~i~}$ ) in structura de date toate punctele deja inserate ( $x{~j~},y{~j~}$ ) vor proveni din un punct ( $x{~j~}, y{~j~}, z{~j~}$ ) cu $z{~j~} <= z{~i~}$, deci nu avem nevoie sa pastram coordonata $z$ a punctelor pentru comparatie. In cazul care implementam problema folosind {_kd trees_} vom avea complexitatea $O(n log n)$ la crearea structurii de date si $O(sqrt(n))$ pentru query, memoria folosita va fi $O(n)$, complexitatea totala a algoritmului $O(n log n + n sqrt(n))$. Daca folosim arbore de intervale atunci vom folosi $O(n log n)$ timp la crearea structurii si vom avea $O(log^2^ n)$ pentru query, memoria folosita va fi $O(n log n)$, complexitatea totala va fi $O(n log n + n log^2^ n)$. Daca folosim tehnica numita \"fractional cascading\" pentru arbori de intervale atunci reducem complexitatea la $O(n log n)$ pentru intreaga problema.\r\n\r\nO alta abordare a problemei bazata tot pe transformarea din triunghiuri in puncte in plan ar fi bazata pe metoda divide si stapaneste. Se impart punctele in doua multimi de dimensiuni egale dupa coordonata $z$, $n/2$ puncte au $z<=ZMID$ si celelalte $n-n/2$ puncte au $z>=ZMID$, dupa ce s-au numarat relatiile de dominanta din cele doua submultimi, trebuie sa gasim numarul de relatii de dominanta in care un punct e in prima multime si al doilea e in a doua multime. Evident oricare ar fi  ( $x{~1~},  y{~1~}, z{~1~}$ ) in prima multime si ( $x{~2~}, y{~2~}, z{~2~}$ ) in a doua multime avem ca $z{~1~} <= ZMID <= z{~2~}$ deci mai trebuie sa verificam doar daca $x{~1~} <= x{~2~}$ si $y{~1~} <= y{~2~}$. Daca tinem sirul sortat dupa $y$ si folosim un arbore indexat binar pentru a insera coordonate $x$ in arbore atunci cand in sirul interclasat ordonat dupa $y$ intalnim un punct din prima multime inseram $x{~1~}$ in arborele indexat binar iar cand intalnim un punct din a doua multime atunci intrebam cate coordonate $x<=x{~2~}$ au fost deja inserate in arborele indexat binar daca $x <= x{~2~} => si y <= y{~2~}$ pentru ca a fost inserat in multime mai devreme, in total faza stapaneste a algoritmului ia $O(n log n)$ timp pentru sortarea dupa $y$ si $O(n log n)$ pentru inserarea in arborele indexat binar deci in totalitate algoritmul dureaza $O(n log^2^ n)$.\r\n\r\nA doua metoda poate fi extinsa la numararea incluziunilor de dreptunghiuri. Dreptunghiurile se vor transforma in puncte in 4D, iar cand vom fi la pasul de stapaneste din algoritm vom sorta dupa $z$ si ne va ramane sa determinam cate perechi $x{~1~} <= x{~2~}$ si $y{~1~} <= y{~2~}$, aceasta o vom rezolva folosind un arbore de intervale rafinat prin \"fractional cascading\", si astfel s-a pastrat complexitatea pasului stapaneste la $O(n log n)$, deci complexitatea totala pentru dreptunghiuri ar fi $O(n log^2^ n)$. Problema cu dreptunghiuri s-a dat la regionala ACM cu $N = 5 000$, atunci o singura echipa a rezolvat problema si solutia lor era $O(N^2^)$.\r\n\r\nh2. Problema 2\r\n\r\nSe dau doua multimi de puncte de coordonate intregi in plan cu $N$ si $M$ puncte. Punctele din prima multime sunt colorate rosu si punctele din a doua multime sunt colorate albastru. Se cere sa se determine o pereche de puncte, unul rosu si unul albastru, intre care distanta manhattan e minima. Coordonatele punctelor sunt cuprinse intre $0$ si $60 000$. $1 <= M <= 30 000$ si $1 <= N <= 30 000$\r\n\r\nTimp de executie: $0.5 secunde$\r\n\r\nPentru fiecare punct rosu vrem sa stim punctul albastru cel mai apropiat, impartim planul in 4 cadrane cu originea in punctul rosu, vrem sa aflam punctul albastru cel mai apropiat din fiecare cadran. Pentru un punct rosu si un punct albastru din cadranul 1 distanta dintre ele e $(x{~a~} - x{~r~}) + (y{~a~} - y{~r~})$ pentru ca $x{~r~} < x{~a~}$ si $y{~r~} < y{~a~}$, regrupand avem $(x{~a~} + y{~a~}) - (x{~r~} + y{~r~})$. Deci vrem sa gasim punctul $(x{~a~}, y{~a~})$ cu proprietatea ca $x{~r~} <= x{~a~}$ si $y{~r~} <= y{~a~}$ si suma $x{~a~} + y{~a~}$ e minima. O solutie ar fi sa folosim un arbore de intervale bidimensional, dar observam ca ambele margini pe domeniul pe care cautam sunt infinite, deci am putea sorta sirurile de puncte descrescator dupa $x$. Cand punctul $(x,y)$ e albastru inseram in arborele indexat binar la pozitia $y$ cheia $x+y$, iar cand punctul este rosu facem un query al elementului minim pe intervalul $[y, +oo)$ (evident toate punctele deja inserate in arbore au ordonata mai mare decat $y$-ul actual). Facem la fel pentru fiecare din cele patru cadrane.\r\n\r\nh2. Problema 3 \r\n\r\nSe dau $1<= N <= 50 000$ de dreptunghiuri in plan si se cere sa se determine numarul de perechi de dreptunghiuri care se intersecteaza. Coordonatele varfurilor dreptunghiurilor sunt intregi si cuprinse intre $0$ si $60 000$.\r\n\r\nTimp de executie: $0.5 secunde$\r\n\r\np=. !cautari-ortogonale?pic6.jpg!\r\n\r\nRezolvam aceasta problema folosind paradigma liniei de baleiere. Sortam dreptunghiurile dupa coordonata $x$ a coltului din dreapta. Dupa cum observam in figura alaturata exista trei pozitii relative ale doua dreptunghiuri care se intersecteaza. Cazurile 1, 2, 4, 5 si 6 se reduc la intersectia laturii verticale din stanga a unui dreptunghi cu latura orizontala de sus a celuilalt dreptunghi, deci acest gen de intersectii pot fi numarate numarand intersectiile intre segmentele orizontale si verticale (aceasta problema a fost deja tratata in articolul [1]). Mai raman cazurile 3 si 7 in care coltul din stanga sus al celui de al doilea dreptunghi e in interiorul primului, acest tip de query il rezolvam cu ajutorul arborilor de intervale, intai inseram in structura toate punctele din dreapta sus ale dreptunghiurilor si apoi pentru fiecare dreptunghi facem query pentru a afla numarul de puncte din interiorul lui.\r\n\r\nh2. Problema 4\r\n\r\nSe dau $1<= N <= 60 000$ de dreptunghiuri in plan, sa se determine un punct care are proprietatea ca este inclus in un numar maxim de dreptunghiuri. Coordonatele varfurilor dreptunghiurilor sunt cuprinse intre $0 si 60 000$.\r\n\r\nTimp de executie: $0.5 secunde$\r\n\r\nReducem problema din plan pe dreapta, daca se da o multime de segmente pe o linie cum determinam un punct care e  acoperit de numar maxim de segmente? O sortare a segmentelor dupa primul capat ar rezolva problema, dar solutia aceasta nu e flexibila daca vrem sa adaugam sau sa stergem segmente. Vom folosi un arbore de intervale unidimensional. Numim acoperire canonica a unui interval, intervalele asociate lui in arborele de intervale (stim din articolul [1] ca numarul acestor intervale este maxim $log n$). In nodurile arborelui de intervale pastram doua atribute: $nr$ si $max$, $nr$ reprezinta numarul de intervale pentru care intervalul asociat nodului face parte din acoperirea canonica, iar $max$ reprezinta intersectia de intervale nevida inclusa strict in intervalul asociat nodului, cu cardinal maxim. Pentru un nod $x$, $x.max$ e egal cu maximul dintre $x.stanga.max + x.stanga.nr$ sau $x.dreapta.max + x.dreapta.nr$. La inserarea sau stergerea din arbore a unui interval avem grija la actualizarea atributelor $max$ si $nr$. Pentru a determina numarul maxim de segmente ce se intersecteaza putem returna $radacina.nr + radacina$.\r\n\r\nAcum ca putem rezolva problema pe dreapta in mod dinamic sa revenim la problema initiala in plan, vom folosi din nou paradigma liniei de baleiere. Folosim numai segmentele verticale si le ignoram pe cele orizontale. Sortam segmentele verticale dupa $x$ si cand intalnim un segment vertical ce a fost initial latura stanga de dreptunghi atunci adaugam acest segment in arborele de intervale si actualizam daca e nevoie cardinalul intersectiei maxime, daca intalnim un segment vertical care initial era latura din dreapta a unui dreptunghi atunci scoatem acest segment din arborele de intervale. Solutia problemei va avea complexitate $O(n log n)$, $O(n log n)$ in faza de sortare a segmentelor si $O(n log n)$ in faza de inserare in arbore si stergere din arbore.\r\n\r\nh2. Alte probleme propuse spre rezolvare\r\n\r\n* \'Evantai\':problema/evantai\r\n* \'Schi\':problema/schi\r\n* \'Cutii\':problema/cutii\r\n* \'Order\':problema/order\r\n* \'Nestable\':http://www.topcoder.com/stat?c=problem_statement&pm=1986\r\n* \'Mobiles\':http://olympiads.win.tue.nl/ioi/ioi2001/contest/day1/mobiles/mobiles.pdf\r\n* \'ZJU 2112\':http://acm.zju.edu.cn/show_problem.php?pid=2112\r\n* \'ZJU 2118\':http://acm.zju.edu.cn/show_problem.php?pid=2118\r\n* \'ZJU 2119\':http://acm.zju.edu.cn/show_problem.php?pid=2119\r\n* \'Wys\':http://www.oi.edu.pl/php/show.php?ac=e180811&module=show&file=zadania/oi11/wys\r\n* \'MIPT 43\':http://acm.mipt.ru/judge/bin/problems.pl?problem=043&sort=ID&lang=en\r\n\r\nh2. Bibliografie\r\n\r\n# \'Arbori de intervale (\"segment trees\") si aplicatii in Geometria Computationala, Dana Lica\':arbori-de-intervale\r\n# \'Arbori Indexati Binar, Mihai Scortaru, GInfo\':http://www.ginfo.ro/revista/13_1/focus.pdf \r\n# \'Kd-Trees, Andrew W. Moore\':http://www.autonlab.org/autonweb/14665/version/2/part/5/data/moore-tutorial.pdf?branch=main&language=en',7271,'public',3692,NULL),('utilizator/alexandru.mosoi','Profil alexandru.mosoi','2007-08-05 10:52:56','2007-08-05 10:52:56','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6694,'public',NULL,NULL),('template/autor-necunoscut','template/autor-necunoscut','2007-08-07 21:35:58','2008-02-04 21:01:12','table{margin:0.5em auto;}. |={background-color:#bedbf4}. !<template/autor-necunoscut?unknown.png! _Din pacate nu am reusit sa identificam autorul acestei probleme._\r\n\'*Intra aici*\':implica-te/extinde-arhiva/autor-necunoscut _pentru a afla cum poti sa ne ajuti_ |',1,'public',NULL,NULL),('runda/summer2007-runda2/clasament','Clasament summer2007-runda2','2007-08-07 21:52:10','2007-08-07 21:52:10','h1. Clasament ==roundparam(round_id=\"summer2007-runda2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer2007-runda2\")==',961,'round: summer2007-runda2',NULL,NULL),('blogideas','blogideas','2007-08-08 00:15:20','2007-08-08 00:15:20','h2. Intrebari pt programatori bazati sau fosti olimpici\r\n\r\n* cele mai interesante 5 carti\r\n* limbajul de programare preferat\r\n* editorul preferat\r\n* cum ai inceput cu informatica\r\n* siteuri preferate\r\n* bloguri preferate\r\n* proiectul mai interesant la care ai lucrat\r\n* planuri de viitor\r\n* alte pasiuni inafara de informatica\r\n* algoritmul preferat\r\n* vreun warstory interesant?\r\n* de ce ai ales scoala pe care ai ales-o\r\n* tii vreo problema de concurs minte, vre-un brainteaser \r\n* tehnica de programare / jmen / tehnologie\r\n* best practice\r\n* cum ataci o problema un proiect prin ce faze treci\r\n* ce structuri de date folosesti, algoritmi\r\n* sfaturi pt cei ce vreau sa inceapa cu programarea\r\n* sistem de operare\r\n* cum lucrezi? in salturi sau putin in fiecare zi\r\n* cat timp petreci in fata calculatorului\r\n* inspiratie/transpiratie, factor motivator\r\n* ba da voi cum va distrati\r\n* muzica filme\r\n* ce faci in primele minute cand ajungi la munca/servici\r\n* cum iti mentii cunostintele la zi\r\n* gasirea unui bug, metode de atac\r\n* mod de munca, intervale compacte, iteratii directe, tehnologii noi sau tehnici bine cunoscute\r\n* impartirea timpului\r\n\r\ntop 5 research papers\r\n\r\ntop 5 programming contest problems\r\n\r\nwebsite statistics',58,'public',NULL,NULL),('dinic','Algoritmul lui Dinic','2007-08-05 10:57:35','2008-01-29 09:43:49','h1. Algoritmul lui Dinic\r\n\r\n(Categoria _Grafuri_, autor(i) _Alexandru Mosoi_)\r\n\r\nTODO:\r\n* ancore la pasi\r\n* poze si exemplificare\r\n* analiza complexitatii\r\n\r\nh2. Introducere\r\n\r\nAcest articol presupune o familiarizare anterioara cu grafuri si retele de transport. Pentru a elimina neclaritati vom da urmatoarea definitie: _O **retea de transport** este un graf orientat in care avem un nod **sursa**, un nod **destinatie**, iar fiecarei muchii ii este asociata o capacitate superioara_. Problema este clasica: cat flux putem baga de la sursa la destinatie fara a depasi capacitatea fiecarei muchii. Algoritmul pe care probabil deja il cunoasteti poarta numele \"Edmonds-Karp\":http://en.wikipedia.org/wiki/Edmonds-Karp_algorithm si are complexitatea O(N*M*M). Algoritmul **Dinic**, prezentat in acest articol, are complexitatea O(N*N*M). Am folosit notatiile obisnuite: $N$ - numarul de noduri, $M$ - numarul de muchii.\r\n\r\nh2. Exemplu\r\n\r\nPentru o mai buna intelegere a articolului vom lucra cu urmatorul exemplu (imagine preluata de pe \"Wikipedia\":http://en.wikipedia.org):\r\n\r\n!dinic?Dinic_flow_example_1.png!\r\n\r\nh2. Descriere\r\n\r\nh3. Pasul 1\r\n\r\nAlgoritmul Edmonds-Karp presupune gasirea, cat timp exista, a unui drum de crestere in reteaua reziduala si marirea fluxului total. Evident, la fiecare pas pot exista mai multe drumuri de crestere (care au luO observatie importanta este ca la fiecare pas in reteua reziduala exista mai multe drumuri de crestere de lungime minima.\r\n\r\nPrimul pas este sa construim din reteua reziduala un graf orientat aciclic in care sa regasim toate drumurile de lungime minima de la sursa la destinatie. Evident in acest dag toate muchiile vor avea capacitatea cel putin 1. Cum construim acest graf? Destul de simplu. Modificam putin bfs-ul de la Edmonds-Karp precum urmeaza. Pentru fiecare nod, calculam distanta (ca numar de muchii) de la sursa pana la el. O muchie $(u, v)$ cu capacitatea $c &gt; 0$ in reteaua reziduala este adaugata la graful construit doar daca distanta de la sursa la $u$ _plus_ $1$ este egala cu distanta de la sursa la nodul $v$ (pe scurt, daca muchia $(u, v)$ apartine unui drum de lungime minima de la sursa la destinatie).\r\n\r\nIn exemplul de mai jos noul graf este construit odata cu parcurgerea in latime. _flow_ reprezinta matricea de adiacenta pentru reteaua reziduala, iar _edges_ memoreaza pentru fiecare nod lista de vecini in graful construit (atentie: muchiile inverse nu apar). \r\n\r\n== code(c) |\r\nwhile (!que.empty()) {\r\n	int node = que.front();\r\n	que.pop();\r\n\r\n	if (node == N-1)\r\n		break;\r\n\r\n	for (int i = 0; i < N; ++i) {\r\n		if (flow[node][i] == 0)\r\n			continue;\r\n\r\n		if (dist[i] == -1) {\r\n			que.push(i);\r\n			dist[i] = dist[node]+1;\r\n			edges[node][++edges[node][0]] = i;\r\n		} else if (dist[i] == dist[node]+1) {\r\n			edges[node][++edges[node][0]] = i;\r\n		}\r\n	}\r\n}\r\n==\r\n\r\nNota: Scriind acest articol, mi-am dat seama ca se putea un pic mai simplu, fara sa tin cont de distanta. Cand se expandeaza nodul _u_, muchia _(u, v)_ se adauga la graf doar daca _v_ este nevizitat. Un nod este **vizitat** daca a fost expandat (scos din coada).\r\n\r\nh3. Pasul 2\r\n\r\nUrmatorul pas este sa bagam flux in graful creat (subraf a retelei reziduale). Acesta operatie se poate face usor cautand drumuri de crestere si pompand flux pe aceste drumuri pana cand nu mai gasim nici un drum. Dupa ce s-a gasit un drum *NU* se face o reactualizare a formei grafului creat la pasul 1, ci doar asupra capacitatilor muchiilor.\r\n\r\nObservatie: daca am gasit un drum de la sursa la destinatie atunci fluxul maxim pe care il pot pompa prin acest drum de crestere este maximul dintre capacitatile muchiilor de pe drum.\r\n\r\nO imbunatatire semnificativa este sa se tina cont ca unele drumuri au un inceput comun. Sa presupunem drumurile $sursa -> ...(drum)... -> nod -> ...(drum 1)... -> destinatie$ si $sursa -> ...(drum)... -> nod -> ...(drum 2)... -> destinatie$. Cele doua drumuri au in comun portiunea $sursa -> ...(drum)... -> nod$. Sa cautam drumurile cu un DFS recursiv. Daca drumurile sunt cautate cu un DFS recursiv, atunci dupa ce se ajunge in $nod$ cu posibilitatea de a pompa maxim $C$ flux, si dupa ce introduc $B$ flux pe primul drum, pe al doilea drum mai pot baga cel mult $C-B$ flux.\r\n\r\n== code(c) |\r\nint do_df(int node, int cap) {\r\n	if (cap == 0)\r\n		return 0;\r\n	if (node == D)\r\n		return cap;\r\n\r\n	int bag = 0;\r\n	for (int i = 1; i <= edges[node][0]; ++i) {\r\n		const int next = edges[node][i];\r\n		if (flow[node][next] == 0)\r\n			continue;\r\n\r\n		const int r = do_df(next, min(cap-bag, flow[node][next]));\r\n		if (r) {\r\n			flow[node][next] -= r;\r\n			flow[next][node] += r;\r\n			bag += r;\r\n		}\r\n	}\r\n\r\n	return bag;\r\n}\r\n==\r\n\r\nFunctia do_df() pompeaza fluxul maxim in graful construit la **pasul 1**. Datorita formei particulare a grafului si ca forma sa nu se schimba dupa fiecare drum de crestere algoritmul nu are deficienta intalnita la algoritmul Ford-Fulkerson. \r\n\r\nh3. Pasul 3\r\n\r\nCat timp mai exista drum de crestere (sau fluxul introdus la pasul anterior este strict pozitiv) reiau algoritmul de la **Pasul 1**.\r\n\r\n\r\nh2. Comentarii\r\n\r\n==user(user=\"vlad_popa\" type=\"tiny\")== : Nu stiu de voi, dar mie mi se pare algoritmul foarte folositor, mai ales in cazuri in care trebuie sa implementezi un algoritm de flux in care ai limite destul de mari... Bravo Alex and... Keep up the good work!',15,'public',NULL,NULL),('summer-challenge-2007/clasament/runda-3','Clasament Summer Challenge 2007, Runda 3','2007-08-09 08:57:40','2007-08-10 19:26:10','h1. Clasament \'Summer Challenge 2007, Runda 3\':summer-challenge-2007/runda-3\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2007\r\n* \'Runda 1\':summer-challenge-2007/runda-1\r\n* \'Runda 2\':summer-challenge-2007/runda-2\r\n*(active) \'Runda 3\':summer-challenge-2007/runda-3\r\n*(active) \'Clasament\':summer-challenge-2007/clasament\r\n\r\n== Rankings(rounds=\"summer2007-runda3\") == ',1,'protected',NULL,NULL),('runda/summer2007-runda3/clasament','Clasament summer2007-runda3','2007-08-10 14:00:55','2007-08-10 14:00:55','h1. Clasament ==roundparam(round_id=\"summer2007-runda3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer2007-runda3\")==',961,'round: summer2007-runda3',NULL,NULL),('summer-challenge-2007/solutii/runda-2','Solutii Summer Challenge, Runda 2','2007-08-10 07:48:31','2009-06-09 15:05:26','h1. Solutii Runda 2\r\n\r\nh2. \'Euclid\':problema/euclid\r\n\r\nProblema se poate rezolva calculand gcd-ul patratelor ce au lungimile laturilor puteri ale lui $2$. Astfel tinem o matrice $V[0..LOGM][0..LOGN][1..M][1..N]$, unde $V[di][dj][i][j]$ reprezinta gcd-ul numerelor din dreptunghiul cu colturile in $(i, j), (i + 2^di^ - 1, j + 2^dj^ - 1)$. Aceasta matrice se poate calcula cu usurinta in $O(logM * logN * M * N)$ incepand cu puterile mai mici ale lui $2$, in stil bottom-up. Putem apoi vedea in $O(1)$ care este gcd-ul elementelor din dreptunghiul cu colturile in $(i, j), (i + w - 1, j + h - 1)$. Pentru aceasta, mai intai sa luam $di = [log h]$ si $dj = [log w]$. Numarul cautat este $gcd(V[di][dj][i][j], V[di][dj][i][j + w - 2^dj^], V[di][dj][i + h - 2^di^][dj], V[di][dj][i + h - 2^di^][j + w - 2^dj^ ])$. Nu mai ramane decat sa luam maximul dintre toate dreptunghiurile posibile. Aceasta solutie foloseste $O(logN * logM * N * M)$ spatiu si timp.\r\n\r\nDesi solutia de mai sus ar fi obtinut punctaj maxim, problema se poate rezolva si mai elegant. Astfel, in loc sa tinem tabela cu toate puterile lui $2$ putem calcula $A[1..M][1..N]$ unde $A[i][j]$ e gcd-ul elementelor din dreptunghiul cu colturile in $(i, j), (i, j + w - 1)$. Aceasta matrice poate fi calculata in $O(logN * N * M)$ folosind acelasi rationament ca mai sus. De asemenea, trebuie sa mai calculam o matrice $B[1..M][1..N]$ unde $B[i][j]$ tine gcd-ul elementelor din $A$ din dreptunghiul $(i, j), (i + h - 1, j)$. Aceasta matrice se calculeaza analog cu matricea A. Rezultatul este $max(B[i][j])$, pentru toate perechile $i, j$ a.i $i + h - 1 &le; M$ si $j + w - 1 &le; N$. Acest algoritm ruleaza in $O((logN + logM) * N * M)$ timp si $O(N * M)$ memorie.\r\n\r\nh2. \'Gbc\':problema/gbc\r\n\r\nSunt in total combinari de $k$ luate cate $n$ in care putem alege nodurile multimii {$A$}. Pentru fiecare din aceste modalitati se face un $AND$ intre toate liniile din matricea de adianceta corespunzatoare nodurilor alese. Nodurile ramase cu $1$ in urma {$AND$}-ului sunt noduri care pot fi alese in multimea {$B$}, avand drumuri catre toate nodurile din multimea {$A$}. Pentru o selectie a multimii $A$ vom avea combinari de $X$ luate cate $M$ posibilitati de a alege multimea {$B$}, unde $X$ este numarul de $1$ ramas in urma {$AND$}-ului. Matricea de adiacenta se va retine codificata pe biti, deci {$AND$} pe linii se reduce la {$AND$} intre numere. Pentru a numara usor cati de $1$ avem intr-un numar se preproceseaza {$nbit[i]$} numarul de biti ai numarului $i$ pentru toate numerele pana la {$2^15^$}. Numerele noastre fiind pana la {$2^30^$} numarul de biti se va calula pe bucati: {$nbit[i&32767] + nbit[i>>15]$} ( $&$ este operatia {$AND$}, $>>$ este operatia de shiftare).\r\n\r\nh2. \'Hypernet\':problema/hypernet\r\n\r\nVom sorta planetele crescator, in functie de numarul de locuitori. Practic, vom considera o renumerotare a planetelor astfel incat {$Q{~1~} &le; Q{~2~} &le; ... &le; Q{~N~}$}. Sa calculam acum o limita inferioara pentru costul  retelei cerute. Vom defini costul unei muchii ({$i,j$}) ca fiind valoare {$Q{~i~}+Q{~j~}$}. Reteaua consta dintr-un arbore avand $N-1$ muchii si inca {$K-(N-1)$} muchii suplimentare. Vom privi arborele ca avand radacina in nodul {$N$}. In acest fel, fiecare nod de la $1$ la $N-1$ va fi legat de o muchie catre tatal lui. Aceasta muchie are un cost de cel mult {$Q{~i~}+Q{~N~}$}. Asadar, o limita superioara pentru costul arborelui este {$CARB=Q{~1~} + Q{~N~} + Q{~2~} + Q{~N~} + ... + Q{~N-1~} + Q{~N~} = (Q{~1~} + ... + Q{~N-1~}) + (N-1) * Q{~N~}$}. O limita superioara pentru costul tuturor celor $K$ muchii este data de $CARB$ + costul celor mai mari $K-(N-1)$ muchii din cele ramase (fara muchiile {$i - N$}). Sa consideram aceasta limita superioara pentru costul celor $K$ muchii ale retelei ca fiind {$CK$}.\r\n\r\nAcum, costul retelei are o limita inferioara data de {$CK + 2 * (suma_totala_a_costurilor_muchiilor - CK) = 2 * suma_totala_a_costurilor_muchiilor - CK$}. Este clar ca doar $K$ perechi de noduri au distanat $1$ intre ele, celelalte perechi avand distanta de cel putin {$2$}. Si din formula se observa ca este de dorit sa avem un cost cat mai mare pentru cele $K$ muchii alese ca facand parte din retea.\r\n Cu aceste considerente, reteaua va fi reprezentata  de muchiile {$(1,N), (2,N), .., (N-1,N)$} si cele mai mari {$K-(N-1)$} muchii din cele ramase. Aceasta retea are distanta $2$ intre oricare pereche de noduri care nu sunt legate direct si are costul egal chiar cu limita inferioara precizata mai sus.\r\n\r\n\r\nAsadar, problema ramasa este aceea de a alege cele mai mari {$K-(N-1)$} muchii avand ambele capete in multimea {${1,2,..,N-1}$}. Doua variante simple au complexitate $O(N*K)$ si {$O(K*logN)$}, insa vor depasi limita de timp.\r\n\r\nO solutie acceptabila ar consta in a cauta binar valoarea celei mai mici muchii din cele $K-(N-1)$ pe care mai dorim sa le alegem si sa calculam in $O(N)$ cate perechi de noduri au costul mai mare sau egal cu valoarea fixata in cautarea binara. Vom alege cea mai mare valoare pentru care exista {$X >= K-(N-1)$} muchii cu cost mai mare sau egal cu ea.\r\n Daca {$X=K-(N-1)$}, am gasit muchiile cautate. Daca $X>K-(N-1)$ este din cauza ca exista prea multe muchii cu acelasi cost maxim gasit. In aceasta situatie, putem scadea din costul total al muchiilor gasite {$costul_maxim_gasit * (X - (K - (N-1)))$} pentru a obtine costul total al celor mai mari $K-(N-1)$ muchii.\r\n\r\nSolutia finala afisata va fi {$CK + 2 * (suma_totala_a_costurilor_muchiilor - CK)$}, unde $CK$ a fost definit anterior. Complexitatea algoritmului este {$O(N * log(N) * log(CMAX))$}.\r\n',5748,'public',NULL,NULL),('summer-challenge-2007/clasament/general','Clasament General Summer Challenge 2007','2007-08-10 16:19:02','2007-08-10 16:28:38','h1. Clasament \'Summer Challenge 2007\':summer-challenge-2007/\r\n\r\n== Rankings(rounds=\"summer2007-runda1 | summer2007-runda2 | summer2007-runda3\") ==',4772,'public',NULL,NULL),('summer-challenge-2007/runda-3','Summer Challenge 2007, Runda 3','2007-08-09 08:56:34','2007-08-10 19:24:35','h1. Summer Challenge 2007, Runda 3\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2007\r\n* \'Runda 1\':summer-challenge-2007/runda-1\r\n* \'Runda 2\':summer-challenge-2007/runda-2\r\n*(active) \'Runda 3\':summer-challenge-2007/runda-3\r\n* \'Clasament\':summer-challenge-2007/clasament\r\n\r\nRunda se va desfasura Duminica, 12 august, la ora {*10^00^*} si va dura *3h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"summer2007-runda3\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"summer2007-runda3\" score=\"1\")==\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 3\':summer-challenge-2007/clasament/runda-3\r\n\r\nh2. Organizatori\r\n\r\n* ==User(user=\"ditzonec\" type=\"tiny\")==\r\n* ==User(user=\"silviug\" type=\"tiny\")==\r\n* ==User(user=\"cosmin\" type=\"tiny\")==\r\n* ==User(user=\"danielp\" type=\"tiny\")==\r\n* ==User(user=\"alexandru.mosoi\" type=\"tiny\")==\r\n',1,'protected',NULL,NULL),('summer-challenge-2007','Summer Challenge 2007','2007-07-25 10:04:21','2007-08-10 19:18:14','h1. Summer Challenge 2007\r\n\r\n(htabs)*(active) \'Detalii\':summer-challenge-2007/\r\n* \'Runda 1\':summer-challenge-2007/runda-1\r\n* \'Runda 2\':summer-challenge-2007/runda-2\r\n* \'Runda 3\':summer-challenge-2007/runda-3\r\n* \'Clasament\':summer-challenge-2007/clasament\r\n\r\nIn toiul vacantei de vara, feriti de canicula, la umbra monitoarelor, infoarena se gandeste la tine!\r\n\r\nTe invitam sa participi la seria de concursuri {*Summer Challenge 2007*}. Vom organiza 3 runde online, de cate -5h fiecare- 5 sau 3 ore fiecare, cu probleme de dificultate variata.\r\n\r\nSummer Challenge este o ocazie buna de antrenament pentru tine (daca nu esti deja la mare :) dar si un ultim test pentru delegatia\r\nRomaniei la Olimpiada Internationala de Informatica 2007 (Croatia).\r\n\r\nAi ocazia sa concurezi cu lotul Romaniei la IOI 2007!\r\n\r\nh2. Program concurs\r\n\r\ntable{width: 50%}. |_. Runda|_. Data |_. Ora |\r\n|\"*Runda 1*\":summer-challenge-2007/runda-1|*Luni, 30 iulie 2007*| *10^00^ - 15^00^* |\r\n|\"*Runda 2*\":summer-challenge-2007/runda-2|*Vineri, 10 august 2007*| *10^00^ - 15^00^* |\r\n|\"*Runda 3*\":summer-challenge-2007/runda-3| *Duminica, 12 august 2007* | *10^00^ - 13^00^* |\r\n\r\nClick pe titlul unei runde pentru informatii detaliate.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"51\" count=\"10\")==\r\n\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru.\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti probleme, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nh2. Prima data pe infoarena?\r\n\r\ninfoarena ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi.\r\n\r\nVezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n',1,'protected',NULL,NULL),('summer-challenge-2007/runda-1','Summer Challenge 2007, Runda 1','2007-07-25 10:21:15','2007-08-12 10:22:25','h1. Summer Challenge 2007, Runda 1\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2007\r\n*(active) \'Runda 1\':summer-challenge-2007/runda-1\r\n* \'Runda 2\':summer-challenge-2007/runda-2\r\n* \'Runda 3\':summer-challenge-2007/runda-3\r\n* \'Clasament\':summer-challenge-2007/clasament\r\n\r\nRunda se va desfasura Luni 30 iulie, la ora {*10^00^*} si va dura *5h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"summer2007-runda1\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"summer2007-runda1\" score=\"1\")==\r\n\r\nSolutiile le gasiti \'aici\':summer-challenge-2007/solutii/runda-1\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 1\':summer-challenge-2007/clasament/runda-1\r\n\r\nh2. Organizatori\r\n\r\n==User(user=\"ditzonec\" type=\"tiny\")==',13,'protected',NULL,NULL),('summer-challenge-2007/clasament/runda-2','Clasament Summer Challenge 2007, Runda 2','2007-08-07 21:49:26','2007-08-10 19:24:26','h1. Clasament \'Summer Challenge 2007, Runda 2\':summer-challenge-2007/runda-2\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2007\r\n* \'Runda 1\':summer-challenge-2007/runda-1\r\n*(active) \'Runda 2\':summer-challenge-2007/runda-2\r\n* \'Runda 3\':summer-challenge-2007/runda-3\r\n*(active) \'Clasament\':summer-challenge-2007/clasament\r\n\r\n== Rankings(rounds=\"summer2007-runda2\") == ',1,'protected',NULL,NULL),('summer-challenge-2007/clasament','Clasament Summer Challenge 2007','2007-08-10 19:21:28','2007-08-12 10:39:55','h1. Clasament \'Summer Challenge 2007\':summer-challenge-2007/\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2007\r\n* \'Runda 1\':summer-challenge-2007/runda-1\r\n* \'Runda 2\':summer-challenge-2007/runda-2\r\n* \'Runda 3\':summer-challenge-2007/runda-3\r\n*(active) \'Clasament\':summer-challenge-2007/clasament\r\n\r\nAcesta este clasamentul cumulat pe cele 3 runde online.\r\n\r\n== Rankings(rounds=\"summer2007-runda1 | summer2007-runda2 | summer2007-runda3\") ==',13,'public',NULL,NULL),('summer-challenge-2007/runda-2','Summer Challenge 2007, Runda 2','2007-08-07 21:47:27','2007-08-10 20:19:17','h1. Summer Challenge 2007, Runda 2\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2007\r\n* \'Runda 1\':summer-challenge-2007/runda-1\r\n*(active) \'Runda 2\':summer-challenge-2007/runda-2\r\n* \'Runda 3\':summer-challenge-2007/runda-3\r\n* \'Clasament\':summer-challenge-2007/clasament\r\n\r\nRunda se va desfasura Vineri, 10 august, la ora {*10^00^*} si va dura *5h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"summer2007-runda2\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"summer2007-runda2\" score=\"1\")==\r\n\r\nSolutiile le gasiti \'aici\':summer-challenge-2007/solutii/runda-2\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 2\':summer-challenge-2007/clasament/runda-2\r\n\r\nh2. Organizatori\r\n\r\n* ==User(user=\"ditzonec\" type=\"tiny\")==\r\n* ==User(user=\"silviug\" type=\"tiny\")==\r\n* ==User(user=\"cosmin\" type=\"tiny\")==\r\n* ==User(user=\"danielp\" type=\"tiny\")==\r\n* ==User(user=\"alexandru.mosoi\" type=\"tiny\")==\r\n',961,'protected',NULL,NULL),('blog/summer-challenge-2007/incheiere','Summer Challenge 2007 s-a incheiat','2007-08-12 10:37:58','2007-08-12 10:39:32','Concursul online _Summer Challenge_ organizat de infoarena s-a incheiat.\r\nFelicitari participantilor si, mai ales, castigatorilor!\r\n\r\n&rarr; \'*Clasamentul cumulat*\':summer-challenge-2007/clasament pe cele 3 runde\r\n&rarr; \'Pagina concursului\':summer-challenge-2007\r\n\r\nSperam ca a fost o experienta utila pentru lotul Romaniei la IOI 2007 (care incepe peste numai 3 zile!). \r\nVa tinem pumnii!\r\n',13,'protected',NULL,NULL),('implica-te/extinde-arhiva','Extinde arhiva','2007-03-12 22:59:26','2010-04-24 23:52:37','h1. Extinde arhiva ==Stars(rating=\"3\")==\r\n\r\nArhiva este una dintre cele mai folositoare sectiuni _infoarena_ pentru utilizatorii nostri. Ea contine probleme pentru multe gusturi. Dar nu pentru toate! Vrem sa o imbunatatim cu probleme cat mai diverse si cu grade de dificultate cat mai variate. La fiecare olimpiada sau concurs national important apar noi \"creatii\" pe care ne straduim sa le punem la dispozitia tuturor intr-un timp cat mai scurt. Ajuta-ne in acest demers!\r\n\r\nh2. De ce m-as baga?\r\n\r\n# Vei afla cum se propune si cum se corecteaza o problema. Vei sti cum sa propui propriile probleme pe _infoarena_.\r\n# Intreaga comunitate iti va multumi pentru noul \"material\" de pregatire.\r\n# Vei fi si tu \"de partea cealalta a baricadei\".\r\n# Pentru unele probleme vei putea scrie enuntul personalizat (cu numele simpatiei tale, spre exemplu).\r\n# Unde-s multi, puterea creste! :P\r\n\r\nh2. Ce pot sa fac?\r\n\r\n# Contacteaza-l pe ==user(user=\"stef2n\" type=\"tiny\")== pe \'forum\':forum/index.php/board,42.0.html sau e-mail.\r\n# Alege-ti problemele pe care vrei sa le pui in arhiva si *verifica* daca exista \'acordul\':implica-te/extinde-arhiva/acord autorului pentru a pune problemele respective. \r\n*{color:red}Atentie!* Comunica acest lucru lui Stefan cat mai repede pentru a evita suprapunerile si pentru a putea aparea in tabelul cu voluntarii activi ;)\r\n# *{color:red}Foarte important:* Citeste despre \'cum se adauga o problema\':documentatie/editare-de-probleme, \"conventii de formatare\":documentatie/conventii-de-formatare si \'textile\':documentatie/textile si intreaba pe forum daca ai nelamuriri.\r\n# Abia dupa ce ai terminat de citit documentatia, cere drepturi de helper pentru a putea pune probleme pe infoarena.\r\n# Scrie enuntul unei probleme folosind \'textile\':http://infoarena.ro/documentatie/textile si gandeste-te la solutii alternative.\r\n# Imbunatateste testele si creeaza altele noi, astfel incat problema sa devina de actualitate.\r\nToate bulanelile/ciucuielile care s-au facut in concursul respectiv trebuie facute sa pice.\r\n# Stabileste limitele de timp si memorie conform cu mediul infoarena de evaluare.\r\n\r\nh2. Problemele la care se lucreaza acum\r\n\r\nTODO\r\n\r\ntable. |_. Sursa de probleme |_. Voluntar |_. Progres |\r\n| Probleme baraje | ==User(user=\"astronomy\" type=\"tiny\")== ==User(user=\"toni2007\" type=\"tiny\")== | ?/? |\r\n| Probleme Cosmin Negruseri | ==User(user=\"bogdan2412\" type=\"tiny\")== | 3/4 |\r\n\r\nh2. Probleme de pus in arhiva \r\n\r\n* \"preONI 2003\":downloads?action=download&file=preoni2.zip\r\n* Probleme de orice autor din \'lista de propunatori infoarena-friendly\':implica-te/extinde-arhiva/acord\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"42.0\")==\r\n',2028,'protected',NULL,NULL),('implica-te/scrie-articole','Scrie articole','2007-03-28 22:23:46','2010-02-15 12:27:54','h1. Scrie articole ==Stars(rating=\"4\")==\r\n\r\nFolosind modelul de \'wiki\':documentatie/wiki, infoarena oferă şansa tuturor membrilor săi să contribuie la realizarea de articole sau la îmbunătăţirea celor existente. Dacă vrei să afli mai multe despre conceptul de wiki intră \'aici\':http://en.wikipedia.org/wiki/Wiki, iar dacă vrei să contribui la această iniţiativă citeşte mai jos ce trebuie sa faci.\r\n\r\nh2. De ce m-aş băga?\r\n\r\n* O carieră în cercetare în informatică poate debuta cu nişte articole online!\r\n* Vei învăţa care sunt elementele cheie pentru a scrie un articol.\r\n* Vei învăţa pe alţii ceea ce ştii, aşa cum probabil şi tu ai învăţat din articolele deja \'existente\':articole.\r\n\r\nh2. Ce pot să fac?\r\n\r\nDe-a lungul timpului, utilizatorii infoarena şi-au manifestat interesul în a scrie articole pentru întreaga comunitate. În momentul de faţă ne concentrăm eforturile atât pe completarea şi aducerea la o formă prezentabilă a acestor articole vechi, cât şi pe scrierea de articole noi. Sunt 3 moduri în care poţi contribui:\r\n\r\nh3. 1. Ajută-ne la ce lucrăm acum\r\n\r\nÎn tabelul de mai jos poţi găsi articolele începute, împreună cu stadiul în care se găseşte fiecare. Dacă eşti dornic să ne ajuţi, alege-ţi unul din articolele de care nu se ocupă nimeni şi ia legătura cu coordonatorul proiectului ca să afli ce mai e de făcut la el.\r\n\r\ntable. |_. Titlu |_. Autor |_. Stadiu |_. Voluntar(i) |\r\n| \'Transformari geometrice\':transformari-geometrice | ==user(user=\"Cosmin\" type=\"tiny\")== | ÎN LUCRU | ==user(user=\"Marius\" type=\"tiny\")== |\r\n| \'Arbori indexaţi binar\':arbori-indexati-binar | ==user(user=\"skortzy\" type=\"tiny\")== | ÎN LUCRU | ? |\r\n| \'Arborele componentelor biconexe şi al nodurilor critice\':http://infoarena.ro/downloads?action=download&file=arborele_componentelor_biconexe_si_al_nodurilor_critice.doc&safe_only=false | ==user(user=\"mugurelionut\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Algoritmi de flux maxim în reţele\':http://infoarena.ro/downloads?action=download&file=flux_maxim_in_retele.doc&safe_only=false | ==user(user=\"mugurelionut\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Tehnici avansate de programare dinamică\':pd | ==user(user=\"Zeus\" type=\"tiny\")== | ÎN LUCRU | ==user(user=\"Zeus\" type=\"tiny\")== |\r\n| \'Flux si cuplaj\':flux-si-cuplaj | ==user(user=\"blasterz\" type=\"tiny\")== | ÎN LUCRU | ==user(user=\"blasterz\" type=\"tiny\")== |\r\n\r\nh3. 2. Preia şi dezvoltă un subiect mai vechi\r\n\r\nAi nevoie de un impuls pentru a-ţi da drumul la scris? Sunt câteva articole pe infoarena începute, dar abandonate, precum şi nişte schiţe. Poţi folosi ideile de start ale autorului şi îl poţi transforma într-un articol bine documentat. În plus, poţi lua legătura cu autorul iniţial şi poţi afla viziunea sa asupra subiectului. Iată o listă de articole abandonate şi de schiţe:\r\n\r\ntable. |_. Titlu |_. Autor initial |\r\n| Programare dinamica / memoizare (trading space for time): \'link1\':programare-dinamica | ==user(user=\"Zeus\" type=\"tiny\")== |\r\n| \'Arbori indexati binar\':aib | ==user(user=\"Skipy\" type=\"tiny\")== |\r\n| \'Dinic\':dinic | ==user(user=\"alexandru.mosoi\" type=\"tiny\")== |\r\n| \'Probleme de geometrie si solutii\':downloads?geometrie.zip | ==user(user=\"Cosmin\" type=\"tiny\")== |\r\n| \'Teoria jocurilor\':teoria-jocurilor | ==user(user=\"filipb\" type=\"tiny\")== |\r\n| \'Psihologia concursurilor de informatica - Lucrul cu numere mari\':lucrul-cu-nr-mari | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| Psihologia concursurilor de informatica - Lucrul cu structuri mari de date | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| Psihologia concursurilor de informatica - Probleme de concurs | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| \'Notiuni de geometrie analitica si aplicatii\':notiuni-de-geometrie-si-aplicatii | ==user(user=\"devilkind\" type=\"tiny\")== \r\n==user(user=\"sima_cotizo\" type=\"tiny\")== |\r\n| \'Diagrame Voronoi\':voronoi | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| \'Algoritmi de baleiere\':algoritmi-de-baleiere | ==user(user=\"stef2n\" type=\"tiny\")== |\r\n\r\nh3. 3. Creează ceva nou\r\n\r\nAi o idee nouă de articol? Sau pur şi simplu vrei să te apuci de la 0 de un subiect? Ia legătura cu coordonatorul proiectului sau anunţă pe \'forum\':forum. Este posibil să primeşti ajutor şi de la alţi utilizatori infoarena. În plus, noi îţi propunem o listă de articole pe care ni le-am dori scrise, în caz că nu te-ai decis asupra temei:\r\n\r\ntable. |_. Titlu |\r\n| Depanarea programelor C/C++ cu gdb in Linux |\r\n| Testarea surselor in timp de concurs sau Cum sa reduci buselile |\r\n| Tutorial LaTeX |\r\n| Probleme cu becuri |\r\n| Punct în interiorul unui poligon neconvex |\r\n| Automate |\r\n\r\nNe rezervam dreptul să nu acceptăm sau să ştergem articolele care nu se potrivesc cu tema şi target-ul site-ului.\r\n\r\nh2. Cu cine iau legătura?\r\n\r\nCu coordonatorul proiectului:\r\n\r\n* ==user(user=\"Marius\" type=\"tiny\")==\r\n\r\nSau dacă vrei să contribui la un articol la care se lucrează deja, poţi vorbi direct cu voluntarii care se ocupă de el.\r\n\r\nh2. Discuţii pe forum\r\n\r\n==SmfTopics(board_id=\"43\")==',3146,'protected',NULL,NULL),('utilizator/marsamg','Profil marsamg','2007-08-20 06:32:55','2007-08-20 06:32:55','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6728,'public',NULL,NULL),('utilizator/azotlichid','Profil azotlichid','2006-11-23 20:29:26','2007-08-23 07:39:25','h2. Despre mine\r\n\r\n* Membru al comisiei la Stelele Informaticii 2006, ONI 2007, Lot Alba 2007\r\n* In 2007 am tinut cateva cursuri de informatica la ICHB\r\n\r\nh2. Studii\r\n\r\n* Student la Brown University (2007-2011)\r\n* Absolvent al Colegiului National de Informatica {@\"Tudor Vianu\"@}, Bucuresti (2002-2006)\r\n\r\nh2. Distinctii primite (cele mai importante)\r\n\r\n* IOI: argint (Grecia, 2004), bronz (Mexic, 2006)\r\n* CEOI: argint (Croatia, 2006)\r\n* BOI: bronz (Bulgaria, 2004)\r\n* ONI: locurile 8 (2003), 2 (2004), 4 (2005), 4 (2006)\r\n* Stelele Informaticii: locurile 4 (2003), 2 (2005)\r\n* PACO: locurile 2 (2004), 1 (2006)\r\n\r\nh2. Articole\r\n\r\n* Siruri de sufixe (impreuna cu Cosmin Negruseri), GInfo 15/10\r\n* Teorema chineza a resturilor - generalizari si aplicatii, GInfo 16/1\r\n\r\n',18,'protected',NULL,NULL),('development-roadmap','infoarena Development Roadmap','2007-08-30 22:22:59','2007-08-31 00:45:49','h1. infoarena Development Roadmap\r\n\r\nAici vom discuta despre viitorul site-ului infoarena din punct de vedere al development-ului. Daca vrei sa aflii mai multe despre cum te poti implica in development intra \'aici\':implica-te/development. De asemenea poti vedea proiectele si sedintele asociatiei infoarena \'aici\':planificare. \r\n\r\nh2. Etapa 1 (no more _beta_)\r\n\r\n_Deadline: pana la sfarsitul anului 2007_\r\n\r\nh3. Agenda\r\n\r\nScopul principal al developmentului ar trebui sa fie imbunatatirea site-ului in vederea organizarii urmatorului preONI, atat din punct de vedere al utilizatorului cat si al administratorului. Trebuie sa:\r\n\r\n# asiguram functionalitatea care exista deja in infoarena 1.0.\r\n# reparam \'bug-urile\':forum/index.php?topic=1359.0 raportate\r\n# investigam \'feature request-urile\':forum/index.php?board=33.0 primite\r\n# implementam feature-uri *2.0*:\r\n## posibilitatea de a rula concursuri automat\r\n## tipuri noi de probleme (output-only, reactive, ACM, etc.)\r\n\r\nh3.  Milestone-uri\r\n\r\n* \'2.1.5 Bells of Innocence\':http://hackers.devnet.ro/milestone/2.1.5%20Bells%20of%20Innocence\r\n* \'2.1.6 Code of Silence\':http://hackers.devnet.ro/milestone/2.1.6%20Code%20of%20Silence\r\n\r\nh2. Etapa 2 (2.0+)\r\n\r\nh3. Agenda\r\n\r\nScopul principal este sa marim target-ul site-ului infoarena si functionalitatea pe care acesta o ofera. Be creative! De-a lungul anilor am avut mai multe \'proiecte\':forum/index.php?board=18.0 si \'idei\':forum/index.php?board=21.0 care nu s-au materializat. Acum e momentul sa punem in practica toate ideile pe care le-am avut! Trebuie sa:\r\n\r\n# adaugam un blog\r\n# fim \"open-source\" din punct de vedere al surselor trimise de concurenti\r\n# implementam \"training path\"-uri\r\n# implementam noi tipuri de concursuri (de viteza, de debug, etc.)\r\n# _more to come_\r\n\r\nh3.  Milestone-uri\r\n\r\n_Atentie, listele de tickete sunt incomplete!_\r\n\r\n* \'2.2 Firewalker\':http://hackers.devnet.ro/milestone/2.2%20Firewalker\r\n* \'2.3 Sons of Thunder\':http://hackers.devnet.ro/milestone/2.3%20Sons%20of%20Thunder\r\n',1,'public',NULL,NULL),('runda/autumn2007-runda1/clasament','Clasament autumn2007-runda1','2007-09-03 20:19:03','2007-09-03 20:19:03','h1. Clasament ==roundparam(round_id=\"autumn2007-runda1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"autumn2007-runda1\")==',961,'round: autumn2007-runda1',NULL,NULL),('autumn-warmup-2007/clasament/runda-1','Clasament Runda 1','2007-09-03 20:22:15','2007-10-06 20:04:26','h1. Clasament \'Autumn Warmup 2007, Runda 1\':autumn-warmup-2007/runda-1\r\n\r\n(htabs)* \'Detalii\':autumn-warmup-2007/\r\n*(active) \'Runda 1\':autumn-warmup-2007/runda-1\r\n* \'Runda 2\':autumn-warmup-2007/runda-2\r\n* \'Runda 3\':autumn-warmup-2007/runda-3\r\n*(active) \'Clasament\':autumn-warmup-2007/clasament\r\n\r\n== Rankings(rounds=\"autumn2007-runda1\") == ',961,'public',NULL,NULL),('utilizator/100puncte','Profil 100puncte','2007-09-06 13:24:20','2007-09-06 13:24:20','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6760,'public',NULL,NULL),('warm-up-2007','warmup2007','2007-09-05 19:13:17','2007-09-05 19:13:17','Scrie aici despre warm-up-2007',4374,'public',NULL,NULL),('blog/autumn-warmup-2007/runda-1','Autumn Warm-Up 2007, Runda 1','2007-09-09 18:53:37','2007-09-09 18:54:59','Vacanta de vara a ajuns la sfarsit.  E timpul sa te revezi cu vechii tai prieteni de la concursurile de info si sa le demonstrezi ca ai ramas in forma.  :)\r\nTe invitam sa participi la runda 1 a concursului Autumn Warm Up cu probleme propuse de utilizatori infoarena.\r\n\r\nRunda 1 se desfasoara *Marti, 11 septembrie 2007, orele 10^00^ - 15^00^*.\r\n\r\n&rarr; \'Autumn Warm Up, Runda 1\':autumn-warmup-2007/runda-1\r\n',13,'public',NULL,NULL),('autumn-warmup-2007/solutii/runda-1','Solutii Autumn Warmup, Runda 1','2007-09-11 11:37:55','2009-02-04 13:14:55','h1. Solutii runda 1\r\n\r\nh2. \'Banuti\':problema/banuti\r\n\r\nNotam cu $min$ valoarea minima. Se observa ca pentru o suma oarecare $s$, daca toate sumele din intervalul $(s,s+min]$ pot fi obtinute, atunci toate sumele $> s$ pot fi obtinute la randul lor. (Pentru a va convinge, in caz ca aveti neclaritati, simulati un knapsack). Se construieste un graf cu $min$ noduri, nodul $x$ semnificand restul $x$ la impartirea cu $min$. Se defineste $cost[x]$, suma minima care poate fi obtinuta $(s)$, cu proprietatea ca $s%min=x$ (restul impartirii sumei la $min$ este $x$); @cost[0]=0@. Se observa ca daca putem obtine o suma $s$, atunci putem obtine toate sumele $s+k*min$ (care au acelasi rest), unde $k>0$. In acest graf fiecare bancnota (de valoare $v$), formeaza o muchie intre nodul $y$ si nodul $(y+v)%min$, cu costul $v$, unde $y$ apartine $[0,min)$. Daca acest graf nu este conex atunci nu avem solutie. Daca este conex, atunci solutia se afla in $max(cost[x])-min$, $x$ apartine $[0,min)$, care poate fi aflata cu Dijkstra. Mentionez faptul ca graful ar avea teoretic $N*min$ muchii. Pe cazul general, $N>min$, deci unele muchii sunt in plus (conform principiului cutiei). Graful pe care se face rezolvarea ar trebui sa aiba $&#8776;min^2^$ muchii. Complexitatea finala este $O(min^2^)$. \r\n\r\n\r\nh2. \'Renovare\':problema/renovare\r\n\r\nVom reduce problema la flux maxim de cost minim astfel: pentru fiecare muchie $a b c cst$ cu semnificatia din enunt vom adauga $2$ muchii in retea, una de capacitate $c$ si cost $0$ si inca una de capacitate infinit si cost $cst$. De asemenea vom conecta nodul $1$ la o sursa auxiliara printr-o muchie de capacitate $x$ si cost $0$. Apoi se ruleaza algoritmul de flux maxim de cost minim in reteaua noua.\r\n\r\nh2. \'Plan\':problema/plan\r\n\r\nConstruim graful componentelor tare conexe si in continuare ne vom referi numai la acest graf. Plasam in multimea $X$ nodurile cu grad de intrare 0, iar in multimea $Y$ nodurile cu grad de iesire 0. Vom gasi in continuare un mod de a construi $max(cardX, cardY)$ sosele si este clar ca acest numar e minim deoarece din fiecare nod din $X$ trebuie sa intre macar o muchie, iar din fiecare nod din $Y$ trebuie sa iasa macar o muchie. In continuare ne vom construi un set maximal (atentie, maximal != maxim) de perechi $(x{~1~}, y{~1~}), (x{~2~}, y{~2~}) ... (x{~k~}, y{~k~})$ astfel incat $x{~1~}, x{~2~} .. x{~k~}$ apartin lui $X$ iar $y{~1~}, y{~2~}.. y{~k~}$ apartin lui $Y$. Mai mult exista drum in graf de la $x{~i~}$ la $y{~i~}$. Acest set se poate construi simplu efectuand cate o parcurgere din fiecare nod a lui $X$. Adaugam muchie de la $y{~1~}$ la $x{~2~}$, $y{~2~}$ la $x{~3~}$ ... $y{~k~}$ la $x{~1~}$. In continuare adaugam muchii de la fiecare nod ramas din $Y$ la un nod ramas din $X$ pana cand vom avea noduri doar in $X$ sau doar in $Y$. Pentru acele noduri adaugam o muchie de la ele la $x{~1~}$ sa zicem, sau de la $x{~1~}$ la ele in functie daca sunt din $X$ sau din $Y$. Am adaugat cate muchii ne-am propus, acum sa vedem daca respecta proprietatea ca avem un drum de la orice nod la orice nod. Dupa ce am construit acel set maximal si practic am construit un ciclu adaugand muchiile, nodurile care au mai ramas din multimea $X$ au drum de la ele la un nod din ciclu, iar cele din multimea $Y$ ramase au drum de la un nod din ciclu la ele. Deci cand consideram doua noduri $A$ si $B$, cu $A$ din $X$ si $B$ din $Y$ si dintre cele care au ramas dupa alegerea nodurilor din setul maximal, si tragem muchie de la $B$ la $A$ vom avea drum de la nodurile din ciclu la $A$, la $B$ si de la ele la nodurile din ciclu. Acelasi lucru se intampla si in momentul cand raman noduri doar din $X$ sau doar din $Y$, vom avea drum de la un nod din ciclu la ele si invers. Deci daca consideram un nod oarecare $P$, acest nod fie este pe ciclu, fie exista drum de la el la ciclu si invers, adica exista drum de la el spre toate nodurile si de la toate nodurile spre el. Pentru nodurile care nu sunt din $X$ sau din $Y$ avem macar un drum de la ele la un nod din $Y$ si de la un nod din $X$ la ele, deci respecta proprietatea.\r\n\r\nh2. \'Numar de Divizori\':problema/ndiv\r\n\r\nSe afla solutia pentru intervalul $[1, A-1]$ si $[1, B]$ si se face diferenta. Pentru un interval $[1, N]$ si un numar $X$, se afla numarul de numere din interval care se divid la $X$ prin aflarea catului $N / X$. O simpla solutie ar fi pentru fiecare $X = 1 2 ... N$ se face suma lui $N/X$. Evident nu intra in timp. Daca se scrie sirul $N/X$ cu $X$ de la $1$ la $N$ se observa ca termenii sirului sunt in ordine descrescatoare. De exemplu sa vedem pentru $N = 12$, vom avea sirul $N/X$ : $12/1$, $12/2$, $12/3$ ... $12/12$ care este $12, 6, 4, 3, 2, 2, 1, 1, 1, 1, 1, 1$. Solutia se bazeaza pe faptul ca aceste numere se repeta pe anumite intervale. Astfel se iau toate numerele $i$ de la $1$ la $sqrt(N)$ si se vor tine intr-un vector sortate valorile: $i$ si $N/i$. Acum pentru doua pozitii consecutive in acest vector vom avea doua valori: $X1$ si $X2$ si $N/X1$ = $N/X2$. Si orice numar din intervalul $[X1, X2]$, sa zicem $Y$ va avea $N/Y$ = $N/X1$. Acum se iau toate pozitiile consecutive in vectorul format si se aduna la solutie $(N/X1)*(X2-X1+1)$ (lungimea intervalului). Corectitudinea acestei solutii se bazeaza pe faptul ca daca ar fi sa imparti numarul $N$ la toate numerele de la $1$ la $N$, se obtin $2*sqrt(N)$ diferite caturi. De exemplu nu poti sa imparti $12$ la ceva mai mic egal cu $12$ si sa obtii catul $11$. Complexitatea va fi $O(sqrt(N))$. ',6172,'public',NULL,NULL),('implica-te/extinde-arhiva/lista-lu-francu','Lista lu\' Francu','2007-08-11 11:04:25','2009-05-09 13:01:21','h1. Lista lu\' Francu\r\n\r\nObiectivul nostru este sa reinviem \"Lista lu\' Francu\":http://voronet.francu.com/probleme/rom/probleme.html. :)\r\n\r\nMandri voluntari: \r\n==User(user=\"cos_min\" type=\"tiny\")==  \r\n==User(user=\"devilkind\" type=\"tiny\")==\r\n==User(user=\"florian\" type=\"tiny\")==\r\n==User(user=\"gabitzish1\" type=\"tiny\")==\r\n==User(user=\"pauldb\" type=\"tiny\")==\r\n\r\nIn caz ca mai sunt si altii dornici sa ni se alature, contactati-l pe Paul sau pe Silviu pe forum.\r\n\r\nUrmatoarele de pe Lista lu\' Francu au fost deja puse in arhiva (puteti sa le luati ca model de adaptare al problemelor pentru arhiva noastra).\r\n\r\ntable(example). |_. Indice si nume pe infoarena |_. Indice si nume pe Lista lu\' Francu |\r\n| \"478. Maimute\":problema/maimute | \"-4. Arborii contraataca\":http://voronet.francu.com/probleme/arhiva/R00-4/enunt.html|\r\n| \"254. Senat\":problema/senat | \"4. Presedinti de comisii\":http://voronet.francu.com/probleme/arhiva/R0004/enunt.html |\r\n| \"257. Catun\":problema/catun |  \"5. Diagrame Voronoi pe grafuri\":http://voronet.francu.com/probleme/arhiva/R0005/enunt.html |\r\n| \"255. Vila\":problema/vila |  \"8. Vila de senator\":http://voronet.francu.com/probleme/arhiva/R0008/enunt.html |\r\n| \"260. Note\":problema/note |  \"9. Scherzo\":http://voronet.francu.com/probleme/arhiva/R0009/enunt.html |\r\n| \"259. Euler\":problema/euler |  \"11. Parcurgere Euler\":http://voronet.francu.com/probleme/arhiva/R0011/enunt.html |\r\n| \"256. Puternic\":problema/puternic |  \"12. Numere puternice\":http://voronet.francu.com/probleme/arhiva/R0012/enunt.html |\r\n| \"258. Alpin\":problema/alpin |  \"14. Alpinism\":http://voronet.francu.com/probleme/arhiva/R0014/enunt.html |\r\n| \"261. Bilete\":problema/bilete |  \"15. Blatistul\":http://voronet.francu.com/probleme/arhiva/R0015/enunt.html |\r\n| \"463. Conserve\":problema/conserve | \"24. Alpinistul contraataca III \":http://voronet.francu.com/probleme/arhiva/R0024/enunt.html |\r\n| \"479. Order2\":problema/order2 | \"28. Ordonare\":http://voronet.francu.com/probleme/arhiva/R0028/enunt.html|\r\n| \"409. Secvente\":problema/secvente | \"32. Secvente\":http://voronet.francu.com/probleme/arhiva/R0032/enunt.html |\r\n| \"538. Impartire\":problema/impartire  | \"-8. Impartire\":http://voronet.francu.com/probleme/arhiva/R00-8/enunt.html | | \r\n| \"537. Capitala\":problema/capitala | \"-7. Capitala\":http://voronet.francu.com/probleme/arhiva/R00-7/enunt.html |   \r\n| \"535. Drum\":problema/drum | \"-6. Jocul Drumului\":http://voronet.francu.com/probleme/arhiva/R00-6/enunt.html| \r\n| \"536. Razboi 2\":problema/razboi2 | \"-3. In vreme de razboi...\":http://voronet.francu.com/probleme/arhiva/R00-3/enunt.html| \r\n| \"539. Permutari 6\":problema/perm6 | \"-2. Permutari\":http://voronet.francu.com/probleme/arhiva/R00-2/enunt.html |\r\n| \"533. Retele\":problema/retele | \"1. Retele de telefonie\":http://voronet.francu.com/probleme/arhiva/R0001/enunt.html |\r\n| \"550. Logic 2\":problema/logic2 | \"16. Insula logicii\":http://voronet.francu.com/probleme/arhiva/R0016/enunt.html | \r\n| \"532. Functii\":problema/functii | \"18. Numarare functii\":http://voronet.francu.com/probleme/arhiva/R0018/enunt.html | \r\n| \"540. Examene\":problema/examene | \"19. Programa subtirica\":http://voronet.francu.com/probleme/arhiva/R0019/enunt.html |\r\n| \"534. Tablite\":problema/tablite | \"35. Numere\":http://voronet.francu.com/probleme/arhiva/R0035/enunt.html | \r\n| \"524. Cinema\":problema/cinema | \"34. Secventa\":http://voronet.francu.com/probleme/arhiva/R0034/enunt.html | \r\n| \"528. Cod\":problema/cod | \"36. Coduri\":http://voronet.francu.com/probleme/arhiva/R0036/enunt.html | \r\n| \"551. Triticale\":problema/triticale | \"37. Turn de triticale\":http://voronet.francu.com/probleme/arhiva/R0037/enunt.html |\r\n| \"530. Interclasare\":problema/interclasare | \"39. Interclasare\":http://voronet.francu.com/probleme/arhiva/R0039/enunt.html | \r\n| \"542. Modulo\":problema/modulo | \"31. Modulo\":http://voronet.francu.com/probleme/arhiva/R0031/enunt.html |\r\n| \"543. Tetris\":problema/tetris | \"22. Tetris\":http://voronet.francu.com/probleme/arhiva/R0022/enunt.html |\r\n| \"541. Pastila\":problema/pastila | \"45. Balanta medicinala\":http://voronet.francu.com/probleme/arhiva/R0045/enunt.html |\r\n\r\nCei mai harnici voluntari (incepand cu 9 august 2007):\r\n\r\n|_. Utilizator |_. Numarul de probleme bagate |\r\n| ==User(user=\"cos_min\" type=\"tiny\")== | 2 |\r\n| ==User(user=\"devilkind\" type=\"tiny\")== | 3 |\r\n| ==User(user=\"gabitzish1\" type=\"tiny\")== | 6 |\r\n| ==User(user=\"florian\" type=\"tiny\")== | 3 |\r\n| ==User(user=\"pauldb\" type=\"tiny\")== | 3 |\r\n\r\nModificati singuri tabelul, dar doar atunci cand ati terminat de bagat o problema (enunt, teste, sursa, eval). \r\n\r\nAici aveti o lista cu probleme de pe lista lui Francu. Problemele care au statusul %{color:red}Trebuie adaugata% sunt cele care ne intereseaza in acest moment. Problemele care nu apar in acest tabel ori nu se potrivesc cu sistemul infoarena ori linkul de pe lista nu mai merge. Cand v-ati decis asupra unei probleme adaugati linkul problemei in tabel ca fiind %{color:green}Adaugata% (linkul se inverzeste singur) iar in coloana de informatii treceti id-ul vostru, in felul acesta daca cineva are o super-idee la o problema care a fost adaugata de altcineva se poate uita in tabel si contacta pe cel care a introdus problema. De asemenea daca o problema vi se pare prea simpla o puteti modifica (in limitele bunului simt).\r\nUnele din problemele de pe lista se regasesc complet in alte probleme de pe infoarena. Nu are rost sa mai punem si aceste probleme. Acele probleme au statusul %{color:green}Inclusa%, avand linkul la status.\r\n\r\ntable(example). |_. Problema de pe lista |_. Status |_. Informatii|\r\n| \"-5. Robotul si gaura\":http://voronet.francu.com/probleme/arhiva/R00-5/enunt.html| %{color:blue}Interactiva% | - |\r\n| \"-1. Observabile\":http://voronet.francu.com/probleme/arhiva/R00-1/enunt.html | %{color:green}Adaugata-link lipsa% | ==User(user=\"alexthero\" type=\"tiny\")== |\r\n| \"2. Sah\":http://voronet.francu.com/probleme/arhiva/R0002/enunt.html | %{color:blue}Interactiva% | - |\r\n| \"3. Fractali\":http://voronet.francu.com/probleme/arhiva/R0003/enunt.html | %{color:red}Trebuie adaugata% | - |\r\n| \"6. Baza de date\":http://voronet.francu.com/probleme/arhiva/R0006/enunt.html | \"Inclusa\":problema/prefix |\r\n| \"7. Jocul vietii 1D\":http://voronet.francu.com/probleme/arhiva/R0007/enunt.html| %{color:green}Adaugata-link lipsa% | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| \"13. Ghisee\":http://voronet.francu.com/probleme/arhiva/R0013/enunt.html | %{color:blue}Interactiva% | - |\r\n| \"20. Alpinistul is coming back\":http://voronet.francu.com/probleme/arhiva/R0020/enunt.html | %{color:red}Trebuie adaugata% | - |\r\n| \"21. Puzzle\":http://voronet.francu.com/probleme/arhiva/R0021/enunt.html | %{color:red}Trebuie adaugata% | Rezolvare dubioasa |\r\n| \"23. Nim\":http://voronet.francu.com/probleme/arhiva/R0023/enunt.html | \"Inclusa\":problema/joc3 | - |\r\n| \"26. Turnu Eiffel\":http://voronet.francu.com/probleme/rom/probleme.html| %{color:red}Trebuie adaugata% | Facuta o solutie a comisiei, si punctajul in functie de solutia comisiei |\r\n| \"27. Poker American\":http://voronet.francu.com/probleme/arhiva/R0027/enunt.html | %{color:blue}Interactiva% | - |\r\n| \"29. Amestecand..amestecuri\":http://voronet.francu.com/probleme/arhiva/R0029/enunt.html | %{color:red}Trebuie adaugata% | - |\r\n| \"30. Reciclarea sticlei\":http://voronet.francu.com/probleme/arhiva/R0030/enunt.html| %{color:green}Adaugata-link lipsa% | ==User(user=\"Florian\" type=\"tiny\")==  |\r\n| \"33. Din mosi stramosi\":http://voronet.francu.com/probleme/arhiva/R0033/enunt.html | \"Inclusa\":problema/concurs | \r\n| \"38. The matrix has you\":http://voronet.francu.com/probleme/arhiva/R0038/enunt.html | %{color:red}Trebuie adaugata% | \r\n| \"40. Straturi\":http://voronet.francu.com/probleme/arhiva/R0040/enunt.html | %{color:red}Trebuie adaugata% | - |\r\n| \"42. Soarecele si pisica\":http://voronet.francu.com/probleme/arhiva/R0042/enunt.html | %{color:red}Trebuie adaugata% | - |\r\n| \"43. Vechea masina de calcul\":http://voronet.francu.com/probleme/arhiva/R0043/enunt.html | %{color:red}Trebuie adaugata% | - |\r\n| \"44. Verigi\":http://voronet.francu.com/probleme/arhiva/R0044/enunt.html | %{color:red}Trebuie adaugata% | - |\r\n',5748,'public',NULL,NULL),('despre-blog','Despre Blog','2007-11-04 14:57:37','2008-02-10 23:22:38','h1. Despre Blog\r\n\r\ninfoarena.ro este un site creat de fosti olimpici la informatica pentru viitorii olimpici. El are probleme ale caror solutii pot fi evaluate online, articole educationale, un forum foarte activ si este inconjurat de o comunitate vibranta. Puteti vedea cateva marturii \'aici\':marturii si mai multe despre site \'aici\':despre-infoarena.\r\n\r\nBlogul infoarena a aparut ca o nevoie de a comunica pe un canal mai bun decat forumul, cu programatorii in general si cu membrii comunitatii infoarena in particular.\r\n\r\nEu sunt Cosmin Negruseri, membrul \'echipei\':echipa-infoarena care se ocupa de blog. Am facut facultatea la sectia Informatica din Universitatea Babes Bolyai - Cluj, am participat la concursuri de programare atat in postura de concurent cat si in cea de membru al comisiei, am fost editor al \'gazetei de informatica\':http://www.ginfo.ro pe perioada unui an, publicand 15 articole. Dupa terminarea facultatii m-am angajat la Google inc. ca software engineer in sediul din Mountain View.\r\n\r\n*shameless plug:* Daca esti un programator foarte bun sau daca cunosti programatori foarte buni care sunt interesati de un job la Google spuneti-le sa ma contacteze la cosminn ~ at ~ gmail.com.',58,'protected',NULL,NULL),('utilizator/greco','Profil greco','2006-11-24 20:56:18','2008-03-21 21:38:13','h2. Site personal\r\n\r\n* \'greco.ro\':www.greco.ro\r\n\r\nh2. Competitii\r\n\r\n* 2006 - locul 2 - ACM-ICPC Europa de Sud-Est, impreuna cu domino si DitzoneC in echipa \"infoarena coders\"\r\n* 2006 - medalie de argint - Olimpiada Internationala de Informatica, Merida, Mexic\r\n* 2006 - medalie de argint - Olimpiada de Informatica a Europei Centrale, Vrsar, Croatia\r\n* 2006 - mentiune - Olimpiada Nationala de Informatica\r\n* 2006 - locul 2 - .campion\r\n* 2005 - medalie de aur - Olimpiada Balcanica de Informatica, Rodos, Grecia\r\n* 2005 - mentiune - Olimpiada Nationala de Informatica\r\n* 2005-2006 - membru al lotului national de informatica\r\n\r\nh2. Articole\r\n\r\n* Algoritmul lui Kuhn\r\n\r\nh2. Membru in comisii\r\n\r\n* 2007 - ONI\r\n* 2007 - .campion\r\n* 2007 - preONI\r\n* 2007 - Stelele Informaticii\r\n* 2006 - preONI\r\n\r\nh2. Stiati ca...\r\n\r\n* Creata in 1688 la initiativa stolnicului Constantin Cantacuzino, Academia Domneasca, institutie de invatamant superior, lacas de inalta cultura al Tarii Romanesti, si-a inceput activitatea in Bucuresti la manastirea Sfantul Sava, fiind de-a lungul timpului cea mai importanta scoala din Tarile Romane.\r\n\r\nh2. Despre mine\r\n\r\n* Sunt membru al Asociatiei Independente a Suporterilor Stelisti.\r\n* Am convenit cu wefgef ca Deep Purple, Iron Maiden si Led Zeppelin (nu neaparat in aceasta ordine) sunt cele mai tari 3 formatii din toate timpurile.\r\n* Ma simt cel mai bine la o sticla de Stejar pe Calea Grivitei, aproape de Sava si de Piata Romana.\r\n* Incerc sa-mi fac timp sa invat invat italiana, galiciana, catalana, napoletana, portugheza, rusa, croata si poloneza si imi fac planuri de calatorie in America Latina.\r\n* Mi-am facut acest profil doar pentru ca m-a batut Cosmin la cap in repetate randuri.\r\n\r\nh2. Povesti\r\n\r\n* Am primit primul meu calculator, un HP Vectra Pentium I @ 100 Mhz, 16 MB RAM, 611 MB HDD scos din uz, in anul 2001. Inca functioneaza la parametri optimi cu ajutorul sistemului de operare Slackware Linux 12.\r\n* Parintii mi-au cumparat primul calculator nou la inceputul clasei a IX-a. Primele luni a rulat intensiv jocul Return to Castle Wolfenstein si programul mIRC, dupa orele 22:00, pe Xnet (\"internetul la puterea X\").\r\n* Tot in clasa a IX-a au inceput sa ma intereseze concursurile de informatica. In ciuda pregatirii pe cont propriu, nu am reusit sa trec de faza pe sector. :-) Lucrurile s-au schimbat multumita orelor de sambata tinute de Rodica Pintea la Liceul Grigore Moisil, unde i-am cunoscut pe DitzoneC, azotlichid si altii... La recomandarea lui azotlichid, mi-am cumparat cartile \"Introducere in algoritmi\" si \"Arta programarii calculatoarelor\". Ii multumesc pentru sfat.\r\n* Modul in care interactionez cu calculatorul a fost schimbat de renuntarea la Xnet (abonament la Astral) si cumpararea numarului special al revistei Chip despre Fedora Core 1. Cel mai util program pe care mi-l puteam imagina se numea Kazaa. O adevarata colectie muzicala era pe punctul de a incepe.\r\n* In clasa a X-a m-am straduit din greu sa ajung in prima pagina a clasamentului celui mai smecher site de info... infoarena.\r\n* Tot in clasa a X-a m-am calificat la Olimpiada Nationala de Informatica si am obtinut 60/600 puncte. Acolo l-am cunoscut pe domino. DitzoneC a fost foarte mirat de faptul ca nu auzisem de Fornetti. A fost la fel de mirat cand i-am spus ca la problema lui Mars nu trebuiau numere mari. :-)\r\n* Un an mai tarziu m-am calificat pentru prima oara in lotul national de informatica. In prima zi de baraj, m-am prins de singura problema pe care am rezolvat-o cand mai erau 3 minute din concurs. In a doua zi de baraj, am salvat in ultimul moment pe partitia pe care trebuia de fapt sa salvam. Cele 30 de puncte au fost decisive pentru calificare. In anul acela am cunoscut noi membri ai comunitatii infoarena: Zeus, danielp, andreitheo...\r\n\r\nh2. Legaturi:\r\n\r\n\"www.fcsteaua.ro\":http://www.fcsteaua.ro\r\n\"www.licsfsava.ro\":http://www.licsfsava.ro\r\n\"www.maidenfans.com\":http://www.maidenfans.com\r\n\"www.linux360.ro\":http://www.linux360.ro\r\n\"www.slackware.com\":http://www.slackware.com\r\n\"www.slashdot.org\":http://www.slashdot.org\r\n\"fmi.unibuc.ro\":http://fmi.unibuc.ro\r\n\r\nh2. Prieteni infoarena:\r\n\r\n(scuze celor pe care i-am uitat)\r\n\r\n* == User(user=\"domino\" type=\"tiny\") ==\r\n* == User(user=\"DitzoneC\" type=\"tiny\") ==\r\n* == User(user=\"bogdan2412\" type=\"tiny\") ==\r\n* == User(user=\"pauldb\" type=\"tiny\") ==\r\n* == User(user=\"astronomy\" type=\"tiny\") ==\r\n* == User(user=\"wefgef\" type=\"tiny\") ==\r\n* == User(user=\"gcosmin\" type=\"tiny\") ==\r\n* == User(user=\"filipb\" type=\"tiny\") ==\r\n* == User(user=\"azotlichid\" type=\"tiny\") ==\r\n* == User(user=\"andreitheo87\" type=\"tiny\") ==\r\n* == User(user=\"Prostu\" type=\"tiny\") ==\r\n* == User(user=\"Zeus\" type=\"tiny\") ==\r\n* == User(user=\"icg\" type=\"tiny\") ==\r\n* == User(user=\"Adriana_S\" type=\"tiny\") ==\r\n* == User(user=\"danielp\" type=\"tiny\") ==\r\n* == User(user=\"cimi\" type=\"tiny\") ==\r\n* == User(user=\"wickedman\" type=\"tiny\") ==\r\n* == User(user=\"georgiana\" type=\"tiny\") ==\r\n* == User(user=\"rss1987\" type=\"tiny\") ==\r\n* == User(user=\"mugurelionut\" type=\"tiny\") ==\r\n* == User(user=\"marius135\" type=\"tiny\") ==\r\n* == User(user=\"Cosmin\" type=\"tiny\") ==\r\n* == User(user=\"efer\" type=\"tiny\") ==\r\n* == User(user=\"svalentin\" type=\"tiny\") ==\r\n* == User(user=\"fluffy\" type=\"tiny\") ==\r\n* == User(user=\"raduzer\" type=\"tiny\") ==\r\n* == User(user=\"ira\" type=\"tiny\") ==\r\n* == User(user=\"dany\" type=\"tiny\") ==\r\n* == User(user=\"adal\" type=\"tiny\") ==\r\n* == User(user=\"druid\" type=\"tiny\") ==\r\n* == User(user=\"cyber\" type=\"tiny\") ==\r\n* == User(user=\"lexx\" type=\"tiny\") ==\r\n* == User(user=\"adona\" type=\"tiny\") ==',66,'protected',NULL,NULL),('summer-challenge-2007/solutii/runda-3','Solutii Summer Challenge 2007, Runda 3','2007-08-26 17:46:55','2008-11-16 12:10:54','h1. Solutii Runda 3\r\n\r\nh2. \'Ndap\':problema/ndap\r\n\r\nPentru fiecare submultime $V\'$ a lui $V$, notam cu $E\'$ multimea muchiilor care au ambele capete in $V\'$, cu $NeConex[V\']$ numarul subgrafurilor neconexe ale lui $V\'$, iar cu $Conex[V\']$ numarul subgrafurilor conexe ale lui $V\'$. Se cunoaste faptul ca numarul total al subgrafurilor unui graf este egal cu $2^|E|^$, de aici rezultand egalitatea $Conex[V\']$ = $2^|E\'|^ - NeConex[V\']$. Pentru fiecare sumbultime $V\'$, vom incerca sa calculam {$NeConex[V\']$}. Gasim un nod oarecare $X$ din $V\'$. Pentru ca un subgraf al lui $V\'$ sa fie neconex, componenta conexa din care face parte nodul $X$ trebuie sa fie diferita de $V\'$. Vom genera toate submultimile $V$~$1$~ ale lui $V\'$ din care face parte $X$ $(V$~$1$~ != $V\'$). Consideram ca multimea $V$~$1$~ reprezinta componenta conexa din care face parte nodul $X$. Numarul de subgrafuri ale lui $V\'$ avand fixata multimea $V$~$1$~ este egal cu produsul dintre numarul de subgrafuri conexe ale lui $V$~$1$~ si numarul total de subgrafuri ale lui $V$~$2$~ = $V\'-V$~$1$~. Astfel, relatia de recurenta devine <tex> NeConex[V\'] = \\displaystyle\\sum_{V_{1} \\subset V\'} Conex[V_{1}] * 2^{|E_{2}|} </tex>. Rezultatul il vom gasi in $Conex[V]$.\r\n\r\n\r\nh2. \'Alinuta\':problema/alinuta\r\n\r\nProblema este o generalizare a cazului cand $K$ este egal mereu cu $0$ (problema \'pietre\':problema/pietre). In cazul cand $K$ este $0$ stim ca exista anumite perechi $(a, b)$ de pietre care sunt pierzatoare. Primele perechi de acest gen sunt : $(1, 2)$, $(3, 5)$, $(4, 7)$, $(6, 10)$. Puteti sa verificati ca pentru aceste configuratii initiale primul jucator este pierzator orice ar face. Aceste perechi se pot genera dupa cateva observatii simple:\r\n\r\n* diferenta intre termeni creste intodeauna cu $1$ ({$2 - 1 = 1$}; $3 - 5 = 2$; $7 - 4 = 3$; $6 - 10 = 4$)\r\n* primul numar din fiecare pereche este cel mai mic numar natural strict pozitiv nefolosit inca in perechile anterioare ( $() -> 1$; $(1, 2) -> 3$; $(1, 2, 3, 5) -> 4$; $(1, 2, 3, 5, 4, 7) -> 6$).\r\n\r\nPe cazul general unde $K$ poate fi oricat ceea ce se schimba este diferenta intre termeni care creste cu $K + 1$ in loc de $1$ (primul subpunct) (cand $K$ este $0$ se verifica);\r\nTot ce ramane de facut este ca la inceput sa precalculam toate perechile $(a, b)$ pierzatoare pentru $K$-ul dat si sa vedem dupa aceea daca o anumita pereche data in fisierul de intrare se afla sau nu printre cele pierzatoare. Cum $A$, $B$ <= $100 000$ este clar ca pot fi cel mult $100 000$ de perechi. Ceea ce ne duce la o complexitate de $O(B)$ precalculare si apoi $O(1)$ pe query (pentru fiecare numar $x$ tinem minte perechea lui $y$ astfel incat $(x, y)$ este pierzator sau $0$ in caz ca nu exista acest $y$).\r\n\r\nIn general pentru problemele de acest tip in timpul concursului se observa regula cu ajutorul unei solutii brute force. In cazul acestei probleme solutia brute force presupunea calcularea unei matrici Win[x][y] = 1 daca (x, y) este castigatoare pentru primul jucator, 0 altfel.\r\n\r\nTotusi, pentru cei care vor sa demonstreze ca algoritmul de mai sus functioneaza iata cateva observatii care va pot ajuta:\r\n\r\n* $(a, b)$ si $(b, a)$ sunt echivalente\r\n* daca $(a, b)$ este configuratie pierzatoare atunci orice $(a, c)$ cu $c > b$ este configuratie castigatoare; de aici rezulta imediat ca pentru un $a$ fixat avem un singur $b$ pentru care $(a, b)$ e pierzatoare restul configuratiilor de forma $(a, x)$ fiind castigatoare\r\n\r\nh2. \'Dame 2\':problema/dame2\r\n\r\nProblema se rezolva prin metoda backtracking. Se iau toate posibilitatile de a aseza damele pe tabla de sah astfel incat oricare doua dame sa nu se atace. Ca sa intre in timp trebuiesc facute unele optimizari cum ar fi:\r\n\r\n* atunci cand punem o dama marcam linia, coloana, prima diagonala si a doua dioagonala pe care este dama ca fiind ocupate pentru ca mai tarziu sa stim ca pe acestea nu putem pune alta dama (optimizam verificarea pentru a vedea daca putem sa punem o dama pe o anumita pozitie sau nu)\r\n* tinem minte numarul minim de dame necesar gasit pana acum si in backtracking daca cumva trecem de acel numar cand cautam o solutie nu mai continuam pentru ca nu are sens (sigur am gasit o solutie cu numar de dame mai mic inainte) (initial acest numar este infinit)\r\n* dupa ce am gasit o solutie cu un anumit numar de dame verificam daca fiecare patratel este atacat de o dama in $O(1)$ folosindu-ne de informatiile stiute de la primul subpunct, si anume: un patratel $(x, y)$ este atacat de o dama daca cel putin una din linia, coloana, prima diagonala, a doua diagonala sunt marcate ca fiind o dama pe ele.\r\n',2028,'public',NULL,NULL),('preoni-2006/finala/solutii','Solutii preONI 2006, Runda finala','2006-03-26 00:00:00','2007-12-14 23:14:33','h1. Solutii preONI 2006, Runda finala\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa Infoarena_)\r\n\r\nSi iata-ne ajunsi in situatia de a trage concluziile dupa tot ce a insemnat preONI 2006. Toata comisia infoArena merita felicitata pentru organizarea si efortul depus de-a lungul campaniei. Inca odata multimim domnului profesor Onea pentru organizarea \"fara cusur\" :).\r\n\r\nFinala a fost ... \"Super. Super\", \"Super tare\", \"mda...a mers\" o spun concurentii. A fost grozav, intr-adevar, si ne-a facut mare placere sa va vedem prezenti intr-un numar atat de mare si veniti atat de departe. Va multumim pentru participare si speram ca ati petrecut un week-end pe cinste cu noi la Focsani.\r\n\r\nDupa cele patru runde online de concurs cu adevarat dure, cei 29 de concurenti si-au facut aparatia, de prin toate ungherele tarii, pe terenul de lupta. Desi in prima seara, la deschiderea ne-scortoasa si informala, concurentii isi zambeau sincer si fara vreun resentiment, in aer plutea \"emotia, tracul, tensiunea, stress-ul\".. Calmul dinaintea furtunii.. Venea marea confruntarea, batalia bataliilor, in urma careia trebuiau alesi castigatorii preONI 2006.\r\n\r\nConcursul s-a dovedit a fi o adevarata proba de foc, o batalie cu fum de creiere din plin si cu multe iesiri la toaleta (vezi \"Cronica\":preoni-2006/finala/cronica). Problemele, la limita imposibilului. Comisia a nascocit cele mai nastrusnice provocari pentru o finala in care participau concurenti adevarati, gata sa dea peste cap toate topurile Olimpiadelor ce vor voni. Muschi incordati, \"trac, tensiune, stress\". La sfarsit, punctaje reflectand truda demna de admirat a unor campioni alergand pe ultima suta de metri a unei curse in 5 acte. Castigatorii au fost sa fie, de acesta data, Cosmin Gheorghe la clasa a IX a, Simion Alexandru la clasa a X a si Marin Radu la clasele XI-XII. Ii felicitam pe ei si, in aceeasi masura, pe toti participantii care, desi au ratat premiile, cu siguranta au castigat prieteni noi.\r\n\r\nSa trecem la analiza problemelor cu care cei 29 concurenti nazdravani au avut de-a face in cele 5 ore ale finalei. Orice sugestie sau corectie privind articolul, solutiile problemelor v-o puteti exprima pe \"forum\":forum.\r\n\r\nh2. DivK\r\n\r\nh3. (problema usoara clasa a IX-a, problema usoara clasa a X-a)\r\n\r\nExista solutii evidente $O(N * (A-B))$ si $O(N * K)$ care obtin punctaje partiale si asupra carora nu se va insista in acest articol. Solutia care obtine insa $100$ de puncte este $O(N)$ si nu este greu de gasit, bazandu-se pe cateva observatii. Sa notam cu $S{~i~}$ suma primelor $i$ numere din sir. Pentru ca subsecventa intre pozitiile $i$ si $j$ sa aiba suma elementelor divizibila cu $K$, atunci $S{~j~}-S{~i-1~}$ trebuie sa fie divizibil cu $K$, sau altfel spus, $S{~i-1~}$ si $S{~j~}$ sa aiba acelasi rest la impartirea cu $K$. Daca stim sa aflam raspunsul problemei pentru subsecvente de lungime maxim $L$ si minim {$1$}, aplicand de doua ori algoritmul pentru $B$ si pentru $A-1$ si scazand cele doua valori obtinute vom obtine numarul de subsecvente cu proprietatea ceruta intre $A$ si $B$ inclusiv. Pentru a afla raspunsul pentru lungimea maxim $L$ procedam astfel: introducem in lista $LISTA{~r~}$ alocata dinamic pozitiile $i$ pentru care $S{~i~}$ da restul $r$ la impartirea cu $K$, in ordine crescatoare. Pentru fiecare rest de la $0$ la $K-1$ parcurgem lista corespunzatoarea, si, daca ne aflam pe un element cu valoarea $p2$ si elementul cel mai din stanga din lista curenta are valoarea $p1$ astfel incat $p2-p1 &le; L$, atunci cand avansam in lista nu mai este necesar sa incepem iterarea listei de la inceput pentru aflarea valorii cea mai din stanga, fiind suficient sa reluam cautarea din dreptul valorii $p1$. Astfel complexitatea algoritmului pentru o lista este $O(LUNGIME)$, unde $LUNGIME$ este lungimea unei liste, deci complexitatea intregului algoritm va fi $O(N)$, pentru ca lungimea tuturor listelor este $N$.\r\nO alta solutie de aceeasi complexitate dar mai rapida este urmatoarea: daca notam cu @v[r]@ de cate ori apare restul $r$ in numerele $S{~i-B~}...S{~i-A+1~}$ pentru pasul curent $i$, atunci la pasul $i+1$ este suficient sa decrementam $v[S{~i-B+1~}%K]$ si sa incrementam $v[S{~i-A+2~}%K]$. La fiecare pas $i$ vom aduna la solutia finala numarul $v[S{~i~}%K]$.\r\n\r\nh2. Lupul Urias si Rau\r\n\r\nh3. (problema medie clasa a IX-a)\r\n\r\nSe construieste vectorul $T{~i~}$ care retine timpul maxim la care oaia $i$ poate fi aleasa si notam $T_max$ valoarea maxima din {$T$}.\r\n\r\nO abordare care insa nu conduce la punctaj maxim este programarea dinamica, calculand $sol{~i,j~}$ cantitatea maxima de lana care se poate alege cu primele $i$ oi pana la momentul {$j$}. Raspunsul se va gasi in {$sol{~n,T_max~}$}. Complexitatea este $O(n^2^)$ si ar obtine aproximativ $50-60$ de puncte.\r\n\r\nO rezolvare ce aduce 100 de puncte se bazeaza pe metoda greedy. Pentru fiecare valoare $j$ de la $T_max$ la $1$ se adauga intr-o multime toate cantitatile de lana $A{~i~}$ pentru oile cu {$T{~i~}=j$}, apoi se extrage valoarea maxima care se adauga la solutie, restul valorilor pastrandu-se in multime pentru pasul urmator. Atentie, se va extrage valoarea maxima chiar daca la acest pas nu s-au introdus valori noi in multime. Pentru a implementa eficient aceste operatii ne vom folosi un heap care suporta operatiile de extragere maxim si adaugare element in {$O(log n)$}. Complexitatea finala a algoritmului va fi de {$O(n log n)$}. Demonstratia intuitiva a faptului ca algoritmul conduce la solutie optima este ca la fiecare pas $j$ se alege valoarea maxima dintre cele care nu vor mai putea fi alese la pasul {$j+1$}.\r\n\r\nO alta solutie tot greedy a problemei este sortarea descrescatoare dupa cantitatile de lana. Pentru fiecare valoare apoi se vede cel mai mare timp mai mic sau egal cu {$T{~i~}$} si la care nu a mai fost aleasa nici o alta oaie. Daca exista un astfel de timp se adauga valoare respectiva la solutie. Acest lucru se poate realiza cu o cautare binara a acestui timp. O alternativa la acest lucru ar fi folosirea multimilor disjuncte. Initial se considera fiecare moment de timp o multime. Notam $X$ = minimul din multimea care il contine pe {$T{~i~}$}. Daca alegem $A{~i~}$ pentru a-l adauga la solutie se va reuni multimea care il contine pe $X$ cu multimea care il contine pe {$X-1$}. Aceasta rezolvare insa este considerata peste nivelul mediu al clasei a 9-a.\r\n\r\nh2. Overlap\r\n\r\nh3. (problema grea clasa a IX-a)\r\n\r\nObservam ca exista doar $4$ rotatii posibile ale planului, facand abstractie de translatii. Daca $CMAX$ este coordonata maxima, atunci punctul ({$i, j$}) se transforma in ({$CMAX-j, i$}), iar dupa $4$ aplicari ale acestei transformari se ajunge din nou la punctul initial. Asadar, vom incerca pe rand fiecare dintre aceste posibilitati. Avand fixata o rotatie, stim ca punctul $1$ se transforma intr-un alt punct $i$ ({$i > 1$}), sau ca un punct $i$ se transforma in el. Cel de-al doilea caz este redundant, deoarece aplicand transformarea {$P{~i~} -> P{~1~}$}, vom lua in considerare si transformarea inversa. De exemplu, daca rotind planul cu $k*90$ de grade si translatandu-l cu $shift_X$ si $shift_y$ obtinem $P{~i~}$ din {$P{~j~}$}, atunci rotind planul cu $(4-k)*90$ grade si translatandu-l cu {$-shift_x$}, {$-shift_y$} vom obtine $P{~j~}$ din {$P{~i~}$}.\r\nOdata fixata rotatia pe care o consideram (inclusiv cea de $0$ grade), presupunem pe rand pentru fiecare punct $i > 1$ ca $P{~1~}$ se transforma in {$P{~i~}$}, si verificam daca aceasta presupunere conduce la o solutie valida. Presupunerea facuta stabileste in mod unic care este translatia efectuata. Retinem un vector $P{~i~}$ = punctul in care se transforma al {$i$}-lea punct dupa aplicarea rotatiei fixate si a translatiei determinate, sau $-1$ daca punctul transformat nu se regaseste printre cele initiale. Pentru a realiza in mod eficient aceasta operatie, la inceputul algoritmului punctele se sorteaza cu o functie de comparare oarecare si la fiecare pas punctul dorit se cauta binar in acest vector, in {$O(log N)$}. Eventual s-ar putea folosi un tabel de dispersie, insa consideram ca aceasta structura de date este prea complicata pentru nivelul clasei a 9-a si nu era necesara pentru obtinerea punctajului maxim.\r\n\r\nAvand vectorul {$P$}, va exista o structura de lanturi si cicluri rezultata in urma aplicarii repetate {$P[P[..P[i]]]$} asupra diverselor puncte. Se poate demonstra usor ca exista solutie daca si numai daca toate lanturile si toate ciclurile au lungime para; in acest caz solutia se poate obtine etichetand alternativ punctele consecutive dintr-un lant sau ciclu.\r\nComplexitatea algoritmului este $O(N^2^ * log N)$ pe cazul defavorabil folosind cautari binare pentru gasirea punctelor, sau $O(N^2^)$ pe cazul mediu folosind un hash (tabel de dispersie).\r\n\r\nh2. Iv\r\n\r\nh3. (problema medie clasa a X-a)\r\n\r\nSolutia simpla, calculata prin metoda programarii dinamice, se bazeaza pe mentinerea starilor ce asigura obtinerea solutiilor distincte. Astfel interclasarea celor doua siruri se va face in acelasi timp atat din stanga cat si din dreapta pentru a garanta pastrarea proprietatii de palindrom. Notand cele doua siruri $A$ si {$B$}, pastram $4$ indici: {$p{~1~}$}, {$p{~2~}$}, {$q{~1~}$}, {$q{~2~}$}, reprezentand pozitia ultimului caracter luat din stanga sirului {$A$}, ultimului luat din dreapta sirului {$A$}, ultimului din stanga sirului {$B$}, respectiv ultimului luat din dreapta sirului {$B$}.\r\n\r\nSe iau 4 cazuri de tranzitie intre stari:\r\n\r\n* ({$p{~1~}, q{~1~}, p{~2~}, q{~2~}$}) => ({$p{~1~}+1, q{~1~}-1, p{~2~}, q{~2~}$}), daca {$A[p{~1~} + 1] = A[q{~1~} - 1]$}\r\n* ({$p{~1~}, q{~1~}, p{~2~}, q{~2~}$}) => ({$p{~1~}+1, q{~1~}, p{~2~}, q{~2~}-1$}), daca {$A[p{~1~} + 1] = B[q{~2~} - 1]$}\r\n* ({$p{~1~}, q{~1~}, p{~2~}, q{~2~}$}) => ({$p{~1~}, q{~1~}-1, p{~2~}+1, q{~2~}$}), daca {$B[p{~2~} + 1] = A[q{~1~} - 1]$}\r\n* ({$p{~1~}, q{~1~}, p{~2~}, q{~2~}$}) => ({$p{~1~}, q{~1~}, p{~2~}+1, q{~2~}-1$}), daca {$B[p{~2~} + 1] = B[q{~2~} - 1]$}\r\n\r\nAceasta ne duce la un algoritm de complexitate {$O(|A|^2^ * |B|^2^)$}, ce ar fi asigurat obtinerea a $60%$ din punctaj. Simpla observare a faptului ca este suficienta pastrarea a numai trei indici, in loc de patru, pentru a pastra o stare completa (deoarece {$p{~1~} + p{~2~} = |A| - q{~1~} + 1 + |B| - q{~2~} + 1$}), duce la un algoritm de complexitate $O(|A|^2^ * |B|)$ ce ar fi obtinut punctaj maxim.\r\n\r\nh2. Robotei\r\n\r\nh3. (problema grea clasa a X-a)\r\n\r\nPentru a afla de cate ori trece un robotel prin pozitia (X Y) avem nevoie de urmatoarele informatii:\r\n\r\n# Cate mutari efectuam daca pornim din pozitia ({$X Y$}) si ajungem tot in ({$X Y$}) - lungimea ciclului care cuprinde pozitia ({$X Y$}). Daca pozitia ({$X Y$}) nu se afla pe un ciclu atunci lucrurile se simplifica (acesta este un caz special care se trateaza separat).\r\n# Cate mutari efectueaza fiecare robot pana ajunge in ({$X Y$}). Desigur, pot exista si roboti care nu ajung niciodata in ({$X Y$}).\r\n\r\nAflarea lungimii ciclului (punctul 1.) se face usor, pornind din pozitia ({$X Y$}), efectuand mutari pana se ajunge din nou in pozitia ({$X Y$}). Daca numarul de mutari depaseste $modX*modY$ si nu am atins inca pozitia ({$X, Y$}), atunci aceasta nu se afla pe un ciclu. Complexitatea acestui pas va fi {$O(modX * modY)$}.\r\nPentru a afla, pentru fiecare robot, numarul de mutari pentru a ajunge in ({$X Y$}), putem asocia un graf caroiajului, fiecarei celule din cele $N*N$ corespunzandu-i un nod in graful orientat construit. Pentru fiecare celula ({$i j$}) vom adauga o muchie orientata in acest graf intre nodul corespunzator celulei ({$i j$}) si nodul corespunzator celulei ( {$[i*i + offsetX] modulo modX , [j*j + offsetY] modulo modY$}). Fiecare nod din acest graf va avea gradul de iesire {$1$}, in consecinta, vor fi atatea muchii cate noduri sunt (adica {$N*N$}).\r\nPornind din pozitia ({$X Y$}), efectuam o parcurgere BFS a grafului INVERSAT si vom afla, pentru fiecare nod, care este numarul de mutari pe care trebuie sa le efectuam, pornind din celula corespunzatoare nodului, pentru a ajunge in pozitia ({$X Y$}). Nodurile care nu pot fi vizitate in aceasta parcurgere corespund unor celule din care nu se poate atinge pozitia ({$X Y$}).\r\nComplexitatea acestui algoritm este $O(N*N)$ si obtine $70%$ din punctaj. Pentru a obtine punctaj maxim, observam ca, dupa prima mutare toti roboteii se afla in caroiajul de dimensiuni ({$modX modY$}), si aplicam acelasi algoritm ignorand pozitiile care sunt in afara acestuia. Observatia precedenta ne permite sa afirmam ca daca un robot pleaca din pozitia ({$i, j$}) e ca si cum ar pleca, imaginar, din pozitia ({$i modX, j modY$}). Putem determina cati roboti pleaca (considerandu-i si pe cei care pleaca imaginar) dintr-o celula ({$i j$}) a caroiajului redus, determinand cate solutii au ecuatiile $x {@%@} modX = i$ si $y {@%@} modY = j$ ({$x$} si $y$ necunoscute) in intervalul [{$0..N-1$}].\r\n\r\nh2. PScNv\r\n\r\nh3. (problema simpla clasele XI-XII)\r\n\r\nAceasta problema a fost aleasa asa cum spune si textul pentru faptul ca sunt mai multe abordari ce rezolva problema. O prima abordare ar fi pentru un $k$ fixat sa vedem daca putem ajunge de la nodul start pana la nodul destinatie folosind doar muchii cu cost mai mic sau egal cu {$k$}. Verificarea acestui fapt o facem folosind o cautare in latime. Cat timp nu putem ajunge de la nodul start la nodul destinatie incrementam pe {$k$} si apoi aplicam o cautare in latime. Astfel aflam valoarea {$k$} minima ceruta in problema. Complexitatea acestui algoritm este {$O(kmax (n + m))$}. Daca notam $kmin$ valoarea ceruta in problema, atunci daca fixam un $k$ si nodul destinatie este accesibil din nodul start folosind doar muchii de pondere mai mica sau egale cu $k$ atunci este evident ca {$kmin &le; k$}, iar daca nodul destinatie nu este accesibil atunci {$kmin > k$}. Pe baza acestei observatii putem dezvolta un algoritm ce cauta binar valoarea $kmin$ ce are complexitatea {$O(log kmax (n + m))$}. O alta abordare se bazeaza pe o modificare usoara a algoritmului Dijkstra de drum minim, in care in loc sa pastram drumuri minime, pastram drumuri pt care muchia maxima are valoare cat mai mica. O implementare cu heapuri a acestui algoritm are complexitate {$O(m log n)$}. De asemenea algoritmul Bellman Ford poate fi modificat usor pentru a ne rezolva problema, chiar daca acest algoritm are complexitatea $O(n*m)$ in practica implementarea lui ce foloseste o lista se comporta cu mult mai bine. Ultimele trei rezolvari ar fi luat in jur de $70$ de puncte.\r\n\r\nSolutia oficiala se bazeaza tot pe o varianta a algoritmului Dijkstra, dar care in loc sa foloseasca un heap pentru a determina nodul $i$ inca neexpandat cu drumul de la sursa la el de cost minim, foloseste niste liste. Aceasta abordare este identica cu cea din problema \"Car\":http://infoarena.ro/task/car, si comisia se astepta ca multi concurenti sa rezolve perfect problema, asteptare infirmata de rezultatele din concurs. Cum ponderile muchiilor sunt numere de la $1$ pana la $1000$ inseamna ca in $d[i]$ oricare ar fi nodul $i$ va fi intotdeauna mai mica sau egala cu {$1000$}. Vom folosi astfel $1000$ de liste dublu inlantuite. In lista $i$ vom tine minte nodurile $x$ pentru care {$d[x] = i$}. Cand $d[x]$ se micsoreaza inseram pe $x$ intr-o lista mai mica, dar pentru a il sterge din lista veche vom folosi \"lazy deletion\". Adica atunci cand ajungem la lista $i$ si vrem sa expandam nodul $x$ verificam mai intai daca {$d[x] = i$}, daca nu inseamna ca $d[x] < i$ si nodul $x$ a fost expandat mai devreme, deci putem sa il ignoram. Acest algoritm are complexitate {$O(kmax + n + m)$}.\r\n\r\nComisia a mai discutat posibilitatea de a propune problema folosind un graf neorientat. Atunci o solutie similara algoritmului Kruskal ar fi avut complexitate aproape de cea optima. Am fi putut folosi un radix sort pentru a sorta muchiile, iar apoi sa adaugam muchii in ordine crescatoare la graf pana cand nodul start si nodul destinatie ar fi fost in aceiasi componenta conexa. Pentru a gestiona componentele conexe am fi folosit structuri de multimi disjuncte. Aceasta solutie ar fi avut complexitatea {$O(kmax + m log*n)$}.\r\n\r\nh2. Arbore\r\n\r\nh3. (problema medie clasele XI-XII)\r\n\r\nO prima idee de rezolvare a problemei are o complexitate de $O(1)$ la operatiile de tip update si $O(n)$ la operatiile de tip query. Cand intalnim o operatie de tip 1 este necesar sa folosim un vector $S[1..N]$ in care marcam aceste modificari. Astfel, adunand valoarea $s$ la elementul $S[p]$ vom observa ca suma pe care a primit-o un nod $X$ este de fapt suma valorilor $S[nod]$ unde $nod$ reprezinta indicele nodurilor din drumul lui $X$ pana la radacina arborelui. Deci, pentru o operatie de tipul 1 vom face o singura adunare, iar pentru o operatie de tipul 2 vom efectua o parcurgere in adancime pentru a cauta suma ceruta. Aceasta solutie obtine in jur de $30$ de puncte.\r\n\r\nO alta abordare ar fi reducerea problemei la nivel de vector. Am putea renumerota nodurile arborelui astfel incat subarborele fiecarui nod sa aiba id-uri consecutive. Acest lucru se poate face cu o parcurgere in adancime. Acum trebuie sa efectuam adunari pe intervale compacte de pe un vector, si trebuie sa gasim un element din vector ce are o anumita suma. Acest lucru se poate face, de asemenea in $O(1)$ pentru update si $O(N)$ pentru query usor. Aceasta solutie este mai rapida decat prima, deoarece nu foloseste apeluri recursive ale functiilor si efectueaza un numar mic de operatii. Asa s-ar fi luat $50-60$ de puncte In cazul in care problema s-ar fi redus la nivel de vector dar atat update-ul cat si querry-ul s-ar fi efectuat in $O(n)$ s-ar fi obtinut $30-40$ de puncte..\r\n\r\nSolutia care ar fi obtinut punctajul maxim se bazeaza pe reducerea problemei la nivel de vector, descrisa in paragraful precedent. Fie {$SEC = sqrt(N)$}. Putem imparti vectorul de lungime $N$ in $SEC$ secvente de lungime {$SEC$}. Vom mai folosi 3 vectori $A[1..N]$ reprezentand sumele pe fiecare element ce au fost adunate la inceputul secventelor de lungime {$SEC$}, $C[1..SEC]$ reprezinta sumele ce s-au adunat pe intregile secvente, iar $P[1..SEC][1..1 000 000]$ este o matrice binara unde $P[i][j] = 1$ daca exista un element din secventa $i$ astfel incat {$A[element] = j$}. Aceasta idee ne ajuta sa rezolvam problema intr-o complexitate de $O(sqrt(n))$ atat pentru query cat si pentru update. Pentru ca memoria folosita sa fie rezonabila implementarea matricii $P$ se face pe biti.\r\n\r\nh2. Pedefe\r\n\r\nh3. (problema grea clasele XI-XII)\r\n\r\nProblema cere determinarea numarului de subsiruri comune crescatoare al sirurilor $S1$ si $S2$ , care-l contin pe $S3$ ca subsir. Pentru a rezolva vom folosi metoda programarii dinamice. Se va construi un tabel $A$ cu semnificatia:\r\n$A[k,i,j]$ = cate subsiruri comune crescatoare exista tinand cont doar de primele $i$ valori ale lui {$S1$}, primele $j$ valori ale lui {$S2$}, si care sa contina ca subsir primele $k$ caractere din {$S3$}, iar ultima valoare din aceste subsiruri sa fie {$S1[i]$}. Valorile din tablou se vor calcula doar atunci cand {$S1[i] = S2[j]$}, in rest valorile vor fi {$0$}. In implementare, se vor pastra doar ultimele doua linii din tabloul {$A$}, {$A[k-1]$} si {$A[k]$}.\r\n\r\nIn continuare se vor prezenta mai multe implementari bazate pe aceasta idee cu diferite complexitati si care aduc punctaje diferite.\r\n\r\nh3. Solutia O(N^2^*M^2^*P) - 30 puncte\r\n\r\nPentru a calcula {$A[k, i, j]$} ne vom uita fie in {$A[k-1]$} daca {$S1[i] = S2[j] = S3[k]$}, fie in {$A[k]$} ({$S1[i] = S2[j]$}, {$S1[i] != S3[k]$}). Se vor aduna valorile {$A[k (sau k-1), p, q]$} cu {$p<i$}, {$q<j$} si {$S1[p] &le; S1[i]$}.\r\n\r\nh3. Solutia O(N*M^2^*P) - 50 puncte\r\n\r\nSe porneste de la solutia anterioara si se observa faptul ca pentru fiecare $q$ care se considera se poate preprocesa suma {$A[k (sau k-1), p, q]$} pentru $p < i$ intr-un tablou {$S$}. Dupa ce se calculeaza {$A[k, i, j]$} considerand doar acele $q$ pentru care {$S2[q] &le; S2[j]$}, se actualizeza {$S[k, j]$}.\r\n\r\nh3. Solutia O(N*M*P*Sigma) - 75 puncte\r\n\r\nIn cazul cel mai devaforabil numarul de valori distincte din siruri este {$min(N, M)$}, dar se garanteaza in enunt ca $Sigma$ (numarul de valori distincte) este $&le; 20$ pentru inca $25%$ din teste. Pornind de la solutia anterioara, se observa ca , parcurgand {$j$}-ul de la $1$ la {$M$}, nu este necesar sa consideram de fiecare data toate valorile {$q < j$}, aceste informatii putand fi actualizate in {$O(1)$}. Deoarece trebuie sa numaram doar valorile cu {$S2[q] &le; S2[j]$}, se pastreaza intr-un vector {$V[x]$} , suma {$q$}-urilor {$< j$} , cu {$S2[q] &le; x$}. Calculul lui {$A[k,i,j]$} se face in {$O(Sigma)$}, iar dupa aceasta se actualizeaza vectorul $V$ in {$O(1)$}.\r\n\r\nh3. Solutia O(N*M*P*lgSigma) - 100 puncte\r\n\r\nSolutia de $100$ este asemantoare cu solutia de $75$ de puncte, singura diferenta fiind folosirea unui arbore indexat binar pentru a face in $O(lg Sigma)$ operatiile desccrise mai sus.\r\n',1,'public',NULL,NULL),('autumn-warmup-2007/runda-2','Autumn Warm Up 2007','2007-09-20 13:11:23','2007-10-04 17:45:21','h1. Autumn Warm Up 2007\r\n\r\n(htabs)* \'Despre concurs\':autumn-warmup-2007/\r\n* \'Runda 1\':autumn-warmup-2007/runda-1\r\n*(active) \'Runda 2\':autumn-warmup-2007/runda-2\r\n* \'Runda 3\':autumn-warmup-2007/runda-3\r\n* \'Clasament\':autumn-warmup-2007/clasament\r\n\r\nRunda se va desfasura Duminica, 23 septembrie, la ora {*10^00^*} si va dura *5h*. Participantii vor avea de rezolvat 4 probleme de natura algoritmica. Evaluarea se va face la sfarsitul concursului.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"autumn2007-runda2\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"autumn2007-runda2\" score=\"1\")==\r\n\r\nSolutiile le gasiti \'aici\':autumn-warmup-2007/solutii/runda-2\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 2\':autumn-warmup-2007/clasament/runda-2\r\n\r\nh2. Organizatori\r\n\r\n* ==User(user=\"domino\" type=\"tiny\")==\r\n* ==User(user=\"svalentin\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"devilkind\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"mugurelionut\" type=\"tiny\")==',2092,'public',NULL,NULL),('blog/summer-challenge-2007/runda-1','Summer Challenge 2007, Runda 1','2007-07-29 21:58:55','2007-10-01 19:53:09','Te invitam sa participi la seria de concursuri \'Summer Challenge 2007\':summer-challenge-2007. Vom organiza 3 runde online, de cate 5h fiecare, cu probleme de dificultate variata.\r\n\r\nSummer Challenge este o ocazie buna de antrenament pentru tine (daca nu esti deja la mare :) dar si un ultim test pentru delegatia\r\nRomaniei la Olimpiada Internationala de Informatica 2007 (Croatia).\r\n\r\nAi ocazia sa concurezi cu lotul Romaniei la IOI 2007!\r\n\r\n&rarr; \'*Pagina concursului*\':summer-challenge-2007',1,'protected',NULL,NULL),('blog/summer-challenge-2007/runda-2-si-3','Summer Challenge 2007, Rundele 2 si 3','2007-08-09 09:04:49','2007-10-01 19:49:44','Rundele 2 si 3 ale concursului Summer Challenge se vor desfasura la 2 zile distanta. Mai exact:\r\n\r\n* \"Runda 2\":summer-challenge-2007/runda-2: Vineri, 10 august 2007, intre orele 10^00^ - 15^00^\r\n* \"Runda 3\":summer-challenge-2007/runda-3: Duminica, 12 august 2007, intre orele 10^00^ - 13^00^\r\n\r\nAi ocazia sa concurezi cu lotul Romaniei la IOI 2007!\r\nSucces!\r\n \r\n&rarr; \'*Pagina concursului*\':summer-challenge-2007',1,'protected',NULL,NULL),('autumn-warmup-2007/clasament','Autumn Warm Up 2007','2007-09-03 20:04:21','2007-10-04 17:45:38','h1. Autumn Warm Up 2007\r\n\r\n(htabs)* \'Despre concurs\':autumn-warmup-2007/\r\n* \'Runda 1\':autumn-warmup-2007/runda-1\r\n* \'Runda 2\':autumn-warmup-2007/runda-2\r\n* \'Runda 3\':autumn-warmup-2007/runda-3\r\n*(active) \'Clasament\':autumn-warmup-2007/clasament\r\n\r\nAcesta este clasamentul cumulat pe cele 3 runde online.\r\n\r\n== Rankings(rounds=\"autumn2007-runda1 | autumn2007-runda2 | autumn2007-runda3\") ==',2092,'public',NULL,NULL),('autumn-warmup-2007/runda-1','Autumn Warm Up 2007','2007-09-03 20:03:28','2007-10-04 17:45:05','h1. Autumn Warm Up 2007\r\n\r\n(htabs)* \'Despre concurs\':autumn-warmup-2007/\r\n*(active) \'Runda 1\':autumn-warmup-2007/runda-1\r\n* \'Runda 2\':autumn-warmup-2007/runda-2\r\n* \'Runda 3\':autumn-warmup-2007/runda-3\r\n* \'Clasament\':autumn-warmup-2007/clasament\r\n\r\nRunda se va desfasura Marti 11 septembrie, la ora {*10^00^*} si va dura *5h*. Participantii vor avea de rezolvat 4 probleme de natura algoritmica. Spre deosebire de anul trecut, evaluarea se va face la sfarsitul concursului.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"autumn2007-runda1\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"autumn2007-runda1\" score=\"1\")==\r\n\r\nSolutiile le gasiti \'aici\':autumn-warmup-2007/solutii/runda-1\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 1\':autumn-warmup-2007/clasament/runda-1\r\n\r\nh2. Organizatori\r\n\r\n* ==User(user=\"ditzonec\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"devilkind\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n* ==User(user=\"vlad_D\" type=\"tiny\")==\r\n',2092,'public',NULL,NULL),('autumn-warmup-2007/clasament/runda-2','Clasament autumn2007-runda2','2007-09-20 13:08:43','2007-10-06 20:02:56','h1. Clasament ==roundparam(round_id=\"autumn2007-runda2\" param=\"title\") ==\r\n\r\n(htabs)* \'Detalii\':autumn-warmup-2007/\r\n* \'Runda 1\':autumn-warmup-2007/runda-1\r\n*(active) \'Runda 2\':autumn-warmup-2007/runda-2\r\n* \'Runda 3\':autumn-warmup-2007/runda-3\r\n*(active) \'Clasament\':autumn-warmup-2007/clasament\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"autumn2007-runda2\")==',961,'round: autumn2007-runda2',NULL,NULL),('blog/romanii-la-disneyworld-partea-a-doua','Romanii la DisneyWorld - partea a doua','2007-12-04 18:18:14','2008-11-15 13:41:14','_Continuam seria de interviuri cu romanii ce au participat la finala concursului TopCoder Collegiate Challenge din toamna asta. Puteti citi prima parte \'aici\':blog/romanii-la-disneyworld-partea-intai . In aceasta parte Lucian Codrut Lazar ne va povesti despre concursurile de componente software si in special despre concursul de design software la care el s-a calificat in finala. Lucian are multa experienta cu aceste concursuri, a participat la 49 de competitii, a fost reviewer (membu al comisiei de corectori) la mai mult de 50 de componente, si a fost de doua ori reviewer la faza finala a concursului. In toamna asta a participat ca si concurent._\r\n\r\nh1. Lazar Codrut Lucian\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/romanii-la-disneyworld-partea-a-doua?luca.jpg! *Poti sa ne spui cate ceva despre concursul de software design? In ce consta el? Care sunt criteriile de notare, si care e partea dificila la un asemenea concurs?*\r\nIn fiecare saptamana (de obicei joi) sunt puse mai multe componente (Java sau C#) pentru care trebuie facut design (sau development) intr-o saptamana. La design se da un document cu cerinte si trebuie facuta diagrama de clase, o diagrama de use case si diagrame de secventa pentru metodele mai complexe. Diagrama de clase contine toate clasele de care e nevoie pentru a implementa cerintele, cu toate metodele si campurile folosite. Toti pasii si toate constrangerile trebuie documentate (documentatia e orientata spre developeri). Mai trebuie un document Word, cu diverse discutii: thread-safety, algoritmi, demo, ... Design-urile sunt corectate de 3 review-eri. Sunt sectiuni pentru abordarea folosita (sabloane folosite, componente reutilizate, class scope, easy-to-use) - asta e partea faina dintr-un design; sectiuni pentru documentatie - aici e mai multa munca patriotica; si sectiuni pentru modul de prezentare. Sa gandesti strucura componentei poate fi mai greu la inceput, dar asta e partea faina a concursului. Apoi intervine partea de documentatie, care ia mult timp si devine enervanta, fiindca stii ce vrei sa faca fiecare entitate sau ce sa scrii in documentul Word, doar ca trebuie sa explici complet si asta ia mult timp.\r\nLa development sunt implementate design-urile de pe locul 1. Se face unit testing si se scrie documentatie orientata utilizator.\r\n\r\n*De ce software design si nu oricare dintre celelalte sectiuni (algoritmica, software development, marathon ...)?*\r\nImi erau familiare sabloanele de proiectare si lucram la un framework pentru desenare de diagrame UML, deci stiam destul de bine UML. Sa incep la development mi-ar fi fost mai greu fiindca trebuia sa invat JUnit (sau NUnit) si parca nici nu prea am spor la implementare. La algoritmica am cam renuntat de cand am intrat la facultate, si oricum eram mult in urma ca nivel de cunostinte (plus ca tastez incet). \r\n\r\n*Cum ai recomanda cuiva sa inceapa sa participe la aceste competitii?*\r\nSa citeasca \'GoF\':http://www.google.com/search?hl=en&q=gang+of+four&btnG=Google+Search (cateva sabloane trebuie stiute: Strategy, Template Method, Abstract Factory, Observer, Adapter, Facade, Decorator). Trebuie intelese diagramele UML de care am zis mai sus. Un tutorial cred ca ajunge. Apoi intervine practica. In plus mai sunt forumuri publice, sau private pentru fiecare componenta. E bine sa intrebi orice nu e clar (despre sistem, despre componenta, despre diagrame, ...), fara frica de a parea penibil. In principiu, daca intrebi ceva cat de cat rezonabil, iti raspunde cineva repede si treci peste neclaritati.\r\n\r\n*Cum se ajunge la nivelul la care te poti califica la o faza finala pentru un asemenea concurs? Citesti carti? Proiecte facute de altii? Care e metoda de invatare?*\r\nInceputul e mai greu - asta poate e valabil la orice tip de competitie. Pe masura ce faci mai multe componente devii mai sigur pe tine, plus ca inveti pe parcurs si din greseli. E bine sa te uiti pe componentele facute de altii. Cel mai bine e sa alegi componente facute de cei cu rating mare, ca sa nu dai peste abordari dubioase, care mai mult te baga in ceata. In cateva luni ajungi aproape de potentialu propriu, si poti incerca oricand sa te califici la turnee. Doar ca trebuie mai multa munca.\r\n\r\n*Ce programe software se folosesc in software design in general si la topcoder in particular?*\r\nSe lucra in Poseidon, dar acum se trece pe TC UML Tool - utilitar UML facut de TopCoder special pentru concursurile lor. Si un editor de documente in format .rtf.\r\n\r\n*Care a fost proiectul facut la TopCoder care ti-a placut cel mai mult?*\r\nTC UML Tool ;-)\r\nDaca e vorba de componente, nu stiu ce sa zic. Mai recent - Graph Framework de la TCCC a fost interesanta, fiindca am avut libertate. Componentele in care sunt constrangeri de interfete sunt urate, fiindca nu prea e loc de o alta abordare si se rezuma doar la munca pentru documentatie.\r\n\r\n*De cate ore crezi ca ai nevoie pentru a face un design bun pentru o asemenea competitie?*\r\n16-20 ore efectiv. Plus mult timp petrecut citind cerintele, intreband pe forumuri si gandindu-te la componenta in timp ce mergi pe strada sau stai la o cafea.\r\n\r\n*Stiu ca in primavara ai fost in comisia ce evalua proiectele concurentilor la sectiunea software design pentru concursul TopCoder Open in Las Vegas. Cum e sa fi de partea cealalta a baricadei?*\r\nE aproape ca si cum ai face munca acasa, doar ca mergi acolo. Proiectele sunt mult mai de calitate (cel putin cele din top) decat ce vezi de obicei. Si iti ia mult mai mult timp sa la corectezi. Plus ca exista presiunea de a nu face vreo pozna sa dai scor prea mare sau prea mic si sa influentezi rezultatele. Asa ca trebuie sa insisti mai mult sa fii sigur ca ce au facut bine e intr-adevar bine si ce greseli ai gasit sunt intr-adevar greseli. Mie mi-a fost mai mult frica sa nu dau scor prea mare, fiindca la  appeal-uri nu poti micsora scorul. Pe review-eri ne-au izolat de concurenti, intr-o camera. Ne-a dat cafea si ceva de rontait. Deci a fost bine.\r\n\r\n*Ce caracteristici crezi ca trebuie sa aiba un designer bun?*\r\nMi-e cam greu sa raspund la intrebarea asta. Sa poata sa transforme cerinte textuale intr-o structura de clase care lucreaza impreuna pentru a atinge un scop. Nu stiu cum se numeste abilitatea asta. Trebuie sa ai o viziune de ansamblu, sa intelegi cum comunica mai multe componente, sa poti depista ce anume introduce limitari intr-o componenta, la fel cum ai depista unde se produce dead-lock intr-o aplicatie  multi-threaded, doar ca lucrezi numai cu diagrame si nu cu cod, deci nu poti scrie teste.\r\n\r\n_Mersi Luci ca ti-ai facut timp sa raspunzi la intrebari. Maine voi pune online interviul cu Mircea Pasoi._\r\n\r\n',1490,'protected',2447,NULL),('utilizator/unubou','Profil unubou','2007-10-04 15:15:29','2007-10-04 15:15:29','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6867,'public',NULL,NULL),('utilizator/kaya','Profil kaya','2007-10-04 15:21:55','2007-10-04 15:21:55','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',6874,'public',NULL,NULL),('autumn-warmup-2007/clasament/runda-3','Clasament autumn2007-runda3','2007-10-04 17:26:08','2007-10-06 20:03:24','h1. Clasament ==roundparam(round_id=\"autumn2007-runda3\" param=\"title\") ==\r\n\r\n(htabs)* \'Detalii\':autumn-warmup-2007/\r\n* \'Runda 1\':autumn-warmup-2007/runda-1\r\n* \'Runda 2\':autumn-warmup-2007/runda-2\r\n*(active) \'Runda 3\':autumn-warmup-2007/runda-3\r\n*(active) \'Clasament\':autumn-warmup-2007/clasament\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"autumn2007-runda3\")==',961,'round: autumn2007-runda3',NULL,NULL),('autumn-warmup-2007','Autumn Warm Up 2007','2007-09-03 19:57:38','2007-10-04 17:45:53','h1. Autumn Warm Up 2007\r\n\r\n(htabs)*(active) \'Despre concurs\':autumn-warmup-2007/\r\n* \'Runda 1\':autumn-warmup-2007/runda-1\r\n* \'Runda 2\':autumn-warmup-2007/runda-2\r\n* \'Runda 3\':autumn-warmup-2007/runda-3\r\n* \'Clasament\':autumn-warmup-2007/clasament\r\n\r\nInainte sa dati piept cu greutatile scolare care va vor priva probabil de mult timp in care ati vrea sa va pregatiti la informatica :D, infoarena mai organizeaza un concurs de adio al vacantei si incalzire pentru un nou an scolar. Astfel concursul \"Autumn Warmup\" ajunge la editia a II-a, iar pentru cei care nu au participat anul trecut, acest concurs are si un factor mai interesant in ceea ce priveste organizarea: in loc sa fie organizat, ca de obicei, de membrii echipei infoarena, este organizat de niste membri obisnuiti.\r\n\r\nVa asteptam in numar cat mai mare, have fun :).\r\n\r\nh2. Program concurs\r\n\r\ntable{width: 50%}. |_. Runda|_. Data |_. Ora |\r\n|\"*Runda 1*\":autumn-warmup-2007/runda-1|*Marti, 11 septembrie 2007*| *10^00^ - 15^00^* |\r\n|\"*Runda 2*\":autumn-warmup-2007/runda-2|*Duminica, 23 septembrie 2007*| *10^00^ - 15^00^* |\r\n|\"*Runda 3*\":autumn-warmup-2007/runda-3|*Duminica, 7 octombrie 2007*| *10^00^ - 15^00^* |\r\n\r\nClick pe titlul unei runde pentru informatii detaliate.\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru.\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti probleme, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':/documentatie/evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nh2. Prima data pe infoarena?\r\n\r\ninfoarena ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi.\r\n\r\nVezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n\r\n\r\n',2092,'public',NULL,NULL),('blog/infoarena-isi-trage-blog','infoarea si-a tras blog','2007-10-10 00:00:11','2007-10-10 00:00:11','Ultimul feature adaugat la site este un \'blog\':blog. Va invitam sa il folositi si speram sa fie interesant si util.',58,'public',NULL,NULL),('problema/homm','Heroes of Might & Magic','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"homm\")==\r\n\r\nHarta Erathiei este data sub forma unui caroiaj cu $M$ linii si $N$ coloane. Terenul este impartit in celule care pot fi accesibile (au valoarea 0) sau inaccesibile (au valoare diferita de 0). Sir Christian doreste sa ajunga din celula de coordonate $(x{~1~}, y{~1~})$ unde a avut loc ultima batalie in celula $(x{~2~}, y{~2~})$ unde se afla Capitala regatului sau. Pentru aceasta el are la dispozitie $K$ mutari. O mutare consta in deplasarea din celula curenta intr-o celula invecinata (pe orizontala sau verticala, nu si pe diagonala).\r\nVa trebui sa determinati numarul variantelor pe care le poate alege Sir Christian. Un drum trebuie sa contina cel mult $K$ mutari, iar Sir Christian poate trece de oricate ori prin aceeasi celula, inclusiv prin celulele $(x{~1~}, y{~1~})$ si $(x{~2~}, y{~2~})$.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $homm.in$ se afla doua numere naturale $M, N$ si $K$, reprezentand numarul liniilor si coloanelor caroiajului, respectiv numarul mutarilor pe care Sir Christian le are la dispozitie; aceste numere sunt separate printr-un spatiu. Urmatoarele $M$ linii contin cate $N$ numere intregi, separate printr-un spatiu, reprezentand elementele caroiajului. Pe ultima linie se vor afla patru numere intregi, reprezentand valorile $x{~1~}, y{~1~}, x{~2~}$ si $y{~2~}$.\r\n\r\nh2. Date de Iesire\r\n\r\nIn fisierul de iesire $homm.out$ se va scrie un singur numar care va reprezenta numarul total al drumurilor posibile.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; M, N &le; 100$\r\n* $1 &le; K &le; 20$\r\n* Numarul total al drumurilor este intotdeauna mai mic decat $1.000.000.000$\r\n* Toate coordonatele sunt date in ordinea linie ({$x$}), coloana ({$y$}).\r\n\r\nExemple\r\n\r\ntable(example). |_. homm.in |_. homm.out |\r\n| 5 5 10 \r\n0 0 0 0 0\r\n0 2 0 3 0\r\n0 0 1 0 0\r\n0 2 0 0 0\r\n0 0 0 0 0\r\n1 1 5 5 | 34 |\r\n| 5 5 10 \r\n0 0 4 0 0\r\n0 2 0 3 0\r\n4 0 1 0 0\r\n0 2 0 0 0\r\n0 0 0 0 0\r\n1 1 5 5 | 0&nbsp; |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"homm\")==\n\n\n',1490,'task: homm',416,NULL),('problema/colectie','Colectie','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"colectie\")==\r\n\r\nTudor s-a gandit ca, deja, colectia lui de CD-uri si DVD-uri a devenit destul de impresionanta si, pentru a organiza mai usor discurile, vrea sa le numeroteze cu etichete. El vrea sa cumpere cutii care contin etichete cu cifre.\r\n\r\nLa magazinul din apropiere se gasesc k asemenea pachete care contin etichete cu cateva cifre de $0$, cateva cifre de $1$ si asa mai departe (pachete diferite pot avea continut diferit).\r\n\r\nTudor ar vrea sa cumpere cateva dintre pachete si sa poata forma din etichete toate numerele de la $1$ la $K$ ({$K$} fiind numarul de CD-uri si DVD-uri din colectie).\r\n\r\nO conditie pentru a realiza etichetarea este ar fi sa nu ramana etichete care nu sunt folosite pentru ca Tudor nu ar avea ce face cu ele. Acest lucru nu este tot timpul posibil. Daca este posibil, atunci ne intereseaza solutia care foloseste un numar minim de pachete.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $colectie.in$ se afla doua numere naturale $N$ si $K$, reprezentand numarul de pachete de la magazin, respectiv numarul de CD-uri si DVD-uri din colectia lui Tudor. Pe urmatoarele $N$ linii se vor afla cate zece numere intregi separate prin spatii; linia $i + 1$ contine numarul de etichete cu cifrele $0, 1, ... 9$ din pachetul $i$.\r\n\r\nh2. Date de Iesire\r\n\r\nIn fisierul de iesire colectie.out se va scrie pe prima linie valoarea $1$ daca exista o solutie, sau valoarea $0$ daca problema nu are solutie. Daca problema are solutie atunci pe urmatoarea linie va fi scris numarul $L$ al pachetelor folosite intr-o solutie optima, iar urmatoarea linie va contine $L$ numere intregi, reprezentand pachetele alese.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; N &le; 32$\r\n* $1 &le; K &le; 100.000.000$\r\n\r\nh2. Exemplu\r\n\r\n\r\ntable(example). |_. colectie.in |_. colectie.out |\r\n|4 11\r\n0 1 0 0 0 0 1 1 0 0\r\n1 2 1 1 1 1 0 0 0 0\r\n0 1 0 0 0 0 0 0 1 1\r\n0 2 0 0 0 0 1 1 1 1\r\n| 1\r\n2\r\n2 4 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"colectie\")==\n\n\n',1490,'task: colectie',417,NULL),('problema/frac','Frac','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"frac\")==\r\n\r\nPatratel este mare pasionat de fractii. Intr-o zi el se gandeste sa scrie pe o foaie de hartie, in ordine crescatoare, toate fractiile ireductibile cu numitorul $N$. Observand insa la timp ca sunt o infinitate de astfel de fractii, el nu se mai oboseste si doreste sa afle doar a $P$-a fractie din sirul la care s-a gandit.\r\n\r\nh2. Cerinta\r\n\r\nSa se determine numaratorul celei de a $P$-a fractii din sirul construit dupa regulile de mai sus.\r\n\r\nh2. Date de Intrare\r\n\r\nPrima linie a fisierului $frac.in$ contine doua numere intregi $N$ si $P$, separate prin cate un spatiu, avand semnificatia descrisa in enunt.\r\n\r\nh2. Date de Iesire\r\n\r\nPrima linie a fisierului $frac.out$ contine un numar natural care reprezinta numaratorul celei de a $P$-a fractii din sirul fractiilor ireductibile cu numitorul $N$.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 12 000 000 000$ ( $12$ miliarde )\r\n* $1 &le; P &le; 10^14^$\r\n* Se garanteaza ca rezultatul nu depaseste $2^61^$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. frac.in |_. frac.out |\r\n| 12 5 | 13 |\r\n\r\nh3. Explicatie\r\n\r\nFractiile sirului sunt: $1/12, 5/12, 7/12, 11/12, 13/12, 17/12$, etc. A $5$-a fractie din acest sir este $13/12$ si are numaratorul $13$.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"frac\")==\n\n\n',1490,'task: frac',421,NULL),('problema/pal','Pal','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"pal\")==\r\n\r\nPrintul Algorel este in incurcatura din nou: a fost prins de Spanul cel Negru in incercarea sa de a o salva pe printesa si acum este inchis in Turnul cel Mare. Algorel poate evada daca gaseste combinatia magica cu care poate deschide poarta turnului. Printul stie cum se formeaza aceasta combinatie magica: trebuie sa utilizeze toate cifrele scrise pe usa turnului pentru a obtine doua numere palindroame, astfel incat suma lor sa fie minima, iar aceasta suma este combinatia magica ce va deschide usa. Primul numar palindrom trebuie sa aiba cel putin $L$ cifre, iar cel de-al doilea poate avea orice lungime diferita de $0$. Numerele palindroame formate nu pot incepe cu cifra $0$. Acum interveniti dumneavoastra in poveste, fiind prietenul sau cel mai priceput in algoritmi. Prin noul super-telefon al sau, printul transmite numarul de aparitii a fiecarei cifre de pe usa turnului precum si lungimea minima $L$ a primului numar, iar dumneavoastra trebuie sa-i trimiteti cat mai repede numerele cu care poate obtine combinatia magica.\r\n\r\nh2. Cerinta\r\n\r\nAvand datele necesare, aflati doua numere palindroame cu care se poate obtine combinatia magica.\r\n\r\nh2. Date de Intrare\r\n\r\nPrima linie a fisierului $pal.in$ contine un numar intreg $L$ reprezentand lungimea minima a primului numar. Urmeaza 10 linii: pe linia $i+2$ se va afla un numar intreg reprezentand numarul de aparitii ale cifrei $i$, pentru $i$ cu valori de la $0$ la $9$.\r\n\r\nh2. Date de Iesire\r\n\r\nPrima linie a fisierului de iesire $pal.out$ contine primul numar palidrom, iar cea de-a doua linie contine cel de-al doilea numar palindrom. Daca exista mai multe solutii se va scrie doar una dintre ele.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* In total vor fi cel mult $100$ de cifre\r\n* $1 &le; L < 100$ si $L$ va fi mai mic decat numarul total de cifre\r\n* Pentru datele de test va exista intotdeauna solutie: se vor putea forma din cifrele scrise pe usa turnului doua numere care incep cu o cifra diferita de $0$, iar primul numar sa aiba cel putin $L$ cifre\r\n* Un numar este palindrom daca el coincide cu rasturnatul sau. De exemplu $12321$ si $7007$ sunt numere palindroame, in timp ce $109$ si $35672$ nu sunt.\r\n* Pentru $30%$ dintre teste, numarul total de cifre va fi cel mult $7$; pentru alte $40%$ din teste numarul total de cifre va fi cel mult $18$, iar pentru restul de $30%$ din teste numarul total de cifre va fi mai mare sau egal cu $30$\r\n* Fiecare linie din fisierul de intrare si din fisierul de iesire se termina cu marcaj de sfarsit de linie.\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. pal.in |_. pal.out |\r\n| 5 \r\n  3\r\n  2\r\n  3\r\n  0\r\n  0\r\n  0\r\n  0\r\n  0\r\n  0\r\n  0\r\n| 10001\r\n  222 |\r\n\r\nh3. Explicatii\r\n\r\nPentru acest exemplu avem L = 5, 3 cifre de 0, 2 cifre de 1 si 3 cifre de 2. Cifrele de la 3 la 9 lipsesc de pe usa turnului.\r\nCele doua palindroame cu care se genereaza combinatia magica sunt 10001 si 222. Combinatia magica va fi suma acestora si anume 10223 (care este suma minima pe care o putem obtine).\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"pal\")==\r\n\r\n\r\n',1490,'task: pal',424,NULL),('problema/camion','Camion','2006-11-11 11:23:41','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"camion\")==\r\n\r\nLa firma la care lucreaza Gigel exista $M$ tipuri de camioane, din fiecare tip existand $N$ exemplare. Gigel aseaza camioanele firmei pe $N$ randuri, asezand pe fiecare coloana numai camioane de acelasi tip. Se formeaza astfel o matrice in care liniile sunt numerotate de sus in jos de la $1$ la $N$, iar coloanele sunt numerotate de la stanga la dreapta de la $1$ la $M$.\r\n\r\nIn fiecare noapte vine o banda de hoti. Seful bandei anunta: \"in noaptea aceasta vom fura toate camioanele care se afla in zona dreptunghiulara avand coltul stanga-sus pe linia $x{~1~}$ si coloana $y{~1~}$, iar coltul opus pe linia $x{~2~}$ si coloana $y{~2~}$.\r\n\r\nIn dimineata urmatoare, Gigel vede acest lucru, si \"acopera\" furtul: pe fiecare linie in care exista spatii libere deplaseaza spre stanga toate camioanele care se afla in dreapta locului liber ramas.\r\n\r\nDe exemplu, pentru $N = 3$ si $M = 5$ initial avem urmatoarea amplasare:\r\n$1 2 3 4 5$\r\n$1 _*2 3*_ 4 5$\r\n$1 _*2 3*_ 4 5$\r\n\r\nIn prima noapte hotii fura camioane, din dreptunghiul cu coltul stanga-sus in linia $2$,coloana $2$ si coltul dreapta-jos linia $3$ coloana $3$. Astfel, in ziua urmatoare, dupa ce Gigel deplaseaza camioanele, amplasarea este urmatoarea:\r\n$_*1 2*_ 3 4 5$\r\n$_*1 4*_ 5$\r\n$_*1 4*_ 5$\r\n\r\nDaca in a doua noapte hotii fura din nou din dreptunghiul cu coltul stanga-sus in linia $1$, coloana $1$ si coltul dreapta-jos in linia $3$, coloana $2$, dupa deplasarile facute ziua de Gigel, amplasarea este urmatoarea:\r\n$3 4 5$\r\n$5$\r\n$5$\r\n\r\nh2. Cerinta\r\n\r\nCunoscand cate tipuri de camioane exista la firma initial, pe cate randuri au fost asezate, numarul $K$ de zile in care au loc furturi si coordonatele dreptunghiurilor din care fura hotii in fiecare noapte, determinati ce tipuri de camioane se afla pe o anumita coloana din amplasarea finala.\r\n\r\nh2. Date de Intrare\r\n\r\nFisierul de intrare $camion.in$ contine pe prima linie $4$ numere naturale: $N M K$ si $C$, reprezentand numarul de randuri pe care au fost asezate camioanele, numarul de coloane, numarul de nopti in care vor fura hotii camioane, respectiv numarul coloanei pentru care se doreste sa se afle ce tipuri de camioane contine la final. Pe fiecare dintre urmatoarele $K$ linii se vor afla cate $4$ numere naturale. Pe linia $i+1$ se afla $x{~1~} y{~1~} x{~2~} y{~2~}$, {$(x{~1~},y{~1~})$} reprezentand linia si coloana coltului stanga-sus, iar {$(x{~2~},y{~2~})$} linia si coloana coltului dreapta-jos al dreptunghiului din care fura hotii in noaptea $i$. Numerele situate pe aceeasi linie sunt separate prin cate un spatiu.\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul de iesire $camion.out$ va contine $N$ linii, pe fiecare cate un numar intreg. Numarul de pe linia $i$ va reprezenta tipul camionului de pe linia $i$ si coloana $C$, dupa $K$ zile. In caz ca pe linia $i$ nu se gaseste nici un camion, se va afisa valoarea $0$ pe linia respectiva.\r\n\r\nh2. Restrictii si observatii\r\n\r\n* $1 &le; N &le; 600$\r\n* $1 &le; C &le; M &le; 600$\r\n* $0 &le; K &le; 30000$\r\n\r\nNu este obligatoriu ca dreptunghiul din care se va efectua un furt sa contina camioane in fiecare loc.\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. camion.in |_. camion.out |\r\n| 3 5 3 1\r\n2 2 3 3\r\n1 1 3 2\r\n1 2 3 4\r\n| 3\r\n5\r\n5 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"camion\")==\n\n\n',1490,'task: camion',428,NULL),('problema/perle','Perle','2006-11-11 11:23:35','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"perle\")==\r\n\r\nGranita nu se trece usor. Asta pentru ca Balaurul Arhirel (mare pasionat de informatica) nu lasa pe nimeni sa treaca decat dupa ce raspunde la niste intrebari!\r\n\r\nIn acea tara exista $3$ tipuri de perle normale (le vom nota cu {$1$}, {$2$} si {$3$}) si $3$ tipuri de perle magice (le vom nota cu {$A$}, {$B$} si {$C$}). Perlele magice sunt deosebite prin faptul ca se pot transforma in alte perle (una sau mai multe, normale sau magice).\r\n\r\nPerla magica de tipul $A$ se poate transforma in orice perla normala (una singura).\r\n\r\nPerla magica de tipul $B$ se poate transforma intr-o perla normala de tipul $2$ si una magica de tipul {$B$}, sau intr-o perla normala de tipul {$1$}, una magica de tipul {$A$}, una normala de tipul {$3$}, una magica de tipul {$A$} si una magica de tipul {$C$}.\r\n\r\nPerla magica de tipul {$C$} se poate transforma intr-o perla normala de tipul {$2$} sau intr-o perla normala de tipul {$3$}, una magica de tipul {$B$} si una magica de tipul {$C$} sau intr-o perla normala de tipul {$1$}, una normala de tipul {$2$} si una magica de tipul {$A$}.\r\n\r\nCa sa rezumam cele de mai sus putem scrie:\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {$A -> 1 | 2 | 3$}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {$B -> 2B | 1A3AC$}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {$C -> 2 | 3BC | 12A$}\r\n\r\nBalaurul Arhirel ne lasa la inceput sa ne alegem o perla magica (una singura), iar apoi folosind numai transformarile de mai sus trebuie sa obtinem un anumit sir de perle normale. Cand o perla magica se transforma, perlele din stanga si din dreapta ei raman la fel (si in aceeasi ordine). De asemenea ordinea perlelor rezultate din transformare este chiar cea prezentata mai sus.\r\n\r\nDe exemplu, daca balaurul ne cere sa facem sirul de perle {$21132123$}, putem alege o perla magica de tipul {$B$} si urmatorul sir de transformari: {$B$} -> {$2B$} -> {$21A3AC$} -> {$21A3A12A$} -> {$21132123$}.\r\n\r\nDeoarece Balaurul nu are prea multa rabdare, el nu ne cere decat sa spunem daca se poate sau nu obtine sirul respectiv de perle.\r\n\r\nh2. Cerinta\r\n\r\nSa se determine pentru fiecare sir de intrare daca se poate obtine prin transformarile de mai sus sau nu (alegand orice prima perla magica, la fiecare sir).\r\n\r\nh2. Date de intrare\r\n\r\nFisierul de intrare $perle.in$ are urmatoarea structura: pe prima linie numarul {$N$}, reprezentand numarul de siruri din fisierul de intrare. Urmeaza $N$ linii; a $i$-a linie dintre cele $N$ descrie sirul {$i$}, printr-o succesiune de numere naturale despartite de cate un spatiu. Primul numar reprezinta lungimea sirului, {$L{~i~}$}, iar urmatoarele {$L{~i~}$} numere sunt tipurile de perle normale, in ordine, de la stanga la dreapta.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $perle.out$ va contine $N$ linii. Pe linia $i$ se va scrie un singur numar $1$ sau $0$ ({$1$} daca se poate obtine sirul al $i$-lea si $0$ daca nu se poate).\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $0 < N < 11$\r\n* $0 < L{~i~} < 10 001$, pentru $i$ de la $1$ la $N$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. perle.in|_. perle.out|\r\n|3\r\n8 2 1 1 3 2 1 2 3\r\n2 2 2\r\n1 3\r\n|1\r\n0\r\n1|\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"perle\")==\n\n\n',1490,'task: perle',688,NULL),('problema/proc','Proc','2006-11-11 11:23:42','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"proc\")==\r\n\r\n\r\nO aplicatie ce trebuie executata pe un calculator multi-procesor consta din $N$ fragmente de cod independente, ce pot fi rulate in paralel. Fiecare fragment trebuie executat in totalitate pe un singur procesor. Din dorinta de a paraleliza cat mai mult aplicatia, fragmentele de cod au dimensiuni mici si, in consecinta, timpi de executie mici. Mai precis, executia fiecarui fragment dureaza UNUL sau DOUA cicluri de ceas pe un procesor de tipul Pentium IV.\r\n\r\nSistemul pe care urmeaza sa fie executata aplicatia consta din $P$ procesoare. Spre deosebire de majoritatea sistemelor de acest fel, insa, cele $P$ procesoare au viteze de executie diferite. Primul procesor este un Pentium IV si este cel mai rapid. Al doilea procesor este de doua ori mai lent decat primul, al treilea de trei ori mai lent ... al $i$-lea procesor este de $i$ ori mai incet decat primul. In aceste conditii, timpul de executie al fiecarui fragment de cod difera, in functie de procesorul pe care va fi executat. Sa prespunem ca un segment de cod are timpul de executie $T$ (unde $T$ este $1$ sau {$2$}) pe primul procesor. Atunci pe un procesor $i$, timpul sau de executie va fi $i*T$.\r\n\r\nh2. Cerinta\r\n\r\nStiind ca fragmentele de cod pot fi executate in orice ordine si pe orice procesor si ca orice procesor poate executa, la un moment dat, un singur fragment de cod, determinati timpul minim dupa care se va termina executia aplicatiei (adica a tuturor fragmentelor de cod). Timpul dupa care se termina aplicatia este egal cu maximul dintre timpii dupa care fiecare procesor redevine disponibil. Timpul dupa care un procesor redevine disponibil este egal cu suma timpilor de executie a fragmentelor de cod rulate pe procesorul respectiv.\r\n\r\nh2. Date de intrare\r\n\r\nPrima (si singura) linie a fisierului de intrare $proc.in$ contine trei numere intregi, separate prin spatii: $N$ - numarul de fragmente de cod, $K$ - numarul de fragmente de cod care au timpul de executie pe un Pentium IV egal cu $1$ (implicit, $N-K$ au timpul de executie egal cu $2$) si $P$ - numarul de procesoare ale sistemului.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul $proc.out$ va contine o singura linie pe care se afla timpul minim dupa care se termina de executat aplicatia.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $0 &le; K &le; N &le; 1.000.000.000$\r\n* $1 &le; P &le; 65.535$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. proc.in |_. proc.out |\r\n| 4 3 2 | 4 |\r\n\r\nh3. Explicatie\r\n\r\nPe primul procesor se executa un fragment de cod cu timpul de executie (calculat pe un Pentium IV) egal cu $1$ si un fragment de cod cu timpul de executie egal cu $2$ => timpul dupa care acest procesor devine disponibil este $1*1 + 1*2 = 3$. Pe al doilea procesor se executa doua fragmente de cod cu timpul de executie (calculat pe un Pentium IV) egal cu $1$ => timpul dupa care acest procesor devine disponibil este $2$ [numarul de fragmente] * $(2*1)$ [timpul de executie al fiecarui fragment pe procesorul $2$] = $4$.\r\n==Include(page=\"template/taskfooter\" task_id=\"proc\")==\n\n\n',1490,'task: proc',465,NULL),('problema/delay','Delay','2006-11-11 11:23:41','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"delay\")==\r\n\r\n==include(page=\"template/badtests\")==\r\n\r\nGigel a cumparat $N$ calculatoare cu care vrea sa deschida un Internet Cafe. Pentru aceasta, el trebuie sa conecteze toate calculatoarele in retea, in asa fel incat oricare doua calculatoare sa poata comunica intre ele, direct sau indirect. Comunicatia dintre calculatoare se realizeaza prin intermediul cablurilor de legatura. Un cablu leaga doua calculatoare, iar transferul de date prin cablu se poate realiza in ambele sensuri. Fiind la inceput si neavand prea multi bani, Gigel a legat calculatoarele intre ele astfel incat intre oricare doua calculatoare exista un singur traseu pe care se pot transmite date.\r\nCurand si-a dat seama ca transferul de date se realizeaza cu viteza foarte mica. Acest lucru se datoreaza faptului ca fiecare pachet de date care trece prin calculatorul $i$ este pus sa astepte un timp {$T{~i~}$}. In aceste conditii, timpul dupa care un pachet de date ajunge de la un calculator la altul este egal cu suma timpilor de asteptare ai fiecarui calculator de pe traseu (inclusiv ai calculatoarelor sursa si destinatie).\r\nDin cand in cand, configuratia anumitor calculatoare este modificata si timpii de asteptare corespunzatori acelor calculatoare se schimba. Cum Gigel are grija foarte mare de calculatoarele sale, el trebuie sa fie mereu informat in legatura cu starea retelei. Mai precis, el trebuie sa poata afla repede care este timpul de transmitere a unui pachet de date intre oricare doua calculatoare din reteaua sa.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care trateaza in mod eficient urmatoarele doua tipuri de operatii:\r\n\r\n* tipul 1: modificarea timpului de asteptare al unui calculator\r\n* tipul 2: determinarea timpului de transmitere a unui pachet de date intre doua calculatoare specificate.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $delay.in$ se afla numarul $N$ de calculatoare. Pe fiecare dintre urmatoarele $N$ linii se afla cate un numar intreg {$T{~i~}$}, reprezentand timpul initial de asteptare al calculatorului corespunzator. Pe urmatoarele $N-1$ linii se afla cate doua numere intregi $a$ si {$b$}, reprezentand numerele a doua calculatoare legate printr-un cablu direct. Pe urmatoarea linie se afla numarul intreg {$M$}, reprezentand numarul de operatii descrise in continuare. Fiecare dintre urmatoarele $M$ linii contine cate $3$ numere intregi separate prin spatii: {$a b c$}.\r\n\r\n* Daca {$a=1$}, atunci $b$ reprezinta numarul de ordine al unui calculator nou configurat, iar $c$ reprezinta noul timp de asteptare al calculatorului $b$\r\n* Daca {$a=2$}, atunci $b$ si $c$ reprezinta numerele de ordine a doua calculatoare diferite, iar programul va trebui sa afiseze in fisierul de iesire timpul de transmitere a unui pachet de date intre calculatoarele $b$ si $c$\r\n\r\nh2. Date de Iesire\r\n\r\nIn fisierul $delay.out$ veti afisa, pe cate o linie separata, timpii determinati in cazul fiecarei operatii de tipul {$2$}, in ordinea in care sunt intalnite in fisierul de intrare. Atunci cand calculati timpul de transmitere a unui pachet de date intre doua calculatoare, trebuie sa considerati timpii de asteptare de la momentul respectiv (care sunt determinati de valorile initiale sau de operatiile de tipul $1$ descrise in fisierul de intrare inaintea operatiei curente).\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $2 &le; N &le; 16.000$\r\n* $0 &le; T{~i~} &le; 1.000$\r\n* $2 &le; M &le; 200.000$\r\n* Calculatoarele sunt numerotate de la $1$ la $N$\r\n* In fisierul de intrare va exista cel putin o operatie de tipul $2$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. delay.in |_. delay.out |\r\n| 5\r\n1\r\n2\r\n3\r\n4\r\n5\r\n1 2\r\n1 3\r\n2 4\r\n3 5\r\n6\r\n2 1 4\r\n2 3 1\r\n1 1 100\r\n2 1 4\r\n2 2 4\r\n2 2 3\r\n| 7\r\n4\r\n106\r\n6\r\n105 |\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"delay\")==\r\n\r\n\r\n',1490,'task: delay',456,NULL),('problema/gard3','Gard3','2006-11-11 11:23:41','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"gard3\")==\r\n\r\nFermierul Ion mai avea o ferma in forma de poligon convex cu $N$ laturi. Intr-o buna zi, el se hotaraste s-o imparta in $K$ regiuni, de asemenea poligoane convexe. Dupa impartire, el va folosi fiecare zona intr-un anumit scop (de exemplu, in zona $1$ va planta vita de vie, in zona $2$ va creste vaci etc.) Pentru aceasta, el va construi $K-1$ garduri. Fiecare gard va fi un segment care va uni doua varfuri din poligon. Gardurile nu se vor intersecta decat, eventual, in varfurile poligonului.\r\nInainte de a se apuca de treaba, fermierul Ion doreste sa afle in cate moduri poate imparti ferma sa in $K$ regiuni (pentru a le examina si a alege un anumit mod de impartire).\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care, pentru valorile $N$ si $K$ date, va afisa numarul de moduri in care fermierul Ion poate imparti ferma sa in $K$ regiuni.\r\n\r\nh2. Date de Intrare\r\n\r\nFisierul $gard3.in$ contine pe prima linie numerele naturale $N$ si {$K$}, separate printr-un spatiu.\r\n\r\nh2. Date de Iesire\r\n\r\nIn fisierul de iesire $gard3.out$ se va afisa numarul de moduri in care se poate imparti ferma in $K$ regiuni.\r\n\r\nh2. Restrictii\r\n\r\n* $3 &le; N &le; 50$\r\n* $1 &le; K &le; N-2$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. gard3.in |_. gard3.out |\r\n| 5 2 | 5 |\r\n\r\nh3. Explicatie\r\n\r\nSe construieste un singur gard. Acesta va uni una dintre  perechile de varfuri: \r\n$(1, 3) (1, 4) (2, 4) (2, 5) (3, 5)$.\r\n\r\ntable(example). |_. gard3.in |_. gard3.out |\r\n| 10 7 | 5005 |\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"gard3\")==\n\n\n',1490,'task: gard3',458,NULL),('problema/sistem','Sistem','2006-11-11 11:23:41','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"sistem\")==\r\n\r\nIntr-un judet exista $N$ orase, numerotate de la $1$ la $N$. Fiecare dintre cele $N$ orase ale judetului este legat de exact alte 2 orase, prin strazi bidirectionale. Si mai ciudat este faptul ca, in cadrul acestui sistem stradal, nu este intotdeauna posibil sa ajungi din orice oras in oricare alt oras mergand pe strazi. Oricum, locuitorii judetului sunt mandri de acest sistem al lor si sunt de parere ca nu mai exista altul la fel. Dumneavoastra vreti sa le demonstrati contrariul si pentru aceasta vreti sa calculati cate sisteme stradale distincte cu proprietatea de mai sus exista. Doua sisteme sunt considerate distincte daca exista cel putin o strada intre o pereche de orase $i$ si $j$ in cadrul primului sistem, care nu exista in cadrul celui de-al doilea.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care sa calculeze cate sisteme stradale distincte exista.\r\n\r\nh2. Date de intrare\r\n\r\nDin fisierul $sistem.in$ veti citi valoarea intreaga $N$, reprezentand numarul de orase ale judetului.\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul $sistem.out$ veti afisa o valoare intreaga, reprezentand numarul de sisteme stradale distincte, cu proprietatea ca orice oras este legat prin strazi directe de exact alte 2 orase.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $3 &le; N &le; 100$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. sistem.in|_. sistem.out|_. sistem.in|_. sistem.out|\r\n|4|3|6|70|\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"sistem\")==\n\n\n',1490,'task: sistem',459,NULL),('problema/doipatru','DoiPatru','2006-11-11 11:23:42','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"doipatru\")==\r\n\r\n\r\nMembrii Lotului National de Informatica sunt foarte mandri de noul joc inventat de ei, pe care l-au denumit asemanator cu o problema de la Olimpiada Internationala de Informatica din anul 2001, care le-a placut foarte mult. Astfel, jocul se numeste DoiPatru.\r\n\r\nPentru acest joc se folosesc $N$ gramezi, fiecare continand cel putin $0$ si cel mult $4$ bile. Numarul total de bile din toate gramezile este $2N$. Doi jucatori muta alternativ. Atunci cand ii vine randul, fiecare jucator este obligat sa efectueze o mutare valida.\r\n\r\nO mutare valida consta din alegerea a doua gramezi, dintre care prima gramada are mai multe bile decat cea de a doua. Jucatorul ia o bila din prima gramada si o muta in cealalta. Mutarea se considera valida, doar daca numarul de bile rezultat in a doua gramada dupa mutarea bilei nu este mai mare decat numarul de bile ramas in prima gramada.\r\n\r\nJocul se termina atunci cand nu mai poate fi efectuata nici o mutare valida (daca va ganditi putin, veti constata ca acest lucru se intampla atunci cand fiecare gramada contine doua bile).\r\n\r\nCastigatorul jocului este desemnat cel care detine mai multe gramezi la sfarsitul jocului. Bineinteles, daca cei doi jucatori detin un numar egal de gramezi, jocul se considera a fi remiza.\r\n\r\nUn jucator detine o gramada daca gramada are doua bile, iar acest numar (de doua bile) a rezultat in urma unei mutari efectuate de jucatorul respectiv. De exemplu, daca un jucator alege o gramada cu $4$ bile si una cu o bila, in urma efectuarii mutarii, el va detine cea de-a doua gramada (care va avea doua bile), dar prima nu va apartine deocamdata nici unuia dintre jucatori. Daca alege o gramada cu $3$ bile si una cu $0$ bile, jucatorul va deveni proprietarul primei gramezi, deoarece, in urma mutarii efectuate, gramada respectiva va ramane cu doua bile. In cazul in care alege o gramada cu $3$ bile si una cu o bila, dupa efectuarea mutarii, el va detine ambele gramezi (amandoua au acum doua bile).\r\n\r\nDaca un jucator este proprietarul unei gramezi la un moment dat in timpul jocului, nu inseamna ca aceasta gramada va ramane in posesia lui pana la sfarsit. De exemplu, sa presupunem ca jucatorul $1$ detine o gramada cu doua bile si este randul jucatorului $2$ sa mute. Daca acesta alege o gramada cu $4$ bile si gramada cu doua bile ce apartine jucatorului $1$, dupa efectuarea mutarii, ambele gramezi vor avea $3$ bile, iar numarul de gramezi aflate in posesia jucatorului $1$ va scadea cu $1$ (gramada detinuta de el anterior nu mai apartine nici unuia din cei doi jucatori, caci nu mai are doua bile).\r\n\r\nDaca la inceputul jocului exista unele gramezi avand doua bile, acestea sunt distribuite in mod egal celor doi jucatori. Daca numarul de gramezi cu doua bile este impar, atunci jucatorul $2$ va primi cu o gramada mai mult decat jucatorul $1$. Jucatorul $1$ este cel care efectueaza prima mutare.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care, pentru un $N$ dat si un set de configuratii initiale ale jocului cu $N$ gramezi, decide rezultatul fiecarei configuratii de joc.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare $doipatru.in$ se afla doi intregi: $N$ si $S$, reprezentand numarul de gramezi folosite in joc, respectiv numarul de configuratii initiale ale jocului, descrise in continuare. Pe urmatoarele $S$ linii se afla cate $N$ valori intregi din intervalul $[0, 4]$, a caror suma este egala cu $2N$, reprezentand cate o configuratie initiala a jocului.\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul de iesire $doipatru.out$, pentru fiecare configuratie initiala a jocului descrisa in fisierul de intrare, in ordinea in care sunt descrise acestea, afisati rezultatul final al jocului, in conditiile in care ambii jucatori joaca optim. Veti afisa valoarea $1$, daca jocul este castigat de primul jucator, valoarea $2$, daca jocul este castigat de cel de-al doilea sau valoarea $0$, daca jocul se termina remiza.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $3 &le; N &le; 30$\r\n* $1 &le; S &le; 1000$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. doipatru.in |_. doipatru.out |\r\n| 5 4\r\n0 3 4 1 2\r\n2 2 2 2 2\r\n1 1 2 2 4\r\n4 3 2 1 0\r\n| 1\r\n2\r\n1\r\n1 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"doipatru\")==\n\n\n',1490,'task: doipatru',460,NULL),('problema/hotel','Hotel','2006-11-11 11:23:42','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"hotel\")==\r\n\r\n\r\nHotelul \"Informatica\" este unul dintre cele mai luxoase hoteluri din Galaciuc. De-a lungul anului multe grupuri de turisti sosesc la acest hotel sau il parasesc la sfarsitul sejurului, asa ca situatia exacta a camerelor libere si ocupate este destul de greu de aflat, mai ales ca hotelul are un numar mare de camere. Dar anul acesta proprietarul hotelului s-a decis ca are nevoie de o schimbare. De aceea v-a angajat pe dumneavoastra pentru a scrie un program eficient, care sa raspunda necesitatilor sale.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care sa trateze in mod eficient urmatoarele $3$ tipuri de instructiuni:\r\n\r\n* tipul $1$: sosirea unui grup nou de turisti\r\n\r\nUn grup de turisti avand $M$ membri vrea sa ocupe $M$ camere libere numerotate consecutiv. Programului $i$ se va furniza numarul $i$ al camerei de inceput al secventei de camere ocupate de grup si numarul $M$ de membri ai grupului. Se garanteaza ca oricare din camerele $i,i+1,.., i+M-1$ este libera la momentul respectiv.\r\n\r\n* tipul $2$: plecarea unui grup de turisti\r\n\r\nAtunci cand pleaca, turistii pleaca in grupuri (nu neaparat cele cu care au venit). Un grup care pleaca si care are $M$ membri paraseste $M$ camere (anterior ocupate) numerotate consecutiv. Programului $i$ se va furniza numarul $i$ al camerei de inceput al secventei de camere eliberate, precum si numarul $M$ de membri ai grupului. Se garanteaza ca toate camerele cu numerele de ordine $i,i+1,..,i+M-1$ sunt deja ocupate de turisti.\r\n\r\n* tipul $3$: intrebarea proprietarului\r\n\r\nProprietarul hotelului poate sa intrebe, din cand in cand, care este lungimea maxima a unei secvente de camere libere numerotate consecutiv. El are nevoie de acest numar pentru a putea sti care este numarul maxim posibil de membri ai unui grup care ar putea fi cazati la hotelul \"Informatica\".\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului $hotel.in$ se vor afla numerele $N$ si $P$, reprezentand numarul de camere ale hotelului (numerotate de la $1$ la {$N$}), respectiv numarul de instructiuni care urmeaza. Pe fiecare din urmatoarele $P$ linii se va afla un numar $c$, reprezentand tipul instructiunii ce va fi descrisa pe linia respectiva:\r\n\r\n* daca $c$ are valoarea $1$, atunci el va fi urmat (pe aceeasi linie) de alte $2$ numere, $i$ si $M$, reprezentand numarul primei camere distribuite grupului abia sosit si numarul de membri ai grupului\r\n* daca $c$ are valoarea $2$, atunci el va fi urmat (pe aceeasi linie) de alte $2$ numere, $i$ si $M$, reprezentand numarul primei camere care va fi eliberata de grupul care tocmai pleaca, precum si numarul de membri ai grupului care paraseste hotelul\r\n* daca $c$ are valoarea $3$, el nu va fi urmat de nici un alt numar pe linia respectiva; programul va trebui, insa, sa afiseze in fisierul de iesire lungimea maxima a unei secvente de camere libere numerotate consecutiv.\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul hotel.out veti afisa, pentru fiecare instructiune de tipul 3, pe cate o linie separata, lungimea maxima a unei secvente de camere libere numerotate consecutiv, luand in considerare instructiunile de tipul 1 si 2 aflate in fisierul de intrare inaintea instructiunii de tip 3 la care se raspunde. Inaintea primei instructiuni, toate camerele sunt libere.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $3 &le; N &le; 100.000$\r\n* $3 &le; P &le; 200.000$\r\n* In orice camera poate fi cazat la un moment dat un singur turist.\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. hotel.in |_. hotel.out |\r\n| 12 10\r\n3\r\n1 2 3\r\n1 9 4\r\n3\r\n2 2 1\r\n3\r\n2 9 2\r\n3\r\n2 3 2\r\n3\r\n| 12\r\n4\r\n4\r\n6\r\n10 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"hotel\")==\n\n\n',1490,'task: hotel',462,NULL),('problema/asmin','Asmin','2006-11-11 11:23:42','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"asmin\")==\r\n\r\nSe considera un arbore (graf conex aciclic) cu $N$ varfuri, fara radacina fixata. Drept radacina, poate fi ales oricare dintre varfuri. Sa presupunem ca a fost ales varful cu numarul {$T$}. Intre oricare varf si $T$ exista un drum unic care contine fiecare varf al arborelui cel mult o singura data (un drum intre varfurile $i$ si $j$ este o secventa de varfuri, care incepe cu {$i$}, se termina cu {$j$}, iar intre oricare doua varfuri consecutive exista o muchie in arbore). Fiecarui varf {$i$}(inclusiv {$T$}) trebuie sa i se asocieze o valoare {$V{~i~}$}, mai mare sau egala cu {$0$}, astfel incat suma valorilor varfurilor de pe drumul dintre $i$ si radacina {$T$}, impartita la {$K$}, sa dea restul {$R{~i~}$}. Se defineste costul arborelui cu radacina fixata in {$T$}, {$C{~T~}$}, ca fiind suma valorilor asociate fiecarui nod. Dintre toate posibilitatile de alegere a valorilor $V{~i~}$ care respecta conditia precizata anterior, se va alege aceea pentru care $C{~T~}$ este minim.\r\nSe constata usor ca alegand alt varf drept radacina, de exemplu, varful {$S$}(diferit de {$T$}), $C{~S~}$ nu este neaparat egal cu {$C{~T~}$}.\r\n\r\nh2. Cerinta\r\n\r\nDandu-se un arbore cu $N$ varfuri, un numar intreg $K$ si valorile {$R{~i~}$}, {$i=1,2,..,N$}, corespunzatoare fiecarui varf, determinati acele varfuri $T$ care pot fi alese drept radacina, pentru care costul $C{~T~}$ este minim (adica {$C{~T~} &le; C{~S~}$}, oricare ar fi $S$ diferit de {$T$}), precum si costul respectiv.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $asmin.in$ se afla doua valori intregi: $N$ si {$K$}. Pe urmatoarele $N-1$ linii se afla cate doua numere intregi {$a b$}, separate printr-un spatiu, avand semnificatia ca exista muchie intre varfurile $a$ si {$b$}. Varfurile sunt numerotate de la $1$ la {$N$}. Pe urmatoarea linie se afla $N$ numere intregi, reprezentand valorile {$R{~i~}$}, {$i=1,2,..,N$}.\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie a fisierului de iesire $asmin.out$ se vor afisa doua valori intregi: $C$ si {$M$}. $C$ reprezinta costul minim posibil al arborelui. $M$ reprezinta numarul de varfuri care pot fi alese drept radacina si pentru care se obtine costul {$C$}. Pe a doua linie se afla $M$ numere intregi separate prin cate un spatiu, scrise in ordine crescatoare, reprezentand numerele varfurilor ce pot fi alese ca radacina astfel incat sa se obtina costul {$C$}.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $2 &le; N &le; 16.000$\r\n* $2 &le; K &le; 1.000$\r\n* $0 &le; R{~i~} &le; K-1$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. asmin.in |_. asmin.out |\r\n| 5 3\r\n1 2\r\n1 3\r\n2 4\r\n2 5\r\n0 1 2 1 0\r\n| 5 2\r\n1 5\r\n| \r\n\r\nh3. Explicatii\r\n\r\nValorile asociate varfurilor celor doi arbori sunt urmatoarele:\r\n$V{~1~}=0   V{~2~}=1  V{~3~}=2   V{~4~}=0   V{~5~}=2$\r\n$V{~1~}=2   V{~2~}=1  V{~3~}=2   V{~4~}=0   V{~5~}=0$\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"asmin\")==\n\n\n',1490,'task: asmin',464,NULL),('problema/parcele','Parcele','2006-11-11 11:23:42','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"parcele\")==\r\n\r\nPe o campie intinsa se afla $N$ copaci situati in puncte de coordonate intregi. Fermierul Ion doreste sa cumpere cateva parcele pe acea campie. Ion poate cumpara numai parcele de forma dreptunghiulara, cu laturile paralele cu axele de coordonate de pe harta zonei, cu dimensiunile intregi fixate ({$DX$} pentru axa $OX$ si $DY$ pentru axa $OY$) si avand colturile situate in puncte de coordonate intregi. Cumpararea unei parcele va trece in proprietatea lui Ion interiorul ei (se considera ca laturile parcelei fac parte din interior).\r\nNumarandu-si banii, Ion s-a hotarat sa cumpere exact DOUA parcele care, evident, sa nu aiba nici un punct comun. Deoarece lui Ion ii plac foarte mult copacii, el isi va alege o modalitate de amplasare a celor doua parcele astfel incat in interiorul lor (inclusiv pe laturi) sa se afle cat mai multi copaci. In acest scop, Ion va cere ajutorul.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care sa determine o modalitate de amplasare a parcelelor, astfel incat Ion sa detina cat mai multi copaci!\r\n\r\nh2. Date de intrare\r\n\r\nFisierul de intrare $parcele.in$ contine:\r\n- pe prima linie doua numere intregi $DX$ si $DY$, reprezentand dimensiunile unei parcele;\r\n- pe cea de a doua linie un numar intreg $N$, reprezentand numarul de copaci;\r\n- pe fiecare dintre urmatoarele $N$ linii cate doua numere intregi $X{~i~}$ si $Y{~i~}$, reprezentand coordonatele copacului cu numarul $i$.\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul de iesire $parcele.out$ veti afisa pe prima linie numarul maxim de copaci pe care ii poate detine Ion.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; DX, DY &le; 99.999$\r\n* $1 &le; N &le; 100.000$\r\n* coordonatele copacilor sunt numere intregi intre $0$ si $99999$ inclusiv\r\n* nu exista doi copaci situati in acelasi punct\r\n* parcelele pot fi plasate oriunde, cu conditia ca sa nu se intersecteze\r\n\r\nh2. Exemplu\r\n\r\n\r\ntable(example). |_. parcele.in |_. parcele.out |\r\n| 2 1\r\n7\r\n0 0\r\n1 0\r\n1 1\r\n3 0\r\n3 1\r\n4 0\r\n1000 1000\r\n| 6 |\r\n\r\nh3. Explicatii\r\n\r\nO solutie posibila este: prima parcela are colturile $(-1, 0)$ si $(1, 1)$ iar a doua parcela are colturile $(3, 0)$ si $(5, 1)$\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"parcele\")==\n\n\n',1490,'task: parcele',466,NULL),('problema/bifo','Bifo','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"bifo\")==\r\n\r\nPentru a-si vindeca rana provocata de Spanul cel Negru, printul Algorel are nevoie de leacul miraculos aflat in posesia vrajitoarei din padurea intunecata. Aceasta i-a promis leacul daca ii rezolva urmatoarea problema, la care ea s-a gandit zadarnic o mie de ani: pornind de la doua cuvinte initiale $A{~1~}$ si $A{~2~}$ si aplicand \"formula bifo\" $A{~n~} = A{~n-2~}A{~n-1~}$ pentru {$3 &le; n$}, se obtin cuvintele $A{~3~}, A{~4~}, A{~5~}$ s.a.m.d. Prin $A{~n-2~}A{~n-1~}$ intelegem concatenarea cuvintelor $A{~n-2~}$ si $A{~n-1~}$ in aceasta ordine. Toate aceste cuvinte ({$A{~1~} A{~2~}, A{~3~} A{~4~}, A{~5~}$} s.a.m.d), sunt la randul lor concatenate, in ordine, formand un sir de caractere infinit denumit sir magic. Formula leacului miraculos are $M$ caractere, pe care vrajitoarea nu le stie. Se stiu insa cele $M$ pozitii din sirul magic in care apar, in ordine, caracterele din formula.\r\n\r\nh2. Cerinta\r\n\r\nCu toata inteligenta lui, Algorel nu poate rezolva aceasta problema. Ajutati-l pe print sa iasa din incurcatura afland formula leacului magic.\r\n\r\nh2. Date de Intrare\r\n\r\nPrimele doua linii ale fisierului $bifo.in$ contin fiecare cate un sir de cel mult $100$ de caractere reprezentand cuvintele $A{~1~}$ (pe prima linie) si respectiv $A{~2~}$ (pe a doua linie). A treia linie contine un numar intreg {$M$}, reprezentand numarul de caractere din formula leacului miraculos. Urmeaza $M$ linii descriind, in ordine, pozitiile din sirul magic unde se gasesc caracterele din formula.\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul de iesire $bifo.out$ va contine pe prima linie un sir de $M$ caractere reprezentand formula leacului miraculos.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; M &le; 100$\r\n* $A{~1~}$ si $A{~2~}$ contin doar litere mici ale alfabetului englez\r\n* Numerotarea pozitiilor din sirul infinit incepe cu $1$\r\n* Cele $M$ pozitii vor fi numere intregi (nu neaparat distincte) de maxim $100$ de cifre\r\n* Pentru $60%$ din teste pozitiile vor fi numere intregi intre $1$ si $1.000.000.000$\r\n* Fiecare linie din fisierul de intrare si din fisierul de iesire se termina cu marcaj de sfarsit de linie\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. bifo.in |_. bifo.out |\r\n| ab\r\ncdx\r\n3\r\n10\r\n4\r\n15\r\n| xdb |\r\n\r\nh3. Explicatii\r\n\r\nPrimele 5 siruri de caractere ob&#254;inute folosind formula bifo sunt:\r\n*ab, cdx, abcdx, cdxabcdx, abcdxcdxabcdx*\r\nConcatenand aceste siruri se ob&#254;ine sirul magic:\r\n{*abcdxabcdxcdxabcdxabcdxcdxabcdx*}...\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"bifo\")==\n\n\n',1490,'task: bifo',425,NULL),('problema/car','Car','2006-11-11 11:23:38','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"car\")==\r\n\r\nIonel a implinit 18 ani si a luat permisul de conducere, azi vrea sa mearga de la el acasa pana la scoala cu masina si singura conditie pe care i-a impus-o tatal sau e aceea de a nu lua foarte multe curbe! Pentru a primi masina si alta data, Ionel vrea sa il impresioneze pe tatal sau si sa mearga pe drumul cel mai putin costisitor din punct de vedere al curbelor. Orasul e reprezentat de o matrice de $N$ linii si $M$ coloane, un element al matricii fiind $0$ daca pe acolo poate trece masina si $1$ daca nu. Masina se poate misca dintr-o celula a matricii in toate cele $8$ celule adiacente, daca ele sunt libere. Costul unui drum de la pozitia initiala la pozitia finala este data de suma costurilor miscarilor. O miscare in directia de mers are costul {$0$}, o miscare la $45$ de grade fata de directia de mers are costul {$1$}, o miscare la $90$ de grade are costul {$2$}, una la $135$ de grade are costul $3$ iar una la $180$ de grade are costul {$4$}. La momentul initial masina poate porni in oricare dintre cele $8$ directii, daca celula din directia respectiva este marcata cu {$0$}.\r\n\r\nh2. Cerinta\r\n\r\nDeterminati pentru Ionel costul minim din punct de vedere al curbelor de la o pozitie initiala la o pozitie finala.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $car.in$ se gasesec doua numere naturale: $N$ (numarul de linii al matricii) si $M$ (numarul de coloane al matricii). Pe urmatoarea linie sunt numerele $Si$ - linia pozitiei initiale a masinii lui Ionel, $Sj$ - coloana pozitiei initiale ale masinii lui Ionel, $Fi$ - linia pozitiei finale, $Fj$ - coloana pozitiei finale. Pe urmatoarele $N$ linii sunt cate $M$ numere de $0$ sau {$1$}.\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie a fisierului de iesire $car.out$ se va gasi costul minim al unui drum de la pozitia initiala la pozitia finala. Daca nu exista nici un drum se va afisa {$-1$}.\r\n\r\nh2. Restrictii\r\n\r\n* $0 &le; N, M &le; 500$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. car.in |_. car.out |\r\n| 5 5\r\n1 1 1 4\r\n0 1 1 0 1\r\n1 0 1 0 1\r\n0 1 1 1 0\r\n1 0 1 0 1\r\n1 1 0 1 1\r\n| 9 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"car\")==\n\n\n',1490,'task: car',243,NULL),('problema/trapeze','Trapeze','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"trapeze\")==\r\n\r\nDaca te joci cu $N$ obiecte identice de forma rotunda si incerci sa formezi diferite forme cu toate obiectele, apar figuri interesante. Una dintre figurile cele mai frumoase este trapezul. El este format din mai multe linii (cel putin una). Pe prima linie stau $A$ obiecte ({$A &ge; 1$}). Pe urmatoarea linie (daca exista) stau $A+1$ obiecte, si tot asa pana se folosesc toate obiectele. De exemplu, cu $15$ obiecte putem forma $4$ trapeze distincte:\r\n\r\n# {$&nbsp;&nbsp;&nbsp;&nbsp;*$}\r\n{$&nbsp;&nbsp;&nbsp;* *$}\r\n{$&nbsp;&nbsp;* * *$}\r\n{$&nbsp;* * * *$}\r\n{$* * * * *$}\r\n# {$&nbsp;&nbsp;* * * *$}\r\n{$&nbsp;* * * * *$}\r\n{$* * * * * *$}\r\n# {$&nbsp;&nbsp;* * * * * * *$}\r\n{$&nbsp;* * * * * * * *$}\r\n# {$* * * * * * * * * * * * * * *$}\r\n\r\nEste important ca toate piesele sa fie folosite in constructia oricarui trapez si toate liniile sa fie complete. Este foarte usor sa determini pentru un numar dat de obiecte care este numarul total de trapeze distincte ce se pot forma. De exemplu, pentru $15$ obiecte numarul total de trapeze este $4$. Mai greu este sa determini care este numarul minim de obiecte necesare pentru a putea forma in total exact $K$ trapeze distincte.\r\n\r\nh2. Cerinta\r\n\r\nPentru valoarea lui $K$ data, determinati numarul minim de obiecte necesare pentru a forma exact $K$ trapeze.\r\n\r\nh2. Date de intrare\r\n\r\nFisierul de intrare $trapeze.in$ va contine pe prima linie numarul natural $K$.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $trapeze.out$ va contine o singura linie pe care va fi scris numarul minim de obiecte necesare pentru a forma in total exact $K$ trapeze.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; K &le; 100$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. trapeze.in |_. trapeze.out |\r\n|4|15|\r\n|5|81|\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"trapeze\")==\n\n\n',1490,'task: trapeze',420,NULL),('problema/barman','Barman','2006-11-11 11:23:38','2009-09-10 08:13:30','==Include(page=\"template/taskheader\" task_id=\"barman\")==\r\n\r\nPaftenie a decis sa se faca barman. Inainte de asta trebuie sa dovedeasca abilitate in manevrarea bauturilor. Barul lui Paftenie este alcatuit din $N$ camere aliniate in cerc. In fiecare camera se afla un pahar cu bautura, fiecare bautura avand o anumita valoare (cuprinsa intre $1$ si $2.000.000.000$). El trebuie sa mute bauturile dintr-o camera in alta astfel incat la sfarsit, bauturile sa fie sortate dupa camere. Daca la sfarsit in camera $i$ se afla o bautura cu valoarea $a{~i~}$, sirul valorilor $a{~1~},a{~2~}...a{~N~}$ se considera sortat daca exista $1 &le; i &le; N$ astfel incat $a{~i~} &le; a{~i+1~} &le; ... &le; a{~N~} &le; a{~1~} &le; ... &le; a{~i-1~}$ (sirul este circular). In orice moment, Paftenie poate tine pe tava cel mult doua pahare. Pentru deplasarea bauturilor, poate efectua urmatoarele mutari:\r\n\r\n* poate lua un pahar din camera in care se afla si sa il aseze pe tava (il costa $10$ secunde)\r\n* poate lasa un pahar intr-o camera in care nu se afla nici o bautura (il costa $10$ secunde)\r\n* se poate deplasa din camera $i$ in camera $j$ avand pe tava $c$ pahare ({$0 &le; c &le; 2$}) (il costa $c*|i-j|$ secunde)\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l pe Paftenie sa sorteze paharele intr-un timp minim!\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $barman.in$ este dat numarul $N$ al bauturilor. Pe urmatoarea linie se afla $N$ intregi reprezentand valorile bauturilor - al $i$-lea numar reprezinta valoarea bauturii aflate initial in camera $i$ ({$a{~i~}$}).\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul $barman.out$ va contine pe prima linie un singur numar reprezentand timpul minim de sortare a bauturilor.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 600$\r\n* In orice moment, in afara de paharele care le are Paftenie pe tava, intr-o camera poate exista maxim un pahar\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. barman.in |_. barman.out |\r\n| 4\r\n1 5 2 2\r\n| 42 |\r\n\r\nh3. Explicatii\r\n\r\n$o 5 2 2$ merge in camera $1$ si pune paharul de acolo pe tava ({$10$}s)\r\n$o 5 2 2$ merge din camera $1$ in camera $2$ cu un pahar pe tava ({$1$}s)\r\n$o o 2 2$ pune pe tava paharul din camera $2$ ({$10$}s)\r\n$o 1 2 2$ asaza pe masa din camera $2$ paharul cu bautura de valoare $1$ ({$10$}s)\r\n$o 1 2 2$ se intoarce in camera $1$ cu un pahar pe tava ({$1$}s)\r\n$5 1 2 2$ asaza pe masa din camera $1$ paharul cu bautura de valoare $5$ ({$10$}s)\r\n&#8594; $42$ de secunde\r\nsirul este sortat deoarece {$1 &le; 2 &le; 2 &le; 5 (a2 &le; a3 &le; a4 &le; a1)$}\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"barman\")==\r\n\r\n\r\n',1490,'task: barman',303,NULL),('problema/stramosi','Stramosi','2006-11-11 11:23:34','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"stramosi\")==\r\n\r\nFamilia lui Gigel este foarte numeroasa, avand exact $N$ membri. Fiecare membru stie cine este stramosul lui direct, mai putin cativa membri care sunt foarte batrani si nu mai tin minte nici macar cine a fost stramosul lor direct. Gigel, fiind o fire curioasa a facut un inventar al familiei sale, in sensul ca a numerotat fiecare membru cu un numar distinct intre 1 si $N$ si stie de asemenea pentru fiecare membru, care este stramosul lui direct (daca acesta exista). Curiozitatea lui este si mai mare, in sensul ca isi pune $M$ intrebari de forma: _\"Care este al $P$-lea stramos al membrului cu numarul $Q$?\"_.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care raspunde corect la toate cele M intrebari ale lui Gigel.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linia a fisierului $stramosi.in$ se afla numerele $N$ si $M$. Pe a doua linie se afla $N$ numere intregi, reprezentand stramosii tuturor membrilor, incepand cu membrul $1$ si terminand cu membrul $N$. Daca un membru nu are stramos, atunci in fisier se va afla numarul $0$. Pe urmatoarele $M$ linii se afla perechi de numere $Q$ si $P$, reprezentand o intrebare de forma: _\"Care este al $P$-lea stramos al membrului cu numarul $Q$?\"_.\r\n\r\nh2. Date de iesire\r\n\r\nPe fiecare din cele $M$ linii ale fisierului $stramosi.out$ se vor afla raspunsurile la intrebari, adica numerele de ordine al stramosilor (sau $0$ daca identitatea stramosului nu este cunoscuta)\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 250 000$\r\n* $1 &le; M &le; 300 000$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. stramosi.in |_. stramosi.out |\r\n|13 7\r\n0 1 2 2 4 1 6 0 8 8 10 10 12\r\n5 2\r\n3 2\r\n7 1\r\n1 3\r\n13 3\r\n9 2\r\n11 1\r\n|2\r\n1\r\n6\r\n0\r\n8\r\n0\r\n10\r\n|\r\n\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"stramosi\")==\n\n\n',1490,'task: stramosi',37,NULL),('problema/joc','Joc','2006-11-11 11:23:34','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"joc\")==\r\n\r\nGicu si Nicu, olimpici la informatica si buni prieteni, mereu incearca sa imbine activitatile lor cu informatica. Spre exemplu, cand se plictisesc in ore ei joaca un joc, bazat pe urmatoarele reguli:\r\n\r\n* fie o matrice cu numere intregi cu $N$ linii si $M$ coloane\r\n* fiecare jucator muta alternativ un jeton plasat pe un element din matrice\r\n* o mutare consta in plasarea jetonului pe o alta pozitie si adaugarea valorii din matrice de pe pozitia respectiva la scorul jucatorului care a facut mutarea; odata plasat jetonul pe o pozitie, jucatorul urmator poate sa mute jetonul doar pe o alta pozitie din dreptunghiul format de coltul stanga-sus si pozitia curenta a matricei\r\n* jocul se termina cand un jucator ajunge cu jetonul in coltul stanga-sus al matricei\r\n* la inceputul jocului, ambii jucatori au scor {$0$}, iar jucatorul care incepe alege pozitia initiala a jetonului\r\n\r\nh2. Cerinta\r\n\r\nPresupunand ca fiecare din cei doi joaca optim, si ca Gicu va incepe jocul, determinati pozitia initiala a jetonului, astfel incat diferenta de scor intre Gicu si Nicu sa fie maxima!\r\n\r\nh2. Date de Intrare\r\n\r\nPrima linie a fisierului $joc.in$ contine doua numere intregi $N$ si {$M$}, separate prin cate un spatiu, care reprezinta numarul de linii si coloane ale matricii. Urmatoarele $N$ linii contin cate $M$ numere intregi, separate prin cate un spatiu, care descriu matricea.\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul $joc.out$ va contine trei numere intregi separate prin cate un spatu: diferenta maxima de scor intre Gicu si Nicu si linia si coloana unde se va plasa jetonul la inceputul jocului.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N, M &le; 1.000$\r\n* Valorile din matrice sunt cuprinse in intervalul [{$-1.000, 1.000$}]\r\n* Liniile sunt numerotate de la $1$ la {$N$}, iar coloanele de la $1$ la $M$\r\n* Prin joc optim se intelege ca Gicu va incerca sa maximizeze diferenta de scor, in timp ce Nicu va incerca sa o minimizeze\r\n* Daca exista mai multe pozitii initiale pentru care se obtine diferenta maxima, atunci se va alege cea in care numarul liniei este cel mai mic, iar in caz de egalitate cea in care numarul coloanei este cel mai mic\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. joc.in |_. joc.out |\r\n| 1 6\r\n2 1 3 4 0 5\r\n| 3 1 6 | \r\n\r\nh3. Explicatii \r\n\r\nIncepand din ({$1, 6$}) jocul optim este: Gicu ia {$5$}, Nicu ia {$4$}, Gicu ia {$2$}. \r\nOrice alta pozitie initiala a jetonului ar fi dus la obtinerea unei diferente de scor mai mica.\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"joc\")==\n\n\n',1490,'task: joc',43,NULL),('problema/biti','Biti','2006-11-11 11:23:33','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"biti\")==\r\n\r\nGigel este pasionat de informatica, si mai ales de cifrele $0$ si {$1$}; asa de mult, incat a atribuit fiecarui din cei $2^N^$ prieteni ai lui cate o eticheta, sub forma unui sir de biti de lungime {$N$}. Toate etichetele sunt distincte intre ele.\r\nGigel s-a gandit intr-o zi ca vrea sa construiasca o eticheta pentru el insusi, de lungime cat mai mica, care sa contina o singura data, ca o subsecventa, fiecare din cele $2^N^$ etichete ale prietenilor lui.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care determina eticheta lui Gigel, de lungime minima.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $biti.in$ se va gasi numarul $N$\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie a fisierului de iesire $biti.out$ se va gasi lungimea sirului. Pe a doua linie se va afisa un sir de biti $0$ sau $1$ care vor reprezenta eticheta gasita.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 20$\r\n* Daca exista mai multe solutii de lungime minima, se va afisa cea minima din punct de vedere lexicografic\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. biti.in |_. biti.out |\r\n| 3\r\n| 10\r\n0001011100 |\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"biti\")==\n\n\n',1490,'task: biti',30,NULL),('problema/zero','Zero','2006-11-11 11:23:35','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"zero\")==\r\n\r\nSe considera numai numerele de $L$ cifre scrise intr-o baza $B$ ({$2 &le; B < L &le; 20$}), in care prima cifra (cea mai semnificativa) este diferita de $0$.\r\n\r\nh2. Cerinta:\r\n\r\nDandu-se doua numere $P$ si $Q$ ({$2 &le; P,Q &le; L-1$}), se cere:\r\n\r\na) cate numere exista cu cel mult $P$ cifre $0$ (zero) consecutive.\r\n\r\nb) cate numere exista cu cel putin $Q$ cifre $0$ (zero) consecutive.\r\n\r\nh2. Date de intrare\r\n\r\nPrima linie a fisierului de intrare $zero.in$ contine numerele $L$, $B$, $P$ si $Q$, separate prin spatii.\r\n\r\nh2. Date de iesire\r\n\r\nPrima linie a fisierului de iesire $zero.out$ contine numarul cerut la punctul a), in timp ce pe a doua linie a fisierului se va afla numarul cerut la punctul b).\r\n\r\nh2. Exemplu:\r\n\r\ntable(example). |_. zero.in |_. zero.out |\r\n|3 2 1 2\r\n|3\r\n1|\r\n\r\n\r\nPentru cel mult o cifra de zero avem numerele $101$, $110$ si $111$, iar pentru cel putin 2 de 0 consecutivi avem numarul $100$.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"zero\")==\r\n\r\n\r\n',1490,'task: zero',48,NULL),('problema/cmmdc','CMMDC','2006-11-11 11:23:33','2008-11-15 16:19:39','==Include(page=\"template/taskheader\" task_id=\"cmmdc\")==\r\n\r\nh2. Date de intrare\r\n\r\nDatele de intrare se citesc din fisierul $cmmdc.in$:\r\n\r\n* pe prima linie: un numar natural, $a$\r\n* pe a doua linie: un numar natural, $b$\r\n\r\nh2. Date de iesire\r\n\r\nDatele de iesire se tiparesc in fisierul $cmmdc.out$\r\n\r\n* pe prima linie: cel mai mare divizor comun pentru $a$ si $b$. Daca $a$ si $b$ sunt numere prime intre ele, atunci se va tipari $0$\r\n\r\nh2. Restrictii\r\n\r\n* Rezultatul nu va depasi niciodata valoarea 30000\r\n\r\nh2. Exemplu\r\n\r\n\r\ntable(example). |_. cmmdc.in |_. cmmdc.out |\r\n|8 12| 4 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"cmmdc\")==\n\n\n',1490,'task: cmmdc',28,NULL),('problema/flip','Jocul Flip','2006-11-11 11:23:33','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"flip\")==\r\n\r\nGigel a descoperit un nou joc pe care l-a numit \"Flip\". Acesta se joaca pe o tabla dreptunghiulara de dimensiuni $N*M$ care contine numere intregi. Fiecare linie si fiecare coloana are un comutator care schimba starea tuturor elementelor de pe acea linie sau coloana, inmultindu-le cu {$-1$}. Scopul jocului este ca pentru o configuratie data a tablei de joc sa se actioneze asupra liniilor si coloanelor astfel incat sa se obtina o tabla cu suma elementelor cat mai mare.\r\n\r\nh2. Cerinta\r\n\r\nDandu-se o configuratie pentru tabla \"Flip\", realizati un program care sa determine suma maxima pe care Gigel o poate obtine.\r\n\r\nh2. Date de Intrare\r\n\r\nPrima linie a fisierului $flip.in$ contine doua numere intregi $N$ si {$M$}, separate prin cate un spatiu, care reprezinta dimensiunea tablei. Urmatoarele $N$ linii contin cate $M$ numere intregi seperate prin cate un spatiu care descriu configuratia tablei de joc.\r\n\r\nh2. Date de Iesire\r\n\r\nPrima linie a fisierului $flip.out$ contine un numar care va reprezenta suma maxima pe care Gigel o poate obtine comutand liniile si coloanele tablei de joc.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N, M &le; 16$\r\n* Tabla de joc contine numere intregi din intervalul [{$-1.000.000,1.000.000$}]\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. flip.in |_. flip.out |\r\n| 5 3\r\n4 -2 2\r\n3 -1 5\r\n2 0 -3\r\n4 1 -3\r\n5 -3 2\r\n| 28 |\r\n\r\nh3. Explicatie\r\n\r\nSe comuta coloana a doua si linia a treia.\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"flip\")==\n\n\n',1490,'task: flip',29,NULL),('problema/fractii','Fractii','2006-11-11 11:23:33','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"fractii\")==\r\n\r\n\r\n\r\nGigel, intr-o zi cand isi facea temele la matematica, s-a apucat sa scrie pe o foaie de hartie, un sir de fractii ireductibile de forma $^P^/{~Q~}$ cu $1 &le; P,Q &le; N$, unde $N$ este un numar natural ales de el. De exemplu, pentru $N = 4$ el a obtinut urmatorul sir:\r\n\r\np=. $^1^/{~1~}  ^1^/{~2~}  ^1^/{~3~}  ^1^/{~4~}  ^2^/{~1~}  ^2^/{~3~}  ^3^/{~1~}  ^3^/{~2~}  ^3^/{~4~}  ^4^/{~1~}  ^4^/{~3~}$\r\n\r\nGigel s-a apucat apoi sa numere cate fractii a obtinut pentru $N = 4$ si a vazut ca sunt $11$.\r\n\r\nh2. Cerinta\r\n\r\nFiind dat un numar natural $N$, sa se determine cate fractii sunt in sirul de fractii construit dupa regulile de mai sus.\r\n\r\nh2. Date de intrare\r\n\r\nFisierul de intrare $fractii.in$ contine pe prima linie numarul natural $N$.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $fractii.out$ trebuie sa contina un numar natural pe prima linie care reprezinta cate fractii sunt in sir.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 1.000.000$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. fractii.in |_. fractii.out |\r\n| 3 | 7 |\r\n| 4 | 11 |\r\n| 5 | 19 |\r\n| 10| 63 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"fractii\")==\r\n\r\n',1490,'task: fractii',33,NULL),('problema/perm','Permutari','2006-11-11 11:23:33','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"perm\")==\r\n\r\nO permutare de lungime $N$ este un sir de elemente distincte din multimea {${1,2,3 ... N}$}. Spunem ca o permutare are $K$ maxime daca exista fix $K$ pozitii distincte in permutare, pentru care elementul curent este mai mare decat toate elementele din stanga lui.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care determina cate permutari de lungime $N$ cu $K$ maxime exista.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierul $perm.in$ se vor gasi numerele $N$ si {$K$}, separate prin cate un spatiu.\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie a fisierul $perm.out$ se va gasi numarul de permutari de lungime $N$ cu $K$ maxime.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; K &le; N &le; 200$\r\n\r\nExemple\r\n\r\ntable(example). |_. perm.in |_. perm.out |\r\n| 3 2 | 3 |\r\n| 5 3 | 35 |\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"perm\")==\n\n\n',1490,'task: perm',31,NULL),('problema/fact','Factorial','2006-11-11 11:23:34','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"fact\")==\r\n\r\nSe da un numar intreg $P$. Sa se gaseasca cel mai mic numar natural strict pozitiv $N$ pentru care $N!$ are exact $P$ cifre de $0$ la sfarsit.\r\n\r\nSe stie ca {$N! = 1 * 2 * 3 * .... * (N - 1) * N$}.\r\n\r\nh2. Date de intrare\r\n\r\nFisierul $fact.in$ va contine pe prima linie numarul intreg $P$.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie a fisierului $fact.out$ se va scrie acel numar $N$ care indeplineste condiitle impuse sau $-1$ daca nu exista un astfel de $N$.\r\n\r\nh2. Restrictii\r\n\r\n* $0$ &le; $P$ &le; $10^8^$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. fact.in |_. fact.out |\r\n| 0&nbsp; | 1  |\r\n| 2 | 10 |\r\n|10 | 45 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"fact\")==\n\n\n',1490,'task: fact',32,NULL),('problema/datorii','Datorii','2006-11-11 11:23:34','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"datorii\")==\r\n\r\nTatal si mama lui Gigel se ocupa cu vanzarea de sisteme de calcul. Afacerea s-a dovedit a fi foarte profitabila datorita unui sistem incredibil de creditare a clientilor: un client care cumpara un calculator in ziua $X$ (in acest moment au trecut $N$ zile de la infiintarea magazinului, zilele se numeroteaza de la 1 la $N$, {$0<X&le;N$}) poate returna banii oricand doreste acesta, neexistand o limita de timp impusa. Astfel, aproape in fiecare zi, la magazinul familiei se prezinta diversi clienti care achita integral sau partial un sistem de calcul cumparat in zilele anterioare. Deoarece vor sa inceapa o noua afacere, Mama si Tata doresc sa il insarcineze pe Gigel cu administrarea magazinului de calculatoare. Pentru aceasta Gigel trebuie sa indeplineasca o conditie esentiala: in orice moment al sederii lui la magazin el poate fi solicitat prin telefon de catre tatal sa raspunda cat mai repede la urmatoarea familie de intrebari: ce suma de bani a ramas inca neachitata luand in considerare achizitiile facute de clienti in zilele $P$, $P+1$, {$P+2$}... {$Q-1$}, {$Q$} ({$0<P&le;Q&le;N$}). Se stie ca niciodata nu s-au cumparat doua calculatoare in aceeasi zi. Ajuta-l pe Gigel sa demonstreze parintilor ca poate administra magazinul.\r\n\r\nh2. Cerinta\r\n\r\nSe dau: $N$, $M$, un sir de numere {$A{~1~}$}, {$A{~2~}$}... {$A{~N~}$} si $M$ operatii. {$A{~i~}$} ({$1&le;A{~i~}&le;1000$}, {$1&le;i&le;N$}) reprezinta suma de bani inca neachitata pentru o comanda efectuata in ziua $i$. O operatie poate fi de doua feluri:\r\n\r\n* $A$ (achitare - se scade o valoare din suma restanta a unei zile anume)\r\n* $B$ (interogare - se cere suma tuturor sumelor restante ale unui interval de zile). Programul trebuie sa scrie in fisierul de iesire suma ceruta de fiecare operatie de tip $B$ in momentul interogarii.\r\n\r\nh2. Date de intrare\r\n\r\nFisierul $datorii.in$ va contine pe prima linie numerele $N$ si $M$. Pe urmatoarea linie se afla valorile sirului {$A{~1~}$}, {$A{~2~}$}... {$A{~N~}$} separate prin cate un spatiu. Urmatoarele $M$ linii descriu operatiile (achitari sau interogari) efectuate in ordinea data. Fiecare linie care descrie o operatie incepe cu un cod binar (un numar intreg cu valoarea 0 sau 1) si continua cu 2 numere intregi.\r\n\r\n* Un cod 0 urmat de doua numere intregi $T$, $V$ ({$1&le;T&le;N$}, {$1&le;V&le;1000$}) reprezinta o operatie de tip $A$ (in momentul respectiv s-a achitat o valoare $V$ din suma restanta a zilei $T$)\r\n* Un cod 1 urmat de doua numere intregi $P$, $Q$ ({$1&le;P&le;Q&le;N$}) o operatie de tip $B$ (se cere suma tuturor sumelor restante din zilele $P$, {$P+1$}, {$P+2$}... $Q$ in momentul respectiv).\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul $datorii.out$ se vor scrie pe cate o linie sumele cerute de fiecare operatie de tip $B$ (sumele se cer in ordinea aparitiei operatiilor in fisierul de intrare).\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 15 000$\r\n* {$0 < M &le; 100 000$}\r\n* In orice moment, {$A{~i~}$} ({$1&le;i&le;N$}) este nenegativ.\r\n\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. datorii.in|_. datorii.out|\r\n|6 6\r\n1 3 2 0 0 10\r\n1 3 6\r\n1 1 4\r\n0 3 1\r\n1 1 6\r\n0 6 2\r\n1 1 6\r\n|12\r\n6\r\n15\r\n13|\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"datorii\")==\n\n\n',1490,'task: datorii',34,NULL);
 INSERT INTO `ia_textblock` VALUES ('problema/copaci','Copaci','2006-11-11 11:23:34','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"copaci\")==\r\n\r\nMacarie, dupa ce a muncit o viata intreaga, se decide la batranete sa se retraga pe o insula pentru a-si gasi linistea interioara si a se dedica naturii. Astfel el cumpara o insula pe care cultiva pomi fructiferi. Insula poate fi reprezentata ca un poligon (nu neaparat convex) intr-un sistem de axe de coordonate pozitive. Pomii sunt plantati doar la coordonate naturale.\r\n\r\nh2. Cerinta\r\n\r\nMacarie este interesat de numarul de copaci pe care il poate planta strict in interiorul insulei. In acest scop el va furnizeaza copacii care determina insula (varfurile poligonului).\r\n\r\nh2. Date de Intrare\r\n\r\nPrima linie a fisierului copaci.in contine numarul intreg $N$ de copaci de pe linie. Urmatoarele $N$ linii contin cate doua numere intregi seperate prin cate un spatiu care descriu coordonatele celor $N$ pomi date intr-o anumita ordine (trigonometrica sau orara).\r\n\r\nh2. Date de Iesire\r\n\r\nPrima linie a fisierului copaci.out contine un numar care va reprezenta numarul de copaci strict in interiorul insula.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $3 &le; N &le; 100.000$\r\n* Coordonatele copacilor au valori intregi din intervalul [{$0, 2.000.000$}]\r\n* pot fi dati mai mult de $2$ copaci pe o latura a \"poligonului\" insulei (cum se vede si in exemplu, penultimul copac)\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. copaci.in |_. copaci.out |\r\n| 13\r\n3 1\r\n6 3\r\n9 2\r\n8 4\r\n9 6\r\n9 9\r\n8 9\r\n6 5\r\n5 8\r\n4 4\r\n3 5\r\n2 4\r\n1 3\r\n| 21 |\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"copaci\")==\n\n\n',1490,'task: copaci',38,NULL),('problema/pietre','Pietre','2006-11-11 11:23:34','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"pietre\")==\r\n\r\nMacarie si Petronela joaca un joc foarte interesant care, spera ei, le va dezvolta inteligenta si mai mult. Astfel ei au in fata doua gramezi de pietre (cu $A$ respectiv $B$ pietre fiecare). Jocul se desfasoara alternativ (Macarie incepe), iar la un moment dat un jucator poate lua un numar oarecare de pietre dintr-o gramada sau poate lua acelasi numar de pietre din ambele gramezi. Pierde cel care nu mai poate lua pietre.\r\n\r\nh2. Cerinta\r\n\r\nVa trebui sa aflati castigatorul pentru $T$ jocuri stiind ca mereu Macarie incepe jocul.\r\n\r\nh2. Date de Intrare\r\n\r\nPrima linie a fisierului $pietre.in$ contine numarul $T$ de teste. Urmatoarele $T$ linii contin cate 2 numere intregi $A$ si $B$ seperate prin cate un spatiu care descriu numarul de pietre din cele doua gramezi.\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul $pietre.out$ va contine $T$ linii corespunzatoare celor $T$ teste cu valoarea $1$ daca la testul respectiv castiga Macarie si $2$ daca invinge Petronela.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; A, B &le; 1.000.000$\r\n* $1 &le; T &le; 10$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. pietre.in |_. pietre.out |\r\n| 2 \r\n1 2\r\n2 3 | 2\r\n1 |\r\n\r\nh3. Explicatii\r\n\r\nIn primul test Macarie poate lua $1$ piatra din oricare gramada, $2$ pietre din a doua gramada sau o piatra din ambele gramezi, in toate cazurile Petronela putand lua toate pietrele ramase castigand jocul.\r\nIn testul $2$ Macarie castiga luand $2$ pietre din a doua gramada si Petronela va pierde conform acelorasi considerente de la exemplul $1$.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"pietre\")==\n\n\n',1490,'task: pietre',39,NULL),('problema/prim','Numere Prime','2006-11-11 11:23:35','2009-08-01 19:03:25','==Include(page=\"template/taskheader\" task_id=\"prim\")==\r\n\r\nGheorghe a invatat la scoala despre numere prime. A invatat ca un numar este prim, daca se divide doar cu $1$ si cu el insusi({$1$} nu este considerat numar prim). A aflat ca exista algoritimi foarte eficienti care pot determina daca un numar este prim sau nu, in timp chiar sub polinomial. Din pacate acesti algoritmi sunt foarte complicati, si Gheorghe s-a gandit la o aproximare. Idea lui este sa consideri un numar prim daca nu se divide la primele $K$ numere prime.\r\n\r\nh2. Cerinta\r\n\r\nDemonstreaza ca ideea lui Gheorghe este doar o aproximare. Dandu-se un numar $K$, afla cel mai mic numar $N$ care nu este divizibil cu primele $K$ numere prime, dar nu este prim.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie din fisierul $prim.in$ se va afla numarul $K$.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie a fisierului $prim.out$ se va gasi numarul $N$ cautat.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; K &le; 100.000$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. prim.in |_. prim.out |\r\n| 1\r\n| 9 |\r\n\r\nh3. Explicatii\r\n\r\n$9$ nu este divizibil cu $2$ si nu este nici prim.\r\n\r\ntable(example). |_. prim.in |_. prim.out |\r\n| 3\r\n| 49 |\r\n\r\nh3. Explicatii\r\n\r\nPrimele $3$ numere prime sunt $2, 3, 5$. Numerele care nu sunt divizibile cu $2, 3$ sau $5$ sunt : $7, 11, 13, 17, 19, 23, 31, 37, 41, 47, 49, .. 49$ este cel mai mic numar care nu este prim.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"prim\")==\r\n\r\n\r\n',1792,'task: prim',49,NULL),('problema/color','Color','2006-11-11 11:23:42','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"color\")==\r\n\r\nConsideram un graf complet cu $N$ varfuri in care muchiile sunt colorate fie in rosu, fie in negru. In acest graf se pot forma triunghiuri monocromatice (trei varfuri conectate prin muchii colorate cu aceeasi culoare).\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care sa determine pentru un graf colorat dat numarul de triunghiuri monocromatice.\r\n\r\nh2. Date de Intrare\r\n\r\nFisierul de intrare $color.in$ contine:\r\n\r\ntable(example). | N S \r\n x{~1~} y{~1~} \r\n x{~2~} y{~2~} \r\n ...\r\n x{~s~} y{~s~}\r\n| N - numarul de varfuri din graf, S - numarul de muchii rosii\r\n x{~i~} y{~i~} - extrmitatile celei de a i-a muchii rosii |\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul de iesire $color.out$ contine pe prima linie numarul de triunghiuri monocromatice.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 4.000$\r\n* $1 &le; S &le; 500.000$\r\n* In fisierul de intrare nu apare de mai multe ori aceeasi muchie.\r\n* Muchiile care nu apar in fisierul de intrare sunt colorate, evident, in negru.\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. color.in |_. color.out |\r\n| 4 4\r\n1 2\r\n2 3\r\n4 3\r\n4 2 \r\n| 1 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"color\")==\n\n\n',1490,'task: color',463,NULL),('problema/cutii','Cutii','2006-11-11 11:23:36','2010-03-21 13:46:48','==Include(page=\"template/taskheader\" task_id=\"cutii\")==\r\n\r\n==include(page=\"template/badtests\")==\r\n\r\nSe dau $N$ cutii paralelipipedice prin dimensiunile lor ({$X, Y$} si {$Z$}). Se stie ca o cutie se poate pune in alta doar daca toate dimensiunile ei sunt strict mai mici cele ale cutiei in care va fi bagata. Se cere numarul maxim de cutii ce pot fi selectate din cele $N$ astfel incat ele sa poata fi \"cuibarite\" (o cutie va contine o cutie care la randul ei va contie o alta s.a.m.d. pana la cea mai mica care nu va mai contine nimic).\r\n\r\nh2. Date de Intrare\r\n\r\nPrima linie a fisierului $cutii.in$ va contine $N$ si $T$, reprezentand numarul de cutii si respectiv numarul de teste care vor urma. Pentru fiecare din cele $T$ teste vor urma cate $N$ linii continand $3$ numere reprezentand dimensiunile fiecarei cutii.\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul $cutii.out$ va contine $T$ linii pe fiecare linie un numar reprezentand numarul maxim de cutii ce pot fi alese pentru fiecare test.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 3500$\r\n* $1 &le; T &le; 100$\r\n* Dimensiunile cutiilor sunt date astfel fiecare dimensiune in parte (din cele trei posibile) ia toate valorile de la $1$ la $N$ in fiecare test din cele $T$ (valorile unei dimensiuni a cutiilor dintr-un test vor forma o permutare a numerelor de la $1$ la $N$).\r\n* Timpul de executie a fost ales astfel incat $20%$ din el va fi folosit pentru citire si restul de $80%$ pentru calcularea rezultatelor\r\n* $40%$ din teste vor avea $N &le; 100$ iar restul vor avea $N = 3500$ si $T = 100$\r\n* O cutie nu poate fi intoarsa in nici un fel (dimensiunile ei isi vor pastra ordinea)\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. cutii.in |_. cutii.out |\r\n| 3 2\r\n1 1 1\r\n2 2 2\r\n3 3 3\r\n1 2 2\r\n2 1 1\r\n3 3 3\r\n| 3\r\n2 |\r\n\r\nh3. Explicatii\r\n\r\nPentru primul set de cutii se selecteaza toate cutiile deoarece cutia cu numarul 2 se poate pune in cutia 3 iar cutia 1 in cea de-a doua. Pentru cel de-al doilea set se selecteaza cutiile 1 si 3 sau cutiile 2 si 3 neexistand posibilitatea de a le lua pe toate. \r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"cutii\")==\r\n\r\n\r\n',2028,'task: cutii',97,NULL),('problema/secv3','Secventa 3','2006-11-11 11:23:36','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"secv3\")==\r\n\r\n==include(page=\"template/badtests\")==\r\n\r\nGigel este o persoana cu o imaginatie foarte bogata, mai ales cand doarme! Intr-o noapte a visat ca are de indeplinit o sarcina foarte bizara: trebuie sa aleaga o secventa (adica un subsir de elemente care apar pe pozitii consecutive in sirul initial) din $N$ elemente pentru care se cunosc costul si timpul. Secventa aleasa trebuia sa fie de lungime minim $L$ si maxim $U$, iar suma costurilor elementelor secventei impartita la suma timpurilor elementelor secventei sa fie maxima.\r\n\r\nh2. Cerinta\r\n\r\nIn scurt timp, visul lui Gigel s-a transformat intr-un cosmar deoarece nu poate sa rezolve sarcina! Scrieti un program care sa-l ajute!\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie in fisierul de intrare $secv3.in$ se afla numere $N, L$ si $U$ separate prin cate un spatiu. Pe cea de a doua linie se vor gasi $N$ numere naturale reprezentand costurile elementelor secventei, iar pe cea de a treia linie se vor gasi $N$ numere naturale reprezentand timpurile elementelor secventei.\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie din fisierul de iesire $secv3.out$ se va gasi un numar real cu prezicie de doua zecimale, reprezentand valoarea maxima a sumei costurilor elementelor din secventa impartita la suma timpurilor elementelor din secventa.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; L &le; U &le; N &le; 30.000$\r\n* Costul si timpul unui element sunt numere naturale din intervalul $[1, 1.000]$\r\n* Numarul scris in fisierul de iesire va fi considerat corect doar daca valoarea absoluta a diferentei dintre rezultatul tau si cel al comisiei este mai mica sau egala cu $10^-2^$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. secv3.in |_. secv3.out |\r\n| 5 1 2\r\n1 1 3 2 5\r\n4 2 5 3 6 | 0.83 |\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"secv3\")==\n\n\n',1490,'task: secv3',91,NULL),('problema/barbar','Barbar','2006-11-11 11:23:37','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"barbar\")==\r\n\r\nPaftenie barbarul este un renumit aventurier. A condus razboaie, a descoperit comori, a cucerit cetati si inimile domnitelor. Insa de aceasta data a fost capturat de catre dusmanii sai cei mai temuti si aruncat intr-o temnita. Temnita este de fapt un grid de dimensiune {$R*C$}. In anumite celule exista dragoni, unele sunt ocupate de pereti, iar altele sunt libere. Paftenie trebuie sa iasa din temnita mergand numai prin celule libere (o celula are maxim 4 vecini) , si asta stand cat mai departe de fiorosii dragoni ale caror flacari ii pot deteriora vestimentatia (astfel incat minima din distantele pana la cel mai apropiat dragon din fiecare din celulele traseului sau sa fie maxim).\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l pe barbarul Paftenie sa iasa din temnita, determinand un traseu astfel incat minima din distantele pana la cel mai apropiat dragon din fiecare din celulele traseului sau sa fie maxim!\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $barbar.in$ sunt date doua numere intregi $R$ si {$C$}, reprezentand numarul liniilor, respectiv al coloanelor temnitei. Pe urmatoarele $R$ linii se afla cate $C$ caractere, neseparate prin spatii, cu urmatoarele semnificatii:\r\n$.$ celula libera\r\n$*$ perete\r\n$D$ dragon\r\n$I$ punctul de plecare al lui Paftenie\r\n$O$ iesirea din temnita\r\n\r\nh2. Date de Iesire \r\n\r\nFisierul de iesire $barbar.out$ va contine pe prima linie un singur numar, reprezentand valoarea maxima pentru minima din distantele pana la cel mai apropiat dragon din fiecare din celulele traseului. In caz ca nu exista solutie se va afisa {$-1$}.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; R, C &le; 1.000$\r\n* Se garanteaza ca in temnita exista cel putin un dragon\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. barbar.in |_. barbar.out |\r\n| 10 10\r\n..........\r\n.I....D...\r\n..........\r\n..D...D...\r\n.*........\r\nD*........\r\n*...D.....\r\n..****....\r\n...O......\r\n..........\r\n| 2 | \r\n\r\nh3. Explicatii\r\n\r\nO solutie posibila:\r\n$..........$\r\n$.I{*ooo*}.D...$\r\n$....{*o*}.....$\r\n$..D.{*o*}.D...$\r\n$.*..{*oo*}....$\r\n$D*...{*ooooo*}$\r\n${@*@}...D....{*o*}$\r\n$..****...{*o*}$\r\n$...O{*oooooo*}$\r\n$..........$\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"barbar\")==\n\n\n',1490,'task: barbar',217,NULL),('problema/traseu','Traseu','2006-11-11 11:23:36','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"traseu\")==\r\n\r\nGigel s-a mutat intr-un oras nou! Pentru a se familiariza cu noile imprejurimi a cumparat harta orasului si a observat ca este alcatuita din $M$ strazi de diferite lungimi, cu sens unic si $N$ intersectii de strazi. Gigel a luat harta si a inceput sa alcauiasca un traseu care porneste dintr-o intersectie anume, trece prin fiecare strada cel putin o data, si revine in intersectia de unde a pornit. Desi dorinta lui de explorare este mare, conditia lui fizica nu este tocmai buna, astfel ca vrea sa gasesasca un traseu in care suma lungimilor strazilor parcurse este minima.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care gaseste un traseu de lungime minima in orasul lui Gigel.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului $traseu.in$ se gasesc numerele $N$ si $M$ separate prin cate un spatiu. Pe urmatoarele $M$ linii se vor gasi triplete de numere $i j k$ cu semnificatia ca exista o strada de la intersectia cu numar $i$ la intersectia cu numar $j$ de lungime $k$.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie din fisierul $traseu.out$ se va afisa un singur numar natural reprezentand lungimea minima a traseului lui Gigel.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 60$\r\n* Lungimile strazilor sunt numere naturale din intervalul $[1, 10 000]$\r\n* Daca intre doua intersectii $i$ si $j$ exista o strada, atunci cu singuranta nu va exista o strada si intre intersectiile $j$ si $i$\r\n* Se garanteaza ca exista cel putin un traseu in oras care trece prin fiecare strada cel putin o data si incepe si se termina in aceeasi intersectie\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. traseu.in |_. traseu.out |\r\n|6 8\r\n1 2 3\r\n2 3 1\r\n3 1 2\r\n1 4 4\r\n4 6 2 \r\n6 1 5\r\n4 5 1\r\n5 1 6\r\n|28 |\r\n\r\nh3. Explicatii\r\n\r\nTraseul ales este: $(1,2,3,1,4,6,1,4,5,1)$.\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"traseu\")==\n\n\n',1490,'task: traseu',92,NULL),('problema/lacate','Lacate','2006-11-11 11:23:36','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"lacate\")==\r\n\r\n\r\nPentru a pazi subiectele de la concursul preONI, comisia care a propus problemele, formata din $N$ persoane, s-a gandit sa pastreze subiectele intr-un seif. Pentru inchiderea seifului sunt necesare un anumit numar de lacate, pentru fiecare lacat existand un anumit numar de chei care-l pot deschide. Distributia cheilor printre membrii comisiei trebuie sa respecte urmatoarele conditii:\r\n\r\n* oricare doi membri detin acelasi numar de chei\r\n* fiecare membru detine chei de la lacate distincte\r\n* toate lacatele seifului se vor putea deschide numai in prezenta oricarui grup format din cel putin $N-1$ membrii\r\n\r\nh2. Cerinta\r\n\r\nStiind ca nici o cheie nu poate deschide doua lacate distincte, determinati numarul minim de lacate necesare, precum si o distributie a cheilor care sa respecte conditiile de mai sus.\r\n\r\nh2. Date de intrare\r\n\r\nIn fisierul de intrare $lacate.in$ se va gasi numarul natural $N$, reprezentand numarul membrilor comisiei.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie din fisierul $lacate.out$ se va gasi doua numere naturale $L$ si $C$ reprezentand numarul minim de lacate necesare, respectiv numarul de chei pe care le va avea fiecare membru. Pe urmatoarele $N$ linii se vor gasi cheile pe care le detine fiecare membru, astfel incat pe linia $i+1$ se vor gasi $C$ numere reprezentand cheile pe care le detine membrul $i$; cheile sunt numerotate cu numere de la $1$ la $L$, fiecare numar reprezentand numarul lacatului pe care il deschide cheia respectiva.\r\n\r\nh2. Restrictii\r\n\r\n* $2 &le; N &le; 256$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. lacate.in |_. lacate.out |\r\n| 2\r\n| 1 1\r\n1\r\n1 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"lacate\")==\n\n\n',1490,'task: lacate',93,NULL),('problema/bool','Bool','2006-11-11 11:23:36','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"bool\")==\r\n\r\nHaralambie a primit la scoala o tema destul de dificila. El trebuie sa evalueze o expresie logica. Aceasta expresie contine variabile (litere mari ale alfabetului englez de la $A$ la $Z$), constante ({$TRUE$} si {$FALSE$}), paranteze rotunde {$($} si {$)$}, si operatorii logici $NOT$, $AND$ si $OR$. $NOT$ are prioritatea cea mai mare, $OR$ are prioritatea cea mai mica. Initial toate variabilele au valoarea $FALSE$. Lui Haralambie ii place sa evalueze expresii, dar variabilele isi mai schimba uneori valoarea si expresia trebuie reevaluata. Speriat din aceasta cauza, a decis sa apeleze la ajutorul vostru!\r\n\r\nDupa cum este mentionat mai sus o expresie logica este definita in unul din modurile urmatoare:\r\n\r\ntable. |_. expresie |_. explicatie |\r\n| $TRUE$ | $&nbsp;$ |\r\n| $FALSE$ | $&nbsp;$ |\r\n| $c$     |  $c - litera mare a alfabetului englez$ |\r\n| $(e)$   |  $e - expresie logica$ |\r\n| $NOT e$ |  $e - expresie logica$ |\r\n| $e1 AND e2$ | $e1 si e2 - expresii logice$ |\r\n| $e1 OR e2$ | $e1 si e2 - expresii logice$ |\r\n\r\nh2. Cerinta\r\n\r\nSe da expresia ce trebuie evaluata si modificarile ce apar la valorile variabilelor. Pentru fiecare modificare de variabila trebuie reevaluata expresia si afisat rezultatul ({$1$} pentru adevarat si $0$ pentru fals).\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $bool.in$ este scrisa expresia logica definita ca mai sus. Pe a doua linie este dat numarul $N$ de modificari ale variabilelor. Pe linia a treia sunt date $N$ caractere intre $A$ si $Z$, reprezentand variabilele a caror valoare este modificata.\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul $bool.out$ va contine o singura linie de lungime $N$. Pentru fiecare modificare de variabila se va afisa un caracter reprezentand valoarea logica a expresiei: $1$ pentru adevarat si $0$ pentru fals.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 100$\r\n* $1 &le; Lungime expresiei &le; 1.000$\r\n* Toate literele care apar in expresie vor fi majuscule\r\n* Nu va exista mai mult de un spatiu intre doua caractere din expresie\r\n* O variabila care are valoarea $TRUE$ isi schimba valoarea in $FALSE$, iar o variabila $FALSE$ se schimba in $TRUE$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. bool.in |_. bool.out |\r\n| A AND ((B OR NOT C) OR ((TRUE)))\r\n4\r\nABCA\r\n| 1110 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"bool\")==\n\n\n',1490,'task: bool',94,NULL),('problema/atac','Atac','2006-11-11 11:23:36','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"atac\")==\r\n\r\nIn tara Arboreea lucrurile au iesit de sub control. OTPB (Organizatia Terorista Petrica Bomba) a hotarat sa atace doua orase din aceasta tara deoarece liderul organizatiei, Petrica, a pierdut alegerile prezidentiale din anul 2004. Tara are $N$ orase, numerotate de la $1$ la $N$, iar reteaua oraselor si strazile dintre aceastea formeaza un arbore (graf neorientat conex ce nu contine cicluri). OTPB stie pentru fiecare strada cate bombe trebuie sa utilizeze pentru a o scoate din uz. Acum se pune problema determinarii numarului cel mai mic de bombe pe care trebuie sa-l utilizeze OTPB pentru ca intre cele doua orase alese (considerate de importanta majora in Arboreea) sa nu mai existe drum intre ele dupa bombardament. Cum importanta oraselor se schimba pe parcusul evolutiei tarii, OTPB vrea sa stie numarul minim de bombe pentru atacul asupra mai multor perechi de orase, mai exact $M$. Totusi se doreste comunicarea usoara a acestor $M$ perechi intre organizatiile teroriste din tara. Astfel, nu se poate transmite intreaga lista a celor $M$ perechi de orase asupra carora se doreste efectuarea unui atac deoarece reteaua de legatura dintre organizatii este cam inceata la capitolul trasmiterea datelor. Totusi s-a gasit o solutie: stiind prima pereche de orase $X$ si $Y$ asupra carora se va efectua un atac si numarul minim de bombe $Z$ ce trebuie utilizate in cazul atacului in orasele $X$ si $Y$, urmatoarea pereche de orase, a doua, se determina utilizand relatiile:\r\n\r\n$X\' = (X*A + Y*B) mod N + 1$\r\n$Y\' = (Y*C + Z*D) mod N + 1$\r\n\r\nA treia pereche de orase se determina utilizand in formula perechea a doua si numarul minim de bombe ce trebuie utilizate pentru a o ataca, a patra din a treia si asa mai departe. Asadar este suficienta cunoasterea primei perechi de orase si a numerelor $A, B, C, D$ pentru a determina toate cele $M$ perechi. De asemenea, din aceeasi cauza - transmiterea greoaie a datelor - OTPB vrea sa afle rezultatele doar pentru ultimele $P$ perechi de orase, considerate suficiente pentru a verifica corectitudinea programului dumneavoastra. Scrieti un program pentru organizatia lui Petrica care calculeaza numarul minim de bombe pentru atacul ultimelor $P$ perechi de orase din cele $M$ daca vreti sa mai ramaneti in viata !\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului $atac.in$ se afla trei numere reprezentand numarul de orase, numarul de perechi de orase pentru care organizatia vrea sa afle numarul minim de bombe in cazul unui atac asupra lor si numarul $P$ de perechi pentru care programul vostru trebuie sa afiseze raspunsul. Pe urmatoarele $N-1$ linii se afla cate doua numere naturale $U$, $V$ cu semnificatia: exista o strada de la orasul $U$ la orasul $i$ ({$i$} este indicele liniei care va lua valori de la $2$ la $N$) pentru care OTPB trebuie sa utilizeze $V$ bombe pentru a o scoate din uz. Pe urmatoarea linie se afla $6$ numere $X, Y, A, B, C, D$ cu semnificatia din enunt.\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul atac.out va avea $P$ linii reprezentand numarul minim de bombe ce trebuie utilizat pentru a ataca ultimele $P$ perechi de orase.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 32.000$\r\n* $0 < P < M &le; 500.000$\r\n* $P &le; 10.000$\r\n* $0 &le; A, B, C, D &le; 10.000$\r\n* numarul de bombe pentru a scoate din uz o strada este un numar natural mai mic decat $100.000$\r\n* OTPB nu va scoate din uz nici o strada; se doreste sondarea terenului si nimic mai mult, momentan; deci pentru fiecare pereche de orase din cele $M$ se considera ca reteaua de strazi este intacta (nici o strada nu este bombardata).\r\n* Se vor acorda puncte pe un test doar daca toate cele $P$ numere din fisierul de iesire sunt corect aflate.\r\n* Este clar ca pentru a afla corect cele $P$ numere trebuie sa calculati numarul minim de bombe pentru toate cele $M$ perechi de orase.\r\n* Nu va bazati pe faptul ca perechile de orase se vor repeta iar setul de perechi distincte este mic! OTPB vrea sa studieze cat mai multe perechi de orase asa ca numerele $A, B, C, D$ vor fi inteligent alese pentru a genera cat mai multe perechi distincte intre cele $M$.\r\n* Daca $X$ coincide cu $Y$ atunci raspunsul este $0$\r\n* Pentru $40%$ din teste $N$ va fi mai mic sau egal $1000$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. atac.in |_. atac.out |\r\n| 7 3 2\r\n1 1\r\n2 2\r\n2 2\r\n1 3\r\n5 3\r\n5 2\r\n6 7 1 1 1 1\r\n| 1\r\n1 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"atac\")==\n\n\n',1490,'task: atac',98,NULL),('problema/tribute','Tribute','2006-11-11 11:23:36','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"tribute\")==\r\n\r\nDin nou cineva trebuie sa cumpere teren... De data asta este Viviana si terenul pe care vrea sa-l cumpere e in forma de dreptunghi cu laturile pararele cu axele sistemului de coordonate. Se cunoaste pozitia a $N$ obiective situate in puncte de coordanate intregi pe care Viviana vrea sa le aibe cat mai aproape de terenul sau. Dupa ce si-a stabilit pozitia terenului ea incepe sa calculeze distanta totala de la terenul ei la cele $N$ obiective. Pentru aceasta ea defineste distanta de la un obiectiv la terenul sau ca fiind distanta Manhattan minima de la obiectiv la orice punct de coordonate intregi care se afla pe propietatea ei sau pe marginile acesteia (bineinteles, conform acestei definitii, obiectivele aflate pe propietatea Vivianei sau pe marginile acesteia se vor afla la distanta 0 fata de terenul sau). Distanta totala de la propietatea la obiective este suma distantelor pentru fiecare obiectiv in parte.\r\n\r\nh2. Cerinta\r\n\r\nAflati pentru Viviana distanta totala minima pe care o poate obtine daca ea vrea sa cumpere un teren de dimensiuni ({$DX$},{$DY$}).\r\n\r\nh2. Date de intrare\r\n\r\nFisierul de intrare $tribute.in$ contine pe prima linie numerele $N$, $DX$ si $DY$, separate prin spatii. Pe urmatoarele $N$ linii se afla pozitia fiecarui obiectiv in plan.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $tribute.out$ trebuie sa contina un singur numar reprezentand distanta totala minima pe care o poate obtine Viviana prin plasarea inteligenta a terenului.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 50.000$\r\n* $1 &le; DX, DY &le; 50.000$\r\n* Coordonatele obiectivelor sunt numere naturale din intervalul $[0, 50 000]$\r\n* Nu exista mai multe obiective in acelasi punct\r\n* Coordonatele terenului nu pot fi inversate\r\n* Terenul se poate plasa oriunde in plan\r\n* Distanta Manhattan intre doua puncte ({$x$}, {$y$}) si ({$z$}, {$t$}) se defineste ca fiind $|x-z| + |y-t|$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. tribute.in |_. tribute.out |\r\n|5 1 1\r\n4 4\r\n0 0\r\n4 1\r\n0 1\r\n4 3\r\n|10 |\r\n\r\nh3. Explicatie\r\n\r\nColtul din stanga jos al terenului se plaseaza in punctul (3, 1). Distantele de la teren la obiective sunt: 2, 4, 0, 3 si respectiv 1. Distanta totala este 2+4+0+3+1 = 10, care este cea minima.\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"tribute\")==\n\n\n',1490,'task: tribute',99,NULL),('problema/coins','Coins','2006-11-11 11:23:36','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"coins\")==\r\n\r\nCapitanul Paftenie este un batran lup de mare. A trecut prin numeroase aventuri si a cutreierat lumea intreaga. Ajuns insa la batranete, isi petrece majoritatea timpului jucand un joc de strategie cu secundul sau. Jocul consta dintr-o tabla orizontala cu *22* de patratele, pe care sunt asezati galbeni (maxim unul in fiecare patratel, reprezentand nave de razboi). Fiecare muta pe rand. O mutare consta din alegerea unui galben si deplasarea sa in primul patratel liber din stanga sa. Daca la un pas Paftenie nu mai poate muta nici o piesa (toti galbenii sunt aliniati pe pozitii consecutive, incepand cu primul patratel), atunci castiga toti galbenii de pe tabla. Paftenie muta intotdeauna primul. Are probleme financiare si din acest motiv ar vrea sa stie numarul maxim de galbeni care ii poate castiga dupa un numar de jocuri.\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l pe Paftenie sa afle rezultatul!\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $coins.in$ este dat numarul $N$ al jocurilor. Pe urmatoarele $N$ linii se afla cate $22$ de numere ({$0$} sau $1$ - $0$ reprezinta patratel liber, $1$ patratel cu galben pe el). Numerele sunt separate prin cate un spatiu.\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul $coins.out$ va contine pe prima linie un numar intreg $M$: valoarea maxima gasita.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 100.000$\r\n* secundul joaca intotdeauna optim\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. coins.in |_. coins.out |\r\n| 4 \r\n 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \r\n 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \r\n 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \r\n 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \r\n| 5 | \r\n\r\nh3. Explicatie\r\n\r\nPaftenie castiga primul si al treilea joc. Astfel, el strange 5 galbeni. \r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"coins\")==\n\n\n',1490,'task: coins',136,NULL),('problema/zaharel','Zaharel','2006-11-11 11:23:36','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"zaharel\")==\r\n\r\nZaharel este un mare pasionat al culorilor, astfel incat a luat o foaie de matematica cu $N$ linii si $N$ coloane si a desenat $M$ buline rosii sau albastre, in casutele foii de mate, in diferite pozitii. Dupa ce a desenat punctele a observat ca exista cel putin un punct rosu pe fiecare linie si cel putin un punct albastru pe fiecare coloana si astfel si-a pus urmatoarea problema: poate sa construiasca doua poligoane (nu neaparat convexe) care sa aiba acelasi numar de varfuri, unul din poligoane sa aiba in varfuri doar buline rosii iar celalalt doar buline albastre, iar centrul de greutate al celor doua poligoane sa fie acelesi? Zaharel nu este baiat pretentios deci nu are nimic impotriva daca cel doua poligoane se intersecteaza sau daca sunt unul in interiorul celuilalt! Trebuie sa fie respectate doar conditiile mentionate mai sus. Centrul de greutate al unui poligon cu varfurile {$(x{~0~},y{~0~})$}{$(x{~1~},y{~1~})$}...{$(x{~n~},y{~n~})$} este considerat ca fiind punctul de coordonate {$((x{~0~} + x{~1~} + ... + x{~n~})/(n+1), (y{~0~} + y{~1~} + ... y{~n~})/(n+1))$}.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care pentru o foaie de mate desenata ca mai sus de Zaharel, determina cele doua poligoane.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului $zaharel.in$ se gasesc numerele naturale $N$ si $M$. Urmatoarele $M$ linii sunt de forma $i j c$ unde $i$ si $j$ sunt numere naturale reprezentand linia, respectiv coloana unei buline, iar $c$ este un caracter reprezentand culoarea ({$R$} pentru rosu si $A$ pentru albastru)\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie a fisierului de iesire $zaharel.out$ sa va afisa un numar, reprezentand cate varfuri are fiecare poligon. Pe urmatoarea linie se vor afisa punctele care descriu poligonul cu varfurile in buline rosii, intr-o ordine oarecare. Pe a treia linie se vor afisa punctele care descriu poligonul cu varfurile in buline albastre, intr-o ordine oarecare.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $6 &le; N &le; 1 000$\r\n\r\n* $2*N &le; M &le; 100 000$\r\n\r\n* Daca nu exista solutie se va afisa -1 in fisierul de iesire\r\n\r\n* Daca exista mai multe solutii se va afisa una singura\r\n\r\n* Poligoanele rezultate trebuie sa aiba minim 2 varfuri\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. zaharel.in |_. zaharel.out |\r\n|6 12\r\n1 3 R\r\n2 4 R\r\n3 1 R\r\n4 6 R\r\n5 2 R\r\n6 4 R\r\n2 1 A \r\n4 2 A\r\n3 3 A\r\n1 4 A\r\n6 5 A\r\n6 6 A\r\n|3\r\n1 3 2 4 3 1\r\n1 4 2 1 3 3|\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"zaharel\")==\n\n\n',1490,'task: zaharel',137,NULL),('problema/sobo','Sobo','2006-11-11 11:23:37','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"sobo\")==\r\n\r\nPetrica, satul de munca pe santier, vrea sa faca de ceva mai apropiat capacitatii sale intelectuale. Astfel si-a luat o cutie cu $N$ sobolani si face experimente pe ei. Printre altele el a scos harta genetica a fiecarui sobolan, care consta intr-o secventa binara de lungime $L$. Printre sobolani se afla unul mai special, cel mai inteligent dintre ei, pe care Gigel, prietenul lui Petrica, il vrea cu orice pret. Petrica insa nu vrea sa renunte la sobolanul inteligent atat de usor si il pune pe Gigel la urmatoarea proba: ii da hartile genetice ale tuturor sobolanilor, fara sa-i spuna care este cel special. Gigel are voie sa puna intrebari de genu: \"Ce valoare are harta sobolanului inteligent in pozitia $x$ ?\" dar raspunsul are un pret, Petrica dandu-i lista preturilor tuturor pozitiilor. Asadar Gigel va trebui sa ghiceasca sobolanul destept pe baza raspunsurilor lui Petrica care sunt de forma: \"Harta sobolanului inteligent are in pozitia $x$ valoarea $y$\" unde $y$ este $0$ sau $1$. Gigel vrea sa stie care e pretul minim pe care il plateste, considerand cel mai defavorabil caz (Petrica va alege raspunsurile astfel incat costul sa fie cat mai mare posibil).\r\n\r\nh2. Cerinta\r\n\r\nGigel va plati considerabil (cu 100 de puncte) pe cel care ii va face un program care sa calculeze acest cost.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie in fisierul de intrare $sobo.in$ se afla numerule $N$, $L$ separate prin cate un spatiu reprezentand numarul de sobolani si lungimea hartilor genetice ale acestora. Pe urmatoarele $N$ linii se afla cate un sir de $L$ biti (nedespartiti de spatii) reprezentand harta unui sobolan. Pe ultima linie se afla $L$ numere separate prin spatii reprezentand costul raspunsului pentru fiecare pozitie.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie din fisierul de iesire $sobo.out$ se va gasi un numar intreg reprezentand costul minim in cel mai defavorabil caz pentru Gigel.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 15$\r\n* $1 &le; L &le; 1000$\r\n* Costurile raspunsurilor sunt numere intregi din intervalul $[1, 1 000 000]$\r\n* Nu exista sobolani cu harti genetice identice\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. sobo.in |_. sobo.out |\r\n| 4 3\r\n101\r\n000\r\n011\r\n010\r\n2 6 7 | 13 |\r\n\r\nh3. Explicatii\r\n\r\nCostul minim 13 (in cel mai defavorabil caz) este obtinut astfel: Gigel intreaba care este valoarea hartii sobolanului inteligent in pozitia 2 si Petrica ii raspunde 1 acesta fiind cel mai defavorabil caz (daca raspunsul lui Petrica ar fi fost 0 urma intrebarea lui Gigel despre valoarea in pozitia 1 si sobolanul ar fi fost identificat cu un costul 6 + 2 = 8). Asadar niciunul dintre primii doi sobolani nu este cel inteligent. Gigel mai trebuie sa afle care din ultimii doi sobolani este cel inteligent si mai cere informatii despre pozitia 3 din harta sobolanului inteligent. Indiferent de raspuns sobolanul inteligent va fi descoperit.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"sobo\")==\n\n\n',1490,'task: sobo',138,NULL),('problema/boom','Boom','2006-11-11 11:23:37','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"boom\")==\r\n\r\nVa las sa ghiciti cine este protagonistul acestei probleme. Nu este foarte greu de imaginat ca numele lui va fi tot Petrica. Ce face el de data aceasta este ceva cu totul aparte: se joaca cu sobolanul cel ghidus. Acesta din urma este localizat intr-o galerie subterana care se prezinta ca o succesiune de $N$ camere dispuse in linie si care sunt numerotate de la $1$ la $N$ in ordinea parcurgerii lor de la un capat la celalalt. Petrica nu stie unde este localizat sobolanul dar vrea cu orice pret sa-l rada de pe fata pamantului. Astfel, el poate detona bombe otravitoare in unele din camerele galeriei (uneori chiar in mai multe simultan) pentru a omori sobolanul. Daca acesta este intr-una din camerele gazate moare pe loc, daca nu camera nu pateste nimic si sobolanul poate circula prin ea imediat dupa detonarea bombei. Lucrurile stau in felul urmator: cei doi inamici joaca in mod cinstit astfel ca dupa ce Petrica detoneaza un set bombe care vor exploda simultan, sobolanul, daca nu a murit, se va muta intr-una din camerele vecine celei in care se afla (camerele de la capete au o singura camera vecina). Petrica a alcatuit un plan de atac compus din $M$ sarje. Pentru fiecare sarja se cunosc pretul realizarii ei si camerele gazate daca ea este pusa in practica. La fiecare pas Petrica va alege doar una din cele $M$ sarje pentru a gaza anumite camere.\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l pe Petrica sa gaseasca o strategie de cost minim in urma careia sobolanul va fi omorat indiferent de pozitia initiala a acestuia.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie in fisierul de intrare $boom.in$ se afla doua numere intregi separate de un singur spatiu $N$ si {$M$}, reprezentand numarul de camere ale galeriei si numarul de sarje. Pe urmatoarele $M$ linii sunt date informatiile cu privire la fiecare sarja (ele sunt numerotate de la $1$ la $M$ in ordinea in care se gasesc in fisierul de intrare). Astfel, pe fiecare linie sunt doi intregi $P$ si {$Q$}, reprezentand pretul si numarul de camere gazete in sarja. Urmeaza $Q$ numere ({$Q$} nu este mai mare decat {$4$}) reprezentand camerele gazate.\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie din fisierul de iesire $boom.out$ se va gasi un numar intreg reprezentand costul minim al unei strategii in urma careia sobolanul va fi mort. Pe urmatoarele linie se afla un numar $T$ reprezentand numarul de sarje care il va omori in mod sigur. Urmatoarele $T$ linii contin numerele sarjelor utilizate de Petrica (aceasta sunt date in ordinea in care au fost utilizate).\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 20$\r\n* $1 &le; M &le; 50$\r\n* Sobolanul nu poate sta pe loc\r\n* Daca exista mai multe solutii cu acelasi cost minim se poate afisa oricare dintre ele\r\n* O sarja poate fi folosita de mai multe ori\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. boom.in |_. boom.out |\r\n| 3 2\r\n1 2 1 3\r\n2 1 2\r\n| 2\r\n2\r\n1\r\n1 |\r\n\r\nh3. Explicatii\r\n\r\nPetrica detoneaza foloseste de doua ori sarja 1. Oriunde s-ar afla sobolanul acesta va muri: daca este in camera 1 sau 3 va muri dupa prima gazare daca se afla in a doua camera va fi obligat sa se mute intr-un din camerele 1 si 3 la urmatorul pas, fiind astfel prins de cea dea doua gazare. Costul total este 2 cel mai mic posibil.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"boom\")==\n\n\n',1490,'task: boom',140,NULL),('problema/petsoft','PetSoft','2006-11-11 11:23:37','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"petsoft\")==\r\n\r\nPetrica detine o companie de software numita PETSOFT cu care este lider in domeniu. Secretul succesului sta in modul de organizare interna din aceasta firma. Fiecare angajat are asociat un numar distinct de la $1$ la $N$ si se stie pentru fiecare angajat cine este seful sau direct (angajatul numarul $1$ este chiar Petrica si nu are nici un sef). Mai exact relatiile dintre angajatii firmei formeaza un arbore cu radacina in nodul $1$. Firma este invitatata la un targ international de software unde isi va prezenta oferta. La conferinta se vor prezenta din partea firmei un numar de echipe (stabilit de Petrica) de cate doi angajati. Petrica nu este interasat de numarul de echipe ci de valoarea lor. Pentru asta el stabileste urmatoarele regula: angajatii $x$ si $y$ pot fi trimisi la conferinta impreuna daca $x$ este seful direct al lui $y$ sau daca $x$ si $y$ au acelasi sef iar valoarea echipei formate din cei doi este $|x - y|$. De asemenea este stiut faptul ca Petrica (angajatul numarul {$1$}) nu va fi incadrat in nici o echipa, el fiind managerul firmei. Valoarea totala e echipelor va fi suma valorilor tuturor echipelor.\r\n\r\nh2. Cerinta\r\n\r\nSe cauta un programator capabil sa stabileasca modul de formare a echipelor astfel incat valoarea totala a echipelor sa fie maxima. Odata gasit, el va fi angajat direct intr-un loc de frunte in ierarhia firmei. Poti fi chiar tu acel programator, dar trebuie sa demostrezi ca esti alegerea buna dezvoltand un program care poate calcula valoarea totala maxima a echipelor pe care firma le va trimite la conferinta.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie in fisierul de intrare $petsoft.in$ se afla un numar intreg $N$ reprezentand numarul de angajati ai firmei. Pe urmatoarele $N-1$ linii sunt date informatiile cu privire la ierhia firmei: pe linia $i$ se afla seful angajatului cu numarul $i$.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie din fisierul de iesire $petsoft.out$ se va gasi un numar intreg reprezentand valoarea totala maxima a echipelor ce vor fi trimise la conferinta.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 1000$\r\n* Fiecare angajat poate fi incadrat in maxim o echipa.\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. petsoft.in |_. petsoft.out |\r\n| 5\r\n1\r\n4\r\n2\r\n4\r\n| 4 |\r\n\r\nh3. Explicatii\r\n\r\nSe vor forma echipele 2-4 si 3-5.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"petsoft\")==\n\n\n',1490,'task: petsoft',141,NULL),('problema/text','Text','2006-11-11 11:23:37','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"text\")==\r\n\r\nDezamagit de rezultatele sale la ultimul concurs, Paftenie a renuntat la programare si s-a concentrat strict asupra muncii laborioase, dar care implica mai putin efort intelectual. De aceasta data, el primeste un text si trebuie sa calculeze lungimea medie a cuvintelor textului, un cuvant fiind definit ca o secventa continua maximala de caractere ale alfabetului englez (\'a\' .. \'z\' , \'A\' .. \'Z\'). Definim lungimea medie = (lungimea totala a cuvintelor textului) / (numarul de cuvinte ale textului).\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care ii rezolva problema lui Paftenie.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare $text.in$ se gaseste textul dat.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $text.out$ va contine pe prima linie un singur intreg, reprezentand partea intreaga a lungimii medii a cuvintelor textului.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* Dimensiunea fisierului de intrare este de cel mult 1MB\r\n* Fisierul de intrare va contine doar litere mari si mici, cifre, spatii si simboluri (adica nu va contine caractere speciale)\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. text.in|_. text.out|\r\n|- Lasa-ma in pace, ca am invatat azi noapte toata ziua!|3|\r\n\r\n_Explicatie_: Lungimea totala a cuvintelor textului = 41, numarul de cuvinte = 11 => [41 / 11] = 3.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"text\")==\n\n\n',1490,'task: text',214,NULL),('problema/trapez','Trapez','2006-11-11 11:23:37','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"trapez\")==\r\n\r\nZaharel este un tip care se plictiseste repede la scoala. Intr-o zi cu soare, cand n-avea chef sa asculte ce preda profesorul de matematica s-a apucat sa deseneze puncte pe o foaie de matematica. El a desenat $N$ astfel de puncte si apoi si-a pus urmatoarea intrebare: cate trapeze se pot forma cu varfurile in aceste puncte? Un trapez este un patrulater convex cu cel putin doua laturi paralele.\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l pe Zaharel sa determine cate trapeze poate forma cu cele $N$ puncte de pe foaia de matematica.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare $trapez.in$ se gaseste numarul natural $N$. Pe urmatoarele $N$ linii se gasesc perechi de numerele naturale reprezentand coordonatele punctelor.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie din fisierul de iesire $trapez.out$ se va gasi numarul de trapeze care se pot forma.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $4 &le; N &le; 1 000$\r\n* Coordonatele punctelor sunt numere intregi din intervalul $[0, 2 000 000 000]$\r\n* Oricare trei puncte sunt necoliniare\r\n* Paralelogramele trebuie numarate de doua ori, fiindca sunt trapeze dupa doua orientari\r\n* Incercati sa evitati folosirea de numere reale in implementare deoarece pot cauza erori de precizie\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. trapez.in |_. trapez.out|\r\n|5\r\n0 0 \r\n0 1\r\n1 4\r\n2 0 \r\n3 1\r\n|1|\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"trapez\")==\n\n\n',1490,'task: trapez',215,NULL),('problema/adn','ADN','2006-11-11 11:23:37','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"adn\")==\r\n\r\nO problema importanta in ultimii ani in biologie a fost gasirea secventei de ADN pentru om. Un lant ADN este format din doua spirale de molecule, fiecare molecula fiind denumita pe scurt A, G, C sau T. Deci un lant ADN poate fi reprezentat ca un sir de caractere din multimea A, G, C si T. Poblema cercetatorilor este ca ei nu pot gasi intreaga secventa ADN cu metode chimice sau biologice dar pot determina sectiuni din ea. Dupa ce au determinat o serie de sectiuni, un sir de molecule care are probabilitatea cea mai mare sa fie apropiat de secventa reala este sirul cel mai scurt de caractere care contine toate sectiunile determinate ca subsecvente!\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care sa-i ajute pe cercetatori sa determine cel mai scurt sir de caractere care contine toate sectiunile determinate ca subsecvente.\r\n\r\nh2. Date de Intrare\r\n\r\nFisierul de intrare $adn.in$ va contine pe prima linie va contine numarul $N$ de secvente ADN iar pe urmatoarele $N$ linii cate un sir de caractere ce contine numai literele A,G,C si T.\r\n\r\nh2. Date de Iesire \r\n\r\nFisierul de iesire $adn.out$ va contine o singura linie cu cel mai scurt sir ce contine secventele din intrare ca subsecvente.\r\n\r\nh2. Restrictii\r\n\r\n* $2 &le; N &le; 18$\r\n* Lungimea fiecarui sir este mai mica de $30.001$\r\n* Daca exista mai multe solutii de lungime minima se va afisa oricare\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. adn.in |_. adn.out |\r\n| 5\r\nGGATATAAAAAC\r\nGATAACCGCGCAGTGATGAGA\r\nTGATGAGATGGGGATATAAAA\r\nAGATAGATGATAACCGCGCAGT\r\nATGGGGATATAAAAACTTTTTT\r\n| AGATAGATGATAACCGCGCAGTGATGAGATGGGGATATAAAAACTTTTTT |\r\n\r\nh3. Explicatie\r\n\r\np(pre).. AGATAGATGATAACCGCGCAGT\r\n        {*GATAACCGCGCAGT*}GATGAGA\r\n                     {*TGATGAGA*}TGGGGATATAAAA\r\n                            {*ATGGGGATATAAAA*}ACTTTTTT\r\n                                {*GGATATAAAAAC*}\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"adn\")==\n\n\n',1490,'task: adn',216,NULL),('problema/iepuri','Iepuri','2006-11-11 11:23:37','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"iepuri\")==\r\n\r\nZaharel a facut o noua pasiune, si anume vrea sa aiba iepuri! Astfel, el s-a dus intr-o zi (o vom numi ziua 0) la magazine si si-a cumparat $X$. Se stie ca iepuri se inmultesc in fiecare zi, astfel incat in ziua 1 el avea $Y$ iepuri, iar in ziua 2 $Z$ iepuri. Baiat perspicace, Zaharel a observat ca, incepand cu ziua 3, numarul de iepuri din fiecare zi depinde de numarul de iepuri din ultimele trei zile astfel: se aduna de $A$ ori numarul de iepuri care existau cu o zi in urma, de $B$ ori numarul de iepuri de acum doua zile si de $C$ ori numarul de iepuri de acum trei zile.\r\n\r\nh2. Cerinta\r\n\r\nSa se determine restul impartirii numarului de iepuri pe care ii va avea Zaharel in ziua $N$ la $666013$.\r\n\r\nh2. Date de Intrare \r\n\r\nFisierul de intrare $iepuri.in$ contine mai multe seturi de date. Pe prima linie se va gasi un numar intreg $T$ reprezetand numarul de seturi de date pentru care se cere raspunsul. Pe urmatoarele $T$ linii se vor gasi cate sapte numere intregi, in ordinea urmtoare: $X Y Z A B C N$.\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul de iesire $iepuri.out$ va contine $T$ linii, cate un numar intreg pe fiecare linie reprezentand raspunsul pentru un set de date. Raspunsul de pe linia $i$ va trebui sa corespunda cu setul de date de pe linia $i+1$ din fisierul de intrare.\r\n\r\nh2. Restrictii\r\n\r\n* $0 &le; T &le; 100$\r\n* $1 &le; X &le; Y &le; Z &le; 10.000$\r\n* $1 &le; A, B, C &le; 1.000$\r\n* $3 &le; N &le; 2.000.000.000$\r\n* Se acorda punctaj pentru un test doar daca s-a dat raspunsul corect pentru toate seturile de date\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. iepuri.in |_. iepuri.out |\r\n| 2\r\n1 1 2 1 1 1 5\r\n1 2 3 1 2 3 4 | 13\r\n22 |\r\n\r\nh3. Explicatie\r\n\r\nPrimul set de date:\r\nIn ziua $3$ va avea $1*2+1*1+1*1=4$ iepuri\r\nIn ziua $4$ va avea $1*4+1*2+1*1=7$ iepuri\r\nIn ziua $5$ va avea $1*7+1*4+1*2=13$ iepuri\r\nAl doilea set de date:\r\nIn ziua $3$ va avea $1*3+2*2+3*1=10$ iepuri\r\nIn ziua $4$ va avea $1*10+2*3+3*2=22$ iepuri\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"iepuri\")==\n\n\n',1490,'task: iepuri',218,NULL),('problema/secv','Secv','2006-11-11 11:23:38','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"secv\")==\r\n\r\nGheorghe a dat peste o noua problema de informatica la care are nevoie de un pic de ajutor!\r\n\r\nh2. Cerinta\r\n\r\nDandu-se un sir de $N$ numere naturale, aflati lungimea minima a unei subsecvente care contine un subsir strict crescator, iar acest subsir contine toate numere din sirul initial o singura data. Daca nu exista o astfel de secventa, raspunsul va fi {$-1$}.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare $secv.in$ se gaseste {$N$}, lungimea sirului. Pe a doua linie se gasesc $N$ numere intregi, sirul propriu-zis.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie a fisierului de iesire $secv.out$ se gaseste numarul cerut.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $0 &le; N &le; 5 000$\r\n* Elementele sirului sunt numere intregi din intervalul $[0, 2 000 000 000]$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. secv.in|_. secv.out|\r\n|8 \r\n2 1 3 2 1 3 4 5\r\n|7 |\r\n\r\nh3. Explicatii\r\n\r\nSingura subsecventa care respecta conditile din enunt este $_1_ 3 _2_ 1 _3 4 5_$\r\nAcesta subsecventa contine subsirul $_1 2 3 4 5_$.\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"secv\")==\n\n\n',1490,'task: secv',242,NULL),('problema/luna','Luna','2006-11-11 11:23:41','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"luna\")==\r\n\r\nIn anul 2507 colonizarea Lunii a luat sfarsit, fiecare tara detine cateva parcele din teritoriul planetei. Firmele de pe Pamant doresc construirea unor cladiri de forma dreptunghiulara pe Luna. Evident, fiecare firma va putea construi doar pe teritoriul care se afla in proprietatea tarii ei de provenienta.\r\n\r\nh2. Cerinta\r\n\r\nStabiliti in cazul fiecarei firme, daca este posibila satisfacerea cererii ei de construire!\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului $luna.in$ se afla doua numere naturale $N$ si $M$, care reprezinta numarul de linii, respectiv numarul de coloane a matricei care descrie harta Lunii. Pe fiecare dintre urmatoarele $N$ linii se afla $M$ numere care indica numarul de ordine a tarii care este proprietara parcelei de pe linia si coloana respectiva de pe harta.\r\n\r\nPe urmatoarea linie se afla numarul $K$ al firmelor de pe Pamant, care doresc sa construiasca pe Luna. Pe urmatoarele $K$ linii sunt scrise triplete de numere, care reprezinta cererile firmelor. Primul numar din triplet reprezinta tara de provenienta a firmei. Al doilea si al treilea numar reprezinta dimensiunile cladirii pe care, conform cererii respective firma ar dori s-o construiasca.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $luna.out$ va contine exact $K$ linii. \r\n\r\n* Daca a $i$-a cerere poate fi satisfacuta, pe a $i$-a linie se va scrie mesajul {$Cererea poate fi satisfacuta$}.\r\n* Daca tara de provenienta a firmei nu are parcele pe Luna, in fisierul de iesire se va scrie mesajul {$Tara de provenienta nu are parcele pe Luna!$}.\r\n* Daca nu se poate construi o cladire cu dimensiunile date, folosind doar parcelele tarii de provenienta, in fisierul de iesire se va scrie mesajul {$Cererea nu poate fi satisfacuta!$}.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N, M &le; 50$\r\n* Numarul de ordine al unei tari este un numar natural cuprins intre $1$ si {$2500$}\r\n* $1 &le; K &le; 100 000$\r\n* Numarul de ordine a tarii de provenienta al unei firme este un numar natural cuprins intre $1$ si $5000$\r\n* Dimensiunile unei cladiri sunt numere naturale cuprinse intre $1$ si $100$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. luna.in|_. luna.out|\r\n|5 10\r\n1 1 1 2 2 2 2 3 3 4\r\n1 1 1 2 2 2 2 3 3 4\r\n5 5 5 2 2 2 2 7 7 4\r\n5 5 5 6 6 6 6 7 7 4\r\n5 5 5 6 6 6 6 7 7 4\r\n6\r\n1 2 3 \r\n2 3 4\r\n3 2 3\r\n1 3 2\r\n7 20 20\r\n8 4 4\r\n|Cererea poate fi satisfacuta!\r\nCererea poate fi satisfacuta!\r\nCererea nu poate fi satisfacuta!\r\nCererea poate fi satisfacuta!\r\nCererea nu poate fi satisfacuta!\r\nTara de provenienta nu are parcele pe Luna!\r\n|\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"luna\")==\n\n\n',1490,'task: luna',452,NULL),('problema/indep','Indep','2006-11-11 11:23:38','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"indep\")==\r\n\r\nFiind dat un sir de numere naturale $A{~1~} A{~2~} ... A{~n~}$ sa se afle numarul de subsiruri independente ale acestuia. Un subsir se numeste independent daca cel mai mare numar natural care divide toate elementele sale este $1$.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care afla numarul cautat.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare se alfa un numar intreg $N$ reprezentand numarul de elemente ale sirului. Pe urmatoarele $N$ linii se afla cate un element al sirului.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire va contine pe prima linie un singur intreg reprezentand numarul cautat.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; N &le; 500$\r\n* Elementele sirului sunt numere naturale din intervalul $[1, 1000]$\r\n* Prin subsir se intelege un subset de elemente ale sirului care nu se afla neaparat pe pozitii consecutive\r\n\r\nh2. Exemplu\r\n\r\n\r\ntable(example). |_. indep.in |_. indep.out |\r\n| 4\r\n3\r\n4\r\n2\r\n6\r\n| 6 |\r\n\r\nh3. Explicatie\r\n\r\nSubsirurile independente sunt:\r\n{3, 2} {3, 4} {3, 4, 2} {3, 2, 6} {3, 4, 6} {3, 4, 2, 6}\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"indep\")==\n\n\n',1490,'task: indep',244,NULL),('problema/cifre','Cifre','2006-11-11 11:23:38','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"cifre\")==\r\n\r\nEugenia ii pune adesea intrebari dificile lui Zaharel, nu pentru ca nu stie raspunsul, dar vrea sa vada cat de perspicace este Zaharel. Uneori exagereaza si intrebarile ei sunt foarte grele, chiar si pentru Zaharel; atunci acesta va cere ajutorul vostru! Astazi Eugenia i-a pus urmatoarea intrebare lui Zaharel: \"eu ma gandesc la un numar intreg din intervalul $[A...B]$, care este probabilitatea ca numarul la care ma gandesc sa contina cel putin $K$ cifre de valoare $C$\"?\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l pe Zaharel sa raspunda cat mai repede la intrebare.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie din fisierul de intrare se gasesc numerele intregi $A, B, C$ si $K$ (in ordinea aceasta)\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie din fisierul de iesire se va scrie probabilitatea, un numar real cu patru zecimale, ca numarul din intervalul $[A...B]$ la care se gandeste Eugenia sa aiba cel putin $K$ cifre de valoare $C$.\r\n\r\nh2. Restrictii\r\n\r\n* $0 &le; A &le; B < 1.000.000.000$\r\n* $0 &le; C, K &le; 9$\r\n* Pentru cel putin $50%$ din teste $B-A &le; 1.000.000$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. cifre.in |_. cifre.out |\r\n| 1 13 1 1 | 0.3846 |\r\n\r\nh3. Explicatii\r\n\r\nIn intervalul $[1..13]$ sunt $5$ numere care contin cel putin o cifra  de valoare $1:  1,10,11,12,13$. \r\nAstfel, probabilitatea este $5/13 = 0.(384615)$\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"cifre\")==\n\n\n',1490,'task: cifre',304,NULL),('problema/farfurii','Farfurii','2006-11-11 11:23:38','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"farfurii\")==\r\n\r\nIn fiecare zi Zaharel este obligat de Eugenia sa spele farfuriile si tacamurile dupa fiecare masa. Dupa ce le spala el trebuie sa le aranjeze pe doua rafturi, farfuriile pe primul si tacamurile pe al doilea... dar nu oricum! El are $N$ farfurii de marimi distincte, cuprinse intre $1$ si $N$ si $K$ tacamuri identice. Pentru fiecare pereche de farfurii asezate in raft astfel incat farfuria de marime mai mare, dintre cele doua, apare inaintea farfuriei de marime mai mica, Zaharel pune un tacam pe randul al doilea.\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l pe Zaharel sa aseze toate farfuriile pe primul raft astfel incat sa puna toate tacamurile pe al doilea raft. Dintre toate asezarile posibile determinati-o pe aceea minim lexicografica din punct de vedere al marimilor.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie din fisierul de intrare $farfurii.in$ se gasesc numerele naturale $N$ si {$K$}.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie din fisierul de iesire $farfurii.out$ se vor gasi $N$ numere distincte intre $1$ si $N$ reprezentand marimile farfuriilor, afisate in ordinea in care au asezate pe raft.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; N &le; 100.000$\r\n* $0 &le; K &le; N*(N-1)/2$\r\n* Pentru cel putin $40%$ din teste $N &le; 2.000$\r\n* O asezare ({$A{~1~},A{~2~}...A{~N~}$}) este mai mica din punct de vedere lexicografic decat o alta asezare ({$B{~1~},B{~2~}...B{~N~}$}) daca exista o pozitie $p$ astfel incat $A{~p~}<B{~p~}$ si $A{~1~}=B{~1~}, A{~2~}=B{~2~}, ... A{~p-1~}=B{~p-1~}$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. farfurii.in |_. farfurii.out |\r\n| 7 8\r\n| 1 2 5 7 6 4 3 |\r\n\r\nh3. Explicatii \r\n\r\nPentru perechile de farfurii din asezare \r\n$({*5 4*}) ({*5 3*}) ({*7 6*}) ({*7 4*}) ({*7 3*}) ({*6 4*}) ({*6 3*}) ({*4 3*})$\r\nZaharel pune cate un tacam pe randul al doilea. O alta asezare posibila este \r\n${*1 2 6 5 7 4 3*}$\r\ndar aceasta este mai mare lexicografic.\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"farfurii\")==\n\n\n',1490,'task: farfurii',305,NULL),('problema/poligon','Poligon','2006-11-11 11:23:39','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"poligon\")==\r\n\r\nDupa o noapte dementa, plina de infractiuni, un ofiter de politie lucreaza la elaborarea unor statistici. El are in fata harta orasului cu punctele unde s-au intamplat infractiuni precum si o zona in forma de poligon (nu neaparat convex) din harta care prezinta interes maxim.\r\n\r\nh2. Cerinta\r\n\r\nFiind dat poligonul ce descrie zona de interes si punctele infractionale trebuie sa aflati numarul de infractiuni petrecute in acea zona.\r\n\r\nh2. Date de intrare\r\n\r\nIn fisierul de intrare $poligon.in$ se vor afla pe prima linie numerele intregi $N$ si $M$ separate printr-un spatiu, $N$ e numarul de varfuri ale zonei poligonale iar $M$ numarul total de infractiuni desfasurate noaptea trecuta. Pe urmatoarele $N$ linii se vor afla cate doi intregi reprezentand coordonatele varfurilor poligonului date in ordinea parcurgerii lor mergand numai intr-o directie (din cele doua posibile) pe laturile sale. Pe urmatoarele $M$ linii se vor afla coordonatele infractiunilor desfasurate in noaptea anterioara.\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul de iesire $poligon.out$ se va afla pe prima linie numarul de puncte interioare sau pe marginea zonei date. Linia se termina cu caracterul \"end of line\".\r\n\r\nh2. Restrictii\r\n\r\n* $3 &le; N &le; 800$\r\n* $1 &le; M &le; 60.000$\r\n* Coordonatele punctelor vor fi numere intregi intre $0$ si $60.000$\r\n* Poligonul nu se auto-intersecteaza\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. poligon.in |_. poligon.out |\r\n| 4 3\r\n0 0\r\n0 100\r\n100 100\r\n100 0\r\n50 50\r\n100 50\r\n100 110 | 2 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"poligon\")==\n\n\n',1490,'task: poligon',308,NULL),('problema/triunghi','Triunghi','2006-11-11 11:23:34','2010-02-19 20:21:06','==Include(page=\"template/taskheader\" task_id=\"triunghi\")==\r\n\r\nLui Gigel ii place sa se joace, asa ca el a primit un joc cu cutii pe care erau scrise numere intregi stict pozitive. Avand o imaginatie bogata, el s-a gandit intr-o zi sa construiasca un triunghi de cutii astfel: o cutie este asezata peste doua cutii, care sunt asezate pe trei cutii... care sunt asezate pe $N$ cutii (deci fiecare cutie se sprijina pe alte doua). Dar Gigel nu se opreste aici, ci vrea ca numarul din fiecare cutie din triunghiul sau (mai putin ultima linie) sa fie egal cu suma numerelor din cele doua cutii de dedesubt.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care determina daca Gigel poate construi un triunghi de latura $N$, in care suma numerelor de pe toate cutiile sa fie $S$, stiind ca pot folosi oricate cutii cu orice numar in ele.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie in fisierul $triunghi.in$ se vor afla numerele $N$ si $S$ separate prin cate un spatiu.\r\n\r\nh2. Date de iesire\r\n\r\nPe primele $N$ linii din fisierul $triunghi.out$ se vor afla numerele de pe cutiile din triunghi: pe linia $i$ vor fi scrise cate $i$ numere intregi strict pozitive care descriu linia $i$ din triunghi. Daca Gigel nu poate construi un astfel de triunghi, in fisier se va afisa in schimb mesajul $imposibil$.\r\n\r\nh2. Restrictii si observatii\r\n\r\n* $1 &le; N &le; 18$\r\n* $1 &le; S &le; 1 000 000$\r\n* Daca sunt posibile mai multe solutii se va afisa oricare dintre ele\r\n\r\nExemple\r\n\r\ntable(example). |_. triunghi.in |_. triunghi.out |\r\n|3 34\r\n|13\r\n6 7\r\n1 5 2|\r\n|4 26\r\n|8\r\n4 4\r\n2 2 2\r\n1 1 1 1|\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"triunghi\")==\r\n\r\n\r\n',2044,'task: triunghi',44,NULL),('problema/cobai','Cobai','2006-11-11 11:23:39','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"cobai\")==\r\n\r\nDiorde, cel mai tare biolog din Tritenii de Jos, lucreaza la crearea unui elixir care sa-i faca pe consatenii sai mai inteligenti. El testeaza acest elixir pe Miki, singurul om din sat care s-a oferit voluntar. Pentru a vedea cat de inteligent este acesta, Diorde a construit un caroiaj dreptunghiular, caroiaj de $M*N$ camere. Din fiecare camera sunt cel mult $4$ usi, orientate inspre Nord, Sud, Est si Vest. In unele camere nu se poate intra, ele fiind inchise. Diorde are un cobai mult mai istet decat multi dintre sateni, cobai caruia ii da drumul dintr-o camera pe care o va inchide dupa aceea, si-l va lasa sa se miste in voie o perioada de timp. Cobaiul este dotat cu un dispozitiv care transmite tot timpul un semnal, care ne spune directia in care se deplaseaza cobaiul. Acest aparat detecteaza doar schimbarile de directie ale cobaiului. Dupa schimbarea unei directii cobaiul se deplaseaza cu cel putin o pozitie in acea directie, si modificarile de directie au loc intotdeauna cu $90$ de grade.\r\n\r\nCe trebuie sa faca Miki pentru a dovedi ca este mai inteligent? Avand in mana harta caroiajului (cu $.$ vor fi marcate camerele deschise iar cu $+$ camerele inchise), si stiind pozitia din care a plecat cobaiul (marcata cu $*$), precum si directiile in care s-a deplasat acesta, trebuie sa determine o pozitie posibila in care se poate afla cobaiul la sfarsitul acelui interval de timp.\r\n\r\nVoi trebuie sa calculati probabilitatea ca Miki sa ghiceasca o pozitie, in care cobaiul poate fi.\r\n\r\nh2. Date de Intrare\r\n\r\nPrima linie a fisierului de intrare contine numerele $M$ si $N$, separate printr-un singur spatiu. Urmatoarele $M$ linii contin cate $N$ caractere care descriu suprafata planetei (caracterele admise apartin multimii {\".\" , \"+\" , \"*\"} si au semnificatia prezentata anterior). Urmatoarea linie va descrie informatiile furnizate de dispozitivul de urmarire, neseparate prin spatii. Litera $N$ indica o deplasare spre nord (spre prima linie a matricei), litera $V$ o deplasare spre vest (spre prima coloana), litera $S$ o deplasare spre sud (spre ultima linie), iar litera $E$ o deplasare spre est (spre ultima coloana).\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul de iesire va contine un singur numar care va indica procentul cautat. Numarul va fi real cu $2$ zecimale, nerotunjit.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; N,M &le; 50$\r\n* Numarul schimbarilor de directie este cel mult $1.000$\r\n* Cobaiul nu poate parasi caroiajul\r\n\r\nh2. Exemplu\r\n\r\n\r\ntable(example). |_. cobai.in |_. cobai.out |\r\n| 4 5\r\n.....\r\n.+.+.\r\n+....\r\n.++.*\r\nNVS \r\n| 28.57 | \r\n\r\nh3. Explicatie\r\n\r\nCaroiajul contine $14$ camere in care se poate intra ( cele notate cu $.$ ). Deplasandu-se in directiile {$N$}, urmat de {$V$}, apoi de $S$ el nu se mai poate afla decat in alte $4$ camere. Rezulta un procent de {$28,57 %$}.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"cobai\")==\n\n\n',1490,'task: cobai',384,NULL),('problema/concert','Concert','2006-11-11 11:23:39','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"concert\")==\r\n\r\nUn grup de $N$ artisti a primit invitatii sa cante la un concert. Fiecarui artist i s-a trimis o invitatie pe care acesta era invitat sa cante intre orele $A$ si $B$. Insa organizatorii acestui eveniment au gresit invitatiile si timpurile in care trebuiau sa cante anumiti artisti se suprapuneau. Artistii, fiind renumiti, nu accepta sa cante decat singuri. De asemenea ei cer despagubiri daca li se cere sa inceapa sa cante dupa ora $A+1$ sau sa termine inainte de ora $B$. Un anumit artist poate sa cante doar intre orele $A$ si $B$ de pe invitatie. Unele invitatii pot fi anulate, asa ca unii artisti pot sa nu cante deloc.\r\n\r\nh2. Cerinta\r\n\r\nCunoscandu-se intervalele intre care poate sa cante fiecare artist, profitul pe care il aduce fiecare artist pe unitatea de timp si despagubirile cerut in ambele cazuri mentionate mai sus, voi trebuie sa aflati care este suma maxima care poate fi obtinuta in concertul respectiv, si cum poate fi ea obtinuta.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierul $concert.in$ se va afla $N$. Pe urmatoarele $N$ linii ale fisierulul se vor gasi cate 5 numere separate prin cate un spatiu. Ele reprezinta $A$, $B$, profitul pe unitatea de timp si despagubirile in cazul in care artistul nu incepe sa cante in $A+1$ si respectiv daca nu termina de cantat in $B$.\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie a fisierul $concert.out$ se va afla suma maxima care poate fi obtinuta din concert.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; N &le; 1.000$\r\n* $1 &le; A{~i~} < B{~i~} &le; 2.000.000.000$\r\n* profitul adus de fiecare artist sau despagubirile cerute de fiecare dintre ei nu vor trece de valoare 500. Despagubirile se platesc o data, nu pe unitate de timp.\r\n* daca artistul $i$ are in contract intervalul $(A{~i~},B{~i~})$ el poate canta intre momentele $A{~i~}+1$ si $B{~i~}$ inclusiv.\r\n* oricare doi artisti au intervalele diferite\r\n* solutia nu va trece de valoare 2^31^-1\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. concert.in |_. concert.out |\r\n| 5 \r\n0 5 10 10 15\r\n3 8 8 8 20\r\n4 10 12 4 10\r\n8 16 7 4 7\r\n12 20 10 5 50 | 189 |\r\n\r\nh3. Explicatie\r\n\r\nArtistul $1$ canta intre orele $1$ si $5$, aducand un profit de $(5-1+1)*10 = 50$ si nu cere despagubiri, pentru ca a cantat intre orele stabilite in invitatie. Artistul $2$ nu canta de loc. Artistul $3$ canta intre orele $6$ si $10$, aducand un profit de $(10-6+1)*12 = 60$, insa i se platesc despagubiri in valoare de $4$, pentru ca nu a inceput la ora la care i s-a spus in invitatie ca va incepe, ora $A+1 = 4$. Astfel artistul $3$ aduce un profit de $60-4 = 56$. Artistul $4$ canta intre orele $11$ si $12$. Aducand un profit de $2*7 = 14$, insa cere ambele despagubiri deci aduca un profit de $14-7-4 = 3$. Artistul cu numarul $5$ aduce un profitde $8*10 = 80$, si nu cere despagubiri, pentru ca a cantat intre orele stabilite. Astfel, totalul se ridica la: $50+56+3+80=189$.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"concert\")==\r\n\r\n\r\n',1490,'task: concert',385,NULL),('problema/perm3','Permutari 3','2006-11-11 11:23:39','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"perm3\")==\r\n\r\nPentru o multime oarecare de numere intregi cu $N$ elemente se poate defini o permutare a acesteia ca fiind o varianta de a aseza elementele multimii. De exemplu pentru multimea $M={4,12,81}$ vom avea permutarile:\r\n\r\n# ${ 4 , 12 , 81 }$\r\n# ${ 4 , 81 , 12 }$\r\n# ${ 12 , 4 , 81 }$\r\n# ${ 12 , 81 , 4 }$\r\n# ${ 81 , 4 , 12 }$\r\n# ${ 81 , 12 , 4 }$\r\n\r\nIn grupul format de toate permutarile unei multimi se poate defini o ordine a acestora astfel incat elementele aflate pe prima pozitie sa fie in ordine crescatoare, elementele de pe a doua pozitie sa fie in ordine crescatoare pentru permutarile care au primul element identic, etc. asa cum se vede in figura. O astfel de ordine se numeste ordine lexicografica. Permutarilor asezate in ordine lexicografica li se pot asocia numere de ordine, in cazul exemplului de mai sus de la $1$ la {$6$}.\r\n\r\nh2. Cerinta\r\n\r\nDandu-se o multime de numere intregi si o permutare a ei concepeti un program care determina numarul de ordine al permutarii in ordine lexicografica\r\n\r\nh2. Date de Intrare\r\n\r\nFisierul de intrare $perm3.in$ contine:\r\n\r\n|_. Valori |_. Semnificatie |\r\n|{$N$} |prima linie: $N$ = numarul de elemente al multimii,  |\r\n|{$m{~1~} m{~2~} m{~3~}$} ... {$m{~N~}$}|a doua linie: elementele multimii, in ordine crescatoare|\r\n|{$p{~1~} p{~2~} p{~3~}$} ... {$p{~N~}$}|a treia linie: elementele permutarii (elementele {$m{~1~} m{~2~} m{~3~}$} ... {$m{~N~}$} dar in alta ordine) |\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul de iesire $perm3.out$ va contine numarul permutarii in ordine lexicografica.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 1.000$\r\n* $1 &le; m{~i~} &le; 2.000.000.000$\r\n\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. perm3.in |_. perm3.out |\r\n| 3\r\n1 23 25\r\n23 1 25\r\n| 3 |\r\n| 4\r\n1 2 3 4\r\n3 4 1 2\r\n| 17 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"perm3\")==\n\n\n',1490,'task: perm3',386,NULL),('problema/triang','Triang','2006-11-11 11:23:39','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"triang\")==\r\n\r\nAndreea a invatat la scoala ce este un triunghi echilateral. Fascinata de aceste figuri geometrice, ea deseneaza in plan $N$ puncte cu coordonate numere reale. Ea insa nu isi da seama cate triunghiuri echilaterale a desenat, asa ca va cere ajutorul!\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului $triang.in$ se afla numarul $N$ de puncte. Pe urmatoarele $N$ linii se vor afla coordonatele celor $N$ puncte sub forma ({$x y$}).\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie a fisierului $triang.out$ se va scrie numarul de triunghiuri echilaterale desenate de Andreea.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $3 &le; N &le; 1.500$\r\n* $-10.000 &le; x, y &le; 10.000$\r\n* Nu vor exista doua puncte cu coordonate identice, iar orice punct poate fi folosit pentru formarea mai multor triunghiuri echilaterale.\r\n* Un triunghi este echilateral daca are toate unghiurile si laturile egale.\r\n* Daca folositi numere reale in programul dumneavoastra, se recomanda folosirea tipurilor double pentru C/C++, respectiv Pascal. Pentru testarea egalitatii a doua numere reale se recomanda folosirea unei precizii de {$10^-3^$}\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. triang.in|_. triang.out|\r\n|3\r\n0 0 \r\n4 0\r\n2 3.4641016\r\n|1|\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"triang\")==\n\n\n',1490,'task: triang',387,NULL),('problema/tri','Tri','2006-11-11 11:23:39','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"tri\")==\r\n\r\n\r\nSe da un triunghi $ABC$ pozitionat astfel incat varful $B$ este in originea axelor (punctul de coordonate $0$ si $0$, varful $C$ se afla pe axa $OX$ si are coordonata $x$ pozitiva, iar varful $A$ are ambele coordonate pozitive.\r\nIn acest triunghi se afla $N$ puncte ({$N$} divizibil cu $3$).\r\n\r\nh2. Cerinta\r\n\r\nSa se determine un punct notat in continuare cu $G$ care sa se afle in interiorul triunghiului $ABC$ si care sa indeplineasca conditia ca in interiorul sau pe conturul fiecaruia din triunghiurile $ABG$, $BCG$ si $CAG$ se afla exact o treime din cele $N$ puncte.\r\nDaca vreunul din cele $N$ punctele se afla pe unul din segmentele $AG$, $BG$ sau $CG$, se va considera ca el apartine doar unuia din cele doua triunghiuri care au in comun segementul respectiv si puteti alege caruia din cele doua triunghiuri ii apartine.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului $tri.in$ se afla $6$ valori numerice intregi reprezentand: primele doua coordonatele varfului $A$, urmatoarele doua coordonatele punctului $B$ (ambele fiind $0$) si ultimele doua coordonatele punctului $C$ (a doua valoare din aceasta pereche este $0$)\r\nPe a doua linie numarul natural $N$. Pe fiecare din urmatoarele $N$ linii se afla cate doua valori numerice intregi reprezentant coordonatele fiecaruia din cele $N$ puncte aflate in interiorul triunghiului $ABC$.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie a fisierului $tri.out$ doua valori numerice reale reprezentand coordonatele punctului $G$.\r\nPe a doua linie $N/3$ perechi de valori numerice intregi separate prin minim un spatiu reprezentant coordonatele punctelor aflate in interiorul sau pe conturul triunghiului $BCG$. Pe a treia linie $N/3$ perechi de valori numerice intregi separate prin minim un spatiu reprezentant coordonatele punctelor aflate in interiorul sau pe conturul triunghiului $ABG$. Pe a patra linie $N/3$ perechi de valori numerice intregi separate prin minim un spatiu reprezentant coordonatele punctelor aflate in interiorul sau pe conturul triunghiului $ACG$.\r\n\r\nh2. Restrictii si observatii\r\n\r\n* $2 < N &le; 10.000$\r\n* Coordonatele pentru varfurile triungiului si pentru fiecare punct din interiorul triunghiului sunt numere intregi nenegative &le; $1.000.000$\r\n* In fiecare pereche reprezentand coordonatele unui punct, prima valoare reprezinta abscisa si a doua ordonata\r\n* Coordonatele punctului $G$ vor fi afisate cu un numar de cel putin $8$ zecimale exacte\r\n* Oricare doua dintre aceste puncte nu sunt coliniare cu unul din varfurile $A$, $B$ sau $C$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. tri.in |_. tri.out |\r\n| 5 5 0 0 10 0\r\n6\r\n8 1\r\n3 0\r\n3 2\r\n9 1\r\n6 1\r\n1 1\r\n| 3.636364 1.590909\r\n3 0  6 1 \r\n3 2  1 1 \r\n8 1  9 1 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"tri\")==\n\n\n',1490,'task: tri',398,NULL),('problema/soc','Soc','2006-11-11 11:23:42','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"soc\")==\r\n\r\nUn grup de $N$ oameni de afaceri s-au intalnit cu ocazia unei conferinte. Unii dintre ei sunt prieteni, altii nu. Fiecare dintre ei are un cont banca ce contine o anumita suma exprimata in euro. De fiecare data cand se intalnesc, se gandesc cum sa initieze o noua afacere. De data aceasta s-au decis sa infiinteze o societate, la care actionarii sa fie o parte dintre ei, astfel incat oricare doi oameni de afaceri care sunt actionari ai societatii sa fie prieteni, iar capitalul societatii (egal cu totalul sumelor din conturile actionarilor) sa fie maxim. Pentru a determina actionarii acestei societati, v-au angajat pe dumneavoastra si, daca le veti da raspunsul in timp util, veti fi recompensat cu o suma frumoasa.\r\n\r\nInainte de a va apuca de treaba, cei $N$ oameni de afaceri v-au pus la dispozitie informatii referitoare la conturile lor din banca si la relatiile de prietenie dintre ei. Analizand problema, ati ajuns la concluzia ca relatiile de prietenie pot fi reprezentate sub forma unui graf neorientat cu $N$ varfuri (corespunzatoare celor $N$ oameni de afaceri); intre doua varfuri diferite exista o muchie, daca cei doi oameni de afaceri corespunzatori celor doua varfuri din graf sunt prieteni (prietenia este reciproca). Graful are o structura speciala, mai exact el este un cograf. Un graf se numeste cograf daca indeplineste cel putin una dintre urmatoarele 3 conditii:\r\n\r\n# Este un graf cu un singur nod\r\n# Este graful-reuniune a doua sau mai multe cografuri\r\n# Este graful complementar al unui cograf\r\n\r\nPrin reuniunea a doua grafuri, unul cu $i$ noduri si muchii intre aceste $i$ noduri, altul cu $j$ noduri si muchii intre aceste $j$ noduri, se obtine un graf cu $i+j$ noduri, care contine toate muchiile din cele doua grafuri, fara a se introduce vreo muchie in plus. De exemplu, pentru doua grafuri, unul avand nodurile etichetate $1$ si $2$ si continand muchia {$[1,2]$}, iar altul avand nodurile etichetate {$9$},{$10$},{$11$} si continand muchiile {$[9,10]$}, {$[9,11]$}, graful-reuniune va contine $5$ noduri etichetate {$1$},{$2$},{$9$},{$10$},{$11$} si +exact+ trei muchii: {$[1,2]$}, {$[9,10]$}, {$[9,11]$}.\r\n\r\nGraful complementar al unui graf se obtine astfel:\r\n\r\n- pentru orice pereche de noduri distincte $[a,b]$ intre care exista muchie in graful initial, NU va exista muchie in graful complementar;\r\n- pentru orice pereche de noduri distincte $[a,b]$ intre care NU exista muchie in graful initial, va exista muchie in graful complementar.\r\n\r\nDe exemplu, pentru graful avand $3$ noduri, etichetate {$4$},{$11$},{$20$}, si $2$ muchii $[4,11]$ si {$[11,20]$}, graful complementar va contine toate cele $3$ noduri si o singura muchie: {$[4,20]$}.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare $soc.in$ se afla numerele intregi $N$ si $M$, separate printr-un spatiu. Pe urmatoarea linie se afla numerele intregi {$E{~i~}$}, {$i=1,2,..,N$}, separate prin cate un spatiu, reprezentand sumele din conturile celor $N$ oameni de afaceri. Numarul $E{~K~}$ reprezinta suma din contul afaceristului numerotat cu $K$. Pe urmatoarele $M$ linii se afla cate doua numere intregi $a$ si $b$ din intervalul {$[1,N]$}, avand semnificatia ca oamenii de afaceri numerotati cu $a$ si, respectiv, $b$ sunt prieteni.\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul $soc.out$ veti afisa, pe prima linie, capitalul maxim al societatii. Pe urmatoarea linie veti afisa numarul {$A$}, reprezentand numarul de actionari ai societatii. Pe cea de-a treia linie veti afisa numerele oamenilor de afaceri care vor fi actionari, separate prin cate un spatiu. Daca exista mai multe posibilitati de a alege actionarii societatii astfel incat capitalul acesteia sa fie maxim, puteti afisa oricare din ele.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 256$\r\n* $0 &le; M &le; N*(N-1)/2$\r\n* {$0 &le; E{~i~} &le; 1 000 000$}, pentru {$i=1,2,..,N$}\r\n* Daca sunt mai multe solutii corecte, se va afisa oricare\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. soc.in|_. soc.out|\r\n|5 4\r\n5 4 3 3 3\r\n2 1\r\n3 4\r\n4 5\r\n5 3\r\n|9\r\n3\r\n3 4 5\r\n|\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"soc\")==\n\n\n',1490,'task: soc',467,NULL),('problema/perechi','Perechi','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"perechi\")==\r\n\r\nSe da un numar intreg strict pozitiv $N$. Trebuie sa determinati cate perechi de numere intregi strict pozitive au cel mai mic multiplu comun egal cu $N$.\r\n\r\nh2. Date de Intrare\r\n\r\nIn fisierul de intrare $perechi.in$ se afla numarul $N$.\r\n\r\nh2. Date de Iesire\r\n\r\nIn fisierul de iesire $perechi.out$ veti afisa numarul determinat.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $0 < N < 2^31^$\r\n* Perechile $(a,b)$ si $(b,a)$ se considera identice.\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. perechi.in |_. perechi.out |\r\n| 12 | 8 |\r\n\r\nh3. Explicatie\r\n\r\nPerechile care au cel mai mic multiplu comun egal cu 12 sunt: $(1,12) (2,12) (3,12) (4,12) (6,12) (12,12) (3,4) (4,6)$\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"perechi\")==\n\n\n',1490,'task: perechi',403,NULL),('problema/petrica','Petrica','2006-11-11 11:23:34','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"petrica\")==\r\n\r\n\r\nPetrica este presedintele unei tari cu $N$ orase conectate prin strazi bidirectionale astfel incat exista un drum unic intre oricare doua dintre ele. Aceste orase sunt numerotate de la $1$ la $N$ astfel incat nu exista doua orase cu acelasi numar. Petrica vrea sa le imparta in patru districte blocand exact trei strazi. De asemenea vrea ca populatia oraselor sa fie distribuita cat mai uniform: diferenta dintre numarul de locuitori din distructul cu cea mai mare populatie si numarul de locuitori din districtul cu cea mai mica populatie sa fie cat mai mica. Aflati pentru presedintele Petrica aceasta diferenta.\r\n\r\nh2. Data de intrare\r\n\r\nPrima linie a fisierului $petrica.in$ va contine numarul $N$ reprezentand numarul de orase. A doua linie contine populatia fiecarui oras ({$N$} valori intregi). Urmatoarele linii contin cate doi intregi $A$ si $B$ cu semnificatia: exista o strada intre orasele $A$ si $B$.\r\n\r\nh2. Data de iesire\r\n\r\nPe prima linie a fisierului $petrica.out$ se va afla un numar natural reprezentand diferenta minima pe care vrea sa o afle Petrica.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $4 &le; N &le; 200$\r\n* Populatia fiecarui oras este un numar intreg din intervalul $[1, 10000]$\r\n* Populatia unui district se calculeaza ca suma populatiei oraselor din districtul respectiv\r\n* Doua orase sunt in acelasi district daca se poate ajunge de la unul la altul mergand pe strazi care nu au fost blocate\r\n* Pentru $50%$ din teste $N &le; 70$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. petrica.in |_. petrica.out |\r\n| 4\r\n2 1 1 1\r\n1 2\r\n1 3\r\n1 4\r\n| 1 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"petrica\")==\n\n\n',1490,'task: petrica',40,NULL),('problema/secventa','Secventa','2006-11-11 11:23:34','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"secventa\")==\r\n\r\n==include(page=\"template/badtests\")==\r\n\r\nGigel are un sir de $N$ numere intregi. Toata lumea stie ca o secventa este un subsir de numere care apar pe pozitii consecutive in sirul initial. Gigel a definit baza unei secvente ca fiind minimul valorilor elementelor din secventa respectiva.\r\n\r\nh2. Cerinta\r\n\r\nFiind dat un numar natural $K$, determinati pentru Gigel o secventa de lungime cel putin $K$ cu baza maxima.\r\n\r\nh2. Date de intrare\r\n\r\nFisierul de intrare $secventa.in$ contine pe prima linie numerele {$N$} si {$K$}, separate prin spatiu. Pe cea de a doua linie se afla elementele sirului separate prin cate un spatiu.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $secventa.out$ trebuie sa contina o singura linie cu trei numere: pozitia de inceput si de sfarsit a secventei de lungime cel putin $K$ cu baza maxima si valoarea maxima a bazei.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; K &le; N &le; 500 000$\r\n* Elementele din vector sunt numere intregi din intervalul $[-30 000, 30 000]$\r\n* Daca exista mai multe solutii pentru care se obtine baza maxima, atunci se va alege cea in care pozitia de inceput a secventei este cea mai mica, iar in caz de egalitate cea in care pozitia de sfarsit a secventei este cea mai mica\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. secventa.in|_. secventa.out|\r\n|8 3\r\n-1 2 3 1 0 4 8 6\r\n|6 8 4|\r\n\r\nh3. Explicatii\r\n\r\nSecventa care incepe pe pozitia $6$ si se termina pe pozitia $8$ (de lungime $3$) este $(4, 8, 6)$ are baza {$minim(4, 8, 6) = 4$}. Nu mai exista o secventa cu lungime mai mare sau egala cu $3$ care sa aiba baza mai mare.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"secventa\")==\n\n\n',1490,'task: secventa',41,NULL),('problema/drumuri','Drumuri','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"drumuri\")==\r\n\r\n\r\nIntr-o tara exista $n$ orase intre care exista un numar total de $m$ drumuri pe care se poate circula in ambele sensuri. Intre oricare doua orase poate exista cel mult un drum.\r\n\r\nDin nefericire, in aceasta tara rata criminalitatii este foarte mare si au loc o multime de jafuri \"la drumul mare\". Din acest motiv, conducatorii tarii au luat decizia de a amplasa paznici pe fiecare drum.\r\n\r\nIn tara respectiva a fost introdusa cota unica de impozitare, motiv pentru care fondurile de la buget sunt limitate. Pentru a reduce cheltuielile, fiecare paznic va trebui sa pazeasca doua drumuri.\r\n\r\nUn paznic poate pazi numai doua drumuri care se intersecteaza si se doreste ca fiecare strada sa fie pazita de exact un paznic si fiecare paznic sa pazeasca exact doua drumuri. Reteaua de drumuri este construita in asa fel incat de la un oras se poate ajunge la oricare altul.\r\n\r\nVa trebui sa verificati daca tara poate fi pazita astfel incat sa fie respectate dorintele liderilor si, daca este posibil, sa stabiliti drumurile pazite de fiecare paznic.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare $drumuri.in$ se afla doua numere naturale $n$ si $m$, reprezentand numarul oraselor, respectiv numarul drumurilor; aceste numere sunt separate printr-un spatiu. Urmatoarele $m$ linii contin cate doua numere intregi, separate printr-un spatiu, reprezentand doua orase intre care se afla un drum.\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul de iesire $drumuri.out$ se va scrie pe prima linie valoarea $1$ daca exista o solutie, sau valoarea $0$ daca problema nu are solutie. Daca problema are solutie atunci pe urmatoarele $m / 2$ linii vor fi scrise cate trei numere intregi; astfel, pe linia $i + 1$ vor fi scrise numerele $x$, $y$ si $z$, separate printr-un spatiu, cu semnificatia: paznicul $i$ pazeste drumul dintre orasele $x$ si $y$, precum si drumul dintre orasele $y$ si $z$.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; n &le; 10.000$\r\n* $1 &le; m &le; 30.000$\r\n\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. drumuri.in |_. drumuri.out |\r\n| 5 6\r\n1 2\r\n2 3\r\n3 1\r\n3 4\r\n4 5\r\n5 3\r\n| 1\r\n3 1 2\r\n3 4 5\r\n2 3 5 |\r\n| 3 3\r\n1 2\r\n2 3\r\n3 1\r\n| 0&nbsp; |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"drumuri\")==\n\n\n',1490,'task: drumuri',418,NULL),('problema/sir23','Siruri 2-3-monotone','2006-11-11 11:23:35','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"sir23\")==\r\n\r\nFie $N$ ({$N$} &le; $1000$) un numar natural. Numim sir _2-3-monoton_ de lungine $N$ un sir $S{~1~}$, $S{~2~}$, $S{~3~}$, ... $S{~n~}$ format din $N$ elemente ale multimii ${1, 2, ... N}$ care verifica urmatoarele doua relatii:\r\n\r\n* $S{~i~}$ &lt; $S{~i+2~}$, oricare ar fi $1$ &le; $i$ &le; $N-2$\r\n* $S{~i~}$ &lt; $S{~i+3~}$, oricare ar fi $1$ &le; $i$ &le; $N-3$\r\n\r\nh2. Cerinta\r\n\r\nFie $X$ numarul de siruri _2-3-monotone_ de lungime $N$. Calculati restul impartirii lui $X$ la $1.000.000$ (1 milion).\r\n\r\nh2. Date de intrare\r\n\r\nFisierul $sir23.in$ va contine pe prima linie numarul intreg $N$.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie a fisierului $sir23.out$ se va scrie numarul cautat.\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. sir23.in |_. sir23.out |\r\n| 2 | 4 |\r\n| 3 | 9 |\r\n| 5 | 88|\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"sir23\")==\r\n\n\n\n',1490,'task: sir23',45,NULL),('problema/cerere','Cerere','2006-11-11 11:23:38','2009-05-09 11:43:49','==Include(page=\"template/taskheader\" task_id=\"cerere\")==\r\n\r\nIn tara maimutelor scotiene arborele genealogic este bine definit deoarece de o bucata buna de timp nu mai murit nici o maimuta. Maimutele au adesea nemultumiri insa numai anumite maimute sunt destul de inteligente incat sa le rezolve. In momentul in care maimuta numarul $i$ are o nemultumire si nu o poate rezolva ea trebuie sa prezinte o cerere in scris celui de-al $K{~i~}$-lea stramos al ei si numai acestuia. La randul lui, acesta (sa-l numim $j$) trebuie sa o trimita celui de-al $K{~j~}$-lea stramos al sau, in cazul in care n-o poate rezolva, si tot asa pana cand o maimuta inteligenta va primi cererea.\r\n\r\nh2. Cerinta\r\n\r\nDandu-se arborele genealogic al maimutelor sa se gaseasca pentru fiecare dintre ele pe la cate maimute trece cererea pana va fi rezolvata.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare se afla un numar intreg N reprezentand numarul de maimute. A doua linie a fisierului contine $N$ numere, $K{~1~} K{~2~} ... K{~n~}$ cu semnificatia din enunt (se garateaza ca exista al $K{~i~}$-lea stramos pentru fiecare maimuta $i$). Daca $K{~i~}$ este $0$ atunci maimuta numarul $i$ poate rezolva cereri. Maimuta care este stramosul tuturor celorlalte maimute (radacina arborelui genealogic) este cea mai inteleapta maimuta si deci va putea rezolva cereri.\r\n\r\nUrmatoarele $N-1$ linii vor contine cate doua numere, separate printr-un spatiu, $A$ si $B$ cu semnificatia: maimuta $A$ este tatal maimutei $B$.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie a fiserului de iesire se vor gasi $N$ numere $G{~1~} G{~2~} ... G{~n~}, G{~i~}$ reprezentand numarul de maimute pe la care trece cererea maimutei numarul {~i~} (excluzand-o pe aceasta).\r\n\r\nh2. Restrictii\r\n\r\n* $2 &le; N &le; 100 000$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. cerere.in |_. cerere.out |\r\n| 10\r\n0 1 0 2 2 0 2 2 1 2\r\n1 2\r\n1 6\r\n2 3\r\n2 4\r\n4 5\r\n6 7\r\n6 8\r\n7 9\r\n7 10\r\n| 0 1 0 1 2 0 1 1 2 1 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"cerere\")==\r\n\r\n\r\n',2038,'task: cerere',240,NULL),('problema/sume','Sume','2006-11-11 11:23:35','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"sume\")==\r\n\r\nHaralambie este un elev silitor, asa ca a decis sa-si faca urmatoarea tema la mate: a primit pe o foaie de hartie un sir de $N$ numere naturale nenule nu neaparat distincte. El a luat toate perechile de numere din acest sir si le-a adunat, le-a scris pe o alta foaie, obtinand astfel un nou sir de numere. Numai ca a pierdut prima foaie si acum vrea sa gaseasca sirul initial de numere.\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l pe Haralambie sa reconstituie sirul initial de numere.\r\n\r\nh2. Date de intrare\r\n\r\nIn fisierul $sume.in$ se afla pe prima linie $P$, iar pe urmatoarea linie sunt scrise $P$ numere naturale mai mici sau egale cu $1000$.\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul $sume.out$ se va afisa pe prima linie $N$ iar pe a doua linie cele $N$ numere din sirul initial despartite printr-un un spatiu.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $3 &le; P &le; 25000$\r\n* In cazul in care exista mai multe solutii, se va afisa in fiser numai una\r\n* In cazul in care nu exista solutie se va afisa in fisier $-1$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. sume.in |_. sume.out|\r\n|3\r\n4 5 3\r\n|3\r\n3 1 2|\r\n|15\r\n5 7 15 10 8 8 16 11 9 18 13 11 21 19 14\r\n|6\r\n2 3 5 13 8 6|\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"sume\")==\n\n\n',1490,'task: sume',85,NULL),('problema/lapte','Lapte','2006-11-11 11:23:36','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"lapte\")==\r\n\r\nHaralambie este un mare bautor de lapte. Impreuna cu prietenii sai organizeaza adesea petreceri salbatice, in care se intrec in bautul laptelui. De data aceasta ei au organizat un joc. Ei au doua feluri de lapte : $lapte A$ si $lapte B$. In aceasta noapte si-au propus sa bea cel putin $L$ litri din fiecare fel. Dar mai e putin si se face dimineata, parintii lui Haralambie se intorc acasa si petrecerea se sparge. Ajutati-i sa bea cat mai repede.\r\n\r\nh2. Cerinta\r\n\r\nSe cunoaste viteza cu care fiecare persoana bea un litru din $laptele A$ si $laptele B$. Trebuie planificata o strategie astfel incat la sfarsitul petrecerii sa fi baut cel putin $L$ litri din $laptele A$ si cel putin $L$ litri din $laptele B$, iar timpul total sa fie minim. O persoana nu poate bea din doua tipuri de lapte in acelasi timp.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare $lapte.in$ sunt scrise numerele $N$ (numarul persoane participante) si $L$ (cantitatea minima de lapte ce trebuie bauta pana la sfarsitul petrecerii). Pe urmatoarele $N$ linii sunt date perechi de numere naturale nenule $a b (1 &le; a, b &le; 100)$ reprezentand timpul in care persoana corespunzatoare bea $1$ litru de $lapte A$, respectiv timpul in care bea $1$ litru de $lapte B$.\r\n\r\nh2. Date de iesire\r\n\r\nPrima linie a fisierului $lapte.out$ va contine un singur numar $T$ - timpul minim in care se va bea cantitatea ceruta de lapte. Pe urmatoarele $N$ linii vor fi perechi de numere naturale. Linia $i + 1$ va contine numerele $x y$ , reprezentand cantitatea de $lapte A$, respectiv cantitatea de $lapte B$ pe care o bea persoana $i$.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N, T, L &le; 100$\r\n* Cantitatea de lapte disponibila se considera nelimitata\r\n* Consumul excesiv de lapte duce la epuizarea bauturii\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. lapte.in |_. lapte.out |\r\n| 3 20\r\n1 1\r\n2 4\r\n1 6\r\n| 18\r\n0 18\r\n5 2\r\n18 0 |\r\n\r\nh3. Explicatii\r\n\r\nTimpul minim este $18$. \r\nCantitatea de lapte $A$ bauta este $0+5+18=23$.\r\nCantitatea de lapte $B$ bauta este $18+2=20$.\r\nPersoana $1$ termina de baut in $1*0+1*18=18$ minute.\r\nPersoana $2$ termina in $2*5+4*2=18$ minute.\r\nPersoana $3$ termina in $1*18+6*0=18$ minute.\r\nTimpul minim dupa care petrecerea va lua sfarsit este $max(18,18,18)=18$\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"lapte\")==\n\n\n',1490,'task: lapte',90,NULL),('problema/critice','Critice','2006-11-11 11:23:38','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"critice\")==\r\n\r\nAlgorel are in pivnita o retea subterana prin care misuna sobolani. Reteau consta din $N$ adaposturi numerotate de la $1$ la $N$ si $M$ tunele intre acestea. Adaposturile $1$ si $N$ comunica cu suprafata fiind singurele locuri din retea cu aceasta propietate (nici un alt adapost sau tunel nu mai are iesire la suprafata). Algorel vrea sa trimita un numar maxim de pisici in retea. Pisicile intra prin adapostul $1$ si ies prin adapostul $N$. Nici o pisica nu poate ramane in retea. Pentru fiecare tunel se stie rezistenta lui, adica numarul maxim de pisici care pot trece prin el fara ca sa se darame. Daca printr-un tunel cu rezistenta nenula a trecut o pisica atunci rezistenta acestuia scade cu o unitate. Algorel a observat ca exista anumite tunele care au propietatea ca daca rezistenta lor creste in timp ce rezistenta celorlalte tunele ramane la fel atunci va creste si numarul maxim de pisici pe care le poate trimite prin retea. El a denumit tunelele cu aceastra propietate tunele critice.\r\n\r\nh2. Cerinta\r\n\r\nFiind data reteaua din pivnita lui Algorel determinati tunelele critice.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului $critice.in$ se gasesc numerele naturale $N$ si $M$ reprezentand numarul de adaposturi si numarul de tunele din reteaua subterana. Urmeaza $M$ linii continand trei numere naturale separate prin spatii, $A B C$, cu semnificatia: intre adaposturile $A$ si $B$ ({$A != B$}) exista un tunel cu rezistenta $C$.\r\n\r\nh2. Date de Iesire\r\n\r\nPrima linie a fisierului de iesire $critice.out$ contine un numar natural $K$ reprezentand numarul de tunele critice din reteaua lui Algorel. Urmatoarele $K$ linii contin cate un numar natural reprezentand indicii muchiilor critice. Indicii vor fi sortati crescator. Muchiile sunt numerotate de la $1$ la $M$ dupa ordinea din fisierul de intrare.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; N &le; 1000$\r\n* $1 &le; M &le; 10000$\r\n* Rezistentele sunt numere naturale mai mici sau egale cu $10000$\r\n* Intre oricare doua noduri exista cel mult un tunel\r\n* Orice tunel poate fi parcurs in ambele sensuri\r\n* Petru $50%$ din teste $M <= 1000$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. critice.in |_. critice.out |\r\n| 5 6\r\n2 1 2\r\n2 3 3\r\n3 5 4\r\n1 4 7\r\n4 3 2\r\n4 5 6\r\n| 2\r\n1\r\n4 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"critice\")==\n\n\n',1490,'task: critice',306,NULL),('problema/secv2','Secventa 2','2006-11-11 11:23:35','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"secv2\")==\r\n\r\n==Include(page=\"template/badtests\")==\r\n\r\nGigel s-a decis sa devina olimpic la informatica, poate asa va reusi sa-si rezolve singur problemele, si nu va mai cere ajutorul vostru! La ora de informatica, profesoara lui i-a dat sa rezolve problema secventei de suma maxima: \"Gigele, eu iti dau un sir de $N$ numere intregi, iar tu trebuie sa gasesti o secventa (adica un subsir de numere care apar pe pozitii consecutive in sirul initial) cu suma elementelor maxima!\". Dupa vreo 30 de minute, Gigel s-a ridicat mandru si a zis: \"Am gasit algoritmul de complexitate optima, doamna profesoara!\"\r\nCa tema pentru acasa Gigel are de rezolvat aproape aceeasi problema: trebuie sa gaseasca secventa de suma maxima de lungime cel putin $K$!\r\n\r\nh2. Cerinta\r\n\r\nGigel inca nu stie destul de multa informatica ca sa poata rezolva aceasta problema, dar poate il ajutati voi! Scrieti un program care rezolva problema din tema lui Gigel.\r\n\r\nh2. Date de intrare\r\n\r\nFisierul de intrare $secv2.in$ contine pe prima linie numerele $N$ si $K$, separate prin spatiu. Pe cea de a doua linie se afla elementele sirului separate prin cate un spatiu.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $secv2.out$ trebuie sa contina o singura linie cu trei numere: pozitia de inceput si de sfarsit a secventei de suma maxima de lungime cel putin $K$ si suma secventei.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; K &le; N &le; 50.000$\r\n* Elementele din vector sunt numere intregi din intervalul $[-25.000, 25.000]$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. secv2.in |_. secv2.out |\r\n| 8 3\r\n0 -6 2 1 4 -1 3 -5 |  3 7 9 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"secv2\")==\n\n\n',1490,'task: secv2',89,NULL),('problema/ferma','Ferma','2006-11-11 11:23:38','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"ferma\")==\r\n\r\n== include(page=\"template/badtests\") ==\r\n\r\nZaharel s-a dus in vizita la bunicii lui de la tara impreuna cu Eugenia. Ferma bunicilor este de forma circulara, iar acolo cresc $N$ gaini. Ferma a fost impartita in $N$ sectoare, numerotate de la $1$ la {$N$}, astfel incat oricare doua sectoare avand numere consecutive sunt adiacente (se afla unul langa altul). In plus, primul si ultimul sector sunt adiacente. In fiecare sector se afla cate o gaina, iar aceasta depune oua in fiecare zi. Bunicii stiu pentu fiecare gaina care este productivitatea ei, adica un numar care reprezinta diferenta dintre consumul gainii si cat produce. Zaharel si cu Eugenia strang de $K$ ori pe zi oua de la gaini astfel: la fiecare strangere cei doi aleg o secventa (adica un sir de sectoare adiacente) formata din cel putin un sector, care contine numai gaini de la care nu s-au luat oua in acea zi.\r\n\r\nh2. Cerinta\r\n\r\nCunoscand productivitatea fiecarea gaini cat si numarul de strangeri dintr-o zi, ajutati-i pe Zaharel si Eugenia sa stranga oua astfel incat suma productivitatilor gainilor de la care a strans oua sa fie maxima.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $ferma.in$ se gasesc numerele naturale $N$ si {$K$}. Pe urmatoarea linie se vor gasi $N$ numere intregi reprezentand productivitatea fiecarei gaini.\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie a fisierului de iesire $ferma.out$ se va afisa suma maxima posibila a productivitatilor gainilor de la care se strang oua.\r\n\r\nh2. Restrictii\r\n\r\n* $2 &le; N &le; 10.000$\r\n* $1 &le; K &le; 1.000$\r\n* Productivitatea fiecarei gaini este un numar intreg din intervalul [{$-100.000, 100.000$}]\r\n* Daca suma maxima posibila a productivitatilor este un numar negativ se va afisa $0$ (se prefera sa nu se stranga nici un ou)\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. ferma.in |_. ferma.out |\r\n| 8 2\r\n2 -6 4 3 -7 -9 10 -1\r\n| 18 |\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"ferma\")==\n\n\n',1490,'task: ferma',307,NULL),('problema/algola','Algola','2006-11-11 11:23:41','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"algola\")==\r\n\r\nIn cadrul organizatiei Algola s-a declarat stare de urgenta. Toti membrii sai, aflati in diferite orase din tara, trebuie sa ajunga cat mai rapid la sediul central. Cele $N$ orase de pe harta tarii sunt numerotate cu numerele de la $1$ la $N$, orasul $1$ fiind locatia sediului central. Strazile ce conecteaza orasele sunt bidirectionale si fiecare dintre strazi poate fi parcursa intr-o unitate de timp de oricare membru Algola. Fiecare strada are o limita de siguranta care indica numarul maxim de membri ce pot circula intr-o unitate de timp pe acea strada. Parcurgerea unei strazi poate incepe numai la momente de timp intregi.\r\n\r\nh2. Cerinta\r\n\r\nFiind data harta oraselor, precum si numarul de membrii ai organizatiei aflati in fiecare oras, sa se calculeze timpul minim $T$ necesar acestora pentru a ajunge la sediul central ({$T$} va fi momentul la care ajunge ultimul membru la sediul central).\r\n\r\nh2. Date de intrare\r\n\r\nPrima linie a fisierului $algola.in$ contine doua numere intregi separate printr-un spatiu, $N$ si $M$, reprezentand numarul de orase de pe harta si numarul de strazi dintre ele. Pe cea de-a doua linie se vor afla N numere separate prin spatii, $A{~1~} A{~2~} ... A{~N~}$ unde $A{~i~}$ reprezinta numarul de membri din orasul $i$. Urmatoarele $M$ linii contin cate trei numere intregi separate prin spatii, $X Y L$, cu semnificatia: intre orasele $X$ si $Y$ exista o strada a carei limita de siguranta este $L$.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $algola.out$ va contine o singura linie numarul $T$ reprezentand timpul minim in care membrii organizatiei ajung la sediul central.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 50$\r\n* $1 &le; M &le; 300$\r\n* Timpul de parcurgere al unui oras este $0$\r\n* Totii membrii vor putea ajunge la sediu central\r\n* Limitele de siguranta ale strazilor sunt numere intregi pozitive din intervalul $[1,10]$\r\n* Toti membrii organizatiei afla de starea de urgenta la momentul $0$\r\n* Organizatia are cel mult $50$ de membri\r\n* Membrii organizatiei pot ramane in orice oras pe o perioada nelimitata de timp\r\n* Pentru $20%$ din teste drumul de la fiecare oras la sediu este unic; pentru inca $30%$ din teste numarul total de membri ai organizatiei va fi maxim $4$\r\n\r\nh2. Exemplu\r\n\r\n\r\ntable(example). |_. algola.in |_. algola.out |\r\n| 4 4\r\n0 5 6 5\r\n1 2 3\r\n1 3 5\r\n4 2 2\r\n4 3 5 | 2 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"algola\")==\n\n\n',1490,'task: algola',427,NULL),('planificare/sponsori','Prezentare infoarena','2007-05-03 18:58:44','2007-11-06 18:02:10','h1. Prezentare infoarena\r\n\r\nh2. Misiunea infoarena\r\n\r\nMisiunea noastra este sa atragem elevii si studentii cei mai buni din domeniul IT si sa le oferim oportunitati de pregatire pe masura lor. Prin materialele si activitatile propuse ii ghidam si ii ajutam sa se pregateasca pentru concursurile nationale si internationale de informatica si programare (vezi pagina de \'marturii\':marturii). Impreuna cu ei vrem sa consolidam si sa extidem comunitatea infoarena, o comunitate deschisa in care fiecare este incurajat sa contribuie si sa impartaseasca ce stie. \r\n\r\nh2. Scurt istoric\r\n\r\ninfoarena a luat fiinta in anul 2003 la initiativa a trei dintre membrii fondatori: Leonard Crestez, Mircea Pasoi si Cristi Strat. Ei is doreau un site de pregatire destinat pasionatilor de informatica din Romania cu evaluare automata disponibila 24/24. Odata lansat, site-ul a devenit primul de acest gen din Romania.\r\n\r\nAl patrulea olimpic, Silviu Ganceanu, s-a alaturat echipei in februarie 2004, cand au organizat primul concurs online. Mai tarziu, celor patru li s-au alaturat alti voluntari pasionati de informatica. In prezent, proiectul infoarena a strans in jurul lui o \'echipa\':echipa-infoarena redutabila de elevi, studenti si profesionisti IT - fosti sau actuali olimpici nationali si internationali.\r\n\r\nIn decembrie 2006 a fost lansat infoarena 2.0, un site construit de la zero care sa-l inlocuiasca pe cel vechi. Oferind o serie de feature-uri noi (rating, profiluri personalizate, pagini wiki, forum integrat) infoarena 2.0 este menit consolideze comunitatea, sa sporesca comunicarea intre membrii acesteia si sa le ofere motivatii noi.\r\n\r\nh2. Comunitatea infoarena\r\n\r\nComunitatea infoarena este formata din 6500+ membri. Printre acestia se numara elevi, studenti si profesori din toata tara. O buna parte din ei sunt implicati activ pregatindu-se impreuna pe tot parcursul anului competitional. Suntem foarte bucurosi ca multi dintre utilizatori \'contribuie\':implica-te la dezvoltarea continutului site-ului. Urmarim ca din randul acestora sa-i promovam in echipa noastra pe cei mai dedicati ei.\r\n\r\nh2. Cum ne indeplinim misiunea\r\n\r\nh4. Concursuri online\r\n\r\nOrganizam periodic \'concursuri online\':concursuri si onsite pe modelul olimpiadelor nationale si internationale. Pana acum am reusit sa organizam peste 30 de astfel de concursuri.\r\n\r\nh4. Arhiva de probleme si evaluator disponibil 24/24\r\n\r\nOferim utilizatorilor nostri o arhiva cu peste 600 de probleme. Acestia isi pot verifica solutiile automat si pot afla in orice moment cat de bine au rezolvat o problema. Arhiva cuprinde probleme propuse in diverse concursuri nationale de profesori de prestigiu si studenti olimpici internationali.\r\n\r\nh4. Forum si pagini de profil personalizate\r\n\r\nPe forum membrii comunitatii comunica si invata impreuna. Ii incurajam permanent sa diagoleze, sa se cunoasca, sa-si faca noi prieteni.\r\n\r\nh4. Articole, downloads, links\r\n\r\ninfoarena reprezinta si o bogata colectie de articole, resurse si legaturi utile fiind un veritabil portal educational. Fiecare utilizator poate contribui la imbogatirea acestei colectii prin imbunatatirea materialelor deja existente sau prin adaugarea unora noi.\r\n\r\nh4. Mediu competitional\r\n\r\nAm construit un mediu competitional oferind utilizatorilor un rating pe baza evolutiei lor in concursuri. In plus, ei sunt stimulati sa se intreaca in clasamentul arhivei si in diversele concursuri organizate de noi.\r\n\r\nh2. Proiecte de viitor\r\n\r\nh4. Dezvoltarea noului site\r\n\r\nIn ciuda tuturor imbunatatirilor aduse de noul site mai avem multe de facut. Dezvoltam constant infrastructura site-ului pentru a le oferi utilizatorilor modalitati performante si moderne de pregatire.\r\n\r\nh4. Organizarea de concursuri cu format inedit\r\n\r\nNe-am gandit la multe concursuri cu format original. Prin intermediul lor urmarim stimularea comunitatii si dezvoltarea unor noi capabilitati ale membrilor comunitatii pe langa cele algoritmice si de programare.\r\n\r\nh4. Promovarea site-ului printre studenti\r\n\r\nConsideram ca materialele de pe site-ul nostru pot fi utile in contextul numeroaselor cursuri de programare, structuri de date si algoritmi din cadrul facultatilor de profil din Romania. Dorim atragerea unui numar si mai mare de studenti pe site-ul nostru prin ineditul modalitatii de pregatire si autoevaluare propus.',1,'public',NULL,NULL),('problema/tvshow','TVShow','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"tvshow\")==\r\n\r\nIntr-un show de televiziune $N$ concurenti participa intr-o competitie pe viata si pe moarte din care doar unul dintre ei poate iesi castigator. Fiecare concurent a adunat pe parcursul emisiunii un numar de puncte, {$S{~i~}$}, si acum urmeaza proba finala. Fiecare dintre ei trebuie sa aleaga una dintre cele doua porti din fata lor. Doar una dintre ele ascunde in spatele ei marele premiu. De asemenea fiecare concurent parieza un numar de puncte {$P{~i~}$} ({$0&le;P{~i~}&le;S{~i~}$}). Daca poarta pe care a ales-o el este cea care ascunde premiul atunci punctajul sau va fi S{~i~}+P{~i~} iar daca nu a ghicit-o S{~i~}-P{~i~}. Concurentul cu punctajul maxim in urma acestei probe va castiga marele premiu. Daca exista mai multe punctaje maxime nu va castiga nimeni. Ultimul concurent, cine altul decat Petrica, se afla in fata unei decizii foarte dificile: el stie punctajele celorlalti concurenti si ce numar de puncte au pariat fiecare dar nu stie ce porti au ales acestia, in schimb stie ca fiecare concurent - chiar si el - are {$50%$} sanse sa ghiceasca poarta castigatoare si {$50%$} sanse sa nu o ghiceasca. Trebuie sa decida ce numar de puncte va paria pentru ca probabilitatea sa de castig sa fie cat mai mare (chiar daca pentru doua moduri de a paria probabilitatile sunt foarte apropiate, diferenta fiind practic nula, Petrica va alege modul pentru care probabilitatea sa de castig este mai mare).\r\n\r\nh2. Cerinta\r\n\r\nCalculati numarul de puncte pe care trebuie sa-l parieze Petrica pentru a avea sanse de castig cat mai mari. Daca exista mai multe solutii alegeti-o pe cea mai mica. De asemenea aflati si probabilitea maxima de castig pe care o poate avea Petrica.\r\n\r\nh2. Date de intrare\r\n\r\nFisierul de intrare $tvshow.in$ va contine pe prima linie numarul intreg $N$ reprezentand numarul de concurenti din concurs. Fiecare din urmatoarele {$N - 1$} linii va contine doi intregi separati printr-un spatiu reprezentand scorul si numarul de puncte pariate pentru fiecare din primii {$N - 1$} concurenti. Ultima linie contine un singur numar intreg reprezentand scorul lui Petrica.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie a fisierului $tvshow.out$ se va afla numarul de puncte pariat de Petrica. Pe urmatoarele doua linii se vor afla doua numere intregi $A$ si $B$ care reprezinta probabilitatea maxima de castig a lui Petrica sub forma de fractie ireductibila (probabilitatea este egala cu {$A/B$}).\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 < N < 301$\r\n* Valorile scorurilor sunt numere intregi din intervalul $[0, 30000]$\r\n* Pentru {$40%$} din teste $N &le; 17$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. tvshow.in |_. tvshow.out |\r\n|3\r\n100 25\r\n100 75\r\n100\r\n|76\r\n1\r\n2 |\r\n|2\r\n10 3\r\n2\r\n|0\r\n0\r\n1 |\r\n|3\r\n50 31\r\n60 41\r\n10\r\n|10\r\n1\r\n8 |\r\n\r\nh3. Explicatii\r\n\r\nPentru primu exemplu, probabilitatea ca Petrica sa castige este de 50% daca alege sa parieze 76 de puncte, indiferent daca primii doi concurenti au ghicit sau nu poarta castigatoare. Daca Petrica a ghicit poarta castigatoare el castiga concursul (acumuland 176 de puncte) iar daca nu a ghicit-o atunci sigur pierde (acumuland 24 de puncte). Daca va paria mai putin de 76 de puncte probabilitatea de a castiga va fi mai mica, iar daca pariaza mai mult probabilitatea va ramane aceeasi.\r\n\r\nPentru cel de-al doilea Petrica pierde orice suma ar paria.\r\n\r\nIn cel de-al treilea exemplu, daca Petrica pariaza 10 puncte are 12.5% sanse sa castige (el castiga doar in cazul in care primii doi concurenti nu ghicesc poarta si el o ghiceste; in oricare din celelalte cazuri Petrica va pierde). Daca pariaza mai putin Petrica va avea 0% sanse de castig.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"tvshow\")==\n\n\n',1490,'task: tvshow',423,NULL),('problema/cifra','Cifra','2006-11-11 11:23:34','2010-03-22 19:52:28','==Include(page=\"template/taskheader\" task_id=\"cifra\")==\r\n\r\nGigel, fiind plictisit, se juca in timpul orei de matematica, desenand pe o foaie. Din pacate, profesorul l-a vazut si i-a spus ca ii pune nota 4 daca nu rezolva urmatoarea problema: pentru o valoarea $N$ data trebuie sa determine ultima cifra a sumei $1^1^ + 2^2^ + ... + N^N^$.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care sa-l ajute pe Gigel si sa determine ultima cifra a acestei sume pentru $T$ valori date ale lui $N$.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie din fisierul $cifra.in$ se va afla numarul $T$. Pe urmatoarele $T$ linii se vor gasi valori ale lui $N$ pentru care trebuie gasit raspunsul.\r\n\r\nh2. Date de iesire\r\n\r\nPe cele $T$ linii ale fisierului $cifra.out$ se vor gasi raspunsurile pentru valorile lui $N$ date in fisierul de intrare.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; T &le; 30.000$\r\n* $*ATENTIE! 1 &le; N < 10^100^*$\r\n* Se acorda punctaj pentru un test doar daca toate cele $T$ valori din fisierul de iesire sunt corecte\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. cifra.in |_. cifra.out |\r\n| 5\r\n1\r\n2\r\n3\r\n4\r\n5\r\n| 1\r\n5\r\n2\r\n8\r\n3 |\r\n\r\nh3. Explicatii\r\n\r\n1^1^  = *1*\r\n1^1^ + 2^2^ = 1 + 4 = *5*\r\n1^1^ + 2^2^ + 3^3^ = 1 + 4 + 27 = 3{*2*}\r\n1^1^ + 2^2^ + 3^3^ + 4^4^ = 1 + 4 + 27 + 256 = 28{*8*}\r\n1^1^ + 2^2^ + 3^3^ + 4^4^ + 5^5^ = 1 + 4 + 27 + 256 + 3125 = 341{*3*}\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"cifra\")==\r\n\r\n\r\n',2028,'task: cifra',35,NULL),('problema/otilia','Otilia','2006-11-11 11:23:41','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"otilia\")==\r\n\r\nOtilia si Burbucel, fiind in fata unei gramezi de $N$ pietre si neavand ce face, stabilesc regulile unui nou joc. Cei doi copii vor ca jocul sa fie simplu asa ca impun doar trei reguli:\r\n1. Primul jucator are voie sa ia din gramada cel mult $K$ piese\r\n2. Cu exceptia primei mutari, fiecare jucator are voie sa ia maxim $P*t$ pietre, unde $t$ este numarul de pietre care au fost substituite din gramada la mutarea precedenta\r\n3. Pierde cel care muta ultimul (cel care ia ultimele pietre din gramada)\r\n\r\nCei doi au jucat multe jocuri, Burbucel fiind intotdeauna cel care alege numerele $N, K$ si $P$ si Otilia primul jucator care muta. Otilia a observat ca alegerile lui Burbucel se repeta dupa $M$ jocuri (alegerea numarul $M+1$ este identica cu alegerea numarul $1$, alegerea numarul $M+2$ este identica cu alegerea numarul $2$, etc.). Ea ar vrea sa stie daca poate castiga sau nu pentru fiecare dintre primele M alegeri ale lui Burbucel. Motivul este usor de intuit: Otilia nu vrea sa-i dea ocazia lui Burbucel sa castige asa ca va renunta pe jocurile unde nu are strategie de castig.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care rezolva dilema Otiliei.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului $otilia.in$ se afla $M$, numarul de alegeri ale lui Burbucel. Urmatoarele $M$ linii contin cate trei numere, $N, K si P$ reprezentand o alegere a lui Burbucel ({$N$} - numarul de pietre din gramada, $K$ - numarul maxim de pietre pe care le poate lua Otilia la prima mutare, $P$ - factorul cu care se inmulteste numarul de pietre luate la mutarea precedenta rezultand astfel numarul maxim de pietre care se pot substitui la mutarea curenta).\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul $otilia.out$ contine $M$ linii, pe linia $i$ aflandu-se $1$ daca Otilia castiga la alegerea numarul $i$ a lui Burbucel sau $0$ daca ea pierde (alegerile sunt numerotate de la $1$ la $M$ in ordinea in care se gasesc in fisierul de intrare).\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; M &le; 30 000$\r\n* $1 &le; N &le; 5 000 000$\r\n* $1 &le; K &le; N$\r\n* $1 &le; P &le; 10$\r\n* Pentru $50%$ din teste $N &le; 500 000$ pentru toate alegerile lui Burbucel\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. otilia.in |_. otilia.out |\r\n|4\r\n1 1 3\r\n3 2 8\r\n5 1 3\r\n100 1 1\r\n|0\r\n1\r\n0\r\n1|\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"otilia\")==\n\n\n',1490,'task: otilia',455,NULL),('problema/tort','Tort','2006-11-11 11:23:35','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"tort\")==\r\n\r\nDe ziua ei, Ionela a facut un tort in forma triunghiulara. Dorind sa-l imparta cu prietenii ei, Ionela efectueaza $A$ taieturi dintr-un colt oarecare si $B$ taieturi din alt colt al tortului (un colt adica un varf al triunghiului initial). Dupa multe astfel de taieturi, ea este dezorientata: oare cate felii de tort in forma triunghiulara a taiat? Prin felie intelegem un triunghi cu taieturi pe laturi si varfuri in intersectiile taieturilor. O felie poate contine si alte taieturi in interior.\r\n\r\nh2. Cerinta\r\n\r\nAjutati-o pe Ionela sa numere feliile de tort in forma triunghiulara.\r\n\r\nh2. Date de intrare\r\n\r\nFisierul $tort.in$ contine pe prima linie numerele $A$ si $B$ separate printr-un spatiu.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul $tort.out$ va contine o linie cu numarul de felii de tort.\r\n\r\nh2. Restrictii\r\n\r\n* $0 &le; A, B &le; 2 000 000 000$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. tort.in|_. tort.out |\r\n|1 2|15 |\r\n|1 0|3 |\r\n\r\nDesenul urmator corespunde ultimului exemplu:\r\n\r\n!problema/tort?tri.jpg!\r\n\r\nCele trei felii sunt: triunghiul mare (tot tortul) si cele 2 mai mici din interior.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"tort\")==\n\n\n',1490,'task: tort',47,NULL),('problema/tj','Tom & Jerry','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"tj\")==\r\n\r\nTom si Jerry joaca un joc intr-un graf neorientat cu $N$ noduri (numerotate de la 1 la $N$). Tom alege unul dintre nodurile grafului si se pozitioneaza in acest nod. Apoi Jerry alege si el unul dintre nodurile grafului (eventual acelasi) si se pozitioneaza in acel nod. Dupa aceste pozitionari _strategice_, incepe jocul efectiv. Tom si Jerry efectueaza mutari alternativ. La fiecare mutare, ei se pot deplasa din nodul in care se afla in orice alt nod invecinat (doua noduri sunt invecinate daca exista o muchie intre ele) sau pot ramane pe loc (in acelasi nod). Tom este cel care efectueaza prima mutare si scopul lui este de a-l prinde pe Jerry. Astfel, Tom castiga jocul daca ajunge in acelasi nod al grafului ca si Jerry. Jerry castiga jocul daca poate sa fuga de Tom la infinit (adica orice mutare ar efectua Tom, la orice moment, Jerry poate efectua la randul lui o mutare prin care sa evite sa ajunga in aceeasi pozitie ca si Tom).\r\n\r\nh2. Cerinta\r\n\r\nPentru un graf dat, determinati daca Tom are strategie sigura de castig.\r\n\r\nh2. Date de intrare\r\n\r\nPrima linie a fisierului $tj.in$ contine numarul natural $T$, reprezentand numarul de grafuri descrise in continuare. Un graf este descris pe o succesiune de linii din fisierul de intrare, dupa cum urmeaza. Prima linie contine numerele naturale $N$ si $M$ reprezentand numarul de noduri, respectiv numarul de muchii ale grafului. Fiecare dintre urmatoarele $M$ linii contine cate 2 numere naturale $a$ si $b$, avand semnificatia ca exista muchie intre nodurile $a$ si $b$. Intre descrierile a doua grafuri consecutive din fisierul de intrare se afla o linie goala.\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul de iesire $tj.out$ veti afisa pentru fiecare graf din fisierul de intrare (in ordinea in care sunt descrise grafurile in fisier) $DA$, in caz ca Tom are strategie sigura de castig, respectiv $NU$, in caz contrar.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; T &le; 20$\r\n* $1 &le; N &le; 256$\r\n* $0 &le; M &le; N*(N-1)/2$\r\n* Nu exista muchie de la un nod la el insusi\r\n* Intre doua noduri ale grafului exista cel mult o muchie\r\n* Cel putin $60%$ din teste vor avea $N &le; 64$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. tj.in |_. tj.out |\r\n|6\r\n2 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n4 4\r\n1 2\r\n1 3\r\n2 3\r\n3 4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n3 2\r\n1 2\r\n2 3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n2 1\r\n1 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n1 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \r\n4 4\r\n1 2\r\n2 3\r\n3 4\r\n4 1\r\n|NU\r\nDA\r\nDA\r\nDA\r\nDA\r\nNU|\r\n\r\n \r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"tj\")==\n\n\n',1490,'task: tj',419,NULL),('problema/evantai','Evantai','2006-11-11 11:23:40','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"evantai\")==\r\n\r\n\r\nLui Algorel ii plac mult sirurile de numere naturale cu proprietati cat mai ciudate. Cautand astfel de ciudatenii ale informaticii, a gasit printr-o carte prafuita de vreme un nou tip de sir denumit evantai. Un evantai este un sir cu un numar par de termeni, $E{~1~} E{~2~} ... E{~2K~}$, cu urmatoarea proprietate:\r\n\r\np=. $E{~1~} + E{~2K~} > E{~2~} + E{~2K-1~} > ... > E{~K~} + E{~K+1~}$\r\n\r\nh2. Cerinta\r\n\r\nFiind dat un sir de numere naturale distincte $A{~1~} A{~2~} ... A{~N~}$, Algorel vrea sa afle cate subsiruri ale acestuia sunt evantaie.\r\n\r\nh2. Date de intrare\r\n\r\nPrima linie a fisierului $evantai.in$ contine numarul intreg $N$, reprezentand numarul de elemente ale sirului. Urmatoarele $N$ linii contin, in ordine, elementele sirului $A$.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie a fisierului $evantai.out$ se va afla un singur numar intreg $C$, reprezentand numarul de subsiruri evantai. Rezultatul va fi afisat modulo $30103$.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $2 &le; N &le; 700$\r\n* Elementele sirului sunt numere intregi distincte cuprinse intre $1$ si $1000$\r\n* Prin subsir se intelege orice insiruire de termeni $A{~i1~} A{~i2~} ... A{~ik~}$ astfel incat $i{~1~} < i{~2~} < ... < i{~k~}$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. evantai.in |_. evantai.out | \r\n| 4\r\n1\r\n2\r\n3\r\n6 | 7 |\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"evantai\")==\n\n\n',1490,'task: evantai',426,NULL),('problema/subsir','Subsir','2006-11-11 11:23:37','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"subsir\")==\r\n\r\nZaharel incearca s-o invete pe prietena lui Eugenia informatica. Astazi a invat-o programare dinamica si anume a inceput cu problema celui mai lung subsir comun: dandu-se doua siruri, sa se determine cel mai lung subsir comun al celor doua siruri. Un subsir al unui sir este format din caractere (nu neaparat consecutive) ale sirului respectiv, in ordinea in care acestea apar in sir.\r\n\r\nEugenia a inteles rezolvarea problemei dar i-a pus urmatoarea intrebare lui Zaharel: cate subsiruri comune de lungime maxima distincte exista pentru cele doua siruri? Doua subsiruri sunt distincte daca exista cel putin un caracter in unul din ele care difera de caracterul din celalat subsir de pe aceeasi pozitie.\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l pe Zaharel si determinati restul impartirii numarului de subsiruri comune de lungime maxima distincte pentru doua siruri date, la numarul $666013$.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare se gaseste primul sir, iar pe a doua linie cel de-al doilea sir.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie a fisierului de iesire se va gasi numarul cerut.\r\n\r\nh2. Restrictii\r\n\r\n* fiecare sir are lungime mai mica sau egala cu $500$\r\n* sirurile contin doar litere mici ale alfabetului englez\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. subsir.in |_. subsir.out |\r\n| banana\r\noana\r\n| 1 |\r\n\r\nh3. Explicatii\r\n\r\nSigurul subsir comun de lungime maxima care se poate forma este @ana@.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"subsir\")==\n\n\n',1490,'task: subsir',212,NULL),('problema/gard2','Gard2','2006-11-11 11:23:41','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"gard2\")==\r\n\r\nDupa succesul avut la vopsirea primului gard, echipa de muncitori a fost angajata sa vopseasca gardul unuia dintre cei mai bogati oameni din oras. Fiind multumiti de suma oferita intregii echipe, muncitorii nu au mai facut prea multe mofturi de data aceasta. Ei s-au decis, insa, sa lucreze in ture: intai muncitorii din prima tura, apoi cei din a doua s.a.m.d. In cadrul fiecarei ture vor lucra *cel putin unul* si *cel mult $K$* muncitori. De asemenea, fiecare muncitor va lucra in *exact* o tura. Surprins de modul de organizare in ture a muncitorilor si fiind un iubitor al problemelor de numarare, proprietarul gardului doreste sa afle in cate moduri pot fi aranjati muncitorii in ture. Intrucat a anuntat ca va oferi o suma frumusica celui care ii va da raspunsul in mai putin de o secunda, ati decis sa scrieti un program care sa va ajute sa castigati premiul pus in joc.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care, pentru valorile $N$ si $K$ date, determina cate posibilitati de aranjare a celor $N$ muncitori in ture exista, astfel incat in fiecare tura sa lucreze cel putin unul si cel mult $K$ dintre ei.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $gard2.in$ se afla doi intregi: $N$ si {$K$}, reprezentand numarul total de muncitori si numarul maxim de muncitori ce pot lucra simultan (intr-o tura).\r\n\r\nh2. Date de Iesire\r\n\r\nIn fisierul de iesire $gard2.out$ veti afisa numarul determinat.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; K &le; N &le; 50$\r\n* Doua posibilitati de asezare sunt distincte daca exista cel putin un muncitor care lucreaza in ture cu numere de ordine diferite.\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. gard2.in |_. gard2.out |\r\n| 3 2 | 12 |\r\n| 4 1 | 24 |\r\n| 5 3 | 530 |\r\n\r\n\r\nh3. Explicatie\r\n\r\nPentru primul exemplu, posibilitatile de aranjare in ture sunt:\r\n\r\n|_. Varianta 1 |_. Varianta 2 |_. Varianta 3 |_. Varianta 4 |_. Varianta 5 |_. Varianta 6 |\r\n| Tura1: *1 2*\r\nTura2: *3*\r\n| Tura1: *1 3*\r\nTura2: *2*\r\n| Tura1: *3 2*\r\nTura2: *1*\r\n| Tura1: *1*\r\nTura2: *2 3*\r\n| Tura1: *2*\r\nTura2: *3 1*\r\n| Tura1: *3*\r\nTura2: *1 2* |\r\n|_. Varianta 7 |_. Varianta 8 |_. Varianta 9 |_. Varianta 10 |_. Varianta 11 |_. Varianta 12 |\r\n| Tura1: *1*\r\nTura2: *2*\r\nTura3: *3*\r\n| Tura1: *1*\r\nTura2: *3*\r\nTura3: *2*\r\n| Tura1: *2*\r\nTura2: *1*\r\nTura3: *3*\r\n| Tura1: *2*\r\nTura2: *3*\r\nTura3: *1*\r\n| Tura1: *3*\r\nTura2: *1*\r\nTura3: *2*\r\n| Tura1: *3*\r\nTura2: *2*\r\nTura3: *1* |\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"gard2\")==\n\n\n',1490,'task: gard2',454,NULL),('problema/pavare','Pavare','2006-11-11 11:23:35','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"pavare\")==\r\n\r\nGigel, primar in orasul sau, s-a gandit sa renoveze strada principala, strada de dimensiuni $M*N$ compusa din bucati de dimensiuni $1*1$. Majoritatea bucatilor sunt stricate, dar mai exista $K$ bucati care sunt considerate bune. Dorind sa plateasca cat mai putini bani, Gigel a luat de la un negustor blocuri de dimensiuni $2*2$ la pretul unui bloc de dimensiuni $1*1$. Pentru a pava strada trebuie sa amplaseze cat mai multe din aceste blocuri pe bucati stricate, fara sa paveze vreo bucata buna deoarece ar aparea denivelari, si fara sa se suprapuna blocurile $2*2$. El si-a dat seama ca mai bine ar fi cumparat blocuri $1*1$, pentru ca ar fi acoperit toata strada fara batai de cap, dar acum nu mai are de ales si are nevoie de ajutorul tau!\r\n\r\nh2. Cerinta\r\n\r\nDeterminati numarul maxim de blocuri $2*2$ pe care le poate pune primarul pentru a repara strada.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie din fisierul $pavare.in$ se vor afla trei numere intregi separate prin cate un spatiu: $N, M$ si $K$. Pe urmatoarele $K$ linii se vor afla perechi de numere intregi reprezentand linia si coloana pe care se afla o bucata buna.\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie in fisierul $pavare.out$ se va afla un numar natural reprezentand numarul maxim de blocuri $2*2$ care pot fi amplasate pe strada.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 150$\r\n* $1 &le; M &le; 15$\r\n* $1 &le; K &le; N*M$\r\n* Liinile sunt numerotate de la $1$ la $N$, iar coloanele de la $1$ la $M$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. pavare.in |_. pavare.out |\r\n| 4 6 3\r\n1 1\r\n2 6\r\n3 3 | 4 | \r\n\r\nh3. Explicatie\r\n\r\nAcesta este un amplasament posibil al blocurilor:\r\n!problema/pavare?untitled.gif! \r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"pavare\")==\n\n\n',1490,'task: pavare',46,NULL),('documentatie/trimiterea-solutiilor','Trimiterea solutiilor','2006-11-27 05:08:00','2007-10-29 20:32:54','h1. Trimiterea solutiilor\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\ninfoarena dispune de un \'evaluator automat\':documentatie/evaluator care compileaza si testeaza solutiile trimise de tine.\r\n\r\nSolutiile se pot trimite in doua feluri:\r\n\r\n* Cel mai simplu, folosesti formularul de sub fiecare enunt. Vezi \'problema A+B\':problema/adunare\r\n* Alternativ dai click pe optiunea _Trimite solutii_ din meniul din stanga, iti alegi problema la care trimiti solutie, fisierul solutie de pe calculatorul tau si dai click pe _Trimite solutia_\r\n\r\nCiteste pe \'pagina evaluatorului\':documentatie/evaluator despre ce compilatoare folosim la infoarena.',1142,'public',NULL,NULL),('problema/robot','Robot','2006-11-11 11:23:39','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"robot\")==\r\n\r\nGigel tocmai si-a cumparat un joc de strategie. Actiunea jocului ia loc pe o harta plana. Pe harta se gaseste un mic robotel si cateva obstacole. Scopul jocului este de a muta robotelul intr-un anumit loc. Fiindca nu se pricepe prea bine la jocuri pe calculator, Gigel va roaga sa-l ajutati.\r\n\r\nRobotelul si obstacolele sunt reprezentate de poligoane convexe, cu varfurile in puncte de coordonate intregi. Spunem ca robotelul se afla intr-o pozitie valida pe harta daca poligonul care il reprezinta nu se intersecteaza cu interiorul nici unui obstacol. Daca robotelul este tangent la unul sau mai multe obstacole, fara a intersecta insa interiorul nici unuia dintre ele, pozitia lui este valida.\r\n\r\nPe tot parcursul jocului obstacolele raman nemiscate si nerotite. De asemenea, robotelul nu se poate roti, insa acesta se poate misca in orice directie. Pe tot parcursul miscarii sale, robotelul trebuie sa ramana intr-o pozitie valida.\r\n\r\nPozitia robotelului pe harta se defineste ca fiind punctul ({$x,y$}), cu $y$ egal cu minimul ordonatelor varfurilor robotelului si cu $x$ egal cu minimul absciselor varfurilor robotelului. Curba desenata de pozitia robotelului in timpul miscarii sale in plan se numeste drumul robotelului.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care citeste configuratia initiala a hartii si care calculeaza lungimea unui drum minim parcurs de robotel pentru a ajunge intr-o pozitie finala.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare $robot.in$ se gaseste numarul $N$ de varfuri ale poligonului reprezentand robotelul. Pe urmatoarele $N$ linii se gasesc coordonatele $x$ si $y$ ale varfurilor robotelului, coordonate separate printr-un spatiu. Pe urmatoarea linie se gaseste numarul $M$ de obstacole. Apoi urmeaza $M$ blocuri reprezentand cate un obstacol, fiecare bloc avand urmatoarea structura:\r\n\r\n* pe prima linie a blocului numarul de varfuri $P$ ale poligonului ce reprezinta obstacolul\r\n* pe urmatoarele $P$ linii, coordonatele $x$ si $y$ ale varfurilor obstacolului, coordonate separate printr-un spatiu.\r\nPe ultima linie a fisierului de intrare, se gasesc coordonatele $x$ si $y$ ale pozitiei in care trebuie sa ajunga robotelul.\r\n\r\nh2. Date de iesire\r\n\r\nPe singura linie a fisierului de iesire $robot.out$ afisati cu doua zecimale exacte distanta minima parcursa de robot pana la pozitia finala pe un drum care respecta cerintele de mai sus. Daca nu exista nici un astfel de drum afisati {$-1$}.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $N &le; 10$\r\n* $M &le; 25$\r\n* toate coordonatele sunt din intervalul ({$-5000,5000$})\r\n* numarul de varfuri de pe poligoanele tuturor obstacolelor nu depaseste $250$\r\n* puteti presupune ca pozitia initiala a robotelului este valida.\r\n* in fisierul de intrare, pentru toate poligoanele, punctele sunt date in sens trigonometric.\r\n* solutia afisata de voi este considerata corecta daca difera de solutia comisiei in valoare absoluta prin cel mult $0.02$\r\n* unii sustin ca adevaratul campion este cel care rezolva *ivv* adevarul este insa ca singurul care poate determina adevaratul campion este robotelul\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. robot.in |_. robot.out |\r\n| 3\r\n0 0\r\n2 0\r\n0 2\r\n1\r\n4\r\n3 0\r\n5 0\r\n5 2\r\n3 2\r\n6 2\r\n| 7.24 |\r\n\r\nh3. Explicatii\r\n\r\n !problema/robot?robot.gif! \r\n\r\nRobotelul apare punctat si obstacolul este desenat cu linie ingrosata. Cerculetul reprezinta pozitia finala a robotelului. Cu o linie usor ingrosata este marcat si un drum de lungime minima.\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"robot\")==\n\n\n',1490,'task: robot',390,NULL),('problema/tabela','Tabela','2006-11-11 11:23:34','2008-11-15 16:19:40','==Include(page=\"template/taskheader\" task_id=\"tabela\")==\r\n\r\nMacarie, pasionat de numere, si mai ales de matrici, incepe intr-o zi sa umple o foaie infinita de matematica cu numere astfel: in coltul cel mai de sus stanga (1, 1) pune 0, apoi scrie de la stanga la dreapta si de sus in jos cel mai mic numar care nu apare pe linia si coloana respectiva. Dandu-se linia si coloana unei casute din tabela aflati numarul de la acea pozitie.\r\n\r\nh2. Date de intrare\r\n\r\nFisierul de intrare $tabela.in$ contine pe prima si singura linie numerele $L$ si $C$, linia si coloana patratelului a carui valoare dorim sa o determinam.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $tabela.out$ contine pe prima linie numarul scris pe foaie la linia $L$ si coloana $C$.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* L si C sunt numere naturale din intervalul $[1, 2 000 000 000]$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. tabela.in|_. tabela.out|_. tabela.in|_. tabela.out|\r\n|2 3|3|4 5|7|\r\n\r\n_Explicatie_: Prima parte a tabelei va arata in felul urmator:\r\n!problema/tabela?tabela.jpg!\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"tabela\")==\n\n\n',1490,'task: tabela',36,NULL),('problema/rubarba','Rubarba','2006-11-11 11:23:38','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"rubarba\")==\r\n\r\nProaspat evadat din temnita, _Paftenie barbarul_ a decis ca este timpul sa puna capat pentru o vreme aventurilor sale. Intorcandu-se la familia lui, s-a dedicat unui nou hobby: gradinaritul. De data aceasta a plantat in gradina sa $N$ tulpini de rubarba. Nefiind specialist in domeniu, a plantat tulpinile aleator, iar acum se pune problema construirii unei sere. Sera trebuie sa fie de forma dreptunghiulara, sa contina in interiorul sau toate tulpinile de rubarba, iar aria sa sa fie minima.\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l pe gradinarul _Paftenie_ sa rezolve problema!\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare este dat numarul $N$ al tulpinilor de rubarba. Pe urmatoarele $N$ linii se afla cate o pereche de numere intregi, reprezentand coordonatele acestora.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire va contine pe prima linie un singur numar real, reprezentand aria minima a dreptunghiului cerut.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1$ &le; $N$ &le; $100.000$\r\n* coordonatele plantelor sunt numere intregi cuprinse intre $0$ si $1.000.000$\r\n* rezultatul se va afisa cu o precizie de $2$ zecimale\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. rubarba.in |_. rubarba.out |\r\n| 9\r\n2 1\r\n4 2\r\n7 2\r\n1 4\r\n7 4\r\n5 6\r\n6 8\r\n8 8\r\n3 9\r\n| 50.32 |\r\n\r\nh3. Explicatie\r\n\r\n!problema/rubarba?rubarba.jpg!\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"rubarba\")==\n\n\n',1490,'task: rubarba',245,NULL),('problema/bombar','Bombar','2006-11-11 11:23:39','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"bombar\")==\r\n\r\nIn timpul bombardamentelor, Paftenie a devenit genist. Trebuie sa dezamorseze niste bombe aflate adanc in pamant si asta repede. Sunt exact $2*N$ bombe, asezate in doua randuri paralele, ca in figura urmatoare:\r\n\r\n!problema/bombar?bombar0.png!\r\n\r\nIntre oricare doua bombe consecutive din acelasi rand sau o bomba si corespunzatoarea sa din celalalt rand se poate sapa un tunel (bombele intre care se pot sapa tuneluri apar legate in figura). Trebuie sa le dezamorseze pe toate, una care una, sapand exact $2*N-1$ tuneluri si trebuie sa poata circula intre oricare doua bombe numai prin tunelurile sapate. Inainte de a trece la treaba, Paftenie se intreaba in cate moduri se pot sapa tunelurile.\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l sa afle pana nu e prea tarziu!\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $bombar.in$ este dat numarul $N$ al bombelor de pe un sir.\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul de iesire $bombar.out$ va contine pe prima linie un singur numar, reprezentand numarul de posibilitati in care se pot sapa tunelurile.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 20.000$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. bombar.in |_. bombar.out |\r\n| 2 | 4 | \r\n\r\nh3. Explicatie\r\n\r\nBombele sunt plasate astfel: \r\n\r\n!problema/bombar?bombar1.png!\r\n\r\nPaftenie poate sapa tunelurile in 4 feluri:\r\n\r\n!problema/bombar?bombar2.png!\r\n\r\ntable(example). |_. bombar.in |_. bombar.out |\r\n|3 |15 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"bombar\")==\n\n\n',1490,'task: bombar',383,NULL),('problema/adunare','A+B','2006-11-11 11:23:33','2010-03-20 13:47:38','==Include(page=\"template/taskheader\" task_id=\"adunare\")==\r\n\r\nAdunare simplă.\r\n\r\nh2. Date de intrare\r\n\r\nDatele de intrare se citesc din fişierul $adunare.in$:\r\n\r\n* pe prima linie un număr intreg $a$\r\n* pe a doua linie un număr intreg $b$\r\n\r\nh2. Date de ieşire\r\n\r\nDatele de ieşire se tipăresc în fişierul $adunare.out$\r\n\r\n* pe prima linie: suma celor două numere $a + b$\r\n\r\nh2. Restricţii\r\n\r\n* Suma celor două numere nu va depăşi niciodată valoarea $2 000 000 000$.\r\n\r\nh2. Precizare\r\n\r\n* Problema e dată pentru a vă obişnui cu site-ul. Nu e nevoie să postaţi pe forum că e foarte uşoara, ştim cu toţii asta. :)\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. adunare.in |_. adunare.out |\r\n| 131\r\n  245\r\n| 376 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"adunare\")==\r\n',1490,'task: adunare',27,NULL),('problema/munte','Munte','2006-11-11 11:23:35','2010-02-19 20:22:18','==Include(page=\"template/taskheader\" task_id=\"munte\")==\r\n\r\nGheorghe vrea sa cucereasca un munte. El are anumite informatii despre munte. Stie cat de inalt este muntele si care e distanta pana la celaltalta parte a muntelui. El mai are si o lista cu puncte speciale prin care trebuie sa treaca, despre acest puncte stie inaltimea lor si ordinea in care apar, nu stie distanta dintre aceste puncte. Muntele este format din $3$ tipuri de teren.\r\n\r\n!problema/munte?img4.jpg!\r\n\r\n* Tipul 1: teren crescator, unde muntele creste un metru pe verticala pentru fiecare metru pe orizontala.\r\n* Tipul 2: teren drept. Pe acesta portiune terenul nici nu urca nici nu coboara.\r\n* Tipul 3: teren descrescator , unde muntele scade un metru pe verticala pentru fiecare metru pe orizontala.\r\n\r\nh2. Cerinta\r\n\r\nGheorghe avand toate aceste informatii, $N$ (inaltimea maxima a muntelui, presupunand ca muntele incepe la nivelul $0$ si se termina la nivelul $0$), $D$ - distanta pe orizontala a muntelui si inaltimea la fiecare punct special, vrea sa stie cate posibilitati are de a parcurge muntele.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie din fisierul $munte.in$ se va afla numarul $N$ - inaltimea maxima a muntelui, $D$ - distanta pe orizontala a muntelui si $K$ - numarul de puncte speciale.\r\nPe urmatoarele $K$ linii sunt scrise inaltimile punctelor speciale\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie a fisierului $munte.out$ se va gasi $P$ - numarul de posibilitati de a traversa muntele.\r\n\r\nObservatii\r\n\r\n* Gheoghe incepe la nivelul $0$ si trebuie sa termine la nivelul $0$\r\n* Doar incepul si sfasitul au nivelul $0$!\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; N &le; 50$\r\n* $1 &le; D &le; 100$\r\n* $0 &le; K &le; 50$\r\n* $0 &le; P &le; 2^63^-1$\r\n\r\nExemple\r\n\r\ntable(example). |_. munte.in |_. munte.out |\r\n| 2 5 0\r\n| 3 |\r\n\r\nh3. Explicatii \r\n\r\nCele 3 posibilitati diferite sunt:\r\n  !problema/munte?img1.jpg!\r\n  !problema/munte?img2.jpg!\r\n  nu este o parcurgere valida pentru ca inaltimea muntelui nu este $2$, ci $1$\r\n\r\ntable(example). |_. munte.in |_. munte.out |\r\n| 2 5 2 \r\n  2\r\n  2\r\n| 1 |\r\n\r\nh3. Explicatii \r\n\r\n!problema/munte?img3.jpg!\r\n\r\nSingura parcurgere posibila este cea de sus\r\n\r\ntable(example). |_. munte.in |_. munte.out |\r\n| 3 8 4\r\n  2\r\n  2\r\n  3\r\n  1 \r\n| 7 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"munte\")==\r\n\r\n\r\n',2044,'task: munte',86,NULL),('problema/concurs','Concurs','2006-11-11 11:23:39','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"concurs\")==\r\n\r\nFuree Pede s-a angajat la BIT (aceasta firma are structura ierarhica in forma de arbore) si a primit sarcina de a gestiona un concurs. La acest concurs participa cu proiecte echipe de cate doi angajati. Numarul de puncte acumulate de echipa este cel daruit de cel mai mic sef comun al celor doi componenti din echipa. Se cunosc echipele participante la concurs, ierarhia firmei si numarul de puncte pe care le poate darui fiecare angajat.\r\n\r\nh2. Cerinta\r\n\r\nFuree Pede va cere ajutorul si vrea sa afle echipa castigatoare (cea care primeste cele mai multe puncte).\r\n\r\nh2. Date de Intrare\r\n\r\nPrima linie a fisierului $concurs.in$ se afla $N$ si $M$, separate prin cate un spatiu. $N$ reprezinta numarul angajatilor , iar $M$ numarul echipelor participante la concurs. Pe urmatoarea linie se afla $N$ numere naturale reprezentand punctele pe care le poate darui fiecare angajat. Urmatoarele $N-1$ linii contin cate doua numere $X,Y$ care descriu ierarhia firmei({$X$} este seful lui $Y$). In final urmeaza $M$ linii cu cate doua numere, reprezentand numerele de ordine ale componentilor fiecarei echipe.\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie a fisierului $concurs.out$ se va afisa trei numare, primul reprezentand punctajul echipei castigatoare , iar celelalte doua componentii echipei castigatoare.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $0 < N < 32001$\r\n* $0 < M < 500001$\r\n* Punctajul maxim este mai mic decat $2.000.000.000$\r\n* In cazul in care un component al unei echipe este seful celuilalt atunci proectul primeste puncte chiar de la acesta.\r\n* In cazul in care mai multe echipe realizeaza acelasi punctaj se va afisa echipa in care numarul de ordine al primului component este mai mic,iar daca si acesta este egal se va afisa echipa in care numarul de ordine celui de-al doilea component este mai mic.\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. concurs.in|_. concurs.out|\r\n| 5 2\r\n6 4 2 2 2 \r\n1 2 \r\n1 5 \r\n2 3 \r\n2 4 \r\n3 4 \r\n3 2 | 4 3 2 |\r\n\r\nh3. Explicatie\r\n\r\nSeful comun al lui 3 4 este 2, echipa castiga 4. Seful comun al lui 3 2 este 2 , echipa castiga 4. Raspunsul este 3 2 deoarece 3=3,dar 2<4.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"concurs\")==\n\n\n',1490,'task: concurs',396,NULL),('problema/regine','Regine','2006-11-11 11:23:39','2008-11-15 16:19:42','==Include(page=\"template/taskheader\" task_id=\"regine\")==\r\n\r\nPe o tabla triunghiulara de latura $N$, trebuiesc asezate cat mai multe regine, astfel incat acestea sa nu se atace.\r\n\r\nO tabla triunghiulara, de latura $N$, are $N$ linii. Pe linia $i$ sunt $i$ locuri in care reginele pot sta, iar locurile sunt asezate sub forma de triunghi, ca in figura de mai jos. Fiind vorba de o tabla mai speciala si reginele sunt speciale, in sensul ca ele se pot deplasa (ataca) in $6$ directii.\r\n\r\n!problema/regine?regine.jpg!\r\n\r\nIn figura de mai sus este reprezentata o tabla de latura $6$, cu o regina pe linia $5$, coloana $4$. Numerotarea liniilor si coloanelor incepe de la $1$ (din varful tablei in jos - pentru linii si de la stanga la dreapta pentru coloane).\r\n\r\nh2. Cerinta\r\n\r\nDeterminati numarul maxim de regine ce pot fi asezate pe o tabla de dimensiune $N$ si o asezare posibila a lor (oricare dintre solutiile cu numar maxim).\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului se afla un numar natural $N$, reprezentand dimensiunea tablei.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul va contine pe prima linie un singur numar intreg, $X$, reprezentand numarul maxim de regine ce pot fi asezate. Pe urmatoarele $X$ linii se vor scrie cate $2$ numere separate de un singur spatiu, reprezentand linia si respectiv coloana reginelor.\r\n\r\nh2. Restrictii\r\n\r\n* $1 < N < 1 001$\r\n* daca un test are numarul corect de regine, dar configuratia reginelor nu este valida, se acorda $30%$ din punctajul testului.\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. regine.in |_. regine.out |\r\n| 3\r\n| 2\r\n2 1\r\n3 3 |\r\n\r\nh3. Explicatii\r\n\r\nPutem aseza maxim $2$ regine: una pe linia $2$, coloana $1$ si una pe linia $3$, coloana $3$.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"regine\")==\n\n\n',1490,'task: regine',389,NULL),('problema/patrate','Patrate','2006-11-11 11:23:39','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"patrate\")==\r\n\r\nCiobanasul Ion vrea sa isi inchida oile in tarcuri si printr-o coincidenta fericita prietenul lui, Vasile are o firma de construit tarcuri. Cum Vasile este bun prieten cu Ion i-a propus sa ii construiasca tarcurile gratis, cu conditia ca ele sa aiba un cost cat mai mic. Vasile accepta sa construiasca cel mult trei tarcuri de forma unor patrate cu laturile paralele cu axele de coordonate. Aceste patrate trebuie sa contina in interior toate oile, consideram pentru simplitate ca o oaie este un punct in plan. Pentru a obtine un cost cat mai mic, trebuie ca latura celui mai mare tarc sa fie cat mai scurta posibil. Tarcurile se pot intersecta, iar un punct de pe marginea tarcului se considera in interior.\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l pe Ion sa gaseasca o solutie care sa il multumeasca pe Vasile.\r\n\r\nh2. Date de intrare\r\n\r\nIn fisierul de intrare $patrate.in$ se afla pe prima linie un numar natural $n$ ce reprezinta numarul oilor lui Ion, iar pe urmatoarele $n$ linii pozitiile oilor, adica fiecare astfel de linie contine doua numere intregi $x, y$ separate printr-un singur spatiu ce reprezinta pozitia unei oi (abscisa si ordonata).\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $patrate.out$ va contine un numar natural ce reprezinta latura minima care o poate avea cel mai mare tarc dintre cele trei, astfel incat toate oile sa fie in interiorul celor trei tarcuri.\r\n\r\nh2. Restrictii\r\n\r\n* $1&le;n&le;50000$\r\n* Coordonatele oilor sunt numere intregi din intervalul $[0, 50000]$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. patrate.in |_. patrate.out |\r\n|6\r\n1 0\r\n2 1\r\n3 2\r\n3 4\r\n5 4\r\n6 0\r\n| 2 |\r\n\r\nh3. Explicatii\r\n\r\n!problema/patrate?image001.gif!\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"patrate\")==\r\n\r\n\r\n',1490,'task: patrate',388,NULL),('problema/pascal','Pascal','2006-11-11 11:23:37','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"pascal\")==\r\n\r\nIon a invatat la ora de matematica despre triunghiul lui Pascal. Fiecare rand din acest triunghi are primul si ultimul element egal cu $0$. Un element din triunghi se calculeaza ca fiind suma celor $2$ elemente exact deasupra acestuia. Randurile sunt numerotate de la $0$, deci, spre exemplu, randul $2$ contine: $1 2 1$. Este un fapt binecunoscut ca valoarea elementului $j$ (cu indexarea elementelor de la $0$) de pe linia $i$ se poate calcula si cu ajutorul formulei: $i!/((i-j)!*j!$) . (Prin $i!$ se intelege produsul $1*2*...*i$).\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l pe Ion sa calculeze cate numere de pe randul $R$ sunt divizibile la $D$.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare $pascal.in$ se gasesc numerele $R$ si $D$.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie a fisierului de iesire $pascal.out$ se va gasi numarul cerut.\r\n\r\nh2. Restrictii\r\n\r\n* $0 &le; R &le; 5.000.000$\r\n* $2 &le; D &le; 6$\r\n* Observatie: $0 != 1$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. pascal.in |_. pascal.out |\r\n| 4 2\r\n| 3 |\r\n\r\nh3. Explicatii \r\n\r\n!problema/pascal?pascal.gif! \r\n\r\nRandul $4$ contine elementele :\r\n$1 4 6 4 1$\r\ndintre care $4$, $6$ si $4$ sunt divizible la $2$ \r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"pascal\")==\n\n\n',1490,'task: pascal',241,NULL),('taietura-minima','Taietura minima in graf cu costuri','2007-02-03 12:57:37','2009-02-20 01:23:25','h1. Taietura minima in graf cu costuri\r\n\r\n(Categoria _Algoritmi_, Autor _Andrei Grigorean_)\r\n\r\nArticolul de fata isi propune sa studieze problema gasirii unei taieturi minime intr-un graf neorientat cu costuri. Algoritmul prezentat este simplu atat ca implementare, cat si ca demonstrare a corectitudinii, iar timpul sau de executie este la fel de bun ca al oricarui algoritm cunoscut pana in momentul de fata.\r\n\r\nh2. Introducere\r\n\r\nConectivitatea este una din problemele clasice in teoria grafurilor, avand multe aplicatii practice, iar gasirea unei taieturi minime intr-un graf cu costuri este fundamentala in algoritmica. Pentru a fi mai precisi, ea consta in partitionarea unui set de noduri in doua multimi nevide, astfel incat suma costurilor muchiilor dintre cele doua multimi sa fie minima. Metodele clasice de abordare a acestei probleme sunt in stransa legatura cu gasirea unui flux maxim intr-o retea de transport. Ford si Fulkerson [1956] au enuntat teorema flux maxim - taietura minima, care arata dualitatea dintre fluxul maxim al unei retele de transport si taietura minima ce poate fi facuta astfel incat sursa si destinatia retelei sa se afle in multimi diferite. Gasirea unei taieturi minime fara sa fie specificate 2 noduri care sa se afle in multimi diferite, se poate face fixand un nod sursa, iar destinatia luand pe rand toate valorile diferite de sursa, in final alegandu-se optimul. Algoritmul prezentat in acest articol insa nu se foloseste de nicio metoda care are legatura cu fluxul maxim.\r\n\r\nh2. Algoritm\r\n\r\nPe parcursul articolului, vom considera un graf neorientat $G$, multimea nodurilor o vom nota cu $V$, iar pe cea a muchiilor cu $E$. Fiecare muchie $e$ are un cost asociat $w(e)$. Pentru a rezolva problema, vom cauta o modalitate cat mai simpla de a gasi 2 noduri $s$ si $t$, precum si valoarea taieturii minime $s-t$. Urmatoarea teorema ne explica de ce este necesar acest lucru:\r\n\r\nTeorema 1: _Fie $s$ si $t$ doua noduri dintr-un graf $G$. Notam cu $G/{s,t}$ graful obtinut din $G$ prin fuzionarea nodurilor $s$ si $t$. Atunci taietura minima a grafului $G$ este cea mai mica dintre taietura minima $s-t$ a grafului $G$ si taietura minima a grafului $G/{s,t}$._\r\n\r\nTeorema este adevarata deoarece facand o taietura minima in graf nodurile $s$ si $t$ fie vor fi in multimi diferite (primul caz tratat), fie in aceeasi multime (cel de-al doilea caz).\r\n\r\nAsadar o procedura care gaseste o taietura minima _$s-t$ arbitrara_ poate fi folosita pentru a construi un algoritm recursiv ce gaseste taietura minima.\r\n\r\nUrmatorul algorim, care poarta denumirea de _cautare maxima de adiacenta_ (in engleza _maximum adjacency search_ sau _maximum cardinality search_) gaseste taietura _$s-t$_ dorita:\r\n\r\n== code(c) |\r\nFazaTaieturiiMinime(G, w, a)\r\n    A <- {a}\r\n    while A != V\r\n        adauga in A nodul cel mai puternic conectat\r\n    retine taietura si micsoreaza graful G prin fuzionarea ultimelor doua noduri adaugate\r\n==\r\n\r\nExplicatie: O submultime $A$ a lui $V$ creste incepand cu un nod arbitrar pana cand $A$ devine egala cu $V$. La fiecare pas, nodul care nu se afla in $A$, _cel mai puternic conectat_, este adaugat multimii. Intr-o formulare mai formala, putem spune ca adaugam nodul\r\n\r\n$z &#8713; A astfel incat w(A, z) = max{w(A, y) | y &#8713; A},$\r\n\r\nunde $w(A, y)$ este suma costurilor muchiilor dintre nodul $y$ si nodurile care apartin multimii $A$. La sfarsitul fiecarei astfel de faze, ultimele doua noduri adaugate fuzioneaza, ceea ce inseamna ca cele doua noduri sunt inlocuite de un nou nod, si orice muchii de la un nod ramas la cele doua noduri scoase sunt inlocuite de o noua muchie de cost egal cu suma costurilor precedentelor doua muchii. Muchiile intre cele doua noduri sunt eliminate. Taietura lui $V$ ce separa ultimul nod adaugat de restul grafului se numeste taietura fazei. Cea mai mica dintre aceste taieturi ale fazei, reprezinta rezultatul dorit, si anume taietura minima in graf.\r\n\r\n== code(c) |\r\nTaieturaMinima(G, w, a)\r\n    while |V| > 1\r\n        FazaTaieturiiMinime(G, w, a)\r\n        daca taietura fazei este mai mica decat taietura minima curenta\r\n            atunci actualizeaza taietura minima curenta\r\n==\r\n\r\nObservatie: Nodul $a$ ramane fixat pe parcursul intregului algoritm. Am putea sa il alegem insa in mod arbitrar la fiecare pas.\r\n\r\nh2. Corectitudine\r\n\r\nPentru a demonstra corectitudinea algoritmului, trebuie mai intai sa demonstram urmatoarea lema:\r\n\r\nLema 1: _Fiecare taietura faza reprezinta o taietura minima $s-t$, unde $s$ si $t$ sunt ultimele 2 noduri adaugate in faza curenta._ \r\n\r\nDemonstratie: Procedura FazaTaieturiiMinime sorteaza nodurile grafului curent, incepand cu a si terminand cu $s$ si cu $t$, in functie de ordinea in care acestea au fost adaugate in multimea $A$. Vom analiza o taietura $C$ $s-t$ oarecare a grafului curent si vom demonstra ca are costul mai mare sau egal cu cel al taieturii faza.\r\n\r\nNumim un nod $v &#8800; a$ activ (in raport cu taietura $C$) daca $v$ si ultimul nod adaugat inainte de $v$ se afla in multimi diferite. Fie $w&#40;C)$ costul taieturii $C, A{~v~}$ multimea nodurilor adaugate inaintea lui $v, C{~v~}$ taietura lui $A{~v~} &#8746; v$ indusa de $C$, iar $w(C{~v~})$ costul taieturii induse.\r\n\r\nVom arata prin inductie ca pentru fiecare nod activ $v$, \r\n\r\n$w(A{~v~}, v) &#8804; w(C{~v~})$\r\n\r\n# Pentru primul nod activ, propozitia de mai sus este adevarata deoarece avem egalitate. \r\n# Presupunem adevarata propozitia pentru toate nodurile active adaugate inaintea unui nod activ $v$, si fie $u$ urmatorul nod activ ce urmeaza sa fie adaugat. Atunci avem:\r\n\r\n$w(A{~u~}, u) = w(A{~v~}, u) + w(A{~u~}\\A{~v~}, u) = &#945;$\r\n\r\nIn continuare, avem $w(A{~v~}, u) &#8804; w(A{~v~}, v)$, deoarece atunci cand a fost ales, nodul $v$ era mai puternic conectat decat $u$ in raport cu $A{~v~}$. Prin inductie avem $w(A{~v~}, v) &#8804; w(C{~v~})$. Toate muchiile dintre $A{~u~}\\A{~v~}$ si $u$ conecteaza multimi diferite ale taieturii $C$. Deci ele contribuie la $w(C{~u~})$, dar nu si la $w(C{~v~})$. Asadar:\r\n\r\n$&#945; &#8804; w(C{~v~}) + w(A{~u~}\\A{~v~}, u) &#8804; w(C{~u~})$\r\n\r\nConcluzie: Cum $t$ este tot timpul un nod activ in raport cu $C$, putem concluziona ca $w(A{~t~}, t) &#8804; w(C{~t~})$, ceea ce demonstreaza ca orice taietura $s-t$ are costul cel putin la fel de mare ca taietura faza.\r\n\r\nh2. Analiza complexitatii\r\n\r\nIn cadrul procedurii TaieturaMinima, vom apela procedura FazaTaieturiiMinime de $O(|V|)$ ori. Observam ca in cadrul acestei din urma proceduri, avem nevoie de o structura de date care sa poata efectua in mod eficient urmatoarele operatii: _extrage_cheia_maxima_ si _creste_valoarea_unei_chei_. Putem folosi un heap Fibonacci pentru a efecuta operatia _extrage_cheia_maxima_ in {$O(log |V|)$} amortizat, iar pentru _creste_valoarea_unei_chei_ in O(1) amortizat, obtinand astfel o complexitate finala de {$O(|V|*|E| + |V|^2^*log |V|)$}. Nu recomand insa implementarea unei asemenea structuri in conditii de concurs, un heap binar fiind suficient, obtinandu-se astfel o complexitate de {$O(|V|*|E|*log |V|)$}\r\n\r\nh2. Probleme de taietura in concursurile de algoritmica\r\n\r\n* \'Croco\':http://campion.edu.ro/problems/3/351/croco_ro.htm - .campion 2006/2007, runda 07\r\n* \'Terrorists\':http://www.topcoder.com/stat?c=problem_statement&pm=7246 - TopCoder, SRM 334, divizia I',2044,'public',3700,NULL),('documentatie/pagina-de-profil','Fa-ti pagina de profil!','2006-11-26 22:14:10','2007-10-29 20:33:18','h1. Fa-ti pagina de profil!\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\n==include(page=\"template/todo\")==\r\n\r\n* Autentifica-te (\'login\':login)\r\n* Viziteaza-ti pagina ta de profil (click pe avatar/username din coltul din dreapta sus al ecranului)\r\n* Click pe _Editeaza_\r\n\r\nCa sa formatezi textul va trebui sa folosesti \'sintaxa textile\':documentatie/textile. Afla mai multe despre cum se editeaza paginile infoarena \'din documentatie\':documentatie/wiki.\r\n\r\nh2. Ce sa scriu in pagina de profil?\r\n\r\nAceasta este pagina cu care te prezinti comunitatii infoarena. Ne-ar interesa sa stim cine esti, unde inveti, profesori pregatitori, distinctii primite, carti si probleme preferate samd.\r\n\r\nEsti liber sa scrii ce doresti dar nu exagera si nu incalca \'regulamentul infoarena\':regulament.\r\n\r\nh2. De ce sa-mi fac pagina de profil?\r\n\r\nInfoarena nu este doar un site cu probleme, ci o comunitate de elevi si studenti interesati de programare si informatica. Ne facem fiecare o pagina de profil ca sa ne prezentam / sa ne cunoastem mai bine.\r\n',1142,'protected',NULL,NULL),('documentatie/rating','Rating infoarena','2006-12-06 11:59:45','2008-10-12 20:58:07','h1. Rating-ul infoarena\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nSistemul de rating infoarena ofera un mod de a ordona si diferentia utilizatorii in functie de performantele acestora in regim de concurs. Rating-urile se calculeaza folosind elemente de statistica si probabilitati.\r\n\r\nEste important de retinut ca rating-ul unui utilizator se actualizeaza doar dupa finalizarea unui concurs organizat pe infoarena. Activitatea de pregatire din arhiva de probleme nu influenteaza rating-ul.\r\n\r\nh2. La ce serveste?\r\n\r\nSistemul de rating ideal ne-ar permite sa afirmam care dintre doi concurenti este _mai puternic_. Evident, acest sistem ideal nu exista (chiar notiunea de _mai puternic_ este discutabila), totusi putem aproxima unul.\r\n\r\nRating-ul infoarena te ajuta sa...\r\n\r\n* iti urmaresti *evolutia personala* in regim de concurs\r\n* iti raportezi performantele la ceilalti utilizatori infoarena\r\n\r\nh2. Cum imi cresc rating-ul?\r\n\r\nParticipa la concursurile infoarena si rezolva cat mai multe probleme. Tu iti vezi de treaba si rating-ul te urmareste :)\r\n\r\nh2. Cum se calculeaza?\r\n\r\ninfoarena foloseste un sistem de rating relativ standard numit \'Glicko\':http://math.bu.edu/people/mg/glicko/glicko.doc/glicko.html, adaptat la nevoile noastre.\r\n\r\nGlicko este un sistem de rating folosit in campionatele de sah, o varianta imbunatatita a algoritmului larg acceptat \'ELO\':http://en.wikipedia.org/wiki/Elo_rating_system.\r\n\r\nh3. Distributie\r\n\r\n!/plot/distribution!\r\n\r\n-Din grafic se observa ca rating-urile infoarena aproximeaza \'distributia normala - Gauss\':http://en.wikipedia.org/wiki/Normal_distribution.  Desi asta nu dovedeste nimic in particular, e un semn bun ca algoritmul functioneaza :)-\r\n\r\nh3. Detalii despre implementare\r\n\r\nVezi direct \'codul sursa al implementarii noastre de Glicko\':http://hackers.devnet.ro/browser/trunk/common/rating.php.\r\nFata de \'algoritmul standard Glicko\':http://math.bu.edu/people/mg/glicko/glicko.doc/glicko.html, am modificat urmatoarele:\r\n\r\n* Glicko a fost inventat pentru jocuri de sah (sau, mai general, jocuri head-to-head) insa concursurile de informatica includ mai multi participanti. Astfel, consideram fiecare pereche de concurenti ca un joc head-to-head.\r\n* Functia care calculeaza scorul probabil (expected value) normalizeaza diferentele de rating mai mari decat $IA_RATING_MAX_DIFF$\r\n* Glicko acorda $0$ pentru infrangere, $1/2$ pentru remiza si $1$ pentru victorie. Am facut o functie care acorda un numar real din intervalul $[0, 1]$ in functie de \'deviatia standard\':http://en.wikipedia.org/wiki/Standard_deviation. Astfel, acordam un numar real in intervalul $[0, 1/2)$ pentru o infrangere, $1/2$ pentru o remiza, respectiv un numar in intervalul $(1/2, 1]$ pentru o victorie.\r\n',1490,'public',NULL,NULL),('problema/perm2','Permutari II','2006-11-11 11:23:34','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"perm2\")==\r\n\r\nSe considera multimea $A$ formata din elementele $1$, $2$, $3$ &hellip; $N$ ({$1$} &le; $N$ &le; $20.000$).\r\n\r\nO permutare $P$ este o functie bijectiva definita pe multimea $A$, cu valori in $A$. (adica asociaza in mod unic fiecarui element din $A$ un element unic tot din $A$).\r\n\r\nUn exemplu de astfel de permutare este ilustrat de tabelul de mai jos\r\n\r\ntable(numbers). |_. $i$    | $1$ |$2$ |$3$ |$4$ |\r\n                |_. $P(i)$ |$2$  |$3$ |$4$ |$1$ |\r\n\r\nDefinim permutarea $P^k^$ astfel:\r\n\r\n$P^k^(i)$ =\r\n\r\n* $P(i)$, atunci cand $k=1$\r\n* $P(P^k-1^(i))$, pentru $k > 1$\r\n\r\nTabelul de mai jos ilustreaza $P^1^$ si $P^2^$:\r\n\r\ntable(numbers). |_. $i$       |$1$ |$2$ |$3$ |$4$ |\r\n                |_. $P^1^(i)$ |$2$ |$3$ |$4$ |$1$ |\r\n                |_. $P^2^(i)$ |$3$ |$4$ |$1$ |$2$ |\r\n\r\nh2. Cerinta\r\n\r\nSe da $N$ si o permutare $P$. Sa se gaseasca cel mai mic numar natural $K$ strict pozitiv, astfel incat oricare ar fi $1$ &le; $i$ &le; $N$ avem $P^k^(i) = i$ (in alte cuvinte, $P^k^$ sa fie _permutarea identica_ ).\r\n\r\nh2. Date de intrare\r\n\r\nFisierul $perm2.in$ va contine pe prima linie numarul intreg $N$.\r\n\r\nPe urmatoarea linie se scriu $N$ numere naturale distincte, fiecare in intervalul $1$ &hellip; {$N$}.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie a fisierului $perm2.out$ se va scrie acel numar $K$ ce indeplineste condiitle impuse.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* Pentru testele furnizate $1$ &le; $K$ &le; $100.000$\r\n\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. perm2.in |_. perm2.out |\r\n| 6\r\n1 2 3 4 5 6 | 1 |\r\n| 4\r\n2 3 4 1 | 4 |\r\n| 8\r\n1 5 2 3 4 8 6 7 | 12 |\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"perm2\")==\n\n\n',1490,'task: perm2',42,NULL),('utilizator/ditzonec','Profil DITzoneC','2006-11-24 20:58:11','2008-03-04 17:10:13','h2. Studii\r\n\r\n* Student la Universitatea Bucuresti, \"Facultatea de Matematica si Informatica\":http://fmi.unibuc.ro/ro/, sectia Informatica\r\n* \"Absolvent al Colegiului National de Informatica {@\"Tudor Vianu\"@}\":http://www.lbi.ro/, Bucuresti\r\n\r\nh2. Distinctii primite\r\n\r\n* 2006 - Calificare faza finala a \"The ACM International Collegiate Programming Contest\":http://icpc.baylor.edu/icpc/finals/default.htm\r\n* 2006 - Medalie de bronz la \"Olimpiada Europei Centrale de Informatica\":http://jagor.srce.hr/hsin/ceoi2006/\r\n* 2006 - Castigator al concursului \".campion\":http://campion.edu.ro/index.php\r\n* 2005-2006 - Membru al lotului national de informatica\r\n* 2003-2006 - Premii si mentiuni la Olimpiada Nationala de Informatica\r\n* 2003-2005 - Calificat la Olimpiada Nationala de Fizica\r\n* 2006 - Calificat la Olimpiada Nationala de Matematica\r\n\r\nh2. Membru in comisii\r\n\r\n* Membru in Comisia Nationala de Informatica la ONI 2007, Lot Alba 2007\r\n* Membru in echipa \'.campion\':http://campion.edu.ro\r\n* preONI si alte concursuri pe infoarena\r\n* Stelele Informaticii 2006-2007\r\n\r\nh2. Hobby\r\n\r\n* Snowboard rules :)',961,'protected',NULL,NULL),('documentatie/editare-de-probleme','Cum se adauga o problema noua','2007-01-20 18:14:08','2008-11-29 21:00:31','h1. Cum se adauga o problema noua\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nh2. Creare problema\r\n\r\n# Pentru a crea o problema noua accesati pagina \'admin/problema-noua\':admin/problema-noua.\r\n# Dupa ce ati ales un _id unic, format numai din litere mici_ pentru problema si tipul problemei (doar _Clasic_ momentan) veti fi dusi la pagina de editare unde veti putea configura parametrii problemei. \r\n# Alegeti titlul problemei (care poate fi diferit de id, de exemplu id-ul $secv13$ si titlul $Secventa 13$); acesta _trebuie sa inceapa cu litera mare_. De asemenea, cand editati enuntul este indicat ca si _titlul care apare ca titlul ferestrei de browser_ sa fie cu _litera mare_ la inceput.\r\n# Setati limita de timp, limita de memorie si numarul de teste pe care le are problema.\r\n# infoarena permite evaluarea problemelor folosind \'grupuri de teste\':documentatie/grupare-teste. In casuta _Grupare teste_ va trebui sa introduci o expresie care sa descrie aceste grupuri. Sintaxa pentru aceasta expresie este prezentata in continuare:\r\n$expresie = grup$ sau $expresie;grup$\r\n$grup = interval$ sau $grup,interval$\r\n$interval = numar$ sau $numar-numar$\r\n$numar = 1$ sau $2$ sau $...$\r\nMai exact o expresie va fi formata dintr-o serie de grupuri separate prin caracterul $;$. Un grup va reprezenta o serie de intervale separate prin caracterul $,$ . Un interval va fi ori numarul unui test (intre $1$ si numarul de teste specificate) ori un interval de numere ({$x-y$} va reprezenta testele $x, x+1, x+2... y-1, y$).\r\n*{color:red}Atentie!* Trebuie ca fiecare test sa apara o singura data in cadrul expresiei. Spre exemplu expresia $1-10;5$ nu este valida deoarece testul $5$ este inclus de doua ori. \r\n# Daca problema are _raspuns unic_, bifati ca problema foloseste $.ok$-uri si lasati gol la campul Evaluator. In cazul in care problema nu are raspuns unic va trebui sa creati _un program de evaluare_ si sa specificati daca acest program de evaluare foloseste $.ok$-uri. Ca sa aflii cum se scrie un program de evaluare pentru o problema intra \'aici\':documentatie/ghid-evaluator.\r\n# Completati campul Sursa cu concursul la care a fost propusa aceasta problema (spre exemplu _preONI 2007, Runda 1_) si specificati ca este un _Task ascuns_. Problemele de la un concurs se vor face automat vizibile odata ce incepe concursul la care sunt atasate.\r\n# Salvati datele introduse apasand butonul _Salveaza_.\r\n\r\nh2. Enunt si teste\r\n\r\n# Editati enuntul care se va gasi la adresa _problema/nume-problema_, in cazul in care n-ati schimbat setarea implicita in formularul de editare al problemei pentru _Pagina cu enuntul_. \r\n# Pentru editarea unei probleme consultati \'documentatia Textile\':documentatie/textile si \'conventiile de formatare\':documentatie/conventii-de-formatare.\r\n# Testele, evaluatorul si eventualele imagini care vor aparea in task se ataseaza la pagina de enunt a problemei. \r\n*{color:red}Atentie!* Testele problemei trebuie sa se numeasca $grader_testX.in$ si $grader_testX.ok$ (unde $X$ este numarul testului, incepand cu 1), iar evaluatorul va trebui de asemenea prefixat cu $grader_$ (vezi \'documentatia pentru evaluatore\':documentatie/ghid-evaluator).\r\n# Cel mai simplu mod de a atasa toate aceste fisiere este printr-o arhiva $ZIP$. La momentul atasarii puteti specifica daca doriti ca arhiva sa fie despachetata. \r\n# *{color:red}Atentie!* Nu atasati testele sub alt nume sau alte fisiere importante, deoarece vor putea fi accesate de utilizatori!\r\n# La final puneti link la topic-ul din \'forum\':forum legat de aceasta problema in campul \"Forum Topic\" din pagina de editare a enuntului.\r\n\r\nh2. Verificarea problemei\r\n\r\n# *{color:red}Atentie!* Pentru a evita cat mai mult posibil situatiile in care testele sunt gresite, este *necesar* sa existe mai multe solutii pentru o problema scrise de persoane diferite, eventual cu abordari diferite.\r\n# Este necesar sa se verifice daca testele respecta restrangerile din enunt. Acest lucru se va face in sursa oficiala (folosind functia $assert()$ de exemplu). \r\n# Ca administrator sau propunator al problemei, puteti oricand trimite solutii si sa se vedeti rezultatul. Utilizatorii normali nu vor avea acces sa trimita solutii la problema, decat in momentul in care aceasta este atasata unui concurs activ, la care utilizatorii sunt inregistrati. De asemenea, in monitor detaliile de evaluare nu vor putea fi vazute de catre ceilalti utilizatorilor normali.\r\n# Puteti oricand modifica limitele de timp, memorie sau alte detalii ale problemei accesand pagina _admin/problema/nume-problema_',1490,'protected',NULL,NULL),('clasament-rating','Clasament dupa rating','2006-12-11 01:03:42','2010-03-24 21:37:19','(htabs)*(active) \'După rating\':clasament-rating\r\n* \'Arhiva de probleme\':clasament-arhiva\r\n* \'Arhiva educatională\':clasament-arhiva-educationala\r\n\r\nh1. Clasament după \'rating\':documentatie/rating\r\n\r\nAcest clasament ordonează utilizatorii după *performanţele obţinute în regim de concurs*.\r\nDoar o parte din utilizatorii infoarena au participat la concursuri cu rating. Marea majoritate au rezolvat numai probleme din arhivă.\r\n\r\n\'Află mai multe\':/documentatie/rating despre rating.\r\n\r\n== TopRated() ==',1490,'protected',NULL,NULL),('problema/fractal','Fractal','2006-11-11 11:23:36','2009-12-22 18:04:16','==Include(page=\"template/taskheader\" task_id=\"fractal\")==\r\n\r\nHilbert a gasit o curba care poate trece prin fiecare punct al spatiului, aceasta curba se bazeaza pe o constructie recursiva. Numim curba de ordin Hilbert de ordinul $K$ curba curba realizata dupa urmatoarele reguli ce trece prin fiecare nod al unei grile de $2^K^*2^K^$ noduri si trece prin noduri vecine ale grilei.\r\nCurba Hilbert de ordinu 1 este o curba simpla:\r\n!problema/fractal?image001.gif!\r\n\r\nVor fi descries in urmatoarele imagini trecerile de la o curba de ordin x la o curba de ordin x+1:\r\nOrdin $1$ -> Ordin $2$\r\n!problema/fractal?image001.gif! !problema/fractal?image002.gif! !problema/fractal?image003.gif! !problema/fractal?image004.gif! !problema/fractal?image005.gif!\r\nOrdin $2$ -> Ordin $3$\r\n!problema/fractal?image006.gif! !problema/fractal?image007.gif! !problema/fractal?image008.gif! !problema/fractal?image009.gif! !problema/fractal?image010.gif!\r\nOrdin $3$ -> Ordin $4$\r\n!problema/fractal?image011.gif! !problema/fractal?image012.gif! !problema/fractal?image013.gif! !problema/fractal?image014.gif! !problema/fractal?image015.gif!\r\nOrdin $4$ -> Ordin $5$\r\n!problema/fractal?image016.gif! !problema/fractal?image017.gif! !problema/fractal?image018.gif! !problema/fractal?image019.gif! !problema/fractal?image020.gif!\r\n\r\nSe dau ca date de intrare din fisierul $fractal.in$ numerele $K, x$ si $y$, unde $K$ este ordinul unei curbe, iar $x$ si $y$ sunt coordanate intregi in interiorul unui patrat de dimensiune $2^K^*2^K^$. Se cere sa scrieti in fisierul de iesire $fractal.out$ in cati pasi se ajunge la coordonatele $(x,y)$ daca punctele din patrat sunt parcurse in ordinea data de curba Hilbert de ordin $K$.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; k &le; 15$\r\n* $1 &le; x,y &le; 2^K^$\r\n* Coordonatele $x$ si $y$ sunt intre $1$ si $2^K^$ inclusiv ({$x$} reprezinta coloana, $y$ linia), iar coltul din stanga sus are coordonatele $(1,1)$.\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. fractal.in |_. fractal.out |\r\n| 1 1 1 | 0&ensp; |\r\n| 3 2 3 | 13 |\r\n| 2 4 1 | 15 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"fractal\")==\r\n\r\n\r\n',1490,'task: fractal',95,NULL),('problema/xormax','Xor Max','2006-11-11 11:23:37','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"xormax\")==\r\n\r\nPaftenie este un elev eminent. De multe ori isi pune intrebari care au sau nu raspunsuri. De data aceasta i-a venit o idee noua. El are un sir de $N$ numere intregi nenegative si vrea sa aleaga o secventa a sirului {$a{~i~} a{~i+1~} ... a{~j~}$} astfel incat {$a{~i~} xor a{~i+1~} xor ... xor a{~j~}$} sa fie maxim.\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l pe Paftenie sa rezolve problema!\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare $xormax.in$ este dat numarul $N$ al intregilor din sir. Pe urmatoarea linie se afla elementele sirului separate prin cate un spatiu.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $xormax.out$ va contine pe prima linie 3 numere: $max$, $start$, $stop$, reprezentand valoarea maxima gasita, pozitia de inceput a secventei, respectiv pozitia ultimului element din secventa aleasa. In caz ca exista mai multe solutii, se va alege secventa cu stop minim, iar daca inca exista mai multe solutii se va alege secventa cea mai scurta.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 100.000$\r\n* Numerele sirului sunt strict mai mici decat {$2^21^$}\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. xormax.in   |_. xormax.out |\r\n|5\r\n1 0 5 4 2\r\n|6 4 5 |\r\n\r\n\r\nh3. Explicatii\r\n\r\nValoarea maxima gasita este 6. Secventa este cea alcatuita din ultimele doua elemente ale sirului (4 xor 2 = 6)\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"xormax\")==\r\n\r\n\r\n',1490,'task: xormax',139,NULL),('planificare/asociatia-infoarena','Infiintarea Asociatiei infoarena','2007-02-16 17:57:12','2007-10-24 13:09:13','h1. Infiintarea Asociatiei infoarena\r\n\r\n\r\n*_COMPLETE_*\r\n\r\n\r\nAsociatia infoarena este in proces de infiintare. Aici o sa va tin la curent cu stadiul in care ma aflu.\r\n\r\nBirocratie sucks.\r\n\r\nh2. Chestii de facut\r\n\r\n_(item-urile taiate sunt finalizate)_\r\n\r\n# -Elaboreaza Statut si Act Constitutiv-\r\n# -Depune cerere de rezervare denumire-\r\n# -Retrage cerere de rezervare (Joi, 11 ianuarie)-\r\n# -Membrii fondatori semneaza statut & act constitutiv la notar-\r\n# -Deschide cont in banca, capital social 350 RON-\r\n## -Baga in banca un capital social de 1500 RON (aproximativ 3 x salar minim pe economie)- (nu mai e nevoie)\r\n## -Trimite actele la Barlad-\r\n# -Contract de comodat. Sediu social in Barlad, la casa lui Cristi-\r\n# -Depunere dosar la Tribunalul Barlad (dupa 1. ... 6.)-\r\n# -Audiere la Tribunal pe *5 martie*-\r\n## -Audierea a decurs bine. Decizia e in pronuntare. Se pare ca vineri vom afla rezultatul final. *Inca nu suntem clear!* Inca e posibil sa ni se mai ceara acte.-\r\n## %{color: red}*UPDATE*%: Ca intr-un film prost, judecatorul nostru a murit in noaptea de dupa audiere. -Nimeni nu stie inca daca s-a pronuntat sau nu in dosarul nostru.- Probabil ca vom afla pana joi (15 martie) rezultatul. Este posibil sa se faca audiere din nou la un alt judecator. -Este posibil sa ne ceara caziere fiscale.-\r\n## -Judecatorul cu pricina nu a apucat sa se pronunte. :(-\r\n# -Am fost programat pentru *o noua* audiere la tribunal, pentru data de 19 martie.-\r\n## -Pe 19 martie am aflat ca audierea s-a stabilit pe 4 aprilie :) here we go again...-\r\n## -Rezervarea de denumire expira pe 8 aprilie. Ca sa nu risc am fost pe data de 28 martie sa o extind cu inca 3 luni. Pe 4 aprilie trebuie sa merg la Ministerul Justitiei sa ridic raspunsul (la cererea de extindere denumire).-\r\n# -Audiere Tribunal 4 aprilie-\r\n## -Curtea e in pronuntare. In jur de 8 primim raspuns prin posta.-\r\n## %{color: red}*UPDATE (13 aprilie): S-a aprobat!*% Pentru ca era si timpul, avem personalitate juridica. Yay!\r\n# Bere si party in cinstea infiintarii\r\n# Stampila -si formulare tipizate-\r\n## Mai nou, nu mai trebuie formulare tipizate pentru facturi si chitante. Se pot face de mana.\r\n\r\n\r\nh2. Note\r\n\r\nVa recomand sa cititi statutul si actul constitutiv. Nu e cu legal shit. E digerabil. E important si nu se poate schimba prea usor.\r\n\r\nO sa incercam o inregistrare fara caziere fiscale / judiciare. Din cate am putut eu afla, cerinta asta e la latitudinea judecatorului. Barladenii sunt nice si poate ca scapam. Daca nu, membrii fondatori trebuie sa scoata fiecare cazier fiscal / judiciar din judetul lor.\r\n\r\nh2. Atasamente\r\n\r\n* \'Act-Constitutiv.doc\':planificare/asociatia-infoarena?Act-Constitutiv.doc\r\n* \'Statut.doc\':planificare/asociatia-infoarena?Statut.doc\r\n* \'Tabel-Semnaturi.doc\':planificare/asociatia-infoarena?Tabel-Semnaturi.doc\r\n',13,'public',NULL,NULL),('preoni-2008/runda-3/solutii/strazi','preoni-2008/runda-3/solutii/strazi','2008-01-20 12:25:51','2008-01-22 19:47:45','h2(#strazi). \'Strazi\':problema/strazi\r\n\r\nReformuland problema, trebuie sa adaugam un numar minim de muchii intr-un graf orientat aciclic astfel incat sa existe un drum hamiltonian. Un drum este o insiruire de noduri $X{~1~} X{~2~} .. X{~K~}$ astfel incat sa existe o muchie intre oricare doua noduri consecutive. Printr-o acoperire cu drumuri a grafului vom defini o multime de drumuri astfel incat fiecare nod din graf apare exact intr-un singur drum. Daca multimea de drumuri are cardinalul minim, atunci acoperirea este minima. Sa presupunem acum ca am gasit o astfel de acoperire minima, multimea de drumuri fiind formata din drumurile $D{~1~}, D{~2~} .. D{~P~}$.\r\nDaca adaugam cate o muchie de la ultimul nod din drumul $D{~i~}$ la primul nod din drumul $D{~i+1~}$ atunci graful nou format va contine un drum hamiltonian, deoarece toate nodurile din graf apar exact o singura data intr-un drum iar acum toate drumurile au fost unite. Este usor de vazut ca acesta este si numarul minim de muchii care trebuie adaugat (se demonstreaza usor prin reducere la absurd, daca ar exista un numar mai mic de muchii care ar putea fi adaugat atunci acoperirea cu drumuri obtinuta anterior nu ar mai fi minima). Sa ne concentram acum pe gasirea unei acoperiri minime. Vom construi un graf bipartit, in partea stanga vom pune nodurile de la $1$ la $N$ iar in partea dreapta de asemenea nodurile de la $1$ la $N$. Sa alegem drumul $D{~1~}$ reprezentat prin succesiunea de noduri $x{~1~} x{~2~} .. x{~t~}$. Acest drum il vom reprezenta in graful bipartit astfel: vom trage muchie de la nodul $x{~1~}$ din partea stanga la nodul $x{~2~}$ din partea dreapta, de la nodul $x{~2~}$ din partea stanga la nodul $x{~3~}$ din partea dreapta etc. Vom face acelasi lucru pentru drumurile $D{~2~} .. D{~P~}$ si observam ca la sfarsit fiecare nod din graful bipartit are maxim un vecin. Mai mult, numarul de noduri din partea stanga din care nu pleaca nici o muchie este egal cu numarul de drumuri din acoperire. Pe noi ne intereseaza ca acest numar sa fie cat mai mic, deci trebuie sa existe un numar cat mai mic de noduri din partea stanga a grafului bipartit care nu au niciun vecin. Pentru a gasi acoperirea minima, pentru fiecare muchie $x->y$ din graful initial vom plasa o muchie de la nodul $x$ din partea stanga a grafului bipartit la nodul $y$ din partea dreapta si vom rula un algoritm de cuplaj maxim. (cuplajul maxim ne garanteaza faptul ca am \"cuplat\" cat de multe noduri posibile din partea stanga a grafului bipartit)\r\n\r\nh3. Probleme asemanatoare\r\n\r\n* \'Drumuri2\':problema/drumuri2\r\n* \'SGU 252\':http://acm.sgu.ru/problem.php?contest=0&problem=252',2092,'public',NULL,NULL),('documentatie/conventii-de-formatare','Conventii de formatare','2006-11-23 21:46:06','2008-01-10 05:34:38','h1. Conventii de formatare\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nAceasta pagina detaliaza anumite conventii de formatare folosite de echipa infoarena in redactarea paginilor. Se recomanda respectarea cu strictete a acestor indicatii pentru a mentine un look uniform. Orice modificare care se abate de la aceste conventii va fi stearsa.\r\n\r\nCorectarea si imbogatirea continutului site-ului este o activitate minutioasa si necesita atentie. Pe pagina asta incercam punem niste reguli fixe pentru ca toata lumea sa stie ce are de facut. Inainte de a citi aceasta pagina cititi \'bazele sintaxei de textile\':documentatie/textile.\r\n\r\nh2. Reguli generale\r\n\r\nIn cazul ca problema a fost importata de pe _infoarena 1.0_ veti vedea urmatoarea linie $==Include(page=\"template/raw\")==$. Daca nu sunteti multumit de rezultatul final, dar nu mai aveti chef sa editati in continuare, puteti include linia $==Include(page=\"template/cleanup\")==$\r\n\r\nCateva reguli scurte si *foarte* importante:\r\n\r\n* Numele nostru este infoarena, fara liniuta. Se poate folosi scrierea *info*_arena_.\r\n* Fiecare pagina incepe cu $h1. Titlu de pagina$.\r\n* Maxim h3, dar incercati sa va limitati la h2.\r\n* Url-urile noastre sunt lowercase cu liniuta.\r\n* Site-ul este in limba romana, inclusiv url-urile.\r\n* Stirile nu au nevoie de nici un fel de header.\r\n* Pe infoarena1 se scriau articole cu solutii. Solutiile se muta in $pagina-concurs/solutii$.\r\n* Fostele articole trebuie integrate in wiki. Nu mai au autor si nici categorii.\r\n\r\nh2. Conventii formatare inline (bold, italic)\r\n\r\nNu folositi bold, italic sau alti modificatori fara un motiv bun. Daca aveti probleme cu inserarea unui anumit caracter puteti consulta aceasta \"lista\":http://en.wikipedia.org/wiki/List_of_HTML_decimal_character_references si sa folositi direct codul HTML de acolo (spre exemplu pentru &le; se foloseste @&le;@, iar pentru &radic; se foloseste @&radic;@).\r\n\r\n* Pentru variabile, constante, etc se va folosi *{@$...$@}* (eg. *{@$7$@}* {->} $7$).\r\n* Pentru ridicare se va pune exponentul intre *{@^...^@}* (eg. *&#0036;7&#0094;9&#0094;&#0036;* {->} $7^9^$).\r\n* Daca nu merg modificatorii inline se folosesc acolade: *{@ {$...$} @}*.\r\n* Daca doriti ca textul dintre modificatori sa nu fie interpretat ca Textile puteti folosi *{@ @...@ @}*, respectiv *&#0123;{@@...@@} &#0125;*.\r\n* Pentru virgula zecimala se va folosi \'*.*\'.\r\n* Pentru numere lungi (eg. 1234567890) este preferata gruparea cifrelor cate 3 pentru baza 10, sau cate 4 pentru bazele 2 si 16. Folositi un singur spatiu pentru despartirea grupelor. Exemple: $1 234 567 890$, $10 0010 1101 1011$, $A4 FAFF A9AB CDC3$, $10 333.445 56$.\r\n\r\nh2. Probleme\r\n\r\nConventiile de formatare a problemelor nu sunt multe dar sunt importante. Va recomandam sa va uitati pe modul de formatarea al problemelor deja existente in arhiva pentru a vedea cum sunt aplicate. In cele ce urmeaza le vom lista pe cele mai importante:\r\n\r\n* Numerele, constantele, variabilele, expresiile, numele fisierelor de intrare/iesire sunt inconjurate de {@$...$@} indiferent de pozitia lor in text! Exceptie fac testele, unde nu trebuie sa folositi dolari: $table(example)$ isi face singur treaba.\r\n* Pastrati structura unui task (vedeti paragraful urmator)!\r\n* Corect este \"Date de intrare\"/\"Date de iesire\"! De exemplu, evitati sa scrieti \"Date de Iesire\".\r\n* Precizarile care sunt propozitii incep cu litera mare si se termina cu punct. La fel si explicatiile.\r\n* Asigura-te ca titlul problemei (completat in prima casuta din modul \"Editeaza\") este scris cu litera mare.\r\n* In unele cazuri apar $ nedoriti in textul final. Dati un search la sfarsit in textul problemei (asa cum este el vazut de utilizator) si verificati ca acest lucru nu se intampla.\r\n\r\nAcceseaza \"template-ul\":template/newtask pentru a vedea structura generala a unui task in cod Textile. Structura unui task este urmatoarea:\r\n\r\n* Header: $==Include(page=\"template/taskheader\" task_id=\"*nume_task*\")==$\r\n* Enunt: Povestea problemei.\r\n* Date de intrare.\r\n* Date de iesire.\r\n* Restrictii: Se pun intr-o lista cu $*$.\r\n* Exemple: un tabel textila cu clasa de css example. Vezi mai jos\r\n* Footer: $==Include(page=\"template/taskfooter\" task_id=\"*nume_task*\")==$\r\n* \'Macro\':documentatie/macro cu topic-ul din forum\r\n\r\nExemplele se pun intr-un tabel formatat similar celui din \"template\":template/newtask. Prima coloana a tabelului va fi formatata in felul urmator:\r\n\r\n@table(example). |_. task_id.in |_. task_id.out |@\r\nunde $task_id$ reprezinta id-ul taskului editat.\r\n\r\nPentru coloane aditionale veti adauga in continuare @_. nume_coloana |@ de cate ori este necesar. Fiecare din liniile de tabel ce urmeaza se va reprezenta pe coloane, fiecare celula fiind separata prin pipe  &#0124;:\r\n\r\n{@ | coloana 1 | coloana 2 | coloana 3 | coloana 4 | @}\r\n\r\nSe pot introduce mai multe linii intr-o singura celula a tabelului folosind, evident, new line. Daca doriti sa introduceti linii goale in tabel folositi @&nbsp;@. Se recomanda ca explicatiile exemplelor sa fie incluse separat, imediat sub tabelul cu exemple, folosind un titlu {@h3@}: {@h3. Explicatii@}\r\n\r\nh2. Concursuri\r\n\r\nVezi \'pagina de concursuri\':concursuri.',6341,'public',NULL,NULL),('templates','Template-uri','2007-04-27 09:45:13','2009-02-14 15:04:19','== include(page=\"template/iap\") ==\r\n\r\n== include(page=\"template/noprofile\") ==\r\n\r\n== include(page=\"template/badtests\") ==\r\n\r\n== include(page=\"template/cleanup\") ==\r\n\r\n== include(page=\"template/todo\") ==\r\n\r\n== include(page=\"template/meeting-under-construction\") ==\r\n\r\n== include(page=\"template/implica-te/scrie-articole\") ==\r\n\r\n== include(page=\"template/implica-te/scrie-articole-2\") ==\r\n\r\n== include(page=\"template/autor-necunoscut\") ==\r\n\r\n== grep (substr=\"%\" page=\"template/%\") ==\r\n\r\n',1490,'public',NULL,NULL),('blog/finala-preoni-2007','Finala preONI 2007','2007-06-22 12:31:23','2007-10-15 15:42:58','Finala concursului preONI 2007 se desfasoara in perioada *24 - 26 iunie 2007* la \'Liceul international de Informatica din Bucuresti\':http://www.ichb.ro.\r\n\r\nSe califica in runda finala primii 10 clasati de la fiecare grupa de varsta, in urma celor 4 runde online. Se asigura cazarea si masa integral. Castigatorii vor primi premii in bani.\r\nConcurentii care nu s-au calificat pot participa online pe site-ul infoarena.\r\n\r\nMultumim sponsorilor nostri!\r\n\r\n!{border: 1px solid silver}preoni-2007?hostway.png!:http://www.hostwaylab.ro/ !{border: 1px solid silver}preoni-2007?ichb.png!:http://www.ichb.ro/ !{border: 1px solid silver}preoni-2007?irealsoft.png!:http://www.irealsoft.ro/\r\n\r\n*{\'&rarr; Vezi pagina dedicata rundei finale\':preoni-2007/runda-finala}*',1,'protected',NULL,NULL),('autumn-warmup-2007/solutii/runda-2','Solutii Autumn Warmup, Runda 2','2007-09-23 11:58:29','2008-12-16 08:39:17','h1. Solutii Autumn Warmup, Runda 2\r\n\r\nSuntem bucurosi ca runda 2 a concursului Autumn Warmup 2007 s-a incheiat cu bine. Acest articol va va prezenta solutiile celor 4 probleme propuse spre rezolvare, precum si cateva aprecieri in legatura cu desfasurarea probei.\r\n\r\nSpre deosebire de prima runda, am incercat sa variem cat mai mult dificultatea problemelor, pentru a le permite tuturor sa se pregateasca. Au fost 2 probleme usoare (Trompeta si MMsir), una de dificultate medie (Curcubeu), iar ultima a fost \"rupere\" (Rompetrol), nivelul de dificultate al acesteia fiind crescut chiar si pentru o competitie gen IOI. Il felicitam pe veteranul \"Codrut Grosu\":/utilizator/ragnar_lodbrok, care a fost singurul concurent ce a obtinut maxim la aceasta problema.\r\n\r\nAruncandu-ne privirea peste clasamentul rundei, observam in frunte membri vechi ai comunitatii, cu rezultate anul acesta la olimpiadele internationale. Runda a fost castigata de \"Bogdan Tataroiu\":/utilizator/bogdan2412 care a reusit sa se impuna cu 3 probleme rezolvate aproape corect si cu un brute-force la Rompetrol. Pe locul 2 s-a clasat \"Cosmin Gheorghe\":/utilizator/gcosmin, iar pe 3 \"Victor Rusu\":/utilizator/victorsb. Ii felicitam atat pe ei, cat si pe ceilalti participanti.\r\n\r\nSpre deosebire de prima runda, remarcam o oarecare omogenitate a punctajelor si speram ca v-au placut problemele. Daca aveti sugestii despre cum am putea sa imbunatatim concursul, le asteptam pe \"forum\":/forum/index.php?topic=2124.0. In continuare va prezentam solutiile problemelor din concurs.\r\n\r\nh2. \'Curcubeu\':problema/curcubeu\r\n\r\nVom considera colorarile incepand cu ultima. Parcurgem intervalul asociat ei si de fiecare data cand gasim o casuta necolorata ii asociem valoarea $C{~i~}$. Aceasta solutie are complexitatea $O(N^2^)$ si ar fi obtinut 20 de puncte. Pentru punctaj maxim este nevoie de un rafinament. Analizand solutia anterioara, observam ca vom parcuge de foarte multe ori casute deja colorate, lucru inutil si consumator de timp. Pentru fiecare pozitie $i$ vom mentine o valoare $Next[i]$, semnficand faptul ca intervalul $[i, Next[i]-1]$ contine doar casute colorate (initial $Next[i] = i$). Astfel, la colorarile urmatoare, vom putea \"sari\" peste secvente intregi de pozitii anterior colorate. Pentru a implementa eficient aceasta solutie, putem folosi una din cele doua euristici ale structurilor pentru multumi disjuncte, cea a comprimarii drumului. Puteti citi mai multe despre structuri pentru multimi disjuncte in \"Cormen\":http://zhuzeyuan.hp.infoseek.co.jp/ita/chap22.htm sau \"aici\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=disjointDataStructure. Complexitatea finala este $O(N log* N)$. De mentionat faptul ca se pot obtine 50 de puncte implementand solutii de complexitate $O(N log N)$ folosind arbori de intervale sau un maxheap.\r\n\r\nh2. \'Trompeta\':problema/trompeta\r\n\r\nProblema se rezolva cu metoda greedy. Se formeaza treptat rezultatul cu ajutorul unei stive: daca cifra curenta este mai buna decat cea din varful stivei si $numarul de cifre din stiva + numarul de cifre ramase &ge; M$, atunci elementul din varful stivei este eliminat. Acest algoritm are complexitate $O(N)$.\r\n\r\nh2. \'MMsir\':problema/mmsir\r\n\r\nVom rezolva problema in $o(n)$ folosind $2$ contori, $st$ si $dr$, si $2$ vectori, $h[i]=1$ daca si numai daca {$a[i-1] < a[i] > a[i+1]$} sau {$a[i-1] > a[i] < a[i+1]$}, si $schimb[i]$ care va fi egal cu cel mai mic $j$ cu proprietatea ca $h[j]=1$ si $j>i$. De aici vom incepe sa construim solutia astfel: initial $dr$ va fi egal cu cel mai mic $i$ cu proprietatea ca secventa $1 i$ isi schimba monotonia de $k$ ori, iar $st$ va fi egal cu $1$. Incepem sa incrementam $dr$ cu cate o unitate si de fiecare data adunam la solutie $schimb[st] - st$. Atunci cand $h[dr-1] = 1$, $st$ ia valoarea $schimb[st]$.\r\n\r\nPentru o rezolvare brute cu complexitate $o(n^2)$ se acordau $30$ de puncte.\r\n\r\nh2. \'Rompetrol\':problema/rompetrol\r\n\r\nVom calcula costurile @cmin[ i ][ j ][ 0 ]@ si @cmin[ i ][ j ][ 1 ]@, avand semnificatiile:\r\n\r\n* @cmin[ i ][ j ][ 0 ]@ = costul minim pentru a amplasa in total $i$ depozite in benzinariile $[1..j]$, iar al $i$-lea depozit se afla localizat chiar in benzinaria $j$\r\n* @cmin[ i ][ j ][ 1 ]@ = costul minim pentru a amplasa in total $i$ depozite in benzinariile $[1..j]$, iar al $i$-lea depozit nu este neaparat amplasat in benzinaria $j$\r\n\r\nRelatiile de recurenta sunt urmatoarele:\r\n\r\n* $cmin[ i ][ j ][ 0 ]$ = <tex> \\displaystyle\\min_{0 \\le j\' \\le j}\\{cmin[i-1][j\'][1] + a_{j} + \\sum_{p = j\' + 1}^j c_{p} * (d_{j} - d_{p})\\} </tex>\r\n* $cmin[ i ][ j ][ 1 ]$ = <tex> \\displaystyle\\min_{1 \\le j\' \\le j}\\{cmin[i][j\'][0] + \\sum_{p = j\' + 1}^j c_{p} * (d_{p} - d_{j\'})\\} </tex>\r\n\r\nValorile initiale sunt:\r\n\r\n* $cmin[ 0 ][ 0 ][ 0 ] = cmin[ 0 ][ 0 ][ 1 ] = 0$\r\n* $cmin[ 0 ][ i ][ 0 ] = cmin[ 0 ][ i ][ 1 ] = infinit$, pentru $i > 0$\r\n\r\nObservand ca in relatiile de recurenta toate valorile $cmin[i][a][b]$ depind doar de valori de tipul $cmin[i-1][a{~1~}][b{~1~}]$ si $cmin[i][a{~2~}][b{~2~}]$, putem retine doar ultimele $2$ linii ale matricii $cmin$, pentru a nu ocupa prea multa memorie.\r\n\r\nPrima solutie pleaca de la implementarea directa a relatiilor de recurenta si are complexitatea $O(N^2^*K)$, in conditiile in care putem calcula in $O(1)$ sumele dupa $p$ ce apar in relatiile de recurenta. Acest lucru se poate realiza usor, calculand in timp $O(N)$ urmatoarii vectori:\r\n\r\n* $csum[i] =$ suma cantitatilor de combusitibil din benzinariile $[1..i]$ ; $csum[i] = csum[i-1]+c[i]$\r\n* $cright[i] =$ suma costurilor de a transporta cantitatile necesare de combustibil de la benzinaria $N$ la fiecare din benzinariile $[i..N]$ ; $cright[i] = cright[i+1] + c[i] * (d[N] - d[i])$\r\n* $cleft[i] =$ suma costurilor de a transporta cantitatea dorita de combustibil de la benzinaria $N$ la benzinariile $[i..N]$ ; $cleft[i] = cleft[i-1] + c[i] * (d[i] - d[ 1 ])$\r\n\r\nCu acesti vectori, <tex> \\displaystyle\\sum_{p = j\' + 1}^j c_{p} * (d_{j} - d_{p}) </tex> se scrie ca fiind egala cu $cright[j{~1~}+1] - cright[j+1] - (csum[j] - csum[j{~1~}]) * (d[N] - d[j])$. In mod similar, <tex> \\displaystyle\\sum_{p = j\' + 1}^j c_{p} * (d_{p} - d_{j\'}) </tex> se scrie ca fiind egala cu $cleft[j] - cleft[j{~1~}] - (csum[j] - csum[j{~1~}])*(d[j{~1~}] - d[ 1 ])$.\r\n\r\nSolutia optima are, insa, complexitatea $O(N*K)$ si se bazeaza pe urmatoarele concepte: pentru fiecare $i$ de la $1$ la $K$ si fiecare pozitie $j$ de la $1$ la $N$ vom defini doua functii $f{~i,j~}$ si $g{~i,j~}$, pe care le vom folosi in calculul valorilor $cmin[ i ][ j ][ 0 ]$ si $cmin[ i ][ j ][ 1 ]$.\r\n\r\n\r\nh3. Calculul valorilor $cmin[ i ][ j ][ 0 ]$\r\n\r\nPentru fiecare pozitie $j$, vom defini functia $f{~i,j~}:[d[j],d[N]] -> int.$ O valoare a acestei functii intr-un punct $d[p]$, corespunzator benzinariei $p, f{~i,j~}(d[p])$, reprezinta costul minim pentru a amplasa $i$ depozite in benzinariile $1,2,..,p,$ in conditiile in care al $i$-lea depozit este in benzinaria $p$, iar benzinariile $j, j+1, .., p$ sunt alimentate cu combustibil de la depozitul din benzinaria $p$. Cu aceste definitii, valoarea lui $cmin[ i ][ j ][ 0 ]$ este minimul dintre valorile functiilor $f{~i,j{~1~}~}$, in punctul $d[j]$, cu $0<=j{~1~}<j$, la care se adauga valoarea $a[j]$. Problema importanta este cum aflam minimul dintre aceste functii, fara a calcula valoarea fiecarei functii in punctul $d[j]$ (care ar conduce la o complexitate $O(N^2^*K)$).\r\n\r\nFormula unei functii $f{~i,j~}(d[p])$ este: <tex> \\displaystyle cmin[ i-1 ][ j-1 ][ 1 ] + \\sum_{q = j}^p c_{q} * (d_{p} - d_{q}) </tex> . Diferenta dintre 2 valori consecutive ale functiei, $df{~i,j~}(d[p+1]) = f{~i,j~}(d[p+1]) - f{~i,j~}(d[p])$, este egala cu $(c[j]+c[j+1] + .. + c[p]) * (d[p+1] - d[p])$. Asadar, de la un pas la altul, functiile $f{~i,j~}$ care au un $j$ mai mic cresc mai mult decat cele care corespund unei pozitii $j$ mai mari (altfel spus, functiile care au aparut mai recent cresc mai incet decat functiile care au aparut de mai mult timp) : $df{~i,j~}(d[p+1]) < df{~i,j{~1~}~}(d[p+1])$, daca $j{~1~} < j$. De aici tragem urmatoarele concluzii:\r\n\r\n* daca valoarea unei functii $f{~i,j~}(d[p+1])$ este mai mare decat valoarea unei functii $f{~i,j{~1~}~}(d[p+1])$, cu $j{~1~}>j$, atunci functia $f{~i,j~}$ nu va mai avea niciodata valoarea minima dintre toate functiile la nici unul din pasii ulteriori.\r\n* daca valoarea unei functii $f{~i,j~}(d[p+1])$ este mai mica decat valoarea unei functii $f{~i,j{~1~}~}(d[p+1])$, cu $j{~1~}>j$, atunci functia $f{~i,j~}$ va fi \'depasita\' de functia $f{~i,j{~1~}~}$ intr-un punct $x{~j,j{~1~}~}$ ; maximul dupa $j$ dinte valorile  {$x{~j,j{~1~}~}$} reprezinta punctul minim posibil la care functia $f{~i,j{~1~}~}$ va avea valoarea minima dintre toate functiile dinaintea ei.\r\n\r\nCu aceste observatii, putem folosi un deque in cadrul algoritmului nostru, care contine functiile \'aparute\' pana la fiecare pas $p$. Functiile sunt sortate dupa valoarea lor la pasul $p$, precum si dupa momentul la care urmeaza sa devina functii cu valoare minima. La fiecare pas $p$ se introduce in deque o functie noua, functia $f{~i,p~}$. Aceasta va elimina toate functiile care au la pasul $p$ o valoare mai mare decat a ei, precum si acele functii pe care le-ar depasi intr-un punct $x$ mai mic decat momentul minim posibil la care acestea ar putea deveni functii cu valoare minima (pentru ca, astfel, acestea nu vor mai deveni niciodata functii cu valoare minima). De asemenea, la fiecare pas $p$ se elimina din partea din fata a deque-ului functiile pentru care functia de dupa ea are punctul in care devine minima mai mic sau egal cu $d[p]$.\r\n\r\nPentru a calcula punctul {$x{~j,j{~1~}~}$} in care o functie $f{~i,j{~1~}~}$ depaseste o functie $f{~i,j~} (j<j{~1~})$, trebuie sa calculam urmatoarele valori. Sa presupunem ca ne aflam la pasul $p=j{~1~}$. Vom calcula $dC = f{~i,j{~1~}~}(d[j{~1~}]) - f{~i,j~}(d[j{~1~}])$. Vom observa acum ca functiile $f{~i,j~}$ au fost definite pe un interval de distante, deoarece, intre doua distante corespunzatoare a doua benzinarii consecutive, ele se comporta ca niste drepte. La pasul $p=j{~1~}$, dreapta corespunzatoare functiei $f{~i,j~}$ are o panta egala cu $dP=(c[j] + c[j+1] + .. + c[j1-1])$, iar dreapta corespunzatoare functiei $f{~i,j{~1~}~}$ are panta $0$. In fiecare punct mai mare decat punctul $d[j{~1~}]$, diferenta dintre pantele dreptelor corespunzatoare celor 2 functii in punctul respectiv va ramane constanta si egala cu $dP$. Se observa usor ca acest lucru este adevarat, pentru ca pantele dreptelor asociate cresc cu aceeasi valoare in fiecare punct in care se afla localizata o benzinarie. Prin urmare, punctul $x$ in care functia $f{~i,j{~1~}~}$ depaseste functia $f{~i,j~}$ este $x=d[j{~1~}] + dC/dP$.\r\n\r\nh3. Calculul valorilor $cmin[ i ][ j ][ 1 ]$\r\n\r\n\r\nCalculul valorilor $cmin[ i ][ j ][ 1 ]$ se realizeaza similar cu calculul valorilor $cmin[ i ][ j ][ 0 ]$. Se vor defini niste functii $g{~i,j~}:[csum[j], csum[N]]$, ale caror valori $g{~i,j~}(csum[p])$ vor reprezenta costul minim pentru a amplasa $i$ depozite in benzinariile $[1..p]$, in conditiile in care al $i$-lea depozit este amplasat in benzinaria $j$. Aceste functii sunt definite pe sumele partiale ale cantitatilor de combustibil pentru a putea folosi un rationament asemanator celui prezentat mai sus si a privi fiecare functie ca o dreapta in intervalul dintre sumele partiale corespunzatoare a doua benzinarii consecutive. Panta unei functii $g{~i,j~}$ intr-un punct $csum[j{~1~}] (j{~1~}>j)$ va fi, conform acestor definitii, $d[j{~1~}]-d[j]$.\r\n\r\nh3. Probleme asemanatoare\r\n\r\n* \'leaves [.campion 2005]\':http://campion.edu.ro/problems/3/260/leaves_ro.htm\r\n* \'batch [IOI 2002]\':http://olympiads.win.tue.nl/ioi/ioi2002/contest/day2/batch/batch.pdf\r\n* petrom [ONI 2006, clasele 11-12]\r\n\r\nh3. Articole utile\r\n\r\n* \'http://citeseer.ist.psu.edu/87954.html\':http://citeseer.ist.psu.edu/87954.html\r\n* \'http://www.cse.ust.hk/faculty/golin/pubs/KMedian_SWAT04.pdf\':http://www.cse.ust.hk/faculty/golin/pubs/KMedian_SWAT04.pdf\r\n\r\n',2092,'public',NULL,NULL),('happy-coding-2008','Happy Coding 2008','2008-05-28 21:40:50','2008-05-31 06:33:38','h1. == roundparam(round_id=\"happy-coding-2008\" param=\"title\") ==\r\n\r\nVa invitam sambata, 31 mai, intre orele 09:30-12:30, la un nou concurs din seria Happy Coding. La fel ca si la editiile anterioare, evaluatorul va fi pornit pe toata durata concursului, iar punctajele ce vor putea fi obtinute la fiecare problema vor fi *0* sau *100* (stil ACM). Concursul va reprezenta prima etapa de selectie a studentilor ce vor face parte din echipele de ACM ale Universitatii Politehnica din Bucuresti (care vor participa la concursul regional sud-est european ACM in luna octombrie 2008).\r\n\r\n== roundregister(round_id=\"happy-coding-2008\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"happy-coding-2008\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"happy-coding-2008\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nIn timpul concursului vei putea \'*vedea clasamentul*\':happy-coding-2008/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"happy-coding-2008\" score=\"1\")==\r\n\r\nCele *6* probleme ale concursului sunt pregatite de ==user(user=\"mugurelionut\" type=\"tiny\")== , unul dintre antrenorii echipelor de ACM din UPB.\r\n\r\nh2. Organizatori\r\n\r\n* ==user(user=\"mugurelionut\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==',1,'round: happy-coding-2008',NULL,NULL),('autumn-warmup-2007/runda-3','Autumn Warm Up 2007','2007-10-04 17:07:54','2007-10-12 14:40:34','h1. Autumn Warm Up 2007\r\n\r\n(htabs)* \'Despre concurs\':autumn-warmup-2007/\r\n* \'Runda 1\':autumn-warmup-2007/runda-1\r\n* \'Runda 2\':autumn-warmup-2007/runda-2\r\n*(active) \'Runda 3\':autumn-warmup-2007/runda-3\r\n* \'Clasament\':autumn-warmup-2007/clasament\r\n\r\nRunda se va desfasura Duminica, 7 octombrie, la ora {*10^00^*} si va dura *5h*. Participantii vor avea de rezolvat 4 probleme de natura algoritmica. Evaluarea se va face la sfarsitul concursului.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"autumn2007-runda3\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"autumn2007-runda3\" score=\"1\")==\r\n\r\nSolutiile le gasiti \'aici\':autumn-warmup-2007/solutii/runda-3\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 3\':autumn-warmup-2007/clasament/runda-3\r\n\r\nh2. Organizatori\r\n\r\n* ==User(user=\"ditzonec\" type=\"tiny\")==\r\n* ==User(user=\"mariusdrg\" type=\"tiny\")==\r\n* ==User(user=\"CezarMocan\" type=\"tiny\")==\r\n* ==User(user=\"PaulDB\" type=\"tiny\")==\r\n* ==User(user=\"mugurelionut\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==',2092,'public',NULL,NULL),('blog/primul-post','Primul post','2007-10-08 03:15:58','2008-11-15 13:41:14','  Salutare, sunt \'Cosmin Negruseri\':http://infoarena.ro/utilizator/Cosmin si sunt bucuros sa va anunt ca *infoarena si-a tras blog*.\r\n\r\n  Vorbeam cu \'Cristi\':http://infoarena.ro/utilizator/wickedman pe la inceputul verii de nevoia unui blog pe inforena. Am ajuns imediat la concluzia ca trebuie sa fie un blog nativ pe infrastructura infoarena si nu unul pe care doar sa il integram. Pe de o parte nu ar trebui sa reinventam roata, dar pe de alta parte sunt multe \'feature-uri\':http://infoarena.ro/documentatie/macro-uri ale siteului de care vrem sa ne folosim. \r\n\r\n  Am discutat si cu \'Mircea\':http://infoarena.ro/utilizator/domino care era interesat de partea de programare, dar a avut timp de ea doar dupa ce si-a terminat internshipul pe vara in Redmond. A terminat prima varianta vinerea asta, dar a pus noul feature pe site doar dupa concursul de duminica. Inca mai e de lucru pe partea tehnica, dar e mai bine sa incepem mai repede decat mai tarziu.\r\n\r\n\r\n*Bine ati venit pe blogul infoarena, speram sa plecati de pe el putin mai destepti de fiecare data.*\r\n\r\n',1490,'protected',2163,NULL),('blog/preoni-2008-in-cautare-de-sigla','preONI 2008 - in cautare de sigla','2007-10-15 08:06:33','2008-11-15 13:41:14','Scoala a inceput de ceva vreme si se apropie perioada concursurilor online. Ca in fiecare an, din 2004 incoace, \'echipa infoarena\':http://infoarena.ro/echipa-infoarena va pregateste o noua editie a concursului preONI. Primul pas ar fi gasirea unui logo pentru concurs, si aici avem nevoie de ajutorul vostru.\r\n\r\nMajoritatea logourilor folosite pe site au fost facute cu ajutorul userilor. Sa vedem cum au aratat siglele de-a lungul timpului.\r\n\r\nLa inceput infoarena.devnet.ro avea acest logo:\r\n\r\n!{background-color:#336699}blog/preoni-2008-in-cautare-de-sigla?logo_vechi.gif!\r\n\r\nCand s-a facut trecerea la a doua versiune a siteului pe domeniul infoarena.ro, Dan Burzo ne-a facut o sigla simpatica, in care mascota siteului are ochelari, ca orice geek respectabil, dar poarta un coif pentu ca e gata de lupta in arena.\r\n\r\n!blog/preoni-2008-in-cautare-de-sigla?logo_burzo.jpg!\r\n\r\nLogoul pentru preONI 2006 a fost realizat tot de Dan Burzo.\r\n!blog/preoni-2008-in-cautare-de-sigla?hlogo.gif!\r\n\r\nIar logourile pentru fiecare runda de \'Cristina Stancu Mara\':utilizator/cimi\r\n\r\n!blog/preoni-2008-in-cautare-de-sigla?logo_runda1.gif! !blog/preoni-2008-in-cautare-de-sigla?logo_runda2.gif! !blog/preoni-2008-in-cautare-de-sigla?logo_runda3.gif! !blog/preoni-2008-in-cautare-de-sigla?logo_runda4.jpg! !blog/preoni-2008-in-cautare-de-sigla?logo_runda_finala.jpg!\r\n\r\nUrmatoarele doua logouri au fost facute pentru preONI 2007. Al doilea nu a fost folosit.\r\n\r\n!blog/preoni-2008-in-cautare-de-sigla?logo.jpg! autor Radu Lupaescu\r\n\r\n!blog/preoni-2008-in-cautare-de-sigla?logo.png! autor Alexandru Marinescu\r\n\r\nLe multumim inca o data celor ce ne-au ajutat si vrem sa va cerem ajutorul in realizarea unui logo pentru preONI 2008. O sugestie ar fi pentru culorile alese sa se integreze bine cu cele ale siteului.\r\n\r\n',1490,'protected',2206,NULL),('happy-coding-2005-2/solutii','Solutii Happy Coding 2','2007-10-12 12:02:08','2008-02-04 10:54:45','h1. Solutii Happy Coding 2\r\n\r\nProblemele date in cadrul acestui concurs au fost folosite pentru a selecta cele 3 echipe care au reprezentat Universitatea Politehnica Bucuresti la etapa regionala sud-est europeana a concursului ACM ICPC, in anul 2005.\r\n\r\nh2. \'Expresii algebrice\':problema/expresii\r\n\r\nVom calcula o matrie $T[i][j]$ reprezentand numarul de arbori de evaluare a sub-expresiei dintre pozitiile $i$ si $j$. Daca sub-expresia dintre aceste pozitii nu este valida (nu este parantezata corect, nu are o structura corespunzatoare de operanzi si operatori etc.), atunci $T[i][j]$ va fi 0. In caz contrar, daca expresia dintre pozitiile $i$ si $j$ este inclusa intre paranteze, atunci $T[i][j]=T[i+1][j-1]$. Daca nu este complet inclusa intr-o pereche de paranteze, atunci exista cel putin un operator care nu este inclus in vreo paranteza. Se cauta intai operatorii \' + \' care nu sunt inclusi intre paranteze si pentru fiecare astfel de operator aflat pe o pozitie $k$, $T[i][j]$ se incrementeaza cu valoarea $T[i][k-1]*T[k+1][j]$. Daca nu se gaseste nici un \' + \' neinclus intre paranteze, atunci se cauta un \' * \' si se realizeaza aceleasi operatii.\r\n\r\nh2. \'Calatorie interplanetara\':problema/calatorie\r\n\r\nVom calcula $C[i][j]$ reprezentand consumul minim pentru ca nava spatiala sa ajunga la planeta $i$ si sa fi parcurs $j$ unitati de timp cu superviteza. Valoarea lui $j$ este cel mult $500$. $C[i][j]$ se calculeaza pe baza lui $C[i-1][j]$ (daca intre planetele $i-1$ si $i$ nava a calatorit cu viteza normala) sau pe baza lui $C[i-1][j-H{~i-1~}]$ (daca intre planetele $i-1$ si $i$ nava a calatorit cu superviteza), alegandu-se varianta minima dintre cele doua posibilitati.\r\n\r\nh2. \'Razboiul lumilor\':problema/razboi\r\n\r\nSolutia optima are complexitate $O(N)$ si se realizeaza parcurgand arborele de $2$ ori. La prima parcurgere fixam radacina arborelui in nodul $1$. Vom calcula pentru fiecare nod $i$ cate $2$ valori: lungimea maxima a unui drum de la orasul $i$ la orice alt oras din subarborele acestuia, {$L{~1~}[i]$}, si lungimea maxima a unui drum de la orasul $i$ la un oras din subarborele acestuia, dar care este diferit de primul drum, {$L{~2~}[i]$} (practic, a doua lungime maxima a unui drum, care poate fi, eventual, egala cu lungimea primului). In a doua parcurgere vom calcula distanta maxima de la fiecare oras $i$ la orice alt oras si vom alege orasele pentru carea aceasta distanta maxima este minima. Pentru radacina arborelui am calculat deja aceasta valoare din prima parcurgere. Pentru orice alt nod $i$, distanta maxima de la $i$ la orice alt oras este ori {$L{~1~}[i]$}, ori un drum ce trece prin parintele lui $i$. Cel mai lung drum ce trece prin parintele lui $i$ are lungimea egala cu distanta de la $i$ la parintele lui $i$ plus {$L{~1~}[parinte[i]]$}, in cazul in care drumul corespunzator lui {$L{~1~}[parinte[i]]$} nu trece prin orasul $i$, respectiv plus {$L{~2~}[parinte[i]]$}, in cazul in care drumul corespunzator lui {$L{~1~}[parinte[i]]$} trece prin orasul $i$.\r\n\r\nA doua solutie are complexitatea $O(N*logN)$ si este o generalizare a solutiei pentru cazul in care toate muchiile arborelui au aceeasi lungime. Solutia pentru cazul muchiilor cu lungimi egale are complexitate $O(N)$ si se bazeaza pe o eliminare repetata a tuturor frunzelor din arbore. Se elimina primul strat de frunze, obtinandu-se un arbore mai mic, apoi se repeta procedeul pana cand arborele ramas are unul sau doua noduri (aceste noduri fiind nodurile cautate). In cazul in care muchiile au lungimi diferite, vom privi arborele dinspre exterior spre interior. Fiecarui nod $i$ din arbore ii corespunde un subarbore care are toate nodurile mai aproape de exterior decat nodul $i$. Vom elimina si de aceasta data frunzele, pe rand. Pentru fiecare nod $i$ vom calcula $dmax[i]$ ca fiind lungimea celui mai lung drum de la nodul $i$ la o frunza din subarborele sau (aceasta valoare reprezinta distanta nodului $i$ fata de exteriorul arborelui). La fiecare pas vom elimina un nod $i$ ramas frunza (deoarece toate nodurile din subarborele sau au fost deja eliminate anterior) pentru care $dmax[i]$ este minim (eliminam frunza cea mai apropiata de exteriorul arborelui initial). Repetam procedeul pana cand ramanem cu un nod sau cu $2$ noduri. Pentru a obtine complexitate mentionata putem folosi un heap.\r\n\r\nh2. \'Divizor si multiplu\':problema/divmul\r\n\r\nSe vor determina toti divizorii primi ai lui $x$ si ai lui $y$, impreuna cu puterile la care apar. Fiecare divizor prim al lui $x$ trebuie neaparat sa fie un divizor prim si al lui $y$, la o putere mai mare sau egala. Vom calcula $D$=numarul de divizori primi care apar la o putere mai mare in $y$ decat in $x$ (inclusiv acei divizori care apar in $y$ si nu apar deloc in $x$). Numarul de perechi ordonate care il au pe $x$ ca cel mai mare divizor comun si pe $y$ ca cel mai mic multiplu comun este $2^D^$.\r\n\r\nh2. \'Palindroame\':problema/palind\r\n\r\nPentru a avea solutie este necesar ca cel mult un singur caracter sa apara in sir de un numar impar de ori. In mod evident, nu vom inversa niciodata o pereche de caractere alaturate identice. Din acest motiv, in cadrul palindromului pe care il vom obtine, prima aparitie a unui caracter va fi \"imperecheata\" cu ultima aparitie a acelui caracter, a doua aparitie cu penultima s.a.m.d. In felul acesta, fiecare pereche defineste un interval $(a,b)$, $a$ reprezentand pozitia caracterului din stanga din cadrul perechii, iar $b$ reprezentand pozitia caracterului din dreapta din cadrul perechii. Singura conditie pentru ca numarul de inversiuni sa fie minim este sa nu ajungem sa inversam niciodata intre ele capetele a $2$ intervale care sunt incluse unul intr-altul. Pornind de la aceasta observatie, putem alege mereu intervalul corespunzator primului element al sirului si sa ducem pe ultima pozitie a sirului capatul dreapta al acestui interval, ramanand apoi cu un sir mai mic. In cazul in care primul element al sirului este caracterul ce trebuie sa se afle in mijlocul palindromului (pentru numar impar de caractere), atunci vom alege intervalul ce corespunde ultimei pozitii a sirului. Vom repeta acest procedeu pana cand ramanem cu un sir de lungime $0$ sau $1$.\r\n\r\nh2. \'Lungimi de interval\':problema/linterv\r\n\r\nVom sorta crescator intervalele dupa capatul stanga si apoi le vom parcurge in aceasta ordine. Vom mentine $2$ valori: $L$, reprezentand lungimea curenta, si $X$, reprezentand punctul cel mai din dreapta pana la care am \"acoperit\" cu intervale axa OX. Vom initializa valoarea lui $L$ cu $0$ si valoarea lui $X$ cu o valoare negativa (minus infinit). Pe masura ce parcurgem intervalele, avem $3$ situatii:\r\n\r\n* capatul stanga al intervalului curent este mai mare decat $X$ sau egal cu el => adunam la $L$ lungimea intervalului curent si setam pe $X$ la valoarea capatului dreapta al intervalului\r\n* capatul stanga al intervalului curent este mai mic decat $X$, iar capatul dreapta al acestuia este mai mic sau egal cu $X$ => nu realizam nici o actiune si mergem mai departe\r\n* capatul stanga al intervalului curent este mai mic decat $X$, iar capatul dreapta al acestuia este mai mare decat $X$ => adunam la $L$ diferenta dintre capatul dreapta al intervalului curent si $X$, iar apoi setam pe $X$ la valoarea capatului dreapta al intervalului curent.\r\n\r\nComplexitatea solutiei este $O(N*logN + N)=O(N*logN)$.\r\n\r\nh2. \'Resturi\':problema/resturi\r\n\r\nVom calcula numarul cerut in mod incremental. La pasul $i$ vom avea calculat numarul $Q$, reprezentand cel mai mic numar care respecta primele $i$ relatii (deci $Q mod p{~j~}=r{~j~}$ pentru orice $j &le; i$). La pasul $1$, $Q$ este egal chiar cu $r{~1~}$. Avand calculat numarul $Q$ la pasul $i$, va trebui sa determinam numarul $Q\'$ la pasul $i+1$ care respecta primele $i+1$ relatii. Acest numar $Q\'$ este de forma $Q + x*M$, cu $x &ge; 0$, unde $M$ este cel mai mic multiplu comun al numerelor $p{~1~},...,p{~i~}$ (fiind numere prime, $M$ este chiar produsul lor). Ideea din spatele acestei formule este ca la numarul $Q$ trebuie adunat un multiplu al numarului $M$, pentru ca numarul obtinut $Q\'$ sa pastreze aceleasi resturi la impartirile la primele $i$ numere prime date. Avem acum urmatoarea ecuatie: $Q + x*M = r{~i+1~} (mod p{~i+1~})$. Trecand pe $Q$ in partea dreapta, obtinem o ecuatie de forma $A*x = B (mod P)$, care se poate rezolva direct, folosind algoritmul lui Euclid extins, pentru a calcula inversul multiplicativ al lui $A$, relativ la numarul prim $P$. O metoda mai simpla de rezolvare a ecuatiei se bazeaza pe a incerca toate valorile posibile pentru $x$, intre 0 si $p{~i+1~}-1$, care functioneaza deoarece valorile numerelor prime sunt relativ mici (mai mici decat $1000$).\r\n\r\nAceasta problema este cunoscuta si ca \'Teorema chineza a restului\':http://en.wikipedia.org/wiki/Chinese_remainder_theorem .\r\n\r\nh2. \'Curse de cai\':problema/cai\r\n\r\nVom sorta caii lui Gigel si Ionel in ordine descrescatoare si ii vom renumerota conform acestei ordini. Vom considera ca Gigel decide pentru fiecare cal al lui Ionel, in ordinea sortata, ce cal de-al sau sa ii opuna in cursa. Solutia prezentata in continuare se bazeaza pe urmatoarea observatie. Sa presupunem ca Gigel a decis ce cai de-ai sai vor concursa impotriva primilor $i$ cai ai lui Ionel si urmeaza sa decida pentru al $i+1-lea$ cal. Singurele doua variante fezabile pe care le are Gigel este sa aleaga cel mai bun cal al sau (dintre cei ramasi) si sa il puna sa concureze cu al $i+1$-lea cal al lui Ionel sau sa aleaga cel mai prost cal al sau. Vom calcula o matrice $C[i][j]$ reprezentand costul maxim pe care il poate obtine Gigel daca i-au mai ramas caii de la $i$ la $j$ (asta inseamna ca toti caii de la $1$ la $i-1$ au fost deja selectati si la fel si toti caii de la $j+1$ la $N$; de aici rezulta ca Gigel a ales deja adversari pentru primii $N-j+i-1$ cai de-ai lui Ionel si acum trebuie sa aleaga adversar pentru urmatorul cal al lui Ionel). $C[i][j]$ se calculeaza pe baza lui $C[i+1][j]$ (daca Gigel alege cel mai bun cal al sau impotriva calului curent al lui Ionel) sau pe baza lui $C[i][j-1]$ (daca elege cel mai prost cal al sau), alegandu-se varianta de cost maxim. \r\n\r\nh2. \'Cercuri\':problema/cercuri\r\n\r\nO metoda simpla este sa translatam primul cerc in originea sistemului de axe de coordonate si sa il rotim pe cel de-al doilea pana cand centrul acestuia se afla pe axa $OX$ (la coordonata $X$ egala cu distanta dintre cele $2$ centre). Trebuie analizate cateva cazuri, pe baza valorilor razelor celor $2$ cercuri si a distantei dintre centrele lor. In cazul in care se decide ca cele $2$ cercuri se intersecteaza in $2$ puncte, vom observa ca, in urma translatiei si rotatie efectuate, cele $2$ puncte de intersectie se vor afla la aceeasi coordonata $x$, dar la coordonate $y$ opuse (egale in modul, dar opuse ca semn). Vom determina cele $2$ coordonate folosind teorema lui Pitagora generalizata in triunghiul format din centrele celor $2$ cercuri si fiecare din cele $2$ puncte de intersectie (deoarece cunoastem lungimile tuturor laturilor). Rezultatul pentru acest caz va fi apoi $2*|y|$.\r\n\r\nh2. \'J-Arbore\':problema/jarbore\r\n\r\nVom calcula $N[i]$, reprezentand cate noduri are arborele pe fiecare nivel (incepand de la $1$), precum si valoarea de pe prima muchie si de pe ultima muchie dintre nivelul $i-1$ si nivelul $i$ ({$v1[i] si v2[i]$}). Avem $N[ 1 ]=1$ si $v1[ 1 ]=v2[ 1 ]=0$. In cazul general, $N[i]=N[i-1]*(i-1)$, $v1[i]=v2[i-1]+1$ si $v2[i]=v1[i]+N[i]-1$. De asemenea, vom calcula cea mai mica si cea mai mare eticheta a unui nod de pe nivelul $i$: $vmin[i]=vmin[i-1]+v1[i]$ si $vmax[i]=vmax[i-1]+v2[i]$. Vom observa ca $24$ de nivele ale arborelui ajung pentru limitele date. Pentru fiecare numar $S$ dat vom gasi nivelul pe care s-ar afla (daca numarul exista in arbore), folosind valorile $vmin[i]$ si $vmax[i]$ (cautam acel nivel $i$ pentru care $vmin[i] &le; S &le; vmax[i]$) . Apoi, pentru a determina unde se afla numarul $S$, vom incerca sa deteminam pozitia acestuia in cadrul nivelului. Pentru aceasta vom realiza o cautare binara. Vom scrie o functie care va determina ce valoare se afla pe pozitia $p$ de pe nivelul $q$: aceasta valoare este valoare de pe pozitia $p/q$ de pe nivelul $q-1$, la care se adauga $v1[q]+p$ (considerand pozitiile numerotate de la $0$ in cadrul unui nivel). Vom determina astfel daca numarul $S$ exista si, daca da, vom reconstitui drumul de la el pana la radacina arborelui (ceea ce facem, oricum, in cadrul functiei de determinare a valorii de pe o pozitie $p$ de pe un nivel $q$).\r\n',6172,'public',NULL,NULL),('blog/interviu-mihai-patrascu-partea-intai','Interviu cu Mihai Patrascu - partea intai','2007-10-09 07:20:18','2008-11-15 13:41:14','!<blog/interviu-mihai-patrascu-partea-intai?mip-portrait.jpg!_(big)Am avut ocazia sa il reintalnesc acum vreo doua luni pe Mihai Patrascu dupa ce ultima data cand il vazusem a fost la Olimpiada Nationala de Informatica din Bacau in 2001. Era venit in Bay Area la un internship la centrul de cercetare IBM Almaden. I-am propus atunci sa facem un interviu pentru viitorul blog de pe infoarena._\r\n\r\n\'Mihai Patrascu\':utilizator/mpatrascu _(big)are printre cele mai bune rezultate la olimpiadele internationale la informatica dintre romani. A luat premiul I la Olimpiada nationala de informatica din clasa a 4a (concurand la clasa a 5a) pana intr-a 12a. La olimpiada internationala la de informatica a luat doua medalii de aur si una de argint (in 2001 a fost locul doi la internationala). La Concursul Europei Centrale de Informatica a luat un aur si un argint, iar la Balcaniada de informatica un argint. In 2005 a luat premiul_ \'Outstanding Male Undergraduate Award\':http://www.cra.org/Activities/awards/undergrad/2005.patrascu.html _(big)pe Statele Unite si Canada. Are chiar si o pagina pe_ \'wikipedia\':http://ro.wikipedia.org/wiki/Mihai_P%C4%83tra%C5%9Fcu_%28informatician%29\r\n\r\n_(big)Interviul va fi impartit in doua parti. In aceasta parte Mihai discuta despre MIT, despre cercetare si despre olimpiade:_\r\n\r\n**Cum ai inceput cu informatica?**\r\n\r\nIn clasa a 2a, am decis sa ma duc la Palatul Copiilor si sa studiez electronica. Din pacate, cursul de electronica se umpluse, dar mai erau locuri la cursul de programare...\r\n\r\n**Ai avut pe cineva care te-a ghidat? Un mentor, o persoana de la care ai invatat?**\r\n\r\nNu, practic niciodata. La mai sus-mentionatul curs de programare am invatat sa programez in Basic timp de cateva luni, si am fost captivat. Dar cu asta s-au sfarsit cursurile de programare care le-am luat. Am invatat Pascal dintr-o carte intr-a 4a, C din alta carte (in engleza) intr-a 6a, apoi pentru pregatire mai serioasa la olimpiada am citit GInfo, probleme de pe la concursuri, Knuth si CLR. In liceu am fost la profilul de mate-fizica.\r\n\r\nPrin facultate a continuat cam la fel. Dupa 1 an la MIT m-am mutat in departamentul de matematica (ca protest pentru departamentul de CS care nu ma lasa in pace), asa ca n-am luat nici pana azi nici un curs de programare. Am luat multe cursuri de algoritmi, evident. Dar n-au avut niciodata legatura cu cercetarea mea :)  Probabil mi-am ales domeniul de lucru dupa aceleasi criterii: un domeniu unde nu se facuse progres de peste 15 ani, si ca atare nu mai existau nici profi nici cursuri predate in mod curent...\r\n\r\n**De ce MIT si nu alte universitati din state sau din Romania?**\r\n\r\nAm facut un an la poli in Craiova, dar era o atmosfera trista. Practic lumea nu era acolo decat ca sa ia o diploma, si, partea cu adevarat trista, diploma aia nici nu prea conta...\r\n\r\nIn State, doar MIT-ul m-a acceptat :) Simplu.\r\n\r\n**Cum a fost procesul de admitere? Cat de mult conteaza o medalie la olimpiada internationala?**\r\n\r\nPana acum cativa ani, la MIT studentii internationali erau practic 100% cu medalii la diverse discipline, si clar asta era criteriul de baza. Multe alte universitati (gen Harvard si restul de Ivy League) cautau oameni cu un profil diferit, care sa ajunga politicieni, manageri etc. In perioada aia era faimoasa bariera culturala intre studentii de la MIT si cei de la Harvard.\r\n\r\nIn zilele noastre a aparut o oarecare convergenta. Internationalii de la MIT sunt mult mai \"normali\" si doar putini mai au medalii, in timp ce celelalte universitati au inceput sa aprecieze mai mult oamenii cu medalii.\r\n\r\nLa MIT au fost multe proteste (spre exemplu, Leiserson s-a plans mult) si speram sa revenim la admisia mai elitista (decanul de admisii a fost concediat recent, pe alte motive, si anul asta vom vedea ce face noul decan).\r\n\r\n**Cum e viata unui roman la MIT, sunt romanii sau strainii in general priviti ca outsideri?**\r\n\r\nLa MIT e foarte greu sa gasesti americani... Toti \"americanii\" sunt de fapt la prima generatie, fiind imigrati recent impreuna cu parintii. Asta se datoreaza educatiei la nivel de liceu in State, care orienteaza lumea spre stiinte sociale, avocatura etc. Persoanele care stiu teorema lui Pitagora la liceu sunt \"buni la matematica\", iar cei care Doamne-fereste iau un curs de trigonometrie sunt \"geeks\".\r\n\r\nLa toate capitolele, MIT-ul este mai mult decat deschis... Majoritatea oamenilor sunt foarte inteligenti, si exista o toleranta foarte mare (dupa principiul ca oamenillor destepti li se permite). Cei mai ciudati oameni i-am vazut la MIT.\r\n\r\n**Cursuri preferate in facultate?**\r\n\r\nAdvanced Data Structures (care l-am si predat un an), Advanced Algorithms, Randomized Algorithms, Geometric Computing, Computer Architecture, Microeconomics, Syntax (in lingvistica, nu programare :p)\r\n\r\n**De ce cercetare si nu programare?**\r\n\r\nCred ca mentalitatea de om de stiinta ma caracterizeaza. Imi doresc foarte mult sa aflu raspunsuri, nu numai sa fac ceva care sa mearga. Ca cercetator pot sa las ceva in urma, ceva cunostiinte noi pentru omenire. Ca programator m-as simti mult mai egoist -- fac ceva ca sa castig eu niste bani.\r\n\r\nIn plus, programarea mi s-a parut intotdeauna o unealta la ce facem noi, nu un scop in sine. Principalul este sa te gandesti, sa \"te prinzi\", si apoi poti sa stai cuminte si sa programezi ideea. Dar esenta e ideea. Un programator bun e unul care gandeste bine, nu unul care tasteaza repede.\r\n\r\n**Te-au influentat in vreun fel olimpiadele din liceu?**\r\n\r\nFoarte mult. Motivul evident e ca mi-au oferit o deschidere -- am vazut locuri noi, oameni noi, probleme mai grele, si apoi din cauza lor am ajuns la MIT. Motivul mai subtil dar mai important e ca olimpiadele au fost locul ideal pentru dezvoltarea spiritului competitiv. In Romania este foarte usor sa ajungi blazat si mediocru. La olimpiade descoperi ca poti sa castigi si poti sa pierzi, iar agonia si extazul sunt la un pas distanta. Odata ce prinzi gustul luptei, iti vei dori mereu sa faci mai mult in viata, si asta te face un om mai reusit.\r\n\r\n**Ti-a ramas in minte vreo problema de la concursuri?**\r\n\r\nAm dat la BOI\'03 o problema draguta cu Farey sequence. E exemplul meu favorit despre cum problemele de concursuri pot fi interesante si pentru \"oamenii mari\". La concurs era suficienta o rezolvare in <tex>O(n\\ lg^2 n)</tex>, si s-au prins cativa oameni. Apoi m-am mai gandit la problema, am gasit o rezolvare in <tex>O(n\\ lg n)</tex> si am publicat-o la o conferinta de Algorithmic Number Theory, ca amuzament matematic. Oamenilor le-am placut, si recent un tip din Polonia (care a fost si\r\nel la IOI prin 1995) a gasit in algoritm in <tex>O(n^{3/4})</tex>, care l-a publicat la European Symposium on Algorithms. Bineinteles ca asta m-a motivat, si i-am imbunatatit algoritmul la <tex>O(n^{2/3})</tex> -- deci recordul revine la Romania :)\r\n\r\nNu e o problema fundamentala care chiar sa conteze, dar arata cum tipul de rationament de la olimpiada e acelasi ca pentru cercetare.\r\n\r\n**Cum te antrenai in timpul liceului? Studiai din carti? Rezolvai probleme de pe siteuri cu evaluatoare automate? Discutai probleme cu colegii?**\r\n\r\nPe vremea mea nu prea existau siteuri cu evaluare automata. N-am folosit niciodata unul, desi cred ca sunt utile.\r\n\r\nEu in principal citeam carti, GInfo, etc si ma gandeam la probleme. Discutam destul de mult cu ceilalti concurenti, de la care invatam idei interesante. Asta se intampla la lot, pentru ca in Craiova nu era nimeni cu care sa pot sa discut.\r\n\r\n**Ai vreun algoritm/structura de date preferata?**\r\n\r\nPartial sums, care este o structura de date foarte clasica si simpla. Problema: ai un array <tex>A[1..n]</tex>, poti sa faci update (A[i] = valoare noua), si queries: raporteaza suma <tex>A[1]+..+A[k]</tex>, pentru k dat.\r\n\r\nCred ca toata lumea stie ca se face in <tex>O(lg\\ n)</tex> cu binary trees, si ideea e super-utila in multe probleme.\r\n\r\nCand am ajuns la MIT, vroiam sa incep sa lucrez in cercetare si citeam lucrari pe care le gaseam pe Internet sa vad despre ce e vorba. Am citit undeva ca nu s-a putut demonstra ca <tex>O(lg\\ n)</tex> e optim la problema asta (spre exemplu, ganditi-va ca pentru a face un dictionar, in loc de binary trees poti sa folosesti hashing, care merge in timp constant). Mi s-ar parut straniu ca nimeni n-a putut demonstra asta, asa ca am scris un paper in care am demonstrat. Mi s-a spus apoi ca asta era \"problema nr 1\" in data structures din 1989, am fost invitat sa dau talkuri despre solutie, si am primit si un premiu.\r\n\r\nTotul a fost accidental, pur si simplu eu nu stiam nimic si am avut o perspectiva total diferita de toata lumea... Dar acum evident sunt foarte atasat de problema asta :)\r\n\r\n\r\nh2. _(big)A doua parte din interviu va fi publicata in curand._\r\n\r\n',1490,'protected',2164,NULL),('blog/three-beautiful-quicksorts','Three Beautiful Quicksorts','2007-10-11 04:52:39','2008-11-15 13:41:14','Eu stiam de Jon Bentley pentru ca este autorul cartii \'Programming Pearls\':http://www.amazon.com/Programming-Pearls-2nd-Jon-Bentley/dp/0201657880/ref=pd_bbs_sr_1/103-0677549-4911837?ie=UTF8&s=books&qid=1192076924&sr=8-1, o carte scrisa foarte bine si care se citeste foarte usor, spre deosebire de Introducere in algoritmi. Ea contine multe trucuri dragute de algoritmica si poate reprezenta o introducere foarte buna pentru cei ce vor sa invete algoritmica. Singura problema e ca nu este tradusa in romana.\r\n\r\nAstfel am fost curios cand Jon a avut o prezentare, numita Three Beautiful Quicksorts, la Google acum doua luni. In talk apar chestii interesante cum ar fi optimizarea metodei _qsort()_ din _C_ (si ca paranteza Joshua Bloch mentioneaza ca implementarea din _Java_ a functiei _sort()_ urmareste indeaproape ideile din talk) sau o imagine in care vedem ca variante diferite ale quick sortului nu au graficul similar cu cel al functiei <tex>n\\ log\\ n</tex>, ci se vad trei bucati care se comporta diferit, ele corespunzand nivelelor de cache si memoriei. Sperand ca v-am deschis putin apetitul, puteti sa vizionati aici prezentarea: \r\n\r\n==GoogleVideo( id=\"-1031789501179533828\" )==\r\n\r\n',1490,'protected',2187,NULL),('sandbox/1expr','sandbox/1expr','2007-10-11 18:04:34','2007-10-11 19:56:45','==Include(page=\"template/taskheader\" task_id=\"1expr\")==\r\n\r\n==Include(page=\"template/cleanup\")==\r\n\r\nGigel, student in anul II (desi a inceput facultatea acum 4 ani - ce sa-i faci, Electronica asta..), tocmai a invatat despre expresii aritmetice ce contin operatorii {@\'+\',\'*\',\'^\'@} si {@\'!\'@}, precum si paranteze ({@\'(\'@} si {@\')\'@}). Totusi, fiind abia in anul II, el se incurca cand trebuie sa lucreze cu numere prea mari, de aceea singurul numar care apare in mod direct (adica nu doar ca rezultat al unei operatii) in cadrul unei expresii este numarul $1$. Vom numi o astfel de expresie 1-expresie. De exemplu, {@\"(1+(1*1))^(1+1+1*1)^(1+(1+1)!)\"@} este o 1-expresie, dar {@\"2+5*7+6!+3^4^3!+1*6\"@} nu este o 1-expresie (deoarece apar in mod direct numerele 2, 3, 4, 5, 6 si 7). O 1-expresie poate fi privita ca un sir format din caracterele {@\'1\',\'+\',\'*\',\'^\',\'!\',\'(\',\')\'@} si care poate fi descris cu ajutorul urmatoarelor reguli gramaticale:\r\n\r\n{@1-expresie =@}\r\n\r\n* {@\'1\'@}\r\n* {@\'(\' 1-expresie \')\'@}\r\n* {@1-expresie \'+\' 1-expresie@}\r\n* {@1-expresie \'*\' 1-expresie@}\r\n* {@1-expresie \'^\' 1-expresie@}\r\n* {@1-expresie \'!\'@}\r\n\r\nDesi in cadrul expresiei apare in mod direct doar numarul $1$, rezultatele evaluarii operatiilor pot fi numere mai mari decat 1, astfel ca Gigel va trebui sa invete sa foloseasca si aceste numere. Pentru a evalua o expresie aritmetica, trebuie cunoscute prioritatile operatorilor. \r\n\r\n* Operatorul cu cea mai mica prioritate este {@\'+\'@} si realizeaza operatia de adunare. Rezultatul 1-expresiei {@\"1+1+1\"@} este 3. \r\n* Operatorul {@\'*\'@} este mai prioritar decat operatorul {@\'+\'@} si realizeaza operatia de inmultire. Rezultatul 1-expresiei {@\"1+1*(1+1)*(1+1+1)+(1+1)*(1+1)\"@} este {@1+1*2*3+2*2=1+6+4=11@}. Operatorul {@\'^\'@} este mai prioritar decat operatorii {@\'+\'@} si {@\'*\'@} si realizeaza operatia de ridicare la putere ({@A^B@} reprezinta {@A@} ridicat la puterea {@B@}). Rezultatul 1-expresiei {@\"(1+1)*(1+1+1)^(1+1)*(1+1+1)+(1+1)\"@} este {@2*3^2*3+2=2*9*3+2=54+2=56@}. \r\n* Spre deosebire de operatorii {@\'+\'@} si {@\'*\'@} care au proprietatea ca {@A+B=B+A@} si {@A*B=B*A@}, in cazul {@\'^\'@} nu este neaparat adevarat ca {@A^B=B^A@} (decat in unele cazuri speciale). O alta particularitate a acestui operator este ordinea de aplicare in cazul absentei parantezelor: el este asociativ dreapta. De exemplu, {@A^B^C^D@} este echivalent cu {@A^(B^(C^D))@}. Rezultatul 1-expresiei {@\"(1+1)^(1+1)^(1+1+1)\"@} este {@2^2^3=2^(2^3)=2^8=256@} si nu {@(2^2)^3=4^3=64@}. Astfel, daca exista mai multi operatori {@\'^\'@} neseparati de paranteze, ordinea de efectuare a operatiilor este de la dreapta catre stanga. \r\n* Operatorul cu prioritatea cea mai mare este {@\'!\'@} si realizeaza operatia \"factorial\". Rezultatul 1-expresiei {@\"(1+1+1)!\"@} este {@3!=6@}. Factorialul unui numar {@X@}, notat {@X!@}, este definit ca fiind {@1*2*..*X@}. Rezultatul 1-expresiei {@\"(1+1)*(1+1+1+1)!^(1+1+1)!!\"@} este {@2*4!^3!!=2*(4!)^(3!!)=2*(4!)^((3!)!)=2*24^(6!)=2*(24^720)@} (rezultatul este un numar prea mare pentru a fi afisat aici).\r\n\r\nLungimea unei 1-expresii este definita ca fiind egala cu numarul de caractere ale sirului ce reprezinta 1-expresia. Lungimea 1-expresiei {@\"(1+1)!^(1+1)*(1+1)+1\"@} este 20. Tema pe care a primit-o Gigel la scoala este urmatoarea: dandu-se un numar $N$, gasiti o 1-expresie de lungime minima al carei rezultat sa fie egal cu $N$. Ajutati-l pe Gigel sa isi rezolve tema.\r\n\r\nh2. Date de Intrare\r\n\r\nPrima linie a fisierului de intrare $1expr.in$ contine numarul intreg $T$. Pe urmatoarele $T$ linii se afla cate un numar intreg $N$.\r\n\r\nh2. Date de Iesire\r\n\r\nIn fisierul de iesire $1expr.out$ veti afisa $T$ linii. Pe a $K$-a linie veti afisa o 1-expresie de lugime minima al carei rezultat este egal cu al $K$-lea numar dintre cele $T$ date in fisierul de intrare. Daca exista mai multe 1-expresii de lungime minima, puteti afisa oricare dintre ele.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; T &le; 100$\r\n* $1 &le; N &le; 3^8^$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. 1expr.in |_. 1expr.out |\r\n|3 \r\n 1\r\n 3\r\n 200 \r\n|1 \r\n 1+1+1 \r\n (1+1)^(1+1+1)*(1+(1+1+1+1)!) |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"1expr\")==',6172,'public',NULL,NULL),('happy-coding-2005-1/solutii','Solutii Happy Coding 1','2007-10-11 22:15:02','2009-05-09 13:11:50','h1. Solutii Happy Coding 1\r\n\r\nProblemele date in cadrul acestui concurs au fost folosite initial la preselectia individuala a studentilor ce au alcatuit echipele care au reprezentat Universitatea Politehnica Bucuresti la concursul ACM ICPC, in anul 2005.\r\n\r\nh2. \'Arie\':problema/arie\r\n\r\nO metoda simpla consta in determinarea punctelor de intersectie intre orice latura a primului poligon si orice latura a celui de-al doilea. Apoi se determina varfurile primului poligon aflate in interiorul celui de-al doilea poligon, precum si varfurile celui de-al doilea poligon aflate in interiorul primului poligon. Se realizeaza apoi o infasuratoare convexa a punctelor astfel determinate. Ca varianta mai simpla, intrucat stim sigur ca punctele determinate sunt varfurile unui poligon convex ce reprezinta aria intersectiei celor $2$ poligoane date, putem calcula un punct \"central\", reprezentat de media aritmetica a coordonatelor punctelor determinate. Apoi vom sorta punctele in jurul acestui punct \"central\", determinand astfel ordinea acestora pe conturul poligonului intersectie. Se calculeaza apoi aria poligonului intersectie, folosind formula bine cunoscuta bazata pe suma determinantilor $2x2$, cate unul pentru fiecare latura a poligonului intersectie, ce contin coordonatele celor $2$ puncte ale fiecarei laturi.\r\n\r\nh2. \'Bile\':problema/bile\r\n\r\nProblema se rezolva folosind structura de date numita multimi disjuncte. Se va inversa sensul operatiilor date, parcurgandu-le de la sfarsit care inceput, si considerand ca ele reprezinta operatii de adaugare a cate unei bile, si nu de eliminare a bilelor. Se va mentine pe parcurs valoarea maxima a componentelor conexe formate.\r\n\r\nh2. \'Muzeu\':problema/muzeu\r\n\r\nProblema se rezolva folosind algoritmul lui Lee, considerand ca se pleaca simultan din toate pozitiile paznicilor. Varianta \"clasica\" a algoritmului porneste de la o singura pozitie. Aceasta pozitie de start este adaugata intr-o coada. Apoi, fiecare element al cozii este expandat pe rand, putand adauga noi elemente in coada, vecine cu acesta. Singura diferenta fata de varianta \"clasica\" este ca la inceput se introduc in coada toate pozitiile corespunzatoare cate unui paznic.\r\n\r\nh2. \'Transport\':problema/transport\r\n\r\nSe va cauta binar capacitatea minima a camionului. Pentru o capacitate fixata $C$, se va folosi un algoritm greedy pentru a determina numarul minim $X$ de transporturi ce trebuie efectuate. Acest algoritm greedy va lua in primul transport un numar maxim de saltele din varful stivei, cu conditia ca suma volumelor acestora sa nu depaseasca valoarea $C$. La al doilea transport va face acelasi lucru, pornind de la salteaua ramasa in varful stivei s.a.m.d. Daca numarul de transporturi determinat $X$ este mai mic sau egal cu $K$, atunci se poate incerca o capacitate mai mica; in caz contrar, se va incerca o capacitate mai mare. \r\n\r\nh2. \'Suma\':problema/suma\r\n\r\nSuma data se poate ca scrie ca <tex> \\displaystyle\\sum_{i = 1}^N i^2 </tex> - <tex> \\displaystyle\\sum_{i = 1}^N i </tex>. Prima suma este egala cu $N*(N+1)*(2*N+1)/6$. A doua suma este egala cu $N*(N+1)/2$. Se vor calcula restul impartirii primei sume la $P$ ({$R{~1~}$}) si restul impartirii celei de-a doua sume la $P$ ({$R{~2~}$}). Pentru aceasta va trebui sa scapam de operatiile de impartire. Aceasta se poate realiza usor, deoarece, in cadrul primei sume, $6$ se scrie ca fiind $2*3$ si cel putin unul din cei $3$ factori de la numarator este divizibil cu $2$ si cel putin unul este divizibil cu $3$. In mod similar, cel putin unul din cei doi factori de la numaratorul celei de-a doua sume este divizibil cu 2. Rezultatul cautat este $(R{~1~}-R{~2~}+P) mod P$.\r\n\r\nh2. \'Numere\':problema/numere\r\n\r\nSingurele stari $(X,Y)$, cu $X &ge; Y$, care ne intereseaza sunt cele prin care trece algoritmul lui Euclid pentru determinarea celui mai mare divizor comun (varianta cu impartiri, nu cea cu scaderi repetate). Pentru o astfel de stare vom calcula $win(X,Y)$ ca avand valoarea $1$, daca jucatorul aflat la mutare are o strategie sigura de castig din starea respectiva, respectiv $0$ in caz contrar. Vom avea $win(X,0)=0$. Daca $X &lt; 2*Y$, atunci $win(X,Y)=1-win(Y,X-Y)$. Daca $X &ge; 2*Y$, atunci $win(X,Y)=1$.\r\n',9232,'public',NULL,NULL),('blog/problema-misto','O problema misto','2007-10-12 07:12:41','2008-11-15 13:41:14','Dumitru Daniliuc mi-a zis o problema simpatica de pe vremea cand se antrena in liceu pentru olimpiadele de matematica, pe care acum vreau sa v-o zic si voua.\r\n\r\nProblema suna asa: Se da o multime S, de puncte in plan. Aria ocupata de puncte e strict mai mica decat unu. Se cere sa se gaseasca un sistem de coordonate astfel ca punctele de coordonate intregi din acest sistem de coordonate sa nu se suprapuna peste nici un punct din multimea S.\r\n\r\nVa rog, daca aveti solutii, sa nu le publicati pe forum ci sa mi le trimiteti ca mesaj privat. In doua zile voi publica o solutie si numele celor ce au rezolvat corect problema.\r\n\r\n*Update:* Multimea S poate contine o infinitate de puncte. De exemplu S e formata din cateva pete si o dreapta. Aria dreptei e 0 si suma ariilor petelor e mai mica ca 1.\r\n\r\n*Update2:* Pentru a nu complica problema si definitia a ce inseamna arie, impunem restrictia ca multimea S este formata din un numar finit de pete, fiecare avand o arie. Deci S nu va contine drepte, spirale sau mai stiu eu ce.\r\n\r\n*Update3:* Sistemul de coordonate trebuie sa fie ortonormat si sa pastreze dimensiunile initiale.\r\n\r\n',1490,'protected',2188,NULL),('reguli','Reguli','2007-10-29 20:23:14','2007-12-06 18:11:58','h2. Cateva reguli si sugestii pentru o mai buna desfasurarea a activitatii pe forumul infoarena\r\n\r\n== include(page=\"template/todo\") ==\r\n\r\nPana acum forumul a reprezentat o parte importanta a proiectului infoarena, permitand membrilor comunitatii sa se cunoasca mai bine si sa se ajute reciproc. In general cei care au postat au dat dovada de bun simt si au avut un comportament civilizat. In utlimul timp insa am observat o oarecare tendinta de marginalizare a unora dintre membri comunitatii si de multe ori a fost nevoie de stergerea unor posturi si banarea unor useri. Forumul infoarena ar trebui sa fie un loc unde vii cu placere pentru a invata informatica, pentru a afla lucruri noi si pentru a te destinde. Pentru a evita situatiile neplacute in viitor, am decis ca ar trebui gasite cateva mici reguli si sugestii.\r\n\r\nh2. Reguli \r\n\r\n* Evitati mesajele obscene, grosolane sau care aduc atingere unor persoane sau relatii sociale. Nu sunt tolerate mesajele cu tenta rasista sau cele discriminatorii. O purtare adecvata presupune combaterea ideilor exprimate si nu a persoanelor care le-au lansat.\r\n* Incercati sa pastrati un ton adecvat in conversatiile cu ceilalti utilizatori. Este de asteptat ca atunci cand cineva are o intrebare sa fie lamurit, si nu sa fie tratat superficial.\r\n* Forumul infoarena nu ar trebui folosit in scopuri publicitare. Deasemenea, dorim sa evitam pe cat posibil spam-urile.\r\n* Posturile ar trebui sa aiba legatura cu topicul din care fac parte, incercati sa nu alimentati discutiile off-topic (prea mult).\r\n* Pentru a comunica un anumit lucru, este de ajuns un singur post. Nu este necesar sa scrieti acelasi post in mai multe categorii ale forumului. Probabil ca nu vi se va raspunde mai repede ;).\r\n* Incurajam ideea ca, la crearea contului, sa completati profilul cu datele voastre reale. Astfel, dati dovada de o mai mare seriozitate in pregatirea voastra pe infoarena.\r\n* Infoarena se adreseaza tuturor celor interesati de informatica, insa nu ar trebui sa reprezinte locul unde sa iti rezolvi temele pentru scoala/facultate. Probabil ca nici cei care si-ar rezolva temele aici nu ar iesi mai castigati.\r\n* Este suparator ca atunci cand citesti un topic sa observi raspunsuri la unele posturi care nu mai exista pentru ca autorii lor le-au sters. Pentru a pastra o oarecare logica a mesajelor, recomandam sa nu stergeti un post daca observati ca vi s-a raspuns.\r\n* Folositi functia edit pentru a va edita mesajele atunci cand doriti sa modificati ceva sau pentru a nu posta de doua ori consecutiv.\r\n* Infoarena nu incurajeaza pirateria sub nicio forma. Sunt strict interzise atasamente sau link-uri catre programe, documente sau fisiere detinute ilegal (fara licenta sau obtinute din surse indoielnice: torrente, DC++ etc).\r\n* Folositi mesajele personale pentru corespundenta privata.\r\n* Karma reprezinta o apreciere a celorlati membri cu privire la activitatea unei persoane pe forum. Nu ar trebui sa aveti o atitudine negativa fata de cineva doar pentru ca v-a dat un minus la karma.\r\n\r\nh2. Recomandari\r\n\r\n* Incercati sa nu folositi limbaj de messenger sau de chat. Uneori este foarte greu de citit si descifrat un post scris intr-o astfel de maniera.\r\n* Nu folositi in mod excesiv majuscule sau culori stridente. Pot crea o senzatie de disconfort pentru cel care citeste. Acelasi lucru e valabil si pentru smiley-uri utilizate abundent.\r\n* Ar fi bine sa acordati o importanta crescuta mesajului pe care doriti sa-l scrieti. Adesea, un punct sau o virgula bine puse pot elimina orice ambiguitate.\r\n* Pentru a nu aduce in discutie subiecte deja tratate pe forum, folositi functia \"Cauta\".',1,'public',NULL,NULL),('blog/salarii-in-it','Salarii in IT','2007-11-12 10:46:08','2008-11-15 13:41:14','Citeam via \'Manafu\':http://manafu.blogspot.com/ un \'articol\':http://www.revistabiz.ro/download/147/CoverStory.pdf interesant din Revista Biz despre salariile in mai multe industrii. Pentru mine e interesanta partea cu salarii in domeniul IT pe care o gasiti in totalitate la pagina 17. Am pus in imaginea alaturata doar partea de dezvoltare soft.\r\n\r\nDupa cum stiu eu salariile in programare din Cluj, pragurile din articol par bune, mai putin ca pe partea de entry level, unde sunt ceva mai mici. Presupun ca sunt variatii mari de la regiune la regiune si de la firma la firma.\r\n\r\n!blog/salarii-in-it?salarii!\r\n\r\nVoua cum vi se par estimarile?\r\n\r\n',1490,'protected',2337,NULL),('happy-coding-2006/solutii','Solutii Happy Coding 3','2007-10-12 23:07:52','2007-11-16 22:12:27','h1. Solutii Happy Coding 3\r\n\r\nO parte din problemele date in cadrul acestui concurs (cele propuse de Mugurel Ionut Andreica) au fost folosite pentru a selecta echipele care au reprezentat Universitatea Politehnica Bucuresti la etapa regionala sud-est europeana a concursului ACM ICPC, in anul 2006.\r\n\r\nh2. \'AVD\':problema/avd\r\n\r\nCea mai simpla solutie consta in generarea tuturor submultimilor de muchii pe care le eliminam. Ce ramane este o reuniune de componente conexe, care defineste fiecare cate o partitie. Dintre toate cele $2^N-1^$ partitii generate, le pastram pe cele unice si impartim acest numar la numarul total de partitii (care poate fi generat si el prin backtracking sau folosind programare dinamica).\r\n\r\nO solutie mai laborioasa consta in generarea fiecarei partitii (putin peste $100$, pt $N=13$) si, pentru fiecare astfel de partitie (care are, sa presupunem $K$ elemente), calcularea urmatoarelor valori: $ok[i][j][S] = 1$ sau $0$ , reprezentand daca e posibil sau nu sa se \"acopere\" elementele partitiei corespunzatoare starii $S$ ( $S$ e un numar pe $K$ biti), folosind nodurile din subarborele lui $i$ si ramanand $j$ noduri, inclusiv nodul $i$, intr-o componenta conexa pe care nu o \"potrivim\" peste vreun element al partitiei (si care poate fi eventual extinsa ulterior de catre un stramos al lui $i$); o valoare $j=0$ indica ca au fost folosite toate nodurile din subarborele lui $i$, inclusiv $i$, pentru a genera componente conexe care se \"potrivesc\" peste elemente ale partitiei. Aceste valori se calculeaza folosind programare dinamica de tip rucsac pe arbore, in functie de valorile calculate pentru fii (valori de tipul $ok[fiu][j\'][S\']$, cu $j\' &lt; j$ si $S\'$ inclus in $S$). Daca $ok[ 1 ][ 0 ][2^K^-1]$ are valoarea $1$, atunci se poate genera o impartire in componente conexe a arborelui, ce corespunde partitiei respective.\r\n\r\nh2. \'CT\':problema/ct\r\n\r\nSe fixeaza radacina arborelui intr-un nod (sa zicem nodul $1$). Pentru fiecare din cele $K$ perechi de orase se calculeaza $LCA$-ul (lowest common ancestor = cel mai apropiat stramos comun). Se poate folosi orice metoda eficienta de determinarea a $LCA$-ului: de exemplu, pentru fiecare nod $i$ se pot memora $O(logN)$ valori, $stramos[i][j]$, reprezentand stramosul aflat cu $2^j^$ nivele mai sus in arbore (cu $j$ incepand de la $0$), iar cu aceste valori, $LCA$-ul a oricare $2$ noduri se poate determina in timp $O(logN)$. Se sorteaza apoi $LCA$-urile tuturor perechilor, in functie de nivelul din arbore ({$LCA$}-urile de pe un nivel mai jos aflandu-se inaintea celor de pe un nivel mai ridicat). In continuare, vom parcurge $LCA$-urile in ordinea sortata. Pentru a rezolva problema, avem acum $2$ posibilitati:\r\n\r\n* Vom renumerota nodurile conform unei parcurgeri in adancime (DF), astfel incat toate nodurile din subarborele oricarui nod $i$ sa formeze un interval de numere consecutive. Apoi vom tine un arbore de intervale pentru aceste numere. In arborele de intervale vom memora daca un nod (identificat prin numarul asociat lui din cadrul parcurgerii DF) a fost eliminat din arbore sau nu. Pentru fiecare $LCA$, in ordinea precizata mai sus, vom verifica daca cel putin unul din cele $2$ noduri al caror $LCA$ este a fost deja eliminat din arbore. Daca nu a fost eliminat nici unul, vom selecta $LCA$-ul acestora ca oras ce va fi bombardat si vom marca ca intreg intervalul de numere corespunzator subarborelui $LCA$-ului a fost eliminat din arbore. Complexitatea acestei variante este $O(K*logN)$, plus complexitatea determinarii celor $K LCA$-uri (care ar putea fi $O(N*logN + K*logN))$.\r\n* A doua varianta nu mai necesita o renumerotare si utilizarea unui arbore de intervale, insa mentine ideea de a memora pentru fiecare nod daca acesta a fost eliminat sau nu din arbore. Parcurgem $LCA$-urile si verificam pentru fiecare daca cel putin unul din cele $2$ noduri din perechea de noduri pentru care a fost calculat $LCA$-ul a fost deja eliminat din arbore. Daca nici unul din cele $2$ noduri nu a fost eliminat din arbore, vom selecta $LCA$-ul ca fiind oras ce va fi bombardat si apoi vom efectua o parcurgere DF pentru a marca toate nodurile din subarborele acestuia ca fiind eliminate. Optimizarea importanta este ca daca, in cadrul acestei parcurgeri, intalnim un nod deja marcat anterior ca fiind eliminat, nu vom parcurge subarborele acestuia. In felul acesta, fiecare nod este marcat ca find eliminat cel mult o singura data, iar complexitatea acestei etape este $O(K + N)$.\r\n\r\nh2. \'Swap\':problema/swap\r\n\r\nVom construi o permutare $P$ a multimii ${1,...,N}$, asociata primului sir ({$N$} este lungimea fiecaruia din cele $2$ siruri). Pentru fiecare caracter $x$ din primul sir, vom calcula al catelea caracter de tipul respectiv este in cadrul primului sir (acest lucru se poate realiza usor in $O(N)$). Apoi vom construi permutarea $P$ in felul urmator: pentru fiecare caracter $x$, pentru care stim ca este al $y$-lea caracter de tipul sau si care se afla pe pozitia $i$, vom seta valoarea lui $P[i]$ ca fiind egala cu pozitia pe care se afla cel de-al $y$-lea caracter egal cu $x$ din cel de-al doilea sir. Numarul de operatii $swap$ necesare este egal cu numarul de inversiuni ale permutarii $P$. Acest numar poate fi determinat eficient in mai multe feluri: folosind mergesort (sortare prin interclasare), arbori de intervale, arbori indexati binar, impartirea in grupe de cate<tex>\\sqrt N</tex> etc.\r\n\r\nh2. \'Obj\':problema/obj\r\n\r\nVom porni de la o solutie avand complexitatea $O(N*K)$. Vom calcula $win[ 0 ][ i ]$ = $1$, daca gramada contine $i$ obiecte, castigatorul trebuie sa stranga un numar par de obiecte, iar jucatorul aflat la mutare are strategie sigura de castig, sau $0$, daca jucatorul aflat la mutare nu are strategie sigura de castig. $win[ 1 ][ i ]$ va reprezenta acelasi lucru, cu diferenta ca cel care castiga jocul este cel care aduna un numar impar de obiecte. Avem $win[ 0 ][ 0 ] = 1$ si $win[ 1 ][ 0 ] = 0$. Pentru fiecare valoare a lui $i$ de la $1$ la $N$, variem numarul de obiecte pe care le ia jucatorul aflat la mutare si, in functie de paritatea acestui numar, paritatea lui $i$ si paritatea numarului de obiecte ce trebuie luate pentru a castiga jocul, se determina starile in care se poate ajunge; ca orice alt joc rezolvat prin programare dinamica, jucatorul aflat la mutare va avea strategie sigura de castig daca cel putin una din starile in care poate ajunge este o stare de pierdere pentru jucatorul ce se va afla la mutare in continuare (adica adversarul).\r\n\r\nSolutia $O(N*K)$ se poate optimiza la $O(N)$, observand ca, de fapt, pentru starile in care poate ajunge jocul dupa efectuarea unei mutari nu ne intereseaza numarul exact de obiecte ramase, ci paritatea acestui numar. Pe masura ce mergem cu $i$ de la $1$ la $N$ si calculam valorile mentionate anterior, retinem si ultima valoare a lui $i$ ce corespunde unei stari de tipul $(x,y,z)$, unde $x$ reprezinta pariatea numarului de obiecte pe care trebuie sa le ia unul din cei doi jucatori pentru a castiga jocul, $y$ reprezinta paritatea numarului de obiecte aflate in gramada, iar $z$ retine daca jucatorul aflat la mutare are sau nu are strategie sigura de castig in conditiile date de $x$ si $y$. Memorand astfel de triplete, problema de decizie pentru un numar de obiecte $i$ se reduce la a verifica daca ultimul numar de obiecte din gramada (ultima pozitie $j &lt; i$) ce corespunde unei stari de un anumit tip care ar determina existenta unei strategii sigure de castig pentru pozitia $i$, se afla in intervalul $[i-K,i-1]$ (adica acel numar de obiecte in gramada poate fi obtinut dintr-o singura mutare).\r\n\r\nUitandu-ne pe valorile obtinute pentru fiecare $i$ de la $1$ la $N$, observam o regula care reduce complexitatea rezolvarii problemei la $O(1)$. Pentru $K$ par, daca $N mod (K + 2) = 1$, castigatorul jocului va fi Ionel (al doilea jucator); in caz contrar, castigatorul va fi Gigel (primul jucator). Pentru $K$ impar, daca $N mod (2 * K + 2) = 1$, atunci castigatorul este Ionel (al doilea jucator); in caz contrar, castigatorul va fi Gigel (primul jucator).\r\n\r\nh2. \'1expr\':problema/1expr\r\n\r\nProblema se rezolva folosind programare dinamica. Pentru fiecare $K$ de la 1 la $3^8^$ se calculeaza lungimea minima a unei $1-expresii$ care are ca rezultat pe $K$, iar ultima operatie efectuata in cadrul acestei $1-expresii$ este $+$, $*$, $^$ sau $!$ (deci se calculeaza $4$ valori). Este important sa se calculeze toate aceste $4$ valori si nu doar o singura lungime minima a unei $1-expresii$ care il are ca rezultat pe $K$, deoarece este posibil ca acea $1-expresie$ sa se obtina folosind operatori de prioritate mica si, pentru a fi folosita in cadrul unor expresii mai mari, sa trebuiasca pusa intre paranteze.\r\n\r\nDe exemplu, $1-expresia$ de lungimea minima pentru $8$ este: $1+1+(1+1+1)!$. O alta scriere a lui $8$, care are lungimea cu $1$ mai mare este: $(1+1)^(1+1+1)$. Insa aceasta a doua reprezentare a lui $8$ poate fi folosita fara a fi inclusa intre paranteze, daca trebuie inmultita cu o alta expresie, in timp ce prima scriere trebuie inclusa intre paranteze.\r\n\r\nProgramarea dinamica este implementata destul de usor (pentru un numar $K$):\r\n\r\n* pentru $+$ : se incearca combinarea a doua expresii al caror rezultat este $X$, respectiv $K-X$\r\n* pentru $*$ : combinarea a doua expresii al caror rezultat este $X$, respectiv $K/X$\r\n* pentru $^$ : similar\r\n* pentru $!$ : numai in cazul in care $K$ este factorialul unui numar (pentru limitele date, factorialul maxim este $7!$ )\r\n\r\nSe calculeaza la inceput cele $4$ valori pentru fiecare numar de la $1$ la limita maxima, apoi pentru fiecare numar dat in fisierul de intrare, doar se afisaza rezultatul (daca s-ar recalcula valorile pentru fiecare numar, s-ar depasi limita de timp).\r\n\r\nh2. \'Cc\':problema/cc\r\n\r\nProblema cere determinarea unui cuplaj de cost minim, intr-un graf bipartit complet. Aceasta se poate realiza folosind un algoritm de flux maxim de cost minim sau, mai rapid, folosind algoritmul Ungar.\r\n\r\nh2. \'Joc3\':problema/joc3\r\n\r\nProblema este cunoscuta sub numele de \"staircase Nim\".\r\n\r\nh2. \'Geometry\':problema/geometry\r\n\r\nPentru fiecare pereche de segmente, se determina daca acestea se intersecteaza. Daca cele $2$ segmente nu sunt paralele, atunci se calculeaza punctul de intersectie al dreptelor suport al celor $2$ segmente si apoi se verifica daca punctul de intersectie se afla in interiorul ambelor segmente. Daca cele $2$ segmente sunt paralele, atunci se verifica daca se afla pe aceeasi dreapta (putem verifica usor acest lucru, calculand intersectia dreptelor suport cu axa $OX$ sau $OY$). Daca sunt pe aceeasi dreapta, se verifica daca exista un capat al unui segment care sa aiba atat coordonata $X$, cat si coordonata $Y$, situate intre coordonatele capetelor celuilalt segment (inclusiv capetele).\r\n\r\nh2. \'Itree\':problema/itree\r\n\r\nUn arbore este \"arbore de intervale\" (conform definitiei din enunt), numai daca orice nod are cel mult $2$ vecini al caror grad este mai mare decat $1$.\r\n\r\nh2. \'Hprob\':problema/hprob\r\n\r\nSe vor numerota cele $4!=24$ de permutari posibile ale celor $4$ obiecte cu numere de la $1$ la $24$. Se va calcula apoi o matrice $A$, unde fiecare element $A[i][j]$ reprezinta probabilitatea ca daca un client gaseste obiectele in starea $j$, acesta sa le puna la loc in ordinea corespunzatoare starii $i$. Vom considera ca, initial, obiectele se aflau in ordinea corespunzatoare starii $1$ si vom calcula probabilitatea ca la sfarsit acestea sa se afle tot in starea $1$. Vom privi matricea $A$ calculata ca o matrice de iteratie. Vom avea un vector $V{~i~}[j]$ reprezentand probabilitatea ca obiectele sa se afle in starea $j$ dupa $k$ iteratii. Putem calcula pe $V{~i~}$ ca fiind $A*V{~i-1~}$. In felul acesta, $V{~N~}=A^N^*V{~0~}$. $V{~0~}$ are valoarea $1$ pe pozitia $1$ si $0$ pe celelalte pozitii, iar $A^N^$ poate fi calculata eficient folosind exponentiere logaritmica.\r\n\r\nh2. \'Nodiv\':problema/nodiv\r\n\r\nh2. \'Arbore de cicluri\':problema/arbciclu\r\n\r\nVom realiza urmatoarea operatie in mod repetat, pana cand operatia nu mai poate fi aplicata: daca exista un nod $i$ avand gradul $2$, iar vecinii acestuia sunt $j$ si $k$, eliminam nodul $i$ din graf si introducem muchia $j-k$, daca aceasta muchie nu exista deja. Daca graful dat este un arbore de cicluri, atunci la final trebuie sa ramanem cu doar $2$ noduri (si, initial, numarul de noduri trebuie sa fi fost cel putin $3$). Pentru a aplica operatia descrisa in mod eficient, vom folosi o coada in care vom introduce nodurile cu gradul $2$. De fiecare data cand extragem din coada un nod $i$, exista posibilitatea sa modificam gradele vecinilor acestuia, $j$ si $k$; daca $j$ sau $k$ ajung sa aiba gradul $2$ in urma eliminarii lui $i$, ii introducem si pe ei in coada. Mai trebuie sa folosim o structura de date eficienta pentru a determina rapid daca $2$ noduri sunt adiacente, precum si pentru a elimina noduri din \"lista\" de adiacenta a altor noduri (in implementarea solutiei oficiale s-au folosit arbori echilibrati, prin intermediul structurii \"set\" din STL).\r\n\r\nh2. \'Gandaci Java\':problema/java\r\n\r\nProblema cere determinarea unui cuplaj maxim intr-un graf bipartit. Algoritmii \"standard\" pentru determinarea unui cuplaj maxim sunt prea lenti pentru limitele date, de aceea este necesara folosirea unei optimizari, cunoscuta ca algoritmul \'Hopcoft-Karp\':http://en.wikipedia.org/wiki/Hopcroft-Karp_algorithm (\'aici\':http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/123641 gasiti o implementare in Python a acestui algoritm).\r\n\r\nh2. \'Roy-Floyd\':problema/rf\r\n\r\nSe aplica algoritmul Roy-Floyd standard, la care se adauga un criteriu suplimentar: in cazul in care se gaseste un drum de distanta egala cu distanta minima curenta, dar avand un numar mai mare de strazi, se va alege drumul respectiv.\r\n\r\nh2. \'Biomech\':problema/biomech\r\n\r\nVom calcula matricea $A[lstart][dirstart][lfinish][dirfinish][P]$, reprezentand timpul minim pentru a ajunge de pe linia $lstart$, o coloana oarecare $X$ si privind in directia $dirstart$, pana pe linia $lfinish$, coloana $X + 2^P^$ (deci o coloana situata cu $2^P^$ pozitii mai in dreapta) si privind in directia $dirfinish$. Pentru $P = 0$, vom folosi un algoritm de drum minim. Va trebui sa avem grija ca solutia de timp minim pentru a trece de pe o coloana pe coloana imediat din dreapta ei poate presupune niste mutari \"in spate\", pe un numar limitat de coloane din stanga. Alegand o limita maxima de $9$ coloane in stanga si in dreapta, putem folosi algoritmul Dijkstra pe un graf ale carui stari constau din elementele unei submatrici de $5$ linii, $19$ coloane si au $8$ orientari. Pentru $P &gt; 0$, $A[lstart][dirstart][lfinish][dirfinish][P] = A[lstart][dirstart][lintermed][dirintermed][P-1] + A[lintermed][dirintermed][lfinish][dirfinish][P-1]$. Variem linia si orientarea intermediara si pastram minimul. In mod similar, vom calcula o matrice $B[lstart][dirstart][lfinish][dirfinish][P]$, unde indicele $P$ va reprezenta sosirea pe o coloana situata cu $2^P^$ coloane la stanga coloanei de start.\r\n\r\nCu aceste matrici calculate, vom determina numarul maxim de coloane pe care le poate parcurge robotul spre stanga si spre dreapta, in timpul dat, alegand maximul dintre cele $2$ variante. Voi prezenta in continuare doar cazul deplasarii spre dreapta, cel al deplasarii spre stanga fiind similar. Vom porni de la coloana $0$ si vom mari treptat numarul de coloane pe care le poate parcurge robotul (fie acest numar $C$). Pentru fiecare valoare a lui $C$ si fiecare stare posibila $(linie,orientare)$ vom mentine timpul minim in care se poate ajunge in stares respectiva. Initial, robotul poate ajunge in $0$ unitati de timp doar in starea initiala, in celelalte stari el neputand ajunge. Vom porni cu $P$ de la valoarea maxima pentru care am calculat valori (de exemplu, aceasta valoare poate fi $61$) si il vom decrementa treptat. Presupunand ca am ajuns pana la coloana $C$, vom incerca acum sa parcurgem inca $2^P^$ coloane. Folosind matricea $A$ si cunoscand timpul minim pentru a ajunge la coloana $C$ in fiecare stare posibila, vom calcula timpul minim corespunzator fiecarei stari pentru a ajunge la coloana $C+2^P^$. Daca cel putin o stare are acest moment de timp mai mic sau egal cu durata de timp maxim data, atunci marim valoarea lui $C$ cu $2^P^$ si vom considera momentele de timp actualizate pentru noua valoare a lui $C$. Daca pentru nici o stare nu se poate ajunge la coloana $C+2^P^$ in timp util, atunci lasam valoare lui $C$ nemodificata, nefacand nimic altceva (la urmatorul pas avand, insa, o valoare a lui $P$ cu $1$ mai mica). Valoarea finala a lui $C$ este numarul maxim de coloane ce poate fi parcurs spre dreapta in timpul dat.\r\n\r\nh2. \'Expresii min-max\':problema/emm\r\n\r\nExpresia data poate fi evaluata folosind o metoda de complexitate liniara ({$O(N)$}). Pentru simplificarea explicatiilor, vom considera ca intreaga expresie este incadrata intr-o pereche de paranteze. Se parcurge expresia de la stanga la dreapta si se va mentine o stiva cu operatorii neevaluati inca, cu rezultate partiale si cu paranteze deschise. Cand se inalneste un operator, acesta se adauga in stiva. Cand se intalneste un operand si in varful stivei este un operator, se efectueaza operatia respectiva (caci in stiva se va gasi si cel de-al doilea operand): adica se elimina din stiva operatorul si cel de-al doilea operand si se pune in varful stivei rezultatul operatiei. Cand se intalneste un operand si in stiva se afla o paranteza deschisa, operandul se pune in varful stivei. La intalnirea unei paranteze inchise vom evalua toate operatiile pana la prima paranteza deschisa din stiva. Apoi vom inlocui paranteza deschisa cu rezultatul evaluarii si, daca pe nivelul urmator din stiva se gaseste un operator, atunci efectuam operatia. La final, in varful stivei vom avea rezultatul expresiei.\r\n\r\nh2. \'Zeap\':problema/zeap\r\n\r\nh2. \'Noroc\':problema/noroc\r\n\r\nUn punct de pornire consta in calcularea unor vectori $p{~i~}[S]$, reprezentand probabilitatea ca dupa $i$ aruncari sa se obtina suma $S$. $S$ ia valori intre $0$ si $M$, iar $i$ trebuie sa ajunga la o valoare suficient de mare $IMAX$, pentru ca probabilitatea cautata sa nu isi mai modifice primele $7$ zecimale dupa $IMAX$ aruncari (adica sa convearga cu precizia dorita). $p{~i~}[S]$ se calculeaza pe baza lui $p{~i-1~}[S-1]$ si $p{~i-1~}[S+1]$, mai putin in cazurile limita $S=M$ si $S=0$, unde formula este usor diferita. Bieninteles, calculul acestor vectori nu se va incadra in limita de timp, dar, uitandu-ne la probabilitatile obtinute pentru diverse valori ale lui $X$ si $M$, vom observa (sau \"ghici\") ca rezultatul cerut de problema este $1-X/M$ (ne intereseaza doar cazul $X &le; M$).\r\n',1,'public',NULL,NULL),('blog/valorificarea-spiritului-competitiv','Valorificarea spiritului competitiv','2008-02-08 10:14:53','2008-11-15 13:41:14','!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/valorificarea-spiritului-competitiv?rhino_threadless.gif 50%!\r\nImi place mult \'threadless.com\':http://threadless.com . E un site unde concureaza diverse designuri de tricouri (poza din stanga luata de pe threadless.com e un exemplu al unui astfel de design). Daca un design primeste un scor bun atunci autorul ia 2000$ si cei de la threadless incep sa vanda tricouri cu designul respectiv. In 2006, creatorii siteului au castigat in jur de 6 milioane de dolari, deci pe langa ca e o idee misto are si sens pe partea financiara. O parte importanta a succesului vine din implicarea afectiva a vizitatorilor. Designurile ce ies castigatoare au fiecare ceva deosebit si nu se produc in masa iar asta ataseaza cumparatorul de tricoul cumparat. Lumea se implica, comenteaza pe forumuri, voteaza, blogheaza si isi fac poze cu tricourile respective.\r\n\r\nAlt site de succes ce se bazeaza pe concursuri este topcoder.com. Dar nu ma refer la concursurile de algoritmica, care au fost gandite ca o metoda de a aduce oameni buni pe site si apoi sa fie recrutati pentru joburi. M-am gandit la concursurile de componente, unde diversi programatori concureaza pentru realiza o componenta software. Succesul siteului e datorat pe de o parte faptului ca programatorii ce concureaza sunt din tari unde salariile de programatori sunt mici. Dincolo de acest aspect, procesul folosit de topcoder pentru crearea unei componente este foarte bine pus la punct si elementul de competitie intre programatori face ca rezultatul final sa fie destul de bun. Probabil este mai bun decat ceva scos de o firma care face outsourcing, dar nu pot sa imi dau cu pararea pentru ca nu am lucrat in Romania la niciuna.\r\n\r\nConcursul organizat de \'Netflix\':http://netflix.com e alt exemplu. Netflix e un serviciu care trimite DVD-uri cu filme in posta. Ei au lucrat la un sistem de recomandari personalizate de filme, pe baza filmelor vazute de clienti. Au transformat problema interna de imbunatatire a algoritmul cu 10% in una deschisa publicului larg cu un premiu de un milion de dolari. La prima vedere premiul de un milion de dolari pare unul foarte mare, dar el reprezinta doar salarul a 10 programatori in state timp de un an. Alta problema este ca nu se stia daca pragul de 10% este usor sau nu de trecut. Ideea de a organiza un concurs pentru a rezolva problema a fost foarte buna, pentru ca multi cercetatori au muncit intens la ea si cei de la Netflix platesc premiul doar daca cineva obtine rezultatul cerut. Deocamdata nimeni nu a reusit sa atinga pragul fixat.\r\n\r\nFaptul ca concurenta aduce dupa ea calitate este clar, dar mi s-au parut interesante abordarile acestiu principiu pe cateva siteuri ce imi plac.\r\n\r\nMai multe despre cei de la threadless puteti vedea in prezentarea lor presarata de glume si idei misto de \'aici\':http://video.google.com/videoplay?docid=6790186192162586479',1490,'protected',2671,NULL),('cosmin/schita4','cosmin/schita4','2007-10-19 11:27:35','2007-10-19 11:27:35','comic strips\r\n\r\nfredo si pid\'jin http://www.pidjin.net/2007/07/31/green-for-the-green/\r\n\r\nhttp://www.phdcomics.com/comics.php\r\n\r\nhttp://xkcd.com/329/\r\n\r\nhttp://www.penny-arcade.com/comic/2007/09/19',58,'public',NULL,NULL),('blog/interviu-mihai-patrascu','Interviu cu Mihai Patrascu','2007-10-19 19:57:33','2007-10-19 19:58:39','\'Cosmin\':utilizator/cosmin a publicat un interviu cu \'*Mihai Patrascu*\':utilizator/mpatrascu pe blog-ul infoarena.\r\n\r\n_Mihai Patrascu are printre cele mai bune rezultate la olimpiadele internationale la informatica dintre romani. A luat premiul I la Olimpiada nationala de informatica din clasa a 4a (concurand la clasa a 5a) pana intr-a 12a. La olimpiada internationala la de informatica a luat doua medalii de aur si una de argint (in 2001 a fost locul doi la internationala)._\r\n\r\n&hellip;\r\n\r\n_In 2005 a luat premiul_ \'Outstanding Male Undergraduate Award\':http://www.cra.org/Activities/awards/undergrad/2005.patrascu.html _(big)pe Statele Unite si Canada._\r\n\r\nCiteste interviul acum:\r\n\r\n* \'Partea 1\':blog/interviu-mihai-patrascu-partea-intai\r\n* \'Partea a 2-a\':blog/interviu-mihai-patrascu-partea-a-doua\r\n',13,'protected',NULL,NULL),('blog/se-apropie-acmul','Se apropie ACMul','2007-10-21 07:51:52','2008-11-15 13:41:14','!>blog/se-apropie-acmul?logo_ICPC.png! Pe 25-28 Octombrie se va desfasura la Universitatea Politehnica din Bucuresti \'faza pe sud estul Europei\':http://acm.ro a concursului ICPC organizat de ACM. Acest concurs este unul in care echipe de trei studenti, fiecare echipa lucrand pe un singur calculator, se infrunta pe parcursul a cinci ore sa rezolve cat mai repede intre sapte si noua probleme.\r\n\r\nSolutia unei probleme se ruleaza pe o suita de teste si este considerata corecta doar daca obtine rezultate corecte pentru toate testele. !<blog/se-apropie-acmul?acm-icpc.jpg! Daca au rezolvat corect o problema, echipa primeste um balon cu culoarea corespunzatoare problemei, daca nu se primesc niste mesaje ca \'Raspuns Gresit\', \'Timp de executie expriat\', \'Limita de memorie depasita\' etc Astfel este usor de a vedea clasamentul sau cea mai simpla problema pe care echipa ta nu a rezolvat-o inca, daca te uiti prin sala la baloanele celorlaltor echipe. Punctajul este alcatuit din suma timpilor trecuti de la inceputul concursului pana la rezolvarea corecta fiecarei probleme, la care se adauga cate 20 de minute penalizare pentru incercarile esuate de a trece testele. Aceasta modalitate de acordare a punctajelor face ca strategia cea mai buna sa fie rezolvarea problemelor simple la inceput. De obicei problemele sunt calibrate cam o treime simple, o treime medii si o treime mai grele, si se urmareste ca fiecare problema sa fie rezolvata de cel putin o echipa, dar sa nu fie o echipa care sa rezolve toate problemele. \r\n\r\nVor mai urma saptamana aceasta cateva posturi legate de \'ACM ICPC\':http://icpc.baylor.edu in curand.\r\n\r\n',1490,'protected',2220,NULL),('blog/de-ce-sa-participi-la-acm-icpc','De ce sa participi la ACM ICPC','2007-10-22 18:18:40','2008-11-15 13:41:14','!>blog/se-apropie-acmul?logo_ICPC.png! Am incercat sa gasesc cateva motive pentru un student la informatica, care nu a avut contact cu olimpiadele in liceu, sa participe la concursurile ACM in timpul facultatii. Ce ar fi folositor pentru el in dorinta de a deveni un programator mai bun? Am ajuns la urmatoarea lista:\r\n\r\n* ca sa mai scrii o linie in CV\r\n* ca sa iti dai seama ca programezi foarte incet\r\n* ca sa vezi ce greu e sa lucrezi in echipa in conditii extreme\r\n* ca sa programezi ceva interesant\r\n* ca sa intelegi algoritmica si structurile de date la un nivel ce trece de superficialitate\r\n* ca sa cunosti alti oameni cu pasiune mare pentru programare\r\n* ca sa ti se para banale intrebarile de coding de la interviurile microsoft sau google\r\n* ca sa inveti chestii mai importante decat ultima tehnologie la moda, cum ar fi identificarea rapida a bugurilor, claritatea codului, proiectarea programului inainte de implementare sau metode de optimizare a timpului si memoriei\r\n* ca sa rezolvi o problema complet a carei solutie merge pe toate cazurile\r\n* ca sa inveti ca nu orice problema se rezolva cu \"metoda backtracking\"\r\n* ca sa poti scrie un post pe blog\r\n\r\nCe motive aveti voi pentru a participa sau pentru a nu participa la acest concurs?\r\n\r\n',1490,'protected',2224,NULL),('blog/ted-talks','TED - talks','2007-10-23 21:09:24','2008-11-16 12:56:03','TED sunt niste conferinte tinute anual cu o serie de discursuri tinute de diversi oameni destepti despre domeniul lor, care sunt deschizatoare de ochi. In 2006 mi-a placut mult talkul despre economie a lui Hans Rosling. El avea o firma cu un produs ce facea niste grafice interactive, animate pe axa timpului. Dupa ce l-a vazut in actiune, Google i-a cumparat firma :). Anul acesta, Hans a mai avut un talk care a fost la fel de interesant, cu un final neasteptat. Fiecare talk are 20 de minute, daca nu faceti ceva important acum, urmariti-le ca merita:\r\n\r\n==Youtubevideo(id=\"hVimVzgtD6w\" width=\"425\" height=\"350\")==\r\n\r\nMyths About the Developing World (2006)\r\n\r\n==Youtubevideo(id=\"YpKbO6O3O3M\" width=\"425\" height=\"350\")==\r\n\r\nWatch the end of poverty (2007)\r\n\r\n',1851,'protected',2226,NULL),('happy-coding-2007/clasament','Clasament Happy Coding 2007','2007-11-10 09:32:42','2007-11-22 21:41:20','h1. Happy Coding 2007     !happy-coding-2007?hc2007-logo.gif!\r\n\r\n(htabs)* \'Despre Happy Coding\':happy-coding-2007\r\n* \'Probleme\':happy-coding-2007/probleme\r\n*(active) \'Clasament\':happy-coding-2007/clasament\r\n\r\n== Rankings(rounds=\"happy-2007\") == \r\n\r\n\r\n\'*&rarr; Monitor de evaluare pentru Happy Coding*\':monitor?round=happy-2007\r\n',2028,'protected',NULL,NULL),('planificare/sedinta-20071024','Sedinta 2007-10-24','2007-10-14 21:35:49','2007-10-25 07:50:32','h1. Sedinta 2007-10-24\r\n\r\n_ora 17:30, locatie: La Cafenescu_\r\n\r\nh2. Participanti\r\n\r\n* Cristian George Strat\r\n* Mircea Pasoi\r\n* Silviu Ganceanu\r\n* Andrei Grigorean\r\n* Adrian Diaconu\r\n* Valentin Stanciu\r\n* Crestez Leonard\r\n\r\nh2. Agenda\r\n\r\n* preONI 2008\r\n* own-a-feature\r\n* development\r\n** better blog commenting features\r\n** infoarena 3.0\r\n** Winter Camp\r\n* gestiune bani\r\n* planificare sedinte viitoare\r\n* schimbari in echipa infoarena\r\n\r\nh2. Rezolutii\r\n\r\n* *Schimbari in echipa infoarena*\r\n** Airinei Adrian devine consilier\r\n** Andrei Grigorean devine consilier\r\n** Cosmin Negruseri devine consilier (din consilier emeritus)\r\n** Adrian Vladu devine consilier emeritus (din consilier)\r\n* preONI 2008\r\n** *Mircea a fost votat contest director (7 pentru; 4 absenti)*\r\n** Mircea face pagina de proiect: planificare/preoni-2008\r\n** Cristi face rost de fonduri\r\n** 4 runde + finala\r\n** incepem in noiembrie (cam pe 20)\r\n** finala inainte de ONI (martie?)\r\n** *nu se dau bani pentru propunatori si organizatori preONI* (7 pentru; 4 absenti)\r\n* roluri\r\n** _se scriu in pagina de echipa_\r\n** development\r\n** blog: Cosmin\r\n** forum (include calendar): wefgef\r\n** implica-te (proiecte noi in comunitate): vali\r\n** articole: *ne trebuie sef, Mircea se retrage*\r\n** extinde arhiva & imbunateste teste: adi\r\n** financiar (contabilitate): fluf\r\n** fundraising: Silviu\r\n** newsletter: Cristi\r\n** concursuri obisnuite: wefgef (supervizat de Mircea)\r\n** community: Cristi\r\n** documentatie\r\n** link-uri\r\n** downloads\r\n* development\r\n** Cristi implementeaza blog commenting features\r\n** Fluf si Mircea scriu design infoarena 3.0 si il vor prezenta la urmatoare sedinta\r\n* Adrese de e-mail @infoarena.ro:\r\n** mircea\r\n** andrei.grigorean\r\n** adrian.diaconu\r\n** cdleonard\r\n** silviu\r\n** valentin\r\n** _ceilalti membri?_\r\n',15,'public',NULL,NULL),('planificare/sedinta-20071027','Sedinta 2007-10-27','2007-10-27 14:38:54','2007-10-27 14:53:58','h1. Sedinta 2007-10-27\r\n\r\n_ora 16:00, locatie: Pizza Maxx_\r\n\r\nh2. Participanti\r\n\r\n* Cristian George Strat\r\n* Mircea Pasoi\r\n* Silviu Ganceanu\r\n* Andrei Grigorean\r\n* Adrian Diaconu\r\n* Airinei Adrian\r\n* Valentin Stanciu\r\n* Daniel Pasaila\r\n\r\nh2. Agenda\r\n\r\n* roluri\r\n\r\nh2. Rezolutii\r\n\r\n* Roluri\r\n** Adrian Airinei pentru rolul de contest director; supervizat de Mircea\r\n** Silviu se baga sef pe articole cu ajutor de la Catalin Tiseanu\r\n** Daniel Pasaila se baga la arhiva de probleme, alaturi de Adi\r\n',13,'public',NULL,NULL),('blog/putina-istorie-acm-icpc-seerc','Putina istorie ACM ICPC SEERC','2007-10-28 23:41:30','2008-11-15 13:41:14','!>blog/se-apropie-acmul?logo_ICPC.png! Alt titlu la care m-am gandit pentru acest post este \"In cate moduri poti sa propui niste probleme busite\".\r\nIn fiecare an sunt probleme cu problemele de la regionala ACM la care participa studentii romani, iar anul asta s-a vazut mai clar din rezultate si nu din studierea testelor. Va ziceam intr-un post anterior ca un set de probleme bune este unul in care fiecare problema e rezolvata de cel putin o echipa, dar nici o echipa nu rezolva toate problemele. Anul asta sapte echipe au rezolvat toate problemele, una reusind sa le rezolve in doua ore si patru minute, cand timpul total al concursului e de cinci ore.\r\n\r\nPutina istorie a problemelor bushite de-a lungul timpului:\r\n\r\n_In 2002 problema Sly Number implica rezolvarea unui sistem de ecuatii liniare modulare. Un concurent a testat cu backtracking testele comisiei si nici unul nu ii dadea rezultatul asteptat. In timpul concursului, o echipa a rezolvat problema respectiva, facand probabil aceiasi greseala ca si solutia comisiei._\r\n\r\n_In 2004 la problema City Game, se cerea determinarea dreptunghiului de arie maxima ce contine doar caracterul F pe o matrice ce contine caractere de F si R. Intre teste era unul care specifica o matrice de 100 de randuri si 100 de coloane, dar avea doar 98 de randuri. Daca aveai norocul ca partea de citire din program sa fie implementata ca si cea a comisieri, puteai rezolva problema ... Multe echipe s-au blocat in problema asta clasica, incercand sa isi gaseasca bugul de implementare care era de fapt in testele comisiei. De asemenea in acelasi an s-a propus problema Alibaba despre care am dubii mari ca ar exista vreo solutie de complexitate mai buna decat_ <tex>O(n^2)</tex> _desi limita de timp din concurs facea ca o asemenea solutie sa obtina mesajul Time Limit Exceeded. Testele la Alibaba sunt foarte misto, cateva teste mici ce merg cu programare dinamica in_ <tex>O(n^2)</tex> _si doua teste mari la care merge lejer greedy._\r\n\r\n_In 2005 s-a propus rezolvarea unui puzzle Sudoku, dar toate testele puteau fi rezolvate punand o cifra in locuri fortate, pentru nici un test nu trebuia facut backtracking. Astfel echipele care fac solutia buna au un dezavantaj fata de echipele care nu isi dau seama ca exista cazuri pe care solutia lor nu merge. Problema Adventurous Driving avea ca limita in enunt n <= 100 iar in teste era un n = 1000. Autorul problemei era mandru de ea, pentru ca doar o echipa a rezolvat-o in timpul concursului._\r\n\r\n_In 2006 problema Shortest Pair of Paths cerea determinarea a doua drumuri minime disjuncte de la sursa la destinatie. Problema este clasica si se rezolva cu flux maxim de cost minim, dar testele au facut ca o solutie ce gaseste de doua ori un drum folosind algoritmul lui Dijkstra sa mearga. Din nou echipele care au stiut ca problema e mai complicata au pierdut timp implementand solutia mai grea. Alta problema bushita a fost Sherloc Holmes care era un knapsack 2d, dar nu prea incapea in memorie pentru ca n si m erau 10000. Dupa concurs s-a vazut ca testele contineau n si m-ul maxim 300._\r\n\r\nAcestea nu sunt singurele exemple.\r\n\r\nSa organizezi un concurs cu multe probleme, la un nivel inalt este foarte greu. Putine regionale reusesc asta. Printre ele sunt ECNA, o regionala din Canada, NEERC, una din Rusia, CEPC, regionala Europei Centrale. Acestea au probleme de calitate, de dificultate mare, cu explicatii de solutii scrise, cu o echipa de organizatori care contin studenti care au fost concurenti. Nu e de mirare ca aceste regionale au aproape in fiecare an o echipa in primele cinci din lume.\r\n\r\nSi la \'TopCoder\':http://topcoder.com/tc se intampla ca un concurs sa fie bushit, desi ei isi bazeaza afacerea lor pe asta. Dar pentru a evita greselile, care, avand in vedere ca organizeaza mai mult de un concurs pe saptamana, ar fi normal sa se intample, acestia au o metodologie foarte bine pusa la punct. Fiecare problema este rezolvata de inca trei oameni, altii decat autorul, care isi dau cu parerea atat asupra problemei cat si asupra testelor alese. Un al patrulea om are grija ca textul sa nu aiba ambiguitati. Autorul trebuie sa faca enuntul, testele si un validator pentru teste.\r\n\r\nConcursul ACM este un eveniment important care se desfasoara o data pe an, si el ar trebui organizat cu grija, astfel incat concurentii sa nu plece cu impresia ca au fost luati in bataie de joc. Ce trebuie facut pentru corectarea problemelor din trecut ar fi intinerirea comisiei stiintifice, scrierea unui validator de teste, si implementarea a mai multor solutii pentru fiecare problema. Nu pare foarte greu, dar se pare ca nu se invata nimic din esecurile anterioare.\r\n\r\nPuteti citi si postul lui Florin Manea, antrenor al echipelor universitatii Bucuresti, despre regionala ACM \'aici\':http://flmanea.blogspot.com/2007/10/icpc-acm-2007-final.html\r\n\r\n',1490,'protected',2238,NULL),('documentatie/sidebar','documentatie/sidebar','2007-10-29 20:18:13','2009-03-20 22:24:30','(vmenu){width:190px}* *Documentatie*\r\n** {\'Wiki\':documentatie/wiki}\r\n** {\'Sintaxa Textile\':documentatie/textile}\r\n** {\'Macro-uri\':documentatie/macro-uri}\r\n** {\'Conventii de formatare\':documentatie/conventii-de-formatare}\r\n* *Pentru utilizatori*\r\n** {\'Tutorial\':documentatie/tutorial}\r\n** {\'Tutorial articole\':documentatie/tutorial-articole}\r\n** {\'Concursuri virtuale\':documentatie/concursuri-virtuale}\r\n** {\'Evaluatorul\':documentatie/evaluator}\r\n** {\'Trimiterea solutiilor\':documentatie/trimiterea-solutiilor}\r\n** {\'Monitorul\':documentatie/monitorul-de-evaluare}\r\n** {\'Borderouri\':documentatie/borderoul-de-evaluare}\r\n** {\'Profil\':documentatie/pagina-de-profil}\r\n** {\'Rating\':documentatie/rating}\r\n* *Pentru propunatori*\r\n** {\'Editare de probleme\':documentatie/editare-de-probleme}\r\n** {\'Ghid evaluator\':documentatie/ghid-evaluator}\r\n** {\'Arhiva educationala\':documentatie/arhiva-educationala}\r\n** {\'Gruparea testelor\':documentatie/grupare-teste}\r\n* {\'Pentru administratori\':documentatie/administrare}',1,'public',NULL,NULL),('documentatie/textile','Formatare Textile','2006-11-11 17:44:32','2009-02-05 08:07:30','h1. Tutorial de Textile\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nh2. Introducere\r\n\r\n_Textile_ este un limbaj de markup ce va ajuta sa editati paginile web. Ce inseamna aceasta? In loc sa scrieti tag-urile specifice de html pentru a edita o astfel de pagina, _Textile_ va pune la dispozitie o serie de elemente de sintaxa prin care puteti edita mai simplu si mult mai rapid aceste pagini. In continuare sunt prezentate notiunile care trebuiesc cunoscute inainte de a incepe scrierea unei pagini html folosind _Textile_. \r\n\r\nh2. Paragrafe\r\n\r\nUn text este structurat pe mai multe paragrafe. Atunci cand folositi Textile, paragrafele trebuiesc separate de o linie alba ( goala ).\r\n\r\ntable(example). |_. Cod _Textile_|_. Cod HTML asociat|\r\n|Un paragraf&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;\r\nAl doilea paragraf\r\n|@<p>Un paragraf</p>@&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;\r\n@<p>Al doilea paragraf</p>@|\r\n\r\n\r\nUn intreg paragraf se poate transforma cu usurinta intr-un header, folosind sintaxa {$hn$} la inceputul paragrafului, unde {$n$} este un numar de la $1$ la $6$. De exemplu, Textile va interpreta linia @h1. Primul header@ ca @<h1>Primul header</h1>@ si rezultatul va fi: \r\n\r\nh1. Primul header\r\n\r\nh2. Modificatori\r\n\r\nPentru a scrie un text cu diferite efecte ( ingrosat, inclinat, subliniat, taiat ) sau in diferite pozitii ( puteri sau indici ) se scrie textul care se doreste a fi modificat intre modificatorii corespunzatori. In tabelul de mai jos este prezentat modul de folosire al acestora:\r\n\r\ntable(example). |_. Cod _Textile_|_. Cod HTML asociat|\r\n|@**Un text ingrosat**@|@<b>Un text ingrosat</b>@|\r\n|@_Aici apare inclinat_@|@<i>Un text inclinat</i>@|\r\n|@+Merge chiar si subliniat+@|@<ins>Merge chiar si subliniat</ins>@|\r\n|@-Text gresit-@|@<del>Text gresit</del>@|\r\n|@Pitagora: a ^2^ + b ^2^ = c ^2^@|@Pitagora: a <sup>2</sup> + b <sup>2</sup> = c <sup>2</sup>@|\r\n|@Chiar si logaritmi: log ~2~ N@|@Chiar si logaritmi: log <sub>2</sub> N@|\r\n\r\nIn cazul in care rezultatele produse de limbajul de markup nu sunt cele asteptate, se poate forta folosirea acestor modificatori prin caracterele { si } puse la inceputul si respectiv la sfarsitul secventei. De exemplu, @{**Text fortat**}@ are ca rezultat {**Text fortat**}.\r\n\r\nPrintre aceste caractere speciale exista si @; care opreste formatarile speciale intr-o secvente. Exemplu: &#64;&#42;capsuna&#42;&#64; are ca rezultat &#42;capsuna&#42;. Daca asta nu functioneaza in pasajul tai poti sa folosesti direct \'entitati html\':http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references. Poti sa scrii &amp;#42;elefanti&amp;#42; pentru a obtine &#42;elefanti&#42;\r\n\r\nh2. Liste\r\n\r\nPentru a crea o lista numerica cu Textile, este suficient sa inseram # inainte de fiecare paragraf:\r\n\r\n@# Primul item@\r\n@# Al doilea item@\r\n@# Al treilea item@\r\n\r\nva genera:\r\n\r\n# Primul item\r\n# Al doilea item\r\n# Al treilea item\r\n\r\nDe asemenea este posibil ca listele sa fie imbricate, incrementand numarul de caractere #. Listele vor avea o structura arborescenta:\r\n\r\n@# Un item@\r\n@## Alt item@\r\n@# Al doilea item@\r\n\r\nva avea ca rezultat:\r\n\r\n# Un item\r\n## Alt item\r\n# Al doilea item\r\n\r\nDaca in locul listelor indexate numeric se doreste creerea listelor cu bulete ( _bulleted lists_ ), in loc de # se va folosi *. Regula pentru liste imbricate ramane valabila si aici:\r\n\r\n@* Capitolul 1@\r\n@** Capitolul 1.1@\r\n@* Capitolul 2@\r\n\r\nproduce urmatorul efect:\r\n\r\n* Capitolul 1\r\n** Capitolul 1.1\r\n* Capitolul 2\r\n\r\nh2. Referinte externe\r\n\r\nPentru a crea o referinta catre un alt site ( un _link_ ), textul descriptiv va fi plasat intre ghilimele duble (\"), urmat imediat de caracterul : si de URLul dorit: @Link catre \"infoarena\":http://infoarena.ro@ va fi interpretat ca Link catre \"infoarena\":http://infoarena.ro. Daca un link este folosit de mai multe ori in acelasi document sau daca se doreste o mai buna organizare a textului, este posibil ca URLul sa fie specificat oriunde in document: intre paranteze patrate se va afla identificatorul unic asociat linkului, dupa care urmeaza adresa propriu-zisa. In momentul in care dorim sa inseram in document acel link este suficient in loc de adresa completa sa introducem doar identificatorul pe care l-am asociat adresei:\r\n\r\n@Link catre \"infoarena\":arena@\r\n@Al doilea link catre \"infoarena\":arena@\r\n\r\n@[arena]http://infoarena.ro@\r\n\r\nare rezultatul:\r\n\r\nLink catre \"infoarena\":arena\r\nAl doilea link catre \"infoarena\":arena\r\n\r\n[arena]http://infoarena.ro\r\n\r\nPentru a posta o imagine pe site, este necesar in prealabil sa o salvati pe server. Pentru aceasta este suficient sa apasati butonul \"Ataseaza\" din coltul dreapta-sus al paginii pe care o editati si sa selectati imaginea pe care doriti sa o transferati pe server. Dupa aceea, pentru a introduce imaginea in pagina va trebui sa introduceti URLul ei intre semnul exclamarii (!).\r\n\r\nDaca am incarcat deja imaginea logo.jpg in pagina curenta,\r\n@!documentatie/textile?logo.jpg!@ va avea rezultatul:\r\n\r\n!documentatie/textile?logo.jpg!\r\n\r\nh2. Tabele\r\n\r\nTabelele simple pot fi construite separand campurile lor prin caracterul |.\r\n\r\n@| nume | varsta | judet |@\r\n@| Popescu | 24 | Bucuresti |@\r\n@| Ionescu | 12 | Constanta |@\r\n\r\nva genera tabelul de mai jos:\r\n\r\n| nume | varsta | judet |\r\n| Popescu | 24 | Bucuresti |\r\n| Ionescu | 12 | Constanta |\r\n\r\nCelulele care doresc sa fie facute cap de tabel vor fi marcate initial printr-un underscore, urmat imediat de un punct.\r\n\r\n@|_. nume |_. varsta |_. judet |@\r\n@| Popescu | 24 | Bucuresti |@\r\n@| Ionescu | 12 | Constanta |@\r\n\r\nva avea urmatorul rezultat:\r\n\r\n|_. nume |_. varsta |_. judet |\r\n| Popescu | 24 | Bucuresti |\r\n| Ionescu | 12 | Constanta |\r\n\r\nh1. Cod <tex>\\LaTeX</tex>\r\n\r\nAtunci cand dorim sa introducem cod \'LaTeX\':http://en.wikipedia.org/wiki/LaTeX putem folosi sintaxa:\r\n$&lt;tex> cod LaTeX </tex&gt;$\r\n\r\nDe exemplu pentru codul:\r\n\r\n$&lt;tex> d = \\sqrt{(c_{2}-c_{1})^{2} + 1 } </tex&gt;$\r\n\r\nse obtine urmatoarea imagine:\r\n\r\n<tex> d = \\sqrt{(c_{2}-c_{1})^{2} + 1 } </tex> \r\n\r\nh2. Fragmente de cod\r\n\r\nAtunci cand dorim sa inseram un fragment de cod in pagina curenta, putem sa folosim sintaxa:\r\n\r\n@== code(c) |@\r\n@...fragment de cod...@\r\n{@==@}\r\n\r\nUrmatoarele limbaje sunt suportate:\r\n\r\n* $code{@(c)@}$ pentru C\r\n* $code(cpp)$ pentru C++\r\n* $code(pas)$ pentru Object Pascal\r\n* $code(java)$ pentru Java\r\n\r\nIata un exemplu:\r\n\r\n== code(c) |\r\n#include <stdio.h>\r\n\r\nint main(void) {\r\n    int a, b;\r\n\r\n    freopen(\"adunare.in\", \"rt\", stdin);\r\n    freopen(\"adunare.out\", \"rt\", stdout);\r\n\r\n    scanf(\"%d%d\", &a, &b);\r\n    printf(\"%d\\n\", a+b);\r\n\r\n    return 0;\r\n}\r\n==\r\n\r\nh2. Aplicarea stilurilor CSS\r\n\r\nEste posibil sa atasam cod CSS elementelor in felul urmator:\r\n\r\ntable(example). |_. Cod _Textile_|_. Cod HTML asociat|_. Rezultat |\r\n|@text %{color:red}bau!% text@|@text <span style=\"color:red\">bau!</span> text@|text %{color:red;}bau!% text|',6720,'public',NULL,NULL),('planificare/raspandeste-vestea','Raspandeste Vestea','2007-02-16 18:04:26','2007-10-29 20:53:10','h1. Raspandeste Vestea\r\n\r\n==include(page=\"planificare/sidebar\")==\r\n\r\n\'Idee de campanie folosita de Firefox\':http://mozilla.wikia.com/wiki/Firefox_Flyers, simpla si usor de pus in aplicare.\r\n\r\nFacem cateva machete de fluturase/afise/pliante despre info-arena si le publicam *in varianta electronica*. Apoi, incercam sa convingem cat mai multi utilizatori (profesori, elevi, studenti etc.) sa le print-eze si sa le distribuie pe cont propriu. Voila!\r\n\r\nVedeti exemplele cu Firefox de la link-ul de mai sus.\r\n\r\nh2. Comentarii\r\n\r\n* read more here: ==smflink(link=\"topic\" topic=\"1723.0\" caption=\"forum\")==\r\n* continuati...\r\n',1,'public',NULL,NULL),('documentatie/pentru-utilizatori','Ghidul utilizatorului','2006-12-11 02:14:57','2008-12-03 21:56:20','h1. Ghidul utilizatorului\r\n\r\nNe bucuram ca ai ajuns pe infoarena! Pe site-ul nostru vei gasi o comunitate entuziasta si o colectie interesanta de materiale educationale care te vor ajuta sa inveti informatica. Ramai cu noi!\r\n\r\nAcesta este un ghid scurt menit sa-ti explice cum te poti pregati pe infoarena. Iti recomandam sa incepi cu {\'tutorialul infoarena\':documentatie/tutorial} daca vrei sa rezolvi probleme sau vrei sa afli despre resursele educationale infoarena (forum, articole, download-uri).\r\n\r\nDaca ai o intrebare viziteaza-ne pe \'forum\':forum. Nu uita sa-ti completezi \'profilul\':documentatie/pagina-de-profil pentru a te integra cat mai bine in comunitatea infoarena. \r\n\r\nPentru informatii specifice despre o anumita functionalitate a site-ului urmareste una din legaturile de mai jos.\r\n\r\n* {\'Monitorul de evaluare\':documentatie/monitorul-de-evaluare}: Ce este si cum se foloseste monitorul de evaluare.\r\n* {\'Borderoul de evaluare\':documentatie/borderoul-de-evaluare}: Cum se interpreteaza borderoul de evaluare.\r\n* {\'Evaluatorul infoarena\':documentatie/evaluator}: Ce configuratie si ce compilatoare foloseste infoarena.\r\n* {\'Trimiterea solutiilor\':documentatie/trimiterea-solutiilor}: Cum se trimit solutii pe infoarena.\r\n* {\'Pagina de profil\':documentatie/pagina-de-profil}: Cum poti sa-ti editeazi profilul pe infoarena.\r\n* {\'Rating\':documentatie/rating}: Ce este si cum functioneaza sistemul de rating\r\n\r\n',15,'public',NULL,NULL),('documentatie/monitorul-de-evaluare','Monitorul de evaluare','2006-11-27 05:07:30','2008-06-04 23:25:26','h1. Monitorul de evaluare\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nCiteste despre \'evaluatorul infoarena\':documentatie/evaluator.\r\n\r\nh2. Ce este monitorul de evaluare?\r\n\r\nMonitorul de evaluare este o pagina in care poti sa vezi sursele trimise pe infoarena si punctajele obtinute de acestea, ordonate cronologic, prima sursa fiind ultima sursa trimisa. Poti sa dai click pe fiecare sursa si sa vezi \'borderoul\':documentatie/borderoul-de-evaluare. In borderou vezi modul in care s-a comportat o sursa pe fiecare test de la problema respectiva.\r\n\r\nh2. Filtrare\r\n\r\nDaca doresti sa vezi doar anumite rezultate in monitor poti folosi filtrele prezentate mai jos, adaugand la adresa monitor-ului caracterul $?$, urmat de o lista de filtre $filtru=valoare$, separate prin $&$. Se pot folosi urmatoarele filtre:\r\n\r\n* $user$ - filtreaza dupa contul utilizatorului\r\n* $task$ - filtreaza dupa problema\r\n* $round$ - filtreaza dupa o runda de concurs (poti folosi $arhiva$ pentru \'Arhiva de probleme\':arhiva)\r\n* $job_id$ - vezi doar job-ul cu acest numar\r\n* $job_begin$ - vezi doar job-urile cu numere mai mari sau egale cu numarul dat\r\n* $job_end$ - vezi doar job-urile cu numere mai mici sau egale cu numarul dat\r\n* $time_begin$ - vezi doar job-urile care au data si timpul mai mare sau egala cu timpul dat (nu exista un format anume la data poti folosi chiar $yesterday$ sau $-1 week$)\r\n* $time_end$ - analog $time_begin$\r\n* $compiler$ - filtreaza dupa compilator ({$cpp$}, $c$ sau $fpc$)\r\n* $status$ - filtreaza dupa status-ul job-urilor ({$waiting$}, $processing$ sau $done$)\r\n* $score_begin$ - vezi doar job-urile care au scorul mai mare sau egal cu numarul dat\r\n* $score_end$ - vezi doar job-urile care au scorul mai mic sau egal cu numarul dat\r\n* $eval_msg$ - vezi doar job-urile care au la inceputul mesajului de evaluare string-ul dat\r\n\r\nDe exemplu, daca vrei sa vezi doar job-urile de ieri pana in prezent trimise la problema adunare in C++ poti accesa \'$http://infoarena.ro/monitor?task=adunare&time_begin=yesterday&compiler=cpp$\':monitor?task=adunare&time_begin=yesterday&compiler=cpp.\r\n\r\nFunctionalitatea de filtrare a fost construita in principal pentru adminitratori. Daca ai drepturi suficiente iti va aparea un buton de \"re-evaluare\", cu care poti sa reevaluezi doar anumite surse. *Atentie!* Re-evaluarea surselor poate lua foarte mult timp.',13,'public',NULL,NULL),('documentatie/ghid-evaluator','Ghid Evaluator','2007-04-27 09:02:13','2007-10-30 00:35:23','h1. Ghid Evaluator\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nh2. Ce este un evaluator?\r\n\r\nPentru problemele in care raspunsul nu este unic, site-ul *infoarena* a fost conceput sa foloseasca un program extern pentru verificarea raspunsului. Acest program se numeste _evaluator_, si poate fi scris in $C, C++$ sau $Pascal$. \r\n\r\nh2. Cum se face un evaluator?\r\n\r\nPentru a realiza un evaluator compatibil cu design-ul infoarena trebuie respectate urmatoarele reguli:\r\n\r\n* In functie de numele introdus in setarile problemei pentru evaluator, fisierul care va fi atasat la pagina problemei trebuie prefixat cu cuvantul $grader_$ (spre exemplu daca s-a introdus in setarile problemei $eval.cpp$ fisierul care trebuie atasat se va numi $grader_eval.cpp$)\r\n* Daca numele problemei este $prob$ fisierul de intrare care se evalueaza se numeste $prob.in$, fisierul de iesire al utilizatorului se numeste $prob.out$, iar fisierul de evaluare (care contine informatii despre raspunsul corect pentru testul respectiv) se numeste $prob.ok$. Nu se recomanda folosirea altor fisiere in timpul evaluarii.\r\n* Odata ce s-a evaluat fisierul de iesire, mesajul trimis de evaluator trebuie afisat la $stderr$, iar punctajul la $stdout$, iar executia programului de evaluare trebuie terminata. Se recomanda scrierea unei functii care sa faca aceste lucruri:\r\n\r\np{width:75%}. == code(cpp) |\r\nvoid result(char msg[], int p)\r\n{\r\n    fprintf(stderr, msg);\r\n    printf(\"%d\", p);\r\n    exit(0);\r\n}\r\n==\r\n\r\n* Evaluator trebuie sa verifice ca fiecare din operatiile de deschidere de fisier sau de citire se efectueaza corect. Cateva exemple in $C/C++$:\r\n** functia $fopen$ returneaza un pointer catre fisierul deschis, iar daca acesta este $NULL$ s-a produs o eroare la deschiderea fisierului iar aceasta trebuia raportata\r\n** functiile $scanf / fscanf$ returneaza numarul de valori citite din lista de argumente; astfel se poate verifica la fiecare apel daca au fost citite toate datele si se poate detecta orice eroare de citire\r\n** asemanator cu $scanf$ , functia $gets / fgets$ returneaza o valoarea diferita de $0$ daca a efectuat cu succes citirea\r\nToate aceste verificari sunt *necesare*, in caz contrar evaluator poate crapa daca fisierul de iesire al utilizatorului nu respecta formatul de iesire. \r\n\r\n* Desi se presupune ca fisierul de intrare ({$.in$}) si fisierul de verificare ({$.ok$}) sunt corecte, se recomanda sa se verifice daca acestea sunt intr-adevar valide folosind acelasi tratament ca pentru fisierul de iesire al utilizatorului. In plus, se poate verifica daca fisierul de intrare respecta intr-adevar restrictiile din enuntul problemei. Aceste verificari pot identifica eventualele greseli din fisierele de intrare \"din fasa\" si de aceea recomandam cu insistenta folosirea lor.\r\n\r\nDaca ai probleme cu redactarea unui evaluator, poti contacta un \'administrator\':echipa-infoarena sau o persoana \'implicata\':implica-te in proiectul \'Extinde Arhiva\':implica-te/extinde-arhiva.\r\n\r\nh2. Exemple\r\n\r\nExemple de verificatoare pentru diverse probleme:\r\n\r\n* \'Buline\':documentatie/ghid-evaluator?buline.cpp\r\n* \'Ghiozdan\':documentatie/ghid-evaluator?ghiozdan.cpp\r\n* \'Shop\':documentatie/ghid-evaluator?shop.cpp\r\n* \'Zero 2\':documentatie/ghid-evaluator?zero2.cpp\r\n* \'Semne\':documentatie/ghid-evaluator?semne.pas (Pascal)\r\n* \'Adapost 2\':documentatie/ghid-evaluator?adapost2.pas (Pascal)\r\n',1,'public',NULL,NULL),('documentatie/grupare-teste','Gruparea testelor','2007-04-27 10:32:30','2009-02-02 16:54:46','h1. Gruparea testelor\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nh2. Despre ce e vorba?\r\n\r\nIn scopul de a imbunatati calitatea evaluarii de pe infoarena, s-a implementat o noua metoda de evaluare a problemelor, metoda folosita din anul 2005 si la \'Olimpiada Internationala de Informatica\':http://olympiads.win.tue.nl/ioi/. \r\n\r\ntable{width:60%}. |{border:1px solid olive;}. Pe scurt, testele se impart in grupuri disjuncte, iar pentru fiecare grup se va acorda punctajul corespunzator tuturor testelor din grup *doar daca* toate testele din grup au primit punctaje diferite de $0$. Astfel, daca cel putin un test dintr-un grup a primit $0$ puncte atunci nu se va acorda nici un punct pentru acel grup de teste. |\r\n\r\nAceasta metoda poate fi folosita in numeroase situatii:\r\n\r\n* in cazul problemelor in care generarea unor teste bune este foarte dificila, se pot grupa mai multe teste random cu diverse teste construite special pentru a detecta solutii gresite\r\n* se pot grupa teste care sa testeze in mod special corectitudinea programului, eficienta sa sau diverse cazuri speciale\r\n* pentru problemele care au propuse la diverse concursuri inainte de a fi adaugate pe infoarena se pot grupa testele din concurs cu alte teste random pentru a elimina solutiile care se bazeaza pe faptul ca se vor folosi exact testele din concurs\r\n* _FIXME: exemple de alte situatii_\r\n\r\nh2. Afla mai mult\r\n\r\nCiteste \'aici\':documentatie/borderoul-de-evaluare despre cum arata un borderou pentru o problema care foloseste gruparea testelor sau \'aici\':documentatie/editare-de-probleme despre cum faci ca o problema sa foloseaca aceasta metoda de evaluare.',15,'public',NULL,NULL),('blog/cutremur-in-california','Primul cutremur trait in California','2007-10-31 03:21:39','2008-11-15 13:41:14','Tocmai am simtit un cutremur, a durat vreo 30 de secunde si mi-a zgaltait putin biroul (5.6 grade magnitudine). Am avut senzatii contrastante, pe de o parte ma gandeam ca este primul meu cutremur in CA dupa ce am auzit mult despre ele, si pe cealalta ca ghiozdanul cu chestii de prim ajutor mi-e acasa. Urmatorul gand in minte mi-a fost faptul ca sistemele Google sunt failsafe si daca s-ar strica cateva harddiskuri tot nu ar fi probleme.\r\n\r\nCe mai, \"Living on the edge!\" in fata calculatorului :).\r\n\r\n',1490,'protected',2248,NULL),('cosmin/schita8','cosmin/schita8','2007-10-31 06:27:20','2007-10-31 06:32:52','_In aceasta a doua parte a interviului, \'Catalin\':http://catalinfrancu.blogspot.com/ ne povesteste despre MIT, dexOnline, Nilatac, Google si alte lucruri foarte interesante. Daca ati ratat prima parte a interviului, o puteti citi \'aici\':blog/interviu-cu-catalin-francu ._\r\n\r\n*De ce MIT si nu alte scoli din state sau din Romania?*\r\n\r\nPentru ca MIT-ul a fost singura universitate care m-a acceptat (privind in urma, am avut un noroc fenomenal). La Politehnica din Bucuresti am facut trei ani de zile si au fost cursuri dupa care m-am dat in vant (de exemplu, cel de Structuri de Date si Algoritmi sau cel de Limbaje Formale si Translatoare). Totusi, erau mult prea multe alte cursuri care nu aveau ce cauta in programa obligatorie si pur si simplu am zis ca nu mai vreau sa invat lucruri inutile.\r\n\r\n*Care au fost cursurile ale preferate in facultate? Ne poti face si o descriere pe scurt?*\r\n\r\nDe la MIT, mi-a placut in mod deosebit cursul de Securitatea Calculatoarelor si Retelelor, care a trecut prin subiecte ca one-way functions, chei publice/private, cookie-uri, spyware, virusi, semnaturi digitale, certificate si multe altele.\r\n\r\n*Ce cursuri ti-au fost folositoare in viata de programator?*\r\n\r\nEu sunt de parere ca practica intr-o companie este foarte deosebita de teoria invatata in scoala. Am luat cursuri de criptografie, algoritmi de aproximare, procese stocastice, probabilitati, limbaje formale si niciunul nu mi-a folosit in mod direct. Mi-ar fi folosit daca as fi scris un client de ssh sau un sistem de modelare financiara, dar nu am avut ocazia sa aplic atat de direct lucrurile invatate la un curs. Indirect, insa, toate mi-au fost folositoare pentru ca m-au invatat concepte noi si, cand m-am izbit de o problema noua, a fost mai usor sa o reduc la ceva cunoscut. De exemplu, nu-mi mai amintesc toti algoritmii studiati la cursul de criptografie, dar mi-au ramas notiuni\r\nfundamentale de algebra modulara si teoria numerelor, de care m-am tot izbit in practica.\r\n\r\n*De cati ani esti in USA?*\r\n\r\nDin 1999.\r\n\r\n*Te simti ca acasa aici?*\r\n\r\nCred ca oriunde traiesti mai mult de o luna - doua devine acasa.\r\n\r\n*De ce ti se face dor?*\r\n\r\nin primii ani petrecuti in America, mi-era dor de Romania. Acum, pe langa asta, cand sunt in Romania mi-e dor de locurile si de prietenii de aici. Cu alte cuvinte, din cauza ca am trait si sunt legat de doua locuri, oriunde m-as duce mi-e dor de ceva. :)\r\n\r\n*Te vei mai intoarce vreodata in Romania?*\r\n\r\nCategoric! Ne-am straduit foarte mult sa ne intretinem relatiile personale din Romania.\r\n\r\n*Ce e dexOnline?*\r\n\r\nPentru oameni, este un dictionar explicativ roman online. Pentru mine, este cea mai mare realizare profesionala a mea.\r\n\r\n*Cum ai inceput cu acest proiect?*\r\n\r\nIn vara lui 2001, am adus cu mine din Romania un dictionar explicativ (DEX). Pe de alta parte, foloseam intens Webster, dictionarul explicativ englez online. M-am gandit ca ar fi cazul sa existe si o pagina similara pentru limba romana.\r\n\r\nLa acea vreme, eu nu aveam practic nici una din cunostintele necesare. stiam putin HTML si aveam o idee despre ce inseamna o pagina dinamica, dar cam atat. Restul, PHP, Apache HTTP, MySQL, CSS, template-uri Smarty si altele le-am invatat cu timpul.\r\n\r\n*Cat timp crezi ca ai petrecut scriind cod pentru proiect?*\r\n\r\nMi-e greu sa fac o estimare. Lucrez de sase ani si am avut saptamani in care n-am facut nimic, saptamani in care am scris cod 30-40 de ore pe saptamana si saptamani in care m-am ocupat de treburi care tin de DEX online, dar nu de programare (de exemplu, introducerea sau moderarea de definitii). Nici numarul de linii de cod nu este o masura buna, pentru ca am aruncat mai mult decat am folosit (de exemplu, prima versiune a serverului era scrisa in Perl).\r\n\r\n*Care este cel mai frumos moment legat de dexOnline pe care l-ai trait?*\r\n\r\nCred ca a fost in 2004, cand echipa a terminat de introdus DEX-ul. Era doar un inceput (20% din numarul de definitii si mult mai putine functii pentru cautare decat azi), dar am simtit cu totii o satisfactie enorma pentru ca am muncit mult si pentru ca toata lumea ne credea nebuni. Astazi avem mult mai multe definitii, DEX online stie sa flexioneze cuvinte, de curand am adaugat si cautarea full-text si realizarile astea pot umbri putin acel prim pas. Dar fara el n-am fi ajuns unde suntem azi.\r\n\r\n*Spune-ne alt proiect interesant la care ai lucrat.*\r\n\r\nAm scris un motor de anti-sah pe care l-am botezat \"Nilatac\" (nu prea creativ, dar e prea tarziu sa-l mai redenumesc). Anti-sahul este o varianta de sah in care captura este obligatorie, iar scopul este sa iti pierzi toate piesele (inclusiv regele, care nu are un statut special). Voiam sa scriu un program de sah care sa stea conectat la FICS (http://freechess.org) si mi-am ales varianta asta, anti-sah, pentru ca era mai simplu de implementat: nu exista sah, nu exista rocada, iar regele poate fi capturat. Spre surprinderea mea, am descoperit ca varianta nu este lipsita de complexitate si frumusete. Jucatorii de varf spun chiar ca anti-sahul se poate masura cu sahul in complexitate.\r\n\r\nAm lucrat la Nilatac din 2001 pana prin 2005 si la inceput singurul algoritm pe care il stiam era alpha-beta. Am scris un program cu acest algoritm, l-am conectat la FICS foarte sigur pe mine si... surpriza: multi jucatori umani il bateau frecvent, iar calculatoarele nici nu discutau cu el. Asa am fost silit sa invat multe alte tehnici, de la carti de deschideri pana la tabele de finaluri si de la o reprezentare mai eficienta a tablei de joc (rotated bitboards) pana la un algoritm complet nou de cautare a arborelui de joc, (Proof Number Search).\r\n\r\nO particularitate interesanta este ca arborele de joc pentru anti-sah este mai mic decat cel pentru sah, din cauza ca initiativa este foarte importanta si o greseala poate duce la pierderea fortata a jocului (cel care a gresit o data poate fi obligat sa captureze piesa dupa piesa pana pierde partida). Din aceasta cauza, lumea spera ca jocul poate fi rezolvat complet. Dupa mutarea 1. e3, se pare ca negrul nu are un raspuns care sa echilibreze partida. Mi-am adus si eu o mica contributie, rezolvand cateva linii din deschidere, iar acum codul si cartea de deschideri sunt disponibile pe internet.\r\n\r\n*Cum ai ajuns la Google?*\r\n\r\nAm fost acceptat ca intern in 2001, la recomandarea fratelui meu si a advisorului meu de la MIT. in 2002 m-am angajat propriu-zis, dupa ce am absolvit facultatea.\r\n\r\n*Cum a fost viata de programator la Google? Ce iti placea cel mai mult?\r\n\r\nDisciplina programarii era extraordinara. Cu totii stim ca e bine ca, atunci cand dai peste un bug in cod, nu e bine sa-l ignori. Fie il repari, fie il raportezi autorului, fie cel putin introduci un raport in bugzilla. Dar la Google lucrul asta chiar se intampla :) Cand scrii o functie noua, care poate fi folositoare si altor echipe, nu pui codul in modulul echipei tale, pe care celelalte echipe nu il folosesc, ci in modulul comun. Lucrul asta cere mai mult timp, pentru ca trebuie sa compilezi si sa rulezi teste suplimentare, dar este atitudinea corecta si Google o incurajeaza.\r\n\r\nIn general, mi-a placut filozofia lor de a face lucrurile bine din prima, chiar daca dureaza mai mult. Fiecare linie de cod trebuie vazuta de cel putin inca o persoana in afara de autor. Asta ridica probleme cum ar fi ca, dupa ce termini de scris o bucata de cod si i-o trimiti unui coleg ca sa ti-o revizuiasca, dureaza cateva ore pana primesti raspunsul si trebuie sa-ti gasesti altceva disjunct la care sa lucrezi pana atunci. Dar beneficiile sunt mari, pentru ca multe buguri sunt gasite inca inainte de a fi adaugate la repository.\r\n\r\n*De ce ai plecat?*\r\n\r\nAm vrut sa am o perioada mai lunga in care sa ma pot ocupa cu norma intreaga de DEX online si de alte proiecte personale (programare, dar si din alte domenii).\r\n\r\n*De ce programare si nu cercetare?*\r\n\r\nProbabil tot Google e raspunsul. :) M-ar fi atras un Ph.D. si o cariera academica, dar mi-a fost imposibil sa dau cu piciorul ocaziei de a lucra la Google.\r\n\r\n*Cum e organizat mediul in care lucrezi? Ce configuratie de calculator? Ce sistem de operare, ide, etc.?*\r\n\r\nCa sistem de operare, am pornit cu RedHat in 1999 si am continuat pe aceeasi linie (azi rulez Fedora). M-am tot gandit sa incerc si alte distributii, dar viata parca e prea scurta ca sa o pierzi instaland sisteme de operare... Un IDE nu folosesc, pentru ca nu exista unul bun pentru dezvoltare de pagini de web. As vrea ceva cu suport pentru PHP, HTML, CSS, MySQL, Javascript si, desi am incercat Eclipse si IntelliJ, niciunul nu pare sa se potriveasca. Asa ca am ramas tot in stadiul de terminal text + emacs si nu pot sa zic ca imi lipseste ceva.\r\n\r\nPoate un lucru amuzant e ca n-am avut niciodata un CD sau DVD de instalare pentru Fedora. intotdeauna am creat un CD minim de boot, dupa care instalarea propriu-zisa am facut-o prin retea.\r\n\r\n*Ce calitati are un programator bun?*\r\n\r\nLucrurile astea le-am invatat si eu de-abia dupa ce am iesit din scoala si am inceput sa lucrez la Google. Descoperi ca una este programarea de olimpiada sau o tema de facultate, unde practic lucrezi ca un hamster intr-un acvariu, si cu totul altceva este lucrul intr-o echipa. Bunaoara, un principiu de baza la Google era ca, daca cineva vine si te intreaba ceva, trebuie sa-ti faci timp sa-i raspunzi, chiar daca si tu ai proiectele si termenele tale. Este mai bine sa aveti amandoi un randament de 80-90% decat sa ai tu un randament de 100% si colegul tau sa nu stie ce are de facut.\r\n\r\nLa fel, este important sa comunici cu restul echipei, sa stii la ce lucreaza ceilalti si ceilalti sa stie la ce lucrezi tu, nu neaparat la nivel de ora sau zi, dar cel putin la nivel de saptamana. Este important ca toata lumea care lucreaza la un proiect sa adopte acelasi stil de formatare a codului. Un programator bun trebuie sa poata citi codul altuia si sa incerce sa-si faca codul cat mai inteligibil de catre altii (graba nu este un motiv sa nu adaugi comentarii acolo unde codul nu este evident).\r\n\r\nDesigur, si calitatile individuale sunt importante. Trebuie sa fii ordonat ca sa-ti poti citi propriul cod dupa cativa ani. si asta cere efort, pentru ca peste cativa ani practic vei fi o cu totul alta persoana si de regula una mai inceata la minte. :) Trebuie sa nu-ti fie frica de un limbaj nou, dar nici sa nu extragi doar strictul necesar din el. Bunaoara, multa vreme dupa ce am invatat Java, m-am ferit sa folosesc mecanismul de exceptii. Cu timpul, le-am inteles avantajele si am invatat sa le folosesc pentru a face codul mai frumos si mai robust. De asemenea, trebuie sa ai rabdarea sa te gandesti de doua ori inainte sa implementezi o data.\r\n\r\n*Care sunt siteurile tale preferate?*\r\n\r\nCa tot romanul, citesc stirile din sport in fiecare zi :) Pentru asta, ma duc la http://onlinesport.ro. Citesc stirile pe http://hotnews.ro si pe http://news.google.com. Evident, de cautat caut cu Google, probabil de vreo suta de ori pe zi, dar asta nu punem la socoteala, e ca si cum ai scrie in CV ca stii sa scrii si sa citesti. Daca am nedumeriri despre Fedora si caut pe Google, de cele mai multe ori ajung la http://fedoraforum.org, care are mereu raspunsurile\r\npotrivite. Pentru generalitati, cel mai des folosesc Wikipedia, un site in fata caruia DEX online pur si simplu paleste.\r\n\r\n*Ce programe iti fac viata mai usoara?*\r\n\r\nM-am gandit destul de mult la intrebarea asta si am ajuns la concluzia ca nu prea mai sunt programe care sa imi faca viata mai usoara. Exista website-uri fara care m-as simti legat de maini, cum ar fi http://maps.google.com cand vreau sa merg undeva. Dar ca software instalat pe calculator, nu cred ca imi trebuie mai mult decat un sistem standard, de genul Linux + Firefox + OpenOffice.\r\n\r\n*Ce hobbyuri ai inafara programarii?*\r\n\r\nImi place muzica corala (mi-am si petrecut catva timp culegand niste partituri corale cu un software specializat, numit Lilypond). imi place si sahul, desi ma deprima ca joc mai prost  decat in liceu, fiindca am mai putin timp liber. si imi plac jocurile pe calculator (desi asta e o afirmatie foarte generala, pentru ca evident sunt jocuri care imi plac si jocuri care nu imi plac).\r\n\r\n*Ce va urma?*\r\n\r\nRestul vietii mele :) E o intrebare foarte generala, dar intamplarea face ca vine la un moment bun. Am luat decizia ca 2007 este ultimul an in care mai lucrez la DEX online. De anul viitor vreau sa incep ceva nou, tot legat de programare, si sunt in cautare de idei.\r\n\r\n*Vrei sa lasi un mesaj cititorilor blogului?*\r\n\r\nCred ca noi toti cei pasionati de informatica avem un noroc formidabil. Este una din cele mai palpitante meserii si cine are putina rabdare si disciplina poate produce multe lucruri folositoare si/sau distractive. Asa este si infoarena.ro: este un site cu un continut valoros si cu o comunitate pe masura.\r\n\r\nDaca ne gandim la cate lucruri ne ofera internetul si informatica de-a gata, cred ca e bine sa incercam sa si oferim ceva inapoi. Sunt convins ca toti utilizatorii infoarena au mici proiecte personale (in engleza sunt numite atat de distractiv \"pet projects\") si i-as incuraja pe toti sa le ofere restului lumii ca software liber.\r\n<br>\r\n_Multumim pentru interviu!_\r\n\r\n\'Comentarii\':',58,'public',NULL,NULL),('blog/interviu-cu-catalin-francu-partea-a-doua','Interviu cu Catalin Francu - partea a doua','2007-10-31 06:43:35','2008-11-15 13:41:14','_In aceasta a doua parte a interviului, \'Catalin\':http://catalinfrancu.blogspot.com/ ne povesteste despre MIT, dexOnline, Nilatac, Google si alte lucruri foarte interesante. Daca ati ratat prima parte a interviului, citi-o \'aici\':blog/interviu-cu-catalin-francu ._\r\n\r\n!<blog/interviu-cu-catalin-francu-partea-a-doua?cata.JPG!*De ce MIT si nu alte scoli din state sau din Romania?*\r\n\r\nPentru ca MIT-ul a fost singura universitate care m-a acceptat (privind in urma, am avut un noroc fenomenal). La Politehnica din Bucuresti am facut trei ani de zile si au fost cursuri dupa care m-am dat in vant (de exemplu, cel de Structuri de Date si Algoritmi sau cel de Limbaje Formale si Translatoare). Totusi, erau mult prea multe alte cursuri care nu aveau ce cauta in programa obligatorie si pur si simplu am zis ca nu mai vreau sa invat lucruri inutile.\r\n\r\n*Care au fost cursurile tale preferate in facultate? Ne poti face si o descriere pe scurt?*\r\n\r\nDe la MIT, mi-a placut in mod deosebit cursul de Securitatea Calculatoarelor si Retelelor, care a trecut prin subiecte ca one-way functions, chei publice/private, cookie-uri, spyware, virusi, semnaturi digitale, certificate si multe altele.\r\n\r\n*Ce cursuri ti-au fost folositoare in viata de programator?*\r\n\r\nEu sunt de parere ca practica intr-o companie este foarte deosebita de teoria invatata in scoala. Am luat cursuri de criptografie, algoritmi de aproximare, procese stocastice, probabilitati, limbaje formale si niciunul nu mi-a folosit in mod direct. Mi-ar fi folosit daca as fi scris un client de ssh sau un sistem de modelare financiara, dar nu am avut ocazia sa aplic atat de direct lucrurile invatate la un curs. Indirect, insa, toate mi-au fost folositoare pentru ca m-au invatat concepte noi si, cand m-am izbit de o problema noua, a fost mai usor sa o reduc la ceva cunoscut. De exemplu, nu-mi mai amintesc toti algoritmii studiati la cursul de criptografie, dar mi-au ramas notiuni fundamentale de algebra modulara si teoria numerelor, de care m-am tot izbit in practica.\r\n\r\n*De cati ani esti in USA?*\r\n\r\nDin 1999.\r\n\r\n*Te simti ca acasa aici?*\r\n\r\nCred ca oriunde traiesti mai mult de o luna - doua devine acasa.\r\n\r\n*De ce ti se face dor?*\r\n\r\nIn primii ani petrecuti in America, mi-era dor de Romania. Acum, pe langa asta, cand sunt in Romania mi-e dor de locurile si de prietenii de aici. Cu alte cuvinte, din cauza ca am trait si sunt legat de doua locuri, oriunde m-as duce mi-e dor de ceva. :)\r\n\r\n*Te vei mai intoarce vreodata in Romania?*\r\n\r\nCategoric! Ne-am straduit foarte mult sa ne intretinem relatiile personale din Romania.\r\n\r\n*Ce e dexOnline?*\r\n\r\nPentru oameni, este un dictionar explicativ roman online. Pentru mine, este cea mai mare realizare profesionala a mea.\r\n\r\n*Cum ai inceput cu acest proiect?*\r\n\r\nIn vara lui 2001, am adus cu mine din Romania un dictionar explicativ (DEX). Pe de alta parte, foloseam intens Webster, dictionarul explicativ englez online. M-am gandit ca ar fi cazul sa existe si o pagina similara pentru limba romana.\r\n\r\nLa acea vreme, eu nu aveam practic nici una din cunostintele necesare. Stiam putin HTML si aveam o idee despre ce inseamna o pagina dinamica, dar cam atat. Restul, PHP, Apache HTTP, MySQL, CSS, template-uri Smarty si altele le-am invatat cu timpul.\r\n\r\n*Cat timp crezi ca ai petrecut scriind cod pentru proiect?*\r\n\r\nMi-e greu sa fac o estimare. Lucrez de sase ani si am avut saptamani in care n-am facut nimic, saptamani in care am scris cod 30-40 de ore pe saptamana si saptamani in care m-am ocupat de treburi care tin de DEX online, dar nu de programare (de exemplu, introducerea sau moderarea de definitii). Nici numarul de linii de cod nu este o masura buna, pentru ca am aruncat mai mult decat am folosit (de exemplu, prima versiune a serverului era scrisa in Perl).\r\n\r\n*Care este cel mai frumos moment legat de dexOnline pe care l-ai trait?*\r\n\r\nCred ca a fost in 2004, cand echipa a terminat de introdus DEX-ul. Era doar un inceput (20% din numarul de definitii si mult mai putine functii pentru cautare decat azi), dar am simtit cu totii o satisfactie enorma pentru ca am muncit mult si pentru ca toata lumea ne credea nebuni. Astazi avem mult mai multe definitii, DEX online stie sa flexioneze cuvinte, de curand am adaugat si cautarea full-text si realizarile astea pot umbri putin acel prim pas. Dar fara el n-am fi ajuns unde suntem azi.\r\n\r\n*Spune-ne alt proiect interesant la care ai lucrat.*\r\n\r\nAm scris un motor de anti-sah pe care l-am botezat \"Nilatac\" (nu prea creativ, dar e prea tarziu sa-l mai redenumesc). Anti-sahul este o varianta de sah in care captura este obligatorie, iar scopul este sa iti pierzi toate piesele (inclusiv regele, care nu are un statut special). Voiam sa scriu un program de sah care sa stea conectat la FICS (http://freechess.org) si mi-am ales varianta asta, anti-sah, pentru ca era mai simplu de implementat: nu exista sah, nu exista rocada, iar regele poate fi capturat. Spre surprinderea mea, am descoperit ca varianta nu este lipsita de complexitate si frumusete. Jucatorii de varf spun chiar ca anti-sahul se poate masura cu sahul in complexitate.\r\n\r\nAm lucrat la Nilatac din 2001 pana prin 2005 si la inceput singurul algoritm pe care il stiam era alpha-beta. Am scris un program cu acest algoritm, l-am conectat la FICS foarte sigur pe mine si... surpriza: multi jucatori umani il bateau frecvent, iar calculatoarele nici nu discutau cu el. Asa am fost silit sa invat multe alte tehnici, de la carti de deschideri pana la tabele de finaluri si de la o reprezentare mai eficienta a tablei de joc (rotated bitboards) pana la un algoritm complet nou de cautare a arborelui de joc, (Proof Number Search).\r\n\r\nO particularitate interesanta este ca arborele de joc pentru anti-sah este mai mic decat cel pentru sah, din cauza ca initiativa este foarte importanta si o greseala poate duce la pierderea fortata a jocului (cel care a gresit o data poate fi obligat sa captureze piesa dupa piesa pana pierde partida). Din aceasta cauza, lumea spera ca jocul poate fi rezolvat complet. Dupa mutarea 1. e3, se pare ca negrul nu are un raspuns care sa echilibreze partida. Mi-am adus si eu o mica contributie, rezolvand cateva linii din deschidere, iar acum codul si cartea de deschideri sunt disponibile pe internet.\r\n\r\n*Cum ai ajuns la Google?*\r\n\r\nAm fost acceptat ca intern in 2001, la recomandarea fratelui meu si a advisorului meu de la MIT. in 2002 m-am angajat propriu-zis, dupa ce am absolvit facultatea.\r\n\r\n*Cum a fost viata de programator la Google? Ce iti placea cel mai mult?*\r\n\r\nDisciplina programarii era extraordinara. Cu totii stim ca e bine ca, atunci cand dai peste un bug in cod, nu e bine sa-l ignori. Fie il repari, fie il raportezi autorului, fie cel putin introduci un raport in bugzilla. Dar la Google lucrul asta chiar se intampla :) Cand scrii o functie noua, care poate fi folositoare si altor echipe, nu pui codul in modulul echipei tale, pe care celelalte echipe nu il folosesc, ci in modulul comun. Lucrul asta cere mai mult timp, pentru ca trebuie sa compilezi si sa rulezi teste suplimentare, dar este atitudinea corecta si Google o incurajeaza.\r\n\r\nIn general, mi-a placut filozofia lor de a face lucrurile bine din prima, chiar daca dureaza mai mult. Fiecare linie de cod trebuie vazuta de cel putin inca o persoana in afara de autor. Asta ridica probleme cum ar fi ca, dupa ce termini de scris o bucata de cod si i-o trimiti unui coleg ca sa ti-o revizuiasca, dureaza cateva ore pana primesti raspunsul si trebuie sa-ti gasesti altceva disjunct la care sa lucrezi pana atunci. Dar beneficiile sunt mari, pentru ca multe buguri sunt gasite inca inainte de a fi adaugate la repository.\r\n\r\n*De ce ai plecat?*\r\n\r\nAm vrut sa am o perioada mai lunga in care sa ma pot ocupa cu norma intreaga de DEX online si de alte proiecte personale (programare, dar si din alte domenii).\r\n\r\n*De ce programare si nu cercetare?*\r\n\r\nProbabil tot Google e raspunsul. :) M-ar fi atras un Ph.D. si o cariera academica, dar mi-a fost imposibil sa dau cu piciorul ocaziei de a lucra la Google.\r\n\r\n*Cum e organizat mediul in care lucrezi? Ce configuratie de calculator? Ce sistem de operare, ide, etc.?*\r\n\r\nCa sistem de operare, am pornit cu RedHat in 1999 si am continuat pe aceeasi linie (azi rulez Fedora). M-am tot gandit sa incerc si alte distributii, dar viata parca e prea scurta ca sa o pierzi instaland sisteme de operare... Un IDE nu folosesc, pentru ca nu exista unul bun pentru dezvoltare de pagini de web. As vrea ceva cu suport pentru PHP, HTML, CSS, MySQL, Javascript si, desi am incercat Eclipse si IntelliJ, niciunul nu pare sa se potriveasca. Asa ca am ramas tot in stadiul de terminal text + emacs si nu pot sa zic ca imi lipseste ceva.\r\n\r\nPoate un lucru amuzant e ca n-am avut niciodata un CD sau DVD de instalare pentru Fedora. intotdeauna am creat un CD minim de boot, dupa care instalarea propriu-zisa am facut-o prin retea.\r\n\r\n*Ce calitati are un programator bun?*\r\n\r\nLucrurile astea le-am invatat si eu de-abia dupa ce am iesit din scoala si am inceput sa lucrez la Google. Descoperi ca una este programarea de olimpiada sau o tema de facultate, unde practic lucrezi ca un hamster intr-un acvariu, si cu totul altceva este lucrul intr-o echipa. Bunaoara, un principiu de baza la Google era ca, daca cineva vine si te intreaba ceva, trebuie sa-ti faci timp sa-i raspunzi, chiar daca si tu ai proiectele si termenele tale. Este mai bine sa aveti amandoi un randament de 80-90% decat sa ai tu un randament de 100% si colegul tau sa nu stie ce are de facut.\r\n\r\nLa fel, este important sa comunici cu restul echipei, sa stii la ce lucreaza ceilalti si ceilalti sa stie la ce lucrezi tu, nu neaparat la nivel de ora sau zi, dar cel putin la nivel de saptamana. Este important ca toata lumea care lucreaza la un proiect sa adopte acelasi stil de formatare a codului. Un programator bun trebuie sa poata citi codul altuia si sa incerce sa-si faca codul cat mai inteligibil de catre altii (graba nu este un motiv sa nu adaugi comentarii acolo unde codul nu este evident).\r\n\r\nDesigur, si calitatile individuale sunt importante. Trebuie sa fii ordonat ca sa-ti poti citi propriul cod dupa cativa ani. si asta cere efort, pentru ca peste cativa ani practic vei fi o cu totul alta persoana si de regula una mai inceata la minte. :) Trebuie sa nu-ti fie frica de un limbaj nou, dar nici sa nu extragi doar strictul necesar din el. Bunaoara, multa vreme dupa ce am invatat Java, m-am ferit sa folosesc mecanismul de exceptii. Cu timpul, le-am inteles avantajele si am invatat sa le folosesc pentru a face codul mai frumos si mai robust. De asemenea, trebuie sa ai rabdarea sa te gandesti de doua ori inainte sa implementezi o data.\r\n\r\n*Care sunt siteurile tale preferate?*\r\n\r\nCa tot romanul, citesc stirile din sport in fiecare zi :) Pentru asta, ma duc la http://onlinesport.ro. Citesc stirile pe http://hotnews.ro si pe http://news.google.com. Evident, de cautat caut cu Google, probabil de vreo suta de ori pe zi, dar asta nu punem la socoteala, e ca si cum ai scrie in CV ca stii sa scrii si sa citesti. Daca am nedumeriri despre Fedora si caut pe Google, de cele mai multe ori ajung la http://fedoraforum.org, care are mereu raspunsurile\r\npotrivite. Pentru generalitati, cel mai des folosesc Wikipedia, un site in fata caruia DEX online pur si simplu paleste.\r\n\r\n*Ce programe iti fac viata mai usoara?*\r\n\r\nM-am gandit destul de mult la intrebarea asta si am ajuns la concluzia ca nu prea mai sunt programe care sa imi faca viata mai usoara. Exista website-uri fara care m-as simti legat de maini, cum ar fi http://maps.google.com cand vreau sa merg undeva. Dar ca software instalat pe calculator, nu cred ca imi trebuie mai mult decat un sistem standard, de genul Linux + Firefox + OpenOffice.\r\n\r\n*Ce hobbyuri ai inafara programarii?*\r\n\r\nImi place muzica corala (mi-am si petrecut catva timp culegand niste partituri corale cu un software specializat, numit Lilypond). imi place si sahul, desi ma deprima ca joc mai prost  decat in liceu, fiindca am mai putin timp liber. si imi plac jocurile pe calculator (desi asta e o afirmatie foarte generala, pentru ca evident sunt jocuri care imi plac si jocuri care nu imi plac).\r\n\r\n*Ce va urma?*\r\n\r\nRestul vietii mele :) E o intrebare foarte generala, dar intamplarea face ca vine la un moment bun. Am luat decizia ca 2007 este ultimul an in care mai lucrez la DEX online. De anul viitor vreau sa incep ceva nou, tot legat de programare, si sunt in cautare de idei.\r\n\r\n*Vrei sa lasi un mesaj cititorilor blogului?*\r\n\r\nCred ca noi toti cei pasionati de informatica avem un noroc formidabil. Este una din cele mai palpitante meserii si cine are putina rabdare si disciplina poate produce multe lucruri folositoare si/sau distractive. Asa este si infoarena.ro: este un site cu un continut valoros si cu o comunitate pe masura.\r\n\r\nDaca ne gandim la cate lucruri ne ofera internetul si informatica de-a gata, cred ca e bine sa incercam sa si oferim ceva inapoi. Sunt convins ca toti utilizatorii infoarena au mici proiecte personale (in engleza sunt numite atat de distractiv \"pet projects\") si i-as incuraja pe toti sa le ofere restului lumii ca software liber.\r\n<br>\r\n_Multumim pentru interviu!_\r\n\r\n',1490,'protected',2249,NULL),('blog/interviu-catalin-francu','Interviu Catalin Francu','2007-10-31 11:01:44','2008-01-23 14:48:59','\'Cosmin\':utilizator/cosmin a publicat pe \'blog-ul infoarena\':blog un interviu cu nimeni altul decat \'*Catalin Francu*\':http://catalinfrancu.blogspot.com/.\r\n\r\n_Catalin este cunoscut in lumea celor pasionati de informatica prin cartea \"Psihologia concursurilor de informatica\", o carte plina de probleme frumoase si deschizatoare de drumuri la vremea ei, si prin \"lista lu\' Francu\", o lista de discutii pe email, unde cativa dintre cei ce au ajuns apoi olimpici internationali la informatica ai Romaniei rezolvau si discutau probleme._\r\n\r\n_In lumea lingvistilor este cunoscut prin proiectul \'dexonline\':http://dexonline.ro . Acesta [...] contine intreg Dictionarul Explicativ al limbii romane si alte dictionare. In timpul liceului, Catalin a luat o medalie de argint la IOI, iar in timpul facultatii s-a clasat pe locul 7 la etapa finala a concursului ACM ICPC cu echipa reprezentanta a MIT. De asemenea a facut parte din comisia stiintifica a Olimpiadei de Informatica a Europei Centrale din 2000 care s-a desfasurat la Cluj. Dupa terminarea facultatii Catalin a lucrat patru ani ca programator la Google inc._\r\n&hellip;\r\n\r\nCiteste interviul acum:\r\n\r\n* \'Partea 1\':blog/interviu-cu-catalin-francu\r\n* \'Partea a 2-a\':blog/interviu-cu-catalin-francu-partea-a-doua\r\n',15,'public',NULL,NULL),('utilizator/stef2n','Stefan Istrate','2006-11-24 21:00:43','2008-01-21 14:39:47','h2. Studii\r\n\r\n* 2007-prezent: Universitatea Bucuresti, \"Facultatea de Matematica si Informatica\":http://fmi.unibuc.ro/ro/, sectia Informatica\r\n* 2003-2007: \"Liceul Teoretic \'Grigore Moisil\'\":http://www.ltgm.ro/ Urziceni\r\n\r\n\r\nh2. Distinctii importante\r\n\r\n* 2007 - Locul 3 la finala preONI, Bucuresti, 26 iunie\r\n* 2007 - Membru al Lotului National de Informatica\r\n* 2007 - Mentiune (locul 10) la Olimpiada Nationala de Informatica, Cluj-Napoca, 10-16 aprilie\r\n* 2006 - Membru al Lotului National de Informatica\r\n* 2006 - Mentiune (locul 10) la Olimpiada Nationala de Informatica, Targoviste, 15-22 aprilie\r\n* 2005 - Participare la Olimpiada Nationala de Informatica, Galati, 25 martie - 1 aprilie\r\n* 2004 - Premiul I la Concursul interjudetean de matematica \"Gheorghe Mihoc\", Slobozia, 24 aprilie\r\n* 2002 - Premiul II la Concursul interjudetean de matematica \"Gheorghe Mihoc\", Slobozia, 16 noiembrie\r\n* 2002 - Premiul III (locul 28) la Olimpiada Nationala de Matematica, Ramnicu-Valcea, 16-22 martie\r\n\r\n\r\nh2. Alte distinctii\r\n\r\n* 2007 - Finalist .campion\r\n* 2007 - Premiul I la Concursul interjudetean de informatica \"Grigore Moisil\", Urziceni, 2-4 februarie\r\n* 2007 - Mentiune la Concursul interjudetean de matematica \"Grigore Moisil\", Urziceni, 2-4 februarie\r\n* 2006 - Premiul I la Concursul interjudetean de informatica \"Grigore Moisil\", Urziceni, 10-12 februarie\r\n* 2006 - Premiul I la Concursul interjudetean de matematica \"Grigore Moisil\", Urziceni, 10-12 februarie\r\n* 2005 - Premiul I la Concursul interjudetean de informatica \"Grigore Moisil\", Urziceni, 15 ianuarie\r\n* 2005 - Premiul III la Concursul interjudetean de matematica \"Grigore Moisil\", Urziceni, 15 ianuarie\r\n* 2004 - Mentiune la Concursul de matematica Unirea, Focsani, 23-25 ianuarie\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* ==user(user=\"georgiana\" type=\"normal\")==\r\n* ==user(user=\"wefgef\" type=\"normal\")==\r\n* ==user(user=\"astronomy\" type=\"normal\")==\r\n* ==user(user=\"Marius\" type=\"normal\")==\r\n',2044,'protected',NULL,NULL),('problema/energii','Energii','2006-11-11 11:23:35','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"energii\")==\r\n\r\n== include(page=\"template/badtests\") ==\r\n\r\nGigel a ajuns administrator la o centrala termo-electrica. Intr-o zi a avut loc o cadere de tensiune si astfel centrala este la pamant. Gigel trebuie sa o repuna in functiune. Stiind ce energie produce fiecare generator cat si costul punerii in functiune el trebuie sa gasesca o solutie de cost minim, pentru a produce o cantitate de energie egala sau mai mare cu cea necesara repornirii centralei.\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l pe Gigel sa gaseasca solutia ceruta !\r\n\r\nh2. Date de Intrare\r\n\r\nFisierul de intrare $energii.in$ are urmatorul format :\r\n$G$ - numarul de generatoare\r\n$W$ - cantitatea de energie necesara repornirii centralei\r\n$EG{~i~} CG{~i~}$ - urmatoarele $G$ linii contin catitatea de energie produsa de generator si costul necesar producerii energiei, separate printr-un spatiu $(1 &le; i &le; G)$\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul de iesire $energii.out$ are urmatorul format :\r\n$C{~min~}$ - costul minim necesar repornirii centralei sau $-1$ daca nu este suficienta energie pentru repornire\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 < G < 1001$\r\n* $1 < W < 5001$\r\n* $1 < EG{~i~},CG{~i~} < 10001$\r\n* Solutia este unica\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. energii.in |_. energii.out |\r\n| 3\r\n8\r\n2 4\r\n2 3\r\n8 9\r\n| 9 |\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"energii\")==\n\n\n',1490,'task: energii',87,NULL),('blog/ginfo-a-murit','Ginfo a murit','2007-10-31 23:05:59','2008-11-15 13:41:14','Mihai Scortaru, redactorul sef al \'Ginfo\':http://www.ginfo.ro , \'a anutat\':http://ba.toptalent.ro/forum/index.php?topic=299.0 ca revista isi intrerupe aparitia.\r\n\r\nPacat.\r\n\r\n',1490,'protected',2252,NULL),('blog-sidebar','Blog','2007-10-07 22:00:41','2007-11-04 18:31:50','p=. \'!blog-sidebar?icon.rss.gif!\':blog?action=rss\r\n\r\np=. \'*Despre Blog*\':despre-blog\r\n\r\nh2. Ultimele insemnari\r\n\r\n==BlogPosts()==\r\n\r\nh2. Categorii\r\n\r\n==BlogTags()==\r\n\r\nh2. Blogroll\r\n\r\n(blog-list)* \"Vivi\'s blog\":http://www.vivi.ro/blog\r\n(blog-list)* \'WebDiarios de Motocicleta\':http://infoweekly.blogspot.com/\r\n(blog-list)* \'Catalin Francu\':http://catalinfrancu.blogspot.com/\r\n(blog-list)* \'Florin Manea\':http://flmanea.blogspot.com\r\n(blog-list)* \"Stevey\'s Blog Rants\":http://steve-yegge.blogspot.com/\r\n(blog-list)* \'Joel on Software\':http://www.joelonsoftware.com\r\n(blog-list)* \'Developing for developers\':http://blogs.msdn.com/devdev/\r\n',1,'protected',NULL,NULL),('skiplists','Skiplists','2005-02-05 00:00:00','2009-02-20 00:35:05','h1. Skiplists\r\n\r\n(Categoria _Structuri de date_, Autori _Sorin Stancu-Mara_, _Mihnea Giurgea_)\r\n\r\nVreau sa va fac cunostinta cu o noua structura randomizata de stocare a datelor. Ea se numeste Skiplist si permite majoritatea operatiilor in timp logaritmic si este foarte usor de implementat. Structura ocupa $O(N)$ memorie si efectueaza majoritatea operatiilor (adaugare, cautare, stergere) in {$O(log N)$}. Bineinteles ca exista STL, dar de cele mai multe ori nimic nu bate o structura \"home-brewed\". Skiplist-urile sunt foarte similare cu arborii AVL, insa sunt un pic mai rapide si mai usor de implementat.\r\n\r\nh2. Introducere\r\n\r\nTotul porneste de la o lista simplu inlantuita in care fiecare element are un link (pointer sau orice altceva care poate indica alt element) catre urmatorul element din lista. Presupunem ca aceasta lista o tinem sortata. Ce ar fi daca de la elementul $x$ nu am sari la elementul {$x+1$}? Ce ar fi daca am sari la {$x+2$}? Acesta este principiul din spatele Skiplist-urilor.\r\n\r\nIntr-un Skiplist fiecare element are un grad, numarul de link-uri la alte elemente. Un link de nivelul $x$ va indica un element care are cel putin $x$ nivele, astfel este posibil ca sa parcurgem toata lista cu link-uri de un anumit nivel. Cheia este ca, cu cat nivelul este mai mare, elemente de nivelul respectiv sunt mai rare, link-urile sunt din ce in ce mai putine si astfel pointeaza mai departe. La nivelul minim,{$0$}, exista un link catre elementul exact urmator, iar cu cat crestem nivelul, cu atat link-urile sunt mai rare si \"sar\" peste mai multe elemente, de unde vine si denumirea de Skiplist-uri, liste cu salt.\r\n\r\nh2. Implementare\r\n\r\nIntr-un skiplist nodurile pot avea orice grad, alegerea gradului tine exclusiv de consideratii de viteza. Pentru detalii vezi sectiunea de complexitate.\r\n\r\nCum se implementeaza o structura de genul asta? Mai intai trebuie sa subliniez ca este la fel de usor de implementat si in Pascal, dar nu mai respecta limita de memorie, care se va duce la {$N log N$}, dar care in cele mai multe cazuri este ok.\r\n\r\nImplementarea in C ar arata ceva de genul:\r\n\r\n== code(cpp) |struct nod {\r\n    int key; \r\n    /* ce mai vreti sa memorati intrun nod. */\r\n    nod** link;\r\n}\r\n==\r\n\r\nIn Pascal {$nod* link$}, un array dinamic, este mai dificil de implementat. Pentru a evita asta putem sa alocam la maxim array-ul, mai exact $log N$ elemente. Asta ridica complexitatea de memorie la {$O(N log N)$}, dar de cele mai multe ori este perfect acceptabil.\r\n\r\n== code(pas) |type pnod=^nod;\r\nnod=record\r\n    key:integer;\r\n    { ce mai vreti sa memorati intr-un nod }\r\n    link:array[0..logN] of pnod;\r\nend;\r\n==\r\n\r\nPe langa asta trebuie sa tineti minte capul listei, care trebuie sa fie un nod de grad maxim. De asemenea, cu cat gradul maxim este mai mare cu atat va merge mai repede pt $N$ mai mare ({$100,000$}) deci cand va ganditi la gradul maxim luati-l ceva de genul {$logN*2$}.\r\n\r\nCa implementare efectiva nu va trebuie decat un singur algoritm, cautarea, restul fiind extrem de usor de dedus. Algoritmul de cautare pe care il vom prezenta isi propune sa caute ultimul element cu cheia mai mica decat o anumita valoare.\r\n\r\nPentru a cauta un element intr-o lista inlantuita normala sortata se incepe de la primul element si se avanseaza pana cand urmatorul nod are cheia mai mare decat cea cautata. Intr-un Skiplist procedam exact la fel, dar folosim faptul ca avem mai multe nivele de inlantuire. Vom incepe de la cel mai inalt nivel, si vom cauta ca intr-o lista inlantuita normala. Cand urmatorul nod la nivelul curent are cheia mai mare (sau este {$null$}) vom scadea nivelul.\r\n\r\nO implementare in pseudo-C ar arata ceva de genul:\r\n\r\n== code(cpp) |\r\nnod *x = cap_de_lista;\r\nint grad = grad_max;\r\nnod temp[grad_max];\r\n    while (gradul >= 0) {\r\n        while (x->link[grad] != NULL && x->link[grad]->key < cheie_cautata)\r\n            x=x->link[grad];\r\n        temp[grad]=x;\r\n        grad--;\r\n    }\r\n==\r\n\r\nAcest algoritm ne da nodul din fata elementului cautat, daca acesta exista, sau cel care are cel mai mare key mai mic decat cel cautat. De aici e simplu sa vedem daca elementul cautat exista in Skiplist, ar trebui sa fie $x->link{~0~}$ (urmatorul element, pe nivelul $0$ structura este o lista simplu inlantuita). De asemenea ne mai ramane si {$temp$}, $temp$ contine acum toate nodurile din fata elementului curent care indica catre elemente de la $x$ in sus. Acest vector $temp$ este o modalitate de a evita listele dublu-inlantuite, si a injumatati consumul de memorie.\r\n\r\nOK, dar cum se fac celelalte operatii? Sa le luam pe rand...\r\n\r\n* Cautare: am explicat deja\r\n* Inserare: vrem sa inseram un nod cu cheia {$k$}. Mai intai cautam cheia $k$ in Skiplist-ul deja existent, apoi alocam un nou nod de grad {$g$}, pe care il adaugam la fiecare nivel mai mic decat {$g$}, exact ca intr-o lista simplu inlantuita.\r\n* Stergere: vrem sa stergem nodul cu cheia {$k$}. Mai intai cautam cheia {$k$}, apoi stergem nodul la fiecare nivel, exact ca intr-o lista normala.\r\n* Interclasare: aici complexitatea mai depinde si de cat de separate sunt cele doua skip-uri. In principiu comparati primele elemente din fiecare lista iar pe cel mai mare il cautati in celalalt skiplist, luati elementele intre start si pozitia unde s-a oprit algoritmul de cautare si le adaugati in structura care va contine uniunea celor doua.\r\n\r\nh2. Complexitate\r\n\r\nPana acum nu am dat nici o explicatie asupra presupusei complexitati $O(log N)$ a operatiilor. Dupa cum puteti vedeam mai sus, operatiile de adaugare si stergere sunt de fapt variante ale operatiiei de cautare, la care se adauga {$O(grad maxim)$}. Cea mai importanta operatie este cea de cautare.\r\n\r\nOperatia de cautare va merge prin toate nivele, deci are complexitate minima {$O(grad maxim)$}. Ne putem imagina un skip-list ideal, in care grad-maxim este {$O(log N)$}, iar gradele sunt o secventa de genul ({$max, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, 16, 1, 2, 1, 4, 1$}...). In acest skip-list, cautarea este echivalenta cu o cautare binara, la fiecare pas vom \"sari\" peste fix jumatate din ce a ramas, pentru o complexitate finala de [$O(log N)$}. Bineinteles, un skip-list real este destul de departe de acest ideal. In cel mai rau caz este posibil ca toate elementele sa aiba acelasi grad, si totul se reduce la o lista inlantuita cu consum mare de memorie, dar este putin probabil. Pe cazul mediu va avea insa complexitatea de {$O(log N)$}.\r\n\r\nPentru a aduce insa la complexitatea de {$O(log N)$}, este nevoie ca gradele sa aiba o distrubutie logaritmica: fiecare nod are gradul {$&ge;1$}, {$N/2$} au gradul {$&ge; 2$}, $N/4$ au gradul {$&ge; 3$}, $n/8$ au gradul {$&ge; 4$}, etc. Pentru asta avem nevoie de o functie de alegere a gradului aleatoare cu probabilitate logaritmica. Putem face ceva simplu de genul:\r\n\r\n== code(cpp) |rang = 1\r\nwhile (rand() % 2 == 0) {\r\n    ++rang;\r\n}\r\n==\r\n\r\nFunctia de mai sus merge satisfacator. Eventual putem sa memoram cate nod-uri de fiecare grad sunt in lista (modificand adaugarea si stergerea), si sa returnam nivelul la care suntem cel mai departe de ideal, dar nu este necesar.\r\n\r\nMemorie este oarecum evident {$O(N)$}. Daca skiplist-ul ar fi complet echilibrat atunci vor exista $N$ link-uri de nivel {$0$}, {$N/2$} de nivel {$1$}, {$N/4$} de nivel {$2$}, etc. Cu putina matematica {$N + N/2 + N/4 + N/8.. = 2 * N$}, adica {$O(n)$}. Pentru cei care programeaza in pascal si nu vor sa se complice cu alocare de array-uri dinamice, memoria va fi evident $O(N log N)$\r\n\r\nh2. Skip Lists vs. AVL - Timpi de executie\r\n\r\nAm testat pe laptopul meu implementearea AVL (vezi \"acest articol\":http://infoarena.ro/multe-smenuri-de-programare-in-cc-si-nu-numai ) vs. Skiplists (vezi implementarea de mai jos). Laptopul este destul de performant, dar important este raportul dintre timpii de executie la AVL, respectiv Skiplists.\r\n\r\n|_. Numar de inserari |_. Numar de stergeri |_. Numar de Cautari |_. Timp Skiplists(1) |_. Timp AVL(2) |_. Raportul timpilor (2) / (1)|\r\n|1.000.000	|0	|0	|1.265	|2.656	|2.099604743|\r\n|1.000.000	|0	|1.000.000	|1.479	|2.672	|1.806626099|\r\n|1.000.000	|1.000.000	|0	|1.969	|4.797	|2.436262062|\r\n|1.000.000	|1.000.000	|1.000.000	|2.437	|4.85	|1.990151826|\r\n\r\nConcluzia: Skiplisturile sunt de 2 ori mai rapide decat AVL-urile.\r\n\r\n\r\nh2. Extinderi\r\n\r\nPe langa algoritmii de baza skip list permite imbogatiri care va permit multe alte lucruri cu timp minim de implementare si complexitate {$O(log N)$}. Cam toate imbogatirile structurii se bazeaza pe memorarea in paralel a unor informatii ajutatoare pt fiecare link (ATENTIE in pascal)\r\n\r\nAcces secvential: vrem sa accesam elementul pe pozitia {$i$}. Pentru aceasta vom memora pe fiecare link cate noduri \"acopera\", cu alte cuvinte cate noduri sare. Cautarea se modifica prin introducerea unei noi variabile care memoreaza indicele nodului curent, si prin comparare pozitie la care se sare in loc de cheia la care se sare. La inserare si stergere, trebuiesc actualizate toate linkurile din {$temp$}, deoarece si cele care indica peste codul curent contin informatii referitoare la el (il numara).\r\n\r\nIntervale: Tot ce trebuie sa adaugam, ca implementare, este o cautare in mod invers, care porneste de la nodul curent ({$START$}) si {$grad = 0$}, si \"urca\" pana cand {$grad > grad_max$}, sau {$link{~grad~} > END$} (nu exista un nod mai inalt intre inceputul si sfarsitul intervalului, dupa care trebuie sa coboare, ca la cautarea obisnuita... (eventual $START$ si $END$ necesita inserare in skiplist). Daca ati fost un pic atenti am parcurs toate link-urile care contin informatii despre intervalul curent. Pentru stabbing querys (avem un punct si ne intereseaza intervalele care le taie punctul respectiv) tot ce trebuie sa face este sa cautam in skiplist punctul respectiv si sa luam din $temp$ informatiile de la fiecare link.\r\n\r\n\r\nh2. Implementare completa\r\n\r\nVa prezint in continuare o implementare eleganta a skip lists-urilor cu cam tot ce ai putea avea nevoie in olimpiade: cautare dupa cheie si index, inserare, stergere, si posibilitatea de a calcula functiile Predecesor(node) si Succesor(node in O(1) cand ai node, pe care il gasesti in timp logaritmic. Vreau sa subliniez ca implementarea fara cautarea dupa index este cu mult mai simpla si scurta.\r\n\r\nNodul de baza contine in cazul de fata un integer pe post de informatie (info), dar puteti pune aici orice altceva, array-ul de dimensiune variabila de pointeri (link), o legatura catre elementul \"din spate\" (prev), si un array de dimensiune variabila de integeri (jump), in care tin minte pentru fiecare pointer din link \"cate elemente sare\" - folositor pentru accesul secvential.\r\n\r\n== code(cpp)|\r\nstruct _node\r\n{\r\n	int info;\r\n	struct _node **link, *prev;\r\n	int *jump;\r\n};\r\ntypedef struct _node Node;\r\n==\r\n\r\nProcedura de a afla inaltimea unui nod, cu un singur apel la funtia rand(). In H se tine minte nivelul curent maxim al listei, si o buna optimizare este sa nu introducem nivele mai mari decat H + 1, pentru o mai buna distributie a nodurilor pe nivele.\r\n\r\n== code(cpp)|\r\nint GetH()\r\n{\r\n	int h, r;\r\n	for (h = 0, r = rand(); r % 2; r >>= 1, h++);\r\n	if (h > H) h = H + 1;\r\n}\r\n==\r\n\r\nPentru a procesa Insert si Remove, vom tine un array de pointeri (path) pentru a indica ultimul nod de pe fiecare nivel obtinut in urma cautarii, precum si array-ul jumped, care ne spune \"cate noduri am sarit\" la fiecare nivel, precum si pointer catre inceputul listei (head) si inaltimea maxima a listei (H).\r\n\r\n== code(cpp)|\r\nNode *path[MAX_H], *head;\r\nint jumped[MAX_H], H;\r\n==\r\n\r\nSi restul functiilor, explicate pe scurt mai sus.\r\n\r\n== code(cpp)|\r\nint Lookup(int key)\r\n{\r\n	Node *node;\r\n	int i;\r\n\r\n	memset(jumped, 0, sizeof(jumped));\r\n	for (i = H+1; i < MAX_H; i++) path[i] = head;\r\n	for (node = head, i = H; i >= 0; i--)\r\n	{\r\n		for (; node->link[i] != NULL && node->link[i]->info < key; node = node->link[i])\r\n			jumped[i] += node->jump[i];\r\n		path[i] = node;\r\n	}\r\n	if (path[0]->link[0] != NULL && path[0]->link[0]->info == key) return 1;\r\n	else return 0;\r\n}\r\n\r\nNode* LookupByIndex(int index)\r\n{\r\n	Node *node;\r\n	int lvl;\r\n\r\n	node = head;\r\n	for (lvl = H; lvl >= 0 && index > 0; lvl--)\r\n		if (node->link[lvl] != NULL && node->jump[lvl] <= index)\r\n		{\r\n			index -= node->jump[lvl];\r\n			node = node->link[lvl];\r\n		}\r\n	if (index > 0) return NULL;\r\n	else return node;\r\n}\r\n\r\nvoid Insert(int key)\r\n{\r\n	if (Lookup(key)) return;\r\n\r\n	Node *node = MakeNode(key, 0);\r\n	int J, i;\r\n\r\n	if (path[0]->link[0] != NULL)\r\n		path[0]->link[0]->prev = node;\r\n	node->prev = path[0];\r\n	for (J = i = 0; i <= nodeH; i++)\r\n	{\r\n		node->link[i] = path[i]->link[i];\r\n		path[i]->link[i] = node;\r\n\r\n		node->jump[i] = path[i]->jump[i] - J;\r\n		path[i]->jump[i] = J + 1;\r\n\r\n		J += jumped[i];\r\n	}\r\n\r\n	for (i = nodeH + 1; i <= MAX_H; i++)\r\n		path[i]->jump[i]++;\r\n\r\n	if (nodeH > H) H = nodeH;\r\n}\r\n\r\nvoid Remove(int key)\r\n{\r\n	if (!Lookup(key)) return;\r\n\r\n	Node *node = path[0]->link[0];\r\n	int i;\r\n\r\n	if (node->link[0] != NULL)\r\n		node->link[0]->prev = path[0];\r\n	for (i = 0; i < MAX_H; i++)\r\n		if (path[i]->link[i] == node)\r\n		{\r\n			path[i]->link[i] = node->link[i];\r\n			path[i]->jump[i] += (node->jump[i] - 1);\r\n		}\r\n		else	\r\n			path[i]->jump[i]--;\r\n	delete node;\r\n}\r\n==\r\n\r\nPredecesorul si succesorul fiecarui nod se iau pur si simplu din node->prev, respectiv $node->link{~0~}$\r\n',2044,'public',3688,NULL),('utilizator/gabi_bobocel','Profil gabi_bobocel','2007-11-03 07:51:26','2007-11-03 07:51:26','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',7012,'public',NULL,NULL),('blog/sedinte-infoarena','Sedinte Infoarena','2007-11-03 08:29:02','2008-11-15 13:41:14','A inceput de ceva vreme anul scolar si ne-am hotartat sa ne organizam si sa punem osul la treaba. Astfel recent cei din \'echipa infoarena\':echipa-infoarena am avut doua sedinte in care am pus tara la cale.\r\n\r\nPentru ca siteul infoarena nu ar fi nimic fara comunitatea utilizatorilor ei, ne-am decis sa va informam  despre discutiile si deciziile luate:\r\n\r\nAu aparut cateva schimbari in echipa, astfel \'Andrei Grigorean\':utilizator/wefgef si \'Adrian Airinei\':utilizator/astronomy devin consilieri. Eu am devenit consilier (din consilier emeritus, ce insemna consilier fara activitate). Adrian Vladu a devenit consilier emeritus. \r\n\r\nS-a discutat despre concursul preONI 2008 pe care il va coordona Mircea. Formatul va fi acelasi ca si anul trecut cu patru runde si finala \"onsite\". Va incepe in luna noiembrie. Cristi va cauta sponsori.\r\n\r\nS-au definit mai clar rolurile membrilor, astfel eu ma voi ocupa de blog. De forum, calendar si  coordonarea concursurilor inafara de preOni se va ocupa Andrei. Silviu va fi responsabil de sectiunea cu articole ajutat de Catalin Tiseanu, si pe langa asta va fi implicat in cautarea de sponsori. Cristi se ocupa de comunitate, de newsletters si de implementarea comentariilor pentru blog. Adrian Diaconu si Daniel vor avea grija de arhiva de probleme. Valentin va munci pe partea proiectelor noi in comunitatea infoarena de la \'Implica-te\':implica-te . Leo se ocupa de partea de gestiune a banilor si va continua sa se ocupe ca si pana acum de evaluator. Iar Adrian Airinei va lucra pe partea de organizare a concursurilor.\r\n\r\nMircea si Leo au adus in discutie lucrul la infoarena 3.0 care presupune o rescriere a siteului. Deocamdata suntem in faza de discutii, iar Mircea si Leo ne vor arata la urmatoarea sedinta un \'design doc\':planificare/infoarena3 pentru a putea evalua mai bine ce avantaje si dezavantaje sunt in lucrul la un nou site.\r\n\r\nVa reamintesc ca avem proiecte interesante la sectiunea \'implica-te\':implica-te , unde ajutorul vostru e binevenit.\r\n\r\n',1490,'protected',2259,NULL),('runda/happy-2007/clasament','Clasament happy-2007','2007-11-03 11:06:09','2007-11-03 11:06:09','h1. Clasament ==roundparam(round_id=\"happy-2007\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"happy-2007\")==',961,'round: happy-2007',NULL,NULL),('utilizator/costel','Profil COstel','2007-11-03 19:22:05','2007-11-03 19:22:05','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',7023,'public',NULL,NULL),('blog/bloguri-microsoft','Blogurile Microsoft','2007-11-04 12:35:50','2008-11-15 13:41:14','Cautam de ceva vreme bloguri interesante legate de programare, si am dat la un moment dat peste  \'blogs.msdn.com\':http://blogs.msdn.com si peste studentclub.ro. Primele sunt bloguri ale unor angajati Microsoft si urmatoarele sunt bloguri ale unor studenti romani, membrii de organizatii studentesti asociate Microsoft. \r\n\r\nPe ambele platforme apar destul de des stiri despre noile si fascinantele tehnologii M$. Pe blogs.msdn.com sunt si multe posturi interesante si inteleg ca, din cand in cand, oamenii trebuie sa isi promoveze tehnologiile si chestiile la care muncesc. Ceea ce nu inteleg este promovarea aceluiasi gen de subiecte propagandistice de catre studenti. Cei care sunt interesati de asemenea chestii, oricum le pot lua direct de la sursa. Nu inteleg inca aceasta entuziasmare la tot ce e nou, si mi se pare o incercare nereusita de a parea la fel de cool ca fratii lor mai mari care lucreaza la M$.\r\n\r\nNu toate blogurile, sau toate posturile de pe studentclub sunt rele, dar multe care le-am vazut m-au lasat cu o impresie proasta. Exista si posturi foarte bune cum ar fi \'acesta\':http://www.hobeanu.com/roblog/?p=78 in care doi frati povestesc experienta lor la internship la Microsoft, din vara aceasta. Daca va uitati atent ii vedeti in poza pe \'Mircea Pasoi\':utilizator/domino si pe \'Tiberiu Florea\':utilizator/greco , care au fost si ei la internship la M$ peste vara.\r\n\r\n',1490,'protected',2264,NULL),('blog/ce-se-intampla-cu-olimpicii','Ce se intampla cu olimpicii?','2008-02-10 08:16:59','2008-11-15 13:41:14','Discutam mai demult cu \'Mihai Patrascu\':utilizator/mpatrascu si eram curiosi ce se intampla cu medaliatii romani la olimpiada internationala de informatica dupa terminarea liceului. Am pus o pagina wiki pe infoarena cu olimpici si datele s-au adunat imediat. Mihai spera ca prin obtinerea listei sa poata incuraja pe unii profesori de la MIT sa dea o importanta mai mare rezultatelor la concursurile de programare in procesul de admitere. Ideea era sa se gaseasca o corelatie intre obtinerea unor rezultate la olimpiade si facultatea urmata sau jobul dupa terminarea facultatii. Rezultatele obtinute le puteti vedea \'aici\':olimpici . Ele sunt un *set de date foarte interesante!* si ne dau o fereastra spre parcursul unor oameni interesanti. Insa nu putem trage concluzia dorita de Mihai, ca multi ajung sa aiba rezultate in cercetare. 22 din totalul de 58 de olimpici romani si moldoveni medaliati la olimpiada internationala de informatica lucreaza sau au facut un internship la Google.\r\n\r\nPot trage concluzia (putin trista) ca multi programatori foarte buni (nu doar olimpicii) prefera sa lucreze la o firma tare din strainatate in loc sa ramana in tara. Domeniul IT trebuie recunoscut ca unul de viitor si oamenii buni ar trebui incurajati sa ramana in Romania si sa puna osul la treaba.\r\n\r\nGasiti \'aici\':http://infoweekly.blogspot.com/2007/08/informatics-olympiads-end.html unul dintre cele cinci posturi scrise de Mihai pe tema destinelor olimpicilor.\r\n\r\n*shameless plug:* Daca esti un programator foarte bun sau daca cunosti programatori foarte buni care sunt interesati de un job la Google spuneti-le sa ma contacteze la cosminn ~ at ~ gmail.com. Si ca o paranteza finala, sunt foarte multi programatori extraordinari la Google care nu au avut in viata lor nici o treaba cu olimpiadele.',1490,'protected',2676,NULL),('blog/problema-saptamanii-2007-10-30-solutie','Problema saptamanii (Solutie)','2007-11-04 11:39:29','2008-11-15 13:41:14','\'Problema\':blog/problema-saptamanii-2007-10-30 a fost rezolvata de Mihai Patrascu, Radu Cebanu, Adrian Vladu, Marius Buzea, Marius Andrei, Adrian Carcu, Giurgea Mihnea, Liviu Ciortea, Adrian Sandor, Razvan Alecsandrescu, Igor Naverniouk si Csaba Patcas.\r\n\r\nLa prima vedere pare nerezolvabila, dar de fapt are o solutie destul de simpla. Ea se bazeaza pe faptul ca multimea ZxZ e numarabila. Putem verifica in fiecare secunda T cate o coordonata X0 + Y * T, parcurgand perechile (X0, Y) in spirala. Vom ajunge la un T1 pentru care teroristul este la locatia X0 + Y * T1. Inca nu am rezolvat problema, pentru ca pot exista mai multe perechi de numere pentru care teroristul sa fie la locatia X0 + Y * T1 in momentul T1. Prin faptul ca am gasit pozitia teroristului la un moment fixat T1, am redus problema la una noua determinata de parametrii X0\', Y\' in care in care nu il stim pe Y dar X0\' = X0 + Y * T1. Aceasta subproblema se poate rezolva usor.\r\n\r\nAlta problema cu teroristi ce mie imi place foarte mult este \'Lesbulan\':problema/lesbulan , ca dovada am si propus-o la concursul Bursele Agora.\r\n\r\nProbleme cu tema similara sunt si \'Soarecele si pisica\':http://probleme.francu.com/arhiva/R0042/enunt.html  (medie ca dificultate, de pe _Lista lu\' Francu_), \'Tom & Jerry\':problema/tj (grea, nu a facut-o nimeni din cate stiu eu cand a propus-o Mugurel la lot) si \'tunnels\':http://acmicpc-live-archive.uva.es/nuevoportal/data/problem.php?p=3811 (foarte grea, nu a facut-o nici o echipa in finala ACM ICPC 2006), \'smuggler\':http://brainyplanet.com/index.php/Smuggler?PHPSESSID=7100dbb47693d7b7fc0056ebd8035df0 (de pe rec.puzzles.org cu solutie). Daca sunteti curiosi de rezolvari, putem sa le discutam pe forum.\r\n\r\n',1490,'protected',2263,NULL),('blog/intrebare-scurta','Intrebare scurta','2007-11-04 15:41:14','2008-11-15 13:41:14','Cat e complexitatea ca timp a Ciurului lui Erastotene? Motivati raspunsul.\r\n\r\n*Update:* E interesant ca nu stim complexitatea unui algoritm pe care il invatam in clasa a 5-a. Ne gandim mai intai ca algoritmul trebuie sa fie mai rapid decat <tex>O(n^2)</tex>, pentru ca facem n pasi si fiecare pas e mai eficient decat o parcurgere a celor n numere. Daca ne uitam mai atent, numerele sunt parcurse pe sarite si numarul de operatii e <tex>n/2 + n/3 + n/4 + ... + n/n = n(1/2 + 1/3 + ... + 1/n)</tex>. Sirul <tex>1 + 1/2 + ... + 1/n - log\\ n</tex> este convergent, astfel deducem ca ciurul lui eratostene are complexitatea mai mica decat <tex>O(n\\ log\\ n)</tex>. Nu am folosit faptul ca in algoritm noi vom marca doar pornind de la valori prime, sarind peste multe valori, astfel numarul de operatii al algoritmului e <tex>n (1/2 + 1/3 + 1/5 + ... + 1/pk)</tex> unde pk e cel mai mare numar prim mai mic decat n. Sirul <tex>1 + 1/2 + 1/3 + 1/5 + ... + 1/pk - ln\\ ln\\ n</tex> e convergent dupa cum putem citi \'aici\':http://en.wikipedia.org/wiki/Meissel-Mertens_constant . Astfel complexitatea algoritmului _Ciurul lui Erstotene_ este <tex>O(n\\ log\\ log\\ n)</tex>.\r\n\r\nAm o alta intrebare pentru voi: Stiti cat e complexitatea algoritmului lui Euclid?\r\n\r\n',1490,'protected',2265,NULL),('blog/happy-coding-2007','Happy Coding 2007','2007-11-05 22:12:19','2007-11-07 10:55:01','Sunteti invitati sa participati la o noua editie a popularului (speram :) ) concurs Happy Coding. Perioada de desfasurare a concursului va fi *sambata, 10 noiembrie, ora 10:00 - duminica, 18 noiembrie, ora 24:00*. Cititi mai multe pe \'pagina concursului\':happy-coding-2007.',1,'protected',NULL,NULL),('propuneri/0-sistemul-iap','IAP #0: Sistemul IAP (infoarena Proposal)','2007-11-07 02:55:19','2007-11-28 16:26:13','h1. IAP #0: Sistemul IAP (infoarena Proposal)\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2007-11-07                             |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"wickedman\")== |\r\n|_. Stare     | *_APROBAT_* (2007-11-27)                     |\r\n\r\nh2. Abstract\r\n\r\nDocumentul descrie un proces de redactare si dezbatere de propuneri adresate \'Asociatiei infoarena\':asociatia-infoarena.\r\n\r\nFiecare propunere semnificativa (proiect, proces, politica) va fi redactata intr-un document _IAP_ (infoarena proposal) si supusa consiliului infoarena spre a fi votata.\r\n\r\nh2. Motivatie\r\n\r\ninfoarena se dezvolta in multe directii. Devine din ce in ce mai greu sa adunam toata echipa intr-un singur loc, sa dezbatem in viu grai si sa ajungem la un consens despre proiecte noi si schimbari _semnificative_. La momentul scrierii acestui IAP avem 4 consilieri infoarena care nu pot participa regulat la sedinte din motiv ca locuiesc in afara orasului Bucuresti sau chiar in afara tarii.\r\n\r\nSistemul IAP ne permite sa implicam toata echipa infoarena in luarea deciziilor. Fiecare consilier va studia propunerile pe cont propriu si va putea cere lamuriri sau oferi feedback prin email. Consilierii care nu se prezinta la sedinte pot vota prin email.\r\n\r\nIn plus, sper sa reducem durata sedintelor infoarena. Studiem individual propunerile si venim la sedinte cu intrebari pertinente si opinii formate.\r\n\r\n|_=. *Atentie! _Doar_ proiectele si schimbarile _semnificative_ necesita un IAP!* |\r\n\r\nh2. Anatomia unui IAP\r\n\r\nUn IAP propune \'Asociatiei infoarena\':asociatia-infoarena sa adopte un proiect semnificativ sau sa creeze / modifice politici si procese. Propunerile sunt adoptate sau respinse pe baza de vot.\r\nSubiectul unui IAP trebuie sa fie _semnificativ_ (termenul este vag in mod necesar) si suficient de bine explicat incat sa permita unui consilier infoarena sa ofere un vot educat.\r\n\r\nFiecare IAP are asociat un numar de ordine imutabil, alocat de catre un membru al echipei infoarena.\r\n\r\nFormatul unui document IAP _nu_ este strict definit dar trebuie sa contina macar urmatoarele elemente:\r\n\r\n# URL in format _propuneri/X-titlu-propunere_ (X este numarul de ordine)\r\n# Titlu in format _IAP #X: Titlu propunere_ (X este numarul de ordine)\r\n# Tabel header cu urmatoarele campuri:\r\n## Data: se va mentiona data inregistrarii numarului de ordine\r\n## Autor(i): de preferat cu link la pagina de profil\r\n## Stare: _*IN-CONSTRUCTIE*_ sau _*IN-DEZBATERE*_ sau _*APROBAT*_ sau _*RESPINS*_ sau _*INVALID*_\r\n*** Starea initiala a unui IAP este _*IN-CONSTRUCTIE*_\r\n*** La o schimbare de stare (i.e. se trece la _*IN-DEZBATERE*_ din _*IN-CONSTRUCTIE*_) se va specifica si data curenta.\r\n# Abstract: descrie foarte succint intreaga propunere\r\n# Motivatie\r\n\r\nh3. Rolul autorului / autorilor\r\n\r\nAutorul unui IAP redacteaza documentul, cere feedback (in mod privat sau in cadrul sedintelor) si ofera explicatii echipei infoarena. Numai dupa colectarea feedback-ului, se poate incepe dezbaterea si votarea unui IAP. Cu cat documentul IAP incorporeaza mai mult feedback din partea echipei infoarena, cu atat are sanse mai mari sa fie aprobat.\r\n\r\nSe recomanda ca autorul sa includa si o sectiune \"Discutii\" in IAP care sa prezinte sugestiile importante primite de la alte persoane.\r\n\r\nh3. Stare\r\n\r\nPot schimba starea unui IAP doar membrii activi ai echipei infoarena.\r\n\r\nIata semnificatia fiecarei stari IAP:\r\n\r\n* _*IN-CONSTRUCTIE*_: Autorul lucreaza la document sau incorporeaza feedback. Un autor poate fi rugat sa detalieze sau sa reconsidere anumite parti dintr-un IAP in urma unui proces de votare.\r\n* _*IN-DEZBATARE*_: Redactarea este finalizata. Propunerea asteapta voturi din partea \'echipei infoarena\':echipa-infoarena.\r\n* _*APROBAT*_: Propunerea a fost aprobata\r\n* _*RESPINS*_: Propunerea a fost respinsa definitiv, nu poate fi aprobata decat cu modificari majore.\r\n* _*INVALID*_: Autorul a abandonat redactarea propunerii sau documentul nu respecta formatul IAP. In general, un IAP va fi considerat invalid numai din motive tehnice. Orice propunere argumentata ajunge la votare.\r\n\r\nh2. Gestionarea propunerilor\r\n\r\nh3. Cum se creaza un IAP?\r\n\r\nAutorul unui IAP poate sa fie orice utilizator insa doar membrii \'echipei infoarena\':echipa-infoarena pot sa inregistreze numere de ordine IAP. Daca nu faci parte din echipa infoarena trebuie sa ceri un numar de ordine.\r\n\r\nh3.  Registrul IAP\r\n\r\nToate propunerile se centralizeaza \'aici\':propuneri.\r\n',13,'public',NULL,NULL),('blog/noutati','Noutati','2007-11-07 03:28:14','2008-11-15 13:41:14','Cativa reprezentanti Google au fost saptamana trecuta la Universitatea Bucuresti si la Politehnica. Au tinut niste seminarii si o serie de interviuri pentru internshipuri sau joburi. Puteti citi mai mult \'aici\':http://www.takemyview.com/blog/?p=65\r\n\r\nTrei studenti romani au participat saptamana trecuta la finala concursului TopCoder Collegiate Challenge desfasurata la Disney Land. Ei au fost \'Mircea Pasoi\':utilizator/domino (\'domino\':http://www.topcoder.com/tc?module=MemberProfile&cr=8362207) la concursul de algoritmica, Vlad Dumitriu (\'vlad_D\':http://www.topcoder.com/tc?module=MemberProfile&cr=13298470) la cel de webdesign si Lucian Lazar (\'Luca\':http://www.topcoder.com/tc?module=MemberProfile&cr=10348862) la concursul de software design. Felicitari pentru calificarea \"onsite\"! Mircea a reusit un rezultat foarte bun pentru Romania, calificandu-se in primii opt pe partea de algoritmi. Ultima data cand un roman reusise aceasta performanta a fost in 2004.\r\n\r\nConcursul \'Campion\':http://campion.edu.ro este o noua editie, iar anul acesta, datorita eforturilor lui \'Marius Andrei\':http://campion.edu.ro/team.php?id=6 si \'Liviu Valsan\':http://campion.edu.ro/team.php?id=4 , are un nou sistem de trimitere a solutiilor. Astfel sursele submitate sunt validate, fiind rulate mai intai prin niste teste simple. Acest sistem este similar cu cel da la Olimpiada Internationala si face ca unele greseli frecvente ale concurentilor care uitau detalii mici dupa un concurs intens sa fie corectate. Sa speram ca introducerea sistemului la concursul Campion este doar primul pas si ca el va fi folosit cat mai curand la olimpiedele judetene si nationale.\r\n\r\nInfoarena organizeaza a patra editie a concursului Happy Coding. Ideea initiala a concursului era sa fie unul in care se programeaza cu zambetul pe buze, fara presiunea din majoritatea concursurilor. Astfel evaluatorul solutiilor este pornit in timpul concursului, iar durata este mai lunga decat cea standard de cinci ore. Ii multumim lui Mugurel Andreica, care propune si de aceasta data problemele. Puteti citi mai mult despre concurs \'aici\':http://infoarena.ro/happy-coding-2007\r\n\r\nZilele astea infoarena a ajuns la peste 7000 de membrii inregistrati!\r\n\r\n',1490,'protected',2278,NULL),('preoni-2008/presa','preONI 2008 - Aparitii in presa','2007-11-08 01:54:11','2007-11-13 18:11:33','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. Aparitii in presa\r\n\r\np=. !{vertical-align:middle;}template/todo?progress.gif! _In curand..._\r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',1,'protected',NULL,NULL),('preoni-2008/runda-1','preONI 2008 - Runda 1','2007-11-08 02:17:03','2007-11-28 22:34:55','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. preONI 2008, Runda 1\r\n\r\n(htabs)*(active) \'Despre...\':preoni-2008/runda-1 \r\n* \'Clasele 5-8\':preoni-2008/runda-1/5-8 \r\n* \'Clasa a 9-a\':preoni-2008/runda-1/9 \r\n* \'Clasa a 10-a\':preoni-2008/runda-1/10 \r\n* \'Clasele 11-12\':preoni-2008/runda-1/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-1/5-8 \r\n\r\nRunda va incepe *Duminica 25 noiembrie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nAceeasi procedura se va urma la fiecare runda preONI. Timp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':preoni-2008/runda-1/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-1/10\r\n* \'Clasele 11-12\':preoni-2008/runda-1/11-12\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':preoni-2008/runda-1/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':preoni-2008/clasament/runda-1/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-1/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-1/11-12\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==User(user=\"domino\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n* ==User(user=\"filipb\" type=\"tiny\")==\r\n* ==User(user=\"ditzonec\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"cosmin\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"domino\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n* ==User(user=\"fluffy\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',1,'protected',NULL,NULL),('preoni-2008/runda-2','preONI 2008 - Runda 2','2007-11-08 02:17:41','2007-12-06 14:16:21','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. preONI 2008, Runda 2\r\n\r\n(htabs)*(active) \'Despre...\':preoni-2008/runda-2 \r\n* \'Clasele 5-8\':preoni-2008/runda-2/5-8 \r\n* \'Clasa a 9-a\':preoni-2008/runda-2/9 \r\n* \'Clasa a 10-a\':preoni-2008/runda-2/10 \r\n* \'Clasele 11-12\':preoni-2008/runda-2/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-2/5-8 \r\n\r\nRunda va incepe *Duminica 16 decembrie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nAceeasi procedura se va urma la fiecare runda preONI. Timp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':preoni-2008/runda-2/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-2/10\r\n* \'Clasele 11-12\':preoni-2008/runda-2/11-12\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':preoni-2008/runda-2/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':preoni-2008/clasament/runda-2/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-2/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-2/11-12\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==User(user=\"domino\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n* ==User(user=\"filipb\" type=\"tiny\")==\r\n* ==User(user=\"ditzonec\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"cosmin\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"domino\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n* ==User(user=\"fluffy\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',1,'protected',NULL,NULL),('preoni-2008/runda-3','preONI 2008 - Runda 3','2007-11-08 02:18:02','2008-02-11 15:49:21','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. preONI 2008, Runda 3\r\n\r\n(htabs)*(active) \'Despre...\':preoni-2008/runda-3 \r\n* \'Clasele 5-8\':preoni-2008/runda-3/5-8 \r\n* \'Clasa a 9-a\':preoni-2008/runda-3/9 \r\n* \'Clasa a 10-a\':preoni-2008/runda-3/10 \r\n* \'Clasele 11-12\':preoni-2008/runda-3/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-3/5-8 \r\n\r\nRunda va incepe *Duminica 20 ianuarie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nAceeasi procedura se va urma la fiecare runda preONI. Timp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':preoni-2008/runda-3/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-3/10\r\n* \'Clasele 11-12\':preoni-2008/runda-3/11-12\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':preoni-2008/runda-3/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':preoni-2008/clasament/runda-3/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-3/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-3/11-12\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"57\" count=\"25\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n* ==User(user=\"filipb\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"danielp\" type=\"tiny\")==\r\n* ==User(user=\"domino\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"domino\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n* ==User(user=\"fluffy\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',1,'protected',NULL,NULL),('preoni-2008/runda-4','preONI 2008 - Runda 4','2007-11-08 02:18:31','2008-02-11 15:49:34','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. preONI 2008, Runda 4\r\n\r\n(htabs)*(active) \'Despre...\':preoni-2008/runda-4 \r\n* \'Clasele 5-8\':preoni-2008/runda-4/5-8 \r\n* \'Clasa a 9-a\':preoni-2008/runda-4/9 \r\n* \'Clasa a 10-a\':preoni-2008/runda-4/10 \r\n* \'Clasele 11-12\':preoni-2008/runda-4/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-4/5-8 \r\n\r\nRunda va incepe *Duminica 17 februarie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nAceeasi procedura se va urma la fiecare runda preONI. Timp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':preoni-2008/runda-4/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-4/10\r\n* \'Clasele 11-12\':preoni-2008/runda-4/11-12\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':preoni-2008/runda-4/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':preoni-2008/clasament/runda-4/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-4/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-4/11-12\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"57\" count=\"25\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n* ==User(user=\"filipb\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"ditzonec\" type=\"tiny\")==\r\n* ==User(user=\"domino\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"domino\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n* ==User(user=\"fluffy\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',1,'protected',NULL,NULL),('preoni-2008/regulament','preONI 2008 - Regulament','2007-11-08 01:58:23','2007-11-25 12:02:04','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. Regulament\r\n\r\nSe recomanda, pe langa citirea acestui regulament, citirea \"regulamentului\":regulament general infoarena.\r\n\r\n\'Echipa infoarena\':echipa-infoarena isi rezerva dreptul de a modifica prezentul regulament pe parcursul desfasurarii concursului. Daca apar prevederi noi sau daca anumite prevederi ale regulamentului sunt modificate sau eliminate, atunci acestea vor fi anuntate pe site-ul concursului. Orice modificare a regulamentului va intra in vigoare, in functie de situatie, fie din momentul publicarii ei, fie dupa incheierea rundei aflate in desfasurare. In momentul anuntarii modificarii va fi precizat si momentul din care aceasta intra in vigoare.\r\n\r\nh2. Dreptul de participare\r\n\r\nPersoanele care fac parte din \'echipa infoarena\':echipa-infoarena cat si alti contribuitorii implicati direct in organizarea concursului *preONI 2008* nu au dreptul de a participa. De asemenea, orice concurent care are un comportament considerat inadecvat fata de echipa infoarena sau fata de alti concurenti va fi descalificat. Un concurent se poate califica la finala doar daca se incadreaza in grupa la care a concurat (aceasta verificare se va face prin prezentarea unei dovezi legale care il incadreaza pe concurent la aceea grupa).\r\n\r\nh2. Repartizarea\r\n\r\nToti participantii vor fi repartizati in *4* grupe, in concordanta cu varsta lor. Repartizarii este asemanatoare cu aceea facuta la olimpiadele de informatica.\r\n\r\n* Gimnaziu{*^beta^*} (clasele 5-8) \r\n* Clasa a 9-a \r\n* Clasa a 10-a\r\n* Clasele 11-12 \r\n\r\nOricine poate participa la o alta grupa decat cea la care se incadreaza, dar calificarea la finala cat si impartirea premiilor se va face conform regulamentului respectiv, fara nici o exceptie.\r\n\r\nh2. Inscriere\r\n\r\nTot ce trebuie sa faceti pentru a participa la concursul *preONI 2008* este sa aveti un cont la infoarena. Inregistrarea se poate face pe site-ul infoarena. Acelasi cont va fi folosit pentru a accesa forum-ul.\r\n\r\nh2. Runde\r\n\r\nVor exista 4 runde de calficare, iar in urma clasamentului stabilit primii de la fiecare grupa vor fi selectati pentru etapa finala desfasurata in cadrul unei tabere. Cele 4 runde vor avea loc sambata si duminica, incepand cu ora 9:00, desi pot interveni exceptii. Durata lor va fi de 4 ore. Pentru un program detaliat al concursului \"click aici\":preoni-2008/program.\r\n\r\nh2. Intrebari\r\n\r\nIn prima ora vor putea fi formulate eventualele intrebari, pe forum, in topicurile special create. Orice intrebare pusa in alt mod (primita ca personal message, pe mail, etc.) va fi ignorata. Raspunsuri vor fi oferite doar la intrebarile puse in prima ora . Intrebarile trebuie formulate astfel incat sa se poate raspunda cu _DA_ sau _NU_. In caz contrar sau in cazul in care raspunsul se afla in textul problemei se va raspunde cu _NO COMMENT_. Nu vor exista exceptii de la aceaste reguli. Daca echipa va considera ca raspunsul la o anumita intrebare este de interes general si clarifica anumite aspecte, atunci se va face un anunt general care va aparea atat pe forum cat si in sectiunea Mesaje de la organizatori a grupei respective. Fiecare grupa va avea doi administratori care se vor ocupa de raspunsul acestor intrebari.\r\n\r\nh2. Trimiterea solutiilor\r\n\r\nTrimitrea solutiile se va face prin intermediul interfetei site-ului infoarena.\r\nOdata logati in contul vostru, veti putea selecta arhiva la care doriti sa lucrati (in cazul acesta una din arhivele {*preONI 2008*}) si veti putea folosi link-ul trimite solutii.\r\n\r\nh2. Evaluare\r\n\r\nDupa expirarea timpului de trimitere a solutiilor acestea vor fi evaluate (\"mai multe detalii aici\":documentatie/evaluator). In mod normal, evaluarea se va face imediat dupa concurs, desi exista posibilitatea ca echipa infoarena sa amane evaluarea din motive obiective. Veti putea vizualiza pozitia ocupata in clasament dupa evaluarea in rubrica Clasament.\r\n\r\nSe recomanda sa instalati pe calculatorul vostru aceleasi versiuni de compilatoare ca cele specificate la link-ul de mai sus. \'Echipa infoarena\':echipa-infoarena nu este responsabila pentru diferentele intre versiuni de compilatoare si nu va efectua reevaluaari in astfel de cazuri.\r\n\r\nh2. Contestatii\r\n\r\nEchipa infoarena isi rezerva dreptul de a reevalua orice problema in situatia in care se detecteaza erori in teste sau in programul de verificare dupa evaluare. Cum testele problemelor nu vor fi facute publice, posiblitatile de a contesta sunt limitate. Pentru a asigura o evaluarea corecta, echipa infoarena va garanteaza ca va testa intens toate problemele inainte de concurs si ca va verifica corectitudinea procesului de evaluare dupa terminare. In caz ca totusi aveti o contestatie, aceasta trebuie trimisa pe mail la adresa _mircea.pasoi -at- gmail.com_ in termen de 24 de ore de la afisarea rezultatelor rundei curente pe site. Ele vor fi rezolvate in termen de maxim 5 zile, iar dupa rezolvarea lor rezultatele vor fi declarate finale.\r\n\r\nh2. Solutii\r\n\r\nLa scurt timp dupa terminarea evaluarii se va publica un articol cu solutiile pentru problemele rundei respective. Testele utilizate pentru evaluare nu vor fi facute publice.\r\n\r\nh2. Transferul problemelor\r\n\r\nProblemele vor fi mutate dupa evaluare in \'Arhiva de probleme\':arhiva infoarena, avand astfel la dispozitie un evaluator 24 din 24 si posiblitatea de a finisa solutiile la problemele nerezolvate in timpul concursului.\r\n\r\nh2. Trisare\r\n\r\n*preONI 2008* este un concurs individual, asadar orice tentativa de colaborare va aduce descalificarea celor implicati. \'echipa infoarena\':echipa-infoarena isi rezerva dreptul de a verifica sursele concurentilor, iar in caz ca se descopera surse aproximativ identice, concurentii respectivi vor fi descalificati din concurs iar user-ul lor de pe infoarena eliminat. Tentativele de frauda (concurarea sub un alt nume decat cel adevarat, etc.) sau orice atac asupra sistemului de evaluare sau asupra paginilor infoarena vor fi pedepsite in aceeasi masura. \r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',1,'protected',NULL,NULL),('preoni-2008/comisie','preONI 2008 - Organizatori','2007-11-08 02:10:48','2008-11-30 14:31:01','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. Organizatori\r\n\r\n\'Echipa infoarena\':echipa-infoarena se ocupa de organizarea si desfasurarea concursului *preONI 2008*.\r\n\r\nh2. Organizare \r\n\r\n* == user(user=\"domino\" type=\"tiny\") == : coordonator concurs\r\n* == user(user=\"wickedman\" type=\"tiny\") == : fonduri, sponsori, presa\r\n* == user(user=\"fluffy\" type=\"tiny\") == : coordonator tehnic (site-ul, evaluatorul etc.)\r\n\r\nh2. Echipa stiintifica\r\n\r\nCei care se vor ocupa de buna desfasurarea a concursului din punct de vedere stiintific (redactarea si compunerea problemelor, realizarea testelor, clarificarea intrebarilor, etc.) sunt:\r\n\r\n* == user(user=\"domino\" type=\"tiny\") ==\r\n* == user(user=\"Cosmin\" type=\"tiny\") ==\r\n* == user(user=\"ditzoneC\" type=\"tiny\") ==\r\n* == user(user=\"filipb\" type=\"tiny\") ==\r\n* == user(user=\"danielp\" type=\"tiny\") ==\r\n* == user(user=\"wefgef\" type=\"tiny\") ==\r\n* == user(user=\"astronomy\" type=\"tiny\") ==\r\n\r\nh2. Multumim\r\n\r\n* &hellip; lui == user(user=\"vlad_d\" type=\"tiny\") == pentru logo-ul preONI 2008 si tuturor celor care au venit cu sugestii de logo pe \'forum\':forum/index.php?topic=2206.0\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',2028,'protected',NULL,NULL),('preoni-2008/clasament','preONI 2008 - Clasament','2007-11-08 02:21:59','2007-11-13 18:16:12','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. Clasament \r\n\r\n(htabs)*(active) \'Pe runde...\':preoni-2008/clasament\r\n* \'Clasele 5-8\':preoni-2008/clasament/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/11-12\r\n\r\ntable(layout). |_. Clasament Runda 1 |_. Clasament Runda 2 |\r\n|* \'Clasele 5-8\':preoni-2008/clasament/runda-1/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-1/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-1/11-12 \r\n|* \'Clasele 5-8\':preoni-2008/clasament/runda-2/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-2/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-2/11-12|\r\n|_. Clasament Runda 3 |_. Clasament Runda 4|\r\n|* \'Clasele 5-8\':preoni-2008/clasament/runda-3/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-3/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-3/11-12\r\n|* \'Clasele 5-8\':preoni-2008/clasament/runda-4/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-4/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-4/11-12|\r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',1,'protected',NULL,NULL),('preoni-2008/clasament/5-8','preONI 2008 - Clasament general, Clasele 5-8','2007-11-08 18:37:31','2007-11-13 18:18:55','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. Clasament clasele 5-8\r\n\r\n(htabs)* \'Pe runde...\':preoni-2008/clasament\r\n*(active) \'Clasele 5-8\':preoni-2008/clasament/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/11-12\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda1-5-8|preoni2008-runda2-5-8|preoni2008-runda3-5-8|preoni2008-runda4-5-8\") == \r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',1,'protected',NULL,NULL),('preoni-2008/clasament/10','preONI 2008 - Clasament general, Clasa a 10-a','2007-11-08 22:46:43','2007-11-13 18:19:39','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. Clasament clasa a 10-a\r\n\r\n(htabs)* \'Pe runde...\':preoni-2008/clasament\r\n* \'Clasele 5-8\':preoni-2008/clasament/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/9\r\n*(active)  \'Clasa a 10-a\':preoni-2008/clasament/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/11-12\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda1-10|preoni2008-runda2-10|preoni2008-runda3-10|preoni2008-runda4-10\") == \r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',1,'protected',NULL,NULL),('preoni-2008/clasament/11-12','preONI 2008 - Clasament general, Clasele 11-12','2007-11-08 22:47:44','2007-11-13 18:20:33','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. Clasament clasele 11-12\r\n\r\n(htabs)* \'Pe runde...\':preoni-2008/clasament\r\n* \'Clasele 5-8\':preoni-2008/clasament/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/10\r\n*(active) \'Clasele 11-12\':preoni-2008/clasament/11-12\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda1-11-12|preoni2008-runda2-11-12|preoni2008-runda3-11-12|preoni2008-runda4-11-12\") == \r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',1,'protected',NULL,NULL),('planificare/sedinta-20071107','Sedinta 2007-11-07','2007-11-05 17:46:26','2007-11-14 07:27:28','h1. Sedinta 2007-11-07\r\n\r\n_ora 18:00, locatie: La Cafenescu_\r\n\r\nh2. Participanti\r\n\r\n* Cristian George Strat\r\n* Silviu Ganceanu\r\n* Mircea Pasoi\r\n* Crestez Leonard\r\n* Valentin Stanciu\r\n* Andrei Grigorean\r\n* Adrian Diaconu\r\n\r\nh2. Agenda\r\n\r\n* Update colaborari cu Adobe:\r\n** sponsorizari pentru concursuri noi\r\n** sposorizare preONI 2007-2008; Ne trebuie un schelet cu cheltuielile pentru preONI sa vedem la ce se baga Adobe (Mircea?)\r\n* \'Sistemul IAP (infoarena Proposal)\':propuneri\r\n** \'IAP #0: Sistemul IAP (infoarena proposals)\':propuneri/0-sistemul-iap\r\n** \'IAP #1: Concurs \"hackaton\"\':propuneri/1-hackaton\r\n** \'IAP #2: Concurs de informatica pentru studenti\':propuneri/2-concurs-studenti\r\n* \'infoarena 3.0\':planificare/infoarena3\r\n* \'preONI 2008\':planificare/preoni-2008\r\n* forum (reguli, restructurat, calendar, macro calendar)\r\n* pagina de roluri in planificare\r\n* cine se ocupa de wiki? Avem nevoie de un \'wikignome\':http://en.wikipedia.org/wiki/Wikipedia:WikiGnome\r\n* Probleme cu server-ul de hosting\r\n** running out of disk space\r\n** altceva?\r\n* Probleme in cod:\r\n** optional latex\r\n** update DB snapshot\r\n\r\n* Fundraising:\r\n** \'prezentare infoarena pentru sponsori\':planificare/sponsori\r\n\r\nh2. Rezolutii\r\n\r\nh3. Restante\r\n\r\n* Vali scrie rolurile in pagina de echipa ({%{color:red}done%})\r\n* Mircea face macro care afiseaza numarul de comentarii ({%{color:red}done%})\r\n* Cristi se uita la SMF API de afisat post-uri, nu doar titlu\r\n\r\nh3. Noi\r\n\r\n* Mircea face buget pentru preONI 2008 ({%{color:red}done%}) si vine cu noi la sedinta Adobe de luni (12 nov) la 11:00\r\n* Fiecare membru al echipei va citi IAP #0 si isi va exprima votul intr-o pagina wiki de sedinta\r\n* Feedback la concurs pentru studenti:\r\n** Cum probam piata?  De unde stim ca vom avea participanti?\r\n** Runda de practice?\r\n** Cum propagam vestea in universitatile din tara\r\n* Silviu renunta la rolul de manager articole\r\n* Silviu primeste rolul de comunitate (de la Cristi) iar Cristi primeste rolul de fund raising (de la Silviu)\r\n* Silviu ii invita pe Skipy ({%{color:red}done%}) si Tiseanu la urmatoarea sedinta pentru rolul de articole\r\n* Silviu le invita pe Sasa si Claudia la urmatoarea sedinta pentru cartea lu Francu + alte roluri ({%{color:red}done%})\r\n* Adi invita pe Mugurel la urmatoarea sedinta pentru incorporare in echipa ({%{color:red}done%})\r\n* Feedback la concurs \"hackaton\"\r\n** Rasplatim firmele pentru implicare in concurs, indiferent de cum se califica\r\n** Distributiile aleatorii par sa nu domine rezultatele concursului\r\n* Mircea schimba runda 2 cu o saptamana mai devreme ({%{color:red}done%})\r\n* wefgef: Pe pagina de regulament de forum trebuie specificat ca este de forum (sa nu se inteleaga ca e regulamentul site-ului)\r\n* Fluf face revert la pagina de regulament ({%{color:red}done by mircea; thanks dude!%})\r\n* wefgef scrie IAP #4 despre restructurarea forum-ului\r\n* Cristi cere mai mult spatiu pe HDD si mai mult RAM pe server ({%{color:red}done%}_: avem 13/20 GB liberi si min-800 max-1024 MB RAM. In plus, Sergiu a facut partitie separata de swap pentru ca a observat ca noi folosim swap._)\r\n* Fluf scrie IAP #3 despre infoarena 3 ({%{color:red}done%})\r\n* Fluf trebuie sa elaboreze \'IAP #3\':propuneri/3-infoarena3: ({%{color:red}done%})\r\n** man in charge ({%{color:red}done%})\r\n** dev process ({%{color:red}done%})\r\n*** code review\r\n*** testing\r\n*** release management & QA\r\n** de ce tichetele nu inseamna nimic? ({%{color:red}done%})\r\n** reuse wiki / blog / forum? ({%{color:red}done%})\r\n** scalabilitate orizontala pe front-end & evaluator\r\n** REST, infoarena API\r\n** internationalizare (strings)\r\n** macro-uri mult mai destepte, extensibile si user-definable\r\n** split plan: dezvoltare ia2 & ia3 in paralel ({%{color:red}done%})\r\n** Propunere alternativa: C++ libinfoarena cu interfata programata in Python ({%{color:blue}alt IAP%})\r\n** integrare forum ({%{color:red}done%})\r\n** motor cautare ({%{color:blue}reuse%})\r\n\r\nh3. Note\r\n\r\n* Vrem sa afisam calendarul in sidebar',1142,'public',NULL,NULL),('propuneri/1-hackaton','IAP #1: Concurs \"hackaton\"','2007-11-06 17:18:39','2008-02-18 10:21:22','h1. IAP #1: Concurs \"hackaton\"\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2007-11-07                             |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"wickedman\")== ==User(type=\"tiny\" user=\"silviug\")== |\r\n|_. Stare     | *_IN-CONSTRUCTIE_*                     |\r\n\r\nh2. Abstract\r\n\r\nSe propune organizarea de concursuri onsite de programare si lucru in echipa pentru studenti si profesionisti IT - in genul EESTEC-AXWAY.\r\n\r\nLa fiecare concurs participa ~10 echipe formate aleator din cate 2 studenti calificati si un profesionist IT. Echipele astfel formate trebuie sa dezvolte o tema pe parcursul a ~12h. Evaluarea se face numai pe baza de criterii masurabile (i.e. timp de executie, acuratete, scor).\r\n\r\nh2. Motivatie\r\n\r\ninfoarena isi va extinde baza de utilizatori studenti si isi va crea legaturi cu industria IT organizand un concurs inedit si cu impact pozitiv atat pentru studentii participanti cat si pentru companiile IT care se implica.\r\n\r\nNoutatea acestui tip de concurs este ca echipele se formeaza din cate 2 studenti si un om din industrie, cu rol de tech lead. Concursul presupune lucrul in echipe create ad-hoc, schimb de experienta, management si, bineinteles, aptitudini de programare & informatica.\r\n\r\nh2. Mod de desfasurare\r\n\r\n\r\n|_. Deocamdata colectam feedback. Sugestiile sunt bine venite. |\r\n\r\n\r\nDesfasurarea unui \"hackaton\" se poate imparti in 3 mari etape.\r\n\r\nh3. 1. Racolare de tech leads\r\n\r\nSe contacteaza mai multe companii sau profesionisti IT. Cautam 10-15 oameni curajosi, cu experienta si vointa care sa joace rolul de tech leads in fiecare echipa.\r\n\r\nPot participa mai multi tech leads de la aceeasi firma, profesori sau freelanceri cu experienta.\r\n\r\nh3. 2. Preselectie online pentru studenti\r\n\r\nOrganizam un concurs de informatica scurt, cu probleme usoare-medii si selectam studentii cu cele mai bune rezultate. Numarul de studenti variaza in functie de cati tech leads am reusit sa racolam. Daca unii tech-leads se retrag intre timp, un numar corespunzatori de studenti cu cele mai slabe rezultate la preselectie vor fi eliminati.\r\n\r\nh3. 3. Proba de concurs\r\n\r\n* \"Hackatonul\" se desfasoara la sediul unei companii IT.\r\n* Se formeaza echipe in mod aleatoriu.\r\n* Timp de lucru: ~12h (din experienta EESTEC-AXWAY, un timp de lucru de 24h e o idee proasta).\r\n* Fiecare echipa are acces la un singur calculator.\r\n\r\nh2. Tema concursului\r\n\r\nAvem libertatea sa alegem teme foarte variate (bots pentru jocuri, motoare de cautare, arhivatoare, euristici etc.) desi pentru unele va trebui sa scriem evaluatoare sau framework-uri.\r\n\r\n*Evaluarea* se va face intotdeauna in functie de un criteriu obiectiv precum timp de executie, acuratete, scor, corectitudine etc. Nu vom dam note pe aprecieri de genul algoritmi folositi, design, calitate cod etc.\r\n\r\nh2. Posibile neajunsuri\r\n\r\nh3. Sincronizare studenti <-> tech leads\r\n\r\nSa presupunem ca profesionistii IT au viata, cel putin mai mult decat un student obisnuit. Gasim tech-leads dispusi sa lucreze 12h sau sa isi piarda un week-end intreg cu un astfel de concurs?\r\n\r\nh3. Tech leads participa in numele firmei\r\n\r\nOare angajatii sunt reticienti sa participe in numele firmei lor? Cum vor fi vazuti in compania lor daca se intorc cu un rezultat \"rusinos\", de exemplu ultimul loc? Nu ar sta mai bine cuminti acasa? Firmele sunt dispuse sa-si \"sustina\" angajatii intr-o astfel de competitie?\r\n\r\nh4. Sugestie\r\n\r\nPutem elimina \"presiunea\" asupra unui tech lead rasplatind companiile participante indiferent de rezultatul obtinut.',15,'public',NULL,NULL),('template/iap','template/iap','2007-11-09 09:59:24','2008-02-04 20:58:03','table{margin:0.5em auto;}. |={background-color:rgb(241, 245, 252); border: 0; padding: .5em; -moz-border-radius: 10px}. !{vertical-align:middle; float: left}template/iap?star.png! Aceasta pagina descrie o \'propunere pentru echipa infoarena\':propuneri. Informatiile prezentate aici nu reprezinta planuri oficiale ale \'Asociatiei infoarena\':asociatia-infoarena decat daca propunerea este adoptata. |\r\n',1,'protected',NULL,NULL),('regulament','Regulament','2007-11-09 20:47:41','2007-11-09 20:48:23','h1. Regulamentul _infoarena_\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nIn afara de regulile de bun simt, pe care nu le scriem aici, la infoarena nu sunt prea multe restrictii...\r\n\r\n# *Distrati-va cat mai mult!* Faceti cunostinta cu alti oameni care va impartasesc interesele.\r\n# Castigati cat mai multe premii la concursurile gazduite aici.\r\n# Nu incercati sa trisati! Nu este distractiv. In plus, se penalizeaza cu descalificare.\r\n# Nu adaugati continut ofensiv pe paginile infoarena sau pe pagina personala\r\n\r\n',1,'public',NULL,NULL),('template/preoni-2008','template/preoni-2008','2007-11-08 01:14:52','2007-12-06 17:25:45','==include(page=\"template/preoni-2008/header\")==\r\n\r\n(vmenu)*(section) \'*preONI 2008*\':preoni-2008\r\n* \'Clasament\':preoni-2008/clasament\r\n* \'Organizatori\':preoni-2008/comisie\r\n* \'Sponsori si premii\':preoni-2008/premii\r\n* \'Regulament\':preoni-2008/regulament\r\n* &nbsp;\r\n* \'Runda 1\':preoni-2008/runda-1\r\n* \'Runda 2\':preoni-2008/runda-2\r\n* \'Runda 3\':preoni-2008/runda-3\r\n* \'Runda 4\':preoni-2008/runda-4\r\n* \'Runda Finala\':preoni-2008/runda-finala\r\n',1,'protected',NULL,NULL),('blog/comentarii','Comentarii','2007-11-10 05:24:14','2008-11-15 13:41:14','\'Mircea\':utilizator/domino a bagat un feature nou. De acum avem un count la numarul comentariilor de la fiecare post, ca toate blogurile respectabile, nu vivi? ;)\r\n\r\n',1490,'protected',2330,NULL),('happy-coding-2007/probleme','Happy Coding 2007, Probleme','2007-11-10 09:35:55','2007-11-22 21:39:28','h1. Happy Coding 2007     !happy-coding-2007?hc2007-logo.gif!\r\n\r\n(htabs)* \'Despre Happy Coding\':happy-coding-2007\r\n*(active) \'Probleme\':happy-coding-2007/probleme\r\n* \'Clasament\':happy-coding-2007/clasament\r\n\r\nh2. Probleme de rezolvat\r\n\r\n== Tasks(round_id=\"happy-2007\" score=\"1\")==\r\n\r\nh2. Clarificari pe forum\r\n\r\n==SmfTopics(board_id=\"56\" count=\"25\")==\r\n',2028,'protected',NULL,NULL),('blog/captchauri-pentru-matematicieni','CAPTCHAuri pentru matematicieni','2007-11-11 03:07:15','2008-11-15 13:41:14','Sunt interesante CHAPTCHAurile bazate pe matematica. Ele pe langa ca pot diferentia intre oameni si calculatoare, pot separa si oameni pe diverse nivele de abilitati matematice.\r\n\r\nCateva exemple:\r\n\r\n2 + 2 = ?\r\n\r\n!blog/captchauri-pentru-matematicieni?captcha.jpg!\r\n\r\n!blog/captchauri-pentru-matematicieni?captcha1.gif!\r\n\r\n',1490,'protected',2333,NULL),('blog/problema-saptamanii-20071110','Problema saptamanii','2007-11-11 04:57:07','2008-11-15 13:41:14','_A venit din nou timpul pentru problema saptamanii. Va propun o problema interesanta ce mi-a zis-o colegul meu de clasa Radu Cebanu acum vreo trei ani._\r\n\r\nSe dau doua puncte A si B. Exista doua drumuri(curbe infinit de subtiri) intre ele si aceste drumuri au proprietatea ca doua mobile punctiforme legate cu o sfoara de lungime 10 m pleaca din A si ajung in B fara a rupe sfoara. Nu exista vreo restrictie asupra miscarii mobilelor, decat ca ele se deplaseaza fiecare pe unul din drumuri. De exemplu viteza lor poate fi diferita, ele pot sa se miste chiar in sensul opus de la B la A, sau un mobil poate sta pe loc in timp ce al doilea se misca. Avem doi roboti in forma de discuri de raza 5 metri, unul cu centrul in A si celalalt cu centrul in B. Intrebarea este daca acesti roboti pot folosi cele doua drumuri pentru a ajunge din A in B si respectiv din B in A, fara a se ciocni. Robotii se misca fiecare cu centrul discului pe unul din drumuri.\r\n\r\n_Va reamintesc ca puteti folosi formul pentru clarificari ale enuntului, si mesajele private pentru solutii complete. Have fun!_\r\n\r\n',1490,'protected',2334,NULL),('runda/pregatire_brasov_oni','pregatire_brasov_oni','2010-03-10 16:48:53','2010-03-10 16:48:53','h1. == roundparam(round_id=\"pregatire_brasov_oni\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"pregatire_brasov_oni\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"pregatire_brasov_oni\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"pregatire_brasov_oni\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"pregatire_brasov_oni\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/pregatire_brasov_oni/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"pregatire_brasov_oni\" score=\"1\")==',6305,'round: pregatire_brasov_oni',NULL,NULL),('template/preoni-2008/header','template/preoni-2008/header','2007-11-08 01:10:19','2008-11-20 18:31:11','p{margin: 2em 0 1em 0; padding: .5em; border: 1px solid silver; -moz-border-radius: 10px;}. !>preoni-2008?adobe.png 13%!:http://myadobe.ro !template/preoni-2008/header?a.jpg!:/preoni-2008\r\n\r\n',1490,'protected',NULL,NULL),('runda/preoni2008-runda1-5-8/clasament','Clasament preoni2008-runda1-5-8','2007-11-13 16:36:16','2007-11-13 16:36:16','h1. Clasament ==roundparam(round_id=\"preoni2008-runda1-5-8\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda1-5-8\")==',1,'round: preoni2008-runda1-5-8',NULL,NULL),('runda/preoni2008-runda1-9/clasament','Clasament preoni2008-runda1-9','2007-11-13 16:37:48','2007-11-13 16:37:48','h1. Clasament ==roundparam(round_id=\"preoni2008-runda1-9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda1-9\")==',1,'round: preoni2008-runda1-9',NULL,NULL),('runda/preoni2008-runda1-10/clasament','Clasament preoni2008-runda1-10','2007-11-13 16:38:35','2007-11-13 16:38:35','h1. Clasament ==roundparam(round_id=\"preoni2008-runda1-10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda1-10\")==',1,'round: preoni2008-runda1-10',NULL,NULL),('preoni-2008/runda-1/11-12','preONI 2008 - Runda 1, Clasele 11-12','2007-11-13 16:41:10','2007-11-13 18:12:53','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda1-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-1 \r\n* \'Clasele 5-8\':preoni-2008/runda-1/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-1/9 \r\n* \'Clasa a 10-a\':preoni-2008/runda-1/10 \r\n*(active) \'Clasele 11-12\':preoni-2008/runda-1/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-1/5-8\r\n\r\n== roundregister(round_id=\"preoni2008-runda1-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda1-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda1-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-1/11-12.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"preoni2008-runda1-11-12\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',1,'round: preoni2008-runda1-11-12',NULL,NULL),('runda/preoni2008-runda1-11-12/clasament','Clasament preoni2008-runda1-11-12','2007-11-13 16:41:10','2007-11-13 16:41:10','h1. Clasament ==roundparam(round_id=\"preoni2008-runda1-11-12\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda1-11-12\")==',1,'round: preoni2008-runda1-11-12',NULL,NULL),('preoni-2008/runda-1/5-8','preONI 2008 - Runda 1, Clasele 5-8','2007-11-13 16:36:16','2007-11-13 18:12:24','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda1-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-1 \r\n*(active) \'Clasele 5-8\':preoni-2008/runda-1/5-8 \r\n* \'Clasa a 9-a\':preoni-2008/runda-1/9 \r\n* \'Clasa a 10-a\':preoni-2008/runda-1/10 \r\n* \'Clasele 11-12\':preoni-2008/runda-1/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-1/5-8\r\n\r\n== roundregister(round_id=\"preoni2008-runda1-5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda1-5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda1-5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-1/5-8.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"preoni2008-runda1-5-8\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',1,'round: preoni2008-runda1-5-8',NULL,NULL),('preoni-2008/runda-1/9','preONI 2008 - Runda 1, Clasa a 9-a','2007-11-13 16:37:48','2007-11-13 18:12:34','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda1-9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-1 \r\n* \'Clasele 5-8\':preoni-2008/runda-1/5-8\r\n*(active) \'Clasa a 9-a\':preoni-2008/runda-1/9 \r\n* \'Clasa a 10-a\':preoni-2008/runda-1/10 \r\n* \'Clasele 11-12\':preoni-2008/runda-1/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-1/5-8\r\n\r\n== roundregister(round_id=\"preoni2008-runda1-9\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda1-9\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda1-9\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-1/9.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"preoni2008-runda1-9\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',1,'round: preoni2008-runda1-9',NULL,NULL),('preoni-2008/runda-1/10','preONI 2008 - Runda 1, Clasa a 10-a','2007-11-13 16:38:35','2007-11-13 18:12:42','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda1-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-1 \r\n* \'Clasele 5-8\':preoni-2008/runda-1/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-1/9 \r\n*(active) \'Clasa a 10-a\':preoni-2008/runda-1/10 \r\n* \'Clasele 11-12\':preoni-2008/runda-1/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-1/5-8\r\n\r\n== roundregister(round_id=\"preoni2008-runda1-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda1-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda1-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-1/10.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"preoni2008-runda1-10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',1,'round: preoni2008-runda1-10',NULL,NULL),('preoni-2008/clasament/runda-1/9','preONI 2008 - Clasament Runda 1, Clasa a 9-a','2007-11-13 18:00:22','2007-11-13 18:13:27','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda1-9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-1\r\n* \'Clasele 5-8\':preoni-2008/runda-1/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-1/10\r\n* \'Clasele 11-12\':preoni-2008/runda-1/11-12\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-1/5-8\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':preoni-2008/clasament/runda-1/5-8\r\n*(active) \'Clasa a 9-a\':preoni-2008/clasament/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-1/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-1/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda1-9\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2008/clasament/runda-1/5-8','preONI 2008 - Clasament Runda 1, Clasele 5-8','2007-11-13 18:03:51','2007-11-13 18:13:14','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda1-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-1\r\n* \'Clasele 5-8\':preoni-2008/runda-1/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-1/10\r\n* \'Clasele 11-12\':preoni-2008/runda-1/11-12\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-1/5-8\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasele 5-8\':preoni-2008/clasament/runda-1/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-1/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-1/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda1-5-8\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('template/preoni-2008/clasament-header','template/preoni-2008/clasament-header','2007-11-13 18:04:22','2007-11-13 18:04:22','&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;',1,'protected',NULL,NULL),('preoni-2008/clasament/runda-1/10','preONI 2008 - Clasament Runda 1, Clasa a 10-a','2007-11-13 18:07:51','2007-11-13 18:13:51','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda1-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-1\r\n* \'Clasele 5-8\':preoni-2008/runda-1/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-1/10\r\n* \'Clasele 11-12\':preoni-2008/runda-1/11-12\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-1/5-8\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':preoni-2008/clasament/runda-1/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-1/9\r\n*(active) \'Clasa a 10-a\':preoni-2008/clasament/runda-1/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-1/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda1-10\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2008/clasament/runda-1/11-12','preONI 2008 - Clasament Runda 1, Clasele 11-12','2007-11-13 18:09:03','2007-11-13 18:14:08','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda1-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-1\r\n* \'Clasele 5-8\':preoni-2008/runda-1/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-1/10\r\n* \'Clasele 11-12\':preoni-2008/runda-1/11-12\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-1/5-8\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':preoni-2008/clasament/runda-1/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-1/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-1/10\r\n*(active) \'Clasele 11-12\':preoni-2008/clasament/runda-1/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda1-11-12\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2008/clasament/9','preONI 2008 - Clasament general, Clasa a 9-a','2007-11-08 22:45:10','2007-11-13 18:19:05','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. Clasament clasa a 9-a\r\n\r\n(htabs)* \'Pe runde...\':preoni-2008/clasament\r\n* \'Clasele 5-8\':preoni-2008/clasament/5-8\r\n*(active) \'Clasa a 9-a\':preoni-2008/clasament/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/11-12\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda1-9|preoni2008-runda2-9|preoni2008-runda3-9|preoni2008-runda4-9\") == \r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',1,'protected',NULL,NULL),('propuneri/3-infoarena3','IAP #3: Infoarena3','2007-10-27 13:31:34','2008-02-20 00:22:18','h1. IAP #3: Infoarena3\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2007-11-08                              |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"fluffy\")==     |\r\n|_. Stare     | *_IN-DEZBATERE_* Propus pentru aprobare |\r\n\r\nh2. Abstract\r\n\r\nPe scurt, codul din spatele site-ului infoarena2 este intr-o stare foarte proasta si trebuie rescris. Pagina aceasta incearca sa explice in detalii problemele din cod, si incearca sa demonstreze ca rescrierea soft-ului este cel mai bun mod de a avansa site-ul.\r\n\r\nIn sedinta din \'24 octombrie\':planificare/sedinta-20071024 eu ( ==user(user=\"fluffy\")== ) am fost insarcinat sa scriu aceasta pagina. In urma sedintei din \'7 noiembrie\':planificare/sedinta-20071107 s-a decis sa reformulam aceasta pagina sub \'format IAP\':propuneri. Propunerea a fost discutata si au venit cateva observatii din partea lui ==User(user=\"wickedman\")==\r\n\r\nAm pus si un \'topic pe forum\':forum/index.php?topic=2243.0, dar pana acum feedback-ul a fost sub asteptari.\r\n\r\n*Update:* Propun sa votam pe idea de a rescrie site-ul in python si sa aprobam acest IAP. Propunerea a devenit mult prea lunga si nu cred ca e practic sa intram in prea multe detalii de arhitectura. Daca o aprobam putem sa copiem bucati in planificare/development si sa facem IAP-uri pentru alte idei majore. Nimic din ce am scris nu ramane batut in cuie.\r\n\r\nh2. Motivatie\r\n\r\nSite-ul infoarena1 a fost scris acum vreo 4-5 ani de Cristi pentru a fi prezentat la InfoEducatie, un concurs de soft de la Galaciuc. Site-ul era foarte impresionant si a castigat concursul 2 ani la rand. Mai mult, site-ul era atat de bun incat a intrat in \"productie\" si a reusit sa adune o comunitate in jurul lui. Comunitatea a produs un numar impresionant de probleme si concursuri iar infoarena a devenit un loc de adunare pentru olimpicii romani.\r\n\r\nMult timp soft-ul din spatele site-ului a ramas aproape identic cu ce a venit Cristi la Galaciuc; s-au facut doar niste fix-uri absolut necesare. Am incercat sa punem pe picioare un \'site de development\':http://hackers.devnet.ro/ si sa bagam codul in subversion dar nimeni nu s-a atins de cod. Au crescut inca niste lucruri *pe langa* infoarena1; un \"portal editabil\" de informatica, un forum si o integrare urata cu \'MediaWiki\':http://www.mediawiki.org/. Eventual am ajuns la concluzia ca nu se poate face nimic in infoarena1 si trebuie rescris totul de la 0.\r\n\r\nIn vara lui 2006 ne-am adunat 5-6 flacai, ne-am dus in munti si ne-am incuiat in casa ca sa facem infoarena2 (multumim din nou lui Vali pentru logistica). Intre noi il aveam doar pe Cristi cu o oarecare experienta in web-development (php/mysql), in rest eram in cea mai mare parte incepatori. Site-ul nu a fost terminat acolo in munti si a fost nevoie de un numar de \"coding camp\"-uri pentru a pune site-ul pe picioare. Eventual site-ul a ajuns la nivelul de functionalitate din infoarena1, si a fost lansat spre sfarsitul lui 2006. Parti de genul editarea de runde/probleme si suportul de concursuri (foarte importante) au fost finalizate abia in 2007.\r\n\r\nSoftul infoarena2 este evident mult mai bun decat infoarena1. Asta se poate vedea cel mai bine in calitatea si dimensiunile site-ului. Numarul de probleme din arhiva este mai mult decat dublu, si a devenit posibil pentru comunitatea site-ului sa \'ne ajute\':implica-te mult mai mult.\r\n\r\nDin pacate dezvoltarea la site-ul infoarena2 a stagnat de multa vreme. Au mai fost tentative de CodingCamp-uri si chiar s-au adaugat \'feature-uri noi\':blog, dar progresul este mult prea incet. Exista multe cauze pentru aceasta stagnare, dar eu (Leonard) consider ca problema principala este este calitatea codului. Infoarena2 este un soft complicat si incurcat in care este mult prea dificil sa faci modificari, iar asta scade motivatia developerilor.\r\n\r\nPutem sa incercam niste \"boost-uri\" de motivare prin CodingCamp-uri dar scopul este sa avem un grup de indivizi care lucreaza de acasa in timpul lor liber. Pentru asta trebuie ca programarea sa fie usoara si distractiva, iar in infoarena2 nu este cazul. Soft-ul nostru este mult mai \"frumos\" decat multe produse comerciale, dar la infoarena2 nu exista motivatia financiara (si nici nu vrem sa existe).\r\n\r\nh2. Ce a mers prost in infoarena2\r\n\r\nPe parcursul dezvoltarii infoarena2 noi (Cristi, Leonard, Mircea, Vali, etc...) am facut un numar de greseli majore la care acum simtim efectele. Daca am incepe din nou programarea la proiectul infoarena3 nu am face din nou aceleasi greseli si rezultatul ar fi mult mai bun. Daca stim care au fost gresile si cum sa le evitam nu vom ajunge din nou in aceasi situatie.\r\n\r\nPoate parea trist ca aruncam la gunoi aproape un an de efort, dar nu este cazul. Vom pastra tot continului site-ului, care valoreaza enorm (si asta tine de fapt infoarena.ro in viata). Vom pastra lectiile infoarena2, care sunt mult mai valoroase decat codul php. Daca am fi alti oameni care am rescrie codul probabil ca am face aceleasi prostii, si atunci ar mai bine sa ne tinem de treaba la infoarena2.\r\n\r\nAm facut o lista cu ce anume am gresit in infoarena2 si cum putem face mai bine (in infoarena3). Este posibil sa reparam multe dintre probleme fara o rescriere, dar nu toate. Multe dintre aceste greseli vizeaza arhitectura fundamentala a site-ului. Acestea nu pot fi reparate decat printr-un efort enorm, iar acel efort cumulat ar fi mai mare decat o rescriere de la 0.\r\n\r\nh3. PHP\r\n\r\nInfoarena2 este un site traditional bazat pe php/mysql si foarte putin javascript. Nu folosim clase si nici exceptii din php. In mod similar nu folosim decat tabele MyISAM in MySQL, fara foreign key-uri, constraint-uri, view-uri sau tranzactii. Pentru layout nu folosim nici un sistem de templating, doar html presarat cu snippet-uri php. Infoarena2 foloseste absolut minimumul de tehnologie posibil pentru un proiect web-based.\r\n\r\nAceasta decizie fost facuta in vara 2006 pentru a face site-ul simplu si usor de programat. Ne-am gandit ca sunt mai multi oameni care stiu si vor sa lucreze cu php/mysql procedural decat cu orice altceva. Este discutabil daca sunt mai multi oameni interesati in php decat in python sau ruby, cel putin dintre utilizatorii nostri. Probabil ca multi ar fi tentati sa ajute la un proiect care foloseste feature-uri avansate de limbaj absente in C/C++/Pascal (si PHP). Dar oricum nu am reusit sa bagam pe nimeni din exterior in echipa de development. Mai mult, am ajuns in situatia in care nici noi nu mai vrem sa programam in php/mysql, sau cel putin nu in modul in care este folosit in infoarena2. PHP este un limbaj foarte util pentru multe lucruri, dar pentru infoarena2 nu a functionat.\r\n\r\nh3. Tabelul ia_parameter_values\r\n\r\nUna dintre tintele infoarena2 a fost sa avem mai multe tipuri de runde si probleme. Deoarece fiecare tip de runda sau de problema are alti \"parametri\", ne-am gandit sa tinem toti acei parametri intr-un sigur tabel de forma \"id-obiect\", \"nume-parametru\", \"valoare\". Este o idee foarte proasta care nu are absolut nici un merit. Acest tabel si gandirea din spatele lui a facut codul de runde si probleme sa devina mult mai complicat decat este necesar, si a avut consecinte absolut infioratoare:\r\n\r\n* Editorul de task-uri si runde a intarziat si e greu utilizabil.\r\n* Securitatea per task/runda este un hack mizerabil.\r\n* *Nu avem* mai multe tipuri de probleme si concursuri (scopul original).\r\n* Rundele inca nu ruleaza automat.\r\n\r\nAr trebui sa avem pentru fiecare tip de problema sau runda un tabel de genul ia_classic_task, care contine o coloana task_id si apoi cate o coloana pentru fiecare parametru. Asta este o solutie acceptabila pentru o baza de date. Eu (Leonard) am incercat aceasta transformare dar *nu am reusit* (din cauza repercursiuni in restul site-ului). Consider ca inlocuirea acestui tabel e mai dificila decat rescrierea de la 0.\r\n\r\nh3. Tabelul ia_score\r\n\r\nTabelul ia_score are coloanele: score_id, user_id, task_id, round_id si score (aproximativ). Primele 4 coloane sunt sunt nulabile, asa ca tabelul nu poate avea PK. Ideea era sa tinem scoruri per runda cu task_id NULL si eventual statistici per task/round cu user_id NULL. Astfel puteam sa tinem toate scorurile in acelasi tabel. Din pacate *nu a mers* si am ajuns in situatia de a avea chiar mai putine statistici decat in infoarena1. Asta cred ca este singurul punct in care infoarena1 *depaseste* infoarena2.\r\n\r\nAcest tabel ar trebui spart in mai multe tabele fara coloane nulabile, si fara oroarea de score_id.\r\n\r\nTabelele ia_score si ia_parameter value sunt niste greseli majore si grosonale care demonstreaza ignoranta in design-ul bazelor de date. Noi am pornit pe idea fundamental gresita de a \"economisi\" numarului de tabele din baza de date. Este similar cu a economisi numarul de functii dintr-un program facand copy-paste la cod, sau numarul de struct-uri folosind void* si aritmetica explicita de pointeri.\r\n\r\nh3. Id-uri VARCHAR (64)\r\n\r\nId-urile pentru utilizatori sunt numere, dar restul sunt VARCHAR (64) cu niste validari facuta in cod prin regex-uri. Ar fi mai bine sa avem toate id-urile drept numere, spre exemplu task_id int si task_name string. task_name se poate obtine foarte usor din task_id adaugand un join trivial.\r\n\r\nMySQL *nu* face \'index pe hash-uri\':http://dev.mysql.com/doc/refman/5.1/en/create-index.html pentru tabele pe disc (doar pentru tabele din memorie). MySQL sorteaza id-urile alfabetic tinand cont de colatii (latin2 pentru noi). Tinand string-uri peste tot crestem dimensiunile tabelelor, iar asta este oribil pentru performanta tabelelor de genul ia_score sau ia_job. Aici s-ar merita de facut niste teste de performanta. Spre exemplu putem compara un tabel de scor exclusiv numeric cu unul plin de string-uri.\r\n\r\nh3. Tabele de wiki: ia_textblock, ia_textblock_history, ia_file.\r\n\r\nUltima versiune a unei pagini de wiki se tine in ia_textblock, iar versiunile precedente se tin in ia_textblock_history cu aceasi structura. Asta inseamna ca orice fel de istorie are nevoie de query-uri complicate folosind UNION. Ar trebui sa tinem un singur tabel, eventual cu un tabel aditional care duplica doar datele cele mai recente.\r\n\r\nAtasamentele sunt un sistem complet distict, sunt fisiere pe disc sub-ordonate unui textblock din baza de date. Manipularea atasamentelor este FOARTE neplacuta, si pot aparea desincronizari in diverese locuri. Securitatea atasamentelor depinde de cea a textblock-urilor (si indirect a problemelor) in moduri complicate si imprevizibile. Ar fi mai bine sa avem un singur suport de \"BLOB-uri\" versionate.\r\n\r\nNu avem suport de redenumire si stergere care sa pastreze istoria, si nici o idee simpla de design care ar permite asa ceva in baza de date. Trebuie investigat daca se poate folosi subversion in loc de MySQL pentru fisiere versionate.\r\n\r\nh3. Securitatea si magia din wiki\r\n\r\nPe parcursul dezvoltarii infoarena2 ne-am dorit sa evitam pe cat posibil functionalitatea \"magica\" din wiki, si am mers prea departe. Am pornit de la idea ca orice pagina este o pagina de wiki, si paginile de probleme/useri/runde/news/blog sunt doar un caz oarecare de pagina wiki. Securitatea paginilor de probleme trebuie totusi sa fie subordonata problemelor. Noi am realizat asta adaugand un \"descriptor de securitate\" ca string pentru fiecare pagina de wiki. Pagina problema/adunare are la securitate un string \"task: adunare\", si asa vizibilitatea paginii depinde de vizibilitatea task-ului. Este un sistem prea generic, incurcat si greu de folosit sau extins.\r\n\r\nAr fi mai bine ca orice url de forma problema/xxx sa intre prin controller-ul de task-uri, care isi subordoneaza textblock-urile care incep cu problema/xxx. Similar am avea controllere de news, blog, user page care subordoneaza tot ce incepe cu stiri, blog sau utilizator/yyy. Pentru restul paginilor am avea un controler *distinct* de wiki. Codul pentru bucatile de editare si istorie a textblock-urile poate fi refolosit in 1000 de moduri. *Nu* este acceptabil sa nu poti ajunge de la editarea de enunt la editarea limitei de timp fara sa modifici in address bar.\r\n\r\nAm avea tabele ia_news, ia_blog_post si ia_wiki care sunt \"deasupra\" lui ia_textblock, iar ia_textblock ar fi folosit doar pentru versionarea unor bucati de text. Securitatea private/protected/public (care este *foarte* utila si absolut ok) poate fi un simplu enum in ia_wiki. Acel enum trebuie editat folosind un simplu dropdown.\r\n\r\nEfortul necesar pentru o astfel de transformare fundamentala in infoarena2 mi se pare iarasi absolut enorm.\r\n\r\nh3. Layer de logica\r\n\r\nInfoarena2 pretinde ca foloseste o arhitectura MVC, dar MVC este o notiunea prea larga si vag definita. Nu este interesanta o discutie detaliata asupra ce inseamna MVC, asa ca voi discuta doar ce se foloseste efectiv in site-ul infoarena2.\r\n\r\nUrl-urile sunt parsate in index.php si in functie de o logica complicata si nu foarte interesanta fiecare request http este pasat la un \"controller\". Un controller este o functie php din www/controllers. Acel controller face ceva cu requestul, de obicei niste query-uri in baza da date, si apoi constrieste un hash de \"date pentru afisat\" care il trimite la un view.\r\n\r\nView-urile nu sunt functii, sunt fisiere .php din www/views. Executia unui view este o operatie sinucigasa, care se trimite direct pe teava. Nu se poate executa cod dupa un view. Fisierul de view se executa folosind continutul hash-ului de data ca variabile globale. In acel view se poate folosi textile, care poate executa macro-uri care(de obicei) se duc iar pana in baza. Asta inseamna ca poti sa te duci in baza dupa executia controller-ului, dar nu mi se pare nimic rau in asta. Macro-urile sunt efectiv niste mini-controllere.\r\n\r\nProblema este ca noi din controllere ne ducem direct in baza si logica fragila de genul securitate este imprastiata intre functiile de UI si de DB. Este riscant (error-prone) sa combini logica site-ului cu parsarea requestului sau construirea query-ului. Aceasta problema are o rezolvare destul de clara si larg acceptata in industrie, de care noi nu stiam in vara lui 2006.\r\n\r\nIntre codul de controller (UI) si codul de baza de data (DB) se mai pune niste cod de \"business logic\" (BL). Tot ce inseamna parsarea request-ului se face in UI si tot ce inseamna contruirea de SQL se face in DB. BL contine de fapt tot codul cu adevarat interesant pentru functionarea corecta a site-ul. Codul de DB nu trebuie sa aiba grija decat sa construiasca query-uri (si sa evite sql injection) iar codul de UI se ocupa de a vedea ce butoane a apasat utilizatorul.\r\n\r\nUnul dintre avantajele majore este ca se pot scrie usor teste pentru BL. Daca BL-ul nu are greseli atunci UI-ul nu poate sa strice nimic in baza (doar experienta utilizatorului). Apeland functii doar de BL este mult mai usor sa verifici corectitudinea unui macro sau controller.\r\n\r\nh3. Testele pe baza de curl\r\n\r\nPHP este un limbaj foarte fragil, unde este foarte usor sa faci greseli grosolane. Asta este o problema generica a limbajelor dinamice de genul php, python, ruby, javascript fata de limbajele de genul C, C++, C# si java. In limbajele dinamice sa fie mult mai important sa testezi codul. Multe lucruri prinse de un compilator de C++ scapa pana in browser folosind PHP.\r\n\r\nTeste curente sunt facute pe baza de \'curl\':http://www.php.net/curl, o librarie de access HTTP. Testele construiesc un request complet http pe care il trimit pe fir, asteapta ca apache sa raspunda, si apoi verifica niste chestii din request. Contruirea requestului se face folosind \'array\':http://www.php.net/manual/en/function.array.php, si verificarile se face cu functii de genul preg_match si strstr. Ambele faze sunt greu de facut, dar avantajul acestui sistem ca testeaza tot codul si este foarte \"realist\".\r\n\r\nPentru a usura testarea am facut controllerele noastre de editare sa accepte un parametru de form absent drept \"nu vreau sa editez acest parametru\". Asta este foarte util in teste dar e un comportament artifical care a \"nascut\" niste bug-uri foarte urate. In retrospectiva a fost o idee proasta, care a introdus o cuplare oribila intre controllere si codul de test. Ambele sunt acum foarte greu de modificat.\r\n\r\nAr fi mai bine sa testam functii BL care nu au nici o treaba cu HTTP. Daca BL-ul este ok atunci sigur bug-urile din UI nu pot sa strice nimic in baza. UI-ul se poate testa apoi de mana, sau folosind ceva de genul \'selenium\':http://www.openqa.org/selenium/.\r\n\r\nh3. Caching exagerat\r\n\r\nInfoarena2 suporta mai multe forme de caching:\r\n\r\n* Cache de textile parsat, inainte de executia macro-urilor. Majoritatea request-urilor nu executa codul de textile.\r\n* Cache de imagini redimensionate. Cand se cere o imagine redimensionata ea este salvata pe disc si se evita operatiile de grafica pentru avatari etc.\r\n* Cache de obiecte din baza de date, folosind memcached sau eaccelerator. Acest cache tine obiecte de genul useri, task-uri si runde.\r\n\r\nAcest ultim mod de caching are inclusiv suport de write-through (cand se salveaza un obiect se sterge varianta din cache) care a fost foarte complex de implementat. Codul de cache este bagat prin multe functii db_ si nu este deloc usor de inteles. Se combina cod de DB, BL si caching in aceleasi functii.\r\n\r\nSuportul de write-through nu este de fapt foarte util pentru ca evaluatorul si partea de web nu folosesc acelasi cache. Eventual am fost fortati sa facem rundele sa traiasca doar 5 secunde in cache. Acest caching nu imbunatateste mult timpul de raspuns: Am masurat de mult timpii de raspuns cu si fara cache la paginile de enunt si diferentele erau nesemnificative. Acest mod de caching complica prea mult codul si nu aduce nimic folositor.\r\n\r\nh3. Interfata utilizator.\r\n\r\nIn infoarena2 nu exista nici un mod definitiv de face construi un form sau un tabel. Exista mai multe sisteme prin cod dar nici unul nu functioneaza definitiv. Avem tabele paginate ca macro-uri, dar sunt niste hack-uri destul de urate. Avem doua moduri \"inteligente\" de construit tabele (format_table si dataset-uri) dar unele sunt facute de mana. Avem un sistem de form-uri automate (pentru ia_parameter_values), dar este folosit doar partial si e foarte limitat. Nu avem un mod simplu si standard de face escape in html.\r\n\r\nIn general fiecare a facut cum l-a taiat capul. Pe toti ne-a taiat cam stramb.\r\n\r\nh2. Organizare pentru infoarena3\r\n\r\nMulte dintre probleme infoarena2 au aparut din cauze non-tehnice, si anume dintr-un proces de dezvoltare haotic. Am adunat niste idei pentru cum putem lucra mai eficient.\r\n\r\nh3. Folosim branch-uri\r\n\r\nIn infoarena2 nu am \'folosit eficient branch-uri\':http://producingoss.com/en/vc.html#branches. Absolut toate modificarile le-am facut direct in trunk iar asta nu este o idee buna. Exista mereu schimbari mari care au nevoie de mai multe commit-uri pentru a fi complet functionale. Astfel de schimbari trebuie facute intai intr-un branch special si abia apoi copiate (cu svn merge) in trunk. Asta face trunk-ul sa fie mai stabil si sa nu mai contina \"cod mort\".\r\n\r\nUn branch poti sa faci oricand daca ai access subversion, fara sa intrebi pe nimeni. Intr-un branch este OK sa experimentezi cu absolut orice fara sa-ti faci griji ca strici site-ul pentru altii. Cand consideri ca este gata de copiat in trunk poti sa chemi pe cineva sa se uite peste modificari. Modificarile pot fi acceptate in trunk, sau pot aparea observatii si branch-ul poate fi respins. Daca un branch este respins poti sa ii rezolvi problemele si sa il propui din nou pentru includere in trunk.\r\n\r\nNe dorim sa punem doar modificari aproximativ atomice in trunk, care sa nu introduca bug-uri. Este in continuare OK sa punem bugfix-uri si tweak-uri minore de CSS direct in trunk. Branch-urile sunt necesare pentru feature-uri de genul blog, latex, array_validate, dataset-uri, caching, tag-uri, etc.\r\n\r\nh3. Responsabilitati\r\n\r\nCodul infoarena este open-source, iar oamenii lucreaza doar in timpul lor liber. Dar daca vrei sa ajuti infoarena atunci trebuie sa te tii de treaba si sa rezolvi tichetele pana la o anumita data. Bineinteles ca nu avem cum sa fortam pe nimeni sa lucreze la infoarena, dar se presupune cine vrea sa ne ajute nu vrea sa frece menta. \r\n\r\nUn tichet \"acceptat\" trebuie sa aiba un owner care este responsabil sa rezolve acel tichet pana la o anumita data. Un deadline nu inseamna \"ar fi frumos sa avem #123 rezolvat pana luna viitoare\". Un deadline inseamna ceva de genul \"eu rezolv #124 pana maine si #125 poimaine\". Astfel de deadline-uri functioneaza ca o motivatie suplimentara.\r\n\r\nAsta este foarte similar cu sistem-ul mare de roluri din \'echipa infoarena\':echipa-infoarena, care pare sa functioneze destul de bine. Pe langa dead-line-uri per-tichet vom avem si un om care se ocupa de development in mod global, care acum este ==user(user=\"fluffy\")==. *TODO:* de detaliat ce face dev lead?\r\n\r\nh3. Milestone-uri semnificative\r\n\r\nMilestone-urile din infoarena2 au fost foarte foarte confusing. Am impartit tichetele vag dupa prioritati, si le-am pus in milestone-uri, dar nu ne-am tinut de treaba. Cu cat un tichet era mai naspa si infricosator cu atat l-am pus undeva in viitor. Daca nimeni nu isi asuma responsabilitatea pentru un tichet atunci acel tichet nu va fi facut, indiferent de milestone-ul in care e pus.\r\n\r\nPropun sa avem 2 tipuri de milestone-uri:\r\n\r\n* Time-based, care incrementeaza versiunea cu _0.0.1_. Acolo punem tichete pentru care stim ca avem oameni sa le faca intr-un interval de timp relativ scurt. Le vom sincroniza aproximativ cu sedintele asociatiei sau cu rundele de concurs.\r\n* Feature-based, care incrementeaza versiunea cu _0.1_. Acolo punem tichete majore, care merita o incrementare a versiunii. Cand gasim oameni mutam tichetele in _+0.0.1_. Cand ramanem fara tichete intr-un astfel de milestone ii facem release.\r\n\r\nh3. Quality Asurrance\r\n\r\nNoi am rulat in mare parte site-ul direct din trunk si am avut de multe ori bug-uri mari pe site-ul live. Motivul principal a fost ca sa nu stagnam development-ul prin birocratie excesiva. Este totusi destul de riscant si neprofesional sa rulam direct din trunk. \r\n\r\nPutem sa avem un site special de development pe trunk, dar care este marcat explicit pentru testing. Site-ul poate sa sa se updateze singur la ultimul trunk si sa ruleze teste automate folosind un dataset redus (pentru a minimiza efectele unei gauri de securitate). Scripturile necesare nu sunt deloc greu de scris. Ramanem totusi la idea de a rula din svn, nu are sens sa facem o procedura separata de upgrade/deployment.\r\n\r\nNoi avem o singura instanta care este in productie la orice moment. Asta inseamna ca nu are sens sa mentinem branch-uri separate stabile sau instabile. Noi nu facem \"release-uri\" publice in sensul standard si e posibil ca layout-ul standard subversion sa nu fie foarte util. Propun sa ne facem un layout custom:\r\n\r\n* branches/more-ajax: Sandbox-uri pentru schimbari majore\r\n* trunk/: Bleeding edge. De aici rulam site-ul de test. Bugs welcome!\r\n* release/infoarena-3.1.7: De aici rulam site-ul live. Facem commit cu multa grija.\r\n* external/smf-2.1.9: Pentru pachete externe care au nevoie de merge; echivalent vendor.\r\n\r\nCand stabilizam copiem ultimul trunk in release/ si testam un pic (o saptamana) pana e stabil. Abia dupa asta migram live pe ultimul release, si facem doar fix-uri pentru bug-uri majore. Ideal ar fi sa nu scriem in release dupa ce migram site-ul live.\r\n\r\nh3. Cum alegem tehnologie\r\n\r\nDe multe ori s-a discutat ca infoarena sa folosesca o anume librarie avansata sau framework. Folosirea unei librarii externe este o decizie majora care trebuie analizata cu grija. O dependinta externa trebuie sa satisfaca urmatoarele conditii:\r\n\r\n* Sa fie simplu de inclus. Sa existe macar pachete debian si fedora; sau sa poata fi copiata direct in svn. *Nu* se accepta installere din afara distributiilor de linux.\r\n* Sa ne ajute cu ceva major care ar fi foarte greu sa facem de la 0.\r\n* Sa fie cunoscuta si dezvoltata activ. Altfel probabil ca respectiva librarie nu e foarte buna.\r\n* Sa nu impuna restrictii asupra arhitecturii site-ului. Asta elimina cam toate framework-urile.\r\n* Scalabil, testabil, etc.\r\n\r\nMai mult, cine propune o dependinta trebuie sa dovedeasca ca indeplineste toate conditiile de mai sus. Putem sa facem asta prin tichete speciale de \"investigare\". Individul responsabil de un asemenea tichet trebuie sa invete tehnologia respectiva si sa ne ajute sa decidem daca merita folosita. Rezultatul unui asemenea tichet este un demo, care poate fi un branch sau o chestie from-scratch. Acel demo trebuie sa demonstreze viabilitatea respectivei tehnologii, dar nu trebuie sa fie neparat imediat utilizabil in trunk.\r\n\r\nIdei de demo-uri:\r\n\r\n* Wiki extern: putem folosi wiki din exterior si construi site-ul peste el?\r\n* \'SqlAlchemy\':http://www.sqlalchemy.org: De facut o schema sql alchemy pentru tabelele de scoruri. Cat de usor se fac query-uri de statistici si cat de rapide sunt?\r\n* \'Selenium\':http://www.openqa.org/selenium/: Cineva sa faca niste teste folosind Selenium peste infoarena2. Cum anume pot fi stocate in svn si rulate de oricine?\r\n* Form-uri: Nu avem o solutie definitiva pentru facut si validat form-uri. Cineva sa ia o asemenea librarie si sa faca CRUD de task-uri, si sa demonstreze ca e sensibil mai usor decat manual.\r\n* Tabele: Demo de tabel de scoruri prin AJAX. Cristi: this means you.\r\n* BL prin HTTP: Se poate face un BL accesibil direct prin http, fara a scrie controllere pentru fiecare functie? Poate evaluatorul sa acceseze functii de BL de pe live, fara access TCP la baza de date?\r\n* Wiki in subversion: Ar avea sens sa tinem textblock-uri si atasamente in subversion? Demo de manipulare cu teste de viteza.\r\n\r\nProbabil ca aceste demo-uri vor fi de fapt formulate sub forma de IAP-uri. Momentan inca nu am decis exact ce tehnologie folosim in infoarena3. Vom incepe sa facem IAP-uri doar cand structura de baza a site-ului este functionala\r\n\r\nh2. Arhitectura infoarena3\r\n\r\nCa sa evitem probleme tehnice din infoarena2 ne trebuie un o arhitectura clara si solida pe care sa putem construi. Trebuie sa evitam a ne \"infunda\" din nou. Acum nu avem inca nici un fel de cod scris si totul poate fi schimbat foarte usor.\r\n\r\nh3. Python ca limbaj de programare\r\n\r\nPropun sa scriem infoarena3 in python. Este un limbaj foarte OK pentru programarea web, cu multe librarii disponibile. Este recunoscut pentru a fi foarte foarte curat si a incuraja un stil frumos de cod. Avem oameni disponibili sa programeze in python.\r\n\r\nEste foarte dificil sa faci o alegere desteapta intre limbaje de programare, atat de dificil incat majoritatea discutiilor pe acest subiect sunt neproductive. Noi am dat cu banul si am ales python. Nu exista motive foarte bune pentru python dar nici motive foarte bune pentru a alege altceva.\r\n\r\nh3. Baza de date\r\n\r\nPropun sa folosim \'SQLAlchemy\':http://www.sqlalchemy.org/ pentru a manipula baza de date, sau macar partea de expresii SQL. Ne scapa de a formata de mana conditii de where pentru chestiile simple, si suporta mai multe baze de date. Trebuie investigat cu multa grija si testata performanta.\r\n\r\nVrem sa suportam minim MySQL pentru productie si SqlLite pentru development. Ar fi foarte util sa putem rula site-ul in modul de development fara o procedura complexa de setup.\r\n\r\nAvem nevoie de o schema a bazei de date inainte de a ne apuca serios de lucru. Probabil ca o sa scriem direct modelul sql alchemy. Cateva idei:\r\n\r\n* Atasamentele intra in baza de date ca blob-uri. Facem cache pe disk in serveru\' de web; dar doar cache.\r\n* Refacem ia_textblock, face doar stocare versionata de blob-uri. De investigat merge cu ia_file.\r\n* Id-ul numerice peste tot.\r\n* ia_task si ia_task_classic, ia_task_output\r\n* ia_round si ia_round_classic. ia_round_archive?\r\n* ia_wiki separat: contine textblock si securitate private/protected/public.\r\n* ia_blog separat: contine data de publicare, autor, tag-uri (in ia_blog_tag)\r\n* Bagam id-uri de topic-uri smf in ia_task si ia_blog.\r\n* Spargem ia_score\r\n* ia_log din start. Il folosim pentru teste.\r\n\r\nh3. Wiki\r\n\r\nLa baza site-ului vom avea o componenta de versionare de fisiere. Aceasta componenta nu stie absolut nimic de useri, probleme, securitate sau tag-uri. Orice semnificatie a fisierelor este data doar de mai sus. De la aceasta componenta ne dorim urmatoarele:\r\n\r\n* Fetch rapid, cu cache transparent pe disc. Nu servim fisiere direct baza de date.\r\n* Istorie completa a modificarilor\r\n* Delete reversibil, care sa apara in istorie\r\n* Mutare/copiere pastrata in istorie.\r\n* Posibilitatea de a distruge complet o revizie\r\n\r\nNu avem nevoie de:\r\n\r\n* Directoare. Ne trebuie doar fisiere.\r\n* Meta-date. Versionam doar blob-uri; eventual cu cateva coloane strongly-typed (mime type?)\r\n* Notiuni de securitate.\r\n* Schimbari atomice pe mai multe fisiere.\r\n\r\nEste dificil sa satisfacem toate cerintele folosind tabele de SQL, dar se poate face. Multe cerinte pot fi relaxate pana aproape de nivelul infoarena2. O varianta interesanta ar fi sa folosim subversion pentru versionare, dar din pacate nu se mapeaza perfect pe ce vrem noi. De investigat si discutat.\r\n\r\nh3. MVC\r\n\r\nAvem ca si in infoarena2 un singur entry-point in tot site-ul. Acolo analizam requestul (ne uitam la url si query string) dupa care pasam munca la un controller. Un controller este o functie python care se ocupa de un request de la cap la coada. Controllerele nu se cheama niciodata unul pe altul.\r\n\r\nMulte controllere vor folosi probabil suportul de versionare. Trebuie sa putem refolosi usor codul de editare si istorie si sa il integram in alte componente. Ne dorim un editor integrat de task-uri si de profil de utilizator.\r\n\r\nDoar componentele mari ale site-ului vor avea propriile controllere. Pentru un tabel rapid sau un raport solutia preferata este sa facem un macro.\r\n\r\nh3. Securitate\r\n\r\nSecuritatea se va face in codul de BL si va fi implementata distinct pentru fiecare tip de entitate. Fiecare utilizator va avem anumite permisiuni global iar pentru unele entitati vom putea adauga drepturi per-utilizator. Incercam sa facem securitatea cat mai simplu; in cod. Incercam sa evitam securitate declarativa dar prea complexa, cum e cea din windows. Nu vom suporta:\r\n\r\n* Id-uri globale de obiecte securizabile.\r\n* Grupuri de obiecte.\r\n* Logica de allow/deny.\r\n* Ierarhii.\r\n* Grupuri de utilizatori.\r\n\r\nFiecare utilizator va avea anumite drepturi globale. Aceste drepturi pot fi editate doar de administratori, folosind checkbox-uri sau dropdown-uri pe pagina de cont. Aceasta pagina trebuie sa fie accesibila din pagina de profil. Drepturile globale vor fi hard-codate la un moment dat, dar le putem schimba din cod.\r\n\r\n* Daca utilizatorul este admin\r\n* Daca poate propune probleme\r\n* Daca poate posta pe blog\r\n* Daca poate edita enunturi de probleme (pentru neclaritati).\r\n* Daca este moderator pe forum (challenge!)\r\n\r\nPentru probleme o sa avem o lista in care pot fi adaugati useri cu drepturi. \r\n\r\n* Propunator: Aproximativ orice\r\n* Reviewer: Modificari in enunt, download de teste.\r\n* Altceva?\r\n\r\nPentru runde putem incepe prin a permite accesul doar administratorilor, dar ulterior putem adauga o lista de useri cu drepturi:\r\n\r\n* Responsabil: poate sa modifice orice.\r\n* Tester: poate submita la probleme in afara concursului.\r\n* Invitat: pentru concursuri private sau finale live.\r\n\r\nh3. Logica de concursuri\r\n\r\nVrem sa suportam mai multe tipuri de probleme sau runde, fara sa oprim evaluatorul. Asta este foarte realizabil daca nu ne incurcam cu sisteme multe prea generice. Nu o sa mai avem descriptori de securitate si ia_parameter_values, toate datele noastre vor fi accesibile in SQL curat. Asta inseamna ca putem sa facem query-uri complexe pentru determinat ce job-uri trebuie evaluate.\r\n\r\nh3. Integrare SMF, textile.\r\n\r\nIntegrarea SMF o se faca in cea mai mare parte cu query-uri direct in tabele de SMF. Tabele SMF sunt relativ inteligibile. Pentru cazurile in care nu ne ajunge putem investiga un mod de a chema cod php din python in acelasi request. Aproape sigur se poate, dar s-ar putea sa ne restranga la mod_python. Daca se poate atunci putem sa evitam sa duplicam codul de header/footer spre exemplu, dar nu este critic.\r\n\r\nExista un parser textile pentru python dar nu esti dezvoltat activ. Asta nu e o problema; il introducem in repository si il modificam pentru ce avem nevoie. Putem face teste automate ca sa verifice ca output-ul este foarte similar. In infoarena2 am incercat sa modificam cat mai putin parser-ul de textile pentru a putea lua update-uri upstream. Asta nu s-a intamplat si cred ca e mai bine sa modificam fara mila.\r\n\r\nh2. Plan de bataie\r\n\r\nAjunge cat am batut campii, trebuie sa ne apucat si de munca. Primul release public se va numi infoarena 3.0 si are ca criteriu implementarea intregii functionalitati infoarena2. Pana atunci vom face dezvoltarea intr-un branch separat din acelasi repository.\r\n\r\nh3. Ce se intampla cu infoarena2 si trac.\r\n\r\nInfoarena2 intra in maintenance-only mode; unde nu reparam decat chestii foarte necesare. Facem release 2.1.5 si trecem la layout-ul de repository propus pentru infoarena3. Bagam toate tichetele intr-un milestone de \"Infoarena 2.99 blue-sky\" si mutam in 2.1.6 doar tichetele pentru care putem asigna un om.\r\n\r\nPentru infoarena3 facem tichete de investigare si 2 milestone-uri: \"3.0\" si \"3.99 blue-sky\" cu aceasi semnificatie. Momentam lucram in branches/infoarena3, facem switch la trunk cand dam release de 3.0. O sa avem si alte branch-uri de research pentru 3.0.\r\n\r\nh3. Barebones read-only site\r\n\r\nCa prim pas trebuie sa facem intai partile de content. Daca avem tot continutul importat putem sa facem teste foarte realiste si sa vedem cat de viabile sunt ideile noastre. Nu incepem cu pagina de inregistrare utilizator. Ne trebuie:\r\n\r\n* Schema sql alchemy pentru baza de date.\r\n* Script import baza de date\r\n* Servire textile cu macro-uri\r\n* Cateva macro-uri (scoruri!)\r\n* Cateva form-uri (editare probleme!)\r\n\r\nh3. Coding camp public\r\n\r\nDupa ce avem site-ul in forma read-only aproximativ complet putem sa facem coding camp-uri cu multa lume pentru a continua dezvoltarea. Aducem oameni, ii invatam cum sa faca branch-uri si ii punem sa faca form-uri si macro-uri.',1,'public',NULL,NULL),('utilizator/corinabolfa','Profil corinabolfa','2007-11-14 13:18:28','2007-11-14 13:18:28','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',7100,'public',NULL,NULL),('utilizator/paulrusu','Profil paulrusu','2007-11-15 20:59:03','2007-11-15 20:59:03','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',7116,'public',NULL,NULL),('newsletter/stelele-2009-9-10','Stelele Informaticii, clasele IX - X și gimnaziu','2009-02-04 00:15:25','2009-02-04 12:25:02','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎn acest weekend se desfăşoară la Bucureşti concursul „Stelele Informaticii” pentru clasele IX-X şi gimnaziu, organizat de \'ICHB\':http://www.ichb.ro/. Deşi „stelele” este un concurs pe bază de invitaţie, anul acesta se va ţine în premieră pe infoarena, iar tu poţi să concurezi cot la cot cu participanţii on-site. Este o ocazie excelentă să-ţi verifici cunostinţele înainte de debutul olimpiadelor!\r\n\r\nProgram „Stelele Informaticii” clasele IX-X şi gimnaziu:\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt}. \'Proba 1\':stelele-2009/9-10/runda-1 - 6 Februarie 2009 între orele 10^00^ şi 14^00^\r\n\'Proba 2\':stelele-2009/9-10/runda-2 - 7 Februarie 2009 între orele 09^00^ şi 13^00^ |\r\n\r\nConcursul pentru clasele XI-XII va fi anunţat şi organizat într-una din săptămânile viitoare. Află mai multe informaţii de pe pagina \'„Stelele Informaticii”\':stelele-2009.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"stelele-2009\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre „Stelele Informaticii”\r\n\r\n„Stelele Informaticii” este un concurs anual organizat şi găzduit de \'Liceul Internaţional de Informatică Bucureşti\':http://www.ichb.ro/. Prima ediţie a concursului a avut loc în noiembrie 2003.\r\n\r\nLa acest concurs sunt invitaţi să participe toţi elevii care au obţinut premii la Olimpiadele Naţionale de Informatică sau care au fost incluşi în loturile de pregătire pentru concursurile internaţionale. În funcţie de locurile disponibile mai participă şi alţi elevi. Scopul competiţiei este de a constitui o primă întrecere a elevilor talentaţi în programare, o avanpremieră a competiţiilor care vor urma pe parcursul anului şcolar. Concursul se desfăşoară separat pentru clasele IX-X şi gimnaziu, respectiv XI-XII, pe parcursul a două probe, în două zile diferite. \r\n\r\nAnul acesta „stelele” se organizează pe infoarena, iar tu ai ocazia să participi alături de concurenţii on-site. La fiecare probă vei avea de rezolvat 3 probleme de natură algoritmică. Subiectele vor fi propuse şi pregătite de către:\r\n\r\n* ==User(user=\"silviug\" type=\"link\")==\r\n* ==User(user=\"pauldb\" type=\"link\")==\r\n* ==User(user=\"wefgef\" type=\"link\")==\r\n* ==User(user=\"efer\" type=\"link\")==\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/doi-la-suta\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==\r\n',13,'protected',NULL,NULL),('blog/jocuri-web','Jocuri pe Web','2007-11-17 14:43:38','2008-11-15 13:41:14','!>blog/jocuri-web?funnyfarm.jpg! Anul trecut am jucat cateva jocuri web misto ce aveau o realizare simpla, dar te prindeau. Ideea lor e ca trebuie sa parcurgi niste pagini web ca sa ajungi pana la pagina finala. Pe fiecare pagina este cate un puzzle pe care daca il rezolvi poti sa treci la pagina urmatoare. Cele pe care le-am vazut eu sunt \'Hacker Puzzle\':http://www.freestuffhotdeals.com/hacker/1.html , \'From A to craZy\':http://shygypsy.com/az/ si unul mai complex care mi-a placut foarte mult \'Funny Farm\':http://www.shygypsy.com/farm/p.cgi . Ultimele doua siteuri sunt facute de Igor Naverniouk, un tip din Canada, si el din lumea concursurilor de programare, cu care mai discut din cand in cand. Pentru ambele jocuri el oferea ceva premii simbolice pentru a atrage vizitatori. Ele au aparut pe prima pagina a \'digg\':http://digg.com , lucru care mi se pare a fi o dovada de succes. Puzzleurile sunt foarte bine facute si Igor zicea ca partea de programare a luat mai putin decat partea de creere a intrebarilor. Dupa ce a aparut siteul pe digg a trebuit sa faca si cateva restructurari in cod ca sa poata primi un trafic neasteptat de mare. Funny Farm avea cateva reclame Google si eram curios cati bani a reusit sa scoata din un joc care mie mi se parea foarte popular si interesant. Raspunsul lui a fost unul sub asteptari, a zis ca a facut in jur de doua mii de dolari, care nu e o suma asa mare cand e comparata cu salarul pe luna a unui programator mediu din state sau Canada.\r\n\r\nTotusi stiu si de jocuri mai banoase ca funny farm cum ar fi \'Tower of Defense\':http://www.handdrawngames.com/DesktopTD/Game.asp pe care autorul \'castiga din reclame\':http://www.codinghorror.com/blog/archives/000872.html opt mii de dolari pe luna.\r\n\r\nModa jocurilor de tipul Hacker Puzzle a aparut si in Romania. Alex Brie face reclama pe blogul sau la \'Brain Tower\':http://alexbrie.net/braintower/ , un joc cu potential, dar la care mi se pare ca mai are de lucru. Problemele nu sunt chiar cele mai interesante, si lipseste satisfactia de la final, in celelate jocuri te puteai semna intr-un guestbook sau luai un premiu. Dar din cate mi-a zis Alex, mai vrea sa lucreze putin la el, si pentru inceput arata bine. Multa bafta!\r\n\r\n*Update* Alex a bagat de ceva vreme si un guestbook pe site.\r\n\r\nCati dintre voi aveti siteuri cu reclame? Cum va merg?\r\n\r\n',1490,'protected',2346,NULL),('blog/joburi-evaluate','Joburi evaluate','2007-11-18 15:21:57','2008-11-15 13:41:14','Evaluatorul infoarena a rulat pana acum mai mult de o suta de mii de joburi. Inaintea inceperii concursului Happy Coding erau vreo 95000 de joburi, iar acum sunt peste o suta cinci.\r\n\r\nSpor la munca in continuare!\r\n\r\n',1490,'protected',2349,NULL),('blog/problema-majoritatii','Problema majoritatii','2007-11-18 15:53:10','2008-11-15 13:41:14','Cum blogul ar trebui sa fie orientat spre comunitatea infoarena am zis ca voi pune cate un post cu jmenuri de algoritmica din cand in cand. Sper sa va placa.\r\n\r\nO problema clasica dar interesanta suna asa: _Se dau n alegatori si fiecare voteaza pe unul dintre ei (toti alegatorii sunt in acelasi timp si candidati). Se stie ca unul dintre alegatori a primit cel putin $n/2$ + 1 voturi si acesta va obtine functia de presedinte. Gasiti un algoritm eficient pentru a determina viitorul presedinte._\r\n\r\nPentru a face putin mai interesanta problema, sa spunem ca sunt de ajuns $n/3 + 1$ voturi pentru a castiga alegerile si mai impunem restrictia ca exact unul dintre participantii la vot are mai mult de $n/3$ voturi.\r\n\r\nCum putem rezolva problema asta?\r\n\r\nO solutie naiva, dar eficienta ar fi sa luam cateva nume votate aleatoare din sir. Cum castigatorul apare ca optiunea a multi votanti, daca alegem destul de multe valori din sirul optiunilor vom da cu probabilitate mare peste castigator. Cand alegem un nume aleator avem probabilitatea $p > 1/3$ ca am ales numele viitorului castigator. Deci daca alegem k valori vom avea un timp de executie de ordinul $O(kn)$ pentru a verifica daca una dintre cele $k$ valori e cea buna si probabilitatea de a gasi peresedintele mai mare de $1 - (1/3)^k^$.\r\n\r\nAlta idee vine de la faptul ca in sirul sortat, elementele de valori egale vor fi pe pozitii consecutive. Astfel numele presedintelui va aparea pe cel putin $n/3 + 1$ pozitii consecutive. Deci numele presedintelui va aparea sigur pe cel putin una din pozitiile $n/3$ sau $2n/3$ din sir. Astfel putem folosi un algoritm de selectie pentru a gasi in $O(n)$ elementele de pe pozitiile $n/3$ si $2n/3$ si apoi in $O(n)$ putem verifica care dintre acesti doi candidati au castigat.\r\n\r\nDaca n nu depaseste un milion, putem la fiecare pas sa incrementam pentru candidatul votat $x$ numerele $a[x / 1000]$ si $b[x % 1000]$. Acum pentru a determina candidatul castigator, gasim valoarea $p$ cu $a[p] > n/3 + 1$ si valoarea $q$ cu $b[q] > n/3 + 1$, iar castigatorul va fi $p * 1000 + q$.\r\n\r\nO solutie ar fi sa folosim un hash map ce mapeaza numele alegatorilor la numarul de voturi castigate. Solutia aceasta este eficienta dar foloseste $O(n)$ memorie suplimentara pentru structura de date.\r\n\r\nAlta solutie este sa facem grupuri de cate trei alegatori cu opinii diferite asupra castigatorului, care se cearta intre ei pana pica jos. Dupa ce am facut toate grupurile de cate trei, ne mai  pot ramane maxim doua optiuni de candidati, in caz contrar mai gaseam un grup de trei votanti cu optiuni diferite. E clar ca dupa ce am eliminat grupurile de cate trei, va exista unul dintre alegatori cu optiunea pentru viitorul presedinte intre alegatorii negrupati, pentru ca acesta e votat de mai mult de $n/3$ ori. Asa ca pentru a gasi presedintele este de ajuns sa verificam cele doua optiuni ai alegatorilor ramasi negrupati. Va prezint codul solutiei:\r\n\r\nMerge in $O(n)$ ca timp si $O(1)$ ca spatiu suplimentar.\r\n== code(c) |\r\nx <- -1, counter_x <- 0;\r\ny <- -1. counter_y <- 0;\r\npentru i = 1,n\r\n  daca counter_x = 0 atunci x <- a[i], counter_x <- 1;\r\n  altfel daca counter_y = 0 atunci y <- a[i]; counter_y <- 1;\r\n      altfel daca x = a[i] atunci counter_x++;\r\n      altfel daca y = a[i] atunci counter_y++;\r\n          altfel\r\n           // am gasit un grup de trei alegatori cu optiunile\r\n           // x, y si a[i] pe care il eliminam\r\n           // x != a[i], y != a[i] si x != y\r\n           counter_x--, counter_y--;\r\nverificam daca x sau y este elementul cautat.     \r\n==\r\n\r\n\r\n_Problema poate parea artificiala, dar reformulata in aceea de a gasi in mod eficient queriuri foarte frecvente(ce apar de $n/k$ ori) pentru un motor de cautare devine mai interesanta si practica. Postul a fost inspirat din articolul \"Problema majoritatii votului\" ce l-am publicat in Ginfo, iar partea cu cearta intre alegatori din R. S. Boyer, J. S. Moore A Fast Majority Vote Algorithm_\r\n\r\n',1490,'protected',2350,NULL),('utilizator/cosmin','Profil Cosmin','2006-11-24 20:56:17','2010-01-03 06:11:58','Cititi \'blogul\':blog !\r\n\r\n!utilizator/cosmin?cosmin_mircea_oni_2006.jpg!\r\n\r\nCu Mircea la ONI 2006.\r\n\r\n\r\nh2. Probleme\r\n\r\n55 de probleme in arhiva infoarena.\r\n\r\nh2. Articole\r\n\r\n* Blog post despre diverse metode de antrenament pentru olimpiada \'Vine Olimpiada\':blog/vine-olimpiada\r\n\r\n* \'Probleme de tăietură\':probleme-de-taietura\r\n* \'Problema majorităţii votului\':problema-majoritatii-votului\r\n* {\'Problema 2-satisfiabilitatii\':2-sat}\r\n* \'Probleme cu secvente\':probleme-cu-secvente\r\n* \'Probleme de acoperire &#40;partea I&#41;\':probleme-de-acoperire-1\r\n* \'Probleme de acoperire &#40;partea a II-a&#41;\':probleme-de-acoperire-2\r\n* \'Missing Numbers\':missing-numbers\r\n* \'Cautari ortogonale\':cautari-ortogonale\r\n* \'Siruri de sufixe\':siruri-de-sufixe\r\n* \'Probleme cu puncte laticiale\':probleme-cu-puncte-laticiale\r\n* \'Teoria jocurilor: numerele Sprague-Grundy\':numerele-sprague-grundy\r\n* \'Coduri Gray\':coduri-gray\r\n* \'Ciurul lui Eratostene\':ciurul-lui-eratostene\r\n* \'Optimizarea programelor folosind operaţii pe biţi\':operatii-pe-biti\r\n\r\n\r\n\r\nh2. Membru in comisii\r\n\r\n* CEOI 2009\r\n* Google Coding Jam, 06, 08, 09, 10\r\n* TopCoder Open 07, TCCC 06, SRM 315\r\n* Initiat Summer Challenge si Happy Coding\r\n* lot 05, 06 ONI 06\r\n* .campion, 2006\r\n* Bursele Agora, 06,05,04\r\n* Algoritmus, 05\r\n* preOni 06,05,04\r\n* Grigore Moisil 06, 03\r\n\r\nh2. Prieteni infoarena:\r\n\r\n* == User(user=\"tabara\" type=\"tiny\") ==\r\n* == User(user=\"domino\" type=\"tiny\") ==\r\n* == User(user=\"wefgef\" type=\"tiny\") ==\r\n* == User(user=\"DitzoneC\" type=\"tiny\") ==\r\n* == User(user=\"greco\" type=\"tiny\") ==\r\n* == User(user=\"wickedman\" type=\"tiny\") ==\r\n* == User(user=\"mpatrascu\" type=\"tiny\") ==',58,'protected',NULL,NULL),('happy-coding-2007/solutii','Solutii Happy Coding 2007','2007-11-19 10:54:07','2010-04-10 10:33:57','h1. Solutii Happy Coding 2007   !happy-coding-2007/solutii?hc2007-logo.gif!\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Abc2\':happy-coding-2007/solutii#abc2\r\n* \'Tritzi\':happy-coding-2007/solutii#tritzi\r\n* \'Regine 2\':happy-coding-2007/solutii#regine2\r\n* \'Rfinv\':happy-coding-2007/solutii#rfinv\r\n* \'Pali\':happy-coding-2007/solutii#pali\r\n* \'Furnica\':happy-coding-2007/solutii#furnica\r\n* \'Flori 2\':happy-coding-2007/solutii#flori2\r\n* \'Bitmap\':happy-coding-2007/solutii#bitmap\r\n* \'Cascaval\':happy-coding-2007/solutii#cascaval\r\n* \'Cercuri 3\':happy-coding-2007/solutii#cercuri3\r\n* \'Antitero\':happy-coding-2007/solutii#antitero\r\n* \'Sistem 2\':happy-coding-2007/solutii#sistem2\r\n* \'Optic\':happy-coding-2007/solutii#optic\r\n* \'Zvon\':happy-coding-2007/solutii#zvon\r\n* \'Cerc 2\':happy-coding-2007/solutii#cerc2\r\n* \'Puteri 2\':happy-coding-2007/solutii#puteri2\r\n* \'Aimin\':happy-coding-2007/solutii#aimin\r\n* \'Multimi\':happy-coding-2007/solutii#multimi\r\n* \'Nrbanda\':happy-coding-2007/solutii#nrbanda\r\n* \'Tramvai\':happy-coding-2007/solutii#tramvai\r\n* \'Biti 3\':happy-coding-2007/solutii#biti3\r\n* \'Clear\':happy-coding-2007/solutii#clear\r\n* \'H\':happy-coding-2007/solutii#h\r\n* \'Permavg\':happy-coding-2007/solutii#permavg\r\n* \'Kboard\':happy-coding-2007/solutii#kboard\r\n\r\nh2(#abc2). \'Abc2\':problema/abc2\r\n\r\nO prima abordare care ar parea sa aiba sanse de a obtine punctaj maxim este de a construi un \'trie\':http://en.wikipedia.org/wiki/Trie al cuvintelor. Cu ajutorul acestui trie putem verifica in complexitate $O(L)$ daca exista vreun cuvant care sa se termine la fiecare pozitie $i$ din sir. Totusi, aceasta solutie are complexitate $O(L*lungime text mare)$ si nu se incadreaza in timp.\r\n\r\nOptimizarea consta in construirea automatului finit determinist asociat celor $N$ cuvinte. Acest automat poate fi construit in complexitate $O(N*L)$, conform algoritmului \'Aho-Corasick\':http://www.softlab.ntua.gr/facilities/public/AD/DM/Algorithms%20for%20Finding%20Patterns%20in%20Strings.html. Modul de constructie este asemanator calculului functiei prefix din algoritmul \'KMP\':http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm. Construim trie-ul cuvintelor, apoi, pentru un nod $X$ al trie-ului, determinam nodul din trie care corespunde celui mai lung sir de caractere care este sufix al sirului asociat nodului $X$. Putem calcula aceste valori pe nivele, intrucat un nod $Y$ de tipul celui mentionat mai sus se va afla intotdeauna pe un nivel superior nodului $X$ (dar nu neaparat pe calea de la radacina trie-ului pana la nodul $X$). Acest automat se poate folosi apoi in cadrul parcurgerii textului dat. Incepem din starea corespunzatoare sirului vid (radacina trie-ului). De fiecare data cand trecem la urmatorul caracter, incercam sa trecem in nodul din trie ce corespunde caracterului respectiv si este fiu al starii curente. Daca acest nod nu exista, la fel ca la KMP, trecem in starea corespunzatoare \"prefixului-sufix\" al starii curente si repetam acest lucru pana cand ajungem in radacina trie-ului sau intr-un nod care are un fiu ce corespunde caracterului urmator din sir. Daca ajungem intr-un nod ce corespunde unei stari finale, atunci am gasit o aparitie a unui cuvant.\r\n\r\nSolutia oficiala foloseste un algoritm de constructie a unui \'automat finit determinist\':http://en.wikipedia.org/wiki/Deterministic_finite_state_machine avand complexitate $O(N*L^2^)$. Se va construi trie-ul cuvintelor, apoi, pe baza acestui trie, se va calcula un automat care are un numar de stari egal cu numarul de noduri ale trie-ului. Pentru fiecare stare $X$ si fiecare caracter $c$, se va calcula functia $nextState[X,c]$, reprezentand starea ce corespunde celui mai lung sir care este un subsir al sirului corespunzator starii $X$ concatenat cu caracterul $c$. Pentru starile $X$ ce au fiu in trie corespunzator unui caracter $c$, $nextState[X,c]$ va fi egal cu acest fiu. Pentru celelalte caractere si o stare $X$, vom avea $O(L)$ stari candidate. Mai exact, sa consideram ca $TX$ este tatal nodului $X$ in trie (presupunand ca $X$ nu este radacina trie-ului) si ca avem starile $Q{~0~}, Q{~1~}, .., Q{~P~}$ stari ce corespund sufixelor de lungime $0, 1, .., P$ ale sirului corespunzator nodului $TX$ (acest sir are $P+1$ caractere). Atunci multimea de stari $R{~1~}, .., R{~P+1~}$ avand aceeasi semnificatie pentru nodul $X$ se calculeaza ca fiind $R{~1~}=fiu[Q{~0~},u], R{~2~}=fiu[Q{~1~},u], .., R{~P+1~}=fiu[Q{~P~},u]$, unde $X=fiu[TX,u]$, adica fiul nodului $TX$, ce corespunde caracterului u. La aceasta multime vom adauga pe R{~0~}=radacina trie-ului (ce corespunde sirului vid). $nextState[X,c]$ va fi egal cu sirul de lungime maxima dintre sirurile corespunzatoare nodurilor $fiu[R{~i~},c]$, cu $0 &le; i &le; P+1$. Se observa usor ca pentru orice nod $X$ pot exista cel mult $O(L)$ stari candidate, deoarece sirul corespunzator unui nod $X$ are $O(L)$ caractere.\r\n\r\nO solutie mai simpla si care ar obtine punctajul maxim consta in folosirea unor functii de hash, ca in algoritmului \'Rabin-Karp\':http://en.wikipedia.org/wiki/Rabin-Karp_string_search_algorithm. Aceste functii trebuie sa fie calculabile usor ({$in O(1)$}) atunci cand avem valoarea hash-ului pentru un sir $S$ si dorim sa calculam valoarea pentru sirul $S\'$ obtinut prin adaugarea unui caracter la dreapta lui $S$ si inlaturarea unui caracter din stanga lui $S$. Cateva variante de functii de hash ar putea fi urmatoarele:\r\n\r\n* functii polinomiale, cu puteri de numere prime: $(c{~N~}*P^N^ + c{~N-1~}*P^N-1^ + c{~1~}*P + c{~0~}) mod Q$ ({$P$} si $Q$ numere prime)\r\n* scrierea sirurilor ca numere in baza $3$ (intrucat alfabetul consta doar din $3$ litere) => este ideea de mai sus, dar cu $P=3$.\r\n\r\nh3. Probleme asemanatoare\r\n\r\n* \'Dangerous Pattern / ZJU\':http://acm.zju.edu.cn/show_problem.php?pid=2115\r\n\r\nh2(#tritzi). \'Tritzi\':problema/tritzi\r\n\r\nh3. Algoritm de complexitate $O(N)$\r\n\r\nVom calcula valorile $T[i,j]$, reprezentand numarul de siruri de $i$ tritzi, pentru care ultimul trit are valoarea $j$. $T[1,j] = (1 mod P)$. Pentru $i &gt; 1$, avem:\r\n\r\n* $T[i, 0] = (T[i-1, 0] + T[i-1, 2]) mod P$\r\n* $T[i, 1] = (T[i-1, 1] + T[i-1, 2]) mod P$\r\n* $T[i, 2] = (T[i-1, 0] + T[i-1, 1] + T[i-1, 2]) mod P$\r\n\r\nAplicarea directa a acestor relatii de recurenta conduce la un algoritm liniar, care, insa, nu se incadreaza in limita de timp.\r\n\r\nh3. Algoritm de complexitate $O(log N)$ - varianta 1\r\n\r\nFolosind relatiile de recurenta de mai sus, putem construi o matrice $A$ de iteratie si vom privi $T[i]$ ca pe un vector coloana. Avem relatia: $T[i] = A * T[i-1]$. $T[N] = A^N-1^ * T[ 1 ]$. $T[ 1 ]$ este cunoscut direct, iar $A^N-1^$ se poate calcula in complexitate $O(log N)$, folosind exponentiere logaritmica.\r\n\r\nh3. Algoritm de complexitate $O(log N)$ - varianta 2\r\n\r\nVom calcula o matrice $T[x][i][y]$ = numarul de siruri de tritzi (mod P), de lungime $2^i^$ si pentru care primul trit are valoarea $x$, iar ultimul trit are valoarea $y$. $T[x][ 0 ][y]$ se determina direct, iar pentru $i &gt; 0$, $T[x][i][y]$ va fi egal cu o suma din $T[x][i-1][a] * T[b][i-1][y]$, unde $a$ si $b$ sunt doua valori ({$0$}, $1$ sau {$2$}) care pot fi plasate una dupa alta.\r\n\r\nApoi vom scrie numarul $N$ ca o suma de puteri ale lui $2$: $N = 2^p1^ + 2^p2^ + ..  2^pK^$. Vom calcula o matrice $U[x][i][y]$ = numarul de siruri de tritzi (mod P) de lungime $2^p1^ + 2^p2^ + .. + 2^pi^$, pentru care primul trit are valoarea $x$ si ultimul trit are valoarea $y$. Avem $U[x][ 0 ][y] = T[x][p0][y]$. Pentru $i &gt; 0$, $U[x][i][y]$ este egal cu o suma din $U[x][i-1][a] * T[b][pi][y]$, unde $a$ si $b$ sunt doua valori de tritzi care pot fi plasate una dupa alta. Rezultatul final il vom obtine adunand toate valorile $U[x][K][y]$, unde $K$ este numarul de biti de $1$ din reprezentarea binara a lui $N$.\r\n\r\nh3. Probleme asemanatoare\r\n\r\n* \'Iepuri / preONI 2005\':http://infoarena.ro/problema/iepuri\r\n* \'Nice Patterns Strike Back / SGU\':http://acm.sgu.ru/problem.php?contest=0&problem=197\r\n* \'Fibo / .campion 2003\':http://campion.edu.ro/problems/3/106/fibo.htm\r\n\r\nh2(#regine2). \'Regine2\':problema/regine2\r\n\r\nProblema se rezolva prin backtracking. Pentru fiecare pozitie (in ordinea liniilor si, pentru fiecare linie, in ordinea coloanelor), se incearca amplasarea sau neamplasarea unei regine in pozitia respectiva, iar apoi se marcheaza toate pozitiile atacate de regina respectiva, pentru a nu se mai incerca amplasarea unei regine viitoare pe o pozitie deja atacata. La intoarcerea din backtracking, pozitiile marcate se demarcheaza (vom folosi, de fapt, un contor pentru fiecare pozitie, in care vom retine de cate regine deja amplasate este atacata pozitia respectiva). Singura optimizare necesara este ca, atunci cand marcam pozitiile atacate de o regina nou-amplasata, vom marca doar pozitiile pe care vom incerca sa amplasam o regina in viitor (adica doar inspre directiile: est, sud-est, sud, sud-vest, si nu in toate cele $8$ directii).\r\n\r\nh3. Probleme asemanatoare\r\n\r\n* \'Problema celor $N$ regine [ clasica ] & co.\':http://acm.fzu.edu.cn/reference/Search%20Techniques.htm\r\n* \'Dame2 / Summer Challenge 2007\':problema/dame2\r\n\r\nh2(#rfinv). \'Rfinv\':problema/rfinv\r\n\r\nh3. Solutie de complexitate $O(N^4^)$\r\n\r\nVom sorta toate cele $O(N^2^)$ distante din matrice in ordine crescatoare si vom initializa o matrice $D[i][j]=infinit$, pentru $i &lt;&gt; j$, respectiv $0$, pentru $i=j$. Pe masura ce parcurgem sirul sortat al distantelor, vom actualiza valorile din matricea $D$. Sa presupunem ca am ajuns la o distanta avand valoarea $x$, ce reprezinta distanta minima dintre $2$ noduri $i$ si $j$. Daca $D[i][j] &lt; x$ sau $D[i][j] &gt; x$ si nu exista muchie in graf intre $i$ si $j$, atunci nu avem solutie si ne oprim. Daca $D[i][j] &gt; x$ si exista muchie intre $i$ si $j$, atunci vom pune pe aceasta muchie costul $x$. In continuare, va trebui sa actualizam valorile $D[a][b]$ afectate de setarea valorii $x$ pe muchia $(i,j)$. Mai exact, pentru fiecare pereche de noduri $(a,b)$, $D[a][b]$ va fi egal cu minimul dintre valoarea actuala $D[a][b]$ si $min { D[a][i] + x + D[j][b], D[a][j] + x + D[i][b] }$.\r\n\r\nDaca nu am intalnit nici o contradictie pe masura ce am parcurs muchiile, atunci raspunsul este $\"DA\"$ ; in caz contrar, raspunsul este $\"NU\"$.\r\n\r\nh3. Solutie de complexitate $O(N^3^)$\r\n\r\nPe fiecare muchie a grafului $(i,j)$ se pune o distanta egala cu valoarea $A[i][j]$ ({$A$} fiind matricea data). Se aplica apoi algoritmul \'Roy-Floyd\':http://en.wikipedia.org/wiki/Floyd-Warshall_algorithm pe acest graf, iar matricea distantelor obtinuta trebuie sa fie identica cu matricea distantelor data (in caz contrar neexistand solutie).\r\n\r\nh3. Probleme asemanatoare\r\n\r\n* \'Rf / Happy Coding 2006\':problema/rf\r\n\r\nh2(#pali). \'Pali\':problema/pali\r\n\r\nSe va calcula $pmin[i]$ = numarul minim de palindroame in care poate fi impartit sirul format din primele $i$ caractere ale sirului dat.\r\n\r\nh3. Solutia 1\r\n\r\nVom avea $pmin[ 0 ] = 0$ si $pmin[i] = 1 + min { pmin[j] | subsirul j+1,..,i este un palindrom }$, cu $0 &le; j &le; i-1$. Pentru a determina rapid daca subsirul dintre $2$ pozitii $k$ si $l$ este un palindrom, vom calcula o matrice $Pali[k][l]$, avand valorile $1$ si $0$, daca subsirul dintre pozitiile $k$ si $l$ este palindrom sau nu. Vom avea $Pali[k][l] = 1$, daca $sir[k] = sir[l]$ si $Pali[k+1][l-1]=1$ (pentru cazul in care {$l-k &ge; 2$}). Pentru ca aceasta solutie sa se incadreze in timp, va trebui ca matricea sa o calculam coloana cu coloana, pe masura ce avem nevoie de valorile din ea.\r\n\r\nh3. Solutia 2\r\n\r\nVom incerca sa calculam valorile $pmin[i]$ treptat. Vom parcurge pozitiile de la $1$ la $N$ si vom incerca sa incepem un palindrom avand centrul in pozitia $i$ (pentru cazul unui palindrom de lungime impara), respectiv avand centrul la pozitiile $i$ si $i+1$ (pentru cazul unui palindrom de lungime para). Ideea importanta este ca, atunci cand ajungem la pozitia $i$, toate valorile $pmin[j]$, cu $j &lt; i$ au fost calculate, iar valorile $pmin[k]$, $k &gt; i$, au niste valori partiale (adica valorile calculate nu sunt inca finale, ele mai putand sa scada ulterior). Vom extinde treptat cat putem de mult un palindrom in jurul pozitiei $i$ (respectiv pozitiilor $i$ si {$i+1$}); la fiecare pas de extindere, vom incrementa palindromul de la lungimea curenta $L$, la lungimea $L+2$ (pentru aceasta verificam caracterele din capatele palindromului); inainte de a realiza extinderea, vom incerca sa folosim palindromul curent in cadrul unei solutii - mai exact, vom avea posibilitatea ca valoarea $pmin[i-(L+1)/2]+1$ sa fie folosita pentru a micsora valoarea lui $pmin[i+(L+1)/2-1]$ (pentru cazul lungimii impare), respectiv valoarea $pmin[i-L/2]+1$ poate fi folosita pentru a micsora valoarea lui $pmin[i+L/2]$ (pentru cazul lungimii pare).\r\n\r\nComplexitatea ambelor solutii este $O(N^2^)$, insa a doua solutie merge mai repede, in practica, deoarece ia in considerare numai palindroamele valide (care pot fi cel mult {$O(N^2^)$}).\r\n\r\nh2(#furnica). \'Furnica\':problema/furnica\r\n\r\n* daca pozitia de start este $\'C\'$, atunci raspunsul este $(t+1)^2^$\r\n* daca pozitia de start este $\'S\'$, atunci:\r\n** daca $t$ este par, atunci raspunsul este $((t/2)+1)^2^$\r\n** daca $t$ este impar, atunci raspunsul este $((t+1)*(t+2)/2)-((t+1)/2)^2^$\r\n\r\nAceste formule (sau altele echivalente) pot fi obtinute folosind urmatorul rationament: furnica se poate afla in orice pozitie aflata la o distanta care are aceeasi paritate ca si $t$, fata de pozitia initiala. Pentru pozitia de start $\'C\'$, aceste pozitii formeaza niste \"romburi\", iar pentru pozitia de start $\'S\'$, aceste pozitii formeaza niste diagonale \"secundare\".\r\n\r\nh2(#flori2). \'Flori2\':problema/flori2\r\n\r\nPentru fiecare punct $i$, se sorteaza toate celelalte $N-1$ puncte in jurul punctului $i$ (in functie de unghi). Parcurgand apoi punctele in ordinea sortata, vom determina numarul maxim de puncte avand acelasi unghi fata de $i$ (folosind o precizie corespunzatoare, de $10^-8^$, de exemplu). Fie acest numar $MAX{~i~}$. Raspunsul cautat este $maxim{MAX{~i~} + 1}$ si se obtine in complexitate $O(N^2^*logN)$.\r\n\r\n*Cosmin:* problema s-a dat si la algoritmus. Acolo limita de timp era foarte stransa si solutiile ce au luat punctaj maxim aveau complexitate $O(N^2^)$. Ajungem la complexitatea aceasta, folosind un hash table pentru a determina numarul maxim de puncte cu acelasi unghi fata de $i$ in loc sa sortam punctele.\r\n\r\nSolutia de complexitate $O(N^3^)$, in care se fixeaza $2$ puncte si se determina in $O(N)$ numarul de puncte ce se afla pe dreapta determinata de cele $2$ puncte, nu se incadreaza in timp.\r\n\r\nh3. Probleme asemanatoare\r\n\r\n* \'Rabbit Hunt / TIMUS\':http://acm.timus.ru/problem.aspx?space=1&num=1052\r\n* \'Maximum Number of Colinear Points / KATTIS\':https://kattis.csc.kth.se/problem?id=maxcolinear\r\n\r\nh2(#bitmap). \'Bitmap\':problema/bitmap\r\n\r\nO prima solutie ar consta in a incerca toate cele $4$ posibilitati de a codifica un bitmap care nu are toate celulele de aceeasi culoare. Aceasta abordare de tip backtracking nu s-ar incadra in timp. Optimizarea necesara consta in \'memoizarea\':http://en.wikipedia.org/wiki/Memoization starilor prin care trecem in cadrul backtracking-ului (algoritmul nu se mai numeste backtracking acum, ci devine un fel de programare dinamica). O stare este data de $2$ numere pe cel mult $11$ biti, $S{~1~}$ si $S{~2~}$. Bitii de $1$ din $S{~1~}$ definesc liniile selectate din cadrul bitmap-ului initial, iar bitii de $1$ din $S{~2~}$ definesc coloanele selectate din cadrul bitmap-ului initial. Bitmap-ul definit de starea $(S{~1~},S{~2~})$ este reprezentat de celulele aflate la intersectia dintre liniile selectate de $S{~1~}$ si coloanele selectate de $S{~2~}$. Prin urmare, vom calcula $lmin[S{~1~},S{~2~}]$ = lungimea minima a bitmap-ului ce corespunde starilor $S{~1~}$ si $S{~2~}$. $lmin[2^M^ 1,2^N^-1]$ va contine rezultatul cautat. Pentru ca solutia sa se incadreze in timp, matricea cu valorile asociate fiecarei stari nu trebuie reinitializata la fiecare test. Se va folosi o matrice suplimentara $last_test$, in care vom memora numarul ultimului test in care am ajuns sa calculam valoarea pentru starea $(S{~1~},S{~2~})$. Daca ajungem la starea $(S{~1~},S{~2~})$ in testul curent, vom verifica valoarea lui $last_test[S{~1~},S{~2~}]$. Daca aceasta este egala cu numarul testului curent, inseamna ca am calculat deja valoarea respectiva; in caz contrar, o vom calcula acum si vom seta $last_test[S{~1~},S{~2~}]$ la numarul testului curent.\r\n\r\nh2(#cascaval). \'Cascaval\':problema/cascaval\r\n\r\nRezolvarea problemei incepe cu o observatie nu neaparat evidenta. Sa presupunem ca in luna $j$, compania are $X$ kilograme de cascaval (produse in luna respectiva sau in lunile anterioare si stocate pana in luna $j$). Sa presupunem, de asemenea, ca aceste $X$ kilograme provin din productia de cascaval din $2$ luni diferite, $i1$ si $i2$. Vom calcula costurile obtinerii celor $X1$ si celor $X2$ kilograme de cascaval:\r\n\r\n* $C1 = F{~i1~} + C{~i1~} * X1 + (S{~i1~} + S{~i1+1~} + .. + S{~j-1~}) * X1 = A1 + B1 * X1$\r\n* $C2 = F{~i2~} + C{~i2~} * X2 + (S{~i2~} + S{~i2+1~} + .. + S{~j-1~}) * X2 = A2 + B2 * X2$\r\n\r\nCostul total pentru a avea $X$ kilograme in luna $j$ este $C1+C2$. Voi arata ca s-ar obtine un cost mai bun daca toate cele $X$ kilograme de cascaval ar fi produse in luna $i1$ sau in luna $i2$. Daca am produce toate cele $X$ kilograme in luna $i1$ si costul obtinut ar fi mai mic sau egal cu $C1+C2$, am avea urmatoarea relatie:\r\n\r\n$A1+B1*(X1+X2) &le; A1+B1*X1+A2+B2*X2$, care devine $B1*X2 &le; A2+B2*X2$ si apoi $(B1-B2)*X2 &le; A2$ $(1)$\r\n\r\nIn mod similar, daca toate cele $X$ kilograme ar fi produse in luna $i2$ si costul obtinut ar fi mai mic sau egal cu $C1+C2$, s-ar obtine relatia: $(B2-B1)*X1 &le; A1$ $(2)$\r\n\r\nPentru a demonstra afirmatia, ar trebui ca cel putin una dintre relatiile $(1)$ si $(2)$ sa fie adevarata. Acest lucru este evident. Sa presupunem ca $B1 &ge; B2$. In acest caz, in relatia $(1)$, am avea in partea stanga o valoarea mai mica sau egala cu $0$, iar in partea dreapta o valoarea mai mare sau egala cu $0$. Deci relatia $(1)$ este adevarata. Daca $B1 &le; B2$, atunci se observa in mod similar ca relatia $(2)$ este adevarata.\r\n\r\nConcluzia la care ajungem este ca daca intr-o luna $j$ compania are $X$ kilograme de cascaval, acestea au fost produse toate in aceeasi luna $i &le; j$. Aceasta concluzie ne permite sa gandim problema in urmatorul mod: In luna $1$ sunt produse un numar suficient de kilograme de cascaval pentru a satisface cererile din lunile $1, 2, .., a$. In luna $a+1$ se produc atatea kilograme de cascaval cate sunt necesare pentru a satisface cererile din lunile $a+1, a+2, .., b$ s.a.m.d. Acest mod de a privi problema ne duce usor cu gandul la o solutie folosind programare dinamica.\r\n\r\nh3. Programare dinamica cu complexitatea $O(N^3^)$\r\n\r\nVom calcula costurile $cmin[i]$, reprezentand costul total minim pentru a satisface cererile din lunile $1, 2, .., i$. Algoritmul este descris in continuare in pseudocod:\r\n\r\n==code(c) |\r\ncmin[ 0 ] = 0\r\npentru i de la 1 la N\r\n  cmin[i]=infinit\r\n  pentru j de la 1 la i\r\n    cost_total = cmin[j-1] + F[j] + C[j] * D[j]\r\n    cost_stocare=S[j]\r\n    pentru k de la j+1 la i\r\n      cost_total = cost_total + (C[j]+cost_stocare) * D[k]\r\n      cost_stocare = cost_stocare + S[k]\r\n    daca cost_total < cmin[i] atunci\r\n      cmin[i]=cost_total\r\n==\r\n\r\n	Se variaza valoarea lui $i$ de la $1$ la $N$ si pentru fiecare valoare incercam sa calculam $cmin[i]$. Pentru aceasta, incercam toate valorile $j &le; i$ care pot reprezenta luna in care sunt produse kilogramele de cascaval necesare in luna $i$. Apoi calculam costul total pentru cazul in care luna $j$ produce cantitatea de cascaval necesara pentru a satisface cererile din lunile $j, j+1, .., i$. In cele din urma vom avea in $cmin[i]$ minimul dintre costurile corespunzatoare fiecarei variante de alegere a lunii $j$. Costul total minim pentru toate cele $N$ luni il avem in $cmin[N]$. Bineinteles, aceasta solutie nu se incadreaza in limita de timp.\r\n\r\nh3. Programare dinamica cu complexitatea $O(N^2^)$\r\n\r\nAlgoritmul descris anterior are complexitatea $O(N^3^)$. El se poate optimiza, insa, usor la complexitatea $O(N^2^)$.\r\n\r\n==code(c) |\r\ncmin[ 0 ] = 0\r\npentru i de la 1 la N\r\n  cmin[i] = infinit\r\n  dtotal = 0\r\n  cost_stocare = 0\r\n  pentru j de la i la 1\r\n    cost_stocare = cost_stocare + S[j] * dtotal\r\n    dtotal = dtotal + D[j]\r\n    cost_productie = F[j] + C[j] * dtotal\r\n    cost_total = cmin[j-1] + cost_productie + cost_stocare\r\n    daca cost_total < cmin[i] atunci\r\n      cmin[i]=cost_total\r\n==\r\n\r\nOptimizarea adusa este minora, dar importanta. In algoritmul anterior, cel de-al treilea ciclu era folosit pentru a aduna la costul total costul stocarii cantitatilor de cascaval. In varianta optimizata, am schimbat sensul de parcurgere al variabilei $j$ si, in felul acesta, putem calcula pe parcurs o parte din costul de stocare. Practic, la inceputul fiecarei iteratii din cel de-al doilea ciclu, $cost_stocare$ retine costul stocarii cantitatiior de cascaval din lunile $j+1, .., i$, el trebuind actualizat doar cu costul de stocare din luna $j$.\r\n\r\nh3. Programare dinamica cu complexitatea $O(N*log^2^N)$\r\n\r\nAceasta solutie este semnificativ diferita fata de primele doua si presupune cunoasterea structurii de date numita arbore de intervale. De data aceasta vom privi problema usor diferit. In principiu, vom dori sa calculam acelasi lucru ca si in solutiile anterioare, si anume $cmin[i]$, reprezentand costul total minim pentru a satisface cererile din primele $i$ luni. Cand calculam $cmin[i]$ putem alege luna $j$ in care se produce cantitatea de cascaval necesara in luna $i$ dintre $i$ valori $(1,2,..,i)$. Vom privi aceste $i$ optiuni ca pe niste functii $f1, f2, .., fi$. Valoarea unei functii $fj$ in punctul $x$, $fj(x)$, reprezinta costul total minim pentru satisfacerea cererilor din primele $x$ luni, in cazul in care luna $j$ a fost aleasa pentru productia cantitatii de cascaval necesara in luna $x$.\r\n\r\nSolutia va contine ciclul principal existent si in solutiile anterioare, in care este variata valoarea lui $i$. Pentru fiecare valoare a lui $i$ apare o functie noua $(fi)$, iar noi trebuie sa evaluam valoarea minima $fj(i)$ dintre toate functiile existente $(f1, f2, .., fi)$.\r\n\r\nInainte de trece mai departe vom introduce doi noi vectori $SP$ si $DP$, reprezentand sume partiale ale costurilor de stocare si ale cantitatilor de cascaval cerute:\r\n\r\n* $SPi = S1 + S2 + .. + Si$\r\n* $DPi = D1 + D2 + .. + Di$\r\n\r\nIn continuare vom defini mai detaliat functiile $fj$ care ne intereseaza. O functie $fj$ apare la momentul $j$ si este definita doar pentru valori $x$ de la $j$ la $N$. Valoarea initiala a functiei este: $fj(j)$ este: $fj(j) = cmin[j-1] + Fj + Cj * Dj$.\r\n\r\nDiferenta dintre doua valori consecutive ale functiei este: $Delta fj(i) = fj(i) - fj(i-1) = Cj * Di + (Sj + Sj+1 + .. + Si-1) * Di$\r\n\r\nAceasta diferenta reprezinta cu cat creste functia fata de momentul anterior. Diferenta contine costul necesar productiei a $Di$ kilograme in luna $j$ si costul necesar stocarii acestei cantitati din luna $j$ (inclusiv) pana in luna $i$ (exclusiv). Diferenta poate fi scrisa folosind vectorul $SP$ introdus anterior, astfel: $Delta fj(i) = Cj * Di + (SPi-1 - SPj-1) * Di$.\r\n\r\nPutem rescrie aceasta diferenta intr-un mod si mai convenabil, in felul urmator: $Delta fj(i) = SPi-1 * Di + (Cj - SPj-1) * Di$. Observam ca diferenta consta dintr-un termen ce depinde doar de punctul in care se evalueaza functia $(i)$ si un termen ce reprezinta un produs dintre un factor ce depinde doar de definitia functiei (constant pentru functia $fj$) si un factor ce depinde doar de punctul in care este calculata functia. Vom nota valoarea $Cj - SPj-1$ cu $Pj$.\r\n\r\nSa ne gandim ce efect are acest mod de scriere al diferentei dinte doua valori consecutive ale unei functii $fi$. In momentul in care trecem de la valoarea $i-1$ la valoarea $i$, toate functiile $fj$ anterioare cresc cu aceeasi valoare $SPi-1 * Di$, precum si cu produsul $Pj * Di$. Singurul inconvenient in tratarea unitara a tuturor functiilor existente la momentul $i$ este reprezentat de aparitia unei functii noi, $fi$. Pentru aceasta, vom schimba putin definitia functiilor. Vom considera ca fiecare functie $fi$ are o valoare initiala in punctul $i-1$, chiar daca ea nu exista, practic, la momentul $i-1$: $fi(i-1) = cmin[i-1] + Fi$\r\n\r\nIn felul acesta, avem $Delta fi(i) = fi(i) - fi(i-1) = Ci * Di = (Ci + SPi-1 - SPi-1) * Di = SPi-1 * Di  + (Ci - SPi-1) * Di = SPi-1 * Di + Pi * Di.$\r\n\r\nFolosind aceasta scriere, putem considera ca toate functiile $fj$ $(j=1,..,i)$ au crescut de la pasul $i-1$ la pasul $i$ cu o valoare $Delta fj(i)$ definita in mod unitar.\r\n\r\nRevenind la solutie, la fiecare pas $i$ va trebui sa determinam minimul dintre valorile $fj(i)$, cu $j$ de la $1$ la $i$ si sa atribuim acest minim lui $cmin[i]$. O solutie care ar calcula valoarea fiecarei functii ar fi prea lenta, avand complexitatea $O(N^2^)$. Chiar si excluzand functiile care nu mai au sanse sa fie minime in viitor, solutia tot nu ar obtine punctaj maxim, din cauza depasirii limitei de timp (totusi, solutia nu trebuie exclusa de la bun inceput, deoarece, cu niste optimizari minore, ea va avea complexitatea $O(N * numarul de functii candidate \"active\")$, iar numarul de functii candidate \"active\" este, in cele mai multe cazuri, semnificativ mai mic decat $N$). In continuare va fi prezentata o modalitate eficienta de determinare a acestei valori minime.\r\n\r\nIntai sa observam ca orice valoare $cmin[i]$ contine o suma de valori constante, pe care le putem calcula de la inceput. $cmin[i]$ va contine suma valorilor $(SPj-1 * Dj)$ (cu $j$ de la $1$ la $i$). Aceasta este suma termenilor comuni fiecarei $Delta fj$. Prin urmare, vom modifica definitiile functiilor noastre pentru a exclude aceasta suma de valori constante si vom adauga suma respectiva la sfarsit, cand vom afisa rezultatul.\r\n\r\nAsadar, vom considera ca $Delta fj(i) = (Cj - SPj-1) * Di = Pj * Di$. Conform acestei noi definitii, valorile calculate $cmin[i]$ nu mai au semnificatia initiala. Totusi, adaugand la valoarea $cmin[N]$ pe care o vom obtine folosind noile definitii ale functiilor, suma precizata, vom obtine costul total minim dorit. Avantajul excluderii acestei sume din calculul valorilor $cmin[i]$ va fi vizibil in continuare.\r\n\r\nSa consideram o reprezentare in plan a functiilor $fj$, in care abscisele $x$ iau valori de la $0$ la $N$, iar ordonatele corespund valorilor functiilor $fj$. Aceste valori pot fi acum si negative, doarece $Pj$ poate fi o valoare negativa. Aceasta reprezentare ne este folositoare doar daca o modificam in felul urmator: abscisa corespunzatoare lunii $i$ este $DP[i]$. Folosind reprezentarea in plan modificata, se observa ca functiile $fj$ sunt niste semidrepte. Acest lucru este evident si din definitia lor. Ele pornesc de la o valoare initiala si apoi cresc pentru fiecare unitate a coordonatei $x$ cu o valoare egala cu $Pj$, corespunzand pantei semidreptei.\r\n\r\nIn acest caz, fiecare functie $fj$ are valoarea minima dintre toate functiile pe un interval de abscise $[lj, rj]$ sau nu are niciodata valoarea minima dintre toate functiile. Acest lucru se poate demonstra usor. Sa presupunem ca functia $fj$ este minima pe doua intervale disjuncte $[lj1, rj1]$ si $[lj2, rj2]$, cu $lj2 &gt; rj1$. Sa presupunem ca la abscisa $rj1$, o alta functie $fk$ a depasit functia $fj$. Mai exact, functia $fk$ avea valori mai mari decat functia $fj$, iar dupa momentul $rj1$ a atins valori mai mici. Pentru ca o functie sa o depaseasca pe alta, este necesar ca panta functiei respective sa aiba o valoare mai mica decat a functiei depasite. Prin urmare, $Pk &lt; Pj$. Dar in aceste conditii, de la abscisa $rj1$ incolo, functia $fk$ va avea mereu valori mai mici decat functia $fj$, astfel ca functia $fj$ nu va mai fi niciodata minima. O alta situatie in care functia $fj$ ar putea sa nu mai fie minima dupa abscisa $rj1$ este pentru ca a aparut o functie $fk$ cu o valoare initiala mai mica decat $fj$, dar o panta mai mare, astfel ca, in cele din urma, functia $fj$ o va depasi pe functia $fk$ si va redeveni minima. Aceasta situatie este si ea imposibila, din modul de calcul al valorii initiale al unei functii $fk$. Aceasta valoare initiala este valoarea minima a unei functii existente la momentul $k-1$, plus valoarea $Fk$ $(Fk &ge; 0)$, iar valoarea minima la momentul aparitiei functiei $fk$ este chiar valoarea functiei $fj$.\r\n\r\nFolosind observatia ca fiecare functie este minima pe cel mult un interval, putem folosi un arbore de intervale pentru a stoca in el semidrepte. Aceasta este o utilizare oarecum neobisnuita a unui arbore de intervale, dar vom vedea ca este foarte utila in cazul acestei probleme. Pseudocodul solutiei este urmatorul:\r\n\r\n==code(c) |\r\n// calculeaza vectorii SP si DP  \r\nSP[ 0 ] = 0  \r\nDP[ 0 ] = 0  \r\npentru i de la 1 la N  \r\n  SP[i] = SP[i-1] + S[i]  \r\n  DP[i] = DP[i-1] + D[i]  \r\n// calculeaza vectorul cmin  \r\ncmin[ 0 ] = 0  \r\npentru i de la 1 la N  \r\n  finit[i] = cmin[i-1] + F[i]  \r\n  P[i] = C[i] - SP[i-1]  \r\n  [li,ri] = find_interval(i) // gaseste intervalul [li,ri] pe care functia fi este minima  \r\n  daca intervalul [li, ri] nu este vid  \r\n    update(li, ri, i, radacina_arborelui_de_intervale)  \r\n  cmin[i] = get_min(i) // determina valoarea minima in punctul i dintre toate functiile existente  \r\nsuma = 0  \r\npentru i de la 1 la N  \r\n  suma = suma + SP[i-1] * D[i]  \r\nafisaza cmin[N] + suma  \r\n==\r\n\r\nCele $3$ functii a caror implementare mai trebuie descrisa in detaliu sunt: $find_interval$, $update$ si $get_min$.\r\n\r\nh4. Functia $find_interval$\r\n\r\nAceasta functie cauta binar, intre $i$ si $N$, prima luna $li$ in care functia $fi$ are o valoare mai mica decat toate celelalte functii. In mod similar se cauta binar si ultima luna $ri$ in care functia $fi$ are o valoare mai mica decat celelalte functii. Pentru a gasi capatul stanga al intervalului pe care o functie este minima, va trebui sa observam cum variaza functia in raport cu valoarea minima de la fiecare moment. O descriere generala a acestui comportament (care exclude cazurile particulare) este urmatoarea: la momentul aparitiei, functia va avea o valoarea mai mare decat valoarea minima din acel moment, apoi diferenta va scadea treptat, pana cand functia devine minima ; functia ramane minima pana la un anumit moment, dupa care diferenta dintre valorile functiei si valoarea minima creste. Acest comportament sugereaza ca trebuie folosita o cautare binara pe \"derivata\" functiei (adica pe diferentele dintre 2 valori consecutive ale functiei si valoarea minima a unei functii in punctele respective).\r\n\r\nPseudocodul pentru calculul capatului stanga al intervalului in care functia fi este minima este urmatorul:\r\n\r\n==code(c) | find_interval(i)  \r\n  left=i\r\n  right=N\r\n  li=N+1\r\n  cat timp left <= right\r\n    mid = (left+right)/2\r\n    fi_mid_1 = finit[i]+(DP[mid]-DP[i-1]) * P[i] // valoarea in punctul DP[mid+1]\r\n    fi_mid_2 = finit[i]+(DP[mid + 1]-DP[i-1]) * P[i] // valoarea in punctul DP[mid]\r\n    fmin1=get_min(mid+1) // valoarea minima in punctul DP[mid+1]\r\n    fmin2=get_min(mid) // valoarea minima in punctul DP[mid]\r\n    df1 = fi_mid_1 - fmin1\r\n    df2 = fi_mid_2 - fmin2\r\n    daca (df1 < 0)\r\n      li = mid\r\n      right = mid - 1\r\n    altfel\r\n    daca (df1 - df2 > 0)\r\n      left = mid + 1\r\n    altfel\r\n      right = mid - 1\r\n// la sfarsit, in li se afla capatul stanga al intervalului in care fi este minima (sau N+1 daca nu exista un astfel de interval)\r\n==\r\n\r\nFunctiile $update$ si $get_min$ se aplica arborelui de intervale si au complexitate $O(logN)$. Complexitatea functiei $find_interval$ este $O(log^2^N)$.\r\n\r\nFiecare nod al arborelui de intervale memoreaza indicele $i$ al unei semidrepte al carei interval $[li,ri]$, in momentul determinarii acestuia, continea complet intervalul corespunzator nodului din arborele de intervale. De asemenea, fiecarui nod al arborelui de intervale ii corespunde un interval $[ l[nod], r[nod] ]$.\r\n\r\nh4. Functia $update$\r\n\r\nPseudocodul functiei $update$ este prezentat in continuare:\r\n\r\n== code(c) | update(li,ri,i,nod) \r\n  daca intervalul corespunzator nodului nod este chiar [li,ri], atunci\r\n    index[nod]=i\r\n  altfel\r\n    fs = fiul stanga al nodului nod\r\n    fd = fiul dreapta al nodului nod\r\n    daca l[fd] > ri atunci\r\n     update(li,ri,i,fs)\r\n   altfel\r\n   daca r[fs] < li atunci\r\n     update(li,ri,i,fd)\r\n   altfel\r\n     update(li,r[fs],i,fs)\r\n     update(l[fd],ri,i,fd)\r\n==\r\n\r\nh4. Functia $get_min$\r\n\r\nFiecare nod din arbore are o referinta catre tatal sau $(tata[nod])$. Radacina arborelui are o referinta catre o valoare nedefinita $(NEDEFINIT)$. Pseudocodul functiei $get_min$ este urmatorul:\r\n\r\n== code(c) | get_min(i)   \r\n  nod = nodul din arbore corespunzator intervalului [i,i] \r\n  val_min=infinit \r\n  cat timp nod != NEDEFINIT \r\n    k=index[nod] \r\n    daca k este definit atunci \r\n      fki = finit[k] + (DP[i] - DP[k-1]) * P[k] \r\n      daca fki < val_min atunci \r\n        val_min=fki \r\n    nod=tata[nod] \r\n  intoarce val_min \r\n==\r\n\r\nh3. Link-uri utile\r\n\r\n* \'Sensitivity Analysis of the Economic Lot-Sizing Problem / MIT\':http://dspace.mit.edu/bitstream/1721.1/5146/1/OR-238-90.pdf -> articolul prezinta o solutie a acestei probleme avand complexitatea optima $O(N*logN)$ \r\n\r\nh3. Probleme asemanatoare\r\n\r\n* \'Euro / BOI 2003\':problema/euro\r\n* \'Yogurt Factory / USACO 2005\':http://acm.pku.edu.cn/JudgeOnline/problem?id=2393\r\n* \'Branza / preONI 2007\':problema/branza\r\n* \'Rompetrol / Autumn Warmup 2007\':problema/rompetrol\r\n\r\nh2(#cercuri3). \'Cercuri3\':problema/cercuri3\r\n\r\nO metoda simpla este sa translatam primul cerc in originea sistemului de axe de coordonate si sa il rotim pe cel de-al doilea pana cand centrul acestuia se afla pe axa $OX$ (la coordonata $X$ egala cu distanta dintre cele $2$ centre). Trebuie analizate cateva cazuri, pe baza valorilor razelor celor $2$ cercuri si a distantei dintre centrele lor (cazurile simple sunt cand unul din cercuri se afla complet in interiorul, respectiv complet in exteriorul celuilalt cerc). In cazul in care se decide ca cele $2$ cercuri se intersecteaza in $2$ puncte, vom observa ca, in urma translatiei si rotatiei efectuate, cele $2$ puncte de intersectie se vor afla la aceeasi coordonata $x$, dar la coordonate $y$ opuse (egale in modul, dar opuse ca semn). Vom determina cele $2$ coordonate folosind \'Teorema lui Pitagora generalizata\':http://en.wikipedia.org/wiki/Pythagorean_theorem in triunghiul format din centrele celor $2$ cercuri si fiecare din cele $2$ puncte de intersectie (deoarece cunoastem lungimile tuturor laturilor). Aria comuna a celor 2 cercuri este acum formata din 2 bucati de cerc, de o parte si de alta a segmentului ce uneste cele 2 puncte de intersectie. Aria fiecareia din cele 2 bucati de cerc se poate scrie ca diferenta dintre aria unui sector de cerc (corespunzator segmentului ce uneste punctele de intersectie) si aria unui triunghi (format din centrul unui cerc si cele 2 puncte de intersectie). O formulare suficient de generala a expresiilor ce calculeaza aria comuna permite tratarea unitara a cazurilor in care cel de-al doilea cerc are centrul in exteriorul, respectiv in interiorul primului cerc.\r\n\r\nh3. Link-uri utile\r\n\r\n* \'Circle-Circle Intersection / Mathworld\':http://mathworld.wolfram.com/Circle-CircleIntersection.html\r\n\r\nh3. Probleme asemanatoare\r\n\r\n* \'Cercuri / Happy Coding 2005 [2]\':problema/cercuri\r\n* \'Cerc2 / Happy Coding 2007\':problema/cerc2\r\n\r\nh2(#antitero). \'Antitero\':problema/antitero\r\n\r\n==code(c) |\r\ncat timp (exista un soldat care se poate deplasa in siguranta intr-o pozitie de unde poate omori un terorist)\r\n  deplaseaza soldatul in pozitia respectiva si elimina teroristul\r\ndaca toti soldatii pot ajunge in siguranta la destinatie, atunci deplaseaza-i acolo si incheie misiunea cu succes\r\naltfel: \"Mission aborted!\"\r\n==\r\n\r\nAceasta este schita unui algoritm usor de implementat care rezolva problema. Practic, se incearca eliminarea repetata a cat mai multor teroristi, dupa care se incearca deplasarea la destinatie. Rezolvarea problemei implica, asadar, doar parcurgeri repetate ale grafului (de exemplu, \'DF\':http://en.wikipedia.org/wiki/Depth-first_search sau \'BF\':http://en.wikipedia.org/wiki/Breadth-first_search), in care unele noduri sunt \"blocate\" (cele in care se afla teroristi in viata si cele amenintate de teroristi in viata).\r\n\r\nh2(#sistem2). \'Sistem2\':problema/sistem2\r\n\r\nProblema se rezolva generand permutari ale celor $N$ variabile si verificand daca ele verifica constrangerile. Ideea importanta este ca verificarea satisfacerii constrangerilor sa nu se realizeze abia dupa ce s-a generat cate o permutarea intreaga, deoarece o astfel de abordare nu s-ar incadra in limita de timp. Pe masura ce selectam o valoare pentru un element $i$ al permutarii, vom verifica toate constrangerile care contin acel element si elemente dinaintea lui $i$ (ale caror valori au fost, de asemenea, deja selectate). Daca cel putin o constrangere nu este satisfacuta, nu vom mai continua generarea permutarii in continuare, ci vom trece la valoarea urmatoare a elementului $i$ (scapand, astfel, de un numar posibil foarte mare de permutari pe care le-am fi generat degeaba). Aceasta optimizarea nu ne-ar fi prea folositoare daca, de exemplu, toate constrangerile contin ultimul element (si verificarea lor se poate face abia la sfarsit), insa, putem schimba ordinea in care selectam valorile elementelor. De exemplu, daca luam elementele in ordinea in care apar acestea in constrangeri (intai cele din prima constrangere, apoi cele din a doua care nu apar si in prima, apoi cele din a treia care nu apar in primele doua s.a.m.d.), putem garanta ca dupa selectarea valorilor a cel mult $4$ elemente vom putea verifica prima constrangere si ca dupa cel mult $8$ elemente putem verifica a doua constrangere. Daca schimbam si ordinea constrangerilor, in asa fel incat constrangerile cu numar mai mic de variabile sa fie primele, obtinem niste optimizari si mai bune. Alta optimizare utila ar fi aceea ca, daca o constrangere contine $P$ variabile, dupa setarea valorilor a $P-1$ dintre ele se poate calcula valoarea celeialalte variabile. De asemenea, pentru fiecare element a carui valoare nu a fost setata inca s-ar putea memora multimea valorilor posibile pe care le mai poate lua in continuare (pe baza variabilelor avand valori setate si a multimilor de valori posibile ale variabilelor cu valori nesetate inca, dar impreuna cu care se afla in cel putin o constrangere),\r\n\r\nIn concluzie, problema nu se rezolva in timp polinomial (lucru care se putea ghici dupa numarul mic de variabile), fiind necesare unele optimizari. Ea poate fi privita ca un caz particular al \'problemei satisfacerii constrangerilor\':http://en.wikipedia.org/wiki/Constraint_satisfaction, care este o problema generala, pentru care au fost studiati multi algoritmi si au fost gasite multe optimizari.\r\n\r\nh2(#optic). \'Optic\':problema/optic\r\n\r\nSa consideram, pe rand, fiecare nod $i$ al arborelui dat (in ordine, de la frunze spre radacina) si subarborele acestuia. Vom rezolva problema considerand ca arborele consta numai din subarborele cu radacina in nodul $i$. In felul acesta, cand vom considera nodul $i=1$, vom avea solutia pentru intreg arborele.\r\n\r\nPentru fiecare nod $i$ al arborelui, strategia optima de distribuire a mesajelor la toate nodurile din subarborele sau consta dintr-un numar $X$ de pasi (momente de timp). In primii $Y &le; X$ dintre acesti pasi, nodul $i$ va trimite mesaje unor noduri din subarborele sau (nu are sens sa existe momente in care nodul $i$ sa nu trimita mesaj, intercalate intre momente in care nodul $i$ trimite mesaj).\r\n\r\nLa fiecare din cei $Y$ pasi, un nod $j$ din subarborele lui $i$ va primi mesajul de la nodul $i$. In continuare, nodul $i$ nu va mai trimite niciodata vreun mesaj unui alt nod din subarborele lui $j$ (daca $i$ ar trimite un mesaj unui nod $j\'$ din subarborele lui $j$, $j$ nu ar putea trimite mesaje in acel pas ; de aceea, am putea decide ca nodul $j$ sa fie cel care trimite mesajul nodului $j\'$, in timp ce nodul $i$ ar putea trimite mesajul unui alt nod). Dupa ce un nod $j$ a primit mesajul de la nodul $i$, vom considera in continuare ca subarborele lui $i$ a ramas fara subarborele lui $j$ (e ca si cum intreg subarborele lui $j$ ar fi fost taiat din subarborele lui $i$).\r\n\r\nVom calcula valorile $Tmin[i][j]$, reprezentand numarul minim de pasi necesari pentru a distribui mesajul tuturor nodurilor din subarborele nodului $i$, considerand ca au fost efectuati primii $j$ pasi din cadrul strategiei optime a nodului $i$ si ca au fost taiate din subarborele lui $i$ toti subarborii primelor $j$ noduri care au primit mesajul direct de la nodul $i$. Evident, cand $i=1$, in $Tmin[ 1 ][ 0 ]$ vom avea numarul minim de pasi necesari pentru distributia mesajului la toate nodurile din arbore.\r\n\r\nVom calcula, in ordine (de la $j=0$), toate valorile $Tmin[i][j]$. Sa observam intai (pentru cazul $j=0$), ca $Tmin[i][ 0 ]$ trebuie sa fie mai mare sau cel putin egal cu $Tmin[f][ 0 ]$, unde $f$ este fiu al lui $i$. Vom cauta binar aceasta valoare, intre maximul dintre valorile $Tmin[f][ 0 ]$ si $N-1$. Sa presupunem ca am fixat, in cadrul cautarii binare, $T$ unitati de timp. Vom initializa fiecare fiu $f$ al lui $i$ ca aflandu-se in starea $s(f)=0$ (adica nu s-a efectuat nici o mutare din cadrul strategiei sale optime). Vom considera fiul $f$ al lui $i$ care are valoarea $Tmin[f][s(f)]$ maxima. Daca $T &gt; Tmin[f][s(f)]$, atunci trimitem mesajul nodului $f$, scadem din T o unitate de timp si mergem mai departe (ignorand nodul $f$ de acum inainte). Daca, la un moment dat, avem $T = Tmin[f][s(f)]$, atunci se demonstreaza (nu foarte usor, dar nici prea greu) ca nodul $i$ trebuie sa trimita mesaj nodului $j$ care este al $s(f)+1$-lea nod la care ar trimite mesaj nodul $f$ in cadrul strategiei sale optime. In felul acesta, taiem subarborele nodului $j$, scadem $T$ cu $1$ unitate si trecem nodul $f$ din starea $s(f)$ in starea $s(f)+1$ (pentru ca deja s-a efectuat o mutare din cadrul strategiei sale optime). Daca, la un moment dat, $T &lt; Tmin[f][s(f)]$, atunci trebuie incercata o valoare mai mare in cadrul cautarii binare.\r\n\r\nInainte de a calcula $Tmin[i][j+1]$ dupa ce am calculat $Tmin[i][j]$, memoram in $Mut[i][j]$ nodul la care a trimis mesaj nodul $i$ prima data (adica al $j+1$-lea nod din cadrul strategiei optime a nodului $i$) si in $F[i][j]$ fiul din subarborele caruia face parte nodul $Mut[i][j]$. De asemenea, starile fiiilor nodului $i$ se seteaza la valorile pe care le aveau inainte de a calcula $Tmin[i][j]$, incrementand doar starea fiului $F[i][j]$ cu $1$ (sau eliminand de tot fiul $F[i][j]$, daca $F[i][j] = Mut[i][j]$). Vom termina calculul acestor valori atunci cand $Tmin[i][j]=0$.\r\n\r\nPartea cea mai grea de demonstrat a algoritmului este data de cazul in care numarul de unitati de timp $T$ este egal cu maximul dintre $Tmin[f][s(f)]$. Intai vom observa ca e clar ca trebuie sa trimitem mesajul unui nod din subarborele lui f, in caz contrar, la momentul de timp urmator vom avea $T &lt; Tmin[f][s(f)]$. Problema consta in alegerea nodului caruia sa trimitem acest mesaj. Observam ca, in acest caz, problema este similara cazului in care nodul $f$, aflat in starea $s(f)$, a primit anterior mesajul de la cineva si trebuie sa il trimita unui nod din subarborele sau; dar aceasta problema am rezolvat-o deja, nodul care trebuie sa primeasca mesajul fiind $Mut[f][s(f)]$.\r\n\r\nPentru reconstituirea solutiei, vom initializa toate nodurile ca aflandu-se in starea $0$ si vom tine un vector cu nodurile la care a ajuns deja mesajul. Prima mutare va fi de la nodul $1$ la nodul $j = Mut[ 1 ][ 0 ]$. Pentru toate nodurile de pe calea de la $1$ (inclusiv) la $j$ (exclusiv), vom incrementa starea in care se afla acestea, apoi vom marca ca nodul $j$ a primit mesajul. La urmatorul moment de timp, vom lua fiecare nod care detine mesajul, vom verifica daca mai are de efectuat pasi din strategia sa optima si daca da, vom efectua pasul corespunzator in mod similar mutarii descrise mai sus.\r\n\r\nComplexitatea solutiei descrise este $O(N^3^ * logN)$.\r\n\r\nO dificultate suplimentara apare in momentul in care avem mai multi fii $f$ ai unui nod $i$, pentru care $Tmin[f][s(f)]$ are aceeasi valoare maxima. In aceasta situatie, va trebui sa il alegem pe cel pentru care sirul $Tmin[f][s(f)], Tmin[f][s(f)+1], ..$ este maxim din punct de vedere lexicografic. Justificarea este ca vrem sa scapam de acel fiu care ne-ar restrictiona cel mai mult mutarile ulterioare daca nu l-am taia acum. Mai exact, daca la un moment dat ajungem cu $T$-ul egal cu $Tmin[f][s(f)]$ (deoarece am eliminat altii fii si nu pe $f$), vrem ca acest fiu $f$ sa aiba sirul respectiv cat mai mic din punct de vedere lexicografic, pentru a ne restrictiona cat mai putin timpul.\r\n\r\nh3. Link-uri utile\r\n\r\n* \'Information Dissemination in Restricted Routing Networks / CiteSeer\':http://citeseer.ist.psu.edu/186949.html -> in acest articol este prezentata o solutie de complexitate O(N^3^) la aceasta problema\r\n\r\nh2(#zvon). \'Zvon\':problema/zvon\r\n\r\nSolutia \"oficiala\" are complexitatea $O(N*logN)$ si presupune calculul urmatoarelor valori: \r\n\r\n* $TMIN[i]$ = timpul minim necesar pentru a propaga zvonul in subarborele lui $i$, din momentul in care i afla zvonul. In mod clar, $TMIN[1]$ reprezinta rezultatul cautat.\r\n\r\nPentru a calcula $TMIN[i]$, vom calcula intai valorile $TMIN$ ale fiiilor lui $i$, pe care le vom sorta apoi descrescator: $TMIN[f1] &ge; TMIN[f2] &ge; .. &ge; TMIN[fK]$. Ordinea in care $i$ va transmite zvonul fiilor sai este chiar ordinea descrescatoare a valorilor $TMIN$ a acestora. In aceste conditii, $TMIN[i] = maxim { 1 + TMIN[f1], 2 + TMIN[f2], .., K + TMIN[fK] }$.\r\n\r\nh3. Probleme asemanatoare\r\n\r\n* \'Consiliul tribului / BOI 2003\':problema/trib\r\n* \'Optic / Happy Coding 2007\':problema/optic\r\n\r\nh2(#cerc2). \'Cerc2\':problema/cerc2\r\n\r\nObservam ca distanta dintre oricare $2$ puncte in care fotonul atinge cercul este aceeasi ca cea dintre punctul initial si punctul $(R*cos(alfa), R*sin(alfa))$. Fie aceasta distanta $D$. Dupa $S$ secunde, fotonul se afla la o distanta $S mod D$ de ultimul punct in care a atins cercul. Operatia $modulo$ se poate defini si pentru numere reale, scriind $S$ ca fiind $k*D + r$, unde k este un numar intreg (si $r$ este restul impartirii). Putem folosi acum Teorema lui Pitagora generalizata, pentru a determina distanta de la foton la centrul cercului, in triunghiul format din punctul curent, ultimul punct de atingere a cercului si centrul cercului. O metoda mai simpla de a calcula aceasta distanta este de a calcula distanta de la centrul cercului la segmentul dintre $2$ puncte consecutive in care fotonul atinge cercul (aceasta distanta este {$R*sin(beta)$}). Cum perpendiculara din centrul cercului pe acest segment il intersecteaza exact in mijloc, putem folosi distanta fotonului fata de mijlocul segmentului si apoi Teorema lui Pitagora intr-un triunghi dreptunghic, pentru a calcula distanta de la foton la centrul cercului (in triunghiul format de centrul cercului, mijlocul segmentului si pozitia fotonului, distanta respectiva este lungimea ipotenuzei).\r\n\r\nh3. Probleme asemanatoare\r\n\r\n* \'Cercuri / Happy Coding 2005 [2]\':problema/cercuri\r\n* \'Cercuri3 / Happy Coding 2007\':problema/cercuri3\r\n\r\nh2(#puteri2). \'Puteri2\':problema/puteri2\r\n\r\nProblema cere determinarea radicalului de ordin $P$ dintr-un numar mare. Exista mai multe metode de realiza acest lucru, dintre care voi mentiona doua:\r\n\r\n* Determinarea radicalului de ordin $P$ cifra cu cifra: Se determina intai numarul de cifre ale numarului (se incadreaza radicalul intre un $10^x^$ si $10^x+1^$), apoi se determina, pe rand, fiecare cifra a rezultatului; pentru fiecare pozitie, se incearca, pe rand, toate cifrele de la $0$ la $9$ si ne oprim la ultima cifra pentru care numarul ridicat la puterea $P$ (considerand ca cifrele de dupa cifra curenta sunt egale cu $0$), nu depaseste $N$-ul dat. Eventual, cifra curenta se poate cauta binar (poate fi util daca rezultatul este tinut intr-o baza mai mare decat $10$).\r\n* Cautarea binara a rezultatului, intre o limita inferioara si o limita superioara. Numarul fixat in cadrul cautarii binare se ridica la puterea $P$ si daca depaseste $N$-ul dat, se pastreaza jumatatea inferioara a intervalului de cautare; in caz contrar, se pastreaza jumatatea superioara a intervalului.\r\n\r\nPe langa alegerea uneia dintre cele $2$ metode, sunt necesare cateva optimizari suplimentare, precum:\r\n\r\n* ridicarea la puterea $P$ trebuie realizata folosind exponentiere logaritmica; in plus, chiar si in cadrul exponentierii logaritmice, putem sa nu efectuam toti pasii daca, la un moment dat, numarul de cifre ale numarului obtinut depaseste numarul de cifre ale lui $N$\r\n* efectuarea tuturor calculelor intr-o baza mai mare decat $10$ (solutia oficiala foloseste baza $10^4^$), deoarece, astfel, numarul de cifre ale numerelor ce intervin in calcule scade simtitor.\r\n* in cazul cautarii binare, intervalul initial de cautare nu trebuie sa fie $[1,N]$, ci un interval mai restrans (de exemplu, $[10^(X/P)-1^, 10^(X/P)+1^]$), unde $X$ este numarul de cifre ale numarului N dat.\r\n\r\nO alta optimizare care ar fi putut avea un impact simtitor asupra timpului de executie este inmultirea a doua numere mari in complexitate $O(C*logC)$, unde $C$ este numarul de cifre ale acestora,  insa implementarea unei astfel de operatii ar fi fost mai complicata (si nu era necesara pentru a obtine punctaj maxim la problema) (vezi \'aici\':http://numbers.computation.free.fr/Constants/Algorithms/fft.html)\r\n\r\nh2(#aimin). \'Aimin\':problema/aimin\r\n\r\nSolutia de complexitate $O(N^3^)$ este evidenta. Se calculeaza $HMIN[i, j]$, reprezentand inaltimea minima a unui arbore ce contine frunzele din intervalul $i, .., j$. $HMIN[i, i] = L{~i~}$, iar $HMIN[i, j] = 1 + min { max {HMIN[i,k], HMIN[k+1,j]} }$ (pentru $i &lt; j$ si $i &le; k &lt; j$ ). Raspunsul il avem in $HMIN[1, N]$. In mod evident, pentru limitele date, algoritmul nu are nici o sansa sa se incadreze in limita de timp (sau de memorie).\r\n\r\nPentru rezolvarea acestei probleme vom folosi un algoritm greedy, avand complexitatea $O(N)$. Vom parcurge sirul frunzelor de la stanga la dreapta si vom mentine o stiva ce corespunde drumului cel mai din dreapta a arborelui de inaltime minima de pana atunci. Sa presupunem ca am calculat arborele de inaltime minima ce corespunde primelor $i$ frunze si acest arbore are pe drumul cel mai din dreapta niste noduri aflate la nivelele $0, 1, 2, .., K$ (deci $K+1$ noduri in total). Pentru fiecare nod de pe acest drum, cunoastem nivelul acestuia, precum si inaltimea subarborelui ce are radacina in nodul respectiv ({$H[i]$}). Vom avea $H[ 0 ] &ge; 1 + H[ 1 ] &ge; 2 + H[ 2 ] &ge; .. &ge; K + H[K]$. Cand introducem a $i+1$-a frunza, ea va fi ultimul nod de pe drumul cel mai din dreapta al arborelui. Pentru a o introduce pe acest drum, va trebui sa introducem un nod suplimentar deasupra unui nivel $x$, care sa aiba ca fiu dreapta frunza $i+1$ si ca fiu stanga subarborele ce corespundea nivelului $x$ dinainte (si care avea inaltimea {$H[x]$}) - vom numi aceasta operatie *split* deasupra nivelului $x$. In urma acestei operatii, inaltimea subarborelui de pe nivelul $x$ si de pe drumul cel mai din dreapta va deveni egala cu $Hnou[x]=1+max{L[i+1], H[x]}$. Vom dori sa aplicam operatia de split unui nivel cat mai de jos, dar care sa nu determine cresterea inaltimii arborelui nostru (daca se poate). Mai exact, vom incerca sa aplicam operatia split deasupra unui nivel $x$, pentru care are loc proprietatea $1+Hnou[x] &le; H[x-1]$ (adica nu se mareste inaltimea subarborelui de pe nivelul {$x-1$}). In mod clar, daca un astfel de nivel $x &ge; 1$ nu exista, va trebui creata o radacina noua, iar inaltimea arborelui va creste (fiind egala cu {$1+max{H[ 0 ],L[i+1]}$}). Vom observa ca acest cel mai din dreapta drum al arborelui se comporta ca o stiva, deoarece, daca la un moment dat nu putem realiza operatia de split deasupra celui mai de jos nivel de pe drum, atunci va trebui neaparat sa o realizam mai sus si subarborele respectiv nu se va mai afla, dupa aceea, pe cel mai din dreapta drum al arborelui.\r\n\r\nCorectitudinea algoritmului prezentat poate fi demonstrata folosind urmatoarele elemente:\r\n\r\n* Presupunem ca avem un arbore de inaltime minima pana la pasul $i$. Daca la pasul $i+1$ nu aplicam operatia split deasupra nivelului $0$, atunci inaltimea arborelui nu creste si cum inaltimea minima pentru $i+1$ frunze nu poate fi mai mica decat cea pentru $i$ frunze, raspunsul este corect.\r\n* Daca pana la pasul $i$ avem un arbore de inaltime minima $HMIN[i]$ si la pasul $i+1$ ajungem sa aplicam operatia split deasupra radacinii, atunci avem $2$ cazuri:\r\n** Daca $L[i+1] &ge; HMIN[i]$, atunci noua inaltime $HMIN[i+1]$ va fi $1+L[i+1]$ si este optima (deoarece inaltimea minima este mai mare sau egala cu {$1+max{L[orice frunza]}$})\r\n** Daca $L[i+1]&lt;HMIN[i]$, atunci avem ca $H[ 0 ]=1+H[ 1 ]=2+H[ 2 ]=...=K+H[K]$ (in caz contrar nu am ajunge sa aplicam operatia de split deasupra radacinii). Vom presupune prin absurd ca ar exista un alt arbore de inaltime minima pana la pasul $i$, care sa aiba un drum cel mai din dreapta diferit de cel la care am ajuns, care ar fi permis introducerea frunzei $i+1$ fara a creste inaltimea arborelui. Aceasta este etapa cea mai importanta a demonstratiei si, in urma analizei catorva cazuri, se va ajunge la o contradictie; contradictia va consta in faptul ca acest presupus arbore ar urma sa aiba o inaltime mai mica decat $HMIN[i]$, ceea ce este absurd.\r\n\r\nPentru o abordare matematica formala a problemei, care foloseste notiuni de calcul algebric pentru obtinerea unui algoritm liniar, puteti citi urmatorul \'articol\':http://citeseer.ist.psu.edu/679514.html.\r\n\r\nPentru a obtine punctaj maxim, datorita limitei de timp nu foarte stricte, se putea implementa si un algoritm cu complexitatea $O(N*logN)$, folosind structuri de date precum \'arbori indexati binar\':http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=binaryIndexedTrees sau \'arbori de intervale\':arbori-de-intervale ; de exemplu, o solutie asemanatoare constructiei unui arbore \'Huffman\':http://en.wikipedia.org/wiki/Huffman_coding, bazata pe unirea repetata a cate doi subarbori alaturati pentru care maximul inaltimilor este minim.\r\n\r\nh2(#multimi). \'Multimi\':problema/multimi\r\n\r\nSe considera matricea $M$ cu $n$ linii si $m$ coloane, unde $M[i][j]=1$, daca $i$ este in $A{~j~}$ si $0$, altfel. Deoarece $A{~1~},...,A{~m~}$ separa multimea $[n]$, rezulta ca oricare $2$ linii ale matricei sunt diferite (daca liniile $k$ si $l$ ar fi egale, atunci $k$ si $l$ nu pot fi separate). De aici rezulta ca $n &le; 2^m^$ (numarul de linii posibile, astfel incat oricare $2$ sa fie diferite). Asadar, $m &ge; log{~2~}n$. Vom arata ca $m=(log{~2~}n) + 1$. Presupunem prin absurd ca $m=log{~2~}n$. Din principiul lui Dirichlet se obtine cu usurinta faptul ca fie apare in matrice linia $00..0$ (contradictie cu conditia de acoperire), fie matricea contine 2 linii identice, ceea ce este absurd.\r\n\r\nPentru $m=(log{~2~}n)+1$ se poate da exemplul urmator: $A{~j~}$ este multimea numerelor mai mici sau egale cu $n$ care au $1$ pe bitul $(j-1)$ din reprezentarea lor binara pe $m$ biti (am numarat bitii de la stanga catre dreapta, incepand cu bitul {$0$})\r\n\r\nh2(#nrbanda). \'Nrbanda\':problema/nrbanda\r\n\r\nSe roteste intreg sirul la stanga, pana cand pe prima pozitie se afla numarul $1$. Apoi problema se rezolva incremental, pas cu pas. La pasul $i$ ({$2 &le; i &le; N$}), avem numerele de la $1$ la $i-1$ pe primele $i-1$ pozitii si vom dori sa aducem numarul $i$ pe pozitia $i$ (daca nu se afla deja acolo). Pentru aceasta, rotim sirul spre dreapta pana cand numarul $i$ ajunge pe ultima pozitie. Apoi separam sirul intre pozitiile $N-1$ si $N$ pana cand pe pozitiile $N-i+1, N-i+2, .., N-1$ se afla numerele $1, 2, .., i-1$ (la fiecare separare, numarul $i$ ramane pe ultima pozitie, iar numerele de pe pozitiile $1,..,N-1$ se rotesc spre stanga). Apoi se roteste intregul sir spre stanga, pana cand numerele $1, .., i$ ajung pe pozitiile $1, .., i$.\r\n\r\nh3. Probleme asemanatoare\r\n\r\n* \'Order2 / Lista lui Francu\':problema/order2\r\n\r\nh2(#tramvai). \'Tramvai\':problema/tramvai\r\n\r\nSe construieste un graf al punctelor de intersectie dintre oricare $2$ drepte. Acest graf are $O(N^2^)$ noduri, insa fiecare nod are cel mult $4$ vecini (cate $2$ pe fiecare din cele $2$ drepte care il determina). Problema se reduce acum la determinarea drumului minim intre $2$ puncte in acest graf. Algoritmul folosit de solutia oficiala este \'Dijkstra\':http://en.wikipedia.org/wiki/Dijkstra\'s_algorithm cu heap, care are complexitatea $O(N^2^*logN)$, insa se poate folosi cu succes si algoritmul \'Bellman-Ford\':http://en.wikipedia.org/wiki/Bellman-Ford_algorithm, implementat folosind o coada. Aceasta varianta, cunoscuta ca algoritmul Bellman-Ford-Moore, are o complexitate teoretica mare, dar, in practica, merge foare bine; este, posibil, insa, ca, in cazul acestei probleme, sa fie necesare unele optimizari pentru a se incadra in limita de timp - de exemplu, folosirea euristicii \"parent checking\". Aceasta euristica se refera la urmatoarea situatie: Sa presupunem ca am extras din coada nodul $X$ (primul nod din coada) si urmeaza sa incercam sa facem update-uri la distantele tuturor vecinilor nodului $X$, folosind distanta calculata pana acum pentru $X$. De asemenea, sa presupunem ca nodul care i-a facut update la distanta minima nodului $X$ este $T$ ({$T$} mai este numit si parintele lui $X$, deoarece este nodul chiar dinaintea lui $X$ de pe drumul minim pana la $X$). Inainte sa incercam sa facem update pentru toti vecinii lui $X$, verificam daca nodul $T$ se afla in coada. Daca se afla in coada, atunci nu mai facem update folosind nodul $X$ si trecem la urmatorul nod din coada. Motivul este urmatorul: Daca nodul $T$ se afla in coada, el a fost introdus acolo dupa ce i-a facut update distantei pana la nodul $X$; noua valoarea a distantei minime pana la $T$ este mai mica decat in momentul cand s-a calculat distanta minima pana la $X$, astfel ca, atunci cand vom extrage din coada nodul $T$, se va micsora in mod sigur si distanta pana la $X$. Prin urmare, nu are rost sa facem acum update-uri folosind nodul $X$, deoarece acesta are calculata o distanta despre care stim sigur ca va fi micsorata in curand.\r\n\r\n\r\n\r\nh2(#biti3). \'Biti3\':problema/biti3\r\n\r\nVom considera bitii fiecarui sir numerotati de la $N$ la $1$ (de la stanga la dreapta) si vom calcula $num[i, j]$ = numarul de siruri de $i$ biti, continand exact $j$ biti de $1$. $num[i, 0] = 1$. Pentru $j &gt; i$, avem $num[i, j] = 0$ ; altfel, $num[i, j] = num[i-1, j] + num[i-1, j-1]$ (cele $2$ variante corespund deciziei de a plasa un bit de $0$ pe pozitia $i$, caz in care pe pozitiile $1,..,i-1$ se afla $j$ biti de $1$, respectiv un bit de $1$ pe pozitia $i$, caz in care pe pozitiile $1,..,i-1$ se mai afla doar $j-1$ biti de $1$). Alt mod de a calcula aceste valori este urmatorul: $num[i,j] = Combinari de i luate cate j$.\r\n\r\nFolosind aceste valori, vom determina bitii celui de-al $M$-lea sir, unul cate unul, pornind de la al $N$-lea bit. La fiecare pas, va trebui sa determinam cate siruri incep cu bitul $0$ si cate siruri incep cu bitul $1$. La inceput, vor exista $num[N-1,3]$ siruri care incep cu bitul $0$ si $num[N-1,2]$ siruri care incep cu bitul $1$. Este evident ca, la un anumit pas, toate sirurile care incep cu $0$ se vor afla inaintea tuturor sirurilor care incep cu $1$. De aceea, daca $M$ &lt; numarul sirurilor care incep cu $0$, bitul respectiv va fi $0$; in caz contrar, bitul va fi $1$. Daca bitul este $1$, inainte de a trece la pasul urmator, va trebui sa actualizam valoarea lui $M$, in asa fel incat sa sarim peste toate sirurile care incep cu $0$ ({$M = M - numarul de siruri care incep cu 0$}), precum si sa tinem cont de faptul ca am mai consumat inca un bit de $1$. Algoritmul in pseudocod este urmatorul:\r\n\r\n== code(c) | nrbiti = 3  \r\nfor i = N -> 1  \r\n  daca num[i-1, nrbiti] >= M atunci  \r\n    bitul i este 0  \r\n  altfel  \r\n    bitul i este 1  \r\n    M = M - num[i-1, nrbiti]  \r\n    nrbiti = nrbiti - 1 \r\n==\r\n\r\nh3. Probleme asemanatoare\r\n\r\n* \'Stringsobits / USACO 1998\':http://oldweb.uwp.edu/academic/mathematics/usaco/1998/Spring/prob.htm#p5\r\n* \'Word Encoding / ACM ICPC NWERC 2004\':http://acm.pku.edu.cn/JudgeOnline/problem?id=2058\r\n* \'Coding of Permutations / POJ\':http://acm.pku.edu.cn/JudgeOnline/problem?id=1349\r\n* \'Bits of Trinity / ACM ICPC NWERC 1999\':http://www.acm.inf.ethz.ch/ProblemSetArchive/B_EU_NWRC/1999/Problems.pdf\'\r\n* \'Cuvinte / Stelele Informaticii 2003\':problema/cuvinte\r\n* Parantezari / Baraj ONI 2000\r\n\r\nh2(#clear). \'Clear\':problema/clear\r\n\r\nProbleme cere acoperirea cu numar minim de drumuri/cicluri a unui subgraf al grafului-grid $MxN$. Problema este foarte asemanatoare cu problema \'Kcity\':problema/kcity , propusa in cadrul \'rundei 3 a concursului Autumn-Warmup 2007\':http://infoarena.ro/autumn-warmup-2007/runda-3 si, daca numerotam nodurile grafului incepand de la $1$, parcurgand matricea pe linii, iar pentru fiecare linie, pe coloane, obtinem un graf care are aceeasi proprietate cu cel din Kcity (modulul diferentei dintre numerele asociate a doua noduri conectate printr-o muchie este limitat de o constanta: $7$, respectiv $10$). Totusi, aplicand direct ideea de rezolvare de la Kcity, se obtine un numar prea mare de stari, care nu permite incadrarea solutiei in limita de timp stabilita.\r\n\r\nh3. Solutia 1 $(O(M * nr_stari(N) * O(4^N^)))$\r\n\r\nh4. Acoperirea cu numar minim de drumuri\r\n\r\nVom calcula valorile $minp[i, S]$, reprezentand numarul minim de drumuri cu care pot fi acoperite toate zonele afectate de pe liniile $1,..,i$, iar pe linia $i$, configuratia drumurilor este data de starea $S$. Starea $S$ contine, pentru fiecare coloana de pe linie, un numar reprezentand starea coloanei respective:\r\n\r\n* $0$ - zona de pe coloana respectiva are gradul $2$ (este in interiorul unui drum) sau are valoarea $0$ in matrice\r\n* $num &gt; 0$ - zona respectiva este capatul unui drum (avand identificatorul $num$)\r\n\r\nIn cadrul unei stari, identificatorul unui drum se poate repeta de cel mult $2$ ori (deoarece un drum are maxim $2$ capete). Identificatorii din starea $S$ au valori ordonate crescator in functie de prima aparitie in cadrul starii S. Observam ca nu mai trebuie sa identificam explicit un nod avand gradul $0$ (reprezentand un drum format dintr-un nod), deoarece orice nod din starea $S$ mai poate fi conectat doar la cel mult un alt vecin (de pe linia urmatoare). Proprietatea importanta care reduce mult numarul de stari este ca drumurile existente in starea $S$ respecta conditia de \"parantezare\": mai exact, daca cele $2$ capete ale unui drum $X$ se afla pe coloanele $c1$ si $c2$, iar cele $2$ capete ale unui drum $Y$ se afla pe coloanele $c3$ si $c4$, atunci $[c1, c2]$ este inclus in $[c3, c4]$ (sau invers). Aceasta proprietate se datoreaza faptului ca orice subgraf al grafului-grid este planar.\r\n\r\nPentru a calcula starile asociate liniei $i$, vom porni de la fiecare stare $S\'$ asociata liniei $i-1$ si vom folosi un algoritm de backtracking pe linia $i$ care va genera starile $S$ ce pot fi obtinute din starea $S\'$, alegand, pentru fiecare zona afectata de pe linia $i$, cate o varianta posibila dintre urmatoarele: \r\n\r\n* incepe drum nou (in cazul functiei de backtracking vom diferentia nodurile ce au grad $0$, de celelalte noduri, insa atunci cand se calculeaza starea corespunzatoare liniei, aceste noduri vor primi un identificatior de drum strict pozitiv) -> numarul de drumuri creste cu 1\r\n* uneste nodul curent de nodul din stanga -> numarul de drumuri ramane constant\r\n* uneste nodul curent de nodul de sus -> numarul de drumuri ramane constant\r\n* uneste nodul curent de nodul de sus, precum si de cel din stanga (numai daca nodul din stanga si cel de sus nu fac parte din acelasi drum si amandoua sunt capete de drumuri) -> numarul de drumuri scade cu 1\r\n\r\nLa final, vom alege valoarea minima dintre valorile $minp[M, S]$. Acest algoritm are, insa, o complexitate de timp prea mare si nu se incadreaza in limita de timp.\r\n\r\nh4. Acoperirea cu numar minim de cicluri\r\n\r\nVom calcula valorile $minc[i, S]$, reprezentand numarul minim de cicluri (inchise), astfel incat fiecare nod de pe liniile $1,..,i$ sa se afle pe un ciclu inchis sau deschis. Starea $S$ contine, pentru fiecare coloana de pe linie, un numar reprezentand starea coloanei respective:\r\n\r\n* 0 - zona de pe coloana respectiva are gradul $2$ (este in interiorul unui ciclu inchis sau deschis) sau are valoarea $0$ in matrice\r\n* $num &gt; 0$ - zona respectiva este capatul unui ciclu deschis (avand identificatorul $num$)\r\n\r\nIn cadrul unei stari, fiecare identificator al unui capat de ciclu deschis apare de exact $2$ ori (nu pot ramane capete de cicluri deschise in spate, caci aceste cicluri nu ar mai putea fi inchise ulterior). La fel ca si in cazul acoperirii cu cicluri, identificatorii ciclurilor sunt numerotati de la $1$, crescator, in functie de prima aparitie in cadrul starii, avand si ei proprietatea de \"parantezare\".\r\n\r\nPentru a calcula starile asociate liniei $i$, vom porni de la fiecare stare $S\'$ asociata liniei $i-1$ si vom folosi un algoritm de backtracking pe linia $i$ care va genera starile $S$ ce pot fi obtinute din starea $S\'$, alegand, pentru fiecare zona afectata de pe linia $i$, cate o varianta posibila dintre urmatoarele: \r\n\r\n* incepe ciclu deschis nou (in cazul functiei de backtracking vom diferentia nodurile ce au grad 0, de celelalte noduri, insa atunci cand se calculeaza starea corespunzatoare liniei, aceste noduri vor primi un identificatior de ciclu strict pozitiv) / aceasta varianta este aplicabila numai daca nodul din stanga nu este si el un ciclu deschis nou si daca nodul de deasupra este in starea 0 -> numarul de cicluri inchise ramane constant\r\n* uneste nodul curent de nodul din stanga / aceasta varianta este aplicabile numai daca nodul de deasupra se afla in starea $0$ iar cel din stanga nu se afla in starea $0$ -> numarul de cicluri inchise ramane constant\r\n* uneste nodul curent de nodul de deasupra / aceasta varianta este aplicabila numai daca in nodul de deasupra nu avem starea 0, iar in nodul din stanga nu s-a deschis un ciclu nou -> numarul de cicluri inchise ramane constant\r\n* uneste nodul curent de nodul de sus, precum si de cel din stanga / numai daca atat nodul de sus, cat si cel din stanga nu se afla in starea $0$\r\n** daca nodul din stanga si cel de sus fac parte din acelasi ciclu -> numarul de cicluri inchise creste cu 1\r\n** daca nodul din stanga si cel de sus nu fac parte din acelasi ciclu -> numarul de cicluri inchise ramane constant (cele $2$ cicluri deschise se combina intr-un singur ciclu deschis)\r\n\r\nLa final, rezultatul dorit il gasim in $minp[M, S{~0~}]$, unde $S{~0~}$ este starea in care toate nodurile de pe linia $M$ se afla in starea $0$ (sunt in interiorul unui ciclu). Ca si in cazul acoperirii cu drumuri, nici aceasta solutie nu se incadreaza in limita de timp. Totusi, din cauza restrictiilor suplimentare de generare a starilor (trebuie sa nu se \"uite\" cicluri deschise in urma), algoritmul de backtracking are, in general, mai putine optiuni de continuare. Din acest motiv, numarul de coloane pentru acest caz este $10$ (fata de $7$ in cazul acoperirii cu drumuri).\r\n\r\nh3. Solutia 2 $(O(M * N * nr_stari(N)))$\r\n\r\nh4. Acoperirea cu numar minim de drumuri\r\n\r\nVom parcurge matricea pe linii, si pentru fiecare linie, pe coloane. Vom mentine o stare $S$ asemanatoare celei din solutia prezentata mai sus, la care se mai adauga un indice $C$ $(1 &le; C &le; N)$, avand semnificatia ca valorile de la $C+1$ la $N$ se refera la pozitiile de pe linia de deasupra, iar valorile de pe pozitiile de la $1$ la $C$ (din cadrul starii) se refera la linia curenta. Mentinand starea in acest fel, cand ajungem la elementul de pe linia $L$ si coloana $C$, vom calcula toate starile pentru care indicele este egal cu $C$. Pentru aceasta, vom parcurge toate starile $S\'$ corespunzatoare coloanei anterioare ({$C-1$} sau $N$, daca $C$ este prima coloana) si vom genera toate starile $S$ cu indicele egal cu $C$, avand de ales dintre urmatoarele optiuni:\r\n\r\n* incepe drum nou -> numarul de drumuri creste cu 1\r\n* uneste nodul curent de nodul din stanga -> numarul de drumuri ramane constant\r\n* uneste nodul curent de nodul de sus -> numarul de drumuri ramane constant\r\n* uneste nodul curent de nodul de sus, precum si de cel din stanga (numai daca nodul din stanga si cel de sus nu fac parte din acelasi drum) -> numarul de drumuri scade cu 1\r\n\r\nSunt, practic, aceleasi optiuni ca si cele din prima solutie, numai ca acum nu mai facem backtracking pe fiecare linie. Fata de solutia anterioara, care memora starile numai la sfarsitul unei linii, acum avem si stari \"partiale\", pana la o anumita coloana de pe o linie. Din cauza ca avem stari \"partiale\", va trebui sa consideram, pentru coloana curenta, si posibilitatea ca elementul respectiv sa fie singurul element de pe un drum (folosind, de exemplu, valoarea $-1$ pentru a codifica acest lucru). Pentru starile ce corespund ultimei coloane, aceasta posibilitate nu este necesar sa fie luata in considerare.\r\n\r\nh4. Acoperirea cu numar minim de cicluri\r\n\r\nSolutia pentru acoperirea cu numar minim de cicluri se bazeaza tot pe memorarea unor stari \"partiale\" (pentru fiecare coloana de pe o linie), spre deosebire de solutia ce memora doar stari pentru cate o linie completa. Prin memorarea acestor stari \"partiale\", se evita backtracking-ul pe fiecare linie.\r\n\r\n\r\nO problema care trebuie luata in considerare in cadrul algoritmului este aceea de a asocia fiecarei stari un numar de la $1$ la numarul total de stari (sau incepand de la $0$), precum si, dat fiind numarul unei stari, sa gasim repede starea ce corespunde acelui numar. Pentru a doua problema, putem tine un vector al tuturor starilor si pur si simplu sa accesam $stare[i]$, unde $i$ este indicele starii care ne intereseaza. Prima problema este ceva mai complicata si pentru rezolvarea ei exista cel putin urmatoarele variante:\r\n\r\n* memoram starile intr-un vector si le tinem sortate lexicografic, astfel ca putem sa cautam binar o stare $S$ in acest vector\r\n* putem folosi o functie de hash, care sa calculeze pentru fiecare stare o valoare unica (de exemplu. privind-o ca un numar in baza $X$, unde $X$ este numarul total de valori distincte ce ar putea aparea in cadrul unei stari); apoi, mentinem o tabela hash sau un arbore echilibrat (de exemplu, $set$ sau $map$ in STL), care sa asocieze fiecarei valori hash a unei stari, indicele acesteia (un numar intre $1$ si numarul total de stari, sau intre $0$ si numarul total de stari minus $1$).\r\n\r\nh3. Probleme asemanatoare\r\n\r\n* \'Kcity / Autumn Warmup 2007\':problema/kcity\r\n* \'Pipes / ACM ICPC NWERC 2004\':http://acm.pku.edu.cn/JudgeOnline/problem?id=2064\r\n\r\nh2(#h). \'H\':problema/h\r\n\r\nh3. Solutie $O(N*log^2^(N))$\r\n\r\nPentru fiecare segment vertical $(X{~1~},Yj{~1~},Ys{~1~})$, vom dori sa determinam un segment vertical din stanga sa $(X{~2~},Yj{~2~},Ys{~2~})$, impreuna cu care formeaza o litera $H$ de lungime maxima, in fiecare din urmatoarele $4$ cazuri (ce depind de pozitia celui de-al doilea segment fata de primul):\r\n\r\n* $Yj{~1~} &le; Ys{~2~} &le; Ys{~1~}$ si $Yj{~2~} &le; Yj{~1~}$ : in acest caz, litera $H$ va avea YjosH = Yj{~1~} si YsusH = Ys{~2~}\r\n* $Yj{~2~} &le; Yj{~1~} &le; Ys{~1~} &le; Ys{~2~}$ : in acest caz, litera $H$ va avea YjosH = Yj{~1~} si YsusH = Ys{~1~}\r\n* $Yj{~1~} &le; Yj{~2~} &le; Ys{~2~} &le; Ys{~1~}$ : in acest caz, litera H va avea YjosH = Yj{~2~} si YsusH = Ys{~2~}\r\n* $Yj{~1~} &le; Yj{~2~} &le; Ys{~1~}$ si $Ys{~1~} &le; Ys{~2~}$ : in acest caz, litera H va avea YjosH = Yj{~2~} si YsusH = Ys{~1~}\r\n\r\nConstatam ca, o data ce am fixat unul din cele $4$ cazuri, este foarte clara contributia fiecaruia din cele $2$ segmente la lungimea literei $H$:\r\n\r\n* cazul $1$: contributia segmentului $1$ este $L{~1~} = X{~1~} - 2 * Yj{~1~}$, iar cea a segmentului $2$ este $W = -X{~2~} + 2 * Ys{~2~}$\r\n* cazul $2$: contributia segmentului $1$ este $L{~1~} = X{~1~} + 2 * (Ys{~1~} - Yj{~1~})$, iar cea a segmentului $2$ este $W = -X{~2~}$\r\n* cazul $3$: contributia segmentului $1$ este $L{~1~} = X{~1~}$, iar cea a segmentului $2$ este $W = -X{~2~} + 2*(Ys{~2~}-Yj{~2~})$\r\n* cazul $4$: contributia segmentului $1$ este $L{~1~} = X{~1~} + 2 * Ys{~1~}$, iar cea a segmentului $2$ este $W = -X{~2~} - 2 * Yj{~2~}$\r\n\r\nIn aceste conditii, pentru fiecare caz, putem privi fiecare segment ca un punct intr-un alt sistem de coordonate 2D, in care coordonata $X$ corespunde lui $Yj$, iar coordonata $Y$ corespunde lui $Ys$. In plus, fiecare punct are asociata o pondere $W$. Pentru fiecare caz construim cu toate cele $N$ puncte un arbore de intervale 2D, care utilizeaza $O(N*logN)$ memorie. Acest arbore de intervale este, de fapt, un arbore de intervale obisnuit pentru coordonatele $X$, insa fiecare nod al arborelui mentine un vector cu coordonatele $Y$ ale punctelor ce corespund intervalului nodului respectiv. In plus, pentru fiecare coordonata $Y$ se mentine si ponderea asociata punctului.\r\n\r\nPentru fiecare caz $C$ si fiecare segment vertical, vom dori sa gasim segmenetul vertical din stanga sa cu care poate forma o litera $H$ de lungime maxima. Acest segment corespunde unui punct ce se afla intr-un dreptunghi ce corespunde constrangerilor pentru coordonatele $Yj$ si $Ys$ corespunzatoare cazului $C$ si care are ponderea $W$ maxima. Pentru fiecare caz, interogarile pot fi astfel puse incat dreptunghiul $[a,b]x[c,d]$ in care cautam punctul sa aiba ori coordonata $c$ egala cu $- infinit$, ori coordonata $d$ egala cu $+ infinit$. In aceste conditii, pentru fiecare nod din arborele de intervale in care se ajunge prin \"spargerea\" segmentului $[a,b]$, va trebui sa determinam ponderea maxima a unui punct care are coordonata $Y$ printre primele $z$ sau printre ultimele $z$ (unde $z$ este determinat folosind cautare binara in fiecare nod al arborelui de intervale al coordonatelor $X$ in care ajungem). Din acest motiv, putem sa mentinem pentru fiecare nod un vector $wmax[z]$ cu ponderea maxima a unui punct dintre primele $z$ puncte ce corespund intervalului nodului, precum si un vector similar ce corespunde ultimelor $z$ puncte ale intervalului; daca unul dintre capetele $c$ sau $d$ nu era egal cu $+/- infinit$, atunci trebuia sa folosim RMQ (Range Minimum Query) pentru fiecare nod din arbore.\r\n\r\nObservam ca, in modul in care am pus interogarile, nu am specificat nicaieri ca punctul cu pondere maxima sa corespunda unui segment aflat in stanga segmentului pentru care facem interogarea. Totusi, daca punctul cu pondere maxima obtinut nu corespunde unui segment aflat in stanga segmentului curent, atunci vom obtine in mod sigur o litera H de lungime mai mare in momentul in care vom efectua interogarea pentru segmentul corespunzator punctului obtinut (acest lucru se datoreaza modului in care sunt definite ponderile).\r\n\r\nMai trebuie sa avem grija ca, atunci cand realizam interogarea, punctul de pondere maxima sa nu corespunda chiar segmentului pentru care facem interogarea (ceea ce se poate intampla, intrucat nu am impus nici o conditie pentru a evita aceasta situatie). Pentru a evita acest lucru, o posibilitate este sa folosim niste limite ale dreptunghiului de interogare care sa excluda punctele ce corespund unor segmente ce au exact acelasi $Yjos$ si acelasi $Ysus$ ca si segmentul curent. In felul acesta, insa, ajungem sa nu luam in considerare $H$-uri formate din $2$ segmente care au acelasy $Yjos$ si acelasi $Ysus$ (dar coordonate $X$ diferite). Acest caz trebuie tratat separat, printr-o simpla sortare si parcurgere a segmentelor (segmentele avand acelasi $Yjos$ si $Ysus$ aflandu-se unul dupa altul in ordinea sortata).\r\n\r\nComplexitatea acestei solutii este $O(N*log^2^N)$ si foloseste memorie $O(N*logN)$.\r\n\r\nh3. Solutie $O(N*logN)$\r\n\r\nSolutia prezentata poate fi optimizata la complexitate $O(N*logN)$, folosind o tehnica standard. Orice query de acest tip corespunzator unui arbore de intervale 2D poate fi redus de la o complexitate $O(log^2^N)$ la o complexitate $O(log N)$. Practic, se va efectua o cautare binara a coordonatei $Y$ inferioare si superioare numai in cadrul radacinii arborelui de intervale. Apoi, din constructia arborelui, vom memora pentru fiecare punct $P$ al fiecarui nod, $4$ pointeri:\r\n\r\n* un pointer catre punctul cu cea mai mica coordonata $Y$ mai mare sau egala cu cea a punctului $P$ si care se afla in intervalul de coordonate $X$ al fiului stanga\r\n* un pointer catre punctul cu cea mai mica coordonata $Y$ mai mare sau egala cu cea a punctului $P$ si care se afla in intervalul de coordonate $X$ al fiului dreapta\r\n* un pointer catre punctul cu cea mai mare coordonata $Y$ mai mica sau egala cu cea a punctului $P$ si care se afla in intervalul de coordonate $X$ al fiului stanga\r\n* un pointer catre punctul cu cea mai mare coordonata $Y$ mai mica sau egala cu cea a punctului $P$ si care se afla in intervalul de coordonate $X$ al fiului dreapta\r\n\r\nO parte din acesti pointeri pot fi calculati in momentul in care, in faza de constructie a arborelui de intervale 2D, se interclaseaza coordonatele $Y$ corespunzatoare fiului stanga si fiului dreapta. Cealalta parte a pointer-ilor se calculeaza realizand inca $2$ parcurgeri ale coordonatelor $Y$ sortate, una de la stanga la dreapta si alta de la dreapta la stanga (in conditiile in care am memorat pentru fiecare coordonata $Y$ de la care din cei doi fii provine).\r\n\r\nUnul dintre concurenti a obtinut $100$ de puncte folosind o structura de date 2D numita \'kd-tree\':http://en.wikipedia.org/wiki/Kd-tree, care poate oferi aceleasi operatii ca si un arbore de intervale 2D. Diferenta consta in cantitatea de memorie folosita ({$O(N)$}, in loc de $O(N*logN)$), dar si in complexitatea cautarii in interiorul unui dreptunghi ({$O(sqrt(N))$}, in loc de $O(log^2^N)$ sau $O(logN)$ cu optimizarea mentionata).\r\n\r\nh3. Link-uri utile\r\n\r\n* \'Cautari Ortogonale / infoarena\':cautari-ortogonale , articol scris de Cosmin Negruseri\r\n* \'Arbori de intervale / infoarena\':arbori-de-intervale , articol scris de d-na. prof. Dana Lica\r\n* \'Range Minimum Query and Lowest Common Ancestor / TopCoder\':http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=lowestCommonAncestor , articol scris de catre Daniel Pasaila\r\n* \'Orthogonal Range Queries / MIT\':http://people.csail.mit.edu/indyk/6.838-old/handouts/lec5.pdf\r\n\r\nh3. Probleme asemanatoare\r\n\r\n* \'Zoo / .campion 2003\':problema/zoo\r\n* \'Kth Number / ACM ICPC NEERC Northern Subregion 2004\':http://acm.tju.edu.cn/toj/showp2722.html\r\n\r\nh2(#permavg). \'Permavg\':problema/permavg\r\n\r\nObservam ca, pentru ca media aritmetica a doua numere sa fie un numar intreg, ambele numere trebuie sa aiba aceeasi paritate. Acesta observatie ne-ar putea conduce la ideea de a separa, in cadrul permutarii, numerele pare de numerele impare. Sa presupunem ca vrem sa amplasam la inceputul permutarii toate numerele pare, apoi toate numerele impare. Sa consideram cazul numerelor pare, cazul numerelor impare tratandu-se similar. Avem $N/2$ numere pare: $2, 4, 6, ...$ pe care trebuie sa le ordonam in asa fel incat media aritmetica a oricare doua numere sa nu se afle intre ele. Vom renumerota numerele pare ca fiind $1, 2, .., N/2$ si vom observa ca acum problema s-a redus la a gasi o permutare de $N/2$ elemente pentru care media a oricare $2$ numere sa nu se afle intre ele (exact problema initiala, dar pentru $N$ injumatatit). Vom aplica in mod recursiv acest algoritm, pana ajungem la permutari cu $1$ sau $2$ elemente.\r\n\r\nDaca aplicam algoritmul direct, obtinem o solutie de tipul \'Divide et Impera\':http://en.wikipedia.org/wiki/Divide_and_conquer_algorithm , ce are complexitatea $O(N*logN)$. O imbuntataire a acestei solutii (care nu este necesara pentru a obtine punctajul maxim la problema) consta in observatia ca, de fapt, va trebui sa rezolvam cel mult $2*logN$ probleme distincte. Sa consideram urmatorul caz (cea mai proasta situatie):\r\n\r\n* $N=2*k+1$: La primul nivel de recursivitate trebuie sa rezolvam problema pentru valorile k si k+1. Avem urmatoarele $2$ subcazuri:\r\n** $k=2*p$ si $k+1=2*p+1$: Pentru $k$, va trebui sa rezolvam la nivelul urmator de recursivitate problema pentru valoarea $p$, iar pentru $k+1$ va trebui sa rezolvam problema pentru valorile $p si p+1$ ; asadar, la urmatorul nivel de recursivitate va trebui sa rezolvam problema doar pentru valorile distincte $p$ si $p+1$.\r\n** $k=2*p-1$ si $k+1=2*p$: Pentru $k$, va trebui sa rezolvam la nivelul urmator de recursivitate problema pentru valorile $p-1$ si $p$, iar pentru $k+1$ va trebui sa rezolvam problema pentru valoarea $p$ ; asadar, la urmatorul nivel de recursivitate va trebui sa rezolvam problema doar pentru valorile distincte $p-1$ si $p$.\r\n\r\nIn concluzie, la fiecare nivel al recursivitatii, avem de rezolvat, de fapt, doar $2$ probleme distincte. Prin urmare, daca memoizam rezultatele pentru fiecare valoare pentru care generam cate o permutare in cadrul algoritmului descris anterior, vom ajunge la o complexitate $O(N)$, in loc de $O(N*logN)$. Aceasta complexitate se obtine din urmatoarea relatie: $N + 2 * (N/2 + N/4 + N/8 + ...) = 3*N$.\r\n\r\nh2(#kboard). \'Kboard\':problema/kboard\r\n\r\nAvem urmatoarele cazuri:\r\n\r\n* $K=1$: Daca $N$ este impar, atunci primul jucator castiga; in caz contrar, al doilea jucator castiga.\r\n* $K &gt; 1$: Pentru $K &gt; 1$, va trebui sa folosim teoria numerelor Grundy (vezi \'link1\':http://www.ginfo.ro/revista/14_5/mate.pdf , \'link2\':http://en.wikipedia.org/wiki/Sprague-Grundy_theory , \'link3\':http://yucs.org/~gnivasch/cgames/spraguegrundy/index.html ). Vom calcula pentru fiecare $i$ de la $1$ la $3000$ o valoarea $grundy[i]$, reprezentand numarul Grundy corespunzator unei table formate din $i$ patratele. Pentru $0 &le; i &le; K-1$, $grundy[i]=0$. Pentru $i &ge; K$, vom genera toate starile in care putem ajunge dupa prima mutare efectuata: $S{~j~}$ $(0 &le; j &le; i-K)$ - plasam piesa pe patratelele $j+1,..,j+K$, impartind tabla in $2$ bucati, una de dimensiune $j$, alta de dimensiune $i-j-K$; calculam apoi numarul Grundy asociat acestei stari \"compuse\", ca fiind $grundy_compus[S{~j~}] = grundy[j] *xor* grundy[i-j-K]$. Vom calcula apoi primul numar natural (mai mare sau egal cu $0$) care nu apare in multimea numerelor $grundy_compus[S{~j~}]$. Aceasta valoare corespunde numarului $grundy[i]$ (pe care doream sa-l calculam). Pentru o dimensiune $i$ a tablei, jucatorul $1$ are strategie sigura de castig daca $grundy[i] &gt; 0$; in caz contrar, va avea strategie sigura de castig jucatorul $2$. Este evident ca, pentru o valoare $M$, putem calcula numerele Grundy pentru dimensiuni ale tablei de la $1$ la $M$ in complexitate $O(M^2^)$. Dupa ce calculam aceste valori, va trebui sa observam niste reguli pentru a putea rezolva problema pentru limitele date:\r\n** $K &gt; 2$ si $max{3000, 69*K-19} = 3000$: Pentru acest caz nu trebuie sa facem nimic special. Pur si simplu calculam numerele Grundy conform algoritmului descris mai sus si, pentru fiecare test, raspundem in complexitate $O(1)$.\r\n** $K &gt; 2$ si $max{3000, 69*K-19} = 69*K-19$: Dimensiunile tablei de la $1$ la $K-1$ sunt pierzatoare pentru primul jucator, iar dimensiunea $K$ este castigatoare. Vom observa ca, dupa dimensiunea $K-1$, exista $12$ stari pierzatoare pentru primul jucator, de forma $a*K+b$, care sunt aceleasi indiferent de $K$ (in sensul ca sunt aceleasi constante $a$ si $b$). Cel mai simplu mod de a observa acest lucru este de a afisa diferenta dintre dimensiunea $X$ a tablei corespunzatoare unei stari pierzatoare si dimensiunea $Y$ a tablei anterioare ce corespunde unei stari pierzatoare. Cele $12$ diferente sunt, in ordine: $2*K$, $2*K$, $4*K-2$, $4*K-2$, $4*K$, $4*K-2$, $8*K-2$, $4*K-2$, $8*K$, $8*K-2$, $16*K-6$, $4*K$ . Aceasta regula este valida pentru $K &ge; 4$ (dar noi o vom folosi doar pentru $K &ge; 44$, deoarece pentru $K &lt; 44$, ne vom afla in cazul anterior).\r\n** $K=2$: In acest caz ne vom uita, din nou, la diferentele dintre doua stari pierzatoare (pentru primul jucator) consecutive. Vom observa ca sirul acestor diferente (considerand prima stare pierzatoare \"interesanta\" ca fiind $K-1$) consta dintr-un prefix de lungime $8$ $(4,4,6,6,4,4,6,4)$, dupa care sirul devine periodic, cu perioada $5$ $(4,12,4,4,10)$.\r\n\r\nh3. Probleme asemanatoare\r\n\r\n* \'Obj / Happy Coding 2006\':problema/obj\r\n* \'Pawns / Bursele Agora 2004\':problema/pawns\r\n* \'Game / Bursele Agora 2004\':problema/game\r\n* \'Pietre / infoarena\':problema/pietre\r\n* \'Otilia / .campion 2005\':problema/otilia\r\n* \'Playing with Matches / SGU\':http://acm.sgu.ru/problem.php?contest=0&problem=153\r\n* \'A Stone Game / TIMUS\':http://acm.timus.ru/problem.aspx?space=1&num=1180\r\n* \'The Game of Squares / TIMUS\':http://acm.timus.ru/problem.aspx?space=1&num=1529\r\n\r\n',11154,'public',NULL,NULL),('blog/membrii-noi','Membri noi','2007-11-20 08:46:27','2008-11-15 13:41:14','Cum v-am mai zis si in alte posturi, suntem bucurosi ca am adaugat doi oameni noi in \'echipa\':echipa-infoarena. Ei sunt \'Adrian Airinei\':utilizator/astronomy si \'Andrei Grigorean\':utilizator/wefgef . Ambii au avut rezultate foarte bune la concursuri de programare ca elevi si au un numar impresionant de probleme rezolvate din arhiva infoarena. Recent i-am luat la intrebari. Vedeti aici ce a iesit:\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/membrii-noi?airinei_adrian.jpg! *Cum ai ajuns membru al siteului infoarena?*\r\n*Adrian:* Cand m-am calificat prima oara la ONI, in clasa a 10a, nu stiam nimic despre site-uri de pregatire pe net. Cei din lotul judetului Iasi vorbeau atunci despre infoarena cum ca ar fi un site foarte util cu probleme si concursuri. Cand am ajuns acasa, am cautat pe google infoarena, mi-am facut un cont si am rezolvat a+b si cmmdc.\r\n\r\n\r\n*Cum ai folosit acest site?*\r\n*Adrian:* In continuare, am gasit site-ul ca fiindu-mi de mare folos, in primul rand am rezolvat multe probleme. Forumul a fost iarasi foarte important, gaseam constant sfaturi utile acolo iar articolele m-au ajutat si ele.\r\n\r\n\r\n*De ce ai intrat in echipa infoarena? Ce iti propui sa faci ca membru al echipei?*\r\n*Adrian:* In calitate de membru al echipei imi propun sa incerc sa ajut cum pot comunitatea infoarena.\r\n\r\n!{margin: 10px; margin-right: 0; border: 1px solid gray;}>blog/membrii-noi?hipiotu.JPG! *Cum ai ajuns membru al echipei infoarena?*\r\n*Andrei:* Dupa IOI, m-a intrebat Mircea intr-o noapte pe mess daca nu vreau sa ma implic mai mult in infoarena. I-am spus ca mi-ar placea, si m-a facut admin imediat.\r\n\r\n*Cum ai folosit acest site?*\r\n*Andrei:* De pe infoarena m-am pregatit cel mai mult pentru olimpiade, am rezolvat majoritatea problemelor din prima jumatate a arhivei. Am invatat cateva si de pe forum, citind posturile celor mai mari. Sectiunea de downloads mi-a fost de asemenea utila (am luat concursurile internationale de acolo). Si articolele m-au ajutat. La inceput cand nu ma prea prindeam de probleme, citeam solutiile oficiale de la diverse concursuri, iar apoi implementam. Desi ideal este sa te chinui pana cand iti vine ideea, la inceput e mult mai greu si uneori trebuie sa citesti solutiile. Tot pe infoarena am auzit de tine :)).\r\n\r\n*De ce ai intrat in echipa infoarena? Ce iti propui sa faci ca membru al echipei?*\r\n*Andrei:* Am intrat pe infoarena pentru a-i ajuta pe cei mai mici sa se pregateasca mai bine. Sper sa propun cateva probleme interesante la concursuri. De asemenea, cred ca pot spune si punctul de vedere al unuia care in urma cu doar cateva luni concura si se pregatea pe site. Atunci cand participi si nu organizezi, vezi lucrurile altfel.\r\n\r\nh2. _Spor la munca baieti, suntem mandrii sa va avem printre noi!_\r\n\r\n',1490,'protected',2382,NULL),('utilizator/roxyshor','Profil roxyshor','2007-11-20 20:01:41','2007-11-20 20:01:41','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',7146,'public',NULL,NULL),('blog/preoni-2008','Incepe preONI 2008','2007-11-23 12:47:30','2007-11-23 12:49:00','Incepe o noua editie preONI, concursul cu premii mari si finala live care te pregateste pentru \'Olimpiada Nationala de Informatica\':http://olimpiada.info.\r\nAnul acesta avem vesti bune pentru elevii de gimnaziu si profesorii lor: \'preONI 2008\':preoni-2008 are o grupa separata pentru clasele V-VIII, si locuri rezervate la runda finala.  In plus, avem premii mai multe si mai mari!  ;)\r\nRunda #1 se desfasoara *Duminica, 25 noiembrie 2007, orele 09:00 - 13:00*, afla mai multe pe \'pagina concursului\':preoni-2008/runda-1.\r\n',1,'protected',NULL,NULL),('preoni-2008/premii','preONI 2008 - Sponsori si premii','2007-11-08 02:00:02','2007-11-23 13:01:47','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. Sponsori si premii\r\n\r\nh2. Premii\r\n\r\nPentru fiecare dintre cele patru grupe, primii elevi din clasament in urma desfasurarilor probelor online vor fi premiati cu o diploma de finalist al concursului *preONI 2008* si o \'runda finala\':preoni-2008/runda-finala de pregatire cu cazare si masa asigurate.\r\nAcesti elevi vor avea sansa sa interactioneze cu membrii \'echipei infoarena\':echipa-infoarena si cu ceilalti membrii ai comunitatii infoarena si sa invete de la si impreuna cu acestia. Runda finala va fi de asenemea un prilej de a ii rasplati pe cei mai buni dintre cei mai buni. Punctajele din acesta runda vor fi independente de cele acumulate la rundele online, iar primii 3 clasati la fiecare grupa vor avea parte de urmatoarele premii:\r\n\r\n* Locul I: 500 lei\r\n* Locul II: 300 lei\r\n* Locul III: 200 lei\r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',1,'protected',NULL,NULL),('runda/1230','1230','2009-09-23 20:21:24','2009-09-23 20:21:24','h1. == roundparam(round_id=\"1230\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"1230\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"1230\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"1230\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/1230/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"1230\" score=\"1\")==',10703,'round: 1230',NULL,NULL),('runda/1230/clasament','Clasament 1230','2009-09-23 20:21:24','2009-09-23 20:21:24','h1. Clasament ==roundparam(round_id=\"1230\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"1230\")==',10703,'round: 1230',NULL,NULL),('runda/geometrie','Probleme de Geometrie','2009-09-24 08:50:38','2009-09-24 12:03:28','h1. == roundparam(round_id=\"geometrie\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"geometrie\") ==\r\n\r\nh2. Probleme\r\n\r\n==Tasks(round_id=\"geometrie\" score=\"1\")==',5070,'round: geometrie',NULL,NULL),('runda/geometrie/clasament','Clasament geometrie','2009-09-24 08:50:38','2009-09-24 08:50:38','h1. Clasament ==roundparam(round_id=\"geometrie\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"geometrie\")==',5070,'round: geometrie',NULL,NULL),('nr','Lucrul cu numere mari','2009-09-24 14:52:15','2009-09-24 14:52:15','h1. Lucrul cu numere mari\r\n\r\nDe multe ori, in probleme, apar situatii cand este nevoie sa memoram numere intregi foarte mari (de ordinul sutelor de cifre), iar uneori trebuie sa efectuam si operatii aritmetice cu aceste numere.\r\n\r\nNumerele reprezentate pe vectori le vom numi pur si simplu \"vectori\", iar numerele reprezentate printr-un tip ordinal de date le vom numi, printr-o analogie usor fortata cu matematica, \"scalari\". Sa vedem acum cum se efectueaza operatiile elementare pe aceste numere.\r\n\r\nh2. Initializarea\r\n\r\nUn vector poate fi initializat in trei feluri: cu $0$, cu un scalar sau cu un alt vector.\r\n\r\nLa initializarea cu $0$, singurul lucru pe care il avem de facut este sa setam numarul de cifre pe $0$. De aceea, este practic inutil sa implementam aceasta functie ca atare; putem folosi in loc singura instructiune pe care ea o contine.\r\n\r\n== code(c)|\r\nvoid Atrib0(Huge H) {\r\n  H[0] = 0;\r\n}\r\n==\r\n\r\nLa initializarea cu un scalar nenul, trebuie sa asezam fiecare cifra pe pozitia corespunzatoare, afland in paralel si numarul de cifre. Se incepe cu cifra unitatilor, si la fiecare pas se pune in vector cifra cea mai putin semnificativa, dupa care numarul de reprezentat se imparte la $10$ (neglijandu-se restul), iar numarul de cifre se incrementeaza.\r\n\r\n== code(c)|\r\nvoid AtribValue(Huge H, unsigned long X) {\r\n  H[0] = 0;\r\n  while (X) {\r\n      ++H[0];\r\n      H[H[0]] = X % BASE;\r\n      X /= BASE;\r\n  }\r\n}\r\n==\r\n\r\nIata, de exemplu, cum se pune pe vector numarul $195$:\r\n!lucrul-cu-nr-mari?img1.jpg!\r\n\r\n\r\nIn sfarsit, initializarea unui vector cu altul se face printr-o simpla copiere (se pot folosi cu succes rutine de lucru cu memoria, cum ar fi $FillChar$ in Pascal sau $memmove$ in C). Pentru eleganta, poate fi folosita si atribuirea cifra cu cifra:\r\n\r\n== code(c)|\r\nvoid AtribHuge(Huge H, Huge X) {\r\n  int i;\r\n  for (i = 0; i <= X[0]; ++i) {\r\n    H[i] = X[i];\r\n  }\r\n}\r\n==\r\n\r\nh2. Compararea\r\n\r\nPentru a compara doua numere \"uriase\", incepem prin a afla numarul de cifre semnificative (deoarece, in urma anumitor operatii pot rezulta zerouri nesemnificative care \"atarna\" totusi la numarul de cifre). Aceasta se face decrementand numarul de cifre al fiecarui numar atata timp cat cifra cea mai semnificativa este $0$. Dupa ce ne-am asigurat asupra acestui punct, comparam numarul de cifre al celor doua cifre. Numarul cu mai multe cifre este cel mai mare. Daca ambele numere au acelasi numar de cifre, pornim de la cifra cea mai semnificativa si comparam cifrele celor doua numere pana la prima diferenta intalnita. In acest moment, numarul a carui cifra este mai mare este el insusi mai mare. \r\nDaca toate cifrele numerelor sunt egale doua cate doua, atunci in mod evident numerele sunt egale.\r\n\r\nDupa cum se vede, algoritmul seamana foarte bine cu ceea ce s-a invatat la matematica prin clasa a II-a (doar ca atunci nu ni s-a spus ca este vorba de un \"algoritm\"). Rutina de mai jos compara doua numere uriase $H1$ si $H2$ si intoarce $-1$, $0$ sau $1$, dupa $H1$ este mai mic, egal sau mai mare decat $H2$.\r\n\r\n== code(c)|\r\nint Sgn(Huge H1, Huge H2) {\r\n  // Elimina zero-urile semnificative, daca exista.\r\n  while (H1[0] && !H1[H1[0]]) H1[0]--;\r\n  while (H2[0] && !H2[H2[0]]) H2[0]--;\r\n\r\n  if (H1[0] < H2[0]) {\r\n    return -1;\r\n  } else if (H1[0] > H2[0]) {\r\n    return +1;\r\n  }\r\n\r\n  for (int i = H1[0]; i > 0; --i) {\r\n    if (H1[i] < H2[i]) {\r\n      return -1;\r\n    } else if (H1[i] > H2[i]) {\r\n      return +1;\r\n    }\r\n  }\r\n  return 0;\r\n}\r\n==\r\n\r\nh2. Adunarea a doi vectori\r\n\r\nFiind dati doi vectori, $A$ cu $M$ cifre si $B$ cu $N$ cifre, adunarea lor se face in mod obisnuit, ca la aritmetica. Pentru a evita testele de depasire, se recomanda sa se completeze mai intai vectorul cu mai putine cifre cu zerouri pana la dimensiunea vectorului mai mare. La sfarsit, vectorul suma va avea dimensiunea vectorului mai mare dintre $A$ si $B$, sau cu $1$ mai mult daca apare transport de la cifra cea mai semnificativa. Procedura de mai jos adauga numarul $B$ la numarul $A$.\r\n\r\n== code(c)|\r\nvoid Add(Huge A, Huge B)\r\n/* A <- A+B */\r\n{ int i,T=0;\r\n\r\n  if (B[0]>A[0])\r\n    { for (i=A[0]+1;i<=B[0];) A[i++]=0;\r\n      A[0]=B[0];\r\n    }\r\n    else for (i=B[0]+1;i<=A[0];) B[i++]=0;\r\n  for (i=1;i<=A[0];i++)\r\n    { A[i]+=B[i]+T;\r\n      T=A[i]/10;\r\n      A[i]%=10;\r\n    }\r\n  if (T) A[++A[0]]=T;\r\n}\r\n==\r\n\r\nh2. Scaderea a doi vectori\r\n\r\nSe dau doi vectori $A$ si $B$ si se cere sa se calculeze diferenta $A$ - $B$. Se presupune $B$ &le; $A$ (acest lucru se poate testa cu functia Sgn). Pentru aceasta, se porneste de la cifra unitatilor si se memoreaza la fiecare pas \"imprumutul\" care trebuie efectuat de la cifra de ordin imediat superior (imprumutul poate fi doar $0$ sau $1$). Deoarece $B$ &le; $A$, avem garantia ca pentru a scadea cifra cea mai semnificativa a lui $B$ din cifra cea mai semnificativa a lui $A$ nu e nevoie de imprumut.\r\n\r\n== code(c)|\r\nvoid Subtract(Huge A, Huge B)\r\n/* A <- A-B */\r\n{ int i, T=0;\r\n\r\n  for (i=B[0]+1;i<=A[0];) B[i++]=0;\r\n  for (i=1;i<=A[0];i++)\r\n    A[i]+= (T=(A[i]-=B[i]+T)<0) ? 10 : 0;\r\n    /* Adica A[i]=A[i]-(B[i]+T);\r\n       if (A[i]<0) T=1; else T=0;\r\n       if (T) A[i]+=10; */\r\n  while (!A[A[0]]) A[0]--;\r\n}\r\n==\r\n\r\n\r\nh2. Inmultirea si impartirea cu puteri ale lui 10\r\n\r\nAceste functii sunt uneori utile. Ele pot folosi si functiile de inmultire a unui vector cu un scalar, care vor fi prezentate mai jos, dar se pot face si prin deplasarea intregului numar spre stanga sau spre dreapta. De exemplu, inmultirea unui numar cu $100$ presupune deplasarea lui cu doua pozitii inspre cifra cea mai semnificativa si adaugarea a doua zerouri la coada. Principalul avantaj al scrierii unor functii separate pentru inmultirea cu $10$, $100$, ..., este ca se pot folosi rutinele de acces direct al memoriei ({$FillChar$}, respectiv $memmove$). Iata functiile care realizeaza deplasarea vectorilor, atat prin mutarea blocurilor de memorie, cat si prin atribuiri succesive.\r\n\r\n== code(c)|\r\nvoid Shl(Huge H, int Count)\r\n/* H <- H*10ACount */\r\n{ \r\n  /* Shifteaza vectorul cu Count pozitii */\r\n  memmove(&H[Count+1],&H[1],sizeof(int)*H[0]);\r\n  /* Umple primele Count pozitii cu 0 */\r\n  memset(&H[1],0,sizeof(int)*Count);\r\n  /* Incrementeaza numarul de cifre */\r\n  H[0]+=Count;\r\n}\r\n\r\nvoid Shl2(Huge H, int Count)\r\n/* H <- H*10ACount */\r\n{ int i;\r\n\r\n  /* Shifteaza vectorul cu Count pozitii */\r\n  for (i=H[0];i;i--) H[i+Count]=H[i];\r\n  /* Umple primele Count pozitii cu 0 */\r\n  for (i=1;i<=Count;) H[i++]=0;\r\n  /* Incrementeaza numarul de cifre */\r\n  H[0]+=Count;\r\n}\r\n\r\nvoid Shr(Huge H, int Count)\r\n/* H <- H/10ACount */\r\n{ \r\n  /* Shifteaza vectorul cu Count pozitii */\r\n  memmove(&H[1],&H[Count+1],sizeof(int)*(H[0]-Count));\r\n  /* Decrementeaza numarul de cifre */\r\n  H[0]-=Count;\r\n}\r\n\r\nvoid Shr2(Huge H, int Count)\r\n/* H <- H/10ACount */\r\n{ int i;\r\n\r\n  /* Shifteaza vectorul cu Count pozitii */\r\n  for (i=Count+1;i<=H[0];i++) H[i-Count]=H[i];\r\n  /* Decrementeaza numarul de cifre */\r\n  H[0]-=Count;\r\n}\r\n==\r\n\r\nh2. Inmultirea unui vector cu un scalar\r\n\r\nSi aceasta operatie este o simpla implementare a modului manual de efectuare a calculului. La inmultirea \"de mana\" a unui numar mare cu unul de o singura cifra, noi parcurgem deinmultitul de la sfarsit la inceput, si pentru fiecare cifra efectuam urmatoarele operatii:\r\n\r\n* Inmultim cifra respectiva cu inmultitorul;\r\n* Adaugam \"transportul\" de la inmultirea precedenta;\r\n* Separam ultima cifra a rezultatului si o trecem la produs;\r\n* Celelalte cifre are rezultatului constituie transportul pentru urmatoarea inmultire;\r\n* La sfarsitul inmultirii, daca exista transport, acesta are o singura cifra, care se scrie inaintea rezultatului.\r\n\r\nExact acelasi procedeu se poate aplica si daca inmultitorul are mai mult de o cifra. Singura deosebire este ca transportul poate avea mai multe cifre (poate fi mai mare ca $9$). Din aceasta cauza, la sfarsitul inmultirii, poate ramane un transport de mai multe cifre, care se vor scrie inaintea rezultatului. Iata de exemplu cum se calculeaza produsul $312$ x $87$:\r\n\r\n!lucrul-cu-nr-mari?imnult1.jpg!\r\n\r\nProcedura este descrisa mai jos:\r\n\r\n== code(c)|\r\nvoid Mult(Huge H, unsigned long X)\r\n/* H <- H*X */\r\n{ int i;\r\n  unsigned long T=0;\r\n\r\n  for (i=1;i<=H[0];i++)\r\n    { H[i]=H[i]*X+T;\r\n      T=H[i]/10;\r\n      H[i]=H[i]%10;\r\n    }\r\n  while (T) /* Cat timp exista transport */\r\n    { H[++H[0]]=T%10;\r\n      T/=10;\r\n    }\r\n}\r\n==\r\n\r\nh2. Inmultirea a doi vectori\r\n\r\nDaca ambele numere au dimensiuni mari si se reprezinta pe tipul de date Huge, produsul lor se calculeaza inmultind fiecare cifra a deinmultitului cu fiecare cifra a inmultitorului si trecand rezultatul la ordinul de marime (exponentul lui $10$) cuvenit. De fapt, acelasi lucru il facem si noi pe hartie. Considerand acelasi exemplu, in care ambele numere sunt \"uriase\", produsul lor se calculeaza de mana astfel\r\n\r\n!lucrul-cu-nr-mari?inmult2.jpg!\r\n\r\nS-a luat deci fiecare cifra a inmultitorului si s-a efectuat produsul partial corespunzator, corectand la fiecare pas rezultatul prin calculul transportului. Rezultatul pentru fiecare produs partial s-a scris din ce in ce mai in stanga, pentru a se alinia corect ordinele de marime. Acest procedeu este oarecum incomod de implementat. Se pot face insa unele observatii care usureaza mult scrierea codului:\r\n\r\n* Prin inmultirea cifrei cu ordinul de marime $10i$ din primul numar cu cifra cu ordinul de marime $10j$ din al doilea numar se obtine o cifra corespunzatoare ordinului de marime $10i$+{$j$} in rezultat (sau se obtine un numar cu mai mult de o singura cifra, caz in care transportul merge la cifra corespunzatoare ordinului de marime $10i$ + $j$ + $1$).\r\n* Daca numerele au $M$ si respectiv $N$ cifre, atunci produsul lor va avea fie $M$ + $N$ fie    $M$ + $N$ - $1$ cifre. Intr-adevar, daca numarul $A$ are $M$ cifre, atunci $10^M-1^$ &le; $A$ < $10^M^$ si {$10^N-1^$} &le; $B$ < $10^N^$, de unde rezulta $10^M+N-2^$ &le; $A$ x $B$ < $10^M+N^$.\r\n* La calculul produselor partiale se poate omite calculul transportului, acesta urmand a se face la sfarsit. Cu alte cuvinte, intr-o prima faza putem pur si simplu sa inmultim cifra cu cifra si sa adunam toate produsele de aceeasi putere, obtinand un numar cu \"cifre\" mai mari ca $9$, pe care il aducem la forma normala printr-o singura parcurgere. Sa reluam acelasi exemplu:\r\n\r\n!lucrul-cu-nr-mari?inmult3.jpg!\r\n\r\nAceasta operatie efectueaza {$M$}x{$N$} produse de cifre si {$M$}{@+@}{$N$} (sau {$M$}{@+@}{$N$}-{$1$}, dupa caz) \"transporturi\" pentru aflarea rezultatului, deci are complexitatea O({$M$}x{$N$}). Iata si implementarea:\r\n\r\n== code(c)|\r\nvoid MultHuge(Huge A, Huge B, Huge C)\r\n/* C <- A x B */\r\n{ int i,j,T=0;\r\n\r\n  C[0]=A[0]+B[0]-1;\r\n  for (i=1;i<=A[0]+B[0];) C[i++]=0;\r\n  for (i=1;i<=A[0];i++)\r\n    for (j=1;j<=B[0];j++)\r\n      C[i+j-1]+=A[i]*B[j];\r\n  for (i=1;i<=C[0];i++)\r\n    { T=(C[i]+=T)/10;\r\n      C[i]%=10;\r\n    }\r\n  if (T) C[++C[0]]=T;\r\n}\r\n==\r\n\r\nMai exista o alta modalitate de a inmulti doua numere de cate $N$ cifre fiecare, care are complexitatea <tex>O(N^{log_2 3}) \\approx O(N^{1.58}) \\approx O(N \\sqrt{N})</tex>. Ea deriva de un algoritm propus de Strassen in 1969 pentru inmultirea matricelor. Diferenta se face simtita, ce-i drept pentru valori mari ale lui $N$, dar constanta multiplicativa creste destul de mult si, in plus, solutia e mai greu de implementat; de aceea nu recomandam implementarea ei in timpul concursului. Ideea de baza este sa se micsoreze numarul de inmultiri si sa se mareasca numarul de adunari, deoarece adunarea a doi vectori se face in O({$N$}), pe cand inmultirea se face in O({$N$} $2$). Sa consideram intregii $A$ si $B$, fiecare de cate $N$ cifre. Trebuie sa-i inmultim intr-un timp T({$N$}) mai bun decat O({$N$} $2$). Sa impartim numarul $A$ in doua \"bucati\" $C$ si $D$, fiecare de cate $N$/{$2$} cifre, iar intregul $B$ in doua bucati $E$ si $F$, tot de cate $N$/{$2$} cifre (presupunem ca $N$ este par):\r\n\r\n!lucrul-cu-nr-mari?img3.jpg!\r\n\r\n\r\nAtunci se poate scrie relatia:\r\n**$A$ x $B$ = ({$C$} x $10^N/2^$ + $D$) x ({$E$} x $10^N/2^$ + $F$) = $CE$ x $10^N^$ ({$CF$} + $DE$) x $10^N/2^$ + $DF$**\r\n\r\nPentru a putea calcula produsul $A$ x $B$ avem, prin urmare, nevoie de patru produse partiale, de trei adunari si de doua inmultiri cu puteri ale lui $10$. Adunarile si inmultirile cu puteri ale lui $10$ se fac in timp liniar. Daca efectuam cele patru produse partiale prin patru inmultiri, rezulta formula recurenta de calcul **T({$N$})=4T({$N$}/{$2$})+O({$N$})** care duce prin eliminarea recurentei la <tex>T(N)\\in O(N)^2</tex>. Cu alte cuvinte, inca n-am castigat nimic. Trebuie sa reusim cumva sa reducem numarul de inmultiri de la $4$ la $3$, chiar daca prin aceasta vom mari numarul de adunari necesare. Sa definim produsul **$G$ = ({$C$} + $D$) x ({$E$} + $F$) = $CE$ + $CF$ + $DE$ + $DF$ = $CE$ + $DF$ + ({$CF$} + $DE$)**\r\nAtunci putem scrie: **$A$ x $B$ = $CE$ x $10$^{$N$}^ + ({$G$} - $CE$ - $DF$) x $10$^{$N$}/{$2$}^ + $DF$**\r\nPentru aceasta varianta, folosim doar trei inmultiri, si chiar daca avem nevoie de sase adunari si scaderi si doua inmultiri cu puteri ale lui $10$, complexitatea se va reduce la <tex> O(N^{log_2 3}) </tex>. In cazul in care $N$ este o putere a lui $2$, impartirea in doua a numerelor se poate face fara probleme la fiecare pas, pana se ajunge la numere de o singura cifra, care se inmultesc direct. In cazul in care $N$ nu este o putere a lui $2$, este comod sa se completeze numerele cu zerouri pana la o putere a lui $2$. In functiile descrise mai jos, $MultRec$ nu face decat inmultirea recursiva, pe cand $MultVect2$ se ocupa si de corectarea numarului de cifre (incrementarea pana la o putere a lui $2$). Pentru calculul produselor $C$ x $E$ si $D$ x $F$, procedura $MultRec$ se autoapeleaza; pentru calcularea produsului ({$C$}{@+@}{$D$}) x ({$E$}{@+@}{$F$}), insa, este nevoie sa fie apelata procedura $MultVect2$, deoarece prin cele doua adunari poate sa apara o crestere a numarului de cifre al factorilor, care in acest caz trebuie readusi la un numar de cifre egal cu o putere a lui $2$.\r\n \r\n== code(c)|\r\nvoid MultHuge2(Huge A, Huge B, Huge P);\r\nvoid MultRec(Huge A, Huge B, Huge P)\r\n{ Huge C,D,E,F,CE,DF;\r\n  if (A[0]==1)\r\n    { P[1]=A[1]*B[1];\r\n      P[0]=(P[2]=P[1]/10)>0 ? 2 : 1;\r\n      P[1]%=10;\r\n    }\r\n    else { P[0]=0;\r\n           AtribHuge(C,A);Shr(C,A[0]/2);\r\n           AtribHuge(D,A);D[0]=A[0]/2;\r\n           AtribHuge(E,B);Shr(E,B[0]/2);\r\n           AtribHuge(F,B);F[0]=B[0]/2;\r\n           MultRec(C,E,CE);MultRec(D,F,DF);\r\n           Add(C,D);Add(E,F);\r\n           MultHuge2(C,E,P);\r\n           Subtract(P,CE);Subtract(P,DF);\r\n           Shl(P,A[0]/2);\r\n           Shl(CE,A[0]);Add(P,CE);\r\n           Add(P,DF);\r\n         }\r\n}\r\nvoid MultHuge2(Huge A, Huge B, Huge P)\r\n/* P <- A x B, varianta NA(lg 3) */\r\n{ int i,j,NDig=A[0]>B[0] ? A[0] : B[0],Needed=1,SaveA,SaveB;\r\n  /* Corecteaza numarul de cifre */\r\n  while (Needed<NDig) Needed<<=1;\r\n  SaveA=A[0];SaveB=B[0];A[0]=B[0]=Needed;\r\n  for (i=SaveA+1;i<=Needed;) A[i++]=0;\r\n  for (i=SaveB+1;i<=Needed;) B[i++]=0;\r\n  MultRec(A,B,P);\r\n  /* Restaureaza numarul de cifre */\r\n  A[0]=SaveA;B[0]=SaveB;\r\n  while (!P[P[0]] && P[0]>1) P[0]--;\r\n}\r\n==\r\n\r\nh2.  Impartirea unui vector la un scalar\r\n\r\nNe propunem sa scriem o functie care sa imparta numarul $A$ de tip Huge la scalarul $B$, sa retina valoarea catului tot in numarul $A$ si sa intoarca restul (care este o variabila scalara). Sa pornim de la un exemplu particular si sa generalizam apoi procedeul: sa calculam catul si restul impartirii lui $1997$ la $7$. Cu alte cuvinte, sa gasim acele numere $C$ de tip Huge si <tex>R\\in\\{0, 1, 2, 3, 4, 5, 6\\}</tex> cu proprietatea ca $1997$ = $7$ x $C$ + $R$.\r\n\r\n!lucrul-cu-nr-mari?impart1.jpg!\r\n\r\nLa fiecare pas se coboara cate o cifra de la deimpartit alaturi de numarul deja existent (care initial este $0$), apoi rezultatul se imparte la impartitor ({$7$} in cazul nostru). Catul este intotdeauna o cifra si se va depune la sfarsitul catului impartirii, iar restul va fi folosit pentru urmatoarea impartire. Restul care ramane dupa ultima impartire este tocmai $R$ pe care il cautam. Procedeul functioneaza si atunci cand deimpartitul are mai multe cifre. La sfarsit trebuie sa decrementam corespunzator numarul de cifre al catului, prin neglijarea zerourilor create la inceputul numarului. Numarul maxim de cifre al catului este egal cu cel al deimpartitului.\r\n\r\n== code(c)|\r\nunsigned long Divide(Huge A, unsigned long X)\r\n/* A <- A/X si intoarce A%X */\r\n{ int i;\r\n  unsigned long R=0;\r\n\r\n  for (i=A[0];i;i--)\r\n    { A[i]=(R=10*R+A[i])/X;\r\n      R%=X;\r\n    }\r\n  while (!A[A[0]] && A[0]>1) A[0]--;\r\n  return R;\r\n}\r\n==\r\n\r\nDaca dorim numai sa aflam restul impartirii, nu mai avem nevoie decat sa recalculam restul la fiecare pas, fara a mai modifica vectorul A:\r\n\r\n== code(c)|\r\nunsigned long Mod(Huge A, unsigned long X)\r\n/* Intoarce A%X */\r\n{ int i;\r\n  unsigned long R=0;\r\n\r\n  for (i=A[0];i;i--)\r\n    R=(10*R+A[i])%X;\r\n  return R;\r\n}\r\n==\r\n\r\nh2. Impartirea a doi vectori\r\n\r\nDaca se dau doi vectori $A$ si $B$ si se cere sa se afle catul $C$ si restul $R$, etapele de parcurs sunt aceleasi ca la punctul precedent, numai ca operatorii \"/\" si \"%\" trebuie implementati de utilizator, ei nefiind definiti pentru vectori. Cu alte cuvinte, dupa ce \"coboram\" la fiecare pas urmatoarea cifra de la deimpartit, trebuie sa aflam cea mai mare cifra $X$ astfel incat impartitorul sa se cuprinda de $X$ ori in restul de la momentul respectiv. Acest lucru se face cel mai comod prin adunari repetate: pornim cu cifra $X$={$0$} si o incrementam, micsorand concomitent restul, pana cand restul care ramane este prea mic. Sa efectuam aceeasi impartire, $1997$:{$7$}, considerand ca ambele numere sunt reprezentate pe tipul Huge.\r\n\r\n!lucrul-cu-nr-mari?impart2.jpg!\r\n\r\nCazul cel mai defavorabil (cand $X$={$9$}) presupune $9$ scaderi si $10$ comparatii, cazul cel mai favorabil (cand $X$={$0$}) presupune numai o comparatie, deci cazul mediu presupune $4$ scaderi si $5$ comparatii. Cautarea lui $X$ se poate face si binar, prin injumatatirea intervalului, ceea ce reduce timpul mediu de cautare la aproximativ $3$ comparatii si $3$ inmultiri, dar codul se complica nejustificat de mult (de cele mai multe ori).\r\n\r\n== code(c)|\r\nvoid DivideHuge(Huge A, Huge B, Huge C, Huge R)\r\n/* A/B = C rest R */\r\n{ int i;\r\n\r\n  R[0]=0;C[0]=A[0];\r\n  for (i=A[0];i;i--)\r\n    { Shl(R,1);R[1]=A[i];\r\n      C[i]=0;\r\n      while (Sgn(B,R)!=1)\r\n        { C[i]++;\r\n          Subtract(R,B);\r\n        }\r\n    }\r\n  while (!C[C[0]] && C[0]>1) C[0]--;\r\n}\r\n==\r\n\r\nh2. Extragerea radacinii cubice\r\n\r\nVom sari peste prezentarea algoritmului de extragere a radacinii patrate, pe care il vom lasa ca tema cititorului, si ne vom indrepta atentia asupra celui de extragere a radacinii cubice, care este putin mai complicat, dar care poate fi usor extins pentru radacini de orice ordin. Problema este exact cea din enunt, asa ca vom porni de la exemplul dat. Sa notam <tex>A = 2.097.152</tex> si <tex> X = \\sqrt[3]{A}</tex>. Cum se afla **$X$** ?\r\n\r\nO prima varianta ar fi cautarea binara a radacinii, prin injumatatirea intervalului. Initial se porneste cu intervalul ({$1$},{$A$}), deoarece radacina cubica se afla undeva intre $1$ si $A$ (evident, incadrarea este mai mult decat acoperitoare; ea ar putea fi mai limitativa, dar nu ar reduce timpul de lucru decat cu cateva iteratii). La fiecare pas, intervalul va fi injumatatit. Cum, probabil ca stiti deja; se ia jumatatea intervalului, se ridica la puterea a treia si se compara cu $A$. Daca este mai mare, inseamna ca radacina trebuie cautata in jumatatea inferioara a intervalului. Daca este mai mica, vom continua cautarea in jumatatea superioara a intervalului. Daca cele doua numere sunt egale, inseamna ca am gasit tocmai ce ne interesa. Prima varianta a pseudocodului este:\r\n\r\n== code(c)|\r\nciteste A cu N cifre\r\n  Lo <- 1, Hi <- A, X <- 0\r\n  cat timp X=0\r\n    Mid <- (Lo+Hi)/2\r\n    daca Mid^3<A\r\n      atunci Lo <- Mid+1\r\n      altfel daca Mid^3>A\r\n               atunci Hi <- Mid-1\r\n               altfel X <- Mid\r\n==\r\n\r\n\r\nIn cazul cel mai rau, algoritmul de mai sus efectueaza $log ~2~ A$ injumatatiri de interval, fiecare din ele presupunand o adunare, o impartire la $2$ si o ridicare la cub. Dintre aceste operatii, cea mai costisitoare este ridicarea la cub, O( $N$^{$2$}^ ). Complexitatea totala este prin urmare O( $N$^{$2$}^ $log ~2~ A$ ). Deoarece $A$ are ordinul de marime $10$^{$N$}^, rezulta complexitatea O( $N$^{$3$}^ $log 10$ )= O( $N$^{$3$}^ ), adica mai proasta decat cea ceruta (de altfel, un algoritm cu aceasta complexitate nici nu s-ar incadra in timp pentru $N$={$1000$}). Daca timpul ne permite, trebuie sa cautam alta metoda.\r\n\r\nIn exemplul ales, sa observam ca $106$&le;{$A$}<{$109$}, de unde deducem ca $102$&le;{$X$}<{$103$}. Cu alte cuvinte, $X$ are $3$ cifre. In cazul general, daca $A$ are $N$ cifre, atunci $X$ are [$N$/{$3$}] cifre (prin [$N$/{$3$}] se intelege \"cel mai mic intreg mai mare sau egal cu $N$/{$3$}\"). Care ar putea fi prima cifra a lui $X$? Daca $X$ incepe cu cifra $2$, atunci $200$&le;{$X$}<{$300$} => $8.000.000$&le;{$2.097.152$}<{$27.000.000$}, ceea ce este fals. Cu atat mai putin poate prima cifra a lui $X$ sa fie mai mare ca $2$. Rezulta ca prima cifra a lui $X$ este $1$. De altfel, pentru a afla acest lucru, putem sa si neglijam ultimele $6$ cifre ale lui $A$. Ne intereseaza doar prima cifra, cea a milioanelor, iar prima cifra a lui $X$ o alegem in asa fel incat cubul ei sa fie mai mic sau egal cu $2$.\r\n\r\nCe putem spune despre a doua cifra? Daca ar fi $3$, atunci $130$&le;{$X$}<{$140$} => $2.197.000$&le;{$2.097.152$}<{$2.744.000$}, fals (deci cifra este cel mult $2$). Daca ar fi $1$, atunci $110$&le;{$X$}<{$120$} => $1.331.000$&le;{$2.097.152$}<{$1.728.000$}, fals. Rezulta ca a doua cifra este obligatoriu $2$. Analog, putem neglija ultimele trei cifre ale lui $A$, iar a doua cifra a lui $X$ este cel mai mare $C$ pentru care <tex> \\overline{1C}^3 \\leq 2097</tex>. Pentru a afla ultima cifra, aplicam acelasi rationament: Daca ar fi $9$, atunci $X$={$129$} si ar rezulta $2146688$={$X$}^{$3$}^={$2097152$}, absurd. Daca consideram ca cifra este $8$, atunci calculul se verifica. Am aflat asadar ca $X$={$128$}.\r\n\r\nProcedeul general este urmatorul: dandu-se un numar $A$ cu $N$ cifre, il completam cu zerouri nesemnificative pana cand $N$ se divide cu $3$ (poate fi necesar sa adaugam maxim doua zerouri). Numarul de cifre semnificative ale radacinii cubice este $M$={$N$}/{$3$}. Aflam pe rand fiecare cifra, incepand cu cea mai semnificativa. Sa presupunem ca am aflat cifrele $X$ ~$M$~, $X$ ~$M-1$~,..., $X$ ~$K+1$~. Cifra $X$~$K$~ este cea mai mare cifra pentru care numarul <tex> \\overline{(X_MX_{M-1}...X_{K+1}X_K00...00)}^3\\leq A</tex>. Cifra $X$~$K$~ este unica, deoarece exista, in general, mai multe cifre care verifica proprietatea ceruta, dar una singura este \"cea mai mare\". O a doua versiune a pseudocodului este deci:\r\n\r\n== code(c)|\r\nciteste A cu N cifre\r\n  X <- 0; T <- 0\r\n  cat timp N%3<>0 adauga un 0 nesemnificativ\r\n  repeta de N/3 ori\r\n    adauga la T urmatoarele 3 cifre din A\r\n    adauga la X cea mai mare cifra astfel incat X^3<= T\r\n==\r\n\r\n\r\nSa evaluam complexitatea acestei versiuni. Linia $1$ se executa in timp liniar, O({$N$}). Liniile $2$ si $3$ se executa in timp constant. Linia $5$ se executa in O({$N$}), iar linia $6$ presupune adaugarea unei cifre (O({$N$})) si o ridicare la cub, adica doua inmultiri (O({$N$}^{$2$}^)). Deoarece liniile $5$ si $6$ se executa de $N$/{$3$} ori (linia $4$), rezulta o complexitate de O({$N$}^{$3$}^). Iata ca nici acest algoritm nu a adus imbunatatiri si pare si ceva mai greu de implementat. El poate fi totusi modificat pentru a-i scadea complexitatea la O({$N$}^{$2$}^).\r\n\r\nPrincipalul neajuns al sau este efectuarea ridicarii la cub, care se face in O({$N$}^{$2$}^). Daca am putea sa-l aflam la fiecare pas pe $X$^{$3$}^ fara a efectua inmultiri, adica in timp liniar, atunci intregul algoritm ar avea complexitate patratica. Bineinteles, prima intrebare care vine pe buzele cititorului este \"cum sa ridicam la cub fara sa facem inmultiri?\". Sa nu uitam insa ceva: ca noi nu-l cunoastem numai pe $X$. Il cunoastem si pe $X$ de la pasul anterior, care avea o cifra mai putin (il vom boteza $OldX$). Sa presupunem ca, printr-o metoda oarecare, am reusit sa-l ridicam pe $OldX$ la puterile a doua si a treia (si am obtinut numerele $OldX2$ si $OldX3$). Cum putem, cunoscand aceste trei numere, precum si noua cifra ce se va adauga la sfarsitul lui $X$ (sa-i spunem $C$ ), sa-l aflam pe $X$, patratul si cubul sau? Nu e prea greu:\r\n\r\n<tex> X = 10 \\cdot OldX + C </tex> \r\n<tex> X^2 = (10 \\cdot OldX + C)^2 = 100 \\cdot OldX^2 + 20 \\cdot OldX \\cdot C + C^2 = 100 \\cdot OldX2 + (20 \\cdot C) \\cdot OldX + C^2</tex>\r\n\r\nIata asadar ca pentru a afla noile valori ale puterilor $1$, $2$ si $3$ ale lui $X$, folosindu-le pe cele vechi, nu avem nevoie decat de adunari si de inmultiri cu numere mici (de ordinul miilor). Toate aceste operatii se fac in timp liniar, deci am reusit sa gasim un algoritm patratic. Iata mai jos sursa C:\r\n\r\n== code(c)|\r\nvoid FindDigit(Huge L,Huge NewL2,Huge NewL3,\r\n     Huge OldL,Huge OldL2,Huge OldL3,Huge Target)\r\n{ Huge Aux;\r\n  L[1]=10;\r\n  do\r\n    { L[1]--;\r\n      /* Trebuie calculat LA3. Se stiu OldL (L/10)\r\n         si noua cifra L[1]. Deci (OldL*10+L[1])A3=?\r\n         Se aplica binomul lui Newton. */\r\n      AtribHuge(NewL3,OldL3);Shl(NewL3,3);\r\n      AtribHuge(Aux,OldL2);Mult(Aux,300*L[1]);\r\n      Add(NewL3,Aux);\r\n      AtribHuge(Aux,OldL);Mult(Aux,30*L[1]*L[1]);\r\n      Add(NewL3,Aux);\r\n      AtribValue(Aux,L[1]*L[1]*L[1]);\r\n      Add(NewL3,Aux);\r\n    }\r\n  while (Sgn(NewL3,Target)==1);\r\n  /* Aceeasi operatie pentru LA2 */\r\n  AtribHuge(NewL2,OldL2);Shl(NewL2,2);\r\n  AtribHuge(Aux,OldL);Mult(Aux,20*L[1]);\r\n  Add(NewL2,Aux);\r\n  AtribValue(Aux,L[1]*L[1]);\r\n  Add(NewL2,Aux);\r\n  /* Noile valori devin \'vechi\' */\r\n  AtribHuge(OldL2,NewL2);\r\n  AtribHuge(OldL,L);\r\n  AtribHuge(OldL3,NewL3);\r\n}\r\nvoid CubeRoot(Huge A, Huge X)\r\n{ Huge Target,OldX,OldX2,OldX3,NewX2,NewX3;\r\n  int i;\r\n  /* Se initializeaza vectorii cu 0 (nici o cifra) */\r\n  OldX[0]=OldX2[0]=OldX3[0]=X[0]=0;\r\n  for (i=1;i<=(A[0]+2)/3;i++)\r\n    { AtribHuge(Target,A);\r\n      Shr(Target,3*((A[0]+2)/3-i));\r\n      Shl(X,1);\r\n      FindDigit(X,NewX2,NewX3,OldX,OldX2,OldX3,Target);\r\n    }\r\n}\r\n==\r\n\r\n\r\nAcum nu mai avem decat sa scriem rutinele de intrare/iesire si programul principal:\r\n\r\n== code(c)|\r\n#include <stdio.h>\r\n#include <mem.h>\r\n#define NMax 1000\r\ntypedef int Huge[NMax+3];\r\nHuge A,X; /* A[0] si X[0] indica numarul de cifre */\r\n\r\nvoid ReadData(void)\r\n{ FILE *F=fopen(\"input.txt\",\"rt\");\r\n  int C,i;\r\n\r\n  A[0]=0;\r\n  do A[++A[0]]=(C=fgetc(F))-\'0\';\r\n  while (C!=EOF);\r\n  A[0]--;\r\n  fclose(F);\r\n  /* Intoarce vectorul pe dos */\r\n  for (i=1;i<=A[0]/2;i++)\r\n    A[i]=(A[i]AA[A[0]+1-i])A(A[A[0]+1-i]=A[i]);\r\n}\r\nvoid WriteSolution(void)\r\n{ FILE *F=fopen(\"output.txt\",\"wt\");\r\n  int i=X[0];\r\n  while (!X[i]) i--;\r\n  while (i) fputc(X[i--]+\'0\',F);\r\n  fclose(F);\r\n}\r\nvoid main(void)\r\n{\r\n  ReadData();\r\n  CubeRoot(A,X);\r\n  WriteSolution();\r\n}\r\n==\r\n\r\nPentru a extinde aceasta metoda la radacini de orice ordin $K$, trebuie numai sa tinem cont de expresia binomului lui Newton:\r\n\r\n<tex> X^p = (10 \\cdot OldX + C)^p = \\sum_{\\substack {0\\leq i \\leq p}} {10^i \\cdot Oldx^i \\cdot C^{p-i}} </tex>\r\n\r\nPresupunand ca avem calculate toate puterile de la $1$ la $p$ ale lui $OldX$, se poate calcula noua valoare a lui $X$^{$p$}^ folosind numai adunari si inmultiri cu scalari. In felul acesta se pot calcula in timp liniar valorile lui $X$, $X$^{$2$}^, $X$^{$3$}^, ...., $X$^{$K$}^.\r\n\r\nh2. Problema\r\n\r\n|_. Timp de implementare|_. Timp de rulare|_. Complexitate|\r\n|1h 30\'|10 secunde|**O(N^2^)**|\r\n\r\nSe da un numar natural cu $N$&le;{$1000$} cifre. Se cere sa se extraga radacina cubica a numarului. Se garanteaza ca numarul citit este cub perfect.\r\nFisierul $INPUT.TXT$ contine un singur rand, terminat cu $EOF$, pe care se afla numarul, cifrele fiind nedespartite.\r\nIn fisierul $OUTPUT.TXT$ se va tipari radacina cubica a numarului, pe o singura linie terminata cu $EOF$.\r\n\r\n|_. INPUT.TXT|_. OUTPUT.TXT|\r\n|2097152|128|\r\n\r\nh2. Rezolvare\r\n\r\nProblema este cat se poate de simpla din punct de vedere matematic; dificultatea apare la implementare, atat datorita structurilor de date necesare, cat mai ales datorita complexitatii cerute. Despre lucrul cu numere intregi (chiar si $Longint$) nici nu poate fi vorba, iar la lucrul cu numere reale apar erori de calcul.\r\n\r\nStructura de date propusa pentru abordarea acestui gen de probleme este urmatoarea: numerele vor fi reprezentate printr-un vector de cifre zecimale. Prima pozitie (pozitia $0$) din vector este rezervata pentru a memora numarul de cifre. Definitia C a tipului de date este:\r\n\r\n== code(c)|\r\ntypedef int Huge[1001];\r\n==\r\n\r\nIata cum s-ar memora numarul \"1997\" intr-un asemenea vector:\r\n\r\n!lucrul-cu-nr-mari?pb1.jpg!\r\n\r\nSe observa ca vectorul este oarecum \"intors pe dos\". Totusi, aceasta forma este cea mai convenabila, pentru ca ea permite implementarea cu o mai mare usurinta a operatiilor aritmetice.\r\n\r\nMai trebuie remarcat ca pe fiecare pozitie $K$ in vector se afla cifra care il reprezinta pe $10$^{$K-1$}^ in numarul reprezentat: in V[1] se afla cifra unitatilor ({$10$}^{$0$}^), in V[2] se afla cifra zecilor ({$10$}^{$1$}^), in V[3] se afla cifra sutelor ({$10$}^{$2$}^) s.a.m.d. Formatul zecimal nu este cea mai fericita (a se citi \"eficienta\") alegere. El ocupa doar patru biti din cei opt ai unui octet, deci face risipa de memorie. Daca am alege baza de numeratie $256$, am folosi la maximum memoria, si in plus operatiile ar fi cu mult mai rapide (deoarece $256$ este o putere a lui $2$, inmultirile si impartirile la $256$ sunt simple deplasari la stanga si la dreapta ale reprezentarilor binare). Sa facem urmatorul calcul ca sa vedem cate cifre are in baza $256$ un numar care are $1000$ de cifre in baza $10$:\r\n\r\n<tex>10^{1000} = 10 \\cdot (10^3)^{333} \\approx 10 \\cdot (2^10)^{333} \\approx 10 \\cdot (2^8)^{335} = 10 \\cdot 256^{335}  </tex>\r\n\r\nAsadar, numarul de cifre s-a redus cam de trei ori. Un algoritm liniar ar functiona de trei ori mai repede pe reprezentari in baza $256$, iar unul patratic ar functiona de noua ori mai repede. Inconvenientul major este dificultatea depanarii unui program care opereaza intr-o baza aritmetica atat de straina noua. Vom ramane deci la baza $10$, cu mentiunea ca acei mai temerari dintre voi pot incerca folosirea bazei $256$.\r\n \r\n\r\n\r\n',10701,'public',NULL,NULL),('happy-coding-2007/blogentry','Post-Happy Coding','2007-11-24 16:11:22','2007-11-24 16:35:41','h1. Post-Happy Coding\r\n\r\nA mai trecut un concurs \'Happy Coding\':happy-coding-2007 si s-ar putea spune ca incepe sa devina un concurs infoarena traditional. Daca in primul an (2005) toate problemele au fost luate de la concursurile de selectie a echipelor ACM ICPC din Universitatea Politehnica Bucuresti, incet-incet Happy Coding a ajuns sa aiba parte de portia sa proprie de probleme originale si interesante ;) Editia de anul acesta a reprezentat cel mai lung concurs infoarena si a avut cel mai mare numar de probleme (25). Ca si in anii anteriori, evaluatorul a fost pornit pe toata durata concursului, dar, pentru a \"contrabalansa\" aceasta facilitate, am stabilit ca la fiecare problema sa se poata obtine doar 0 sau 100 de puncte. In felul acesta, Happy Coding a devenit mai asemanator cu concursurile de tip \'ACM ICPC\':http://icpc.baylor.edu/icpc/ decat cu olimpiadele scolare - mie personal imi plac mai mult concursurile de tip ACM ICPC, datorita clasamentului \"live\" si a dinamismului mai ridicat. Apropo de clasament \"live\", a existat un \"curent de opinie\" la IOI anul acesta, conform caruia ar trebui sa existe un fel de clasament semi-live si la IOI (sa vedem ce se va intampla in viitor :) ).\r\n\r\nProblemele au avut nivele de dificultate variate, rezolvarile lor necesitand observatii, idei si smenuri simple si/sau cunoscute, precum si idei noi, complicate si dificil de gasit. Imi era clar ca, desi durata concursului era de peste 8 zile si jumatate, ar fi fost foarte greu pentru cineva sa rezolve toate problemele. De aceea consider remarcabil rezultatul lui ==user(user=\"bogdan2412\" type=\"tiny\")==, care a reusit sa rezolve 24 din cele 25 de probleme (oare cat timp va dura pana va rezolva cineva si problema \'Optic\':problema/optic , chiar si cu solutia publicata ? :) ) si a luat concursul in serios de la bun inceput, situandu-se pe unul din primele 2 locuri inca din prima zi de concurs.\r\n\r\nIn ceea ce priveste rezultatele celorlalti concurenti, eu le-as incadra in 7 (\'numar magic\':http://www.musanim.com/miller1956/) categorii, in functie de numarul de probleme rezolvate:\r\n\r\n* cat.1: 23-25 probleme rezolvate => rezultat excelent\r\n* cat.2: 21-22 probleme rezolvate => rezultat foarte bun\r\n* cat.3: 16-20 probleme rezolvate => rezultat bun\r\n* cat.4: 11-15: probleme rezolvate => rezultat ok\r\n* cat.5: 7-10 probleme rezolvate => rezultat satisfacator\r\n* cat.6: 3-6 probleme rezolvate => mai are mult de lucrat si multe de invatat (dar are potential ;) )\r\n* cat.7: 0-2 probleme rezolvate => in trecere pe la concurs :)\r\n\r\nDesi speram ca cei mai multi concurenti (45%-50%) sa se claseze in categoriile 1-5, o scurta privire aruncata asupra \'clasamentului\':happy-coding-2007/clasament arata ca lucrurile nu au stat astfel, aproximativ 75% dintre participanti situandu-se in categoriile 6 si 7 :( . Din acest punct de vedere, sunt usor dezamagit si am incercat sa ma gandesc care ar fi motivul pentru care cea mai mare parte a participantilor a rezolvat foarte putine probleme. Mi-au trecut prin minte 3 motive posibile:\r\n\r\n* Au luat mult prea la propriu ideea de \"programare cu zambetul pe buze\" si au tratat concursul cu o foarte mare lejeritate. Presupun ca aceasta reprezinta o posibilitate, insa atunci sunt curios ce anume i-a facut sa zambeasca in timp ce programau. Pe mine ma face sa zambesc un program bine scris care obtine 100 de puncte :)\r\n* Au rezolvat mai multe probleme, insa nu in proportie de 100%, iar sistemul de punctare \"0 sau 100\" nu i-a avantajat in aceasta privinta. Este posibil ca lipsa de experienta in ceea ce priveste concursurile de informatica sa nu permita unui participant sa isi gaseasca bug-urile din surse sau sa inteleaga motivele pentru care algoritmul sau nu functioneaza nici chiar intr-un interval de peste 8 zile si jumatate.\r\n* Nivelul de dificultate al problemelor a fost prea ridicat (ceea ce este evident pentru o parte dintre probleme) si nu au reusit sa gaseasca o solutie corecta sau care sa respecte constrangerile de timp si de memorie impuse.\r\n\r\nDintre cele 3 motive mentionate, primul se poate \"rezolva\" tratand concursurile mai serios, iar al doilea se poate \"rezolva\" programand mai mult si capatand experienta. A treia cauza posibila este cea care ma ingrijoreaza cel mai mult si este si cea mai dificil de \"tratat\" in mod individual (fara ajutorul cuiva). Pentru a ajunge sa poti rezolva probleme grele, in afara de a te stradui mai mult de unul singur, este important sa poti invata ceva si de la ceilalti. De aceea, am incercat sa scriu un articol cu solutiile problemelor cat mai detaliat, pentru a ajuta astfel pe toata lumea sa invete cateva (sau mai multe :) ) idei noi. \r\n\r\nIn perspectiva concursurilor viitoare, intrucat nu exista o reteta sigura pentru a ajunge in situatia de a iti veni (cine stie de unde :) ) ideile necesare pentru a rezolva o problema, pot doar sa va sugerez sa luati in considerare urmatoarele posibilitati:\r\n\r\n* ganditi-va singuri (fara a cere ajutor) la fiecare problema, pana cand gasiti solutia sau pana cand trece o anumita perioada de timp dupa care considerati ca nu puteti gasi solutia singuri (aici depinde de fiecare.. ar trebui sa fie cel putin 1-2 saptamani, dar mie mi s-a intamplat sa ma prind cum sa rezolv o problema si dupa 6 ani :) )\r\n* comunicati cu ceilalti membri ai comunitatii, schimband idei, discutand algoritmi si cerand sfaturi; si tineti minte sa ii ajutati si voi pe altii atunci cand veti avea posibilitatea\r\n* faceti pregatire cu un profesor care se pricepe; e foarte util pentru voi sa va ofere cineva informatii si cunostinte intr-un mod structurat (sa stiti ca asta nu e o reclama la adresa mea :) va spun doar ce mi se pare mie util si ce am facut si eu cand eram elev)\r\n* cititi cursuri de Computer Science, Graph Theory, Computational Geometry, Data Structures, String Algorithms, etc. si articole de cercetare de pe Internet; veti gasi multe concepte si idei foarte interesante, care s-ar putea sa va \"lumineze\" un pic mintea :)\r\n* participati la cat mai multe concursuri; chiar daca va prindeti cum sa rezolvati o problema, este important sa implementati corect si repede algoritmul de rezolvare\r\n\r\nDaca are cineva si alte sugestii (sau nu este de acord cu unele din cele mentionate), il invit sa comenteze pe forum.\r\n\r\nMult succes la concursurile urmatoare!\r\n',468,'public',NULL,NULL),('blog/post-happy-coding','Post-Happy-Coding','2007-11-24 17:18:50','2008-11-15 13:41:14','_Concursul Happy Coding s-a incheiat, si a fost unul de succes, facand ca traficul de pe site sa se dubleze. Mugurel si restul echipei de propunatori au facut treaba buna, propunand un numar impresionant de probleme, iar acum tot Mugurel ne prezinta o analiza la rece a concursului:_\r\n\r\nA mai trecut un concurs \'Happy Coding\':happy-coding-2007 si s-ar putea spune ca incepe sa devina un concurs infoarena traditional. Daca in primul an (2005) toate problemele au fost luate de la concursurile de selectie a echipelor ACM ICPC din Universitatea Politehnica Bucuresti, incet-incet Happy Coding a ajuns sa aiba parte de portia sa proprie de probleme originale si interesante ;) Editia de anul acesta a reprezentat cel mai lung concurs infoarena si a avut cel mai mare numar de probleme (25). Ca si in anii anteriori, evaluatorul a fost pornit pe toata durata concursului, dar, pentru a \"contrabalansa\" aceasta facilitate, am stabilit ca la fiecare problema sa se poata obtine doar 0 sau 100 de puncte. In felul acesta, Happy Coding a devenit mai asemanator cu concursurile de tip \'ACM ICPC\':http://icpc.baylor.edu/icpc/ decat cu olimpiadele scolare - mie personal imi plac mai mult concursurile de tip ACM ICPC, datorita clasamentului \"live\" si a dinamismului mai ridicat. Apropo de clasament \"live\", a existat un \"curent de opinie\" la IOI anul acesta, conform caruia ar trebui sa existe un fel de clasament semi-live si la IOI (sa vedem ce se va intampla in viitor :) ).\r\n\r\nProblemele au avut nivele de dificultate variate, rezolvarile lor necesitand observatii, idei si smenuri simple si/sau cunoscute, precum si idei noi, complicate si dificil de gasit. Imi era clar ca, desi durata concursului era de peste 8 zile si jumatate, ar fi fost foarte greu pentru cineva sa rezolve toate problemele. De aceea consider remarcabil rezultatul lui ==user(user=\"bogdan2412\" type=\"tiny\")==, care a reusit sa rezolve 24 din cele 25 de probleme (oare cat timp va dura pana va rezolva cineva si problema \'Optic\':problema/optic , chiar si cu solutia publicata ? :) ) si a luat concursul in serios de la bun inceput, situandu-se pe unul din primele 2 locuri inca din prima zi de concurs.\r\n\r\nIn ceea ce priveste rezultatele celorlalti concurenti, eu le-as incadra in 7 (\'numar magic\':http://www.musanim.com/miller1956/) categorii, in functie de numarul de probleme rezolvate:\r\n\r\n* cat.1: 23-25 probleme rezolvate => rezultat excelent\r\n* cat.2: 21-22 probleme rezolvate => rezultat foarte bun\r\n* cat.3: 16-20 probleme rezolvate => rezultat bun\r\n* cat.4: 11-15: probleme rezolvate => rezultat ok\r\n* cat.5: 7-10 probleme rezolvate => rezultat satisfacator\r\n* cat.6: 3-6 probleme rezolvate => mai are mult de lucrat si multe de invatat (dar are potential ;) )\r\n* cat.7: 0-2 probleme rezolvate => in trecere pe la concurs :)\r\n\r\nDesi speram ca cei mai multi concurenti (45%-50%) sa se claseze in categoriile 1-5, o scurta privire aruncata asupra \'clasamentului\':happy-coding-2007/clasament arata ca lucrurile nu au stat astfel, aproximativ 75% dintre participanti situandu-se in categoriile 6 si 7 :( . Din acest punct de vedere, sunt usor dezamagit si am incercat sa ma gandesc care ar fi motivul pentru care cea mai mare parte a participantilor a rezolvat foarte putine probleme. Mi-au trecut prin minte 3 motive posibile:\r\n\r\n* Au luat mult prea la propriu ideea de \"programare cu zambetul pe buze\" si au tratat concursul cu o foarte mare lejeritate. Presupun ca aceasta reprezinta o posibilitate, insa atunci sunt curios ce anume i-a facut sa zambeasca in timp ce programau. Pe mine ma face sa zambesc un program bine scris care obtine 100 de puncte :)\r\n* Au rezolvat mai multe probleme, insa nu in proportie de 100%, iar sistemul de punctare \"0 sau 100\" nu i-a avantajat in aceasta privinta. Este posibil ca lipsa de experienta in ceea ce priveste concursurile de informatica sa nu permita unui participant sa isi gaseasca bug-urile din surse sau sa inteleaga motivele pentru care algoritmul sau nu functioneaza nici chiar intr-un interval de peste 8 zile si jumatate.\r\n* Nivelul de dificultate al problemelor a fost prea ridicat (ceea ce este evident pentru o parte dintre probleme) si nu au reusit sa gaseasca o solutie corecta sau care sa respecte constrangerile de timp si de memorie impuse.\r\n\r\nDintre cele 3 motive mentionate, primul se poate \"rezolva\" tratand concursurile mai serios, iar al doilea se poate \"rezolva\" programand mai mult si capatand experienta. A treia cauza posibila este cea care ma ingrijoreaza cel mai mult si este si cea mai dificil de \"tratat\" in mod individual (fara ajutorul cuiva). Pentru a ajunge sa poti rezolva probleme grele, in afara de a te stradui mai mult de unul singur, este important sa poti invata ceva si de la ceilalti. De aceea, am incercat sa scriu un articol cu solutiile problemelor cat mai detaliat, pentru a ajuta astfel pe toata lumea sa invete cateva (sau mai multe :) ) idei noi. \r\n\r\nIn perspectiva concursurilor viitoare, intrucat nu exista o reteta sigura pentru a ajunge in situatia de a iti veni (cine stie de unde :) ) ideile necesare pentru a rezolva o problema, pot doar sa va sugerez sa luati in considerare urmatoarele posibilitati:\r\n\r\n* ganditi-va singuri (fara a cere ajutor) la fiecare problema, pana cand gasiti solutia sau pana cand trece o anumita perioada de timp dupa care considerati ca nu puteti gasi solutia singuri (aici depinde de fiecare.. ar trebui sa fie cel putin 1-2 saptamani, dar mie mi s-a intamplat sa ma prind cum sa rezolv o problema si dupa 6 ani :) )\r\n* comunicati cu ceilalti membri ai comunitatii, schimband idei, discutand algoritmi si cerand sfaturi; si tineti minte sa ii ajutati si voi pe altii atunci cand veti avea posibilitatea\r\n* faceti pregatire cu un profesor care se pricepe; e foarte util pentru voi sa va ofere cineva informatii si cunostinte intr-un mod structurat (sa stiti ca asta nu e o reclama la adresa mea :) va spun doar ce mi se pare mie util si ce am facut si eu cand eram elev)\r\n* cititi cursuri de Computer Science, Graph Theory, Computational Geometry, Data Structures, String Algorithms, etc. si articole de cercetare de pe Internet; veti gasi multe concepte si idei foarte interesante, care s-ar putea sa va \"lumineze\" un pic mintea :)\r\n* participati la cat mai multe concursuri; chiar daca va prindeti cum sa rezolvati o problema, este important sa implementati corect si repede algoritmul de rezolvare\r\n\r\nDaca are cineva si alte sugestii (sau nu este de acord cu unele din cele mentionate), il invit sa comenteze in sectiunea de comentarii.\r\n\r\nMult succes la concursurile urmatoare!\r\n\r\n',1490,'protected',2389,NULL),('happy-coding-2007','Happy Coding 2007','2007-11-03 11:15:18','2007-11-24 17:45:49','h1. Happy Coding 2007     !happy-coding-2007?hc2007-logo.gif!\r\n\r\n(htabs)*(active) \'Despre Happy Coding\':happy-coding-2007\r\n* \'Probleme\':happy-coding-2007/probleme\r\n* \'Clasament\':happy-coding-2007/clasament\r\n\r\nSunteti invitati sa participati la o noua editie a popularului (speram :) ) concurs Happy Coding. Perioada de desfasurare a concursului este *sambata, 10 noiembrie, ora 10:00 - duminica, 18 noiembrie, ora 24:00*.\r\n\r\nEvaluatorul va functiona pe toata perioada desfasurarii concursului. La toate problemele veti putea obtine numai *0* sau *100* de puncte (ori vor avea un singur test, ori toate testele vor fi grupate), in mod similar concursurilor de tip ACM ICPC.\r\n\r\nSucces!\r\n\r\n==roundregister(round_id=\"happy-2007\")==\r\n\r\nh2. Solutii\r\n\r\nPuteti citi aici \'articolul cu solutii\':happy-coding-2007/solutii pentru cele 25 de probleme.\r\n\r\nIar \'aici\':blog/post-happy-coding aveti analiza concursului.\r\n\r\nh2. Organizatori\r\n\r\nCa si in editiile anterioare, majoritatea problemelor sunt propuse de ==User(user=\"mugurelionut\" type=\"tiny\")== ajutat de aceasta data de Mihai Stroe si ==User(user=\"flmanea\" type=\"tiny\")==. O parte dintre probleme au fost folosite in anii anteriori la selectiile echipelor ACM ICPC din cadrul Universitatii Politehnica Bucuresti, dar nu va ingrijorati, pentru ca veti avea parte si de multe probleme noi si originale! ;)\r\n\r\nNumarul problemelor pe care le veti avea de rezolvat va fi *25*.\r\n\r\n* ==User(user=\"ditzonec\" type=\"tiny\")==\r\n* ==User(user=\"mugurelionut\" type=\"tiny\")==\r\n* ==User(user=\"flmanea\" type=\"tiny\")==\r\n',58,'protected',NULL,NULL),('preoni-2008/runda-1/solutii','Solutii preONI 2008, Runda 1','2007-11-25 11:22:12','2008-01-04 11:49:23','==include(page=\"template/preoni-2008/header\")==\r\n\r\nh1. Solutii preONI 2008, Runda 1\r\n\r\nIata ca a inceput o noua editie a concursului \"de marca\" infoarena, preONI 2008. Suntem incantati ca am reusit sa strangem atat de multi participanti la prima runda si speram ca numarul lor va creste pe parcursul rundelor urmatoare. Acest articol va prezenta atat solutiile problemelor propuse in concurs, cat si cateva remarci pe marginea desfasurarii probei.\r\n\r\nAnul acesta a fost prima editie cand gimnaziul si clasa a 9-a au fost despartie in doua grupe. Concurentii au fost pusi in fata unui set de probleme mai usor, iar punctajele obtinute au fost cele mai mari dintre toate grupele. \"Multimi2\":problema/multimi2 a fost problema usoara, prima submisie corecta avand loc la ora 9:38 si apartinandu-i lui \"Marius Petcu\":utilizator/marius21, iar in total 13 concurenti au obtinut 100 de puncte. Problema medie, \"Ecuatie\":problema/ecuatie a fost rezolvata de doar 2 concurenti, \"Cezar Mocan\":utilizator/cezarmocan si \"Vlad Gavrila\":utilizator/gavrilavlad. \"Ordine\":problema/ordine, problema grea, a fost rezolvata corect de un singur concurent, \"Andrei Purice\":utilizator/protoman. Acesta din urma si \"Cezar Mocan\":utilizator/cezarmocan, au castigat runda, fiecare cu cate 2 probleme rezolvate. De apreciat faptul ca Cezar a iesit primul si la clasa a 9-a, desi este inca in ultimul an de gimnaziu.\r\n\r\nLa clasa a 9-a punctajele concurentilor au fost destul de mici, \"Cezar Mocan\":utilizator/cezarmocan reusind sa se impuna cu 2 probleme rezolvate corect, \"Economie\":problema/economie si \"Ecuatie\":problema/ecuatie. Problema grea, \"Teren\":problema/teren nu a fost rezolvata corect de niciun concurent, cel mai mare punctaj apartinandu-i lui \"Victor Ionescu\":utilizator/vanila_cpp care a obtinut 80 de puncte si a iesit al doilea. In clasamentul de la clasa a 9-a figureaza foarte multi concurenti de la clasa a 10-a. Speram sa remediem aceasta problema pana la runda urmatoare a concursului.\r\n\r\nIn fruntea clasamentului clasei a 10-a il gasim, asa cum se astepta multa lume, pe \"Bogdan Tataroiu\":utilizator/bogdan2412, care a obtinut 230 de puncte. La 100 de puncte in spate, pe locurile 2-3, se afla \"Adriana Sperlea\":utilizator/adriana_s si \"Andrei Tiberiu Jurba\":utilizator/znakeu. Problema usoara, \"Economie\":problema/economie, a fost rezolvata de 4 concurenti, iar cea medie, \"Pairs\":problema/pairs doar de Bogdan. \"Aliens\":problema/aliens s-a dovedit a fi foarte grea, in special datorita etapei de implementare, limita stransa de timp si memorie impunand o solutie \"ca la carte\". Punctajul maxim obtinut in concurs la aceasta problema a fost de 30 de puncte. Speram sa vedem o imbunatatire a mediei punctajelor la rundele urmatoare.\r\n\r\nLa clasele 11-12, setul de probleme ales s-a dovedit a fi unul greu. Punctajele ar putea fi impartite in 3 categorii, primii 2 clasati obtinand 200 de puncte, iar apoi urmeaza 13 concurenti care au resit sa rezolve corect o problema si au avut intre 100 si 140 de puncte. Din pacate marea majoritatea a concurentilor nu au reusit sa obtina mai mult de 30 de puncte. Problema usoara a fost \"Pairs\":problema/pairs, ea aparand si in setul de la clasa a 10-a. Problema medie, \"Tunelul groazei\":problema/tunel, a fost rezolvata de doi concurenti, \"Stefan Filip\":utilizator/prostu si \"Stefan Istrate\":utilizator/stef2n. \"NKPerm\":problema/nkperm, problema grea, nu a fost rezolvata de niciun concurent, insa \"Mugurel Ionut Andreica\":utilizator/mugurelionut a obtinut 80 de puncte cu o solutie care lua TLE pe 2 teste. Aruncand la final o privire pe clasament, gasim in frunte 2 concurenti care nu mai participa la olimpiade, \"Mugurel Ionut Andreica\":utilizator/mugurelionut, care nu mai are nevoie de nicio prezentare, si \"Stefan Istrate\":utilizator/stef2n, student in anul I la \"FMI\":http://www.fmi.unibuc.ro si fost membru al lotului national in ultimii 2 ani. Pozitiile 3-4 sunt impartite de \"Cosmin Gheorghe\":utilizator/gcosmin si de \"Victor Rusu\":utilizator/victorsb.\r\n\r\n\"Echipa infoarena\":echipa-infoarena ii felicita pe toti participantii la runda 1 a concursului preONI si spera ca in rundele urmatoare vor fi si mai multi participanti si punctaje mai mari :).\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Ordine\':preoni-2008/runda-1/solutii#ordine\r\n* \'Multimi 2\':preoni-2008/runda-1/solutii#multimi2\r\n* \'Ecuatie\':preoni-2008/runda-1/solutii#ecuatie\r\n* \'Economie\':preoni-2008/runda-1/solutii#economie\r\n* \'Teren\':preoni-2008/runda-1/solutii#teren\r\n* \'Pairs\':preoni-2008/runda-1/solutii#pairs\r\n* \'Aliens\':preoni-2008/runda-1/solutii#aliens\r\n* \'Tunelul groazei\':preoni-2008/runda-1/solutii#tunel\r\n* \'NKPerm\':preoni-2008/runda-1/solutii#nkperm\r\n\r\n==include(page=\"preoni-2008/runda-1/solutii/ordine\")==\r\n\r\n==include(page=\"preoni-2008/runda-1/solutii/multimi2\")==\r\n\r\n==include(page=\"preoni-2008/runda-1/solutii/ecuatie\")==\r\n\r\n==include(page=\"preoni-2008/runda-1/solutii/economie\")==\r\n\r\n==include(page=\"preoni-2008/runda-1/solutii/teren\")==\r\n\r\n==include(page=\"preoni-2008/runda-1/solutii/pairs\")==\r\n\r\n==include(page=\"preoni-2008/runda-1/solutii/aliens\")==\r\n\r\n==include(page=\"preoni-2008/runda-1/solutii/tunel\")==\r\n\r\n==include(page=\"preoni-2008/runda-1/solutii/nkperm\")==\r\n',2993,'public',NULL,NULL),('preoni-2008/runda-1/solutii/economie','preoni-2008/runda-1/solutii/economie','2007-11-25 13:57:16','2007-11-26 16:23:55','h2(#economie). \'Economie\':problema/economie\r\n\r\nSortam crescator sirul de valori si putem observa ca valoarea cea mai mica din sir sigur va trebui folosita deoarece ea nu poate fi obtinuta adunand alte valori din sir (restul valorilor sunt mai mari sau egale decat aceasta). Fie cea mai mica valoare din sir $v{~1~}$, acum e clar ca putem obtine toate valorile de forma $x*v{~1~}$. Daca $v{~2~}$, a doua cea mai mica valoare din sir nu este de forma $x*v{~1~}$ va trebui sigur sa o folosim si pe ea. In general, daca suntem la pasul $i$ si $v{~i~}$ nu poate fi obtinuta din subsetul curent de valori selectate vom introduce $v{~i~}$ in subsetul care reprezinta solutia si vom updata toate valorile care se pot obtine considerand si aceasta valoare. Cum am introdus in subsetul solutie doar valorile care erau strict necesare, acesta este si numarul minim de valori. Complexitatea solutiei este {$O(N*VMAX)$} ca timp si {$O(VMAX)$} ca spatiu, unde $VMAX$ este valoarea maxima din sir, in cazul nostru $50 000$.\r\n',2092,'public',NULL,NULL),('preoni-2008/runda-1/solutii/aliens','preoni-2008/runda-1/solutii/aliens','2007-11-25 13:58:26','2010-03-20 22:55:06','h2(#aliens). \'Aliens\':problema/aliens\r\n\r\nProblema se rezolva cu ajutorul programarii dinamice. Fiecare fractie din cele date se poate scrie ca un produs de forma {$2^x^ * 3^y^ * 5^z^$}, unde {$x$}, $y$ si $z$ sunt numere intregi. Daca codificam fiecare fractie prin tripletul corespunzator, problema revine la a selecta anumite triplete {$(x{~1~}, y{~1~}, z{~1~})$}, {$(x{~2~}, y{~2~}, z{~2~})$}... {$(x{~K~} y{~K~} z{~K~})$} din cele $N$ astfel incat:\r\n\r\n* {$x{~1~} + x{~2~} + ... + x{~K~} &ge; 0$}\r\n* {$y{~1~} + y{~2~} + ... + y{~K~} &ge; 0$}\r\n* {$z{~1~} + z{~2~} + ... + z{~K~} &ge; 0$}\r\n* $2^(x{~1~} + x{~2~} + ... + x{~K~})^ * 3^(y{~1~} + y{~2~} + ... + y{~K~})^ * 5^(z{~1~} + z{~2~} + ... + z{~K~})^$ sa fie maxim posibil.\r\n\r\nFie {$D{~i, x3, x5~}$} valoarea maxim posibila pentru exponentul lui $2$ care se poate obtine din primele $i$ fractii, astfel incat exponentul lui $3$ sa fie $x3$ si exponentul lui $5$ sa fie {$x5$}. Tabloul {$D$} poate contine si indici negativi! Relatia de recurenta este urmatoarea:\r\n{$D{~i, x3, x5~}$} = maxim({$D{~i-1, x3, x5~}, D{~i-1, x3-x3\', x5-x5\'~} + x2\'$}), unde {$(x2\' x3\' x5\')$} este tripletul asociat celei de a {$i$}-a fractii.\r\nDin considerente de memorie nu vom retine tot tabloul {$D$}. Deoarece elementele de pe pozitii de forma ({$i, a, b$}) depind doar de elemente de pe pozitii de forma ({$i-1, a\', b\'$}) vom retine o singura matrice in locul unui tablou tridimensional si vom actualiza elementele din aceasta matrice printr-o parcurgere convenabila a indicilor.\r\nDupa ce avem tabloul $D$ construit, aflam maxim({$2^D{~N,x3,x5~}^ * 3^x3^ * 5^x5^$}), cu {$D{~N, x3, x5~} &ge; 0$}, $x3 &ge; 0$ si {$x5 &ge; 0$}. Pentru a compara doua numere $2^x1^ * 3^y1^ * 5^z1^$ si $2^x2^ * 3^y2^ * 5^z2^$ vom logaritma si vom compara {$x1*ln2 + y1*ln3 + z1*ln5$} cu {$x2*ln2 + y2*ln3 + z2*ln5$}. Atunci cand am aflat o solutie optima, este necesara implementarea operatiilor pe numere mari, deoarece rezultatul nu se incadreaza in nici un tip de date conventional.\r\nComplexitatea problemei este {$O(N^3^)$} de constanta {$4*(log{~3~}MAX)*(log{~5~}MAX)$}, unde {$MAX = 400.000.000$}. Aceasta solutie obtine 100 de puncte.',11154,'public',NULL,NULL),('preoni-2008/runda-1/solutii/tunel','preoni-2008/runda-1/solutii/tunel','2007-11-25 13:58:50','2007-11-25 18:35:26','h2(#tunel). \'Tunelul groazei\':problema/tunel\r\n\r\nVom nota cu $X[i]$ timpul mediu pentru a ajunge din nodul $i$ in nodul $N$. Evident, $X[N]$ va fi $0$. Pentru fiecare nod $i$, il vom exprima pe $X[i]$ in functie de toate valorile $X[j]$, unde $j$ este vecin cu $i$. Probabilitatea de a ajunge dintr-un nod $i$ in vecinul sau $j$ este $1/Grad[i]$. Deci, exista probabilitatea de $1/Grad[i]$ ca $X[i]$ sa fie egal cu $Distanta[i][j] + X[j]$. Dandu-i lui $j$ valorile tuturor vecinilor lui $i$, gasim o exprimare a lui $X[i]$ sub forma unei ecuatii. Folosind aceste observatii putem sa ne construim un sistem pe care sa il rezolvam cu metoda lui Gauss.',2028,'public',NULL,NULL),('preoni-2008/runda-1/solutii/teren','preoni-2008/runda-1/solutii/teren','2007-11-25 13:57:29','2007-11-27 13:43:56','h2(#teren). \'Teren\':problema/teren\r\n\r\nVom alege doua linii $i$ si $j$ din matrice ({$i &le; j$}) si vom determina care este dreptunghiul de arie maxima marginit de aceste doua linii si care contine cel mult $X$ valori de $1$. Fie $A[k] (1 &le; K &le; M)$ numarul de valori de $1$ de pe coloana $k$ care se afla intre liniile $i$ si $j$. Odata calculat acest vector $A$ problema se reduce la o problema pe vector si anume a determina o secventa de lungime maxima din vectorul $A$ cu suma elementelor $&le; X$. \r\nPentru a rezolva aceasta subproblema ne vom plimba cu doi indici $st$ si $dr (st &le; dr)$ care vor reprezenta capetele unei secvente cu suma elementelor $&le; X$. Pe masura cu avansam cu indicele $dr$ spre dreapta vom mari indicele $st$ in cazul in care suma curenta depaseste $X$ si la fiecare pas vom actualiza secventa de lungime maxima cu valoarea $dr-st+1$ , respectiv dreptunghiul de arie maxima cu valoarea $(j-i+1)*(dr-st+1)$.\r\nVom prezenta in continuare pseudocod pentru algoritmul descris, presupunand ca avem deja vectorul $A[1..M]$.\r\n\r\n==code(c) |st = 1\r\nsuma = 0\r\npentru dr = 1, M:\r\n    suma += A[dr]\r\n    cat timp (st <= dr) si (suma > X):\r\n        suma -= A[st]\r\n        st = st+1\r\n    daca st <= dr:\r\n        arie_max = max(arie_max, (j-i+1)*(dr-st+1))\r\n==\r\n\r\nComplexitatea acestui algoritm este $O(M)$, deoarece ciclul $cat timp$ nu se va executa mai mult de $M$ ori in total. Mai trebuie doar sa artam cum se poate calcula vectorul $A[1..M]$ in $O(M)$ pentru a obtine o rezolvare de complexitate $O(N^2^*M)$ (sunt $O(N^2^)$ perechi de linii pentu care vom efectua acest pas). \r\nFie $S$ o matrice cu semnificatia ca $S[p][q]$ reprezinta numarul de valori de $1$ din coloana $q$ de pe liniile $&le; p$. Putem calcula aceasta matrice dupa recurenta $S[p][q] = S[p-1][q] + T[p][q]$ unde $T$ este o matrice reprezentand terenul. Folosind aceasta matrice putem determina vectorul $A[1..M]$ cand avem fixate doua linii $i, j$ dupa recurenta $A[k] = S[j][k]-S[i-1][k]$. ',2092,'public',NULL,NULL),('preoni-2008/runda-1/solutii/ecuatie','preoni-2008/runda-1/solutii/ecuatie','2007-11-25 13:57:06','2007-11-26 19:05:42','h2(#ecuatie). \'Ecuatie\':problema/ecuatie\r\n\r\nDupa cum bine stim de la matematica putem rescrie o ecuatie $Ax^2^+Bx+C$ ca $A(x-x{~1~})(x-x{~2~})$ unde $x{~1~},x{~2~}$ sunt solutiile ecuatiei. Acestea se pot determina astfel:\r\n\r\n* Fie $delta = b^2^-4ac$\r\n* $x{~1~} = (-b-&radic;delta)/2a$\r\n* $x{~2~} = (-b+&radic;delta)/2a$\r\n\r\nEste evident ca o prima condite ca sa putem rescrie ecuatia sub forma $(P{~1~}x+Q{~1~})(P{~2~}x+Q{~2~})$ unde $P{~1~},P{~2~},Q{~1~},Q{~2~}$ sunt numere intregi este ca $delta$ sa fie patrat perfect.\r\nDin cele mai sus putem deduce ca:\r\n$(P{~1~}x+Q{~1~})(P{~2~}x+Q{~2~})$ = $P{~1~}P{~2~}(x+Q{~1~}/P{~1~})(x+Q{~2~}/P{~2~})$ = $A(x-x{~1~})(x-x{~2~})$\r\nEste imediat evident ca $P{~1~}$ trebuie sa fie un divizor al numarului $A$. Vom lua astfel fiecare divizor $d$ al numarului $A$ (atentie la semn! pentru $2$ se vor lua valorile $1,-1,2,-2$) si vom atribui urmatoarele valori:\r\n\r\ntable(layout). |* $P{~1~} = d$\r\n* $Q{~1~} = -x{~1~}*d$\r\n* $P{~2~} = A/d$\r\n* $Q{~2~} = -x{~2~}*(A/d)$|* $P{~1~} = d$\r\n* $Q{~1~} = -x{~2~}*d$\r\n* $P{~2~} = A/d$\r\n* $Q{~2~} = -x{~1~}*(A/d)$|\r\n\r\nUn divizor $d$ se considera bun doar daca $Q{~1~},Q{~2~}$ sunt numere intregi (atentie, $x{~1~}$ si $x{~2~}$ nu trebuie neaparat sa fie numere intregi ca sa existe solutii!). Astfel, putem genera toate solutiile intr-un vector, pe care le putem apoi sorta dupa $P{~1~}$ respectiv $Q{~1~}$ si vom afisa a $K$-a solutie din vector. \r\nPentru a genera toti divizorii numarului $A$ in complexitate $O(&radic;A)$ vom folosi urmatorul algoritm:\r\n==code(cpp) |pentru d = 1, sqrt(|A|):\r\n    daca A%d = 0:\r\n        d, -d, A/d, -A/d sunt divizori\r\n==\r\nO metoda simpla pentru a evita generarea aceleiasi solutii de mai multe ori (de exemplu in cazurile in care $d = A/d$ sau $x{~1~} = x{~2~}$) este eliminarea duplicatelor din vectorul de solutii inainte sa afisam rezultatul.',2028,'public',NULL,NULL),('preoni-2008/runda-1/solutii/ordine','Ordine','2007-11-25 13:55:52','2007-11-26 16:16:23','h2(#ordine). \'Ordine\':problema/ordine\r\n\r\nVom forma pas cu pas sirul solutie inserand de fiecare data primul caracter posibil (prin primul caracter posibil intelegem cel mai mic din punct de vedere lexicografic). Daca am inserat caractere pe primele $x-1$ pozitii si acum ne aflam pe pozitia $x$, este clar ca acest caracter este in primul rand diferit de caracterul de pe pozitia $x-1$. Acum daca exista un caracter care apare de $(N-x+1)/2+1$ ori, atunci acesta este singurul caracter pe care il putem insera, altfel vom insera primul disponibil diferit de cel de pe pozitia $x-1$. Daca avem un sir de lungime $P$ si un caracter apare de $P/2+1$ ori singurul mod de constructie a sirului este $cx{~1~}cx{~2~}cx{~3~}c....cx{~k~}c..$ unde $c$ este caracterul majoritar iar prin $x{~1~}, x{~2~}..x{~k~}..$ am notat celelalte caractere diferite de $c$. Complexitatea solutiei este {$O(sigma*N)$}, unde $sigma$ este dimensiunea alfabetului, in cazul nostru $26$. Plecand de la aceasta idee se poate obtine usor si un algoritm {$O(N)$}, dar acesta nu era necesar pentru obtinerea punctajului maxim.',2092,'public',NULL,NULL),('preoni-2008/runda-1/solutii/multimi2','preoni-2008/runda-1/solutii/multimi2','2007-11-25 13:56:50','2007-11-26 16:21:28','h2(#multimi2). \'Multimi 2\':problema/multimi2\r\n\r\nDaca $N$ este de forma $4*p$ vom imparti cele $N$ numere in grupe de cate patru numere de forma $4k, 4k+1, 4k+2, 4k+3$. Observam ca $4k-(4k+1)-(4k+2)+(4k+3)=0$. Numerele de forma $4k$ si $4k+3$ le vom plasa in prima multime iar celelalte in a doua multime si vom obtine diferenta $0$ minim posibila. Daca $N$ da restul $1$ la impartirea cu $4$, $N-1$ este divizibil cu $4$, vom imparti numerele de la $2$ la $N$ in grupe de cate patru ca la pasul anterior si vom plasa numarul $1$ in oricare din cele doua multimi si vom obtine diferenta $1$. Daca $N$ da restul $2$ la impartirea cu $4$, vom incepe prin a imparti numerele de la $3$ la $N$ iar apoi pe $1$ il vom introduce intr-o multime iar pe $2$ in cealalta, astfel vom obtine diferenta $1$. Daca $N$ da restul $3$ la impartirea cu $4$ vom imparti in grupe de cate patru numerele de la $4$ la $N$, numerele $1$ si $2$ le vom introduce intr-o multime, iar $3$ in cealalta si vom obtine diferenta $0$. Complexitatea solutiei este {$O(N)$}.\r\n',2092,'public',NULL,NULL),('propuneri/4-forum','IAP #4: Restructurare forum','2007-11-26 16:30:07','2008-02-11 16:32:07','h1. IAP #4: Restructurare forum\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2007-11-26                             |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"wefgef\")==    |\r\n|_. Stare     | *_RESPINS_*                     |\r\n\r\nh2. Abstract\r\n\r\nSe propune reorganizarea forumului infoarena intr-o forma liniara, care sa permita accesul mai rapid la topicuri. Deasemenea se doreste o modalitate de organizare care sa permita familiarizarea mai rapida cu forumul din partea membrilor noi.\r\n\r\nh2. Motivatie\r\n\r\nStructura actuala a forumului infoarena ingreuneaza navigarea, uneori fiind necesara accesarea succesiva a trei subforumuri pentru a viziona topicul dorit.\r\n\r\nNumarul utilizatorilor inregistrati pe site creste in fiecare zi si deseori se intampla ca noii veniti sa posteze aiurea in forumuri gresite. O organizare mai buna ar putea preintampina astfel de erori.\r\n\r\nDe asemenea, exista sectiuni vechi si depasite, care ar trebui mutate intr-o arhiva de discutii ce nu mai sunt de actualitate.\r\n\r\n*Cosmin:* Ce e misto la o ierarhie mai plata, e ca daca sunt subiecte noi sau replici noi le identifici mai bine vizual. Eu de exemplu dau direct click pe postul de la o sectiune verde, si posturile respective sunt cele mai accesate. O data ce un post nu mai e cel mai nou din o sectiune nu mai intra lumea pe el asa mult.\r\n\r\nh2. Modalitate de organizare a forumului\r\n\r\nMomentan forumul are doar doua categorii: \"infoarena - concursuri, probleme, evaluator, articole\" si \"Comunitate - feedback, proiecte si distractie\". Propun sa cream mai multe categorii si sa mutam unele subforumuri pe prima pagina pentru a usura accesul la ele.\r\n\r\nM-am gandit la urmatoarea structura (care trebuie imbunatatita, singur nu am avut destula inspiratie):\r\n\r\n* Categoria 1: Concursuri\r\n** preONI 2008\r\n** Happy Coding 2007\r\n** Arhiva de concursuri\r\n** Calendar de concursuri\r\n\r\nObservatii:\r\n\r\n# Forumul \"Calendar de concursuri\" ar contine toate topicurile din forumul actual \"Concursuri\".\r\n# In momentul in care forumul unui concurs de pe prima pagina (cum ar fi aici de exemplu \"Happy Coding 2007\") nu mai este de actualitate, el este mutat in \"Arhiva de concursuri\".\r\n\r\n* Categoria 2: Infoarena related topics (Nu am gasit un nume potrivit deocamdata)\r\n** Arhiva de probleme\r\n** Articole\r\n** Downloads\r\n\r\nObservatii:\r\n\r\n# Momentan \"Arhiva de probleme\" contine subforumurile \"Probleme pentru bacalaureat\" si \"Teste grila\". Acestea ar urma sa fie mutate in categoria 8.\r\n# Downloads ar urma sa fie mutat din \"Articole\" pe prima pagina.\r\n\r\n* Categoria 3: Probleme externe\r\n** SGU\r\n** TIMUS\r\n** UVA\r\n** SPOJ\r\n** PKU\r\n** TJU\r\n\r\nObservatii:\r\n\r\n# Ar putea fi adaugat orice site de pe care lucreaza concurentii romani probleme\r\n\r\n* Categoria 4: Implica-te\r\n** Imbunatatire teste\r\n** Development\r\n** Scrie articole\r\n** Extinde arhiva\r\n\r\n* Categoria 5: Discutii intime\r\n** Proiecte, idei\r\n** Discutii administratori\r\n** Arhiva cu discutii intime\r\n** preONI 2008\r\n\r\nObservatii:\r\n\r\n# Cateogorie invizibila pentru utilizatorii obisnuiti\r\n# Acces limitat pentru moderatori/helperi.\r\n\r\n* Categoria 6: Informatica\r\n** Algoritmi, structuri de date\r\n** Programare si limbaje\r\n** Teme\r\n\r\n* Categoria 7: Comunitate - feedback, distractie\r\n** Feedback infoarena\r\n** Blog\r\n** Sondaje\r\n** Offtopic\r\n\r\n* Categoria 8: Arhiva cu discutii ce nu mai sunt de actualitate\r\n** Probleme pentru bacalaureat\r\n** Teste grila\r\n** Arhiva (subforumul actual al \"Feedback infoarena\")\r\n\r\nh2. Reguli\r\n\r\nCred ca ar trebui completat si finalizat setul de \"reguli\":reguli.\r\n\r\nh3. Feedback\r\n\r\nM-am gandit destul de mult cum ar fi cel mai bine sa organizam forumul. Desi nu ar arata la fel de estetic prima pagina, cred totusi ca astfel ar creste utilitatea. Astept pareri si propuneri.',1,'public',NULL,NULL),('propuneri/2-concurs-studenti','IAP #2: Concurs pentru studenti','2007-11-06 21:46:50','2007-11-28 11:52:14','h1. IAP #2: Concurs pentru studenti\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2007-11-07                             |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"silviug\")==  ==User(type=\"tiny\" user=\"wickedman\")==|\r\n|_. Stare     | *_IN-CONSTRUCTIE_*                     |\r\n\r\nh2. Abstract\r\n\r\nIn acest document propunem organizarea unui concurs de programare pentru studenti.\r\n\r\nConcursul se va desfasura in echipe de cate 1-3 studenti si urmareste stimularea insusirii cunostintelor fundamentale de algoritmi. In particular, concursul este conceput sa-i ajute pe studenti in pregatirea pentru ACM.\r\n\r\nh2. Motivatie\r\n\r\nComunitatea infoarena va fi extinsa inspre studenti. Baza noastra de cunostinte va deveni utila si studentilor putand fi folosita ca material aditional pentru anumite cursuri.\r\n\r\nLa momentul actual nu exista nici un concurs _national_ de informatica destinat studentilor. Ne propunem organizarea unui astfel de concurs (2 runde online + finala) de 2-3 ori pe an.\r\n\r\nh2. Format\r\n\r\nIn elaborarea formatului am pornit de la urmatoarele premise:\r\n\r\n* Concursul sa fie pe echipe. Permitem echipe intre 1-3 oameni pentru a nu descuraja pe cei care vor sa participe \"din curiozitate\" si nu doresc sa-si racoleze coechipieri.\r\n* Formatul rundelor de calificare si regulile sa fie flexibile pentru a permite studentilor \"ocupati\" sa participe.\r\n\r\n\r\nh3. Echipe\r\n\r\n* O echipa poate fi formata din 1 pana la 3 studenti de la aceeasi facultate\r\n* Echipele se formeaza inainte de prima runda de calificare si raman pana la final\r\n\r\nh3. Runde de calificare\r\n\r\n* Online\r\n* 3-10 probleme, rezolvabile in 3-4 ore de o echipa buna (etalon: _infoarena coders_)\r\n* Solutiile pot fi submitate oricand pe parcursul a ~12 (nu dorim ore fixe pentru a reduce conflictele cu activitatile studentilor).\r\n* -Se vor da punctaje partiale pentru solutii incorecte/neoptime.- Punctaje ca la happy coding (max sau 0).\r\n* La rundele online vrem ca participantii sa vada cate teste au mers si motivul pentru care pica restul pentru a face concursul mai digerabil. La finala acest lucru nu mai e valabil.\r\n* Se pot da probleme cu punctaje maxime diferite.\r\n* Nu exista restrictii referitor la numarul de calculatoare folosite sau timpul de rezolvare a problemelor.\r\n* Orice echipe care schimba surse intre ele vor fi descalificate ({%{color:red}sistem de detectare?%})\r\n\r\nh3. Runda finala:\r\n\r\n* Calificam primele 5-10 echipe\r\n* Concurs gen ACM -dar cu punctaje partiale-\r\n* Un singur calculator\r\n* 5 ore, 5-10 probleme, una rezolvabila de absolut toata lumea, scorul maxim imposibil de obtinut\r\n\r\nh3. Premii:\r\n\r\n* Vrem premii \'sparse\' care sa incurajeze participarea (de ex. tricouri/hanorace pentru toti cei care fac peste 100 in rundele de calificare)\r\n* Primul premiu sa fie destul de tentant\r\n* Premiile de la finala se vor da pentru fiecare component al echipei castigatoare. Astfel, daca in echipa castigatoare va fi un singur om acesta NU va lua premiul cat pentru 3 oameni. Vom incuraja astfel formarea unor echipe cat mai mari.\r\n\r\nh3. Buget\r\n\r\n\'Aici\':http://spreadsheets.google.com/ccc?key=pAYu9RV8qA7ooCba2vicqXQ se gaseste o propunere de buget.\r\n\r\n\r\nh3. Feedback\r\n\r\nCosmin: La Mures organizeaza un concurs pe echipe cu mai multe runde in care prima echipa castiga vreo 500 si in un concurs parca o problema daca o faceai era 100 de euro. Mi s-a parut misto ideea.\r\n\r\nSilviu: Ideea de bonus pe problema e buna. Personal as face pe numar de probleme si in finala. De exemplu: 333 de euro daca rezolvi 7/10, 222  - 5/10.\r\n\r\nCosmin: Pentru participare trebuie sa stim oameni din universitatile alea, eu stiu la Babes. Dar asa iti trebuie cate un om bagat in treaba la fiecare universitate.\r\n\r\nSilviu: De acord, insa pentru inceput nu o sa putem acoperi toate universitatile din tara. Una din ideile noastre e sa trimitem un mail la team-leader-ii echipelor de ACM. Asta ar acoperi o buna parte din studentii car ar putea participa in prima faza.\r\n\r\nCosmin: Trebuie sa fie cat mai usor de participat la concursuri, altfel ii prinzi doar pe cei ce vor acm, trebuie sa poata participa oamenii si casual nu numai pe bune. Vrem un public cat mai larg nu doar fosti lotisti. Pt asta trebuie timp putin (o ora jumate), probleme de dificultate medie si simpla, eventual cu 2 nivele ca sa putem sa ii vedem si pe cei mai buni si doar 2 probleme.\r\n\r\nSilviu: Desi ideea de la care ai plecat e buna (nu vrem sa targetam doar acm-isti), implementarea pe care o propui deriva de la ce vrem noi cu concursul asta. Formatul pe care il propui e asemanator unui SRM si pare a fi alt gen de concurs. O observatie interesanta e ca nici topcoder-ul nu atrage foarte multi studenti din Romania. Motivele cele mai importante care imi vin in minte sunt: elitismul si concurenta acerba. Ne trebuie ceva mai entry-level, sa incurajam lumea sa incerce.\r\n\r\nCosmin: O chestie super importanta e sa avem formatu concursului de acm pus pe site, si atunci cand o universitate face pregatiri interne sa il poata folosi.\r\n\r\nSilviu: Corect, totusi nu e relevant relativ la concursul nostru. Putem sa-i dam drumul si cu infrastructura curenta. Ce spui tu e un feature request care ar prinde foarte bine pe infoarena.\r\n\r\n\r\nh3. Sugestii de la \'sedinta\':http://infoarena.ro/planificare/sedinta-20071107\r\n\r\n* Am putea organiza o runda online de proba (sau mai degraba practice). Este primul nostru concurs pentru studenti. O runda de proba i-ar ajuta sa se familiarizeze cu platforma. In plus, ne-ar putea oferi informatii despre interesul studentilor in astfel de concursuri.\r\n* Cum probam piata? De unde stim ca vom avea participanti?\r\n* Runda de practice?\r\n* Cum propagam vestea in universitatile din tara?\r\n* *Nu vom avea probleme de copyright daca facem concursul/finala prea ACM like?*\r\n\r\n\r\n',15,'public',NULL,NULL),('preoni-2008/runda-1/solutii/pairs','preoni-2008/runda-1/solutii/pairs','2007-11-25 13:57:47','2007-11-29 18:47:56','h2(#pairs). \'Pairs\':problema/pairs\r\n\r\nProblema admite o rezolvare triviala de complexitate {$O(N^2^log MAX)$}, unde $MAX$ este maximul dintre cele $N$ numere ale multimii {$M$}: pentru fiecare pereche de numere din multimea data se calculeaza cel mai mare divizor comun folosind algoritmul lui Euclid. O astfel de rezolvare obtine 20-30 de puncte, in functie de prezenta unor optimizari. Rezolvarea optima are complexitatea {$O(MAX log MAX)$} si se baza pe faptul ca {$O(N/1 + N/2 + N/3 ... + N/N)$} = {$O(N log N)$}, pentru orice {$N$}.\r\nDin numarul total de perechi, {$N*(N-1)/2$}, vom scadea numarul de perechi {$(x y)$}, astfel incat $x$ si $y$ nu sunt prime intre ele si vom obtine rezultatul cerut. Notam cu $Res$ numarul de perechi {$(x y)$}, cu {$cmmdc(x, y) > 1$}. Pentru a afla efectiv numarul $Res$ vom folosi procedeul includerii si excluderii. Fie {$x{~i~}$} numarul de numere din $M$ care se divid cu {$i$}. Vectorul $x$ se poate calcula in {$O(MAX log MAX)$}: pentru fiecare numar $i$ de la $1$ la $MAX$ verificam cate din numerele {$i$}, {$2i$}, {$3i$} ... {$[MAX/i]*i$} apartin multimii {$M$}. Consideram toate numerele $P$ ce se scriu ca produs de numere prime, unde fiecare numar prim este folosit cel mult o data. Daca numarul de numere prime din descompunerea lui $P$ este un numar impar, adunam {$x{~P~} * (x{~P~}-1) / 2$} la {$Res$}. Altfel, din {$Res$} scadem {$x{~P~} * (x{~P~}-1) / 2$}.\r\nRezolvarea de complexitate {$O(MAX log MAX)$} asigura obtinerea punctajului maxim.\r\n\r\n',256,'public',NULL,NULL),('blog/inteligenta-nativa-sau-educata','Inteligenta, nativa sau educata?','2007-11-30 08:45:15','2008-11-15 13:41:14','Prin scoala generala si apoi in liceu, credeam ca inteligenta unui om are un nivel maxim pana la care se poate ajunge, care prin oricata munca nu se poate depasi.\r\n\r\nLa sfarsitul liceului si inceputurile facultatii, prin 2002, m-am mai maturizat si eu si mi-am schimbat parerea. Cred ca in conditii intr-un mediu bun si cu o motivatie puternica poti progresa extrem de mult. Este mai important sa lucrezi bine si sa nu intri in rutina, decat sa lucrezi mult.\r\n\r\nAm citit mai multe articole interesante legate de tema asta din care trei mi-au ramas in minte:\r\n\r\n\'How to raise smart kids\':http://www.sciam.com/article.cfm?id=the-secret-to-raising-smart-kids&print=true ne spune cum copiii care cred ca inteligenta poate fi antrenata evolueaza in timp mult mai bine fata de cei cu credinta ca inteligenta e o chestie nativa.\r\n\r\n\'Teach yourself programming in ten years\':http://norvig.com/21-days.html , scris de directorul pe cercetare de la Google, sustine ca performanta intr-un domeniu se atinge dupa multi ani de practica, si ne ofera ca exemple unii oameni considerati genii, cum au fost Mozart, Beatles sau Chaucer, ce au produs rezultate de nivel foarte inalt dupa mai mult de zece ani de activitate in domeniul in care erau experti.\r\n\r\nAl treilea articol \'The Grandmaster Experiment\':http://psychologytoday.com/articles/index.php?term=pto-3789.html&fromMod=popular_parenting este despre psihologul Polgar care si-a ajutat toate cele trei fiice ale sale sa devina maestre la sah. Polgar nu credea in notiunea de geniu, iar reusita lui demonstreaza intr-o oarecare masura acest lucru.  Intr-o perioada in care se considera ca viziunea spatiala era una mai grea pentru inteligenta feminina, performantele celor trei fete au demonstrat contrariul.\r\n\r\nCititi toate trei articolele pentru ca merita.\r\n\r\nVoi ce credeti? Este inteligenta o caracteristica mai mult nativa sau educata?\r\n\r\n',1490,'protected',2433,NULL),('preoni-2008/runda-2/solutii/dusman','preoni-2008/runda-2/solutii/dusman','2007-12-16 15:07:09','2007-12-17 22:45:56','h2(#dusman). \'Dusman\':problema/dusman\r\n\r\nDesi la o prima vedere limitele ar putea parea prea mari, problema se rezolva folosind tehnica backtracking. Pur si simplu se genereaza in ordine lexicografica primele $K$ permutari indeplinind conditiile din enunt.\r\n\r\nUrmatorul cod reprezinta o implementare simplista si intuitiva a problemei:\r\n\r\n==code(c)|void dusman(int i)\r\n{\r\n    if(k<0) return;\r\n    if(i>n)\r\n        k--;  \r\n        if(k==0)\r\n           afiseaza();        \r\n        return;\r\n    for(j=1;j<=n;++j)\r\n        if(!v[j]&&!A[p[i-1]][j])\r\n            v[j]=1;\r\n            p[i]=j;\r\n            doit(i+1);\r\n            viz[j]=0;\r\n}\r\n==\r\n\r\nAlgoritmul merge repede si furnizeaza solutie repede datorita restrictiei ca fiecare vecin are cel mult 3 dusmani.\r\n\r\nCa o optimizare la acest algoritm ca de altfel la majoritatea problemelor care implica generarea permtarilor se pot folosi \'dacing links\':http://en.wikipedia.org/wiki/Dancing_Links, dar acest lucru nu era necesar pentru obtinerea punctajului maxim.',1,'public',NULL,NULL),('implica-te/scrie-articole/todo','Articole TODO list','2007-10-29 18:27:10','2008-02-19 09:16:15','h1. Articole TODO list\r\n\r\nh2. Silviu\r\n\r\n* Terminat heapuri\r\n* Revizuit articole hash-uri ({*done*})\r\n* Ping autori: Alex Mosoi, Catalin Tiseanu, Mihnea Giurgea\r\n* ??\r\n\r\nh2. Stefan\r\n\r\n* Transformat problemele lui Cosmin in articol\r\n* Ping autori: Marius Stroe, Tibi Savin/Sima Cotizo, Mircea Dima\r\n* ??\r\n\r\nh2. Generale\r\n\r\n* Cioturi la articole\r\n** Lista de articole cu care incepem\r\n** Facut cioturi\r\n* Transcris \"Psihologia\" in format textila\r\n** Momentan e OK asa ca prim pas\r\n** Mai multe detalii \'aici\':implica-te/scrie-articole/cartea-lui-francu\r\n* Revizuit pagina de articole si layout-ul ei.\r\n* Revizuit articolele existente\r\n** Pus TOC\r\n** Refactorizat, actualizat continut\r\n* Documentatie despre articole\r\n** Cum se scrie un articol?\r\n** LaTeX\r\n** Coding style in articole\r\n',15,'public',NULL,NULL),('utilizator/login','Profil login','2007-12-05 17:33:19','2007-12-05 17:33:19','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',7290,'public',NULL,NULL),('blog/demouri-tari-de-la-siggraph','Demouri tari de la SIGGRAPH','2007-10-28 11:05:33','2008-11-16 12:44:29','Pol Catalin mi-a aratat un demo de la \'SIGGRAPH 2007\':http://www.siggraph.org/s2007/ . Demonstratia este impresionanta, si ne arata cum, cu un algoritm simplu, putem obtine o calitate foarte buna cand redimensionam imagini. Algoritmul functioneaza bine chiar daca imaginea finala e mai mare decat cea initiala.\r\n\r\nM-am uitat pe la alte paperuri si demouri de la SIGGRAPH si am dat peste plasma pong, un joculet foarte misto care mi-a adus aminte de vremurile din liceu cand pierdeam ore in sir implementand diversi algoritmi ce generau plasme sau focuri.\r\n\r\nPuteti vedea mai jos cele doua demouri, primul e de cinci minute, iar al doilea de doua. Enjoy!\r\n\r\n==YoutubeVideo(id=\"c-SSu3tJ3ns\" width=\"425\" height=\"350\")==\r\n\r\n*Update* Gasiti \'aici\':http://www.seamcarving.com/arik/imret.pdf lucrarea care descrie algoritmul folosit.\r\n\r\n==YoutubeVideo(id=\"4ibrqdfm9WA\" width=\"425\" height=\"355\")==\r\n\r\n\r\n',1851,'protected',2233,NULL),('blog/romanii-la-disneyworld-partea-a-treia','Romanii la DisneyWorld - partea a treia','2007-12-05 19:03:55','2008-11-15 13:41:14','_In aceasta serie de interviuri povestim despre concursurile de pe TopCoder cu cei trei romani care au participat la finala concursului TopCoder Collegiate Chalenge din aceasta toamna. Puteti citi celelalte doua interviuri \'aici\':blog/romanii-la-disneyworld-partea-intai si \'aici\':blog/romanii-la-disneyworld-partea-a-doua . Pe \'Mircea\':utilizator/domino probabil il stiti deja si nu cred ca mai are nevoie de prezentare. In acest interviu el ne povesteste despre formatul competitiilor de algoritmica. Cred ca va fi interesant sa cititi opinia romanului cu cel mai mare rating la algoritmica despre aceste concursuri._\r\n\r\nh2. Mircea Pasoi\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/romanii-la-disneyworld-partea-a-treia?mircea.jpg!*Povesteste-ne putin despre formatul concursului de algoritmica.*\r\nFormatul general Topcoder este urmatorul: ai 75 de minute sa faci 3 probleme, una usoara de 250 de puncte, una medie de 500 de puncte si una grea de 1000 de puncte. Cand trimti o problema punctajul pe care il primesti depinde de cat de repede ai rezolvat-o. Dupa cele 75 de minute ai inca 15 minute de \"challenge\", moment in care te uiti in sursele celorlati concurenti si incerci sa gasesti greseli. La sfarsit se evalueaza probleme si primesti puncte pentru o problema doar daca ai trecut toate testele.\r\nDeaorece la o finala problemele sunt mult mai grele decat la un SRM obisnuit, faza de \"coding\" este de 85 de minute.\r\n\r\n*E a doua oara cand te califici la faza finala a concursului TopCoder Collegiate Challenge. Se simte vreo diferenta fata de anul trecut?*\r\nCred ca rating-ul si rezultatul de anul asta dovedesc ca fost am mult mai bine pregatit ca anul trecut, si stiam si la ce sa ma astept de data asta. Chiar si asa, mai am mult de lucrat pana cand sa ma pot pune cu cei mai buni.\r\n\r\n*Cum se compara acest concurs cu celelalte concursuri internationale la care ai participat? Ca timp, stres, tipuri de probleme, strategie in concurs, concurenti sau locatie?*\r\n\r\nTopcoder este foarte diferit de concursurile de liceu. In primul rand cand treci de la concursuri de 5 ore la concursuri de 75 de minute diferenta e dramatica , si iti ia ceva sa te acomodezi. Un lucru foarte important la Topcoder este sa scrii cod corect, scurt si fara bug-uri. Poate pentru multa lume suna trivial, dar este mult mai greu decat pare! Concursurile de liceu nu te ajuta prea multe la chestiile astea, fiindca daca ai 5 ore iti permiti sa scrii incet, sa faci debug si mult testing. Plus ca uneori nu conteaza daca ai bug-uri ca tot iei puncte. Asa ceva nu merge la Topcoder. Eu unul am fost de mult ori surprins de solutiile altora care erau mult mai scurte si mai clare decat ceea ce faceam eu. Asta m-a ajutat mult sa-mi imbunatatesc implementarile. E surprinzator cate de usor e sa te complici sau sa faci chestii redundate cand scrii o sursa. Cred ca asta e si diferenta dintre cei din varf si restul lumii. Nu sunt mai buni pentru ca stiu sa scrie cod mai repede si mai mult, sunt mai buni pentru ca gandesc mai eficient si stiu sa scrie cod cat mai simplu.\r\nExperienta de asemenea conteaza foarte mult. Cand ai 4-5 ore iti permiti sa incerci sa explorezi mai multe idei de rezolvare, lucru care rareori se intampla la Topcoder. Stai intre 5 si 15 minute sa te gandesti si apoi te apuci sa implementezi. Daca n-ai plecat pe ideea buna, de obicei nu mai sanse sa rectifici greseala. Mai bine treci la alta problema. Citeam pe undeva ca marii maestri la sah sunt mai buni decat restul nu pentru ca pot analiza mai multe posiblitati decat majoritatea lumii, ci pentru ca stiu sa analizeze cele mai bune posibilitati. Ceva de genul asta e valabil si la Topcoder.\r\nO alta chestie destul de diferita sunt problemele, care de obicei sunt ceva mai simple decat cele pe la concursurile de liceu (ma refer in principal la 250 si 500, deoarece 1000le de obicei e comparabil cu problemele grele de liceu). Mindset-ul pe care trebuie sa-l ai cand rezolvi la Topcoder este destul de diferit de cel din liceu unde trebuie sa stai ceva timp sa te prinzi de solutia cea mai eficienta, de obicei trecand prin mai multe solutii din ce in ce mai eficiente. Aici trebuie sa te gandesti din prima care e solutia pe care o pot implementa cel mai repede si care se incadreaza in timp! Eu la inceput mereu aveam tendinta sa ma complic in rezolvari, sa optimizez unde nu era cazul sau sa ma gandesc direct la idei mai complicate decat era nevoie.\r\nPer total, eu consider Topcoder ceva mai distractiv decat concursurile de liceu si o provocare mult mai mare in acelasi timp. Un lucru foarte important este ca oamenii cu care concurezi chiar sunt cei mai buni din lume, nu cei mai buni elevi de liceu (diferenta e ceva de genul ONI vs. IOI). \r\n\r\n*Cum te-ai pregatit pentru concurs?*\r\nDin pacate nu m-am mai pregatit deloc in ultimul an in mod special pentru Topcoder. Prin asta ma refer sa intru in arena si sa fac SRM-uri vechi. In schimb m-am pregatit pe infoarena si pentru ACM si se pare ca a fost destul de folositor pana acum.\r\n\r\n\r\n*Este greu sa te calfici in finala?*\r\nDa, este destul de greu. Cum am zis concurezi cu cei mai buni din lume pentru 48 de locuri. Poate parea mult, dar pe masura ce Topcoder devine din ce in ce mai popular e din ce in ce mai greu sa te califici Acum 2-3 ani nu erau mai deloc rusi la finale deoarece nu stiau de Topcoder, iar acum sunt in jur de 15 oameni din Rusia in mod constant. Cu China e aceeasi poveste si mai sunt si alte tari. Din fericire incepand cu TCO 2008 vor fi 72 de locuri. Oricum, oricat de bun ai fi, fara un pic de noroc n-ai cum sa te califici :)\r\n\r\n*Ce abilitati trebuie sa aiba un concurent puternic la algoritmica?*\r\nIn mare parte ar fi ce am mentionat si mai sus:\r\n\r\n* sa gandesti repede si sa stii ce idei de rezolvare sa incerci (experienta ajuta mult in cazul asta)\r\n* sa scrii cod scurt si fara bug-uri intr-un ritm decent (nu trebuie sa-ti zboare degetele pe tastatura)\r\nO chestie deseori neglijata este cat de bine iti controlezi emotiile. Este foarte important sa fii cat mai relaxat la astfel de concursuri, si mai ales la TC unde stresul este ceva mai mare din cauza timpului putin.\r\n\r\n*Care a fost problema ta favorita din concurs?*\r\nProblema de 1000 din Room 3 pe care am facut-o doar eu si inca o persoana si cu ajutorul careia m-am calificat in cei 8 din finala.\r\n\r\n*Ce ti-a placut la DisneyLand?*\r\nParcurile Disney :) Ar fi fost si mai tare daca ne lasau 2 zile in loc de 1 sa vedem toate parcurile. Daca cineva vrea sa vada poze pe care le-am facut la Disney si la TCCC poate sa intre \'aici\':http://picasaweb.google.com/mircea.pasoi/TCCC07 .\r\n\r\n*Ce iti place la TopCopder?*\r\nCam tot ce am explicat mai sus :) Trebuia sa te ascult si sa ma fi ocupat inca din liceu serios de Topcoder. :P\r\n\r\n_Cu acest post am terminat seria de interviuri despre concursurile topcoder. Sper ca acestea v-au motivat sa incercati competitiile care sunt foarte misto si pe toate gusturile. Ca liceean sau ca student este o modalitate foarte buna sa inveti ceva nou, sa cunosti oameni foarte buni, sa faci un ban in timpul liber si sa intrii in contact cu recruiteri pentru companii puternice ca Google, Microsoft, NVidia, Yahoo, AMD, Intel, City Group, UBS si altele. \'Paul\':utilizator/pauldb a anuntat deja pe \'forum\':forum/index.php?topic=2452 , dar vreau sa reamintesc si eu elevilor de liceu ca se apropie turneul TopCoder pentru liceeni. Anul trecut s-au calificat doua echipe din Romania. Una de la Colegiul national \"Liviu Rebreanu\" - Bistrita (liceul meu :) ) si alta de la ICHB, a doua echipa nu a putut sa participe pentru ca turneul era in conflict cu alt concurs. Sper ca anul asta sa se califice si mai multe echipe din Romania. Bafta!_\r\n\r\n',1490,'protected',2454,NULL),('runda/preoni2008-runda2-5-8/clasament','Clasament preoni2008-runda2-5-8','2007-12-06 14:17:32','2007-12-06 14:17:32','h1. Clasament ==roundparam(round_id=\"preoni2008-runda2-5-8\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda2-5-8\")==',1,'round: preoni2008-runda2-5-8',NULL,NULL),('preoni-2008/runda-2/9','preONI 2008 - Runda 2, Clasa a 9-a','2007-12-06 14:19:26','2007-12-06 14:24:32','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda2-9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-2 \r\n* \'Clasele 5-8\':preoni-2008/runda-2/5-8\r\n*(active) \'Clasa a 9-a\':preoni-2008/runda-2/9 \r\n* \'Clasa a 10-a\':preoni-2008/runda-2/10 \r\n* \'Clasele 11-12\':preoni-2008/runda-2/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-2/5-8\r\n\r\n== roundregister(round_id=\"preoni2008-runda2-9\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda2-9\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda2-9\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-2/9.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"preoni2008-runda2-9\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',1,'round: preoni2008-runda2-9',NULL,NULL),('runda/preoni2008-runda2-9/clasament','Clasament preoni2008-runda2-9','2007-12-06 14:19:26','2007-12-06 14:19:26','h1. Clasament ==roundparam(round_id=\"preoni2008-runda2-9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda2-9\")==',1,'round: preoni2008-runda2-9',NULL,NULL),('preoni-2008/runda-2/10','preONI 2008 - Runda 2, Clasa a 10-a','2007-12-06 14:20:47','2007-12-06 14:25:10','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda2-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-2 \r\n* \'Clasele 5-8\':preoni-2008/runda-2/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-2/9 \r\n*(active) \'Clasa a 10-a\':preoni-2008/runda-2/10 \r\n* \'Clasele 11-12\':preoni-2008/runda-2/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-2/5-8\r\n\r\n== roundregister(round_id=\"preoni2008-runda2-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda2-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda2-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-2/10.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"preoni2008-runda2-10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',1,'round: preoni2008-runda2-10',NULL,NULL),('runda/preoni2008-runda2-10/clasament','Clasament preoni2008-runda2-10','2007-12-06 14:20:47','2007-12-06 14:20:47','h1. Clasament ==roundparam(round_id=\"preoni2008-runda2-10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda2-10\")==',1,'round: preoni2008-runda2-10',NULL,NULL),('runda/preoni2008-runda2-11-12/clasament','Clasament preoni2008-runda2-11-12','2007-12-06 14:22:06','2007-12-06 14:22:06','h1. Clasament ==roundparam(round_id=\"preoni2008-runda2-11-12\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda2-11-12\")==',1,'round: preoni2008-runda2-11-12',NULL,NULL),('preoni-2008/runda-2/5-8','preONI 2008 - Runda 2, Clasele 5-8','2007-12-06 14:17:32','2007-12-06 14:23:47','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda2-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-2 \r\n*(active) \'Clasele 5-8\':preoni-2008/runda-2/5-8 \r\n* \'Clasa a 9-a\':preoni-2008/runda-2/9 \r\n* \'Clasa a 10-a\':preoni-2008/runda-2/10 \r\n* \'Clasele 11-12\':preoni-2008/runda-2/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-2/5-8\r\n\r\n== roundregister(round_id=\"preoni2008-runda2-5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda2-5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda2-5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-2/5-8.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"preoni2008-runda2-5-8\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',1,'round: preoni2008-runda2-5-8',NULL,NULL),('preoni-2008/runda-2/11-12','preONI 2008 - Runda 2, Clasele 11-12','2007-12-06 14:22:06','2007-12-16 08:49:12','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda2-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-2 \r\n* \'Clasele 5-8\':preoni-2008/runda-2/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-2/9 \r\n* \'Clasa a 10-a\':preoni-2008/runda-2/10 \r\n*(active) \'Clasele 11-12\':preoni-2008/runda-2/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-2/5-8\r\n\r\n== roundregister(round_id=\"preoni2008-runda2-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda2-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda2-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-2/11-12.\r\n\r\nh2. Probleme\r\n\r\n{*S-a modificat exemplul la problema Gather si s-a adaugat o precizare: Gigel nu se numara ca detinut in calculul pentru depasirea capacitatilor D*}\r\n\r\n== Tasks(round_id=\"preoni2008-runda2-11-12\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',961,'round: preoni2008-runda2-11-12',NULL,NULL),('preoni-2008/clasament/runda-2/5-8','preONI 2008 - Clasament Runda 2, Clasele 5-8','2007-12-06 14:26:47','2007-12-06 14:26:47','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda2-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-2\r\n* \'Clasele 5-8\':preoni-2008/runda-2/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-2/10\r\n* \'Clasele 11-12\':preoni-2008/runda-2/11-12\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-2/5-8\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasele 5-8\':preoni-2008/clasament/runda-2/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-2/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-2/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda2-5-8\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2008/clasament/runda-2/9','preONI 2008 - Clasament Runda 2, Clasa a 9-a','2007-12-06 14:27:27','2008-01-13 18:35:22','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda2-9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-2\r\n* \'Clasele 5-8\':preoni-2008/runda-2/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-2/10\r\n* \'Clasele 11-12\':preoni-2008/runda-2/11-12\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-2/5-8\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':preoni-2008/clasament/runda-2/5-8\r\n*(active) \'Clasa a 9-a\':preoni-2008/clasament/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-2/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-2/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda2-9\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2008/clasament/runda-2/10','preONI 2008 - Clasament Runda 2, Clasa a 10-a','2007-12-06 14:28:01','2007-12-06 14:28:01','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda2-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-2\r\n* \'Clasele 5-8\':preoni-2008/runda-2/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-2/10\r\n* \'Clasele 11-12\':preoni-2008/runda-2/11-12\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-2/5-8\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':preoni-2008/clasament/runda-2/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-2/9\r\n*(active) \'Clasa a 10-a\':preoni-2008/clasament/runda-2/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-2/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda2-10\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2008/clasament/runda-2/11-12','preONI 2008 - Clasament Runda 2, Clasele 11-12','2007-12-06 14:28:28','2007-12-06 14:28:28','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda2-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-2\r\n* \'Clasele 5-8\':preoni-2008/runda-2/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-2/10\r\n* \'Clasele 11-12\':preoni-2008/runda-2/11-12\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-2/5-8\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':preoni-2008/clasament/runda-2/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-2/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-2/10\r\n*(active) \'Clasele 11-12\':preoni-2008/clasament/runda-2/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda2-11-12\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('propuneri/5-open-surse','IAP #5: Open surse','2007-12-06 18:09:21','2008-01-16 08:08:00','h1. IAP #5: Open surse\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2007-12-06 |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"domino\")== |\r\n|_. Stare     | *_APROBAT_* (2007-12-18) |\r\n\r\n(toc)*{text-align:center;} *Continut*\r\n* \'Abstract\':propuneri/5-open-surse#abstract\r\n* \'Motivatie\':propuneri/5-open-surse#motivatie\r\n* \'Dezavantaje\':propuneri/5-open-surse#dezavantaje\r\n* \'Detalii\':propuneri/5-open-surse#detalii\r\n* \'Implementare\':propuneri/5-open-surse#implementare\r\n* \'Feedback\':propuneri/5-open-surse#feedback\r\n\r\nh2(#abstract). Abstract\r\n\r\nSe propune un sistem prin care concurentii vor avea acces la sursele trimise de alti concurenti la anumite probleme. \r\n\r\nh2(#motivatie). Motivatie\r\n\r\nVizualizarea surselor trimise de alti concurentii este un feature cerut de utilizatori de foarte mult timp si asupra caruia au avut loc multe dezbateri. Concluzia generala a fost ca este o _idee buna_, vizualizarea de surse facute de alta lume ajuta foarte mult!\r\nAvand in vedere volumul foarte mare de probleme din arhiva (peste $600$) cat si punctajul mediu al utilizatorilor infoarena (vezi \'clasament\':clasament-arhiva), este clar ca o mare parte din probleme nu contribuie foarte mult la scopul site-ului, acela de a oferi o pregatire de performanta la informatica. In aceasta situatie, consider ca putem experimenta cu diverse sisteme de publicare a surselor folosind un subset din probleme din arhiva, fara a pierde practic nimic din valoarea arhivei. Un astfel de experiment are avantajul enorm ca vom avea feedback real despre ce efecte are publicarea surselor, nu vom mai ramane doar la stadiu de dat cu parerea.\r\nAsadar, acest document isi propune momentan sa prezinte diverse variante prin care putem face publice o parte din surse, urmand sa se contureze un sistem complet in urma feedback-ului primit.\r\n\r\nh2(#dezavantaje). Dezavantaje \r\n\r\nIn numeroasele discutii care au mai avut loc despre acest subiect, s-au enumerat diverse dezavantaje ale acestui sistem cum ar fi:\r\n\r\n* oamenii or sa triseze\r\n* clasamentul nu mai este relativ\r\n* etc. etc.\r\n\r\nSuntem foarte constienti ca exista diverse dezavantaje ale unui astfel sistem, dar eu cred ca avantajele depasesc cu mult orice dezavantaj! Asadar, cand citit acest documenti tineti minte ca este mult mai important sa incercam sa facem ceva si sa vedem cum merge, decat sa nu facem nimic din cauza ca se poate intampla cine stie ce.\r\n\r\nh2(#detalii). Detalii\r\n\r\n* Problemele la care vom face publice sursele vor fi din \'Arhiva de probleme\':arhiva si nu vor fi o arhiva separata. \r\n* In jur de $50$ probleme ar trebui sa fie de ajuns pentru un prim experiment.  Vom lua din problemele la care exista solutiile descrise in articole.\r\n* Problemele la care sunt publice sursele vor fi marcate clar, atat in lista de probleme, cat si in momentul in care citesti o problema.\r\n* Nu va exista posibilitatea de a alege sa nu ti se publice sursele. infoarena este o comunitate in care lumea vrea sa invete, cine nu vrea sa aiba sursele publice sa nu lucreze pe infoarena. \r\n* In momentul cand vezi o sursa, vei avea un link de _raportat_ sursa, in cazul in care crezi ca utilizatorul la care te uiti a copiat sursa sau a obfuscat-o. Ca si pe forum, odata ce dai click poti sa scrii un mesaj care va ajunge la admini; acestia vor investiga situatia si vor lua masurile necesare. Copierea sau obfuscarea codului vor fi pedepsite public de catre echipa infoarena. :)\r\n* Vei putea vedea sursele la o problema cu surse publice oricand, nu trebuie sa fii logat.\r\n\r\nh3(#bonus). Bonus\r\n\r\n* Ar fi cool sa poti da note la surse si sa existe posibilitatea de a comenta asupra lor\r\n* Modul de statistici care sa scoata in evidenta sursele cele mai bune ca rating / timp de executie / lungime.  Acesta e elementul de competitie care ii poate motiva pe cei mai buni sa trimita surse la probleme open source.\r\n\r\nh2(#implementare). Implementare\r\n\r\nVoi completa detaliile de implementare in momentul in care vom stabili exact formatul sistemului.\r\n\r\nh2(#feedback). Feedback\r\n\r\nIntra pe \'forum\':forum/index.php?topic=2458.0 pentru a da feedback.\r\n\r\n==SmfTopic(topic_id=\"2458\")==\r\n\r\n',2044,'public',NULL,NULL),('utilizator/123456789','Profil 123456789','2007-12-09 14:20:28','2007-12-09 14:20:28','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',7320,'public',NULL,NULL),('blog/olimpicul-de-la-facebook','Olimpicul de la Facebook','2007-12-10 18:25:08','2008-11-15 13:41:14','In filmul despre \'Here comes another bubble\':blog/bubblebubble ce l-am pus recent pe blog, am vazut o fata cunoscuta de pe topcoder. E vorba de \"Adam D\'Angelo\":http://www.topcoder.com/tc?module=MemberProfile&cr=260987 , el este acum \'Chief Technical Officer\':http://en.wikipedia.org/wiki/Chief_technical_officer al Facebook (reteaua sociala hot a momentului). I-am gasit destul de repede profilul pe linkdedin.com care arata cam asa:\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/olimpicul-de-la-facebook?adam.jpg!*Facebook:*\r\nBuilt the initial ad serving infrastructure, optimized product code and databases for scalability as traffic increased, built the logging infrastructure for feed, and analyzed data. Created an rpc layer that led to increased development speed, easier maintainability, and language independence for most new services we later developed. Set up the engineering hiring process.\r\n\r\n*Honors and awards:*\r\nFinalist, Topcoder Collegiate Challenge, 2005\r\n2nd in North America (team of 3), ACM International Computer Programming Contest, 2004\r\n1st in North America (team of 3), ACM International Computer Programming Contest, 2003\r\nSilver Medal, International Olympiad in Informatics, 2002\r\n\r\nIl consider pe Adam un exemplu pentru cei care spun ca algoritmica/olimpiadele nu au importanta in programare. Probabil ca nu au importanta cand faci o aplicatie simpla de baze de date, dar cand apar sisteme mari si nevoia de eficienta, cativa olimpici pot fi foarte utili. (Prin olimpici eu inteleg elevi sau studenti care au avut rezultate la un concurs international, nu unii care au fost la olimpiada pe scoala sau pe judet.)\r\n\r\nMi s-a parut interesant ca pagina lor de joburi contine puzzleuri ce imi aduc aminte de problemele de la concursurile topcoder. Probabil e mana lui Adam acolo :).\r\n\r\n',1490,'protected',2463,NULL),('blog/despre-olimpici','Vivi despre olimpici','2007-12-11 18:32:44','2008-11-15 13:41:14','\'Vivi\':vivi.ro a scris pe blogul lui un post misto despre utilitatea olimpicilor intr-o firma de programare. Il gasiti \'aici\':http://www.vivi.ro/blog/?p=488 .\r\n\r\nE interesant atat postul cat si comentariile legate de el. Voi ce parere aveti?\r\n\r\n',1490,'protected',2466,NULL),('newsletter/preoni-2008/runda-2','preONI 2008, Runda 2 - acum si pentru gimnaziu!','2007-12-13 17:10:32','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nParticipa si tu la Runda #2 a concursului preONI!\r\n\npreONI este concursul cu premii mari si finala live care te\r\npregateste pentru Olimpiada Nationala de Informatica.\r\n\nElevii de gimnaziu participa la o grupa de varsta separata si au\r\nlocuri rezervate la runda finala.\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Runda #2 se desfasoara...\r\n\np{padding-left: 2em;}. Duminica, 16 decembrie 2007, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nVezi pagina concursului: \'preoni-2008\':preoni-2008\r\n\nh2.  Atentie! Concurs cu rating! \n\nDaca vrei sa ti se modifice rating-ul in urma participarii la aceasta\r\nrunda trebuie sa iti anunti participarea din timp.  Intra pe\r\n\'preoni-2008\':preoni-2008 si inscrie-te la Runda #2.\r\n\nPoti sa participi la concurs chiar si daca nu te-ai inscris in\r\nprealabil insa nu ti se va modifica rating-ul.\r\n==NewsletterRating(username=\"%username%\")==\r\n\nCiteste despre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Noutati \n\nAparent s-a stabilit cand se desfasoara olimpiadele de informatica\r\npentru anul 2008.\r\n\nGimnaziu, Olimpiada de Informatica\r\n\np{padding-left: 2em;}. Etapa judeteana: 26 ianuarie 2008\r\n    Etapa nationala: 5 - 9 februarie 2008, Bacau\r\n\nLiceu, Olimpiada de Informatica\r\n\np{padding-left: 2em;}. Etapa judeteana: 15 martie 2008\r\n    Etapa nationala: 29 aprilie - 5 mai 2008, Prahova\r\n\nSursa:\r\n\'http://forum.portal.edu.ro/index.php?showtopic=81412\':http://forum.portal.edu.ro/index.php?showtopic=81412\r\n\nh2.  Concursul preONI \n\npreONI, concursul de marca al comunitatii infoarena, este dedicat\r\nelevilor de liceu si gimnaziu ce se pregatesc pentru Olimpiada\r\nNationala de Informatica.\r\n\nConcursul este impartit in 4 grupe de varsta:  clasele V-VIII, clasa\r\na IX-a, clasa a X-a si clasele XI-XII.  Se organizeaza 4 runde online\r\nde calificare.  In urma acestora, cei mai buni de la fiecare grupa\r\nsunt invitati la o runda finala.\r\n\nIn cadrul unei runde vei avea de rezolvat 3 probleme in 4 ore.\r\nProblemele sunt de natura algoritmica si de dificultate similara\r\ncelor de la ONI.\r\n\nOferim premii substantiale acelor concurenti care se claseaza pe\r\nprimele locuri la runda finala.\r\n\nEditia 2008 a concursului preONI se desfasoara sub atenta\r\nsupraveghere a lui Mircea Pasoi, in calitate de director de concurs.\r\n\nPe pagina oficiala ( \'preoni-2008\':preoni-2008 ) vei gasi\r\ninformatii despre cum participi, cine propune probleme, premii,\r\nregulamentul concursului samd.\r\n\npreONI 2008 este organizat in parteneriat cu Adobe Romania si\r\nsprijinit de catre iRealSoft.\r\n\nh2.  Runda #1 \n\nS-a desfasurat pe 25 noiembrie.\r\n\nPoti vedea rezultatele aici: \r\n\'preoni-2008/clasament/runda-1/11-12\':preoni-2008/clasament/runda-1/11-12\r\n\niar solutiile oficiale aici:\r\n\'preoni-2008/runda-1/solutii\':preoni-2008/runda-1/solutii\r\n\nTe asteptam la Runda #2!\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nRamai alaturi de noi.  Te ajutam sa devii olimpic!\r\nEchipa infoarena iti ureaza succes!\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n\n',13,'protected',NULL,NULL),('planificare/sedinta-20071128','Sedinta 2007-11-28','2007-11-24 18:58:30','2007-12-18 00:38:56','h1. Sedinta 2007-11-28\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Locatie si ora\':planificare/sedinta-20071128#locatie\r\n* \'Participanti\':planificare/sedinta-20071128#participanti\r\n* \'Agenda\':planificare/sedinta-20071128#agenda\r\n* \'Rezolutii\':planificare/sedinta-20071128#rezolutii\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *miercuri* la ora *18:00* la \'*&raquo; Hostway Romania*\':http://hostway.ro\r\n\r\n*Update*: Pentru cine nu stie ajunga, putem sa ne intalnim la *17:45* la statia de metrou *Nicolae Grigorescu*.\r\n\r\nh3. Locatie\r\n\r\nStr. Theodor Pallady, nr. 26, Sector 3, Bucuresti - intersectia cu Str. Mizil, in spatele Liceului de Chimie.  \'*&raquo; Click pentru harta*\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-11381&-9511\r\n\r\nUn mod de a ajunge acolo este sa coborati din metrou la statia Nicolae Grigorescu si sa luati orice tramvai in directia corecta (adica opusa Dristor) pentru 3 statii.  In statia in care trebuie sa coborati veti vedea Liceul de Chimie.\r\n\r\nh3. Despre locatie\r\n\r\nVom tine sedinta intr-o sala de conferinte a companiei HOSTWAY. Avem la dispozitie sala, whiteboard, proiector, internet si bauturi specifice lucrului la birou :)\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"mugurelionut\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== --> sustin ideea de a ne intalni la metrou\r\n* ==user(user=\"fluffy\" type=\"tiny\")== --> Probabil intarzii, e dezastru locatia\r\n* ==user(user=\"greco\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioara\':planificare/sedinta-20071107\r\n* Stabilit locuri de intalnire pentru sedintele viitoare\r\n* Discutie cu Mugurel\r\n* Feedback preONI 2008 Runda 1\r\n* Update Adobe?\r\n* Topic-uri pentur IAP-uri? Eventual poll admin-only pentru vot.\r\n* Votat \'IAP #0\':propuneri/0-sistemul-iap, \'IAP #1\':propuneri/1-hackaton, \'IAP #2\':propuneri/2-concurs-studenti, \'IAP #3\':propuneri/3-infoarena3\r\n* Upgrade forum\r\n* Cleanup svn & hackers\r\n* \'IAP #4\':propuneri/4-forum\r\n* Reorganizare navigare/sitemap (IAP #5?). E oarecum confuz.\r\n* almanah\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Cristi face check-in la macro-ul de blog comments ({%{color:red}done%}) si Mircea relationeaza topic-uri cu post-uri ({%{color:red}done%})\r\n* IAP #0 s-a votat\r\n* Cristi se uita la preview bug ({%{color:red}fixed%})\r\n* Mircea rezolva layout-ul pe 1024xY ({%{color:red}done%})\r\n* In newsletter-ul pentru runda #2, Cristi va explica despre sistemul de inscriere ({%{color:red}done%})\r\n* Luni avem intalnire cu Adobe:  Cristi, Silviu, Mircea ({%{color:red}done%})\r\n** Merg laptop-urile daca avem bani de concurs\r\n* Cristi face cont la PayPal\r\n* Cristi scrie IAP despre almanah\r\n* Silviu vorbeste cu Skipy despre articole, eventual stabileste o intalnire scurta cu el ({%{color:red}done%})\r\n* Adi face topic-uri de votat IAP-uri, dar fara poll-uri ({%{color:red}done%})\r\n* Leo scrie IAP despre restructurat sistemul de navigatie\r\n* Leo face upgrade la forum ({%{color:red}done%})\r\n* Leo face clean-up la SVN ({%{color:red}done%})\r\n\r\nh2. Notite\r\n\r\n* sistem de pregatire pentru incepatori\r\n** arhiva de probleme pentru incepatori\r\n** profiler\r\n** teste open\r\n** profesorii sunt direct interesati\r\n',1,'protected',NULL,NULL),('preoni-2008/clasament/runda-3/11-12','preONI 2008 - Clasament Runda 3, Clasele 11-12','2007-12-16 06:44:44','2008-01-13 18:38:35','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda3-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-3\r\n* \'Clasele 5-8\':preoni-2008/runda-3/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-3/10\r\n* \'Clasele 11-12\':preoni-2008/runda-3/11-12\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-3/5-8\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':preoni-2008/clasament/runda-3/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-3/10\r\n*(active) \'Clasele 11-12\':preoni-2008/clasament/runda-3/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda3-11-12\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('template/inscriere','template/inscriere','2007-01-21 02:27:03','2009-02-04 18:49:55','Trebuie sa te inscrii doar daca vrei sa ti se modifice rating-ul in urma participarii la aceasta runda. Daca odata inscris nu mai poti participa, te poti deinscrie.\r\n\r\nPoti participa la concurs chiar si daca nu te-ai inscris in prealabil.\r\n\r\n*Atentie!* Odata inscris, \'rating-ul\':documentatie/rating tau va fi afectat, chiar si daca nu vei trimite solutii!\r\n\r\n\'*Vezi cine s-a inscris*\':lista-inregistrare/%round%',1490,'protected',NULL,NULL),('blog/interviu-octavian-costache-partea-intai','Interviu cu Octavian Costache - partea intai','2007-12-13 22:13:40','2008-11-15 13:41:14','!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/interviu-octavian-costache-partea-intai?vivi2.jpg 50%! _Daca dai un Google search dupa romani ce lucreaza la Google probabil o sa il gasesti pe Octavian Costache, cunoscut de prieteni si de cei de prin blogosfera romaneasca ca Vivi. Prima data cand am vorbit cu el a fost parca in 2005 dupa un ONI by Net cand eram foarte curios de rezultate, si apoi l-am mai intalnit cand era in vizita la \'GooglePlex\':http://maps.google.com/maps?f=q&hl=en&geocode=&time=&date=&ttype=&q=the+googleplex&sll=37.407255,-122.044373&sspn=0.67087,1.433716&ie=UTF8&ll=37.421861,-122.084713&spn=0.00262,0.0056&t=h&z=18&om=1. Apropo de asta e interesant cum atat de multi olimpici internationali au ajuns sa lucreze la google, pe langa lista de angajati full time de \'aici\':olimpici , cel putin alti 8-9 olimpici au facut internshipuri pe vara. Vivi are un \'CV\':http://www.vivi.ro/_cv.html variat si cu realizari cum ar fi premii la olimpiadele de informatica, premii la concursul internetics de webdesign, premiant si apoi participant in comisie la concursul infoeducatie, realizarea impreuna cu Irina Dumitrascu a siteului \'doizece.ro\':http://doizece.ro , cel mai mare site de jocuri online din Romania, pe care l-a vandut inainte de a se angaja la google companiei neogen, are un blog ce e intre primele 50 de bloguri din Romania, a fost asistent la cursuri de algoritmica si instructor la cursuri Cisco. Tot Vivi a initiat \'ONI by Net\':http://olimpiada.info/bynet/ , partea online a olimpiadei natinale de informatica. Astfel am fost sigur ca un interviu cu el ar fi foarte interesant. Acum postez doar prima parte a interviului._\r\n\r\n*Cum ai inceput cu informatica?*\r\nIn clasa a 5-a am vazut primul PC XT la mama la serviciu. Pe vremea aia doar ma jucam, ne-am cumparat un HC90 pe care incarcam jocuri de pe caseta. Probabil primul meu program a fost un program in Basic cu care puteam sa desenez. Am desenat o masina si am salvat-o pe o caseta. :-) In clasa a 7-a am inceput sa fac informatica la scoala si mi-am dat seama ca sunt bun la rezolvat probleme si algoritmi. Intr-a 9-a am dat la clasa de informatica pentru ca era considerata cea mai buna clasa din liceu. Am inceput sa merg la olimpiade si cam de aici a inceput totul.\r\n\r\n*Scriai in pagina personala ca ai fost si la concursuri la fizica cand erai tanar? De ce nu ai continuat pe calea respectiva?*\r\nLa fizica era prea multa teorie de studiat iar eu sunt lenes din fire. Concursurile de informatica aveau mai putine teoreme si teorii in spate. In timp ce la fizica provocarea era sa faci conexiuni intre teorii si demonstratii si trebuia sa memorezi multa informatie, la informatica provocarile erau mult mai aproape de rezolvarea pura de probleme unde nu este nevoie de un fond teoretic atat de mare. La informatica puteai rezolva probleme si fara sa le demonstrezi sau fara sa ai fondul teoretic, deci puteam sa fiu mai lenes pe partea de pregatire. :-)\r\n\r\n*Ce ti-a ramas din viata competitionala?*\r\nAlgoritmii. Fundatia mult prea solida de structuri de date si algoritmi este, cred eu, lucrul care pana acum mi-a folosit cel mai mult. Inclinatia catre rezolvare de probleme si modalitatea de a le aborda, deprinse dupa ani buni de competitie, au devenit, cred eu, parte din personalitatea mea datorita olimpiadelor si acum imi influenteaza viata (mai ales cea profesionala).\r\n\r\nPrietenii pe care mi i-am facut la concursuri sunt un alt lucru care mi-a ramas, atat dintre elevi cat si dintre profesori. Cu multi dintre ei m-am intalnit over and over again, i-am intalnit in facultate, i-am intalnit la Google si probabil ne vom mai intalni pe unde o sa ne mai ducem.\r\n\r\n*Mai tii minte vreo problema frumoasa?*\r\nProbabil cea mai placuta amintire este o problema de la ONI in clasa a 9-a pentru ca am fost singurul care am rezolvat-o corect. :-) Nu mai tin minte problema exacta, era ceva despre oameni catre trebuiau grupati in niste lifturi.\r\n\r\n*Ai avut pe parcursul vietii oameni de la care ai invatat mult sau consideri ca ai invatat totul singur?*\r\nOamenii de la care am invatat au fost foarte importanti. Nu neaparat pentru ceea ce stiau, ci pentru ca mi-au folosit drept modele, motivandu-ma sa fiu mai bun, sa fac mai mult, sa vreau sa invat si sa vreau sa ma autodepasesc. Cea mai puternica motivatie, pentru mine, este atunci cand admir pe cineva si vreau sa fiu si eu ca respectivul.\r\n\r\nNu au fost foarte multi, poate trei sau patru oameni pe care i-am admirat din anumite puncte de vedere, insa pentru mine au fost foarte importanti.\r\n\r\n*Cum ai inceput cu crearea de siteuri?*\r\nIntr-o tabara la Galaciuc Marius Deak a tinut un curs de HTML unde am facut primul \'site\' cu Netscape 2.0, Notpad si Photoshop 3.5. :-) Apoi daca tot stiam HTML, am facut site-ul Divertis. Fratele meu era fan si voia neaparat sa ajunga sa vorbeasca cu cei din grup. M-a convins si pe mine ca a le face un site oficial pe degeaba este o modalitate buna de a ajunge sa ii cunoastem si pentru mine un lucru bun in a imi exersa noul dobandit skill de a face pagini web.\r\n\r\nIntamplator a iesit bine, a ajutat foarte mult si renumele Divertis, iar cu nou castigata incredere am descoperit ca pot face niste bani de buzunar din chestia asta asa ca am continuat sa fiu freelancer.\r\n\r\nApoi pentru o vreme, cel putin parte din motivatia de a face noi site-uri era si nevoia de a avea un proiect cu care sa merg la Galaciuc si sa (incerc sa) castig ceva. Ma amuz uneori cand ma gandesc ce motive copilaresti m-au indemnat sa fac lucruri care mai apoi au avut o influenta fundamentala in viata mea.\r\n\r\n*La infoeducatie ai fost atat participant cat si in comisie, cum se compara cele doua roluri?*\r\nSunt satisfactii in ambele. Ca participant este adrenalina concursului, dorinta de a castiga, dorinta de a dovedi ca tu esti cel mai bun si evident satisfactia atunci cand castigi. :-) Ca si membru al juriului sau al comisiei satisfactiile sunt mai putin intense dar intr-un fel mai... mature. Ai ocazia sa influentezi felul in care se intampla unele lucruri, sa le faci mai bine, sa ai grija ca toate lucruri sa mearga cum trebuie. Ai satisfactia de a insemna ceva pentru participanti, fie ca ei sunt constienti de asta sau nu.\r\n\r\nCred ca fiecare rol isi are varsta lui. Ca adolescenti ne dorim sa dovedim, sa aratam lumii ce putem si ce stim. Dupa ce dovedim (mai ales noua insine) de ce suntem in stare vine momentul in care ne dorim sa ne lasam amprenta asupra lumii, sa influentam vieti si schimbam lumea, nu doar pe noi insine. Nevoia de a dovedi ceva se schimba intr-o nevoie de a face bine umanitatii.\r\n\r\n*Ce proiecte pe care le-ai vazut la infoeducatie ti-au ramas in minte?*\r\nIronic, multele proiecte facute pentru lectii la Istorie si la fel de multele \'site-uri ale liceului\'. Ambele scopuri nobile care aproape niciodata nu au fost facute pentru elevi ci intotdeauna pentru a lua o nota la Istorie sau la Informatica. Fiecare dintre ele ar fi putut probabil fi site-uri excelente care sa castige premii daca ar fi stiut sa fie mai putin stereotipice si daca ar fi fost facute pentru a fi utile, nu pentru note.\r\n\r\n*Cate au continuat sa existe si sa fie de succes dupa concurs?*\r\nVrei sa laud InfoArena, sau de ce ma intrebi asta? :-) Cred ca au existat cateva: divertis, e-scoala, todom.ro, site-urile liceelor de care vorbeam la intrebarea anterioara. Nu am urmarit istoria recenta a concursului, probabil ar fi o statistica interesanta de realizat.\r\n\r\n*Cum se compara concursuri ca Infoeducatie cu Olimpiadele de Informatica?*\r\nCred ca au scopuri foarte diferite si cel mai probabil se complementeaza. Olimpiadele ofera o motivatie pentru pregatirea teoretica, structuri de date si algoritmi absolut necesare unui programator bun. Infoeducatia ofera pregatirea practica, motiveaza spiritul antreprenorial din fiecare dintre noi, dorinta de a face si realiza un proiect al nostru. Daca vrei, olimpiada de informatica te moviteaza sa inveti CUM sa faci, in timp ce Infoeducatia te motiveaza sa inveti CE sa faci.\r\n\r\n*Care sunt caracteristicile unui website reusit?*\r\nConsiderand ca nu te referi la site-urile de prezentare sau la cele experimentale, as spune ca un website reusit este un site care acopera cel mai bine o anumita nevoie a utilizatorilor sai. Felul in care este facut, culorile, realizarea tehnica, grafica, tehnologia din spate, sunt importante doar ca si mijloace pentru a atinge singurul si cel mai important scop: de a fi cea mai buna unealta in mana utilizatorului caruia i se adreseaza.\r\n\r\nSuna un pic abstract, dar tot ce vreau sa spun este: atunci cand faceti un site, judecati-l din punct de vedere pragmatic si utilitar.\r\n\r\n*Ce l-ai sfatui pe cineva care vrea sa se apuce de creearea de siteuri web ca metoda de abordare generala, tehnologii, tooluri, concepte de design samd?*\r\nVezi intrebarea anterioara. :-) Toate cele pe care le insiri tu conteaza doar in contextul in care servesc cel mai bine utilizatorul. Tehnologia este importanta doar pentru a fi sigur ca site-ul tau scaleaza si functioneaza corect. Tool-urile sunt importante doar in contextul in care te ajuta sa faci lucrurile mai repede. Conceptele de design doar in contextul in care stiu sa transmita mesajul in cel mai usor mod cu putinta. Insa in the end, ele sunt doar mijloacele si nici una din ele nu te va ajuta sa transformi intr-un succes un site care nu este facut pentru utilizatori.\r\n\r\nEste ca si cum m-ai intreba ce masina este cea mai potrivita pentru a ajunge undeva. Daca iti este clar unde vrei sa ajungi si cat de repede, poti sa iti alegi masina cea mai potrivita pentru asta. Insa degeaba ai o super masina daca nu ai o destinatie si un scop. O sa poti sa te plimbi cu ea prin cartier sa te dai mare ca stii Ruby on Rails, dar dupa doua ture o sa o bagi in garaj si o sa te intorci de unde ai plecat.\r\n\r\nDe exemplu, doizece.ro era facut cu php+mysql in partea web a site-ului, flash pentru jocuri si java pentru serverul din spate. Puteam la fel de bine sa fie facut in ruby on rails pentru partea web si in C++ pentru server, insa am ales tehnologiile astea pentru ca eram confortabili cu ele, erau usor de folosit si faceau lucrurile de care noi aveam nevoie. Desi am folosit php in aproape toate site-urile pe care le-am facut in Romania nici pana acum nu stiu php decat la un nivel intermediar pentru ca asta era tot ce aveam nevoie.\r\n\r\nDeci, ca sa iti raspund totusi la intrebare, invatati ce va este cel mai usor pentru a putea realiza ceva. Php, mySql, Java sunt exemple excelente. Nu uitati insa ca sunt doar tool-uri si nu le acordati importanta decat in masura in care merita. Razboaiele despre care limbaj este cel mai tare sunt de cele mai multe ori inutile.\r\n\r\n*Povesteste-ne despre un proiect de-al tau ce ti-a placut in mod deosebit in afara de doizece.ro :).*\r\nDidactic.ro este un proiect mai putin \'cool\' dar care a schimbat foarte mult viata profesorilor ajutandu-i sa comunice si sa impartaseasca teste, lectii, reviste scolare si mult alt continut generat de utilizatori. Timp de doi ani l-am dezvoltat impreuna cu Emil Onea si s-a impus recent ca unul din cele mai vizitate site-uri dedicate educatiei din Romania (\'http://www.trafic.ro/top/educatie-invatamant/\':http://www.trafic.ro/top/educatie-invatamant/), in contextul in care celelalte site-uri populare sunt in principal site-uri de referate. Cred ca putini oameni stiu ca eu am fost singurul dezvoltator al site-ului asta inainte sa plec din Romania si ca acum este in mare parte neschimbat.\r\n\r\nPovestea cu el este interesanta pentru ca este un site pe care l-am dezvoltat pentru Softwin desi ma plateau pentru asta mai putin decat credeam eu ca merit. Cu toate astea l-am facut pentru ca voiam sa fac ceva interesant, credeam in idee, stiam ca trebuie facut si am zis ca mai bine lucrez la ceva si sunt platit mai putin decat sa stau degeaba (si sa nu castig nimic :-) ).\r\n\r\n*Povesteste-ne despre OniByNet.*\r\nIn 2000 am facut, pentru prima data la noi, CEOI by NET. Cred ca am ajuns sa il fac eu pentru ca ma ocupam in general de site-ul editiei respective. Cand mi-am dat seama ca se poate, am inceput sa il bat la cap pe Emil sa convinga comisia ca un astfel de concurs pentru ONI poate fi foarte important pentru cei care raman acasa, pentru pregatirea lor, pentru a nu isi pierde exercitiul.\r\n\r\nAm insistat mult si am reusit, la inceput destul de timid. In timp am insistat sa facem ONIbyNET din ce in ce mai important si am reusit ca in cativa ani sa aducem castigatorii la baraj cu drepturi egale cu cei de la olimpiada normala. Pentru mine este un fel de victorie personala, dovada ca am schimbat un sistem si ca datorita mie acum viata catorva sute de elevi pasionati este schimbata, chiar si daca foarte putin, in bine.\r\n\r\n_Partea a doua a interviului va aparea in curand._\r\n\r\n',1490,'protected',2472,NULL),('blog/interviu-octavian-costache-partea-a-doua','Interviu cu Octavian Costache - partea a doua','2007-12-16 07:24:09','2008-11-15 13:41:14','!{margin: 10px; margin-left: 0; border: 1px solid gray;}blog/interviu-octavian-costache-partea-a-doua?vivi1.jpg 70%!\r\n\r\n(in poza de la stanga la dreapta: The Beatles, ah pardon \'Mars\':http://campion.edu.ro/team.php?id=6 , \'Vivi\':http://vivi.ro/blog , \'Cristi\':utilizator/wickedman si \'Cosmin\':utilizator/cosmin in septembrie in San Francisco)\r\n\r\n_Continuam cu a doua parte a interviului interesant cu Octavian Costache. Puteti citi prima parte \'aici\':blog/interviu-octavian-costache-partea-intai . In aceasta parte el ne spune despre facultate, viata de freelancing, despre blogging, despre Google si alte lucruri interesante. Cititi si cel mai important, comentati interviul._\r\n\r\n*Ai facut facultatea in Romania, si mai tarziu ai plecat la Google in New York. Nu te-ai gandit la sfarsitul liceului sa pleci din tara la o universitate in strainatate?*\r\nAm avut si gandul asta, ba chiar am dat si Toefl-ul. Cred ca am fost insa prea lenes pentru a incerca cu adevarat, probabil nici nu am fost motivat suficient, sa fac facultatea in afara nu era un vis sau un scop al meu. Un alt motiv care m-a facut sa nu aplic a fost neincrederea pe care o aveam in sansele de reusita pentru ca la olimpiade nu am avut rezultate stralucite (doar niste premii la nationala).\r\n\r\n*De ce ai ales ca facultate sectia Calculatoare, Politehnica Bucuresti?*\r\nEra singura facultate despre care stiam ca \'e buna pentru calculatoristi\'. Cealalta varianta era sectia de informatica de la Universitate, dar acolo se auzea ca profesorii nu sunt la fel de buni, nu avea la fel de multa traditie si ca se facea multa mate (care mie nu imi place deloc).\r\n\r\n*Ce cursuri ti-au placut in facultate si de ce, si care nu ti-au placut?*\r\nAs putea scrie un intreg eseu despre toate cursurile din facultate. :-) Mi-au placut cursurile din anii mai mari, cred ca cele mai multe au fost bine facute. Cele de sisteme de operare (thread-uri, low level stuff), retele, algoritmi. Au fost si cateva cursuri mai exotice care mi-au placut (programare functionala). Din motive pur subiective probabil cel mai mult mi-a placut cursul de sisteme multi agent, a fost un domeniu care m-a atras pentru ca mi se pare cool sa faci roboti si programe autonome. E ca si cum ti-ai construi o jucarie pe care apoi o poti studia cum merge si cum evolueaza de capul ei. Si chiar asta am ajuns sa facem cand am facut niste programe care se jucau pe doizece de capul lor, isi alegeau partenerii, incercau sa faca conversatie, sa fie inteligente. A fost foarte distractiv. Nu vreau sa imi aduc aminte de cele care nu mi-au placut, probabil primii doi ani cu totul.\r\n\r\n*Ai fost instructor si preparator la mai multe cursuri. Cum e experienta de a fi profesor, care erau partile frumoase si cele dificile?*\r\nE mai dificil decat pare sa iti pregatesti un laborator si sa ai incredere ca nu te vei face de ras in fata unui grup de studenti, cel putin prima oara cand faci laboratorul respectiv. E greu sa fii laborant bun, e greu sa admiti cand nu stii si sa fii deschis la tot felul de oameni si tot felul de intrebari. Cel mai mult mi-a placut faptul ca puteam sa trezesc entuziasmul in studenti la materia pe care o faceam. Eu cred ca orice subiect are o parte interesanta care il face fascinant si util si principala satisfactie (si responsabilitate) a unui preparator este sa reuseasca sa arate aceasta parte interesanta studentilor si sa ii faca sa inteleaga de ce ceea ce invata e cool.\r\n\r\n*Ai recomanda unui student sa faca cursurile Cisco?*\r\nDa, primul modul este de basic networking si sunt acolo lucruri generale care te ajuta sa intelegi cum functioneaza retelele si internetul. Cred ca este un modul extrem de util pentru cultura ta generala de dezvoltator software. Celelalte module sunt utile doar pentru cei care vor sa faca din asta o cariera.\r\n\r\n*Am vazut in CV ca ti-ai facut lucrarea de diploma din Inteligenta Arfiticiala. Cum se imbina algoritmica si inteligenta artificiala cu web designul?*\r\nWell, se imbina foarte indirect. Revin la exemplul cu programele noastre care se jucau pe doizece de capul lor. Pentru ca stiam sa dezvoltam site-uri web am facut doizece si a avut succes, pentru ca stiam algoritmica am stiut sa scalam doizece pentru a putea sa reziste in fata succesului pe care l-a avut, si pentru ca stiam inteligenta artificiala am putut sa facem niste agenti care sa ne ajute sa popularizam jocurile mai putin de succes si sa ne ajute sa facem diverse experimente.\r\n\r\nEste totusi doar un caz fericit, un exemplu ca se poate. As spune ca mult mai comuna este inrudirea dintre algoritmica si web development (design-ul intr-adevar nu se inrudeste cu asta) pentru ca trebuie sa intelegi web-ul pentru a dezvolta site-uri de succes si cel mai probabil te va ajuta foarte mult algoritmica atunci cand aceste site-uri vor avea succes. Inteligenta artificiala nu prea intra in ecuatie decat in cazuri extreme si rare, in situatii speciale si depinde foarte mult de problemele pe care incerci sa le rezolvi. De exemplu, daca vei vrea sa faci o interfata cool care intelege limbajul natural atunci vei avea nevoie de inteligenta artificiala.\r\n\r\n*Ai un blog cunoscut. In \'ze list\':http://zelist.ro apare in primele 50 de bloguri din Romania. De ce ti-ai facut blog?*\r\nEu cred ca am o viata interesanta care poate motiva si inspira pe altii. Credeam si inca mai cred ca am multe lucruri de spus, ca exista valoare in a impartasi experientele prin care trec eu si altora. Este probabil parte si din motivul pentru care am fost preparator, imi place sa inspir si sa motivez oameni, sa explic si sa educ, sa arat altora perspective noi asupra lumii la care ei poate nu s-au gandit. Asta a fost principalul motiv pentru care am inceput sa am blog, combinat cu ideea ca facand asta, inspirand, educand, provocand oamenii la a gandi mai mult, vor afla si ca exist, ca gandesc, ca sunt destept.\r\n\r\nCa un efect secundar de care mi-am dat seama ceva mai tarziu, blogul mi-a fost foarte folositor si pentru nevoia de comunicare de la inceputul venirii mele in America. Eram singur, fara prieteni si fara nici un cunoscut, intr-o tara straina. Blogul m-a ajutat, la inceput fara sa imi dau seama, sa am un loc unde sa comunic cu prietenii, sa le spun ce imi trecea prin cap, sa simt ca cineva ma asculta. Psihologic m-a ajutat foarte mult, chiar daca intentia initiala a fost alta.\r\n\r\n*De ce crezi ca are succes?*\r\nAs zice ca blogul meu are un succes moderat. Este citit de un public destul de restrans de oameni care ma cunosc sau oameni interesati de industria online. Cred ca succesul lui este dat de o combinatie intre pozitia din care emit pareri (pozitie care confera mai multa autoritate parerilor mele decat parerilor unui anonim), felul in care scriu (cu grija, coerent, clar, interesant) si continutul pe care il scriu (de multe ori analize coerente si argumentate, perspective interesante, sinteze sau opinii la care de obicei oamenii nu se gandesc). Este, evident, o parere foarte subiectiva. :-)\r\n\r\n*Cum ai convinge pe cineva sa isi faca blog?*\r\nNu as vrea sa conving pe nimeni care nu simte ca are ceva de spus sa isi faca blog. Cred ca un blog este ceva care trebuie sa iti faci doar atunci cand simti ca ai ce sa comunici, ca perspectivele tale aduc valoare asupra unor subiecte, ca ai ceva de comunicat (despre lume, despre ceea ce faci tu, despre ce se intampla in interiorul unei echipe, etc).\r\n\r\n*Ce tipuri de bloguri citesti?*\r\n1. Bloguri despre industria online din Romania. Citesc cam orice blog al persoanelor care au cat de cat legatura cu online-ul de la noi. Ma intereseaza sa aflu tot ceea ce se intampla, sa imi formez o idee despre atitudinea generala a celor are au blog despre diverse evenimente, sa aflu lucruri interesante.\r\n2. Foarte putine bloguri personale, pe care le citesc tot din motive personale.\r\n3. Un blog despre New York in care mai aflu despre concerte interesante, restaurante, teatre sau in general ce se mai intampla cool prin oras.\r\n\r\n*Ai niste bloguri preferate care se ocupa de programare?*\r\nNu.\r\n\r\n*Ai fost o bucata buna de vreme freelancer. Ce avantaje si dezavantaje are munca ca freelancer fata de cea a unui programator angajat la o firma?*\r\nCa freelancer ai libertate deplina. Poti sa fii propriul tau stapan, sa faci lucrurile cum vrei tu, cand vrei tu, in ce fel vrei tu. Este ceva romantic in asta din punctul meu de vedere, esti un fel de mercenar in afara sistemului, mereu lucrand dar mereu pe drumuri, gata oricand sa isi faca bagajele si sa se duca in alta parte si sa se apuce de altceva. Exista avantaje destul de clare fata de un job normal: nu trebuie sa te duci la servici, poti sa muncesti cand vrei tu, in general nu ai un sef care sa iti spuna ce sa faci. E drept, ti se spune ce sa faci pe fiecare proiect. Dar esti liber sa iti alegi ce proiecte sa faci, daca sa mai lucrezi cu cineva sau nu.\r\n\r\nCa angajat ai insa o echipa cu care sa lucrezi si care sa te ajute. Ai oameni la care sa te raportezi si sa iti dai seama cat de bun esti. Lucrezi la proiecte mai mari si cu impact mai mare, dispare adrenalina si eterna intrebare \"oare luna asta o sa am bani?\".\r\n\r\nDaca vrei, este diferenta intre a iesi cu tipe asa la intamplare si a avea o relatie serioasa cu o tipa. Exista avantaje si dezavantaje in amandoua. Cand ai o prietena stabila ai free sex la dispozitie, stabilitate, siguranta, daca va iubiti vedeti lumea impreuna, impartasiti bucuriile si tristetile. Cand esti single sex-ul este mai greu de gasit dar este mai divers si mai interesant, nu stii ce iti rezerva viitorul, esti liber sa te duci unde vrei cand vrei si sa faci absolut ce vrei. Amandoua au sens la anumite varste, amandoua situatiile au propriile lor avantaje si dezavantaje.\r\n\r\n*De ce Google si nu o alta firma sau propriul tau startup?*\r\nDupa ce am fost freelancer mi-am dat seama ca mi-ar fi absolut imposibil sa ma duc la un job normal. Am aplicat la Google intamplator, a fost singura firma la care am aplicat vreodata (nici macar nu aveam un CV redactat). Nu voiam un job, voiam sa vad daca as putea obtine unul, era doar un challenge pentru mine, mai mult in joaca.\r\n\r\nDupa ce am trecut de interviuri mi-am dat seama ca este o ocazie pe care nu pot sa o ratez, sa lucrez la Google in New York, o oferta pe care nu o puteam refuza. De la Google am avut mult de invatat, m-am maturizat enorm ca programator. Din faptul ca traiesc in New York mi-am deschis orizonturile, am cunoscut lumea si am vazut perspective pe care nu le stiam inainte, lucru care se intampla de fiecare data cand iesi din universul care iti este familiar si te duci intr-un loc cu totul nou.\r\n\r\nDe ce nu o alta firma? Nu voiam sa devin un pion lucrand la un proiect ascuns dintr-o companie imensa, nu e ceva care sa imi doresc sau care sa ma caracterizeze. Google este singura companie pe care o stiu unde intr-adevar poti face o diferenta, poti face lucruri vizibile si poti face ce vrei tu, cat timp ai energia sa vrei.\r\n\r\n*Ce lucruri importante ai invatat de cand lucrezi la Google?*\r\nProbabil cel mai important a fost contactul cu alti oameni destepti. Am invatat sa fiu mai matur si ceva mai analitic. Am invatat cateva principii pe care, desi cred ca le urmaream oarecum inainte mai mult instictual acum stiu si care sunt argumentele din spatele lor (the user comes first, speed matters, release early and often).\r\n\r\nCalitatea codului pe care il scriu a crescut. Desi in ultimii cinci ani (la google sunt doar de 2) am crezut cam in fiecare an ca mi-am atins maturitatea ca programator, in fiecare an mi-am dat seama ca am evoluat fata de anul trecut, ca scriu cod mai clar, mai curat, mai argumentat, ca stiu sa evaluez mai bine ce e usor de citit si de inteles, ce e bine sa fie facut si ce nu.\r\n\r\n*Ce iti place la viata din state?*\r\nO sa iti spun ce imi place la viata in New York, pentru ca eu acolo locuiesc si este un loc destul de diferit de restul Americii.\r\n\r\nImi place mult de tot orasul in sine. Imi place ca exista mii de restaurante, baruri, concerte, evenimente. Imi place ca atunci cand vrei poti sa gasesti cam orice dristactie la care te poti gandi. Imi place ca totul este extrem de comod de la cumparaturi si plati de facturi online pana la doing laundry.\r\n\r\nEste totusi un raspuns foarte personal si sper ca toti cei care citesc asta sa nu sara la concluzii stereotipice despre America. Trebuie sa iti dai seama ca astfel de raspunsuri variaza mult de la persoana la persoana si depind mult de contextul fiecaruia.\r\n\r\n*Crezi ca o sa te mai intorci in Romania?*\r\nEste o optiune la care ma gandesc uneori ca fiind o optiune posibila.\r\n\r\n*Ce pasiuni mai ai inafara de blogging si programare?*\r\nImi place sa zbor. Am facut parasutism si mai apoi parapanta si incerc sa zbor atunci cand pot. Mi-ar placea sa traiesc undeva unde sa pot face asta mai mult si mai usor dar pana acum nu a fost cazul.\r\n\r\nIn ultima vreme filmul. Am inceput sa vad multe filme si nu doar la cinema, sa urmaresc curente cinematografice si sa incerc sa inteleg mai bine regizorii, influentele lor, mesajele pe care vor sa le transmita. Am inceput sa privesc filmul ca pe o arta si sa incep, cred eu, sa o inteleg ceva mai bine din perspectiva asta.\r\n\r\nFotografia uneori. Imi place mult sa incerc sa spun povesti prin fotografie si sa incerc sa devin mai bun la a face asta.\r\n\r\n*Ce sfaturi ai da cuiva care e la inceput cu programarea?*\r\nStau de cinci minute sa ma gandesc ce sa raspund la intrebarea asta si sunt atat de multe perspective si puncte de vedere in care se pot da sfaturi incat imi este foarte greu sa raspund. Am incercat sa editez un raspuns de cateva ori dar mi-e foarte greu asa ca am renuntat.\r\n\r\nProbabil le-as spune sa se tina de programare si sa traga tare, traim intr-o vreme cand a venit randul programatorilor sa schimbe lumea in care traim. Suntem abia la inceputurile unei ere de glorie a tehnologiei si a comunicatiilor, internetul este doar la inceput si inca nu s-a maturizat, sunt vremuri entuziasmante si extrem de interesante pentru oricine care lucreaza in aceasta industrie si urmeaza vremuri si mai interesante. Este mai usor ca niciodata pentru grupuri din ce in ce mai mici de oameni sa inceapa sa schimbe lumea in feluri semnificative.\r\n\r\nDaca cineva are intrebari mai concrete, va rog, nu ezitati. :-)\r\n\r\n_Multumim Vivi._\r\n\r\n',1490,'protected',2485,NULL),('preoni-2008/runda-2/solutii/litere','preoni-2008/runda-2/solutii/litere','2007-12-16 15:05:52','2007-12-17 12:58:44','h2(#litere). \'Litere\':problema/litere\r\n\r\nProblema cere de fapt sa se calculeze numarul de inversiuni ale sirului. Numim inversiune o pereche $(i, j)$, cu $i < j$, iar $S[i] > S[j]$. Pentru a face acest lucru eficient, vom parcurge sirul, iar la fiecare pas vom numara cate litere mai mari decat litera curenta am intalnit pana acum. Putem sa ne mentinem un vector de frecvente ale literelor, complexitatea algoritmului fiind $O(N * Sigma)$, unde $Sigma = 26$ - marimea alfabetului.',2028,'public',NULL,NULL),('preoni-2008/runda-2/solutii/rays','preoni-2008/runda-2/solutii/rays','2007-12-16 15:10:00','2007-12-16 17:34:28','h2(#rays). \'Rays\':problema/rays\r\n\r\nPentru fiecare din cele $2$ semiplane determinate de axa Oy rezolvam problema si adunam in final rezultatele. Sa presupunem ca vrem sa aflam numarul minim de raze ce trebuiesc proiectate astfel incat sa distrugem toate segmentele verticale cu {$y > 0$}. Sortam dupa unghi capetele segmentelor verticale date. Astfel, fiecare segment va avea de fapt asociat un interval \"de unghiuri\". Daca anumite intervale \"de unghiuri\" se intersecteaza, atunci poate fi dusa o raza care sa elimine toate segmentele aferente acestor intervale.\r\nProblema se reduce la a determina numarul minim de puncte pentru un set de intervale dat astfel incat fiecare interval sa contina cel putin unul din punctele determinate. Aceasta problema se poate rezolva optim in {$O(N log N)$} folosind metoda greedy. Fiecare interval determina doua tipuri de evenimente: \"de intrare\" (capatul din stanga, mai mic) si \"de iesire\" (capatul din dreapta, mai mare). Sortam evenimentele pentru toate cele $N$ intervale si realizam o baleiere. In momentul in care ajungem la un punct de intrare, introducem intr-o coada intervalul asociat evenimentului. Atunci cand se intalneste un eveniment de iesire, se aduna $1$ la solutie si se goleste coada, fara a mai considera vreodata evenimentele ce apartin unor intervale deja eliminate.',256,'public',NULL,NULL),('preoni-2008/runda-2/solutii/hacker','preoni-2008/runda-2/solutii/hacker','2007-12-16 15:11:53','2008-02-06 22:30:04','h2(#hacker). \'Hacker\':problema/hacker\r\n\r\nh3. Pasul 1\r\n\r\nIn prima faza vom incerca sa rezolvam problema atunci cand sirul dat este format numai din $?$ (fie $Nr[N]$ numarul lor pentru o lungime $N$). Pentru asta avem nevoie de urmatoarea observatie:\r\n\r\n* Fie un sir de lungime $N$ in care exista un prefix egal cu un sufix; fie lungimea acestui prefix/sufix $L$. Daca $2L > N$ (prefixul si sufixul se intersecteaza) atunci exista si un prefix egal cu un sufix, de lungime $L\' < L$ pentru care $2L\' &le; N$ (nu se intersecteaza).\r\n\r\nAceasta observatie este destul de evidenta. Lasam demonstratia ei pe seama cititorilor. Vom numi in continuare un sir in care nu exista nici un prefix egal cu un sufix ca fiind bun. \r\n\r\n* Daca avem un sir care nu este bun de lungime impara ({$N=2k+1$}), putem elimina elementul din mijloc (de pe pozitia $k+1$) si obtinem un sir de lungime $N-1$ care in continuare nu va fi bun (datorita observatiei de mai sus). Treaba este valabila si invers. Putem lua orice sir bun de lungime $N-1$, inseram orice valoare intre $0$ si $K-1$ in mijloc si va fi in continuare bun. Astfel, $Nr[N] = K*Nr[N-1]$\r\n* Putem aplica in mare parte acelasi rationament si pentur sirurile de lungime para ({$N=2k$}). Inseram orice valoare pe pozitia $k$ intr-un sir bun de lungime $N-1$ pentru a obtine siruri de lungime $N$. Se observa ca in acest caz pot aparea si siruri care nu sunt bune, si anume cele in care exista un prefix de lungime $k = N/2$ egal cu un sufix. Este evident ca numarul lor este $Nr[N/2]$. Putem trage concluzia ca $Nr[N] = K*Nr[N-1] - Nr[N/2]$.\r\n\r\nh3. Pasul 2\r\n\r\nVom incerca acum sa rezolvam problema initiala plecand de la ce-am descoperit mai sus. Vom nota cu $count(S)$ numarul de siruri bune care se potrivesc cu $S$ ({$S$} este un sir de cifre si $?$).\r\n\r\n* Consideram un sir $S$ de lungime $N = 2k+1$. Putem elimina caracterul din mijloc, reducand problema la una de dimensiune mai mica. Daca caracterul eliminat a fost $?$ vom inmulti rezultatul cu $K$.\r\n\r\n==code(c)|daca S[N/2+1] = \'?\':\r\n  count(S) = K*count(S[1..N/2]+S[N/2+2..N])\r\naltfel:\r\n  count(S) = count(S[1..N/2]+S[N/2+2..N])\r\n==\r\n\r\n* Consideram acum un sir $S$ de lungime $N = 2k$. Ca si pentru cazul de lungime impara putem elimina caracterul din mijloc ca sa reducem la o problema de dimensiune mai mica. Desigur, in acest caz pot aparea si siruri care nu sunt bune, si anume cele in care exista un prefix de lungime $k = N/2$ egal cu un sufix. Putem determina numarul acestor siruri daca gasim un alt sir de lungime $N/2$ care sa se potriveasca cu ambele jumtati ale lui $S$. Vom nota cu $intersect(A, B)$ un sir care se potriveste si cu $A$ si cu $B$. De exemplu, $intersect(?0?1, ??11) = ?011$ sau $intersect(?0, ?1) = sir vid$. Astfel, va trebui sa scadem valorea lui $count()$ pentru intersectia celor doua jumatati ale lui $S$, reprezentand numarul sirurilor care nu sunt bune.\r\n\r\n==code(c)|daca S[N/2+1] = \'?\':\r\n  count(S) = K*count(S[1..N/2-1]+S[N/2+1..N]) - count(intersect(S[1..N/2], S[N/2+1..N]))\r\naltfel:\r\n  count(S) = count(S[1..N/2-1]+S[N/2+1..N]) - count(intersect(S[1..N/2], S[N/2+1..N]))\r\n==\r\n\r\n==code(c)|intersect(a, b):\r\n  rez = \"\"\r\n  pentru i = 1, |a|:\r\n    daca a[i] = \'?\':\r\n      rez += b[i]\r\n    altfel:\r\n      daca b[i] != \'?\' si b[i] != a[i] returneaza \"\" // nu exista intersectie\r\n      rez += a[i]\r\n  returneaza rez\r\n==\r\n\r\nRezolvarea prezentata mai sus se traduce imediat intr-o functie recursiva. Sa vedem cum ar functiona pe un exemplu:\r\n$count(0?1?1) = count(0??1)$\r\n$count(0??1) = K*count(0?1) - count(01)$ deoarece $intersect(0?, ?1) = 01$\r\n$count(0?1) = K*count(01)$\r\n$count(01) = 1$\r\n\r\nh3. Pasul 3\r\n\r\nDesi avem acum o modalitate de a rezolva problema este clar ca o implementare directa a functiei recursive duce la o complexitate exponentiala, care ar parea cam mare pentru $N = 200$. Sa vedem exact cate apeluri se fac pentru $count()$ in cel mai rau caz. Fie $C(N)$ numarul de apeluri recursive pentru un sir de lungime $N$, in cel mai rau caz.\r\n\r\n* $C(2*k+1) = C(2*k)+1$\r\n* $C(2*k) = C(2*k-1)+C(k)+1$\r\n\r\nO scurta evaluarea a acestei functii ne va arata ca pentru $N = 200$ valoarea $C(N)$ este in jur de $500.000$. Cum pentru fiecare apel $C(N)$ se fac $O(N)$ operatii (datorita manipularii sirurilor) putem estima ca algoritmul va face in jur de $100$ de milioane de operatii. Asadar, putem spera ca s-ar incadra in timp, si intr-adevar solutia oficiala este implementarea directa a functiei recursive prezentate mai sus. Se poate aplica memoizare pentru a mai optimiza solutia, dar nu era necesar. Chiar si memoizand, rezolvarea este tot exponentiala. Daca aveti cumva o solutie in timp polinomial pentru aceasta problema nu ezitati sa o scrieti pe forum, deoarece nici noi nu stim nici una.',1,'public',NULL,NULL),('preoni-2008/runda-2/solutii/nunta','preoni-2008/runda-2/solutii/nunta','2007-12-16 15:07:36','2007-12-16 16:56:31','h2(#nunta). \'Nunta\':problema/nunta\r\n\r\nFie {$F{~N~}$} numarul de moduri de a aseza la masa $N$ perechi. Se observa imediat ca {$F{~1~}$} = $1$ si {$F{~2~}$} = {$2$}. Pentru a calcula {$F{~N~}$} este necesar sa stim valorile elementelor {$F{~N-1~}$} si {$F{~N-2~}$}. Astfel, pentru o asezare oarecare a primelor $N-2$ cupluri, putem aseza cea de-a $N$-a si a $(N-1)$-a pereche ca in imagine:\r\n\r\n!preoni-2008/runda-2/solutii/nunta?1.bmp!\r\n\r\n\r\nIn acest caz, avem {$F{~N-2~}$} variante de asezare.\r\nPerechea a {$N$}-a poate fi asezata si in modul urmator:\r\n!preoni-2008/runda-2/solutii/nunta?2.bmp!\r\n\r\nIn acest caz, avem {$F{~N-1~}$} variante de asezare. Numarand astfel putem sti ca nu vom numara aceeasi asezare de mai multe ori. Obtinem relatia de recurenta: {$F{~N~}$} = {$F{~N-1~}$} + {$F{~N-2~}$}. Rezolvarea problemei se bazeaza deci pe afisarea celui de-al $(N+1)$-lea numar din \'sirul lui Fibonacci\':http://en.wikipedia.org/wiki/Fibonacci_number. Deoarece rezultatul nu se incadreaza in nici un tip de date conventional, trebuie implementata adunarea pe numere mari. De exemplu, al {$1000$}-lea numar Fibonacci are $209$ cifre. Operatiile cu numere mari sunt tratate in acest \'articol\':Multe-smenuri-de-programare-in-CC-si-nu-numai. Din considerente de memorie se vor retine la fiecare pas doar ultimele doua numere Fibonacci.',256,'public',NULL,NULL),('preoni-2008/runda-2/solutii/multiplu','preoni-2008/runda-2/solutii/multiplu','2007-12-16 15:09:21','2007-12-16 17:17:32','h2(#multiplu). \'Multiplu\':problema/multiplu\r\n\r\nO rezolvare triviala ar fi generarea (prin metoda \'backtracking\':http://en.wikipedia.org/wiki/Backtracking) in ordine crescatoare a tuturor numerelor formate doar din cifre de $0$ si $1$ si verificarea proprietatii de divizibilitate. In momentul in care am intalnit un numar care este multiplu si pentru $A$ si pentru $B$ afisam rezultatul si oprim executia programului.\r\nSolutia optima are complexitatea {$O(A*B)$}. Fie $M$ cel mai mic multiplu comun pentru numerele $A$ si $B$. Trebuie sa determinam cel mai mic numar natural format doar cu cifre de $0$ si $1$ si care este multiplu pentru {$M$}. Vom avea o coada in care vom introduce cele mai mici numere formate cu $0$ si $1$ care dau un anumit rest la impartirea cu $M$. Initial, in coada se va afla doar numarul $1$. La un moment dat, daca ne aflam pe pozitia $i$ in coada si pe aceasta pozitie se afla numarul $X$, tratam urmatoarele cazuri:\r\n\r\n* adaugam cifra $0$ la sfarsitul lui {$X$}. Daca nu exista nici un numar in coada care sa aiba restul {$(X*10) % M$}, atunci introducem $X*10$ in coada.\r\n* adaugam cifra $1$ la sfarsitul lui {$X$}. Daca nu exista nici un numar in coada care sa aiba restul {$(X*10+1) % M$}, atunci introducem $X*10+1$ in coada.\r\n\r\nIn momentul in care introducem in coada un numar care are restul $0$ la impartirea cu {$M$}, il afisam si oprim executia programului. Se observa ca in coada vor fi introduse cel mult $M$ numere, deoarece exista $M$ resturi posibile la impartirea cu {$M$}. Cum $M$ este cel mult $A*B$, complexitatea acestui algoritm este {$O(A*B)$}.\r\nDin motive de eficienta, in coada nu vor fi introduse numerele propriu-zis, ci doar resturile acestora la impartirea cu {$M$}. Pentru reconstituirea solutiei este necesara retinerea a doi vectori suplimentari {$up$} si {$cif$}, unde {$up{~i~}$} indica ultima pozitie de la care s-a plecat pentru a ajunge la pozitia $i$, iar {$cif{~i~}$} este ultima cifra ({$0$} sau {$1$}) a numarului de pe pozitia $i$ in coada.',256,'public',NULL,NULL),('development/cerinte','Cerinte infoarena3','2007-12-16 20:03:52','2008-02-20 00:21:01','h1. Cerinte infoarena3\r\n\r\nPe pagina asta incercam sa adunam cerintele pentru infoarena3. Nu ne dorim o specificatie formala, doar o liste pe puncte cu feature-uri pe care nu le putem rata. O astfel de lista este utila; nu trebuie sa facem vreo decizie tehnica care sa ne impiedice din a implementa unul dintre aceste puncte.\r\n\r\nCei mai importanti utilizatorii ai site-ului sunt cei care fac content, mai ales propunatorii de probleme. Infoarena2 este o imbunatatire majora fata de infoarena1 pe acest aspect, doar se poate mult mult mai bine. Rugam propunatorii de probleme sa adauge puncte pe aceasta lista.\r\n\r\nAu mai fost cateva topic-uri relevante: \'1\':forum/index.php?topic=2347.0 , \'2\':forum/index.php?topic=1361.100\r\n\r\n*{\'Back to development\':development}*\r\n\r\nh2. Ze list\r\n\r\n* User profile\r\n** Se pot edita si toate informatiile din SMF din aceasi interfata.\r\n** Se afiseaza nivelul de securitate al user-ului: a, b sau c\r\n** Daca nu este user standard atunci o pagina separata cu lista de drepturi.\r\n** Admin poate sa editeze orice date din profilul oricui.\r\n* Propus probleme\r\n** Exista o singura pagina pentru adaugare sau editare\r\n** Exista mai multe sectiune cu tab-uri in partea de sus\r\n** Sectiunea de enunt arata ca editarea normala de wiki\r\n** Sectiunea de informatii problema.\r\n** Sectiunea de teste/evaluator.\r\n*** Lista de teste\r\n*** Upload/download de teste ca zip\r\n** Surse oficiale?\r\n** Sectiunea de securitate.\r\n*** Se afiseaza lista de utilizatori si drepturi\r\n*** Se pot adauga drepturi unui utilizator\r\n*** Un utilizator poate avea drepturile a, b, c\r\n* Blog\r\n** Pagina de editat blog-post contine\r\n*** Continut\r\n*** Tag-uri\r\n*** Data la care devine vizibil (sau marcat draft)\r\n*** ID topic (eventual buton create topic).\r\n** Pagine de view blog-post contine:\r\n*** Lista de comentarii de pe forum. Hide/Show cu javascript.\r\n*** Link de reply\r\n*** Permalink?',1,'public',NULL,NULL),('preoni-2008/runda-2/solutii/grozavesti','preoni-2008/runda-2/solutii/grozavesti','2007-12-16 15:06:42','2007-12-16 23:05:29','h2(#grozavesti). \'Grozavesti\':problema/grozavesti\r\n\r\nObservam ca daca avem la dispozitie o matrice $NxN$ putem aduce orice element pe pozitia $(1,1)$ in cel mult doua interschimbari (una pentru linii si una pentru coloane). Daca elementul minim se afla pe pozitia $(i,j)$ interschimbam linia $i$ si coloana $j$ cu linia $1$ si coloana $1$. Astfel pentru fiecare $x$ de la $1$ la $N$ vom plasa pe pozitia $(x,x)$ cel mai mic element din submatricea avand coltul stanga sus $(x,x)$. Acum problema se reduce la aflarea elementului minim din submatricea avand coltul stanga sus $(x,x)$. Se poate implementa direct acest pas iterand prin toate valorile posibile si se obtine un algoritm de complexitate $O(N^3^)$. Daca in loc sa ne uitam la toata submatricea, verificam doar valorile de pe diagonala principala din submatrice obtinem complexitatea $O(N^2)$, dar acest lucru nu era necesar pentru obtinerea punctajului maxim.\r\n',2092,'public',NULL,NULL),('preoni-2008/runda-2/solutii/gather','preoni-2008/runda-2/solutii/gather','2007-12-16 15:11:13','2007-12-17 21:09:21','h2(#gather). \'Gather\':problema/gather\r\n\r\nVom calcula o matrice {$A[i][j]$} - distanta minima ca sa ajungem in celula $i$ urmariti de detinutii care corespund cifrelor de $1$ in reprezentarea binara a lui {$j$}. De fapt ne vor interesa doar valorile pentru celulele in care se afla detinuti, de aceea vom calcula doar aceste valori.\r\n\r\nPentru calcularea acestor valori vom construi un graf format din noduri de tipul ({$i,j$}) unde $i$ este o celula in care se afla un detinut, iar $j$ este un numar intre $0$ si {$2^K^$}. Vom avea muchie de la ({$i,j$}) la ({$t,j+2^t^$}) daca $t$ nu apare in reprezentarea binara a lui {$j$} si exista un drum de la celula celula $i$ la celula $t$ astfel incat capacitatea minima a muchiilor de pe acest drum sa fie mai mare sau egala decat numarul de biti de $1$ din descompunerea lui {$j$}(adica numarul de detinuti care il urmaresc pe Gigel). Costurile asociate acestei muchii va fi exact suma costurilor de pe drumul minim de la $i$ la $t$ care respecta conditia respectiva.\r\n\r\nPentru a calcula toate costurile muchiilor noului graf se aplica de {$k^2^$} ori algoritmul lui Dijkstra. Vom calcula pentru fiecare $i$ de la $1$ la $k$ si pentru fiecare $j$ de la $1$ la $k$ drumurile minime de la nodul in care se afla detinutul $i$ la toate nodurile folosind doar muchii ce au capcitate mai mare sau egala cu {$j$}.\r\n\r\nOdata construit noul graf se poate aplica Dijkstra pe el pentru a calcula matricea $A$, sau se poate folosi programare dinamica datorita aciclicitatii grafului.\r\n\r\nComplexitatea finala va fi $O( K^2^*N^2^ + 2^K^*K^2^)$.',1,'public',NULL,NULL),('preoni-2008/runda-2/solutii','Solutii preONI 2008, Runda 2','2007-12-16 15:04:37','2007-12-21 17:22:29','==include(page=\"template/preoni-2008/header\")==\r\n\r\nh1. Solutii preONI 2008, Runda 2\r\n\r\nIata ca s-a terminat si runda a 2-a a concursului preONI 2008. Concurentii au continuat lupta spre marea finala, fiind pusi de aceasta data in fata unui set mai frumos de probleme, credem noi. Speram ca dificultatile tehnice intampinate la evaluarea surselor nu au umbrit prea mult aceasta runda. Prezentam in continuare solutiile problemelor propuse spre rezolvare, precum si rezumatul celor intamplate pe parcursul concursului.\r\n\r\nNe bucura faptul ca la clasele 5-8 au fost rezolvate corect toate cele 3 probleme. Observam ca se profileaza un nucleu de elevi destul de buni si speram ca multi dintre ei sa reprezinte cu succes Romania la olimpiadele internationale peste cativa ani. In fruntea clasamentului gasim la egalitate 3 elevi, fiecare cu 200 de puncte: \'Andrei Purice\':utilizator/protoman, \'Radu Zernoveanu\':utilizator/raduzer si \'Vlad Gavrila\':utilizator/gavrilavlad. In spatele lor s-au clasat mai multi concurenti cu cate 140 de puncte, dovada a unui set echilibrat de probleme. In clasamentul general stafeta pentru calificarea la runda finala a fost ridicata destul de sus, insa mai sunt 2 runde in care se pot recupera multe puncte.\r\n\r\nDe aceasta data, cele mai ridicate punctaje s-au inregistrat la clasa a 9-a. Clasamentul este dominat de \'Victor Ionescu\':utilizator/vanila_cpp, care a fost foarte aproape de a obtine punctajul maxim. Dupa un inceput mai timid in prima runda, a recuperat si a trecut pe primul loc si la general. Pe urmatoarele pozitii s-au clasat \'Vlad Tataranu\':utilizator/tvlad si \'Ioana Pandele\':utilizator/ioanna. Problema usoara, \'Litere\':problema/litere, si cea medie, \'Nunta\':problema/nunta, au fost rezolvate corect de mai multi concurenti, insa punctajul maxim la cea grea, \'Operatii\':problema/operatii, a fost de 90 de puncte. Oricum, rezultatele au fost pe masura asteptarilor, felicitari!\r\n\r\nNu acelasi lucru s-ar putea spune si despre rezultatele de la clasa a 10-a. Problema usoara, \'Operatii\':problema/operatii a fost rezolvata corect de doar 4 concurenti, iar cea medie, \'Rays\':problema/rays de unul singur. Punctajul maxim la problema grea, \'Multiplu\':problema/multiplu a fost de doar 30 de puncte. Primul s-a clasat \'Alexandru Tudorica\':utilizator/tudalex, cu doua probleme rezolvate corect, al doilea, cu o zi mai proasta decat de obicei, \'Bogdan Tataroiu\':utilizator/bogdan2412, iar al treilea \'Istvan Hevele\':utilizator/h_istvan. Speram intr-o imbunatatire a punctajelor la rundele ce urmeaza.\r\n\r\nIn fruntea clasamentului de la clasele 11-12 gasim nume binecunoscute. \'Mugurel Andreica\':utilizator/mugurelionut a reusit sa se impuna si de aceasta data, cu 210 puncte, fiind urmat la egalitate de \'Cosmin Gheorghe\':utilizator/gcosmin si de \'Paul Baltescu\':utilizator/pauldb. Implementarile atente la problemele \'Multiplu\':problema/multiplu si \'Gather\':problema/gather ar fi garantat o pozitie fruntasa. Despre problema grea, \'Hacker\':problema/hacker nu avem prea multe de spus. Punctajul cel mai mare ii apartine lui Mugurel, 20 de puncte, iar rezolvarea exponentiala potrivita pentru a intra in timp nu a fost gasita de nimeni.\r\n\r\nIi felicitam pe toti cei care au participat la runda a 2-a si le uram succes mai departe!\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Litere\':preoni-2008/runda-2/solutii#litere\r\n* \'Grozavesti\':preoni-2008/runda-2/solutii#grozavesti\r\n* \'Dusman\':preoni-2008/runda-2/solutii#dusman\r\n* \'Nunta\':preoni-2008/runda-2/solutii#nunta\r\n* \'Operatii\':preoni-2008/runda-2/solutii#operatii\r\n* \'Multiplu\':preoni-2008/runda-2/solutii#multiplu\r\n* \'Rays\':preoni-2008/runda-2/solutii#rays\r\n* \'Gather\':preoni-2008/runda-2/solutii#gather\r\n* \'Hacker\':preoni-2008/runda-2/solutii#hacker\r\n\r\n==include(page=\"preoni-2008/runda-2/solutii/litere\")==\r\n\r\n==include(page=\"preoni-2008/runda-2/solutii/grozavesti\")==\r\n\r\n==include(page=\"preoni-2008/runda-2/solutii/dusman\")==\r\n\r\n==include(page=\"preoni-2008/runda-2/solutii/nunta\")==\r\n\r\n==include(page=\"preoni-2008/runda-2/solutii/operatii\")==\r\n\r\n==include(page=\"preoni-2008/runda-2/solutii/multiplu\")==\r\n\r\n==include(page=\"preoni-2008/runda-2/solutii/rays\")==\r\n\r\n==include(page=\"preoni-2008/runda-2/solutii/gather\")==\r\n\r\n==include(page=\"preoni-2008/runda-2/solutii/hacker\")==\r\n',5748,'public',NULL,NULL),('preoni-2008/runda-2/solutii/operatii','preoni-2008/runda-2/solutii/operatii','2007-12-16 15:08:32','2007-12-18 10:20:00','h2(#operatii). \'Operatii\':problema/operatii\r\n\r\nProblema admite multe rezolvari si a fost propusa pentru o departajare a concurentilor. Un prim algoritm ar fi selectarea la fiecare pas a secventei de lungime maxima ce contine numai elemente nenule si decrementarea cu o unitate a tuturor elementelor secventei. Procedeul se repeta cat timp exista o secventa cu elemente nenule (cat timp vectorul nu este nul). Deoarece la fiecare pas s-a selectat secventa de lungime maxima, numarul final de operatii va fi minim posibil. Aceasta solutie obtine 20-40 de puncte, in functie de prezenta optimizarilor.\r\nProblema se poate rezolva in complexitate liniara si exista mai multe rezolvari diferite ce au aceasta complexitate. Una din rezolvari este urmatoarea: fie $MAX$ maximul elementelor din vectorul {$v$}. Retinem $MAX$ liste, in a $i$-a lista avand memorate pozitiile din vector pe care apare numarul $i$. Pornim de la vectorul nul si inseram pe rand numerele {$1$}, {$2$}, ... {$MAX$}. Calculam la fiecare pas $i$ numarul de intervale in care impart primele $i$ numere vectorul {$v$}, rezultatul final fiind suma numerelor de intervale de la fiecare pas.\r\nDe exemplu, pentru vectorul {$v = (0 1 4 2 4 1 3)$} se procedeaza in felul urmator: plecam de la vectorul nul cu $7$ elemente. Introducem valoarea $0$ pe pozitia $1$ si s-a format un \"interval\" cu pozitii care nu au fost inca completate ( pozitiile $2-7$ ). Introducem numarul $1$ pe pozitiile $2$ si $6$ si se formeaza $2$ intervale: pozitiile $3-4-5$ si $7$. Introducem elementul $2$ pe pozitia $4$ si se formeaza $3$ intervale, cate un interval pe pozitiile {$3$}, $5$ si {$7$}, etc. In final se aduna numarul de intervale de la fiecare pas si se afiseaza rezultatul obtinut. Procedand in acest fel, vom sti sigur ca numarul de operatii folosite este minim: daca la pasul $i$ avem un anumit numar de intervale, aplicam operatia specificata in problema o data pentru fiecare interval.\r\nCa sa aflam in {$O(1)$} la fiecare pas cate intervale avem, tinem un vector caracteristic {$uz$}, unde {$uz{~i~}$} este $1$ daca si numai daca numarul de pe pozitia $i$ a fost inserat (marcat). Fie $nr_interval$ numarul curent de intervale. Distingem 4 cazuri:\r\n\r\n* marcam pozitia $i$, si pozitiile $i-1$ si $i+1$ sunt nemarcate => $nr_interval$ creste cu o unitate\r\n* marcam pozitia $i$, pozitia $i-1$ nemarcata si $i+1$ marcata => $nr_interval$ nu se modifica\r\n* marcam pozitia $i$, pozitia $i+1$ nemarcata si $i-1$ marcata => $nr_interval$ nu se modifica\r\n* marcam pozitia $i$ si pozitiile $i-1$ si $i+1$ sunt marcate => $nr_interval$ scade cu o unitate\r\n\r\nAceasta solutie este foarte simplu de implementat si obtine 100 de puncte. \r\n\r\nO solutie alternativa si cu o implementare mult mai concisa a fost oferita de \"Bitis Gabriel\":http://infoarena.ro/utilizator/gabitzish1. Aceasta se bazeaza pe urmatoarea observatie: capetele stangi ale secventelor ce vor fi selectate pentru incrementare vor fi doar acele pozitii cu valoare strict mai mare decat pozitia precedenta. Evident, celelalte pozitii vor fi acoperite de secvente care pornesc mai in stanga. De exemplu, pentru vectorul de mai sus, se vor selecta doar secvente ce incep cu valorile {$1$}, {$4$}, {$4$}, {$3$}. Pentru a afla numarul minim de operatii, vom tine un contor pe care il vom creste de fiecare data cand {$v[i]>v[i-1]$} cu valoarea {$v[i]-v[i-1]$}, pentru fiecare {$i$} cuprins intre {$1$} si {$N$}. Conventional {$v[$}{$0]=0$}. Solutia poate fi optimizata (desi nu este necesar pentru 100 de puncte) pentru a nu retine tot vectorul, ci numai ultimii 2 termeni. Complexitatea obtinuta este {$O(N)$}.',2044,'public',NULL,NULL),('blog/avem-comentarii','Avem comentarii!','2007-12-18 01:15:36','2008-11-15 13:41:14','Cristi si Mircea au simplificat modul in care se pot face comentarii pe blog. Daca sunteti curiosi de detaliile tehnice va puteti uita la changeurile facute \'aici\':http://hackers.devnet.ro/changeset/832 si \'aici\':http://hackers.devnet.ro/changeset/864 . Comentariile arata acum asa:\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}blog/avem-comentarii?comentarii2.jpg 70%!\r\n\r\nMai ar fi de lucru, dar e un pas mare in fata ca utilizabilitate.\r\n\r\n\r\n\r\n\r\n',1490,'protected',2500,NULL),('blog/interviu-radu-berinde-partea-intai','Interviu cu Radu Berinde - partea intai','2007-12-19 01:47:16','2008-11-15 13:41:14','_Radu Berinde este unul din putinii romani cu doua medalii de aur la olimpiada internationala de informatica. Acum studiaza la MIT, iar vara trecuta a facut un internship la Google pentru a doua oara. Am avut ocazia sa lucrez cu el pe acelasi proiect si m-a impresionat prin o gramada de idei bune si viteza cu care scrie cod elegant si util. In aceasta prima parte a interviului ne povesteste ceva din experienta lui legata de olimpiade._\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/interviu-radu-berinde-partea-intai?radu.jpg 50%! \r\n\r\n(Radu cu tiburonul sau).\r\n\r\n*Cum ai inceput cu informatica? Dar cu concursurile?*\r\n\r\nEram prin clasa a patra cand sora mea a adus acasa un 286. Se intamplase ca imi rupsesem picioru (intr-un mic accident de masina) si stateam acasa toata ziua. Dupa ce m-am plictisit de ce jocuri se gaseau, am inceput sa ma uit din ce in ce mai interesat la ce facea sora mea, care isi scriea proiectu pt facultate in Pascal. Am invatat incet incet, pana am rescris de la capat tot proiectul (initial proiectul folosea programarea pe obiecte, eu l-am rescris fara obiecte). Asa a inceput pasiunea pentru programare; am tot continuat sa invat de prin carti si sa fac diverse programe. Prin clasa a 5-a sau a 6-a am inceput sa merg la Palatul Copiilor; acolo au vazut ca stiu deja destul de multe si am intrat direct in grupele unde se pregateau cei care mergeau la concursuri nationale de informatica. Am fost pregatiti foarte bine de Dna. Rodica Pintea. In clasa a 6-a am fost la primul meu concurs de informatica (la Lugoj), unde am luat punctaj maxim. Nu mai e nevoie sa spun ca de-atunci problemele de concurs au ramas pasiunea mea.\r\n\r\n*Ai participat si la alte olimpiade? Ai avut alte subiecte care ti-au placut in scoala?*\r\n\r\nDintre subiectele de la scoala, cel mai mult imi placea matematica (surpriza..); participam la olimpiade si faceam destul de bine la proba de sector, dar la municipiu eram depasit total :) Am fost si la fizica o data sau de doua ori, dar spre sfarsitul gimnaziului nu prea mi-a mai placut. In liceu m-am concentrat destul de mult pe concursurile de informatica; nu pot sa zic ca m-am implicat prea mult in ce se facea la scoala.\r\n\r\n*Cum te antrenai pentru olimpiade?*\r\n\r\nIn primul rand, lucram foarte multe probleme, de oriunde se putea: olimpiade din romania, internationale, din alte tari, USACO, ACM, orice. Incercam sa gasesc si teste ca sa pot verifica solutia mea. Pana prin clasele 9-10 mai participam si la pregatiri, la Palatul Copiilor, sau la liceu, organizate de Dna. Pintea sau alti profesori si studenti.\r\n\r\n*Ai avut pe cineva care te-a ajutat in lumea olimpiadelor, sau ai invatat totul singur?*\r\n\r\nBineinteles, probabil mai multi decat pot mentiona aici. Cred ca cea mai mare influenta a avut-o Dna. Prof. Rodica Pintea, care a fost profesoara mea de la Palatul Copiilor. Am fost pregatit si de si de Dl. Prof. Atanasiu in anumite perioade. Am invatat mult si de la prieteni olimpici mai mari ca mine: Andrei Marius, Adrian Drumea, Andrei Gheorghe, Angel Proorocu (hmm de ce incep toti cu A?). La diverse pregatiri am mai invatat lucruri si de la alti (atunci) studenti fosti olimpici, ca Bogdan Batog, Mihai Stroe, Dumitru Bogdan.\r\n\r\n*Sunt cateva probleme ce ti-au ramas in minte de la concursurile la care ai participat?*\r\n\r\nMi-a ramas in minte problema XOR de la IOI 2002. Se dadea o matrice cu patratele albe sau negre; se putea face o singura operatie, de a alege un dreptunghi (o submatrice) si a inversa culoarea tututor patratelelor din dreptunghi. Era cu intrare data in prealabil, si se cereau solutii cu numar de operatii cat mai mic. Solutia era un algoritm foarte simplu care obtinea o 2-aproximare - cu acest hint va las sa va prindeti singuri de el :)\r\n\r\n*Care e structura ta de date preferata?*\r\n\r\nDintre cele mai de baza, AVL.. Dintre cele de geometrie, range trees (cu Willard-Lueker refinement/fractional cascading).\r\n\r\n*Care e algoritmul preferat?*\r\n\r\nGreu de spus exact, dar voi descrie ceva ce mi-a placut intodeauna foarte mult - algoritmii in timp liniar bazati pe ideea de lista dublu sortata, in care la fiecare pas se insereaza un element nou, stergandu-se mai intain elementele din coada listei care sunt mai \"proaste\". De exemplu, pentru problema sirului divizat: se da un sir de numere A[1..N], se cere un M maxim astfel incat toate A[1..M-1] sunt mai mici decat A[M] si toate A[M+1..2M] sunt mai mari decat A[M]. Se poate rezolva in timp daca la fiecare pas (pentru fiecare M) putem afla minimul elementelor A[M+1..2M}. Putem rezolva problema in timp liniar daca mentinem o lista dublu sortata pentru a afla la fiecare pas minimul elementelor A[M+1..2M]: lista e sortata crescator dupa valoare si dupa pozitie. Ideea este ca daca in zona curenta de interes avem doua numere A si B, A e la stanga decat B, si A > B, nu ne va mai interesa niciodata A, deci il putem arunca. Cand inseram un numar nou X mai intai stergem repetat ultimul element al listei pana cand acesta e mai mic ca X, apoi inseram pe X la sfarsitul listei. La fiecare pas se sterge si cate un element de la inceputul listei. Minimul va fi intotdeauna ultimul element din lista. Pentru o problema mai avansata care foloseste aceasta metoda, vedeti problema Batch de la IOI 2002.\r\n\r\n*Cate probleme crezi ca ai rezolvat la viata ta?*\r\n\r\nAs zice ca peste 1000, poate chiar spre 1500-2000.\r\n\r\n*Ce mai tii minte din viata de olimpic? Care erau concurentii cu care te infruntai? (ai ramas prieten cu unii?)*\r\n\r\nMulti dintre cei din Bucuresti care participau la olimpiade (si faceau bine) imi erau (si sunt) prieteni buni. Era foarte placut sa ne intalnim la o bere si sa discutam probleme si idei de rezolvare. Formam un grup destul de mare, era foarte distractiv sa mergem impreuna la olimpiade sau loturi.\r\n\r\n\r\n*Stiu ca la IOI cand erai clasa a 12-a ai bushit doua probleme si tot ai luat aur, ne poti povesti mai mult despre acel episod?*\r\n\r\nAnul acela nu a fost atat de bun pentru mine (am facut destul de prost si la CEOI), n-as putea sa spun exact din ce motive. In prima zi a fost o problema grea la care am gasit o solutie inteligenta, insa era destul de complicata si intr-un program imens am uitat sa pun un if sau doua si am pierdut 100 de puncte (care la final m-ar fi adus pe locul 1). Am mai facut alte greseli si in ziua 2, mai mult din cauza rezultatului prost din ziua 1. Dar sunt convins ca mai toti care au luat aur atunci au facut si ei tot felul de greseli stupide, deci nu cred ca am fost neaparat mai ghinionist. Nu pot spune neaparat ca meritam sa iau mai mult, dar sunt sigur ca as fi putut sa fiu in forma mai buna in care sa nu am probleme. Pot spune totusi ca am fost dezamagit de subiectele de atunci, care nu mi s-au parut deloc la fel de frumoase si inteligente ca cele din 2002. M-a intristat un pic cand am realizat ca pana la urma te pregatesti ani intregi pentru 6 probleme care se poate intampla sa \"iti pice prost\" in ziua respectiva.\r\n\r\n*Cum te prinzi de probleme? Ai observat vreo metoda care ajuta?*\r\n\r\nA fost o evolutie destul de clara. Am lucrat multe probleme, pana cand la un moment dat eram foarte bucuros sa primesc probleme \"clasice\", insa eram inca speriat de cele \"de idee\". In timp insa, cunoscand problemele clasice am inceput sa am idei foarte bune. Nu e ceva ce poti sa obtii printr-o metoda anume; daca intelegi foarte multe idei, vei incepe la un moment dat sa le combini in moduri noi. ',1490,'protected',2502,NULL),('planificare/sedinta-20071218','Sedinta 2007-12-18','2007-12-13 17:41:33','2008-01-18 17:51:56','h1. Sedinta 2007-12-18\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Locatie si ora\':planificare/sedinta-20071218#locatie\r\n* \'Participanti\':planificare/sedinta-20071218#participanti\r\n* \'Agenda\':planificare/sedinta-20071218#agenda\r\n* \'Rezolutii\':planificare/sedinta-20071218#rezolutii\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *marti* la ora *18:00* la \'-Hostway Romania-\':http://hostway.ro \'*&raquo; ICHB*\':http://ichb.ro\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"fluffy\" type=\"tiny\")== \r\n* ==user(user=\"silviug\" type=\"tiny\")== \r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioara\':planificare/sedinta-20071128\r\n* Stabilit locuri de intalnire pentru sedintele viitoare\r\n* Stabilit orar sedinta (din 2 in 2 saptamani)\r\n* Goal-uri infoarena pentru 2008\r\n* Votat \'IAP #5\':propuneri/5-open-surse\r\n* Update Adobe\r\n* Discutat \'IAP #4\':propuneri/4-forum\r\n* infoarena 2.1.5\r\n* Program preONI rundele 3-5\r\n* Calendar concursuri\r\n* Algoritm nou pt rating\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Cristi aranjeaza CSS-ul la comentariu ({%{color:red}done%})\r\n* Cristi scrie IAP despre almanah\r\n* Cristi face cont la PayPal ({%{color:red}done%})\r\n* Leo face IAP despre restructurat sistem de navigatie\r\n* Mircea face IAP despre arhiva pentru incepatori\r\n* Fluf discuta cu Malex despre stack trace.  Malex ne ajuta.\r\n* Programul preONI 2008 ramane la fel\r\n* Mircea face o lista de task-uri pregatitoare pentru finala preONI (rezervare cazare, laborator info, mancare etc.) ({%{color:red}done%})\r\n* Mircea il preseaza pe tipul de la Microsoft\r\n* Fluf lanseaza 2.1.5\r\n* Mircea face macro de calendar de concursuri bagate din SMF ({%{color:red}done%})\r\n* Facem intalniri odata la doua saptamani in zile de miercuri incepand cu 9 ianuarie.  Facem intalniri la ora 10 la Poli.\r\n* S-a votat IAP#5\r\n* IAP#4: Wefgef face structura de forum din nou, o votam si schimbam pe live deodata\r\n* Cristi scrie IAP despre community ladder\r\n\r\nh2. Notite\r\n\r\n* Ramane de vazut cine implementeaza IAP #5\r\n* Mircea vorbeste cu Adi si Cosmin despre research la algoritmul de rating\r\n',13,'protected',NULL,NULL),('utilizator/bigmazilu','Profil BigMazilu','2008-01-03 05:55:51','2008-11-08 00:15:27','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(Sunt elev in clasa a 12-a in Liceul Teoretic Nicolae Balcescu, Medgidia, si vreau sa devin programator:D:D)_\r\n\r\nh2. Distinctii primite\r\n\r\n* La olimpiada (2008) locul 8 - pe judet, iar in orash (Medgidia) -  sunt primul, i-am intrecut chiar si pe cei de-a 12-a (TOTI) \r\n* Altceva , inca nimic..., dar la olimpiada din 2009 sper sa fac ravagii...',7395,'public',NULL,NULL),('trainingpath/arbori','trainingpath/arbori','2008-01-06 07:24:55','2008-01-06 07:24:55','** arbori\r\n*** diametrul, centrul unui arbore\r\n\r\nDiametru cu programare dinamica, consideram arborele avand o radacina. Pentru fiecare nod calculam cu programare dinamica cele mai lungi doua drumuri disjuncte care pornesc din acel nod inspre frunze. Rezultatul este maximul sumei lungimilor celor doua drumuri care pornesc din acelasi varf.\r\n\r\nPentru gasirea centrului unui arbore put\r\n\r\n*** testare daca doi arbori sunt izomorfi\r\n*** cod pruffer',58,'public',NULL,NULL),('blog/interviu-radu-berinde-partea-a-doua','Interviu cu Radu Berinde - partea a doua','2008-01-08 17:59:43','2008-11-15 13:41:14','_Postez a doua parte a interviului cu Radu Berinde. In aceasta parte el ne povesteste despre concursuri, despre MIT, despre Google si despre cat impinge la piept, de asemenea va aparea si putin context legat de poza cu masina din prima parte a interviului. Enjoy!  _\r\n\r\n*Dupa terminarea liceului ai fost fost in comisii la cateva concursuri, cum e participarea pe cealalta parte a baricadei?*\r\n\r\nPe de-o parte, esti mult mai relaxat si distantat de ce se intampla in concurs; pe de alta parte, trebuie sa te gandesti foarte bine la ce faci, pentru ca deciziile tale afecteaza multi oameni.  In rest nu prea vad ce comparatie sa fac intre cele doua activitati, sunt foarte diferite..\r\n\r\n\r\n*Cum se compune o problema pentru concurs?*\r\n\r\nMi se pare destul de greu (si frustrant) sa scoti o problema buna; e ceva la care trebuie sa te gandesti in timp, si apoi sa te decizi unde/cand sa o propui. Sunt mai multe variante de compunere a unei probleme: una e sa te gandesti (probabil pornind de la o problema pe care o cunosti) la o cerinta noua, apoi sa te gandesti cum s-ar putea rezolva. Astfel e destul de greu sa nimeresti o cerinta buna, insa in gasirea rezolvarii pot sa apara idei noi.\r\n\r\nAlta varianta e sa te gandesti la o idee pe care vrei sa se bazeze solutia, si apoi sa te gandesti la ce ar trebui sa ceara o problema care se rezolva in modul respectiv. Astfel e mai usor sa scoti problema, dar idei noi de rezolvare par mai greu (din moment ce solutia e oarecum deja fixata).\r\n\r\n*Pentru cei ce participa la concursuri pe infoarena, esti cunoscut prin \"jmenurile de implementare\" pe care le invata din sursele tale. Poti sa ne povestesti de unul dintre aceste \"jmenuri\"?*\r\n\r\nRegula de baza cand incerci sa optimizezi un program (in afara de a imbunatati algoritmul) e sa fii atent numai la partile din program care folosesc majoritatea timpului de executie. Mi se intoarce stomacul pe dos cand vad oameni care \"optimizeaza\" inlocuind in orice loc posibil inmultirile cu operatii pe biti, sau alte chestii asemanatoare (de parca nu le-ar optimiza oricum compilatorul). Codul trebuie sa fie cat mai usor de citit si inteles - asa e cel mai probabil sa iasa corect (si degeaba merge repede daca e gresit). Cand vrei sa optimizezi, te concentrezi pe ceea ce conteaza. De obicei este vorba de cateva linii de cod si e inutil sa optimizezi orice altceva in afara de aceste linii. Era o vorba care suna ceva de genul: in majoritatea cazurilor, 99% din timpul de rulare este petrecut in 1% din liniile de cod.\r\n\r\nCa sa stii sa optimizezi, trebuie sa intelegi cat de cat ce se intampla mai jos de compilator; in majoritatea situatiilor, trebuie sa ai idee de cum functioneaza calculatorul, sa stii cum sa te folosesti de cache-ul de memorie, sau sa stii care operatii sunt mai costisitoare.\r\n\r\nPot sa va povestesc despre o problema la un lot (Petrol din 2003); era despre un graf cu $N$ noduri si $M$ muchii si avea o solutie evidenta care folosea $N$ BF-uri (timp $N*M$). Solutia care se cerea era in $M*log N$ daca imi amintesc bine, iar solutia in $N*M$ ar fi trebuit sa ia in jur de 30-40 de puncte. Eu am reusit sa iau 90 de puncte cu aceasta solutie. Cum? O singura linie conta - cea care definea bucla de expandare a vecinilor unui nod. Trebuia sa optimizez cat mai mult enumerarea vecinilor unui nod. Ideea a fost sa citesc mai intai intrarea doar pentru a numara vecinii fiecarui nod, sa aloc cate un vector exact de marimea necesara pentru fiecare nod, apoi sa citesc din nou intrarea si sa completez vectorii. Astfel, efortul de a enumera toti vecinii in unui nod in parcurgere este minim; vecinii sunt unul langa altul in memorie si cache-ul este folosit foarte bine. Mai era o singura decizie de luat - cum sa stii cand sa te opresti in enumerarea vecinilor; am testat in timpul concursului tot felu de metode si cea mai rapida a fost sa adaug un numar special (0) la sfarsitul fiecarui vector. Sigur, ar fi fost mai bine sa fiu mai destept si sa ma prind de solutia corecta, dar care ar mai fi fost spectacolul? :)\r\n\r\n*Stiu ca pentru un an erai inscris la Universitatea Bucuresti si la Universitatea Politehnica, iar apoi ai plecat la MIT. Poti sa ne povestesti mai mult? Ce te-a facut sa alegi MIT?*\r\n\r\nEram deja decis sa aplic la MIT inainte sa incep facultatea in Romania. Motivul in principal a fost ca in facultatile din Romania nu prea se invata mare lucru (la informatica). In nici un caz nu cat se invata la una ca MIT. Simteam ca am totusi un talent deosebit si ca trebuie sa il folosesc/extind in continuare (ceea ce clar nu se intampla la facultate in Romania). Nu eram chitit sa plec din tara; faptul ca trebuia sa plec era un dezavantaj. Am aplicat doar la MIT, in ideea ca daca plec din tara, macar sa merite. Plus ca aici aveam si cele mai mari sanse sa fiu acceptat, pentru ca aici conteaza (sau contau..) cel mai mult medaliile.\r\n\r\n*Care sunt cursurile ce ti-au placut mai mult in facultate (si de ce)?*\r\n\r\nMi-au placut materia la multe cursuri. La unele mi-au displacut lucruri legate de cerinte, proiecte finale, etc. insa materia mi-a placut la majoritatea cursurilor de informatica.\r\n\r\nCursul de sisteme de operare a fost foarte interesant; pe de-o parte, am studiat in detaliu un sistem foarte mic de la care a plecat UNIX, pe de alta parte am implementat un sistem bazat pe cu totul alte idei.\r\nLa sfarsit am avut si un proiect in care puteam sa facem cam orice in sistemul nostru de operare; a fost foarte interesant - unii au portat stackuri TCP/IP si web-servere, altii sisteme de fisiere distribuite, si multe alte chestii. Eu am portat un compilator, vi, si quake1 :)\r\n\r\nAlt curs interesant a fost unul de sisteme distribuite, in care am invatat despre multe sisteme si tehnici care au avut succes, si am si implementat un sistem la sfarsit. Alt curs a fost unul de grafica, la care am implementat multe chestii misto.\r\n\r\nDin cele teoretice, mi-au placut teoria complexitatii, geometrie computationala, algoritmi avansati; la toate am invatat lucruri foarte interesante. Am luat si un algoritm mai avansat care mi-a placut foarte mult; se chema \"sketching, streaming, and sub-linear space algorithms\". A fost despre tehnici si algoritmi cu care sa aproximezi (probabilistic) ceva folosind mult mai putin spatiu decat ar lua \"ceva\"-ul respectiv (care de obicei era un vector intr-un spatiu de\r\ndimensiune foarte mare).\r\n\r\n*Cum e viata de stundent la MIT? Cum se imbina munca cu distractia?*\r\n\r\nDe multe ori nu prea frumoasa; sunt cam exagerati in volumul de materie, teme, cerinte si uneori trebuie sa depui eforturi foarte mari sa tii pasul. In unele perioade esti mai relaxat, si poti sa te bucuri de mai mult timp liber.  Nu e la fel de distractiv in Romania, unde sunt majoritatea prietenilor mei mai apropiati. Insa sunt locuri, oameni, si lucruri frumoase si acolo; si ai si avantajul de a trai intr-o tara mult mai dezvoltata si mai civilizata.\r\n\r\n*Cand ai inceput cu concursurile pe topcoder ai ajuns foarte repede intre cei mai buni de pe sait, e usor pentru tine sa participi la concursuri la un nivel inalt dupa ce ai facut o pauza?*\r\n\r\nMi se pare ca in timp se clarifica ideile si cunostiintele. Cred ca acum as fi mai bun decat eram in liceu daca m-as duce din nou la olimpiadele din liceu (dupa ce m-as mai antrena un pic).\r\n\r\n*Cum se compara concursurile pe topcoder cu celelalte la care ai participat?*\r\n\r\nLa Topcoder e foarte important sa scrii codul repede. La olimpiade, niciodata nu ma grabeam sa scriu codul, preferam sa ma concentrez sa fiu sigur ca e corect; ba mai mult, de multe ori scriam si generatoare de teste, si variante mai incete de rezolvare cand se putea, ca sa verific programele.  La topcoder nu poti sa faci asta si mai pierzi cateodata din greseli mici; antrenamentul conteaza foarte mult. In rest, problemele nu mi s-au parut cu mult diferite fata de ce eram obisnuit.\r\n\r\n*De ce nu ai participat la ACM ICPC?*\r\n\r\nN-am ajuns nicaieri, dar asta nu inseamna ca n-am participat. Am participat o data pentru Politehnica cu Marius Andrei si Mugurel Andreica; am fost primii care nu ne-am calificat. Am avut ghinion la o problema simpla care nu iesea deloc si la alta care avea o greseala in enunt si am pierdut mult timp rezolvand practic alta problema. \"Ghinion\" poate insemna si ca totusi nu ne antrenasem foarte mult (nu cat ar fi trebuit).\r\n\r\nAm participat si o data pentru MIT insa am fost pus exact inainte de concurs intr-o echipa cu doi americani pe care nu-i cunosteam deloc (al treilea membru al echipei lor pleca in finala topcoder si nu putea participa). Evident ca am fost dat la o parte, din moment ce ei nu stiau nimic despre mine. Am participat la faza regionala, unde toate problemele in afara de una erau foarte simple; le-au facut ei doi pe toate foarte repede. La cea grea ma gandisem deja dar nu m-au lasat sa o scriu eu, si tot unul din ei s-a apucat; m-am enervat ca stateam langa el si ii ziceam ca nu face ceva bine si nu ma asculta chiar daca aveam dreptate. Ma enerva ca se si complica, si scria un Dijkstra cu heapuri in STL cand putea sa il faca in N^2 si sa fie mult mai usor si clar. N-a iesit din prima, si a durat pana am rezolvat-o; intre timp, cealalta echipa de la MIT le facuse deja. Celelalte echipe n-au reusit sa faca nici macar toate problemele simple, deci oricum echipele de la MIT au iesit distantat pe primele locuri. Din pacate, chiar daca erau mai multe locuri de calificare, nu se putea califica decat o singura echipa de la fiecare facultate (nu mi-e clar de ce). In echipele de la MIT aproape toti fusesera in primii 10 la un IOI, deci nu e de mirare ca ne-am luptat intre noi.\r\n\r\nDupa aceea n-am mai participat. Motivul principal a fost ca imi manca destul de mult timp - cateva saptamani din semestru, cel putin o zi din weekend o pierdeam cu concursuri/antrenamente pt. ACM. Cum temele si alte chestii iau si ele destul timp mult, era prea mult. In plus, in fiecare an vin tipi proaspat dupa IOI, si cred ca e destul de greu sa tii pasul. Si oricum e foarte greu sa iti gasesti colegi cu care sa mearga bine lucrul in echipa.\r\n\r\n*Ai fost de doua ori la internship pe vara la Google, cu ce impresii ai ramas?*\r\n\r\nNu cred ca mi-ar placea sa lucrez full-time la Google. Cred ca depinde destul de mult de proiect, insa pare ca pana la urma ce faci tu nu conteaza asa de mult. Probabil ca asa e peste tot.. In comparatie cu majoritatea companiilor, probabil ca e foarte bine la Google; imi displace totusi stilul asta american (sau poate nu e doar american?) de a sta toata ziua la servici. Eu prefer sa lucrez in continuu si sa plec cat mai repede acasa, ca am lucruri mai bune/placute de facut.\r\nMajoritatea par ca stau la servici 10-11 ore din care 2-3 freaca menta. Ma rog, probabil ca nu mi-ar placea sa lucrez full-time nicaieri si de-aici vine problema :)\r\n\r\n*Poti sa ne zici un proiect software misto la care ai lucrat?*\r\n\r\nNu am mai lucrat demult la un proiect; pe la inceputul liceului eram pasionat de grafica 3d, si am facut un engine 3d care citea harti de quake1 si apoi quake3 si te puteai plimba prin ele.\r\n\r\n*Care sunt programele de pe calculator care le folosesti cel mai des, pt programare si in rest?*\r\n\r\nLucrez in Windows XP dar am mai tot timpul un Slackware deschis intr-un VMware (si folosesc X-Win32 in loc de X). Documentele/temele le scriu in linux, cu vim si latex (si xdvi). In Windows nu folosesc mult Total Commander (fostul Windows Commander). Programe mici le scriu in linux, folosesc vim si gcc. Mai lucrez in Eclipse si in Visual Studio din cand in cand.\r\n\r\n*Care sunt siteurile tale preferate?*\r\n\r\ninfoarena :p\r\nhowstuffworks\r\nwikipedia\r\nmininova\r\ntheonion\r\n\r\n*Ai ceva carti de programare preferate?*\r\n\r\nIntroduction to Computational Geometry, de Shamos si Preparata.\r\nTheory of Computation, de Sipser.\r\n\r\n*Dar carti ce nu au legatura cu programarea?*\r\n\r\nMaximum Boost de Corky Bell :)\r\n\r\n*Cat timp petreci in fata calculatorului?*\r\n\r\nMult prea mult.\r\n\r\n*Alte pasiuni inafara de programare?*\r\n\r\nAcum sunt pasionat de mesterit la masini, lucrez la masina cand am timp si cand nu e prea frig afara. Am schimbat sau imbunatatit pana acum tot felu de chestii - componente de suspensie, etriere, discuri de frana, arbore cu came, chestii de la esapament, tot felu de relee si circuite - si inca merge :) Cred ca daca as avea timp si bani, un timp destul de mare as face numai asta.\r\n\r\n*Cat impingi la piept?*\r\n\r\nHaha, cel mai mult am impins 120kg la declinat, dar asta s-a intamplat cu (prea) mult timp in urma..\r\n\r\n*Te mai intorci in Romania sau ramai in State?*\r\n\r\nIn viitorul apropiat probabil ca voi ramane in State. Mai departe e greu de spus, cred ca depinde de prea multe lucruri pe care nu pot sa le prevad. In orice caz, am pastrat contactul cu prietenii din Romania, si il voi pastra in continuare indiferent de ce se va intampla - deci intotdeauna voi avea motive sa ma intorc.\r\n\r\n*Ce faci dupa ce termini facultatea?*\r\n\r\nNu stiu inca. Cred ca voi mai face un an pentru master, apoi probabil voi lucra in State, cel putin pentru un timp.\r\n\r\n_Multumesc pentru interviu!_',1490,'protected',2554,NULL),('utilizator/ruxandra_enus','Profil ruxandra_enus','2008-01-11 12:20:38','2008-01-11 12:20:38','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',7424,'public',NULL,NULL),('utilizator/astronomy','Profil Airinei Adrian','2006-11-24 21:00:50','2008-01-11 23:26:08','h2. Despre mine\r\n\r\n* Sunt student in anul I la Facultatea de Informatica, Iasi\r\n* Pana la varsta de 6 ani am locuit in Radauti, de la 7 ani am venit in Iasi, unde am studiat la Scoala nr. 12 in clasele primare, iar in gimnaziu si liceu am studiat la Colegiul Costache Negruzzi\r\n* Ce imi placea cel mai mult cand eram mic era sa joc fotbal\r\n\r\nh2. Informatica\r\n\r\nIn gimnaziu faceam informatica la scoala, dar nu stiam nimic pe atunci, in timpul orelor jucam \"dave\" sau alte jocuri. In clasa a 9a am inceput sa rezolv primele probleme de algoritmica. Am fost foarte surprins sa ies pe primul loc la OMI 2004 (olimpiada municipala iasi), dar la OJI 2004 nu am reusit mare lucru, nu m-am calificat mai departe. La OJI 2005 am iesit din sala cu gandul ca am rezolvat problema \"Lacusta\", dar cand am auzit pe sala ca se rezolva cu programare dinamica am spus ca sigur am gresit-o (aceasta a fost prima problema din viata rezolvata de punctaj maxim in timpul unui concurs). Mai tarziu aveam sa aflu ca metoda care am folosit-o e denumita programare dinamica in literatura de specialitate. M-am calificat astfel la ONI 2005 si am reusit sa obtin 22 puncte din 600. Apoi a urmat momentul cand am inceput sa lucrez serios la informatica, imi aduc aminte in prima zi cand am ajuns acasa am cautat pe google site-ul infoarena, auzisem de el la ONI. Pe la inceputul vacantei aveam vreo 2000-3000 de puncte. De altfel, infoarena a fost principalul meu site de pe care am dobandit experienta in algoritmi.\r\n\r\nh2. Multumiri\r\n\r\nMultumesc tuturor care m-au ajutat sa obtin aceste performante. (sunt multi!)\r\n\r\nh2. Distinctii primite\r\n\r\n* Medalie de argint, IOI 2007 Zagreb\r\n* Medalie de aur, BOI 2007 Chisinau\r\n* Participare in lotul national largit de informatica 2006, 2007\r\n* Premiul II ONI 2006\r\n* Mentiune ONI 2007\r\n\r\nh2. Wefgef pe infoarena\r\n\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\nPoza eu cu Wefgef\r\n!utilizator/astronomy?P1050136.JPG 45%!',2092,'protected',NULL,NULL),('teorema-chineza-a-resturilor','Teorema chineza a resturilor - generalizari si aplicatii','2007-04-02 18:38:02','2009-02-20 00:18:11','h1. Teorema chineza a resturilor - generalizari si aplicatii\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"MciprianM\") ==\r\n\r\n(Categoria _Matematica_, Autor _Adrian Vladu_)\r\n\r\nh2. Scurta istorie\r\n\r\nSe considera un numar de obiecte. Impartindu-le in grupuri de cate trei, raman doua negrupate. Impartindu-le in grupuri de cate cinci, raman trei. Impartindu-le in grupuri de cate sapte, raman doua. Cate obiecte sunt? Aceasta este problema enuntata de matematicianul chinez Sun-Tsu in secolul al IV-lea al erei noastre. El a demonstrat ca toate numerele naturale de forma <tex>23 + 105 * k</tex> reprezinta solutiile acestei probleme. Din pacate nu putem sti daca a dezvoltat o metoda generala pentru a rezolva astfel de sisteme de ecuatii modulare. Aceasta este tema tratata in articolul care urmeaza.\r\n\r\nh2. Definitie\r\n\r\nPentru inceput, sa consideram sirul <tex>n = n_{1}, n_{2}, ..., n_{k}</tex> ale carui elemente sunt, luate doua cate doua, prime intre ele. *Teorema chineza a restului* (t.c.r.) afirma ca exista o corespondenta biunivoca intre orice numar <tex>a\\in\\mathbb{Z}_{n}</tex> si multimea ordonata de resturi ale lui a modulo <tex>n_{i}, i\\in\\{1, 2, ..., k\\}</tex>. Cu alte cuvinte, operatiile in <tex>\\mathbb{Z}_{n}</tex> pot fi aplicate echivalent atat pe numere cat si pe multimile ordonate corespunzatoare resturilor modulo <tex>n_{i}</tex>. Pentru orice <tex>a, b \\in \\mathbb{Z}_{n}</tex>, notam <tex>a_{i} = a\\ mod\\ n</tex>, respectiv <tex>b_{i} = b\\ mod\\ n</tex>, generand corespondentele <tex>a \\leftrightarrow \\{a_{1}, a_{2}, ..., a_{k}\\}</tex> respectiv <tex>b \\leftrightarrow \\{b_{1}, b_{2}, ..., b_{k}\\}</tex>. Conform teoremei chineze a restului, pentru orice operator <tex>\\circ \\in \\{+, -, * \\}</tex>, <tex>a \\circ b \\leftrightarrow \\{(a_{1} \\circ b_{1})\\ mod\\ n_{1} , ( a_{2}\\circ b_{2})\\ mod\\ n_{2}, ..., (a_{k} \\circ b_{k})\\ mod\\ n_{k}\\}</tex> ramane o corespondenta valida. Problema care se iveste imediat este conversia dintr-o forma in alta. Transformarea unui numar in multimea corespunzatoare este imediata. Partea mai dificila este operatia inversa, iar aceasta este problema care va fi tratata in continuare. Pentru determinarea numarului <tex>x \\in \\mathbb{Z}_{n}</tex>, corespunzator multimii <tex>\\{ a_{1}, a_{2}, ..., a_{k}\\}</tex>, este suficienta rezolvarea sistemului de ecuatii modulare:\r\n\r\n<tex>x \\equiv a_{1}(mod\\ n_{1})</tex>\r\n<tex>x \\equiv a_{2}(mod\\ n_{2})</tex>\r\n<tex>...</tex>\r\n<tex>x \\equiv a_{k}(mod\\ n_{k})</tex>\r\n\r\nDeoarece avem de a face cu o corespondenta biunivoca, conform teoremei, exista un singur <tex>x \\in \\mathbb{Z}_{n}</tex> care satisface sistemul de mai sus. Procedeul prin care se determina aceasta valoare nu este deosebit de complicat:\r\n\r\n*  se noteaza <tex>n = n_{1} * n_{2} * ... * n_{k}</tex> si <tex>M_{i}= n / n_{i}</tex> (deoarece oricare doua valori <tex>n_{i}</tex> si <tex>n_{j}</tex> sunt prime intre ele, avem intotdeauna <tex>cmmdc(M_i, n_i) = 1</tex>);\r\n*  se calculeaza <tex>x_i</tex> , <tex>i \\in \\{1, 2, ..., k\\}</tex> cu proprietatea <tex>M_i * x_i \\equiv 1 (mod\\ n_i)</tex>; cu alte cuvinte, avem <tex>x_i = M_i^{-1}\\ mod\\ n_i</tex>;\r\n*  se determina <tex>x = (a_1 * M_1 * x_1 + a_2 * M_2 * x_2_ + ... + a_k * M_k * x_k)\\ mod\\ n</tex>.\r\n\r\nSa demonstram mai intai ca acesta valoare <tex>x</tex> satisface sistemul. Este necesar ca pentru orice <tex>i \\in \\{1, 2, ..., k\\}</tex>, <tex>x \\equiv a_i(mod\\ n_i)</tex>. Mai exact, trebuie sa fie satisfacuta egalitatea <tex>((a_1 * M_1 * x_1 + a_2 * M_2 * x_2 + ... + a_k * M_k * x_k)\\ mod\\ n)\\ mod\\ n_i = a_i</tex>, <tex>\\forall i \\in \\{1, 2, ..., k\\}</tex>. Datorita faptului ca <tex>n_i | n</tex>, avem <tex>(a_1 * M_1 * x_1 + a_2 * M_2 * x_2 + ... + a_k * M_k * x_k)\\ mod\\ n_i = a_i</tex>. Stim ca <tex>M_i = n / n_i</tex>, <tex>\\forall j \\neq i</tex>, <tex>M_j\\ mod\\ n_i = 0</tex>, deci <tex>\\forall j \\neq i</tex>, <tex>(a_j * M_j * x_j)\\ mod\\ n_i = 0</tex>. Este suficient sa demonstram ca <tex>(a_i * M_i * x_i)\\ mod\\ n_i = a_i \\Leftrightarrow (a_i * (M_i * x_i)\\ mod\\ n_i)\\ mod\\ n_i = a_i</tex>. Folosind <tex>M_i * x_i \\equiv 1 (mod\\ n_i)</tex> ajungem la egalitatea evidenta <tex>a_i = a_i</tex>(q.e.d.)\r\n\r\nMai ramane de verificat daca valoarea <tex>x</tex> este unica. Fie <tex>x\'</tex> o alta solutie; avem <tex>x < n</tex> si <tex>x\' < n</tex>. Daca <tex>x \\equiv a_i (mod\\ n_i)</tex> si <tex>x\' \\equiv a_i (mod\\ n_i)</tex>, <tex>\\forall i \\in \\{1, 2, ..., k\\}</tex>, presupunand ca <tex>x\' < x</tex>, avem <tex>x\'-x \\equiv 0 (mod\\ n_i)</tex>, <tex>\\forall i \\in \\{1, 2, ... k\\}</tex>. Datorita faptului ca numerele <tex>n_i</tex> sunt relativ prime, rezulta ca <tex>x\'-x = k * n</tex>, <tex>k \\in \\mathbb{Z}^*</tex>, deci <tex>x\'-x \\geq n</tex>, ceea ce contrazice ipoteza initiala. Asadar, solutia este unica, asa cum poate fi dedus si din t.c.r. Mai mult, verificand daca se pastreaza corespondenta in cazul aplicarii operatorilor, demonstrarea t.c.r. poate fi usor incheiata.\r\n\r\nPentru calcularea inversului modular al unui numar din <tex>\\mathbb{Z}_n</tex>, de obicei se foloseste \"algoritmul extins al lui Euclid\":http://infoarena.ro/Algoritmul-lui-Euclid. Evident, pentru ca acest invers sa existe, trebuie sa avem <tex>cmmdc(a, n) = 1</tex>. Aplicam algoritmul extins al lui Euclid si determinam <tex>x</tex> si <tex>y</tex> astfel incat <tex>a * x + n * y = 1</tex> si obtinem <tex>a^{-1} = x\\ mod\\ n</tex>; pentru a verifica observam ca egalitatea <tex>a^{-1} = x\\ mod\\ n</tex> este echivalenta cu <tex>a * (x\\ mod\\ n) \\equiv 1 (mod\\ n)</tex> care, la randul sau, este echivalenta cu <tex>a * x \\equiv 1 (mod\\ n)</tex>. Aceasta ultima afirmatie este evident adevarata deoarece avem <tex>a * x + n * y = 1</tex>. Pentru valori mici ale lui <tex>n</tex>, este recomandata preprocesarea \"bruta\" a inverselor tuturor numerelor <tex>a</tex> din <tex>\\mathbb{Z}_n</tex> prime cu <tex>n</tex>, folosind doua structuri repetitive imbricate.\r\n\r\nh2. Rezolvarea sistemelor de ecuatii modulare liniare generale\r\n\r\n\r\nO problema mai generala care ne-ar putea interesa este rezolvarea sistemelor de ecuatii modulare\r\n\r\n<tex>x \\equiv a_1(mod\\ n_1)</tex>\r\n<tex>x \\equiv a_2(mod\\ n_2)</tex>\r\n<tex>...</tex>\r\n<tex>x \\equiv a_k(mod\\ n_k)</tex>\r\n\r\nunde <tex>n_1, n_2, ..., n_k</tex> nu sunt neaparat prime intre ele. Este suficienta generalizarea pentru un sistem de doua ecuatii. Din\r\n<tex>x \\equiv a_1(mod\\ n_1)</tex>\r\n<tex>x \\equiv a_2(mod\\ n_2)</tex>\r\nse va obtine o a treia ecuatie <tex>x \\equiv a_s (mod\\ n_s)</tex> satisfacuta de orice valoare <tex>x</tex> cu proprietatea ca exista <tex>b_1, b_2 \\in \\mathbb{Z}</tex>, astfel incat <tex>x = n_1 * b_1 + a_1 = n_2 * b_2 + a_2</tex>. Pentru oricare astfel de valoare <tex>x</tex>, vom avea:\r\n<tex>x \\equiv a_1 (mod\\ n_1)</tex>\r\nsi\r\n<tex>x \\equiv a_2 (mod\\ n_2)</tex>.\r\nCu alte cuvinte, sistemul si noua ecuatie sunt echivalente.\r\n\r\nDaca deteriminam valoarea <tex>x</tex> minima care satisface sistemul de ecuatii modulare, toate celelalte solutii vor fi obtinute adunand la acesta un multiplu al celui mai mic multiplu comun al numerelor <tex>n_1, n_2, ..., n_k</tex>. Din <tex>n_1 * b_1 + a_1 = n_2 * b_2 + a_2</tex> se obtine <tex>n_1 * b_1 - n_2 * b_2 = a_2 - a_1</tex>. Fie <tex>d = cmmdc(n_1, n_2)</tex>. Aplicand \"algoritmul extins al lui Euclid\":http://infoarena.ro/Algoritmul-lui-Euclid se determina valorile <tex>c_1</tex> si <tex>c_2</tex> astfel incat <tex>n_1 * c_1 + n_2 * c_2 = d</tex>. Amplificand cu <tex>(a_2 - a_1) / d</tex> se obtine: <tex>n_1 * c_1 * (a_2 - a_1) / d + n_2 * c_2 * (a_2 - a_1) / d = a_2 - a_1</tex>. Am putea fi tentati sa credem ca <tex>b_1 = c_1 * (a_2 - a_1) / d</tex> si <tex>b_2 = c_2 * (a_2 - a_1)</tex>, dar aceasta nu este intotdeauna cea mai buna solutie. Fie <tex>h = cmmmc(n_1, n_2)</tex>, valoarea minima pentru care, daca <tex>x</tex> este solutie, atunci si <tex>x + h</tex> este solutie (cu alte cuvinte, <tex>h</tex> este perioada). Notand <tex>l = (a_2 - a_1) / d</tex>, observam ca <tex>n_1 * c_1 * l - n_2 * c_2 * l + k * h - k * h = n_1 * (c_1 * l + k * h / n_1) - n_2 * (c_2 * l + k * h/ n_2)</tex> satisface sistemul. Dorim sa gasim cea mai mica solutie, deci valoarea <tex>c_1 * l + k * h / n_1</tex> trebuie sa fie cat mai mica posibil. Fie <tex>m_1 = c_1 * l + k * h / n_1</tex>, iar <tex>n_1 * m_1 + b_1</tex> cea mai mica valoare care satisface sistemul. Stim ca <tex>n_1 * m_1 + b_1 < h</tex> si exista o singura solutie mai mica decat <tex>h</tex>. Avem <tex>h / n_1 > m_1 \\geq 0</tex>, deci <tex>m_1 = (c_1 * l)\\ mod\\ (h / n_1)</tex>. Sistemul format din cele doua ecuatii este satisfacut pentru valorile <tex>x = cmmmc(n_1, n_2) * i + n_1 * m_1 + b_1</tex>, pentru <tex>i \\geq 0</tex>. Sistemul este astfel echivalent cu <tex>x \\equiv n_1 * m_1 + b_1 (mod\\ cmmmc(n_1, n_2))</tex>.\r\nPentru a rezolva un sistem de ecuatii cu mai mult de doua necunoscute este suficient sa aplicam succesiv operatiile descrise mai sus, reducand perechile de ecuatii la una singura echivalenta, pana cand ramane o singura ecuatie modulara.\r\n\r\nLimbajele de programare evalueaza gresit operatiile de forma $*a mod n*$ , atunci cand $a$ este un numar intreg negativ. Pentru a evita neplacerile ar trebui implementata o functie proprie pentru operatia modulo. Un exemplu este prezentat in continuare:\r\n\r\n==code(c) | \r\nint mod(int a, int n) {\r\n    a %= n;\r\n    if (a < 0) a += n;\r\n    return a;\r\n}\r\n==\r\n\r\nh2. Teorema chineza intr-un sistem de sharing $k$-threshold\r\n\r\nSe considera o informatie secreta codificata intr-un numar foarte mare <tex>N</tex>. Pentru a-l pastra in siguranta, acesta este impartit la <tex>n</tex> servere din tara. Daca <tex>p</tex> servere nu functioneaza, din diverse motive, <tex>N</tex> poate fi recuperat folosind <tex>n-p</tex> servere ramase, atata timp cat <tex>n-p \\geq k</tex>, valoarea threshold.\r\n\r\nAlegand <tex>n</tex> numere prime <tex>p_1, p_2, ..., p_n</tex>, cuprinse intre <tex>N^{1/k}</tex> si <tex>N^{1/(k-1)}</tex>, <tex>N</tex> poate fi determinat folosind exact <tex>k</tex> servere, dar niciodata mai putine. Fiecare server <tex>i</tex> primeste catul si restul impartirii lui <tex>N</tex> la <tex>p_i</tex>. Pentru reconstituire se foloseste _t.c.r_, obtinandu-se astfel valoarea <tex>N</tex> cautata. Acest lucru este posibil deoarece alegand, fara a restrange generalitatea, primele <tex>k</tex> servere, se obtine o solutie modulo <tex>p_1 * p_2 * ... * p_k</tex>. Vom avea intotdeauna <tex>p_i > N^{1/k} * p_1 * p_2 * ... * p_n > N</tex>. Toate solutiile vor fi de forma <tex>x = (p_1 * p_2 * ...  * p_n) * i + x_0</tex>; dat fiind faptul prezentat anterior, ne intereseaza doar solutia cu <tex>i = 0</tex>. Presupunand ca se iau in considerare <tex>r < k</tex> servere, se obtin (din nou fara a restrange generalitatea) solutii de forma <tex>x = (p_1 * p_2 * ...  * p_r)  * i + x_0</tex>. Un adversar care cunoaste <tex>r</tex> secrete poate itera dupa <tex>i</tex>, incercand toate valorile posibile ale lui <tex>x</tex>. Desi initial am putea crede ca solutia va fi gasita usor, alegand o valoare <tex>p_i</tex> mult mai mica decat <tex>N^{1/(k-1)}</tex>, solutia generala va fi de forma <tex>x = M * i + x_0</tex>, unde <tex>M</tex> este mult mai mic decat <tex>N</tex>, aceasta lasand intrusului un numar imens de incercari, iar ghicirea valorii corecte devine practic imposibila.\r\n\r\nh2. Bibliografie\r\n\r\n# Th. Cormen, Ch. Leiserson, R. Rivest, Introduction to Algorithms\r\n# Donald E. Knuth, The Art of Computer Programming vol. 2 - Seminumerical Algorithms\r\n# Sarad A.V aka Data, Applications to Chinese Remainder Theorem\r\n# @***@ \"Internet Problem Solving Contest 2005, Problem G - Gears in Action\":http://ipsc.ksp.sk/contests/ipsc2005/real/problems/g.php\r\n',2044,'public',3685,NULL),('blog/doua-articole-noi','Doua articole noi','2008-01-12 09:47:15','2008-01-12 09:47:21','Membrii comuntatii infoarena au pregatit doua articole noi foarte interesante:\r\n\r\n* \'Teorema chineza a resturilor\':teorema-chineza-a-resturilor\r\n* \'Heavy path decomposition\':heavy-path-decomposition',1,'protected',NULL,NULL),('runda/preoni2008-runda3-5-8/clasament','Clasament preoni2008-runda3-5-8','2008-01-13 18:08:38','2008-01-13 18:08:38','h1. Clasament ==roundparam(round_id=\"preoni2008-runda3-5-8\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda3-5-8\")==',1,'round: preoni2008-runda3-5-8',NULL,NULL),('preoni-2008/runda-3/9','preONI 2008 - Runda 3, Clasa a 9-a','2008-01-13 18:10:39','2008-01-13 18:25:24','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda3-9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-3 \r\n* \'Clasele 5-8\':preoni-2008/runda-3/5-8\r\n*(active) \'Clasa a 9-a\':preoni-2008/runda-3/9 \r\n* \'Clasa a 10-a\':preoni-2008/runda-3/10 \r\n* \'Clasele 11-12\':preoni-2008/runda-3/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-3/5-8\r\n\r\n== roundregister(round_id=\"preoni2008-runda3-9\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda3-9\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda3-9\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-3/9.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"preoni2008-runda3-9\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',1,'round: preoni2008-runda3-9',NULL,NULL),('runda/preoni2008-runda3-9/clasament','Clasament preoni2008-runda3-9','2008-01-13 18:10:39','2008-01-13 18:10:39','h1. Clasament ==roundparam(round_id=\"preoni2008-runda3-9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda3-9\")==',1,'round: preoni2008-runda3-9',NULL,NULL),('preoni-2008/runda-3/10','preONI 2008 - Runda 3, Clasa a 10-a','2008-01-13 18:15:34','2008-01-13 18:30:36','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda3-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-3 \r\n* \'Clasele 5-8\':preoni-2008/runda-3/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-3/9 \r\n*(active) \'Clasa a 10-a\':preoni-2008/runda-3/10 \r\n* \'Clasele 11-12\':preoni-2008/runda-3/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-3/5-8\r\n\r\n== roundregister(round_id=\"preoni2008-runda3-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda3-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda3-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-3/10.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"preoni2008-runda3-10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',1,'round: preoni2008-runda3-10',NULL,NULL),('runda/preoni2008-runda3-10/clasament','Clasament preoni2008-runda3-10','2008-01-13 18:15:34','2008-01-13 18:15:34','h1. Clasament ==roundparam(round_id=\"preoni2008-runda3-10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda3-10\")==',1,'round: preoni2008-runda3-10',NULL,NULL),('preoni-2008/runda-3/11-12','preONI 2008 - Runda 3, Clasele 11-12','2008-01-13 18:16:35','2008-01-13 18:32:57','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda3-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-3 \r\n* \'Clasele 5-8\':preoni-2008/runda-3/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-3/9 \r\n* \'Clasa a 10-a\':preoni-2008/runda-3/10 \r\n*(active) \'Clasele 11-12\':preoni-2008/runda-3/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-3/5-8\r\n\r\n== roundregister(round_id=\"preoni2008-runda3-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda3-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda3-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-3/11-12.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2008-runda3-11-12\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',1,'round: preoni2008-runda3-11-12',NULL,NULL),('runda/preoni2008-runda3-11-12/clasament','Clasament preoni2008-runda3-11-12','2008-01-13 18:16:35','2008-01-13 18:16:35','h1. Clasament ==roundparam(round_id=\"preoni2008-runda3-11-12\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda3-11-12\")==',1,'round: preoni2008-runda3-11-12',NULL,NULL),('preoni-2008/clasament/runda-3/10','preONI 2008 - Clasament Runda 3, Clasa a 10-a','2008-01-13 18:36:43','2008-01-13 18:36:43','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda3-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-3\r\n* \'Clasele 5-8\':preoni-2008/runda-3/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-3/10\r\n* \'Clasele 11-12\':preoni-2008/runda-3/11-12\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-3/5-8\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':preoni-2008/clasament/runda-3/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-3/9\r\n*(active) \'Clasa a 10-a\':preoni-2008/clasament/runda-3/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-3/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda3-10\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2008/runda-3/5-8','preONI 2008 - Runda 3, Clasele 5-8','2008-01-13 18:08:38','2008-01-13 18:23:31','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda3-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-3 \r\n*(active) \'Clasele 5-8\':preoni-2008/runda-3/5-8 \r\n* \'Clasa a 9-a\':preoni-2008/runda-3/9 \r\n* \'Clasa a 10-a\':preoni-2008/runda-3/10 \r\n* \'Clasele 11-12\':preoni-2008/runda-3/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-3/5-8\r\n\r\n== roundregister(round_id=\"preoni2008-runda3-5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda3-5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda3-5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-3/5-8.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"preoni2008-runda3-5-8\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',1,'round: preoni2008-runda3-5-8',NULL,NULL),('preoni-2008/clasament/runda-3/5-8','preONI 2008 - Clasament Runda 3, Clasele 5-8','2008-01-13 18:34:11','2008-01-13 18:34:11','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda3-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-3\r\n* \'Clasele 5-8\':preoni-2008/runda-3/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-3/10\r\n* \'Clasele 11-12\':preoni-2008/runda-3/11-12\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-3/5-8\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasele 5-8\':preoni-2008/clasament/runda-3/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-3/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-3/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda3-5-8\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2008/clasament/runda-3/9','preONI 2008 - Clasament Runda 3, Clasa a 9-a','2008-01-13 18:35:48','2008-01-13 18:35:48','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda3-9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-3\r\n* \'Clasele 5-8\':preoni-2008/runda-3/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-3/10\r\n* \'Clasele 11-12\':preoni-2008/runda-3/11-12\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-3/5-8\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':preoni-2008/clasament/runda-3/5-8\r\n*(active) \'Clasa a 9-a\':preoni-2008/clasament/runda-3/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-3/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-3/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda3-9\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('utilizator/radoo','Profil radoo','2008-01-14 13:17:03','2008-01-14 13:17:03','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',7448,'public',NULL,NULL),('programare-dinamica','programare-dinamica','2008-01-16 00:11:20','2008-01-16 00:11:20','h1. Programare dinamica\r\n\r\n* parantezare optima de matrici\r\n* cel mai lung subsir crescator\r\n* knapsack\r\n* cel mai lung subsir comun\r\n* ciclu hamiltonian in $O(n^2^ * 2^n^)$\r\n* dinamicile in 3^n^\r\n* arbore de cautare optim\r\n* numarul posibilitatilor de acoperire a unei table cu dominouri\r\n\r\n\r\n\'tutorial de pe topcoder\':http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg\r\n',15,'public',NULL,NULL),('newsletter/preoni-2008/runda-3','preONI 2008, Runda 3, interviu Radu Berinde & Octavian Costache','2008-01-18 00:16:28','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nAm multe noutati pentru tine!  Aseaza-te comod si citeste pana\r\nla capat.\r\n\nPentru inceput, te invit sa participi la Runda #3, preONI 2008!\r\n\npreONI este concursul cu premii mari si finala live care te\r\npregateste pentru Olimpiada Nationala de Informatica.\r\nAnul acesta, elevii de gimnaziu participa la o grupa de varsta\r\nseparata si au locuri rezervate la runda finala.\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Runda #3 se desfasoara...\r\n\np{padding-left: 2em;}. Duminica, 20 ianuarie 2008, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nVezi pagina concursului: \'preoni-2008\':preoni-2008\r\n\nh2.  Atentie! Concurs cu rating! \n\nDaca vrei sa ti se modifice rating-ul in urma participarii la aceasta\r\nrunda trebuie sa iti anunti participarea din timp.  Intra pe\r\n\'preoni-2008\':preoni-2008 si inscrie-te la Runda #3.\r\n\nPoti sa participi la concurs chiar si daca nu te-ai inscris in\r\nprealabil insa nu ti se va modifica rating-ul.\r\n==NewsletterRating(username=\"%username%\")==\r\nCiteste despre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Interviuri noi pe blog! \n\nCosmin te asteapta pe blog-ul infoarena cu doua interviuri noi si\r\nspectaculoase!  De data aceasta, oaspetii lui sunt sunt Radu Berinde\r\nsi Octavian Costache (aka Vivi).\r\n\nCiteste interviurile si vino pe forum sa stam de vorba!\r\n\nRadu Berinde\r\n\np{padding-left: 2em;}. Radu este unul din putinii romani cu doua medalii de aur la\r\n    olimpiada internationala de informatica.  Multi au invatat\r\n    din sursele lui ingenioase si din \"smenurile\" lui de\r\n    implementare.  Acum studiaza la MIT, iar vara trecuta a facut al\r\n    doilea internship la Google.  (Cosmin) Am avut ocazia sa lucrez\r\n    cu el pe acelasi proiect si m-a impresionat prin o gramada de\r\n    idei bune si viteza cu care scrie cod elegant si util.\r\n    Radu ne povesteste ceva din experienta lui legata de olimpiade si\r\n    concursuri, despre MIT, Google, masini si despre cat impinge la\r\n    piept.\r\n\np{padding-left: 2em;}. Interviu Radu Berinde, Partea I\r\n    \'blog/interviu-radu-berinde-partea-intai\':blog/interviu-radu-berinde-partea-intai\r\n\np{padding-left: 2em;}. Interviu Radu Berinde, Partea I\r\n    \'blog/interviu-radu-berinde-partea-a-doua\':blog/interviu-radu-berinde-partea-a-doua\r\n\nOctavian Costache\r\n\np{padding-left: 2em;}. Vivi insemneaza pe CV-ul propriu o gramada de realizari variate:\r\n    4 premii la Internetics, premii la olimpiadele de informatica,\r\n    premiant si apoi organizator la InfoEducatie.  A realizat\r\n    impreuna cu Irina Dumitrascu site-ul doizece.ro, cel mai mare\r\n    site de jocuri online din Romania, vandut ulterior companiei\r\n    Neogen.  Este angajat la Google in New York.  Scrie unul dintre\r\n    cele mai populare blog-uri din Romania (\'http://vivi.ro/blog/\':http://vivi.ro/blog/).\r\n    A fost asistent la cursuri de algoritmica la UPB si instructor la\r\n    cursuri Cisco.  Tot Vivi a fost printre initiatorii ONI by Net -\r\n    partea online a olimpiadei nationale de informatica.\r\n    Vivi imparte cu noi cateva sfaturi si idei despre facultate,\r\n    freelancing, Google, blogging si programare.\r\n\np{padding-left: 2em;}. Interviu Vivi, Partea I\r\n    \'blog/interviu-octavian-costache-partea-intai\':blog/interviu-octavian-costache-partea-intai\r\n\np{padding-left: 2em;}. Interviu Vivi, Partea II\r\n    \'blog/interviu-octavian-costache-partea-a-doua\':blog/interviu-octavian-costache-partea-a-doua\r\n\nAlte interviuri luate de Cosmin si pe care le poti gasi pe blog:\r\nCatalin Francu, Mihai Patrascu, Mircea Pasoi si Lazar Codrut.\r\n\nBlog-ul infoarena ( \'blog\':blog ) poate fi urmarit\r\nsi via RSS.  URL-ul pentru feed este:\r\n\'blog\':blog?action=rss\r\n\nh2.  Avem articole noi! \n\nMembrii comunitatii infoarena au adaugat doua articole noi\r\npentru tine.\r\n\np{padding-left: 2em;}. *   Teorema Chineza a Resturilor\r\n        \'teorema-chineza-a-resturilor\':teorema-chineza-a-resturilor\r\n        Autor: Adrian Vladu, transcris de Marginean Ciprian\r\n\np{padding-left: 2em;}. *   Heavy Path Decomposition\r\n        \'heavy-path-decomposition\':heavy-path-decomposition\r\n        Autor: Marius Stroe\r\n\nCiteste-le.  Te asteptam pe forum cu sugestii si intrebari.\r\n\nh2.  Concursul preONI \n\npreONI, concursul de marca al comunitatii infoarena, este dedicat\r\nelevilor de liceu si gimnaziu ce se pregatesc pentru Olimpiada\r\nNationala de Informatica.\r\n\nConcursul este impartit in 4 grupe de varsta:  clasele V-VIII, clasa\r\na IX-a, clasa a X-a si clasele XI-XII.  Se organizeaza 4 runde online\r\nde calificare.  In urma acestora, cei mai buni de la fiecare grupa\r\nsunt invitati la o runda finala.\r\n\nIn cadrul unei runde vei avea de rezolvat 3 probleme in 4 ore.\r\nProblemele sunt de natura algoritmica si de dificultate similara\r\ncelor de la ONI.\r\n\nOferim premii substantiale acelor concurenti care se claseaza pe\r\nprimele locuri la runda finala.\r\n\nEditia 2008 a concursului preONI se desfasoara sub atenta\r\nsupraveghere a lui Mircea Pasoi, in calitate de director de concurs.\r\n\nPe pagina oficiala ( \'preoni-2008\':preoni-2008 ) vei gasi\r\ninformatii despre cum participi, cine propune probleme, premii,\r\nregulamentul concursului samd.\r\n\npreONI 2008 este organizat in parteneriat cu Adobe Romania si\r\nsprijinit de catre iRealSoft.\r\n\nh2.  Runda #2 \n\nS-a desfasurat pe 16 decembrie 2007.\r\n\nPoti vedea rezultatele aici: \r\n\'preoni-2008/clasament/runda-2/11-12\':preoni-2008/clasament/runda-2/11-12\r\n\niar solutiile oficiale aici:\r\n\'preoni-2008/runda-2/solutii\':preoni-2008/runda-2/solutii\r\n\nTe asteptam la Runda #3!\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nRamai alaturi de noi.  Te ajutam sa devii olimpic!\r\nEchipa infoarena iti ureaza succes!\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('preoni-2008/runda-3/solutii/fructe','preoni-2008/runda-3/solutii/fructe','2008-01-20 12:20:04','2008-01-22 18:24:18','h2(#fructe). \'Fructe\':problema/fructe\r\n\r\nSe observa ca indiferent de fructele pe care Miruna le mananca, paritatea numarului de banane ramane aceeasi. De aici putem concluziona ca ultimul fruct va fi o banana daca initial aveam un numar impar de banane, si o portocala in caz contrar.',2028,'public',NULL,NULL),('preoni-2008/runda-3/solutii/restante','preoni-2008/runda-3/solutii/restante','2008-01-20 12:22:09','2008-01-22 11:19:12','h2(#restante). \'Restante\':problema/restante\r\n\r\nPentru fiecare cuvant ii sortam literele in ordine crescatoare. Apoi sortam toate cuvintele in ordine crescatoare. Daca doua cuvinte alaturate din lista de cuvinte sortate sunt egale este clar ca aceste cuvinte nu sunt originale. Dupa sortare putem afla deci in $O(N)$ usor cuvintele care sunt originale, parcurgand lista de cuvinte pas cu pas. Pentru sortare trebuie folosit un algoritm rapid, de exemplu quicksort pentru a obtine complexitatea $O(N*L*logN)$, unde $L$ este lungimea maxima a unui cuvant, in cazul nostru $16$.\r\n',2092,'public',NULL,NULL),('preoni-2008/runda-3/solutii/piese','preoni-2008/runda-3/solutii/piese','2008-01-20 12:23:42','2008-01-22 14:30:42','h2(#piese). \'Piese\':problema/piese\r\n\r\nComplexitatea optima este {$O(M * N)$} si obtine $100$ de puncte. Solutia oficiala se bazeaza pe o abordare recursiva: fie {$f(x{~1~}, y{~1~}, x{~2~}, y{~2~})$} functia care acopera cu un numar minim de piese submatricea de colturi {$(x{~1~}, y{~1~})$}, {$(x{~2~}, y{~2~})$}. Intuitiv, numarul minim de piese pentru aceasta submatrice se obtine daca in {$(x{~1~}, y{~1~})$} asezam piesa cu latura maxim posibila. Latura maxima este egala cu cel mai mare numar natural $k$ astfel incat {$2^k^ &le; minim(x{~2~}-x{~1~}+1, y{~2~}-y{~1~}+1)$}. Dupa ce am asezat piesa de latura $k$ pe tabla, apelam recursiv {$f(x{~1~}, y{~1~}+2^k^, x{~1~}+2^k^-1, y{~2~})$} si {$f(x{~1~}+2^k^, y{~1~}, x{~2~}, y{~2~})$}. Apelarea este corecta deoarece, din metoda de constructie a functiei $f$ stim sigur ca nu va exista o piesa care sa aiba simultan patratele in submatricile {$(x{~1~}, y{~1~}+2^k^)$},{$(x{~1~}+2^k^-1, y{~2~})$} si {$(x{~1~}+2^k^, y{~1~})$},{$(x{~2~}, y{~2~})$}.',256,'public',NULL,NULL),('preoni-2008/runda-3/solutii/partitie','preoni-2008/runda-3/solutii/partitie','2008-01-20 12:24:08','2008-01-20 12:54:06','h2(#partitie). \'Partitie\':problema/partitie\r\n\r\nPutem reformula problema astfel: se dau $N$ puncte coliniare (putem sa consideram punctele ca fiind pe axa Ox), fiecare punct avand o coordonata. Trebuie sa coloram punctele cu numar minim de culori astfel incat intre oricare doua puncte colorate la fel sa fie cel putin distanta {$D$}.\r\n\r\n_Lema_: Fie un segment $AB$ de lungime $D-1$ care sa contina un numar maxim de puncte din cele date. Fie $MAX$ numarul de puncte de pe segmentul {$AB$}. $MAX$ este numarul minim de culori cerut.\r\n\r\nEste evident ca nu putem folosi mai putin de $MAX$ culori. Daca am folosi mai putine culori ar exista (conform principiului cutiei) in segmentul $AB$ doua puncte colorate la fel, dar aceste doua puncte s-ar afla la mai putin de $D$ unitati distanta. In concluzie, numarul minim de culori este cel putin {$MAX$}.\r\nVom demonstra ca exista o constructie cu $MAX$ culori. Avand punctele sortate in functie de coordonata lor, le coloram astfel: $1 2 3 ... MAX 1 2 3 ... MAX 1 2 ...$. De exemplu, pentru $N = 11$ si {$MAX = 3$}, cele $11$ puncte vor fi colorate astfel: ({$1 2 3 1 2 3 1 2 3 1 2$}). Se observa ca intre oricare doua puncte colorate la fel (inclusiv capetele) exista cel putin $MAX+1$ puncte si deci distanta dintre ele va fi sigur mai mare sau egala cu $D$, deoarece, in caz contrar, ar exista un segment de lungime $D-1$ care sa contina cel putin $MAX+1$ puncte - evident fals, din moment ce am presupus ca $MAX$ este numarul maxim de puncte de pe un segment de lungime {$D-1$}.\r\n\r\nAsadar, pentru a rezolva problema trebuie sa gasim segmentul $AB$ de lungime $D-1$ care contine un numar maxim de puncte din cele date in interior si vom colora punctele dupa cum s-a prezentat mai sus. Segmentul $AB$ va avea capatul din stanga ( mai mic ) intr-unul din cele $N$ puncte. In caz contrar, $AB$ ar putea fi translatat spre dreapta pana punctul $A$ ajunge peste unul din punctele date si, in acest caz, $AB$ ar contine un numar mai mare sau egal de puncte decat initial. Fie $C$ vectorul de coordonate. Daca avem acest vector sortat crescator, pentru fiecare $i$ trebuie sa gasim acel indice maxim $j &ge; i$ astfel incat {$C{~j~}-C{~i~}$} &le; {$D-1$}, iar, in final, $MAX$ va fi maximul dintre valorile de forma {$j-i+1$}. Pentru ca acest pas sa aiba complexitatea {$O(N)$}, in momentul in care cautam indicele $j$ pentru indicele curent $i$ nu vom incepe cautarea de la $i$, ci de la $j$-ul obtinut anterior.\r\n\r\nComplexitatea solutiei prezentate este {$O(Nlog{~2~}N)$}, iar complexitatea dupa sortare este {$O(N)$}. Algoritmul descris obtine $100$ de puncte.\r\n',256,'public',NULL,NULL),('preoni-2008/runda-3/solutii/gardieni','preoni-2008/runda-3/solutii/gardieni','2008-01-20 12:24:47','2008-01-22 15:03:51','h2(#gardieni). \'Gardieni\':problema/gardieni\r\n\r\nProblema cere ca, dandu-se $N$ intervale si un cost pentru fiecare interval, sa asociem fiecarui moment $x$ din {$[1, T]$} exact un interval din cele $N$ care sa contina momentul $x$. Costul pentru $x$ va fi costul intervalului asociat. Trebuie sa gasim acea asociere care minimizeaza suma costurilor tuturor momentelor de la $1$ la {$T$}. \r\nProblema se rezolva prin metoda greedy: fiecarui moment $i$ de la $1$ la $T$ ii vom asocia intervalul de cost minim ce il contine pe $i$. O prima solutie (neeficienta) are complexitatea {$O(T * N)$}. Pseudocodul este prezentat mai jos:\r\n\r\n==code(c)|Cost_Total = 0\r\npentru fiecare moment i de la 1 la T\r\n       minim = INFINIT // o valoare foarte mare\r\n       pentru fiecare interval i de capete x[i] si y[i]\r\n              daca (x[i] <= i) si (i <= y[i]) si (c[i] < minim)\r\n                    minim = c[i]\r\n       Cost_Total = minim \r\n==\r\n\r\nDatorita restrictiei ca numarul maxim de intervale care se intersecteaza este maxim 10, stim ca suma lungimilor intervalelor este maxim {$10*T$}, deci {$(y{~1~}-x{~1~}+1) + (y{~2~}-x{~2~}+1) +  ... + (y{~N~}-x{~N~}+1) &le; 10*T$}. Pseudocodul de mai jos, desi aparent are complexitatea tot {$O(T * N)$}, are complexitatea reala {$O(T)$}, de constanta de 10:\r\n\r\n==code(c)|\r\n// minim[i] = costul minim al unui interval ce contine punctul i\r\npentru fiecare moment i de la 1 la T\r\n       minim[i] = INFINIT // o valoare foarte mare\r\npentru fiecare interval i (x[i], y[i]) de cost c[i]\r\n       pentru fiecare moment j de la x[i] la y[i]\r\n              daca c[i] < minim[j]\r\n                   minim[j] = c[i]\r\nCost_Total = 0\r\npentru fiecare moment i de la 1 la T\r\n       Cost_Total = Cost_Total + minim[i]\r\n==\r\n\r\nAceasta abordare obtine 100 de puncte.\r\nExista si o solutie de complexitate {$O(Nlog{~2~}N)$} care are avantajul ca rezolva problema pe cazul general, in care nu exista nicio restrictie asupra numarului maxim de intervale care se intersecteaza. Aceasta abordare foloseste procedeul numit \'baleiere\':http://en.wikipedia.org/wiki/Sweep_line_algorithm si o structura de date numita \"heap\":heap. Daca nu descoperiti singuri ideea din spatele acestei abordari puteti sa intrebati pe \'forum\':forum/index.php?topic=2604.0.\r\n\r\n[heap]http://en.wikipedia.org/wiki/Heap_(data_structure)',256,'public',NULL,NULL),('preoni-2008/runda-3/solutii/xerox','preoni-2008/runda-3/solutii/xerox','2008-01-20 12:25:34','2008-01-21 10:40:24','h2(#xerox). \'Xerox\':problema/xerox\r\n\r\nPe baza urmatoarelor observatii, vom reduce problema la a rezolva jocul NIM:\r\n\r\n* Pentru o foaie data, pozitiile punctelor nu conteaza. Intr-adevar, atat timp cat punctele sunt distincte, vom putea duce intotdeauna o curba inchisa, suficient de subtire, pe langa celelelalte puncte.\r\n* Considerand o foaie cu $N$ puncte, dupa selectarea unei curbe, vom putea lasa celuilalt jucator o foaie cu $0$, $1$, ..., sau $N-1$ puncte. Acest lucru se poate face trasand curba prin $N$, $N-1$, ..., respectiv $1$ punct. Asadar, dintr-o stare cu $N$ puncte, putem ajunge in oricare din starile $0$, $1$, ..., $N-1$.\r\n* Prin obtinerea unei stari din alta, putem rearanja punctele pe foaie (am observat ca pozitiile punctelor nu conteaza). Asadar, geometria foii nu conteaza, chiar daca dupa selectare forma dreptunghiului se distruge.\r\n* Dintr-o stare cu $N$ puncte se poate ajunge si in alte stari prin scindarea foii in alte doua, selectand pe o curba $i$ puncte, ingloband in interiorul ei alte $j$ puncte si lasand in afara ei restul de $N-i-j$. Totusi, nu vom face astfel de scindari, fiind suficiente observatiile de la punctul 2.\r\n\r\nProblema devine: avem $N$ foi (gramezi), fiecare cu cate un numar $M{~i~}$ de puncte (pietre) pe (in) ea. Fiecare foaie (gramada) cu $M{~i~}$ puncte (pietre) poate ajunge intr-o stare cu $0$, $1$, ..., sau $M{~i~}-1$ puncte (pietre) prin trasarea unei curbe prin (luarea unui numar de) puncte (pietre). Aceasta este chiar problema jocului NIM.',1,'public',NULL,NULL),('preoni-2008/runda-3/solutii/inundatii','preoni-2008/runda-3/solutii/inundatii','2008-01-20 12:25:16','2009-01-23 21:32:33','h2(#inundatii). \'Inundatii\':problema/inundatii\r\n\r\nO prima observatie necesara in rezolvarea problemei este urmatoarea: putem rezolva problema independent pentru valorile $X$, $Y$ si $Z$ datorita  functiei de distanta. Astfel, avem de rezolvat de fapt urmatoarea problema: Se da un sir de $N$ numere intregi $A{~1~},A{~2~}...A{~N~}$ cu $A{~i~} > A{~i+1~}$, sa se gaseasca un sir de numere intregi $B{~1~},B{~2~}...B{~N~}$ cu $B{~i~} < B{~i+1~}$ care minimizeaza suma $|A{~i~}-B{~i~}|$. Vom rezolva astfel aceasta problema pentru $X, Y$ si $Z$, la final adunand rezultatele.\r\nVom mai simplifica un pic problema, inlocuind restrictia $B{~i~} < B{~i+1~}$ cu $B{~i~} &le; B{~i+1~}$ astfel: scadem din $A{~i~}$ valoarea $i$, rezolvam pentru $&le;$, si la final adunam $i$ la loc in $A$ si $B$.\r\nExemplu:\r\n\r\n* $A = (10, 7, 4, 1)$\r\n* Scadem $i$ si obtinem $A = (9, 5, 1, -3)$\r\n* Gasim un $B$ optim care respecta $B{~i~} &le; B{~i+1~}$. Sunt mai multe solutii posibile, vom lua $B = (5, 5, 5, 5)$\r\n* Adunam la loc $i$ si obtinem ca solutia este $B = (6, 7, 8, 9)$\r\n\r\nSe poate observa ca pentru a obtine rezultat optim pentru problema simplificata, $B$ va avea valori egale. Daca privim valorile din $A$ si valoarea din $B$ pe care o cautam ca puncte pe axa, putem recunoaste problema clasica \'a oficiului postal in 1 dimenisune\':http://foldoc.org/?post+office+problem (se gaseste si in Cormen la capitolul de Statistici si ordine). Putem trage imediat concluzia ca valoarea din $B$ pe care o cautam va fi mediana lui $A$ (nu conteaza pe care o luam cand $N$ e par). Valorile din $A$ sunt sortate descrescator (si dupa scadere), deci putem determina mediana in $O(1)$. \r\n\r\nO solutie alternativa foloseste \"cautare ternara\":http://en.wikipedia.org/wiki/Ternary_search in $O(N*log{~1.5~}(N))$. Pentru sirul $A$ de mai sus fie functia $f:[A{~N~}, A{~1~}] -> R$, cu $f(x)$ costul obtinerii din inegalitatile $A{~1~} > .. > A{~i~} >= x >= A{~i+1~} > .. > A{~N~}$ pe urmatoarele $A{~1~} < .. < A{~i~} <= x <= A{~i+1~} < .. < A{~N~}$ cu $A{~2~} = A{~1~} + 1, .. A{~N~} = A{~1~} + (N-1)$ pentru minimalitate. Functia $f$ indeplineste proprietatea necesara pentru aplicarea cautarii ternare: exista un $X$ astfel inca functia descreste pe intervalul $[A{~N~}, X]$ si isi schimba monotonia pe $[X, A{~1~}]$. Pentru determinarea acestui punct folosim cautarea ternara si in final rezultatul va fi $f(X)$.\r\n',2092,'public',NULL,NULL),('preoni-2008/runda-3/solutii/stergeri','preoni-2008/runda-3/solutii/stergeri','2008-01-20 12:23:06','2008-01-23 15:26:53','h2(#stergeri). \'Stergeri\':problema/stergeri\r\n\r\nSa presupunem ca dupa ce am efectuat toate stergerile am ramas cu valorile $X{~1~}, X{~2~} .. X{~k~} .. X{~p~}$. Ne intereseaza ce valoare are $X{~k~}$ (initial $X{~k~}=k$). Vom considera ordinea inversa a operatiilor, adica plecand de la aceste valori acum nu vom mai face stergeri, vom face inserari de intervale. Altfel spus, in loc sa ne intrebam ce element e pe pozitia $K$ dupa $M$ stergeri, vom afla pe ce pozitie va ajunge al $K$-lea element dupa $M$ inserari. Daca capatul stanga al unui interval ce trebuie inserat se afla in stanga lui $X{~k~}$ atunci $X{~k~}$ va trebui deplasat la dreapta cu $L$ unitati ({$L$} este lungimea intervalului), altfel $X{~k~}$ va ramane neschimbat. Astfel, dupa ce s-au efectuat toate inserarile, daca $X{~k~}$ se va afla pe pozitia $T$ este clar ca $T$ este raspunsul la problema noastra.',2092,'public',NULL,NULL),('preoni-2008/runda-3/solutii','Solutii preONI 2008, Runda 3','2008-01-20 12:19:34','2008-01-22 22:19:21','==include(page=\"template/preoni-2008/header\")==\r\n\r\nh1. Solutii preONI 2008, Runda 3\r\n\r\nRunda a 3-a a concursului preONI 2008 s-a incheiat. Acest articol va prezenta solutiile celor 9 probleme propuse spre rezolvare si cateva aprecieri pe marginea desfasurarii probei de duminica dimineata. \r\n\r\nCa de obicei, concurentii au avut de rezolvat 3 probleme de dificultate variata. Noi am considerat aceasta runda ca fiind mai usoara decat precedentele doua, iar acest lucru s-a putut observa in punctajele obitinute. Multi concurenti au recuperat inainte de ultima batalie pentru cele 10 locuri la Marea Finala preONI 2008.\r\n\r\nIn fruntea clasamentului de la gimnaziu gasim 2 concurenti cu 280 de puncte: \'Radu Voroneanu\':utilizator/radu_voroneanu si \'Andrei Purice\':utilizator/protoman. Pe ultimul loc al podiumului, la 30 de puncte in spatele primilor clasati, il gasim pe \'Serban Andrei Stan\':utilizator/savim. In clasamentul general cei din frunte pot sta linisiti inainte de runda a 4-a, insa lucrurile sunt foarte neclare spre ultimele locuri calificante, cu punctaje stranse si multi concurenti avand sanse de calificare. Problemele au fost destul de usoare, cu multe punctaje de 100. Probabil ca daca unul din primii doi ar fi implementat quicksort la problema medie \'Restante\':problema/restante, am fi asistat la un punctaj maxim :). Mai ramane de precizat faptul ca problema grea, \'Stergeri\':problema/stergeri, a fost cea care a facut diferenta, ea fiind rezolvata corect doar de primii 3 concurenti clasati.\r\n\r\nSpre deosebire de runda anterioara, de aceasta data punctajele la clasa a 9-a au fost mai mici. In fruntea clasamentului este \'Ioana Pandele\':utilizator/ioanna. Nu putem sa nu remaracam rezultatele extraordinare pe care le-a obtinut la editia preONI 2008, mai ales avand in vedere ca nu a rezolvat nici macar o problema pe infoarena (cel putin nu de pe acest cont :P). Pe locurile 2 si 3 gasim medaliatii Romaniei cu aur la JBOI 2007, \'Victor Ionescu\':utilizator/vanila_cpp si \'Vlad Tataranu\':utilizator/tvlad. Un lucru foarte interesant este faptul ca niciun concurent de la clasa a 9-a nu a rezolvat problema usoara, \'Restante\':problema/restante. Acest lucru probabil ca se datoreaza limitei stranse de timp, care nu permitea solutiilor neoptimizate ce nu foloseau quicksort sa obtina punctajul maxim. Problema medie \'Piese\':problema/piese a fost rezolvata de 3 concurenti, iar cea grea, \'Partitie\':problema/partitie, doar de Ioana.\r\n\r\nLa clasa a 10-a, \'Bogdan Tataroiu\':utilizator/bogdan2412 a fost foarte aproape de a obtine punctajul maxim. Probabil ca daca ar fi implementat solutia simpla la \'Gardieni\':problema/gardieni si nu s-ar fi complicat, reducand complexitatea dar marind constanta, ar fi luat 300 de puncte. In spatele lui, foarte aproape, s-a clasat \'Bogdan Casu-Pop\':utilizator/bogdanhm999 cu 280 de puncte, iar pe 3 il gasim pe \'Istvan Hevele\':utilizator/h_istvan. Am avut parte de un set echilibrat de problemele, iar punctajele concurentilor au fost destul de bune. In clasamentul general observam ca punctajele din jurul locului 10 sunt destul de mici, probabil ca un rezultat foarte bun in ultima runda ar putea sa asigure calificarea chiar si unuia dintre concurentii clasati momentan pe locurile codase.\r\n\r\nSalutam primul punctaj de 300 de puncte la editia preONI din acest an obtinut de \'Cosmin Gheorghe\':utilizator/gcosmin. Pe locul 2 s-a clasat \'Victor Rusu\':utilizator/victorsb cu 260 de puncte, iar locul 3 este impartit de \'Paul Baltescu\':utilizator/pauldb si de \'Florin Pogocsan\':utilizator/binary_fire. Setul de probleme a fost accesibil, iar punctajele au fost cele mai mari de pana acum, 10 concurenti obtinand cel putin 200 de puncte. Se observa detasarea primilor 3 la general, insa si la aceasta grupa calificarea se joaca in ultima runda.\r\n\r\n\'Echipa infoarena\':echipa-infoarena ii felicita pe toti participantii si le ureaza bafta in continuare!\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Fructe\':preoni-2008/runda-3/solutii#fructe\r\n* \'Restante\':preoni-2008/runda-3/solutii#restante\r\n* \'Stergeri\':preoni-2008/runda-3/solutii#stergeri\r\n* \'Piese\':preoni-2008/runda-3/solutii#piese\r\n* \'Partitie\':preoni-2008/runda-3/solutii#partitie\r\n* \'Gardieni\':preoni-2008/runda-3/solutii#gardieni\r\n* \'Inundatii\':preoni-2008/runda-3/solutii#inundatii\r\n* \'Xerox\':preoni-2008/runda-3/solutii#xerox\r\n* \'Strazi\':preoni-2008/runda-3/solutii#strazi\r\n\r\n==include(page=\"preoni-2008/runda-3/solutii/fructe\")==\r\n\r\n==include(page=\"preoni-2008/runda-3/solutii/restante\")==\r\n\r\n==include(page=\"preoni-2008/runda-3/solutii/stergeri\")==\r\n\r\n==include(page=\"preoni-2008/runda-3/solutii/piese\")==\r\n\r\n==include(page=\"preoni-2008/runda-3/solutii/partitie\")==\r\n\r\n==include(page=\"preoni-2008/runda-3/solutii/gardieni\")==\r\n\r\n==include(page=\"preoni-2008/runda-3/solutii/inundatii\")==\r\n\r\n==include(page=\"preoni-2008/runda-3/solutii/xerox\")==\r\n\r\n==include(page=\"preoni-2008/runda-3/solutii/strazi\")==\r\n',2028,'public',NULL,NULL),('winter-challenge-2008/runda-2/solutii/sn','winter-challenge-2008/runda-2/solutii#sn','2008-02-24 10:20:07','2008-03-10 20:22:37','h2(#sn). \'Siguranta Nationala\':problema/sn\r\n\r\nProblema se rezolva prin metoda Greedy. Se parcurge in ordinea crescatoare a capetelor stanga tinand $2$ variabile $Rss$ si $Rsa$:\r\n\r\n* $Rss$ - tot intervalul $[1,Rss]$ este acoperit de rachete \'sol-sol\'\r\n* $Rsa$ - tot intervalul $[1,Rsa]$ este acoperit de rachete \'sol-aer\'\r\n\r\nLa pasul $i$ avem urmatoarele cazuri (presupunem ca $Rss &le; Rsa$):\r\n\r\n# {$B{~i~}$} &le; $Rss$, in acest caz nu conteaza de ce tip va fi considerat intervalul $i$, deoarece toate punctele din $[1,{$B{~i~}$}]$ au fost acoperite anterior\r\n# {$B{~i~}$} > $Rss$, in acest caz intervalul va fi de tip \'sol-aer\', iar $Rsa$ va primi valoarea {$B{~i~}$}.\r\n\r\nDin pacate limitare memoriei facea imposibila stocarea intervalelor. Din fericire ele erau deja sortate, deci se puteau preprocesa pe parcursul citirii. De asemenea, cand se stabilea tipul unui interval se afisa in fisierul de iesire.\r\n\r\nAstfel algoritmul foloseste $O(1)$ memorie si are complexitatea $O(n)$.',1231,'public',NULL,NULL),('propuneri/6-arhiva-educationala','IAP #6: Arhiva educationala','2008-01-22 12:43:54','2008-04-26 12:34:43','h1. IAP #6: Arhiva educationala\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2008-01-22 |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"domino\")== |\r\n|_. Stare     | *_APROBAT_* |\r\n\r\n(toc)*{text-align:center;} *Continut*\r\n* \'Abstract\':propuneri/6-arhiva-educationala#abstract\r\n* \'Motivatie\':propuneri/6-arhiva-educationala#motivatie\r\n* \'Detalii\':propuneri/6-arhiva-educationala#detalii\r\n* \'Implementare\':propuneri/6-arhiva-educationala#implementare\r\n* \'Feedback\':propuneri/6-arhiva-educationala#feedback\r\n\r\nh2(#abstract). Abstract\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie.\r\n\r\nh2(#motivatie). Motivatie\r\n\r\nDesi \'arhiva\':arhiva contine un numar impresionant de probleme (600+) si este in crestere, cei incepatori in concursurile de algoritmica de obicei nu gasesc aceste probleme foarte folositoare deoarece nu stiu sa le rezolve, sunt prea grele, nu stiu de ce iau 0, TLE, etc. \r\nAsadar se simte lipsa unor probleme elementare, care sa indrume un incepator prin documentatie si acces liber la teste si la sursele celorlati utilizatori. \r\nDe asemenea, dupa ce un utilizator citeste un \'articol\':articole pe infoarena sau pe \'alte site-uri\':links despre un algoritm, cea mai la indemana metoda de a vedea cat de bine a inteles ce-a citit este sa rezolve probleme care folosesc acele notiuni. Acest lucru nu este intotdeauna asa de usor, deoarece de obicei nu exista probleme care sa se poata rezolva aplicand acel algoritm in starea pura. \r\nSpre exemplu, cineva care abia a invatat algoritmul Ford-Fulkerson de flux, ar avea nevoie de o problema in care sa se ceara pur si simplu determinarea unui flux maxim intr-o retea, fara alte complicatii.\r\n\r\nh2(#detalii). Detalii\r\n\r\n* Titlul problemelor vor reprezenta algoritmul care se cere (Ex: \'Flux maxim\', \'Dijkstra cu heap-uri\', \'Ungar\', etc.)\r\n* Enuntul problemei va prezenta direct ce se cere, fara povesti sau alte vrajeli. Sunt incurajate enunturi de forma: \"Se da un graf neorientat $G$ cu $N$ noduri si $M$ muchii ...\".\r\n* Desi nu este obligatoriu, se recomanda ca enunturile sa aiba si link-uri la documentatia necesara pentru a invata algoritmul cu care se rezolva. \r\n* Oricine va putea vedea testele problemei uitandu-se la atasamente. (Nu trebuie sa fii logat)\r\n* Oricine va putea vedea sursele trimise pana acum la orice problema. (Nu trebuie sa fii logat)\r\n* _Feedback(Silviu)_ Pe cat posibil, evaluatorele de la problema asta sa dea informatii despre motivul pentru care a picat un test. De exemplu, pentru o problema in care se cere afisarea unui numar sa se afiseze ceva de genu: \"Ai afisat: x, Raspunsul corect: y\". Pentru chestii mai complexe unde sunt teste cu anumite particularitati merge un README care descrie testele sau afisate mesaje despre test. Ma gandesc la ceva de genu: \"Raspus gresit. In acest test se verifica faptul ca ...\".\r\n\r\nh2(#implementare). Implementare\r\n\r\n* Efortul de implementare este aproape zero daca se implementeaza \'IAP #5\':propuneri/5-open-surse.\r\n* Un mod bun de a intretine aceasta arhiva ar fi in paralel cu proiectul de \'scris articole\':implica-te/scrie-articole si \'training path-ul\':training-path. _Feedback(Silviu)_: Trebuie sa extragem o lista de probleme clasice pe care vrem sa le bagam si apoi apelat la baietii care vor sa se implice.\r\n* Cel mai important lucru este gasirea unui om care sa se ocupe de aceasta arhiva. _Feedback(Silviu)_: Trebuie intrebat PaulDB daca nu vrea sa coordoneze pusul problemelor.\r\n\r\nh2(#feedback). Feedback\r\n\r\nIntra pe \'forum\':forum/index.php?topic=2617.0 pentru a da feedback.\r\n\r\n==SmfTopic(topic_id=\"2617\")==\r\n',6061,'public',NULL,NULL),('structuri-mari','Lucrul cu structuri mari de date','2008-02-01 20:26:51','2008-02-01 20:26:51','h1. Lucrul cu structuri mari de date\r\n\r\n',5601,'public',NULL,NULL),('winter-challenge-2008/clasament','Winter Challenge 2008','2008-01-24 14:17:56','2008-02-20 10:16:45','h1. Winter Challenge 2008\r\n\r\n(htabs)* \'Despre concurs\':winter-challenge-2008/\r\n* \'Runda 1\':winter-challenge-2008/runda-1\r\n* \'Runda 2\':winter-challenge-2008/runda-2\r\n*(active) \'Clasament\':winter-challenge-2008/clasament\r\n\r\nAcesta este clasamentul cumulat pe cele doua runde.\r\n\r\n==Rankings(rounds = \"winter2008-1 | winter2008-2\")==',2092,'protected',NULL,NULL),('preoni-2008','preONI 2008','2007-11-08 01:35:25','2008-11-30 14:03:58','==Include(page=\"template/preoni-2008\")==\r\n\r\nh2. Detalii\r\n\r\n*preONI*, concursul de pregatire pentru \'Olimpiada Nationala de Informatica\':http://olimpiada.info, a ajuns la a *5-a* editie!\r\n\r\n*preONI 2008* incepe cu 4 runde online de calificare. Cei mai buni de la fiecare grupa sunt invitati la finala on-site. Castigatorii rundei finale sunt premiati in bani si obiecte.\r\n\r\nEditia 2008 aduce ca noutate o *grupa separata pentru elevii de gimnaziu*!\r\n\r\np=. %{background-color: #fafafa}Remember... \'*preONI 2007*\':preoni-2007 *|* \'*preONI 2006*\':preoni-2006%\r\n\r\nh2. Program concurs\r\n\r\nFaceti click pe titlul unei runde pentru informatii detaliate.\r\n\r\ntable{width:50%}. |_. Runda |_. Data |_. Ora |\r\n| \'*Runda 1*\':preoni-2008/runda-1 | *25 Noiembrie 2007, Duminica* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 2*\':preoni-2008/runda-2 | *16 Decembrie 2007, Duminica* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 3*\':preoni-2008/runda-3 | *20 Ianuarie 2008, Duminica* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 4*\':preoni-2008/runda-4 | *17 Februarie 2008, Duminica* |=. *09^00^ - 13^00^* |\r\n| \'*Runda Finala*\':preoni-2008/runda-finala |=. *21-23 Martie 2008* | |\r\n\r\nh2. Despre preONI\r\n\r\n*preONI*, concursul de marca al comunitatii infoarena, este dedicat elevilor de gimnaziu si de liceu ce se pregatesc pentru ONI (\'Olimpiada Nationala de Informatica\':http://olimpiada.info/).\r\n\r\nConcursul este impartit in *4* grupe: gimanziu (pentru clasele V-VIII), clasa a IX-a, clasa a X-a si clasele XI-XII. Se organizeaza 4 runde online de calificare. In urma acestora, cei mai buni de la fiecare grupa sunt invitati la o \'runda finala\':preoni-2008/runda-finala.\r\n\r\nIn cadrul unei runde, concurentii au de rezolvat 3 probleme in 4 ore. Castigatorii rundei finale sunt premiati cu bani si/sau obiecte.\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru!\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti probleme, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':documentatie/evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nPoti sa rezolvi probleme de la orice grupa de varsta. Totusi, te vei califica la runda finala numai daca te incadrezi in grupa la care ai concurat!\r\n\r\nh2. Prima data pe _infoarena_?\r\n\r\n\'infoarena\':/ ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi si vezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',2028,'protected',NULL,NULL),('blog/imagine-cup','Imagine Cup 2008','2008-01-25 13:31:04','2008-01-25 19:39:53','h1. Imagine Cup 2008\r\n\r\n\'*Imagine Cup*\':http://www.imaginecup.com este o competitie internationala pentru studenti pasionati de tehnologie si de arte digitale. Concursul contine inclusiv o sectiune de _algoritmi_. Puteti afla mai multe detalii din mesajul de mai jos din partea \'*Microsoft Romania*\':http://www.microsoft.com/romania/.\r\n\r\nbq. Stimati studenti,\r\nVa incurajez sa participati la Imagine Cup 2008. Este o sansa foarte buna de afirmare si de dezvoltare a unor abilitati cum sunt cele de comunicare si de lucru in echipa sau de aprofundare a unor tehnologii ce va pot folosi azi si pe viitor. Competitia este un excelent prilej de inovare si Microsoft Romania in parteneriat cu Autoritatea Nationala pentru Cercetare Stiintifica sunt initiatorii programului Innovation Accelerator, adresat studentilor cu performante deosebite la Imagine Cup 2008:\r\n&bull; finantarea proiectelor pentru dezvoltarea accelerata a prototipurilor inainte de finala (cu pana la 4000 de RON) si\r\n&bull; sesiuni de dezvoltare a competentelor de prezentare si cunostinte de business utile viitorilor antreprenori in tehnologia de varf. Obtineti mai multe detalii de pe \'www.microsoft.ro/educatie/studenti\':http://www.microsoft.ro/educatie/studenti (consultati paginile dedicate sectiunii Software Design).\r\n \r\nAveti de ales intre urmatoarele 9 sectiuni:\r\n&bull; Software Design, Embedded Development, Game Development - proiecte complexe, inovatie, lucru in echipa\r\n&bull; Algorithm, IT Challenge, Project Hoshimi - probe dinamice, in general competitii individuale\r\n&bull; Photography, Short Film si Interface Design - arte digitale\r\n \r\nTema generala a competitiei este legata de rolul tehnologiei in ocrotirea mediului inconjurator. Puteti lua contact cu cateva idei de participare foarte pertinente de pe forumurile competitiei, de exemplu legate de \'Biroul Unesco pentru Educatie si Dezvoltare Durabila\':http://imaginecup.com/Community/forums/t/5072.aspx. Daca sunteti interesati de impresiile unor finalisti romani de anul trecut in Seul, va recomand 4 interviuri publicate pe \'www.msevents.ro\':http://www.msevents.ro (prezentare Silverlight), \'www.techready.tv/imaginecup\':http://www.techready.tv/imaginecup (format WMV) sau \'www.trilulilu.ro/microsoft\':http://www.trilulilu.ro/microsoft (prezentare Flash).\r\n \r\nFinala mondiala va avea loc in iulie 2008, in Paris. Aveti timp suficient pentru o participare de calitate cu care mai tarziu sa ne mandrim in facultatea noastra. Primul pas este sa va inregistrati pe www.imaginecup.com. Inregistrarea nu ia mai mult decat 1-2 minute si de aici mai departe veti fi indrumati in functie de sectiunea preferata si etapele pe care trebuie sa le parcurgeti in concurs.\r\n \r\nAveti grija, pentru 7 dintre cele 9 sectiuni termenul limita pentru participare este 1 februarie 2008. Daca sunt nelamuriri, va rog sa le adresati in scris lui Todi Pruteanu, alexanp@microsoft.com.\r\n \r\nSucces in sesiune si parcurs cat mai lung la Imagine Cup.',1,'protected',NULL,NULL),('blog/conferinta-mihai-patrascu','Conferinta Mihai Patrascu la UNIBUC','2008-01-25 14:11:41','2008-01-26 08:31:58','h1. Conferinta Mihai Patrascu la UNIBUC\r\n\r\n\'*Facultatea de Matematica si Informatica*\':http://fmi.unibuc.ro/ro si Centrul de Cercetare in Modele de Calcul, Algoritmi si Criptografie (MOCALC) anunta:\r\n\r\np{border: 2px dashed silver;display:block;width:50%;margin:0em auto;padding:0.3em;text-align:center;}=. Conferinta ==user(user=\"mpatrascu\")==\r\n*Perspective Geometrice in Dezvoltarea Algoritmilor*\r\n_Joi 31 ianuarie si vineri 1 februarie, ora *15:00*, sala *220*_\r\n\r\nh3. Rezumat\r\n\r\nbq. Cum ajuta o constructie Cantor pentru cardinalitatea numerelor rationale la obtinerea unor structuri de date eficiente? De ce estimarea normelor in dimensiuni inalte este necesara la optimizarea cautarilor in baze de date? Cum pot progrese in intelegerea geometriilor ne-euclidiene sa ajute la constructia microprocesoarelor? Perspectiva geometrica s-a dovedit din ce in ce mai utila in progresele recente in dezvoltarea algoritmilor. In acest curs, vom discuta cateva idei matematice reprezentative, si cativa algoritmi frumosi care se obtin. Cursul este la nivel introductiv si speram ca va contine idei interesante si pentru informaticieni care urasc matematica si pentru matematicieni care urasc informatica.\r\n\r\nh3. Despre\r\n\r\n==user(user=\"mpatrascu\" type=\"tiny\")== este student la doctorat la \'MIT\':http://mit.edu si are printre cele mai bune rezultate la olimpiadele internationale la informatica dintre romani. Poti afla mai multe despre el din interviul (\'partea 1\':blog/interviu-mihai-patrascu-partea-intai si \'partea 2\':blog/interviu-mihai-patrascu-partea-a-doua) luat de Cosmin Negruseri, din \'pagina lui personala\':http://web.mit.edu/~mip/www/ sau de pe \'blog-ul\':http://infoweekly.blogspot.com/ lui.',15,'protected',NULL,NULL),('newsletter/winter-challenge-2008/runda-1','Winter Challenge, Runda 1','2008-01-25 20:00:02','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nTe invit sa participi la prima runda (din doua) a concursului\r\nWinter Challenge.\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Runda 1 se desfasoara...\r\n\np{padding-left: 2em;}. Duminica, 27 ianuarie 2008, orele 09:00 - 14:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nVezi pagina concursului: \'winter-challenge-2008\':winter-challenge-2008\r\nca sa afli cum poti participa.\r\n\nSucces!\r\n\nh2.  Atentie! Concurs cu rating! \n\nDaca vrei sa ti se modifice rating-ul in urma participarii la aceasta\r\nrunda trebuie sa iti anunti participarea din timp.  Intra pe\r\n\'winter-challenge-2008\':winter-challenge-2008 si inscrie-te la Runda 1.\r\n\nPoti sa participi la concurs chiar si daca nu te-ai inscris in\r\nprealabil insa nu ti se va modifica rating-ul.\r\n==NewsletterRating(username=\"%username%\")==\r\nCiteste despre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Despre Winter Challenge \n\nVei primi 3 probleme de dificultate comparabila cu cea de la\r\nOlimpiada Nationala de Informatica.  Timpul de lucru este de 5h.\r\n\nOrganizatorii concursului sunt:\r\n\np{padding-left: 2em;}. Bogdan A. Stoica\r\n    [  ==User(user=\"fireatmyself\" type=\"link\")==  ]\r\n\np{padding-left: 2em;}. Mugurel Ionut Andreica\r\n    [  ==User(user=\"mugurelionut\" type=\"link\")==  ]\r\n\np{padding-left: 2em;}. Airinei Adrian\r\n    [  ==User(user=\"astronomy\" type=\"link\")==  ]\r\n\nh2.  Interviuri noi pe blog! \n\nCosmin te asteapta pe blog-ul infoarena cu doua interviuri noi si\r\nspectaculoase!  De data aceasta, oaspetii lui sunt sunt Radu Berinde\r\nsi Octavian Costache (aka Vivi).\r\n\nCiteste interviurile si vino pe forum sa stam de vorba!\r\n\nRadu Berinde\r\n\np{padding-left: 2em;}. Radu este unul din putinii romani cu doua medalii de aur la\r\n    olimpiada internationala de informatica.  Multi au invatat\r\n    din sursele lui ingenioase si din \"smenurile\" lui de\r\n    implementare.  Acum studiaza la MIT, iar vara trecuta a facut al\r\n    doilea internship la Google.  (Cosmin) Am avut ocazia sa lucrez\r\n    cu el pe acelasi proiect si m-a impresionat prin o gramada de\r\n    idei bune si viteza cu care scrie cod elegant si util.\r\n    Radu ne povesteste ceva din experienta lui legata de olimpiade si\r\n    concursuri, despre MIT, Google, masini si despre cat impinge la\r\n    piept.\r\n\np{padding-left: 2em;}. Interviu Radu Berinde, Partea I\r\n    \'blog/interviu-radu-berinde-partea-intai\':blog/interviu-radu-berinde-partea-intai\r\n\np{padding-left: 2em;}. Interviu Radu Berinde, Partea I\r\n    \'blog/interviu-radu-berinde-partea-a-doua\':blog/interviu-radu-berinde-partea-a-doua\r\n\nOctavian Costache\r\n\np{padding-left: 2em;}. Vivi insemneaza pe CV-ul propriu o gramada de realizari variate:\r\n    4 premii la Internetics, premii la olimpiadele de informatica,\r\n    premiant si apoi organizator la InfoEducatie.  A realizat\r\n    impreuna cu Irina Dumitrascu site-ul doizece.ro, cel mai mare\r\n    site de jocuri online din Romania, vandut ulterior companiei\r\n    Neogen.  Este angajat la Google in New York.  Scrie unul dintre\r\n    cele mai populare blog-uri din Romania (\'http://vivi.ro/blog/\':http://vivi.ro/blog/).\r\n    A fost asistent la cursuri de algoritmica la UPB si instructor la\r\n    cursuri Cisco.  Tot Vivi a fost printre initiatorii ONI by Net -\r\n    partea online a olimpiadei nationale de informatica.\r\n    Vivi imparte cu noi cateva sfaturi si idei despre facultate,\r\n    freelancing, Google, blogging si programare.\r\n\np{padding-left: 2em;}. Interviu Vivi, Partea I\r\n    \'blog/interviu-octavian-costache-partea-intai\':blog/interviu-octavian-costache-partea-intai\r\n\np{padding-left: 2em;}. Interviu Vivi, Partea II\r\n    \'blog/interviu-octavian-costache-partea-a-doua\':blog/interviu-octavian-costache-partea-a-doua\r\n\nAlte interviuri luate de Cosmin si pe care le poti gasi pe blog:\r\nCatalin Francu, Mihai Patrascu, Mircea Pasoi si Lazar Codrut.\r\n\nBlog-ul infoarena ( \'blog\':blog ) poate fi urmarit\r\nsi via RSS.  URL-ul pentru feed este:\r\n\'blog\':blog?action=rss\r\n\nh2.  Avem articole noi! \n\nMembrii comunitatii infoarena au adaugat doua articole noi\r\npentru tine.\r\n\np{padding-left: 2em;}. *   Teorema Chineza a Resturilor\r\n        \'teorema-chineza-a-resturilor\':teorema-chineza-a-resturilor\r\n        Autor: Adrian Vladu, transcris de Marginean Ciprian\r\n\np{padding-left: 2em;}. *   Heavy Path Decomposition\r\n        \'heavy-path-decomposition\':heavy-path-decomposition\r\n        Autor: Marius Stroe\r\n\nCiteste-le.  Te asteptam pe forum cu sugestii si intrebari.\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nRamai alaturi de noi.  Te ajutam sa devii olimpic!\r\nEchipa infoarena iti ureaza succes!\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('planificare/sedinta-20080118','Sedinta 2008-01-18','2008-01-15 19:49:35','2008-02-01 16:24:54','h1. Sedinta 2008-01-18\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *vineri* la ora *19:30* la \'*ICHB*\':http://ichb.ro\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")== \r\n* ==user(user=\"stef2n\" type=\"tiny\")== \r\n* ==user(user=\"ditzonec\" type=\"tiny\")== \r\n* _&hellip; asteptam confirmari_\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioara\':planificare/sedinta-20071218\r\n* preONI 2008 :: financial update\r\n* preONI 2008 :: organizare runda finala\r\n* hackaton\r\n* Articole si Cartea lu Francu - status update/planuri de viitor\r\n* Program si locatie pentru sedintele urmatoare\r\n* implementare IAP #5\r\n* propunatori pentru unirea\r\n* infoarena OKRs pentru 2008 si 2008Q1\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* [0/2] Cristi face IAP de community ladder\r\n* [0/2] Cristi face IAP de almanah\r\n* Fluf discuta cu Malex despre stack trace.  Malex ne ajuta.\r\n* Mircea face IAP pentru arhiva de incepatori %{color:red;}(done)%\r\n* Mircea se intereseaza de 2% pentru anul asta %{color:red;}(done)% -> \'2%\':doi-la-suta\r\n* Mircea il preseaza pe tipul de la Microsoft %{color:red;}(done)%\r\n* Fluf lanseaza 2.1.5\r\n* IAP#4: Wefgef face structura de forum din nou, o votam si schimbam pe live deodata\r\n* Cristi pune buton PayPal pe infoarena\r\n* Cristi intreaba despre cazare la Nichita Stanescu %{color:red;}(done)%\r\n* Silviu vorbeste cu Ali despre laborator si mancare %{color:red;}(done)% Detalii in \'pagina\':planificare/preoni-2008/finala dedicata finalei.\r\n* Cristi vorbeste cu Delia despre tricouri %{color:red;}(done)%\r\n* [0/2] Silviu e contest director pentru hackaton si face plan pentru Adobe.\r\n* Silviu supravegheaza pe Claudia & Diana pentru articolele din Cartea lui Francu. %{color:red;}(will do :P)%\r\n* Silviu face o metrica pentru transcrierea articolelor din Cartea lui Francu.  %{color:red;}(done)% Vezi \'pagina\':implica-te/scrie-articole/cartea-lui-francu.\r\n* [0/2] Stefan periaza training path-ul intr-o structura arborescenta coerenta si prezentabila. %{color:red;}(done)%\r\n* Mircea face changeset minimal pentru IAP #5. %{color:red;}(done)%\r\n* [0/2] Adi face lista de 50 de probleme open source. %{color:red;}(done)%\r\n* Intalnirea urmatoare:  2008-02-01, seara la ICHB\r\n\r\nh2. Notite\r\n\r\n* Va face Vali rost de design de tricou?\r\n* Trebuie reorganizata pagina /articole\r\n',13,'public',NULL,NULL),('blog/vine-olimpiada','Vine Olimpiada','2008-01-26 13:15:02','2008-11-15 13:41:14','_Se apropie olimpiada judeteana si ma gandeam de ceva vreme sa scriu un articol despre diverse metode de antrenament. Am exagerat putin cu lungimea articolului, probabil am avut in minte postul \'Size matters\':http://steve-yegge.blogspot.com/2008/01/blogging-theory-201-size-does-matter.html a lui Steve Yegge, dar va incurajez cu caldura sa il cititi in totalitate. Sper sa va placa sa il cititi in aceiasi masura in care mi-a placut mie sa il scriu._\r\n\r\nTin minte senzatiile de la olimpiadele de mate din gimnaziu, cand ajungeam la concursuri regionale sau nationale si nu prea intelegeam despre ce vorbeau unii elevi de exemplu \"principiul cutiei\" sau \"media patratica\". Un elev era foarte nervos ca nu facuse \"problema cu musca\" la clasa. Stiind trucul respectiv ar fi rezolvat toate patru problemele la olimpiada nationala, fara acel truc a ramas doar cu trei probleme rezolvate perfect. Eu eram foarte fericit ca anul ala rezolvasem o problema si un subpunct de la alta si mergeam cu capul sus acasa cu un premiu.\r\n\r\nAlta amintire este ca in clasa a 8-a rezolvasem o problema de distanta in spatiu de care eram foarte multumit si la o tabara de pregatire un elev din Arad, si el pe clasa a 8-a, mi-a zis ca a rezolvat problema respectiva in 5 metode, una dintre ele folosind integrale. La aceiasi tabara nu imi iesise o problema de geometrie in plan care cerea minimizarea unor distante si acelasi elev din Arad mi-a aratat o cartulie ce trata acel gen de probleme si mi-a zis ca daca studiam cartea inainte ma prindeam de problema. Eu abia daca rezolvam o culegere de probleme intr-un an de zile ...\r\n\r\nEra o problema de standarde diferite, cum inca nu eram copt, credeam ca ideile apar din aer si e de ajuns sa stii la nivel de clasa matematica si apoi sa te \"scremi\" tare ca sa reusesti sa rezolvi problemele.\r\n\r\nIn liceu am trecut pe info, unde mi se parea mai usor. Erau doar vreo doua culegeri de probleme nu mii ca la matematica prin care sa filtrezi pana sa gasesti una ca lumea. L-am cunoscut pe Adi Carcu cu care si acum sunt foarte bun prieten. Mergeam la el acasa destul de des si povesteam probleme pana se facea tarziu ... cred ca parintii lui se intrebau cand o sa plec :).\r\n\r\nPana in clasa a 11-a aveam idei pe la probleme dar nu imi iesea implementarea la nici una. Atunci a inceput concursul Bursele Agora la care am participat serios facand la fiecare problema solutii diferite, evaluator, generatoare de teste aleatoare si soltuii brute force. Abia dupa ce am facut 15 probleme de la Bursele Agora ca lumea am inceput sa am incredere in abilitatile mele de implementare. Atunci am dat si peste Cormen, si eram tare entuziast pentru ca inainte nu aveam de unde invata si deodata aveam o carte in care erau explicate toate chestiile despre care auzisem. \r\n\r\nCred ca atunci a fost momentul cand am devenit pasionat de informatica. Citeam in fiecare zi cate ceva mai si implementam si ma gandeam la probleme, si asa mi-am dat seama ce inseamna sa fii olimpic. Cand esti pasionat faci un lucru din placere in fiecare zi. Nu tragi tare cu o saptamana sau doua inainte de judeteana sa acoperi ceva material din programa. Pentru un elev pasionat nu exista programa ci doar placerea de a rezolva probleme si de a invata ceva nou.\r\n\r\nMi-am dat seama cum la matematica eram un pigmeu fata de cei care se pregateau serios. Nu se poate compara munca de un an cu cea de cateva saptamani sau doua luni. \r\n\r\nIn facultate am meditat de cateva ori un elev care obtinea rezultate destul de bune, dar cand a venit la pregatire am vazut rapid ca nu avea baze teoretice aproape deloc, facea totul dupa intuitie si se descurca bine. A venit cu vreo doua luni inainte de olimpiada si apoi a doua data cu 2 saptamani, si i-am zis ca are o gramada de gauri in cunostinte. El mi-a replicat ca in astea doua saptamani trage tare. Mi-a venit sa rad si i-am zis ca nu are rost sa se chinuie sa acumuleze multa informatie ci sa foloseasca aceiasi metoda care i-a mers si pana atunci. Problema e ca dupa ce faci un salt in cunostinte, la inceput nu rezolvi probleme mai usor, ci iti dai seama ca abordarile tale sunt gresite. Astfel in loc sa mai incerci o abordare gresita cu care ai putea castiga  60-70 de puncte vei astepta ideea care rezolva perfect problema. Dar ideea respectiva s-ar putea sa nu vina si tu sa ramai cu 0 puncte. Invatarea si evolutia e un maraton nu un sprint (am furat expresia asta de la Emanuel, colegul de apartament ;)).\r\n\r\nRadu Berinde imi povestea cum intr-o vacanta de vara facea probleme pe acm.timus.ru toata ziua, in vremea aia era al 4-lea in clasamentul rezolvitorilor de pe site. Programul lui zilnic era: antrenamente la sala, iesire seara la bere, si probleme pe timus in restul zilei. Mi se pare o vacanta destul de misto :)\r\n\r\nAdi Carcu nu se antrena mai deloc pentru concursuri, inainte de judeteana facea una sau doua probleme ca sa fie sigur ca nu si-a iesit din mana si cam atat. Dar el intrase in lot din clasa a 9-a si acolo facuse antrenamente serioase unde luptai pentru locul la un concurs international. Mihai Patrascu zicea ca o tabara de antrenament ar fi durat o luna in vremea cand participa Adrian.\r\n\r\nPe langa asta, Adi avea tot timpul proiecte personale de programare la care lucra (printre care un chat listener pentru reteaua din camin :)), si cred ca ele ajuta chiar daca nu sunt de algoritmica. Adi dupa fiecare lot trecea prin problemele ce s-au dat si incerca sa le rezolve astfel incat codul sursa sa fie eficient, foarte inteligibil si foarte scurt. Tot timpul programele lui mi se pareau foarte simple si lizibile in comparatie cu cele ale altor concurenti. Simplitatea, lizibilitatea si faptul ca codul sursa e scurt ajuta mult la viteza de depanarea a bugurilor.\r\n\r\nIn clasa a 11-a, in seara dinaintea probei citisem intr-o gazeta de info cum se gasesc componentele biconexe intr-un graf neorientat. A doua zi la concurs am primit o problema care cerea determinarea componentelor biconexe intr-un graf neorientat. Nu mai imi aminteam toate detaliile dar, naiv, m-am apucat de lucru. Dupa trei ore nu am reusit sa fac nimic si nu am implementat nici macar solutia evidenta.\r\n\r\nEste important sa va antrenati implementarea cum facea Adi pentru a va da seama cum puteti transforma solutiile in cod cat mai simplu, de asemenea orice algoritm netrivial care credeti ca il veti folosi intr-un concurs gen componente biconexe, flux, infasuratoare convexa, subsir crescator de lungime maxima in O(n log n), arbori echilibrati, trebuie sa il implementati de doua sau trei ori pentru a fi sigur ca il faceti corect si rapid cand aveti nevoie de el. Problemele cele mai dificile sunt cand trebuie sa combinati mai multi algoritmi sau structuri de date, iar in concurs se adauga stresul, limitele de timp si nu ar trebui sa mai aveti si probleme de implementare a algoritmilor ce i-ati studiat deja. E bine sa implementati algoritmii pe care ii considerati clasici de mai multe ori si pentru a putea estima mai bine timpul necesar pentru a rezolva o problema. Partea de \"time management\" e si ea una importanta in concursuri.\r\n\r\nDaca vreti sa va antrenati implementarea la problemutze simple puteti incerca cu incredere practice rooms de la topcoder, acolo sunt de la probleme simple la mai grele si aveti acces la codul sursa al unor concurenti care au incercat si ei problemele respective. Puteti vedea o gramada de variante de rezolvare a aceleiasi probleme si va puteti decide care e cea mai buna varianta pentru stilul vostru. La probleme mai grele puteti incerca cu incredere infoarena. Sper ca proiectul in care sharuim sursele si proiectul cu arhiva de invatare va fi folositor in acest sens.\r\n\r\nCu Mircea Pasoi si Silviu Ganceanu vorbeam cand erau ei pe a 10-a respectiv a 12-a aproape in fiecare zi probleme pe messenger si ei lucrau arhiva problemelor de pe \'acm.sgu.ru\':http://acm.sgu.ru , Silviu se si mutase la ICHB si il avea pe Mihai Stroe profesor. Mie mi se pare ca i-a ajutat foarte mult pe amandoi faptul ca discutau si lucrau in paralel.\r\n\r\nSilviu imi zicea de trei elevi din clasa a 10-a care lucrasera inainte de ONI toata arhiva de pregatire de la USACO si iesisera pe primele trei locuri la clasa a 10-a la ONI, cred ca primul a fost Valentin Stanciu, daca tin bine minte. Lui Silviu ii placea cum cei trei elevi ai lui se ambitionasera unul de la altul si au evoluat mult.\r\n\r\nNu stiu daca ati urmarit anul trecut evolutia clasamentului arhivei de probleme, dar eu vedeam cum wefgef, gcosmin si btataroiu se luptau intre ei si in fiecare zi isi mareau numarul de probleme rezolvate din arhiva.\r\n\r\nEste foarte bine sa ai un prieten sau un grup de prieteni pasionati si ei de concursuri. Concurenta te ambitioneaza iar comunicarea cu alti pasionati de algoritmica te ajuta sa aflii tot felul de trucuri mai repede. In general profesorul de la clasa e depasit de nivelul problemelor de olimpiada, daca nu l-ai depasit inca ar trebui sa iti faci probleme. Rolul profesorului este doar sa zgandare pasiunea in tine la inceput, dupa aia esti pe cont propriu si de aceea comunicarea cu un grup de pasionati e vitala. Pe \'forumul\':forum infoarena sau pe cel de la topcoder va puteti face prieteni pe care ii veti pastra si mai tarziu in viata.\r\n\r\nAr ajuta daca gasiti pe un fost olimpic de la care sa luati meditatii, in Bucuresti cel mai simplu e sa mergi la ICHB, in Iasi sau Suceava gasiti relativ usor fosti olimpici puternici, in Ardeal in schimb mai rar, probabil ati putea vorbi cu Patcas Csaba (coleg cu mine de an) care pregateste echipa Babesului pentru ACM si pe cativa baieti din Cluj pentru ONI. Cineva cu experienta in concursuri va poate ghida inspre anumite tipuri de probleme, spre siteuri sau carti utile.\r\n\r\nPregatirea psihica si controlarea stresului in timpul concursului sunt si ele importante. Mircea a preluat o idee de la echipa de ACM a universitatii Waterloo, si inainte de un concurs important face o pauza de programare de o saptamana ca sa se linisteasca. Abordarea asta s-ar putea sa nu fie buna pentru cei ce \"ingrasa porcu in ajun\". Puteti sa incercati sa aflati din timp care sunt conditiile in care trebuie sa participati in concurs si sa va antrenati in acele conditii pentru a avea un mediu familiar cand ajungeti la fata locului.\r\n\r\nAlta modalitate de pregatire e participarea la cat mai multe concursuri pe internet. Pentru mine Bursele Agora a insemnat destul de mult si cred ca nu numai pentru mine, poate ne zice si Mugurel ceva aici. De asemenea cand organizam concursul \"Algoritmus\" impreuna cu Ciprian Cana, am vazut un nume nou prin clasamente, Radu Marin. Facea destul de bine pe problemele care eu cu Cipri ne chinuisem sa fie destul de grele. I-am zis lui Mircea la misto ca va avea un concurent puternic anul ala. Predictia s-a transformat in realitate si Radu a luat medalie de bronz anul respectiv la IOI.\r\n\r\nSumarizez putin elementele importante ce ajuta la obtinerea unor rezultate bune la olimpiade :\r\n\r\n* munca individuala ghidata de pasiune\r\n* antrenarea modalitatii de codare a algoritmilor\r\n* gasirea unui grup de prieteni pasionati\r\n* gasirea unui mentor cu experienta\r\n* participarea la cat mai multe concursuri online\r\n\r\nCu proiectul infoarena incercam sa va ajutam sa atingeti performanta in informatica cat mai usor. Avem o \'arhiva\':arhvia cu un numar impresionant de probleme frumoase, o \'sectiune\':articole de articole interesante, o \'lista\':training-path de trucuri care ar trebui stiuta pentru concursuri si doua proiecte pe care le gasiti \'aici\':/propuneri/5-open-surse si \'aici\':propuneri/6-arhiva-educationala care vor mari si mai mult utilitatea siteului.\r\n\r\nVa astept cu comentarii! Sunt curios si de stilul vostru de antrenament!\r\n\r\nDaca mai vreti si alte sfaturi puteti citi \'ghidul pentru concursuri\':ghid-complet-pentru-concursurile-de-informatica al lui Mircea, sau \'articolul\':blog/post-happy-coding lui Mugurel.',1490,'public',2630,NULL),('preoni-2008/runda-1/solutii/nkperm','preoni-2008/runda-1/solutii/nkperm','2007-11-25 13:59:07','2008-03-30 09:29:30','h2(#nkperm). \'NKPerm\':problema/nkperm\r\n\r\nVom presupune ca avem o functie care determina cate $(N,K)$ permutari exista care incep cu un prefix dat putem efecuta ambele operatii intr-un mod relativ simplu. Pentru a rezolva operatia de tip $A$ putem folosi aceasta functie ca sa numaram cate permutari sunt mai mici din punct de vedere lexicografic decat cea data astfel: luam fiecare prefix al permutarii date si determinam cate permutari exista care incep cu acesta si care au urmatorul element mai mic decat elementul respectiv din permutarea data.\r\nSa luam permutarea din exemplu $(1 3 2 1 2 3)$. Vom adauga rezultatele pentru prefixele:\r\n$(1 1 ...)$\r\n$(1 2 ...)$\r\n$(1 3 1 ...)$\r\n$(1 3 2 1 2 1 ...)$\r\n\r\nUrmeaza pseudocodul pentru algoritmul descris:\r\n==code(c) |rez = 1\r\naparitii[1..N] = {0}\r\npentru i = 1, N*K:\r\n   pentru j = 1, P[i]-1:\r\n       daca j!=P[i-1] si aparitii[j] < K:\r\n           rez += numara(P[1..i-1]+[j])\r\n   aparitii[P[i]]++\r\n==\r\n\r\nCum operatia $B$ este practic inversa operatiei $A$ rezolvarea este foarte asemanatoare. Vom determina prefixul permutarii cautate element cu element, folosind functia de numarare:\r\n==code(c) |rez = 0\r\naparitii[1..N] = {0}\r\npentru i = 1, N*K:\r\n   pentru j = 1, N:\r\n       daca j!=P[i-1] si aparitii[j] < K:\r\n           daca rez+numara(P[1..i-1]+[j]) >= X:\r\n               P[i] = j \r\n               break\r\n           altfel:\r\n               rez += numara(P[1..i-1]+[j]) \r\n   aparitii[P[i]]++\r\n==\r\n\r\nRamane doar sa vedem acum cum putem determina in mod eficient cate $(N,K)$ permutari exista cu un prefix dat. O prima observatie ar fi ca putem reprezenta o un prefix ca un vector de aparitii pentru numerele de la $1$ la $N$ impreuna cu un numar reprezentand ultimul element pus in permutare. Putem folosi aceasta reprezentare ca sa scriem urmatoarea functie recursiva:\r\n==code(c) |numara(aparitii[], ultim):\r\n    daca rezultatul pentru (aparitii[], ultim) a mai fost calculat:\r\n        returneaza rezultatul stocat\r\n    daca aparitii[1..N] = {K,K,...,K}:\r\n        returneaza 1\r\n    rez = 0\r\n    pentru i = 1, N:\r\n        daca i != ultim si aparitii[i] < K:\r\n            aparitii[i]++\r\n            rez += numara(aparitii, i)\r\n            aparitii[i]--\r\n    stocheaza rez pentru (aparitii[], ultim)\r\n    returneaza rez\r\n==\r\n\r\nPutem observa ca functia folosesete tehnica de memoizare pentru a nu calcula acelasi rezultat de mai multe ori, dar din pacate numarul de stari posibile este mult prea mare ({$K^N^*N$}) pentru a reprezenta o solutie eficienta. Totusi, putem face urmatoarea observatie: pentru un prefix dat nu ne intereseaza efectiv ce numere apar in prefix, ci de cate ori apar fiecare. Spre exemplu rezultatul pentru prefixul $(1 2 1 3 2 ...)$ va fi acelasi cu rezultatul pentru prefixele $(2 1 3 1 2 ...), (13 5 13 27 5 ...)$, etc.. Astfel putem reprezenta un prefix ca un vector $cate[0...K]$ unde $cate[i]$ este numarul de valori care apar de $i$ ori in prefix. De asemenea, mai trebuie sa retinem si de cate ori apare in prefix ultima valoarea pusa. Putem acum rescrie functia de numarare:\r\n==code(c) |numara(cate[], ultim):\r\n    daca rezultatul pentru (cate[], ultim) a mai fost calculat:\r\n        returneaza rezultatul stocat\r\n    daca cate[K] = N:\r\n        returneaza 1\r\n    rez = 0\r\n    pentru i = 0, K-1:\r\n        daca cate[i] != 0:  \r\n            cate[i]--\r\n            cate[i+1]++\r\n            daca i = ultim:\r\n                // fara valori egale pe pozitii adiacente\r\n                rez += cate[i]*numara(cate, i+1)\r\n            altfel:\r\n                rez += (cate[i]+1)*numara(cate, i+1)\r\n            cate[i+1]--\r\n            cate[i]++\r\n    stocheaza rez pentru (cate[], ultim)\r\n    returneaza rez\r\n==\r\n\r\nPutem estima ca numarul de stari in cazul acesta este $N^(K+1)^*(K+1)$, care este destul de mare pentru $N = 20, K = 5$ (desi mult mai mic decat in cazul precedent). Cum @cate[0]+cate[1]+...+cate[K]@ $&le; N$ numarul de stari prin care se trece efectiv este mult mult mai mic decat aceasta prima estimare. \r\n\r\nh3. Detalii de implemetare\r\n\r\n* O codificare rapida a starilor poate fi reprezentarea lor sub forma unui numar de lungime $K+2$ in baza $N+1$, codificare care incape intr-un intreg pe $32$ de biti. \r\n* In functia de numarare ne putem da seama in momentul in care rezultatul este mai mare de $2^55^$ (limita impusa in enunt), si putem returna direct valoarea $2^55^$ fara a afecta corectitudinea solutiei. Aceasta optimizare reduce mult numarul starilor care sunt parcurse, deoarece pentru foarte multe stari rezultatul depaseste $2^55^$. \r\n* Pentru a verifica daca un rezultat a mai fost calculat deja se poate folosi o tabela \'hash\':tabele-hash-scurta-prezentare, dar mai simplu pentru programatorii $C++$ ar fi fost sa foloseasca un \'map\':http://www.sgi.com/tech/stl/Map.html (desi nu are complexitate $O(1)$ optimizarile anterioare sunt mai mult decat suficiente pentru a face solutiile care folosesc $map$ sa se incadreze in timp)\r\n\r\nSolutia oficiala care implementeaza ideile descrise mai sus ruleaza sub $0.1s$ si parcurge $~100.000$ de stari pe testele cele mai mari.\r\n',1507,'public',NULL,NULL),('lucrul-cu-nr-mari','Lucrul cu numere mari','2008-01-26 19:21:32','2008-08-21 15:02:39','h1. Lucrul cu numere mari\r\n\r\nDe multe ori, in probleme, apar situatii cand este nevoie sa memoram numere intregi foarte mari (de ordinul sutelor de cifre), iar uneori trebuie sa efectuam si operatii aritmetice cu aceste numere.\r\n\r\nNumerele reprezentate pe vectori le vom numi pur si simplu \"vectori\", iar numerele reprezentate printr-un tip ordinal de date le vom numi, printr-o analogie usor fortata cu matematica, \"scalari\". Sa vedem acum cum se efectueaza operatiile elementare pe aceste numere.\r\n\r\nh2. Initializarea\r\n\r\nUn vector poate fi initializat in trei feluri: cu $0$, cu un scalar sau cu un alt vector.\r\n\r\nLa initializarea cu $0$, singurul lucru pe care il avem de facut este sa setam numarul de cifre pe $0$. De aceea, este practic inutil sa implementam aceasta functie ca atare; putem folosi in loc singura instructiune pe care ea o contine.\r\n\r\n== code(c)|\r\nvoid Atrib0(Huge H) {\r\n  H[0] = 0;\r\n}\r\n==\r\n\r\nLa initializarea cu un scalar nenul, trebuie sa asezam fiecare cifra pe pozitia corespunzatoare, afland in paralel si numarul de cifre. Se incepe cu cifra unitatilor, si la fiecare pas se pune in vector cifra cea mai putin semnificativa, dupa care numarul de reprezentat se imparte la $10$ (neglijandu-se restul), iar numarul de cifre se incrementeaza.\r\n\r\n== code(c)|\r\nvoid AtribValue(Huge H, unsigned long X) {\r\n  H[0] = 0;\r\n  while (X) {\r\n      ++H[0];\r\n      H[H[0]] = X % BASE;\r\n      X /= BASE;\r\n  }\r\n}\r\n==\r\n\r\nIata, de exemplu, cum se pune pe vector numarul $195$:\r\n!lucrul-cu-nr-mari?img1.jpg!\r\n\r\n\r\nIn sfarsit, initializarea unui vector cu altul se face printr-o simpla copiere (se pot folosi cu succes rutine de lucru cu memoria, cum ar fi $FillChar$ in Pascal sau $memmove$ in C). Pentru eleganta, poate fi folosita si atribuirea cifra cu cifra:\r\n\r\n== code(c)|\r\nvoid AtribHuge(Huge H, Huge X) {\r\n  int i;\r\n  for (i = 0; i <= X[0]; ++i) {\r\n    H[i] = X[i];\r\n  }\r\n}\r\n==\r\n\r\nh2. Compararea\r\n\r\nPentru a compara doua numere \"uriase\", incepem prin a afla numarul de cifre semnificative (deoarece, in urma anumitor operatii pot rezulta zerouri nesemnificative care \"atarna\" totusi la numarul de cifre). Aceasta se face decrementand numarul de cifre al fiecarui numar atata timp cat cifra cea mai semnificativa este $0$. Dupa ce ne-am asigurat asupra acestui punct, comparam numarul de cifre al celor doua cifre. Numarul cu mai multe cifre este cel mai mare. Daca ambele numere au acelasi numar de cifre, pornim de la cifra cea mai semnificativa si comparam cifrele celor doua numere pana la prima diferenta intalnita. In acest moment, numarul a carui cifra este mai mare este el insusi mai mare. \r\nDaca toate cifrele numerelor sunt egale doua cate doua, atunci in mod evident numerele sunt egale.\r\n\r\nDupa cum se vede, algoritmul seamana foarte bine cu ceea ce s-a invatat la matematica prin clasa a II-a (doar ca atunci nu ni s-a spus ca este vorba de un \"algoritm\"). Rutina de mai jos compara doua numere uriase $H1$ si $H2$ si intoarce $-1$, $0$ sau $1$, dupa $H1$ este mai mic, egal sau mai mare decat $H2$.\r\n\r\n== code(c)|\r\nint Sgn(Huge H1, Huge H2) {\r\n  // Elimina zero-urile semnificative, daca exista.\r\n  while (H1[0] && !H1[H1[0]]) H1[0]--;\r\n  while (H2[0] && !H2[H2[0]]) H2[0]--;\r\n\r\n  if (H1[0] < H2[0]) {\r\n    return -1;\r\n  } else if (H1[0] > H2[0]) {\r\n    return +1;\r\n  }\r\n\r\n  for (int i = H1[0]; i > 0; --i) {\r\n    if (H1[i] < H2[i]) {\r\n      return -1;\r\n    } else if (H1[i] > H2[i]) {\r\n      return +1;\r\n    }\r\n  }\r\n  return 0;\r\n}\r\n==\r\n\r\nh2. Adunarea a doi vectori\r\n\r\nFiind dati doi vectori, $A$ cu $M$ cifre si $B$ cu $N$ cifre, adunarea lor se face in mod obisnuit, ca la aritmetica. Pentru a evita testele de depasire, se recomanda sa se completeze mai intai vectorul cu mai putine cifre cu zerouri pana la dimensiunea vectorului mai mare. La sfarsit, vectorul suma va avea dimensiunea vectorului mai mare dintre $A$ si $B$, sau cu $1$ mai mult daca apare transport de la cifra cea mai semnificativa. Procedura de mai jos adauga numarul $B$ la numarul $A$.\r\n\r\n== code(c)|\r\nvoid Add(Huge A, Huge B)\r\n/* A <- A+B */\r\n{ int i,T=0;\r\n\r\n  if (B[0]>A[0])\r\n    { for (i=A[0]+1;i<=B[0];) A[i++]=0;\r\n      A[0]=B[0];\r\n    }\r\n    else for (i=B[0]+1;i<=A[0];) B[i++]=0;\r\n  for (i=1;i<=A[0];i++)\r\n    { A[i]+=B[i]+T;\r\n      T=A[i]/10;\r\n      A[i]%=10;\r\n    }\r\n  if (T) A[++A[0]]=T;\r\n}\r\n==\r\n\r\nh2. Scaderea a doi vectori\r\n\r\nSe dau doi vectori $A$ si $B$ si se cere sa se calculeze diferenta $A$ - $B$. Se presupune $B$ &le; $A$ (acest lucru se poate testa cu functia Sgn). Pentru aceasta, se porneste de la cifra unitatilor si se memoreaza la fiecare pas \"imprumutul\" care trebuie efectuat de la cifra de ordin imediat superior (imprumutul poate fi doar $0$ sau $1$). Deoarece $B$ &le; $A$, avem garantia ca pentru a scadea cifra cea mai semnificativa a lui $B$ din cifra cea mai semnificativa a lui $A$ nu e nevoie de imprumut.\r\n\r\n== code(c)|\r\nvoid Subtract(Huge A, Huge B)\r\n/* A <- A-B */\r\n{ int i, T=0;\r\n\r\n  for (i=B[0]+1;i<=A[0];) B[i++]=0;\r\n  for (i=1;i<=A[0];i++)\r\n    A[i]+= (T=(A[i]-=B[i]+T)<0) ? 10 : 0;\r\n    /* Adica A[i]=A[i]-(B[i]+T);\r\n       if (A[i]<0) T=1; else T=0;\r\n       if (T) A[i]+=10; */\r\n  while (!A[A[0]]) A[0]--;\r\n}\r\n==\r\n\r\n\r\nh2. Inmultirea si impartirea cu puteri ale lui 10\r\n\r\nAceste functii sunt uneori utile. Ele pot folosi si functiile de inmultire a unui vector cu un scalar, care vor fi prezentate mai jos, dar se pot face si prin deplasarea intregului numar spre stanga sau spre dreapta. De exemplu, inmultirea unui numar cu $100$ presupune deplasarea lui cu doua pozitii inspre cifra cea mai semnificativa si adaugarea a doua zerouri la coada. Principalul avantaj al scrierii unor functii separate pentru inmultirea cu $10$, $100$, ..., este ca se pot folosi rutinele de acces direct al memoriei ({$FillChar$}, respectiv $memmove$). Iata functiile care realizeaza deplasarea vectorilor, atat prin mutarea blocurilor de memorie, cat si prin atribuiri succesive.\r\n\r\n== code(c)|\r\nvoid Shl(Huge H, int Count)\r\n/* H <- H*10ACount */\r\n{ \r\n  /* Shifteaza vectorul cu Count pozitii */\r\n  memmove(&H[Count+1],&H[1],sizeof(int)*H[0]);\r\n  /* Umple primele Count pozitii cu 0 */\r\n  memset(&H[1],0,sizeof(int)*Count);\r\n  /* Incrementeaza numarul de cifre */\r\n  H[0]+=Count;\r\n}\r\n\r\nvoid Shl2(Huge H, int Count)\r\n/* H <- H*10ACount */\r\n{ int i;\r\n\r\n  /* Shifteaza vectorul cu Count pozitii */\r\n  for (i=H[0];i;i--) H[i+Count]=H[i];\r\n  /* Umple primele Count pozitii cu 0 */\r\n  for (i=1;i<=Count;) H[i++]=0;\r\n  /* Incrementeaza numarul de cifre */\r\n  H[0]+=Count;\r\n}\r\n\r\nvoid Shr(Huge H, int Count)\r\n/* H <- H/10ACount */\r\n{ \r\n  /* Shifteaza vectorul cu Count pozitii */\r\n  memmove(&H[1],&H[Count+1],sizeof(int)*(H[0]-Count));\r\n  /* Decrementeaza numarul de cifre */\r\n  H[0]-=Count;\r\n}\r\n\r\nvoid Shr2(Huge H, int Count)\r\n/* H <- H/10ACount */\r\n{ int i;\r\n\r\n  /* Shifteaza vectorul cu Count pozitii */\r\n  for (i=Count+1;i<=H[0];i++) H[i-Count]=H[i];\r\n  /* Decrementeaza numarul de cifre */\r\n  H[0]-=Count;\r\n}\r\n==\r\n\r\nh2. Inmultirea unui vector cu un scalar\r\n\r\nSi aceasta operatie este o simpla implementare a modului manual de efectuare a calculului. La inmultirea \"de mana\" a unui numar mare cu unul de o singura cifra, noi parcurgem deinmultitul de la sfarsit la inceput, si pentru fiecare cifra efectuam urmatoarele operatii:\r\n\r\n* Inmultim cifra respectiva cu inmultitorul;\r\n* Adaugam \"transportul\" de la inmultirea precedenta;\r\n* Separam ultima cifra a rezultatului si o trecem la produs;\r\n* Celelalte cifre are rezultatului constituie transportul pentru urmatoarea inmultire;\r\n* La sfarsitul inmultirii, daca exista transport, acesta are o singura cifra, care se scrie inaintea rezultatului.\r\n\r\nExact acelasi procedeu se poate aplica si daca inmultitorul are mai mult de o cifra. Singura deosebire este ca transportul poate avea mai multe cifre (poate fi mai mare ca $9$). Din aceasta cauza, la sfarsitul inmultirii, poate ramane un transport de mai multe cifre, care se vor scrie inaintea rezultatului. Iata de exemplu cum se calculeaza produsul $312$ x $87$:\r\n\r\n!lucrul-cu-nr-mari?imnult1.jpg!\r\n\r\nProcedura este descrisa mai jos:\r\n\r\n== code(c)|\r\nvoid Mult(Huge H, unsigned long X)\r\n/* H <- H*X */\r\n{ int i;\r\n  unsigned long T=0;\r\n\r\n  for (i=1;i<=H[0];i++)\r\n    { H[i]=H[i]*X+T;\r\n      T=H[i]/10;\r\n      H[i]=H[i]%10;\r\n    }\r\n  while (T) /* Cat timp exista transport */\r\n    { H[++H[0]]=T%10;\r\n      T/=10;\r\n    }\r\n}\r\n==\r\n\r\nh2. Inmultirea a doi vectori\r\n\r\nDaca ambele numere au dimensiuni mari si se reprezinta pe tipul de date Huge, produsul lor se calculeaza inmultind fiecare cifra a deinmultitului cu fiecare cifra a inmultitorului si trecand rezultatul la ordinul de marime (exponentul lui $10$) cuvenit. De fapt, acelasi lucru il facem si noi pe hartie. Considerand acelasi exemplu, in care ambele numere sunt \"uriase\", produsul lor se calculeaza de mana astfel\r\n\r\n!lucrul-cu-nr-mari?inmult2.jpg!\r\n\r\nS-a luat deci fiecare cifra a inmultitorului si s-a efectuat produsul partial corespunzator, corectand la fiecare pas rezultatul prin calculul transportului. Rezultatul pentru fiecare produs partial s-a scris din ce in ce mai in stanga, pentru a se alinia corect ordinele de marime. Acest procedeu este oarecum incomod de implementat. Se pot face insa unele observatii care usureaza mult scrierea codului:\r\n\r\n* Prin inmultirea cifrei cu ordinul de marime $10i$ din primul numar cu cifra cu ordinul de marime $10j$ din al doilea numar se obtine o cifra corespunzatoare ordinului de marime $10i$+{$j$} in rezultat (sau se obtine un numar cu mai mult de o singura cifra, caz in care transportul merge la cifra corespunzatoare ordinului de marime $10i$ + $j$ + $1$).\r\n* Daca numerele au $M$ si respectiv $N$ cifre, atunci produsul lor va avea fie $M$ + $N$ fie    $M$ + $N$ - $1$ cifre. Intr-adevar, daca numarul $A$ are $M$ cifre, atunci $10^M-1^$ &le; $A$ < $10^M^$ si {$10^N-1^$} &le; $B$ < $10^N^$, de unde rezulta $10^M+N-2^$ &le; $A$ x $B$ < $10^M+N^$.\r\n* La calculul produselor partiale se poate omite calculul transportului, acesta urmand a se face la sfarsit. Cu alte cuvinte, intr-o prima faza putem pur si simplu sa inmultim cifra cu cifra si sa adunam toate produsele de aceeasi putere, obtinand un numar cu \"cifre\" mai mari ca $9$, pe care il aducem la forma normala printr-o singura parcurgere. Sa reluam acelasi exemplu:\r\n\r\n!lucrul-cu-nr-mari?inmult3.jpg!\r\n\r\nAceasta operatie efectueaza {$M$}x{$N$} produse de cifre si {$M$}{@+@}{$N$} (sau {$M$}{@+@}{$N$}-{$1$}, dupa caz) \"transporturi\" pentru aflarea rezultatului, deci are complexitatea O({$M$}x{$N$}). Iata si implementarea:\r\n\r\n== code(c)|\r\nvoid MultHuge(Huge A, Huge B, Huge C)\r\n/* C <- A x B */\r\n{ int i,j,T=0;\r\n\r\n  C[0]=A[0]+B[0]-1;\r\n  for (i=1;i<=A[0]+B[0];) C[i++]=0;\r\n  for (i=1;i<=A[0];i++)\r\n    for (j=1;j<=B[0];j++)\r\n      C[i+j-1]+=A[i]*B[j];\r\n  for (i=1;i<=C[0];i++)\r\n    { T=(C[i]+=T)/10;\r\n      C[i]%=10;\r\n    }\r\n  if (T) C[++C[0]]=T;\r\n}\r\n==\r\n\r\nMai exista o alta modalitate de a inmulti doua numere de cate $N$ cifre fiecare, care are complexitatea <tex>O(N^{log_2 3}) \\approx O(N^{1.58}) \\approx O(N \\sqrt{N})</tex>. Ea deriva de un algoritm propus de Strassen in 1969 pentru inmultirea matricelor. Diferenta se face simtita, ce-i drept pentru valori mari ale lui $N$, dar constanta multiplicativa creste destul de mult si, in plus, solutia e mai greu de implementat; de aceea nu recomandam implementarea ei in timpul concursului. Ideea de baza este sa se micsoreze numarul de inmultiri si sa se mareasca numarul de adunari, deoarece adunarea a doi vectori se face in O({$N$}), pe cand inmultirea se face in O({$N$} $2$). Sa consideram intregii $A$ si $B$, fiecare de cate $N$ cifre. Trebuie sa-i inmultim intr-un timp T({$N$}) mai bun decat O({$N$} $2$). Sa impartim numarul $A$ in doua \"bucati\" $C$ si $D$, fiecare de cate $N$/{$2$} cifre, iar intregul $B$ in doua bucati $E$ si $F$, tot de cate $N$/{$2$} cifre (presupunem ca $N$ este par):\r\n\r\n!lucrul-cu-nr-mari?img3.jpg!\r\n\r\n\r\nAtunci se poate scrie relatia:\r\n**$A$ x $B$ = ({$C$} x $10^N/2^$ + $D$) x ({$E$} x $10^N/2^$ + $F$) = $CE$ x $10^N^$ ({$CF$} + $DE$) x $10^N/2^$ + $DF$**\r\n\r\nPentru a putea calcula produsul $A$ x $B$ avem, prin urmare, nevoie de patru produse partiale, de trei adunari si de doua inmultiri cu puteri ale lui $10$. Adunarile si inmultirile cu puteri ale lui $10$ se fac in timp liniar. Daca efectuam cele patru produse partiale prin patru inmultiri, rezulta formula recurenta de calcul **T({$N$})=4T({$N$}/{$2$})+O({$N$})** care duce prin eliminarea recurentei la <tex>T(N)\\in O(N)^2</tex>. Cu alte cuvinte, inca n-am castigat nimic. Trebuie sa reusim cumva sa reducem numarul de inmultiri de la $4$ la $3$, chiar daca prin aceasta vom mari numarul de adunari necesare. Sa definim produsul **$G$ = ({$C$} + $D$) x ({$E$} + $F$) = $CE$ + $CF$ + $DE$ + $DF$ = $CE$ + $DF$ + ({$CF$} + $DE$)**\r\nAtunci putem scrie: **$A$ x $B$ = $CE$ x $10$^{$N$}^ + ({$G$} - $CE$ - $DF$) x $10$^{$N$}/{$2$}^ + $DF$**\r\nPentru aceasta varianta, folosim doar trei inmultiri, si chiar daca avem nevoie de sase adunari si scaderi si doua inmultiri cu puteri ale lui $10$, complexitatea se va reduce la <tex> O(N^{log_2 3}) </tex>. In cazul in care $N$ este o putere a lui $2$, impartirea in doua a numerelor se poate face fara probleme la fiecare pas, pana se ajunge la numere de o singura cifra, care se inmultesc direct. In cazul in care $N$ nu este o putere a lui $2$, este comod sa se completeze numerele cu zerouri pana la o putere a lui $2$. In functiile descrise mai jos, $MultRec$ nu face decat inmultirea recursiva, pe cand $MultVect2$ se ocupa si de corectarea numarului de cifre (incrementarea pana la o putere a lui $2$). Pentru calculul produselor $C$ x $E$ si $D$ x $F$, procedura $MultRec$ se autoapeleaza; pentru calcularea produsului ({$C$}{@+@}{$D$}) x ({$E$}{@+@}{$F$}), insa, este nevoie sa fie apelata procedura $MultVect2$, deoarece prin cele doua adunari poate sa apara o crestere a numarului de cifre al factorilor, care in acest caz trebuie readusi la un numar de cifre egal cu o putere a lui $2$.\r\n \r\n== code(c)|\r\nvoid MultHuge2(Huge A, Huge B, Huge P);\r\nvoid MultRec(Huge A, Huge B, Huge P)\r\n{ Huge C,D,E,F,CE,DF;\r\n  if (A[0]==1)\r\n    { P[1]=A[1]*B[1];\r\n      P[0]=(P[2]=P[1]/10)>0 ? 2 : 1;\r\n      P[1]%=10;\r\n    }\r\n    else { P[0]=0;\r\n           AtribHuge(C,A);Shr(C,A[0]/2);\r\n           AtribHuge(D,A);D[0]=A[0]/2;\r\n           AtribHuge(E,B);Shr(E,B[0]/2);\r\n           AtribHuge(F,B);F[0]=B[0]/2;\r\n           MultRec(C,E,CE);MultRec(D,F,DF);\r\n           Add(C,D);Add(E,F);\r\n           MultHuge2(C,E,P);\r\n           Subtract(P,CE);Subtract(P,DF);\r\n           Shl(P,A[0]/2);\r\n           Shl(CE,A[0]);Add(P,CE);\r\n           Add(P,DF);\r\n         }\r\n}\r\nvoid MultHuge2(Huge A, Huge B, Huge P)\r\n/* P <- A x B, varianta NA(lg 3) */\r\n{ int i,j,NDig=A[0]>B[0] ? A[0] : B[0],Needed=1,SaveA,SaveB;\r\n  /* Corecteaza numarul de cifre */\r\n  while (Needed<NDig) Needed<<=1;\r\n  SaveA=A[0];SaveB=B[0];A[0]=B[0]=Needed;\r\n  for (i=SaveA+1;i<=Needed;) A[i++]=0;\r\n  for (i=SaveB+1;i<=Needed;) B[i++]=0;\r\n  MultRec(A,B,P);\r\n  /* Restaureaza numarul de cifre */\r\n  A[0]=SaveA;B[0]=SaveB;\r\n  while (!P[P[0]] && P[0]>1) P[0]--;\r\n}\r\n==\r\n\r\nh2.  Impartirea unui vector la un scalar\r\n\r\nNe propunem sa scriem o functie care sa imparta numarul $A$ de tip Huge la scalarul $B$, sa retina valoarea catului tot in numarul $A$ si sa intoarca restul (care este o variabila scalara). Sa pornim de la un exemplu particular si sa generalizam apoi procedeul: sa calculam catul si restul impartirii lui $1997$ la $7$. Cu alte cuvinte, sa gasim acele numere $C$ de tip Huge si <tex>R\\in\\{0, 1, 2, 3, 4, 5, 6\\}</tex> cu proprietatea ca $1997$ = $7$ x $C$ + $R$.\r\n\r\n!lucrul-cu-nr-mari?impart1.jpg!\r\n\r\nLa fiecare pas se coboara cate o cifra de la deimpartit alaturi de numarul deja existent (care initial este $0$), apoi rezultatul se imparte la impartitor ({$7$} in cazul nostru). Catul este intotdeauna o cifra si se va depune la sfarsitul catului impartirii, iar restul va fi folosit pentru urmatoarea impartire. Restul care ramane dupa ultima impartire este tocmai $R$ pe care il cautam. Procedeul functioneaza si atunci cand deimpartitul are mai multe cifre. La sfarsit trebuie sa decrementam corespunzator numarul de cifre al catului, prin neglijarea zerourilor create la inceputul numarului. Numarul maxim de cifre al catului este egal cu cel al deimpartitului.\r\n\r\n== code(c)|\r\nunsigned long Divide(Huge A, unsigned long X)\r\n/* A <- A/X si intoarce A%X */\r\n{ int i;\r\n  unsigned long R=0;\r\n\r\n  for (i=A[0];i;i--)\r\n    { A[i]=(R=10*R+A[i])/X;\r\n      R%=X;\r\n    }\r\n  while (!A[A[0]] && A[0]>1) A[0]--;\r\n  return R;\r\n}\r\n==\r\n\r\nDaca dorim numai sa aflam restul impartirii, nu mai avem nevoie decat sa recalculam restul la fiecare pas, fara a mai modifica vectorul A:\r\n\r\n== code(c)|\r\nunsigned long Mod(Huge A, unsigned long X)\r\n/* Intoarce A%X */\r\n{ int i;\r\n  unsigned long R=0;\r\n\r\n  for (i=A[0];i;i--)\r\n    R=(10*R+A[i])%X;\r\n  return R;\r\n}\r\n==\r\n\r\nh2. Impartirea a doi vectori\r\n\r\nDaca se dau doi vectori $A$ si $B$ si se cere sa se afle catul $C$ si restul $R$, etapele de parcurs sunt aceleasi ca la punctul precedent, numai ca operatorii \"/\" si \"%\" trebuie implementati de utilizator, ei nefiind definiti pentru vectori. Cu alte cuvinte, dupa ce \"coboram\" la fiecare pas urmatoarea cifra de la deimpartit, trebuie sa aflam cea mai mare cifra $X$ astfel incat impartitorul sa se cuprinda de $X$ ori in restul de la momentul respectiv. Acest lucru se face cel mai comod prin adunari repetate: pornim cu cifra $X$={$0$} si o incrementam, micsorand concomitent restul, pana cand restul care ramane este prea mic. Sa efectuam aceeasi impartire, $1997$:{$7$}, considerand ca ambele numere sunt reprezentate pe tipul Huge.\r\n\r\n!lucrul-cu-nr-mari?impart2.jpg!\r\n\r\nCazul cel mai defavorabil (cand $X$={$9$}) presupune $9$ scaderi si $10$ comparatii, cazul cel mai favorabil (cand $X$={$0$}) presupune numai o comparatie, deci cazul mediu presupune $4$ scaderi si $5$ comparatii. Cautarea lui $X$ se poate face si binar, prin injumatatirea intervalului, ceea ce reduce timpul mediu de cautare la aproximativ $3$ comparatii si $3$ inmultiri, dar codul se complica nejustificat de mult (de cele mai multe ori).\r\n\r\n== code(c)|\r\nvoid DivideHuge(Huge A, Huge B, Huge C, Huge R)\r\n/* A/B = C rest R */\r\n{ int i;\r\n\r\n  R[0]=0;C[0]=A[0];\r\n  for (i=A[0];i;i--)\r\n    { Shl(R,1);R[1]=A[i];\r\n      C[i]=0;\r\n      while (Sgn(B,R)!=1)\r\n        { C[i]++;\r\n          Subtract(R,B);\r\n        }\r\n    }\r\n  while (!C[C[0]] && C[0]>1) C[0]--;\r\n}\r\n==\r\n\r\nh2. Extragerea radacinii cubice\r\n\r\nVom sari peste prezentarea algoritmului de extragere a radacinii patrate, pe care il vom lasa ca tema cititorului, si ne vom indrepta atentia asupra celui de extragere a radacinii cubice, care este putin mai complicat, dar care poate fi usor extins pentru radacini de orice ordin. Problema este exact cea din enunt, asa ca vom porni de la exemplul dat. Sa notam <tex>A = 2.097.152</tex> si <tex> X = \\sqrt[3]{A}</tex>. Cum se afla **$X$** ?\r\n\r\nO prima varianta ar fi cautarea binara a radacinii, prin injumatatirea intervalului. Initial se porneste cu intervalul ({$1$},{$A$}), deoarece radacina cubica se afla undeva intre $1$ si $A$ (evident, incadrarea este mai mult decat acoperitoare; ea ar putea fi mai limitativa, dar nu ar reduce timpul de lucru decat cu cateva iteratii). La fiecare pas, intervalul va fi injumatatit. Cum, probabil ca stiti deja; se ia jumatatea intervalului, se ridica la puterea a treia si se compara cu $A$. Daca este mai mare, inseamna ca radacina trebuie cautata in jumatatea inferioara a intervalului. Daca este mai mica, vom continua cautarea in jumatatea superioara a intervalului. Daca cele doua numere sunt egale, inseamna ca am gasit tocmai ce ne interesa. Prima varianta a pseudocodului este:\r\n\r\n== code(c)|\r\nciteste A cu N cifre\r\n  Lo <- 1, Hi <- A, X <- 0\r\n  cat timp X=0\r\n    Mid <- (Lo+Hi)/2\r\n    daca Mid^3<A\r\n      atunci Lo <- Mid+1\r\n      altfel daca Mid^3>A\r\n               atunci Hi <- Mid-1\r\n               altfel X <- Mid\r\n==\r\n\r\n\r\nIn cazul cel mai rau, algoritmul de mai sus efectueaza $log ~2~ A$ injumatatiri de interval, fiecare din ele presupunand o adunare, o impartire la $2$ si o ridicare la cub. Dintre aceste operatii, cea mai costisitoare este ridicarea la cub, O( $N$^{$2$}^ ). Complexitatea totala este prin urmare O( $N$^{$2$}^ $log ~2~ A$ ). Deoarece $A$ are ordinul de marime $10$^{$N$}^, rezulta complexitatea O( $N$^{$3$}^ $log 10$ )= O( $N$^{$3$}^ ), adica mai proasta decat cea ceruta (de altfel, un algoritm cu aceasta complexitate nici nu s-ar incadra in timp pentru $N$={$1000$}). Daca timpul ne permite, trebuie sa cautam alta metoda.\r\n\r\nIn exemplul ales, sa observam ca $106$&le;{$A$}<{$109$}, de unde deducem ca $102$&le;{$X$}<{$103$}. Cu alte cuvinte, $X$ are $3$ cifre. In cazul general, daca $A$ are $N$ cifre, atunci $X$ are [$N$/{$3$}] cifre (prin [$N$/{$3$}] se intelege \"cel mai mic intreg mai mare sau egal cu $N$/{$3$}\"). Care ar putea fi prima cifra a lui $X$? Daca $X$ incepe cu cifra $2$, atunci $200$&le;{$X$}<{$300$} => $8.000.000$&le;{$2.097.152$}<{$27.000.000$}, ceea ce este fals. Cu atat mai putin poate prima cifra a lui $X$ sa fie mai mare ca $2$. Rezulta ca prima cifra a lui $X$ este $1$. De altfel, pentru a afla acest lucru, putem sa si neglijam ultimele $6$ cifre ale lui $A$. Ne intereseaza doar prima cifra, cea a milioanelor, iar prima cifra a lui $X$ o alegem in asa fel incat cubul ei sa fie mai mic sau egal cu $2$.\r\n\r\nCe putem spune despre a doua cifra? Daca ar fi $3$, atunci $130$&le;{$X$}<{$140$} => $2.197.000$&le;{$2.097.152$}<{$2.744.000$}, fals (deci cifra este cel mult $2$). Daca ar fi $1$, atunci $110$&le;{$X$}<{$120$} => $1.331.000$&le;{$2.097.152$}<{$1.728.000$}, fals. Rezulta ca a doua cifra este obligatoriu $2$. Analog, putem neglija ultimele trei cifre ale lui $A$, iar a doua cifra a lui $X$ este cel mai mare $C$ pentru care <tex> \\overline{1C}^3 \\leq 2097</tex>. Pentru a afla ultima cifra, aplicam acelasi rationament: Daca ar fi $9$, atunci $X$={$129$} si ar rezulta $2146688$={$X$}^{$3$}^={$2097152$}, absurd. Daca consideram ca cifra este $8$, atunci calculul se verifica. Am aflat asadar ca $X$={$128$}.\r\n\r\nProcedeul general este urmatorul: dandu-se un numar $A$ cu $N$ cifre, il completam cu zerouri nesemnificative pana cand $N$ se divide cu $3$ (poate fi necesar sa adaugam maxim doua zerouri). Numarul de cifre semnificative ale radacinii cubice este $M$={$N$}/{$3$}. Aflam pe rand fiecare cifra, incepand cu cea mai semnificativa. Sa presupunem ca am aflat cifrele $X$ ~$M$~, $X$ ~$M-1$~,..., $X$ ~$K+1$~. Cifra $X$~$K$~ este cea mai mare cifra pentru care numarul <tex> \\overline{(X_MX_{M-1}...X_{K+1}X_K00...00)}^3\\leq A</tex>. Cifra $X$~$K$~ este unica, deoarece exista, in general, mai multe cifre care verifica proprietatea ceruta, dar una singura este \"cea mai mare\". O a doua versiune a pseudocodului este deci:\r\n\r\n== code(c)|\r\nciteste A cu N cifre\r\n  X <- 0; T <- 0\r\n  cat timp N%3<>0 adauga un 0 nesemnificativ\r\n  repeta de N/3 ori\r\n    adauga la T urmatoarele 3 cifre din A\r\n    adauga la X cea mai mare cifra astfel incat X^3<= T\r\n==\r\n\r\n\r\nSa evaluam complexitatea acestei versiuni. Linia $1$ se executa in timp liniar, O({$N$}). Liniile $2$ si $3$ se executa in timp constant. Linia $5$ se executa in O({$N$}), iar linia $6$ presupune adaugarea unei cifre (O({$N$})) si o ridicare la cub, adica doua inmultiri (O({$N$}^{$2$}^)). Deoarece liniile $5$ si $6$ se executa de $N$/{$3$} ori (linia $4$), rezulta o complexitate de O({$N$}^{$3$}^). Iata ca nici acest algoritm nu a adus imbunatatiri si pare si ceva mai greu de implementat. El poate fi totusi modificat pentru a-i scadea complexitatea la O({$N$}^{$2$}^).\r\n\r\nPrincipalul neajuns al sau este efectuarea ridicarii la cub, care se face in O({$N$}^{$2$}^). Daca am putea sa-l aflam la fiecare pas pe $X$^{$3$}^ fara a efectua inmultiri, adica in timp liniar, atunci intregul algoritm ar avea complexitate patratica. Bineinteles, prima intrebare care vine pe buzele cititorului este \"cum sa ridicam la cub fara sa facem inmultiri?\". Sa nu uitam insa ceva: ca noi nu-l cunoastem numai pe $X$. Il cunoastem si pe $X$ de la pasul anterior, care avea o cifra mai putin (il vom boteza $OldX$). Sa presupunem ca, printr-o metoda oarecare, am reusit sa-l ridicam pe $OldX$ la puterile a doua si a treia (si am obtinut numerele $OldX2$ si $OldX3$). Cum putem, cunoscand aceste trei numere, precum si noua cifra ce se va adauga la sfarsitul lui $X$ (sa-i spunem $C$ ), sa-l aflam pe $X$, patratul si cubul sau? Nu e prea greu:\r\n\r\n<tex> X = 10 \\cdot OldX + C </tex> \r\n<tex> X^2 = (10 \\cdot OldX + C)^2 = 100 \\cdot OldX^2 + 20 \\cdot OldX \\cdot C + C^2 = 100 \\cdot OldX2 + (20 \\cdot C) \\cdot OldX + C^2</tex>\r\n\r\nIata asadar ca pentru a afla noile valori ale puterilor $1$, $2$ si $3$ ale lui $X$, folosindu-le pe cele vechi, nu avem nevoie decat de adunari si de inmultiri cu numere mici (de ordinul miilor). Toate aceste operatii se fac in timp liniar, deci am reusit sa gasim un algoritm patratic. Iata mai jos sursa C:\r\n\r\n== code(c)|\r\nvoid FindDigit(Huge L,Huge NewL2,Huge NewL3,\r\n     Huge OldL,Huge OldL2,Huge OldL3,Huge Target)\r\n{ Huge Aux;\r\n  L[1]=10;\r\n  do\r\n    { L[1]--;\r\n      /* Trebuie calculat LA3. Se stiu OldL (L/10)\r\n         si noua cifra L[1]. Deci (OldL*10+L[1])A3=?\r\n         Se aplica binomul lui Newton. */\r\n      AtribHuge(NewL3,OldL3);Shl(NewL3,3);\r\n      AtribHuge(Aux,OldL2);Mult(Aux,300*L[1]);\r\n      Add(NewL3,Aux);\r\n      AtribHuge(Aux,OldL);Mult(Aux,30*L[1]*L[1]);\r\n      Add(NewL3,Aux);\r\n      AtribValue(Aux,L[1]*L[1]*L[1]);\r\n      Add(NewL3,Aux);\r\n    }\r\n  while (Sgn(NewL3,Target)==1);\r\n  /* Aceeasi operatie pentru LA2 */\r\n  AtribHuge(NewL2,OldL2);Shl(NewL2,2);\r\n  AtribHuge(Aux,OldL);Mult(Aux,20*L[1]);\r\n  Add(NewL2,Aux);\r\n  AtribValue(Aux,L[1]*L[1]);\r\n  Add(NewL2,Aux);\r\n  /* Noile valori devin \'vechi\' */\r\n  AtribHuge(OldL2,NewL2);\r\n  AtribHuge(OldL,L);\r\n  AtribHuge(OldL3,NewL3);\r\n}\r\nvoid CubeRoot(Huge A, Huge X)\r\n{ Huge Target,OldX,OldX2,OldX3,NewX2,NewX3;\r\n  int i;\r\n  /* Se initializeaza vectorii cu 0 (nici o cifra) */\r\n  OldX[0]=OldX2[0]=OldX3[0]=X[0]=0;\r\n  for (i=1;i<=(A[0]+2)/3;i++)\r\n    { AtribHuge(Target,A);\r\n      Shr(Target,3*((A[0]+2)/3-i));\r\n      Shl(X,1);\r\n      FindDigit(X,NewX2,NewX3,OldX,OldX2,OldX3,Target);\r\n    }\r\n}\r\n==\r\n\r\n\r\nAcum nu mai avem decat sa scriem rutinele de intrare/iesire si programul principal:\r\n\r\n== code(c)|\r\n#include <stdio.h>\r\n#include <mem.h>\r\n#define NMax 1000\r\ntypedef int Huge[NMax+3];\r\nHuge A,X; /* A[0] si X[0] indica numarul de cifre */\r\n\r\nvoid ReadData(void)\r\n{ FILE *F=fopen(\"input.txt\",\"rt\");\r\n  int C,i;\r\n\r\n  A[0]=0;\r\n  do A[++A[0]]=(C=fgetc(F))-\'0\';\r\n  while (C!=EOF);\r\n  A[0]--;\r\n  fclose(F);\r\n  /* Intoarce vectorul pe dos */\r\n  for (i=1;i<=A[0]/2;i++)\r\n    A[i]=(A[i]AA[A[0]+1-i])A(A[A[0]+1-i]=A[i]);\r\n}\r\nvoid WriteSolution(void)\r\n{ FILE *F=fopen(\"output.txt\",\"wt\");\r\n  int i=X[0];\r\n  while (!X[i]) i--;\r\n  while (i) fputc(X[i--]+\'0\',F);\r\n  fclose(F);\r\n}\r\nvoid main(void)\r\n{\r\n  ReadData();\r\n  CubeRoot(A,X);\r\n  WriteSolution();\r\n}\r\n==\r\n\r\nPentru a extinde aceasta metoda la radacini de orice ordin $K$, trebuie numai sa tinem cont de expresia binomului lui Newton:\r\n\r\n<tex> X^p = (10 \\cdot OldX + C)^p = \\sum_{\\substack {0\\leq i \\leq p}} {10^i \\cdot Oldx^i \\cdot C^{p-i}} </tex>\r\n\r\nPresupunand ca avem calculate toate puterile de la $1$ la $p$ ale lui $OldX$, se poate calcula noua valoare a lui $X$^{$p$}^ folosind numai adunari si inmultiri cu scalari. In felul acesta se pot calcula in timp liniar valorile lui $X$, $X$^{$2$}^, $X$^{$3$}^, ...., $X$^{$K$}^.\r\n\r\nh2. Problema\r\n\r\n|_. Timp de implementare|_. Timp de rulare|_. Complexitate|\r\n|1h 30\'|10 secunde|**O(N^2^)**|\r\n\r\nSe da un numar natural cu $N$&le;{$1000$} cifre. Se cere sa se extraga radacina cubica a numarului. Se garanteaza ca numarul citit este cub perfect.\r\nFisierul $INPUT.TXT$ contine un singur rand, terminat cu $EOF$, pe care se afla numarul, cifrele fiind nedespartite.\r\nIn fisierul $OUTPUT.TXT$ se va tipari radacina cubica a numarului, pe o singura linie terminata cu $EOF$.\r\n\r\n|_. INPUT.TXT|_. OUTPUT.TXT|\r\n|2097152|128|\r\n\r\nh2. Rezolvare\r\n\r\nProblema este cat se poate de simpla din punct de vedere matematic; dificultatea apare la implementare, atat datorita structurilor de date necesare, cat mai ales datorita complexitatii cerute. Despre lucrul cu numere intregi (chiar si $Longint$) nici nu poate fi vorba, iar la lucrul cu numere reale apar erori de calcul.\r\n\r\nStructura de date propusa pentru abordarea acestui gen de probleme este urmatoarea: numerele vor fi reprezentate printr-un vector de cifre zecimale. Prima pozitie (pozitia $0$) din vector este rezervata pentru a memora numarul de cifre. Definitia C a tipului de date este:\r\n\r\n== code(c)|\r\ntypedef int Huge[1001];\r\n==\r\n\r\nIata cum s-ar memora numarul \"1997\" intr-un asemenea vector:\r\n\r\n!lucrul-cu-nr-mari?pb1.jpg!\r\n\r\nSe observa ca vectorul este oarecum \"intors pe dos\". Totusi, aceasta forma este cea mai convenabila, pentru ca ea permite implementarea cu o mai mare usurinta a operatiilor aritmetice.\r\n\r\nMai trebuie remarcat ca pe fiecare pozitie $K$ in vector se afla cifra care il reprezinta pe $10$^{$K-1$}^ in numarul reprezentat: in V[1] se afla cifra unitatilor ({$10$}^{$0$}^), in V[2] se afla cifra zecilor ({$10$}^{$1$}^), in V[3] se afla cifra sutelor ({$10$}^{$2$}^) s.a.m.d. Formatul zecimal nu este cea mai fericita (a se citi \"eficienta\") alegere. El ocupa doar patru biti din cei opt ai unui octet, deci face risipa de memorie. Daca am alege baza de numeratie $256$, am folosi la maximum memoria, si in plus operatiile ar fi cu mult mai rapide (deoarece $256$ este o putere a lui $2$, inmultirile si impartirile la $256$ sunt simple deplasari la stanga si la dreapta ale reprezentarilor binare). Sa facem urmatorul calcul ca sa vedem cate cifre are in baza $256$ un numar care are $1000$ de cifre in baza $10$:\r\n\r\n<tex>10^{1000} = 10 \\cdot (10^3)^{333} \\approx 10 \\cdot (2^10)^{333} \\approx 10 \\cdot (2^8)^{335} = 10 \\cdot 256^{335}  </tex>\r\n\r\nAsadar, numarul de cifre s-a redus cam de trei ori. Un algoritm liniar ar functiona de trei ori mai repede pe reprezentari in baza $256$, iar unul patratic ar functiona de noua ori mai repede. Inconvenientul major este dificultatea depanarii unui program care opereaza intr-o baza aritmetica atat de straina noua. Vom ramane deci la baza $10$, cu mentiunea ca acei mai temerari dintre voi pot incerca folosirea bazei $256$.\r\n \r\n\r\n\r\n',2044,'public',NULL,NULL),('winter-challenge-2008/runda-1/solutii','Solutii Winter Challenge 2008, Runda 1','2008-01-27 12:44:48','2008-02-24 15:13:56','h1. Solutii Winter Challenge 2008, Runda 1\r\n\r\nS-a incheiat \"prima runda\":winter-challenge-2008/runda-1 a concursului \"Winter Challenge\":winter-challenge-2008/. Se pare ca problemele au fost \"frumoase\", desi concursul a fost organizat \"pe fuga\". Runda viitoare promit sa fie organizata mai din timp.\r\n\r\n\r\nFelicitarii \"tuturor participantilor\":winter-challenge-2008/clasament si, in special, primilor 3 clasati:\r\n\r\n==Rankings(rounds=\"winter2008-1\" display_entries=\"3\" pager_style=\"none\")==\r\n\r\nSperam ca in runda a doua sa obtineti punctaje mai mari, problemele vor avea nivelul celor de la ONI. Din pacate, si numarul de participanti a fost scazut, dar speram ca pe viitor vor fi mai multi concurenti. Daca aveti pareri sau sugestii despre aceasta runda exrpimati-le pe \"forum\":forum/index.php?topic=2637.0.\r\n\r\nAs vrea sa le multumesc lui \"Adrian Airinei\":utilizator/astronomy si lui \"Andrei Grigorean\":utilizator/wefgef pentru sprijinul acordat, si, totodata, intregii \"echipe infoarena\":echipa-infoarena.\r\n{@  @}\r\n{@  @}\r\n\r\nMult succes in continuare,\r\n\r\nEchipa Winter Challenge.\r\n{@  @}\r\n{@  @}\r\n\r\nIn continuare vom prezenta solutiile oficiale ale problemelor. Daca aveti nelamuriri puteti cere explicatii suplimentare pe \"forum\":forum.\r\n{@  @}\r\n{@  @}\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Primar\':winter-challenge-2008/runda-1/solutii#primar\r\n* \'Jetoane2\':winter-challenge-2008/runda-1/solutii#jetoane2\r\n* \'Tero\':winter-challenge-2008/runda-1/solutii#tero\r\n\r\n\r\n==include(page=\"winter-challenge-2008/runda-1/solutii/primar\")==\r\n\r\n==include(page=\"winter-challenge-2008/runda-1/solutii/jetoane2\")==\r\n\r\n==include(page=\"winter-challenge-2008/runda-1/solutii/tero\")==\r\n',1231,'public',NULL,NULL),('utilizator/victorsb','Profil victorsb','2006-11-24 21:00:15','2008-11-13 16:28:46','h2. Studii\r\n\r\n* 2008 - prezent: Universitatea din Bucuresti, Facultatea de Matematica si Informatica\r\n* 2006 - 2008: Liceul International de Informatica Bucuresti\r\n* 2000 - 2006: Colegiul National \"Samuel von Brukenthal\", Sibiu\r\n\r\nh2. Distinctii primite\r\n\r\n* Medalie de aur la BOI 2008\r\n* Medalie de bronz la CEOI 2007\r\n* Medalie de aur la Olimpiada din Yakutia 2006\r\n* Premiul I la ONI 2008\r\n* Premiul II la ONI 2006\r\n* Mentiune la ONI 2005, 2007\r\n* Membru al lotului national de informatica 2006, 2007, 2008',1851,'protected',NULL,NULL),('template/newround','%round_id%','2006-11-06 00:40:20','2009-12-22 17:27:03','h1. == roundparam(round_id=\"%round_id%\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"%round_id%\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"%round_id%\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"%round_id%\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"%round_id%\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/%round_id%/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"%round_id%\" score=\"1\")==',1490,'protected',NULL,NULL),('tabele-hash','Tabele Hash','2008-01-26 19:29:42','2008-01-30 17:34:11','Articol mutat la adresa \"http://infoarena.ro/tabele-hash-prezentare-detaliata\":http://infoarena.ro/tabele-hash-prezentare-detaliata. Aceasta pagina se poate sterge.',2044,'public',NULL,NULL),('winter-challenge-2008/runda-1/solutii/primar','winter-challenge-2008/runda-1/solutii/primar','2008-01-27 19:01:55','2008-01-27 19:01:55','h2(#primar). \'Primar\':problema/primar\r\n\r\nContrar punctajelor, aceasta a vrut sa fie problema usoara a setului. \r\n\r\nProblema are doua parti: aflarea discriminarii minime si gasirea componentei Consiliului Local.\r\n\r\nPentru prima parte era nevoie sa se observe faptul ca discriminarea pe o ulita este fie $0$, fie $1$. $0$ era in cazul in care ulita avea un numar par de case (alegeam din prima casa un barbat, apoi o femeie, etc.) si, respectiv, $1$, cand pe ulita erau un numar impar de case.\r\n\r\nPartea a doua necesita o analiza mai atenta. \r\nPrima solutie se bazeaza pe teoria grafurilor. Vom construi un graf bipartit, unde nodurie din partea stanga sunt reprezentate de dreptele paralele cu $OX$, iar nodurile din partea dreapta sunt reprezentate de dreptele paralele cu $OY$. Intre un nod din stanga si un nod din dreapta va exista muchie doar daca la intersectia celor doua drepte se afla o casa. Se porneste dintr-un nod cu grad impar, marcand alternativ muchiile (casele) cu $0$ sau $1$ si eliminandu-le. Raman, astfel, numai noduri cu grad par, care vor forma cicluri, dar care se pot rezolva folosind, din nou, algoritmul de mai sus.\r\nO alta rezolvare pentru partea a doua, este urmatoarea: \r\nSe pleaca dintr-un punct nemarcat si se marcheaza cu $0$; se merge, pe dreapta, paralel cu $OX$, in urmatorul punct nemarcat, care se marcheaza cu $1$; se merge, apoi, pe dreapta, paralel cu $OY$, in urmatorul punct nemarcat si se marcheaza cu $0$, etc. Pentru o complexitate eficienta, punctele se pot stoca sub forma unor liste, ale caror campuri retin urmatorul punct nemarcat pe $OX$ si, respectiv, urmatorul punct nemarcat pe $OY$. Daca unii utilizatori _InfoArena_, nu sunt obisnuiti cu implementarea listelor, pot tine niste vectori ( $NextOX{~i~}$ si $NextOY{~i~}$ ) in care sa retina indicii urmatoarelor puncte nemarcate.\r\n\r\nComplexitatea primei parti este $O(N * log{~2~}N)$ pentru sortare, iar complexitatea celei de-a doua parti este $O(N)$. In total, complexitatea algoritmului este $O(N * log{~2~}N)$.\r\n\r\n',2028,'public',NULL,NULL),('winter-challenge-2008/runda-1/solutii/jetoane2','winter-challenge-2008/runda-1/solutii/jetoane2','2008-01-27 19:03:39','2008-01-27 19:04:43','h2(#jetoane2). \'Jetoane2\':problema/jetoane2\r\n\r\nProblema se rezolva prin programare dinamica. Vom considera $2$ matrici:\r\n\r\n* $A{~i~}~,~ {~j~}$ = $1$ daca intervalul de jetoane dintre pozitiile $i$ si $j$ poate fi eliminat, sau $0$, altfel.\r\n* $B{~i~}~,~ {~j~}~,~ {~k~}$ = $1$ daca intre pozitiile $i$ si $j$ se poate plasa al $k$-lea cuvant si se poate elimina +tot+ intervalul, sau $0$, altfel.\r\n\r\nAstfel $B{~i~}~,~ {~j~} {~k~}$ = $1$ daca si numai daca exista un $p$ &isin; [$i$, $j$], astfel incat:\r\n\r\n# $Cuv{~k~}~,~ {~l~} = Sir{~p+l~}$, &forall; $1$ &le; $l$ &le; $Lung{~k~}$\r\n# $A{~i~}~,~ {~p-1~} = A ~(i+Lung{~k~})~ ~,~ ~j~ = 1$\r\n\r\n$Sir{~p+l~}$ reprezinta sirul initial, $Cuv{~k~}~,~ {~l~}$ reprezinta a $l$-a litera din al $k$-lea cuvant si $Lung{~k~}$, lungimea acestuia. Dinamica se va calcula, crescator, dupa lungimea intervalului [$i$, $j$]. Daca &exist; $k$ astfel incat $B{~i~}~,~ {~j~}~,~ {~k~}$ = $1$, atunci $A{~i~}~,~ {~j~}$ = $1$.\r\n\r\nDupa determinarea valorilor lui $A$ si cum scorul depinde +exclusiv+ de intervalele [$i$, $j$] ce pot fi eliminate, se va aduna la rezultat suma ponderilor de pe toate intervalele [$i$, $j$] cu $A{~i~}~,~ {~j~}$ = $1$.\r\n\r\nComplexitatea solutiei este $O(N * L^3^ * CONST)$, unde $L$ reprezinta lungimea sirului initial, iar CONST = 10. \r\n\r\nExista si o solutie de complexitate $O(N * L^3^)$, care, in practica, merge mai repede. Aceasta solutie a fost data de catre \"Cosmin Gheorghe\":utilizator/gcosmin si o voi publica imediat dupa ce primesc acordul sau.\r\n',2028,'public',NULL,NULL),('planificare/sedinta-20080201','Sedinta 2008-02-01','2008-01-20 20:30:59','2008-02-06 23:22:31','h1. Sedinta 2008-02-01\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *vineri* la ora *17:30* la \'*FMI, Universitatea Bucuresti*\':http://fmi.unibuc.ro\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"Marius\" type=\"tiny\")== (Marius nu poate veni vineri; ne intalnim cu el joi, dupa conferinta)\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* _&hellip; asteptam confirmari_\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioara\':planificare/sedinta-20080118\r\n* Program si locatie pentru sedintele urmatoare\r\n* preONI 2008 update runda finala\r\n** design tricou\r\n** update cazare, masa, lab\r\n* om pentru Google Custom Search\r\n* revive infoarena 2.x development\r\n* votat IAP #6\r\n* infoarena OKRs pentru 2008 si 2008Q1\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* [1/2] Cristi face IAP de community ladder\r\n* [1/2] Cristi face IAP de almanah\r\n* IAP #6 de citit pana data viitoare\r\n* Cristi da drumul la 2%\r\n* Cristi vb. cu Fluf\r\n* Respingem IAP #4\r\n* Cristi investigheaza de ce nu merge card-ul la Raiffeisen.\r\n* Silviu trateaza cu Emi despre Augustin, tipul de la Poli.\r\n* Mircea si Cristi (dar mai mult Mircea) cauta si telefoneaza hoteluri.\r\n* Vali face in weekend design la tricou IA.  Cristi ii da PSD-ul mascotei si sigla vectoriala.\r\n* [1/2] Silviu e contest director pentru hackaton si face plan pentru Adobe.\r\n* Sedinta urmatoare pe 2008-02-18 la FMI ({-voi calatoriti in timp?-} Gata, nu mai calatorim in timp :P)\r\n* Adi mai cauta surse de probleme pentru arhiva\r\n* Silviu il intreaba pe Stefan despre Google Custom Search. *Update(silviu):* Stefan e de acord sa se bage.\r\n\r\nh2. Notite\r\n\r\n* Trebuie reorganizata pagina /articole\r\n* om pentru Google Custom Search\r\n',15,'public',NULL,NULL),('pregatire','Pregatire la informatica','2008-02-01 00:04:39','2008-02-21 20:47:55','h1. Pregatire la informatica\r\n\r\nAici vrem sa adunam toate centrele de pregatire la info, persoanele care sunt dispuse sa faca meditatii precum si grupurile de elevi care se intrunesc periodic pentru pregatire la info.\r\n\r\nEste foarte util sa va intalniti (live!) periodic cu alte persoane care se pregatesc la informatica.  Puteti rezolva probleme impreuna, puteti sa simulati concursuri sau puteti ciocni o bere si sa vorbiti despre info.  Astfel de intalniri va pot stimula sa trageti mai tare si sa invatati mai repede.\r\n\r\nh2. Centre de excelenta\r\n\r\n\"Iasi?\":http://www.liis.ro/~cex_is/\r\n\r\nBucuresti?\r\n\r\nh2. Persoane care fac meditatii\r\n\r\nIn tabelul asta adunam contacte cu fosti studenti si profesori tari care pot da meditatii la nivel de olimpiada.\r\n\r\n|_. Nume |_. Locatie |_. Contact |\r\n| Csaba Patcas | Cluj Napoca / Oradea | ... |\r\n| Clara Ionescu | Cluj Napoca | ... |\r\n| Radu Lupsa | Cluj Napoca | ... |\r\n| Ciprian Cana | Cluj Napoca | ... |\r\n| Mugurel Ionut Andreica | Bucuresti | ... |\r\n| Constantin Galatan | Bistrita | ... |\r\n| Lucian Ilea |  Cluj Napoca | ... |\r\n| majoritatea din \'echipa infoarena\':echipa-infoarena | ... | ... |\r\n| Marius Andrei | Silicon Valley, California | :-) |\r\n| Cosmin Negruseri | Mountain View, California | :-) |\r\n\r\nAlba?\r\n\r\nSuceava?\r\n\r\nIasi?\r\n\r\nh2. Grupuri organizate\r\n\r\nh3. _Numele grupului_, _Locatie_\r\n\r\nDescriere: ...\r\nMembri: ...\r\n\r\n&rarr; \'Vezi pagina grupului\':grup/pokemonii\r\n',1507,'public',NULL,NULL),('documentatie/structura-articol','Structura unui articol','2008-11-12 00:12:29','2008-11-12 00:17:09','h1. Titlul articolului\r\n\r\n(Categoria _Nume-categorie_, Autor _Nume-autor_)\r\n\r\n(toc){width: 10em}*{text-align:center;} *Continut*\r\n* \'Sectiunea 1\':documentatie/structura-articol#sectiune1\r\n* \'Sectiunea 2\':documentatie/structura-articol#sectiune2\r\n* \'Sectiunea 3\':documentatie/structura-articol#sectiune3\r\n\r\nh2(#sectiune1). Sectiunea 1\r\n\r\nContinutul primei sectiuni\r\n\r\nh2(#sectiune2). Sectiunea 2\r\n\r\nContinutul celei de-a doua sectiuni\r\n\r\nh2(#sectiune3). Sectiunea 3\r\n\r\nContinutul celei de-a treia sectiuni\r\n',2044,'public',NULL,NULL),('runda/star_trek','star_trek','2009-03-29 14:24:54','2009-04-04 17:57:22','h1. == roundparam(round_id=\"star_trek\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"star_trek\") ==\r\n\r\nExtraterestrii sunt pe cale sa atace Pamantul si nava Enterprise pleaca sa atace baza extraterestrilor (pe care o numesc firma) (problema Poarta), dupa ce mai face reparatiile necesare dupa ultima lupta (sistemul logic al calculatorului (prob Bool), laboratoare (pr Reactivi) etc.). Dar nici extraterestrii nu stau degeaba. Ei lanseaza mai repede asediul si nava Enterprise nu apuca sa le intercepteze. Navele ajung si incep asedierea Pamantului (Dezastru, Razboiul lumilor, Razboi 2). Generalii Pamantului trimit cerere de sprijin unei planete, dar, fiind prea departe, nu ajunge inainte de asediu (Calatorie interplanetara).\r\nPamantul trebuie sa incerce sa reziste pana la sosirea intaririlor.\r\n\r\nDin moment ce pe calculatoarele lor (oamenilor si extraterestrilor) ruleaza tot Linux, infoarena li s-a parut destinatia perfecta pentru a trimite cereri de ajutor. Au promis 100 de denarii spatiali / program celor care le trimit programe sa-i ajute in acest conflict.\r\n\r\nEste decizia ta. Ajuti Pamantul sa scape din aceasta incurcatura, sau joci rolul de \"agent dublu\", ajutand ambele parti ale conflictului, pentru a strange o suma frumusica de bani?\r\n\r\nConexiunea se stabileste ==roundparam(round_id=\"star_trek\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"star_trek\" param=\"duration\" strong=\"true\")== ore. Dupa aceea, conexiunea se va intrerupe si va incepe asaltul.\r\n\r\nAmbele parti, stiind ca e posibil sa nu se ofere nimeni, au acceptat sa verifice intai programele pe niste experiente de-ale lor precedente si sa trimita bani, fiecare cum merita. Daca cineva trimite mai tarziu o sursa mai buna, ii trimit si diferenta de bani.\r\n\r\n\'*Lista vanatorilor de recompense si cati bani a castigat fiecare*\':runda/star_trek/clasament\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"star_trek\" score=\"1\")==',8689,'round: star_trek',3820,NULL),('template/badtests','template/badtests','2007-02-19 00:43:29','2008-11-16 08:58:06','table{margin:0.5em auto;}. |={background-color:#F8EABA;}. !<template/badtests?attention.gif! _Testele pentru aceasta problema nu sunt destul de bine construite pentru a departaja corect solutii ineficiente sau gresite._\r\n\'*Intra aici*\':implica-te/imbunatatire-teste _daca vrei sa ne ajuti sa imbunatatim calitatea testelor pentru aceasta problema!_ |',1490,'protected',NULL,NULL),('template/preoni-2008/footer','template/preoni-2008/footer','2007-11-08 01:49:35','2008-02-11 15:56:39','p{margin: 2em 1em 1em 1em; padding: 1em; height: 70px; border-top: 1px solid silver;}. \r\n!{margin-right: 1em;}<preoni-2008?adobe.png 13%!:http://myadobe.ro/\r\n!{margin-right: 1em;}<preoni-2008?irealsoft.png!:http://www.irealsoft.ro/\r\n!{margin-right: 1em;}<preoni-2006?microsoft.jpg!:http://www.microsoft.com/romania/ \r\nConcurs organizat in parteneriat cu \'*Adobe Romania*\':http://myadobe.ro/ si sprijinit de \'iRealSoft\':http://www.irealsoft.ro/ si \'Microsoft Romania\':http://www.microsoft.com/romania.\r\n',1,'protected',NULL,NULL),('blog/mic-puzzle','Un mic puzzle','2008-02-07 08:41:41','2008-11-15 13:41:14','Am vazut urmatorul puzzle pe un site cu intrebari de interviu Microsoft. Daca nu il stiti deja, incercati sa il rezolvati singuri fara a cauta indicii pe net. E un test interesant de intelegere a operatiilor pe biti.\r\n\r\nCe returneaza functia foo, cand x e un intreg fara semn pe 32 de biti?\r\n\r\n== code(cpp) |\r\nunsigned int foo(unsigned int x) {\r\n  x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1);\r\n  x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2);\r\n  x = ((x >> 4) & 0x0F0F0F0F) | ((x & 0x0F0F0F0F) << 4);\r\n  x = ((x >> 8) & 0x00FF00FF) | ((x & 0x00FF00FF) << 8);\r\n  return (x >> 16) | (x << 16);\r\n}\r\n==',1490,'protected',2669,NULL),('preoni-2008/runda-4/5-8','preONI 2008 - Runda 4, Clasele 5-8','2008-02-11 15:58:02','2008-02-11 16:10:18','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda4-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-4 \r\n*(active) \'Clasele 5-8\':preoni-2008/runda-4/5-8 \r\n* \'Clasa a 9-a\':preoni-2008/runda-4/9 \r\n* \'Clasa a 10-a\':preoni-2008/runda-4/10 \r\n* \'Clasele 11-12\':preoni-2008/runda-4/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-4/5-8\r\n\r\n== roundregister(round_id=\"preoni2008-runda4-5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda4-5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda4-5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-4/5-8.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"preoni2008-runda4-5-8\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',1,'round: preoni2008-runda4-5-8',NULL,NULL),('runda/preoni2008-runda4-5-8/clasament','Clasament preoni2008-runda4-5-8','2008-02-11 15:58:02','2008-02-11 15:58:02','h1. Clasament ==roundparam(round_id=\"preoni2008-runda4-5-8\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda4-5-8\")==',1,'round: preoni2008-runda4-5-8',NULL,NULL),('preoni-2008/runda-4/9','preONI 2008 - Runda 4, Clasa a 9-a','2008-02-11 15:58:16','2008-02-11 16:11:29','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda4-9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-4 \r\n* \'Clasele 5-8\':preoni-2008/runda-4/5-8\r\n*(active) \'Clasa a 9-a\':preoni-2008/runda-4/9 \r\n* \'Clasa a 10-a\':preoni-2008/runda-4/10 \r\n* \'Clasele 11-12\':preoni-2008/runda-4/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-4/5-8\r\n\r\n== roundregister(round_id=\"preoni2008-runda4-9\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda4-9\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda4-9\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-4/9.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"preoni2008-runda4-9\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',1,'round: preoni2008-runda4-9',NULL,NULL),('runda/preoni2008-runda4-9/clasament','Clasament preoni2008-runda4-9','2008-02-11 15:58:16','2008-02-11 15:58:16','h1. Clasament ==roundparam(round_id=\"preoni2008-runda4-9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda4-9\")==',1,'round: preoni2008-runda4-9',NULL,NULL),('runda/preoni2008-runda4-10/clasament','Clasament preoni2008-runda4-10','2008-02-11 15:58:30','2008-02-11 15:58:30','h1. Clasament ==roundparam(round_id=\"preoni2008-runda4-10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda4-10\")==',1,'round: preoni2008-runda4-10',NULL,NULL),('preoni-2008/runda-4/11-12','preONI 2008 - Runda 4, Clasele 11-12','2008-02-11 15:58:39','2008-02-11 16:15:08','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda4-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-4 \r\n* \'Clasele 5-8\':preoni-2008/runda-4/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-4/9 \r\n* \'Clasa a 10-a\':preoni-2008/runda-4/10 \r\n*(active) \'Clasele 11-12\':preoni-2008/runda-4/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-4/5-8\r\n\r\n== roundregister(round_id=\"preoni2008-runda4-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda4-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda4-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-4/11-12.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2008-runda4-11-12\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',1,'round: preoni2008-runda4-11-12',NULL,NULL),('runda/preoni2008-runda4-11-12/clasament','Clasament preoni2008-runda4-11-12','2008-02-11 15:58:39','2008-02-11 15:58:39','h1. Clasament ==roundparam(round_id=\"preoni2008-runda4-11-12\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda4-11-12\")==',1,'round: preoni2008-runda4-11-12',NULL,NULL),('preoni-2008/runda-4/10','preONI 2008 - Runda 4, Clasa a 10-a','2008-02-11 15:58:30','2008-03-31 16:40:08','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda4-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-4 \r\n* \'Clasele 5-8\':preoni-2008/runda-4/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-4/9 \r\n*(active) \'Clasa a 10-a\':preoni-2008/runda-4/10 \r\n* \'Clasele 11-12\':preoni-2008/runda-4/11-12 \r\n* \'Rezultate\':preoni-2008/clasament/runda-4/5-8\r\n\r\n== roundregister(round_id=\"preoni2008-runda4-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda4-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda4-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-4/10.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"preoni2008-runda4-10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',256,'round: preoni2008-runda4-10',NULL,NULL),('preoni-2008/clasament/runda-4/5-8','preONI 2008 - Clasament Runda 4, Clasele 5-8','2008-02-11 16:16:09','2008-02-11 16:16:09','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda4-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-4\r\n* \'Clasele 5-8\':preoni-2008/runda-4/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-4/10\r\n* \'Clasele 11-12\':preoni-2008/runda-4/11-12\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-4/5-8\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasele 5-8\':preoni-2008/clasament/runda-4/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-4/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-4/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda4-5-8\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2008/clasament/runda-4/9','preONI 2008 - Clasament Runda 4, Clasa a 9-a','2008-02-11 16:16:57','2008-02-11 16:16:57','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda4-9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-4\r\n* \'Clasele 5-8\':preoni-2008/runda-4/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-4/10\r\n* \'Clasele 11-12\':preoni-2008/runda-4/11-12\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-4/5-8\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':preoni-2008/clasament/runda-4/5-8\r\n*(active) \'Clasa a 9-a\':preoni-2008/clasament/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-4/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-4/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda4-9\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2008/clasament/runda-4/10','preONI 2008 - Clasament Runda 4, Clasa a 10-a','2008-02-11 16:17:40','2008-02-11 16:17:40','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda4-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-4\r\n* \'Clasele 5-8\':preoni-2008/runda-4/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-4/10\r\n* \'Clasele 11-12\':preoni-2008/runda-4/11-12\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-4/5-8\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':preoni-2008/clasament/runda-4/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-4/9\r\n*(active) \'Clasa a 10-a\':preoni-2008/clasament/runda-4/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-4/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda4-10\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('preoni-2008/clasament/runda-4/11-12','preONI 2008 - Clasament Runda 4, Clasele 11-12','2008-02-11 16:18:37','2008-02-11 16:18:37','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda4-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':preoni-2008/runda-4\r\n* \'Clasele 5-8\':preoni-2008/runda-4/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-4/10\r\n* \'Clasele 11-12\':preoni-2008/runda-4/11-12\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-4/5-8\r\n\r\n==include(page=\"template/preoni-2008/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':preoni-2008/clasament/runda-4/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-4/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-4/10\r\n*(active) \'Clasele 11-12\':preoni-2008/clasament/runda-4/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda4-11-12\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('blog/stelele-informaticii','Surse de la Stelele Informaticii 2008','2008-02-14 15:26:07','2008-02-14 16:32:59','h1. Surse de la Stelele Informaticii 2008\r\n\r\nIn perioadele *18-19 decembrie 2007* si *8-9 februarie 2008* s-a desfasurat concursul national _Stelele Informaticii_. Rezultatele concursului le poti gasi \'aici (9-10)\':http://stelele.ichb.ro/stele/9-10/clasament si \'aici (11-12)\':http://stelele.ichb.ro/stele/11-12/clasament. \r\nPoti gasi cele 12 probleme propuse in \'arhiva de probleme\':arhiva, impreuna cu sursele trimise.',1,'protected',NULL,NULL),('problema/loto','Loto','2006-11-11 11:23:35','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"loto\")==\r\n\r\nGigel este un mare pasionat al jocurilor de noroc, iar cel mai mult ii place sa joace la loto \"$6$ din $N$\". La acest joc, el poate scrie pe un bilet $6$ numere, din $N$ numere naturale distincte date de Loteria Nationala; un numar poate fi folosit pe un bilet de mai multe ori. Gigel a visat intr-o noapte ca suma numerelor scrise pe biletul castigator va fi $S$, asa ca a doua zi s-a dus sa puna si el un bilet castigator!\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care ii spune lui Gigel ce numere trebuie sa aleaga ca sa obtina un bilet castigator (cu suma $S$)\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie din fisierul $loto.in$ se vor gasi numerele naturale $N$ si $S$, separate prin cate un spatiu. Pe a doua linie vor fi $N$ numere naturale distincte, date de Loteria Nationala.\r\n\r\nh2. Date de Iesire\r\n\r\nIn fisierul $loto.out$ se vor gasi $6$ valori reprezentand numerele alese pentru biletul lui Gigel. Daca nu se poate obtine un bilet castigator in fisierul de iesire se va afla doar numarul $-1$.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 100$\r\n* $1 &le; S &le; 600.000.000$\r\n* Valorile numerelor date de Loteria Nationala nu vor depasi $100.000.000$\r\n* Daca exista mai multe solutii, se va afisa una singura\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. loto.in |_. loto.out |\r\n| 3 13 \r\n1 2 3 | 1 1 2 3 3 3 |\r\n| 3 19\r\n1 2 3 | -1 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"loto\")==\r\n\r\n\r\n',1490,'task: loto',88,NULL),('newsletter/preoni-2008/runda-4','preONI 2008, Runda 4; Vrei compilatoare \"standard\" la OJI?','2008-02-15 20:41:35','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nTe invit sa participi la Runda 4, ultima runda de calificare la\r\nfinala preONI 2008!\r\n\nPrimii ~10 concurenti de la fiecare grupa de varsta vor participa la\r\nfinala preONI care va avea loc in Bucuresti.\r\n\npreONI este concursul cu premii mari si finala live care te\r\npregateste pentru Olimpiada Nationala de Informatica.  Anul acesta,\r\nelevii de gimnaziu participa la o grupa de varsta separata si au\r\nlocuri rezervate la runda finala.\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Runda #4 se desfasoara...\r\n\np{padding-left: 2em;}. Duminica, 17 februarie 2008, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nVezi pagina concursului: \'preoni-2008\':preoni-2008\r\n\nh2.  Atentie! Concurs cu rating! \n\nDaca vrei sa ti se modifice rating-ul in urma acestei runde trebuie\r\nsa iti anunti participarea din timp.  Intra pe\r\n\'preoni-2008\':preoni-2008 si inscrie-te la Runda #4.\r\n\nPoti sa participi la concurs chiar si daca nu te-ai inscris in\r\nprealabil insa nu ti se va modifica rating-ul.\r\n==NewsletterRating(username=\"%username%\")==\r\nCiteste despre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Vrei compilatoare standard (GNU C/C++, FreePascal) la OJI? \n\nCu totii stim ca Olimpiada Judeteana de Informatica inca se mai da in\r\nmediile de dezvoltare Borland.  In anul 2008 folosim compilatoare si\r\neditoare dezvoltate acum 15 ani pentru sistemul de operare MS-DOS.\r\n\nMediile Borland folosite la OJI (dar si la clasa) sunt din ce in ce\r\nmai depasite si incompatibile cu standardele actuale ale limbajelor\r\nC, C++ si Pascal.  Limitari severe la alocarea memoriei, lipsa\r\ntipurilor de date pe 64 de biti, librarii standard absente (de exemplu\r\nSTL) sau invechite sunt doar cateva dintre problemele pe care elevii\r\nle intampina.\r\n\nFolosirea compilatoarelor \"standard\" este optionala la faza nationala\r\na olimpiadei de informatica si obligatorie la probele de baraj,\r\nloturi si la toate competitiile internationale.  Cu toate acestea\r\nelevii inca mai sunt nevoiti foloseasca medii Borland pentru a trece\r\nde faza judeteana a olimpiadei.\r\n\nIn comisia OJI exista profesori dispusi sa faca schimbari in bine.\r\nProblema compilatoarelor nu este una noua.  Consideram ca nu i s-a\r\nacordat atentia cuvenita desi efectele sunt din ce in ce mai presante.\r\n\nDaca ai argumente pentru sau impotriva introducerii de compilatoare\r\n\"standard\" la OJI, te invitam sa participi la discutie pe forum-ul\r\ninfoarena:\r\n\'forum/index\':forum/index.php?topic=2684\r\n\nAtentie!  Scopul discutiei este sa strangem argumente pertinente si\r\nprecise in favoarea (sau dupa caz, in defavoarea) acestui demers.\r\nLogistica unui eveniment national precum OJI este deja suficient de\r\ndificila incat orice schimbare necesita motive intemeiate.\r\n\nSperam ca organizatorii olimpiadei de informatica vor cantari\r\nargumentele noastre si vor lua masurile care se cuvin pentru\r\nurmatoarele editii.\r\n\nh2.  Noutati pe blog \n\nCosmin Negruseri scrie un post super interesant despre metode de\r\nantrenament la olimpiade, greseli clasice, anecdote si intamplari\r\namuzante traite de el in pragul unor competitii de matemtica si\r\ninformatica.\r\n\nDaca nu l-ai citit deja, intra aici:\r\n\'blog/vine-olimpiada\':blog/vine-olimpiada\r\n\nAsteptam si parerile tale!\r\n\nBlog-ul infoarena ( \'blog\':blog ) poate fi urmarit\r\nsi via RSS.  URL-ul pentru feed este:\r\n\'blog\':blog?action=rss\r\n\nh2.  Concursul preONI \n\npreONI, concursul de marca al comunitatii infoarena, este dedicat\r\nelevilor de liceu si gimnaziu ce se pregatesc pentru Olimpiada\r\nNationala de Informatica.\r\n\nConcursul este impartit in 4 grupe de varsta:  clasele V-VIII, clasa\r\na IX-a, clasa a X-a si clasele XI-XII.  Se organizeaza 4 runde online\r\nde calificare.  In urma acestora, cei mai buni de la fiecare grupa\r\nsunt invitati la o runda finala.\r\n\nIn cadrul unei runde vei avea de rezolvat 3 probleme in 4 ore.\r\nProblemele sunt de natura algoritmica si de dificultate similara\r\ncelor de la ONI.\r\n\nOferim premii substantiale acelor concurenti care se claseaza pe\r\nprimele locuri la runda finala.\r\n\nEditia 2008 a concursului preONI se desfasoara sub atenta\r\nsupraveghere a lui Mircea Pasoi, in calitate de director de concurs.\r\n\nPe pagina oficiala ( \'preoni-2008\':preoni-2008 ) vei gasi\r\ninformatii despre cum participi, cine propune probleme, premii,\r\nregulamentul concursului samd.\r\n\npreONI 2008 este organizat in parteneriat cu Adobe Romania si\r\nsprijinit de catre iRealSoft si Microsoft Romania.\r\n\nh2.  Runda #3 \n\nS-a desfasurat pe 20 ianuarie 2008.\r\n\nPoti vedea rezultatele aici: \r\n\'preoni-2008/clasament/runda-3/11-12\':preoni-2008/clasament/runda-3/11-12\r\n\niar solutiile oficiale aici:\r\n\'preoni-2008/runda-3/solutii\':preoni-2008/runda-3/solutii\r\n\nTe asteptam la Runda #4!\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nRamai alaturi de noi.  Te ajutam sa devii olimpic!\r\nEchipa infoarena iti ureaza succes!\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('blog/problema-saptamanii-solutie-20080215','Problema saptamanii (solutie)','2008-02-16 08:16:21','2008-11-15 13:41:14','_Am luat o pauza destul de lunga cu *problema saptamanii*. La ultima problema am primit doar doua solutii si am uitat de la cine (amintiti-mi si va trec ca rezolvitori). Gasiti textul \'aici\':blog/problema-saptamanii-20071110 ._\r\n\r\nSolutia problemei e destul de misto: Ne gandim la spatiul starilor problemei ca un patratul unitate din planul cartezian cu originea in (0, 0) si cu punctul diagonal opus in (1, 1). Abscisa unui punct din patratul acesta reprezinta pozitia normalizata pe intervalul [0, 1] a unui mobil sau un robot pe unul dintre cele doua drumuri de la A la B, iar ordonata punctului va reprezenta pozitia normalizata a celuilalt mobil respectiv robot pe al doilea drum de la A la B. Acum pentru ca ambele mobile pleaca din A si ajung in B, punctele asociate pozitiilor lor ne vor da o curba pornind din punctul (0, 0) si ajungand in punctul (1, 1). Iar punctele ce reprezinta miscarea celor doi roboti, care unul pleaca din A si ajunge in B si celalalt pleaca din B si ajunge in A, ne descriu o curba ce pleaca din punctul (0, 1) in (1, 0). Cele doua curbe trebuie sa se intersecteze si de aici rezulta ca orice doua drumuri am forma intre orasele A si B si orice itinerariu ar avea robotii, daca doua mobile pot ajunge de la A la B fiind legate cu o sfoara de lungime 10 m, atunci robotii nu pot ajunge unul din A in B si celalat din B in A fara sa se atinga.',1490,'protected',2699,NULL),('preoni-2008/runda-4/solutii/factoriale','preoni-2008/runda-4/solutii/factoriale','2008-02-17 11:24:50','2008-02-17 12:47:09','h2(#factoriale). \'Factoriale\':problema/factoriale\r\n\r\nPentru fiecare numar de forma {$x{~i~}!$} aflam descompunerea sa in factori primi apoi aflam si descompunerea numarului $M$ adunand exponentii corespunzatori bazelor egale din descompunerile numerelor {$x{~i~}!$}. Daca avem $M$ factorizat, putem afla solutia problemei usor. Pentru ca un numar $X$ sa se scrie sub forma {$A^K^$}, cu $A$ si $K$ naturale, trebuie ca fiecare exponent din factorizarea lui $X$ sa fie multiplu de {$K$}. Fie $REZ$ rezultatul minim. La inceput {$REZ = 1$}. Pentru fiecare termen de forma {$p{~i~}^e{~i~}^$} din descompunerea in factori primi a numarului $M$ inmultim $REZ$ cu {$p{~i~}^K - e{~i~}%K^$}, unde {$a % b$} reprezinta restul impartirii lui $a$ la $b$ daca $a$ nu este multiplu de $b$ si $b$ altfel.\r\nDeoarece rezultatul poate fi foarte mare, este necesara implementarea operatiilor pe numere mari. Idei privitoare la implementarea operatiilor pe numere mari gasiti \'aici\':http://infoarena.ro/multe-smenuri-de-programare-in-cc-si-nu-numai. ',256,'public',NULL,NULL),('preoni-2008/runda-4/solutii/garaj','preoni-2008/runda-4/solutii/garaj','2008-02-17 11:25:26','2008-02-20 14:22:22','h2(#garaj). \'Garaj\':problema/garaj\r\n\r\nObservam ca daca in timpul $T$ putem termina transportul, atunci transportul poate fi terminat si la momentele de timp mai mari decat $T$. Deci putem cauta binar timpul maxim in care circula un camion. Pentru un timp $T$ fixat, vom vedea care este numarul maxim de sticle care pot fi duse la adapost, daca acest numar este mai mare sau egal decat $M$, timpul fixat este unul valid si vom incerca sa gasim un timp mai mic, altfel vom incerca un timp mai mare. Dupa ce am minimizat timpul maxim in care circula un camion, vom sorta camioanele descrescator dupa numarul de sticle pe care il pot transporta in acest timp si vom alege pe rand cate un camion incepand cu primul pana cand numarul de sticle pe care il pot transporta toate camioanele alese va fi mai mare sau egal cu $M$.\r\n',2092,'public',NULL,NULL),('preoni-2008/runda-4/solutii/nivele','preoni-2008/runda-4/solutii/nivele','2008-02-17 11:27:40','2008-02-20 20:13:40','h2(#nivele). \'Nivele\':problema/nivele\r\n\r\nPentru a determina daca un sir de numere poate reprezenta nivelele frunzelor dintr-un arbore binar vom incerca sa determinam daca putem construi arborele eliminand frunze din arbore. Daca exista doua frunze aflate pe pozitii adiacente in vector si care au aceasi valoarea, le putem elimina din arbore, lasand in loc o frunza pe nivelul $L-1$. Daca la final in vector o singura frunza pe nivelul $1$ atunci putem raspunde cu $DA$. Putem implementa eficient acest algoritm folosind o stiva. Se parcurg frunzele de la stanga la dreapta si la fiecare pas se verifica nivelul frunzei curentei cu nivelul frunzei din varful stivei:\r\n\r\n* daca sunt diferite se insereaza nivelul curent in stiva\r\n* daca sunt egale se scoate frunza din varful stivei, iar nivelul frunzei curente scade cu $1$\r\n\r\nLa final, se verifica daca in stiva a ramas o singura frunza cu nivelul $1$.\r\n\r\n\r\n',1,'public',NULL,NULL),('preoni-2008/runda-4/solutii/arbori','preoni-2008/runda-4/solutii/arbori','2008-02-17 11:28:06','2008-02-20 21:01:49','h2(#arbori). \'Arbori\':problema/arbori\r\n\r\nProblema se rezolva prin programare dinamica. Se construieste o matrice $A[i][j][k]$ numarul de arbori cu urmatoarele proprietati:\r\n\r\n* au $i$ noduri\r\n* gradul radacinii este $j (mod M)$\r\n* ultimul fiu al radacinii este un subarbore cu $k$ noduri\r\n* fiecare nod intern din arbore (mai putin radacina) are gradul $K (mod M)$\r\n\r\nRaspunsul se va gasi in $A[N][K][N]$. Arborii fiind neetichetat, ordinea fiilor nu conteaza, asadar putem considera ca fiecare nod are fiii in ordine crescatoare a numarului de noduri din subarbore. \r\n\r\nPentru a calcula $A[i][j][k]$ vom itera o variabila $x$ dupa numarul de fii ai radacinii cu fix $k$ noduri in subarbore. Astfel, pentru fiecare $x$ intre $0$ si $i/k$ vom aduna la $A[i][j][k]$ valoarea $A[i-x*k][(j-x) mod M][k-1] * Nr(k, x)$ unde $Nr(k, x)$ este numarul de moduri in care se pot aranja $x$ subarbori cu $k$ noduri fiecare. Stim ca pentru subarborii de $k$ noduri avem $A[k][(K-1) mod M][N]$ posibilitati ({$K-1$} deoarece ii legam de o radacina). Dintre toate aceste posiblitati trebuie sa alegem $x$, tinand cont de faptul ca ordinea nu conteaza. Numarul pe care il cautam va fi $Nr(k, x) = Comb(A[k][(K-1) mod M][N]+x-1, x)$, deoarece $Comb(n+k-1, k)$ reprezinta numarul de moduri in care $n$ obiecte identice pot fi distribuite in $k$ cutii distincte.\r\nComplexitatea spatiu a rezolvarii este $O(N^2^*M)$, iar complexitatea timp este $O(N^2^*M*lg N)$, deoarece $N/1+N/2+N/3...N/N = N*lg N$ (cand iteram $x$ iteram doar pana la $i/x$). Desigur, am presupus ca putem calcula combinarile in $O(1)$. Acest lucru chiar este posibil, presupunand ca avem valoarea combinarii pentru $x$, putem determina valorea pentru $x+1$ in $O(1)$. Datorita limitelor mici, se putea obtine punctaj maxim si calculand combinarile in $O(x)$, obtinand astfel o solutie $O(N^3^*M)$. Rezolvarea se mai poate optimiza folosind tehnica de memoizare.',1,'public',NULL,NULL),('preoni-2008/runda-4/solutii/lampa','preoni-2008/runda-4/solutii/lampa','2008-02-17 11:25:07','2008-02-17 12:31:19','h2(#lampa). \'Lampa\':problema/lampa\r\n\r\n\r\nFie {$x{~i~}$} sirul de cuvinte obtinute. {$x{~0~}$} si {$x{~1~}$} sunt doua siruri initiale, iar, in rest, avem relatia {$x{~i~}$} = {$x{~i-1~}$} + {$x{~i-2~}$}, pentru orice {$i > 1$}, unde {$a + b$} reprezinta concatenarea sirurilor de caractere {$a$} si {$b$}. Daca ni se da {$x{~N~}$} trebuie sa determinam {$x{~0~}$} si {$x{~1~}$}. Sa notam {$x{~0~}$} = $A$ si {$x{~1~}$} = $B$ ( $A$ si $B$ sunt siruri de caractere ). Sirul $x$ va avea forma: {$A$}, {$B$}, {$AB$}, {$BAB$}, {$ABBAB$}, {$BABABBAB$}, etc. Se observa ca numarul de siruri $A$ din al $N$-lea termen este {$fib{~N-2~}$}, iar numarul de $B$ este {$fib{~N-1~}$}, unde $fib$ este sirul lui Fibonacci ({$fib{~0~}$} = {$fib{~1~}$} = $1$ si {$fib{~n~}$} = {$fib{~n-1~}$} + {$fib{~n-2~}$} pentru orice {$n > 1$}).\r\nFie $M$ = {$length(x{~N~})$}. Avem relatia: $M$ = {$length(A)$} * {$fib{~N-2~}$} + {$length(B)$} * {$fib{~N-1~}$} (*). Aflam toate solutiile {$(length(A), length(B))$} ale ecuatiei de mai sus. Pentru aceste lungimi $A$ si $B$ sunt unic determinate, in functie de paritatea lui {$N$}:\r\n\r\n* Daca $N$ este par, $A$ este egal cu primele {$length(A)$} caractere din {$x{~N~}$} si $B$ este egal cu urmatoarele {$length(B)$} caractere.\r\n* Daca $N$ este impar, $B$ este egal cu primele {$length(B)$} caractere din {$x{~N~}$} si $A$ este egal cu urmatoarele {$length(A)$} caractere.\r\n\r\nPentru $A$ si $B$ determinate verificam in complexitate {$O(M)$} daca intr-adevar al $N$-lea termen al sirului pornind de la $A$ si $B$ este sirul dat si, in caz afirmativ afisam perechea {$(A B)$}.\r\n\r\nAcest algoritm este in practica foarte rapid deoarece {$fib[N]$} atinge foarte repede valori mari. Pentru testele date, dupa cum reiesea si din tabelul din restrictiile problemei, avem:\r\n\r\ntable(example). |_. Test |_. N  |_. M |_. Numarul de solutii ale ecuatiei (*) |\r\n|1|8|523|5|\r\n|2|8|4200|40|\r\n|3|10|5001|7|\r\n|4|9|8910|32|\r\n|5|7|46189|1155|\r\n|6|6|88600|5906|\r\n|7|25|346468|1|\r\n|8|14|590005|17|\r\n|9|15|1010860|12|\r\n|10|17|3027197|6|\r\n\r\nSe observa ca pe cele 10 teste folosite la corectare {$O(M) * O(numar_de_solutii_ecuatie)$} este relativ mic, deci o astfel de rezolvare garanteaza obtinerea punctajului maxim.\r\n',256,'public',NULL,NULL),('winter-challenge-2008/runda-2/solutii','Solutii Winter Challenge 2008, Runda 2','2008-02-24 10:11:18','2008-02-24 19:14:20','h1. Solutii Winter Challenge 2008, Runda 2\r\n\r\n{@ @}\r\n{@ @}\r\nCu aceasta runda se incheie \"editia 2008 a concursului Winter Challenge\":winter-challenge-2008. Sper ca a fost pe placul tuturor participantilor pe care ii asteptam si anul viitor, la urmatoarea editie. \r\n\r\nFata de \"Runda 1\":winter-challenge-2008/runda-1 punctajele si numarul participantilor au fost mult mai mari, lucru care nu a putut decat sa ne bucure. Am avut si doua punctaje maxime obtinute de \"Filip Stefan\":utilizator/Prostu si \"Victor Rusu\":utilizator/victorsb care au reusit sa rezolve corect ambele probleme. \"Runda 2\":winter-challenge-2008/runda-2 a fost si un bun prilej de antrenament pentru OJI, care bate la usa.\r\n\r\nFelicitari \"tuturor participantilor\":winter-challenge-2008/clasament/runda-2, iata primii clasati:\r\n\r\n==Rankings(rounds=\"winter2008-2\" display_entries=\"4\" pager_style=\"none\")==\r\n\r\nIl felicitam pe \"Stefan Istrate\":utilizator/stef2n care nu mai este elev, ci student in anul I la \"Facultatea de Matematica si Informatica\":http://fmi.unibuc.ro/ro si fost membru al lotului national in ultimii 2 ani. De asemenea ii felicitam pe Filip, Victor si \"Cosmin\":utilizator/gcosmin care nu mai au nevoie de nicio prezentare.\r\n\r\nVreau ca pe aceasta cale sa ii multumesc si lui \"Mugurel Ionut Andreica\":utilizator/mugurelionut pentru ca a acceptat sa colaboram si in acest an. Ca si la prima runda, le multumesc lui \"Andrei Grigorean\":utilizator/wefgef, \"Adrian Airinei\":utilizator/astronomy si lui \"Cristian George Strat\":utilizator/wickedman pentru sprijinul acordat, cat si intregii \"echipe infoarena\":echipa-infoarena. \r\n\r\nNu in ultimul rand va multumesc \"voua\":winter-challenge-2008/clasament, cei care ati participat la acest concurs.\r\n\r\nMult succes in continuare si bafta la OJI,\r\nVaru.\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Siguranta Nationala\':winter-challenge-2008/runda-2/solutii#sn\r\n* \'Joc pe grid\':winter-challenge-2008/runda-2/solutii#jpg\r\n\r\n\r\n\r\n==include(page=\"winter-challenge-2008/runda-2/solutii/sn\")==\r\n\r\n==include(page=\"winter-challenge-2008/runda-2/solutii/jpg\")==\r\n',1,'public',NULL,NULL),('preoni-2008/runda-4/solutii/carnati','Solutie','2008-02-17 11:26:20','2008-02-17 21:41:08','h2(#carnati). \'Carnati\':problema/carnati\r\n\r\nPrima observatie pe care o facem este faptul ca pretul fixat de Gigel va fi unul dintre preturile clientilor sai. Odata ce avem fixat un pret {$X$} putem sa construim o dinamica {$A{~i~}$} profitul maxim daca magazinul este deschis in momentul in care trece clinetul {$i$} (clientii vor fi sortati crescator dupa timpul la care trec). Relatia de recurenta se observa usor {$A{~i~}= max(A{~i-1~}-(T{~i~}-T{~i-1~})*C+G,G-C$}), unde {$G$} este {$X$} pentru {$X &le; P{~i~}$} sau {$0$} in caz contrar. De fapt, avand fixat {$X$} si construind vectorul {$H{~2*i~}=G-C$}, {$H{~2*i+1~}={@-@}(T{~i~}-T{~i-1~})*C$} problema se reduce la determinarea subsecventei de suma maxima.\r\n\r\nComplexitatea de rezolvare pentru {$X$} fixat este {$O(N)$}, deci in final algoritumul va fi {$O(N^2^)$}',961,'public',NULL,NULL),('preoni-2008/runda-4/solutii/koba','preoni-2008/runda-4/soluti/koba','2008-02-18 10:40:31','2008-02-18 10:56:15','h2(#koba). \'Koba\':problema/koba\r\n\r\nh3. Solutia 1 (neoptima)\r\n\r\nO solutie neoptima ar fi parcurgerea de la $1$ la $N$ si adaugarea fiecarei cifre cerute la suma. Acest lucru se face folosind doar ultimele cifre din numere, pentru a nu implementa pe numere mari, cu formula $T{~i~}=(T{~i-1~}+T{~i-2~}*T{~i-3~}) % 10$. Complexitatea acestei solutii este $O(N)$.\r\n\r\nh3. Solutia 2\r\n\r\nPentru o solutie optima, se observa ca, de la un moment dat, sirul devine periodic. Fie numarul $abc$ care reprezinta $3$ cifre $a, b$ si, respectiv, $c$.\r\nTinem un vector in care $A[abc]$ va reprezenta pozitia pe care a aparut tripletul $a, b, c$ in sirul pe care l-am construit pana la momentul respectiv. Parcurgand cu un indice $i$ de la $1$ la $N$ si adunand in suma $S$ cifrele folosite pana la momentul actual, daca la un moment dat, un triplet $a, b, c$ va aparea pentru a doua oara, facem suma cifrelor (notata cu $Sum$) de la ultima aparitie a celor $3$ cifre pana la momentul actual si memoram in $M$ numarul de cifre din aceasta suma $(i-A[abc]+1)$. In acest moment, stim suma cifrelor pana la pasul $i$. Acum trebuie aflata suma cifrelor de la $i+1$ la $N$. Pentru a afla acesta suma, scadem din $N$ pe $i$ (pentru a afla suma cifrelor de dupa $i$) si vedem de cate ori intra in \"noul\" $N$ acea secventa \"periodica\" si adunam $(N/M)*Sum$ la $S$. Pana acum am calculat suma cifrelor pana la cel mai mare multiplu al lui $M$ mai mic decat $N$. De aici mai adaugam la $S$ primele $N%M$ cifre din partea periodica.',3997,'public',NULL,NULL),('blog/doi-la-suta','Sprijina Asociatia infoarena! Directioneaza 2%','2008-02-18 13:23:56','2008-02-18 13:25:37','Directioneaza catre noi 2% din impozitul pe venit datorat la stat.\r\n\r\nIn conformitate cu prevederile \'Codului Fiscal, art. 84\':http://www.edex.ro/articol_cod_fiscal_16661_Art.%2084:%20Stabilirea%20si%20plata%20impozitului%20pe%20venitul%20net%20anual%20impozabil.html poti directiona 2% din impozitul pe venit datorat la stat catre o entitate non-profit (i.e. Asociatia infoarena).\r\n\r\nProcedura este foarte simpla si nu te costa nimic!\r\n\r\n&rarr; \'*Vezi cum se face*\':doi-la-suta\r\n',13,'protected',NULL,NULL),('planificare/sedinta-20080218','Sedinta 2008-02-18','2008-02-03 13:21:30','2008-02-18 18:08:24','h1. Sedinta 2008-02-18\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *luni* la ora *18:00* la \'*ICHB*\':http://www.ichb.ro.\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* _&hellip; asteptam confirmari_\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioara\':planificare/sedinta-20080201\r\n* preONI 2008 update\r\n* Brainstorm *infoarena.ro/research* (o sectiune dedicata studentilor interesati de algoritmica teoretica, sisteme, CS in general in care se anunta conferintele/evenimentele importante)\r\n** Idei preliminare:\r\n*** www.infoarena.ro/research - un mini-blog in care se anunta conferintele (cand stim de ele) cu comentarii, bibliografie si note postate dupa conferinta\r\n*** mailing list/google calendar asociat care sa te anunte inainte de conferinta :)\r\n* \'Hackaton\':planificare/hackaton\r\n** Cum facem preselectia studentilor?\r\n** Tema?\r\n* votat IAP #6\r\n* development\r\n* stabilit locatie si data pentru sedinta urmatoare\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* [2/3] Cristi redacteaza IAP de community ladder\r\n* [2/3] Cristi face IAP de almanah\r\n* Silviu il invita pe Malex la sedinta urmatoare pentru feature de stack trace\r\n* Cristi scrie cerere pentru problema de card la Raiffeisen.\r\n* Vorbesc cu Vali sa schimbe culorile pentru fundal alb\r\n* Adi a gasit surse de probleme, face lista si pune lumea la treaba\r\n* Mircea cloneaza search-ul pe un cont Google neutru, il instaleaza pe site si ii da lui Stefan parola ca sa-l imbunatateasca\r\n* Intalnirea urmatoare pe 2008-03-03\r\n* Alexandra contacteaza prin email lista preliminara a finalistilor preONI: telefoane (el si parinti), clasa, liceu, tricou, insotitor?\r\n* Ne place solutia cu UPB daca primim cazare, masa si laboratoare. Trebuie sa aflam cu ce ne influenteaza alegerile UPB. Mergem pe 2008-02-19 cu Silviu sau cu Mugurel. Cristi vine cu o prezentare infoarena printata.\r\n* Mircea semneaza ca participantii la finala nu au trisat :)\r\n* Cristi si Silviu contacteaza Adobe sa stabilim intalnire despre preONI si hackaton\r\n\r\nh2. Notite\r\n\r\n* Vali face profiler?\r\n',13,'public',NULL,NULL),('blog/imaginecup','Imagine Cup','2008-02-20 07:25:43','2008-11-20 17:20:00','Microsoft promoveaza pe \'trilulilu\':http://www.trilulilu.ro/ concursul pentru elevi si studenti Imagine Cup. Concursul are sectiuni diverse precum cea de algoritmi, software design si embedded development. Studentii romani au obtinut rezultate destul de bune anul trecut, cativa calificandu-se in etapa finala a concursului desfasurata la Seul.\r\n\r\nPuteti vedea un mic promo al concursului de anul acesta:\r\n\r\n==TriluliluVideo(user=\"microsoft\" id=\"4bbc23d5de1524\")==\r\n\r\nAici un interviu cu echipa 921UBB finalista a sectiunii de software design:\r\n\r\n==TriluliluVideo(user=\"microsoft\" id=\"fea6e79eb1abc3\")==\r\n\r\n(fac treaba buna colegii mei de la Babes :) )\r\n\r\nIar aici un interviu cu echipa TechOwls finalista a sectiunii embeded development (Liviu Ciortea, un membru al echipei, e si un utilizator vechi al comunitatii infoarena si a propus cateva probleme):\r\n\r\n==TriluliluVideo(user=\"microsoft\" id=\"73a203269b3a7b\")==\r\n\r\nImi place sa vad ca se promoveaza astfel de concursuri si studentii care obtin rezultate. Incercati si voi sa participati anul asta!',1851,'protected',2727,NULL),('runda/winter2008-2','winter2008-2','2008-02-20 09:57:06','2008-02-20 09:57:06','h1. == roundparam(round_id=\"winter2008-2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"winter2008-2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"winter2008-2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"winter2008-2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':winter2008-2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"winter2008-2\" score=\"1\")==',2092,'round: winter2008-2',NULL,NULL),('runda/winter2008-2/clasament','Clasament winter2008-2','2008-02-20 09:57:06','2008-02-20 09:57:06','h1. Clasament ==roundparam(round_id=\"winter2008-2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"winter2008-2\")==',2092,'round: winter2008-2',NULL,NULL),('winter-challenge-2008/runda-1','Winter Challenge 2008','2008-01-24 14:33:09','2008-02-20 10:33:31','h1. Winter Challenge 2008\r\n\r\n(htabs)* \'Despre concurs\':winter-challenge-2008/\r\n*(active) \'Runda 1\':winter-challenge-2008/runda-1\r\n* \'Runda 2\':winter-challenge-2008/runda-2\r\n* \'Clasament\':winter-challenge-2008/clasament\r\n\r\nRunda va incepe *Duminica 27 ianuarie*, la ora {*09^00^*} si va dura *5h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\n== roundregister(round_id=\"winter2008-1\") ==\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"winter2008-1\" score=\"1\")==\r\n\r\nSolutiile le gasiti \'aici\':winter-challenge-2008/runda-1/solutii.\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 1\':winter-challenge-2008/clasament/runda-1\r\n\r\nh2. Organizatori\r\n\r\n* ==User(user=\"fireatmyself\" type=\"tiny\")==\r\n* ==User(user=\"mugurelionut\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==',2092,'protected',NULL,NULL),('winter-challenge-2008/clasament/runda-1','Clasament Winter Challenge 2008, runda 1','2008-02-20 10:39:11','2008-02-20 10:39:11','==Rankings(rounds = \"winter2008-1\")==',2092,'protected',NULL,NULL),('winter-challenge-2008/clasament/runda-2','Clasament Winter Challenge 2008, runda 2','2008-02-20 10:41:56','2008-02-24 10:57:35','h1. Clasament Winter Challenge 2008, runda 2\r\n\r\n==Rankings(rounds = \"winter2008-2\")==',1,'protected',NULL,NULL),('winter-challenge-2008/runda-2','Winter Challenge 2008','2008-02-20 10:00:55','2008-02-21 15:45:23','h1. Winter Challenge 2008\r\n\r\n(htabs)* \'Despre concurs\':winter-challenge-2008/\r\n* \'Runda 1\':winter-challenge-2008/runda-1\r\n*(active) \'Runda 2\':winter-challenge-2008/runda-2\r\n* \'Clasament\':winter-challenge-2008/clasament\r\n\r\nRunda va incepe *Duminica 24 februarie*, la ora {*09^00^*} si va dura *3h*. Participantii vor avea de rezolvat 2 probleme de factura algoritmica. Nivelul problemelor va fi asemanator cu OJI, avand in vedere ca olimpiada judeteana se apropie acest concurs ar putea fi o buna ocazie de antrenament. Cele doua probleme variaza in dificultate, astfel orice persoana de orice varsta este incurajata sa participe:).\r\n\r\n== roundregister(round_id=\"winter2008-2\") ==\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"winter2008-2\" score=\"1\")==\r\n\r\nh2. Clasament\r\n\r\n\'Clasament runda 2\':winter-challenge-2008/clasament/runda-2\r\n\r\nh2. Organizatori\r\n\r\n* ==User(user=\"fireatmyself\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n',2092,'protected',NULL,NULL),('preoni-2008/runda-4/solutii/stalpi','preoni-2008/runda-4/solutii/stalpi','2008-02-17 11:26:39','2008-02-20 15:26:08','h2(#stalpi). \'Stalpi\':problema/stalpi\r\n\r\nVom sorta stalpii dupa coordonata $X$ si vom calcula $best[n]$ = costul minim pentru a acoperi primii $n$ stalpi (dupa sortare). De asemenea vom sorta stalpii dupa valoarea $X+D$ si aceasta va fi ordinea in care ii vom procesa. Cand procesam stalpul $i$ (din ordinea sortata dupa $X+D$) vom afla $R$, cel mai din dreapta stalp pentru care $X{~R~} &le; X{~i~}+D{~i~}$ si $L$, cel mai din dreapta stalp pentru care $X{~L~} < X{~i~}-S{~i~}$. Atunci o valoare posibila pentru $best[ R ]$ ar fi $min(best[L], best[L+1]...best[N])+cost[i]$. Daca $best[ R ]$ si-a imbunatatit vechea valoare (initial vectorul $best$ va fi initializat cu infinit) atunci pentru $1&le;j&le;R best[j]=min(best[j],best[ R ])$. Pentru a implementa eficient operatiile descrise se poate folosi un \'arbore de intervale\':arbori-de-intervale, sau mai simpu de implementat, un \'arbore indexat binar\':http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=binaryIndexedTrees.\r\n',2092,'public',NULL,NULL),('blog/la-inceputul-sezonului-competitional','La inceputul sezonului competitional','2008-02-20 23:29:36','2008-11-15 13:41:14','Dupa cum \'ne anuntase\':blog/vine-olimpiada Cosmin, sezonul olimpiadelor scolare a inceput si elevii talentati din toata tara se pregatesc de fazele din ce in ce mai avansate ale concursului national de informatica. Locala s-a terminat deja, si fiecare noua proba creste nu doar nivelul problemelor propuse spre rezolvare, ci si intensitatea emotiilor participantilor. Desi unii elevi buni au trait o mica tragedie nereusind sa se califice pe judet (daca va incalzeste cu ceva, am trecut si eu prin asta si am considerat-o pana la urma ca pe o experienta pozitiva - desi de-abia dupa cativa ani am ajuns la aceasta concluzie), majoritatea celor care s-au pregatit serios pe parcursul anului se gandesc acum la etapa judeteana, poate cea mai stresanta dintre toate.\r\n\r\nOricat de neimportant vi se pare acest sfat in comparatie cu modalitatile de asimilare a algoritmilor avansati, nu stiu cum sa va fac sa-l intelegeti cat mai bine: *Abordati olimpiada cu o atitudine pozitiva. Nu va ganditi la lucrurile pe care le-ati putea pierde, ci la cele pe care le aveti de castigat.*\r\n\r\nNu trebuie neaparat s-o recunoasteti fata de altii, dar noi, fostii \"olimpici\", o stim prea bine: de multe ori va ganditi mult mai mult la ce s-ar intampla in cazul unui esec decat la urmarile pe care le-ar avea un eventual succes. Priviti atat OJI cat si ONI ca pe acele momente ale anului in care sunt sanse sa-i dezamagiti pe cei din jurul vostru (parinti, profesori, colegi), si sa simtiti ca tot efortul investit s-a dus pe apa sambetei. Si asta va face sa va consumati inutil cu sentimente negative (nu esti afectat doar atunci cand te vezi \"sub linie\", ci mai ales in orele / zilele / saptamanile in care te intrebi cum ar fi ca dupa atata munca o greseala stupida sau lipsa de inspiratie pe moment sa produca o astfel de nenorocire). O afirm cu maxima convingere, avand in vedere ca eu insumi am trecut prin asta, si nu o data. Ii aud, de asemenea, pe elevii de azi spunand lucruri ca: \"am facut prost, dar macar nici X de la mine din liceu nu s-a calificat\". Unde credeti ca poate duce acest stil de \"competitie\"?\r\n\r\nFiti un pic sinceri cu voi insiva: in ce context va ganditi la iminenta judetenei? Daca o puneti alaturi de excursia pe care o veti face la munte cu clasa, sau cu jocul super-tare care se va lansa luna viitoare, e bine. Perspectiva olimpiadei va bucura, deoarece e o activitate pe care o faceti in primul rand din placere, asa cum si trebuie. Dar nu cumva intrati intr-o stare de frenezie, incercand sa invatati un milion de noi metode de rezolvare a problemelor (care nu va vor intra in cap peste noapte, din moment ce ingrasarea porcului in ajun chiar NU functioneaza), facand calcule si pronosticuri despre sansele concurentei si gandindu-va la toate lucrurile care ar putea merge prost? Bineinteles, nu va recomand sa va relaxati total cu convingerea ca nu mai puteti schimba nimic, dar opriti-va un moment pentru a va gandi la ceea ce faceti si la ce impact are starea asta de neliniste sufleteasca asupra voastra.\r\n\r\n*In urma fazei judetene a olimpiadei, nu puteti pierde nimic. Daca credeti ca puteti pierde participarea la olimpiada nationala, asta arata ca ati comis o greseala provenita din infumurare: cum ati putea pierde un lucru pe care acum nu-l aveti? Va considerati deja calificati? Foarte rau. \"Olimpiada\" inseamna ca fiecare are sansa lui, si ca nu exista castigatori sau pierzatori stabiliti anterior concursului.*\r\n\r\nPoate ca observatiile de aici nu sunt pe placul tuturor, dar ele nu au aparut, cu siguranta, din senin. Nu esti un om rau, slab sau prost daca te concentrezi mai mult pe evitarea esecului decat pe obtinerea reusitei. Participantii la concursurile de informatica au foarte multe calitati pe care altii si le-ar dori, dar de multe ori lucrurile pe care ei le realizeaza sunt sub adevaratul lor potential. Lasati altora fatalitatea, superstitiile si gandul rau pus caprei vecinului si priviti cu incredere la oportunitatile pe care fazele superioare ale olimpiadei vi le ofera.\r\n\r\nSpor la treaba!',1490,'protected',2732,NULL),('preoni-2008/runda-4/solutii/heavymetal','preoni-2008/runda-4/solutii/heavymetal','2008-02-17 11:24:01','2008-02-21 10:10:39','h2(#heavymetal). \'Heavy metal\':problema/heavymetal\r\n\r\nO solutie care ar fi obtinut aproximativ 40 de puncte ar fi putut fi urmatoarea: ne construim un vector Best[i], reprezentand timpul total maxim in care vor canta formatii daca fiecare concert se va termina inainte de ora i. Rezultatul cautat se va afla in Best[Tmax], unde Tmax va fi timpul maxim de terminare a unui concert. Relatia de recurenta va fi:\r\n\r\n==code(c)|pentru i de la 1 la Tmax\r\n    Best[i] = Best[i-1];\r\n    pentru fiecare concert j cu B[j] = i\r\n        Best[i] = max(Best[i], Best[A[j]] + (B[j] - A[j]))\r\n==\r\n\r\nSolutia ce ar fi obtinut punctajul maxim nu reprezinta nimic altceva decat o rafinare a acestui algoritm. Observam ca valorile A[i] si B[i] sunt foarte mari, iar pentru a rezolva aceasta problema le vom normaliza. Vom sorta intervalele in functie de timpul de terminare si vom calcula Best[i] doar pentru valorile in care exista cel putin un concert care se termina la timpul i.\r\n\r\n\r\n',2028,'public',NULL,NULL),('donatii','Donatii PayPal','2008-02-22 02:56:15','2008-11-20 14:25:35','==infoarenaPayPal()==\r\n',1490,'protected',NULL,NULL),('winter-challenge-2008','Winter Challenge 2008','2008-01-24 14:17:56','2008-02-22 15:38:09','h1. Winter Challenge 2008\r\n\r\n(htabs)*(active) \'Despre concurs\':winter-challenge-2008/\r\n* \'Runda 1\':winter-challenge-2008/runda-1\r\n* \'Runda 2\':winter-challenge-2008/runda-2\r\n* \'Clasament\':winter-challenge-2008/clasament\r\n\r\nh2. Detalii\r\n\r\nCa si anul trecut, in preajma olimpiadelor (de informatica, bineinteles), infoarena iti laseaza inca o provocare. Concursul **Winter Challenge** a ajuns la a **II**-a editie.\r\n\r\nSpre deosebire de anul trecut, va exista doar o singura grupa de varsta. In schimb, vom organiza doua runde. In prima runda concurentii vor avea de rezolvat 3 probleme in 5 ore, dificultatea subiectelor fiind la niveulul \"Olimpiadei Nationale de Informatica\":http://olimpiada.info/, sau la nivelul concursului \"preONI\":preoni-2008. Runda a doua va fi o buna ocazie de antrenament pentru OJI, concurentii avand de rezolvat 2 probleme in 3 ore.\r\n\r\nVa asteptam in numar cat mai mare si speram sa acumultai punctajele dorite. \r\n\r\nMult succes!\r\n\r\nh2. Program concurs\r\n\r\ntable{width: 50%}. |_. Runda|_. Data |_. Ora |\r\n|\"*Runda 1*\":winter-challenge-2008/runda-1|*Duminica, 27 ianuarie 2008*| *9^00^ - 14^00^* |\r\n|\"*Runda 2*\":winter-challenge-2008/runda-2|*Duminica, 24 februarie 2008* | *9^00^ - 12^00^* |\r\n\r\nClick pe titlul unei runde pentru informatii mai detaliate.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* daca doresti sa ti se modifice rating-ul in urma participarii! *Daca nu te inscrii* nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum! Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru!\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti probleme, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':documentatie/evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nh2. Prima data pe _infoarena_?\r\n\r\n\'infoarena\':/ ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi si vezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n',2092,'protected',NULL,NULL),('newsletter/winter-challenge-2008/runda-2','Winter Challenge, Runda 2 - antrenament inainte de OJI','2008-02-22 12:47:59','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nTe invit sa participi la a doua (si ultima) runda a concursului\r\nWinter Challenge.\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Runda 2 se desfasoara...\r\n\np{padding-left: 2em;}. Duminica, 24 februarie 2008, orele 09:00 - 12:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nSe apropie OJI.  Runda aceasta este o ocazie buna de antrenament!\r\n\nVezi pagina concursului: \'winter-challenge-2008\':winter-challenge-2008\r\nca sa afli cum poti participa.\r\n\nSucces!\r\n\nh2.  Atentie! Concurs cu rating! \n\nDaca vrei sa ti se modifice rating-ul in urma acestei runde\r\ntrebuie sa iti anunti participarea din timp.  Intra pe\r\n\'winter-challenge-2008\':winter-challenge-2008 si inscrie-te la Runda 2.\r\n\nPoti sa participi la concurs chiar si daca nu te-ai inscris in\r\nprealabil insa nu ti se va modifica rating-ul.\r\n==NewsletterRating(username=\"%username%\")==\r\nCiteste despre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Despre Winter Challenge, Runda 2 \n\nDe data aceasta vei primi doua probleme de dificultate comparabila\r\ncu cele de la Olimpiada Judeteana de Informatica.\r\nTimpul de lucru este de 3h.\r\n\nOrganizatorii rundei 2 sunt:\r\n\np{padding-left: 2em;}. Bogdan A. Stoica\r\n    [  ==User(user=\"fireatmyself\" type=\"link\")==  ]\r\n\np{padding-left: 2em;}. Andrei Grigorean\r\n    [  ==User(user=\"wefgef\" type=\"link\")==  ]\r\n\np{padding-left: 2em;}. Airinei Adrian\r\n    [  ==User(user=\"astronomy\" type=\"link\")==  ]\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nRamai alaturi de noi.  Te ajutam sa devii olimpic!\r\nEchipa infoarena iti ureaza succes!\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('doi-la-suta','Sprijină Asociația infoarena! - Sistemul 2%','2008-01-28 21:09:12','2010-02-19 19:11:41','h1. Sprijină Asociaţia infoarena! - Sistemul 2%\r\n\r\n*_Direcţionează către noi 2% din impozitul pe venit datorat la stat._*\r\n\r\nbq. Sistemul \"2%\" permite contribuabililor persoane fizice să direcţioneze 2% din impozitul lor pe venit către o organizaţie neguvernamentală. Este un sistem prin care cetăţenii au posibilitatea să decidă în mod direct ce se întamplă cu impozitele lor. [...] Direcţionarea nu costă nimic. \'(Sursa)\':http://www.doilasuta.ro\r\n\r\n*Nu te costă nimic!* Impozitul pe venit rămâne acelaşi. \r\n\r\nÎncă de la lansarea acestui sistem în 2008, procedura a funcţionat. Fondurile direcţionate către infoarena până acum au fost:\r\n\r\ntable{width:200px}.\r\n|_. An |_. Suma |\r\n| 2009 | 7.892 RON |\r\n| 2008 | 4.620 RON |\r\n\r\nh2. La ce folosim contribuţiile\r\n\r\ninfoarena ajută elevi şi studenţi să înveţe informatică şi programare. De mai bine de 6 ani de zile organizăm concursuri de informatică, scriem articole, dezvoltăm software, facem schimb de experienţă şi idei. Ne-am organizat pe acest site deoarece împreună învăţăm mai bine. Dacă doreşti să citeşti mai multe despre ce facem noi, răsfoieşte secţiunea \'Despre infoarena\':despre-infoarena.\r\n\r\nVom folosi contribuţiile venite pe această cale să:\r\n\r\n* oferim premii: membrii comunităţii sunt mai motivaţi să se pregătească şi să participe la un concurs online de informatică atunci când se dau premii\r\n* organizăm finale de concursuri: în fiecare an organizăm \'un concurs\':algoritmiada-2010 cu finală; finala are menirea să ne strangă la un loc cu ce mai buni dintre elevii şi studenţii României pentru câteva zile şi să formăm noi prietenii\r\n* motivăm comunitatea să se \'implice\':implica-te\r\n* finanţăm \'proiecte infoarena\':propuneri\r\n\r\nVezi \'obiectivele infoarena\':okr pentru trimestrul curent şi \'rezoluţiile şi notiţele fiecărei şedinţe de consiliu\':planificare.\r\n\r\nh2. Ce trebuie să faci\r\n\r\nProcedura este foarte simplă. Ai grijă să te încadrezi în *termenul limită: 15 mai 2010*.\r\n\r\n# În funcţie de sursa ta de venit, descarcă, printează şi completează una din declaraţiile următoare:\r\n** Dacă ai venituri numai din salarii: \'declaraţia 230\':doi-la-suta?decl_230_2008.pdf\r\n** Dacă ai venituri (şi) din alte surse (cedarea folosinţei bunurilor, drepturi de autor etc): \'declaraţia 200\':doi-la-suta?decl_200_2008.pdf\r\n# Foloseşte următoarele date de identificare pentru Asociaţia infoarena:\r\n** *CUI*: 21752294\r\n** *IBAN*: RO15 RZBR 0000 0600 0919 4268, *Deschis la*: Raiffeisen, Ag. Unirea, Bucureşti\r\n** *Adresa sediu social*: Str. Dragoş Vodă Nr. 49, Bl. P9, Ap. 11, Bârlad, Jud. Vaslui\r\n# Depune declaraţiile completate la administraţia financiară de care aparţine domiciliul tău. Alternativ poţi să trimiţi declaraţia prin scrisoare recomandată către administraţia financiară.\r\n\r\nAlte informaţii utile:\r\n\r\n* Completează în două exemplare declaraţia corespunzătoare. Unul din exemplare trebuie depus la administraţia financiară, iar celălalt rămâne la tine.\r\n\r\n* Nu e nicio problemă dacă nu ştii exact suma care trebuie virată. Lasă rubrica \"Suma\" necompletată şi organul fiscal va calcula şi va vira suma admisă, conform legii\r\n\r\n* \'Adrese şi numere de telefon pentru administraţiile financiare din Bucureşti\':http://www.miculparis.ro/utile/administratie/administratii_financiare_bucuresti.html\r\n\r\n* \'Declaraţia 230 originală\':http://doilasuta.ro/pagini/resurse/decl_230_2008.pdf si \'Declaraţia 200 originală\':http://doilasuta.ro/pagini/resurse/decl_200_2008.pdf\r\n\r\n* \'Legislaţie pentru sistemul 2%\':http://doilasuta.ro/pagini/index.php?option=com_content&task=view&id=29&Itemid=45\r\n\r\nh2. Intrebări, sugestii\r\n\r\nDacă ai nelămuriri putem discuta pe forum:\r\n\r\n==SmfTopic(topic_id=\"2725\")==\r\n',2044,'protected',NULL,NULL),('utilizator/svalentin','svalentin\'s page','2006-11-24 20:56:19','2009-10-29 00:02:26','h2. infoarena\r\n\r\n* Intretin evaluatorul infoarena: ==User(user=\"eval\" type=\"tiny\")==\r\n* Buguri, sugestii, etc pe ==smflink(link=\"board\" board=\"33\" caption=\"forum\")==\r\n* Contact: svalentin - at - infoarena.ro\r\n\r\nh2. Despre mine\r\n\r\n* Anul III la facultatea de Automatica si Calculatoare din cadrul Universitatii Politehnice Bucuresti\r\n\r\n* Poze de la diferite evenimente - \'picasaweb\':http://picasaweb.google.com/valentin.stanciu\r\n* Cont pe deviantart - \'valentin-stanciu\':http://valentin-stanciu.deviantart.com (fotografii)\r\n** samples:\r\n*** !utilizator/svalentin?School_Musician_by_svNightBlade.jpg!:http://www.deviantart.com/deviation/28295559/\r\n*** !utilizator/svalentin?Panoramic_mountains_by_svNightBlade.jpg!:http://www.deviantart.com/deviation/35987288/\r\n\r\nh2. Distinctii primite\r\n\r\n* premiul I ONI in clasa a 8-a  (2004)\r\n* premiul I ONI in clasa a 10-a (2005)\r\n* Medalie de argint la concursul Tuymaada din Yakutia (2005)\r\n* premiul I ONI in clasa a 11-a (2006)\r\n* membru al lotului national de informatica din 2006\r\n* premiul II ONI clasa a 12-a (2007) --> Felicitari wefgef ;)\r\n* membru al lotului national de informatica din 2007\r\n* more small stuff',75,'protected',NULL,NULL),('flux','Retele de transport','2008-02-22 21:53:39','2008-02-22 21:56:18','Click \'aici\':flux?action=download&file=flux.zip pentru a downloada arhiva.',2092,'protected',NULL,NULL),('winter-challenge-2008/runda-2/solutii/jpg','winter-challenge-2008/runda-2/solutii/jpg','2008-02-24 10:24:43','2008-03-10 20:28:31','h2(#jpg). \'Joc pe grid\':problema/jpg\r\n\r\nAceasta problema are solutii a caror complexitate creste gradat, incercand sa fie accesibila cat mai multor concurenti.\r\n\r\nPentru toate cele trei solutii este necesara urmatoarea observtie: toate segmentele date in fisierul de intrare, care nu formeaza un patrat complet de latura $1$, sunt considerate redundante si, deci, trebuie eliminate.\r\n\r\nh3. Solutia de 30 de puncte (clasa a 9-a si clasa a 10a nivel incepator)\r\n\r\nPentru $N &le; 13$ figurile care se pot forma sunt asemanatoare cu cele ale jocului Tetris:\r\n\r\n!winter-challenge-2008/runda-2/solutii/jpg?f1.bmp!\r\n\r\nAstfel sunt doar $12$ categorii de constructii ce respecta specificatiile enuntului. Pentru fiecare figura se poate calcula \"de mana\" daca este castigatoare (negru) sau nu (rosu). Pentru a verifica rapid carei constructii ii corespund segmentele descrise in input, cele $12$ configuratii se pot tine in $12$ matrici care au elementele $1$ sau $0$ (vezi exemplul de mai jos).\r\n\r\n\r\n== code(c) |    1 0 0        0 0 0        0 1 0\r\nM1: 1 0 0    M2: 0 1 0    M3: 1 0 1\r\n    1 1 0        1 1 1        0 0 0   ...==\r\n\r\nIn acelasi mod poate fi memorata si figura din input si se poate raspunde in O({$N^3^$}) la cerinta problemei.\r\n\r\nh3. Solutia de 60 de puncte (clasa a 10-a nivel avansat, clasele 11-12 nivel incepator)\r\n\r\nEste usor de observat ca, daca $N$-ul creste, numarul configuratiilor creste si el, iar raspunsurile nu se mai pot precalcula atat de usor.\r\n\r\nSa abordam altfel problema. Pentru $N &le; 23$ este intuitiv ca trebuie sa gasim un algoritm de complexitate, aproximativ, $O(2^N^)$ ({$8.388.608$} de operatii se incadreaza lejer in limita de timp).\r\nLa un moment dat, un segment poate sa fie colorat sau sa nu fie colorat. De aceea, cele $N$ laturi pot fi reprezentate ca un numar in baza $2$, in care fiecare bit retine starea unui segment ({$1$}-colorat, $0$-necolorat). Se observa ca acest numar nu are mai mult de $23$ de biti si nu depaseste $8.388.608$ ({$2^23^$}).\r\nFie $A{~i~}$ = $1$ daca pentru configuratia $i$ +jucatorul aflat la mutare+ are strategie de castig sau $0$ in caz contrar. Valorile lui $A$ se pot calcula recursiv, dar facand cateva optimizari, pentru a se incadra in limita de timp:\r\n\r\n# (cea mai importanta) vom folosi memoizarea pentru a nu calcula de mai multe ori valoarea pentru acelasi $i$\r\n# la fiecare pas se elimina segmentele care nu mai fac parte din niciun patrat de $1x1$\r\n# (sau 2\') putem reprezenta figura la un moment dat ca o matrice fiecare celula tinand informatii despre segmentele ce ii definesc conturul; cu alte cuvinte, $M{~i~}{~j~}$ va fi un numar cu $4$ biti, primul bit reprezentand starea laturii din stanga a patratului $(i,j)$, al doilea - starea laturii de sus, al treilea - starea laturii din dreapta si in final, al patrulea - starea laturii de jos; asadar, matricea va avea elemente doar din multimea ${1,2,4,8,15}$.\r\n\r\nPentru obtinerea celor $70$ de puncte insa, nu era necesara decat prima optimizare.\r\n\r\nDupa ce am calculat elementele lui $A$, configuratiile de tipul $2^k^$, $0 &le; k < N$ pentru care exista strategie de castig, constituie o posibila prima mutare.\r\n\r\nAsadar algoritmul are complexitatea $O(N*2^N^)$ folosind $O(2^N^)$ memorie.\r\n\r\nh3. Solutia de 100 de puncte (clasele 11-12 nivel avansat)\r\n\r\nSolutia anterioara poate fi rafinata prin urmatoarea observatie: daca la un moment dat, am colorat o latura, atunci toate laturile patratului (patratelor) de $1x1$ de care apartinea pot fi considerate redundante. Cum $N &le; 50$ se pot forma doar $20$ de patrate de latura $1$ (un grid cu $4$ linii si $5$ coloane). Astfel in loc ca numarul $i$ sa retina in fiecare bit al sau informatii despre segmente, va retine informatii despre patrate. Deci, cand eliminam o latura vom considera ca eliminam toate patratele de care apartine (care pot fi $1$ sau $2$). In mod evident, pentru a se incadra in timp, sunt necesare optimizarile de la solutia precedenta.\r\n\r\nAm obtinut astfel o solutie de complexitate $O(N*2^K^)$ folosind $O(2^K^)$ memorie, unde $K$ este numarul de patratele ({$1x1$}) ce pot fi construite cu segmentele din input.',1231,'public',NULL,NULL),('blog/prezentari-mihai-patrascu','Prezentari Mihai Patrascu','2008-02-25 00:43:39','2008-11-15 13:41:14','\'Mihai\':utilizator/mpatrascu a fost prin Romania recent si a dat doua prezentari de informatica teoretica la Universitatea Bucuresti. Prezentarile au fost adresate studentilor care sunt interesati de cariera de cercetare in algoritmica si structuri de date. Imi parea rau ca nu pot sa vad si eu cursurile si l-am rugat pe Alex Susu sa incerce sa le filmeze.\r\n\r\nPuteti vedea subiectele abordate de Mihai \'aici\':http://infoweekly.blogspot.com/2008/02/introducing-tcs.html.\r\n\r\nAlex a pus cursurile online. Cel din prima zi il puteti vedea aici:\r\n\r\n\'http://icwww.epfl.ch/~susu/MVI_9367.AVI\':http://icwww.epfl.ch/~susu/MVI_9367.AVI\r\n\'http://icwww.epfl.ch/~susu/MVI_9368.AVI\':http://icwww.epfl.ch/~susu/MVI_9368.AVI\r\n\'http://icwww.epfl.ch/~susu/MVI_9369.AVI\':http://icwww.epfl.ch/~susu/MVI_9369.AVI\r\n\'http://icwww.epfl.ch/~susu/MVI_9370.AVI\':http://icwww.epfl.ch/~susu/MVI_9370.AVI\r\nIar cel din a doua zi aici:\r\n\'http://icwww.epfl.ch/~susu/MVI_9375.AVI\':http://icwww.epfl.ch/~susu/MVI_9375.AVI\r\n\'http://icwww.epfl.ch/~susu/MVI_9376.AVI\':http://icwww.epfl.ch/~susu/MVI_9376.AVI\r\n\'http://icwww.epfl.ch/~susu/MVI_9377.AVI\':http://icwww.epfl.ch/~susu/MVI_9377.AVI\r\n\'http://icwww.epfl.ch/~susu/MVI_9378.AVI\':http://icwww.epfl.ch/~susu/MVI_9378.AVI\r\n\r\nMultumesc Alex! Calitatea video nu e foarte buna dar cea audio e ok si se intelege cam tot. Dimensiunea videourilor e destul de mare, poate isi face cineva timp sa la puna pe youtube ;). Nu am apucat sa vad toate videourile pentru ca inca le downloadez, dar din ce am vazut pana acum ele sunt interesante si inteligibile si pentru amatori.\r\n\r\nVizionarea acestor prezentari mi-a intarit convingerea ca informatica e un domeniu de cercetare misto, in care, spre deosebire de matematica, poti intra si mai apoi contribui relativ usor pornind de la cunostintele acumulate la olimpiade.\r\n\r\n\r\n\r\n\r\n',1490,'protected',2756,NULL),('runda/arhiva-educationala/clasament','Clasament arhiva-educationala','2008-02-25 20:33:29','2008-02-25 20:33:29','h1. Clasament ==roundparam(round_id=\"arhiva-educationala\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"arhiva-educationala\")==',256,'round: arhiva-educationala',NULL,NULL),('runda/simularecnitv2','simularecnitv2','2010-03-24 21:44:28','2010-03-24 21:44:28','h1. == roundparam(round_id=\"simularecnitv2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"simularecnitv2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"simularecnitv2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"simularecnitv2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"simularecnitv2\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/simularecnitv2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"simularecnitv2\" score=\"1\")==',256,'round: simularecnitv2',NULL,NULL),('cool-papers','Cool research papers','2008-01-24 01:57:36','2008-03-11 17:06:17','h1. Cool research papers\r\n\r\nO lista cu paper-uri misto. Cine adauga un paper ar trebui sa zica pe scurt de ce merita citit.\r\n\r\n\r\ntable. |_. Paper |_. Cine l-a pus |_{width:30%}. De ce merita citit |\r\n| \'Text Algorithms\':http://web.njit.edu/~rytter/TEACHING/TEXTS/book.html | ==user(user=\"Cosmin\" type=\"tiny\")== | Carte cu o gramada de algoritmi pe stringuri, scrisa de un cercetator francez (M. Crochemore) si de un cercetator polonez (W. Rytter) cu rezultate bune in stringology (Rytter este si antrenor al lotului polonez). |\r\n| \'Suffix arrays: A new method for on-line string searches\':http://webglimpse.net/pubs/suffix.pdf | ==user(user=\"Cosmin\" type=\"tiny\")== | ? |\r\n| \'Cuckoo hashing\':http://cs.nyu.edu/courses/fall05/G22.3520-001/cuckoo-jour.pdf | ==user(user=\"Cosmin\" type=\"tiny\")== | ? |\r\n| \'An O(ND) Difference Algorithm and Its Variations\':http://www.xmailserver.org/diff2.pdf | ==user(user=\"Cosmin\" type=\"tiny\")== | Distanta de editare in $O(n)$ memorie (cum am dat eu la GInfo), in $O(d*n)$ timp unde $d$ este distanta de editare finala (cum a dat Mars la ONI). |\r\n| \'Computational Complexity: A Modern Approach\':http://www.cs.princeton.edu/theory/complexity/book.pdf | ==user(user=\"azotlichid\" type=\"tiny\")== | Calculabilitate, clase de complexitate, algoritmi de aproximare si aplicatii. Scrisa de doi profi de la Princeton si oferita gratuit pe net. |\r\n| \'The LCA Problem Revisited\':http://www.ics.uci.edu/~eppstein/261/BenFar-LCA-00.pdf | ==user(user=\"mpatrascu\" type=\"tiny\")== | Era un classic pe Lista lui Francu |\r\n| \'Simple Linear Work Suffix Array Construction\':http://www.cs.helsinki.fi/juha.karkkainen/publications/icalp03.pdf | ==user(user=\"mpatrascu\" type=\"tiny\")== | Un algoritm de construit suffix trees/array absolut superb. |\r\n| \'Dynamic Transitive Closure via Dynamic Matrix Inverse\':http://www.mimuw.edu.pl/~sank/pub/sankowski_focs04.ps | ==user(user=\"mpatrascu\" type=\"tiny\")== | Ca sa ne convingem ca n-am invatat algebra de clasa 11 degeaba. |\r\n| Level ancestor | ==user(user=\"Cosmin\" type=\"tiny\")== | ? |\r\n| Minimal diameter spanning tree | ==user(user=\"Cosmin\" type=\"tiny\")== | ? |\r\n| Smallest polygon containing k points | ==user(user=\"Cosmin\" type=\"tiny\")== | ? |\r\n| Fenwick trees | ? | ? |\r\n| \'Dictionary matching and indexing with errors and dont cares\':http://www.cs.nyu.edu/cs/faculty/cole/papers/CGL04.ps | ==user(user=\"flmanea\" type=\"tiny\")== | Cateva probleme interesante pe siruri cu wild-carduri |\r\n| \'Dynamic dictionary matching and compressed suffix trees\':http://www.cs.pitt.edu/~hlchan/research/publications/soda05-chan.pdf | ==user(user=\"flmanea\" type=\"tiny\")== | Din nou algoritmi pe siruri. |\r\n| \'Rank Aggregation Methods for the Web\':http://www10.org/cdrom/papers/577/index.html | ==user(user=\"flmanea\" type=\"tiny\")== | Un articol interesant despre clasamente si combinarea lor, in contextul cautarii pe web. |\r\n| \'Finding an Optimal Tree Searching Strategy in Linear Time\':http://www.cs.brown.edu/~shay/BST.pdf | ==user(user=\"azotlichid\" type=\"tiny\")== | Arbori binari de cautare optimali in O(N) |\r\n| \'An Efficient Context-Free Parsing Agorithm\':http://www.cs.cmu.edu/afs/cs.cmu.edu/project/cmt-55/lti/Courses/711/Class-notes/p94-earley.pdf | ==user(user=\"flmanea\" type=\"tiny\")== | O lucrare de inceput in teoria limbajelor formale, interesanta mai ales din punct de vedere istoric. Algoritmul prezentat este un punct de plecare in multi algoritmi de parsing folositi si acum. Autorul, Jay Earley, a scris doar vreo 10 lucrari de CS, si acum e psiholog, dar aceasta e considerata drept una dintre lucrarile de mare importanta in informatica teoretica a secolului trecut.|\r\n| \'Left-leaning Red-Black trees\':http://www.cs.princeton.edu/%7Ers/talks/LLRB/RedBlack.pdf | ==user(user=\"rgrig\" type=\"tiny\")== | Implementare mai simpla pentru arbori Rosu-Negru. Merita citita si discutia de la pagina \'asta\':http://geomblog.blogspot.com/2008/02/notes-from-dagstuhl-i-red-black-trees.html (later edit, flmanea) |\r\n| \'Treaps\':http://www.win.tue.nl/~speckman/CourseMat/04-treaps.pdf | ==user(user=\"cosmin\" type=\"tiny\")== | Treapurile sunt arbori echilibrati foarte simplu de implementat. Mult mai curati si ceva mai eficienti decat arbori Rosu Negru sau arborii AVL. Fara atatea cazuri la care sa fii atent. Nu se predau la scoala pentru ca demonstratia ca in medie operatiile iau O(log n) timp este mai dificila, dar in concursurile de programare sunt ideali. Ar trebui sa ii puteti implementa in 15 minute dupa ce ii intelegeti, fara a toci bucati de cod pe de rost. |\r\n| \'Natural Proofs\':http://www.cs.umd.edu/~gasarch/BLOGPAPERS/natural.pdf | ==user(user=\"flmanea\" type=\"tiny\")== | \'Premiul Godel\':http://sigact.acm.org/prizes/godel/ in \'2007\':http://sigact.acm.org/prizes/godel/2007.html.  |',1466,'public',NULL,NULL),('utilizator/petro','Profil petro','2008-02-27 11:21:09','2008-03-22 09:58:22','',7732,'public',NULL,NULL),('schimbare-borland/pachet-devel','Pachet development','2008-02-27 18:20:47','2008-02-28 07:19:38','O lista cu ce ar trebui sa contina pachetul de development\r\n\r\nh1. Windows\r\n\r\n* DevC++ (sau wxDev-C++ varianta mai noua)\r\n* RHIDE\r\n* MinGW Developer Studio\r\n* Free Pascal\r\n\r\nh1. Linux\r\n\r\n* g++ & vim / emacs / kate\r\n* RHIDE\r\n* Free Pascal',1204,'public',NULL,NULL),('blog/cum-fac-altii','Cum fac altii','2008-02-28 08:55:18','2008-11-15 13:41:14','Atunci cand vrei sa te apuci de un lucru sau sa imbunatatesti un anumit proiect, unul din primii pasi pe care trebuie sa ii faci e studiul modului in care alti oameni au reusit deja sa atinga obiectivele pe care ti le propui. Desi noi, cei din comunitatea infoarena, nu avem functii in Ministerul Educatiei, parerea mea e ca putem sa ne gandim ce putem face pentru \"imbunatatirea\" olimpiadei de informatica din Romania.\r\n\r\nSa vedem, deci, ce tari stau mai bine ca noi din acest punct de vedere. _Statele Unite ale Americii_ au un \'concurs\':http://ace.delos.com/ioigate destul de cunoscut elevilor romani, care permite oricui sa participe online la probele sustinute \"proctored\" (sub supraveghere) de elevii americani. Cu siguranta, concursul USACO a avut un impact puternic in Romania: foarte multa lume a trecut prin programul de pregatire de pe site-ul lor, majoritatea celor care spera sa ajunga la ONI participa constant la rundele online, si cel putin 3 romani (poate mai multi, de 3 stiu eu) au fost invitati, in urma rezultatelor foarte bune, sa participe la faza finala din America. Personal, nu cred ca USACO e un model prea bun pentru olimpiadele din Romania, din mai multe motive. In primul rand, foarte putini americani studiaza informatica (\"programming\", cum ii zice USACO), si numarul celor care-si incearca sansele la acest concurs e unul destul de mic. Din acest motiv, conducatorul lotului american (Rob Kolstad) poate sa tina legatura cu multi dintre concurenti de-a lungul anilor, sa discute cu parintii si profesorii lor, si sa creeze cel mai bun concurs in raport cu interesul national. Foarte ciudat e ca nu se stie de la inceput ce pondere are fiecare proba, stabilirea constantelor pentru calculul formulei finale fiind una din atributiile aceluiasi Kolstad, *dupa ce concursul s-a incheiat!*\r\n\r\nNici nu vreau sa-mi imaginez ce fel de scandaluri ar iesi in Romania in urma unei astfel de abordari, mai ales avand in vedere ca la noi unii parinti sunt mai preocupati de rezultatele concursurilor decat copiii lor, si sunt gata oricand sa faca circ atunci cand simt ca cineva a comis vreo nedreptate fata de ei. De altfel, nici mie nu-mi place ideea in sine. In America, acolo unde pana si admiterea la facultate se face in urma unui proces subiectiv, asa ceva e tolerabil. Dar in Romania, avand in vedere istoria ultimilor 60 de ani, nu putem aplica eficient un astfel de sistem.\r\n\r\nDoua tari la care privim de multa vreme cu respect (pentru rezultatele obtinute) sunt _China_ si _Rusia_. Ajungem, ca de obicei, la concluzia ca in tarile in care traiul este un chin (rusii de rand traiesc in saracia pe care le-au adus-o comunismul si apoi acapararea tuturor resurselor tarii de catre oligarhia sustinuta de Kremlin, iar chinezii au fost \"imblanziti\" de catre sistemul politic represiv si inuman), apar si talentele extraordinare. Pe langa generalizarile despre o presupusa inteligenta colectiva a natiunilor, se pare ca daca esti deznadajduit si ti se pare ca nu prea ai cum sa scapi de soarta dura, faci tot ce-ti sta in putinta ca sa exploatezi o ocazie atunci cand ea apare. Sa revenim totusi la olimpiade. Din pacate, nu avem atat de multe informatii despre cele din Rusia si China. Exista diverse informatii care s-au scurs, insa numai cei care cunosc limba rusa au acces la problemele si solutiile de la rusi, in timp ce pentru celelalte s-ar putea ca nici macar limba chineza sa nu fie de ajuns. Conform lui \'Zhu Zeyuan\':http://zhuzeyuan.hp.infoseek.co.jp/ , guvernul chinez a desfiintat site-ul IOI Forum, acolo unde se discutau si probleme din tara lor, tocmai pentru a-i impiedica pe straini sa acceada la ele. Ceea ce stim, insa, e ca problemele din ambele parti sunt foarte grele si interesante, si ca ambele tari se bazeaza pe organizarea unui numar ridicat de tabere de pregatire, a caror eficienta a fost demonstrata. De asemenea, China alege participantii la IOI cu un an inainte, pentru a le da suficiente ocazii sa se pregateasca si sa aduca glorie patriei. Parerea mea e ca ar trebui, eventual cu ajutorul celor care inteleg limba rusa, sa studiem mai mult ceea ce se intampla la ei si sa vedem ce se poate adapta in Romania. Sa-i lasam pe chinezi in pace, pentru ca in Romania nu vom manca niciodata orez de placere si nici nu vom spune ca mersul pe bicicleta e hobby-ul nostru national, imbinand utilul cu placutul. Suntem pur si simplu prea diferiti de ei.\r\n\r\nIn _Europa_ sunt mai multe locuri in care ne-am putea uita. _Croatii_ si _slovacii_, printre altii, se descurca destul de bine in ceea ce priveste organizarea olimpiadelor. Totusi, parerea mea e ca _polonezii_ dau \'cel mai bun exemplu\':http://www.oi.edu.pl/ . Site-ul lor, tradus partial in engleza, e o resursa indispensabila pentru cei care vor sa rezolve probleme care sa le dezvolte creativitatea. Multi dintre noi au stat zile / saptamani / luni gandindu-se la cate o problema de acolo, constatand ca de fapt se rezolva cu o idee simpla, dar greu de gasit. Nu cred ca e vreun alt concurs care sa sintetizeze mai bine ceea ce inteleg eu prin ideea de \"olimpiada de informatica\" (desi mai demult gandeam altfel, si mi se parea ca un concurs ca al lor e prea \"incorect\" fata de cei care se pregatesc mult - vorbim despre asta intr-un alt post).\r\n\r\nOlimpiada poloneza are 3 faze cu subiecte unice pe tara. De multe ori, cea mai grea e \"etapa locala\", insa elevii au la dispozitie aproape o luna pentru a se gandi la subiectele propuse. Aceasta standardizare a evaluarii a insemnat o simplificare a intregului proces competitional, si \"mai simplu\" inseamna de multe ori \"mai bun\", sau cel putin \"mai logic\". De ce sa te concentrezi pe un sistem complicat, cand poti sa te concentrezi pe subiectele propriu-zise? Problemele au un grad mare de originalitate, in spatele lor sunt idei adevarate (nu reformulari ale altor cerinte mai vechi), si solutiile sunt foarte ingenioase. De asemenea, cei care pricep limba poloneza isi pot comanda \"blue book\"-urile, acele carti care contin toate solutiile, explicatiile si \"rezervele\" care nu s-au dat, sumarizand intreaga activitate dintr-un an de zile. Nu exista solutii redactate in 3 randuri care sa faca o simpla trimitere la alte carti, iar ceea ce se obtine astfel reprezinta o resursa cu totul deosebita pentru cei care vor sa se puna la curent cu tot ce a miscat in anii precedenti in concursurile poloneze de informatica. Primii clasati la faza finala (ca si in multe alte tari dezvoltate, nu exista separare pe clase si nici macar sistemul juniors / seniors ca la croati) primesc premii foarte consistente de la sponsorii destul de puternici si interesati. Cei mai buni primesc si dreptul de a participa la CPSPC (Czech - Polish - Slovak Preparation Contest), un concurs foarte puternic, dar fara o miza deosebita. Un fel de lot la comun pentru 3 tari. In afara faptului ca obtinerea unui loc de IOI necesita si un pic de noroc (pt. ca se bazeaza pe rezolvarea a numai 5 probleme in etapa a 3-a), mi se pare ca avem foarte multe de invatat de la ceea ce au facut si fac in continuare polonezii. Mereu vor exista cateva aspecte de imbunatatit, si acest lucru e normal!\r\n\r\n*Oricum, ca sa n-o mai lungim prea mult. Cine sunt cei interesati de imbunatatirea sistemului competitional la informatica? Si ce pot face ei in sensul acesta? Pentru ca e frumos sa discutam, dar e si mai frumos sa tragem niste concluzii, sa redactam niste planuri, si sa mergem cu ele la \"factorii de decizie\", incluzand aici oficialitatile din minister si potentialii sponsori. Isi doreste cineva destul de mult sa avem si noi o olimpiada mai buna, din toate punctele de vedere?*',1490,'public',2779,NULL),('blog/algoritmiada-2010-runda-2','Algoritmiada 2010: Analiza rundei 2','2009-12-23 19:06:19','2009-12-25 13:32:22','Pe data de 20 decembrie a avut loc cea de-a doua rundă a concursului Algoritmiada 2010. Abia intraţi în vacanţă, concurenţii şi-au mai amânat câteva zile excursiile la munte pentru a participa la o nouă rundă a celui mai prestigios concurs info{_arena_}.\r\n\r\nSă aruncăm o privire asupra statisticilor acestei runde:\r\n\r\ntable. |_. &nbsp; |_. Runda 1 |_. Runda 2 |\r\n| Câţi concurenţi au trimis soluţii | 181 | 135 |\r\n| Câţi concurenţi s-au înscris | 308 | 174 |\r\n| Surse trimise | 765 | 627 |\r\n| Surse cu punctaj pozitiv | 345 | 312 |\r\n| Concurenţi cu punctaj pozitiv | 122 | 107 |\r\n| Punctaj mediu al concurenţilor care au trimis soluţii | 58.07 | 76.26 |\r\n| Punctaj mediu al concurenţilor cu punctaj strict mai mare ca 0 | 86.15 | 96.87 |\r\n\r\nÎn primul rând, observăm o scădere a numărului de participanţi faţă de prima rundă. Din statistici se mai observă o creştere a punctajelor faţă de runda anterioară, ceea ce denotă fie că subiectele au fost ceva mai uşoare, fie că participanţii au fost mai bine pregătiţi. :) Uitându-ne atent şi la clasament, vom vedea că subiectele propuse au reuşit să-i departajeze bine pe concurenţi.\r\n\r\nElevii de gimnaziu au avut de înfruntat în această rundă un set de probleme ceva mai dificil, având o problemă comună cu clasele 11-12. Cu toate acestea, == User(user=\"GheorgheMihai\") == a reuşit să obţină 230 de puncte cu care şi-a asigurat primul loc. Locul al doilea i-a revenit lui == User(user=\"Magnus\") == care a obţinut 150 de puncte, iar pe locul al treilea s-au situat == User(user=\"marta_dianna\") ==, == User(user=\"liana\") == şi == User(user=\"Challenge\") ==, toţi cu câte 140 de puncte.\r\n\r\nLa clasele 9-10, primul clasat a fost == User(user=\"savim\") == cu 245 de puncte, fiind urmat de == User(user=\"cezarmocan\") == cu 230 de puncte si == User(user=\"freak93\") == cu 200 de puncte.\r\n\r\nLa grupa 11-12, punctajele au fost net mai mari decât în runda precedentă şi acest lucru s-a datorat unui set de probleme mai uşor. Primul loc a fost ocupat de == User(user=\"victor.ionescu\") == cu 260 de puncte, fiind urmat de un grup de 4 elevi: == User(user=\"perticas_catalin\") ==, == User(user=\"hadesgames\") ==, == User(user=\"katakuna\") == şi == User(user=\"andrei-alpha\") ==, toţi cu câte 220 de puncte.\r\n\r\nLa grupa de studenţi, primul clasat a fost == User(user=\"andreitheo87\") == care a reuşit să obţină cel mai mare punctaj din această rundă: 280 de puncte. În urma lui s-au clasat == User(user=\"mugurelionut\") == cu 250 de puncte şi == User(user=\"razvi9\") == cu 180 de puncte.\r\n\r\nRunda a fost, din păcate, marcată de câteva probleme de natură tehnică. În primul rând, în ultima oră de concurs, a căzut conexiunea la internet a calculatorului pe care se află evaluatorul timp de 20 de minute. Acest lucru, le-a creat concurenţilor neplăceri majore, deoarece nu au mai putut vedea în timp util dacă soluţiile trimise de ei au întâmpinat probleme la compilare, iar rezultatele la evaluarea parţială au apărut cu întârziere. Tot din acest motiv, evaluarea a durat mai mult timp, rezultatele finale nefiind disponibile chiar la finalul concurslui. În al doilea rând, site-ul s-a comportat destul de prost în ultimele minute ale concursului. Pentru a evita o înrăutăţire a lucrurilor, comisia a luat decizia de a face rezultatele publice doar după ce toate sursele au fost evaluate. Cu toate acestea, au exitat \'reclamaţii\':forum/index.php?topic=4370.msg36834 cum că unii concurenţi n-au putut să mai submiteze soluţiile terminate în ultimele minute. Ne pare rău că au apărut astfel de probleme şi vom încerca să le remediem pe viitor. Probleme de natură ştiinţifică nu au fost sesizate, comisia pregătind subiectele cu rigurozitatea obişnuită. Doar articolul cu soluţii s-a lăsat ceva mai mult aşteptat faţă de runda precedentă, dar acest lucru s-a strecurat neobservat, probabil concurenţii au aşteptat cu mai mult interes sărbătorile decât soluţiile oficiale. :)\r\n\r\nUrmătoarea rundă va avea loc cel mai probabil în a doua jumătate a lunii februarie. Am luat această decizie, pentru a evita perioada algomerată pentru studenţi din timpul sesiunii. Mai mult, elevii de liceu vor avea o ocazie în plus să-şi verifice cunoştinţele înainte de Olimpiada Judeţeană ce va avea loc la începutul lunii martie.\r\n\r\nÎn încheiere, echipa info{_arena_} vă doreşte sărbători fericite şi un an nou cu cât mai multe realizări deosebite!',1792,'protected',4388,NULL),('utilizator/filipb','Profil filipb','2006-11-24 20:56:41','2010-04-24 10:11:34','h2. Despre mine\r\n\r\n* Data nasterii: 17 martie 1989\r\n* Student in anul II la \'Universitatea Politehnica Bucuresti\':http://www.pub.ro, sectia \'Calculatoare\':http://www.acs.pub.ro\r\n\r\nh2. Membru in comisiile stiintifice la concursurile de informatica\r\n\r\n* 2010, 2009 - Olimpiada Nationala de Informatica\r\n* 2009 - Olimpiada Europei Centrale si de Est (\'CEOI\':http://www.ceoi2009.ro)\r\n* 2009 - Concursul National \'.campion\':http://campion.edu.ro\r\n* 2008, 2007, 2006 - Concursul National \'preONI\':preoni-2008\r\n\r\nh2. Rezultate obtinute la olimpiadele si concursurile de informatica\r\n\r\n* 2008, Macedonia - Medalie de aur la Olimpiada Balcanica de Informatica\r\n* 2008 - Membru al lotului national largit de informatica\r\n* 2008, Ploiesti - Premiul al II-lea la Olimpiada Nationala de Informatica\r\n* 2007 - Membru al lotului national largit de informatica\r\n* 2007, Cluj - Premiul I la Olimpiada Nationala de Informatica\r\n* 2006 - Premiul al II-lea la Concursul National \"Stelele Informaticii\"\r\n* 2006, Targoviste - Premiul I la Olimpiada Nationala de Informatica\r\n* 2005, Yakutsk, Rusia - Medalie de aur la Olimpiada Internationala Pluridisciplinara TUYMAADA\r\n* 2005, Galati - Premiul I la Olimpiada Nationala de Informatica\r\n* 2003, Focsani - Premiul I la Olimpiada Nationala de Informatica',256,'protected',NULL,NULL),('preoni-2008/runda-4/solutii','Solutii preONI 2008, Runda 4','2008-02-17 11:22:59','2008-03-02 21:22:25','==include(page=\"template/preoni-2008/header\")==\r\n\r\nh1. Solutii preONI 2008, Runda 4\r\n\r\nDupa 4 runde a sosit timpul ca preONI 2008 sa isi anunte finalistii. Felicitari tuturor participantilor pentru efortul depus! Speram ca v-au placut problemele propuse la editia din acest an preONI si va asteptam in continuare la concursurile organizate de infoarena. Cu finalistii ne vom intalni pe parcursul lunii martie, sa ne vedem cu bine! Daca nu v-ati calificat nu fiti dezamagiti, caci va veti putea masura fortele in runda finala participand online (premiile insa se acorda doar finalistilor).\r\n\r\nCea de a patra runda preONI 2008 a adus si cel de-al doilea punctaj maxim, obtinut de \'Cezar Mocan\':utilizator/cezarmocan, care a terminat in forta rundele de calificare. Cezar a fost singurul care a rezolvat problema grea a setului de la gimnaziu, \'Heavy metal\':problema/heavymetal. Pe pozitia secunda s-a clasat \'Alex Mircescu\':utilizator/alex_mircescu cu 260 de puncte, iar pe ultima treapta a podiumului, cu cate 240 de puncte, \'Andrei Purice\':utilizator/protoman si \'Radu Voroneanu\':utilizator/radu_voroneanu. Tinem sa felicitam concurentii de gimnaziu pentru prestatia lor, acestia avand cele mai mari punctaje in clasamentul general total.\r\n\r\nLa clasa a 9-a punctajele au fost destul de mici, cele mai grele 2 probleme, \'Garaj\':problema/garaj si \'Lampa\':problema/lampa nefiind rezolvate de nimeni corect. In fruntea clasamentului il gasim pe \'Alexandru Tache\':utilizator/hadesgames cu 150 de puncte, urmat de \'Victor Ionescu\':utilizator/vanila_cpp cu 140 de puncte, respectiv de \'Vlad Tataranu\':utilizator/tvlad cu 130 de puncte. Un lucru destul de ingrijorator pe care l-am remarcat este prestatia generala scazuta a elevilor de clasa a 9-a. Cu exceptia primilor clasati care s-au comportat destul de bine, punctajele din clasamentul general total sunt extrem de scazute. Sunt foarte multi concurenti de gimnaziu care ocupa pozitii destul de fruntase datorita problemelor comune celor doua grupe. Speram intr-o remediere a situatiei in concursurile ce vor urma. Bafta!\r\n\r\nUltima runda nu a adus punctaje prea mari nici la clasa a 10-a. \'Bogdan Tataroiu\':utilizator/bogdan2412 a reusit sa se impuna din nou cu 200 de puncte, urmat de \'Adriana Sperlea\':utilizator/adriana_s cu 130 de puncte si de \'Cristian Palianos\':utilizator/za_wolf cu 110 puncte. Un aspect pozitiv este faptul ca toate cele 3 probleme, \'Garaj\':problema/garaj, \'Carnati\':problema/carnati si \'Stalpi\':problema/stalpi, au fost rezolvate de 100 de puncte. Probabil ca s-ar fi obtinut punctaje mai mari daca unii concurenti ar fi dat dovada de mai multa concentrare in timpul rundei de concurs. Oricum, felicitari si participantilor de la clasa a 10-a!\r\n\r\nLa clasele 11-12 punctajele obtinute au fost mari. In frunte il gasim pe binecunoscutul \'Mugurel Ionut Andreica\':utilizator/mugurelionut. Veteranul Mugurel si-a demonstrat inca o data valoarea reusind sa se impuna cu 270 de puncte. Pe urmatoarele 3 pozitii se afla la egalitate \'Cosmin Gheorghe\':utilizator/gcosmin, \'Alexandru Tandrau\':utilizator/alexthero si \'Victor Rusu\':utilizator/victorsb cu cate 200 de puncte. Problema usoara \'Nivele\':problema/nivele s-a dovedit a fi accesibila multor concurenti, deasemenea si cea medie, \'Stalpi\':problema/stalpi, a avut destule punctaje maxime. In schimb problema grea, \'Arbori\':problema/arbori, nu a fost rezolvata de nimeni, punctajul cel mai mare apartinandu-i lui Mugurel - 70 de puncte. Felicitari si seniorilor! Va asteptam la runda finala sa va masurati fortele inainte de olimpiadele si concursurile majore ale anului!\r\n\r\nIn incheiere...\r\nIata ca au trecut si cele 4 runde de calificare ale concursului preONI 2008. \'Echipa infoarena\':echipa-infoarena va multumeste si va ureaza numai bine! Ne vedem la finala!\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Heavy metal\':preoni-2008/runda-4/solutii#heavymetal\r\n* \'Koba\':preoni-2008/runda-4/solutii#koba\r\n* \'Factoriale\':preoni-2008/runda-4/solutii#factoriale\r\n* \'Lampa\':preoni-2008/runda-4/solutii#lampa\r\n* \'Garaj\':preoni-2008/runda-4/solutii#garaj\r\n* \'Carnati\':preoni-2008/runda-4/solutii#carnati\r\n* \'Stalpi\':preoni-2008/runda-4/solutii#stalpi\r\n* \'Nivele\':preoni-2008/runda-4/solutii#nivele\r\n* \'Arbori\':preoni-2008/runda-4/solutii#arbori\r\n\r\n==include(page=\"preoni-2008/runda-4/solutii/heavymetal\")==\r\n\r\n==include(page=\"preoni-2008/runda-4/solutii/koba\")==\r\n\r\n==include(page=\"preoni-2008/runda-4/solutii/factoriale\")==\r\n\r\n==include(page=\"preoni-2008/runda-4/solutii/lampa\")==\r\n\r\n==include(page=\"preoni-2008/runda-4/solutii/garaj\")==\r\n\r\n==include(page=\"preoni-2008/runda-4/solutii/carnati\")==\r\n\r\n==include(page=\"preoni-2008/runda-4/solutii/stalpi\")==\r\n\r\n==include(page=\"preoni-2008/runda-4/solutii/nivele\")==\r\n\r\n==include(page=\"preoni-2008/runda-4/solutii/arbori\")==\r\n',2028,'public',NULL,NULL),('propuneri/8-almanah','IAP #8: \"Almanah\" infoarena','2008-03-03 16:12:49','2008-03-03 16:17:03','h1. IAP #8: \"Almanah\" infoarena\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2008-03-03 |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"wickedman\")== |\r\n|_. Stare     | *_IN-CONSTRUCTIE_* |\r\n\r\nh2(#abstract). Abstract\r\n\r\nSe propune redactarea, publicarea si comercializarea unei compilatii de articole scrise de membrii infoarena.\r\n\r\nh2(#motivatie). Motivatie\r\n\r\nPropunerea de fata doreste sa motiveze membrii comunitatii infoarena sa scrie articole de calitate. Din cate am observat, perspectiva unei publicatii \"cu ISBN\" pe CV-ul personal este un factor destul de motivant pentru unii. :)\r\n\r\nEste relativ usor sa scoatem o carte impreuna.\r\n\r\nAcest proiect nu urmareste sa scoata profit din vanzarea unor astfel de publicatii. Articolele care apar in \"almanah\" vor fi mai intai publicate pe site.\r\n\r\nh2(#detalii). Plan\r\n\r\n# Alegem o echipa de editori si un coordonator de proiect.\r\n# Echipa de editori va stabili criteriile de calitate pentru articole (nu trebuie dezbatute in acest IAP).\r\n# \"Vindem\" ideea la utilizatorii infoarena si strangem articole astfel incat sa umplem un volum de 200 - 250 pagini A4 (probabil in jur de 35-40 articole?)\r\n# Publicam cartea si o vindem a.i. sa ne acoperim costurile de productie.\r\n# Repetam procedeul :)\r\n\r\nh2. Editare & publicare\r\n\r\nNu cunosc detalii tehnice despre ce tip de fisiere trebuie sa prezentam editurilor / tipografiilor. Din cate stiu eu, standardul tehnic e destul accesibil (se accepta si fisiere MS Word). In orice caz, articolele se vor redacta ca de obicei pe wiki-ul infoarena.\r\n\r\nIn functie de cerintele tipografiei vom scrie un program de conversie din wiki-ul infoarena in formatul cerut. Estimez ca nu vom avea probleme aici.\r\n\r\nCosturile de imprimare variaza destul de mult in functie de numarul de exemplare. Un cost orientativ pentru 100 de exemplare este de 35 lei / exemplar.\r\n\r\n*TODO*: Adauga cateva oferte de carte\r\n\r\nh2. Drepturi de autor\r\n\r\nO chestiune mai delicata o constituie drepturile de autor. Nu putem folosi articole care au aparut in GInfo sau in alte publicatii! Exceptie fac cazurile in care autorul are permisiune scrisa (explicita!) din partea publicatiei.\r\n\r\nIn plus, vom avea grija ca editura / tipografia prin care vom publica \"almanahul\" sa nu solicite / obtina drepturi de autor asupra continutului infoarena.\r\n\r\nh2. Comercializare\r\n\r\nNu vreau sa ne ocupam de comenzi & livrare. Sper sa gasim un magazin online prin care sa ne vindem cartile. Ei se vor ocupa de comenzi & livrare - ar trebui sa aiba deja infrastructura necesara - noi le aducem clientii si impartim profitul.\r\n\r\nCa solutie de back-up, si ca sa nu blocam acest IAP cu gasirea unui partener de comercializare, putem sa lucram cu \'Librariile Hamangiu\':http://hamangiu.ro/librariile-hamangiu.htm. L.H. au puncte de desfacere in mai multe orase mari din tara si ne pot ajuta.\r\n\r\n*TODO*: Proiectie de incasari si balanta cu costurile de productie\r\n\r\nh2(#feedback). Feedback\r\n\r\nQ: Care ar putea fi echipa de editori? Cine ar fi coordonator?\r\n\r\nQ: Aveti idei bune de titlu?\r\n\r\nQ: Care sunt potentialii clienti? Cate exemplare credeti ca putem vinde?\r\n',13,'public',NULL,NULL),('runda/concurs12345/clasament','Clasament concurs12345','2009-07-18 17:37:06','2009-07-18 17:37:06','h1. Clasament ==roundparam(round_id=\"concurs12345\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"concurs12345\")==',10280,'round: concurs12345',NULL,NULL),('blog/sfaturi-practice-inainte-de-oji','Sfaturi practice inainte de OJI (partea I)','2008-03-07 10:24:39','2008-11-15 13:41:14','1) *Mergeti cu starea de spirit potrivita!*\r\n\r\nAm discutat un pic despre asta \'si aici\':blog/la-inceputul-sezonului-competitional si am de gand sa mai abordez subiectul in viitor. Ca sa nu ma repet, o sa sintetizez: starea voastra de spirit va avea un impact mai mare asupra rezultatului decat ceea ce mai puteti invata in timpul ramas. :)\r\n\r\n2) *Nu credeti in legile lui Murphy*\r\n\r\nSunt cea mai proasta chestie pentru oricine vrea sa reuseasca orice. Felia de paine unsa pe o parte are 50% sanse sa cada pe partea care nu trebuie. Nu mai multe, nu mai putine, ci 50%. Stiti prea bine de unde ati pornit, unde sunteti, unde vreti sa ajungeti. Norocul si ghinionul n-au nicio treaba cu concursurile de informatica. Sfaturile care incurajeaza pesimismul si resemnarea sunt doar modalitati de a-i face pe cei instabili emotional sa-si piarda si mai mult din echilibru!\r\n\r\n3) *Faceti cateva liste inainte de concurs*\r\n\r\nDe exemplu lista lucrurilor pe care nu trebuie sa le uitati: ceas (nu telefon), pixuri, apa, buletin. In fiecare dimineata de OJI ma gandeam numai la ce-as fi putut uita acasa. Nu e bine! De asemenea, lista greselilor frecvente pe care le-ati facut in timp ce ati rezolvat probleme in ultima luna. De cate ori ati avut un conflict de nume intre o variabila globala si una locala? De cate ori ati pierdut ore bune ca sa va dati seama ca aveati un vector prea mic? Fiecare dintre noi face greseli, si are un top al celor mai frecvente lucruri care-i cauzeaza probleme la implementare. Si totusi, de fiecare data pierdem la fel de mult timp pentru ca la sfarsit sa exclamam cu furie/tristete: \"iar am gresit chestia asta?!?\".\r\n\r\nIn mod cert veti face erori cauzate de neatentie in concurs - toti facem! Problema e sa le identificati cat mai rapid, pentru ca nu aveti cum sa le eliminati din start.\r\n\r\n4) *Studiati mediul de programare*\r\n\r\nSfat care nu poate fi repetat de destule ori pentru cei care lucreaza tot anul in GNU C/C++, eventual in Linux. Stiu ca iti e _sila_ (nu, nu e un cuvant prea puternic) de Borland. Si mie imi e, si cred ca tuturor membrilor echipei Info-Arena le e. E invechit, retardat, si cum mai vreti voi. Dar regulile sunt reguli si veti avea nevoie sa dati doua surse care sa ia multe puncte atunci cand sunt compilate cu produsele Borland. Toata lumea trebuie sa treaca prin asta, si probabil ca ceilalti elevi buni sunt la fel de \"nerabdatori\" ca si tine sa se confrunte cu acest adevarat obstacol. Nu mai incerca sa amani readaptarea la Borland, e ca atunci cand dezlipesti un plasture. Cu cat mai repede, cu atat mai bine.\r\n\r\n5) *Nu uitati sa va distrati!*\r\n\r\nPentru ca despre asta ar trebui sa fie olimpiada pana la urma. Nimeni nu o sa nege aspectul competitiv, si tuturor ne place sa castigam. :D Dar in viata sunt multe \"concursuri\", si olimpiada judeteana e unul singur dintre ele, destul de nesemnificativ fata de altele pe care le veti descoperi mai incolo. E OK sa tintiti la primul loc si chiar sa recunoasteti asta fara sa va fie rusine. Totusi, performanta vine atunci cand  lucrurile decurg fara un efort constient prea mare din partea ta. Atunci cand esti in febra concursului si treci prin momentele alea in care scopul tau devine nu sa faci mai bine decat celalalt, ci sa rezolvi perfect problema.\r\n\r\nSuna ciudat pentru cineva \"din afara\", dar noi, cei din comunitatea Info-Arena, ne distram rezolvand probleme. :) De ce sa ne ascundem?\r\n\r\n_Va urma..._\r\n\r\n*Tiberiu Florea* - \'greco.ro\':http://www.greco.ro',1490,'protected',2807,NULL),('planificare/sedinta-20080303','Sedinta 2008-03-03','2008-02-28 15:19:06','2008-03-08 14:01:56','h1. Sedinta 2008-03-03\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *luni* la ora *18:30* la \'*UNIBUC*\':http://www.unibuc.ro\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"alexandru.mosoi\" type=\"tiny\")==  --&gt; nu mai vin, ma sacaie o masea si nu ma simt prea bine\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== --> o sa intarzii\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* _&hellip; asteptam confirmari_\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioara\':planificare/sedinta-20080218\r\n* preONI 2008 Shock Therapy\r\n* Cum putem folosi \'moss\':http://theory.stanford.edu/~aiken/moss/\r\n** Exemplu la ICHB (Silviu: nu pun link-ul, vi-l arat in timpul sedintei)\r\n* infoarena research? Florin Manea\r\n* stabilit locatie si data pentru sedinta urmatoare\r\n* development\r\n* feedback arhiva educationala\r\n* server in NXDATA\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Feedback pentru IAP #7 si #8, votam data viitoare\r\n* Silviu il invita din nou pe Malex\r\n* Mircea cloneaza search-ul pe un cont Google neutru, il instaleaza pe site si ii da lui Stefan parola ca sa-l imbunatateasca.\r\n* Vali testeaza \'Paypal\':donatii si Cristi ne zice daca a mers\r\n* Mircea il contacteaza pe Vlad Nistorica pe messenger %{color:red}(done)% - e a 10-a, nu a 9-a\r\n* Mircea semneaza ca participantii la finala nu au trisat :) %{color:red}(done)% \r\n* Cristi si Silviu contacteaza Adobe sa stabilim intalnire despre preONI si hackaton\r\n* Finala se face in doua transe (2-2)\r\n* Vali numara calculatoarele joi (20080306) %{color:red}(done)% - 16 labul bun ICHB + 16 lab ISB + 14 labul prost (din care sa spunem ca putem face 7 mai destepte)\r\n* Cristi si Mircea fac rezervare la hotel marti sau miercuri pentru 2 zile si eventual o a treia zi la nevoie. Trebuie inclusi si Buru, Astronomy si Pasa. %{color:red}(done @ UPB)%\r\n* Silviu vorbeste cu Ali despre mancare.\r\n* Cristi vorbeste cu potentiali noi sponsori pentru premii.\r\n* Vali gaseste solutie buna de imprimat diplome.\r\n* Cristi suna la tricouri si da comanda. (marimi tricouri echipa ia: LMMLXLLMM)\r\n* Mircea face pagina la finala\r\n* Silviu vorbeste cu Ali despre microbuze\r\n* Adi si wefgef il ajuta pe Buru sa schimbe politica si procesul de propunere la arhiva educationala.\r\n* Intalnirea viitoare pe 2008-03-14 la ICHB \r\n\r\nh2. Notite\r\n\r\n==user(user=\"alexandru.mosoi\" type=\"tiny\")==\r\n\r\n* (nu-mi dau seama daca cineva mi-a sters sau nu notitele, asa ca le pun din nou)\r\n* \'etrace\':http://ndevilla.free.fr/etrace/ - pentru chestii simple, nu stie sa faca stacktrace cand buseste, arata doar functiile chemate (fara argumente). detaliile de debugging nu sunt foarte usor de citit, asa ca e foarte limitat.\r\n* nm + c++filt + gdb --interpreter=mi - se face un program (in python de exemplu), care pune break la fiecare functie si la interupere afiseaza argumentele (si variabilele locale in parinte). chestia asta e destul de puternica, se poate pride unde crapa, sa afiseze variabilele locale si argumentele.\r\n\r\n* Avem nevoie de 3 zile?\r\n',1,'public',NULL,NULL),('utilizator/shmecheru','Profil shmecheru','2008-03-10 11:42:47','2008-03-10 11:42:47','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',7820,'public',NULL,NULL),('documentatie/borderoul-de-evaluare','Borderoul de evaluare','2006-11-27 06:21:51','2008-03-24 13:40:07','h1. Borderoul de evaluare\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nBorderoul de evaluare prezinta informatii despre cum a decurs evaluarea unei solutii trimise de un concurent. Borderoul include timpul de executie, numarul de puncte obtinute la fiecare test si, uneori, mesaje de compilare sau de rulare (runtime) ale solutiei.\r\n\r\nh2. Mesaje de eroare\r\n\r\n* *OK* (sau un mesaj asemanator): programul tau a mers corect pe testul respectiv si ai primit punctele care le meritai.\r\n* *Wrong Answer*, *Raspuns gresit* (sau un mesaj asemanator): programul tau a terminat executia, dar raspunsul oferit nu a fost corect; verifica daca ai respectat intocmai cum este precizat in enunt formatul fisierului de iesire cat si formatul fisierului de intrare cand efectuezi citirea\r\n* *Time Limit Exceeded*: programul tau a depasit timpul de executie permis pentru testul respectiv; cele mai dese cauze pentru acest mesaj sunt: algoritmul folosit este ineficient, fie programul tau contine bucle care se executa la infinit, fie programul tau incearca sa citeasca de la tastatura, etc.\r\n* *System Error* (sau un mesaj asemanator): acest mesaj nu ar trebui sa apara. ==SmfLink(link=\"board\" board=\"33\" caption=\"Anunta echipa infoarena!\")==\r\n* *Missing output file* (sau un mesaj asemanator): programul tau nu a creat un fisier de iesire, sau in cazul in care a creat un fisier, nu a avut numele specificat in enuntul problemei.\r\n* *Runtime Error - Invalid memory reference*: acest mesaj se poate referi la faptul ca depasesti limita de memorie disponibila (este scrisa in enunt; de asemenea, stiva nu poate depasi $8$ MB) sau acces invalid in memorie, accesarea unui pointer invalid, indecsi intr-un tablou care depasesc dimensiunile tabloului, etc.\r\n* *Runtime Error*: cele mai cunoscute cauze pentru astfel de mesaje sunt depasirea stivei, accesarea unor fisiere gresite, erori cu numere reale, impartire la 0, etc. Un mesaj foarte intalnit este SIGKILL si semnifica ca programul tau a fost oprit de evaluator datorita unei erori ca cele descrise mai sus.\r\n\r\nh2. Punctaj / grupa\r\n\r\nIn cazul problemelor care folosesc \'gruparea testelor\':documentatie/grupare-teste , se va afisa si punctajul pe grupa pe langa punctajul pe test. In acest caz, testele se evalueaza in ordinea in care au fost grupate, iar pentru a delimita grupele, culoarea de fundal a randurilor alterneaza.\r\n\r\np=. !documentatie/grupare-teste?borderou.jpg!\r\n\r\nh2. Greseli frecvente\r\n\r\n* nu sterge ecranul si nu scrie nimic pe iesirea standard (ecran). Solutiile trimise sunt corectate automat de sistemul de evaluare. Acesta nu ia in considerare informatiile tiparite pe ecran ci doar cele scrise in fisierul de iesire specificat in descrierea problemei.\r\n* nu folosi functii care asteapta apasarea unei taste sau introducerea unei valori de la tastatura ($getch$, $readkey$, $readln$ etc.) Solutiile trimise sunt corectate automat de sistemul de evaluare. Sursele care folosesc astfel de functii vor primi punctaj $0$ pentru $timp de executie depasit$!\r\n* foloseste doar librariile standard pentru rezolvarea problemelor, adica cele care vin odata cu distributia limbajului de programare. Vezi \"lista oficiala de compilatoare\":documentatie/evaluator folosite la infoarena.\r\n* *numele fisierelor este case sensitive!* Prin conventie, toate fisierele de intrare si de iesire vor avea nume in lowercase (fara majuscule).\r\n\r\nh2. Pentru programatorii C/C++\r\n\r\n* Tipul $int$ din GNU GCC este pe $32$ de biti, nu $16$ ca in Borland C/C++, $char$ pe $8$ biti, $short$ pe $16$ biti, $long$ pe $32$, $long long$ pe $64$ de biti.\r\n* Foloseste sprintf in loc de itoa sau ltoa.\r\n* Programul de evaluare ruleaza pe un sistem de operare UNIX. Foloseste $\"\\n\"$ pentru terminarea liniei curente, nu $\"\\r\\n\"$.\r\n* Functia $main$ trebuie sa fie de tip $int$ si sa intoarca $0$ - $return 0;$\r\n* Nu folosi librarii dependente de sistemul de operare (ex. $dos.h$, $graphics.h$). Foloseste evaluatorul pentru a descoperi care sunt acestea.\r\n* No folosi modificatorii $far$, $huge$, $_huge$, $__huge$ pentru ca nu exista in GNU GCC. De asemenea, nu exista nici functiile care folosesc aceste tipuri de date (de ex. $farmalloc$, $farfree$ etc.) si nici conceptul de memory model (tiny, small, medium, large, huge). De toate acestea nu mai e nevoie intrucat ai acces la toata memoria prin functii standard si pointer-i standard - $new$, $delete$, $malloc$ etc. \r\n\r\nh2. Pentru programatorii Pascal\r\n\r\n* Nu folosi nici unul din unit-urile $dos$, $crt$ sau $graph$! Nu ai nevoie de nici unul din ele pentru a rezolva problemele de aici. Daca totusi le folosesti, programul nu va compila!\r\n',2524,'public',NULL,NULL),('blog/sfaturi-practice-inainte-de-oji-2','Sfaturi practice inainte de OJI (partea II)','2008-03-11 22:07:25','2008-11-15 13:41:14','6) *Cel putin o zi libera inainte de proba*\r\n\r\nAltii ar sugera o saptamana. Eu n-am putut niciodata sa iau o pauza atat de mare, si va inteleg perfect daca nu puteti nici voi. Totusi, nu trebuie sa puneti mana pe tastatura in ultima zi. Deconectati-va in orice fel va place voua, dar nu lucrati. E o recomandare care nu se negociaza! Faceti-va programul pe zilele ramase asa cum stiti ca sa-l respectati.\r\n\r\n7) *Invatati regulamentul*\r\n\r\nStiti motto-ul cercetasilor? _BE PREPARED!_ Se poate intampla ca regulile sa nu fie respectate. Nu credeti? Acum cativa ani, regulamentul spunea ca elevul are dreptul sa-si aleaga modelul de memorie printr-un comentariu la inceputul sursei sau verbal in timpul evaluarii semi-automate. Persoana care se ocupa de jumatatea manuala a evaluarii refuza sa inteleaga acest lucru.\r\n\r\nNu te poti baza pe faptul ca totul se va desfasura corect. Poate va fi nevoie sa te certi pentru un lucru sau altul (nu recomand daca nu esti sigur ca ai dreptate), si daca se ajunge in situatia asta nu e nimic mai penibil decat sa te certi fara sa stii ce spun regulile. Cat de mult poate lua o lectura completa a regulamentului? O poti face in perioada de relaxare premergatoare zilei de concurs.\r\n\r\n8) *Nu uitati ce se testeaza de fapt*\r\n\r\nOricat de paradoxal pare, e unul din lucrurile usor de scapat din vedere. Nu se testeaza cine e mai bun, mai destept sau mai rezistent. Se testeaza cine obtine mai multe puncte pe doua probleme, intr-un anumit mediu de programare, in 3 ore de lucru. Desi factorii enumerati mai sus vor conta, nici unul dintre ei nu va fi decisiv.\r\n\r\nPe problemele pe care nu stiti sa le rezolvati, puteti obtine puncte cu greedy-uri nedemonstrate, backtracking-uri si diverse alte abordari neconventionale. Doua probleme rezolvate foarte bine sunt mai bune decat o problema rezolvata perfect. O sursa de 3 randuri care afiseaza \'-1\' poate face diferenta intre 95 si 105 puncte, si asa mai departe. Sunt lucruri pe care le-ati mai auzit de 100 de ori, si totusi merita repetate.\r\n\r\n9) *Testati, testati, testati*\r\n\r\nIesi de la concurs si colegii te intreaba cate probleme ai facut. Le spui ca una (sau doua, daca esti priceput si ai avut o zi buna). Si totusi, clasamentul aduce mereu surprize neplacute. De ce? Pentru ca o problema nu e rezolvata atunci cand functioneaza pe exemplu. Uneori vedem rezultatul corect si ne grabim sa trecem mai departe pentru ca nu vrem sa dam peste un test care ne demonstreaza ca implementarea e gresita. Totusi, daca refuzi sa vezi un lucru, nu inseamna ca acel lucru nu exista. E mult mai bine sa stii din timpul concursului ce nu merge decat sa iesi increzator in niste surse busite.\r\n\r\nSubiectul e prea complex pentru a-l dezvolta acum. Stiti cu totii sa dati teste de mana, si ar trebui sa stiti si sa scrieti un program brute-force si un generator de teste mai mari, nu e nevoie sa cititi intr-o carte despre cum se face asta.\r\n\r\n10) *Ramaneti lucizi dupa ce se termina*\r\n\r\nTocmai au trecut 3 ore extenuante. Ai terminat la limita de implementat ceva, nu esti 100% sigur daca o sa mearga. Intrebi in stanga si in dreapta ce au facut altii si constientizezi ca de-acum nu mai poti schimba nimic. Ce-o fi o fi.\r\n\r\nOpreste-te, respira adanc, si revino-ti in fire. Indiferent de ce crezi ca ai facut, nu ai voie sa adopti masuri extreme cum ar fi plecatul acasa atunci cand ti se permite sa asisti la corectare. Crede-ma, nu vrei sa iei decizii importante din cauza impulsurilor pe care le ai in astfel de momente. Partea cea mai grea a trecut, acum mai trebuie sa ai grija doar de cateva detalii.\r\n\r\n_*Multa bafta tuturor! Aveti incredere in voi!*_\r\n\r\n*Tiberiu Florea* - \'greco.ro\':http://www.greco.ro',1490,'public',2833,NULL),('propuneri/7-community-ladder','IAP #7: Community Ladder','2008-02-18 14:52:06','2009-10-27 20:48:45','h1. IAP #7: Community Ladder\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2008-02-18 |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"wickedman\")== |\r\n|_. Stare     | *_RESPINS_* |\r\n\r\nh2(#abstract). Abstract\r\n\r\nSistemul CL (Community Ladder) ofera credit, responsabilitate si autoritate persoanelor care se implica in dezvoltarea proiectului si a comunitatii infoarena.\r\n\r\nh2(#motivatie). Motivatie\r\n\r\nComunitatea infoarena are nevoie de un sistem care sa motiveze membrii sa participe, sa-si asume responsabilitati si sa vina cu initiative.\r\n\r\n\"Motivarea\" membrilor comunitatii este o tema larga si o problema foarte vag definita. Probabil nu exista planuri sau formule care sa garanteze succesul insa am reusit in acest IAP sa identific cateva elemente importante, poate chiar necesare, pentru o comunitate sanatoasa.\r\n\r\nh2(#obiective). Obiectivele CL\r\n\r\n* *Recunoaste public efortul*, implicarea, vechimea, \"muschiul\" si statutul membrilor infoarena in cadrul comunitatii. Acest obiectiv se bazeaza pe presupunerea ca fiecare voluntar vrea sa i se recunoasca statutul si munca depusa.\r\n* *Ofera responsabilitate si autoritate* membrilor care se implica semnificativ. Ca intr-o meritocratie, CL garanteaza ca daca te implici semnificativ in dezvoltarea unor proiecte vei avea un cuvant de spus in conducerea lor.\r\n** Corolar: Echipa infoarena (cei care primesc functia de consilier infoarena in cadrul \'Asociatiei infoarena\':asociatia-infoarena) se formeaza din acei membri care ajung la ultima treapta a CL.\r\n\r\nh2(#implementare). Implementare\r\n\r\nh3. Puncte infoarena\r\n\r\nSe va implementa un sistem de puncte acordate pentru efort si implicare in comunitatea infoarena.\r\n\r\nFiecare utilizator primeste puncte pentru diverse task-uri pe care le indeplineste in cadrul unui proiect infoarena. Punctele sunt acordate de catre coordonatorul proiectului sau de catre administratorii infoarena.\r\n\r\nToate punctele acordate sunt inregistrate cu o explicatie si sunt relationate cu utilizatorul care le-a acordat. Intr-una din paginile de profil ale utilizatorului se va afisa un desfasurator cu punctele primite impreuna cu explicatiile aferente. La fel se vor afisa si punctele acordate de catre un utilizator. Aceste masuri asigura transparenta si echilibrul sistemului de punctare.\r\n\r\nNu oricine poate sa acorde puncte infoarena. Administratorii pot oferi anumitor utilizatori (de exemplu coordonatorilor de proiecte) dreptul de a acorda un numar limitat de puncte. Se vor impune limite asupra numarului maxim de puncte ce poate fi acordat dintr-o data precum si asupra numarului total de puncte ce poate fi acordat de catre un utilizator.\r\n\r\nExemplu: Gigel, coordonatorul proiectului de arhiva educationala primeste din partea unui administrator dreptul de a acorda maxim cate 5 puncte deodata si in total 50 de puncte pentru derularea proiectului sau. Gigel acorda fiecarui autor de probleme cate 4-5 puncte / problema dupa cum crede de cuviinta. Atunci cand  isi epuizeaza \"creditul\" de puncte mai cere de la administrator. De fiecare data cand acorda niste puncte, Gigel va introduce o justificare precum numele problemei introduse de autor. Punctele oferite de Gigel apar intr-un desfasurator pe pagina lui de profil;  la fel si pentru fiecare utilizator care a lucrat la proiectul lui Gigel si a primit puncte.\r\n\r\nh3. Badge-uri noi\r\n\r\nPrin badge-uri ma refer la simbolul care apare langa username oriunde pe site (exemplu ==User(user=\"wickedman\" type=\"tiny\")==).\r\n\r\nIn momentul actual badge-ul este compus doar din bulina de rating. Se vor implementa noi badge-uri care sa reflecte:\r\n\r\n* punctajul infoarena (recunoaste implicarea utilizatorului in comunitate)\r\n* rating (recunoaste \"muschiul\" utilizatorului in regim de concurs)\r\n* vechime - i.e. data inregistrarii (recunoste vechimea unui membru in cadrul comunitatii)\r\n* statutul (marker special pentru membrii echipei infoarena;  nu doar pentru ca da bine la femei :) dar si pentru ca echipa infoarena are security_level administrator)\r\n\r\nPrototipuri de badge-uri\r\n\r\n|_. 16x16 |_. 32x32 |_. Explicatie |\r\n| !propuneri/7-community-ladder?ia-badge-2-s.png! | !propuneri/7-community-ladder?ia-badge-2-l.png! | Utilizator de nivel 3/5 la punctaj infoarena si cu rating \"rosu\" de algoritmi. Fundalul navy-blue poate indica vechimea. |\r\n| !propuneri/7-community-ladder?ia-badge-3-s.png! | !propuneri/7-community-ladder?ia-badge-3-l.png! | Fundalul mai inchis la culoare indica vechime si mai mare decat utilizatorul de mai sus. |\r\n| !propuneri/7-community-ladder?ia-badge-1-s.png! | !propuneri/7-community-ladder?ia-badge-1.png! | Prototip cu stelute in loc de bare verticale |\r\n| !propuneri/7-community-ladder?ia-badge-4-s.png! | !propuneri/7-community-ladder?ia-badge-4-l.png! | infoarenaut de nivel 5/5 dar fara rating de concursuri |\r\n\r\nh3. CV infoarena / infoarena Resume\r\n\r\nSe va implementa o noua pagina de profil pentru fiecare utilizator: _CV infoarena_ / _infoarena Resume_.\r\nRolul aceste pagini este sa scoata in evidenta realizarile utilizatorului in cadrul comunitatii infoarena.\r\n\r\nPagina este completata automat de catre desfasuratorul de puncte infoarena dar si manual de catre utilizator. Vom incuraja utilizatorii sa scrie cat mai mult in aceste pagini, sa puna poze si sa se laude cu realizarile lor. Paginile de CV infoarena ne aduc mai multe beneficii dintre care numesc transparenta (fiecare utilizator poate sa vada de ce este nevoie ca sa ajungi \"sus\" in CL) si social proof (multi utilizatori arata la altii cat de frumos e sa lucrezi la infoarena :).\r\n\r\nh3. Hint-uri destepte pe badge-uri\r\n\r\nInformatiile CL despre un utilizator trebuie sa fie cat mai vizibile si mai accesibile. Prin contrast, daca ar fi ascunse bine prin site, nimeni nu s-ar obosi sa le citeasca si implicit sa le scrie.\r\n\r\nSe vor implementa hint-uri in Javascript dupa cum urmeazaza:\r\n\r\n* cand duci cursorul de mouse pe un badge ti se afiseaza o cutie cu:\r\n** numar puncte infoarena, rating si vechime;  eventual se vor adauga numarul de concursuri, scorul din arhiva samd.\r\n** buton de vizualizat CV-ul infoarena sau pagina de profil\r\n* CV-ul infoarena / pagina de profil se afiseaza in acelasi ecran (AJAX) fara a schimba pagina pe care tocmai o citea utilizatorul.\r\n\r\nh3. Tratament special pentru utilizatorii noi\r\n\r\nSistemul CL trebuie sa faca diferenta intre utilizatorii proaspat inregistrati si cei vechi dar fara activitate.\r\n\r\nUtilizatorii noi trebuie incurajati sa participe si sa contribuie. Celorlalti membri mai vechi trebuie sa le \"sugeram\" ca au de a face cu un potential nou membru al comunitatii.\r\n\r\nUtilizatorii proaspat inregistrati vor avea un badge distinctiv timp de o perioada fixa.  (Q: o luna?)\r\n\r\nh2(#feedback). Feedback\r\n\r\nQ: Cum stabilim punctele initiale pe care le primeste fiecare utilizator?\r\n\r\n*Silviu*: Ce puncte initiale?\r\n* Sedinta 20080411: Initial dam puncte pentru probleme, articole, contest-directors, arhiva educationala, development, download\r\n\r\nQ: Cate puncte ar trebui sa primeasca fiecare membru al echipei infoarena?\r\n\r\n*Silviu*: Pragul de care vorbesc mai jos?\r\n\r\nQ: Care sunt pragurile de punctaj infoarena pentru nivelurile I, II, III, IV si V?\r\n\r\nA: Colectam punctajele initiale si stabilim pragurile. Avem praguri fixe, cineva care dobandeste un anumit nivel nu scade in timp.\r\n\r\nQ: Ce se intampla in caz de \"inflatie\" de puncte? Utilizatorilor vechi li se vor ajusta numarul de puncte?\r\n\r\n*Silviu*: O idee ar fi prag de puncte peste care un utilizator primeste numai distinctii. Pragul trebuie gandit in asa fel incat in momentul in care e atins utilizatorul este deja in echipa infoarena de ceva vreme (3 luni).\r\n\r\nQ: Aveti vreo idee de nume pentru punctele infoarena?\r\n\r\n*Vali*: Honor points sau Community points \r\n*Crist*: coifuri\r\n',13,'public',2795,NULL),('preoni-2008/runda-finala','preONI 2008, Runda Finala','2007-11-08 02:18:53','2008-03-15 20:34:50','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. preONI 2008, Runda Finala\r\n\r\n(htabs)*(active) \'Despre&hellip;\':preoni-2008/runda-finala\r\n* \'Program\':preoni-2008/runda-finala/program\r\n* \'Regulament\':preoni-2008/runda-finala/regulament\r\n* \'Probleme\':preoni-2008/runda-finala/probleme\r\n* \'Rezultate\':preoni-2008/clasament/runda-finala/5-8\r\n\r\nFinala concursului preONI 2008 se desfasoara in *Bucuresti*, mai exact la \'Universitatea Politehnica din Bucuresti\':http://www.upb.ro in perioada *21-23 martie 2008*.\r\n\r\n\'Premiile concursului\':preoni-2008/premii preONI se vor acorda in functie de rezultatele rundei finale. Punctajele obtinute in perioada de calificare vor servi doar la departajare. \r\n\r\nConcurentiilor li se vor asigura cazarea si masa integral dar nu si costul transportului pana la locul unde se va desfasura concursul.\r\n\r\nh2. Calificare\r\n\r\nCalificarea in aceasta etapa se face exclusiv pe baza \'clasamentului din primele 4 runde\':preoni-2008/clasament. Mentionam ca o persoana se poate califica la finala doar la grupa de varsta destinata lui si ca se va face si o identificare prin intermediul Cartii de Identiate (Buletin) sau Carnet de Note vizat si cu poza (pentru cei care nu au inca buletin) pentru a evita frauda. Daca aveti nelamuriri revedeti si \'regulamentul\':preoni-2008/regulament. \r\n\r\n*Pentru concurentii care nu s-au calificat in finala, vom gazdui si o varianta online a concursului in paralel cu finala de la Bucuresti!* Aveti ocazia sa va comparati performanta cu cei care au ajuns in finala. ;) Nu se acorda premii participantilor online.\r\n\r\nStudiati \'programul de desfasurare\':preoni-2008/runda-finala/program pentru mai multe informatii.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"57\" count=\"10\")==\r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',13,'protected',NULL,NULL),('runda/september_contest','september_contest','2009-09-10 08:58:43','2009-09-10 08:58:43','h1. == roundparam(round_id=\"september_contest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"september_contest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"september_contest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"september_contest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/september_contest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"september_contest\" score=\"1\")==',9356,'round: september_contest',NULL,NULL),('preoni-2008/runda-finala/regulament','preONI 2008 - Runda Finala, Regulament','2008-03-14 19:25:32','2008-03-15 21:23:52','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. preONI 2008, Runda Finala - Regulament\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2008/runda-finala\r\n* \'Program\':preoni-2008/runda-finala/program\r\n*(active) \'Regulament\':preoni-2008/runda-finala/regulament\r\n* \'Probleme\':preoni-2008/runda-finala/probleme\r\n* \'Rezultate\':preoni-2008/clasament/runda-finala/5-8\r\n\r\nParticipantii la runda finala - atat cei calificati in finala de la Bucuresti cat si cei care participa online - se obliga sa respecte \'regulamentul concursului preONI\':preoni-2008/regulament.\r\n\r\nIn plus, finala de la Bucuresti se desfasoara sub urmatoarele reguli:\r\n\r\n* Concurentii vor fi prezenti in salile de concurs la orele anuntate\r\n* Fiecare concurent va primi foi pentru ciorne (pix nu este inclus)\r\n* Timp de 1 ora dupa primirea subiectelor concurentii pot formula intrebari referitoare la enunturile problemelor; intrebarile se vor formula pe \'forum\':forum (se va specifica pe pagina rundei in ce topic anume se pun intrebarile); modalitate de formulare a intrebarile este identica cu cea de la primele 4 runde\r\n* In timpul probelor de concurs, concurentii:\r\n** nu vor avea asupra lor telefoane mobile sau alte mijloace de comunicatie\r\n** nu vor utiliza suporturi externe proprii (dischete/CD/flash-disk)\r\n** nu vor utiliza alte surse de documentare decat cele prezente pe calculator\r\n** nu vor incerca sa interfereze in nici un mod cu activitatile altui concurent\r\n** nu vor deteriora mediile de lucru\r\n** nu vor incerca sa interfereze cu sistemul de evaluare\r\n* In programele concurentilor nu sunt permise urmatoarele:\r\n** schimbarea drepturilor de acces la fisiere\r\n** atacul asupra securitatii sistemului sau evaluatorului\r\n** accesarea informatiilor despre sistemul de fisiere\r\n** executarea unor alte programe\r\n\r\nOrice incercare de frauda sau de a sabota desfasurarea corecta a concursului va fi urmata imediat de eliminarea elevului respectiv din concurs, cat si de pe _infoarena_.\r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',13,'protected',NULL,NULL),('runda/preoni2008-runda5-5-8/clasament','Clasament preoni2008-runda5-5-8','2008-03-14 19:34:15','2008-03-14 19:34:15','h1. Clasament ==roundparam(round_id=\"preoni2008-runda5-5-8\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda5-5-8\")==',1,'round: preoni2008-runda5-5-8',NULL,NULL),('preoni-2008/runda-finala/9','preONI 2008, Runda Finala, Clasa a 9-a','2008-03-14 19:34:35','2008-03-15 20:47:49','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda5-9\" param=\"title\") ==\r\n\r\n==Include(page=\"template/preoni-2008/runda-finala/probleme\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':preoni-2008/runda-finala/5-8\r\n*(active) \'Clasa a 9-a\':preoni-2008/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2008/runda-finala/11-12\r\n\r\n== roundregister(round_id=\"preoni2008-runda5-9\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda5-9\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda5-9\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-finala/9.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"preoni2008-runda5-9\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',13,'round: preoni2008-runda5-9',NULL,NULL),('preoni-2008/runda-finala/10','preONI 2008, Runda Finala, Clasa a 10-a','2008-03-14 19:34:56','2008-03-15 20:48:08','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda5-10\" param=\"title\") ==\r\n\r\n==Include(page=\"template/preoni-2008/runda-finala/probleme\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':preoni-2008/runda-finala/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-finala/9\r\n*(active) \'Clasa a 10-a\':preoni-2008/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2008/runda-finala/11-12\r\n\r\n== roundregister(round_id=\"preoni2008-runda5-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda5-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda5-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-finala/10.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"preoni2008-runda5-10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',13,'round: preoni2008-runda5-10',NULL,NULL),('preoni-2008/runda-finala/11-12','preONI 2008, Runda Finala, Clasele 11-12','2008-03-14 19:35:12','2008-03-15 20:48:19','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda5-11-12\" param=\"title\") ==\r\n\r\n==Include(page=\"template/preoni-2008/runda-finala/probleme\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':preoni-2008/runda-finala/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-finala/10\r\n*(active) \'Clasele 11-12\':preoni-2008/runda-finala/11-12\r\n\r\n== roundregister(round_id=\"preoni2008-runda5-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda5-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda5-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-finala/11-12.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"preoni2008-runda5-11-12\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',13,'round: preoni2008-runda5-11-12',NULL,NULL),('template/preoni-2008/runda-finala/probleme','template/preoni-2008/runda-finala/probleme','2008-03-15 20:46:19','2008-03-15 20:46:43','\r\n(htabs)* \'Despre&hellip;\':preoni-2008/runda-finala\r\n* \'Program\':preoni-2008/runda-finala/program\r\n* \'Regulament\':preoni-2008/runda-finala/regulament\r\n*(active) \'Probleme\':preoni-2008/runda-finala/probleme\r\n* \'Rezultate\':preoni-2008/clasament/runda-finala/5-8\r\n',13,'protected',NULL,NULL),('runda/preoni2008-runda5-9/clasament','Clasament preoni2008-runda5-9','2008-03-14 19:34:35','2008-03-14 19:34:35','h1. Clasament ==roundparam(round_id=\"preoni2008-runda5-9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda5-9\")==',1,'round: preoni2008-runda5-9',NULL,NULL),('runda/preoni2008-runda5-5-10','preoni2008-runda5-5-10','2008-03-14 19:34:44','2008-03-14 19:34:44','h1. == roundparam(round_id=\"preoni2008-runda5-5-10\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"preoni2008-runda5-5-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda5-5-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda5-5-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni2008-runda5-5-10/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"preoni2008-runda5-5-10\" score=\"1\")==',1,'round: preoni2008-runda5-5-10',NULL,NULL),('runda/preoni2008-runda5-5-10/clasament','Clasament preoni2008-runda5-5-10','2008-03-14 19:34:44','2008-03-14 19:34:44','h1. Clasament ==roundparam(round_id=\"preoni2008-runda5-5-10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda5-5-10\")==',1,'round: preoni2008-runda5-5-10',NULL,NULL),('runda/preoni2008-runda5-10/clasament','Clasament preoni2008-runda5-10','2008-03-14 19:34:56','2008-03-14 19:34:56','h1. Clasament ==roundparam(round_id=\"preoni2008-runda5-10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda5-10\")==',1,'round: preoni2008-runda5-10',NULL,NULL),('runda/preoni2008-runda5-11-12/clasament','Clasament preoni2008-runda5-11-12','2008-03-14 19:35:12','2008-03-14 19:35:12','h1. Clasament ==roundparam(round_id=\"preoni2008-runda5-11-12\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni2008-runda5-11-12\")==',1,'round: preoni2008-runda5-11-12',NULL,NULL),('template/preoni-2008/runda-finala/rezultate','template/preoni-2008/runda-finala/rezultate','2008-03-15 20:48:56','2008-03-15 20:50:34','(htabs)* \'Despre&hellip;\':preoni-2008/runda-finala\r\n* \'Program\':preoni-2008/runda-finala/program\r\n* \'Regulament\':preoni-2008/runda-finala/regulament\r\n* \'Probleme\':preoni-2008/runda-finala/probleme\r\n*(active) \'Rezultate\':preoni-2008/clasament/runda-finala/5-8\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;',13,'protected',NULL,NULL),('preoni-2008/clasament/runda-finala/5-8','preONI 2008, Clasament Runda Finala, Clasele 5-8','2008-03-14 20:11:34','2008-03-15 20:50:46','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda5-5-8\" param=\"title\") ==\r\n\r\n==Include(page=\"template/preoni-2008/runda-finala/rezultate\")==\r\n\r\n(htabs-2)*(active) \'Clasele 5-8\':preoni-2008/clasament/runda-finala/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-finala/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda5-5-8\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',13,'protected',NULL,NULL),('preoni-2008/clasament/runda-finala/9','preONI 2008, Clasament Runda Finala, Clasa a 9-a','2008-03-14 20:13:32','2008-03-15 20:51:07','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda5-9\" param=\"title\") ==\r\n\r\n==Include(page=\"template/preoni-2008/runda-finala/rezultate\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':preoni-2008/clasament/runda-finala/5-8\r\n*(active) \'Clasa a 9-a\':preoni-2008/clasament/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-finala/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda5-9\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',13,'protected',NULL,NULL),('preoni-2008/clasament/runda-finala/10','preONI 2008 - Clasament Runda Finala, Clasa a 10-a','2008-03-14 20:15:56','2008-03-23 07:37:27','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda5-10\" param=\"title\") ==\r\n\r\n==Include(page=\"template/preoni-2008/runda-finala/rezultate\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':preoni-2008/clasament/runda-finala/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-finala/9\r\n*(active) \'Clasa a 10-a\':preoni-2008/clasament/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2008/clasament/runda-finala/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda5-10\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',13,'protected',NULL,NULL),('preoni-2008/clasament/runda-finala/11-12','preONI 2008, Clasament Runda Finala, Clasele 11-12','2008-03-14 20:17:23','2008-03-15 21:37:50','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda5-11-12\" param=\"title\") ==\r\n\r\n==Include(page=\"template/preoni-2008/runda-finala/rezultate\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':preoni-2008/clasament/runda-finala/5-8\r\n* \'Clasa a 9-a\':preoni-2008/clasament/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2008/clasament/runda-finala/10\r\n*(active) \'Clasele 11-12\':preoni-2008/clasament/runda-finala/11-12\r\n\r\np<. == Rankings(rounds=\"preoni2008-runda5-11-12\") == \r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('utilizator/1gnition','Profil 1gnition','2008-03-15 14:55:25','2008-03-15 14:55:25','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',7905,'public',NULL,NULL),('preoni-2008/runda-finala/probleme','preONI 2008, Runda Finala - Probleme','2008-03-15 20:35:21','2008-03-15 20:47:16','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. preONI 2008, Runda Finala - Probleme\r\n\r\n==Include(page=\"template/preoni-2008/runda-finala/probleme\")==\r\n\r\nAlege grupa de varsta.\r\n\r\n(htabs-2)* \'Clasele 5-8\':preoni-2008/runda-finala/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2008/runda-finala/11-12\r\n\r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',13,'protected',NULL,NULL),('preoni-2008/runda-finala/5-8','preONI 2008, Runda Finala, Clasele 5-8','2008-03-14 19:34:15','2008-03-15 20:47:35','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. == roundparam(round_id=\"preoni2008-runda5-5-8\" param=\"title\") ==\r\n\r\n==Include(page=\"template/preoni-2008/runda-finala/probleme\")==\r\n\r\n(htabs-2)*(active) \'Clasele 5-8\':preoni-2008/runda-finala/5-8\r\n* \'Clasa a 9-a\':preoni-2008/runda-finala/9\r\n* \'Clasa a 10-a\':preoni-2008/runda-finala/10\r\n* \'Clasele 11-12\':preoni-2008/runda-finala/11-12\r\n\r\n== roundregister(round_id=\"preoni2008-runda5-5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni2008-runda5-5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni2008-runda5-5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':preoni-2008/clasament/runda-finala/5-8.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"preoni2008-runda5-5-8\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/preoni-2008/footer\")==',13,'round: preoni2008-runda5-5-8',NULL,NULL),('documentatie/tutorial-articole','Tutorial articole','2008-03-15 23:06:32','2008-11-13 18:54:08','h1. Tutorial pentru scrierea articolelor\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nNe bucuram ca ai ajuns aici si vrei sa contribui la continutul educational al site-ului. Aceasta pagina se vrea un ghid rapid si eficient care sa te puna la treaba. Poti sa citesti inainte si despre \'Textile\':documentatie/textile si \'conventiile de formatare\':documentatie/conventii-de-formatare pe care le utilizam, dar crearea unui articol este mult mai simpla si mai frumoasa decat acele seturi de reguli. :)\r\n\r\nh2. Structura articolului\r\n\r\nMai mult ca sigur ca ai un plan pe care vrei sa-l urmezi in scrierea articolului. Punerea lui pe infoarena este cu atat mai simpla. Tot ce trebuie sa faci este sa copii continutul paginii \'\"Structura articol\"\':documentatie/structura-articol in pagina articolului tau, iar apoi sa il adaptezi in functie de titlul, categoria si sectiunile adecvate. Dupa cum observi in structura, e foarte important sa ai un cuprins care sa-i ajute pe utilizatori sa se duca direct la tinta in articol.\r\nReferitor la structura, iti facem si cateva recomandari care vor pune in valoare munca ta:\r\n\r\n* Mentine sectiunile de cel mult 1 pagina pentru a fi usor de urmarit.\r\n* Propune-i cititorului o lista de probleme care il pot ajuta in intelegerea subiectului abordat.\r\n* Include la sfarsit si o lista bibliografica cu sursele din care te-ai documentat.\r\n\r\nh2. Bucati de cod\r\n\r\nDaca subiectul pe care il tratezi necesita si implementari intr-un limbaj de programare, nu ezita sa incluzi bucati de cod edificatoare. Iata un exemplu despre cum ar trebui sa arate codul pe care il incluzi:\r\n\r\n== code(cpp) |\r\nconst int MAX_N = 100;\r\n\r\nint N, A[MAX_N], B[MAX_N];\r\n\r\nvoid merge_sort(int l, int r) {\r\n    int m = (l + r) >> 1, i, j, k;\r\n    if(l == r) return;\r\n\r\n    merge_sort(l, m);\r\n    merge_sort(m + 1, r);\r\n\r\n    for(i = l, j = m + 1, k = l; i <= m || j <= r; )\r\n        if(j > r || (i <= m && A[i] < A[j]))\r\n            B[k++] = A[i++];\r\n        else\r\n            B[k++] = A[j++];\r\n\r\n    for(k = l; k <= r; k++)\r\n        A[k] = B[k];\r\n}\r\n==\r\n\r\nCe trebuie sa observi la el?\r\n\r\n* numele de variabile si de functii sunt sugestive\r\n* indentarea se face cu 4 spatii, nu tab-uri\r\n* se evita macro-urile, folosind in schimb constante, typedef, functii inline\r\n* codul este aerisit prin separarea cu spatii a operatorilor de restul codului (mai putin $++$ si $--$)\r\n* codul compileaza pe o versiune recenta a unui compilator modern\r\n\r\nh2. Formule\r\n\r\nDaca articolul tau necesita formule mai complicate, nu te lasa descurajat. Infoarena suporta <tex>\\LaTeX</tex>. Si ca sa-ti trezim un pic apetitul si sa iti placa sa lucrezi la articolul tau, iata ce se poate face:\r\n\r\n<tex>infoarena = \\displaystyle\\sum_{user=1}^\\infty implicare_{user}</tex>\r\n\r\nh2. Alte aspecte\r\n\r\nSperam ca munca la articole sa fie simpla si placuta. Daca totusi te incurci in site-ul nostru, ia legatura cu unul din membrii echipei infoarena si o sa fii indrumat. Spor la treaba!',2044,'public',NULL,NULL),('documentatie','Documentatie','2006-11-21 14:59:13','2009-03-21 21:23:07','h1. Documentatie\r\n\r\n==include(page=\"documentatie/sidebar\")==\r\n\r\nAici centralizam toate paginile care prezinta modul in care se utilizeaza site-ul si evaluatorul infoarena.\r\n\r\n* *Continut*: Cum se manipuleaza continutul site-ului\r\n** {\'Wiki\':documentatie/wiki}: O introducere in wiki-ul infoarena.\r\n** {\'Sintaxa Textile\':documentatie/textile}: Detalii hardcore despre formatarea cu textile.\r\n** {\'Macro-uri\':documentatie/macro-uri}: Ce sunt, cum se folosesc, cateva macro-uri comune.\r\n** {\'Conventii de formatare\':documentatie/conventii-de-formatare}: Cum anume se foloseste formatarea pentru a ajunge la un look uniform.\r\n* *Ghid utilizator*: Inregistrare, submit, monitor, clasament. Cat mai scurt.\r\n** {\'Tutorial infoarena\':documentatie/tutorial}: Un tutorial infoarena\r\n** {\'Tutorial articole\':documentatie/tutorial-articole}: Un scurt ghid pentru crearea unui articol\r\n** {\'Evaluatorul infoarena\':documentatie/evaluator}: Ce configuratie si ce compilatoare foloseste infoarena.\r\n** {\'Trimiterea solutiilor\':documentatie/trimiterea-solutiilor}: Cum se trimit solutii.\r\n** {\'Monitorul de evaluare\':documentatie/monitorul-de-evaluare}: Ce este si cum se foloseste monitorul de evaluare.\r\n** {\'Borderoul de evaluare\':documentatie/borderoul-de-evaluare}: Cum se interpreteaza borderoul de evaluare.\r\n** {\'Pagina de profil\':documentatie/pagina-de-profil}: Cum se face o pagina de profil pe infoarena.\r\n** {\'Rating\':documentatie/rating}: Ce este si cum functioneaza sistemul de rating\r\n** {\'Concursuri virtuale\':documentatie/concursuri-virtuale}: Cum se creaza si cum se participa la un concurs virtual.\r\n* *Ghid propunatori*: Cum devii propunator, ce inseamna.\r\n** {\'Editare de probleme\':documentatie/editare-de-probleme}: Cum se pun teste, cum se verifica etc.\r\n** {\'Ghid evaluator\':documentatie/ghid-evaluator}: Cum se face un program de evaluare.\r\n** {\'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala}: Setul de reguli pentru problemele din arhiva educationala.\r\n** {\'Gruparea testelor\':documentatie/grupare-teste}: Ce inseamna gruparea testelor si cum se foloseste.\r\n* {\'Ghid administratori\':documentatie/administrare}',1490,'public',NULL,NULL),('all-you-can-code-2008','All You Can Code 2008','2008-11-23 11:19:07','2008-11-27 21:07:12','==include(page=\"templates/all-you-can-code-logo\")==\r\n\r\nh1. == roundparam(round_id=\"all-you-can-code2008\" param=\"title\") ==\r\n\r\n(htabs)*(active) \'Despre...\':all-you-can-code-2008\r\n* \'Probleme\':all-you-can-code-2008/probleme \r\n* \'Clasament\':all-you-can-code-2008/clasament\r\n\r\nConcursul _All You Can Code_ este organizat de trei membri infoarena: Florin Pogocsan, Puni Andrei Paul si Mihai Ciucu.\r\n\r\nh2. Despre concurs\r\n\r\nInainte ca iarna sa isi intre in drepturi, in ultimul week-end din luna noiembrie, te invitam sa iei parte la un concurs organizat de membrii comunitatii. Concursul va fi o buna ocazie de antrenament atat pentru cei mai mici, cat si pentru cei mai mari, in asa fel incat participarea este incurajata indiferent de varsta. Concurentii vor avea de rezolvat 9 probleme de algoritmica de dificultate variata. Timpul in care concurentii pot trimite solutii va fi de 36h (o zi si jumatate), concursul va incepe *sambata, 29 noiembrie, ora 12^00^*, ultima submisie fiind acceptata *duminica, 30 noiembrie, ora 24^00^*. \r\nIn primele *4* ore din concurs evaluatorul va fi oprit (se pot trimite surse, dar ele nu vor fi evaluate), in rest pe toata durata urmatoare a concursului evaluatorul va fi pornit si la toate problemele vor exista si punctaje partiale. Va asteptam in numar cat mai mare la concurs, succes tuturor!\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 12^00^* daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* nu ti se va modifica \'rating-ul\':documentatie/rating, insa poti sa participi oricum!\r\n\r\n== roundregister(round_id=\"all-you-can-code2008\") ==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==user(user=\"crawler\" type=\"tiny\")==\r\n* ==user(user=\"binary_fire\" type=\"tiny\")==\r\n* ==user(user=\"gogu\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru!\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti problemele, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':documentatie/evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nh2. Prima data pe _infoarena_?\r\n\r\n\'infoarena\':/ ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi si vezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n',2092,'protected',NULL,NULL),('summer-challenge-2/solutii','Solutii - Summer Challenge Doi','2006-08-11 00:00:00','2008-11-23 17:28:10','h1. Solutii - Summer Challenge Doi\r\n\r\n(Categoria _Competitii_, autor(i) _Adrian Diaconu si Cosmin Negruseri_)\r\n\r\nh2. \"Sah\":problema/sah\r\n\r\nPrima observatie ar fi ca pentru a ne asigura ca intr-o regiune numarul de casute albe este egal cu numarul de celule negre este suficient ca aria regiunii sa fie para.\r\n\r\nPlecand de la aceasta observatie si de la faptul ca $N$ este mereu par propunem urmatoarea impartire a tablei si voi demonstra apoi ca indeplineste conditiile din enunt. Impartim tabla in benzi de latime $2$ (pentru a asigura paritatea ariilor). Apoi prima banda o lasam intreaga, iar pentru urmatoarele banda $i$ se va inmparti in $i-1$ si {$N-i+1$}. Astfel se vor creea $N-1$ regiuni. Se observa ca toate dreptunghiurile difera intre ele prin lungime deoarece se folosesc toate numerele de la $1$ la $N$ mai putin {$N/2$}.\r\n\r\nPentru a demonstra ca $N-1$ este numarul maxim de regiuni care se poate creea vom presupune ca se poate imparti tabla in $N$ regiuni. Vom considera ca se folosesc cele mai mici arii posibile, dar acestea trebuie sa fie toate pare. Suma ariilor va fi $2+4+6+..+2*N= 2*(N*(N+1)/2)=N*N+N$ ceea ce ar depasi tabla noastra.\r\n\r\nh2. \"Plimbare\":problema/plimbare\r\n\r\nEvident ca o conditie necesara ca un graf turneu (asa se numesc grafurile ca cel mentionat in enunt in care exista exact un arc intre oricare doua noduri) sa aiba un circuit hamiltonean ar fi ca graful sa fie tare conex, daca nu ar fi tare conex atunci evident nu poate exista un circuit intre doua noduri aflate in doua componente tari conexe diferite. Aceasta conditie este si suficienta asa cum va reiesi din algoritmul pe care il vom explica mai jos.\r\n\r\nAstfel pentru graful nostru vom determina componentele tari conexe, si vom cauta un circuit hamiltonean in cea mai mare dintre acestea. De acum ne vom concentra doar asupra nodurilor acestei componente. Evident ca aceasta componenta conexa contine cel putin un circuit, pentru a determina unul facem o cautare in adancime, si trebuie sa gasim la un moment dat o muchie de intoarcere (pentru ca altfel componenta nu ar fi tare conexa). Vom imparti nodurile din aceasta componenta in patru multimi: $A$ multimea nodurilor din circuit, $B$ multimea nodurilor din afara circuitului pentru care exista si arce orientate de la noduri din circuit la ele, si arce orientate de la ele la noduri din circuit, $C$ multimea nodurilor din afara circuitului pentru care exista numai arce ce pornesc din circuit inspre noduri, si $D$ multimea nodurilor pentru care toate arcele intre ele si noduri din circuit sunt orientate de la ele inspre circuit. Puteti observa ca nodurile din multimea $B$ pot fi inserate tot timpul in circuit undeva inlocuind un arc intre doua noduri ale circuitului cu doua arce de la un nod al circuitului la nodul multimii $B$ si apoi la alt nod din circuit. Inserarea unui astfel de nod dureaza maxim $O(n)$ pasi, alti $O(n)$ pasi ar fi necesari pentru modificarea multimilor $B, C, D$ pentru ca circuitul s-a schimbat. Dupa ce nu ne mai ramane nici un nod in {$B$}. Ramanem doar cu noduri de tip $C$ sau {$D$}. Orice nod din multimea $C$ va avea cel putin un arc orientat spre alt nod din multimea $D$ pentru ca altfel nu am fi intr-o componenta tare conexa. Acum aceste doua noduri legate printr-o muchie dinspre $C$ inspre $D$ pot fi inserate in circuit. Astfel am aratat o cale practica de a mari lungimea circuitului pana cand epuizam toate nodurile.\r\n\r\nDaca folosim metoda de determinare a componentelor tari conexe folosind un algoritm eficient de complexitate {$O(N + M)$}, atunci algoritmul are complexitatea $O(N^2^)$ pentru ca la fiecare inserare facem $O(n)$ pasi. Un algoritm mai eficient nu putem obtine deoarece {$M = N(N-1)/2$}, deci si citirea datelor e {$O(N^2^)$}. $N$ a fost fixat la $100$ pentru ca am vrut sa punem accent asupra ideii de gasire a circuitului si nu asupra algoritmului de determinare eficienta a componentelor tari conexe.\r\n\r\nh2. \"TreiD\":problema/TreiD\r\n\r\nAceasta problema e similara cu problema \"Bmatrix\":problema/bmatrix din arhiva si a fost propusa pentru a favoriza utilizatorii inraiti :).\r\nTrei dreptunghiuri pot avea ca amplasare relativa doar 6 pozitii diferite:\r\n${@+@}------{@+@}&nbsp;&nbsp;&nbsp;&nbsp;{@+@}------{@+@}&nbsp;&nbsp;&nbsp;&nbsp;{@+@}------{@+@}$ \r\n${@|@}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{@|@}&nbsp;&nbsp;&nbsp;&nbsp;{@|@}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{@|@}&nbsp;&nbsp;&nbsp;&nbsp;{@|@}&nbsp;&nbsp;{@|@}&nbsp;&nbsp;&nbsp;{@|@}$\r\n${@+@}------{@+@}&nbsp;&nbsp;&nbsp;&nbsp;{@+@}--{@+@}---{@+@}&nbsp;&nbsp;&nbsp;&nbsp;{@+@}&nbsp;&nbsp;{@+@} &nbsp;&nbsp;{@+@}$\r\n${@|@}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{@|@}&nbsp;&nbsp;&nbsp;&nbsp;{@|@}&nbsp;&nbsp;{@|@}&nbsp;&nbsp;&nbsp;{@|@}&nbsp;&nbsp;&nbsp;&nbsp;{@|@} &nbsp;{@|@}&nbsp;&nbsp;&nbsp;{@|@}$\r\n${@+@}------{@+@}&nbsp;&nbsp;&nbsp;&nbsp;{@+@}&nbsp;&nbsp;{@+@}&nbsp;&nbsp;&nbsp;{@+@}&nbsp;&nbsp;&nbsp;&nbsp;{@+@}------{@+@}$          \r\n${@|@}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{@|@}&nbsp;&nbsp;&nbsp;&nbsp;{@|@}&nbsp;&nbsp;{@|@}&nbsp;&nbsp;&nbsp;{@|@}&nbsp;&nbsp;&nbsp;&nbsp;{@|@}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{@|@}$\r\n${@+@}------{@+@}&nbsp;&nbsp;&nbsp;&nbsp;{@+@}------{@+@}&nbsp;&nbsp;&nbsp;&nbsp;{@+@}------{@+@}$  \r\nsi rotatiile cu 90 de grade ale acestora.\r\n\r\nPentru a determina pentru fiecare configuratie solutia optima putem incerca orice impartire posibila cu doua linii in trei zone a dreptunghiului initial. Apoi ne trebuie pentru fiecare dreptunghi de tipul {$[1..i]x[1..j], [1..i][j..m], [i..n]x[1..j], [i..n]x[j..m], [i..j]x[1..m] si [1..n]x[i..j]$}.\r\nCa sa determinam suma numerelor din un dreptunghi $[r{~1~}..r{~2~}]x[c{~1~}..c{~2~}]$ folosim o matrice $B[i][j]$ care e suma elementelor din {$[1..i]x[1..j]$}, avand aceasta matrice calculata putem determina ca suma elementelor din dreptunghiul $[r{~1~}..r{~2~}]x[c{~1~}..c{~2~}]$ este {$B[r{~2~}][c{~2~}] - B[r{~1~} - 1][c{~2~}] - B[r{~2~}][c{~2~} - 1] + B[r{~1~} - 1][c{~1~} - 1]$}. Pentru a calcula $B[i][j]$ eficient parcurgem elementele matricii initiale $A$ in ordine si avem ca {$B[i][j] = A[i][j] + B[i][j - 1] + B[i- 1][j] - B[i-1][j-1]$}.\r\n\r\nVom explica cum determinam submatricea optima pentru dreptunghiul $[i..j]x[1..m]$ in {$O(n)$}, celelalte dreptunghiuri putand fi determinate intr-un mod asemanator. Avem trei cazuri posibile: linia de sus a dreptunghiului optim nu coincide cu linia {$i$}, si astfel putem lua informatia despre el din rezultatul calculului pentru dreptunghiul {$[i+1..j]x[1..m]$}, al doilea caz e cand linia de jos nu coincide cu linia {$j$}, acum luam rezultatul optim pentru dreptunghiul {$[i..j-1]x[1..m]$}. Al treilea caz cand dreptunghiul optim se sprijina pe liniile $i$ si $j$ il putem rezolva in $O(n)$ asemanator problemei de determinare a unei subsecvente de suma maxima pe un vector {$C$}. $C[k]$ va fi egal cu suma elementelor din dreptunghiul $[i..j] x [k..k]$ (deci suma elementelor din banda $[i..j]$ ce sunt pe coloana {$k$}).\r\n\r\nPentru a determina subsecventa de suma maxima a sirului {$C$}, vom folosi vectorul {$sum[k]$} {$= C[k] + C[k-1] + ... + C[1&#0093;$}. Astfel suma elementelor $C[k..l]$ este egala cu {$sum[l] - sum[k - 1]$}. Pentru a determina subsecventa de suma maxima ce se termina in $l$ trebuie sa gasim cea mai mica $sum[k - 1]$ pentru a maximiza expresia {$sum[l] - sum[k - 1]$}. Astfel obtinem urmatorul cod:\r\n== code(c) |\r\nint min_sum = 0;\r\nint best = - infinit;\r\nfor (int k = 0; k < m; k++) {\r\n    if (best < sum[l] - min_sum)\r\n        best = sum[l] - min_sum;\r\n    if (sum[l] < min_sum) min_sum = sum[l];\r\n}\r\nreturn best;\r\n==\r\nAcest algoritm are complexitatea {$O(n)$}.\r\n\r\nAstfel algoritmul calculeaza in $O(n)$ valoarea optima pentru $O(n^2^)$ zone, deci in total avem un algoritm ce consuma $O(n^2^)$ memorie si are complexitatea $O(n^3^)$ ca timp.',4230,'public',NULL,NULL),('utilizator/darkdude','Profil darkdude','2008-03-12 06:05:06','2009-03-30 09:02:18','h2. Despre mine\r\n\r\nElev in Saguna (Brasov) a X-a\r\n\r\nPHP, JS + jQuery, C++ ( poate Perl la vara :) ) = chestii utile\r\nQuakeLive, WoW, The West si altele = frecangeli.\r\n\r\n\r\n\r\nh2. Prieteni\r\n\r\n==user(user=\"codrin\" type=\"normal\")==\r\n',7841,'public',NULL,NULL),('runda/1','1','2009-03-22 14:02:20','2009-03-22 14:02:20','h1. == roundparam(round_id=\"1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"1\" score=\"1\")==',8454,'round: 1',NULL,NULL),('runda/1/clasament','Clasament 1','2009-03-22 14:02:20','2009-03-22 14:02:20','h1. Clasament ==roundparam(round_id=\"1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"1\")==',8454,'round: 1',NULL,NULL),('utilizator/mugurelionut','Profil mugurelionut','2006-11-24 20:57:07','2008-05-30 12:04:53','h2. \'Pagina personala\':https://mail.cs.pub.ro/~mugurel.andreica/  (under construction)\r\n\r\n* \'colectia personala de probleme de informatica\':https://mail.cs.pub.ro/~mugurel.andreica/task_archive.htm (3.5 GB)\r\n\r\nh2. Studii\r\n\r\n* 2006-prezent : Doctorat la Facultatea de Automatica si Calculatoare, Universitatea Politehnica Bucuresti\r\n* 2006-2008 : Masterat la Facultatea de Automatica si Calculatoare, Universitatea Politehnica Bucuresti (media 10 la toate examenele)\r\n* 2001-2006 : Facultatea de Automatica si Calculatoare (sef de promotie cu media 10 :D )\r\n* 1997-2001 : Colegiul National \"Cantemir-Voda\", Bucuresti (sef de promotie cu media 9.99 :D )\r\n* 1989-1997 : Scoala generala 307, Bucuresti (guess what? tot sef de promotie :) ) \r\n\r\nh2. Premii, medalii si distinctii\r\n\r\n* Finala ACM ICPC\r\n  - 2005, Martie : Medalie de Bronz (locul 10)\r\n  - 2002, Martie : Locul 18 \r\n* Etapa regionala sud-est europeana a concursului ACM ICPC (ACM SEERC)\r\n  - 2004, Octombrie : Locul 1\r\n  - 2003, Octombrie : Locul 4\r\n  - 2001, Octombrie : Locul 1\r\n* Olimpiada Internationala de Informatica\r\n  - 2001, Iulie : Medalie de Argint\r\n* Olimpiada Internationala Pluridisciplinara \"Tuymaada\"\r\n  - 2000, Iulie : Premiul I (locul 1)\r\n* Olimpiada Nationala de Informatica\r\n  - 2001 : Premiul I (locul 2)\r\n  - 2000 : Premiul III\r\n  - 1999 : Premiul II (locul 5)\r\n* Concursul de programare \"Bursele Agora\"\r\n  - 2005 : Locul 1\r\n  - 2004 : Locul 3\r\n  - 2002 : Locul 1\r\n  - 2001 : Locul 1\r\n* Internet Problem Solving Contest (IPSC)\r\n  - 2002, Mai : Locul 5\r\n* Cupa COMPAQ\r\n  - 2001, Ianuarie: Locul 1 (singura data cand am obtinut la vreun concurs un punctaj mai mare decat Mihai Patrascu :) ) *Cosmin:* Parca si la ACM ai facut mai bine :).\r\n* USACO\r\n  - 2001, Spring Contest: Locul 1\r\n\r\nh2. Profesori care m-au ajutat la pregatirea pentru concursurile de informatica (in ordine cronologica)\r\n\r\n* Emil Dragomirescu\r\n* Radu Jugureanu\r\n* Rodica Pintea\r\n* Mihai Stroe\r\n\r\nh2. Activitati legate de informatica\r\n\r\n* Membru al comitetului stiintific al Olimpiadei Balcanice de Informatica, Iasi, 2003\r\n* Membru al comitetului stiintific al Olimpiadei Nationale de Informatica (2002-2007)\r\n* Coach al unora dintre echipele ce au reprezentat Universitatea Politehnica Bucuresti la etapa regionala sud-est europeana a concursului ACM ICPC (2005-2007)\r\n* Membru al echipei ce a selectat (si, intr-o oarecare masura, pregatit) lotul de informatica al Romaniei (2002-2007)\r\n* Membru al echipei proiectului .campion (2002-2007)\r\n* Membru al comitetului stiintific al concursului \"Stelele Informaticii\" (2003, 2005, 2006)\r\n* Deputy Leader al delegatiei Romaniei la IOI 2007\r\n\r\nh2. Publicatii\r\n\r\n* \"Towards ServMark, an Architecture for Testing Grids\", M. Andreica, N. Tapus, A. Iosup, D.H.J. Epema, C. Dumitrescu, I. Raicu, I. Foster, M. Ripeanu - CoreGRID Techincal Reports 2006 (http://www.coregrid.net/mambo/content/view/209/203/)\r\n* \"Towards a Communication Framework Based on Balanced Message Flow Distribution\", M. Andreica, I. Legrand, N. Tapus, IEEE Region 8 EUROCON Conference, Septembrie 2007\r\n* \"Arborele componentelor biconexe si al nodurilor critice\", Mugurel Ionut Andreica, GInfo 16/5, Mai 2006\r\n',468,'protected',NULL,NULL),('dijkstra-buckets','dijkstra-buckets','2008-03-17 18:24:33','2008-03-17 18:30:18','*Aceasta pagina este in constructie.*\r\n\r\n\'Algoritmul lui Dijkstra cu buckets\':http://infoarena.ro/forum/index.php?topic=2778.msg22617#msg22617\r\n\r\n',3760,'public',NULL,NULL);
 INSERT INTO `ia_textblock` VALUES ('algoritmi-de-baleiere','Algoritmi de baleiere (sweeping)','2008-03-15 19:21:49','2008-03-17 23:59:29','h1. Algoritmi de baleiere (sweeping)\r\n\r\n(Categoria _Geometrie_, Autor _Stefan Istrate_)\r\n\r\n(toc){width: 25em}*{text-align:center;} *Continut*\r\n* \'Introducere\':algoritmi-de-baleiere#introducere\r\n* \'Prezentarea metodei\':algoritmi-de-baleiere#prezentare\r\n* \'Baleiere verticala\':algoritmi-de-baleiere#baleiere_verticala\r\n* \'Baleiere radiala\':algoritmi-de-baleiere#baleiere_radiala\r\n* \'Un alt algoritm pentru infasuratoarea convexa\':algoritmi-de-baleiere#infasuratoare_convexa\r\n* \'Aplicatii\':algoritmi-de-baleiere#aplicatii\r\n* \'Bibliografie\':algoritmi-de-baleiere#bibliografie\r\n\r\nh2(#introducere). Introducere\r\n\r\nSa presupunem ca vrem sa implementam un joc video in care personajul-jucator se poate plimba pe o harta planara cu obstacole (ziduri), iar in fiecare moment trebuie sa desenam pe ecran doar obstacolele pe care le vede acesta (chiar si partial). Mai precis, personajul reprezinta un punct, iar zidurile reprezinta segmente in plan. Ceea ce ne intereseaza sunt segmentele vizibile. Un punct este vizibil din alt punct daca segmentul ce le uneste nu intersecteaza niciun zid. Un zid este vizibil daca are cel putin un punct vizibil din pozitia jucatorului. Desigur, am putea alege cate 2 obstacole si trata toate cazurile care apar, dupa care sa pastram doar portiunile vizibile din cele 2 obstacole, dar aceasta abordare poate fi costisitoare uneori. Cel mai indicat ar fi sa gasim un mod eficient de \"scanare\" a planului prin care sa obtinem o lista de segmente vizibile.\r\n\r\nh2(#prezentare). Prezentarea metodei\r\n\r\nAceasta tehnica de \"scanare\" mentionata mai sus poarta numele de _baleiere_, sau _sweeping_ (engl. _sweeping_ = \"maturare\"). Exemplul de mai sus ilustreaza tocmai faptul ca tehnologiile si programele avansate din ziua de azi au la baza tehnici simple, dar nu lipsite de importanta. In majoritatea problemelor de geometrie vom intalni obiecte geometrice: puncte, drepte, segmente, figuri, corpuri. Avem nevoie sa stim sa le gestionam corect si sa extragem informatiile necesare in functie de situatia ivita.\r\n\r\nFie $S$ o multime de obiecte in plan pentru care trebuie sa extragem anumite informatii si $Q$ intrebarea la care trebuie sa raspundem. Abordarea intuitiva ar fi: alegem o dreapta (fie ea orizontala, verticala sau oblica) si o plimbam peste multimea de obiecte; in timpul baleierii ne asiguram ca sunt extrase toate informatiile referitoare la intrebarea $Q$; dupa ce am terminat scanarea, construim si afisam raspunsul pe baza informatiilor adunate. O descriere ceva mai explicita se poate vedea in imaginea de mai jos:\r\n\r\n!algoritmi-de-baleiere?fig1.jpg!\r\n\r\nIn timpul baleierii, la fiecare pas trebuie sa avem la dispozitie o structura de date continand toate obiectele intersectate de linia de baleiere. Pentru exemplul de mai sus, multimea de obiecte e traversata de sus in jos, iar la pasul curent sunt intersectate obiectele $b$, $d$, $e$, $f$. Continuand traversarea, vor urma, in ordine, eliminarea lui $b$ din structura de date, eliminarea lui $d$, adaugarea lui $g$, etc. Dupa cum se observa, multimea obiectelor intersectate sufera destule modificari, ceea ce ne determina sa alegem o structura dinamica de date care sa ne confere eficienta. De cele mai multe ori, alegerea noastra va fi un arbore echilibrat. In cadrul algoritmului, vom vrea sa stim si care sunt momentele la care multimea obiectelor intersectate sufera modificari. Aceste momente vor reprezenta _evenimentele_, iar multimea acestora se va numi _lista de evenimente_. Iata pasii unui algoritm de baleiere (pastram notatia $Q$ pentru intrebarea pe care o adresam):\r\n\r\n== code(c) |\r\nInitializeaza lista de evenimente (L)\r\nInitializeaza multimea obiectelor intersectate (M)\r\nCAT TIMP L este nevida\r\n    Sterge din L evenimentul care urmeaza\r\n    DACA un nou obiect este intersectat de linia de baleiere\r\n        Adauga-l in M\r\n    DACA un obiect inceteaza a mai fi intersectat\r\n        Sterge-l din M\r\n    Aduna informatii privitoare la intrebarea Q\r\n    DACA este cazul\r\n        Adauga noi evenimente in L\r\nRaspunde la intrebarea Q pe baza informatiilor adunate\r\n==\r\n\r\nh2(#baleiere_verticala). Baleiere verticala\r\n\r\nSa vedem acum o situatie mai concreta. Sa presupunem ca avem $N$ dreptunghiuri in primul cadran al unui plan, cu laturile paralele cu axele de coordonate, iar latura de jos fixata pe axa $OX$. Cum am putea afla aria reuniunii tuturor dreptunghiurilor? De data aceasta, nici macar o solutie naiva nu este multumitoare. Cel mai simplu lucru la care ma gandesc ar fi calcularea ariei folosind principiul includerii si excluderii: se aduna ariile tuturor dreptunghiurilor, se scad ariile comune cator 2 dreptunghiuri, se aduna ariile comune cator 3 dreptunghiuri, etc. Este evident ca aceasta abordare este total nerecomandata din cauza timpului de rulare exponential. Ei bine, solutia la aceasta problema se bazeaza pe o baleiere verticala in care linia de baleiere este plimbata de la stanga la dreapta peste obiecte.\r\n\r\nSa observam mai intai ca laturile verticale ale dreptunghiurilor, precum si latura de jos pot fi ignorate, pastrand doar latura de sus pentru fiecare dreptunghi. Figura initiala este compusa din fasii verticale, fiecare fasie fiind delimitata in partea superioara de un segment (latura de sus a unui dreptunghi initial). Nu ne ramane de facut decat o parcurgere a fiecarei fasii si calcularea ariei acesteia, apoi insumarea tuturor.\r\n\r\n!algoritmi-de-baleiere?fig2.jpg!\r\n\r\nSa analizam acum problema din perspectiva tehnicii pe care dorim sa o folosim. Evenimentele sunt, in acest caz, capetele stangi si cele drepte ale segmentelor orizontale. O alta observatie importanta este aceea ca, parcurgand o fasie cu linia de baleiere verticala, niciun segment nu este adaugat sau eliminat intre timp din multimea obiectelor intersectate. Schimbarile vor aparea doar la granita dintre fasii.\r\n\r\nInainte de a parcurge lista de evenimente, o vom sorta crescator in functie de abscisele capetelor segmentelor orizontale. Apoi, la fiecare pas, vom procesa toate evenimentele cu aceeasi abscisa. In ce consta acest lucru? Mai intai interogam structura de date continand obiectele deja intersectate si il alegem pe cel cu ordonata maxima $Y$. Aria ultimei fasii din stanga liniei de baleiere poate fi calculata usor cu formula $Y * D$, unde $D$ este distanta pana la pozitia precedenta a liniei de baleiere, si apoi adaugata la aria totala. In cele din urma vom insera sau, dupa caz, vom sterge din structura de date obiectele a caror stare se schimba din cauza evenimentelor de la abscisa curenta. Asadar, vom avea nevoie de inserari, stergeri si interogari rapide. Putem alege un \'arbore de intervale\':arbori-de-intervale (fiind necesara, inainte de toate, o normalizare a tuturor ordonatelor), un heap sau un arbore binar echilibrat de cautare in care ordonarea cheilor sa se faca dupa ordonata. Aveti, totusi, grija la duplicate: pot exista mai multe segmente orizontale cu aceeasi ordonata $Y$, ceea ce inseamna ca structura noastra de date trebuie sa gestioneze corect inserarea unui obiect cu o ordonata deja existenta sau stergerea acestuia.\r\n\r\nSa vedem acum analiza complexitatii. Avem nevoie de un timp $O(N * log N)$ pentru sortarea listei de evenimente dupa abscisa, $O(log N)$ (sau chiar $O(1)$ la heap-uri si la $set$-urile din STL) pentru alegerea obiectului cu ordonata maxima, $O(log N)$ pentru inserare si stergere in structura de date aleasa. Intrucat sunt $2 * N$ evenimente (cate 2 capete pentru fiecare segment), iar pentru fiecare efectuam o interogare si o adaugare / stergere, complexitatea finala va fi $O(N * log N) + O(N) * (O(log N) + O(log N)) = O(N * log N)$.\r\n\r\nSituatia se poate complica daca dreptunghiurile nu au o latura fixata pe axa $OX$. Nu mai este suficienta o simpla extragere a elementului maxim din structura de date, ci trebuie sa retinem mult mai multe informatii pentru a pastra complexitatea $O(N * log N)$. Aceasta generalizare a fost data la Olimpiada Baltica de Informatica din 2001 (problema Mars Maps).\r\n\r\nh2(#baleiere_radiala). Baleiere radiala\r\n\r\nBaleierea verticala nu este singura modalitate de scanare a planului. Pentru exemplificarea acestui lucru, se poate porni tot de la o situatie concreta: avand $N$ puncte in plan, vrem sa aflam numarul maxim de puncte coliniare. O solutie triviala ar fi sa se fixeze 2 puncte si sa se numere toate punctele coliniare cu cele 2 dintre cele ramase. Complexitatea totala ar fi $O(N^3^)$ care, in mod evident, nu este multumitoare. O imbunatatire semnificativa a algoritmului se obtine folosind tehnica de baleiere: se fixeaza un punct si se scaneaza planul cu ajutorul unei semidrepte avand originea in punctul fixat. Rotind semidreapta si suprapunand-o peste un punct, numaram daca mai exista si altele peste care s-a suprapus. Nu trebuie sa ne ingrijoreze faptul ca pot fi puncte coliniare cu unele gasite deja, dar care se afla in sensul opus celui dat de semidreapta aleasa, pentru ca oricum vom face o baleiere in fiecare punct si intr-unul din ele le vom numara corect in mod sigur pe cele coliniare. Implementarea eficienta a acestei metode presupune ca, odata fixata originea semidreptei, sa se sorteze toate celelalte puncte in functie de unghiul polar relativ la punctul fix. Complexitatea ajunge, astfel, la $O(N^2^ * log N)$.\r\n\r\nO aplicatie ceva mai spectaculoasa a baleierii radiale este gasirea unui triunghi dreptunghic cu varfurile printre $N$ puncte date. Fixand un punct, putem cauta un triunghi dreptunghic care sa aiba unghiul drept in acel punct. Pentru acest lucru, vom sorta punctele exact ca la problema precedenta, dar baleierea o vom face rotind simultan 2 semidrepte cu originile in punctul fix, intre care mentinem in orice moment un unghi de 90 de grade. Cand ambele semidrepte se vor suprapune peste cate un punct, vom gasi ceea ce cautam. Complexitatea acestui algoritm va fi tot $O(N^2^ * log N)$.\r\n\r\nh2(#infasuratoare_convexa). Un alt algoritm pentru infasuratoarea convexa\r\n\r\nh2(#aplicatii). Aplicatii\r\n\r\nIata si o scurta lista de probleme care merita implementate:\r\n\r\n* BOI 2001: \'Mars Maps\':http://www.ii.uni.wroc.pl/boi/index.phtml?id=11\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n\r\n\r\n*Cosmin:* Articolul asta despre baleiere http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=lineSweep e destul de bine facut, poti sa trimiti lumea sa il citeasca. Chestia cu aria dreptunghiurilor nu e explicata si in articolul lui Mircea despre arbori de intervale? Mai bine ii trimiti acolo direct, decat sa le mai prezinti acelasi lucru inca o data. Si acolo parca complexitatea e O(n log n) in total.\r\n\r\n*Stefan:* Articolul de pe Topcoder o sa-l mentionez impreuna cu altele la bibliografie. La complexitatea problemei cu aria dreptunghiurilor ai avut dreptate si este $O(N * log N)$ (am modificat asta in articol). Cat despre articolul cu \'arbori de intervale\':arbori-de-intervale (singurul astfel de articol in romana de care stiu este al doamnei Dana Lica, nu al lui Mircea), acolo este prezentata in detaliu aplicatia cu perimetrul reuniunii de dreptunghiuri, iar cea cu aria este trecuta doar la Probleme propuse. In plus, aplicatia pe care o prezint eu nu vrea sa reproduca pe niciuna din ele, ci este o varianta mult mai simplificata pentru a prezenta tehnica de baleiere. In problema pe care o prezint, un query sau un update vizeaza un singur element dintr-o multime, pe cand in problema generala a ariei dreptunghiurilor, update-ul vizeaza un interval de elemente.\r\n\r\n*Cosmin:* :) da e al doamnei Lica .... perimetrul nu merge in O(n log n) perimetru e O(n log n + nr de segmente de pe perimetru) nu am citit articolul dar tind sa cred ca e prezentata treaba cu aria.',2044,'public',NULL,NULL),('meet-in-the-middle','meet-in-the-middle','2008-03-18 18:33:31','2008-03-18 19:50:21','Others call this split and merge.\r\n\r\n\'Wikipedia\':http://en.wikipedia.org/wiki/Meet-in-the-middle_attack\r\n\r\n\'IOI 2001 Double\':http://olympiads.win.tue.nl/ioi/ioi2001/contest/day2/double/double.pdf\r\n\r\n\'A family of diophantine equations / EQS Baraj ONI 2001\':http://web.mit.edu/~mip/www/probs.html\r\n\r\n\'Problema fotbal (sa se imparta o multime in doua de sume cat mai apropiate) \':http://www.ginfo.ro/revista/14_3/concurs3.pdf\r\n\r\n\'TC LongPipes\':http://www.topcoder.com/stat?c=problem_statement&pm=2226&rd=5851&rm=151088&cr=303185\r\n\r\n\'TC KnapsackProblem\':http://www.topcoder.com/stat?c=problem_statement&pm=6742&rd=10763\r\n\r\n\'TC Knapsack (problema cerea solutia lexicografic minima pentru o problema a rucsacului unde n era maxim  34) \':http://www.topcoder.com/tc?module=Static&d1=match_editorials&d2=srm140\r\n\r\n\'discrete logarithm problem\':http://en.wikipedia.org/wiki/Baby-step_giant-step\r\n\r\n\'UVA 10836\':http://acm.uva.es/p/v108/10836.html\r\n\r\n\'TC SplitAndMergeGame\':http://www.topcoder.com/stat?c=problem_statement&pm=6449\r\n\r\n\'Colectie\':problema/colectie\r\n\r\n\'TC BuildCircuit\':http://www.topcoder.com/stat?c=problem_statement&pm=8510&rd=11124&rm=268752&cr=8362207\r\n\r\n\'UVA 704\':http://acm.uva.es/p/v7/704.html\r\n\r\n\'UVA 11084 Anagram Division\':http://online-judge.uva.es/p/v110/11084.html\r\n\r\n\'UVA 11095 Tabriz City\':http://online-judge.uva.es/p/v110/11095.html',58,'public',NULL,NULL),('aib','Arbori Indexati Binar','2007-12-06 11:47:10','2008-03-19 15:22:53','h1. Arbori Indexati Binar\r\n\r\n(Categoria _Structuri de date_, autor _Giurgea Mihnea_)\r\n\r\n\r\nh2. Abstract - Problema\r\n\r\nAIB-urile sunt o structura de date care implementeaza eficient urmatoarea problema: avem un vector de numere, si vrem sa raspundem la urmatoarele operatii asupra lui: \r\n\r\n# se incremeneaza/ decrementeaza un numar din vector\r\n# care este suma unei anumite subsecvente a vectorului?\r\nPentru un exemplu mai concret, vezi problema \'datorii\':problema/datorii.\r\n\r\nSa ne gandim la cateva posibile solutii: am putea sa implementam usor un algoritm naiv de complexitate O(N), sau cu ceva efort sa folosim \'arborii de intervale\':arbori-de-intervale pentru o complexitate O(logN). In continuare va vom prezenta structura de date numita AIB, usor de implementat si de aceeasi complexitate ca si arborii de intervale. Mai mult, deoarece acestia au constanta mult mai mica decat arborii de intervale, in practica se vor dovedi mult mai rapizi si vor ocupa si mai putina memorie.\r\n\r\nh2. Concret - Cum?\r\n\r\nFie V vectorul de numere care se modifica in timp real. Vom reprezenta AIB-ul folosind un alt vector, pe care il vom denumi, sugestiv, AIB, cu urmatoarea semnificatie:\r\n_AIB[x]_ = suma subsecventei din V cu capetele: _[x - 2^k^ + 1; x]_, unde k = numarul de 0-uri terminale din reprezentarea binara a lui x.\r\n\r\n| Indicele _x_ |1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|\r\n| Inceputul subsecventei asociata lui _AIB[x]_ |1|1|3|1|5|5|7|1|9|9|11|9|13|13|15|1|\r\n\r\nh2. Detalii implementare\r\n\r\nValoarea x - 2^k^ + 1, unde k = numarul de 0-uri terminale se poate calcula foarte usor astfel:\r\n\r\n_#define zeros(x) ( (x ^ (x - 1)) & x )_\r\n\r\nAceast define va calcula valoarea 2^k^ pentru x, unde k = numarul de 0-uri terminale. Pentru a intelege de ce, sa luam cateva exemple:\r\n\r\n| x | 10011000| 11001111|\r\n| x-1 | 10010111| 11001110|\r\n| x ^ (x-1) | 00001111| 00000001|\r\n| (x ^ (x-1)) & x | 00001000 | 00000001|\r\n\r\nFolosind acest define, implementarea operatiilor devine foarte simpla.\r\n\r\n== code(c) | \r\nvoid Add(int x, int quantity)\r\n{\r\n    int i;\r\n\r\n    for (i = x; i <= N; i += zeros(i))\r\n        AIB[i] += quantity;\r\n}\r\n\r\nint Compute(int x)\r\n{\r\n    int i, ret = 0;\r\n\r\n    for (i = x; i > 0; i -= zeros(i))\r\n        ret += AIB[i];\r\n    return ret;\r\n}\r\n\r\n==\r\n\r\nFunctia Add(x, quantity) incrementeaza valoarea lui V[x] cu quantity, care poate fi si negativ pentru a decrementa. Functia Compute(x) calculeaza suma V [1] + V [2] + ... + V [x]. Pentru a calcula suma subsecventei V [L...U] folositi _Compute(U) - Compute(L-1)_.\r\n\r\nComplexitatea in timp a fiecarei operatii este O(logN), pentru ca, in cazul celei de-a doua operatii, la fiecare pas ultimul bit nenul al lui _i_ devine nul, si deci _for_-ul va itera de maxim log x ori. Structura ocupa spatiu O(N), doar vectorul AIB.\r\n\r\nh2. Aplicatii\r\n\r\nSa presupunem ca problema initiala se restrange la a marca/ demarca o pozitie, si ne propunem sa aflam care este cea de a K-a pozitie marcata.\r\n\r\nO prima idee de rezolvare, de complexitate O(log^2^ N), este urmatoarea: cautam binar pozitia, si la fiecare pas, pentru a compara pozitia curenta _i_ cu solutia, calculam in O(logN) functia _cnt(i) :=_ suma elementelor de pe pozitiile 1...i; _cnt(i)_ reprezinta de fapt numarul de numere intre 1 si i, pe care il comparam cu K pentru a stii cum facem urmatorul pas. \r\n\r\nA doua idee de rezolvare, de complexitate O(logN) se poate realiza optimizand prima idee. Folosim \'cautarea binara a lui Patrascu\':http://infoarena.ro/multe-smenuri-de-programare-in-cc-si-nu-numai si urmatoarea observatie: cnt(8+4) = cnt(8) + AIB[8+4], cnt(16+4) = cnt(16) + AIB[16+4], etc. Daca ne uitam la cum functioneaza functia Compute(int x), putem generaliza astfel: cnt(x) = cnt(x - zeros(x)) + AIB[x]. Implementarea propriu-zisa o lasam ca tema pentru cititor, impreuna cu problema gasirii celui de-al K-lea numar dintr-un AIB oarecare, pornind de la ideea de mai sus.\r\n\r\nAIB-urile se pot extinde usor la cazul multidimensional, si lasam aceasta implementare ca tema pentru cititor. De asemenea, incercati sa rezolvati urmatoarele probleme de pe infoarena:\r\n1. \'Datorii\':problema/datorii\r\n2. \'Ben\':problema/ben\r\n3. \'Evantai\':problema/evantai\r\n4. \'Schi\':problema/schi\r\n\r\n\r\n\r\nPentru o lectura mai profunda in acest domeniu, va recomand \'acest articol de pe TopCoder\':http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=binaryIndexedTrees.\r\n\r\n\r\n\r\n',5,'public',NULL,NULL),('blog/jake-jarvis-si-aplicatia-lui-de-facebook','Jake Jarvis si aplicatia lui de Facebook','2008-03-19 16:19:51','2008-11-16 12:48:56','Toata lumea a auzit de \'Mark Zuckerberg\':http://en.wikipedia.org/wiki/Mark_Zuckerberg, studentul care a renuntat la Harvard pentru a se ocupa de \'site-ul pe care il lansase\':http://www.facebook.com/ (si care s-a imbogatit, cu ocazia asta).\r\n\r\nMai interesant pentru elevii pasionati de informatica mi se pare totusi exemplul lui Jake Jarvis, un pusti de 16 ani care a programat o aplicatie care se integreaza cu Facebook si a vandut-o pe o suma consistenta. Majoritatea romanilor au acum la dispozitie resursele pe care le-a avut el. E mult mai usor sa faci lucruri importante decat cu cativa ani in urma, iar cunostintele programare si algoritmi va ofera ocazia de a va face cunoscuti chiar inainte de a atinge varsta majoratului. Va dati seama?\r\n\r\n==YoutubeVideo(id=\"1yAUweG0Qgc\" width=\"437\" height=\"370\")==\r\n\r\n*Tiberiu Florea* - \'greco.ro\':http://www.greco.ro',1851,'public',2895,NULL),('utilizator/stelistul','Profil stelistul','2008-05-04 17:43:51','2008-05-04 17:43:51','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',8181,'public',NULL,NULL),('sisteme-de-ecuatii','Sisteme de ecuatii','2008-03-19 10:26:37','2008-03-19 23:11:51','Teorie:\r\n\'Gaussian elimination\':http://en.wikipedia.org/wiki/Gaussian_elimination\r\n\'Row echelon form\':http://en.wikipedia.org/wiki/Row_echelon_form\r\n\r\nProbleme:\r\n\'SGU 275 To xor or not to xor\':http://acm.sgu.ru/problem.php?contest=0&problem=275\r\n\'.campion Xor\':http://campion.edu.ro/problems/3/323/xor_ro.htm\r\n\'SGU 260 Puzzle\':http://acm.sgu.ru/problem.php?contest=0&problem=260\r\n\'UVA 10808\':http://online-judge.uva.es/p/v108/10808.html\r\n\'UVA 326\':http://online-judge.uva.es/p/v3/326.html\r\n\'UVA 10014\':http://online-judge.uva.es/p/v100/10014.html\r\n\'BColor\':problema/bcolor\r\n\'Laser\':problema/laser\r\n\'TC XORing\':http://www.topcoder.com/stat?c=problem_statement&pm=4829&rd=8095&rm=246636&cr=270505\r\n\'TC Escape the jail\':http://www.topcoder.com/stat?c=problem_statement&pm=7353\r\n\'Register CEOI 2003\':http://ceoi.inf.elte.hu/probarch/03/register-en.pdf\r\n\'Tunelul groazei\':problema/tunel\r\n\'SGU 200\':http://acm.sgu.ru/problem.php?contest=0&problem=200\r\n\'TC CoinGame\':http://www.topcoder.com/stat?c=problem_statement&pm=6005',1,'public',NULL,NULL),('planificare/sedinta-20080314','Sedinta 2008-03-14','2008-03-11 10:45:21','2008-03-20 21:17:37','h1. Sedinta 2008-03-14\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *vineri* la ora *18:00* la \'*ICHB*\':http://www.ichb.ro\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")== ---> Sorry, nu mai vin (am obosit si mi s-a facut foame de la dat gauri).\r\n* ==user(user=\"wefgef\" type=\"tiny\")== ---> nu mai pot veni, sunt prea racit\r\n* ==user(user=\"wickedman\" type=\"tiny\")== ---> am laborator pana la 18:00.  Incepeti va rog fara mine.\r\n* ==user(user=\"svalentin\" type=\"tiny\")== ---> nu am venit, aveam impresia ca este luni\r\n* _&hellip; asteptam confirmari_\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioara\':planificare/sedinta-20080303 pentru ce e legate de preONI 2008\r\n* preONI 2008 update\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Mircea face pagina de runda finala %{color:red}(\'done\':preoni-2008/runda-finala)% \r\n* Vali gaseste shop de imprimat diplome si le imprima (probabil 60 buc; telefoneaza pentru confirmare).\r\n* Silviu vorbeste cu Ali despre microbuze. Avem nevoie de microbuze de la gara la P19 (vineri seara), sambata sau duminica pentru excursie la Casa Poporului si eventual duminica la plecare. %{color:red}(done)% *Update(Silviu):* Trebuie sa venim cu lista sosirilor si cu ora cand vrem microbuze pentru mini-excursie. Abia atunci poate sa ne spuna daca sunt microbuze cand ne trebuie noua. Problema de fapt e vineri, cand se lucreaza.\r\n* Silviu vorbeste cu Tapus despre calculatoare si set-up. In functie de ce zice Tapus o sa facem un hei-rup sa instalam tot ce trebuie. %{color:red}(done)% *Update(Silviu):* Desi nu ne place, a ramas ca facem mare parte din treaba vineri undeva dupa ora 18:00. Ne trebuie oameni cati mai multi la prasit so feel free to join us.\r\n* Silviu && (Cristi || Mircea) vorbesc cu Dl. Zaharia pentru programul de masa. %{color:red}(done)% *Update(Silviu):* Am vb cu dumnealui la telefon. Am stabilit ore pentru mese (programul e la Cristi). Din cate am inteles, o sa ne dea mancare de 25 RON/zi de om -- sper sa iasa decent. Putem modifica orele de masa la nevoie (trebuie sa anuntam).\r\n*Update(Cristi):* Am scris programul pe site; Dupa o discutie cu Silviu am tras concluzia ca ar fi indicat sa optimizam numarul de locuri de masa - la unele mese vor fi mult mai putin de 55 de oameni.\r\n* Silviu vorbeste cu Ali ca nu se mai face concurs in laboratoarele & cantina ICHB. Vali a spus ca Ali crede ca facem concursul la ei. %{color:red}(done)% \r\n* Cristi scoate banii cash necesari din banca si ii da lui Mircea. %{color:red}(done)%\r\n*Update(Cristi):* Am scos 4000 cash pentru premii si am pus 6000 pe card pentru alte cheltuieli. Atentie! Avem limita zilnica de ~3000+ lei la extragerile de pe card.\r\n* Mircea intretine lista de cheltuieli pentru finala preONI. %{color:red}(done)%\r\n* Cristi se intalneste cu furnizorul de tricouri si le ridica (joi). %{color:red}(done)%\r\n*Update(Cristi):* Tricourile sunt purtabile dar nu sunt foarte ok. Vom avea probleme la marimi (sunt prea mari!) si sigla de pe fata are un fel de aura verde imprejur. Am cerut inca 50 tricouri de dimensiuni mai mici in regim de urgenta si vor fi gata undeva sambata. Putem sa dam la oameni tricouri mari si sa le schimbam dupa aceea cu unele mai mici.\r\n* Cristi plateste si a doua transa din factura de tricouri. %{color:red}(done)%\r\n* (Cristi || Mircea) merg la P19 sa intrebe despre sosirea participantilor. Cine ii cazeaza in camere?\r\n*Update(Cristi):* D-na Ilona a spus ca exista un administrator la camin intotdeauna. In plus, putem sa cazam participantii si mai de dimineata, nu neaparat dupa 12. Tot administratorul de camin ne va face si factura.\r\n* (Cristi || Silviu) fac rost de cheia de la Sala Senatului pentru vineri seara si pentru duminica + afla daca avem proiector in Sala Senatului. O secretara a spus ca trebuie sa cerem cheia dinainte. %{color:red}(done)% *Update(Silviu):* Am vb cu Bogdan Cavescu si Corneliu Chira (responsabili cu sala). Cred ca suntem acoperiti aici (avem si numar de telefon -- ask me).\r\n* Cristi vorbeste cu Adobe si iRealSoft despre materialele lor promotionale. %{color:red}(done)% Mircea vorbeste cu MS. \r\n*Update(Cristi):* iRealSoft a spus ca nu poate veni la finala. Adobe va aduce vineri pe la ora 17 niste materiale promotionale (banner-e stand-up si posibil badge-uri);  In plus, Adobe ofera pix si notebook de matematica la elevi in ziua concursului.\r\n* Mircea trimite email la MS cu invitatie la finala. (Adobe si iRealSoft au primit deja) %{color:red}(done)%\r\n* Mircea se asigura ca Buru, Pasa, Astronomy stiu ca sunt invitati la finala. %{color:red}(done)%\r\n* Program _surpriza_ %{color:red}(done)%\r\n*Update(Cristi):* Alexandru Dimofte organizeaza o iesire la film sambata dupa cina. A ales un film, a facut o rezervare de 45 de locuri; Sambata trebuie sa strangem carnete de elevi / studenti si sa i le dam lui Andu ca sa cumpere bilete. Iesim la film la Plazza pe la ora 20 (Silviu trebuie sa ne spuna daca face rost de microbuz) si ne intoarcem pe la 22-23 cu RATB :P\r\n\r\n\r\nh2. Notite\r\n\r\n* *Avem nevoie de voluntari pentru intampinat concurentii la gara.* Alexandra colecteaza datele despre sosiri si poate sa vina partial vineri sa ii intampine pe concurenti la gara.\r\n* Am putea redacta un comunicat de presa\r\n* Invitati special la finala:  Ecaterina, Tapus, *alte sugestii?*\r\n* Trebuie sa hotaram daca facem excursie in Bucuresti sambata sau duminica. Alexandru Dimofte s-a oferit sa faca pe ghidul dar trebuie sa-i spunem exact cand si in ce fel.\r\n* Trebuie sa hotaram daca facem party ca in 2006 sau un gratar ca in 2007. (ambele :D, adica un grataro-party)\r\n',13,'public',NULL,NULL),('utilizator/chryss13','Profil chryss13','2008-03-21 02:32:31','2008-03-21 02:32:31','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',7954,'public',NULL,NULL),('preoni-2008/runda-finala/program','preONI 2008, Runda Finala - Program de desfasurare','2008-03-14 15:20:05','2008-03-21 07:53:45','==Include(page=\"template/preoni-2008\")==\r\n\r\nh1. preONI 2008, Runda Finala - Program de desfasurare\r\n\r\n(htabs)* \'Despre&hellip;\':preoni-2008/runda-finala\r\n*(active) \'Program\':preoni-2008/runda-finala/program\r\n* \'Regulament\':preoni-2008/runda-finala/regulament\r\n* \'Probleme\':preoni-2008/runda-finala/probleme\r\n* \'Rezultate\':preoni-2008/clasament/runda-finala/5-8\r\n\r\nProgramul de mai jos este deschis la sugestii si se poate modifica pe parcursul desfasurarii concursului.\r\n\r\ntable{width:75%}. |_. Data |_. Activitati |\r\n| Vineri, 21 martie 2008 | * 12:00 - 18:00 Sosire si cazare participanti la caminul *P19* din \'Universitatea Politehnica Bucuresti\':http://www.upb.ro/\r\n* 13:00 - 14:00 Pranz\r\n* 18:00 - 19:00 Deschidere oficiala\r\n* 19:00 - 20:00 Cina |\r\n| Sambata, 22 martie 2008 | * 08:00 - 09:00 Mic dejun\r\n* 09:00 - 09:30 Acomodare, testarea statiilor de lucru \r\n* *09:30 - 14:30 Proba de concurs*\r\n* 15:00 - 16:00 Pranz\r\n* 18:00 - 20:00 Cina\r\n* 20:00 - 22:00 Program surpriza | \r\n| Duminica, 23 martie 2008 | * 08:00 - 09:00 Mic dejun\r\n* 09:00 - 09:30 Evaluare live \r\n* 09:30 - 10:30 Consultare borderouri evaluare, contestatii\r\n* 11:00 - 12:00 Festivitatea de premiere\r\n* 13:00 - 14:00 Pranz\r\n* 19:00 - 20:00 Cina\r\n* Plecare |\r\n\r\nFestivitatea de deschidere si cea de premiere vor avea loc in Sala Senatului din cladirea rectoratului Universitatii Politehnice Bucuresti (Splaiul Independentei Nr. 313). Prezenta la festivitatea de deschidere este obligatorie.\r\n\r\nMasa se serveste in cantina rectoratului - etajul 5 din cladirea rectoratului UPB.\r\n\r\nConcurentii din afara Municipiului Bucuresti vor fi cazati in caminul P19 al UPB aflat pe Splaiul Independentei Nr. 290.\r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',13,'protected',NULL,NULL),('blog/preoni-2008-concursul-si-premierea','PreONI 2008: Concursul si premierea','2008-03-23 12:09:12','2008-11-15 13:41:14','Sambata a fost ziua centrala a finalei PreONI 2008, deoarece concurentii au avut la dispozitie 5 ore ca sa rezolve problemele si sa-si adjudece premiile puse in joc. Dupa o scurta intarziere, au urmat 5 ore de gandire si implementare, cu emotiile aferente, dar cu mai putine griji decat la o Olimpiada Nationala.\r\n\r\nSeturile de probleme au fost:\r\n\r\n* *la gimnaziu*: \'Oz\':problema/oz, \'Sandokan\':problema/sandokan si \'Marbles\':problema/marbles\r\n* *la clasa a IX-a*: \'Sandokan\':problema/sandokan, \'Peste\':problema/peste si \'Progresii\':problema/progresii\r\n* *la clasa a X-a*: \'Wanted\':problema/wanted, \'Sortare\':problema/sortare si \'Peste\':problema/peste\r\n* *la clasele XI-XII*: \'Vanatoare\':problema/vanatoare, \'Sortare\':problema/sortare si \'Talharie\':problema/talharie\r\n\r\nAutorii sunt \'Filip Buruiana\':utilizator/filipb, \'Adrian Airinei\':utilizator/astronomy, \'Adrian Diaconu\':utilizator/DITzoneC, \'Mircea Pasoi\':utilizator/domino si \'Andrei Grigorean\':utilizator/wefgef.\r\n\r\nDupa concurs, participantii si comisia au mers in Plaza Romania pentru a vedea filmul _Step Up 2_, intr-o pauza de relaxare si socializare.\r\n\r\nZiua de duminica a inceput cu evaluarea LIVE, spectaculoasa de obicei. La ora 11, \'Cristi\':utilizator/wickedman a anuntat finalul concursului de anul acesta, constatand ca nu exista contestatii sau alte tipuri de reclamatii din partea concurentilor. In numele infoarena, UPB si Adobe Romania, a transmis tuturor celor de fata ca organizarea evenimentului a fost o placere pentru noi toti, deoarece ne bucura sa dam ocazia elevilor pasionati de informatica sa se distreze si sa faca ceea ce stiu cel mai bine. Toata lumea a primit felicitari pentru prestatia avuta; se stie ca simpla calificare in finala PreONI e o realizare in sine.\r\n\r\n\'Mircea\':utilizator/domino a prezentat membrii infoarena care si-au adus contributia la aceasta finala, si i-a premiat cu prima cana personalizata cu insemnele concursului PreONI. Apoi a trecut la anuntarea si premierea celor mai bine clasati concurenti.\r\n\r\n* gimnaziu\r\n** *premiul I*: Cezar Mocan\r\n** *premiul II*: Radu Stefan Voroneanu\r\n** *premiul III*: Andrei Purice\r\n\r\n* clasa a IX-a\r\n** *premiul I*: Ioana Pandele\r\n** *premiul II*: Alexandru Tache\r\n** *premiul III*: Bogdan Bazu\r\n\r\n* clasa a X-a\r\n** *premiul I*: Bogdan Tataroiu (cu singurul scor perfect - 300 de puncte)\r\n** *premiul II*: Istvan Hevele\r\n** *premiul III*: Bogdan Casu-Pop\r\n\r\n* clasele XI-XII\r\n** *premiul I*: Cosmin Gheorghe\r\n** *premiul II*: Alexandru Tandrau\r\n** *premiul III*: Paul-Dan Baltescu\r\n\r\nToata lumea a primit diplome de participare, iar finala s-a terminat cu o poza de grup si un concert la pian al invitatului special, Maricel Mihalcea. Speram ca v-ati simtit bine la PreONI 2008, si ca ne vom reintalni la anul pentru o noua finala!\r\n\r\n\'_Pozele facute de Sergiu Strat_\':http://picasaweb.google.com/nevrax/PreONI2008\r\n\'_Pozele facute de Valentin Stanciu_\':http://picasaweb.google.com/valentin.stanciu/PreONI2008\r\n\'_Pozele facute de Mircea Pasoi_\':http://picasaweb.google.com/mircea.pasoi/PozePreONI2008\r\n\r\n*Tiberiu Florea* - \'greco.ro\':http://www.greco.ro',1490,'protected',2923,NULL),('blog/finala-preoni-2008','Finala preONI 2008','2008-03-24 23:07:05','2008-03-25 09:18:23','h1. Finala preONI 2008\r\n\r\nIn perioada *21-23 martie 2008* s-a desfasurat \'runda finala\':preoni-2008/runda-finala a concursului \'*preONI 2008*\':preoni-2008. Poti afla mai multe despre cum s-a desfasurat pe \'blog\':blog:\r\n\r\n* \'preONI 2008 - Deschiderea\':blog/preoni-2008-deschiderea\r\n* \'preONI 2008 - Concursul si premierea\':blog/preoni-2008-concursul-si-premierea\r\n\r\nTot acolo puteti gasi si poze de la acest eveniment.',13,'protected',NULL,NULL),('preoni-2008/runda-finala/solutii','Solutii preONI 2008, Runda finala','2008-03-25 09:21:25','2008-03-25 11:16:54','==include(page=\"template/preoni-2008/header\")==\r\n\r\nh1. Solutii preONI 2008, Runda finala\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Oz\':preoni-2008/runda-finala/solutii#oz\r\n* \'Marbles\':preoni-2008/runda-finala/solutii#marbles\r\n* \'Sandokan\':preoni-2008/runda-finala/solutii#sandokan\r\n* \'Progresii\':preoni-2008/runda-finala/solutii#progresii\r\n* \'Peste\':preoni-2008/runda-finala/solutii#peste\r\n* \'Wanted\':preoni-2008/runda-finala/solutii#wanted\r\n* \'Sortare\':preoni-2008/runda-finala/solutii#sortare\r\n* \'Vanatoare\':preoni-2008/runda-finala/solutii#vanatoare\r\n* \'Talharie\':preoni-2008/runda-finala/solutii#talharie\r\n\r\n==include(page=\"preoni-2008/runda-finala/solutii/oz\")==\r\n\r\n==include(page=\"preoni-2008/runda-finala/solutii/marbles\")==\r\n\r\n==include(page=\"preoni-2008/runda-finala/solutii/sandokan\")==\r\n\r\n==include(page=\"preoni-2008/runda-finala/solutii/progresii\")==\r\n\r\n==include(page=\"preoni-2008/runda-finala/solutii/peste\")==\r\n\r\n==include(page=\"preoni-2008/runda-finala/solutii/wanted\")==\r\n\r\n==include(page=\"preoni-2008/runda-finala/solutii/sortare\")==\r\n\r\n==include(page=\"preoni-2008/runda-finala/solutii/vanatoare\")==\r\n\r\n==include(page=\"preoni-2008/runda-finala/solutii/talharie\")==\r\n',1,'public',NULL,NULL),('preoni-2008/runda-finala/solutii/oz','preoni-2008/runda-finala/solutii/oz','2008-03-25 09:22:40','2008-03-25 10:03:55','h2(#oz). \'Oz\':problema/oz\r\n\r\nFie $v$ vectorul de $N$ numere care reprezinta solutia problemei. Initial consideram toate elementele vectorului $v$ ca fiind egale cu {$1$}. In momentul in care intalnim o pereche de forma ({$i j d$}), facem urmatoarele transformari:\r\n\r\n* {$v{~i~}$} devine {$cmmmc(v{~i~}, d)$}\r\n* {$v{~j~}$} devine {$cmmmc(v{~j~}, d)$},\r\n\r\nunde prin {$cmmmc(a, b)$} se noteaza cel mai mic multiplu comun al numerelor $a$ si {$b$}.\r\nAcest lucru garanteaza ca atat {$v{~i~}$} cat si {$v{~j~}$} se divid prin {$d$}, si ca toate relatiile anterioare sunt respectate. In plus, deoarece alegem cel mai mic multiplu comun, stim sigur ca solutia pe care o obtinem va fi minim posibila. Este insa posibil ca cele $M$ relatii date sa fie contradictorii. De exemplu, pentru {$N = 3$} si relatiile ({$1,2,3$}), ({$2,3,6$}) si ({$1,3,1$}) nu vom avea solutie, deoarece din primele doua relatii stim sigur ca atat {$v{~1~}$} cat si {$v{~3~}$} sunt divizibile cu 3, in timp ce ultima relatie cere ca cele doua numere sa fie prime intre ele. Pentru a verifica daca intr-adevar problema are solutie este suficient, dupa ce obtinem vectorul $v$ prin procedeul de mai sus, aplicand transformarile corespunzatoare tuturor celor $M$ relatii, sa testam pentru fiecare triplet ({$i j d$}) daca intr-adevar cel mai mare divizor comun dintre {$v{~i~}$} si {$v{~j~}$} este {$d$}, in caz contrar neexistand solutie.\r\nPentru a calcula {$cmmmc(a, b)$} se foloseste relatia {$cmmmc(a, b)$} = {$a * b / cmmdc(a, b)$}, iar {$cmmdc(a, b)$} se va calcula optim folosind \'Algoritmul lui Euclid\':problema/euclid2.',256,'public',NULL,NULL),('preoni-2008/runda-finala/solutii/sandokan','preoni-2008/runda-finala/solutii/sandokan','2008-03-25 09:23:16','2008-04-06 15:16:26','h2(#sandokan). \'Sandokan\':problema/sandokan\r\n\r\nObservam ca elementul maxim din sir va ramane tot timpul in configuratia finala. Datorita acestul fapt, la fiecare pas putem alege elementul maxim impreuna cu alte $K-1$ elemente pe care le vom elimina. Deci daca configuratia finala contine $P$ elemente, unul din cele $P$ elemente este elementul maxim, iar restul de $P-1$ le putem alege in toate modurile posibile. Raspunsul la problema noastra este $Combinari(N-1, P-1)$. Ca detaliu de implementare, puteam folosi recurenta $C[n][k] = C[n-1][k-1]+C[n-1][k]$, obtinand complexitate $O(N^2^)$ ca timp si memorie $O(N)$ (avem nevoie doar de ultimele doua linii din matrice). O alta varianta ar fi fost sa plecam de la faptul ca <tex>C(n,k) = \\frac{n!}{(n-k)!*k!} = \\frac{(n-k+1)*(n-k+2)*...*n}^{k!}</tex>. Putem itera $k$ de la $1$ la $P-1$ si fiecare termen de forma $n-k+i$ il vom imparti atat pe el cat si pe $k$ la $cmmdc(k, n-k+i)$. La sfarsit va trebui doar sa inmultim valorile care au ramas la numarator.\r\n',2044,'public',NULL,NULL),('preoni-2008/runda-finala/solutii/wanted','preoni-2008/runda-finala/solutii/wanted','2008-03-25 09:24:18','2008-03-30 20:54:12','h2(#wanted). \'Wanted\':problema/wanted\r\n\r\nProblema se va rezolva folosind programare dinamica. Vom considera satele sortate dupa ordonata {$X$}. Vom construi matricile\r\n\r\n* {$A{~i,j~}$} - distanta minima parcursa pentru a rezolva intervalul {$i...j$} si daca ne-am afla initial in satul {$i-1$}\r\n* {$B{~i,j~}$} - distanta minima parcursa pentru a rezolva intervalul {$i...j$} si daca ne-am afla initial in satul {$j+1$}\r\n\r\nRelatia de recurenta se poate observa usor. Fixam pe rand fiecare sat {$k$} pe care il vom vizita prima oara si ne uitam la {$A{~k+1,j~}$} si {$B{~i,k-1~}$}, alegand maximul dintre cele doua (luam in coniderare doar cazul cel mai defavorabil). Dintre toate posibilitatile de a alege {$k$} o vom retine pe cea care da rezultatul minim.\r\n\r\nPentru a stabili rezultatul fixam din nou {$k$}, primul sat vizitat si alegem minimul dintre toate posibilitatile.\r\n\r\nComplexitatea algoritmului va fi {$O(n^3^)$}.',961,'public',NULL,NULL),('preoni-2008/runda-finala/solutii/talharie','preoni-2008/runda-finala/solutii/talharie','2008-03-25 09:25:34','2008-04-05 13:44:38','h2(#talharie). \'Talharie\':problema/talharie\r\n\r\nVom numerota caracterele din sir de la $0$ la $N-1$. Vom identifica o rotatie a sirului prin indecele asociat caracterului cu care respectiva rotatie incepe. Notand cu $D$ cel mai mare divizor comun al numerelor $N$ si $K$, putem demonstra folosind notiuni elementare de teoria numerelor ca toate rotatiile pe care le putem obtine efectuand operatia descrisa in enunt sunt multiplii ai lui $D$. Folosindu-ne de faptul ca diferenta intre oricare doua rotatii consecutive care ne intereseaza este constanta, putem foarte usor sa modificam cei doi algorimti prezentati in \'articolul\':rotatie-lexicografic-minima scris de Mircea Pasoi. Pentru a obtine 100 de puncte, era suficienta implementarea algoritmului de complexitate $O(N * log N)$.',2028,'public',NULL,NULL),('preoni-2008/runda-finala/solutii/marbles','preoni-2008/runda-finala/solutii/marbles','2008-03-25 09:22:58','2008-03-25 10:20:49','h2(#marbles). \'Marbles\':problema/marbles\r\n\r\nDatorita modului in care sunt mutate bilele, ordinea relativa a acestora nu se va schimba pe parcursul efectuarii operatiilor, deci ordinea culorilor va ramane neschimbata. Initial sortam bilele din fisierul de intrare dupa coordonata lor, si calculam un tablou de sume partiale {$S$}, unde {$S{~c,i~}$} va reprezenta numarul de aparitii ale culorii $c$ in primele $i$ bile din lista sortata. La fiecare pas vom avea un vector de coordonate $x$ = ({$x{~1~}$}, {$x{~2~}$},... , {$x{~N~}$}), care, conform observatiei de mai sus, va ramane intotdeauna sortat crescator. Astfel, putem realiza operatia de mutare a unei bile in complexitatea {$O(log{~2~}N)$}, cautand binar pozitia in vectorul $x$ pe care apare bila care trebuie mutata, si modificand aceasta valoare. Daca dorim sa aflam care este numarul maxim de bile de aceeasi culoare din intervalul [{$i, j$}] este suficient sa cautam binar valorile {$a$} si {$b$}, unde $a$ este cel mai mic numar natural astfel incat {$i &le; x{~a~}$}, iar $b$ este cel mai mare numar natural astfel incat {$x{~b~} &le; j$}. Astfel, toate bilele intre pozitiile $a$ si $b$ inclusiv vor avea coordonata in intervalul [{$i, j$}]. Iteram fiecare culoare $C$ de la $1$ la $64$ si afisam maximul valorilor de forma {$S{~C,b~}-S{~C,a-1~}$}, care reprezinta chiar numarul de aparitii ale culorii $C$ intre pozitiile $a$ si {$b$}.\r\nComplexitatea algoritmului de mai sus va fi {$O(Nlog{~2~}N + N*C + Mlog{~2~}N + M*C)$}. Aceasta solutie obtine punctajul maxim.',256,'public',NULL,NULL),('preoni-2008/runda-finala/solutii/vanatoare','preoni-2008/runda-finala/solutii/vanatoare','2008-03-25 09:25:12','2008-03-25 11:23:26','h2(#vanatoare). \'Vanatoare\':problema/vanatoare\r\n\r\nProblema se rezolva cu ajutorul programarii dinamice. Sa notam cu {$M{~i~}$} multimea {$j$ | al {$j$}-lea bit din reprezentarea lui $i$ in baza $2$ este {$1$}}. Fie {$D{~i~}$} numarul minim de vanatori necesari pentru a omori toti mistretii cu numere de ordine din multimea $M{~i~}$. Relatia de recurenta va fi {$D{~i~}$} = {$1 + minim(D{~M{~i~}-M{~j~}~})$}, dupa toate numerele $j$ cu proprietatea ca multimea {$M{~j~}$} este inclusa in multimea {$M{~i~}$} si toti mistretii din {$M{~j~}$} pot fi omorati de acelasi vanator, situat la o coordonata intre $0$ si {$T$}. Pentru a stabili daca toti mistretii din {$M{~j~}$} pot fi omorati de acelasi vanator, vom realiza o preprocesare. Astfel, {$A{~i~}$} va fi $true$ daca si numai daca putem plasa un vanator intre $0$ si $T$ care sa omoare toti mistretii din {$M{~i~}$}. O optimizare evidenta care imbunatateste cu mult timpul de executie este ca pentru o stare $i$ sa eliminam acele $j$ despre care stim sigur ca {$A{~j~}$} va fi {$false$}. Astfel, daca la un moment dat alegem un numar $j$ pentru care {$A{~j~}$} va fi {$false$} nu are rost sa consideram nici un numar $k$, pentru care {$M{~j~}$} inclus in {$M{~k~}$}, pentru ca {$A{~k~}$} va fi sigur {$false$}.\r\nPentru a calcula valoarea lui $A{~i~}$ trebuie sa determinam cel mai mic numar natural $P$ (daca exista) astfel incat vanatorul plasat in $P$ sa poata omori toti mistretii din $M{~i~}$. Aceasta relatie este echivalenta cu P % v{~j~} = c{~j~}, pentru orice $j$ inclus in {$M{~i~}$}. Pentru a afla numarul $P$ pentru o stare $i$ putem folosi \'teorema chineza a resturilor\':teorema-chineza-a-resturilor. Nu este necesar insa sa aplicam aceasta teorema de la inceput pentru fiecare stare, ci este suficient sa vedem care este ultimul bit $j$ de $1$ din $i$, si sa combinam solutia pentru {$M{~i~}-{j}$} si {${j}$}. A{~i~} va fi $true$ daca si numai daca {$0 &le; P &le; T$}.\r\nComplexitatea finala va fi {$O(2^N^ * N)$} + {$O(3^N^)$} = {$O(3^N^)$}.',1,'public',NULL,NULL),('hash','hash','2008-03-28 16:38:33','2008-12-13 08:12:44','Download \'aici\':http://infoarena.ro/hash?action=download&file=hash.zip\r\nDownload \'aici2\':http://infoarena.ro/hash?action=download&file=HASH.OUT',2092,'public',NULL,NULL),('grigore-moisil-2008/5-6','Grigore Moisil 2008, Clasele 5-6','2008-03-31 06:35:47','2008-04-05 12:35:27','==Include(page=\"template/grigore-moisil-2008\")==\r\n\r\nh1. Grigore Moisil 2008\r\n\r\n(htabs)* \'Despre concurs\':grigore-moisil-2008/\r\n* \'Clasament\':grigore-moisil-2008/clasament/5-6\r\n\r\nh2. Clasele 5-6\r\n\r\nConcursul se va desfasura *Duminica, 6 aprilie*, la ora {*10^00^*} si va dura *3h*. Participantii vor avea de rezolvat doua probleme de natura algoritmica.\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2008-5-6\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2008-5-6\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':grigore-moisil-2008/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"moisil2008-5-6\" score=\"1\")==\r\n\r\nh2. Clasament\r\n\r\n\'Evaluatorul\':documentatie/evaluator va fi oprit pe toata perioada desfasurarii concursului. Dupa terminarea rundei de concurs va incepe evaluarea in timp real. Rezultatele finale le puteti gasi \'aici\':grigore-moisil-2008/clasament.\r\n',256,'round: moisil2008-5-6',NULL,NULL),('template/grigore-moisil-2008','template/grigore-moisil-2008','2008-03-31 15:59:13','2008-11-16 12:14:13','!grigore-moisil-2008?moisil.jpg 80%!:/grigore-moisil-2008\r\n\r\n\r\n(vmenu)*(section) \'*Informatii generale*\':grigore-moisil-2008\r\n* \'Clasament\':grigore-moisil-2008/clasament/5-6\r\n* &nbsp;\r\n* Grupe de varsta\r\n* \'Clasele 5-6\':grigore-moisil-2008/5-6\r\n* \'Clasele 7-8\':grigore-moisil-2008/7-8\r\n* \'Clasa a 9-a\':grigore-moisil-2008/9\r\n* \'Clasa a 10-a\':grigore-moisil-2008/10\r\n* \'Clasele 11-12\':grigore-moisil-2008/11-12',2028,'protected',NULL,NULL),('runda/moisil2008-5-6','moisil2008-5-6','2008-03-31 16:20:13','2008-03-31 16:20:13','h1. == roundparam(round_id=\"moisil2008-5-6\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"moisil2008-5-6\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2008-5-6\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2008-5-6\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':moisil2008-5-6/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"moisil2008-5-6\" score=\"1\")==',256,'round: moisil2008-5-6',NULL,NULL),('runda/moisil2008-5-6/clasament','Clasament moisil2008-5-6','2008-03-31 16:20:13','2008-03-31 16:20:13','h1. Clasament ==roundparam(round_id=\"moisil2008-5-6\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil2008-5-6\")==',256,'round: moisil2008-5-6',NULL,NULL),('grigore-moisil-2008/7-8','Grigore Moisil 2008, Clasele 7-8','2008-03-31 16:34:15','2008-04-05 23:34:18','==Include(page=\"template/grigore-moisil-2008\")==\r\n\r\nh1. Grigore Moisil 2008\r\n\r\n(htabs)* \'Despre concurs\':grigore-moisil-2008/\r\n* \'Clasament\':grigore-moisil-2008/clasament/7-8\r\n\r\nh2. Clasele 7-8\r\n\r\nConcursul se va desfasura *Duminica, 6 aprilie*, la ora {*10^00^*} si va dura *3h*. Participantii vor avea de rezolvat doua probleme de natura algoritmica.\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2008-7-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2008-7-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':grigore-moisil-2008/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"moisil2008-7-8\" score=\"1\")==\r\n\r\nh2. Clasament\r\n\r\n\'Evaluatorul\':documentatie/evaluator va fi oprit pe toata perioada desfasurarii concursului. Dupa terminarea rundei de concurs va incepe evaluarea in timp real. Rezultatele finale le puteti gasi \'aici\':grigore-moisil-2008/clasament.\r\n',2028,'round: moisil2008-7-8',NULL,NULL),('runda/moisil2008-7-8','moisil2008-7-8','2008-03-31 16:35:14','2008-03-31 16:35:14','h1. == roundparam(round_id=\"moisil2008-7-8\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"moisil2008-7-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2008-7-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2008-7-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':moisil2008-7-8/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"moisil2008-7-8\" score=\"1\")==',256,'round: moisil2008-7-8',NULL,NULL),('runda/moisil2008-7-8/clasament','Clasament moisil2008-7-8','2008-03-31 16:35:14','2008-03-31 16:35:14','h1. Clasament ==roundparam(round_id=\"moisil2008-7-8\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil2008-7-8\")==',256,'round: moisil2008-7-8',NULL,NULL),('runda/moisil2008-9','moisil2008-9','2008-03-31 16:37:31','2008-03-31 16:37:31','h1. == roundparam(round_id=\"moisil2008-9\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"moisil2008-9\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2008-9\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2008-9\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':moisil2008-9/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"moisil2008-9\" score=\"1\")==',256,'round: moisil2008-9',NULL,NULL),('runda/moisil2008-9/clasament','Clasament moisil2008-9','2008-03-31 16:37:31','2008-03-31 16:37:31','h1. Clasament ==roundparam(round_id=\"moisil2008-9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil2008-9\")==',256,'round: moisil2008-9',NULL,NULL),('runda/moisil2008-10','moisil2008-10','2008-03-31 16:38:22','2008-03-31 16:38:22','h1. == roundparam(round_id=\"moisil2008-10\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"moisil2008-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2008-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2008-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':moisil2008-10/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"moisil2008-10\" score=\"1\")==',256,'round: moisil2008-10',NULL,NULL),('runda/moisil2008-10/clasament','Clasament moisil2008-10','2008-03-31 16:38:22','2008-03-31 16:38:22','h1. Clasament ==roundparam(round_id=\"moisil2008-10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil2008-10\")==',256,'round: moisil2008-10',NULL,NULL),('runda/moisil2008-11-12','moisil2008-11-12','2008-03-31 16:39:20','2008-03-31 16:39:20','h1. == roundparam(round_id=\"moisil2008-11-12\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"moisil2008-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2008-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2008-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':moisil2008-11-12/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"moisil2008-11-12\" score=\"1\")==',256,'round: moisil2008-11-12',NULL,NULL),('runda/moisil2008-11-12/clasament','Clasament moisil2008-11-12','2008-03-31 16:39:20','2008-03-31 16:39:20','h1. Clasament ==roundparam(round_id=\"moisil2008-11-12\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil2008-11-12\")==',256,'round: moisil2008-11-12',NULL,NULL),('grigore-moisil-2008/clasament/7-8','Grigore Moisil 2008, Clasament clasele 7-8','2008-03-31 17:02:15','2008-03-31 17:02:15','==Include(page=\"template/grigore-moisil-2008\")==\r\n\r\nh1. == roundparam(round_id=\"moisil2008-7-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre concurs\':grigore-moisil-2008/\r\n*(active) \'Clasament\':grigore-moisil-2008/clasament/5-6\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n(htabs)* \'Clasele 5-6\':grigore-moisil-2008/clasament/5-6\r\n*(active) \'Clasele 7-8\':grigore-moisil-2008/clasament/7-8\r\n* \'Clasa a 9-a\':grigore-moisil-2008/clasament/9\r\n* \'Clasa a 10-a\':grigore-moisil-2008/clasament/10\r\n* \'Clasele 11-12\':grigore-moisil-2008/clasament/11-12\r\n\r\np<. == Rankings(rounds=\"moisil2008-7-8\") == ',256,'protected',NULL,NULL),('grigore-moisil-2008/9','Grigore Moisil 2008, Clasa a 9-a','2008-03-31 16:44:01','2008-04-05 23:34:32','==Include(page=\"template/grigore-moisil-2008\")==\r\n\r\nh1. Grigore Moisil 2008\r\n\r\n(htabs)* \'Despre concurs\':grigore-moisil-2008/\r\n* \'Clasament\':grigore-moisil-2008/clasament/9\r\n\r\nh2. Clasa a 9-a\r\n\r\nConcursul se va desfasura *Duminica, 6 aprilie*, la ora {*10^00^*} si va dura *3h*. Participantii vor avea de rezolvat doua probleme de natura algoritmica.\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2008-9\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2008-9\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':grigore-moisil-2008/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"moisil2008-9\" score=\"1\")==\r\n\r\nh2. Clasament\r\n\r\n\'Evaluatorul\':documentatie/evaluator va fi oprit pe toata perioada desfasurarii concursului. Dupa terminarea rundei de concurs va incepe evaluarea in timp real. Rezultatele finale le puteti gasi \'aici\':grigore-moisil-2008/clasament.\r\n',2028,'round: moisil2008-9',NULL,NULL),('grigore-moisil-2008/10','Grigore Moisil 2008, Clasa a 10-a','2008-03-31 16:44:37','2008-04-05 12:07:33','==Include(page=\"template/grigore-moisil-2008\")==\r\n\r\nh1. Grigore Moisil 2008\r\n\r\n(htabs)* \'Despre concurs\':grigore-moisil-2008/\r\n* \'Clasament\':grigore-moisil-2008/clasament/10\r\n\r\nh2. Clasa a 10-a\r\n\r\nConcursul se va desfasura *Duminica, 6 aprilie*, la ora {*10^00^*} si va dura *3h*. Participantii vor avea de rezolvat doua probleme de natura algoritmica.\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2008-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2008-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':grigore-moisil-2008/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"moisil2008-10\" score=\"1\")==\r\n\r\nh2. Clasament\r\n\r\n\'Evaluatorul\':documentatie/evaluator va fi oprit pe toata perioada desfasurarii concursului. Dupa terminarea rundei de concurs va incepe evaluarea in timp real. Rezultatele finale le puteti gasi \'aici\':grigore-moisil-2008/clasament.\r\n',256,'round: moisil2008-10',NULL,NULL),('grigore-moisil-2008/11-12','Grigore Moisil 2008, Clasele 11-12','2008-03-31 16:47:55','2008-04-05 23:34:48','==Include(page=\"template/grigore-moisil-2008\")==\r\n\r\nh1. Grigore Moisil 2008\r\n\r\n(htabs)* \'Despre concurs\':grigore-moisil-2008/\r\n* \'Clasament\':grigore-moisil-2008/clasament/11-12\r\n\r\nh2. Clasele 11-12\r\n\r\nConcursul se va desfasura *Duminica, 6 aprilie*, la ora {*10^00^*} si va dura *3h*. Participantii vor avea de rezolvat trei probleme de natura algoritmica.\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2008-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2008-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':grigore-moisil-2008/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"moisil2008-11-12\" score=\"1\")==\r\n\r\nh2. Clasament\r\n\r\n\'Evaluatorul\':documentatie/evaluator va fi oprit pe toata perioada desfasurarii concursului. Dupa terminarea rundei de concurs va incepe evaluarea in timp real. Rezultatele finale le puteti gasi \'aici\':grigore-moisil-2008/clasament.\r\n',2028,'round: moisil2008-11-12',NULL,NULL),('grigore-moisil-2008/clasament/5-6','Grigore Moisil 2008, Clasament clasele 5-6','2008-03-31 16:57:37','2008-03-31 17:02:34','==Include(page=\"template/grigore-moisil-2008\")==\r\n\r\nh1. == roundparam(round_id=\"moisil2008-5-6\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre concurs\':grigore-moisil-2008/\r\n*(active) \'Clasament\':grigore-moisil-2008/clasament/5-6\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n(htabs)*(active) \'Clasele 5-6\':grigore-moisil-2008/clasament/5-6\r\n* \'Clasele 7-8\':grigore-moisil-2008/clasament/7-8\r\n* \'Clasa a 9-a\':grigore-moisil-2008/clasament/9\r\n* \'Clasa a 10-a\':grigore-moisil-2008/clasament/10\r\n* \'Clasele 11-12\':grigore-moisil-2008/clasament/11-12\r\n\r\np<. == Rankings(rounds=\"moisil2008-5-6\") == ',256,'protected',NULL,NULL),('grigore-moisil-2008/clasament/9','Grigore Moisil 2008, Clasament clasa a 9-a','2008-03-31 17:04:09','2008-03-31 17:04:09','==Include(page=\"template/grigore-moisil-2008\")==\r\n\r\nh1. == roundparam(round_id=\"moisil2008-9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre concurs\':grigore-moisil-2008/\r\n*(active) \'Clasament\':grigore-moisil-2008/clasament/5-6\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n(htabs)* \'Clasele 5-6\':grigore-moisil-2008/clasament/5-6\r\n* \'Clasele 7-8\':grigore-moisil-2008/clasament/7-8\r\n*(active) \'Clasa a 9-a\':grigore-moisil-2008/clasament/9\r\n* \'Clasa a 10-a\':grigore-moisil-2008/clasament/10\r\n* \'Clasele 11-12\':grigore-moisil-2008/clasament/11-12\r\n\r\np<. == Rankings(rounds=\"moisil2008-9\") == ',256,'protected',NULL,NULL),('grigore-moisil-2008/clasament/10','Grigore Moisil 2008, Clasament clasa a 10-a','2008-03-31 17:05:05','2008-03-31 17:05:05','==Include(page=\"template/grigore-moisil-2008\")==\r\n\r\nh1. == roundparam(round_id=\"moisil2008-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre concurs\':grigore-moisil-2008/\r\n*(active) \'Clasament\':grigore-moisil-2008/clasament/5-6\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n(htabs)* \'Clasele 5-6\':grigore-moisil-2008/clasament/5-6\r\n* \'Clasele 7-8\':grigore-moisil-2008/clasament/7-8\r\n* \'Clasa a 9-a\':grigore-moisil-2008/clasament/9\r\n*(active) \'Clasa a 10-a\':grigore-moisil-2008/clasament/10\r\n* \'Clasele 11-12\':grigore-moisil-2008/clasament/11-12\r\n\r\np<. == Rankings(rounds=\"moisil2008-10\") == ',256,'protected',NULL,NULL),('grigore-moisil-2008/clasament/11-12','Grigore Moisil 2008, Clasament clasele 11-12','2008-03-31 17:06:15','2008-03-31 17:06:15','==Include(page=\"template/grigore-moisil-2008\")==\r\n\r\nh1. == roundparam(round_id=\"moisil2008-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre concurs\':grigore-moisil-2008/\r\n*(active) \'Clasament\':grigore-moisil-2008/clasament/5-6\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n(htabs)* \'Clasele 5-6\':grigore-moisil-2008/clasament/5-6\r\n* \'Clasele 7-8\':grigore-moisil-2008/clasament/7-8\r\n* \'Clasa a 9-a\':grigore-moisil-2008/clasament/9\r\n* \'Clasa a 10-a\':grigore-moisil-2008/clasament/10\r\n*(active) \'Clasele 11-12\':grigore-moisil-2008/clasament/11-12\r\n\r\np<. == Rankings(rounds=\"moisil2008-11-12\") == ',256,'protected',NULL,NULL),('blog/grigore-moisil-2008','stiri/grigore-moisil-2008','2008-04-04 23:27:48','2008-04-04 23:27:54','h1. Grigore Moisil pe infoarena\r\n\r\ninfoarena organizeaza online pe data de *6 aprilie* concursul interjudetean \"Grigore Moisil\". Astfel vei avea ocazia sa iti masori fortele cu cei care participa live la concurs. Vor exista 5 grupe de varsta: clasele 5-6, clasele 7-8, clasa a 9-a, clasa a 10-a si respectiv clasele 11-12. Afla mai multe detalii pe \'pagina concursului\':grigore-moisil-2008.',1,'protected',NULL,NULL),('newsletter/grigore-moisil-2008','Grigore Moisil 2008 by net','2008-04-05 09:21:35','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nIn perioada 4-6 aprilie se desfasoara la Cluj-Napoca concursul\r\ninterjudetean de matematica si informatica \"Grigore Moisil\".\r\ninfoarena gazduieste o varianta online a acestui concurs iar tu\r\nesti invitat sa participi.\r\n\nAi ocazia sa iti masori fortele cu cei care participa live la\r\nconcurs. Problemele vor fi impartite pe 5 grupe de varsta!\r\n\nSucces!\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Concursul online se desfasoara...\r\n\np{padding-left: 2em;}. Duminica, 6 aprilie 2008, orele 10:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nVezi pagina concursului: \'grigore-moisil-2008\':grigore-moisil-2008\r\nca sa afli cum poti participa.\r\n\nSucces!\r\n\nh2.  Despre concurs \n\nA XXIII-a editie a \"Grigore Moisil\" este organizata de ISJ Cluj\r\nin colaborare cu Universitatea \"Babes-Bolyai\" si cu Societatea de\r\nStiinte Matematica din Romania.\r\nLa acest concurs, participa 230 de elevi de clasele V-XII (150\r\nla matematica 80 la informatica) din judetele Maramures, Bihor,\r\nSatu-Mare, Salaj, Bistrita-Nasaud si Cluj.\r\n\nAceasta este a doua editie cand proba de informatica a concursului\r\nse desfasoara si pe infoarena. Suntem foarte bucurosi sa sprijinim\r\nintentia unui concurs interjudetean, regional, de a se deschide\r\ncatre participanti din toata tara. Este un pas inainte si speram\r\nsa constituie un exemplu pozitiv pentru alte concursuri similare.\r\n\nVor propune probleme Prof. Clara Ionescu si Patcas Csaba\r\npentru 5 grupe de varsta: clasele 5-6, clasele 7-8, clasa a 9-a,\r\nclasa a 10-a si respectiv clasele 11-12.\r\n\nOrganizatorii rundei online pe infoarena sunt:\r\n\np{padding-left: 2em;}. Filip Cristian Buruiana\r\n    [  ==User(user=\"filipb\" type=\"link\")==  ]\r\n\np{padding-left: 2em;}. Airinei Adrian\r\n    [  ==User(user=\"astronomy\" type=\"link\")==  ]\r\n\nAcesta nu este un concurs cu rating.\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nRamai alaturi de noi.  Te ajutam sa devii olimpic!\r\nEchipa infoarena iti ureaza succes!\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('grigore-moisil-2008','Grigore Moisil 2008','2008-03-31 06:28:54','2008-04-06 13:30:34','==Include(page=\"template/grigore-moisil-2008\")==\r\n\r\nh1. Grigore Moisil 2008\r\n\r\n(htabs)*(active) \'Despre concurs\':grigore-moisil-2008/\r\n* \'Clasament\':grigore-moisil-2008/clasament/5-6\r\n\r\ninfoarena organizeaza online pe data de 6 aprilie concursul interjudetean \"Grigore Moisil\". Astfel vei avea ocazia sa iti masori fortele cu cei care participa live la concurs. Vor exista $5$ grupe de varsta: clasele {$5-6$}, clasele {$7-8$}, clasa a {$9$}-a, clasa a {$10$}-a si respectiv clasele {$11-12$}.\r\n\r\nConcursul se va desfasura *Duminica, 6 aprilie*, la ora {*10^00^*} si va dura *3h*.\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* prof. Clara Ionescu\r\n* Patcas Csaba\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"filipb\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru!\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti problemele, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':documentatie/evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nh2. Prima data pe _infoarena_?\r\n\r\n\'infoarena\':/ ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi si vezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n',2028,'protected',NULL,NULL),('grigore-moisil-2008/solutii','Grigore Moisil 2008, Articolul cu solutii','2008-04-06 07:14:15','2008-11-26 12:15:07','p{style=\"margin: 2em 0 1em 0; padding: .5em; border: 1px solid silver; -moz-border-radius: 10px;\"}. !grigore-moisil-2008?moisil.jpg 80%!:/grigore-moisil-2008\r\n\r\nh1. Solutii Grigore Moisil 2008\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Joc8\':grigore-moisil-2008/solutii#joc8\r\n* \'Patrat\':grigore-moisil-2008/solutii#patrat\r\n* \'Fibo\':grigore-moisil-2008/solutii#fibo\r\n* \'Pusculita\':grigore-moisil-2008/solutii#pusculita\r\n* \'Suma3\':grigore-moisil-2008/solutii#suma3\r\n* \'Pitici2\':grigore-moisil-2008/solutii#pitici2\r\n* \'Carti\':grigore-moisil-2008/solutii#carti\r\n* \'Euro2\':grigore-moisil-2008/solutii#euro2\r\n* \'Zip\':grigore-moisil-2008/solutii#zip\r\n* \'Lacat\':grigore-moisil-2008/solutii#lacat\r\n* \'Online\':grigore-moisil-2008/solutii#online\r\n\r\n==include(page=\"grigore-moisil-2008/solutii/joc8\")==\r\n\r\n==include(page=\"grigore-moisil-2008/solutii/patrat\")==\r\n\r\n==include(page=\"grigore-moisil-2008/solutii/fibo\")==\r\n\r\n==include(page=\"grigore-moisil-2008/solutii/pusculita\")==\r\n\r\n==include(page=\"grigore-moisil-2008/solutii/suma3\")==\r\n\r\n==include(page=\"grigore-moisil-2008/solutii/pitici2\")==\r\n\r\n==include(page=\"grigore-moisil-2008/solutii/carti\")==\r\n\r\n==include(page=\"grigore-moisil-2008/solutii/euro2\")==\r\n\r\n==include(page=\"grigore-moisil-2008/solutii/zip\")==\r\n\r\n==include(page=\"grigore-moisil-2008/solutii/lacat\")==\r\n\r\n==include(page=\"grigore-moisil-2008/solutii/online\")==\r\n',1490,'public',NULL,NULL),('grigore-moisil-2008/solutii/fibo','grigore-moisil-2008/solutii/fibo','2008-04-06 07:24:09','2008-04-06 16:00:47','h2(#fibo). \'Fibo\':problema/fibo\r\n\r\nProblema poate fi abordata in mai multe feluri:\r\n\r\n* Luam in considerare pe rand toate numerele mai mici sau egale cu numarul dat $N$ si generam reprezentarea lor in sistemul Fibonacci. Apoi verificam sirul de caractere pentru a stabili daca este sau nu palindrom. \r\n* Este posibil sa abordam problema si invers, adics sa generam sirul de caractere palindrom formate din cifre $1$ si $0$. Lungimea sirului de caractere va fi egala cu lungimea sirului Fibonacci continand numere mai mici sau egale cu $n$. Cum al $30$-lea termen fibonacci depaseste $10^6^$ avem cel mult $2^16^$ posibilitati de a genera palindroame.\r\n',2092,'public',NULL,NULL),('grigore-moisil-2008/solutii/suma3','grigore-moisil-2008/solutii/suma3','2008-04-06 07:24:57','2008-04-06 16:01:13','h2(#suma3). \'Suma3\':problema/suma3\r\n\r\nProblema se rezolva prin metoda backtracking, dar pentru a obtine un program cat de cat performant este nevoie de diverse optimizari. Prima data se observa ca nu trebuie generate sume mai mari decat valoarea minima actuala. Aceasta valoare se actualizeaza dupa caz pe parcursul generarii solutiilor impreuna cu sirul care contine traseul. A doua optimizare este mai interesanta: vom pastra fiecare element al tabloului dat si sub forma unui sir ordonat dupa valoarea elementelor, impreuna cu pozitia din tablou.',2092,'public',NULL,NULL),('grigore-moisil-2008/solutii/carti','grigore-moisil-2008/solutii/carti','2008-04-06 07:26:04','2008-04-07 15:17:19','h2(#carti). \'Carti\':problema/carti\r\n\r\nO stare a cartilor de pe masa se poate reprezenta printr-un numar din intervalul {$[0, 8191]$} in felul\r\nurmator: scriind numarul in sistem binar obtinem forma {$b{~12~}b{~11~}...b{~1~}b{~0~}$}, unde {$b{~i~} = 1$}, daca si numai daca cartea cu valoarea $i+1$ se afla pe masa.\r\nSa consideram vectorul {$win{~i~}$} cu semnificatia:\r\n\r\n* {$win{~i~} = true$}, daca jucatorul care este la mutare in starea $i$ are strategie sigura de castig\r\n* {$win{~i~} = false$}, in caz contrar\r\n\r\nDeterminarea valorilor {$win{~i~}$} este destul de simpla. Daca dintr-o stare se poate ajunge intr-o stare in care jucatorul pierde, inseamna ca starea curenta este o stare cu strategie sigura de castig: \r\n\r\n* {$win{~i~} = true$}, daca din starea $i$ se poate ajunge intr-o stare $j$ astfel incat {$win{~j~} = false$}\r\n* {$win{~i~} = false$}, in caz contrar\r\n\r\nDintr-o stare $i$ se poate ajunge intr-o stare $j$ daca $j$ se poate obtine din $i$ prin scaderea a cel mult $k$ biti consecutivi. Asadar pentru a vedea in ce stari putem ajunge dintr-o stare {$i$}, trebuie sa incercam toate valorile lui $k$ posibile si toate pozitiile pe care poate aparea sirul de biti consecutivi. \r\n\r\n==code(c)|win[state]:=0;\r\nfor i:=1 to k do\r\nbegin\r\nmask:=0;\r\nfor j:=0 to i-1 do mask:=mask or (1 shl j);\r\nfor j:=0 to 13-i do\r\nif (state and (mask shl j))=(mask shl j)\r\nthen\r\nif not DoesWin(state-(mask shl j))\r\nthen\r\nbegin\r\nwin[state]:=1;\r\nbreak;\r\nend;\r\nif win[state]=1\r\nthen break;\r\nend;==\r\n\r\nRamane sa calculam numarul $nr$ asociat starii initiale de pe masa, si daca {$win{~nr~} = true$} sa afisam Alice, iar in caz contrar sa afisam Bob. Pentru a calcula {$win{~nr~}$} vom avea nevoie de examinarea a {$2^N^$} stari, asadar algoritmul final are complexitatea {$O(2^N^ * K)$} pentru fiecare configuratie din fisierul de intrare.\r\n',256,'public',NULL,NULL),('grigore-moisil-2008/solutii/lacat','grigore-moisil-2008/solutii/lacat','2008-04-06 07:27:11','2008-04-06 15:59:04','h2(#lacat). \'Lacat\':problema/lacat\r\n\r\nProblema se poate rezolva in mai multe feluri, algoritmii respectivi avand complexitati diferite.\r\n\r\n1. Prezentam rezolvarea consacrata, care modeleaza efectiv pasii care trebuie efectuati conform regulii jocului. Se aplica metoda _Divide et Impera_, unde avem urmatoarele subprobleme:\r\n\r\n* $TotiJos(m)$: Elibereaza primele $m$ inele (in ordine oarecare), restul inelelor raman neschimbate\r\n\r\n==code(c)|Algoritm TotiJos(m):\r\n    Pentru i = m, 1 executa:\r\n        Daca lacat[i] atunci\r\n            Jos(i)\r\n        Sfarsit(Daca)\r\n    Sfarsit(Pentru)\r\nSfarsit(Algoritm)\r\n==\r\n\r\n* $Jos(i)$: Elibereaza al $i$-lea inel, inelele avand numere de ordine $j > i$ raman neschimbate (inelele avand numere de ordine j < i pot fi in orice pozitie dupa efectuarea operatiei)\r\n\r\n==code(c)|Algoritm Jos(i):\r\n    Daca (i > 1) si (!lacat[i-1]) atunci\r\n        Sus(i-1)\r\n    Sfarsit(Daca)\r\n    Daca (i > 2) atunci\r\n        TotiJos(i-2)\r\n    Sfarsit(Daca)\r\n    lacat[i] = fals           {al i-lea inel jos}\r\n    Scrie: \'J\', i\r\nSfarsit(Algoritm)\r\n==\r\n\r\n* $Sus(i)$: Pune la loc al $i$-lea inel, inelele avand numere de ordine j > i raman neschimbate (inelele avand numere de ordine j < i pot fi in orice pozitie dupa efectuarea operatiei).\r\n\r\n==code(c)|Algoritm Sus(i):\r\n    Daca (i > 1) si (!lacat[i-1]) atunci\r\n        Sus(i-1)\r\n    Sfarsit(Daca)\r\n    Daca i > 2 atunci\r\n        TotiJos(i-2)\r\n    Sfarsit(Daca)\r\n    lacat[i] = adevarat  	      {al i-lea inel sus}\r\n    Scrie: \'S\', i\r\nSfarsit(Algoritm)\r\n==\r\n\r\nIn programul principal se initializeaza sirul $lacat$ cu valoarea $adevarat$ (reprezentand faptul ca acestia sunt sus, adica lacatul este inchis). Apoi se apeleaza subprogramul $TotiJos(n)$.\r\n\r\nDeoarece numarul pasilor trebuie afisat la inceput, acesta poate fi calculat cu un algoritm liniar:\r\n\r\n==code(c)|Algoritm Calculeaza():\r\n    nrpasi = 1\r\n    Pentru q = 2, n executa:\r\n        nrpasi = nrpasi * 2\r\n        Daca q este numar impar atunci\r\n            nrpasi = nrpasi + 1\r\n        Sfarsit(Daca)\r\n    Sfarsit(Pentru)\r\nSfarsit(Algoritm)\r\n==\r\n\r\n2. O abordare bazata pe parcurgerea in adancime a spatiului solutiilor are complexitatea O(2^n^) si astfel in timpul acordat functioneaza doar daca n &le; 11 datorita limitelor de memorie.\r\n\r\n3. Cea de a treia posibilitate ar fi fost implementarea unei parcurgeri in latime obtinand solutii in timpul acordat daca n &le; 16. \r\n\r\n4. Cel de a patrulea algoritm (cunoscut sub denumirea DFSID) functioneaza in timpul acordat doar pentru n &le; 5.\r\n',2092,'public',NULL,NULL),('grigore-moisil-2008/solutii/online','grigore-moisil-2008/solutii/online','2008-04-06 07:27:39','2009-06-09 15:38:13','h2(#online). \'Online\':problema/online\r\n\r\nProblema cere costul arborelui partial de cost minim, graful initial schimbandu-se la fiecare pas. Prima idee ar fi rularea unui algoritm clasic pentru gasirea arborelui partial de cost minim de $K + 1$ ori. In functie de algoritmul folosit si de metoda de implementare, obtinem complexitati diferite. Folosind algoritmul Kruskal putem obtine complexitati de $O(K * N * M)$, $O(K * (M * log M + N^2^))$ sau $O(K * M * log M)$. Folosind algoritmul Prim putem obtine complexitatea $O(K * N^2^)$, sau $O(K * M * log N)$ in cazul folosirii heap-urilor la implementare.\r\nTotusi niciuna dintre aceste variante nu se incadreaza in timp pentru limitele date, asa ca propunem urmatorul algoritm, avand complexitatea $O(N^2^ + K * N)$. Prima data se gaseste arborele partial de cost minim pentru graful initial, folosind algoritmul Prim. Pentru urmatorii $K$ pasi avem doua posibilitati:\r\n\r\n# Muchia curenta este intre doua noduri din arborele partial minim actual. Daca muchia are lungime mai mica, suprascriem muchia din arbore si costul arborelui se imbunatateste cu diferenta costurilor. Daca muchia are lungime mai mare sau egala, arborele ramane neschimbat.\r\n# Muchia nu face parte din arbore. Fiindca arborele are numar maxim de muchii din punctul de vedere al aciclitatii, o noua muchie va forma cu siguranta un ciclu. Pentru a ajunge iarasi la un arbore, din acest ciclu trebuie stearsa o muchie. Pentru ca arborele care rezulta sa aiba cost minim, vom sterge muchia cu cost maxim din ciclu.\r\n',5748,'public',NULL,NULL),('preoni-2008/runda-finala/solutii/progresii','preoni-2008/runda-finala/solutii/progresii','2008-03-25 09:23:37','2008-04-06 12:15:16','h2(#progresii). \'Progresii\':problema/progresii\r\n\r\nReformuland problema, avem de fapt $N$ progresii aritmetice si trebuie sa gasim ratia pentru fiecare ca numarul de termeni din progresii $&le; L$ sa fie cel mult $K$. Vom construi pas cu pas solutia. La pasul $i$ vom determina ratia progresiei $i$ ca fiind cea mai mica posibila astfel incat daca restul progresiilor (de la $i+1$ la $N$) au ratia maxima posibila obtinem solutie. Ratia progresiei $i$ o putem cauta binar in intervalul $[1,M]$. Pentru a obtine in final complexitatea $O(N*logN)$ vom mai precalcula un vector $sum[i] = numarul de termeni &le; L$ daca toate ratiile de la $i$ la $N$ sunt egale cu $M$.',2092,'public',NULL,NULL),('preoni-2008/runda-finala/solutii/peste','preoni-2008/runda-finala/solutii/peste','2008-03-25 09:23:55','2008-04-06 12:22:40','h2(#peste). \'Peste\':problema/peste\r\n\r\nSa presupunem ca la momentul $x$ introducem in apa plasa $i$ si vrem in viitor sa introducem si plasa $j$. Avem doua posibilitati: plasa $j$ o introducem la un moment de timp mai mare decat $x+T[i]$ sau la un moment de timp din intervalul $[x,x+T[i]]$. In cazul al doilea cel mai favorabil este sa introducem plasa $j$ la momentul $x$. Odata ce ne hotaram ca la un moment $t$ sa introducem in apa cateva plase este suficient sa fixam timpul maxim de asteptare (momentul la care vom scoate toate plasele introduse la momentul $t$) si sa consideram cel mult $K$ plase care prind cat mai mult peste si timpul in care fac asta este mai mic sau egal decat timpul maxim fixat. Vom preprocesa un vector $aux[t] =$ numarul maxim de pesti pe care ii putem prinde daca plasele introduse au timpul de asteptare mai mic sau egal decat $t$. Apoi, folosind programare dinamica vom calcula vectorul $best[t] =$ numarul maxim de pesti pe care ii putem prinde de la momentul $0$ la momentul $t$. Solutia se va afla in $best[T]$. Relatia de recurenta va fi $best[t] = max(best[t-1]+aux[ 1 ], best[t-2]+aux[ 2 ]...best[t-TMAX]+aux[TMAX])$. Complexitatea solutiei va fi $O(N*logK+T*TMAX)$, unde $TMAX$ este timpul maxim de asteptare a unei plase (in cazul nostru $1000$). Pentru a preprocesa vectorul $aux[]$ putem folosi un heap sa obtinem complexitatea acestui pas $O(N*logK)$.\r\n\r\n',2092,'public',NULL,NULL),('grigore-moisil-2008/solutii/zip','grigore-moisil-2008/solutii/zip','2008-04-06 07:26:51','2008-04-07 08:10:55','h2(#zip). \'Zip\':problema/zip\r\n\r\nProblema se poate imparti in doua parti. Prima data se construieste un graf complet cu $n$ noduri, in care ponderea unei muchii semnifica numarul maxim de caractere care pot fi comune daca cuvintele corespunzatoare nodurilor respective se scriu unul dupa celalalt. Dupa construirea grafului ramane sa determinam drumul cel mai lung, care contine exact $m$ noduri. Numarul cautat va fi $(m * k - lungimea acestui drum)$. Prima parte se poate rezolva cu algoritmul trivial in $O(n^2^*k^2^)$, sau folosind functia prefix din algoritmul \'Knuth-Morris-Pratt\':problema/strmatch in $O(n^2^*k)$. A doua parte se poate rezolva cu metoda backtracking in $O(n^m^)$. Evident, aceasta metoda este mult prea lenta, chiar si cu optimizarile posibile. O metoda mai rapida este folosirea metodei programarii dinamice si are o complexitate de $O(n^2^*m)$. Se calculeaza matricea $d$, cu semnificatia: $d[i,j]$ este drumul de lungime maxima, care trece prin $i$ noduri si se termina in nodul $j$. Evident, valoarea cautata va fi $max(d[m,i], i = 1, 2 ... n)$.',2092,'public',NULL,NULL),('grigore-moisil-2008/solutii/pitici2','grigore-moisil-2008/solutii/pitici2','2008-04-06 07:25:44','2008-04-06 16:10:45','h2(#pitici2). \'Pitici2\':problema/pitici2\r\n\r\nRezolvarea optima ruleaza in timp liniar: Daca toate punctele se afla pe o singura dreapta, problema devine triviala. In caz contrar putem gasi trei puncte necolineare, sa le notam cu $A$, $B$ si $C$.\r\nAvem doua cazuri:\r\n\r\n* Dreptele $AB$, $BC$ si $AC$ acopera toate punctele: am obtinut solutia.\r\n* Exista un punct $D$, care nu este acoperit de niciuna dintre dreptele de mai sus. Daca exista trei drepte, care acopera toata multimea de puncte, putem avea doua cazuri:\r\n** Doua drepte acopera cate doua puncte din $A$, $B$, $C$ si $D$, iar a treia acopera alte puncte. Pentru verificarea acestui caz incercam toate cele trei imperecheri posibile $(AB+CD,AC+BD,AD+BC)$.\r\n** O dreapta acopera doua puncte din $A$, $B$, $C$ si $D$, iar doua trec prin cate un punct din cele ramase. Acest caz se trateaza in felul urmator: sa consideram o anumita imperechere, care defineste doua drepte, de exemplu $AB+CD$. Daca punctele neacoperite de aceste doua drepte nu sunt colineare, sa consideram un punct $E$, care nu se afla pe cele doua drepte. Daca multimea de puncte se poate acoperi cu trei drepte, punctul $E$ trebuie sa se afle pe una din ele. Stiind ca $E$ nu se afla pe $AB$, incercam variantele $AB+CE$ si $AB+DE$. Pentru celelalte imperecheri procedam in mod simetric.',2092,'public',NULL,NULL),('grigore-moisil-2008/solutii/pusculita','grigore-moisil-2008/solutii/pusculita','2008-04-06 07:24:36','2008-04-06 15:59:45','h2(#pusculita). \'Pusculita\':problema/pusculita\r\n\r\nPentru obtinerea punctajului maxim este necesara cunoasterea programarii dinamice. Vom construi un sir cu indicii de la $0$ la $S$, in care pe pozitia $i$ vom stoca cea mai mica valoare ce pot avea niste monezi avand suma greutatilor egala cu $i$. La inceput initializam toate elementele vectorului cu o valoare mare,\r\nmai putin elementul de pe pozitia $0$, care va fi initializat cu $0$. Sirul se calculeaza dupa cum urmeaza:\r\n==code(c)|for q:=0 to s do\r\n   for w:=1 to n do\r\n      if (q>=greutate[w]) and (sir[q]-sir[q-greutate[w]]>valoare[w])\r\n      then \r\n          sir[q]:=sir[q-v[w]]+valoare[w];\r\n==',2092,'public',NULL,NULL),('grigore-moisil-2008/solutii/joc8','grigore-moisil-2008/solutii/joc8','2008-04-06 07:21:27','2008-04-07 15:03:46','h2(#joc8). \'Joc8\':problema/joc8\r\n\r\nDin descrierea jocului se desprinde algoritmul cautarii binare, algoritm care nu trebuia sa fie cunoscut de concurenti, deoarece este descris in enunt. Singurele dificultati constau in intelegerea si implementarea modelului descris.\r\n\r\n==code(c)|Citeste x,y\r\n  gasit = fals\r\n  cat timp nu gasit si (x <= y) executa:\r\n    z = (x + y) div 2\r\n    Citeste: raspuns\r\n    Daca raspuns = 1 atunci\r\n      gasit = adevarat\r\n    altfel\r\n      Citeste: raspuns\r\n      Daca raspuns = 1 atunci\r\n        y = z - 1\r\n      altfel\r\n        x = z + 1\r\n      Sfarsit(Daca)\r\n    Sfarsit(Daca)\r\n  Sfarsit(Cat timp)\r\n  Daca gasit atunci\r\n    Scrie: z\r\n  altfel\r\n    Scrie: 0\r\n  Sfarsit(Daca)\r\nSfarsit(Algoritm)==\r\n',256,'public',NULL,NULL),('grigore-moisil-2008/solutii/euro2','grigore-moisil-2008/solutii/euro2','2008-04-06 07:26:27','2008-04-07 15:23:46','h2(#euro2). \'Euro2\':problema/euro2\r\n\r\nPovestea din enunt \"ascunde\" urmatoarea problema: sa se determine cel mai lung subsir care este crescator pana la o anumita pozitie, apoi este descrescator.\r\n\r\nProblema se poate rezolva corect utilizand in mai multe feluri metoda programarii dinamice, dar rezolvarile vor avea performante diferite. \r\n\r\n{$1.$} Cel mai simplu algoritm de tip $brute force$ genereaza toate cele {$2^N^$} submultimi ale multimii numerelor date, si le verifica pentru a decide daca au proprietatea ceruta. Aceasta solutie are o complexitate {$O(N * 2^N^)$}.\r\n\r\n{$2.$} Solutii mai performante obtinem utilizand algoritmi de determinare a celui mai lung subsir crescator (descrescator), apeland la metoda programarii dinamice. Rezolvarea corecta consta in determinarea lungimii celui mai lung subsir crescator considerand ca si capat al acestuia pe rand, fiecare element al sirului dat, si lungimea celui mai lung subsir descrescator considerand ca prim element al acestuia, pe rand, fiecare element al sirului dat. Avand aceste lungimi, prin combinarea lor si determinarea maximului sumelor perechilor de lungimi corespunzatoare, obtinem rezultatul in complexitate {$O(N)$}. Lungimile mentionate se pot calcula cu unul din algoritmii cunoscuti avand complexitatile {$O(N^2^)$} sau, optim, {$O(Nlog{~2~}N)$}.\r\n',256,'public',NULL,NULL),('grigore-moisil-2008/solutii/patrat','grigore-moisil-2008/solutii/patrat','2008-04-06 07:23:48','2008-04-07 15:35:08','h2(#patrat). \'Patrat\':problema/patrat\r\n\r\nProblema se rezolva simplu daca construim vectorul {$ok$}, unde {$ok{~i~}$} va fi $true$ daca si numai daca $i$ respecta proprietatile din enunt. Pentru a construi acest vector putem proceda astfel:\r\n\r\n==code(c)|pentru i = 1, 20000\r\n     ok[i] = false\r\npentru i = 1, [radical(20000)]\r\n    pentru j = i+1, [radical(20000)]\r\n        daca i * i + j * j <= 20000\r\n            ok[i * i + j * j] = true\r\n==\r\n\r\nPentru a afisa toate numerele intre $x$ si $y$ ce se pot scrie ca suma de patrate este suficient sa iteram un $i$ intre cele doua margini si sa afisam acele valori care indeplinesc {$ok{~i~} = true$}.',256,'public',NULL,NULL),('preoni-2008/runda-finala/solutii/sortare','preoni-2008/runda-finala/solutii/sortare','2008-03-25 09:24:38','2008-04-07 18:54:42','h2(#sortare). \'Sortare\':problema/sortare\r\n\r\nPresupunem ca avem o permutare de lungime $n$ si pozitiile $A{~n~}, B{~n~}$ si $C{~n~}$. Vom considera doua cazuri:\r\n\r\n# $A{~n~} &ne; B{~n~} &ne; C{~n~}$\r\nIn cazul in care cei trei indici sunt diferiti este evident ca nu poate aparea ca pivot numarele $1$ sau $n$, deoarece nu exista numere mai mici, respectiv mai mari decat ele. In schimb, putem construi sirul astfel sa apara ca pivot orice numar de la $2$ la $n-1$. Deoarece vrem ca adancimea sa fie maxima, trebuie ca una din cele doua bucati care se obtin dupa partititonare sa fie cat mai mare. Asadar, are rost sa punem ca pivot doar $2$ sau $n-1$, reducand rezolvarea pentru lungimea $n$ la rezolvarea lungimii $1$ si lungimii $n-2$. \r\n# $A{~n~} = B{~n~}$ sau $A{~n~} &ne; C{~n~}$ sau $A{~n~} &ne; B{~n~}$\r\nIn cazul in care cel putin doi din indici sunt egali putem aplica un rationament ca cel de mai sus, doar ca de data asta putem pune ca pivot si numerele $1$ si $n$. Astfel, rezolvarea pentru lungime $n$ se reduce la rezolvarea lungimii $n-1$.\r\n\r\nPe baza acestor doua observatii putem face o rezolvare recursiva care alege pivotul in mod greedy in functie de cele doua cazuri. Complexitatea rezolvarii este $O(N^2^)$.',1,'public',NULL,NULL),('template/implica-te/scrie-articole-2','template/implica-te/scrie-articole-2','2008-04-07 22:05:09','2008-12-26 19:51:03','table{margin:0.5em auto;}. |={background-color:#EFEFFF;border:1px solid #9F9FFF}. !<template/implica-te/scrie-articole?icon_pow_community.gif! Acest articol a fost adăugat de ==user(user=\"%user_id1%\" type=\"tiny\")== şi ==user(user=\"%user_id2%\" type=\"tiny\")==\r\n\'*Intră aici*\':implica-te/scrie-articole _dacă doreşti să scrii articole sau află cum te poţi_ \'*implica*\':implica-te _în celelalte proiecte infoarena!_ |\r\n',15,'protected',NULL,NULL),('planificare/sedinta-20080411','Sedinta 2008-04-11','2008-03-14 19:30:29','2008-04-11 22:38:42','h1. Sedinta 2008-04-11\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *vineri, 11 aprilie* la ora *18:00* la \'*UNIBUC*\':http://unibuc.ro\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* _&hellip; asteptam confirmari_\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare sedinta anterioara (\'1\':planificare/sedinta-20080303 si \'2\':planificare/sedinta-20080314)\r\n* stabilit locatie si data pentru sedinta urmatoare\r\n* discutat/votat \'IAP #7\':propuneri/7-community-ladder si \'IAP #8\':propuneri/8-almanah\r\n* Discutie scurta despre finala preONI\r\n** Ce a mers bine?\r\n** Ce a mers prost?\r\n** Lectii invatate\r\n** Nume nou pentru concurs + grupa de studenti preONI 2008\r\n** Intalnire cu dna Andronescu pentru multumiri si vazut daca putem tot la Poli la anu (??)\r\n* Hackaton\r\n** Contact Adobe\r\n** Il facem sau nu?\r\n** Ce presupune? Cine e dispus sa ajute\r\n** Preselectie pe SPOJ?\r\n* Arhiva educationala\r\n** Nu a mai intrat nicio problema in arhiva de ceva timp. Ce s-a intamplat?\r\n** Dintr-o sedinta trecuta: \"Adi si wefgef il ajuta pe Buru sa schimbe politica si procesul de propunere la arhiva educationala.\"\r\n* Complexul elitist\r\n** Se pare ca suntem prea elitisti. Multi sunt cei carora li se pare ca infoarena e numai pentru staruri.\r\n** Cum putem sa fim mai \"accesibili\"?\r\n** Concluzii + Plan de atac\r\n* infoarena.org\r\n** Discutie despre propunerea lui Mugurel\r\n** Concluzii + Plan de atac\r\n* extindere \'IAP #5\':propuneri/5-open-surse\r\n* development\r\n* infoarena research? Florin Manea\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Mircea cloneaza search-ul pe un cont Google neutru, il instaleaza pe site si ii da lui Stefan parola ca sa-l imbunatateasca.\r\n* Intalnirea pe 2008-04-23 ora 18:00 la UNIBUC\r\n* IAP#7:\r\n** Adi face lista de merit (puncte initiale) pentru arhiva de probleme\r\n** Silviu si Stefan... articole\r\n** Buru ... arhiva educationala (DE CONFIRMAT CA SE OCUPA)\r\n** Mircea ... contest-directors\r\n** Cristi ... development\r\n* Cristi incepe lucrul la un prototip, chiar daca nu am votat inca propunerea.\r\n* Cristi face raport de trafic pe articole si use case-uri pentru utilizatori.\r\n* Silviu se mai gandeste la IAP#8 pana data viitoare.\r\n* Silviu il invita pe Stefan la sedinta urmatoare.\r\n* Mircea face raport post-mortem preONI\r\n** Distributia participantilor\r\n** Cine si ce a muncit la eveniment\r\n** Cati bani s-au cheltuit\r\n** Trafic\r\n** Sectiune de lectii invatate / lucruri de evitat sau de repetat data viitoare\r\n*** Cristi scrie despre presa, ceremonii si imagine\r\n*** Mircea scrie despre procedeul de propus probleme\r\n*** Wefgef scrie despre entertainment\r\n*** Vali scrie despre instalari\r\n*** Silviu scrie despre alte chestii... se gandeste\r\n*** cineva(?) scrie despre concurs online VS concurs offline\r\n*** tu despre ce scrii?\r\n* Hackaton\r\n** Il facem\r\n** Proba de preselectie online. Se vor da probleme care se pot rezolva cu cunostinte minimale de C.\r\n** Le dam internet in primele X ore.\r\n** Cristi + Mircea + Silviu + Vali merg la Adobe pentru: timeline, tema si organizare\r\n* IAP#5:\r\n** Cristi scoate un raport despre problemele \"open surse\". Raportul include:\r\n*** Cate surse au vazut utilizatorii\r\n*** Evolutia numarului de submitari dupa deschidere si cate din sursele astea sunt identice\r\n*** Topul problemelor si evolutia numarului de vizualizari dupa ce au fost deschise\r\n** Adi si Wefgef deschid inca ~25 de probleme\r\n* Discutam despre complexul elitist si infoarena.org in urmatoarea sedinta\r\n\r\nh2. Notite\r\n\r\n* Merge sistemul de donatii Paypal\r\n',13,'public',NULL,NULL),('blog/trondheim','Trondheim - sau de ce sa investesti in educatie','2008-04-12 10:13:17','2008-11-15 13:41:14','!{margin: 10px; margin-left: 0; border: 1px solid gray;}blog/trondheim?trondheim.jpg!\r\n\r\nTrondheim e un oras destul de rece din Norvegia in care e mai mult noapte decat zi, dar din cand in cand ai sansa sa vezi aurora boreala. El are 165 000 de locuitori. Orasul asta nu pare a avea nimic special, dar surprinzator Google, Yahoo si Microsoft au toate cate un sediu acolo. In Romania nu ne putem lauda cu asa ceva, desi mitul ca \"romanu e destept\" este bine bagat in constiinta colectiva.\r\nCa exemple pozitive in Romania stiu doar de \'Adobe\':http://myadobe.ro care au sucursala in Bucuresti unde se lauda ca fac chestii destul de misto. Nu aveam nici o parere despre Adobe, dar dupa ce am inceput sa le citesc blogul mi s-a parut o firma din ce in ce mai misto. Mai sunt si Oracle in Bucuresti, Nokia in Cluj si Amazon la Iasi, dar sunt inodore/incolore pentru mine. Probabil ar trebui sa urmeze exemplul Adobe si sa isi faca blog.\r\nAm intrebat colegii din Trondheim cum a reusit sa fie asa de atractiv pentru cei trei giganti IT. Ei mi-au povestit ca orasul este unul studentesc, avand 25000 de studenti, si un centru intelectual in Norvegia. Se face multa cercetare, iar in facultatea de informatica se studiaza mult Information Retrieval. Astfel sunt multi profi si studenti care lucreaza la cel mai inalt nivel exact pe domeniul pe care se bat Google, Yahoo si Microsoft. Unul dintre acesti profesori a pornit o mica companie care avea un motor de cautare. Aceasta companie a fost cumparata de Yahoo si au aparut si centrele Google si Microsoft care au luat oameni cu experienta de la prima companie, profesori de la universitate si studenti pregatiti pe information retreival.\r\n\r\nAstfel se pare ca investitiile bine plasate pot fi destul de profitabile intr-un interval de timp mediu. Din pacate in Romania nu se fac investitii in educatie sau cercetare, si de aceea suntem condamnati urmatorii cativa ani sa ramanem indienii europei si sa facem outsourcing.',1490,'protected',2992,NULL),('grigore-moisil-2008/clasament','grigore-moisil-2008/clasament','2008-04-13 16:00:45','2008-11-16 09:22:08','*Clasele 11-12:*\r\nArdelean Viktor: 301/300\r\nIuga Alexandru: 69/300\r\nMatei Misarca: 400/300\r\n\r\n*Clasele 10:*\r\nSuciu Mircea: 3/100\r\nIonescu Robert-Marius: Comming soon..',1,'public',NULL,NULL),('principiul-includerii-si-excluderii','Principiul Includerii si Excluderii','2008-04-15 03:06:37','2010-03-11 16:36:30','\'Din Arhiva Educationala\':problema/pinex\r\nhttp://www.ginfo.ro/10_6/041.shtml\r\nProbleme de combinatorica si teoria grafurilor, Ioan Tomescu\r\nTeme si probleme de matematica, Mircea Ganga\r\nTeme pentru cercurile si concursurile de matematica ale elevilor, Busneag',9232,'public',NULL,NULL),('utilizator/andreiparau','Profil andreiparau','2008-04-15 15:52:11','2008-04-15 15:52:11','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',8118,'public',NULL,NULL),('utilizator/leka','Profil Leka','2008-04-16 06:46:37','2008-04-16 06:46:37','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',8131,'public',NULL,NULL),('cosmin/stefan','cosmin/stefan','2008-04-20 09:13:03','2008-04-20 11:37:09','',58,'public',NULL,NULL),('blog/ce-am-invatat-din-3-oni-uri','Ce am invatat din 3 ONI-uri','2008-04-22 14:09:38','2008-11-15 13:41:14','In timpul liceului, am avut de trei ori ocazia sa concurez la Olimpiada Nationala de Informatica. N-au fost patru, asa cum mi-as fi dorit, dar pentru ca fiecare mi-a mai deschis putin ochii in ceea ce priveste concursurile scolare, m-am gandit sa va impartasesc si voua cateva concluzii pe care le-am considerat, la timpul lor, utile.\r\n\r\n*2004 - Buzau*\r\n\r\nIn primul rand, am aflat ca ONI nu e un concurs la care au acces doar super-elitele care in copilarie programau in loc sa fure corcoduse sau sa dea cu piciorul in minge. :) Indiferent de nivelul de la care pornim (in cazul meu, de la 0 la inceputul liceului), distanta pana la ONI poate fi parcursa prin munca de catre orice elev care-si doreste asta cu adevarat.\r\n\r\nAm mai invatat ca miracolele nu se intampla prea des. Desi am fost nemultumit de cele 60 (50+10) de puncte obtinute, le meritam cu prisosinta si, la nivelul la care eram, mult mai multe nu se puteau obtine. E bine sa dai ce ai mai bun, dar la fel de bine e sa estimezi sincer cat de pregatit esti.\r\n\r\nNu mi-a placut ca ne-au trimis acasa in timpul primei probe de baraj (din considerente organizatorice), dar pana si drumul cu trenul inapoi spre Bucuresti a folosit la ceva. Niciodata un concurent mai slab decat tine (sau care a avut, pur si simplu, o prestatie slaba) nu trebuie ironizat sau desconsiderat. Dupa doua probe de concurs, participantii se impart in \"calificati\" si \"necalificati\", nu in \"destepti\" si \"prosti\".\r\n\r\n*2005 - Galati*\r\n\r\nNu e suficient sa lucrezi mult, trebuie sa fii eficient. Fata de Buzau am obtinut un rezultat mult mai bun, si totusi am vazut cum altii progresasera in rastimpul unui an semnificativ mai repede decat mine. Poate ca ai rezolvat 100 de probleme in ultima luna, dar cu adevarat important e cat de utile au fost ele. Cu siguranta puteai face 50 care sa te ajute mai mult. Alegeti-va cu grija ce lucrati! Le multumesc lui Catalin Tiseanu si Andrei Teodorescu pentru aceasta lectie. Ma repet, dar recomand cel putin un site cu probleme de idee. Cel al olimpiadei poloneze sau SPOJ/SGU, dar acolo trebuie sa descoperiti singuri \"perlele\". Si, bineinteles, infoarena. ;)\r\n\r\n\"Networking\"-ul se face greu, dar fara el sansele de reusita scad dramatic. Trebuie sa abordezi alti oameni cu care sa ai o colaborare benefica pentru toata lumea. Nu trebuie sa-ti fie frica sa spui altora lucrurile pe care tu le stii, dar e esential sa fii corect. Sa dai aproximativ la fel de mult cat primesti, si asta inseamna inclusiv sa te bagi in vorba cu cei foarte buni doar dupa ce le poti spune ceva care sa-i intereseze.\r\n\r\nNorocul exista si conteaza. Am fost la limita deasupra liniei de intrare in lot, si cele 30 de puncte pe care le-am obtinut in a doua zi de baraj au contribuit decisiv. Cred ca respectiva experienta m-a marcat mult, dar m-a si ajutat sa privesc lucrurile dintr-un alt unghi.\r\n\r\n*2006 - Targoviste*\r\n\r\nPe masura ce devii mai bun, norocul conteaza mai putin sau \"_The harder I work, the luckier I get_\". A fost frustrant sa nu progresez dupa inca un an (am obtinut tot locurile 9-10 si mentiune), dar stiam ca de data asta meritam mai mult decat ce obtinusem. Iar confirmarea a venit la baraj (unde n-am mai avut emotii) si la loturi.\r\n\r\nPerformanta e suma mai multor factori, dintre care pe unii ii ignoram fara sa fie cazul. Psihicul (mentalitatea de invingator, linistea interioara, respectul de sine) fac de multe ori diferenta intre un castigator si un simplu concurent. In ultima jumatate de ora a unei probe te emotionezi si nu mai gandesti limpede. Daca te clasezi prost la ONI, te descurajezi si la baraj. Sunt probleme cu care se confrunta toata lumea, dar in privinta lor chiar se poate face ceva. Analizati-va comportamentul din trecut, izolati factorii la care nu ati lucrat, si acordati-le o atentie sporita.\r\n\r\nLumea nu incepe si nu se termina cu olimpiadele. Cu cat am progresat mai mult, cu atat mi-am dat seama mai bine de asta. Trebuie sa fii concentrat si preocupat de concurs, dar daca nu reusesti sa te detasezi de agitatia generala o iei razna. Comportamentul perfect intr-o zi de ONI? Te trezesti cu dorinta de a rezolva probleme, te rupi de orice altceva in timpul probei, dar la o ora dupa ce s-a terminat te plimbi, te linistesti, te gandesti la altele. Daca nu poti dormi seara din cauza grijilor, nu e OK.\r\n\r\n*Bonus: 2007 - Cluj*\r\n\r\nTreaba comisiei nu e una usoara, si-mi pare bine ca am cunoscut si cealalta parte a baricadei. Fara niste oameni pe care ii criticam extrem de usor, olimpiada ar scadea calitativ destul de repede. Respectati comisia. :)\r\n\r\nTot ce mai pot spune acum e ca duc dorul anilor in care participam la Olimpiada Nationala, asa cum o sa-l duceti si voi. Pana atunci, profitati la maxim de ocazia pe care o aveti ca sa va demonstrati talentul, ca sa invatati si ca sa va distrati pe cinste. Nu in ultimul rand, va urez tuturor multa bafta!\r\n\r\n*Tiberiu Florea* - \'greco.ro\':http://www.greco.ro',1490,'public',3021,NULL),('utilizator/cristi.oprea','Profil cristi.oprea','2008-09-22 16:13:19','2008-09-22 16:13:19','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',8515,'public',NULL,NULL),('numerele-sprague-grundy','Teoria jocurilor: numerele Sprague-Grundy','2008-11-18 17:10:41','2009-02-20 01:09:12','h1. Teoria jocurilor: numerele Sprague-Grundy\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"portocala\") ==\r\n\r\n(Categoria _Matematică_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 25em}*{text-align:center;} *Conţinut*\r\n* \'Introducere\':numerele-sprague-grundy#introducere\r\n* \'Ce este jocul NIM?\':numerele-sprague-grundy#jocul-nim\r\n* \'Aplicaţii ale strategiei NIM\':numerele-sprague-grundy#aplicatii-nim\r\n* \'Numerele Sprague-Grundy\':numerele-sprague-grundy#sprague-grundy\r\n* \'Aplicaţii ale numerelor Sprague-Grundy\':numerele-sprague-grundy#aplicatii-sg\r\n* \'Concluzii\':numerele-sprague-grundy#concluzii\r\n* \'Probleme suplimentare\':numerele-sprague-grundy#probleme-suplimentare\r\n* \'Bibliografie\':numerele-sprague-grundy#bibliografie\r\n\r\nh2(#introducere). Introducere\r\n\r\nDomeniu relativ nou şi încă necercetat în adâncime, $teoria jocurilor$ este o ramură a matematicii în care de multe ori primează inventivitatea şi nu cunoştinţele. Tocmai din acest motiv, în cadrul acestui articol vom introduce câteva noţiuni teoretice care ne vor ajuta în rezolvarea unor probleme din teoria jocurilor. Ingeniozitatea celor pasionaţi poate fi testată prin introducerea unor probleme de teoria jocurilor la concursurile de matematică şi informatică. Deoarece în România teoria jocurilor nu este studiată în şcoli, problemele din acest domeniu pot pune în dificultate concurenţii.\r\n\r\nh2(#jocul-nim). Ce este jocul NIM?\r\n\r\nPentru început ne vom familiariza cu jocul clasic $NIM$:\r\n\r\nbq. Se consideră $N$ grămezi de pietre. Doi jucători, vor ridica alternativ oricâte pietre dintr-o singură grămadă. Câştigătorul este cel care ia ultima piatră.\r\n\r\nÎn rezolvare distingem mai multe cazuri:\r\n\r\n* Pentru cazul trivial în care numărul de grămezi este egal cu $1$, primul jucător are, evident, strategie de câştig, el putând lua toate pietrele din grămadă.\r\n* Dacă numărul de grămezi este egal cu $2$, primul jucător are strategie de câştig atunci când numărul de pietre din prima grămadă este diferit de numărul de pietre din cea de-a doua, strategia lui fiind cea de a aduce tot timpul grămada mai mare la numărul de pietre al grămezii mai mici, şi cum jocul este finit, înseamnă că primul jucător o să aducă jocul în starea $(0, 0)$.\r\n* Dacă numărul de grămezi este mai mare decât doi, strategia se complică şi nu se mai observă cu \"ochiul liber\". Stările câştigătoare pentru mai multe grămezi sunt acele stări pentru care suma $XOR$ a numerelor de pietre din grămezi este diferită de $0$, restul stărilor fiind de pierdere.\r\n\r\nDe exemplu, dacă avem $4$ grămezi cu $1$, $3$, $5$, respectiv $7$ pietre:\r\n\r\n* $*O*$\r\n* $*OOO*$\r\n* $*OOOOO*$\r\n* $*OOOOOOO*$\r\n\r\nAtunci vom avea:\r\n\r\n* $*1 = (0001){~2~}*$\r\n* $*3 = (0011){~2~}*$\r\n* $*5 = (0101){~2~}*$\r\n* $*7 = (0111){~2~}*$\r\n\r\nEfectuând \'$XOR$\':http://www.fredosaurus.com/notes-cpp/expressions/bitops.html (operatorul $^$ în $C/C++$) între reprezentările binare ale numerelor, obţinem $*0 = (0000){~2~}*$. Conform propoziţiei de mai sus, această stare este de pierdere.\r\n\r\nSă demonstrăm cele afirmate. Dintr-o poziţie cu suma $XOR$ egală cu $*0*$, pentru orice mutare ajungem evident la o poziţie cu suma $XOR$ diferită de $*0*$, pentru că luând dintr-o grămadă un număr $x$ de pietre, suma $XOR$ corespunzătoare noii stări, pe poziţia bitului de $*1*$ cel mai din dreapta în reprezentarea lui $x$, va avea valoarea $*1*$.\r\n\r\nMai rămâne de demonstrat că din orice poziţie cu suma $XOR$ diferită de $*0*$ putem trece printr-o mutare convenabilă într-o poziţie cu suma $XOR$ egală cu $*0*$. Căutăm o grămadă al cărui număr de pietre are bitul $*1*$ pe poziţia celei mai mari puteri a lui $2$ care apare în suma $XOR$. Fie $x$ valoarea sumei $XOR$ a tuturor grămezilor şi $y$ numărul de pietre din grămada găsită mai devreme. O mutare \"câştigătoare\" este extragerea din grămada găsită care are $y$ pietre a {$y - (x XOR y)$} pietre ({$x XOR y$} este mai mic decât $y$ pentru că în $y$ se anulează bitul cel mai semnificativ al lui $x$). Atunci noua sumă $XOR$ va fi egală cu $*0*$.\r\n\r\nDe exemplu:\r\n\r\n* $*4{@ ^ 8 ^ @}17 = (00100){~2~}{@ ^ @}(01000){~2~}{@ ^ @}(10001){~2~} = (11101){~2~} = 29*$.\r\n\r\nMutarea câştigătoare constă în a lua din cea de-a treia gramadă un număr de pietre egal cu:\r\n\r\n* $*17 - (17 ^ 29) = 17 - 12 = 5 = (00101){~2~}*$.\r\n\r\nDupă acest pas grămezile vor avea $4$, $8$, $12$ pietre. Ne aflăm astfel într-o stare cu suma $XOR$ egală cu $*0*$.\r\n\r\nh2(#aplicatii-nim). Aplicaţii ale strategiei NIM\r\n\r\nExemplificăm în continuare câteva probleme în care se foloseşte strategia jocului $NIM$.\r\n\r\nh3(#problema-1). Problema 1\r\n\r\nbq. Pe o tablă de şah, care are $N x M$ căsuţe, sunt plasaţi pe prima linie $N$ pioni albi şi pe ultima linie $N$ pioni negri. Fiecare dintre cei doi jucători poate muta un singur pion, care îi aparţine, un număr strict pozitiv de căsuţe în sus sau în jos, astfel încât să nu ajungă vreun pion alb să fie mai jos decât pionul negru de pe aceeaşi coloană. Pierde jucătorul care nu mai poate muta.\r\n\r\nh3. Soluţie\r\n\r\nAceastă problemă este o deghizare a jocului $NIM$, numărul de pătrăţele libere între pionul alb şi pionul negru de pe coloana $i$ putând fi considerat numărul de pietre din grămada $i$. Singura diferenţă este că se pot adăuga pietre la grămadă (existând posibilitatea mutării înapoi). Această problemă se rezolvă uşor, jucătorul care are strategie de câştig putând evita asemenea mutări. O astfel de mutare poate fi utilă numai pentru jucătorul care este într-o poziţie de pierdere. Când jucătorul care nu are strategie de câştig mută înapoi $x$ căsuţe, celălalt jucător va muta pionul propriu de pe aceeaşi coloanã cu $x$ căsuţe în faţă, astfel ajungându-se la aceeaşi stare cu cea existentă cu două mutări anterior (considerând diferenţa poziţiilor).\r\n\r\nh3(#problema-2). Problema 2 (Baraj ONI 1997)\r\n\r\nbq. Pe o linie sunt plasate la coordonate întregi $2 x N$ piese roşii şi albastre. Fiecare piesă roşie poate fi mutată în dreapta oricâte poziţii astfel încât să nu sară peste o piesă albastră, iar piesele albastre pot fi mutate oricâte poziţii la stânga astfel încât să nu depăşească vreo piesă roşie. Piesele vor alterna: roşu, albastru, roşu, albastru etc. Pierde jucătorul care nu mai poate muta.\r\n\r\nh3. Soluţie\r\n\r\nAceastă problemă poate fi, de asemenea, redusă la jocul $NIM$. Diferenţele poziţiilor perechilor de piese roşii şi albastre consecutive constituie numărul de pietre al grămezilor din jocul $NIM$.\r\n\r\nh3(#problema-3). Problema 3: \'Nim Game - Give Away!\':http://acm.mipt.ru/judge/problems.pl?problem=103 (El Judge)\r\n\r\nbq. Se consideră $N$ grămezi de pietre, jucătorii mută alternativ, fiecare jucător extrăgând oricâte pietre dintr-o singură grămadă. Cel care ia ultima piatră pierde jocul.\r\n\r\nh3. Soluţie\r\n\r\nStrategia acestui joc este similară cu cea aplicată în jocul $NIM$ cu câteva mici diferenţe. Jucătorul care are strategie de câştig în poziţia curentă în cadrul jocului $NIM$ face aceeaşi mutare pe care ar face-o în cazul jocului $NIM$, exceptând cazul în care această mutare lasă doar grămezi cu o singură piatră şi numărul acestor grămezi este par. În această situaţie, dacă ar trebui să distrugă o grămadă de $x$ pietre, jucătorul poate lua $x - 1$, iar dacă ar trebui să lase o singură piatră din grămada actuală, poate lua întreaga grămadă. Astfel, numărul de grămezi rămase va fi impar şi el nu va face ultima mutare.\r\n\r\nh2(#sprague-grundy). Numerele Sprague-Grundy\r\n\r\nJocurile care prezintă interes pentru jucători sunt acelea care necesită examinarea unui număr foarte mare de stări pentru determinarea strategiei de câştig, deoarece în caz contrar câştigătorul s-ar cunoaşte chiar de la început. Spre deosebire de aceştia, matematicienii sau informaticienii sunt interesaţi de determinarea unor strategii pentru astfel de jocuri. Toate jocurile imparţiale cu doi jucători cu informaţie totală pot fi reduse la jocul *$NIM$* care se joacă cu nişte grămezi virtuale, în care mutările posibile sunt extragerea oricâtor pietre dintr-o grămadă sau adăugarea oricâtor pietre la o grămadă (aşa cum am menţionat anterior, adăugarea de pietre la o grămadă nu complică analiza jocului).\r\n\r\nAfirmaţia anterioară constituie un rezultat al _Teoriei Sprague-Grundy_. _Roland Percival Sprague_ (1936) şi _Patrick Michael Grundy_ (1939) sunt doi matematicieni care s-au ocupat, independent, de teoria jocurilor imparţiale.\r\n\r\nÎn continuare, considerăm următorul enunţ:\r\n\r\nbq. Se consideră un graf aciclic care conţine în noduri câţiva pioni, jucătorii alternează la mutare şi fiecare poate muta câte un pion pe un arc care iese din nodul în care este situat pionul. Pierde jucătorul care nu mai poate muta.\r\n\r\nÎntrucât graful este aciclic, jocul este finit şi are întotdeauna un câştigător. Practic, acest joc este suma unor jocuri, mai precis suma a mai multor jocuri cu un singur pion pe graful aciclic. Jocul cu un singur pion poate fi analizat destul de uşor, fiecare nod al grafului putând fi colorat cu alb sau negru după cum există sau nu strategie de câştig dacă în nodul curent ar fi poziţionat pionul. Această colorare poate fi realizată uşor dacă se porneşte de la nodurile fără urmaş şi la fiecare pas se colorează câte un nod ai cărui urmaşi sunt deja coloraţi. Orice joc imparţial poate fi redus la un joc cu un singur pion. Nodurile sunt poziţiile jocului şi arcele grafului sunt mutările posibile din fiecare poziţie. Jocul iniţial poate fi şi el transformat, dar numărul de noduri creşte foarte mult (pentru $N$ pioni şi $M$ noduri, numărul de noduri din jocul transformat este {$N^M^$}) şi nu este practic să colorăm graful rezultat. Folosind teoria dezvoltată de Sprague şi Grundy, putem reduce complexitatea analizei jocului cu $N$ pioni la complexitatea analizei jocului cu un pion.\r\n\r\nVom introduce funcţia *$mex$* cu semnificaţia: $mex(S)$ este elementul minimal natural care nu aparţine mulţimii $S$. Pentru fiecare nod $x$ al grafului aciclic considerat, vom calcula valoarea funcţiei $gx = mex(gx{~1~}, gx{~2~}, …, gx{~k~})$, unde $x{~1~}$, $x{~2~}$, …, $x{~k~}$ sunt urmaşii nodului $x$ în graf. Pentru nodurile fără urmaşi $gx = 0$.\r\n\r\nAnalog jocului cu un singur pion, graful poate fi etichetat din aproape în aproape, pornind de la nodurile fără urmaşi. Observăm că, dacă $gx = 0$, în jocul cu un singur pion situat în nodul $x$ nu avem strategie de câştig, iar dacă $gx$ este diferit de $0$ avem strategie de câştig. Restul informaţiei ne ajută la determinarea unei strategii pentru jocul cu $N$ pioni. Observăm că putem reduce acest joc la jocul $NIM$ în care grămada virtuală asociată pionului $i$ are un număr de pietre egal cu valoarea $g$ a nodului în care este situat pionul $i$.\r\n\r\n_De ce este acest joc echivalent cu jocul NIM?_\r\n\r\nAşa cum la $NIM$ puteam lua oricâte pietre dintr-o grămadă, aici putem muta pionul dintr-un nod cu valoarea $g$ într-un nod astfel încât noua valoare pentru pionul $i$ poate fi orice număr de la $0$ la $g - 1$. Prin urmare, pentru a verifica dacă suntem într-o poziţie de câştig în jocul cu pionii, putem aplica strategia jocului $NIM$ şi obţinem că suntem într-o poziţie de câştig dacă suma $XOR$ a numerelor din nodurile ocupate de cei $N$ pioni este diferită de $0$. Această sumă se numeşte _funcţia Sprague-Grundy_: <tex> SG(i_{1}, ..., i_{n}) = g_{i_1} {\\mathbin{\\char`\\^}} g_{i_2} {\\mathbin{\\char`\\^}} g_{i_3} {\\mathbin{\\char`\\^}} ... {\\mathbin{\\char`\\^}} g_{i_n}</tex>.\r\n\r\nProblema se rezolvă acum uşor efectuând o sortare topologică a nodurilor grafului aciclic şi numerotând nodurile folosind funcţia $mex$.\r\n\r\nh2(#aplicatii-sg). Aplicaţii ale numerelor Sprague-Grundy\r\n\r\nÎn continuare, să studiem alte probleme ce se pot rezolva cu numerele $Sprague-Grundy$.\r\n\r\nh3(#problema-4). Problema 4: Joc (Bursele Agora 2003/2004, Runda 13)\r\n\r\nbq. Să se verifice existenţa unei strategii de câştig pentru un joc similar cu $NIM$ în care se poate lua dintr-o grămadă o piatră sau un număr prim de pietre.\r\n\r\nDacă determinăm valorile $Sprague-Grundy$ pentru grămezi de dimensiuni mici putem observa că se repeta o succesiune de numere: $0 1 2 3 0 1 2 3 ...$ Putem demonstra prin inducţie că această secvenţă se va repeta la nesfârşit. Pentru o grămadă de dimensiune $n$, valoarea asociată va fi $n modulo 4$. Pentru $0 ≤ n ≤ 3$ afirmaţia este adevărată. Vom presupune afirmaţia adevărată pentru toate valorile $m < n$. Să demonstrăm acum că este adevărată şi pentru $n$. Deoarece putem lua din $n$ pietre una, două sau trei pietre, mai rămâne valoarea $n modulo 4$ care nu este eliminată încă din valorile potenţiale asociate grămezii de dimensiune $n$. Vom arăta în continuare că această valoare nici nu va fi eliminată. Eliminarea ei ar însemna că putem lua din $n$ un număr $p$ de pietre şi atunci din $(n - p) modulo 4 = n modulo 4$, am avea: $p modulo 4 = 0$, dar $p$ este un număr prim, deci valoarea $Sprague-Grundy$ asociată unei grămezi de dimensiune $n$ este $n modulo 4$.\r\n\r\nh3(#problema-5). Problema 5: \'Stone game\':http://acm.mipt.ru/judge/problems.pl?problem=101 (El Judge)\r\n\r\nbq. Se consideră $K$ grămezi cu $n{~1~}, n{~2~}, ..., n{~K~}$ pietre fiecare. Când este rândul său, un jucător poate lua dintr-o gramadă $2^m^$ pietre. Jucătorul care ia ultima piatră câştigă. Restricţii: $K ≤ 50, n{~i~} ≤ 10^200^$.\r\n\r\nh3. Soluţie\r\n\r\nSă determinăm valorile $Sprague-Grundy$ pentru grămezi mici:\r\n\r\n$0 : 0;    1 : 1;    2 : 2;    3 : 0;    4 : 1;    5 : 2;    6 : 0$\r\n\r\nObservăm şi aici secvenţa repetitivă $0 1 2 0 1 2$, deci am putea trage concluzia că valoarea $Sprague-Grundy$ asociată unei grămezi de dimensiune $n$ este $n modulo 3$. Această afirmaţie este adevarată şi urmează aceeaşi demonstraţie ca în cazul problemei anterioare, iar restul $modulo 3$ pentru un număr cu $200$ de cifre este simplu de găsit determinând suma cifrelor numărului.\r\n\r\nh3(#problema-6). Problema 6: \'Stone game II\':http://acm.mipt.ru/judge/problems.pl?problem=102 (El Judge)\r\n\r\nbq. Se consideră $K$ grămezi de pietre cu $n{~1~}, n{~2~} ..., n{~K~}$ pietre. Un jucător poate lua dintr-o grămadă la mutarea lui un număr pozitiv de pietre, dar nu mai mult de jumătate din pietrele din grămadă. Jucătorul care nu mai poate muta pierde. Restricţii: $K ≤ 50, n{~i~} ≤ 100000$.\r\n\r\nh3. Soluţie\r\n\r\nNumărul $100000$ nu este foarte mare şi valorile $Sprague-Grundy$ pot fi determinate _off-line_ şi incluse în programul nostru sub formă de constante. Putem scrie pentru valori mici secvenţa $Sprague-Grundy$:\r\n\r\n$1 2 3 4 5 6 7 8 9 10 11 12 13 14$\r\n$0 1 0 2 1 3 0 4 2  5  1  6  3  7$\r\n\r\nPentru $n$ impar valoarea asociată este aceeaşi cu valoarea asociată lui $n/2$, şi pentru $n$ par valoarea asociată este $n/2$. Acest lucru se poate demonstra prin inducţie matematică.\r\n\r\nh3(#problema-7). Problema 7: Sticks (CEOI 2000)\r\n\r\nbq. Se consideră $n$ ({$n ≤ 10$}) rânduri de beţe pe o masă, cu $S{~i~}$ ({$S{~i~} ≤ 10$}) beţe aliniate pe fiecare rând şi doi jucători. Beţele de pe rândul $i$ sunt numerotate secvenţial de la $1$ la $S{~i~}$. Cei doi jucători mută alternativ. Fiecare mişcare constă în eliminarea a unu, două sau trei beţe de pe acelaşi rând. Beţele trebuie sã fie numerotate secvenţial, adică să fie consecutive. De exemplu, un rând are $10$ beţe şi primul jucător elimină beţele $4$, $5$, $6$, deci vor rămâne numai beţele $1$, $2$, $3$, $7$, $8$, $9$, $10$. Al doilea jucător poate lua la rândul său beţele $1$, $2$, $3$, dar nu beţele $3$, $7$, $8$ pentru că acestea nu sunt numerotate consecutiv (bineînţeles că există şi alte mutări valide). Câştigă jucătorul care ia ultimul băţ de pe masă.\r\n\r\nh3. Soluţie\r\n\r\nProblema generală are o soluţie ingenioasă care ţine seama de parităţile rândurilor, dar la această problemă, datorită mărginirii lui $S{~i~}$ ({$S{~i~} ≤ 10$}) nu este necesar să fim ingenioşi. Restricţia $S{~i~} ≤ 10$ ne ajută prin faptul cã numărul total de poziţii (dacă jucăm pe o singură gramadă), este $2^10^$. Vom reprezenta o poziţie printr-un întreg, iar dacă acel întreg are în codificarea lui binară pe poziţia $i$ un bit de $1$ înseamnă că el reprezintă un rând de beţe care conţine în el băţul numerotat cu $i$. Este uşor de realizat un graf aciclic al mişcărilor pentru un rând (graful este aciclic pentru că la fiecare mutare luăm beţe din configuraţie). Numerotăm fiecare poziţie cu numerele $Sprague-Grundy$, şi acum problema deciderii dacă suntem sau nu într-o poziţie câştigătoare devine banală. În problema iniţială trebuia să jucăm împotriva calculatorului şi să câştigăm. Putem realiza aceasta folosind mutarea câştigătoare prezentată la jocul $NIM$.\r\n\r\nh3(#problema-8). Problema 8: \'Joc\':problema/joc2 (Bursele Agora 2006)\r\n\r\nbq. Doi participanţi mănâncă alternant din nişte tablete de ciocolată după următoarele reguli:\r\n{*} taie o tabletă în două, tăietura trebuie să fie paralelă cu una din laturile tabletei şi trebuie să nu taie pătrăţelele de ciocolată;\r\n{*} pot să rupă şi să mănânce orice linie sau coloană de pătrăţele care nu se află pe marginea tabletei;\r\n{*} pot să rupă şi să mănânce toate patrăţelele de pe marginea tabletei, cu condiţia ca tableta rămasă să aibă cel puţin dimensiunea $1 x 1$.\r\nNiciuna dintre aceste trei mutări nu poate fi efectuată asupra unei tablete de dimensiune $1 x 1$. Pierde jucătorul care nu mai poate efectua nicio mutare. În fişierul de intrare se va afla numărul $N$ ({$1 ≤ N ≤ 100$}) de tablete, iar pe următoarea linie vor fi $N$ perechi de numere întregi care reprezintă dimensiunile tabletelor. În fişierul de ieşire se va afla un singur număr întreg reprezentând numărul mutărilor câştigătoare pentru primul jucător.\r\n\r\nh3. Soluţie\r\n\r\nPentru această problemă vom calcula matricea $SG{~i,j~}$ care reprezintă valoarea $Sprague-Grundy$ asociată unei tablete de dimensiuni $(i, j)$. Să vedem care este recurenţa care va satisface elementele matricei $SG$:\r\n\r\n<tex> SG_{i,j} = mex( \\underbrace{ \\underbrace{SG_{i,k} {\\mathbin{\\char`\\^}} SG_{i,j-k},}_{1 \\leq k < j} \\underbrace{SG_{k,j} {\\mathbin{\\char`\\^}} SG_{i-k,j},}_{1 \\leq k < i} }_{mutarea\\ \\^{i}nt\\^{a}i } </tex> <tex> \\underbrace{ \\underbrace{SG_{i,k} {\\mathbin{\\char`\\^}} SG_{i,j-k-1},}_{1 \\leq k < j - 1} \\underbrace{SG_{k,j} {\\mathbin{\\char`\\^}} SG_{i-k-1,j},}_{1 \\leq k < i - 1} }_{mutarea\\ a\\ doua} </tex> <tex> \\underbrace{ \\underbrace{SG_{i-2,j-2}}_{i > 2,\\ j > 2} }_{mutarea\\ a\\ treia} )</tex>\r\n\r\nAcum, pentru a calcula numărul de mutări câştigătoare efectuăm asupra fiecărei tablete din fişierul de intrare toate mutările posibile (care sunt cel mult $4 * 100 + 1$) şi facem suma $XOR$ a valorilor $Sprague-Grundy$ pentru restul tabletelor neimplicate în mutare şi a tabletelor rezultate din mutare. Pentru a calcula $SG{~i,j~}$ trebuie sã parcurgem cel mult $2 * i + 2 * j + 1$ valori obţinute. Astfel, algoritmul de determinare a valorilor matricei $SG$ are ordinul de complexitate $O(N^3^)$. Complexitatea algoritmului care determină numărul de mutări câştigătoare este $O(N^2^)$.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nAm văzut că aceste numere sunt folositoare pentru rezolvarea unor probleme de jocuri combinatorice. Chiar dacă numărul stărilor grafului nostru aciclic poate să fie foarte mare, putem să ne dăm seama, câteodată, din valorile mici de o regulă pe care o urmează numerele, sau măcar putem determina mai uşor configuraţii pentru care jocul are sau nu strategie de câştig, fapt care ne poate ajuta în descoperirea rezolvării generale.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\n* \'Joc3\':problema/joc3\r\n* \'Got Root?\':http://ipsc.ksp.sk/contests/ipsc2003/real/problems/g.php, _IPSC 2003_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* \'Colecţia GInfo\':http://www.ginfo.ro/\r\n* Mihai Oltean - _Programarea Jocurilor Matematice_, Editura Albastră, Cluj-Napoca, 1996\r\n* Thomas S. Ferguson - \'Game Theory Text\':http://www.math.ucla.edu/~tom/gamescourse.html\r\n* \'Interactive Mathematics\':http://www.cut-the-knot.com\r\n* \'Wolfram MathWorld\':http://www.mathworld.wolfram.com\r\n* \'IPSC\':http://ipsc.ksp.sk/\r\n',2044,'public',3590,NULL),('runda/happy-coding-2008/clasament','Clasament happy-coding-2008','2008-05-28 21:40:50','2008-05-28 21:40:50','h1. Clasament ==roundparam(round_id=\"happy-coding-2008\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"happy-coding-2008\")==',1,'round: happy-coding-2008',NULL,NULL),('blog/probleme-de-formula','Probleme \"de formula\"','2008-04-27 03:15:47','2008-11-15 13:41:14','Nu imi plac problemele \"de formula\"! Acestea sunt problemele de natura matematica din concursurile de programare, care ,de obicei, cer numararea unor configuratii si au ca raspuns o formula. Un motiv este lipsa de originalitate; e foarte probabil ca problema sa fi fost luata dintr-o carte de matematica. Alt motiv este ca nu testeaza partea de programare; de obicei programele ce rezolva astfel de probleme sunt usor de implementat (cateodata mai ai nevoie de numere mari...). Al treilea motiv e ca nu departajeaza elevii dupa valoarea sau ideile lor, ci mai mult \"randomizeaza\" rezultatele; unele formule sunt foarte greu de gasit pe cale matematica, dar sunt mai usor de ghicit.\r\n\r\nPentru a gasi formula de rezolvare, putem sa ne uitam la cateva rezultate mici si sa incercam sa ghicim cum arata formula ce le genereaza. O metoda banala ar fi sa variem fiecare parametru de intrare si sa vedem cum se modifica numarul cautat.\r\n\r\nIn problema mea \'aladdin2\':problema/aladdin2, se cere _numarul de colorari al celulelor unei table n X m cu alb sau negru astfel ca orice patrat de dimensiune 2x2 sa aiba exact doua patrate colorate alb si doua colorate negru_. Formula e banala $2^n^ + 2^m^ - 2$ si se observa imediat cu variarea dimensiunilor.\r\n\r\nIntr-o alta prolema data la un baraj se cerea _afisarea numarului de arbori partiali ai unui graf bipartit complet cu n noduri de o parte si m noduri de cealalta_. E mult mai simplu sa ghiciti de formula $n^n-1^ * m^m-1^$ decat sa mergeti pe calea rezolvarii oficiale care deduce formula prin folosirea \'codului Prufer\':http://en.wikipedia.org/wiki/Pr%C3%BCfer_sequence\r\n\r\nAdi Carcu imi zicea ca in \'99 au inceput sa se dea probleme la baraj pentru care rezultatul era o combinare. La a doua problema de genul asta, multi dintre concurenti au generat triunghiul lui Pascal si au cautat rezultatele din exemplu in el. Astfel ei au rezolvat o problema de dificultate medie in cateva minute.\r\n\r\nAlta problema interesanta e determinarea _numarului de permutari fara puncte fixe_. Problema are o solutie draguta folosind programare dinamica. Totusi poate fi rezolvata altfel urmand schimbarea rezultatului o data cu variarea lui $n$, si se observa destul de usor ca poate fi folosita formula $[n!/e + 1]$.\r\n\r\nIn 2006 s-a dat la lot determinarea \'numarului de acoperiri cu dominouri a unui diamant aztec\':http://mathworld.wolfram.com/AztecDiamond.html. Formula e foarte simpla $2^n(n+1)/2^$ insa demonstratia solutiei e foarte complicata - implica folosirea de permanenti apoi transformarea lor in determinanti folosind numere complexe. Probabil nici baietii din lotul national de matematica nu s-ar descurca cu o problema de genul asta. Surprinzator, mare parte din concurentii de la concursul respectiv au rezolvat-o perfect. Unul dintre cei care nu a rezolvat-o, a fost Adrian Vladu, care, in loc sa incerce sa ghiceasca formula, a incercat sa gaseasca rezolvarea matematica. Eu vazusem problema in faza de documentare pentru articolele mele cu \'probleme de acoperire\':implica-te/scrie-articole. Stiam ca nu poate fi rezolvata decat prin ghicirea rezultatului. De aceea inca imi pare rau ca am fost in comisie si  problema a fost folosita in concurs.\r\n\r\nCand participi la un concurs online te poti uita pe \'Online encyclopedia of integer sequences\':http://www.research.att.com/~njas/sequences/ Am folosit siteul asta pentru cateva probleme de la concursurile topcoder, si pentru o problema la Oni by Net. Sau poti sa cauti rezultatele pe Google :).\r\n\r\nRadu Stefan a folosit o metoda destul de misto pentru a rezolva urmatoarea problema:\r\n\r\n_Se cere sa se numere in cate moduri se pot aseza k regi pe tabla de sah de n x n astfel incat regii sa nu se atace._\r\n\r\nRadu s-a gandit ca solutia va fi un polinom in doua variabile $P(n, k)$, iar gradul polinomului nu va fi prea mare (parca el a presupus ca limita e 6). Astfel a generat folosind metoda backtracking solutiile pentru $n <= 6$ si $k <= 6$. A considerat coeficientii polinomului ca necunoscute si a rezolvat sistemul de ecuatii liniare date $P(n, k)$ si valorile obtinute prin algoritmul backtracking. Astfel luat punctaj maxim pe problema respectiva.\r\n\r\nProblema patrat(lot 2005), cerea _determinarea numarului de patrate magice de dimensiune 3x3 unde suma elementelor de pe linii, coloane si diagonale este $N$_. Solutia este un polinomul de gradul 4. Fie el $P(X) = aX^4^ + bX^3^ + cX^2^ + dX + e$. Numim $V{~1~}, V{~2~}, V{~3~}, V{~4~} si V{~5~}$ numarul de solutii pentru $N = 1, ..., 5$. Acum sistemul de care vorbeam mai sus va arata asa:\r\n\r\n$a + b + c + d + e = V{~1~}$\r\n$16a + 8b + 4c + 2d + e = V{~2~}$\r\n$81a + 27b + 9c + 3d + e = V{~3~}$\r\n$256a + 64b + 16c + 4d + e = V{~4~}$\r\n$625a + 125b + 25c + 5d + e = V{~5~}$\r\n\r\nPentru polinoame intr-o singura variabila mai puteti folosi metoda \'diferentelor divizate\':http://en.wikipedia.org/wiki/Divided_differences#Forward_differences care are o implementare foarte simpla.\r\n\r\nDaca formula e ceva mai complicata decat un polinom, putem sa speram ca sirul solutiilor e caracterizat de o recurenta liniara, si astfel putem folosi din nou rezolvarea de sisteme de ecuatii lineare pentru a afla coeficientii recurentei.\r\n\r\n\r\nSper ca am aratat ca propunerea unei *probleme de formula* este o idee *foarte proasta*! Si chiar daca va confruntati cu una veti putea sa o rezolvati rapid folosind micile trucuri expuse mai sus. Chiar daca si eu am propus o problema de formula, sper ca ele vor disparea din concursurile importante gen ONI, baraje si LOT.\r\n\r\nIn rest Paste Fericit si Bafta la ONI!',1490,'protected',3029,NULL),('utilizator/torque','Profil Torque','2008-05-07 10:27:39','2008-05-07 10:27:39','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',8201,'public',NULL,NULL),('blog/problema-saptamanii-pioni','Problema saptamanii - Pioni','2008-05-09 07:19:53','2008-11-15 13:41:14','_E timpul pentru o noua problema de rezolvat. Trimiteti-mi rezolvarile ca mesaj privat sau pe email la cosminn - at - gmail.com si in o saptamana voi pune o lista cu cei ce au rezolvat-o corect._\r\n\r\nSe dau patru pioni in plan. Ei sunt varfurile unui patrat. O mutare consta in saltul unui pion peste un alt pion astfel ca dupa mutare pozitia primului pion e simetrica cu pozitia initiala iar al doilea pion e centrul de simetrie. Determinati o modalitate de folosi acest tip de mutari pentru a pune pionii in varfurile unui patrat mai mare decat patratul initial.',1490,'protected',3043,NULL),('blog/a-trecut-si-olimpiada','A trecut si olimpiada','2008-05-12 06:52:01','2008-11-15 13:41:14','A trecut si anul asta olimpiada. Imi amintesc cum in fiecare an, dupa olimpiada, ma gandeam ca anul viitor va fi mult mai bine. Dar gandurile astea dispareau si la urmatoarea olipiada ma apucam de pregatiri abia cu o saptamana sau doua inainte de judeteana. Rezultatele erau la fel, adica lipseau. Asta pana cand am participat serios la concursul Bursele Agora, care m-a fortat intr-un fel sa fac o pregatire pe tot parcursul anului.\r\n\r\nPuteti citi cateva posturi despre concursul de anul asta pe \'blogul\':http://flmanea.blogspot.com/ lui Florin Manea, care a fost presedintele comisiei stiintifice anul acesta:\r\n* \'ONI 2008: Impresii\':http://flmanea.blogspot.com/2008/04/oni-2008-impresii.html\r\n* \'ONI 2008: Subiectele\':http://flmanea.blogspot.com/2008/04/oni-2008-subiectele.html\r\n* \'ONI 2008: Prefata\':http://flmanea.blogspot.com/2008/04/oni-2008-prefata.html\r\n\r\nS-a facut un mare pas in fata cu adaugarea medaliilor, ca si la celelalte olimpiade (mate, fizica). Cred ca acestea vor ajuta foarte mult la motivarea participantilor spre a isi creste nivelul de la an la an.\r\n\r\nEu regret faptul ca anul asta nu s-a facut Oni By Net. Era o traditie buna care e pacat ca a fost intrerupta. Chiar vorbeam cu ceva vreme inainte de concurs cu Catalin Francu si ne gandeam sa participam. Florin avea pe blogul lui un argument ca poti oricum sa rezolvi problemele offline. Se vede ca nu a participat la un Oni By Net, e foarte misto sa iti poti compara fortele cu concurentii de la concursul oficial. Nu se poate asemana experienta respectiva cu rezolvatul catorva probleme intr-o arhiva oarecare. Sper ca la anul sa fie reluata organizarea acestei parti a concursului. Din cate am inteles, Liviu Valsan ar fi vrut sa ajute la organizarea ei.\r\n\r\nFelicitari castigatorilor, iar celorlalti spor la munca si bafta mare la anul!',1490,'protected',3047,NULL),('utilizator/domino','Profil Mircea Pasoi','2006-11-24 15:55:10','2009-07-29 08:56:34','h2. Despre mine\r\n\r\n\'{!utilizator/domino?btn_viewmy_160x33.gif!}\':http://www.linkedin.com/in/mirceapasoi\r\n\r\n* Sunt membru fondator si vicepresedinte al Asociatiei infoarena\r\n* Membru in echipa \'.campion\':http://campion.edu.ro\r\n* Membru in Comisia Nationala de Informatica la ONI 2007, ONI 2008, ONI 2009, Lot Suceava 2007, Lot Alba 2007, Lot Iasi 2008, CEOI 2009\r\n* Membru in echipa \'USACO\':http://usaco.org care selecteaza si propune problemele pentru concursurile online USACO si pentru tabara de pregatire USAICO\r\n* Am fost la internship in perioada iulie-septembrie 2007 la Microsoft, Redmond \r\n* Am fost la internship in perioada iulie-septembrie 2008 la Google, Mountain View\r\n* Am fost la \"Surprize, Surprize\" si am primit un Renault Scenic din 2003 :)\r\n\r\nh2. Studii\r\n\r\n* 2006-2009: Universitatea Bucuresti, Facultatea de informatica\r\n* 1998-2006: Colegiul National \"I. L. Caragiale\" Ploiesti (Matematica-Informatica)\r\n\r\nh2. Trivia\r\n\r\n* Am lansat \'cel mai tare motor de cautare de joburi!\':http://balaur.ro impreuna cu == User(user=\"wickedman\" type=\"tiny\") == si == User(user=\"silviug\" type=\"tiny\") ==\r\n* Am predat informatica la ICHB in perioada 2007-2008\r\n* Am participat la organizarea concursurilor \"Stelele Informaticii\" in 2006-2009\r\n\r\nh2. Premii (cele mai importante)\r\n\r\n* 2007, Noiembrie - Locul 8 la Finala TopCoder Collegiate Challenge, Orlando, USA\r\n* 2007, Martie - Finalist la ACM world finals in Tokyo\r\n* 2006, Noiembrie - Finalist TopCoder Collegiate Challenge, San Diego, USA\r\n* 2006, Octombrie - Locul 2 la regionala ACM South-Eastern, Bucuresti, Romania \r\n* 2006, August - Aur (locul 7) la IOI, Merida, Mexico\r\n* 2006, Iulie - Argint la CEOI, Vrsar, Croatia \r\n* 2006, Iunie - Invitat la tabara de pregatire a lotului america (USAICO), Colorado Springs, USA\r\n* 2005, August - Argint la IOI, Nowy Sacz, Polonia\r\n* 2004, Iulie - Argint la BOI, Plovdiv, Bulgaria\r\n* 2003, 2005, 2006 - Locul I la ONI\r\n\r\nh2. Publicatii\r\n\r\n* 2006 \"Fundamentele programarii - culegere de probleme pentru clasa a 11-a\", autori Dana Lica si Mircea Pasoi, Editura L&S Info-mat, ISBN 973-88073-2-1\r\n* 2005 \"Fundamentele programarii - culegere de probleme pentru clasa a 10-a\", autori Dana Lica si Mircea Pasoi, Editura L&S Info-mat, ISBN 973-86022-9-7\r\n* 2005 \"Fundamentele programarii - culegere de probleme pentru clasa a 9-a\", autori Dana Lica si Mircea Pasoi, Editura L&S Info-mat, ISBN 973-7658-02-7\r\n* 2005, Decembrie \"Rotatie minim lexicografica\", GInfo, vol. 15/8\r\n* 2005, Octombrie \"Ghid complet pentru concursurile de informatica\", GInfo, vol. 15/6 \r\n\r\nh2. Mentori\r\n\r\n* == User(user=\"danal\" type=\"tiny\") ==\r\n* == User(user=\"cosmin\" type=\"tiny\") ==\r\n* == User(user=\"mugurelionut\" type=\"tiny\") ==\r\n',1,'protected',NULL,NULL),('blog/viva-las-vegas','Viva Las Vegas','2008-05-21 09:26:43','2008-11-15 13:41:14','Saptamana trecuta s-a desfasurat la Las Vegas etapa finala a concursului TopCoder Open. Am trecut si eu pe acolo ca sa ma intalnesc cu romanii ce au ajuns la aceasta etapa a concursului.\r\n\r\n!<{margin: 10px; margin-left: 0; border: 1px solid gray;}blog/viva-las-vegas?tco.jpg 70%!:http://infoarena.ro/blog/viva-las-vegas?action=download&file=tco.jpg Ii vedeti in poza alaturata de la stanga la dreapta pe \'Adrian Carcu\':http://www.topcoder.com/tc?module=MemberProfile&cr=278342 care, fiind veteran al acestor concursuri, a fost reviewer la competitia de design, dand note participantilor, pe mine ca musafir neinvitat :), \'Lazar Lucian\':http://www.topcoder.com/tc?module=MemberProfile&cr=10348862 , finalist la concursul de design software, \'Liviu Ciortea\':http://www.topcoder.com/tc?module=MemberProfile&cr=8593420 , finalist la concursul de algoritmi, romanul cu cel mai mare rating pe topcoder la algoritmica, \'ratonul_bolnav\':http://www.topcoder.com/tc?module=MemberProfile&cr=22657109 , concurent la concursul maraton si \'Vlad Dumitriu\':http://www.topcoder.com/tc?module=MemberProfile&cr=13298470 , finalist al concursului de design grafic.\r\n\r\nDespre Lucian ati mai putut citi in acest \'post\':blog/romanii-la-disneyworld-partea-a-doua in care ne spunea detalii legate de participarea lui la TopCoder Collegiate Challenge. La acest concurs Luci s-a descurcat \"ceva mai bine\", obtinand locul doi si un premiu de *10.000$*. Felicitari! Sunt mandru de Lucian in mod special pentru ca el a fost colegul de facultate cu care am baut o bere in prima zi de scoala in Cluj.\r\n\r\nVlad participa a doua oara la finala concursului de design grafic si ati mai putut citi despre el in acest \'post\':http://infoarena.ro/blog/romanii-la-disneyworld-partea-intai de pe blogul infoarena.\r\n\r\nLiviu e la prima participare la un turneu final, dar l-am mai laudat \'aici\':blog/imaginecup ca fiind finalist al concursului ImagineCup organizat de Microsoft.\r\n\r\nCe am mai retinut de la concurs e ca finala de algoritmica a fost foarte disputata si Tomek a castigat-o dupa o pauza de 4 ani. Puteti citi mai multe pe \'blogul concursului\':http://www.topcoder.com/tc?module=Static&d1=tournaments&d2=tco08&d3=blog\r\n\r\nSi daca tot am avut un titlu ademenitor sa va spun si cateva impresii legate de Orasul Pacatelor. Las Vegasul e  impresionant, au reusit americanii astia sa construiasca o metropola in mijlocul unui desert. Totul mi s-a parut putin fals si menit sa iti scoata cat mai multi bani din buzunar. Pe strada sunt o gramada de oameni care incearca sa iti paseze numere de stripteoze, dar pentru ca legea nu ii lasa sa te abordeze direct, ei pocnesc din degete si incearca sa iti dea fluturase cu numere de fete. In interiorul cazinourilor sunt drumuri lungi printre mese de ruleta si automate cu jocuri, pentru a creste cat mai mult sansele de a fi prins in mrejele lor. De asemenea lumina e artificiala si nu sunt geamuri spre exterior, iar ceasuri nu se prea gasesc. Totul pentru a face ca jucatorii sa piarda notiunea timpului. Singurul ceas ce l-am vazut in cazino era in magazinul de ceasuri Swatch :). Anul trecut am fost in vizita si apoi le ziceam la prieteni ca e un oras ce merita sa il vizitezi doar o data, dar se pare ca am trecut peste impresia putin negativa si l-am vizitat si a doua oara. \r\n\r\nPuteti vedea cateva poze \'aici\':http://picasaweb.google.com/LiviuEfEr/LasVegasMai2008 sau \'aici\':http://picasaweb.google.com/vladut.mail/TCO08Part5LastOne\r\n\r\nFelicitari inca o data finalistilor si poate ne vedem si la anul!',1490,'protected',3062,NULL),('newsletter/blog-hc2007','Blog, Concurs Happy Coding, interviuri M. Patrascu & C. Francu','2007-11-08 21:15:03','2009-01-20 09:42:36','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nAm incercat sa inghesui in subiectul de e-mail cat mai multe\r\nlucruri marfa la care am lucrat in ultima vreme...\r\n\r\ninfoarena are multe noutati pentru tine.  Aseaza-te bine pe scaun\r\nsi citeste pana la capat!\r\n\r\nPentru inceput, te invitam la un nou concurs, de luuuunga durata:\r\n\r\np{padding-left: 2em;}. Happy Coding 2007\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Incepe:      Sambata, 10 noiembrie, ora 10:00\r\n    Se incheie:  Duminica, 18 noiembrie, ora 24:00\r\n    Durata:      7.5 zile!\r\n\r\np{padding-left: 2em;}. Peste 20+ probleme si evaluator deschis pe toata\r\n    durata concursului!\r\n\r\np{padding-left: 2em;}. \'happy-coding-2007\':happy-coding-2007\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\r\nh2.  Avem blog! \r\n\r\nCosmin Negruseri a deschis blog-ul infoarena tocmai din California,\r\nde la sediul Google Inc. :)\r\n\r\nIntra pe blog, citeste, aboneaza-te la feed si comenteaza alaturi\r\nde ceilalti infoarenauti.  Cosmin are resurse nelimitate de\r\npuzzle-uri, interviuri, prieteni destepti, noutati remarcabile din\r\nlumea informaticii si a industriei IT.\r\n\r\n\'blog\':blog\r\n\r\nDupa numai o luna de activitate, blog-ul infoarena numara deja 26 de\r\npost-uri!\r\n\r\nCosmin facut parte din comisiile de organizare a multor competitii\r\nde informatica, printre care TopCoder Open \'07, Google Code Jam \'06,\r\npreONI & o gramada concursuri infoarena, loturile de informatica\r\n2005 & 2006, ONI, .campion, Bursele Agora si Grigore Moisil.\r\nA publicat articole in GInfo & infoarena si a fost numit \'coder of\r\nthe month\' de catre TopCoder in 2004.\r\n\r\nCiteste mai multe despre Cosmin aici:\r\n\'http://infoarena.ro/utilizator/Cosmin\':http://infoarena.ro/utilizator/Cosmin\r\n\r\nh2.  Happy Coding 2007 \r\n\r\nMugurel Ionut Andreica, Florin Manea si Adrian Diaconu te invita\r\nla a 3-a editie a concursului Happy Coding!\r\n\r\nDaca nu stiai deja, Happy Coding inseamna sa rezolvi probleme\r\nfrumoase, cu zambetul pe buze, fara griji si fara stresul obisnuit\r\nal competiilor de informatica.\r\n\r\nAi peste o saptamana (!) la dispozitie sa rezolvi 20+ probleme\r\nde dificultate variata.  Evaluatorul infoarena este alaturi de tine\r\nla fiecare solutie trimisa.  Vei afla imediat daca ai rezolvat\r\nproblema sau daca trebuie sa incerci din nou...\r\n\r\nPe tot parcursul concursului poti sa urmaresti evolutia clasamentului\r\nsi sa ceri lamuriri pe forum.\r\n\r\nCa si in editiile anterioare, majoritatea problemelor sunt propuse\r\nde Mugurel Ionut Andreica (peste 20 de probleme!!!), de data aceasta\r\najutat de catre Mihai Stroe si Florin Manea.\r\n\r\nMugurel Ionut Andreica este printre putinii oameni normali care au\r\nabsolvit Facultatea de Automatica si Calculatoare, UPB, cu media\r\n...umm 10 (!) liceul cu media 9.99 si au fost in acelasi timp sefi de\r\npromotie in scoala generala!  :)   Si asta e de-abia inceputul...\r\n\r\nCiteste mai multe pe pagina lui de profil:\r\n ==User(user=\"mugurelionut\" type=\"link\")== \r\n\r\nh2.  Interviuri cu Mihai Patrascu si Catalin Francu\r\n\r\nCosmin, gazda ta pe blog-ul infoarena, a intervievat doi dintre\r\ncei mai cunoscuti si mai respectati fosti olimpici romani, ajunsi\r\ndeparte prin lume cu treburilor lor... :)\r\nEste vorba de Mihai Patrascu si Catalin Francu!\r\n\r\nInterviurile au fost publicate pe blog si ne ajuta pe toti sa\r\nintelegem ce inseamna sa fii talentat si sa muncesti pe masura.  :)\r\n\r\nCiteste interviurile si nu te sfii sa lasi un comentariu lui\r\nCosmin si prietenilor sai.\r\n\r\nMihai Patrascu\r\n\r\np{padding-left: 2em;}. Mihai Patrascu are printre cele mai bune rezultate la\r\n    olimpiadele internationale la informatica dintre romani. A luat\r\n    premiul I la Olimpiada nationala de informatica din clasa a 4a\r\n    (concurand la clasa a 5a) pana intr-a 12a. La olimpiada\r\n    internationala de informatica a luat doua medalii de aur si\r\n    una de argint (in 2001 a fost locul II la IOI).\r\n\r\np{padding-left: 2em;}. In 2005 a luat premiul \'Outstanding Male Undergraduate Award\'\r\n    pe Statele Unite si Canada.\r\n\r\np{padding-left: 2em;}. Interviu, Partea I\r\n    \'blog/interviu-mihai-patrascu-partea-intai\':blog/interviu-mihai-patrascu-partea-intai\r\n\r\np{padding-left: 2em;}. Interviu, Partea II\r\n    \'blog/interviu-mihai-patrascu-partea-a-doua\':blog/interviu-mihai-patrascu-partea-a-doua\r\n\r\nCatalin Francu\r\n\r\np{padding-left: 2em;}. Catalin este cunoscut in lumea celor pasionati de informatica\r\n    prin cartea \"Psihologia concursurilor de programare\", o carte\r\n    plina de probleme frumoase si deschizatoare de drumuri la vremea\r\n    ei, si prin \"lista lu\' Francu\", o lista de discutii pe email,\r\n    unde cativa dintre cei ce au ajuns apoi olimpici internationali\r\n    la informatica ai Romaniei rezolvau si discutau probleme.\r\n\r\np{padding-left: 2em;}. In lumea lingvistilor este cunoscut prin proiectul\r\n    \'http://dexonline.ro/\':http://dexonline.ro/  Acesta [...] contine intreg Dictionarul\r\n    Explicativ al limbii romane si alte dictionare.  In timpul\r\n    liceului, Catalin a luat o medalie de argint la IOI, iar in\r\n    timpul facultatii s-a clasat pe locul 7 la etapa finala a\r\n    concursului ACM ICPC cu echipa reprezentanta a MIT.  De asemenea\r\n    a facut parte din comisia stiintifica a Olimpiadei de\r\n    Informatica a Europei Centrale din 2000 care s-a desfasurat la\r\n    Cluj.  Dupa terminarea facultatii Catalin a lucrat 4 ani ca\r\n    programator la Google Inc.\r\n\r\np{padding-left: 2em;}. Interviu, Partea I\r\n    \'blog/interviu-cu-catalin-francu\':blog/interviu-cu-catalin-francu\r\n\r\np{padding-left: 2em;}. Interviu, Partea II\r\n    \'blog/interviu-cu-catalin-francu-partea-a-doua\':blog/interviu-cu-catalin-francu-partea-a-doua\r\n\r\nUrmareste blog-ul infoarena pentru alte interviuri precum acestea!\r\n\r\nh2.  Urmeaza preONI 2008! \r\n\r\nIn curand vom anunta editia 2008 a concursului preONI.\r\n\r\nEchipa preONI, condusa de Mircea Pasoi lucreaza din greu pentru o\r\nnoua editie, mai frumoasa, mai mare si cu mult mai multe premii\r\npentru tine!\r\n\r\nUrmareste blog-ul infoarena si vei afla din timp. ;)\r\n\r\nh2.  Prima data la infoarena? \r\n\r\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\r\nRamai alaturi de noi.  Te ajutam sa devii olimpic!\r\n\r\nSucces!\r\nEchipa infoarena\r\n\r\nh2.  Mesaj nesolicitat? \r\n\r\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\r\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\r\n\r\n',1490,'protected',NULL,NULL),('newsletter/preoni-2008/runda-1','preONI 2008, Runda 1 - acum si pentru gimnaziu!','2007-11-21 18:05:57','2009-01-20 09:43:09','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nIncepe o noua editie preONI, concursul cu premii mari si finala live\r\ncare te pregateste pentru Olimpiada Nationala de Informatica.\r\n\r\nAnul acesta avem vesti bune pentru elevii de gimnaziu si profesorii\r\nlor:  preONI 2008 are o grupa separata pentru clasele V-VIII, si\r\nlocuri rezervate la runda finala.  In plus, avem premii mai multe\r\nsi mai mari!  ;)\r\n\r\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Runda #1 se desfasoara...\r\n\r\np{padding-left: 2em;}. Duminica, 25 noiembrie 2007, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\r\nVezi pagina concursului: \'preoni-2008\':preoni-2008\r\n\r\nh2.  Atentie! Concurs cu rating! \r\n\r\nParticiparea la aceasta runda iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te poate aduce mai aproape te varful clasamentului.\r\n==NewsletterRating(username=\"%username%\")==\r\nCiteste despre rating: \'documentatie/rating\':documentatie/rating.\r\n\r\nh2.  Concursul preONI \r\n\r\npreONI, concursul de marca al comunitatii infoarena, este dedicat\r\nelevilor de liceu si gimnaziu ce se pregatesc pentru Olimpiada\r\nNationala de Informatica.\r\n\r\nConcursul este impartit in 4 grupe de varsta:  clasele V-VIII, clasa\r\na IX-a, clasa a X-a si clasele XI-XII.  Se organizeaza 4 runde online\r\nde calificare.  In urma acestora, cei mai buni de la fiecare grupa\r\nsunt invitati la o runda finala.\r\n\r\nIn cadrul unei runde vei avea de rezolvat 3 probleme in 4 ore.\r\nProblemele sunt de natura algoritmica si de dificultate similara\r\ncelor de la ONI.\r\n\r\nOferim premii substantiale acelor concurenti care se claseaza pe\r\nprimele locuri la runda finala.\r\n\r\nEditia 2008 a concursului preONI se desfasoara sub atenta\r\nsupraveghere a lui Mircea Pasoi, in calitate de contest director.\r\n\r\nPe pagina concursului ( \'preoni-2008\':preoni-2008 ) vei gasi\r\ninformatii despre cum participi, cine propune probleme, premii,\r\nregulamentul concursului samd.\r\n\r\nh2.  S-a incheiat Happy Coding 2007 \r\n\r\nDupa 25 de probleme frumoase si un timp de lucru de peste o\r\nsaptamana, maratonul Happy Coding 2007 s-a incheiat.\r\n214 concurenti au trimis solutii la probleme si au urmarit in timp\r\nreal evolutia clasamentului.\r\n\r\nMugurel Ionut Andreica, Adrian Diaconu si Florin Manea, in calitate\r\nde organizatori ai concursului Happy Coding felicita toti cei 214\r\nparticipantii si in special pe cei clasati pe primele locuri.\r\n\r\nIata cum arata varful clasamentului:\r\n\r\np{padding-left: 2em;}. Loc    Nume                       Punctaj (max 2500)\r\n    ~ ~ ~  ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~  ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n       1   Bogdan Tataroiu            2400\r\n       2   Victor Rusu                2300\r\n       2   Liviu Ciortea              2300\r\n       4   Catalin Tiseanu            2200\r\n       4   Gheorghe Cosmin            2200\r\n       4   Mircea Pasoi               2200\r\n       4   Andrei Grigorean           2200\r\n    ~ ~ ~  ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~  ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\r\nVezi clasamentul intreg:\r\n\'happy-coding-2007/clasament\':happy-coding-2007/clasament\r\n\r\nVezi solutiile oficiale:\r\n\'happy-coding-2007/solutii\':happy-coding-2007/solutii\r\n\r\nh2.  Interviuri cu Mihai Patrascu si Catalin Francu\r\n\r\nDaca nu esti la curent cu noutatile infoarena, afla ca ne-am facut\r\nblog: \'blog\':blog\r\n\r\nCosmin Negruseri, gazda ta pe blog-ul infoarena, a intervievat doi\r\ndintre cei mai cunoscuti si mai respectati fosti olimpici romani,\r\najunsi departe prin lume cu treburilor lor... :) Este vorba de Mihai\r\nPatrascu si Catalin Francu!\r\n\r\nInterviurile au fost publicate pe blog si ne ajuta pe toti sa\r\nintelegem ce inseamna sa fii talentat in informatica si sa muncesti\r\npe masura.  :)\r\n\r\nCiteste interviurile si nu te sfii sa lasi un comentariu lui Cosmin\r\nsi invitatilor sai.\r\n\r\nMihai Patrascu\r\n\r\np{padding-left: 2em;}. Mihai Patrascu are printre cele mai bune rezultate la olimpiadele\r\n    internationale la informatica dintre romani. A luat premiul I la\r\n    Olimpiada nationala de informatica din clasa a 4a (concurand la\r\n    clasa a 5a) pana intr-a 12a. La olimpiada internationala de\r\n    informatica a luat doua medalii de aur si una de argint (in 2001\r\n    a fost locul II la IOI).\r\n\r\np{padding-left: 2em;}. In 2005 a luat premiul \'Outstanding Male Undergraduate Award\' pe\r\n    Statele Unite si Canada.\r\n\r\np{padding-left: 2em;}. Interviu, Partea I\r\n    \'blog/interviu-mihai-patrascu-partea-intai\':blog/interviu-mihai-patrascu-partea-intai\r\n\r\np{padding-left: 2em;}. Interviu, Partea II\r\n    \'blog/interviu-mihai-patrascu-partea-a-doua\':blog/interviu-mihai-patrascu-partea-a-doua\r\n\r\nCatalin Francu\r\n\r\np{padding-left: 2em;}. Catalin este cunoscut in lumea celor pasionati de informatica\r\n    prin cartea \"Psihologia concursurilor de programare\", o carte\r\n    plina de probleme frumoase si deschizatoare de drumuri la vremea\r\n    ei, si prin \"lista lu\' Francu\", o lista de discutii pe email,\r\n    unde cativa dintre cei ce au ajuns apoi olimpici internationali\r\n    la informatica ai Romaniei rezolvau si discutau probleme.\r\n\r\np{padding-left: 2em;}. In lumea lingvistilor este cunoscut prin proiectul\r\n    \'http://dexonline.ro/\':http://dexonline.ro/  Acesta [...] contine intreg Dictionarul\r\n    Explicativ al limbii romane si alte dictionare.  In timpul\r\n    liceului, Catalin a luat o medalie de argint la IOI, iar in\r\n    timpul facultatii s-a clasat pe locul 7 la etapa finala a\r\n    concursului ACM ICPC cu echipa reprezentanta a MIT.  De asemenea\r\n    a facut parte din comisia stiintifica a Olimpiadei de Informatica\r\n    a Europei Centrale din 2000 care s-a desfasurat la Cluj.  Dupa\r\n    terminarea facultatii Catalin a lucrat 4 ani ca programator la\r\n    Google Inc.\r\n\r\np{padding-left: 2em;}. Interviu, Partea I\r\n    \'blog/interviu-cu-catalin-francu\':blog/interviu-cu-catalin-francu\r\n\r\np{padding-left: 2em;}. Interviu, Partea II\r\n    \'blog/interviu-cu-catalin-francu-partea-a-doua\':blog/interviu-cu-catalin-francu-partea-a-doua\r\n\r\nUrmareste blog-ul infoarena pentru alte interviuri precum acestea!\r\n\r\nh2.  Prima data la infoarena? \r\n\r\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\r\nRamai alaturi de noi.  Te ajutam sa devii olimpic!\r\n\r\nSucces!  Echipa infoarena\r\n\r\nh2.  Mesaj nesolicitat? \r\n\r\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\r\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\r\n\r\n\r\n',1490,'protected',NULL,NULL),('blog/problema-saptamanii-pion-solutie','Problema saptamanii - Pioni (Solutie)','2008-05-26 09:38:31','2008-11-15 13:41:14','Problema Pioni a fost rezolvata de Radu Cebanu, \'Andrei Grigorean\':utilizator/wefgef si \'Stefan Istrate\':utilizator/stef2n . Cinste lor, campionilor :)\r\n\r\nVa reamintesc problema:\r\n\r\n_Se dau patru pioni in plan. Ei sunt varfurile unui patrat. O mutare consta in saltul unui pion peste un alt pion astfel ca dupa mutare pozitia primului pion e simetrica cu pozitia initiala iar al doilea pion e centrul de simetrie. Determinati o modalitate de folosi acest tip de mutari pentru a pune pionii in varfurile unui patrat mai mare decat patratul initial._\r\n\r\nSolutia ei este destul de simpla: Presupunem prin absurd ca putem construi un patrat mai mare. Datorita faptului ca mutarile sunt simetrice, construirea unui patrat mai mare e echivalenta cu construirea unui patrat mai mic. Luam o grila laticeala ce are punctele (0,0), (1, 0), (1, 1) si (0, 1) in varfurile patratului nostru. Este evident orice mutare va pune punctele in coordonate intregi pe aceasta grila. De aici rezulta ca nu putem construi un patrat de latura mai mica decat 1. Astfel presupunerea noastra initiala este falsa si *nu putem construi un patrat mai mare decat cel initial*.',1490,'protected',3095,NULL),('utilizator/cata00','Profil cata00','2008-05-26 22:15:38','2008-05-26 22:15:38','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',8260,'public',NULL,NULL),('blog/cplusplus-introducere-in-standard-template-library','C++, Introducere in Standard Template Library','2008-05-26 23:15:19','2008-11-15 13:41:14','_Imi face placere sa va anunt aparitia la editura ALL a carti \"C++, Introducere in Standard Template Library\" a carui autor este domnul profesor \'Constantin Galatan\':http://campion.edu.ro/team.php?id=19 de la Colegiul National \"Liviu Rebreanu\" din Bistrita. Il cunosc inca de pe vremea liceului pe domnul Galatan care e un profesor de informatica profesionist si dedicat. Mi-as dori ca toti profesorii de informatica din tara sa puna atata suflet in meseria lor. El a fost organizator a partii de informatica a concursului interjudetean \"Grigore Moisil\" in 2006, a fost in comisiile stiintifice la ONI 2006, ONI 2007, iar in 2008 la ONI fost seful comisiei stiintifice la clasa a 9-a, a facut de asemenea parte din comisie la loturile din 2007 si va face parte din comisia loturilor din 2008, a facut parte din echipa .campion in 2006, 2007 si 2008. De asemenea inaintea cartii pe care v-am anuntat-o, a mai publicat cartea \"Secrete C++\":http://www.secretecpp.ro/ Va las mai departe cu cateva cuvinte din partea domnului profesor:_\r\n\r\nLa sugestia lui Cristian George Strat de a informa membrii infoarena despre aparitia unei carti de STL, m-am decis in cele din urma sa scriu cateva cuvinte, legate nu doar de STL.\r\n\r\nCred ca nu voi surprinde pe nimeni daca afirm ca ceea ce se petrece pe infoarena se urmareste cu mult interes, nu numai de catre elevi si studenti, ci si de catre alti oameni, printre care multi profesori. Acestia din urma nu activeaza pe forum, insa nu din cauza lipsei de interes. Este mai degraba intelegerea faptului ca pe infoarena elevii si studentii trebuie sa se simta in largul lor, sa discute liber. Desi s-ar putea ca unii sa ma contrazica, eu cred ca in momentul in care un profesor intervine pe un fir de discutie, exista probabilitatea ca o anumita stanjeneala sa se faca simtita.\r\n\r\nInfoarena este acum un fenomen care-si manifesta influenta pozitiva asupra celor care studiaza informatica. Ca unul dintre cei care lucreaza efectiv cu elevi ai claselor de mate-info, simt ajutorul tot mai puternic al infoarenei. Nu de la bun inceput l-am simtit. Pana anul trecut, trebuie sa spun ca imi convingeam cu greutate elevii sa intre pe infoarena ca sa participe de pilda, la concursuri. Cineva chiar mi-a spus odata: \"domunule profesor, ce rost mai are sa intru pentru 0 sau 10 puncte ?. Sunt prea grele problemele\". Am fost nevoit sa admit acest lucru. Chiar pentru copiii cu performante onorabile: calificari la nationale sau mentiuni la ONI, problemele de pe infoarena au fost de multe ori prea dificile. Desigur ca nivelul ridicat de dificultate a contribuit mult la formarea elitelor, a celor super pregatiti, dar hai sa vedem cati elevi super pregatiti avem in tara? Treizeci ? Patruzeci ?\r\n\r\nExista o categorie de elevi la sectiile de mate-info, sa-i spunem prin abuz de limbaj \"patura mijlocie\", formata din persoane cu multe calitati. Numarul lor este de ordinul sutelor, poate chiar a miilor in aceasta tara. Acesti copii merita tot efortul nostru. Din randurile lor se pot ivi adevarati olimpici iar in viitor, informaticieni valorosi. Au insa nevoie de o mana de ajutor ferma care sa-i sustina si sa-i ridice in stratosfera performantei.\r\n\r\nUltimele initiative ale infoarenei: \"Arhiva Educationala\", accesul liber la sursele unor probleme, sectiuni de concurs pentru cei mici, si evident forumul, sunt veriga lipsa, legatura dintre infoarena si multimea de elevi.\r\n\r\nCand intru acum in laborator si gasesc cinci, pana la cincisprezece copii care isi cauta ceva de facut pe infoarena, realizez ca cineva mi-a intins si mie o mana in munca cu acesti elevi.\r\n\r\nIn final, revin la cartea de STL, \"C++. Introducere in Standard Template Library\" pe care am publicat-o la editura ALL. Lucrarea poate fi utilizata atat ca tutorial cat si ca referinta completa STL. Este de folos celor care utilizeaza deja STL dar vor sa se perfectioneze, dar si incepatorilor. Contine si un capitol special de lucru cu sabloane in C++. Informatii suplimentare gasiti \'aici\':http://www.all.ro/detail.asp?idtitlu=3973\r\n\r\nTucu Galatan\r\n',1490,'protected',3096,NULL),('limeeval','LimeEval : Evaluator pe Windows Free','2008-03-16 12:23:00','2008-05-27 06:37:09','*Aceasta pagina e in constructie*\r\n\r\nh1=. *LimeEval*\r\n\r\nh5=. *Aceasta pagina are nevoie de o rescriere totala, pentru a fi actuala cu versiunea curenta a evaluatorului, corectat de buguri si cu new features. Pagina va fi rescrisa la lansarea versiunii 1.0*\r\n\r\nSunt ocupat cu bac-ul acuma, nu mai am timp sa curat sursa si sa o pun la liber, dar dupa BAC, am sa fac niste documentatie, si instructiuni de utilizare videouri etc.. si o sa lansez proiectul ca Open Source\r\n\r\nUltimul build e din /05/26, modificari la autodetectarea idurilor si functii de curatare. Enjoy.\r\n\r\nh3. {\'LimeEval - build 0.9.5.26 (build 0.9.5.26)\':limeeval?lime_v0.9.5.26.zip}',1476,'public',NULL,NULL),('happy-coding-2008/clasament','Clasament Happy Coding 2008','2008-05-30 20:12:30','2008-05-30 20:12:30','h1. Happy Coding 2008\r\n\r\n== Rankings(rounds=\"happy-coding-2008\") == \r\n\r\n\'*&rarr; Monitor de evaluare pentru Happy Coding*\':monitor?round=happy-coding-2008\r\n',1,'protected',NULL,NULL),('utilizator/dexterelu','Profil dexterelu','2008-06-02 18:00:47','2008-06-02 18:00:47','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',8299,'public',NULL,NULL),('blog/certificari','La ce folosesc certificarile','2008-06-05 04:08:55','2008-11-15 13:41:14','In timpul facultatii aveam colegi care se intrebau daca diverse certificari, cum ar fi cele date de Microsoft sau Sun, sunt utile intr-un CV. Eu nu am crezut niciodata ca ar fi bune sau folositoare. Mi s-au parut o modalitate relativ simpla de a mai scrie o linie in CV daca el e cam gol.\r\n\r\nAcum sunt si mai convins de inutilitatea lor, nu conteaza deloc ca apare o certificare sau alta, sau chiar zece certificari in CV. Este mult mai importanta experienta ta, proiectele misto la care ai lucrat decat faptul ca ai studiat cateva zile pentru un examen grila unde inveti diverse detalii exoterice ale limbajului sau tehnologiei in care te certifici. Cand te angajezi undeva esti testat de obicei destul de bine pe partea tehnica si sunt si alte chestii importante cum ar fi abilitatile de comunicare, faptul ca ai sau nu o certificare va fi probabil ultimul lucru la care se va uita cineva.\r\n\r\nLa Google s-a incercat mai demult abordarea stiintifica a \'problemei angajarii\':http://www.guardian.co.uk/technology/2007/jan/07/news.workandcareers de personal. Un experiment a fost testarea daca vreun termen sau succesiune de termeni ce apare in CV cum ar fi \"programming contest\" se coreleaza cu decizia de angajare sau neangajare a cuiva. S-a gasit un singur astfel de termen, acesta era \"certified\". Iar termenul se corela negativ.\r\n\r\nCertificarile nici macar nu sunt greu de obtinut. Ar fi si absurd deoarece companiile ce le ofera vor sa faca bani din asta si vor sa aiba cat mai multi oameni ce le dau. Deci sunt direct interesate ca testele sa nu para usoare (astfel testele dureaza cateva ore si au zeci sau sute de intrebari), dar totusi majoritatea celor ce au depus putin efort sa le treaca cu brio.\r\n\r\nStiu ca la certificarile java 90% din intrebarile de la testele reale le gasesti in teste de pe net. Astfel invatarea pentru examen se trasforma pentru unii in memorarea intrebarilor mai dure pentru a nu le gresi in testul real. Aparitia marii majoritati a intrebarilor din testul grila real in testele de pregature de pe internet nu este ceva normal daca vrei ca rezultatul la acest test sa garanteze un nivel tehnic bun celor l-au trecut. Dar garantarea nivelului tehnic nu este prima prioritate a testului.\r\n\r\nSi totusi aceste teste pot fi utile. Incepatorii in un anumit limbaj pot folosi un asemenea test pentru a isi face o imagine mai in detaliu despre limbajul care il studiaza. Dar cred ca sunt si alte tehnici mai bune sa inveti un limbaj nou. De exemplu poti incerca sa faci un mic proiect in acel limbaj, si pe langa ca inveti limbajul ramai si cu ceva util pe urma acestui efort. Din cauza ca certificarile sunt utile doar incepatorilor, cand vad ca un CV are trecut ca lucru important o certificare, imi ridic un semn de intrebare.',1490,'protected',3132,NULL),('blog/firefox-download-day','Ajuta Firefox sa stabileasca un record mondial','2008-06-05 15:44:08','2008-11-26 18:51:43','Ajuta Firefox sa stabileasca un record mondial Guiness pentru cel mai downloadat pachet software in 24h.\r\n\r\n\'!blog/firefox-download-day?468x60_dday.png!\':http://www.spreadfirefox.com/en-US/worldrecord\r\n',1,'public',NULL,NULL),('blog/problema-saptamanii-produs-solutie','Problema saptamanii - Produs (Solutie)','2008-06-07 23:50:08','2008-11-15 13:41:14','Problema curenta a fost rezolvata de urmatorii Alexandru Mosoi, Bogdan Dumitru, Mihai Patrascu, Mihai Stroe, Delia David, Dumitru Ciubatii, Teodorescu Andrei-Marius, Dobrota Valentin Eugen, Ghitulete Razvan, Savin Tiberiu, Nicolae Titus, Adrian Vladu, Catalin Tiseanu. Oare a fost problema simpla sau se apropie vacanta?\r\n\r\nProblema suna asa:\r\n\r\n_Sa se determine produsul maxim a unor numere reale pozitive a caror suma e 100._\r\n\r\nAm primit si cateva solutii care presupuneau ca numerele sunt intregi sau in care se considera ca am cerut produsul maxim pentru exact doua numere. Mie textul mi s-a parut destul de clar si se pare ca a fost la fel de clar pentru majoritatea celor ce mi-au trimis solutia buna.\r\n\r\nAveti aici solutia lui Mihai Patrascu:\r\n\r\n1. Arati convexitate: daca $a+b=S, max(a*b) = S^2^/4$. Deci daca doua numere sunt inegale, le faci egale pastrand suma si marind produsul. Deci ca sa optimizezi pt $k$ numere, optimul e $(100/k)^k$\r\n\r\n2. Ca sa optimizezi dupa $k$, iei logaritm: $k(ln 100 - ln k)$. Derivata e: $ln 100 - ln k - k*(1/k) = ln(100/e) - ln k$. Vedem ca functie e creascatoare pana la $k=100/e$ si descrescatoare dupa. Deci optimul e $k = floor(100/e)$ sau $k=ceil(100/e)$.\r\n\r\n3. Folosind Google :)\r\n$(100 / 36)^36^ = 9.39961298 * 10^15^$\r\n$(100 / 37)^37^ = 9.47406172 * 10^15^$',1490,'protected',3136,NULL),('bogdan2412/2008_lot_iasi','bogdan2412-lot','2008-06-13 07:11:12','2008-06-13 23:54:28','h1. Intersectii de semiplane\r\n\r\n*Poti sa rezolvi problema triathlon in O(n^2). Ca sa vezi daca o problema de programare liniara 2d are solutie poti folosi un algoritm incremental randomizat care adauga semiplane ce merge in O(n). Uita-te aici http://www.cs.umd.edu/class/spring2007/cmsc754/Lects/754lects.pdf paginile 43 - 45. Poate ar ajuta sa mentionezi ca intersectia de semiplane (semispatii .. whatever) e folosita in programarea liniara.*\r\n\r\n# Camera (Cosmin Negruseri)\r\nhttp://infoarena.ro/problema/camera\r\n# Intersectie de poligoane convexe\r\n# Triathlon (2000-2001 ACM Northeastern European Regional Programming Contest)\r\nhttp://acm.timus.ru/problem.aspx?space=1&num=1062\r\n\r\nh1. Camera\r\n\r\n* Timp executie pe test	*$1$ sec*\r\n* Limita de memorie *$64 MB$*\r\n\r\nZebu si-a cumparat recent o noua parcela de pamant pe care vrea sa isi extinda afacerea cu gaini, dar el este foarte ingrijorat de hotii care pot afecta bunastarea afacerii. Un prieten care a fost recent in State i-a facut cadou o camera de filmat foarte performanta care are capacitatea de a filma dupa un unghi de $360$ de grade. Zebu este foarte bucuros de aceasta achizitie pe care o poate folosi imediat pentru a supraveghea parcela nou cumparata. Dar camera nu poate supraveghea intreaga parcela daca este dispusa in orice punct al acesteia, si Zebu este curios care e suprafata pe care camera poate fi pozitionata astfel ca toate punctele parcelei sa poata fi supravegheate. Parcela o putem modela ca un poligon cu $N$ varfuri, iar camera ca un punct in interiorul acestui poligon.\r\n\r\nh2. Cerinta:\r\n\r\nDeterminati aria zonei unde poate fi amplasata camera!\r\n\r\nh2. Date de Intrare:\r\n\r\nFisierul $camera.in$ va contine pe prima linie un numar intreg ce reprezinta valoarea lui $N$. Pe urmatoarele $N$ linii se vor afla cate doua numere intregi separate prin un singur spatiu, pe a $i+1$-a linie se vor afla coordonatele celui de al $i$-lea varf.\r\n\r\nh2. Date de Iesire:\r\n\r\nFisierul $camera.out$ va contine un singur numar real cu doua zecimale care reprezinta aria zonei in care poate fi plasata camera.\r\n\r\nh2. Restrictii:\r\n\r\n* $3 &le; N &le; 2000$\r\n* $-100000 &le; xi, yi &le; 100000$, $(xi, yi)$ sunt coordonatele varfurilor poligonului\r\n* Pentru $20%$ din teste marginile parcelei vor fi paralele cu axele de coordonate.\r\n* Doua numere reale se considera egale daca diferenta intre ele e cel mult $10^-6^$.\r\n* Un rezultat va fi considerat corect daca diferenta intre el si solutia rezultatul returnat de solutia oficiala este $&le; 0.01$.\r\n\r\nh2. Exemplu:\r\n\r\ntable(example). |_. camera.in |_. camera.out |\r\n| 9\r\n5 1\r\n5 2\r\n1 3\r\n3 4\r\n2 8\r\n5 5\r\n9 6\r\n7 3\r\n9 2\r\n| 2.86\r\n|\r\n\r\nh2. Explicatie\r\n\r\n!problema/camera?camera.gif!\r\n\r\nh2. Solutie\r\n\r\nProblema pare la prima vedere destul de complicata. O solutie posibila ar fi sa pornim cu poligonul initial si sa il intersectam cu cate o dreapta determinata de fiecare din laturile lui. Aceasta rezolvare ar putea parea destul de complicata pentru ca implica intersectii de drepte cu poligoane concave. Zona din care toate laturile poligonului sunt vizibile este cunoscuta sub numele de nucleu sau kernel in engleza. Pentru ca dintr-un punct sa fie vizibila o latura a poligonului, acest punct trebuie sa fie in semiplanul determinat de aceasta latura. De aici deducem ca nucleul poligonului este de fapt intersectia celor $N$ semiplane determinate de laturile poligonului. Pornim la inceput cu o zona patrata care contine toate punctele poligonului, astfel ea va contine si nucleul poligonului. Vom taia pe rand cu semiplane acest patrat. Poligonul intermediar va fi tot timpul convex, ceea ce ne usureaza cu mult rezolvarea. Vedem in urmatoarea imagine un exemplu al pasilor algoritmului:\r\n\r\n!preoni-2006/runda-2/solutii?nucleu1.jpg!\r\n\r\nParcurgem laturile poligonului intr-o ordine oarecare. Vom avea doi pointeri $cur$ si $next$ care vor reprezenta doua varfuri consecutive de pe poligonul care e solutia curenta. Daca ambele puncte sunt in interiorul semiplanului, atunci solutiei urmatoare ii adaugam punctul urmator. Daca punctul curent e in interior si punctul urmator este in exterior atunci solutiei ii adaugam punctul de intersectie {$p$}. Daca ambele puncte sunt in exterior procesam urmatoarea pereche. Daca punctul curent e in exterior si urmatorul punct este in interior atunci solutiei ii adaugam punctul de intersectie $p$ si punctul urmator. Astfel obtinem un algoritm de complexitate {$O(n^2^)$}.\r\n\r\n!preoni-2006/runda-2/solutii?nucleu2.jpg!\r\n\r\nh2. Solutie $O(N log N)$\r\n\r\n!>bogdan2412-lot?figura-buna.png 50%! Vom imparti problema in doua subprobleme diferite, semiplanele orientate in sus si cele orientate in jos. Pentru a evita probleme cu dreptele verticale putem roti sistemul cu un unghi. Cum intersectia semiplanelor formeaza un poligon convex, laturile de pe acest poligon sunt sortate in functie de panta. Pentru fiecare subproblema vom determina cate o parabola, intersectia celor 2 reprezentand intersectia tuturor semiplanelor.\r\n\r\nVoi prezenta rezolvarea pentru subproblema cu semiplanele orientate in sus, cealalta subproblema rezolvandu-se analog. Ne putem imagina semiplanele ca fiind orientate catre un punct, astfel calcularea intersectiei semiplanelor reducandu-se la determinarea dreptelor vizibile din acest punct. Aceasta problema este una cunoscuta care poate fi rezolvata cu putine cunostinte de dualizare.\r\n\r\nIn primul rand, trebuie sa determinam un punct care se afla in interiorul intersectiei si sa translatam intregul sistem astfel incat acest punct sa devina noua origine. Dorim sa translatam toate dreptele in jos astfel incat semnul lui $(0, 0)$ fata de acestea sa fie $-$. Daca exista o dreapta determinata de coeficientii $(a, b, c)$ pentru care semnul lui $(0, 0)$ este pozitiv atunci $a * 0 + b * 0 + c > 0$ sau $c > 0$. Este suficient sa scadem din coeficientul $c$ al tuturor dreptelor pe cel mai mare dintre acesta $+ 1$.\r\n\r\nIn planul dual, tuturor dreptelor vizibile din origine le vor corespunde puncte aflate pe convex hull si tuturor dreptelor care nu sunt vizibile din origine le vor corespunde puncte aflate in interiorul poligonului convex. In plus, dreptele ce formeaza parabola vor avea aceeasi ordine ca si punctele de pe poligonul convex. Astel putem rezolva fiecare subproblema in complexitatea necesara pentru aflarea unui convex hull, $O(N log N)$.\r\n\r\nPentru a determina intersectia celor doua parabole trebuie sa determinam perechiile de segmente care se intersecteaza. Observam ca intr-o parabola punctele de intersectie intre doua drepte consecutive sunt ordonate in functie de coordonata $x$. Astfel putem determina segmentele care se intersecteaza parcurgand cele doua liste cu doi pointeri in paralel. In timp ce parcurgem punctele de intersectie din prima parabola, mentinem un pointer catre segmentul din a doua parabola care contine coordonata $x$ a primului pointer. La fiecare pas verificam daca extremitatile segmentului din prima parabola se afla de parti opuse ale segmentului din a doua parabola. Daca da, verificam daca intersectia celor doua drepte se afla in interiorul segmentului din a doua parabola sau incrementam al doilea pointer altfel. Complexitatea acestei etape este $O(N)$. Complexitate totala $O(N log N)$.\r\n\r\nh1. Intersectie de poligoane convexe\r\n\r\nO aplicatie imediata a intersectiei de semiplane o constituie aflarea intersectiei a doua poligoane convexe. Observam ca un poligon convex poate fi obtinut prin intersectia semiplanelor formate de laturile sale. Astfel, putem lua toate semiplanele determinate de laturile celor doua poligoane la un loc si sa calculam intersectia acestora cu ajutorul algoritmilor prezentati mai sus. O alta solutie ar fi sa adaptam algoritmul $O(N^2^)$ si, in loc sa pornim cu un patrat suficient de mare astfel incat sa cuprinda toate punctele, pornim cu unul dintre poligoane. Apoi, intersectand semiplanurile determinate de fiecare latura a celuilalt poligon cu poligonul initial obtinem intersectia celor doua poligoane.\r\n\r\nh1. Triathlon\r\n\r\n* Timp de executie pe test: *2 sec*\r\n* Limita de memorie: *16 MB*\r\n\r\nTriathlon is an athletic contest consisting of three consecutive sections that should be completed as fast as possible as a whole. The first section is swimming, the second section is riding bicycle and the third one is running.\r\n\r\nThe speed of each contestant in all three sections is known. The judge can choose the length of each section arbitrarily provided that no section has zero length. As a result sometimes she could choose their lengths in such a way that some particular contestant would win the competition.\r\n\r\nh2. Input\r\n\r\nThe first line of the input contains integer number $N (1 &le; N &le; 100)$, denoting the number of contestants. Then $N$ lines follow, each line contains three integers $Vi, Ui$ and $Wi$ $(1 &le; Vi, Ui, Wi &le; 10000)$, separated by spaces, denoting the speed of ith contestant in each section.\r\n\r\nh2. Output\r\n\r\nFor every contestant write to the output one line, that contains word $\"Yes\"$ if the judge could choose the lengths of the sections in such a way that this particular contestant would win (i.e. she is the only one who would come first), or word $\"No\"$ if this is impossible.\r\n\r\nh2. Sample\r\n\r\ntable(example). |_. Input |_. Output |\r\n| 9\r\n10 2 6\r\n10 7 3\r\n5 6 7\r\n3 2 7\r\n6 2 6\r\n3 5 7\r\n8 4 6\r\n10 4 2\r\n1 8 7\r\n| Yes\r\nYes\r\nYes\r\nNo\r\nNo\r\nNo\r\nYes\r\nNo\r\nYes\r\n|\r\n\r\nh2. Solutie\r\n\r\n* $distanta = viteza * timp$\r\n\r\nNotand cu $X, Y, Z$ distantele alese pentru cele 3 probe, timpul in care un participant $i$ termina triatlonul este egal cu <tex>\\frac{X}{V_i} + \\frac{Y}{U_i} + \\frac{Z}{W_i}</tex>. Astfel pentru fiecare participant trebuie sa vedem daca exista 3 astfel de valori astfel incat\r\n\r\n* <tex>\\frac{X}{V_i} + \\frac{Y}{U_i} + \\frac{Z}{W_i} > \\frac{X}{V_j} + \\frac{Y}{U_j} + \\frac{Z}{W_j}</tex>, oricare ar fi $j$ diferit de $i$\r\n\r\nObservam ca putem reduce una din probe impartind prin $Z$ inegalitatea si considerand ca proba a 3-a are intotdeauna distanta 1.\r\n\r\n* <tex>\\frac{X}{Z*V_i} + \\frac{Y}{Z*U_i} + \\frac{1}{W_i} > \\frac{X}{Z*V_j} + \\frac{Y}{Z*U_j} + \\frac{1}{W_j}</tex>\r\n\r\nNotand cu <tex>X\' = \\frac{X}{Z}</tex> si cu <tex>Y\' = \\frac{Y}{Z}</tex> obtinem inegalitatea \r\n\r\n* <tex>\\frac{X\'}{V_i} + \\frac{Y\'}{U_i} + \\frac{1}{W_i} > \\frac{X\'}{V_j} + \\frac{Y\'}{U_j} + \\frac{1}{W_j}</tex>\r\n\r\nDucand totul intr-o parte obtinem:\r\n\r\n* <tex>X\' * (\\frac{1}{V_i} - \\frac{1}{V_j}) + Y\' * (\\frac{1}{U_i} - \\frac{1}{U_j}) + (\\frac{1}{W_i} - \\frac{1}{W_j}) > 0</tex>\r\n\r\nObservam ca inegalitatea de mai sus se aseamana cu ecuatia dreptei <tex>a * x + b * y + c = 0</tex> si ca inegalitatea reprezinta semiplanul aflat deasupra dreptei determinate de coeficientii <tex>(\\frac{1}{V_i} - \\frac{1}{V_j}, \\frac{1}{U_i} - \\frac{1}{U_j}, \\frac{1}{W_i} - \\frac{1}{W_j})</tex>.\r\n\r\nAstfel fiecare adversar al concurentului $i$ determina in planul $(x, y)$ un semiplan in care valorile $(X\', Y\')$ trebuie sa se afle pentru ca $i$ sa castige triatlonul. Daca aria intersectiei acestor semiplane este diferita de 0 atunci participantul $i$ poate castiga triatlonul.\r\n\r\nPentru fiecare participant putem determina in $O(N^2^)$ sau in $O(N log N)$ aria intersectiei semiplanelor, complexitatea totala fiind de $O(N^3^)$ sau $O(N^2^ log N)$.\r\n',58,'public',NULL,NULL),('blog/post-nou','Post nou','2008-06-17 06:11:41','2008-11-15 13:41:14','Nu am mai scris de ceva vreme si ca sa nu va plictisiti in lipsa de un post mai destept va sugerez niste articole interesante:\r\n\r\n\'PayPal mafia\':http://money.cnn.com/2007/11/13/magazines/fortune/paypal_mafia.fortune/index.htm Un articol despre fondatorii si cei ce au lucrat la PayPal. Multi dintre ei au plecat si au creat la randul lor cateva firme software de succes cum ar fi Slide, Yelp, Digg sau YouTube. E interesant ca nu se aud succese asa rasunatoare de la oameni plecati din Google. Deocamdata ar fi doar FriendFeed care e pe un trend ascendent, iar Twitter e facut de cei ce au facut Blogger, dar pe acestia nu ii putem considera de la Google pentru ca Blogger a fost o achizitie.\r\n\r\n\'Google spotlights data center inner workings\':http://news.cnet.com/8301-10784_3-9955184-7.html Jeff Dean, care e un super inginer de la Google, explica modul de functionare a unui data center de la noi. E destul de interesant articolul, mai ales in contextul postului lui Vivi despre scalabilitate \'50 de servere vs. 10.000\':http://www.vivi.ro/blog/?p=554 .\r\n\r\n\'Introduction to Google Search Quality\':http://googleblog.blogspot.com/2008/05/introduction-to-google-search-quality.html? In acest articol Udi Manber, care e seful pe Search Quality la Google, explica putin din procesul de imbunatatire a algoritmilor de cautare. Poate numele Udi Manber va e cunoscut pentru ca e autorul paperului \'Suffix Arrays: A new method for on-line string searches\':http://webglimpse.net/pubs/suffix.pdf\r\n\r\nPe curand!',1490,'protected',3151,NULL),('runda/splunge4','splunge4','2009-07-23 06:01:19','2009-07-23 06:01:19','h1. == roundparam(round_id=\"splunge4\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"splunge4\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"splunge4\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"splunge4\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/splunge4/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"splunge4\" score=\"1\")==',4439,'round: splunge4',NULL,NULL),('blog/google-code-jam-2008','Google Code Jam 2008','2008-06-24 02:22:18','2008-11-15 13:41:14','Dupa o pauza de un an, concursul Google Code Jam se relanseaza. Inregistrarea este deschisa pe \'siteul concursului\':http://code.google.com/codejam/ tuturor celor peste 18 ani. De data asta nu va fi folosita platforma Topcoder ci concursul va avea personalitate lui. In loc sa trimiteti surse la un evaluator online automat, va trebui sa rezolvati niste seturi de date si sa trimiteti fisierele de ouput. Formatul acesta e destul de misto pentru ca va permite utilizatorilor sa foloseasca orice limbaj sau tooluri software pentru a rezolva problemele.\r\nProiectul a fost construit pe platforma \'Google App Engine\':http://code.google.com/appengine/ ca parte a filozofiei \"eat your own dog food\". Aceasta are la baza ideea ca pentru a face un produs bun pentru clienti, primul client trebuie sa fii chiar tu. Pentru a gasi probleme interesante pentru Google Code Jam, s-a organizat un concurs intern de propus de probleme la care am participat cu destul entuziasm si sper ca din problemele mele sa se selecteze cateva care vor fi folosite. Au participat la concursul intern o gramada de nume cunoscute dintre topcoderii cunoscuti ce lucreaza la Google. Asa ca nu am nici un dubiu ca problemele din concurs vor fi deosebite si interesante.\r\n\'Mars\':http://campion.edu.ro/team.php?id=6 si-a folosit parte din timpul lui de 20% de la Google pentru a ajuta la partea de infrastructura a proiectului si la evaluarea calitatii problemelor, daca nu va place ceva el e de vina :), sau daca va intereseaza Google App Engine tot pe el il puteti lua la intrebari. Proiectul e foarte misto ca realizare si din prisma oamenilor care au lucrat la el, nu va pot spune mai multe nume, dar e un fel de \"who\'s who\" a concursurilor de programare din ultimii ani.\r\n\r\nSper sa participati si sa va vad in toamna pe cat mai multi dintre voi la finala din Mountain View!',1490,'protected',3159,NULL),('runda/junior-challenge-2008','junior-challenge-2008','2008-06-27 12:36:00','2008-06-27 12:36:00','h1. == roundparam(round_id=\"junior-challenge-2008\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"junior-challenge-2008\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"junior-challenge-2008\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"junior-challenge-2008\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':junior-challenge-2008/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"junior-challenge-2008\" score=\"1\")==',256,'round: junior-challenge-2008',NULL,NULL),('runda/junior-challenge-2008/clasament','Clasament junior-challenge-2008','2008-06-27 12:36:00','2008-06-27 12:36:00','h1. Clasament ==roundparam(round_id=\"junior-challenge-2008\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"junior-challenge-2008\")==',256,'round: junior-challenge-2008',NULL,NULL),('newsletter/junior-challenge-2008','Junior Challenge 2008; castiga un tricou infoarena!','2008-07-02 17:51:25','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\ninfoarena organizeaza un nou concurs pentru tine!\r\nPrimii 5 juniori vor primi cate un tricou infoarena!\r\n\nTe invitam sa participi la Junior Challenge, un concurs destinat in\r\nprincipal juniorilor. Totusi, nu te lasa pacalit de nume! Te asiguram\r\nca setul de problemele va fi o reala provocare, asa ca, indiferent\r\nde varsta, te provocam sa participi.\r\nConcursul este totodata o ocazie de antrenament pentru echipa ce va\r\nreprezenta Romania la Olimpiada Balcanica de Juniori. Masoara-ti\r\nfortele cu ei!\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Concursul se desfasoara...\r\n    Sambata, 5 iulie 2008, orele 10:00 - 14:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nVezi pagina concursului: \'junior-challenge-2008\':junior-challenge-2008\r\npentru mai multe informatii.\r\n\nSucces!\r\n\nh2.  Atentie! Concurs cu rating! \n\nDaca vrei sa ti se modifice rating-ul in urma acestui concurs\r\ntrebuie sa iti anunti participarea din timp. Intra pe\r\n\'junior-challenge-2008\':junior-challenge-2008 si inscrie-te.\r\n\nPoti sa participi la concurs chiar si daca nu te-ai inscris in\r\nprealabil insa nu ti se va modifica rating-ul.\r\n==NewsletterRating(username=\"%username%\")==\r\nCiteste despre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Despre Junior Challenge \n\nJunior Challenge este un concurs marca infoarena, ajuns la a doua\r\neditie.\r\nVei avea de rezolvat 3 probleme de natura algoritmica intr-un timp\r\nde lucru de 4h. Unele probleme vor avea o dificultate destul de\r\nridicata, chiar si pentru un elev de liceu.\r\n\nOrganizatorii acestei editii sunt:\r\n\np{padding-left: 2em;}. Airinei Adrian\r\n    [  ==User(user=\"astronomy\" type=\"link\")==  ]\r\n\np{padding-left: 2em;}. Filip Cristian Buruiana\r\n    [  ==User(user=\"filipb\" type=\"link\")==  ]\r\n\np{padding-left: 2em;}. Andrei Grigorean\r\n    [  ==User(user=\"wefgef\" type=\"link\")==  ]\r\n\np{padding-left: 2em;}. Stanciu Valentin\r\n    [  ==User(user=\"svalentin\" type=\"link\")==  ]\r\n\nPrimii 5 juniori (elevi din ciclul gimnazial sau primar) vor primi\r\ncate un tricou infoarena!\r\n\nh2.  Olimpiada Balcanica de Juniori \n\nA doua editie a Olimpiadei Balcanice de Juniori (JBOI) se organizeaza\r\nla Shumen, Bulgaria in perioada 8 - 13 iulie 2008.\r\nMai multe informatii despre competitie poti gasi pe site-ul\r\noficial: \'http://jboi2008.com/\':http://jboi2008.com/\r\n\nDelegatia de juniori Romaniei, condusa de Prof. Dana Lica si\r\nProf. Marinel Serban este compusa din elevii: Gavrila Vlad,\r\nPurice Andrei, Pripoae Teodor Anton si Voroneanu Radu Stefan.\r\nLe uram multa bafta si speram sa fie in mare forma pentru aceasta\r\ncompetitie!\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nEchipa infoarena iti ureaza succes!\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('junior-challenge-2008/probleme','Probleme Junior Challenge 2008','2008-06-28 08:26:55','2008-07-04 07:28:25','==include(page=\"templates/junior_head\")==\r\n\r\nh1. == roundparam(round_id=\"junior-challenge-2008\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':junior-challenge-2008\r\n*(active) \'Probleme\':junior-challenge-2008/probleme \r\n* \'Clasament\':junior-challenge-2008/clasament\r\n\r\n_Junior Challenge_ este un concurs marca \'*infoarena*\':/, ajuns deja la a doua editie. Detalii despre prima editie a concursului gasesti \'aici\':junior-challenge.\r\n\r\nh2. Probleme\r\n\r\nAici vei gasi problemele atunci cand va incepe concursul.\r\n\r\n== Tasks(round_id=\"junior-challenge-2008\" score=\"1\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n',256,'round: junior-challenge-2008',NULL,NULL),('junior-challenge-2008','Junior Challenge 2008','2008-06-27 11:55:32','2008-07-05 15:13:56','==include(page=\"templates/junior_head\")==\r\n\r\nh1. == roundparam(round_id=\"junior-challenge-2008\" param=\"title\") ==\r\n\r\n(htabs)*(active) \'Despre...\':junior-challenge-2008\r\n* \'Probleme\':junior-challenge-2008/probleme \r\n* \'Clasament\':junior-challenge-2008/clasament\r\n\r\n_Junior Challenge_ este un concurs marca \'*infoarena*\':/, ajuns deja la a doua editie. Detalii despre prima editie a concursului gasesti \'aici\':junior-challenge.\r\n\r\nh2. Despre concurs\r\n\r\n_Junior Challenge_ este un concurs dedicat atat incepatorilor in programare, cat si celor care doresc un concurs la care sa programeze cu zambetul pe buze. Totodata, concursul este si o ocazie de antrenament oferita lotului ce va reprezenta Romania la \'Olimpiada Balcanica de Juniori\':http://jboi2008.com/:\r\n\r\n* ==user(user=\"GavrilaVlad\" type=\"tiny\")==\r\n* ==user(user=\"Protoman\" type=\"tiny\")==\r\n* ==user(user=\"toni2007\" type=\"tiny\")==\r\n* ==user(user=\"radu_voroneanu\" type=\"tiny\")==\r\n\r\nEchipa va fi insotita de prof. Marinel Serban si de prof. Dana Lica.\r\nDaca vrei sa iti masori fortele cu cei patru reprezentati ai Romaniei, atunci participa si tu!\r\n\r\nConcursul incepe ==roundparam(round_id=\"junior-challenge-2008\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"junior-challenge-2008\" param=\"duration\" strong=\"true\")== ore. Participanii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nPrimii clasati, care sunt in plus elevi in ciclul primar sau gimnazial, vor primi un tricou infoarena:\r\n\r\n!junior-challenge-2008?tricou.jpg!\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 10^00^* daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating, insa poti sa participi oricum!\r\n\r\n== roundregister(round_id=\"junior-challenge-2008\") ==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru!\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti problemele, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':documentatie/evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nh2. Prima data pe _infoarena_?\r\n\r\n\'infoarena\':/ ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi si vezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n',2028,'round: junior-challenge-2008',NULL,NULL),('junior-challenge-2008/clasament','Junior Challenge 2008, Clasament','2008-07-04 07:29:58','2008-07-04 07:30:26','==include(page=\"templates/junior_head\")==\r\n\r\n(htabs)* \'Despre...\':junior-challenge-2008\r\n* \'Probleme\':junior-challenge-2008/probleme \r\n*(active) \'Clasament\':junior-challenge-2008/clasament\r\n\r\np<. == Rankings(rounds=\"junior-challenge-2008\") == ',256,'protected',NULL,NULL),('blog/junior-challenge-2008','Junior Challenge 2008 + 1 tricou infoarena','2008-07-04 10:48:51','2008-07-04 10:53:01','Concursul Junior Challenge 2008, un concurs marca infoarena ajuns deja la editia a doua, se va desfasura online sambata, 5 iulie. Pagina concursului se gaseste \'aici\':junior-challenge-2008.\r\nCastigatorii concursului care sunt elevi in ciclul primar sau gimnazial vor primi cate un tricou infoarena. Va invitam sa participati insa pe toti, deoarece subiectele sunt cu adevarat provocatoare. Mult succes celor care vor participa si nu uitati sa va inscrieti daca doriti sa vi se modifice ratingul.',256,'protected',NULL,NULL),('junior-challenge-2008/solutii/grigo','junior-challenge-2008/solutii/grigo','2008-07-05 09:23:05','2008-07-05 12:08:51','h2(#grigo). \'Grigo\':problema/grigo\r\n\r\nO analiza atenta a structurii permutarilor care respecta conditiile impuse ne arata ca daca ultima pozitie trebuie sa fie vizibila atunci in toate permutarile pe acea pozitie se va afla valoarea $N$, iar in caz contrar pe ultima pozitie se poate afla orice valoare intre $1$ si $N-1$. De aici vine ideea construirii unei solutii bazate pe programare dinamica. Vom calcula un vector $NrSol[i]$, reprezentand numarul de permutari de $i$ numere ca respecta conditiile impuse daca se iau in considerare doar pozitiile de la $1$ la $i$. Recurenta este destul de simplu de dedus. Astfel, daca pozitia $i$ trebuie sa fie vizibila, atunci in mod evident $NrSol[i] = NrSol[i-1]$, deoarece pe pozitia $i$ este necesar sa se afle valoarea $i$. Daca pozitia $i$ nu trebuie sa fie vizibila, atunci $NrSol[i] = (i-1) * NrSol[i-1]$, deoarece pe ultima pozitie putem pune orice numar intre $1$ si $i-1$, ramanandu-ne astfel $i-1$ valori distincte, pe care le putem reinterpreta ca fiind o permutare. Raspunsul cautat se va gasi in $NrSol[N]$.',256,'protected',NULL,NULL),('junior-challenge-2008/solutii/reconst','junior-challenge-2008/solutii/reconst','2008-07-05 09:25:07','2008-07-05 12:09:03','h2(#reconst). \'Reconst\':problema/reconst\r\n\r\nVom considera fiecare intrebare pusa ca fiind un interval de pozitii pentru care este necesar sa aiba o anumita suma data. O prima observatie care ne va ajuta sa rezolvam problema este ca daca nu avem doua intervale care sa inceapa pe aceeasi pozitie putem gasi foarte usor un algoritm greedy care sa furniezeze un raspuns corect. Parcurgem sirul de la ultima pozitie inspre prima, si vom considera ca toate elementele sale au valoarea $0$, mai putin cele care sunt capatul de inceput al unui interval. Pentru aceste pozitii, vom considera valoarea lor ca fiind acel numar egal cu diferenta intre suma data a intervalului si suma valorilor deja alese pentru celelalte pozitii care fac parte din interval. In continuare vom analiza cazul in care exista cel putin o pereche de intervale care au acelasi capat de inceput. Fie doua intervale $[A, B]$ si $[A, C]$. Daca $B = C$, atunci putem pur si simplu sa nu luam in calcul unul din cele doua intervale. In caz contrar putem considera ca $B < C$ fara a restrange generalitatea. Fie $S1$ suma data pentru primul interval si $S2$ suma data pentru cel de-al doilea. Este destul de simplu de observat ca in loc de intervalul $[A, C]$ de suma $S2$, putem sa consideram intervalul $[B+1, C]$ de suma $S2-S1$. Repetand acest pas atat timp cat este nevoie vom ajunge la o configuratie in care nu exista doua intervale care sa aiba acelasi capat de inceput. Acest algoritm are complexitatea {$O(M^2^)$}, deoarece fiecare segment poate fi _inlocuit_ cu un alt segment mai mic de maxim $M$ ori.',256,'protected',NULL,NULL),('junior-challenge-2008/solutii','Junior Challenge 2008, Articolul cu solutii','2008-07-05 09:20:51','2008-07-05 12:09:22','==include(page=\"templates/junior_head\")==\r\n\r\nh1. Solutii Junior Challenge 2008\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Grigo\':junior-challenge-2008/solutii#grigo\r\n* \'Reconst\':junior-challenge-2008/solutii#reconst\r\n* \'Gropi\':junior-challenge-2008/solutii#gropi\r\n\r\n\r\n==include(page=\"junior-challenge-2008/solutii/grigo\")==\r\n\r\n==include(page=\"junior-challenge-2008/solutii/reconst\")==\r\n\r\n==include(page=\"junior-challenge-2008/solutii/gropi\")==\r\n',256,'protected',NULL,NULL),('junior-challenge-2008/solutii/gropi','Gropi','2008-07-05 09:25:43','2008-07-05 12:25:10','h2(#gropi). \'Gropi\':problema/gropi\r\n\r\nDatorita restrictiilor mici pentru jumatate din teste, se poate implementa un algoritm trivial de complexitate {$O(M*C)$} care obtine $50$ de puncte. Sa consideram un traseu de la {$(x{~1~} y{~1~})$} la {$(x{~2~} y{~2~})$}, cu {$y1 &le; y2$} ( in caz contrar putem inversa punctul de plecare cu cel de sosire ). Cat timp {$y{~1~} < y{~2~}$} vom face una din urmatoarele actiuni:\r\n\r\n* daca este posibil, ne deplasam spre dreapta (daca zona de pe coloana urmatoare si linia curenta nu este o zona cu gropi). Incrementam rezultatul cu {$1$};\r\n* in caz contrar, schimbam linia si incrementam rezultatul cu {$1$}.\r\n\r\nIn final afisam rezultatul obtinut, la care adaugam eventual $1$ daca zona in care ne aflam este pe linia opusa liniei punctului destinatie (in acest caz mai trebuie sa facem un pas in sus sau in jos). Cum pentru fiecare traseu se efectueaza maxim $C$ operatii, complexitatea va fi {$O(M*C)$}.\r\n\r\nSolutia de $100$ de puncte are complexitatea {$O((N + M)log{~2~}N)$}. Se observa ca numarul de casute strabatute _pe orizontala_ este constant (egal cu {$y{~2~}-y{~1~}+1$}), si trebuie sa aflam deci numarul de schimbari de directie pentru a afla raspunsul pentru un traseu. Vom imparti matricea data in _zone_, in functie de pozitionarea gropilor. O zona va fi formata dintr-o singura linie si coloane consecutive si in plus va avea proprietatea ca gropile pe care le contine sunt toate pe aceeasi linie. Se observa ca aceste _zone_ apar alternativ pe linii: dupa o zona ce se afla pe linia {$1$}, va veni o zona pe linia {$2$} si invers. In exemplul dat zonele apar astfel:\r\n\r\n!junior-challenge-2008/solutii/gropi?layere.jpg!\r\n\r\nPentru a evita cazurile particulare putem pozitiona o groapa pe coloana $0$, pe linia opusa liniei primei gropi (cu coloana cea mai mica).\r\n\r\nDupa ce am realizat aceasta impartire vom cauta binar zonele in care se afla punctul de plecare si punctul de sosire. Sa presupunem ca zona punctului de plecare este $i1$ si cea a punctului de sosire este {$i2$} si ca {$i1 < i2$}. Datorita structurii unui drum optim, putem identifica mai multe cazuri. De exemplu, daca {$x{~1~}$} este egal cu linia pe care se afla gropile in zona $i1$ si {$y{~1~}$} este mai mic decat coloana ultimei gropi din zona {$i1$}, iar punctul destinatie are aceeasi proprietate in functie de zona {$i2$}, atunci traseul va avea urmatoarea structura: prima data schimbam linia, apoi ne deplasam pe orizontala pana la zona {$i1+1$}, schimbam iarasi linia si ne deplasam pe orizontala pana la zona {$i1+2$}... si tot asa pana ajungem la zona {$i2$} in dreptul coloanei {$y2$}, dupa care schimbam linia si ajungem in {$(x{~2~} y{~2~})$}. Numarul de pasi in acest caz este {$(y{~2~}-y{~1~}+1) + 1 + (i2-i1) + 1$}. Dupa ce cautam binar este suficient sa determinam toate cazurile care exista si complexitatea devine {$O(1)$} deoarece se efectueaza un numar constant de adunari si scaderi.\r\n',256,'protected',NULL,NULL),('runda/runda_gimnaziu_doi','runda_gimnaziu_doi','2009-04-08 06:03:40','2009-04-08 06:03:40','h1. == roundparam(round_id=\"runda_gimnaziu_doi\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"runda_gimnaziu_doi\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"runda_gimnaziu_doi\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"runda_gimnaziu_doi\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/runda_gimnaziu_doi/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"runda_gimnaziu_doi\" score=\"1\")==',393,'round: runda_gimnaziu_doi',NULL,NULL),('runda/runda_gimnaziu_doi/clasament','Clasament runda_gimnaziu_doi','2009-04-08 06:03:40','2009-04-08 06:03:40','h1. Clasament ==roundparam(round_id=\"runda_gimnaziu_doi\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"runda_gimnaziu_doi\")==',393,'round: runda_gimnaziu_doi',NULL,NULL),('teoria-jocurilor/adunarea-jocurilor/adunarea-or','Adunarea or','2008-08-25 19:17:09','2008-08-25 19:17:09','h3(#or). Adunarea or\r\n\r\nSa presupunem ca dorim sa adunam jocurile {$G{~1~}$}, {$G{~2~}$}, ..., {$G{~P~}$}, astfel incat la fiecare pas jucatorul care urmeaza poate sa isi aleaga oricate jocuri si sa faca o mutare in fiecare din jocurile alese. Jucatorul care nu mai poate muta pierde. Un astfel de caz se intalneste in problema \'Pioni\':problema/pioni.\r\n\r\n_Teorema_: Pentru un anumit joc $G$ care este suma jocurilor {$G{~1~}$}, {$G{~2~}$}, ..., {$G{~N~}$} dupa cum a fost definita mai sus o stare {$v = (v{~1~},v{~2~}, ..., v{~N~})$} este pierzatoare daca si numai daca {$mex(v{~1~}) = mex(v{~2~}) = ... = mex(v{~N~}) = 0$}.\r\n\r\n_Demonstratie_: Daca toate starile {$v{~1~}$}, {$v{~2~}$}, ..., {$v{~n~}$} sunt terminale atunci starea $v$ este pierzatoare si {$mex(v{~1~}) = mex(v{~2~}) = ... = mex(v{~N~}) = 0$}, deci teorema este adevarata. Daca starea $x$ contine cel putin un joc cu valoarea Sprague-Grundy nenula se fac mutari in toate aceste jocuri astfel incat sa lase adversarul intr-o stare in care toate jocurile au valoarea SG egala cu {$0$}. Dintr-o astfel de stare, orice mutare ar face adversarul va exista cel putin un joc cu valoarea SG nenula.',256,'protected',NULL,NULL),('notiuni-de-geometrie-si-aplicatii','Notiuni elementare de geometrie si aplicatii','2007-06-22 12:40:45','2009-06-30 17:26:29','h1. Notiuni elementare de geometrie si aplicatii\r\n\r\n(Categoria _Geometrie_, Autori _Savin Tiberiu_ si _Sima Mihai Cotizo_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'**0. Introducere**\':notiuni-de-geometrie-si-aplicatii#introducere\r\n* \'1. Arii\':notiuni-de-geometrie-si-aplicatii/arii\r\n** \'- triunghi\':notiuni-de-geometrie-si-aplicatii/arii#triunghi\r\n** \'- patrulater\':notiuni-de-geometrie-si-aplicatii/arii#patrulater\r\n** \'- poligon\':notiuni-de-geometrie-si-aplicatii/arii#poligon\r\n* \'2. Drepte\':notiuni-de-geometrie-si-aplicatii/drepte\r\n** \'- elemente generale\':notiuni-de-geometrie-si-aplicatii/drepte#general\r\n** \'- ecuaţii\':notiuni-de-geometrie-si-aplicatii/drepte#ecuatii\r\n** \'- distanţa punct-linie\':notiuni-de-geometrie-si-aplicatii/drepte#dpl\r\n** \'- distanţa punct-segment(semidreaptă)\':notiuni-de-geometrie-si-aplicatii/drepte#dps\r\n* \'3. Punct în poligon\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon\r\n** \'- crossing-number\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon#cn\r\n** \'- winding-number (?)\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon#wn\r\n** \'- şmenuri\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon#smen\r\n* \'4. Intersecţii de drepte şi segmente\':notiuni-de-geometrie-si-aplicati/intersectii-drepte-si-segmente\r\n* 5. Distanţe\r\n** - între linii\r\n** - între segmente şi semidrepte\r\n** - cea mai mică distanţă între două mobile\r\n* 6. Bounding ...\r\n** - ... box\r\n** - ... circle\r\n* \'7. Infaşurătoare convexă\':notiuni-de-geometrie-si-aplicatii/infasuratoare-convexa\r\n* 8. Puncte extreme şi distanţa poligon-linie\r\n* 9. Tangente\r\n* 10. Probleme de concurs\r\n\r\nh2(#introducere). 0. Introducere\r\n\r\n**Geometria** (din greaca veche - {_geo_}=pământ, {_metria_}=a măsura) este partea matematicii care se ocupă cu problemele privind dimensiunile, forma şi poziţia figurilor. Introducerea coordonatelor de către René Descartes a dus la dezvoltarea geometriei analitice, a cărei scop devine studierea geometriei prin funcţii şi ecuaţii.\r\n\r\nÎn problemele de olimpiadă este necesară cunoaşterea câtorva noţiuni şi idei de bază pentru a facilita găsirea unui algoritm eficient într-un timp scurt. Prezentul articol are ca scop explicarea acestor noţiuni privitoare la geometria plană (2D) şi studierea câtorva idei aplicate în problemele de concurs.\r\n\r\n',3270,'public',NULL,NULL),('blog/metaprogramare-cu-template-uri',' Meta-programare cu template-uri','2008-08-19 02:39:19','2008-11-15 13:41:14','\'Radu Berinde\':http://web.mit.edu/texel/www/, _care vara asta face un internship la_ \'VMware\':http://en.wikipedia.org/wiki/VMware, _va scrie un guest post despre programarea templateurilor in C++. Despre Radu am mai vorbit \'aici\':blog/interviu-radu-berinde-partea-intai si \'aici\':blog/interviu-radu-berinde-partea-a-doua ._\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/metaprogramare-cu-template-uri?radu.jpg! Am inceput sa citesc o carte interesanta - \"Modern C++ Design\", numita si \"the crack book\" din motive ce devin evidente inca de prin capitolul 2. Intamplator, e scrisa chiar de un roman, Andrei Alexandrescu, care e unul dintre cei mai mari experti pe C++ din lume. Cartea arata cum se pot face lucruri foarte interesante si/sau ciudate cu template-uri. Mi-am amintit de ceva ce am auzit acum mult timp: despre cineva care facuse un program C++ care nu compila, dar mesajele de eroare aratau numerele prime. Mi se parea ceva de-a dreptul bolnav, insa - comparativ cu ce se intampla prin cartea mentionata - acum pare trivial un astfel de program. Si de fapt chiar este destul de simplu, asa ca m-am gandit sa fac un mic \"tutorial\" in care sa explic cum se face.\r\n\r\n*Principiul de baza*\r\n\r\nPoate stiti ca in STL exista o implementare generala pentru vector, insa exista si o implementare speciala numai pentru _vector&lt;bool&gt;_, care foloseste doar cate un bit pentru fiecare valoare. Idioma C++ care permite asa ceva este \"template specialization\" si este un mecanism foarte puternic (mult mai puternic decat vom vedea aici). Practic, compilatorul are mai multe definitii din care alege una anume. Folosind acest lucru putem sa \"trucam\" compilatorul in a face un \"if\".\r\n\r\nDe exemplu, sa zicem ca vrem sa facem o asertie la timpul compilarii. Avem o expresie statica (care poate fi calculata la compilare) si vrem sa primim o eroare daca aceasta expresie nu se evalueaza la true. Putem sa folosim aceasta idee de template specialization:\r\n\r\n==code(c) |\r\ntemplate<bool> struct CompileTimeError {};\r\ntemplate<> struct CompileTimeError<true> { enum { Cool = 1 }; };\r\n==\r\n\r\nAm definit un tip _CompileTimeError_ care in general este gol. Insa daca parametrul bool se intampla sa fie true, compilatorul foloseste definitia specializata a tipului. Daca avem o expresie _expr_, sa ne gandim la urmatoarea expresie:\r\n\r\n==code(c) |\r\nCompileTimeError<expr>::Cool\r\n==\r\n\r\nDaca _expr = true_, s-ar evalua la 1. Insa daca este _false_, vom avea o eroare de compilare - definitia generala nu include identificatorul _Cool_. Am reusit sa facem compilatorul sa evalueze doua lucruri diferite in functie de o expresie - un \"if\" daca vreti.\r\n\r\n*Recursivitate*\r\n\r\nPentru ca tipurile sunt prin definitie imutabile, nu vom putea face compilatorul sa ruleze algoritmi iterativi - nu avem cum sa il facem sa mentina o stare. Va trebui sa convertim orice lucru iterativ in ceva recursiv, cum am face la un limbaj functional (in stil lisp). Cum determinam daca un numar este prim fara sa mentinem stare? Putem sa definim o \"functie\" _HasDivisors_ cu doi parametri, $N$ si $K$. _HasDivisors_ returneaza true daca vreun numar intre 2 si $K$ il divide pe $N$. Astfel, un numar este prim daca _HasDivisors_ este true pentru parametrii $N$ si $N-1$. Putem implementa aceasta idee cu template-uri:\r\n\r\n== code(c) |\r\ntemplate <int N, int K>\r\nstruct HasDivisors\r\n{\r\n    enum { Result = (N % K == 0) || HasDivisors<N, K-1>::Result };\r\n};\r\n\r\ntemplate <int N>\r\nstruct HasDivisors<N, 1>\r\n{\r\n    enum { Result = 0 };\r\n};\r\n\r\ntemplate <int N>\r\nstruct IsPrime\r\n{\r\n    enum { Result = !HasDivisors<N, N-1>::Result };\r\n};\r\n==\r\n\r\nObservam recursivitatea din _HasDivisors_; conditia de oprire este implementata prin specializarea partiala _HasDivisors&lt;$N$, 1&gt;_\r\n\r\nPutem combina acestea cu definitiile de mai sus pentru a genera erori pentru numerele prime:\r\n\r\n== code(c) |\r\ntemplate <int N>\r\nstruct PrimeErrors\r\n{\r\n    enum { Result = CompileTimeError<!IsPrime<N>::Result>::Cool +\r\n                      PrimeErrors<N-1>::Result };\r\n};\r\n\r\ntemplate <>\r\nstruct PrimeErrors<1>\r\n{\r\n    enum { Result = 0 };\r\n};\r\n==\r\n\r\nPrima parte a expresiei din _PrimeErrors_ este doar o asertie la timpul compilarii. Operatia de adunare e folosita doar pentru recursivitate. Din nou, specializarea ne da voie sa definim conditia de oprire a recursivitatii. In final nu mai avem nevoie decat de o instructiune care sa faca compilatorul sa evalueze _PrimeErrors_:\r\n\r\n== code(c) |\r\nPrimeErrors<100>::Result x;\r\n==\r\n\r\nDaca compilam acest program, vom primi erori ca mai jos (am taiat din liniile repetitive):\r\n\r\n== code(c) |\r\ntemplates.cpp: In instantiation of \'PrimeErrors<2>\':\r\ntemplates.cpp:25:   instantiated from \'PrimeErrors<3>\'\r\ntemplates.cpp:25:   instantiated from \'PrimeErrors<4>\'\r\ntemplates.cpp:25:   instantiated from \'PrimeErrors<5>\'\r\n...\r\ntemplates.cpp:34:   instantiated from here\r\ntemplates.cpp:25: error: \'Cool\' is not a member of\r\n\'CompileTimeError<false>\'\r\ntemplates.cpp: In instantiation of \'PrimeErrors<3>\':\r\ntemplates.cpp:25:   instantiated from \'PrimeErrors<4>\'\r\ntemplates.cpp:25:   instantiated from \'PrimeErrors<5>\'\r\n...\r\ntemplates.cpp:34:   instantiated from here\r\ntemplates.cpp:25: error: \'Cool\' is not a member of\r\n\'CompileTimeError<false>\'\r\ntemplates.cpp: In instantiation of \'PrimeErrors<5>\':\r\ntemplates.cpp:25:   instantiated from \'PrimeErrors<6>\'\r\ntemplates.cpp:25:   instantiated from \'PrimeErrors<7>\'\r\n...\r\ntemplates.cpp:34:   instantiated from here\r\ntemplates.cpp:25: error: \'Cool\' is not a member of\r\n\'CompileTimeError<false>\'\r\n==\r\n\r\nDaca filtram doar liniile cu In _instantiation of ..._, vedem frumos rezultatul dorit:\r\n\r\n== code(c) |\r\nroot@slack ~# gcc templates.cpp 2>&1 | grep \"In in\" \r\ntemplates.cpp: In instantiation of \'PrimeErrors<2>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<3>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<5>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<7>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<11>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<13>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<17>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<19>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<23>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<29>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<31>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<37>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<41>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<43>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<47>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<53>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<59>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<61>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<67>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<71>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<73>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<79>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<83>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<89>\':\r\ntemplates.cpp: In instantiation of \'PrimeErrors<97>\':\r\n==\r\n\r\nDragut, nu?',1490,'protected',3204,NULL),('teoria-jocurilor/numere-sg','Numere Sprague-Grundy','2008-07-21 13:14:09','2008-08-25 19:01:54','h1. Teoria jocurilor\r\n\r\n(Categoria _Teoria jocurilor_, Autor _Filip Cristian Buruiana_)\r\n\r\n(toc)*{text-align:center} *Capitole*\r\n* \'Notiuni de baza\':teoria-jocurilor\r\n* \'Jocul NIM\':teoria-jocurilor/jocul-nim\r\n* \'*Numere Sprague-Grundy*\':teoria-jocurilor/numere-SG\r\n* \'Adunarea jocurilor\':teoria-jocurilor/adunarea-jocurilor\r\n* \'w-numere\':teoria-jocurilor/w-numere\r\n* \'Aplicatii si probleme\':teoria-jocurilor/probleme\r\n\r\nh2. Numere Sprague-Grundy\r\n\r\nAlaturi de jocul {$NIM$}, numerele Sprague-Grundy au o importanta deosebita in analiza jocurilor impartiale. Majoritatea acestora se poate reduce la urmatorul joc: \"Se considera un graf orientat aciclic care contine un pion intr-un nod oarecare. Cei doi jucatori muta alternativ. Prin mutare se intelege miscarea pionului din nodul in care se afla intr-un nod adiacent. Jucatorul care nu mai poate muta pierde.\"\r\n\r\n!<teoria-jocurilor/numere-SG?img001.jpg 75%!\r\n\r\n&nbsp;\r\nDe exemplu, pentru graful din figura alaturata, daca pionul se afla initial in nodul $1$, primul jucator aflat la mutare va pierde in cazul unui joc perfect.\r\n&nbsp;\r\n&nbsp;\r\nCum graful este aciclic, jocul este finit si are intotdeauna un castigator. Daca in graf exista un singur pion, castigatorul poate fi determinat prin metoda programarii dinamice. Astfel, {$win{~x~}$} va fi _true_ daca si numai daca primul jucator aflat la mutare are strategie de castig atunci cand pionul se afla in nodul {$x$}. Astfel, {$win{~x~}$} = _true_ daca si numai daca exista un nod $y$ astfel incat sa existe arc intre $x$ si $y$ si {$win{~y~}$} = _false_. In caz contrar, {$win{~x~}$} = _false_. Pentru exemplul de mai sus, {$win{~2~}$} = _true_, iar {$win{~1~}$} si {$win{~4~}$} vor fi _false_. Valorile vectorului $win$ se vor calcula in ordinea din sortarea topologica a nodurilor, in complexitate {$O(N + M)$}, unde $N$ este numarul de noduri iar $M$ numarul de muchii din graful dat.\r\n\r\nTotusi, daca in graf ar exista mai multi pioni, problema determinarii castigatorului nu mai poate fi rezolvata prin programare dinamica. Folosind teoria dezvoltata independent de Roland Percival Sprague (1936) si Patrick Michael Grundy (1939), putem reduce complexitatea jocului cu mai multi pioni la complexitatea analizei jocului cu un pion. Ca in algoritmul de programare dinamica de mai sus, se incearca determinarea pozitiilor castigatoare si a celor necastigatoare pentru un singur pion.\r\n\r\n_Definitie_: Functia Sprague-Grundy pentru un graf {$G = (V, E)$} este o functie {$mex$} ({_minimum excludant_}) definita pe $V$ cu valori in multimea numerelor naturale, unde {$mex(x) = minim(n &ge; 0 |n diferit de mex(y), oricare ar fi y vecin al lui x)$}.\r\n\r\n!>teoria-jocurilor/numere-SG?img002.jpg 75%!\r\nAltfel spus, valoarea Sprague-Grundy pentru un nod $x$ al grafului aciclic dat este cel mai mic numar natural care nu este atribuit niciunui vecin al nodului {$x$}. Atribuirea valorilor se face incepand cu nodurile terminale, carora le este asociata valoarea {$0$}. Valorile Sprague-Grundy pentru nodurile grafului de mai jos sunt scrise cu rosu in dreptul fiecarui nod.\r\n&nbsp;\r\nSe observa ca pozitiile care au valoarea Sprague-Grundy egala cu $0$ sunt _pierzatoare_, in timp ce restul pozitiilor sunt _castigatoare_. Aceasta inseamna ca daca {$mex(x) = 0$}, in jocul cu un singur pion situat in nodul $x$ jucatorul care muta primul nu are strategie sigura de castig, iar daca {$mex(x)$} este diferit de $0$ atunci jucatorul care muta primul va castiga intotdeauna, in cazul in care joaca optim. Aceasta afirmatie este usor de demonstrat: daca {$mex(x)$} este diferit de $0$ atunci exista un nod {$y$}, vecin al lui {$x$}, astfel incat {$mex(y)$} sa fie egal cu $0$. In consecinta, primul jucator il va aduce intotdeauna pe adversarul sau in noduri care au valoarea Sprague-Grundy egala cu $0$. Mai mult, primul jucator va ramane intotdeauna in noduri cu valoare diferita de $0$, deoarece al doilea jucator nu il poate forta sa ajunga in aceste noduri: din nodurile cu valoarea $0$ se poate ajunge doar in noduri cu valoarea nenula. In concluzie, jucatorul al doilea va pierde, deoarece va fi adus intr-un nod final (fara urmasi). La o analiza mai atenta se observa ca starile de joc respecta proprietatile pozitiilor castigatoare si pierzatoare, enuntate \'aici\':teoria-jocurilor.\r\n\r\nValorile Sprague-Grundy se pot calcula si pentru jocuri in care nu apar precizate explicit grafuri. Fiecare stare posibila a jocului va fi un nod in graf, iar un arc va indica o posibila mutare: o trecere de la o stare la alta, conform regulilor existente.\r\n\r\np{margin:1em; padding: 0.5em; height: 45px; border-top: 1px solid silver;}=. \r\n\'Notiuni de baza\':teoria-jocurilor | \'Jocul NIM\':teoria-jocurilor/jocul-nim | \'*Numere Sprague-Grundy*\':teoria-jocurilor/numere-SG |\r\n\'Adunarea jocurilor\':teoria-jocurilor/adunarea-jocurilor | \'w-numere\':teoria-jocurilor/w-numere | \'Aplicatii si probleme\':teoria-jocurilor/probleme',256,'protected',NULL,NULL),('teoria-jocurilor','Teoria jocurilor','2008-07-21 12:13:44','2008-11-16 12:19:40','h1. \r\n\r\n&nbsp;\r\n\r\np{font-size:32px;}=. Teoria jocurilor\r\n\r\np{margin-right:8em;}>. _Filip Cristian Buruiana_\r\n\r\n&nbsp;\r\n&nbsp;\r\n\r\n\'!teoria-jocurilor?dice.jpg!\':teoria-jocurilor/notiuni\r\n\r\np{margin:1em; padding: 0.5em; height: 45px; border-top: 1px solid silver;}=. \r\n\'Notiuni de baza\':teoria-jocurilor | \'Jocul NIM\':teoria-jocurilor/jocul-nim | \'Numere Sprague-Grundy\':teoria-jocurilor/numere-SG |\r\n\'Adunarea jocurilor\':teoria-jocurilor/adunarea-jocurilor | \'w-numere\':teoria-jocurilor/w-numere | \'Aplicatii si probleme\':teoria-jocurilor/probleme\r\n',2028,'protected',NULL,NULL),('teoria-jocurilor/adunarea-jocurilor','Adunarea jocurilor','2008-07-21 13:15:55','2008-08-25 19:16:24','h1. Teoria jocurilor\r\n\r\n(Categoria _Teoria jocurilor_, Autor _Filip Cristian Buruiana_)\r\n\r\n(toc)*{text-align:center} *Capitole*\r\n* \'Notiuni de baza\':teoria-jocurilor\r\n* \'Jocul NIM\':teoria-jocurilor/jocul-nim\r\n* \'Numere Sprague-Grundy\':teoria-jocurilor/numere-SG\r\n* \'*Adunarea jocurilor*\':teoria-jocurilor/adunarea-jocurilor\r\n* \'w-numere\':teoria-jocurilor/w-numere\r\n* \'Aplicatii si probleme\':teoria-jocurilor/probleme\r\n\r\nh2. Adunarea jocurilor\r\n\r\nValorile Sprague-Grundy reprezinta o generalizare fata de algoritmul de programare dinamica in cazul jocului cu un singur pion, deoarece cu ajutorul acestor valori pot fi combinate mai multe jocuri. De exemplu, putem presupune ca in graful orientat sunt mai multi pioni in loc de unul singur si ca o mutare consta in deplasarea unui pion din nodul in care se afla intr-un nod adiacent. La fel ca mai sus, cine nu mai poate muta pierde. In acest caz, castigatorul in cazul unui joc perfect nu se poate determina pe baza programarii dinamice in timp polinomial. Mai mult, determinarea castigatorului nu este deloc triviala, asa cum era in cazul jocului cu un pion. Atunci cand combinam (adunam) mai multe jocuri elementare, rezultatul poate fi determinat in mod eficient cu ajutorul valorilor Sprague-Grundy. \r\n\r\nIn cazul jocului cu mai multi pioni, in loc sa consideram un singur graf, putem considera (conceptual) mai multe grafuri de joc identice, in fiecare dintre acestea aflandu-se cate un pion. Acum, o mutare inseamna alegerea unui graf si deplasarea pionului din graful ales conform regulilor pentru un singur pion. In acest fel, am separat jocul initial in mai multe jocuri _independente_. Stim rezultatul pentru fiecare joc _independent_ in parte si dorim sa determinam castigatorul pentru jocul cu mai multe grafuri. Aceasta inseamna ca dorim sa combinam rezultatele partiale pentru a determina rezultatul general. Pentru aceasta vom folosi _adunarea grafurilor de joc_. \r\n\r\nSa presupunem ca avem $P$ jocuri notate {$G{~1~}$}, {$G{~2~}$}, ..., {$G{~P~}$}, pe care dorim sa le adunam. Fiecare din cele $P$ jocuri poate fi reprezentat ca un graf orientat fara circuite in care multimea nodurilor (notata {$V{~i~}$} pentru jocul {$i$}) este data de multimea starilor iar multimea arcelor (notata {$E{~i~}$} pentru jocul {$i$}) este data de perechile ordonate de stari adiacente (exista arc de la $x$ la $y$ daca se poate ajunge printr-o mutare din starea $x$ in starea $y$). Adunand cele $P$ jocuri obtinem un nou joc {$G$} pentru care o stare (nod in graful asociat) este un {$P$}-uplu {$(v{~1~},v{~2~}, ...,v{~P~})$} care ne precizeaza starea curenta pentru fiecare joc individual ({$v{~i~}$} este starea curenta in jocul $i$). Pentru a afla daca pentru o anumita stare din jocul $G$ exista sau nu strategie sigura de castig am putea aplica algoritmul de programare dinamica (prezentat mai sus) pentru graful asociat jocului {$G$}. Se observa insa ca acest graf are {$|V{~1~}|*|V{~2~}|* ...*|V{~P~}|$} noduri, deci algoritmul nu este eficient.\r\n\r\nIn continuare vom arata cum putem sa determinam eficient daca o stare este castigatoare sau nu pentru un joc compus folosindu-ne de informatiile preprocesate pentru fiecare joc individual.\r\n\r\n\r\n(vmenu)*(section) \'*Adunarea xor*\':teoria-jocurilor/adunarea-xor#xor\r\n* \'Adunarea or\':teoria-jocurilor/adunarea-or#or\r\n* \'Adunarea almost or\':teoria-jocurilor/adunarea-almost#almost\r\n* \'Adunarea and\':teoria-jocurilor/adunarea-and\r\n* \'Adunarea also\':teoria-jocurilor/adunarea-also\r\n\r\nh3(#xor). Adunarea xor\r\n\r\nVom aduna jocurile {$G{~1~}$}, {$G{~2~}$}, ..., {$G{~P~}$} astfel incat la fiecare pas jucatorul care urmeaza trebuie sa isi aleaga exact un joc si sa faca o mutare in jocul respectiv. Jucatorul care nu mai poate muta pierde. Un astfel de joc este generalizarea jocului cu un pion din capitolul precedent si se intalneste in problema \'Pawns\':problema/pawns, data la concursul national Bursele Agora. Pentru a determina castigatorul in cazul acestui joc, ne vom folosi de urmatoarea teorema:\r\n\r\n_Teorema_: Fie jocurile independente {$G{~1~}$}, {$G{~2~}$}, ..., {$G{~P~}$} si fie {$G$} suma acestor jocuri. Daca la fiecare pas alegem un singur joc si efectuam o mutare in jocul ales, atunci o stare {$(v{~1~},v{~2~}, ...,v{~P~})$} din jocul {$G$} este pierzatoare daca si numai daca {$mex(v{~1~}) xor mex(v{~2~}) xor ... xor mex(v{~P~}) = 0$}, unde {$v{~i~}$} reprezinta starea din jocul {$G{~i~}$}. \r\n\r\n_Demonstratie_: Demonstratia este similara cu cea a jocului {$NIM$}, cele doua jocuri fiind asemanatoare. Starile care au suma-xor {$0$} sunt pierzatoare, celelalte stari fiind castigatoare.\r\n\r\nDintr-o stare pierzatoare putem ajunge numai in stari castigatoare. Prin reducere la absurd putem presupune ca mutam dintr-o valoare {$x = mex(v{~i~})$} intr-o valoare {$x\' = mex(v\'{~i~})$}. Daca notam cu $S$ suma xor a starilor din jocurile diferite de {$i$}, atunci avem {$S xor x = 0$}, deci {$S = x$}. Dar trebuie sa avem si {$S xor x\' = 0$}, deci $S$ este egal si cu {$x\'$}, ceea ce implica {$x = x\'$}. Aceasta egalitate nu poate avea loc, deoarece dintr-o stare nu putem ajunge intr-o stare adiacenta care sa aiba aceeasi valoarea Sprague-Grundy (conform definitiei functiei {$mex$}). \r\n\r\nDin orice stare castigatoare putem ajunge intr-o stare pierzatoare. \r\n\r\nVom arata ca jocul $G$ este echivalent cu un joc $NIM$ cu $N$ gramezi in care gramada $i$ are {$mex(v{~i~})$} pietre. In jocul $NIM$ putem alege o gramada cu {$mex(x{~i~})$} pietre si sa luam cateva astfel incat in gramada sa ramana a<g(xi) pietre. Acestei mutari in jocul NIM ii corespunde o mutare in jocul compus G in care se alege jocul individual Gi si se muta din stare curenta xi intr-o stare y cu g(y)=a. Deoarece a<g(xi) va exista mereu o astfel de stare y. Nu vom lua in considerare mutarile cand dintr-o stare xi se muta intr-o stare y cu g(y)>g(xi) deoarece urmatorul jucator poate muta din starea y intr-o stare z cu g(z)=g(xi) si anuleaza practic mutarea precedentului. (de editat)\r\n\r\np{margin:1em; padding: 0.5em; height: 45px; border-top: 1px solid silver;}=. \r\n\'Notiuni de baza\':teoria-jocurilor | \'Jocul NIM\':teoria-jocurilor/jocul-nim | \'Numere Sprague-Grundy\':teoria-jocurilor/numere-SG |\r\n\'*Adunarea jocurilor*\':teoria-jocurilor/adunarea-jocurilor | \'w-numere\':teoria-jocurilor/w-numere | \'Aplicatii si probleme\':teoria-jocurilor/probleme',256,'protected',NULL,NULL),('teoria-jocurilor/notiuni','Notiuni de baza','2008-08-28 10:42:44','2008-11-16 12:20:51','h1. Teoria jocurilor\r\n\r\n(Categoria _Teoria jocurilor_, Autor _Filip Cristian Buruiana_)\r\n\r\n(toc)*{text-align:center} *Capitole*\r\n* \'*Notiuni de baza*\':teoria-jocurilor\r\n* \'Jocul NIM\':teoria-jocurilor/jocul-nim\r\n* \'Numere Sprague-Grundy\':teoria-jocurilor/numere-SG\r\n* \'Adunarea jocurilor\':teoria-jocurilor/adunarea-jocurilor\r\n* \'w-numere\':teoria-jocurilor/w-numere\r\n* \'Aplicatii si probleme\':teoria-jocurilor/probleme\r\n\r\nh2. Notiuni de baza\r\n\r\n\r\nPrin _joc_ se intelege un sir de decizii (actiuni, mutari), luate de parti ale caror interese se ciocnesc. Jocurile studiate in acest articol sunt cele care au doi parteneri. De asemenea, toate jocurile analizate sunt jocuri cu _mutari libere_: la fiecare pas, jucatorul aflat la mutare poate alege sa efectueze una in mod constient, in functie de regulament si de situatia jocului la momentul respectiv.  Decizia nu este constransa de niciun factor aleator, precum zaruri, carti de joc sau monede.\r\n!<teoria-jocurilor?dice.jpg 30%! Pentru un joc dat, un jucator are strategie _sigura de castig_ daca acesta va castiga, prin mutari alese pe baza unui anumit criteriu in functie de starea de joc, indifierent de modul in care ar incerca adversarul sa ii impiedice victoria. In aceasta situatie, spunem ca jocul respectiv are _rezultatul predeterminat_. Mai jos sunt prezentate cele cinci conditii necesare si suficiente pentru ca un joc sa aiba rezultatul predeterminat:\r\n\r\n* Se termina dupa un numar finit de pasi\r\n* Nu contine un element intamplator introdus de zaruri, carti de joc, etc.\r\n* Este un joc cu informatie completa, in care un jucator inainte de a executa o mutare cunoaste rezultatele tuturor mutarilor precedente\r\n* Un jucator poate vedea toate mutarile adversarului\r\n* Jucatorii muta alternativ\r\n\r\nh4(#pozitii). Pozitii castigatoare, pozitii pierzatoare\r\n\r\n!>teoria-jocurilor?winlose.jpg 48%!\r\n\r\nFie un joc in care rezultatul este predeterminat, deci unul dintre jucatori are strategie sigura de castig. Intr-un astfel de joc, multimea tuturor starilor (situatiilor) care pot aparea la un moment dat poate fi separata in doua submultimi $P$ si $N$ cu proprietatile:\r\n\r\n* intersectia dintre $P$ si $N$ este multimea vida\r\n* reuniunea multimilor $P$ si $N$ este multimea tuturor starilor de joc\r\n* din orice stare din $P$, putem ajunge, efectuand o mutare convenabila, intr-o stare din $N$\r\n* starile din care nu se mai poate efectua nicio mutare ({_terminale_}) sunt in multimea $N$\r\n* din orice stare neterminala din $N$, oricum am efectua o mutare, vom ajunge intr-o stare din $P$ \r\n\r\nO stare din multimea $P$ se va numi castigatoare sau $P$-pozitie, iar o stare din $N$ se va numi pierzatoare sau $N$-pozitie. Jucatorul aflat la mutare care este intr-o $P$-pozitie are strategie sigura de castig, in timp ce jucatorul care se afla intr-o $N$-pozitie va pierde, indiferent de mutarile pe care le va face, in situatia in care adversarul sau joaca optim.\r\nDemonstratia acestei afirmatii se bazeaza pe proprietatile de mai sus. Se observa urmatorul invariant: jucatorul cu strategie de castig se va afla mereu intr-o pozitie castigatoare in cazul unui joc perfect, in timp ce adversarul sau se va afla mereu intr-o pozitie de pierdere. Prin joc perfect se intelege ca jucatorul cu strategie de castig, aflat evident intr-o $P$-pozitie, isi va aduce adversarul intr-o pozitie de pierdere. Mai mult, adversarul, aflat acum intr-o pozitie de pierdere, nu poate lasa jocul decat intr-o pozitie de castig, si procedeul se reia, urmand alternanta starilor castig-pierdere, pana cand s-a ajuns intr-o stare terminala ({$N$}-pozitie), si nu se mai poate muta. Astfel, jucatorul aflat initial intr-o $P$-pozitie castiga, aducandu-si adversarul in imposibilitatea de a efectua o mutare.\r\n\r\np{margin:1em; padding: 0.5em; height: 45px; border-top: 1px solid silver;}=. \r\n\'*Notiuni de baza*\':teoria-jocurilor | \'Jocul NIM\':teoria-jocurilor/jocul-nim | \'Numere Sprague-Grundy\':teoria-jocurilor/numere-SG |\r\n\'Adunarea jocurilor\':teoria-jocurilor/adunarea-jocurilor | \'w-numere\':teoria-jocurilor/w-numere | \'Aplicatii si probleme\':teoria-jocurilor/probleme',2028,'protected',NULL,NULL),('teoria-jocurilor/jocul-nim','Jocul NIM','2008-07-21 13:12:12','2008-11-16 09:28:57','h1. Teoria jocurilor\r\n\r\n(Categoria _Teoria jocurilor_, Autor _Filip Cristian Buruiana_)\r\n\r\n(toc)*{text-align:center} *Capitole*\r\n* \'Notiuni de baza\':teoria-jocurilor\r\n* \'*Jocul NIM*\':teoria-jocurilor/jocul-nim\r\n* \'Numere Sprague-Grundy\':teoria-jocurilor/numere-SG\r\n* \'Adunarea jocurilor\':teoria-jocurilor/adunarea-jocurilor\r\n* \'w-numere\':teoria-jocurilor/w-numere\r\n* \'Aplicatii si probleme\':teoria-jocurilor/probleme\r\n\r\nh2. Jocul NIM\r\n\r\n!>teoria-jocurilor/jocul-nim?nim.jpg 90%!\r\nProbabil cel mai cunoscut joc impartial este jocul {$NIM$}. In acest joc, se considera $N$ gramezi, fiecare gramada avand un numar de pietre. La fiecare pas, jucatorul aflat la mutare elimina un numar nenul de pietre (eventual toate) dintr-o singura gramada. Jucatorii muta alternativ. Castigatorul este cel care ia ultimele pietre. De obicei, jocul $NIM$ se joaca cu $3$ gramezi de pietre, insa strategia de castig este aceeasi indiferent de numarul gramezilor.\r\n\r\nh4. Operatia _exclusive-or_\r\n\r\n!<teoria-jocurilor/jocul-nim?tabel.jpg 80%!\r\n&nbsp;\r\nPentru a determina strategia de castig ne vom folosi de operatia _xor_ ({_exclusive or_}) si proprietatile ei. Aceasta operatie se realizeaza prin operatorul $^$ in C/C++, si prin $xor$ in Pascal. Ca operatie pe biti, ea poate fi interpretata ca adunare in baza $2$ fara transport, dupa cum reiese din tabelul alaturat.\r\n&nbsp;\r\nAtunci cand facem _xor_ intre numere naturale trebuie mai intai sa transformam aceste numere in baza $2$, si apoi sa adunam fara transport bitii de pe fiecare pozitie. De exemplu, $1 xor 7 xor 5 = 3$, deoarece avem:\r\n\r\n{$1 = (001){~2~}$}  &nbsp;{$xor$}\r\n{$7 = (111){~2~}$}\r\n{$5 = (101){~2~}$}\r\n______________\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {${@(011)@}{~2~} = 3$}\r\n\r\nh4. Strategia de castig\r\n\r\nPe baza operatiei _xor_, strategia de castig pentru $NIM$ poate fi formulata conform urmatoarei teoreme:\r\n\r\n_Teorema_: Fie $N$ gramezi. Prima gramada are {$x{~1~}$} pietre, cea de a doua {$x{~2~}$}, si asa mai departe, pana la ultima care are {$x{~N~}$} pietre. O astfel de pozitie este pierzatoare in jocul de $NIM$ daca si numai daca _suma-xor_ a numerelor de pietre din gramezi este {$0$}, adica daca {$x{~1~} xor x{~2~} ... xor x{~N~} = 0$}.\r\n\r\nPentru a demonstra aceasta teorema, trebuie sa aratam ca dintr-o stare cu suma-xor egala cu $0$ (pierzatoare), oricum am muta, nu putem ajunge decat intr-o stare cu suma-xor nenula (castigatoare), si ca dintr-o stare castigatoare putem efectua o mutare in mod convenabil astfel incat sa ajungem intr-o stare de pierdere. \r\n\r\nSa presupunem prin reducere la absurd ca dintr-o stare cu suma-xor $0$ putem ajunge in alta stare care are suma-xor tot $0$. Selectam o gramada oarecare cu $y$ pietre si dorim sa eliminam un numar de pietre din aceasta gramada. Daca notam cu $S$ suma-xor a numerelor de pietre din celelalte $N-1$ gramezi neselectate, atunci avem {$S xor y = 0$}. Dar {$a xor b = 0$} daca si numai daca {$a = b$}, deci {$S = y$}. Daca din gramada selectata eliminam $x$ pietre, {$0 < x &le; y$}, pentru a ajunge intr-o stare tot cu suma-xor $0$ trebuie sa avem {$S xor (y-x) = 0$}, echivalent cu {$S = y-x$}. De aici si din {$S = y$} rezulta ca {$x = 0$}, fals, deoarece nu putem elimina $0$ pietre. Deci oricum am efectua o mutare dintr-o stare de pierdere vom ajunge intr-o stare castigatoare.\r\n\r\nRamane de demonstrat ca din orice stare de castig putem sa aducem adversarul intr-o stare pierzatoare. Fie $S$ suma-xor a marimilor celor $N$ gramezi. Daca exista o gramada cu $y$ pietre astfel incat {$y > y xor S$}, atunci putem elimina {$y - y xor S$} pietre din aceasta gramada, ramanand cu {$y - (y - y xor S) = y xor S$} pietre. Din gramada cu $y$ pietre am obtinut o gramada cu {$y xor S$} pietre, deci noua suma-xor va fi obtinuta din cea veche ({$S$}) xorata cu ea insasi: {$(... xor y) xor S = S xor S = 0$}. In consecinta, daca exista o gramada cu proprietatea de mai sus, atunci putem ajunge din orice stare de castig in una de pierdere. Fie $p$ pozitia celui mai semnificativ bit din reprezentarea binara a lui {$S$}. Printre cele $N$ gramezi, va exista cel putin una care are bitul de pe pozitia $p$ egal cu $1$ (altfel bitul $p$ din $S$ ar fi fost {$0$}). Fie $y$ numarul de pietre dintr-o astfel de gramada. Bitii de $1$ din $y$ si $S$ de pe pozitia $p$ se vor anula pentru ca {$1 xor 1 = 0$}. Astfel, vom avea {$y > y xor S$}.\r\n\r\n!teoria-jocurilor/jocul-nim?xor.jpg 90%!\r\n\r\nIn consecinta, putem ajunge din orice stare de castig intr-o stare de pierdere. Teorema este astfel demonstrata.\r\n\r\np{margin:1em; padding: 0.5em; height: 45px; border-top: 1px solid silver;}=. \r\n\'Notiuni de baza\':teoria-jocurilor | \'*Jocul NIM*\':teoria-jocurilor/jocul-nim | \'Numere Sprague-Grundy\':teoria-jocurilor/numere-SG |\r\n\'Adunarea jocurilor\':teoria-jocurilor/adunarea-jocurilor | \'w-numere\':teoria-jocurilor/w-numere | \'Aplicatii si probleme\':teoria-jocurilor/probleme',1,'protected',NULL,NULL),('winter-challenge-2008/runda-1/solutii/tero','winter-challenge-2008/runda-1/solutii/tero','2008-01-27 19:04:29','2008-08-30 12:05:31','h2(#tero). \'Tero\':problema/tero\r\n\r\nDupa cum multi si-au dat seama, problema este asemanatoare cu cea a lui Dan Ionut Fechete, \"Trafic\":problema/trafic.\r\n\r\nFiind niste limite de timp foarte mari, \"cautare binara + flux\":http://campion.edu.ro/problems.php?mode=view_solution&problem_id=279&group_number=3&year=2005 nu intra in timp. \r\n\r\nPentru a se incadra in limita stabilita, era necesar algoritmul lui Karzanov pentru flux maxim intr-o retea. Acest algoritm a fost prezentat in cadrul taberei de pregatire a Lotului National, de catre Mugurel Ionut Andreica (\"Algoritmi de flux maxim in retele\":http://infoarena.ro/downloads?action=download&file=flux_maxim_in_retele.doc) si constituie o mica parte din teza sa de Masterat.\r\n\r\nPresupunem, intial, ca pe fiecare muchie poate fi plasat +doar un singur soldat+. Cum $S$ < $M$, acest lucru este intotdeauna posibil. Astel, fiecarei muchii i se va atribui capacitatea $1$. Rulam algoritmul de flux maxim si retinem fluxul. Calculam, pentru fiecare muchie, maximul dintre distantele de la aceasta pana la nodul $1$ si pana la nodul $N$, apoi sortam descrescator muchiile, in functie de aceasta valoare. \r\nIn continuare, vom incerca sa gasim pozitia soldatului care ajunge ultimul in orasul atacat, parcurgand muchiile in ordinea sortarii: pentru o muchie $e$, vrem sa stabilim daca, pozitionand mai mult de un soldat pe ea (crescand capacitatea la o valoare foarte mare), va creste sau nu fluxul initial. Daca nu va modifica valoarea fluxului, inseamna ca putem pune oricati soldati pe $e$, fara a influenta rezultatul final, deci muchia este inutila. Daca modifica valoarea fluxului, asta inseamna ca cel mai lenes soldat trebuie sa fie pozitionat pe $e$ si afisez valoarea maximului dintre distante pentru muchia respectiva. \r\n\r\nPentru a avea o complexitate +teoretica+ de $O(M*N^3^)$ (in practica merge cu mult mai repede), va trebui sa facem doua optimizari:\r\n\r\n# se va reface reteaua reziduala L0 (vezi articolul lui Mugurel) +doar daca exista un drum nesaturat, ce contine muchia $e$+\r\n# pentru a verifica daca fluxul creste, nu se va relua tot algoritmul de flux maxim, ci se vor folosi informatiile anterior calculate.\r\n\r\nDesi nu ar fi trebuit sa ia decat $30$ de puncte, in solutia prezentata de Ionut Fechete, se putea inlocui Edmond-Karp cu algoritmul lui Dinic (vezi articolul lui Mugurel), obtinandu-se astfel punctaj maxim. Singurul care a facut acest lucru in concrus (si singurul care a obtinut punctaj foarte mare la aceasta problema), a fost \"Bogdan Tataroiu\":utilizator/bogdan2412.\r\n\r\nIn arhiva vom incerca sa schimbam testele astfel incat aceasta solutie sa nu obtina punctaj maxim.',6756,'public',NULL,NULL),('blog/google-lanseaza-chrome','Google lanseaza browserul Chrome','2008-09-02 01:00:24','2008-11-15 13:41:14','!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/google-lanseaza-chrome?google-chrome-logo.jpg! In sfarsit \'Google lanseaza Chrome\':http://googleblog.blogspot.com/2008/09/fresh-take-on-browser.html , un browser open source.\r\n\r\nLansarea a fost anuntata prin un \'comic book\':http://books.google.com/books?id=8UsqHohwwVYC&printsec=frontcover#PPP1,M1 foarte misto facut, ce sumarizeaza bine feature-urile interesante ale acestui produs.\r\n\r\nChestia ce mi se pare mie cea mai utila este faptul ca fiecare tab este independent de celelalte ruland in un \"proces\" diferit. Asta inseamna ca daca un tab iti crapa poti sa il inchizi fara sa inchizi restul taburilor.\r\n\r\n!{margin: 10px; margin-left: 10px; border: 1px solid gray;}>blog/google-lanseaza-chrome?google-chrome-screenshot.jpg 70%! Browserul este construit peste \'WebKit\':http://webkit.org/ un layout engine open source folosit de Safari (browserul Apple). Acest engine este destul de rapid si din cate am inteles e mult mai curat si mai usor de folosit pentru programatori, decat Gecko (layout engine-ul folosit de FireFox).\r\n\r\nDe asemenea Chrome are integrat un javascript engine numit V8 care se lauda cu o performanta foarte buna.\r\n\r\nEu consider ca acest proiect va fi un pas important in fata pentru lumea browserelor, o data prin cresterea concuretei si apoi prin faptul ca proiectul e open source iar ideile bune vor putea fi copiate si integrate rapid in celelalte broswere.',1490,'protected',3218,NULL),('blog/un-widget-pentru-erori-404','Un widget pentru erori 404','2008-09-02 03:25:04','2008-11-15 13:41:14','Proiectul pe care am inceput eu la Google acum aproape doi ani, a lansat relativ recent \'un widget \':http://googlewebmastercentral.blogspot.com/2008/08/make-your-404-pages-more-useful.html pentru detinatorii de siteuri, care face paginile de erori 404 ceva mai utile. Deocamdata widgetul e in faza experimentala. El incearca sa vada daca ati facut o greseala la tastare si sa o corecteze oferindu-va un URL corect cat mai apropiat de cel tastat. De asemenea widgetul mai are un link spre sitemap, unul spre directorul superior si o casuta de cautare ce contine sugestii pentru cautare.\r\n\r\nProiectul a fost pornit de \'Mihai Stroe\':http://www.google.com/search?hl=en&q=Mihai+Stroe&btnG=Google+Search&aq=f&oq= ca un \'proiect de 20%\':http://www.google.com/search?hl=en&q=20+percent+time&btnG=Search . Acest proiect e unul de suflet pentru mine, prin el am cunoscut mult din infrastructura Google, am lucrat cu \'cativa\':http://www.google.com/search?hl=en&q=Mihai+Stroe&btnG=Google+Search&aq=f&oq= \'oameni\':http://www.google.com/search?hl=en&q=Radu+Berinde&btnG=Google+Search&aq=f&oq= \'foarte\':http://www.google.com/search?hl=en&q=Dan+Popovici&btnG=Search  \'buni\':http://www.google.com/search?hl=en&q=Sorin+Stancu+Mara&btnG=Search , si am vazut cum se duce la Google un proiect de la faza de prototip pana la cateva lansari oficiale.\r\n\r\nLa multe succese in continuare Mihai si echipei!\r\n\r\n*Update* Acum ca ati folosit putin Chrome poate ati remarcat pagina de erori DNS sau 404. Aceasta pagina e si ea o aplicatie a proiectului de care va ziceam.',1490,'protected',3217,NULL),('blog/zece-ani-de-google','Zece ani de Google','2008-09-08 11:10:04','2008-11-15 13:41:14','Cu ocazia aniversarii a 10 ani de la existenta Google, ziarul Evenimentul Zilei a scris un articol mai amplu cu acest subiect. Am fost contactat de unul dintre redactorii lor pentru a da un scurt interviu. La fel s-a intamplat si cu Cristi Strat si Mihai Stroe. Chiar daca redactorul nu a reprodus complet intrebarile si raspunsurile, ci doar a luat partile care i s-au parut lui mai interesante, articolul este unul foarte reusit. Asa cum vorbeam cu Radu Grigore, este unul dintre putinele articole de genul asta la care nu imi pun mainile in cap.\r\n\r\nDe multe ori cei ce scriu in ziare despre IT nu au legatura prea mare cu domeniul si fac confuzii mari.\r\nUn exemplu: in \'articolul\':http://www.adevarul.ro/articole/fostii-olimpici-ii-antreneaza-pe-concurentii-de-la-olimpiade/305061 din Adevarul despre siteul infoarena, pe la sfarsitul articolului aparea un paragraf in care se spunea de cativa programatori din Galati care au salarii de 500 de euro. Informatia respectiva nu avea treaba cu tot restul articolului, si nici macar nu era interesanta pentru ca in Bucuresti programatorii decenti se asteapta la salarii in jur de 1000 de euro.\r\n\r\nEu cred ca intrebarile si raspunsurile din interviurile pentru Evenimentul Zilei sunt destul de interesante, mai ales pentru tipul de public pe care il are blogul infoarena. Mihai si Cristi au fost si ei de acord, asa ca le voi publica aici in urmatoarele zile.\r\n\r\nPana atunci puteti citi articolul din Evenimentul Zilei \'AICI\':http://www.evz.ro/articole/detalii-articol/819647/Creierele-romanesti-din-solda-imperiului-Google/\r\n\r\n',1490,'protected',3223,NULL),('acm-icpc-upb-2008/probleme','Probleme ACM ICPC UPB 2008','2008-09-08 19:50:30','2008-09-12 10:12:19','!acm-icpc-upb-2008?logo1.jpg 50%!\r\n\r\nh1. == roundparam(round_id=\"acmpoli2008-1\" param=\"title\") ==\r\n\r\n*{color:red}ATENTIE! Datorita multiplelor probleme aparute am decis sa extindem durata concursului la 6 ore*\r\n\r\n(htabs)* \'Despre...\':acm-icpc-upb-2008\r\n*(active) \'Probleme\':acm-icpc-upb-2008/probleme \r\n* \'Clasament\':acm-icpc-upb-2008/clasament\r\n\r\nh2. Probleme\r\n\r\nAici vei gasi problemele atunci cand va incepe concursul.\r\n\r\n== Tasks(round_id=\"acmpoli2008-1\" score=\"1\")==',2092,'protected',NULL,NULL),('sandbox/code-test','sandbox/code-test','2006-11-28 20:47:04','2009-03-07 19:17:31','h1. Keep on codin\'\r\n\r\n== code(c) |\r\n#include <stdio.h>\r\n\r\nint main(void) {\r\n    printf(\"Hello World\\n\");\r\n    return 0;\r\n}\r\n==\r\n\r\n== code(pas) |\r\nbegin\r\n\r\n  writeln(\'Hello world\');\r\n\r\nend.\r\n==\r\n\r\nh2. Capsunele pe campii\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n\r\nint main() {\r\n    cout<<\"Hello World\"<<endl;\r\n    return 0;\r\n}\r\n==\r\n\r\n== code(pas) |\r\nbegin\r\n  writeln(\'Hello world\');\r\nend.\r\n==\r\n\r\nh3. Use only F/OSS, Microsft sucks ;) just because they like design NOT the code itself.\r\n\r\nHowever, on a GNU system NEVER type *sudo make me sandwich*, and expect the results...',8700,'public',NULL,NULL),('ia3','ia3','2008-04-08 19:58:00','2008-09-08 18:06:33','h2. Introducere\r\n\r\nInca de prima data cand am vizitat site-ul infoarena am simtit ceva diferit fata de alte comunitati. La acea vreme infoarena era unul dintre primele site-uri open-source la care eram membru. Nu prea stiam pe atunci prea multe despre software-ul liber, dar astazi multumesc tuturor celor care m-au ajutat si indrumat de am ajuns aici.\r\n\r\nSunt un utilizator infoarena fericit si am decis sa fac un wishlist, la fel cum fac pentru fiecare software open-source care-l folosesc zilnic.Iubesc comunitatea open-source in primul rand pentru ca munca se bazeaza pe voluntariat si oricand pot participa sa fac lucrurile mai bune, asa ca am sa enunt cateva idei care le pot implementa chiar eu pentru infoarena 3.\r\n\r\nh2. Wishlist\r\n\r\n* posibilitatea alegerii unei probleme aleator\r\n* nickul <11 caractere & numele unui utilizator <24 caractere\r\n* confirmare email la noii utilizatori inregistrati\r\n* CAPTCHA\r\n* O mica cutie de upload de 1MB\r\n* Cateva citate aleatoare si anunturi despre fosti olimpici\r\n* posibilitatea de a purta un nume cu caratere romanesti\r\n* MySQL in utf-8\r\n* Transformarea unor functii ale siteului in scripturi AJAX spre exemplu plugin-ul karma\r\n* Inlocuirea pluginului karma cu thanks plugin\r\n\r\nh2. Comentarii\r\n\r\nTo be continued.',7812,'public',NULL,NULL),('runda/acm-icpc-upb-2008','runda/acm-icpc-upb-2008','2008-09-10 12:35:56','2008-09-10 12:35:56','Scrie aici despre runda/acm-icpc-upb-2008',6587,'public',NULL,NULL),('acm-icpc-upb-2008/clasament','Clasament Selectie ACM ICPC UPB 2008','2008-09-08 16:02:03','2008-09-12 10:12:38','!acm-icpc-upb-2008?logo1.jpg 50%!\r\n\r\nh1. == roundparam(round_id=\"acmpoli2008-1\" param=\"title\") ==\r\n\r\n*{color:red}ATENTIE! Datorita multiplelor probleme aparute am decis sa extindem durata concursului la 6 ore*\r\n\r\n(htabs)* \'Despre...\':acm-icpc-upb-2008\r\n* \'Probleme\':acm-icpc-upb-2008/probleme \r\n*(active) \'Clasament\':acm-icpc-upb-2008/clasament\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"acmpoli2008-1\")==',2092,'protected',NULL,NULL),('utilizator/upb_sdv','Profil upb_sdv','2008-09-12 03:09:44','2008-09-12 03:09:44','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',8461,'public',NULL,NULL),('acm-icpc-upb-2008','Selectie echipe ACM ICPC, UPB 2008','2008-09-08 16:02:03','2008-09-12 10:16:45','!acm-icpc-upb-2008?logo1.jpg 50%!\r\n\r\nh1. == roundparam(round_id=\"acmpoli2008-1\" param=\"title\") ==\r\n\r\n*{color:red}ATENTIE! Datorita multiplelor probleme aparute am decis sa extindem durata concursului la 6 ore*\r\n\r\n(htabs)*(active) \'Despre...\':acm-icpc-upb-2008\r\n* \'Probleme\':acm-icpc-upb-2008/probleme \r\n* \'Clasament\':acm-icpc-upb-2008/clasament\r\n\r\nh2. Despre concurs\r\n\r\nConcursul constituie selectia oficiala a celor $3$ echipe ce vor reprezenta Universitatea Politehnica din Bucuresti (UPB) la etapa regionala sud-est europeana a concursului ACM ICPC, ce va avea loc in luna octombrie. In afara echipelor din UPB, care vor participa pentru a obtine unul dintre cele $3$ locuri \"castigatoare\", sunteti invitati sa participati cu totii la concurs, pe care il puteti considera o ocazie buna de a va reveni din \"amorteala\" din timpul verii si de a va \"intra in mana\" pentru concursurile cu miza mai importanta ce urmeaza sa aiba loc.\r\n\r\nConcursul incepe ==roundparam(round_id=\"acmpoli2008-1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"acmpoli2008-1\" param=\"duration\" strong=\"true\")== ore. Participanii vor avea de rezolvat 10 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 10^00^* daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating, insa poti sa participi oricum!\r\n\r\n== roundregister(round_id=\"acmpoli2008-1\") ==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==user(user=\"mugurelionut\" type=\"tiny\")==\r\n* ==user(user=\"mpatrascu\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru!\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti problemele, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. Pe tot parcursul rundei, \'evaluatorul\':documentatie/evaluator infoarena iti va testa solutiile pentru corectitudine, iar clasamentul se va actualiza in timp real.\r\n\r\nh2. Prima data pe _infoarena_?\r\n\r\n\'infoarena\':/ ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi si vezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n',2092,'protected',NULL,NULL),('runda/onisim2009-7','onisim2009-7','2009-08-23 10:13:27','2009-08-23 10:32:34','h1. %{color:blue}ONiSiM% 2009 clasa a VII-a\r\n\r\n== roundregister(round_id=\"onisim2009-7\") ==\r\n\r\nh4. Concursul este o simulare a %{color:blue}Olimpiadei nationale de informatica 2009% .\r\n\r\nh4. Runda propune spre rezolvare cele 3 propleme propuse pentru %{color:blue}clasa a 7-a% .\r\n\r\nh4. Daca nu ai avut ocazia sa rezolvi aceste probleme o vei avea acum.\r\n\r\nh1. Succes !\r\n\r\n|**DATA CONCURSULUI**|%{color:blue}**DUMiNiCA 23 AUGUST 2009**%|\r\n|**ORA DE INCEPERE**|%{color:blue}**13:30:00**%|\r\n|**ORA DE FINALIZARE**|%{color:blue}**17:30:00**%|\r\n|**TIMP DE LUCRU**|%{color:blue}**4 ORE**%|\r\n|**REZULTATE**|\'*RANKS-aici*\':runda/onisim2009-7/clasament|\r\n\r\nh1. %{color:blue}Probleme%\r\n\r\nh1.  \r\n\r\n==Tasks(round_id=\"onisim2009-7\" score=\"1\")==',10498,'round: onisim2009-7',4117,NULL),('runda/euclid/clasament','Clasament euclid','2010-04-11 13:20:36','2010-04-11 13:20:36','h1. Clasament ==roundparam(round_id=\"euclid\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"euclid\" detail_task=\"true\")==',12519,'round: euclid',NULL,NULL),('runda/euclid_2','euclid_2','2010-04-11 13:30:35','2010-04-11 13:30:35','h1. == roundparam(round_id=\"euclid_2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"euclid_2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"euclid_2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"euclid_2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"euclid_2\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/euclid_2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"euclid_2\" score=\"1\")==',12519,'round: euclid_2',NULL,NULL),('teoria-jocurilor/w-numere','w-numere','2008-07-21 13:16:46','2008-09-14 09:44:18','h1. Teoria jocurilor\r\n\r\n(Categoria _Teoria jocurilor_, Autor _Filip Cristian Buruiana_)\r\n\r\n(toc)*{text-align:center} *Capitole*\r\n* \'Notiuni de baza\':teoria-jocurilor\r\n* \'Jocul NIM\':teoria-jocurilor/jocul-nim\r\n* \'Numere Sprague-Grundy\':teoria-jocurilor/numere-SG\r\n* \'Adunarea jocurilor\':teoria-jocurilor/adunarea-jocurilor\r\n* \'*w-numere*\':teoria-jocurilor/w-numere\r\n* \'Aplicatii si probleme\':teoria-jocurilor/probleme\r\n\r\nh2. w-numere\r\n\r\nIn capitolul precedent am observat diferite modalitati de a aduna jocuri. Jucatorul care efectua ultima mutare in aceste jocuri compuse castiga. Putem extinde insa complexitatea jocurilor analizate, considerand ca pentru un joc compus $G$ castigatorul este cel care castiga primul unul dintre jocurile independente care compun jocul {$G$}. Acest tip de joc este numit sugestiv \"_The Winner takes it all_\" (WTIA).\r\n\r\n_Definitie_: Fie $G$ suma jocurilor {$G{~1~}$}, {$G{~2~}$}, ..., {$G{~P~}$}. Jucatorul aflat la mutare alege unul din jocurile care il compun pe $G$ si efectueaza o mutare in jocul ales. Intr-un joc de tip _WTIA_, daca unul din jucatori pierde un joc independent {$G{~i~}$}, atunci el pierde intreg jocul {$G$}.\r\n\r\nh4. Jocul NIM pe nivele\r\n\r\nJocul $NIM$ este un caz trivial daca se joaca dupa regulile {$WTIA$}, deoarece jucatorul care muta primul poate alege o gramada oarecare si sa ia toate pietrele din aceasta gramada, castigand astfel un joc independent (gramada din care s-a facut mutarea) si, implicit, tot jocul cu mai multe gramezi. Putem introduce insa urmatoarea variatie a jocului $NIM$, care nu este deloc triviala: \"Fie $N$ supergramezi de monede, fiecare supergramada fiind formata dintr-un numar oarecare de gramezi asezate una peste cealalta. La fiecare mutare un jucator alege o supergramada si ia cel putin o moneda din cea mai de sus gramada nevida. Cand un jucator ia ultimile monede dintr-o supergramada jocul se termina si acesta este declarat castigator.\"\r\n\r\nSa consideram un exemplu cu doua supergramezi. Prima dintre acestea contine gramezi de dimensiune {$4$}, {$9$} si {$3$}, de la baza inspre varf, iar a doua supergramada este compusa din doua gramezi de cate $2$ si respectiv $5$ pietre. Primul jucator poate alege sa elimine pietre din prima supragramada sau din cea de a doua. In cazul in care alege sa faca mutarea din prima supragramada, atunci el poate lua intre una si trei pietre din gramada din varf. Daca ia trei pietre, gramada de sus se goleste, iar noua gramada de la varf din care se vor face mutari in prima supergramada va contine $9$ pietre.\r\n\r\nh4. Clasificarea pozitiilor\r\n\r\nIn acest joc $NIM$ pe nivele identificam urmatoarele pozitii speciale (numite _superpozitii_):\r\n\r\n* _superpierzatoare_, in care exista o supergramada care nu contine nicio gramada. In acest caz, jucatorul aflat la mutare este considerat pierzator.\r\n* _supercastigatoare_, in care jucatorul la rand va castiga dintr-o singura mutare. Toate pozitiile care au cel putin o supergramada formata dintr-o singura gramada nevida sunt supercastigatoare deoarece un jucator poate goli aceasta supergramada la urmatoarea mutare, castigand jocul. \r\n\r\nToate celelalte pozitii (in care fiecare supergramada contine cel putin doua gramezi) sunt considerate normale.\r\n\r\nDaca jucatorul aflat la mutare gaseste jocul intr-o pozitie superpierzatoare atunci a pierdut. Daca in schimb pozitia este una supercastigatoare, el va castiga dintr-o singura mutare. Daca jucatorul se afla intr-o pozitie normala, atunci el poate aduce jocul in alta pozitie normala sau intr-o pozitie supercastigatoare. Aducerea adversarului intr-o pozitie supercastigatoare va duce insa la pierderea jocului. In consecinta, jucatorul aflat in pozitii normale va muta doar in alte pozitii normale. Se observa ca atunci cand un jucator nu mai poate muta intr-o pozitie normala pierde jocul deoarece va fi obligat sa mute intr-o pozitie supercastigatoare.\r\n\r\nh4. Functia w\r\n\r\nPentru a determina daca dintr-o pozitie jucatorul aflat la mutare are strategie de castig vom introduce o functie {$w$} astfel:\r\n\r\n_Definitie_: Functia $w$ este o functie definita pe multimea starilor unui joc cu valori in multimea numerelor naturale reunita cu indicatorii speciali $SC$ (pentru o pozitie supercastigatoare) si $SP$ (pentru una superpierzatoare). Functia w se obtine astfel:\r\n\r\n# {$w(x) = SP$}, daca $x$ este o pozitie superpierzatoare\r\n# {$w(x) = SC$}, daca exista o stare $u$ astfel incat din $x$ sa se poata ajunge in $u$ printr-o mutare si {$w(u) = SP$}\r\n# {$w(x) = minim(n &ge; 0 | n diferit de w(u), oricare ar fi u stare vecina a lui x pentru care w(u) este numar natural)$}. Prin stare vecina se intelege ca se poate ajunge dintr-o singura mutare din $x$ in {$u$}.\r\n\r\nAltfel spus, pozitiile superpierzatoare vor avea asociat indicatorul $SP$, iar cele supercastigatoare indicatorul $SC$. Eliminand toate aceste pozitii speciale vom obtine un graf in care toate pozitiile sunt normale. Daca aplicam algoritmul functiei $mex$ de determinare a valorilor Sprague-Grundy pe pozitiile ramase obtinem chiar valorile returnate de functia {$w$} pentru aceste pozitii. \r\n\r\np{padding:0.1em 0.5em 0.5em 0.5em; margin:0.5em; border: 1px solid #666666;background-color:#E2E2E2}. \r\n_Teorema_: Asemanator cu functia {$mex$}, o pozitie $x$ este pierzatoare daca si numai daca {$w(x) = SP$} sau {$w(x) = 0$}.\r\n\r\n_Demonstratie_: Daca {$w(x) = SP$}, atunci evident $x$ este o pozitie de pierdere. Daca {$w(x)$} este numar natural si {$w(x) > 0$}, atunci este posibil ca jucatorul la mutare sa mute intr-o pozitie $y$ cu {$w(y) = 0$} (conform definitiei). Dintr-o pozitie {$w(x) = 0$} se poate muta numai in pozitii supercastigatoare sau in pozitii cu {$w(x) > 0$} (intr-o stare superpierzatoare nu se poate muta, deoarece in aceste stari se poate ajunge doar din stari supercastigatoare). Dat fiind faptul ca jocul este finit, se va ajunge la situatia in care din pozitia {$w(x) = 0$} nu mai exista decat mutari in pozitii {$SC$}.\r\n\r\np{padding:0.1em 0.5em 0.5em 0.5em; margin:0.5em; border: 1px solid #666666;background-color:#E2E2E2}. \r\n_Teorema_: Fie un joc $G$ definit ca adunarea de tip $WTIA$ a jocurilor {$G{~1~}$}, {$G{~2~}$}, ... {$G{~p~}$}. Pozitia {$x$} din jocul {$G$}, care este un {$p$}-uplu de forma {$(x{~1~}, x{~2~}, ... x{~p~})$}, unde {$x{~i~}$} este starea din jocul {$G{~i~}$}, este pierzatoare daca si numai daca cel putin una din urmatoarele conditii este indeplinita:\r\n&nbsp;\r\n1. exista un joc $i$ astfel incat {$w(x{~i~}) = SP$}\r\n2. pentru orice joc $i$, {$w(x{~i~})$} este numar natural. In plus, {$w(x{~1~}) xor w(x{~2~}) xor ... xor w(x{~p~}) = 0$}.\r\n\r\n_Demonstratie_: Vom verifica daca pentru aceasta impartire sunt indeplinite conditiile pentru $P$-pozitii si $N$-pozitii, prezentate \'aici\':teoria-jocurilor/notiuni#pozitii. Daca exista un joc $i$ astfel incat {$w(x{~i~}) = SP$}, atunci starea $x$ este una terminala si este de pierdere. Mai mult, din orice pozitie pierzatoare neterminala conform impartirii de mai sus, oricum am efectua o mutare, vom ajunge intr-o pozitie castigatoare.\r\n\r\nToate pozitiile terminale x au un subjoc xi care este SP, altfel s-ar mai putea efectua mutari. Daca un jucator este intr-o pozitie pierzatoare atunci w(x) = SP sau {$w(x{~1~}) xor w(x{~2~}) xor ... xor w(x{~p~}) = 0$}. Primul caz a fost analizat mai sus. Daca un jucator muta in orice subjoc k atunci fie va muta intr-o pozitie supercastigatoare in acel joc, fie va muta intr-o pozitie y cu w(y) Ã¢ï¿½Â  w(xk). In abele cazuri va muta in pozitii castigatoare.\r\nDaca un jucator este intr-o pozitie castigatoare atunci w(x) = SC sau w(x1) xor w(x2) xor ... xor w(xp) diferit de {$0$}. In primul caz va exista un subjoc xk astfel incat w(xk) = SC. Un jucator va putea muta in acest subjoc intr-o pozitie superpierzatoare. Daca suma nim a w-numerelor subjocurilor este diferita de 0 atunci un jucator poate gasi cu usurinta o mutare care sa o modifice in 0, procedand similar jocului Nim.\r\n\r\nh4. Aplicatie pe jocul NIM pe nivele\r\n\r\n\r\np{margin:1em; padding: 0.5em; height: 45px; border-top: 1px solid silver;}=. \r\n\'Notiuni de baza\':teoria-jocurilor | \'Jocul NIM\':teoria-jocurilor/jocul-nim | \'Numere Sprague-Grundy\':teoria-jocurilor/numere-SG |\r\n\'Adunarea jocurilor\':teoria-jocurilor/adunarea-jocurilor | \'*w-numere*\':teoria-jocurilor/w-numere | \'Aplicatii si probleme\':teoria-jocurilor/probleme',256,'protected',NULL,NULL),('teoria-jocurilor/probleme','Aplicatii, probleme','2008-07-21 13:17:22','2008-09-14 12:16:06','h1. Teoria jocurilor\r\n\r\n(Categoria _Teoria jocurilor_, Autor _Filip Cristian Buruiana_)\r\n\r\n(toc)*{text-align:center} *Capitole*\r\n* \'Notiuni de baza\':teoria-jocurilor\r\n* \'Jocul NIM\':teoria-jocurilor/jocul-nim\r\n* \'Numere Sprague-Grundy\':teoria-jocurilor/numere-SG\r\n* \'Adunarea jocurilor\':teoria-jocurilor/adunarea-jocurilor\r\n* \'w-numere\':teoria-jocurilor/w-numere\r\n* \'*Aplicatii si probleme*\':teoria-jocurilor/probleme\r\n\r\nh2. Aplicatii, probleme\r\n\r\nIn continuare vom analiza cateva aplicatii si probleme in care se aplica teoria si teoremele prezentate in capitolele precedente.\r\n\r\nh3. 1. \'Game\':problema/game, concursul national Bursele Agora, 2004\r\n\r\nFie $N$ gramezi de pietre si doi jucatori care muta alternativ. O mutare consta din alegerea unei gramezi si eliminarea unei singure pietre sau a unui numar prim de pietre din gramada aleasa. Castiga jucatorul care ia ultimele pietre. Sa se precizeze care din cei doi jucatori va castiga.\r\n\r\nJocul de mai sus este similar cu jocul de {$NIM$}, numai ca aici nu putem lua oricate pietre dintr-o gramada, ci doar o singura piatra sau un numar prim de pietre. Pentru a rezolva problema, facem urmatoarea observatie: jocul cu mai multe gramezi respecta \'proprietatile unei adunari de tip xor\':teoria-jocurilor/adunarea-jocurilor a jocurilor cu o singura gramada, deoarece la fiecare pas jucatorul care urmeaza trebuie sa isi aleaga exact un joc (o gramada) si sa faca o mutare in jocul respectiv. Conform teoremei, rezulta ca trebuie sa determinam valoarea $mex$ pentru o gramada cu $x$ pietre, si apoi sa facem suma-xor a valorilor corespunzatoare marimilor celor $N$ gramezi. In cazul in care suma-xor este diferita de {$0$} va castiga jucatorul care muta primul, iar in caz contrar va castiga celalalt jucator.\r\n\r\n!<teoria-jocurilor/probleme?graf1.jpg 90%!\r\nMai ramane de calculat valoarea $mex$ pentru o gramada cu {$x$} pietre. Putem construi un graf orientat, aciclic, in care nodul numerotat cu {$x$}, {$x &ge; 0$}, reprezinta o gramada de dimensiune {$x$}. In acest graf va exista arc de la $x$ la $y$ doar daca $x - y$ este egal cu $1$ sau este un numar prim. Astfel, un arc reprezinta o posibila mutare in jocul dat.\r\n \r\nVom incerca sa calculam valorile Sprague-Grundy corespunzatoare nodurilor acestui graf. In tabelul de mai jos sunt prezentate aceste valori pentru primele noduri ale grafului.\r\n\r\n|_. nod|&nbsp;0|&nbsp;1|&nbsp;2|&nbsp;3|&nbsp;4|&nbsp;5|&nbsp;6|&nbsp;7|&nbsp;8|&nbsp;9|&nbsp;10|\r\n|_. SG|&nbsp;0|&nbsp;1|&nbsp;2|&nbsp;3|&nbsp;0|&nbsp;1|&nbsp;2|&nbsp;3|&nbsp;0|&nbsp;1|&nbsp;2|\r\n\r\nSe poate demonstra prin inductie dupa $n$ ca valoarea asociata nodului $n$ este {$n modulo 4$}. Pentru {$0 &le; n &le; 3$} afirmatia este adevarata. Presupunem afirmatia adevarata pentru orice {$m < n$}. Din gramada de $n$ obiecte pot fi luate unul, doua sau trei obiecte, deci valoarea pentru $n$ nu poate fi niciuna din valorile pentru {$n-1$}, {$n-2$} si {$n-3$}. Valoarea {$n modulo 4$} este deocamdata cea mai mica valoare care nu este inca eliminata si poate corespunde gramezii cu $n$ obiecte. Este usor de aratat ca aceasta valoare nu va fi eliminata. Presupunem prin reducere la absurd ca valoarea ar fi eliminata, deci putem alege un numar prim $p$ de obiecte din cele $n$ astfel incat {$(n-p) modulo 4 = n modulo 4$}, echivalent cu {$p modulo 4 = 0$}, fals, deoarece $p$ era un numar prim. In concluzie, afirmatia pentru $n$ este adevarata si, conform principiului inductiei matematice, este adevarata pentru orice $n$ numar natural. In concluzie, valoarea Sprague-Grundy pentru nodul $n$ este {$n modulo 4$}. \r\n\r\nCoreland toate observatiile de mai sus, primul jucator castiga daca si numai daca {$(x{~1~} mod 4) xor (x{~2~} mod 4) ... xor (x{~N~} mod 4)$} este diferit de {$0$}. \r\n\r\nh3. 2. \'Cartonase\':problema/cartonase, concursul national .campion, 2007-2008\r\n\r\nFie $N$ cartonase asezate in linie dreapta pe o masa si doi jucatori care muta alternativ. Fiecare cartonas are o fata colorata in rosu, iar cealalta in albastru. O mutare consta in alegerea unui cartonas cu fata rosie in sus si intoarcerea lui. In plus, daca doreste, cel care e la mutare poate sa isi aleaga orice alt cartonas (indiferent de culoarea fetei care este in sus) care se afla la stanga celui ales initial si sa il intoarca. Stiind culorile fetelor care sunt initial in sus, sa se precizeze care jucator castiga.\r\n\r\nAcest joc este cunoscut in literatura de specialitate ca _Turning Turtles_, si este de fapt echivalent cu \'jocul NIM\':teoria-jocurilor/jocul-nim, studiat in acest articol. Putem asocia unui cartonas rosu situat pe pozitia $i$ o gramada cu $i$ pietre in jocul {$NIM$}. Se pot observa urmatoarele:\r\n\r\n* Starea finala din problema este cea in care nu mai exista niciun cartonas cu fata rosie in sus. Deasemenea, in jocul {$NIM$}, se ajunge in starea finala cand toate gramezile de pietre sunt vide.\r\n* Daca un jucator intoarce un singur cartonas rosu situat pe pozitia $i$, mutarea lui este echivalenta cu a lua toate pietrele din gramada ce contine $i$ pietre.\r\n* Daca un jucator intoarce cartonasul rosu de pe pozitia $i$, iar apoi mai intoarce un alt cartonas de pe pozitia $j$ ({$1 &le; j < i$}), avem urmatoarele posibilitati:\r\n** cartonasul de pe pozitia $j$ este albastru: dupa ce se efectueaza mutarea, vom avea pe pozitia $j$ un cartonas rosu, iar pe pozitia $i$ un cartonas albastru. Aceasta mutare este echivalenta cu a lua exact $i-j$ pietre din gramada ce contine $i$ pietre, obtinand o gramada cu $j$ pietre.\r\n** cartonasul de pe pozitia $j$ este rosu: dupa ce se efectueaza mutarea, vom aveam pe pozitiile $i$ si $j$ cartonase albastre, inainte acestea fiind rosii. Aceasta mutare este echivalenta cu a lua toate pietrele din gramezile ce contineau {$i$}, respectiv {$j$} pietre. Insa in jocul {$NIM$}, a lua toate pietrele din gramezile ce contin $i$, respectiv $j$ pietre este echivalent cu a lua $i-j$ pietre din gramada cu $i$ pietre, deoarece suma-xor a numerelor de pietre din gramezi nu se schimba.\r\n\r\nFolosindu-ne de aceste observatii, putem concluziona ca primul jucator va castiga atunci si numai atunci cand suma-xor a pozitiilor unde se afla cartonasele cu fata rosie in sus este diferita de {$0$}.\r\n\r\nh3. 3. \'A Coloring Game\':http://acm.sgu.ru/problem.php?contest=0&problem=328, concurs regional, Rusia, 2007\r\n\r\nFie $N$ casute asezate in linie una dupa alta. Initial, fiecare casuta are exact una din cele trei stari posibile: necolorata, colorata in rosu, colorata in albastru. Sunt doi jucatori care muta alternativ. Prin mutare se intelege colorarea unei casute necolorate in rosu sau in albastru, astfel incat, la fiecare pas, sa nu existe doua casute adiacente colorate la fel. Sa se precizeze care jucator are strategie sigura de castig.\r\n\r\nPentru a rezolva aceasta problema ne vom folosi de \'numerele Sprague-Grundy\':teoria-jocurilor/numere-SG si de teoria prezentata in capitolul \'Adunarea jocurilor\':teoria-jocurilor/adunarea-jocurilor. Se observa ca sirul initial de casute poate fi divizat in mai multe subsecvente maximale disjuncte, astfel incat fiecare subsecventa este de unul din cele $4$ tipuri prezentate mai jos:\r\n\r\n* subsecventa cu ambele capete necolorate (tip {$1$})\r\n* subsecventa cu un capat colorat si cu un capat necolorat (tip {$2$})\r\n* subsecventa cu ambele capete colorate la fel (tip {$3$})\r\n* subsecventa cu un capat colorat in rosu, iar celalalt in albastru (tip {$4$})\r\n\r\nColorarea unei casute inseamna o mutare in jocul determinat de subsecventa careia apartine casuta. Cum la fiecare pas se alege un singur joc din cele existente si se efectueaza o singura mutare in acest joc, suntem in cazul unei adunari de tip xor a jocurilor. In consecinta, vom determina valorile Sprague-Grundy pentru fiecare joc independent in parte si vom face suma-xor a acestor valori.\r\n\r\nSa notam cu {$A{~n~}$} valoarea Sprague-Grundy a unei secvente de lungime {$n$} de tipul {$1$}. Similar, se noteaza cu {$B{~n~}$}, {$C{~n~}$} si {$D{~n~}$} valorile pentru secvente de lungime $n$ de tipul {$2$}, $3$ si respectiv {$4$}. Pentru a calcula efectiv aceste valori facem toate mutarile posibile si calculam $mex$ dintre valorile obtinute.\r\n\r\nh3. 4. Triomino, Bytecode, 2008.\r\n\r\n!>teoria-jocurilor/probleme?triomino.jpg 70%!\r\nFie o tabla cu doua linii si $N$ coloane si doi jucatori care muta alternativ. La fiecare pas, jucatorul aflat la mutare aseaza pe tabla o piesa de forma celei din figura alaturata, astfel incat aceasta piesa sa nu se suprapuna (nici macar partial) peste alte piese deja asezate pe tabla. Atunci cand este asezata, piesa poate fi rotita cu {$90$}, {$180$} sau {$270$} de grade. Sa se precizeze care din cei doi jucatori are strategie de castig. De exemplu, pentru {$N = 3$}, jucatorul care muta primul are strategie de castig, iar pentru {$N = 4$} ce de-al doilea jucator are o astfel de strategie. Se cere un algoritm de complexitate {$O(N^2^)$}.\r\n\r\nh3. 5. \'Chess Training\':http://www.topcoder.com/stat?c=problem_statement&pm=6866&rd=10808, Topcoder, SRM 384\r\n\r\nAplicatie pt. WTIA\r\n\r\np{margin:1em; padding: 0.5em; height: 45px; border-top: 1px solid silver;}=. \r\n\'Notiuni de baza\':teoria-jocurilor | \'Jocul NIM\':teoria-jocurilor/jocul-nim | \'Numere Sprague-Grundy\':teoria-jocurilor/numere-SG |\r\n\'Adunarea jocurilor\':teoria-jocurilor/adunarea-jocurilor | \'w-numere\':teoria-jocurilor/w-numere | \'*Aplicatii si probleme*\':teoria-jocurilor/probleme',256,'protected',NULL,NULL),('runda/summer_camp_2','summer_camp_2','2009-06-25 14:38:19','2009-06-25 14:38:19','h1. == roundparam(round_id=\"summer_camp_2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"summer_camp_2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"summer_camp_2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"summer_camp_2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/summer_camp_2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"summer_camp_2\" score=\"1\")==',6957,'round: summer_camp_2',NULL,NULL),('ciurul-lui-eratostene','Ciurul lui Eratostene','2004-11-24 00:00:00','2009-02-20 00:08:15','h1. Ciurul lui Eratostene\r\n\r\n(Categoria _Matematica_, Autor _Cosmin Negruseri_)\r\n\r\nArticolul de fata incearca o implementarea mai eficienta a acestui algoritm clasic. Se poate optimiza pentru a folosi doar $O(sqrt(n))$ memorie, varianta prezentata aici folosind $O(n / log n)$ memorie, unde log n e numarul de biti al unui cuvant.\r\n\r\nCiurul lui Eratostene e un algoritm clasic care se invata la scoala impreuna cu conceptul de numere prime inca din clasa a 6. Acest algoritm determina toate numerele prime mai mici decat un numar dat ca parametru. Ideea lui de abordare a acestei probleme poate fi modificata pentru a rezolva si alte probleme precum problema \"Fractii\":problema/Fractii din arhiva infoarena, problema \"Riemann vs Mertens\":http://acm.uva.es/p/v107/10738.html din arhiva \"uva\":http://acm.uva.es/, problema \"Divizibilitate\":http://algoritmus.org/probleme/Probleme_Runda04.php a rundei 4 a concursului algoritmus, sau problema \"Square Free\":http://www.topcoder.com/stat?c=problem_statement&pm=2342&rd=4770 a SRM-ului 190 de pe TOPCODER, rezolvarea ei o gasiti \"aici\":http://www.topcoder.com/index?t=statistics&c=srm190_prob. \r\nIn articolul acesta nu ne vom concentra asupra acestor probleme ci asupra implementarii optimizate ale algoritmului original.\r\n\r\nAm mai scris despre aceste optimizari intr-un articol din ginfo, dar codul de acolo nu era testat si nu merge :).\r\n\r\nIdeea la acest algoritm e ca marcam intr-un sir fiecare multiplu al unui numar prim si numerele ramase nemarcate sunt numere prime, o descriere mai grafica gasiti la \"adresa\":http://mathworld.wolfram.com/SieveofEratosthenes.html.\r\n\r\nSa incercam o prima implementare a acestui algoritm (implementarile vor folosi limbajul Java, dar sunt foarte usor transformabile in C/C++).\r\n\r\n== code(java) | \r\n  //class PrimeNumbersSieve1\r\n  final int MAXSIZE = 1000001;\r\n  char[] p = new char[MAXSIZE];\r\n  //p[i] == 0 if i is prime\r\n  public int getTheNumber(int n) {\r\n    int i, j, nr = 0;\r\n    for (i = 2; i <= n; ++i) {\r\n      if (p[i] == 0) {\r\n        nr++;\r\n        for (j = i + i; j <= n; j += i) {\r\n          p[j] = 1;\r\n        }\r\n      }\r\n    }\r\n    return nr;\r\n  }\r\n==\r\n\r\nO prima idee de optimizare ar fi sa nu mai luam in calcul numerele pare pentru ca stim ca singurul numar prim par e {$2$}. Deci sa vedem noua varianta a programului:\r\n\r\n== code(java) | \r\n  //class PrimeNumbersSieve2\r\n  final int MAXSIZE = 1000001;\r\n  char[] p = new char[MAXSIZE];\r\n\r\n  //p[i] == 0 if i is prime\r\n  \r\n  public int getTheNumber(int n) {\r\n    int i, j, nr = 1;\r\n    for (i = 3; i <= n; i += 2) {\r\n      if (p[i] == 0) {\r\n        nr++;\r\n        for (j = i + i + i; j <= n; j += i << 1) {\r\n          p[j] = 1;\r\n        }\r\n      }\r\n    }\r\n    return nr;\r\n  }\r\n==\r\n\r\nPutem incerca o optimizare de memorie, pentru ca nu mai avem nevoie de elementele cu index par din sirul {$p$}. Acum semnificatia lui $p{~i~}$ s-a schimbat $p{~i~}$ fiind 0 daca $2*i+1$ e numar prim si $1$ daca nu.\r\n\r\n== code(java) | \r\n  // class PrimeNumbersSieve3 \r\n  final int MAXSIZE = 1000000/2+1;\r\n  char[] p = new char[MAXSIZE];\r\n\r\n  //p[i] == 0 if 2*i + 1 is prime\r\n  \r\n  public int getTheNumber(int n) {\r\n    int i, j, nr = 1;\r\n    for (i = 1; (i << 1) + 1 <= n; i += 1) {\r\n      if (p[i] == 0) {\r\n        nr++;\r\n        for (j = i + i + i + 1; (j << 1) + 1 <= n; j += (i << 1) + 1) {\r\n          p[j] = 1;\r\n        }\r\n      }\r\n    }\r\n    return nr;\r\n  }\r\n==\r\n\r\nUrmatoarea optimizare va fi marcarea multiplilor numarului prim $i$ de la $i*i$ nu de la $2*i$ cum am facut in prima varianta sau de la $3*i$ cum am facut in a {$2$}-a. Aceasta optimizare este evidenta: orice numar prim compus multiplu de $i$ mai mic decat $i*i$ are un factor prim mai mic decat {$i$}, si acel factor l-a marcat mai devreme, deci nu are rost sa il marcam si la pasul {$i$}. Ideea aceasta este exact ideea ce se foloseste la rezolvarea problemei \"Numere Prime\":problema/prim din arhiva infoarena. Sa vedem acum codul sursa:\r\n\r\n== code(java) | \r\n  //class PrimeNumbersSieve4 \r\n  final int MAXSIZE = 1000000/2+1;\r\n  char[] p = new char[MAXSIZE];\r\n\r\n  //p[i] == 0 if 2*i + 1 is prime\r\n  \r\n  public int getTheNumber(int n) {\r\n    int i, j, nr = 1;\r\n    for (i = 1; ((i * i) << 1) + (i << 1) <= n; i += 1) {\r\n      if (p[i] == 0) {\r\n        for (j = ((i * i) << 1) + (i << 1); (j << 1) + 1 <= n; j += (i << 1) + 1) {\r\n          p[j] = 1;\r\n        }\r\n      }\r\n    }\r\n    for (i=1; 2 * i + 1 <= n; ++i) \r\n        if (p[i] == 0) nr++;\r\n    return nr;\r\n  }\r\n==\r\n\r\nCodul sursa arata putin urat pentru ca nu lucram direct cu $i$ ci cu {$2*i+1$}, am mai facut optimizarea ce apare si in \"mathworld\":http://mathworld.wolfram.com/, nu parcurgem numerele pana la $n$ pentru marcarea multiplilor ci pana la $sqrt(n)$ lucru care e evident dupa cele explicate mai sus.\r\n\r\nUltima imbunatatire care o vom aduce este aceea de a folosi mai putina memorie. Cum pentru fiecare numar e necesara doar o informatie booleana, aceasta o putem tine intr-un bit, nu este necesar un char intreg. Sa vedem cum arata codul:\r\n\r\n== code(java) | \r\n  //class PrimeNumbersSieve5 \r\n  final int MAXSIZE = 100000000/2/8+1;\r\n  char[] p = new char[MAXSIZE];\r\n\r\n  //(p[i>>3]&(1<<(i&7))) == 0 if 2*i + 1 is prime\r\n  \r\n  public int getTheNumber(int n) {\r\n    int i, j, nr = 1;\r\n    for (i = 1; ((i * i) << 1) + (i << 1) <= n; i += 1) {      \r\n      if ((p[i >> 3] & (1 << (i & 7))) == 0) {\r\n        for (j = ((i * i) << 1) + (i << 1); (j << 1) + 1 <= n; j += (i << 1) + 1) {\r\n          p[j >> 3] |= (1 << (j & 7));\r\n        }\r\n      }\r\n    }\r\n    for (i = 1; 2 * i + 1 <= n; ++i)  \r\n         if ((p[i >> 3] & (1 << (i & 7))) == 0) \r\n             nr++;\r\n    return nr;\r\n  }\r\n==\r\n\r\nCodul {@p[i >> 3] & (1 << (i & 7)) @}&#0061;&#0061;{@ 0@} testeaza daca al {@i@}-lea bit din sirul de biti e $0$ (deci daca {@2*i+1@} e prim). {@i >> 3@} e echivalent cu {@i / 8@} deci se gaseste pt bitul al {@i@}-lea in ce char e el stocat din sirul nostru de charuri. {@i & 7@} e echivalent cu {@i % 8@} ca sa aflam pe ce bit al charului e stocat numarul prim {@i@}.\r\n\r\nCodul {@p[j >> 3] |= (1 << (j & 7))@} seteaza bitul {@j % 8@} al charului {@j / 8@} in {@1@}, pentru ca sa stim ca numarul {@2 * j + 1@} nu e prim.\r\n\r\nUltima varianta arata destul de urat fata de prima, sa vedem daca s-a meritat efortul. Urmatoarele date sunt obtinute pe un procesor Athlon XP la 1.8 Ghz:\r\n\r\n* 10 runs of {@BruteForcePrimes().method1(1000000)@} lasted: 24.956 seconds\r\n* 10 runs of {@PrimeNumbersSieve1().getTheNumber(1000000)@} lasted: 3.024 seconds\r\n* 10 runs of {@PrimeNumbersSieve2().getTheNumber(1000000)@} lasted: 1.842 seconds\r\n* 10 runs of {@PrimeNumbersSieve3().getTheNumber(1000000)@} lasted: 1.422 seconds\r\n* 10 runs of {@PrimeNumbersSieve4().getTheNumber(1000000)@} lasted: 0.971 seconds\r\n* 10 runs of {@PrimeNumbersSieve5().getTheNumber(1000000)@} lasted: 0.22 seconds\r\n\r\nCodul folosit pentru testare e:\r\n\r\n== code(java) | \r\n  public static void main(String[] arg) {\r\n    double tick = System.currentTimeMillis();\r\n    for (int i = 0; i < 10; ++i) {\r\n      System.out.println(\"Run \" + i \r\n    + \" result: \"+\r\n      new PrimeNumbersSieve1().\r\n      getTheNumber(1000000));\r\n    }\r\n    System.out.println(\" 10 runs of \"\r\n  + \"PrimeNumbersSieve1().\" \r\n  + \"getTheNumber(1000000) \" \r\n  + \"lasted: \" \r\n  + (System.currentTimeMillis() \r\n  - tick) \r\n  * 1e-3 + \" seconds\");\r\n  }\r\n==\r\n\r\nS-a rulat fiecare cod de $10$ ori pentru a da ocazia optimizarilor Just In Time din java sa isi faca treaba.\r\n\r\nSe pare ca optimizarile codului initial au dus la o imbunatatire a vitezei cu un factor de {$10$}.\r\n\r\nProblemele sugerate la inceputul articolului sunt destul de frumoase si ar trebui rezolvate. Pentru fiecare dintre ele puteti sa va testati rezolvarea: la algoritmus sunt disponibile fisierele de intrare si iesire, infoarena si uva au evaluatoare automate si pentru problema de pe \"TOPCODER\":http://www.topcoder.com/tc puteti intra in applet-ul lor si sa incercati sa o rezolvati in practice roomul asociat SRM-ului 190 dupa ce o rezolvati folositi optiunea Run System Test din Practice Room Options.\r\n\r\n',2044,'public',3682,NULL),('heapuri','Heap-uri','2008-01-18 16:31:03','2009-02-20 01:08:56','h1. Heap-uri\r\n\r\n== include(page=\"template/implica-te/scrie-articole-2\" user_id1=\"Cyber\" user_id2=\"silviug\") ==\r\n\r\n(Categoria _Structuri de date_, Autor _Catalin Francu_, Versiunea originala preluata din cartea _\"Psihologia concursurilor de informatica\"_)\r\n\r\n(toc){width: 30em}*{text-align:center;} *Continut*\r\n* \'Definirea notiunii de _heap_\':heapuri#definire\r\n* \'Structura de heap si metode ajutatoare\':heapuri#structura\r\n* \'Cautarea maximului\':heapuri#cautarea-maximului\r\n* \'Crearea unei structuri de heap dintr-un vector oarecare\':heapuri#creare-heap\r\n* \'Eliminarea unui element, stiind pozitia lui in heap\':heapuri#stergere\r\n* \'Inserarea unui element\':heapuri#inserare\r\n* \'Sortarea unui vector (heapsort)\':heapuri#heapsort\r\n* \'Cautarea unui element\':heapuri#cautare\r\n* \'Alternative STL\':heapuri#stl\r\n* \'Aplicatii\':heapuri#aplicatii\r\n\r\nIn acest articol vom prezenta structura de date numita $heap$, cum poate fi aceasta implementata, precum si alternative STL. Desi este putin probabil sa ajungeti sa implementati heap-urile de la \"zero\" daca stiti STL, consideram ca prezentarea acestora nu este de prisos. Aici atingem problema mai generala \"de ce trebuie sa inteleg X (poate fi vorba de un algoritm, o structura de date, s.a.m.d.) daca il am deja implementat?\". Iata cateva motive:\r\n\r\n* va antreneaza mintea\r\n* va veti putea descurca in situatii in care aveti nevoie de o structura de date asemanatoare, dar nu la fel\r\n* veti fi utilizatori informati ai bibliotecii STL\r\n* veti intelege cand este bine sa folositi o structura de date si cand nu\r\n* veti avea avantajul de a sti precis de ce operatiile de baza au anumite complexitati\r\n\r\nAcum ca avem o motivatie, sa studiem impreuna heap-urile.\r\n\r\nh2(#definire). Definirea notiunii de _heap_\r\n\r\nUn heap ({_engl._} gramada) este un vector care poate fi privit si ca un arbore binar, asa cum se vede in figura de mai jos:\r\n\r\n!heapuri?heap.JPG!\r\n\r\nLanga fiecare nod din arbore se afla cate un numar, reprezentand pozitia in vector pe care ar avea-o nodul respectiv. Pentru cazul considerat, vectorul echivalent ar fi {$H = (12 10 11 10 7 9 3 2 8 1 4 3)$}.\r\n\r\nSe observa ca nodurile sunt parcurse de la stanga la dreapta si de sus in jos. O proprietate necesara pentru ca un arbore binar sa se poata numi $heap$ este ca toate nivelurile sa fie complete, cu exceptia ultimului, care se completeaza incepand de la stanga si continuand pana la un anume punct. De aici deducem ca inaltimea unui heap cu $N$ noduri este <tex> h=[\\log_2 N] </tex> (reamintim ca inaltimea unui arbore este adancimea maxima a unui nod, considerand radacina drept nodul de adancime $0$). Reciproc, numarul de noduri ale unui heap de inaltime $h$ este <tex> N\\in [2^h, 2^{h+1}-1]</tex>.\r\n\r\nTot din aceasta organizare mai putem deduce ca tatal unui nod $k > 1$ este nodul $[k/2]$, iar fiii nodului $k$ sunt nodurile $2k$ si $2k+1$. Daca $2k = N$, atunci nodul $2k+1$ nu exista, iar nodul $k$ are un singur fiu; daca $2k > N$, atunci nodul $k$ este frunza si nu are niciun fiu. Exemple: tatal nodului $5$ este nodul $2$, iar fiii sai sunt nodurile $10$ si $11$. Tatal nodului $6$ este nodul $3$, iar unicul sau fiu este nodul $12$. Tatal nodului $9$ este nodul $4$, iar fii nu are, fiind frunza in heap.\r\n\r\nDar cea mai importanta proprietate a heap-ului, cea care il face util in operatiile de aflarea a maximului, este aceea ca valoarea oricarui nod este mai mare sau egala cu valoarea oricarui fiu al sau. Dupa cum se vede mai sus, nodul $2$ are valoarea $10$, iar fiii sai - nodurile $4$ si $5$ - au valorile $10$ si respectiv $7$. Intrucat operatorul $&ge;$ este tranzitiv, putem trage concluzia ca un nod este mai mare sau egal decat oricare din nepotii sai si, generalizand, va rezulta ca orice nod este mai mare sau egal decat toate nodurile din subarborele a carui radacina este.\r\n\r\nAceasta afirmatie nu decide in niciun fel intre valorile a doua noduri dispuse astfel incat niciunul nu este descendent al celuilalt. Cu alte cuvinte, nu inseamna ca orice nod de pe un nivel mic are valoare mai mare decat nodurile mai apropiate de frunze. Este cazul nodului $7$, care are valoarea $3$ si este mai mic decat nodul $9$ de valoare $8$, nod asezat totusi mai jos in heap. In orice caz, o prima concluzie care rezulta din aceasta proprietate este ca radacina are cea mai mare valoare din tot heap-ul.\r\n\r\nStructura de heap permite efectuarea multor operatii intr-un timp foarte bun:\r\n\r\n* Cautarea maximului in $O(1)$\r\n* Crearea unei structuri de heap dintr-un vector oarecare in $O(N)$\r\n* Eliminarea unui element in $O(log N)$\r\n* Inserarea unui element in $O(log N)$\r\n* Sortarea elementelor din heap in $O(N log N)$\r\n\r\nMentionam ca operatia de cautare a unui element are complexitatea $O(N)$ dar, de obicei, heap-ul nu este folosit cand acest tip de operatii este frecvent.\r\n\r\nDesigur, toate aceste operatii se fac mentinand permanent structura de heap a arborelui, adica respectand modul de repartizare a nodurilor pe niveluri si plasarea mai sus a elementelor de valoare mai mare. Este de la sine inteles ca datele nu se vor reprezenta in memorie in forma arborescenta, ci in cea vectoriala.\r\n\r\nPrecizam de asemenea ca heap-ul poate fi organizat si pe baza operatorului de $&le;$. In acest caz, in varful heap-ului vom avea minimul dintre elementele pastrate in heap. In functie de operatorul folosit, putem numi structura de date $max-heap$ sau $min-heap$. In continuare vom prezenta operatiile intr-un max-heap, adaptarea lor pentru min-heap-uri fiind usoara.\r\n\r\nh2(#structura). Structura de heap si metode ajutatoare\r\n\r\nIn blocul de cod de mai jos prezentam cum se defineste un heap ca vector si cateva metode ajutatoare:\r\n\r\n==code(cpp) |\r\nconst int MAX_HEAP_SIZE = 16384;\r\ntypedef int Heap[MAX_HEAP_SIZE];\r\n\r\ninline int father(int nod) {\r\n    return nod / 2;\r\n}\r\n\r\ninline int left_son(int nod) {\r\n    return nod * 2;\r\n}\r\n\r\ninline int right_son(int nod) {\r\n    return nod * 2 + 1;\r\n}\r\n==\r\n\r\nh2(#cautarea-maximului). Cautarea maximului\r\n\r\nPractic, operatia aceasta nu are de facut decat sa intoarca valoarea primului element din vector:\r\n==code(cpp) |\r\ninline int max(Heap H) {\r\n    return H[1];\r\n}\r\n==\r\n\r\nh2(#creare-heap). Crearea unei structuri de heap dintr-un vector oarecare\r\n\r\nPentru a discuta acest aspect, vom vorbi mai intai despre doua proceduri specifice heap-urilor, $sift$ ({_engl._} a cerne) si $percolate$ ({_engl._} a se infiltra). Sa presupunem ca un vector are o structura de heap, cu exceptia unui nod care este mai mic decat unul din fiii sai. Este cazul nodului $3$ din figura de mai jos, care are o valoare mai mica decat fiii sai (nodurile $6$ si $7$):\r\n\r\n!heapuri?create1.JPG!\r\n\r\nCe e de facut? Desigur, nodul va trebui coborat in arbore, iar in locul lui vom aduce alt nod, mai exact unul dintre fiii sai. Intrebarea este: care din fiii sai? Daca vom aduce nodul $7$ in locul lui, acesta fiind mai mic decat nodul $6$, anomalia se va pastra. Trebuie deci sa schimbam nodul $3$ cu nodul $6$:\r\n\r\n!heapuri?create2.JPG!\r\n\r\nProblema nu este insa rezolvata, deoarece noul nod $6$, proaspat \"retrogradat\", este inca mai mic decat fiul sau, nodul $12$. De data aceasta avem un singur fiu, deci o singura optiune: schimbam nodul $6$ cu nodul $12$ si obtinem o structura de heap corecta:\r\n\r\n!heapuri?create3.JPG!\r\n\r\nProcedura $sift$ primeste ca parametri un heap $H$ cu $N$ noduri si un nod $K$ si presupune ca ambii subarbori ai nodului $K$ au structura de heap corecta. Misiunea ei este sa \"cearna\" nodul $K$ pana la locul potrivit, interschimband mereu nodul cu cel mai mare fiu al sau pana cand nodul nu mai are fii (ajunge pe ultimul nivel in arbore) sau pana cand fiii sai au valori mai mici decat el.\r\n\r\n==code(cpp) |\r\nvoid sift(Heap H, int N, int K) {\r\n    int son;\r\n    do {\r\n        son = 0;\r\n        // Alege un fiu mai mare ca tatal.\r\n        if (left_son(K) <= N) {\r\n            son = left_son(K);\r\n            if (right_son(K) <= N && H[right_son(K)] > H[left_son(K)]) {\r\n                son = right_son(K);\r\n            }\r\n            if (H[son] <= H[K]) {\r\n                son = 0;\r\n            }\r\n        }\r\n\r\n        if (son) {\r\n            swap(H[K], H[son]);  // Functie STL ce interschimba H[K] cu H[son].\r\n            K = son;\r\n        }\r\n    } while (son);\r\n}\r\n==\r\n\r\nProcedura $percolate$ se va ocupa tocmai de fenomenul invers. Sa presupunem ca un heap are o \"defectiune\" in sensul ca observam un nod care are o valoare mai mare decat tatal sau. Atunci, va trebui sa interschimbam cele doua noduri. Este cazul nodului $10$ din figura care urmeaza. Deoarece fiul care trebuie urcat este mai mare ca tatal, care la randul lui (presupunand ca restul heap-ului e corect) este mai mare decat celalalt fiu al sau, rezulta ca dupa interschimbare fiul devenit tata este mai mare decat ambii sai fii. Trebuie totusi sa privim din nou in sus si sa continuam sa urcam nodul in arbore fie pana ajungem la radacina, fie pana ii gasim un tata mai mare ca el. Iata ce se intampla cu nodul $10$:\r\n\r\n!heapuri?create4.JPG!\r\n\r\n==code(cpp) |\r\nvoid percolate(Heap H, int N, int K) {\r\n    int key = H[K];\r\n\r\n    while ((K > 1) && (key > H[father(K)])) {\r\n        H[K] = H[father(K)];\r\n        K = father(K);\r\n    }\r\n\r\n    H[K] = key;\r\n}\r\n==\r\n\r\nAcum ne putem ocupa efectiv de construirea unui heap. Am spus ca procedura $sift$ presupune ca ambii fii ai nodului pentru care este ea apelata au structura de heap. Aceasta inseamna ca putem apela procedura $sift$ pentru orice nod imediat superior nivelului frunzelor, deoarece frunzele sunt arbori cu un singur nod, si deci heap-uri corecte. Apeland procedura $sift$ pentru toate nodurile de deasupra frunzelor, vom obtine deja o structura mai organizata, asigurandu-ne ca pe ultimele doua niveluri avem de-a face numai cu heap-uri. Apoi apelam aceeasi procedura pentru nodurile de pe al treilea nivel incepand de la frunze, apoi pentru cele de deasupra lor si asa mai departe pana ajungem la radacina. In acest moment, heap-ul este construit. Iata cum functioneaza algoritmul pentru un arbore total dezorganizat:\r\n\r\n!heapuri?create5.JPG!\r\n\r\np{padding-left: 4em}. _Nivelul frunzelor este organizat_\r\n\r\n!heapuri?create6.JPG!\r\n\r\np{padding-left: 3em}. _Ultimele doua niveluri sunt organizate_\r\n\r\n!heapuri?create7.JPG!\r\n\r\np{padding-left: 3.5em}. _Ultimele trei niveluri sunt organizate_\r\n\r\n!heapuri?create8.JPG!\r\n\r\np{padding-left: 7em}. _Structura de heap_\r\n\r\n==code(cpp) |\r\nvoid build_heap(Heap H, int N) {\r\n    for (int i = N / 2; i > 0; --i) {\r\n        sift(H, N, i);\r\n    }\r\n}\r\n==\r\n\r\nS-a apelat caderea incepand de la al $N / 2$ - lea nod, deoarece acesta este ultimul nod care mai are fii, restul cu indici mai mari fiind frunze. Sa calculam acum complexitatea acestui algoritm. Un calcul sumar ar putea spune: exista $N$ noduri, fiecare din ele se \"cerne\" pe $O(log N)$ niveluri, deci timpul de constructie a heap-ului este $O(N log N)$. Totusi nu este asa. Presupunem ca ultimul nivel al heap-ului este plin. In acest caz, jumatate din noduri vor fi frunze si nu se vor cerne deloc. Un sfert din noduri se vor afla deasupra lor si se vor cerne cel mult un nivel. O optime din noduri se vor putea cerne cel mult doua niveluri, si asa mai departe, pana ajungem la radacina care se afla singura pe nivelul ei si va putea cadea maxim $h$ niveluri (reamintim ca <tex> h=[\\log_2 N] </tex>). Rezulta ca timpul total de calcul este dat de formula <tex>O(\\displaystyle {\\sum_{k=1}^{[\\log_2 N]} k} \\times \\frac{N}{2^{k+1}}) = O(N)</tex>. Demonstrarea egalitatii se poate face facand substitutia $N = 2^h^$ si continuand calculele. Se va obtine tocmai complexitatea $O(2^h^)$. Lasam aceasta verificare ca tema cititorului.\r\n\r\nh2(#stergere). Eliminarea unui element, stiind pozitia lui in heap\r\n\r\nDaca eliminam un element din heap, trebuie numai sa refacem structura de heap. In locul nodului eliminat s-a creat un gol, pe care trebuie sa il umplem cu un alt nod. Care ar putea fi acela? Intrucat trebuie ca toate nivelurile sa fie complet ocupate, cu exceptia ultimului, care poate fi gol numai in partea sa dreapta, rezulta ca singurul nod pe care il putem pune in locul celui eliminat este ultimul din heap. O data ce l-am pus in gaura facuta, trebuie sa ne asiguram ca acest nod \"de umplutura\" nu strica proprietatea de heap. Deci vom verifica: daca nodul pus in loc este mai mare ca tatal sau, vom apela procedura $percolate$. Altfel vom apela procedura $sift$, in eventualitatea ca nodul este mai mic decat unul din fiii sai. Iata exemplul de mai jos:\r\n\r\n!heapuri?delete1.JPG!\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nSa presupunem ca vrem sa eliminam nodul de valoare $9$, aducand in locul lui nodul de valoare $X$. Insa $X$ poate fi orice numar mai mic sau egal cu $18$. Spre exemplu, $X$ poate fi $16$, caz in care va trebui urcat deasupra nodului de valoare $10$, sau poate fi $1$, caz in care va trebui cernut pana la nivelul frunzelor. Deoarece caderea si urcarea se pot face pe cel mult $[log N]$ niveluri, rezulta o complexitate a procedeului de $O(log N)$.\r\n\r\n==code(cpp) |\r\nvoid cut(Heap H, int& N, int K) {\r\n    H[K] = H[N];\r\n    --N;\r\n\r\n    if ((K > 1) && (H[K] > H[father(K)])) {\r\n        percolate(H, N, K);\r\n    } else {\r\n        sift(H, N, K);\r\n    }\r\n}\r\n==\r\n\r\nh2(#inserare). Inserarea unui element\r\n\r\nDaca vrem sa inseram un nou element in heap, lucrurile sunt mult mai simple. Nu avem decat sa-l asezam pe a $N + 1$ - a pozitie in vector si apoi sa-l \"promovam\" pana la locul potrivit. Din nou, urcarea se poate face pe maxim $[log N]$ niveluri, de unde complexitatea logaritmica.\r\n\r\n==code(cpp) |\r\nvoid insert(Heap H, int& N, int key) {\r\n    H[++N] = key;\r\n    percolate(H, N, N);\r\n}\r\n==\r\n\r\nh2(#heapsort). Sortarea unui vector (heapsort)\r\n\r\nAcum ca am stabilit toate aceste lucruri, ideea algoritmului de sortare vine de la sine. Incepem prin a construi un heap. Apoi extragem maximul (adica varful heap-ului) si refacem heap-ul. Cele doua operatii luate la un loc dureaza $O(1) + O(log N) = O(log N)$. Apoi extragem din nou maximul (care va fi al doilea element ca marime din vector) si refacem din nou heap-ul. Din nou, complexitatea operatiei compuse este $O(log N)$. Daca facem acest lucru de $N$ ori, vom obtine vectorul sortat intr-o complexitate de $O(N log N)$.\r\n\r\nPartea cea mai frumoasa a acestui algoritm este ca el nu foloseste deloc memorie suplimentara. Iata explicatia: cand heap-ul are $N$ elemente, vom extrage maximul si il vom tine minte undeva in memorie. Pe de alta parte, in locul maximului (adica in radacina arborelui) trebuie adus ultimul element al vectorului, adica $H[N]$. Dupa aceasta operatie, heap-ul va avea $N - 1$ noduri, al $N$-lea ramanand liber. Ce alt loc mai inspirat decat acest al $N$-lea nod ne-am putea dori pentru a stoca maximul? Practic, am interschimbat radacina, adica pe $H[&#49;]$ cu $H[N]$. Acelasi lucru se face la fiecare pas, tinand cont de micsorarea permanenta a heap-ului.\r\n\r\n==code(cpp) |\r\nvoid heapsort(Heap H, int N) {\r\n    build_heap(H, N);\r\n\r\n    // Sorteaza vectorul.\r\n    for (int i = N; i >= 2; --i) {\r\n        swap(H[1], H[i]);\r\n        sift(H, i - 1, 1);\r\n    }\r\n}\r\n==\r\n\r\nh2(#cautare). Cautarea unui element\r\n\r\nAceasta operatie este singura care nu poate fi optimizata (in sensul reducerii complexitatii sub $O(N)$). Aceasta deoarece putem fi siguri ca un nod mai mic este descendentul unuia mai mare, dar nu putem sti daca se afla in subarborele stang sau drept; din aceasta cauza, nu putem face o cautare binara. Totusi, o oarecare imbunatatire se poate aduce fata de cautarea secventiala. Daca radacina unui subarbore este mai mica decat valoarea cautata de noi, cu atat mai mult putem fi convinsi ca descendentii radacinii vor fi si ei mai mici, deci putem sa renuntam la a cauta acea valoare in tot subarborele. In felul acesta, se poate intampla ca bucati mari din heap sa nu mai fie explorate inutil. Pe cazul cel mai defavorabil, insa, parcurgerea intregului heap este necesara. Lasam scrierea unei proceduri de cautare pe seama cititorului.\r\n\r\nh2(#stl). Alternative STL\r\n\r\nDesi nu sunt greu de implementat, avem vesti bune pentru programatorii in C++: heap-urile sunt deja implementate in STL. Containerul se numeste \'$priority_queue$\':http://www.sgi.com/tech/stl/priority_queue.html si implementeaza toate operatiile prezentate, mai putin operatiile de cautare a unei valori si de stergere a unui nod. Aceste doua operatii sunt destul de atipice pentru o coada de prioritati si in general nu sunt asociate cu aceasta structura de date in cartile de algoritmi.\r\n\r\nTotusi, in unele aplicatii avem nevoie de o structura de date care suporta toate operatiile amintite in timp cel mult logaritmic (inclusiv stergerea si cautarea unei valori). Aceasta structura exista deja in STL: $set$-urile. Acestea sunt de fapt multimi mentinute ca arbori binari echilibrati. Singurele dezavantaje sunt ca de obicei merg mai incet decat cozile de prioritate si folosesc mai multa memorie.\r\n\r\nDaca nu sunteti familiari cu aceste structuri de date, va recomandam sa cititi paginile lor de documentatie: \'$priority_queue$\':http://www.sgi.com/tech/stl/priority_queue.html, \'$set$\':http://www.sgi.com/tech/stl/set.html si \'$multiset$\':http://www.sgi.com/tech/stl/multiset.html. Daca nu intelegeti totul de la inceput (pentru ca nu stiti clase si template-uri in C++), uitati-va pe exemple si pe lista de functii membre si invatati cum se folosesc.\r\n\r\nIn continuare vom ilustra cum putem implementa operatiile de extragere a maximului, extragere a minimului, inserare, stergere si cautare folosind un $multiset$. Vom folosi un $multiset$ pentru ca toate copiile unui numar vor fi pastrate daca el va fi inserat de mai multe ori (spre deosebire de $set$, care il va pastra o singura data). Va recomandam cu caldura sa copiati codul pe calculatorul vostru si sa experimentati cu el pentru a vedea ce afiseaza si a intelege ce se intampla.\r\n\r\n==code(cpp) |\r\n#include <set>\r\nusing namespace std;\r\n\r\nint main() {\r\n    multiset <int> my_set;\r\n    my_set.insert(1); // Insereaza o valoare.\r\n    my_set.insert(1);\r\n\r\n    if (my_set.find(1) != my_set.end()) { // Cauta o valoare.\r\n        printf(\"Am gasit 1 in set!\\n\");\r\n    } else {\r\n        printf(\"1 nu se afla set!\\n\");\r\n    }\r\n\r\n    // Sterge o valoare din set. Daca aceasta se afla de\r\n    // mai multe ori in set, este stearsa numai o copie.\r\n    my_set.erase(my_set.find(1));\r\n    printf(\"Exista %d elemente in set\\n\", my_set.size());\r\n\r\n    my_set.insert(1);\r\n    my_set.insert(1);\r\n\r\n    // Sterge o valoare din set. Daca aceasta se afla de\r\n    // mai multe ori in set, sunt sterse toate copiile.\r\n    my_set.erase(1);\r\n    printf(\"Exista %d elemente in set\\n\", my_set.size());\r\n\r\n    my_set.insert(1);\r\n    my_set.insert(-3);\r\n    my_set.insert(7);\r\n\r\n    // Valoarea minima.\r\n    multiset <int> :: iterator it = my_set.begin();\r\n    printf(\"Valoarea cea mai mica din set este %d\\n\", *it);\r\n\r\n    // Valoarea maxima.\r\n    it = my_set.end();\r\n    --it;\r\n    printf(\"Valoarea cea mai mare din set este %d\\n\", *it);\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#aplicatii). Aplicatii\r\n\r\n* \'Dijkstra cu heap-uri\':http://infoarena.ro/problema/dijkstra\r\n* \'Magnetic storms\':http://acm.timus.ru/problem.aspx?space=1&num=1126\r\n* \'Manager\':http://acm.tju.edu.cn/toj/showp1675.html\r\n* \'Supermarket\':http://acm.tju.edu.cn/toj/showp1681.html\r\n* Sea - Baraj ONI 2004 (Autor: Radu Berinde)\r\n* Interclasati $K$ vectori sortati. (Sugestie: complexitatea dorita este $O(N * log K)$, unde $N$ este lungimea sirului rezultat prin interclasare)\r\n* Determinati cele mai mici $K$ elemente dintr-un sir cu $N$ elemente cand dispuneti de memorie mult mai putina ca $O(N)$. ({$K$} este mult mai mic decat $N$)\r\n',2044,'public',3528,NULL),('acm-icpc-upb-2008/solutii','Solutii - Concurs de selectie a echipelor ACM ICPC, UPB 2008','2008-10-04 10:05:23','2008-11-04 19:37:38','h1. Solutii - Concurs de selectie a echipelor ACM ICPC, UPB 2008\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Rest\':acm-icpc-upb-2008/solutii#rest\r\n* \'Dictree\':acm-icpc-upb-2008/solutii#dictree\r\n* \'Exit\':acm-icpc-upb-2008/solutii#exit\r\n* \'G2mm\':acm-icpc-upb-2008/solutii#g2mm\r\n* \'Ksecv\':acm-icpc-upb-2008/solutii#ksecv\r\n* \'Maxunice\':acm-icpc-upb-2008/solutii#maxunice\r\n* \'Mm\':acm-icpc-upb-2008/solutii#mm\r\n* \'Per\':acm-icpc-upb-2008/solutii#per\r\n* \'Pkinv\':acm-icpc-upb-2008/solutii#pkinv\r\n* \'Pp\':acm-icpc-upb-2008/solutii#pp\r\n\r\n==include(page=\"acm-icpc-upb-2008/solutii/rest\")==\r\n\r\n==include(page=\"acm-icpc-upb-2008/solutii/dictree\")==\r\n\r\n==include(page=\"acm-icpc-upb-2008/solutii/exit\")==\r\n\r\n==include(page=\"acm-icpc-upb-2008/solutii/g2mm\")==\r\n\r\n==include(page=\"acm-icpc-upb-2008/solutii/ksecv\")==\r\n\r\n==include(page=\"acm-icpc-upb-2008/solutii/maxunice\")==\r\n\r\n==include(page=\"acm-icpc-upb-2008/solutii/mm\")==\r\n\r\n==include(page=\"acm-icpc-upb-2008/solutii/per\")==\r\n\r\n==include(page=\"acm-icpc-upb-2008/solutii/pkinv\")==\r\n\r\n==include(page=\"acm-icpc-upb-2008/solutii/pp\")==\r\n',6455,'public',NULL,NULL),('acm-icpc-upb-2008/solutii/exit','acm-icpc-upb-2008/solutii/exit','2008-10-04 14:26:27','2008-10-04 14:26:27','h2(#exit). \'Exit\':problema/exit',2044,'public',NULL,NULL),('acm-icpc-upb-2008/solutii/g2mm','acm-icpc-upb-2008/solutii/g2mm','2008-10-04 14:26:59','2008-11-03 10:22:39','h2(#g2mm). \'G2mm\':problema/g2mm\r\n\r\nIn primul rand trebuie mentionat faptul ca va exista intotdeauna un cuplaj perfect in acest graf, lucru care va reiesi din algoritmul prezentat in continuare. Vom nota graful din intrare cu G iar graful patrat cu @G^2@. Vom creea un arbore partial al grafului G, pentru asta putem folosi un DF sau un BF. Avand arborele il vom parcurge de jos in sus (de la frunze catre radacina) si vom creea cuplajul astfel: Pentru fiecare nod consideram sirul F{~1~}, F{~2~}, F{~3~} .. F{~N~} unde F{~i~} este un fiu al nodului curent care nu a fost inca introdus in cuplaj. Daca acest sir are numar impar de noduri atunci introducem si nodul curent in sir, acesta avand acum un numar par de elemente. Acum cuplam pur si simplu aceste noduri din sir (e usor de gasit o astfel de modalitate) avand in vedere ca in @G^2@ aceste noduri vor avea toate muchii intre ele. Exista intotdeauna solutie deoarece graful are un numar par de noduri si este conex.',2993,'public',NULL,NULL),('acm-icpc-upb-2008/solutii/ksecv','acm-icpc-upb-2008/solutii/ksecv','2008-10-04 14:27:38','2008-10-04 14:27:38','h2(#ksecv). \'Ksecv\':problema/ksecv',2044,'public',NULL,NULL),('acm-icpc-upb-2008/solutii/mm','acm-icpc-upb-2008/solutii/mm','2008-10-04 14:28:51','2008-10-04 14:28:51','h2(#mm). \'Mm\':problema/mm',2044,'public',NULL,NULL),('acm-icpc-upb-2008/solutii/per','acm-icpc-upb-2008/solutii/per','2008-10-04 14:29:21','2008-10-05 14:51:30','h2(#per). \'Per\':problema/per\r\n\r\nCea mai rapida solutie se bazeaza pe hashing. Pentru aflarea rezultatului vom construi o dinamica A[i][j] = numarul de secvente de lungime i concatenate care se termina in j. \r\nFormula de recurenta este usor de dedus :\r\n\r\n*  Daca la pasul i,j sirul care incepe pe i-j+1 este identic cu cel de pe i-2j+1 atunci A[i][j] = A[i][j-i]+ 1 \r\n*  alfel A[i][j] = 1;\r\n\r\n\r\nPentru a afla in O(1) daca doua siruri sunt egale vom construi H[i][j] = (ch[i] - \'a\') * prim[ 1 ]  + (ch[i+1] - \'a\') + prim[ 2 ] + .. + (ch[j] - \'a\' * prim[j-i+1] ) unde prim[i] va fi al i-lea numar prim si ch[i] este caracterul de pe pozitia i. \r\n\r\nDesi nu in toate cazurile un hash ar da o solutie corecta aici este putin probabil sa apara 2 valori identice pentru siruri diferite.\r\nLa fiecare pas cand intalinim un A[i][j] >= K adunam la rezultat.\r\n\r\nPentru a se incadra in memorie este necesar sa mentinem doar ultima linie a matricii pentru hash si dinamica.\r\nCompexitatea finala este O(N^2) ca timp si O(N) ca memorie.    \r\n ',7271,'public',NULL,NULL),('acm-icpc-upb-2008/solutii/pp','acm-icpc-upb-2008/solutii/pp','2008-10-04 14:30:19','2008-10-04 14:30:19','h2(#pp). \'Pp\':problema/pp',2044,'public',NULL,NULL),('utilizator/raduzer','Radu Zernoveanu','2006-11-24 21:05:46','2009-11-19 10:51:35','h1. Despre mine\r\n\r\nSunt elev in clasa a X-a la Liceul International de Informatica. Ca-mi place informatica, nu cred ca mai este nevoie sa spun!... Imi place sa skiez, sa joc tenis (de masa si de camp), sa joc biliard, sa inot si imi mai plac multe alte sporturi de echipa. A... era sa uit de role, tiroliana si toate jocurile de rope course!\r\n\r\nMotto: \"Crezi ca poti sau crezi ca nu poti, in ambele cazuri ai dreptate!\"- Henry Ford\r\n\r\nh2. Probleme adaugate pe Infoarena\r\n\r\n\'Submat\':problema/submat , \'Reteta\':problema/reteta , \'Pm\':problema/pm , \'2Numere\':problema/2numere , \'Puzzle\':problema/puzzle , \'Fi\':problema/fi , \'Joc7\':problema/joc7 , \'Rezervatie Naturala\':problema/rezervatie , \'Joc6\':problema/joc6\r\n\r\nh1. Profesori\r\n\r\n==user(user=\"pauldb\" type=\"tiny\")==\r\n==user(user=\"wefgef\" type=\"tiny\")==\r\n==user(user=\"silviug\" type=\"tiny\")== \r\n==user(user=\"greco\" type=\"tiny\")== \r\n==user(user=\"alexandru.mosoi\" type=\"tiny\")== si ==user(user=\"svalentin\" type=\"tiny\")==  (cei care m-au pregatit pentru JBOI 2007) \r\n\r\n\r\nh1. Distinctii primite\r\n\r\n* Finala .Campion 2009 - Premiul I, Grupa S\r\n* ONI 2009 - mentiune\r\n* ONI 2008 - Premiul III\r\n* JBOI 2007 - Medalie de argint\r\n* ONI 2007 - Premiul II\r\n* ONI 2005 - mentiune(locul 4)\r\n\r\nh1. Prieteni pe Infoarena\r\n\r\n==user(user=\"CezarMocan\" type=\"tiny\")== \r\n==user(user=\"tvlad\" type=\"tiny\")== \r\n==user(user=\"savim\" type=\"tiny\")== \r\n==user(user=\"Vman\" type=\"tiny\")== \r\n==user(user=\"Protoman\" type=\"tiny\")== \r\n==user(user=\"gcosmin\" type=\"tiny\")== \r\n==user(user=\"snaked31\" type=\"tiny\")== \r\n==user(user=\"svalentin\" type=\"tiny\")==\r\n==user(user=\"bogdan2412\" type=\"tiny\")== \r\n==user(user=\"greco\" type=\"tiny\")== \r\n==user(user=\"wefgef\" type=\"tiny\")== \r\n==user(user=\"mariusdrg\" type=\"tiny\")== \r\n==user(user=\"gabitzish1\" type=\"tiny\")==\r\n==user(user=\"slayer4u\" type=\"tiny\")==\r\n==user(user=\"gavrilavlad\" type=\"tiny\")==\r\n==user(user=\"silviug\" type=\"tiny\")== \r\n==user(user=\"Florian\" type=\"tiny\")== \r\n==user(user=\"MaxDamage\" type=\"tiny\")== \r\n\r\nh2. Prieteni din fostii colegi de la Colegiul National Tudor Vianu:\r\n\r\n==user(user=\"alexmilu\" type=\"tiny\")== \r\n==user(user=\"ye_kai008\" type=\"tiny\")== \r\n==user(user=\"Radu_Bumbacea\" type=\"tiny\")== \r\n==user(user=\"alexandra_nae\" type=\"tiny\")== \r\n==user(user=\"roberta_raileanu\" type=\"tiny\")== \r\n\r\nSper ca nu am uitat pe nimeni...\r\n\r\n',3997,'protected',NULL,NULL),('blog/ziua-robotilor-inteligenti','Ziua Robotilor Inteligenti','2009-01-10 14:32:17','2009-01-10 14:56:18','\'Mihai Oltean\':http://www.google.ro/search?hl=ro&q=mihai+oltean&btnG=C%C4%83utare+Google&meta= repeta evenimentul de care \'va ziceam\':blog/robocup anul trecut. Anul acesta se numeste Ziua robotilor inteligenti si se desfasoara duminica, 11 ianuarie la ora 12 in campusul universitatii Babes Bolyai.\r\n\r\nStudentii anului trei de la sectia informatica din cadrul facultatii de matematica si informatica, au programat robotii cu comportamente utile. Dintre proiectele ce vor fi prezentate sunt: capcana pentru soareci, tanc autonom, transport bere etc.\r\n\r\nPuteti citi mai multe despre eveniment \'aici\':http://ubbots.com',58,'protected',3554,NULL),('migrat-tag-img','migrat-tag-img','2008-10-12 18:49:51','2008-10-12 18:54:02','Aceste pagini contin tag-uri de imagini cu linkuri catre pagini externe. Paginile care merg catre http://infoarena.ro ar trebui sa mearga in continuare.\r\n\"Patch pt CSRF\":http://hackers.devnet.ro/ticket/341\r\n\r\n==grep (substr=\"%! http://% !%\" page=\"%\")==\r\n\r\n==grep (substr=\"%!http://%!%\" page=\"%\")==\r\n',1490,'public',NULL,NULL),('blog/romania-e-frumoasa','Google Translate si Romania e frumoasa','2008-10-13 13:09:47','2008-11-15 13:41:14','Circula pe messengere si prin \'bloguri\':http://www.zoso.ro/2008/10/sa-cultivam-banane.html exemple amuzante ale traducerii din limba romana a expresiilor de genul \"Romania e frumoasa\" in \"Australia is beautiful\". Mi se pare ca subiectul merita putin context si il va face mai putin hilar.\r\n\r\nAbordarea Google pentru a rezolva problema traducerii de texte este \'una statistica\':http://www.google.com/intl/ro/help/faq_translation.html#statmt . Se trece prin o gramda de texte traduse si se obtin modele statistice care dau niste probabilitati ca o bucata de text sa fie tradusa in alta bucata de text. Algoritmul de traducere e din ce in ce mai bun cu cat are mai multe date la dispozitie. Rezultatele evaluarilor arata ca Google Translate este la un nivel \"state of the art\" si daca o sa il comparati cu o gramada de alte programe de tradus(programe gratuite sau programe ce pot fi obtinute contra cost) veti putea vedea asta. \r\n\r\nAlgoritmii cei mai buni de traducere sunt inca foarte departe de coerenta unor vorbitori umani, dar ei sunt utili pentru a face internetul mai accesibil celor ce nu vorbesc engleza. Probabil daca stati sa cautati veti gasi o gramada de alte exemple in care traducerea unui text nu va fi cea buna, iar dintre acestea veti gasi cateva exemple in care traducerea are efecte comice. Cu timpul calitatea se va imbunatatii si exemplele respective vor fi din ce in ce mai putine. Pana atunci puteti folosi google translate ca ceea ce este: una dintre cele mai tari scule de traducere automata.\r\n\r\n*Update:* Intre timp problema a fost sesizata intern si corectata. E misto ca se pot rezolva probleme de genul asta repede. Asta imi aminteste de \'feature-ul\':http://blag.xkcd.com/2008/10/08/youtube-audio-preview/ care a aparut pe youtube inspirat din un comic.\r\n\r\n',1490,'protected',3305,NULL),('utilizator/lorincziisti','Profil lorincziisti','2008-10-15 12:21:00','2008-10-15 12:21:00','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',8637,'public',NULL,NULL),('planificare/sedinta-20081010','Sedinta 2008-10-10','2008-10-01 19:29:54','2008-10-17 06:28:49','h1. Sedinta 2008-10-10\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *vineri, 10 octombrie* la ora *12:00* la \'*Cafepedia, Universitate*\':http://metropotam.ro/Unde-iesim/2008/01/art6577605495-Cafenea-Cafepedia-Universitate/\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")== (inca nu sunt sigur ca pot ajunge, depinde de orarul de la facultate)\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"astronomy\" type=\"tiny\")== (nu pot veni, dar il somez pe ==user(user=\"wefgef\" type=\"tiny\")== sa ma reprezinte)\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* _&hellip; asteptam confirmari_\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare sedintele anterioare (\'1\':planificare/sedinta-20080411, \'2\':planificare/sedinta-20080303 si \'3\':planificare/sedinta-20080314)\r\n* stabilit locatie si data pentru sedinta urmatoare\r\n* membri noi\r\n* reorganizare (OKRs)\r\n* preONI 2009\r\n* Adobe + hackaton\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Am introdus membrii noi: ==user(user=\"victorsb\" type=\"tiny\")==, ==user(user=\"Prostu\" type=\"tiny\")==, ==user(user=\"stef2n\" type=\"tiny\")==, ==user(user=\"bogdan2412\" type=\"tiny\")==, ==user(user=\"pauldb\" type=\"tiny\")==, ==user(user=\"gcosmin\" type=\"tiny\")==, ==user(user=\"alexthero\" type=\"tiny\")==\r\n* Se aproba \'IAP #9\':propuneri/9-okr\r\n* *Structura si responsabili:*\r\n** *Arhiva de probleme* \r\n*** Extinde arhiva - ==user(user=\"ditzonec\" type=\"tiny\")==\r\n*** Imbunatateste teste - ==user(user=\"ditzonec\" type=\"tiny\")==\r\n*** Open surse - ==user(user=\"gcosmin\" type=\"tiny\")==\r\n*** _Tagging_ - ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n** *Arhiva educationala* - ==user(user=\"filipb\" type=\"tiny\")==, ==user(user=\"pauldb\" type=\"tiny\")==\r\n** *Concursuri*\r\n*** Organizeaza concursuri - ==user(user=\"astronomy\" type=\"tiny\")==\r\n*** Newsletter - ==user(user=\"wickedman\" type=\"tiny\")==\r\n*** Fundraising - ==user(user=\"wickedman\" type=\"tiny\")==\r\n*** _preONI_ -  ==user(user=\"wefgef\" type=\"tiny\")==\r\n*** _Rating_ - ==user(user=\"victorsb\" type=\"tiny\")==\r\n*** _Hackaton_ - ?\r\n*** _Concurs pentru studenti_ - ?\r\n** *Articole, Downloads, Links*\r\n*** Scrie Articole - ==user(user=\"stef2n\" type=\"tiny\")==\r\n*** Downloads & Links - ==user(user=\"Prostu\" type=\"tiny\")==\r\n*** _\"Almanah\" infoarena_ - ? \r\n** *Development*\r\n*** _Long standing issues_ - ==user(user=\"domino\" type=\"tiny\")==\r\n*** _Community Ladder_ - ?\r\n*** _infoarena 3 \"Pie in the sky\"_ - ==user(user=\"domino\" type=\"tiny\")==\r\n** *Calendar* - ==user(user=\"pauldb\" type=\"tiny\")==\r\n** *Forum* - ==user(user=\"wefgef\" type=\"tiny\")==\r\n** *Blog* - ==user(user=\"Cosmin\" type=\"tiny\")==\r\n** *Comunitate* - ?\r\n** *Proiecte Noi* - ?\r\n** *Contabilitate* - ?\r\n\r\n* Ne intalnim in saptamana 20-24 octombrie (vineri 24 probabil), la ora 12:00. Loc: ? \r\n* Mircea actualizeaza pagina de echipa infoarena %{color:red;}(done)%\r\n* Pana la sedinta urmatoarea responsabilii redacteaza OKR-uri\r\n* Facem o pagina publica in care punem OKR-urile %{color:red;}(done)%\r\n* Mircea organizeaza coding classes/camp cu lumea interesata de development \r\n* Din \'sedinta anterioara\':planificare/sedinta-20080411: task-urile pentru IAP #7, Hackaton se amana pana se stabilesc responsabili\r\n* Mircea incearca sa faca raport post-mortem pentru preONI 2008 (Wefgef il bate la cap)\r\n* Cosmin vorbeste cu Cristi despre open surse %{color:red;}(done)%\r\n* Pentru urmatoarea sedinta: discutam despre complexul elitist si infoarena.org\r\n* Fiecare membru se gandeste la OKR-uri globale pentru urmatoarele 6-12 luni din infoarena\r\n* Vali investigheaza problemele de performanta de la concursuri\r\n* Mircea si Silviu vorbesc cu Cristi despre hackaton si eventual merg la Adobe\r\n* Mircea vorbeste cu Tero despre infoarena %{color:red;}(done)%\r\n* Mircea vorbeste cu Leo despre infoarena %{color:red;}(done)%\r\n* Incercam sa umplem golurile din structura data viitoare\r\n\r\nh2. Notite\r\n\r\n* Ce facem cu PayPal?\r\n* Prostu isi schimba parola\r\n',15,'public',NULL,NULL),('blog/drumuri-lungi','Drumuri Lungi','2008-10-17 08:58:36','2008-11-15 13:41:14','Era o vreme cand uram drumurile lungi, mai ales primele zboruri de avion Romania/California si inapoi. Stai acolo 16 sau 20 de ore pe scaun amortesti si te uiti la niste filme pe un ecran mic pe care abia se vede. Asta daca ai noroc. Dar ultimele cateva drumuri m-au facut sa imi schimb parerea.\r\n\r\nPe drumul ce l-am facut recent in Seul am citit o carte care am cumparat-o de ceva vreme si tot statea necitita prin casa, Blink de Malcom Gladwell. E destul de tare, v-o recomand. Pe drumul inspre Disney Land, anul trecut am citit Freakonomics. Acum vreo doi ani, cand trebuia sa merg pe tren opt ore la Suceava la pregatirile lotului, mi-au venit idei de vreo cinci sau sase probleme noi pe care le-am propus mai tarziu la diverse concursuri. Cam toate erau pe aceiasi tema (teoria grafurilor, brute force si optimizari pe biti), dar le-am folosit la concursuri diferite :). Cand mergeam in Spania la sfarsitul anului I de facultate, mi-am amintit sapte probleme pe care nu stiam sa le rezolv in liceu. Cand m-am intors acasa le rezolvasem pe toate. Probabil mai pot gasi si alte exemple ...\r\n\r\nIn weekend sau dupa munca parca ai chestii mai bune sau interesante de facut decat sa citesti o carte sau sa te gandesti la niste probleme. De exemplu sa te mai odihnesti, sa socializezi sau sa citesti cateva articole \"bytesized\" pe internet. O calatorie parca te forteaza sa te concentrezi fiind imobilizat intr-o anumita masura si neavand distrageri.\r\n\r\nAti avut si voi experiente similare? Eu abia astept cate un drum lung ...',1490,'protected',3310,NULL),('utilizator/gabitzish1','GABITZISH... Bitis Gabriel.... ','2007-03-02 12:09:21','2010-03-16 14:05:57','h2. Despre mine\r\n\r\nSunt student in anul I la Facultatea de Stiinte din Oradea, departamentul Informatica.\r\nAm inceput sa lucrez pe infoarena de pe la sfarsitul clasei a X\'a.\r\n\r\nh2. Distinctii primite:\r\n\r\n* Mentiune la Concursul Interjudetean \"Marian Tarina\", Turda, 2007.\r\n* Premiul 1 la OJI 2008 (judetul Bihor).\r\n* Premiul 3 la Concursul Interjudetean \"Grigore Moisil\", Cluj-Napoca, 2008.\r\n* Mentiune si medalie de bronz la ONI 2008, Ploiesti.\r\n* Premiul 1 la Concursul Interjudetean \"Marian Tarina\", Turda, 2008.\r\n* Premiul 1 la OJI 2009 (judetul Bihor).\r\n* Premiul 1 la Concursul National \"Urmasii lui Moisil\", Iasi, 2009 + titlul de \"Pui de Moisil\" :P.\r\n* Premiul 1 la Concursul Interjudetean \"Grigore Moisil\", Satu Mare, 2009.\r\n* Finalist .campion 2009\r\n* Membru al lotului national restrans 2009\r\n\r\nh2. Activitate pe Infoarena:\r\n\r\nh3. Probleme adaugate in arhiva:\r\n\r\n* \"498. Alee\":/problema/alee\r\n* \"499. Dir\":/problema/dir\r\n* \"501. Ecuatii 2\":/problema/ecuatii2\r\n* \"514. Sudest\":/problema/sudest\r\n* \"535. Drum\":/problema/drum\r\n* \"536. Razboi 2\":/problema/razboi2\r\n* \"538. Impartire\":/problema/impartire\r\n* \"539. Perm 6\":/problema/perm6\r\n* \"550. Logic2\":/problema/logic2\r\n* \"551. Triticale\":/problema/triticale\r\n* \"744. Numar2\":/problema/numar2\r\n* \"745. Iepuri2\":/problema/iepuri2\r\n* \"746. Colaj\":/problema/colaj\r\n* \"749. Concurs2\":/problema/concurs2\r\n* \"767. Ab2\":/problema/ab2\r\n* \"768. Iepuras\":/problema/iepuras\r\n* \"769. Palind2\":/problema/palind2\r\n* \"770. Auto\":/problema/auto\r\n* \"771. Div\":/problema/div\r\n* \"772. Teatru\":/problema/teatru\r\n* \"922. Expresie\":/problema/expresie\r\n* \"923. Placare\":/problema/placare\r\n* \"926. Cerc3\":/problema/cerc3\r\n* \"927. Project management\":problema/pm2\r\n\r\nh3. Probleme propuse in arhiva:\r\n\r\n* \"905. Cifra lipsa\":/problema/cifralipsa\r\n\r\nh3. Probleme adaugate in arhiva educationala:\r\n\r\n* \"Floyd-Warshall / Roy-Floyd\":/problema/royfloyd\r\n* \"Parcurgere DFS - componente conexe\":/problema/dfs\r\n\r\nh2. Prieteni pe Infoarena:\r\n\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"mariusdrg\" type=\"tiny\")==\r\n* ==User(user=\"devilkind\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"razvi9\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"Dastas\" type=\"tiny\")==\r\n* ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n* ==User(user=\"blasterz\" type=\"tiny\")==\r\n* ==User(user=\"stef2n\" type=\"tiny\")==\r\n* ==User(user=\"CezarMocan\" type=\"tiny\")==\r\n* ==User(user=\"Protoman\" type=\"tiny\")==\r\n* ==User(user=\"motty\" type=\"tiny\")==\r\n* ==User(user=\"Florian\" type=\"tiny\")==\r\n* ==User(user=\"anna_bozianu\" type=\"tiny\")==\r\n* ==User(user=\"sima_cotizo\" type=\"tiny\")==\r\n* ==User(user=\"sigrid\" type=\"tiny\")==\r\n\r\n',6172,'public',NULL,NULL),('propuneri/9-okr','IAP #9: OKR','2008-10-02 18:07:36','2008-10-21 08:40:34','h1. IAP #9: OKRs\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2008-10-09 |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"domino\")== ==User(type=\"tiny\" user=\"wickedman\")== |\r\n|_. Stare     | *_APROBAT_* |\r\n\r\nh2(#abstract). Abstract\r\n\r\nSe propune ca Asociatia si site-ul infoarena sa fie impartite in mai multe unitati organizationale. De asemenea, se propune un mod prin care echipa infoarena sa isi stabileasca obiective si sa urmareasca indeplinirea acestora. \r\n\r\n*Un OKR (Objective and Key Results) este format dintr-un obiectiv si o serie de rezultate cheie, masurabile. Daca rezultatele cheie au fost indeplinite, se considera ca obiectivul a fost atins.* \r\n\r\nh2(#motivatie). Motivatie\r\n\r\nPropunerea de fata doreste sa ne sporeasca eficienta. Odata cu pornirea \'mai multor proiecte\':implica-te in cadrul infoarena si cu marirea \'echipei infoarena\':echipa-infoarena, devine din ce in ce mai greu sa lucram impreuna eficient. Desi au mai fost tentative de stabilire a rolurilor in cadrul echipei infoarena, nu s-a mai incercat pana acum stabilirea clara a unor obiective pe termen scurt, cel putin nu intr-un mod transparent.\r\n\r\nh2(#okrs). Despre OKRs\r\n\r\n*Pentru simplitate, toate OKR-urile se stabilesc trimestrial.* Un an calendaristic are 4 trimestre: Q1, Q2, Q3, si Q4). Q1 corespunde lunilor Ianuarie, Februarie, si Martie. Proiectele care necesita mai mult timp decat un trimestru se vor segmenta in bucati mai mici.\r\n\r\nLa inceputul fiecarui trimestru, echipa infoarena va stabili prin vot OKRs pentru fiecare unitate organizationala, dar si individual pentru fiecare membru al echipei infoarena. Obiectivele individuale trebuie sa fie aliniate cu obiectivele unitatilor organizationale.\r\n\r\nFiecare unitate este condusa de un membru al echipei infoarena. Acesta este responsabil pentru indeplinirea obiectivelor unitatii sale. La sfarsitul fiecarui trimestru vom evalua cat de bine am reusit sa ne atingem obiectivele.\r\n\r\nPentru transparenta, OKR-urile individuale se vor afisa in pagina de profil fiecarui a fiecarui membru al echipei infoarena.\r\n\r\nh2(#org). Organizare\r\n\r\nMai jos se propune o lista de unitati organizationale. Fiecare unitate organizationala este condusa de un membru al echipei infoarena, insa desemnarea acestora nu face parte din acest IAP. \r\n\r\n* Arhiva de probleme \r\n** \'Extinde arhiva\':implica-te/extinde-arhiva\r\n** \'Imbunatateste teste\':implica-te/imbunatatire-teste\r\n** \'Arhiva educationala\':arhiva-educationala\r\n** Open surse\r\n** Tagging\r\n\r\n* Concursuri de informatica\r\n** preONI\r\n** Organizare concursuri\r\n** Rating\r\n** _Hackaton_\r\n\r\n* Continut educational\r\n** Articole\r\n** Downloads & Links\r\n** \'_Almanah infoarena_\':propuneri/8-almanah\r\n** Calendar concursuri\r\n\r\n* Comunitate\r\n** Forum\r\n** Blog\r\n** Statistici\r\n** \'Community Ladder\':propuneri/7-community-ladder\r\n\r\n* Software Development\r\n** Infrastructura pentru development\r\n** infoarena 2\r\n** Documentatie\r\n** _coding camps_\r\n** _infoarena 3_\r\n\r\n* Fund raising\r\n\r\n* Marketing si relatii publice\r\n\r\n* Administrativ\r\n** Hosting, data center ops.\r\n** Contabilitate\r\n\r\nh2(#feedback). Feedback\r\n\r\n...',13,'public',NULL,NULL),('blog/cateva-scurte','Cateva scurte','2008-11-06 07:35:59','2008-11-15 13:41:14','Colegii mei de liceu, de la formatia Grimus, \'lanseaza albumul de debut Panikon\':http://life.hotnews.ro/stiri-prin_oras-5004869-cozi-pentru-muzica-primul-album-grimus-panikon.htm puteti asculta cateva melodii \'aici\':http://www.myspace.com/grimusworld Bravo Vali, Cristi si Bogdan! Bafta mare!\r\n\r\nMie imi plac piesele Backseat Driver, Different Color Shues si Solitude. Sa imi spuneti care va plac voua.\r\n\r\n\'Bogdan Ionescu, primul admis la Politehnica din Milano\':http://www.hotnews.ro/stiri-esential-5008237-hacker-roman-inchisoare-primul-admis-politehnica-din-milano.htm\r\n\r\nAsta dupa ce \'Olimpic roman arestat in Italia pentru furt\':http://www.9am.ro/stiri-revista-presei/Social/95396/Olimpic-roman-inchis-in-Italia-pentru-furt.html\r\n\r\nPe alta nota, despre olimpici romani, si aici chiar despre un membru al echipei infoarena: \'Interviu cu Filip Buruiana, locul intai la Balcaniada de Informatica\':http://student.hotnews.ro/stiri-profi_2_0-5048473-interviu-filip-buruiana-locul-intai-balcaniada-informatica-inca-mai-face-carte-romania.htm Felicitari Filip!\r\n\r\n\'Manevra inteligenta pe bursa facuta de Porche\':http://www.economist.com/finance/displaystory.cfm?story_id=12523898&fsrc=rss\r\n\r\n\'Un articol misto referitor la Barack Obama scris de Cristian Tudor Popescu\':http://www.gandul.info/puterea-gandului/presedintele-planetei-pamant.html?4237;3437627\r\n\r\n*Update:* Baietii de la Grimus au videoclipul la piesa Backseat Driver pe \'youtube\':http://uk.youtube.com/watch?v=dT6yxgEUj4M\r\n\r\n*Update2:* Azi, inca un \'articol\':http://www.banateanul.ro/ultima-ora/arad-hackerul-care-a-penetrat-nasa-a-scapat-de-inchisoare-3442891 despre alt super hacker roman.',1490,'protected',3346,NULL),('planificare/sedinta-20081021','Sedinta 2008-10-21','2008-10-19 23:24:44','2008-11-02 11:47:30','h1. Sedinta 2008-10-21\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *marti, 21 octombrie* la ora *16:30* la \'*Cafepedia, Universitate*\':http://metropotam.ro/Unde-iesim/2008/01/art6577605495-Cafenea-Cafepedia-Universitate/\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")== (s-ar putea sa intarzii ~30 de min)\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")== (am putea sa gasim un loc mai ieftin unde sa ne intalnim de acum incolo)\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")== (s-ar putea sa intarzii ~30 de min)\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* _&hellip; asteptam confirmari_\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioare\':planificare/sedinta-20081010\r\n* Stabilit locatie si data pentru sedinta urmatoare\r\n* OJI \'Schimbare Borland\':schimbare-borland/argumentatie\r\n* discutat/votat OKR-uri\r\n* Hackaton\r\n* Coding Camp\r\n* preONI 2009\r\n* Blog post\r\n* Grup infoarena\r\n* Complexul elitist si infoarena.org\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* OJI: Prostu, Bogdan, Cosmin si Silviu se ocupa de analiza mediilor de dezvoltare pentru Windows pana la sedinta viitoare; discutia are loc pe grup; trebuie sa vedem daca se baga si Vali\r\n* Notite pentru OKR-uri:\r\n** Extinde arhiva: 30 de probleme de la loturi (si juniori) si ONI\r\n** Imbunatatire teste: numere exacte\r\n** Open surse: doar masurare\r\n** Arhiva educationala: 15-20 de probleme ; nu se aproba notitele\r\n** Tagging: bagam cat mai multe date in tag-uri; scopul e filtrare\r\n** Organizeaza concursuri: pagina concursuri + concursul lui Ciucu (in noiembrie)\r\n** Scrie articole: tragem linie, inchidem articolele incomplete\r\n* Mircea face Coding Camp in weekend-ul 8-9 noiembrie (Silviu a zis ca vine si el!) si inca unul intr-un alt weekend\r\n* Tero si Victor isi completeaza profilul\r\n* Mircea actualizeaza pagina de Organigrama folosind notitele lui Cristi si rezultatele de azi  %{color:red;}(done)%\r\n* Notite preONI 2009 \"smecher\":\r\n** vrem sistem de submit \r\n** schimbam numele\r\n** finala in alt loc decat Bucuresti\r\n* Mircea vorbeste cu Cristi de probleme de performanta si e High Priority pentru coding camp  %{color:red;}(done)%\r\n* \"Complexul elitist si infoarena.org\" se raporteaza si e #1 pe agenda de data viitoare\r\n* Sedinta in ~2 saptamani, probabil fix inainte de Coding Camp\r\n* Cosmin scrie IAP de Virtual Contents %{color:red;}(done)%\r\n* Pentru sedinta viitoare ne gandim la ce zice Cosmin: prea multe chestii de facut, prea putina lume; ne trebuie mai mult \"focus\" pe chestiile foarte importante (ex.: OJI, preONI, development)\r\n* In sdeinta viitoare discutam din nou OKR-urile (si le prioritizam)\r\n\r\nh2. Notite\r\n\r\n* Ce facem cu Hackaton?\r\n\r\nh2. Notite de la Cristian\r\n\r\n* Am discutat cu Mircea si am clarificat propunerea de OKRs ca sa semene mai mult cu modelul folosit de Google. Daca nu ati apucat sa cititi, iata un rezumat intr-un paragraf:\r\n\r\nbq. Un OKR (Objective and Key Results) este format dintr-un obiectiv si o serie de rezultate cheie, masurabile. Daca rezultatele cheie au fost indeplinite, se considera ca obiectivul a fost atins. Toate OKR-urile se stabilesc trimestrial.\r\n\r\nCarevasaica, trebuie sa ne aliniem la trimestre, deci primele OKR-uri vor fi numai pentru ce-a mai ramas din octombrie, luna noiembrie, si decembrie - practic mai putin de doua luni daca luam in calcul sarbatorile. In ianuarie ne facem urmatorul set de obiective. Daca vi se pare prea des, ganditi-va ca dureaza macar cateva iteratii pana ca OKR-urile sa devina deprinderi.\r\n\r\n* De asemenea, am revizuit cu Mircea unitatile organizationale. Cred ca aici mai e de reflectat, si v-as ruga sa o faceti.\r\n\r\n* Legat de OKR-urile propuse deja in organigrama, le-am citit si cred ca sunt un inceput bun. Inca nu au structura de OKRs. Fiecare obiectiv trebuie sa aiba setul _lui_ de rezultate cheie, ca sa putem determina la sfarsit care obiective au fost atinse si care nu. O sa le mai citesc pe masura ce le redactati si o sa va contactez personal acolo unde cred ca sunt neclaritati. \r\n\r\n* O remarca legata de preONI: Silviu si Mircea cunosc discutia pe care am purtat-o cu Ecaterina Andronescu. Nu mai putem sa ne raportam la ONI. Putem sa facem un concurs mai bun decat ONI, mai progresist. Dupa cum vedeti, organizarea nationalei ramane aproape neschimbata dupa atatia ani, si este sanatos, cred, sa fie mai conservatori. Totusi, cineva trebuie sa dea un exemplu, cineva trebuie sa faca experimente. Faceti din preONI ce ati vrea voi sa reprezinte ONI. Lasati comisia nationala sa se ghideze dupa noi, nu invers.\r\n\r\n* Legat de articole: Catalin Francu vrea sa scrie o serie de articole introductive, la nivel de manual de clasa a IX-a. Asta adreseaza oarecum \"complexul elitist.\"\r\n\r\n* Imi asum partea de Fund raising, Community Ladder (partea de implementare, la design am nevoie de ajutorul vostru), newsletter, marketing si relatii publice.\r\n',1,'public',NULL,NULL),('schimbare-borland/jurnal','Jurnal de lucru','2008-11-14 18:13:04','2008-11-14 18:13:04','h1. La ce se lucreaza\r\n\r\nh2. Analiza mediilor de dezvoltare (done)\r\n\r\n|_. Task |_. Responsabil |\r\n| Testat RHIDE pe 32-bit Windows | ==user(user=\"svalentin\" type=\"tiny\")== |\r\n| Testat RHIDE pe 64-bit Windows | ==user(user=\"svalentin\" type=\"tiny\")== |\r\n| Testat MingwDS pe WindowsXP | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| Testat DevCpp pe WindowsXP | ==user(user=\"silviug\" type=\"tiny\")== |\r\n\r\nh2. Alegerea mediilor si argumentarea alegerii\r\n\r\nAu fost alese FreePascal si MingwDS.\r\n\r\nTODO: Argumentarea alegerii.\r\n\r\nh2. Installer (deadline: 13 noiembrie 2008)\r\n\r\nResponsabil: ==user(user=\"svalentin\" type=\"tiny\")== \r\n\r\nh2. Documentatie (deadline: 13 noiembrie 2008)\r\n\r\n|_. Task |_. Responsabil |_. Link |\r\n| Documentatie installer | ?? | ?? |\r\n| Documentatie mediu Pascal | ==user(user=\"victorsb\" type=\"tiny\")== | \'Ghid de utilizare Free Pascal\':schimbare-borland/ghid-freepascal |\r\n| Documentatie mediu C/C++ | ==user(user=\"prostu\" type=\"tiny\")== | \'Introductie MinGW Developer Studio\':schimbare-borland/ghid |\r\n\r\n',1,'public',NULL,NULL),('acm-icpc-upb-2008/solutii/dictree','Solutie Dictree','2008-10-04 14:26:01','2008-11-02 23:14:35','h2(#dictree). \'Dictree\':problema/dictree\r\n\r\nProblema se reduce la gasirea numarului de noduri ale trie-ului format din cuvintele din dictionar. Cu toate aceastea, limita de memorie restransa nu permite construirea efectiva a trie-ului. Pentru a rezolva problema, putem sorta lexicografic cuvintele din dictionar si sa vedem cate noduri \"aduce\" fiecare cuvant fata de cel precedent lexicografic. Este usor de observat ca acest numar este egal cu diferenta dintre lungimea cuvantului curent si lungimea celui mai lung prefix comun al celor doua cuvinte. Complexitatea solutiei este $O(N*logN*Lmax)$, unde $Lmax$ este lungimea maxima a unui cuvant.',1792,'public',NULL,NULL),('sandbox/utf8','sandbox/utf8','2008-10-24 18:38:29','2008-10-24 18:38:29','Scrie aici despre sandbox/utf8',13,'public',NULL,NULL),('blog/interviu-evz-mihai-stroe','Interviu Mihai Stroe (Evenimentul Zilei)','2008-10-23 10:52:11','2008-11-15 13:41:14','_Va spuneam in un \'blog post\':http://infoarena.ro/blog/zece-ani-de-google anterior despre \'interviul\':http://www.evz.ro/articole/detalii-articol/819647/Creierele-romanesti-din-solda-imperiului-Google/ pe care l-am dat impreuna cu Mihai Stroe si Cristi Strat pentru Evenimentul Zilei. In articol nu au aparut raspunsurile interviurilor in totalitate. Si cum v-am promis, va redau pentru inceput interviul cu Mihai Stroe._\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/interviu-evz-mihai-stroe?mihaistroe.jpg!*1. Scurta prezentare*\r\n\r\nMihai Stroe a absolvit Facultatea de Calculatoare din Universitatea Politehnica din Bucuresti, unde a terminat si programul de Master. Experienta sa cuprinde participarea la numeroase concursuri nationale si internationale de programare intre 1995 si 2004, initial in calitate de concurent, iar apoi ca organizator. Mihai a inceput ca programator la Google in iunie 2004, dupa terminarea Master-ului. In cadrul companiei, a lucrat la cateva proiecte pentru imbunatatirea infrastructurii Google si a calitatii rezultatelor motorului de cautare.\r\n\r\nDupa aproape trei ani petrecuti la sediul principal din Mountain View, California, Mihai s-a transferat la biroul din Zurich in 2007. In prezent are functia de Technical Lead / Manager.\r\n\r\n\r\n*2. In Romania, un job la Google este insotit aproape intotdeauna de un soi de admiratie ce nu are nevoie de argumente. Cat de greu este de fapt sa ajungi acolo?*\r\n\r\nSelectia este foarte serioasa, si nu este usor sa obtii un job. Pe de alta parte, cred ca avem mai mult de 100 de angajati romani, iar vara aceasta am avut 20-30 de studenti romani care au facut stagii de trei luni la Google, venind de la universitati din tara sau din strainatate. Aceste cifre demonstreaza valoarea programatorilor romani.\r\n\r\n*3. Ce te motiveaza sa faci ceea ce faci?*\r\n\r\nPentru mine, cea mai importanta motivatie este faptul ca proiectele la care lucrez sunt vizibile in exterior si ajuta milioane de utilizatori in fiecare zi. De exemplu, am adus imbunatatiri la motorul de cautare, si am dezvoltat functionalitate pentru Google Toolbar si pentru Google Chrome, noul nostru browser care a fost lansat sapatamana aceasta.\r\n\r\n*4. Este Google tinta ultima a oricarui programator? Se poate mai bine de atat?*\r\n\r\nPentru mine este locul ideal. Oamenii cu care lucrez sunt foarte bine pregatiti. Proiectele sunt interesante. Daca avem idei care pot avea un impact puternic asupra companiei, suntem incurajati sa le dezvoltam. Bineinteles, recompensele sunt pe masura realizarilor si angajatii cu performante deosebite pot avansa repede in cariera. In plus, Google este una din companiile care influenteaza puternic dezvoltarea Internetului. In momentul de fata sunt convins ca peste 10 ani ma veti gasi tot la Google.\r\n\r\n*5. Stim chiar de la Google ca mediul de lucru este unul foarte relaxat. Nu cumva flexibilitatea asta inseamna o responsabilizare a angajatului?*\r\n\r\nIntr-adevar, mediul de lucru este flexibil - dar ritmul de dezvoltare este alert. In general lucram in echipe mici, de 3 pana la 10 angajati; proiectele mari sunt impartite in mai multe echipe. Angajatii sunt motivati si se sustin reciproc.\r\n\r\nAccesul la informatie in cadrul companiei este foarte bine pus la punct. Astfel, imi este foarte usor sa aflu ce anume se intampla in oricare alt proiect, ceea ce imi permite sa contribui cu idei si sa  identific persoane care m-ar putea ajuta in proiectele proprii.\r\n\r\nIn plus, creativitatea este incurajata; angajatii pot petrece 20% din timpul de lucru (de exemplu o zi pe saptamana) in cadrul unui alt proiect decat cel principal, la alegere. De asemenea, putem folosi acest timp pentru a dezvolta o idee proprie. In momentul in care este clar ca ideea va avea succes,\r\nse formeaza o echipa care poate sa o realizeze. Aceasta strategie a condus la dezvoltarea unor proiecte importante, cum ar fi Google News.\r\n\r\nPersonal, am folosit aceasta flexibilitate pentru a incepe, dezvolta si conduce unul din proiectele la care lucrez, bazat pe o idee proprie. In momentul de fata, la acest proiect lucreaza 8 angajati.\r\n\r\nDupa ce ideea respectiva a devenit proiectul meu principal, 20% din timpul meu de lucru a ramas in continuare flexibil. M-am folosit de acest lucru pentru a organiza cursuri de pregatire pentru noii angajati si prezentari ale companiei la doua universitati din Romania.\r\n\r\n\r\n*6. Ce (mai) inseamna Romania pentru Mihai Stroe? Iti doresti sa te intorci?*\r\n\r\nVizitez Romania foarte des; anul acesta voi avea probabil 7-8 vizite. Familia si o mare parte din prietenii mei sunt in Bucuresti, iar familia sotiei mele este la Cluj, deci avem legaturi puternice cu Romania. Pe termen lung sunt sanse mari sa ramanem in Elvetia - dar drumul de la Zurich la Bucuresti sau la Cluj nu este chiar atat de greu de parcurs...\r\n\r\n\r\n*7. Daca maine s-ar infiinta un birou Google in Romania, ai veni sa lucrezi aici?*\r\n\r\nAs veni pentru cel putin 6-12 luni, sa ajut la formarea si pregatirea grupului din Romania.\r\n\r\n\r\n*8. Ce sfaturi i-ai da unui tanar roman care vrea sa lucreze la Google?*\r\n\r\nDepinde de pregatirea din momentul actual. De exemplu, pentru mai multi romani care au participat la concursuri internationale de programare, nu a fost extraordinar de dificil sa ajunga la Google - dar aceasta nu este o conditie necesara.\r\n\r\nCred ca o buna pregatire generala in informatica, mai ales in algoritmi si sisteme distribuite, impreuna cu un nivel foarte avansat de pregatire in unul din domeniile care ne intereseaza, sunt importante pentru succes.\r\n\r\nPentru mai multe detalii, puteti accesa www.google.com/jobs\r\n\r\nTestarea pentru selectie este foarte serioasa, si unii candidati valorosi nu reusesc sa obtina o pozitie in cadrul companiei - dar asta nu inseamna ca ar trebui sa fie dezamagiti, exista si alte oportunitati.\r\n\r\n\r\n*9. Sunt convins ca foloseai motorul de cautare inainte sa intri in companie. Obiectiv vorbind, de ce e cel mai bun de pe piata?*\r\n\r\nParerea mea este ca rezultatele cautarii pe Google sunt superioare rezultatelor produse de alte motoare de cautare. Motorul de cautare este cel mai important proiect din companie si avem un numar mare de echipe care aduc imbunatatiri.\r\n\r\nCa realizari importante, din ultima perioada, as remarca modul in care sunt combinate mai multe tipuri de informatie. De exemplu, pe www.google.com, rezultatele pentru interogarea \"Marea Neagra\" pot include pagini web, imagini si continut video.\r\n\r\nCa fapt divers, in 2004, dupa ce am fost acceptat pentru interviuri, am contactat cateva zeci de prieteni si i-am intrebat ce motor de cautare folosesc. Toti cei intrebati, fara exceptie, au raspuns \"Google\".\r\n\r\n*10. Cum crezi ca ar fi aratat lumea fara Google?*\r\n\r\nGoogle a avut contributii majore la dezvoltarea aplicatiilor Internet si la organizarea informatiei disponibile online. Cand spun aceasta, nu ma refer numai la motorul de cautare; am obtinut rezultate similare in mai multe domenii.\r\n\r\nDe exemplu, inainte de lansarea serviciului Gmail in 2004, principalele servicii de e-mail ofereau cativa MB de spatiu de stocare, iar cautarea era ineficienta. Gmail a schimbat aceste lucruri, oferind in momentul lansarii 1 GB de stocare (de cateva sute de ori mai mult) si perfectionand cautarea, iar in timp, celelalte servicii s-au adaptat.\r\n\r\nSunt convins ca Google Chrome va duce la progrese similare in domeniul browserelor. In viitor ne putem astepta la multe alte imbunatatiri.\r\n\r\n_Saptamana viitoare voi publica interviul cu_ \'Cristian Strat\':utilizator/wickedman',1490,'protected',3324,NULL),('blog/problema-saptamanii-vanatori','Problema saptamanii - Vanatori','2008-10-23 09:58:10','2008-11-15 13:41:14','_Va propun o noua problema, trimiteti-mi ca si pana acum solutiile la cosminn at gmail.com, si neclaritatile legate de enunt in sectiunea de comentarii._\r\n\r\nSe da o padure infinita in care copacii sunt dispusi in o grila laticeala (puteti sa va imaginati copacii ca punctele din ZxZ). Se cere sa se determine numarul maxim de vanatori care se pot pune in puncte din grila laticeala, astfel ca fiecare vanator sa poata vedea orice alt vanator direct. Inainte sa punem un vanator intr-un punct laticeal, taiem copacul deja existent acolo. Daca segmentul ce uneste punctele asociate a doi vanatori contine un alt punct laticeal, fie acesta ocupat de un copac sau un al treilea vanator, se considera ca acesti doi vanatori nu se pot vedea direct. De asemenea doi vanatori nu pot sta in acelasi punct laticeal.',1490,'protected',3314,NULL),('runda/contest','contest','2009-03-21 08:23:15','2009-03-21 08:23:15','h1. == roundparam(round_id=\"contest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"contest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"contest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"contest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/contest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"contest\" score=\"1\")==',8857,'round: contest',NULL,NULL),('blog/cunoasterea-pe-net','De ce este bun un curs de compilatoare si cunoasterea pe net','2008-10-29 23:16:16','2008-11-15 13:41:14','_Virgil Palanciuc este \'olimpic international\':olimpici \"din garda veche\" si Software Engineer de 8 ani. A lucrat in departamentul de compilatoare al Freescale Romania iar momentan este Project Manager la Evo Software. Impreuna cu Bogdan Nitulescu si o armata de asistenti (printre care ma numar si eu) preda cursul de compilatoare la UPB. Recent Virgil a trimis un email catre studentii acestui curs pe lista de discutii asociata. Noua ni s-a parut interesant si util mesajul transmis si ne-am gandit sa vi-l impartasim si voua prin intermediul blogului :)_\r\n\r\n_Silviu Ganceanu_\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/cunoasterea-pe-net?virgil.jpg! Doamna profesoara Athanasiu obisnuia sa scrie articole in PC Magazine, prin care sa transmita mesaje studentilor, sa corecteze unele perceptii pe care le considera gresite, si asa mai departe. Unele dintre ele le mai gasiti inca pe pagina \'Utile\':http://cs.pub.ro/~cpl/index.php?section=Utile a cursului CPL. Poate ca in timp, vor deveni \"obsolete\", poate ca au devenit deja, sau poate ca vor fi mereu actuale.\r\n\r\nEu din pacate nu am talentul epic al ei, si nici experienta sa. Dar de data asta o sa ma risc, sa scriu un \"articol\" similar cu articolele ei incercand sa raspund la intrebarea \"De ce e important pentru voi acest curs de compilatoare\". Am observat in ultimul timp o atitudine care tinde sa prinda elan odata cu raspandirea accesului la internet - am auzit mult prea des parerea ca \"De ce e nevoie sa stiu asta? Daca am nevoie, caut pe net\". O parere partial corecta... totusi doar partial. Invitat intr-o emisiune TV, acum cativa ani, Neagu Djuvara a recunoscut că nu stie data bataliei de la Podul Inalt: \"Am totul notat pe fise, nu retin datele\". Asa e, nu trebuie sa retii toate datele pentru a fi un mare istoric. Nu trebuie sa retii toate metodele si interfetele din Java API pentru a fi un programator bun - e un exercitiu de memorare complet inutil.\r\n\r\nInsa: atitudinea aceasta e, din pacate, prea des dusa in extrem - pana la punctul la care, cand unui student de la A/C i s-a cerut sa incrementeze o variabila, a scris pe tabla doar \"++\" (fara numele varibilei), scuzandu-se ca \"nu are nevoie sa stie sintaxa C, poate sa o caute in manual oricand\". Desigur ca voi intelegeti absurditatea acestei atitudini - dar exista forme mult mai \"nevinovate\" de manifestare a unei atitudini similare. Cea mai comuna este atitudinea studentului care atunci cand are o tema de facut la scoala, cauta ceva similar pe internet si adapteaza. Scuza, invariabil, este ca \"reutilizarea e extrem de importanta\" si ca \"la serviciu nimeni nu-ti cere sa scrii totul de la 0, refolosesti tot ce poti\". Asa este, la serviciu refolosesti. Dar voi acum sunteti intr-o perioada in care nu trebuie sa _produceti_ cod util, ci trebuie sa _intelegeti_. E prea putin relevant cu ce nota terminati scoala, mai nimeni nu o sa va intrebe de asta. E mult mai important sa intelegeti cat mai mult cum functioneaza lucrurile, sa intelegeti ca lucrurile nu functioneaza \"by magic\" in calculatoare, ci urmeaza o logica foarte clara, ca daca faci ceva intr-un anumit fel poate fi eficient, sau ineficient, si asa mai departe. Sa intelegeti ca un \"+=\" nu e intotdeauna operatia inocenta care pare a fi, daca ne uitam strict la sintaxa. De aceea e important cursul de compilatoare (si cel de sisteme de operare), fiindca, poate mai mult decat oricare alte cursuri, fac legatura intre 2 lumi: cea a limbajelor de nivel inalt, a \"abstractizarilor\" - in care programatorul \"zboara deasupra lucrurilor\" si pierde de multe ori legatura cu \"realitatea hardware\" - si lumea \"de jos\" - in care lucrurile trebuie puse cap la cap, legate intre ele, adaptate la procesor, simplificate, facute sa functioneze ca un tot unitar. E ceva ce nu veti gasi niciodata pe google - nu fara a _sti deja_ ce cautati. Daca stiti paradigmele de programare, daca stiti _cum_ si _de ce_ functioneaza constructiile si mecanismele dintr-un limbaj de programare - atunci va va fi mult mai usor sa adaptati la un orice alt limbaj nou fiindca veti intelege ca limbajul e doar un instrument facut pentru a va mari productivitatea, la fel ca si un IDE, debugger samd. Si nu veti cadea in capcana de a va auto-intitula \"Programator Java\" / \"Programator .NET\".\r\n\r\nLa interviu la Google, din cate mi s-a spus, daca un candidat stie de dinainte raspunsul la o intrebare raspunsul lui este complet ignorat. Ceva similar faceam si eu (fara sa stiu ca Google face asta): de exemplu pun candidatii sa scrie o functie de cautare a unui subsir intr-un sir de caractere si daca e evident ca stie algoritmul Boyer-Moore, atunci il pun sa scrie altceva - e prea putin relevant faptul ca a memorat un algoritm. Dar e foarte important daca el intelege complexitatea algoritmului pe care l-a scris, daca atunci cand i se cere sa scrie o varianta mai eficienta, stie \"de unde sa apuce problema\" pentru a cauta o solutie mai eficienta, si \"de ce solutia curenta nu e eficienta\".\r\n\r\nCititi de exemplu articolul \'acesta\':http://itmanagement.earthweb.com/entdev/article.php/11070_3761921_1 - fara sa fiu neaparat 100% de acord cu el, mi se par interesante (si probabil extrem de relevante pentru el) intrebarile \"de filtrare\" pe care le pune la interviu. Nimeni nu va ofera \"pe tava\" raspunsul la asa ceva si sunt probleme dureros de prezente in anumite medii. E ceva ce nu inveti in mod direct la scoala dar, daca ai inteles cum functioneaza un procesor, cum functioneaza un compilator, cum functioneaza un linker, cum functioneaza un sistem de operare, ai o sansa sa te descurci.\r\n\r\nIn fine, inchei acest mail cu un link la articolul care m-a facut de fapt sa-l scriu - il gasiti \'aici\':http://www.dilemaveche.ro/index.php?nr=244&cmd=articol&id=9271. Mi s-a parut impresionant cum un om de varsta tatalui meu reuseste sa inteleaga internetul mai bine decat multi oameni tineri, de 20 ani. Sau ma rog, eu asa cred, ca l-a inteles foarte foarte bine: \"Dar a fi cultivat nu înseamnă a şti, înseamnă a şti să cauţi. Nu a şti să utilizezi o „maşină de căutare\", ci a transforma căutarea într-un parcurs laborios, imprevizibil, plin de fertile derapaje colaterale. Cultura nu te îmbogăţeşte prin ceea ce îţi livrează în mod expres, ci prin aventura drumului, prin barocul tatonărilor. Cultura e facultatea de a decide ce e de făcut cînd nu ştii ceva: cum să pui întrebarea, la ce uşă să baţi, în care orizont să te mişti.\"\r\n\r\nDl. Plesu vorbeste despre cultura, dar eu zic ca e perfect valabil in contextul mai larg al \"cunoasterii\" - fix asta trebuie sa invatati voi din facultate: cum sa pui intrebarea, la ce usa sa bati, in care orizont sa te misti. Asta e lucrul cu care trebuie sa ramaneti - _cum_ se rezolva o tema si in nici un caz cu \"am reusit sa fac niste modificari prin analogie intr-un program de pe net, deci se cheama ca m-am descurcat sa o fac\".\r\n\r\nSpor la lucru la tema 2, apucati-va de lucru din timp ca e mult mai grea ca tema 1 :)\r\n\r\n      Virgil.\r\n\r\nP.S. Tocmai m-a intrebat ceva un coleg de la alta echipa - nu intelegea de ce in ASP atunci cand pune \"listbox\" in pagina nu poate face un item din lista sa fie hyperlink, pe cand daca pune \"gridview\" se poate. Nu i-a trecut prin cap ca ar afla raspunsul extrem de usor daca s-ar uita ce HTML se genereaza in spatele acelor controale ASP ...\r\n',1490,'protected',3330,NULL),('schimbare-borland/argumentatie','Argumentatia','2008-02-19 09:51:30','2008-11-25 10:34:50','h1. Argumentatia\r\n\r\n==include(page=\"template/schimbare-borland\")==\r\n\r\nbq. Justificati deficientele compilatoarelor Borland (concis, cu liniuta de la capat, fara experiente personale sau aprecieri colaterale). *Emanuela Cerchez*\r\n\r\n* BorlandC impune un standard invechit.\r\n** Surse concepute pentru el nu vor compila pe compilatoare conforme cu standardul international actual.\r\n** Bibliotecile folosite in Borland nu sunt conforme cu standardul international.\r\n** Lipsa bibliotecilor STL, incluse in standardul de C++.\r\n* Compilatoarele Borland sunt compilatoare pe 16 biti. Procesoarele actuale sunt pe 32 sau 64 de biti. Compilatoarele propuse ca alternativa (gcc si fpc) sunt pe 32 de biti.\r\n* Mediile Borland au fost concepute pentru mediul DOS. In Windows acestea ruleaza sub \'NTVDM\':http://en.wikipedia.org/wiki/NTVDM (Virtual DOS Machine) care practic emuleaza mediul DOS. De aici apar o serie de probleme:\r\n** Programele sufera unele probleme cu folosirea excesiva a procesorului si a memoriei pe Windows XP. Acest lucru ingreuneaza rularea altor aplicatii in paralel pe un calculator cu un singur procesor.\r\n** Pe Windows x64 nu este posibila rularea programelor de DOS.\r\n* Compilatoarele Borland compileaza si ruleaza mult mai incet decat gcc sau g++. Acest lucru este cauzat atat de lipsa optiunilor de optimizare pentru noile tipuri de procesoare cat si de emularea DOS sus mentionata.\r\n* Memorie statica limitata la 640KB. In cazul BorlandC instabilitate in gestionarea memoriei alocate dinamice.\r\n* Datorita limitarii memoriei nu este posibila departajarea solutiilor in complexitati diferite de timp. De exemplu nu poate testa diferenta intre o solutie O(N ^3^ ) si o solutie O(N ^2^ lgN) si O(N ^2^ ) memorie, N-ul fiind limitat la 200. Astfel, sunt limitate tipurile de probleme care pot fi date la olimpiada.\r\n* Compilatoarele Borland nu se mai folosesc la nicio competitie internationala.\r\n* Compilatoarele Borland folosite la OJI nu mai sunt in de dezvoltare activa si versiunile mai noi nu sunt gratuite. In schimb, compilatoarele gcc/fpc sunt gratuite si imbunatatite activ.\r\n\r\nh2. Resurse\r\n\r\n* \'Discutie forum infoarena\':forum/index.php?topic=2684.0\r\n* \'Discutie forum .campion\':http://forum.portal.edu.ro/index.php?showtopic=84391\r\n\r\n',75,'public',NULL,NULL),('propuneri/10-virtual-contest','IAP #10: Virtual Contest','2008-10-21 17:33:19','2009-01-12 21:16:44','h1. IAP #10: Virtual contest\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2008-10-21 |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"gcosmin\")== |\r\n|_. Stare     | *APROBAT* |\r\n\r\nh2(#abstract). Abstract\r\n\r\nSe propune crearea unui sistem prin care orice membru infoarena isi poate crea propriul concurs cu probleme alese din arhiva.\r\n\r\nh2(#motivatie). Motivatie\r\n\r\nCum arhiva de probleme devine din ce in ce mai mare si mai diversificata, crearea unui concurs cu probleme necunoscute de catre un anumit grup de oameni este mai usoara. \r\nAceasta optiune ar avea un mare impact in pregatirea concurentilor in regim de concurs :\r\n\r\n* pe plan individual : prin auto-testare\r\n* pe plan de grup : in acest caz avem posibilitati multiple \r\n** cativa membrii ai comunitatii decid sa isi masoare \"fortele\" intre ei\r\n** la un concurs creat de un concurent cu scopuri individuale, se strang mai multi oameni dornici de participare si pregatire\r\n** un profesor decide sa isi supuna elevii unei testari folosind aceasta optiune de pe infoarena\r\n\r\nDe asemenea un concurent ce a ratat un concurs infoarena il poate simula pentru a-si compara rezultate cu ceilalti participanti.\r\nAvantajele sunt evidente mai ales ca avem exemplul unor site-uri acm cu functii asemanatoare : sgu, tju, etc.\r\n\r\nh2(#implementare). Implementare\r\n\r\nEste nevoie de un sistem usor de folosit, intuitiv care sa atraga comunitatea spre aceasta noua modalitate de pregatire.\r\n\r\nOrice concurs va avea urmatorii parametrii, pe care creatorul concursului are dreptul sa ii aleaga dupa bunul plac :\r\n\r\n# Numele rundei\r\n# Data si ora inceperii\r\n# Durata\r\n# Problemele (acestea vor putea fi selectate din arhiva de probleme in orice numar si oricare)\r\n# Starea evaluatorului, daca acesta este oprit sau pornit\r\n# Un clasament propriu ce se creaza in functie de optiunea de mai sus la sfarsitul sau in timpul rundei\r\n\r\nPagina destinata concursurilor virtuale va contine doua lucruri esentiale :\r\n\r\n# O lista cu toate concursurile programate, sortate dupa data si ora inceperii. Un concurent trebuie doar sa caute concursul dorit in aceasta lista, sa il selecteze si va fi directionat catre pagina concursului unde poate vedea problemele, clasamentul sau poate trimite solutii (similar oricarui concurs normal). In caz ca respectivul concurs nu a inceput inca va fi anuntat :)\r\n# Optiunea \"Creaza concurs\" ce va directiona utilizatorul catre o pagina destinata creari unui concurs. Aici stabilteste toti parametrii descrisi mai sus, dupa dorintele proprii. El poate modifica apoi acesti parametrii oricand.\r\n\r\nh2(#Alte mentionar). Alte mentionari\r\n\r\n* Nu exista optiunea ca aceste concursuri sa conteze pentru rating.\r\n* Nu se va crea topic special pentru ele in forum si nici nu vor fi anuntate in calendarul infoarena al concursurilor. O posibilitate ar fi crearea unui calendar specific concursurilor virtuale dar aceast \"feature\" ramane pentru a fi discutat.\r\n* Concurentii vor putea \"trisa\" la aceste concursuri trimitand sursele deja implementate la problemele din concurs. Nu se poate face nimic in acest sens dar nu conteaza, concursurile virtuale fiind doar pentru pregatirea celor binevoitori si dornici :)\r\n* Concursurile ce s-au terminat de mai mult de doua saptamanani vor fi sterse automat din baza de date (nu are nici un rost sa fie tinute prea mult)\r\n\r\nh2(#feedback). Feedback\r\n\r\nIntra pe \'forum\':forum/index.php?topic=3313.0 pentru a da feedback.',1,'public',NULL,NULL),('runda/splunge6','splunge6','2009-08-24 18:18:48','2009-08-24 18:18:48','h1. == roundparam(round_id=\"splunge6\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"splunge6\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"splunge6\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"splunge6\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/splunge6/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"splunge6\" score=\"1\")==',4439,'round: splunge6',NULL,NULL),('blog/ratinguri','Ratinguri ','2008-10-29 07:55:34','2008-11-15 13:41:14','Am observat de multe ori cum pe bloguri, liste de discutii, forumuri sau threaduri de email incepe cate o discutie legata de o oarecare problema si apar replici cu multe idei diferite. Cateodata solutia cea mai buna apare pe la inceput dar este ignorata si se discuta la nesfarsit idei evident mai slabe. In general oamenii ce raspund mai tarziu sunt bine intentionati dar nu isi cunosc nivelul.\r\n\r\nAsta nu se intampla si pe forumurile de pe topcoder. Acolo participantii au rating in functie de performanta in concursuri. Astfel comunitatea e structurata ca o meritocratie. Coderii cotati cu rosu sunt respectati. Daca cineva cu rating de peste 2200 a postat o replica probabil are dreptate si poti sa te concentrezi mai bine pe ceea ce a zis. Puteam sa filtrez rapid posturile interesante si educative. Daca nu a raspuns cineva cu rating rosu pe un thread probabil nu e interesant si trec mai departe. Cum informatia abunda pe internet, filtrarea continutului de calitate devine din ce in ce mai importanta.\r\n\r\nSimt cateodata lipsa acestor ratinguri, mai ales in domenii care nu le cunosc la fel de bine ca si concursurile de algoritmica. Un exemplu ar fi discutiile despre economie. Acolo sunt multi care isi dau cu parerea, dar nu iti poti da seama usor care sunt surse credibile de informatie si care sunt oameni care vor sa fie si ei in pas cu moda.\r\n\r\nAr fi interesant de vazut in ce alte contexte ar fi utile.',1490,'protected',3326,NULL),('schimbare-borland/alternativa','Alternativele la Borland','2008-10-21 17:57:19','2008-11-25 10:35:02','h1. Alternativele la Borland\r\n\r\n==include(page=\"template/schimbare-borland\")==\r\n\r\n(toc)*{text-align:center} *De testat*\r\n* \'Visual C++ 2008\':schimbare-borland/alternativa#visualc\r\n* \'Rhide\':schimbare-borland/alternativa#rhide\r\n* \'MinGW\':schimbare-borland/alternativa#mingw\r\n\r\n==include(page=\"schimbare-borland/alternativa/visualc\")==\r\n\r\n==include(page=\"schimbare-borland/alternativa/rhide\")==\r\n\r\n==include(page=\"schimbare-borland/alternativa/mingw\")==\r\n\r\n\r\n',75,'public',NULL,NULL),('acm-icpc-upb-2008/solutii/maxunice','Solutie Maxunice','2008-10-04 14:28:15','2008-11-02 21:33:50','h2(#maxunice). \'Maxunice\':problema/maxunice\r\n\r\n\r\nO observatie destul de intuitiva este ca pentru a avea cat mai multe numere in rezultat, acestea trebuie sa fie cat mai mici. Astfel, solutia va fi de forma unui sir de numere consecutive care incepe cu $1$, cu proprietatea ca suma elementelor din sir este $&le; N$. Pentru a obtine suma exact $N$, vom mari ultimul termen din sir.\r\n',1792,'public',NULL,NULL),('newsletter/summer-challenge-2007/runda-2-si-3','Summer Challenge 2007, Rundele 2 si 3','2007-08-09 08:23:08','2009-01-20 09:43:31','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nEsti invitat(a) sa participi la rundele 2 si 3 ale concursului\r\nSummer Challenge!\r\n\r\nSummer Challenge este o ocazie buna de antrenament pentru tine\r\n(daca nu esti deja la mare :) dar si un ultim test pentru delegatia\r\nRomaniei la Olimpiada Internationala de Informatica 2007 (Croatia).\r\n\r\nAi ocazia sa te intreci cu lotul Romaniei la IOI 2007!\r\n\r\np{padding-left: 2em;}. Runda 2\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Vineri, 10 august 2007, orele 10:00 - 15:00\r\n\r\np{padding-left: 2em;}. Pagina rundei:\r\n    \'summer-challenge-2007/runda-2\':summer-challenge-2007/runda-2\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\r\np{padding-left: 2em;}. si...\r\n\r\np{padding-left: 2em;}. Runda 3\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Duminica, 12 august 2007, orele 10:00 - 13:00\r\n    Dureaza doar 3h!\r\n\r\np{padding-left: 2em;}. Pagina rundei:\r\n    \'summer-challenge-2007/runda-3\':summer-challenge-2007/runda-3\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\r\nh2.  Atentie! Concurs cu rating! \r\n\r\nParticiparea la aceste runde iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te va aduce mai aproape de varful clasamentul.\r\n==NewsletterRating(username=\"%username%\")==\r\nAfla mai multe despre rating: \'documentatie/rating\':documentatie/rating\r\n\r\nh2.  Comisie si organizatori\r\n\r\nPentru rundele 2 si 3 vor propune probleme:\r\nCosmin Negruseri, Mugurel Andreica si Igor Naverniouk.\r\n\r\nOrganizatori:\r\nAdrian Diaconu, Daniel Pasaila, Alexandru Mosoi si Silviu Ganceanu.\r\n\r\nPentru informatii suplimentare (cum particip, intrebari etc.)\r\nviziteaza pagina concursului: \'summer-challenge-2007\':summer-challenge-2007\r\n\r\nh2.  Clasament Runda 1 \r\n\r\nProbabil stii ca prima runda SC s-a desfasurat pe 30 iulie...\r\nIata primii 5 concurenti:\r\n\r\np{padding-left: 2em;}. Loc    Nume                    Scor (max 300)\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n      1    Bogdan Tataroiu          174\r\n      2    Gheorghe Cosmin          160\r\n      3    Paul-Dan Baltescu        144\r\n      4    Airinei Adrian           120\r\n      5    Andrei Grigorean         100\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\r\nVezi clasamentul complet:\r\n\'summer-challenge-2007/clasament/runda-1\':summer-challenge-2007/clasament/runda-1\r\n\r\nh2.  IOI 2007 \r\n\r\nA 19-a editie a Olimpiadei Internationale de Informatica este gazduita\r\nde Croatia (in Zagreb) si se desfasoara in perioada 15-22 august.\r\n\r\nPagina web: \'http://www.hsin.hr/ioi2007/\':http://www.hsin.hr/ioi2007/\r\n\r\nUram succes delegatiei Romaniei la IOI 2007! Speram sa faca ce stiu ei\r\nmai bine, sa obtina rezultate exceptionale.\r\n\r\nLotul este condus de catre Prof. Emanuela Cerchez.\r\nParticipanti:\r\n\r\np{padding-left: 2em;}. Andrei Grigorean\r\n    Cosmin Gheorghe\r\n    Adrian Airinei\r\n    Bogdan Tataroiu\r\n\r\nh2.  Prima data la infoarena? \r\n\r\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\r\nRamai alaturi de noi. Te ajutam sa devii olimpic!\r\n\r\nSucces!\r\nEchipa infoarena\r\n\r\nh2.  Mesaj nesolicitat? \r\n\r\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\r\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\r\n\r\n',1490,'protected',NULL,NULL),('acm-icpc-upb-2008/solutii/rest','Solutie Rest','2008-10-04 14:25:22','2008-11-01 23:47:01','h2(#rest). \'Rest\':problema/rest\r\n\r\nProblema se reduce la gasirea unei structuri care sa permita rezolvarea celor doua tipuri de operatii. Putem folosi un arbore de intervale $A$, unde un nod reprezinta restul impartirii la $P$ a numarului format din alipirea cifrelor in baza $B$ din intervalul corespunzator. Constructia arborelui se poate face recursiv: $A[i] = (A[fiu_stanga] * B^lungime_interval_fiu_dreapta^ + A[fiu_dreapta]) % P$. Pentru a face o operatie de tipul $1$ (update), modificam frunza corespunzatoare operatiei si actualizam arborele recursiv dinspre frunza spre radacina. La o operatie de tipul $2$ (query), intervalul dat il spargem intr-un numar minim de intervale consecutive ce apar si in arbore. Rezultatul pentru un query, se face din compunerea acestor intervale, dupa aceeasi formula de recurenta. \r\nPentru a obtine complexitatea $O(logN)$ atat pe operatia query, cat si pe update, este necesara precalcularea puterilor lui $B$ modulo $P$.',2044,'public',NULL,NULL),('blog/problema-saptamanii-vanatori-solutie','Problema saptamanii - Vanatori (Solutie)','2008-11-01 10:13:21','2008-11-15 13:41:14','_Problema Vanatori a fost rezolvata corect de Delia David, Ovidiu Gheorghioiu, Bogdan Dumitru, Dobrota Valentin-Eugen si Catalin Tiseanu._\r\n\r\nIncercarea unor cazuri pe foaie duce la intuitia ca numarul maxim de vanatori este 4. Sa vedem de ce aceasta intuitie este adevarata. Orice vanator ce e intr-un punct (x, y) ce apartine uneia dintre cele patru clase x - par, y - par; x - par, y - impar; x - impar, y - par si x - impar, y - impar. Orice doua puncte din aceiasi clasa sunt unite de un segment ce are mijlocul intr-un punct de coordonate intregi. Astfel am demonstrat ca putem numarul maxim de vanatori este 4, cate unul corespunzator fiecarei clase.\r\n\r\n_Ovidiu a venit cu generalizarea la spatiu n dimensional unde numarul maxim de vanatori e $2^n^$. M-a si intrebat daca nu ar fi restrictia ce cerea ca trei vanatori sa nu fie colineari care e numarul maxim de vanatori care pot fi pusi pe grila. Eu naiv i-am zis ca pot fi pusi o infinitate, si Ovi mi-a raspuns ca sunt mai putin de 6 miliarde de oameni cu permis de port arma, deci numarul maxim clar nu e o infinitate ;)._',1490,'protected',3335,NULL),('schimbare-borland/alternativa/rhide','schimbare-borland/alternativa/rhide','2008-11-02 21:32:55','2008-12-04 13:42:26','h2(#rhide). \'Rhide\':http://www.delorie.com/djgpp/zip-picker.html\r\n\r\nEste un mediu de dezvoltare pentru DJGPP. DJGPP cuprinde un set de compilatoare si un set de unelte pentru dezvoltarea de programe pentru DOS si Windows. Compilatoarele pentru C si C++ sunt porturi ale GNU C/C++ si respecta in mare parte standardul actual. Compilatorul este pe 32 de biti.\r\nMediul de dezvoltare Rhide este asemanator ca interfata cu cel din BorlandC 3.1. Acelasi ecran albastru, aceleasi shortcuturi (F2 save, alt-F3 close window, ctrl-F9 ruleaza programul) si are acelasi watch pentru debugare programelor.\r\nIn general este un mediu de dezvoltare mai instabil decat BorlandC, pentru ca face mai usor crash si are mici probleme de configurare, cum ar fi inchiderea ferestrelor (trebuie inchise intr-un mod special, sau setata o optiune pentru a scapa de ea) si rezolutia care daca este schimbata fata de cea implicita poate cauza neplaceri la debug cand se face step. Aceste probleme apar numai la instalarea directa si se pot remedia daca se face un pachet care sa aibe grija la stabilitate.\r\n\r\nh4. Avantaje\r\n\r\n* Interfata similara cu BorlandC, deci si usurinta in folosire\r\n* Lipsa nevoii creerii unui proiect in mod imperativ (desi pentru stabilitate e recomandata crearea unui proiect)\r\n* Debugger simplu de folosit (desi rudimentar).\r\n\r\nh4. Dezavantaje\r\n\r\n* Software-ul nu mai este in dezvoltare activa.\r\n* Foarte instabil. Utilizatorul este nevoit sa invete metode de a evita crashurile.\r\n\r\nh4. Verdict\r\n\r\nEfortul necesar invatarii metodelor de a evita crashurile este comparabil cu efortul invatarii unui mediu total nou si superior si din punct de vedere al functionalitatii. Propunem ca acest IDE sa fie *evitat* in solutia de inlocuire a compilatoarelor Borland.',1490,'public',NULL,NULL),('schimbare-borland/alternativa/visualc','schimbare-borland/alternativa/visualc','2008-11-02 21:35:21','2008-12-04 13:43:31','h2(#visualc). \'Visual C++ 2008 Express Edition\':http://www.microsoft.com/express/\r\n\r\nEste o solutie bogata pentru dezvoltarea aplicatiilor in Windows. Este un mediu stabil, dar este foarte mare, instalarea lui necesitand peste 450 MB. Mediul Visual C++ este creat pentru dezvoltatorii de aplicatii pentru Windows, fiind construit sa satisfaca majoritatea nevoilor unei companii care isi dezvolta produsele in C++.\r\nCompilatorul folosit este mai mult orientat spre backward-compatibility decat spre respectarea standardului. Asadar, se poate intampla ca o functie care exista in acest compilator sa nu existe in standard iar functiile standard sa functioneze putin diferit (de exemplu, rand() returneaza valori intre 0 si 2^15^-1, probabil din vremurile cand intul era pe 2 bytes, rand() ar trbeui sa returneaze o valoare intre 0 si MAX_VAL, iar acum MAX_VAL e 2^31^-1).\r\n\r\n\r\nh4. Avantaje:\r\n\r\n* Integrarea buna in Windows\r\n* Suport, updateuri regulate\r\n* Debugger bun (poate afisa obiecte din STL, chiar si seturi de zeci de mii de elemente).\r\n\r\nh4. Dezavantaje:\r\n\r\n* Unele incompatibilitati cu GCC\r\n* Dimensiunea mare.\r\n',1490,'public',NULL,NULL),('template/schimbare-borland','template/schimbare-borland','2008-11-25 10:33:00','2008-11-25 10:33:00','(vmenu)*(section) \'*Schimbare Borland*\':schimbare-borland\r\n* \'Argumentatie\':schimbare-borland/argumentatie\r\n* \'Alternative\':schimbare-borland/alternativa\r\n* \'Alegerile\':schimbare-borland/alegeri\r\n* \'Ghid MinGW Developer Studio\':schimbare-borland/ghid\r\n* \'Ghid FreePascal\':schimbare-borland/ghid-freepascal\r\n* \'*Pachet*\':schimbare-borland/pachet\r\n* \'Autori\':schimbare-borland/autori\r\n',75,'public',NULL,NULL),('okr/20084/community-ladder','okr/20084/wickedman/community-ladder','2008-11-05 20:23:35','2008-11-05 20:31:34','(okr)* Design Community Ladder.\r\n** Finalizeaza \'IAP#7 - Community Ladder\':http://infoarena.ro/propuneri/7-community-ladder.\r\n* Masoara cateva lucruri importante pentru comunitatea infoarena.\r\n** Masoara cati utilizatori activi avem.\r\n** Masoara cati utilizatori au trimis solutii, cati au contribuit la articole, probleme, forum.\r\n',13,'public',NULL,NULL),('okr/20084/newsletter','okr/20084/wickedman/newsletter','2008-11-05 20:32:34','2008-11-06 13:57:13','(okr)* Eficientizeaza procesul de trimis newsletter, in special pentru anuntarea unui concurs nou.\r\n** Template de newsletter pentru anuntarea unui concurs. %(comment)(Mesajul va contine automat informatiile relevante insa utilizatorul va putea adauga texte suplimentare.)%\r\n** Trecem la HTML. %(comment)(Redactarea unui newsletter trebuie sa fie la fel de simpla precum editarea unei pagini wiki. Newsletter-ele trebuie sa beneficieze de toate facilitatile wiki-ului, inclusiv preview, macro-uri, si imagini inline.)%\r\n** Interfata trebuie sa fie suficient de simpla incat si alti membri infoarena sa poata redacta un newsletter.\r\n %(comment)(Inca nu vor putea sa le si trimita, decat daca lanseaza manual script-ul send-newsletter pe live. Pasul urmator este sa facem un daemon precum eval.)%\r\n* Afla cat de importante si eficiente (mai) sunt newsletter-ele.\r\n** Marcheaza toate link-urile din newsletter-e cu un tag de tracking. %(comment)(Asta ne permite sa analizam cel putin din log-uri daca utilizatorii dau click din newsletter.)%\r\n** Integreaza tag-urile de tracking cu Google Analytics. %(comment)(Asta ne permite sa vedem cat de eficient este un newsletter.)%\r\n\r\n',13,'public',NULL,NULL),('okr/20084/fund-raising','okr/20084/wickedman/fund-raising','2008-11-05 20:43:24','2008-11-05 20:43:24','(okr)* Alcatuieste portofoliu de sponsori.\r\n** Centralizeaza lista cu sponsorii infoarena, contributiile lor, si date de contact.\r\n\r\n',13,'public',NULL,NULL),('okr/20084/wickedman','wickedman, obiective pe trimestrul 4, anul 2008','2008-11-05 20:45:14','2008-11-05 21:00:13','h1. Cristian George Strat\r\n\r\nh2. Obiective pe trimestrul 4, 2008\r\n\r\n(To be done.)\r\n\r\nh3. Newsletter\r\n\r\n==include(page=\"okr/20084/newsletter\")==\r\n\r\nh3. Fund Raising\r\n\r\n==include(page=\"okr/20084/fund-raising\")==\r\n\r\nh3. Community Ladder\r\n\r\n==include(page=\"okr/20084/community-ladder\")==',13,'public',NULL,NULL),('blog/de-ce-python','De ce Python?','2008-11-07 07:20:56','2008-11-15 13:41:14','Am tot auzit lucruri bune despre limbajul de programare Python si unde lucrez are o sustinere destul de mare. Am devenit din ce in ce mai curios si la inceputul verii am scris cateva programele ca sa imi incerc puterile.\r\n\r\nPentru ca inveti un limbaj nu prin a citi o gramada de carti ci prin lucra in el, am cautat o modalitate de a scrie cateva programe simple. Am intrat pe \'projecteuler.net\':http://projecteuler.net . Acesta e un site cu in jur de 200 de probleme si fiecare problema are ca raspuns un numar. Poti incerca sa gasesti rezultatul folosind creionul si hartia sau sa codezi un program in orice limbaj. Dupa ce ai rezolvat o problema ai acces la threadul de pe forum unde discuta cei ce au rezolvat problema. Acolo sunt multi oameni care isi posteaza rezolvarile cat mai concise sau cat mai eficiente si astfel vezi mai multe solutii diferite de a ta si inveti smecherii de limbaj sau algoritmi mai buni.\r\n\r\nDupa cateva luni imi place limbajul foarte mult. Chestia cea mai misto e ca am ajuns sa ma simt productiv foarte repede in el. E un limbaj interpretat asa ca nu trebuie sa astepti dupa compilare. Pe langa asta are o consola in care poti sa incerci sa vezi ce fac diverse bucati de cod. Lucru foarte util cand nu stii limbajul. De asemenea este destul de intuitiv. S-a intamplat de mai multe ori sa nu fiu sigur de cum se fac unele lucruri, sa le incerc si sa mearga.\r\n\r\nAlt avantaj este acela ca limbajul e dynamically si strongly typed. Asta inseamna ca nu o sa iti mai bati capul ca in C++ cu erori interminabile de compilare si mai inseamna ca limbajul suporta programarea cu generice. Astfel putem avea programe de genul:\r\n\r\n== code(c) |\r\n>>> def suma(a, b):\r\n...   return a + b\r\n>>> suma(1, 2)\r\n3\r\n>>> suma(\'mere\', \'pere\')\r\n\'merepere\'\r\n==\r\n\r\nImi place ca indentarea codului face parte din limbaj, aceasta restrictie ajuta mult la lizibilitatea programelor pentru ca impune un stil de codat similar pentru toata lumea. Iar lizibilitatea unui cod este foarte importanta, pentru ca petrecem mult mai mult timp citind cod decat scriind cod nou.\r\n\r\nDe asemenea limbajul incearca sa ajute programatorul cat mai mult, izoland detalii care nu sunt importante. De exemplu la operatiile pe intregi avem implementate numere mari si nu mai trebuie sa avem grija sa nu facem overflow.\r\n\r\nEste un limbaj succint. Spre deosebire de java, pentru a face ceva nu trebuie sa scrii foarte mult.\r\n\r\nAre foarte multe librarii, unele dintre ele intrate deja in limbajul de baza. Ca exemple as aminti _NumPy_,o librarie de calcule numerice, care contine printre altele metode din algebra liniara sau generatoare de numere aleatoare, _sqlite_ care se ocupa cu operatii pe o baza de date si _PIL_ o librarie de prelucrare a imaginilor.\r\n\r\nIn Python se poate folosi si paradigma programarii functionale. El are elemente ca _map()_, _reduce()_, _filter()_, si operatorul _lambda_. \r\nMetoda _map(functie, secventa)_ ne intoarce o lista care sunt rezultatele aplicarii functiei peste elementele unei secvente. Operatorul _reduce(functie, lista)_ ne intoarce rezultatul aplicarii cumulate a functiei peste elementele secventei. Putem scrie cod de genul:\r\n\r\n== code(c) |\r\n>>> # un sir de intregi din unul de stringuri\r\n>>> map(int, [\"1\", \"2\", \"3\"])\r\n[1, 2, 3]\r\n>>>  # suma elementelor din un sir\r\n>>> reduce(lambda x,y: x + y, [1, 2, 3])\r\n6\r\n>>>  # filtram elementele impare\r\n>>> filter(lambda x: x % 2 == 0, [1, 2, 3])\r\n[2]\r\n==\r\n\r\nFaptul ca limbajul nu este unul pur functional, face invatarea ideilor din programarea functionala mai usoara.\r\n\r\nMai imi plac si _list comprehensions_ care sunt doar _zahar sintactic_, dar le folosesc destul de des. Ele sunt o modalitate naturala si succinta de a crea liste. Va dau mai jos cateva exemple:\r\n== code(c) |\r\n>>>  # patratele numerelor de la 1 la 4\r\n>>> [x**2 for x in range(1, 5)]\r\n[1, 4, 9, 16]\r\n>>> # pentru doi vectori a si b\r\n>>> a, b = [1, 2, 3, 4], [1,4,8,16]\r\n>>> # toate sumele intre un element din a si unul din b\r\n>>> [x + y for x in a for y in b]\r\n[2, 5, 9, 17, 3, 6, 10, 18, 4, 7, 11, 19, 5, 8, 12, 20]\r\n==\r\n\r\nSi imi mai plac _tuplurile_ pentru ca de multe ori ai nevoie de cate un tip de date rapid. De exemplu un punct 3 dimensional il putem obtine ca _punct = (-1, 0, 11)_.\r\n\r\nCa minusuri, unul mare este eficienta. Astfel cand scriam solutii pentru probleme de la google code jam, unele erau de 50 pana la 100 de ori mai incete ca varianta implementata in java sau C++. Dar cred ca productivitatea programatorului este mult mai importanta ca eficienta codului, iar Python lucreaza bine cu limbajul C si bucatile ineficiente pot fi reimplementate in C.\r\n\r\nSper ca, daca nu ati lucrat deja in Python, v-am trezit putin apetitul. Daca aveti deja experienta cu Python ce caracteristici v-au placut? Cei care nu sunt convinsi inca pot citi \'aici\':http://norvig.com/spell-correct.html cum se poate face un spell corrector in 21 de linii de Python.',1490,'protected',3347,NULL),('utilizator/alexthero','Profil alexthero','2006-11-24 20:57:39','2008-11-08 22:12:27','\'Topcoder handle\':http://www.topcoder.com/tc?module=MemberProfile&cr=22658843\r\n\r\nh2. Studii\r\n\r\n* 2008-prezent: Jacobs University Bremen, majoring in Computer Science\r\n* 2006-2008: International Computers High School of Bucharest\r\n* 2000-2006: Liceul \"Avram Iancu\" Cluj-Napoca\r\n\r\nh2. Premii si distinctii\r\n\r\n* Bronz BOI 2008, Bitola, Macedonia\r\n* Premiul I, \"Grigore Moisil\" Baia Mare 2004, \"Marian Tarina\" Turda 2004, 2005\r\n* Premiul II, ONI 2005 Galati, PreONI 2008\r\n* Premiul III, Stelele Informaticii, 2007, 2008, .Campion 2007\r\n* Mentiune ONI 2004, 2006, 2007, 2008\r\n* Component al lotului national de informatica 2007, 2008\r\n* calificare la finalele TCHS (2007, 2008)\r\n* calificare la semifinala Google CodeJam 2008\r\n* Premiu special, .Campion 2008\r\n\r\nCV-ul meu (deocamdata scurt) poate fi vazut \'aici\':http://infoarena.ro/utilizator/alexthero?action=download&file=cv.pdf\r\n\r\nh2. Activitati si timp liber\r\n\r\n* masini - am un Ford Mondeo model 2003, cu motor de 1.8 si 125 de cai putere\r\n* web design\r\n* inot, fotbal\r\n\r\nh2. Mentori\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"mugurelionut\" type=\"tiny\")==\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* ==user(user=\"chucknorris\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"sims_gl\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"cezarmocan\" type=\"tiny\")==\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"devilkind\" type=\"tiny\")==\r\n* ==user(user=\"adriana_s\" type=\"tiny\")==\r\n* ==user(user=\"mariusdrg\" type=\"tiny\")==\r\n* ==user(user=\"prostu\" type=\"tiny\")==\r\n* ==user(user=\"dama\" type=\"tiny\")==\r\n* ==user(user=\"vially\" type=\"tiny\")==\r\n* ==user(user=\"webspider\" type=\"tiny\")==\r\n* ==user(user=\"cimi\" type=\"tiny\")==\r\n\r\nh1. Haide \"U\"!',716,'protected',NULL,NULL),('utilizator/monocrom133','Profil monocrom133','2008-11-08 07:44:55','2008-11-08 07:44:55','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',8784,'public',NULL,NULL),('schimbare-borland/ghid/instalare','Ghid de instalare pentru MinGW Developer Studio','2008-11-10 16:19:38','2008-11-10 19:18:52','h1. Ghid de instalare pentru MinGW Developer Studio\r\n\r\n==include(page=\"schimbare-borland/ghid/menu\")==\r\n\r\nInstalarea MinGW Developer Studio nu necesita nici un fel de efort si este foarte simpla (necesitand 5 clickuri).\r\nUrmatoarele imagini sunt un preview pentru instalare.\r\n\r\n!schimbare-borland/ghid/instalare?install_dev_1.JPG!\r\n\r\n!schimbare-borland/ghid/instalare?install_dev_2.JPG!\r\n\r\n!schimbare-borland/ghid/instalare?install_dev_3.JPG!\r\n\r\n!schimbare-borland/ghid/instalare?install_dev_4.JPG!\r\n\r\n!schimbare-borland/ghid/instalare?install_dev_5.JPG!\r\n\r\n!schimbare-borland/ghid/instalare?install_dev_6.JPG!\r\n',1490,'public',NULL,NULL),('schimbare-borland/ghid/menu','schimbare-borland/ghid/menu','2008-11-10 19:14:48','2008-11-25 10:38:48','(toc)*{text-align:center} *Ghid*\r\n* \'Despre MinGW\':schimbare-borland/ghid\r\n* \'Instalare\':schimbare-borland/ghid/instalare\r\n* \'Crearea unui proiect\':schimbare-borland/ghid/proiect\r\n* \'Scrierea unei surse\':schimbare-borland/ghid/sursa\r\n* \'Debugging\':schimbare-borland/ghid/debug\r\n',75,'public',NULL,NULL),('blog/problema-saptamanii-probabilitati','Problema saptamanii - Probabilitati','2008-11-10 23:46:33','2008-11-15 13:41:14','_De data asta va dau doua probleme interesante de probabilitati, sunt relativ clasice, deci nu va suparati daca le-ati mai vazut inainte. Va amintesc ca imi puteti trimite solutii la cosminn at gmail.com._\r\n\r\n1. Se da o moneda ce nu e ideala, adica nu cade cap sau pajura cu probabilitatea 0.5 ci cu o probabilitate _p_ respectiv _1-p_. Nu stim cat e valoarea lui _p_. Exita o metoda de a genera valori 0 sau 1 cu probabilitati egale?\r\n\r\n2. Presupunem ca am gasit o modalitate de a obtine valori 0 sau 1 cu probabilitati egale. Exista acum o modalitate de a alege cu aceiasi probabilitate unul dintre fructele mar, para sau portocala, folosind metoda de generare a numerelor 0 sau 1? ',1490,'protected',3349,NULL),('schimbare-borland/ghid/proiect','Crearea unui proiect in MinGW Developer Studio','2008-11-10 17:27:32','2009-08-21 09:54:00','h1. Crearea unui proiect in MinGW Developer Studio\r\n\r\n==include(page=\"schimbare-borland/ghid/menu\")==\r\n\r\nPentru a compila si a rula surse folosind mediul MinGW Developer Studio este necesara crearea unui proiect. Majoritatea mediilor de dezvoltare folosite in programare folosesc proiecte pentru a oferi o usoara administrare a programului aflat in dezvoltare.\r\n\r\nDaca lucrati la o solutie ce foloseste un singur fisier, un proiect poate parea sa va ingreuneze munca, insa din momentul in care veti implementa un proiect mai complex, conceptul de proiect o sa capete mai mult sens.\r\n\r\nPentru a crea un proiect nou puteti alege din urmatoarele trei optiuni:\r\n\r\n# Da-ti click pe prima icona din toolbar\r\n# Selectati File->New\r\n# Tastati Ctrl-N\r\n\r\n\'!schimbare-borland/ghid/proiect?creare_proiect_1.JPG 30%!\':schimbare-borland/ghid/proiect?action=download&file=creare_proiect_1.JPG \'!schimbare-borland/ghid/proiect?creare_proiect_2.JPG 30%!\':schimbare-borland/ghid/proiect?action=download&file=creare_proiect_2.JPG\r\n\r\nVom crea un proiect simplu, care interactioneaza cu consola din Windows. Alegeti locatia in care vreti sa se salveze proiectul vostru si dati-i un nume si selectati \"Win32 Console Application\" si apoi dati click pe butonul \"OK\".\r\n\r\n\r\n\'!schimbare-borland/ghid/proiect?creare_proiect_3.JPG 30%!\':schimbare-borland/ghid/proiect?action=download&file=creare_proiect_3.JPG \r\n\r\nFelicitari, ati creat un proiect in MinGW Developer Studio.\r\n\r\n\'!schimbare-borland/ghid/proiect?creare_proiect_4.JPG 30%!\':schimbare-borland/ghid/proiect?action=download&file=creare_proiect_4.JPG \r\n\r\n',3689,'public',NULL,NULL),('utilizator/dragosldf','Profil dragosldf','2008-11-11 14:45:57','2008-11-11 14:45:57','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',8808,'public',NULL,NULL),('okr/20094/fund-raising','okr/20094/fund-raising','2009-10-28 18:12:30','2009-10-28 18:12:30','(okr)* Obtine sponsorizari pentru Algoritmiada 2010.\r\n** Alcatuieste mapa cu care o sa ne prezentam sponsorilor.\r\n** Contacteaza posibilii sponsori.\r\n',2038,'public',NULL,NULL),('okr/20094','OKRs 2009Q4','2009-10-28 17:25:56','2010-01-12 18:23:32','h2. 2009Q4\r\n\r\nMedia notelor pe acest trimestru a fost **0.89**.\r\n\r\nh3(#arhiva). Arhivele de probleme\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Adauga Probleme | ==user(user=\"stef2n\" type=\"tiny\")== | ==include(page=\"okr/20094/adauga-probleme\")== | 0.9 |\r\n| Tagging|==user(user=\"bogdan2412\" type=\"tiny\")== | ==include(page=\"okr/20094/tagging\")== | 0.9 |\r\n\r\nh3(#concursuri). Concursuri\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Organizeaza concursuri | ==user(user=\"bogdan2412\" type=\"tiny\")== | ==include(page=\"okr/20094/organizeaza-concursuri\")== | 1 |\r\n| \'Algoritmiada 2010\':algoritmiada-2010 | ==user(user=\"pauldb\" type=\"tiny\")== | ==include(page=\"okr/20094/algoritmiada\")== | 1 |\r\n\r\nh3(#continut). Continut educational\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Scrie articole\':implica-te/scrie-articole | ==user(user=\"marius\" type=\"tiny\")== | ==include(page=\"okr/20094/articole\")== | 0.6 |\r\n\r\nh3(#development). Development\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'infoarena 2.x Stable\':http://hackers.devnet.ro/roadmap | ==user(user=\"bogdan2412\" type=\"tiny\")== | ==include(page=\"okr/20094/devel-ia2\")== | 1 |\r\n\r\nh3(#administrativ). Administrativ\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Strangere fonduri | ==user(user=\"gcosmin\" type=\"tiny\")== | ==include(page=\"okr/20094/fund-raising\")== | 0.8 |\r\n',2038,'public',NULL,NULL),('template/despre-infoarena','template/despre-infoarena','2006-12-10 20:21:49','2009-01-26 14:34:16','(vmenu)* \'Despre infoarena\':despre-infoarena\r\n* \'Prezentare\':prezentare\r\n* \'Echipa\':echipa-infoarena\r\n* \'Obiective curente\':okr\r\n* \'Asociatia infoarena\':asociatia-infoarena\r\n* \'Regulament\':regulament\r\n* \'Registru diplome\':registru-diplome\r\n* \'Marturii\':marturii\r\n* \'Contact\':contact\r\n',13,'protected',NULL,NULL),('okr/20091','OKRs 2009Q1','2009-01-26 14:41:23','2009-11-26 18:43:41','h2. 2009Q1\r\n\r\nMedia notelor pe acest trimestru a fost *0.6*.\r\n\r\nh3(#arhiva). Arhiva de probleme\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Extinde arhiva\':implica-te/extinde-arhiva | ==user(user=\"ditzonec\" type=\"tiny\")== | ==include(page=\"okr/20091/extinde-arhiva\")== | 1 |\r\n| \'Imbunatateste teste\':implica-te/imbunatatire-teste | ==user(user=\"ditzonec\" type=\"tiny\")== | ==include(page=\"okr/20091/imbunatatire-teste\")== | .0 |\r\n| \'Arhiva educationala\':implica-te/arhiva-educationala | ==user(user=\"pauldb\" type=\"tiny\")== | ==include(page=\"okr/20091/arhiva-educationala\")== | .2 |\r\n| Tagging|==user(user=\"bogdan2412\" type=\"tiny\")== | ==include(page=\"okr/20091/tagging\")== | .0 |\r\n\r\nh3(#concursuri). Concursuri\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Organizeaza concursuri | ==user(user=\"astronomy\" type=\"tiny\")== | ==include(page=\"okr/20091/organizeaza-concursuri\")== | 1 |\r\n| Algoritmiada | ==user(user=\"wefgef\" type=\"tiny\")== | ==include(page=\"okr/20091/algoritmiada\")== | .95 |\r\n| \'Virtual contests\':propuneri/10-virtual-contest | ==user(user=\"gcosmin\" type=\"tiny\")== | ==include(page=\"okr/20091/virtual-contest\")== | 1 |\r\n| \'Calendar\':forum?action=calendar | ==user(user=\"pauldb\" type=\"tiny\")== | ==include(page=\"okr/20091/calendar\")== | 1 |\r\n\r\nh3(#continut). Continut educational\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Scrie articole\':implica-te/scrie-articole | ==user(user=\"stef2n\" type=\"tiny\")== | ==include(page=\"okr/20091/articole\")== | .6 |\r\n\r\nh3(#development). Development\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'infoarena 2.x Stable\':http://hackers.devnet.ro/roadmap | ==user(user=\"domino\" type=\"tiny\")== | ==include(page=\"okr/20091/devel-ia2\")== | .75 |\r\n\r\nh3(#comunitate). Comunitate\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Community Ladder\':propuneri/7-community-ladder | ==user(user=\"wickedman\" type=\"tiny\")==, ==user(user=\"silviug\" type=\"tiny\")==  | ==include(page=\"okr/20091/community\")== | .1 |\r\n\r\nh3(#administrativ). Administrativ\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Newsletter | ==user(user=\"wickedman\" type=\"tiny\")==| ==include(page=\"okr/20091/newsletter\")== | .8 |\r\n| Strangere fonduri | ==user(user=\"wickedman\" type=\"tiny\")== | ==include(page=\"okr/20091/fund-raising\")== | .4 |\r\n',2044,'public',NULL,NULL),('okr/20091/algoritmiada','okr/20091/algoritmiada','2009-01-26 14:45:51','2009-02-15 00:38:10','(okr)* Organizarea Rundei 3\r\n** Stabilirea listei de invitaţi la finală\r\n\r\n(okr)* Organizarea Rundei finale\r\n** Selectarea concurenţilor ce participă finală\r\n** Selectarea subiectelor pentru finală\r\n** Respectarea programului de lucru stabilit de comisia ştiinţifică\r\n** Stabilirea locaţiei si datei de desfăşurare\r\n** Sponsori\r\n** Comunicat de presa online şi apariţii în presa scrisă\r\n',13,'public',NULL,NULL),('okr/20091/arhiva-educationala','okr/20091/arhiva-educationala','2009-01-26 14:46:08','2009-02-09 13:33:56','(okr)* dezvoltarea arhivei educationale\r\n** de imbunatatit documentatia\r\n** de gasit useri noi pentru echipa\r\n** de adaugat 15 probleme noi\r\n** de verificat si imbunatatit 5 probleme de pana acum\r\n** de updatat pagina principala\r\n',1792,'public',NULL,NULL),('okr/20091/articole','okr/20091/articole','2009-01-26 14:46:24','2009-01-26 15:59:09','(okr)* Sporirea numarului de articole de pe site\r\n** Aparitia a 10 articole, noi sau transcrieri\r\n* Sporirea interactivitatii articolelor\r\n** Implementarea ticketului \'362\':http://hackers.devnet.ro/ticket/362 referitor la comentarii in stil de blog pentru orice pagina wiki',2044,'public',NULL,NULL),('okr/20091/calendar','okr/20091/calendar','2009-01-26 14:46:37','2009-01-26 14:52:11','(okr)* anuntarea concursurilor din timp\r\n** sa mearga treaba ca si pana acum',13,'public',NULL,NULL),('okr/20091/community','okr/20091/community-ladder','2009-01-26 14:46:50','2009-01-26 16:02:40','(okr)* Design Community Ladder.\r\n** Finalizează, dezbate şi aprobă \'IAP#7 - Community Ladder\':http://infoarena.ro/propuneri/7-community-ladder.\r\n* Community Dashboard: Afişează în timp real câţi şi ce utilizatori&hellip;\r\n** Trimit soluţii la arhivă, arhiva educaţională\r\n** Activează pe forum\r\n** Contribuie pe wiki, la probleme, la documentaţie.\r\n** Participă la concursuri\r\n** Trimit patch-uri în repository\r\n',13,'public',NULL,NULL),('okr/20091/devel-ia2','okr/20091/devel-ia2','2009-01-26 14:47:01','2009-02-08 15:54:27','(okr)* continuarea dezvoltarii infoarena 2.x \r\n** organizam 1-2 coding camp-uri cu echipa infoarena\r\n** lansam facilitatea de concursuri virtuale \r\n',1,'public',NULL,NULL),('schimbare-borland/ghid/debug','Depanarea cu MinGW Developer Studio','2008-11-11 21:04:03','2008-11-13 15:56:28','h1. Depanarea cu MinGW Developer Studio\r\n\r\n==include(page=\"schimbare-borland/ghid/menu\")==\r\n\r\nO parte importanta a unui mediu de dezvoltare pentru programatori il constituie depanatorul. MinGW Developer Studio foloseste gdb in acest scop, oferind o interfata simpla si intuitiva pentru urmarirea pasilor de executie ai programului.\r\n\r\nErorile de compilare sunt afisate in partea inferioara a ferestrei, in tabul \"Build\". Pentru a gasi usor eroare se poate da click pe eroare si cursorul va fi pozitionat pe linia unde a fost intampinata eroarea.\r\n\r\n\'!schimbare-borland/ghid/debug?debug_1.JPG 30%!\':schimbare-borland/ghid/debug?action=download&file=debug_1.JPG \'!schimbare-borland/ghid/debug?debug_2.JPG 30%!\':schimbare-borland/ghid/debug?action=download&file=debug_2.JPG\r\n\r\nPentru a incepe depanarea stabilim mai intai puctele de interes la care vrem ca programul nostru sa se opreasca pentru a putea vedea evolutia lui. Se aseaza cursorul pe liniile la care se doreste oprirea executiei programului si se marcheaza din meniu Debug->Toggle Brakepoint sau se tasteaza F9.\r\n\r\n\'!schimbare-borland/ghid/debug?debug_3.JPG 30%!\':schimbare-borland/ghid/debug?action=download&file=debug_3.JPG \'!schimbare-borland/ghid/debug?debug_4.JPG 30%!\':schimbare-borland/ghid/debug?action=download&file=debug_4.JPG\r\n\r\nPentru a porni procesul de depanare se selecteaza din meniu Debug->Go sau se tasteaza F5.\r\n\r\n\'!schimbare-borland/ghid/debug?debug_5.JPG 30%!\':schimbare-borland/ghid/debug?action=download&file=debug_5.JPG \'!schimbare-borland/ghid/debug?debug_6.JPG 30%!\':schimbare-borland/ghid/debug?action=download&file=debug_6.JPG\r\n\r\nSageata galbena indica linia la care se afla executia programului. Pentru a chestiona variabilele se deschide watch din meniu Debug->QuickWatch sau se tasteaza Shift+F5. In fereastra deschisa se pot tasta expresii care vor fi evaluate folosind datele din faza curenta de executie a programului (constante, variabile, functii)\r\n\r\n\'!schimbare-borland/ghid/debug?debug_7.JPG 30%!\':schimbare-borland/ghid/debug?action=download&file=debug_7.JPG \'!schimbare-borland/ghid/debug?debug_8.JPG 30%!\':schimbare-borland/ghid/debug?action=download&file=debug_8.JPG\r\n\r\nPentru a face un pas peste o linie se face click pe Debug->Step Over sau se tasteaza F10. In cazul unei functii, daca se doreste sa depanatorul sa intre in apelul functiei, fara sa sare direct la evaluare ei se poate folosi Debug->Step Into sau se poate tasta F11.\r\n\r\n\'!schimbare-borland/ghid/debug?debug_9.JPG 30%!\':schimbare-borland/ghid/debug?action=download&file=debug_9.JPG \'!schimbare-borland/ghid/debug?debug_10.JPG 30%!\':schimbare-borland/ghid/debug?action=download&file=debug_10.JPG\r\n\'!schimbare-borland/ghid/debug?debug_11.JPG 30%!\':schimbare-borland/ghid/debug?action=download&file=debug_11.JPG\r\n\r\nPentru a sari la urmatorul Breakpoint se poate face click pe Debug->Go sau se poate tasta F5.\r\n\r\n\'!schimbare-borland/ghid/debug?debug_12.JPG 30%!\':schimbare-borland/ghid/debug?action=download&file=debug_12.JPG \'!schimbare-borland/ghid/debug?debug_13.JPG 30%!\':schimbare-borland/ghid/debug?action=download&file=debug_13.JPG\r\n\r\nPentru a opri procesul de debug se face click pe Debug->Stop Debugging sau se tasteaza Shift+F5.\r\n\r\n\'!schimbare-borland/ghid/debug?debug_14.JPG 30%!\':schimbare-borland/ghid/debug?action=download&file=debug_14.JPG \'!schimbare-borland/ghid/debug?debug_15.JPG 30%!\':schimbare-borland/ghid/debug?action=download&file=debug_15.JPG\r\n\r\n',15,'public',NULL,NULL),('planificare/sedinta-20081107','Sedinta 2008-11-07','2008-11-02 11:48:43','2008-11-13 18:04:55','h1. Sedinta 2008-11-07\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *vineri, 7 noiembrie* la ora *18:30* la \'*Retro Cafe*\':http://metropotam.ro/Unde-iesim/2008/07/art2701725520-Millennium-Bank-recomanda-Retro-Cafe/\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* _&hellip; asteptam confirmari_\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioare\':planificare/sedinta-20081021\r\n* Stabilit data pentru sedinta urmatoare\r\n* Update OJI \'Schimbare Borland\':schimbare-borland/argumentatie\r\n* preONI/infoarena Challenge 2009\r\n* discutat/votat OKR-uri + focus\r\n** La articole momentan se propun mai multe; Am vb cu Malex si e de acord sa bagam cioturi de articole cu problemele pe care le-a cules el de pe net pe diverse teme (se gasesc in temele date la ICHB si \'aici\':http://www.google.com/notebook/public/13674492159061973354/BDQ6ESwoQnNix_ugi)\r\n* \'Coding Camp Alcatraz\':planificare/camp-alcatraz\r\n* \'Virtual Contests\':propuneri/10-virtual-contest\r\n* Ce facem cu Hackaton?\r\n* Adrese de email @infoarena.ro, Mircea si Silviu au privilegii de administrare pe Google Apps.\r\n\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Alegeri pentru OJI:\r\n** Compilator: MinGW GCC\r\n** IDE: MinGW Developer\r\n* Urmatorii pasi:\r\n** documentatie: diferente intre compilatoare, mic ghid de start pentru IDE-uri\r\n*** ==user(user=\"victorsb\" type=\"tiny\")==, ==user(user=\"prostu\" type=\"tiny\")==\r\n** pachet: instalat toate software-urile din cateva click-uri\r\n*** ==user(user=\"svalentin\" type=\"tiny\")== ( ==user(user=\"domino\" type=\"tiny\")== da idei)\r\n* Deadline: 13 noiembrie 2008 (1 saptamana)\r\n\r\n* preONI: avem \'topic cu nume\':forum/index.php/topic,3312.msg28118.html#msg28118\r\n* Wefgef baga mail pe grup si votam pana luni seara (10 noiembrie) %{color:red;}(done)%\r\n* Mircea ii da mail @ infoarena lui Vali (svalentin), Prostu (prostu), GCosmin (gcosmin) %{color:red;}(done)%\r\n* Coding Camp sambata la ora 10:00\r\n* Wefgef pregateste infrastructura pentru viitorul \"preONI\"\r\n** Prima runda vrem sa fie in jur de 14 decembrie\r\n* Mircea le da la Prostu si Gcosmin acces la Google Analytics %{color:red;}(done)%\r\n* Tero si Victor isi completeaza profilul %{color:red;}(Tero done)%\r\n* Urmatoarea sedinta va fi pe 18 noiembrie\r\n\r\nh2. Notite\r\n\r\n* Sa plateasca infoarena de acum la sedinta\r\n',1,'public',NULL,NULL),('schimbare-borland/ghid/sursa','Ghid pentru scriere unei surse in MinGW Developer Studio','2008-11-10 19:49:16','2008-11-13 15:52:43','h1. Ghid pentru scriere unei surse pentru un proiect in MinGW Developer Studio.\r\n\r\n==include(page=\"schimbare-borland/ghid/menu\")==\r\n\r\nDupa ce ati creat un proiect in MinGW Developer Studio urmeaza sa creati o sursa. Pentru a crea o sursa puteti da click pe prima icoana din toolbar SAU File->New si apoi selectati C/C++ Source File si denumiti fisierul. Aveti grija sa fie bifata casuta \"Add to project\", daca nu este bifata sursa creata nu va fi adaugata la proiect si va trebui adaugata ulterior.\r\n\r\n\'!schimbare-borland/ghid/sursa?creare_sursa_3.JPG 30%!\':schimbare-borland/ghid/sursa?action=download&file=creare_sursa_3.JPG \'!schimbare-borland/ghid/sursa?creare_sursa_4.JPG 30%!\':schimbare-borland/ghid/sursa?action=download&file=creare_sursa_4.JPG\r\n\r\nO alta optiune pentru a adauga o sursa la un proiect este urmatoarea: right-click pe proiect si se selecteaza sursa. Se poate introduce orice nume, daca fisierul nu exista atunci cand dati dublu-click pe nume veti fi intrebati daca doriti ca fisierul sa fie creat. Daca fisierul exista, cand dati dublu-click pe nume fisierul va fi deschis.\r\n\r\n\'!schimbare-borland/ghid/sursa?creare_sursa_1.JPG 30%!\':schimbare-borland/ghid/sursa?action=download&file=creare_sursa_1.JPG \'!schimbare-borland/ghid/sursa?creare_sursa_2.JPG 30%!\':schimbare-borland/ghid/sursa?action=download&file=creare_sursa_2.JPG\r\n\'!schimbare-borland/ghid/sursa?creare_sursa_2_bis.JPG 30%!\':schimbare-borland/ghid/sursa?action=download&file=creare_sursa_2_bis.JPG\r\n\r\nAcum suntem fericiti: putem scrie sursa. Exemple in C si respectiv in C++ in pozele ce urmeaza:\r\n\r\n\'!schimbare-borland/ghid/sursa?creare_sursa_c.JPG 30%!\':schimbare-borland/ghid/sursa?action=download&file=creare_sursa_c.JPG \'!schimbare-borland/ghid/sursa?creare_sursa_cpp.JPG 30%!\':schimbare-borland/ghid/sursa?action=download&file=creare_sursa_cpp.JPG\r\n\r\nProgramul se compileaza din Build->Build and Execute sau apasand tasta F8.\r\n\r\n\'!schimbare-borland/ghid/sursa?creare_sursa_6.JPG 30%!\':schimbare-borland/ghid/sursa?action=download&file=creare_sursa_6.JPG\r\n\r\nPentru a elimina o anumita sursa din proiect se face right-click pe numale sursei in structura arborescenta a fisierelor proiectului si se selecteaza \"Remove nume_sursa.cpp from project\".\r\n\r\n\'!schimbare-borland/ghid/sursa?creare_sursa_8.JPG 30%!\':schimbare-borland/ghid/sursa?action=download&file=creare_sursa_8.JPG\r\n\r\n',15,'public',NULL,NULL),('schimbare-borland/ghid-freepascal/instalare','Ghid de instalare pentru Free Pascal','2008-11-13 18:03:46','2008-11-25 12:12:42','h2(#instalare). Ghid de instalare pentru Free Pascal\r\n\r\nInstalarea Free Pascal este foarte simpla si se efectueaza confirmand setarile implicite din cele 6 etape. Dupa instalare este necesara stergerea fisierului C:\\FPC\\2.2.2\\bin\\i386-win32\\fp.cfg pentru a rezolva o problema de incompatibilitate. Acest fisier va fi creat corect automat la prima rulare a mediului Free Pascal.\r\n\r\nIata un preview:\r\n\r\n!schimbare-borland/ghid-freepascal/instalare?install_freepascal1.JPG!\r\n\r\n!schimbare-borland/ghid-freepascal/instalare?install_freepascal2.JPG!\r\n\r\n!schimbare-borland/ghid-freepascal/instalare?install_freepascal3.JPG!\r\n\r\n!schimbare-borland/ghid-freepascal/instalare?install_freepascal4.JPG!\r\n\r\n!schimbare-borland/ghid-freepascal/instalare?install_freepascal5.JPG!\r\n\r\n!schimbare-borland/ghid-freepascal/instalare?install_freepascal6.JPG!\r\n\r\n!schimbare-borland/ghid-freepascal/instalare?install_freepascal7.JPG!\r\n\r\n!schimbare-borland/ghid-freepascal/instalare?install_freepascal8.JPG!\r\n\r\n!schimbare-borland/ghid-freepascal/instalare?install_freepascal9.JPG!\r\n',1490,'public',NULL,NULL),('runda/matrice','matrice','2009-04-13 07:44:18','2009-04-13 07:44:18','h1. == roundparam(round_id=\"matrice\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"matrice\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"matrice\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"matrice\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/matrice/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"matrice\" score=\"1\")==',9356,'round: matrice',NULL,NULL),('schimbare-borland/ghid-freepascal/mediu','Folosirea mediului Free Pascal','2008-11-13 18:38:26','2008-11-25 12:13:01','h2(#mediu). Folosirea mediului Free Pascal\r\n\r\nMediul Free Pascal este asemenator celui din Borland Pascal.\r\n\r\nh3. Manipularea Fisierelor\r\n\r\nSe creaza un fisier nou urmand calea File-New din meniu. Acesta poate fi salvat din meniu(File-Save) sau apasand F2.\r\nPentru deschiderea unui fisier existent se foloseste File-Open sau se apasa F3 dupa care se selecteaza calea fisierului.\r\n\r\n\'!schimbare-borland/ghid-freepascal/mediu?file_new.JPG 50%!\':schimbare-borland/ghid-freepascal/mediu?action=download&file=file_new.JPG \'!schimbare-borland/ghid-freepascal/mediu?sursa_noua.JPG 50%!\':schimbare-borland/ghid-freepascal/mediu?action=download&file=sursa_noua.JPG\r\n\r\nh3. Compilarea si rularea unei surse\r\n\r\nPentru a compila o sursa intai se deschide fisierul respectiv dupa care se selecteaza din meniu Compile-Compile sau se apasa Alt - F9.\r\nPentru a rula o sursa se foloseste calea Run-Run din meniu sau se apasa Ctrl - F9.\r\n\r\nObservatie: Executabilul sursei si orice alte fisiere cu care acesta va interactiona se vor gasi in **directorul curent**.\r\n\r\n\'!schimbare-borland/ghid-freepascal/mediu?compile.JPG 50%!\':schimbare-borland/ghid-freepascal/mediu?action=download&file=compile.JPG\r\n\r\nh3. Modificarea directorului curent\r\n\r\nDirectorul in care lucreaza mediul Free Pascal este in mod implicit C:\\FPC\\2.2.2\\bin\\i386-win32\\. Acesta poate fi schimbat din meniu(File-Change dir..) sau executand click-dreapta pe shortcut-ul Free Pascal, selectand Properties si modificand campul \"Start in:\".\r\n\r\n\'!schimbare-borland/ghid-freepascal/mediu?change_dir.JPG 50%!\':schimbare-borland/ghid-freepascal/mediu?action=download&file=change_dir.JPG \'!schimbare-borland/ghid-freepascal/mediu?start_in.JPG 60%!\':schimbare-borland/ghid-freepascal/mediu?action=download&file=start_in.JPG\r\n',1490,'public',NULL,NULL),('treapuri','Treapuri','2008-01-21 16:18:25','2010-01-24 11:58:11','h1. Treapuri\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'{*} Introducere\':treapuri#introducere\r\n* \'{*} Avantaje\':treapuri#avantaje\r\n* \'{*} Operaţii\':treapuri#operatii\r\n** \'- Căutare\':treapuri#cautare\r\n** \'- Rotaţii\':treapuri#rotatii\r\n** \'- Inserare\':treapuri#inserare\r\n** \'- Ştergere\':treapuri#stergere\r\n** \'- Split\':treapuri#split\r\n** \'- Join\':treapuri#join\r\n** \'- Alte operaţii\':treapuri#alte-operatii\r\n* \'{*} Concluzii\':treapuri#concluzii\r\n* \'{*} Aplicaţii\':treapuri#aplicatii\r\n* \'{*} Bibliografie\':treapuri#bibliografie\r\n\r\n\r\nÎn acest articol voi prezenta o alternativă pentru arborii binari de căutare echilibraţi, precum $AVL$, $Red-Black Trees$, $Splay Trees$ şi $B-Trees$.\r\n\r\nh2(#introducere). Introducere\r\n\r\nTreapul este un arbore binar în care fiecare nod conţine două informaţii:\r\n\r\n* $cheie$\r\n\r\n* $prioritate$\r\n\r\nStructura de date respectă doi invarianţi:\r\n\r\n* $dacă parcurgem arborele în inordine, atunci vom obţine nodurile sortate (invariantul arborilor de căutare)$\r\n\r\n* $prioritatea fiecărui nod este mai mare decât cea a fiilor săi (invariantul heapurilor)$\r\n\r\nÎn consecinţă, treapul este un arbore binar de căutare pentru chei şi un max-heap pentru priorităţi.\r\n\r\nÎn continuare, vom presupune că oricare două chei din treapul $T$ sunt distincte. Cazul când avem nevoie de chei egale se va trata relativ uşor după ce acest articol va fi înţeles.\r\n\r\nAstfel, din moment ce $T$ este un heap, nodul $v$ cu prioritatea cea mai mare trebuie să fie rădăcina. Întrucât este şi un arbore binar de căutare, orice nod $u$ cu $cheie(u) < cheie(v)$ se găseşte în subarborele stâng al lui $v$, şi orice nod $w$ cu $cheie(w) > cheie(v)$ se găseşte în subarborele drept.\r\n\r\nCheile şi priorităţile asociate lor, in condiţiile în care ambele sunt distincte, determină în mod unic forma unui treap. Prin inducţie se demonstrează că treapul este arborele binar obţinut prin inserarea cheilor în ordinea descrescătoare a priorităţilor. Algoritmul de inserare este cel obişnuit pentru arborii de căutare. Astfel, cum fiecare set de priorităţi asociat nodurilor va aranja arborele într-un singur mod, probabilitatea ca arborele să fie echilibrat este rezonabil de mare, fapt datorat numărului mic al arborilor rău echilibraţi în comparaţie cu cei echilibraţi. Iată şi secretul acestei structuri de date: probabilitatea infimă de a se găsi o serie de priorităţi generate aleator care să nu menţină arborele echilibrat.\r\n\r\nh2(#avantaje). Avantaje\r\n\r\nStructurile de date de heap şi de arbori binari de căutare sunt uşor de implementat şi de înţeles, iar treapurile sunt o combinaţie a acestor două concepte. Astfel, este suficient să fie înţeleşi cei doi invarianţi, după care implementarea se poate face cu uşurinţă în 20 de minute, fără antrenament. De obicei, la structuri ca $Arborii Roşu-Negru$ trebuie folosite serii de rotaţii stânga şi dreapta complexe şi analizată o multitudine de cazuri, pe când la treapuri facem doar câte o rotaţie stânga sau dreapta la fiecare pas al algoritmului. Ei nu sunt predaţi pentru că se preferă ca exemple didactice $Arborii Roşu-Negru$ sau cei $AVL$ care au o demonstraţie accesibilă că limita celei mai lente operaţii este $O(log N)$. Dar treapurile, deşi cu o demonstraţie mai grea pentru limita de $O(log N)$, ce implică probabilităţi, sunt mult mai uşor de implementat, iar în practică este greu de decis care sunt cei mai rapizi. Sunt, deci, o opţiune demnă de luat în seamă. Pe de altă parte, treapurile suportă şi alte două operaţii pe care nu le putem face cu $Arborii Roşu-Negru$ sau cu arborii $AVL$. Aceste operaţii sunt \'$join$\':treapuri#join şi \'$split$\':treapuri#split.\r\n\r\nh2(#operatii). Operaţii\r\n\r\nCostul operaţiilor de mai jos este proporţional cu adâncimea unui nod din treap. După cum am menţionat mai sus, cu ajutorul teoriei probabilităţilor se poate deduce că adâncimea medie aşteptată a oricărui nod este $O(log N)$, ceea ce implică costul celor mai lente operaţii să fie, în medie, $O(log N)$.\r\n\r\nMai jos avem definiţia în cod $C++$ a unui treap şi o funcţie de iniţializare, care marchează că treapul cu rădăcina $R$ este gol.\r\n\r\n== code(cpp) |\r\nstruct T {\r\n    int key, priority;\r\n    T *left, *right;\r\n    T() {}\r\n    T(int key, int priority, T* left, T* right) {\r\n        this->key = key;\r\n        this->priority = priority;\r\n        this->left = left, this->right = right;\r\n    }\r\n} *R, *nil; // nil indica un nod \'gol\'\r\n\r\nvoid init(T* &R) {\r\n    srand(unsigned(time(0)));\r\n    R = nil = new T(0, 0, NULL, NULL);\r\n}\r\n==\r\n\r\nh3(#cautare). Căutare\r\n\r\nCăutarea într-un treap este identică cu cea într-un arbore binar de căutare. Pentru a verifica dacă o cheie există putem proceda în felul următor:\r\n\r\n== code(cpp) |\r\nint search(T* n, int key) {\r\n    if (n == nil) return 0;\r\n    if (key == n->key) return 1;\r\n    if (key < n->key)\r\n        return search(n->left, key);\r\n    else\r\n        return search(n->right, key);\r\n}\r\n==\r\n\r\nh3(#rotatii). Rotaţii\r\n\r\nRotaţiile sunt cărămizile de la baza structurii de treap.\r\n\r\np=. !treapuri?Fig1-ok.png!\r\n\r\np=. _Rotaţiile într-un arbore binar de căutare. Nodurile sunt reprezentate de cercuri, iar subarborii de triunghiuri. Ambele operaţii de rotaţie menţin invariantul arborilor de căutare._\r\n\r\nSă urmărim efectul rotaţiilor asupra structurii de heap a unui treap care respectă doar invariantul arborilor de căutare. Aşadar, să presupunem că arborele din figura din stânga are o structură de heap cu excepţia lui $w$ care are o prioritate mai mare decât a lui $z$. Dacă îl rotim pe $w$ spre dreapta vedem în figura a doua că structura de heap este satisfăcută. Din moment ce $A$ era un subarbore valid al lui $w$, va rămâne în continuare un subarbore valid. Cum $B$ şi $C$ se aflau iniţial sub $z$, ei aveau o prioritate mai mică decât a lui $z$, şi, astfel, după rotaţie ei sunt subarbori valizi pentru $z$. Este clar că $z$ este un fiu valid al lui $w$, prin presupunerea făcută iniţial. \r\n\r\nSă urmărim dacă invariantul arborilor de căutare se menţine în urma unei astfel de rotaţii.\r\n\r\n* În arborele din figura din stânga avem inegalităţile următoare: $A < w < B; z < C; w, A, B < z$. Din acestea se obţine: $A < w < B < z < C$.\r\n* În arborele din figura din dreapta avem inegalităţile următoare: $A < w; B < z < C; w < z, B, C$. Din acestea se obţine: $A < w < B < z < C$.\r\n\r\nÎntrucât am obţinut acelaşi şir de inegalităţi, am arătat existenţa invariantului arborilor de căutare.\r\n\r\nReţineţi că această rotaţie împreună cu imaginea sa în oglindă stau la baza algoritmilor de \'$inserare$\':treapuri#inserare şi \'$ştergere$\':treapuri#stergere!\r\n\r\nPentru o rotaţie este necesar un număr constant de operaţii cu pointeri.\r\n\r\n== code(cpp) |\r\nvoid rotleft(T* &n) {\r\n    T *t = n->left;\r\n    n->left = t->right, t->right = n;\r\n    n = t;\r\n}\r\n\r\nvoid rotright(T* &n) {\r\n    T *t = n->right;\r\n    n->right = t->left, t->left = n;\r\n    n = t;\r\n}\r\n\r\nvoid balance(T* &n) {\r\n    if (n->left->priority > n->priority)\r\n        rotleft(n);\r\n    else if (n->right->priority > n->priority)\r\n        rotright(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(1)$.\r\n\r\nh3(#inserare). Inserare\r\n\r\nÎn cadrul operaţiei de inserare vom atribui unui nod nou o prioritate aleatoare şi îl vom insera, conform algoritmului standard de inserare într-un arbore binar, la baza arborelui. Să presupunem că dorim să inserăm nodul $z$ cu cheia $9$ şi prioritatea $51$.\r\n\r\np=. !treapuri?Fig2.png!\r\n\r\np=. _De la stânga la dreapta: inserarea nodului $z$. De la dreapta la stânga: ştergerea nodului $z$. Deoarece $z$ are prioritatea cea mai mare dintre toate nodurile, această inserare poate fi privită şi ca o operaţie de $split$. Subarborii stâng şi drept ai rădăcinii din ultima figură sunt chiar treapurile căutate: $T{~<~}$ şi $T{~>~}$. Invers, din $T{~<~}$ şi $T{~>~}$ se obţine, prin ştergerea rădăcinii, rezultatul operaţiei $join$._\r\n\r\nCheile formează un arbore de căutare, dar priorităţile pot să nu mai formeze un heap. Pentru a redobândi această proprietate, cât timp nodul de inserat, are prioritatea mai mare decât a părintelui său, se va executa o \'$rotaţie$\':treapuri#rotatii a lui $z$, o operaţie locală care scade nivelul lui $z$ cu $1$ şi creşte nivelul părintelui lui $z$ cu $1$, şi care menţine invariantul arborilor de căutare. Timpul de inserare al lui $z$ este proporţional cu adâncimea lui înainte de rotaţii - trebuie să coborâm, după care să urcăm înapoi efectuând rotaţiile necesare.\r\n\r\n== code(cpp) |\r\nvoid insert(T* &n, int key, int priority) {\r\n    if (n == nil) {\r\n        n = new T(key, priority, nil, nil);\r\n        return;\r\n    }\r\n    if (key < n->key)\r\n        insert(n->left, key, priority);\r\n    else if (key > n->key)\r\n        insert(n->right, key, priority);\r\n\r\n    balance(n);\r\n}\r\n==\r\n\r\nUn nod poate fi inserat în modul următor:\r\n== code(cpp) |\r\n...\r\ninsert(R, key, rand() + 1); // adăugăm 1 deoarece prioritatea 0 o are doar nodul nil\r\n...\r\n==\r\n\r\nunde $R$ este rădăcina, iar $key$ este cheia de inserat.\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#stergere). Ştergere\r\n\r\nOperaţia de ştergere este inversul operaţiei de inserare. Scopul este să aducem acest nod, fie el $z$, în poziţia unei frunze pentru a-l şterge. Astfel, pentru a menţine cei doi invarianţi (făcând excepţie de $z$) vom alege fiul cu prioritatea mai mare şi îl vom \'$roti$\':treapuri#rotatii în locul lui $z$, cât timp acesta nu este frunză. Atunci când $z$ devine frunză îl vom şterge.\r\n\r\n== code(cpp) |\r\nvoid erase(T* &n, int key) {\r\n    if (n == nil) return;\r\n\r\n    if (key < n->key)\r\n        erase(n->left, key);\r\n    else if (key > n->key)\r\n        erase(n->right, key);\r\n    else {    \r\n        if (n->left == nil && n->right == nil)\r\n            delete n, n = nil;\r\n        else {\r\n            (n->left->priority > n->right->priority) ? rotleft(n) : rotright(n);\r\n            erase(n, key);\r\n        }\r\n    }\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#split). Split\r\n\r\nUneori dorim să despărţim treapul $T$ în două treapuri $T{~<~}$ şi $T{~>~}$ astfel încât cheile din $T{~<~}$ să conţină cheile din $T$ mai mici decât o cheie $key$ dată, iar $T{~>~}$ să conţină cheile din $T$ mai mari decât aceeaşi cheie $key$. Soluţia constă în inserarea unui nod ajutător $z$ a cărui cheie este $key$ şi prioritate $infinit$. După inserare, $z$ va fi rădăcina arborelui, având prioritatea cea mai mare, iar subarborii stâng şi drept ai rădăcănii vor fi exact treapurile căutate. Pe $z$ îl vom şterge, deoarece nu mai avem nevoie de el.\r\n\r\nCostul operaţiei $split$ este egal cu costul operaţiei de \'$inserare$\':treapuri#inserare a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid split(T* &R, T* &Ts, T* &Tg, int key) {\r\n    insert(R, key, infinity);\r\n    Ts = R->left, Tg = R->right;\r\n    delete R, R = nil;\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#join). Join\r\n\r\nOperaţia $join$ constă în unirea a două treapuri $T{~<~}$ şi $T{~>~}$, unde fiecare cheie din $T{~<~}$ este mai mică decât o cheie $key$, iar fiecare cheie din $T{~>~}$ este mai mare decât aceeaşi cheie $key$, într-un singur super-treap. $Join$ se realizează în mod invers operaţiei de $split$ prin crearea unei rădăcini $z$ cu cheia $key$ şi o prioritate aleatoare, ce are ca subarbore stâng pe $T{~<~}$, iar ca subarbore drept pe $T{~>~}$, pe care o vom suprima.\r\n\r\nCostul operaţiei $join$ este egal cu costul operaţiei de \'$ştergere$\':treapuri#stergere a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid join(T* &R, T* Ts, T* Tg, int key) {\r\n    R = new T(key, 0, Ts, Tg);\r\n    erase(R, R->key);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#alte-operatii). Alte operaţii\r\n\r\nStructura de date de treap suportă, pe lângă operaţiile prezentate, şi operaţia de determinare a celei de a $K$-a chei, precum şi determinarea maximului, a minimului, a succesorului sau predecesorului unei chei, sau de tipărire a conţinutului cheilor pe baza relaţiei de ordine stabilite.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nNu întotdeauna $STL$ ne scapă din încurcătură. Nu avem în această bibliotecă o structură de date pentru determinarea celei de a $K$-a chei în timp logaritmic şi nici nu ne putem folosi de structura arborescentă a lui $set$. Exemple grăitoare, în care se foloseşte structura arborescentă a treapurilor, sunt aplicaţiile prezentate mai jos. Cât despre alternative, puteţi face o comparaţie a funcţiilor \'$erase$\':treapuri#stergere sau \'$balance$\':treapuri#rotatii cu cele din articolul următor despre arborii \'$AVL$\':multe-smenuri-de-programare-in-cc-si-nu-numai#AVL.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\n* \'Secv8\':problema/secv8, info{_arena_}\r\n* \'Order\':problema/order, info{_arena_}\r\n* \'Schi\':problema/schi, info{_arena_}\r\n* \'Zeap\':problema/zeap, info{_arena_}\r\n* \'Bile4\':problema/bile4, info{_arena_}\r\n* \'Vmem\':http://campion.edu.ro/problems/3/444/vmem_ro.htm, .campion\r\n* \'Trains\':http://campion.edu.ro/problems/3/432/trains_ro.htm, .campion\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* \'Eternally Confuzzled\':http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_bst2.aspx\r\n* \'Fast Set Operations Using Treaps\':http://www.cs.cmu.edu/afs/cs.cmu.edu/project/scandal/public/papers/treaps-spaa98.pdf, operaţiile \'$split$\':treapuri#split şi \'$join$\':treapuri#join sub altă formă\r\n* \'Treaps and Skip Lists\':http://compgeom.cs.uiuc.edu/~jeffe/teaching/algorithms/notes/06-treaps.pdf\r\n* \'Balanced Search Trees\':http://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15451-s07/www/lecture_notes/lect0208.pdf\r\n',1507,'public',3442,NULL),('probleme-de-acoperire-1','Probleme de acoperire (partea I)','2008-11-14 08:56:52','2009-02-20 00:58:32','h1. Probleme de acoperire (partea I)\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"marius\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 30em}*{text-align:center} *Conţinut*\r\n* \'Problema 1 &#40;Olimpiada de Informatică, Bucureşti, 1995&#41;\':probleme-de-acoperire-1#problema1\r\n* \'Problema 2 &#40;Lot 2001&#41;\':probleme-de-acoperire-1#problema2\r\n* \'Problema 3 &#40;Concursul Naţional de Informatică Lugoj, 1998&#41;\':probleme-de-acoperire-1#problema3\r\n* \'Problema 4\':probleme-de-acoperire-1#problema4\r\n* \'Problema 5\':probleme-de-acoperire-1#problema5\r\n* \'Problema 6 &#40;ONI 2001&#41;\':probleme-de-acoperire-1#problema6\r\n* \'Problema 7 &#40;ACM ICPC 1997&#41;\':probleme-de-acoperire-1#problema7\r\n* \'Problema 8: Floor tiles &#40;Lot matematică 2001&#41;\':probleme-de-acoperire-1#problema8\r\n* \'Problema 9\':probleme-de-acoperire-1#problema9\r\n* \'Concluzii\':probleme-de-acoperire-1#concluzii\r\n* \'Bibliografie\':probleme-de-acoperire-1#bibliografie\r\n\r\nÎn acest prim articol vom prezenta o serie de probleme apărute la concursurile de programare care au o tematică similară, şi anume aceea de acoperire în plan. În general acest tip de probleme sunt $NP-complete$, dar pentru cazurile particulare prezentate, problemele sunt rezolvabile. Cea de-a doua parte a articolului o puteţi găsi în \"$secţiunea următoare...$\":probleme-de-acoperire-2.\r\n\r\nh2(#problema1). Problema 1 (Olimpiada de Informatică, Bucureşti, 1995)\r\n\r\nbq. Se dă un pătrat de latură $2^n^$ care se împarte în pătrate disjuncte de latură $1$. Unul dintre aceste pătrate se elimină. Se cere acoperirea suprafeţei rămase cu piese de forma: \r\n\r\np=. !probleme-de-acoperire-1?OlimpBuc1.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nPrima întrebare care ne vine în minte este dacă aria ce trebuie acoperită este divizibilă cu $3$. Aria este $4^n^ – 1 = (4 – 1)(4^n-1^ + 4^n-2^ + … + 4 + 1)$, deci este multiplu de $3$. Să trecem acum la ideea rezolvării.\r\n\r\nÎmpărţim pătratul în $4$ pătrate de dimensiuni egale. Unul dintre ele are un pătrat lipsă. Facem ca celelalte trei pătrate să aibă şi ele un pătrat lipsă prin plasarea unei piese care să acopere câte un colţ al fiecăruia dintre cele trei pătrate rămase, după cum observăm în figură.\r\n\r\np=. !probleme-de-acoperire-1?OlimpBuc2.jpg!\r\n\r\nAstfel am redus problema la patru noi probleme de dimensiuni mai mici.\r\n\r\np=. !probleme-de-acoperire-1?OlimpBuc3.jpg!\r\n\r\nAcum se vede clar cum, prin metoda $divide et impera$, putem să acoperim întreg pătratul cu piesele cerute.\r\n\r\nh2(#problema2). Problema 2 (Lot 2001)\r\n\r\nbq. Se dă un pătrat de latură $6N + 1$ care se împarte în pătrate disjuncte de latură $1$. Unul dintre aceste pătrate se elimină. Se cere acoperirea suprafeţei rămase cu piese de forma:\r\n\r\np=. !probleme-de-acoperire-1?OlimpBuc1.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nSă vedem întâi cum rezolvăm cazul minim în care $N = 1$.\r\n\r\np=. !probleme-de-acoperire-1?P21.JPG!\r\n\r\nÎn aceste trei figuri am epuizat toate cazurile pentru table de dimensiune $7$ unde lipseşte un pătrat. În fiecare desen am lăsat un pătrat de latură doi liber pentru a trata astfel cele patru cazuri în care pătrăţelul lipsă ar face parte din acest pătrat. Recurgând şi la rotaţiile acestor soluţii acoperim toate cazurile posibile pentru pătrăţelul lipsă. Menţionăm că cele trei soluţii au fost găsite cu uşurinţă de mână de autor.\r\n\r\nSă presupunem că ştim cum să acoperim un pătrat de latură $6N + 1$. Să vedem acum cum acoperim un pătrat de latură $6N + 7$. În acest nou pătrat putem plasa într-un colţ de-al lui un pătrat de latură $6N + 1$, care are un pătrăţel lipsă. Pătratul acesta îl ştim acoperi şi după cum arată şi figura următoare ne mai rămâne să acoperim două dreptunghiuri de dimensiuni $6 &#120; 6n$, respectiv $6n &#120; 6$ şi un pătrat de latură $7$ cu patrăţelul din colţ lipsă. Dreptunghiurile le putem acoperi cu dreptunghiuri de dimensiuni $2 &#120; 3$ formate din câte două piese, iar pătratul de $7 &#120; 7$ cu un colţ lipsă este un caz pentru $N = 1$ al problemei noastre.\r\n\r\np=. !probleme-de-acoperire-1?P22.jpg! \r\n\r\nh2(#problema3). Problema 3 (Concursul Naţional de Informatică Lugoj, 1998)\r\n\r\nbq. Să se acopere complet un pătrat de latură $N &ge; 6$ cu următoarele piese, astfel ca fiecare piesă să fie folosită cel puţin o dată.\r\n\r\np=. !probleme-de-acoperire-1?P31doi.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nObservăm că fiecare piesă este formată din $4$ pătrăţele. De aici deducem că $N^2^$ este multiplu de $4$ deci $N$ e multiplu de $2$. Pentru $N = 6$ avem următoarea soluţie:\r\n\r\np=. !probleme-de-acoperire-1?P32.jpg!\r\n\r\nPentru $N > 6$ putem împărţi pătratul într-un pătrat de latură $6$ şi două dreptunghiuri de dimensiuni $6 x (N – 6)$ şi $(N – 6) x N$, după cum observăm în figura următoare. Dreptunghiurile pot fi acoperite cu piese de tip $3$.\r\n\r\np=. !probleme-de-acoperire-1?P33.jpg!\r\n\r\nh2(#problema4). Problema 4\r\n\r\nbq. Să se determine dacă putem acoperi o tablă de dimensiune $N x N$ cu dominouri după ce îi eliminăm două colţuri opuse.\r\n\r\nh3. Soluţie:\r\n\r\nPrima observaţie pe care o facem este aceea că $N$ trebuie să fie par pentru ca tabla să poată fi acoperită. Este evident pentru cazurile $N = 2$ sau $N = 4$ că problema nu are soluţie, dar pentru cazuri mai mari demonstraţia faptului că există sau nu există soluţie pare dificilă, şi valorile lui $N$ pentru care o abordare exhaustivă a posibilităţilor de acoperire a tablei cu dominouri ar fi eficientă sunt destul de mici. \r\n\r\nO idee interesantă este aceea de a colora pătratele tablei în acelaşi mod în care se colorează o tablă de şah, aşa cum vedem în figura următoare. \r\n\r\np=. !probleme-de-acoperire-1?P41.jpg!\r\n\r\nOrice domino amplasat pe tablă va acoperi două pătrăţele de culori diferite, deci tabla trebuie să aibă un număr egal de pătrăţele colorate alb şi negru, fapt care nu se întâmplă în problema noastră. De aici deducem că nu putem acoperi tabla din care au fost eliminate două colţuri opuse. O problemă ce se poate aborda cu o tehnică asemănătoare este următoarea: „Se dă un dreptunghi de dimensiuni $7 &#120; 10$. Din colţurile lui scoatem câte un pătrat de latură $1$. Să se arate că figura rămasă nu poate fi pardosită cu dreptunghiuri de laturi $3$ şi $1$.” Pentru probleme de acelaşi gen şi soluţia la această problemă puteţi să consultaţi în \'[1]\':probleme-de-acoperire-1#bibliografie secţiunea $1.1 Invariant$, sau în \'[2]\':probleme-de-acoperire-1#bibliografie secţiunea $Probleme de colorare şi acoperire$.\r\n\r\nh2(#problema5). Problema 5\r\n\r\nbq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $2 x N$ cu dominouri.\r\n\r\nh3. Soluţie:\r\n\r\nPentru $N = 1$ avem o posibilitate, pentru $N = 2$ avem două posibilităţi, iar în cazul general daca notăm cu <tex> F[n] </tex> numărul de posibilităţi, avem, aşa cum putem observa şi din figură, <tex> F[n] = F[n - 1] + F[n - 2] </tex>, deci exact şirul lui Fibonacci.\r\n\r\np=. !probleme-de-acoperire-1?P51.jpg!\r\n\r\nh2(#problema6). Problema 6 (ONI 2001)\r\n\r\nbq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $3 x N$ cu dominouri.\r\n\r\nh3. Soluţie:\r\n\r\nŞi în această problemă $N$ trebuie să fie par pentru ca tabla să poată fi acoperită. Avem următoarele posibilităţi la început:\r\n\r\np=. !probleme-de-acoperire-1?P61.jpg!\r\n\r\nObservăm că în ultimele două cazuri pătrăţelul rămas gol poate fi acoperit într-un singur mod de un nou domino, aşa cum ne arată dominoul haşurat. Numim <tex> A[n] </tex> numărul de moduri în care poate fi acoperit un dreptunghi de dimensiune $3 x n$ de dominouri, şi <tex> B[n] </tex> numărul de moduri în care putem acoperi un dreptunghi de $3 x n$ dominouri la care se mai lipeşte pe margine un domino vertical aşa cum vedem în figura următoare.\r\n\r\np=. !probleme-de-acoperire-1?P62.jpg!\r\n\r\nPutem observa uşor că <tex> A[2n + 2] = 3A[2n] + 2B[2n - 2] </tex>, iar <tex> B[2n] = A[2n] + B[2n - 2] </tex>. Aceste două recurenţe ar fi fost de ajuns pentru a rezolva problema în concurs. În cartea \'[3]\':probleme-de-acoperire-1#bibliografie rezolvarea continuă pentru a determina un număr explicit: <tex> A[2n + 2] = 3 A[2n] + 2A[2n - 2] + 2B[2n - 4] </tex> (am înlocuit pe <tex> B[2n - 2] </tex>). Mai departe obţinem <tex> A[2n + 2] = 4 A[2n] - A[2n - 2] </tex>. Putem uşor afla că <tex> A[2] = 3 </tex> şi <tex> A[4] = 11 </tex>. Ecuaţia caracteristică a ecuaţiei liniare este <tex> X^{2} - 4X + 1 = 0 </tex>, iar de aici obţinem că <tex> A[2n] = \\frac{1}{2\\sqrt{3}} * ((\\sqrt{3} + 1) * (2 + \\sqrt{3})^{n} + (\\sqrt{3} - 1) * (2 - \\sqrt{3})^{n}) </tex> (metoda rezolvării recurenţelor liniare este prezentată în manualul de clasa a 11-a de matematică). Un astfel de răspuns nu ne prea ajută pe noi ca programatori pentru că ar trebui să putem efectua operaţii cu numere reale cu o precizie destul de mare pentru a ajunge la rezultatul dorit. Totuşi, faptul că am găsit o recurenţa liniară ne ajută să determinăm mult mai repede numărul de posibilităţi folosindu-ne de următorul raţionament:\r\n\r\nDacă avem o recurenţa <tex> X[n] = aX[n - 1] + bX[n - 2] </tex> atunci:\r\n\r\n<tex>\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\na & b \\\\\r\n1 & 0 \\end{array} \\right)\\]\r\n\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\nX[n - 1] \\\\\r\nX[n - 2] \\end{array} \\right)\\]  </tex>\r\n\r\n<tex> = </tex>\r\n\r\n<tex>\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\nX[n] \\\\\r\nX[n - 1] \\end{array} \\right)\\]  </tex>\r\n\r\n<tex> \\Leftrightarrow </tex>\r\n\r\n<tex>\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\na & b \\\\\r\n1 & 0 \\end{array} \\right)\\]^{(n-1)}\r\n\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\nX[1] \\\\\r\nX[0] \\end{array} \\right)\\]  </tex>\r\n\r\n<tex> = </tex>\r\n\r\n<tex>\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\nX[n] \\\\\r\nX[n - 1] \\end{array} \\right)\\]  </tex>\r\n\r\nIar cum o matrice o putem ridica la o putere în număr logaritmic de paşi, putem afla <tex> X[n] </tex> mult mai repede.\r\n\r\nh2(#problema7). Problema 7 (ACM ICPC 1997)\r\n\r\nbq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $N x M (N &le; 20, M &le; 20)$ cu dominouri.\r\n\r\nh3. Soluţie:\r\n\r\nPoate părea surprinzător, dar pentru această problemă, deşi pare foarte grea, există o formulă: <tex> {2}^{\\frac{M*N}{2}} * \\prod {(\\cos^{2}\\frac{m*pi}{M+1} + cos^{2}\\frac{n*pi}{N+1})}^{\\frac{1}{4}} </tex> pentru <tex>0 < m < M+1</tex>, <tex>0 < n < N+1</tex>. Şi mai surprinzător este că această expresie ce conţine numere iraţionale are ca rezultat un număr întreg. Pentru o demonstraţie a acestei formule puteţi să intraţi pe adresa \'[4]\':probleme-de-acoperire-1#bibliografie. Ar fi anormal să ştim o asemenea formulă pe de rost în speranţa că vom primi problema la vreun concurs. Dimensiunile mici ale problemei o făceau abordabilă printr-un algoritm ce combină $programarea dinamică$ cu $backtracking-ul$ pe care îl vom prezenta în secţiunea următoare.\r\n\r\nh2(#problema8). Problema 8: \'Floor tiles\':http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&Itemid=8&category=18&page=show_problem&problem=1585 (Lot matematică 2001)\r\n\r\nbq. Se dă un dreptunghi de dimensiuni $M x N$, să se determine dacă el se poate acoperi cu piese de forma:\r\n\r\np=. !probleme-de-acoperire-1?OlimpBuc1.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nSă considerăm pe rând:\r\n\r\n* Tablele de $2 x n$ le putem acoperi doar dacă $n$ este multiplu de $3$, pentru că aria dreptunghiului trebuie să fie multiplu de $3$.\r\n* Tablele de $3 x n$ le putem acoperi doar dacă $n$ este par, pentru că suntem obligaţi să acoperim dreptunghiul cu dreptunghiuri verticale de dimensiuni $2 &#120; 3$.\r\n* Tablele de $4 x n$ le putem acoperi doar dacă $n$ este multiplu de $3$, şi putem face acest lucru folosind dreptunghiuri de $2 &#120; 3$.\r\n* Tabla de $5 &#120; 3$ nu poate fi acoperită după cum am văzut la tablele de $3 x n$. \r\n* Tabla de $5 &#120; 6$ poate fi acoperită cu dreptunghiuri de $2 &#120; 3$ aşa cum vedem în figură. \r\n\r\np=. !probleme-de-acoperire-1?P81.jpg!\r\n\r\n* Pentru tabla de $5 &#120; 9$ este uşor să determinăm o acoperire de mână. Una găsită de autor apare în figură. Menţionăm că tabla de $5 &#120; 9$ este cea mai mică tablă de dimensiuni impare pe care o putem acoperi complet. Putem acoperi table de dimensiuni $5 x n$ cand $n$ e multiplu de $3$ şi e diferit de $3$ ({$n = 9 + 6k$} sau $n = 6 + 6k$ unde $k &ge; 0$ deci adăugăm la o soluţie de $5 x (n – 6)$ un dreptunghi de dimensiuni $5 &#120; 6$).\r\n\r\np=. !probleme-de-acoperire-1?P82.jpg!\r\n\r\n* Pentru cazul general $M x N$, presupunem fără a reduce generalitatea că $N$ e multiplu de $3$. Pentru $M &le; 5$ problema e deja rezolvată. Să vedem acum rezolvarea pentru $M > 5$: dacă $M$ e par atunci putem obţine uşor o soluţie folosind dreptunghiuri de dimensiune $2 &#120; 3$, iar dacă $M$ e impar atunci obţinem întâi o soluţie pentru $(M – 2) x N$ la care adăugăm o bandă de dimensiune $2 x N$ formată din dreptunghiuri $2 &#120; 3$.\r\n\r\nh2(#problema9). Problema 9\r\n\r\nbq. Pentru un dreptunghi de dimensiuni $N x M$ să se determine o acoperire cu dominouri a lui astfel încât să nu existe vreo linie verticală sau orizontală care să taie dreptunghiul în două fără să intersecteze vreun domino.\r\n\r\nh3. Soluţie:\r\n\r\nÎn figura următoare avem o soluţie greşită:\r\n\r\np=. !probleme-de-acoperire-1?P91.jpg!\r\n\r\nEste evident că pentru dreptunghiuri de dimensiuni $2 x N$, $3 x N$ şi $4 x N$ nu există soluţie. Pentru $5 &#120; 6$ şi $6 &#120; 8$ este foarte uşor să găsim o soluţie de mână; avem o solutie pentru $5 &#120; 6$ în următoarea figură. Pentru $6 &#120; 6$ nu există soluţie. Pentru aceasta putem folosi o demonstraţie matematică care se găseşte în \'[6]\':probleme-de-acoperire-1#bibliografie sau putem folosi un algoritm de tip $backtracking$ pentru a ne asigura că nu există vreo soluţie.\r\n\r\np=. !probleme-de-acoperire-1?P92.jpg!\r\n\r\nUn dreptunghi de dimensiune $N x M$ îl putem mări la unul de dimensiune $(N + 2) x M$ folosind procedeul prezentat în ultima figură.\r\n\r\np=. !probleme-de-acoperire-1?P93.jpg!\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nAcest articol a pus accentul mai mult asupra gândirii matematice în problemele de acoperire. În \'articolul următor\':probleme-de-acoperire-2 încercăm o abordare orientată spre algoritmică.\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* [1] Mircea Ganga - _Teme şi probleme de matematică_, Ed. Tehnică, Bucureşti, 1991\r\n* [2] Valentin Vornicu - _Olimpiada de matematică - de la provocare la experienţă_, Ed. Gil, 2003\r\n* [3] Ioan Tomescu - _Probleme de combinatorică şi teoria grafurilor_, Ed. Didactică şi Pedagogică, 1981\r\n* [4] \'http://brainyplanet.com/index.php/Count 1x2\':http://brainyplanet.com/index.php/Count%201x2\r\n* [5] _Romanian mathematical competitions 2001_, Ed. Theta, Bucureşti, 2001\r\n* [6] _Probleme de matematică traduse din revista sovietica KVANT_, Ed. Didactică şi Pedagogică, Bucureşti, 1983\r\n',2044,'public',3384,NULL),('probleme-de-acoperire-2','Probleme de acoperire (partea a II-a)','2008-11-15 18:53:30','2009-02-20 00:58:10','h1. Probleme de acoperire (partea a II-a)\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"marius\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 37em}*{text-align:center} *Conţinut:*\r\n* \'Problema 1: MagicBoxes &#40;TopCoder&#41;\':probleme-de-acoperire-2#problema1\r\n* \'Problema 2: Pavement &#40;IOI 2001&#41;\':probleme-de-acoperire-2#problema2\r\n* \'Problema 3 &#40;ACM ICPC 1997&#41;\':probleme-de-acoperire-2#problema3\r\n* \'Problema 4: Hardwood Floor &#40;SGU&#41;\':probleme-de-acoperire-2#problema4\r\n* \'Problema 5: CaseysArt &#40;TopCoder&#41;\':probleme-de-acoperire-2#problema5\r\n* \'Problema 6: Another chocolate maniac &#40;SGU&#41;\':probleme-de-acoperire-2#problema6\r\n* \'Problema 7: Bugs &#40;CEOI 2002&#41;\':probleme-de-acoperire-2#problema7\r\n* \'Problema 8 &#40;Lot 2001, SGU Domino, IPSC 2004, Algoritmus 2005, IOI 2005&#41;\':probleme-de-acoperire-2#problema8\r\n* \'Aplicaţii\':probleme-de-acoperire-2#aplicatii\r\n* \'Bibliografie\':probleme-de-acoperire-2#bibliografie\r\n\r\nSubiectul acestui articol sunt acoperirile in plan, cu o abordare bazată pe tehnici de programare. În \"$...secţiunea precedentă$\":probleme-de-acoperire-1 am studiat problemele de acoperire care nu necesită cunoştinţe avansate de algoritmi.\r\n\r\nh2(#problema1). Problema 1: \'MagicBoxes\':http://www.topcoder.com/stat?c=problem_statement&pm=932 (TopCoder)\r\n\r\nbq. Să se determine numărul $N$ maxim astfel ca într-un dreptunghi de dimensiuni $L x W (1 &le; L, W &le; 30)$ să poată fi dispuse paralel cu axele de coordonate $N$ pătrate de laturi $1, 2, ..., N$ astfel ca oricare două pătrate să nu aibă porţiuni care se suprapun.\r\n\r\nh3. Soluţie:\r\n\r\nAceastă problemă, deşi clasică, este dificil de rezolvat în cazul general şi singura abordare a ei este aceea de a folosi metoda $backtracking$. \r\n\r\nÎntâi putem stabili o limită superioară a numarului $N$: este evident că $N &le; W, N &le; L$ şi că $1^2^ + 2^2^ + ... + N^2^ &le; L x W$. Putem porni cu $N$ de la limita superioară dată de aceste inegalităţi şi să încercăm să dispunem cele $N$ pătrate în interiorul dreptunghiului. O optimizare simplă care ne-ar fi ajutat să rezolvăm problema, precalculând toate rezultatele, ar fi fost să punem în dreptunghi pătratele în ordinea descrescătoare a înălţimii. Altă observaţie ce reduce timpul de execuţie este că piesa cea mai mare nu trebuie pusă în toate poziţiile posibile, ci într-un sfert din ele, din cauza soluţiilor simetrice, iar între ea şi margine nu trebuie lăsat spaţiu puţin pentru că acela va rămâne nefolosit. Observaţia care ne-ar fi dus la o soluţie care să rezolve un test în două secunde, cât era limita de timp în concurs, este că procedura $backtracking$ pierde mult timp pentru verificarea dacă o piesă poate fi pusă pe o anumită poziţie. Dacă în loc de reprezentarea pe matrice folosim $L$ întregi, astfel ca bitul al $j$-lea din întregul $i$ sa fie $1$ dacă celula $(i, j)$ este deja ocupată şi $0$ altfel, vom putea verifica dacă pătratul de latură $i$ poate fi plasat pe o anumită poziţie în $i$ paşi, şi nu în $i^2^$ paşi ca înainte.\r\n\r\nAceastă reprezentare pe biţi este foarte utilă în probleme de acest gen, şi cum avem întregi de $64$ de biţi pe care îi putem folosi, avem o metodă foarte simplă de reprezentare a tablelor de mărime până la $64$.\r\n\r\nh2(#problema2). Problema 2: Pavement (IOI 2001)\r\n\r\nbq. Se dă o matrice de dimensiuni $N x M (1 &le; N &le; 7 şi 1 &le; M &le; 100)$. Unele celule ale acestei matrici sunt distruse şi trebuie acoperite cu piese de forma din $Fig. 1$. Fiecare celulă rămasă neacoperită se consideră o greşeală, iar dacă o piesă cu care am acoperit celule distruse a trebuit să fie tăiată pentru a acoperi numai celule distruse, fiecare pătrăţel din partea nefolosită a piesei este considerată o greşeală. Se cere acoperirea tablei astfel ca numărul de greşeli să fie minimizat. În $Fig. 2$, pentru prima tablă, acoperirea optimă are două greşeli, aşa cum vedem în al doilea desen.\r\n\r\np=. _Fig. 1_ !probleme-de-acoperire-2?P221.jpg!       _Fig. 2_ !probleme-de-acoperire-2?P222.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nAşa cum am zis şi în articolul anterior, problemele de acoperire sunt în general $NP-complete$, deci prima idee ar fi să încercăm o rezolvare prin metoda $backtracking$, dar dimensiunile datelor de intrare ne arată că o asemenea rezolvare nu ne rezolvă problema.\r\n\r\nStrategii polinomiale de tip $greedy$ sau de tip $programare dinamică$ nu vor rezolva această problemă pe toate cazurile de intrare, şi pentru orice strategie se poate găsi câte un contraexemplu. Totuşi vom putea să folosim o rezolvare bazată pe combinarea tehnicilor de $programare dinamică$ şi $backtracking$. Să vedem cum.\r\n\r\nConstruim soluţia optimă coloană cu coloană, dar este evident din următorul exemplu că pentru a construi soluţia optimă pentru coloana $j + 1$ nu este de ajuns să acoperim optim primele $j$ coloane.\r\n\r\np=. !probleme-de-acoperire-2?P223.jpg!\r\n\r\nEvident soluţia optimă pe primele trei coloane ale tablei foloseşte piesa în formă de cruce şi se obţine o acoperire cu $0$ greşeli, dar când vrem să acoperim toate $4$ coloanele tablei folosind prima acoperire obţinem o tablă cu $2$ greşeli, iar folosind două piese de tipul doi orientate înspre stânga, obţinem o acoperire cu o singură greşeală.\r\n\r\nPentru a obţine o soluţie cu $j + 1$ coloane ne trebuie toate soluţiile cu $j$ coloane la care ştim configuraţia coloanelor $j – 1$ şi $j$ (o piesă poate influenţa configuraţia a cel mult trei coloane). De aici se conturează ideea de a folosi un tablou $best$ unde $best[j][config1][config2]$ conţine numărul minim de greşeli astfel încât coloana $j$ are pătratele rămase neacoperite date de mulţimea $config1$, iar coloana $j - 1$ are pătratele neacoperite date de mulţimea $config2$. Pentru a trece de la $j$ la $j + 1$, facem un $backtracking$ pe o tablă de trei coloane dintre care prima are pătrăţelele ocupate date de $config2$, a doua pătrăţelele ocupate date de $config1$, iar a treia nu are nici un pătrăţel ocupat. După ce am plasat în procedura $backtracking$ nişte piese ajungem la configuraţiile pentru coloane date de mulţimile $c1 c2 c3$ şi actualizăm dacă am obţinut un număr mai mic pe $best[j + 1][c3][c2]$. În procedura recursivă ţinem cont atunci când vom acoperi cu piese un pătraţel deja acoperit sau un pătraţel ce nu este stricat. Ambele mulţimi $config1$ şi $config2$ pot fi reprezentate cu biţii unui întreg, $N$ fiind mic, astfel: primii $7$ biţi ai unui întreg vor reprezenta elementele primei mulţimi iar următorii $7$ biţi elementele celei de a două mulţimi. Memoria folosită de algoritmul nostru are ordinul de complexitate $O(M * 4^N^)$, acesta putând fi uşor micşorat la $O(4^N^)$ pentru că la pasul $j + 1$ avem nevoie numai de linia $j$ a matricii. Pentru a reduce numărul de stări folosite ne vom folosi de observaţia că putem să facem o restricţie asupra acoperirilor, aceea că atunci când ajungem la coloana $j$ orice piesă nouă amplasată trebuie să acopere cel puţin un pătrăţel neacoperit de pe coloana $j – 1$. Fie $newBest[j][config12]$ structura care păstrează cele mai bune acoperiri cu această restricţie. Atunci soluţia optimă va fi în $newBest[M + 1]$ unde am considerat o nouă coloană $M + 1$ a tablei ce nu are niciun pătrăţel stricat. Pentru tablele astfel acoperite, configuraţiile ultimelor două pătrăţele de pe o linie sunt de forma: $11$ şi $10$ şi $00$, configuraţia $01$ nu apare pentru că este evident că nu există o piesă care să acopere un pătrat din ultima coloană, un pătrat cu două coloane înainte şi să nu acopere pătratul imediat în stânga pătratului de pe ultima linie. Astfel avem $O(3^N^)$ configuraţii posibile pentru ultimele două coloane. Mai există multe configuraţii de două coloane la care nu se poate ajunge folosind piesele din problemă, dar o analiză exactă ar fi dificilă şi probabil ar complica inutil implementarea. Să vedem cum arată configuraţiile pe un exemplu:\r\n\r\np=. !probleme-de-acoperire-2?P224.jpg!\r\n\r\nPutem reprezenta această acoperire astfel:\r\n\r\np=. **00010**\r\n**01110**\r\n**11110**\r\n**00011**\r\n\r\nIar ultimele două coloane arată în felul următor:\r\n\r\np=. **10**\r\n**10**\r\n**10**\r\n**10**\r\n**11**\r\n\r\nÎn acest caz $config$ are valoarea $1 * 3^0^ + 1 * 3^1^ + 1 * 3^2^ + 1 * 3^3^ + 2 * 3^4^ = 202$. Acum, la fiecare pas vrem să punem pe coloana $j – 1$ câte o piesă pentru a obţine rezultatele pentru $newBest[j + 1]$, sau să nu punem o piesă acolo. Avem $9$ posibilităţi de a pune piese (fiecare rotaţie şi reflexie a pieselor din problemă) şi posibilitatea de a nu pune piesă în pătrăţelul curent, deci în total $10$ posibilităţi. Astfel, complexitatea algoritmului nostru devine $O(M * 3^N^ * 10^N^)$, dar constanta din faţă este subunitară (mult mai mică decât 1) din cauză că nu vom trece prin stări imposibile.\r\n\r\nh2(#problema3). Problema 3 (ACM ICPC 1997)\r\n\r\nbq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $N x M (N &le; 15, M &le; 15)$ cu dominouri.\r\n\r\nh3. Soluţie:\r\n\r\nAm văzut în \'partea I a articolului\':probleme-de-acoperire-1 că există o formulă pentru acest număr. Abordarea matematică poate fi generalizată şi pentru mai multe probleme asemănătoare de acoperire, dar cunoştinţele necesare sunt avansate, deci această abordare nu ne prea ajută pe noi ca informaticieni.\r\n\r\nO soluţie care ne va da numărul exact şi ar fi putut fi folosită în concurs este asemănătoare celei expuse mai sus. Vom folosi o combinaţie a metodei $backtracking$ cu metoda $programării dinamice$. Tabloul $numWays[i][config]$ va fi numărul de posibilităţi de a acoperi complet primele $i - 1$ coloane ale unei table, iar pe coloana $i$ pătratele ocupate să fie reprezentate de $config$. Astfel, $numWays[i + 1][config1]$ va fi egal cu suma de $numWays[i][config]$, unde putem acoperi cu dominouri două coloane astfel ca pe prima coloană să fie acoperite toate celulele, în afara celor date de $config$, iar pe a doua coloană să fie acoperite celulele date de $config1$. De exemplu, starea dată de $(4, 100100)$ este prezentată în următoarea figură:\r\n\r\np=. !probleme-de-acoperire-2?P231.jpg!\r\n\r\nDacă algoritmul pune trei dominouri pe liniile $4$ şi $5$ aşa cum vedem mai sus, atunci vom trece în starea $(5, 011000)$. La final, vom returna valoarea aflată în $numWays[N + 1][&#48;]$. Complexitatea ca timp a acestei rezolvări este $O(M * 4^N^)$, iar ca spaţiu $O(2^N^)$.\r\n\r\nh2(#problema4). Problema 4: \'Hardwood Floor\':http://acm.sgu.ru/problem.php?contest=0&problem=131 (SGU)\r\n\r\nbq. Determinaţi numărul de acoperiri ale unei table de dimensiuni $N x M (1&le; N &le; 9, 1 &le; M &le; 9)$ cu piese de tipul:\r\n\r\np=. !probleme-de-acoperire-2?P241b.jpg!\r\n\r\nExemplu: Pentru $N = 3$ şi $M = 2$ avem $5$ acoperiri posibile.\r\n\r\nh3. Soluţie:\r\n\r\nÎn rezolvare putem folosi direct ideea de la problema anterioară.\r\n\r\nh2(#problema5). Problema 5: \'CaseysArt\':http://www.topcoder.com/stat?c=problem_statement&pm=1706 (TopCoder)\r\n\r\nbq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $N x M (N &le; 18, M &le; 15)$ cu piese de forma:\r\n\r\np=. !probleme-de-acoperire-2?P251.jpg!\r\n\r\nDe exemplu, pentru $N = 3, M = 4$ avem următoarele acoperiri:\r\n\r\np=. !probleme-de-acoperire-2?P252.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nDin nou, ideea de rezolvare este cea prezentată în \'$Problema 2$\':probleme-de-acoperire-2#problema2. Complexitatea soluţiei este $O(N * 4^M^)$, dar trebuie să fim conştienţi că aceasta este o limită superioară mult mai mare decât complexitatea reală. Să vedem şi implementarea unei asemenea soluţii:\r\n\r\n== code(java) |\r\nimport java.util.*;\r\n\r\npublic class CaseysArt {\r\n    double[][] num;\r\n    int step, w;\r\n    int[][][] p = {{{0, 1}, {1, 1}},\r\n        {{1, 0},{1, 1}},\r\n        {{1, 1},{0, 1}},\r\n        {{1, 1},{1, 0}}};\r\n    int[][] sol;\r\n\r\n    void checksol() {\r\n        int config = 0, config1 = 0;\r\n        for (int i = 0; i < w; i++) {\r\n            if (sol[i][0] == 0) config |= (1 << i);\r\n            if (sol[i][1] == 1) config1 |= (1 << i);\r\n        }\r\n        num[1 ^ step][config1] += num[step][config];\r\n    }\r\n\r\n    void doit(int x) {\r\n        if (x == w)\r\n            checksol();\r\n        else {\r\n            if (x < w - 1) {\r\n                int i, j, k;\r\n                boolean bool;\r\n\r\n                for (k = 0; k < 4; k++) {\r\n                    bool = true;\r\n                    for (i = 0; i < 2; i++) {\r\n                        for (j = 0; j < 2; j++) {\r\n                            if (p[k][i][j] == 1)\r\n                                bool = bool && (sol[x + i][j] == 0);\r\n                        }\r\n                    }\r\n\r\n                    if (bool) {\r\n                        for (i = 0; i < 2; i++) {\r\n                            for (j = 0; j < 2; j++) {\r\n                                if (p[k][i][j] == 1)\r\n                                    sol[x + i][j] = 1;\r\n                            }\r\n                        }\r\n                        doit(x + 1);\r\n                        for (i = 0; i < 2; i++) {\r\n                            for (j = 0; j < 2; j++) {\r\n                                if (p[k][i][j] == 1)\r\n                                    sol[x + i][j]=0;\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            doit(x+1);\r\n        }\r\n    }\r\n\r\n    public double howManyWays(int l, int w) {\r\n        num = new double[2][1 << w];\r\n        this.w = w;\r\n        num[0][0] = 1;\r\n        step = 0;\r\n        sol = new int[w][2];\r\n        for (int i = 1; i < l; i++) {\r\n            Arrays.fill(num[1 ^ step], 0);\r\n            doit(0);\r\n            step ^= 1;\r\n        }\r\n        return num[step][(1 << w) - 1];\r\n    }\r\n}\r\n==\r\n\r\nÎn $num[i][config]$ ţinem minte câte posibilităţi sunt să acoperim $i - 1$ linii cu piesele date în problemă, iar linia $i$ să fie ocupată aşa cum arată reprezentarea în baza $2$ a numărului întreg $config$. Se observă folosirea variabilei $step$ care de la un pas la altul se transformă astfel: $step &#94;= 1$. Acest mic truc ne face să putem folosi o matrice de doar $2$ linii în loc să folosim $N$ linii. La momentul $i$, în $num[step][config]$ avem informaţia ce ar fi fost în mod normal în $num[i][config]$, iar în $num[1 &#94; step][config1]$ vom calcula ce ar fi fost normal în $num[i + 1][config1]$. În şirul $p$ ţinem minte forma pieselor din problemă.\r\n\r\nÎn procedura $doit$ punem pe două linii consecutive piese în toate modurile posibile. Această procedură face ca pe prima linie să avem o configuraţie de pătrăţele libere $config$, iar pe a doua o configuraţie de pătrăţele ocupate $config1$. Dacă pătrăţelele reprezentate de $config$ nu au fost ocupate la pasul curent ele trebuie să fi fost ocupate la pasul anterior. Astfel, pentru fiecare pereche de configuraţii $config$ şi $config1$ trebuie să efectuăm operaţia $num[i + 1][config1] += num[i][config]$.\r\n\r\nDacă această rezolvare ar fi fost folosită în timpul concursului, ea ar fi ieşit din timp. Pentru optimizare putem face mai multe îmbunătăţiri. Un exemplu ar fi să generăm direct cele două configuraţii de biţi în procedura $backtracking$ şi să nu mai folosim şirul $sol$. O altă idee care ar fi dus la rezolvarea problemei în timpul concursului ar fi fost calcularea tuturor rezultatelor posibile şi trimiterea unei soluţii care returna aceste rezultate precalculate. Această abordare ar fi fost posibilă pentru că numărul de configuraţii iniţiale este mic.\r\n\r\nh2(#problema6). Problema 6: \'Another chocolate maniac\':http://acm.sgu.ru/problem.php?contest=0&problem=132 (SGU)\r\n\r\nbq. Se dă o tablă de dimensiuni $M x N (1 &le; M &le; 70, 1 &le; N &le; 7)$ cu unele pătrate lipsă. Se cere numărul minim de dominouri ce pot fi plasate pe tablă fară să se suprapună între ele sau să acopere vreun pătrat ce nu aparţine tablei, astfel ca nici o altă piesă de domino să nu se poată adăuga la configuraţie fără ca aceasta să se suprapună peste una veche. Pentru tabla următoare vedem uşor în a doua figură că soluţia optimă va conţine 4 dominouri.\r\n\r\np=. !probleme-de-acoperire-2?P261.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nDin nou vom folosi $metoda programării dinamice$ îmbinată cu metoda $backtracking$. \r\n\r\nVom umple tabla linie cu linie şi la fiecare pas putem pune dominouri orizontale pe linia curentă şi verticale pe linia curentă şi linia următoare. Trebuie să fim atenţi când trecem de la linia curentă la următoarea să nu lăsăm pe linia curentă loc liber unde poate fi amplasat un domino orizontal, pentru că acest loc nu va putea fi ocupat de piese amplasate mai târziu. Se poate lăsa spaţiu gol pe linia curentă şi linia următoare pentru că o celulă a acestei poziţii va putea fi acoperită la pasul următor. Vedem astfel că dacă linia curentă este linia $i$ atunci avem trei stări posibile pentru ultimele două pătrăţele de pe fiecare coloană: $00$ (celule neocupate), $10$ (penultima celulă ocupată şi ultima goală), $11$ (ambele celule ocupate de dominouri). Starea $01$ nu poate exista. În procedura $backtracking$ care generează configuraţiile la care putem ajunge de la o configuraţie dată trebuie să mai avem grijă să nu ocupăm cu un domino o celulă ce nu aparţine tablei. Astfel, pentru a găsi soluţia problemei vom folosi un tablou $min[i][config]$ care va păstra numărul minim de dominouri care trebuie amplasate pe tablă astfel ca pe liniile $1, 2, ..., i - 1$ să nu poată fi amplasat vreun domino pe celulele rămase goale, iar $config$ va fi un număr întreg care atunci când e transformat în baza $3$ arată configuraţia liniilor $i - 1$ şi $i$.\r\n\r\nLa fiecare pas, procedura $backtracking$ alege dacă să pună un domino orizontal, unul vertical sau să treacă mai departe, deci o limită superioară ar fi $O(3^M^)$ operaţii (nu toate configuraţiile vor fi posibile). În tablou avem $N x 3^M^$ stări, deci complexitatea algoritmului este $O(N * 9^M^)$. Menţionăm din nou că aceasta este o limită superioară şi că algoritmul se va comporta mult mai bine în practică.\r\n\r\nh2(#problema7). Problema 7: \'Bugs\':http://acm.pku.edu.cn/JudgeOnline/problem?id=1038 (CEOI 2002)\r\n\r\nbq. Să se acopere o tablă de dimensiuni $M x N (1 &le; M &le; 10, 1 &le; N &le; 150)$ cu un număr maxim de piese de dimensiuni $3 x 2$ şi $2 x 3$. Tabla are unele celule ce trebuie să nu fie acoperite, iar oricare două piese nu se pot suprapune. Pentru tabla de mai jos, numărul maxim de piese cu care se poate acoperi este $3$.\r\n\r\np=. !probleme-de-acoperire-2?P272.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nEvident, putem încerca o soluţie identică cu cea a \'$Problemei 1$\':probleme-de-acoperire-2#problema1, dar aici limitele sunt puţin mai mari şi avem nevoie de un algoritm mai eficient.\r\n\r\nExistă o rezolvare de complexitate $O(N * M * 3^M^)$ care, aşa cum deja v-aţi obişnuit, combină metoda $backtracking$ cu metoda $programării dinamice$. Folosim un tablou $max[N][M + 1][3^(M + 1)^]$ care conţine numărul maxim de dale puse pentru o anumită stare. Fiecare element al matricii va fi iniţial egal cu $0$. Iterăm rândurile în ordinea $1 ... N$, coloanele în ordinea $1 ... M$ şi configuraţiile în ordine lexicografică. Când vom procesa starea reprezentată de parametrii $(i, j, config)$ vom decide dacă punem una dintre piese cu colţul din stânga sus în $(i, j)$ sau dacă lăsăm celula $(i, j)$ liberă. O stare $(i, j, config)$ se referă la un pătrăţel din matrice şi la o bandă „activă” de pătrăţele ce are lăţimea $2$. Banda conţine celulele $(i1, j + 1), (i1, j + 2)$ pentru $i1 < i$ şi celulele $(i2, j), (i2, j + 1)$ pentru $i &le; i2$. Cifrele în baza $3$ ale parametrului $config$ ne spun starea perechilor de pătrate de pe banda activă: $00$ este reprezentat în $config$ de cifra $0$, $10$ de cifra $1$ şi $11$ de cifra $2$ (configuraţia $01$ nu poate apărea). De exemplu, starea $(4, 3, 1000212)$ va reprezenta configuraţia prezentată în următoarea imagine (ultima cifră corespunde primei perechi de pătrăţele, penultima cifră celei de-a doua perechi ş.a.m.d.):\r\n\r\np=. !probleme-de-acoperire-2?P273.jpg!\r\n\r\nDacă decidem să nu punem piesă în pătrăţelul $(4, 3)$ atunci din starea $(4, 3, 1000212)$ trecem în starea $(5, 3, 1000212)$.\r\n\r\np=. !probleme-de-acoperire-2?P274.jpg!\r\n\r\nDacă punem o piesă verticală ajungem în starea $(7, 3, 1111212)$.\r\n\r\np=. !probleme-de-acoperire-2?P275.jpg!\r\n\r\nIar dacă punem o piesă orizontală atunci ajungem în starea $(6, 3, 1022212)$.\r\n\r\np=. !probleme-de-acoperire-2?P276.jpg!\r\n\r\nTablei îi adăugăm la sfârşit o coloană pe care nu pot fi aşezate piese. Rezultatul cerut de problemă se va afla în $max[N][M + 1][&#48;]$. Menţionăm că problemele \'$2$\':probleme-de-acoperire-2#problema2, \'$3$\':probleme-de-acoperire-2#problema3 şi \'$4$\':probleme-de-acoperire-2#problema4 pot fi rezolvate în mod asemănător în complexitate $O(N * M * 2^M^)$.\r\n\r\nh2(#problema8). Problema 8 (Lot 2001, \'SGU Domino\':http://acm.sgu.ru/problem.php?contest=0&problem=101, \'IPSC 2004\':http://ipsc.ksp.sk/contests/ipsc2004/practice/problems/t.php, Algoritmus 2005, IOI 2005)\r\n\r\nbq. Se dă o tablă de dimensiuni $N x M$, din care unele pătrate sunt eliminate. Se cere să se determine o acoperire a tablei cu număr maxim de dominouri $(1 &le; N, M &le; 200)$. De exemplu, o tablă ce nu are nicio celulă eliminată, de $3 x 3$ pătrăţele, poate fi acoperită cu cel mult $4$ dominouri care nu se suprapun. O soluţie posibilă este prezentată în a doua figură.\r\n\r\np=. !probleme-de-acoperire-2?P281.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nAceasta este o problemă celebră, sau aşa se pare după numărul de concursuri în care a fost folosită, şi este o generalizare a unei probleme din \'articolul precedent\':probleme-de-acoperire-1.\r\n\r\nPrima idee ar fi să încercăm o abordare $greedy$ şi să punem piese pe tablă într-o ordine oarecare cât timp mai este loc. Dar putem găsi uşor contraexemple pentru acest tip de abordare. Limitele sunt mult prea mari pentru ca o rezolvare bazată pe $programare dinamică$ combinată cu $backtracking$ să meargă. O idee ce am utilizat-o în articolul anterior ne va fi folositoare şi aici. Colorăm tabla noastră în mod asemănător unei table de şah şi numerotăm pătrăţelele tablei.\r\n\r\np=. !probleme-de-acoperire-2?P282.jpg!\r\n\r\nAcum vedem că un domino amplasat pe tablă trebuie să ocupe o celulă colorată alb şi una negru, celule care sunt adiacente. Dacă realizăm un graf în care nodurile sunt celulele, iar între două noduri există muchie dacă ele sunt adiacente vertical sau orizontal pe tablă, observăm că graful este bipartit. O acoperire cu dominouri corespunde în acest graf unei mulţimi de muchii pentru care nu există două muchii cu acelaşi capăt (o muchie corespunde amplasării posibile a unui domino, iar restricţia menţionată face să nu existe dominouri care se suprapun). Deci pentru a găsi o soluţie maximală pentru problema iniţială, trebuie să găsim o mulţime de muchii neadiacente de cardinal maxim. În acest mod am transformat cerinţa într-o problemă clasică de teoria grafurilor cunoscută sub numele de $cuplaj maxim într-un graf bipartit$. Vedem în imaginea următoare cum a fost transformată tabla într-un graf şi cum soluţia prezentată în exemplu corespunde unui $cuplaj maxim$ în graful asociat tablei.\r\n\r\np=. !probleme-de-acoperire-2?P283.jpg!\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\n* \'Pavare\':problema/pavare, info{_arena_}\r\n* \'Choco\':problema/choco, info{_arena_}\r\n* \'Little Kings\':http://acm.sgu.ru/problem.php?contest=0&problem=223, SGU\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* [1] \"IOI\'01 Competition\":http://olympiads.win.tue.nl/ioi/ioi2001/contest/A-2001-7.pdf\r\n* [2] \"CEOI\'02 Competition material\":http://ics.upjs.sk/ceoi/\r\n* [3] \'SGU\':http://acm.sgu.ru\r\n* [4] \'TopCoder\':http://www.topcoder.com/tc\r\n',2044,'public',3384,NULL),('stl','Standard Template Library (STL)','2004-12-05 00:00:00','2009-02-19 23:59:44','h1. Standard Template Library (STL)\r\n\r\n(Categoria _Limbaje de programare_, Autor _Radu Grigore_)\r\n\r\n(toc){width: 15em}*{text-align:center;} *Continut*\r\n* \'Introducere\':stl#introducere\r\n* \'Containeri\':stl#containeri\r\n* \'Iteratori\':stl#iteratori\r\n* \'Algoritmi\':stl#algoritmi\r\n* \'Concluzie si referinte\':stl#concluzie\r\n\r\nBiblioteca standard C++ are trei mari componente: biblioteca de functii C, cea de stream-uri de intrare / iesire si Standard Template Library (STL). Acest articol prezinta un subset al STL pe care il folosesc adesea in practica.\r\n\r\nh2(#introducere). Introducere\r\n\r\nSTL se bazeaza pe trei concepte centrale: containeri, iteratori si algoritmi. Ca tehnica de programare folosita, e bine sa stiti ca orientarea pe obiecte aproape ca lipseste. In schimb se utilizeaza din plin polimorfismul parametric. In C++ numele acestuia este \"template\"; in C# si Java se obisnuieste sa se spuna \"generice\".\r\n\r\nIn continuare voi presupune ca sunteti familiari cu utilizarea template-urilor si cunoasteti bine limbajul C. Codul folosit presupune ca la inceputul fisierului sa existe:\r\n\r\n== code(cpp) |\r\n#include <vector>\r\n#include <list>\r\n#include <map>\r\n#include <set>\r\n#include <queue>\r\n#include <deque>\r\n#include <string>\r\n#include <algorithm>\r\n#include <iterator>\r\n#include <iostream>\r\n#include <cassert>\r\nusing namespace std;\r\n==\r\n\r\nh2(#containeri). Containeri\r\n\r\nIn limbajul de baza avem la dispozitie tablourile pentru reprezentarea unei secvente indexate de elemente. Dimensiunea unui tablou trebuie fie sa fie cunoscuta la compilare, fie sa fie gestionata explicit de programator prin alocare dinamica. Principalul avantaj al STL este ca ne scapa de aceasta grija. In afara de adresarea indexata obisnuita, secventele STL au si operatia {$push_back$}: adauga un element la sfarsit (si, evident, creste dimensiunea cu {$1$}). Exista si operatia inversa {$pop_back$}: elimina ultimul element. Cele trei secvente STL care suporta aceste operatii sunt $vector$, $deque$ si $list$. Un exemplu de utilizare este:\r\n\r\n== code(cpp) |\r\n// v are 10 elemente egale cu 0\r\nvector <int> v(10);\r\n// acces indexat\r\nv[1] = 2;\r\ncout << v[0] << endl;\r\nv.push_back(3);\r\ncout << v[10] << endl;\r\nv.pop_back();\r\n==\r\n\r\nCele trei secvente difera prin implementare. Pe scurt, $vector$ tine datele intr-o zona continua de memorie, $list$ este o lista dublu inlantuita a elementelor, iar $deque$ este ceva intre: o lista inlantuita de pachete continue (deque vine de la \"double ended queue\", dar se pronunta \"deck\" = \"pachet\", tocmai pentru a sugera implementarea).\r\n\r\nEste util sa stim in mare care e implementarea pentru a alege secventa potrivita in functie de operatiile pe care le avem de facut si de frecventa lor. De exemplu $vector$ are cel mai rapid acces indexat; pe de alta parte adaugarea unui element poate duce la copierea intregului continut daca nu mai exista memorie rezervata la coada (adica {$v.capacity() == v.size()$}). Lista este rapida pentru inserari de elemente in interior, dar este lenta pentru accesul la acestea. $Deque$ este mai eficienta decat $vector$ daca se fac multe operatii $push_back$ dar este ceva mai lenta pentru accese indexate uzuale. In plus mai exista si o diferenta de interfata. Atat $deque$, cat si $list$ ofera fata de $vector$ operatiile {$push_front$} si {$pop_front$}. Aceasta deoarece in cazul vectorilor, ele ar fi avut complexitatea $O(N)$ daca se dorea pastrarea rapiditatii accesului indexat.\r\n\r\nSa vedem o implementare \"de jucarie\" a unei cozi cu ajutorul $deque$ pentru a mai ilustra cateva functii membre.\r\n\r\n== code(cpp) |\r\ntemplate <typename T>\r\nclass Queue {\r\n    private:\r\n        deque <T> data;\r\n    public:\r\n        void Push(const T& el) {\r\n            data.push_back(el);\r\n        }\r\n        T Pop() {\r\n            assert(!data.empty());\r\n            T result(data.front());\r\n            data.pop_front();\r\n            return result;\r\n        }\r\n};\r\n==\r\n\r\nInteresant este ca STL are deja astfel de adaptori ale secventelor simple: {$stack$}, {$queue$} si {$priority_queue$}. Metodele uzuale sunt {$pop$}, {$push$} si {$top$}; $push$ si $pop$ au semantica uzuala, iar $top$ intoarce o referinta la elementul care va fi inlaturat de urmatorul {$pop$}. In plus, se mai poate testa daca containerul e gol cu {$empty$}. Voi da un exemplu de utilizare a {$priority_queue$}:\r\n\r\n== code(cpp) |\r\npriority_queue <int> pq;\r\npq.push(3);\r\npq.push(4);\r\npq.push(1);\r\n\r\ncout << pq.top() << endl; pq.pop(); // afiseaza 4\r\ncout << pq.top() << endl; pq.pop(); // afiseaza 3\r\ncout << pq.top() << endl; pq.pop(); // afiseaza 1\r\ncout << pq.empty() << endl; // afiseaza 1 (= true)\r\n==\r\n\r\nDesigur, putem redefini operatorul \"mai mic\" daca dorim o ordonare diferita. De exemplu putem afla cel mai apropiat punct de ({$0, 0, 0$}) astfel:\r\n\r\n== code(cpp) |\r\nstruct Point {\r\n    int x, y, z;\r\n    bool operator < (const Point& o) const {\r\n        return x * x + y * y + z * z > o.x * o.x + o.y * o.y + o.z * o.z;\r\n    }\r\n};\r\n\r\npriority_queue <Point> pq;\r\n==\r\n\r\nIntrucat operatiunile de extindere / micsorare la capete sunt uzuale pentru adaptorii stack / queue, acestia folosesc in mod obisnuit drept container un deque. Iar o coada de prioritati este implementata cu heap-uri asa incat rapiditatea accesului indexat este importanta si vector-ul este alegerea default. Aceste alegeri pot fi insa configurate. De exemplu daca aveti o coada de prioritati in care stiti ca veti introduce foarte multe elemente si veti extrage doar cateva ar fi poate mai bine sa folositi:\r\n\r\n== code(cpp) |\r\npriority_queue < int, deque <int> > pq;\r\n==\r\n\r\nCam atat despre secvente. Celalalt tip important de containeri sunt containerii asociativi: $map$ si $set$ (mai exista $multimap$ si $multiset$ dar nu vom vorbi despre ei). Primul este o multime de perechi $(cheie, valoare)$ ce pot fi regasite rapid dupa $cheie$, care este unica. Implementarea este cu arbori rosu-negru, asa incat timpul de inserare si cel de cautare este {$O(logN)$}. O utilizare tipica pentru $map$ este:\r\n\r\n== code(cpp) |\r\nmap <string, int> name_to_phone;\r\nname_to_phone[\"Ion Ion\"] = 8234783;\r\nname_to_phone[\"Me\"] = 8237462;\r\ncout << name_to_phone[\"Ion Ion\"] << endl;\r\n==\r\n\r\nPentru un set, utilizarea uzuala este:\r\n\r\n== code(cpp) |\r\nset <string> s;\r\ns.insert(\"Ion ion\");\r\ns.insert(\"baubau\");\r\ncout << (s.find(\"Gica\") != s.end()) << endl; // afiseaza 0 = false\r\ncout << (s.find(\"baubau\") != s.end()) << endl; // afiseaza 1 = true\r\n==\r\n\r\nPentru a se putea construi un arbore de cautare pentru chei de tipul $T$, atat $set$ cat si $map$ necesita ca $less <T>$ sa fie bine definit. Daca nu oferiti voi o specializare a template-ului, cea generica apeleaza operatorul {$<$}. Cu alte cuvinte, cu exceptia unor situatii deosebite ce probabil nu apar intr-un concurs, e bine de retinut ca trebuie sa fie definit operatorul {$<$}.\r\n\r\nUn map este foarte util pentru a memoiza o functie recursiva.\r\n\r\n== code(cpp) |\r\nU my_func(T t) {\r\n    // e recursiva si pura (rezultatul depinde doar de parametri)\r\n    return result;\r\n}\r\n==\r\n\r\nSe transforma in:\r\n\r\n== code(cpp) |\r\nmap <T, U> cache;\r\n\r\nU my_func(T t) {\r\n    map <T, U> :: const_iterator it = cache.find(t);\r\n    if(it != cache.end())\r\n        return it->second;\r\n    // corpul vechi\r\n    return cache[t] = result;\r\n}\r\n==\r\n\r\nTransformarea e automata si se face foarte usor. In multe cazuri, plusul de viteza este suficient si nu e nevoie ca tot codul sa fie transformat in varianta cu programare dinamica. In plus solutia de mai sus merge si atunci cand $t$ poate avea valori foarte mari sau nu este un intreg (de exemplu e o structura, un string etc.) si trecerea la programare dinamica n-ar fi evidenta si ar lua ceva timp de gasit o solutie.\r\n\r\nh2(#iteratori). Iteratori\r\n\r\nGanditi-va la algoritmul de gasire a maximului. El nu depinde de implementarea folosita pentru reprezentarea multimii! Tot ceea ce trebuie sa faci este sa accesezi toate elementele... nici macar nu conteaza ordinea. Ei bine, iteratorii permit o astfel de decuplare a structurilor de date de algoritmi.\r\n\r\nExemplu:\r\n\r\n== code(cpp) |\r\ntemplate <typename T>\r\ntypename T::value_type max(typename T::const_iterator begin, typename T::const_iterator end) {\r\n    assert(begin != end); // container vid\r\n    typename T::const_iterator it;\r\n    typename T::value_type r = *begin;\r\n    for(it = begin; it != end; ++it)\r\n        if(*it > r)\r\n            r = *it;\r\n    return r;\r\n}\r\n==\r\n\r\nObservati ca sintaxa pentru iteratori seamana mult cu sintaxa pentru pointeri. Iteratorii din C++ sunt analogul enumeratorilor din C# si Java, doar ca sunt mai flexibili. Operatile care se pot face cu ei sunt: \"treci la urmatorul element\" {$(++it)$}, \"treci la elementul anterior\" {$(--it)$}, \"da-mi o referinta la elementul catre care arati\" $(*it)$ si compararea ({$it_a == it_b$}, {$it_a != it_b$}). Unii iteratori pot, in plus, sa se deplaseze cu $n$ pozitii ({$it += n$}, {$it -= n$}).\r\n\r\nCodul de mai sus poate fi utilizat pentru oricare dintre cele trei secvente prezentate anterior astfel:\r\n\r\n== code(cpp) |\r\ndeque <int> d;\r\nvector <int> v;\r\n// ... prelucrari ...\r\ncout << max(d.begin(), d.end()) << endl;\r\ncout << max(v.begin(), v.end()) << endl;\r\n==\r\n\r\nh2(#algoritmi). Algoritmi\r\n\r\nDupa cum vedeti, utilizarea functiei $max$ este simpla, mai complicata este definitia. Din fericire header-ul $&lt;algorithm&gt;$ are deja scrise tot felul de astfel de functii dragute. Una de care s-ar putea sa va indragostiti :) este {$next_permutation$}. Ea primeste ca parametri limitele unei secvente (ca mai sus) si transforma acea secventa in urmatoarea permutare in ordine lexicografica si intoarce $true$, sau intoarce $false$ daca ordonarea este deja ultima. Iata cum se foloseste:\r\n\r\n== code(cpp) |\r\nstring handle(\"rgrig\");\r\nsort(handle.begin(), handle.end()); // alta functie folositoare\r\ndo {\r\n    cout << handle << endl;\r\n} while(next_permutation(handle.begin(), handle.end()));\r\n==\r\n\r\nCodul de mai sus ilustreaza o alta functie utila: {$sort$}. In exemplul urmator vom vedea cum poate fi folosita $next_permutation$ pentru a genera toate combinarile de $n$ elemente luate cate {$k$}.\r\n\r\n== code(cpp) |\r\nvector <int> choose(n);\r\nfor(int i = n - k; i < n; ++i)\r\n    choose[i] = 1;\r\ndo {\r\n    // ... foloseste choose ...\r\n} while(next_permutation(choose.begin(), choose.end()));\r\n==\r\n\r\nAm utilizat un vector de intregi si nu unul de booleeni asa cum ar dicta \"spiritul\" C++ pentru ca secventa $vector$ are o specializare pentru tipul $bool$ si impacheteaza cate $32$ de elemente intr-un intreg nativ. Acest lucru are tot felul de efecte neplacute, printre care scaderea vitezei. Exista si un efect \"placut\", dar util probabil in conjuncturi speciale: ocupa mai putin spatiu.\r\n\r\nO alta functie interesanta este {$copy$}. Pe aceasta o putem folosi pentru a concatena doua secvente sau pentru a tipari continutul unei secvente.\r\n\r\n== code(cpp) |\r\nvector <int> a, b;\r\n// ... pune niste valori in a si b ...\r\n\r\n// pune tot continutul lui b la sfarsitul lui a\r\ncopy(b.begin(), b.end(), back_inserter(a));\r\n\r\n// tipareste continutul lui a\r\ncopy(a.begin(), a.end(), ostream_iterator <int> (cout, \", \"));\r\n==\r\n\r\nO functie utila pentru prelucrarea sirurilor inainte de parsare este {$replace$}. De exemplu, pentru a inlocui toate virgulele cu spatii intr-un sir se procedeaza astfel:\r\n\r\n== code(cpp) |\r\nstring s(\"a,b,c,d\");\r\nreplace(s.begin(), s.end(), \',\', \' \');\r\n==\r\n\r\nDaca doriti sa cautati o subsecventa intr-o secventa mai mare atunci puteti folosi {$search$}. Acesta intoarce un iterator care pointeaza la locul unde s-a gasit subsecventa sau $end$, in caz ca nu s-a gasit. De exemplu, pentru a gasi toate aparitiile unui cuvant intr-un sir putem scrie:\r\n\r\n== code(cpp) |\r\n// un deque e mai eficient decat un string pentru texte lungi\r\ndeque <char> text;\r\nstring word;\r\n// ... pune niste valori in text si word ...\r\ndeque <char> :: iterator it = text.begin();\r\nint c = 0;\r\nwhile((it = search(it, text.end(), word.begin(), word.end())) != text.end()) {\r\n    ++c; ++it;\r\n}\r\n// c contine numarul de aparitii ale cuvintului in text, numarand si aparitii care se suprapun\r\n==\r\n\r\nAtentie: complexitatea functiei $search$ este $O(M * N)$ asa incat uneori e prea lenta.\r\n\r\nPentru a numara de cate ori apare un element intr-o secventa putem utiliza functia {$count$}.\r\n\r\n== code(cpp) |\r\nint av[] = {1, 2, 3, 1, 2, 3, 1};\r\n// un mod de a pune date in v\r\nvector <int> v(av, av + sizeof(av) / sizeof(av[0]));\r\ncout << count(v.begin(), v.end(), 1) << endl; // afiseaza 3\r\nif(!count(v.begin(), v.end(), 4))\r\n    cout << \"v nu contine 4\" << endl;\r\n==\r\n\r\nDaca vrem sa stim doar daca un element apare sau nu intr-o secventa, o varianta ce se poate dovedi mai rapida in situatii foarte particulare este sa folosim {$find$}.\r\n\r\n== code(cpp) |\r\nif(find(v.begin(), v.end(), 4) == v.end())\r\n    cout << \"v nu contine 4\" << endl;\r\n==\r\n\r\nIn sfarsit, o ultima functie interesanta ce lucreaza pe secvente este {$reverse$}. Utilizare tipica:\r\n\r\n== code(cpp) |\r\nint av[] = {1, 1, 2, 1};\r\nvector <int> v(av, av + sizeof(av) / sizeof(av[0]));\r\nreverse(v.begin(), v.end()); // acum v contine 1, 2, 1, 1\r\n==\r\n\r\nAlte mici utilitare care operaza cu valori normale (nu containeri) sunt: {$max$}, {$min$}, {$swap$}. Semantica este probabil evidenta din nume, dar voi da totusi un exemplu de utilizare:\r\n\r\n== code(cpp) |\r\nint a = 2, b = 1;\r\nint m = min(a, b);\r\nint M = max(a, b);\r\nswap(m, M);\r\ncout << M << \" \" << m << endl; // afiseaza \"1 2\"\r\n==\r\n\r\nh2(#concluzie). Concluzie si referinte\r\n\r\nIn acest articol am prezentat doar o portiune reprezentativa a STL. Am preferat sa dau multe exemple simple in locul unor explicatii mai teoretice. Uneori mi-a fost tare greu sa ma abtin (de exemplu sa nu povestesc mai in detaliu cum e gestionata implicit zona de memorie \"rezervata\" si de ce...)\r\n\r\nPentru mai multe detalii puteti fie sa consultati o referinta electronica, fie sa studiati cartea lui Bjarne Stroustrup, \"Limbajul C++\", aparuta la Teora. Alte referinte ajutatoare:\r\n\r\n# \'Power up C++ with the Standard Template Library: Part I\':http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=standardTemplateLibrary\r\n# \'Power up C++ with the Standard Template Library: Part II: Advanced Uses\':http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=standardTemplateLibrary2\r\n# \"Referinta SGI\":http://www.sgi.com/tech/stl/\r\n# \"Standardul C++\":http://www.csci.csusb.edu/dick/c++std/cd2/\r\n',2044,'public',3678,NULL),('schimbare-borland/alegeri','Alegerile','2008-11-18 00:45:59','2008-11-25 10:35:25','h1. Alegerile\r\n\r\n==include(page=\"template/schimbare-borland\")==\r\n\r\nIn urma unei \'analize riguroase a alternativelor\':schimbare-borland/alternativa, am considerat ca urmatoarele pachete sunt cele mai potrivite pentru OJI:\r\n\r\n* FreePascal \r\n* MinGW Developer Studio\r\n\r\nTODO: argumentat decizia',75,'public',NULL,NULL),('blog/harta-politicii','Senatorii si Deputatii lucreaza part time','2008-11-18 06:04:08','2008-11-19 07:15:17','!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/harta-politicii?badge_hpol_150x100.png! \'Vivi\':http://vivi.ro/blog recidiveaza. Dupa ce a facut o gramada de siteuri, printre care doizece.ro cel mai mare site de jocuri din Romania sau initiativa cu harta publicitatii acum are un nou proiect personal interesant la care lucreaza. Acesta este \'harta politicii din Romania\':http://vivi.ro/politica in care a agregat date legate de prezenta si legile votate de senatori si deputati. Concluzia in mare e ca prezenta la vot e penibila si ca senatorii si deputatii lucreaza part time!\r\n\r\nPuteti vedea datele stranse de el \'aici\':http://vivi.ro/politica si posturi care analizeaza putin datele \'aici\':http://www.vivi.ro/blog/?p=1015 , \'aici\':http://www.vivi.ro/blog/?p=1080 , \'aici\':http://www.vivi.ro/blog/?p=1099  si \'aici\':http://www.vivi.ro/blog/?p=1128 . Ideea proiectului e misto si e o modalitate obiectiva de a prezenta niste date, fara a cobori la nivelul scandalurilor de presa.\r\n\r\nIn contextul in care in postul anterior vorbeam despre DEX online ce a inceput ca un proiect personal, avem inca un exemplu cu ce poate face un programator. Noi putem sa colectam date, sa le analizam si sa le prezentam in o forma in care pot fi intelese foarte usor. Ar fi misto sa apara multe initiative de genul asta, pornite poate chiar de la membrii infoarena.',58,'protected',3362,NULL),('schimbare-borland/pachet','Pachetul de instalare','2008-11-14 18:15:23','2009-08-11 08:57:01','h1. Pachetul de instalare\r\n\r\n==include(page=\"template/schimbare-borland\")==\r\n\r\nPe pagina aceasta gasiti un pachet care instaleaza diverse compilatoare si medii de programare, menite sa fie folosite ca alternativa la produsele Borland folosite la OJI.\r\n\r\n\'*&raquo; Downloadeaza pachetul!*\':schimbare-borland/pachet?OJIkit2.exe\r\n\r\nPachetul contine urmatoarele componente:\r\n\r\n* \'FreePascal 2.2.2\':http://www.freepascal.org/\r\n* \'Documentatie Free Pascal\':http://www.freepascal.org/docs.var\r\n* \'MinGW Developer Studio 2.05\':http://en.kioskea.net/telecharger/telecharger-608-mingw-developer-studio\r\n* \'Documentatie STL\':http://www.sgi.com/tech/stl/\r\n\r\nPachetul a fost creat folosind programul open source \'Nullsoft Scriptable Install System\':http://nsis.sourceforge.net/Main_Page. Sursele pachetului sunt disponibile pentru \'download\':schimbare-borland/pachet?OJIkit-source-full.zip. Versiunea fara continutul componentelor este disponibila \'aici\':schimbare-borland/pachet?OJIkit-source.zip.\r\n\r\nScanat de virusi cu McAfee Enterprise Workstation. (11-08-2009)\r\n',75,'public',NULL,NULL),('blog/dexonline','DEX online sub capotă','2008-11-14 23:44:46','2008-11-15 16:10:25','_Discutam de mai multă vreme cu_ \'Cătălin Frâncu\':http://www.google.com/search?hl=en&q=catalin+francu&btnG=Search _despre proiecte personale şi despre_ \'Dex Online\':http://dexonline.ro _. Cu Cătălin am mai discutat pe blogul infoarena_ \'aici\':http://infoarena.ro/blog/interviu-cu-catalin-francu _şi_ \'aici\':http://infoarena.ro/blog/interviu-cu-catalin-francu-partea-a-doua _. Acum, la mai bine de un an dupa acele discuţii el a scris un articol foarte interesant despre traiectoria acestui proiect. Articolul este destul de lung, dar cred că e foarte interesant şi puteţi învăţa mult din el. De obicei înveţi din experienta proprie şi durează o perioada până treci prin destule proiecte incât să ai o privire de ansamblu. Articolul ăsta poate să vă scurteze acea perioadă. Aşa că luaţi o cană de cafea sau ceai şi vă urez lectură plăcută!_\r\n\r\n*Scopul articolului*\r\n\r\nAcest articol prezintă diverse aspecte din existenţa de şapte ani a proiectului DEX online. Totuşi, articolul nu este în primul rând despre DEX online. Îl scriu la sugestia lui Cosmin Negruşeri pentru comunitatea infoarena.ro. Intenţia articolului este să disece, pentru foştii şi actualii olimpici la informatică, un exemplu de proiect din lumea reală, pentru a sublinia diferenţele între 1000 de progrămele de câte 100 de linii şi un program de 100.000 de linii, între programarea de unul singur şi lucrul în echipă, într-un proiect cu multe alte faţete decât cea informatică.\r\n\r\nTextul pune în lumină particularităţi de natură tehnică, socială, etică şi financiară ale proiectului DEX online. Dintre acestea, voi insista pe latura etică şi socială a proiectului, pentru că de acolo au venit mai multe provocări şi realizări decât din domeniile tehnic şi financiar. Documentul se lansează adesea în judecăţi de natură morală, cu riscul de a plictisi. Sunt de părere că administratorul unui proiect cu oarecare utilitate practică nu poate rămâne amoral, ci trebuie să ia nişte decizii.\r\n\r\nNu recomand nimănui să facă lucrurile exact aşa cum le-am făcut noi. DEX online ar putea fi mai prezentabil. Sau ar putea oferi un corector ortografic pentru Word. Sau ar putea costa 5€/lună pentru accesul nelimitat la definiţii. Sau şi-ar putea răsplăti colaboratorii cu 10 centi pentru fiecare definiţie trimisă. Sau ar putea include un dicţionar urban. Acestea toate sunt hotărâri pe care le ia coordonatorul unui proiect în funcţie de timpul disponibil şi de scopurile echipei sale.\r\n\r\n\r\n*Auto organizarea proiectului*\r\n\r\nDEX online nu are manageri, nu are avocaţi, nu are contabili, nu are şedinţe, nu are ore fixe. Într-un cuvânt, DEX online nu are o ierarhie. DEX online are un website şi o listă de discuţii pentru voluntari, plus alte câteva unelte secundare (un sistem de gestiune a bug-urilor, un sistem de gestiune a emailurilor de la utilizatori, o pagină wiki practic nefolosită). Oamenii sunt cei mai productivi atunci când le oferi o listă de lucruri pe care le pot face în folosul proiectului şi îi laşi să facă ce le place cel mai mult. Ca urmare, avem unele definiţii care stau necorectate de luni de zile, deşi între timp am corectat mii de alte definiţii. Mie, ca programator, îmi revine sarcina de a crea o interfaţă în care voluntarii să poată lucra eficient. De aceea, îmi petrec mai mult timp lucrând la pagina moderatorului (invizibilă publicului larg) decât la paginile publice.\r\n\r\nEste surprinzător ce oameni de calitate poţi aduna dacă menţii o listă de email activă timp de 7 ani. Ei rezolvă multe din problemele care pe mine mă depăşesc. De fapt, am încetat să mă mai consider „conducătorul” proiectului după primele 6 luni; prefer titlul istoric de „fondator” sau pe cel de „coordonator”. De exemplu, primim zilnic emailuri cu întrebări de natură lingvistică la care eu nu aş şti să răspund. Sau ne-am izbit de fineţuri legale. Sau a trebuit să creez o schemă MySQL pentru nişte date pe care nu le înţelegeam la nivel conceptual. Din fericire, pe lista noastră de discuţii există lingvişti, avocaţi şi programatori care ne-au scos întotdeauna din impas. Cu timpul, separarea funcţiilor s-a produs de la sine. De exemplu, sistemul de email are o coadă de mesaje destinate mie, cu cerinţe la care numai eu pot răspunde. La restul mesajelor aproape nu mă mai uit, pentru că alţi voluntari şi-au însuşit această parte a sistemului şi se ocupă impecabil de ea.\r\n\r\nDEX online nu a avut niciodată ambiţii pe termen lung sau OKR-uri _(obiective şi rezultate cheie)_. Sună un pic paradoxal, dar poţi avea nişte idei generale despre ce ar trebui făcut, fără să faci din asta o obligaţie. Poţi să te aştepţi să atingi obiectivul X la momenul T fără să promiţi că vei îndeplini obiectivul Y, care depinde de X, la momentul T + 1. De exemplu, am început prin a culege definiţii din DEX. Bazându-ne pe progresul zilnic, am estimat că va dura cam 5 ani să culegem tot DEX-ul (până la urmă a durat doar 3). Dar nu ne-am gândit la modul serios cu ce ne vom ocupa timpul după aceea sau ce vom face cu baza de date odată ce va fi completă. Nu mi-a plăcut niciodată acest gen de presiune, am preferat să nu le-o induc voluntarilor, şi nu se poate spune că am bătut pasul pe loc din cauza asta. Nici unui voluntar nu i s-a părut inacceptabil că am muncit trei ani pentru a culege un dicţionar, nici nu ne-am trezit în vreo dimineaţă sâcâiţi de gândul că trebuie să mai introducem 50 de definiţii şi poate n-avem chef.\r\n\r\nUn aspect care poate dezamăgi, dar aşa s-a întâmplat, a fost începutul întâmplător al proiectului. Nu am stat zile în şir să mă gândesc „la ce-aş putea eu munci care să aibă un impact seminificativ pe internetul românesc?”. Abia după ce lucrasem la el vreun an am conştientizat că DEX online ar putea ajunge un site de referinţă. Ideea proiectului mi-a venit în 2001, când eram student în Boston şi foloseam zilnic dicţionare explicative englezeşti online pentru a-mi scrie temele. Pe de altă parte, duceam lipsa unui dicţionar explicativ românesc. Odată am avut o dispută cu un prieten asupra pluralului lui „cratiţă”: el susţinea că este „cratiţe”, iar eu „crătiţi”. Răspunsul, care i-a dat dreptate, a trebuit să aştepte câteva luni până am mers în vacanţă în România. De acolo am venit înapoi cu un DEX, dar m-am gândit că ar fi frumos să existe o variantă pe internet, de pe urma căreia să profite toată lumea, nu doar eu. Dar, având în vedere că după 6 luni de existenţă DEX online cuprindea vreo 50 de definiţii, din care vreo 45 introduse de mine, nu l-am luat foarte în serios. Ulterior, Federaţia Română de Scrabble (F.R.Sc.) a descoperit site-ul şi a început să contribuie masiv cu definiţii. Probabil acolo a fost punctul critic al proiectului şi, privind înapoi, mi se pare că s-a întâmplat un lucru nemaipomenit de improbabil ca 10 oameni să-şi pună încrederea într-un proiect cvasianonim, care ar fi putut merge prost din nenumărate motive. Concluzia acestui paragraf este că inspiraţia vine de unde nu te aştepţi.\r\n\r\n\r\n*Finanţe*\r\n\r\nDEX online nu vehiculează nici un fel de sume băneşti. Am evitat ca proiectul să aducă orice fel de venituri, din motive multiple.\r\n\r\n# Banii aduc discordie. Singurul caz în care poate aş accepta să caut profit de pe urma siteului ar fi dacă toţi colaboratorii proiectului ne-am umple de bani, ceea ce o judecată la rece arată că nu e cazul. Veniturile ar fi imposibil de repartizat echitabil, deoarece natura muncii depusă de fiecare voluntar este diferită şi deci greu de cuantificat. Unii răspund la emailuri, alţii introduc sau corectează definiţii, alţii scriu cod, alţii lucrează la generarea flexiunilor.\r\n# Veniturile vin din reclamă, iar reclama strică un site. Îl strică mai mult (dacă este o reclamă cu „daţi click pe maimuţă”) sau mai puţin (dacă este Google AdSense), dar îl strică, pentru că prin natura ei reclama are scopul de a distrage utilizatorul de la conţinutul paginii.\r\n# O altă sursă de venituri ar fi limitarea accesului gratuit şi introducerea de costuri pentru accesul complet la baza de date, care nu intră în discuţie, deoarece nu se potriveşte filozofiei noastre.\r\n# Veniturile trebuie contorizate, raportate la Fisc, impozitate, ceea ce duce la nevoia înregistrării unei firme, la angajarea unui contabil şi alte probleme cu care preferăm să nu ne dăm bătăi de cap.\r\n# Odată ce un serviciu generează venituri, apare automat nevoia de mai multe venituri în flux continuu pentru a acoperi nişte cheltuieli periodice (tot ceea ce înseamnă cheltuielile unei firme). Ori, DEX online a ajuns acolo unde este tocmai pentru că nu l-am împins în nici un fel de la spate şi nu l-am tratat ca pe un serviciu, ceva de care trebuie să te ocupi în fiecare zi la oră fixă.\r\n\r\nDEX online nu are nici cheltuieli seminificative. Am obţinut tot ce ne-a trebuit de la oameni şi firme care au apreciat calitatea proiectului: găzduirea, unele dintre dicţionare, fonduri pentru cumpărarea unui software de OCR. Cea mai mare donaţie însă este timpul liber al fiecăruia dintre participanţi.\r\n\r\n\r\n*Free as in freedom*\r\n\r\nÎn prezent, baza de date şi codul DEX online sunt disponibile sub licenţa GPL, dar am trecut prin diferite stadii până a ajunge aici.\r\n\r\nPână în 2004, când DEX online conţinea cam 30.000 de definiţii, nici nu ne-am pus problema unei licenţe, mai ales că încă nu ştiam cu ce ochi priveşte Academia Română proiectul DEX online. Intenţia mea era în continuare să aştept până la reglementarea situaţiei cu Academia şi, eventual, DEX online să intre sub tutela acestui for.\r\n\r\nTotuşi, în timp ce Academia nu manifesta nici un interes pentru DEX online, restul internetului românesc începuse să ne remarce. Apăruseră multe concepţii greşite şi critici la adresa DEX online, iar noi, ocupaţi cu introducerea datelor, neglijasem să ne expunem clar principiile într-un document. În paralel, interesul pentru baza de date era în creştere şi fusesem de mai multe ori vizitaţi de crawlere web a căror intenţie părea să fie să transfere toate definiţiile (comportamentul era evident diferit de al unui motor de căutare general). De asemenea, se punea problema dacă definiţiile preluate din DEX reprezintă un furt intelectual sau nu.\r\n\r\nÎn acest context, am petrecut câteva zile schimbând emailuri cu ceilalţi membri ai proiectului şi, în final, am pus licenţa GFDL (GNU Free Documentation Licence) pe baza de date. Ulterior, am înlocuit GFDL cu GPL (General Public License), care se aplică la fel de bine scopurilor noastre şi evită nişte neajunsuri ale GFDL (în privinţa traducerilor şi a incompatibilităţii cu unele distribuţii de Linux). Licenţierea bazei de date a rezolvat multe probleme de natură etică, dar şi tehnică:\r\n\r\n* Am demonstrat că scopul primar al DEX online este să-i ajute pe vorbitorii de limbă română, nu să obţină profit material.\r\n* Am preîntâmpinat crearea unei pieţe negre pentru baza de date. Este imposibil să împiedici copierea unei definiţii odată ce o afişezi pe ecran.\r\n* Am permis programatorilor să folosească baza noastră de date pentru diverse aplicaţii interesante, ei având garanţia că nu putem să ne răzgândim mâine şi să le spunem „accesul la baza de date nu mai este liber” (în acest sens, licenţa GPL protejează mai degrabă documentul decât pe autorul său).\r\n* Deşi relaţia noastră cu Academia Română are încă un semn de întrebare, cel puţin am eliminat orice alte părţi din această dispută.\r\n* Din punct de vedere etic, am oferit în mod liber rodul unui proiect care, la rândul lui, s-a folosit din plin de resurse libere şi gratuite (nu doar software, dar şi munca voluntarilor, găzduirea, lista modelelor de flexiune, dicţionarele de la firma Siveco sau -- de ce nu -- educaţia mea, pentru care n-am cheltuit niciodată vreun ban).\r\n\r\n\r\n*Proiecte externe bazate pe DEX online*\r\n\r\nCa dovadă că decizia de a redistribui liber baza de date a fost bună, iată ce unelte externe folosesc baza de date a DEX online (numai cele despre care am aflat noi):\r\n\r\n* Clienţi pentru consultarea offline a bazei de definiţii (vezi secţiunea de unelte)\r\n* Dicţionar pentru telefoanele mobile: http://www.jarcraft.com/page.php?9\r\n* Corector ortografic pentru OpenOffice, Firefox şi Thunderbird: http://www.archeus.ro/lingvistica/CorectorOrtografic\r\n* Dicţionar de rime: http://stefann22.lx.ro/\r\n* Client de Google Talk: http://www.archeus.ro/lingvistica/CautareGTalk\r\n* Spânzurătoarea: http://www.roportal.ro/jocuri/joaca-online/54.htm\r\n\r\n\r\n*Momente semnificative*\r\n\r\nNefiind împovărat de griji financiare sau de obiective pe termen lung, DEX online a avut o existenţă destul de liniştită. Din acest punct de vedere, mă bucur că DEX online a rămas în stadiul de proiect făcut în timpul liber. Au existat totuşi câteva momente când viitorul proiectului a fost foarte nesigur sau, dimpotrivă, când proiectul a avansat în salturi foarte mari.\r\n\r\nÎn primul rând, după cum am arătat, începutul a fost greoi. Mulţi factori făceau proiectul să arate cam neviabil. Cuprindea cu totul cam 50 de definiţii. Nu era disponibil tot timpul, deoarece era găzduit pe calculatorul meu din cămin, pe care îl mai şi rebootam uneori în Windows ca să mă joc câte ceva. Iar aspectul grafic era de-a dreptul îngrozitor: în primii 2 ani, DEX oline nu a folosit nici un fel de CSS, pentru că nu ştiam ce este acela. Mai exact, când am început proiectul DEX online, ştiam doar în mare ce este aceea o „pagină dinamică”: un program care e de presupus să producă ieşire HTML, care este servită clientului. Restul (HTML, formulare HTML, MySQL, Perl / PHP) le-am învăţat din mers. DEX online avea un fundal violet, fonturi negre şi tabele cu chenare groase. În diverse browsere, diverse caractere Unicode apăreau mai mari, mai mici, mai groase decât caracterele ASCII sau erau înlocuite de pătrăţele. Probabil că dacă aş vedea astăzi o iniţiativă asemănătoare, aş cataloga-o drept neserioasă. Este admirabil că primii noştri voluntari au reuşit să vadă dincolo de prezentare şi să se axeze pe conţinut.\r\n\r\nDe un alt impas ne-am izbit în 2004, când am reuşit să luăm legătura cu editura care a publicat DEX ediţiile 1996 şi 1998 (motivul pentru care nu le-am scris mai devreme a fost că aveau un website făcut complet în Flash, neindexat, la vremea aceea, de nici un motor de căutare; nu aveau nici legături către site, deci nu i-am putut găsi). Prima reacţie a editurii când le-am prezentat proiectul a fost „trebuie să închideţi siteul acum, altfel veţi suporta consecinţele legale”. Ca urmare, prima măsură pe care am luat-o a fost să aplicăm licenţa GFDL pe date, pentru ca în cazul în care ar fi trebuit să închidem siteul, datele să aibă o şansă să se răspândească. Ulterior, am ajuns la concluzia că ediţiile 1996 şi 1998 ale DEX sunt 99% identice cu ediţiile 1984 şi chiar 1975, care, fiind publicate în perioada comunistă, nu conţineau nici un fel de informaţii de copyright. Editura nu şi-a dat nici până astăzi acordul expres pentru DEX online, dar nici nu ne-a mai pus beţe în roate şi îi suntem recunoscători pentru aceasta.\r\n\r\nÎn septembrie 2004, DEX online a sărit brusc de la 65.000 de definţii la vreo 240,000. Firma Siveco, care deţine drepturile de copiere asupra mai multor dicţionare (de sinonime, de antonime etc.) ne-a acordat permisiunea de a le republica sub licenţa GFDL. Câştigul a fost substanţial, dar ne-a dat şi foarte mult de lucru în lunile următoare. Am muncit mult la scripturile care au importat aceste definiţii, dar chiar şi aşa datele au fost importate cu destule erori, care au trebuit depistate şi corectate manual. Paradoxal, mulţi dintre oamenii cu pregătire lingvistică din jurul DEX online consideră aceste dicţionare ca fiind slabe calitativ (nu neapărat prin definiţii incorecte, cât prin definiţii inconsistente, neînchiderea tranzitivă a setului de sinonime şi alte motive). Totuşi, la acel moment erau cele mai bune date pe care le aveam la dispoziţie. E drept că pentru 1% din căutări rezultatele sunt nemulţumitoare, dar eu consider că acesta este un procentaj foarte bun.\r\n\r\nUn eveniment interesant s-a petrecut în noiembrie 2006, când a apărut primul dicţionar urban pentru limba română (http://123urban.ro). Băieţii de la 123urban au o misiune foarte coerent definită: de a continua consemnarea limbii române de acolo de unde a lăsat-o Academia. Efortul lor este unul necesar: cel de a documenta termenii din nişa argotică. Apariţia lor ne-a făcut şi pe noi să ne întrebăm care ne sunt, de fapt scopurile şi cât de departe suntem dispuşi să mergem pentru a ne îmbogăţi baza de cuvinte definite. O variantă de colaborare, din punctul nostru de vedere, ar fi fost să includem baza lor de date ca pe o „sursă” separată (cot la cot cu DEX, DOOM şi celelalte). Până la urmă, colaborarea nu s-a materializat şi nu am mai urmărit-o de atunci. Noi nu am fost siguri că moderarea lor şi sistemul lor de votare funcţionează bine. Dacă o persoană propune o sintagmă, dar nimeni nu o coroborează printr-un vot pozitiv, DEX online trebuie să accepte acea sintagmă sau nu? În plus, baza de date a 123urban nu este disponibilă sub o licenţă compatibilă cu GPL, ceea îngreunează colaborarea din punct de vedere tehnic şi principial.\r\n\r\n\r\n*Evoluţia generatorului de flexiuni*\r\n\r\nÎn prezent, DEX online oferă flexiunile majorităţii cuvintelor limbii române. Dar procesul prin care am ajuns la acest stadiu este un exemplu tipic de colaborare într-un proiect deschis. Încep cu un mini-glosar pentru lămurirea termenilor tehnici:\r\n\r\n* *lexem*: unitate lexicală; suport minim al semnificaţiei; pentru toate scopurile practice, este cam totuna cu „cuvânt”.\r\n* *formă flexionară*: formă modificată a unui cuvânt pentru a exprima un raport gramatical (număr, gen, timp etc.). De exemplu, copilul este o formă flexionară a lexemului copil.\r\n* *paradigmă*: totalitatea formelor flexionare ale unui cuvânt.\r\n* *model de flexiune*: paradigmă comună tuturor lexemelor care se flexionează la fel (de exemplu, _a lucra_, _a forma_ şi _a cresta_ au toate acelaşi model de flexiune). Este practic o clasă de echivalenţă.\r\n\r\nÎn 2006 am început să ne gândim serios să adăugăm flexiuni la cuvintele din DEX online. Cel mai complex aspect este reprezentarea diferitelor transformări pe care le suferă un cuvânt. Flexionarea în limba română se face, în general, prin adăugarea unor sufixe, dar aceste sufixe pot fi foarte variate. Ca exemplu, pluralul substantivelor feminine poate fi format cu _-e (case)_, cu _-i (inimi)_, cu _-uri (ierburi)_, cu _-ele (acadele)_, cu _-ale (macarale)_ etc. În plus, Limba română abundă în fenomene morfologice care transformă un sunet într-altul la aplicarea unei flexiuni. Exemple de transformări comune sunt _t → ţ (bărbat → bărbaţi)_ sau _o → oa (uşor → uşoară)_. Unele flexiuni suferă mai multe transformări _(sămânţă → seminţe)_. În plus, dorim să stocăm şi informaţii despre accentul fiecărui lexem şi cum se mută el în timpul flexionării _(a împrumutá → eu împrumút)_, ceea ce duce la o varietate exponenţială de modele de flexiune.\r\n\r\nPrima versiune a generatorului de flexiuni, pe care am implementat-o fără să mă consult cu nimeni (şi rău am făcut), indica în forma de bază a cuvântului fenomenele morfologice care apar la flexionare. De exemplu, pentru _bărbat_ stocam forma de bază _bărbaT_, unde _T_ indică transformarea _t →ţ_. Pentru _băiat_ stocam forma de bază _băiAT_ pentru a indica transformările _a → e_ şi _t → ţ (băieţi)_. Această informaţie referitoare la fiecare cuvânt trebuia cuplată cu nişte meta-cunoştinţe referitoare la partea de vorbire. De exemplu, transformarea _t → ţ_ nu se aplică decât la pluralul substantivelor (forma de singular articulat este tot _bărbatul_, nu _bărbaţul_).\r\n\r\nImplementarea acestui sistem a fost relativ uşoară, dar concepţia a fost greşită. Cineva ar fi trebuit să treacă prin toate cuvintele limbii române şi să indice aceste fenomene morfologice. Volumul de muncă ar fi fost mic comparabil cu tastarea unui dicţionar întreg, dar ar fi fost oricum considerabil. Argumentul care a demolat complet această implementare a fost că ea nu putea reprezenta toate modelele de flexiune. În primul rând, numărul de fenomene morfologice depăşeşte cu mult numărul de litere şi simboluri Unicode convenabile pentru notaţie, iar în al doilea rând, flexionarea bazată pe sufixe este inerent ambiguă. De exemplu, _roditor_ şi _chior_ au acelaşi sufix _-or_, dar se flexionează diferit ( _roditoare_, respectiv _chioară_).\r\n\r\nDe-abia în acest moment am început să caut alte soluţii. Astfel am aflat că lista de forme flexionare exista deja de zeci de ani. Alf Lombard (1902-1996), un lingvist suedez, a prins drag de limba română şi i-a studiat gramatica în amănunt. După care a creat nişte aşa-numite „modele de flexiune”. Adică a împărţit cuvintele limbii române în clase de echivalenţă cu flexionare identică, atâtea câte a putut identifica. Pentru fiecare clasă, a ales un cuvânt-exponent căruia i-a înşirat explicit paradigma. Prin studierea transformărilor exponentului, se poate deduce paradigma altui cuvânt cu acelaşi model de flexiune. De exemplu, _ceapă_ şi _damigeană_ au acelaşi model de flexionare. _Ceapă_ este exponent şi pluralul lui, definit explicit, este _cepe_. Observăm transformările _ea → e_ şi _ă → e_. Prin analogie, pluralul lui _damigeană_ este _damigene_. În final, s-a dovedit că limba română are cam 800 de modele de flexiune (circa 280 pentru verbe, 320 pentru substantive, 120 pentru adjective şi altele). Aceste modele au fost publicate în Dictionnaire morphologique de la langue roumaine, apărut în 1981.\r\n\r\nDe aici datele au fost preluate de F.R.Sc. Ei aveau nevoie de lista flexiunilor pentru a stabili dacă un cuvânt depus în timpul jocului de scrabble este corect. Au adus deci lista de modele de flexiune la zi, conform cu ultimele norme ortografice, şi au etichetat toate cuvintele nou intrate în limbă cu modelul corespunzător. Această listă exista în format digital, dar era menţinută manual, într-un fişier Word. Pentru concursurile de scrabble, arbitrul dispunea de două cărţulii tipărite: una cu cuvintele acceptate, etichetate cu modelul de flexiune, şi una cu modelele de flexiune desfăşurate explicit.\r\n\r\nDEX online a preluat listele de la F.R.Sc., beneficiind aşadar, complet gratuit, de rodul unei munci de zeci de ani. Ulterior, am continuat să etichetăm multe alte lexeme pe care F.R.Sc nu le tratase, deoarece din cele 130,000 de lexeme din DEX online, numai jumătate provin din DEX, restul provenind din alte dicţionare de specific (în special de neologisme şi de arhaisme).\r\n\r\nÎn prezent, lista de flexiuni are foarte multe aplicaţii utile:\r\n\r\n* Pe baza ei am generat un corector ortografic.\r\n* Ea permite căutarea „full-text”, care altfel nu ar putea funcţiona prea bine. În absenţa listei de flexiuni, am putea căuta „carte” prin tot textul definiţiilor, dar căutarea nu ar înapoia definiţiile care conţin textul „cărţi” sau „cărţilor”.\r\n* Ea ne permite să răspundem la un click pe orice cuvânt dintr-o definiţie, trimiţând la definiţia acelui cuvânt. Din nou, fără această listă nu am şti ce să facem când utilizatorul ar da click pe cuvântul „cărţi”, pentru că nu am şti care este forma de bază a cuvântului.\r\n\r\nPentru a ne revanşa faţă de F.R.Sc., am decis să creăm un subsistem al DEX online (numit intern Flex online) în care F.R.Sc. să poată gestiona, mai bine decât într-un fişier Word, lista de cuvinte acceptate. De exemplu, dacă se dovedeşte că două lexeme nu se flexionează chiar identic, sistemul permite spargerea unui model de flexiune în două, modificarea clonei şi reasignarea lexemelor într-unul din cele două modele. Când F.R.Sc. emite o versiune nouă a listei de cuvinte (la fiecare câţiva ani), sistemul Flex online le permite să compare cele două versiuni, ceea ce ajută la eliminarea erorilor.\r\n\r\n\r\n*Ce am învăţat din asta*\r\n\r\nCând cineva vă oferă ajutorul, faceţi-vă luntre şi puntre ca să-i creaţi condiţii de muncă. Colaboratorii nu cresc pe toate drumurile şi trebuie preţuiţi. Dacă cineva vrea să scrie cod pentru proiect, daţi-i acces la repository şi asiguraţi-vă că vă poate trimite patch-uri. Dacă vrea să raporteze bug-uri, asiguraţi-vă că aveţi un sistem gen Bugzilla. Dacă se oferă să vă creeze un skin sau o interfaţă grafică mai bună, asiguraţi-vă că există o separare bună între extragerea datelor şi prezentarea lor (respectiv, folosiţi un template engine). Dacă vă pune la dispoziţie date, luaţi-le. O bună parte din programarea pentru DEX online am petrecut-o scriind scripturi care să importe diverse documente. A fost plicticos, dar a meritat.\r\n\r\nBriciul lui Occam este o regulă foarte bună pentru a delimita munca manuală de scripting. Dacă durează X ore să prelucraţi manual nişte date şi Y ore să scrieţi un script care să le proceseze automat, scriptul merită scris doar dacă X > Y. De nenumărate ori am depistat nişte erori sistematice în definiţiile din DEX, dar le-am corectat manual, una câte una.\r\n\r\nProgramarea este frumoasă, dar reimplementarea a ceva ce există şi funcţionează, doar pentru că nu v-aţi informat şi nu aţi întrebat pe nimeni, este o risipă de talent.\r\n\r\n20% din oameni fac 80% din muncă. Fiecare ţine cont cum vrea de acest fapt. La DEX online am încercat să le creez condiţii şi celorlalţi 80% dintre voluntari, dar recunosc că nu am reuşit întotdeauna. De exemplu, mulţi dintre voluntari, deşi au dorit să ne ajute, nu au învăţat niciodată cum să formateze corect definiţiile (avem un mini-set de notaţii pentru bold, italic, exponenţi ş.a.m.d.). Practic trebuia să trecem prin toată definiţia, să-i adăugăm diacritice şi să o formatăm, ceea ce dura cam la fel de mult ca şi rescrierea ei de la zero. De la un punct încolo am renunţat să îi mai trimit la documentaţie -- le respingeam pur şi simplu definiţiile trimise.\r\n\r\nÎn marea lor majoritate, oamenii sunt buni şi vor să ajute; foarte puţini sunt cei care încearcă să facă rău sistemului. Problema este că oamenii răi sunt mai perseverenţi, iar efectele pot fi foarte grave („dacă amesteci o linguriţă de bălegar într-un butoi de vin, obţii un butoi de bălegar”). Trebuie deci să fiţi pregătiţi să vă petreceţi o bună parte din timp scriind cod care nu creează conţinut util, ci previne vandalismul. Este supărător, dar cu timpul vă veţi obişnui. De exemplu, nici un programator nu se supără că trebuie să implementeze autentificarea cu parole, deşi acel cod este destinat numai să-i blocheze pe cei 1% dintre utilizatori care s-ar gândi să se lege în contul altcuiva.\r\n\r\nOricât de intuitiv de folosit este proiectul vostru, marea majoritate a utilizatorilor nu vor şti să-l folosească sau îi vor folosi numai un subset mic de funcţii. De exemplu, puţină lume dă click pe legătura către conjugări / declinări care apare după rezultatele căutării în DEX online. Trebuie să fiţi pregătiţi să răspundeţi la multe, multe întrebări. Este bine să aveţi un sistem semiautomat de gestionare a emailurilor, unde să puteţi crea şabloane, pentru că multe din întrebări vor necesita răspunsuri identice. DEX online foloseşte OTRS, dar există multe alte soluţii.\r\n\r\nFaceţi-vă cât mai dispensabili. Cu cât proiectul este mai descentralizat, cu atât va evolua mai uşor. Să nu ajungeţi niciodată la stadiul în care nu vă puteţi lua o vacanţă că se duce totul de râpă. În general, dacă alţi membri ai proiectului au mai multă energie ca voi, aveţi datoria morală să configuraţi sistemul astfel încât să nu-i ţineţi în loc. La DEX online, unica componentă de care mă ocup singur este scrierea codului. Corectarea definiţiilor şi a lexemelor şi răspunsul la emailuri merg foarte bine (sau chiar mai bine) în lipsa mea.\r\n\r\nUn proiect util nu este neapărat dificil din punct de vedere tehnic. DEX online este exemplul perfect în acest sens. Sunt puţine locuri în cod unde am avut nevoie să implementez un algoritm „deştept”. Poate un exemplu ar fi diff-ul între două versiuni ale unei definiţii, pe care până la urmă nici nu îl folosim la nimic în practică. Un alt lucru la care ne-am gândit destul de mult înainte de a-l implementa este schema bazei de date care stochează modelele de flexiune. În rest însă, DEX online excelează prin răbdare, prin volumul de date adunate şi prin calitatea voluntarilor implicaţi, dar mai puţin prin algoritmii şi structurile de date folosite.\r\n\r\nConcluzia este că sunt oameni care vorbesc şi sunt oameni care fac. DEX online nu a fost creat în cel mai eficient mod posibil (am tastat de mână o mulţime de definiţii); nu excelează la nivel tehnic (baza de date conţine, în esenţă, nişte cuvinte asociate cu nişte definiţii şi cu nişte forme flexionare); a fost adesea luat în râs şi criticat, mai ales în primii 3 ani de existenţă; are şi acum suficiente greşeli de tipar; şi, fiind vorba de un instrument lingvistic, nu va fi niciodată complet. Dar, în ritmul nostru şi cu neajunsurile noastre, o mână de oameni cu multă răbdare am reuşit să producem un document remarcabil.',1490,'protected',3356,NULL),('planificare/camp-alcatraz','Coding Camp Alcatraz','2008-11-01 20:59:45','2008-11-16 13:17:13','h1. Coding Camp _Alcatraz_\r\n\r\nNe intalnim in weekend-ul *15-16 noiembrie 2008* la \'*Hostway Romania*\':http://hostway.ro\r\nPrima zi incepe la *ora 10:00* la statia de metrou Nicolae Grigorescu.\r\n\r\nh2. Locatie\r\n\r\n*Str. Theodor Pallady, nr. 26, Sector 3, Bucuresti* - intersectia cu Str. Mizil, in spatele Liceului de Chimie.  \r\nVezi harta pe \'*Salut Bucuresti*\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-11381&-9511 sau pe \'*Yahoo*\':http://maps.yahoo.com/#mvt=m&lat=44.409197&lon=26.177519&zoom=18\r\n\r\nUn mod de a ajunge acolo este sa coborati din metrou la statia Nicolae Grigorescu si sa luati orice tramvai in directia corecta (adica opusa Dristor) pentru 3 statii.  In statia in care trebuie sa coborati veti vedea Liceul de Chimie.\r\n\r\nAvem la dispozitie sala, whiteboard, proiector, internet.\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu Linux (preferabil Ubuntu) instalat pe el\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri\r\n\r\nh2. Participanti\r\n\r\nSpecifica cand poti veni si cat poti sta.\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"stef2n\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"wefgef\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==: minim o zi\r\n* ==user(user=\"silviug\" type=\"tiny\")==: minim o zi\r\n* ==user(user=\"victorsb\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"svalentin\" type=\"tiny\")==: minim o zi\r\n\r\n...\r\n\r\nh2. Plan\r\n\r\nh3. Ziua 1 (2008-11-15)\r\n\r\n* Workflow and tools: \'Trac\':http://hackers.devnet.ro and \'Review Board\':http://reviewboard.infoarena.ro &#10003;\r\n* Explicat \'MVC\':http://en.wikipedia.org/wiki/Model-view-controller si \'unit testing\':http://en.wikipedia.org/wiki/Unit_testing &#10003;\r\n* Toata lumea face \'setup\':http://hackers.devnet.ro/wiki/HackingTutorial la infoarena &#10003;\r\n* Citim si actualizam \'wiki-ul\':http://hackers.devnet.ro/wiki &#10003;\r\n* Rulat \'YSlow!\':http://developer.yahoo.com/yslow/ si citit tutoriale (\'1\':http://developer.yahoo.com/performance/rules.html, \'2\':http://www.thinkvitamin.com/features/webapps/serving-javascript-fast)\r\n* Reorganizat \'tichete\':http://hackers.devnet.ro/report/3 pentru 2.2 &#10003;\r\n** \'Notite la tichete\':camp-alcatraz/tichete-2.2\r\n* Lucram la identificarea bottleneck-urilor si rezolvarea lor (\'benchmarks\':http://hackers.devnet.ro/wiki/Benchmarks) &#10003;\r\n* Backup script &#10003;\r\n\r\nh3. Ziua 2 (2008-11-16)\r\n\r\n* Raport despre imbunatatirile de performanta\r\n* Implementam alte feature-uri &#10003;\r\n* Stabilim data si obiectivele pentru urmatorul Coding Camp &#10003;\r\n* Feedback\r\n\r\nh2. To Do\r\n\r\n* -Luat stampila de la Sergiu-\r\n* -Mers la banca sa punem bani pe card-\r\n* -\'Code review\':http://reviewboard.infoarena.ro la toate change-urile de pana acum-\r\n* -svn up pe live-\r\n\r\nh2. Performanta site-ului\r\n\r\n(Cristian: las mai jos niste notite despre cum ar putea fi imbunatatita performanta site-ului. Nu sunt informatii 100% verificate, luati-le ca puncte de plecare in investigatiile pe care le faceti.)\r\n\r\nh3. Benchmarks\r\n\r\nFolositi ./scripts/benchmark pentru masuratori. Cel mai probabil trebuie imbunatatit putin. (Nu face decat sa ruleze apache-benchmark pe o serie de URL-uri.) Experimentati cu flag-ul -c pentru request-uri concurente.\r\n\r\nBenchmark-urile trebuie interpretate cu atentie. Configuratia live este diferita de cea pentru development.\r\n\r\nh3. MySQL\r\n\r\nMySQL, asa cum il folosim noi, este suspectul principal. De fiecare data cand site-ul nu raspunde si am putut sa ma uit la lista de procese MySQL era in top. Chiar si cand site-ul este responsive si fara trafic semnificativ, MySQL consuma constant CPU. Spre exemplu, acum e 5 dimineata in Romania, site-ul este responsive, iar primele doua procese arata asa:\r\n\r\n==code(c)|\r\n  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND\r\n 1179 mysql     15   0  175m  44m 3072 S   84  4.3  60370:09 mysqld\r\n19234 apache    17   0 75336  24m  10m S    8  2.4   0:03.17 httpd\r\n==\r\n\r\nUnele query-uri sunt prea incete. In /var/lib/mysql/infoarena-slow.log gasiti un slow-queries log facut de MySQL. (Are 1.4GB!) Log-ul trebuie interpretat cu atentie deoarece unele query-uri incete pot declansa o cascada de alte query-uri incete. Un query care in mod obisnuit este foarte rapid poate sa se blocheze asteptand un alt query sa termine; ambele query-uri ajung in infoarena-slow.log.\r\n\r\nDin ce am observat eu mai demult, printre cele mai incete query-uri se numara cel pentru monitorul de evaluare, mai ales pe masura ce avansezi la pagina 2, 3, 4, etc.\r\n\r\nDaca vedeti un query incet, sansele sunt ca sa poata fi optimizat. Folositi EXPLAIN (SQL) ca sa vedeti daca facem uz de indecsi, incercat sa reformulati JOIN-uri cu subqueries (WHERE X = (SELECT ... )), si, daca trebuie, faceti cache la tabele.\r\n\r\nh3. Caching\r\n\r\nDaca trebuie, putem sa bagam in cache intreg tabelul de utilizatori, probleme, runde, si poate altele. Asta ar optimiza semnificativ unele query-uri. Spre exemplu, in monitorul de evaluare nu ar mai trebui sa facem JOIN la tabelele de task-uri, runde, si utilizatori pentru a afisa titluri si nume. SELECT-am doar id-uri iar restul informatiilor le scoatem din cache.\r\n\r\nCaching-ul poate sa rezolve multe probleme de performanta insa are dezavantaje importante:\r\n\r\n* Complica codul. Cand actualizezi X in baza de date trebuie sa invalidezi X din cache impreuna cu toate informatiile care au fost calculate pe baza lui X.\r\n* Serializarea si deserializarea nu sunt operatii teribil de rapide. Nu e eficient sa faci \'apc_fetch\':http://www.php.net/manual/en/ref.apc.php la un array cu intreaga lista de utilizatori. Cache-ul trebuie spart pe bucatele mici. E rapid sa faci fetch la un element insa probabil nu-ti permiti sa iterezi prin multe elemente.\r\n\r\nh3. Directoare mari si plate\r\n\r\nAm observat ca pe live (FS ext3), timpul de acces la un fisier oarecare dintr-un director variaza foarte mult in functie de numarul total de fisiere din acel director.\r\n\r\n==code(c)|\r\n# echo -n ~infoarena/live/{cache,attach,www,www/views} /var/lib/php/session /tmp /usr/bin /usr/lib | xargs -d\" \" -IX echo \' echo -e `find X -type f -maxdepth 1 | wc -l` \"\\t\" `~infoarena/live/scripts/fs-benchmark X` \"\\t\" X \' | bash\r\n\r\n39114    1.7286          /home/infoarena/live/cache\r\n28773    1.2640          /home/infoarena/live/attach\r\n10       0.0021          /home/infoarena/live/www\r\n45       0.0031          /home/infoarena/live/www/views\r\n102972   1.8296          /var/lib/php/session\r\n348      0.0028          /tmp\r\n1194     0.1031          /usr/bin\r\n309      0.3081          /usr/lib\r\n==\r\n\r\nPrima coloana reprezinta numarul de fisiere dintr-un director, a doua reprezinta timpul de acces (fopen + fread 2KB) la 100 de fisiere alese aleator din acel director. Script-ul fs-benchmark il gasiti pe live.\r\n\r\nEu doar am observat ca timpul de acces variaza semnificativ insa _nu stiu daca si cum ne afecteaza pe noi_. Incarcarea unei pagini de \'clasament\':clasament-arhiva fara cache in browser poate sa genereze usor 50 de request-uri HTTP. Daca la fiecare request accesam un fisier de sesiune (din /var/lib/php/session) si inca un fisier din cache sau din attach, ajungem la 100 de accesari de fisiere.\r\n\r\nProbabil ca din acelasi motiv \'MediaWiki stocheaza fisiere de cache in directoare \"stufoase.\"\':http://www.mediawiki.org/wiki/Manual:File_cache\r\n\r\nh3. Sesiuni in memorie\r\n\r\ninfoarena foloseste momentan sistemul de sesiuni implicit configurat in PHP, adica multe fisiere (~100k) in /var/lib/php/session. Sistemul de sesiuni din PHP suporta customizarea backend-ului de stocare. Se poate cupla usor APC. Dezavantaj: cand repornim Apache pierdem toate sesiunile.\r\n\r\n(:P Nota pentru Mircea: Nu ne trebuie memached, avem un singur server.)\r\n',1,'public',NULL,NULL),('blog/interviu-cristi-strat-evz','Interviu Cristian George Strat (Evenimentul Zilei)','2008-11-27 07:58:07','2008-11-27 08:22:16','_Continui cu interviul pe care l-a dat Cristian George Strat pentru Evenimentul Zilei cu ocazia aniversarii a 10 ani de la creerea companiei Google. Un post_ \'anterior\':http://infoarena.ro/blog/interviu-evz-mihai-stroe _contine interviul cu Mihai Stroe (unul dintre cei doi olimpici romani care au obtinut puctaj maxim la olimpiada internationala de informatica). Puteti gasi articolul publicat in ziar_ \'aici\':http://www.evz.ro/articole/detalii-articol/819647/Creierele-romanesti-din-solda-imperiului-Google/ \r\n\r\n\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/interviu-cristi-strat-evz?cristian-george-strat.png!*1. Scurta prezentare.*\r\n\r\nCristian George Strat, din Bârlad, este proaspat absolvent al Facultatii de matematica si Informatica, Universitatea Bucuresti. Cristian face in prezent al doilea stagiu la Google; primul a fost la sediul principal din Mountain View, California iar cel de acum in Zürich, Elvetia.\r\n\r\nCristian este Presedintele Asociatiei infoarena (http://infoarena.ro/) si co-fondator, impreuna cu fratele sau, la o companie romaneasca de consultanta software si networking.\r\n\r\n\r\n\r\n*2. In Romania, un job la Google este insotit aproape intotdeauna de un soi de admiratie ce nu are nevoie de argumente. Cat de greu este de fapt sa ajungi acolo?*\r\n\r\nLa Google se trimit peste un milion de CV-uri anual. Poate parea ca sunt foarte exigenti insa cred ca cerintele lor sunt rezonabile pentru cineva cu adevarat pasionat de programare. Spre exemplu, cei care participa la olimpiade sau la alte concursuri de informatica nu au dificultati majore la interviurile de angajare. Insa nu e obligatoriu sa participi la concursuri; aceleasi cunostinte pot fi dobandite de un student constiincios si pe parcursul unei facultati de profil, dublata cu mult studiu individual.\r\n\r\n\r\n\r\n*3. Ce te motiveaza sa faci ceea ce faci?*\r\n\r\nIn general consider ca e foarte distractiv sa programezi! :) In plus, la Google ai ocazia sa iti aduci contributia la proiecte care ajuta milioane de oameni din intreaga lume. Spre exemplu, poti imbunatati un produs astfel incat utilizatorul sa realizeze ce si-a propus cu cateva secunde mai repede; daca inmultesti cateva secunde cu numarul potential de utilizatori realizezi ca ai scutit omenirea de ani intregi de momente frustrante.\r\nDe asemenea ma motiveaza enorm echipa in care lucrez. Imagineaza-ti ca toti din jurul tau sunt activi, dedicati si entuziasti. E molipsitor; crezi ca poti sa fii altfel?\r\n\r\n\r\n\r\n*4. Este Google tinta ultima a oricarui programator? Se poate mai bine de atat?*\r\n\r\nGoogle e printre cele mai ravnite companii din lume, o dovada fiind si faptul ca s-a clasat pe primul loc in studiul Fortune \"Cele mai bune 100 companii pentru care sa lucrezi\". In ceea ce ma priveste, mi-e greu sa-mi imaginez o companie care sa-mi ofere oportunitati mai mari, un mediu de lucru mai antrenant si colegi mai valorosi decat imi ofera Google. Cu toate acestea insa nu cred ca toti programatorii tintesc sa ajunga aici. Am multi prieteni care lucreaza in Romania si sunt foarte multumiti si entuziasmati de ceea ce fac.\r\n\r\n\r\n\r\n*5. Stim chiar de la Google ca mediul de lucru este unul foarte relaxat. Nu cumva flexibilitatea asta inseamna o responsabilizare a angajatului?*\r\n\r\nLa Google ai program flexibil, la nevoie poti sa lucrezi de acasa, poti sa iei pauze oricand, sa-ti aduci catelul la munca, sau sa-ti inviti prietenii in vizita. In pauze avem la dispozitie mese de biliard, tenis, fussball, jocuri video, putem servi o gustare intr-una din multele bucatarii amplasate in campus sau putem citi o carte in biblioteca.\r\nDesi avem si libertate si tentatii sa irosim vremea, nimeni nu o face. Suntem tratati cu respect, incredere si ca atare ne responsabilizam singuri, nu avem nevoie de presiune \"de sus\".\r\n\r\n\r\n\r\n*6. Ce (mai) inseamna Romania pentru Cristian George Strat? Iti doresti sa te intorci?*\r\n\r\nPentru mine, Romania inseamna o familie iubitoare, prieteni dragi, si amintiri.\r\nAltfel, cred ca Romania ofera multe oportunitati antreprenorilor, in particular celor din industria software si online. Cred ca acum e momentul in care investitii si initiative inspirate pot avea un impact major si pot atrage castiguri pe masura.\r\n\r\nDin alte puncte de vedere insa, cred ca noi romanii suntem groaznici. E trist sa traiesti intr-un oras murdar si poluat, sa-ti irosesti zilnic ore in trafic si la cozi sau sa te fereasca Sfantul sa ajungi prin spitale. Nu pot sa fiu \"optimist\", sa spun cu incredere ca o sa fie bine. Lucrurile evolueaza dezamagitor de incet si nu neaparat inspre mai bine. Insa divaghez...\r\n\r\nImi doresc si ma voi intoarce in tara, macar pentru cativa ani.\r\n\r\n\r\n\r\n*7. Daca maine s-ar infiinta un birou Google in Romania, ai veni sa lucrezi aici?*\r\n\r\nE o intrebare buna. Da, as veni o vreme. De asemenea, cred ca sunt foarte multi programatori talentati in Romania care doresc sa lucreze la Google insa nu sunt dispusi sau nu pot sa se mute in alta tara. Un birou Google in Romania ar fi minunat!\r\n\r\n\r\n\r\n*8. Ce sfaturi i-ai da unui tanar roman care vrea sa lucreze la Google?*\r\n\r\nN-as putea sa dau sfaturi insa pot sa povestesc din experienta mea. Din cate am observat, Google pune accent pe cunostinte fundamentale precum algoritmi, structuri de date, arhitectura sistemelor, statistica, etc. si mai putin pe anumite tehnologii. Limbajele de programare, librariile, sistemele de operare samd. se schimba de la an la an, devin depasite, irelevante.\r\nTrebuie sa studiezi informatica pe cont propriu. Nu e de ajuns sa asimilezi ce te invata la scoala sau in facultate. Avem in Romania site-uri foarte bune de pregatire la informatica - algoritmi si structuri de date - precum http://infoarena.ro/ si http://campion.edu.ro/. Acestea sunt adevarate comunitati de elevi, studenti si profesionisti pasionati de informatica, alaturi de care poti sa inveti mult mai repede.\r\n\r\nIn fine, as vrea sa mentionez ca procesul de angajare nu este perfect. Au fost refuzati si oameni foarte buni. Nu e o mare tragedie daca nu treci de interviuri; un om bune are multe optiuni.\r\n\r\n\r\n\r\n*9. Sunt convins ca foloseai motorul de cautare inainte sa intri in companie. Obiectiv vorbind, de ce e cel mai bun de pe piata?*\r\n\r\nCred ca relevanta si calitatea rezultatelor sunt doua dintre cele mai importante aspecte ale unui motor de cautare. Google exceleaza la amandoua. In plus, este si rapid si simplu de folosit.\r\n\r\n\r\n\r\n*10. Cum crezi ca ar fi aratat lumea fara Google?*\r\n\r\nGoogle a contribuit foarte mult la dezvoltarea internetului. Spre exemplu, programele de advertising AdWords si AdSense au ajutat sute de mii de oameni si companii sa castige bani dezvoltand site-uri web de calitate. Aplicatiile Google - Gmail, Calendar, Docs, etc. - au redefinit limitele tehnologice si posibilitatile de interactiune ale acestui mediu. Valuri de inovatii au urmat in industrie. Va mai aduceti aminte casutele de email de 2MB, de 500 de ori mai mici decat ce oferea Gmail la lansare? Alte initiative Google cu impact potential major sunt de abia la inceput: Google Chrome promite sa imbunatateasca browser-ul web, aceasta componenta esentiala a experientei online; Google.org, angajamentul companiei de a investi 1% din profit si din timpul angajatilor catre actiuni filantropice si probleme globale.\r\n\r\nGoogle a demonstrat ca este o companie cu practici etice si se bucura de increderea utilizatorilor sai. Nu stiu cum ar fi aratat lumea fara Google dar stiu ca lumea e \"mai buna\" datorita lor.',58,'protected',3388,NULL),('blog/bubblebubble','Bubble bubble','2007-12-05 13:54:13','2008-11-16 12:41:25','via \'Mircea\':utilizator/domino\r\n\r\n==YoutubeVideo(id=\"fi4fzvQ6I-o\" width=\"425\" height=\"355\")==\r\n',1851,'protected',2448,NULL),('blog/romanii-la-disneyworld-partea-intai','Romanii la DisneyWorld - partea intai','2007-12-04 00:15:34','2008-11-16 13:11:05','!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/romanii-la-disneyworld-partea-intai?disney.jpg 40%! _In fiecare an \'topcoder\':www.topcoder.com organzieaza doua turnee, unul deschis numai studentilor si altul deschis pentru oricine cu varsta mai mare de 18 ani. De anul trecut cei de pe topcoder au initiat si o competitie de programare pentru liceeni. Ei au mai multe tipuri de competitii: algoritmica, maraton, development, design si studio. La concursuri se califica si romani din cand in cand printre care \'Adrian Carcu\':http://www.topcoder.com/tc?module=MemberProfile&cr=278342 a avut rezultate mai deosebite fiind de doua ori campion si o data locul doi la sectiunea de software design. De la el am luat si eu microbul. Tin minte cum participam impreuna la concursuri de algoritmica la Laboratoru de cercetare al UBB pe la 4 noaptea pentru ca acestea erau organziate in special pentru programatorii din state._\r\n\r\n_In perioada 30 Octombrie - 2 Noiembrie s-a desfasurat finala concursului TopCoder Collegiate Challenge la Disney World, iar in finale s-au calificat trei romani: \'vlad_d\':http://www.topcoder.com/tc?module=MemberProfile&cr=13298470 (\'Vlad Dumitriu\':utilizator/vlad_D ) ce a participat la partea de studio a concursului, \'luca\':http://www.topcoder.com/tc?module=MemberProfile&cr=10348862 (Lazar Lucian, doctorand la Babes Bolyai, Cluj) care a participat pe partea de software design si \'domino\':http://www.topcoder.com/tc?module=MemberProfile&cr=8362207 (\'Mircea Pasoi\':utilizator/domino student Universitatea Bucuresti) ce a participat la concursul de algoritmica si a reusit sa se califice in finala mica a acestui concurs clasandu-se in primii 8 programatori din lume. Am vrut sa aflati mai multe despre concursurile topcoder asa ca le-am luat interviuri celor trei. In acest post public interviul cu Vlad depsre concursul de design grafic, dupa care vor urma doua posturi cu intrebari si raspunsuri pentru Luca si Mircea. Vlad e participant mai vechi pe infoarena si ne-a facut logo-ul pentru preOni. Ii multumesc inca o data din partea echipei._\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/romanii-la-disneyworld-partea-intai?vlad.jpg!\r\n\r\nh1. Vlad Dumitriu\r\n\r\n*Cum e concursul de design grafic?*\r\nE fain. La Studio Design trebuie \"desenate\" diferite chestii. Apar tot felu de proiecte de la logo design pana la webdesign, printing design si tot felul. Iar daca te referi la finala e faina atmosfera, te intalnesti cu oameni de treaba si primesti un proiect care trebuie sa il termini in 8 ore.\r\n\r\n*De ce ai ales sectiunea de design?*\r\nAh, pai am incercat Algo dar am picat din runda 1 din cauza unei \'{\' la MM am ajuns in runda 2 si eram in juru lui top 100, si dupaia m-a cuprins lenea. Asa ca am incercat si Studio Design.\r\n\r\n*Cum ai inceput cu designul?*\r\nAm inceput si eu sa ma joc prin Photoshop, sa editez poze si etc.\r\n\r\n*Ce tooluri sunt folosite?*\r\nLa studio design ai voie Photoshop CS3, AI CS3, si GIMP. Eu folosesc numa Photoshop si AI.\r\n\r\n*Care sunt partile dificile in acest concurs?*\r\nProbabil Inspiratia iar daca ai ceva practica cam poti sa iti desenezi ideile.\r\n\r\n*Ce caracteristici trebuie sa aiba un design bun?*\r\nSa fie bun. In primu rand sa  indeplineasca conditile din proiect requirements iar dupaia conteaza foarte mult stilu, culorile folosite, fonturile folosite, elemente grafice, sunt multe.\r\n\r\n*Cum ar trebui sa inceapa cineva interesat de acest tip de concursuri?*\r\nProbabil tutoriale de pe net sau daca este la scoala de Grafic Design numa\' bine.\r\n\r\n*Ce ii deosebeste pe designerii buni fata de cei medii?*\r\nProbabil practica in caz ca au acelasi talent. Cred ca trebuie si talent si practica.\r\n\r\n*Cat timp iti ia sa termini un design?*\r\nDepinde. De la cateva ore la o zi probabil. Depinde cat de mare e proiectul, iar dupa terminare mai vine si revizuirea. Pe Studio.Topcoder la proiectele mici ai voie sa faci maxim 2 concepte iar la cele mai mari numai unu.\r\n\r\n*Cum a fost la DisneyLand?*\r\nHmm.. Fain.. de mers cu familia daca ai copii mici. In rest pentru studenti nu prea e DisneyLand-ul, ci GreatAmerica, SixFlags etc.. ceva mai serios.\r\n\r\n_Mersi pentru interviu Vlad. Revin maine cu unul din celelalte doua interviuri._\r\n\r\n',2028,'protected',2445,NULL),('blog/muzica','Muzica','2007-11-17 09:09:19','2008-11-16 12:51:30','Cateodata imi place sa ascult muzica in timp ce programez. In timpul liceului stiam inceputul melodiilor de la Deep Purple in ordine alfabetica, pentru ca asa erau in winamp, si cand se apropia sfarsitul uneia incepeam sa fredonez urmatoarea. Acum mi s-au schimbat putin gusturile si in timp ce lucrez imi place Daft Punk. Au o muzica interesanta, cu versuri simple fara intreruperi bruste de ton si asta e bine pentru concentrare.\r\n\r\nVoi ce muzica ascultati cand programati?\r\n\r\nApropo de Daft Punk, v-am pus un video bestial de pe youtube, la inceput e mai lent dar pe la 2:00 incepe sa fie interesant.\r\n\r\n==YoutubeVideo(id=\"K2cYWfq--Nw\" width=\"425\" height=\"355\")==\r\n\r\nIdeea e destul de misto, dar nu \'toate\':http://youtube.com/watch?v=nPLOiBM8hLk melodiile sunt la fel de reusite.\r\n\r\n\r\n',1851,'protected',2344,NULL),('blog/human-computation','Human Computation','2007-11-10 06:26:47','2008-11-20 18:23:58','In cel mai tare tech-talk de pe google video (350.000 de vizionari), Luis Von Ahn ne prezinta o metoda ingenioasa de a folosi oameni pentru a rezolva problemele dificile pentru un calculator. Metoda aleasa e inspirata din o practica a hackerilor. Acestia ii pun pe utilizatorii unui site deochiat sa scrie ce text contine un \'CAPTCHA\':http://en.wikipedia.org/wiki/Captcha inainte de a vedea urmatoarea imagine. Ei reusesc astfel sa treaca de protectia siteurilor de mail, obtinand astfel o gramada de casute din care pot trimite spam. Acum ii respect mai mult pe indivizi chiar daca nu respect motivatia lor.\r\n\r\nGoogle a cumparat cu bani grei idea lui Luis si a implementat-o in \'Google Image Labeler\':http://images.google.com/imagelabeler/ . Poate de acuma il veti juca  in loc de minesweeper :).\r\n\r\nAveti videoul aici. Dureaza o ora, daca nu aveti atata timp uitati-va neaparat la primele 15 minute ca nu trebuie ratat.\r\n\r\n==GoogleVideo(id=\"-8246463980976635143\" width=\"400\" height=\"326\")==\r\n',1490,'protected',2331,NULL),('blog/photosynth','Photosynth','2007-11-03 09:57:16','2008-11-16 12:52:50','Un prieten imi zicea recent ca pun prea multe referinte la Google in posturi, si ar trebui sa adaug referinte la Microsoft ca blogul sa fie mai obiectiv (el lucreaza pentru M$).\r\n\r\nPentru a mai echilibra scorul, am pus videoul de mai jos cu o demonstratie impresionanta a unei aplicatii Microsoft. Demonstratia a avut loc tot la TED talks. Cred ca visul oricarui programator este sa lucreze la un astfel de proiect revolutionar.\r\n\r\n==Youtubevideo(id=\"jEcHcRqxmj4\" width=\"425\" height=\"355\")==\r\n\r\n\r\n\r\n\r\n',1851,'protected',2260,NULL),('blog/interviu-cu-catalin-francu','Interviu cu Catalin Francu - partea intai','2007-10-26 08:26:21','2008-11-16 13:03:41','_Odata cu angajarea mea la Google am avut ocazia sa cunosc multi fosti olimpici, pe care ii stiam doar dupa nume, vazandu-i in \'Ginfo\':http://www.ginfo.ro sau in listele cu premii la diverse concursuri. Unul dintre acesti olimpici este \'Catalin Francu\':http://catalin.francu.com/ , caruia, la o cina in San Francisco, i-am smuls promisiunea ca va raspunde la cateva intrebari pentru ce avea sa fie blogul infoarena. Acum va voi prezenta prima parte a interviului, dupa o scurta prezentare a lui Catalin._\r\n!<blog/interviu-cu-catalin-francu?infoarena.jpg!\r\n_Catalin este cunoscut in lumea celor pasionati de informatica prin cartea \"Psihologia concursurilor de programare\", o carte plina de probleme frumoase si deschizatoare de drumuri la vremea ei, si prin \"lista lu\' Francu\", o lista de discutii pe email, unde cativa dintre cei ce au ajuns apoi olimpici internationali la informatica ai Romaniei rezolvau si discutau probleme. Iar in lumea lingvistilor este cunoscut prin proiectul \'dexonline\':http://dexonline.ro . Acesta este un wiki (inovator pentru 2001, cand Catalin a inceput proiectul) care contine intreg Dictionarul Explicativ al limbii romane si alte dictionare. In timpul liceului, Catalin a luat o medalie de argint la olimpiada internationala de informatica, iar in timpul facultatii s-a clasat pe locul 7 la etapa finala a concursului ACM ICPC cu echipa reprezentanta a MIT. De asemenea a facut parte din comisia stiintifica a Olimpiadei de Informatica a Europei Centrale din 2000 care s-a desfasurat la Cluj. Dupa terminarea facultatii Catalin a lucrat patru ani ca programator la Google inc._\r\n\r\n_In aceasta prima parte a interviului, Cata ne vorbeste de olimpiade, de cartea \"Psihologia concursurilor de programare\" si despre \"Lista lu\' Francu\"._\r\n\r\n*Cum ai inceput cu informatica?*\r\n\r\nParintii mei au facut parte din primele generatii de la ICI, ceea ce si-a pus amprenta asupra mea si a fratelui meu. Prin clasa a 4-a am vazut prima oara un calculator ZX Spectrum. Mi-au placut mult jocurile, iar cu timpul am inceput sa ma intreb si cum sunt facute si daca as putea face si eu ceva asemanator. in clasa a 8-a, cand s-a pus problema sa-mi aleg un liceu, deja nu mai aveam dubii.\r\n\r\n*Erau alte discipline de care erai interesat in timpul scolii?*\r\n\r\nDa... in dictionar, langa definitia pentru \"tocilar\" este poza mea :) Am invatat multe prostii care acum imi dau seama ca au fost pierdere de vreme, dar unele materii chiar mi-au placut. De felul meu am fost atras de matematica si fizica. Muzica si biologia erau frumoase, dar erau predate foarte prost.\r\n\r\n*Cum si ce lucrai pentru olimpiade?*\r\n\r\nGeneratia mea (promotia 1996) n-a avut foarte multe resurse la indemana. Circulau colectii de probleme din anii trecuti, dar comunicarea intre olimpici era de baza, pentru ca unul afla de un algoritm interesant si il raspandea. Manualele domnului profesor Sorin Tudor au fost multa vreme \"Biblia\" mea; de altfel consider ca la vremea lor au fost pur si simplu avangardiste (si nu stiu cati profesori se pricepeau sa predea notiunile pe care le contineau acele manuale).\r\n\r\n*Ce persoane au avut o influenta in formarea ta?*\r\n\r\nParintii si fratele meu Cristi, in primul rand. Mi-amintesc ca eram prin clasa a 2-a, iar Cristi tocmai invata despre scheme logice si se chinuia sa mi le explice si mie. Mie imi placeau romburile cel mai mult, dar altceva n-am inteles. :) La liceu am avut multi profesori buni de informatica, dar in special doamna Rodica Cherciu si domnul Sorin Tudor. Este adevarat ca un profesor poate sa atraga sau sa sperie un elev, dupa cum isi preda materia. Nu in ultimul rand, la loturile de informatica au fost intotdeauna oameni deosebiti (elevi si profesori). in lumea olimpiadelor mi-am cunoscut multi dintre prietenii de astazi.\r\n\r\n*Mai tii minte probleme frumoase de la olimpiada?*\r\n\r\nMi-a placut intotdeauna, pentru simplitatea ei, problema acoperirii tablei cu L-triominouri (Se da o tabla cu dimensiunea de <tex>2^n \\ast 2^n</tex> din care s-a eliminat un patrat. Se cere ca restul sa se acopere cu L-triominouri). Am pus de multe ori aceasta intrebare la interviuri la Google si putini au stiut sa o rezolve in 10-15 minute. Problema care m-a determinat sa ma apuc serios de studiul algoritmilor este \"Se da un arbore neorientat. in fiecare nod se afla un bec. Initial toate becurile sunt stinse. Prin atingerea unui bec, el si toate becurile vecine isi schimba starea. Sa se identifice o ordine de atingere a becurilor astfel incat in final toate becurile sa fie aprinse.\"\r\n\r\n*Ce structura de date iti place cel mai mult?*\r\n\r\nE greu de raspuns la intrebarea asta. E mai important sa stii la ce e buna o structura de date decat sa-ti placa. De exemplu, am cunoscut oameni care nu suporta listele inlantuite si folosesc intotdeauna vectori, chiar si atunci cand au de facut insertii sau concatenari.\r\nCand folosesti Java si ambele structuri sunt deja implementate, si trebuie numai sa stii de ce tip sa declari variabila, aceasta reticenta este foarte daunatoare.\r\n\r\nPentru simplitatea implementarii, imi plac mult seturile disjuncte cu compresia caii (folosite, de exemplu, in algoritmul lui Kruskal pentru aflarea arborelui partial de cost minim). Analiza teoretica a complexitatii este foarte subtila.\r\n\r\n*Sunt olimpiadele folositoare?*\r\n\r\nEste iarba verde? :)\r\n\r\n*Cum e de partea cealalta a baricadei in concursurile de informatica, cand participi ca organizator?*\r\n\r\nAvem mai putin timp liber, pentru ca mereu e cate ceva de facut, dar satisfactiile si placerea sunt la fel de mari. Daca vreun student sau un profesor are un ceas liber, prefera sa implementeze o solutie pentru vreuna din probleme. Nu numai pentru ca e bine sa avem mai multe solutii pentru verificare, ci si din acea dorinta, care ne impinge pe toti la concursuri, de a ne masura fortele cu o problema noua.\r\n\r\n*Cum ti-a venit idea sa scrii \"Psihologia Concursurilor de Programare\"?*\r\n\r\nDomnul profesor Sorin Tudor a venit cu ideea sa-mi impartasesc cateva din experientele de la olimpiade. Pentru ca de aici nu aveau cum sa rezulte mai mult de 10-20 de pagini, m-am gandit sa adaug cateva structuri de date pe care le-am folosit destul de frecvent la concursuri si care nu erau discutate in manualele de liceu.\r\n\r\n*Cum ai ales structura cartii si problemele?*\r\n\r\nM-am gandit la cateva structuri de date, implementabile in timp de concurs, despre care elevii nu prea aveau de unde citi. Problemele alese fie exemplifica folosirea acestor tipuri de date, fie subliniaza unele alegeri care tin de psihologia fiecarui concurent. De exemplu, am gasit un algoritm greedy care merge pe toate exemplele mele, dar nu il pot demonstra matematic. il implementez sau nu? Sau am gasit un algoritm lent cu care stiu ca nu o sa iau punctaj maxim. il implementez sau caut altul mai bun?\r\n\r\n*Cat timp ti-a luat sa scrii cartea si cat de usor a fost sa o publici?*\r\n\r\nCateva luni, dintr-o vacanta de vara pana prin noiembrie. Publicarea nu a fost o problema, deoarece ideea cartii a venit tocmai de la Sorin Tudor, care avea propria editura. Mai problematica a fost tiparirea, pentru ca la migrarea pe alt calculator si pe alta imprimanta, se dadea peste cap toata paginarea (pe vremea aceea nu auzisem de LaTeX, de PDF, sau in general de altceva in afara de Microsoft Word).\r\n\r\n*A meritat efortul?*\r\n\r\nFara nici un dubiu! A fost una din primele mele slujbe platite, am castigat un ban facand ceea ce imi placea si a rezultat ceva palpabil si -- din cate aud -- folositor.\r\n\r\n*De ce ai inceput lista lui Francu?*\r\n\r\nIn 1996 am inceput (sau mai degraba am continuat, de unde l-a lasat fratele meu) un mic cerc de informatica. Cu timpul am inceput sa corespondam si prin email. Emailurile au capatat valoare in sine si am creat o lista de discutii dedicata.\r\n\r\n*Cum a evoluat lista si discutiile de pe lista de-a lungul timpului?*\r\n\r\nLa inceput, trimiteam probleme, asteptam o saptamana si corectam solutiile trimise. Perioada cea mai buna a listei, zic eu, a fost cand am introdus o notiune de \"coeficient\" (se numea DFCC si se masura in Dexteri). Dincolo de copilaria numelui, m-am straduit sa nascocesc un coeficient care scadea incet cu timpul, pentru a-i incuraja pe abonati sa trimita solutii la fiecare etapa.\r\n\r\n*De ce a murit?*\r\n\r\nPlecarea la MIT a fost \"inceputul sfarsitului\". Aveam mai putin timp liber si o vreme s-a ocupat Cristi Cadar de lista (de altfel, el a propus aproape jumatate din numarul problemelor). Ocazional au mai contribuit si alti \"ilustri\" ca Rodica Pintea, Valentin Gheorghita, Mihai Badoiu, Irina Dumitrascu, Bogdan Dumitru, Alex Susu...\r\n\r\nUn alt motiv a fost ca elevii care au participat initial la cercul de informatica au absolvit liceul, ceea ce mi-a redus mie motivatia de preparator. :) si nu in ultimul rand a fost aparitia altor site-uri, romanesti si internationale, dedicate problemelor de programare, cu evaluatoare automate etc. Ma bucur mult ca infoarena.ro incorporeaza majoritatea problemelor propuse pe lista, pentru ca ne-am gandit mult la ele si ar fi fost pacat sa se piarda.\r\n\r\n_A doua parte a interviului va fi publicata in curand._\r\n\r\n_In contextul interviului cu Cata (cum ii zic prietenii), infoarena are doua proiecte unde este nevoie de ajutorul vostru. Unul este transcrierea cartii \"Psihologia concursurilor de programare\" in format textile. Altul ar fi cel de transformare a problemelor din Lista lu\' Francu in formatul infoarena si de adaugarea lor in arhiva (au mai ramas vreo 10 probleme de adaugat). Aveti mai multe detalii \'aici\':implica-te/scrie-articole si \'aici\':implica-te/extinde-arhiva ._\r\n\r\n_In poza de mai sus apar \'Cristi Strat\':utilizator/wickedman , \'maestru\' Catalin, \'eu\':utilizator/cosmin , iar cenzurati sunt doi ilustrii necunoscuti :), se dau puncte de karma pe forum pentru cine ii identifica pe cei doi._\r\n\r\n',2028,'protected',2228,NULL),('blog/alta-problema-misto','Alta problema misto','2007-10-20 06:59:34','2008-11-16 12:56:17','Cum v-a placut prima problema, voi continua sa postez din cand in cand probleme interesante. Din cate imi amintesc, cred ca urmatoarea este de la olimpiadele rusesti ca si prima de altfel. Rusii au pe la concursuri tot felul de probleme cretze care par simple dupa ce le vezi solutia.\r\n\r\n_Avem opt lanterne ce emit lumina in forma unor \'triedre\':http://dexonline.ro/search.php?cuv=triedre drepte. Sa se demonstreze ca oricare ar fi pozitia lanternelor in spatiu (consideram lanternele ca niste puncte), exista o orientare a triedrelor de lumina astfel ca oricare punct din spatiu sa fie luminat de cel putin o lanterna._\r\n\r\nDiscutati problema la sectiunea de comentarii. In doua zile voi publica solutia mea, daca nu apare aceeasi solutie pe forum.\r\n\r\n',2028,'protected',2218,NULL),('blog/interviu-mihai-patrascu-partea-a-doua','Interviu cu Mihai Patrascu - partea a doua','2007-10-19 10:53:04','2008-11-16 13:05:12','!<blog/interviu-mihai-patrascu-partea-a-doua?mip-big.JPG! _Acum zece zile am publicat \'prima parte\':blog/interviu-mihai-patrascu-partea-intai a interviului cu \'Mihai Patrascu\':utilizator/mpatrascu . A venit timpul sa publicam si partea a doua. In ea Mihai ne vorbeste de olimpiade, de modul lui de lucru si de interese in afara programarii:_\r\n\r\n**Cum ai recomanda cuiva sa se antreneze pentru concursuri sau sa se pregateasca pentru cercetare?**\r\n\r\nCred ca cel mai eficient e sa ajungi sa programezi suficient de bine, si apoi sa te concentrezi pe gandirea teoretica la probleme. De prin clasa a 10a nu programam decat cateva zile inainte de olimpiada sa-mi intru in mana. Restul doar ma gandeam dar nu implementam (economiseste mult timp la pregatire).\r\n\r\nDin cauza asta nu am fost niciodata un programator prea rapid... In plus capacitatea mea de debug este aproape nula, asa ca preferam sa scriu foarte incet si fara buguri. N-as avea niciodata sanse la un concurs ca ACM sau top coder :)\r\n\r\n**Care e secretul reusitei la concursuri sau in cercetare? caracteristicile native, educatia profunda, munca depusa?**\r\n\r\nClar ca fara inteligenta nu se poate :), dar toti oamenii care ajung sa faca ceva la olimpiade sunt foarte inteligenti. Cred ca ce face diferenta la un nivel inalt e atitudinea personala. In mod constant erau oameni in lot pe care ii consideram mai destepti decat mine, dar eu eram mai hotarat sa castig, lucram mai mult cand trebuia sa lucrez, ma relaxam mai mult cand trebuia sa ma relaxez etc. Nici ceilalti concurenti, nici comisia nu sunt cu un cap mai sus ca tine -- daca tu ai incredere ca esti tare, atunci chiar esti mai tare.\r\n\r\n**Cum abordezi o problema, ai o reteta standard (generalizare, simplificare, trecerea prin o lista de tehnici) sau ai cate un \"aha\" moment?**\r\n\r\nNu, simt ca intotdeauna imi vin idei dubioase si fara explicatie. Problemele la care ma prindeam cel mai greu erau chestii clasice ca flux, cuplaj, etc -- pana sa ma gandesc ca de fapt poate se foloseste ceva standard imi lua ceva timp.\r\n\r\n**Cum se compune o problema de olimpiada?**\r\n\r\nFoarte greu... Am un dispret pentru problemele bazate pe materie avansata. Ne trebuie probleme noi, cu o rezolvare elementara, nu bazate pe ceva care inveti la facultate. Problemele trebuie sa fie cu adevarat concurs de perspicacitate, si ar trebui sa fie la fel de grele pentru un concurent din liceu si pentru un prof care studiaza algoritmi de 50 de ani... Din pacate, e greu de gasit astfel de probleme, si nu am propus prea multe probleme.\r\n\r\n**De ce nu ai continuat cu concursurile de programare in timpul facultatii?**\r\n\r\nConcursurile mi se par prin definitie ceva pentru liceu. La nivelul ala inca inveti, si e bine ca ceva sa te motiveze sa inveti, in timp ce iti ascuti inteligenta in domeniu. La facultate stii mai multe, si pot sa faci alte chestii mai important pentru tine si pentru omenire... Poti sa te angajezi, sa lucrezi in cercetare, etc. Poti sa-ti faci un renume la inceput cu IOI, dar pana la urma succesul in viata depinde de alte chestii.\r\n\r\nAsta gandeam inca din liceu, asa ca mi-a fost usor sa renunt. In treacat fie spus, am fost de 2 ori la ACM din inertie, o data cu Craiova, si o data la MIT. Amandoua esecuri lamentabile :) Cu echipa din Craiova problema era ca nimeni nu programa suficient de repede (in frunte cu mine). Cu MIT problema a fost interactiunea mea cu autoritatea :) -- am iesit primul la concursul individual, dar echipa s-a format din locurile 2,3,4 la decizia profilor coordonatori.\r\nRazbunarea mea a fost ca anul ala MIT-ul nu s-a calificat la regionala ;)\r\n\r\n**La ce alte proiecte software ai lucrat?**\r\n\r\nSingurul proiect mai mare care l-am facut a fost evaluatorul pentru olimpiade (nu stiu daca se mai foloseste, dar s-a folosit la BOI la Iasi si la cateva nationale). Restul totul au fost programe mici pt olimpiade. Si cand am lucrat pentru companii, am lucrat pe directii de cercetare unde nu trebuie decat programe mici prototip care sa testeze o idee.\r\n\r\n**Ai vreo metoda dupa care iti imparti timpul sau lucrezi cand si cum ai chef?**\r\n\r\nEu profit de libertatea din cercetare pana la punctul unde enervez pe toata lumea :) Daca n-am chef sa fac nimic saptamana asta, nu fac nimic saptamana asta. Ma duc la munte, citesc ceva, nu conteaza. Cand lumea munceste la o lucrare (care implica finalizat tot felul de detalii si scrisul propriu-zis), eu de obicei fac misto de ei :) De obicei nu reusesc nici macar sa scriu pe hartie niste calcule.\r\n\r\nDar daca am o idee de rezolvare in cap si vreau sa scriu o lucrare pentru o conferinta, am o reteta standard. Cu 2-3 zile inainte de deadline, imi iau periuta de dinti, 10-15 sticle de Pepsi Diet, cateva kg de prajituri, si ma duc in birou. Si acolo petrec cele 2-3 zile lucrand (am determinat ca rata optima de somn in birou e cam 2h pe zi). Adrenalina e foarte interesanta.\r\n\r\n**Citesti bloguri/frecventezi forumuri? Spune-ne cateva exemple.**\r\n\r\nChiar am si eu un blog la \'http://infoweekly.blogspot.com/\':http://infoweekly.blogspot.com/, in care discut probleme de cercetare in algoritmi. Cred ca unele chestii ar putea fi interesante pentru studentii la olimpiade in ani mai mari, care vor sa se decida ce vor sa faca in viitor. Pot sa vada cateva probleme si sa vada daca ii tenteaza teoria.\r\n\r\nDe citit, citesc cateva bloguri din teorie, dar nu cu prea multa pasiune (doar ca e util sa te tii la curent). La forumuri nu particip.\r\n\r\n**Ce interese, hobbyuri, pasiuni care nu sunt legate de programare ai?**\r\n\r\nA, multe... Desi intotdeauna stau rau cu timpul, asa ca fac mai putine decat as vrea. Imi place foarte mult sa calatoresc, si acum pot sa fac asta cu toate conferintele la care ma duc (am ajuns in 28 de tari pana acum). Imi place sa vorbesc cu lumea, sa descopar culturi noi, si imi place sa citesc mult despre istorie.\r\n\r\nPeriodic descopar pasiuni pt un nou sport. In liceu mergeam pe munte si jucam badmington, apoi am facut alergari (era o vreme cand alergam 16km pe seara), am jucat rugby (in Divizia 3 din State), mai recent climbing si sailing.\r\n\r\n**Pe ce te concentrezi acum?**\r\n\r\nAnul asta voi termina doctoratul... Trebuie sa scriu o teza si sa aplic pentru joburi (in pricipal, o sa aplic pentru joburi de prof la universitati). Asta ia destul de mult timp. In rest, mai lucrez la cercetare, si mai calatoresc.\r\n\r\n**Cum tii pasul cu cercetarea curenta? Sunt conferintele importante si discutiile cu ceilalti cercetatori (comunitatea din care faci parte), sau e deajuns sa citesti research paperurile ce apar?**\r\n\r\nSunt cateva conferinte importante la care ma duc intotdeauna. Problema e ca nu pot sa stau intr-o sala si sa ascult o prezentare (lipsa de concentrare). Asa ca in timpul conferintei ma intalnesc cu prieteni vechi care de asemenea nu vor sa fie prezenti, si mergem la bere sa mai discutam probleme. Ca sa aflu ce se intampla citesc lucrari pe Net.\r\n\r\n**Cum te vezi in 5-10 ani?**\r\n\r\nSper ca cu un job :) Planul este sa lucrez in continuare in domeniu si sa mai rezolv cateva probleme importante. Apoi as vrea sa incerc si sa fondez o companie cu o idee trasnet. Avem multe rezultate valoroase in teorie, care nu se aplica pentru ca lumea nu se gandeste suficient la impactul mai larg si nu gaseste aplicatiile bune. Daca imi vine vreo idee buna la capitolul asta nu voi ezita sa incerc o companie, in paralel cu jobul de prof.\r\n\r\n**Vrei sa le transmiti ceva celor ce acum incep cu viata competitionala?**\r\n\r\nE sansa voastra sa aratati lumii ce tari sunteti, si sa deveniti si mai tari pe parcurs. E un drum bun in viata.\r\n\r\n_Ii multumim lui Mihai pentru un interviu foarte interesant._\r\n\r\n',2028,'protected',2217,NULL),('blog/olimpiada-internationala-de-informatica-2007-jurnal-de-bord','Olimpiada Internationala de Informatica 2007 - jurnal de bord','2007-10-17 09:28:17','2008-11-16 13:06:27','_L-am rugat pe \'Andrei Grigorean\':utilizator/wefgef sa ne scrie un jurnal despre experienta lui la \'Olimpiada Interantionala de Informatica\':http://ro.wikipedia.org/wiki/Olimpiada_Interna%C5%A3ional%C4%83_de_Informatic%C4%83. Initial ma gandeam ca ar fi misto sa ne zica aproape live ce s-a intamplat in fiecare zi :), dar asta ar fi adaugat la stresul competitiei. Astfel am fost bucuros cand s-a oferit sa faca un rezumat dupa concurs, apoi am fost si mai bucuros cand l-a terminat. Multumim Andrei! Acum puteti sa il cititi si voi:_\r\n\r\nh2. IOI 2007\r\n\r\nIn perioada 15-22 august 2007 am avut ocazia de a participa la \'cea de a XIX-a editie a Olimpiadei Internationale de Informatica\':http://www.hsin.hr/ioi2007/ , desfasurata in capitala Croatiei, Zagreb. Ceilalti trei membri ai lotului Romaniei au fost: \"Cosmin Gheorghe\":/utilizator/gcosmin, \"Bogdan Tataroiu\":/utilizator/bogdan2412 si \"Adrian Airinei\":/utilizator/astronomy. Am fost insotiti de prof. Emanuela Cerchez (Team Leader) si de \"Mugurel Ionut Andreica\":/utilizator/mugurelionut (Deputy Leader).\r\n\r\nh2. Acomodarea\r\n\r\nIn data de 15 august, la ora 4:30 dimineata, ne-am intalnit cu totii la aeroportul international \"Henri Coanda\" din Otopeni. Am zburat pana in Budapesta, unde am schimbat avionul pentru a ajunge in Zagreb. Am aterizat in Croatia pe la amiaza si am fost una din primele delegatii sosite. Un autocar ne astepta in fata aeroportului si am fost dusi in complexul unde am fost cazati si unde am luat masa timp de o saptamana. Am stat cate doi in camera, eu impreuna cu Cosmin, respectiv Bogdan cu Adrian, si imparteam aceeasi baie. Conditiile nu erau extraordinare, insa nici nu ne puteam plange - erau totusi camine studentesti. In privinta mancarii insa, am doar cuvinte de lauda. Puteam servi oricat doream din mese diverse, foarte gustoase. Am mancat foarte mult la IOI, mai ales eu si Cosmin :P.\r\n\r\nh2. Competitia\r\n\r\nInainte cu o zi de a incepe competitia a avut loc sesiunea de pregatire. Scopul acestui eveniment este familiarizarea cu sistemul folosit in concursul real si oarecum o usoara \"incalzire\" a concurentilor. Am avut posibilitatea de a implementa si submita timp de doua ore cele trei probleme afisate pe site-ul olimpiadei cu trei saptamani inainte. Totul a decurs bine, cu exceptia catorva probleme cu Rhide-ul.\r\n\r\nApoi a venit prima zi de concurs. Eu personal ma asteptam sa fie probleme interesante si asa a si fost. Am primit doua batch-uri si o problema interactiva. Dupa o scurta trecere in revista, am decis sa aboredez mai intai problemele sails si flood. Dupa doua ore si jumatate nu gasisesm nicio rezolvare, moment in care m-am hotarat sa incerc aliens. Dupa aproximativ o jumatate de ora gasisesm rezolvarea si am inceput sa implementez. Pana la sfarsitul concursului nu am mai reusit sa gasesc solutiile optime la sails sau la floodm asa ca am trimis rezolvari brute-force (la flood am terminat de implementat cu 5 minute inainte de final). Rezultatele din prima zi au fost conform asteptarilor: Cosmin - 235 pct (a facut sails de 100), Bogdan - 172 pct, eu - 145 pct si Adrian - 120 pct. Dupa estimarile mele aveam un aur, un argint si doua medalii de bronz cu aceste punctaje. Nu am reusit niciunul sa rezolvam problema flood, desi dupa ce am auzit solutia mi se parea mai simpla decat estimasem initial. Si punctajele obtinute de ceilalti concurenti aratau ca sails fusese cea mai grea din prima zi, nu flood.\r\n\r\nA doua zi de concurs a fost putin diferita de prima. Am primit trei batch-uri, de dificultate variata. Miners era clar problema simpla, imediat cum am citit-o am si implementat-o. S-a dovedit ca peste 100 de concurenti au luat maxim la ea. Pairs era de fapt compusa din trei subprobleme independente - am gasit rezolvarea in timp util la toate, insa trebuia sa implementez arbori de intervale 2D, asa ca am decis sa o las la urma si sa incerc sa rezolv training. Aceasta a fost cea mai grea problema din concurs, cu doar 3 punctaje maxime :). Nu am reusit sa gasesc solutia optima, asa ca dupa ce am implementat o sursa care lua 30 de puncte, m-am intors la pairs. Faptul ca nu am implementat pana la urma ultima subproblema, si ca am uitat sa pun un -1, au facut ca punctajul meu in a doua zi sa fie de 172 de puncte. Adrian si Bogdan au luat 200, iar Cosmin 150.\r\n\r\nh2. Excursii\r\n\r\nDupa fiecare zi de concurs, organizatorii ne-au dus in doua excursii care mie mi-au placut foarte mult. Prima din ele a fost la un lac unde se pregateau sportivii croati pentru diferite sporturi pe apa (gen canoe). Acolo ne-am petrecut jumate de zi. Eu si Adrian, impreuna cu 3 bulgari, am jucat fotbal cu rusii, care aveau o mare vedeta in echipa - \"Petr Mitrichev\":http://www.topcoder.com/tc?module=MemberProfile&cr=10574855&tab=alg. Daca la informatica nu am fost mai buni, macar la fotbal i-am batut... de doua ori :D. Se mai putea juca badminton, tenis de masa - a fost un fel de picnic cu vreo 400 de persoane.\r\nA doua excursie a durat o zi intreaga. Am vizitat Lacurile Plitvice si casa memoriala Nikola Tesla. Puteti vedea cateva poze \"aici\":http://www.liis.ro/~marinel/2007/ioi2007/ioi/ema/index2.html. Peisajele erau superbe, aratau mai bine in realitate decat in poze. Am fost la cea mai mare cascada din Croatia (din pacate nu apare in album), iar dupa masa am ajuns la casa memoriala a faimosului om de stiinta - pe mine nu m-a impresionat prea tare, nu aveau o modalitate atractiva de a prezenta informatia.\r\n\r\nh2. Sfarsit de poveste\r\n\r\nCu punctajele noastre am obtinut pana la urma cu totii medalii de argint, sa speram ca in anii urmatori Cosmin si Bogdan, impreuna cu ceilalti participanti la IOI, vor face mai bine decat am facut noi anul acesta. Ne-am intors acasa pe data de 22 august pe aeroportul \"Henri Coanda\", unde ne asteptau parinti, profesori, reprezentanti Intel si presa. Si-am incalecat pe-o sa, si v-am spus povestea asa.\r\n\r\n_*Felicitam echipa Romaniei inca o data pentru rezultatul obtinut* si mentionam ca dupa olimpiada, cei doi seniori ai echipei (\'Andrei Grigorean\':utilizator/wefgef si \'Adrian Airinei\':utilizator/astronomy ) s-au alaturat \'echipei infoarena\':echipa-infoarena ._\r\n\r\n',2028,'protected',2210,NULL),('blog/robocup','RoboCup 2008','2008-01-20 02:53:32','2008-11-16 12:53:41','!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/robocup?robocup.JPG 73%!\r\n\r\nMihai Oltean, proful ce mi-a coordonat licenta si pe care s-ar putea sa il cunoasteti ca autor al cartilor \"Algoritmi, Proiectare si Programare\" si \"Programarea jocurilor matematice\", a avut 15 minute de celebritate saptamana trecuta, aparand pe mai multe canale de televiziune la stiri. El a organizat un concurs intre studentii ce au urmat cursul de \"Roboti inteligenti\". Studentii trebuiau sa programeze diversi roboti echipati cu senzori sa iasa dintr-un labirint. Inca nu l-am prins pe Mihai online sa il intreb daca nereusita robotului sa iasa afara din labirint insemna picarea examenului, da e o idee interesanta.\r\n\r\nMai multe despre eveniment gasiti \'aici\':http://www.cs.ubbcluj.ro/~moltean/roboti/\r\n\r\nFelicitari Mihai pentru organizarea unui eveniment reusit, sper ca acest concurs sa se repete si in anii urmatori!\r\n\r\n==Youtubevideo(id=\"Ml74mIYrrAw\" width=\"425\" height=\"355\")==\r\n',1851,'protected',2587,NULL),('blog/worse-than-we-feared','Worse than we feared!','2008-01-20 23:48:25','2008-11-16 12:58:16','==Youtubevideo(id=\"CmYDgncMhXw\" width=\"425\" height=\"355\")==',1851,'protected',2608,NULL),('blog/epilog-bogdan-patrut','Epilog','2008-03-15 01:26:23','2008-11-16 13:02:29','Acum _10 ani_ am publicat un manual de Programarea calculatoarelor electronice (la Teora, dupa programa de atunci de clasa a X-a). Am scris atunci un epilog la acel manual, pe care editorii nu l-au inclus. Probabil considerau ca e nepotrivit. Le-am inteles decizia.\r\n\r\nEditura InfoData din Cluj doreste sa republice acest manual al meu. Cartea se va numi \"Tehnici de programare si structuri dinamice de date\". Doresc (in numele meu personal, ca si al colaboratorului meu, editorul) sa va cer sfatul in privinta daca ar fi bine sau nu ca acest epilog sa fie inclus in carte.\r\nMultumesc!\r\n\r\n*Bogdan Patrut*\r\n\r\nh3=. Epilog\r\n\r\nNe punem intrebarea, la finalul acestei carti: este utila o asemenea carte? Si daca da (sau daca nu), ne intrebam si de ce.\r\n\r\nCartea pe care o aveti in maini este un manual de Programarea calculatoarelor. Un manual se adreseaza unui grup oarecum restrans de cititori, prin insasi denumirea sa de manual. Aici, manualul se adreseaza elevilor de liceu (clasa a X-a) si profesorilor sai, care studiaza la clasele de informatica. Astfel de clase exista (si existau) in liceele de informatica, dar exista si in acele licee teoretice sau chiar industriale, economice si au aparut mai ales dupa Revolutie, din dorinta conducerilor liceelor de a atrage elevi buni in clasa a IX-a.\r\n\r\nCat de pregatiti au fost acesti elevi pentru viitorul lor dialog cu calculatorul e greu de stabilit. Cat de bine pregatiti pentru profesia pe care o vor urma la finele liceului, daca ea va fi in domeniul informaticii sau va avea in vreun fel sau altul tangenta cu informatica si calculatorul, vom vedea peste cativa ani.\r\n\r\nDin experienta ultimilor ani de invatamant preuniversitar informatic se pot trage mai multe concluzii.\r\n\r\nIn primul rand, se observa ca foarte multi elevi doresc sa urmeze profilul informatica, chiar daca unii dintre ei nu au vazut sau nu au folosit vreodata un calculator.\r\n\r\nSunt multi altii care au avut posibilitatea de a folosi un calculator personal, fie la ei acasa, fie la serviciul unuia dintre parinti, fie chiar in scoala generala sau pe la vreun cerc de copii. Dar cati dintre acestia au trecut de stadiul de a vedea in calculator o simpla jucarie, poate cea mai scumpa jucarie? Putini. Dintre acestia, si mai putini au incercat sa utilizeze calculatorul, in sensul de a opera cu diferite programe utilitare, cu Windows, cu programe de grafica sau editoare de texte.\r\n\r\nAcestia din urma ne bucura, deoarece ei sosesc in clasa a IX-a cu un bagaj de cunostinte si o experienta in folosirea calculatoarelor. Desi au fost acumulate dezorganizat, haotic (ceea ce presupune existenta unor mari lacune in cultura lor informatica), cunostintele pe care le au micii viitori informaticieni din clasele a IX-a le sunt de mare folos. Dar diferenta intre acestia si cei ce nu au folosit pana atunci un calculator devine repede nesemnificativa, chiar pe parcursul primului trimestru de liceu. Evident, a lucra cu un calculator nu e mare filosofie, iar copiii, care nu au atata teama, atata neincredere, ca adultii, ci dimpotriva sunt mult mai inventivi, mai curiosi sau mai increzatori, invata repede sa faca cine stie ce minuni cu un calculator electronic.\r\n\r\nMulti copii vin la profilul informatica, crezand ca se vor juca la calculatoare. Pur si simplu! Altii viseaza ca vor explora o lume fascinanta nebanuita, ca in serialele stiintifico-fantastice, iar altii cred ca vor explora Internetul toata ziua.\r\n\r\nSi scoala incepe. Vine profesorul de informatica si incepe sa le vorbeasca despre constante, variabile, expresii, tipuri de date sau despre instructiunea de atribuire. Elevii devin seriosi, crezand ca acesta e doar inceputul, ca urmeaza ceva fascinant.\r\n\r\nSi, intr-adevar, acela era doar inceputul. Se preda instructiunea if, apoi entuziasmul elevilor incepe sa dispara. Cand se ajunge la while, deja unii nu mai inteleg nimic sau nu mai pot tine pasul.\r\n\r\nE clar. Ceva se intampla. In orice caz, elevii isi dau seama ca informatica nu este o joaca. Sau cel putin programarea. E ceva ca la \"mate\". E ceva greu. Unii se apuca de carte. Altii prefera sa astepte prima ora de laborator, sau macar prima ora de Sisteme de calcul, unde parca e mai simplu. Si mai util. Da, mai util. Iata cuvantul magic.\r\n\r\nSimtul practic este o caracteristica a generatiei actuale de elevi. Ei nu inteleg, nu accepta (in marea lor majoritate) sa invete ceva care nu le este de folos. Incercarea profesorului de a explica ca toate aceste lucruri pe care le preda sunt utile, pentru ca ele stau la baza tuturor produselor software realizate de firme americane sau internationale, nu duce la nimic. Elevul o tine tot pe a lui, argumentand cu replici care demonstreaza lipsa sa de motivatie intrinseca a invatarii.\r\n\r\nE greu sa demonstrezi unui elev ce poti face cu toate if-urile sau while-urile pe care i le predai. Elevul te poate intreba: Stiti sa faceti un joc, domnule profesor? Dar un Windows sau macar o parte din el (sa zicem programul Notepad)?\r\n\r\nE greu sa raspunzi la o asemenea provocare, e greu sa le raspunzi in general. Ajungi la finele clasei a IX-a si constati ca, la Algoritmi si limbaje de programare, nu mai lucrezi decat cu o treime din clasa. Restul se prefac ca inteleg sau ca invata, tu te faci ca ii asculti sau ca ii notezi.\r\n\r\nUrmeaza clasa a X-a, unde la Programarea calculatoarelor continui cu materia de anul trecut, iar aici ii inveti si mai mult sa analizeze, sa gandeasca o problema. Pe cine? Pe doar cei o treime din clasa, care stapanesc sintaxa si semantica limbajului Pascal, care stiu sa ordoneze un vector sau sa determine cel mai mic element dintr-o matrice.\r\n\r\nCeilalti incearca sa invete pe de rost problema damelor sau sortarea prin interclasare, iar asta nu pentru ca nu au inteles algoritmul, ci pentru ca nu stiu sa-l transpuna in program. (In treacat fie spus, niciodata nu am inteles de ce considera ei atat de greu formalismul unui limbaj pentru implementarea unui algoritm.).\r\n\r\nDin cei cu care ai ramas sa lucrezi, majoritatea incep sa scrie programe de grafica. Nimic rau in asta, unii ajung la performante deosebite, realizeaza jocuri, sunt premiati pe la diferite concursuri nationale sau interjudetene, dar se limiteaza doar la atat.\r\n\r\nMai raman cativa. Acestia, foarte putin la numar, sunt olimpicii. Pentru ei, materia de Programarea calculatoarelor este o pasiune. Insa, ei inteleg repede ce le predai, prin urmare va fi nevoie sa te abonezi la gazeta sau sa cauti carti cu probleme grele. Sau sa inventezi tu. Ei iti aduc satisfactia ca nu predai chiar la pereti.\r\n\r\nAcestia sunt elevii care gandesc. Pentru ca ei sa fie stimulati sa-si foloseasca gandirea trebuie ca multumirea si satisfactiile lor sa nu fie doar acelea ale castigarii unui premiu la olimpiada, o excursie sau intrarea fara concurs la o facultate sau alta.\r\n\r\nPragmatismul lor cere altceva: cere o slujba in care sa-si foloseasca cu succes cunostintele si mai ales capul. Deocamdata asa ceva nu exista in Romania. De aceea pleaca. Stiti unde...\r\n\r\nCe fac ceilalti. Ceilalti termina liceul. Multi dintre ei au prins din zbor unele chestii care li se cer la locul de munca, acolo unde \"cei de la firma\" zic ca \"am mai vazut eu dintr-astia de la informatica, care nu stiu nimic\". Acolo ti se cere sa stii. Ce? Sa lucrezi cu nu stiu ce varianta de nu stiu ce program, care au aia nevoie acolo. Sau sa faci service, sa desfaci si sa asamblezi calculatoare.\r\n\r\nChiar daca inteleg sau nu programarea, elevii care termina informatica sunt o elita.\r\n\r\nUnii au nevoie de cunostinte pentru slujbele lor viitoare. Altii au nevoie de slujbe pentru cunostintele lor.\r\n\r\nSa se auda acolo unde trebuie!\r\n\r\n\r\n\r\np>. *Bogdan Patrut*\r\n\r\n\r\nP.S. Am discutat despre lipsa de motivatie a elevului de a invata programarea. Nu am discutat, insa, despre motivatia profesorului de a o preda. Am fi raspus astfel la intrebarea: de ce pleaca tot mai multi tineri informaticieni din invatamant?',2028,'public',2865,NULL),('blog/preoni-2008-deschiderea','PreONI 2008: Deschiderea','2008-03-21 21:52:17','2008-11-26 12:30:19','!>blog/preoni-2008-deschiderea?IMG_1354.JPG 200x200!:http://picasaweb.google.com/valentin.stanciu/PreONI2008#5181955588066252178\r\n\r\nAstazi s-a dat startul finalei PreONI 2008 prin festivitatea de deschidere care a avut loc in Sala Senatului din Rectoratul Universitatii Politehnica Bucuresti. Atmosfera a fost una destinsa si toata lumea nerabdatoare in asteptarea unei noi editii a celui mai important concurs al comunitatii noastre.\r\n\r\n\'Cristian Strat\':utilizator/wickedman a luat primul cuvantul de la microfon, urand bun-venit tuturor la finala PreONI in numele infoarena si al partenerilor sai: \'UPB\':http://www.pub.ro si \'Adobe Romania\':http://www.myadobe.ro. Cristi i-a felicitat pe cei 40 de participanti pentru prestatia avuta in rundele concursului desfasurate online.\r\n\r\nIn continuare a vorbit Nicolae Tapus, pe care cei mai multi dintre noi il cunosc in calitate de presedinte al \'ACM Romania\':http://www.acm.ro. Dupa urarile de rigoare, acesta a prezentat pe scurt Universitatea Politehnica. Am aflat ca acolo invata 26.000 de studenti la licenta, masterat si doctorat in cadrul unor domenii ca:\r\n\r\n* Inginerie Electrica\r\n* Automatica si Calculatoare\r\n* Mecanica\r\n* Electronica, Telecomunicatii si Tehnologia Informatiei\r\n* Inginerie in Limbi Straine\r\n\r\nDomnul Tapus le-a expus pe scurt celor prezenti satisfactiile si posibilitatile pe care li le ofera o cariera in domeniul informaticii, asigurandu-i de nivelul ridicat al institutiei in cadrul careia activeaza.\r\n\r\nIn continuare, s-au adresat audientei reprezentantii companiei Adobe. Alexaxndru Costin a pornit, dupa mai multe incercari lipsite de succes, o afacere care a fost in cele din urma cumparata de actualul sau angajator. Nu a reusit sa ajunga la ONI (a participat la Olimpiadele Judetene in Vaslui), dar i-a asigurat pe elevii care il ascultau ca prin munca si perseverenta in depasirea obstacolelor care apar pe drum poti reusi sa infirmi pronosticurile care nu iti dau multe sanse de reusita. Exemplul sau (care include si mai multe interviuri ratate) confirma acest lucru.\r\n\r\nMihai, unul dintre colegii sai de facultate, impreuna cu care a pus bazele firmei \'InterAkt\':http://www.interaktonline.com/, ne-a povestit despre interesul pe care l-a avut in liceu pentru olimpiadele de Matematica, Informatica si Chimie. Cu toate ca s-a descurcat mai mult decat onorabil la facultate, pasiunea sa pentru antreprenoriat a fost mai puternica si nu regreta acest lucru. De aici a pornit o discutie intre domnul Tapus si cei doi angajati ai Adobe, in urma careia a rezultat ca sunt cu totii de acord ca facultatea are un rol fundamental in educatia si viata oamenilor, si ca nimeni nu descurajeaza un traseu mai conventional in perioada studentiei.\r\n\r\n!>blog/preoni-2008-deschiderea?IMG_1377.JPG 200x200!:http://picasaweb.google.com/valentin.stanciu/PreONI2008#5181955880124028514\r\n\r\nLa final, \'Mircea Pasoi\':utilizator/domino a vorbit despre aspectele tehnice ale concursului din urmatoarele doua zile. In sala s-a auzit un usor oftat cand a spus ca probele dureaza 5 ore din cauza dificultatii lor mai mari decat a celor precedente. Concurentii au aflat ca vor primi rezultatele duminica si ca evaluarea va avea loc LIVE in sala in care s-a tinut si festivitatea de deschidere. Discutia s-a mutat in domeniul sistemelor de operare si mediilor de programare, motiv pentru toata lumea sa rada la o gluma despre Borland C++. Recent incheiata Olimpiada Judeteana de Informatica e probabil inca proaspata in memoria elevilor.\r\n\r\nTot Cristi a pus capat \"zilei 0\" din cadrul PreONI, anuntand o serie de surprize: tricoul InfoArena (o premiera!), cadourile din partea Adobe si o iesire la film sambata seara. Dupa o pauza de socializare s-a mers la cantina pentru a lua cina, urmand ca gasca sa se sparga: concurentii la casele / camerele lor iar comisia inapoi in laboratoare, pentru a se asigura ca totul va decurge perfect maine.\r\n\r\nMult succes si distractie placuta celor care participa la PreONI 2008!\r\n\r\n\'_Vezi galeria foto de la deschiderea PreONI 2008!_\':http://picasaweb.google.com/valentin.stanciu/PreONI2008\r\n\r\n*Tiberiu Florea* - \'greco.ro\':www.greco.ro',1490,'protected',2911,NULL),('blog/protocoale-de-securitate','Protocoale de securitate','2008-04-20 10:33:08','2008-11-16 13:09:03','_Discutam cu Stefan Ciobaca, pe care il stiu de cand participam amandoi la Bursele Agora, si mi-a venit ideea sa scrie si el un post pe blogul infoarena. Stefan are cateva medalii la olimpiade internationale si un premiu intai la concursul Bursele Agora, a fost in comisii la ONI, Lot si la .campion. El a facut doua internshipuri pe vara la Microsoft si acum este in perioada de practica a masterului la ENS Cachan in Paris. Puteti sa ii cititi blogul_ {\'aici\':http://nothingintoinsight.blogspot.com/}. _Mai departe ii dau cuvantul._\r\n\r\nCosmin m-a rugat sa scriu un _guest-post_; am decis sa fac o scurta introducere in domeniul cu care ma ocup la _LSV_ (\'www.lsv.ens-cachan.fr\':http://www.lsv.ens-cachan.fr).\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<cosmin/stefan?poza-infoarena.jpg 20%!\r\n*Protocoalele de securitate* (numite de asemenea *protocoale criptografice*) sunt mici programe care ruleaza intr-o retea cu ajutorul carora participantii pot comunica in mod \"sigur\". Desigur, o definitie mai vaga nici ca se putea.\r\n\r\nPentru a intelege despre ce e vorba, voi lua un exemplu clasic de protocol de tip _challenge-response_. Sa presupunem ca doi agenti A si B (Alice si Bob), au stabilit in prealabil o parola K (de exemplu K ar putea fi \"stupidduck\" sau \"03031984\") cunoscuta de amandoi (si de nimeni altcineva) si acum vor sa comunice intre ei. Alice doreste sa fie sigura ca vorbeste cu Bob. In acest sens, ei decid sa execute urmatorul protocol:\r\n\r\np=. A -> B: enc(n, K)\r\nB -> A: enc(n + 1, K)\r\n\r\np=. [enc(x, y) denota criptarea lui x cu parola y.]\r\n\r\nAlice este cea care initializeaza convorbirea si vrea sa se asigure ca vorbeste cu Bob. In acest scop, genereaza un numar aleator n si ii trimite lui Bob mesajul obtinut prin criptarea lui n cu parola K (partea de \"challenge\"). Stiind K, Bob poate decripta mesajul primit, afland in acest fel valoarea lui n. Bob calculeaza apoi n+1, cripteaza noul numar folosind parola K, si ii trimite inapoi lui Alice rezultatul (\"response\").\r\n\r\nDupa executia acestui protocol, Alice \"stie\" ca a vorbit cu Bob. Rationamentul ei are urmatoarea forma: \"_Am generat un numar aleator n, l-am criptat cu parola K (pe care o stiu doar eu si cu Bob). Am primit inapoi n+1 criptat cu parola K. Singura posibilitate de a primi n+1 este ca cineva sa fi aflat valoarea lui n si sa fi adaugat 1, apoi sa recripteze mesajul cu K. Ori acel cineva putea fi doar Bob, deci vorbesc cu el._\"\r\n\r\nDesi este gresit (vom vedea in continuare de ce), acest rationament ne ajuta sa descoperim cateva lucruri despre *modelul abstract* in care studiem securitatea protocolului (in literatura de specialitate abstractiile folosite aici sunt reunite sub denumirea de *modelul simbolic*).\r\n\r\nIn primul rand, presupunem ca un atacator are puteri depline asupra retelei (intr-un anumit sens, presupunem ca atacatorul _este_ reteaua). Atacatorul poate intercepta mesaje, poate crea mesaje noi, poate sterge mesaje, poate trimite mesaje mai vechi, etc. Acest model al atacantului este putin exagerat, dar sanatos.\r\n\r\nAlta observatie de bun simt pe care o facem este ca Alice are incredere ca Bob a pastrat secreta parola K. Intr-adevar, daca Bob este corupt, protocol nu mai are sens.\r\n\r\nInca un lucru care merita remarcat: presupunem ca primitivele de criptare sunt perfecte: atacatorul nu poate deduce nici un fel de informatie despre continutul unui mesaj cifrat, decat daca cunoaste parola. Desi aceasta presupunere este incorecta in practica (intamplator si in teorie, dar nu intram aici in detalii), o folosim deoarece multe atacuri se folosesc strict de structura protocolului, tratand primitivele criptografice (criptarea in cazul nostru) ca niste cutii negre.\r\n\r\nVoi prezenta in continuare un atac simplu asupra protocolui de mai sus. Atacul presupune ca parola K, stabilita in prealabil de Alice si Bob, are o dimensiune \"relativ mica\". Aceasta presupunere este naturala, deoarece un om nu poate sa retina un lucru complicat (alege ca parola o combinatie de cuvinte cunoscute, o data de nastere, un cod stil PIN, etc).\r\n\r\nEve (asa ii spunem atacatorului) intercepteaza o conversatie intre Alice si Bob si tine minte enc(n, K) si enc(n+1, K). Deoarece parola este de dimensiune relativ mica, Eve foloseste un dictionar pentru a genera toate parolele posibile (lasa calculatorul sa ruleze peste noapte). Pentru fiecare parola generata, Eve face un test simplu: cand decripteaza primul mesaj, adauga 1 si recripteaza rezultatul, obtine al doilea mesaj? Daca da, a dat (cu o probabilitate mare) peste parola folosita de Alice si Bob.\r\n\r\nIn atacul prezentat, Eve a fost un atacator pasiv: nu a modificat, creat, sau sters mesaje din retea. Tipul de atac lansat de Eve se numeste _offline guessing attack_. _Guessing attack_ deoarece atacatorul \"ghiceste\" valorile posibile ale parolei; _offline_ pentru ca testeaza daca a nimerit o parola corecta fara sa interectioneze cu Alice si cu Bob.\r\n\r\nCa un exercitiu, puteti sa dati exemplu foarte cunoscut de protocol care ar putea fi susceptibil unui _online guessing attack_ si puteti preciza cum e (sau cum poate fi) prevenit un astfel de atac in practica?\r\n\r\nDupa cum vedeti, un protocol simplu poate fi susceptibil la atacuri suficient de subtile incat sa cerem o demonstratie formala a securitatii lui. Din pacate, desi _mult_ mai buna decat o argumentatie informala asupra securitatii, o astfel de demonstratie nu ne asigura decat... o demonstratie... intr-un anumit model. Modelul este o abstractie tractabila a realitatii; spre deosebire de model, realitatea e cruda.\r\n\r\n!cosmin/stefan?alice_and_bob.png 40%!:http://xkcd.com/177/\r\n\r\nClick pe poza pentru un comic strip de pe xkcd.com\r\n\r\nMai mult, e greu de spus ce inseamna *securitate*: diverse protocoale pot avea diverse cerinte; printre proprietatile de securitate cele mai studiate sunt: _confidentialitate_ ({_secrecy_}) -- atacatorul nu afla un anumit lucru, _autenticitate_ ({_authenticity_}) -- stim cine este emitatorul unui mesaj, _anonimat_ -- un utilizator nu doreste ca toata lumea sa afle ce vrea sa faca.\r\n\r\nDespre protocoale de securitate se pot spune multe lucruri interesante, dar deocamdata inchei aici. Sper ca am reusit sa va castig atentia si ca subiectul vi se pare interesant. Ca un exercitiu de gandire, va las placerea sa descoperiti cum se poate concepe un protocol de tip _challenge-response_ similar ca scop protocolului descris aici, dar astfel incat sa nu fie susceptil la un _atac de dictionar_ ({_guessing attack_} = {_atac de dictionar_}, in romana).\r\n\r\nAstept comentariile voastre.',2028,'protected',3011,NULL),('bogdan2412/cache-stress-test','bogdan2412/cache-stress-test','2008-11-16 09:46:52','2008-11-16 09:47:49','==include(page=\"/blog/a-trecut-si-olimpiada\")==\r\n\r\n==include(page=\"/blog/alt-demo-de-la-microsoft\")==\r\n\r\n==include(page=\"/blog/alta-problema-misto\")==\r\n\r\n==include(page=\"/blog/alta-problema-misto-solutie\")==\r\n\r\n==include(page=\"/blog/avem-comentarii\")==\r\n\r\n==include(page=\"/blog/bloguri-microsoft\")==\r\n\r\n==include(page=\"/blog/bubblebubble\")==\r\n\r\n==include(page=\"/blog/captchauri-pentru-matematicieni\")==\r\n\r\n==include(page=\"/blog/cateva-scurte\")==\r\n\r\n==include(page=\"/blog/ce-am-invatat-din-3-oni-uri\")==\r\n\r\n==include(page=\"/blog/ce-se-intampla-cu-olimpicii\")==\r\n\r\n==include(page=\"/blog/certificari\")==\r\n\r\n==include(page=\"/blog/comentarii\")==\r\n\r\n==include(page=\"/blog/cplusplus-introducere-in-standard-template-library\")==\r\n\r\n==include(page=\"/blog/cum-fac-altii\")==\r\n\r\n==include(page=\"/blog/cunoasterea-pe-net\")==\r\n\r\n==include(page=\"/blog/cutremur-in-california\")==\r\n\r\n==include(page=\"/blog/de-ce-python\")==\r\n\r\n==include(page=\"/blog/de-ce-sa-participi-la-acm-icpc\")==\r\n\r\n==include(page=\"/blog/demouri-tari-de-la-siggraph\")==\r\n\r\n==include(page=\"/blog/despre-olimpici\")==\r\n\r\n==include(page=\"/blog/dexonline\")==\r\n\r\n==include(page=\"/blog/drumuri-lungi\")==\r\n\r\n==include(page=\"/blog/epilog-bogdan-patrut\")==\r\n\r\n==include(page=\"/blog/ginfo-a-murit\")==\r\n\r\n==include(page=\"/blog/google-code-jam-2008\")==\r\n\r\n==include(page=\"/blog/google-lanseaza-chrome\")==\r\n\r\n==include(page=\"/blog/harta-politicii-romanesti\")==\r\n\r\n==include(page=\"/blog/human-computation\")==\r\n\r\n==include(page=\"/blog/imaginecup\")==\r\n\r\n==include(page=\"/blog/inteligenta-nativa-sau-educata\")==\r\n\r\n==include(page=\"/blog/interviu-cu-catalin-francu\")==\r\n\r\n==include(page=\"/blog/interviu-cu-catalin-francu-partea-a-doua\")==\r\n\r\n==include(page=\"/blog/interviu-despre-google\")==\r\n\r\n==include(page=\"/blog/interviu-evz-mihai-stroe\")==\r\n\r\n==include(page=\"/blog/interviu-mihai-patrascu-partea-a-doua\")==\r\n\r\n==include(page=\"/blog/interviu-mihai-patrascu-partea-intai\")==\r\n\r\n==include(page=\"/blog/interviu-octavian-costache-partea-a-doua\")==\r\n\r\n==include(page=\"/blog/interviu-octavian-costache-partea-intai\")==\r\n\r\n==include(page=\"/blog/interviu-radu-berinde-partea-a-doua\")==\r\n\r\n==include(page=\"/blog/interviu-radu-berinde-partea-intai\")==\r\n\r\n==include(page=\"/blog/intrebare-scurta\")==\r\n\r\n==include(page=\"/blog/jake-jarvis-si-aplicatia-lui-de-facebook\")==\r\n\r\n==include(page=\"/blog/joburi-evaluate\")==\r\n\r\n==include(page=\"/blog/jocuri-web\")==\r\n\r\n==include(page=\"/blog/la-inceputul-sezonului-competitional\")==\r\n\r\n==include(page=\"/blog/membrii-noi\")==\r\n\r\n==include(page=\"/blog/metaprogramare-cu-template-uri\")==\r\n\r\n==include(page=\"/blog/mic-puzzle\")==\r\n\r\n==include(page=\"/blog/muzica\")==\r\n\r\n==include(page=\"/blog/noutati\")==\r\n\r\n==include(page=\"/blog/o-problema-misto-solutie\")==\r\n\r\n==include(page=\"/blog/olimpiada-internationala-de-informatica-2007-jurnal-de-bord\")==\r\n\r\n==include(page=\"/blog/olimpicul-de-la-facebook\")==\r\n\r\n==include(page=\"/blog/petr-are-blog\")==\r\n\r\n==include(page=\"/blog/photosynth\")==\r\n\r\n==include(page=\"/blog/post-happy-coding\")==\r\n\r\n==include(page=\"/blog/post-nou\")==\r\n\r\n==include(page=\"/blog/preoni-2008-concursul-si-premierea\")==\r\n\r\n==include(page=\"/blog/preoni-2008-deschiderea\")==\r\n\r\n==include(page=\"/blog/preoni-2008-in-cautare-de-sigla\")==\r\n\r\n==include(page=\"/blog/prezentari-mihai-patrascu\")==\r\n\r\n==include(page=\"/blog/primul-post\")==\r\n\r\n==include(page=\"/blog/problema-majoritatii\")==\r\n\r\n==include(page=\"/blog/problema-misto\")==\r\n\r\n==include(page=\"/blog/problema-saptamanii-2007-10-30\")==\r\n\r\n==include(page=\"/blog/problema-saptamanii-2007-10-30-solutie\")==\r\n\r\n==include(page=\"/blog/problema-saptamanii-20071110\")==\r\n\r\n==include(page=\"/blog/problema-saptamanii-pion-solutie\")==\r\n\r\n==include(page=\"/blog/problema-saptamanii-pioni\")==\r\n\r\n==include(page=\"/blog/problema-saptamanii-probabilitati\")==\r\n\r\n==include(page=\"/blog/problema-saptamanii-produs\")==\r\n\r\n==include(page=\"/blog/problema-saptamanii-produs-solutie\")==\r\n\r\n==include(page=\"/blog/problema-saptamanii-solutie-20080215\")==\r\n\r\n==include(page=\"/blog/problema-saptamanii-vanatori\")==\r\n\r\n==include(page=\"/blog/problema-saptamanii-vanatori-solutie\")==\r\n\r\n==include(page=\"/blog/probleme-de-formula\")==\r\n\r\n==include(page=\"/blog/protocoale-de-securitate\")==\r\n\r\n==include(page=\"/blog/putina-istorie-acm-icpc-seerc\")==\r\n\r\n==include(page=\"/blog/ratinguri\")==\r\n\r\n==include(page=\"/blog/robocup\")==\r\n\r\n==include(page=\"/blog/romania-e-frumoasa\")==\r\n\r\n==include(page=\"/blog/romanii-la-disneyland\")==\r\n\r\n==include(page=\"/blog/romanii-la-disneyland-partea-intai\")==\r\n\r\n==include(page=\"/blog/romanii-la-disneyworld-partea-a-doua\")==\r\n\r\n==include(page=\"/blog/romanii-la-disneyworld-partea-a-treia\")==\r\n\r\n==include(page=\"/blog/romanii-la-disneyworld-partea-intai\")==\r\n\r\n==include(page=\"/blog/salarii-in-it\")==\r\n\r\n==include(page=\"/blog/se-apropie-acmul\")==\r\n\r\n==include(page=\"/blog/sedinte-infoarena\")==\r\n\r\n==include(page=\"/blog/sfaturi-practice-inainte-de-oji\")==\r\n\r\n==include(page=\"/blog/sfaturi-practice-inainte-de-oji-2\")==\r\n\r\n==include(page=\"/blog/surse-deschise\")==\r\n\r\n==include(page=\"/blog/ted-talks\")==\r\n\r\n==include(page=\"/blog/three-beautiful-quicksorts\")==\r\n\r\n==include(page=\"/blog/trondheim\")==\r\n\r\n==include(page=\"/blog/un-widget-pentru-erori-404\")==\r\n\r\n==include(page=\"/blog/valorificarea-spiritului-competitiv\")==\r\n\r\n==include(page=\"/blog/vine-olimpiada\")==\r\n\r\n==include(page=\"/blog/viva-las-vegas\")==\r\n\r\n==include(page=\"/blog/worse-than-we-feared\")==\r\n\r\n==include(page=\"/blog/zece-ani-de-google\")==\r\n\r\n',1490,'public',NULL,NULL),('the-monty-hall-problem','The Monty Hall Problem','2004-11-20 00:00:00','2009-02-20 00:10:46','h1. The Monty Hall Problem\r\n\r\n(Categoria _Matematica_, Autor _Alexandra Gartu_)\r\n\r\n(toc){width: 20em}*{text-align:center;} *Continut*\r\n* \'Problema\':the-monty-hall-problem#problema\r\n* \'Argumentul 1\':the-monty-hall-problem#argument1\r\n* \'Argumentul 2\':the-monty-hall-problem#argument2\r\n* \'Putina matematica... sau Argumentul 3\':the-monty-hall-problem#argument3\r\n* \'Putina istorie...\':the-monty-hall-problem#istorie\r\n\r\nIn acest articol nu vom discuta despre algoritmi clasici, structuri de date sau competitii de informatica. Vreau sa va prezint o problema de logica ce presupune doar cunostinte elementare de matematica. Scopul este de a ne \"antrena\" mintea / perspicacitatea, iar legatura cu informatica vine din faptul ca multe din problemele pe care le rezolvati la informatica presupun idei mai mult decat cunostinte clasice.\r\n\r\nh2(#problema). Problema\r\n\r\nProblema celor trei porti se refera la faimoasa situatie din show-urile televizate (in speta \"Let\'s Make a Deal\", prezentat de americanul Monty Hall) cand unul dintre concurenti trebuie sa aleaga una din cele $3$ porti: in spatele a doua dintre ele se afla cate o capra, iar in spatele celei de-a treia se afla un Rolls Royce. Dupa ce concurentul a ales prima data, prezentatorul (stiind unde se gaseste Rolls Royce-ul) ii arata una din capre, din spatele uneia din usile pe care NU le-a ales. Intrebarea care se pune este daca respectivul concurent ar trebui sau nu sa-si schimbe optiunea dupa aceasta dezvaluire.\r\n\r\nh2(#argument1). Argumentul 1\r\n\r\nInitial, sansele de a alege poarta corecta sunt de {$1/3$}. Faptul ca ti-a fost aratata o capra nu schimba cu nimic probabilitatea ca prima oara sa fi ales corect. Sansele ca prima decizie sa fie corecta inca sunt de {$1/3$}, deci ar trebui sa iti modifici decizia fiindca acum in spatele celei de-a treia porti exista {$2/3$} sanse sa se afle un Rolls Royce.\r\n\r\nExista asadar doua cazuri:\r\n\r\n# ai ghicit corect prima oara - sanse $1/3$\r\n# ai ghicit incorect prima oara - sanse $2/3$\r\n\r\nSa presupunem acum ca iti schimbi decizia:\r\n\r\n# avusesei dreptate la prima decizie - sansele sa pierzi sunt $1/3$\r\n# gresisei prima oara - sansele sa castigi sunt $2/3$\r\n\r\nh2(#argument2). Argumentul 2\r\n\r\nModificam ipoteza considerand ca avem initial $100$ de usi. Alegem una dintre ele avand $99/100$ sanse sa ghicim gresit. Din nou moderatorul emisiunii stie unde este Rolls Royce-ul, asa ca ne arata $98$ de capre. Dupa acest pas inca nu stim in spatele careia din usi se afla masina: asta inseamna ca sansele de a ghici sunt $1/2$? In mod cert, nu: sansa de a ghici a fost initial si a ramas {$1/100$}. Deci, in mod sigur este indicat sa schimbam decizia initiala.\r\n\r\nh2(#argument3). Putina matematica... sau Argumentul 3\r\n\r\nSa numim cele $3$ porti {$A, B, C$}. Sa presupunem ca ai ales poarta $A$ si ca Monty Hall ti-a aratat o capra in spatele usii {$B$}.\r\n\r\n* Probabilitatea ca masina sa se afle in spatele portii $X$: {$P(X) = 1/3$}\r\n* Probabilitatea ca moderatorul sa deschida poarta $B$ daca premiul se afla la {$A$}: $P(moderatorul deschide B | A) = 1/2$\r\n* Probabilitatea ca moderatorul sa deschida poarta $B$ daca premiul se afla la {$B$}: $P(moderatorul deschide B | B) = 0$\r\n* Probabilitatea ca moderatorul sa deschida poarta $B$ daca premiul se afla la {$C$}: $P(moderatorul deschide B | C) = 1$\r\n\r\nh3. Concluzii\r\n\r\nProbabilitatea ca moderatorul sa deschida poarta $B$ este:\r\n\r\n$P(moderatorul deschide B) =$\r\n$P(A) * P(moderatorul deschide B | A) +$\r\n$P(B) * P(moderatorul deschide B | B) +$\r\n$P(&#67;) * P(moderatorul deschide B | C)$\r\n$= 1/6 + 0 + 1/3 = 1/2$\r\n\r\n$P(A | moderatorul deschide B) = P(A) * P(moderatorul deschide B | A) / P(moderatorul deschide B)$\r\n$= (1/6) / (1/2) = 1/3$\r\n\r\n$P(C | moderatorul deschide B) = P(&#67;) * P(moderatorul deschide B | C) / P(moderatorul deschide B)$\r\n$= (1/3) / (1/2) = 2/3$\r\n\r\nDeci, probabilitatea ca in spatele usii $C$ sa se afle o masina este {$2/3$}.\r\n\r\nh2(#istorie). Putina istorie...\r\n\r\nProblema a fost publicata mai intai de Martin Gardener in octombrie $1959$ si se referea la $3$ detinuti dintre care unul, ales aleator, va fi eliberat. Sa numim cei trei prizonieri {$A, B, C$}. $A$ ii cere gardianului sa-i spuna care dintre colegii lui NU va fi eliberat. Desigur, asta nu inseamna ca sansele lui de a fi eliberat cresc (ele fiind tot {$1/3$}) in timp ce sansele celui de-al treilea condamnat (cel nenominalizat) cresc la {$2/3$}.\r\n\r\nMarilyn Vos Savant\'s, considerata omul cu cel mai ridicat IQ pana in momentul de fata, a publicat aceasta problema, in prima forma din acest articol in anul $1990$ in rubrica sa din Parade Magazine. Solutia ei (cel de-al doilea argument) a fost contestata in numeroase randuri (a primit peste $10000$ de scrisori care sustineau ca demonstratia este eronata) si a aparut pe prima pagina in {@21 iulie 1991@} in New York Times (\"Her answer... has been debated in the halls of the C.I.A. and the barracks of fighter pilots in the Persian Gulf. It has been analyzed by mathematicians at M.I.T. and computer programmers at Los Alamos National Laboratory in New Mexico. It has been tested in classes ranging from second grade to graduate level at more than 1000 schools across the country.\").\r\n',2044,'public',3683,NULL),('blog/problema-saptamanii-probabilitati-solutie','Problema saptamanii - Probabilitati (solutie)','2008-11-20 08:40:51','2008-11-20 09:11:32','_Problema curenta a fost rezolvat de Ovidiu Gheorghioiu, Delia David, Andrei Olariu si de Radu Grigore._\r\n\r\nNu exista nici o modalitate prin care sa obtinem rezultate uniform aleatoare folosind un numar finit de aruncari pentru ca se poate intampla ca la orice aruncare a monedei sa obtinem cap la infinit si atunci nu avem cum sa obtinem rezultate diferite.\r\n\r\nSolutiile lui Andrei:\r\n\r\n1. Se arunca moneda de cate 2 ori. Daca pica pajura si apoi cap -> pajura, daca avem cap si apoi pajura -> cap, daca avem 2 rezultate egale, repetam ambele aruncari.\r\n\r\n2. Generam doua numere din multimea {0, 1} folosind metoda de la pct 1. Obtinem 00 -> mar, 01 -> para, 10 -> portocala, 11 -> repetam cele 2 generari.\r\n\r\nPrima problema are mai mult de 50 de ani fiind rezolvata de unul dintre pionierii informaticii, \'John Von Neumann\':http://en.wikipedia.org/wiki/John_von_Neumann#Computer_science\r\n\r\nA doua e interesanta in contextul generatoarelor de numere aleatoare. De exemplu in C++ unii folosim, pentru a genera numere aleatoare de la 0 la n - 1, instructiunile rand() % n. Acum dupa ce ati vazut problema 2 este clar ca unele rezultate sunt mai probabile ca altele.\r\n\r\nIn java sau Python generatoarele aleatoare sunt mai bune.\r\n\r\nVarianta implementata in java:\r\n\r\n== code(c) |\r\n public int nextInt(int n) {\r\n     if ((n & -n) == n)  // i.e., n is a power of 2\r\n         return (int)((n * (long)next(31)) >> 31);\r\n\r\n     int bits, val;\r\n     do {\r\n         bits = next(31);\r\n         val = bits % n;\r\n     } while(bits - val + (n-1) < 0);\r\n     return val;\r\n }\r\n==\r\n\r\nputeti citi \'aici\':http://java.sun.com/j2se/1.5.0/docs/api/java/util/Random.html explicatia codului.\r\n\r\nO varianta care foloseste ceva mai multe dintre rezultatele aruncarilor pentru prima problema ar fi sa consideram si rezultatele de genul cap, cap, pajura, pajura ca 0 si pajura, pajura, cap, cap ca 1 si asa mai departe.\r\n\r\nOvidiu sugera urmatoarea generalizare pentru problema 2: Care e numarul mediu maxim de numere aleatoare intre 0 si k - 1 pe care le putem obtine dintr-un stream de biti uniform aleatori.',58,'protected',3363,NULL),('blog/problema-saptamanii-cartofi','Problema saptamanii - Cartofi','2008-11-21 19:48:26','2008-11-25 23:27:39','Sa se demonstreze ca, dandu-se doi cartofi, exista o curba inchisa in trei dimensiuni care se poate desena pe suprafetele ambilor cartofi.\r\n\r\n_Ca de obicei, puteti trimite solutii pe mail la adresa cosmin at gmail.com_\r\n\r\n*Update* Am gresit adresa la care trebuia sa trimiteti solutia e cosminn at gmail.com. Ma scuzati, daca ati trimis deja solutia mai trimiteti-o o data.',58,'protected',3367,NULL),('summer-challenge-2009/solutii/runda-2/simpla','Soluție Simpla','2009-08-01 10:15:59','2009-08-01 16:16:40','h2(#simpla). \'Simpla\':problema/simpla\r\n\r\nPornim de la observaţia că în intervalul $[0, 10^n^-1]$ există exact jumătate numere naturale cu suma cifrelor pară. Rezultă că avem $5 * 10^n-1^$ numere naturale cu suma cifrelor pară. Pentru a rezolva problema pe intervalul $[a, b]$, vom folosi o funcţie $f(x)$ egală cu numărul numerelor cu suma cifrelor pară din intervalul $[0, x]$. Astfel, rezultatul va fi $f(b) - f(a - 1)$.\r\n\r\nPentru a calcula valoarea returnată de un $f(x)$, să presupunem că $x = x{~1~}x{~2~}..x{~m-1~}x{~m~}$. Avem $f(x) = x{~1~} * 5*10^m-2^ + x{~2~} * 5*10^m-3^ + .. + x{~m-1~} * 5 + v$. Acest lucru este posibil deoarece pentru un $x{~i~}$ nu are importanţă suma $x{~1~} + .. + x{~i-1~}$, întrucât numărul numerelor cu suma cifrelor pară este egal cu al celor cu suma cifrelor impară. Cazul ultimei cifre, se tratează prin a considera toate numerele cuprinse în intervalul $[x - x{~m~}, x]$ care se vor aduna la rezultat dacă au suma cifrelor pară, rezultat reţinut în $v$ în formula de mai sus. Sau mai simplu, $f(2*k+1) = k$ si $f(2*k) = f(2*k+1)-(1-S(2*k+1))%2$, unde $S(x) =$ suma cifrelor lui x.',4439,'public',NULL,NULL),('runda/all-you-can-code2008/clasament','Clasament all-you-can-code2008','2008-11-23 11:19:07','2008-11-23 12:58:04','h1. Clasament ==roundparam(round_id=\"all-you-can-code2008\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"all-you-can-code2008\")==',2092,'protected',NULL,NULL),('templates/all-you-can-code-logo','all-you-can-code-logo','2008-11-23 12:24:46','2008-11-23 12:57:04','!templates/all-you-can-code-logo?bitcat.jpg!',2092,'protected',NULL,NULL),('all-you-can-code-2008/probleme','Probleme All You Can Code 2008','2008-11-23 12:46:49','2008-11-30 17:44:21','==include(page=\"templates/all-you-can-code-logo\")==\r\n\r\nh1. == roundparam(round_id=\"all-you-can-code2008\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':all-you-can-code-2008\r\n*(active) \'Probleme\':all-you-can-code-2008/probleme \r\n* \'Clasament\':all-you-can-code-2008/clasament\r\n\r\nConcursul _All You Can Code_ este organizat de trei membri infoarena: Florin Pogocsan, Puni Andrei Paul si Mihai Ciucu.\r\n\r\nh2. Probleme\r\n\r\nAici vei gasi problemele atunci cand va incepe concursul.\r\n\r\n== Tasks(round_id=\"all-you-can-code2008\" score=\"1\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==user(user=\"crawler\" type=\"tiny\")==\r\n* ==user(user=\"binary_fire\" type=\"tiny\")==\r\n* ==user(user=\"gogu\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n',1490,'round: all-you-can-code2008',NULL,NULL),('all-you-can-code-2008/clasament','Clasament All You Can Code 2008','2008-11-23 13:00:23','2008-11-29 10:31:35','==include(page=\"templates/all-you-can-code-logo\")==\r\n\r\n(htabs)* \'Despre...\':all-you-can-code-2008\r\n* \'Probleme\':all-you-can-code-2008/probleme \r\n*(active) \'Clasament\':all-you-can-code-2008/clasament\r\n\r\np<. == Rankings(rounds=\"all-you-can-code2008\") == ',1490,'protected',NULL,NULL),('algoritmiada-2009/runda-2/solutii/bazaconii','algoritmiada-2009/runda-2/solutii/bazaconii','2009-01-03 17:06:41','2009-01-11 11:56:39','h1(#bazaconii). \'Bazaconii\':problema/bazaconii\r\n\r\nPrima observatie pe care o putem face este ca putem rezolva problema independent pentru fiecare bit al numerelor. Vom numi vecini doua numere din sir daca intre ele exista o relatie prin care este cunoscuta suma lor xor. Daca pentru al $i$-lea numar din sir setam al $j$-lea bit $0$ stim ca pentru toti vecinii lui $i$ bitul $j$ este fortat la una din cele doua valori posibile (ecuatiile $0 xor x = 0$ si $0 xor x = 1$ au solutii unice). Acelasi lucru se intampla si daca setam al $j$-lea bit $0$. Odata ce am setat bitii pentru vecinii lui $i$ putem seta si biti pentru vecinii vecinilor lui $i$ si asa mai departe. Practic vom folosi o coada in care vom introduce intai al $i$-lea numar apoi vom scoate mereu din coada un numar caruia i-am setat bitul si daca vecinii sai nu se afla deja in coada ii vom introduce si pe acestia. Pentru a obtine solutia minim lexicografica vom incerca mereu sa alegem numarul cu indicele cel mai mic care nu a fost deja preprocesat si daca atat $0$ cat si $1$ furnizeaza o solutie valida vom seta bitul la valoarea $0$. La sfarsit mai trebuie sa verificam daca toate conditiile se respecta. Mai simplu decat sa verificam pentru fiecare bit in parte este sa observam ca daca exista solutie, atunci daca fixam un numar din sir pe valoarea $0$ va exista si in acest caz o solutie.',2038,'public',NULL,NULL),('newsletter/autumn-warmup-2007/runda-1','Autumn Warm-Up, Runda 1; Rezultate IOI si SC 2007','2007-09-09 18:33:52','2009-01-20 09:35:37','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nVacanta de vara a ajuns la sfarsit.  Ai nevoie de un concurs\r\nde incalzire, inainte sa inceapa scoala, si, o data cu ea,\r\npregatirile pentru un nou an de olimpiade.\r\n\r\nE timpul sa te revezi cu vechii tai prieteni de la concursurile\r\nde info si sa le demonstrezi ca ai ramas in forma.  :)\r\n\r\nTe invit sa participi la runda 1 a concursului Autumn Warm Up\r\ncu probleme propuse de utilizatori infoarena.\r\n\r\np{padding-left: 2em;}. Runda 1\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Marti, 11 septembrie 2007, orele 10:00 - 15:00\r\n\r\np{padding-left: 2em;}. Pagina rundei:\r\n    \'autumn-warmup-2007/runda-1\':autumn-warmup-2007/runda-1\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\r\nh2.  Atentie! Concurs cu rating! \r\n\r\nParticiparea la aceasta runda iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te va aduce mai aproape de varful clasamentului.\r\n==NewsletterRating(username=\"%username%\")==\r\nAfla mai multe despre rating: \'documentatie/rating\':documentatie/rating\r\n\r\nh2.  Despre Autumn Warm Up, Runda 1\r\n\r\nVei avea de rezolvat 4 probleme de natura algoritmica.\r\nTimpul de lucru este de 5h iar evaluarea se face la sfarsit.\r\n\r\nVor propune probleme: Paul-Dan Baltescu, Savin Tiberiu,\r\nAirinei Adrian si Vlad Dumitriu.\r\n\r\nConcursul este supravegheat de Adrian Diaconu.\r\n\r\nPentru informatii suplimentare (cum particip, intrebari etc.)\r\nviziteaza pagina concursului: \'autumn-warmup-2007\':autumn-warmup-2007\r\n\r\nh2.  Rezultate Summer Challenge 2007 \r\n\r\nIata castigatorii concursului Summer Challenge (30 iul - 12 aug),\r\nin urma celor 3 runde online organizate de infoarena:\r\n\r\np{padding-left: 2em;}. Loc    Nume                    Scor (max 900)\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n      1    Gheorghe Cosmin          755\r\n      2    Bogdan Tataroiu          682\r\n      3    Andrei Grigorean         574\r\n      4    Airinei Adrian           488\r\n      5    Victor Rusu              480\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\r\nVezi clasamentul complet:\r\n\'summer-challenge-2007/clasament\':summer-challenge-2007/clasament\r\n\r\nh2.  Rezultate IOI 2007 \r\n\r\nA 19-a editie a Olimpiadei Internationale de Informatica a fost\r\ngazduita de Croatia (in Zagreb) in perioada 15-22 august.\r\n\r\nPagina web: \'http://www.hsin.hr/ioi2007/\':http://www.hsin.hr/ioi2007/\r\n\r\nDelegatia Romaniei, condusa de Prof. Emanuela Cerchez, a obtinut\r\n4 medalii de argint.  Felicitari!\r\n\r\nMedaliatii Romaniei la IOI sunt:  Cosmin Gheorghe, Bogdan Tataroiu,\r\nAdrian Airinei si Andrei Grigorean.\r\n\r\nDaca simti nevoia sa ii feliciti, probabil ca ii poti gasi pe\r\nforum-ul infoarena:\r\n\'http://infoarena.ro/forum/index.php?topic=2076.0\':http://infoarena.ro/forum/index.php?topic=2076.0  ;)\r\n\r\nh2.  Prima data la infoarena? \r\n\r\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\r\nRamai alaturi de noi.  Te ajutam sa devii olimpic!\r\n\r\nSucces!\r\nEchipa infoarena\r\n\r\nh2.  Mesaj nesolicitat? \r\n\r\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\r\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\r\n\r\n',1490,'protected',NULL,NULL),('newsletter/autumn-warmup-2007/runda-3','Autumn Warm Up, Runda 3','2007-10-05 16:40:56','2009-01-20 09:42:17','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nTe invit sa participi la Runda 3 a concursului Autumn Warm Up.\r\n\r\np{padding-left: 2em;}. Runda 3\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Duminica, 7 octombrie 2007, orele 10:00 - 15:00\r\n\r\np{padding-left: 2em;}. Pagina rundei:\r\n    \'autumn-warmup-2007/runda-3\':autumn-warmup-2007/runda-3\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\r\nh2.  Atentie! Concurs cu rating! \r\n\r\nParticiparea la aceasta runda iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te va aduce mai aproape de varful clasamentului.\r\n==NewsletterRating(username=\"%username%\")==\r\nAfla mai multe despre rating: \'documentatie/rating\':documentatie/rating\r\n\r\nh2.  Despre Autumn Warm Up, Runda 3\r\n\r\nVei avea de rezolvat 4 probleme de dificultate variata.\r\nTimpul de lucru este de 5h iar evaluarea se face la sfarsit.\r\n\r\nVor propune probleme: Dragus Marius, Cezar Mocan,\r\nMugurel Ionut Andreica si Airinei Adrian.\r\n\r\nConcursul este supravegheat de Adrian Diaconu.\r\n\r\nPentru informatii suplimentare (cum particip, intrebari etc.)\r\nviziteaza pagina concursului: \'autumn-warmup-2007\':autumn-warmup-2007\r\n\r\nh2.  Clasament Runda 1 + Runda 2 \r\n\r\nPunctajele acestei runde se vor aduna la clasamentul curent.\r\nIata varful clasamentului cumulat pe primele doua runde:\r\n\r\np{padding-left: 2em;}. Loc    Nume                    Scor (max 900)\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n      1    Gheorghe Cosmin                 595\r\n      2    Victor Rusu                     531\r\n      3    Tudose Vlad                     370\r\n      4    Bogdan Tataroiu                 320\r\n      5    Florin Pogocsan                 290\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\r\nVezi clasamentul complet:\r\n\'autumn-warmup-2007/clasament\':autumn-warmup-2007/clasament\r\n\r\nh2.  Prima data la infoarena? \r\n\r\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\r\nRamai alaturi de noi.  Te ajutam sa devii olimpic!\r\n\r\nSucces!\r\nEchipa infoarena\r\n\r\nh2.  Mesaj nesolicitat? \r\n\r\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\r\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\r\n\r\n',1490,'protected',NULL,NULL),('blog/outliers','Outliers','2008-11-24 06:13:17','2008-11-24 07:13:58','Am auzit de Malcolm Gladwell uitandu-ma la TED talks si vazand \'talkul\':http://www.youtube.com/watch?v=iIiAAhUeR6Y acestuia in care discuta cum a fost revolutionata industria alimentara folosind experimente si concepte din statistica. Mi-a placut mult talkul si am cautat mai multe despre el. Asa am gasit cartile Tipping Point si Blink, care sunt doua best selleruri scrise de Malcolm (va spuneam intr-un \'post anterior\':http://infoarena.ro/blog/drumuri-lungi ca am citit Blink pe avion). Imi place stilul autorului. El descrie concepte stiintifice in termeni accesibili unor oameni de rand. In plus, isi sustine ipotezele prin exemple. E o modalitate foarte buna de a mentine interesul cititorului si de a comunica unele idei. \r\n\r\n\'Altii\':http://www.joelonsoftware.com/items/2008/11/18.html urasc acest stil considerand cartile lui Malcolm ca fiind adresate unor oameni ce nu citesc carti in mod obisnuit si ca extrapoleaza prea mult avand cateva exemple particulare.  Fiecare din noi avem un stil diferit de a acumula informatie. Putem ajunge instantaneu la posturi interesante pe bloguri,  in ziare online sau agregatoare gen reddit sau digg. Devenim astfel din ce in ce mai obisnuiti cu satisfactie intelectuala imediata si ne este greu sa ne mentinem atentia pe o durata mai lunga, incat sa citim o carte intreaga. Ii respect abilitatea de a ma tine interesat pe tot parcursul cartii, chiar daca nu iau tot ce zice el de bun.\r\n\r\nRecent a aparut Outliers, o noua carte sub semnatura lui Malcolm. Aceasta analizeaza destinele unor oameni ce reusesc in viata si incearca sa demonstreze ca o poveste de succes este o combinatie intre un efort sustinut si putin noroc, dar mai putin important este un talent inascut. O ipoteza a lui este ca iti trebuie cel putin 10000 de ore de lucru intr-un domeniu pentru a ajunge un expert. Gladwell exemplifica cum cei de origine asiatica sunt mai harnici decat restul americanilor  pentru ca stramosii lor au lucrat pe campurile de orez. Astfel foarte multi dintre cercetatorii de top ai Statelor Unite sunt la ora actuala asiatici.\r\n\r\nUnele idei ce apar in carte carte nu sunt noi. Le-am mai vazut in alte articole si chiar am scris un blog post \"Inteligenta, nativa sau educata\":http://infoarena.ro/blog/inteligenta-nativa-sau-educata in care discutam teme similare.\r\n\r\nCartea incepe sa aiba putin buzz si apar articole in presa despre ea. Puteti citi \'aici\':http://www.guardian.co.uk/books/2008/nov/15/malcolm-gladwell-outliers-extract un extras mai lung din carte. Pe \'siteul\':http://www.gladwell.com/outliers/index.html autorului gasiti de asemenea mai multe fragmente interesante.\r\n\r\nOutliers e foarte interesanta si v-o recomand cu caldura. De fapt va recomand tot ce a scris Malcolm. Puteti gasi pe youtube unele discursuri de ale lui iar pe net are mai multe texte interesante publicate.\r\n',58,'protected',3375,NULL),('schimbare-borland','Schimbarea compilatoarelor Borland la OJI','2008-10-22 10:18:36','2008-11-25 10:34:38','h1. Schimbarea compilatoarelor Borland la OJI\r\n\r\n==include(page=\"template/schimbare-borland\")==\r\n\r\nh2. Despre ce e vorba\r\n\r\n* \'Argumentatia\':schimbare-borland/argumentatie\r\n* \'Alternative\':schimbare-borland/alternativa\r\n* \'Alegerile\':schimbare-borland/alegeri\r\n* \'Ghid MinGW Developer Studio\':schimbare-borland/ghid\r\n* \'Ghid FreePascal\':schimbare-borland/ghid-freepascal\r\n* \'Pachet\':schimbare-borland/pachet\r\n* \'Autori\':schimbare-borland/autori\r\n\r\nh2. Altele\r\n\r\n* \'Jurnal de lucru\':schimbare-borland/jurnal',75,'public',NULL,NULL),('schimbare-borland/autori','Autori','2008-11-19 21:14:04','2008-11-25 12:05:56','h1. Autori\r\n\r\n==include(page=\"template/schimbare-borland\")==\r\n\r\nUrmatorii membrii din \'echipa infoarena\':echipa-infoarena s-au implicat la acest proiect:\r\n\r\n* ==user(user=\"svalentin\" type=\"tiny\")==: argumentatie, analiza alternative, testare, pachet de instalare\r\n* ==user(user=\"Prostu\" type=\"tiny\")==: argumentantie, analiza alternative, testare, documentatie\r\n* ==user(user=\"victorsb\" type=\"tiny\")==: argumentatie, documentatie\r\n* ==user(user=\"silviug\" type=\"tiny\")==: argumentatie, analiza alternative, documentatie, testare, coordonare\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==: argumentatie, analiza alternative\r\n* ==user(user=\"domino\" type=\"tiny\")==: coordonare',1490,'public',NULL,NULL),('schimbare-borland/ghid-freepascal/menu','schimbare-borland/ghid-freepascal/menu','2008-11-13 18:15:28','2008-11-25 12:13:15','(toc)*{text-align:center} *Ghid Free Pascal*\r\n* \'Instalare\':schimbare-borland/ghid-freepascal#instalare\r\n* \'Folosirea mediului\':schimbare-borland/ghid-freepascal#mediu',1490,'public',NULL,NULL),('schimbare-borland/ghid-freepascal','Ghid de utilizare Free Pascal','2008-11-13 19:19:21','2008-11-25 10:43:38','h1. Scurt ghid pentru folosirea Free Pascal\r\n\r\n==include(page=\"template/schimbare-borland\")==\r\n\r\n==include(page=\"schimbare-borland/ghid-freepascal/menu\")==\r\n\r\n==include(page=\"schimbare-borland/ghid-freepascal/instalare\")==\r\n\r\n==include(page=\"schimbare-borland/ghid-freepascal/mediu\")==',75,'public',NULL,NULL),('template/newtask','%task_id%','2006-11-05 14:40:14','2008-11-25 13:56:15','== include(page=\"template/taskheader\" task_id=\"%task_id%\") ==\r\n\r\nPoveste şi cerinţă...\r\n\r\nh2. Date de intrare\r\n\r\nFişierul de intrare $%task_id%.in$ ...\r\n\r\nh2. Date de ieşire\r\n\r\nÎn fişierul de ieşire $%task_id%.out$ ...\r\n\r\nh2. Restricţii\r\n\r\n* $... &le; ... &le; ...$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. %task_id%.in |_. %task_id%.out |\r\n| This is some\r\n  text written on\r\n  multiple lines.\r\n| This is another\r\n  text written on\r\n  multiple lines.\r\n| \r\n\r\nh3. Explicaţie\r\n\r\n...\r\n\r\n== include(page=\"template/taskfooter\" task_id=\"%task_id%\") ==\r\n',1490,'protected',NULL,NULL),('planificare/sedinta-20081125','Sedinta 2008-11-25','2008-11-24 15:06:43','2008-12-17 00:27:22','h1. Sedinta 2008-11-25\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *marti, 25 noiembrie* la ora *19:00* la \'*Retro Cafe*\':http://metropotam.ro/Unde-iesim/2008/07/art2701725520-Millennium-Bank-recomanda-Retro-Cafe/\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"astronomy\" type=\"tiny\")== Il rog pe ==user(user=\"wefgef\" type=\"tiny\")== sa ma reprezinte\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioare\':planificare/sedinta-20081107\r\n* Update OJI\r\n* Tricouri Junior Challenge\r\n* All you can code\r\n* Algoritmiada\r\n* Feedback Coding Camp\r\n* Stabilit urmatorul Coding Camp\r\n* Stelele powered by infoarena\r\n* OKR-uri\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Vali mai are 2 tricouri. Le da lui Paul sa le livreze. %{color:red;}(2/2 done)%\r\n* E lume available pentru \"All you can code\".\r\n* All you can code: primele 4 ore sunt fara evaluare \r\n** Astronomy actualizeaza pagina concursului\r\n* Algoritmiada:\r\n** Bagam grupa de studenti si unim clasele 9-10.\r\n** Prima runda pe 14 decembrie\r\n** Facem 3 runde: dec, ian, feb, martie finala\r\n** Trebuie sa anuntam pana pe 1 decembrie\r\n** Suntem deja in prima saptamana din program. Sefi de grupe:\r\n*** Gimnaziu: ==user(user=\"astronomy\" type=\"tiny\")==\r\n*** 9-10: ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n*** 11-12: ==user(user=\"ditzonec\" type=\"tiny\")==\r\n*** Studenti: ==user(user=\"wefgef\" type=\"tiny\")==\r\n** Wegef bate lumea la cap sa citeasca rolurile, sa propuna probleme, etc.\r\n* Mircea si Bogdan fac release la 2.2 vineri %{color:red;}(done, duminica after contest)%\r\n* Mircea se ocupa sa organizeze urmatorul coding camp pe 13-14 decembrie\r\n** Probabil facem la ICHB, ca nu incapem la Hostway\r\n* Punem stire ca nu mai ai voie cu HTML si sa-si actualizeze lumea profilele\r\n* Stelele:\r\n** Facem Stelele pe infoarena\r\n** La fiecare submit retinem IP-ul ca sa detectam cine triseaza (in 2.2.1)\r\n* Avem probleme la rating:\r\n** Inregistrarea is broken\r\n** Nu avem curba lui Gauss\r\n** Trebuie sa facem posiblitatea sa te deinscrii pana incepe concursul (2.2.1)\r\n** Cosmin, Wefgef si Bogdan redacteaza IAP pentru rating\r\n\r\nh2. Notite\r\n\r\n...',1792,'public',NULL,NULL),('newsletter/all-you-can-code','All You Can Code!','2008-07-02 17:51:25','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nImi face placere sa te anunt ca membrii comunitatii infoarena ti-au\r\npregatit un concurs de o zi si jumatate, cu 10 probleme de\r\ndificultate variata, si cu evaluator online. Problemele au fost atent\r\nalese incat concursul sa fie potrivit pentru toate varstele si,\r\nbineinteles, cat mai distractiv.\r\n\nTe asteptam in acest weekend sa participi alaturi de noi la concursul\r\n\"All You Can Code.\"   Tu cate probleme poti rezolva?\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Concursul *incepe*\r\n\np{padding-left: 4em;}. Sambata, 29 Noiembrie 2008, la ora 12:00\r\n\np{padding-left: 2em;}. si se *termina* Duminica la ora 24:00.\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nVezi pagina concursului: \'all-you-can-code-2008\':all-you-can-code-2008\r\npentru mai multe informatii.\r\n\nSucces!\r\n\nh2.  Atentie! Concurs cu rating! \n\nDaca vrei sa ti se modifice rating-ul in urma acestui concurs\r\ntrebuie sa iti anunti participarea din timp. Intra pe\r\n\'all-you-can-code-2008\':all-you-can-code-2008 si inscrie-te.\r\n\nPoti sa participi la concurs chiar si daca nu te-ai inscris in\r\nprealabil insa nu ti se va modifica rating-ul. ==NewsletterRating(username=\"%username%\")==\r\nCiteste despre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Despre concurs \n\nConcursul \"All You Can Code\" este organizat de trei membri infoarena:\r\n\np{padding-left: 2em;}. Florin Pogocsan\r\n    [ \'utilizator/\':utilizator/Binary_Fire ]\r\n\np{padding-left: 2em;}. Puni Andrei Paul\r\n    [  ==User(user=\"crawler\" type=\"link\")==  ]\r\n\np{padding-left: 2em;}. Mihai Ciucu\r\n    [  ==User(user=\"gogu\" type=\"link\")==  ]\r\n\nVei avea 36h la dispozitie sa rezolvi 10 probleme de algoritmica de\r\ndificultate variata. Concursul incepe Sambata, 29 noiembrie, ora\r\n12:00, ultima submisie fiind acceptata Duminica, 30 noiembrie, ora\r\n24:00. Problemele au fost alese astfel incat concursul sa fie potrivit\r\npentru toti, indiferent de varsta.\r\n\nIn primele 4 ore din concurs evaluatorul va fi oprit. (Se pot trimite\r\nsurse, dar ele nu vor fi evaluate.) In rest, pe toata durata\r\nurmatoare a concursului evaluatorul va fi pornit si la toate\r\nproblemele vor exista si punctaje partiale.\r\n\nIti uram succes si te asteptam sa participi!\r\n\nh2.  Blogul infoarena \n\nPriveste lumea dintr-o alta perspectiva.\r\n\nAfla de ce concursurile la care participi acum iti vor fi de folos in\r\nviitor, ce fac fostii olimpici ai Romaniei, cum e sa lucrezi la\r\nGoogle, Microsoft, si altele. Cosmin Negruseri, gazda blogului, si\r\ninvitatii lui te asteapta cu ganduri si insemnari din experienta lor.\r\n\nIata trei dintre insemnarile recente. Ia-ti o pauza bine meritata si\r\nciteste-le. Asteptam comentariile tale.\r\n\np{padding-left: 2em;}. *   DEX online sub capota\r\n        \'blog/dexonline\':blog/dexonline\r\n\np{padding-left: 2em;}. *   De ce Python?\r\n        \'blog/de-ce-python\':blog/de-ce-python\r\n\np{padding-left: 2em;}. *   De ce este bun un curs de compilatoare si cunoasterea pe net\r\n        \'blog/cunoasterea-pe-net\':blog/cunoasterea-pe-net\r\n\nBlog-ul infoarena poate fi urmarit si prin RSS! Adresa\r\nfeed-ului este: \'blog\':blog?action=rss\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('documentatie/wiki','Ghid infoarena: Wiki','2006-11-21 15:39:50','2009-01-10 12:02:28','h2. Introducere wiki\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nInfoarena este un site bazat pe \'wiki\':http://en.wikipedia.org/wiki/Wiki; tot continutul nostru este editabil (daca ai permisiunile necesare). Poti sa modifici orice pagina publica, nu trebuie decat sa dai click pe link-ul de editare. Te rugam totusi sa nu editezi aceasta pagina (care face parte din \'documentatia\':documentatie oficiala), in schimb poti sa experimentezi in \'groapa cu nisip\':sandbox.\r\n\r\nh2. Textile\r\n\r\nPaginile infoarena sunt scrise intr-un markup foarte light care seamana mult cu plain-text. In loc sa ne inventam propria sintaxa, ne folosim de \'textile\':http://hobix.com/textile/, un markup plain-text foarte puternic si usor de citit. Folosind textile, paginile din infoarena sunt simplu de editat si arata foarte curat.\r\n\r\nO scurta introducere in textile (vezi \'ghidul complet\':documentatie/textile):\r\n\r\n* Poti sa marchezi anumite fraze/cuvinte/etc cu modificatori inline. Spre exemplu poti sa pui *&#42;bold&#42;*, _&#95;italic&#95;_, +&#43;underline&#43;+, ^&#94;superscript&#94;^ si ~&#126;subscript&#126;~. Textile in general aplica aceaste formatari doar cand sunt separate prin punctuatie, etc. Poti sa fortezi formatarea folosin acolade: al{*&#123;&#42;aba&#42;&#125;*}la.\r\n\r\n* Textile stie multe formatari. Daca ceva nu-ti place poti sa faci escape punand @ in jurul pasajului: @@*Non-bold*@@\r\n\r\n* Textile imparte codul in blocuri separate prin linii goale. Poti si pui diverse declaratii pentru a formata blocul. \"h1.\", \"h2. \" fac headere, \"bq. \" face citat, etc.\r\n\r\n* Poti sa faci liste cu sau fara numere punand pe fiecare linie # sau respectiv *.\r\n\r\n* Link-urile se fac cu o sintaxa de genul @\'nume link\':http://adresa/@. Daca adresa nu contine http:// in fata este considerat un link intern infoarena.\r\n\r\n* !>home?rabbits.jpg 100x100! Pentru a posta o imagine pe site, este necesar in prealabil sa o atasezi unei pagini. Imaginile sunt introduse cu sintaxa @!pagina?atasament!@. Poti sa redimensionezi automat imaginile cu @!home?rabbits.jpg 50x50!@.\r\n\r\nh2. Macro-uri\r\n\r\nContinutul paginilor infoarena poate fi imbogatit folosind macro-uri. Scopul principal al macro-urilor este sa afiseze informatii din baza de date fara pagini special. Astfel inclusiv paginile de clasamente sunt usor de editat.\r\n\r\nMacro-uri sunt introduse cu sintaxa @==MacroName(a1=\"b1\" a2=\"b2)==@. Sintaxa de macro-uri este foarte stricta, nu se accepta virgule intre parametri, apostrofi, etc.\r\n\r\nCateva exemple de ce poti face cu macro-uri (vezi \'documentatia completa\':documentatie/macro-uri).\r\n\r\n* Link-uri la utilizatori:\r\n** @==user(user=\"chucknorris\" type=\"tiny\")==@ ==user(user=\"chucknorris\" type=\"tiny\")==\r\n** @==user(user=\"chucknorris\" type=\"normal\")==@ ==user(user=\"chucknorris\" type=\"normal\")==\r\n\r\n* Clasamente:\r\n** Pentru clasamentul unui singur concurs: @==Rankings(rounds = \"preoni2007_runda1_9\")==@\r\n** Pentru clasamentul mai multor concursuri combinat: @==Rankings(rounds = \"runda1 | runda2 | ...\")==@\r\n\r\n* Liste de posturi din forum: \r\n** Pentru topicurile dintr-o sectiune: @== SmfTopics(board_id=\"1\" count=\"10\") ==@\r\n** Pentru posturile dintr-un topic: @== SmfTopic(topic_id=\"1440\") ==@',6273,'public',NULL,NULL),('blog/petr-mitrichev-are-blog','Petr Mitrichev are Blog','2008-11-30 01:40:57','2008-11-30 02:34:39','Am vazut de ceva vreme ca \'Petr\':http://www.google.com/search?hl=en&q=Petr+Mitrichev&btnG=Search , clasat primul la sectia de algoritmica de pe topcoder, si-a facut blog la adresa \'petr-mitrichev.blogspot.com\':http://petr-mitrichev.blogspot.com/ . El domina de cativa ani concursurile de pe topcoder si a fost de doua ori pe locul doi la etapa finala a concursului ACM ICPC.\r\n\r\nPe blog discuta probleme interesante si tehnici din concursuri, iar mai recent a inceput sa isi inregistreze competitiile. E foarte misto sa vezi cum lucreaza cel mai tare concurent la concursurile de programare, sa vezi ca mai are buguri din cand in cand, ca mai revine peste sectiuni de cod, ca nu scrie extraordinar de repede. Si este impresionant cat de repede se prinde de cate o problema sau ce repede se gandeste la teste pentru challange phase.\r\n\r\nLectura placuta!',58,'protected',3411,NULL),('template/algoritmiada-2009/header','template/algoritmiada-2009/header','2008-11-30 14:05:56','2009-04-25 16:01:34','p{margin: 2em 0 1em 0; padding: .2em; border: 1px solid silver; -moz-border-radius: 10px;}. !>algoritmiada-2009?adobe.png 13%!:http://myadobe.ro \'!template/algoritmiada-2009/header?logo.jpg 100%!\':algoritmiada-2009',2028,'protected',NULL,NULL),('template/algoritmiada-2009','template/algoritmiada-2009','2008-11-30 13:51:26','2008-11-30 14:16:34','==include(page=\"template/algoritmiada-2009/header\")==\r\n\r\n(vmenu)*(section) \'*Algoritmiada 2009*\':algoritmiada-2009\r\n* \'Clasament\':algoritmiada-2009/clasament\r\n* \'Organizatori\':algoritmiada-2009/comisie\r\n* \'Sponsori si premii\':algoritmiada-2009/premii\r\n* \'Regulament\':algoritmiada-2009/regulament\r\n* &nbsp;\r\n* \'Runda 1\':algoritmiada-2009/runda-1\r\n* \'Runda 2\':algoritmiada-2009/runda-2\r\n* \'Runda 3\':algoritmiada-2009/runda-3\r\n* \'Runda finala\':algoritmiada-2009/runda-finala\r\n',2028,'protected',NULL,NULL),('template/algoritmiada-2009/footer','template/algoritmiada-2009/footer','2008-11-30 14:38:20','2008-12-12 21:45:49','p{margin: 2em 1em 1em 1em; padding: 1em; height: 5px; border-top: 1px solid silver;}. \r\n',1,'protected',NULL,NULL),('algoritmiada-2009/premii','Algoritmiada 2009 - Sponsori si premii','2008-11-30 14:43:30','2008-11-30 22:17:26','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Sponsori si premii\r\n\r\nh2. Premii\r\n\r\nPentru fiecare dintre cele patru grupe, primii din clasament in urma desfasurarilor probelor online vor fi premiati cu o diploma de finalist al concursului *Algoritmiada 2009* si o \'runda finala\':algoritmiada-2009/runda-finala cu cazare si masa asigurate.\r\nAcestia vor avea sansa sa interactioneze cu membrii \'echipei infoarena\':echipa-infoarena si cu ceilalti membri ai comunitatii infoarena si sa invete de la si impreuna cu acestia. Runda finala va fi de asenemea un prilej de a ii rasplati pe cei mai buni dintre cei mai buni. Punctajele din acesta runda vor fi independente de cele acumulate la rundele online, iar primii 3 clasati la fiecare grupa vor avea parte de urmatoarele premii:\r\n\r\n* Locul I: 500 lei\r\n* Locul II: 300 lei\r\n* Locul III: 200 lei\r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('algoritmiada-2009/regulament','Algoritmiada 2009 - Regulament','2008-11-30 14:48:16','2008-11-30 21:36:54','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Regulament\r\n\r\nSe recomanda, pe langa citirea acestui regulament, citirea \"regulamentului\":regulament general infoarena.\r\n\r\n\'Echipa infoarena\':echipa-infoarena isi rezerva dreptul de a modifica prezentul regulament pe parcursul desfasurarii concursului. Daca apar prevederi noi sau daca anumite prevederi ale regulamentului sunt modificate sau eliminate, atunci acestea vor fi anuntate pe site-ul concursului. Orice modificare a regulamentului va intra in vigoare, in functie de situatie, fie din momentul publicarii ei, fie dupa incheierea rundei aflate in desfasurare. In momentul anuntarii modificarii va fi precizat si momentul din care aceasta intra in vigoare.\r\n\r\nh2. Dreptul de participare\r\n\r\nPersoanele care fac parte din \'echipa infoarena\':echipa-infoarena cat si alti contribuitori implicati direct in organizarea concursului *Algoritmiada 2009* nu au dreptul de a participa. De asemenea, orice concurent care are un comportament considerat inadecvat fata de echipa infoarena sau fata de alti concurenti va fi descalificat. Un concurent se poate califica la finala doar daca se incadreaza in grupa la care a concurat (aceasta verificare se va face prin prezentarea unei dovezi legale care il incadreaza pe concurent la aceea grupa).\r\n\r\nh2. Repartizarea\r\n\r\nToti participantii vor fi repartizati in *4* grupe, in concordanta cu varsta lor. Repartizarea se face astfel\r\n\r\n* Clasele 5-8\r\n* Clasele 9-10\r\n* Clasele 11-12 \r\n* Studenti (facultate, mastrat, doctorat)\r\n\r\nOricine poate participa la o alta grupa decat cea la care se incadreaza, dar calificarea la finala cat si impartirea premiilor se va face conform regulamentului, fara nici o exceptie.\r\n\r\nh2. Inscriere\r\n\r\nTot ce trebuie sa faceti pentru a participa la concursul *Algoritmiada 2009* este sa aveti un cont la infoarena. Inregistrarea se poate face pe site-ul infoarena. Acelasi cont va fi folosit pentru a accesa forum-ul.\r\n\r\nh2. Runde\r\n\r\nVor exista 3 runde de calficare, iar in urma clasamentului stabilit primii de la fiecare grupa vor fi selectati pentru etapa finala desfasurata in cadrul unei tabere. Cele 3 runde vor avea loc duminica, incepand cu ora 9:00, desi pot interveni exceptii. Durata lor va fi de 4 ore. Pentru un program detaliat al concursului \"click aici\":algoritmiada-2009/program.\r\n\r\nh2. Intrebari\r\n\r\nIn prima ora vor putea fi formulate eventualele intrebari, pe forum, in topicurile special create. Orice intrebare pusa in alt mod (primita ca personal message, pe mail, etc.) va fi ignorata. Raspunsuri vor fi oferite doar la intrebarile puse in prima ora . Intrebarile trebuie formulate astfel incat sa se poate raspunda cu _DA_ sau _NU_. In caz contrar sau in cazul in care raspunsul se afla in textul problemei se va raspunde cu _NO COMMENT_. Nu vor exista exceptii de la aceaste reguli. Daca echipa va considera ca raspunsul la o anumita intrebare este de interes general si clarifica anumite aspecte, atunci se va face un anunt general care va aparea atat pe forum cat si in sectiunea Mesaje de la organizatori a grupei respective. Fiecare grupa va avea doi administratori care se vor ocupa de raspunsul acestor intrebari.\r\n\r\nh2. Trimiterea solutiilor\r\n\r\nTrimitrea solutiile se va face prin intermediul interfetei site-ului infoarena.\r\nOdata logati in contul vostru, veti putea selecta arhiva la care doriti sa lucrati (in cazul acesta una din arhivele {*Algoritmiada 2009*}) si veti putea folosi link-ul trimite solutii.\r\n\r\nh2. Evaluare\r\n\r\nEvaluarea solutiilor (\"mai multe detalii aici\":documentatie/evaluator) trimise se face in timp real, insa punctajele nu vor fi facute publice decat la incheirea rundei de concurs. Veti putea vizualiza pozitia ocupata in clasament dupa terminarea rundei in rubrica Concurs.\r\n\r\nSe recomanda sa instalati pe calculatorul vostru aceleasi versiuni de compilatoare ca cele specificate la link-ul de mai sus. \'Echipa infoarena\':echipa-infoarena nu este responsabila pentru diferentele intre versiuni de compilatoare si nu va efectua reevaluaari in astfel de cazuri.\r\n\r\nh2. Contestatii\r\n\r\nEchipa infoarena isi rezerva dreptul de a reevalua orice problema in situatia in care se detecteaza erori in teste sau in programul de verificare dupa evaluare. Cum testele problemelor nu vor fi facute publice, posiblitatile de a contesta sunt limitate. Pentru a asigura o evaluarea corecta, echipa infoarena va garanteaza ca va testa intens toate problemele inainte de concurs si ca va verifica corectitudinea procesului de evaluare dupa terminare. In caz ca totusi aveti o contestatie, aceasta trebuie trimisa pe mail la adresa _andrei.grigorean -at- gmail.com_ in termen de 24 de ore de la afisarea rezultatelor rundei curente pe site. Ele vor fi rezolvate in termen de maxim 5 zile, iar dupa rezolvarea lor rezultatele vor fi declarate finale.\r\n\r\nh2. Solutii\r\n\r\nLa scurt timp dupa terminarea evaluarii se va publica un articol cu solutiile pentru problemele rundei respective. Testele utilizate pentru evaluare nu vor fi facute publice.\r\n\r\nh2. Transferul problemelor\r\n\r\nProblemele vor fi mutate dupa evaluare in \'Arhiva de probleme\':arhiva infoarena, avand astfel la dispozitie un evaluator 24 din 24 si posiblitatea de a finisa solutiile la problemele nerezolvate in timpul concursului.\r\n\r\nh2. Trisare\r\n\r\n*Algoritmiada 2009* este un concurs individual, asadar orice tentativa de colaborare va aduce descalificarea celor implicati. \'echipa infoarena\':echipa-infoarena isi rezerva dreptul de a verifica sursele concurentilor, iar in caz ca se descopera surse aproximativ identice, concurentii respectivi vor fi descalificati din concurs iar user-ul lor de pe infoarena eliminat. Tentativele de frauda (concurarea sub un alt nume decat cel adevarat, etc.) sau orice atac asupra sistemului de evaluare sau asupra paginilor infoarena vor fi pedepsite in aceeasi masura. \r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('algoritmiada-2009/comisie','Algoritmiada 2009 - Organizatori','2008-11-30 14:31:28','2009-05-09 07:49:27','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Organizatori\r\n\r\n\'Echipa infoarena\':echipa-infoarena se ocupa de organizarea si desfasurarea concursului *Algoritmiada 2009*.\r\n\r\nh2. Organizare \r\n\r\n* == user(user=\"wefgef\" type=\"tiny\") == : coordonator concurs\r\n* == user(user=\"wickedman\" type=\"tiny\") == : fonduri, sponsori, presa\r\n* == user(user=\"bogdan2412\" type=\"tiny\") == : coordonator tehnic (site-ul, evaluatorul etc.)\r\n* == user(user=\"svalentin\" type=\"tiny\") == : solutii tehnice pentru finala, diplome\r\n\r\nh2. Echipa stiintifica\r\n\r\nCei care se vor ocupa de buna desfasurarea a concursului din punct de vedere stiintific (redactarea si compunerea problemelor, realizarea testelor, clarificarea intrebarilor, etc.) sunt:\r\n\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"prostu\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n\r\nh2. Multumim\r\n\r\n* &hellip; lui == user(user=\"vlad_d\" type=\"tiny\") == pentru logo-ul Algoritmiada 2009 si tuturor celor care au venit cu sugestii de logo pe \'forum\':forum/index.php?topic=3422.0\r\n\r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',75,'protected',NULL,NULL),('algoritmiada-2009/clasament','Algoritmiada 2009 - Clasament','2008-11-30 15:17:43','2008-11-30 15:38:36','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Clasament \r\n\r\n(htabs)*(active) \'Pe runde...\':algoritmiada-2009/clasament\r\n* \'Clasele 5-8\':algoritmiada-2009/clasament/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/studenti\r\n\r\ntable(layout). |_. Clasament Runda 1 |_. Clasament Runda 3 |\r\n|* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-1/studenti\r\n|* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-3/studenti|\r\n|_. Clasament Runda 2 |\r\n|* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-2/studenti|\r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('template/algoritmiada-2009/clasament-header','template/algoritmiada-2009/clasament-header','2008-11-30 15:30:23','2008-11-30 15:30:23','&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;',2028,'protected',NULL,NULL),('algoritmiada-2009/clasament/5-8','Algoritmiada 2009 - Clasament general, Clasele 5-8','2008-11-30 15:24:28','2008-11-30 15:41:35','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Clasament clasele 5-8\r\n\r\n(htabs)* \'Pe runde...\':algoritmiada-2009/clasament\r\n*(active) \'Clasele 5-8\':algoritmiada-2009/clasament/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/studenti\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda1-5-8|algoritmiada2009-runda2-5-8|algoritmiada2009-runda3-5-8\") == \r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('algoritmiada-2009/clasament/9-10','Algoritmiada 2009 - Clasament general, Clasele 9-10','2008-11-30 15:39:40','2008-11-30 15:49:33','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Clasament clasele 9-10\r\n\r\n(htabs)* \'Pe runde...\':algoritmiada-2009/clasament\r\n* \'Clasele 5-8\':algoritmiada-2009/clasament/5-8\r\n*(active) \'Clasele 9-10\':algoritmiada-2009/clasament/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/studenti\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda1-9-10|algoritmiada2009-runda2-9-10|algoritmiada2009-runda3-9-10\") == \r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',1490,'protected',NULL,NULL),('algoritmiada-2009/clasament/studenti','Algoritmiada 2009 - Clasament general, Studenti','2008-11-30 15:47:31','2008-11-30 15:48:57','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Clasament studenti\r\n\r\n(htabs)* \'Pe runde...\':algoritmiada-2009/clasament\r\n* \'Clasele 5-8\':algoritmiada-2009/clasament/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/11-12\r\n*(active) \'Studenti\':algoritmiada-2009/clasament/studenti\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda1-studenti|algoritmiada2009-runda2-studenti|algoritmiada2009-runda3-studenti\") == \r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('algoritmiada-2009/clasament/11-12','Algoritmiada 2009 - Clasament general, Clasele 11-12','2008-11-30 15:44:31','2008-11-30 15:49:13','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Clasament clasele 11-12\r\n\r\n(htabs)* \'Pe runde...\':algoritmiada-2009/clasament\r\n* \'Clasele 5-8\':algoritmiada-2009/clasament/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2009/clasament/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/studenti\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda1-11-12|algoritmiada2009-runda2-11-12|algoritmiada2009-runda3-11-12\") == \r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('algoritmiada-2009/runda-1','Algoritmiada 2009 - Runda 1','2008-11-30 16:34:11','2008-12-01 17:51:29','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Algoritmiada 2009, Runda 1\r\n\r\n(htabs)*(active) \'Despre...\':algoritmiada-2009/runda-1 \r\n* \'Clasele 5-8\':algoritmiada-2009/runda-1/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2009/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-1/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-1/5-8 \r\n\r\nRunda va incepe *Duminica 14 decembrie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-1/studenti\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':algoritmiada-2009/runda-1/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-1/studenti\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"ditzonec\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"prostu\" type=\"tiny\")==\r\n* ==User(user=\"stef2n\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"domino\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('algoritmiada-2009/runda-1/5-8','Algoritmiada 2009 - Runda 1, Clasele 5-8','2008-11-30 17:12:06','2009-02-03 20:23:59','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda1-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-1 \r\n*(active) \'Clasele 5-8\':algoritmiada-2009/runda-1/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2009/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-1/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-1/5-8\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda1-5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda1-5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda1-5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-1/5-8.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda1-5-8\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',1792,'round: algoritmiada2009-runda1-5-8',NULL,NULL),('algoritmiada-2009/runda-1/9-10','Algoritmiada 2009 - Runda 1, Clasele 9-10','2008-11-30 17:31:46','2008-11-30 17:50:30','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda1-9-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-1 \r\n* \'Clasele 5-8\':algoritmiada-2009/runda-1/5-8 \r\n*(active) \'Clasele 9-10\':algoritmiada-2009/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-1/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-1/9-10\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda1-9-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda1-9-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda1-9-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-1/9-10.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda1-9-10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',2028,'round: algoritmiada2009-runda1-9-10',NULL,NULL),('algoritmiada-2009/runda-1/11-12','Algoritmiada 2009 - Runda 1, Clasele 11-12','2008-11-30 17:33:43','2008-11-30 17:50:44','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda1-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-1 \r\n* \'Clasele 5-8\':algoritmiada-2009/runda-1/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2009/runda-1/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2009/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-1/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-1/11-12\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda1-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda1-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda1-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-1/11-12.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda1-11-12\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',2028,'round: algoritmiada2009-runda1-11-12',NULL,NULL),('algoritmiada-2009/clasament/runda-1/9-10','Algoritmiada 2009 - Clasament Runda 1, Clasele 9-10','2008-11-30 18:00:13','2008-11-30 18:06:30','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda1-9-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-1\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-1/studenti\r\n*(active) \'Rezultate\':algoritmiada-2009/clasament/runda-1/9-10\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-1/5-8\r\n*(active) \'Clasele 9-10\':algoritmiada-2009/clasament/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-1/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda1-9-10\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('algoritmiada-2009/runda-1/studenti','Algoritmiada 2009 - Runda 1, Studenti','2008-11-30 17:52:43','2008-11-30 17:56:49','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda1-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-1 \r\n* \'Clasele 5-8\':algoritmiada-2009/runda-1/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2009/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-1/11-12\r\n*(active) \'Studenti\':algoritmiada-2009/runda-1/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-1/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda1-studenti\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda1-studenti\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda1-studenti\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-1/studenti.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda1-studenti\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',1490,'round: algoritmiada2009-runda1-studenti',NULL,NULL),('algoritmiada-2009/clasament/runda-1/11-12','Algoritmiada 2009 - Clasament Runda 1, Clasele 11-12','2008-11-30 18:09:08','2008-11-30 18:09:08','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda1-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-1\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-1/studenti\r\n*(active) \'Rezultate\':algoritmiada-2009/clasament/runda-1/11-12\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-1/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2009/clasament/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-1/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda1-11-12\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('algoritmiada-2009/clasament/runda-1/studenti','Algoritmiada 2009 - Clasament Runda 1, Studenti','2008-11-30 18:11:51','2008-11-30 18:14:15','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda1-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-1\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-1/studenti\r\n*(active) \'Rezultate\':algoritmiada-2009/clasament/runda-1/studenti\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-1/11-12\r\n*(active) \'Studenti\':algoritmiada-2009/clasament/runda-1/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda1-studenti\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('all-you-can-code-2008/solutii','Solutii All you can code 2008','2008-12-01 12:04:37','2008-12-01 12:05:53','h1. Solutii All you can code 2008\r\n\r\n... Rezumat concurs ...\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Secventa 6\':all-you-can-code-2008/solutii#secv6\r\n* \'Control\':all-you-can-code-2008/solutii#control\r\n* \'Grau\':all-you-can-code-2008/solutii#grau\r\n* \'Take 5\':all-you-can-code-2008/solutii#take5\r\n* \'Drept\':all-you-can-code-2008/solutii#drept\r\n* \'Ktree\':all-you-can-code-2008/solutii#ktree\r\n* \'Segmente\':all-you-can-code-2008/solutii#seg\r\n* \'Transport rutier\':all-you-can-code-2008/solutii#rutier\r\n* \'Tree Search\':all-you-can-code-2008/solutii#treesearch\r\n\r\n==include(page=\"all-you-can-code-2008/solutii/secv6\")==\r\n\r\n==include(page=\"all-you-can-code-2008/solutii/control\")==\r\n\r\n==include(page=\"all-you-can-code-2008/solutii/grau\")==\r\n\r\n==include(page=\"all-you-can-code-2008/solutii/take5\")==\r\n\r\n==include(page=\"all-you-can-code-2008/solutii/drept\")==\r\n\r\n==include(page=\"all-you-can-code-2008/solutii/ktree\")==\r\n\r\n==include(page=\"all-you-can-code-2008/solutii/seg\")==\r\n\r\n==include(page=\"all-you-can-code-2008/solutii/rutier\")==\r\n\r\n==include(page=\"all-you-can-code-2008/solutii/treesearch\")==\r\n',1490,'public',NULL,NULL),('all-you-can-code-2008/solutii/secv6','all-you-can-code-2008/solutii/secv6','2008-12-01 12:07:21','2010-03-30 13:45:44','h2(#secv6). \'Secventa 6\':problema/secv6\r\n\r\nProblema cere determinarea numarului perechilor de indici i, j (i < j) pentru care a{~k~} < a{~i~} si a{~k~} < a{~j~}, unde i < k < j. Sa consideram multimea T a indicilor care verifica relatia de mai sus pentru pozitia p a sirului dat. Daca avem t{~1~} si t{~2~} apartinand lui T, t{~1~} < t{~2~}, cum a{~t1~} < a{~k~} cu t{~1~} < k < p, rezulta ca a{~t2~} < a{~t1~}; asadar multimii ordonate (crescator) T ii corespune o multime ordonate (descrescator) A\'. Multimea A\' poate fi construita cu ajutorul unei stive sortate, la pasul p sunt scoase din stiva elemente mai mici sau egale decat a{~p~} si este introdus elemntul a{~p~}. Stiva construita astfel contine elementele corespunzatoare indicilor multimii T prezentate mai sus, dar contine si elemente in plus (este respectata numai una din conditiile problemei). Observam ca ultimul element care respecta si a doua conditie este, in ordinea stivei sortate, primul element mai mare sau egal decat a{~p~}. In concluzie numarul de indici care respecta conditia pentru pozitia p este egala cu numarul de elemente scoase din stiva sortata la introducerea elementului a{~p~} +1 daca ultimul element scos din stiva este diferit de a{~p~}.',11154,'public',NULL,NULL),('all-you-can-code-2008/solutii/control','all-you-can-code-2008/solutii/control','2008-12-01 12:08:22','2008-12-01 12:08:22','h2(#control). \'Control\':problema/control\r\n\r\n...',1490,'public',NULL,NULL),('all-you-can-code-2008/solutii/grau','all-you-can-code-2008/solutii/grau','2008-12-01 12:08:48','2008-12-01 12:08:48','h2(#grau). \'Grau\':problema/grau\r\n\r\n...',1490,'public',NULL,NULL),('all-you-can-code-2008/solutii/take5','all-you-can-code-2008/solutii/take5','2008-12-01 12:09:46','2008-12-01 12:09:46','h2(#take5). \'Take 5\':problema/take5\r\n\r\n...',1490,'public',NULL,NULL),('all-you-can-code-2008/solutii/drept','all-you-can-code-2008/solutii/drept','2008-12-01 12:10:05','2008-12-01 12:10:05','h2(#drept). \'Drept\':problema/drept\r\n\r\n...',1490,'public',NULL,NULL),('all-you-can-code-2008/solutii/seg','all-you-can-code-2008/seg','2008-12-01 12:11:18','2008-12-01 12:11:18','h2(#seg). \'Seg\':problema/seg\r\n\r\n...',1490,'public',NULL,NULL),('all-you-can-code-2008/solutii/rutier','all-you-can-code-2008/rutier','2008-12-01 12:11:54','2008-12-01 12:11:54','h2(#rutier). \'Transport rutier\':problema/rutier\r\n\r\n...',1490,'public',NULL,NULL),('blog/modele','Modele','2008-12-03 05:35:53','2008-12-03 09:01:28','Discutam cu \'Mircea\':http://www.google.com/search?hl=en&q=Mircea+Pasoi&btnG=Google+Search&aq=f&oq= vara asta despre Eric Schmidt si Steve Jobs. Ii comparam noi si lui Mircea ii placea mai mult de Steve pe cand mie imi placea de Eric. \r\n\r\nPe \'Eric Schmidt\':http://en.wikipedia.org/wiki/Eric_Schmidt am senzatia ca il pot intelege. El este la origine programator. Pe parcursul doctoratului a fost unul dintre creatorii \'Lex\':http://dinosaur.compilertools.net/lex/ un generator de analizatoare lexicografice (probabil ati auzit de lex daca ati facut un curs de compilatoare). A fost Chief Technical Officer la Sun Microsistems, apoi Chief Executive Officer la Novell . Ultimul job pe care il detine e CEO al Google. Lui Eric ii place sa vorbeasca si se gasesc o \'gramada\':http://www.youtube.com/results?search_query=Eric+Schmidt&search_type=&aq=f de interviuri. Opiniile lui sunt bine gandite si argumentate, iar prin ele ma convinge ca este un om valoros.\r\n\r\nPe Steve Jobs in schimb nu il inteleg. El ca personaj e \'foarte cool\':http://www.google.com/search?q=steve+jobs+reality+distortion+field&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-US:official&client=firefox-a si are in spate multe realizari. A revolutionat industria calculatoarelor personale, apoi creand Pixar a revolutionat industria filmelor de animatie. Mai tarziu revenind la Apple a revolutionat industria de mp3 playere si mai recent prin iPhone a revolutionat industria telefoanelor mobile. Sunt mai putine \'materiale\':http://www.youtube.com/results?search_query=Steve+Jobs&search_type=&aq=-1&oq=Steve+Job online despre el, si e mai greu sa vezi de ce Steve are succes.\r\n\r\nPe de o parte Eric e la baza un inginer care a devenit un manager foarte bun. Steve e un product manager exceptional care are o vedere de ansamblu foarte buna. Pentru mine e putin mai greu sa inteleg partile de strategie si de marketing, si acolo exceleaza Steve. Pe langa viziunea macro pe care o are el se concentreaza foarte mult si pe detalii, mai ales pe unele de design. Am auzit indirect de oameni ce lucreaza la Apple la care Steve a venit in birou fara sa fi vorbit cu ei vreodata inainte, si le-a cerut sa mute un buton din aplicatia lor cativa milimetri la stanga.\r\n\r\nConsider discutii de genul asta interesante. Oamenii pe care ii respecti si pe care ii consideri modele, spun ceva despre tine. Acestia arata intr-o anumita masura directia in care vrei sa te indrepti, calitatile pe care le consideri importante si pe care ti-ai dori sa le ai.\r\n\r\nVoi ce parere aveti despre Eric sau Steve si pe ce alti oameni din IT ii respectati?',58,'protected',3441,NULL),('blog/orlando-lanseaza-un-motor-de-cautare-romanesc','Orlando lanseaza un motor de cautare romanesc','2008-12-04 07:19:42','2008-12-04 07:28:19','Orlando Nicoara de la Mediapro Interactiv \'lanseaza\':http://www.orlando.ro/2008/12/03/okidokiro-file-de-poveste/ un motor de cautare romanesc numit \'okidoki.ro\':http://okidoki.ro . Proiectul e destul de ambitios avand in vedere ca Google este foarte folosit in Romania. Eu ii doresc mult succes si sper sa mai apara si alte proiecte la fel de ambitioase in Romania.\r\n\r\nPuteti asculta \'aici\':http://www.trilulilu.ro/blogoree_ro/fe9a7ed527e814 un interviu foarte interesant luat lui Orlano Nicoara de Bobby Voicu. Orlando e foarte vechi in internetul romanesc si are o gramada de realizari, puteti vedea cu ce se lauda \'aici\':http://www.orlando.ro/about/ . Bobby e un blogger destul de cunoscut si reprezentantul Yahoo! in Romania.\r\n',58,'protected',3444,NULL),('runda/drag0sh','drag0sh','2010-01-20 09:37:32','2010-01-20 09:37:32','h1. == roundparam(round_id=\"drag0sh\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"drag0sh\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"drag0sh\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"drag0sh\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"drag0sh\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/drag0sh/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"drag0sh\" score=\"1\")==',3775,'round: drag0sh',NULL,NULL),('blog/problema-saptamanii-cartofi-solutie','Problema saptamanii Cartofi (Solutie)','2008-12-06 07:18:29','2008-12-07 11:36:00','Problema curenta a fost rezolvata de Alexandru Mosoi, Marius Andrei, Igor Naverniouk, Delia David si Dumitru Daniliuc.\r\n\r\nProblema cerea _sa se demonstreze ca, dandu-se doi cartofi, exista o curba inchisa in trei dimensiuni care se poate desena pe suprafetele ambilor cartofi_.\r\n\r\nAceasta e una dintre problemele care par foarte grele la prima vedere si apoi daca auzi sau te prinzi de solutie pare foarte simpla.\r\n\r\nNe imaginam \"fantomele\" cartofilor. Le intersectam. O curba de intersectie a celor doua corpuri ne va da o curba ce poate fi desenata pe suprafete ambilor cartofi.',58,'protected',3453,NULL),('utilizator/tudalex','Profil tudalex','2006-11-24 21:03:03','2009-03-25 20:26:27','\r\nh2. Despre mine\r\n\r\nNimic interesant!\r\n\r\n\r\nh2. Distinctii primite\r\n\r\nUn amarat de loc 2 la ONI 2006 (clasa a 8-a).\r\nSi inca unu la ONI 2007\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* ==User(user=\"eval\" type=\"normal\")==\r\n* ==User(user=\"matah\" type=\"normal\")== You pick on her means you pick on me\r\n\r\n* ==User(user=\"znakeu\" type=\"normal\")== The only master of Darkness that there is!(aah si coleg de clasa mai nou :P)\r\n\r\n* ==User(user=\"xdanx\" type=\"normal\")== One of my best friends\r\n\r\n* ==User(user=\"p1gl3t\" type=\"normal\")== If the nation needs a hero.. we call on to him \r\n* ==User(user=\"slayer4u\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"silviug\" type=\"tiny\")==\r\n* ==User(user=\"webspider\" type=\"tiny\")==\r\n* ==User(user=\"mariusdrg\" type=\"tiny\")==\r\n* ==User(user=\"greco\" type=\"tiny\")==\r\n* ==User(user=\"nivan\" type=\"tiny\")==\r\n* ==User(user=\"adriana_s\" type=\"tiny\")==\r\n* ==User(user=\"protoman\" type=\"tiny\")==',2934,'protected',NULL,NULL),('propuneri/11-rating','IAP #11: Revizuirea functionalitatii ratingului','2008-12-09 22:34:33','2009-01-12 21:16:30','h1. IAP #11: Revizuirea functionalitatii ratingului\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2008-12-10 |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"bogdan2412\")== |\r\n|_. Stare     | *RESPINS* |\r\n\r\nh2(#abstract). Abstract\r\n\r\nSe propune revizuirea sistemului de inregistrare si de calculare a ratingului. Acest IAP nu isi propune sa redreseze problemele existente la nivel de algoritm de calculare a ratingului (ratingul actual nu respecta curba lui Gauss), ci problemele cauzate de faptul ca doar o parte din utilizatorii participanti la un concurs conteaza in calcularea ratingului.\r\n\r\nh2(#motivatie). Motivatie\r\n\r\nConform \'documentatiei\':documentatie/rating, ratingul reprezinta un mod de a masura performantele unui concurent in regim de concurs in raport cu ceilalti concurenti. Sistemul actual de inregistrare / rating permite utilizatorilor sa participe la un concurs fara ca ratingul lor sa fie afectat, fapt ce scade din relevanta ratingului din mai multe motive:\r\n\r\n* In primul rand, pe plan individual, unii concurenti putand fi tentati sa se inregistreze doar la concursurile la care sunt siguri ca vor face bine (elevi de clasele 11-12 care participa la concursuri de gen Junior Challenge), dar nu la concursurile corespunzatoare varstei lor.\r\n* In al doilea rand, pe plan global, datorita faptului ca ratingul pentru un concurent este calculat in functie de rezultatele concurentilor *inregistrati* raportat la rezultatul lui, nu in functie de rezultatele tuturor concurentilor.\r\n\r\nh2(#implementare). Implementare\r\n\r\nIn cadrul \'sedintei din 25 noiembrie 2008\':planificare/sedinta-20081125 au fost propuse doua alternative, fiecare cu avataje si dezavantaje.\r\n\r\nh3(#propunere1). Propunerea 1\r\n\r\nUtilizatorii sunt obligati sa se inregistreze la un concurs pentru a putea submita solutii. Utilizatorii neinregistrati vor putea in continuare sa citeasca problemele, dar vor trebui sa astepte pana cand concursul s-a incheiat pentru a putea trimite solutii la probleme in arhiva. Alternativ, se poate implementa posibilitatea trimiterii solutiilor si de catre utilizatorii neinregistrati, dar acestia sa nu apara in clasament.\r\n\r\nh4. Avantaje\r\n\r\n* Cea mai mare relevanta a sistemului de rating\r\n\r\nh4. Dezavantaje\r\n\r\n* Unii concurenti uita sa se inregistreze (pentru concursuri gen Algoritmiada asta poate fi o problema destul de serioasa). Pana acum, insa, rundele au fost anuntate cu mult timp inainte (1-2 saptamani), deci utilizatorii ar trebui sa aiba destul timp.\r\n* Utilizatorilor carora le pica netul sau curentul si nu deschid problemele tot li se va modifica ratingul.\r\n\r\nh3(#propunere2). Propunerea 2\r\n\r\nEliminam facilitatea de inscriere. In schimb, cand un utilizator trimite o sursa, acesta este automat considerat participant la concurs si ratingul lui va fi modificat la sfarsit.\r\n\r\nh4. Avantaje\r\n\r\n* Utilizatorii nu mai pot sa uite sa se inregistreze.\r\n* Utilizatorilor carora le pica netul si nu apuca nici sa citeasca problemele, dar care s-au inregistrat cu o zi inainte, nu le mai este modificat ratingul.\r\n\r\nh4. Dezavantaje\r\n\r\n* Concurentii care participa la concurs dar nu reusesc sa rezolve nici o problema nu sunt luati in calcul pentru rating, desi acestia au citit problemele si ar trebui sa fie.\r\n* Pentru concursuri lungi de genul Happy Coding, All you can code, utilizatorii (in special studenti, fosti olimpici) nu vor mai putea trimite solutii doar la problemele grele sau care li se par mai interesante fara sa fie considerati ca participanti.\r\n\r\nh3(#propunere3). Propunerea 3\r\n\r\nEliminam toate functionalitatea de rating / inregistrare pentru ca ne creaza prea multe probleme. :)\r\n\r\nh2(#feedback). Feedback\r\n\r\nIntra pe \'forum\':forum/index.php?topic= pentru a da feedback.',1,'public',3543,NULL),('tree-decompositions','Tree decompositions','2008-01-10 13:06:32','2009-02-20 01:06:49','h1. Tree decompositions\r\n\r\n(Categoria _Algoritmi_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Continut:*\r\n* \'Liniarizare\':tree-decompositions#liniarizare\r\n** \'{*} Solutie $O((M+N)*log(N))$\':tree-decompositions#solutie-liniarizare\r\n* \'Descompunere in lanturi\':tree-decompositions#descompunere-in-lanturi\r\n** \'{*} Solutie $O(M*N)$\':tree-decompositions#solutie-brute\r\n** \'{*} Solutie $O(M*sqrt(N)*log(N))$\':tree-decompositions#solutie-sqrt-log\r\n** \'{*} Solutie $O(M*log^2^(N))$\':tree-decompositions#solutie-log-log\r\n* \'Aplicatii\':tree-decompositions#aplicatii\r\n* \'Bibliografie\':tree-decompositions#bibliografie\r\n\r\nAcest articol prezinta modalitati de prelucrare a unui arbore pentru calcularea eficienta a unei sume si a valorii maxime / minime aflate pe lantul elementar dintre doua noduri. Mentionez ca, in acest articol, $lant$ va insemna intotdeauna $lant elementar$ (un nod poate aparea cel mult o data).\r\n\r\nh2(#liniarizare). Liniarizare\r\n\r\nUn enunt care apare frecvent la concursurile de informatica este urmatorul:\r\n\r\nFie <tex> G = (V, E) </tex> un graf neorientat conex, <tex> |E| = |V| - 1 </tex> (pe scurt, un arbore). Vom considera ca fiecare nod <tex> x \\in V </tex> are asociata o valoare <tex> value[x] </tex> din multimea numerelor reale. Se dau $M$ instructiuni, $M &le; 200000$, de doua tipuri: \r\n\r\n* instructiunile de primul tip cer sa se afiseze suma valorilor tuturor nodurilor ce se afla pe lantul dintre <tex> x, y \\in V </tex> (practic, daca <tex> P = (x_{0}, x_{1}, x_{2}, ..., x_{n}) </tex>, <tex> x_{0} = x </tex>, <tex> x_{n} = y </tex>, este lantul ce uneste cele doua noduri, atunci se cere <tex> \\Delta = \\displaystyle\\sum_{u \\in P} value[u] </tex>)\r\n* cele de al doilea tip modifica valoarea atasata unui nod.\r\n\r\nh3(#solutie-liniarizare). Solutie $O((M+N)*log(N))$\r\n\r\nSolutia se foloseste de o tehnica numita liniarizarea arborelui. Aceasta presupune o parcurgere in adancime si retinerea unor informatii necesare pentru interogare si actualizare: <tex> seq[\\ ] </tex>, <tex> firstPos[\\ ] </tex>, <tex> lastPos[\\ ] </tex>. Iata pseudocodul acestei parcurgeri:\r\n\r\n== code(c) |\r\nPARCURGE(x)\r\n    seq_len++\r\n    seq[seq_len] = value[x]\r\n    firstPos[x] = seq_len\r\n\r\n    pentru fiecare fiu y al lui x executa\r\n        PARCURGE(y) // apeleaza recursiv pentru y\r\n    sfarsit pentru\r\n\r\n    seq_len++\r\n    seq[seq_len] = -value[x]\r\n    lastPos[x] = seq_len\r\n==\r\n\r\np=. !tree-decompositions?fig1.jpg!\r\n\r\np=. _Fig. 1: Pentru arborele de mai sus si vectorul de valori_ <tex> value[\\ ] = \\{3, 5, 7, 1, 2, 4\\} </tex>, <tex> seq[\\ ] </tex> _construit este ilustrat in figura. Se observa usor ca tot subarborele unui nod se anuleaza cand este explorat in intregime._\r\n\r\nS-a construit, astfel, vectorul <tex> seq[\\ ] </tex> care are urmatoarea proprietate: \"daca <tex> \\Delta = \\displaystyle\\sum_{i = firstPos[x]}^{firstPos[y]} seq[i] </tex>, <tex> x </tex> fiind un stramos al lui <tex> y </tex>, atunci <tex> \\Delta = \\displaystyle\\sum_{u \\in P} value[u] </tex>, <tex> P = (x_{0}, x_{1}, x_{2}, ..., x_{n}) </tex>, <tex> x_{0} = x </tex>, <tex> x_{n} = y </tex>\". Conform acesteia, daca vom determina cel mai apropiat stramos comun pentru doua noduri, atunci nu va fi nevoie decat de o structura de date ce permite calcularea intr-un mod eficient a sumei pe un interval din <tex> seq[\\ ] </tex> si modificarea unei valori din acest vector. Putem obtine complexitatea $O(log(N))$ pe fiecare din cele doua operatii folosind structura de date numita $arbori de intervale$. Pentru determinarea eficienta a celui mai apropiat stramos comun si pentru detalii despre arborii de intervale consultati \'bibliografia\':tree-decompositions#bibliografie.\r\n\r\nh2(#descompunere-in-lanturi). Descompunere in lanturi\r\n\r\nAcum ne vom concentra asupra urmatoarei sarcini, de determinare a valorii maxime / minime. Sa urmarim enuntul de mai jos.\r\n\r\nFie <tex> G = (V, E) </tex> un graf neorientat conex, <tex> |E| = |V| - 1 </tex> (tot un arbore). Vom considera, bineinteles, ca fiecare nod <tex> x \\in V </tex> are asociata o valoare <tex> value[x] </tex> din multimea numerelor reale. Se dau $M$ instructiuni, $M &le; 200000$, de doua tipuri:\r\n\r\n* primul tip de instructiuni cere sa se scrie maximul dintre valorile nodurilor ce se afla pe lantul dintre <tex> x, y \\in V </tex> (daca <tex> P = (x_{0}, x_{1}, x_{2}, ..., x_{n}) </tex>, <tex> x_{0} = x </tex>, <tex> x_{n} = y </tex>,  atunci se cere <tex> \\Delta = \\max \\{value[u]\\ /\\ u \\in P \\} </tex>)\r\n* al doilea tip modifica valoarea asociata unui nod.\r\n\r\nh3(#solutie-brute). Solutie $O(M*N)$\r\n\r\nSunt o multitudine de solutii simple ce ne pot trece prin minte. Pentru cea aleasa de mine voi retine un vector <tex> parent[\\ ] </tex>, semnificand parintele unui nod calculat printr-o parcurgere in adancime, si un vector <tex> depth[\\ ] </tex> ce retine adancimea, adica numarul de muchii de la radacina pana la nodul interogat. Cu ajutorul lor, prima cerinta se rezolva in $O(N)$ astfel: pornesc din cele doua noduri si merg \"in sus\" pe arbore, in paralel (raportat la <tex> depth[\\ ] </tex>), pana cand ajung in cel mai apropiat stramos comun, retinand pe parcurs valoarea maxima ceruta. Rezolvarea cerintei a doua se face simplu in $O(1)$, modificand direct <tex> value[\\ ] </tex>.\r\n\r\nh3(#solutie-sqrt-log). Solutie $O(M*sqrt(N)*log(N))$\r\n\r\nTehnica liniarizarii arborelui nu ne este de folos in acest caz, deoarece modul de reprezentare a informatiilor nu permite obtinerea unei complexitati mai bune fata de \'solutia lenta\':tree-decompositions#solutie-brute prezentata mai sus.\r\n\r\nO solutie mai buna foloseste asa numita tehnica $longest path decomposition$, tehnica ce necesita cunostine minime despre grafuri si cu care vom obtine complexitatea $O(M*sqrt(N)*log(N))$ urmand pasii de mai jos:\r\n\r\n# Se elimina cel mai lung lant radacina-frunza din arbore si se apeleaza recursiv pentru restul componentelor conexe;\r\n# Se retine fiecare lant ca un vector <tex> Path[\\ ].array[\\ ] </tex> cu noduri ordonate crescator dupa adancime si se pastreaza un pointer catre nodul din lantul sau parinte <tex> Path[\\ ].parent </tex>;\r\n# Pentru fiecare nod se retine lantul caruia apartine <tex> whatPath[\\ ] </tex> si pozitia in vectorul lantului <tex> whatPos[\\ ] </tex>.\r\n\r\nEste evident ca memoria ocupata este $O(N)$, fiecare nod fiind inclus intr-un singur lant. Numarul maxim de lanturi prin care putem trece pornind din radacina pana intr-una din frunze, este $O(sqrt(N))$.\r\n\r\np=. !tree-decompositions?Figura2.jpg!\r\n\r\np=. _Fig. 2: Cazul defavorabil cand sunt $O(sqrt(N))$ lanturi elementare._\r\n\r\nFie  <tex> x, y \\in V </tex>, <tex> x </tex> stramos al lui <tex> y </tex>. Functia care determina valoarea maxima pe lantul dintre <tex> x </tex> si <tex> y </tex> este prezentata in urmatorul pseudocod:\r\n\r\n== code(c) |\r\nQUERY(x, y)\r\n    ret = value[x]\r\n    cat timp x diferit de y executa\r\n        daca whatPath[x] = whatPath[y] atunci\r\n            ret = Maxim(ret, QUERYAi(Path[whatPath[y]], whatPos[x], whatPos[y]))\r\n            y = x\r\n        altfel\r\n            ret = Maxim(ret, QUERYAi(Path[whatPath[y]], 1, whatPos[y]))\r\n            y = Path[whatPath[y]].parent\r\n        sfarsit daca\r\n    sfarsit cat timp\r\n    returneaza ret\r\n==\r\n\r\nFunctia $QUERYAi(Path[], lo, hi)$ returneaza in $O(log(N))$, cu ajutorul structurii de date $arbori de intervale$, maximul dintre valorile cuprinse in intervalul $[lo, hi]$. Raspunsul cerintei de primul tip va fi {$Maxim(QUERY (lca, x), QUERY (lca, y))$}, variabila <tex> lca </tex> fiind cel mai apropiat stramos comun al lui <tex> x </tex> si <tex> y </tex>. Pentru rezolvarea cerintei de tipul doi, vom folosi aceiasi arbori de intervale care vor avea un cost de $O(log(N))$ pe operatie. Nu voi prezenta aceasta functie, ea fiind in detaliu prezentata in una din sursele afisate in \'bibliografie\':tree-decompositions#bibliografie.\r\n\r\nComplexitatea finala: $O(M*sqrt(N)*log(N))$. Cel mai rau caz pentru un query este cand se trece prin toate lanturile (in numar de $sqrt(N)$) efectuandu-se cate un query pe fiecare arbore de intervale asociat ({$O(log(N))$}).\r\n\r\nh3(#solutie-log-log). Solutie $O(M*log^2^(N))$\r\n\r\nO imbunatatire la solutia \'precedenta\':tree-decompositions#solutie-sqrt-log o reprezinta $heavy path decomposition$, care se foloseste de acelasi algoritm, cu exceptia faptului ca fiul ales pentru determinarea unui lant este cel cu numar maxim de noduri in subarborele sau ({$heavy$}), si nu cel cu inaltimea maxima ({$longest$}). Prin urmare, numarul maxim de lanturi prin care se trece pentru a ajunge de la un nod la radacina este cel mult $O(log(N))$ dupa cum se poate vedea si din figura urmatoare:\r\n\r\np=. !tree-decompositions?Figura3.jpg!\r\n\r\np=. _Fig. 3: Fiecare nod apartine unui singur lant. Lanturile sunt reprezentate de muchii solide._\r\n\r\nComplexitatea finala: $O(M*log^2^(N))$. In practica, aceasta tehnica se comporta foarte bine si poate fi folosita cu succes. Singurul inconvenient este numarul mare de linii de cod scrise.\r\n\r\nh2(#aplicatii). Aplicatii\r\n\r\n* \"Query on a tree\":http://www.spoj.pl/problems/QTREE/\r\n* \"Caves and tunnels\":http://acm.timus.ru/problem.aspx?space=1&num=1553 - Petrozavodsk training camp, 2007\r\n* \"Delay\":problema/delay - Lotul National de Informatica, 2002\r\n* \"Omizi\":problema/omizi - .campion, 2005\r\n* \"Arbfind\":problema/arbfind - Lotul National de Informatica, 2006\r\n* \"CT\":problema/ct - Happy Coding, 2006\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* Thomas H. Cormen, Charles E. Leiserson, Ronald R. Rivest - _\"Introducere in Algoritmi\"_\r\n* Dana Lica - \"_Arbori de intervale si aplicatii in geometria computationala_\":arbori-de-intervale\r\n* Daniel Pasaila - \"_Range Minimum Query and Lowest Common Ancestor_\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=lowestCommonAncestor\r\n* Emilian Miron - \"_Lowest Common Ancestor_\":lowest-common-ancestor\r\n* Michael A. Bender, Martin Farach-Colton - \"_The level ancestor problem simplified_\":http://cs.sunysb.edu/~bender/pub/latin02-level.ps\r\n* Oren Weimann - \"_Advanced data structures_\":http://courses.csail.mit.edu/6.851/spring07/scribe/lec09.pdf\r\n',2044,'public',3694,NULL),('newsletter/algoritmiada-2009-1','Incepe Algoritmiada! Acum si pentru studenti','2008-07-02 17:51:25','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nIncepe Algoritmiada, cel mai mare si mai important concurs organizat\r\nde infoarena!\r\n\nLa Algoritmiada participa elevi de gimnaziu, elevi de liceu, *dar si\r\nstudenti,* si chiar masteranzi sau doctoranzi! (Avem grupe separate\r\npentru fiecare.)\r\n\nAlgoritmiada se desfasoara in 4 runde: 3 runde online de calificare,\r\nsi o runda finala on-site la care invitam concurentii cu cele mai\r\nbune punctaje. Cei mai buni vor castiga premii serioase, in bani si\r\nobiecte.\r\n\nRunda 1 se desfasoara in acest weekend. Te asteptam in arena! Arata\r\nce stii la Algoritmiada.\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Runda 1 se desfasoara\r\n\np{padding-left: 4em;}. Duminica, 14 Decembrie 2008, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nVezi pagina concursului: \'algoritmiada-2009\':algoritmiada-2009\r\npentru mai multe informatii.\r\n\nSucces!\r\n\nh2.  Atentie! Concurs cu rating! \n\nDaca vrei sa ti se modifice rating-ul in urma acestei runde trebuie\r\nsa iti anunti participarea din timp. Intra pe\r\n\'algoritmiada-2009/runda-1\':algoritmiada-2009/runda-1 si inscrie-te.\r\n\nPoti sa participi la concurs chiar si daca nu te-ai inscris in\r\nprealabil insa nu ti se va modifica rating-ul. ==NewsletterRating(username=\"%username%\")==\r\nCiteste despre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Despre Algoritmiada \n\nAlgoritmiada este un concurs nou, cu premii, organizat de infoarena.\r\n\nAi participat in anii trecuti la preONI? Algoritmiada este\r\ncontinuarea seriei preONI, un concurs mai mare, mai distractiv, si cu\r\npremii mai frumoase.\r\n\nSubiectele vor fi propuse de catre o echipa de fosti si actuali\r\nolimpici la informatica: Airinei Adrian, Bogdan Tataroiu, Adrian\r\nDiaconu, Andrei Grigorean, Gheorghe Cosmin, Filip Stefan, si Stefan\r\nIstrate. De ce ei? Intra pe pagina rundei si citeste cate ceva despre\r\nexperienta fiecaruia: \'algoritmiada-2009/runda-1\':algoritmiada-2009/runda-1\r\n\nLa Runda 1 vei avea la dispozitie 4h sa rezolvi 3 probleme de natura\r\nalgoritmica. Concurentii sunt impartiti in 4 grupe de varsta:\r\ngimnaziu, clasele 9-10, clasele 11-12, si studenti (inclusiv\r\nmasteranzi si doctoranzi).\r\n\nIntra pe pagina concursului ca sa afli mai multe:\r\n\'algoritmiada-2009\':algoritmiada-2009\r\n\nIti uram succes si te asteptam in arena!\r\n\nh2.  Seria de concursuri preONI s-a incheiat \n\nDupa 5 ani, seria de concursuri preONI se retrage. Cel mai longeviv\r\nconcurs infoarena, cel mai amplu eveniment organizat de noi pana\r\nacum, cu o traditie lunga si cu mii de participanti, se incheie.\r\n\nDe anul acesta incepe Algoritmiada. Vom incerca sa aplicam lectiile\r\ninvatate pana acum, insa avem nevoie de ajutorul tau. Fii alaturi de\r\nnoi, contacteaza-ne pe forum, ajuta-ne sa facem din Algoritmiada o\r\ncompetitie la care ti-ar placea sa participi oricand.\r\n\nAi participat vreodata la preONI? Iti mai aduce aminte ce fel a fost,\r\nce probleme ai primit? Ti-am facut poze la finala? Viziteaza inca\r\nodata paginile editiilor anterioare:\r\n\np{padding-left: 2em;}. *   preONI 2008, finala la Univ. Politehnica, Bucuresti\r\n        \'preoni-2008\':preoni-2008\r\n\np{padding-left: 2em;}. *   preONI 2007, finala la Lic. Int. de Informatica, Bucuresti\r\n        \'preoni-2007\':preoni-2007\r\n\np{padding-left: 2em;}. *   preONI 2006, finala la C. N. \"Unirea\", Focsani\r\n        \'preoni-2006\':preoni-2006\r\n\np{padding-left: 2em;}. *   preONI 2005, finala online\r\n        \'preoni-2005\':preoni-2005\r\n\np{padding-left: 2em;}. *   preONI 2004, finala online\r\n        \'preoni-2004\':preoni-2004\r\n\nh2.  Blogul infoarena \n\nAfla de ce concursurile la care participi acum iti vor fi de folos in\r\nviitor, ce fac fostii olimpici ai Romaniei, cum e sa lucrezi la\r\nGoogle, Microsoft, si altele. Cosmin Negruseri, gazda blogului, si\r\ninvitatii lui te asteapta cu ganduri si insemnari din experienta lor.\r\n\nIata trei dintre insemnarile recente. Ia-ti o pauza bine meritata si\r\nciteste-le. Asteptam comentariile tale.\r\n\np{padding-left: 2em;}. *   DEX online sub capota\r\n        \'blog/dexonline\':blog/dexonline\r\n\np{padding-left: 2em;}. *   De ce Python?\r\n        \'blog/de-ce-python\':blog/de-ce-python\r\n\np{padding-left: 2em;}. *   De ce este bun un curs de compilatoare si cunoasterea pe net\r\n        \'blog/cunoasterea-pe-net\':blog/cunoasterea-pe-net\r\n\nBlog-ul infoarena poate fi urmarit si prin RSS! Adresa\r\nfeed-ului este: \'blog\':blog?action=rss\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nh2.  Fii un bun infoarenaut! Implica-te! \n\nMai mult ca oricand, infoarena are nevoie de ajutorul tau! infoarena\r\neste un efort colectiv, munca a zeci de voluntari pe parcursul a 5\r\nani de zile.  Vrem sa-i sprijinim pe toti cei care, pasionati de\r\ninformatica si programare, vor sa invete mai mult, vor sa isi\r\nperfectioneze abilitatile.\r\n\nVrei sa compui problemele tale? Vrei sa organizezi concursuri? Iti\r\nplace sa programezi, doresti sa inveti cum se dezvolta un site precum\r\ninfoarena?  Vrei sa redactezi articole despre algoritmi si structuri\r\nde date? Pentru toate acestea, si pentru multe altele, infoarena are\r\nnevoie de ajutorul tau!\r\n\nAfla cum te poti implica in comunitatea infoarena:\r\n\'implica-te\':implica-te\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n\n',13,'protected',NULL,NULL),('utilizator/mjoska','Profil mjoska','2008-12-13 10:18:21','2008-12-13 10:18:21','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',9137,'public',NULL,NULL),('articole/template-limbaje-de-programare','articole/template-limbaje-de-programare','2008-12-13 14:59:53','2008-12-13 15:00:16','* \'STL\':stl\r\n* \'Introducere in asamblare\':introducere-in-asamblare\r\n* {\'12 ponturi pentru programatorii C/C++\':12-ponturi-pentru-programatorii-cc}\r\n* \'Multe &quot;smenuri&quot; de programare in C/C++... si nu numai!\':multe-smenuri-de-programare-in-cc-si-nu-numai',2044,'protected',NULL,NULL),('articole/template-diverse','articole/template-diverse','2008-12-13 15:13:04','2009-12-29 03:18:04','* \'Optimizarea programelor folosind operaţii pe biţi\':operatii-pe-biti\r\n* \'Concursul de informatica &#40;de la agonie la extaz&#41;\':concursul-de-informatica\r\n* \'Ghid complet pentru concursurile de informatica\':ghid-complet-pentru-concursurile-de-informatica\r\n* \'DJGPP - instalarea de la A la Z\':djgpp-instalarea-de-la-a-la-z',3146,'protected',NULL,NULL),('articole/solutii','Solutii (oficiale) la diverse competitii','2008-12-13 14:42:08','2009-02-27 00:06:17','h1. Solutii (oficiale) la diverse competitii\r\n\r\ntable(layout){width:75%}. | ==include(page=\"articole/template-solutii\" display=\"list-item\")== |\r\n\r\n\'_« inapoi la pagina principala_\':articole',2044,'protected',NULL,NULL),('articole/algoritmi','Algoritmi si tehnici de programare','2008-12-13 15:05:43','2009-02-27 00:05:42','h1. Algoritmi si tehnici de programare\r\n\r\ntable(layout){width:75%}. | ==include(page=\"articole/template-algoritmi\" display=\"list-item\")== |\r\n\r\n\'_« inapoi la pagina principala_\':articole',2044,'protected',NULL,NULL),('articole/structuri-de-date','Structuri de date','2008-12-13 14:26:32','2009-02-27 00:06:30','h1. Structuri de date\r\n\r\ntable(layout){width:75%}. | ==include(page=\"articole/template-structuri-de-date\" display=\"list-item\")== |\r\n\r\n\'_« inapoi la pagina principala_\':articole',2044,'protected',NULL,NULL),('articole/limbaje-de-programare','Limbaje de programare','2008-12-13 14:57:59','2009-02-27 00:07:00','h1. Limbaje de programare\r\n\r\ntable(layout){width:75%}. | ==include(page=\"articole/template-limbaje-de-programare\" display=\"list-item\")== |\r\n\r\n\'_« inapoi la pagina principala_\':articole',2044,'protected',NULL,NULL),('articole/matematica','Matematica','2008-12-13 15:02:49','2009-02-27 00:06:43','h1. Matematica\r\n\r\ntable(layout){width:75%}. | ==include(page=\"articole/template-matematica\" display=\"list-item\")== |\r\n\r\n\'_« inapoi la pagina principala_\':articole',2044,'protected',NULL,NULL),('articole/diverse','Diverse','2008-12-13 15:12:10','2009-02-27 00:07:10','h1. Diverse\r\n\r\ntable(layout){width:75%}. | ==include(page=\"articole/template-diverse\" display=\"list-item\")== |\r\n\r\n\'_« inapoi la pagina principala_\':articole',2044,'protected',NULL,NULL),('algoritmiada-2009/runda-1/solutii','Solutii Algoritmiada 2009 Runda 1','2008-12-01 12:04:37','2008-12-17 12:04:02','h1. Solutii Algoritmiada 2009, Runda 1\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Tablete\':algoritmiada-2009/runda-1/solutii#tablete\r\n* \'Densitate\':algoritmiada-2009/runda-1/solutii#densitate\r\n* \'Propozitie\':algoritmiada-2009/runda-1/solutii#propozitie\r\n* \'Jstc\':algoritmiada-2009/runda-1/solutii#jstc\r\n* \'Coprime\':algoritmiada-2009/runda-1/solutii#coprime\r\n* \'Scandura\':algoritmiada-2009/runda-1/solutii#scandura\r\n* \'Piese2\':algoritmiada-2009/runda-1/solutii#piese2\r\n* \'Sprim\':algoritmiada-2009/runda-1/solutii#sprim\r\n* \'Kprime\':algoritmiada-2009/runda-1/solutii#kprime\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/tablete\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/densitate\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/propozitie\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/jstc\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/coprime\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/scandura\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/piese2\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/sprim\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/kprime\")==',1490,'public',NULL,NULL),('utilizator/florinov','Profil FlorinOv','2008-12-14 09:55:30','2008-12-14 09:55:30','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',9161,'public',NULL,NULL),('algoritmiada-2009/runda-1/solutii/tablete','Tablete','2008-12-14 13:01:41','2008-12-17 11:37:45','h1(#tablete). \'Tablete\':problema/tablete\r\n\r\nPe baza a catorva observatii, se poate gasi o multitudine de reguli de completare a matricii $N x N$, tinand cont de restrictiile din enunt. Iata o solutie posibila, cu mentiunea ca nu e singura:\r\n\r\n* Daca $K$ este par, se completeaza dreptunghiul $N x K$ (partea din stanga a matricii) in ordine, de la stanga la dreapta si de sus in jos, cu numerele de la $1$ la $N x K$.\r\n* Daca $K$ este impar, iar $N$ par, se iau iarasi numerele in ordine crescatoare si se completeaza dreptunghiul $N x K$ (partea din stanga) pe fasii de $2 x K$ in felul urmator:\r\n\r\ntable{text-align:center; width:200px;}.\r\n| 1 | 2 | ... | K - 1 | K + 1 |\r\n| K | K + 2 | ... | 2 * K - 1 | 2 * K |\r\n\r\n* Daca $K$ este impar, iar $N$ este tot impar, se completeaza ca mai sus pe fasii, cu mentiunea ca ultima fasie va fi completata pe jumatate, iar ultima linie din dreptunghiul $N x K$ va contine numerele $(N - 1) * K + 1, (N - 1) * K + 2, ..., N * K - 1, N * K + 1$. Valoarea $N * K$ o putem pune in pozitia $(1, K + 1)$.\r\n\r\nIn toate situatiile de mai sus, partea din dreapta a matricii ramasa necompletata se completeaza de la stanga la dreapta si de sus in jos cu numerele ramase. Astfel, toate restrictiile din enunt sunt satisfacute.',2044,'public',NULL,NULL),('algoritmiada-2009/runda-1/solutii/jstc','Jstc','2008-12-14 13:11:41','2008-12-16 17:01:22','h1(#jstc). \'Jstc\':problema/jstc\r\n\r\nPrima observatie necesara in rezolvarea problemei este faptul ca stiva este intotdeauna crescatoare. A doua observatie este ca raspunsul pentru un anumit numar $x$ poate doar sa creasca dupa diferite operatii de tip insert sau erase (el poate sa fie si $-1$ dar acesta este un caz particular usor de rezolvat). \r\nIn continuare ideea rezolvarii este una gen \"multimi disjuncte\". Vom tine pentru fiecare numar $x$ care poate aparea ca query $nxt[x]$ ce reprezinta un numar mai mare ca $x$ dar care sigur nu sare de urmatorul numar mai mare ca $x$ ce se afla momentan in stiva. Cum zicea a doua observatie $nxt[x]$ poate doar sa creasca in urma diverselor operatii. Acum pentru a cauta raspunsul si anume primul numar din stiva mai mare sau egal cu $x$ vom parcurge pe rand $nxt[x]$, $nxt[nxt[x]]$, $nxt[nxt[nxt[x]]]$... pana cand gasim un numar care se afla in stiva (putem tine un vector de char sau unul pe biti pentru a verifica daca un numar se afla in stiva sau nu rapid, sau pentru $x$ ce se afla in stiva sa tinem $nxt[x] = x$). Tot conform celei de a doua observatii putem acum sa modificam valorile $nxt[x]$, $nxt[nxt[x]]$, $nxt[nxt[nxt[x]]]$... in raspunsul pentru intrebarea x. Astfel drumurile se vor \"compacta\" si nu vom parcurge de prea multe ori aceleasi drumuri pentru ca este inutil. \r\nAceasta abordare duce la o complexitate aproximativ $O(1)$ amortizat pe intrebare, ce obtine punctajul maxim.\r\n\r\nAlta solutie evidenta era cautarea binara dar aceasta nu ia punctaj maxim.',2038,'public',NULL,NULL),('algoritmiada-2009/runda-1/solutii/coprime','Coprime','2008-12-14 13:12:18','2008-12-16 16:47:28','h1(#coprime). \'Coprime\':problema/coprime\r\n\r\nVom modela problema sub forma unui graf in care colegii Mirunei reprezinta nodurile, iar perechile de copii care au primit bomboane ce reprezinta doua numere prime intre ele muchiile. Va trebui sa atribuim fiecarui nod {$x$} o valoare {$N[x]$}, astfel incat sa existe o muchie {$(x, y)$} daca si numai daca {$(N[x], N[y]) = 1$}. Initial vom atribui fiecarui nod valoarea $1$. Apoi, vom considera fiecare muchie care **nu** apare in graf, si vom inmulti valorile capetelor sale cu un numar prim care nu a mai fost folosit anterior. La sfarsit vom afisa valorile obtinute. Este necesara folosirea numerelor mari, iar pentru a nu afisa prea multe cifre trebuie considerate cele mai mici numere prime posibile.',2028,'public',NULL,NULL),('2-sat','Problema 2-satisfiabilității','2008-12-09 15:55:03','2010-01-14 18:51:23','h1. Problema 2-satisfiabilităţii\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"marius\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 30em}*{text-align:center} *Conţinut:*\r\n* {\'Introducere\':2-sat#introducere}\r\n* {\'Forme normale ale formulelor logice\':2-sat#forme-normale}\r\n* {\'SAT, 3-SAT, 2-SAT\':2-sat#overview-sat}\r\n* {\'Soluţii pentru 2-SAT\':2-sat#solutii-2-sat}\r\n** {\'Soluţie $O(M * 2^N^)$\':2-sat#solutie-1}\r\n** {\'Soluţie $O(N * M)$\':2-sat#solutie-2}\r\n** {\'Soluţie $O(N^2^ * M)$\':2-sat#solutie-3}\r\n** {\'Soluţie $O(M + N)$\':2-sat#solutie-4}\r\n* {\'Aplicaţii\':2-sat#aplicatii}\r\n** {\'Party &#40;preONI 2003/2004&#41;\':2-sat#party}\r\n** {\'Cigraf\':2-sat#cigraf}\r\n** {\'Orpath &#40;Olimpiadă Rusia&#41;\':2-sat#orpath}\r\n** {\'Aladdin &#40;Bursele Agora 2005/2006, Runda 1&#41;\':2-sat#aladdin}\r\n* {\'Probleme propuse\':2-sat#probleme}\r\n* {\'Bibliografie\':2-sat#bibliografie}\r\n\r\nh2(#introducere). Introducere\r\n\r\nProblema satisfiabilităţii, notată prescurtat cu $SAT$, cere determinarea existenţei pentru o formulă booleană <tex> \\phi </tex> a unei atribuiri satisfiabile. O formulă booleană <tex> \\phi </tex> este compusă din $variabile$ logice <tex> (x_{1}, x_{2}, ...) </tex>, $operatori$ logici ( <tex> \\wedge </tex> şi,  <tex> \\vee </tex> sau, <tex> \\sim </tex> non, <tex> \\rightarrow </tex> implicaţie, <tex> \\leftrightarrow </tex> echivalenţă), şi $paranteze$. O atribuire de valori booleene pentru variabilele acestei expresii se numeşte $atribuire satisfiabilă$ dacă evaluarea expresiei după atribuirea valorilor dă ca rezultat valoarea de adevăr $adevărat$. De acum încolo vom folosi pentru simplitate valorile <tex> 1 </tex> şi <tex> 0 </tex> în loc de $adevărat$ şi $fals$.\r\n\r\nUn exemplu de formulă ar fi <tex> \\phi = ((x_{1} \\rightarrow x_{2}) \\vee \\sim((\\sim x_{1} \\leftrightarrow x_{3}) \\vee x_{4})) \\wedge \\sim x_{2} </tex>. Aceasta are atribuirea satisfiabilă <tex> \\langle x_{1} = 0, x_{2} = 0, x_{3} = 1, x_{4} = 1 \\rangle </tex> pentru că <tex> \\phi = ((0 \\rightarrow 0) \\vee \\sim((\\sim 0 \\leftrightarrow 1) \\vee 1)) \\wedge \\sim 0 = (1 \\vee \\sim (1 \\vee 1)) \\wedge 1 = (1 \\vee 0) \\wedge 1 = 1</tex>. \r\n\r\nh2(#forme-normale). Forme normale ale formulelor logice\r\n\r\nOrice formulă booleană poate fi transformată în două forme:\r\n\r\n* $Forma normal conjunctivă$ în care expresia este exprimată ca o conjuncţie de propoziţii, iar fiecare propoziţie este formată dintr-o disjuncţie de $literali$. Un $literal$ este o variabilă care poate fi sau nu negată. Un exemplu de expresie în forma normal conjunctivă ar fi: <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) \\wedge (x_{3} \\vee x_{2} \\vee x_{4}) \\wedge (\\sim x_{1} \\vee \\sim x_{3} \\vee \\sim x_{4}) </tex> care are pe <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) </tex> ca primă propoziţie cu literalii <tex> x_{1} </tex>, <tex> \\sim x_{1} </tex>, <tex> \\sim x_{2} </tex>.\r\n\r\n* $Forma normal disjunctivă$ este formată ca o disjuncţie de propoziţii, fiecare dintre aceste propoziţii fiind o conjuncţie de literali. Un exemplu de o asemenea formulă ar fi următoarea: <tex> (x_{1} \\wedge x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge \\sim x_{3}) \\vee (\\sim x_{1} \\wedge x_{2} \\wedge \\sim x_{2}) </tex>.\r\n\r\nh2(#overview-sat). SAT, 3-SAT, 2-SAT\r\n\r\nProblema $SAT$ este $NP-completă$. De fapt, este prima problemă $NP-completă$ găsită. Stephen Cook a demonstrat $NP-completitudinea$ ei în 1971. Pe vremea aceea nu se ştia nici măcar că problemele $NP-complete$ există. Această problemă rămâne $NP-completă$ chiar dacă restricţionăm expresiile la unele care în forma normal conjunctivă au doar trei literali. Problema satisfiabilităţii pentru asemenea expresii se numeşte $3-SAT$, şi multe probleme pot fi demonstrate a fi $NP-complete$ prin reducerea lui $3-SAT$ la problemele respective în timp polinomial. Din fericire, problema $2-SAT$, adică cea pentru care în fiecare propoziţie există doar $2$ literali, se poate rezolva eficient. Restul articolului va prezenta trei metode de rezolvare a problemei $2-SAT$ şi câteva aplicaţii ale acesteia din concursuri de programare.\r\n\r\nh2(#solutii-2-sat). Soluţii pentru 2-SAT\r\n\r\nUn exemplu de problemă $2-SAT$ ar fi satisfiabilitatea formulei <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Această formulă este satisfăcută de valorile <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>. Pentru a satisface întreaga expresie trebuie ca în fiecare propoziţie cel puţin unul din cei doi literali să aibă valoarea de adevăr <tex> 1 </tex>.\r\n\r\nh3(#solutie-1). Soluţie $O(M * 2^N^)$\r\n\r\nO primă metodă de rezolvare ar fi să încercăm toate cele $2^N^$ posibilităţi de atribuire posibilă, dar această metodă are ordinul de complexitate $O(M * 2^N^)$ şi este eficientă doar pentru instanţe mici ale problemei.\r\n\r\nh3(#solutie-2). Soluţie $O(N * M)$\r\n\r\nUrmătoarea soluţie pare trivială, dar găsirea acestui algoritm şi realizarea faptului că el rezolvă corect problema sunt mai grele decât impresia lăsată după citirea ei. Considerăm o propoziţie oarecare cu două variabile $p$ şi $q$, apoi una dintre ele, de exemplu $p$. Îi atribuim literalului în care apare $p$ valoarea $0$. Pentru ca propoziţia respectivă să aibă $1$ valoarea de adevăr, atunci valoarea lui $q$ trebuie fixată. Fixând şi valoarea lui $q$, probabil şi alte propoziţii ce conţin literalul $q$ vor avea celălalt literal fixat. Propagăm astfel o serie de schimbări. După ce toate schimbările forţate au fost făcute, propoziţiile rezultate vor fi de următoarele tipuri: <tex> a \\vee b </tex>, <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex>. Propoziţii de tip <tex> 0 \\vee b </tex> nu pot apărea pentru că toate schimbările forţate au fost deja propagate. Dacă apare o propoziţie <tex> 0 \\vee 0 </tex> atunci alegerea făcută pentru valoarea lui $p$ este greşită. Vom încerca şi alegerea opusă pentru $p$. Dacă ambele duc la o propoziţie de tip <tex> 0 \\vee 0 </tex> atunci expresia nu poate fi satisfăcută. Propoziţiile de forma <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex> pot fi ignorate. În acest fel am eliminat cel puţin o variabilă şi o propoziţie din expresie. Dacă expresia iniţială era satisfiabilă, atunci şi expresia din care s-au eliminat câteva propoziţii a rămas satisfiabilă. Continuând pe această idee obţinem un algoritm de complexitate $O(N * M)$, pentru că la fiecare atribuire de valoare pentru o variabilă parcurgem şirul de propoziţii o dată. \r\n\r\nSă vedem cum funcţionează algoritmul pentru expresia: <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Considerăm propoziţia <tex> (x_{1} \\vee \\sim x_{2}) </tex> şi <tex> \\langle x_{2} = 1 \\rangle </tex>. Astfel, vom obţine mai departe <tex> (x_{1} \\vee 0) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee 1) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. În propoziţia <tex> (x_{1} \\vee 0) </tex>, <tex> x_{1} </tex> trebuie să fie egal cu <tex> 1 </tex>. Acum, expresia devine: <tex> (0\\ \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee 0) </tex>. Din propoziţia <tex> (0\\ \\vee \\sim x_{3}) </tex> obţinem <tex> \\langle x_{3} = 0 \\rangle </tex>, iar din <tex> (x_{4} \\vee 0) </tex> obţinem <tex> \\langle x_{4} = 1 \\rangle </tex>. Deci, atribuirea satisfiabilă este <tex> \\langle x_{1} = 1, x_{2} = 1, x_{3} = 0, x_{4} = 1 \\rangle </tex>.\r\n\r\nh3(#solutie-3). Soluţie $O(N^2^ * M)$\r\n\r\nO altă soluţie elegantă se bazează pe o metodă randomizată:\r\n\r\n== code(cpp) |\r\natribuim valori booleene arbitrare variabilelor;\r\ncât timp expresia nu este satisfăcută, execută\r\n    găsim o propoziţie cu valoarea de adevăr 0;\r\n    schimbăm valoarea de adevăr a oricăreia dintre cele două variabile prezente în propoziţie;\r\nsfârşit cât timp\r\n==\r\n\r\nLinia $4$ va face ca acea propoziţie să aibă noua valoare de adevăr <tex> 1 </tex>.\r\n\r\nDe ce ar merge acest algoritm? Să presupunem că există o soluţie a problemei, o notăm cu <tex> S </tex>, iar cu <tex> X </tex> notăm şirul valorilor curente ale variabilelor. Ne uităm la fiecare pas al algoritmului la numărul de variabile care au valori diferite în soluţie faţă de cele din <tex> X </tex> (acest număr de diferenţe între elementele de acelaşi index pentru două şiruri se mai numeşte şi \'distanţă Hamming\':http://en.wikipedia.org/wiki/Hamming_distance între şiruri). Fie această valoare la pasul current $K$. Noi am vrea să avem $K = 0$. Cum va evolua $K$ pe parcursul algoritmului? La un moment dat noi schimbăm valoarea unei variabile luate aleator dintr-o propoziţie nesatisfăcută. Pentru că în <tex> S </tex> propoziţia este satisfăcută, înseamnă că cel puţin una dintre cele două variabile ale propoziţiei are valori diferite în <tex> X </tex> faţă de <tex> S </tex>. Astfel, operaţia făcută de noi are probabilitate de cel puţin $0.5$ să ne aducă mai aproape de soluţie. Vom nota cu <tex> T(i) </tex> numărul probabil de paşi în care un şir <tex> X </tex> aflat la distanţa Hamming egală cu $i$ faţă de <tex> S </tex>, va fi transformat în <tex> S </tex>. Evident:\r\n\r\n<tex> T(0) = 0 </tex>\r\n\r\n<tex> T(i) \\le \\dfrac {T(i + 1) + T(i - 1)}{2} + 1 </tex> pentru $0 < i < N$ ({$N$} e numărul de variabile booleene ale expresiei)\r\n\r\nSe pune semnul de inegalitate pentru că ambele variabile pot avea valori diferite faţă de cele din soluţie, deci schimbarea valorii oricăreia ar putea să ne aducă mai aproape de soluţie.\r\n\r\nDacă toate variabilele diferă de soluţie, orice schimbare ne aduce mai aproape de aceasta:\r\n\r\n<tex> T(N) = T(N - 1) + 1 </tex>\r\n\r\nNe interesează numai limitele superioare, deci folosim doar egalităţi în loc de inegalităţi:\r\n\r\n<tex> X(0) = 0 </tex>, <tex> X(i) = \\dfrac {X(i + 1) + X(i - 1)}{2} + 1 </tex>, <tex> X(N) = X(N - 1) + 1 </tex>\r\n\r\nDacă adunăm toate ecuaţiile obţinem:\r\n\r\n<tex> X(0) + X(1) + ... + X(N) = </tex> <tex> \\dfrac {X(0) + X(1) + 2X(2) + ... + 2X(N - 2) + X(N - 1) + X(N)}{2} + X(N) + N - 1 </tex>\r\n\r\nDe aici avem că <tex> \\dfrac {X(1) + X(N - 1) - X(N)}{2} = N - 1 </tex>, iar din <tex> X(N) = X(N - 1) + 1 </tex> rezultă că <tex> X(1) = 2N - 1 </tex>. Mai departe avem că <tex> X(2) = 4N - 4 </tex> <tex> ... </tex> <tex> X(i) = 2iN - i^2 </tex>, de unde, când <tex> i = N </tex>, avem că <tex> X(N) = N^2 </tex>.\r\n\r\nAstfel, numărul mediu de paşi ai algoritmului este pătratic în numărul $N$ de variabile. Lăsând algoritmul să ruleze de 2-3 ori mai mulţi paşi decât numărul mediu, avem o probabilitate foarte mare să ajungem la rezultat.\r\n\r\nh3(#solutie-4). Soluţie $O(M + N)$\r\n\r\nO a treia soluţie se bazează pe relaţia de implicaţie. Aceasta are următoarea tabelă de adevăr:\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> A \\rightarrow B </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nRelaţia de implicaţie are următoarea semnificaţie: dacă <tex> A </tex> este adevărat atunci şi <tex> B </tex> este adevărat. Scriem tabela expresiei <tex> \\sim A \\vee B </tex> şi observăm că aceasta este egală cu cea a relaţiei de implicaţie.\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> \\sim A \\vee B </tex>|\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nFiecare clauză <tex> A \\vee B </tex> poate fi scrisă ca două implicaţii <tex> (\\sim A \\rightarrow B) </tex> şi <tex> (\\sim B \\rightarrow A) </tex>. Realizăm un graf al implicaţiilor. Astfel, nodurile grafului vor fi variabilele <tex> A </tex>, <tex> B </tex> <tex> ... </tex> şi negaţiile lor <tex> \\sim A </tex>, <tex> \\sim B </tex> <tex> ... </tex> iar muchiile acestui graf vor fi implicaţiile echivalente cu propoziţiile din expresie. Deci, dacă expresia are $M$ propoziţii, graful va avea $2M$ muchii. Acestea fiind zise, expresiei <tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) </tex> îi corespunde graful:\r\n\r\np=. !2-sat?Graf.png!\r\n\r\nDacă avem <tex> A \\longrightarrow B </tex> o muchie în graful nostru şi literalul <tex> A </tex> este adevărat, atunci şi literalul <tex> B </tex> trebuie să fie adevărat pentru ca propoziţia reprezentată de muchie să fie satisfăcută. Putem demonstra prin inducţie că dacă există un drum în graf de la literalul <tex> A </tex> la literalul <tex> B </tex>, atunci dacă <tex> A </tex> este adevărat şi <tex> B </tex> trebuie să fie adevărat. Dacă există un drum de la un literal <tex> X </tex> la <tex> \\sim X </tex>, precum şi un drum invers, atunci nu va exista soluţie pentru că nu putem seta în acelaşi timp o variabilă şi valoarea ei negată la valoarea adevărat. De aici rezultă că dacă în graful asociat expresiei există o variabilă <tex> X </tex> în aceeaşi componentă tare conexă cu <tex> \\sim X </tex> atunci instanţa problemei satisfiabilităţii nu poate fi satisfăcută. Dacă nu există o asemenea variabilă, vom vedea în continuare cum putem rezolva problema. Întâi, facem observaţia că dacă în graf există muchia <tex> A \\longrightarrow B </tex> atunci există şi muchia <tex> \\sim B \\longrightarrow \\sim A </tex>. Astfel, dacă există un drum de la <tex> A </tex> la <tex> B </tex> în graf, aplicând proprietatea menţionată pentru fiecare muchie a drumului, vom găsi un drum de la <tex> \\sim B </tex> la <tex> \\sim A </tex>. Evident, afirmaţia este valabilă şi reciproc: dacă există drum de la <tex> B </tex> la <tex> A </tex> atunci vom avea un drum de la nodul <tex> \\sim A </tex> la <tex> \\sim B </tex>. Astfel, dacă avem că <tex> A </tex> şi <tex> B </tex> sunt în aceeaşi componentă tare conexă atunci şi nodurile <tex> \\sim A </tex> şi <tex> \\sim B </tex> sunt în aceeaşi componentă tare conexă. Deci, dacă nu există doi literali <tex> X </tex> şi <tex> \\sim X </tex> în aceeaşi componentă tare conexă, putem să împărţim graful în componente tare conexe şi să împerechem componentele câte două astfel ca în fiecare pereche să apară o componentă <tex> U </tex> cu nişte literali şi altă componentă <tex> \\sim U </tex> cu aceiaşi literali negaţi. Pentru a găsi o soluţie vom determina mai întâi componentele tare conexe ale grafului. Apoi putem contracta fiecare componentă într-un nod. Graful obţinut va fi aciclic. Alegem un nod <tex> u </tex> în care nu intră nicio muchie (un asemenea nod trebuie să existe pentru a nu exista cicluri). Din considerente de simetrie, din nodul lui pereche <tex> \\sim u </tex> nu va ieşi nicio muchie. Literalilor componentei <tex> U </tex> putem să le dăm valoarea de adevăr <tex> 0 </tex>, iar literalilor din componenta pereche <tex> \\sim U </tex>  putem să le dăm valoarea de adevăr <tex> 1 </tex>. Această alegere nu impune restricţii asupra celorlalţi literali şi elimină câteva variabile din problemă. Repetarea recursivă a acestui pas pe graful rămas va duce la rezolvarea problemei. Determinarea \'componentelor tare conexe\':problema/ctc se poate face în complexitatea $O(N + M)$. Pentru a vedea acest algoritm puteţi consulta \'secţiunea $23.5$\':http://zhuzeyuan.hp.infoseek.co.jp/ita/chap23.htm din {\'[1]\':2-sat#bibliografie}. Iar eliminarea nodurilor de care vorbeam mai sus se poate face în $O(N + M)$ folosind o \'sortare topologică\':problema/sortaret.\r\n\r\nSă urmărim cum merge algoritmul nostru pe exemplul de mai sus. Componentele tare conexe sunt următoarele: <tex> \\{A\\} </tex>, <tex> \\{\\sim A\\} </tex>, <tex> \\{B, C, \\sim D\\} </tex>, <tex> \\{\\sim B, \\sim C, D\\} </tex>. În nodul asociat componentei <tex> \\{A\\} </tex> nu intră nicio muchie. Astfel, putem să îi atribuim lui <tex> A </tex> valoarea <tex> 0 </tex>, iar după eliminarea lui <tex> \\{A\\} </tex> şi <tex> \\{\\sim A\\} </tex>în nodul asociat componentei <tex> \\{\\sim B, \\sim C, D\\} </tex> nu intră nicio muchie, deci putem să îi atribuim lui <tex> B </tex> valoarea <tex> 1 </tex>, lui <tex> C </tex> valoarea <tex> 1 </tex> şi lui <tex> D </tex> valoarea <tex> 0 </tex>. Această atribuire este satisfiabilă după cum vedem în continuare:\r\n\r\n<tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) = </tex> <tex> (\\sim 0 \\vee \\sim 1) \\wedge (1 \\vee \\sim 1) \\wedge (1 \\vee 1) \\wedge (\\sim 1 \\vee \\sim 0) \\wedge (1 \\vee 0) = </tex> <tex> 1 \\wedge 1 \\wedge 1 \\wedge 1 \\wedge 1 = 1 </tex>\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\nRestul articolului va prezenta aplicaţii ale problemei $2-SAT$ din concursurile de programare.\r\n\r\nh2(#party). \'Party\':problema/party (preONI 2003/2004)\r\n\r\nbq. George vrea să îşi organizeze majoratul şi îşi doreşte ca petrecerea să fie de neuitat. Mâncarea, băutura, locaţia şi sonorizarea sunt deja asigurate, mai rămâne problema chemării prietenilor. El şi cu prietenul lui cel mai bun, Lucian, au preferinţe diferite şi pentru a nu se certa au pus la punct o listă de cerinţe care vor trebui să fie îndeplinite astfel încât cheful să se desfăşoare în cele mai bune condiţii! Pentru uşurinţă, prietenii lui George vor fi identificaţi prin numere întregi de la $1$ la $N$ ({$1 ≤ N ≤ 100$}) şi cerinţele în număr de $M$ ({$1 ≤ M ≤ 1.000$}) vor fi de tipurile 0, 1, 2 sau 3. O cerinţă de genul <tex> x \\ y </tex> 0 are semnificaţia că <tex> x </tex> sau <tex> y </tex> trebuie să participe la petrecere; <tex> x \\ y </tex> 1 are semnificaţia că dacă <tex> x </tex> participă nu există nicio restricţie pentru <tex> y </tex>, dar dacă <tex> x </tex> nu participă atunci nici <tex> y </tex> nu participa; <tex> x \\ y </tex> 2 are semnificaţia simetrică cu cerinţa 1; iar cerinţa <tex> x \\ y </tex> 3 are semnificaţia că cel puţin unul dintre <tex> x </tex> şi <tex> y </tex> nu participă la petrecere. Scrieţi un program care să-i ajute pe cei doi să determine care persoane vor fi invitate la petrecere. Se garantează că va fi posibilă întotdeauna organizarea unei petreceri!\r\n\r\nh3. Soluţie\r\n\r\nAceastă problemă este inspirată dintr-o problemă de la $CEOI 2002$ şi este evident că ne cere să determinăm o atribuire satisfiabilă pentru o formulă logică formată ca conjuncţie între cerinţele care se transformă astfel:\r\n\r\n* _cerinţa de tip 0_ corespunde propoziţiei <tex> x \\vee y </tex>;\r\n* _cerinţa de tip 1_ corespunde propoziţiei <tex> x \\vee \\sim y </tex>;\r\n* _cerinţa de tip 2_ corespunde propoziţiei <tex> \\sim x \\vee y </tex>;\r\n* _cerinţa de tip 3_ corespunde propoziţiei <tex> \\sim x \\vee \\sim y </tex>.\r\n\r\nUna din primele două rezolvări ar fi putut soluţiona această problemă, dar problema de la $CEOI$ avea limite mai mari şi pentru rezolvarea ei ar fi trebuit un algoritm de complexitate $O(N + M)$.\r\n\r\nh2(#cigraf). Cigraf\r\n\r\n_Autor: Mugurel Ionuţ Andreica_\r\n\r\nbq. Se dă un graf neorientat cu $N$ ({$1 &le; N &le; 1000$}) noduri şi $M$ ({$0 &le; M &le; N*(N-1)/2$}) muchii. Se doreşte împărţirea nodurilor acestui graf în $2$ mulţimi, <tex> C </tex> şi <tex> I </tex>, având următoarele proprietăţi: fiecare nod face parte din exact una din cele $2$ mulţimi, există muchie între oricare $2$ noduri din mulţimea <tex> C </tex>, nu există nicio muchie între $2$ noduri din mulţimea <tex> I </tex>. Este posibil ca una dintre cele $2$ mulţimi să fie vidă. Soluţia nu este neapărat unică. Numele celor două mulţimi provin de la $clică$ şi $mulţime independentă$. De exemplu, pentru graful de $6$ noduri ce are muchiile <tex> \\{\\{1, 4\\}, \\{4, 6\\}, \\{6, 1\\}, \\{2, 4\\}, \\{2, 6\\}, \\{3, 4\\}, \\{1, 3\\}\\} </tex> o împărţire posibilă ar fi <tex> C = \\{1, 4, 6\\} </tex>, <tex> I = \\{2, 3, 5\\} </tex>.\r\n\r\nh3. Soluţie\r\n\r\nDacă între două noduri există muchie atunci nu pot fi amândouă în mulţimea <tex> I </tex>, iar dacă între două noduri nu există muchie nu pot fi amândouă în mulţimea <tex> C </tex>. Transformăm această problemă într-o instanţă de $2-SAT$ astfel: faptul că nodul <tex> x </tex> aparţine mulţimii <tex> C </tex> îl reprezentăm dându-i lui <tex> x </tex> valoarea <tex> 1 </tex>, iar apartenenţa la mulţimea <tex> I </tex> se codifică prin valoarea <tex> 0 </tex>. Acum existenţa unei muchii <tex> (x, y) </tex> corespunde expresiei <tex> x \\vee y </tex>, astfel cel puţin unul din nodurile <tex> x </tex> şi <tex> y </tex> nu va fi în mulţimea <tex> I </tex>. Dacă nu există muchia <tex> (x, y) </tex> putem scrie <tex> \\sim x \\vee \\sim y </tex>, această expresie va fi adevărată dacă cel puţin un nod din cele două nu va fi în mulţimea <tex> C </tex>.\r\n\r\nh2(#orpath). Orpath (Olimpiadă Rusia)\r\n\r\nbq. Într-o ţară pacifistă, există $N$ oraşe şi $K$ autobuze $(1 &le; N, K &le; 100)$. La orele aglomerate ale zilei, nu trebuie să existe două autobuze care merg în acelaşi timp în sensuri opuse. Traseul fiecărui autobuz este un ciclu. Spunem că el merge în sens pozitiv dacă va parcurge oraşele în ordinea $1 2 3 4 1 2 3 4 1 2$ ... sau în sens negativ dacă le parcurge în ordinea $1 4 3 2 1 4 3 2 1 4$ ... Găsiţi o posibilitate de atribuire a sensului fiecărui autobuz astfel ca accidentele de trafic să fie evitate (nu vor exista două autobuze care să se întâlnească şi să aibă sensuri de mers opuse). Pentru fiecare autobuz se vor şti oraşele de pe ruta lui, şi pentru fiecare două oraşe vecine pe rută se va şti timpul necesar autobuzului pentru a ajunge dintr-un oraş în altul. De exemplu, pentru $4$ oraşe unde oricare două sunt la timp de mers egal cu $10$, şi pentru două autobuze cu rutele $1 2 4$ şi $3 4 2$, o soluţie ar fi ca primul autobuz să meargă în sens pozitiv iar celălalt în sens negativ.\r\n\r\nh3. Soluţie\r\n\r\nPentru orice două autobuze vom găsi care sunt sensurile de mers pentru ele astfel ca cele două autobuze să nu se întâlnească şi să provoace un accident. Pentru un sens fixat putem afla pentru un autobuz pe ce interval de timp va fi pe o anumită stradă. El va fi în general pe o stradă $(i, j)$ pe un interval de tipul $[t1 + k*T ... t2 + k*T]$ unde $t1$ este timpul din prima rută parcursă pentru a ajunge la $i$, $t2$ timpul pentru a ajunge la $j$, iar $T$ este durata totală a unei rute. Acum, pentru a determina dacă două autobuze se vor întâlni pe o rută $(i, j)$ trebuie ca ele să se deplaseze în sensuri opuse pe această rută, iar intervalele $[t1 + k*T1 ... t2 + k*T1]$ ale primului să se intersecteze cu intervalele $[tt1 + p*T2 ... tt2 + p*T2]$ ale celui de-al doilea. Este clar acum că putem transforma problema într-o instanţă de $2-SAT$ prin maparea autobuzelor în variabile logice, a sensurilor de mers în valorile $adevărat$ şi $fals$, iar pentru orice pereche de autobuze să fie o propoziţie logică ce ia valoarea $adevărat$ doar dacă sensurile de mers determinate de variabilele logice asociate autobuzelor sunt compatibile. Mai trebuie determinat într-un mod eficient dacă două clase de intervale de timp se intersectează. Aceasta rămâne ca temă cititorului.\r\n\r\nh2(#aladdin). \'Aladdin\':problema/aladdin (Bursele Agora 2005/2006, Runda 1)\r\n\r\nbq. Aladdin, aşa cum ştiaţi, este un mare magnat în afacerea de comercializare a covoarelor magice. Acesta doreşte să o cucerească pe prinţesa Iasmina, iar aceasta, pentru a-i testa inteligenţa îl roagă să îi facă un covor dreptunghiular împărţit în pătrăţele, asemănator unei table de şah cu $N$ linii şi $M$ coloane $(1 &le; N, M &le; 1000)$. Fiecare pătrăţel de pe covor trebuie colorat cu alb sau cu negru. Pentru fiecare pătrat care conţine $4$ pătrăţele Iasmina pune condiţia să aibă un număr fixat de pătrăţele colorate cu negru. Ajutaţi-l pe Aladdin să realizeze un covor care satisface condiţiile impuse de prinţesa Iasmina!\r\n\r\nh3. Soluţie\r\n\r\nÎntâi, să considerăm un exemplu. Pentru o cerinţă de forma:\r\n\r\ntable{width: 90px; text-align: center}.\r\n| <tex> 3 </tex> | <tex> 2 </tex> | <tex> 3 </tex> |\r\n| <tex> 2 </tex> | <tex> 3 </tex> | <tex> 3 </tex> |\r\n| <tex> 1 </tex> | <tex> 2 </tex> | <tex> 1 </tex> |\r\n\r\nuna din soluţii este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nFie <tex> A </tex> o matrice soluţie a problemei noastre. Vom numerota rândurile matricii de la $0$ la $N - 1$ şi coloanele de la $0$ la $M - 1$. Matricea de intrare <tex> S </tex> reprezintă de fapt sumele din fiecare pătrat de câte $2 x 2$ elemente. Facem observaţia că dacă ştim într-un pătrat de $2 x 2$ valorile pentru trei dintre celule, atunci valoarea din a patra celulă este unic determinată pentru că ştim suma elementelor din pătrat. Vedem astfel, că dacă ştim valorile elementelor din prima linie a matricii <tex> A </tex> şi din prima coloană, restul valorilor sunt unic determinate. Pentru a rezolva problema vom presupune <tex> A[0][0] </tex> cunoscut (de fapt, mai întâi vom rezolva problema presupunând că <tex> A[0][0] = 1 </tex>, iar dacă nu obţinem nicio soluţie vom încerca cu <tex> A[0][0] = 0 </tex>). Vom nota celulele <tex> A[0][1] </tex>, <tex> A[0][2]</tex>, <tex>...</tex>, <tex> A[0][M - 1] </tex> cu <tex> x_{1} </tex>, <tex> x_{2} </tex>, <tex>...</tex>, <tex> x_{M-1} </tex>, iar celulele <tex> A[1][0] </tex>, <tex> A[2][0] </tex>, <tex>...</tex>, <tex> A[N - 1][0] </tex> cu <tex> y_{1} </tex>, <tex> y_{2} </tex>, <tex>...</tex>, <tex> y_{N-1} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> A[0][0] </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> ... </tex> | <tex> x_{M-1} </tex> |\r\n| <tex> y_{1} </tex> | <tex> 1 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n| <tex> y_{2} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 0 </tex> |\r\n| ... | ... | ... | ... | ... |\r\n| <tex> y_{N-1} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n\r\nAcum, pentru fiecare celulă putem demonstra prin inducţie că <tex> A[i][j] = (-1)^i x_{j} + (-1)^j y_{i} + b[i][j] </tex>. Unde <tex> b[i][j] </tex> sunt nişte constante ce sunt calculate în funcţie de matricea primită la intrare. Este uşor de observat că dacă:\r\n\r\n<tex> A[i-1][j] = (-1)^{(i-1)} x_{j} + (-1)^j y_{i-1} + b[i-1][j] </tex>,\r\n<tex> A[i-1][j-1] = (-1)^{(i-1)} x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i-1][j-1] </tex>,\r\n<tex> A[i][j-1] = (-1)^i x_{j-1} + (-1)^{(j-1)} y_{i} + b[i][j-1] </tex>,\r\n\r\natunci:\r\n\r\n<tex> A[i][j] = </tex> <tex> S[i-1][j-1] - </tex> <tex> A[i-1][j] - </tex> <tex> A[i][j-1] - </tex> <tex> A[i-1][j-1] = </tex> <tex> S[i-1][j-1] - </tex> <tex> ((-1)^{(i-1)} x_{j} + </tex> <tex> (-1)^j y_{i-1} + </tex> <tex> b[i-1][j]) - </tex> <tex> ((-1)^{(i-1)} x_{j-1} + </tex> <tex> (-1)^{(j-1)} y_{i-1} + </tex> <tex> b[i-1][j-1]) - </tex> <tex> ((-1)^i x_{j-1} + </tex> <tex> (-1)^{(j-1)} y_{i-1} + </tex> <tex> b[i][j-1]) = </tex> <tex> (-1)^i x_{j} - </tex> <tex> (-1)^j y_{i-1} + </tex> <tex> (-1)^i x_{j-1} + </tex> <tex> (-1)^j y_{i-1} - </tex> <tex> (-1)^i x_{j-1} + </tex> <tex> (-1)^j y_{i} + </tex> <tex> S[i-1][j-1] - </tex> <tex> b[i-1][j] - </tex> <tex> b[i][j-1] - </tex> <tex> b[i-1][j-1] = </tex> <tex> (-1)^i x_{j} + </tex> <tex> (-1)^j y_{i} + </tex> <tex> b[i][j] </tex>.\r\n\r\nDe aici concluzionăm că <tex> b[i][j] = S[i-1][j-1] - b[i-1][j] - b[i][j-1] - b[i-1][j-1] \\ (*)</tex>.\r\n\r\nAvem un sistem format din inecuaţiile:\r\n\r\n<tex> 0 \\le x_{j} \\le 1 </tex>\r\n<tex> 0 \\le y_{i} \\le 1 </tex>\r\n<tex> -b[i][j] \\le (-1)^i x_{j} + (-1)^j y_{i} \\le 1 - b[i][j] </tex>\r\n\r\nEste uşor acum să transformăm acest sistem într-o formulă booleană în {\'formă normal conjunctivă\':2-sat#forme-normale} în care fiecare expresie are cel mult $2$ literali. Fiecare relaţie o putem înmulţi sau nu cu $-1$ astfel ca părţile constante ale relaţiei să fie pozitive. Observăm că <tex> -2 \\le b[i][j] \\le 3 </tex>, altfel nu avem soluţie. Dacă partea constantă minimă într-o relaţie este $2$ atunci ambele variabile au valori fixe, iar dacă este $1$ sau $0$ atunci relaţia o putem scrie ca o disjuncţie logică cu doi literali.\r\n\r\nO relaţie precum <tex> 0 \\le x + y \\le 1 </tex> poate fi tansformată logic în <tex> \\sim x \\vee \\sim y </tex>, astfel <tex> x </tex> şi <tex> y </tex> nu vor fi în acelaşi timp <tex> 1 </tex>, una de genul <tex> 1 \\le x + y \\le 2 </tex> va fi transformată în <tex> x \\vee y </tex>, astfel cel puţin <tex> x </tex> sau <tex> y </tex> va fi egal cu <tex> 1 </tex>, alta de tipul <tex> 0 \\le x - y \\le 1 </tex> poate fi scrisă ca <tex> x \\vee \\sim y </tex>, una de tipul <tex> 2 \\le x + y \\le 3 </tex> în <tex> x \\wedge y </tex>, iar una de tipul <tex> 0 \\le -x -y \\le 1 </tex> în <tex> \\sim x \\wedge \\sim y </tex>, una de tipul <tex> 1 \\le x - y  \\le 2 </tex> în <tex> x \\wedge \\sim y </tex>. Astfel am redus problema la rezolvarea unei instanţe de $2-SAT$. Avem $N+M-1$ necunoscute şi @(N-1)*(M-1)@ propoziţii. Folosind {\'a treia metodă de rezolvare\':2-sat#solutie-3} vom obţine un algoritm de complexitate $O((M + N)^2^)$ care soluţionează problema noastră.\r\n\r\nSă vedem cum merge acestă rezolvare pe exemplul din problemă:\r\n\r\nAlegem <tex> A[0][0] = 1 </tex>. Necunoscutele vor fi <tex> x_{1} </tex>, <tex> x_{2} </tex>, <tex> x_{3} </tex> şi <tex> y_{1} </tex>, <tex> y_{2} </tex>, <tex> y_{3} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> x_{3} </tex> |\r\n| <tex> y_{1} </tex> | <tex> A[1][1] </tex> | <tex> A[1][2] </tex> | <tex> A[1][3] </tex> |\r\n| <tex> y_{2} </tex> | <tex> A[2][1] </tex> | <tex> A[2][2] </tex> | <tex> A[2][3] </tex> |\r\n| <tex> y_{3} </tex> | <tex> A[3][1] </tex> | <tex> A[3][2] </tex> | <tex> A[3][3] </tex> |\r\n\r\nFolosind recurenţa <tex> (*) </tex> obţinem că matricea <tex> b </tex> este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 2 </tex> | <tex> 0 </tex> | <tex> 3 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> -1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n\r\nDe aici obţinem sistemul de inegalităţi:\r\n\r\n<tex> 0 \\le x_{1} \\le 1,  0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le 1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, -2 \\le -x_{1} - y_{1} \\le -1, 0 \\le -x_{2} + y_{1} \\le 1, -3 \\le -x_{3} - y_{1} \\le -2, </tex>\r\n<tex> 0 \\le y_{2} \\le 1,  0 \\le  x_{1} - y_{2} \\le  1,-1 \\le  x_{2} + y_{2} \\le 0,  1 \\le  x_{3} - y_{2} \\le  2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, -1 \\le -x_{1} - y_{3} \\le  0, 0 \\le -x_{2} + y_{3} \\le 1, -1 \\le -x_{3} - y_{3} \\le  0 </tex>\r\n\r\nTransformăm relaţiile astfel ca să nu apară nicio constantă negativă:\r\n\r\n<tex> 0 \\le x_{1} \\le 1, 0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le  1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, 1 \\le x_{1} + y_{1} \\le 2, 0 \\le -x_{2} + y_{1} \\le 1, 2 \\le x_{3} + y_{1} \\le 3, </tex>\r\n<tex> 0 \\le y_{2} \\le 1, 0 \\le x_{1} - y_{2} \\le 1, 0 \\le -x_{2} - y_{2} \\le 1, 1 \\le x_{3} - y_{2} \\le 2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, 0 \\le x_{1} + y_{3} \\le 1, 0 \\le -x_{2} + y_{3} \\le 1, 0 \\le x_{3} + y_{3} \\le 1 </tex>\r\n\r\nAcest sistem poate fi transformat într-o expresie booleană:\r\n\r\n<tex> (x_{1} \\vee y_{1}) \\wedge (\\sim x_{2} \\vee y_{1}) \\wedge (x_{3} \\wedge y_{1}) \\wedge </tex>\r\n<tex> (x_{1} \\vee \\sim y_{2}) \\wedge (\\sim x_{2} \\wedge \\sim y_{2}) \\wedge (x_{3} \\wedge \\sim y_{2}) \\wedge </tex>\r\n<tex> (\\sim x_{1} \\vee \\sim y_{3}) \\wedge (\\sim x_{2} \\vee y_{3}) \\wedge (\\sim x_{3} \\vee \\sim y_{3}) </tex>.\r\n\r\nAcestă expresie e satisfăcută de valorile: <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 1, y_{1} = 1, y_{2} = 0, y_{3} = 0 \\rangle </tex>, iar de aici putem determina o soluţie a problemei noastre iniţiale ca fiind:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nh2(#probleme). Probleme propuse\r\n\r\nPentru a vă familiariza cu subiectul prezentat în acest articol, vă propunem să încercaţi să rezolvaţi următoarele probleme:\r\n\r\n# \'Excursion\':http://www.oi.edu.pl/download/boi-2001.pdf - Baltic Olympiad in Informatics, 2001\r\n# \'Peaceful Commission\':http://www.oi.edu.pl/php/show.php?ac=e100000&module=show&file=zadania/oi8/spokojna - Polish Olympiad in Informatics, 2001\r\n\r\nh2(#bibliografie). Bibliografie:\r\n\r\n# T. H. Cormen, C. E. Leiserson, R. R. Rivest - \'_Introducere în Algoritmi_\':http://zhuzeyuan.hp.infoseek.co.jp/ita/toc.htm\r\n# \'_Satisfiability_\':http://en.wikipedia.org/wiki/Satisfiability, Wikipedia\r\n# \'_BOI 2001 Competition Material_\':http://www.oi.edu.pl/download/boi-2001.pdf\r\n# \'_CEOI 2002 Competition Material_\':http://ics.upjs.sk/ceoi/Documents.html',2044,'public',3704,NULL),('algoritmiada-2009/runda-1/solutii/densitate','Densitate','2008-12-14 13:09:54','2008-12-17 05:04:58','h1(#densitate). \'Densitate\':problema/densitate\r\n\r\nProblema cere sa raspundeti la intrebari de forma: \"Cate numere prime sunt intre $a$ si $b$?\" ({$a$} si $b$ inclusiv), cu $0 < a &le; b &le; N < 500000$. Complexitatea dorita pentru preprocesare este $O(N log logN)$ si cea pentru query este de $O(1)$. \r\nIn primul rand trebuie sa stim care sunt numele prime intre 1 si N. Algoritmul clasic de verificare a divizibilitatii unui numar $x$ cu toate valorile pana la $x/2$ este ineficient, avand complexitate $O(x)$, acesta poate fi optimizat pana la $O(sqrt(x))$ daca se verifica numai numerele intre $2$ si $sqrt(x)$, dar acesta este eficient doar daca se testeaza primalitatea unui singur numar. Noi insa dorim sa stim toate numrele prime intre $1$ si $N$ si pentru asta se foloseste \'Ciurul lui Eratostene\':problema/ciur . Acest algoritm tine un sir $V$ in care $V[i]=1$ are semnificatia ca $i$ este prim si $V[i] = 0$ inseamna ca $i$ nu e prim. La pasul $i$, daca $i$ este prim, se seteaza $V[k] = 0$ pentru toti multiplii $k$ lui $i$ pana la $N$. Complexitatea acestui algoritm este $O(N/2 + N/3 + N/5 ... ) = O(N log logN)$\r\nLa pasul al doilea trebuie sa raspundem la intrebari. Sa parcurgem toate valorile intre a si b ar fi ineficient. Tinem insa un sir de sume cumulate $S$ unde $S[i]$ reprezinta numarul de numere prime mai mici sau egale decat $i$, astfel $S[i] = S[i-1] + V[i]$. Raspunsul se calculeaza ca $S[b] - S[a-1]$. Metoda sumelor cumulate poate fi extinsa pentru un spatiu $N^k^$.',58,'public',NULL,NULL),('algoritmiada-2009/runda-1/solutii/sprim','Sprim','2008-12-14 13:15:11','2008-12-16 16:49:01','h1(#sprim). \'Sprim\':problema/sprim\r\n\r\nFie $A[i]$ vectorul citit. Consideram pentru fiecare pozitie $i$ vectorul $P[i]$ pozitia cea mai din dreapta pana in pozitia $i$, astfel incat $A[i]$ nu e prim cu $A[P[i]]$. Vrem sa calculam $S[i]$ = pozitia unde incepe subsecventa maximala (ce respecta conditiile din enunt) care contine $i$ pe ultima pozitie. Raspunsul este suma tuturor $i - S[i]$ cu $1 &le; i &le; N$.\r\nPresupunem ca avem calculat $S[i-1]$ si vrem sa calculam $S[i]$. Se observa doua conditii necesare si suficiente pentru S[i]:\r\n\r\n# $S[i] > P[i]$ (e clar ca subsecventa care contine $i$ nu poate sa treaca sau sa contina $P[i]$ pentru ca astfel nu se respecta conditia)\r\n# $S[i] &ge; S[i-1]$ (trebuie ca subsecventa care contine $i$ sa nu treaca mai departe de subsecventa care contine $i-1$ pentru ca iar nu se respecta conditia)\r\n\r\nDe aici rezulta ca $S[i] = max(S[i-1], P[i] + 1)$. Tot ce ramane de calculat este $P[i]$ si dupa aceea $S[i]$ se poate calcula secvential de la $1$ la $N$.\r\n\r\nPentru a calcula $P[i]$ eficient vom proceda in felul urmator: ca sa stim cea mai din dreapta pozitie pana in $i$ astfel incat $A[i]$ nu e prim cu $A[P[i]]$ ne intereseaza cel mai din dreapta numar care contine un factor prim al lui $A[i]$. Aceasta este usor de facut tinand un vector cu ultima aparitie al fiecarui factor prim pana la pozitia $i$. $P[i]$ va fi maximul dintre ultimele pozitii ale factorilor primi ai numarului $A[i]$. Dupa ce terminam de procesat numarul $A[i]$ modificam vectorul cu aparitiile factorilor primi ai lui $A[i]$ cu pozitia $i$.\r\n\r\nAveti grija la descompunerea numerelor in factori primi. Pentru a lua punctaj maxim se recomanda incercarea secventiala a fiecarui numar prim pana in $sqrt(A[i])$.',2038,'public',NULL,NULL),('algoritmiada-2009/runda-1/solutii/scandura','Scandura','2008-12-14 13:13:33','2008-12-18 22:33:45','h1(#scandura). \'Scandura\':problema/scandura\r\n\r\nNotam lungimea scandurei finale $i$ cu $l[i]$.\r\n\r\nVom incerca sa reprezentam taieturile scandurilor sub forma unui arbore. Radacina arborelui va fi scandura initiala de lungime <tex>L = \\sum{l[i]}</tex>. In urma unei taieturi, dintr-o scandura de lungime $A$ vor porni maxim $M$ alte muchii catre noduri a caror suma a lungimilor va fi tot $A$. Frunzele arborelui vor reprezenta cele $N$ lungimi de scanduri finale. Costul unei modalitati de taiere a scandurii mari va fi atunci egal cu suma valorilor nodurilor din arbore care nu sunt frunze. Datorita faptului ca un nod in arbore are costul egal cu suma costurilor fiilor, putem reprezenta costul fiecarui nod in functie de costul frunzelor. Daca drumul de la frunza $i$ pana la radacina trece prin $k$ noduri (incluzand radacina, neincluzand frunza), atunci costul total produs de frunza $i$ va fi egal cu $k$ * $l[i]$. Costul total al unei modalitati de taiere va fi egal cu <tex>\\sum{l[i] * distanta(i, radacina)}</tex>.\r\n\r\nPentru $M = 2$, putem echivala imediat problema cu cea a determinarii unei \'codari Huffman\':http://en.wikipedia.org/wiki/Huffman_coding. Codarea Huffman este o metoda de comprimare a datelor, cunoscandu-se pentru fiecare caracter din alfabet frecventa cu care el apare in text. Deoarece unele caractere apar mai des decat altele, putem comprima textul asociind lungimi diferite in reprezentarea binara a fiecarui caracter si deci costul total pentru a reprezenta un text va fi egal cu <tex>\\sum{len[i] * frecventa[i]}</tex>, unde $len[i]$ este lungimea reprezentarii caracterului i, iar $frecventa[i]$ este frecventa cu care apare el. Reprezentarea huffman genereaza un arbore in acelasi mod ca si problema noastra, un bit de 0 simbolizand vecinul stang, un bit de 1 simbolizand vecinul drept. Fiecarei scanduri initiale de lungime $l[i]$ ii putem asocia un caracter distinct cu o frecventa de $l[i]$ si se observa ca problemele devin echivalente.\r\n\r\nPentru $M > 2$ putem extinde codarea Huffman, considerand ca un caracter este reprezentat in baza $M$, in loc de baza $2$.\r\n\r\nPentru $M = 2$, o codare Huffman de cost minim se determina extragand la fiecare pas cele $2$ noduri cu cost cel mai mic si inlocuirea lor cu un nod de cost egal cu suma lor. Acelasi lucru il vom face si pe cazul generalizat. Observam ca este optim sa taiem la fiecare pas scandura in cat mai multe bucati, doar la ultima taietura rezultand mai putin de $M$ bucati. Pentru a ne usura implementarea vom adauga la inceput cateva scanduri auxiliare de lungime $0$ pana cand fiecare scandura o vom putea taia in fix M bucati. La fiecare pas din algoritm vom scoate $M$ noduri din structura si vom adauga unul inapoi, in final ramanand cu un singur nod cu costul egal cu suma scandurilor, deci vom adauga inainte de executarea algorimului scanduri de lungime $0$ pana cand $N$ devine de forma $(M - 1) * k + 1$.\r\n\r\nImplementarea in $O(N log N)$ a algoritmului pentru determinarea codarii Huffman, cu ajutorul structurilor de date heap, obtine $70$ de puncte. Pentru $100$ de puncte este necesara implementarea algoritmului in complexitate $O(N)$, folosind faptul ca lungimile scandurilor in fisierul de intrare sunt sortate.\r\n',6172,'public',NULL,NULL),('algoritmiada-2009/runda-1/solutii/propozitie','Propozitie','2008-12-14 13:10:58','2008-12-17 20:16:07','h1(#propozitie). \'Propozitie\':problema/propozitie\r\n\r\nFie $S$ sirul initial de caractere. Vom rezolva problema cu ajutorul programarii dinamice. Vom construi o matrice $A$, in care $A[i][j]$ va reprezenta numarul de posibilitati de a obtine propozitii valide cu primele $i$ caractere, iar ultimul cuvant din propozitie sa aibe exact $j$ vocale. Pentru a calcula valorile $A[i][j]$ putem proceda in urmatorul fel: alegem intai subsecventa de litere $S{~j~}S{~j+1~}...S{~i~}$ si o vom considera pe aceasta ultimul cuvant dintr-o propozitie valida. Daca subsecventa de litere de la $k$ la $i$ contine $p$ vocale atunci va trebui sa adunam la $A[i][p]$ toate valorile $A[j-1][q]$, unde $q$ este cuprins intre $0$ si $K$. Evident vom considera doar subsecventele pentru care $p &le; K$. O implementare bruta a acestei solutii va avea complexitatea $O(N*N*K)$. Putem reduce complexitatea la $O(N*N)$ daca vom precalcula $B[i] = A[i]{@ [0] @} + A[i]{@ [1] @} + ... + A[i]{@ [K] @}$. Plecand de la aceasta idee putem dezvolta o solutie de complexitate $O(N*K)$. Vom calcula $A[i][j]{@ [0] @}$ numarul de propozitii valide formate cu primele $i$ caractere in care ultimul cuvant are $j$ vocale si se termina pe pozitia $i$ si $A[i][j]{@ [1] @}$ numarul de propozitii valide cu primele $i$ caractere in care ultimul cuvant are $j$ vocale si nu se termina pe pozitia $i$. Relatiile de recurenta se obtin usor in $O(1)$ si complexitatea va fi $O(N*K)$ ca timp si $O(K)$ ca memorie (observam ca sunt suficiente doar ultimele doua linii din matrice). Putem optimiza si mai mult aceasta solutie observand ca de fapt daca am calcula $B[i]$ fiind numarul de propozitii valide continand doar primele $i$ caractere, $B[i] = B[i-1]+B[i-2]+...+B[j]$, unde $j$ este cel mai mic posibil astfel incat $S{~j+1~}S{~j+2~}..S{~i~}$ are cel mult $K$ vocale. Cand suntem la pasul $i$ vom avea un indice $j$, la trecerea la pasul $i+1$ se observa ca acest indice ori ramane la fel, ori in cazul in care $S{~i+1~}$ este vocala si aveam deja $K$ vocale indicele $j$ creste pana cand vom avea din nou cel mult $K$ vocale. Astfel putem obtine o solutie in complexitate $O(N)$ ca timp si de asemenea $O(N)$ ca memorie. Oricare din aceste ultime doua solutii obtinea punctajul maxim.',2092,'public',NULL,NULL),('algoritmiada-2009/runda-1/solutii/piese2','Piese2','2008-12-14 13:14:37','2008-12-18 20:40:26','h1(#piese2). \'Piese2\':problema/piese2\r\n\r\nVom imparti cele $2*K$ piese in $K$ perechi: prima piesa rosie va fi in pereche cu prima piesa albastra, a doua piesa rosie cu a doua piesa albastra, samd. Observam ca jucatorul care va duce piesele intr-o configuratie in care piesele din aceeasi pereche sunt adiacente, pierde. De aici vine ideea calcularii paritatii sumei numarului de pozitii libere intre piesele din fiecare pereche. Daca aceasta suma este impara, atunci va castiga Miruna, iar strategia pe care o va urma va fi sa mute la fiecare pas o piesa catre dreapta. Daca suma este para, va castiga Aglaia iar strategia ei este sa mute la fiecare pas o piesa catre stanga.',2028,'public',NULL,NULL),('algoritmiada-2009/runda-1/solutii/kprime','Kprime','2008-12-14 13:15:50','2008-12-18 21:06:54','h1(#kprime). \'Kprime\':problema/kprime\r\n\r\nVom verifica pentru fiecare numar din sir daca este prim sau nu, iar apoi ne vom construi un sir $S$, pentru care $S[i]$ va reprezenta numarul de elemente prime care se afla intre pozitiile $1$ si $i$. Apoi pentru fiecare pozitie, vom incerca sa determinam numarul de subsecvente care contin $K$ numere prime si au capatul din dreapta pe pozitia aleasa. Pentru o pozitie $i$, va trebui sa determinam cel mai mic $j1$ pentru care $S[i] - S[j1] = K$ si cel mai mare $j2$ pentru care $S[i] - S[j2] = K$. Pentru a obtine punctaj maxim, era suficienta folosirea cautarii binare, desi se poate obtine o complexitate O(N) a acestui pas plimbandu-ne cu trei pointeri.',2028,'public',NULL,NULL),('blog/feynman','Richard Feynman si placerea cunoasterii','2009-01-05 18:56:36','2009-01-05 22:35:08','Richard Feynman este un fizician american faimos care a luat premiul Nobel, a fost implicat in creerea bombei atomice si in inspectarea dezastrului exploziei rachetei Challenger. Cel mai important insa mi se pare ca pe langa faptul ca are o minte impresionanta este ca el are un talent extraordinar de povestitor. \r\n\r\nAm vazut de ceva vreme pe youtube un interviu intitulat \"The pleasure of finding things out\", pe care vreau sa vi-l recomand. In el Feynman povesteste despre relatia extraordinara pe care a avut-o cu tatal sau, modul ingenios prin care acesta il educa. Mai vorbeste despre lucrul la bomba nucleara si la problemele morale ce le-a avut dupa realizarea ei, despre premiul Nobel si despre lipsa lui de respect fata de onoruri si autoritate, despre particule subatomice, despre modul lui de lucru ca cercetator, despre cum a incercat la randul lui sa isi educe copiii ...\r\n\r\nAsa ca va recomand din suflet urmatorul documentar:\r\n==GoogleVideo( id=\"7136440703094429927\" )==\r\n\r\nDaca nu v-ati saturat inca, puteti citi aici cartea \"Surely you\'re joking mr Feynman\":http://vidyaonline.org/arvindgupta/surelyjoking.pdf',58,'protected',3542,NULL),('algoritmiada-2009/runda-2','Algoritmiada 2009 - Runda 2','2008-11-30 16:35:07','2008-12-22 17:16:36','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Algoritmiada 2009, Runda 2\r\n\r\n(htabs)*(active) \'Despre...\':algoritmiada-2009/runda-2 \r\n* \'Clasele 5-8\':algoritmiada-2009/runda-2/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2009/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-2/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-2/5-8 \r\n\r\nRunda va incepe *Duminica 11 ianuarie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-2/studenti\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':algoritmiada-2009/runda-2/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-2/studenti\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"domino\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',2044,'protected',NULL,NULL),('algoritmiada-2009/runda-2/5-8','Algoritmiada 2009 - Runda 2, Clasele 5-8','2008-12-22 14:14:19','2008-12-22 14:14:19','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda2-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-2 \r\n*(active) \'Clasele 5-8\':algoritmiada-2009/runda-2/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2009/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-2/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-2/5-8\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda2-5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda2-5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda2-5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-2/5-8.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda2-5-8\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('algoritmiada-2009/runda-2/studenti','Algoritmiada 2009 - Runda 2, Studenti','2008-12-22 14:41:30','2008-12-22 14:41:30','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda2-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-2 \r\n* \'Clasele 5-8\':algoritmiada-2009/runda-2/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2009/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-2/11-12\r\n*(active) \'Studenti\':algoritmiada-2009/runda-2/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-2/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda2-studenti\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda2-studenti\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda2-studenti\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-2/studenti.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda2-studenti\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('algoritmiada-2009/runda-2/9-10','Algoritmiada 2009 - Runda 2, Clasele 9-10','2008-12-22 14:24:19','2008-12-22 14:45:15','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda2-9-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-2 \r\n* \'Clasele 5-8\':algoritmiada-2009/runda-2/5-8 \r\n*(active) \'Clasele 9-10\':algoritmiada-2009/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-2/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-2/9-10\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda2-9-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda2-9-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda2-9-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-2/9-10.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda2-9-10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('algoritmiada-2009/runda-2/11-12','Algoritmiada 2009 - Runda 2, Clasele 11-12','2008-12-22 14:30:40','2008-12-22 14:45:40','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda2-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-2 \r\n* \'Clasele 5-8\':algoritmiada-2009/runda-2/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2009/runda-2/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2009/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-2/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-2/11-12\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda2-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda2-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda2-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-2/11-12.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda2-11-12\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('algoritmiada-2009/runda-2/solutii','Solutii Algoritmiada 2009, Runda 2','2008-12-22 14:47:18','2009-01-11 11:57:39','h1. Solutii Algoritmiada 2009, Runda 2\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Marmote\':algoritmiada-2009/runda-2/solutii#marmote\r\n* \'Ejoc\':algoritmiada-2009/runda-2/solutii#ejoc\r\n* \'Bazaconii\':algoritmiada-2009/runda-2/solutii#bazaconii\r\n* \'Colier\':algoritmiada-2009/runda-2/solutii#colier\r\n* \'Papuci\':algoritmiada-2009/runda-2/solutii#papuci\r\n* \'Nrsec\':algoritmiada-2009/runda-2/solutii#nrsec\r\n* \'Jap\':algoritmiada-2009/runda-2/solutii#jap\r\n\r\n==include(page=\"algoritmiada-2009/runda-2/solutii/marmote\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-2/solutii/ejoc\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-2/solutii/bazaconii\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-2/solutii/colier\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-2/solutii/papuci\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-2/solutii/nrsec\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-2/solutii/jap\")==\r\n',2038,'public',NULL,NULL),('algoritmiada-2009/runda-2/solutii/marmote','algoritmiada-2009/runda-2/solutii/marmote','2009-01-03 17:05:46','2009-01-14 19:31:59','h1(#marmote). \'Marmote\':problema/marmote\r\n\r\nSe observa ca o vizuina are forma unui romb cu centrul in punctul $X{~i~}$, $Y{~i~}$. O prima solutie de complexitate $O(N*M + K*L^2^)$ este urmatoarea: vom mentine o matrice $Fol[i][j]$ in care vom marca pozitiile care apartin vreunei vizuine. In momentul in care soseste o noua marmota vom verifica in $O(L^2^)$ daca toate pozitiile vizuinei sale nu sunt folosite de alta marmota, iar in caz afirmativ vom marca pozitiile noii vizuini in matrice.\r\nObservatia necesara pentru a reduce complexitatea este ca daca avem doua vizuini care se intersecteaza, atunci pentru fiecare din cele doua vizuini cel putin unul din cele patru varfuri este o pozitie comuna. Astfel, putem sa verificam in $O(1)$ daca o anumita marmote poate sa isi construiasca vizuina uitandu-ne doar la cele patru varfuri. Pentru a obtine o solutie corecta trebuie sa avem grija la vizuinele care se afla pe marginile campului. Va trebui sa extindem matricea $Fol$ astfel incat sa cuprinda in totalitate vizuinile. Complexitatea acestei solutii este $O(N*M + K)$.',3689,'public',NULL,NULL),('algoritmiada-2009/clasament/runda-2/5-8','Algoritmiada 2009 - Clasament Runda 2, Clasele 5-8','2008-12-22 14:50:17','2008-12-22 14:50:17','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda2-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-2\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-2/studenti\r\n*(active) \'Rezultate\':algoritmiada-2009/clasament/runda-2/5-8\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasele 5-8\':algoritmiada-2009/clasament/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-2/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda2-5-8\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('algoritmiada-2009/clasament/runda-2/9-10','Algoritmiada 2009 - Clasament Runda 2, Clasele 9-10','2008-12-22 14:52:24','2008-12-22 14:52:24','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda2-9-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-2\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-2/studenti\r\n*(active) \'Rezultate\':algoritmiada-2009/clasament/runda-2/9-10\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-2/5-8\r\n*(active) \'Clasele 9-10\':algoritmiada-2009/clasament/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-2/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda2-9-10\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('algoritmiada-2009/clasament/runda-2/11-12','Algoritmiada 2009 - Clasament Runda 2, Clasele 11-12','2008-12-22 14:53:28','2008-12-22 14:53:28','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda2-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-2\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-2/studenti\r\n*(active) \'Rezultate\':algoritmiada-2009/clasament/runda-2/11-12\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-2/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2009/clasament/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-2/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda2-11-12\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('algoritmiada-2009/clasament/runda-2/studenti','Algoritmiada 2009 - Clasament Runda 2, Studenti','2008-12-22 14:54:31','2008-12-22 14:54:31','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda2-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-2\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-2/studenti\r\n*(active) \'Rezultate\':algoritmiada-2009/clasament/runda-2/studenti\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-2/11-12\r\n*(active) \'Studenti\':algoritmiada-2009/clasament/runda-2/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda2-studenti\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('algoritmiada-2009/runda-2/solutii/papuci','algoritmiada-2009/runda-2/solutii/papuci','2009-01-03 17:07:27','2009-01-11 11:57:04','h1(#papuci). \'Papuci\':problema/papuci\r\n\r\nObservam ca daca privim capatul din stanga al unei perechi ca o paranteza deschisa si capatul din dreapta ca o paranteza inchisa obtinem defapt un sir de parantezari valide. De asemenea daca inversam doua litere dintr-o pereche observam ca sunt afectate doar parantezarea care incepe exact dupa capatul din dreapta al perechii, parantezarea care incepe exact dupa capatul din stanga al perechii si cea care se termina exact inainte de capatul din dreapta al perechii (evident daca acestea exista). Vom rezolva problema cu ajutorul programarii dinamice. Sa presupunem ca avem o pereche $x$ care are in interiorul ei perechile $a{~1~} a{~2~} ... a{~k~}$ care corespund unor alte parantezari corecte: $( a{~1~} a{~2~} ... a{~k~} )$. Vom calcula $Min[ x ][ 0 ]$ ca fiind costul minim care se obtine pentru perechea $x$ daca nu interschimbam caracterele si $Min[ x ][ 1 ]$ costul minim care se obtine daca interschimbam parantezele. Acest cost se calculeaza luand in calcul doar ce se intampla in interiorul perechii de paranteze $x$. Pentru a calcula aceasta valoare am avea nevoie de valorile $Min[ a{~1~} ][ 0 ], Min[ a{~1~} ][ 1 ], Min[ a{~2~} ][ 0 ], Min[ a{~2~} ][ 1 ] ...$. Apoi trebuie sa facem o noua dinamica in care vom calcula o matrice $Cmin[ 2 ][ 2 ]$ in care prima valoare indica faptul daca am interschimbat sau nu caracterele din perechea $a{~1~}$ si a doua valoare daca am interschimbat sau nu caracterele din perechea $a{~2~}$. Putem calcula aceasta matrice in timp liniar. Dupa ce am calculat toate valorile $Min[ i ][ 0 ]$ si $Min[ i ][ 1 ]$ putem calcula raspunsul final luand in calcul numai relatiile care nu sunt incluse in alte relatii (vom avea un sir de genul $(..)(..)(..)$). Complexitatea pentru a calcula toate valorile necesare din dinamica este $O(N)$, deoarece o pereche o accesam doar atunci cand calculam valorile pentru perechea de paranteza ce o include pe ea, dar numai pentru prima dintre acestea. Se pot obtine 100 de puncte si cu solutii de complexitate $O(N*logN)$ care folosesc o sortare pentru a determina sirul de parantezari.',2038,'public',NULL,NULL),('flux-si-cuplaj','Flux si cuplaj','2008-01-22 17:57:12','2009-01-04 20:48:56','h1. Flux si Cuplaj \r\n\r\n(Categoria _Algoritmi_, autor _Mircea Dima_)\r\n\r\n# Retele de transport \r\n# Algoritmiii Ford Fulkerson si Edmonds-Karp \r\n** UVA 10735\r\n** PKU 2391\r\n# Algoritmul lui Dinic si algoritmul lui Karzanov\r\n** \"Tero\":http://infoarena.ro/problema/tero\r\n# Taietura minima in graf / conexiune de muchii\r\n** Hardware Store\r\n** SPOJ Optmark\r\n** ZJU 2429\r\n# Flux cu capacitati inferioare si superioare\r\n** SGU 176\r\n** \'Drumuri2\':problema/drumuri2\r\n** Joc (finala .campion 2006)\r\n# Cuplaj in graf bipartit \r\n** SGU 234, 190\r\n# Algoritm de flux maxim pentru cuplaj\r\n** CEOI 2002 Guards\r\n** PKU 2226\r\n# Cuplaj folosind lanturi alternante (cunoscut si ca PairUp)\r\n** Dicing/KOS polonezi\r\n** PKU 3189\r\n# Algoritmul Hopcroft-Karp \r\n** \'Java\':problema/java\r\n** Baltica 2001 Knights\r\n# Suport in graf bipartit\r\n** \'Felinare\':problema/felinare\r\n** SGU 234\r\n** Knights - BalticOI 2001\r\n# Cuplaj maxim de cost minim (cu Bellman-Ford cu si fara coada)\r\n** \'Traseu\':problema/traseu\r\n** \'Trafic\':problema/trafic\r\n** SGU 252\r\n** UVA 10806\r\n** Problema chinezi\r\n# Cuplaj maxim de cost minim folosind Dijkstra\r\n** \'CC\':problema/cc\r\n\r\nh2. 1. Retele de transport\r\n\r\nO **retea de transport** $G=(V, E)$ este un graf orientat in care fiecarui arc $(u, v) &#8712; E$ ii este asociata o **capacitate** nenegativa $c(u,v) >=0$.\r\nVom distinge 2 varfuri importante in retea: varful **sursa S** si varful **destinatie D**.\r\nUn flux in reteaua de mai sus este o functie $f: V x V -> R$ care satisface urmatoarele conditii:\r\n\r\n# **Restrictie de capacitate:** pentru orice $u, v &#8712; V$ avem $f(u, v)<=c(u, v)$\r\n# **Antisimetrie:** pentru orice $u, v &#8712; V$ avem $f(u, v)=-f(v, u)$\r\n# **Conservarea fluxului:** pentru orice $u &#8712; V - {S, D}$ avem $&#8721; v &#8712; V$ din $f(u, v) = 0$\r\n\r\nPrima restrictie impune pur si simplu ca fluxul de la un varf la altul sa nu depaseasca valoarea capacitatii.\r\nAntisimetria impune ca fluxul de la un varf u la un varf v sa fie egal cu opusul fluxului de la varful v la u. Astfel, fluxul de la un varf la el insusi este 0. \r\nConservarea fluxului impune ca _\"ceea ce intra intr-un nod sa fie egal cu ceea ce iese din nod\"_\r\n\r\nMai pe intelesul tuturor putem sa ne imaginam ca fiecare arc este o conducta pentru material. Fiecare conducta are o capacitate data, care este defapt ritmul maxim cu care lichidul se poate deplasa in conducta. De exemplu, printr-o teava pot curge cel mult 2000 litri de apa pe ora, sau pe un fir conductor un curent electric de maximum 20 amperi. Varfurile sunt jonctiunile conductelor si in afara varfului sursa si destinatie, materialul nu se poate acumula in nici un varf. Aceasta proprietate se numeste **conservarea fluxului** si este identica cu legea lui Kirchoff in cazul curentului electric.\r\n\r\n\r\nh2. 2. Algoritmiii Ford Fulkerson si Edmonds-Karp\r\n\r\n\r\nh3. Metoda Ford-Fulkerson\r\n== code(c) |\r\nFord-Fulkerson(c, f)\r\n      f[i][j]=0 pt i,j=1,n\r\n      cat timp exista un drum de ameliorare p executa\r\n          mareste fluxul f de-a lungul drumului p\r\n      returneaza f\r\n==\r\n\r\nCe este un drum de ameliorare? Un drum de ameliorare este un drum de la sursa la destinatie care are proprietatea ca fiecare muchie are cap[i]-flux[i] > 0, \r\nsau mai bine zis, \"se mai poate pompa lichid prin conductele ce compun drumul\".\r\n\r\nConform acestei metode se poate implementa un algoritm cu o complexitate ce depinde de capacitati (marim fluxul cu o unitate la fiecare pas).\r\n\r\nEdmonds si Karp au dat urmatorul algoritm ce are complexitate O(N *M^2):\r\nDrumul de ameliorare il vom determina folosind un BFS (cautare in latime) si in loc sa marim fluxul cu o singura unitate, vom mari fluxul cu valoarea minima dintre capacitatile de pe drumul de amelioarare. Se observa intuitiv ca dupa saturarea unui drum de ameliorare se satureaza cel putin o muchie. Dupa O(M) saturari de drumuri se observa ca cel mai scurt drum de la sursa la destinatie trebuie sa creasca. Asadar dupa O(N*M) astfel de operatii destinatia nu va mai fi accesibila din sursa si prin urmare avem fluxul maxim. Cum fiecare operatie (din cele O(N*M) ) au complexitate O(M+N) (BFS) rezulta complexitatea finala O(N* M^2).\r\n\r\n\r\n==code(c) |\r\n#include <cstdio>\r\n#define N 128\r\n#define oo 0x3f3f3f3f //infinit\r\nint cap[N][N], flux[N][N];\r\nint t[N];\r\nint n, m;\r\n\r\nint bfs(int source, int sink)\r\n{\r\n	int Q[N+1], p=0,q=0;\r\n	bool use[N];\r\n	memset(use, 0, sizeof(use));\r\n	memset(t, 0, sizeof(t));\r\n	Q[0]=source;\r\n	use[source]=1;\r\n	\r\n	while(p<=q) \r\n	{\r\n		int u=Q[p++];//scoatem primul element din coada\r\n		\r\n		for(int i=source;i<=sink;++i) // pt fiecare nod ( adiacent )\r\n			if(!use[i]) // nu am folosit nodul\r\n				if(cap[u][i] - flux[u][i] > 0) // mai putem pompa?\r\n				{\r\n					Q[++q]=i; // inseram nodul i in coada\r\n					t[i]=u;  \r\n					use[i]=1; \r\n				}\r\n	}\r\n				\r\n	if(t[sink]) return 1;\r\n	return 0;\r\n}\r\n\r\nint edmond-karp(int source, int sink)\r\n{\r\n	int flow=0; //fluxul\r\n	int i, min;\r\n	\r\n	while(bfs(source, sink)) // cat timp mai exista un drum de ameliorare\r\n	{\r\n		min=oo;\r\n		for(i=sink; i; i=t[i])\r\n			if(cap[t[i]][i]-flux[t[i]][i] < min) min=cap[t[i]][i]-flux[t[i]][i]; \r\n//calculam minimul dintre capacitatile ramase de pe drum\r\n		\r\n		for(i=sink ; i; i=t[i]) \r\n			flux[t[i]][i]+=min, //adaugam minimul la fluxul de pe arcele de pe drum\r\n			flux[i][t[i]]-=min; //scadem minimul de pe arcele inverse\r\n		\r\n		flow+=min; // adaugam minimul la flux\r\n	}\r\n      return flow;\r\n}\r\n\r\n==\r\n\r\n\r\nh2. 2. Algoritmul lui Dinic si algoritmul lui Karzanov\r\n\r\nh3. Algoritmul lui Dinic\r\n\r\nIn cadrul fiecarui ciclu while al algoritmului Edmond-Karp determinam un singur drum de ameliorare. In cadrul algoritmului lui Dinic se determina nu un singur drum, ci un numar maximal (nu neaparat maxim) de drumuri de ameliorare. Practic ne uitam la nodurile adiacente destinatiei si daca se poate ajunge in destinatie din acel nod atunci saturam drumul respectiv.\r\n\r\n== code(c) |\r\nint dinic(int source, int sink)\r\n{\r\n	int flow=0; //fluxul\r\n	int i, min,j;\r\n	\r\n	while(bfs(source, sink)) // cat timp mai exista un drum de ameliorare\r\n	{\r\n		\r\n		for(j=source;j<sink;++j)\r\n			if(cap[j][sink]-flux[j][sink] > 0)\r\n			{\r\n				\r\n				min=oo;\r\n				\r\n				if(cap[j][sink]-flux[j][sink] < min) min=cap[j][sink]-flux[j][sink];\r\n				\r\n				for(i=j; i; i=t[i])\r\n					if(cap[t[i]][i]-flux[t[i]][i] < min) min=cap[t[i]][i]-flux[t[i]][i];\r\n //calculam minimul dintre capacitatile de pe drum\r\n		\r\n				if(min == oo) continue;\r\n				\r\n				flux[j][sink]+=min;\r\n				flux[sink][j]-=min;\r\n				\r\n				for(i=j ; i; i=t[i]) \r\n					flux[t[i]][i]+=min, //adaugam minimul la fluxul de pe arcele de pe drum\r\n					flux[i][t[i]]-=min; //scadem minimul de pe arcele inverse\r\n		\r\n				flow+=min; // adaugam minimul la flux\r\n			}\r\n	}\r\n     return flow;	\r\n}\r\n==\r\n\r\nh2. Grafuri bipartite\r\n Cuplaj maxim, Multime independentă maximală, Suport minim\r\n	\r\n\r\n\r\n\r\n\r\nUn graf bipartit este un graf G = (V, E) în care mulţimea V poate fi partiţionată în două mulţimi, V1 şi V2 astfel încât orice muchie (u, v) C E implică fie că u C V1 şi v  C V2 fie că u C V2  şi v C V1. Cu alte cuvinte, toate muchiile merg de la mulţimea V1 la mulţimea V2 sau invers.\r\n\r\nProprietăţile grafurilor bipartite sunt: \r\n1.	G este 2-colorabil (adică nodurile pot fi colorate în 2 culori astfel încât orice muchie sa aiba noduri colorate diferit)\r\n2.	G nu are cicluri de lungime impară\r\n\r\nÎn grafurile bipartite anumite probleme care erau NP pe grafuri normale, se pot rezolva în timp polinomial. Exemple de astfel de probleme sunt: cuplaj maxim, mulţime independentă maximală şi suport minim.\r\n\r\nh3. Cuplaj Maxim\r\n\r\nFiind dat un graf neorientat G = (V, E),  un cuplaj este o submulţime de muchii M astfel încât pentru toate vârfurile v  C V, există cel mult o muchie în M incidentă în v. Spunem că un vârf v C V este cuplat de cuplajul M dacă există cel mult o muchie în M incidentă în v; altfel spunem ca v este neconectat. Un cuplaj maxim  este un cuplaj de cardinalitate maximă.\r\n\r\n !flux-si-cuplaj?cuplaj1.jpg!\r\n \r\nÎn imagine: un graf bipartit G = (V, E) cu partiţia vârfurilor V = L U R. (a) Un cuplaj de cardinalitate 2. (b) Un cuplaj maxim de cardinalitate 3.\r\n\r\nPentru a determina cuplajul maxim vom transforma graful bipartit într-o reţea de transport adaugând un nod sursa (s)si un nod destinaţie (t) şi vom pune capacitate 1 pe toate muchiile.\r\n\r\nReţeaua de transport corespunzătoare grafului de mai sus:\r\n \r\n !flux-si-cuplaj?cuplaj2.jpg!\r\n\r\nCuplajul maxim va fi chiar fluxul maxim în această reţea. Nu ne rămâne decât să rulăm unul din algoritmii cunoscuţi precum Edmonds-Karp, Dinic… Complexitatea obţinută va fi O(V *  E) deoarece orice cuplaj în graful bipartit are cardinalitate cel mult min(V1, V2).\r\n	\r\nUn algoritm performant pentru determinarea cuplajului maxim este Algoritmul Hopcroft-Karp. Acest algoritm în loc să determine un singur drum de ameliorare la fiecare pas, el determină un numar maximal (nu neapărat maxim) de drumuri distincte. Astfel se poate demonstra că numarul de paşi necesari este cel mult sqrt(V) . Prin urmare complexitatea va deveni O(E*sqrt(V)).\r\n\r\n\r\nh2. 10. Suport Minim\r\n\r\nÎntr-un graf bipartit un suport minim reprezintă o mulţime de noduri cu cardinal minim pentru care orice muchie a grafului este adiacentă cu cel puţin unul dintre nodurile mulţimii. Conform Teoremei lui Koning într-un graf bipartit cuplajul maxim şi suportul minim sunt egale. \r\nPentru a calcula suportul minim vom porni de la un cuplaj maxim. Nodurile din prima mulţime care aparţin cuplajului vor fi incluse în suportul minim, iar pentru cele care nu aparţin cuplajului vom folosi o funcţie recursiva care în momentul în care gaseşte o muchie care nu are cel puţin un nod în suport, adauga nodul din V2 şi şterge nodul din stânga cu care este cuplat nodul respctiv şi apelează recursiv pentru nodul din stânga.\r\n\r\n\r\nFuncţia recursiva arata astfel:\r\n\r\n\r\n== code(c) |\r\ninline void support(int n)\r\n{\r\n    vector<int>::iterator it;\r\n\r\n    for(it=a[n].begin(); it!=a[n].end(); ++it) \r\n    //pentru fiecare nod *it(din dreapta) adiacent lui n\r\n	if(!sr[*it]) // daca nu e in suport\r\n	{\r\n	    sr[*it]=1;  // il adaug in suport\r\n	    sl[l[*it]]=0; \r\n    // sterg din suport nodul din stanga cu care este cuplat *it\r\n	    support(l[*it]); // apelez recursiv pentru nodul din stanga\r\n	}\r\n}\r\n\r\n==\r\n\r\nh2. Mulţime independentă maximală\r\n\r\nÎntr-un graf bipartit o mulţime independentă maximală reprezintă o mulţime de noduri astfel încât oricare 2 noduri din mulţime să nu fie legate printr-o muchie iar orice muchie din graf să aiba unul din noduri în mulţimea independentă.\r\nO proprietate interesantă a unei mulţimi independente maximale este aceea că ea este fie o clică maximală fie un subgraf complet în graful complementar.\r\nMulţimea independentă maximală este complementul oricărui suport minim în sensul că daca avem un suport minim, o mulţime independentă maximală va fi formată din nodurile care nu aparţin suportului minim.\r\n',1204,'public',NULL,NULL),('blog/algoritmiada-runda1','Algoritmiada - analiza rundei 1','2008-12-26 17:36:37','2009-01-07 18:10:36','Prima runda a concursului Algoritmiada s-a incheiat si o data cu aceasta a fost marcat inceputul noului concurs major organizat de infoarena. Speram ca acest concurs sa devina unul cat mai placut pentru tinerii pasionati de informatica din toata tara. Inainte de toate iata cateva statistici despre acesta runda: au trimis solutii 223 de concurenti desi s-au inscris 356 de utilizatori (eliminandu-i pe cei ce s-au inscris la mai multe runde). Au fost trimise 1245 solutii, 685 dintre ele obtinand punctaje mai mari decat 0. Ne-am straduit ca problemele sa fie ceva mai abordabile anul acesta si ca dovada au fost 162 concurenti cu punctaje diferite de 0, media fiind de 103.36 de puncte.\r\n\r\nLa varful clasamentului punctajele au fost mari, 2 concurenti reusind punctajul maxim. La grupa 5-8 s-au remarcat ==user(user=\"GavrilaVlad\")== (punctaj maxim), ==user(user=\"alex_mircescu\")== si ==user(user=\"taloibogdan\")== (ambii cu 190 de puncte). Urmeaza o serie de concurenti cu punctaje frumoase, fiind destui participanti care au reusit sa rezolve cel putin o problema.\r\n\r\nLa grupa 9-10, pe primele 2 locuri s-au clasat ==user(user=\"savim\")== si ==user(user=\"CezarMocan\")==, amandoi avand 230 de puncte. Ei sunt urmati indeaproape de un pluton de concurenti cu punctaje apropiate de 200 de puncte condus de ==user(user=\"katakuna\")== cu 215 puncte.\r\n\r\n==user(user=\"bogdanhm999\")==, ==user(user=\"mihai_florea\")== (ambii cu 200 de puncte) si ==user(user=\"Vman\")== (cu 170 de puncte) si-au adjudecat primele 3 locuri legitime de la grupa 11-12, ==user(user=\"Zeus\")== fiind student.\r\n\r\nIn grupa studenti se pare ca vom avea o batalie interesata, runda aceasta fiind adjudecata clar de ==user(user=\"efer\")== care a obtinut punctajul maxim dupa numai \'o ora si jumatate\':monitor?user=efer de la inceperea concursului. El este amenintat serios de urmatorii sai: ==user(user=\"mugurelionut\")==, ==user(user=\"TYTUS\")== si ==user(user=\"octav\")== toti cu cate 235 de puncte dupa aceasta runda.\r\n\r\nJudecand dupa multele egalitati de la varful clasamentului vom avea o competitie acerba anul aceasta in toate grupele. Am fost placut surprinsi de calitatea participantilor in grupa de studenti unde punctajele sunt mari. Judecand si dupa participarea ridicata, se pare ca existau destul de multi studenti care abia asteptau sa se intreaca intr-o astfel de competitie.\r\n\r\nDesi feedback-ul primit de la voi a fost unul in general pozitiv, au fost si cateva probleme tehnice pe parcursul concursului. In primul rand, ==user(user=\"MciprianM\")== a descoperit un bug care permitea aflarea punctajului pentru sursele trimise. Din fericire, acesta a fost semnalat si eliminat rapid, cand inca nu se trimisesera multe solutii. Multumim lui Ciprian pentru fair play-ul de care a dat dovada, el anunand foarte prompt bug-ul. A mai existat o problema cu sincronizarea intre serverul pe care este site-ul si cel pe care se face testarea. Din acest motiv concursul a inceput si s-a terminat mai devreme. Aceasta a provocat unele neplaceri concurentilor care sperau sa impuste puncte exact la final. Vom incerca sa inlaturam aceasta problema in rundele viitoare. La sfarsitul concursului, datorita numarului prea mare de conexiuni la baza de date, site-ul a inceput sa cedeze si paginile se incarcau intermitent. Pe partea stiintifica au fost doua imperfectiuni: la problema $tablete$ limita a fost prea stransa pentru unele surse scrise in Pascal si la problema $jstc$ au fost grupate 14 teste masura reclamata de concurenti ca fiind prea radicala.\r\n\r\nIn ciuda acestor probleme, organizarea a fost buna per ansamblu. Nu au existat probleme cu testele problemelor iar enunturile au fost clare. Site-ul s-a comportat mult mai bine fata de concursurile din vara. Concluzionand, noi credem ca a fost o runda reusita: participantii au dovedit ca sunt talentati si competitivi iar echipa infoarena s-a mobilizat exemplar. Multumim comisiei stiintifice pentru rigoarea si creativitatea dovedita in pregatirea problemelor si comisiei tehnice pentru imbunatatirile vizibile aduse site-ului.\r\n\r\nIn final as vrea sa va intreb cum v-a placut aceasta runda. Ce a mers rau si ce a mers bine pentru voi? _(cei care au dat feedback sunt scutiti :P)_',2044,'protected',3527,NULL),('algoritmiada-2009/runda-2/solutii/ejoc','algoritmiada-2009/runda-2/solutii/ejoc','2009-01-03 17:06:11','2009-01-14 19:16:55','h1(#ejoc). \'Ejoc\':problema/ejoc\r\n\r\nJocul se aseamana foarte tare cu algoritmul lui Euclid prin scaderi. Stim ca daca avem doua numere $A$ si $B$ si tot scadem din cel mai mare pe cel mai mic, pana cand numerele devin egale, numerele la sfarsit o sa fie egale cu $cmmdc(A, B)$ (cel mai mare divizor comun). Aici cu siguranta se va ajunge la un moment dat sa se obtina $cmmdc(A, B)$, si apoi acest $cmmdc(A, B)$ va putea fi scazut in mod repetat din $A$ sau din $B$. Cum jocul se termina cand nu se mai poate efectua nici o mutare se observa ca la sfarsit se vor obtine toti multiplii lui $cmmdc(A, B)$ pana in A sau in B. Rezulta ca numarul de mutari nu depinde de mutarile jucatorilor ci doar de $A$ si $B$, si acesta este $max(A, B)$ / $cmmdc(A, B) - 2$ (e un caz particular cand $A = B$ dar acesta este usor de rezolvat). Castigatorul este deci determinat doar de paritatea numarului de mutari posibile. ',3689,'public',NULL,NULL),('algoritmiada-2009/runda-2/solutii/jap','algoritmiada-2009/runda-2/solutii/jap','2009-01-03 17:08:08','2009-01-11 12:49:07','h1(#jap). \'Jap\':problema/jap\r\n\r\nVom considera toate numerele naturale intre $2$ si $N$ inclusiv care nu pot fi scrise sub forma $x^y^$, unde $y diferit de 1$. Notam aceasta multime cu numere $S$. Pentru fiecare din aceste numere vom calcula puterea maxima la care poate fi ridicat astfel incat rezultatul sa fie $&le; N$. Pentru un numar $i$, vom considera ca aceasta putere este $j$ (deci $i^j^ &le; N$) si vom incerca sa calculam cate elemente distincte se pot genera ridicand fiecare din elementele $i^1^$, $i^2^$, $i^3^$, ..., $i^j^$ la puteri intre $1$ si $M$. Astfel pentru $i$ va trebui sa calculam cate elemente distincte are secventa $i^1^$, $i^2^$, ..., $i^M^$, $i^2*1^$, $i^2*2^$, ..., $i^2*M^$, ..., $i^j*1^$, $i^j*2^$, ..., $i^j*M^$. Observam ca oricum am alege $x$ si $y$ din multimea $S$, secventele generate cu regula de mai sus vor fi complet disjuncte, si in plus reuniunea tuturor secventelor va constitui intreaga secventa data in enunt. Astfel, suma numarului de elemente distincte determinate pentru fiecare $x$ din $S$ va reprezenta numarul cerut in enunt.\r\n\r\nSetul $S$ poate fi determinat, parcurgand elementele de la $2$ la $N$ si marcand toate puterile mai mari ca 1 al elementului curent ca nefacand parte din set. Determinarea setului $S$ are complexitate $O(N)$.\r\n\r\nDe aici putem elabora mai multe solutii de complexitati diferite:\r\n\r\n* $O(N)$ precalculare, $O(N * M * log(N * M))$ pe test - $20$ de puncte\r\n\r\nPentru fiecare $i$ din $S$, calculam $j$, cel mai mare numar natural astfel incat $i^j^ &le; N$, adaugam puterile $1, 2, 3, ..., M, 2, 4, 6, ..., 2M, ..., j, 2j, 3j, ..., jM$ intr-un vector, il sortam si adunam la rezultat numarul de elemente distincte din el.\r\n\r\n* $O(N)$ precalculare, $O(N log N)$ pe test - $50$ de puncte\r\n\r\nPentru fiecare $i$, vom calcula numarul de elemente distincte din secventa corespunzatoare lui folosind principiul includerii si excluderii. Fie $A$ un subset al multimii $[1, 2, 3, ..., j]$. Vom calcula $comun[A]$ = numarul de puteri aflate in intersectia tuturor secventelor $(x*1, x*2, x*3, ..., x*M)$, pentru $x apartinand lui A$. Intersectia acestor secvente trebuie sa contina numai elemente $&le; M * min(A)$, unde $min(A)$ = elementul minim din subsetul A, si numai elemente divizibile cu $lcm(A)$, unde $lcm(A)$ reprezinta cel mai mic multiplu comun al elementelor din $A$. Astfel $comun[A]$ va fi egal cu $[M * min(A) / lcm(A)]$, unde $[x]$ reprezinta partea intreaga a lui $x$.\r\n\r\nAcum, conform principiului includerii si excluderii. putem determina numarul de elemente distincte ale secventei corespunzatoare lui $i$, adunand $comun[A]$ pentru toate subseturile $A$ avand numar impar de elemente si scazand $comun[A]$ pentru toate subseturile $A$ avand numar par de elemente.\r\n\r\nObservam ca pentru multe numere din setul $S$, puterea maxima $j$ la care poate fi ridicat astfel incat rezultatul sa fie $&le; N$ se repeta si vom calcula $comun[A]$ de multe ori pentru aceleasi subseturi. Pentru a evita acest lucru putem calcula valorile lui $comun$ la inceput, pentru orice subset al multimii $[1, 2, 3, ..., log{~2~} N]$ si mentine $rez[x]$ = numarul de elemente distincte din secventa generata de un element $i$ din $S$ pentru care puterea maxima este egala cu $x$.\r\n\r\nComplexitatea totala devine O(2^log N^ log N)) precalcularea lui $comun$ + $O(N)$ adunarea sumelor, deci $O(N log N)$.\r\n\r\n* $O(N + nr_M_distinct * N log N)$ precalculare, $O(N)$ pe test - $70$ de puncte\r\n\r\nObservam ca valorile lui $comun$ si $rez$ depind doar de $M$ si deci le putem calcula doar pentru fiecare $M$ diferit din fisierul de intrare.\r\n\r\n* $O(N + nr_M_distinct * N log N)$ precalculare, $O(log^2^ N)$ pe test - $100$ de puncte\r\n\r\nAm observat deja ca daca $2$ numere diferite $i$ si $j$ din setul $S$ au aceeasi putere maxim $j$ la care pot fi ridicate fara sa depaseasca $N$, numarul de elemente distincte din secventa generata de fiecare dintre ele este egal.\r\n\r\nIn loc sa parcurgem toate elementele din $S$, putem numara pentru fiecare putere $j$ de la $1$ la $log{~2~} N$ cate numere din $S$ au aceasta putere maxima. Pentru fiecare putere putem determina limitele sale inferioare si superioare prin cautare binara si, precalculand $nrInS[i]$ = cate numere naturale $&le; i$ sunt in setul $S$, putem determina cate elemente sunt in $S$ intre cele 2 limite. Complexitate finala pe test $O(log^2^ N)$.\r\n\r\nh2. Observatie\r\n\r\nEste posibil sa ajungem la un query time de $O(1)$.\r\nAstfel, sa presupunem ca pentru fiecare putere pana in $logN$ stim cate duplicate sunt generate de un numar care este putere maxima.\r\n( exemplu: pentru exponentul egal cu 4, stim ca avem $x$ duplicate. Atunci daca inmultim numarul de numere care sunt puteri la a patra ( 16, 81, etc ) cu $x$ o sa avem numarul de duplicate date de puterile la a patra. Daca facem asta pentru fiecare putere $p$ pana in $logN$, si adaugam la rezultat, obtinem rezultatul query-ului pentru un $N$ dat. \r\nIn primul rand, pentru fiecare $n <= N$ si $p <= logN$, putem precalcula cate puteri la a $p$-a sunt $<= n$, in $O( N log N )$. De asemenea, putem\r\npreprocesa fiecare query posibil in $O(N log N)$ [ nu avem decat sa stocam produsul \"cate puteri la a $p$-a sunt $<= n$\" * \"cate duplicate sunt pentru $p$\"]. \r\nTinand cont ca $O(N log N)$ necesitam oricum pentru fiecare $M$ distinct, ajungem la un query time de $O(1)$.\r\n\r\nSper ca s-a inteles :)\r\n\r\nh2. Solutie alternativa\r\n\r\nA doua solutie calculeaza care sunt puterile $i$ pentru care $u^i^$ poate fi scris ca $v^j^$ cu $v < u$ si $j &le; M$. Prima conditie pe care trebuie sa o indeplineasca $u$, este sa se scrie de forma $p{~1~}^f1^ * ... * p{~t~}^ft^$ unde $cmmdc(f{~1~}, ..., f{~t~}) = d$, $d != 1$. Daca notam $w$ radicalul de ordin $d$ al lui $u$, atunci $u^i^$ se va scrie ca $w^d*i^$, ba chiar mai mult se va scrie ca $(w^q^)^i*d/q^$ unde $q$ divide $d$.\r\nPornind de la aceste observatii putem calcula pentru un M fixat cate numere distincte generaza $(w^d^)^i^$ pentru fiecare d in parte ( $d$ este maxim $log{~2~}N$, adica $16$). $(w^d^)^i^$ se poate scrie in functie de $w^q^$ cu $q < d$, daca $i$ e divizibil cu $q/cmmdc(d, q)$, adica $i*d$ multiplu al lui $cmmmc(d, q)$. Asadar pentru fiecare $d$ intre $2$ si $16$ si $q$ intre $1$ si $d$, vom insemna intr-un tablou ca puterea $k*cmmmmc(d, q)$, unde $k * cmmmc(d, q) / q <= M$ este duplicat pentru orice $u = w^d^$.\r\nAcum mai trebuie sa calculam pentru toate valorile de la $1$ la $N$ care este cmmdc-ul puterilor factorilor (adica $d$). Aceasta se poate face foarte repede sub forma asemanatoare cu ciurul lui Eratostene, numerele care au $d > 1$ pot fi scrise ca un numar mai mic ridicat la o putere si in loc sa adunam, inmultim.\r\nCu acest algoritm calculam dintr-o data toate query-urile care au acelasi $M$. \r\nComplexitatea finala este $O(nr_M_distinct * (M log^2^ N + N log N))$. O implementare atenta a acestei solutii va lua $100$ de puncte.\r\n\r\n',958,'public',NULL,NULL),('newsletter/algoritmiada-2009-2','Algoritmiada, Runda 2; Rezultate runda anterioara','2009-01-08 19:05:51','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nIn curand incepe a doua runda a concursului Algoritmiada, cel mai\r\nmare si mai important concurs organizat de infoarena!\r\n\nLa Algoritmiada participa elevi de gimnaziu, elevi de liceu, *dar si\r\nstudenti*! (Avem grupe separate pentru fiecare. Studentii pot fi\r\nchiar masteranzi sau doctoranzi.)\r\n\nRunda 2 se desfasoara in acest weekend. Intrece-te cu cei mai buni!\r\nAsigura-ti locul la finala si castiga premii serioase!\r\n\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Runda 2 se desfasoara\r\n\np{padding-left: 4em;}. Duminica, 11 Ianuarie 2009, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nVezi pagina concursului: \'algoritmiada-2009\':algoritmiada-2009\r\npentru mai multe informatii.\r\n\nSucces!\r\n\nh2.  Atentie! Concurs cu rating! \n\nDaca vrei sa ti se modifice rating-ul in urma acestei runde trebuie\r\nsa iti anunti participarea din timp. Intra pe\r\n\'algoritmiada-2009/runda-2\':algoritmiada-2009/runda-2 si inscrie-te.\r\n\nPoti sa participi la concurs chiar si daca nu te-ai inscris in\r\nprealabil insa nu ti se va modifica rating-ul. ==NewsletterRating(username=\"%username%\")==\r\nCiteste despre rating: \'documentatie/rating\':documentatie/rating.\r\n\nh2.  Despre Algoritmiada, Runda 2 \n\nAlgoritmiada este un concurs nou, cu premii, organizat de infoarena.\r\nConcursul se desfasoara in 3 runde online de calificare si o\r\nfinala on-site. Cei mai buni vor castiga premii serioase, in bani si\r\nobiecte.\r\n\nLa Runda 2 vei avea la dispozitie 4h sa rezolvi 3 probleme de natura\r\nalgoritmica. Concurentii sunt impartiti in 4 grupe de varsta:\r\ngimnaziu, clasele 9-10, clasele 11-12 si studenti (inclusiv\r\nmasteranzi si doctoranzi).\r\n\nSubiectele vor fi propuse de catre o echipa de fosti si actuali\r\nolimpici la informatica: Airinei Adrian, Bogdan Tataroiu, Andrei\r\nGrigorean, Gheorghe Cosmin, Paul-Dan Baltescu si Stefan Istrate.\r\nDe ce ei? Intra pe pagina rundei si citeste cate ceva despre\r\nexperienta fiecaruia: \'algoritmiada-2009/runda-2\':algoritmiada-2009/runda-2\r\n\nIti uram succes si te asteptam in arena!\r\n\nh2.  Despre runda anterioara \n\nSilviu Ganceanu a facut o analiza a primei runde Algoritmiada.\r\nAfla cati concurenti au participat, cate surse s-au trimis si\r\nimpresii despre runda aici:\r\n\'blog/algoritmiada-runda1\':blog/algoritmiada-runda1\r\n\nVezi rezultatele si clasamentul aici:\r\n\'algoritmiada-2009/clasament\':algoritmiada-2009/clasament\r\n\nh2.  Seria de concursuri preONI s-a incheiat \n\nDupa 5 ani, seria de concursuri preONI se retrage. Cel mai longeviv\r\nconcurs infoarena, cel mai amplu eveniment organizat de noi pana\r\nacum, cu o traditie lunga si cu mii de participanti, se incheie.\r\n\nDe anul acesta incepe Algoritmiada. Vom incerca sa aplicam lectiile\r\ninvatate pana acum, insa avem nevoie de ajutorul tau. Fii alaturi de\r\nnoi, contacteaza-ne pe forum, ajuta-ne sa facem din Algoritmiada o\r\ncompetitie la care ti-ar placea sa participi oricand.\r\n\nAi participat vreodata la preONI? Iti mai aduce aminte ce fel a fost,\r\nce probleme ai primit? Ti-am facut poze la finala? Viziteaza inca\r\nodata paginile editiilor anterioare:\r\n\np{padding-left: 2em;}. *   preONI 2008, finala la Univ. Politehnica, Bucuresti\r\n        \'preoni-2008\':preoni-2008\r\n\np{padding-left: 2em;}. *   preONI 2007, finala la Lic. Int. de Informatica, Bucuresti\r\n        \'preoni-2007\':preoni-2007\r\n\np{padding-left: 2em;}. *   preONI 2006, finala la C. N. \"Unirea\", Focsani\r\n        \'preoni-2006\':preoni-2006\r\n\np{padding-left: 2em;}. *   preONI 2005, finala online\r\n        \'preoni-2005\':preoni-2005\r\n\np{padding-left: 2em;}. *   preONI 2004, finala online\r\n        \'preoni-2004\':preoni-2004\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nh2.  Fii un bun infoarenaut! Implica-te! \n\nMai mult ca oricand, infoarena are nevoie de ajutorul tau! infoarena\r\neste un efort colectiv, munca a zeci de voluntari pe parcursul a 5\r\nani de zile.  Vrem sa-i sprijinim pe toti cei care, pasionati de\r\ninformatica si programare, vor sa invete mai mult, vor sa isi\r\nperfectioneze abilitatile.\r\n\nVrei sa compui problemele tale? Vrei sa organizezi concursuri? Iti\r\nplace sa programezi, doresti sa inveti cum se dezvolta un site precum\r\ninfoarena?  Vrei sa redactezi articole despre algoritmi si structuri\r\nde date? Pentru toate acestea, si pentru multe altele, infoarena are\r\nnevoie de ajutorul tau!\r\n\nAfla cum te poti implica in comunitatea infoarena:\r\n\'implica-te\':implica-te\r\n\nInvata alaturi de noi!\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n\n',13,'protected',NULL,NULL),('algoritmiada-2009/runda-2/solutii/colier','algoritmiada-2009/runda-2/solutii/colier','2009-01-03 17:07:03','2009-01-11 11:56:51','h1(#colier). \'Colier\':problema/colier\r\n\r\nSe observa destul de usor ca starea de castigare pentru $N = 2$ este $01$ sau $10$. Acum sa vedem ce se intampla cand avem un colier cu $N > 2$ perle. In primul rand trebuie sa avem cel putin o perla $1$. De fiecare data cand alegem un $1$, putem sa avem vecinii $0 **1** 0$, $0 **1** 1$, $1 **1** 0$, $1 **1** 1$. Putem observa ca in urma unei astfel de operatii paritatea perlelor $0$ ramane aceeasi. De aici tragem concluzia ca numarul de perle $0$ trebuie sa fie impar (pentru ca la un moment dat trebuie sa ajungem in una din starile castigatoare pentru $N = 2$). Tot la fel de usor se observa ca sigur exista o secventa de alegeri care sa ne duca la sfarsit, daca avem numar impar de perle $0$ (singurul caz particular ar fi cand avem doar trei perle $1$ una langa alta si o alegem pe cea din mijloc, atunci ramanem fara perle $1$, dar daca alegem de fiecare data o perla $1$ care are cel putin un vecin $0$ sigur o sa fie totul bine, si cum trebuie sa existe cel putin o perla $0$ sigur putem face aceasta alegere). De aici solutia iese foarte usor. Aveti grija, exista cateva cazuri particulare usoare, pe care va las sa le descoperiti singuri :).',2038,'public',NULL,NULL),('algoritmiada-2009/runda-2/solutii/nrsec','algoritmiada-2009/runda-2/solutii/nrsec','2009-01-03 17:07:53','2009-01-11 11:57:14','h1(#nrsec). \'Nrsec\':problema/nrsec\r\n\r\nPrimul pas in rezolvarea acestei probleme este sa vedem ca $S$ poate fi cautat binar. Fie $NR[S]$ numarul de subsecvente a caror suma este mai mica sau egala cu $S$. $NR[S]$ este crescator in functie de $S$, cand creste $S$, creste si $NR[S]$ deci $S$ poate fi cautat binar. Ce ramane de facut este avand un $S$ sa aflam $NR[S]$. Pentru ca numerele pot fi si negative sumele subsecventelor care se termina intr-un anumit punct nu sunt neaparat crescatoare, trebuie sa gasim o solutie care sa nu tina cont de asta.\r\nO solutie este asa: facem sumele partiale $A[i]$ = suma primelelor $i$ numere din sir. Acum suma unei subsecvente $i$ - $j$ este $A[j] - A[i - 1]$. Sortam aceste sume tinand pentru fiecare si indicele ei. Parcurgem sumele sortate in ordine. Sa presupunem ca suntem la pozitia $i$. Vrem sa numaram cate subsecvente cu capatul in $i$ au suma mai mica sau egala cu $S$. Fie $j$ celalat capat al acestor subsecvente. $J$ trebuie sa respecte $A[j] - A[i - 1] &le; S$. Se poate usor observa ca $j$ poate fi de la o anumita pozitie incolo in sirul sortat si daca $i$ creste, $j$ poate doar sa creasca. Explicatie: sa presupunem ca sirul de sume partiale este : $-1, 1, 5, 6$ si $S = 2$. Daca $i = 1$, $j$ poate fi de la $1$ spre sfarsit, daca $i = 2$, $j$ poate fie de la $1$ spre sfarsit, daca $i = 3$, $j$ poate fi de la $3$ spre sfarsit, daca $i = 4$, $j$ poate fi de la $4$ spre sfarsit. $J$ poate fi astfel usor determinat in timp ce parcurgem vectorul cu $i$ in $O(N)$. Avand $j$ pentru fiecare $i$ putem deduce ca numarul subsecventelor care se au un capat in $i$ si a caror suma este mai mica sau egala cu $S$ este $N - j + 1$ (unde $N$ este numarul elementelor din sir). Dar daca adunam toate aceste valori observam ca unele subsecvente le numaram de doua ori. Ca sa evitam acest lucru putem sa numaram doar pozitiile $j$ care apar ca indice din vectorul initial (nesortat) inaintea lui $i$. Pentru aceasta putem folosi un arbore de intervale, sau un arbore indexat binar (orice structura care poate sa faca update si query pe un interval in $O(log N)$). La inceput in acesta tinem toate pozitiile posibile, si pe masura ce $j$ creste scoatem pozitiile din spatele lui $j$. La pozitia $i$ facem query pe intervalul $1...PI[i]$ (unde $PI[i]$ este pozitia sumei partiale $i$ inainte de sortare).\r\nO alta solutie se bazeaza pe algoritmul $merge sort$ si este asemanatoare cu modul de numarare a numarului de inversiuni dintr-o permutare. Va las pe voi sa va ganditi cum :).\r\nComplexitatea acestor algoritmi in total este: $O(N * log N * log S_MAX)$ (unde $S_MAX$ este suma maxima a unei subsecvente)',2038,'public',NULL,NULL),('probleme-cu-secvente','Probleme cu secvențe','2008-11-23 19:46:37','2009-07-10 15:17:50','h1. Probleme cu secvenţe\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"alecman\") ==\r\n\r\n(Categoria _Algoritmi şi tehnici de programare_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut*\r\n* \'Introducere \':probleme-cu-secvente#introducere\r\n* \'Problema 1: Subsecvenţa de sumă maximă \':probleme-cu-secvente#problema-1\r\n* \'Problema 2: Maximum Sum \':probleme-cu-secvente#problema-2\r\n* \'Problema 3: SequenceQuery \':probleme-cu-secvente#problema-3\r\n* \'Problema 4 \':probleme-cu-secvente#problema-4\r\n* \'Problema 5 \':probleme-cu-secvente#problema-5\r\n* \'Problema 6: Secvenţă \':probleme-cu-secvente#problema-6\r\n* \'Problema 7: Agricultura \':probleme-cu-secvente#problema-7\r\n* \'Problema 8: Secvenţa 2 \':probleme-cu-secvente#problema-8\r\n* \'Problema 9: Sum \':probleme-cu-secvente#problema-9\r\n* \'Problema 10: Secvenţa 3 \':probleme-cu-secvente#problema-10\r\n* \'Problema 11: XorMax \':probleme-cu-secvente#problema-11\r\n* \'Probleme propuse\':probleme-cu-secvente#probleme-propuse\r\n* \'Bibliografie\':probleme-cu-secvente#bibliografie\r\n\r\nh2(#introducere). Introducere\r\n\r\nAcest articol prezintă o serie de probleme înrudite cu problema subsecvenţei de sumă maximă, însoţite de rezolvări eficiente. Problemele prezentate pot apărea oricând ca subprobleme în concursurile de programare, studierea lor mărind în mod util bagajul de cunoştinţe al unui elev pasionat de algoritmică.\r\n\r\nh2(#problema-1). Problema 1: \'Subsecvenţa de sumă maximă\':problema/ssm\r\n\r\nbq. Se dă un şir de $N$ numere întregi $(a{~1~}, a{~2~}, ..., a{~N~})$. Să se determine o subsecvenţă $(a{~i~}, a{~i+1~}, ..., a{~j~})$ care să aibă suma maximă.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(-1, 2, 3, -4, -2, 2, 1, -3, -2, -3, -4, 9, -2, 1, 7, 8, -19, -7, 2, 4, 3)$, o subsecvenţă de sumă maximă este $(9, -2, 1, 7, 8)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPrima rezolvare care ne vine în minte are complexitatea $O(N^3^)$ şi constă în determinarea sumei fiecărei subsecvenţe posibile şi reţinerea maximului acestor sume. Este evident că anumite sume parţiale sunt calculate de mai multe ori.\r\n\r\nPutem reduce complexitatea la $O(N^2^)$ ţinând cont de faptul că suma subsecvenţei $a[i..j]$ este egală cu suma subsecvenţei $a[i..j-1]$, la care se adună $a[j]$. Păstrăm într-un şir $sum[i]$ suma elementelor din subsecvenţa $a[1..i]$. Pentru a determina suma elementelor din subsecvenţa $a[i..j]$ facem diferenţa: $sum[i] - sum[j-1]$.\r\n\r\nIdeea poate fi rafinată calculând pentru fiecare indice $i$ numărul $best[i]$, reprezentând subsecvenţa de sumă maximă cu capătul drept în $i$. Este uşor de observat că $best[i] = max(sum[i] - sum[j-1])$, unde $j$ ia valori de la $1$ la $i$. Relaţia anterioară se mai poate scrie: $best[i] = sum[i] - min(sum[j-1])$. Obţinem astfel un algoritm liniar care ne determină subsecvenţa de sumă maximă cerută.\r\n\r\n== code(cpp) |\r\nsum[0] = 0;\r\nfor (i = 1; i <= N; i++) sum[i] = a[i] + sum[i-1];\r\nmin = sum[0];\r\nbestSum = -INFINIT;\r\nfor (i = 1; i <= N; i++) {\r\n    best[i] = sum[i] - min;\r\n    if (min > sum[i]) min = sum[i];\r\n    if (bestSum < best[i]) bestSum = best[i];\r\n}\r\n==\r\n\r\nO altă metodă de calcul poate fi dedusă folosind paradigma _Divide et Impera_. La fiecare pas împărţim şirul în jumătate şi aflăm subsecvenţele de sumă maximă din cele două jumătăţi. După aceea trebuie să găsim subsecvenţa de sumă maximă ce are un capăt în fiecare din cele două jumătăţi ale sirului. Pentru aceasta alipim sufixul de sumă maximă a primei jumătăţi cu prefixul de sumă maximă a celei de a doua.\r\n\r\n== code(cpp) |\r\nint getMaxSubsequence(int l, int r) {\r\n    if (l == r) return a[l];\r\n    mid = (l + r) / 2;\r\n    bestL = getMaxSubsequence(l, mid);\r\n    bestR = getMaxSubsequence(mid + 1, r);\r\n    suf = 0; \r\n    pre = 0; \r\n    maxSuf = -INFINIT; \r\n    maxPre = -INFINIT;\r\n    for (i = mid; i >= l; i--) {\r\n        suf += a[i];\r\n        if (maxSuf < suf) maxSuf = suf;\r\n    }\r\n    for (i = mid + 1; i <= r; i++) {\r\n        pre += a[i];\r\n        if (maxPre < pre) maxPre = pre;    \r\n    }\r\n    return max(bestL, max(bestR, maxPre + maxSuf));\r\n}\r\n==\r\n\r\nO idee bazată pe paradigma programării dinamice ar fi să folosim un şir $best[i]$, reprezentând suma maximă a unei subsecvenţe ce se termină în $a[i]$. Problema se rezolvă cu următoarea formulă de recurenţă: $best[i] = max(a[i], best[i-1] + a[i])$. Formula poate fi demonstrată prin inducţie matematică.\r\n\r\n== code(cpp) |\r\nbestSum = a[1];\r\nfor (i = 1; i <= N; ++ i) {\r\n    best[i] = a[i];\r\n    if (best[i] < best[i-1] + a[i]) \r\n        best[i] = best[i-1] + a[i];\r\n    if (bestSum < best[i])\r\n        bestSum = best[i];\r\n}\r\n==\r\n\r\nO ultimă idee, dacă se garantează că există cel puţin un număr pozitiv, ar fi să partiţionăm şirul în subsecvenţe încât fiecare să aibă ambele capete cât mai mici posibile şi suma elementelor subsecvenţei să fie negativă. Pentru exemplul dat avem următoarea partiţionare: $[-1], [2, 3, -4, -2], [2, 1, -3, -2], [-3], [-4], [9, -2, 1, 7, 8, -19, -7], [2, 4, 3]$. O subsecvenţă de sumă maximă va avea primul capăt la începutul unei astfel de subsecvenţe, acest lucru explicându-se prin faptul că în caz contrar secvenţa poate fi mărită în stânga (orice secvenţă din cele alese pentru partiţionare are toate prefixele de sumă pozitivă, în afară de prefixul ce reprezintă întreaga subsecvenţă). De asemenea, orice subsecvenţă de sumă maximă nu va conţine elemente din altă parte a partiţiei, pentru că dacă subsecvenţa se întinde pe mai multe părţi, atunci putem elimina prefixul subsecvenţei care reprezintă o parte a partiţiei, acea parte având suma negativă.\r\n\r\n== code(cpp) |\r\nsum = 0;\r\nbestSum = -INFINIT;\r\nfor (i = 1; i <= N; i++) {\r\n    sum += a[i];\r\n    if (sum < 0)\r\n        sum = 0;\r\n    else if (sum > bestSum) \r\n        bestSum = sum;      \r\n}\r\n==\r\n\r\nh2(#problema-2). Problema 2: \'Maximum Sum\':http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=3&page=show_problem&problem=44 (UVa)\r\n\r\nbq. Se dă o matrice de dimensiuni $N x N$ cu elemente întregi. Se cere determinarea unei submatrici a cărei elemente au suma maximă. \r\n\r\nh3. Exemplu:\r\n\r\nPentru matricea<tex>\\[ \\left( \\begin{array}{cccc}0 & -2 & -7 & 0 \\\\9 & 2 & -6 & 2 \\\\-4 & 1 & -4 & 1 \\\\-1 & 8 & 0 & -2 \\end{array} \\right)\\]</tex>submatricea de sumă maximă este următoarea:<tex>\\[ \\left( \\begin{array}{cc}9 & 2 \\\\-4 & 1 \\\\-1 & 8 \\end{array} \\right)\\]</tex>\r\n\r\nh3. Rezolvare:\r\n\r\nPutem folosi trucul construirii sumelor parţiale din rezolvarea anterioară, pentru cazul $2D$. Păstrăm în $sum[i][j]$ suma tuturor elementelor $a[i{~1~}][j{~1~}]$ cu proprietatea că $1 &le; i{~1~} &le; i$, şi $1 &le; j{~1~} &le; j$. Putem calcula sumele prin metoda programării dinamice în complexitate $O(N^2^)$ folosind formula: $sum[i][j] = a[i][j] + sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1]$. Acum, pentru a calcula suma elementelor din matricea cu colţurile $(i{~1~}, j{~1~})$ şi $(i{~2~}, j{~2~})$, unde $i{~1~} &le; i{~2~}$ şi $j{~1~} &le; j{~2~}$, este suficient să facem calculul $sum[i{~2~}][j{~2~}] - sum[i{~1~}-1][j{~2~}] - sum[i{~2~}][j{~1~}-1] + sum[i{~1~}-1][j{~1~}-1]$. Astfel putem evalua suma din fiecare submatrice în timp constant, deci rezolvarea are ordinul de complexitate $O(N^4^)$.\r\n\r\nO altă idee ar fi ca pentru fiecare pereche $(i{~1~}, i{~2~})$ fixată să determinăm perechea optimă $(j{~1~}, j{~2~})$. Dacă avem liniile $i{~1~}$ şi $i{~2~}$ fixate atunci problema se transformă din una bidimensională în una unidimensională. Astfel pentru fiecare coloană $j$ vom considera $b[j]$ ca sumă a elementelor $a[i][j]$ cu proprietatea că $i{~1~} &le; i &le; i{~2~}$. În exemplul nostru, dacă $i{~1~} = 2$ şi $i{~2~} = 3$, atunci avem: $b{~1~} = 9 + (-4)$, $b{~2~} = 2 + 1$, $b{~3~} = (-6) + (-4)$ şi $b{~4~} = 2 + 1$. Pentru a rezolva problema unidimensională folosim unul din algoritmii liniari prezentaţi mai sus, astfel obţinându-se un algoritm de complexitate totală $O(N^3^)$. Acest truc de a fixa două linii pentru a transforma problema în una unidimensională este util în multe probleme pe matrice sau cu puncte în plan.\r\n\r\nCel mai bun algoritm cunoscut pentru această problemă are complexitatea <tex>O(N^{3\\sqrt{\\frac{\\log \\log N}{\\log N}}})</tex> şi este mai mult un algoritm teoretic decât unul practic, uşor implementabil. Pentru detalii puteti consulta lucrarea [3].\r\n\r\nh2(#problema-3). Problema 3: \'SequenceQuery\':problema/sequencequery (Bursele Agora 2006)\r\n\r\nbq. Se consideră un şir $A = (a{~1~}, a{~2~}, ..., a{~N~})$, format din numere întregi $(-100.000 &le; a{~i~} &le; 100.000)$, şi $M$ perechi de numere $(x, y)$ $(1 &le; N, M &le; 100.000)$. Pentru fiecare pereche ordonată de indici $(x, y)$ trebuie determinată subsecvenţa de sumă maximă a subşirului $a{~x~}, a{~x+1~}, ..., a{~y~}$. Subsecvenţele alese trebuie să conţină cel puţin un element. \r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(-1, 2, 3, -2, 4, -3, 8, -3)$ şi intervalele $[1, 5]$, $[4, 8]$ si $[6, 6]$ avem soluţiile: \r\n\r\n* $7$ pentru subsecvenţa $(-1, *2*, *3*, *-2*, *4*)$;\r\n\r\n* $9$ pentru subsecvenţa $(-2, *4*, *-3*, *8*, -3)$;\r\n\r\n* $-3$ pentru subsecvenţa $({*-3*})$.\r\n\r\nh3. Rezolvare:\r\n\r\nPutem obţine un algoritm de complexitate $O(M * N)$ folosind algoritmii liniari din prima problemă, dar să vedem cum putem reduce complexitatea folosind alte abordări. Mai întâi calculăm şirul $sum[]$ al sumelor parţiale, după care împărţim şirul în $K$ subsecvenţe de lungimi egale $[N / K]$, şi păstrăm următoarele informaţii pentru fiecare din ele:\r\n\r\n* $max[i]$ - cea mai mare valoare $sum[j]$, unde: $N / K * (i - 1) < j &le; N / K * i$;\r\n\r\n* $min[i]$ - cel mai mic $sum[j - 1]$, unde: $N / K * (i - 1) < j &le; N / K * i$;\r\n\r\n* $best[i]$ - valoarea subsecventei de suma maxima a secventei curente.\r\n\r\nAcum, pentru a afla subsecvenţa de sumă maximă a subsecvenţei $a[x..y]$ studiem cele două cazuri posibile:\r\n\r\n# Dacă elementele de indice $x$ şi $y$ aparţin aceleiaşi subsecvenţe, atunci putem găsi ceea ce căutăm folosind algoritmul liniar direct pe şirul $a[x..y]$. Complexitate: $O(N / K)$.\r\n\r\n# Dacă nu sunt în aceeaşi secvenţă, atunci vom împărţi şirul $a[x..y]$ în:\r\n\r\n* un prefix de subsecvenţă din cele ce aparţin partiţionării,\r\n\r\n* un sufix de subsecvenţă,\r\n\r\n* zero sau mai multe subsecvenţe complete ce aparţin partiţionării,\r\n\r\ndupă care rezolvăm problema pentru sufix şi prefix prin metoda liniară în $O(N / K)$, şi determinăm în $O(1)$ pentru fiecare bucată în care este spart şirul $a[x..y]$ subsecvenţa ei de sumă maximă.\r\n\r\nMai rămâne să găsim subsecvenţa de sumă maximă cu capătul în bucăţi diferite. Pentru două bucăţi fixate $i < j$, subsecvenţa de sumă maximă ce are câte un capăt în fiecare bucată are valoarea: $max[j] - min[i]$. Determinarea subsecvenţei de sumă maximă cu capetele în bucăţi diferite devine astfel de complexitate $O(K)$. Deci, pentru a rezolva o întrebare trebuie să facem $O(N / K + K)$ calcule. Pentru a reduce complexitatea problemei considerăm pe $K = sqrt(N)$. Complexitatea totală a acestei soluţii este $O(N + M * sqrt(N))$.\r\n\r\nSă vedem ce se întâmplă pe exemplu:\r\n\r\ntable{width:300px; text-align:right;}.\r\n|_. $a$ | - | $-1$ | $2$ | $3$ | $-2$ | $4$ | $-3$ | $8$ | $-3$ | $1$ |\r\n|_. $sum$ | $0$ | $-1$ | $1$ | $4$ | $2$ | $6$ | $3$ | $11$ | $8$ | $9$ |\r\n\r\nşirul e împărţit în trei subsecvenţe $[-1, 2, 3], [-2, 4, -3], [8, -3, 1]$:\r\n\r\ntable{width:100px; text-align:right;}.\r\n|_. $max$ | $4$ | $6$ | $11$ |\r\n|_. $min$ | $-1$ | $2$ | $8$ |\r\n|_. $best$ | $5$ | $4$ | $8$ |\r\n\r\nPentru a răspunde la întrebarea $[1, 5]$ trebuie să răspundem la cele două subsecvenţe componente $[1..3]$ şi $[4..5]$. Soluţia optimă pentru $[1..3]$ este $best[&#49;] = 5$. Soluţia optimă pentru $[4..5]$ o determinăm folosind algoritmul liniar, ea fiind $4$. Acum, pentru a determina subsecvenţa de sumă maximă cu câte un capăt în fiecare interval folosim formula: $max(sum[i]) - min(sum[j - 1])$, unde $4 &le; i &le; 5$ şi $1 &le; j &le; 3$. Valoarea $max(sum[i])$ o găsim parcurgând intervalul $[4, 5]$ ca fiind $6$, iar valoarea $min(sum[j - 1])$ o avem deja calculată în $min[&#49;]$. De aici obţinem rezultatul $7$.\r\n\r\nO soluţie similară poate fi obţinută cu ajutorul arborilor de intervale. Mai întâi creăm arborele de intervale. Pentru fiecare interval aflăm elementele $min$, $max$ şi $best$ astfel:\r\n\r\n* $min[x..y] = minim(min[x..(x+y)/2], min[(x+y)/2 + 1 .. y])$;\r\n\r\n* $max[x..y] = maxim(max[x..(x+y)/2], max[(x+y)/2 + 1 .. y])$;\r\n\r\n* $best[x..y] = maxim(best[x..(x+y)/2], maxim(best[(x+y)/2 + 1 .. y], max[(x+y)/2 + 1 .. y] - min[x..(x+y)/2]))$.\r\n\r\nAcum pentru a răspunde la întrebările din problemă fiecare interval va fi împărţit în $O(log N)$ subintervale canonice care apar în arborele de intervale. Apoi printr-o parcurgere asemănătoare celei din rezolvarea anterioară se poate obţine rezultatul pentru fiecare întrebare în $O(log N)$. Soluţia va avea complexitatea $O(N + M * log N)$.\r\n\r\nÎn următorul desen observăm structura unui arbore de intervale pentru un şir cu $16$ elemente. Daca se pune întrebarea $[2, 11]$ acest interval va fi spart în intervalele $[2, 2], [3, 4], [5, 8], [9, 10], [11, 11]$.\r\n\r\np=. !probleme-cu-secvente?numere2.png!\r\n\r\nPrezentăm procedura de construire a arborelui, implementată în _java_:\r\n\r\n== code(java) |\r\npublic void build_tree(int index, int low, int high) {\r\n    if (low == high) {\r\n        if (low != 0) aint[index] = new Node(low, high, a[low] - a[low - 1], a[low], a[low]);\r\n        else aint[index] = new Node(low, high, 0, 0, 0);\r\n    }\r\n    else {\r\n        aint[index] = new Node(low, high, -INFINIT, -INFINIT, INFINIT);\r\n        int mid = (low + high) / 2;\r\n        build_tree(2 * index, low, mid);\r\n        build_tree(2 * index + 1, mid + 1, high);\r\n        aint[index].maxS = Math.max(aint[2 * index].maxS,\r\n                Math.max(aint[2 * index + 1].maxS, aint[2 * index + 1].max - aint[2 * index].min));\r\n        aint[index].max = Math.max(aint[2 * index].max, aint[2 * index + 1].max);\r\n        aint[index].min = Math.min(aint[2 * index].min, aint[2 * index + 1].min);\r\n    }\r\n}\r\n==\r\n\r\nşi procedura care răspunde la întrebări tot în _java_:\r\n\r\n== code(java) |\r\nlong minPrefix;\r\nint x, y;\r\npublic long queryTree(int index, int low, int high) {\r\n    if (x <= low && high <= y) {\r\n        long maxRet = aint[index].maxS;\r\n        if (minPrefix != INFINIT) {\r\n            maxRet = Math.max(maxRet, aint[index].max - minPrefix);\r\n        }\r\n        minPrefix = Math.min(minPrefix, aint[index].min);\r\n        return maxRet;\r\n    }\r\n    else {\r\n        int mid = (low + high) / 2;\r\n        if (x <= mid && mid < y) \r\n            return Math.max(queryTree(2 * index, low, mid), queryTree(2 * index + 1, mid + 1, high));\r\n        else if (x > mid) \r\n            return queryTree(2 * index + 1, mid + 1, high);\r\n        else \r\n            return queryTree(2 * index, low, mid);\r\n    }\r\n}\r\n==\r\n\r\nAutorul vă recomandă articolele [1] şi [2] pentru o înţelegere mai profundă a structurii de date numită arbori de intervale. Problema poate fi soluţionată şi în $O(N + M)$, dar algoritmul este mult prea complicat pentru un concurs de programare; cei interesaţi pot să îl găsească în [4].\r\n\r\nh2(#problema-4). Problema 4 (ACM ICPC NWERC 97, olimpiada online 2000, .campion 2001)\r\n\r\nbq. Se dă un şir $(a{~1~}, a{~2~}, ..., a{~N~})$ format din numere întregi. Se cere să se determine subsecvenţa $a[i..j]$ care are modulul sumei elementelor minim.\r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(2, 8, -6, -6, 9, 4, -3)$, subsecvenţa este $(4, -3)$, având suma în modul $1 = |4 - 3|$.\r\n\r\nh3. Rezolvare:\r\n\r\nConstruim întâi şirul sumelor parţiale. Pentru oricare două elemente $sum[i]$ şi $sum[j]$ cu $(i != j)$ modulul sumei unei subsecvenţe din şir va fi $|sum[i] - sum[j]|$. Dacă $i < j$, atunci secvenţa va fi $a[i+1..j]$, iar dacă $j < i$, atunci secvenţa va fi $a[j+1 .. i]$. Astfel, pentru a găsi subsecvenţa de modul minim trebuie, de fapt, să găsim perechea de indici $i$ şi $j$ astfel ca $|sum[i] - sum[j]|$ să fie minim. Sortând şirul sumelor parţiale şi luând o pereche de indici $i < j$, atunci $sum[i] < sum[j]$, iar $|sum[j] - sum[i]| = sum[j] - sum[i]$. Pentru a găsi perechea $(i, j)$ pentru care $i < j$ şi $sum[j] - sum[i]$ este minim, trebuie ca $i$ să fie egal cu $j + 1$. Astfel obţinem un algoritm de complexitate $O(N * log N)$.\r\n\r\nSă vedem cum merge pe exemplul prezentat:\r\n\r\ntable{width:300px; text-align:right;}.\r\n|_. $a$ | - | $2$ | $8$ | $-6$ | $-6$ | $9$ | $4$ | $-3$ |\r\n|_. $sum$ | $0$ | $2$ | $10$ | $4$ | $-2$ | $7$ | $11$ | $8$ |\r\n|_. $ind$ | $0$ | $1$ | $2$ | $3$ | $4$ | $5$ | $6$ | $7$ |\r\n\r\nÎn şirul $ind$ vom păstra indicii reali ai sumelor parţiale. După sortare avem:\r\n\r\ntable{width:300px; text-align:right;}.\r\n|_. $sum$ | $-2$ | $0$ | $2$ | $4$ | $7$ | $8$ | $10$ | $11$ | \r\n|_. $ind$ | $4$ | $0$ | $1$ | $4$ | $5$ | $7$ | $2$ | $6$ |\r\n\r\nO secvenţă de modul $2$ ar fi cea reprezentată de sumele $8$ şi $10$, cu indicii $7$ şi $2$. Această secvenţă este $(-6, -6, 9, 4, -3)$. Observăm ca cea mai mică diferenţă între termeni consecutivi e cea dintre $8$ şi $7$, care au indicii $7$ şi $5$, de unde obţinem că subsecvenţa de modul minim este $(4, -3)$. \r\n\r\nh2(#problema-5). Problema 5 (USACO)\r\n\r\nbq. Se dă un şir $(a{~1~}, a{~2~}, ..., a{~N~})$ format din $N (1 &le; N &le; 100 000)$ numere întregi $(1 &le; a{~i~} &le; 2 000)$ si un numar natural $F$. Se cere să se determine subsecvenţa $a[i..i + K - 1]$ cu media aritmetică a elementelor maximă, unde $K$ are proprietatea $K &ge; F$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(6, 4, 2, 10, 3, 8, 5, 9, 4, 1)$ şi $F = 6$ soluţia optimă este $(10, 3, 8, 5, 9, 4)$, cu media $6.5$.\r\n\r\nh3. Rezolvare:\r\n\r\nFie $X$ un număr real. Considerând şirul $b$, obţinut prin transformarea $b{~i~} = a{~i~} - X$, atunci toate subsecvenţele şirului $b$ vor avea valoarea mediei elementelor lor cu $X$ mai mică decât valoarea subsecvenţelor corespunzătoare din şirul $a$. Observăm apariţia a trei cazuri:\r\n\r\n* Dacă subsecvenţa de sumă maximă din $b$ are valoarea mai mare ca $0$, atunci şi media ei va fi mai mare ca $0$. Rezultă astfel că şi media subsecvenţei corespunzătoare din şirul $a$ va fi mai mare decât $X$, deci media maximă a unei subsecvenţe din $a$ va fi mai mare ca $X$. \r\n\r\n* Cand subsecvenţa de sumă maximă din şirul $b$ are media mai mică decât $0$, atunci orice subsecvenţă din şirul $a$ va avea media mai mică decât $X$. \r\n\r\n* În cazul în care subsecvenţa de sumă maximă a şirului $b$ are valoarea egală cu zero, atunci subsecvenţa de medie maximă a şirului $a$ are media $X$.\r\n\r\nAstfel putem face o căutare binară pentru a determina valoarea $X$ a mediei maxime. Ne mai rămâne să determinăm un algoritm eficient pentru găsirea subsecvenţei de sumă maximă de lungime cel puţin $F$. O asemenea soluţie urmăreşte una din ideile din prima problemă: fie $best[i]$ subsecvenţa de sumă maximă ce se termină în $a[i]$. Evident $best[i] = max(a[i], best[i - 1] + a[i])$. Acum secvenţa de sumă maximă ce se termină în $a[i]$, de lungime cel puţin $F$ se găseşte ca $a[i] + a[i - 1] + .. + a[i - F + 2] + best[i - F + 1]$. Această relaţie poate fi calculată în $O(1)$ dacă ne folosim de trucul sumelor parţiale. Complexitatea finală este $O(N * log C)$, unde $C$ e valoarea maximă a lui $a{~i~}$.\r\n\r\nh2(#problema-6). Problema 6: \'Secvenţă\':problema/secventa\r\n\r\nbq. Se da un şir de $N$ numere întregi. O secvenţă este un subşir de numere care apar pe poziţii consecutive în şirul iniţial. Definim baza unei secvenţe ca fiind minimul valorilor elementelor din secvenţa respectivă. Fiind dat un număr natural $K$, determinaţi o secvenţă de lungime cel puţin $K$, cu baza maximă. Restrictii: $1 &le; K &le; N &le; 500 000$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru $K = 3$ şi şirul $(-1, 2, 3, 1, 0, 4, 8, 6)$, secvenţa de bază maximă este $(4, 8, 6)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPresupunem că orice secvenţă optimă ar avea lungimea mai mare decât $K$. Atunci putem obţine o secvenţă mai mică, cu aceeaşi bază eliminând unul din capetele unei secvenţe optime. Deci este de ajuns să cautăm secvenţele optime de lungime exact $K$.\r\n\r\nAcum putem face o parcurgere a şirului pentru a rezolva problema. Mai întâi punem într-un $min-heap$ $K$ elemente, verificăm vârful heapului şi obţinem astfel minimul secvenţei $a[1..K]$. Apoi eliminăm elementul $a[&#49;]$ din heap şi inserăm elementul $a[K + 1]$. Prin verificarea vârfului heapului obţinem minimul secvenţei $a[2..K + 1]$. Continuăm procedeul până aflăm elementul minim pentru fiecare subsecvenţă de lungime $K$ a şirului $a$ (complexitate $O(N * log K)$). Există şi alte soluţii pentru găsirea elementului minim al unei subsecvenţe, precum folosirea unui arbore de intervale sau folosirea tehnicii $O(N * log N) / O(1)$ pentru problema _RMQ_.\r\n\r\nO observaţie importantă este aceea că dacă vrem să vedem minimul secvenţei ce se termină în $i$ şi avem $j{~1~} < j{~2~} &le; i$ şi $a[j{~1~}] &ge; a[j{~2~}]$, atunci evident $a[j{~1~}]$ nu va fi minimul secvenţei ce se termină în $i$. Folosim o structură de date ca la soluţia cu heapuri, care adaugă elemente noi şi şterge elemente vechi, dar pe lângă elementele ce au fost inserate acum $K$ paşi şi trebuie şterse, mai ştergem şi elementele mai noi care nu ne vor mai fi utile, după cum este $a[j{~2~}]$ mai sus. Ca structură de date folosim o listă în care putem insera şi şterge de la ambele capete, un _deque_. Fiecare element inserat în deque va fi o pereche de valori, valoarea din şir şi indexul din şir $(a[i], i)$. Când o valoare este inserată în şir, ea este pusă la capătul din dreapta al şirului, dar înainte de inserare cât timp elementul din capătul şirului are valoarea mai mare decât $a[i]$ el este eliminat. La fiecare pas după o inserţie se verifică dacă elementul din capătul din stânga este mai „bătrân” de $K$ iteraţii.\r\n\r\nDin cauza modului în care se fac inserţiile şi ştergerile, şirul va fi sortat totdeauna crescător după indecşi şi crescător după valori. Tot timpul ultimul element din stivă va conţine valoarea bazei. Acest algoritm are complexitatea $O(N)$ pentru că fiecare element este inserat şi şters din deque cel mult o dată.\r\n\r\nSă vedem cum funcţionează rezolvarea pe un exemplu : $a = (-1, 2, 3, 1, 0, 4, 8, 6)$\r\n\r\n* inserăm $(-1, 1)$\r\nlista devine: $(-1, 1)$\r\n \r\n\r\n* inserăm $(2, 2)$\r\nlista devine: $(-1, 1) (2, 2)$\r\n\r\n\r\n* inserăm $(3, 3)$\r\nlista devine: $(-1, 1) (2, 2) (3, 3)$\r\nelementul minim al secvenţei $a[1..3]$ este $-1$\r\n\r\n\r\n* inserăm $(1, 4)$\r\nştergem $(3, 3)$ şi $(2, 2)$\r\nştergem $(-1, 1)$ ( inserat acum $4$ paşi )\r\nlista de vine: $(1, 4)$\r\nelementul minim al secvenţei $a[2..4]$ este $1$\r\n\r\n\r\n* inserăm $(0, 5)$\r\nştergem $(1, 4)$\r\nlista devine: $(0, 5)$\r\nelementul minim al secvenţei $a[3..5]$ este $0$.\r\n\r\n\r\n* inserăm $(4, 6)$\r\nlista devine: $(0, 5) (4, 6)$\r\nelementul minim al secvenţei $a[4..6]$ este $0$\r\n\r\n\r\n* inserăm $(8, 7)$\r\nlista devine: $(0, 5) (4, 6) (8, 7)$\r\nelementul minim al secvenţei $a[5..7]$ este $0$\r\n\r\n\r\n* inserăm $(6, 8)$\r\nştergem $(8, 7)$\r\nştergem $(0, 5)$ ( inserat acum $4$ paşi )\r\nlista devine: $(4, 6) (6, 8)$\r\nelementul minim al secvenţei $a[6..8]$ este $4$\r\n\r\nh2(#problema-7). Problema 7: Agricultura (Algoritmus)\r\n\r\nbq. Se dă o matrice de dimensiuni $N x M$ de numere naturale. Se cere determinarea unei submatrici cu număr maxim de celule în care diferenţa între valoarea maximă şi valoarea minimă este mai mică decât o valoare dată $K$. Restrictii: $2 &le; N, M &le; 150$, $1 &le; K &le; 1 000$.\r\n\r\nh3. Exemplu:\r\n\r\nDe exemplu pentru $K = 3$ şi matricea <tex>\\[ \\left( \\begin{array}{cccccc}1 & 1 & 3 & 1 & 2 & 7 \\\\9 & 2 & 3 & 2 & 3 & 2 \\\\7 & 8 & 2 & 3 & 1 & 5 \\\\4 & 5 & 6 & 0 & 1 & 4 \\end{array} \\right)\\]</tex>, soluţia optimă va avea $9$ celule.\r\n\r\nh3. Rezolvare:\r\n\r\nProblema constă în determinarea submatricei cu număr maxim de celule în care diferenţa între valoarea maximă şi valoarea minimă este mai mică decât $K$. Vom folosi ideea de la problema cu subsecvenţa de sumă maximă pe matrice, adică vom fixa două linii $i{~1~}$ şi $i{~2~}$. Acum pentru fiecare coloană $j$ păstrăm în $m[j]$ elementul minim şi în $M[j]$ elementul maxim $a[i][j]$ cu $i{~1~} &le; i &le; i{~2~}$. Astfel la fiecare pas trebuie acum să rezolvăm problema determinării unei subsecvenţe de lungime maximă pentru care diferenţa între elementul maxim şi minim este mai mică decât $K$. Folosind un _max-heap_ şi un _min-heap_ putem parcurge elementele şirurilor $M$ şi $m$ în ordine inserând la fiecare pas elemente în heap şi determinând cea mai lungă secvenţă ce se termină în $i$ cu proprietatea dată. Vom ţine un al $2$-lea indice $j$, iniţial $0$, care atâta timp cât diferenţa între elementul maxim din max-heap cu elementul minim din min-heap este mai mare sau egală cu $K$, vom scoate din heapuri elementele $M[j]$, respectiv $m[j]$ şi îl vom incrementa pe $j$. Complexitate: $O(N^3^ log N)$. Dacă în loc de heapuri folosim deque-uri, atunci acest algoritm va avea complexitatea $O(N^3^)$.\r\n\r\nh2(#problema-8). Problema 8: \'Secvenţa 2\':problema/secv2\r\n\r\nbq. Se da un şir de $N$ numere întregi şi un număr natural $K$. O secvenţă este un subşir de numere care apar pe poziţii consecutive în şirul iniţial. Se cere să se găsească secvenţa de sumă maximă de lungime cel puţin $K$. Restrictii: $1 &le; K &le; N &le; 50 000$.\r\n\r\nh3. Exemplu:\r\n\r\nDe exemplu pentru şirul $(0, -6, 2, 1, 4, -1,  3, -5)$ şi $K = 3$, soluţia optimă este $(2, 1, 4, -1, 3)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPutem folosi rezolvarea liniară bazată pe programare dinamică prezentată ca subalgoritm în soluţia \'problemei $5$\':probleme-cu-secvente#problema-5, dar putem simplifica logica din acea rezolvare. Vom folosi şirul sumelor parţiale $sum[]$, iar pentru a determina subsecvenţa de sumă maximă ce se termină în $i$ şi are lungimea cel puţin $K$ trebuie să găsim $sum[j]$ minim astfel ca $j < i - K$. Parcurgem lista, şi la pasul $i$ determinăm $best[i] = sum[i] - min(sum[j])$, $j < i - K$. Comparăm minimul curent cu $sum[i - K]$ şi trecem la pasul următor. Complexitate: $O(N)$.\r\n\r\nh2(#problema-9). Problema 9: \'Sum\':problema/sum2 (Stelele Informaticii 2003)\r\n\r\nbq. Se dă un şir de $N$ numere întregi. Se caută un subşir cu lungimea cuprinsă între $L$ şi $U$, format din elemente consecutive ale şirului iniţial, cu suma elementelor maximă. Restrictii: $1 &le; L &le; U &le; N &le; 100 000$.\r\n\r\nh3. Rezolvare:\r\n\r\nPentru fiecare $i$ este de ajuns să aflăm valoarea expresiei $sum[i] - sum[j]$, unde $i - L > j &ge; i - U$. Pentru a determina valoarea optimă pentru $sum[j]$ putem folosi un heap de dimensiune $U - L$, sau putem folosi tehnici de determinare a valorii minime într-un interval dat. Complexitate: $O(N * log(U - L))$.\r\n\r\nAltă abordare de aflare a minimelor unor secvenţe de lungime dată (în cazul acesta lungimea este $U - L$ ) a fost prezentată în rezolvarea \'problemei $6$\':probleme-cu-secvente#problema-6. Folosind acea tehnică obţinem o rezolvare de complexitate liniară.\r\n\r\nO altă rezolvare frumoasă prezentată în [4] este următoarea: spunem că o secvenţă este negativă spre stânga dacă suma oricărui prefix ( în afară de secvenţa în sine ) al secvenţei este negativ sau zero. O partiţie a secvenţei $A = (A{~1~}, A{~2~}, ..., A{~k~})$ este minimală negativă spre stânga dacă fiecare $A{~i~}$ este negativă spre stânga, iar suma elementelor lui $A{~i~}$ este strict pozitivă dacă $i != k$. De exemplu secvenţa $(-4, 1, -2, 3)$ este negativă la stânga, pe când secvenţa $(5, -3, 4, -1, 2, -6)$ nu este. Partiţia $(5) (-3, 4) (-1, 2) (-6)$ este minimală negativă la stânga.\r\n\r\nPentru fiecare element din partiţie ţinem minte un pointer $p[i]$ spre ultimul element din subsecvenţa din care face parte. Fiecare interval $[i, p[i]]$ va corespunde celei mai scurte subsecvenţe care începe în $i$ şi are suma pozitivă. Pentru a determina o soluţie a problemei pentru fiecare $i$ din care poate începe o subsecvenţă de sumă maximă, ne vom plimba cu un pointer $j$ astfel ca $j$ să fie cât mai depărtat de $i$ şi $j - i + 1 &le; U$. Obţinem astfel de fiecare dată o subsecvenţă de sumă maximă ce începe în $i$, cu lungimea mai mică sau egală cu $U$. Indicele $j$ va fi întotdeauna un capăt de secvenţă negativă la stânga şi la fiecare mărire a lui $i$ verificăm dacă lui $j$ îi putem atribui valoarea $p[j + 1]$ ( adică dacă $p[j + 1] - i + 1 &le; U$ ). Dacă secvenţa de sumă maximă de lungime cel mult $U$ ce începe în $i$ are lungimea mai mică decât $L$, atunci secvenţa de sumă maximă cu lungimea cuprinsă între $L$ şi $U$ are lungimea exact $L$. Complexitate: $O(N)$.\r\n\r\nh2(#problema-10). Problema 10: \'Secvenţa 3\':problema/secv3\r\n\r\nbq. Se dă un şir de $N$ elemente pentru care se cunosc două informaţii: costul şi timpul. O secvenţă este un subşir de numere care apar pe poziţii consecutive în şirul iniţial. Se caută o secvenţă din cele $N$ elemente care să fie de lungime minim $L$ şi maxim $U$, iar suma costurilor elementelor secvenţei împărţiţă la suma timpurilor elementelor secvenţei să fie maximă. Restrictii: $1 &le; L &le; U &le; N &le; 30 000$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru $L = 1, R = 2$ şi şirurile $c = ( 1, 1, 3, 2, 5 )$ şi $t = ( 4, 2, 5, 3, 6 )$, subsecvenţa cea mai eficientă are costul $0.83$.\r\n\r\nh3. Rezolvare:\r\n\r\nProcedăm ca la \'problema $5$\':probleme-cu-secvente#problema-5 şi căutăm binar valoarea optimă. şirul va fi transformat în: $b[i] = c[i] - t[i] * X$, $i = 1..N$. Acum trebuie să mai rezolvăm subproblema care cere să determinăm o subsecvenţă de sumă maximă pentru care lungimea se află între $L$ şi $U$. Această subproblemă a fost soluţionată în \'problema anterioară\':probleme-cu-secvente#problema-9, unde s-a găsit un algoritm liniar. Astfel soluţia acestei probleme are complexitatea $O(N * log C)$.\r\n\r\nh2(#problema-11). Problema 11: \'XorMax\':problema/xormax\r\n\r\nbq. Se dă un şir de $N$ numere întregi nenegative. Să se aleagă o secvenţă a şirului, $(a{~i~}, a{~i+1~}, ..., a{~j~})$, astfel încât $a{~i~} xor a{~i+1~} xor ... xor a{~j~}$ să fie maxim. Restrictii: $1 &le; N &le; 100 000$ si $a{~i~} < 221$ cu $i = 1..N$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(1, 0, 5, 4, 2)$, secvenţa cu valoarea sumei _xor_ maximă este $(4, 2)$, cu suma $6$. \r\n\r\nh3. Rezolvare:\r\n\r\nSuma _xor_ a două numere este de fapt adunare binară fără transport, fapt care o face similară operaţiei _modulo_. Problema e asemănătoare cu cea a subsecvenţei de modul minim. Vom obţine toate sumele _xor_ parţiale şi pentru a vedea pentru $sum[i]$ perechea optimă cu care crează o sumă cât mai mare trebuie să găsim acea sumă $sum[j]$ astfel că fiecare bit al lui $sum[i]$ să fie diferit de fiecare bit al lui $sum[j]$, dacă acest lucru este posibil. Pentru a face această căutare cât mai eficientă, putem menţine sumele $sum[i]$ ca şiruri de caractere $0$ sau $1$ într-un _trie_ [5]. Structura de trie pentru cazul când alfabetul are dimensiunea $2$ este identică cu cea de heap. Această soluţie are complexitatea $O(N * log C)$.\r\n\r\nh2(#probleme-propuse). Probleme propuse\r\n\r\nPentru a vă însuşi mai bine tehnicile învăţate în acest articol, puteţi rezolva următoarele probleme:\r\n\r\n* \'Balans\':problema/balans\r\n* \'Struţi\':problema/struti\r\n* \'Deque\':problema/deque\r\n* \'Trie\':problema/trie\r\n* \'Maxq\':problema/maxq\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Dana Lica - \'_Arbori de intervale şi aplicaţii în geometria computaţională_\':arbori-de-intervale\r\n# Cosmin Negruşeri - \'_Căutări Ortogonale: Structuri de date şi aplicaţii_\':cautari-ortogonale\r\n# Takaoka T. - \'_Efficient Algorithms for the Maximum Subarray Problem by Distance Matrix Multiplication_\':http://www.cosc.canterbury.ac.nz/tad.takaoka/cats02.pdf\r\n# Kuan Yu Chen, Kun Mao Chao - \'_On the Range Maximum-Sum Segment Query_\':http://www.csie.ntu.edu.tw/~kmchao/papers/2007_DAM_RMSQ.pdf\r\n# Yaw Ling Liu, Tao Jiang, Kun Mao Chao - \'_Efficient Algorithms for Locating the Length-Constrained Heaviest Segments, with Applications to Biomolecolar Sequence Analysis_\':http://www.csie.ntu.edu.tw/~kmchao/seq2003/mslc.pdf\r\n# T. H. Cormen, C. E. Leiserson, R. R. Rivest - \'_Introducere in Algoritmi_\':http://zhuzeyuan.hp.infoseek.co.jp/ita/toc.htm\r\n',4297,'public',3553,NULL),('articole','Articole de informatica, algoritmi, structuri de date','2006-11-05 23:22:34','2009-01-12 09:47:26','h1. Articole\r\n\r\nPentru o pregatire completa, info{_arena_} iti propune o serie de articole care te vor ajuta in eforturile tale de a ajunge un bun programator. Vei lua contact cu diverse structuri de date, vei invata noi tehnici de programare cu care poti aborda problemele, vei afla cum sa scrii programe eficiente. Tot aici iti vom da idei de rezolvare pentru problemele de la diverse concursuri.\r\n\r\nIn plus, te incurajam sa fii alaturi de noi la imbogatirea continutului site-ului. \"Afla cum poti scrie si tu articole\":implica-te/scrie-articole.\r\n\r\ntable(layout).\r\n|_. Algoritmi si tehnici de programare |_. Solutii (oficiale) la diverse competitii |\r\n| ==include(page=\"articole/template-algoritmi\" display=\"none\")== \'_(vezi toate articolele din aceasta categorie)_\':articole/algoritmi |/3. ==include(page=\"articole/template-solutii\" display=\"none\")== \'_(vezi toate articolele din aceasta categorie)_\':articole/solutii |\r\n|_. Structuri de date |\r\n| ==include(page=\"articole/template-structuri-de-date\" display=\"none\")== \'_(vezi toate articolele din aceasta categorie)_\':articole/structuri-de-date |\r\n||_. Matematica |_. Limbaje de programare |\r\n| ==include(page=\"articole/template-matematica\" display=\"none\")== \'_(vezi toate articolele din aceasta categorie)_\':articole/matematica | ==include(page=\"articole/template-limbaje-de-programare\" display=\"none\")== \'_(vezi toate articolele din aceasta categorie)_\':articole/limbaje-de-programare |\r\n|_. Diverse |\r\n| ==include(page=\"articole/template-diverse\" display=\"none\")== \'_(vezi toate articolele din aceasta categorie)_\':articole/diverse |\r\n',2044,'protected',NULL,NULL),('trie-forest-based-sort','trie-forest-based-sort','2009-01-12 18:52:31','2009-01-28 20:04:18','h1. Sorting Big Numbers using Trie-Forest based sort\r\n\r\nh2. authors : Serban Lupulescu and Mircea Dima\r\n\r\n \r\n\r\nh3. The first idea is that if you have a string of length h, you can insert it in a trie of height h. We could maintain a list of tries,\r\n\r\nh3. trie H[N], where H[i] is a trie with height i so when we insert a string with length i, we insert it in H[i].\r\n\r\nh3. But what happens when we have, say 2 strings, one of length 3, and one with length 10^20^? We can\'t declare H[10^20^].\r\n\r\nh3. Instead we can keep an optimal binary search tree, where the keys are the length of the trie, and the additional information is the\r\n\r\nh3. trie itself.\r\n\r\nh3. Now if we have a string with length h we have 2 possibilities:\r\n\r\nh3. 1) if there is a trie with height h in the binary search tree, we insert the string in that trie\r\n\r\nh3. 2) if there isn\'t a trie with height h in the binary search tree, we create it, we insert the string in an empty trie, and then we insert the trie in\r\n\r\nh3. the binary search tree.\r\n\r\n\r\n== code(c) |\r\n\r\n// Sorting Big Numbers using Trie-Forest based sort indexed in a STL set (Red-Black Tree)\r\n// copyright(c) Serban Lupulescu & Mircea Dima\r\n// Time Complexity: O(n*max_len)\r\n// Faculty of Mathematics and Computer Science, University of Bucharest\r\n// :D\r\n#include <cstdio>\r\n#include <string>\r\n#include <set>\r\n#include <vector>\r\n#define N 10024\r\n\r\nusing namespace std;\r\n\r\ninline int length(char a[])\r\n{\r\n      int n=0;\r\n      while(a[n] >= \'0\' && a[n] <= \'9\') ++n;\r\n      return n;\r\n}\r\n\r\nstruct nod { int nr; nod *next[10];};\r\n\r\ntypedef nod* trie;\r\n\r\ninline void init(trie &n)\r\n{\r\n      n=new nod;\r\n      n->nr=0;\r\n      memset(n->next, 0, sizeof(n->next));\r\n}\r\n\r\nstruct cmp{\r\n      bool operator()(const pair<int, trie> &a, const pair<int, trie> &b)const\r\n      {\r\n            if(a.first < b.first) return 1;\r\n            return 0;\r\n      }\r\n};\r\n\r\ntypedef set<pair<int, trie> , cmp > Tree;\r\ntypedef set<pair<int, trie> , cmp >:: iterator Tree_it;\r\n\r\n \r\n\r\nTree R; // Red-Black binary search tree with key values = pointers\r\n\r\ninline trie find(int len) // find a trie in RBTREE\r\n{\r\n      Tree_it i= R.find(make_pair(len, (trie)0));\r\n      if(i == R.end()) return (trie) 0;\r\n      return i->second;\r\n}\r\n\r\ninline void insert(trie t, int len)\r\n{\r\n      R.insert(make_pair(len, t));\r\n}\r\n\r\ninline void erase(trie t, int len)\r\n{\r\n      R.erase(make_pair(len, t));\r\n}\r\n\r\ninline void insert(trie T,char a[], int n)\r\n{\r\n      for(int i=0; i < n; ++i)\r\n      {\r\n            if(T->next[a[i]] == 0) //if I don\'t have an edge, I create it\r\n            {\r\n                  T->next[a[i]]=new nod;\r\n                  T->next[a[i]]->nr=0;\r\n                  memset(T->next[a[i]]->next, 0, sizeof(T->next));\r\n            }\r\n            T=T->next[a[i]]; // go down the edge\r\n      }          \r\n      ++T->nr;\r\n}\r\n\r\nchar sol[N];\r\n\r\ninline void afis(trie T, int n)\r\n{\r\n      for(int i=0; i < 10; ++i)\r\n            if(T->next[i])\r\n            {\r\n                  sol[n]=i;\r\n                 \r\n                  if(T->next[i]->nr)//has a number ended here?\r\n                  {\r\n                        for(int j=1; j <= T->next[i]->nr; ++j)\r\n                        {\r\n                              int k;\r\n                              for(k=0; k <= n && sol[k] == 0; ++k);\r\n                             \r\n                              for(; k <= n; ++k) printf(\"%d\", sol[k]);\r\n                              printf(\"\\n\");\r\n                        }\r\n                  }    \r\n                  afis(T->next[i], n+1);\r\n            }\r\n}\r\n\r\nvoid read()\r\n{\r\n      freopen(\"sort.in\",\"r\",stdin);\r\n      freopen(\"sort.out\",\"w\",stdout);\r\n      while(!feof(stdin))\r\n      {\r\n            char a[N];\r\n            memset(a, 0, sizeof(a));\r\n            gets(a);\r\n            int n=length(a);\r\n            for(int i=0; i < n; ++i) a[i]-=\'0\';\r\n            trie t=find(n);\r\n           \r\n            if(t == 0)\r\n            {\r\n                  t= new nod;\r\n                  init(t);\r\n                  insert(t, n);\r\n            }\r\n           \r\n            insert(t, a, n);\r\n      }\r\n     \r\n      for(Tree_it i = R.begin(); i != R.end(); ++i) afis(i->second, 0);\r\n           \r\n}\r\n\r\nint main()\r\n{\r\n      read();    \r\n      return 0;\r\n}\r\n==',1204,'public',NULL,NULL),('planificare/sidebar','planificare/sidebar','2007-10-29 20:20:53','2009-10-25 11:49:02','(vmenu)* *{\'Planificare\':planificare}*\r\n* \'Algoritmiada 2010\':planificare/algoritmiada-2010\r\n** \'Promovare\':planificare/algoritmiada-2010/promovare\r\n** \'How-to\':planificare/algoritmiada-2010/how-to\r\n** \'Roluri\':planificare/algoritmiada-2010/roluri\r\n** \'Runda 1\':planificare/algoritmiada-2010/runda-1\r\n** \'Runda 2\':planificare/algoritmiada-2010/runda-2\r\n** \'Runda 3\':planificare/algoritmiada-2010/runda-3\r\n** \'Runda 4\':planificare/algoritmiada-2010/runda-4\r\n** \'Runda Finala\':planificare/algoritmiada-2010/runda-finala\r\n* \'Raspandeste vestea\':planificare/raspandeste-vestea\r\n* \'Cheltuieli\':planificare/cheltuieli\r\n* \'*Propuneri*\':propuneri\r\n* \'*Development*\':development\r\n* \'*Implica-te*\':implica-te\r\n\r\n',1792,'protected',NULL,NULL),('blog/infoarena_in_2008_articole','Infoarena in 2008: Articole','2009-01-17 07:45:36','2009-01-17 08:24:29','_S-au intamplat multe anul trecut cu *infoarena* si am vrut sa fac o trecere in revista ca sa vedem cum evolueaza siteul si comunitatea in timp. Astfel am contactat membrii echipei si i-am rugat sa imi spuna ce s-a intamplat nou in fiecare sectiune a siteului._\r\n\r\n_Modificarile primite au fost prea multe pentru a putea fi scrise in un singur post asa ca le-am impartit. In acest post voi discuta despre sectiunea de_ \'articole\':articole\r\n\r\nS-au adaugat 8 articole dintre care doua originale si sase transcrise:\r\n\r\n\'Treapurile\':treapuri sunt arbori de cautare echilibrati foarte usor de implementat. Dupa ce intelegeti invariantul de heap si invariantul de arbore de cautare, implementarea devine foarte naturala. Astfel veti putea sa ii implementati fara probleme in 20 de minute. Daca ii studiati nu veti mai avea nevoie sa tineti minte sau sa desenati pe foaie cazurile complicate de reechilibrare a arborilor AVL sau a arborilor rosu negrii.\r\n\r\nArticolul \'Tree Decompositions\':tree-decompositions scris de Marius Stroe prezinta doua tehnici utile in unele probleme in care apar querieuri pe arbori, tehnici care la vremea lor erau stiute in cercuri restranse si de care imi amintesc cu placere.\r\n\r\n\'Probleme de acoperire 1\':probleme-de-acoperire-1 si \'Probleme de acoperire 2\':probleme-de-acoperire-2 sunt doua articole ce le-am scris in Ginfo despre diverse probleme aparute la concursuri de info, multe dintre problemele respective fiind luate din carti de mate. Cand ma documentam pentru aceste articole am dat peste o problema care cerea determinarea numarului de posibilitati de acoperire cu dominouri a unui \'diamant aztec\':http://mathworld.wolfram.com/AztecDiamond.html . Am decis sa nu o adaug in articol pentru ca avea o rezolvare matematica care folosea numere complexe si permanentul unei matrici. In 2006 insa, la baraj s-a dat aceasta problema mascata ca un cuplaj si majoritatea concurentilor au \"bulanit\" problema, rezultatul fiind o formula destul de simpla 2^n(n+1)/2^. Sunt aproape sigur ca nimeni nu a gasit o \'demonstratie\':http://www.emis.de/journals/EJC/Volume_12/PDF/v12i1r18.pdf in timpul concursului pentru acea formula. Imi pare rau si acum ca nu am publicat-o in aceste articole pentru ca astfel problema nu ar fi fost propusa in concurs.\r\n\r\nArticolul \'Heapuri\':heapuri este preluat din cartea Psihologia concursurilor de programare a lui Catalin Francu, si este putin actualizat prin adaugarea de catre Silviu Ganceanu a sectiunii Alternative STL.\r\n\r\nArticolul \'Siruri de sufixe\':siruri-de-sufixe e rezultatul unei colaborari cu Adrian Vladu pentru Ginfo, el contine o structura de date misto folosita in prelucrarea sirurilor de caractere, implementarea lui Adrian ce este impresionant de scurta si mai multe probleme ca aplicatii.\r\n\r\n\'Coduri Gray\':coduri-gray discuta cinci probleme in rezolvarea carora se foloseste acest cod binar.\r\n\r\n\'Probleme cu numere lipsa si nu numai ...\':missing-numbers contine o serie de problemute interesante care datorita simplitatii si ingeniozitatii lor au ajuns probleme de interviu la companii mari ca Microsoft.\r\n\r\nArticolele noi si transcrierile de articole vechi au fost parte a eforturilor din sectiunea \'Implica-te\':implica-te a siteului. S-au facut eforturi mari pentru a imbunatati articolele si pe partea de aspect si pe partea de continut tehnic. Coordonatorul proiectului este ==user(user=\"stef2n\" type=\"tiny\")== iar cei doi useri care au facut cea mai mare parte a muncii anul trecut sunt  == user(user=\"marius\" type=\"tiny\") == si ==user(user=\"alecman\" type=\"tiny\")== . Este impresionant cum cativa oameni pun osul la treaba si fac majoritatea muncii pe tot parcursul anului. Ma asteptam ca munca sa fie mai uniform distribuita intre membrii comunitatii. Baietii merita din plin felicitati!\r\n\r\nAti vazut cum un om pasionat are un impact mare pe infoarena... Va asteptam cu proiecte in sectiunea \'Implica-te\':implica-te.',2044,'protected',3582,NULL),('blog/algoritmiada-runda2','Algoritmiada - analiza rundei 2','2009-01-21 10:34:36','2009-01-21 10:43:12','A doua runda a concursului Algoritmiada a avut loc pe 11 ianuarie, fiind primul concurs organizat de infoarena in 2009. Acesta s-a desfasurat fara nicio problema tehnica sau stiintifica, marcand un inceput in forta a echipei infoarena. Speram sa o tinem tot asa pe parcursul anului.\r\n\r\nMai intai de toate sa vedem cum arata statisticile rundei in comparatie cu cele din runda precedenta:\r\n\r\ntable. |_. &nbsp; |_. Runda 1 |_. Runda 2 |\r\n| Cati concurenti au trimis solutii | 223 | 157 |\r\n| Cati concurenti s-au inscris | 356 | 232 |\r\n| Surse trimise | 1245 | 894 |\r\n| Surse cu punctaj pozitiv | 685 | 408 |\r\n| Concurenti cu punctaj pozitiv | 162 | 113 |\r\n| Punctaj mediu al concurentilor care au trimis solutii | 75.09 | 43.85 |\r\n| Punctaj mediu al concurentilor cu punctaj strict mai mare ca 0 | 103.36 | 60.93 |\r\n\r\nIn primul rand observam ca au participat mai putini concurenti fata de prima runda. Este posibil ca inceputul de an sa-i fi prinsi nepregatiti pe unii participanti. Pentru a nu specula mai departe asupra motivelor, i-as ruga pe cei care nu au participat sa ne spuna ce s-a intamplat.\r\n\r\nIn al doilea rand observam ca problemele au fost ceva mai grele fata de runda precedenta. Aceasta a fost o decizie luata de comisia stiintifica pentru a va oferi probleme ceva mai interesante si pentru a va departaja.\r\n\r\nAcest lucru s-a vazut imediat si la varful clasamentului pentru mai toate grupele. Mai putin grupa 5-8, unde ==user(user=\"GavrilaVlad\")== si-a vazut de treaba si in runda aceasta, reusind din nou punctajul maxim. Felicitari Vlad pentru o performanta notabila. Pe podium au mai urcat ==user(user=\"radu_voroneanu\")== si ==user(user=\"taloibogdan\")== care s-au descurcat foarte bine reusind 250 si respectiv 220 de puncte.\r\n\r\nLa grupa 9-10, runda a fost adjudecata de ==user(user=\"raduzer\")== cu 150 de puncte. Imediat in spatele lui s-a clasat ==user(user=\"savim\")== (140 de puncte) si apoi doi concurenti cu 120 de puncte: ==user(user=\"jean\")== si ==user(user=\"andrei-alpha\")==.\r\n\r\nLa grupa 11-12 pe primul loc au terminat ==user(user=\"runnaway90\")== si ==user(user=\"cotofana\")== ambii cu 130 de puncte. La o diferenta de 5 puncte urmeaza ==user(user=\"stocarul\")== si ==user(user=\"Mishu91\")==.\r\n\r\nIn grupa de studenti ==user(user=\"Zeus\")== a iesit pe primul loc cu un punctaj frumos: 215 puncte. El a venit cu o solutie ingenioasa la problema \'jap\':problema/jap fiind singurul concurent care a reusit sa o rezolve. Pe locul 2 s-a clasat ==user(user=\"skipy\")== cu 200 de puncte fiind urmat de ==user(user=\"mugurelionut\")== cu 170 de puncte.\r\n\r\nIn urma acestei runde singurele nemultumiri au fost pe tema dificultatii problemelor. Judecand dupa punctaje, seturile de la 9-10 si 11-12 au fost un pic peste puterile concurentilor. In grupa studenti distributia punctajelor la varf este una buna, pe cand in grupa 5-8 este perfecta: cei mici merita motivati prin punctaje mai mari si probleme mai abordabile.\r\n\r\nInca sunt relativ multi utilizatori care au punctaje nule (~28%). Pe acestia ii sfatuiesc sa persevereze si sa incerce sa impuste punctele ce pot fi obtinute cu solutii _brute force_. Tehnica e simpla: \r\n\r\n==code(cpp) |\r\nif (N <= BRUTE_FORCE_LIMIT) {\r\n    do_brute_force();\r\n} else {\r\n    do_something_else();\r\n}\r\n==\r\n\r\nTragand linia, organizarea a fost buna. Comisia stiintifica a facut o treaba temeinica, ca de obicei, singurele aspecte care trebuie reglate in viitor fiind dificultatea problemelor si combaterea punctajelor nule. In aceasta runda, comisia ne-a surprins in mod placut cu publicarea solutiilor mult mai prompt fata de runda trecuta.\r\n\r\nInainte de runda 3, as vrea sa va aduc aminte ca aceasta este ultima sansa sa va calificati in finala. Cand va fi anuntata data desfasurarii, marcati-o in calendar si pregatiti-va sa dati tot ce aveti mai bun pentru a prinde un loc de finalist. Daca ne uitam la \'clasamentele generale\':algoritmiada-2009/clasament sunt foarte multi concurenti care au sanse sa se califice. Spre exemplu, in \'grupa 5-8\':algoritmiada-2009/clasament/5-8 diferenta dintre locul 7 si locul 60 este de numai 100 de puncte, foarte usor recupelabila in urma unei performante bune in runda 3. O situatie similara avem si in \'grupa 9-10\':algoritmiada-2009/clasament/9-10. Cum punctajele primilor 10 concurenti sunt la mai toate grupele sub 300, si un concurent cu 0 puncte dupa primele 2 runde are sanse de calificare la finala.\r\n\r\nIn vederea selectarii finalistilor dupa runda 3, va recomandam sa va completati/updatati profilul cu date despre clasa/anul in care sunteti precum si informatii despre institutia de invatamant. De fapt, am fi bucurosi daca toti utilizatorii si-ar completa profilul, aceasta fiind una din modalitatile prin care putem sa ne cunoastem intre noi. Exemple de profile completate puteti gasi la mai toti membrii echipei infoarena.\r\n\r\nInchei prin a va ura putini gandaci si multa inspiratie in runda 3! Fie ca cei mai buni sa castige!',15,'protected',3597,NULL),('introducere-in-asamblare','Introducere in asamblare','2005-08-15 00:00:00','2009-02-19 23:52:58','h1. Introducere in asamblare\r\n\r\n(Categoria _Limbaje de programare_, Autor _Cristian Botau_)\r\n\r\n(toc){width: 35em}*{text-align:center} *Conţinut:*\r\n* \'Limbajul de asamblare: avantaje si dezavantaje in folosirea lui\':introducere-in-asamblare#limbajul-de-asamblare\r\n** \'Avantaje ale limbajului de asamblare\':introducere-in-asamblare#avantaje-limbaj-asamblare\r\n** \'Dezavantaje ale limbajului de asamblare\':introducere-in-asamblare#dezavantaje-limbaj-asamblare\r\n* \'Notiuni de baza ale limbajului de asamblare\':introducere-in-asamblare#notiuni-de-baza\r\n** \'Registrii\':introducere-in-asamblare#registrii\r\n*** \'Registrii de uz general\':introducere-in-asamblare#registrii-de-uz-general\r\n*** \'Registrii de segment si index\':introducere-in-asamblare#registrii-de-segment-si-index\r\n*** \'Registrii speciali\':introducere-in-asamblare#registrii-speciali\r\n*** \'Flagurile microprocesorului\':introducere-in-asamblare#flagurile-microprocesorului\r\n** \'Instructiunile de baza ale microprocesorului 8086\':introducere-in-asamblare#instructiuni-de-baza-8086\r\n*** \'Instructiunea MOV\':introducere-in-asamblare#instructiune-MOV\r\n*** \'Instructiuni aritmetice. Instructiunile ADD, SUB, INC, DEC\':introducere-in-asamblare#instructiuni-aritmetice\r\n*** \'Instructiuni pe biti. Instructiunile AND, TEST, OR, XOR, NOT\':introducere-in-asamblare#instructiuni-pe-biti\r\n*** \'Instructiunile PUSH/POP\':introducere-in-asamblare#instructiuni-PUSH-POP\r\n*** \'Instructiunea CMP\':introducere-in-asamblare#instructiune-CMP\r\n*** \'Jump-urile neconditionate (JMP) si jump-urile conditionate (JE, JNE, JB, JBE, JA, JAE, JZ, JNZ)\':introducere-in-asamblare#jumpuri\r\n*** \'Instructiunea LOOP\':introducere-in-asamblare#instructiune-loop\r\n*** \'Instructiunea INT\':introducere-in-asamblare#instructiune-INT\r\n* \'Transcrierea unor instructiuni C/PASCAL in asamblare\':introducere-in-asamblare#instructiuni-CPascal-in-asamblare\r\n** \'IF cond THEN instr\':introducere-in-asamblare#if-then\r\n** \'IF cond THEN instr1 ELSE instr2\':introducere-in-asamblare#if-then-else\r\n** \'DO { inst } WHILE\':introducere-in-asamblare#do-while\r\n* \'Program demonstrativ\':introducere-in-asamblare#program-demonstrativ\r\n* \'Linkuri\':introducere-in-asamblare#linkuri\r\n* \'Doua cuvinte conclusive...\':introducere-in-asamblare#concluzie\r\n\r\nAcest articol prezinta un limbaj mai putin folosit : limbajul de asamblare. Este folosit de cele mai multe ori pentru marirea vitezei de rulare a programelor. In prima sectiune sunt prezentate cateva avantaje / dezavantaje in folosirea acestui limbaj, iar ulterior sunt definite notiunile elementare ce trebuie stiute inainte de a trece la tratarea limbajului propriu-zis. De asemenea, sunt prezentate cateva intructiuni si transcrieri ale unor structuri din C/Pascal in limbaj de asamblare. In final sunt comparati timpii de executie intre varianta pascal si varianta assembler ale unei proceduri de {$Bubble Sort$}.\r\n\r\nh2(#limbajul-de-asamblare). Limbajul de asamblare : avantaje si dezavantaje in folosirea lui\r\n\r\nDesi este unul dintre cele mai vechi limbaje de programare, limbajul de asamblare este incorporat si in cele mai noi compilatoare cum ar fi Visual C++ si Delphi. Codul de asamblare este foarte apropiat de codul executabil al programelor, asamblorul avand rolul de a codifica instructiunile din limbaj de asamblare in cod masina.\r\n\r\nIn prezent, limbajul de asamblare este din ce in ce mai putin folosit in scrierea programelor, deoarece compilatoarele de ultima generatie au functiile cele mai folosite de programatori deja scrise si optimizate in limbaj de asamblare (gen memmove, memset / fillchar, etc.) incluse in unit-uri si biblioteci. Bineinteles, daca se doreste atingerea unor timpi de executie foarte mici, folosirea limbajului de asamblare este preferabila (cand avem algoritmul de complexitate optima).\r\n\r\nh3(#avantaje-limbaj-asamblare). Avantaje ale limbajului de asamblare\r\n\r\n* Viteza foarte mare de executie a programelor (unele programe scrise si optimizate in asamblare au viteza de executie pana la 5-10 de ori mai mare decat cele scrise in C sau Pascal);\r\n* Marimea codului executabil este foarte mica;\r\n* Ajuta utilizatorul sa inteleaga mai bine cum functioneaza microprocesorul si sa scrie programe eficiente si in High Level Languages.\r\n\r\nh3(#dezavantaje-limbaj-asamblare). Dezavantaje ale limbajului de asamblare\r\n\r\n* nu este portabil; un program scris pentru calculatoare IBM PC nu va rula pe un Apple Macintosh (difera unele instructiuni);\r\n* un program in asamblare este mai greu de scris si ia mai mult timp decat un program scris in Pascal sau C;\r\n* un program scris in asamblare este mai greu de depanat;\r\n\r\nMajoritatea compilatoarelor din prezent permit programatorului sa scrie anumite parti de cod sau subprograme in asamblare, astfel incat programatorul sa poata scrie in asamblare doar partea din program care se executa de cele mai multe ori, programul ruland astfel mult mai rapid. Sunt si compilatoare dedicate exclusiv limbajului de asamblare, cum ar fi TASM - Turbo Assembler (il gasiti in directorul BP/Bin), MASM - Microsoft Assembler, etc.\r\n\r\nPentru a scrie o secventa de limbaj de asamblare intr-un program $C$ se foloseste cuvantul rezervat $asm$ :\r\n\r\n== code(cpp) |asm { instructiuni in asamblare };\r\n==\r\n\r\niar in pascal :\r\n\r\n== code(pas) |asm\r\n    cod asamblare\r\nend.\r\n==\r\n\r\nh2(#notiuni-de-baza). Notiuni de baza ale limbajului de asamblare\r\n\r\nh3(#registrii). Registrii\r\n\r\nLimbajul de asamblare este foarte apropiat de codul executabil, deci pentru ca programatorul sa fie capabil sa scrie codul in asamblare trebuie sa cunoasca modul in care functioneaza microprocesorul si modul in care acesta executa instructiunile.\r\n\r\nToate operatiile aritmetice/logice/acces la memorie se fac prin intermediul registrilor. Registrii microprocesorului sunt asemanatori variabilelor (pot fi initializati cu anumite valori, se pot efectua operatii asupra lor, pot fi accesati (cititi/modificati)).\r\nRegistrii microprocesorului sunt clasificati in mai multe categorii :\r\n\r\n* registri de uz general : {$eax$}, {$ebx$}, {$ecx$}, {$edx$} si subregistrii lor;\r\n* registri segment : {$cs$} (code segment), {$ds$} (data segment), {$es$} (extra segment), {$ss$} (stack segment) - sunt folositi pentru adresarea memoriei in cazul modelului de memorie segmentat\r\n* registrii index : {$esi$}, $edi$ (source index, destination index);\r\n* registri speciali : {$ebp$}, {$esp$}, {$ip$};\r\n\r\nRegistrii de uz general sunt folositi in executia operatiilor aritmetice si logice. Registrii de segment si cei index sunt folositi in adresarea memoriei, iar cei speciali sunt folositi de microprocesor si S.O. pentru rularea programelor.\r\n\r\nh4(#registrii-de-uz-general). Registrii de uz general\r\n\r\nAcestia sunt :\r\n\r\n* $eax$ - numit si \"accumulator\" - acesta este cel mai folosit in executarea operatiilor aritmetice (adunare, scadere, inmultire, impartire);\r\n* $ebx$ - numit si \"base\" - acesta registru este folosit pentru adresarea indirecta a memoriei;\r\n* $ecx$ - numit si \"count\" - acest registru este folosit mai ales in cadrul \"buclelor\" (in instructiunile repetitive : for/ while do/ do while/ repeat until);\r\n* $edx$ - numit si \"data\" - retine anumite variabile, si este folosit impreuna cu $eax$ in executarea operatiei \"div\", impartire intreaga (avand rolul de a retine restul impartirii).\r\n\r\nDupa cum ati observat, fiecare registru general are o functie specifica, insa oricare din ei pot fi folositi si la operatii aritmetice/logice, adresare memorie sau ca si variabile.\r\n\r\nRegistrii precedati de prefixul \"{$e$}\" sunt pe $32$ de biti, deci pot fi tratati ca si variabile {$unsigned long$}/{$signed long$} ({$doubleword$}). Acestia pot fi folositi si ca registri pe $16$ biti ({$word$}) sau pe $8$ biti ({$byte$}) prin intermediul \"subregistrilor\" : {$ax$}, {$bx$}, {$cx$}, $dx$ (reprezinta word-ul nesemnificativ = cel din dreapta)., {$ah$}, {$bh$}, {$ch$}, $dh$ (byte-ul cel mai semnificativ al {$ax$}, {$bx$}, {$cx$}, {$dx$}), {$al$}, {$bl$}, {$cl$}, {$dl$}(registrii pe 8 biti).\r\n\r\nh4(#registrii-de-segment-si-index). Registrii de segment si index\r\n\r\nAcesti registri sunt folositi la adresarea memoriei.\r\nDe exemplu\r\nAvem variabila {$void *x;$}({$x : pointer$} in pascal);\r\npentru modelul de memorie segmentata, in adresarea memoriei adresate de $x$ se folosesc intructiunile (vezi \"Intructiunile de baza ale unui microprocesor 8086\") :\r\n\r\n== code(cpp) |// es:[di] va accesa adresa pointata de x;\r\nles di, x\r\n// se copiaza in ax primul word\r\n// de la adresa es:[di]\r\nmov ax, es:[di]\r\n// se copiaza in al cel de-al 3-lea byte\r\n// de la adresa es:[di]\r\nmov al, es:[di+2]\r\n==\r\n\r\nParantezele drepte se refera la zona de memorie adresata de registru.\r\nExemplu :\r\n\r\n\"{$[esi]$}\" se refera la valoarea aflata la adresa de memorie cu offset-ul esi, iar \"{$esi$}\" se refera la valoarea stocata in registrul esi;\r\n\r\ndaca $esi = 100$ atunci [{$esi$}] va reprezenta valoarea care se afla la adresa cu offset-ul {$100$}, iar esi va reprezenta valoarea {$100$}.\r\n\r\nVa sfatuiesc sa NU incercati sa modificati urmatorii registri : $cs$ (care contine segmentul la care se afla incarcat codul executabilului, $ss$ contine segmentul de memorie in care se afla stiva sistemului).\r\n\r\nh4(#registrii-speciali). Registrii speciali\r\n\r\nSunt folositi foarte rar in scrierea efectiva a programelor, deci nu veti accesa prea des acesti registri.De exemplu, $ip$ (instruction pointer) care retine adresa (de fapt offset-ul) la care se afla instructiunea care urmeaza sa fie executata.\r\n\r\nh4(#flagurile-microprocesorului). Flagurile microprocesorului\r\n\r\nFlag-urile microprocesorului sunt asemanatoare unor variabile boolene. Cu ajutorul lor putem afla rezultatul unei comparatii sau daca o operatie a produs \"overflow\", etc. Aceste flag-uri nu pot fi accesate direct ca si registrii, ci testarea daca un flag este activat se face prin intermediul \"jump\"-urilor conditionate.(vezi instructiunea {$cmp$}).\r\n\r\nExemplu :\r\nFie {$ax = 1$}. Decrementarea lui $ax$ cu $1$ va duce la activarea flagului numit Zero-Flag.(rezultatul operatiei a fost {$0$}).\r\nFie {$ax = 65535$} ({$0xFFFF$}). Incrementarea lui $ax$ cu $2$ va duce la setarea flagului numit Overflow-Flag (rezultatul operatiei nu \"incape\" in $16$ biti);\r\n\r\nh3(#instructiuni-de-baza-8086). Instructiunile de baza ale microprocesorului 8086\r\n\r\nSunt folosite urmatoarele prescurtari :\r\n\r\n* {$reg8$}/ {$reg16$}/ {$reg32$} - se refera la registri pe {$8$}/{$16$}/{$32$} biti;\r\n* {$imm8$}/ {$imm16$}/ {$imm32$} - se refera la valori imediate (constante);\r\n* {$mem8$}/ {$mem16$}/ {$mem32$} - zona memorie de memorie sau variabile pe {$8$}/{$16$}/{$32$} biti;\r\n\r\nh4(#instructiune-MOV). Instructiunea MOV\r\n\r\n_Sintaxa_:\r\n\r\n* $mov dest, source$ // echivalenta cu dest = source\r\n\r\n_Variante_:\r\n\r\n* $mov reg8/16/32, mem8/16/32$\r\n* $mov reg8/16/32, reg8/16/32$\r\n* $mov mem8/16/32, reg8/16/32$\r\n* $mov reg8/16/32, imm8/16/32$\r\n* $mov mem8/16/32, imm8/16/32$\r\n\r\n_Descriere_:\r\n\r\nInstructiunea copiaza o valoare dintr-o locatie in alta locatie. Aceasta locatie poate fi zona de memorie, variabila, registru. De retinut este ca nu exista variante ale instructiunii care copiaza direct dintr-o zona de memorie in alta.\r\n\r\n_Flaguri afectate_:\r\n\r\nInstructiunea mov nu modifica nici un flag.\r\n\r\n_Restrictii_:\r\n\r\nAmbii operanzi trebuie sa aiba aceeasi marime. De exemplu pentru ultima varianta a instructiunii mov trebuie specificata marimea zonei de memorie. Instructiunea \"mov [bx], 0\" nu este corecta deoarece compilatorul nu stie ce vrea sa faca instructiunea: sa copieze valoarea 0 in byte-ul, in word-ul sau in doubleword-ul de la adresa bx. Astfel variantele corecte sunt:\r\n\r\n== code(cpp) |mov byte ptr [bx], 0\r\nmov word ptr [bx], 0\r\nmov dword ptr [bx], 0\r\n==\r\n\r\n_Exemplu_:\r\n\r\n== code(cpp) |mov ax, 3 // ax = 3\r\nmov bx, ax // bx = ax\r\n==\r\n\r\nh4(#instructiuni-aritmetice). Instructiuni aritmetice. Instructiunile ADD, SUB, INC, DEC\r\n\r\n_Sintaxa_:\r\n\r\n* $add dest, source$ // echivalenta cu dest+=source\r\n* $sub dest, source$ // echivalenta cu dest-=source\r\n* $inc dest$ // echivalenta cu dest++\r\n* $dec dest$ // echivalenta cu dest--\r\n\r\n_Variante_:\r\n\r\n* $add(sub) reg8/16/32, mem8/16/32$\r\n* $add(sub) reg8/16/32, reg8/16/32$\r\n* $add(sub) mem8/16/32, reg8/16/32$\r\n* $add(sub) reg8/16/32, imm8/16/32$\r\n* $add(sub) mem8/16/32, imm8/16/32$\r\n\r\n_Descriere_:\r\n\r\nInstructiunea \"{$add$}\" este folosita pentru a aduna doua valori, \"{$sub$}\" pentru a scadea o valoare din alta, \"{$inc$}\" - incrementarea unei variabile, \"{$dec$}\" - decrementarea unei variabile (registru/memorie).\r\n\r\n_Flaguri afectate_:\r\n\r\n* $carry flag$ - pentru \"signed overflow\"\r\n* $overflow flag$ - pentru overflow\r\n* $sign flag$ - activat daca rezultatul este negativ\r\n* $zero flag$ - activat daca rezultatul operatiei a fost 0\r\n* $parity flag$ - este setat in functie de paritatea rezultatului\r\n\r\n_Restrictii_:\r\n\r\nDestinatia trebuie sa aiba aceeasi marime ca si sursa.\r\n\r\n_Exemplu_:\r\n\r\n== code(cpp) |mov ax, 3 // ax = 3\r\nadd bx, ax // bx = ax+3\r\n==\r\n\r\nh4(#instructiuni-pe-biti). Instructiuni pe biti. Instructiunile AND, TEST, OR, XOR, NOT\r\n\r\n_Sintaxa_:\r\n\r\n* $and dest, source$ // echivalenta cu dest&=source\r\n* $test dest, source$ // dest & source\r\n* $or dest, source$ // echivalenta cu dest|=source\r\n* $xor dest, source$ // echivalenta cu dest^=source\r\n* $not dest$ // ~dest\r\n\r\n_Variante_:\r\n\r\nPentru \"{$and$}\", \"{$or$}\", \"{$test$}\", \"{$xor$}\" sunt ca si cele de la \"{$add$}\". Pentru \"{$not$}\" avem doua variante :\r\n\r\n* $not reg8/16/32$\r\n* $not mem$\r\n\r\n_Descriere_:\r\n\r\nExecuta operatiile pe biti corespunzatoare. Instructiunea test (non-destructive and) este asemanatoare lui and, dar nu afecteaza rezultatul ci doar flagurile.\r\n\r\n_Flaguri afectate_:\r\n\r\nInstructiunea \"{$not$}\" nu afecteaza nici un flag.\r\nFlagurile afectate de celalalte instructiuni sunt :\r\n\r\n* {$carry$}, $overflow$ - le dezactiveaza\r\n* $sign flag$ - este copiat bitul cel mai semnificativ din rezultat (semnul rezultatului, de fapt)\r\n* $zero flag$ - activat daca rezultatul operatiei a fost 0\r\n* $parity flag$ - este setat in functie de paritatea rezultatului\r\n\r\n_Restrictii_:\r\n\r\nDestinatia trebuie sa aiba aceeasi marime ca si sursa.\r\nInstructinile $OR/XOR/INC/DEC$ modifica flag-urile microprocesorului: {$Carry$}(numai {$ADD/SUB$}), {$Overflow$}, {$Zero$}, {$Parity$}.\r\n\r\n_Exemplu_:\r\n\r\n== code(cpp) |mov ax, 5 // ax = 3\r\ntest ax, 1 // daca (ax & 1)\r\njz @skip // daca ax este nu este impar sari la @skip\r\n// executa instructiuni\r\n@skip\r\nand bx, FFFEh // bx = bx & 0xFFFE (se sterge bitul cel mai nesemnificativ)\r\n==\r\n\r\nh4(#instructiuni-PUSH-POP). Instructiunile PUSH/POP\r\n\r\n_Descriere_:\r\n\r\nAceste instructiuni sunt folosite pentru accesarea stivei sistemului. Instructiunea PUSH pune pe stiva sistemului o valoare, iar instructiunea POP extrage valoarea din varful stivei.\r\n\r\n_Sintaxa_:\r\n\r\n* $push val$\r\n* $pop val$\r\n\r\n_Variante_:\r\n\r\n* $push reg8/16/32$\r\n* $pop reg8/16/32$\r\n\r\n_Exemplu_:\r\n\r\n== code(cpp) |@lp:\r\npush cx // salvam valoarea cx\r\n... // prelucreaza datele, se poate modifica cx\r\npop cx // scoate de pe stiva valoarea cx\r\ndec cx\r\njnz @lp // daca (cx != 0) atunci sari inapoi la @lp\r\n==\r\n\r\nh4(#instructiune-CMP). Instructiunea CMP\r\n\r\n_Descriere_:\r\n\r\nCompara doua valori si seteaza flag-urile microprocesorului cu rezultatele compararii. De cele mai multe ori este folosita in combinatie cu jump-urile (vezi mai jos).\r\n\r\n_Sintaxa_:\r\n\r\n* $cmp val1, val2$\r\n\r\n_Variante_:\r\n\r\n* $cmp reg8/16/32, reg8/16/32$\r\n* $cmp reg8/16/32, imm8/16/32$\r\n* $cmp mem8/16/32, reg8/16/32$\r\n* $cmp mem8/16/32, imm8/16/32$\r\n\r\nh4(#jumpuri). Jump-urile neconditionate (JMP) si jump-urile conditionate (JE, JNE, JB, JBE, JA, JAE, JZ, JNZ)\r\n\r\nAceste instructiuni sunt folosite pentru generarea instructiunilor If /while do /do while /repeat /for.Sunt asemanatoare instructiunii goto din C/Pascal.\r\n\r\n_Sintaxa_:\r\n\r\n$instructiune label$\r\n\r\n* $JE$ * \"sare\" cu executia programului la label daca flag-ul equality este setat;\r\n* $JNE$ * \"sare\" cu executia programului la label daca flag-ul equality nu este setat;\r\n* $JB$ * \"sare\" cu executia programului la label daca flag-ul below este setat;\r\n* $JBE$ * \"sare\" cu executia programului la label daca flag-ul below sau flagul equality este setat;\r\n* $JA$ * \"sare\" cu executia programului la label daca flag-ul below nu este setat;\r\n* $JAE$ * \"sare\" cu executia programului la label daca flag-ul equality este setat sau flag-ul below nu este setat;\r\n* $JZ$ * \"sare\" cu executia programului la label daca flag-ul zero este setat;\r\n* $JNZ$ * \"sare\" cu executia programului la label daca flag-ul zero nu este setat;\r\n* $JMP$ * \"sare\" cu executia programului la label;\r\n\r\n_Exemplu_:\r\n\r\n== code(cpp) |mov ax, 1\r\n@loop :\r\n    instr1\r\n    instr2\r\n    *\r\n    inc ax\r\n    // compara ax cu valoarea 10 si seteaza flagurile\r\n    cmp ax, 10\r\n    // daca ax != 10 sari inapoi la @loop\r\n\r\njne @loop\r\n\r\n== code(cpp) |instr1\r\njmp @label1\r\n    instr2\r\n    instr3\r\n@label1 :\r\n==\r\n\r\nIn ultimul exemplu instr2 si instr3 nu vor fi executate deoarece inaintea lor se afla instructiunea jump care face ca programul sa sara cu executia la instructiunea imediat urmatoare etichetei \"label1\".\r\n\r\nh4(#instructiune-loop). Instructiunea LOOP\r\n\r\nInstructiunea \"loop\" este folosita de obicei in transcrierea for-urilor si a buclelor.\r\n\r\n_Sintaxa_:\r\n\r\n* $loop label$\r\n\r\n_Descriere_:\r\n\r\nEchivalenta cu :\r\n\r\n== code(cpp) |dec ecx (sau dec cx)\r\njz label\r\n==\r\n\r\nh4(#instructiune-INT). Instructiunea INT\r\n\r\n_Descriere_:\r\n\r\nInstructiunea INT apealeaza o intrerupere.\r\n\r\n_Sintaxa_:\r\n\r\n* $INT nr_intrerupere$ (un numar cuprins intre 0 si 255);\r\n\r\nIntreruperile opresc programul din rulare, executa un anumit cod si apoi permit continuarea rularii programului. Cu ajutorul apelului intreruperilor aplicatia poate sa comunice cu sistemul de operare, si cu unele componente hardware ale calculatorului (mouse-ul, tastatura, imprimanta, etc). Fiecare intrerupere are asociat un numar.\r\n\r\n_Exemple_:\r\n\r\n* $0x9$ : intreruperea pentru tastatura;\r\n* $0x10$ : intreruperea care ofera serviciile BIOS pentru accesul la placa video;\r\n* $0x21$ : intreruperea sistemului de operare DOS;\r\n* $0x33$ : intreruperea pentru mouse;\r\n\r\nIn DOS pentru initializarea mouse-ului se va apela functia numarul $0$ a intreruperii $0x33$ :\r\n\r\n== code(cpp) |asm\r\n{\r\n    mov ax, 0\r\n    // seteaza registrul ax cu valoarea 0 pentru ca\r\n    // driverul ce gestioneaza intreruperea 0x33\r\n    //sa stie ca trebuie sa initializeze mouse-ul\r\n    int 0x33\r\n}\r\n==\r\n\r\nPentru afisarea mouse-ului :\r\n\r\n== code(cpp) |asm\r\n{\r\n    mov ax, 1\r\n    int 0x33\r\n}\r\n==\r\n\r\nPentru ascunderea cursorului de la mouse :\r\n\r\n== code(cpp) |asm\r\n{\r\n    mov ax, 2\r\n    int 0x33;\r\n}\r\n==\r\n\r\nh2(#instructiuni-CPascal-in-asamblare). Transcrierea unor instructiuni C/PASCAL in asamblare\r\n\r\nh3(#if-then). IF cond THEN instr\r\n\r\nExemplu : \r\n\r\n== code(cpp) |if (a==5) b=a; // a, b : integer\r\n==\r\n\r\n== code(cpp) |mov ax, a\r\ncmp ax, 5\r\n// ne intrebam daca !cond\r\njnz @skip_if\r\nmov b, ax\r\n@skip_if :\r\n==\r\n\r\nh3(#if-then-else). IF cond THEN instr1 ELSE instr2\r\n\r\nExemplu: \r\n\r\n== code(cpp) |if (a==b) a-=b; else b-=a;\r\n==\r\n\r\nTranscrierea in asamblare :\r\n\r\n== code(cpp) |mov ax, a\r\nmov bx, b\r\n// compara ax cu bx si seteaza flag-urile\r\ncmp ax, bx\r\nje @if_then\r\n// if (ax == bx) sari la @if_then\r\nsub b, ax\r\njmp @end_if :\r\n@if_then :\r\nsub a, bx\r\n@end_if :\r\n==\r\n\r\n\r\nh3(#do-while). DO { inst } WHILE\r\n\r\nExemplu :\r\n\r\n== code(cpp) |int i, a, n;\r\ni = 0;\r\na = 0;\r\ndo\r\n{\r\n    i++;\r\n    a+=i;\r\n} while (i<=n);\r\n==\r\n\r\nCodul in asamblare :\r\n\r\n== code(cpp) |// cx = 0, instructiunea xor cx, cx este\r\n// mai rapida decat mov cx, 0\r\nxor cx, cx\r\nxor ax, ax\r\nmov bx, n\r\n@while :\r\n    inc cx\r\n    add ax, cx\r\n    cmp cx, bx\r\n    jne @while\r\nmov a, ax\r\nmov I, cx\r\n==\r\n\r\nSau folosind instructiunea loop (pornim invers) :\r\n\r\n== code(cpp) |mov cx, n\r\n@while:\r\n    add ax, cx\r\nloop @while\r\n==\r\n\r\nIn codul de mai sus (prima varianta) puteti observa cateva mici optimizari : retinerea variabilelor in registri (accesul la registri este mult mai rapid decat la memorie), inlocuirea instructiunii {$mov reg, 0$ cu {$xor reg, reg$}. Varianta \"xor\" este mai rapida (desi $mov$ si $xor$ \"teoretic\" au tot atatea ceasuri de procesor) deoarece instructiunea $mov reg, 0$ transcrisa in cod masina este mai \"lunga\" (are cu $2-4$ bytes mai mult decat {$xor reg, reg$}). Aceeasi regula se aplica si in cazul \"{$or reg, reg$}\" in testarea daca valoarea unui registru este egala cu {$0$}, intrucat instructiunea \"{$or$}\" modifica flagurile procesorului ({$ZeroFlag$}). O alta optimizare este folosirea registrului $ax$ pentru calcule (in majoritatea cazurilor instructiunile care folosesc registrul $(e)ax$ sunt mai rapide).\r\n\r\nh2(#program-demonstrativ). Program demonstrativ\r\n\r\nExemplu de functie in realizata in C/Asamblare (compilator folosit BC++ 3.1):\r\n\r\n== code(cpp) |// BSort.CPP\r\n#include <stdio.h>\r\n#include <conio.h>\r\n\r\nint a[20], n;\r\n\r\nvoid bsort()\r\n{\r\n	asm {\r\n		mov di,seg a\r\n		mov es,di\r\n		mov di,offset a\r\n		// es:[di] inceputul vectorului\r\n		// es - adresa segment\r\n		// di - adresa offset\r\n	};\r\n\r\ndo_while_not_ok :\r\n	asm {\r\n		// ok = 1;\r\n		mov dx, 1\r\n		// cx = n;\r\n		mov cx, n\r\n		// cx = n-1\r\n\r\n		dec cx\r\n		// ax = a[0]\r\n		mov ax, es:[di]\r\n		// punem di pe stiva\r\n		push di\r\n	}\r\ninner_for :\r\n	asm {\r\n		// bx = a[i-1]\r\n		mov bx, ax\r\n		// ne mutam pe noua pozitie in vector\r\n		add di, 2\r\n		// ax = a[i]\r\n		mov ax, es:[di]\r\n		// comparam ax cu bx (a[i-1] cu a[i])\r\n		cmp bx, ax\r\n		// if (a[i-1] <= a[i]) don\'t swap\r\n		jbe if_not\r\n		// interschimbam a[i-1] cu a[i]\r\n		xchg bx, ax\r\n		// le scriem in memorie\r\n		mov es:[di], ax\r\n		mov es:[di-2], bx\r\n		// ok = 0\r\n		xor dx, dx\r\n	}\r\nif_not :\r\n	asm {\r\n		// cx--;\r\n		dec cx\r\n		jnz inner_for\r\n		// daca cx != 0 atunci continuam for-ul\r\n		pop di\r\n		// compara dx cu 0\r\n		// (mai rapid decat cmp dx, 0)\r\n		or dx, dx\r\n		// if (ok) executam inca odata while-ul\r\n		jz do_while_not_ok\r\n	}\r\n}\r\n\r\nvoid citire()\r\n{\r\n	printf(\"Numarul de elemente : \");\r\n	scanf(\"%d\", &n);\r\n	for (int i=0; i<n; i++)\r\n	{\r\n		printf(\"a[%d] = \", i);\r\n		scanf(\"%d\", &a[i]);\r\n	}\r\n}\r\n\r\nvoid afis()\r\n{\r\n	for (int i=0; i<n; i++)\r\n		printf(\"%d \", a[i]);\r\n}\r\n\r\nint main()\r\n{\r\n	citire();\r\n	bsort();\r\n	afis();\r\n	return 0;\r\n}\r\n==\r\n\r\nVarianta Pascal + Asm (compilata cu BP 7.0):\r\n\r\n== code(pas) |program b_sort;\r\n\r\nconst   max_N = 1000;\r\n        n_tests = 100;\r\n\r\nvar N : Integer;\r\n    a, b : array [1..max_N] of Integer;\r\n\r\nprocedure citire;\r\nvar f : Text;\r\n    i : Integer;\r\nbegin\r\n    Assign(f, \'bsort.in\'); Reset(f);\r\n    readln(f, N);\r\n    for i := 1 to N do\r\n        read(f, b[i]);\r\n    Close(f)\r\nend;\r\n\r\nprocedure flip;\r\nvar i : Integer;\r\nbegin\r\n    for i:=1 to N do\r\n        a[i] := b[i];\r\nend;\r\n\r\nvar p : pointer;\r\n\r\nprocedure bsort; assembler;\r\nasm\r\n{ les <=> es = seg(p), di = offset(p) }\r\n    les di, p\r\n    @do_while_not_ok :\r\n        mov dx, 1\r\n        mov cx, N\r\n        dec cx\r\n        mov ax, es:[di]\r\n        push di\r\n        @inner_for :\r\n            mov bx, ax\r\n            add di, 2\r\n            mov ax, es:[di]\r\n            cmp bx, ax\r\n            jbe @if_not\r\n            xchg bx, ax\r\n            mov es:[di], ax\r\n            mov es:[di-2], bx\r\n            xor dx, dx\r\n            @if_not :\r\n                dec cx\r\n                jnz @inner_for\r\n        pop di\r\n        or dx, dx\r\n    jz @do_while_not_ok\r\nend;\r\n\r\nprocedure bsort2;\r\nvar ok : Boolean;\r\n    i, aux : Integer;\r\nbegin\r\n    repeat\r\n        ok := true;\r\n        for i := 1 to n-1 do\r\n            if (a[i] > a[i+1]) then\r\n            begin\r\n                aux := a[i];\r\n                a[i] := a[i+1];\r\n                a[i+1] := aux;\r\n                ok := false;\r\n            end;\r\n    until ok;\r\nend;\r\n\r\nvar i : Integer;\r\n    starttick, endtick : LongInt;\r\n    time : Longint absolute $0000:$046C;\r\n\r\n{ timer pentru masurarea timpului }\r\nconst tickspersecond = 18.206;\r\n\r\nprocedure starttimer;\r\nbegin\r\n    starttick := time;\r\nend;\r\n\r\nfunction elapsedtime : real;\r\nbegin\r\n    endtick := time;\r\n    elapsedtime := (endtick - starttick)*\r\n        (1 / tickspersecond);\r\nend;\r\n\r\nbegin\r\n    citire;\r\n    p := @a;\r\n    starttimer;\r\n    for i:=1 to n_tests do\r\n    begin\r\n        flip;\r\n        bsort;\r\n    end;\r\n    writeln(n_tests, \' rulari ale bsort in asamblare\r\n        au rulat in : \', elapsedtime : 6:3, \' secunde\');\r\n    starttimer;\r\n    for i:=1 to n_tests do\r\n    begin\r\n        flip;\r\n        bsort2;\r\n    end;\r\n    writeln(n_tests, \' rulari ale bsort obisnuit\r\n            au rulat in : \',elapsedtime : 6:3, \' secunde\');\r\nend.\r\n==\r\n\r\nOutput program pascal (pe pc-ul meu: Duron $750$ Mhz):\r\n\r\n* $100$ rulari ale bsort in asamblare au rulat in : $1.263$ secunde\r\n* $100$ rulari ale bsort obisnuit au rulat in : $4.614$ secunde\r\n\r\nDe precizat este ca nu am optimizat programul aproape deloc (am transcris codul din pascal in asm). Cu optimizari \"hardcore\" se pot obtine timpi mult mai buni. Diferenta dintre varianta asm si varianta high level language este mai mica pe compilatoarele mai noi, cum ar fi GCC sau FreePascal deoarece acestea stiu genera un cod mai optimizat. Totusi, nici un compilator nu poate bate creierul uman.\r\n\r\nh2(#linkuri). Linkuri\r\n\r\n* \'_The Art of Assembly Language_\':http://www.scribd.com/doc/6498072/Art-of-Assembly. O carte detaliata si foarte buna atat pentru incepatori cat si pentru avansati.\r\n\r\n* \'_How to optimize for the Pentium processor_\':http://www.goof.com/pcg/doc/pentopt.txt. Un tutorial bun pentru optimizarea programelor in asamblare pentru procesoarele din familia Pentium. Tutorialul este pentru avansati.\r\n\r\n* \'_Assembly Tutorials_\':http://www.techtutorials.info/assembly.html. Mai multe tutoriale despre assembly language.\r\n\r\nh2(#concluzie). Doua cuvinte conclusive...\r\n\r\nAcest articol trateaza \"bazele\" programarii in asamblare, dupa cum ii zice numele este doar o introducere. Pentru a sti sa programezi in _asm_, trebuie invatate mult mai multe lucruri. Scopul articolului este de a starni interesul cititorilor si de a le oferi o imagine asupra acestui limbaj. Cei ce doresc sa invete mai multe despre _assembly language_ sunt invitati sa citeasca cartile / tutorialele din sectiunea \'linkuri\':introducere-in-asamblare#linkuri.',2044,'public',3676,NULL),('template/deinscriere','template/deinscriere','2009-01-22 22:13:11','2009-02-04 17:20:39','Trebuie sa te inscrii doar daca vrei sa ti se modifice rating-ul in urma participarii la aceasta runda. Daca odata inscris nu mai poti participa, te poti deinscrie.\r\n\r\nPoti participa la concurs chiar si daca nu te-ai inscris in prealabil.\r\n\r\n*Atentie!* Odata inscris, \'rating-ul\':documentatie/rating tau va fi afectat, chiar si daca nu vei trimite solutii!\r\n\r\n\'*Vezi cine s-a inscris*\':lista-inregistrare/%round%',1792,'protected',NULL,NULL),('runda/try_it','try_it','2009-05-17 05:21:48','2009-05-17 05:21:48','h1. == roundparam(round_id=\"try_it\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"try_it\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"try_it\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"try_it\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/try_it/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"try_it\" score=\"1\")==',10247,'round: try_it',NULL,NULL),('runda/cx21.03.2009','cx21.03.2009','2009-03-20 22:47:52','2009-03-20 22:47:52','h1. == roundparam(round_id=\"cx21.03.2009\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cx21.03.2009\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cx21.03.2009\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cx21.03.2009\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cx21.03.2009/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cx21.03.2009\" score=\"1\")==',6191,'round: cx21.03.2009',NULL,NULL),('blog/problema-saptamanii-monede','Problema saptamanii - Monede','2009-01-26 06:02:25','2009-01-26 06:09:30','Pe o masa dreptunghiulara punem monede de raza 1 pana cand nu mai putem adauga o noua moneda fara ca ea sa se suprapuna cu altele. Unele monede pot fi partial inafara mesei. Daca numarul total de monede este $n$, sa se demonstreze ca toata suprafata mesei poate fi acoperita de $4n$ monede de raza unu care se pot suprapune.\r\n\r\n_Ca de obicei puteti trimite solutiile la adresa cosminn at gmail.com_\r\n\r\n',58,'protected',3604,NULL),('okr/20084','OKRs 2008Q4','2009-01-26 14:02:53','2009-01-26 15:49:28','h2. 2008Q4\r\n\r\nh3(#arhiva). Arhiva de probleme\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Extinde arhiva\':implica-te/extinde-arhiva | ==user(user=\"ditzonec\" type=\"tiny\")== | ==include(page=\"okr/20084/extinde-arhiva\")== | 0.5 |\r\n| \'Imbunatateste teste\':implica-te/imbunatatire-teste | ==user(user=\"ditzonec\" type=\"tiny\")== | ==include(page=\"okr/20084/imbunatatire-teste\")== | 1 |\r\n|\'Open surse\':propuneri/5-open-surse | ==user(user=\"gcosmin\" type=\"tiny\")== | ==include(page=\"okr/20084/open-surse\")== | 0.25 |\r\n| \'Arhiva educationala\':implica-te/arhiva-educationala | ==user(user=\"filipb\" type=\"tiny\")==, ==user(user=\"pauldb\" type=\"tiny\")== | ==include(page=\"okr/20084/arhiva-educationala\")== | 0.75 |\r\n| Tagging|==user(user=\"bogdan2412\" type=\"tiny\")== | ==include(page=\"okr/20084/tagging\")== | 0.5 |\r\n\r\nh3(#concursuri). Concursuri\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Organizeaza concursuri | ==user(user=\"astronomy\" type=\"tiny\")== | ==include(page=\"okr/20084/organizeaza-concursuri\")== | 0.75 |\r\n| Algoritmiada | ==user(user=\"wefgef\" type=\"tiny\")== | ==include(page=\"okr/20084/algoritmiada\")== | 1 |\r\n| \'Rating\':documentatie/rating | ==user(user=\"victorsb\" type=\"tiny\")== | ? | ? |\r\n| \'Hackaton\':propuneri/1-hackaton| ? | ? | ? |\r\n| \'Calendar\':forum?action=calendar | ==user(user=\"pauldb\" type=\"tiny\")== | ==include(page=\"okr/20084/calendar\")== | 1 |\r\n\r\nh3(#continut). Continut educational\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Scrie articole\':implica-te/scrie-articole | ==user(user=\"stef2n\" type=\"tiny\")== | ==include(page=\"okr/20084/articole\")== | 0.75 |\r\n| \'Downloads\':downloads, \'Links\':links | ==user(user=\"Prostu\" type=\"tiny\")== | ==include(page=\"okr/20084/downloads\")== | 0.1 | \r\n| \'Almanah infoarena\':propuneri/8-almanah | ? | ? | ? |\r\n\r\nh3(#development). Development\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'infoarena 2.x Stable\':http://hackers.devnet.ro/roadmap | ==user(user=\"domino\" type=\"tiny\")== | ==include(page=\"okr/20084/devel-ia2\")== | 0.5 |\r\n| \'infoarena 3.0\':propuneri/3-infoarena3 | ==user(user=\"domino\" type=\"tiny\")== | ==include(page=\"okr/20084/devel-ia3\")== | 0.25 |\r\n\r\nh3(#comunitate). Comunitate\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Blog\':blog | ==user(user=\"Cosmin\" type=\"tiny\")== | ? | ? |\r\n| \'Forum\':forum | ==user(user=\"wefgef\" type=\"tiny\")== | ==include(page=\"okr/20084/forum\")== | 0.3 |\r\n| \'Community Ladder\':propuneri/7-community-ladder | ==user(user=\"wickedman\" type=\"tiny\")== | ==include(page=\"okr/20084/community-ladder\")== | 0.75 |\r\n\r\nh3(#administrativ). Administrativ\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Newsletter | ==user(user=\"wickedman\" type=\"tiny\")==| ==include(page=\"okr/20084/newsletter\")== | 0.6 |\r\n| Strangere fonduri | ==user(user=\"wickedman\" type=\"tiny\")== | ==include(page=\"okr/20084/fund-raising\")== | 0 |\r\n| Contabilitate | ? | ? | ? |\r\n| Hosting, data center ops. | ? | ? | ? |\r\n| Marketing si relatii publice | ? | ? | ? |\r\n\r\n',13,'public',NULL,NULL),('okr/20091/extinde-arhiva','okr/20091/extinde-arhiva','2009-01-26 14:47:38','2009-01-26 18:11:55','(okr)* Adaugarea in arhiva a 9 de probleme noi\r\n** adaugat lot Iasi 2008',1,'public',NULL,NULL),('okr/20091/forum','okr/20091/forum','2009-01-26 14:47:50','2009-01-26 19:00:52','',1,'public',NULL,NULL),('okr/20091/fund-raising','okr/20091/wickedman/fund-raising','2009-01-26 14:48:03','2009-01-28 11:50:25','(okr)* Alcătuieşte portofoliu de sponsori.\r\n** Centralizează lista cu sponsorii infoarena, contribuţiile lor, şi date de contact.\r\n* 2%\r\n** Blog post despre direcţionările 2% din 2008.\r\n** Actualizează pagina 2% pentru 2009.\r\n* PayPal\r\n** Evidenţiază PayPal ca modalitate de sponsorizare.',13,'public',NULL,NULL),('okr/20091/imbunatatire-teste','okr/20091/imbunatatire-teste','2009-01-26 14:48:14','2009-01-26 18:12:26','(okr)* Detectarea problemelor cu teste slabe\r\n** Marcarea tuturor problemelor cu teste slabe din paginile 4-6',1,'public',NULL,NULL),('okr/20091/newsletter','okr/20091/newsletter','2009-01-26 14:48:25','2009-01-26 19:06:26','(okr)* Eficientizează procesul de trimis newsletter, în special pentru anunţarea unui concurs nou.\r\n** Macro pentru anunţarea unui concurs.\r\n** Template-uri pentru boilerplate. (rating, implică-te, prima dată la infoarena, etc.)\r\n* Posibilitatea ca alţi membri infoarena sa poată redacta un newsletter şi să trimită un newsletter.\r\n** Documentaţie script send-newsletter\r\n** Un newsletter va fi trimis de altcineva decât Cristian.\r\n',1,'public',NULL,NULL),('planificare/sedinta-20090112','Sedinta 2009-01-12','2009-01-05 15:03:20','2009-01-26 17:21:17','h1. Sedinta 2009-01-12\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe întâlnim *luni, 12 ianuarie* la ora *18^00^* la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== - pe seara as prefera\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")== - ar fi mai bine mai spre 16:00 si nu la retro cafe\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== - as prefera dupa 18:30\r\n* ==user(user=\"prostu\" type=\"tiny\")== - as prefera dupa 16:00\r\n* ==user(user=\"stef2n\" type=\"tiny\")== - prezent doar daca nu are loc in intervalul 18-20, din cauza unei lucrari\r\n* ==user(user=\"gcosmin\" type=\"tiny\")== - ar merge mai spre seara (dupa 6:30-7:00 asa)\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinta anterioara\':planificare/sedinta-20081125| ==user(user=\"domino\" type=\"tiny\")==|\r\n| Algoritmiada (sponsorizari)| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n| OKR-uri (Q4 2008 si Q1 2009)|  ==user(user=\"domino\" type=\"tiny\")== |\r\n| Coding camp |  ==user(user=\"domino\" type=\"tiny\")== |\r\n| \'IAP 11\':propuneri/11-rating | ==user(user=\"bogdan2412\" type=\"tiny\")== |\r\n| \'IAP 10\':propuneri/10-virtual-contest | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Stelele |  ==user(user=\"silviug\" type=\"tiny\")== |\r\n| ONIbyNET si sistem de submit | ==user(user=\"domino\" type=\"tiny\")== |\r\n| Fix it week/camp | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| CCS pe viitor? | ==user(user=\"wickedman\" type=\"tiny\")== |\r\n| Misc | ==user(user=\"silviug\" type=\"tiny\")== |\r\n\r\nh3. Detalii\r\n\r\n* Stelele:\r\n** Go international: desi la stadiul de idee, Ali se gandeste sa invite bulgarii cei mai tari la stele; ce-ar presupune asta din partea noastra?\r\n** Va avea loc in vacanta inter-semestriala (perioada 31 ianuarie - 7 februarie)\r\n** Masuri de securitate, probleme cu adminii (Bogdan are parola pe live) \r\n* Fix it week/camp:\r\n** Scop: imbogatirea si imbunatatirea continutului site-ului, implicarea comunitatii in activitatile noastre, identificarea de noi colaboratori \"de baza\"\r\n** Fix it week: declararea unei saptamani in care toata comunitatea trage tare pentru content; cel mai simplu exemplu sunt articole de transcris; putem include si task-uri mai specializate ca finalizarea de probleme in arhiva [educationala]?, documentatie pentru diverse parti din site, etc.\r\n** Fix it camp: in paralel sau ca alternativa la fix it week; membrii infoarena se imbraca in salopete cu harlete in spate si se aduna intr-un loc prestabilit; chemam membrii comunitatii care vor sa se implice si \"plantam\" articole, documentatie, etc. o zi sau un week-end intr-o locatie precum ICHB. \r\n** In sedinta aceasta as dori sa primesc feedback si sugestii noi despre:\r\n*** Forma acestui eveniment: week or/and camp or/and ??\r\n*** Ce putem realiza cu un astfel de eveniment? (in materie de continut si implicare a comunitatii; care din scopuri sunt SF?)\r\n*** Ma ofer (Silviu) eu sa organizez evenimentul in Q1-09, intr-o forma in care cadem cu totii de acord. \r\n* Misc:\r\n** Silviu: De ce nu avem (inca) comentarii la articole? Mai sunt alte pagini la care am vrea comentarii (in stil de blog)?\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Punem stire ca nu mai ai voie cu HTML si sa-si actualizeze lumea profilele\r\n* OKR-uri:\r\n** Am dat note (medie 0.53)\r\n** Mircea curata pagina de OKR-uri (+ istorie)\r\n** Tema: fiecare responsabil face OKR-uri pentru data viitoare si selectam pentru Q1\r\n** Cristi face blog post despre OKR-uri\r\n* Algoritmiada:\r\n** Silviu, Cristi si Wef se ocupa de sponsori\r\n** Wef cu Silviu fac bugetul\r\n** Silviu stabileste contacte cu Poli si cu Sonia\r\n* Stelele:\r\n** Le luam parolele lui Bogdan si Cosmin\r\n** Cristi face ticket-ul cu IP-ul (La fiecare submit retinem IP-ul ca sa detectam cine triseaza)\r\n* IAP 11:\r\n** 2 tichete:\r\n*** Facem o pagină de submit mai deşteaptă. S-au propus mai multe soluţii, am şi eu câteva idei. Vom şti clar la ce runde participă conştient un concurent. Asta rezolvă şi faptul că acum e greu să facem statistici!\r\n*** Facilitate pentru de-înregistrare. \r\n** Bogdan baga o intersectie intre cei care s-au inscris si cei care au submitat -> 90% la primele doua runde de Algoritmiada\r\n** Se respinge\r\n* IAP 10:\r\n** Se accepta\r\n** Cosmin face OKR-uri pentru asta\r\n* Cristi se baga pentru ONIbyNET@infoarena.ro; Cristi si Mircea fac lobby\r\n* Mircea porneste discutie despre urmatorul Coding Camp\r\n* Silviu baga blog post: analiza runda 2 Algoritmiada (\'done\':blog/algoritmiada-runda2)\r\n* Fixit week/camp:\r\n** Combinam fixit camp cu coding camp\r\n** Silviu face fixit camp\r\n** Cristi si Silviu vorbesc de premii\r\n* Algoritmiada runda 3 (15 februarie; worst case 22 februarie)\r\n* Cristi face rezervare recurenta la CCS. Urmatoarea sedinta pe 26 ianuarie 2009. Nu uita de net si intreaba si de camp!\r\n\r\nh2. Notite\r\n\r\n* Material de prezentare pentru Algoritmiada\r\n* internationalizare pentru infoarena?\r\n\r\n',1,'protected',NULL,NULL),('okr/20091/open-surse','okr/20091/open-surse','2009-01-26 14:48:35','2009-01-26 18:17:00','',1,'public',NULL,NULL),('okr/20091/organizeaza-concursuri','okr/20091/organizeaza-concursuri','2009-01-26 14:48:44','2009-02-04 00:02:47','(okr)* Grigore Moisil by Net\r\n** Promovare în timp util.\r\n',13,'public',NULL,NULL),('okr/20091/tagging','okr/20091/tagging','2009-01-26 14:48:56','2009-01-26 15:37:46','(okr)* 25 de probleme din arhiva taguite de catre utilizatori\r\n** Implementat algoritm care sa afiseze taguri cu probabilitate mare sa se potriveasca in functie de voturile utilizatorilor cu punctaj maxim pe problema.\r\n** Implementat interfata de votat/raportat taguri',1490,'public',NULL,NULL),('okr/20084/extinde-arhiva','okr/20084/extinde-arhiva','2009-01-26 14:03:54','2009-01-26 14:03:54','(okr)* Adaugarea in arhiva a 20 de probleme noi\r\n** adaugat baraje juniori\r\n** adaugat lot Iasi 2008',13,'public',NULL,NULL),('okr/20084/imbunatatire-teste','okr/20084/imbunatatire-teste','2009-01-26 14:05:10','2009-01-26 14:05:10','(okr)* Detectarea problemelor cu teste slabe\r\n** Marcarea tuturor problemelor cu teste slabe din primele 3 pagini',13,'public',NULL,NULL),('okr/20084/open-surse','okr/20084/open-surse','2009-01-26 14:08:28','2009-01-26 14:11:24','(okr)* dupa analizarea statisticilor extrase se concluzioneaza daca efectul open surse a fost unul benefic sau nu pentru comunitate, in functie de concluzie se decide daca se pun si alte probleme open (cate si care), sau nu\r\n** pentru statistici se masoara urmatoarele: numarul de accesari, numarul de rezolvari, numarul total de submisii la o problema, numarul de submisii pe concurent, numarul de surse identice, numarul surselor accesate, cate surse de 100 are un concurent la o problema',13,'public',NULL,NULL),('okr/20084/arhiva-educationala','okr/20084/arhiva-educationala','2009-01-26 14:11:56','2009-01-26 14:11:56','(okr)* dezvoltarea arhivei educationale cu 15 de probleme\r\n** alegem o echipa din 5-6 utilizatori care sa contribuie la dezvoltarea arhivei educationale\r\n** stabilim si bagam cele 15 de probleme\r\n* verificarea problemelor adaugate pana acum\r\n** verificarea problemelor existente (daca respecta formatul, explicatiile sunt complete si clare, etc.)\r\n',13,'public',NULL,NULL),('okr/20084/tagging','okr/20084/tagging','2009-01-26 14:12:55','2009-01-26 15:37:18','(okr)* Pregatiri pentru implementarea tagurile in 2009Q1\r\n** Alegere subset de probleme din arhiva\r\n** Alegere set de taguri (ex: greedy, dinamica...)\r\n** Pagina destinata tagurilor la sectiunea implica-te, incurajarea utilizatorilor care au rezolvat probleme sa ajute la taguire (prin newsletter, notice pe prima pagina)\r\n',1490,'public',NULL,NULL),('okr/20084/organizeaza-concursuri','okr/20084/organizeaza-concursuri','2009-01-26 14:13:20','2009-01-26 14:13:20','(okr)* Aparitia rubricii \"organizeaza concursuri\" la sectiunea proiecte infoarena\r\n** Redactarea paginei \"organizeaza concursuri\" si continutului aferent ei\r\n** Stabilirea exacta a modului de organizare a unui concurs de catre un utilizator\r\n* Organizarea concursului lui Ciucu\r\n** testarea problemelor ce urmeaza sa fie folosite in concurs\r\n** lansarea concursului la sfarsitul lunii noiembrie',13,'public',NULL,NULL),('okr/20084/algoritmiada','okr/20084/algoritmiada','2009-01-26 14:13:41','2009-01-26 14:13:41','(okr)* organizarea unui concurs cel putin la fel de bun ca editia preONI de anul trecut\r\n** stabilirea numelui noului concurs\r\n** stabilirea datelor rundelor (si a finalei onsite?)\r\n** organizarea bugetului alocat concursului de anul acesta\r\n** gasirea unei echipe de persoane (~10 oameni) care sa faca parte din comisia stiintifica preONI 2009. Permitem sa propuna celor care nu fac parte din echipa?\r\n** stabilirea regulilor de organizare a fiecarei runde',13,'public',NULL,NULL),('okr/20084/calendar','okr/20084/calendar','2009-01-26 14:14:32','2009-01-26 14:14:32','(okr)* anuntarea concursurilor din timp\r\n** sa mearga treaba ca si pana acum',13,'public',NULL,NULL),('okr/20084/articole','okr/20084/articole','2009-01-26 14:14:50','2009-01-26 14:14:50','(okr)* Eficientizeaza procesul de adaugare a articolelor noi si de contributie la cele deja existente\r\n** Stabileste conventiile de formatare uniforma pentru articole\r\n** Redacteaza un mini-HOWTO despre adaugarea unui articol nou\r\n** Mentine, in mod transparent, evidenta articolelor incepute si stabileste termene de finalizare de comun acord cu autorul/editorul\r\n* Restructureaza si aduce la o forma prezentabila continutul existent\r\n** Alege 3-5 editori care sa se ocupe de aspect, continut, completari la articole\r\n** Impreuna cu editorii, ajuta la finalizarea articolelor in progres si a cioturilor de articole\r\n** Restructureaza pagina principala si intreaga sectiune\r\n** Integreaza sistemul de comentarii si la articole pentru un plus de interactivitate',13,'public',NULL,NULL),('okr/20084/downloads','okr/20084/downloads','2009-01-26 14:15:03','2009-01-26 14:15:03','(okr)* Utilitatea arhivelor din sectiunea download si respectiv a linkurilor din sectiunea links. \r\n** Integritatea si intregirea arhivelor\r\n** Update la linkuri (daca au murit sau daca au aparrut versiuni mai ale articolelor, programelor, etc)\r\n** Structurarea celor 2 pagini pentru o navigare mai usoara (Care alternativa e mai comoda, just google it sau intri pe infoarena si vezi daca ce cauti este pe site)',13,'public',NULL,NULL),('okr/20084/devel-ia2','okr/20084/devel-ia2','2009-01-26 14:15:52','2009-01-26 14:15:52','(okr)* infoarena stabil cu concursuri automate\r\n** organizam 2-3 coding camp-uri cu echipa infoarena\r\n** alegem tickete relevante pentru 2.2 si le rezolvam pe toate; facem release\r\n** organizam runde de preONI pe noul sistem complet automat si fara incidente',13,'public',NULL,NULL),('okr/20084/devel-ia3','okr/20084/devel-ia3','2009-01-26 14:16:04','2009-01-26 14:16:04','(okr)* comunitate functionala de developeri\r\n** crestem numarul de contribuitori: sa avem macar 2-3 oameni activi\r\n** folosim best practices: documentatie si tutoriale pentru incepatori, code review, tickets, documentation, setup script,  unit tests, benchmarks, regression tests',13,'public',NULL,NULL),('okr/20084/forum','okr/20084/forum','2009-01-26 14:16:18','2009-01-26 14:16:18','(okr)* reorganizarea forumului\r\n** gasirea si numirea noilor moderatori\r\n** implementarea unui sistem captcha pentru postari ale vizitatorilor\r\n** alcaturiea unui set de reguli _elementare_ pentru cei care posteaza',13,'public',NULL,NULL),('okr/20091/virtual-contest','okr/20091/virtual-contest','2009-01-26 14:49:06','2009-01-26 14:53:35','(okr)* Un sistem ce permite concursuri virtuale (si posibil arhive individuale)\r\n** Implementare propriu-zisa ce sa ofere toate functionalitatile specificate in \'IAP\':propuneri/10-virtual-contest\r\n** Lansarea publica',13,'public',NULL,NULL),('utilizator/oana_enusoiu','Profil oana_enusoiu','2009-01-28 16:12:14','2009-01-28 16:12:14','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',9454,'public',NULL,NULL),('algoritmiada-2010/premii','Algoritmiada 2010 - Sponsori si premii','2009-10-25 17:30:27','2010-04-13 16:21:31','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Sponsori si premii\r\n\r\nh2. Premii\r\n\r\nPentru fiecare dintre cele patru grupe, primii din clasament in urma desfasurarilor probelor online vor fi premiati cu o diploma de finalist al concursului *Algoritmiada 2010* si o \'runda finala\':algoritmiada-2010/runda-finala cu cazare si masa asigurate.\r\nAcestia vor avea sansa sa interactioneze cu membrii \'echipei infoarena\':echipa-infoarena si cu ceilalti membri ai comunitatii infoarena si sa invete de la si impreuna cu acestia. Runda finala va fi de asenemea un prilej de a ii rasplati pe cei mai buni dintre cei mai buni. Punctajele din acesta runda vor fi independente de cele acumulate la rundele online, iar primii 3 clasati la fiecare grupa vor avea parte de urmatoarele premii:\r\n\r\n* Locul I: \'Amazon Kindle 2\':http://www.amazon.com/Kindle-Wireless-Reading-Display-Generation/dp/B0015T963C + \'leather cover\':http://www.amazon.com/Amazon-Kindle-Leather-Display-Generation/dp/B002Y27P6O.\r\n* Locul II: Gift certificate Amazon in valoare de 150 GBP, valabil pe \'site-ul Amazon\':http://www.amazon.co.uk/.\r\n* Locul III: Gift certificate Amazon in valoare de 75 GBP, valabil pe \'site-ul Amazon\':http://www.amazon.co.uk/.\r\n\r\n==Include(page=\"template/algoritmiada-2010/footer\")==',2038,'protected',NULL,NULL),('utilizator/alexandrub','Profil AlexandruB','2009-02-02 07:21:03','2009-02-02 07:21:03','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',9493,'public',NULL,NULL),('blog/doi-la-suta-2008-raport','Vă mulțumim pentru sprijin! 2% pentru infoarena','2009-02-02 19:53:16','2009-05-08 13:58:20','h1. Vă mulţumim pentru sprijin!\r\n\r\nPeste 50 de persoane au sprijinit \'Asociaţia infoarena\':asociatia-infoarena direcţionând 2% din impozitul pe venit în 2008 (pentru anul fiscal 2007). Direcţionările au însumat 4.619 lei.\r\n\r\nAm fost surprinşi într-un mod plăcut de aceste contribuţii. Ne bucurăm că apreciaţi infoarena şi munca pe care o depunem. Vă mulţumim pentru sprijin! Vom folosi banii aceştia la organizarea finalei \'Algoritmiada\':algoritmiada-2009, principala cheltuială anuală a \'Asociaţiei infoarena\':asociatia-infoarena.\r\n\r\nh4. Ce este „2%”?\r\n\r\nbq. Sistemul „2%” permite contribuabililor persoane fizice să direcţioneze 2% din impozitul lor pe venit către o organizaţie neguvernamentală. Este un sistem prin care cetăţenii au posibilitatea să decidă în mod direct ce se întamplă cu impozitele lor. [...] Direcţionarea nu costă nimic. \'(Sursa)\':http://www.doilasuta.ro\r\n\r\nVă rugăm să vizitaţi pagină dedicată \'sistemului 2%\':doi-la-suta pentru mai multe detalii.\r\n\r\nh4. Contribuabili în 2008\r\n\r\nNu avem o listă nominală cu toţi contribuabilii din cauză că programul „2%” prevede ca identitatea acestora să rămână secretă. Avem însă un tabel cu instituţiile fiscale ce au efectuat viramente în contul \'Asociaţiei infoarena\':asociatia-infoarena.\r\n\r\ntable{width:auto}. |_. Data |_. Instituţie |_. Sumă (lei) |\r\n| 2008-11-12 | Ministerul Finanţelor, acţiuni generale 2% |>. 1.334,42 |\r\n| 2008-12-17 | Sector 3, Bucureşti |>. 637,42 |\r\n| 2008-11-26 | Trezoreria Bugetului de Stat |>. 540,42 |\r\n| 2008-12-22 | Sector 5, Bucureşti |>. 475,42 |\r\n| 2008-11-25 | Sector 1, Bucureşti |>. 411,42 |\r\n| 2008-11-17 | Sibiu |>. 347,72 |\r\n| 2008-11-03 | AF Plopeni |>. 315,42 |\r\n| 2008-11-27 | Slatina |>. 228,42 |\r\n| 2008-11-05 | Bugetul de Stat |>. 144,42 |\r\n| 2008-11-27 | Sector 6 |>. 117,42 |\r\n| 2008-12-18 | Galaţi |>. 67,42 |\r\n|>\\2. *Total* |>. *4.619,92* |\r\n\r\nDacă nu vă regăsiţi în lista de mai sus deşi v-aţi exercitat dreptul de a direcţiona 2% din impozit, vă rog să mă \'contactaţi\':mailto:cristian@infoarena.ro.\r\n\r\nh3. Ce facem cu banii primiţi?\r\n\r\nPrincipala cheltuială a \'Asociaţiei infoarena\':asociatia-infoarena o reprezintă organizarea anuală a finalei \'Algoritmiada\':algoritmiada-2009, eveniment la care sunt invitate 60 de persoane pentru care asigurăm cazare, masă şi premii. În funcţie de locaţia pe care o alegem şi de partenerii care ne sprijină, bugetul finalei poate să depăşească 20.000 lei, astfel că toate aceste contribuţii sunt foarte bine venite, chiar necesare.\r\n\r\nAlte direcţii în care vrem să investim resurse financiare ţin de stimularea comunităţii, în special a membrilor care se implică semnificativ în \'proiectele infoarena\':implica-te şi organizarea \'întrunirilor\':planificare echipei infoarena. Spre exemplu, în week-endul 28 Februarie - 1 Martie, echipa infoarena organizează un „coding camp” - un „hei rup” la care reparăm bug-uri şi implementăm noi facilităţi pentru site şi evaluator.\r\n\r\nh3. „2%” în 2009\r\n\r\nDacă apreciaţi proiectul infoarena, vă rugăm să ne sprijiniţi şi în 2009. Procedura de direcţionare este simplă şi nu vă costă nimic! *Termenul limită este 15 mai 2009.*\r\n\r\n\'*Aflaţi ce trebuie să faceţi şi la ce vom folosi contribuţiile*\':doi-la-suta.\r\n\r\np. &nbsp;\r\n\r\nSunteţi unul dintre contribuabili? Spuneţi-ne cum a decurs procedura de direcţionare. Aţi întâmpinat probleme? Aveţi nelămuriri? Lăsaţi-ne un comentariu.\r\n',13,'public',3619,NULL),('preoni-2006/runda-2/solutii','Solutii preONI 2006 - Runda a 2-a','2005-12-17 00:00:00','2009-05-17 07:03:48','h1. Solutii preONI 2006 - Runda a 2-a\r\n\r\n(Categoria _Competitii_, autor(i) _Echipa infoarena_)\r\n\r\nRunda a 2-a concursului preONI 2006 s-a incheiat. Acest articol va prezinta solutiile oficiale ale celor 7 probleme propuse.\r\n\r\nFiecare grupa a avut spre rezolvare 3 probleme, fiecare fiind catalogata de catre comisie ca fiind usoara, medie sau grea. Batalia pentru calificarea la finala este in toi!\r\n\r\nPentru mai multe detalii despre finala, cat si despre concursul preONI 2006 si sponsorii nostri va rugam sa consultati pagina \"preONI-2006\":preONI-2006.\r\n\r\nRezultatele finale sunt disponibile la:\r\n\r\n* \"Clasa a 9-a\":preoni-2006/runda-2/clasament-9\r\n* \"Clasa a 10-a\":preoni-2006/runda-2/clasament-10\r\n* \"Clasele 11-12\":preoni-2006/runda-2/clasament-11-12\r\n\r\nDificultatea problemelor nu a lasat nici de aceasta data de dorit. Desi ne-am fi asteptat la punctaje mai mari, rezultatele concurentilor au fost decente. Provocarile oferite de Infoarena sunt intr-adevar dificile, iar obtinerea unui punctaj apropiat de cel maxim nu este usor de realizat. In editiile ce vor urma vom tine cont de acest aspect. Pana atunci va invitam sa discutati despre aceasta runda de concurs pe \"forum-ul infoarena\":http://forum.infoarena.ro/index.php/board,20.0.html.\r\n\r\nCa de obicei, problemele din acest concurs au fost puse si in \"Arhiva de probleme\":arhiva, disponibile pentru rezolvare 24 de ore din 24. Va asteptam cu forte proaspete la runda a 3-a din 21 ianuarie 2006 !!!\r\n\r\nh2. Dame\r\n\r\nh3. (clasa a 9-a problema usoara)\r\n\r\nIn primul rand, numarul maxim de dame este $N$ pentru $N = 1$ si {$N &ge; 4$}, si $N-1$ pentru {$N = 2, 3$}. Putem codifica solutia ca o permutare de la $1$ la {$N$}, astfel asigurand ca nu exista doua dame pe aceeasi linie sau coloana. O solutie clasica care foloseste metoda backtracking si face verificarea daca o dama este atacata sau nu in $O(1)$ va obtine $30$ de puncte.\r\nVerificarea in $O(1)$ se face pastrand doi vectori pentru fiecare diagonala in functie de orientare, in care se marcheaza daca o diagonala este ocupata. O \"imbunatatire\" la backtracking este randomizarea ordinii in care se incearca completarea solutiei la fiecare pas. O astfel\r\nde solutie merge usor si pentru $N = 200$ si ar fi obtinut cel putin $60$ de puncte.\r\nExista mai multe metode prin care s-ar fi putut obtine $100$ de puncte. O solutie greedy este urmatoarea: se incepe cu o solutie oarecare si cat timp exista doua dame care, daca s-ar interschimba coloanele lor, se imbunatateste solutia, se aplica interschimbarea. Daca\r\nnu s-a obtinut o solutie buna, se reinitializeaza solutia initiala si se reaplica algoritmul. In practica, complexitatea algoritmului tinde la {$O(N log N)$}, desi teoretic este {$O(N^3^)$}. De asemenea pe masura ce $N$ este mai mare, numarul necesar de reinitializari ale algoritmului tinde catre {$0$}. Mai multe detalii gasiti \"aici\":http://www.cit.gu.edu.au/~sosic/nqueens.html\r\nO alta solutie , matematica, se bazeaza pe un sablon de construire a solutiei in functie de restul lui $N$ la {$12$}.\r\n\r\n* Se insereaza numerele pare de la $2$ la $N$ intr-o lista\r\n* Daca restul lui $N$ la $12$ este $3$ sau $9$ se muta $2$ la sfarsitul listei\r\n* Se insereaza numerele impare de la $1$ la $N$ in lista\r\n* Daca restul este $8$ se interschimba perechile ({$3 1$}, {$7 5$}, ...)\r\n* Daca restul este $2$ se interschimba $1$ cu $3$ si $5$ se muta la sfarsitul listei\r\n* Daca restul este $3$ sau $9$ se muta $1$ si $3$ la sfarsitul listei\r\n\r\nLista va codifica o solutie cum s-a precizat si inainte, al {$i$}-lea element reprezetand o dama pe randul $i$ si pe coloana {$lista{~i~}$}.\r\nAceasta solutie $O(N)$ este preluata de \"aici\":http://en.wikipedia.org/wiki/Eight_queens_puzzle\r\n\r\nh2. Zota & Chidil\r\n\r\nh3. (clasa a 9-a problema medie)\r\n\r\nO solutie de complexitate $O((M + N)lg N)$ este imediata. Se vor folosi doi vectori, fiecare continand coordonatele punctelor afectate de capcane, mai putin punctul de coordonate ({$0, 0$}), pentru a respecta conditia impusa in enunt. Primul vector $vx$ va fi sortat dupa coordonata {$x$}, iar in caz de egalitate dupa coordonata {$y$}. Al doilea, {$vy$}, va fi sortat dupa $y$ si, in caz de egalitate, dupa {$x$}.\r\n\r\nLa fiecare mutare executata de Chidil (un numar de pasi facut intr-o anume directie) se calculeaza numarul de celule afectate prin care trece. Pentru aceasta se vor aplica doua cautari binare in vectorul corespunzator.\r\n\r\nDaca se deplaseaza inspre $N$ sau {$S$}, cautarea se va face in {$vx$}, altel, in {$vy$}. Diferenta dintre cele doua valori returnate de cautarile binare furnizeaza numarul de celule afectate prin care Chidil trece la acea mutare.\r\n\r\nPentru un timp de executie bun, se recomanda folosirea functiei $sort()$ din STL pentru sortare si a containerului @pair<int, int>@ pentru pastrarea coordonatelor in cei doi vectori.\r\n\r\nh2. Grupuri\r\n\r\nh3. (clasa a 9-a problema grea, clasa a 10-a problema medie)\r\n\r\nO limita superioara pentru numarul de grupuri este $S / K$ unde $S$ reprezinta suma canitatilor de animale. Este evident ca, daca putem construi $X$ grupuri, putem construi si $Y &le; X$ grupuri, fapt care ne duce la ideea sa cautam binar numarul de grupuri. Pentru a verifica daca putem construi un numar de grupuri $X$ ne imaginam completarea unei matrice cu $X$ linii si $K$ coloane, fiecare linie reprezetand un grup. Din restrictiile problemei elementele de pe fiecare linie trebuie sa fie distincte. Vom completa aceasta matrice coloana cu coloana, pentru fiecare cantitate de animale daca este $&le; X$ le punem pe toate in matrice, daca este $> X$ punem doar $X$ in matrice (deoarece daca punem mai multe vor fi cel putin doua pe aceeasi linie). Pentru primul exemplu din enunt, matricea se va completa astfel:\r\n\r\np(pre). {@1 * *    1 2 *    1 2 3    1 2 3@}\r\n{@1 * *    1 2 *    1 2 *    1 2 4@}\r\n{@1 * *    1 * *    1 3 *    1 3 4@}\r\n{@* * *    2 * *    2 3 *    2 3 4@}\r\n\r\nAsadar , daca in final am putut completa toata matricea se pot forma $X$ grupuri. Este evident ca strategia folosita de verificare este optima. Completarea matricei se face doar conceptual, verificarea avand complexitatea $O(N)$ prin parcurgerea vectorului {$A$}, rezultand un algoritm de complexitate {$O(N lg(S/K))$}.Pe baza algoritmului descris mai sus, se poate obtine un algoritm {$O(N)$}, desi acesta n-ar fi fost necesar pentru $100$ de puncte.\r\n\r\nAlgoritmul lucreaza astfel: daca cel mai mare element este $&le; S/K$ , verificarea prezentata mai sus ne garanteaza ca vom putea obtine $S/K$ grupuri, toate elementele fiind $&le; S/K$ se vor folosi toate {$S$}, iar matricea este {$(S/K)*K = S$}. Daca cel mai mare element este $> S$ atunci putem rezolva aceeasi problema recursiv pentru cantitatile existente mai putin cea mai mare si grupuri de marime {$K-1$}. Acest rezultat va fi mai mic sau egal cu cel mai mare element, deci ne va ajunge pentru a completa grupurile la marimea {$K$}. Deoarece canitatile sunt date sortate, complexitatea este {$O(N)$}.\r\n\r\nh2. 1-2 perm\r\n\r\nh3. (clasa a 10-a problema usoara)\r\n\r\nProblema a fost incadrata in categoria usoara deoarece la majoritatea problemelor de acest tip concurentii genereaza cu backtracking valorile pentru primele numere si deduc formula generala. In cazul acesta, formula se putea vedea destul de usor:\r\n\r\n== code(cpp) |T[1] = 1, T[2] = 2, T[3] = 6, T[4] = 12;\r\nT[i] = T[i - 1] + T[i - 3] + 2 * (i - 2)\r\n==\r\n\r\nPentru cei mai curiosi din fire, vom demonstra cum se ajunge la aceasta formula. Fie $A{~i~}$ numarul permutarilor de lungime $i$ care au $1$ pe prima sau ultima pozitie, adica dublul numarului permutarilor care au $1$ pe prima pozitie (exceptie face, ca in toti pasii care vor urma, permutarea de lungime {$1$}). De asemenea, fie $B{~i~}$ numarul permutarilor de lungime $i$ care nu au $1$ pe prima sau ultima pozitie. Evident, {$T{~i~} = A{~i~} + B{~i~}$}. Primele valori sunt\r\n\r\n== code(cpp) |A[1] = 1, B[1] = 0\r\nA[2] = 2, B[2] = 0\r\nA[3] = 4, B[3] = 2\r\nA[4] = 8, B[4] = 4\r\n==\r\n\r\nPentru calculul lui $A$ consideram urmatoarele cazuri:\r\n\r\n# incepem permutarea cu $1, 2$ => avem $A{~i-1~}$ posibilitati\r\n# incepem permutarea cu $1, 3, 2, 4$ => avem $A{~i-3~}$ posibilitati\r\n# incepem permutarea cu $1, 3$ dar nu continuam cu $2$ => vom mai avea o singura posibilitate, de forma ({$1, 3, 5, 7, 9, 8, 6, 4, 2$}). Adica ``urcam\'\' cu numerele impare si ``coboram\'\' cu cele pare pana la {$2$}. Bineinteles, aceasta posibilitate poate fi considerata si in sens invers.\r\nDeci {$A{~i~} = A{~i-1~} + A{~i-3~} + 2$}.\r\n\r\nPentru calculul lui $B$ incepem cu numarul $1$ si observam ca celelalte numere pot fi completate doar alternativ (stanga-dreapta sau dreapta-stanga) pana la un anumit pas, si incepand de pe pozitia la care ne-am oprit, in unul din modurile calculate precedent. Pentru $i = 7$ incepand cu $1$ avem cazurile:\r\n\r\n* ({$3, 1, 2$}) => in continuare A{~5~} moduri\r\n* ({$3, 1, 2, 4$}) => in continuare A{~4~} moduri\r\n* ({$5, 3, 1, 2, 4$}) => in continuare A{~3~} moduri\r\n* ({$5, 3, 1, 2, 4, 6$}) => in continuare A{~2~} moduri\r\n* ({$7, 5, 3, 1, 2, 4, 6$}) => in continuare A{~1~} moduri\r\n\r\nObservam ca valorile calculate precedent in $A$ sunt de fapt dublul celor de care avem noi nevoie, dar considerand si modul invers de completare alternativa, rezultatul obtinut va fi cel corect.\r\nDeci {$B{~i~} = A{~i-2~} + A{~i-3~} + ... + A{~1~}$}, adica {$B{~i~} = B{~i-1~} + A{~i-2~}$}.\r\n\r\nAm ajuns la urmatoarele 2 siruri recurente:\r\n\r\n* $A{~i~} = A{~i-1~} + A{~i-3~} + 2$\r\n* $B{~i~} = B{~i-1~} + A{~i-2~}$\r\n\r\nMai facem urmatoarea observatie: {$A{~i~} - B{~i-1~} = (A{~i-1~} + A{~i-3~} + 2) - (B{~i-2~} + A{~i-3~}) = A{~i-1~} - B{~i-2~} + 2$}, ceea ce inseamna ca {$A{~i~} - B{~i-1~} = 2 * (i - 1)$} (demonstratie prin inductie, tinand cont de faptul ca {$A{~2~} + B{~1~} = 2$}).\r\n\r\nIn sfarsit, sa calculam sirul {$T{~i~} = A{~i~} + B{~i~}$}.\r\n{$T{~i~} = A{~i~} + B{~i~} = A{~i-1~} + A{~i-3~} + 2 + B{~i-1~} + A{~i-2~} = (A{~i-1~} + A{~i-3~}) + (B{~i-1~} + B{~i-3~}) + (A{~i-2~} - B{~i-3~}) + 2 = T{~i-1~} + T{~i-3~} + (A{~i-2~} - B{~i-3~}) + 2$}. Dupa cum am observat mai devreme $A{~i-2~} - B{~i-3~} = 2 * (i - 3)$ => {$T{~i~} = T{~i-1~} + T{~i-3~} + 2 * (i - 2)$}, ceea ce ne propusesem sa demonstram.\r\n\r\nPunctajele se obtin in modul urmator:\r\n\r\n* $O(N^2^)$ timp, $O(N)$ memorie ~ $50%$\r\n* $O(N)$ timp, $O(N)$ memorie ~ $70%$\r\n* $O(N)$ timp, $O(1)$ memorie ~ $90-100%$\r\n\r\nh2. Desc\r\n\r\nh3. (clasa a 10-a problema grea, clasele 11-12 problema usoara)\r\n\r\nO observatie evidenta ar fi faptul ca in cadrul produsului nu vor aparea decat divizorii lui {$N$}. De aceea vom creea vectorul $dvz$ care contine toti cei $D$ divizori ai lui N. In continuare se va construi matricea {$A$}, unde elementul {$A{~i,j~}$}  va retine numarul de posibilitati de a obtine divizorul {$i$}, folosind divizorii {$j$}, {$j+1$}, ..., $D$. Aceasta se va construi in ordine descrescatoare a coloanelor. Initial $A{~i,j~}= A{~i,j+1~}$  deoarce se vor folosi aceleasi moduri de descompunere folosind divizorii {$j+1$}, {$j+2$}, ..., {$D$}, apoi vom lua in considerare cazul in care se foloseste divizorul {$j$}. Pentru asta trebuie ca {$dvz{~j~}$}  sa divida pe {$dvz{~i~}$}, iar in acest caz vom adauga la $A{~i,j~}$  pe $A{~X,j~}$  unde $X$  este indicele divizoului {$dvz{~i~}/dvz{~j~}$}. Procesarea unei coloane trebuie sa se faca crescator deoarece {$X < i$}. Cautarea lui X se poate face fie binar, dar daca ne uitam mai atent vom observa ca valorile lui {$X$} sunt crescatoare deci putem continua cautarea liniar de la pasul la care ne oprisem pentru {$i-1$}. Acest lucru va asigura o complexitate totala {$O(D)$} pentru fiecare coloana a matricii. Complexitatea totala rezultand {$O(D^2^)$}. Singura initializare care trebuie facuta va fi {$A{~0,i~} = 1$} pentru {$1 &#8804; i &#8804; D$} deoarce se considera ca se poate obtine produsul $1$ intr-un singur mod, iar rezultatul se va gasi in {$A{~D,1~}$}.\r\n\r\nPentru a gasi cea de a {$K$}-a descompunere a lui $N$ ne vom folosi de aceasta matrice. Incercam pe rand sa punem fiecare divizor pe prima pozitie. Cand punem divizorul $i$ pe prima pozitie vom avea $A{~X,i~}$ posibilitati unde $X$ reprezinta indicele divizorului {$N/dvz{~i~}$}. Daca numarul acestor posibilitati este mai mic strict decat $K$ se va scadea acest numar din $K$ deoarece toate descompunerile care incep cu $dvz{~i~}$ sunt mai mici lexicografic decat varianta cautata de noi. Daca numarul acestor posibilitati este mai mare sau egal cu $K$ atunci descompunerea cautata de noi incepe cu {$dvz{~i~}$} si vom cauta in continuare a {$K$}-a descompunere pentru $N/dvz{~i~}$ folosind insa divizori mai mari decat {$dvz{~i~}$}. \r\n\r\nh2. Struti\r\n\r\nh3. (clasele 11-12 problema medie)\r\n\r\nVom incerca sa rezolvam fiecare oferta in {$O(M*N)$}, complexitatea finala a algoritmului fiind astfel {$O(P*M*N)$}. Matricea de altitudini o vom nota cu mat. Intai vom determina maximul pe portiuni dreptunghiulare de forma [{$i,j$}]-[{$i+DX-1,j+DY-1$}], iar apoi, prin aceeasi metoda vom afla si minimul. Pentru a afla maximul pe astfel de portiuni, vom nota cu {$MAX{~i,j~} = max{mat{~i,j~}, mat{~i+1,j~} ... mat{~i+DX-1,j~}}$}. Pentru fiecare coloana, vom utiliza o stiva sortata crescator dupa linii si descrescator dupa valoare altitudinilor. Stiva va retine elemente situate pe pozitii intre $i$ si {$i+DX-1$}, cu altitudinile sortate descrescator.\r\n\r\nDaca avem stiva construita la linia {$i$}, atunci pentru linia urmatoare vom scoate primul element din stiva doar daca pozitia pe care se afla este mai mica sau egala cu {$i$}, iar elementul curent il vom introduce pentru a mentine stiva ordonata. Complexitatea acestui pas este {$O(M*N)$}, pe fiecare coloana efectuandu-se $O(M)$ operatii, pentru ca fiecare element este introdus si scos din stiva exact o data. Pentru a afla maximul intregii portiuni dreptunghiulare, aplicam acelasi procedeu, notand: {$MAX2{~i,j~} = max{MAX{~i,j~}, MAX{~i,j+1~} ... MAX{~i,j+DY-1~}}$}.\r\n\r\nPentru a afla si minimul pe portiuni se procedeaza similar.\r\n\r\nIn plus, pentru o oferta vom procesa atat perechea ({$DX, DY$}), cat si ({$DY, DX$}), daca si numai daca {$DX$} diferit de {$DY$}. Altfel, vom procesa doar ({$DX, DY$}).\r\n\r\nh2. Camera\r\n\r\nh3. (clasele 11-12 problema grea)\r\n\r\nProblema pare la prima vedere destul de complicata. O solutie posibila ar fi sa pornim cu poligonul initial si sa il intersectam cu cate o dreapta determinata de fiecare din laturile lui. Aceasta rezolvare ar putea parea destul de complicata pentru ca implica intersectii de drepte cu poligoane concave. Zona din care toate laturile poligonului sunt vizibile este cunoscuta sub numele de nucleu sau kernel in engleza. Pentru ca dintr-un punct sa fie vizibila o latura a poligonului, acest punct trebuie sa fie in semiplanul determinat de aceasta latura. De aici deducem ca nucleul poligonului este de fapt intersectia celor $N$ semiplane determinate de laturile poligonului. Pornim la inceput cu o zona patrata care contine toate punctele poligonului, astfel ea va contine si nucleul poligonului. Vom taia pe rand cu semiplane acest patrat. Poligonul intermediar va fi tot timpul convex, ceea ce ne usureaza cu mult rezolvarea. Vedem in urmatoarea imagine un exemplu al pasilor algoritmului:\r\n\r\n!preoni-2006/runda-2/solutii?nucleu1.jpg!\r\n\r\nParcurgem laturile poligonului intr-o ordine oarecare. Vom avea doi pointeri $cur$ si $next$ care vor reprezenta doua varfuri consecutive de pe poligonul care e solutia curenta. Daca ambele puncte sunt in interiorul semiplanului, atunci solutiei urmatoare ii adaugam punctul urmator. Daca punctul curent e in interior si punctul urmator este in exterior atunci solutiei ii adaugam punctul de intersectie {$p$}. Daca ambele puncte sunt in exterior procesam urmatoarea pereche. Daca punctul curent e in exterior si urmatorul punct este in interior atunci solutiei ii adaugam punctul de intersectie $p$ si punctul urmator. Astfel obtinem un algoritm de complexitate {$O(n^2^)$}. Mentionam ca acest algoritm poate fi folosit si la determinarea intersectiei a doua poligoane convexe.\r\n\r\n!preoni-2006/runda-2/solutii?nucleu2.jpg!\r\n\r\n',9232,'public',NULL,NULL),('stelele-2009/11-12','Stelele Informaticii 2009, clasele 11-12','2009-02-03 20:52:01','2009-02-03 21:18:17','h1. Stelele Informaticii 2009, clasele 11-12\r\n\r\np=. !template/todo?progress.gif! _In curand..._\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!',1792,'protected',NULL,NULL),('stelele-2009/9-10/runda-1','Stelele Informaticii 2009, clasele 9-10, ziua 1','2009-02-03 20:06:14','2009-02-03 21:50:39','h1. == roundparam(round_id=\"stelele-2009-runda1-9-10\" param=\"title\") ==\r\n\r\n\r\n(htabs)* \'Despre...\':stelele-2009/9-10\r\n*(active) \'Ziua 1\':stelele-2009/9-10/runda-1 \r\n* \'Ziua 2\':stelele-2009/9-10/runda-2\r\n* \'Rezultate\':stelele-2009/9-10/clasament\r\n\r\n== roundregister(round_id=\"stelele-2009-runda1-9-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"stelele-2009-runda1-9-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"stelele-2009-runda1-9-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':stelele-2009/9-10/clasament/runda-1.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"stelele-2009-runda1-9-10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"71\" count=\"5\")==',1792,'round: stelele-2009-runda1-9-10',NULL,NULL),('stelele-2009/9-10/clasament/runda-2','Stelele Informaticii 2009, clasele 9-10, ziua 2','2009-02-03 21:54:57','2009-02-03 22:07:54','h1. Clasament \'Stelele Informaticii 2009, clasele 9-10, ziua 2\':stelele-2009/9-10/runda-2\r\n\r\np<. == Rankings(rounds=\"stelele-2009-runda2-9-10\") == ',1792,'protected',NULL,NULL),('stelele-2009/9-10/clasament','Stelele Informaticii 2009, clasele 9-10','2009-02-03 21:52:03','2009-02-03 22:08:23','h1. Clasament \'Stelele Informaticii 2009, clasele 9-10\':stelele-2009/9-10\r\n\r\n(htabs)* \'Despre...\':stelele-2009/9-10\r\n* \'Ziua 1\':stelele-2009/9-10/runda-1 \r\n* \'Ziua 2\':stelele-2009/9-10/runda-2\r\n*(active) \'Rezultate\':stelele-2009/9-10/clasament\r\n\r\nAcesta este clasamentul cumulat al celor 2 probe\r\n\r\n== Rankings(rounds=\"stelele-2009-runda1-9-10 | stelele-2009-runda2-9-10\") ==\r\n\r\n',1792,'protected',NULL,NULL),('stelele-2009','Stelele Informaticii 2009','2009-02-03 20:45:18','2009-02-03 21:40:38','h1. Stelele Informaticii 2009\r\n\r\n_Stelele Informaticii_ este un concurs anual organizat şi găzduit de \"Liceul Internaţional de Informatică Bucureşti\":http://www.ichb.ro/. Prima ediţie a concursului a avut loc în noiembrie 2003.\r\n\r\nLa acest concurs sunt invitaţi să participe toţi elevii care au obţinut premii la Olimpiadele Naţionale de Informatică sau au fost incluşi în loturile de pregătire pentru concursurile internaţionale. În funcţie de locurile disponibile mai participa şi alţi elevi. Scopul competiţiei este de a constitui o primă întrecere a elevilor talentaţi în programare, o avanpremieră a competiţiilor care vor urma pe parcursul anului şcolar. Concursul se desfăşoară separat pentru clasele IX-X şi gimnaziu, respectiv XI-XII.\r\n\r\nDeşi concursul este pe bază de invitaţie, începând din acest an, infoarena iţi ofera în premieră ocazia să concurezi cot la cot cu participanţii onsite. Este o ocazie excelentă să-ţi verifici cunostinţele înainte de debutul olimpiadei.\r\n\r\nh2. Cum particip?\r\n\r\nPentru a participa la concurs trebuie să fii \'înregistrat\':register pe site-ul nostru.\r\n\r\nÎn ziua de concurs intri pe site, citeşti problemele de la grupa ta de vârstă şi trimiţi soluţiile înainte de expirarea timpului. \'Evaluatorul\':documentatie/evaluator nostru iţi va testa automat soluţiile iar punctajul îl vei afla la sfârşitul concursului. Tot atunci vei putea consulta clasamentul pentru a vedea ce au făcut şi ceilalţi concurenţi.\r\n\r\nh3. Prima dată pe _infoarena_?\r\n\r\n_infoarena_ ajută elevi şi studenţi să devină excelenţi în informatică! Gratuit ;) Citeşte \'ghidul utilizatorului\':documentatie/pentru-utilizatori şi află mai multe \'despre noi\':despre-infoarena.\r\n\r\nh2. Program concurs\r\n\r\ntable{width: 50%}. |_. Etapa |_. Data |\r\n| \"Stelele Informaticii 2009, clasele 9-10\":stelele-2009/9-10 | *6-7 februarie 2009* |\r\n| \"Stelele Informaticii 2009, clasele 11-12\":stelele-2009/11-12 | *Va urma* | \r\n',15,'protected',NULL,NULL),('stelele-2009/9-10/clasament/runda-1','Clasament Stelele Informaticii 2009, clasele 9-10, ziua 1','2009-02-03 21:45:34','2009-02-03 22:06:57','h1. Clasament \'Stelele Informaticii 2009, clasele 9-10, ziua 1\':stelele-2009/9-10/runda-1\r\n\r\np<. == Rankings(rounds=\"stelele-2009-runda1-9-10\") == ',1792,'protected',NULL,NULL),('stelele-2009/9-10','Stelele Informaticii 2009, clasele 9-10','2009-02-03 20:03:14','2009-02-03 22:00:15','h1. Stelele Informaticii 2009, clasele 9-10\r\n\r\n(htabs)*(active) \'Despre...\':stelele-2009/9-10\r\n* \'Ziua 1\':stelele-2009/9-10/runda-1 \r\n* \'Ziua 2\':stelele-2009/9-10/runda-2\r\n* \'Rezultate\':stelele-2009/9-10/clasament\r\n\r\nConcursul se desfasoara pe doua probe. In fiecare proba, participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii la proba corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi probe, concurentii se pot inscrie pentru a participa la proba respectiva. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\nh2. Probleme\r\n\r\nClick pe proba potrivita&hellip;\r\n\r\n* \'Ziua 1\':stelele-2009/9-10/runda-1\r\n* \'Ziua 2\':stelele-2009/9-10/runda-2\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Ziua 1\':stelele-2009/9-10/clasament/runda-1\r\n* \'Ziua 2\':stelele-2009/9-10/clasament/runda-2\r\n\r\nClasamentul final va aparea \'aici\':stelele-2009/9-10/clasament.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"71\" count=\"5\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==User(user=\"silviug\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"efer\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"domino\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n',1792,'protected',NULL,NULL),('stelele-2009/9-10/runda-2','Stelele Informaticii 2009, clasele 9-10, ziua 2','2009-02-03 20:07:21','2009-02-03 21:50:16','h1. == roundparam(round_id=\"stelele-2009-runda2-9-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':stelele-2009/9-10\r\n* \'Ziua 1\':stelele-2009/9-10/runda-1 \r\n*(active) \'Ziua 2\':stelele-2009/9-10/runda-2\r\n* \'Rezultate\':stelele-2009/9-10/clasament\r\n\r\n== roundregister(round_id=\"stelele-2009-runda2-9-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"stelele-2009-runda2-9-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"stelele-2009-runda2-9-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':stelele-2009/9-10/clasament/runda-2.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"stelele-2009-runda2-9-10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"71\" count=\"5\")==',1792,'round: stelele-2009-runda2-9-10',NULL,NULL),('template/newsletter/implica-te','template/implica-te','2009-02-04 00:14:16','2009-02-04 00:21:05','h2{font-size: 12pt}. Fii un bun infoarenaut! Implică-te! \r\n\r\ninfoarena este un efort colectiv, munca a zeci de voluntari pe parcursul a 5 ani de zile. Vrem să-i sprijinim pe toţi cei care, pasionaţi de informatică şi programare, vor să înveţe mai mult, vor să îşi perfecţioneze abilităţile.\r\n\r\nVrei să compui problemele tale? Vrei să organizezi concursuri? Îţi place să programezi, doreşti să înveţi cum se dezvoltă un site precum infoarena? Vrei să redactezi articole despre algoritmi şi structuri de date? Pentru toate acestea, şi pentru multe altele, poţi să ni te alături!\r\n\r\n\'*Implică-te în comunitatea infoarena!*\':implica-te\r\n',13,'protected',NULL,NULL),('template/newsletter/rating','template/newsletter/rating','2009-02-04 00:08:21','2009-02-04 00:26:55','h2{font-size: 12pt}. Atenţie! Concurs cu rating!\r\n\r\nDacă vrei să ţi se modifice \'rating-ul\':documentatie/rating în urma acestei runde trebuie să îţi anunţi participarea din timp. Intră pe \'pagina concursului\':%round_url% şi înscrie-te. ==NewsletterRating(username=\"%username%\")==\r\n\r\nPoţi să participi la concurs chiar şi dacă nu te-ai înscris în prealabil însă nu ţi se va modifica \'rating-ul\':documentatie/rating.\r\n',13,'protected',NULL,NULL),('template/newsletter/prima-data','template/prima-data','2009-02-04 00:11:25','2009-12-15 16:57:21','h2{font-size: 12pt}. Prima dată pe infoarena? \r\n\r\nCiteşte \'tutorialul infoarena\':documentatie/tutorial, află mai multe \'despre noi\':despre-infoarena şi antrenează-te cu probleme \'educaţionale\':arhiva-educationala sau de \'concurs\':arhiva.\r\n',1792,'protected',NULL,NULL),('template/newsletter/doi-la-suta','template/newsletter/doi-la-suta','2009-02-04 01:37:03','2009-02-04 12:24:18','h2{font-size: 12pt}. Mulţumim pentru sprijin!\r\n\r\nPeste 50 de persoane au sprijinit \'Asociaţia infoarena\':asociatia-infoarena direcţionând 2% din impozitul pe venit în anul fiscal 2008. Am fost surprinşi într-un mod plăcut de aceste contribuţii. Ne bucurăm că munca pe care o depunem este apreciată.\r\n\r\nDacă susţii proiectul infoarena, atunci te rugăm să afli mai multe despre aceste contribuţii, cum vor fi folosite şi de ce sunt imporante pentru noi: \'2% pentru infoarena\':blog/doi-la-suta-2008-raport.\r\n\r\nTermenul limită este *15 mai 2009*.',13,'protected',NULL,NULL),('documentatie/tutorial','Tutorial infoarena','2007-01-18 14:10:59','2009-05-03 19:01:54','h1. Tutorial infoarena\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nh2. Cum rezolv probleme?\r\n\r\nh3. Alege o problema\r\n\r\nIn \'arhiva de probleme\':arhiva gasesti o serie impresionanta de probleme (peste 800) adunate in cei patru ani de functionare a site-ului. Daca vrei sa incepi cu ceva mai usor poti incerca \'arhiva educationala\':arhiva-educationala unde gasesti probleme clasice cu tot cu sugestii de rezolvare.\r\n\r\nOdata ce ai ajuns intr-una din arhive poti alege o problema facand click pe ea. In momentul acesta poti citi problema si suntem siguri ca deja ai idei despre cum se rezolva :) Cand una din ideile tale s-a concretizat intr-o sursa scrisa intr-unul din \'limbajele acceptate\':documentatie/evaluator poti trece la ...\r\n\r\nh3. Trimiterea solutiei\r\n\r\nPentru a trimite o sursa trebuie sa fii autentificat. Daca nu ai inca un cont infoarena fa bine si te \'inregistreaza\':register ca merita :).\r\n\r\nOdata autentificat acceseaza \'Trimite solutii\':submit din menu-ul din stanga. Vei avea de completat urmatoarele informatii:\r\n\r\n* problema pentru care vrei sa trimiti solutia (da click pe lista corespunzatoare si apoi tasteaza numele problemei)\r\n* fisierul sursa (vei indica unde se gaseste sursa pe calculatorul tau)\r\n* compilatorul pe care il vrei (in mod normal, acesta se completeaza automat daca este recunoscuta extensia sursei)\r\n\r\nAceiasi pasi poti sa-i faci si daca ai deschis o problema folosind campurile din josul paginii. Ai ghicit, sursa trebuie sa fie pentru problema care e deschisa ;)\r\n\r\nAcum gata poti apasa butonul _Trimite solutia_ si astepta mesajul de confirmare. Hai apasa ca nu explodeaza! :)\r\n\r\nh3. Ce punctaj ai luat?\r\n\r\nPentru a afla ce punctaj a acumulat solutia ta, mergi in \'monitorul de evaluare\':monitor.\r\n\r\nFelicitari, ai trimis prima ta sursa pe infoarena! Sper ca ai luat 100!\r\n\r\nh2. Articole _infoarena_\r\n\r\nN-ai avut noroc? Simti ca poti mai mult si ai vrea sa inveti?\r\n\r\ninfoarena are ca scop primar excelenta in informatica, nu evaluam numai surse :). Avem o serie de \'articole\':articole despre Algoritmi, Structuri de date, Geometrie analitica, Limbaje de programare si chiar Matematica. De asemenea, pentru multe din problemele din arhiva, mai exact cele din concursurile organizate _infoarena_, poti gasi idei de rezolvare in articolul cu solutii asociat concursului.\r\n\r\nDaca stii prea multe si simti nevoia sa ne demonstrezi si noua acest lucru sau daca pur si simplu vrei sa lasi ceva in urma ta pe pamant te incurajam sa scrii \'articole noi\':implica-te/scrie-articole si sa le imbunatatesti pe cele existente.\r\n\r\nh2. Alte resurse\r\n\r\nDin nou o sa te batem la cap cu comunitatea: daca vrei sa discuti despre o anumita problema sau alte lucruri care despre informatica si programare acceseaza \'forumul infoarena\':forum. \r\n\r\n_infoarena_ iti pune la dispozitie o multitudine de download-uri la sectiunea \"Downloads\":downloads. Acolo poti gasi problemele si testele la cateva concursuri importante, articole si utilitare.\r\n\r\nMai poti gasi o multime de link-uri catre site-uri interesante in sectiunea \'Links\':links.\r\n\r\n\r\n',2028,'public',NULL,NULL),('utilizator/metalkitten','Profil metalkitten','2009-02-04 15:26:15','2010-04-13 14:22:14','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n* _(Buna, sunt a 9a la CNVA Galati. Pot sa zic ca am unele pasiuni, printre care si sa stau(asta fiind cea mai mare pasiune a mea). Fac info din a 5a, dar niciodata nu am reusit sa ma mobilizez sa lucrez. Ca dovada numarul de probleme rezolvate de pe infoarena. Am vrut sa ma duc la ICHB din a 9a, da` tot in Galati am ramas. Ce sa zic... imi place sa ascult muzica, sa ies cu prietenii, sa ma distrez, sa ma joc, imi place marea si sufar de frig. Si nu pot sa zic \"L\".)_\r\n\r\nh2. Distinctii primite\r\n\r\n* Clasa a 5a\r\nLocul I la OJI(pe Galati si pe tara, cu 200 p)\r\nParticipare la ONI Targoviste\r\nLocul I la Concursul Centrelor de Excelenta Suceava(clasele 5-6)\r\n\r\n* Clasa a 6a\r\nLocul I la OJI(pe Galati)\r\nParticipare la ONI Cluj-Napoca\r\nLocul I la Concursul InfoCNVA\r\n\r\n* Clasa a 7a\r\nLocul I la OJI(pe Galati)\r\nParticipare la ONI Bacau\r\n\r\n* Clasa a 8a\r\nLocul I la OJI(pe Galati)\r\nParticipare la ONI Galati\r\nCalificare la baraj\r\n\r\n* Clasa a 9a\r\nLocul I la OJI(pe Galati)\r\nMedalie de bronz la ONI Constanta(2 locuri sub mentiune si baraj, damn it!:)) )\r\n',9503,'public',NULL,NULL),('runda/runda_a_2-1/clasament','Clasament runda_a_2-1','2009-03-29 11:48:11','2009-03-29 11:48:11','h1. Clasament ==roundparam(round_id=\"runda_a_2-1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"runda_a_2-1\")==',6490,'round: runda_a_2-1',NULL,NULL),('algoritmiada-2009/runda-3','Algoritmiada 2009, Runda 3','2008-11-30 16:35:23','2009-02-12 12:52:58','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Algoritmiada 2009, Runda 3\r\n\r\n(htabs)*(active) \'Despre...\':algoritmiada-2009/runda-3 \r\n* \'Clasele 5-8\':algoritmiada-2009/runda-3/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2009/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-3/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-3/5-8 \r\n\r\nRunda va incepe *Duminica 15 februarie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-3/studenti\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':algoritmiada-2009/runda-3/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-3/studenti\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==User(user=\"prostu\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"domino\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('algoritmiada-2009/runda-3/5-8','Algoritmiada 2009 - Runda 3, Clasele 5-8','2009-02-05 15:32:35','2009-02-05 15:32:35','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda3-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-3 \r\n*(active) \'Clasele 5-8\':algoritmiada-2009/runda-3/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2009/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-3/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-3/5-8\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda3-5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda3-5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda3-5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-3/5-8.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda3-5-8\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('algoritmiada-2009/runda-3/9-10','Algoritmiada 2009 - Runda 3, Clasele 9-10','2009-02-05 15:39:04','2009-02-05 15:39:04','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda3-9-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-3 \r\n* \'Clasele 5-8\':algoritmiada-2009/runda-3/5-8 \r\n*(active) \'Clasele 9-10\':algoritmiada-2009/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-3/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-3/9-10\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda3-9-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda3-9-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda3-9-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-3/9-10.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda3-9-10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('algoritmiada-2009/runda-3/11-12','Algoritmiada 2009 - Runda 3, Clasele 11-12','2009-02-05 15:48:42','2009-02-05 15:48:42','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda3-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-3 \r\n* \'Clasele 5-8\':algoritmiada-2009/runda-3/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2009/runda-3/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2009/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-3/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-3/11-12\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda3-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda3-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda3-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-3/11-12.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda3-11-12\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('algoritmiada-2009/runda-3/studenti','Algoritmiada 2009 - Runda 3, Studenti','2009-02-05 15:54:06','2009-02-05 15:54:06','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda3-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-3 \r\n* \'Clasele 5-8\':algoritmiada-2009/runda-3/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2009/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-3/11-12\r\n*(active) \'Studenti\':algoritmiada-2009/runda-3/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-3/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda3-studenti\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda3-studenti\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda3-studenti\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-3/studenti.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda3-studenti\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('algoritmiada-2009/clasament/runda-3/studenti','Algoritmiada 2009 - Clasament Runda 3, Studenti','2009-02-05 16:03:23','2009-02-05 16:08:33','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda3-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-3\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-3/studenti\r\n*(active) \'Rezultate\':algoritmiada-2009/clasament/runda-3/studenti\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-3/11-12\r\n*(active) \'Studenti\':algoritmiada-2009/clasament/runda-3/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda3-studenti\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('algoritmiada-2009/clasament/runda-3/5-8','Algoritmiada 2009 - Clasament Runda 3, Clasele 5-8','2009-02-05 16:05:06','2009-02-05 16:05:06','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda3-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-3\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-3/studenti\r\n*(active) \'Rezultate\':algoritmiada-2009/clasament/runda-3/5-8\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasele 5-8\':algoritmiada-2009/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-3/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda3-5-8\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('algoritmiada-2009/clasament/runda-3/9-10','Algoritmiada 2009 - Clasament Runda 3, Clasele 9-10','2009-02-05 16:06:24','2009-02-05 16:06:24','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda3-9-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-3\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-3/studenti\r\n*(active) \'Rezultate\':algoritmiada-2009/clasament/runda-3/9-10\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-3/5-8\r\n*(active) \'Clasele 9-10\':algoritmiada-2009/clasament/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-3/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda3-9-10\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('algoritmiada-2009/clasament/runda-3/11-12','Algoritmiada 2009 - Clasament Runda 3, Clasele 11-12','2009-02-05 16:07:31','2009-02-05 16:07:31','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda3-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-3\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-3/studenti\r\n*(active) \'Rezultate\':algoritmiada-2009/clasament/runda-3/11-12\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-3/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2009/clasament/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-3/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda3-11-12\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('runda/concurs_nou1','concurs_nou1','2009-03-29 13:43:05','2009-03-29 13:43:05','h1. == roundparam(round_id=\"concurs_nou1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"concurs_nou1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"concurs_nou1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"concurs_nou1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/concurs_nou1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"concurs_nou1\" score=\"1\")==',9995,'round: concurs_nou1',NULL,NULL),('algoritmiada-2009','Algoritmiada 2009 - olimpiada algoritmilor','2008-11-30 14:01:47','2009-04-01 17:36:16','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh2. Despre Algoritmiada\r\n\r\nIncepând de anul acesta, _infoarena_ organizează concursul de programare Algoritmiada. La acest concurs pot participa, în premieră pe ţară, tineri pasionaţi de informatică de toate vârstele: de la elevi de gimnaziu până la studenţi şi doctoranzi.\r\n\r\nConcursul are patru grupe valorice: gimnaziu, clasele 9-10, clasele 11-12, studenţi (inclusiv masteranzi şi doctoranzi). Participanţii vor avea ocazia să-şi demonstreze talentul, cunostinţele şi iuţimea minţii în 3 probe online urmând ca cei mai buni sa fie invitaţi la finala on-site.\r\n\r\nh2. Cum particip?\r\n\r\nPentru a participa la concurs trebuie să fii \'înregistrat\':register pe site-ul nostru.\r\n\r\nÎn ziua de concurs intri pe site, citeşti problemele de la grupa ta de vârstă şi trimiţi soluţiile înainte de expirarea timpului. \'Evaluatorul\':documentatie/evaluator nostru iţi va testa automat soluţiile iar punctajul îl vei afla la sfârşitul concursului. Tot atunci vei putea consulta clasamentul pentru a vedea ce au făcut şi ceilalţi concurenţi.\r\n\r\nh3. Prima dată pe _infoarena_?\r\n\r\n_infoarena_ ajută elevi şi studenţi să devină excelenţi în informatică! Gratuit ;) Citeşte \'ghidul utilizatorului\':documentatie/pentru-utilizatori şi află mai multe \'despre noi\':despre-infoarena.\r\n\r\nh2. Program\r\n\r\nFaceţi click pe titlul unei runde pentru informaţii detaliate.\r\n\r\ntable{width:50%}. |_. Runda |_. Data |_. Durata |\r\n| \'*Runda 1*\':algoritmiada-2009/runda-1 | *14 Decembrie 2008, Duminică* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 2*\':algoritmiada-2009/runda-2 | *11 Ianuarie 2009, Duminică* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 3*\':algoritmiada-2009/runda-3 | *15 Februarie 2009, Duminică* |=. *09^00^ - 13^00^* |\r\n| \'*Runda Finală*\':algoritmiada-2009/runda-finala | *2 Mai 2009, Sâmbătă* |=. *09^00^ - 13^00^*|\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('concursul-de-informatica','Concursul de informatica (de la agonie la extaz)','2008-02-03 17:43:07','2009-02-27 00:09:51','h1. Concursul de informatica (de la agonie la extaz)\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"Cyber\") ==\r\n\r\n(Categoria _Diverse_, Autor _Catalin Francu_, Preluat din cartea _\"Psihologia concursurilor de informatica\"_)\r\n\r\n(toc){width: 25em}*{text-align:center} *Conţinut:*\r\n* \'Inainte de concurs\':concursul-de-informatica#inainte-de-concurs\r\n* \'In timpul concursului\':concursul-de-informatica#in-timpul-concursului\r\n* \'Strategii de abordare a problemelor\':concursul-de-informatica#strategii\r\n* \'Concluzii\':concursul-de-informatica#concluzii\r\n\r\nbq. \"Cine doreste sa-si rezolve treburile la vremea potrivita, sa-si imparta cu atentie timpul\" - Plaut\r\n\r\nExperienta demonstreaza ca, oricat de mare ar fi bagajul de cunostinte acumulat de un elev, mai e nevoie de ceva pentru a-i asigura succesul la olimpiada de informatica. Aceasta deoarece in timp de concurs lucrurile stau cu totul altfel decat in fata calculatorului de acasa sau de la scoala. Reusita depinde, desigur, in cea mai mare masura de puterea fiecaruia de a pune in practica ceea ce a invatat acasa. Numai ca in acest proces intervin o serie de factori care tin de temperament, de experienta individuala, de numarul de ore dormite in noaptea dinaintea concursului (care in taberele nationale este ingrijorator de mic) si asa mai departe. \r\n\r\nCu riscul de a cadea in demagogie, trebuie sa spunem ca un concurs de informatica presupune mult mai mult decat un simplu act de prezenta la locul desfasurarii ostilitatilor. Articolul de fata incearca sa enunte cateva principii ale concursului, pe care autorul si le-a insusit in cei patru ani de liceu, atat din experienta proprie, cat si invatand de la altii. Cititorul este liber sa respinga aceste sfaturi sau sa le accepte, filtrandu-le prin prisma personalitatii sale si alegand ceea ce i se potriveste.\r\n\r\nh2(#inainte-de-concurs). Inainte de concurs\r\n\r\nPrimul si cel mai de seama lucru pe care trebuie sa il stiti este ca e important si sa participi, dar e si mai important sa participi onorabil, iar daca se poate sa si castigi. Nu trebuie sa porniti la drum cu ingamfare; modestia e buna, dar nu trebuie in nici un caz sa duca la neincredere in sine. Fiecare trebuie sa stie clar de ce e in stare si, mai presus de toate, sa se gandeasca ca la urma urmei nu dificultatea concursului conteaza, caci concursul, greu sau usor, este acelasi pentru toti. Mult mai importanta este valoarea individuala si nu in ultimul rand pregatirea psihologica.\r\n\r\nAutorul a fost peste masura de surprins sa constate ca multi elevi merg la concurs fara ceas si fara hartie de scris. Aceasta este fara indoiala o greseala capitala. In timpul concursului trebuie tinuta o evidenta drastica a timpului scurs si a celui ramas. E drept ca in general supraveghetorii anunta din cand in cand timpul care a trecut, dar e bine sa nu va bazati pe nimeni si nimic altceva decat pe voi insiva. Unii colegi spuneau \"Ei, ce nevoie am de ceas? Oricum am ceasul calculatorului la indemana.\". Asa e, dar e extrem de incomod sa te opresti mereu la jumatatea unei idei, sa iesi din mediul de programare (in cazul celor sub DOS) si sa afli cat e ceasul.\r\n\r\nIn ceea ce priveste hartia de scris, ea este in mod sigur necesara. De fapt, o parte importanta a rezolvarii unei probleme este proiectarea matematica a algoritmului, lucru care nu se poate face decat cu creionul pe hartie. Pe langa aceasta, majoritatea problemelor opereaza cu vectori, matrice, arbori, grafuri etc., iar exemplele pe care este testat programul realizat trebuie neaparat verificate \"de mana\". E de preferat sa aveti hartie de matematica; este foarte folositoare pentru problemele de geometrie analitica, precum si pentru reprezentarea matricelor. Cantitatea depinde de imaginatia fiecaruia. In unele cazuri speciale, autorului i s-a intamplat sa umple 7-8 coli A4.\r\n\r\nh2(#in-timpul-concursului). In timpul concursului\r\n\r\nDin fericire pentru unii si din nefericire pentru altii, majoritatea examenelor iti cer sa dovedesti nu ca esti bine pregatit, ci ca esti mai bine pregatit decat altii. Aceasta inseamna ca si la olimpiada de informatica se aplica legea pestelui mai mare sau, cum i se mai spune, a concurentei. Valoarea absoluta a fiecaruia nu conteaza chiar in totalitate, ceea ce constituie sarea si piperul concursului. Intr-adevar, ce farmec ar avea sa mergi la un concurs la care se stie inca dinainte cine este cel mai bun? Este destul de amuzant sa observi cum fiecare spera sa prinda \"o zi buna\", iar adversarii sai \"o zi proasta\".\r\n\r\nEste usor sa fii printre cei mai buni atunci cand concursul este usor. Mai greu e sa fii cel mai bun atunci cand concursul este dur, pentru ca atunci intervine - inevitabil - dramul de noroc al fiecaruia. Niciodata insa nu se poate invoca greutatea concursului drept o scuza pentru un eventual esec. Concursul este la fel de greu pentru toti. Se poate intampla, mai ales daca probele dureaza mai multe zile (3-4) ca nici unul din concurenti sa nu acumuleze mai mult de 70-80% din punctajul maxim. Totusi, aceasta nu inseamna ca ei nu sunt bine pregatiti; mai mult, unul dintre ei trebuie sa fie primul. Asadar, niciodata nu trebuie adoptata o strategie de genul \"problema asta e grea si n-am s-o pot rezolva perfect, asa ca nu ma mai apuc deloc de ea\". Nu trebuie sa va impacientati daca vi se intampla sa nu aveti o idee geniala de rezolvare a unei probleme. Nu va cere nimeni sa faceti perfect o problema, ci numai sa prezentati o solutie care sa acumuleze cat mai multe puncte. Evident, prima varianta este intotdeauna preferabila, dar nu obligatorie.\r\n\r\nDe multe ori se intampla ca un elev sa gaseasca o solutie cat de cat buna la o problema si, macar ca stie ca nu va lua punctajul maxim, ci doar o parte, sa renunte sa caute o solutie mai eficienta, deoarece timpul pierdut astfel ar aduce un castig prea mic si ar putea fi folosit la rezolvarea altor probleme. Desigur, daca nu faci toate problemele perfect, nu mai poti fi sigur de premiul I, pentru ca altcineva poate sa te intreaca. Dar pe de alta parte, locul pe care te clasezi conteaza numai la etapa nationala a olimpiadei sau la concursurile internationale. In rest, important e numai sa te califici, adica sa intri in primele cateva locuri.\r\n\r\nFeriti-va ca de foc de criza de timp. E mare pacat sa ratezi o problema intreaga pentru ca n-ai avut timp sa scrii procedura de afisare a solutiei. Rezervati-va intotdeauna timpul pe care il socotiti necesar pentru implementare si depanare.\r\n\r\nNiciodata, chiar daca concursul este usor, nu e bine sa iesiti din sala de concurs inainte de expirarea timpului. Oricat ati fi de convinsi ca ati facut totul perfect, mai verificati-va; veti avea de furca cu remuscarile daca descoperiti dupa aceea ca ceva, totusi, nu a mers bine. Puteti face o multime de lucruri daca mai aveti timp (desi acest lucru se intampla rar). Iata o serie de metode de a exploata timpul:\r\n\r\n* Verificati-va programul cu cat mai multe teste de mici dimensiuni. Sa presupunem ca programul vostru lucreaza cu vectori de maxim $10.000$ de elemente. E o idee buna sa il rulati pentru vectori de unul sau doua elemente. Nu se stie cum pot sa apara erori.\r\n\r\n* Treceti la polul opus si creati-va un test de dimensiune maxima, dar cu o structura particulara, pentru care este usor de calculat rezultatul si de mana. De exemplu, vectori de $10.000$ elemente cu toate elementele egale, sau vectori de forma $(1, 2, ..., 9.999, 10.000)$. Daca nu puteti sa editati un asemenea fisier de mana, copiind si multiplicand blocuri, puteti scrie un program care sa-l genereze.\r\n\r\n* Daca inca v-a mai ramas timp, creati-va un program care sa genereze teste aleatoare. Spre exemplu, un program care sa citeasca un numar $N$ si sa creeze un fisier $INPUT.TXT$ in care sa scrie $N$ numere aleatoare. Intr-o prima faza, puteti folosi aceste teste pentru a verifica daca nu cumva la valori mai mari programul da eroare, se blocheaza (la alocarea unor zone mari de memorie) sau depaseste limita de timp, caz in care mai aveti de lucru.\r\n\r\n* Daca tot nu va da nimeni afara din sala, puteti scrie un alt program auxiliar care, primind fisierul $INPUT.TXT$ si fisierul $OUTPUT.TXT$ produs de programul vostru, verifica daca iesirea este corecta. Aceasta deoarece, de obicei, este mult mai usor de verificat o solutie decat de produs una (sau, cum spunea Murphy, \"cunoasterea solutiei unei probleme poate ajuta in multe cazuri la rezolvarea ei\"). Folosind \"generatorul\" de teste si \"verificatorul\", puteti testa programul mult mai bine. De altfel, la multe probleme chiar testele rulate de comisia de corectare sunt create tot aleator.\r\n\r\n* In caz ca ati dat o solutie euristica la o problema NP-completa, puteti implementa si un backtracking ca sa vedeti cat de bune sunt rezultatele gasite euristic. Apoi, puteti incepe sa modificati functia euristica pentru a o face cat mai performanta.\r\n\r\nh2(#strategii). Strategii de abordare a problemelor\r\n\r\nSi ca sa nu mai lungim vorba, iata cateva strategii care par sa dea rezultate.\r\n\r\nh3. A)\r\n\r\nImediat ce primiti problemele, cititi toate enunturile si faceti-va o idee aproximativa despre gradul de dificultate al fiecarei probleme. Neaparat verificati daca se dau limite pentru datele de intrare (numarul maxim de elemente ale unui vector si valoarea maxima a acestora, numarul maxim de noduri dintr-un graf etc.) si pentru timpii de executie pentru fiecare test. Daca nu se dau, intrebati imediat. Dimensiunea input-ului poate schimba radical dificultatea problemei. Spre exemplu, pentru un vector cu $N = 100$ elemente, un algoritm $O(N^3^)$ merge rezonabil, pe cand pentru $N = 10.000$ acelasi algoritm ar depasi cu mult cele cateva secunde care se acorda de obicei. Fair-play-ul cere sa puneti intrebarile cu voce tare, pentru ca si ceilalti sa auda; de altfel, nu aveti nici un motiv sa va feriti de ceilalti concurenti. Cei care sunt interesati de aceste intrebari le-ar pune oricum si ei, iar cei care nu sunt interesati vor ignora oricum raspunsul.\r\n\r\nDaca exista probleme care cer sa se gaseasca un optim (maxim/minim) al unei valori, intrebati daca se acorda punctaje partiale pentru solutii neoptime. Si acest fapt poate schimba natura problemei. Dupa aceasta,\r\n\r\n== code(c) |\r\nNr_probleme_nerezolvate = Nr_probleme_primite;\r\n\r\nwhile ((Nr_probleme_nerezolvate > 0) && !(\"Timpul a expirat, va rugam sa salvati.\")) {\r\n==\r\n\r\nh3. B)\r\n\r\nFaceti o impartire a timpului pentru problemele ramase proportional cu punctajul fiecarei probleme. In general problemele au punctaje egale, dar nu totdeauna. De exemplu, daca o problema e cotata cu 100 puncte, iar alta cu 50, veti aloca de doua ori mai mult timp primei probleme, chiar daca nu vi se pare prea grea. Incercati sa nu depasiti niciodata limitele de timp pe care le-ati fixat. Daca in schimb reusiti sa economisiti timp fata de cat v-ati propus, cu atat mai bine, veti face o realocare a timpului si veti avea mai mult pentru celelalte probleme.\r\n\r\nh3. C)\r\n\r\nApucati-va de problema _cea mai simpla_, chiar daca e punctata mai slab. Mai bine sa duceti la bun sfarsit o problema usoara si sa luati un punctaj mai mic, decat sa va apucati de o problema grea si sa nu terminati niciuna. Daca toate problemele par grele, alegeti-o pe cea din domeniul care va este cel mai familiar, in care ati lucrat cel mai mult. Daca va este indiferent si acest lucru, alegeti o problema unde simtiti ca aveti o idee simpla de rezolvare. Daca, in sfarsit, nu aveti nici o idee la nicio problema, apucati-va de cea mai bine punctata.\r\n\r\nh3. D)\r\n\r\nCititi din nou enuntul, de data aceasta cu mare grija. Intrebati supraveghetorul pentru orice nelamurire. Daca anumite lucruri nu sunt specificate, iar profesorul nu va da nici un fel de informatii suplimentare, tratati problema in cazul cel mai general. Iata mai multe exemple frecvente in care enuntul nu este limpede:\r\n\r\n* Daca nu se precizeaza cat de mari pot fi intregii dintr-un vector, nu lucrati pe $int$, ci pe $long long int$;\r\n	\r\n* In problemele de geometrie analitica, e bine sa presupuneti ca punctele nu au coordonate intregi, ci reale;\r\n\r\n* De asemenea, patratele si dreptunghiurile nu au neaparat laturi paralele cu axele, ci sunt asezate oricum in plan (aceasta poate intr-adevar sa complice extrem de mult problema; nu va doresc sa va izbiti de o asemenea neclaritate...);\r\n	\r\n* Daca fisierul de intrare contine siruri de caractere, sa nu presupuneti ca ele au maxim $255$ de caractere. Mai bine scrieti propria voastra procedura de citire a unui sir de caractere, care sa citeasca din fisier caracter cu caracter pana la sfarsitul de linie, decat sa aveti surprize.\r\n	\r\n* Grafurile nu sunt neorientate, ci orientate. In principiu, enuntul nu are voie sa fie neclar in aceasta privinta, dar au existat cazuri de neintelegere.\r\n\r\nh3. E)\r\n\r\nIncepeti sa va ganditi la algoritmi cat mai buni, estimand in acelasi timp si cat v-ar lua ca sa-i implementati. Faceti, pentru fiecare idee care va vine, calculul complexitatii. Nu trebuie neaparat sa gasiti cel mai eficient algoritm, ci numai unul suficient de bun. In general, trebuie ca, dintre toti algoritmii care se incadreaza in timpul de rulare, sa-l alegeti pe cel care este cel mai usor de implementat.\r\n\r\nSa presupunem ca timpul de testare este de $0.5$ secunde, lucrati pe un Pentium 4, algoritmul vostru are complexitatea $O(N^3^)$, iar $N$ este maxim $100$. Un Pentium 4 face in jur de $10.000.000$ de operatii pe secunda. Programul vostru are timp de rulare cubic, iar $N^3^$ este maxim $1.000.000$. De aici deducem ca programul ar trebui sa se incadreze in $0.1$ secunde. Calculul nostru este grosier, dar luand si o marja de eroare arhisuficienta, rezulta ca programul trebuie sa mearga cu usurinta in $0.5$ secunde, deci algoritmul este acceptabil.\r\n\r\nh3. F)\r\n\r\nDaca algoritmul gasit este greu de implementat, mai cautati un altul o vreme. Trebuie insa ca timpul petrecut pentru gasirea unui nou algoritm plus timpul necesar pentru scrierea programului sa nu depaseasca timpul necesar pentru implementarea primului algoritm, altfel nu castigati nimic. Deci nu exagerati cu cautarile si nu incercati sa reduceti dincolo de limita imposibilului complexitatea algoritmului. Mai ales, nu uitati ca programul nu poate avea o complexitate mai mica decat dimensiunea input-ului sau a output-ului. De exemplu, daca programul citeste sau scrie matrice de dimensiune $N x N$, nu are sens sa va bateti capul ca sa gasiti un algoritm mai bun decat $O(N^2^)$.\r\n\r\nh3. G)\r\n\r\nDintre toate ideile de implementare gasite (care se incadreaza fara probleme in timp), o veti alege pe cea mai scurta ca lungime de cod. De exemplu:\r\n\r\n* Daca $N &le; 1.000$ si dispuneti de doi algoritmi, unul pe care il estimati cam la $200$ de linii de program, de complexitate $O(N*log N)$ si unul de $100$ de linii de complexitate $O(N^2^)$, cel de-al doilea este evident preferabil, pentru ca nu pierdeti nimic din punctaj, sau cel mult pierdeti un test prin cine stie ce intamplare, in schimb castigati timp pretios pe care il puteti folosi pentru alte probleme. Bineinteles, primul program este mai eficient, dar in conditii de concurs el este prea eficient. Este o mandrie sa faceti o problema perfect chiar daca ratati o alta, dar este un castig si mai mare sa faceti amandoua problemele suficient de bine.\r\n\r\nh3. H)\r\n\r\nIn general, pentru orice problema exista cel putin o solutie, fie si una slaba. Sunt numeroase cazurile cand nici nu va vine alta idee de rezolvare decat cea slaba. De regula, cand nu aveti in minte decat o rezolvare neeficienta a problemei, care stiti ca nu o sa treaca toate testele (un backtracking, sau un $O(N^5^)$, $O(N^6^)$ etc.), e bine sa incercati urmatorul lucru:\r\n\r\n* Sa presupunem ca v-a mai ramas o ora pentru rezolvarea acestei probleme. Calculati cam cat timp v-ar trebui ca sa implementati rezolvarea slaba. Sa zicem 40 de minute. In acest calcul trebuie sa includeti si timpul de depanare a programului (care variaza de la persoana la persoana) si pe cel de testare. Daca sunteti foarte siguri pe voi, puteti sa neglijati timpul de testare, dar orice program trebuie testat cel putin pe exemplul de pe foaie.\r\n\r\n* Mai raman deci 20 de minute, timp in care va puteti gandi la altceva, la alta solutie. Pentru a avea sanse mai mari sa gasiti o alta solutie, este indicat sa incercati sa ignorati complet solutia slaba, sa nu o luati ca punct de plecare. Incercati sa va \"goliti\" mintea si sa gasiti ceva nou, altfel va veti invarti mereu in cerc.\r\n\r\n* Daca va vine vreo idee mai buna, ati scapat de griji si mergeti la punctul **F)**. Altfel, la expirarea timpului de 20 de minute, va apucati sa implementati solutia pe care o aveti, oricat de ineficienta ar fi (de fapt, orice solutie, oricat de ineficienta, trebuie sa ia macar o treime sau o jumatate din punctaj, daca nu apar erori de implementare).\r\n\r\n* Puteti, ca o masura extrema, sa depasiti cu maxim 5 minute cele 20 de minute planificate, dar de cele mai multe ori acesta e timp pierdut, deoarece intervine stresul si nu puteti sa va mai concentrati.\r\n\r\nh3. I)\r\n\r\nDaca ati ajuns pana aici inseamna ca ati optat pentru o varianta de implementare. Din acest moment, pentru aceasta varianta veti scrie programul, fara a va mai gandi la altceva, chiar daca pe parcurs va vin alte idei. Iata unele lucruri pe care e bine sa le stiti despre scrierea unui program:\r\n\r\n* Datele de intrare se presupun a fi corecte. Aceasta este o regula nescrisa (uneori) a concursului de informatica. Chiar daca, prin absurd, stiti sigur ca datele de intrare trebuie verificate, mai bine n-o faceti, din mai multe motive. In primul rand, scopul cu care v-a fost data problema este altul decat sa se constate cine verifica mai bine datele de intrare. De aceea, cel mult un test sau doua vor fi cu date gresite. In al doilea rand, nu se justifica sa risipiti atata timp numai pentru cateva puncte pe care le-ati putea pierde daca nu faceti verificarea. In al treilea rand, e posibil sa gresiti oricum problema in sine, caz in care nu mai conteaza daca ati citit perfect datele de intrare. In sfarsit, legea lui Murphy spune ca \"oricate teste ar efectua cineva asupra datelor de intrare, se va gasi cineva care sa introduca date gresite\". Efortul este deci zadarnic...\r\n\r\n* Daca se poate, evitati lucrul cu pointeri. Programele care ii folosesc sunt mai greu de depanat si se pot bloca mult mai usor.\r\n	\r\n* Sa presupunem ca aveti de lucrat cu matrice de dimensiuni maxim $100 x 100$. Unii elevi au obiceiul sa dimensioneze la inceput matricele de $5 x 5$ sau $10 x 10$, deoarece sunt mai comod de evaluat cu $Evaluate (Ctrl-F4)$ sau $Watch (Ctrl-F7)$. Acest lucru este adevarat, dar exista riscul ca la sfarsit sa uitati sa redimensionati matricele de $100 x 100$. Decat sa faceti o asemenea greseala (care in mod sigur va va compromite toata problema), mai bine setati dimensiunile corecte de la inceput. De altfel, ideal ar fi ca depanarea programelor sa fie suprimata cu totul si programul sa mearga din prima.\r\n\r\n* Evitati lucrul cu numere reale, daca puteti. Operatiile in virgula mobila sunt mult mai lente. De exemplu, testul daca un numar este prim nu va incepe in nici un caz cu linia\r\n\r\n==code(c) |	\r\nwhile (i <= sqrt(N))\r\n==\r\n\r\nci cu linia\r\n\r\n==code(c) |\r\nwhile (i * i <= N)\r\n==\r\n\r\nDin punct de vedere logic, conditiile sunt perfect echivalente. Totusi, prima se evalueaza de cateva zeci de ori mai incet decat a doua.\r\n\r\n* Daca lucrati cu numere reale, nu folositi testul\r\n\r\n==code(c) |\r\nif (R1 == R2)\r\n==\r\n\r\ndeoarece pot aparea erori, ci implementati o functie:\r\n\r\n==code(c) |\r\nint equal(double R1, double R2) {\r\n    if (fabs(R1 - R2) < 1e-4) // 1e-4 = 0.0001\r\n        return 1;\r\n    return 0;\r\n}\r\n==\r\n\r\nNumarul de zerouri de dupa virgula trebuie sa fie suficient de mare astfel incat doua numere diferite sa nu fie tratate drept egale (se poate lucra de pilda cu $0.0000001$).\r\n\r\n* Tot in cazul numerelor reale, evitati pe cat posibil sa faceti impartiri, deoarece sunt foarte greoaie. De exemplu:\r\n\r\n$X / 5 <=> 0.2 * X$\r\n$X / Y / Z <=> X / (Y * Z)$\r\n\r\n* Optimizarile de genul $X shl 1$ respectiv $X << 1$ in loc de $2 * X$ sunt niste artificii de cele mai multe ori neesentiale, care in schimb fac formulele mai lungi, greu de urmarit si pot crea complicatii. Cel mai bine este sa lucrati cu notatiile obisnuite si doar la sfarsit, daca timpul de rulare trebuie redus cu orice pret, sa faceti inlocuirile.\r\n\r\n* Alegeti-va numele de variabile in asa fel incat programul sa fie clar. Sunt permise mai mult de doua litere! Numele fiecarei proceduri, functii, variabile trebuie sa-i explice clar utilitatea. E drept, lungimea programului creste, dar codul devine mult mai limpede si timpul de depanare scade foarte mult. Ca o regula generala, claritatea programelor face mult mai usoara intelegerea lor chiar si dupa o perioada mai indelungata de timp (luni, ani). Nu trebuie nici sa cadeti in cealalta extrema. De exemplu, nu depasiti 10 caractere pentru un nume de variabila.\r\n\r\n* Salvati programul cat mai des. Daca va obisnuiti, chiar la fiecare doua-trei linii. Dupa ce o sa va intre in reflex n-o sa va mai incomodeze cu nimic acest obicei, mai ales ca in ziua de azi salvarea unui program de 2-3 KB se face practic instantaneu. Au fost frecvente cazurile in care o pana de curent prindea pe picior gresit multi concurenti, iar dupa aceea nu mai este absolut nimic de facut, pentru ca nimeni nu va va crede pe cuvant ca ati facut programul si ca el mergea.\r\n\r\n* Obisnuiti-va sa programati modular. Faceti proceduri separate pentru citirea si initializarea datelor, pentru sortare, pentru afisarea rezultatelor etc. In general nu se recomanda sa scrieti proceduri in alte proceduri (adica e bine ca toate procedurile sa apartina direct de programul principal). Procedurile, acolo unde e posibil, nu trebuie sa depaseasca un ecran, pentru a putea avea o viziune de ansamblu asupra fiecareia in parte. Acest lucru ajuta mult la depanare.\r\n\r\n* Rulati programul cat mai des. In primul rand dupa ce scrieti procedura de citire a datelor. Daca e nevoie de sortarea datelor de intrare, nu strica sa va convingeti ca programul sorteaza bine, ruland doua-trei teste oarecare. E pacat sa pierdeti puncte dintr-o greseala copilareasca.\r\n\r\n* O situatie delicata apare cand fisierul de intrare contine mai multe seturi de date (teste). In acest caz, atentia trebuie sporita, deoarece daca la primul sau al doilea test programul vostru da eroare si se opreste din executie, veti pierde automat si toate celelalte teste care urmeaza. Daca in fisierul de intrare exista un singur set de date, atunci pierderea din vedere a unui caz particular al problemei nu putea duce, in cel mai rau caz, decat la picarea unui test. Asa insa, picarea unui test poate atrage dupa sine picarea tuturor celor care ii urmeaza. Pe langa corectitudinea strict necesara, programul trebuie sa se incadreze si in timp pentru orice fel de test. Daca la primul sau al doilea test din suita programul depaseste timpul (sau, si mai rau, se blocheaza), e foarte probabil sa fie oprit din executie de catre evaluatorul comisiei, deci din nou veti pierde toate testele care au ramas neexecutate.\r\n\r\n* Tot in situatia in care exista mai multe seturi de date in fisierul de intrare, daca iesirea se face intr-un fisier, este bine ca dupa afisarea rezultatului pentru fiecare test sa actualizati fisierul de iesire (prin comanda $fflush$). In felul acesta, chiar daca la unul din teste programul se blocheaza sau da eroare, rezultatele deja scrise raman scrise. Altfel, e posibil ca rezultatele de la testele anterioare sa ramana intr-un buffer in memorie, fara a fi \"varsate\" pe disc.\r\n\r\n* Daca fisierul de iesire are dimensiuni foarte mari, de exemplu daca vi se cer toate solutiile, iar numarul acestora este de ordinul zecilor de mii, puteti avea surpriza ca timpul sa nu va ajunga pentru a le tipari pe toate in fisierul de iesire. Si in acest caz, este recomandat ca dupa tiparirea fiecarei solutii sa executati comanda $fflush$, sau sa inchideti fisierul de iesire si sa-l redeschideti in modul $append$.\r\n\r\nh3. J)\r\n\r\nDaca ati trecut cu bine si de faza de scriere a programului, mai aveti doar partile de depanare si testare, care de multe ori se imbina. Metoda cea mai buna de depanare este urmatoarea:\r\n\r\n* Incepeti cu un test nici prea simplu, nici prea complicat (si usor de urmarit cu creionul pe hartie) si executati-l de la cap la coada. Daca merge perfect, treceti la teste mai complexe (minim 4 teste si maxim 7-8). Daca le trece si pe acestea, puteti fi mandri. Legile lui Murphy in programare se aplica in continuare: \"Depanarea nu poate demonstra ca un program merge; ea poate cel mult demonstra ca un program nu merge\". Totusi, daca programul vostru a mers perfect pe 7-8 teste date la intamplare, exista sanse foarte mari sa mearga pe majoritatea testelor comisiei, sau chiar pe toate.\r\n\r\n* Exemplul dat in enunt nu are in general nicio semnificatie deosebita (de fapt, are mai curand darul de a semana confuzie printre concurenti), iar daca programul merge pe acest test particular, nu inseamna ca o sa mearga si pe alte teste. In culegere nu a fost explicat pe larg algoritmul decat pe exemplul din enuntul fiecarei probleme, dar aceasta s-a facut numai pentru a nu supraincarca materialul.\r\n\r\n* Daca la unul din teste programul nu merge corespunzator, rulati din nou testul, dar de data aceasta procedura cu procedura. Dupa fiecare procedura evaluati variabilele si vedeti daca au valorile asteptate. In felul acesta puteti localiza cu precizie procedura, apoi linia unde se afla eroarea. Corectati in aceasta maniera toate erorile, pana cand testul este trecut.\r\n	\r\n* In acest moment, luati de la capat toate testele pe care programul le-a trecut deja. In urma depanarii, s-ar putea ca alte greseli sa iasa la suprafata si programul sa nu mai mearga pe vechile teste.\r\n	\r\n* Repetati procedeul de mai sus pana cand toate testele merg. Daca va obisnuiti sa programati modular si ingrijit, depanarea si testarea n-ar trebui sa dureze mai mult de 5-10 minute. Din acest moment, nu mai modificati nici macar o litera in program, sau daca tineti sa o faceti, pastrati-va in prealabil o copie. Nu va bazati pe faptul ca puteti sa tineti minte modificarile facute si sa refaceti oricand forma initiala a programului in caz ca noua versiune nu va fi buna.\r\n	\r\n* Daca totusi nu-i puteti \"da de cap\" programului, iar timpul alocat problemei respective expira, aduceti programul la o forma in care sa mearga macar pe o parte din teste (pe jumatate, de exemplu) si treceti la problema urmatoare.\r\n\r\nh3. K)\r\n\r\n==code(c) |\r\n    Nr_probleme_nerezolvate--;\r\n}\r\n==\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nProbabil nu veti fi de acord cu toate sfaturile date mai sus. E bine insa sa le aplicati. Scopul pentru care ele au fost impartasite este de a ajuta concurentii sa se acomodeze mai usor cu atmosfera concursului. De multe ori, primul an de participare la olimpiada se soldeaza cu un rezultat cel mult mediu, deoarece, oricat ar spune cineva \"ei, nu-i asa mare lucru sa mergi la un concurs\", experienta acumulata conteaza mult. De aceea, abia de la a doua participare si uneori chiar de mai tarziu incep sa apara rezultatele. Intentia autorului a fost sa va usureze misiunea si sa va dezvaluie cateva din dificultatile de toate felurile care apar la orice concurs, pentru a nu va da ocazia sa le descoperiti pe propria piele. Sper ca aceste ponturi va vor fi de folos.',2044,'public',3719,NULL),('algoritmiada-2009/runda-3/solutii','Solutii Algoritmiada 2009, Runda 3','2009-02-11 14:15:33','2009-02-15 11:15:26','h1. Solutii Algoritmiada 2009, Runda 3\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Fetite\':algoritmiada-2009/runda-3/solutii#fetite\r\n* \'Recurenta\':algoritmiada-2009/runda-3/solutii#recurenta\r\n* \'Par\':algoritmiada-2009/runda-3/solutii#par\r\n* \'Kino\':algoritmiada-2009/runda-3/solutii#kino\r\n* \'Secvmax\':algoritmiada-2009/runda-3/solutii#secvmax\r\n* \'Marmelada\':algoritmiada-2009/runda-3/solutii#marmelada\r\n* \'Gminmax\':algoritmiada-2009/runda-3/solutii#gminmax\r\n* \'Patrulatere\':algoritmiada-2009/runda-3/solutii#patrulatere\r\n\r\n==include(page=\"algoritmiada-2009/runda-3/solutii/fetite\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-3/solutii/recurenta\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-3/solutii/par\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-3/solutii/kino\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-3/solutii/secvmax\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-3/solutii/marmelada\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-3/solutii/gminmax\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-3/solutii/patrulatere\")==\r\n\r\n',1490,'public',NULL,NULL),('algoritmiada-2009/runda-3/solutii/secvmax','Secvmax','2009-02-11 14:24:05','2009-02-19 21:37:37','h1(#secvmax). \'Secvmax\':problema/secvmax\r\n\r\nSolutie $1$ \r\n\r\nO sa sortam query-urile crescator. Cand parcurgem query-urile in ordinea sortarii unele pozitii din vectorul initial vor putea fi folosite (apar pe parcurs). Acum ne intereseaza sa tinem o structura care sa sa suporte adaugarea unei pozitii intr-un vector si sa ne zica cea mai lunga subsecventa \"lipita\". Pentru aceasta ori putem sa folosim o structura de date gen \"paduri de multimi disjuncte\" ori pentru fiecare capat al unei bucati \"lipite\" tinem celalat capat si de fiecare daca cand introducem o pozitie noua actualizam aceste informatii uitandu-ne la pozitia din stanga si cea din dreapta. Sa luam un exemplu:\r\nFie sirul initial $1, 2, 4, 2, 3$ si query-urile $3, 1, 2, 4$ care dupa sortare vor fi $1, 2, 3, 4$. O sa parcurgem query-urile in ordinea sortarii. Se poate observa ca atunci cand ajungem la valoarea $x$ a unui query toate valorile mai mici sau egale cu $x$ din vectorul initial pot fi folosite. Trebuie sa gasim cea mai lunga bucata continua (lipita) de elemente mai mici sau egale cu $x$. Pe exemplu sirul va evolua asa (elementele cu valoarea $1$ reprezinta numerele ce pot fi folosite):\r\n----- $1, 2, 4, 2, 3$\r\n1 -> $1, 0, 0, 0, 0$\r\n2 -> $1, 1, 0, 1, 0$ \r\n3 -> $1, 1, 0, 1, 1$ \r\n4 -> $1, 1, 1, 1, 1$. \r\nCa sa gasim cea mai lunga bucata de $1$-uri lipite putem proceda in felul urmator: pentru fiecare bucata lipita deja aparuta de la pozitia $x$ la pozitia $y$ tinem doua valori: $D[x] = y$ si $L[y] = x$ (reprezentand capatul opus al bucatii). Lungimea unei astfel de bucati este $y - x + 1$. Trebuie sa mentinem aceste informatii in timp ce unele noi pozitii apar. Cand o noua pozitie $x$ apare trebuie sa intializam informatia pentru segmentul $x - x$ ( $D[x] = x$ si $L[x] = x$ ). Dupa aceea trebuie sa ne uitam la pozitiile $x - 1$ si $x + 1$. Avem doua bucati posibile care trebuiesc lipite cu noua pozitie (daca ambele exista o sa le lipim intre ele) : bucata $L[x-1]...x-1$ si $x+1...D[x+1]$ ce pot fi unite cu $x...x$ (stim ca aceste bucati exista daca avem o informatie in $L[x-1]$ sau in $D[x+1]$ ). Acum trebuie doar sa actualizam unele L-uri si unele D-uri. Ca sa mentinem cea mai lunga bucata lipita in primul rand trebuie sa observam ca aceasta poate doar sa creasca (doar lipim bucati). Asadar putem sa tinem o valoare $lmax$ care sa o actualizam de fiecare data cand lipim niste bucati noi. Trebuie sa mai avem grija ca nu raspundem la intrebari in ordinea lor initiala ci in ordinea sortarii, de aceea trebuie sa tinem pentru fiecare intrebare pozitia initala pe care apare si sa raspundem la pozitia respectiva (putem tine raspunsurile intr-un vector si sa afisam abia la sfarsit).\r\nComplexitatea acestor solutii (cea prezentata si cea care se foloseste de multimi disjuncte) este $O(N log N + M log M)$ ambele luand punctajul maxim.\r\n\r\n\r\nSolutie $2$ \r\n\r\nPentru fiecare element din sir vom calcula $st[i]$ si $dr[i]$ , adica lungimea maxima a unei secvente care se termina cu $a[i]$ si contine doar elemente mai mici sau egale cu $a[i]$, respectiv lungimea maxima a unei secvente care incepe cu $a[i]$ si contine doar elemente mai mici sau egale cu $a[i]$. Aceste informatii le obtinem cu ajutorul unei stive a carei elemente se vor mentine sortate.\r\ncombinand $st[i]$ si $dr[i]$ obtine lungimea maxima a unei secvente care contine doar elemente mai mici sau egale cu $a[i]$, vom nota aceasta valoare $best[i]$. Vom construi sirul $sol[i] = max(best[j])$, unde $a[j] <= a[i]$. Pentru fiecare intrebare vom cauta binar $X$ cel mai mare numar mai mic sau egal cu $Q$, rapsunsul va fi $sol[X]$. Complexitatea acestei solutii este $O(N log N + M log N)$.\r\n\r\n\r\nSolutie oferita de ==user(user=\"crawler\" type=\"tiny\")== \r\n\r\n',2038,'public',NULL,NULL),('algoritmiada-2009/runda-3/solutii/gminmax','Gminmax','2009-02-11 14:21:24','2009-03-05 10:43:29','h1(#gminmax). \'Gminmax\':problema/gminmax\r\n\r\nSe observa ca daca vrem ca un subgraf sa aibe gradul minim al unui nod $X$ trebuie ca toate nodurile cu grad mai mic ca $X$ sa fie scoase inainte. De aici ne vine ideea sa scoatem nodurile cu grad minim pe rand. La fiecare nod scos avem grija sa actualizam gradele nodurilor vecine nodului scos. La fiecare pas verificam daca gradul minim al unui nod ramas e mai mare ca rezultatul si actualizam. Este destul de evident ca asa descoperim si cel mai mare subgraf optim.\r\n\r\nO solutie ar fi sa folosim un arbore de intervale care sa suporte operatiile necesare. Aceasta abordare duce la o complexitate $O(M log N)$.\r\n\r\nO alta solutie este un algoritm in complexitate $O(N + M)$ unde ne folosim de $N$ liste in care tinem nodurile. In a $i$-a lista tinem nodurile cu gradul $i$. Parcurgem listele in ordine. Pentru lista curenta parcurgem toate nodurile nescoase inca si scadem gradul nodurilor vecine acestuia, inca nescoase. Cand scadem gradul unui nod, copiem acel nod din lista in care se afla in lista cu un grad mai mic la sfarsitul acesteia (mai tarziu cand vizitam acelasi nod in lista lui superioara nu il consideram pentru el a fost scos inainte intr-o lista inferioara). Putem sa folosim o functie recursiva care sa rezolve toate nodurile nevizitate dintr-o lista. Astfel cand inseram un nod intr-o lista inferioara celeia in care ne aflam apelam aceasta functie pentru lista inferioara. Cand terminam cu lista inferioara revenim la lista curenta si asa mai departe. Fiecare nod $x$ va aparea in $grad[x]$ liste.\r\n\r\nDin pacate nu se poate face o diferenta clara intre cele doua solutii (la timp), astfel incat ambele iau punctajul maxim (de asemenea ambele ocupa memorie $O(N + M)$).',2038,'public',NULL,NULL),('algoritmiada-2009/runda-3/solutii/patrulatere','Patrulatere','2009-02-11 14:20:12','2009-02-15 19:03:58','h1(#patrulatere). \'Patrulatere\':problema/patrulatere\r\n\r\nCea mai simpla solutie la aceasta problema este sa numaram numarul de patrulatere concave cu varfuri in punctele date si sa le scadem din numarul total de patrulatere (combinari de $N$ luate cate $4$). Singura modalitate in care se poate forma un patrulater concav este ca unul din cele 4 puncte sa se afle in triunghiul determinat de celelate 3. Astfel deducem ca trebuie sa numaram pentru fiecare triunghi cate puncte contine in interior. Cunoscatorii probabil ca stiu deja cum se rezolva aceasta problema (ea a fost data in mai multe randuri pe infoarena si alte site-uri; de exemplu \'Tri2\':problema/tri2). \r\nO sa explic pe scurt cum putem rezolva: pentru fiecare segment determinat de doua puncte $i - j$ calculam cate puncte se afla in trapezul ce se formeaza sub acel segment (trapezul determinat de segment si de o dreapta paralela cu $Ox$ ce trece prin ordonata $-INF$ cu celelalte doua drepte paralele cu $Oy$ ce trec prin capetele segmentului). Acestea putem sa le calculam in $O(N^3^)$. Avand aceste informatii putem sa calculam cate puncte sunt intr-un triunghi in $O(1)$ adunand sau scazand (in functie de triunghi) cate puncte sunt sub fiecare segment ce determina un triunghi (un fel de includere si excludere). Aceasta abordare duce la o complexitate toatala $O(N^3^)$ care obtine punctajul maxim.\r\n',2028,'public',NULL,NULL),('algoritmiada-2009/runda-3/solutii/fetite','Fetite','2009-02-11 14:25:38','2009-02-15 11:17:02','h1(#fetite). \'Fetite\':problema/fetite\r\n\r\nVom rezolva problema recursiv. Fie $f(N)$ numarul de ordine al ultimei petale ramase in cazul in care avem la inceput o floare cu $N$ petale. Se disting $2$ cazuri:\r\n\r\n* $N$ este un numar par. Vor fi eliminate toate petalele pare si ne vom intoarce la petala $1$. Putem considera ca am redus jocul la $N/2$ petale, singurul lucru de care trebuie sa avem grija este renumerotarea petalelor. Deducem ca $f(N) = 2 * f(N/2) - 1$.\r\n* $N$ este un numar impar. Vor fi eliminate toate petalele pare si apoi vom elimina petala numarul $1$. Vom ajunge la petala $3$, si observam ca am redus din nou jocul la $N/2$ petale. Din renumerotare rezulta $f(N) = 2 * f(N/2) + 1$.\r\n\r\nComplexitatea acestui algoritm este O(log N).',1490,'public',NULL,NULL),('newsletter/algoritmiada-2009-3','Algoritmiada, Runda 3; Rezultate runde anterioare','2009-02-12 08:27:32','2009-02-12 13:20:24','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎn curând începe a treia şi ultima rundă online a concursului Algoritmiada, cel mai mare şi mai important concurs organizat de infoarena!\r\n\r\nLa Algoritmiada participă elevi de gimnaziu, elevi de liceu, *dar şi studenţi*! (Avem grupe separate pentru fiecare. Studenţii pot fi chiar masteranzi sau doctoranzi.)\r\n\r\nRunda 3 se desfăşoară în acest weekend. Întrece-te cu cei mai buni! Asigură-ţi locul la finală şi câştigă premii serioase!\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Runda 3 se desfăşoară\r\n*Duminică, 15 Februarie 2009, orele 09^00^ - 13^00^*. |\r\n\r\nVezi \'pagina concursului\':algoritmiada-2009 pentru mai multe informaţii.\r\n\r\nSucces!\r\n\r\nh2{font-size: 12pt}.  Despre Algoritmiada, Runda 3\r\n\r\nAlgoritmiada este un concurs nou, cu premii, organizat de infoarena. Concursul se desfăşoară în 3 runde online de calificare şi o finală on-site. Cei mai buni vor câştiga premii serioase, în bani şi obiecte.\r\n\r\nLa Runda 3 vei avea la dispoziţie $4h$ să rezolvi $3$ probleme de natură algoritmică. Concurenţii sunt împărţiţi în 4 grupe de vârstă: gimnaziu, clasele 9-10, clasele 11-12 şi studenţi (inclusiv masteranzi şi doctoranzi).\r\n\r\nSubiectele vor fi propuse de către o echipă de foşti şi actuali olimpici la informatică: \r\n\r\n* ==User(user=\"astronomy\" type=\"link\")==\r\n* ==User(user=\"wefgef\" type=\"link\")==\r\n* ==User(user=\"gcosmin\" type=\"link\")==\r\n* ==User(user=\"bogdan2412\" type=\"link\")==\r\n* ==User(user=\"pauldb\" type=\"link\")==\r\n* ==User(user=\"prostu\" type=\"link\")==\r\n\r\nDe ce ei? Intră pe \'pagina rundei\':algoritmiada-2009/runda-3 şi citeşte câte ceva despre experienţa fiecăruia.\r\n\r\nIti urăm succes şi te asteptăm în arenă!\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(username=\"%username%\" round_url=\"algoritmiada-2009/runda-3\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}.  Despre rundele anterioare\r\n\r\n\'Silviu Gănceanu\':utilizator/silviug a făcut o analiză a primelor două runde Algoritmiada. Află câti concurenţi au participat, câte surse s-au trimis şi impresii despre rundă:\r\n\r\n* \'Algoritmiada - analiza rundei 1\':blog/algoritmiada-runda1\r\n* \'Algoritmiada - analiza rundei 2\':blog/algoritmiada-runda2\r\n\r\nVezi rezultatele şi clasamentul total \'aici\':algoritmiada-2009/clasament.\r\n\r\n==include(page=\"template/newsletter/doi-la-suta\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==\r\n',1490,'protected',NULL,NULL),('algoritmiada-2009/runda-3/solutii/kino','Kino','2009-02-11 14:24:45','2009-02-15 11:18:13','h1(#kino). \'Kino\':problema/kino\r\n\r\nPentru ca suma distanţelor între oricare două şiruri să fie maximă, trebuie să maximizăm distanţele poziţie cu poziţie, deoarece numerele care nu se află pe aceeaşi poziţie nu se afectează reciproc. Astfel, la fiecare pas numărăm câte poziţii libere sunt şi incercăm să le completăm cu numere cât mai puţin utilizate până atunci la poziţia respectivă. Observăm că este suficient să folosim maxim $N$ numere distincte. O soluţie brute force de complexitate $O(N^2^*L)$ care alege numărul cu frecvenţa minimă la fiecare pas ar fi obţinut $30$ de puncte. Pentru a ajunge la soluţia optimă, sortăm şirul frecvenţelor şi obţinem astfel o \"scară\". Scara se completează treptat pe nivele, la fiecare pas existând două alternative: continuăm să alegem elementul următor de pe nivel sau alegem primul element, pe cel frecvenţa minimă. Complexitatea acestui pas este $O(N)$ şi, deci, complexitatea totală este $O(NlogN*L)$ (din cauza sortării).',1490,'public',NULL,NULL),('algoritmiada-2009/runda-3/solutii/par','Par','2009-02-11 14:20:35','2009-02-15 11:16:21','h1(#par). \'Par\':problema/par\r\n\r\nExista mai multe solutii la aceasta problema. Folosind programare dinamica putem calcula $A[i][j]$, numarul minim de inversari care trebuie facut pentru a obtine o secventa corect parantezata. $A[i][j]$ se poate obtine din $A[i+1][j-1]$ (avem o secventa corect parantezata in interior) sau din $A[i][k]+A[k+1][j]$ (concatenam doua secvente corect parantezate) pentru $k$ intre $i+1$ si $j-1$. Complexitatea va fi $O(N^3^)$. O idee mai buna ar fi sa calculam $C[i][j]$ numarul minim de inversari astfel incat daca am luat in calcul doar primele $i$ caractere vor ramane $j$ paranteze deschise care trebuie inchise in continuare. $C[i][j]$ poate proveni doar din $C[i-1][j-1]$ sau $C[i-1][j-1]$, deci complexitatea va fi $O(N^2^)$, suficienta pentru a obtine 100 puncte. Aceasta nu este insa cea mai buna solutie, exista si o solutie greedy care ruleaza in timp liniar. Ne imaginam ca avem o stiva in care tinem parantezele deschise care le avem la un moment dat. Procesam apoi sirul initial de paranteze. Daca paranteza curenta este inchisa si in stiva se afla macar o paranteza deschisa, eliminam din stiva o paranteza deschisa si trecem mai departe. Daca paranteza curenta este inchisa si in stiva nu se afla nicio paranteza deschisa atunci inversam paranteza curenta si o introducem in stiva. Daca paranteza curenta este deschisa o introducem in stiva. Dupa ce am parcurs tot sirul initial trebuie ca in stiva sa existe un numar par de paranteze deschise. Pentru a obtine un numar minim de inversari trebuie inversate exact jumatate din ele.',1490,'public',NULL,NULL),('algoritmiada-2009/runda-3/solutii/marmelada','Marmelada','2009-02-11 14:21:51','2009-02-15 11:17:13','h1(#marmelada). \'Marmelada\':problema/marmelada\r\n\r\nFolosind o \'parcurgere in latime\':problema/bfs vom calcula drumul minim de la $S$ la $D$. Fie $K$ lungimea acestui drum minim. Apoi sortam sirul initial de costuri si realizam o bijectie intre muchiile din drumul minim si primele $K$ costuri din sirul sortat. Restul muchiilor le putem atribui orice cost din cele ramase disponibile. Este clar ca in acest fel obtinem cel mai scurt drum posibil intre $S$ si $D$, deoarece nu exista un drum mai scurt de $K$ muchii intre $S$ si $D$ si pentru acest drum de lungime $K$ orice atribuire de costuri muchiilor poate genera doar un drum cel mult egal cu cel calculat. Complexitatea va fi deci $O(M*logM+N)$.',1490,'public',NULL,NULL),('template/detailed-feedback','template/detailed-feedback','2009-02-14 15:07:32','2009-02-14 15:30:00','table{margin:0.5em auto;}. |={background-color:#EFEFFF; border:1px solid #9F9FFF; padding: 0.5em;}. !<template/detailed-feedback?report.png! In momentul in care trimiti o sursa, vei putea vedea scorul obtinut pe o parte din testele folosite la evaluare in \'monitor\':monitor?task=%task_id%. |',1490,'public',NULL,NULL),('algoritmiada-2009/runda-3/solutii/recurenta','Recurenta','2009-02-11 14:20:55','2009-02-15 11:17:48','h1(#recurenta). \'Recurenta\':problema/recurenta\r\n\r\nPentru a afla termenul de indice $n$ al sirului D vom calcula pe rand toate valorile lui $D{~i~}$ pentru k &le; i &le; n. O prima solutie tine un vector de intregi pe 64 de biti si pentru a calcula valoarea lui $D{~i~}$ itereaza pe rand peste toate valorile $D{~j~}$, $i - k &le; j &le; i-1$, adunandu-le.\r\nAceasta solutie are complexitate $O(n*k)$ si functioneaza pentru $n$ foarte mic, solutia ia $30$ de puncte. O solutie asemanatoare dar care foloseste adunarea pe numere mari va lua $60$ de puncte. Se observa ca nu avem nevoie decat de ultimii $k$ termeni ai sirului $D$ pentru a determina valoarea unui termen, astfel putem optimiza memoria folosita de la O(N * nr_mari) la O(K * nr_mari). De asemeni nu este nevoie sa calculam suma ultimilor $k$ termeni la fiecare pas, pentru ca $D{~i+1~} = 2 * D{~i~} - D{~i-k~}$. Folosind aceasta relatie de recurenta complexitatea algoritmului este de O(N * nr_mari) si obtine $100$ de puncte. Pentru ca solutia sa intre in memorie se va utiliza optimizarea prezentata mai sus sau numerele mari vor fi implementate folosind o baza mare (10^9^)',1490,'public',NULL,NULL),('problema/gard','Gard','2006-11-11 11:23:41','2009-06-10 10:29:32','==Include(page=\"template/taskheader\" task_id=\"gard\")==\r\n\r\nO echipa de $K$ muncitori a fost angajata sa vopseasca un gard format din $N$ scanduri numerotate de la $1$ la $N$, de la stanga spre dreapta. Fiecare muncitor $i (1 &le; i &le; K)$ se aseaza in fata scandurii $S{~i~}$ si poate vopsi numai un interval compact (adica numerele de ordine ale scandurilor din interval sunt consecutive) avand maxim $L{~i~}$ scanduri, interval care trebuie sa contina scandura $S{~i~}$. Pentru fiecare scandura vopsita, acesta este platit cu suma $P{~i~}$. Din motive de eficienta, oricare 2 muncitori din echipa trebuie sa vopseasca intervale de scanduri disjuncte (adica oricare scandura a gardului poate fi vopsita de cel mult un membru al echipei).\r\nFiind conducatorul echipei de muncitori, dumneavoastra doriti sa determinati pentru fiecare membru al echipei intervalul de scanduri pe care acesta va trebui sa il vopseasca, astfel incat castigul total sa fie maxim. Castigul total este egal cu suma castigurilor realizate de fiecare membru al echipei. Castigul realizat de fiecare muncitor este egal cu numarul de scanduri vopsite de acesta inmultit cu $P{~i~}$ (pentru muncitorul cu numarul $i$).\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care determina castigul maxim obtinut de cei $K$ muncitori.\r\n\r\nh2. Date de Intrare\r\n\r\nFisierul de intrare $gard.in$ contine:\r\n\r\ntable(example). |gard.in | Semnificatie |\r\n| N K \r\n L{~1~} P{~1~} S{~1~} \r\n L{~2~} P{~2~} S{~2~} \r\n ... \r\n L{~K~} P{~K~} S{~K~} | N - numarul de scanduri; K - numarul de muncitori \r\n L{~i~} - numarul maxim de scanduri ce pot fi vopsite de muncitorul cu numarul $i$ \r\n P{~i~} - suma primita de muncitorul $i$ pentru fiecare scandura vopsita de acesta \r\n S{~i~} - scandura din gard in fata careia se aseaza muncitorul i |\r\n\r\nh2. Date de Iesire\r\n\r\nIn fisierul $gard.out$ veti afisa castigul maxim obtinut de intreaga echipa de muncitori.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 16.000$\r\n* $1 &le; K &le; 100$\r\n* $1 &le; P{~i~} &le; 10.000$\r\n* $1 &le; L{~i~},S{~i~} &le; N$\r\n* Toate numerele $S{~i~}$ vor fi distincte.\r\n* Nu trebuie vopsite neaparat toate cele $N$ scanduri ale gardului.\r\n* Este permis ca unul sau mai multi dintre membrii echipei sa nu vopseasca nici o scandura, caz in care scandura in fata careia s-au asezat initial poate fi vopsita, eventual, de catre alt muncitor.\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. gard.in |_. gard.out |\r\n| 8 4\r\n3 2 2\r\n3 2 3\r\n3 3 5\r\n1 1 7 | 17 |\r\n\r\nh3. Explicatie\r\n\r\nMuncitorul $1$ vopseste intervalul de scanduri $[1, 2]$; muncitorul $2$ vopseste intervalul de scanduri $[3, 4]$; muncitorul $3$ vopseste intervalul de scanduri $[5, 7]$; muncitorul $4$ nu vopseste nici o scandura.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"gard\")==\r\n\r\n\r\n',15,'task: gard',453,NULL),('runda/vot/voteaza_nargy_si_fumeanu','Votateaza Nargy si Fumeanu','2010-03-04 12:19:47','2010-03-04 16:15:27','h1. Voteaza Nargy si Fumeanu\r\n\r\n_Nargy si Fumeanu sunt prieteni de nedespartit. De aceea, au decis sa intre in intrecere impreuna._\r\n\r\nAici puteti vota pentru Nargy si Fumeanu in cadrul \"concursului de vot al personajului preferat Infoarena\":runda/vot.\r\n\r\nVotarea incepe ==roundparam(round_id=\"voteaza_nargy_si_fumeanu\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"voteaza_nargy_si_fumeanu\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"voteaza_nargy_si_fumeanu\" units=\"2\") ==\r\n\r\n\'*Rezultate*\':runda/vot/voteaza_nargy_si_fumeanu/clasament\r\n\r\nh2. Itemi de vot\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"voteaza_nargy_si_fumeanu\" score=\"1\")==',8689,'public',4600,NULL),('runda/getready','getready','2009-04-23 17:45:37','2009-04-23 17:45:37','h1. == roundparam(round_id=\"getready\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"getready\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"getready\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"getready\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/getready/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"getready\" score=\"1\")==',9681,'round: getready',NULL,NULL),('runda/getready/clasament','Clasament getready','2009-04-23 17:45:37','2009-04-23 17:45:37','h1. Clasament ==roundparam(round_id=\"getready\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"getready\")==',9681,'round: getready',NULL,NULL),('propuneri','Propuneri infoarena','2007-11-07 01:42:16','2010-02-16 16:33:26','h1. Propuneri infoarena\r\n\r\nAceasta pagina centralizeaza toate documentele IAP (infoarena Proposal).\r\n\r\nUn IAP (infoarena Proposal) este un document care propune \'Asociatiei infoarena\':asociatia-infoarena sa adopte un proiect semnificativ sau sa creeze / modifice politici si procese.\r\n\r\nMai multe informatii despre sistemul IAP gasesti chiar in \'IAP #0\':propuneri/0-sistemul-iap ;)\r\n\r\nh2. Cum fac o noua propunere?\r\n\r\n*Trebuie sa ceri un numar IAP* de la un \'consilier infoarena\':echipa-infoarena. Explica in mare ideea ta si, daca acel consilier este de acord, vei primi un numar IAP si permsiunea sa-l scrii. In general, consilierii infoarena sunt deschisi la aproape orice idee bine argumentata.\r\n\r\nNu poti crea un IAP fara acordul unui consilier infoarena!\r\n\r\nh2.  Registrul IAP\r\n\r\n*Atentie!* Doar o parte din propunerile de mai jos au fost aprobate! Orice IAP ramane in registru, chiar si daca este respins.\r\n\r\nDeschide fiecare IAP in parte pentru a afla verdictul sau starea in care se afla.\r\n\r\n|_. IAP # |_. Titlu                                                       |_. Autor(i) |_. Stare |\r\n| 0&nbsp; | \'Sistemul IAP (infoarena proposals)\':propuneri/0-sistemul-iap | ==User(type=\"tiny\" user=\"wickedman\")== | *Aprobat* |\r\n| 1       | \'Concurs \"hackaton\"\':propuneri/1-hackaton                     | ==User(type=\"tiny\" user=\"wickedman\")==  \r\n==User(type=\"tiny\" user=\"silviug\")== | *Respins* |\r\n| 2       | \'Concurs de informatica pentru studenti\':propuneri/2-concurs-studenti | ==User(type=\"tiny\" user=\"wickedman\")== \r\n==User(type=\"tiny\" user=\"silviug\")== | *Respins*  |\r\n| 3       | \'Infoarena 3.0\':propuneri/3-infoarena3 | ==User(type=\"tiny\" user=\"fluffy\")== | *Respins* |\r\n| 4       | \'Restructurare forum\':propuneri/4-forum | ==User(user=\"wefgef\" type=\"tiny\")== | *Respins* |\r\n| 5       | \'Open surse\':propuneri/5-open-surse | ==User(user=\"domino\" type=\"tiny\")== | *Aprobat* |\r\n| 6       | \'Arhiva educationala\':propuneri/6-arhiva-educationala | ==User(user=\"domino\" type=\"tiny\")== | *Aprobat* |\r\n| 7       | \'Community Ladder\':propuneri/7-community-ladder | ==User(user=\"wickedman\" type=\"tiny\")== | *Respins* |\r\n| 8       | \'\"Almanah\" infoarena\':propuneri/8-almanah | ==User(user=\"wickedman\" type=\"tiny\")== | *Fara resurse* |\r\n| 9       | \'OKR\':propuneri/9-okr | ==User(user=\"domino\" type=\"tiny\")==\r\n==User(user=\"wickedman\" type=\"tiny\")==| *Aprobat* |\r\n| 10       | \'Virtual Contests\':propuneri/10-virtual-contest | ==User(user=\"gcosmin\" type=\"tiny\")== | *Aprobat* |\r\n| 11       | \'Revizuirea functionalitatii ratingului\':propuneri/11-rating | ==User(user=\"bogdan2412\" type=\"tiny\")== | *Respins* |\r\n| 12       | \'Infoarena.org\':propuneri/12-infoarena.org | ==User(user=\"alexthero\" type=\"tiny\")== | In constructie |\r\n| 13       | \'Alegerea preşedintelui infoarena\':propuneri/13-presedinte | ==User(user=\"wickedman\" type=\"tiny\")== | *Aprobat* |\r\n| 14       | \'Grupuri probleme\':propuneri/14-grupuri-probleme | ==User(user=\"toni2007\" type=\"tiny\")== | In constructie |\r\n| 15       | \'Task tagging\':propuneri/15-task-tagging | ==User(user=\"bogdan2412\" type=\"tiny\")== | *Aprobat* |\r\n| 16       | \'Reorganizare arhiva\':propuneri/16-reorganizare-arhiva | ==User(user=\"wefgef\" type=\"tiny\")== | *Aprobat* |',1490,'public',NULL,NULL),('documentatie/arhiva-educationala','Ghid pentru arhiva educationala','2008-03-16 08:29:33','2009-02-17 17:44:49','h1. Ghid pentru arhiva educationala\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nProblemele din arhiva educationala se creeaza la fel ca orice alta problema de pe infoarena. Pentru a afla cum poti crea o problema, consulta materialul de \'aici\':documentatie/editare-de-probleme. Deosebirea dintre o problema obisnuita de pe infoarena si o problema din arhiva educationala este modul in care sunt formatate. \r\nAstfel, o problema din arhiva educationala trebuie sa respecte urmatorul set de reguli:\r\n\r\nh2. Reguli privind enuntul\r\n\r\n* Enuntul problemei va contine o sectiune speciala numita _Indicatii de rezolvare_, in care va fi prezentata o explicatie succinta a metodei de rezolvare a problemei. Tot in aceasta sectiune, vor fi precizate link-uri catre diferite articole ce trateaza tema respectiva sau carti in care este prezentat subiectul in cauza.\r\n* Pentru problemele in care exista mai multe rezolvari, se va preciza punctajul orientativ obtinut de fiecare complexitate sau metoda in parte. De exemplu, pentru algoritmul de drumuri minime a lui Djikstra, se poate preciza ca un algoritm de complexitate {$O(N^2^)$} obtine $50$ de puncte, in timp ce o abordare {$O(Mlog{~2~}N)$} conduce la obtinerea punctajului maxim. Si solutiile neoptime vor fi insostite de o explicatie minimala.\r\n* Se recomanda folosirea imaginilor pentru a ilustra mai bine cerinta sau pentru a explica mai bine metoda de rezolvare.\r\n* In fiecare problema va aparea un link catre sursa oficiala, scrisa de unul din membrii echipei infoarena sau de voluntarul care a creat problema.\r\n* Se recomanda precizarea unui set de probleme de pe site-uri cu evaluator automat (\'infoarena\':/, \'sgu\':http://acm.sgu.ru, \'uva\':http://acm.uva.es, \'timus\':http://acm.timus.ru, etc), a caror rezolvare se bazeaza pe algoritmul in cauza. Link-urile catre aceste probleme vor aparea la sectiunea _Aplicatii_. De asemenea, daca algoritmul sau structura de date prezentata este o subproblema a unui alt algoritm mai dificil, in aceasta sectiune va fi explicata pe scurt legatura dintre cele doua probleme. Daca este posibil, problema mai dificila va fi insotita de un link tot in \'arhiva educationala\':arhiva-educationala.\r\n\r\nh2. Reguli privind testele si sursele\r\n\r\n* Toate testele si sursele trimise vor fi vizibile oricarui utilizator. \r\n* Sursele oficiale (date ca exemplu de implementare la _Indicatii de rezolvare_) trebuie scrise cat mai lizibil si trebuie insotite de comentarii pentru a fi accesibile oricarui utilizator.\r\n* Aproximativ 20%-30% din testele folosite la evaluare vor trebui sa aiba dimensiuni mici astfel incat sa poata fi verificate manual.\r\n* Testele trebuie verificate daca respecta restrictiile folosind functia $assert$.\r\n* Optional, evaluatorul pentru o problema trebuie sa returneze mesaje cat mai diversificate pentru ca utilizatorii sa isi poate descoperi usor eventualele greseli.\r\n\r\nh2. Exemple\r\n\r\nExemple de probleme pentru aceasta arhiva gasiti mai jos:\r\n\r\n* \'Ciclu eulerian\':problema/ciclueuler\r\n* \'Componente biconexe\':problema/biconex\r\n* \'Flux maxim\':problema/maxflow\r\n* \'Trie\':problema/trie\r\n\r\n',1792,'public',NULL,NULL),('blog/membri-noi-2008-p1','Infoarena în 2008: Membri noi, partea 1','2009-02-27 08:38:00','2009-02-27 09:02:07','_După cum spunea şi Cosmin în \'postul despre articole\':blog/infoarena_in_2008_articole s-au întamplat multe cu infoarena anul trecut. Totuşi, cred că cel mai important lucru este că echipa s-a îmbogăţit substanţial, cu un număr record de membri noi: 7!_\r\n\r\n_Toţi s-au acomodat şi au intrat rapid în pâine: mulţi au propus şi vor propune probleme interesante la concursurile marca infoarena, majoritatea şi-au manifestat interesul pentru dezvoltarea site-ului şi câţiva dintre ei au deja contribuţii substanţiale, o parte dintre ei coordonează şi realizează proiecte infoarena care în trecut stagnau sau înaintau greu. Pe lânga toate aceste lucruri grozave, au adus un suflu nou în echipă şi ne-au contaminat cu entuziasm şi pe cei mai vechi._\r\n\r\n_Îmi face placere să fiu eu cel care vă prezintă noul val de membri ai echipei infoarena. Îi vom introduce, ca de obicei, prin botezul infoarena: un scurt interviu. Cum sunt mulţi îi voi prezenta în două posturi. În prima parte vom discuta cu: Alexandru Ţandrău, Bogdan Tătăroiu şi Cosmin Gheorghe._\r\n\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/membri-noi-2008-p1?alexandru_tandrau.jpg! *Cum ai ajuns membru al siteului infoarena?*\r\n*Alexandru:* A trecut atât de mult timp de atunci incat nici nu mai stiu. Tin minte insa ca m-am blocat, ca multi utilizatori ai siteului, la a patra problema, fractii. Un sfat pentru utilizatorii noi: cititi forumul! Contine o gramada de informatii utile.\r\n\r\n*De ce ai intrat în echipa infoarena? Ce îţi propui să faci ca membru al echipei?*\r\n*Alexandru:* Siteul si echipa infoarena m-au ajutat foarte mult pana acum. Asa ca Silviu, pot spune ca am invatat cea mai mare parte a informaticii pe care o stiu in ultimii 2 ani de liceu. Aceasta se datoreaza in principal siteului infoarena si a celorlalti membrii ai echipei care m-au pregatit (Silviu, Mircea, Wefgef). Cred ca acum pot si eu sa-i ajut pe cei care sunt la inceput de drum in informatica.\r\n\r\n*Ce pasiuni ai înafara de programare?*\r\n*Alexandru:* Imi plac foarte mult masinile (cu motoare cat mai mari si mai puternice). De asemenea sunt un infocat sustinator al Universitatii Cluj si sunt nelipsit de la toate meciurile echipelor acestui club atunci cand sunt in localitate. Din pacate acest lucru se intampla tot mai rar in ultimul timp.\r\n\r\np=. ~ ~ ~\r\n\r\n!{margin: 10px; margin-right: 0; border: 1px solid gray;}>blog/membri-noi-2008-p1?bogdan_tataroiu.jpg! *Cum ai ajuns membru al siteului infoarena?*\r\n*Bogdan:* M-am inregistrat pe site in clasa a 7-a (cred), nu mai tin minte exact de unde aflasem de infoarena. Eram entuziasmat ca primele doua probleme erau usoare si le implementasem repede si dup-aia am dat de fractii... A trecut un an, doi pana cand am rezolvat problema aia.\r\n\r\n*Cum ai folosit acest site?*\r\n*Bogdan:* Infoarena a fost primul site pe care am inceput sa lucrez. Eram membru de pe vremea cand arhiva avea 50-60 de probleme. Imi placea mai mult cand arhiva avea mai putine probleme, apucai sa citesti majoritatea sa-ti alegi la care sa te gandesti, erau toate originale, pe idei de rezolvare foarte diferite. Ma chinuiam sa urc in clasamentul arhivei, stateam si zile intregi pe o problema. Mi-a fost destul de greu la inceput, cu fiecare problema invatam cate ceva nou. Era de la inceput o comunitate foarte tare, puneam intrebari pe forum si tot timpul se gasea cineva sa-mi raspunda.\r\n\r\n*De ce ai intrat în echipa infoarena? Ce îţi propui să faci ca membru al echipei?*\r\n*Bogdan:* In primul rand o sa ma ocup de development, asta fiind si unul dintre motivele pentru care am intrat in echipa. Sunt o groaza de lucruri de facut la infoarena, si mi se pare o experienta buna in cazul in care o sa ma angajez vreodata in software development. Deja am implementat multe feature-uri care mi s-au parut foarte utile: evaluarea surselor in timpul concursului, rezultate partiale pe testele folosite la evaluare, suport pentru unicode (diacritice) fiind principalele schimbari vizibile utilizatorilor.\r\n\r\np=. ~ ~ ~\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/membri-noi-2008-p1?cosmin_gheorghe.jpg! *Cum ai ajuns membru al siteului infoarena?*\r\n*Cosmin:* Pe la sfarsitul clasei a 8-a am aflat de acest site de la ==user(user=\"bogdan2412\")==. Mi s-a parut interesant si am inceput si eu sa lucrez pe infoarena.\r\n\r\n*Cum ai folosit acest site?*\r\n*Cosmin:* La inceput problemele de pe infoarena mi se pareau foarte grele (unele continua sa mi se para grele si acum). Cu toate acestea eram foarte determinat pe vremea aceea sa fiu cat mai bun si cu ajutorul de pe forum si intreband in stanga si in dreapta am inceput incet incat sa ma prind si eu :). La vreo 3-4 luni de lucrat aproape constant pe infoarena am aflat de clasamentul general (stiu, destul de tarziu). Am observat atunci ca eram pe a doua sau a treia pagina si mi-am dorit si eu sa ajung pe prima pagina alaturi de oameni precum Mircea Pasoi care pentru mine la vremea aceea erau niste modele demne de urmat :p. Am participat si la concursurile infoarena care au fost mereu o provocare.\r\n\r\n*De ce ai intrat în echipa infoarena? Ce îţi propui să faci ca membru al echipei?*\r\n*Cosmin:* Am intrat in echipa infoarena pentru ca in primul rand sunt multe lucruri de invatat lucrand la dezvoltarea site-ului dar de asemenea vreau sa rasplatesc la randu-mi comunitatea pentru tot ce am invatat eu de la ea.\r\n\r\nh3. _Spor la treabă băieţi! Suntem mândri să vă avem printre noi!_\r\n\r\n',15,'public',3721,NULL),('utilizator/sergiuc','Profil SergiuC','2009-02-18 11:33:54','2009-02-18 11:33:54','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',9597,'public',NULL,NULL),('utilizator/thesvcoolman','Profil thesvcoolman','2009-07-18 08:14:17','2009-07-18 08:14:17','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',10547,'public',NULL,NULL),('runda/horax_round_1/clasament','Clasament horax_round_1','2009-07-16 09:47:41','2009-07-16 09:47:41','h1. Clasament ==roundparam(round_id=\"horax_round_1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"horax_round_1\")==',445,'round: horax_round_1',NULL,NULL),('coduri-gray','Coduri Gray','2008-02-23 08:00:17','2009-11-14 09:50:35','h1. Coduri Gray\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"alecman\") ==\r\n\r\n(Categoria _Matematica_, Autor _Cosmin Negruseri_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Cuprins*\r\n* \'Introducere\':coduri-gray#introducere\r\n* \'Problema 1: Turnurile din Hanoi\':coduri-gray#hanoi\r\n* \'Problema 2: Becuri\':coduri-gray#becuri\r\n* \'Problema 3: Matrix\':coduri-gray#matrix\r\n* \'Problema 4: Divizori\':coduri-gray#divizori\r\n* \'Problema 5: Sortnet\':coduri-gray#sortnet\r\n* \'Bibliografie\':coduri-gray#biblio\r\n\r\nh2(#introducere). Introducere\r\n\r\nUn cod Gray de ordin $n$ este un sir care contine toate numerele de la $0$ la $2^n-1^$, astfel incat orice doua numere consecutive din sir sa difere in reprezentarea lor binara prin exact un bit. Exista mai multe coduri Gray distincte, cel mai des intalnit fiind asa-numitul **\"binary reflected Gray code\"** (in continuare cand vom vorbi despre codul Gray ne vom referi de fapt la acest cod). Modul de constructie este destul de intuitiv: fiecare numar nou este format din cel anterior prin modificarea celui mai putin semnificativ bit, astfel incat numarul sa nu mai fi fost adaugat inainte la sir (de exemplu, pentru $n = 2$ si primul numar $0$, sirul obtinut va fi $0, 1, 3, 2$).\r\n\r\nIn continuare vom nota acest cod cu $G{~n~}$. Putem da astfel o noua metoda de constructie. Fie $G\'{~n-1~}$ sirul $G{~n-1~}$ inversat, atunci obtinem $G{~n~}$ daca punem cate un bit $0$ in fata fiecarui numar din $G{~n-1~}$, urmat de numerele din $G\'{~n-1~}$, carora le adaugam cate un $1$ ca bit semnificativ ( pe scurt $G{~n~} = 0G{~n-1~},1G\'{~n-1~} (1)$). Se poate observa ca acest cod este circular, diferenta intre ultimul si primul numar fiind de exact un bit. De asemenea, orice cod de ordin $n$ il contine pe cel de $n-1$ ca prefix, deci am putea nota prin $G{~&infin;~}$ sirul numerelor naturale in care orice doua numere consecutive difera in reprezentarea binara prin exact un bit si pentru care sirul primelor $2^n^$ elemente coincide cu $G{~n~}$ (&forall; $n$ &isin; _**N**_). \r\n\r\nFie $g(x)$ al $x$-lea numar din $G{~&infin;~}$ si $g-1(y)$ pozitia la care apare numarul $y$ in sirul $G{~&infin;~}$. Se pune problema calcularii eficiente a celor doua functii. Se poate demonstra prin inductie ca daca avem un numar $x$ cu reprezentarea binara $(...a{~2~}a{~1~}a{~0~}){~2~}$ si codul lui Gray $(...b{~2~}b{~1~}b{~0~}){~2~}$, atunci avem $b{~i~} = a{~i~} ^&and;^ a{~i+1~}$ (2). De exemplu, pentru numarul $6$ cu reprezentarea binara $110$, atunci $g(110) = 101$. De aici se deduce ca $g(x) = x ^&and;^ (x / 2)$. Din (2) obtinem ca $b{~i~} ^&and;^ b{~i+1~} ^&and;^ b{~i+2~} ^&and;^ ... = (a{~i~} ^&and;^ a{~i+1~}) ^&and;^ (a{~i+1~} ^&and;^ a{~i+2~}) ^&and;^ (a{~i+2~} ^&and;^ a{~i+3~}) ^&and;^ ... = a{~i~}$. Suma este finita deoarece va exista un $b{~i~}$ egal cu $0$ si un $a{~i~}$ egal cu $0$ (daca $i$ este indeajuns de mare). Rezulta astfel ca $g-1(y) = y ^&and;^ y/2 ^&and;^ y/4 ^&and;^ ...$\r\n\r\nDin cele de mai sus obtinem urmatoarele metode:\r\n\r\n== code(cpp) |\r\nint binToGray(int x) {\r\n    return x ^ (x >> 1);\r\n}\r\n==\r\n\r\n== code(cpp) |\r\nint grayToBin(int y) {\r\n    int ret = 0;\r\n    while (y > 0) {\r\n        ret ^= y;\r\n        y >>= 1;\r\n    }\r\n    return ret;     \r\n}\r\n==\r\n\r\nh2(#hanoi). Problema 1: _Turnurile din Hanoi_\r\n\r\nAvem trei tije si $n$ discuri de dimensiuni diferite plasate in ordinea descrescatoare a dimensiunilor pe prima tija. Se doreste mutarea tuturor discurilor pe cea de a doua tija, singurul tip de miscare posibila fiind mutarea unui disc de pe o tija pe alta, cu conditia ca pe tija destinatie discul din varf (daca exista un asemenea disc) sa fie mai mare decat discul pe care il mutam acum.\r\n\r\nh3. Rezolvare\r\n\r\nAceasta este o problema clasica in predarea recursivitatii, dar ea are o solutie care se foloseste de codul Gray. Urmarim la fiecare pas ce bit se schimba de la numerele consecutive ale lui $G{~n~}$ - acest bit corespunde discului pe care il vom muta (cel mai putin semnificativ bit corespunde celui mai mic disc etc). Problema este ca nu stim pe ce tija trebuie sa mutam discul respectiv. Exista o regula simpla care ne poate ajuta: un disc nu trebuie plasat pe alt disc cu aceeasi paritate. Folosind aceasta strategie, putem rezolva problema in numar minim de pasi ( $2^n^ - 1$ ).\r\n\r\nh2(#becuri). Problema 2: _Becuri_\r\n\r\nUn bec este conectat la $n$ intrerupatoare. Fiecarui astfel de intrerupator ii poate fi schimbata starea prin apasare. Problema este ca nu stim starea lor initiala. Se cere sa se determine o strategie care ar face numar minim de apasari in cazul cel mai defavorabil, pentru a aprinde becul.\r\n\r\nh3. Rezolvare\r\n\r\nPentru a fi siguri ca aprindem becul trebuie in cel mai rau caz sa trecem prin toate configuratiile apasat/ne-apasat ale intrerupatoarelor. Pentru a schimba starea curenta trebuie sa apasam cel putin un buton, deci in cazul cel mai defavorabil va trebui sa facem cel putin $2^n^ - 1$ apasari. Codul Gray ne da o posibilitate de a trece prin toate configuratiile trecand de la una la alta prin o apasare de buton, rezolvandu-ne problema.\r\n\r\nh2(#matrix). Problema 3: \'_Matrix_\':http://acm.sgu.ru/problem.php?contest=0&problem=249 (SGU)\r\n\r\nTrebuie sa aranjati numerele de la $0$ la $2^(n + m)^ - 1$ intr-o matrice cu $2^n^$ randuri si $2^m^$ coloane. De asemenea, numerele care sunt situate in celule adiacente pe verticala sau orizontala trebuie sa difere prin exact un bit in reprezentarea lor binara. Matricea este ciclica, adica pentru fiecare rand celula cea mai din stanga se considera invecinata cu cea mai din dreapta, de asemenea pentru fiecare coloana celula cea mai de sus se considera invecinata cu celula cea mai de jos. La intrare se dau numerele $n$ si $m$ ( $0 < n, m; n + m <= 20$ ). Trebuie sa afisati o asemenea matrice. De exemplu daca $n = 1$ si $m = 1$ o matrice ar fi\r\n( $0$ $2$ )\r\n( $1$ $3$ )\r\n\r\nh3. Rezolvare\r\n\r\nO prima metoda ar fi de a determina codului $G{~n+m~}$, iar apoi de a-l scrie serpuit in matrice (liniile de index par de la stanga la dreapta, cele de index impar in sens invers).\r\n\r\nDe exemplu, daca $n = 2$ si $m = 2$ avem:\r\n$G{~4~} = {0000, 0001, 0011, 0010, 0110, 0111, 0101, 0100, 1100, 1101, 1111, 1110, 1010, 1011, 1001, 1000}$\r\n\r\n| 0000 | 0001 | 0011 | 0010 |\r\n| 0100 | 0101 | 0111 | 0110 |\r\n| 1100 | 1101 | 1111 | 1110 |\r\n| 1000 | 1001 | 1011 | 1010 |\r\n\r\nAlta modalitate de rezolvare care ne da de fapt aceeasi matrice este urmatoarea: in celula $(i,j)$ vom avea rezultatul concatenarii reprezentarilor binare ale lui $i$ (din codul $G{~n~}$) si $j$ (din codul $G{~m~}$).\r\n\r\nDe exemplu, matricea pentru $n = 3$ si $m = 2$ este:\r\n\r\n|_. - |_. 00 |_. 01 |_. 11 |_. 10 |\r\n|_. 000 | 00000 | 00001 | 00011 | 00010 |\r\n|_. 001 | 00100 | 00101 | 00111	| 00110 |\r\n|_. 011 | 01100 | 01101 | 01111 | 01110 |\r\n|_. 010 | 01000 | 01001 | 01011 | 01010 |\r\n|_. 110 | 11000 | 11001 | 11011 | 11010 |\r\n|_. 111 | 11100 | 11101 | 11111 | 11110 |\r\n|_. 101 | 10100 | 10101 | 10111 | 10111 |\r\n|_. 100 | 10000 | 10001 | 10011 | 10010 |\r\n\r\nEste evident ca orice doua numere adiacente in matrice sunt diferite in reprezentarea binara prin exact un bit. In concurs limita de timp era foarte stransa si trebuia folosita functia prezentata anterior. Deci pe linia $i$, coloana $j$ a matricei scriem numarul (binToGray(i) << M) | binToGray(j).\r\n\r\nh2(#divizori). Problema 4: \'_Divizori_\':problema/divizori\r\n\r\nVom considera un numar natural $N$. In sirul $A$ vom aseza toti divizorii lui $N (2 <= N <= 2.000.000.000)$. Se cere sa se permute elementele sirului $A$ astfel incat pentru oricare doua elemente consecutive $A[i]$ si $A[i+1]$ sa avem fie $A[i] = A[i+1] * p$, fie $A[i+1] = A[i] * p$ ( $p$ numar prim oarecare). Valoarea $p$ poate diferi de la o pereche de elemente la alta. De exemplu, pentru $N = 12$ o posibila solutie ar fi $1, 2, 3, 4, 12, 6, 3$.\r\n\r\nh3. Rezolvare\r\n\r\nNumarul $N$ are maxim $2*N^1/2^$ divizori. Descompunerea lui $N$ in factori primi are forma $P{~1~}^E{~1~}^ * P{~2~}^E{~2~}^ * ... * P{~k~}^E{~k~}^$ ( $P{~1~}, P{~2~}, ..., P{~k~}$ - numere prime, si $E{~i~} &isin; _**N**_, E{~i~} &gt; 0$ ). Un divizor al lui $N$ va fi reprezentat printr-un vector de exponenti $(e{~1~}, e{~2~}, ..., e{~k~})$ unde $0<=e{~i~}<=E{~k~}$. Prin urmare, problema noastra poate fi usor redusa la urmatoarea cerinta: ordonati toti vectorii $(e{~1~}, e{~2~}, ..., e{~k~})$ intr-un sir cu proprietatea ca diferenta intre doi vectori consecutivi se realizeaza la o singura pozitie a vectorilor si cele doua elemente ale vectorilor de pe pozitia respectiva difera prin o unitate.\r\nExemplul din enuntul problemei se poate reprezenta astfel:\r\n$1, 2, 4, 12, 6, 3$\r\n$P{~1~} = 2 E{~1~} = 2$\r\n$P{~2~} = 3 E{~2~} = 1$\r\n$(0,0), (1,0), (2,0), (2,1), (1,1), (0,1)$\r\n\r\nAceasta problema este o generalizare a determinarii codului Gray si poate fi rezolvata generalizand metoda expusa mai sus. Presupunem ca stim sa generam o solutie pentru $M = N/(P{~k~}E{~k~})$ (o solutie pentru un numar cu $k-1$ factori primi). Sa vedem cum generam o solutie pentru $N$. Fie $C$ vectorul solutie pentru $M$ si $R$ vectorul $C$ inversat. O solutie poate fi:\r\n$C, P{~k~}*R, P{~k~}^2^*C, P{~k~}^3^*R ...$\r\nAstfel am concatenat $E{~k~}$ coduri pentru $M$, inmultind cu $P{~k~}$ si pe fiecare pozitie impara am pus secventa inversata pentru $M$. Am facut aceasta pentru ca cele doua capete ce vor ajunge in codul final consecutive sa difere numai prin $P{~k~}$.\r\n\r\nExemplu: $E{~1~} = 3; E{~2~} = 2; E{~3~} = 1$\r\n$(0,0,0) (1,0,0) (2,0,0) (3,0,0)$ - Solutia pentru un factor prim.\r\n$(0,0,0) (1,0,0) (2,0,0) (3,0,0) (3,1,0) (2,1,0) (1,1,0) (0,1,0) (0,2,0) (1,2,0) (2,2,0) (3,2,0)$ - Solutia pentru doi factori primi.\r\n$(0,0,0) (1,0,0) (2,0,0) (3,0,0) (3,1,0) (2,1,0) (1,1,0) (0,1,0) (0,2,0) (1,2,0) (2,2,0) (3,2,0)$\r\n$(3,2,1) (2,2,1) (1,2,1) (0,2,1) (0,1,1) (1,1,1) (2,1,1) (3,1,1) (3,0,1) (2,0,1) (1,0,1) (0,0,1)$ - Solutia pentru cei trei factori primi.\r\n\r\nComplexitatea finala a solutiei este $O(T)$ unde $T$ reprezinta numarul de divizori ai lui $N$.\r\n\r\nh2(#sortnet). Problema 5: \'_Sortnet_\':problema/sortnet (Lot 2002)\r\n\r\nO retea completa de sortare este o retea de sortare cu $N$ fire de adancime $D$ ce are $D * (N/2)$ comparatori. Amintim principiul $0-1$ care spune ca o retea de sortare sorteaza orice $N$ numere daca aceasta sorteaza orice secventa de $N$ numere $0-1$. Problema noastra cere sa se determine cate astfel de secvente de $0-1$ nu sunt sortate corect.\r\n\r\nh3. Rezolvarea lui Mihai Patrascu\r\n\r\nObservam ca dupa primul strat de comparatori sunt exact $3^(N/2)^$ rezultate posibile, pentru ca intrarile trecute printr-un comparator se transforma astfel:\r\n\r\n| (0,0) -> (0,0) | (0,1) -> (1,0) | (1,0) -> (1,0) | (1,1) -> (1,1) |\r\n\r\nPentru a testa fiecare astfel de rezultat daca e sortat sau nu de urmatoarele $D-1$ straturi, nu vor trebui simulate toate in complexitate $O(N * 3^N/2^ * D)$. Prin generarea secventelor conform codului Gray in baza 3 putem doar sa urmarim modificarea rezultatului pentru doua rezultate succesive in $O(D)$. Un numar in baza trei il transformam in baza doi cu numar dublu de cifre, astfel:\r\n\r\n| 0 -> 00 | 1 -> 10 | 2 - > 11 |\r\n\r\nacest cod reprezentand un rezultat posibil dupa evaluarea unei secvente binare de catre primul strat al retelei. Modificarea unei cifre in baza trei conform codului Gray generalizat pentru numere in aceasta baza, duce la modificarea unei cifre in codul binar a unui bit. Urmarirea modificarilor facute de acest bit schimbat in evaluarile facute de reteaua de sortare o putem face in complexitate $O(D)$. Astfel complexitatea finala este $O(3^N/2^ * D)$.\r\n\r\nMentionam ca problema este pe site-ul InfoArena (\'Sortnet\':problema/sortnet) si acolo o rezolvare $O(2^N^ * D)$ intra in timp, dar si pentru aceasta trebuie sa folosim codul Gray si sa urmarim modificarile date de schimbarea unui bit in evaluare. Dam mai jos rezolvarea eleganta si usor de inteles a lui Mircea Pasoi:\r\n\r\n== code(cpp) |\r\n#include <stdio.h>\r\n\r\nint N, M, G[ 33 ][ 20 ], V[ 33 ], V2[ 33 ], Res;\r\n\r\ninline int GRAY(int x)\r\n{\r\n    return x ^ ( x >> 1 );\r\n}\r\n\r\ninline int BIT(int a, int b)\r\n{\r\n    return (a & (1 << b)) > 0;\r\n}\r\n\r\ninline int MIN(int a, int b)\r\n{\r\n    return (a < b) ? a : b;\r\n}\r\n\r\ninline int MAX(int a, int b)\r\n{\r\n    return (a > b) ? a : b;\r\n}\r\n\r\ninline int SORTED(int x)\r\n{\r\n    return (x & (x+1)) == 0;\r\n}\r\n\r\nint works(int n, int a)\r\n{\r\n    int i, b, t;\r\n\r\n    V2[0] = n;\r\n    for (i = 0; i < M; i++)\r\n    {\r\n        b = G[i][a];\r\n        if ((BIT(V[i], MAX(a, b)) && !BIT(V[i], MIN(a, b))) ||\r\n            (BIT(V2[i], MAX(a, b)) && !BIT(V2[i], MIN(a, b))))\r\n            a = b;\r\n        V[i] = V2[i];\r\n        V2[i+1] = V[i+1]^(1<<a);\r\n    }\r\n    V[M] = V2[M];\r\n\r\n    return SORTED(V[M]);\r\n}\r\n\r\nint main(void)\r\n{\r\n    int i, j, k, a, b, bit;\r\n\r\n    freopen(\"sortnet.in\", \"r\", stdin);\r\n    freopen(\"sortnet.out\", \"w\", stdout);\r\n\r\n    scanf(\"%d %d\\n\", &N, &M);\r\n    for (i = 0; i < M; i++)\r\n        for (j = 0; j < N/2; j++)\r\n        {\r\n            scanf(\"<%d,%d> \", &a, &b);\r\n            a--; b--;\r\n            G[i][a] = b; G[i][b] = a;\r\n        }\r\n\r\n    Res = 1;\r\n    for (i = 1; i < (1 << N); i++) \r\n    {\r\n        k = GRAY(i) ^ GRAY(i-1);\r\n        for (bit = 0; (1<<bit) < k; bit++);\r\n        Res += works(GRAY(i), bit);\r\n    }\r\n    printf(\"%d\\n\", Res);\r\n\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#biblio). Bibliografie\r\n\r\n# D.E.Knuth TAOC Prefascicle 2A\r\n# W.H. Press et. all. Numerical Recipies in C, Cambridge University Press\r\n# \'Gray code, wikipedia\':http://en.wikipedia.org/wiki/Gray_code\r\n',2044,'public',3686,NULL),('tabele-hash-scurta-prezentare','Tabele hash - scurta prezentare','2008-01-30 12:30:09','2009-02-26 18:20:06','h1. Tabele hash - scurta prezentare\r\n\r\n(Categoria _Structuri de date_, Autor _Mihnea Giurgea_)\r\n\r\n(toc){width: 20em}*{text-align:center;} *Continut*\r\n* \'Scopul tabelelor de dispersie\':tabele-hash-scurta-prezentare#scop\r\n* \'Adresare directa\':tabele-hash-scurta-prezentare#adresare_directa\r\n* \'Standard hashing\':tabele-hash-scurta-prezentare#standard_hashing\r\n* \'Functii de hash\':tabele-hash-scurta-prezentare#functii\r\n* \'In loc de concluzie\':tabele-hash-scurta-prezentare#concluzie\r\n\r\nh2(#scop). Scopul tabelelor de dispersie (hash tables)\r\n\r\nNe propunem sa cream o structura de date eficienta care sa poata face urmatoarele operatii cat mai repede posibil: _Insereaza_, _Cauta_ si _Sterge_. Ideea din spatele hashing-ului este memorarea unui element intr-un tablou sau lista, in functie de cheia sa. Pe cazul mediu toate aceste operatii necesita $O(1)$ timp. Sa vedem cum:\r\n\r\nh2(#adresare_directa). Adresare directa\r\n\r\nElementele sunt puse intr-un tablou alocat static pe pozitiile cheilor lor. Prin adresare directa, un element cu cheia $k$ va fi memorat in locatia $k$. Toate cele 3 operatii sunt extrem de simple (necesita doar o accesare de memorie), dar dezavantajul este ca aceasta tehnica \"mananca\" foarte multa memorie: $O(|U|)$, unde $U$ este universul de chei.\r\n\r\nh2(#standard_hashing). Standard hashing\r\n\r\nPrimul pas in a rezolva problema memoriei este de a folosi $O(N)$ memorie in loc de $O(|U|)$, unde $N$ este numarul de elemente adaugate in hash. Astfel, un element cu cheia $k$ nu va fi memorat in locatia $k$, ci $h(k)$, unde $h: U -> {0, 1, ..., N-1}$ - o functie aleasa aleator, dar determinista ({$h(x)$} va returna mereu aceeasi valoare pentru un anumit $x$ in cursul rularii unui program). Daca functia este aleasa aleator, elementele vor fi \"imprastiate\" in hash in mod egal. Ideal ar fi ca fiecare element sa fie stocat singur in locatia lui. Acest lucru insa nu este posibil, pentru ca $N < |U|$ si, deci, de multe ori mai multe elemente vor fi repartizate in aceeasi locatie. Aceasta problema se numeste coliziune.\r\n\r\nCum rezolvam coliziunile?\r\n\r\nh3. Inlantuire\r\n\r\nIn fiecare locatie din hash tinem o lista inlantuita; astfel, la oricare din cele 3 operatii se va parcurge toata lista. Pe un caz pur teoretic, toate cele $N$ elemente ar putea fi repartizate in aceeasi locatie, insa pe cazuri practice lungimea medie a celui mai lung lant este de {$lg(N)$}.\r\n\r\n* Memorie: $O(N)$\r\n* Pointeri: DA\r\n\r\nh3. Liste statice\r\n\r\nAceasta metoda este o imbunatatire a punctului anterior: pentru ca lungimea unui lant este cel mult {$lg(N)$}, putem sa folosim, in loc de liste inlantuite, vectori alocati dinamic de lungime $lg(N)$ - sau {$lg(N) + 3$}, ca sa fim siguri :). Scapam astfel de lucrul cu pointerii.\r\n\r\n* Memorie: $O(N*lg(N))$\r\n* Pointeri: NU\r\n\r\nh3. Adresare deschisa\r\n\r\nPrin adresare deschisa, toate elementele sunt memorate in tabela de hash. Pentru a realiza operatiile cerute, verificam succesiv tabela de hash pana cand fie gasim o locatie libera (in cazul _Inserarii_), fie gasim elementul cautat (pentru _Cauta_, _Sterge_). Insa, in loc sa cautam tabela de hash in ordinea $0, 1, ..., N-1$, sirul de pozitii examinate depinde de cheia ce se insereaza. Pentru a determina locatiile corespunzatoare, extindem functia de hash astfel incat sa contina si numarul de verificare ca un al doilea parametru $h: U * {0, 1, ..., N-1} -> {0, 1, ..., N-1}$. Astfel, cand vom insera un element, verificam mai intai locatia {$h(k, 0)$}, apoi {$h(k, 1)$} etc. Cand ajungem sa verificam {$h(k, N)$} putem sa ne oprim pentru ca tabela de hash este plina. Pentru cautare aplicam aceeasi metoda; daca ajungem la {$h(k, N)$} sau la o pozitie goala, inseamna ca elementul nu exista. Stergerile se fac insa mai greu, pentru ca nu se poate \"sterge\" pur si simplu un element deoarece ar strica tot hash-ul. In schimb, se marcheaza locatia ce trebuie stearsa cu o valoare $STERS$ si se modifica functia _Insereaza_ astfel incat sa vada locatiile cu valoarea $STERS$ ca pozitii goale.\r\n\r\n* Memorie: $O(N)$\r\n* Pointeri: NU\r\n\r\nh3. Double hashing-ul lui Mihai Patrascu\r\n\r\nO imbunatatire foarte mare la tabela de hashing este... inca o tabela de hashing. Vom avea 2 tabele, fiecare cu propria ei functie de hash, iar coliziunile le rezolvam prin inlantuire; cand inseram un element, il vom adauga in tabela in care intra intr-un lant mai scurt. Cautarea se face in ambele tabele in locatiile returnate de cele 2 functii de hash; stergerea la fel. Astfel, lungimea celui mai lung lant va fi, in medie, {$lg(lg(N))$}. Dar, in practica, lungimea unui astfel de lant nu va depasi $4$ elemente, pentru ca cel mai mic $N$ pentru care $lg(lg(N)) = 5$ este {$2^32^ ~ 4.000.000.000$}!!! Deci, in loc de liste folosim vectori statici de dimensiune $4$.\r\n\r\n* Memorie: $O(N)$\r\n* Pointeri: NU\r\n\r\nh2(#functii). Functii de hash\r\n\r\nToate functiile de hash intorc un numar intre $0$ si {$M-1$}, unde $M$ este dimensiunea maxima a tabelei de hash. Este recomandat ca $M$ sa fie ales un numar prim si sa se evite alegerea lui {$M=2^k^$}.\r\n\r\nh3. Pentru numere intregi:\r\n\r\n* $h(x) = x % M$\r\n* {$h(x) = (x * r) % M$}, $r$ - numar aleator ales la inceputul programului\r\n\r\nh3. Pentru numere reale\r\n\r\n* {$h(x) = [ {A * x} * M ]$}, $0 < A < 1$\r\n\r\n${x}$ - partea fractionara a lui $x$\r\n$[x]$ - partea intreaga a lui $x$\r\n$[x] + {x} = x$ - prin definitie\r\n$A$ este un numar care trebuie ales inainte sau la inceputul rularii programului. Alegerea lui influenteaza eficienta functiei. Knuth propune valoarea <tex>A = \\frac{(\\sqrt{5}-1)}{2} \\approx 0.6180339887...</tex>\r\n\r\nh3. Pentru adresarea deschisa\r\n\r\n* $h(x, i) = (h\'(x) + i) % M$\r\n* $h(x, i) = (h\'(x) + r1 * i + r2 * i^2^) % M$\r\n* $h(x, i) = (h1(x) + i * h2(x)) % M$\r\n$r1$, $r2$ - numere alese aleator la inceputul programului.\r\n\r\nh2(#concluzie). In loc de concluzie\r\n\r\nDesi o tabela hash poate fi implementata in diverse moduri (cu pointeri sau fara, cu mai multa sau mai putina memorie etc), nu pentru toate situatiile e la fel de usor de ales o functie eficienta. Implementarile mai complexe necesita mai multe sapaturi dupa functii bune. Iar de multe ori se prefera implementari concise si clare in locul celor stufoase care maresc eficienta, dar nu suficient. De aceea, cel mai frecvent mod de tratare al coliziunilor ramane inlantuirea. Mai multe detalii despre acesta, precum si anumite precizari despre cum sa alegi o functie hash buna in cazul diverselor tipuri de date, gasiti in articolul \'Tabele hash - prezentare detaliata\':tabele-hash-prezentare-detaliata preluat din cartea \"Psihologia concursurilor de informatica\" a lui Catalin Francu. In acelasi articol gasiti si o lista de aplicatii pentru aceasta structura de date eficienta.',2044,'public',3687,NULL);
 INSERT INTO `ia_textblock` VALUES ('siruri-de-sufixe','Siruri de sufixe','2007-05-21 16:33:05','2009-11-08 11:31:05','h1. Siruri de sufixe\r\n\r\n== include(page=\"template/implica-te/scrie-articole-2\" user_id1=\"amadaeus\" user_id2=\"Marius\") ==\r\n\r\n(Categoria _Structuri de date_, Autori _Adrian Vladu, Cosmin Negruseri_)\r\n\r\n(toc){width: 25em}*{text-align:center;} *Continut*\r\n* \'Introducere\':siruri-de-sufixe#introducere\r\n* \'Ce sunt sirurile de sufixe (suffix arrays)?\':siruri-de-sufixe#prezentare\r\n* \'Cum construim un sir de sufixe?\':siruri-de-sufixe#constructie\r\n* \'Calcularea celui mai lung prefix comun @(LCP)@\':siruri-de-sufixe#lcp\r\n* \'Cautarea\':siruri-de-sufixe#cautare\r\n* \'Probleme de concurs\':siruri-de-sufixe#probleme\r\n* \'Concluzii\':siruri-de-sufixe#concluzii\r\n* \'Bibliografie\':siruri-de-sufixe#bibliografie\r\n\r\nh2(#introducere). Introducere\r\n\r\nUn domeniu important in algoritmica folosita in practica este acela al algoritmilor pe siruri de caractere. Astfel, la concursurile de programare sunt prezente foarte multe probleme de prelucrare si procesare a unor siruri de caractere. In cadrul concursurilor si antrenamentelor multi dintre noi s-au lovit de probleme ce s-ar fi rezolvat usor daca se reusea in mod eficient determinarea existentei unui cuvant ca subsecventa a unui alt cuvant. Vom prezenta o structura versatila ce permite acest lucru, inlesnind de multe ori realizarea altor operatii utile pe un string dat.\r\n\r\nh2(#prezentare). Ce sunt sirurile de sufixe (suffix arrays)?\r\n\r\nPentru a avea o idee mai buna despre _suffix arrays_, vom face inainte o scurta prezentare a structurii de date numita in engleza _trie_ si a _arborilor de sufixe_ (suffix trees^{\'[1]\':siruri-de-sufixe#bibliografie}^) care sunt o forma speciala a structurii de date trie. Un trie este un arbore menit sa stocheze siruri. Fiecare nod al lui va avea in general un numar de fii egal cu marimea alfabetului sirurilor de caractere care trebuies stocate. In cazul nostru, cu siruri ce contin litere mici ale alfabetului englez, fiecare nod va avea cel mult 26 de fii. Fiecare muchie porneste din tata spre fii si va fi etichetata cu o litera distincta a alfabetului. Etichetele legaturilor de pe un drum de la radacina pana la o frunza vor alcatui un cuvant stocat in arbore. Dupa cum se observa, verificarea existentei unui cuvant in aceasta structura de date este foarte eficienta si se realizeaza in complexitate $O(M)$, unde $M$ e lungimea cuvantului. Astfel, timpul de cautare nu depinde de numarul de cuvinte pe care trebuie sa il gestioneze structura de date, fapt ce face aceasta structura ideala pentru implementarea dictionarelor.\r\n\r\nSa vedem acum ce este un _trie de sufixe_. Dat fiind un string $A$ = $a{~0~}a{~1~}...a{~n-1~}$, notam cu $A{~i~}$ = $a{~i~}a{~i+1~}...a{~n-1~}$ sufixul lui $A$ care incepe la pozitia $i$. Fie $n$ = lungimea lui $A$. Trie-ul de sufixe este format prin comprimarea tuturor sufixelor $A{~1~}...A{~n-1~}$ intr-un trie, ca in figura de mai jos. Trie-ul de sufixe corespunzator stringului $abac$ este:\r\n\r\np=. !siruri-de-sufixe?fig01v.png!\r\n\r\nOperatiile pe aceasta structura se realizeaza extrem de usor:\r\n\r\n* _verificarea daca un string $W$ este substring al lui $A$_ - este suficienta parcurgerea nodurilor, incepand din radacina si urmarind muchiile etichetate corespunzator caracterelor din $W$ (complexitate $O(|W|)$)\r\n\r\n* _cautarea celui mai lung prefix comun pentru doua sufixe ale lui $A$_ - se aleg nodurile $u$ si $v$ ale trie-ului corespunzatoare sfarsitului celor doua sufixe, iar prin aplicarea unui algoritm de gasire a LCA (Lowest Common Ancestor / cel mai apropiat stramos comun) se gaseste nodul corespunzator sfarsitului prefixului cautat. De exemplu, pentru $abac$ si $ac$ se gasesc nodurile $5$ si $6$. Cel mai apropiat stramos comun al lor este $2$, de unde rezulta prefixul $a$. Autorii va recomanda articolul \'[2]\':siruri-de-sufixe#bibliografie pentru o rezolvare in $O(sqrt(n))$, \'[3]\':siruri-de-sufixe#bibliografie pentru o prezentare accesibila a unei rezolvari in $O(log n)$ sau $O(1)$, si articolul \'[4]\':siruri-de-sufixe#bibliografie pentru un algoritm \"state of the art\".\r\n\r\n* _gasirea celui de-al $k$-lea sufix in ordine lexicografica_ - (complexitate $O(n)$, cu o preprocesare corespunzatoare). De exemplu al $3$-lea sufix al sirului $abac$ este reprezentat in trie-ul nostru de a $3$-a frunza.\r\n\r\nDesi ideea unui trie de sufixe este incantatoare la prima vedere, implementarea simplista in care inseram pas cu pas sufixele in structura noastra necesita un timp de ordinul $O(n^2^)$. Exista o structura numita _arbore de sufixe_^{\'[1]\':siruri-de-sufixe#bibliografie}^ care se poate construi in timp liniar fata de lungimea sirului de caractere. Arborele de sufixe este un trie de sufixe in care lanturile din care nu ieseau alte muchii erau comprimate intr-o singura muchie (in exemplul de mai sus acestea ar fi lanturile $2-3-4-5$ si $1-7-8-9$). Dar implementarea  algoritmului de complexitate liniara pentru construirea unui arbore de sufixe este anevoioasa, fapt care ne determina sa cautam o alta structura, mai usor de realizat.\r\n\r\nSa vedem care sunt sufixele lui $A$, parcurgand arborele in adancime. Avand in vedere faptul ca la parcurgerea in adancime trebuie sa consideram nodurile in ordinea lexicografic crescatoare a muchiilor care le leaga de tata, obtinem urmatorul sir de sufixe:\r\n\r\np=. !siruri-de-sufixe?fig07.png!\r\n\r\nEste usor de observat ca acestea sunt ordonate crescator. Pentru memorare, nu este necesar sa pastram un vector ordonat de sufixe, suficienta fiind pastrarea indicilor fiecarui sufix din sirul ordonat. Pentru exemplul de mai sus obtinem vectorul $P = (0, 2, 1, 3)$, acesta fiind array-ul de sufixe pentru stringul $abac$.\r\n\r\nh2(#constructie). Cum construim un sir de sufixe?\r\n\r\nPrima metoda care ne vine in minte este sortarea tuturor sufixelor lui $A$ folosind un algoritm de complexitate $O(n lg n)$. Insa compararea a doua sufixe se face in timp $O(n)$, deci complexitatea finala va fi $O(n^2^ lg n)$. Exista totusi un algoritm relativ usor de implementat si inteles, avand o complexitate de $O(n lg n)$. Desi este asimptotic mai mare decat cel al constructiei unui arbore de sufixe (suffix tree), in practica timpul de constructie al unui sir de sufixe este mult mai mic, din cauza constantei care apare in fata algoritmul liniar. De asemenea, cantitatea de memorie folosita in cazul implementarii cu memorie $O(n)$ este de la 3 pana la 5 ori mai mica decat in cazul unui arbore de sufixe.\r\n\r\nAlgoritmul se bazeaza pe mentinerea ordinii sufixelor sirului, sortate dupa prefixele lor de lungime $2^k^$. Astfel vom executa $m$ = $[log{~2~}n]$ (marginit superior) pasi, la pasul $k$ stabilind ordinea sufixelor daca sunt luate in considerare doar primele $2^k^$ caractere din fiecare sufix. Se foloseste o matrice $P$ de dimensiune $m x n$.  Notam cu $A{~i~}^k^$ subsecventa lui $A$ de lungime $2^k^$ ce incepe pe pozitia $i$. Pozitia lui $A{~i~}^k^$ in sirul sortat al subsecventelor $A{~j~}^k^$ $(j=0,n-1)$ se pastreaza in $P{~(k,i)~}$.\r\n\r\nPentru a trece de la pasul $k$ la pasul $k+1$ se concateneaza toate secventele $A{~i~}^k^$ cu $A{~i+2^k^~}^ k^$, obtinandu-se astfel substringurile de lungime $2^k+1^$. Pentru stabilirea ordinii se folosesc informatiile obtinute la pasul anterior. Pentru fiecare indice $i$ se pastreaza o pereche de intregi formata din $P{~(k,i)~}$ si $P{~(k,i+2^k^)~}$. Nu trebuie sa ne preocupe faptul ca $i+2^k^$ poate pica in afara sirului, deoarece vom completa sirul cu pseudocaracterul {@$@}, despre care vom considera ca este lexicografic mai mic decat oricare alt caracter. In urma sortarii, perechile vor fi aranjate conform ordinii lexicografice a substringurilor de lungime $2^k+1^$ corespunzatoare. Un ultim lucru care mai trebuie notat este ca la un anumit pas $k$, pot exista doua (sau mai multe) substringuri $A{~i~}^k^$ = $A{~j~}^k^$, iar acestea trebuie etichetate identic ({$P{~(k,i)~}$} trebuie sa fie egal cu {$P{~(k,j)~}$}). O imagine spune mai mult decat o mie de cuvinte:\r\n\r\np=. !siruri-de-sufixe?fig02.png!\r\n\r\nPasul 0:\r\n\r\np=. !siruri-de-sufixe?fig03.png!\r\n\r\nPasul 1:\r\n\r\np=. !siruri-de-sufixe?fig04.png!\r\n\r\nPasul 2:\r\n\r\np=. !siruri-de-sufixe?fig05.png!\r\n\r\nPasul 3:\r\n\r\np=. !siruri-de-sufixe?fig06.png!\r\n\r\nIata un pseudocod ce sugereaza pasii principali ce trebuie urmati:\r\n\r\n== code(c) |\r\nn <- lungime(A)\r\npentru i <- 0, n-1\r\n    P(0, i) <- pozitia lui Ai in sirul ordonat al caracterelor lui A\r\nsfarsit pentru\r\ncnt <- 1\r\npentru k <- 1, [log2 n] (marginit superior)\r\n    pentru i <- 0, n-1\r\n        L(i) <- (P(k-1, i), P(k-1, i+cnt), i)\r\n    sfarsit pentru\r\n    sorteaza L\r\n    calculeaza P(k, i), i = 0, n-1\r\n    cnt <- 2 * cnt\r\nsfarsit pentru\r\n==\r\n\r\nDe remarcat ca nu este neparat necesara o anumita numerotare a substringurilor, atat timp cat intre ele este pastrata o relatie de ordine valida. In vederea atingerii complexitatii $O(n lg n)$ pentru sortare se recomanda folosirea metodei _radix sort_ (de doua ori sortare prin numarare), aceasta avand complexitate $O(n)$. Insa, pentru usurarea implementarii, se poate folosi functia $sort()$ din STL (Standard Template Library, o librarie ce contine unele structuri de date si algoritmi in limbajul C++). Desi complexitatea va creste la $O(n lg^2^ n)$ in cazul cel mai defavorabil, implementarea devine simtitor mai simpla, iar in practica diferentele sunt abia sesizabile pentru siruri cu lungime mai mica decat $100 000$.\r\n\r\nMai jos puteti vedea o implementare extrem de scurta pentru suffix array in $O(n lg^2^ n)$.\r\n\r\n== code(cpp) |\r\n#include <cstdio>\r\n#include <cstring>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\nconst int MAXN = 65536;\r\nconst int MAXLG = 17;\r\n\r\nchar A[MAXN];\r\nstruct entry {\r\n    int nr[2], p;\r\n} L[MAXN];\r\nint P[MAXLG][MAXN], N, i, stp, cnt;\r\n\r\nbool cmp(const entry &a, const entry &b) {\r\n    return a.nr[0] == b.nr[0] ? (a.nr[1] < b.nr[1]) : (a.nr[0] < b.nr[0]);\r\n}\r\n\r\nint main() {\r\n    gets(A);\r\n    for (N = strlen(A), i = 0; i < N; ++i)\r\n        P[0][i] = A[i] - \'a\';\r\n    for (stp = 1, cnt = 1; cnt >> 1 < N; ++stp, cnt <<= 1) {\r\n        for (i = 0; i < N; ++i) {\r\n            L[i].nr[0] = P[stp - 1][i];\r\n            L[i].nr[1] = i + cnt < N ? P[stp - 1][i + cnt] : -1;\r\n            L[i].p = i;\r\n        }\r\n        sort(L, L + N, cmp);\r\n        for (i = 0; i < N; ++i)\r\n            P[stp][L[i].p] = i > 0 && L[i].nr[0] == L[i - 1].nr[0] && L[i].nr[1] == L[i - 1].nr[1] ? P[stp][L[i - 1].p] : i;\r\n    }\r\n    return 0;\r\n}\r\n==\r\n\r\nSirul de sufixe se va gasi pe ultima linie a matricei $P$. Cautarea celui de-al $k$-lea sufix in ordine lexicografica este acum imediata, deci nu vom reveni asupra acestui aspect.\r\nCantitatea de memorie folosita poate fi redusa renuntand la folosirea intregii matrice $P$ si pastrindu-se la fiecare pas doar ultimele doua linii ale acesteia. In acest caz, insa, structura nu va mai fi capabila sa execute eficient operatia ce urmeaza.\r\n\r\nh2(#lcp). Calcularea celui mai lung prefix comun (LCP)\r\n\r\nSe dau doua sufixe ale unui string $A$. Se cere calcularea celui mai lung prefix comun al lor. Am aratat ca un arbore de sufixe poate realiza aceasta in timp $O(1)$ cu o preprocesare corespunzatoare. Sa vedem daca un sir de sufixe poate atinge aceeasi performanta.\r\nFie cele doua sufixe $A{~i~}$ si $A{~j~}$. Folosind matricea $P$, putem itera descrescator de la cel mai mare $k$ pana la $0$ si verifica daca $A{~i~}^k^$ = $A{~j~}^k^$. Daca cele doua prefixe sunt egale, am gasit un prefix comun de lungime $2^k^$. Nu ne ramane decat sa actualizam $i$ si $j$, incrementandu-le cu $2^k^$ si sa verificam in continuare daca mai gasim prefixe comune. Codul functiei care calculeaza LCP este foarte simplu:\r\n\r\n== code(cpp) |\r\nint lcp(int x, int y) {\r\n    int k, ret = 0;\r\n    if (x == y) return N - x;\r\n    for (k = stp - 1; k >= 0 && x < N && y < N; --k)\r\n        if (P[k][x] == P[k][y])\r\n            x += 1 << k, y += 1 << k, ret += 1 << k;\r\n    return ret;\r\n}\r\n==\r\n\r\nComplexitatea este insa $O(lg n)$ pentru un calcul al acestui prefix. Reducerea la $O(1)$ se bazeaza pe urmatoarea observatie: $lcp(x, y)$ = $min{ lcp(x, x + 1), lcp(x + 1, x + 2), ..., lcp(y - 1, y) }$. Demonstratia este imediata daca ne uitam in arborele de sufixe corespunzator. Asadar, este suficient ca la inceput sa calculam cel mai lung prefix comun intre toate perechile de sufixe consecutive (timp $O(n lg n)$) si sa introducem o structura aditionala ce permite calculul in $O(1)$ al minimului dintr-un interval. Cea mai eficienta astfel de structura este cea pentru RMQ (range minimum query), despre care nu vom da detalii aici, dar care este studiata in amanunt in \'[3]\':siruri-de-sufixe#bibliografie, \'[4]\':siruri-de-sufixe#bibliografie si \'[5]\':siruri-de-sufixe#bibliografie. Cu inca o preprocesare in $O(n lg n)$ ceruta de noua structura putem acum sa raspundem in $O(1)$ query-urilor LCP. Structura folosita de RMQ cere tot $O(n lg n)$ memorie, asadar timpul si memoria finale necesare sunt $O(n lg n)$.\r\n\r\nh2(#cautare). Cautarea\r\n\r\nDeoarece sirul de sufixe ne ofera ordinea sufixelor lui $A$, cautarea unui string $W$ in $A$ se poate face simplu cu o cautare binara. Deoarece compararea se face in $O(|W|)$, cautarea va avea complexitatea $O(|W| lg n)$. Lucrarea \'[6]\':siruri-de-sufixe#bibliografie ofera structurii de date si algoritmului de cautare cateva rafinamente ce permit reducerea timpului la $O(|W| + lg n)$, dar autorii nu considera ca acestea sunt folositoare in concursurile de programare.\r\n\r\nh2(#probleme). Probleme de concurs\r\n\r\nAutorii au incercat sa adune cat mai multe probleme ce pot fi rezolvate cu ajutorul sirurilor de sufixe. Parcurgerea tuturor problemelor la prima citire, ar putea fi greoaie pentru un cititor care a avut primul contact cu aceasta structura de date citind acest articol. Pentru a usura lectura problemele sunt asezate intr-o ordine crescatoare a dificultatilor.\r\n\r\nh3. *Problema 1*: \'_Parola ascunsa_\':https://www.spoj.pl/problems/BEADS/ (acm 2003, enunt modificat)\r\n\r\nConsideram un sir de caractere de lungime $n$ $(1 &le; n &le; 100000)$. Sa se determine rotatia lui circulara lexicografic minima. De exemplu, rotatiile sirului de caractere $alabala$ sunt:\r\n$alabala$\r\n$labalaa$\r\n$abalaal$\r\n$balaala$\r\n$alaalab$\r\n$laalaba$\r\n$aalabal$\r\niar cea mai mica dintre ele in ordine lexicografica este $aalabal$.\r\n\r\nh3. Solutie:\r\n\r\nDe obicei, in probleme unde apare rotatia unui sir dat, putem sa ne folosim de trucul de a concatena sirului de caractere acelasi sir pentru a simplifica problema. Dupa aceasta transformare problema ne cere subsecventa lexicografica minima de lungime n a noului sir. Ordinea subsecventelor de lungime n ale unui sir este egala cu ordinea sufixelor determinate de subsecventele date, deci ne putem folosi de siruri de sufixe pentru a rezolva aceasta problema.\r\n\r\nO problema asemanatoare a fost propusa de unul dintre autori la concursul Bursele Agora, editia 2003-2004, care se putea rezolva pe aceiasi idee. Implementarea trebuia facuta atent pentru solutia oficiala era o rezolvare eficienta ce nu folosea aceasta structura de date.\r\n\r\nh3. *Problema 2*: _Sir_ (baraj 2004)\r\n\r\nSe considera un sir $c{~1~}c{~2~}...c{~n~}$ format din $n$ $(1 &le; n &le; 30 000)$ caractere din multimea ${A, B}$. Concatenam sirul cu el insusi si obtinem un sir de lungime $2n$. Pentru un indice $k$ $(1 &le; k &le; 2n)$ consideram subsecventele de lungime cel mult $n$, care se termina pe pozitia $k$, iar dintre acestea fie $s(k)$ subsecventa cea mai mica in ordine lexicografica. Determinati indicele $k$ pentru care $s(k)$ are lungimea cea mai mare. \r\n_Nota suplimentara_: fie $X$ si $Y$ doua siruri oarecare, iar \"$o$\" operatia de concatenare. In aceasta problema se va considera ca $X > X o Y$.\r\n\r\nh3. Solutie:\r\n\r\nSirul cautat este prima permutare circulara in ordine lexicografica a sirului dat. Notam cu $S{~i~}^k^$ substringul de lungime $k$ ce incepe la pozitia $i$. Fie $S{~i~}^n^$ cel mai mic substring in ordine lexicografica de lungime $n$ al sirului obtinut prin concatenare.  Presupunand prin absurd ca $s(i+n-1) < n$ ar insemna ca exista un $i\'$ $(i < i\' &le; j)$ astfel incat $S{~i\'~}^j-i\'+1^$ este lexicografic mai mic decat $S{~i~}^n^$. Dar din conditia impusa de enunt avem $S{~i\'~}^j-i\'+1^ > S{~i\'~}^n^$. Dar $S{~i\'~}^n^ > S{~i~}^n^$ => contradictie.\r\nDesi exista un algorirm de complexitate $O(n)$ specializat pentru siruri ce contin doar literele $A$ si $B$, metoda preferata de autor (si cu care a obtinut punctaj maxim in timpul concursului) a fost folosirea sirurilor de sufixe, ca in problema anterioara.\r\n\r\nh3. *Problema 3*: \'_Substr_\':http://infoarena.ro/problema/substr (baraj 2003) \r\n\r\nSe da un text format din $N$ caractere (litere mari, litere mici si cifre). Un substring al acestui text este o secventa de caractere care apar pe pozitii consecutive in text. Fiind dat un numar $K$, sa se gaseasca lungimea celui mai lung substring care apare in text de cel putin $K$ ori $(1 &le; N &le; 16384)$.\r\n\r\nh3. Solutie:\r\n\r\nAvand sufixele textului sortate, iteram cu o variabila $i$ de la $0$ la $N-K$ si calculam cel mai lung prefix comun intre sufixul $i$ si sufixul $i+K-1$. Prefixul maxim determinat in cursul acestei parcurgeri reprezinta solutia problemei.\r\n\r\nh3. *Problema 4*: \'_Ghicit_\':http://infoarena.ro/problema/ghicit (baraj 2003)\r\n\r\nTu si cu Taranul jucati un joc neinteresant. Tu ai un sir de caractere mare. Taranul iti spune un alt sir de caractere, iar tu trebuie sa raspunzi cat mai repede daca sirul respectiv este sau nu o subsecventa a sirului tau.\r\nTaranul  iti pune multe intrebari si, fiindca esti informatician, te-ai gandit ca ar merge mai repede daca ai sti dinainte toate sirurile despre care te poate intreba.\r\nInainte de a face toata acesta munca te-ar interesa numarul total de subsecvente distincte ale sirului tau, ca sa stii daca are sens sa te apuci de acesta treaba sau nu.\r\nScrieti un program care afla numarul de subsecvente distincte ale unui sir de caractere dat. $(1 &le; lungimea sirului &le; 10 000)$\r\n\r\nh3. Solutie:\r\n\r\nAceasta problema ne cere, de fapt, sa calculam numarul de noduri (fara radacina) ale trie-ului de sufixe asociat unui string. Fiecare secventa distincta din sir este determinata de drumul unic pe care il parcurgem in trie-ul de sufixe cand cautam acea secventa. Pentru exemplul $abac$ avem secventele $a$, $ab$, $aba$, $abac$, $ac$, $b$, $ba$, $bac$ si $c$, acestea sunt determinate de drumul de la radacina trieului spre nodurile $2$, $3$, $4$, $5$, $6$, $7$, $8$ si $9$ in aceasta ordine. Cum constructia trie-ului de sufixe are complexitate patratica, iar construirea unui arbore de sufixe este anevoioasa, este preferabila o abordare prin prisma sirurilor de sufixe. Obtinem sirul sortat de sufixe in $O(n lg n)$, dupa care cautam pozitia in care fiecare pereche de sufixe consecutive difera (folosind functia $lcp$) si adunam la solutie restul caracterelor. Complexitatea totala este $O(n lg n)$.\r\n\r\nh3. *Problema 5*: \'_SETI_\':http://infoarena.ro/problema/seti (ONI 2002, enunt modificat)\r\n\r\nSe da un string de lungime $N$ $(1 &le; N &le; 131072)$ si $M$ stringuri de lungime cel mult $64$. Se cere sa se numere aparitiile fiecarui string din cele $M$ in stringul mare.\r\n\r\nh3. Solutie:\r\n\r\nSe procedeaza la fel ca in cazul sirurilor de sufixe, numai ca este suficient sa ne oprim dupa pasul 6, unde am calculat relatia de ordine intre stringurile de lungime $2^6^ = 64$. Avand substringurile de lungime 64 sortate, fiecare query este rezolvat cu doua cautari binare. Complexitatea algoritmului este $O(N lg 64 + M * 64 * lg N) = O(N + M lg N)$.\r\n\r\nh3. *Problema 6*: _Subsecventa comuna_ (Olimpiada poloneza si TopCoder 2004, enunt modificat)\r\n\r\nSe considera trei siruri de caractere $S{~1~}$, $S{~2~}$ si $S{~3~}$, de lungimi $m$, $n$ si $p$ $(1 &le; m, n, p &le; 10000)$. Sa se determine subsecventa de lungime maxima care este comuna celor trei siruri. De exemplu, daca $S{~1~} = abababca$, $S{~2~} = aababc$ si $S{~3~} = aaababca$, atunci subsecventa comuna de lungime maxima pentru cele trei siruri este $ababc$.\r\n\r\nh3. Solutie:\r\n\r\nDaca ar fi vorba doar de doua siruri de lungimi mai mici am putea rezolva usor problema folosind metoda programarii dinamice; astfel, solutia pentru doua siruri ar avea ordinul de complexitate $O(N^2^)$.\r\nO alta idee ar fi sa consideram fiecare sufix al sirului $S{~1~}$ si sa incercam sa ii gasim potrivirea de lungime maxima in celelalte doua siruri.\r\nPotrivirea de lungime maxima rezolvata naiv ar avea complexitatea $O(N^2^)$, dar folosind algoritmul $KMP$^{\'[8]\':siruri-de-sufixe#bibliografie}^, putem obtine prefixul maxim al unui sir care se gaseste ca subsecventa in al doilea sir in $O(N)$, iar utilizand aceasta metoda pentru fiecare sufix al lui $S{~1~}$, am avea o solutie al carei ordin de complexitate este $O(N^2^)$.\r\nSa vedem ce se intampla daca sortam sufixele celor trei siruri:\r\n\r\np=. !siruri-de-sufixe?fig08.png!\r\n\r\nAcum interclasam prefixele celor trei siruri (consideram $&sect; < # < @ < a ...)$:\r\n\r\np=. !siruri-de-sufixe?fig09.png!\r\n\r\nSubsecventa comuna maxima corespunde prefixelor comune maxime pentru cele trei sufixe $ababca&sect;$, $ababc#$ si $ababca@$. Urmariti unde apar ele in sirul sortat al tuturor sufixelor. De aici avem ideea ca solutia se afla ca o secventa $[i..j]$ a sirului sortat de sufixe cu proprietatea ca secventa contine cel putin cate un sufix din fiecare sir, iar prefixul cel mai lung comun primului sufix din secventa si ultimul sufix din secventa este maxim; acest cel mai lung prefix este chiar solutia problemei. Alte subsecvente comune ale celor trei siruri ar fi prefixe comune pentru cate o subsecventa a sirului de sufixe sortat, de exemplu $bab$ pentru $bababca&sect;$, $babc@$, $babca&sect;$, sau $a$ pentru $a&sect;$, $a@$, $aaababca@$, $aababc#$. Pentru a determina aceasta secventa de prefix comun maxim putem folosi o parcurgere cu doi indici ({$start$} si $end$). Indicele $start$ variaza intre $1$ si numarul de sufixe, iar $end$ este cel mai mic indice mai mare decat $start$ astfel incat intre $start$ si $end$ sa existe sufixe din toate cele trei siruri. Astfel, perechea $[start, end]$ va indica, la un moment dat, secventa optima $[i..j]$. Aceasta parcurgere este liniara, deoarece $start$ poate avea cel mult $n$ valori, iar $end$ va fi incrementat de cel mult $n$ ori. Pentru a sorta sirul tuturor sufixelor nu este nevoie sa sortam mai intai sufixele fiecarui sir si apoi sa interclasam sufixele. Putem realiza operatia mult mai simplu concatenand cele trei siruri in unul singur (pentru exemplul considerat avem $abababca&sect;aababc@aaababca#)$ si sortand sufixele acestuia.\r\n\r\nh3. *Problema 7*: _Cel mai lung palindrom_ (USACO Training Gate)\r\n\r\nSe considera un sir de caractere $S$ de lungime $n$ $(1 &le; n &le; 20000)$. Determinati subsecventa de lungime maxima care este si palindrom (un sir de caractere este palindrom daca este identic cu sirul obtinut prin oglindirea sa).\r\n\r\nh3. Solutie:\r\n\r\nDaca dorim sa determinam, pentru un indice fixat $i$, care este cel mai mare palindrom centrat in $i$ atunci ne intereseaza prefixul maxim al subsecventei $S[i+1..n]$ care se potriveste cu prefixul subsecventei $S[1..i]$ reflectate. Pentru a rezolva cu usurinta aceasta problema sortam impreuna si sufixele sirului cu prefixele reflectate ale sirului (operatie care se realizeaza usor concatenand sirul $S&sect;$ cu sirul $S$ oglindit, $S^\'^$) si vom efectua interogari pentru cel mai lung prefix comun pentru $S[i+1]$ si $S^\'^[n-i+1]$ $(S^\'^[n-i+1] = S[1..i])$, la care putem raspunde folosind siruri de sufixe in timp $O(1)$. Astfel, putem rezolva problema in timp $O(N log N)$. Sa observam ca am tratat aici doar cazul in care palindromul este de lungime para, dar cazul in care palindromul are lungime impara se trateaza analog.\r\n\r\nh3. *Problema 8*: _Template_ (Olimpiada poloneza 2004, enunt modificat)\r\n\r\nPentru un string $A$, sa se determine lungimea minima a unui substring $B$ cu proprietatea ca $A$ poate fi obtinut prin lipirea intre ele a mai multor stringuri $B$ (la lipire doua stringuri se pot suprapune, dar in locurile in care se suprapun caracterele celor doua stringuri trebuie sa coincida). \r\n\r\nh4. Exemplu\r\n\r\nPentru string-ul $ababbababbabababbabababbababbaba$ rezultatul este $8$. String-ul $B$ de lungime minima este $ababbaba$. $A$ poate fi obtinut din $B$ astfel:\r\n\r\n$*ababbababbabababbabababbababbaba*$\r\n$ababbaba$\r\n$.....ababbaba$\r\n$............ababbaba$\r\n$...................ababbaba$\r\n$........................ababbaba$\r\n\r\nh3. Solutia 1:\r\n\r\nO solutie simpla foloseste siruri de sufixe, un arbore echilibrat si un $max-heap$ (se pot folosi structurile $set$ si $priority_queue$ din $STL$). Este evident ca sablonul cautat este un prefix al lui $A$. Asadar, pentru fiecare prefix $B$ al lui $A$ vom verifica daca prin lipirea tuturor aparitiilor lui $B$ in $A$ se obtine chiar cuvantul initial $A$. Pentru a face aceasta verificare este suficient calculul distantei dintre perechile de potriviri consecutive ale lui $B$. Trebuie sa avem grija ca prefixele sa acopere si sfarsitul sirului. Pentru aceasta, cel mai comod este sa mai consideram o aparitie a lui $B$ pe pozitia $n+1$. Daca distanta maxima gasita este mai mare decat lungimea lui $B$, acel prefix nu reprezinta o solutie. Pentru o rezolvare eficienta, vom considera initial $B$ ca fiind prefixul de lungime $1$, urmand sa introducem la sfarsitul sau, caracter cu caracter, restul caracterelor string-ului $A$. Daca la fiecare pas mentinem multimea $S$ a pozitiilor de inceput ale potrivirilor lui $B$ in $A$, dupa introducerea unui nou caracter in $B$, multimea $S$ va \"pierde\" anumite elemente (posibil niciunul). Pentru administrare eficienta, vom considera sirul sortat de sufixe ale lui $A$ si doi pointeri, $L$ si $R$, reprezentand primul, respectiv ultimul sufix din sir care il au ca prefix pe $B$. La adaugarea unui nou caracter in $B$, se incrementeaza, respectiv decrementeaza $L$ si $R$ cat timp acestea nu indica sufixe care il au ca prefix pe noul $B$. Arborele echilibrat va contine tot timpul pozitiile de inceput ale sufixelor continute intre $L$ si $R$, iar $heap-ul$ va contine distantele intre elemente consecutive ale arborelui. La inserarea unui nou caracter in $B$, trebuie sa avem grija de intretinerea acestor structuri. Algoritmul se incheie atunci cand cel mai mare (primul) element din $heap$ este mai mic sau egal cu lungimea lui $B$. Lungimea finala a lui $B$ ne ofera rezultatul cautat. Ordinul de complexitate este $O(N lg N)$, unde $N$ este lungimea lui $A$. Sa consideram un exemplu. $S$ este marcat cu $1$ in pozitiile in care s-a gasit o potrivire a lui $B$ in $A$:\r\n\r\n$1: aab$\r\n$2: aabaab$\r\n$3: ab$\r\n$4: abaab$\r\n$5: abaabaab$\r\n$6: b$\r\n$7: baab$\r\n$8: baabaab$\r\n\r\np=. !siruri-de-sufixe?fig12.png!\r\n\r\nh3. Solutia 2 (Mircea Pasoi):\r\n\r\nPentru sirul de caractere $S$, determinam pentru fiecare $i$ de la $1$ la $n$ lungimea celui mai lung prefix al lui $S$ cu $S[i..n]$. Aceasta operatie se poate realiza folosind siruri de sufixe. De exemplu, daca $S$ este sirul nostru si $T$ este sirul de potriviri maxime ale sufixelor, atunci:\r\n\r\np=. !siruri-de-sufixe?fig10.png!\r\n\r\nPentru toate lungimile posibile $k$ ale sablonului $(1 &le; k &le; n)$ verificam daca distanta maxima $d$ intre indicii celor mai departate doua elemente de valori mai mari sau egale cu $k$ in sirul $T$ nu este mai mare decat $k$. Prezentam in continuare un exemplu:\r\n\r\np=. !siruri-de-sufixe?fig11v.png!\r\n\r\nCea mai mica valoare a lui $k$ pentru care distanta $d$ este suficient de mica reprezinta lungimea sablonului cautat (in cazul precedent $k = 5$). Pentru a obtine un algoritm de complexitate buna trebuie ca acest pas sa fie eficient; putem sa folosim un arbore de intervale, sa folosim un contor cu $k$ care variaza de la $1$ la $n$ si sa eliminam din arbore elemente de marime mai mica decat $k$ si, la fiecare pas, sa actualizam arborele pentru a putea raspunde la interogari de genul: _care este distanta maxima intre doua elemente care exista acum in structura_. Algoritmul are complexitatea $O(N log N)$. Pentru o prezentare amanuntita a arborilor de intervale, va recomand \'[9]\':siruri-de-sufixe#bibliografie si \'[10]\':siruri-de-sufixe#bibliografie.\r\n\r\nh3. *Problema 9* (Olimpiada Baltica de Informatica^{%{font-size:12px}\'[11]\':siruri-de-sufixe#bibliografie%}^, 2004)\r\n\r\nUn sir de caractere $S$ se numeste repetitie $(K, L)$ daca $S$ se obtine prin concatenarea de $K &ge; 1$ ori a unui sir $T$ de lungime $L &ge; 1$. De exemplu, sirul $S = abaabaabaaba$ este o repetitie $(4, 3)$ cu $T = aba$. Sirul $T$ are lungimea trei si $S$ se obtine repetandu-l pe $T$ de patru ori. Avand un sir de caractere $U$ format din caractere $a$ si/sau $b$ de lungime $n$ $(1 &le; n &le; 50000)$, va trebui sa determinati o repetitie $(K, L)$ care apare ca subsecventa a lui $U$ astfel incat $K$ sa fie cat mai mare. De exemplu, sirul $U = babbabaabaabaabab$ contine repetitia $(4, 3)$, sirul $S$ incepand de pe pozitia $5$. Aceasta este si repetitia maxima, deoarece sirul nu mai contine nici o alta subsecventa care sa se repete de mai mult de patru ori. Daca sirul contine mai multe solutii cu acelasi $K$, poate fi aleasa oricare dintre ele.\r\n\r\nh3. Solutie:\r\n\r\nDorim ca pentru un $L$ fixat sa determinam cea mai mare valoare $K$ astfel incat in sirul $U$ sa avem o subsecventa $S$ care este repetitie $(K, L)$. Vom considera acum un exemplu: $U = babaabaabaabaaab$, $L = 3$ si o subsecventa fixata $X = aab$ care incepe pe pozitia $4$ a sirului $U$. Putem incerca sa extindem secventa $aab$ la ambele capete cat mai mult posibil prin repetarea ei asa cum vedem in continuare:\r\n\r\n$b a b *a a b* a a b a a b a a a b$\r\n$*a* a b a a b$\r\n$&emsp;a b a a b a a b a a b a *a b a*$\r\n\r\nExtinzand in acest mod cat mai mult in stanga secventa noastra si apoi extinzand la dreapta prefixul de lungime $L$ (in exemplul nostru prefixul de lungime $3$) al secventei obtinute, gasim cea mai lunga repetitie a unui sir de caractere de lungime $L$ cu proprietatea ca repetitia contine ca subsecventa sirul $X$ (daca repetitia este $(1, L)$ afirmatia anterioara nu este adevarata, dar acesta este un caz trivial). Acum observam ca pentru a identifica toate repetitiile $(K, L)$ cu $L$ fixat din sirul $U$, este suficient sa partitionam sirul in $n/L$ bucati si sa extindem aceste bucati. Remarcam ca daca va fi posibil sa realizam acest lucru pentru ficare bucata in $O(1)$ algoritmul final va avea ordinul de complexitate $O(n/1 + n/2 + n/3 + .. + n/n)$ (fiecare bucata se poate repeta in totalitate sau doar partial in stanga sau in dreapta, iar noi nu vom extinde fiecare bucata separat, ci bucatile adiacente le vom reuni intr-o noua bucata; asadar, daca avem $p$ bucati consecutine de aceeasi dimensiune, vom determina extinderile lor maxime in timp $O(p)$). Dar stim ca sirul $1 + 1/2 + 1/3 + 1/4 + .. + 1/n - ln n$ converge spre o constanta $c$, numita constanta lui $Euler$, si $c &lt; 1$; de aici tragem concluzia ca $O(n/1 + n/2 + n/3 + .. + n/n)$ = $O(n log n)$, deci algoritmul, in cazul in care extinderile maxime pot fi calculate usor, ar avea ordinul de complexitate $O(n log n)$. Acum intervin in rezolvarea noastra arborii de sufixe. Pentru a determina cu cat putem extinde cel mai mult subsecventa $U[i..j]$ a sirului $U$ la dreapta, practic ne intereseaza cel mai lung prefix comun al subsecventei $U[i..j]$ si al subsecventei $U[j+1..n]$. Pentru a extinde cat mai mult la stanga este suficient sa inversam sirul $U$ si ajungem sa rezolvam aceeasi problema. Am vazut ca problema celui mai lung prefix comun a doua secvente se rezolva in timp $O(1)$ cu ajutorul sirurilor de sufixe. Astfel, avem nevoie de crearea sirului de sufixe, etapa pe care o rezolvam intr-un timp de ordinul $O(n log n)$ si apoi de aplicarea algoritmului explicat anterior care are complexitatea $O(n log n)$. In concluzie, algoritmul prezent are complexitatea totala $O(n log n)$.\r\n\r\nh3. *Problema 10* (ACM SEER 2004)\r\n\r\nAvand un sir de caractere $S$ dat, se cere ca pentru fiecare prefix al sau sa se determine daca este un sir de caractere periodic. Astfel, pentru fiecare $i$ $(2 &le; i &le; N)$ ne intereseaza cel mai mare $K &ge; 1$ (daca exista un asemenea $K$) cu proprietatea ca prefixul lui $S$ de lungime $i$ poate fi scris cub forma $A^k^$ (sirul $A$ concatenat cu el insusi de $k$ ori) pentru un sir de caractere $A$. De asemenea, ne intereseaza si valoarea $k$ (avem $0 &le; N &le; 1000000$).\r\n\r\nh4. Exemplu\r\n\r\nPentru sirul $aabaabaabaab$ obtinem rezultatul prezentat in continuare:\r\n\r\n$2 2$\r\n$6 2$\r\n$9 3$\r\n$12 4$\r\n\r\nh4. Explicatii\r\n\r\n* prefixul $aa$ are perioada $a$;\r\n* prefixul $aabaab$ are perioada $aab$;\r\n* prefixul $aabaabaab$ are perioada $aab$;\r\n* prefixul $aabaabaabaab$ are perioada $aab$;\r\n\r\nh3. Solutie:\r\n\r\nSa vedem ce se intampla cand incercam sa potrivim un sir cu un sufix al sau. Consideram un sir si il impartim in doua, obtinand un prefix si un sufix:\r\n\r\n$S = aab aabaabaaaab$\r\n$suf = aab aabaaaab$\r\n$pre = aab$\r\n\r\nDaca sufixul se potriveste cu sirul initial pe un numar de caractere mai mare sau egal cu lungimea sirului $pre$, inseamna ca $pre$ este si un prefix al sufixului; deducem ca putem imparti si sufixul in $pre$ si $suf1$, iar sirul putem sa il impartim in $pre$, $pre$ si $suf1$. Daca sirul se potriveste cu sufixul pe un numar de caractere mai mare sau egal cu dublul lungimii sirului $pre$, atunci sufixul se potriveste cu $suf1$ pe un numar de caractere mai mare sau egal cu lungimea sirului $pre$, deci $suf1$ poate fi scris ca $pre$ si $suf2$, deci $suf$ poate fi scris ca $pre$, $pre$, $suf2$, iar $S$ poate fi scris ca $pre$, $pre$, $pre$, $suf2$:\r\n\r\n$S = aab aab aab aaaab$\r\n$suf = aab aab aaaab$\r\n$suf1 = aab aaaab$\r\n$pre = aab$\r\n\r\nObservam astfel ca daca sirul $S$ se potriveste cu sufixul sau pe cel putin $k * |pre|$ caractere, atunci $S$ are un prefix de lungime $(k+1) * |pre|$ care este periodic. Folosindu-ne de structura de date $siruri de sufixe$, putem determina pentru fiecare sufix potrivirea maxima cu sirul initial. Daca al $i$-lea sufix se potiveste cu sirul pe primele $k * (i-1)$ pozitii, atunci putem actualiza informatia care indica daca prefixele de dimensiune $j * (i-1)$ (unde $2 &le; j &le; k$) sunt periodice. Pentru fiecare sufix $S$, actualizarea tuturor informatiilor are ordinul de complexitate $O(n / (i-1))$. Astfel, ordinul de complexitate al algoritmului de rezolvare a acestei probleme este $O(n log n)$. Trebuie remarcat faptul ca putem obtine o rezolvare in timp $O(n)$ folosind o idee similara si algoritmul $KMP$, dar prezentarea acestei rezolvari depaseste scopul acestui articol.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nMentionam ca in timpul concursurilor autorii prefera solutiile ale caror ordine de complexitate sunt $O(n log^2^ n)$, mai lente, dar mai usor de implementat, si care folosesc un spatiu de memorie de ordinul $O(n)$. Din punctul de vedere al timpului real de executie, cele doua tipuri de solutii vor fi comparabile, iar in concurs simplitatea solutiei usureaza foarte mult implementarea si depanarea. Din cele prezentate putem concluziona ca sirurile de sufixe sunt o structura de date usor de implementat si foarte utila. In ultimii ani apar la concursuri tot mai multe probleme care necesita cunoasterea acestora. Mai putem observa si faptul ca polonezii propun probleme destul de grele la olimpiade. Speram ca acest articol va va fi de folos si ca de acum inainte sirurile de sufixe vor fi la indemana oricui are nevoie de ele pentru a le folosi intr-un concurs de informatica.\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Mark Nelson, _Fast string searching with suffix trees_\r\n# Mircea Pasoi, \'_Multe \"smenuri\" de programare in C/C++... si nu numai!_\':multe-smenuri-de-programare-in-cc-si-nu-numai\r\n# Emilian Miron, \'_LCA - Lowest common ancestor_\':lowest-common-ancestor\r\n# Michael A. Bender, Martin Farach-Colton, _The LCA Problem Revisited_\r\n# Erik Demaine, _MIT Advanced Data Structures, Lecture 11, April 2nd, 2003_\r\n# Udi Manber, Gene Myers, \'_Suffix arrays: A new method for on-line string searches_\':http://webglimpse.net/pubs/suffix.pdf\r\n# Mohamed Ibrahim Abouelhoda, Stefan Kurtz, Enno Ohlebusch, \'_Replacing suffix trees with enhanced suffix arrays_\':http://www.zbh.uni-hamburg.de/pubs/pdf/AboKurOhl2004.pdf, Journal of Discrete Algorithms 2, 2004\r\n# Thomas Cormen, Charles Leiserson, Ronald Rivest, \'_Introducere in algoritmi_\':http://zhuzeyuan.hp.infoseek.co.jp/ita/toc.htm, Editura Computer Libris Agora, 2000\r\n# Dana Lica, \'_Arbori de intervale_\':arbori-de-intervale\r\n# Cosmin Negruseri, \'_Cautari ortogonale_\':cautari-ortogonale, GInfo 15/5 (Mai 2005), Editura Agora Media\r\n# \'BOI 2004\':http://www.boi2004.lv/\r\n',9232,'public',3691,NULL),('algoritm-kuhn',' Algoritmul lui Kuhn (Ungar)','2007-04-03 22:20:23','2009-03-17 19:28:01','h1. Algoritmul lui Kuhn (Ungar)\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"sims_gl\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Tiberiu Florea_)\r\n\r\nh2. Introducere\r\n\r\nVoi prezenta in continuare problema afectarii impreuna cu una din cele mai eficiente solutii pentru rezolvarea ei: _Algoritmul lui Kuhn_. In ultima parte a articolului, voi oferi un exemplu de implementare usor de folosit in concursurile de informatica. Se presupun cunoscute notiunile de *cuplaj maxim* si *suport minim* intr-un graf bipartit, precum si modul de obtinere a unui cuplaj maxim intr-un graf bipartit cu ajutorul drumurilor de crestere. Sa incepem cu definitia problemei discutate.\r\n\r\n*Problema de afectare*: Exista {$m$} muncitori si $n$ lucrari, fiecare muncitor putand efectua una sau mai multe lucrari. Notam muncitorii cu $x{~1~}$ , $x{~2~}$, ..., $x{~m~}$, lucrarile cu $y{~1~}$, $y{~2~}$ , ..., $y{~n~}$, si asociem costul $v{~ij~}$ &le; $0$ efectuarii de catre muncitorul $x{~i~}$ a lucrarii $y{~j~}$, faptul ca $v{~ij~}$ = &#8734; avand semnificatia ca muncitorul $x{~i~}$ nu poate efectua lucrarea $y{~j~}$. Sa se gaseasca o repartizare a celor $m$ muncitori la cele $n$ lucrari astfel incat un muncitor sa efectueze cel mult o lucrare, iar o lucrare sa fie efectuata de cel mult un muncitor, cu conditia ca costul total de executie sa fie minim.\r\n\r\nDefinim *matricea de afectare* astfel: $X$ = $(x{~ij~})$, $1$ &le; $i$ &le; $m$, $1$ &le; $j$ &le; $n$, $x{~ij~}$ = $1$ daca muncitorul $x{~i~}$ efectueaza lucrarea $y{~j~}$, si $x{~ij~}$ = $0$ in caz contrar. Cand $&#8721;{~ij~}$ = $min(m, n)$, matricea de afectare se numeste *saturanta*. Voi prezenta algoritmul elaborat in 1955 de Kuhn, numit de acesta _algoritmul ungar pentru rezolvarea problemelor de afectare definite de matrice saturante_, cunoscut si sub numele de _metoda ungara_, deoarece se bazeaza pe rezultatele a doi matematicieni maghiari: D. K&#246;nig si E. Egerv&#225;ry. Demonstratia va presupune ca $m$ = $n$; se va vedea apoi ca algoritmul se poate extinde foarte usor la matrice care nu sunt patrate.\r\n\r\nh2. Descrierea algoritmului\r\n\r\nAlgoritmul utilizeaza urmatoarea proprietate:\r\n\r\n*Propozitia 1*: _Multimea solutiilor minime ale unei probleme de afectare nu se modifica daca la toate elementele unei linii sau coloane a matricei costurilor se aduna acelasi numar real &#955;._\r\n\r\nDe asemenea, este necesara cunoasterea urmatoarei teoreme:\r\n\r\n*Teorema 1 (Teorema lui K&#246;nig)*: _Fie $G$ un graf bipartit, $&#957;(G)$ cardinalul unui cuplaj maxim in acest graf, si $&#964;(G)$ cardinalul unui suport minim. Atunci exista egalitatea: $&#957;(G)$ = $&#964;(G)$, adica numarul maxim de muchii ale unui cuplaj este egal cu numarul minim de varfuri ale unui suport._\r\n\r\nDeoarece $m$ = $n$ si matricea de afectare este saturanta, orice solutie a problemei de afectare contine un singur $1$ in fiecare linie si in fiecare coloana, deci, prin transformarea matricei costurilor, costul asociat oricarei solutii creste cu &#955;. Din acest motiv, multimea solutiilor minime ale problemei de afectare nu se modifica prin transformari de acest tip ale matricei costurilor.\r\n\r\nAlgoritmul lui Kuhn se bazeaza si pe faptul ca o solutie a problemei de afectare corespunde unui cuplaj al grafului bipartit cu partile $X$ = {$x{~1~}$, $x{~2~}$, ..., $x{~n~}$} si $Y$ = {$y{~1~}$, $y{~2~}$, ..., $y{~n~}$}, si se desfasoara in mai multi pasi, fiind prezentat aici intr-o varianta modificata si simplificata fata de cea originala. Ideea este urmatoarea: daca prin anumite operatii de adunare a unei constante la toate elementele unei linii sau coloane a matricei costurilor toate numerele din matrice raman pozitive si exista un cuplaj de cardinal $n$ in graful bipartit definit de zerourile matricei, atunci solutia problemei se gaseste pe pozitiile nume din matrice.\r\n\r\nAcest lucru se demonstreaza imediat pe baza propozitiei $1$, avand in vedere faptul ca in matricea care contine numai numere nenegative nu poate exista o transversala cu costul negativ. Vom incerca, deci, sa aplicam in mod repetat transformarile descrise, pana cand va exista un cuplaj de cardinal maxim.\r\n\r\nVom adopta urmatoarele conventii de transpunere a limbajului de teoria grafurilor in termeni de matrice:\r\n\r\n* Spunem despre o linie sau despre o coloana ca este *acoperita* daca la un anumit pas face parte din multimea nodurilor marcate in cadrul procesului de determinare a unui suport minim.\r\n\r\n* Spunem despre un element al matricei ca este *incercuit* daca face parte din cuplajul gasit pana in momentul respectiv.\r\n\r\n* Spunem despre un element al matricei ca este *taiat* daca corespunde unei muchii care va putea fi folosita pentru obtinerea unui drum de crestere, intr-un sens ce va fi clarificat ulterior.\r\n\r\nh2. Algoritmul propriu-zis\r\n\r\nInitial, toate liniile si coloanele sunt decuplate. Algoritmul se va desfasura in $n$ pasi, fiecare pas decurgand dupa cum urmeaza:\r\n\r\nSe descopera toate liniile si coloanele matricei si se acopera toate coloanele cuplate. Se pastreaza elementele incercuite, dar se considera ca nici un element nu este taiat. Pornind de la cuplajul obtinut la pasul anterior, se determina un suport minim de acelasi cardinal, adica o multime de linii si coloane care acopera toate zerourile. Modul de obtinere a suportului minim a fost dezvoltat de Egerv&#225;ry, iar demonstratia corectitudinii sale depaseste scopul acestui articol. Cititorii interesati pot consulta Caius Iacob, _Matematici clasice si moderne_, vol. I, Bucuresti: Editura Tehnica, 1978 pentru o demonstratie completa. Atata timp cat putem gasi un zero descoperit pe o linie $i$ si o coloana $j$, il taiem si consideram urmatoarele doua cazuri:\r\n\r\n# *Linia $i$ este cuplata*: Acoperim linia $i$ si descoperim coloana cu care este cuplata. Coloana cu care este cuplata linia $i$ va fi mereu acoperita din cauza modului in care lucreaza algoritmul: in orice moment ori linia ori coloana pe care se afla un zero incercuit vor fi acoperite, deoarece initial toate coloanele cuplate sunt acoperite, si singura operatie pe care o efectuam este descoperirea unei coloane si acoperirea liniei cu care aceasta este cuplata.\r\n# *Linia $i$ nu este cuplata*: Incercam sa construim un drum de crestere, dupa cum urmeaza: \r\nPornim de pe pozitia pe care tocmai am taiat-o. Daca coloana in care se afla nu este cuplata, cuplam linia $i$ cu coloana $j$, si drumul de crestere este complet. Daca coloana $j$ este cuplata, continuam drumul de crestere cu zeroul incercuit din coloana $j$ si zeroul taiat care se gaseste pe linia acelui zero. Fie $k$ linia cu care este cuplata coloana $j$. $(k, j)$ este incercuit, coloana $j$ nu este acoperita, ceea ce inseamna ca linie $k$ este acoperita. Dar o linie nu poate fi acoperita decat in conditiile in care la un pas anterior am gasit un zero descoperit in acea linie, l-am taiat, si am descoperit coloana din care facea parte. In concluzie, vom putea gasi mereu un zero taiat pe linia care ne intereseaza. Deoarece numarul elementelor incercuite este finit, fiecare din ele va fi selectat cel mult o data, si vom putea mereu sa gasim un zero taiat cu care sa continuam drumul de crestere, rezulta ca in cele din urma vom gasi un zero taiat intr-o coloana necuplata, moment in care drumul de crestere va fi complet.\r\n\r\nDaca la pasul anterior nu am gasit un drum valid de crestere, vom considera matricea formata din elementele care nu apartin unor linii sau coloane acoperite si vom calcula minimul &#955; din elementele coloanelor neacoperite si il vom aduna la elementele liniilor acoperite. Deoarece toate zerourile sunt acoperite o singura data conform modului de obtinere a suportului minim, aceste operatii nu vor face sa dispara din zerourile obtinute pana la acest pas, si nici nu vor provoca aparitia unor elemente negative, insa vor produce cel putin inca un zero, pe pozitia pe care a fost gasit minimul. Suportul minim al matricei costurilor va creste cu cel putin o unitate prin aplicarea repetata a acestor pasi. Conform teoremei lui K&#246;nig, aceasta inseamna ca numarul elementelor unui cuplaj maxim al matricei obtinute creste cu cel putin o unitate, deci in cele din urma vom reusi sa gasim un drum de crestere cu ajutorul caruia sa marim cuplajul obtinut. Concluzia pe care o tragem este urmatoarea: la fiecare din cei $n$ pasi vom repeta aplicarea operatiilor descrise pana la obtinerea unui drum de ameliorare, iar cuplajul maxim va creste cu $1$. DUpa cei $n$ pasi, vom avea un cuplaj de cardinal $n$ care va corespune transversalei minime din matricea costurilor. Complexitatea algoritmului descris este $O(N^4^)$, insa se comporta bine in practica, in functie de costurile muchiilor grafului pe care se realizeaza cuplajul.\r\n\r\nh2. Detalii de implementare\r\n\r\nAlgoritmul lui Kuhn este destul de cunoscut de catre participantii la concursurile de informatica, dar nu este folosit foarte des, deoarece se considera ca este mult prea greu de implementat. In continuare se va vedea ca, cu putina atentie, metoda descrisa mai sus este implementabila in timp de concurs, in cel mult $10$ minute.\r\n\r\nAvem nevoie de o matrice $G$ care va retine graful propriu-zis. Pentru a nu irosi spatiul, in loc de a memora in alta parte matricea modificata, vom memora in vectorii $vr$ si $vc$ suma valorilor care au fost adaugate pe o anumita linie, respectiv scazute pe o anumita coloana. Vectorii $l$ si $r$ vor retine cu cine este cuplata o anumita linie, respectiv coloana, sau $0$ daca acea linie/coloana nu a fost cuplata inca. $p{~i~}$ = $j$ are semnificatia ca $(i, j)$ este taiat, iar vectorii $cr$ si $cc$ sunt folositi pentru a afla rapid daca o linie/coloana este acoperita. Fara alte comentarii, voi trece direct la prezentarea codului sursa care implementeaza pas cu pas cele descrise mai sus.\r\n\r\n== code(c) |\r\n#include <stdio.h>\r\n#include <string.h>\r\n\r\nint N, G[256][256], l[256], r[256], p[256], cr[256], cc[256], vr[256], vc[256];\r\n\r\nvoid find_zero () {\r\n    int i, j, min, t;\r\n\r\n    for (min = 1 << 30, i = 1; i <= N; ++ i) if (!cr[i])\r\n        for (j = 1; j <= N; ++ j) if (!cc[j])\r\n            min <?= G[i][j] + vr[i] - vc[j];\r\n\r\n    for (i = 1; i <= N; ++ i) if (cr[i]) vr[i] += min;\r\n    for (j = 1; j <= N; ++ j) if (!cc[j]) vc[j] += min;\r\n\r\n    for (i = 1; i <= N; ++ i) if (!cr[i])\r\n        for (j = 1; j <= N; ++ j) if (!cc[j] && G[i][j] + vr[i] == vc[j])\r\n            if (r[i]) {\r\n                p[i] = j, cr[i] = 1, cc[r[i]] = 0;\r\n                break;\r\n            } else {\r\n                do t = l[j], r[i] = j, l[j] = i, i = t, j = p[i]; while (t);\r\n                return;\r\n            }\r\n\r\n    find_zero ();\r\n}\r\n\r\nint main() {\r\n    int i, j, min, cnt;\r\n\r\n    scanf(\"%d\", &N);\r\n\r\n    for (i = 1; i <= N; ++ i)\r\n        for (j = 1; j <= N; ++ j) scanf(\"%d\", &G[i][j]);\r\n\r\n    memset (vr, 0, sizeof (vr)), memset (vc, 0, sizeof (vc));\r\n    memset (l, 0, sizeof (l)), memset (r, 0, sizeof (r));\r\n\r\n    for (cnt = 0; cnt < N; ++ cnt) {\r\n        memset (cr, 0, sizeof (cr)), memset (p, 0, sizeof (p));\r\n        memcpy (cc, l, sizeof (cc));\r\n        find_zero ();\r\n    }\r\n\r\n    return 0;\r\n}\r\n==\r\n\r\nh2. Optimizari\r\n\r\nCodul de mai sus a fost destul de compactat si optimizat incat sa nu mai aiba nevoie decat de urmatorul pas pentru a stoarce si ultima picatura de performanta din el: nu este nevoie sa pornim cu cuplajul de cardinal $0$. La inceput scadem valoarea minima din fiecare linie, apoi scadem valoarea minima din fiecare coloana. In acest moment putem sa parcurgem matricea pas cu pas si, cand gasim un element nul a carui linie si coloana nu au fost cuplate il adaugam la cuplajul initial. Astfel, nu vom mai fi nevoiti sa facem $n$ pasi, iar timpul de executie va scadea simtitor.\r\n\r\nh2. Extinderi\r\n\r\nDupa cum am promis, algoritmul lui Kuhn va putea fi aplicat si pe matrice ne-patrate. Daca $m$ &#8800; $n$ vom transforma matricea costurilor astfel:\r\n\r\n# pentru $m$ < $n$, se adauga matricei costurilor initiale $n$ - $m$ linii care contin numai $0$.\r\n# pentru $m$ > $n$, se adauga matricei costurilor initiale $m$ - $n$ coloane care contin numai $0$.\r\n\r\nIn cazul unor probleme de afectare pentru care se cauta o afectare saturanta care maximizeaza suma $&#8721;{~i,j~}x{~ij~}v{~ij~}$, vom defini o noua matrice a costurilor, ale care elemente sunt: $v\'{~ij~}$ = $v{~0~}$ - $v{~ij~}$, $1$ &le; $i$ &le; $m$, $1$ &le; $j$ &le; $n$, $v{~0~}$ = $max{~i,j~}v{~ij~}$. Observam ca daca matricea costurilor initiala contine un element egal cu &#8734; aceasta problema este banala, deci presupunem $v{~0~}$ < &#8734;. Solutia de cost minim a problemei cu matricea costurilor modificata va coincide cu solutia de cost maxim a problemei de afectare cu matricea costurilor initiala. Demonstratia este imediata, si ramane ca tema cititorului.',9893,'public',3701,NULL),('missing-numbers','Missing Numbers','2008-03-15 17:15:50','2009-02-22 10:39:02','h1. Probleme cu numere lipsa si nu numai...\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"alecman\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruseri_)\r\n\r\n(toc){width: 25em}*{text-align:center} *Cuprins*\r\n* \'Problema 1 ( _interviu Microsoft_ ) \':missing-numbers#prob1\r\n* \'Problema 2 ( _interviu Microsoft_ ) \':missing-numbers#prob2\r\n* \'Problema 3 ( _interviu Microsoft, lot 1999_ ) \':missing-numbers#prob3\r\n* \'Problema 4 ( _IBM Research: Ponder This_ ) \':missing-numbers#prob4\r\n* \'Problema 5 \':missing-numbers#prob5\r\n* \'Problema 6 ( _interviu Microsoft_ ) \':missing-numbers#prob6\r\n* \'Problema 7 \':missing-numbers#prob7\r\n* \'Problema 8 \':missing-numbers#prob8\r\n* \'Problema 9 \':missing-numbers#prob9\r\n* \'Problema 10 ( _el judge_) \':missing-numbers#prob10\r\n* \'Problema 11 ( _Info-Oltenia 2005, clasa a IX-a_) \':missing-numbers#prob11\r\n* \'Bibliografie\':missing-numbers#biblio\r\n\r\nh2(#prob1). Problema 1 ( _interviu Microsoft_ )\r\n\r\nSe dau $n-1$ numere distincte de la $1$ la $n$, sa se dea un algoritm cat mai eficient care sa determine numarul lipsa.\r\n\r\nh3. Rezolvare\r\n\r\nPrima rezolvare ce ne poate veni in minte este aceea de a verifica daca fiecare numar $1 -> n$ este prezent in sirul nostru, printr-o parcurgere (acest algoritm are complexitatea $O(n^2^)$ ). O alta rezolvare triviala ar fi sa sortam numerele si sa determinam prin parcurgere numarul $i$ pentru care $a[i] != i$ (pentru sortari rapide algoritmul are complexitatea $O(n log n)$ ).\r\n\r\nO rezolvare mai eficienta poate fi data folosind _Divide et Impera_. Putem imparti numerele in doua multimi, una in care vom pune numerele mai mici sau egale cu $n/2$, iar in cealalta restul. Acum vom sti din care din cele doua multimi lipseste numarul, dupa numarul de elemente al acestora. Considerand $T(n)$ timpul de executie al algoritmului, atunci complexitatea devine $T(n) = T(n/2) + O(n) = O(n)$. Deci algoritmul este liniar, si foloseste memorie $O(n)$, ignorand memoria consumata de stiva din algoritmul Divide et Impera ( $O(log n)$ ). O alta idee este de a folosi un tabel de dispersie sau un sir de valori booleene care va folosi memorie suplimentara $O(n)$ (poate fi redusa la $O(n/log n)$ daca se lucreaza pe biti).\r\n\r\nO rezolvare eleganta se foloseste de proprietatea ca suma numerelor naturale de la $1$ la $n$ este $n(n + 1)/2$. Numarul lipsa este egal cu diferenta dintre $n(n + 1 )/2$ si suma numerelor noastre. Aceasta solutie are complexitatea $O(n)$ (parcurgem sirul pentru a determina suma) ca timp si $O(1)$ ca memorie. Daca $n$ este destul de mare, s-ar putea ca $n(n+1)/2$ sa depaseasca domeniul de reprezentare al intregilor, rezultand in necesitatea implementarii operatiilor cu numere mari. Pentru a evita acest lucru folosim operatia **xor** (notata prin ^&and;^ ) si proprietatile ei $a ^&and;^ a = 0$ si $a ^&and;^ b = b ^&and;^ a$. Vom face suma xor a numerelor $a[i] ^&and;^ i$ (1 <= i <= n):\r\n$S = a[ 1 ] ^&and;^ 1 ^&and;^ a[ 2 ] ^&and;^ 2 ^&and;^ ... ^&and;^ a[ n - 1 ] ^&and;^ n - 1 ^&and;^ n$\r\n\r\nAstfel fiecare numar care apare in sir va fi in suma de doua ori si va fi anulat, iar rezultatul final va fi indicele numarului lipsa. Solutia are compexitatea $O(n)$ ca timp si $O(1)$ ca spatiu.\r\n\r\nh2(#prob2). Problema 2 ( _interviu Microsoft_ )\r\n\r\nSe da un sir de $n+1$ numere de la $1$ la $n$ in care unul se repeta, iar restul sunt distincte. Sa se dea un algoritm cat mai eficient care sa determine numarul ce se repeta.\r\n\r\nh3. Rezolvare\r\n\r\nEvident, abordarile de la problema anterioara se aplica si aici.\r\n\r\nh2(#prob3). Problema 3 ( lot 1999, _interviu Microsoft_ )\r\n\r\nSe da o lista inlantuita prin primul ei element. Se cere un algoritm cat mai eficient care sa determine daca lista are sau nu ciclu.\r\n\r\nh3. Rezolvare\r\n\r\nFie $n$ numarul total de elemente ale listei. O solutie triviala in $O(n)$ timp si $O(n)$ memorie ar fi sa parcurgem lista si sa adaugam pe rand elementele unui tabel de dispersie (cand apare de doua ori acelasi element rezulta ca am gasit un ciclu). O metoda folosita de unii concurenti este parcurgerea listei pe o perioada de timp determinata (timpul de executie fixat), fiind sanse mari ca un ciclu sa nu existe daca nu s-a gasit nici unul pana la momentul incheierii executiei.\r\n\r\nExista un algoritm mai elegant, care ruleaza tot in timp liniar. El se numeste _Algoritmul lui Floyd de detectie a ciclului intr-o lista_. O aplicatie importanta este _Algoritmul Pollard &rho;_, folosit pentru factorizarea intregilor cu multe cifre. Se folosesc doi pointeri $a$ si $b$, unde $a$ se misca de doua ori mai repede decat $b$ in lista (denumit si _Algoritmul iepurelui si testoasei_). Reprezentarea grafica seamana cu litera greceasca &rho;. Notam lungimea lantului cu &lambda; si lungimea ciclului cu &mu;.\r\n\r\n!missing-numbers?missing_numbers_pic2.png!\r\n\r\n== code(c) |\r\n//cap - pointer spre capatul listei\r\na = b = cap;\r\ndo{\r\n    b = b -> next;\r\n    a = a -> next -> next;\r\n}while(a != b);\r\n==\r\n\r\nCand $a$ si $b$ sunt amandoi in ciclu, este evident ca la un moment dat $a = b$. In exemplul desenat, dupa sase iteratii cei doi pointeri vor indica acelasi element. Pentru determinarea lungimii ciclului se mai poate face o parcurgere in care doar un pointer se misca. Acum dupa ce stim lungimea &mu; a ciclului, putem afla si lungimea &lambda; a lantului astfel: luam un pointer la inceputul listei si al doilea care a facut deja &mu; pasi in lista (amandoi pointerii au aceeasi viteza). Dupa &lambda; pasi ei vor fi egali. Astfel am obtinut o rezolvare liniara.\r\n\r\nh2(#prob4). Problema 4 ( _IBM Research: Ponder This_ )\r\n\r\nUn sir de lungime $n$ contine numere intregi din multimea ${1, 2, ..., n-1}$. Folosind _Principiul lui Dirichlet_ deducem ca cel putin un element se repeta. Gasiti un algoritm liniar care afiseaza o valoare ce se repeta, folosind memorie suplimentara constanta si nemodificand la nici un pas vreun element din sir.\r\n\r\nh3. Rezolvare\r\n\r\nAici nu merge solutia cu suma xor de la problemele $1$ si $2$ pentru ca numerele pot fi repetate oricum si nu putem folosi relatiile obtinute pentru a determina un numar care se repeta. Daca toate elementele din sir ar fi distincte, atunci sirul ar avea structura unei permutari. Cum ele nu sunt neaparat distincte ne vine ideea de a vedea care este diferenta intre un asemenea sir si o permutare, pentru a folosi idei care apar la permutari (ciclurile acestora). Fiecare element din sirul nostru indica inspre altul, deci il putem considera un graf orientat in care arcele sunt $(i, a[i])$. De exemplu putem face urmatoarea reprezentare pentru sirul $3, 2, 1, 3, 4$:\r\n\r\n!missing-numbers?missing_numbers_pic3.png!\r\n\r\nDin fiecare nod iese cate un arc si cum sunt un numar finit de noduri rezulta ca din orice nod pornim ajungem intr-un ciclu. In momentul in care intram in ciclu, acel numar se va repeta, deci vrem ca primul nod sa nu apartina nici unui ciclu. Un astfel de nod e nodul $n$, pentru ca nici un element $a[i]$ nu va fi egal cu $n$. Deci, daca pornim de la nodul $n$ suntem in afara oricarui ciclu si putem sa mergem pe drumul pe care il indica pentru a ajunge eventual intr-un ciclu. Am vazut in problema anterioara cum determinam lungimea lantului pentru o lista ce contine un ciclu. Putem determina astfel elementul de la intrarea in ciclu in complexitate $O(n)$ si problema noastra este rezolvata.\r\n\r\nh2(#prob5). Problema 5\r\n\r\nSe da un sir de $N$ intregi ce contine numere intre $1$ si $N$. Sa se determine cat mai eficient daca acest numar este o permutare, fara a distruge sirul.\r\n\r\nh3. Rezolvare\r\n\r\nPentru ca valorile sirului sunt intregi, iar valorile elementelor unei permutari sunt pozitive, rezulta ca putem folosi bitul de semn al fiecarui numar pentru ca acesta ramane liber. Verificam mai intai daca exista vreun element negativ in sir. Apoi, daca nu exista, vom marca elementele parcurse din ciclurile permutarii astfel $a[i] = -a[i]$. Daca un element este marcat de doua ori sau am gasit initial un numar negativ, atunci cele $N$ numere nu reprezinta o permutare. Pentru a reface sirul initial, vom schimba toate elementele ce au semn negativ din sir cu valorile lor in modul. Astfel am obtinut o rezolvare liniara ce foloseste spatiu suplimentar $O(1)$.\r\n\r\nh2(#prob6). Problema 6 ( _interviu Microsoft_ )\r\n\r\nSe dau n numere de la 1 la n. Unul din ele unul apare de doua ori in sir, iar restul sunt distincte. Evident ca un numar nu va aparea niciodata. Sa se dea un algoritm cat mai eficient care sa determine numarul lipsa si numarul ce apare de doua ori.\r\n\r\nh3. Rezolvare\r\n\r\nNotam cu $a$ numarul lipsa si cu $b$ numarul ce apare de doua ori. Majoritatea celor care stiu sa rezolve problema $1$ prin cele doua solutii optime (suma numerelor si suma xor) incearca sa rezolve aceasta problema determinand doua relatii diferite asupra lui $a$ si $b$, din care apoi incearca sa obtina valorile cerute. Scazand din $n(n + 1)/2$ suma numerelor din fisier obtinem valoarea pentru $a - b$, iar facand suma xor a numerelor din fisier si a numerelor de la $1$ la $n$ obtinem valoarea pentru $a ^&and;^ b$. In acest moment putem considera ca problema este rezolvata, dar la o analiza mai atenta se poate observa ca numerele care verifica relatiile respective nu sunt unice. De exemplu pentru $a = 10$ si $b = 9$ obtinem valorile $a - b = 1$ si $a ^&and;^ b = 3$. Aceleasi valori le obtinem si pentru $a = 6$ si $b = 5$. Se observa de aici ca cele doua relatii nu pot fi folosite pentru a rezolva problema.\r\nStim care este valoarea diferentei $D{~1~} = a - b$, dar mai avem nevoie de o relatie pentru a determina numerele $a$ si $b$. Vom incerca in continuare sa folosim operatia de inmultire pentru a obtine cea de-a doua relatie. Vom avea: $a/b = n! / (a[ 1 ] * a[ 2 ] * ... * a[ n ])$. Aceasta relatie nu poate fi calculata in $O(n)$ pentru ca numarul de cifre al lui $n!$ nu este constant. Pentru a evita lucrul cu numere mari am putea sa logaritmam intreaga relatie, obtinand $lg a - lg b = lg 1 + lg 2 + ... + lg n - lg a[ 1 ] - lg a[ 2 ] - ... - lg a[ n ]$. Aceasta rezolvare ar fi buna daca ar fi posibila realizarea unor calcule perfecte cu numere reale. Din pacate acest lucru nu este posibil si rezolvarea are mari probleme cu precizia. \r\nO a doua relatie o putem obtine ca diferenta intre suma patratelor numerelor de la $1$ la $n$ si suma patratelor numerelor din fisier. Obtinem astfel $D{~2~} = a^2^ - b^2^$. Din aceste doua relatii putem usor afla ca $a = (D{~1~} + D{~2~}/D{~1~})/2$ si $b = (D{~2~}/D{~1~} - D{~1~})/2$. Aceasta rezolvare are complexitatea $O(n)$ ca timp si $O(1)$ ca spatiu.\r\n\r\nh2(#prob7). Problema 7\r\n\r\nSe dau $n - k$  numere distincte de la $1$ la $n$. Sa se dea un algoritm cat mai eficient care sa determine numerele lipsa.\r\n\r\nh3. Rezolvare\r\n\r\nFie $a, b, c, ...$ numerele ce lipsesc. Am putea extinde ideea din problema anterioara pentru a obtine in $O(n*k)$ sumele $S{~1~} = a + b + c + ..., S{~2~} = a^2^ + b^2^ + c^2^ + ..., ..., S{~k~} = a^k^ + b^k^ + c^k^ + ...$ si sa obtinem valorile elementelor $a, b, c, ...$, dar in general daca valoarea lui $k$ este variabila, atunci putem gasi solutia ce satisface toate cele $k$ relatii in timp exponential. O metoda este de a transforma relatiile intr-un polinom de radacini $a, b, c, ...$. Pentru a gasi $P(x) = a{~0~}X^k^ + a{~1~}X^k-1^ + ... + a{~k~}$ putem folosi relatiile lui Viete[1]\r\n$s{~1~} = a + b + c + d + ...$ \r\n$s{~2~} = ab + ac + ad + bc + bd + cd + ...$\r\n$s{~3~} = abc + acd + bcd + ...$\r\n$s{~4~} = abcd + ...$\r\n...\r\n$s{~i~} = (-1)^i^ a{~n-i~}/a{~n~}$\r\n\r\nAceste sume $s{~k~}$ sunt numite polinoame simetrice si sunt strans legate de sumele de puteri $k S{~k~}$ prin relatiile Newton Girard[2]. Astfel avem un algoritm ce determina polinomul in $O(nk)$ si spatiu $O(k)$ (daca se ignora faptul ca numerele ar putea depasi intervalul numerelor reprezentabile pe un intreg), dar determinarea solutiei finale se poate face in $O(1)$ doar pentru ecuatii de gradul doi sau trei, pentru care stim formule de calcul. Pentru ecuatii de grad mai mare nu exista formule generale si trebuie aplicate metode care aproximeaza solutiile. O astfel de metoda ar fi sa derivam polinomul, sa gasim solutiile pentru $P\'(x) = 0$, iar apoi sa folosim cate o cautare binara pentru a gasi solutiile $P(x) = 0$.\r\nDe exemplu pentru trei numere lipsa $a, b, c$ este usor sa determinam $S{~1~} = a + b + c, S{~2~} = a^2^ + b^2^ + c^2^, S{~3~} = a^3^ + b^3^ + c^3^$. $S{~1~}^2^ = a^2^ + b^2^ + c^2^ + 2ab + 2bc + 2ac = S{~2~} + 2s{~2~}, S{~1~}^3^ = a^3^ + b^3^ + c^3^ + 3a^2^b + 3a^2^c + 3b^2^a + 3b^2^a + 3c^2^a + 3c^2^b + 6abc = S{~3~} + 3(a^2^b + b^2^a + abc) + 3(a^2^c + c^2^a + abc) + 3(b^2^c + c^2^b + abc) - 3abc = S{~3~} + 3ab*s{~1~} + 3ac*s{~1~} + 3bc*s{~1~} - s{~3~} = S{~3~} + 3s{~2~}*s{~1~} - s{~3~}$. Din aceste relatii putem sa obtinem usor $s{~1~}, s{~2~}, s{~3~}$ si apoi putem aplica formulele lui Cardano de rezolvare a ecuatiei de gradul trei pe ecuatia $x^3^ - s{~1~} x^2^ + s{~2~} x - s{~3~} = 0$.\r\n\r\nh2(#prob8). Problema 8\r\n\r\nIntr-o structura de date avem $n - 1$ numere intregi (pentru simplitate $n = 2^b^ - 1$, cu numere distincte de la $0$ la $n$). Asupra elementelor din structura de date putem face urmatoarea operatie getBit(i, j), care returneaza al $j$-lea bit din reprezentarea binara a numarului $a[ i ]$. Astfel daca $a[ 4 ] = 11$, atunci getBit(4, 3) returneaza $0$ pentru ca $11$ se scrie in baza $2$ ca $1011$. Sa se dea o solutie eficienta care gaseste numarul lipsa.\r\n\r\nh3. Rezolvare\r\n\r\nAcum vom folosi din nou un algoritm bazat pe Divide et Impera. La primul pas impartim multimea in doua submultimi - cea a numerelor pare si cea a numerelor impare, si vedem in care din ele se gaseste numarul nostru lipsa (am aflat astfel ultimul bit al rezultatului). Acum putem aplica recursiv procedura aceasta pe numerele din o lista cu jumatate din lungimea listei initiale impartite la doi (ignoram ultimul bit al numerelor). Aceasta solutie are complexitate $O(n)$ pentru ca dupa fiecare pas executat in timp liniar, dimensiunea problemei se injumatateste. Memoria suplimentara e $O(n)$ (doi vectori care sa pastreze indicii elementelor pare, respectiv impare).\r\n\r\nh2(#prob9). Problema 9\r\n\r\nGeneralizam problema anterioara si se cere un algoritm eficient pentru un sir din care lipsesc $n - k$ numere.\r\n\r\nh3. Rezolvare\r\n\r\nDin nou vedem cate numere din sir au ultima cifra $0$ si cate au $1$. Astfel putem determina $k{~0~}$ - numarul de valori lipsa cu ultima cifra $0$, si $k{~1~}$ - numarul de valori lipsa care au ultima cifra $1$. Daca notam timpul de rezolvare al problemei noastre $T(n, k)$, acum avem de rezolvat doua subprobleme cu timpii $T(n/2, k{~0~})$ si $T(n/2, k{~1~})$. Acum impartim cele $k{~0~}$ numere in $k{~00~}$ si $k{~10~}$ valori care se termina in $00$, respectiv $10$ in reprezentarea in baza $2$. Aceasta solutie are complexitate $O(n log n)$ si nu imbunatateste cu nimic solutia in care sortam elementele sirului.\r\n\r\nh2(#prob10). Problema 10 ( _el judge_ )\r\n\r\nSe dau $n$ numere intregi astfel incat fiecare numar apare de un numar par de ori, in afara de unul singur, care apare de un numar impar de ori. Se cere determinarea acelui numar. De exemplu in sirul $1 2 2 3 1 2 2 2 3 3 3$, numai elementul $2$ apare de un numar impar de ori.\r\n\r\nh3. Rezolvare\r\n\r\nEste evident ca daca facem suma xor a tuturor numerelor, rezultatul va fi numarul ce apare de numar impar de ori. Astfel solutia are complexitatea $O(n)$ ca timp si $O(1)$ ca memorie folosita.\r\n\r\nh2(#prob11). Problema 11 ( _Info-Oltenia 2005, clasa a IX-a_ )\r\n\r\nSe dau $n$ siruri formate din cifre de la $1$ la $8$ (inclusiv), de lungime maxima $500$. Toate sirurile sunt repetate de $k$ ori sau de multiplu de $k$ ori, cu exceptia unui singur sir, care nu este repetat de $k$ ori, sau de multiplu de $k$ ori. Sa se afiseze sirul care nu se repeta. ( $1 <= n <= 32000, k < 2005$ )\r\n\r\nh3. Rezolvare\r\n\r\nPutem face o solutie similara cu cea de mai sus. Consideram un tablou $A$ cu $500 * 8$ elemente, fiecare linie $i$ corespunzand cifrelor de pe pozitia $i$ din sirurile de cifre date la intrare. Cand procesam un sir dintre cele date la intrare, daca el are pe pozitia $i$ cifra $j$ atunci incrementam elementul $A[ i ][ j ]$. In acest tablou, pe fiecare linie $i$, toate elementele in afara de unul vor fi $0$ sau multiplu de $k$, iar elementul $A[ i ][ j ]$ care nu e multiplu de $k$ este a $j$-a cifra a numarului care se repeta de un numar de ori ce nu este divizibil cu $k$. Aceasta solutie are complexitate ca timp $O(n*L)$, iar ca spatiu $O(L)$, unde $L$ este lungimea maxima a unui sir de cifre.\r\n\r\nh2(#biblio). Bibliografie\r\n\r\n*(#fn1) 1. \'Relatiile lui Viete, _mathworld_ \':http://mathworld.wolfram.com/VietasFormulas.html\r\n*(#fn2) 2. \'Formulele Newton-Girard, _mathworld_ \':http://mathworld.wolfram.com/Newton-GirardFormulas.html\r\n*(#fn3) 3. {\'Cycle detection, _wikipedia_ \':http://en.wikipedia.org/wiki/Floyd\'s_cycle-finding_algorithm}',6172,'public',3702,NULL),('planificare/sedinta-20090126','Sedinta 2009-01-26','2009-01-22 17:34:00','2009-02-22 21:46:50','h1. Sedinta 2009-01-26\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe întâlnim *luni, 26 ianuarie* la ora *19^00^* la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")== (inca nu stiu cand scap de la examen)\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"alexthero\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinta anterioara\':planificare/sedinta-20090112| ==user(user=\"domino\" type=\"tiny\")==|\r\n|OKRs Q12009| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n|Algoritmiada| ... |\r\n|Stelele| ==user(user=\"silviug\" type=\"tiny\")==|\r\n|Fix-it camp| ... |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n* Despre Stele\r\n** Sunt ok datele: 31-1 pentru 9-10 si 6-7 pentru 11-12?\r\n** Seturi de probleme\r\n*** Se dau ~120 RON pe problema (e pe bani!)\r\n*** Avem probleme pentru 9-10? Cate?\r\n*** Pentru 11-12 trebuie sa ne intalnim (fara Bogdan si Cosmin) la ICHB. Marti/miercuri?\r\n\r\nDiscutii despre probleme la 9-10. Intalnire marti-miercuri pentru 11-12.\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Cristi face blog post despre OKR-uri\r\n* Silviu stabileste contacte cu Poli\r\n* Fixit camp:\r\n** Cristi si Silviu vorbesc de premii %{color:red;}(done)%\r\n* Stele %{color:red;}(done)%:\r\n** Ne intalnim maine la 10 la ICHB sa vorbim de probleme: Silviu, Adi, Paul, Victor, Stefan. Victor vorbeste cu Wef\r\n** Cristi baga newsletter si Silviu ii zice din timp (minim 3 zile)\r\n** Cristi vorbeste cu Ali pentru configurarea proxy-ului\r\n** Cristi face .htaccess pentru a bana forumul\r\n* Algoritmiada:\r\n** Se face pe 15 februarie\r\n** Sponsori posibili: Adobe, Microsoft, iRealSoft\r\n* Il iertam pe Mort de datorie (a gresit la calcule)\r\n* Coding camp:\r\n** 28 februarie - 1 martie\r\n** Cine vine: Cristi, Vali, Prostu, Bogdan, Victor, Cosmin, Stefan, Mircea\r\n** Probabil: Silviu, Paul, Adi, Wef\r\n** Tero baga de acasa\r\n** Mircea face planul de coding camp (Virtual Contest e prioritar)\r\n*** Reorganizat sidebar si topnav (Cristi are idei, link la index de newsletter)\r\n*** Solutie de backup\r\n** Cristi se ocupa de locatie %{color:red;}(done)%\r\n* Nu facem fixit camp in Q1\r\n* Mircea se uita sa vada cati oameni au trimis doar in Arhiva Educationala %{color:red;}(31 de useri, 251 de joburi; 74 care au trimis doar in Arhiva Educationala si cel mult la Adunare si/sau CMMDC)%\r\n* Vali face IAP si OKR despre ordonarea problemelor (vezi formula de la IMDB) %{color:red;}(working on it, sorry de delay!)%:\r\n* Incercam \"video sedinta\" cu Airinei (webcam/Skype)\r\n* Lumea da feedback la IAP 7 pana la urmatoarea sedinta\r\n* Cristi face blog post despre 2% %{color:red;}(done)%:\r\n* Silviu vorbeste cu Mars despre evaluator ( %{color:red;}(done)%: ce facea Mars nu adreseaza problema noastra)\r\n* Mircea trimite mail pentru cine nu si-a completat OKR-urile\r\n* Facem sedinta pe 16 februarie. Cosmin cumpara apa, suc si pahare (bon cu stampila). Cristi se ocupa de sala. %{color:red;}(done)%\r\n* Paul, Prostu, Tero & Co trimit poza si descriere lui Cosmin pentru blog despre membri noi. %{color:red;}(Paul, Tero done)%\r\n\r\nh2. Notite\r\n\r\n* Punem stire ca nu mai ai voie cu HTML si sa-si actualizeze lumea profilele\r\n* Stefan discuta cu Marius Stroe dupa finala\r\n',13,'public',NULL,NULL),('blog/okrs-20091','Obiective infoarena','2009-02-16 15:39:49','2009-02-23 11:17:37','\'Echipa infoarena\':echipa-infoarena a crescut cu 7 membri noi în anul 2008, la fel şi comunitatea infoarena şi numărul de proiecte pe care le-am început împreună. Toate bune şi frumoase, doar că această creştere ne-a obligat să căutăm metode mai eficiente de a ne organiza şi de a lucra împreună. Vă povestesc în continuare despre sistemul „OKR” şi obiectivele infoarena pe acest trimestru.\r\n\r\nNoi, echipa infoarena, ne întrunim periodic în şedinţe \'încă din 2006\':planificare. Ce se întâmplă la o şedinţă tipică? Păi, în afara faptului că facem glume şi pierdem vremea aiurea, stabilim ce \'concursuri\':concursuri să organizăm, când facem \'următorul coding camp\':planificare/camp-2.2.1, ce \'facilităţi\':http://hackers.devnet.ro/report/1 mai adăugăm la site (sau mai scoatem) şi pe care dintre membrii comunităţii infoarena îi rugăm să intre în echipă alături de noi. Ce _altceva_ se mai întâmplă la şedinţele infoarena e o taină sacră şi nu pot să o divulg aici pe blog. :)\r\n\r\nŞedinţele sunt foarte bune pentru că ne ajută să ne punem la curent unii cu ceilalţi despre progresele pe care le facem şi problemele pe care le întâmpinăm. Din păcate, nu mai sunt de ajuns. Ce mai trebuie să faci ca mulţi oameni să lucreze eficient împreună? Nu ştiu, însă e nevoie măcar de un ţel comun, de un reper spre care să navigheze toţi, de nişte obiective. Din acest motiv am adoptat \'sistemul OKRs\':propuneri/9-okr pe care mai mulţi dintre noi l-am văzut şi l-am folosit la Google în internship-uri.\r\n\r\nDespre OKRs citiţi mai multe în \'pagina dedicată\':propuneri/9-okr. Pe scurt însă, OKR-urile (Objectives and Key Results) sunt o serie de obiective şi rezultate cheie măsurabile pe care ni le stabilim trimestrial. Fiecare obiectiv are un responsabil, iar la sfârşitul trimestrului tragem linie şi facem bilanţul: care dintre obiectivele propuse am reuşit să le îndeplinim?\r\n\r\nCa să probăm ideea ne-am asumat în octombrie 2008 \'o serie de obiective\':okr/20084 şi am început să lucrăm la ele. Timpul a zburat repede, iar la sfârşitul trimestrului am constatat că doar jumătate din ce ne-am propus am şi realizat. Oops! Dacă sună dezamăgitor, să ştiţi că nu e. În realitate am fost optimişti şi ne-am asumat obiective prea ambiţioase pentru o perioadă de timp atât de scurtă. Pe principiul „experientia docet” o să avem grijă de data asta să obţinem o notă mai mare. :)\r\n\r\nIată \'obiectivele infoarena pe anul *2009, trimestrul I*\':okr/20091, trimestru din care a mai rămas o lună şi câteva zile. Deşi OKR-urile sunt redactate foarte succint, am să încerc totuşi să le fac un rezumat pe blog şi să adaug pe alocuri câteva detalii interesante.\r\n\r\np=. ~ ~ ~\r\n\r\nSunt ~800 de probleme în arhivă, adică suficient de multe. Din păcate însă, sunt puse la grămadă fără nici un indiciu despre dificultate sau despre tipul soluţiei căutate. Ca utilizator începător este greu să găseşti probleme pe care să le poţi rezolva. Trimestrul acesta dezvoltăm un sistem de tagging pe care îl vom folosi ulterior să clasificăm problemele din arhivă. În paralel căutăm şi o metodă bună de ordonare a problemelor în funcţie de dificultatea lor.\r\n\r\nArhiva educaţională, un proiect foarte îndrăgit de noi şi care împlineşte zilele acestea un an de existenţă, continuă să crească rapid, însă cu ceva mai multă atenţie la calitate.\r\n\r\nLegat de concursuri, trimestrul acesta lucrăm la o nouă facilitate majoră a site-ului infoarena: \'concursuri virtuale\':propuneri/10-virtual-contest, adică o facilitate prin care utilizatorii infoarena îşi pot organiza singuri concursuri folosind problemele din arhivă. Tare, nu!? Tot trimestrul acesta organizăm runda finală a \'Algoritmiadei\':algoritmiada-2009, singurul concurs on-site organizat de infoarena. (În premieră pentru infoarena, Algoritmiada are şi o grupă de studenţi!)\r\n\r\n\'Secţiunea articole\':articole a primit „multă dragoste” în ultimul an şi a crescut enorm faţă de 2007. Planul pe acest trimestru? Se lucrează în continuare, adică mult şi foarte bine. :)\r\n\r\n„hacker-ii infoarena”, cei care dezvoltă software-ul pentru site şi evaluator, trebuie să implementeze două mari facilităţi: \'concursuri virtuale\':propuneri/10-virtual-contest şi tagging la probleme. În paralel lucrăm şi la infrastructură, mai exact la ajustarea timpilor de execuţie pentru momentul când vom muta evaluatorul pe un calculator mai puternic şi un sistem automat şi distribuit de backup.\r\n\r\nPentru a îndeplini obiectivele de development vom organiza cel puţin \'un coding camp\':planificare/camp-2.2.1, adică un week-end întreg în care ne întâlnim toţi într-un loc să „codăm”. Apropos de coding camp, hai şi tu! E o ocazie perfectă să înveţi programare web, Linux şi „best practices” pe care le vei întâlni mai târziu la cele mai bune companii de software.\r\n\r\nUn alt proiect important la care lucrăm este \'community ladder\':propuneri/7-community-ladder, un sistem prin care „oferim credit, responsabilitate şi autoritate persoanelor ce se implică in dezvoltarea proiectului şi a comunităţii infoarena”. Nu ne-am propus să îl şi implementăm în acest trimestru, însă vom dezbate conceptul şi vom face un plan pentru trimestrul următor.\r\n\r\nVom mai dezvolta şi un modul de statici în timp real despre comunitatea infoarena: câţi utilizatori / contribuitori activi sunt pe infoarena, câţi activează pe forum, câţi participă la concursuri, editează pagini wiki, trimit soluţii la probleme din arhivă, etc. Toate aceste statistici ne vor ajuta să măsurăm impactul schimbărilor pe care le vom face în trimestrele următoare.\r\n\r\nO altă problemă de care ne ocupăm, chiar una spinoasă, este strângerea fondurilor pentru \'Asociaţia infoarena\':asociatia-infoarena. Principala cheltuială a noastră o reprezintă organizarea anuală a finalei \'Algoritmiada\':algoritmiada-2009, eveniment la care sunt invitate 60 de persoane pentru care asigurăm cazare, masă şi premii. Alte cheltuieli ţin de organizarea de \'coding-camp-uri\':planificare/camp-2.2.1 şi a \'şedinţelor\':planificare.\r\n\r\nVom insista mai mult pe \'direcţionările de 2%\':doi-la-suta din impozitul pe venit datorat la stat deoarece \'au funcţionat bine anul trecut\':blog/doi-la-suta-2008-raport şi vom experimenta cu donaţii PayPal. Marea majoritate a fondurilor infoarena vin însă din sponsorizări acordate de către companii private. Trimestrul acesta căutăm sponsori pentru \'finala Algoritmiada\':algoritmiada-2009 şi probabil vom întâmpina dificultăţi mai mari decât în anii trecuţi din cauza contextului economic.\r\n\r\np=. ~ ~ ~\r\n\r\nCam aşa aş rezuma eu obiectivele acestui trimestru. Citiţi \'OKR-urile\':okr/20091 pentru alte detalii şi nu vă lăsaţi induşi în eroare că sunt menţionate în ele doar câteva persoane - aceia sunt doar „responsabilii”. Pentru obiectivele infoarena lucrează o \'echipă formidabilă\':echipa-infoarena alături de câteva zeci de voluntari din comunitatea infoarena.\r\n\r\nTu ce părere ai despre obiectivele infoarena pe acest trimestru? Crezi că sunt prea modeste, crezi că sunt prea ambiţioase? Ai o idee bună pe care ar trebui să o punem în practică? Vrem să o auzim! Cea mai bună idee va fi premiată cu un tricou infoarena! ;)\r\n',13,'protected',3710,NULL),('schimbare-borland/ghid','Scurt ghid pentru folosirea MinGW Developer Studio','2008-11-10 16:02:04','2009-08-23 15:25:01','h1. Scurt ghid pentru folosirea MinGW Developer Studio\r\n\r\n==include(page=\"template/schimbare-borland\")==\r\n\r\n==include(page=\"schimbare-borland/ghid/menu\")==\r\n\r\nMinGW Developer Studio este un mediu de dezvoltare integrat (Integrated Development Environment, pe scurt IDE) pentru C/C++. Mediul este unul light-weight folosind resurse putine si oferind posibilatea dezvoltarii programelor in mod stabil.\r\n\r\nDesi proiectul a fost abandonat de cativa ani el este intr-o forma stabila si suporta schimbarea compilatorului MinGW (care este in dezvoltare activa) avand astfel posibilitatea mentinerii unui pachet modern, in pas cu standardele C/C++. In plus, compilatorul si debuggerul MinGW (vezi detalii in urmatoarea sectiune) pot fi folosite independent de MinGW Developer Studio impreuna cu un alt editor la alegere.\r\n\r\nh2. Despre MinGW\r\n\r\nMinGW (Minimalist Gnu for Windows) este o colectia gratuita de librarii imbogatind GNU Compliler Collection cu fisiere si librarii specifice Windows. Scopul proiectului initial a fost integrarea facilitatilor oferite de Windows32 in compilatorul gcc si binutils (inclusiv debugger-ul gdb) si portarea acestora pe Windows. Mare parte din codul MinGW este distribuit sub licenta GPL, insa nu in intregime, detalii gasiti \'aici\':http://www.mingw.org/license.\r\n\r\nh2. Diferente intre compilatoarele BorlandC 3.1 si MinGW 3.3.1\r\n\r\n* Compilatorul MinGW cere in cazul executiei corecte a programului codul 0. Asadar nu se accepta ca **main()** sa fie declarat **void**, este obligatoriu ca sa fie declarat ca **int**. De exemplu:\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n\r\nusing namespace std;\r\n\r\nint main(void) {\r\n    cout << \"acest program compileaza\";\r\n    return 0;\r\n}\r\n==\r\n\r\n* Tipul de date **int** este reprezentat pe 4 bytes, asadar **int** ia valori intre -2147483647 si 2147483647. In BorlandC tipul de date **int** ocupa 2 bytes.\r\n* Exista tipul de date **long long** care este reprezentat pe 8 bytes care ia valori intre -2^62^+1 pana la 2^62^-1. In BorlandC acest tip de date nu exista. Pentru a citi/afisa numere pe 64 de biti cu libraria <stdio.h> se foloseste specificatorul de format non-standard \"%I64d\". Cateva detalii \'aici\':http://ascending.wordpress.com/2008/04/22/long-long-on-windows-dev-c-mingw/.\r\n* Pointerii ocupa 4 bytes, astfel incat memoria totala disponibila este de 4 GB, care in anul 2008 inseamna oricat, trebuie totusi sa aveti grija la dimensiunea stivei sistem (aceasta insa poate fi marita usor). In BorlandC pointerii ocupa 2 bytes si memoria disponibila este de 64 KB, folosindu-se modificatorii huge sau far pointeri aveau 4 bytes dar totusi memoria disponibila era limitata la 640 KB.\r\n* MinGW ofera suport pentru \'Standard Template Library\':http://www.sgi.com/tech/stl/. Dintre structurile implementate fac parte vectorii, cozile, stivele, arborii echlibrati, cozile de prioritate, etc; iar dintre algoritmii implementati sunt sortarea, cautarea binara, generarea permutarilor, etc.\r\n',3689,'public',NULL,NULL),('sica','sica','2009-02-24 16:59:40','2009-02-24 16:59:40','in umbra marelui urs',2092,'public',NULL,NULL),('articole/template-structuri-de-date','articole/template-structuri-de-date','2008-12-13 14:24:20','2009-03-29 20:42:07','* \'Deque şi aplicaţii\':deque-si-aplicatii\r\n* \'Tabele hash - prezentare detaliata\':tabele-hash-prezentare-detaliata\r\n* !>articole/template-structuri-de-date?quad-tree.jpg! \'Heap-uri\':heapuri\r\n* \'Treapuri\':treapuri\r\n* \'Cautari ortogonale\':cautari-ortogonale\r\n* \'Siruri de sufixe\':siruri-de-sufixe\r\n*{display: %display%} \'Suffix array in timp liniar\':suffix-array-liniar\r\n*{display: %display%} \'Arbori de intervale si aplicatii in geometrie\':arbori-de-intervale\r\n*{display: %display%} \'Skiplists\':skiplists\r\n*{display: %display%} \'Tabele hash\':tabele-hash-scurta-prezentare',2044,'protected',NULL,NULL),('tabele-hash-prezentare-detaliata','Tabele hash - prezentare detaliata','2008-01-30 15:12:38','2009-02-27 00:12:20','h1. Tabele hash - prezentare detaliata\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"Cyber\") ==\r\n\r\n(Categoria _Structuri de date_, Autor _Catalin Francu_, Preluat din cartea _\"Psihologia concursurilor de informatica\"_)\r\n\r\n(toc){width: 20em}*{text-align:center;} *Continut*\r\n* \'Necesitatea tabelelor hash\':tabele-hash-prezentare-detaliata#necesitate\r\n* \'Descrierea structurii de date\':tabele-hash-prezentare-detaliata#descriere\r\n* \'Metoda impartirii cu rest\':tabele-hash-prezentare-detaliata#metoda-impartirii-cu-rest\r\n* \'Metoda inmultirii\':tabele-hash-prezentare-detaliata#metoda-inmultirii\r\n* \'Probleme propuse\':tabele-hash-prezentare-detaliata#probleme-propuse\r\n\r\nh2(#necesitate). Necesitatea tabelelor hash\r\n\r\nIn multe aplicatii lucram cu structuri mari de date in care avem nevoie sa facem cautari, inserari, modificari si stergeri. Aceste structuri pot fi vectori, matrice, liste etc. In cazurile mai fericite ale vectorilor, acestia pot fi sortati, caz in care localizarea unui element se face prin metoda injumatatirii intervalului, adica in timp logaritmic. Chiar daca nu avem voie sa sortam vectorul, tot se pot face anumite optimizari care reduc foarte mult timpul de cautare. De exemplu, probabil ca multi dintre cititori au idee despre ce inseamna indexarea unei baze de date. Daca avem o baza de date cu patru elemente de tip string, si anume\r\n\r\n$B = (\"bac\", \"zugrav\", \"abac\", \"zarva\")$\r\n\r\nputem construi un vector $Ind$ care sa ne indice ordinea in care s-ar cuveni sa fie asezate cuvintele in vectorul sortat. Ordinea alfabetica (din cartea de telefon) a cuvintelor este: \"abac\", \"bac\", \"zarva\", \"zugrav\", deci vectorul $Ind$ este:\r\n\r\n$Ind = (3, 1, 4, 2)$\r\n\r\nsemnificand ca primul cuvant din vectorul sortat ar trebui sa fie al treilea din vectorul $B$, respectiv \"abac\", si asa mai departe. In felul acesta am obtinut un vector sortat, care presupune o indirectare a elementelor. Vectorul sortat este\r\n\r\n$B\' = (B(Ind(1)), B(Ind(2)), B(Ind(3)), B(Ind(4))$.\r\n\r\nAceasta operatie se numeste indexare. Ce-i drept, constructia vectorului $Ind$ nu se poate face intr-un timp mai bun decat $O(N log N)$, dar dupa ce acest lucru se face (o singura data, la inceputul programului), cautarile se pot face foarte repede. Daca pe parcurs se fac adaugari sau stergeri de elemente in/din baza de date, se va pierde catva timp pentru mentinerea indexului, dar in practica timpul acesta este mult mai mic decat timpul care s-ar pierde cu cautarea unor elemente in cazul in care vectorul ar fi neindexat. Nu vom intra in detalii despre indexare, deoarece nu acesta este obiectul articolului de fata.\r\n\r\nIn unele situatii nu se poate face nici indexarea structurii de date. Sa consideram cazul unui program care joaca sah. Numarul de pozitii posibile ale pieselor pe tabla de sah este mult prea mare. Nu poate fi vorba nici macar de retinerea tuturor, cu atat mai putin de indexarea lor. In esenta, modul de functionare al acestui program se reduce la o rutina care primeste o pozitie pe tabla si o variabila care indica daca la mutare este albul sau negrul, rutina intorcand cea mai buna mutare care se poate efectua din acea pozitie. Majoritatea programelor de sah incep sa expandeze respectiva pozitie, examinand tot felul de variante ce pot decurge din ea si alegand-o pe cea mai promitatoare, asa cum fac si jucatorii umani. Pozitiile analizate, fiind mult mai putine decat cele posibile, sunt stocate in memorie sub forma unei liste.\r\n\r\nSa ne inchipuim acum urmatoarea situatie. Este posibil ca, prin expandarea unei configuratii initiale a tablei sa se ajunga la aceeasi configuratie finala pe doua cai diferite. Spre exemplu, daca albul muta intai calul la _f3_, apoi nebunul la _c4_, pozitia rezultata va fi aceeasi ca si cand s-ar fi mutat intai nebunul si apoi calul (considerand bineinteles ca negrul da in ambele situatii aceeasi replica). Daca configuratia finala a fost deja analizata pentru prima varianta, este inutil sa o mai analizam si pentru cea de-a doua, pentru ca rezultatul (concluzia la care se va ajunge) va fi exact acelasi. Dar cum isi poate da programul seama daca pozitia pe care are de gand s-o analizeze a fost analizata deja sau nu?\r\n\r\nCea mai simpla metoda este o scanare a listei de configuratii examinate din memorie. Daca in aceasta lista se afla pozitia curenta de analizat, inseamna ca ea a fost deja analizata si vom renunta la ea. Daca nu, o vom analiza acum. Ideea in mare a algoritmului este:\r\n\r\n== code(c) |\r\nfunctia Analizeaza(Pozitie P)\r\n    cauta P in lista de pozitii deja analizate\r\n    daca P nu exista in lista\r\n        expandeaza P si afla cea mai buna mutare M\r\n        adauga P la lista de pozitii analizate\r\n        intoarce M\r\n    altfel\r\n        intoarce valoarea M atasata pozitiei P gasite in lista\r\nsfarsit\r\n==\r\n\r\nNu vom insista asupra a cum se expandeaza o pozitie si cum se calculeaza efectiv cea mai buna mutare. Noi ne vom interesa de un singur aspect, si anume cautarea unei pozitii in lista. Tehnica cea mai \"naturala\" este o parcurgere a listei de la cap la coada, comparand pe rand pozitia cautata cu fiecare pozitie din lista. Daca lista are memorate $N$ pozitii, atunci in cazul unei cautari cu succes (pozitia este gasita), numarul mediu de comparatii facute este $N/2$, iar numarul cel mai defavorabil ajunge pana la $N$. In cazul unei cautari fara succes (pozitia nu exista in lista), numarul de comparatii este intotdeauna $N$. De altfel, cazul cautarii fara succes este mult mai frecvent pentru problema jocului de sah, unde numarul de pozitii posibile creste exponential cu numarul de mutari. Acelasi numar de comparatii il presupune si stergerea unei pozitii din lista (care presupune intai gasirea ei) si adaugarea (care presupune ca pozitia de adaugat sa nu existe deja in lista).\r\n\r\nPentru imbunatatirea practica a acestui timp sunt folosite _tabelele de dispersie_ sau _tabelele hash_ (engl. _hash_ = a toca, tocatura). Mentionam de la bun inceput ca tabelele hash nu au nicio utilitate din punct de vedere teoretic. Daca suntem rau intentionati, este posibil sa gasim exemple pentru care cautarea intr-o tabela hash sa dureze la fel de mult ca intr-o lista simplu inlantuita, respectiv $O(N)$. Dar in practica timpul cautarii si al adaugarii de elemente intr-o tabela hash coboara uneori pana la $O(1)$, iar in medie scade foarte mult (de mii de ori).\r\n\r\nh2(#descriere). Descrierea structurii de date\r\n\r\nIata despre ce este vorba. Sa presupunem pentru inceput ca in loc de pozitii pe tabla de sah, lista noastra memoreaza numere intre 0 si 999. In acest caz, tabela hash ar fi un simplu vector $H$ cu $1000$ de elemente booleene. Initial, toate elementele lui $H$ au valoarea $False$ (sau $0$). Daca numarul $473$ a fost gasit in lista, nu avem decat sa setam valoarea lui $H(473)$ la $True$ (sau $1$). La o noua aparitie a lui $473$ in lista, vom examina elementul $H(473)$ si, deoarece el este $True$, inseamna ca acest numar a mai fost gasit. Daca dorim stergerea unui element din hash, vom reseta pozitia corespunzatoare din $H$. Practic, avem de-a face cu un exemplu rudimentar de ceea ce se cheama functie de dispersie, adica $h(x) = x$. O proprietate foarte importanta a acestei functii este injectivitatea; este imposibil ca la doua numere distincte sa corespunda aceeasi intrare in tabela. Sa incercam o reprezentare grafica a metodei:\r\n\r\np=. !tabele-hash-prezentare-detaliata?hash1.jpg!\r\n\r\nIata primul set de functii de gestionare a unui hash.\r\n\r\n== code(c) |\r\nconst int M = 1000;\r\ntypedef int DataType;\r\ntypedef DataType Hash[M];\r\nHash H;\r\n\r\nvoid InitHash1(Hash H) {\r\n    for (int i = 0; i < M; H[i++] = 0);\r\n}\r\n\r\ninline int h(DataType K) {\r\n    return K;\r\n}\r\n\r\nint Search1(Hash H, DataType K) {\r\n    // Intoarce -1 daca elementul nu exista in hash\r\n    // sau indicele in hash daca el exista\r\n    return H[h(K)] ? h(K) : -1;\r\n}\r\n\r\nvoid Add1(Hash H, DataType K) {\r\n    H[h(K)] = 1;\r\n}\r\n\r\nvoid Delete1(Hash H, DataType K) {\r\n    H[h(K)] = 0;\r\n}\r\n==\r\n\r\nPrin \"numar de intrari\" in tabela se intelege numarul de elemente ale vectorului $H$; in general, orice tabela hash este un vector. Pentru ca functiile sa fie cat mai generale, am dat tipului de date _int_ un nou nume _DataType_. In principiu, tabelele hash se aplica oricarui tip de date. In realitate, fenomenul este tocmai cel invers: orice tip de date trebuie \"convertit\" printr-o metoda sau alta la tipul de date _int_, iar functia de dispersie primeste ca parametru un intreg. Functiile hash prezentate in viitor nu vor mai lucra decat cu variabile de tip intreg. Vom vorbi mai tarziu despre cum se poate face conversia. Acum sa generalizam exemplul de mai sus.\r\n\r\nIntr-adevar, cazul anterior este mult prea simplu. Sa ne inchipuim de pilda ca in loc de numere mai mici ca $1.000$, avem numere de pana la $2.000.000.000$. In aceasta situatie posibilitatea de a reprezenta tabela ca un vector caracteristic iese din discutie. Numarul de intrari in tabela este de ordinul miilor, cel mult al zecilor de mii, deci cu mult mai mic decat numarul total de chei (numere) posibile. Ce avem de facut? Am putea incerca sa adaugam un numar $K$ intr-o tabela cu $M$ intrari (numerotate de la 0 la $M-1$) pe pozitia $K mod M$, adica $h(K) = K mod M$. Care va fi insa rezultatul? Functia $h$ isi va pierde proprietatea de injectivitate, deoarece mai multor chei le poate corespunde aceeasi intrare in tabela, cum ar fi cazul numerelor $1.234$ si $2.001.234$, ambele dand acelasi rest la impartirea prin $M = 1.000$. Nu putem avea insa speranta de a gasi o functie injectiva, pentru ca atunci numarul de intrari in tabela ar trebui sa fie cel putin egal cu numarul de chei distincte. Vrand-nevrand, trebuie sa rezolvam coliziunile (sau conflictele) care apar, adica situatiile cand mai multe chei distincte sunt repartizate la aceeasi intrare.\r\n\r\nVom reveni ulterior la oportunitatea alegerii functiei modul si a numarului de $1.000$ de intrari in tabela. Deocamdata vom folosi aceste date pentru a explica modul de functionare a tabelei hash pentru functii neinjective. Sa presupunem ca avem doua chei $K1$ si $K2$ care sunt repartizate de functia $h$ la aceeasi intrare $X$, adica $h(K1) = h(K2) = X$. Solutia cea mai comoda este ca $H(X)$ sa nu mai fie un numar, ci o lista liniara simplu inlantuita care sa contina toate cheile gasite pana acum si repartizate la aceeasi intrare $X$. Prin urmare vectorul $H$ va fi un vector de liste:\r\n\r\np=. !tabele-hash-prezentare-detaliata?hash2.jpg!\r\n\r\nSa analizam acum complexitatea noilor functii de cautare, adaugare si stergere. Cautarea nu se va mai face in toata lista, ci numai in lista corespunzatoare din $H$. Altfel spus, o cheie $K$ se va cauta numai in lista $H(h(K))$, deoarece daca cheia $K$ a mai aparut, ea a fost in mod sigur repartizata la intrarea $H(h(K))$. De aceea, cautarea poate ajunge, in cazul cel mai defavorabil cand toate cheile din lista se repartizeaza la aceeasi intrare in hash, la o complexitate $O(N)$. Daca reusim insa sa gasim o functie care sa distribuie cheile cat mai aleator, timpul de intrare se va reduce de $M$ ori. Avantajele sunt indiscutabile pentru $M = 10.000$ de exemplu.\r\n\r\nIntrucat operatiile cu liste liniare sunt in general cunoscute, nu vom insista asupra lor. Prezentam aici numai adaugarea si cautarea, lasandu-va ca tema scrierea functiei de stergere din tabela.\r\n\r\n== code(c) |\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n\r\nconst int M = 1000;\r\ntypedef struct List_ {\r\n    long P;\r\n    struct List_ *Next;\r\n} List;\r\ntypedef List* Hash[M];\r\nHash H;\r\n\r\nvoid InitHash2(Hash H){\r\n    for (int i = 0; i < M; H[i++] = NULL);\r\n}\r\n\r\nint h2(int K) {\r\n    return K % M;\r\n}\r\n\r\nint Search2(Hash H, int K) {\r\n    // Intoarce 0 daca elementul nu exista in hash\r\n    // sau 1 daca el exista\r\n    List *L;\r\n    for (L = H[h2(K)]; L && (L->P != K); L = L->Next);\r\n    return L != NULL;\r\n}\r\n\r\nvoid Add2(Hash H, int K) {\r\n    List *L = (List *) malloc(sizeof(List));\r\n    L->P = K;\r\n    L->Next = H[h2(K)];\r\n    H[h2(K)] = L;\r\n}\r\n==\r\n\r\nAm spus ca functiile de dispersie sunt concepute sa lucreze numai pe date de tip intreg; celelalte tipuri de date trebuie convertite in prealabil la tipuri de date intregi. Iata cateva exemple:\r\n\r\n* Variabilele de tip string pot fi transformate in numere in baza $256$ prin inlocuirea fiecarui caracter cu codul sau _ASCII_. De exemplu, sirul \"abac\" poate fi privit ca un numar de 4 cifre in baza $256$, si anume numarul $(97 98 97 99)$. Conversia lui in baza $10$ se face astfel:\r\n\r\n$X = ((97 * 256 + 98) * 256 + 97) * 256 + 99 = 1.633.837.411$\r\n\r\nPentru stringuri mai lungi, rezulta numere mai mari. Uneori, ele nici nu mai pot fi reprezentate cu tipurile de date ordinare. Totusi, acest dezavantaj nu este suparator, deoarece majoritatea functiilor de dispersie presupun o impartire cu rest, care, indiferent de marimea numarului de la intrare, produce un numar controlabil.\r\n\r\n* Variabilele de tip data se pot converti la intreg prin formula:\r\n\r\n$X = A * 366 + L * 31 + Z$\r\n\r\nunde $A$, $L$ si $Z$ sunt respectiv anul, luna si ziua datei considerate. De fapt, aceasta functie aproximeaza numarul de zile scurse de la inceputul secolului I. Ea nu are pretentii de exactitate (ca dovada, toti anii sunt considerati a fi bisecti si toate lunile a avea 31 de zile), deoarece s-ar consuma timp inutil cu calcule mai sofisticate, fara ca dispersia insasi sa fie imbunatatita cu ceva. Conditia care trebuie neaparat respectata este ca functia de conversie data <tex> \\leftrightarrow </tex> intreg sa fie injectiva, adica sa nu se intample ca la doua date $D1$ si $D2$ sa li se ataseze acelasi intreg $X$; daca acest lucru se intampla, pot aparea erori la cautarea in tabela (de exemplu, se poate raporta gasirea datei $D1$ cand de fapt a fost gasita data $D2$). Pentru a respecta injectivitatea, s-au considerat coeficientii $366$ si $31$ in loc de $365$ si $30$. Daca numarul de zile scurse de la 1 ianuarie anul 1 d.H. ar fi fost calculat cu exactitate, functia de conversie ar fi fost si surjectiva, dar, dupa cum am mai spus, acest fapt nu prezinta interes.\r\n\r\n* Analog, variabilele de tip ora se pot converti la intreg cu formula:\r\n\r\n$X = (H * 60 + M) * 60 + S$\r\n\r\nunde $H$, $M$ si $S$ sunt respectiv ora, minutul si secunda considerate, sau cu formula\r\n\r\n$X = ((H * 60 + M) * 60 + S) * 100$\r\n\r\ndaca se tine cont si de sutimile de secunda. De data aceasta, functia este surjectiva (oricarui numar intreg din intervalul $0 - 8.639.999$ ii corespunde in mod unic o ora).\r\n\r\n* In majoritatea cazurilor, datele sunt structuri care contin numere si stringuri. O buna metoda de conversie consta in alipirea tuturor acestor date si in convertirea la baza $256$. Caracterele se convertesc prin simpla inlocuire cu codul _ASCII_ corespunzator, iar numerele prin convertirea in baza $2$ si taierea in \"bucati\" de cate opt biti. Rezulta numere cu multe cifre (prea multe chiar si pentru tipul $long long$), care sunt supuse unei operatii de impartire cu rest. Functia de conversie trebuie sa fie injectiva. De exemplu, in cazul tablei de sah despre care am amintit mai inainte, ea poate fi transformata intr-un vector cu $64$ de cifre in baza $16$, cifra $0$ semnificand un patrat gol, cifrele $1-6$ semnificand piesele albe (pion, cal, nebun, turn, regina, rege), iar cifrele $7-12$ semnificand piesele negre. Prin trecerea acestui vector in baza $256$, rezulta un numar cu $32$ de cifre. La acesta se mai pot adauga alte cifre, respectiv partea la mutare ($0$ pentru alb, $1$ pentru negru), posibilitatea de a efectua rocada mica/mare de catre alb/negru, numarul de mutari scurse de la inceputul partidei si asa mai departe.\r\n\r\nVom termina prin a prezenta doua functii de dispersie foarte des folosite.\r\n\r\nh2(#metoda-impartirii-cu-rest). Metoda impartirii cu rest\r\n\r\nDespre aceasta metoda am mai vorbit. Functia hash este: $h(x) = x mod M$ unde $M$ este numarul de intrari in tabela. Problema care se pune este sa-l alegem pe $M$ cat mai bine, astfel incat numarul de coliziuni pentru oricare din intrari sa fie cat mai mic. De asemenea, trebuie ca $M$ sa fie cat mai mare, pentru ca media numarului de chei repartizate la aceeasi intrare sa fie cat mai mica. Totusi, experienta arata ca nu orice valoare a lui $M$ este buna.\r\n\r\nDe exemplu, la prima vedere s-ar putea spune ca o buna valoare pentru $M$ este o putere a lui $2$, cum ar fi $1024$, pentru ca operatia de impartire cu rest se poate face foarte usor in aceasta situatie. Totusi, functia $h(x) = x mod 1024$ are un mare defect: ea nu tine cont decat de ultimii $10$ biti ai numarului $x$. Daca datele de intrare sunt numere in mare majoritate pare, ele vor fi repartizate in aceeasi proportie la intrarile cu numar de ordine par, pentru ca functia $h$ pastreaza paritatea. Din aceleasi motive, alegerea unei valori ca $1000$ sau $2000$ nu este prea inspirata, deoarece tine cont numai de ultimele $3-4$ cifre ale reprezentarii zecimale. Multe valori pot da acelasi rest la impartirea prin $1000$. De exemplu, daca datele de intrare sunt anii de nastere ai unor persoane dintr-o agenda telefonica, iar functia $h(x) = x mod 1000$, atunci majoritatea cheilor se vor ingramadi (termenul este sugestiv) intre intrarile $920$ si $990$, restul ramanand nefolosite.\r\n\r\nPractic, trebuie ca $M$ sa nu fie un numar rotund in nicio baza aritmetica, sau cel putin nu in bazele $2$ si $10$. O buna alegere pentru $M$ sunt numerele prime care sa nu fie apropiate de nicio putere a lui $2$. De exemplu, in locul unei tabele cu $M = 10.000$ de intrari, care s-ar comporta dezastruos, putem folosi una cu $9973$ de intrari. Chiar si aceasta alegere poate fi imbunatatita; intre puterile lui 2 vecine, respectiv $8192$ si $16384$, se poate alege un numar prim din zona $11.000 - 12.000$. Risipa de memorie de circa $1.000 - 2.000$ de intrari in tabela va fi pe deplin compensata de imbunatatirea cautarii.\r\n\r\nh2(#metoda-inmultirii). Metoda inmultirii\r\n\r\nPentru aceasta metoda functia hash este $h(x) = [M * {x*A}]$. Aici $A$ este un numar pozitiv subunitar, $0 < A < 1$, iar prin ${x*A}$ se intelege partea fractionara a lui $x*A$, adica $x*A - [x*A]$. De exemplu, daca alegem $M = 1234$ si $A = 0.3$, iar $x = 1997$, atunci avem $h(x) = [1234 * {599.1}] = [1234 * 0.1] = 123$. Se observa ca functia $h$ produce numere intre $0$ si $M-1$. Intr-adevar $0 &le; {x*A} < 1$ <tex>\\Rightarrow</tex> $0 &le; M * {x*A} < M$.\r\n\r\nIn acest caz, valoarea lui $M$ nu mai are o mare importanta. O putem deci alege cat de mare ne convine, eventual o putere a lui $2$. In practica, s-a observat ca dispersia este mai buna pentru unele valori ale lui $A$ si mai proasta pentru altele. Donald Knuth propune valoarea <tex> A = \\frac{\\sqrt{5}-1}{2} \\approx 0.618034 </tex>.\r\n\r\nCa o ultima precizare necesara la acest articol, mentionam ca functia de cautare e bine sa nu intoarca pur si simplu $0$ sau $1$, dupa cum cheia cautata a mai aparut sau nu inainte intre datele de intrare. E recomandabil ca functia sa intoarca un pointer la zona de memorie in care se afla prima aparitie a cheii cautate. Vom da acum un exemplu in care aceasta valoare returnata este utila. Daca, in cazul prezentat mai sus al unui program de sah, se ajunge la o anumita pozitie $P$ dupa ce albul a pierdut dreptul de a face rocada, aceasta pozitie va fi retinuta in hash. Retinerea nu se va face nicidecum efectiv (toata tabla), pentru ca s-ar ocupa foarte multa memorie. Se va memora in loc numai un pointer la pozitia respectiva din lista de pozitii analizate. Pe langa economia de memorie in cazul cheilor de mari dimensiuni, mai exista si alt avantaj. Sa ne inchipuim ca, analizand in continuare tabla, programul va ajunge la aceeasi pozitie $P$, dar in care albul are inca dreptul de a face rocada. E limpede ca aceasta varianta este mai promitatoare decat precedenta, deoarece albul are o libertate mai mare de miscare. Se impune deci fie stergerea vechii pozitii $P$ din lista si adaugarea noii pozitii, fie modificarea celei vechi prin setarea unei variabile suplimentare care indica dreptul albului de a face rocada. Aceasta modificare este usor de facut, intrucat cautarea in hash va returna chiar un pointer la pozitia care trebuie modificata. Bineinteles, in cazul in care pozitia cautata nu se afla in hash, functia de cautare trebuie sa intoarca $NULL$.\r\n\r\nIn incheiere, prezentam un exemplu de functie de dispersie pentru cazul tablei de sah.\r\n\r\n== code(c) |\r\nconst int M = 9973;  // Numarul de \"intrari\".\r\ntypedef struct {\r\n    // Tabla de joc, cu 0 <= T[i][j] <= 12.\r\n    char b_T[8][8];\r\n\r\n    // Ultimii doi biti ai lui b_CastleW indica daca albul are dreptul de a\r\n    // efectua rocada mare, respectiv pe cea mica. Analog pentru b_CastleB.\r\n    char b_CastleW, b_CastleB;\r\n\r\n    // 0 sau 1, dupa cum la mutare este albul sau negrul.\r\n    char b_Side;\r\n\r\n\r\n    // 0..8, indicand coloana (0..7) pe care partea la mutare poate efectua o\r\n    // captura \"en passant\". 8 indica ca nu exista aceasta posibilitate.\r\n    char b_EP;\r\n\r\n    // Numarul de mutari efectuate.\r\n    int b_NMoves;\r\n} Board;\r\nBoard B;\r\n\r\nint h3(Board *B) {\r\n    int i, j;\r\n\r\n    // Valoarea initiala a lui S este un numar pe 17 biti care\r\n    // inglobeaza toate variabilele suplimentare pe langa T.\r\n    // S se va lua apoi modulo M.\r\n    long S = (B->b_NMoves           // 8 biti\r\n            +(B->b_CastleW << 8)    // 2 biti\r\n            +(B->b_CastleB << 10)   // 2 biti\r\n            +(B->b_Side << 12)      // 1 bit\r\n            +(B->b_EP << 13)) % M;  // 4 biti\r\n\r\n    for (i = 0; i <= 7; i++)\r\n        for (j = 0; j <= 7; j++) {\r\n            S = (16 * S + B->b_T[i][j]) % M;\r\n        }\r\n\r\n    return S;\r\n}\r\n==\r\n\r\nh2(#probleme-propuse). Probleme propuse\r\n\r\nIata si o scurta lista de probleme ce se rezolva eficient folosind tabelele hash:\r\n\r\n* \'SGU 174 - Walls\':http://acm.sgu.ru/problem.php?contest=0&problem=174\r\n* \'UVA 10748 - Knights Roaming\':http://icpcres.ecs.baylor.edu/onlinejudge/external/107/10748.html\r\n* \"UVA 10815 - Andy\'s First Dictionary\":http://icpcres.ecs.baylor.edu/onlinejudge/external/108/10815.html\r\n* \'UVA 10887 - Concatenation of Languages\':http://icpcres.ecs.baylor.edu/onlinejudge/external/108/10887.html\r\n* \'UVA 704 - Colour Hash\':http://icpcres.ecs.baylor.edu/onlinejudge/external/7/704.html\r\n',2044,'public',3720,NULL),('concursuri-virtuale','Concursuri Virtuale','2009-02-28 16:19:24','2010-04-20 12:42:41','h1. Concursuri Virtuale\r\n\r\nAcum îţi *poţi organiza propriile concursuri* pe site-ul infoarena! Poţi alege câteva probleme din cele $1000$ prezente în arhivă şi să simulezi un concurs împreună cu alţi membrii ai comunităţii! \r\nTu îţi alegi ziua, ora şi durata fiecarui concurs. Participarea la un concurs nu este restricţionată, oricine îşi poate crea un concurs şi poate participa la cele deja existente. Mai jos găsiţi o listă cu toate concursurile organizate până acum de către utilizatorii infoarena.\r\n\r\nPentru \'mai multe detalii cu privire la crearea şi participarea\':documentatie/concursuri-virtuale la un concurs virtual citiţi \"aici\":documentatie/concursuri-virtuale.\r\n\r\n\r\n%{margin:auto; font-size: 1.25em; font-weight:bold; padding: 0.25em 0.5em; border: 1px double #999999; border-top-color: #CCCCCC; border-left-color: #CCCCCC; background: url(http://infoarena.ro/static/images/background_form_element.gif) repeat-x}\'Creează concurs nou\':admin/runda-noua%\r\n\r\n\r\n\r\n==RoundList(type=\"user-defined\" show_authors=\"true\")==\r\n',1490,'protected',NULL,NULL),('runda/runda_a_2-1','runda_a_2-1','2009-03-29 11:48:11','2009-03-29 11:48:11','h1. == roundparam(round_id=\"runda_a_2-1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"runda_a_2-1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"runda_a_2-1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"runda_a_2-1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/runda_a_2-1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"runda_a_2-1\" score=\"1\")==',6490,'round: runda_a_2-1',NULL,NULL),('planificare/camp-2.2.1','Coding Camp \"A New Day\"','2009-02-01 22:33:19','2009-11-09 10:37:11','h1. Coding Camp _\"A New Day\"_\r\n\r\nNe intalnim in weekend-ul *28 februarie-1 martie 2009*, in fiecare zi incepand cu *ora 10:00*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nScopul final al coding camp-ului este lansarea versiunii \'*infoarena 2.2.1*\':http://hackers.devnet.ro/milestone/2.2.1%20A%20New%20Day.\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu Linux (preferabil Ubuntu) instalat pe el\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri\r\n\r\nh2. Participanti\r\n\r\nSpecifica cand poti veni si cat poti sta.\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"alexthero\" type=\"tiny\")==: de acasa - tot weekend-ul\r\n* ==user(user=\"wickedman\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"stef2n\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"devilkind\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"silviug\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"prostu\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"victorsb\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"filipb\" type=\"tiny\")==: duminica\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"danielp\" type=\"tiny\")==: + ==user(user=\"astronomy\" type=\"tiny\")==: 1 zi, de acasa (duminica)\r\n\r\nh2. Agenda\r\n\r\nh3. Must have\r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n| Reorganizat sidebar si topnav | ==user(user=\"wickedman\" type=\"tiny\")==  | Nu s-a facut. |\r\n| Script de backup | ==user(user=\"wickedman\" type=\"tiny\")== | Partial. |\r\n| \'Virtual Contests\':propuneri/10-virtual-contest | ==user(user=\"domino\" type=\"tiny\")== ==user(user=\"bogdan2412\" type=\"tiny\")== | Complet. |\r\n| \'Pagina de submit desteapta\':http://hackers.devnet.ro/ticket/366 | ==user(user=\"bogdan2412\" type=\"tiny\")== | Complet. |\r\n| Optimizat pagina de clasament | 0 | Nu s-a facut. |\r\n| Script de recalculat timpii de evaluare | ==user(user=\"filipb\" type=\"tiny\")== | Nu s-a facut. |\r\n\r\nh3. Nice to have\r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n| Probleme interactive | ==user(user=\"silviug\" type=\"tiny\")== | Nu s-a facut. | \r\n| \'Scoruri detaliate\':http://hackers.devnet.ro/ticket/263 | ==user(user=\"devilkind\" type=\"tiny\")==  | La review. |\r\n| \'Pagina de changes mai detaliata\':http://hackers.devnet.ro/ticket/155 | ==user(user=\"prostu\" type=\"tiny\")== | Nu s-a facut. |\r\n| \'Permisiuni in pagina de changes\':http://hackers.devnet.ro/ticket/363 | ==user(user=\"prostu\" type=\"tiny\")== | Nu s-a facut. |\r\n| Tagging pentru probleme | 0 | Nu s-a facut. | \r\n| Community Dashboard | 0 | Nu s-a facut. |\r\n| \'Interfata de updatat rating-uri\':http://hackers.devnet.ro/ticket/239 | ==user(user=\"victorsb\" type=\"tiny\")== | La review. |\r\n| \'Feed-uri pe Feedburner\':http://hackers.devnet.ro/ticket/344 | ==user(user=\"domino\" type=\"tiny\")==  | Nu s-a facut. |\r\n\r\nh3. Others\r\n\r\n|_. Task|_. Cine lucreaza |_. Status |\r\n| \'Grafice rating\':http://hackers.devnet.ro/ticket/211 | ==user(user=\"stef2n\" type=\"tiny\")== | Complet. |\r\n| \'Optimizat diff-ul\':http://hackers.devnet.ro/ticket/360 | ==user(user=\"gcosmin\" type=\"tiny\")== | Complet. |\r\n| \'Script pentru topic-uri de pe forum la probleme\':http://hackers.devnet.ro/ticket/367 | ==user(user=\"alexthero\" type=\"tiny\")== | La review. |\r\n| \'Atasamente ca zip\':http://hackers.devnet.ro/ticket/306 | ==user(user=\"alexthero\" type=\"tiny\")== | Complet. |\r\n| \'Licenta CC\':http://hackers.devnet.ro/ticket/343 | 0 | Nu s-a facut. |\r\n| \'Run YSlow and improve performance\':http://hackers.devnet.ro/ticket/351 | 0 | Nu s-a facut. |\r\n| \'Sterge o revizie\':http://hackers.devnet.ro/ticket/132 | ==user(user=\"devilkind\" type=\"tiny\")==  | Complet. |\r\n| \'Paginator pentru comentarii\':http://hackers.devnet.ro/ticket/368 | ==user(user=\"coditza\" type=\"tiny\")==  | Complet. |\r\n| \'Sistem de monitorizare\':http://hackers.devnet.ro/ticket/179 | 0 | Nu s-a facut. |\r\n',1490,'public',NULL,NULL),('planificare/sedinta-20090216','Sedinta 2009-02-16','2009-02-09 14:25:39','2009-03-16 17:23:54','h1. Sedinta 2009-02-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Februarie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala -8- 22.)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")== (nu s-ar putea un pic mai devreme ca sa prindem si metroul la intoarcere?)\r\n* ==user(user=\"silviug\" type=\"tiny\")== (@Filip: cred că terminăm pe la 22:00, deci prinzi metrou)\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"danielp\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090126| ==user(user=\"silviug\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Concursul Centrelor de Excelenta/Concurs in engleza | ==user(user=\"filipb\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n|Rezoluţii pentru IAP-uri antice (1, 2, 8)| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh2. Detalii\r\n\r\n\r\nh3. Misc\r\n\r\n* OKRs Q12009\r\n\r\n* Community ladder\r\n\r\n* Ce se mai aude cu initiativa in care donam calculatoare utilizate?\r\n\r\n* Tutorial C/C++\r\n** E nevoie de un tutorial introductiv de C/C++ cu exemple de rezolvari din arhiva\r\n** Ideea Thero. Vrea sa-l faca chiar el. Si Paul vrea sa se implice. Later edit: Lui Paul ii ajunge Arhiva educationala deocamdata. :)\r\n** Va fi video!\r\n** Facem IAP?\r\n\r\n* Infoarena \"educational tool\"\r\n** Are rost sa ne propunem o infoarena utila si pentru elevul mediu de nationala?\r\n** Profesori pe care ii putem contacta sa le cerem parerea/sa se implice in infoarena.\r\n** Paul: \"Ar fi bine sa incercam sa convingem pe cati mai multi dintre profesori ca nu suntem interesati sa ii concuram, ci dimpotriva suntem dispusi sa ii ajutam in pregatirea elevilor lor mai buni.\" Cum facem asta?\r\n* Centrul de Excelenţă Bucureşti\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Reportat review la blog post %{color:red}(done)%\r\n* Vali face IAP si OKR despre ordonarea problemelor (vezi formula de la IMDB)\r\n* Wefgef ia mancare si bautura (limita 30 RON) %{color:red}(done; 14.3 lei)%\r\n* Wefgef numara cati nu sunt din Bucuresti la Algoritmiada %{color:red}(done; 19/42)%\r\n* Wefgef vorbeste in Tg. Mures cu Universitatea Sapientia %{color:red}(done)%\r\n* Wefgef face lista de cerinte (Algoritmiada) %{color:red}(done)%\r\n* Silviu face rost de contact in Brasov %{color:red}(done)%\r\n* Silviu vorbeste la Poli iara, cu Tapus\r\n* Mort face mail spam pentru sponsori (Silviu si Wef review) %{color:red}(done)%\r\n* Wefgef da drumul la pregatirea problemelor pentru runda finala & pagini %{color:red}(done)%\r\n* Mircea vorbeste cu Vali si Paul de Coding Camp %{color:red;}(done)%\r\n* Airinei trebuie sa confirme ca vine la Coding Camp %{color:red;}(done)%\r\n* Cristi se ocupa de locatie Coding Camp %{color:red;}(done)%\r\n* Mircea mai pune task-uri pe agenda de Coding Camp %{color:red}(done)%\r\n* Wefgef stabileste contact cu Florentina\r\n* Cristi reinoieste domeniul infoarena.org %{color:red}(done)%\r\n* infoarena in engleza e prioritar pentru urmatorul Coding Camp\r\n* Silviu vorbeste cu Tero despre .org   %{color:red;}done%: Thero e pe felie. Face IAP cat de curand ;) %{color:red} (A făcut IAP.)%\r\n* S-a respins IAP 1, 2, 3 si 8 este fara resurse\r\n* Silviu face la Coding Camp task-uri interactive %{color:red}(done)%\r\n* Wefgef scoate forum-ul de la OKR-uri %{color:red}(done)%\r\n* Silviu si Cristi concretizeaza IAP 7 (2 sedinte)\r\n* Urmatoarea sedinta pe 2 martie\r\n* Silviu vorbeste cu Blonde despre donat calculatoare\r\n* Cristi o intreaba pe Pookie despre comunicat de presa %{color:red}(done)%\r\n\r\nh2. Notiţe\r\n\r\n* Ne trebuie mapa cu prezentare infoarena pentru sponsori\r\n* Silviu pune stire ca nu mai ai voie cu HTML si sa-si actualizeze lumea profilele',13,'protected',NULL,NULL),('utilizator/zerobarat','Profil zerobarat','2009-03-02 11:31:04','2009-03-02 11:31:04','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',9739,'public',NULL,NULL),('documentatie/backup','Backup infoarena','2009-03-02 17:58:32','2009-03-17 19:47:28','h1. Backup infoarena\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nUna dintre responsabilităţile administratorilor infoarena este aceea de păstra conţinutul site-ului în siguranţă, astfel încât să poată fi recuperat în urma unor evenimente excepţionale nedorite. Este posibil ca server-ul pe care găzduim site-ul să pice, este posibil să pierdem informaţii importante, fie accidental, fie din cauza unor persoane rău intenţionate. În orice caz, este necesar să ne protejăm de astfel de evenimente cu ajutorul unui backup periodic.\r\n\r\nCâţiva administratori infoarena vor face backup periodic folosind calculatoarele lor personale. Scopul este să obţinem un sistem redundant de backup, complet automatizat şi uşor de monitorizat. Pagina aceasta explică acestor administratori ce trebuie să facă pentru a-şi configura staţiile de lucru personale în acest sens.\r\n\r\n*Atenţie!* Discută cu ceilalţi administratori infoarena înainte să te apuci să faci şi tu backup. 3-4 replici sunt suficiente, mai multe de atât consumă inutil bandă pe server.\r\n\r\nh2. Cerinţe\r\n\r\n* Sistem de operare Linux\r\n* $rsync$, şi client $ssh$ %{color:gray}(Cel mai probabil sunt deja instalate.)%\r\n* \'O copie locală de infoarena\':http://hackers.devnet.ro/wiki/HackingTutorial, instalată, configurată şi funcţională. Ai grijă să o menţii la o versiune actuală, întrucât scriptul de backup se poate modifica în timp. %{color:gray}(Este OK să foloseşti chiar copia pe care în mod normal dezvolţi cod pentru infoarena. Nu e nevoie să configurezi şi evaluatorul. Nu este necesar ca server-ul Apache sau MySQL să ruleze.)%\r\n* Cel puţin $10 GB$ spaţiu de stocare disponibil.\r\n\r\nh2. Basic Setup\r\n\r\nProcesul de backup va rula cu permisiunile unui utilizator oarecare de pe sistemul tău. Nu are importanţă ce utilizator e, însă e mai simplu să fie chiar utilizatorul pe care îl foloseşti în mod obişnuit când lucrezi la calculator. În continuare voi presupune că numele tău de utilizator este *$wickedman$* şi că eşti logat pe calculator.\r\n\r\n# Generează o cheie privată *fără parolă* pentru acces la contul de backup de pe server-ul infoarena.\r\n$ $ssh-keygen -f ~/.ssh/ia-backup$\r\n# Autorizează cheia ta pentru backup. Acest pas necesită acces root@infoarena.ro. Un mod de a-ţi autoriza cheia este să execuţi comanda următoare de pe calculatorul tău:\r\n$ $ssh -p 21883 root@infoarena.ro echo `cat ~/.ssh/ia-backup.pub` \'>> /home/backup/.ssh/authorized_keys\'$\r\n# Testează accesul la backup@infoarena.ro:\r\n$ $ssh -i ~/.ssh/ia-backup -p 21883 backup@infoarena.ro \'echo `whoami`@`hostname`\'$\r\nar trebui să afişeze $backup@infoarena$.\r\n# Crează un director pentru backup şi asigură-te că ai suficient spaţiu liber pe partiţia respectivă. (Vezi cerinţe.) Scriptul de backup e configurat să folosească în mod implicit $~/backup/infoarena$. Dacă vrei să foloseşti alt director va trebui să îl modifici corespunzător.\r\n$ $mkdir -p ~/backup/infoarena$\r\n# Execută scriptul de backup. Mai jos presupun că eşti în directorul în care ai făcut checkout la infoarena, dar nu e obligatoriu.\r\n$ $./scripts/mirror-backup$\r\n%{color:red}*Atenţie!*% Scriptul va începe să copieze toate ataşamentele de pe infoarena.ro, adică peste 6.7GB! Asigură-te că ai o conexiune cât poţi de bună ca să nu dureze o veşnicie. Desigur, următoarele apelări vor transfera mult mai puţine date.\r\n# În final ar trebui să ai o structură de directoare similară cu cea de mai jos:\r\n$ $find ~/backup/infoarena -type d$\r\n$/home/wickedman/backup/infoarena$\r\n$/home/wickedman/backup/infoarena/attach$\r\n$/home/wickedman/backup/infoarena/attach/200910$\r\n$/home/wickedman/backup/infoarena/archive$\r\n$/home/wickedman/backup/infoarena/archive/db$\r\n$/home/wickedman/backup/infoarena/archive/hackers$\r\n$/home/wickedman/backup/infoarena/archive/hackers/trac$\r\n$/home/wickedman/backup/infoarena/archive/hackers/reviewboard$\r\n$/home/wickedman/backup/infoarena/archive/hackers/svn$\r\n$/home/wickedman/backup/infoarena/archive/conf$\r\n\r\nCu fiecare lansare, $./scripts/mirror-backup$ sincronizează ultimele versiuni de backup locale cu cele de pe infoarena.ro şi poate fi rulat cu încredere de oricâte ori. Baza de date infoarena este criptată cu parolă pe server folosind \'GPG\':http://www.gnupg.org/.\r\n\r\nh2. Backup automat zilnic\r\n\r\nÎn continuare vom configura calculatorul să facă backup automat în fiecare zi folosind utilitarul $anacron$. Spre deosebire de $cron$, acesta nu necesită ca staţia de lucru să fie deschisă la o anumită oră din zi. Eşti liber să închizi şi să deschizi calculatorul oricând doreşti.\r\n\r\n# Instalează anacron. (Pe Ubuntu merge $apt-get install anacron$.)\r\n# Editează $/etc/anacrontab$\r\n$ $sudo vim /etc/anacrontab$\r\nşi adaugă la sfârşitul fişierului linia următoare. %{color:red}*Atenţie!*% Ajustează corespunzător textul îngroşat!\r\n${white-space:nowrap;overflow:auto}1	30	infoarena-backup	 sudo -H -u *wickedman* /home/{*wickedman/d/infoarena*}/scripts/mirror-backup | mail -s \"infoarena backup notice\" *cristian@infoarena.ro*$\r\n%{color:gray}(Asta înseamnă că job-ul „infoarena-backup” se execută odată pe zi, la 30 de minute după ce ai pornit calculatorul. Folosesc $sudo -u$ ca să execut job-ul cu permisiuni de utilizator obişnuit. Înlocuieşte cristian@infoarena.ro cu adresa ta de email la care doreşti să primeşti notificări la fiecare backup.)%\r\n# Testează configuraţia $anacron$.\r\n$ $sudo anacron -fnd infoarena-backup$\r\n$Anacron 2.3 started on 2009-03-03$\r\n$Will run job `infoarena-backup\'$\r\n$Jobs will be executed sequentially$\r\n$Job `infoarena-backup\' started$\r\n$Job `infoarena-backup\' terminated (mailing output)$\r\n$Normal exit (1 job run)$\r\n\r\nh2. Notificări prin email\r\n\r\nBackup-ul zilnic trimite o notificare prin email la fiecare rulare. Asta ne ajută să monitorizăm sistemul şi să ştim în permanenţă dacă încă mai funcţionează. Pentru ca notificările să fie trimise trebuie să îţi instalezi şi să îţi configurezi un server SMTP. Sunt multe moduri în care poţi să faci asta, mai jos prezint doar unul care pare să meargă la mine.\r\n\r\n# $ $sudo apt-get install postfix mailutils$\r\n$postfix$ este un server SMTP. În timpul instalării este posibil să apară un wizard de configurare, caz în care poţi să alegi opţiunea „Internet site” şi în rest să accepţi orice opţiune default deja completată. (pe sistem „next! next! next!” :P)\r\n# Testează notificările prin email.\r\n$ $sudo anacron -fnd infoarena-backup$\r\nAr trebui să primeşti un email „infoarena backup notice” care însă cel mai probabil se duce în SPAM.\r\n# Forward-ează toate email-urile de notificare către backup-notice@infoarena.ro. În felul acesta putem să monitorizăm împreună că toate terminalele de backup funcţionează, deci că avem backup redundant. Dacă foloseşti Gmail poţi să faci asta cu un filtru.\r\n',75,'protected',NULL,NULL),('blog/membri-noi-2008-p2','Infoarena în 2008: Membri noi, partea 2','2009-03-02 22:07:58','2009-03-03 08:33:47','_Continuăm seria de membri noi luându-i la întrebări, în ordine, pe: Ştefan Filip, Paul Băltescu, Ştefan Istrate şi Victor Rusu._\r\n\r\n_Dacă nu aţi citit \'prima parte\':blog/membri-noi-2008-p1 a acestui post, vă rog să o faceţi pentru că ea conţine o introducere a tuturor membrilor noi ai echipei._\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/membri-noi-2008-p2?stefan_filip.jpg! *Cum ai ajuns membru al siteului infoarena?*\r\n*Ştefan:* Am ajuns membru al siteului infoarena la inceputul clasei a X-a, adica acum 3 ani. Participasem in anii anteriori la olimpiada si acest site mi-a fost recomandat ca sursa de probleme de pregatire si pentru concursurile de antrenament.\r\n\r\n*Cum ai folosit acest site?*\r\n*Ştefan:* Am inceput greu cu arhiva. Primele probleme mi s-au parut grele, si aveam un sentiment de reusita dupa rezolvarea fiecareia, fiind nevoit sa apelez aproape de fiecare data la ajutor pentru a ajunge la solutie. De cand sunt membru infoarena am participat la majoritatea concursurilor organizate. Am un oarecare respect pentru concursurile organizate pe infoarena, pentru ca de cele mai multe ori problemele sunt interesante si grele. Au fost multe concursuri in care nu am rezolvat nici o problema si asta m-a impulsionat sa lucrez probleme mai grele si sa invat mai multe.\r\n\r\n*Cand ai început cu programarea?*\r\n*Ştefan:* Din clasa a II-a am fost membru al clubului \"Cygnus Computer\", pe vremea aceea invatam sa folosim calculatorul, ce este paint, ce este notepad :). In clasa a V-a am invat limbajul Pascal si am inceput sa fac niste joculete rudimentare in modul lui grafic. In clasa a VI-a grupa s-a desfiintat si a trebuit sa trec la grupa paralela care facea programare. Un an mai devreme alesesem sa nu vin la aceste cursuri, dar nu am mai avut alternative. Mi-a placut ce faceam la curs si de atunci particip la olimpiada de informatica. La primul meu \"ONIgim\" am luat numai punctajul din oficiu, dar am ajuns pana la urma in clasa a XII-a la ONI sa iau si premiul I.\r\n\r\n*Ce pasiuni ai înafara de programare?*\r\n*Ştefan:* Pasiuni in afara de programare... cred ca sportul. Am facut mai multi ani dans sportiv si atletism. In clasa a VI-a cred ca am luat premiul II la concursul pe Bucuresti pentru proba de rezistenta :).\r\n\r\np=. ~ ~ ~\r\n\r\n!{margin: 10px; margin-right: 0; border: 1px solid gray;}>blog/membri-noi-2008-p2?paul_baltescu.jpg! *Cum ai ajuns membru al siteului infoarena?*\r\n*Paul:* Prima oara am auzit de infoarena in clasa a IX-a de la un coleg mai mare cu un an, Andrei Gönczi. In perioada aceea se organiza preONI 2005. Asa mi-am facut cont, mai mult ca sa scap de gura lui. Am inceput sa lucrez serios de aici abia printr-a X-a si a devenit principala mea sursa de pregatire. Nu cred ca am mai bagat pe vreun site atatea surse. :)\r\n\r\n*Cand ai început cu programarea?*\r\n*Paul:* Primele tangente cu informatica le-am avut in vacanta de vara intre clasa a IV-a si a V-a. Pe vremea aceea, domnul profersor Edmond Butyka preda informatica la Liceul Teoretic \"Onisifor Ghibu\" Cluj - Napoca, unde invatam si eu. Dansul s-a hotarat sa ma initieze in tainele programarii alaturi de alti elevi pe care ii pregatea pentru olimpiada. Recunosc ca eu am fost mai mult atras de partidele de Age of Empires in retea pe care le jucam dupa orele de pregatire. :) Dupa ce a trecut vacanta am pierdut contactul cu informatica. In clasa a VI-a, dupa cateva esecuri (sau realizari minore, cum vreti sa le spuneti) la concursurile de matematica, un prieten al mamei mele, inspector de matematica, i-a sugerat sa ma trimita si la un concurs de informatica. Concursul se tinea la Palatul Copiilor. Tin minte ca au fost doua probleme. Una mi s-a parut imposibila si nu cred ca am facut sursa la ea, cealalta cerea sa se verifice daca un numar <= 1000 este palindrom. La problema asta am facut sursa (nu cu stil cum as face acum, verificand daca numarul este egal cu oglinditul sau, ci pe cazuri in functie de numarul de cifre verificam cifrele corespunzatoare). Stiu ca era complet gresita solutia mea (ca implementare). La evaluare a venit o doamna si a dat doua teste (unul cu raspunsul DA, altul cu raspunsul NU). Mi-au mers ambele mai mult din voia sortii si am luat premiul II la concurs. Apoi am participat la Olimpiada Judeteana de Informatica, m-am calificat la limita (al 36-37-lea cred) si la nationala am luat 0. Cu toate astea am continuat mai departe, desi in gimnaziu n-am facut nicio ora de informatica la\r\nscoala, toata pregatirea fiind in particular cu domnul profesor Butyka. Ma folosesc de ocazia acestui interviu sa-i multumesc in public pentru ajutorul pe care mi l-a dat.\r\n\r\n*De ce ai intrat in echipa infoarena? Ce iti propui sa faci ca membru al echipei?*\r\n*Paul:* Am intrat in echipa infoarena ca sa incerc sa rasplatesc ajutorul care mi-a fost oferit. Ca membru al echipei voi incerca sa ajut mai departe elevii, contribuind activ la dezvoltarea site-ului si implicandu-ma in activitatile organizate pentru comunitate.\r\n\r\np=. ~ ~ ~\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/membri-noi-2008-p2?stefan_istrate.jpg! *Cum ai ajuns membru al siteului infoarena?*\r\n*Ştefan:* Imi amintesc ca m-am inregistrat pe infoarena intr-o perioada in care imi faceam conturi pe mai toate site-urile, nestiiind daca imi va folosi la ceva. Am rezolvat A+B si CMMDC, dupa care am fost descurajat de restul problemelor, asa ca am stagnat. Abia dupa cateva luni am revenit si am inceput o pregatire serioasa pe site.\r\n\r\n*Cum ai folosit acest site?*\r\n*Ştefan:* Au fost mai multe etape. La inceput ma straduiam din greu sa rezolv probleme si citeam timid raspunsurile celor de pe forum. Dar nu ma simteam in stare sa intervin in discutii. Apoi am inceput sa intreb si eu si sa acumulez experienta. Cu timpul, am oferit si eu sfaturi. Am incercat sa asimilez si, totodata, sa contribui la continutul site-ului.\r\n\r\n*De ce ai intrat în echipa infoarena? Ce îţi propui să faci ca membru al echipei?*\r\n*Ştefan:* Am intrat in echipa ca urmare a unei contributii constante. Desi a trecut un an de cand am terminat cu liceul si olimpiadele, proiectul infoarena imi insufla in continuare entuziasm. Cu o comunitate asa numeroasa, imi doresc ca efortul cumulat al tuturor sa dea nastere unui continut cat mai valoros. Asta e scopul meu in cadrul proiectului.\r\n\r\n*Cand ai inceput cu programarea?*\r\n*Ştefan:* Destul de tarziu as zice: in clasa a 9-a. Dar cat de cat serios, in clasa a 10-a cand mi-am pus problema \"oare ce voi face la atestat daca eu nu pricep o boaba de C++?\". Si am invatat destula informatica incat sa-mi dau seama ca nu ma multumesc cu asa putin si ca vreau mult mai mult decat un simplu certificat.\r\n\r\n*Ce pasiuni ai in afara de programare?*\r\n*Ştefan:* Am multe, dar cateva sunt mai importante: muntele, fotografiatul si bicicleta. Si toate pornesc din copilarie: prima expeditie pe Moldoveanu, primul aparat foto nedigital, primul BMX. :)\r\n\r\n*Spune-ne o intamplare interesanta legata de site-ul infoarena!*\r\n*Ştefan:* Intr-o noapte am fost asa nemultumit de cum aratau formulele intr-un articol de pe infoarena, incat am studiat tot felul de tutoriale pe net si am invatat comenzi de LaTeX. Doar ca sa rescriu formulele respective si sa arate mai ingrijit.\r\n\r\np=. ~ ~ ~\r\n\r\n!{margin: 10px; margin-right: 0; border: 1px solid gray;}>blog/membri-noi-2008-p2?victor_rusu.jpg! *Cand ai inceput cu programarea si cum ai ajuns membru al siteului infoarena?*\r\n*Victor:* Am inceput sa invat informatica in clasa a 9-a sub indrumarea domnului profesor Stelian Ciurea. De la el am aflat despre site-ul infoarena si am devenit membru in speranta ca imi va fi de folos pentru pregatirea la informatica. Problemele din arhiva inca erau la un nivel prea ridicat pentru mine, iar la primele concursuri la care am participat pe site nu am avut rezultate promitatoare, insa asta nu m-a oprit ci m-a motivat sa continui pregatirea.\r\n\r\n*Cum ai folosit acest site?*\r\n*Victor:* Site-ul mi-a fost de mare ajutor si am invatat sa rezolv probleme citind articolele si discutiile de pe forum. Concursurile mi-au oferit sansa de a concura in conditii specifice olimpiadelor de informatica alaturi de alti olimpici si a ma evalua in comparatie cu ei. Aceste clasamente au reflectat cu precizie abilitatile fiecarui concurent, dovada fiind faptul ca la olimpiada nationala si in lotul de informatica am intalnit multi membri infoarena.\r\n\r\n*De ce ai intrat in echipa infoarena?*\r\n*Victor:*  Acum, dupa ce am terminat liceul, imi dau seama ca o mare parte din realizarile mele se datoreza comunitatii infoarena, fara de care nu as fi ajuns la acelasi nivel de performanta si nu as fi avut rezultatele pe care le-am avut. Alaturi de echipa infoarena, niste oameni deosebiti cu o dorinta de a oferi o pregatire temeinica urmatoarelor generatii de elevi la informatica, voi incerca sa ajut la dezvoltarea comunitatii si la imbunatatirea site-ului.\r\n\r\n\r\nh3. _Spor la treabă băieţi! Suntem mândri să vă avem printre noi!_\r\n\r\n',2970,'protected',3729,NULL),('gaboru','Profil gabor_oliviu1991','2009-03-03 13:15:08','2009-03-03 13:15:08','h2. Despre mine\r\n\r\n* ==user(user=\"gabor_oliviu1991\" type=\"normal\")==\r\n\r\nElev la \'Colegiul National Moise Nicoara\':http://moisenicoara.ro  din Arad\r\n\r\n* \'Blog\':http://gaborucorupt.blog.com/\r\n* \'Hi5\':http://gaboru-corupt.hi5.com/ \r\n\r\nh2. Prieteni pe infoarena\r\n\r\n\r\n\r\n* ==user(user=\"c_e_manu\" type=\"normal\")==\r\n* ==user(user=\"razyelx\" type=\"normal\")==\r\n* ==user(user=\"oznmonkey\" type=\"normal\")==\r\n* ==user(user=\"pave\" type=\"normal\")==\r\n* ==user(user=\"manuelciosici\" type=\"normal\")==\r\n* ==user(user=\"gabitzish1\" type=\"normal\")==\r\n\r\n   ',6276,'public',NULL,NULL),('propuneri/12-infoarena.org','IAP #12: Infoarena.org','2009-02-17 11:16:13','2009-03-06 10:23:44','h1. IAP #12: Infoarena.org\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2009-02-17                             |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"alexthero\")== |\r\n|_. Stare     | *_IN-CONSTRUCTIE_*                     |\r\n\r\n(toc)*{text-align:center;} *Continut*\r\n* \'Abstract\':propuneri/12-infoarena.org#abstract\r\n* \'Motivatie\':propuneri/12-infoarena.org#motivatie\r\n* \'Implementare\':propuneri/12-infoarena.org#implementare\r\n* \'Traduceri\':propuneri/12-infoarena.org#traduceri\r\n* \'Alte proiecte\':propuneri/12-infoarena.org#alte-proiecte\r\n* \'Feedback\':propuneri/12-infoarena.org#feedback\r\n\r\nh2(#abstract). Abstract\r\n\r\nSe propune utilizarea softului deja existent pentru crearea unei versiuni infoarena in limba engleza, independenta ca si continut de infoarena.ro. Realizarea acestui proiect consta in implementarea modificarilor necesare la nivel de cod si traducerea continutului.\r\n\r\nh2(#motivatie). Motivatie\r\n\r\nMotivele si avantajele acestui proiect sunt multiple si evidente. Motivatia imediata o constituie organizarea Concursului Centrelor de Excelenta cu participare internationala (polonezi). Celelalte motive si avantaje:\r\n\r\n* organizarea de concursuri internationale\r\n* formarea unei comunitati internationale si cooptarea unor colaboratori internationali\r\n* potential acces la problemele si materialele de pregatire ale unor tari ca rusia, china, etc.\r\n* recunoasterea brandului infoarena la nivel international\r\n* access la o gama mai larga de eventuali sponsori\r\n\r\nh2(#implementare). Implementare\r\n\r\nO metoda usoara si rapid de pus in practica este sa punem sus codul si sa ne apucam sa traducem. Aceasta metoda are mai multe neajunsuri pe care vom incerca sa le rezolvam pe parcursul acestui document.\r\n\r\n1. Folosirea aceluiasi cod pe ambele site-uri si update-uri concomitente.\r\nUn punct important ar fi ca ambele site-uri sa poata fi updatate cu acelasi cod scris de \"hackerul infoarena\". Problema propriu zisa este intercalarea elementelor de limba cu cele de cod. Ca sa rezolvam aceasta problema ar trebui sa avem niste \"language files\", care sa contina toate frazele folosite in cod (tot in afara paginilor wiki). SMF are deja aceste fisiere, dar e posibil ca noi sa fi modificat cate ceva in versiunea romaneasca.\r\n\r\nAvantaje:\r\n\r\n* acelasi cod pentru ambele siteuri\r\n* extinderea usoara la mai multe limbi (doar prin modificarea unui language file)\r\n\r\nDezavantaje:\r\n\r\n* volum mult de munca bruta? trebuie trecut prin fiecare fisier si modificat tot textul\r\n\r\n2. Concursuri care pot fi date simultan pe ambele siteuri\r\nPornind de la motivatie, o intrebare care vine inevitabil este: \"cum dam concursuri simultan pe ambele siteuri\". O prima solutie ar fi crearea concursurilor pe ambele siteuri, cu probleme identice, dar traduse. Singura problema ar fi cum afisam clasamentele (cu concurenti de pe ambele siteuri). Ideal ar fi ca fiecare din cele 2 clasamente sa contina si userii care au submitat dincolo, dar cu un flag si cu link catre profilul lor. Putem avea username-uri identice, dar ele sa defineasca un alt utilizator.\r\n\r\nSolutie: definim un nou macro care (dandui-se linkurile dintre concursuri + probleme):\r\n\r\n* se conecteaza la baza de date a celuilalt site / un fisier xml public actualizat de celalalt site\r\n* afiseaza clasamentul concatenat\r\nTrebuie sa folosim aceasi metoda ca acum pentru a reda eficient clasamentele.\r\n\r\nAvantaje: \r\n\r\n* aparent rezolvam toate subproblemele care ar putea aparea la crearea concursurilor\r\n\r\nDezavantaje:\r\n\r\n* link inestetic catre profilul de pe celalalt site\r\n* multe linkuri catre acelasi site dauneaza la page ranking? nu sunt sigur\r\n\r\n3. Teste\r\n\r\nO alta informatie reduntanta sunt testele. Nu as fi mentionat acest lucru daca nu trimitea Bogdan e-mail-ul din 22 feb. Putem linka unele pagini intre ele, astfel incat atasamentele celor doua pagini sa fie aceleasi si mentinute o singura data. Totusi, pentru inceput, cred ca acest lucru nu e necesar.\r\n\r\n*O lista scurta cu ce trebuie implementat inainte sa ne apucam de tradus:*\r\n\r\n* language files\r\n* clasamente comune\r\n\r\nh2(#traduceri). Traduceri\r\n\r\nNe propunem sa traducem urmatoarele pentru prima versiune:\r\n\r\n* documentatia necesara pentru un utilizator care vrea sa rezolve probleme si sa participe la concurs\r\n* un set de 5 probleme reprezentative din arhiva de probleme (A+B, CMMDC, 3 mai grele..)\r\n* un set de 3 probleme reprezentative din arhiva educationala\r\n* 1-2 articole\r\n* forumul incepe de la 0\r\n\r\nVom crea un nou proiect marca infoarena, \"traduce infoarena\" in care cautam colaboratori. Acestia vor traduce continut. Fiecare e liber sa traduca in limita timpului disponibil.\r\n\r\nh2(#alte-proiecte). Localizare in alte proiecte open-source\r\n\r\nPHPbb\r\n\r\n* Exista language packs specializate pe diferite limbi. Fiecare language pack contine aceleasi fisiere, care reprezinta\r\nimpartirea tuturor frazelor folosite pe categorii. Fiecare fraza e definita de un text generic in engleza. e.g. \r\n\'SUBMIT_VOTE\' = \'Trimite vot\'.\r\n\r\nMediaWiki\r\n\r\n* Cate un fisier .php pentru fiecare limba care contine toate mesajele traduse. Din nou, fraza e definita de un text generic in \r\nengleza. \r\n* Ce e interesant la mediaWiki e ca au o metoda care returneaza mesajul in limba in functie de preferinte ( cred :) ). De exemplu, \r\ndaca preferintele sunt 1. Engleza 2. Romana 3. Germana, functia cauta prima data textul respectiv in engleza. Daca nu e gasit, cauta \r\nin romana, iar apoi in germana. Acest lucru s-ar aplica bine la infoarena.org, avem preferinte: 1. Engleza 2. Romana pentru \r\ninfoarena.org si preferinte: 1. Romana 2. Engleza pentru infoarena.ro. In cazul in care mesajul nu e gasit in prima limba, putem sa \r\ncoloram textul din aceasta functie in ceva saritor in ochi (rosu?) pentru a sti ca trebuie tradus. Putem sa facem acest lucru doar \r\npentru admini sau/si pentru helperi.\r\n\r\nWordpress\r\n\r\n* Cate un fisier .po sau .mo pentru fiecare limba. In fisierele acestea se gasesc comentarii pentru fiecare mesaj care spun unde\r\neste gasita fraza. Exemplu\r\n\r\n== code(c) |\r\n#: wp-admin/edit-pages.php:29\r\n#: wp-admin/edit-pages.php:32\r\n#: wp-admin/edit.php:37\r\n#: wp-admin/edit.php:40\r\n#: wp-admin/page.php:170\r\n#: wp-admin/page.php:173\r\n#: wp-admin/post.php:211\r\n#: wp-admin/post.php:214\r\n#: wp-admin/upload.php:84\r\n\r\nmsgid \"Error in deleting...\"\r\nmsgstr \"Eroare la stergere...\"\r\n==\r\n\r\nh2(#feedback). Feedback\r\n\r\nIntra pe \'forum\':forum/index.php?topic=3712.0 pentru a da feedback.',716,'public',3712,NULL),('runda/lol1','lol1','2009-03-22 08:24:15','2009-03-22 08:24:15','h1. == roundparam(round_id=\"lol1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"lol1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"lol1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"lol1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/lol1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"lol1\" score=\"1\")==',9782,'round: lol1',NULL,NULL),('utilizator/toni2007','Profil toni2007','2007-02-17 19:45:49','2010-02-04 20:29:19','h2. Despre mine\r\n\r\nSunt elev in clasa a 10a la ICHB. De prin clasa a 6-a am inceput sa lucrez la informatica (singur si in pascal) si am reusit sa iau mentiune (locul 5) la ONI. In clasa a 7-a, poate datorita succesului din anul precedent, am lasat-o mai moale, si nu am reusit nici macar sa ma calific la nationala, dar am luat locul intai la Bynet. In clasa a 8-a am iesit pe locul 4 si am prins JBOI-ul unde am luat medalie de argint. In clasa a 9-a am intrat in lot si am ajuns la olimpiada din Yakutia unde am luat medalie de aur. Lucrez in principal de pe infoarena dar si de pe \"SGU\":http://acm.sgu.ru/teaminfo.php?id=017929 and \"SPOJ\":http://spoj.pl/, aceste fiind principalele mele surse de pregatire.\r\n\r\n* Limbaje de programare C, C++, Pascal, C# , Nemerle, FreeBasic, Java, D, PHP, Perl, Ruby, Python, Pike\r\n* Alte limbaje: HTML, Windows batch programming, BaSh\r\n* Sisteme de operare: Linux, Unix, Windows\r\n* Consider ca Fedora este o distributie Linux mult mai buna decat Ubuntu.\r\n\r\n\"Aici\":http://opensvn.csie.org/eval este evaluatorul scris de mine, pe platforma JRUN, o interfata pentru evaluatorul scris de \"Sanduleac Dan\":utilizator/sandyxp.\r\n\r\nh2. Distinctii primite\r\n\r\nh3. Informatica:\r\n\r\nJBOI 2008 medalie de argint (locul 6)\r\nOlimpiada Pluridisciplinara Tuymaada din Yakutia (2009) Medalie de aur \r\nONI 2009 locul 1\r\nInclus in lotul de juniori 2008\r\nInclus in lotul de seniori 2009\r\nONI 2008 locul 4\r\nONI 2007 locul 1 la Bynet\r\nONI 2006 locul 5\r\nCalificare finala Algoritmiada 2009\r\nCalificare finala .campion 2009\r\n\r\nh2. Profesori pe infoarena\r\n\r\n==user(user=\"pauldb\" type=\"normal\")==\r\n\r\n==user(user=\"wefgef\" type=\"normal\")==\r\n\r\n==user(user=\"silviug\" type=\"normal\")==\r\n\r\nh2. Prieteni pe infoarena \r\n\r\n==user(user=\"CezarMocan\" type=\"normal\")==\r\n\r\n==user(user=\"Savim\" type=\"normal\")==\r\n\r\n==user(user=\"raduzer\" type=\"normal\")==\r\n\r\n==user(user=\"GavrilaVlad\" type=\"normal\")==\r\n\r\n==user(user=\"mariusdrg\" type=\"normal\")==\r\n\r\n==user(user=\"crawler\" type=\"normal\")==\r\n\r\n==user(user=\"perticas_catalin\" type=\"normal\")==\r\n\r\n==user(user=\"Zilla\" type=\"normal\")==\r\n\r\n==user(user=\"hadesgames\" type=\"normal\")==\r\n\r\n==user(user=\"Ilinca\" type=\"normal\")==\r\n\r\n==user(user=\"tvlad\" type=\"normal\")==\r\n\r\n==user(user=\"andrei-alpha\" type=\"normal\")==\r\n\r\n==user(user=\"tamas_iulia\" type=\"normal\")==\r\n\r\n==user(user=\"tudalex\" type=\"normal\")==\r\n\r\n==user(user=\"DjSefu\" type=\"normal\")==\r\n\r\n==user(user=\"gabitzish1\" type=\"normal\")==\r\n\r\n==user(user=\"ciprianf\" type=\"normal\")==\r\n\r\n== include(page=\"template/taskfooter\" task_id=\"adunare\") ==\r\n ',6061,'public',NULL,NULL),('runda/6','6','2009-04-08 14:03:20','2009-04-08 14:03:20','h1. == roundparam(round_id=\"6\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"6\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"6\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"6\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/6/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"6\" score=\"1\")==',393,'round: 6',NULL,NULL),('runda/6/clasament','Clasament 6','2009-04-08 14:03:20','2009-04-08 14:03:20','h1. Clasament ==roundparam(round_id=\"6\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"6\")==',393,'round: 6',NULL,NULL),('runda/4','4','2009-04-08 14:05:05','2009-04-08 14:05:05','h1. == roundparam(round_id=\"4\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"4\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"4\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"4\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/4/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"4\" score=\"1\")==',393,'round: 4',NULL,NULL),('runda/4/clasament','Clasament 4','2009-04-08 14:05:05','2009-04-08 14:05:05','h1. Clasament ==roundparam(round_id=\"4\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"4\")==',393,'round: 4',NULL,NULL),('runda/problemiada_1','problemiada_1','2009-04-08 19:04:02','2009-04-08 19:04:02','h1. == roundparam(round_id=\"problemiada_1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"problemiada_1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"problemiada_1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"problemiada_1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/problemiada_1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"problemiada_1\" score=\"1\")==',5748,'round: problemiada_1',NULL,NULL),('runda/problemiada_1/clasament','Clasament problemiada_1','2009-04-08 19:04:02','2009-04-08 19:04:02','h1. Clasament ==roundparam(round_id=\"problemiada_1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"problemiada_1\")==',5748,'round: problemiada_1',NULL,NULL),('runda/ice_1','ice_1','2009-04-08 19:37:13','2009-04-08 19:37:13','h1. == roundparam(round_id=\"ice_1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"ice_1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"ice_1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ice_1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/ice_1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"ice_1\" score=\"1\")==',9782,'round: ice_1',NULL,NULL),('runda/ice_1/clasament','Clasament ice_1','2009-04-08 19:37:13','2009-04-08 19:37:13','h1. Clasament ==roundparam(round_id=\"ice_1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"ice_1\")==',9782,'round: ice_1',NULL,NULL),('runda/page1contest','page1contest','2009-11-22 19:59:06','2009-11-22 19:59:06','h1. == roundparam(round_id=\"page1contest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"page1contest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"page1contest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"page1contest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/page1contest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"page1contest\" score=\"1\")==',7156,'round: page1contest',NULL,NULL),('registru-diplome','Registru diplome','2007-06-26 09:34:59','2009-07-18 11:27:50','h1. Registru diplome\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nNe mandrim cu activitatea noastra si incercam sa premiem numai persoane care suntem convinsi ca merita. Incercam sa acordam diplome de onoare numai celor care intr-adevar inteleg spiritul infoarena si ne ajuta sa ne indeplinim obiectivele.\r\n\r\nFiecare diploma eliberata de infoarena este inseriata si inregistrata aici. O diploma infoarena care nu se gaseste in registrul de mai jos nu este valida.\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n\r\n\r\n|_. Nr.|_. Data     |_. Tip Diploma |_. Eveniment |_. Presedinte infoarena |_. Presedinte comisie |_. Eliberata pe numele |\r\n|  1 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Tataroiu Bogdan* |\r\n|  2 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Sperlea Adriana* |\r\n|  3 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Ionescu Victor* |\r\n|  4 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Simion Alexandru* |\r\n|  5 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Baltescu Paul Dan* |\r\n|  6 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Rusu Victor* |\r\n|  7 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Airinei Adrian* |\r\n|  8 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Grigorean Andrei* |\r\n|  9 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Savu Victor* |\r\n| 10 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Lica Adela* |\r\n| 11 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Savin Tiberiu* |\r\n| 12 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Stroe Marius* |\r\n| 13 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Istrate Stefan* |\r\n| 14 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Chis Raoul* |\r\n| 15 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Duta Vlad* |\r\n| 16 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Purice Andrei* |\r\n| 17 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Tudorica Alexandru* |\r\n| 18 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Velicu Adrian* |\r\n| 19 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Parcalabescu Maria* |\r\n| 20 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Gheorghe Cosmin* |\r\n| 21 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Dragus Marius* |\r\n| 22 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Sanduleac Dan* |\r\n| 23 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Puni Andrei Paul* |\r\n| 24 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Pasaila Daniel* |\r\n| 25 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Stanciu Valentin* |\r\n| 26 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Pasoi Mircea* |\r\n| 27 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Strat Cristian George* |\r\n| 28 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Luca Elisabeth* |\r\n| 29 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Cardei Claudia* |\r\n| 30 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Pastor Diana* |\r\n| 31 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Haret Alexandra* |\r\n| 32 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Radulescu Flaviu* |\r\n| 33 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Yuksel Ali* |\r\n| 34 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Florea Tiberiu* |\r\n| 35 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Vladu Adrian* |\r\n| 36 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Diaconu Adrian* |\r\n| 37 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Ganceanu Silviu Ionut* |\r\n| 38 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Crestez Leonard* |\r\n| 39 | 2007-06-25 | premiul 3, clasa IX       | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Sperlea Adriana* |\r\n| 40 | 2007-06-25 | premiul 2, clasa IX       | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Tataroiu Bogdan* |\r\n| 41 | 2007-06-25 | premiul 1, clasa IX       | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Tudorica Alexandru* |\r\n| 42 | 2007-06-25 | premiul 3, clasa X        | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Savu Victor* |\r\n| 43 | 2007-06-25 | premiul 2, clasa X        | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Puni Andrei* |\r\n| 44 | 2007-06-25 | premiul 1, clasa X        | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Gheorghe Cosmin* |\r\n| 45 | 2007-06-25 | premiul 3, clasele XI-XII | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Rusu Victor* |\r\n| 46 | 2007-06-25 | premiul 2, clasele XI-XII | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Simion Alexandru* |\r\n| 47 | 2007-06-25 | premiul 1, clasele XI-XII | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Grigorean Andrei* |\r\n| 48 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Dragos Ciobanescu* |\r\n| 49 | 2008-03-23 | premiu 1, clasele 5-8      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Cezar Mocan* |\r\n| 50 | 2008-03-23 | premiu 2, clasele 5-8      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Radu Stefan Voroneanu* |\r\n| 51 | 2008-03-23 | premiu 3, clasele 5-8      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Andrei Purice* |\r\n| 52 | 2008-03-23 | premiu 1, clasa 9      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Ioana Pandele* |\r\n| 53 | 2008-03-23 | premiu 2, clasa 9      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Alexandru Tache* |\r\n| 54 | 2008-03-23 | premiu 3, clasa 9      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Bogdan Bazu* |\r\n| 55 | 2008-03-23 | premiu 1, clasa 10      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Bogdan Tataroiu* |\r\n| 56 | 2008-03-23 | premiu 2, clasa 10     | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Istvan Hevele* |\r\n| 57 | 2008-03-23 | premiu 3, clasa 10      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Bogdan Casu-Pop* |\r\n| 58 | 2008-03-23 | premiu 1, clasele 11-12      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Cosmin Gheorghe* |\r\n| 59 | 2008-03-23 | premiu 2, clasele 11-12      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Alexandru Tandrau* |\r\n| 60 | 2008-03-23 | premiu 3, clasele 11-12      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Paul-Dan Baltescu* |\r\n| 61 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Radu Oprescu* |\r\n| 62 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Andrei Jurba* |\r\n| 63 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Palianos Cristian* |\r\n| 64 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Ada Solcan* |\r\n| 65 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Victor Popescu* |\r\n| 66 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Victor Ionescu* |\r\n| 67 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Alexandru Tudorica* |\r\n| 68 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Adriana Sperlea* |\r\n| 69 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Vlad Tataranu* |\r\n| 70 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Vicol Sergiu* |\r\n| 71 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Adrian Hulparu* |\r\n| 72 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Bogdan Taloi* |\r\n| 73 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Ioana Radu* |\r\n| 74 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Marius Petcu* |\r\n| 75 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Alex Mircescu* |\r\n| 76 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Radu Zernoveanu* |\r\n| 77 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Serban Stan* |\r\n| 78 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Vlad Gavrila* |\r\n| 79 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Filip Stefan* |\r\n| 80 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Tiberiu Savin* |\r\n| 81 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Florin Pogocsan* |\r\n| 82 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Marius Dragus* |\r\n| 83 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Alexandru Simion* |\r\n| 84 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Vlad Tudose* |\r\n| 85 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Mihai Damaschin* |\r\n| 86 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Victor Rusu* |\r\n| 87 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Adrian Airinei* |\r\n| 88 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Silviu Ganceanu* |\r\n| 89 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Filip Buruiana* |\r\n| 90 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Andrei Grigorean* |\r\n| 91 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Adrian Diaconu* |\r\n| 92 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Mircea Pasoi* |\r\n| 93 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Cristian Strat* |\r\n| 94 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Valentin Stanciu* |\r\n| 95 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Tiberiu Florea* |\r\n| 96 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Claudia Cardei* |\r\n| 97 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Alexandra Haret* |\r\n| 98 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Elisabeth Luca* |\r\n| 99 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Sergiu Strat* |\r\n| 100 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Maricel Mihalcea* |\r\n| 101 | 2009-05-02 | premiul 3, gimnaziu | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Gheorghe Mihai* |\r\n| 102 | 2009-05-02 | premiul 2, gimnaziu | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Siminiuc Antoanela* |\r\n| 103 | 2009-05-02 | premiul 1, gimnaziu | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Gavrilă Vlad* |\r\n| 104 | 2009-05-02 | premiul 3, clasele IX-X | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Mocan Cezar* |\r\n| 105 | 2009-05-02 | premiul 2, clasele IX-X | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Purice Andrei* |\r\n| 106 | 2009-05-02 | premiul 1, clasele IX-X | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Stan Şerban Andrei* |\r\n| 107 | 2009-05-02 | premiul 3, clasele XI-XII | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Szasz Robert* |\r\n| 108 | 2009-05-02 | premiul 2, clasele XI-XII | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Pârvu Andrei* |\r\n| 109 | 2009-05-02 | premiul 1, clasele XI-XII | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Tutunaru Mihai Cosmin* |\r\n| 110 | 2009-05-02 | premiul 2, studenţi | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Mugurel Ionuţ Andreica* |\r\n| 111 | 2009-05-02 | premiul 3, studenţi | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Tudose Vlad* |\r\n| 112 | 2009-05-02 | premiul 1, studenţi | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Saveluc Vlad* |\r\n| 113 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Silviu-Ionuţ Gănceanu* |\r\n| 114 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Mircea Paşoi* |\r\n| 115 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Cristina Petrovici* |\r\n| 116 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Ştefan Istrate* |\r\n| 117 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Marius Stroe* |\r\n| 118 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Valentin Stanciu* |\r\n| 119 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Victor Rusu* |\r\n| 120 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Adrian Airinei* |\r\n| 121 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Bogdan Tătăroiu* |\r\n| 122 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Cosmin Gheorghe* |\r\n| 123 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Ştefan Filip* |\r\n| 124 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Andrei Grigorean | *Cristian George Strat* |\r\n| 125 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Andrei Grigorean* |\r\n| 126 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Manuela Şerban* |\r\n| 127 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Teodor Schiller* |\r\n| 128 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Mariana Bulbuc* |\r\n| 129 | 2009-05-02 | participare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Voicu Octavian* |\r\n| 130 | 2009-05-02 | participare | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Dima Mircea* |\r\n| 131 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Delia Blăjan* |\r\n| 132 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Alexandru Costin* |\r\n| 133 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Alexandra Haret* |\r\n',75,'protected',NULL,NULL),('runda/refacere','refacere','2009-04-09 10:17:18','2009-04-09 10:30:00','h1. == roundparam(round_id=\"refacere\" param=\"title\") ==\r\n\r\n    O planeta din imperiul galactic Zaron a fost distrusa in timpul razboiului. Imperiul nu-si permite sa mai piarda alte planete asa intra in conflic petru a dobandi o planeta noua bogata in resurse. Pentru a se locui pe planeta trebuie refacuta complet. Ajutati imperiul sa-si refaca forta. \r\n\r\n== roundregister(round_id=\"refacere\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"refacere\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"refacere\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/refacere/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"refacere\" score=\"1\")==',7670,'round: refacere',NULL,NULL),('runda/refacere/clasament','Clasament refacere','2009-04-09 10:17:18','2009-04-09 10:17:18','h1. Clasament ==roundparam(round_id=\"refacere\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"refacere\")==',7670,'round: refacere',NULL,NULL),('runda/concurs','concurs','2009-04-09 15:53:36','2009-04-09 15:53:36','h1. == roundparam(round_id=\"concurs\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"concurs\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"concurs\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"concurs\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/concurs/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"concurs\" score=\"1\")==',10117,'round: concurs',NULL,NULL),('runda/concurs/clasament','Clasament concurs','2009-04-09 15:53:36','2009-04-09 15:53:36','h1. Clasament ==roundparam(round_id=\"concurs\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"concurs\")==',10117,'round: concurs',NULL,NULL),('runda/pentru_incepatori','pentru_incepatori','2009-04-09 16:51:52','2009-04-09 16:51:52','h1. == roundparam(round_id=\"pentru_incepatori\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"pentru_incepatori\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"pentru_incepatori\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"pentru_incepatori\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/pentru_incepatori/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"pentru_incepatori\" score=\"1\")==',9735,'round: pentru_incepatori',NULL,NULL),('runda/pentru_incepatori/clasament','Clasament pentru_incepatori','2009-04-09 16:51:52','2009-04-09 16:51:52','h1. Clasament ==roundparam(round_id=\"pentru_incepatori\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pentru_incepatori\")==',9735,'round: pentru_incepatori',NULL,NULL),('grigore-moisil-2009/solutii/palindrom','grigore-moisil-2009/solutii/palindrom','2009-04-05 20:17:57','2009-04-09 19:00:14','h2(#palindrom). \'Palindrom\':problema/palindrom\r\n\r\nSe aplică _metoda Greedy_. Conform cerinţei din enunţ se impune să inserăm caractere doar la sfârşitul şirului. Observăm că un palindrom de lungime minimă se obţine prin inserarea unui număr minim de caractere la sfârşitul şirului. Pentru a obţine acest număr minim trebuie să găsim lungimea maximă a unui palindrom care se termină pe ultima poziţie a şirului. Dacă şirul iniţial este $abcdzyxyz$, palindromul căutat este $zyxyz$, iar rezultatul va fi $abcdzyxyzdcba$, adică vom adăuga caracterele aflate în faţa palindromului cu care se termină şirul iniţial, dar în ordine inversă.\r\n\r\nNotăm cu $T$ şirul $S$ inversat. Dacă parcurgem şirul $S$ de la stânga la dreapta, va trebui ca pentru fiecare poziţie $i$ să determinăm cel mai lung sufix al şirului $S[1..i]$ care este prefix al şirului $T[1..n]$, unde $n$ este lungimea şirului. Dacă lungimea acestui subşir este $lung$ atunci:\r\n\r\n# dacă $lung = n – i$, atunci am obţinut un palindrom de lungime $2 * lung$ cu centrul între poziţiile $i$ şi $i + 1$.\r\n# dacă $lung = n – i + 1$, atunci am obţinut un palindrom de lungime $2 * lung – 1$ cu centrul în poziţia $i$.\r\n# dacă $lung < n – i$, atunci nu avem un palindrom şi ignorăm această poziţie.\r\n\r\nPentru a determina acest subşir observăm că este nevoie să construim funcţia prefix (cunoscut din \'algoritmul $KMP$\':automate-finite-si-kmp de potrivire a şirurilor) pentru şirul $T$ şi să parcurgem ulterior şirul $S$ pentru a determina lungimile.\r\n\r\nAlgoritmul are complexitatea $O(n)$.\r\n\r\nO alta soluţie care ar fi obţinut 100 de puncte este folosirea hashurilor pentru a căuta cel mai lung sufix palindrom (vezi \'potrivirea şirurilor\':problema/strmatch pe baza algoritmului Rabin-Karp ).\r\nParcugând şirul de la sfarşit se reţine intr-un hash sufixul obţinut până la acel moment, iar in alt hash inversul acestui sufix. În caz că aceste 2 hashuri sunt identice se reţine poziţia curentă şi se continuă căutarea.\r\n\r\nSoluţia se obţine adăugând in ordine inversa, la coada şirului iniţial, caracterele aflate in stanga poziţiei de început a celui mai lung sufix palindrom. \r\n\r\nDeoarece compararea celor doua hashuri se face in $O(1)$ algoritmul final va avea complexitatea $O(n)$\r\n',5021,'public',NULL,NULL),('runda/ice_2/clasament','Clasament ice_2','2009-04-10 05:46:49','2009-04-10 05:46:49','h1. Clasament ==roundparam(round_id=\"ice_2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"ice_2\")==',9782,'round: ice_2',NULL,NULL),('probleme-cu-puncte-laticiale','Probleme cu puncte laticiale','2009-02-09 21:51:10','2010-01-24 15:32:55','h1. Probleme cu puncte laticiale\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"portocala\") ==\r\n\r\n(Categoria _Matematică_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 25em}*{text-align:center;} *Conţinut*\r\n* \'Introducere\':probleme-cu-puncte-laticiale#introducere\r\n* \'Problema 1\':probleme-cu-puncte-laticiale#problema1\r\n* \'Problema 2\':probleme-cu-puncte-laticiale#problema2\r\n* \'Problema 3: Copaci\':probleme-cu-puncte-laticiale#problema3\r\n* \'Problema 4\':probleme-cu-puncte-laticiale#problema4\r\n* \'Problema 5: Counting triangles\':probleme-cu-puncte-laticiale#problema5\r\n* \'Problema 6: Dreptunghiuri\':probleme-cu-puncte-laticiale#problema6\r\n* \'Problema 7: Paralelograme\':probleme-cu-puncte-laticiale#problema7\r\n* \'Concluzii\':probleme-cu-puncte-laticiale#concluzii\r\n* \'Bibliografie\':probleme-cu-puncte-laticiale#bibliografie\r\n\r\nh2(#introducere). Introducere\r\n\r\nArticolul de faţă se va concentra pe probleme în care vor apărea puncte de coordonate întregi care sunt numite puncte laticiale. Sursele [1] şi [2] menţionate în \'bibliografie\':probleme-cu-puncte-laticiale#bibliografie conţin câte un capitol despre puncte laticiale care, deşi sunt mai riguros tratate decât în acest articol, pot fi interesante pentru un elev în pregătirea pentru olimpiadă. Să vedem acum câteva probleme ce au apărut pe la concursurile de programare.\r\n\r\nh2(#problema1). Problema 1\r\n\r\nbq. Să se determine numărul de puncte de coordonate întregi prin care trece segmentul determinat de punctele $(0, 0)$ şi $(N, M)$. De exemplu, pentru $N = 9$ şi $M = 12$ pe segment vor fi $4$ puncte de coordonate întregi.\r\n\r\np=. !probleme-cu-puncte-laticiale?img1.JPG 70%!\r\n\r\nh3. Rezolvare\r\n\r\nPutem considera doar cazurile în care $0 &le; N &le; M$. Dacă $N = 0$ atunci, evident, avem $M + 1$ puncte pe segment. Astfel, trebuie să rezolvăm doar cazul în care $1 &le; N &le; M$.\r\nEvident că orice punct $(x, y)$, pentru a fi pe segmentul nostru, trebuie să satisfacă ecuaţia $y = (M / N) * x$. Această ecuaţie are ca soluţie un număr natural doar dacă $M * x$ se divide cu $N$. De aici, dacă $D = cmmdc(M, N)$ atunci $x$ se divide cu $N / D$. Obţinem, astfel, $x$ de forma $k * (N / D)$, de unde rezultă că $y$ este de forma $y = k * (M / D)$. Pentru ca punctul $(x, y)$ să aparţină segmentului, trebuie ca $0 &le; x &le; N$ şi $0 &le; y &le; M$, şi, înlocuind în a doua inegalitate pe $y$ avem $0 &le; k &le; D$. În concluzie, numărul de puncte de pe un segment de la $(0, 0)$ la $(N, M)$ este egal cu cel mai mare divizor comun al numerelor $M$ şi $N$ la care adăugăm $1$. Putem determina acest număr în complexitate $O(log (N + M))$.\r\n\r\nh2(#problema2). Problema 2\r\n\r\nbq. Se dă un triunghi cu vârfurile în puncte laticiale. Se cere să se determine numărul de puncte de coordonate întregi ce se află în interiorul triunghiului sau pe laturile lui. De exemplu, un triunghi cu vârfurile de coordonate $(1, 5)$, $(5, 1)$ şi $(6, 6)$ are $16$ puncte în interior.\r\n\r\np=. !probleme-cu-puncte-laticiale?img2.JPG!\r\n\r\nh3. Rezolvare\r\n\r\nPentru un dreptunghi cu laturile paralele cu axele de coordonate de lungime $M$ şi lăţime $N$ avem că numărul de puncte situate strict în interiorul dreptunghiului este $(M - 1) * (N - 1)$, iar numărul de puncte situate pe laturile poligonului este $2M + 2N$. Dacă notăm cu $B$ numărul de puncte de pe laturi, cu $I$ numărul de puncte situate strict în interiorul unui dreptunghi şi cu $A$ aria dreptunghiului, observăm că $I + B/2 - 1 = (M - 1) * (N - 1) + M + N - 1 = M * N = A$.\r\nÎn cazul triunghiurilor dreptunghice ce au două catete vom vedea că această formulă se păstrează. Evident avem că $A = (M * N)/2$. Pe ipotenuza triunghiului vom avea $D$ puncte ({$D = cmmdc(M, N) + 1$}, dar aceasta nu ne interesează pe moment). Rezultă că numărul de puncte de pe laturile triunghiului este $B = M + N + D - 1$. Numărul de puncte $I$ din interiorul triunghiului este numărul de puncte din interiorul dreptunghiului $(M - 1) * (N - 1)$ din care se scad punctele interioare de pe diagonala $D - 2$, rezultatul împărţindu-se apoi la $2$. De aici avem $I = ((M - 1) * (N - 1) - D + 2) / 2$.\r\n\r\nVerificăm formula $I + B/2 - 1 = (M - 1) * (N - 1)/2 - D/2 + 1 + M/2 + N/2 + D/2 + 1/2 = (M * N)/2$. Deci formula se verifică şi pe astfel de triunghiuri.\r\n\r\nAcum ne uităm la cel mai mic dreptunghi ce conţine un triunghi oarecare. Acest dreptunghi poate fi împărţit în patru triunghiuri din care unul este cel iniţial, iar celelalte sunt trei triunghiuri dreptunghice pentru care catetele merg de-a lungul liniilor laticiale. Vom vedea că formula noastră se verifică şi pentru triunghiuri oarecare. Notăm cu $I{~d~}$ numărul de puncte interioare dreptunghiului, $A{~d~}$ aria dreptunghiului şi $B{~d~}$ numărul de puncte de pe laturile dreptunghiului, cu $I{~1~}$, $I{~2~}$, $I{~3~}$ numărul de puncte din interiorul celor trei triunghiuri dreptunghice, $B{~1~}$, $B{~2~}$, $B{~3~}$ numărul de puncte de pe laturile celor trei triunghiuri, iar $A{~1~}$, $A{~2~}$ şi $A{~3~}$ ariile celor trei triunghiuri. Avem că $I = I{~d~} - I{~1~} - I{~2~} - I{~3~} - B + 3$ (trebuie să eliminăm punctele de pe laturile triunghiului interior şi să avem grijă de vârfurile acestui triunghi), $B = B{~1~} + B{~2~} + B{~3~} - B{~d~}$ iar $A = A{~d~} - A{~1~} - A{~2~} - A{~3~}$. De aici avem că $I + B/2 - 1 = I{~d~} - I{~1~} - I{~2~} - I{~3~} - B{~1~}/2 - B{~2~}/2 - B{~3~}/2 + B{~d~}/2 - 1 + 3 = (I{~d~} + B{~d~}/2 - 1) - (I{~1~} + B{~1~}/2 - 1) - (I{~1~} + B{~1~}/2 - 1) - (I{~1~} + B{~1~}/2 - 1) = A{~d~} - A{~1~} - A{~2~} - A{~3~} = A$, deci egalitarea este valabilă şi pentru triunghiuri oarecare.\r\n\r\np=. !probleme-cu-puncte-laticiale?img3.JPG!\r\n\r\nAcum aria triunghiului cu vârfurile $(x1, y1)$, $(x2, y2)$, $(x3, y3)$ o putem afla uşor folosind \'formula lui Heron\':http://en.wikipedia.org/wiki/Heron%27s_formula sau folosind determinantul:\r\n<tex> \\displaystyle \\frac {1} {2} \\cdot | \\left| \\begin{array}{ccc}\r\nx_{1} & y_{1} & 1 \\\\\r\nx_{2} & y_{2} & 1 \\\\\r\nx_{3} & y_{3} & 1 \\end{array} \\right| |.  </tex>\r\n\r\nNumărul de puncte de pe laturile triunghiului poate fi determinat uşor folosind formula demonstrată în problema anterioară. Acum, folosind formula $I + B/2 - 1 = A$ putem afla numărul $I$ şi problema e rezolvată prin întoarcerea numărului $I + B$. Complexitatea rezolvării este $O(log N)$ unde $N$ este valoarea maximă a coordonatelor.\r\n\r\nh2(#problema3). Problema 3: \'Copaci\':problema/copaci (info{_arena_})\r\n\r\nbq. Se dă un poligon prin vârfurile sale aflate doar la coordonate numere naturale. Poligonul nu este neapărat convex. Se cere să se găsească numărul punctelor aflate strict în interiorul poligonului la coordonate numere întregi.\r\nDe exemplu, pentru poligonul dat prin vârfurile $(0, 4)$, $(0, 5)$, $(2, 7)$, $(2, 4)$, $(6, 6)$ şi $(4, 0)$ avem $12$ astfel de puncte.\r\n\r\np=. !probleme-cu-puncte-laticiale?img4.JPG 80%!\r\n\r\nh3. Rezolvare\r\n\r\nFormula $I + B/2 - 1 = A$ prezentată mai sus se numeşte \'Teorema lui Pick\':http://en.wikipedia.org/wiki/Pick%27s_theorem, iar ea este valabilă şi pentru poligoane oarecare. Acest fapt este adevărat pentru că orice poligon are o diagonală interioară care îl împarte în două poligoane distincte. Dacă notăm $I{~1~}$ şi $I{~2~}$ punctele interioare celor două poligoane, $B{~1~}$ şi $B{~2~}$ punctele de pe laturile celor două poligoane, $A{~1~}$ şi $A{~2~}$ ariile celor două poligoane şi $D$ numărul de puncte de coordonate întregi de pe diagonală, atunci, dacă egalitatea ar fi fost satisfăcută pentru cele două poligoane, am avea că $B{~1~} + B{~2~} = B + 2D - 2$, $I = I{~1~} + I{~2~} + D - 2$. De aici avem $A = A{~1~} + A{~2~} = I{~1~} + B{~1~}/2 - 1 + I{~2~} + B{~2~}/2 - 1 = I{~1~} + I{~2~} + B/2 + D - 1 - 2 = I + B/2 - 1$. Astfel putem demonstra prin inducţie că relaţia este satisfăcută pentru orice poligon.\r\n\r\nAria unui poligon poate fi calculată uşor folosind următoarea formulă: \r\n<tex> \\displaystyle A = \\sum_{i=1}^{n} (x_i \\cdot y_{i+1}-x_{i+1} \\cdot y_i) </tex>, unde punctul de indice $n + 1$ este primul punct. Astfel, obţinem un algoritm de complexitate $O(N log (Max_X + Max_Y))$.\r\n\r\nh2(#problema4). Problema 4 (Marele Premiu Paco, 2000)\r\n\r\nbq. Se dă o grilă de puncte laticiale de dimensiuni $N × N$. Se cere să se determine numărul de pătrate care se pot forma astfel încât vârfurile lor să aparţină punctelor din grilă. De exemplu, pe o grilă de dimensiuni $3 × 3$ există $6$ pătrate.\r\n\r\np=. !probleme-cu-puncte-laticiale?img5.JPG!\r\n\r\nh3. Rezolvare:\r\n\r\nUn pătrat cu $L$ puncte pe o latură, cu laturile paralele cu axele de coordonate, poate fi translatat în $(N - L + 1)*(N - L + 1)$ poziţii diferite pe grilă.\r\n\r\np=. !probleme-cu-puncte-laticiale?img6.JPG 70%!\r\n\r\nConsiderăm pentru un pătrat din mulţimea soluţiilor, dreptunghiul minim cu laturile paralele cu axele de coordonate ce conţine acest pătrat. Este uşor să vedem că acest dreptunghi este de fapt un pătrat. Într-un pătrat ce are $L$ puncte pe latură, înscrie $L - 2$ pătrate care nu au laturile paralele cu axele de coordonate. \r\n\r\np=. !probleme-cu-puncte-laticiale?img7.JPG 70%!\r\n\r\nAstfel, vedem că numărul total de pătrate pe o grilă $N * M$ este, succesiv:\r\n\r\n* <tex> \\displaystyle\\sum_{L=2}^{N} (N-L+1)(N-L+1)(L-1) = </tex>\r\n* <tex> = \\displaystyle\\sum_{L=1}^{N-1} (N-L)(N-L)L </tex>\r\n* <tex> = \\displaystyle\\sum_{L=1}^{N-1} L*N^2 - 2*L^2*N + L^3 </tex>\r\n* <tex> = \\displaystyle N^2 * \\sum_{L=1}^{N-1} L - 2 * N * \\sum_{L=1}^{N-1} L^2 + \\sum_{L=1}^{N-1} L^3 </tex>\r\n* <tex> = \\displaystyle N^2 * \\frac{N(N - 1)}{2} - 2 * N * \\frac{N(N - 1)(2N - 1)}{6} + \\left[\\frac{N(N - 1)}{2}\\right]^2 </tex>\r\n\r\nAm folosit formulele cunoscute din manualul de clasa a 10-a:\r\n\r\n* <tex> \\displaystyle\\sum_{k=1}^{n} k = \\frac{n(n+1)}{2} </tex>\r\n* <tex> \\displaystyle\\sum_{k=1}^{n} k^2 = \\frac{n(n+1)(2n+1)}{6} </tex>\r\n* <tex> \\displaystyle\\sum_{k=1}^{n} k^3 = \\left[\\frac{n(n+1)}{2}\\right]^2 </tex>\r\n\r\nAceastă soluţie are complexitatea $O(1)$, fiind o simplă formulă.\r\n\r\nh2(#problema5). Problema 5: \'Counting triangles\':http://acmicpc-live-archive.uva.es/nuevoportal/data/problem.php?p=3295 (ACM ICPC Asia, Dhaka 2005/2006) \r\n\r\nbq. Triunghiurile sunt poligoane cu trei laturi şi cu aria strict pozitivă. Triunghiurile laticiale sunt triunghiuri ce au vârfurile de coordonate întregi. În această problemă va trebui să găsiţi numărul de triunghiuri laticiale ce se pot găsi pe o grilă de dimensiuni $M * N$ $(1 &le; M, N &le; 1000)$. De exemplu, pe o grilă de dimensiuni $1 * 2$ găsim $18$ triunghiuri laticiale distincte după cum vedem în figură:\r\n\r\np=. !probleme-cu-puncte-laticiale?img14.JPG 70%!\r\n\r\nh3. Rezolvare\r\n\r\nPrima idee de rezolvare ar fi de a lua toate combinaţiile de trei puncte distincte dintre cele $N * M$ puncte şi apoi de a elimina oricare trei puncte coliniare, dar partea a doua pare greu de realizat în mod eficient. Vom număra, asemănător rezolvării de mai sus, numărul de triunghiuri înscrise într-un dreptunghi paralel cu axele de coordonate. Ulterior, acel dreptunghi îl vom putea translata pe grila de puncte laticiale şi astfel vom putea număra toate triunghiurile posibile.\r\n\r\np=. !probleme-cu-puncte-laticiale?img9.JPG 70%!\r\n\r\nOricum ar fi un triunghi situat într-un dreptunghi ce este minimal, cel puţin un vârf al triunghiului trebuie să fie un vârf al dreptunghiului. Se disting astfel două cazuri: primul în care un vârf al triunghiului este şi vârf al dreptunghiului şi celelalte două puncte sunt situate pe cele două laturi ale dreptunghiului ce nu au ca şi capăt primul punct, iar al doilea caz în care cel puţin două vârfuri sunt vârfuri ale dreptunghiului opuse pe diagonală. Dacă dreptunghiul are $H$ puncte pe verticală şi $W$ puncte pe orizontală, atunci în primul caz vom avea $4 * ((H - 1)(W - 1) + H - 1 + W - 1)$ triunghiuri, iar în al doilea caz vom avea $2 * (H * W - X)$ unde $X$ e numărul de puncte de coordonate întregi de pe diagonala dreptunghiului. Cum trebuie să numărăm triunghiurile înscrise în fiecare dreptughi pentru care $1 &le; H &le; N$ şi $1 &le; W &le; M$, obţinem un algoritm de complexitate $O(N*M log N)$, unde $log N$ apare la calcularea lui $X$.\r\n\r\nh2(#problema6). Problema 6: \'Dreptunghiuri\':problema/dreptunghiuri (preOni, 2006, runda 1)\r\n\r\nbq. Se dă o grilă de puncte laticiale de dimensiuni $N * M (0 &lt; N, M &le; 400)$. Să se determine numărul dreptunghiurilor cu vârfurile în punctele laticiale. De exemplu, pentru o grilă de $3 * 3$ puncte găsim $10$ dreptunghiuri.\r\n\r\np=. !probleme-cu-puncte-laticiale?img10.JPG 70%!\r\n\r\nh3. Rezolvare\r\n\r\nUn dreptunghi care apare în grila de puncte laticiale e mărginit de două drepte verticale la stânga şi la dreapta, şi de două drepte orizontale în sus şi în jos. Acum, dacă vrem pentru patru drepte fixate să ştim câte dreptunghiuri mărginesc ele, ne putem uita la următorul desen.\r\n\r\np=. !preoni-2006/runda-1/solutii?drept.jpg 70%!\r\n\r\nDacă dreptunghiul determinat de cele patru drepte are laturile $H$ şi $W$, atunci un dreptunghi înscris va împărţi laturile lui în bucăţile {$A$}, $B$ şi {$C$}, {$D$}. Acum, folosind teorema lui Pitagora avem că:\r\n\r\n* $A^2^ + D^2^ = Galben^2^$\r\n* $B^2^ + C^2^ = Verde^2^$\r\n* $Galben^2^ + Verde^2^ = Roz^2^$\r\n* $(A + B)^2^ = Roşu^2^$\r\n* $(C $-$ D)^2^ = Albastru^2^$\r\n* $Roşu^2^ + Albastru^2^ = Roz^2^$\r\n\r\nDe aici avem că {$(A + B)^2^ + (C - D)^2^ = A^2^ + B^2^ + C^2^ + D^2^$}. Astfel, obţinem {$AB = CD$}, dar {$B = H - A$}, iar {$D = W - C$}, deci, avem că {$C^2^ - WC + A(H - A) = 0$}. Dacă îl fixăm pe $A$ atunci trebuie sa rezolvăm o ecuaţie de gradul doi în necunoscută {$C$}, iar soluţia trebuie să fie întreagă între $0$ şi {$W$}.\r\n\r\nAstfel, în $O(H)$ vom şti numărul de dreptunghiuri înscrise într-un dreptunghi de dimensiuni {$H * W$}. Acest dreptunghi poate fi pus în $(N - H + 1) * (M - W + 1)$ locaţii pe o grilă de dimensiune {$N * M$}. Deci, soluţia are complexitate {$O(N*M^2^)$}, pentru fiecare dreptunghi de dimensiuni $1 &le; H &le; N$ şi $1 &le; W &le; M$ calculându-se numărul de dreptunghiuri înscrise.\r\n\r\nO rezolvare de complexitate $O(N^2^*M^2^)$ în care se căutau soluţiile ecuaţiei printr-un for ar fi luat $60$ de puncte. Rezolvarea directa folosind ecuaţia de gradul doi ia în jur de $80$ de puncte. Algoritmul poate fi optimizat la factorii constanţi. De exemplu, avem nevoie de funcţia radical care este înceată, pe care, precalculând-o, obţinem o accelerare a vitezei. Altă idee este că numarul de soluţii cu $A &le; H/2$ este egal cu numărul de soluţii cu $A &ge; H - H/2$, iar a treia idee de optimizare este că numarul de dreptunghiuri înscrise într-un dreptunghi de dimensiuni {$H$}, $W$ este acelaşi cu numărul de dreptunghiuri înscrise într-un dreptunghi de dimensiuni {$W$}, {$H$}.\r\n\r\nh2(#problema7). Problema 7: \'Paralelograme\':problema/paralelograme (Bursele Agora, 2005/2006, runda 1)\r\n\r\nbq. Se dă o grilă laticială cu $N$ linii şi $M$ coloane, unde $0 &lt; N, M &le; 2000$. Să cere determinarea numărului paralelogramelor cu vârfurile aflate la coordonate numere întregi. De exemplu, pentru $N = 2$ şi $M = 2$ putem construi $22$ de paralelograme.\r\n\r\np=. !probleme-cu-puncte-laticiale?img12.JPG!\r\n\r\nh3. Rezolvare\r\n\r\nCa să determinăm numărul de paralelograme ce se pot găsi pe o grilă laticială, proprietatea că diagonalele unui paralelogram se înjumătăţesc pare să ne ajute în obţinerea unui algoritm de complexitate $O(N + M)$. Însă, autorul nu a reuşit să numere într-un mod eficient câte paralelograme sunt degenerate (cu cele patru vârfuri coliniare) pentru a putea să le eliminăm din numărul total.\r\n\r\nDin nou, putem folosi ideea celui mai mic dreptunghi cu laturile paralele cu axele de coordonate pentru a număra repede o clasă mare de paralelograme de aceiaşi formă. Avem două cazuri posibile:\r\n\r\np=. !probleme-cu-puncte-laticiale?img13.JPG 70%!\r\n\r\nPrimul în care cele patru puncte sunt pe laturile dreptunghiului iar nici un vârf nu coincide cu vârfurile dreptunghiului, şi al doilea în care există două puncte în vârfuri opuse ale dreptunghiului. În primul caz, dacă avem poziţiile a două vârfuri fixate pe două laturi consecutive ale dreptunghiului, atunci poziţiile celorlalte două vârfuri sunt unic determinate. De aici obţinem că în primul caz avem $(h - 2) * (w - 2)$ paralelograme. În al doilea caz, dacă fixăm două vârfuri ale paralelogramului în colţurile dreptunghiului, celelalte două vârfuri vor fi simetrice faţă de centrul de greutate al dreptunghiului. Cum nu trebuie să luăm în calcul posibilitatea ca vârfurile să fie pe diagonala dreptunghiului, obţinem $h * w - cmmdc(h - 1, w - 1) - 2$ posibilităţi.\r\n\r\nAstfel, am ajuns la următorul algoritm:\r\n\r\n==code(c) |\r\nlong num = 0;\r\nfor (long h = 2; h <= N + 1; h++) {\r\n    for (long w = 2; w <= M + 1; w++) {\r\n        laux = (h - 2) * (w - 2) + h * w - cmmdc(h - 1, w - 1) - 2;\r\n        num += (N - h + 1) * (M - w + 1) * laux;\r\n    }\r\n}\r\n==\r\n\r\nAcest algoritm are complexitatea $O(N*M log N)$ şi nu s-ar fi încadrat în timpul impus, deoarece marea parte a calculelor este efectuată în determinarea celui mai mare divizor comun a două numere. Având în vedere că numerele folosite sunt între $1$ şi $N$ respectiv între $1$ şi $M$, putem să precalculăm o matrice $CMMDC[X][Y]$, $1 &le; X &le; N$ şi $1 &le; Y &le; M$, în $O(N * M)$. Astfel, complexitatea soluţiei a fost redusă la $O(N * M)$. Mai putem optimiza factorii constanţi ai soluţiei observând că într-un dreptunghi de dimensiuni $H * W$ poate fi înscris acelaşi număr de dreptunghiuri ca şi într-un dreptunghi $W * H$. Acest artificiu aproape dublează viteza algoritmului. Menţionăm că aceleaşi optimizări pot fi făcute şi la problema cu triunghiuri.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nCititorul poate să încerce aplicarea tehnicilor din articol la alte probleme similare precum determinarea numărului de patrulatere convexe nedegenerate cu vârfurile puncte laticiale, sau numărului de romburi sau trapeze.\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Buşneag, Maftei, _„Teme pentru cercurile şi concursurile de matematică ale elevilor”_, Scrisul Românesc, Craiova, 1983\r\n# Iaglom, Iaglom, _„Probleme neelementare tratate elementar”_, Editura Tehnică, Bucureşti, 1962\r\n# \'WolframMathWorld\':http://mathworld.wolfram.com\r\n# \'FAQs\':http://www.faqs.org/faqs/graphics/algorithms-faq/\r\n# \'Geometry Algorithms\':http://geometryalgorithms.com/Archive/algorithm_0101/',4827,'public',3853,NULL),('runda/matrice/clasament','Clasament matrice','2009-04-13 07:44:18','2009-04-13 07:44:18','h1. Clasament ==roundparam(round_id=\"matrice\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"matrice\")==',9356,'round: matrice',NULL,NULL),('runda/23','23','2009-04-13 15:20:22','2009-04-13 15:20:22','h1. == roundparam(round_id=\"23\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"23\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"23\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"23\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/23/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"23\" score=\"1\")==',9312,'round: 23',NULL,NULL),('runda/23/clasament','Clasament 23','2009-04-13 15:20:22','2009-04-13 15:20:22','h1. Clasament ==roundparam(round_id=\"23\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"23\")==',9312,'round: 23',NULL,NULL),('runda/1234','1234','2009-04-13 21:17:29','2009-04-13 21:17:29','h1. == roundparam(round_id=\"1234\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"1234\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"1234\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"1234\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/1234/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"1234\" score=\"1\")==',7797,'round: 1234',NULL,NULL),('runda/1234/clasament','Clasament 1234','2009-04-13 21:17:29','2009-04-13 21:17:29','h1. Clasament ==roundparam(round_id=\"1234\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"1234\")==',7797,'round: 1234',NULL,NULL),('runda/cnrv_oji_2','cnrv_oji_2','2010-02-06 11:44:08','2010-02-06 11:44:08','h1. == roundparam(round_id=\"cnrv_oji_2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cnrv_oji_2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cnrv_oji_2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cnrv_oji_2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"cnrv_oji_2\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cnrv_oji_2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cnrv_oji_2\" score=\"1\")==',5748,'round: cnrv_oji_2',NULL,NULL),('runda/splunge2','splunge2','2009-07-15 06:02:07','2009-07-15 06:02:07','h1. == roundparam(round_id=\"splunge2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"splunge2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"splunge2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"splunge2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/splunge2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"splunge2\" score=\"1\")==',4439,'round: splunge2',NULL,NULL),('runda/algorithmic_contest.1','algorithmic_contest.1','2009-04-15 19:04:16','2009-04-15 19:11:52','h1. == roundparam(round_id=\"algorithmic_contest.1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"algorithmic_contest.1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algorithmic_contest.1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algorithmic_contest.1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nConcursul consta in 3 problema de natura algoritmica relativ usoare, dar care va pune participantul in mici dificultati. Participa si Tu!\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/algorithmic_contest.1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"algorithmic_contest.1\" score=\"1\")==',9232,'round: algorithmic_contest.1',NULL,NULL),('runda/algorithmic_contest.1/clasament','Clasament algorithmic_contest.1','2009-04-15 19:04:16','2009-04-15 19:04:16','h1. Clasament ==roundparam(round_id=\"algorithmic_contest.1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"algorithmic_contest.1\")==',9232,'round: algorithmic_contest.1',NULL,NULL),('runda/problemiada_2','problemiada_2','2009-04-15 20:34:23','2009-04-15 20:34:23','h1. == roundparam(round_id=\"problemiada_2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"problemiada_2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"problemiada_2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"problemiada_2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/problemiada_2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"problemiada_2\" score=\"1\")==',5748,'round: problemiada_2',NULL,NULL),('runda/problemiada_2/clasament','Clasament problemiada_2','2009-04-15 20:34:23','2009-04-15 20:34:23','h1. Clasament ==roundparam(round_id=\"problemiada_2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"problemiada_2\")==',5748,'round: problemiada_2',NULL,NULL),('runda/problemiada_3','Problemiada - Editia 3','2009-04-16 12:08:18','2009-04-17 07:07:19','h1. == roundparam(round_id=\"problemiada_3\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"problemiada_3\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"problemiada_3\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"problemiada_3\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/problemiada_3/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"problemiada_3\" score=\"1\")==',5748,'round: problemiada_3',NULL,NULL),('runda/problemiada_3/clasament','Clasament problemiada_3','2009-04-16 12:08:18','2009-04-16 12:08:18','h1. Clasament ==roundparam(round_id=\"problemiada_3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"problemiada_3\")==',5748,'round: problemiada_3',NULL,NULL),('utilizator/cosser','Profil','2007-12-10 17:02:46','2010-01-17 19:22:25','\r\n',7333,'public',NULL,NULL),('runda/back_in','back_in','2009-10-03 17:26:54','2009-10-03 17:26:54','h1. == roundparam(round_id=\"back_in\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"back_in\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"back_in\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"back_in\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/back_in/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"back_in\" score=\"1\")==',9356,'round: back_in',NULL,NULL),('runda/horax_round_1','horax_round_1','2009-07-16 09:47:41','2009-07-16 09:47:41','h1. == roundparam(round_id=\"horax_round_1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"horax_round_1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"horax_round_1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"horax_round_1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/horax_round_1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"horax_round_1\" score=\"1\")==',445,'round: horax_round_1',NULL,NULL),('runda/loool','loool','2009-04-06 08:34:26','2009-04-06 08:34:26','h1. == roundparam(round_id=\"loool\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"loool\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"loool\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"loool\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/loool/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"loool\" score=\"1\")==',9995,'round: loool',NULL,NULL),('runda/qwerty-5','qwerty-5','2009-03-30 14:53:30','2009-03-30 14:53:30','h1. == roundparam(round_id=\"qwerty-5\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"qwerty-5\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"qwerty-5\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"qwerty-5\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/qwerty-5/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"qwerty-5\" score=\"1\")==',4439,'round: qwerty-5',NULL,NULL),('utilizator/v_vero_93','Profil v_vero_93','2009-03-11 08:58:13','2009-03-11 08:58:13','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',9830,'public',NULL,NULL),('utilizator/gmf92','Profil GMF92','2009-03-15 16:42:32','2009-03-15 16:42:32','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',9891,'public',NULL,NULL),('runda/infostar','infostar','2009-03-21 13:15:49','2009-03-21 13:15:49','h1. == roundparam(round_id=\"infostar\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"infostar\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"infostar\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"infostar\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/infostar/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"infostar\" score=\"1\")==',9795,'round: infostar',NULL,NULL),('documentatie/concursuri-virtuale','Concursuri virtuale','2009-03-17 19:08:11','2009-03-20 22:27:58','h1. Documentaţie pentru concursurile virtuale\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nConcursurile virtuale sunt create de catre utilizatori cu probleme din arhiva, avand ca scop propria pregatire si testare in regim de concurs. Pagina destinata concursurilor virtuale se afla \'aici\':concursuri-virtuale. Odata ajunsi aici aveti doua optiuni: participarea la un concurs virtual sau crearea unuia.\r\n\r\nh2. Participare\r\n\r\nPentru a participa la un concurs virtual selectati din lista un concurs la care vreti sa participati. Aici puteti vedea numele concursului, autorul, starea (in desfasurare, incheiat sau inca neinceput) si data la care acesta va avea sau a avut loc. Participarea se face ca la orice concurs normal. **Atentie**: cand trimiteti o sursa trebuie sa selectati concursul la care vreti sa fie trimisa aceasta sursa.\r\n\r\nh2. Creare\r\n\r\nPentru crearea unui concurs nou exista un buton **Creaza concurs nou**. Dupa ce apasati pe acest buton veti fi directionati catre \'aceasta\':admin/runda-noua pagina. Aici selectati numele concursului. Tipul acestuia va fi setat automat (administratorii au mai multe optiuni pentru tipul unui concurs si de aceea a ramas aceasta casuta). Dupa aceasta apasati butonul **Creaza runda**. Veti fi directionati catre o pagina cu mai multe campuri:\r\n\r\n* **Titlul**: sub acest nume va aparea in lista de concursuri virtuale.\r\n* **Pagina de prezentare**: aceasta este pagina la care este trimis utilizatorul cand da click pe numele rundei in monitor sau in pagina de concursuri virtuale. De obicei nu este nevoie sa o modificati.\r\n* **Timpul de start**: timpul cand va incepe concursul scris in formatul specificat.\r\n* **Lista de probleme**: aici puteti alege problemele. Selectati probleme dintr-o anumita parte si mutati-le in cealalta cu sagetile > si < (>> sau << muta toate problemele). In stanga se afla problemele din arhiva si in dreapta problemele care vor fi in concurs.\r\n* **Tipul rundei** : concurs virtual.\r\n* **Evaluare publica**: alegeti daca rezultate se vor afisa in timpul sau dupa concurs.\r\n* **Durata**: durata concursului specificata in ore.\r\n\r\nDupa ce setati toti parametrii necesari, apasati butonul **Salveaza**. Pentru a modifica ulterior parametrii de mai sus trebuie sa accesati pagina manual (din pacate nu exista inca un buton de editat pentru runda; o sa incercam sa punem cat de curand). Pentru o runda cu numele **test** pagina rundei va fi **http://infoarena.ro/runda/test** iar pagina pentru editarea parametrilor va fi **http://infoarena.ro/{+admin+}/runda/test**. La aceasta pagina are acces doar cel ce a creat concursul.',1,'public',NULL,NULL),('planificare/sedinta-20090316','Sedinta 2009-03-16','2009-02-23 16:00:45','2009-03-20 22:12:25','h1. Sedinta 2009-03-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Martie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== (posibil sa intarzii vreo jumatate de ora)\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== (daca o sa mai fiti, eu o sa ajung dupa 20:00, am facultate)\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== (si eu o sa ajung un pic mai tarziu, am facultate)\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090216| ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Concursul Centrelor de Excelenta/Concurs in engleza | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Recapitulare OKRs: suntem în grafic?| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n\r\n\r\nh2. Detalii\r\n\r\nh3. Misc\r\n\r\n* Diacritice\r\n* Donare calculatoare\r\n* Algoritmiada 2009\r\n** Sponsori - Adobe, Microsoft\r\n** Data si locatia finalei\r\n** Invitatii concurenti\r\n** Materiale promotionale (tricouri)\r\n** Organizare tehnica\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Silviu si Cristi concretizeaza IAP 7 (1 sedinta)\r\n* Mircea dă mail la Microsoft. Cristi oferă template.\r\n* Alexandra se ocupă de invitaţii, confirmări şi sosiri\r\n* Cosmin vorbeşte cu Malex să afle ce tool foloseşte pentru detectarea surselor identice şi în foloseşte.\r\n* Singura opţiune pentru finala Algoritmiada: 3-5 aprilie.\r\n* Wefgef face plan concret şi complet de acţiune pentru finală (pagină wiki)\r\n* Wefgef se ocupă de design de tricou (grafică vectorială!)\r\n* Vali şi Bogdan se ocupă pe partea tehnică la finala Algoritmiada\r\n* Vali se ocupă de diplome (design şi printare)\r\n* Buru porneşte un thread pe grup despre detaliile tehnice pentru recalculat timpii %{color:red}(done)%\r\n* Wefgef face listă cu ce trebuie instalat la Algoritmiada\r\n* Toata lumea citeşte IAP 12\r\n* Vali bagă backup (înpreună cu Cristi, Bogdan, Silviu)\r\n* Victor testează pe local funcţionalitatea de Virtual Contests până marţi seara şi dă un mail. %{color:red}(done)%\r\n* Cosmin scrie documentaţie pentru Virtual Contests până marţi seara. %{color:red}(done)%\r\n* Prostu face blog post pentru Virtual Contensts până marţi seara. %{color:red}(done)%\r\n* Mircea, Cristi şi Bogdan bagă review la change-ul lui Devilkind până vineri seara.\r\n* Mircea face review la script pentru topic-uri de pe forum la probleme.\r\n* Victor îi arată lui Prostu cum se foloseşte format_table. Prostu bagă la review săptămâna asta.\r\n* Victor bagă la review interfaţa de updatat rating. %{color:red}(done)%\r\n* Cristi îi contactează pe Paul, Airinei legat de OKR-uri.\r\n* Cristi bagă medie intermediară la OKR-uri.\r\n* Standard de diacritice: stil consistent per pagină. Dacă o pagină este scrisă deja cu diacritice, toate modificările se fac cu diacritice. Dacă o pagină nu are diacritice aceasta poate fi convertită la diacritice, dar numai în întregime.\r\n* Wefgef face poll pentru schimbarea zilei de şedinţă.\r\n* Prostu aduce merinde la următoarea şedinţă.\r\n* Wefgef conduce următoarea şedinţă.\r\n\r\nh2. Notiţe\r\n\r\n* Raportăm IAP pentru Vali.\r\n* Fără ketchup; e cancerigen.\r\n* La finala Algoritmiada se vine de joi.\r\n* Blog post pentru Coding Camp \"A New Day\"\r\n',1,'protected',NULL,NULL),('blog/concursuri-virtuale','Concursuri Virtuale','2009-03-17 20:58:23','2009-03-20 22:26:39','Infoarena lansează o nouă facilitate: \'Concursuri Virtuale\':concursuri-virtuale!\r\n\r\nS-a tot vorbit despre o modalitate prin care utilizatorii să ţină propriile lor concursuri folosind problemele din arhivele infoarena. Ideile s-au concretizat în \'IAP 10\':propuneri/10-virtual-contest. Acesta a fost votat în şedinţa de pe 12 ianuarie şi a fost implementat în mare parte în \'Coding-Campul\':planificare/camp-2.2.1 de pe 28 februarie. În sfârşit un vis mai vechi s-a transformat în realitate!\r\nCu această ocazie îi lăudăm pe ==user(user=\"bogdan2412\")== şi pe ==user(user=\"domino\")== pentru munca depusă în dezvoltarea acestei noi secţiuni a site-ului. Good job, guys!\r\n\r\nAceastă nouă facilitate permite participantilor să îşi testeze capacităţile în concursuri de orice nivel şi la orice moment din zi şi mai ales, din noapte. De exemplu, se apropie Olimpiada Naţională de Informatică, suntem clasa a 10-a, si vrem să simulam o zi de concurs. Nimic mai simplu, putem folosi chiar problemele care s-au dat in anii trecuţi (dacă nu le-am rezolvat deja), creăm un concurs virtual cu problemele dorite: \'Banda\':problema/banda, \'Pavare3\':problema/pavare3 şi \'Poarta\':problema/poarta, stabilim durata de concurs de 4 ore şi momentul începerii rundei, să zicem a doua zi la ora 10 şi am cam terminat.\r\nPe pagina concursurilor virtuale putem vedea ce concursuri au fost programate şi să selectam concursul la care să participam. Pe pagina rundei vom vedea problemele dupa începerea concursului. În momentul primei submisii vom fi atentionaţi să selectăm concursul la care vrem să trimitem solutia. Acesta va fi reţinut şi selectat automat pentru celelalte probleme care fac parte din concurs. O dată trimisă soluţia, ea va fi evaluată, dar scorul ei nu va fi afişat decât dacă am selectat această opţiune în momentul creării concursului. \r\n\r\nDe asemeni, membrii mai zeloşi din comunitate pot să-şi măsoare între ei forţele când au chef, pornind un concurs virtual. Eu sper sa văd în viitor concursuri în care vreo 3-4 membri se întrec timp de vreo 12 ore încercând să rezolve vreo 5 probleme de-ale lui Mugurel Ionuţ Andreica, alese aleator dintre cele pe care nici unul din participanţi le avea rezolvate.\r\n\r\nSperăm să ne împărtăşiţi entuziasmul legat de această nouă funcţionalitate! Aşteptăm feedback şi vă urăm _happy coding_!',1,'public',3780,NULL),('runda/cx21.03.2009/clasament','Clasament cx21.03.2009','2009-03-20 22:47:52','2009-03-20 22:47:52','h1. Clasament ==roundparam(round_id=\"cx21.03.2009\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"cx21.03.2009\")==',6191,'round: cx21.03.2009',NULL,NULL),('runda/concurs_de_test','concurs_de_test','2009-03-20 22:51:30','2009-03-20 22:51:30','h1. == roundparam(round_id=\"concurs_de_test\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"concurs_de_test\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"concurs_de_test\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"concurs_de_test\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/concurs_de_test/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"concurs_de_test\" score=\"1\")==',58,'round: concurs_de_test',NULL,NULL),('runda/concurs_de_test/clasament','Clasament concurs_de_test','2009-03-20 22:51:30','2009-03-20 22:51:30','h1. Clasament ==roundparam(round_id=\"concurs_de_test\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"concurs_de_test\")==',58,'round: concurs_de_test',NULL,NULL),('runda/01/clasament','Clasament 01','2009-03-20 23:07:31','2009-03-20 23:07:31','h1. Clasament ==roundparam(round_id=\"01\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"01\")==',8420,'round: 01',NULL,NULL),('runda/01','InfoTech','2009-03-20 23:07:31','2009-03-21 13:47:04','h1. == roundparam(round_id=\"01\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"01\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"01\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"01\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/01/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"01\" score=\"1\")==',8420,'round: 01',NULL,NULL),('runda/pentru-cei-mici','pentru-cei-mici','2009-03-21 06:10:07','2009-03-21 15:07:36','h1. == roundparam(round_id=\"pentru-cei-mici\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"pentru-cei-mici\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"pentru-cei-mici\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"pentru-cei-mici\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/pentru-cei-mici/clasament.\r\n\r\n\r\nh2. Probleme\r\nSunt 3 probleme usoare.\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"pentru-cei-mici\" score=\"1\")==',7668,'round: pentru-cei-mici',NULL,NULL),('runda/pentru-cei-mici/clasament','Clasament pentru-cei-mici','2009-03-21 06:10:07','2009-03-21 06:10:07','h1. Clasament ==roundparam(round_id=\"pentru-cei-mici\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pentru-cei-mici\")==',7668,'round: pentru-cei-mici',NULL,NULL),('runda/s','s','2009-03-21 06:18:54','2009-03-21 06:18:54','h1. == roundparam(round_id=\"s\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"s\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"s\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"s\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/s/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"s\" score=\"1\")==',7668,'round: s',NULL,NULL),('runda/s/clasament','Clasament s','2009-03-21 06:18:54','2009-03-21 06:18:54','h1. Clasament ==roundparam(round_id=\"s\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"s\")==',7668,'round: s',NULL,NULL),('runda/papiu_contest','papiu_contest','2009-03-21 07:17:22','2009-03-21 07:17:22','h1. == roundparam(round_id=\"papiu_contest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"papiu_contest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"papiu_contest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"papiu_contest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/papiu_contest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"papiu_contest\" score=\"1\")==',445,'round: papiu_contest',NULL,NULL),('runda/papiu_contest/clasament','Clasament papiu_contest','2009-03-21 07:17:22','2009-03-21 07:17:22','h1. Clasament ==roundparam(round_id=\"papiu_contest\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"papiu_contest\")==',445,'round: papiu_contest',NULL,NULL),('runda/ab2','ab2','2009-03-21 07:59:17','2009-03-21 07:59:17','h1. == roundparam(round_id=\"ab2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"ab2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"ab2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ab2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/ab2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"ab2\" score=\"1\")==',8967,'round: ab2',NULL,NULL),('runda/ab2/clasament','Clasament ab2','2009-03-21 07:59:17','2009-03-21 07:59:17','h1. Clasament ==roundparam(round_id=\"ab2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"ab2\")==',8967,'round: ab2',NULL,NULL),('runda/contest/clasament','Clasament contest','2009-03-21 08:23:15','2009-03-21 08:23:15','h1. Clasament ==roundparam(round_id=\"contest\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"contest\")==',8857,'round: contest',NULL,NULL),('runda/concurs_test','concurs_test','2009-03-21 08:37:27','2009-03-21 08:37:27','h1. == roundparam(round_id=\"concurs_test\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"concurs_test\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"concurs_test\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"concurs_test\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/concurs_test/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"concurs_test\" score=\"1\")==',6191,'round: concurs_test',NULL,NULL),('runda/concurs_test/clasament','Clasament concurs_test','2009-03-21 08:37:27','2009-03-21 08:37:27','h1. Clasament ==roundparam(round_id=\"concurs_test\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"concurs_test\")==',6191,'round: concurs_test',NULL,NULL),('runda/easy','easy','2009-03-21 08:38:19','2009-03-21 08:38:19','h1. == roundparam(round_id=\"easy\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"easy\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"easy\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"easy\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/easy/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"easy\" score=\"1\")==',8857,'round: easy',NULL,NULL),('runda/easy/clasament','Clasament easy','2009-03-21 08:38:19','2009-03-21 08:38:19','h1. Clasament ==roundparam(round_id=\"easy\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"easy\")==',8857,'round: easy',NULL,NULL),('runda/cupadetest','cupadetest','2009-03-21 08:56:53','2009-03-21 08:56:53','h1. == roundparam(round_id=\"cupadetest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cupadetest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cupadetest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cupadetest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cupadetest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cupadetest\" score=\"1\")==',4509,'round: cupadetest',NULL,NULL),('runda/cupadetest/clasament','Clasament cupadetest','2009-03-21 08:56:53','2009-03-21 08:56:53','h1. Clasament ==roundparam(round_id=\"cupadetest\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"cupadetest\")==',4509,'round: cupadetest',NULL,NULL),('runda/testhorax','testhorax','2009-03-21 10:12:29','2009-03-21 10:12:29','h1. == roundparam(round_id=\"testhorax\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"testhorax\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"testhorax\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"testhorax\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/testhorax/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"testhorax\" score=\"1\")==',445,'round: testhorax',NULL,NULL),('runda/testhorax/clasament','Clasament testhorax','2009-03-21 10:12:29','2009-03-21 10:12:29','h1. Clasament ==roundparam(round_id=\"testhorax\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"testhorax\")==',445,'round: testhorax',NULL,NULL),('runda/lol','lol','2009-03-21 10:19:10','2009-03-21 10:19:10','h1. == roundparam(round_id=\"lol\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"lol\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"lol\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"lol\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/lol/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"lol\" score=\"1\")==',9782,'round: lol',NULL,NULL),('runda/lol/clasament','Clasament lol','2009-03-21 10:19:10','2009-03-21 10:19:10','h1. Clasament ==roundparam(round_id=\"lol\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"lol\")==',9782,'round: lol',NULL,NULL),('runda/inceput','inceput','2009-03-21 10:54:45','2009-03-24 10:12:36','h1. == roundparam(round_id=\"inceput\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"inceput\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"inceput\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"inceput\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/inceput/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"inceput\" score=\"1\")==',9757,'round: inceput',NULL,NULL),('runda/pcm','runda/pcm','2009-03-21 10:56:56','2009-03-21 10:56:56','Aceasta este prima runa. De acum pana la nationala vor fi probleme care sa pregateasca copii pentru gimnaziu.',7668,'public',NULL,NULL),('runda/gsp','gsp','2009-03-21 11:03:39','2009-03-21 11:22:00','Sincer as vrea sa il sterg :)\r\n',6333,'round: gsp',NULL,NULL),('runda/concurs_nou','concurs_nou','2009-03-21 11:20:53','2009-03-21 11:20:53','h1. == roundparam(round_id=\"concurs_nou\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"concurs_nou\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"concurs_nou\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"concurs_nou\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/concurs_nou/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"concurs_nou\" score=\"1\")==',6341,'round: concurs_nou',NULL,NULL),('runda/gsp/clasament','Clasament gsp','2009-03-21 11:03:39','2009-03-21 11:03:39','h1. Clasament ==roundparam(round_id=\"gsp\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"gsp\")==',6333,'round: gsp',NULL,NULL),('runda/concurs_nou/clasament','Clasament concurs_nou','2009-03-21 11:20:53','2009-03-21 11:20:53','h1. Clasament ==roundparam(round_id=\"concurs_nou\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"concurs_nou\")==',6341,'round: concurs_nou',NULL,NULL),('runda/a','a','2009-03-21 11:21:47','2009-03-21 11:59:42','h1. == roundparam(round_id=\"a\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"a\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"a\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"a\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/a/clasament.\r\n\r\nh2. Probleme\r\n\r\n\r\n\'flip\':http://infoarena.ro/problema/flip/.\r\nProbleme\r\n\'Flip\':http://infoarena.ro/problema/hd/.\r\n\r\n==Tasks(round_id=\"a\" score=\"1\")==',7668,'round: a',NULL,NULL),('runda/a/clasament','Clasament a','2009-03-21 11:21:47','2009-03-21 11:21:47','h1. Clasament ==roundparam(round_id=\"a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"a\")==',7668,'round: a',NULL,NULL),('runda/drastik_challange_1/clasament','Clasament drastik_challange_1','2009-03-21 11:54:05','2009-03-21 11:54:05','h1. Clasament ==roundparam(round_id=\"drastik_challange_1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"drastik_challange_1\")==',6957,'round: drastik_challange_1',NULL,NULL),('runda/infotest','infotest','2009-03-21 11:56:34','2009-03-21 11:56:34','h1. == roundparam(round_id=\"infotest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"infotest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"infotest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"infotest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/infotest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"infotest\" score=\"1\")==',9249,'round: infotest',NULL,NULL),('runda/infotest/clasament','Clasament infotest','2009-03-21 11:56:34','2009-03-21 11:56:34','h1. Clasament ==roundparam(round_id=\"infotest\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"infotest\")==',9249,'round: infotest',NULL,NULL),('runda/drastik_challange_1','drastik_challange_1','2009-03-21 11:54:05','2009-03-22 12:19:33','h1. == roundparam(round_id=\"drastik_challange_1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"drastik_challange_1\") ==\r\n\r\nConcursul se adreseaza oricarei grupe de varsta, mai ales celor de clasa a X-a. Va invit pe toti sa participati. Cei mai buni sa castige.\r\n\r\nPentru cei din Targu Mures:\r\nLocul I - doua sucuri\r\nLocul II - un suc\r\n\r\nConcursul incepe ==roundparam(round_id=\"drastik_challange_1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"drastik_challange_1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/drastik_challange_1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"drastik_challange_1\" score=\"1\")==',6957,'round: drastik_challange_1',NULL,NULL),('admin/infotest','admin/infotest','2009-03-21 12:05:01','2009-03-21 12:05:23','Am creat acest  concurs pentru o ultima pregatire pentru ONI.\r\n\r\nbq. Nu-ti fie teama ca inaintezi prea incet. Teme-te daca te opresti. Sun Tzu ',9249,'public',NULL,NULL),('runda/infostar/clasament','Clasament infostar','2009-03-21 13:15:49','2009-03-21 13:15:49','h1. Clasament ==roundparam(round_id=\"infostar\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"infostar\")==',9795,'round: infostar',NULL,NULL),('runda/final-selection','final-selection','2009-03-21 13:55:38','2009-03-21 13:55:38','h1. == roundparam(round_id=\"final-selection\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"final-selection\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"final-selection\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"final-selection\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/final-selection/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"final-selection\" score=\"1\")==',7700,'round: final-selection',NULL,NULL),('runda/final-selection/clasament','Clasament final-selection','2009-03-21 13:55:38','2009-03-21 13:55:38','h1. Clasament ==roundparam(round_id=\"final-selection\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"final-selection\")==',7700,'round: final-selection',NULL,NULL),('runda/cnmnarad','cnmnarad','2009-03-21 14:06:11','2009-03-22 12:05:43','h1. == roundparam(round_id=\"cnmnarad\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cnmnarad\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cnmnarad\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cnmnarad\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cnmnarad/clasament.\r\n\r\nh2. Probleme\r\n\r\n* Sunt 3 probleme medii, undeva cam la nivelul OJI clasa a X-a. Concursul este special facut pentru olimpicii de la Colegiul National \"Moise Nicoara\" Arad dar oricine e bine venit.\r\n\r\n* Cand trimiteti surse pentru acest concurs, in pagina problemei respective selectati la \"Concurs\" \"CNMN Arad Week 1\". Aceasta optiune va fi disponibila duminica 22 martie 2009 intre orele 14 si 17. \r\n\r\n* Daca trisati nu aveti nimic de castigat. Dar daca nu trisati aveti multe de invatat.\r\n\r\n* Succes!\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cnmnarad\" score=\"1\")==',9156,'round: cnmnarad',NULL,NULL),('runda/cnmnarad/clasament','Clasament cnmnarad','2009-03-21 14:06:11','2009-03-21 14:06:11','h1. Clasament ==roundparam(round_id=\"cnmnarad\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"cnmnarad\")==',9156,'round: cnmnarad',NULL,NULL),('runda/test123','test123','2009-03-21 14:33:23','2009-03-21 14:33:23','h1. == roundparam(round_id=\"test123\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"test123\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"test123\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"test123\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/test123/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"test123\" score=\"1\")==',4439,'round: test123',NULL,NULL),('runda/test123/clasament','Clasament test123','2009-03-21 14:33:23','2009-03-21 14:33:23','h1. Clasament ==roundparam(round_id=\"test123\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"test123\")==',4439,'round: test123',NULL,NULL),('runda/pcm2','pcm2','2009-03-21 15:02:40','2009-03-21 15:02:40','h1. == roundparam(round_id=\"pcm2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"pcm2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"pcm2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"pcm2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/pcm2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"pcm2\" score=\"1\")==',7668,'round: pcm2',NULL,NULL),('runda/pcm2/clasament','Clasament pcm2','2009-03-21 15:02:40','2009-03-21 15:02:40','h1. Clasament ==roundparam(round_id=\"pcm2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pcm2\")==',7668,'round: pcm2',NULL,NULL),('runda/ardeiumplut','ardeiumplut','2009-03-21 15:48:50','2009-03-21 15:48:50','h1. == roundparam(round_id=\"ardeiumplut\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"ardeiumplut\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"ardeiumplut\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ardeiumplut\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/ardeiumplut/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"ardeiumplut\" score=\"1\")==',9156,'round: ardeiumplut',NULL,NULL),('runda/ardeiumplut/clasament','Clasament ardeiumplut','2009-03-21 15:48:50','2009-03-21 15:48:50','h1. Clasament ==roundparam(round_id=\"ardeiumplut\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"ardeiumplut\")==',9156,'round: ardeiumplut',NULL,NULL),('runda/incercare','incercare','2009-03-21 15:59:03','2009-03-21 15:59:03','h1. == roundparam(round_id=\"incercare\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"incercare\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"incercare\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"incercare\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/incercare/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"incercare\" score=\"1\")==',878,'round: incercare',NULL,NULL),('runda/incercare/clasament','Clasament incercare','2009-03-21 15:59:03','2009-03-21 15:59:03','h1. Clasament ==roundparam(round_id=\"incercare\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"incercare\")==',878,'round: incercare',NULL,NULL),('runda/petru_toti','petru_toti','2009-03-21 16:17:50','2009-03-21 16:17:50','h1. == roundparam(round_id=\"petru_toti\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"petru_toti\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"petru_toti\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"petru_toti\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/petru_toti/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"petru_toti\" score=\"1\")==',9436,'round: petru_toti',NULL,NULL),('runda/petru_toti/clasament','Clasament petru_toti','2009-03-21 16:17:50','2009-03-21 16:17:50','h1. Clasament ==roundparam(round_id=\"petru_toti\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"petru_toti\")==',9436,'round: petru_toti',NULL,NULL),('runda/a_short_round','a_short_round','2009-03-21 16:23:12','2009-03-21 16:23:12','h1. == roundparam(round_id=\"a_short_round\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"a_short_round\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"a_short_round\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"a_short_round\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/a_short_round/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"a_short_round\" score=\"1\")==',3146,'round: a_short_round',NULL,NULL),('runda/a_short_round/clasament','Clasament a_short_round','2009-03-21 16:23:12','2009-03-21 20:41:56','h1. Clasament ==roundparam(round_id=\"a_short_round\" param=\"title\") ==\r\n\r\nFelicitări mie! :-)\r\n\r\n==Rankings(rounds = \"a_short_round\")==',3146,'round: a_short_round',NULL,NULL),('runda/contest01','contest01','2009-03-21 17:49:11','2009-03-21 17:49:11','h1. == roundparam(round_id=\"contest01\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"contest01\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"contest01\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"contest01\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/contest01/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"contest01\" score=\"1\")==',4772,'round: contest01',NULL,NULL),('runda/contest01/clasament','Clasament contest01','2009-03-21 17:49:11','2009-03-21 17:49:11','h1. Clasament ==roundparam(round_id=\"contest01\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"contest01\")==',4772,'round: contest01',NULL,NULL),('runda/simulare_oni2008_clasa10_ziua1','simulare_oni2008_clasa10_ziua1','2009-03-21 17:57:45','2009-03-21 17:57:45','h1. == roundparam(round_id=\"simulare_oni2008_clasa10_ziua1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"simulare_oni2008_clasa10_ziua1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"simulare_oni2008_clasa10_ziua1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"simulare_oni2008_clasa10_ziua1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/simulare_oni2008_clasa10_ziua1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"simulare_oni2008_clasa10_ziua1\" score=\"1\")==',2028,'round: simulare_oni2008_clasa10_ziua1',NULL,NULL),('runda/simulare_oni2008_clasa10_ziua1/clasament','Clasament simulare_oni2008_clasa10_ziua1','2009-03-21 17:57:45','2009-03-21 17:57:45','h1. Clasament ==roundparam(round_id=\"simulare_oni2008_clasa10_ziua1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"simulare_oni2008_clasa10_ziua1\")==',2028,'round: simulare_oni2008_clasa10_ziua1',NULL,NULL),('runda/simulare_oni2008_clasa10_ziua2','simulare_oni2008_clasa10_ziua2','2009-03-21 18:08:47','2009-03-21 18:08:47','h1. == roundparam(round_id=\"simulare_oni2008_clasa10_ziua2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"simulare_oni2008_clasa10_ziua2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"simulare_oni2008_clasa10_ziua2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"simulare_oni2008_clasa10_ziua2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/simulare_oni2008_clasa10_ziua2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"simulare_oni2008_clasa10_ziua2\" score=\"1\")==',4464,'round: simulare_oni2008_clasa10_ziua2',NULL,NULL),('runda/simulare_oni2008_clasa10_ziua2/clasament','Clasament simulare_oni2008_clasa10_ziua2','2009-03-21 18:08:47','2009-03-21 18:08:47','h1. Clasament ==roundparam(round_id=\"simulare_oni2008_clasa10_ziua2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"simulare_oni2008_clasa10_ziua2\")==',4464,'round: simulare_oni2008_clasa10_ziua2',NULL,NULL),('runda/infohard','infohard','2009-03-21 18:10:52','2009-03-21 18:10:52','h1. == roundparam(round_id=\"infohard\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"infohard\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"infohard\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"infohard\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/infohard/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"infohard\" score=\"1\")==',9795,'round: infohard',NULL,NULL),('runda/infohard/clasament','Clasament infohard','2009-03-21 18:10:52','2009-03-21 18:10:52','h1. Clasament ==roundparam(round_id=\"infohard\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"infohard\")==',9795,'round: infohard',NULL,NULL),('runda/brasov_city_challenge','brasov_city_challenge','2009-03-21 20:22:47','2009-03-21 20:22:47','h1. == roundparam(round_id=\"brasov_city_challenge\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"brasov_city_challenge\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"brasov_city_challenge\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"brasov_city_challenge\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/brasov_city_challenge/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"brasov_city_challenge\" score=\"1\")==',6333,'round: brasov_city_challenge',NULL,NULL),('runda/brasov_city_challenge/clasament','Clasament brasov_city_challenge','2009-03-21 20:22:47','2009-03-21 20:22:47','h1. Clasament ==roundparam(round_id=\"brasov_city_challenge\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"brasov_city_challenge\")==',6333,'round: brasov_city_challenge',NULL,NULL),('runda/kingoni/clasament','Clasament kingoni','2009-03-21 21:50:28','2009-03-21 21:50:28','h1. Clasament ==roundparam(round_id=\"kingoni\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"kingoni\")==',9156,'round: kingoni',NULL,NULL),('runda/1_1','1_1','2009-03-21 21:56:25','2009-03-21 21:56:25','h1. == roundparam(round_id=\"1_1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"1_1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"1_1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"1_1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/1_1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"1_1\" score=\"1\")==',155,'round: 1_1',NULL,NULL),('runda/1_1/clasament','Clasament 1_1','2009-03-21 21:56:25','2009-03-21 21:56:25','h1. Clasament ==roundparam(round_id=\"1_1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"1_1\")==',155,'round: 1_1',NULL,NULL),('runda/kingoni','kingoni','2009-03-21 21:50:28','2009-03-22 13:34:36','h1. == roundparam(round_id=\"kingoni\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"kingoni\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"kingoni\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"kingoni\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n* De ce \'King ONI\':http://images.ea.com/games/redalert3/Units/KingOni/RA3_KingOni1.jpg ? Daca ati jucat C&C: Red Alert 3, nu e nevoie sa va explic. Daca nu ati jucat, nu are rost sa va explic. \r\n\r\n* Concursul e o simulare pentru ONI, clasa a X-a.\r\n\r\n* Frumos ar fi sa fiti toti fair-play, deoarece nu aveti nimic de castigat daca trisati, dar aveti de invatat daca nu trisati.\r\n\r\n* Succes!\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/kingoni/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"kingoni\" score=\"1\")==',9156,'round: kingoni',NULL,NULL),('runda/lol1/clasament','Clasament lol1','2009-03-22 08:24:15','2009-03-22 08:24:15','h1. Clasament ==roundparam(round_id=\"lol1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"lol1\")==',9782,'round: lol1',NULL,NULL),('runda/random-contest','random-contest','2009-03-22 08:33:56','2009-03-22 08:33:56','h1. == roundparam(round_id=\"random-contest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"random-contest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"random-contest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"random-contest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/random-contest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"random-contest\" score=\"1\")==',1430,'round: random-contest',NULL,NULL),('runda/random-contest/clasament','Clasament random-contest','2009-03-22 08:33:56','2009-03-22 08:33:56','h1. Clasament ==roundparam(round_id=\"random-contest\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"random-contest\")==',1430,'round: random-contest',NULL,NULL),('runda/nicolae.gutza','nicolae.gutza','2009-03-22 08:57:12','2009-03-22 08:57:12','h1. == roundparam(round_id=\"nicolae.gutza\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"nicolae.gutza\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"nicolae.gutza\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"nicolae.gutza\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/nicolae.gutza/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"nicolae.gutza\" score=\"1\")==',4453,'round: nicolae.gutza',NULL,NULL),('runda/nicolae.gutza/clasament','Clasament nicolae.gutza','2009-03-22 08:57:12','2009-03-22 08:57:12','h1. Clasament ==roundparam(round_id=\"nicolae.gutza\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"nicolae.gutza\")==',4453,'round: nicolae.gutza',NULL,NULL),('runda/test912','test912','2009-03-22 09:12:05','2009-03-22 09:12:05','h1. == roundparam(round_id=\"test912\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"test912\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"test912\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"test912\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/test912/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"test912\" score=\"1\")==',3333,'round: test912',NULL,NULL),('runda/test912/clasament','Clasament test912','2009-03-22 09:12:05','2009-03-22 09:12:05','h1. Clasament ==roundparam(round_id=\"test912\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"test912\")==',3333,'round: test912',NULL,NULL),('runda/endurance','endurance','2009-03-22 13:10:43','2009-03-22 13:33:37','h1. == roundparam(round_id=\"endurance\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"endurance\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"endurance\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"endurance\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n* Acest concurs este destinat celor mai buni dintre cei buni. Concursul dureaza 12 ore si este alcatuit din 15 probleme grele. Acest concurs testeaza nu numai priceperea in programare cat si rezistenta si concentrarea.\r\n\r\n* Nu aveti de castigat nimic daca trisati, ci aveti de castigat daca jucati corect.\r\n\r\n* May the best one win!\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/endurance/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"endurance\" score=\"1\")==',9156,'round: endurance',NULL,NULL),('runda/endurance/clasament','Clasament endurance','2009-03-22 13:10:43','2009-03-22 13:10:43','h1. Clasament ==roundparam(round_id=\"endurance\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"endurance\")==',9156,'round: endurance',NULL,NULL),('runda/lolol','lolol','2009-03-22 13:29:18','2009-03-22 13:29:18','h1. == roundparam(round_id=\"lolol\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"lolol\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"lolol\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"lolol\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/lolol/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"lolol\" score=\"1\")==',6167,'round: lolol',NULL,NULL),('runda/lolol/clasament','Clasament lolol','2009-03-22 13:29:18','2009-03-22 13:29:18','h1. Clasament ==roundparam(round_id=\"lolol\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"lolol\")==',6167,'round: lolol',NULL,NULL),('razvy','Profil PavelRazvan','2009-03-22 13:32:28','2009-03-22 13:32:28','h2. Despre mine \r\n\r\nSunt elev in clasa a X-a...\r\nCam atat ;)\r\n\r\nh2. Studii\r\n\r\n\r\n* *\'Gimnaziul National Nicolae Balcescu\'*\r\n \r\n\r\n* *\'Colegiul National Alexandru Papiu Ilarian\'*-profilul mate-info intensiv informatica (in prezent)\r\n\r\n\r\n\r\nh2. Prieteni de pe infoarena\r\n\r\n\r\n==user(user=\"horax\" type=\"normal\")==\r\n\r\n==user(user=\"DraStiK \" type=\"normal\")==\r\n\r\n==user(user=\"ssergiuss\" type=\"normal\")==\r\n\r\n==user(user=\"raica_cristi\" type=\"normal\")==\r\n\r\n==user(user=\"danielb\" type=\"normal\")==\r\n\r\n==user(user=\"warcry\" type=\"normal\")==\r\n\r\n==user(user=\"tranzistor\" type=\"normal\")==\r\n\r\n==user(user=\"moldo_razvan\" type=\"normal\")==\r\n\r\n==user(user=\"Florin_92\" type=\"normal\")==\r\n\r\n==user(user=\"coni\" type=\"normal\")==\r\n\r\n\r\n\r\n',6958,'public',NULL,NULL),('runda/aa','aa','2009-03-22 16:42:03','2009-03-22 16:42:03','h1. == roundparam(round_id=\"aa\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"aa\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"aa\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"aa\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/aa/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"aa\" score=\"1\")==',8857,'round: aa',NULL,NULL),('runda/aa/clasament','Clasament aa','2009-03-22 16:42:03','2009-03-22 16:42:03','h1. Clasament ==roundparam(round_id=\"aa\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"aa\")==',8857,'round: aa',NULL,NULL),('runda/strong_contest','strong_contest','2009-03-22 17:43:45','2009-03-22 17:43:45','h1. == roundparam(round_id=\"strong_contest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"strong_contest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"strong_contest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"strong_contest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/strong_contest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"strong_contest\" score=\"1\")==',6720,'round: strong_contest',NULL,NULL),('runda/strong_contest/clasament','Clasament strong_contest','2009-03-22 17:43:45','2009-03-22 17:43:45','h1. Clasament ==roundparam(round_id=\"strong_contest\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"strong_contest\")==',6720,'round: strong_contest',NULL,NULL),('runda/nice_contest','nice_contest','2009-03-22 17:45:13','2009-03-22 17:45:13','h1. == roundparam(round_id=\"nice_contest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"nice_contest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"nice_contest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"nice_contest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/nice_contest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"nice_contest\" score=\"1\")==',6702,'round: nice_contest',NULL,NULL),('runda/nice_contest/clasament','Clasament nice_contest','2009-03-22 17:45:14','2009-03-22 17:45:14','h1. Clasament ==roundparam(round_id=\"nice_contest\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"nice_contest\")==',6702,'round: nice_contest',NULL,NULL),('runda/cnmnarad2/clasament','Clasament cnmnarad2','2009-03-22 20:27:56','2009-03-22 20:27:56','h1. Clasament ==roundparam(round_id=\"cnmnarad2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"cnmnarad2\")==',9156,'round: cnmnarad2',NULL,NULL),('runda/cnmnarad2','cnmnarad2','2009-03-22 20:27:56','2009-03-22 20:42:14','h1. == roundparam(round_id=\"cnmnarad2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cnmnarad2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cnmnarad2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cnmnarad2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n* Sunt 3 probleme medii, undeva cam la nivelul OJI clasa a X-a. Concursul este special facut pentru olimpicii de la Colegiul National \"Moise Nicoara\" Arad dar oricine e bine venit.\r\n\r\n* Daca trisati nu aveti nimic de castigat. Dar daca nu trisati aveti multe de invatat.\r\n\r\n* Succes!\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cnmnarad2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cnmnarad2\" score=\"1\")==',9156,'round: cnmnarad2',NULL,NULL),('runda/drastik_challange_2','drastik_challange_2','2009-03-23 05:38:48','2009-03-23 05:38:48','h1. == roundparam(round_id=\"drastik_challange_2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"drastik_challange_2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"drastik_challange_2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"drastik_challange_2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/drastik_challange_2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"drastik_challange_2\" score=\"1\")==',6957,'round: drastik_challange_2',NULL,NULL),('runda/drastik_challange_2/clasament','Clasament drastik_challange_2','2009-03-23 05:38:48','2009-03-23 05:38:48','h1. Clasament ==roundparam(round_id=\"drastik_challange_2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"drastik_challange_2\")==',6957,'round: drastik_challange_2',NULL,NULL),('runda/qwerty-1','qwerty-1','2009-03-23 12:09:55','2009-03-23 12:09:55','h1. == roundparam(round_id=\"qwerty-1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"qwerty-1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"qwerty-1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"qwerty-1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/qwerty-1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"qwerty-1\" score=\"1\")==',4439,'round: qwerty-1',NULL,NULL),('runda/qwerty-1/clasament','Clasament qwerty-1','2009-03-23 12:09:55','2009-03-23 12:09:55','h1. Clasament ==roundparam(round_id=\"qwerty-1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"qwerty-1\")==',4439,'round: qwerty-1',NULL,NULL),('runda/prepreoni_2009_gim','prepreoni_2009_gim','2009-03-23 12:34:58','2009-03-23 12:34:58','h1. == roundparam(round_id=\"prepreoni_2009_gim\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"prepreoni_2009_gim\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"prepreoni_2009_gim\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"prepreoni_2009_gim\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/prepreoni_2009_gim/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"prepreoni_2009_gim\" score=\"1\")==',4863,'round: prepreoni_2009_gim',NULL,NULL),('runda/prepreoni_2009_gim/clasament','Clasament prepreoni_2009_gim','2009-03-23 12:34:58','2009-03-23 12:34:58','h1. Clasament ==roundparam(round_id=\"prepreoni_2009_gim\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"prepreoni_2009_gim\")==',4863,'round: prepreoni_2009_gim',NULL,NULL),('runda/dexter','dexter','2009-03-23 13:14:43','2009-03-23 13:17:06','h1. == roundparam(round_id=\"dexter\" param=\"title\") ==\r\n\r\nWhat does this button do? o.O\r\n\r\n\r\n== roundregister(round_id=\"dexter\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"dexter\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"dexter\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/dexter/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"dexter\" score=\"1\")==',1507,'round: dexter',NULL,NULL),('runda/dexter/clasament','Clasament dexter','2009-03-23 13:14:43','2009-03-23 13:14:43','h1. Clasament ==roundparam(round_id=\"dexter\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"dexter\")==',1507,'round: dexter',NULL,NULL),('runda/pregatire_oni_1/clasament','Clasament pregatire_oni_1','2009-03-23 14:47:45','2009-03-23 14:47:45','h1. Clasament ==roundparam(round_id=\"pregatire_oni_1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pregatire_oni_1\")==',6172,'round: pregatire_oni_1',NULL,NULL),('runda/pregatire_oni_1','pregatire_oni_1','2009-03-23 14:47:44','2009-03-24 10:29:17','h1. == roundparam(round_id=\"pregatire_oni_1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"pregatire_oni_1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"pregatire_oni_1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"pregatire_oni_1\" param=\"duration\" strong=\"true\")== ore. Runda va contine 3 probleme de la olimpiadele nationale de informatica din anii anteriori.\r\nDe preferat sa nu se trimita solutiile in arhiva prima data, pentru a vedea punctajul!\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/pregatire_oni_1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"pregatire_oni_1\" score=\"1\")==',6172,'round: pregatire_oni_1',NULL,NULL),('runda/brasov_challenge_2','brasov_challenge_2','2009-03-23 17:38:50','2009-03-23 17:38:50','h1. == roundparam(round_id=\"brasov_challenge_2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"brasov_challenge_2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"brasov_challenge_2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"brasov_challenge_2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/brasov_challenge_2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"brasov_challenge_2\" score=\"1\")==',8180,'round: brasov_challenge_2',NULL,NULL),('runda/brasov_challenge_2/clasament','Clasament brasov_challenge_2','2009-03-23 17:38:50','2009-03-23 17:38:50','h1. Clasament ==roundparam(round_id=\"brasov_challenge_2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"brasov_challenge_2\")==',8180,'round: brasov_challenge_2',NULL,NULL),('runda/oo','oo','2009-03-23 19:25:08','2009-03-23 19:25:08','h1. == roundparam(round_id=\"oo\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oo\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oo\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oo\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/oo/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"oo\" score=\"1\")==',9491,'round: oo',NULL,NULL),('runda/oo/clasament','Clasament oo','2009-03-23 19:25:08','2009-03-23 19:25:08','h1. Clasament ==roundparam(round_id=\"oo\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"oo\")==',9491,'round: oo',NULL,NULL),('runda/scratch.the.answer','scratch.the.answer','2009-03-24 08:46:59','2009-03-24 08:46:59','h1. == roundparam(round_id=\"scratch.the.answer\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"scratch.the.answer\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"scratch.the.answer\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"scratch.the.answer\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/scratch.the.answer/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"scratch.the.answer\" score=\"1\")==',9905,'round: scratch.the.answer',NULL,NULL),('runda/scratch.the.answer/clasament','Clasament scratch.the.answer','2009-03-24 08:47:00','2009-03-24 08:47:00','h1. Clasament ==roundparam(round_id=\"scratch.the.answer\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"scratch.the.answer\")==',9905,'round: scratch.the.answer',NULL,NULL),('runda/prega','prega','2009-03-24 09:41:47','2009-03-24 09:41:47','h1. == roundparam(round_id=\"prega\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"prega\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"prega\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"prega\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/prega/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"prega\" score=\"1\")==',4371,'round: prega',NULL,NULL),('runda/prega/clasament','Clasament prega','2009-03-24 09:41:47','2009-03-24 09:41:47','h1. Clasament ==roundparam(round_id=\"prega\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"prega\")==',4371,'round: prega',NULL,NULL),('runda/ag','ag','2009-03-24 09:46:13','2009-03-24 09:46:13','h1. == roundparam(round_id=\"ag\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"ag\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"ag\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ag\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/ag/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"ag\" score=\"1\")==',4371,'round: ag',NULL,NULL),('runda/ag/clasament','Clasament ag','2009-03-24 09:46:13','2009-03-24 09:46:13','h1. Clasament ==roundparam(round_id=\"ag\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"ag\")==',4371,'round: ag',NULL,NULL),('runda/inceput/clasament','Clasament inceput','2009-03-24 10:12:36','2009-03-24 10:12:36','h1. Clasament ==roundparam(round_id=\"inceput\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"inceput\")==',9757,'round: inceput',NULL,NULL),('runda/placinta/clasament','Clasament placinta','2009-03-24 10:26:59','2009-03-24 10:26:59','h1. Clasament ==roundparam(round_id=\"placinta\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"placinta\")==',2934,'round: placinta',NULL,NULL),('runda/placinta','placinta','2009-03-24 10:26:59','2009-03-24 10:36:50','h1. THE CAKE IS A LIE... IT SMELLS LIKE PIE!!!\r\n\r\nh1. == roundparam(round_id=\"placinta\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"placinta\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"placinta\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"placinta\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/placinta/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"placinta\" score=\"1\")==',2934,'round: placinta',NULL,NULL),('runda/pie2','pie2','2009-03-24 10:40:08','2009-03-24 10:40:08','h1. == roundparam(round_id=\"pie2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"pie2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"pie2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"pie2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/pie2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"pie2\" score=\"1\")==',6846,'round: pie2',NULL,NULL),('runda/pie2/clasament','Clasament pie2','2009-03-24 10:40:08','2009-03-24 10:40:08','h1. Clasament ==roundparam(round_id=\"pie2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pie2\")==',6846,'round: pie2',NULL,NULL),('runda/test913','test913','2009-03-24 13:33:21','2009-03-24 13:33:21','h1. == roundparam(round_id=\"test913\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"test913\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"test913\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"test913\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/test913/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"test913\" score=\"1\")==',6245,'round: test913',NULL,NULL),('runda/test913/clasament','Clasament test913','2009-03-24 13:33:21','2009-03-24 13:33:21','h1. Clasament ==roundparam(round_id=\"test913\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"test913\")==',6245,'round: test913',NULL,NULL),('runda/concurs_pd/clasament','Clasament concurs_pd','2009-03-24 14:23:30','2009-03-28 12:42:39','h1. Clasament ==roundparam(round_id=\"concurs_pd\" param=\"title\") ==\r\n\r\nAm inregistrat 0 participanti.',3680,'round: concurs_pd',NULL,NULL),('runda/concurs_pd','concurs_pd','2009-03-24 14:23:30','2009-03-24 14:40:36','h1. == roundparam(round_id=\"concurs_pd\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"concurs_pd\") ==\r\n\r\nRunda pentru incepatori de toate varstele (solutiile oficiale nu utilizeaza structuri de date care se studiaza doar in anii terminali ai liceului) care vor sa se perfectioneze in tehnica programarii dinamice.\r\n\r\nConcursul incepe ==roundparam(round_id=\"concurs_pd\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"concurs_pd\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/concurs_pd/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"concurs_pd\" score=\"1\")==',3680,'round: concurs_pd',NULL,NULL),('runda/666-69','666-69','2009-03-24 16:12:17','2009-03-24 16:12:17','h1. == roundparam(round_id=\"666-69\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"666-69\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"666-69\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"666-69\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/666-69/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"666-69\" score=\"1\")==',7831,'round: 666-69',NULL,NULL),('runda/666-69/clasament','Clasament 666-69','2009-03-24 16:12:17','2009-03-24 16:12:17','h1. Clasament ==roundparam(round_id=\"666-69\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"666-69\")==',7831,'round: 666-69',NULL,NULL),('runda/pregatire','pregatire','2009-03-24 16:12:34','2009-03-24 16:12:34','h1. == roundparam(round_id=\"pregatire\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"pregatire\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"pregatire\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"pregatire\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/pregatire/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"pregatire\" score=\"1\")==',6305,'round: pregatire',NULL,NULL),('runda/pregatire/clasament','Clasament pregatire','2009-03-24 16:12:34','2009-03-24 16:12:34','h1. Clasament ==roundparam(round_id=\"pregatire\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pregatire\")==',6305,'round: pregatire',NULL,NULL),('runda/concurs_cu_o_problema_usoara_si_una_medie','concurs_cu_o_problema_usoara_si_una_medie','2009-03-24 18:12:39','2009-03-24 18:12:39','h1. == roundparam(round_id=\"concurs_cu_o_problema_usoara_si_una_medie\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"concurs_cu_o_problema_usoara_si_una_medie\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"concurs_cu_o_problema_usoara_si_una_medie\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"concurs_cu_o_problema_usoara_si_una_medie\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/concurs_cu_o_problema_usoara_si_una_medie/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"concurs_cu_o_problema_usoara_si_una_medie\" score=\"1\")==',9903,'round: concurs_cu_o_problema_usoara_si_una_medie',NULL,NULL),('runda/concurs_cu_o_problema_usoara_si_una_medie/clasament','Clasament concurs_cu_o_problema_usoara_si_una_medie','2009-03-24 18:12:39','2009-03-24 18:12:39','h1. Clasament ==roundparam(round_id=\"concurs_cu_o_problema_usoara_si_una_medie\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"concurs_cu_o_problema_usoara_si_una_medie\")==',9903,'round: concurs_cu_o_problema_usoara_si_una_medie',NULL,NULL),('runda/oni.pre','oni.pre','2009-03-24 19:06:43','2009-03-24 19:06:43','h1. == roundparam(round_id=\"oni.pre\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oni.pre\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oni.pre\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oni.pre\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/oni.pre/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"oni.pre\" score=\"1\")==',5406,'round: oni.pre',NULL,NULL),('runda/oni.pre/clasament','Clasament oni.pre','2009-03-24 19:06:43','2009-03-24 19:06:43','h1. Clasament ==roundparam(round_id=\"oni.pre\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"oni.pre\")==',5406,'round: oni.pre',NULL,NULL),('runda/prega2','prega2','2009-03-25 05:42:08','2009-03-25 05:42:08','h1. == roundparam(round_id=\"prega2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"prega2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"prega2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"prega2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/prega2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"prega2\" score=\"1\")==',4371,'round: prega2',NULL,NULL),('runda/prega2/clasament','Clasament prega2','2009-03-25 05:42:08','2009-03-25 05:42:08','h1. Clasament ==roundparam(round_id=\"prega2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"prega2\")==',4371,'round: prega2',NULL,NULL),('runda/qwerty-2','qwerty-2','2009-03-25 10:30:03','2009-03-25 10:30:03','h1. == roundparam(round_id=\"qwerty-2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"qwerty-2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"qwerty-2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"qwerty-2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/qwerty-2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"qwerty-2\" score=\"1\")==',4439,'round: qwerty-2',NULL,NULL),('runda/qwerty-2/clasament','Clasament qwerty-2','2009-03-25 10:30:03','2009-03-25 10:30:03','h1. Clasament ==roundparam(round_id=\"qwerty-2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"qwerty-2\")==',4439,'round: qwerty-2',NULL,NULL),('runda/pregatire.oni.clasa.a.noua','pregatire.oni.clasa.a.noua','2009-03-25 11:43:31','2009-03-26 16:04:23','<DELETED>',8700,'round: pregatire.oni.clasa.a.noua',NULL,NULL),('runda/incepatori','incepatori','2009-03-26 17:22:17','2009-03-26 17:22:17','h1. == roundparam(round_id=\"incepatori\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"incepatori\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"incepatori\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"incepatori\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/incepatori/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"incepatori\" score=\"1\")==',8109,'round: incepatori',NULL,NULL),('runda/pregatire.oni.clasa.a.noua/clasament','Clasament pregatire.oni.clasa.a.noua','2009-03-25 11:43:31','2009-03-25 11:43:31','h1. Clasament ==roundparam(round_id=\"pregatire.oni.clasa.a.noua\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pregatire.oni.clasa.a.noua\")==',8700,'round: pregatire.oni.clasa.a.noua',NULL,NULL),('runda/simulareonidouamiioptclasanoua/clasament','Clasament simulareonidouamiioptclasanoua','2009-03-25 11:45:23','2009-03-25 11:45:23','h1. Clasament ==roundparam(round_id=\"simulareonidouamiioptclasanoua\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"simulareonidouamiioptclasanoua\")==',8700,'round: simulareonidouamiioptclasanoua',NULL,NULL),('runda/test1','test1','2009-03-25 17:09:55','2009-03-25 17:09:55','h1. == roundparam(round_id=\"test1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"test1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"test1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"test1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/test1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"test1\" score=\"1\")==',9978,'round: test1',NULL,NULL),('runda/test1/clasament','Clasament test1','2009-03-25 17:09:55','2009-03-25 17:09:55','h1. Clasament ==roundparam(round_id=\"test1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"test1\")==',9978,'round: test1',NULL,NULL),('runda/c-1','c-1','2009-03-25 21:01:35','2009-03-25 21:01:35','h1. == roundparam(round_id=\"c-1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"c-1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"c-1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"c-1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/c-1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"c-1\" score=\"1\")==',9782,'round: c-1',NULL,NULL),('runda/c-1/clasament','Clasament c-1','2009-03-25 21:01:35','2009-03-25 21:01:35','h1. Clasament ==roundparam(round_id=\"c-1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"c-1\")==',9782,'round: c-1',NULL,NULL),('runda/qwerty-3','qwerty-3','2009-03-26 13:51:03','2009-03-26 13:51:03','h1. == roundparam(round_id=\"qwerty-3\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"qwerty-3\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"qwerty-3\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"qwerty-3\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/qwerty-3/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"qwerty-3\" score=\"1\")==',4439,'round: qwerty-3',NULL,NULL),('runda/qwerty-3/clasament','Clasament qwerty-3','2009-03-26 13:51:03','2009-03-26 13:51:03','h1. Clasament ==roundparam(round_id=\"qwerty-3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"qwerty-3\")==',4439,'round: qwerty-3',NULL,NULL),('runda/simulareonidouamiioptclasanoua','simulareonidouamiioptclasanoua','2009-03-25 11:45:23','2009-03-26 15:52:25','h1. == roundparam(round_id=\"simulareonidouamiioptclasanoua\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"simulareonidouamiioptclasanoua\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"simulareonidouamiioptclasanoua\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"simulareonidouamiioptclasanoua\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/simulareonidouamiioptclasanoua/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"simulareonidouamiioptclasanoua\" score=\"1\")==\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n(c) CTA 2009',8700,'round: simulareonidouamiioptclasanoua',NULL,NULL),('runda/incepatori/clasament','Clasament incepatori','2009-03-26 17:22:17','2009-03-26 17:22:17','h1. Clasament ==roundparam(round_id=\"incepatori\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"incepatori\")==',8109,'round: incepatori',NULL,NULL),('runda/katamashhh','katamashhh','2009-04-03 08:33:26','2009-04-03 08:33:26','h1. == roundparam(round_id=\"katamashhh\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"katamashhh\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"katamashhh\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"katamashhh\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/katamashhh/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"katamashhh\" score=\"1\")==',9989,'round: katamashhh',NULL,NULL),('runda/lame.contest/clasament','Clasament lame.contest','2009-03-27 22:18:25','2009-03-27 22:18:25','h1. Clasament ==roundparam(round_id=\"lame.contest\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"lame.contest\")==',9714,'round: lame.contest',NULL,NULL),('runda/pregatire-pentrut-nationala','pregatire-pentrut-nationala','2009-03-28 13:10:40','2009-03-28 13:10:40','h1. == roundparam(round_id=\"pregatire-pentrut-nationala\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"pregatire-pentrut-nationala\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"pregatire-pentrut-nationala\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"pregatire-pentrut-nationala\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/pregatire-pentrut-nationala/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"pregatire-pentrut-nationala\" score=\"1\")==',9903,'round: pregatire-pentrut-nationala',NULL,NULL),('runda/pregatire-pentrut-nationala/clasament','Clasament pregatire-pentrut-nationala','2009-03-28 13:10:40','2009-03-28 13:10:40','h1. Clasament ==roundparam(round_id=\"pregatire-pentrut-nationala\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pregatire-pentrut-nationala\")==',9903,'round: pregatire-pentrut-nationala',NULL,NULL),('runda/cnrg','cnrg','2009-03-28 14:30:24','2009-03-28 14:30:24','h1. == roundparam(round_id=\"cnrg\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cnrg\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cnrg\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cnrg\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cnrg/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cnrg\" score=\"1\")==',5293,'round: cnrg',NULL,NULL),('runda/cnrg/clasament','Clasament cnrg','2009-03-28 14:30:24','2009-03-28 14:30:24','h1. Clasament ==roundparam(round_id=\"cnrg\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"cnrg\")==',5293,'round: cnrg',NULL,NULL),('runda/beginners','beginners','2009-03-29 07:22:55','2009-03-29 07:22:55','h1. == roundparam(round_id=\"beginners\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"beginners\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"beginners\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"beginners\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/beginners/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"beginners\" score=\"1\")==',8109,'round: beginners',NULL,NULL),('runda/beginners/clasament','Clasament beginners','2009-03-29 07:22:55','2009-03-29 07:22:55','h1. Clasament ==roundparam(round_id=\"beginners\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"beginners\")==',8109,'round: beginners',NULL,NULL),('runda/preoni-cl._5-8','preoni-cl._5-8','2009-03-29 09:58:46','2009-03-29 09:58:46','h1. == roundparam(round_id=\"preoni-cl._5-8\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"preoni-cl._5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoni-cl._5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoni-cl._5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/preoni-cl._5-8/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"preoni-cl._5-8\" score=\"1\")==',6490,'round: preoni-cl._5-8',NULL,NULL),('runda/preoni-cl._5-8/clasament','Clasament preoni-cl._5-8','2009-03-29 09:58:46','2009-03-29 09:58:46','h1. Clasament ==roundparam(round_id=\"preoni-cl._5-8\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoni-cl._5-8\")==',6490,'round: preoni-cl._5-8',NULL,NULL),('runda/4-aprilie_preoni-cl._5-8','4-aprilie_preoni-cl._5-8','2009-03-29 09:59:35','2009-03-29 09:59:35','h1. == roundparam(round_id=\"4-aprilie_preoni-cl._5-8\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"4-aprilie_preoni-cl._5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"4-aprilie_preoni-cl._5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"4-aprilie_preoni-cl._5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/4-aprilie_preoni-cl._5-8/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"4-aprilie_preoni-cl._5-8\" score=\"1\")==',6490,'round: 4-aprilie_preoni-cl._5-8',NULL,NULL),('runda/4-aprilie_preoni-cl._5-8/clasament','Clasament 4-aprilie_preoni-cl._5-8','2009-03-29 09:59:35','2009-03-29 09:59:35','h1. Clasament ==roundparam(round_id=\"4-aprilie_preoni-cl._5-8\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"4-aprilie_preoni-cl._5-8\")==',6490,'round: 4-aprilie_preoni-cl._5-8',NULL,NULL),('runda/concurs_nou1/clasament','Clasament concurs_nou1','2009-03-29 13:43:05','2009-03-29 13:43:05','h1. Clasament ==roundparam(round_id=\"concurs_nou1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"concurs_nou1\")==',9995,'round: concurs_nou1',NULL,NULL),('runda/star_trek/clasament','Clasament star_trek','2009-03-29 14:24:54','2010-01-01 18:36:32','h1. Vanatorii de recompense ==roundparam(round_id=\"star_trek\" param=\"title\") ==\r\n\r\nFelicitari celor mai bogati!!!\r\n\r\n==Rankings(rounds = \"star_trek\")==',8689,'round: star_trek',NULL,NULL),('runda/ktmalx_93','ktmalx_93','2009-03-29 18:15:53','2009-03-29 18:15:53','h1. == roundparam(round_id=\"ktmalx_93\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"ktmalx_93\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"ktmalx_93\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ktmalx_93\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/ktmalx_93/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"ktmalx_93\" score=\"1\")==',9989,'round: ktmalx_93',NULL,NULL),('runda/ktmalx_93/clasament','Clasament ktmalx_93','2009-03-29 18:15:53','2009-03-29 18:15:53','h1. Clasament ==roundparam(round_id=\"ktmalx_93\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"ktmalx_93\")==',9989,'round: ktmalx_93',NULL,NULL),('runda/bac-calinush','bac-calinush','2009-03-29 18:53:02','2009-03-29 18:53:02','h1. == roundparam(round_id=\"bac-calinush\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"bac-calinush\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"bac-calinush\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"bac-calinush\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/bac-calinush/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"bac-calinush\" score=\"1\")==',10001,'round: bac-calinush',NULL,NULL),('runda/bac-calinush/clasament','Clasament bac-calinush','2009-03-29 18:53:02','2009-03-29 18:53:02','h1. Clasament ==roundparam(round_id=\"bac-calinush\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"bac-calinush\")==',10001,'round: bac-calinush',NULL,NULL),('runda/9a.info','9a.info','2009-03-29 18:57:20','2009-03-29 18:57:20','h1. == roundparam(round_id=\"9a.info\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"9a.info\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"9a.info\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"9a.info\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/9a.info/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"9a.info\" score=\"1\")==',9989,'round: 9a.info',NULL,NULL),('runda/9a.info/clasament','Clasament 9a.info','2009-03-29 18:57:20','2009-03-29 18:57:20','h1. Clasament ==roundparam(round_id=\"9a.info\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"9a.info\")==',9989,'round: 9a.info',NULL,NULL),('runda/alxktms93','alxktms93','2009-03-29 19:11:04','2009-03-29 19:11:04','h1. == roundparam(round_id=\"alxktms93\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"alxktms93\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"alxktms93\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"alxktms93\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/alxktms93/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"alxktms93\" score=\"1\")==',9925,'round: alxktms93',NULL,NULL),('runda/alxktms93/clasament','Clasament alxktms93','2009-03-29 19:11:04','2009-03-29 19:11:04','h1. Clasament ==roundparam(round_id=\"alxktms93\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"alxktms93\")==',9925,'round: alxktms93',NULL,NULL),('deque-si-aplicatii','Deque și aplicații','2009-01-22 22:28:12','2009-11-28 21:57:12','h1. Deque şi aplicaţii\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'Descrierea structurii\':deque-si-aplicatii#descriere\r\n* \'Aplicaţii:\':deque-si-aplicatii#problema-1\r\n** \'_1. Book Pile &#40;SGU&#41;_\':deque-si-aplicatii#problema-1\r\n** \'_2. Vila 2 &#40;.campion, 2005&#41;_\':deque-si-aplicatii#problema-2\r\n** \'_3. Şir_\':deque-si-aplicatii#problema-3\r\n** \'_4. Platforma &#40;.campion, 2009&#41;_\':deque-si-aplicatii#problema-4\r\n** \'_5. Trans &#40;ONI 2004&#41;_\':deque-si-aplicatii#problema-5\r\n** \'_6. Otilia &#40;.campion, 2005&#41;_\':deque-si-aplicatii#problema-6\r\n** \'_7. Bcrc &#40;Stelele Informaticii, 2006&#41;_\':deque-si-aplicatii#problema-7\r\n** \'_8. Cut the Sequence &#40;PKU&#41;_\':deque-si-aplicatii#problema-8\r\n* \'Concluzii\':deque-si-aplicatii#concluzii\r\n* \'Probleme suplimentare\':deque-si-aplicatii#probleme-suplimentare\r\n* \'Bibliografie\':deque-si-aplicatii#bibliografie\r\n\r\nÎn acest articol voi prezenta o structură de date liniară de tip listă numită _deque_. Aceasta nu este una complexă, în schimb se va dovedi foarte folositoare. După o scurtă prezentare, mă voi axa pe o serie de aplicaţii care vor arăta surprinzătoarea sa utilitate în locurile unde am fi crezut că nu se mai poate face nimic pentru a reduce complexitatea algoritmului. De menţionat că primul care a folosit această noţiune a fost Donald Knuth în lucrarea \"_The Art of Computer Programming_\" ({_Volume 1: Fundamental Algorithms, Third Edition_}) din 1997.\r\n\r\nh2(#descriere). Descrierea structurii\r\n\r\nStructura de _deque_ (pronunţat, de obicei, _deck_) poate fi privită ca o listă cu două capete prin intermediul cărora se şterg sau inserează noi elemente. În literatura de specialitate aceste capete se numesc _head_ şi _tail_, iar deque-ul mai este recunoscut şi ca fiind o coadă cu două capete _(double ended queue)_.\r\n\r\nPentru implementarea unui deque putem recurge la liste dublu înlănţuite sau la un vector static când se cunoaşte numărul elementelor din colecţie. Limbajul C++ pune şi el la dispoziţia programatorilor o implementare prin intermediul containerului \'_std::deque_\':http://www.cplusplus.com/reference/stl/deque/ din headerul _<deque>_.\r\n\r\nh3(#operatii). Operaţii:\r\n\r\nVom putea utiliza această structură de date în situaţiile când avem nevoie de următoarele operaţii (sunt listate cu numele sub care se găsesc în limbajul C++):\r\n\r\ntable{width:70%}. | * _front()_ | întoarce primul element |\r\n| * _back()_ | întoarce ultimul element |\r\n| * _push_front()_ | inserează un element în faţă |\r\n| * _push_back()_ | inserează un element în spate |\r\n| * _pop_front()_ | scoate primul element |\r\n| * _pop_back()_ | scoate ultimul element |\r\n| * _empty()_ | întoarce _true_ dacă în deque nu se găseşte niciun element şi _false_ în caz contrar |\r\n\r\np=. !deque-si-aplicatii?new_deque.png 75%!\r\n\r\nToate aceste operaţii se execută în timp $O(1)$ pe o structură implementată de la zero sau în timp $O(1)$ \'amortizat\':http://en.wikipedia.org/wiki/Amortized_analysis pentru containerul $deque$ din C++.\r\n\r\nÎn multe aplicaţii unde soluţiile parţiale se reprezintă sub forma unui şir continuu de valori care permite inserarea şi ştergerea doar pe la capete se poate folosi un $deque$. Să urmărim în continuare cazuri concrete în care simplitatea unui $deque$ duce la soluţii de multe ori optime şi implementări foarte scurte şi clare. Aplicaţiile sunt prezentate în ordinea crescătoare a dificultăţii şi din acest motiv le recomand cu căldură tuturor celor care învaţă din acest articol să le parcurgă în ordine.\r\n\r\nh2(#problema-1). 1. \'Book Pile\':http://acm.sgu.ru/problem.php?contest=0&problem=271 (SGU)\r\n\r\nbq. Se dau $N$ cărţi aşezate una deasupra celeilalte asupra cărora se vor efectua $M$ operaţii de două tipuri: 1. $ADD${$(nume)$}: se adaugă cartea $nume$ deasupra celorlalte; 2. $ROTATE$: primele $K$ cărţi de deasupra se rotesc (dacă sunt mai puţin de $K$ cărţi atunci se vor roti toate). Rotaţia presupune inversarea celor $K$ elemente, adică ultimul va fi primul, penultimul va fi al doilea etc. Se cere să se afişeze cărţile în ordine, prima fiind cea de deasupra, după efectuarea celor $M$ operaţii.\r\nRestricţii: $0 &le; N, K &le; 40 000$, $0 &le; M &le; 100 000$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se poate deduce pe baza observaţiei următoare: odată avansată dincolo de poziţia $K$, o carte ajunge pe poziţia finală, întrucât orice operaţie ulterioară (inserare sau rotaţie) nu o va mai afecta. Să presupunem că iniţial avem cărţile $A B C$ şi $K = 3$. Dacă îl vom adăuga pe $D$, atunci nu avem nevoie pentru operaţiile următoare decât de cărţile $D A B$, deoarece, dacă vom roti ulterior primele $K$ cărţi, $C$ nu va mai fi niciodată considerat. După o rotaţie, noua ordine va fi $B A D$ şi $C$ va fi pe raft la loc sigur. Dacă îl vom adăuga pe $E$, topul se va schimba în $E B A$, iar pe raft, în mod sigur vor fi $D C$, în această ordine. Cele $K$ cărţi din vârf se prezintă ca o secvenţă continuă de elemente, la care se adaugă noi elemente sau se elimină dintre acestea numai pe la _capete_. Aceste capete sunt chiar $head$ şi $tail$ ale unui $deque$.\r\n\r\np=. !deque-si-aplicatii?bookpile.png 40%!\r\n\r\nLa final, când se vor termina operaţiile, cărţilor de pe raft li se vor adăuga cele din $deque$ şi se va afişa soluţia. În cazul presupus, soluţia va fi: $E B A D C$.\r\n\r\nÎntrucât operaţiile unui $deque$ se execută în timp $O(1)$, soluţia are complexitatea $O(N + M)$.\r\n\r\nh2(#problema-2). 2. \'Vila 2\':problema/vila2 (.campion, 2005)\r\n\r\nbq. Se dă un şir $S$ de $N$ numere întregi şi $D$ un număr natural. Se cere să se determine diferenţa maximă dintre oricare două numere din şir cu proprietatea că diferenţa în modul a poziţiilor pe care se găsesc în şirul $S$ nu depăşeşte $D$.\r\nRestricţii: $2 &le; N &le; 100 000$, $1 &le; D &le; N/2$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia naivă constă în procesarea tuturor perechilor de numere care se găsesc pe poziţii cu diferenţa în modul mai mică sau egală decât $D$.\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    ret = 0;\r\n    pentru i = 1, N execută\r\n        pentru j = Max(1, i - D), i execută\r\n            dacă ret < |S[i] - S[j]| atunci\r\n                ret = |S[i] - S[j]|;\r\n        sfârşit_pentru;\r\n    sfârşit_pentru;\r\n    return ret;\r\nSfârşit.\r\n==\r\n\r\nComplexitatea algoritmului este $O(N^2^)$, dar pentru limitele problemei este enorm de mare.\r\n\r\nDin pseudocodul de mai sus se vede că pentru un indice $i$ fixat, iterăm cu un alt indice $j$ pentru a găsi diferenţa maximă în modul dintre $S[i]$ şi un alt număr din intervalul $[i - D, i]$. Însă, diferenţa dintre cel mai mare număr şi cel mai mic număr este cel puţin la fel de bună ca rezultatul de la $j$-ul anterior. Astfel, pentru indicele $i$ fixat succesiv cu $1$, $2$, .., $N$, considerăm secvenţa $[i - D, i]$ în care determinăm valoarea maximă şi valoarea minimă, iar diferenţa lor o comparăm cu rezultatul cel mai bun obţinut până în acel moment.\r\n\r\nPentru fixarea ideii, să urmărim cum putem determina eficient valoarea maximă din fiecare secvenţă $[i - D, i]$.\r\n\r\n_Observaţie_: Fie $i{~1~}$, $i{~2~}$ doi indici astfel încât $i - D &le; i{~1~} &lt; i{~2~} &le; i$.\r\n\r\n# Dacă $S[i{~1~}] &le; S[i{~2~}]$ atunci, cât timp cei doi indici vor fi în intervale de tipul $[i - D, i]$, valoarea de pe poziţia $i{~2~}$ va fi întotdeauna preferată valorii de pe poziţia $i{~1~}$. Când se ajunge la un interval care nu-l mai conţine pe $i{~1~}$, $i{~2~}$ rămâne în continuare preferat.\r\n# Dacă $S[i{~1~}] &gt; S[i{~2~}]$ atunci şi valoarea de pe poziţia $i{~1~}$ şi cea de pe poziţia $i{~2~}$ sunt candidate la maxim, la momentul curent sau în viitor.\r\n\r\nCu această observaţie deducem că într-o secvenţă $[i - D, i]$ vom avea un şir strict descrescător de numere: $T{~i~} = S[i{~1~}] &gt; S[i{~2~}] &gt; ... &gt; S[i{~K~}]$, unde $S[i{~1~}]$ elimină toate elementele $S[j]$, cu $S[j] &le; S[i{~1~}]$ şi $i - D &le; j &lt; i{~1~}$, $S[i{~2~}]$ elimină toate elementele $S[j]$, cu $S[j] &le; S[i{~2~}]$ şi $i{~1~} &lt; j &lt; i{~2~}$, $S[i{~3~}]$ elimină toate elementele $S[j]$, cu $S[j] &le; S[i{~3~}]$ şi $i{~2~} &lt; j &lt; i{~3~}$ ş.a.m.d. De reţinut este că niciuna dintre valorile de pe poziţiile eliminate nu poate fi maximă, motiv pentru care le-am putut elimina. Şirul $T{~i~}$ are următoarele proprietăţi:\r\n\r\n* se termină pe poziţia curentă, adică are loc egalitatea $i{~K~} = i$ întrucât poziţia $i$ nu va fi eliminată de nicio altă poziţie;\r\n* valoarea căutată, adică maximul dintre numerele din secvenţă, se găseşte pe prima poziţie. \r\n\r\nCând vom avansa la secvenţa următoare, $[i - D + 1, i + 1]$, vom forma şirul $T{~i+1~}$ ştergând din indicii $i{~1~}$, $i{~2~}$ ... atâta timp cât nu se găsesc în intervalul curent şi vom şterge din poziţiile $i{~K~}$, $i{~K-1~}$ ... cât timp $S[i + 1] &ge; S[i{~K~}]$, $S[i + 1] &ge; S[i{~K-1~}]$ ...\r\n\r\nŞirul $T{~i~}$ poate fi păstrat prin intermediul şirului de indici $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$. Operaţiile pe acest şir se efectuează doar pe la cele două capete, aşadar poate fi implementat cu ajutorul unui $deque$.\r\n\r\nPentru $S[] = {5, 9, 4, 7, 4, 1}$ şi $D = 3$ obţinem următoarele stări ale unui deque:\r\n\r\n* <tex> \\langle \\widehat{5\\ [1]} \\rangle </tex>;\r\n* <tex> \\langle 5\\ [1] \\rangle \\Leftarrow 9\\ [2] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]} \\rangle </tex>;\r\n* <tex> \\langle 9\\ [2] \\rangle \\Leftarrow 4\\ [3] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 4\\ [3] \\rangle </tex>;\r\n* <tex> \\langle 9\\ [2],\\ 4\\ [3] \\rangle \\Leftarrow 7\\ [4] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 7\\ [4] \\rangle </tex>;\r\n* <tex> 9\\ [2] \\Leftarrow \\langle 7\\ [4] \\rangle \\Leftarrow 4\\ [5] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5] \\rangle </tex>;\r\n* <tex> \\langle 7\\ [4],\\ 4\\ [5] \\rangle \\Leftarrow 1\\ [6] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5],\\ 1\\ [6] \\rangle </tex>;\r\n\r\nCum fiecare indice din $1$, $2$, ..., $N$ este adăugat şi şters cel mult o dată din deque, complexitatea finală este $O(N)$.\r\n\r\nh2(#problema-3). 3. \'Şir\':problema/sir\r\n\r\nbq. Se dă un şir $S$ de numere întregi de lungime $N$. Se cere să se găsească secvenţa de lungime maximă cuprinsă între $X$ şi $Y$ astfel încât $MAX - MIN &le; Z$, unde $MAX$ este maximul dintre toate numerele întregi din secvenţă, iar $MIN$ minimul dintre acestea. Secvenţa soluţie va fi cea cu poziţia de început maximă dintre toate secvenţele de lungime maximă.\r\nRestricţii: $3 &le; N &le; 100 000$, $1 &le; X &le; Y &le; N$, $0 &le; Z &le; 30 000$.\r\n\r\nh3. Soluţie:\r\n\r\nVoi prezenta mai jos o rafinare a soluţiei în trei paşi.\r\n\r\nPrima rezolvare se găseşte uşor, deoarece nu facem decât să urmărim textul: pentru fiecare poziţie $i$ fixată ({$i$} ia valorile $1$, $2$, ..., $N$ succesiv) vom considera toate secvenţele candidate la rezultatul final, adică vom plimba un $j$ între poziţiile $i - Y + 1$ şi $i - X + 1$. Pentru un interval $[j, i]$ vom determina $MAX$ şi $MIN$ în $O(log N)$ cu un arbore de intervale, iar dacă diferenţa dintre acestea nu depăşeşte $Z$ vom compara rezultatul cu cel obţinut până în acel moment. Complexitatea finală va fi $O(N * (Y - X) * log N)$.\r\n\r\nCum se cere secvenţa de lungime maximă, pentru fiecare poziţie $i$ trebuie găsit indicele $j$ cât mai mic cuprins între $i - Y + 1$ şi $i - X + 1$ astfel încât secvenţa $[j, i]$ să fie candidată la soluţie. Ce proprietăţi are indicele $j$?\r\n\r\n* $i - Y + 1 &le; j &le; i - X + 1$ şi $MAX - MIN &le; Z$;\r\n* având $i$-ul fixat, dacă trecem de la $j$ la $j + 1$, maximul poate scădea, iar minimul poate creşte, dar în mod sigur diferenţa lor va rămâne mai mică sau egală cu $Z$; soluţia astfel obţinută este mai scurtă, deci nu îmbunătăţeşte soluţia obţinută anterior.\r\n* dacă trecem de la $i$ la $i + 1$, cel mai mic $j$ găsit la pasul anterior poate ori să nu corespundă celor două restricţii (caz în care îl incrementăm cât timp $j < i - Y + 2$ sau $MAX - MIN > Z$), ori să corespundă şi atunci este cel mai mic care să respecte proprietăţile pentru $i + 1$.\r\n\r\nPentru determinarea lui $MAX$, respectiv lui $MIN$ pe fiecare interval $[j, i]$, se poate folosi un arbore de intervale. Complexitatea finală va fi $O(N * log N)$.\r\n\r\nSă vedem cum putem îmbunătăţi complexitatea $O(log N)$ pentru determinarea maximului şi minimului. Mai jos vom vedea algoritmul pentru a-l calcula pe $MAX$, cazul lui $MIN$ fiind similar. Observaţia care ne ajută în multe probleme pentru reducerea complexităţii de la $O(log N)$ la $O(1)$ este, asemănător problemei precedente, următoarea:\r\n\r\n_Observaţie_: Fie $[j, i]$ un interval de interes şi $i{~1~}$ şi $i{~2~}$ doi indici astfel încât $j &le; i{~1~} < i{~2~} &le; i$. Atunci, dacă $S[i{~1~}] < S[i{~2~}]$ poziţia $i{~2~}$ va fi întotdeauna preferată poziţiei $i{~1~}$ atâta timp cât cele două poziţii vor fi în acelaşi interval de interes. Aşadar putem renunţa la $i{~1~}$ pentru etapele următoare, eliminându-l. Dacă, însă, $S[i{~1~}] &ge; S[i{~2~}]$, atunci poziţia $i{~1~}$ \"va umbri\" poziţia $i{~2~}$ atâta timp cât cele două poziţii vor fi în intervalul de forma $[j, i]$. În schimb, când $i{~1~}$ va fi eliminat, $i{~2~}$ are şansa să fie un candidat la $MAX$ dintre restul elementelor de la dreapta sa. În acest caz, vom păstra ambele poziţii şi pentru paşii următori.\r\n\r\nRezultă din această observaţie, analog \'problemei anterioare\':deque-si-aplicatii#problema-2, că în intervalul $[j, i]$ se va forma un şir de poziţii $i{~1~} < i{~2~} < ... < i{~k~}$ astfel încât $S[i{~1~}] &ge; S[i{~2~}] &ge; ... &ge; S[i{~k~}]$, din care extragem $MAX$ ca fiind $S[i{~1~}]$. Folosind iarăşi structura de date $deque$, complexitatea algoritmului va fi $O(N)$.\r\n\r\nÎn pseudocod, algoritmul va arăta în felul următor:\r\n\r\n== code(cpp) |\r\n// S şirul de numere iniţial şi N lungimea sa\r\n\r\n// Subalgoritmul push() inserează în deque poziţia p din şirul S în conformitate cu\r\n// funcţia booleană fct, o funcţie generică\r\nSubalgoritmul push(deque, întreg p, funcţia fct) este:\r\n    cât timp (!deque.empty() şi fct(S[p], S[deque.back()])) execută\r\n        deque.pop_back();\r\n    deque.push_back(p);\r\nSfârşit;\r\n\r\n// Funcţia query() întoarce numărul din S corespunzător primului indice\r\n// din deque aflat în intervalul de interes [j, i].\r\nFuncţia query(deque, întreg j) este:\r\n    cât timp (!deque.empty() şi deque.front() < j) execută\r\n        deque.pop_front();\r\n    return S[deque.front()];\r\nSfârşit;\r\n\r\nAlgoritmul este:\r\n    lg = 0; j = 1;\r\n    pentru i = 1, N execută\r\n        // funcţia min(a, b) întoarce true dacă a < b\r\n        push(min_deq, i, min);\r\n        // funcţia max(a, b) întoarce true dacă a > b\r\n        push(max_deq, i, max);\r\n        cât timp ((j <= i - Y sau query(max_deq, j) - query(min_deq, j) > Z) şi j <= i - X + 1) execută\r\n            j = j + 1;\r\n        // [j, i] este intervalul candidat la soluţia optimă pentru poziţia i\r\n        dacă (j <= i - X + 1) şi (query(max_deq, j) - query(min_deq, j) <= Z) atunci\r\n            dacă (lg >= i - j + 1) atunci\r\n                lg = i - j + 1, start = j, stop = i;\r\n    sfârşit_pentru\r\n\r\n    dacă (lg > 0) atunci\r\n        soluţia este (lg, start, stop);\r\n    altfel\r\n        nu există soluţie;\r\nSfârşit.\r\n==\r\n\r\nh2(#problema-4). 4. \'Platforma\':http://campion.edu.ro/problems/3/509/platforma_ro.htm (.campion, 2009)\r\n\r\nbq. Se dă o matrice $P$ de dimensiuni $M x N$ cu elemente numere întregi. Se defineşte valoarea maximă dintr-un dreptunghi de dimensiuni $R x C$ ca fiind valoarea maximă dintre elementele aflate în acel dreptunghi.\r\nCerinţă: Să se găsească un dreptunghi de dimensiuni $R x C$ cu valoarea maximă minimă.\r\nRestricţii: $1 &le; M, N &le; 1000$, $1 &le; R &le; M$, $1 &le; C &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nAceastă problemă reprezintă o extindere în două dimensiuni a problemei anterioare \'Vila 2\':deque-si-aplicatii#problema-2, unde am studiat cazul unidimensional al determinării pe un vector a maximului / minimului pentru fiecare subsecvenţă de o lungime fixată.\r\n\r\nCerinţa constă în amplasarea unui dreptunghi $R x C$ astfel încât valoarea maximă din interiorul său să fie cât mai mică. Una din ideile simple constă în fixarea colţului din stânga sus în toate cele $(M - R + 1) x (N - C + 1)$ poziţii şi determinarea maximului din interiorul său cu o altă parcurgere a celor $R x C$ elemente. Putem, în schimb, să fixăm o linie $i$, iar pentru a fixa colţul din stânga sus mai iterăm cu un indice $j$ între coloanele $1$ şi $N - C + 1$. De aici devine clar că atunci când avansăm indicele coloanei, în dreptunghiul curent apare o nouă coloană, $j + C$, şi dispare coloana $j$. Dacă pentru fiecare coloană $j$ de pe linia curentă $i$ reţinem un $Max{~i,j~}$ egal cu maximul dintre elementele $P{~i,j~}, P{~i+1,j~}, ..., P{~i+R-1,j~}$, atunci pe linia fixată $i$ vom avea un vector din $N$ elemente (numărul de coloane al matricei $P$) alcătuit din valorile $Max{~i,1~}, Max{~i,2~}, Max{~i,3~}, ..., Max{~i,j~}, ..., Max{~i,N-1~}, Max{~i,N~}$. Iar pe acest vector va trebui să determinăm pentru fiecare subsecvenţă de $C$ elemente, valoarea maximă. Dintre toate subsecvenţele o vom alege pe cea cu valoarea maximă cea mai mică. Iar acest rezultat va fi o soluţie pentru linia fixată. Cu valorile din $Max$ precalculate, pentru fiecare linie avem complexitatea $O(N)$, deci $O(M * N)$ pentru întreaga matrice. Însă, implementând direct, valorile din $Max$ se calculează în $O(M * N * R)$. Mai sus am definit $Max{~i,j~}$ ca fiind maximul dintre $P{~i,j~}, P{~i+1,j~}, ..., P{~i+R-1,j~}$. Rezultă că $Max{~i+1,j~}$ este maximul dintre $P{~i+1,j~}, P{~i+2,j~}, ..., P{~i+R-1,j~}, P{~i+R,j~}$, adică maximul dintre elementele lui $Max{~i,j~}$ din care scoatem $P{~i,j~}$ şi adăugăm $P{~i+R,j~}$. De aici deducem că pentru fiecare coloană fixată, valorile lui $Max$ de pe coloana respectivă se reduc la a determina pentru fiecare subsecvenţă de lungime $R$ (numărul de linii al dreptunghiului de amplasat) elementul maxim. Aceste rezultate se obţin în $O(M)$ pentru fiecare coloană, deci $O(N * M)$ în total.\r\n\r\nRezultă complexitatea finală $O(M * N)$.\r\n\r\nh2(#problema-5). 5. \'Trans\':problema/trans (ONI 2004)\r\n\r\nbq. Se dau $N$ blocuri de piatră, de culoare albă sau neagră aşezate în ordinea $1$, $2$, ..., $N$. Blocurile de piatră trebuie să fie transportate în ordinea în care sunt, iar pentru aceasta va trebui închiriat un camion. Se mai dau $Q$ tipuri de camioane. Camionul de tipul $i (1 &le; i &le; Q)$ poate transporta maxim $K{~i~}$ blocuri de piatră la un moment dat şi pentru un transport se percepe taxa $T{~i~}$. Se impune condiţia ca toate blocurile de piatră plasate în camion la un transport sa aibă aceeaşi culoare. Aşadar, pentru a fi transportate toate blocurile, se va alege un camion de un anumit tip, iar camionul va efectua unul sau mai multe transporturi. Pentru a micşora suma totală plătită, există posibilitatea de a schimba culoarea oricărui bloc de piatră (din alb în negru sau din negru în alb); pentru fiecare bloc $i (1 &le; i &le; N)$ se cunoaşte suma $S{~i~}$ ce trebuie plătită pentru a-i schimba culoarea $C{~i~}$.\r\nCerinţă: Pentru fiecare dintre cele $Q$ tipuri de camioane, determinaţi suma minimă plătită pentru a transporta toate cele $N$ blocuri.\r\nRestricţii: $1 &le; N &le; 16.000$, $1 &le; Q &le; 100$, $1 &le; K{~i~} &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se bazează pe găsirea unei formule de recurenţă ce respectă principiul optimalităţii specific metodei programării dinamice.\r\n\r\nPentru început, fixăm un camion dintre cele <tex> Q </tex>. Fie <tex> K </tex> numărul maxim de pietre pe care acesta le poate transporta şi <tex> T </tex> taxa percepută. Notăm <tex> sum_{i,c} </tex> costul pentru a schimba toate pietrele <tex> 1, 2, \\ldots, i </tex> în culoarea <tex> c </tex> (<tex> c = 0 </tex> pentru alb şi <tex> c = 1 </tex> pentru negru). Rezultă că în <tex> sum_{i,c} </tex> se vor însuma toate valorile <tex> S_{j} </tex>, cu <tex> j \\le i </tex> pentru care <tex> C_{j} = 1 - c </tex>. \r\n\r\nÎn continuare, considerăm <tex> bst_{i,c} </tex> costul minim pentru a transporta pietrele <tex> 1, 2, \\ldots, i </tex>, iar ultimul transport conţine pietre de culoare <tex> c </tex>. Întrucât nu putem transporta mai mult de <tex> K </tex> pietre, <tex> bst_{i,c} </tex> depinde doar de poziţiile <tex> i - K, i - K + 1, \\ldots, i - 1 </tex>. Cunoaştem că ultimul camion va transporta o secvenţă continuă de pietre începând de la o poziţie <tex> j + 1 </tex> până la poziţia <tex> i </tex>, unde <tex> i - K \\le j \\le i - 1 </tex>. Astfel, pentru fiecare <tex> j </tex> în intervalul precedent, costul va fi <tex> Min(bst_{j,0}, bst_{j,1}) </tex> (transportăm primele <tex> j </tex> pietre cât mai ieftin) adunat cu <tex> sum_{i,c} - sum_{j,c} </tex> (costul transformării pietrelor <tex> j + 1, \\ldots, i </tex> în culoarea <tex> c </tex>) şi plus taxa <tex> T </tex>. Rezultă recurenţa:\r\n\r\n* <tex> bst_{i,c} = Min\\ \\{\\ Minim(bst_{j,0},\\ bst_{j,1}) + sum_{i,c} - sum_{j,c} + T\\ :\\ i - K \\le j \\le i - 1\\ \\}; </tex>\r\n\r\nDacă ne vom opri aici, complexitatea soluţiei va fi <tex> O(Q * N^{2}) </tex>.\r\n\r\nRelaţia de recurenţă poate fi îmbunătăţită. Observăm că pentru poziţia <tex> i </tex>, <tex> sum_{i,c} </tex> este o valoare constantă, ca şi <tex> T </tex>. Astfel, deducem următoarea relaţie de recurenţă:\r\n\r\n* <tex> bst_{i,c} = Min\\ \\{\\ Minim(bst_{j,0},\\ bst_{j,1}) - sum_{j,c}\\ :\\ i - K \\le j \\le i - 1\\ \\} + sum_{i,c} + T; </tex>\r\n\r\nNotez în continuare, pentru uşurinţă în scriere, <tex> T_{j,c} = Min(bst_{j,0}, bst_{j,1}) - sum_{j,c} </tex>. Să fixăm doi indici <tex> i_{1} </tex> şi <tex> i_{2} </tex>, astfel încât <tex> i - K \\le i_{1} < i_{2} \\le i - 1 </tex>. Dacă <tex> T_{i_{1},c} > T_{i_{2},c} </tex> atunci întotdeauna poziţia <tex> i_{2} </tex> va fi preferată poziţiei <tex> i_{1} </tex>. Când cele două nu se vor mai afla ambele în intervalul <tex> [i - K, i - 1] </tex>, poziţia eliminată va fi poziţia <tex> i_{1} </tex>. Dacă <tex> T_{i_{1},c} \\le T_{i_{2},c} </tex>, atunci nu putem decide care poziţie este mai bună în viitor, aşa că le vom păstra pe ambele. Rezultă mai departe, după cum am arătat în problemele anterioare, că în intervalul <tex> [i - K, i - 1] </tex> vom avea o serie de indecşi candidaţi la minim <tex> i - K \\le i_{1} < i_{2} < \\ldots < i_{n} \\le i - 1 </tex> astfel încât <tex> T_{i_{1},c} \\le T_{i_{2},c} \\le  ... \\le T_{i_{n},c} </tex>. Mai departe, găsim <tex> bst_{i,c} = T_{i_{1},c} + sum_{i,c} + T </tex>. Urmează să îl introducem şi pe <tex> T_{i,c} </tex> în şirul de indecşi de mai sus, el fiind egal cu <tex> Minim(bst_{i,0}, bst_{i,1}) - sum_{i,c} </tex>. Acest lucru se va face în felul următor: se vor elimina din <tex> i_{n}, , i_{n-1}, \\ldots </tex> atâta timp cât <tex> T_{i_{n},c} > T_{i,c} </tex>, <tex> T_{i_{n-1},c} > T_{i,c} \\ldots </tex> adică atâta timp cât poziţia <tex> i </tex> este preferată lui <tex> i_{n}, i_{n-1}, \\ldots </tex>. Fiind la poziţia <tex> i + 1 </tex>, intervalul se va transforma în <tex> [i - K + 1, i] </tex>, aşadar, vom mai elimina din primii indici <tex> i_{1}, i_{2}, \\ldots </tex> atâta timp cât <tex> i_{1} < i - K + 1, i_{2} < i - K + 1, \\ldots </tex>.\r\n\r\nDupă cum am arătat şi la problema precedentă, acest şir de indecşi <tex> i_{1}, i_{2}, \\ldots, i_{n} </tex> are proprietatea că este un şir continuu de numere care admite inserări şi ştergeri pe la capete ({$head$} şi {$tail$}), şir ce poate fi reprezentat printr-un deque. Cum fiecare index dintre <tex> 1, 2, \\ldots, N </tex> va fi adăugat şi şters cel mult o singură dată din deque, complexitatea soluţiei va fi <tex> O(N) </tex> pentru fiecare camion, deci <tex> O(Q * N) </tex> în total.\r\n\r\nIată şi o sursă scurtă, clară şi eficientă pentru această problemă:\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\n#include <vector>\r\n#include <deque>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\nconst char iname[] = \"trans.in\";\r\nconst char oname[] = \"trans.out\";\r\n\r\n#define MAXN  16005\r\n#define Min(a, b) ((a) < (b) ? (a) : (b))\r\n#define FOR(i, a, b)  for (int i = (a); i <= (b); ++i)\r\n\r\nint C[MAXN], S[MAXN], bst[MAXN][2], sum[MAXN][2], N;\r\n\r\nvoid insert(deque < pair <int, int> >& deq, const pair <int, int>& p) {\r\n    while (!deq.empty() && deq.back().second > p.second)\r\n        deq.pop_back();\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque < pair <int, int> >& deq, const int idx) {\r\n    while (deq.front().first < idx)\r\n        deq.pop_front();\r\n    return deq.front().second;\r\n}\r\n\r\nint work(const int K, const int T) {\r\n    deque < pair <int, int> > deq[2];       // pair (idx, value)\r\n    FOR (c, 0, 1)\r\n        insert(deq[c], pair <int, int>(0, 0));\r\n    FOR (i, 1, N) {   // obiectul i\r\n        FOR (c, 0, 1) // culoare\r\n            bst[i][c] = query(deq[c], i - K) + sum[i][c] + T;\r\n        FOR (c, 0, 1)\r\n            insert(deq[c], pair <int, int>(i, Min(bst[i][0], bst[i][1]) - sum[i][c]));\r\n    }\r\n    return Min(bst[N][0], bst[N][1]);\r\n}\r\n\r\nint main(void) {\r\n    ifstream in(iname);  ofstream out(oname);\r\n    in >> N;\r\n    FOR (i, 1, N) {\r\n        in >> C[i] >> S[i];\r\n        FOR (c, 0, 1)\r\n            sum[i][c] += sum[i - 1][c];\r\n        sum[i][1 - C[i]] += S[i];\r\n    }\r\n    int cnt, K, T;\r\n    in >> cnt;\r\n    FOR (i, 1, cnt)\r\n        in >> K >> T, out << work(K, T) << \"\\n\";\r\n\r\n    in.close(), out.close();\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#problema-6). 6. \'Otilia\':problema/otilia  (.campion, 2005)\r\n\r\nbq. Otilia şi Burbucel au o grămadă de $N$ pietre şi vor juca un joc cu următoarele trei reguli: 1. Primul jucător are voie să ia din gramadă cel mult $K$ piese; 2. Cu excepţia primei mutări, fiecare jucător are voie să ia maxim $P * t$ pietre, unde $t$ este numărul de pietre care au fost substituite din grămadă la mutarea precedentă; 3. Pierde cel care mută ultimul (cel care ia ultimele pietre din grămadă).\r\nCerinţă: Se dau $M$ jocuri prin numerele $N$, $K$ şi $P$. Se cere să se determine pentru fiecare joc dacă Otilia va câştiga sau nu.\r\nRestricţii: $1 &le; M &le; 30.000$, $1 &le; N &le; 5.000.000$, $1 &le; K &le; N$, $1 &le; P &le; 10$.\r\n\r\nh3. Soluţie (Silviu Gănceanu):\r\n\r\nProblema se rezolvă prin programare dinamică. Soluţia se bazează pe observaţia de mai jos. Considerăm $P$-ul fixat şi notăm cu $stare(X, Y)$ poziţia de start în care avem $X$ pietre şi numărul maxim de pietre care se pot lua la prima mutare este $Y$.\r\n\r\n_Observaţia 1_: „Dacă există strategie sigură de câştig pentru $stare(X, Y)$ atunci există şi pentru orice $stare(X, T)$ cu $T &ge; Y$.” \r\n\r\nDe ce? Pentru că orice mutare validă pentru $stare(X, Y)$ este validă şi pentru $stare(X, T)$. Având această observaţie notăm cu $MinY[X] = Y$, $Y$ minim astfel încât avem strategie de câştig pentru $stare(X, Y)$.\r\n\r\n_Observaţia 2_: „{$stare(X, Y)$} este pierzătoare dacă şi numai dacă $Y < MinY[X]$.” \r\n\r\nAceasta reiese din definiţia lui $MinY[X]$.\r\n\r\n$MinY[X]$ se calculează după următoarea recurenţă, care rezultă din regulile jocului: \r\n\r\n* $MinY[X]$ este cel mai mic $i$ pentru care avem $MinY[X - i] > P * i$.\r\n\r\nDe aici se naşte prima soluţie, care este implementarea directă a recurenţei. Deşi complexitatea acesteia pare a fi $O(N^2^)$ ea se comportă foarte bine pentru $N &le; 500 000$. Aşadar, această soluţie acoperă aproximativ $50%$ din testele de intrare. Printr-o rafinare a acestei soluţii se obţine un algoritm de complexitate $O(N)$. Rafinarea se bazează pe: \r\n\r\n_Observaţia 3_: „Să presupunem că dorim să calculăm $MinY[X]$. Facem următoarea afirmaţie: orice poziţie _rea_ pentru $X$ (în care dacă mutăm pierdem) va fi _rea_ şi pentru $X + 1$.”\r\n\r\nAcest lucru este simplu de observat dacă privim ce înseamnă că o poziţie $Q$ e rea pentru $X$: \r\n\r\n* $MinY[Q] > X - Q$, pentru $X$;\r\n* $MinY[Q] > X - Q + 1$, pentru $X + 1$.\r\n\r\nEste evident că prima relaţie o implică pe cea de-a doua. În momentul acesta se poate construi următorul algoritm: având lista de poziţii care pot fi bune pentru $X$ (sortată descrescător) o căutăm pe cea mai mare ca valoare care este într-adevăr bună. În principiu, scoatem din capul listei poziţiile rele până când dăm de o poziţie bună. La listă se va adăuga şi $X$ şi se va trece la pasul următor. Operaţiile algoritmului sunt chiar operaţiile asupra unui deque.\r\n\r\nh2(#problema-7). 7. \'Bcrc\':problema/bcrc (Stelele Informaticii, 2006)\r\n\r\nbq. Se consideră $N$ camere, numerotate de la $1$ la $N$, aşezate în cerc. Iniţial (la momentul de timp 0), ne aflăm în camera $1$. În fiecare moment de timp, putem alege să rămânem în camera în care ne aflăm sau să ne deplasăm într-o cameră vecină într-o unitate de timp. Se dă o listă de $M$ cutii ce conţin bomboane prin $T$, $C$ şi $B$: cutia apare la momentul $T$ în camera $C$ şi conţine $B$ bomboane. Cutia va dispărea la momentul $T + 1$.\r\nCerinţă: Cunoscând numărul de camere din labirint şi momentele de timp la care apar cutiile cu bomboane, determinaţi care este numărul maxim de bomboane pe care le putem culege.\r\nRestricţii: $3 &le; N &le; 2.048$, $0 &le; M &le; 50.000$, $1 &le; T &le; 1.000.000.000$, $1 &le; C &le; N$, $1 &le; B &le; 9.999$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia foloseşte metoda programării dinamice.\r\n\r\nO stare se reprezintă prin camera în care ne aflăm şi momentul de timp. Fie <tex> bst_{i,j} </tex> numărul maxim de bomboane culese până în momentul <tex> i </tex> când ne găsim în camera <tex> j </tex>. O observaţie evidentă este că <tex> bst_{i,j} </tex> se poate modifica doar în momentele în care apar cutiile. Prin urmare, vom considera momentele de timp când apar cutiile, momente ce sunt în număr de <tex> M </tex>, <tex> bst_{i,j} </tex> însemnând numărul maxim de bomboane culese ştiind că ne aflăm în camera <tex> j </tex> după ce am cules cutia <tex> i </tex>. De cine depinde această stare? Ştim că <tex> bst_{i-1,1 \\ldots N} </tex> a fost deja calculat în mod optim. Să notăm cu <tex> T </tex> diferenţa de timp dintre momentele la care apar cutia <tex> i </tex> şi cutia <tex> i - 1 </tex>. În această stare, cutie <tex> i </tex> şi cameră <tex> j </tex>, putem ajunge din maxim <tex> T </tex> camere spre stânga sau spre dreapta, întrucât fiecare deplasare între două camere costă o unitate de timp. De unde deducem că:\r\n\r\n* <tex> bst_{i,j} = Max\\{\\ bst_{i-1,j-T},\\ bst_{i-1,j-T+1}, \\ldots,\\ bst_{i-1,j}, \\ldots,\\ bst_{i-1,j+T-1},\\ bst_{i-1,j+T}\\ \\}; </tex>\r\n\r\nMetoda directă, şi aparent eficientă, constă în folosirea unui arbore de intervale pentru aflarea acestui maxim. Însă, intervalul <tex> [j-T,j+T] </tex> se deplasează constant spre dreapta, dacă vom considera indicii <tex> j </tex> în ordine <tex> 1, 2, 3, \\ldots </tex>. În acest interval noile elemente se introduc prin dreapta şi altele se elimină prin stânga. Însă, cum am arătat în problemele precedente, nu avem nevoie de toate valorile din acest interval. Şi din acest motiv vom folosi un deque de lungime maximă <tex> T * 2 + 1 </tex> cu care vom elimina poziţiile care nu sunt candidate la soluţie. Mai jos este o reprezentare grafică a deplasării intervalului menţionat mai sus.\r\n\r\np=. !deque-si-aplicatii?bcrc.png 40%!\r\n\r\nComplexitatea finală: <tex> O(M * N) </tex>.\r\n\r\nh2(#problema-8). 8. \'Cut the Sequence\':http://acm.pku.edu.cn/JudgeOnline/problem?id=3017 (PKU) \r\n\r\nbq. Se dă o secvenţă $S$ de $N$ numere întregi. Va trebui să se împartă secvenţa în mai multe subsecvenţe astfel încât suma valorilor din fiecare parte să nu depăşească un număr întreg $M$ dat, iar dacă însumăm maximul din fiecare subsecvenţă să obţinem o sumă cât mai mică.\r\nRestricţii: $0 &lt; N &le; 100.000$, $0 &le; S{~i~} &le; 1.000.000$.\r\n\r\nh3. Soluţie:\r\n\r\nŞi această soluţie foloseşte metoda programării dinamice. Construim <tex> bst_{i} </tex> egal cu costul minim de a împărţi primele <tex> i </tex> numere din <tex> S </tex>. Pentru a calcula <tex> bst_{i} </tex> alegem toate secvenţele posibile care încep la o poziţie <tex> j+1 </tex>, <tex> j < i </tex>, şi adunăm valorile corespunzătoare:\r\n\r\n* <tex> bst_{i} = Min\\{bst_{j} + Max\\{S_{j+1},.., S_{i}\\}\\ :\\ 0 \\le j < i, \\displaystyle\\sum_{k=j+1}^{i} S_{k} \\le M\\}; </tex>\r\n\r\nImplementarea directă a acestei recurenţe conduce la un algoritm de complexitate <tex> O(N^{2}) </tex>, dar care pentru restricţiile impuse nu este de ajuns.\r\n\r\nSă obţinem în continuare alte informaţii. Fie indicele <tex> j </tex> minim astfel încât <tex> \\displaystyle\\sum_{k=j+1}^{i} \\le M </tex>. Maximul obţinut din mulţimea <tex> \\{S_{j+1},.., S_{i}\\} </tex> se găseşte pe o poziţie <tex> j^{\'} </tex> unde <tex> j < j^{\'} \\le i </tex>. Însă, orice indice <tex> k </tex> cu <tex> j \\le k < j^{\'} </tex> are proprietatea că rezultatul expresiei <tex> Max\\{S_{k+1},.., S_{i}\\} </tex> se găseşte pe poziţia <tex> j^{\'} </tex>. Rezultă că <tex> \\forall k \\in \\{j, j+1,.., j^{\'}-1\\} </tex>, <tex> bst_{i} </tex> poate fi îmbunătăţit cu valoarea <tex> bst_{k} + S_{j^{\'}} </tex>. Minimul mulţimii <tex> \\{bst_{k} + S_{j^{\'}} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} </tex> este egal cu minimul expresiei <tex> \\{bst_{k} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} + S_{j^{\'}} (*) </tex>, deci, schimbând reperele, pentru maximul de pe poziţia <tex> j^{\'} </tex>, dacă lungimea secvenţei care se termină în <tex> i </tex> este cel puţin <tex> i-j^{\'}+1 </tex>, atunci optimul se obţine calculând rezultatul expresiei <tex> (*) </tex>. Pentru minimul valorilor vectorului <tex> bst </tex> pe un interval <tex> [j, j^{\'}-1] </tex> putem folosi un arbore de intervale pentru <tex> O(log_{2}N) </tex> pe interogare.\r\n\r\nDar, lungimea optimă a ultimei secvenţe ce se termină în <tex> i </tex> poate fi mai mică decât <tex> i-j^{\'}+1 </tex>, deci poate fi cel mult <tex> i-j^{\'} </tex>. Optimul se găseşte printre elementele mulţimii <tex> \\{bst_{k} + Max\\{S_{k+1},..,S_{i}\\} : j^{\'} \\le k < i\\} </tex>. Dacă procedăm ca la pasul anterior vom obţine un alt indice <tex> j^{\'\'} </tex> cu aceleaşi proprietăţi pentru secvenţa <tex> [j^{\'}, i] </tex> precum <tex> j^{\'} </tex> pentru secvenţa <tex> [j, i] </tex>.\r\n\r\nInductiv obţinem un şir de indici <tex> j_{0} = j < j_{1} < j_{2} < .. < j_{K} = i </tex> astfel încât <tex> S_{j_{1}} </tex> este cel mai mare element al secvenţei <tex> (j, i] </tex>, <tex> S_{j_{2}} </tex> cel mai mare element al secvenţei <tex> (j_{1}, i] </tex>, şi aşa mai departe, când <tex> j_{K} </tex> este chiar <tex> i </tex>.\r\n\r\nCu ajutorul relaţiei <tex> (*) </tex> şi a şirului <tex> j_{1} < j_{2} < .. < j_{K} = i </tex> vom construi un alt vector <tex> iMin </tex> cu proprietatea că <tex> iMin_{p} = Min\\{bst_{r} + S_{j_{p}} : j_{p-1} \\le r < j_{p}\\} </tex>. În final, <tex> bst_{i} = Minim\\{iMin_{1}, iMin_{2}, .., iMin_{K}\\} </tex>, rezultat pe care îl putem obţine în <tex> O(log_{2}N) </tex> dacă folosim un arbore de intervale.\r\n\r\nÎnsă, cum se construieşte şirul <tex> j_{1} < j_{2} < .. < j_{K} = i </tex>? În \'a doua problemă\':deque-si-aplicatii#problema-2 am construit cu ajutorul unui deque exact şirul de indici de care avem nevoie aici. Când vom înainta la indicele <tex> i + 1 </tex> vom modifica şirul astfel încât să respecte proprietăţile de mai sus utilizând operaţiile normale asupra unui deque. Mai sus am menţionat cum se obţine <tex> bst_{i} </tex> lucru care implică combinarea structurilor de deque şi arbore de intervale. Arborele de intervale reţine valorile lui <tex> iMin </tex> pentru fiecare element al deque-lui. \r\n\r\nPentru a înţelege cum funcţionează acest algoritm să considerăm ca date de intrare şirul <tex> S = \\{5, 9, 4, 7, 4, 1, 6, 3\\} </tex> şi <tex> M = 15 </tex>. Perechile din deque sunt de forma <tex> (S_{i}, iMin_{p}) </tex>. Fie <tex> i = 1, 2, \\ldots 8 </tex>:\r\n\r\n* <tex> i = 1: j = 0, head = 1, tail = 1, deque = \\{\\ (5, 0)\\ \\} \\Rightarrow bst_{1} = 5; </tex>\r\n* <tex> i = 2: j = 0, head = 1, tail = 1, deque = \\{\\ (9, 0)\\ \\} \\Rightarrow bst_{2} = 9; </tex>\r\n* <tex> i = 3: j = 1, head = 1, tail = 2, deque = \\{\\ (9, 5),\\ (4, 9)\\ \\} \\Rightarrow bst_{3} = 13; </tex>\r\n* <tex> i = 4: j = 2, head = 2, tail = 2, deque = \\{\\ (7, 9)\\ \\} \\Rightarrow bst_{4} = 16; </tex>\r\n* <tex> i = 5: j = 2, head = 2, tail = 3, deque = \\{\\ (7, 9),\\ (4, 16)\\ \\} \\Rightarrow bst_{5} = 16; </tex>\r\n* <tex> i = 6: j = 3, head = 2, tail = 4, deque = \\{\\ (7, 13),\\ (4, 16),\\ (1, 16)\\ \\} \\Rightarrow bst_{6} = 17; </tex>\r\n* <tex> i = 7: j = 4, head = 3, tail = 3, deque = \\{\\ (6, 16)\\ \\} \\Rightarrow bst_{7} = 22; </tex>\r\n* <tex> i = 8: j = 4, head = 3, tail = 4, deque = \\{\\ (6, 16),\\ (3, 22)\\ \\} \\Rightarrow bst_{8} = 22; </tex>\r\n\r\nMai jos se vede o figură în care elementele unui deque sunt de fapt o secvenţă \"continuă\" de frunze ale unui arbore de intervale pentru cazul <tex> i = 6 </tex>.\r\n\r\np=. !deque-si-aplicatii?PKU0.png 60%!\r\n\r\np=. _Numărul maxim de elemente ce pot trece prin deque este $8$. În figură, arborele ţine minimul de pe poziţiile $2$, $3$, $4$ din deque._\r\n\r\nAlgoritmul în pseudocod arată în felul următor:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    sum  = 0;\r\n    last = 0;\r\n    // indicii head si tail ai dequeului\r\n    head = tail = 1;\r\n    // poziţia lui bst[0] se inserează în deque\r\n    deque[1] = 0;\r\n    pentru i = 1, N execută\r\n        sum += S[i];\r\n        temp = bst[ deque[tail] ];\r\n        cât timp (head <= tail) şi (S[ deque[tail] ] <= S[i]) execută\r\n            temp = Min(temp, iMin[tail]);\r\n            tail--;\r\n        sfârşit;\r\n        // adaug poziţia i la deque\r\n        tail++;\r\n        deque[tail] = i;\r\n        // actualizez iMin[]\r\n        iMin[tail]  = temp;\r\n        // actualizez T[], arborele de intervale pe deque[]\r\n        Update(T, tail, iMin[tail] + S[i]);\r\n        // suma valorilor din [last, i] trebuie să nu depăşească M\r\n        cât timp (sum > M) execută\r\n            sum -= S[last];\r\n            dacă (deque[head] == last) atunci\r\n                head++;\r\n            sfârşit;\r\n            last++;\r\n        sfârşit;\r\n        // actualizez iMin[], Tb[] arborele de intervale pe bst[]\r\n        iMin[head] = Query(Tb, Max(last - 1, 0), deque[head] - 1);\r\n        // actualizez T[]\r\n        Update(T, head, iMin[head] + S[ deque[head] ]);\r\n        // reţin optimul pentru poziţia curentă\r\n        bst[i] = Query(T, head, tail);\r\n        // actualizez Tb[]\r\n        Update(Tb, i, bst[i]);\r\n    sfârşit;\r\n    scrie bst[N];\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală este <tex> O(N*log_{2}N) </tex>.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nFilozofia din spatele structurii de deque devine utilă, de obicei, în părţile finale ale rezolvării unei probleme. Însă, ce pot spune cu certitudine este că această structură de date, pe cât este de simplă, pe atât este de eficientă şi necesară.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\nÎnţelegerea profundă nu se poate realiza decât prin rezolvarea a cât mai multor probleme. Succes!\r\n\r\n* \'Deque\':problema/deque, _Arhiva educaţională_\r\n* \'Secvenţă\':problema/secventa\r\n* \'Secvenţă 3\':problema/secv3\r\n* \'Secvenţă 4\':problema/secv4\r\n* \'Sum 2\':problema/sum2, _Stelele Informaticii, 2003_\r\n* \'Drept 2\':problema/drept2, _Lotul Naţional de Informatică, 2006_\r\n* \'Copaci 2\':problema/copaci2, _.campion, 2007_\r\n* \'Struţi\':problema/struti\r\n* \'Brânză\':problema/branza\r\n* \'Trompetă\':problema/trompeta\r\n* \'Buline\':problema/buline\r\n* \'Balans\':problema/balans\r\n* \'Ksecv\':problema/ksecv, _Selecţie echipe ACM ICPC, UPB, 2008_\r\n* \'Munte4\':problema/munte4, _Lotul Naţional de Informatică, 2005_\r\n* \'Gard\':problema/gard, _ONI, 2002_\r\n* \'Ghiozdan\':problema/ghiozdan\r\n* \'Cover\':problema/cover, _Baraj ONI, 2007_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# D.E. Knuth - \"_The Art of Computer Programming, Volume 1: Fundamental Algorithms, Third Edition_\", Addison-Wesley, 1997\r\n# Cosmin Negruşeri, \"_Probleme cu secvenţe_\":probleme-cu-secvente\r\n# Dana Lica, \"_Arbori de intervale şi aplicaţii în geometria computaţională_\":arbori-de-intervale\r\n# wikipedia, \'_Deque_\':http://en.wikipedia.org/wiki/Deque\r\n# \'C++ Reference\':http://www.cplusplus.com/',3146,'public',3802,NULL),('runda/porc_crop','porc_crop','2010-02-05 17:08:03','2010-02-05 17:08:03','h1. == roundparam(round_id=\"porc_crop\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"porc_crop\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"porc_crop\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"porc_crop\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"porc_crop\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/porc_crop/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"porc_crop\" score=\"1\")==',6333,'round: porc_crop',NULL,NULL),('runda/pentru_clasele_5-8','pentru_clasele_5-8','2009-03-30 10:22:58','2009-03-30 10:22:58','h1. == roundparam(round_id=\"pentru_clasele_5-8\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"pentru_clasele_5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"pentru_clasele_5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"pentru_clasele_5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/pentru_clasele_5-8/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"pentru_clasele_5-8\" score=\"1\")==',7670,'round: pentru_clasele_5-8',NULL,NULL),('runda/pentru_clasele_5-8/clasament','Clasament pentru_clasele_5-8','2009-03-30 10:22:58','2009-03-30 10:22:58','h1. Clasament ==roundparam(round_id=\"pentru_clasele_5-8\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pentru_clasele_5-8\")==',7670,'round: pentru_clasele_5-8',NULL,NULL),('runda/qwerty-4','qwerty-4','2009-03-30 10:46:43','2009-03-30 10:46:43','h1. == roundparam(round_id=\"qwerty-4\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"qwerty-4\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"qwerty-4\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"qwerty-4\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/qwerty-4/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"qwerty-4\" score=\"1\")==',4439,'round: qwerty-4',NULL,NULL),('runda/qwerty-4/clasament','Clasament qwerty-4','2009-03-30 10:46:43','2009-03-30 10:46:43','h1. Clasament ==roundparam(round_id=\"qwerty-4\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"qwerty-4\")==',4439,'round: qwerty-4',NULL,NULL),('runda/qwerty-5/clasament','Clasament qwerty-5','2009-03-30 14:53:30','2009-03-30 14:53:30','h1. Clasament ==roundparam(round_id=\"qwerty-5\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"qwerty-5\")==',4439,'round: qwerty-5',NULL,NULL),('runda/gluma_de_1_aprilie','gluma_de_1_aprilie','2009-03-30 16:16:50','2009-03-31 05:39:21','h1. == roundparam(round_id=\"gluma_de_1_aprilie\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"gluma_de_1_aprilie\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"gluma_de_1_aprilie\" param=\"start_time\" strong=\"true\")==.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/gluma_de_1_aprilie/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"gluma_de_1_aprilie\" score=\"1\")==',6958,'round: gluma_de_1_aprilie',NULL,NULL),('runda/gluma_de_1_aprilie/clasament','Clasament gluma_de_1_aprilie','2009-03-30 16:16:50','2009-03-30 16:16:50','h1. Clasament ==roundparam(round_id=\"gluma_de_1_aprilie\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"gluma_de_1_aprilie\")==',6958,'round: gluma_de_1_aprilie',NULL,NULL),('runda/qwerty-6','qwerty-6','2009-03-31 07:12:17','2009-03-31 07:12:17','h1. == roundparam(round_id=\"qwerty-6\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"qwerty-6\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"qwerty-6\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"qwerty-6\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/qwerty-6/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"qwerty-6\" score=\"1\")==',4439,'round: qwerty-6',NULL,NULL),('runda/qwerty-6/clasament','Clasament qwerty-6','2009-03-31 07:12:17','2009-03-31 07:12:17','h1. Clasament ==roundparam(round_id=\"qwerty-6\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"qwerty-6\")==',4439,'round: qwerty-6',NULL,NULL),('runda/qwerty-7','qwerty-7','2009-03-31 07:15:44','2009-03-31 07:15:44','h1. == roundparam(round_id=\"qwerty-7\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"qwerty-7\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"qwerty-7\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"qwerty-7\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/qwerty-7/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"qwerty-7\" score=\"1\")==',4439,'round: qwerty-7',NULL,NULL),('runda/qwerty-7/clasament','Clasament qwerty-7','2009-03-31 07:15:44','2009-03-31 07:15:44','h1. Clasament ==roundparam(round_id=\"qwerty-7\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"qwerty-7\")==',4439,'round: qwerty-7',NULL,NULL),('runda/infoexpert','infoexpert','2009-03-31 07:37:07','2009-03-31 07:37:07','h1. == roundparam(round_id=\"infoexpert\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"infoexpert\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"infoexpert\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"infoexpert\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/infoexpert/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"infoexpert\" score=\"1\")==',8487,'round: infoexpert',NULL,NULL),('runda/infoexpert/clasament','Clasament infoexpert','2009-03-31 07:37:07','2009-03-31 07:37:07','h1. Clasament ==roundparam(round_id=\"infoexpert\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"infoexpert\")==',8487,'round: infoexpert',NULL,NULL),('runda/qwerty-8','qwerty-8','2009-03-31 10:42:07','2009-03-31 10:42:07','h1. == roundparam(round_id=\"qwerty-8\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"qwerty-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"qwerty-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"qwerty-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/qwerty-8/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"qwerty-8\" score=\"1\")==',4439,'round: qwerty-8',NULL,NULL),('runda/qwerty-8/clasament','Clasament qwerty-8','2009-03-31 10:42:07','2009-03-31 10:42:07','h1. Clasament ==roundparam(round_id=\"qwerty-8\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"qwerty-8\")==',4439,'round: qwerty-8',NULL,NULL),('runda/codegen/clasament','Clasament codegen','2009-03-31 15:45:43','2009-03-31 15:56:20','h1. Clasament ==roundparam(round_id=\"codegen\" param=\"title\") ==\r\n\r\nFelicitari tuturor participantilor la acest concurs!\r\n\r\n==Rankings(rounds = \"codegen\")==',6791,'round: codegen',NULL,NULL),('runda/codegen','Concurs de viteza','2009-03-31 15:45:43','2009-03-31 15:59:56','h1. == roundparam(round_id=\"codegen\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"codegen\") ==\r\n\r\n    \r\n*Concursul este destinat celor care gandesc rapid. Concursul dureaza 1.5 ore si este alcatuit din 3 probleme usoare. Acest concurs testeaza nu numai priceperea in programare ci si puterea de concentrare.\r\n* Nu aveti de castigat nimic daca trisati, ci aveti de castigat daca jucati corect.\r\n* May the best one win!\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/codegen/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"codegen\" score=\"1\")==',6791,'round: codegen',NULL,NULL),('grigore-moisil-2009/5-8','Grigore Moisil 2009, clasele 5-8','2009-03-31 18:55:05','2009-03-31 19:39:41','h1. == roundparam(round_id=\"moisil2009-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':grigore-moisil-2009 \r\n*(active) \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n* \'Rezultate\':grigore-moisil-2009/clasament/5-8\r\n\r\n== roundregister(round_id=\"moisil2009-5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2009-5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2009-5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/moisil2009-5-8/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"moisil2009-5-8\" score=\"1\")==',2092,'protected',NULL,NULL),('runda/moisil2009-5-8/clasament','Clasament moisil2009-5-8','2009-03-31 18:55:05','2009-03-31 18:55:05','h1. Clasament ==roundparam(round_id=\"moisil2009-5-8\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil2009-5-8\")==',2092,'round: moisil2009-5-8',NULL,NULL),('runda/moisil2009-9/clasament','Clasament moisil2009-9','2009-03-31 18:58:39','2009-03-31 18:58:39','h1. Clasament ==roundparam(round_id=\"moisil2009-9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil2009-9\")==',2092,'round: moisil2009-9',NULL,NULL),('grigore-moisil-2009/10','Grigore Moisil 2009, clasa a 10a','2009-03-31 18:59:30','2009-03-31 19:40:50','h1. == roundparam(round_id=\"moisil2009-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':grigore-moisil-2009 \r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n*(active) \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n* \'Rezultate\':grigore-moisil-2009/clasament/5-8\r\n\r\n== roundregister(round_id=\"moisil2009-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2009-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2009-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/moisil2009-10/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"moisil2009-10\" score=\"1\")==',2092,'protected',NULL,NULL),('runda/moisil2009-10/clasament','Clasament moisil2009-10','2009-03-31 18:59:30','2009-03-31 18:59:30','h1. Clasament ==roundparam(round_id=\"moisil2009-10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil2009-10\")==',2092,'round: moisil2009-10',NULL,NULL),('runda/moisil2009-11-12/clasament','Clasament moisil2009-11-12','2009-03-31 19:00:03','2009-03-31 19:00:03','h1. Clasament ==roundparam(round_id=\"moisil2009-11-12\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil2009-11-12\")==',2092,'round: moisil2009-11-12',NULL,NULL),('grigore-moisil-2009','Grigore Moisil 2009','2009-03-31 19:07:10','2009-04-06 08:17:43','h1. Grigore Moisil 2009\r\n\r\n(htabs)*(active) \'Despre...\':grigore-moisil-2009 \r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n* \'Rezultate\':grigore-moisil-2009/clasament/5-8\r\n\r\nInfoarena organizeaza si in acest an editia online a concursului interjudetean de informatica Grigore Moisil. Concurentii pot profita de aceasta ocazie pentru a efectua un ultim test inainte de Olimpiada Nationala. Concursul se va desfasura *Duminica 5 aprilie*, la ora {*09^00^*} si va dura *3h*. Participantii vor avea de rezolvat 2-3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n\r\nSolutiile le poti gasi \'aici\':grigore-moisil-2009/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':grigore-moisil-2009/clasament/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/clasament/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/clasament/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/clasament/11-12\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* prof. Clara Ionescu\r\n* ==User(user=\"SleepyOverlord\" type=\"tiny\")==\r\n* ==User(user=\"Marius\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n',2092,'protected',NULL,NULL),('grigore-moisil-2009/9','Grigore Moisil 2009, clasa a 9a','2009-03-31 18:58:39','2009-03-31 19:39:52','h1. == roundparam(round_id=\"moisil2009-9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':grigore-moisil-2009 \r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n*(active) \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n* \'Rezultate\':grigore-moisil-2009/clasament/5-8\r\n\r\n== roundregister(round_id=\"moisil2009-9\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2009-9\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2009-9\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/moisil2009-9/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"moisil2009-9\" score=\"1\")==',2092,'protected',NULL,NULL),('grigore-moisil-2009/11-12','Grigore Moisil 2009, clasele 11-12','2009-03-31 19:00:03','2009-03-31 19:41:02','h1. == roundparam(round_id=\"moisil2009-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':grigore-moisil-2009 \r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n*(active) \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n* \'Rezultate\':grigore-moisil-2009/clasament/5-8\r\n\r\n== roundregister(round_id=\"moisil2009-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2009-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2009-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/moisil2009-11-12/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"moisil2009-11-12\" score=\"1\")==',2092,'protected',NULL,NULL),('grigore-moisil-2009/clasament/5-8','Clasament Grigore Moisil 2009, clasele 5-8','2009-03-31 19:43:34','2009-03-31 19:43:55','h1. == roundparam(round_id=\"moisil2009-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':grigore-moisil-2009 \r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n*(active) \'Rezultate\':grigore-moisil-2009/clasament/5-8\r\n\r\n&nbsp;\r\n&nbsp;\r\n\r\n(htabs)*(active) \'Clasele 5-8\':grigore-moisil-2009/clasament/5-8\r\n* \'Clasa a 9-a\':grigore-moisil-2009/clasament/9\r\n* \'Clasa a 10-a\':grigore-moisil-2009/clasament/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/clasament/11-12\r\n\r\np<. == Rankings(rounds=\"moisil2009-5-8\") == \r\n\r\n',2092,'protected',NULL,NULL),('grigore-moisil-2009/clasament/9','Clasament Grigore Moisil 2009, clasa a 9a','2009-03-31 19:45:08','2009-03-31 19:45:15','h1. == roundparam(round_id=\"moisil2009-9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':grigore-moisil-2009 \r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n*(active) \'Rezultate\':grigore-moisil-2009/clasament/5-8\r\n\r\n&nbsp;\r\n&nbsp;\r\n\r\n(htabs)* \'Clasele 5-8\':grigore-moisil-2009/clasament/5-8\r\n*(active) \'Clasa a 9-a\':grigore-moisil-2009/clasament/9\r\n* \'Clasa a 10-a\':grigore-moisil-2009/clasament/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/clasament/11-12\r\n\r\np<. == Rankings(rounds=\"moisil2009-9\") == \r\n',2092,'protected',NULL,NULL),('grigore-moisil-2009/clasament/10','Clasament Grigore Moisil 2009, clasa a 10a','2009-03-31 19:45:49','2009-03-31 19:45:49','h1. == roundparam(round_id=\"moisil2009-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':grigore-moisil-2009 \r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n*(active) \'Rezultate\':grigore-moisil-2009/clasament/5-8\r\n\r\n&nbsp;\r\n&nbsp;\r\n\r\n(htabs)* \'Clasele 5-8\':grigore-moisil-2009/clasament/5-8\r\n* \'Clasa a 9-a\':grigore-moisil-2009/clasament/9\r\n*(active) \'Clasa a 10-a\':grigore-moisil-2009/clasament/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/clasament/11-12\r\n\r\np<. == Rankings(rounds=\"moisil2009-10\") == \r\n',2092,'protected',NULL,NULL),('grigore-moisil-2009/clasament/11-12','grigore-moisil-2009/clasament/11-12','2009-03-31 19:46:27','2009-03-31 19:46:27','h1. == roundparam(round_id=\"moisil2009-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':grigore-moisil-2009 \r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n*(active) \'Rezultate\':grigore-moisil-2009/clasament/5-8\r\n\r\n&nbsp;\r\n&nbsp;\r\n\r\n(htabs)* \'Clasele 5-8\':grigore-moisil-2009/clasament/5-8\r\n* \'Clasa a 9-a\':grigore-moisil-2009/clasament/9\r\n* \'Clasa a 10-a\':grigore-moisil-2009/clasament/10\r\n*(active) \'Clasele 11-12\':grigore-moisil-2009/clasament/11-12\r\n\r\np<. == Rankings(rounds=\"moisil2009-11-12\") == \r\n',2092,'protected',NULL,NULL),('runda/drastik_challange_3','drastik_challange_3','2009-04-01 07:08:26','2009-04-01 07:08:26','h1. == roundparam(round_id=\"drastik_challange_3\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"drastik_challange_3\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"drastik_challange_3\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"drastik_challange_3\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/drastik_challange_3/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"drastik_challange_3\" score=\"1\")==',6957,'round: drastik_challange_3',NULL,NULL),('runda/drastik_challange_3/clasament','Clasament drastik_challange_3','2009-04-01 07:08:26','2009-04-01 07:08:26','h1. Clasament ==roundparam(round_id=\"drastik_challange_3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"drastik_challange_3\")==',6957,'round: drastik_challange_3',NULL,NULL),('newsletter/grigore-moisil-2009','Grigore Moisil 2009; Noutăți','2009-04-01 15:32:25','2009-04-01 16:48:56','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎn perioada 3-5 Aprilie se desfăşoară la Satu Mare Concursul Interjudeţean de Informatică _Grigore Moisil_. Pentru al treilea an la rând, infoarena gazduieşte o ediţie online a acestui concurs iar tu eşti invitat să participi.\r\n\r\nMăsoară-ţi forţele cu cei care participă _live_ la concurs şi cu ceilalţi membri infoarena! În plus, la mai puţin de 10 zile înainte de \'ONI\':http://www.activemall.ro/oni2009/, ai nevoie de această ocazie de antrenament şi verificare. Eşti pregătit?\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Concursul se desfăşoară\r\n*Duminică, 5 Aprilie 2009, între orele 09^00^ - 12^00^*. |\r\n\r\nVezi \'pagina concursului\':grigore-moisil-2009 pentru mai multe informaţii.\r\n\r\nMai am o noutate pentru tine - *concursuri virtuale*! Vrei să-ţi faci propriul concurs pe infoarena? Citeşte până la capăt...\r\n\r\n\r\nh2{font-size: 12pt}. Despre concurs\r\n\r\nAcesta este al treilea an când proba de informatică a concursului „Grigore Moisil” se desfăşoară şi online pe infoarena. Suntem foarte bucuroşi să sprijinim intenţia unui concurs regional de a se deschide către participanţi din toată ţara.\r\n\r\nVei avea de rezolvat 2 - 3 probleme de natură algoritmică într-un timp de lucru de 3h. Concursul se împarte pe 4 grupe de vârstă: clasele 5-8, clasa a 9-a, clasa a 10-a şi clasele 11-12.\r\n\r\nSubiectele vor fi propuse şi pregătite de către:\r\n\r\n* Prof. Clara Ionescu\r\n* ==User(user=\"SleepyOverlord\" type=\"link\")==\r\n* ==User(user=\"Marius\" type=\"link\")==\r\n\r\nIţi urăm mult succes şi te asteptăm la concurs!\r\n\r\n==include(username=\"%username%\" round_url=\"grigore-moisil-2009\" page=\"template/newsletter/rating\")==\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\nh2{font-size: 12pt}. %{color:red}NOU!% Concursuri virtuale\r\n\r\ninfoarena lansează o nouă facilitate: \'concursuri virtuale\':concursuri-virtuale! Această facilitate permite membrilor infoarena să îşi creeze singuri concursuri cu probleme din arhivă (peste 800!) la orice moment din zi şi, mai ales, din noapte. \r\n\r\nCiteşte \'prezentarea concursurilor virtuale\':blog/concursuri-virtuale alături de reacţia comunităţii infoarena la această nouă facilitate. Te aşteptăm cu păreri şi sugestii.\r\n\r\n==include(page=\"template/newsletter/doi-la-suta-call\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==\r\n',13,'protected',NULL,NULL),('runda/123456','123456','2009-04-01 19:31:56','2009-04-01 19:31:56','h1. == roundparam(round_id=\"123456\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"123456\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"123456\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"123456\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/123456/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"123456\" score=\"1\")==',9482,'round: 123456',NULL,NULL),('runda/123456/clasament','Clasament 123456','2009-04-01 19:31:56','2009-04-01 19:31:56','h1. Clasament ==roundparam(round_id=\"123456\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"123456\")==',9482,'round: 123456',NULL,NULL),('runda/romanian_masters','romanian_masters','2009-04-01 20:47:13','2009-04-01 20:47:13','h1. == roundparam(round_id=\"romanian_masters\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"romanian_masters\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"romanian_masters\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"romanian_masters\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/romanian_masters/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"romanian_masters\" score=\"1\")==',8482,'round: romanian_masters',NULL,NULL),('runda/romanian_masters/clasament','Clasament romanian_masters','2009-04-01 20:47:13','2009-04-01 20:47:13','h1. Clasament ==roundparam(round_id=\"romanian_masters\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"romanian_masters\")==',8482,'round: romanian_masters',NULL,NULL),('runda/vcontest','vcontest','2009-04-01 22:09:02','2009-04-01 22:09:02','h1. == roundparam(round_id=\"vcontest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"vcontest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"vcontest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"vcontest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/vcontest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"vcontest\" score=\"1\")==',1204,'round: vcontest',NULL,NULL),('runda/vcontest/clasament','Clasament vcontest','2009-04-01 22:09:02','2009-04-01 22:09:02','h1. Clasament ==roundparam(round_id=\"vcontest\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"vcontest\")==',1204,'round: vcontest',NULL,NULL),('runda/qwerty-9/clasament','Clasament qwerty-9','2009-04-01 22:42:27','2009-04-01 22:42:27','h1. Clasament ==roundparam(round_id=\"qwerty-9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"qwerty-9\")==',4439,'round: qwerty-9',NULL,NULL),('runda/qwerty-9','qwerty-9','2009-04-01 22:42:27','2009-04-01 23:34:46','h1. == roundparam(round_id=\"qwerty-9\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"qwerty-9\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"qwerty-9\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"qwerty-9\" param=\"duration\" strong=\"true\")== ore. Participantii vor avea de rezolvat 10 probleme.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/qwerty-9/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"qwerty-9\" score=\"1\")==',4439,'round: qwerty-9',NULL,NULL),('runda/high_level_contest','high_level_contest','2009-04-02 05:17:21','2009-04-02 05:17:21','h1. == roundparam(round_id=\"high_level_contest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"high_level_contest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"high_level_contest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"high_level_contest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/high_level_contest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"high_level_contest\" score=\"1\")==',6455,'round: high_level_contest',NULL,NULL),('runda/high_level_contest/clasament','Clasament high_level_contest','2009-04-02 05:17:21','2009-04-02 05:17:21','h1. Clasament ==roundparam(round_id=\"high_level_contest\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"high_level_contest\")==',6455,'round: high_level_contest',NULL,NULL),('runda/high_level_contest2','high_level_contest2','2009-04-02 05:20:54','2009-04-02 05:20:54','h1. == roundparam(round_id=\"high_level_contest2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"high_level_contest2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"high_level_contest2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"high_level_contest2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/high_level_contest2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"high_level_contest2\" score=\"1\")==',6455,'round: high_level_contest2',NULL,NULL),('runda/high_level_contest2/clasament','Clasament high_level_contest2','2009-04-02 05:20:54','2009-04-02 05:20:54','h1. Clasament ==roundparam(round_id=\"high_level_contest2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"high_level_contest2\")==',6455,'round: high_level_contest2',NULL,NULL),('runda/onipre','onipre','2009-04-02 06:07:33','2009-04-02 06:07:33','h1. == roundparam(round_id=\"onipre\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"onipre\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"onipre\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"onipre\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/onipre/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"onipre\" score=\"1\")==',6791,'round: onipre',NULL,NULL),('runda/onipre/clasament','Clasament onipre','2009-04-02 06:07:33','2009-04-02 06:07:33','h1. Clasament ==roundparam(round_id=\"onipre\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"onipre\")==',6791,'round: onipre',NULL,NULL),('runda/oniprechallenge','runda/oniprechallenge','2009-04-02 06:16:31','2009-04-02 06:16:31','Scrie aici despre runda/oniprechallenge',6791,'public',NULL,NULL),('runda/oniprec','oniprec','2009-04-02 06:17:25','2009-04-02 14:06:56','h3. **_Creat special pentru clasele 5-8 si nu numai_**\r\n\r\nh1. == roundparam(round_id=\"oniprec\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oniprec\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oniprec\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oniprec\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/oniprec/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"oniprec\" score=\"1\")==',6791,'round: oniprec',NULL,NULL),('runda/oniprec/clasament','Clasament oniprec','2009-04-02 06:17:25','2009-04-02 06:17:25','h1. Clasament ==roundparam(round_id=\"oniprec\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"oniprec\")==',6791,'round: oniprec',NULL,NULL),('parsarea-numerelor','Parsarea Numerelor','2009-04-02 07:48:41','2009-04-02 07:51:01','h1. Parsarea Numerelor\r\n\r\nSunt probleme care au datele de intrare mari (ex. 1 milion de numere), solutia e simpla se poate parsa citirea\r\n\r\nh2. Numere naturale\r\n\r\n== code(c) |\r\n\r\n#define DIM 10000\r\nchar buff[DIM];\r\nint poz=0;\r\n\r\nvoid citeste(int &numar)\r\n{\r\n     numar = 0;\r\n     //cat timp caracterul din buffer nu e cifra ignor      \r\n     while (buff[poz] < \'0\' || buff[poz] > \'9\')     \r\n          //daca am \"golit\" bufferul atunci il umplu\r\n          if (++poz == DIM) \r\n               fread(buff,1,DIM,stdin),poz=0;\r\n     //cat timp dau de o cifra recalculez numarul          \r\n     while (\'0\'<=buff[poz] && buff[poz]<=\'9\')\r\n     {\r\n          numar = numar*10 + buff[poz] - \'0\';\r\n          if (++poz == DIM) \r\n               fread(buff,1,DIM,stdin),poz=0;               \r\n     }     \r\n}\r\n\r\n==\r\n\r\nh2. Numere intregi\r\n\r\n== code(c) |\r\n#define DIM 10000\r\nchar buff[DIM];\r\nint poz=0;\r\n\r\nvoid citeste(int &numar)\r\n{\r\n     numar = 0;\r\n     char semn=\'+\';     \r\n     while (buff[poz] < \'0\' || buff[poz] > \'9\')\r\n     {     \r\n          semn = buff[poz];\r\n          if (++poz == DIM) \r\n               fread(buff,1,DIM,stdin),poz=0;\r\n     }          \r\n     while (\'0\'<=buff[poz] && buff[poz]<=\'9\')\r\n     {\r\n          numar = numar*10 + buff[poz] - \'0\';\r\n          if (++poz == DIM) \r\n               fread(buff,1,DIM,stdin),poz=0;               \r\n     }     \r\n     if (semn == \'-\')\r\n          numar = -numar;\r\n}\r\n==\r\n\r\nin plus mai este o smecherie pentru numere intregi functia atoi din stdlib.h\r\n\r\n\r\n== code(c) |\r\nvoid citeste(int &numar)\r\n{\r\n     fgets(buff,32,stdin);     \r\n     numar = atoi(buff);\r\n}\r\n==\r\n\r\nacest cod functioneaza cand numerele apr pe randuri diferite\r\n\r\nh2. Numere reale\r\n\r\n== code(c) |\r\n\r\n#define DIM 10000\r\nchar buff[DIM];\r\nint poz=0;\r\n\r\n\r\nvoid citeste(double &numar)\r\n{\r\n     numar = 0;\r\n     char semn=\'+\';\r\n     //caut inceputul numarului     \r\n     while (buff[poz] < \'0\' || buff[poz] > \'9\')\r\n     {     \r\n          semn = buff[poz];\r\n          if (++poz == DIM) \r\n               fread(buff,1,DIM,stdin),poz=0;\r\n     }          \r\n     //citesc partea de dinainte de virgula\r\n     while (\'0\'<=buff[poz] && buff[poz]<=\'9\')\r\n     {\r\n          numar = numar*10 + buff[poz] - \'0\';\r\n          if (++poz == DIM) \r\n               fread(buff,1,DIM,stdin),poz=0;               \r\n     }     \r\n     //daca are virgula citesc si partea de dupa\r\n     if (buff[poz] == \'.\')\r\n     {\r\n          double tmp,cnt;\r\n          tmp = 0;\r\n          cnt = 1;\r\n          ++poz;\r\n          while (\'0\'<=buff[poz] && buff[poz]<=\'9\')\r\n          {\r\n               cnt = cnt/10;\r\n               tmp = tmp + cnt*(double(buff[poz]-\'0\'));\r\n               if (++poz == DIM) \r\n                    fread(buff,1,DIM,stdin),poz=0;               \r\n          }\r\n          numar += tmp;                    \r\n     }\r\n     //daca are semnul minus il fac negativ\r\n     if (semn == \'-\')\r\n          numar = - numar;\r\n}\r\n\r\n==\r\n\r\n',4439,'public',NULL,NULL),('runda/infoexpet','infoexpet','2009-04-02 19:22:39','2009-04-02 19:22:39','h1. == roundparam(round_id=\"infoexpet\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"infoexpet\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"infoexpet\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"infoexpet\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/infoexpet/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"infoexpet\" score=\"1\")==',7451,'round: infoexpet',NULL,NULL),('runda/infoexpet/clasament','Clasament infoexpet','2009-04-02 19:22:39','2009-04-02 19:22:39','h1. Clasament ==roundparam(round_id=\"infoexpet\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"infoexpet\")==',7451,'round: infoexpet',NULL,NULL),('runda/oni','oni','2009-04-02 19:23:12','2009-04-02 19:23:12','h1. == roundparam(round_id=\"oni\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oni\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oni\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oni\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/oni/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"oni\" score=\"1\")==',7451,'round: oni',NULL,NULL),('runda/oni/clasament','Clasament oni','2009-04-02 19:23:12','2009-04-02 19:23:12','h1. Clasament ==roundparam(round_id=\"oni\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"oni\")==',7451,'round: oni',NULL,NULL),('runda/simulare','simulare','2009-04-02 22:35:29','2009-04-03 10:27:37','h1. == roundparam(round_id=\"simulare\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"simulare\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"simulare\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"simulare\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/simulare/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"simulare\" score=\"1\")==',1792,'round: simulare',NULL,NULL),('runda/simulare/clasament','Clasament simulare','2009-04-02 22:35:29','2009-04-02 22:35:29','h1. Clasament ==roundparam(round_id=\"simulare\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"simulare\")==',1792,'round: simulare',NULL,NULL),('runda/katamashhh/clasament','Clasament katamashhh','2009-04-03 08:33:26','2009-04-03 08:33:26','h1. Clasament ==roundparam(round_id=\"katamashhh\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"katamashhh\")==',9989,'round: katamashhh',NULL,NULL),('runda/simulationoni','simulationoni','2009-04-03 13:32:54','2009-04-03 13:32:54','h1. == roundparam(round_id=\"simulationoni\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"simulationoni\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"simulationoni\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"simulationoni\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/simulationoni/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"simulationoni\" score=\"1\")==',8680,'round: simulationoni',NULL,NULL),('runda/simulationoni/clasament','Clasament simulationoni','2009-04-03 13:32:54','2009-04-03 13:32:54','h1. Clasament ==roundparam(round_id=\"simulationoni\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"simulationoni\")==',8680,'round: simulationoni',NULL,NULL),('runda/pregatire_oni','pregatire_oni','2009-04-03 14:21:27','2009-04-03 14:21:27','h1. == roundparam(round_id=\"pregatire_oni\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"pregatire_oni\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"pregatire_oni\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"pregatire_oni\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/pregatire_oni/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"pregatire_oni\" score=\"1\")==',8239,'round: pregatire_oni',NULL,NULL),('runda/pregatire_oni/clasament','Clasament pregatire_oni','2009-04-03 14:21:27','2009-04-03 14:21:27','h1. Clasament ==roundparam(round_id=\"pregatire_oni\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pregatire_oni\")==',8239,'round: pregatire_oni',NULL,NULL),('runda/testx','testx','2009-04-03 15:59:36','2009-04-03 15:59:36','h1. == roundparam(round_id=\"testx\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"testx\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"testx\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"testx\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/testx/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"testx\" score=\"1\")==',393,'round: testx',NULL,NULL),('runda/testx/clasament','Clasament testx','2009-04-03 15:59:36','2009-04-03 15:59:36','h1. Clasament ==roundparam(round_id=\"testx\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"testx\")==',393,'round: testx',NULL,NULL),('runda/euclid_2/clasament','Clasament euclid_2','2010-04-11 13:30:35','2010-04-11 13:30:35','h1. Clasament ==roundparam(round_id=\"euclid_2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"euclid_2\" detail_task=\"true\")==',12519,'round: euclid_2',NULL,NULL),('planificare/sedinta-20090403','Sedinta 2009-04-03','2009-03-29 22:30:49','2009-07-14 07:25:58','h1. Sedinta 2009-04-03\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe intalnim *vineri, 3 aprilie* la ora *19:00* la \'*Retro Cafe*\':http://metropotam.ro/Unde-iesim/2008/07/art2701725520-Millennium-Bank-recomanda-Retro-Cafe/\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== (probabil voi intarzia)\r\n* ==user(user=\"stef2n\" type=\"tiny\")== (nu ajung mai devreme de 20:00)\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"prostu\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090316| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|OKRs| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n\r\nh3. Algoritmiada\r\n\r\n* Sponsori\r\n* Participanţi\r\n* Trisori\r\n* Blog post runda 3\r\n* Lista cereri\r\n* Cazare şi masă\r\n* Tricouri\r\n* Organizare tehnică\r\n* Presă\r\n\r\nh2. Detalii\r\n\r\nh3. Misc\r\n\r\n* Marius Stroe?\r\n* Backup notice.\r\n* Concursul CEX\r\n* Concursul \"Grigore Moisil\"\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Mircea dă mail la Microsoft.\r\n* Wefgef face listă cu ce trebuie instalat la Algoritmiada\r\n* Mircea, Cristi şi Bogdan bagă review la change-ul lui Devilkind. (?)\r\n* Mircea face review la script pentru topic-uri de pe forum la probleme. (?)\r\n* Victor îi arată lui Prostu cum se foloseşte format_table. Prostu bagă la review săptămâna asta.\r\n* Prostu aduce merinde la următoarea şedinţă.\r\n* Wefgef reactualizează bugetul Algoritmiadei.\r\n* Vali se gândeşte la premii cool şi ieftine.\r\n* Prostu vorbeşte la Oracle despre sponsorizare.\r\n* Wefgef bagă post despre trişare la Algoritmiada.\r\n* Wefgef şi Cristi fac listă de cereri. Wefgef o trimite la liceu.\r\n* Până vineri Wefgef ia legatura cu hotelurile si restaurantul.\r\n* Tricorui > picnic.\r\n* Wefgef vorbeşte cu Vlad_d de design de tricouri.\r\n* Cristi vorbeşte de serigrafiere dacă primeşte design.\r\n* Vali şi Wefgef merg la Braşov cu o săptămână înainte de finală.\r\n* Pookie face comunicat de presă online.\r\n* Joi facem o conferinţă legată de Algoritmiadă.\r\n* Paul îl invită pe Stroe la finală.\r\n* Cristi actualizează notele cu semn de întrebare de la OKRs.\r\n\r\nh2. Notiţe\r\n\r\n* Silviu si Cristi concretizeaza IAP 7 (1 sedinta)\r\n* Blog post pentru Coding Camp \"A New Day\"\r\n* Silviu bagă post drespre runda 3. (?)\r\n* Cristi vorbeşte cu Cristina Petrovici despre implicarea în infoarena.\r\n* Cristi are de recuperat 68 de lei (15 daţi lui Victor Rusu şi 50 consumaţia de la Retro Cafe).\r\n',2044,'protected',NULL,NULL),('runda/de_la_inceput','de_la_inceput','2009-04-04 18:36:40','2009-04-04 18:36:40','h1. == roundparam(round_id=\"de_la_inceput\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"de_la_inceput\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"de_la_inceput\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"de_la_inceput\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/de_la_inceput/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"de_la_inceput\" score=\"1\")==',7700,'round: de_la_inceput',NULL,NULL),('runda/de_la_inceput/clasament','Clasament de_la_inceput','2009-04-04 18:36:40','2009-04-04 18:36:40','h1. Clasament ==roundparam(round_id=\"de_la_inceput\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"de_la_inceput\")==',7700,'round: de_la_inceput',NULL,NULL),('runda/pentru_o_bere','pentru_o_bere','2009-04-04 18:45:10','2009-04-04 18:45:10','h1. == roundparam(round_id=\"pentru_o_bere\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"pentru_o_bere\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"pentru_o_bere\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"pentru_o_bere\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/pentru_o_bere/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"pentru_o_bere\" score=\"1\")==',6490,'round: pentru_o_bere',NULL,NULL),('runda/pentru_o_bere/clasament','Clasament pentru_o_bere','2009-04-04 18:45:10','2009-04-04 18:45:10','h1. Clasament ==roundparam(round_id=\"pentru_o_bere\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pentru_o_bere\")==',6490,'round: pentru_o_bere',NULL,NULL),('runda/very-long_olimp','very-long_olimp','2009-04-04 18:49:31','2009-04-04 18:49:31','h1. == roundparam(round_id=\"very-long_olimp\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"very-long_olimp\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"very-long_olimp\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"very-long_olimp\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/very-long_olimp/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"very-long_olimp\" score=\"1\")==',6490,'round: very-long_olimp',NULL,NULL),('runda/very-long_olimp/clasament','Clasament very-long_olimp','2009-04-04 18:49:31','2009-04-04 18:49:31','h1. Clasament ==roundparam(round_id=\"very-long_olimp\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"very-long_olimp\")==',6490,'round: very-long_olimp',NULL,NULL),('runda/2050','2050','2009-04-04 20:18:37','2009-04-04 20:18:37','h1. == roundparam(round_id=\"2050\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"2050\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"2050\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"2050\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/2050/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"2050\" score=\"1\")==',6490,'round: 2050',NULL,NULL),('runda/2050/clasament','Clasament 2050','2009-04-04 20:18:37','2009-04-04 20:18:37','h1. Clasament ==roundparam(round_id=\"2050\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"2050\")==',6490,'round: 2050',NULL,NULL),('runda/in_time','in_time','2009-04-04 20:19:03','2009-04-04 20:19:03','h1. == roundparam(round_id=\"in_time\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"in_time\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"in_time\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"in_time\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/in_time/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"in_time\" score=\"1\")==',6490,'round: in_time',NULL,NULL),('runda/in_time/clasament','Clasament in_time','2009-04-04 20:19:03','2009-04-04 20:19:03','h1. Clasament ==roundparam(round_id=\"in_time\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"in_time\")==',6490,'round: in_time',NULL,NULL),('runda/info2009','info2009','2009-04-05 05:23:31','2009-04-05 05:23:31','h1. == roundparam(round_id=\"info2009\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"info2009\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"info2009\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"info2009\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/info2009/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"info2009\" score=\"1\")==',8572,'round: info2009',NULL,NULL),('runda/info2009/clasament','Clasament info2009','2009-04-05 05:23:31','2009-04-05 05:23:31','h1. Clasament ==roundparam(round_id=\"info2009\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"info2009\")==',8572,'round: info2009',NULL,NULL),('runda/simulare2','simulare2','2009-04-05 07:16:04','2009-04-05 07:16:04','h1. == roundparam(round_id=\"simulare2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"simulare2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"simulare2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"simulare2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/simulare2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"simulare2\" score=\"1\")==',2993,'round: simulare2',NULL,NULL),('runda/simulare2/clasament','Clasament simulare2','2009-04-05 07:16:04','2009-04-05 07:16:04','h1. Clasament ==roundparam(round_id=\"simulare2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"simulare2\")==',2993,'round: simulare2',NULL,NULL),('runda/salvare','salvare','2009-04-05 09:16:43','2009-04-05 09:16:43','h1. == roundparam(round_id=\"salvare\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"salvare\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"salvare\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"salvare\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/salvare/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"salvare\" score=\"1\")==',7700,'round: salvare',NULL,NULL),('runda/salvare/clasament','Clasament salvare','2009-04-05 09:16:43','2009-04-05 09:16:43','h1. Clasament ==roundparam(round_id=\"salvare\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"salvare\")==',7700,'round: salvare',NULL,NULL),('runda/meesh','meesh','2009-04-05 12:15:01','2009-04-05 12:15:01','h1. == roundparam(round_id=\"meesh\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"meesh\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"meesh\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"meesh\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/meesh/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"meesh\" score=\"1\")==',9989,'round: meesh',NULL,NULL),('runda/meesh/clasament','Clasament meesh','2009-04-05 12:15:01','2009-04-05 12:15:01','h1. Clasament ==roundparam(round_id=\"meesh\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"meesh\")==',9989,'round: meesh',NULL,NULL),('runda/infoo-9a','infoo-9a','2009-04-05 12:18:19','2009-04-05 12:18:19','h1. == roundparam(round_id=\"infoo-9a\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"infoo-9a\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"infoo-9a\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"infoo-9a\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/infoo-9a/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"infoo-9a\" score=\"1\")==',9989,'round: infoo-9a',NULL,NULL),('runda/infoo-9a/clasament','Clasament infoo-9a','2009-04-05 12:18:19','2009-04-05 12:18:19','h1. Clasament ==roundparam(round_id=\"infoo-9a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"infoo-9a\")==',9989,'round: infoo-9a',NULL,NULL),('grigore-moisil-2009/solutii/alibaba','grigore-moisil-2009/solutii/alibaba','2009-04-05 16:34:45','2009-04-06 06:31:46','h2(#alibaba). \'Alibaba\':problema/alibaba\r\n\r\nVom prezenta trei moduri de abordare a rezolvării.\r\n\r\nh3. Varianta 1\r\n\r\nSă observăm că la fiecare pas trebuie tăiată ultima cifră dintr-o secvenţă descrescătoare de cifre aflate pe poziţii consecutive. Astfel peste această cifră vom putea pune cea aflată pe poziţia imediat următoare şi care are valoare mai mare. Conform acestui algoritm pentru exemplul din enunţ $(12312)$ se vor obţine pe rând numerele: $2312$, $312$, $32$.\r\n\r\nAlgoritmul de mai sus pierde timp preţios efectuând translatările aferente tăierii unei cifre. În concluzie vom crea un şir martor în care memorăm faptul că o anumită cifră este tăiată sau nu.\r\n\r\nh3. Varianta 2\r\n\r\nPornim de la observaţia că pentru a maximiza numărul trebuie să aducem pe prima poziţie cea mai mare cifră posibilă. Dacă putem tăia maxim $K$ cifre, rezultă că vom putea muta pe prima poziţie o cifră dintre primele $K + 1$ cifre. Pornim cu cifrele din intervalul $[1, N]$ şi cu valoarea $K$. Dacă cifra având valoare maximă din intervalul $[1, K + 1]$ se află pe poziţia $L$, atunci problema se reduce la intervalul $[L + 1, N]$ şi valoarea $K – L$. O implementare naivă va avea complexitatea $O(K^2^)$ în cel mai rău caz, dar în practică algoritmul se comportă mult mai bine. Menţionăm că complexitatea se poate reduce la $O(K log K)$ folosind arbori de intervale.\r\n\r\nh3. Varianta 3\r\n\r\nSoluţia foloseşte _metoda Greedy_. În continuare, vom considera $S$ ca fiind şirul cifrelor. Pentru a forma cel mai mare număr, trebuie ca pe primele poziţii să avem cifre cât mai mari. Din acest motiv, vom căuta prima cea mai mare cifră din şir, după care următoarea cea mai mare cifră din şir ş.a.m.d. Spre exemplu, pentru şirul $1295413746$ cifrele găsite sunt, în această ordine, $9$, $7$ şi $6$. Cu aceste cifre vom forma un şir $T$, aici $976$, care este cel mai mare dacă, în cazul acesta, trebuie să eliminăm $7$ cifre. Dacă, însă, numărul cifrelor ce trebuie eliminate este mai mic, atunci trebuie să avem un şir $T$ mai lung adăugându-i noi cifre din cele rămase. Când vom insera aceste cifre noi, vrem ca cele găsite până acum să rămână pe poziţii cât mai înaintate. De aceea, pentru fiecare şir rămas cuprins între cifrele găsite, $12$, $5413$, $4$, vom aplica acelaşi procedeu, însă, le vom considera în ordine inversă, $4$, $5413$, $12$, pentru ca cifrele cele mai mari să rămână pe poziţii cât mai semnificative. Vom repeta recursiv procedeul până când şirul $T$ are lungimea $N – K$.\r\n\r\nSubproblema determinării celei mai mari cifre, a următoarei celei mai mari cifre ş.a.m.d. se rezolvă cu ajutorul unei stive în timp liniar. Algoritmul parcurge şirul cifrelor de la cea mai semnificativă la cea mai puţin semnificativă, scoate din stivă toate elementele care sunt mai mici strict decât cifra curentă, iar apoi o inserează pe aceasta în vârful structurii de date.\r\n\r\n== code(cpp) |\r\n...\r\nstk_len = 0\r\npentru i = 1, n execută\r\n  cât timp (stk_len > 0) şi (stk[stk_len] < S[i]) execută\r\n    stk_len --;\r\n  sfârşit cât timp\r\n  stk[stk_len] = S[i]\r\n  stk_len ++\r\nsfârşit pentru\r\n...\r\n==\r\n\r\nComplexitate finală: $O(N)$.\r\n',3146,'public',NULL,NULL),('runda/info_conquiz','info_conquiz','2009-04-05 17:04:45','2009-04-05 17:04:45','h1. == roundparam(round_id=\"info_conquiz\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"info_conquiz\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"info_conquiz\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"info_conquiz\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/info_conquiz/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"info_conquiz\" score=\"1\")==',9436,'round: info_conquiz',NULL,NULL),('runda/info_conquiz/clasament','Clasament info_conquiz','2009-04-05 17:04:45','2009-04-05 17:04:45','h1. Clasament ==roundparam(round_id=\"info_conquiz\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"info_conquiz\")==',9436,'round: info_conquiz',NULL,NULL),('runda/info_conquiztador','info_conquiztador','2009-04-05 17:05:03','2009-04-05 17:05:03','h1. == roundparam(round_id=\"info_conquiztador\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"info_conquiztador\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"info_conquiztador\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"info_conquiztador\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/info_conquiztador/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"info_conquiztador\" score=\"1\")==',9436,'round: info_conquiztador',NULL,NULL),('runda/info_conquiztador/clasament','Clasament info_conquiztador','2009-04-05 17:05:03','2009-04-05 17:05:03','h1. Clasament ==roundparam(round_id=\"info_conquiztador\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"info_conquiztador\")==',9436,'round: info_conquiztador',NULL,NULL),('runda/info_conquiztador002','info_conquiztador002','2009-04-05 17:10:39','2009-04-05 17:10:39','h1. == roundparam(round_id=\"info_conquiztador002\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"info_conquiztador002\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"info_conquiztador002\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"info_conquiztador002\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/info_conquiztador002/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"info_conquiztador002\" score=\"1\")==',9436,'round: info_conquiztador002',NULL,NULL),('runda/info_conquiztador002/clasament','Clasament info_conquiztador002','2009-04-05 17:10:39','2009-04-05 17:10:39','h1. Clasament ==roundparam(round_id=\"info_conquiztador002\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"info_conquiztador002\")==',9436,'round: info_conquiztador002',NULL,NULL),('runda/hardcore','hardcore','2009-04-05 19:02:28','2009-04-05 19:02:28','h1. == roundparam(round_id=\"hardcore\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"hardcore\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"hardcore\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"hardcore\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/hardcore/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"hardcore\" score=\"1\")==',6333,'round: hardcore',NULL,NULL),('runda/hardcore/clasament','Clasament hardcore','2009-04-05 19:02:28','2009-04-05 19:02:28','h1. Clasament ==roundparam(round_id=\"hardcore\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"hardcore\")==',6333,'round: hardcore',NULL,NULL),('grigore-moisil-2009/solutii/palindrom2','grigore-moisil-2009/solutii/palindrom2','2009-04-05 19:30:17','2009-04-05 19:30:48','h2(#palindrom2). \'Palindrom2\':problema/palindrom2\r\n\r\nSe aplică _metoda Greedy_. Conform cerinţei din enunţ se impune să inserăm caractere doar la sfârşitul şirului. Observăm că un palindrom de lungime minimă se obţine prin inserarea unui număr minim de caractere la sfârşitul şirului. Pentru a obţine acest număr minim trebuie să găsim lungimea maximă a unui palindrom care se termină pe ultima poziţie a şirului. \r\n\r\nSpre exemplu, dacă şirul iniţial este $abcdzyxyz$, palindromul căutat este $zyxyz$, iar rezultatul va fi $abcdzyxyzdcba$, adică vom adăuga caracterele aflate în faţa palindromului cu care se termină şirul iniţial, dar în ordine inversă. De aici, problema se rezumă la a determina această lungime maximă a unui palindrom care se termină pe ultima poziţie a şirului. Se fixează un indice $k$ succesiv pe poziţiile $1, 2, ..., n$ şi se verifică dacă şirul $S[k..n]$ este un palindrom:\r\n\r\n== code(cpp) |\r\nAlgoritm Pali(k, n, S, ok):\r\n  i = k\r\n  j = n\r\n  ok = adevărat\r\n  cât timp i < j şi ok execută\r\n    dacă S[i] != S[j] atunci\r\n      ok = fals\r\n    sfârşit dacă\r\n    i = i + 1\r\n    j = j - 1\r\n  sfârşit cât timp\r\nSfârşit algoritm.\r\n==\r\n\r\nDacă $ok$ este adevărat, atunci $S[k..n]$ este palindrom. Algoritmul se opreşte la primul palindrom determinat, acesta fiind de lungimea cea mai mare.\r\nComplexitate: $O(n^2^)$.\r\n',3146,'public',NULL,NULL),('grigore-moisil-2009/solutii/bete2','grigore-moisil-2009/solutii/bete2','2009-04-05 19:39:16','2009-04-06 06:34:44','h2(#bete2). \'Bete2\':problema/bete2\r\n\r\nProblema revine la numărarea tripleţilor de forma $a = b + c$ în mulţimea numerelor date şi poate fi abordată în mai multe feluri. Vom prezenta câteva posibilităţi,\r\n\r\nh3. Varianta 1\r\n\r\nCea mai simplă rezolvare se bazează pe trei for-uri. Înaintea aplicării algoritmului de mai jos, şirul se sortează descrescător.\r\n\r\n== code(cpp) |\r\nAlgoritm Bete(n, lung, nr):\r\n  Ordonare(n, lung)	{ ordonăm şirul lungimilor în ordine crescătoare }\r\n  nr = 0\r\n  Pentru i = 1, n - 2 execută\r\n    Pentru j = i + 1, n - 1 execută\r\n      Pentru k = j + 1, n execută\r\n        Dacă lung[i] = lung[j] + lung[k] atunci\r\n          nr ++	       { în nr numărăm posibilităţile de a forma tripleţii de forma a = b + c }\r\n        sfârşit dacă\r\n      sfârşit pentru\r\n    sfârşit pentru\r\n  sfârşit pentru\r\nSfârşit algoritm\r\n==\r\n\r\nCu această rezolvare se puteau obţine 40-50 puncte. \r\n\r\nh3. Varianta 2\r\n\r\nExistă şi posibilitatea generării tuturor submulţimilor având trei elemente care se acceptă pentru a fi numărate doar dacă au proprietatea cerută. Înainte de aplicarea algoritmului de mai jos, şirul se sortează descrescător.\r\n\r\n== code(cpp) |\r\nAlgoritm Generare(i):\r\n  Pentru j = x[i - 1] + 1, n - 3 + i execută	{ şirul x are şi elementul x0 = 0, generăm mulţimi având 3 elemente }\r\n    x[i] = j\r\n    Dacă i < 3 atunci\r\n      Generare(i + 1)\r\n    altfel\r\n      Dacă lung[x[1]] = lung[x[2]] + lung[x[3]] atunci\r\n         nr ++\r\n      sfârşit dacă\r\n    sfârşit dacă\r\n  sfârşit pentru\r\nSfârşit algoritm\r\n==\r\n\r\nCu această rezolvare se putea obţine aproximativ acelaşi punctaj ca soluţia precedentă.\r\n\r\nh3. Varianta 3\r\n\r\nÎmbunătăţim varianta 1 reducându-i complexitatea de la $Θ(n^3^)$ la $Θ(n^2^ log n)$. Acest lucru este posibil înlocuind al treilea for cu algoritmul căutării binare. Cu această rezolvare se puteau obţine $100$ puncte.\r\n\r\nh3. Varianta 4\r\n\r\nAlgoritmul poate fi îmbunătăţit în continuare prin înlocuirea căutării binare cu \'tabele de dispersie\':http://infoarena.ro/tabele-hash-prezentare-detaliata, obţinându-se un algoritm cu ordinul de execuţie $O(n^2^)$ care ar obţine tot 100 de puncte.\r\n\r\n\r\n',3146,'public',NULL,NULL),('grigore-moisil-2009/solutii/fotbal','grigore-moisil-2009/solutii/fotbal','2009-04-05 19:45:59','2009-04-05 19:45:59','h2(#fotbal). \'Fotbal\':problema/fotbal\r\n\r\nProblema este mai dificilă decât pare la prima vedere. Întâi vom calcula numărul de puncte obţinute de fiecare echipă, numărul total de goluri înscrise şi primite şi golaverajul. Vom sorta echipele după aceste criterii şi în continuare lucrăm cu acest clasament. Vom grupa echipe de pe poziţii consecutive dacă au obţinut acelaşi număr de puncte şi vom avea trei cazuri în funcţie de mărimea unei asemenea grupe:\r\n\r\n# Dacă grupa are un singur element, echipa respectivă ocupă clar locul din clasament.\r\n# Dacă grupa are două elemente, trebuie verificat meciul direct dintre cele două echipe. Dacă au jucat meci egal, se va verifica golaverajul, în caz de egalitate numărul golurilor înscrise, iar dacă şi acesta este egal se va da cu banul.\r\n# Dacă grupa are trei sau patru elemente, vom apela recursiv procedura, numai pentru echipele respective. Limita pentru $n$ garantează că în cel mai rău caz se va întâmpla un singur apel de acest gen.\r\n\r\nUn caz special, care mai trebuie tratat este, când există o singură grupă, adică toate echipele au punctaj egal. Acest caz se tratează printr-o nouă grupare, de data asta după golaveraj şi atribuirea poziţiilor corespunzătoare pentru echipele din fiecare grupă.\r\n\r\nComplexitatea finală este $O(n^2^)$.\r\n\r\nO altă soluţie foloseşte un vector în care se reţine pentru fiecare echipă numărul echipelor mai bune decât aceasta. Întâi, vom face clasamentul după punctajul obţinut. Dacă vor exista mai multe echipe la egalitate, vom marca aceste echipe într-un vector martor şi vom reface clasamentul separat pentru ele în funcţie de rezultatul direct, golaveraj şi numărul golurilor înscrise. În implementare, dacă una din aceste echipe este mai bună decât cealaltă, se va aduna încă o poziţie la valoarea curentă din vector. După acest pas, pentru a determina poziţia cea mai bună pentru fiecare dintre echipe vom număra pe câte poziţii apar valori strict mai mici. Pentru poziţia cea mai rea pe care o poate ocupă în clasament vom aduna toate valorile din vector mai mici sau egale.',3146,'public',NULL,NULL),('grigore-moisil-2009/solutii/cuburi3','grigore-moisil-2009/solutii/cuburi3','2009-04-05 20:01:01','2009-04-06 06:39:35','h2(#cuburi3). \'Cuburi3\':problema/cuburi3\r\n\r\nVom prezenta trei soluţii, toate aplicând metoda $programării dinamice$, prima fiind una cu _memoizare_, a doua una clasică iar a treia folosind \'_arbori indexaţi binar_\':http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=binaryIndexedTrees.\r\n\r\nh3. Varianta 1\r\n\r\nVom arăta că soluţia are structură optimă: presupunem că turnul de cuburi format din cuburile numerotate cu $p{~1~}, p{~2~}, ..., p{~k~}$ în această ordine are înălţime maximă. Acum turnul de cuburi format din cuburile $p{~2~}, ..., p{~k~}$ este cel mai înalt turn care îl are la bază pe $p{~2~}$. Dacă ar exista turn mai înalt care la bază să îl aibă tot pe $p{~2~}$, atunci acesta s-ar putea aşeza pe $p{~1~}$ şi astfel am obţine un turn mai înalt decât cel din presupunerea iniţială. Am afirmat că acel ipotetic turn mai înalt care începe cu $p{~2~}$ l-am aşeza pe $p{~1~}$, deoarece $p{~1~}$ nu poate să apară în acest turn care începe cu $p{~2~}$, ţinând cont de proprietăţile turnului. \r\n\r\nDescompunem problema în subprobleme: pentru orice $i (1 &le; i &le; n)$ trebuie să determinăm înălţimea maximă a turnului care la bază îl are pe cubul $i$. Fie $bst{~i~}$ turnul de înălţime maximă ce se termină pe poziţia $i$.\r\n\r\n* $bst{~i~} = max { bst{~j~} : 1 &le; j &le; n, i != j  şi g{~j~} &le; g{~i~} şi l{~j~} &le; l{~i~} } + l{~i~}$ \r\n\r\nVom determina soluţia optimă recursiv şi vom păstra rezultatele subproblemelor, de unde le vom citi dacă în continuare va fi nevoie de ele. Şirul care memorează rezultatele subproblemelor se iniţializează cu $0$, pentru a şti dacă elementul respectiv s-a calculat deja sau nu.\r\n\r\nAlgoritmul lucrează în $O(n^2^)$, şi are nevoie de $Θ(n)$ memorie.\r\n\r\nh3. Varianta 2\r\n\r\nO altă soluţie având complexitatea $O(n^2^)$ se poate obţine sortând cuburile descrescător după lungimea laturii şi în caz de egalitate după greutate. După sortare putem aplica _metoda programării dinamice_ în felul următor:\r\n\r\n* $bst{~i~}$ – înălţimea celui mai înalt turn ce se poate construi în aşa fel încât ultimul cub să fie cubul $i$.\r\n\r\nSortarea ne garantează că cubul $i$ se poate aşeza doar pe cuburi având indice mai mic. Astfel recurenţa va fi:\r\n\r\n* $bst{~i~} = max { bst{~j~} : 1 &le; j < i şi g{~j~} &ge; g{~i~}} + l{~i~}$ \r\n\r\nSoluţia se va afla în elementul maxim din $bst$. Pentru a putea reconstrui soluţia, trebuie reţinut pentru fiecare $i$, acel $j$ prin care s-a obţinut maximul pentru $bst{~i~}$.\r\n\r\nh3. Varianta 3\r\n\r\nFolosind arbori indexaţi binar (notat în continuare cu AIB), vom obţine un algoritm de complexitate $O(n log n)$ care necesită $Θ(n)$ memorie. Deoarece cerinţa problemei este de a construi un subşir $(g{~1~}, l{~1~}), (g{~2~}, l{~2~}), ..., (g{~k~}, l{~k~})$ astfel încât $g{~1~} &ge; g2 &ge; ... &ge; gk$ şi $l{~1~} &ge; l{~2~} &ge; ... &ge; l{~k~}$, întâi sortăm descrescător cuburile în funcţie de lungimea laturii, iar în caz de egalitate, descrescător în funcţie de greutate.\r\n\r\nPentru poziţia $i$ vom alege $bst{~j~}$ maxim, astfel încât greutatea cubului $j$, $j < i$,  să fie mai mare sau egală cu greutatea cubului $i$. Observăm că $j < i$ este echivalent cu $l{~j~} &ge; l{~i~}$, adică condiţia lungimilor laturilor este îndeplinită. Însă, noi avem nevoie doar de greutăţile mai mari sau egale decât greutatea curentă $g{~i~}$. Aici intervine AIB, în felul următor:\r\n\r\n* sortăm crescător greutăţile cuburilor, eliminăm duplicatele obţinând un vector de lungime $lung$;\r\n* căutăm în acest vector cu algoritmul căutării binare greutatea curentă $g{~i~}$, găsind-o pe o poziţie $p$;\r\n* interogăm AIB-ul pe intervalul $[p, lung]$ pentru a determina $max { bst{~j~} : 1 &le; j < i şi g{~j~} &ge; g{~i~}}$;\r\n* actualizăm în AIB intervalul $[1, p]$ cu $bst{~i~}$.\r\n\r\nOperaţiile de interogare şi actualizare într-un AIB au complexitatea $O(log(n))$.\r\n',3146,'public',NULL,NULL),('grigore-moisil-2009/solutii/motel','grigore-moisil-2009/solutii/motel','2009-04-05 20:12:07','2009-04-05 20:12:54','h2(#motel). \'Motel\':problema/motel\r\n\r\nProblema poate fi abordată cu _metoda Greedy_ sau cu algoritmul determinării unui cuplaj maxim. Dar soluţia cea mai eficientă se va obţine folosind \'_heapuri_\':heapuri. \r\n\r\nh3. Varianta 1\r\n\r\nDin păcate, aplicarea metodei Greedy nu conduce la rezultate corecte. Dacă sortăm intervalele solicitate de turişti în ordine crescătoare după ziua care închide intervalul şi sortăm crescător vectorul zilelor specificate de artist, şi parcurgem în paralel cele două şiruri pentru a verifica dacă ziua precizată de artist de pe poziţia $i$ face parte sau nu din intervalul aflat pe aceeaşi poziţie, vom greşi, deoarece pierdem soluţii pentru cazuri de forma următoare:\r\n$2$\r\n$1 4$\r\n$2 3$\r\n$1$\r\n$2$\r\nSortarea după ultima zi din interval ne conduce la \r\n$2 3$\r\n$1 4$\r\n\r\n$1$ nu face parte din intervalul $[2, 3]$ şi astfel am ajunge la concluzia că nu avem soluţie, cu toate că ea există:\r\n$1 1$\r\n$2 2$\r\n\r\nO astfel de rezolvare ar fi obţinut $30$ de puncte.\r\n\r\nDe asemenea, nici varianta când sortăm după extremitatea stângă a intervalelor nu funcţionează corect. Să considerăm de exemplu cazul\r\n$1 4$\r\n$2 3$\r\n$2$\r\n$4$\r\n\r\nVom atribui intervalului $[1, 4]$ punctul $2$ şi astfel punctului $4$ nu i se va mai putea atribui intervalul rămas şi iarăşi am ajunge la concluzia că nu există soluţie. Această rezolvare obţine de asemenea $30$ de puncte.\r\n\r\nh3. Varianta 2\r\n\r\nPentru cei care au cunoştinţe de teoria grafurilor o primă idee ar putea fi construirea unui graf bipartit şi încercarea găsirii unui cuplaj de cardinalitate $n$. Acest lucru se poate face în complexitate $O(n * m)$ sau $O(sqrt(n) * m)$. În cel mai rău caz $m$ poate ajunge până la $n^2^$, dar în practică acest caz este cel mai simplu, pentru că orice cuplare între intervale şi zile duce la soluţie optimă. O implementare eficientă a acestei idei poate obţine între $55$ şi $70$ de puncte.\r\n\r\nh3. Variata 3\r\n\r\nO soluţie mult mai simplu de implementat şi care în practică are un timp de rulare asemănător este următoarea: sortăm zilele în care artistul este disponibil în ordine crescătoare. Le parcurgem în această ordine şi atribuim fiecăruia intervalul care are extremitatea din dreapta cea mai mică, dintre intervalele care o cuprind. O implementare naivă va avea complexitatea $Θ(n^2^)$ şi ar obţine între $55$ şi $70$ de puncte\r\n\r\nPentru a obţine punctaj maxim vom implementa ideea de mai sus într-un mod mai eficient. Pentru acesta trebuie să cunoaştem structura de date numită _min-heap_. Criteriul de sortare al heap-ului va fi extremitatea dreaptă a intervalelor. \r\n\r\nSortăm intervalele după extremitatea stângă. La pasul $i$ căutăm intervalul pe care să-l cuplăm cu ziua $i$. Introducem în heap intervalele încă neintroduse, care cuprind ziua $i$, după care ştergem din heap intervalele care nu mai cuprind ziua $i$. Dacă heap-ul devine vid, nu există soluţie, în caz contrar cuplăm ziua $i$ cu intervalul din vârful heap-ului. Complexitate totală: $O(n log n)$.\r\n',3146,'public',NULL,NULL),('grigore-moisil-2009/solutii/peisaj','grigore-moisil-2009/solutii/peisaj','2009-04-05 20:30:48','2009-04-06 13:22:17','h2(#peisaj). \'Peisaj\':problema/peisaj\r\n\r\nRăspunsul la subpunctul a) este echivalent cu numărul parantezărilor corecte şi se poate calcula cu formula \'numerelor Catalan\':http://www.ginfo.ro/revista/15_5/mate1.pdf. Totuşi, putem observa, că subpunctul a) este de fapt un caz special al subpunctului b), când $K = 1$.\r\n\r\nPentru a rezolva subpunctul b) vom aplica _metoda programării dinamice_. O stare va fi definită prin trei parametri:\r\n\r\n* $B{~i,j,b~}  (i = 1, 2, ..., N; j = 0, 1, ..., N/2, b = {adevărat, fals})$ – numărul de posibilităţi prin care după aşezarea a $i$ beţişoare se poate ajunge la nivelul $j$, astfel încât cerinţa problemei (de a ajunge cel puţin odată la nivelul $K$) să fie sau nu satisfăcută.\r\n\r\nRecurenţele vor fi:\r\n\r\n* $B{~i,j, fals~} = B{~i-1,j-1,fals~} + B{~i-1,j+1,fals~}$\r\n* $B{~i,j,adevărat~} = B{~i-1,j-1,adevărat~} + B{~i-1,j+1,adevărat~}, dacă j != K$\r\n* $B{~i,j,adevărat~} = B{~i-1,j-1,fals~} + B{~i-1,j+1,adevărat~}, dacă j = K$\r\n\r\nSubpunctul c) se rezolvă tot cu metoda programării dinamice. Aici vom defini o stare în modul următor:\r\n\r\n* $C{~i,j,v,u~} (i = 1, 2, …, N, j = 0, 1, N/2, v = 0, 1, …, K, u = {/, \\}$ – numărul posibilităţilor prin care după aşezarea a $i$ beţişoare se poate ajunge la nivelul $j$, formând $v$ vârfuri în aşa fel încât ultimul beţişor aşezat să fie de forma $u$.\r\n\r\nRecurenţele vor fi:\r\n\r\n* $C{~i,j,v,/~} = C{~i-1,j-1,v,/~} + C{~i-1,j-1,v,\\~}$\r\n\r\n* $C{~i,j,v,\\~} = C{~i-1,j+1,v,\\~} + C{~i-1,j+1,v-1,/~}$\r\n\r\nRăspunsurile finale se vor afla în $B{~n,0,0~}$, $B{~n,0,1~}$, respectiv $C{~n,0,k,\\~}$. Complexitate finală: $Θ(N^2^ * K)$.\r\n',4772,'public',NULL,NULL),('grigore-moisil-2009/solutii/pari','grigore-moisil-2009/solutii/pari','2009-04-05 20:48:47','2009-04-06 06:24:08','h2(#pari). \'Pari\':problema/pari\r\n\r\nSoluţia acestei probleme se foloseşte de noţiuni elementare din teoria grafurilor. Pentru început, considerăm un graf $G$ format din mulţimea tuturor indicilor. Muchiile se vor construi între două noduri $(i, j)$ astfel încât resturile împărţirii la doi a celor două numere să fie diferite iar $cmmdc(i, j) &ge; d$. În continuare, considerăm că nodurile au două culori: alb pentru indicii care au paritate corespunzătoare şi negru pentru indicii care nu au paritatea corespunzătoare. Rezultă că dacă nodurile negre vor dispărea atunci vom găsi o soluţie. Ideea ce se conturează este ca din fiecare nod negru să parcurgem graful în lăţime sau adâncime adunând alternativ $+1$ şi $-1$ pe muchii, adică la numerele de pe poziţiile indicate de capetele muchiei, până când găsim un alt nod negru. Observăm astfel că pe acest lanţ, singurele noduri care îşi vor schimba culoarea vor fi doar nodul sursă şi nodul destinaţie.\r\n\r\nComplexitatea finală este $O(n * m)$, unde $n$ e numărul de elemente ale şirului $S$, iar $m$ numărul de perechi ce se pot forma.\r\n',3146,'public',NULL,NULL),('grigore-moisil-2009/solutii','grigore-moisil-2009/solutii','2009-04-05 16:25:15','2009-04-05 20:51:20','h1. Soluţii Grigore Moisil 2009\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Alibaba\':grigore-moisil-2009/solutii#alibaba\r\n* \'Palindrom2\':grigore-moisil-2009/solutii#palindrom2\r\n* \'Bete2\':grigore-moisil-2009/solutii#bete2\r\n* \'Fotbal\':grigore-moisil-2009/solutii#fotbal\r\n* \'Cuburi3\':grigore-moisil-2009/solutii#cuburi3\r\n* \'Motel\':grigore-moisil-2009/solutii#motel\r\n* \'Palindrom\':grigore-moisil-2009/solutii#palindrom\r\n* \'Peisaj\':grigore-moisil-2009/solutii#peisaj\r\n* \'Pari\':grigore-moisil-2009/solutii#pari\r\n\r\n==include(page=\"grigore-moisil-2009/solutii/alibaba\")==\r\n\r\n==include(page=\"grigore-moisil-2009/solutii/palindrom2\")==\r\n\r\n==include(page=\"grigore-moisil-2009/solutii/bete2\")==\r\n\r\n==include(page=\"grigore-moisil-2009/solutii/fotbal\")==\r\n\r\n==include(page=\"grigore-moisil-2009/solutii/cuburi3\")==\r\n\r\n==include(page=\"grigore-moisil-2009/solutii/motel\")==\r\n\r\n==include(page=\"grigore-moisil-2009/solutii/palindrom\")==\r\n\r\n==include(page=\"grigore-moisil-2009/solutii/peisaj\")==\r\n\r\n==include(page=\"grigore-moisil-2009/solutii/pari\")==',3146,'public',NULL,NULL),('zen','Profil brainwashed20','2009-04-05 21:42:27','2009-04-05 21:42:27','',9778,'public',NULL,NULL),('runda/ice_2','ice_2','2009-04-10 05:46:49','2009-04-10 05:46:49','h1. == roundparam(round_id=\"ice_2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"ice_2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"ice_2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ice_2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/ice_2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"ice_2\" score=\"1\")==',9782,'round: ice_2',NULL,NULL),('runda/concurs_gimnaziu_nivel_lot_gminaziu_3_probleme','concurs_gimnaziu_nivel_lot_gminaziu_3_probleme','2009-04-07 19:40:34','2009-04-07 19:40:34','h1. == roundparam(round_id=\"concurs_gimnaziu_nivel_lot_gminaziu_3_probleme\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"concurs_gimnaziu_nivel_lot_gminaziu_3_probleme\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"concurs_gimnaziu_nivel_lot_gminaziu_3_probleme\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"concurs_gimnaziu_nivel_lot_gminaziu_3_probleme\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/concurs_gimnaziu_nivel_lot_gminaziu_3_probleme/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"concurs_gimnaziu_nivel_lot_gminaziu_3_probleme\" score=\"1\")==',393,'round: concurs_gimnaziu_nivel_lot_gminaziu_3_probleme',NULL,NULL),('runda/concurs_gimnaziu_nivel_lot_gminaziu_3_probleme/clasament','Clasament concurs_gimnaziu_nivel_lot_gminaziu_3_probleme','2009-04-07 19:40:34','2009-04-07 19:40:34','h1. Clasament ==roundparam(round_id=\"concurs_gimnaziu_nivel_lot_gminaziu_3_probleme\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"concurs_gimnaziu_nivel_lot_gminaziu_3_probleme\")==',393,'round: concurs_gimnaziu_nivel_lot_gminaziu_3_probleme',NULL,NULL),('runda/concurs_gimnaziu_nivel_lot_gimnaziu_3_probleme','runda/concurs_gimnaziu_nivel_lot_gimnaziu_3_probleme','2009-04-08 06:06:30','2009-04-08 06:18:47','nu merge Paul :D\r\nmerge acum runda_gimnaziu_doi',393,'public',NULL,NULL),('runda/loool/clasament','Clasament loool','2009-04-06 08:34:26','2009-04-06 08:34:26','h1. Clasament ==roundparam(round_id=\"loool\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"loool\")==',9995,'round: loool',NULL,NULL),('runda/moisil_reload1','moisil_reload1','2009-04-06 09:29:35','2009-04-06 09:29:35','h1. == roundparam(round_id=\"moisil_reload1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"moisil_reload1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil_reload1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil_reload1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/moisil_reload1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"moisil_reload1\" score=\"1\")==',5748,'round: moisil_reload1',NULL,NULL),('runda/moisil_reload1/clasament','Clasament moisil_reload1','2009-04-06 09:29:35','2009-04-06 09:29:35','h1. Clasament ==roundparam(round_id=\"moisil_reload1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil_reload1\")==',5748,'round: moisil_reload1',NULL,NULL),('runda/moisil_reloaded1','moisil_reloaded1','2009-04-06 09:38:50','2009-04-06 09:38:50','h1. == roundparam(round_id=\"moisil_reloaded1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"moisil_reloaded1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil_reloaded1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil_reloaded1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/moisil_reloaded1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"moisil_reloaded1\" score=\"1\")==',5748,'round: moisil_reloaded1',NULL,NULL),('runda/moisil_reloaded1/clasament','Clasament moisil_reloaded1','2009-04-06 09:38:50','2009-04-06 09:38:50','h1. Clasament ==roundparam(round_id=\"moisil_reloaded1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil_reloaded1\")==',5748,'round: moisil_reloaded1',NULL,NULL),('runda/moisil_again','moisil_again','2009-04-06 09:41:29','2009-04-06 09:41:29','h1. == roundparam(round_id=\"moisil_again\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"moisil_again\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil_again\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil_again\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/moisil_again/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"moisil_again\" score=\"1\")==',5748,'round: moisil_again',NULL,NULL),('runda/moisil_again/clasament','Clasament moisil_again','2009-04-06 09:41:29','2009-04-06 09:41:29','h1. Clasament ==roundparam(round_id=\"moisil_again\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"moisil_again\")==',5748,'round: moisil_again',NULL,NULL),('runda/ciuperca_challenge','ciuperca_challenge','2009-04-06 09:51:04','2009-04-06 09:51:04','h1. == roundparam(round_id=\"ciuperca_challenge\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"ciuperca_challenge\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"ciuperca_challenge\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ciuperca_challenge\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/ciuperca_challenge/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"ciuperca_challenge\" score=\"1\")==',8456,'round: ciuperca_challenge',NULL,NULL),('runda/ciuperca_challenge/clasament','Clasament ciuperca_challenge','2009-04-06 09:51:04','2009-04-06 09:51:04','h1. Clasament ==roundparam(round_id=\"ciuperca_challenge\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"ciuperca_challenge\")==',8456,'round: ciuperca_challenge',NULL,NULL),('utilizator/pufuleti_sange','Profil pufuleti_sange','2009-04-06 11:39:27','2009-04-06 11:39:27','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',10091,'public',NULL,NULL),('runda/free.gigi','free.gigi','2009-04-06 13:54:09','2009-04-06 13:54:09','h1. == roundparam(round_id=\"free.gigi\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"free.gigi\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"free.gigi\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"free.gigi\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/free.gigi/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"free.gigi\" score=\"1\")==',6953,'round: free.gigi',NULL,NULL),('runda/free.gigi/clasament','Clasament free.gigi','2009-04-06 13:54:09','2009-04-06 13:54:09','h1. Clasament ==roundparam(round_id=\"free.gigi\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"free.gigi\")==',6953,'round: free.gigi',NULL,NULL),('runda/wrong-contest','wrong-contest','2009-04-06 14:46:10','2009-04-06 14:46:10','h1. == roundparam(round_id=\"wrong-contest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"wrong-contest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"wrong-contest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"wrong-contest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/wrong-contest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"wrong-contest\" score=\"1\")==',7535,'round: wrong-contest',NULL,NULL),('runda/wrong-contest/clasament','Clasament wrong-contest','2009-04-06 14:46:10','2009-04-06 14:46:10','h1. Clasament ==roundparam(round_id=\"wrong-contest\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"wrong-contest\")==',7535,'round: wrong-contest',NULL,NULL),('runda/wrong-contest-2','wrong-contest-2','2009-04-06 15:06:39','2009-04-06 15:06:39','h1. == roundparam(round_id=\"wrong-contest-2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"wrong-contest-2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"wrong-contest-2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"wrong-contest-2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/wrong-contest-2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"wrong-contest-2\" score=\"1\")==',7535,'round: wrong-contest-2',NULL,NULL),('runda/wrong-contest-2/clasament','Clasament wrong-contest-2','2009-04-06 15:06:39','2009-04-06 15:06:39','h1. Clasament ==roundparam(round_id=\"wrong-contest-2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"wrong-contest-2\")==',7535,'round: wrong-contest-2',NULL,NULL),('runda/wrong-contest-3','wrong-contest-3','2009-04-06 15:11:13','2009-04-06 15:11:13','h1. == roundparam(round_id=\"wrong-contest-3\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"wrong-contest-3\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"wrong-contest-3\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"wrong-contest-3\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/wrong-contest-3/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"wrong-contest-3\" score=\"1\")==',7535,'round: wrong-contest-3',NULL,NULL),('runda/wrong-contest-3/clasament','Clasament wrong-contest-3','2009-04-06 15:11:13','2009-04-06 15:11:13','h1. Clasament ==roundparam(round_id=\"wrong-contest-3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"wrong-contest-3\")==',7535,'round: wrong-contest-3',NULL,NULL),('runda/wrong-contest-4','wrong-contest-4','2009-04-06 15:24:32','2009-04-06 15:24:32','h1. == roundparam(round_id=\"wrong-contest-4\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"wrong-contest-4\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"wrong-contest-4\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"wrong-contest-4\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/wrong-contest-4/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"wrong-contest-4\" score=\"1\")==',7535,'round: wrong-contest-4',NULL,NULL),('runda/wrong-contest-4/clasament','Clasament wrong-contest-4','2009-04-06 15:24:32','2009-04-06 15:24:32','h1. Clasament ==roundparam(round_id=\"wrong-contest-4\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"wrong-contest-4\")==',7535,'round: wrong-contest-4',NULL,NULL),('runda/wrong-contest-5/clasament','Clasament wrong-contest-5','2009-04-06 15:49:58','2009-04-06 15:49:58','h1. Clasament ==roundparam(round_id=\"wrong-contest-5\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"wrong-contest-5\")==',7535,'round: wrong-contest-5',NULL,NULL),('runda/wrong-contest-5','wrong-contest-5','2009-04-06 15:49:58','2009-04-06 15:49:58','h1. == roundparam(round_id=\"wrong-contest-5\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"wrong-contest-5\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"wrong-contest-5\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"wrong-contest-5\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/wrong-contest-5/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"wrong-contest-5\" score=\"1\")==',7535,'round: wrong-contest-5',NULL,NULL),('runda/all.you.can.happily.code','all.you.can.happily.code','2009-04-07 07:27:38','2009-04-07 07:27:38','h1. == roundparam(round_id=\"all.you.can.happily.code\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"all.you.can.happily.code\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"all.you.can.happily.code\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"all.you.can.happily.code\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/all.you.can.happily.code/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"all.you.can.happily.code\" score=\"1\")==',5021,'round: all.you.can.happily.code',NULL,NULL),('runda/all.you.can.happily.code/clasament','Clasament all.you.can.happily.code','2009-04-07 07:27:38','2009-04-07 07:27:38','h1. Clasament ==roundparam(round_id=\"all.you.can.happily.code\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"all.you.can.happily.code\")==',5021,'round: all.you.can.happily.code',NULL,NULL),('runda/the_wild_west','the_wild_west','2009-04-07 08:46:34','2009-04-07 09:51:51','h1. == roundparam(round_id=\"The_Wild_West\" param=\"title\") ==\r\n\r\n    Fermierul Frank a intrat intr-o mare incurcatura. crezand ca va avea o recolta bogata anul acesta a imprumutat din banca o suma mare de bani. Dar plantatia lui a fost distrusa de inundatie. Acum el mai are doar niste vaci si daca nu plateste va pierde ferma. Din fericire exista o scapara daca reuseste sa treaca granita si sa vanda la un pret foarte bun carne de vita ilegal. El are nevoie neaparat de ajutor si va roaga pe voi sal ajutati deoarece nu a mai calatorit atat departe de casa si nu stie sa se descurce.\r\n\r\n\r\n== roundregister(round_id=\"the_wild_west\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"the_wild_west\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"the_wild_west\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/the_wild_west/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"the_wild_west\" score=\"1\")==',7670,'round: the_wild_west',NULL,NULL),('runda/the_wild_west/clasament','Clasament the_wild_west','2009-04-07 08:46:34','2009-04-07 08:46:34','h1. Clasament ==roundparam(round_id=\"the_wild_west\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"the_wild_west\")==',7670,'round: the_wild_west',NULL,NULL),('runda/barbari','barbari','2009-04-07 09:58:39','2009-04-07 10:09:44','h1. == roundparam(round_id=\"barbari\" param=\"title\") ==\r\n\r\n   Tara a fost atacata de barbari. Vin din toate partile si nu poti spune niciodata unde vor ataca data viitoare. Marele comadant de razboi al tarii a stabilit o strategie petru invingerea barbarilor. El trebuie sa stabileasca unde se afla sediul lor si cum lupta ei dupa care el va trebui sa adune si sa trimita repede soldatii in orasele tinte. Dupa ce vor pleca barbarii el trebuie sa stabileasca o masura de protectie impotriva unei noi aparitii a barbarilor. Daca il ajutati sa indeplineasca planul el va garanteaza ca veti fi faimosi.   \r\n\r\n\r\n== roundregister(round_id=\"barbari\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"barbari\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"barbari\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/barbari/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"barbari\" score=\"1\")==',7670,'round: barbari',NULL,NULL),('runda/barbari/clasament','Clasament barbari','2009-04-07 09:58:39','2009-04-07 09:58:39','h1. Clasament ==roundparam(round_id=\"barbari\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"barbari\")==',7670,'round: barbari',NULL,NULL),('runda/porc','porc','2009-04-22 17:00:57','2009-04-22 17:00:57','h1. == roundparam(round_id=\"porc\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"porc\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"porc\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"porc\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/porc/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"porc\" score=\"1\")==',6333,'round: porc',NULL,NULL),('runda/porc/clasament','Clasament porc','2009-04-22 17:00:57','2009-04-22 17:00:57','h1. Clasament ==roundparam(round_id=\"porc\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"porc\")==',6333,'round: porc',NULL,NULL),('runda/runda_de_porc','runda_de_porc','2009-04-22 17:02:08','2009-04-22 17:02:08','h1. == roundparam(round_id=\"runda_de_porc\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"runda_de_porc\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"runda_de_porc\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"runda_de_porc\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/runda_de_porc/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"runda_de_porc\" score=\"1\")==',6333,'round: runda_de_porc',NULL,NULL),('runda/runda_de_porc/clasament','Clasament runda_de_porc','2009-04-22 17:02:08','2009-04-22 17:02:08','h1. Clasament ==roundparam(round_id=\"runda_de_porc\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"runda_de_porc\")==',6333,'round: runda_de_porc',NULL,NULL),('utilizator/sima_cotizo','Profil sima_cotizo','2006-11-24 21:03:54','2009-06-29 18:49:39','h2. Studii:\r\n\r\n* Student la Jacobs University, Bremen\r\n* Absolvent al Colegiului National \"I.L. Caragiale\" Ploiesti (promotia 2009)\r\n\r\n\r\nh2. Distinctii primite la informatica:\r\n\r\n* Membru al **lotului national** 2009\r\n* **ONI 2009** (clasa a 12-a) : mentiune (locul 7)\r\n* **ONI 2008** (clasa a 11-a) : medalie de aur (locul 6)\r\n* **Finala _.campion_ 2007** : locul 5\r\n* **ONI 2007** (clasa a 10-a) : premiul 3, locul 4\r\n* **Finala _.campion_ 2006**: participant [parca locul 8]\r\n* **ONI 2006** (clasa a 9-a) : premiul 3, locul 4\r\n* **Finala _preONI_ 2006** : locul 4 \r\n\r\nh2. Cu ce am \"incurcat\" infoarena:\r\n\r\n# \'Articolul despre arbori de intervale\':arbori-de-intervale\r\n# \'Articolul (inca neterminat) despre geometrie analitica\':notiuni-de-geometrie-si-aplicatii\r\n# Problema \'\"Evaluare de expresii\"\':problema/evaluare din \'arhiva educationala\':arhiva-educationala\r\n# Problemele de clasele XI-XII de la ONI 2008: \'albinuta\':problema/albinuta , \'curent\':problema/curent , \'pviz\':problema/pviz , \'atac2\':problema/atac2 , \'drum2\':problema/drum2 , \'virus\':problema/virus\r\n# Problemele \'nomem\':problema/nomem , \'pattern\':problema/pattern si \'zeroc\':problema/zeroc de la Barajele din cadrul Lotului de la Cluj, 2009\r\n\r\nh2. Rhide pe Linux:\r\n\r\nAm atasat \'arhiva\':http://infoarena.ro/utilizator/sima_cotizo?action=download&file=rhide_kit_linux.tar de Rhide, se gasesc in ea si instructiuni de instalare. ',3270,'protected',NULL,NULL),('algoritmiada-2009/runda-finala','Algoritmiada 2009, Runda Finala','2008-11-30 16:37:06','2009-05-09 07:36:23','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Algoritmiada 2009, Runda Finala\r\n\r\n(htabs)*(active) \'Despre&hellip;\':algoritmiada-2009/runda-finala\r\n* \'Program\':algoritmiada-2009/runda-finala/program\r\n* \'Regulament\':algoritmiada-2009/runda-finala/regulament\r\n* \'Probleme\':algoritmiada-2009/runda-finala/probleme\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-finala/5-8\r\n* \'Poze\':algoritmiada-2009/runda-finala/poze\r\n\r\nFinala concursului Algoritmiada 2009 se desfasoara in *Brasov*, la \'Colegiul National de Informatica \"Grigore Moisil\"\':http://www.moisilbrasov.ro in perioada *1-3 mai 2009*.\r\n\r\n\'Premiile concursului\':algoritmiada-2009/premii Algoritmiada se vor acorda in functie de rezultatele rundei finale. Punctajele obtinute in perioada de calificare vor servi doar la departajare. \r\n\r\nConcurentiilor li se vor asigura cazarea si masa integral dar nu si costul transportului pana la locul unde se va desfasura concursul.\r\n\r\nh2. Calificare\r\n\r\nCalificarea in aceasta etapa se face exclusiv pe baza \'clasamentului din primele 3 runde\':algoritmiada-2009/clasament. Mentionam ca o persoana se poate califica la finala doar la grupa de varsta destinata lui si ca se va face si o identificare prin intermediul Cartii de Identiate (Buletin) sau Carnet de Note vizat si cu poza (pentru cei care nu au inca buletin) pentru a evita frauda. Daca aveti nelamuriri revedeti si \'regulamentul\':algoritmiada-2009/regulament. \r\n\r\n*Pentru concurentii care nu s-au calificat in finala, vom gazdui si o varianta online a concursului in paralel cu finala de la Brasov!* Aveti ocazia sa va comparati performanta cu cei care au ajuns in finala. ;) Nu se acorda premii participantilor online.\r\n\r\nStudiati \'programul de desfasurare\':algoritmiada-2009/runda-finala/program pentru mai multe informatii.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',75,'protected',NULL,NULL),('algoritmiada-2009/runda-finala/regulament','Algoritmiada 2009 - Runda Finala, Regulament','2009-04-25 20:06:06','2009-05-09 07:38:19','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Algoritmiada 2009, Runda Finala - Regulament\r\n\r\n(htabs)* \'Despre&hellip;\':algoritmiada-2009/runda-finala\r\n* \'Program\':algoritmiada-2009/runda-finala/program\r\n*(active) \'Regulament\':algoritmiada-2009/runda-finala/regulament\r\n* \'Probleme\':algoritmiada-2009/runda-finala/probleme\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-finala/5-8\r\n* \'Poze\':algoritmiada-2009/runda-finala/poze\r\n\r\nParticipantii la runda finala - atat cei calificati in finala de la Brasov cat si cei care participa online - se obliga sa respecte \'regulamentul concursului Algoritmiada\':algoritmiada-2009/regulament.\r\n\r\nIn plus, finala de la Brasov se desfasoara sub urmatoarele reguli:\r\n\r\n* Concurentii vor fi prezenti in salile de concurs la orele anuntate\r\n* Fiecare concurent va primi foi pentru ciorne (pix nu este inclus)\r\n* Timp de 1 ora dupa primirea subiectelor concurentii pot formula intrebari referitoare la enunturile problemelor; intrebarile se vor formula pe \'forum\':forum (se va specifica pe pagina rundei in ce topic anume se pun intrebarile); modalitate de formulare a intrebarile este identica cu cea de la primele 3 runde\r\n* In timpul probelor de concurs, concurentii:\r\n** nu vor avea asupra lor telefoane mobile sau alte mijloace de comunicatie\r\n** nu vor utiliza suporturi externe proprii (dischete/CD/flash-disk)\r\n** nu vor utiliza alte surse de documentare decat cele prezente pe calculator\r\n** nu vor incerca sa interfereze in nici un mod cu activitatile altui concurent\r\n** nu vor deteriora mediile de lucru\r\n** nu vor incerca sa interfereze cu sistemul de evaluare\r\n* In programele concurentilor nu sunt permise urmatoarele:\r\n** schimbarea drepturilor de acces la fisiere\r\n** atacul asupra securitatii sistemului sau evaluatorului\r\n** accesarea informatiilor despre sistemul de fisiere\r\n** executarea unor alte programe\r\n\r\nOrice incercare de frauda sau de a sabota desfasurarea corecta a concursului va fi urmata imediat de eliminarea elevului respectiv din concurs, cat si de pe _infoarena_.\r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',75,'protected',NULL,NULL),('algoritmiada-2009/runda-finala/probleme','Algoritmiada 2009, Runda Finala - Probleme','2009-04-25 20:25:57','2009-04-25 20:25:57','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Algoritmiada 2009, Runda Finala - Probleme\r\n\r\n==Include(page=\"template/algoritmiada-2009/runda-finala/probleme\")==\r\n\r\nAlege grupa de varsta.\r\n\r\n(htabs-2)* \'Clasele 5-8\':algoritmiada-2009/runda-finala/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-finala/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-finala/studenti\r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('template/algoritmiada-2009/runda-finala/probleme','template/algoritmiada-2009/runda-finala/probleme','2009-04-25 20:41:01','2009-05-09 07:39:14','(htabs)* \'Despre&hellip;\':algoritmiada-2009/runda-finala\r\n* \'Program\':algoritmiada-2009/runda-finala/program\r\n* \'Regulament\':algoritmiada-2009/runda-finala/regulament\r\n*(active) \'Probleme\':algoritmiada-2009/runda-finala/probleme\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-finala/5-8\r\n* \'Poze\':algoritmiada-2009/runda-finala/poze',75,'protected',NULL,NULL),('algoritmiada-2009/runda-finala/5-8','Algoritmiada 2009, Runda Finala, Clasele 5-8','2009-04-25 20:52:16','2009-04-25 20:52:16','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda5-5-8\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2009/runda-finala/probleme\")==\r\n\r\n(htabs-2)*(active) \'Clasele 5-8\':algoritmiada-2009/runda-finala/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-finala/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-finala/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda5-5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda5-5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda5-5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-finala/5-8.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda5-5-8\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('runda/algoritmiada2009-runda5-5-8','algoritmiada2009-runda5-5-8','2009-04-25 20:52:41','2009-04-25 20:52:41','h1. == roundparam(round_id=\"algoritmiada2009-runda5-5-8\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda5-5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda5-5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda5-5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/algoritmiada2009-runda5-5-8/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"algoritmiada2009-runda5-5-8\" score=\"1\")==',2028,'round: algoritmiada2009-runda5-5-8',NULL,NULL),('runda/algoritmiada2009-runda5-5-8/clasament','Clasament algoritmiada2009-runda5-5-8','2009-04-25 20:52:41','2009-04-25 20:52:41','h1. Clasament ==roundparam(round_id=\"algoritmiada2009-runda5-5-8\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"algoritmiada2009-runda5-5-8\")==',2028,'round: algoritmiada2009-runda5-5-8',NULL,NULL),('algoritmiada-2009/runda-finala/9-10','Algoritmiada 2009, Runda Finala, Clasele 9-10','2009-04-25 21:55:49','2009-04-25 21:55:49','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda5-9-10\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2009/runda-finala/probleme\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':algoritmiada-2009/runda-finala/5-8\r\n*(active) \'Clasele 9-10\':algoritmiada-2009/runda-finala/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-finala/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda5-9-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda5-9-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda5-9-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-finala/9-10.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda5-9-10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('runda/algoritmiada2009-runda5-9-10','algoritmiada2009-runda5-9-10','2009-04-25 21:56:08','2009-04-25 21:56:08','h1. == roundparam(round_id=\"algoritmiada2009-runda5-9-10\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda5-9-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda5-9-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda5-9-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/algoritmiada2009-runda5-9-10/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"algoritmiada2009-runda5-9-10\" score=\"1\")==',2028,'round: algoritmiada2009-runda5-9-10',NULL,NULL),('runda/algoritmiada2009-runda5-9-10/clasament','Clasament algoritmiada2009-runda5-9-10','2009-04-25 21:56:08','2009-04-25 21:56:08','h1. Clasament ==roundparam(round_id=\"algoritmiada2009-runda5-9-10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"algoritmiada2009-runda5-9-10\")==',2028,'round: algoritmiada2009-runda5-9-10',NULL,NULL),('algoritmiada-2009/runda-finala/11-12','Algoritmiada 2009, Runda Finala, Clasele 11-12','2009-04-25 22:17:43','2009-04-25 22:17:43','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda5-11-12\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2009/runda-finala/probleme\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':algoritmiada-2009/runda-finala/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-finala/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2009/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-finala/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda5-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda5-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda5-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-finala/11-12.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda5-11-12\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('runda/algoritmiada2009-runda5-11-12','algoritmiada2009-runda5-11-12','2009-04-25 22:18:02','2009-04-25 22:18:02','h1. == roundparam(round_id=\"algoritmiada2009-runda5-11-12\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda5-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda5-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda5-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/algoritmiada2009-runda5-11-12/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"algoritmiada2009-runda5-11-12\" score=\"1\")==',2028,'round: algoritmiada2009-runda5-11-12',NULL,NULL),('runda/algoritmiada2009-runda5-11-12/clasament','Clasament algoritmiada2009-runda5-11-12','2009-04-25 22:18:02','2009-04-25 22:18:02','h1. Clasament ==roundparam(round_id=\"algoritmiada2009-runda5-11-12\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"algoritmiada2009-runda5-11-12\")==',2028,'round: algoritmiada2009-runda5-11-12',NULL,NULL),('algoritmiada-2009/runda-finala/studenti','Algoritmiada 2009, Runda Finala, Studenti','2009-04-25 22:20:49','2009-04-25 22:20:49','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda5-studenti\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2009/runda-finala/probleme\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':algoritmiada-2009/runda-finala/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-finala/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-finala/11-12\r\n*(active) \'Studenti\':algoritmiada-2009/runda-finala/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda5-studenti\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda5-studenti\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda5-studenti\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-finala/studenti.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda5-studenti\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('runda/algoritmiada2009-runda5-studenti','algoritmiada2009-runda5-studenti','2009-04-25 22:21:13','2009-04-25 22:21:13','h1. == roundparam(round_id=\"algoritmiada2009-runda5-studenti\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda5-studenti\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda5-studenti\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda5-studenti\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/algoritmiada2009-runda5-studenti/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"algoritmiada2009-runda5-studenti\" score=\"1\")==',2028,'round: algoritmiada2009-runda5-studenti',NULL,NULL),('runda/algoritmiada2009-runda5-studenti/clasament','Clasament algoritmiada2009-runda5-studenti','2009-04-25 22:21:13','2009-04-25 22:21:13','h1. Clasament ==roundparam(round_id=\"algoritmiada2009-runda5-studenti\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"algoritmiada2009-runda5-studenti\")==',2028,'round: algoritmiada2009-runda5-studenti',NULL,NULL),('runda/super_easy','super_easy','2009-04-26 15:24:56','2009-04-26 15:24:56','h1. == roundparam(round_id=\"super_easy\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"super_easy\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"super_easy\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"super_easy\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/super_easy/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"super_easy\" score=\"1\")==',2380,'round: super_easy',NULL,NULL),('runda/super_easy/clasament','Clasament super_easy','2009-04-26 15:24:56','2009-04-26 15:24:56','h1. Clasament ==roundparam(round_id=\"super_easy\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"super_easy\")==',2380,'round: super_easy',NULL,NULL),('runda/tot','tot','2009-04-26 15:27:57','2009-04-26 15:27:57','h1. == roundparam(round_id=\"tot\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"tot\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"tot\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"tot\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/tot/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"tot\" score=\"1\")==',2380,'round: tot',NULL,NULL),('runda/tot/clasament','Clasament tot','2009-04-26 15:27:57','2009-04-26 15:27:57','h1. Clasament ==roundparam(round_id=\"tot\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"tot\")==',2380,'round: tot',NULL,NULL),('algoritmiada-2009/clasament/runda-finala/5-8','Algoritmiada 2009, Clasament Runda Finala, Clasele 5-8','2009-04-26 18:34:14','2009-04-26 18:39:54','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda5-5-8\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2009/runda-finala/rezultate\")==\r\n\r\n(htabs-2)*(active) \'Clasele 5-8\':algoritmiada-2009/clasament/runda-finala/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-finala/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-finala/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda5-5-8\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('template/algoritmiada-2009/runda-finala/rezultate','template/algoritmiada-2009/runda-finala/rezultate','2009-04-26 18:35:42','2009-05-09 07:39:39','(htabs)* \'Despre&hellip;\':algoritmiada-2009/runda-finala\r\n* \'Program\':algoritmiada-2009/runda-finala/program\r\n* \'Regulament\':algoritmiada-2009/runda-finala/regulament\r\n* \'Probleme\':algoritmiada-2009/runda-finala/probleme\r\n*(active) \'Rezultate\':algoritmiada-2009/clasament/runda-finala/5-8\r\n* \'Poze\':algoritmiada-2009/runda-finala/poze\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;',75,'protected',NULL,NULL),('algoritmiada-2009/clasament/runda-finala/9-10','Algoritmiada 2009, Clasament Runda Finala, Clasele 9-10','2009-04-26 18:38:38','2009-04-26 18:40:12','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda5-9-10\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2009/runda-finala/rezultate\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-finala/5-8\r\n*(active) \'Clasele 9-10\':algoritmiada-2009/clasament/runda-finala/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-finala/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda5-9-10\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('algoritmiada-2009/clasament/runda-finala/11-12','Algoritmiada 2009, Clasament Runda Finala, Clasele 11-12','2009-04-26 18:39:45','2009-05-02 11:06:19','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda5-11-12\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2009/runda-finala/rezultate\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-finala/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-finala/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2009/clasament/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-finala/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda5-11-12\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',1490,'protected',NULL,NULL),('algoritmiada-2009/clasament/runda-finala/studenti','Algoritmiada 2009, Clasament Runda Finala, Studenti','2009-04-26 18:41:24','2009-04-26 18:41:24','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda5-studenti\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2009/runda-finala/rezultate\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-finala/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-finala/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-finala/11-12\r\n*(active) \'Studenti\':algoritmiada-2009/clasament/runda-finala/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda5-studenti\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('andrici_cezar/string','andrici_cezar/Stringuri C++/Pas','2009-04-26 06:38:49','2009-04-28 17:38:25','h2. Stringuri in C++\r\n\r\n(toc){width: 25em}*{text-align:center} *Conţinut:*\r\n* \'Declararea\':andrici_cezar/string#declararea\r\n* \'Iniţializări\':andrici_cezar/string#initializari\r\n* \'Citirea\':andrici_cezar/string#citirea\r\n* \'Afişarea\':andrici_cezar/string#afisarea\r\n* \'Funcţii\':andrici_cezar/string#functii\r\n** \'Lungime şir\':andrici_cezar/string#strlen\r\n** \'Copierea\':andrici_cezar/string#strcpy\r\n** \'Compararea\':andrici_cezar/string#compararea\r\n* \'Probleme cu stringuri:\':andrici_cezar/string#string\r\n** \'Password\':problema/password\r\n** \'Litere\':problema/litere\r\n** \'Mesaj\':problema/mesaj\r\n\r\n\r\n{+Pointeri+} Variabile cara au ca valoare o adresă de memorie terminata cu terminator de sir {$\'\\0\'$};\r\n\r\nh3(#Declararea). Declarare:\r\n\r\n== code(cpp) |\r\n\r\nchar sir[lg+1],*p;\r\n\r\n//lg=lungime sirului + o pozitie pentru terminator\r\n//*p pointer\r\n\r\n==\r\n\r\nh3(#initializari). Iniţializări\r\n\r\n== code(cpp) |\r\n\r\nchar var[]=\"aeiouAEIOU\",*cif[]=\"0123456789\",sir[1000]=\"Exemplu de string 2009\";\r\n \r\n==\r\n\r\nh3(#citirea). Citirea\r\n\r\n* Text fară caractere albe\r\n\r\nCitire la {+iostream.h+} sau {+fstream.h+}\r\n\r\n== code(cpp) |\r\n\r\nfin>>sir;\r\n\r\n==\r\n\r\nsau la {+stdio.h+}\r\n\r\n== code(cpp) |\r\n\r\nscanf(\"%s\",&sir);\r\n\r\n==\r\n\r\n* Text cu caractere albe\r\n\r\nCitire la {+iostream.h+} sau {+fstream.h+}\r\n\r\n== code(cpp) |\r\n\r\nfin.get(sir,lg-max)\r\n\r\nfin.get(sir,lg-max,caracter-de-oprire)\r\n\r\n==\r\n\r\nSe citeşte şirul până la caracter-de-oprire, dar fără a depăşi lg-maxş\r\n\r\n== code(cpp) |\r\n\r\nfin.get(sir,20,\' \'); //sir=\"exemplu\"\r\nfin.get(sir,20,\'.\'); //sir=\"exemplu de string 20\"\r\nfin.get(sir,999); //sir=\"exemplu de string 2009\"\r\n\r\n==\r\n\r\n* Citirea cu $fin.gettline$\r\n\r\n== code(cpp) |\r\n\r\nfin.gettline(sir,lg_max);\r\nfin.gettline(sir,lg_max,caracter-de-oprire);\r\n\r\n==\r\n\r\n$gettline$ extrage şi caracterul de oprire din zona breffer(intermediară);\r\n$get$ doar verifică dacă urmează caracterul de oprire, nu îl extrage;\r\n\r\n== code(cpp) |\r\n\r\nfin.get(); //extrage caracterul curent din breffer\r\ngets(sir); // citeşte şirul curent (poate contine şi spaţii)\r\n\r\n==\r\n\r\nh3(#afisarea). Afişarea\r\n\r\nAfisarea în {+iostream.h+} şi {+fstream.h+}\r\n\r\n==code(cpp) |\r\n\r\nfout<<sir;\r\n\r\n==\r\n\r\nsau în {+stdio.h+}\r\n\r\n==code(cpp) |\r\n\r\nprintf(\"%s\",sir);\r\n\r\n==\r\n\r\nh3(#functii). Funcţii\r\n\r\n\r\nh4(#strlen). Aflarea lungimii unui sir\r\n\r\n\r\n==code(cpp) |\r\n\r\na=\"String\"\r\nn=strlen(a); //n=6\r\n\r\n==\r\n\r\nh4(#strcpy). Copierea\r\n \r\n\r\n* {$a$}<-{$b$}\r\n\r\n==code(cpp) |\r\n\r\nstrcpy(a,b);\r\n\r\n==\r\n\r\n* $a$ <- secventa din $b$\r\n\r\n==code(cpp) |\r\n\r\nb=\"String\";\r\nstrcpy(a,b,nr_caractere);\r\na[nr_caractere]=\'\\0\'; \r\n\r\nb=\"String\";\r\nstrcpy(a,b,5);\r\na[5]=\'\\0\'; //a=\"Strin\"\r\n\r\nb=\"String\";\r\nstrcpy(a,b+2,2);\r\na[2]=\'\\0\';// a=\"ri\";\r\n\r\n==\r\n\r\nh4(#compararea). Compararea\r\n\r\n* \"Aer<\"aer\" dacă folosim funcţia $strcmp$ care face diferenţa dintre literele mici si cele mari\r\n\r\n==code(cpp) |\r\n\r\nstrcmp(\"Aer\",\"aer\");// <\r\nstrcmp(\"aer\",\"Aer\");// >\r\nstrcmp(\"aer\",\"aer\");// =\r\n\r\nstrcmp(a,b);\r\n\r\n==\r\n\r\n* \"AeR\"=\"aer\" dacă folosim funcţia $stricmp$ care nu face diferenţa dintre literele mici si cele mari\r\n\r\n==code(cpp) |\r\n\r\nstricmp(\"AeR\",\"aer\");//=\r\nstricmp(\"abc\",\"abd\");//<\r\nstricmp(\"abd\",\"abc\");//>\r\n\r\nstricmp(a,b);\r\n\r\n==\r\n\r\nh3(#string). Probleme cu stringuri\r\n\r\n\'Password\':http://infoarena.ro/problema/password/ (\'Rotatie lexicografic minima\':http://infoarena.ro/rotatie-lexicografic-minima/)\r\n\'Litere\':http://infoarena.ro/problema/litere/\r\n\'Mesaj\':http://infoarena.ro/problema/mesaj/',7668,'public',NULL,NULL),('algoritmiada-2009/runda-finala/program','Algoritmiada 2009, Runda Finala - Program de desfasurare','2009-04-26 18:47:43','2009-05-09 07:38:13','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Algoritmiada 2009, Runda Finala - Program de desfasurare\r\n\r\n(htabs)* \'Despre&hellip;\':algoritmiada-2009/runda-finala\r\n*(active) \'Program\':algoritmiada-2009/runda-finala/program\r\n* \'Regulament\':algoritmiada-2009/runda-finala/regulament\r\n* \'Probleme\':algoritmiada-2009/runda-finala/probleme\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-finala/5-8\r\n* \'Poze\':algoritmiada-2009/runda-finala/poze\r\n\r\nProgramul de mai jos este deschis la sugestii si se poate modifica pe parcursul desfasurarii concursului.\r\n\r\ntable{width:75%}. |_. Data |_. Activitati |\r\n| Vineri, 1 mai 2009 | * 12:00 - 17:00 Sosire si cazare participanti la hotelurile Decebal si Aurora\r\n* 14:00 - 15:00 Pranz\r\n* 18:00 - 19:00 Deschidere oficiala\r\n* 19:00 - 20:00 Cina\r\n* 20:00 - 22:00 Program liber |\r\n| Sambata, 2 mai 2009 | * 08:00 - 09:00 Mic dejun\r\n* 09:00 - 09:30 Acomodare, testarea statiilor de lucru \r\n* *09:30 - 14:30 Proba de concurs*\r\n* 15:00 - 16:00 Pranz\r\n* 16:00 - 19:00 Vizitarea orasului\r\n* 19:00 - 20:00 Cina\r\n* 20:30 - 23:30 Fotbal in sala | \r\n| Duminica, 3 mai 2009 | * 08:00 - 09:00 Mic dejun\r\n* 09:00 - 09:30 Evaluare live \r\n* 09:30 - 10:30 Consultare borderouri evaluare, contestatii\r\n* 11:00 - 12:00 Festivitatea de premiere\r\n* 12:30 - 13:30 Pranz\r\n* Plecare |\r\n\r\nFestivitatea de deschidere si cea de premiere vor avea loc in Sala Festiva a C.N. \"Grigore Moisil\".\r\n\r\nMasa se serveste la restaurantul Cramele lui Decebal II.\r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',75,'protected',NULL,NULL),('runda/porc_ag','porc_ag','2010-02-08 20:34:01','2010-02-08 20:34:01','h1. == roundparam(round_id=\"porc_ag\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"porc_ag\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"porc_ag\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"porc_ag\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"porc_ag\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/porc_ag/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"porc_ag\" score=\"1\")==',6333,'round: porc_ag',NULL,NULL),('runda/porc2','porc2','2009-04-29 19:22:37','2009-04-29 19:22:37','h1. == roundparam(round_id=\"porc2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"porc2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"porc2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"porc2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/porc2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"porc2\" score=\"1\")==',6333,'round: porc2',NULL,NULL),('runda/porc2/clasament','Clasament porc2','2009-04-29 19:22:37','2009-04-29 19:22:37','h1. Clasament ==roundparam(round_id=\"porc2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"porc2\")==',6333,'round: porc2',NULL,NULL),('newsletter/algoritmiada-2009-4','Algoritmiada, Runda Finală','2009-04-30 07:19:46','2009-04-30 08:31:33','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎn curând începe a patra şi ultima rundă a concursului Algoritmiada, cel mai mare şi cel mai tare concurs organizat de infoarena!  :)\r\n\r\nLa Algoritmiada participă elevi de gimnaziu, elevi de liceu, *dar şi studenţi*! Avem grupe separate pentru fiecare. Studenţii pot fi chiar masteranzi sau doctoranzi.\r\n\r\nFinala se desfăşoară în acest weekend la Colegiul Naţional de Informatică „Grigore Moisil” din Braşov. Dacă nu te-ai calificat la finală, ai ocazia să-ţi măsori forţele cu cei mai buni participând online! Intră în arenă şi vezi pe ce loc te situezi printre elite!\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Runda Finală se desfăşoară\r\n*Sâmbătă, 2 Mai 2009, orele 09^30^ - 14^30^*. |\r\n\r\nVezi \'pagina concursului\':algoritmiada-2009 pentru mai multe informaţii.\r\n\r\nSucces!\r\n\r\nh2{font-size: 12pt}.  Despre Algoritmiada, Runda Finală\r\n\r\nAlgoritmiada este un concurs nou, cu premii, organizat de infoarena. Concursul s-a desfăşurat în 3 runde online de calificare şi aceasta finală on-site. Cei mai buni vor câştiga premii serioase, în bani şi obiecte.\r\n\r\nLa Finală vei avea la dispoziţie $5 ore$ să rezolvi $3$ probleme de natură algoritmică. Concurenţii sunt împărţiţi în 4 grupe de vârstă: gimnaziu, clasele 9-10, clasele 11-12 şi studenţi (inclusiv masteranzi şi doctoranzi).\r\n\r\nSubiectele vor fi propuse de către o echipă de foşti şi actuali olimpici la informatică: \r\n\r\n* ==User(user=\"astronomy\" type=\"link\")==\r\n* ==User(user=\"wefgef\" type=\"link\")==\r\n* ==User(user=\"bogdan2412\" type=\"link\")==\r\n* ==User(user=\"gcosmin\" type=\"link\")==\r\n* ==User(user=\"prostu\" type=\"link\")==\r\n* ==User(user=\"filipb\" type=\"link\")==\r\n\r\nPentru organizarea şi buna desfăşurare a Rundei Finale se vor ocupa:\r\n\r\n* ==User(user=\"wefgef\" type=\"link\")==\r\n* ==User(user=\"bogdan2412\" type=\"link\")==\r\n* ==User(user=\"judy_k\" type=\"link\")==\r\n* ==User(user=\"wickedman\" type=\"link\")==\r\n* ==User(user=\"svalentin\" type=\"link\")==\r\n\r\nMulţumim partenerilor noştri \'*Adobe Romania*\':http://myadobe.ro şi \'*Colegiul Naţional de Informatică „Grigore Moisil”*\':http://www.moisilbrasov.ro pentru sprijinul acordat, atât financiar cât şi logistic.\r\n\r\nÎţi urăm succes şi te asteptăm pe infoarena!\r\n\r\nh2{font-size: 12pt}. Care sunt finaliştii?\r\n\r\n==include(page=\"algoritmiada-2009/finalisti\")==\r\n\r\n==include(username=\"%username%\" round_url=\"algoritmiada-2009/runda-finala\" page=\"template/newsletter/rating\")==\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/doi-la-suta-call\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==\r\n',13,'protected',NULL,NULL),('runda/for_begginers','for_begginers','2009-04-30 07:30:12','2009-04-30 07:30:12','h1. == roundparam(round_id=\"for_begginers\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"for_begginers\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"for_begginers\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"for_begginers\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/for_begginers/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"for_begginers\" score=\"1\")==',7667,'round: for_begginers',NULL,NULL),('runda/for_begginers/clasament','Clasament for_begginers','2009-04-30 07:30:12','2009-04-30 07:30:12','h1. Clasament ==roundparam(round_id=\"for_begginers\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"for_begginers\")==',7667,'round: for_begginers',NULL,NULL),('algoritmiada-2009/finalisti','Finaliști Algoritmiada 2009','2009-04-30 08:10:16','2009-04-30 08:28:12','Aceştia sunt finaliştii Algoritmiada 2009 *care au confirmat* participarea la runda finală din Braşov.\r\n\r\nh4. Clasele 5-8\r\n\r\n# ==user(user=\"gavrilavlad\" type=\"link\")==\r\n# ==user(user=\"taloibogdan\" type=\"link\")==\r\n# ==user(user=\"GheorgheMihai\" type=\"link\")==\r\n# ==user(user=\"marius21\" type=\"link\")==\r\n# ==user(user=\"antoanela\" type=\"link\")==\r\n# ==user(user=\"eudanip\" type=\"link\")==\r\n\r\nh4. Clasele 9-10\r\n\r\n# ==user(user=\"CezarMocan\" type=\"link\")==\r\n# ==user(user=\"andrei-alpha\" type=\"link\")==\r\n# ==user(user=\"savim\" type=\"link\")==\r\n# ==user(user=\"raduzer\" type=\"link\")==\r\n# ==user(user=\"Protoman\" type=\"link\")==\r\n# ==user(user=\"toni2007\" type=\"link\")==\r\n# ==user(user=\"hadesgames\" type=\"link\")==\r\n# ==user(user=\"Diaconu\" type=\"link\")==\r\n# ==user(user=\"AndreyP\" type=\"link\")==\r\n# ==user(user=\"tvlad\" type=\"link\")==\r\n# ==user(user=\"vanila_cpp\" type=\"link\")==\r\n\r\nh4. Clasele 11-12\r\n\r\n# ==user(user=\"bogdanhm999\" type=\"link\")==\r\n# ==user(user=\"mihai_florea\" type=\"link\")==\r\n# ==user(user=\"stocarul\" type=\"link\")==\r\n# ==user(user=\"andrei.12\" type=\"link\")==\r\n# ==user(user=\"Scrazy\" type=\"link\")==\r\n# ==user(user=\"cotofana\" type=\"link\")==\r\n# ==user(user=\"Zilla\" type=\"link\")==\r\n# ==user(user=\"Mishu91\" type=\"link\")==\r\n# ==user(user=\"runnaway90\" type=\"link\")==\r\n# ==user(user=\"hasegandani\" type=\"link\")==\r\n\r\nh4. Studenţi\r\n\r\n# ==user(user=\"mugurelionut\" type=\"link\")==\r\n# ==user(user=\"Zeus\" type=\"link\")==\r\n# ==user(user=\"seal\" type=\"link\")==\r\n# ==user(user=\"SleepyOverlord\" type=\"link\")==\r\n# ==user(user=\"skipy\" type=\"link\")==\r\n# ==user(user=\"TYTUS\" type=\"link\")==\r\n# ==user(user=\"octav\" type=\"link\")==\r\n# ==user(user=\"rss1987\" type=\"link\")==\r\n# ==user(user=\"blasterz\" type=\"link\")==\r\n# ==user(user=\"diac_paul\" type=\"link\")==\r\n\r\n',13,'protected',NULL,NULL),('bogdan2412/temp','Algoritmiada 2009, Runda Finala - Program de desfasurare','2009-05-01 13:26:25','2009-05-01 13:26:48','==Include(page=\"template/algoritmiada-2009/header\")==\r\n\r\nh1. Algoritmiada 2009, Runda Finala - Program de desfasurare\r\n\r\nProgramul de mai jos este deschis la sugestii si se poate modifica pe parcursul desfasurarii concursului.\r\n\r\ntable{width:75%}. |_. Data |_. Activitati |\r\n| Vineri, 1 mai 2009 | * 12:00 - 17:00 Sosire si cazare participanti la hotelurile Decebal si Aurora\r\n* 14:00 - 15:00 Pranz\r\n* 18:00 - 19:00 Deschidere oficiala\r\n* 19:00 - 20:00 Cina\r\n* 20:00 - 22:00 Program liber |\r\n| Sambata, 2 mai 2009 | * 08:00 - 09:00 Mic dejun\r\n* 09:00 - 09:30 Acomodare, testarea statiilor de lucru \r\n* *09:30 - 14:30 Proba de concurs*\r\n* 15:00 - 16:00 Pranz\r\n* 16:00 - 19:00 Vizitarea orasului\r\n* 19:00 - 20:00 Cina\r\n* 20:30 - 23:30 Fotbal in sala | \r\n| Duminica, 3 mai 2009 | * 08:00 - 09:00 Mic dejun\r\n* 09:00 - 09:30 Evaluare live \r\n* 09:30 - 10:30 Consultare borderouri evaluare, contestatii\r\n* 11:00 - 12:00 Festivitatea de premiere\r\n* 12:30 - 13:30 Pranz\r\n* Plecare |\r\n\r\nFestivitatea de deschidere si cea de premiere vor avea loc in Sala Festiva a C.N. \"Grigore Moisil\".\r\n\r\nMasa se serveste la restaurantul Cramele lui Decebal II.\r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',1490,'protected',NULL,NULL),('algoritmiada-2010/runda-2/solutii','Solutii Algoritmiada 2010 Runda 2','2009-11-28 15:29:53','2009-12-20 13:56:02','h1. Solutii Algoritmiada 2010, Runda 2\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Popularitate\':algoritmiada-2010/runda-2/solutii#popularitate\r\n* \'Dinti\':algoritmiada-2010/runda-2/solutii#dinti\r\n* \'Secv9\':algoritmiada-2010/runda-2/solutii#secv9\r\n* \'Redu\':algoritmiada-2010/runda-2/solutii#redu\r\n* \'Jap2\':algoritmiada-2010/runda-2/solutii#jap2\r\n* \'Recurenta2\':algoritmiada-2010/runda-2/solutii#recurenta2\r\n* \'Palmieri\':algoritmiada-2010/runda-2/solutii#palmieri\r\n\r\n==include(page=\"algoritmiada-2010/runda-2/solutii/popularitate\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-2/solutii/dinti\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-2/solutii/secv9\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-2/solutii/redu\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-2/solutii/jap2\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-2/solutii/recurenta2\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-2/solutii/palmieri\")==',1792,'public',NULL,NULL),('runda/concurs12345','concurs12345','2009-07-18 17:37:06','2009-07-18 17:37:06','h1. == roundparam(round_id=\"concurs12345\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"concurs12345\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"concurs12345\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"concurs12345\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/concurs12345/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"concurs12345\" score=\"1\")==',10280,'round: concurs12345',NULL,NULL),('utilizator/wickedman','Cristian George Strat (wickedman)','2006-11-24 20:56:12','2010-03-24 07:10:18','h2. Despre mine\r\n\r\n* *Membru fondator şi fost Preşedinte al Asociaţiei infoarena* \'{!utilizator/domino?btn_viewmy_160x33.gif!}\':http://www.linkedin.com/in/cristiangeorgestrat\r\n* Co-fondator \'summify.com\':summify.com\r\n* Co-fondator \'balaur.ro\':balaur.ro\r\n* Co-fondator INNOVATE CONSULT, companie ce oferă servicii software şi networking\r\n* Google internship, summer 2008, Zurich, Switzerland\r\n* Google internship, summer 2007, Mountain View, California\r\n* Membru al comisiei ştiinţifice ONI 2009, clasa a IX-a\r\n* Presedinte al juriului de _Pagini Web_, \"InfoEducatie\":http://infoeducatie.ro/ 2006\r\n* Membru al juriului de _Programare_ \"InfoMatrix 2009\":http://infomatrix.ro/\r\n* Membru al juriului de _Programare_ \"InfoMatrix 2008\":http://infomatrix.ro/\r\n* Membru al juriului de _Pagini Web_ \"InfoEducatie\":http://infoeducatie.ro/ 2005\r\n* Membru al juriului de _Pagini Web_ la concursul Unirea 2005\r\n* Locurile I, I, II, III la concursul national de software si pagini web \"InfoEducatie\":http://infoeducatie.ro/\r\n* Locul II la concursul pe echipe EESTEC Olympics 2006\r\n* Finalist la \'Challenge24\':http://challenge24.org/\r\n* Locul 4 la ONI 2004\r\n* Finalist \'.campion\':http://campion.edu.ro/ 2004 \r\n* Calificare în lotul lărgit de informatică 2004\r\n\r\nh3. Publicaţii\r\n\r\n* \'Solving Maximum Flow Problems on Real World Bipartite Graphs\':http://www.siam.org/proceedings/alenex/2009/alx09_002_negruserin.pdf, Cosmin Silvestru Negruşeri, Mircea Bogdan Paşoi, Barbara Stanley, Clifford Stein, and Cristian George Strat (\'ALENEX09 Proceedings\':http://www.siam.org/proceedings/alenex/2009/alenex09.php)\r\n\r\nh3. Studii\r\n\r\n* -Student in anul IV la- Absolvent \"FMI\":http://fmi.unibuc.ro/ 2008, Universitatea Bucuresti\r\n* C.N. \"Gh. Rosca Codreanu\", Barlad, Jud. Vaslui\r\n\r\nh3. Trivia\r\n\r\n* infoarena a fost initial un proiect pentru concursul national \'InfoEducatie\':http://infoeducatie.ro/, sectiunea pagini web. La prima participare (in 2002) am primit locul III, iar in 2003 am castigat locul I.\r\n* l-am cunoscut pe \'Mircea Pasoi\':utilizator/domino si pe \'Crestez Leonard\':utilizator/fluffy pe canalul IRC #olimpada. Ei vroiau sa faca un site de probleme\r\n* am fost coleg de clasa cu \'Silviu Ganceanu\':utilizator/silviug in 9-11\r\n* ce vedeti acum este site-ul infoarena versiunea 2. \'Inainte era albastru\':http://web.archive.org/web/20060307025837/http://infoarena.devnet.ro/\r\n\r\nh3. Din presă\r\n\r\n* \'Creierele româneşti din solda „imperiului” Google\':http://www.evz.ro/articole/detalii-articol/819647/Creierele-romanesti-din-solda-imperiului-Google/, Evenimentul Zilei\r\n* \'Foştii olimpici îi antrenează pe concurenţii de la olimpiade\':http://www.adevarul.ro/articole/2007/fostii-olimpici-ii-antreneaza-pe-concurentii-de-la-olimpiade.html, Adevărul\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* == User(user=\"chucknorris\" type=\"tiny\") ==\r\n* == User(user=\"eval\" type=\"tiny\") ==\r\n',13,'protected',NULL,NULL),('runda/mission_impossible','mission_impossible','2009-05-04 16:22:38','2009-05-04 16:22:38','h1. == roundparam(round_id=\"mission_impossible\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"mission_impossible\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"mission_impossible\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"mission_impossible\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/mission_impossible/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"mission_impossible\" score=\"1\")==',6276,'round: mission_impossible',NULL,NULL),('runda/mission_impossible/clasament','Clasament mission_impossible','2009-05-04 16:22:39','2009-05-04 16:22:39','h1. Clasament ==roundparam(round_id=\"mission_impossible\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"mission_impossible\")==',6276,'round: mission_impossible',NULL,NULL),('runda/concurs_1','concurs_1','2009-05-04 16:29:23','2009-05-04 16:29:23','h1. == roundparam(round_id=\"concurs_1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"concurs_1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"concurs_1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"concurs_1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/concurs_1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"concurs_1\" score=\"1\")==',6276,'round: concurs_1',NULL,NULL),('runda/concurs_1/clasament','Clasament concurs_1','2009-05-04 16:29:23','2009-05-04 16:29:23','h1. Clasament ==roundparam(round_id=\"concurs_1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"concurs_1\")==',6276,'round: concurs_1',NULL,NULL),('runda/concurs_2','concurs_2','2009-05-04 16:38:53','2009-05-04 16:38:53','h1. == roundparam(round_id=\"concurs_2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"concurs_2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"concurs_2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"concurs_2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/concurs_2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"concurs_2\" score=\"1\")==',6276,'round: concurs_2',NULL,NULL),('runda/concurs_2/clasament','Clasament concurs_2','2009-05-04 16:38:53','2009-05-04 16:38:53','h1. Clasament ==roundparam(round_id=\"concurs_2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"concurs_2\")==',6276,'round: concurs_2',NULL,NULL),('blog/loturi-online','Loturi online','2009-05-07 09:53:27','2009-06-09 20:16:44','Iată o veste care mie mi se pare grozavă: anul acesta există şi o variantă online a loturilor naţionale de selecţie! Se pot simula în acelaşi timp cu loturile reale atât probele destinate seniorilor cât si cele de juniori. Intraţi \'aici\':http://eval.hangman.ro/ pentru mai multe detalii.\r\n\r\nIniţiativa este deosebit de utilă mai ales pentru cei dintre voi care aspiră la un loc în lotul naţional pentru anii viitori. Pentru (viitorii) studenţi poate fi o ocazie bună de distracţie cu probleme de cel mai înalt nivel.\r\n\r\nÎn clasa a 11-a, după ce am ieşit primul la ONI, am ratat de puţin lotul naţional - am fost al 2 sau al 3-lea sub linie. Cred că m-aş fi bucurat foarte mult să pot simula loturile \"real-time\" cu cei care au fost mai în formă ca mine la baraje. Aş fi avut o motivaţie în plus pentru continuarea pregătirii şi opurtunităţi suplimentare să rezolv probleme grele. Pentru că indiferent de rezultatul final eu mă simţeam foarte bine în timpul probelor de la ONI, baraje sau loturi. Şi am să vă mărturisesc şi de ce: pentru că timp de 4-5 ore reuşeam să mă concentrez asupra unor probleme frumoase şi grele.\r\n\r\nSper ca macăr câţiva dintre voi să gândească la fel şi să participe. Vă urez mult succes!',15,'protected',3898,NULL),('runda/masterhard','masterhard','2009-05-07 13:56:55','2009-05-07 13:56:55','h1. == roundparam(round_id=\"masterhard\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"masterhard\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"masterhard\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"masterhard\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/masterhard/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"masterhard\" score=\"1\")==',9795,'round: masterhard',NULL,NULL),('runda/masterhard/clasament','Clasament masterhard','2009-05-07 13:56:55','2009-05-07 13:56:55','h1. Clasament ==roundparam(round_id=\"masterhard\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"masterhard\")==',9795,'round: masterhard',NULL,NULL),('runda/go','go','2009-05-07 13:57:07','2009-05-07 13:57:07','h1. == roundparam(round_id=\"go\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"go\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"go\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"go\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/go/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"go\" score=\"1\")==',9795,'round: go',NULL,NULL),('runda/go/clasament','Clasament go','2009-05-07 13:57:07','2009-05-07 13:57:07','h1. Clasament ==roundparam(round_id=\"go\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"go\")==',9795,'round: go',NULL,NULL),('runda/test01','test01','2009-05-08 13:09:01','2009-05-08 13:09:01','h1. == roundparam(round_id=\"test01\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"test01\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"test01\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"test01\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/test01/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"test01\" score=\"1\")==',7271,'round: test01',NULL,NULL),('runda/test01/clasament','Clasament test01','2009-05-08 13:09:01','2009-05-08 13:09:01','h1. Clasament ==roundparam(round_id=\"test01\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"test01\")==',7271,'round: test01',NULL,NULL),('newsletter/doi-la-suta-2009','Sprijină infoarena!','2009-05-08 13:54:37','2009-05-08 17:19:58','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\ninfoarena are nevoie acum de sprijinul tău! Dacă apreciezi comunitatea infoarena, concursurile şi evenimentele organizate de noi, şi dacă doreşti să ne sprijini, citeşte mesajul de mai jos şi arată-l părinţilor tăi.\r\n\r\nConform \'Codului Fiscal\':http://www.edex.ro/articol_cod_fiscal_16661_Art.%2084:%20Stabilirea%20si%20plata%20impozitului%20pe%20venitul%20net%20anual%20impozabil.html, tu sau părinţii tăi aveţi dreptul să direcţionaţi către Asociaţia infoarena 2% din impozitul pe venit datorat la stat. Aceste contribuţii ne ajută enorm să ne desfăşurăm activitatea. În plus, ne bucurăm să vedem că munca pe care o depunem este apreciată.\r\n\r\n*Termenul limită este 15 mai 2009, deci într-o săptămână.* Procedura este simplă şi nu costă nimic!\r\n\r\nCiteşte în continuare ca să afli ce trebuie să faci.\r\n\r\nh2{font-size: 12pt}. Despre sistemul 2%\r\n\r\nCitat din \'doilasuta.ro\':http://www.doilasuta.ro:\r\n\r\nbq. Sistemul 2% permite contribuabililor persoane fizice să direcţioneze 2% din impozitul lor pe venit către o organizaţie neguvernamentală. Este un sistem prin care cetăţenii au posibilitatea să decidă în mod direct ce se întamplă cu impozitele lor. [...] Direcţionarea nu costă nimic.\r\n\r\n\'Mai multe informaţii despre 2% pentru infoarena\':doi-la-suta\r\n\r\nh2{font-size: 12pt}. Chiar funcţionează?\r\n\r\nMultă lume ne întreabă dacă sistemul chiar funcţionează, dacă direcţionările chiar ajung în contul infoarena. Răspunsul este da! În 2008 procedura \'a funcţionat\':/blog/doi-la-suta-2008-raport. Peste 50 de persoane au sprijinit infoarena direcţionând 2% din impozitul pe venit. Direcţionările au însumat 4.619 lei.\r\n\r\nAm fost surprinşi într-un mod plăcut de aceste contribuţii. Ne-am bucurat să vedem că munca pe care o depunem este apreciată.\r\n\r\nVezi întregul \'*raport despre 2% în 2008*\':blog/doi-la-suta-2008-raport.\r\n\r\nh2{font-size: 12pt}. La ce folosim aceste contribuţii?\r\n\r\nVom folosi contribuţiile venite pe această cale să:\r\n\r\n* oferim premii la concursurile infoarena: membrii comunităţii sunt mai motivaţi să se pregătească şi să participe la un concurs online de informatică atunci când se dau premii\r\n* organizăm finale de concursuri: în fiecare an organizăm \'un concurs\':algoritmiada-2009 cu finală; finala are menirea să ne strangă la un loc cu ce mai buni dintre elevii şi studenţii României pentru câteva zile şi să formăm noi prietenii\r\n* motivăm comunitatea să se \'implice\':implica-te\r\n* finanţăm \'proiecte infoarena\':propuneri\r\n\r\nCel mai recent exemplu de utilizare a fondurilor primite pe această cale - alături de fondurile primite de la sponsori - este \'Finala Algoritmiada 2009\':algoritmiada-2009/runda-finala pe care am organizat-o în Braşov în perioada 1-3 Mai. La finală am asigurat cazare şi mâncare pentru aproximativ 55 de persoane. De asemenea, am acordat premii în bani celor mai buni concurenţi.\r\n\r\ninfoarena ajută elevi şi studenţi să înveţe informatică şi programare. De 5 ani de zile organizăm concursuri de informatică, scriem articole, dezvoltăm software, facem schimb de experienţă şi idei. Credem cu tărie că împreună învăţăm mai bine.\r\n\r\nCiteşte mai multe \'despre infoarena\':despre-infoarena.\r\n\r\nh2{font-size: 12pt}. Contribuţia mea contează?\r\n\r\nDa! Pentru un venit lunar de 1.400 lei, deci un venit anual de 16.800 lei, suma direcţionată către infoarena corespunzătoare impozitului pe venit aferent este de aproximativ 53 lei. Această sumă acoperă cheltuielile de cazare ale unui concurent calificat la \'finala Algoritmiada\':algoritmiada-2009/runda-finala. Aceeaşi sumă acoperă cheltuielile a două \'şedinţe infoarena\':planificare.\r\n\r\nEste lesne de văzut că mai multe direcţionări şi/sau venituri mai mari se adună uşor la o sumă considerabilă. De exemplu, 10 direcţionări pot asigura fondul de premiere la un concurs infoarena.\r\n\r\nh2{font-size: 12pt}. Ce trebuie să fac?\r\n\r\nProcedura este simplă. Ai grijă să te încadrezi în *termenul limită de 15 mai 2009*.\r\n\r\n# Descarcă şi printează una din declaraţiile următoare:\r\n** \'*Declaraţia 230, pentru venituri numai din salarii*\':http://infoarena.ro/doi-la-suta?action=download&file=decl_230_2008-infoarena.pdf&safe_only=false\r\nsau\r\n** \'Declaraţia 200, pentru venituri şi din alte surse precum chirii, drepturi de autor etc.\':http://infoarena.ro/doi-la-suta?action=download&file=decl_200_2008-infoarena.pdf&safe_only=false\r\n# Completează declaraţia cu datele tale personale\r\n** Datele Asociaţiei infoarena au fost completate în prealabil de către noi, însă le găseşti \'aici\':doi-la-suta pentru orice eventualitate.\r\n** Nu e nevoie să calculezi suma ce urmează a fi virată. Dacă laşi rubrica „Suma” necompletată, organul fiscal va calcula şi va vira suma admisă, conform legii.\r\n# Depune declaraţia completată la administraţia financiară corespunzătoare domiciliului tău.\r\n** Alternativ poţi să rogi pe altcineva să depună declaraţia în locul tău, sau poţi să o trimiţi prin scrisoare recomandată către administraţia financiară.\r\n\r\nh2{font-size: 12pt}. Spune şi prietenilor tăi!\r\n\r\nOrice direcţionare contează, însă poţi avea un impact mai mare dacă spui şi prietenilor tăi. Declaraţiile nu trebuie depuse personal la administraţia financiară de către fiecare contribuabil. Ele pot fi depuse „la pachet” de către o singură persoană.\r\n\r\n\r\nÎţi mulţumim pentru sprijinul tău! Dacă ai întrebări, nu ezita să ne contactezi \'pe forum\':http://infoarena.ro/forum/?topic=2725.0 sau pe această adresă de email.',13,'protected',NULL,NULL),('blog/doi-la-suta-2009','Sprijină Asociația infoarena! Direcționează 2%','2009-05-09 07:33:41','2009-06-09 20:16:13','h1. Sprijină Asociaţia infoarena! Direcţionează 2%\r\n\r\ninfoarena are nevoie de sprijinul tău!\r\n\r\nConform \'Codului Fiscal\':http://www.edex.ro/articol_cod_fiscal_16661_Art.%2084:%20Stabilirea%20si%20plata%20impozitului%20pe%20venitul%20net%20anual%20impozabil.html, ai dreptul să direcţionezi către Asociaţia infoarena 2% din impozitul pe venit datorat la stat. Aceste contribuţii ne ajută enorm să ne desfăşurăm activitatea. În plus, ne bucurăm să vedem că munca pe care o depunem este apreciată. Procedura este simplă şi nu costă nimic!\r\n\r\n*Atenţie! Termenul limită este 15 mai 2009.*\r\n\r\n*Chiar funcţionează?*\r\n\r\nMultă lume ne întreabă dacă sistemul chiar funcţionează, dacă direcţionările chiar ajung în contul infoarena. Răspunsul este da! În 2008 procedura \'a funcţionat\':/blog/doi-la-suta-2008-raport. Peste 50 de persoane au sprijinit infoarena direcţionând 2% din impozitul pe venit. Direcţionările au însumat 4.619 lei. Vezi întregul \'*raport despre 2% în 2008*\':blog/doi-la-suta-2008-raport.\r\n\r\n*La ce folosim aceste contribuţii?*\r\n\r\nVom folosi contribuţiile venite pe această cale să:\r\n\r\n* oferim premii la concursurile infoarena: membrii comunităţii sunt mai motivaţi să se pregătească şi să participe la un concurs online de informatică atunci când se dau premii\r\n* organizăm finale de concursuri: în fiecare an organizăm \'un concurs\':algoritmiada-2009 cu finală; finala are menirea să ne strangă la un loc cu ce mai buni dintre elevii şi studenţii României pentru câteva zile şi să formăm noi prietenii\r\n* motivăm comunitatea să se \'implice\':implica-te\r\n* finanţăm \'proiecte infoarena\':propuneri\r\n\r\nCel mai recent exemplu de utilizare a fondurilor primite pe această cale - alături de fondurile primite de la sponsori - este \'Finala Algoritmiada 2009\':algoritmiada-2009/runda-finala pe care am organizat-o în Braşov în perioada 1-3 Mai. La finală am asigurat cazare şi mâncare pentru aproximativ 55 de persoane. De asemenea, am acordat premii în bani celor mai buni concurenţi.\r\n\r\ninfoarena ajută elevi şi studenţi să înveţe informatică şi programare. De 5 ani de zile organizăm concursuri de informatică, scriem articole, dezvoltăm software, facem schimb de experienţă şi idei. Credem cu tărie că împreună învăţăm mai bine.\r\n\r\nCiteşte mai multe \'despre infoarena\':despre-infoarena.\r\n\r\n*Contribuţia mea contează?*\r\n\r\nDa! Pentru un venit lunar de 1.400 lei, deci un venit anual de 16.800 lei, suma direcţionată către infoarena corespunzătoare impozitului pe venit aferent este de aproximativ 53 lei. Această sumă acoperă cheltuielile de cazare ale unui concurent calificat la \'finala Algoritmiada\':algoritmiada-2009/runda-finala. Aceeaşi sumă acoperă cheltuielile a două \'şedinţe infoarena\':planificare.\r\n\r\nEste lesne de văzut că mai multe direcţionări şi/sau venituri mai mari se adună uşor la o sumă considerabilă. De exemplu, 10 direcţionări pot asigura fondul de premiere la un concurs infoarena.\r\n\r\n*Ce trebuie să fac?*\r\n\r\nProcedura este simplă. Ai grijă să te încadrezi în *termenul limită de 15 mai 2009*.\r\n\r\n# Descarcă şi printează una din declaraţiile următoare:\r\n** \'*Declaraţia 230, pentru venituri numai din salarii*\':http://infoarena.ro/doi-la-suta?action=download&file=decl_230_2008-infoarena.pdf&safe_only=false\r\nsau\r\n** \'Declaraţia 200, pentru venituri şi din alte surse precum chirii, drepturi de autor etc.\':http://infoarena.ro/doi-la-suta?action=download&file=decl_200_2008-infoarena.pdf&safe_only=false\r\n# Completează declaraţia cu datele tale personale\r\n** Datele Asociaţiei infoarena au fost completate în prealabil de către noi, însă le găseşti \'aici\':doi-la-suta pentru orice eventualitate.\r\n** Nu e nevoie să calculezi suma ce urmează a fi virată. Dacă laşi rubrica „Suma” necompletată, organul fiscal va calcula şi va vira suma admisă, conform legii.\r\n# Depune declaraţia completată la administraţia financiară corespunzătoare domiciliului tău.\r\n** Alternativ poţi să rogi pe altcineva să depună declaraţia în locul tău, sau poţi să o trimiţi prin scrisoare recomandată către administraţia financiară.\r\n\r\n*Spune şi prietenilor tăi!*\r\n\r\nOrice direcţionare contează, însă poţi avea un impact mai mare dacă spui şi prietenilor tăi. Declaraţiile nu trebuie depuse personal la administraţia financiară de către fiecare contribuabil. Ele pot fi depuse „la pachet” de către o singură persoană.\r\n\r\nÎţi mulţumim pentru sprijin! Dacă ai întrebări, nu ezita să laşi un comentariu la acest post sau să ne \'contactezi\':contact.\r\n\r\n\r\n&rarr; \'*Află mai multe despre 2% pentru infoarena*\':doi-la-suta\r\n',15,'protected',3899,NULL),('algoritmiada-2009/runda-finala/poze','algoritmiada-2009/runda-finala/poze','2009-05-09 07:37:29','2009-05-09 07:51:42','==include(page=\"template/algoritmiada-2009/header\")==\r\n\r\nh1. Algoritmiada 2009, Runda Finala - Poze\r\n\r\n(htabs)* \'Despre&hellip;\':algoritmiada-2009/runda-finala\r\n* \'Program\':algoritmiada-2009/runda-finala/program\r\n* \'Regulament\':algoritmiada-2009/runda-finala/regulament\r\n* \'Probleme\':algoritmiada-2009/runda-finala/probleme\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-finala/5-8\r\n*(active) \'Poze\':algoritmiada-2009/runda-finala/poze\r\n\r\n== Gallery(page=\"algoritmiada-2009/runda-finala/poze\" file=\"%.jpg\") ==',75,'public',NULL,NULL),('runda/easy-supereasy','easy-supereasy','2009-05-10 10:58:21','2009-05-10 10:58:21','h1. == roundparam(round_id=\"easy-supereasy\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"easy-supereasy\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"easy-supereasy\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"easy-supereasy\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/easy-supereasy/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"easy-supereasy\" score=\"1\")==',10164,'round: easy-supereasy',NULL,NULL),('runda/easy-supereasy/clasament','Clasament easy-supereasy','2009-05-10 10:58:21','2009-05-10 10:58:21','h1. Clasament ==roundparam(round_id=\"easy-supereasy\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"easy-supereasy\")==',10164,'round: easy-supereasy',NULL,NULL),('runda/ultraeasy','ultraeasy','2009-05-10 11:02:28','2009-05-10 11:02:28','h1. == roundparam(round_id=\"ultraeasy\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"ultraeasy\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"ultraeasy\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ultraeasy\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/ultraeasy/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"ultraeasy\" score=\"1\")==',10164,'round: ultraeasy',NULL,NULL),('runda/ultraeasy/clasament','Clasament ultraeasy','2009-05-10 11:02:28','2009-05-10 11:02:28','h1. Clasament ==roundparam(round_id=\"ultraeasy\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"ultraeasy\")==',10164,'round: ultraeasy',NULL,NULL),('runda/begin-here','begin-here','2009-05-10 14:06:45','2009-05-10 14:06:45','h1. == roundparam(round_id=\"begin-here\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"begin-here\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"begin-here\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"begin-here\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/begin-here/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"begin-here\" score=\"1\")==',10247,'round: begin-here',NULL,NULL),('runda/begin-here/clasament','Clasament begin-here','2009-05-10 14:06:45','2009-05-10 14:06:45','h1. Clasament ==roundparam(round_id=\"begin-here\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"begin-here\")==',10247,'round: begin-here',NULL,NULL),('utilizator/pcinfo','Profil pcinfo','2009-04-21 15:39:09','2009-05-14 11:44:11','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n* absolventă a Facultăţii de Ştiinţe, Specializarea Matematică-Informatică, Universitatea Lucian Blaga din Sibiu\r\n\r\n* masterat în informatică de gestiune la Universitatea Babeş Bolyai, Cluj-Napoca\r\n\r\n* profesoară gradul I la Colegiul Naţional Gheorghe Lazăr Sibiu\r\n\r\n* membră a Comisiei Naţionale de Informatică\r\n\r\n* membră a comisiei naţionale la ONI 2005-2009\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* ==user(user=\"maxine80\" type=\"normal\")==\r\n* ==user(user=\"gulos\" type=\"normal\")==\r\n* ==user(user=\"claudiu725\" type=\"normal\")==\r\n* ==user(user=\"cotofana\" type=\"normal\")==\r\n* ==user(user=\"stanesealex\" type=\"normal\")==\r\n\r\n',10147,'public',NULL,NULL),('ultraeasy','ultraeasy','2009-05-11 16:53:26','2009-05-11 16:53:26','Scrie aici despre ultraeasy',9781,'public',NULL,NULL),('runda/untitled','untitled','2009-05-11 16:54:07','2009-05-11 16:54:07','h1. == roundparam(round_id=\"untitled\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"untitled\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"untitled\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"untitled\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/untitled/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"untitled\" score=\"1\")==',9781,'round: untitled',NULL,NULL),('runda/untitled/clasament','Clasament untitled','2009-05-11 16:54:07','2009-05-11 16:54:07','h1. Clasament ==roundparam(round_id=\"untitled\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"untitled\")==',9781,'round: untitled',NULL,NULL),('runda/untitled1','untitled1','2009-05-11 16:55:27','2009-05-11 16:55:27','h1. == roundparam(round_id=\"untitled1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"untitled1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"untitled1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"untitled1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/untitled1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"untitled1\" score=\"1\")==',9781,'round: untitled1',NULL,NULL),('runda/untitled1/clasament','Clasament untitled1','2009-05-11 16:55:27','2009-05-11 16:55:27','h1. Clasament ==roundparam(round_id=\"untitled1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"untitled1\")==',9781,'round: untitled1',NULL,NULL),('runda/21','21','2009-05-12 20:03:20','2009-05-12 20:03:20','h1. == roundparam(round_id=\"21\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"21\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"21\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"21\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/21/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"21\" score=\"1\")==',10208,'round: 21',NULL,NULL),('runda/21/clasament','Clasament 21','2009-05-12 20:03:20','2009-05-12 20:03:20','h1. Clasament ==roundparam(round_id=\"21\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"21\")==',10208,'round: 21',NULL,NULL),('paypal','Donații prin PayPal','2009-05-12 23:04:34','2009-05-12 23:04:34','h1. Donaţii prin PayPal\r\n\r\nSprijină Asociaţia infoarena folosind PayPal.\r\n\r\n==InfoarenaPayPal()==\r\n\r\n\r\n',13,'protected',NULL,NULL),('runda/123','123','2009-05-13 20:15:17','2009-05-13 20:15:17','h1. == roundparam(round_id=\"123\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"123\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"123\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"123\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/123/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"123\" score=\"1\")==',10208,'round: 123',NULL,NULL),('runda/123/clasament','Clasament 123','2009-05-13 20:15:17','2009-05-13 20:15:17','h1. Clasament ==roundparam(round_id=\"123\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"123\")==',10208,'round: 123',NULL,NULL),('runda/01234556789','01234556789','2009-05-13 20:16:04','2009-05-13 20:16:04','h1. == roundparam(round_id=\"01234556789\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"01234556789\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"01234556789\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"01234556789\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/01234556789/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"01234556789\" score=\"1\")==',10208,'round: 01234556789',NULL,NULL),('runda/01234556789/clasament','Clasament 01234556789','2009-05-13 20:16:04','2009-05-13 20:16:04','h1. Clasament ==roundparam(round_id=\"01234556789\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"01234556789\")==',10208,'round: 01234556789',NULL,NULL),('runda/concurs_info','concurs_info','2009-05-13 20:16:04','2009-05-13 20:16:04','h1. == roundparam(round_id=\"concurs_info\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"concurs_info\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"concurs_info\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"concurs_info\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/concurs_info/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"concurs_info\" score=\"1\")==',10208,'round: concurs_info',NULL,NULL),('runda/concurs_info/clasament','Clasament concurs_info','2009-05-13 20:16:04','2009-05-13 20:16:04','h1. Clasament ==roundparam(round_id=\"concurs_info\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"concurs_info\")==',10208,'round: concurs_info',NULL,NULL),('runda/infogang','infogang','2009-05-15 05:58:50','2009-05-15 05:58:50','h1. == roundparam(round_id=\"infogang\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"infogang\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"infogang\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"infogang\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/infogang/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"infogang\" score=\"1\")==',6958,'round: infogang',NULL,NULL),('runda/infogang/clasament','Clasament infogang','2009-05-15 05:58:50','2009-05-15 05:58:50','h1. Clasament ==roundparam(round_id=\"infogang\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"infogang\")==',6958,'round: infogang',NULL,NULL),('runda/prelot2/clasament','Clasament prelot2','2009-05-16 14:31:22','2009-05-16 14:31:22','h1. Clasament ==roundparam(round_id=\"prelot2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"prelot2\")==',1204,'round: prelot2',NULL,NULL),('runda/prelot2','prelot2','2009-05-16 14:31:22','2009-05-16 15:00:54','h1. == roundparam(round_id=\"prelot2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"prelot2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"prelot2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"prelot2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nConcursul va avea **6 probleme** de natura algoritmica  de nivel ridicat \r\n\r\nCele 8 ore au fost gandite astfel: 3 ore de lucru, 2 ore pauza , 3 ore de lucru.\r\n\r\nDesigur puteti sa va impartiti timpul cum doriti :).\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/prelot2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"prelot2\" score=\"1\")==',1204,'round: prelot2',NULL,NULL),('runda/try_it/clasament','Clasament try_it','2009-05-17 05:21:48','2009-05-17 05:21:48','h1. Clasament ==roundparam(round_id=\"try_it\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"try_it\")==',10247,'round: try_it',NULL,NULL),('algoritmiada-2009/runda-finala/solutii','Solutii Algoritmiada 2009, Runda Finala','2009-05-18 19:16:26','2009-05-18 19:23:19','h1. Solutii Algoritmiada 2009, Runda Finala\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Subsir100\':algoritmiada-2009/runda-finala/solutii#subsir100\r\n* \'Trmax\':algoritmiada-2009/runda-finala/solutii#trmax\r\n* \'Ambuscada\':algoritmiada-2009/runda-finala/solutii#ambuscada\r\n* \'Echipe2\':algoritmiada-2009/runda-finala/solutii#echipe2\r\n* \'Electrica\':algoritmiada-2009/runda-finala/solutii#electrica\r\n* \'Carpet Bomber\':algoritmiada-2009/runda-finala/solutii#carpetbomber\r\n* \'Morcovi\':algoritmiada-2009/runda-finala/solutii#morcovi\r\n* \'Secv2m\':algoritmiada-2009/runda-finala/solutii#secv2m\r\n* \'Propozitie2\':algoritmiada-2009/runda-finala/solutii#propozitie2\r\n* \'Jmenoasa\':algoritmiada-2009/runda-finala/solutii#jmenoasa\r\n* \'Dsip\':algoritmiada-2009/runda-finala/solutii#dsip\r\n\r\n\r\n==include(page=\"algoritmiada-2009/runda-finala/solutii/subsir100\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-finala/solutii/trmax\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-finala/solutii/ambuscada\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-finala/solutii/echipe2\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-finala/solutii/electrica\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-finala/solutii/carpetbomber\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-finala/solutii/morcovi\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-finala/solutii/secv2m\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-finala/solutii/propozitie2\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-finala/solutii/jmenoasa\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-finala/solutii/dsip\")==\r\n\r\n',1792,'public',NULL,NULL),('algoritmiada-2009/runda-finala/solutii/propozitie2','Propozitie2','2009-05-18 19:31:39','2009-05-26 19:28:32','h2(#propozitie2). \'Propozitie2\':problema/propozitie2\r\n\r\nPentru fiecare dintre cele $C$ cuvinte se poate calcula un vector $ap$, care retine numarul de aparitii ale fiecarui caracter. Asadar $ap[i][j] = numarul de aparitii ale caracterului j in cuvantul i$. \r\n\r\nAstfel pentru fiecare pozitie din sirul initial, se poate calcula in $O(SIGMA)$ daca exista o permutare a unui cuvant care sa se potriveasca in sir, avand ultima pozitie cu care coincide, pozitia actuala. Relatia de recurenta este evidenta, $Sol[i] = suma de Sol[i-L[j]]$, cuvantul $j$ se potriveste in pozitia $i$, iar $L[j]$ este lungimea cuvantului $j$. Asadar complexitatea finala este $O(N*C*SIGMA)$, unde $SIGMA$ in cazul de fata este $26$',6333,'public',NULL,NULL),('algoritmiada-2009/runda-finala/solutii/jmenoasa','Jmenoasa','2009-05-18 19:32:39','2010-04-24 21:13:57','h1. \'Jmenoasa\':problema/jmenoasa\r\n\r\nVom transforma matricea initiala astfel:\r\n\r\n* Introducem intre oricare doua elemente adiacente pe orizontala un $0$ daca elementul din stanga este mai mic, un $1$ in caz contrar.\r\n* Introducem intre oricare doua elemente adiacente pe verticala un $0$ daca elementul de sus este mai mic, un $1$ in caz contrar.\r\n* Elementele initiale ale matricei se tranforma in $0$.\r\n* Completam restul matricei cu $0$.\r\n\r\nAm redus problema la determinarea celei mai mari submatrice care incepe si se termina pe o coloana impara si cotine numai $0$ pentru o matrice avand elementele in multimea {$0$, $1$}. Putem gasi solutia adaptand cunoscutul algoritm de determinare a submatricei de $0$ avand aria maxima.',2028,'public',NULL,NULL),('algoritmiada-2009/runda-finala/solutii/dsip','Dsip','2009-05-18 19:33:01','2009-05-18 19:33:01','h1. \'Dsip\':problema/dsip',1792,'public',NULL,NULL),('algoritmiada-2009/runda-finala/solutii/morcovi','Morcovi','2009-05-18 19:30:27','2009-05-24 10:55:42','h2(#morcovi). \'Morcovi\':problema/morcovi\r\n\r\nProblema se rezolva prin programare dinamica. Notam cu $bst[i][j]$ = gradul de satisfactie maxim pe care il poate obtine iepurele, daca a efectuat pasii corespunzatori bitilor de $1$ ai lui $i$, si se afla in nodul $j$. Se observa ca din $bst[i][j]$ se poate ajunge in orice $bst[i + 2^poz^][j + Pas[poz]]$ si $bst[i + 2^poz^][j - Pas[poz]]$, cu $poz$ de la 1 la $P$, iar al $poz$ - lea bit a lui $i$ este $0$. Pentru fiecare stare se alege maximul posibil. Evident rezultatul va fi maximul de pe linia $bst[2^P^ - 1]$.\r\nObservatie: $Pas[i]$ reprezinta lungimea celui de-al $i$ -lea pas citit din fisierul de intrare.',6333,'public',NULL,NULL),('all-you-can-code-2008/solutii/treesearch','Tree Search','2008-12-01 12:12:19','2009-05-19 09:33:18','h2(#treesearch). \'Tree Search\':problema/treesearch\r\n\r\nProblema se rezolva prin programare dinamica. Presupunem ca agatam arborele intr-un nod oarecare. Folosind DFS, calculam P[ $i$ ] = costul maxim al unui drum care contine drept capat nodul $i$, si contine doar noduri din subarborele lui $i$. Relatia de recurenta se determina relativ simplu: P[ $i$ ] = C[ $i$ ], daca $i$ este nod terminal, iar P[ $i$ ] = max ( C[ $i$ ], C[ $i$ ] + P[ $k$ ] ), pentru $k$ - adiacent a lui $i$ ( diferit de tatal lui $i$ ). De asemenea, mai trebuie calculat si un vector de tati: tata[ $x$ ] = tatal nodului $x$. Avand acesti vectori calculati, mai trebuie sa determinam drumul de cost maxim care are drept extremitate nodul $i$, si pleaca \"in sus\". Astfel, notam cu T[ $i$ ] - costul maxim al unui drum care pleaca din $i$, \"in sus\". Pentru a calcula acest vector, ne trebuie cate o parcurgere DF pt fiecare fiu al radacinii. Presupunem ca dorim sa calculam $T$[] pentru subarborele $k$ al radacinii (asadar, $k$ este fiu al radacinii). Trebuie sa procedam astfel:\r\n\r\n* T[ $radacina$ ] se initializeaza cu max ( C[ $radacina$ ], P[ $j$ ] ), unde $j$ este un fiu al radacinii, diferit de $k$.\r\n* Aplicam un algoritm de tip DF, avand ca punct de plecare $k$. Pentru fiecare nod $x$ pe care il parcurgem (avand tatal $t$) calculam T[ $x$ ] = max ( C[ $x$ ], C[ $x$ ] + T[ $t$ ], C[ $x$ ] + C[ $t$ ] + P[ $j$ ]), unde $j$ este un fiu al lui $t$, diferit de $i$ si diferit de $tata[$t$]$. Continuam parcurgerea cu fiecare subarbore a lui $x$ (considerand radacina tot nodul $radacina$)\r\n\r\nAsadar, putem acum calcula $bst[ $x$ ]$ = costul maxim al unui drum care contine nodul $x$, pe baza lui $P$ si a lui $T$. Relatia de recurenta se determina usor. Avand acest vector calculat, putem raspunde in O(1) pe query. Asadar complexitatea programului va fi O( $N$ + $M$ ).\r\n\r\nObservatie: Pentru a calcula cel mai mare fiu al radacinii, diferit de fiul $k$, se va folosi un deque, altfel algoritmul putand deveni O( $N$ ^ $2$).\r\n',5748,'public',NULL,NULL),('algoritmiada-2009/runda-finala/solutii/secv2m','Secv2m','2009-05-18 19:31:02','2009-05-24 10:54:15','h2(#secv2m). \'Secv2m\':problema/secv2m\r\n\r\nO prima solutie de complexitate $O(N^3^)$ ar fi alegerea tuturor secventelor de lungime $L$ din cele doua siruri, adunarea lor, alegerea maximului din fiecare set, solutia fiind minimul acestor maxime. Insa, aceasta solutie se poate imbunatati. Astfel, vor suprapune cele doua siruri pentru fiecare pozitie astfel incat sa se obtina toate posibilitatile, si consideram sirul $S$ care va contine $A[i] + B[i]$. Pentru exemplu, primele suprapuneri arata astfel:\r\n$A : 4 3 4 2 2 - - -$\r\n$B : - - 3 1 3 2 5 3 2$\r\n$S : - - 7 3 5 - - - -$\r\n\r\n$A : 4 3 4 2 2 - - -$\r\n$B : - 3 1 3 2 5 3 2$\r\n$S : - 6 5 5 4 - - -$\r\n\r\n$A : 4 3 4 2 2 - -$\r\n$B : 3 1 3 2 5 3 2$\r\n$S : 7 4 7 4 7 - -$\r\n\r\n$A : - 4 3 4 2 2 -$\r\n$B : 3 1 3 2 5 3 2$\r\n$S : - 5 6 6 7 5 -$\r\n\r\nSolutia se obtine folosind structura de date numita \'Deque\':problema/deque, folosindu-se metoda aplicata la problema \'Secventa\':problema/secventa.\r\nSe observa ca exista $N + M$ pozitii in care se pot \'aseza\' cele doua siruri, iar solutia se obtine in timp liniar, asadar complexitatea finala este $O(N^2^)$. ',6333,'public',NULL,NULL),('algoritmiada-2009/runda-finala/solutii/subsir100','Subsir100','2009-05-18 19:25:51','2009-05-24 10:55:16','h2(#subsir100). \'Subsir100\':problema/subsir100\r\n\r\nVom calcula numarul de subsiruri \"interesante\" din sirul obtinut prin ordonarea sirului dat folosind metoda programarii dinamice. Corectitudinea algoritmului este data de faptul ca, numarul de subsiruri \"interesante\" din sirul dat este egal cu numarul de subsiruri \"interesante\" din sirul obtinut prin ordonarea sirului dat, deoarece exista o bijectie intre multimea subsirurilor \"interesante\" din sirul dat si multimea subsirurilor \"interesante\" din sirul obtinut prin ordonarea sirului dat (Tema demonstratia).\r\nFie $A[1...N]$ sirul obtinut prin ordonarea sirului dat, iar $X[i]$ numarul de subsiruri \"interesante\" din sirul $A[i...N]$, oricare ar fi $i$ un numar natural nenul cu proprietatea $i$ &le; $N$.\r\nEvident $X[N] = 1$ si $X[i] = X[i+1] + X[j] + 1$, unde $j$ este cel mai mic numar natural nenul ( $i$ < $j$ &le; $N$ ) cu proprietatea ca $A[j] != A[i]$. In cazul in care nu exista un astfel de $j$, adunam $0$ in loc de X[j]. Relatia de recurenta se explica astfel: \r\nNumarul subsirurilor \"interesante\" din $A[i...N]$ este egal cu numarul subsirurilor \"interesante\" din $A[i...N]$ care nu il contin pe $A[i]$, plus numarul subsirurilor \"interesante din\" $A[i...N]$ care il contin pe $A[i]$. Iar numarul subsirurilor \"interesante\" din $A[i...N]$ care nu il contin pe $A[i]$ este egal cu numarul subsirurilor \"interesante\" din $A[i+1...N]$ ( $A[i+1...N]$ nu il contine pe $A[i]$, iar aici ma refer la termenul $A[i]$ si nu la valoarea lui). Pentru a obtine toate subsirurile \"interesante\" din $A[i...N]$ care il contin pe $A[i]$ trebuie sa eliminam din sirul $A[i...N]$ toti termenii care au valoarea egala cu valoarea lui $A[i]$ ( Intr-un subsir \"interesant\" toate valorile sunt distincte ) si sa il adaugam pe $A[i]$ la inceputul fiecarui subsir \"interesant\" din sirul ramas. La acestea se adauga sirul care contine un singur termen si anume pe $A[i]$. Raspunsul cautat va fi in $X[$1$]$.\r\nDesi complexitatea determinarii sirului $X$ este $O(N)$, complexitatea finala este $O(N*logN)$, datorita sortarii sirului dat.',6333,'public',NULL,NULL),('algoritmiada-2009/runda-finala/solutii/ambuscada','Ambuscada','2009-05-18 19:28:19','2009-05-24 10:56:15','h2(#ambuscada). \'Ambuscada\':problema/ambuscada\r\n\r\nPrimul pas din rezolvarea problemei reprezinta sortarea celor $N$ soldati dupa timp. Apoi se construieste un sir $S$ care retine pentru fiecare moment de timp (dintre cele ale soldatilor), capacitatea maxima de efort obtinuta de exact $K$ soldati avand timpul mai mic decat timpul actual. \r\n\r\nApoi avand aceste valori calculate, se poate cauta binar capacitatea maxima de efort ce se poate obtine pentru un timp mai mic sau egal cu cel dat pentru fiecare intrebare. Avand si aceasta valoare calculata, se poate cauta binar printre obiective, obiectivul cu numarul cel mai mare mai mic sau egal cu numarul calculat anterior, acesta fiind si rezultatul. \r\n\r\nAsadar, complexitatea finala este $O(NlogN + MlogN + MlogP)$  ',6333,'public',NULL,NULL),('raicacristi','Profil raica_cristi','2009-05-22 07:54:47','2009-05-22 07:54:47','\r\n\r\nh2. Profesori pe infoarena\r\n\r\n==user(user=\"horax\" type=\"normal\")==\r\n\r\n==user(user=\"Binary_Fire\" type=\"normal\")==\r\n\r\n==user(user=\"crawler\" type=\"normal\")==\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n==user(user=\"drastik\" type=\"normal\")==\r\n\r\n==user(user=\"ssergiuss\" type=\"normal\")==\r\n\r\n==user(user=\"zilla\" type=\"normal\")==\r\n\r\n==user(user=\"hasegandani\" type=\"normal\")==\r\n\r\n==user(user=\"PavelRazvan\" type=\"normal\")==\r\n\r\n==user(user=\"tranzistor\" type=\"normal\")==\r\n\r\n==user(user=\"warcry\" type=\"normal\")==\r\n\r\n==user(user=\"jupanubv92\" type=\"normal\")==\r\n\r\n\r\n',7497,'public',NULL,NULL),('algoritmiada-2009/runda-finala/solutii/echipe2','Echipe2','2009-05-18 19:28:51','2009-05-24 10:53:23','h2(#echipe2). \'Echipe2\':problema/echipe2\r\n\r\nSe observa ca pentru a minimaliza diferenta dintre cel mai mare si cel mai mic al unei multimi, se creaza o multime cu maximele fiecarei perechi, respectiv una cu minimele fiecarei perechi. \r\n\r\nDemonstratie: Consideram ca pana la pasul $i$, maximele au fost introduse in multimea $A$, iar minimele in multimea $B$. Acum presupunem ca dorim ca maximul (pe care il notam cu $M$) dintre elementele perechii $i$ dorim sa-l introducem in multimea $B$, si minimul (pe care il notam cu $m$) in multimea $A$. Evident $max(B) &le; max(A)$ si $min(B) &le; min(A)$. De aici se disting mai multe cazuri:\r\n\r\n* $M > max(B)$, ceea ce inseamna ca dezechilibrul maxim la multimii $B$ este $M - min(B)$. Dar cum $m &le; M$ si $min(B) &le; min(A)$, rezulta ca\r\nse obine un dezechilibru mai mic daca $M$ e introdus in $A$ si $m$ in $B$.\r\n* $m < min(A)$, cazul se trateaza exact la fel ca si cel de mai sus.\r\n* In cazul in care $min(B) &le; M &le; max(B)$ si $min(A) &le; m &le; max(A)$, se observa ca nu are importanta in ce multime sunt distribuite $M$ si $m$, intrucat rezultatul ramane acelasi.\r\n\r\nPrin urmare, problema se rezolva liniar, asadar complexitatea este $O(N)$',6333,'public',NULL,NULL),('runda/easy_problems','easy_problems','2009-05-22 14:42:41','2009-05-22 14:42:41','h1. == roundparam(round_id=\"easy_problems\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"easy_problems\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"easy_problems\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"easy_problems\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/easy_problems/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"easy_problems\" score=\"1\")==',9356,'round: easy_problems',NULL,NULL),('runda/easy_problems/clasament','Clasament easy_problems','2009-05-22 14:42:41','2009-05-22 14:42:41','h1. Clasament ==roundparam(round_id=\"easy_problems\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"easy_problems\")==',9356,'round: easy_problems',NULL,NULL),('runda/pregatire9','pregatire9','2009-05-22 21:17:31','2009-05-22 21:17:31','h1. == roundparam(round_id=\"pregatire9\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"pregatire9\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"pregatire9\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"pregatire9\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/pregatire9/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"pregatire9\" score=\"1\")==',256,'round: pregatire9',NULL,NULL),('runda/pregatire9/clasament','Clasament pregatire9','2009-05-22 21:17:31','2009-05-22 21:17:31','h1. Clasament ==roundparam(round_id=\"pregatire9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pregatire9\")==',256,'round: pregatire9',NULL,NULL),('utilizator/sergiu_92','Profil Sergiu_92','2009-05-23 19:42:12','2009-05-23 19:42:12','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',10300,'public',NULL,NULL),('algoritmiada-2009/runda-finala/solutii/carpetbomber','Carpet Bomber','2009-05-18 19:30:02','2009-05-24 10:52:42','h2(#carpetbomber). \'Carpet Bomber\':problema/carpetbomber\r\n\r\nIntervalele date se sorteaza si apoi se impart dupa tipul lor. Apoi se aleg tipurile cate 2 si se incearca gasirea solutiei. Complexitatea este $O(T^2^ + N^2^)$. Pentru fiecare tip de bomba exista $nr{~i~}$ bombe de tipul respectiv, si numarul de operatii efectuate este egal cu suma $nr{~i~} * nr{~j~}$, oricare ar fi $i$ si $j$ in intervalul $[1, T]$. Suma aceasta este egala cu suma $nr{~i~} * (N - nr{~i~})$, pentru $i$ de la $1$ la $T$, ceea ce in total este mai mic decat $N * N$.',6333,'public',NULL,NULL),('algoritmiada-2009/runda-finala/solutii/electrica','Electrica','2009-05-18 19:29:32','2009-05-24 10:53:55','h2(#electrica). \'Electrica\':problema/electrica\r\n\r\nO prima observatie este ca numarul total de operatii pentru a transforma configuratia in care toate becurile sunt stinse in configuratia data este egal cu numarul total de operatii necesar stingerii tutror becurilor din configuratia data.\r\n\r\nO solutie brute-force in $O(N^4^)$ ar fi sa parcurgem matricea si in cand intalnim un $1$, atunci este clar ca el va fi capatul din stanga-sus al unui patrat, si se schimba starea tuturor elementelor din patratul de latura $L$, avand drept colt elementul actual. \r\n\r\nAceasta idee se poate imbunatati, pentru fiecare element se poate afla numarul de schimbari la care a fost supus in $O(1)$, utilizand $N$ cozi pentru linii si $M$ cozi pentru coloane. Astfel, pentru fiecare element se verifica paritatea sumei dimensiunilor cozilor corespunzatoare liniei respectiv coloanei. Daca acest numar este par, atunci valoarea elementului nu se modifica, in caz contrar acesta devine $1$ daca era $0$, respectiv $0$ daca era $1$. Daca dupa aceste transformari, elementul este 1, atunci valoarea lui se schimba si indicii se introduc in coada pentru linie, respectiv pentru coloane. Atat coada pentru linie, cat si cozile pentru coloane vor contine elementele sortate, iar atunci cand diferenta dintre indicii primului element si elementului actual este mai mare decat $L$, atunci acel element este scos din coada.',6333,'public',NULL,NULL),('algoritmiada-2009/runda-finala/solutii/trmax','Trmax','2009-05-18 19:27:10','2009-05-27 15:39:19','h2(#trmax). \'Trmax\':problema/trmax\r\n\r\nProblema se rezolva cu ajutorul programarii dinamice. Pentru inceput vom calcula matricea $A$, unde $A[i][j]$ reprezinta numarul de $0$-uri consecutive avand pe ultima pozitie elementul de pe pozitia $(i, j)$, in cazul in care acesta este nenul, sau $0$ altfel. Relatia de recurenta este evidenta, $A[i][j] = A[i][j-1] + 1$, daca elementul este nul, $A[i][j] = 0$ , altfel.\r\n\r\nApoi se calculeaza matricea $bst$, in $bst[i][j]$ se va memora inaltimea celui mai mare triunghi care are in coltul din dreapta jos elementul de pe pozitia $(i, j)$. Relatia de recurenta este $bst[i][j] = min(bst[i-1][j-1] + 1, (A[i][j] + 1) /2)$. Raspunsul final va fi maximul din aceasta matrice ridicat la patrat.',6333,'public',NULL,NULL),('runda/dragos','dragos','2009-05-24 15:11:04','2009-05-24 19:34:40','h1. == roundparam(round_id=\"dragos\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"dragos\") ==\r\n\r\nConcursul este adresat tuturor elevilor de clasa a 9-a, care la anu vor infrunta OJI 2010. Tema acestui concursul este algoritmul lui Lee, cunoscut de catre programatori, ceea ce consta in gasirea unui drum de timp minim intr-un caroiaj, etc.\r\n\r\nToate cele 5 probleme se rezolva cu algoritmul lui Lee. In teoria de specialitate, defapt acest algoritm este o parcurgere BF a unui graf.\r\n\r\nConcursul incepe ==roundparam(round_id=\"dragos\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"dragos\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nh2. Probleme\r\n\r\n==Tasks(round_id=\"dragos\" score=\"1\")==\r\n\r\nDupa terminarea rundei veti putea vedea \"clasamentul\":http://infoarena.ro/runda/dragos/clasament',6957,'round: dragos',NULL,NULL),('runda/dragos/clasament','Clasament dragos','2009-05-24 15:11:04','2009-05-24 15:11:04','h1. Clasament ==roundparam(round_id=\"dragos\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"dragos\")==',6957,'round: dragos',NULL,NULL),('runda/pavel','pavel','2009-05-25 08:11:04','2009-05-25 08:11:04','h1. == roundparam(round_id=\"pavel\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"pavel\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"pavel\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"pavel\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/pavel/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"pavel\" score=\"1\")==',6957,'round: pavel',NULL,NULL),('runda/pavel/clasament','Clasament pavel','2009-05-25 08:11:04','2009-05-25 08:11:04','h1. Clasament ==roundparam(round_id=\"pavel\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pavel\")==',6957,'round: pavel',NULL,NULL),('blog/problema-saptamanii-monede-solutie1','Problema saptamanii - Monede (Solutie)','2009-07-21 08:16:49','2009-07-21 08:22:57','Nu am mai scris de mult si v-am ramas dator cu solutia problemei Monede, daca ati uitat cerinta, puteti citi enuntul:\r\n\r\n_Pe o masa dreptunghiulara punem monede de raza 1 pana cand nu mai putem adauga o noua moneda fara ca ea sa se suprapuna cu altele. Unele monede pot fi partial inafara mesei. Daca numarul total de monede este n, sa se demonstreze ca toata suprafata mesei poate fi acoperita de 4n monede de raza unu care se pot suprapune._\r\n\r\nDaca inlocuim cele n monede de raza unu cu monede centrate la fel dar care au raza doi, ele vor acoperi total masa, pentru ca in configuratia initiala, orice punct neacoperit era la o distanta mai mica decat unu de o moneda (in caz contrar am fi putut plasa inca o moneda de raza unu centrata in punctul respectiv).\r\nAsta inseamna ca, cu n monede de raza unu putem acoperi un dreptunghi cu aria un sfert din aria mesei. Cu patru astfel de dreptunghiuri acoperite, putem obtine o configuratie a 4n monede ce acopera intreaga masa.\r\n\r\nSingurul rezolvitor a fost Andrei Dragus, felicitari.',58,'protected',4042,NULL),('runda/aplicatii_delphi','aplicatii_delphi','2009-05-28 20:23:29','2009-05-28 20:23:29','h1. == roundparam(round_id=\"aplicatii_delphi\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"aplicatii_delphi\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"aplicatii_delphi\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"aplicatii_delphi\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/aplicatii_delphi/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"aplicatii_delphi\" score=\"1\")==',10320,'round: aplicatii_delphi',NULL,NULL),('runda/aplicatii_delphi/clasament','Clasament aplicatii_delphi','2009-05-28 20:23:30','2009-05-28 20:23:30','h1. Clasament ==roundparam(round_id=\"aplicatii_delphi\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"aplicatii_delphi\")==',10320,'round: aplicatii_delphi',NULL,NULL),('runda/secvente','secvente','2009-05-30 18:32:33','2009-05-30 18:32:33','h1. == roundparam(round_id=\"secvente\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"secvente\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"secvente\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"secvente\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/secvente/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"secvente\" score=\"1\")==',8956,'round: secvente',NULL,NULL),('runda/secvente/clasament','Clasament secvente','2009-05-30 18:32:33','2009-05-30 18:32:33','h1. Clasament ==roundparam(round_id=\"secvente\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"secvente\")==',8956,'round: secvente',NULL,NULL),('ccex2009/9','Concursul Centrelor de Excelenta, clasa a 9a','2009-05-31 11:04:03','2009-06-05 10:14:09','&nbsp;\r\n\r\nh1. Concursul Centrelor de Excelenta 2009\r\n\r\n!> ccex2009?logo.png 35%!:/ccex2009\r\n\r\n(htabs)* \'Despre concurs\':ccex2009\r\n*(active) \'Clasa a 9-a\':ccex2009/9\r\n* \'Clasa a 10-a\':ccex2009/10\r\n* \'Clasele 11-12\':ccex2009/11-12\r\n* \'Clasament\':ccex2009/clasament\r\n\r\nh2. Clasa a 9-a\r\n\r\n== roundregister(round_id=\"ccex2009-9\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"ccex2009-9\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ccex2009-9\" param=\"duration\" strong=\"true\")== ore. Participantii vor avea de rezolvat doua probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':ccex2009/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"ccex2009-9\" score=\"1\")==\r\n\r\nh2. Clasament\r\n\r\n\'Evaluatorul\':documentatie/evaluator va fi pornit pe toata perioada desfasurarii concursului. Sursele vor fi evaluate pe masura ce sunt trimise de concurenti, insa scorul va ramane ascuns pana la terminarea rundei de concurs. Rezultatele finale le puteti gasi \'aici\':ccex2009/clasament.\r\n',256,'protected',NULL,NULL),('runda/ccex2009-9','ccex2009-9','2009-05-31 11:08:05','2009-05-31 11:08:05','h1. == roundparam(round_id=\"ccex2009-9\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"ccex2009-9\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"ccex2009-9\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ccex2009-9\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/ccex2009-9/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"ccex2009-9\" score=\"1\")==',256,'round: ccex2009-9',NULL,NULL),('runda/ccex2009-9/clasament','Clasament ccex2009-9','2009-05-31 11:08:05','2009-05-31 11:08:05','h1. Clasament ==roundparam(round_id=\"ccex2009-9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"ccex2009-9\")==',256,'round: ccex2009-9',NULL,NULL),('runda/ccex2009-10','ccex2009-10','2009-05-31 11:13:03','2009-05-31 11:13:03','h1. == roundparam(round_id=\"ccex2009-10\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"ccex2009-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"ccex2009-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ccex2009-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/ccex2009-10/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"ccex2009-10\" score=\"1\")==',256,'round: ccex2009-10',NULL,NULL),('runda/ccex2009-10/clasament','Clasament ccex2009-10','2009-05-31 11:13:03','2009-05-31 11:13:03','h1. Clasament ==roundparam(round_id=\"ccex2009-10\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"ccex2009-10\")==',256,'round: ccex2009-10',NULL,NULL),('ccex2009/11-12','Concursul Centrelor de Excelenta, clasele 11-12','2009-05-31 11:15:51','2009-06-05 10:14:30','&nbsp;\r\n\r\nh1. Concursul Centrelor de Excelenta 2009\r\n\r\n!> ccex2009?logo.png 35%!:/ccex2009\r\n\r\n(htabs)* \'Despre concurs\':ccex2009\r\n* \'Clasa a 9-a\':ccex2009/9\r\n* \'Clasa a 10-a\':ccex2009/10\r\n*(active) \'Clasele 11-12\':ccex2009/11-12\r\n* \'Clasament\':ccex2009/clasament\r\n\r\nh2. Clasele 11-12\r\n\r\n== roundregister(round_id=\"ccex2009-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"ccex2009-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ccex2009-11-12\" param=\"duration\" strong=\"true\")== ore. Participantii vor avea de rezolvat doua probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':ccex2009/clasament/11-12.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"ccex2009-11-12\" score=\"1\")==\r\n\r\nh2. Clasament\r\n\r\n\'Evaluatorul\':documentatie/evaluator va fi pornit pe toata perioada desfasurarii concursului. Sursele vor fi evaluate pe masura ce sunt trimise de concurenti, insa scorul va ramane ascuns pana la terminarea rundei de concurs. Rezultatele finale le puteti gasi \'aici\':ccex2009/clasament/11-12.',256,'protected',NULL,NULL),('runda/ccex2009-11-12','ccex2009-11-12','2009-05-31 11:16:09','2009-05-31 11:16:09','h1. == roundparam(round_id=\"ccex2009-11-12\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"ccex2009-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"ccex2009-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ccex2009-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/ccex2009-11-12/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"ccex2009-11-12\" score=\"1\")==',256,'round: ccex2009-11-12',NULL,NULL),('runda/ccex2009-11-12/clasament','Clasament ccex2009-11-12','2009-05-31 11:16:09','2009-05-31 11:16:09','h1. Clasament ==roundparam(round_id=\"ccex2009-11-12\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"ccex2009-11-12\")==',256,'round: ccex2009-11-12',NULL,NULL),('ccex2009/clasament','Concursul Centrelor de Excelenta, clasament 9','2009-05-31 11:48:04','2009-06-04 10:58:11','&nbsp;\r\n\r\nh1. Concursul Centrelor de Excelenta 2009\r\n\r\n!> ccex2009?logo.png 35%!:/ccex2009\r\n\r\n(htabs)* \'Despre concurs\':ccex2009\r\n* \'Clasa a 9-a\':ccex2009/9\r\n* \'Clasa a 10-a\':ccex2009/10\r\n* \'Clasele 11-12\':ccex2009/11-12\r\n*(active) \'Clasament\':ccex2009/clasament\r\n\r\n&nbsp;\r\n&nbsp;\r\n\r\n(htabs)*(active) \'Clasa a 9-a\':ccex2009/clasament\r\n* \'Clasa a 10-a\':ccex2009/clasament/10\r\n* \'Clasele 11-12\':ccex2009/clasament/11-12\r\n\r\np<. == Rankings(rounds=\"ccex2009-9\") == \r\n',256,'protected',NULL,NULL),('ccex2009/clasament/10','Concursul Centrelor de Excelenta, clasament 10','2009-05-31 11:49:30','2009-05-31 11:49:30','&nbsp;\r\n\r\nh1. Concursul Centrelor de Excelenta 2009\r\n\r\n!> ccex2009?ccex.jpg 50%!:/ccex2009\r\n\r\n(htabs)* \'Despre concurs\':ccex2009\r\n* \'Clasa a 9-a\':ccex2009/9\r\n* \'Clasa a 10-a\':ccex2009/10\r\n* \'Clasele 11-12\':ccex2009/11-12\r\n*(active) \'Clasament\':ccex2009/clasament\r\n\r\n&nbsp;\r\n&nbsp;\r\n\r\n(htabs)* \'Clasa a 9-a\':ccex2009/clasament\r\n*(active) \'Clasa a 10-a\':ccex2009/clasament/10\r\n* \'Clasele 11-12\':ccex2009/clasament/11-12\r\n\r\np<. == Rankings(rounds=\"ccex2009-10\") == \r\n',256,'protected',NULL,NULL),('ccex2009/clasament/11-12','Concursul Centrelor de Excelenta, clasament 11-12','2009-05-31 11:50:25','2009-05-31 11:50:30','&nbsp;\r\n\r\nh1. Concursul Centrelor de Excelenta 2009\r\n\r\n!> ccex2009?ccex.jpg 50%!:/ccex2009\r\n\r\n(htabs)* \'Despre concurs\':ccex2009\r\n* \'Clasa a 9-a\':ccex2009/9\r\n* \'Clasa a 10-a\':ccex2009/10\r\n* \'Clasele 11-12\':ccex2009/11-12\r\n*(active) \'Clasament\':ccex2009/clasament\r\n\r\n&nbsp;\r\n&nbsp;\r\n\r\n(htabs)* \'Clasa a 9-a\':ccex2009/clasament\r\n* \'Clasa a 10-a\':ccex2009/clasament/10\r\n*(active) \'Clasele 11-12\':ccex2009/clasament/11-12\r\n\r\np<. == Rankings(rounds=\"ccex2009-11-12\") == \r\n',256,'protected',NULL,NULL),('ccex2009/10','Concursul Centrelor de Excelenta, clasa a 10a','2009-05-31 11:12:24','2009-06-05 10:11:49','&nbsp;\r\n\r\nh1. Concursul Centrelor de Excelenta 2009\r\n\r\n!> ccex2009?logo.png 35%!:/ccex2009\r\n\r\n(htabs)* \'Despre concurs\':ccex2009\r\n* \'Clasa a 9-a\':ccex2009/9\r\n*(active) \'Clasa a 10-a\':ccex2009/10\r\n* \'Clasele 11-12\':ccex2009/11-12\r\n* \'Clasament\':ccex2009/clasament\r\n\r\nh2. Clasa a 10-a\r\n\r\n== roundregister(round_id=\"ccex2009-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"ccex2009-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ccex2009-10\" param=\"duration\" strong=\"true\")== ore. Participantii vor avea de rezolvat doua probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':ccex2009/clasament/10.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"ccex2009-10\" score=\"1\")==\r\n\r\nh2. Clasament\r\n\r\n\'Evaluatorul\':documentatie/evaluator va fi pornit pe toata perioada desfasurarii concursului. Sursele vor fi evaluate pe masura ce sunt trimise de concurenti, insa scorul va ramane ascuns pana la terminarea rundei de concurs. Rezultatele finale le puteti gasi \'aici\':ccex2009/clasament/10.',256,'protected',NULL,NULL),('runda/aviara_gripa','aviara_gripa','2009-05-31 15:55:43','2009-05-31 15:55:43','h1. == roundparam(round_id=\"aviara_gripa\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"aviara_gripa\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"aviara_gripa\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"aviara_gripa\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/aviara_gripa/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"aviara_gripa\" score=\"1\")==',10331,'round: aviara_gripa',NULL,NULL),('runda/aviara_gripa/clasament','Clasament aviara_gripa','2009-05-31 15:55:43','2009-05-31 15:55:43','h1. Clasament ==roundparam(round_id=\"aviara_gripa\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"aviara_gripa\")==',10331,'round: aviara_gripa',NULL,NULL),('runda/porc3','porc3','2009-05-31 17:12:51','2009-05-31 17:12:51','h1. == roundparam(round_id=\"porc3\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"porc3\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"porc3\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"porc3\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/porc3/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"porc3\" score=\"1\")==',6333,'round: porc3',NULL,NULL),('runda/porc3/clasament','Clasament porc3','2009-05-31 17:12:51','2009-05-31 17:12:51','h1. Clasament ==roundparam(round_id=\"porc3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"porc3\")==',6333,'round: porc3',NULL,NULL),('runda/concurs_de_test_mugurel','concurs_de_test_mugurel','2009-06-03 10:31:42','2009-06-03 10:31:42','h1. == roundparam(round_id=\"concurs_de_test_mugurel\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"concurs_de_test_mugurel\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"concurs_de_test_mugurel\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"concurs_de_test_mugurel\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/concurs_de_test_mugurel/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"concurs_de_test_mugurel\" score=\"1\")==',468,'round: concurs_de_test_mugurel',NULL,NULL),('runda/concurs_de_test_mugurel/clasament','Clasament concurs_de_test_mugurel','2009-06-03 10:31:42','2009-06-03 10:31:42','h1. Clasament ==roundparam(round_id=\"concurs_de_test_mugurel\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"concurs_de_test_mugurel\")==',468,'round: concurs_de_test_mugurel',NULL,NULL),('ccex2009','Concursul Centrelor de Excelență','2009-05-31 10:24:55','2009-06-05 16:19:30','&nbsp;\r\n\r\nh1. Concursul Centrelor de Excelenta 2009\r\n\r\n(htabs)*(active) \'Despre concurs\':ccex2009\r\n* \'Clasa a 9-a\':ccex2009/9\r\n* \'Clasa a 10-a\':ccex2009/10\r\n* \'Clasele 11-12\':ccex2009/11-12\r\n* \'Clasament\':ccex2009/clasament\r\n\r\n!> ccex2009?logo.png 35%!:/ccex2009\r\n\'*infoarena*\':/, împreună cu Inspectoratul Şcolar Judeţean Suceava, organizează pe data de $6$ iunie _concursul interjudeţean al Centrelor de Excelenţă_. La concurs vor participa elevi de gimnaziu şi de liceu din mai multe judeţe. Concursul online va fi disponibil doar pentru clasele $9-12$.\r\n\r\nConcurenţii care vor participa live la Suceava vor fi evaluaţi de evaluatorul infoarena. Astfel, toţi ceilalţi concurenţi vor avea ocazia să îşi măsoare forţele cu aceştia, la oricare din cele $3$ grupe de vârstă: \'clasa a {$9$}-a\':ccex2009/9, \'clasa a {$10$}-a\':ccex2009/10 şi, respectiv, \'clasele {$11-12$}\':ccex2009/11-12. %{color:red}În plus, concurentii care vor participa online şi se vor clasa în primele $3$ locuri la fiecare grupă de vârstă, vor primi din partea organizatorilor diplome şi tricouri.%\r\n\r\nConcursul se va desfăşura *Sâmbătă, 6 iunie*, la ora {*9^00^*} şi va dura *4h*.\r\n\r\nPagina oficiala a concursului se gaseste \'*aici*\':http://ccex.infosv.ro/index.php.\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse şi pregătite de:\r\n\r\n* inspector de specialitate Giorgie Vlad\r\n* prof. Petronela Aga\r\n* prof. Gabriela Coaja\r\n* prof. Antoneta Lazarescu\r\n* prof. Ovidiu Marcu\r\n* lector dr. ing. Radu-Daniel Vatavu\r\n* ==User(user=\"filipb\" type=\"tiny\")==\r\n* ==User(user=\"amadaeus\" type=\"tiny\")==\r\n\r\nPentru întrebări de factură organizatorică / tehnică poţi contacta următoarele persoane:\r\n\r\n* ==User(user=\"filipb\" type=\"tiny\")==\r\n* ==User(user=\"Marius\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* îţi urează mult succes!\r\n\r\nh2. Cum particip?\r\n\r\nÎnainte de toate trebuie să \'te înregistrezi\':register pe site-ul nostru!\r\n\r\nOricine este invitat să participe. În ziua de concurs intri pe site, citeşti problemele, le rezolvi, şi trimiţi soluţiile înainte de expirarea timpului de lucru. Sursele vor fi evaluate pe măsura ce sunt trimise de către concurenţi, însă scorul va rămâne ascuns până la terminarea rundei de concurs. Clasamentul se va actualiza în timp real pe parcursul evaluării.\r\n\r\nh2. Prima dată pe _infoarena_?\r\n\r\n\'infoarena\':/ ajută elevi şi studenţi să devină excelenţi în informatică! Gratuit ;) \'Citeşte mai multe\':despre-infoarena despre noi şi vezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n',3146,'protected',NULL,NULL),('lista-lui-wefgef','Lista lui wefgef','2009-06-05 22:27:38','2009-06-05 22:32:23','h1. == roundparam(round_id=\"lista-lui-wefgef\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"lista-lui-wefgef\") ==\r\n\r\nAm alcătuit o listă cu problemele pe care trebuie să vă concentraţi dacă urmăriţi calificarea la IOI.\r\n\r\nPentru a vă măsura forţele cu ceilalţi consultaţi \'*clasamentul*\':lista-lui-wefgef/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"lista-lui-wefgef\" score=\"1\")==',2028,'round: lista-lui-wefgef',NULL,NULL),('lista-lui-wefgef/clasament','lista-lui-wefgef/clasament','2009-06-05 22:34:58','2009-06-05 22:34:58','h1. Clasament \'Lista lui wefgef\':lista-lui-wefgef\r\n\r\nAcest clasament reflecta munca depusa in *rezolvarea problemelor grele* de pe infoarena.\r\n\r\n== Rankings(rounds=\"lista-lui-wefgef\") ==',2028,'protected',NULL,NULL),('runda/acm_upb_2009','acm_upb_2009','2009-06-06 06:10:42','2009-06-06 06:10:42','h1. == roundparam(round_id=\"acm_upb_2009\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"acm_upb_2009\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"acm_upb_2009\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"acm_upb_2009\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/acm_upb_2009/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"acm_upb_2009\" score=\"1\")==',75,'round: acm_upb_2009',NULL,NULL),('runda/acm_upb_2009/clasament','Clasament acm_upb_2009','2009-06-06 06:10:42','2009-06-06 06:10:42','h1. Clasament ==roundparam(round_id=\"acm_upb_2009\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"acm_upb_2009\")==',75,'round: acm_upb_2009',NULL,NULL),('blog/algoritmiada-2009-final','Algoritmiada 2009 la final','2009-05-26 20:31:32','2009-08-24 12:10:50','Iată ca Algoritmiada 2009 a ajuns la final: runda finală a avut loc şi o parte din voi a petrecut câteva zile într-un oraş frumos al ţării alături de echipa infoarena.\r\n\r\nLa final, aş vrea să ne uităm peste statisticile pentru fiecare rundă. Pe baza lor putem să apreciem dacă Algoritmiada va deveni un concurs mai popular de la an la an.\r\n\r\ntable. |_. &nbsp; |_. Runda 1 |_. Runda 2 |_. Runda 3 |_. Finala |_. Total |\r\n| Câţi concurenţi au trimis soluţii | 223 | 157 | 126 |  97 | 313 |\r\n| Câţi concurenţi s-au inscris | 356 | 232 | 151 | 103 | 508 |\r\n| Surse trimise | 1245 | 894 | 995 | 758 | 3892 |\r\n| Surse cu punctaj pozitiv | 685 | 408 | 561 | 537 | 2191 |\r\n| Concurenţi cu punctaj pozitiv | 162 | 113 | 112 | 92 | 242 |\r\n| Punctaj mediu al concurenţilor care au trimis soluţii | 75.09 | 43.85 | 105.43 | 118.09 | 154.53 |\r\n| Punctaj mediu al concurenţilor cu punctaj > 0 | 103.36 | 60.93 | 118.61 | 124.51 | 199.87 |\r\n\r\nPutem observa că numărul celor care au trimis soluţii a scăzut de la rundă la rundă. Mă întreb care sunt motivele pentru care concurenţii renunţă progresiv. Primul care îmi vine în minte ar fi că pe măsură ce îţi dai seama că nu mai ai sanse de calificare renunţi. Personal dezaprob o astfel de atitudine: participi la fiecare concurs ca să înveţi -- faptul că ajungi la finală e un bonus, nu scopul în sine! Pe studenţi îi iertăm pentru că au mai puţin timp să se distreze cu probleme de algoritmică. Nota bene pentru cei mici: trageţi tare acum că mai târziu se mai schimbă priorităţile.\r\n\r\nCâteva cuvinte despre organizarea finalei. Îmi pare rău ca n-am ajuns la finală să joc fotbal. Aş fi vrut să-l văd şi eu evoluând pe atât de lăudatul fotbalist din echipa infoarena. Da ==user(user=\"astronomy\")==, despre tine e vorba.\r\n\r\nÎn altă ordine de idei, aceasta este prima finală organizată de infoarena în care membrii mai vechi s-au implicat mai puţin spre deloc. Am dorit să-i lăsam pe cei mai tineri să ia microfonul în mână şi să iasă în faţă. V-aţi descurcat foarte bine! Aţi adus un suflu nou şi lucruri inovatoare. Mersi pentru vâsle!\r\n\r\nDin feedback-ul trimis de voi pe \'forum\':http://infoarena.ro/forum/index.php?topic=3897.0 reiese că organizarea a fost bună. Câteva din problemele menţionate pe care vom încerca să le eliminăm pe viitor: evaluarea live nu a meritat aşteptarea de o zi şi putea fi mai spectaculoasă; au fost câteva teste buşite (de obicei nu ni se întamplă, o punem pe seama aglomerării organizatorice).\r\n\r\nAş vrea să remarc performanţa deosebită a lui ==user(user=\"gavrilavlad\")== care a obţinut punctajul maxim în toate probele Algoritmiadei la grupa Gimnaziu. Felicitări Vlad!\r\n\r\nŞi acum publicitate ... :)\r\n\r\nLăsând gluma la o parte, anul acesta infoarena a făcut eforturi financiare şi organizatorice mari pentru a organiza finala în afara Bucureştiului. Am ales Braşov şi am ales bine pentru că acolo ne-am bucurat de sprijinul deosebit generos al liceului \'Colegiul National de Informatica \"Grigore Moisil\"\':http://www.moisilbrasov.ro. Doamna directoare Mariana Bulbuc ne-a ajutat şi ne-a susţinut punând suflet în organizarea finalei cot la cot cu noi. Ne-am bucurat si de sprijinul doamnei profesoare Manuela Şerban iar domnul Teodor Schiller a fost de un real ajutor în rezolvarea problemelor de natură tehnică. Pe lângă domniile lor, am mai fost ajutaţi de o armată de elevi ai liceului. Le mulţumim tuturor acestor oameni deosebiţi şi sperăm să reedităm colaborarea în anii următori!\r\n\r\nMulţumim şi sponsorului Algoritmiadei, \'Adobe România\':http://myadobe.ro/. Este al doilea an consecutiv când Adobe susţine activităţile noastre şi asta ne bucură foarte mult. Adobe a înţeles că ce facem este important pentru viitorul IT-ului din România şi că voi meritaţi să fiţi răsplătiţi şi încurajaţi. Chiar şi pe timp de criză.\r\n\r\nÎn final vă spun \'unde\':algoritmiada-2009/runda-finala/poze găsiţi pozele de la finală şi vă urez o vacanţă frumoasă! Să vă odihniţi şi să vă distraţi din plin iar când vă plictisiţi de atâta distracţie, mai lucraţi la informatică. Pe infoarena, bineînţeles! :)',15,'protected',3967,NULL),('runda/po-m','po-m','2009-06-09 13:35:33','2009-06-09 13:35:33','h1. == roundparam(round_id=\"po-m\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"po-m\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"po-m\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"po-m\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/po-m/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"po-m\" score=\"1\")==',10357,'round: po-m',NULL,NULL),('runda/po-m/clasament','Clasament po-m','2009-06-09 13:35:33','2009-06-09 13:35:33','h1. Clasament ==roundparam(round_id=\"po-m\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"po-m\")==',10357,'round: po-m',NULL,NULL),('runda/ultima_rasuflare','ultima_rasuflare','2009-06-09 17:25:58','2009-06-09 17:25:58','h1. == roundparam(round_id=\"ultima_rasuflare\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"ultima_rasuflare\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"ultima_rasuflare\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ultima_rasuflare\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/ultima_rasuflare/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"ultima_rasuflare\" score=\"1\")==',7668,'round: ultima_rasuflare',NULL,NULL),('runda/ultima_rasuflare/clasament','Clasament ultima_rasuflare','2009-06-09 17:25:58','2009-06-09 17:25:58','h1. Clasament ==roundparam(round_id=\"ultima_rasuflare\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"ultima_rasuflare\")==',7668,'round: ultima_rasuflare',NULL,NULL),('blog/cateva-pentru-vacanta','Cateva recomandări pentru vacanţă','2009-06-09 20:07:47','2009-06-09 20:19:57','Cum vacanţa se apropie, am două recomandări pentru timpul vostru liber:\r\n\r\n* Sper că v-a plăcut să simulaţi online la loturile de la Bistriţa. Puteţi participa şi la probele din cadrul lotului de Cluj. \'Aici\':http://li.cj.edu.ro:8888 găsiţi mai multe detalii.\r\n\r\n* Cu toţii ştim sau am auzit de Cormen - cartea pe care fiecare olimpic la informatică ar trebui să o citească din scoarţă în scoarţă la un moment dat. Dar poate că nu toţi stiaţi că pe youtube există cursurile profesorului Leiserson (L-ul din CLRS). Le puteţi urmări \'aici\':http://www.youtube.com/watch?v=JPyuH4qXLZ0. Dacă vizionaţi câte unul pe zi le terminaţi în mai puţin de o lună ;)\r\n\r\nDacă sunteţi interesaţi, puteţi găsi înregistrări video de la mai multe cursuri de la MIT tot pe \'youtube\':http://www.youtube.com/user/MIT. Şi cei de la Stanford au \'cursuri online\':http://see.stanford.edu/see/lecturelist.aspx?coll=11f4f422-5670-4b4c-889c-008262e09e4e.\r\n\r\nDacă mai stiţi şi alte resurse ca acestea, vă rog să lasaţi un comentariu.',15,'protected',3988,NULL),('utilizator/silviug','Profil silviug','2006-11-24 20:56:12','2009-07-05 08:55:11','h2. Despre mine\r\n\r\n* Membru fondator si vicepresedinte al Asociatiei infoarena\r\n* Co-fondator al celui mai tare \'motor de căutare de joburi\':http://balaur.ro/ din .ro\r\n* Omul zilei, 20 septembrie 2004, Jurnalul National\r\n* Stagii:\r\n## Google, Mountain View, summer 2006\r\n## Google, Zurich, summer 2007\r\n## \'EPFL\':http://www.epfl.ch/, Lausanne, summer 2008\r\n* Am invatat 80% din informatica pe care o stiu in ultimii doi ani de liceu\r\n* De cativa ani buni sunt trainer al echipei de informatica ICHB\r\n* Absolvent al facultatii de Automatica si Calculatoare, Universitatea Politehnica Bucuresti\r\n\r\nh2. Frânturi de trecut\r\n\r\n* Am pus mana pe calculator abia in clasa a 9-a, in prima ora de informatica. Desi ora a fost traumatizanta fiindca nu stiam ce sa fac cu dihania din fata mea, pe parcursul anului am dezvoltat o pasiune pentru informatica.\r\n* Doua episoade marcante din evolutia mea ca informatician:\r\n## Intr-o noapte de prin clasa a 10-a faceam probleme pe foaie din Ginfo (nu aveam calculator acasa) si s-a intrerupt curentul electric. Totusi, am continuat sa ma bat cu problemele multe ore in sir la lumina lumanarii.\r\n## In vacanta de iarna din clasa a 10-a, fiindca nu aveam un calculator personal, doamna profesoara Gheorghian mi-a dat acasa un calculator al scolii. Am muncit foarte foarte mult in acea vacanta. Reflectati un pic la posibilitatile pe care le aveti voi... Ce mai stati?\r\n* Primul calculator personal mi l-au luat parintii mei spre sfarsitul clasei a 10-a, dupa ce am luat locul 1 la Olimpiada Judeteana de Matematica si m-am calificat la Nationala.\r\n* Dupa cum v-ati dat seama, mai intai am fost olimpic la mate dar spre sfarsitul liceului impuscam puncte la olimpiadele de informatica.\r\n* In clasa a 11-a am fost coleg de banca cu \"Wickedman\":utilizator/wickedman. Valorificam orele plictisitoare rezolvand probleme de informatica.\r\n\r\n\r\nh2. Distinctii primite (cele mai importante)\r\n\r\n* 2 x locul 2 - Axway-Eestec Olympic 2006 (concursuri maraton de 24 de ore in echipe de 3).\r\n* Finalist Google Code Jam, Mountain View 2005.\r\n* Medalie de Aur, Olimpiada Internationala de Informatica, Atena 2004.\r\n* Medalie de Bronz, Olimpiada Balcaniada de Informatica, Plovdiv 2004.\r\n* Locul I, Olimpiada Nationala de Informatica, Focsani 2003.\r\n* Mentiune, Olimpiada Nationala de Matematica, Ramnicu Valcea 2002 (asta e distictia cea mai importanta obtinuta ca matematician).',15,'protected',NULL,NULL),('runda/problemiada_4','Problemiada - Editia 4','2009-06-10 21:48:26','2009-06-11 09:17:36','h1. == roundparam(round_id=\"problemiada_4\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"problemiada_4\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"problemiada_4\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"problemiada_4\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/problemiada_4/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"problemiada_4\" score=\"1\")==',5748,'round: problemiada_4',NULL,NULL),('runda/problemiada_4/clasament','Clasament problemiada_4','2009-06-10 21:48:26','2009-06-10 21:48:26','h1. Clasament ==roundparam(round_id=\"problemiada_4\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"problemiada_4\")==',5748,'round: problemiada_4',NULL,NULL),('runda/oji_11','oji_11','2009-06-11 06:40:43','2009-06-11 06:40:43','h1. == roundparam(round_id=\"oji_11\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oji_11\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oji_11\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oji_11\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/oji_11/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"oji_11\" score=\"1\")==',6957,'round: oji_11',NULL,NULL),('runda/oji_11/clasament','Clasament oji_11','2009-06-11 06:40:43','2009-06-11 06:40:43','h1. Clasament ==roundparam(round_id=\"oji_11\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"oji_11\")==',6957,'round: oji_11',NULL,NULL),('runda/6576','6576','2009-06-11 18:30:18','2009-06-11 18:30:18','h1. == roundparam(round_id=\"6576\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"6576\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"6576\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"6576\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/6576/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"6576\" score=\"1\")==',10280,'round: 6576',NULL,NULL),('runda/6576/clasament','Clasament 6576','2009-06-11 18:30:18','2009-06-11 18:30:18','h1. Clasament ==roundparam(round_id=\"6576\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"6576\")==',10280,'round: 6576',NULL,NULL),('runda/biti','biti','2009-06-14 12:49:33','2009-06-14 12:49:33','h1. == roundparam(round_id=\"biti\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"biti\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"biti\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"biti\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/biti/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"biti\" score=\"1\")==',4359,'round: biti',NULL,NULL),('runda/biti/clasament','Clasament biti','2009-06-14 12:49:33','2009-06-14 12:49:33','h1. Clasament ==roundparam(round_id=\"biti\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"biti\")==',4359,'round: biti',NULL,NULL),('runda/fanninfo','fanninfo','2009-06-17 14:49:53','2009-06-17 14:49:53','h1. == roundparam(round_id=\"fanninfo\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"fanninfo\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"fanninfo\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"fanninfo\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/fanninfo/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"fanninfo\" score=\"1\")==',10480,'round: fanninfo',NULL,NULL),('runda/fanninfo/clasament','Clasament fanninfo','2009-06-17 14:49:53','2009-06-17 14:49:53','h1. Clasament ==roundparam(round_id=\"fanninfo\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"fanninfo\")==',10480,'round: fanninfo',NULL,NULL),('runda/problemiada_5','Problemiada - Editia 5','2009-06-18 18:47:03','2009-06-18 18:49:03','h1. == roundparam(round_id=\"problemiada_5\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"problemiada_5\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"problemiada_5\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"problemiada_5\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/problemiada_5/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"problemiada_5\" score=\"1\")==',5748,'round: problemiada_5',NULL,NULL),('runda/problemiada_5/clasament','Clasament problemiada_5','2009-06-18 18:47:03','2009-06-18 18:47:03','h1. Clasament ==roundparam(round_id=\"problemiada_5\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"problemiada_5\")==',5748,'round: problemiada_5',NULL,NULL),('runda/putinlee','putinlee','2009-06-20 11:42:51','2009-06-20 11:42:51','h1. == roundparam(round_id=\"putinlee\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"putinlee\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"putinlee\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"putinlee\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/putinlee/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"putinlee\" score=\"1\")==',9232,'round: putinlee',NULL,NULL),('runda/putinlee/clasament','Clasament putinlee','2009-06-20 11:42:51','2009-06-20 11:42:51','h1. Clasament ==roundparam(round_id=\"putinlee\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"putinlee\")==',9232,'round: putinlee',NULL,NULL),('runda/summer_camp_1','summer_camp_1','2009-06-22 05:23:48','2009-06-22 05:23:48','h1. == roundparam(round_id=\"summer_camp_1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"summer_camp_1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"summer_camp_1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"summer_camp_1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/summer_camp_1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"summer_camp_1\" score=\"1\")==',6957,'round: summer_camp_1',NULL,NULL),('runda/summer_camp_1/clasament','Clasament summer_camp_1','2009-06-22 05:23:48','2009-06-22 05:23:48','h1. Clasament ==roundparam(round_id=\"summer_camp_1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer_camp_1\")==',6957,'round: summer_camp_1',NULL,NULL),('runda/splunge0','splunge0','2009-06-22 08:36:48','2009-06-22 08:36:48','h1. == roundparam(round_id=\"splunge0\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"splunge0\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"splunge0\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"splunge0\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/splunge0/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"splunge0\" score=\"1\")==',4439,'round: splunge0',NULL,NULL),('runda/splunge0/clasament','Clasament splunge0','2009-06-22 08:36:48','2009-06-22 08:36:48','h1. Clasament ==roundparam(round_id=\"splunge0\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"splunge0\")==',4439,'round: splunge0',NULL,NULL),('runda/summer_camp_2/clasament','Clasament summer_camp_2','2009-06-25 14:38:19','2009-06-25 14:38:19','h1. Clasament ==roundparam(round_id=\"summer_camp_2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer_camp_2\")==',6957,'round: summer_camp_2',NULL,NULL),('selonyy','Profil Selony','2009-06-26 05:24:16','2009-06-26 05:24:16','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',10492,'public',NULL,NULL),('runda/pgleague','pgleague','2009-06-26 18:15:26','2009-06-26 18:15:26','h1. == roundparam(round_id=\"pgleague\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"pgleague\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"pgleague\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"pgleague\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/pgleague/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"pgleague\" score=\"1\")==',10505,'round: pgleague',NULL,NULL),('runda/pgleague/clasament','Clasament pgleague','2009-06-26 18:15:26','2009-06-26 18:15:26','h1. Clasament ==roundparam(round_id=\"pgleague\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pgleague\")==',10505,'round: pgleague',NULL,NULL),('blog/membru-nou','Echipa infoarena s-a îmbogăţit, din nou :)','2009-06-28 20:12:37','2009-06-30 12:49:07','_După cum o parte din voi aţi aflat la finala Algoritmiada, echipa infoarena s-a îmbogăţit cu un nou membru: Marius Stroe. Pentru cei care nu au fost acolo, Marius a primit din partea echipei infoarena un mini-tort cu cifra 0 pe post de lumânare. Explicaţia a fost că are 0 ani de infoarena şi este cea mai nouă achiziţie a echipei._\r\n\r\n_În ciuda acestui fapt Marius are deja multe contribuţii în \'proiectele infoarena\':implica-te în calitate de voluntar. Puteţi vedea acest lucru chiar pe pagina sa de \'profil\':utilizator/Marius. Îmi place cum şi-a enumerat Marius contribuţiile cele mai importante pe pagina sa de pe infoarena. Aş vrea să văd mai mulţi voluntari că îşi actualizează profilul cu realizările lor în cadrul comunităţii._\r\n\r\n_Marius a fost invitat în echipa infoarena tocmai datorită contribuţiilor sale consistente. El este dovada că oricine poate ajunge în echipa infoarena în urma unei implicări constante şi productive în proiectele iniţiate de noi. O vorbă mai veche spune că orice soldat are în raniţă bastonul de mareşal :) Păstrând proporţiile, vreau să spun că oricare dintre voi poate fi promovat în echipă pe această cale: realizări importante pentru comunitate._\r\n\r\n_Să nu mai lungim vorba şi să vedem cum a răspuns Marius la interviul de botez. Mult succes, Marius, în activitatea ta ca membru infoarena!_\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/membru-nou?marius_stroe.jpeg! *Cum ai ajuns membru al siteului infoarena?*\r\nÎnainte să fiu membru al siteului infoarena am fost abonat al revistei GInfo. Pe siteul acestei reviste am găsit un link către infoarena. Google nu mi-a folosit pe atunci. :-)\r\n\r\n\r\n*Cum ai folosit acest site?*\r\nCred că infoarena a fost primul site pe care am văzut multe probleme la un loc spre a fi rezolvate. Nu îmi aduc aminte sigur dar nu cred că ştiam de celelalte siteuri precum Timus, Sgu, UVa, Spoj... După ce am submitat prima sursă la problema A + B am văzut că evaluatorul online chiar funcţionează. Mi s-a părut o idee foarte interesantă să lucrez la o problemă şi să văd rezultatul imediat. Iar acest lucru m-a determinat să lucrez să văd cât ştiu. Până la primul ONI la care am participat în clasa a 10-a am rezolvat toate problemele de pe prima pagină din arhivă, mai puţin Fractal. :-) Ţin minte că într-o zi am rezolvat nu mai puţin de 7 probleme, ale căror idei includeau o programare dinamică pe un arbore, un trie, o căutare binară etc. Ceea ce înseamnă, pe scurt, că am învăţat multe într-un timp scurt.\r\n\r\n\r\n*De ce ai intrat in echipa infoarena? Ce îţi propui sa faci ca membru al echipei?*\r\nAm voie să zic că o perioadă de timp nu am ştiut că sunt membru al echipei infoarena? :-) Mă bucur că sunt membru al acestei echipe, fapt ce înseamnă că munca mea a fost apreciată. Ce scopuri am? Nu îmi place cum arată infoarena acum. Ar arăta mult mai bine cu numeroase articole şi o arhivă educaţională bogată. Sunt multe probleme, însă puţină teorie. Scopul meu e ca această latură a siteului să se dezvolte mult mai mult.\r\n\r\n\r\n*Când ai început cu programarea?*\r\nPrimul rând pe care l-am scris în vreun limbaj de programare a fost _int main(void)_, undeva prin clasa a 9-a. În vacanţa de vară dinainte să încep liceul îmi cumpărasem o carte despre C/C++ pentru că auzisem că la liceu voi face acest limbaj. La şcoală, fiindu-mi uşor să rezolv ultima problemă de la fiecare capitol, am trecut la manualul de clasa a 10-a, după care am dat de infoarena şi am aruncat toate cărţile. :-)\r\n\r\n\r\n*Ce pasiuni ai în afara de programare?*\r\nÎmi plac karatele pentru că mă ajută să eliberez energiile în plus. Însă, acum la facultate le-am abandonat, nemaiavând atâtea energii negative. Îmi mai place să citesc şi să ascult muzică Trance.\r\n\r\n\r\n*Spune-ne o întamplare interesantă legată de site-ul infoarena!*\r\nSunt mai multe astfel de întâmplări. În primul rând, a fost o surpriză plăcută să aflu că sunt membru al echipei infoarena. Pe de altă parte, lucrând cu Ştefan Istrate la articole nu pot uita cât m-am rugat de el să îmi corecteze conţinutul articolului Deque şi aplicaţii, pentru că după ce se uitase pe primele trei probleme a avut nevoie de două săptămâni să îşi recâştige răbdarea pierdută. :-)\r\n',15,'protected',4022,NULL),('notiuni-de-geometrie-si-aplicatii/drepte','Drepte','2009-06-28 22:40:04','2009-06-28 22:40:04','h2. Ecuatiile dreptei\r\n\r\nDreptele sunt locuri geometrice ce indeplinesc _ecuatia dreptei_. Cu alte cuvinte, ecuatia unei drepte reprezinta o relatie care este respectata de toate punctele aflate pe dreapta. Forma generala a ecuatiei unei drepte in sistemul $xOy$ este\r\n\r\n<tex>(d): a*x + b*y + c = 0</tex>\r\n\r\nIn cazul in care dreapta nu se afla in plan, fiecare punct $A$ ( $x1$ , $x2$ , $x3$ ,... $Xn$ ) (pentru n dimensiuni) de pe ea va indeplini conditiile:\r\n<tex>\r\n$$\\left\\{\\begin{array}{lr}\r\nx_1 = a_1\\cdot x_0_1 + b_1; \\\\\r\nx_2 = a_2\\cdot x_0_2 + b_2; \\\\\r\n... \\\\\r\nx_n = a_n\\cdot x_0_n + b_n;\r\n\\end{array}\\right\r\n$$\r\n</tex>\r\n\r\nA nu se confunda cu ecuatia planului:\r\n\r\n<tex>(d): a*x + b*y + c*z + d = 0</tex>\r\n\r\nPentru simplitate, de aici inainte ne vom referi numai la drepte in plan. De mentionat este faptul ca daca trecem pe $y$ in partea dreapta si impartim prin $-b$ (consideram un caz general, nu cel nefericit in care $b=0$), obtinem:\r\n\r\n<tex>(d): y = \\frac{(-a)}{b}*x + \\frac{(-c)}{b}</tex>\r\n\r\n<tex>(d): y = m*x + n</tex>, unde <tex>m=-\\frac{a}{b}, n=-\\frac{c}{b}</tex>\r\n\r\nDe asemenea, fiind date doua puncte $A(x{~1~}, y{~1~})$ si $B(x{~2~}, y{~2~})$, ecuatia dreptei determinate de ele se poate scrie\r\n\r\n<tex>(d): \\frac{x-x_1}{x_2-x_1} = \\frac{y-y_1}{y_2-y_1}</tex>\r\n\r\nAceasta poate sa nu ne fie de prea mare ajutor, dar facand produsul mezilor cu extremii si desfacand parantezele vom obtine <tex>(d): (y_1-y_2)*x + (x_2-x_1)*y + (x_1*y_2-x_2*y_1) = 0</tex>, de unde putem deduce foarte usor cine sunt $a$, $b$, $c$ din scrierile precedente.\r\n\r\nSe stie ca orice dreapta imparte planul in 2 semiplane: cel cu puncte pentru care, daca aplicam ecuatia, vom obtine o valoare strict pozitiva, si cel pentru care vom obtine o valoare strict negativa. De aceea, daca avem o dreapta data prin 2 puncte $A(x{~1~}, y{~1~})$ si $B(x{~2~}, y{~2~})$ de pe aceasta, atunci punctul $C(x{~3~}, y{~3~})$ va apartine dreptei $AB$ daca si numai daca\r\n\r\n<tex>\\left| \\begin{array}{ccc}\r\nx_1 & y_1 & 1 \\\\\r\nx_2 & y_2 & 1 \\\\\r\nx_3 & y_3 & 1 \\end{array} \\right| = 0</tex>\r\n\r\nh2. Panta unei drepte\r\n\r\nPanta unei drepte se poate defini ca fiind tangenta unghiului facut de dreapta cu orizontala, mai exact cu orice dreapta paralela cu axa $OX$. Ea se calculeaza astfel:\r\n\r\n<tex>m = \\frac{y_1-y_2}{x_1-x_2}</tex> sau <tex>m = -\\frac{a}{b}</tex>\r\n\r\nIn a doua ecuatie $a$ si $b$ reprezinta coeficientii ecuatiei dreptei respective\r\n\r\n<tex>(d): a*x + b*y + c = 0</tex>\r\n\r\nProprietati:\r\n {*} Doua drepte care au pantele egale sunt ori paralele ori confundate.\r\n {*} Doua drepte care au produsul pantelor egal cu $-1$ sunt perpendiculare. \r\n\r\nh2. Distanta dintre un punct si o dreapta\r\n\r\nPentru a calcula distanta care ne trebuie noua vom calcula panta dreptei $d{~1~}$ notata cu $m{~1~}$. Acum vrem sa construim o dreapta $d{~2~}$ perpendiculara pe dreapta $d{~1~}$ care trece prin punctul $A$. Stim ca $m{~1~}*m{~2~}=-1$ si de aici aflam usor $m{~2~}$ (panta dreptei $d{~2~}$). In acest moment avem panta dreptei $d{~2~}$ si un punct care ii apartine. Avand aceste 2 informatii putem sa calculam usor ecuatia ei si punctul de intersectie cu dreapta $d{~1~}$ ({_Vezi capitolul Drepte_}). Distanta dintre dreapta si punct va fi egala cu distanta dintre punct si punctul de intersectie al celor $2$ drepte.\r\n\r\nDe asemenea exista si o formula pt a determina distanta de la un punct la o dreapta: considerand punctul $A(x{~0~},y{~0~})$ si dreapta $d:ax+by+c=0$, vom avea :\r\n<tex> d(A,d) = \\frac{|\\mbox{a\\cdot x_0+b\\cdot y_0+c}|}{\\mbox{\\sqrt{a^2+b^2}}}</tex>\r\n\r\nh2. Distanta dintre un punct si un segment\r\n\r\nSa presupunem un punct $A(x{~1~},y{~1~})$ si un segment determinat de punctele $B(x{~2~},y{~2~})$ si $C(x{~3~},y{~3~})$ si vrem sa aflam distanta dintre punct si segment. \r\n\r\n$D$=min(dist({$A$},{$B$}),dist({$A$},{$C$})) in cazul in care perpendiculara din punctul $A$ pe dreapta $BC$ *nu* cade in interiorul segmentului $BC$, altfel distanta va fi egala cu distanta dintre punctul $A$ si dreapta $BC$, lucru care l-am tratat mai sus.',3270,'public',NULL,NULL),('notiuni-de-geometrie-si-aplicati/intersectii-drepte-si-segmente','Intersectii de drepte si segmente','2009-06-28 22:43:12','2009-06-28 22:43:12','h2. Punctul de intersectie a 2 drepte\r\n\r\nDupa cum am vazut, o dreapta reprezinta un loc geometric. Sa zicem ca avem 2 drepte $d{~1~}$ si $d{~2~}$ si dorim sa aflam punctul $A(x, y)$ cu propietatea ca acesta apartine atat dreptei $d{~1~}$, cat si dreptei $d{~2~}$. Scriem ecuatiile celor 2 drepte:\r\n\r\n<tex> a_1 * x + b_1 * y + c_1 = 0</tex>\r\n<tex> a_2 * x + b_2 * y + c_2 = 0</tex>\r\n\r\nAm ajuns astfel la un sistem de 2 ecuatii cu 2 necunoscute. Pentru a ajunge la niste formule mai directe de calculare a celor 2 coordonate vom inmulti prima relatie cu $b{~2~}$ si pe cea de-a doua cu $b{~1~}$.\r\n\r\n<tex>a_1 * b_2 * x + b_1 * b_2 * y + c_1 * b_2 = 0</tex>\r\n<tex>a_2 * b_1 * x + b_1 * b_2 * y + c_2 * b_1 = 0</tex>\r\n\r\nScadem cele doua relatii si ajungem la o singura ecuatie cu o singura necunoscuta:\r\n\r\n<tex>(a_1 * b_2 - a_2 * b_1) * x + c_1 * b_2 - c_2 * b_1 = 0 \\Leftrightarrow</tex>\r\n<tex>x = \\frac{\\mbox{c_2 * b_1 - c_1 * b_2}}{\\mbox{a_1 * b_2 - a_2 * b_1}}</tex>\r\n\r\nO data ce l-am aflat pe $x$, descoperirea celeilalte coordonate e destul de triviala:\r\n\r\n<tex>a_1*x + b_1 * y + c_1 = 0</tex>\r\n<tex>y = \\frac{\\mbox{-c_1 - a_1 * x}}{\\mbox{b_1}}</tex>\r\n\r\n',3270,'public',NULL,NULL),('notiuni-de-geometrie-si-aplicatii/infasuratoare-convexa','Infasuratoare convexa','2009-06-28 22:44:35','2009-06-28 22:44:35','h2. Infasuratoarea convexa\r\n\r\nEnuntul problemei: Se da un set de puncte in plan, sa se determine un poligon convex de arie minima care contine toate punctele in interiorul sau. \r\nRezolvare: O posibila solutie este sa fixam punctul cu abscisa minima ,iar in caz de egalitate luam punctul cu ordonata minima, si sa translatam toate punctele pana cand acesta ajunge in punctul de coordonate $(0,0)$. Acum vom sorta punctele dupa formula <tex> \\frac{y}{x} </tex> unde $x$ si $y$ sunt coordonatele punctului, iar in caz de egalitate dupa distanta fata de punctul $(0,0)$. In cazul nefericit in care $x=0$ vom considera ca <tex> \\frac{y}{x} = INF </tex>. Apoi vom parcurge punctele in ordine si le vom introduce intr-o stiva. Inainte sa introducem un punct in stiva trebuie insa sa ne uitam daca nu cumva punctele $st[vf-1] , st[vf]$ si $P$ sunt in ordine invers trigonometrica ( $st$ - stiva, $vf$ - varful stivei, $P$ - punctul curent). Aici ne vom folosi de o alta proprietate a determinantului cu ajutorul caruia determinam aria unui triunghi. Mai exact vom calcula\r\n<tex>D=\\left| \\begin{array}{ccc}\r\n\\ x_1 & y_1 & 1\\\\\r\nx_2 & y_2 & 1\\\\\r\nx_3 & y_3 & 1\\end{array} \\right| \r\n</tex>\r\npentru $st[vf-1] = (x{~1~}.y{~1~}) , st[vf]= (x{~2~},y{~3~}), P(x{~3~},y{~3~})$. Daca $D$ este negativ atunci inseamna ca unghiul cu originea in $st[vf]$ face o intoarcere la dreapta si trebuie scos din stiva. Repetam procedeul pana cand ramanem cu un singur punct in stiva sau pana cand intalnim un $D >= 0$ dupa care adaugam punctul in stiva. Dupa ce am terminat e posibil ca poligonul nostru inca sa fie convex deoarece nu am verificat unghiul care are originea in $st[vf]$, asa ca il vom calcula pe $D$ pentru punctele $st[vf-1],st[vf],st[ 1 ]$ si vom scoate punctul din varf atata timp cat $D$ va fi negativ. Punctele ramase reprezinta infasuratoarea convexa a setului de puncte primite la intrare.\r\n*devilkind*: E posibil sa nu fi inteles eu bine, dar la faza cand y/x e 0 cred ca trebui sa pui INF sau -INF in functie de semnul lui y. nush daca merge doar cu INF. - FIXED\r\n',3270,'public',NULL,NULL),('transformari-geometrice','Transformări geometrice','2009-04-12 08:01:38','2009-07-01 18:59:37','h1. Transformări geometrice\r\n\r\n(Categoria _Matematică_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'_Introducere_\':transformari-geometrice#introducere\r\n** \'Translaţia\':transformari-geometrice#translatia\r\n** \'Simetria\':transformari-geometrice#simetria\r\n** \'Rotaţia\':transformari-geometrice#rotatia\r\n** \'Omotetia\':transformari-geometrice#omotetia\r\n** \'Desfăşurarea în plan\':transformari-geometrice#desfasurarea-in-plan\r\n* \'_Aplicaţii_\':transformari-geometrice#aplicatia-1\r\n** \'Aplicaţia 1\':transformari-geometrice#aplicatia-1\r\n** \'Aplicaţia 2\':transformari-geometrice#aplicatia-2\r\n** \'Aplicaţia 3\':transformari-geometrice#aplicatia-3\r\n** \'Aplicaţia 4: _PolyLine_ &#40;TopCoder&#41;\':transformari-geometrice#aplicatia-4\r\n** \'Aplicaţia 5 &#40;Olimpiada Letonă, 1997&#41;\':transformari-geometrice#aplicatia-5\r\n** \'Aplicaţia 6: _Pool_ &#40;Timus&#41;\':transformari-geometrice#aplicatia-6\r\n** \'Aplicaţia 7: _NCushion_ &#40;TopCoder&#41;\':transformari-geometrice#aplicatia-7\r\n** \'Aplicaţia 8\':transformari-geometrice#aplicatia-8\r\n** \'Aplicaţia 9\':transformari-geometrice#aplicatia-9\r\n** \'Aplicaţia 10\':transformari-geometrice#aplicatia-10\r\n** \'Aplicaţia 11\':transformari-geometrice#aplicatia-11\r\n** \'Aplicaţia 12\':transformari-geometrice#aplicatia-12\r\n** \'Aplicaţia 13\':transformari-geometrice#aplicatia-13\r\n** \'Aplicaţia 14\':transformari-geometrice#aplicatia-14\r\n** \'Aplicaţia 15\':transformari-geometrice#aplicatia-15\r\n** \'Aplicaţia 16\':transformari-geometrice#aplicatia-16\r\n** \'Aplicaţia 17\':transformari-geometrice#aplicatia-17\r\n** \'Aplicaţia 18\':transformari-geometrice#aplicatia-18\r\n\r\nh2(#introducere). Introducere\r\n\r\nÎn acest articol vom introduce câteva noţuni legate de transformările geometrice care se pot dovedi utile în concursurile de programare.\r\n\r\nÎnainte de toate prezentăm câteva aspecte teoretice, o mare parte din ele nefiind foarte interesante şi probabil sunt conţinute şi în manualele de liceu. Cititorul poate trece direct la probleme şi, în măsura în care noţiunile din soluţii îi sunt neclare, poate reveni asupra părţii teoretice.\r\n\r\nh3(#translatia). Translaţia\r\n\r\nTranslaţia unei figuri geometrice reprezintă mişcarea tuturor componentelor ei pe o anumita distanţă si direcţie. Această transformare poate fi uşor caracterizată de un vector $v = (dx, dy)$. Când vrem să translatăm un punct $P(x, y)$ după $v$, e de ajuns să facem operaţia $P’ = P + v$. Astfel, $P’$ are cooronatele $(x + dx, y + dy)$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* pastrează orientarea poligoanelor (adică, dacă vârfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi şi ele în ordine trigonometrică);\r\n* păstrează unghiurile;\r\n* o dreaptă va fi transformată în altă dreaptă paralelă cu prima;\r\n* înafară de translaţia trivială de vector $v = (0, 0)$, această transformare nu are puncte fixe (adică orice punct va fi transformat într-un punct diferit);\r\n* translaţii successive vor rezulta tot într-o translaţie (adică, dacă vrem să translatăm un punct dupa $v$ şi apoi după $v{~1~}$, atunci obţinem acelaşi rezultat dacă translatăm direct după $v + v{~1~}$);\r\n* translaţia este comutativă;\r\n\r\nh3(#simetria). Simetria\r\n\r\nExistă două tipuri de simetrii: simetria faţă de un punct şi simetria faţa de o dreaptă.\r\n\r\nUn punct $A$ îl are simetric pe $A’$ faţă de un punct $O$, dacă segmentul $AA’$ are ca mijloc punctul $O$. Dacă avem un punct $(x{~0~}, y{~0~})$ căruia vrem să îi aflăm simetricul faţă de un punct de coordonate $(x, y)$ atunci acesta va fi $(2x – x{~0~}, 2y – y{~0~})$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* păstrează orientarea poligoanelor (adică, dacă varfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi şi ele în ordine trigonometrică);\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* are ca punct fix punctul $O$, iar drepte fixe cele care trec prin punctul $O$;\r\n* simetrii succesive după centre diferite $O{~1~}(x{~1~}, y{~1~}) O{~2~}(x{~2~}, y{~2~})$ sunt o translaţie de vector $v = 2(x{~2~} – x{~1~})$;\r\n* simetriile după un punct nu comută;\r\n\r\nSă calculăm simetricul unui punct $P(x{~0~}, y{~0~})$ faţă de o dreaptă de ecuaţie $ax + by + c = 0$. Notăm cu $d$ distanţa de la punctul $P$ la dreaptă, <tex> d = \\displaystyle\\frac{|a*x_{0} + b*y_{0} + c|}{\\sqrt{a^2 + b^2}} </tex>, şi cu $(m{~1~}, m{~2~})$ cosinii directori ai vectorului $n(a, b)$ normal la dreaptă. Valorile cosinilor directori sunt: <tex> m_{1} = \\displaystyle \\pm \\frac{a}{\\sqrt{a^2 + b^2}} </tex> şi <tex> m_{2} = \\displaystyle \\pm \\frac{b}{\\sqrt{a^2 + b^2}} </tex>. Vom alege semnul minus dacă $ax{~0~} + by{~0~} + c > 0$ iar semnul plus dacă $ax{~0~} + by{~0~} + c < 0$. Astfel, simetricul punctului $P$ va avea coordonatele $(x{~0~} + 2*d*m{~1~}, y{~0~} + 2*d*m{~2~})$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* nu păstrează orientarea poligoanelor (adică, dacă varfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi în sens orar);\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* are ca puncte fixe dreapta de simetrie;\r\n* simetrii succesive după drepte paralele sunt o translaţie;\r\n* simetrii succesive după drepte concurente sunt rotaţii;\r\n* simetriile nu comută;\r\n\r\nh3(#rotatia). Rotaţia\r\n\r\nAceasta este o transformare care roteşte punctele în sens trigonometric în jurul unui punct numit centru de rotaţie după un unghi fixat numit unghi de rotaţie. Dacă avem rotaţia de centru $O(x{~0~}, y{~0~})$ şi unghi $alfa$, atunci imaginea unui punct $P(x, y)$ va fi $P’(x{~0~} + (x – x{~0~}) * cos(alfa)  - (y – y{~0~}) * sin(alfa), y{~0~} + (x – x{~0~}) * sin(alfa)  + (y – y{~0~}) * cos(alfa))$.\r\n \r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* păstrează orientarea poligoanelor;\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* dacă nu este o rotaţie trivială de unghi $0$ atunci are ca punct fix centrul de rotaţie;\r\n* nu are drepte fixe, dar are cercuri fixe centrate în centrul de rotaţie;\r\n* două rotaţii succesive $R{~1~}(O{~1~}, alfa)$ şi $R{~2~}(O{~2~}, beta)$ se compun într-o translaţie sau o rotaţie $R{~3~}(O{~3~}, alfa + beta)$;\r\n* în general rotaţiile nu comută;\r\n\r\nh3(#omotetia). Omotetia\r\n\r\nAceasta este o transformare ce scalează obiectele în funcţie de un centru de omotetie şi un raport. Un punct $P(x, y)$ transformat după o omotetie $H(O(x{~0~}, y{~0~}), k)$ (centru $O$ şi raport $k$) va avea imaginea $P’(x{~0~} + k * (x - x{~0~}), y{~0~} + k * (y - y{~0~}))$.\r\n\r\nProprietăţi:\r\n\r\n* nu păstrează distanţele;\r\n* păstrează orientarea poligoanelor;\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele, iar transformata unei drepte va fi paralelă cu dreapta;\r\n* are ca punct fix centrul de omotetie;\r\n* două omotetii succesive $H{~1~}(O{~1~}, k{~1~})$ şi $H{~2~}(O{~2~}, k{~2~})$ se compun într-o translaţie sau omotetie $H{~3~}(O{~3~}, k{~1~} + k{~2~})$;\r\n* în general omotetiile nu comută;\r\n\r\nh3(#desfasurarea-in-plan). Desfăşurarea în plan\r\n\r\nAceasta nu este o transformare geometrică propriu-zisă, ci mai mult o tehnică folositoare în rezolvarea unor probleme pe care o puteţi vedea aplicată în problemele ce urmează ...\r\n\r\n*To do:* de verificat teoria de aici. :)\r\n\r\nh2(#aplicatia-1). Aplicaţia 1\r\n\r\n!< transformari-geometrice?aplicatie-1.1.png 60%!\r\n\r\nbq. Fie două puncte $A$ şi $B$ de aceiaşi parte a unei drepte $d$. Se cere să se determine un punct $M$ pe dreapta $d$ cu proprietatea că suma $AM + MB$ e mininimă.\r\n\r\n!> transformari-geometrice?aplicatie-1.2.png 60%!\r\n\r\nh3. Rezolvare:\r\n\r\nDucem simetricul punctului $A$ faţă de dreapta $d$ pe care îl notăm cu $A’$. Oricare ar fi un punct $N$ pe dreapta $d$, $AN = A’N$ pentru că triunghiul $AA’N$ este isoscel având dreapta $d$ şi înălţime şi mediană. Astfel, avem că $AN + NB = A’N + NB$, deci pentru ca să minimizăm suma $AM + MB$ trebuie de fapt să minimizăm suma $A’M + MB$. Punctele $A’$ şi $B$ sunt situate de părţi diferite ale dreptei, deci punctul $M$ trebuie situat la intersecţia segmentului $A’B$ cu dreapta $d$.\r\n\r\nh2(#aplicatia-2). Aplicaţia 2\r\n\r\n!< transformari-geometrice?aplicatie-2.1.png 60%!\r\n\r\nbq. Fie două puncte $A$ şi $B$ în interiorul unui unghi format de semidreptele $d{~1~}$ şi $d{~2~}$ care au capătul comun $O$. Se cere să se determine două puncte $M$ şi $N$ astfel ca $M$ să aparţină lui $d{~1~}$ şi $N$ să aparţină lui $d{~2~}$ iar suma $AM + MN + NB$ să fie minimă.\r\n\r\n!> transformari-geometrice?aplicatie-2.2.png 60%!\r\n\r\nh3. Rezolvare:\r\n\r\nFolosim aceeaşi idee: ducem simetricul punctului $A$, notat cu $A’$, faţă de dreapta $d{~1~}$ şi simetricul punctului $B$ notat cu $B’$ faţă de dreapta $d{~2~}$. Orice puncte $M$ şi $N$ am alege, avem că $AM + MN + NB = A’M + MN + NB’$. Pentru a minimiza suma $A’M + MN + NB’$ trebuie ca $M$ şi $N$ să fie intersecţiile segmentului $A’B’$ cu semidreptele $d{~1~}$ şi $d{~2~}$.\r\n\r\n\r\nh2(#aplicatia-3). Aplicaţia 3\r\n\r\n!< transformari-geometrice?aplicatie-3.1.png 70%!\r\n\r\nbq. Dându-se un triunghi ascuţitunghic $ABC$ se cere să se determine un triunghi înscris în acesta de perimetru minim.\r\n\r\nh3. Rezolvare:\r\n\r\n!> transformari-geometrice?aplicatie-3.2.png 70%!\r\n\r\nLuăm un punct $M$ pe baza $BC$ a triunghiului $ABC$, un punct $P$ pe latura $AB$ şi un punct $N$ pe latura $AC$. Dacă avem $M’$ simetricul lui $M$ faţă de $AB$ şi $M’’$ simetricul lui $M$ faţă de $AC$, atunci $MN + NP + PM = M’’N + NP + PM’$. Ca să minimizăm această sumă, punctele $P$ şi $N$ trebuie să fie la intersecţia segmentului $M’M’’$ cu laturile $AB$, respectiv $AC$. Perimetrul triunghiului $MNP$ va fi egal cu lungimea segmentului $M’M’’$. Observăm că unghiul $M’AM’’$ are măsura egală cu $2 * măsura unghiului BAC$ şi că triunghiul $M’AM’’$ e isoscel de latură egală cu $AM$. Pentru ca $M’M’’$ să aibă lungimea minimă trebuie ca $AM$ să fie cât mai scurt. Acest segment este minim atunci când $M$ este piciorul înalţimii din $A$. La fel putem să deducem că $N$ este piciorul înălţimii din $B$, iar $P$ este piciorul înălţimii din $C$. Astfel, soluţia de perimetru minim este triunghiul ortic.\r\n\r\nh2(#aplicatia-4). Aplicaţia 4: \'_PolyLine_\':http://www.topcoder.com/stat?c=problem_statement&pm=4509 (TopCoder) X\r\n\r\nbq. Se consideră un dreptunghi cu colţurile de coordonate $(0, 0)$ , $(a, 0)$, $(a, b)$, $(0, b)$. Mai considerăm două puncte $A$ şi $B$ de coordonate $(x{~1~}, y{~1~})$ şi $(x{~2~}, y{~2~})$ în interiorul dreptunghiului. Se cere să se determine lungimea minimă a unei linii frânte ce porneşte din $A$ ajunge în $B$ şi intersectează fiecare latură a dreptunghiului. În figura de mai jos, avem un dreptunghi de dimensiuni $4 x 3$ şi trei posibilităţi de a plasa două puncte în interiorul dreptunghiului, împreună cu soluţiile optime. Rezultatele pentru cele trei exemple sunt: $7.8102$, $8.6023$, respectiv $9.4339$.\r\n\r\np=. !transformari-geometrice?aplicatie-4.1.png 70%!\r\n\r\n!> transformari-geometrice?aplicatie-4.2.png 70%!\r\n\r\nh3. Rezolvare:\r\n\r\nEste evident că o soluţie optimă va fi formată din cinci segmente. Putem încerca toate ordinele posibile ale drumului liniei frânte, fiind $4! = 24$ asemenea ordini. Pentru fiecare ordine căutăm drumul optim. Acesta poate fi găsit folosind trucul prezentat în problemele anterioare. Să luăm un exemplu: pentru punctele $A(1, 2)$ şi $B(1,3)$ şi dreptunghiul de dimensiuni $4$ şi $3$, luăm punctele $M, N, P, Q$ pe laturile din stânga, jos, dreapta respectiv sus ale dreptunghiului astfel încât să minimizăm suma $AM + MN + NP + PQ + QB$. Acum, vom duce simetricul lui $A$, notat cu $A’$, faţă de latura din stânga şi simetricul lui $B$, notat cu $B’$, faţă de latura de sus. Avem că $AM = A’M$ şi $QB = QB’$. Deci, ca să minimizăm suma $AM + MN + NP + PQ + QB$ trebuie să minimizăm suma $A’M + MN + NP + PQ + QB’$. Vom duce simetricul lui $A’$, notat prin $A’’$, faţă de latura de jos, şi simetricul lui $B’$, notat prin $B’’$, faţă de latura din dreapta. Avem că $A’M + MN <= A’’N$ şi că $PQ + QB’ <= QB’’$, deci obţinem că pentru a minimiza suma $AM + MN + NP + PQ + QB$ trebuie să minimizăm suma $A’’M + MN + NB’’$. Putem realiza acest obiectiv dacă $M$ şi $N$ vor fi intersecţiile segmentului $A’’B’’$ cu latura de jos, respectiv latura din dreapta a dreptunghiului, iar soluţia este exact distanţa de la $A’’$ la $B’’$.\r\n\r\nh2(#aplicatia-5). Aplicaţia 5 (Olimpiada Letonă, 1997)\r\n\r\n!< transformari-geometrice?aplicatie-5.1.png 70%!\r\n\r\n!> transformari-geometrice?aplicatie-5.2.png 70%!\r\n\r\nbq. Laturile unui teren dreptunghiular de biliard de dimensiuni $43 x 73$ sunt etichetate cu literele $A, R, Z, D$. O bilă $B$ (dimensiunile căreia pot fi ignorate) este plasată în interiorul acestui teren la $13$ centimetri distanţă de latura $R$ şi la $29$ de centimetri distanţă de latura $D$. Un jucător îşi pune tacul pe latura $R$ la un punct ce e situat la $K$ centimetri distanţă de latura $D$ şi loveşte direct bila $B$. Bila se mişcă drept şi dacă e cazul loveşte marginile terenului. Mişcarea bilei se supune legilor fizicii, astfel, când bila se loveşte de margine ea va avea o traiectorie simetrică cu traiectoria iniţială faţă de dreapta perpendiculară pe margine în punctul de impact. O parte din traiectoria bilei o puteţi vedea în figură. Problema esta pentru un număr fix $K (0 &le; K &le; 73)$ şi $N (0 &le; N &le; 10^9^)$. Să se determine distanţa bilei faţă de latura $R$ şi distanţa faţă de latura $D$, după ce bila s-a deplasat exact $N$ centimetri.\r\n\r\n!> transformari-geometrice?aplicatie-5.3.png 65%!\r\n\r\nh3. Rezolvare:\r\n\r\nO rezolvare bazată pe simularea mişcării bilei pare anevoioasă, iar din cauza faptului că $N$ poate fi foarte mare, acest algoritm nu este eficient. O rezolvare elegantă este următoarea. Întâi umplem planul cu o grilă infinită de dreptunghiuri de dimensiuni $43 x 73$. Dacă am lăsa ca bila să îşi continue mişcarea şi am ignora prima lovire a marginii, în terenul adiacent, atunci traiectoria bilei ar fi de la trecerea marginii simetrică cu traiectoria normală a bilei, deci ar fi ca şi cum am reflecta întreaga tablă. Acest fenomen se repetă de fiecare dată când atingem o margine. Astfel, dacă ducem un segment pe direcţia de deplasare a bilei, ce pleacă din $B$, de lungime $N$, şi se termină în $C$ atunci putem vedea în ce dreptunghi este el inclus, şi în funcţie de acest dreptunghi să transformăm punctul $C$ în poziţia finală a bilei în dreptunghiul iniţial.\r\n\r\nh2(#aplicatia-6). Aplicaţia 6: \'_Pool_\':http://acm.timus.ru/problem.aspx?space=1&num=1258 (Timus)\r\n\r\n!> transformari-geometrice?aplicatie-6.1.png 80%!\r\n\r\nbq. Programatorului Vasile îi place să se plimbe prin biroul lui dreptunghiular. El începe drumul din locul unde este situat biroul lui şi se plimbă până când crede că ar trebui să se apuce de lucru din nou. Drumul lui urmează legea de mişcare dată de „unghiul de incidenţă este egal cu unghiul de reflexie”. Vasile se mişcă de la zid la zid în linie dreaptă. Şeful direct al lui Vasile este interesat cât timp pierde acesta în plimbările lui. Este uşor să aflăm timpul, împărţind distanţa parcursă la viteza medie a lui Vasile (aceasta a fost deja calculată de şef), deci trebuie să se afle distanţa parcursă. Se ştie ordinea în care au fost atinşi pereţii întrucât Vasile, fiind neatent, se loveşte de pereţi şi astfel se aud bufniturile în fiecare zid. Se dau dimensiunile camerei lui Vasile: $W$ şi $D (0 &le; W, D &le; 100)$, poziţia iniţială, poziţia finală şi secvenţa de litere $N, S, E, V$ care este ordinea în care sunt atinşi pereţii. De exemplu, în imagine pereţii sunt atinşi în ordinea $NVEVES$. Numărul de coliziuni nu depăşeste $1000$, poziţiile iniţiale şi finale nu se află pe marginile dreptunghiului, iar drumul lui Vasile nu va trece prin vreun colţ al încăperii.\r\n\r\nh3. Rezolvare:\r\n\r\nPrecum în problema anterioară, când Vasile atinge un perete mişcarea lui se oglindeşte faţă de mişcarea normală. Vom procesa fiecare instrucţiune din şirul în care e prezentată ordinea atingerii pereţilor. O instrucţiune va însemna o reflexie a dreptunghiului curent şi a punctului destinaţie al lui Vasile. După ce vom procesa toate coliziunile obţinem dreptunghiul final şi punctul de destinaţie transformat în interiorul acestui dreptunghi. Acum linia frântă care unea punctul de start s-a transformat într-un segment de dreaptă între punctul de start şi imaginea punctului final după ce s-a realizat asupra lui seria de transformări.\r\n\r\nh2(#aplicatia-7). Aplicaţia 7: \'_NCushion_\':http://www.topcoder.com/stat?c=problem_statement&pm=1963 (TopCoder)\r\n\r\nbq. Pe o masă de biliard de dimensiuni $2000 x 1000$ sunt aşezate două bile la coordonate întregi. Se cere să se determine numărul de posibilităţi de lovire a primei bile, astfel ca ea să lovească exact de $N$ ori manta $(1 &le; N &le; 500)$ şi apoi să lovească cea de a doua bilă. Mişcarea bilei se consideră ideală, iar dacă bila loveşte un colţ se consideră că s-au atins două mante şi bila se va mişca pe aceiaşi direcţie în sens opus.\r\n\r\nh3. Rezolvare:\r\n\r\n!> transformari-geometrice?aplicatie-7.1.png 70%!\r\n\r\nSoluţia foloseşte ideea de mai sus de a reflecta tabla de biliard împreună cu poziţia celei de a doua bile. Aşa cum am văzut în problema anterioară, fiecare şir de atingeri al mantelor ne dă exact un mod în care prima bilă o poate lovi pe cea de a doua. Dacă ştim în ce dreptunghi reflectat vrem să lovim bila a doua, fixând acest dreptunghi, avem o direcţie fixată şi un şir de mante fix pe care le va atinge bila dacă va fi lovită în acea direcţie. În figură avem cazul în care trebuie să lovim exact două mante înainte să atingem a doua bilă.\r\n\r\nÎn desen am colorat cu negru bila iniţială şi cu alb a doua bilă şi imaginile ei. Cu linie punctată am desenat traiectoriile care ar fi atins bila a doua fără a atinge de două ori manta şi cu linie neagră direcţiile pe care manta ar fi atinsă exact de două ori. Observăm că pentru a atinge manta de $N$ ori o bilă trebuie să intre în $N$ alte dreptunghiuri. Deci, asociem poziţiilor dreptunghiurilor un sistem de coordonate în care dreptunghiul iniţial are coordonatele $(0, 0)$. Pentru ca bila să atingă exact $N$ mante, coordonatele $(x, y)$ ale dreptunghiului trebuie să satisfacă egalitatea $|x| + |y| = N$. Mai trebuie să avem grijă ca drumul bilei care atinge $N$ mante să nu atingă a doua bilă înainte de atingerea tuturor mantelor. Aceste observaţii ne duc la următoarea soluţie: pentru toate dreptunghiurile $(x, y)$, care satisfac proprietatea $|x| + |y| < N$, păstrăm într-o structură de date (structura preferată de autor ar fi un \'tabel de dispersie\':tabele-hash-prezentare-detaliata) vectorul asociat direcţiei pe care ar fi trebuit lovită prima bilă pentru a ajunge la imaginea celei de a doua bile din acest dreptunghi. Apoi, pentru fiecare dreptunghi pentru care $|x| + |y| = N$, dacă direcţia asociată lui nu este în structura de date, incrementăm numărul de soluţii. Această rezolvare are complexitatea $O(N^2^ log N)$ pentru că normalizarea unei direcţii implică folosirea \'algoritmului lui Euclid\':problema/euclid2 ce are complexitate $O(log N)$.\r\n\r\nh2(#aplicatia-8). Aplicaţia 8: \'PuckShot\':http://www.topcoder.com/stat?c=problem_statement&pm=2411&rd=4750 (TopCoder)\r\n\r\nbq. Un jucător de hockey stângaci are o mişcare în care de la mijlocul terenului izbeşte pucul de marginea terenului care apoi întră în spaţiul porţii. Terenul este de $3000$ de centimetri lăţime. Distanţa între linia de mijloc şi linia de gol este de $1733$ de centimetri. Poarta este centrată pe linia de gol şi are dimensiunea de $183$ de centimetri. Când jucătorul loveşte, puc-ul se va lovi de marginea terenului şi apoi va ricoşa simetric în poartă. Pucul şi stâlpii porţii vor fi considerate puncte. Pe gheaţă vor fi cel mult nouă jucători care vor fi modelaţi ca segmente orizontale de lungime $50$ centimetri. Pentru ca lovitura să aibă succes, traiectoria ei nu trebuie să intersecteze niciun jucător. Pentru simplitate, puteţi presupune că terenul este perfect dreptunghiular. Se cere unghiul format de lovitura jucătorului cu linia de mijloc, astfel ca lovitura să fie cu succes şi pucul să intre în poartă şi să fie cât mai apropiat de stâlpul drept al porţii. Structura unui teren de hockey este prezentată în următoarea figură:\r\n\r\np=. !transformari-geometrice?aplicatie-8.1.png 70%!\r\n\r\nh3. Rezolvare:\r\n\r\n!> transformari-geometrice?aplicatie-8.2.png 70%!\r\n\r\nO rezolvare posibilă ar fi să pornim cu o lovitură de un unghi fixat şi să vedem dacă ajunge în poartă, iar apoi să creştem unghiul loviturii puţin câte puţin. Prin folosirea unor consideraţii de simetrie putem rezolva problema mai uşor şi mai eficient. Oglindim terenul împreună cu toţi jucătorii. Astfel, transformăm lovitura din două segmente în unul singur care trece prin dreapta de simetrie. Acum, luăm fiecare punct lateral al jucătorilor, fiecare punct lateral al imaginii reflectate ale jucătorilor şi punctele porţii reflectate, şi unim aceste puncte cu punctul de unde jucătorul va lovi pucul. Verificăm care dintre aceste drepte dacă sunt rotite foarte puţin la dreapta sau la stânga intersectează imaginea porţii reflectate şi nu intersectează segmentele ce reprezintă jucătorii sau imaginea lor reflectată. Astfel, soluţia noastră are complexitatea $O(N^2^)$ unde $N$ este numărul de jucători, pentru că pentru fiecare dintre cele $4N + 2$ raze trebuie să verificăm intersecţia cu $2N + 1$ segmente. Pe acestă idee putem realiza o soluţie în $O(N log N)$ folosind o linie de baleiere care trece prin punctul iniţial si se mişcă circular în jurul lui.\r\n\r\nh2(#aplicatia-9). Aplicaţia 9: \'Poligon 2\':problema/poligon2 (infoarena)\r\n\r\nbq. Se dau coordonatele mijloacelor laturilor unui poligon nu neapărat convex şi care se poate autointersecta. Se cere să se determine coordonatele vârfurilor poligonului.\r\n\r\nh3. Rezolvare:\r\n\r\nConsiderăm că poligonul are $N$ vârfuri. Rezolvăm problema întâi pentru $N$ par. Luăm primul vârf al poligonului, şi îi determinăm simetricul faţă de primul mijloc de latură. Astfel găsim al doilea vârf. Dacă luăm al doilea vârf printr-o simetrie îl obţinem pe al treilea ş.a.m.d. Deci prin $N$ simetrii obţinem din nou primul punct. Cum $N$ este par fiecare două simetrii compuse sunt o translaţie, deci avem o serie de translaţii care se compun într-una care duce punctul iniţial în punctul iniţial. Aşa cum am vazut la partea teoretică translaţia are un punct fix doar dacă ea e translaţie trivială. Translaţia fiind trivială, putem porni cu orice punct din plan şi să obţinem celelalte $N + 1$ puncte din poligon ca şi rezultate ale simetriilor aplicate succesiv. În cazul în care $N$ e impar transformarea explicată mai sus are ca rezultat compunerea între o translaţie şi o simetrie, compunere care aşa cum puteţi verifica are ca rezultat o simetrie de alt centru. Dar punctul iniţial este transformat în acelaşi punct, deci el trebuie să fie centrul de simetrie al transformării compuse. şi, atunci luăm un punct oarecare $P$ în plan, efectuăm cele $N$ transformări asupra lui şi obţinem un punct $P’$. Primul punct al poligonului va fi mijlocul acestui segment.\r\n\r\nh2(#aplicatia-10). Aplicaţia 10: \'Dmg\':problema/dmg (Stelele Informaticii 2005, infoarena)\r\n\r\nbq. Se dau $N (1 &le; N &le; 1500)$ puncte de coordonate întregi. Să se determine numărul de axe de simetrie al sistemului de puncte.\r\n\r\nh3. Rezolvare:\r\n\r\nAxele de simetrie ale sistemului de puncte trebuie să fie şi axe de simetrie pentru poligonul ce reprezintă înfăşurătoarea convexă a acestor puncte. Dacă vrem să găsim axele de simetrie ale unui poligon convex, observăm că dacă el are număr par de vârfuri, atunci trebuie ca acestea sau să fie mediatoare pentru o latură a poligonului, sau să treacă prin două vârfuri. Dacă el are număr impar de laturi atunci axele de simetrie trebuie să fie mediatoare pentru o latură şi să treacă printr-un punct al poligonului. Astfel, după calcularea în $O(N log N)$ a înfăţurătorii convexe, putem afla în timp $O(N)$ care sunt candidate la axa de simetrie a poligonului. Verificarea faptului dacă o dreaptă este axă de simetrie pentru un set de puncte o putem face în $O(N)$ folosindu-ne de o tabelă de dispersie. Algoritmul de determinare a axelor de simetrie are complexitatea finală $O(N^2^)$.\r\n\r\nh2(#aplicatia-11). Aplicaţia 11 (ONM 1997, clasa a VIII-a)\r\n\r\nbq. Se dă un paralelipiped $ABCDEFGH$, cu $AB = 5$, $BC = 4$, $AE = 3$. Se cere să determinăm poziţia unui punct $M$ ce aparţine segmentului $BF$ cu proprietatea că suma $AM + MG$ este minimă.\r\n\r\n!< transformari-geometrice?aplicatie-11.1.png 55%!\r\n\r\nh3. Rezolvare\r\n\r\n!> transformari-geometrice?aplicatie-11.2.png 55%!\r\n\r\nPentru această problemă ne putem imagina o soluţie analitică în care vrem să minimizăm funcţia $AM + MG$ care depinde de coordonata $y$, dar o asemenea rezolvare nu ar fi fost accesibilă unui elev de clasa a VIII-a. O soluţie elegantă şi simplă este următoarea. Desfăşurăm în plan feţele $ABFE$ şi $BCGD$. Astfel se formează dreptunghiul $ACGE$, unde $AC = 9$ şi $AE = 3$. Acum este clar că punctul $M$ trebuie să fie intersecţia diagonalei $AG$ cu $FB$. De aici putem găsi foarte uşor că $BM = 5/3$.\r\n\r\nh2(#aplicatia-12). Aplicaţia 12 (TopCoder)\r\n\r\nbq. Pe partea frontală a unui zgârie-nor foarte înalt, ce are forma unui paralelipiped, cu baza un pătrat de latura $200$ de metri, este situat un păianjen. Acesta vrea să mănânce o muscă situată pe faţa din dreapta a zgârie-norului. ştiind coordonatele păianjenului şi ale muştei vi se cere să determinaţi drumul cel mai scurt pe care îl poate face păianjenul ca să mănânce musca iar întreaga deplasare a lui să fie pe suprafaţa zgârie-norului (coordonatele gângăniilor se măsoară relativ la colţul stânga sus al feţei pe care se află fiecare).\r\n\r\nh3. Rezolvare:\r\n\r\nDesfăşurăm paralelipipedul în toate modurile posibile (aşa cum vedem în figură) şi alegem dintre toate drumurile soluţia optimă.\r\n\r\n!< transformari-geometrice?aplicatie-12.1.png 55%!\r\n\r\n!> transformari-geometrice?aplicatie-12.2.png 55%!\r\n\r\nh2(#aplicatia-13). Aplicaţia 13\r\n\r\n!> transformari-geometrice?aplicatie-13.1.png 75%!\r\n\r\nbq. Se dă un triunghi $ABC$ şi trei drepte $d{~1~}$, $d{~2~}$ şi $d{~3~}$ care nu sunt paralele între ele două câte două. Se cere să se determine un triunghi înscris în triunghiul $ABC$ ce are laturile paralele cu dreptele $d{~1~}$, $d{~2~}$ respectiv $d{~3~}$.\r\n\r\nh3. Rezolvare:\r\n\r\nConstruim un triunghi $D’E’F’$ ce are laturile paralele cu dreptele $d{~1~}$, $d{~2~}$ şi $d{~3~}$, iar punctul $E’$ aparţine semidreptei $[AC$ şi punctul $F’$ aparţine semidreptei $[AB$. Acum fixăm un punct $D$ în intersecţia lui $AD’$ cu $BC$ şi în acest punct ducem două drepte paralele cu dreptele $d{~1~}$ şi $d{~2~}$. Aceste drepte vor intersecta laturile triunghiului în punctele $F$ şi $E$. În omotetia de centru $A$ şi raport $AD / AD’$ triunghiul $D’E’F’$ se transformă în $DEF$, care este un triunghi ce respectă condiţia din enunţ.\r\n\r\nh2(#aplicatia-14). Aplicaţia 14: \'Triangular Square\':http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=82&page=show_problem&problem=1666 (UVa)\r\n\r\nbq. Se dă un triunghi $ABC$. Vrem să găsim aria maximă a unui pătrat situat în întregime în interiorul triunghiului. În imagine avem un pătrat în interiorul unui triunghi, dar acesta nu este de arie maximă. De exemplu într-un triunghi cu laturile de dimensiuni $6$, $6$ şi $6$, aria maximă este $7.754051$.\r\n\r\n!> transformari-geometrice?aplicatie-14.1.png 75%!\r\n\r\nh3. Rezolvare:\r\n\r\nPornim de la presupunerea intuitivă că cel mai mare pătrat ce se poate plasa în interiorul unui triunghi trebuie să aibă una din laturi pe o latură a triunghiului. Astfel, pentru a determina pătratul de arie maximă avem trei posibilităţi de aşezare pe laturile triunghiului. Pentru o aşezare fixată putem afla uşor pătratul maxim din interiorul triunghiului ce are două varfuri pe latura $BC$. O modalitate ar fi să desenăm un pătrat $M’N’P’Q’$ ce are punctele $Q’$ şi $P’$ pe semidreapta $[BC$ şi punctul $M’$ pe semidreapta $[BA$. După care, luăm punctul $N$ ca intersecţie a dreptei $BN’$ cu $AC$. Găsim pătratul $MNPQ$ ca fiind omoteticul pătratului $M’N’P’Q’$ după omotetia de centru $B$ şi raport $BN / BN’$. Altă modalitate de construcţie a pătratului ar fi cea prezentată în a doua figură, adică: se construieşte în exterior, pe latura $BC$ a triunghiului, un pătrat $BCQ’P’$, se determină punctele $P$ şi $Q$ ca şi intersecţii al segmentului $AQ’$ cu $BC$ şi al segmentului $AP’$ cu $BC$. Pătratul $MNPQ$ va fi omoteticul pătratului $BCP’Q’$, după omotetia de centru $A$ şi raport $QP / BC$.\r\n\r\nh2(#aplicatia-15). Aplicaţia 15: \'Arhipelago\':http://acm.sgu.ru/problem.php?contest=0&problem=120 (SGU)\r\n\r\nbq. Se dau coordonatele a două vârfuri ale unui poligon regulat de $N$ laturi. Se cere, dacă ştiţi pe $N$, cele două perechi de coordonate şi $N{~1~}$, $N{~2~}$ indicii celor două puncte pe poligon, să determinaţi coordonatele tuturor celor $N$ vârfuri.\r\n\r\nh3. Rezolvare:\r\n\r\nFie $O$ centrul cercului circumscris poligonului regulat. Dacă notăm $A$ şi $B$ cele două puncte, atunci putem uşor să determinăm măsura unghiului $AOB$ pe care o notăm cu $alfa$. Triunghiul $AOB$ este isoscel şi ştim că are la bază unghiuri de măsură $beta = (180 – alfa) / 2$. Pentru a determina punctul $O$ vom roti dreapta $AB$ în jurul lui $A$ după un unghi $beta$, şi vom roti dreapta $AB$ în jurul lui $B$ după un unghi $beta$. Cele două drepte ce rezultă din cele două rotaţii se vor intersecta în punctul $O$. Astfel, am găsit centrul cercului circumscris poligonului, pentru a găsi punctele lui îi aplicăm vârfului $A$ rotaţiile de centru $O$ şi unghiuri $360K/N$ unde $K$ ia toate valorile naturale de la $1$ la $N$.\r\n\r\nh2(#aplicatia-16). Aplicaţia 16: \'Geometrical dreams\':http://acm.timus.ru/problem.aspx?space=1&num=1046 (Timus)\r\n\r\nbq. Pe laturile unui poligon $A{~1~}A{~2~}...A{~N~}$ (vârfurile $A{~i~}$ sunt numerotate în ordine trigonometrică), se construiesc în exterior triunghiurile isoscele $A{~i~}M{~i~}A{~i+1~}$, iar unghiul $A{~i~}M{~i~}A{~i+1~} = alfa{~i~}$ (aici $A{~N+1~} = A{~1~}$). Suma măsurilor unghiurilor $alfa{~i~}$ nu este multiplu de $360$ de grade. Dacă ni se dau $N &le; 50$, coordonatele punctelor $M{~i~}$ şi unghiurile $alfa{~i~}$, scrieţi un program care ne dă coordonatele vârfurilor poligonului.\r\n\r\nh3. Rezolvare:\r\n\r\nAşa cum am văzut în partea teoretică, o compunere de mai multe rotaţii are ca rezultat o rotaţie al cărei unghi este suma unghiurilor rotaţiilor parţiale. Dacă pornim cu punctul $A{~1~}$ şi îl rotim în jurul lui $M{~1~}$ cu un unghi $alfa{~1~}$, după care luăm punctul rezultat şi îl rotim în jurul lui $M{~2~}$ cu unghiul $alfa{~2~}$ şi aşa mai departe până când am rotit pe $A{~1~}$ în punctelor $M{~1~}$, $M{~2~}$, ... $M{~n~}$. Efectuând aceşti paşi vom obţine pe rând vârfurile poligonului, iar la sfârşit $A{~1~}$ va ajunge din nou în poziţia iniţială. Acest procedeu este de fapt o serie de rotaţii, şi vedem că aplicarea lui asupra lui $A{~1~}$ îl lasă neschimbat. Cum suma măsurilor unghiurilor de rotaţie nu este multiplu de $360$ de grade, înseamnă că rotaţia nu este trivială, iar o rotaţie netrivială are ca punct fix doar centrul ei. Aşadar putem lua un punct oarecare în plan asupra căruia aplicăm procedeul şi vom obţine imaginea lui. Folosind aceste două puncte şi $alfa = suma de alfa{~i~}$ ca unghi de rotaţie, putem determina centrul $A{~1~}$ de rotaţie. După care efectuând transformările asupra lui $A{~1~}$ obţinem celelalte puncte ale poligonului.\r\n\r\nh2(#aplicatia-17). Aplicaţia 17: Texan (Baraj ONI, 2005)\r\n\r\n!> transformari-geometrice?aplicatie-17.1.png 75%!\r\n\r\nbq. Se dă un poligon convex de $N$ vârfuri $(3 &le; N &le; 700)$. Se cere să se determine un triunghi echilateral cu vârfurile aparţinând laturilor poligonului convex.\r\n\r\nh3. Rezolvare:\r\n\r\nLuăm un punct $O$ pe o latură a poligonului. Rotim întreg poligonul în jurul acestui punct $60$ de grade în sens trigonometric. Poligonul rotit va intersecta poligonul iniţial într-un nou punct $B$. Acest punct $B$ îl rotim în jurul lui $O$ cu $60$ de grade în sens orar. Rezultatul este un punct $B’$ care evident aparţine poligonului iniţial. Acum triunghiul $OBB’$ este echilateral pentru că $OB = OB’$ şi măsura unghiului $BOB’$ este de $60$ de grade. Menţionăm că aceasta a fost una dintre cele mai dure probleme de la selecţia lotului de anul acesta. O rezolvare de complexitate $O(N^2^)$ a fost de ajuns pentru punctajul maxim, dar facem observaţia că intersecţia a două poligoane convexe se poate face în complexitate $O(N)$.\r\n\r\nh2(#aplicatia-18). Aplicaţia 18: dotNet (.campion, 2004)\r\n\r\nbq. Se dau $N$ puncte în planul euclidian prin coordonatele lor, numere întregi. Apoi se efectuează $M$ operaţii asupra tuturor punctelor, într-o ordine dată $(1 &le; N &le; 100 000, 0 &le; M &le; 10 000)$. O operaţie poate fi de două tipuri: de translaţie sau de rotaţie. Într-o operaţie de rotaţie, punctele sunt rotite în jurul originii cu un anumit număr de grade în sens trigonometric. Într-o operaţie de translaţie, originea este mutată în alt punct relativ la originea curentă şi coordonatele celorlalte puncte sunt modificate astfel încât să reprezinte aceleaşi puncte relativ la noua origine. Scrieţi un program care calculează coordonatele tuturor punctelor după cele $M$ operaţii.\r\n\r\nh3. Rezolvare:\r\n\r\nFolosim scrierea operaţiilor de translaţie si rotaţie ca produs de  matrici. Dacă vrem să rotim punctul $(x, y)$ în jurul punctului de coordonate $(0, 0)$ după un unghi <tex> \\alpha </tex> atunci putem scrie:\r\n\r\n<tex> \\left[ \\begin{array}{c} x_1 \\\\ y_1 \\\\ 1 \\end{array} \\right] = \\begin{bmatrix} cos \\alpha & -sin \\alpha & 0 \\\\ sin \\alpha & cos \\alpha & 0 \\\\ 0 & 0 & 1 \\end{bmatrix} \\times \\left[ \\begin{array}{c} x \\\\ y \\\\ 1 \\end{array} \\right] </tex>\r\n\r\nIar translaţia o putem scrie ca:\r\n\r\n<tex> \\left[ \\begin{array}{c} x_2 \\\\ y_2 \\\\ 1 \\end{array} \\right] = \\begin{bmatrix} 1 & 0 & dx \\\\ 0 & 1 & dy \\\\ 0 & 0 & 1 \\end{bmatrix} \\times \\left[ \\begin{array}{c} x \\\\ y \\\\ 1 \\end{array} \\right] </tex>\r\n\r\nAstfel transformarea pentru un punct devine un produs de matrici care la sfârşit se înmulţeşte cu un vector ce reprezintă coordonatele punctului pe care vrem să îl transformăm. Pentru că transformarea compusă este aceeaşi pentru fiecare dintre cele $N$ puncte, determinăm matricea care o reprezintă o singură dată şi apoi o putem aplica pe rând fiecărui punct. Algoritmul are complexitatea $O(N + M)$.\r\nMenţionăm că o problemă similară apare pe SGU sub numele de wizards, diferenţa fiind că acolo operaţiile sunt în spaţiul tridimensional, dar rezolvarea este aproape identică.\r\n\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Nicolescu, Boskoff, _Probleme practice de geometrie_, Ed. Tehnică, Bucureşti, 1990\r\n# \'Cut the Knot\':http://www.cut-the-knot.org\r\n# \'Timus\':http://acm.timus.ru/\r\n# \'UVa\':http://uva.onlinejudge.org/\r\n# \'TopCoder\':http://www.topcoder.com/tc\r\n# \'SGU\':http://acm.sgu.ru\r\n# Dijkstra’s EWDs',3146,'public',NULL,NULL),('runda/summer_camp_3','summer_camp_3','2009-06-30 20:35:46','2009-06-30 20:35:46','h1. == roundparam(round_id=\"summer_camp_3\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"summer_camp_3\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"summer_camp_3\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"summer_camp_3\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/summer_camp_3/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"summer_camp_3\" score=\"1\")==',6957,'round: summer_camp_3',NULL,NULL),('runda/summer_camp_3/clasament','Clasament summer_camp_3','2009-06-30 20:35:46','2009-06-30 20:35:46','h1. Clasament ==roundparam(round_id=\"summer_camp_3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer_camp_3\")==',6957,'round: summer_camp_3',NULL,NULL),('runda/runda_0','runda_0','2009-07-01 03:52:39','2009-07-01 03:52:39','h1. == roundparam(round_id=\"runda_0\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"runda_0\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"runda_0\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"runda_0\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/runda_0/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"runda_0\" score=\"1\")==',10498,'round: runda_0',NULL,NULL),('runda/runda_0/clasament','Clasament runda_0','2009-07-01 03:52:39','2009-07-01 03:52:39','h1. Clasament ==roundparam(round_id=\"runda_0\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"runda_0\")==',10498,'round: runda_0',NULL,NULL),('runda/w0','w0','2009-07-01 03:54:43','2010-03-04 08:16:16','h1. == roundparam(round_id=\"w0\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"w0\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"w0\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"w0\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/w0/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"w0\" score=\"1\")==',10498,'round: w0',NULL,NULL),('runda/w0/clasament','Clasament w0','2009-07-01 03:54:43','2009-07-01 03:54:43','h1. Clasament ==roundparam(round_id=\"w0\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"w0\")==',10498,'round: w0',NULL,NULL),('olimpici','Romanii medaliati la IOI','2007-08-07 23:11:25','2009-10-14 06:39:47','h1. Romanii medaliati la IOI\r\n\r\nh2. Legenda\r\n\r\n* !olimpici?medal_gold.gif! - medalie de aur\r\n* !olimpici?medal_silver.gif! - medalie de argint\r\n* !olimpici?medal_bronze.gif! - medalie de bronz\r\n* *?* - informatie necunoscuta\r\n* *--* - nu se aplica (ex: este inca la scoala si nu are un loc de munca, sau nu are PhD, etc.)\r\n* *^**^* - compania este un \'startup\':http://en.wikipedia.org/wiki/Startup_company\r\n\r\ntable=. |_. Nume |_. Tara |_. Liceu |_. Medalii |_. \'Undergrad\':http://en.wikipedia.org/wiki/Undergraduate |_. \'PhD\':http://en.wikipedia.org/wiki/Doctor_of_Philosophy |_. Job |\r\n| \'Cosmin Gheorghe\':utilizator/gcosmin  | Romania | ICHB (Bucuresti) |  !olimpici?medal_gold.gif! 2009; !olimpici?medal_gold.gif! 2008; !olimpici?medal_silver.gif! 2007  | -- |  -- |  -- |\r\n| \'Mihai Patrascu\':http://web.mit.edu/~mip/www/  | Romania | Carol I (Craiova) |  !olimpici?medal_gold.gif! 2001; !olimpici?medal_gold.gif! 2000; !olimpici?medal_silver.gif! 1999  | MIT | MIT (theory) | internship IBM, angajat IBM, angajat AT&T |\r\n| Radu Berinde  | Romania | ICHB + Vianu(Bucuresti) | !olimpici?medal_gold.gif! 2003; !olimpici?medal_gold.gif! 2002  | MIT | -- | 2 internshipuri Google, internship vmware, angajat vmware |\r\n| Daniel Dumitran  | Romania | ICHB (Bucuresti) |  !olimpici?medal_gold.gif! 2002; !olimpici?medal_gold.gif! 2000  | MIT | -- | Moka5^**^ (Silicon Valley), internship Google |\r\n| \'Adrian Soviani\':http://www.cs.princeton.edu/~asoviani/  | Romania | Tudor Vianu (Bucuresti) |  !olimpici?medal_gold.gif! 1994; !olimpici?medal_gold.gif! 1993  | MIT | Princeton (parallel computing) | formerly Akamai |\r\n| \'Bogdan Tataroiu\':utilizator/bogdan2412  | Romania | ICHB (Bucuresti) |  !olimpici?medal_gold.gif! 2009; !olimpici?medal_silver.gif! 2007; !olimpici?medal_bronze.gif! 2008  |  -- |  -- |  -- |\r\n| \'Mircea Pasoi\':utilizator/domino  | Romania | IL Caragiale (Ploiesti) |  !olimpici?medal_gold.gif! 2006; !olimpici?medal_silver.gif! 2005  | Univ. Bucuresti |  -- | internship Microsoft internship Google, angajat UberVu |\r\n| Victor Costan  | Romania | Vianu (Bucuresti) |  !olimpici?medal_gold.gif! 2003; !olimpici?medal_silver.gif! 2002  | MIT | -- | angajat Google, internship Apple, internship Google |\r\n| Mihai Stroe  | Romania | ? (Bucuresti) |  !olimpici?medal_gold.gif! 1998; !olimpici?medal_bronze.gif! 1997  | Poli. Bucuresti | -- | Google (Zurich) |\r\n| Ovidiu Gheorghioiu  | Romania | Horia, Closca si Crisan (Alba Iulia) |  !olimpici?medal_gold.gif! 1997; !olimpici?medal_silver.gif! 1996  | MIT | -- | Google (Mtn View, Calif.) |\r\n| \'Mihai Badoiu\':http://people.csail.mit.edu/mihai/ | Romania | Tudor Vianu (Bucuresti) |  !olimpici?medal_gold.gif! 1995; !olimpici?medal_silver.gif! 1996  | MIT | MIT (theory) | Google (NY) |\r\n| \'Radu Lupsa\':http://cs.ubbcluj.ro/~rlupsa/  | Romania | Avram Iancu (Cluj) |  !olimpici?medal_gold.gif! 1993; !olimpici?medal_silver.gif! 1995  | ENS Paris | Babes-Bolyai, Cluj (image proc.) | prof @ Babes Bolyai |\r\n| Codrut Grosu  | Romania | Vianu (Bucuresti) | !olimpici?medal_gold.gif! 2006  |  Poli. Bucuresti |  -- |  -- |\r\n| \'Silviu Ganceanu\':utilizator/silviug  | Romania | CN Gheorghe Rosca Codreanu (Barlad) + ICHB (Bucuresti) |  !olimpici?medal_gold.gif! 2004  |  Poli. Bucuresti |  -- |  2 internshipuri Google |\r\n| Vlad Dascalu  | Romania | ? (Bacau) |  !olimpici?medal_gold.gif! 2001  | Poli. Bucuresti | -- |  Google (Zurich) |\r\n| \'Bogdan Dumitru\':http://alumnus.caltech.edu/~dumi/  | Romania | IL Caragiale (Ploiesti) |  !olimpici?medal_gold.gif! 1999  | Caltech | -- | formerly Google, Microsoft (Mountain View) |\r\n| \'Alexandr Andoni\':http://www.mit.edu/~andoni/  | Moldova | ? (Chisinau) |  !olimpici?medal_silver.gif! 1999; !olimpici?medal_silver.gif! 1998; !olimpici?medal_bronze.gif! 1997  | MIT | MIT (theory) | internship Google, internship IBM |\r\n| Matei Zaharia  | Canada |  ? | !olimpici?medal_silver.gif! 2003; !olimpici?medal_silver.gif! 2002  | Waterloo, Canada | Berkeley | internship Google, internship Facebook |\r\n| Adrian Vladu  | Romania | Tudor Vianu (Bucuresti) |  !olimpici?medal_silver.gif! 2004; !olimpici?medal_bronze.gif! 2006  | Brown | -- | -- |\r\n| \'Radu Stefan\':http://ce.et.tudelft.nl/~radu124/  | Romania | Andrei Saguna (Brasov) |  !olimpici?medal_silver.gif! 2000; !olimpici?medal_bronze.gif! 1999  | Brasov | Delft, Holland (parallel computing) | -- |\r\n| Virgil Palanciuc  | Romania | Horia, Closca si Crisan (Alba Iulia) |  !olimpici?medal_silver.gif! 1995; !olimpici?medal_bronze.gif! 1994  | Poli. Bucuresti | -- | Adobe, Romania |\r\n| \'Emil Praun\':http://www.cs.utah.edu/~emilp/  | Romania | Tudor Vianu (Bucuresti) | !olimpici?medal_silver.gif! 1993; !olimpici?medal_bronze.gif! 1992  | Caltech | Princeton (graphics) | Google (formerly prof @ Utah) |\r\n| \'Marius Dragus\':utilizator/mariusdrg  | Romania | ICHB (Bucuresti) |  !olimpici?medal_silver.gif! 2009  |  Poli. Bucuresti |  -- |  -- |\r\n| \'Paul-Dan Baltescu\':utilizator/pauldb  | Romania | ICHB (Bucuresti) |  !olimpici?medal_silver.gif! 2008  |  Univ. Bucuresti |  -- |  -- |\r\n| \'Adrian Airinei\':utilizator/astronomy  | Romania | Costache Negruzzi (Iasi) |  !olimpici?medal_silver.gif! 2007  |  A.I. Cuza, Iasi |  -- |  -- |\r\n| \'Andrei Grigorean\':utilizator/wefgef  | Romania | ICHB (Bucuresti) |  !olimpici?medal_silver.gif! 2007  |  Univ. Bucuresti |  -- |  internship Google |\r\n| Tiberiu Florea  | Romania | Sf. Sava (Bucuresti) |  !olimpici?medal_silver.gif! 2006  |  Univ. Bucuresti |  -- |  internship Microsoft |\r\n| Dan Fechete  | Romania | Spriru Haret (Suceava) |  !olimpici?medal_silver.gif! 2005  | Univ. Bucuresti |  -- |  acceptat la internship Google |\r\n| \'Crestez Leonard\':utilizator/fluffy | Romania | ? (Braila) |  !olimpici?medal_silver.gif! 2004  |  Poli. Bucuresti | -- | -- |\r\n| Stefan Ciobaca  | Romania | Stefan cel Mare (Suceava) |  !olimpici?medal_silver.gif! 2003  | A.I.Cuza, Iasi |  -- |  2 internshipuri Microsoft |\r\n| Dan Ghinea  | Romania | Vianu (Bucuresti) | !olimpici?medal_silver.gif! 2003  |  Univ. Bucuresti |  ? |  2 intershipuri Google |\r\n| Mugurel Andreica  | Romania | ? (Bucuresti) |  !olimpici?medal_silver.gif! 2001  |  Poli. Bucuresti | Poli. Bucuresti |  Asst Prof @ Poli. Bucuresti |\r\n| Angel Proorocu  | Romania | Tudor Vianu (Bucuresti) | !olimpici?medal_silver.gif! 2000  |  Univ. Bucuresti |  -- |  Microsoft (Dublin) |\r\n| Tudor Leu  | Romania | Unirea (Focsani) |  !olimpici?medal_silver.gif! 1998  | MIT | -- | Google (NY) |\r\n| Mihai Scortaru  | Romania | Tiberiu Popovici (Cluj) |  !olimpici?medal_silver.gif! 1998  | U. Tech. Cluj |  -- | Atlantis Soft^**^, Cluj; GInfo |\r\n| \'Vali Gheorghita\':http://www.es.ele.tue.nl/~vali/ | Romania | IL Caragiale (Ploiesti) |  !olimpici?medal_silver.gif! 1997  | Poli. Bucuresti | Eindhoven (embedded sys.) | Google (Zurich) |\r\n| \'Catalin Francu\':http://catalin.francu.com/  | Romania | Tudor Vianu (Bucuresti) |  !olimpici?medal_silver.gif! 1996  | MIT | -- | Google (Mnt View, Calif) |\r\n| Marius Vlad  | Romania | ? (Bucuresti) |  !olimpici?medal_silver.gif! 1996  | Poli. Bucuresti |  ? | Google (Zurich) |\r\n| \'Iuliu Vasilescu\':http://web.mit.edu/~iuliuv/www/ | Romania | ? (Tulcea) |  !olimpici?medal_silver.gif! 1995  | Poli. Bucuresti | MIT (robotics) | -- |\r\n| \'Alexandru Salcianu\':http://cag.csail.mit.edu/~salcianu/  | Romania | Tudor Vianu (Bucuresti) |  !olimpici?medal_silver.gif! 1994  | ENS Cachan (France) | MIT (systems) | Google NY |\r\n| Mihai Preda  | Romania | ? | !olimpici?medal_silver.gif! 1994  |  ? |  ? |  Google (Cracovia) |\r\n| Valentin Necula  | Romania | ? |  !olimpici?medal_silver.gif! 1992  |  ? |  ? |  ? |\r\n| Constantin Jucovschi  | Moldova | MoldoTurc (Chisinau) | !olimpici?medal_bronze.gif! 2004; !olimpici?medal_bronze.gif! 2003; !olimpici?medal_bronze.gif! 2002; !olimpici?medal_bronze.gif! 2001  | Bremen | -- |  internship Google |\r\n| Dumitru Codreanu  | Moldova | MoldoTurc (Chisinau) | !olimpici?medal_bronze.gif! 2002; !olimpici?medal_bronze.gif! 2001; !olimpici?medal_bronze.gif! 2000  | Univ. Bucuresti | -- | Ubisoft (?) |\r\n| Dumitru Ciubatii  | Moldova | MoldoTurc (Chisinau) | !olimpici?medal_bronze.gif! 2004; !olimpici?medal_bronze.gif! 2002  | Univ. Bucuresti | -- | internship Google |\r\n| \'Andrei Puni\':utilizator/crawler  | Romania | Al. Papiu Ilarian (Targu Mures) | !olimpici?medal_bronze.gif! 2009  |  UBB Cluj |  ? |  ? |\r\n| Filip Simion  | Moldova | MoldoTurc (Chisinau) | !olimpici?medal_bronze.gif! 2005  | Princeton | -- | -- |\r\n| Daniel Pasaila  | Romania | C.N Petru Rares (Suceava) |  !olimpici?medal_bronze.gif! 2005  | A.I.Cuza, Iasi | -- | -- |\r\n| Radu Marin  | Romania | ? (Focsani) | !olimpici?medal_bronze.gif! 2005  | A.I.Cuza, Iasi | -- | internship Google |\r\n| Sorin Stancu-Mara  | Romania | ICHB (Bucuresti) |  !olimpici?medal_bronze.gif! 2004  |  Bremen | -- | 2 internshipuri Google, angajat Google |\r\n| Constantin Dolghieru  | Moldova | Prometeu (Chisinau) | !olimpici?medal_bronze.gif! 2004  | Poli. Bucuresti |  -- |  -- |\r\n| Eugen Sorbalo  | Moldova | MoldoTurc (Chisinau) | !olimpici?medal_bronze.gif! 2003  | Bremen | -- | -- |\r\n| Csaba Andras  | Romania | Ady Endre (Oradea) |  !olimpici?medal_bronze.gif! 2001  | Budapest |  ? |  ? |\r\n| Corneliu Margine  | Moldova | Mircea Eliade (Chisinau) | !olimpici?medal_bronze.gif! 2001  | Bremen | -- |  ? |\r\n| Denis Bogdanas  | Moldova | ? | !olimpici?medal_bronze.gif! 2000  | ? |  ? |  ? |\r\n| Adrian Carcu  | Romania | Liviu Rebreanu (Bistrita) |  !olimpici?medal_bronze.gif! 1999  |  Babes Bolyai  |  -- |  Montran, Cluj Napoca|\r\n| Diodor Bitan  | Romania | Tudor Vianu (Bucuresti) | !olimpici?medal_bronze.gif! 1998  |  ? |  ? |  ? |\r\n| Nicolae Branza  | Moldova | ? | !olimpici?medal_bronze.gif! 1997  | Poli. Bucuresti |  ? |  ? |\r\n| \'Dan Stratila\':http://web.mit.edu/~dstrat/www/  | Moldova | ? | !olimpici?medal_bronze.gif! 1997  | Univ. Chisinau | MIT (operations research) | -- |\r\n| Alin Sinpalean  | Romania | Scoala nationala de gaz (Medias) | !olimpici?medal_bronze.gif! 1997  | Poli. Bucuresti | -- | Google (Zurich)|\r\n| Bogdan Ghenea  | Romania | Tudor Vianu (Bucuresti) | !olimpici?medal_bronze.gif! 1993  |  ? |  ? |  ? |\r\n',2028,'public',NULL,NULL),('runda/the_easiest_race','the_easiest_race','2009-07-03 07:36:35','2009-07-03 07:36:35','h1. == roundparam(round_id=\"the_easiest_race\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"the_easiest_race\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"the_easiest_race\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"the_easiest_race\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/the_easiest_race/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"the_easiest_race\" score=\"1\")==',10515,'round: the_easiest_race',NULL,NULL),('runda/the_easiest_race/clasament','Clasament the_easiest_race','2009-07-03 07:36:35','2009-07-03 07:36:35','h1. Clasament ==roundparam(round_id=\"the_easiest_race\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"the_easiest_race\")==',10515,'round: the_easiest_race',NULL,NULL),('runda/my_cex','my_cex','2009-07-03 07:48:01','2009-07-03 07:48:01','h1. == roundparam(round_id=\"my_cex\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"my_cex\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"my_cex\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"my_cex\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/my_cex/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"my_cex\" score=\"1\")==',10515,'round: my_cex',NULL,NULL),('runda/my_cex/clasament','Clasament my_cex','2009-07-03 07:48:01','2009-07-03 07:48:01','h1. Clasament ==roundparam(round_id=\"my_cex\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"my_cex\")==',10515,'round: my_cex',NULL,NULL),('runda/splunge1','splunge1','2009-07-05 20:23:59','2009-07-05 20:23:59','h1. == roundparam(round_id=\"splunge1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"splunge1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"splunge1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"splunge1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/splunge1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"splunge1\" score=\"1\")==',4439,'round: splunge1',NULL,NULL),('runda/splunge1/clasament','Clasament splunge1','2009-07-05 20:23:59','2009-07-05 20:23:59','h1. Clasament ==roundparam(round_id=\"splunge1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"splunge1\")==',4439,'round: splunge1',NULL,NULL),('runda/summer_camp_4','summer_camp_4','2009-07-19 12:01:35','2009-07-19 12:01:35','h1. == roundparam(round_id=\"summer_camp_4\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"summer_camp_4\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"summer_camp_4\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"summer_camp_4\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/summer_camp_4/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"summer_camp_4\" score=\"1\")==',6957,'round: summer_camp_4',NULL,NULL),('programare-dinamica-introducere','Introducere in programarea dinamica ','2009-07-14 09:09:43','2009-07-14 09:10:06','h1. Introducere in programarea dinamica ',1430,'public',NULL,NULL),('runda/summer_camp_4/clasament','Clasament summer_camp_4','2009-07-19 12:01:35','2009-07-19 12:01:35','h1. Clasament ==roundparam(round_id=\"summer_camp_4\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer_camp_4\")==',6957,'round: summer_camp_4',NULL,NULL),('runda/splunge2/clasament','Clasament splunge2','2009-07-15 06:02:07','2009-07-15 06:02:07','h1. Clasament ==roundparam(round_id=\"splunge2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"splunge2\")==',4439,'round: splunge2',NULL,NULL),('summer-challenge-2009/runda-1','Summer Challenge 2009, Runda 1','2009-07-19 18:30:13','2009-07-19 18:32:23','h1. Summer Challenge 2009, Runda 1\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2009\r\n*(active) \'Runda 1\':summer-challenge-2009/runda-1\r\n* \'Runda 2\':summer-challenge-2009/runda-2\r\n* \'Runda 3\':summer-challenge-2009/runda-3\r\n* \'Clasament\':summer-challenge-2009/clasament\r\n\r\nRunda se va desfasura Sambata 25 iulie, la ora {*10^00^*} si va dura *5h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"summer2009-runda1\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"summer2009-runda1\" score=\"1\")==\r\n\r\nSolutiile le gasiti \'aici\':summer-challenge-2009/solutii/runda-1\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 1\':summer-challenge-2009/clasament/runda-1\r\n\r\nh2. Organizatori\r\n\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"marius\" type=\"tiny\")==',2028,'protected',NULL,NULL),('summer-challenge-2009/clasament/runda-1','Clasament Summer Challenge 2009, Runda 1','2009-07-19 18:53:10','2009-07-19 18:53:10','h1. Clasament \'Summer Challenge 2009, Runda 1\':summer-challenge-2009/runda-1\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2009/\r\n*(active) \'Runda 1\':summer-challenge-2009/runda-1\r\n* \'Runda 2\':summer-challenge-2009/runda-2\r\n* \'Runda 3\':summer-challenge-2009/runda-3\r\n*(active) \'Clasament\':summer-challenge-2009/clasament\r\n\r\n== Rankings(rounds=\"summer2009-runda1\") == ',2028,'protected',NULL,NULL),('summer-challenge-2009/clasament','Clasament Summer Challenge 2009','2009-07-19 18:49:07','2009-07-19 18:49:07','h1. Clasament \'Summer Challenge 2009\':summer-challenge-2009/\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2009\r\n* \'Runda 1\':summer-challenge-2009/runda-1\r\n* \'Runda 2\':summer-challenge-2009/runda-2\r\n* \'Runda 3\':summer-challenge-2009/runda-3\r\n*(active) \'Clasament\':summer-challenge-2009/clasament\r\n\r\nAcesta este clasamentul cumulat pentru cele 3 runde online.\r\n\r\n== Rankings(rounds=\"summer2009-runda1 | summer2009-runda2 | summer2009-runda3\") ==',2028,'protected',NULL,NULL),('summer-challenge-2009/runda-2','Summer Challenge 2009, Runda 2','2009-07-19 18:40:07','2009-07-28 19:43:03','h1. Summer Challenge 2009, Runda 2\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2009\r\n* \'Runda 1\':summer-challenge-2009/runda-1\r\n*(active) \'Runda 2\':summer-challenge-2009/runda-2\r\n* \'Runda 3\':summer-challenge-2009/runda-3\r\n* \'Clasament\':summer-challenge-2009/clasament\r\n\r\nRunda se va desfasura Vineri 31 iulie, la ora {*08^30^*} si va dura *5h*. Participantii vor avea de rezolvat 4 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"summer2009-runda2\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"summer2009-runda2\" score=\"1\")==\r\n\r\nSolutiile le gasiti \'aici\':summer-challenge-2009/solutii/runda-2\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 2\':summer-challenge-2009/clasament/runda-2\r\n\r\nh2. Organizatori\r\n\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"marius\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==',2028,'protected',NULL,NULL),('summer-challenge-2009/solutii/runda-1','Solutii Summer Challenge 2009, Runda 1','2009-07-19 18:59:21','2009-07-25 13:28:57','h1. Solutii \'Summer Challenge 2009, Runda 1\':summer-challenge-2009/runda-1\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Joc11\':summer-challenge-2009/solutii/runda-1#joc11\r\n* \'Drepte3\':summer-challenge-2009/solutii/runda-1#drepte3\r\n* \'Posta\':summer-challenge-2009/solutii/runda-1#posta\r\n\r\n==include(page=\"summer-challenge-2009/solutii/runda-1/joc11\")==\r\n\r\n==include(page=\"summer-challenge-2009/solutii/runda-1/drepte3\")==\r\n\r\n==include(page=\"summer-challenge-2009/solutii/runda-1/posta\")==\r\n',2028,'public',NULL,NULL),('newsletter/summer-2009-1','Summer Challenge 2009, Runda 1','2009-07-19 20:11:35','2009-07-28 19:35:05','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎn toiul vacanţei de vară, feriţi de caniculă, la umbra monitoarelor, infoarena se gândeşte la tine! :)\r\n\r\nTe invităm să participi la seria de concursuri Summer Challenge 2009. Vom organiza 3 runde online, de câte 5h fiecare, cu probleme de dificultate variată.\r\n\r\nSummer Challenge este o ocazie bună de antrenament pentru tine (dacă nu eşti deja la mare :P), dar şi un ultim test pentru delegaţia României la Olimpiada Internaţională de Informatică 2009 (Bulgaria). Cu această ocazie, după o lungă perioadă de pauză, doi dintre veteranii noştri se întorc în arenă: \'Bogdan Tătăroiu\':utilizator/bogdan2412 şi \'Cosmin Gheorghe\':utilizator/gcosmin. Întrece-te cu ei!\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Runda 1 se desfăşoară\r\n*Sâmbătă, 25 Iulie 2009, orele 10^00^ - 15^00^*. |\r\n\r\nOrganizatorii primei runde online Summer Challenge 2009 sunt:\r\n\r\n* \'Andrei Grigorean\':utilizator/wefgef\r\n* \'Marius Stroe\':utilizator/marius\r\n* \'Paul - Dan Baltescu\':utilizator/pauldb\r\n\r\nPentru informaţii suplimentare (cum particip, întrebări etc.) vizitează \'pagina concursului\':summer-challenge-2009.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"summer-challenge-2009/runda-1\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}.  Concursurile internaţionale de informatică din 2009\r\n\r\nÎn perioada 28 iunie - 8 iulie a avut loc Olimpiada Pluridisciplinară din Yakutia. Echipa noastră s-a prezentat excelent:\r\n\r\n* \'Andrei Purice\':utilizator/protoman - AUR ABSOLUT\r\n* \'Teodor Pripoae\':utilizator/toni2007 - AUR\r\n* \'Andrei Poenaru\':utilizator/andreyp - ARGINT\r\n\r\nTot la începutul acestei veri, România a găzduit cea de a XVI-a ediţie a \'Olimpiadei de Informatică a Europei Centrale\':http://ceoi2009.ro/. Concurenţii noştri au obţinut următoarele medalii:\r\n\r\n* \'Cosmin Gheorghe\':utilizator/gcosmin - ARGINT\r\n* \'Bogdan Tătăroiu\':utilizator/bogdan2412 - ARGINT\r\n* \'Marius Drăguş\':utilizator/mariusdrg - ARGINT\r\n* \'Andrei Pârvu\':utilizator/andrei.12 - ARGINT\r\n* \'Şerban Andrei Stan\':utilizator/savim - ARGINT\r\n* \'Andrei Antonescu\':utilizator/andrei-alpha - BRONZ\r\n* \'Andrei Puni\':utilizator/crawler - BRONZ\r\n* \'Flaviu Pepelea\':utilizator/Pepelea_Flaviu - BRONZ\r\n* \'Victor Ionescu\':utilizator/vanila_CPP - BRONZ\r\n\r\nFelicitări băieţi! Suntem mândri de voi!\r\n\r\nA XXI-a ediţie a \'Olimpiadei Internaţionale de Informatică\':http://ioi2009.org/ este găzduită de Bulgaria (în Plovdiv) şi se desfăşoară în perioada 8-15 august.\r\n\r\nUrăm succes delegaţiei României la IOI 2009! Sperăm ca reprezentanţii noştri să facă ce ştiu cel mai bine, să obţină rezultate excepţionale.\r\n\r\nLotul României este condus de către Prof. Constatin Galaţan şi de către As. Univ. Dr. \'Mugurel Ionuţ Andreica\':utilizator/mugurelionut. Participanţi:\r\n\r\n* \'Cosmin Gheorghe\':utilizator/gcosmin\r\n* \'Bogdan Tătăroiu\':utilizator/bogdan2412\r\n* \'Marius Drăguş\':utilizator/mariusdrg\r\n* \'Andrei Puni\':utilizator/crawler\r\n\r\nVă urăm multă baftă! Să veniţi înapoi cu medalii cât mai strălucitoare!\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==',2028,'protected',NULL,NULL),('runda/splunge4/clasament','Clasament splunge4','2009-07-23 06:01:19','2009-07-23 06:01:19','h1. Clasament ==roundparam(round_id=\"splunge4\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"splunge4\")==',4439,'round: splunge4',NULL,NULL),('blog/problema-saptamanii-stream','Problema saptamanii - Stream','2009-07-21 08:54:36','2009-07-21 10:22:40','Daca tot am inceput sa scriu, am o problema draguta ce s-ar potrivi la un interviu tehnic:\r\n\r\n_Se da un stream de n numere intregi. Sa se gaseasca un algoritm ce determina cele mai mici k numere din acest stream in timp O(n) si memorie O(k). Streamul are urmatoarele doua metode int getNext() si bool hasNext()._\r\n\r\nCa de obicei, puteti trimite solutiile pe adresa cosminn at gmail.com',58,'protected',4043,NULL),('runda/1august','1august','2009-07-21 19:55:14','2009-07-21 19:55:14','h1. == roundparam(round_id=\"1august\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"1august\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"1august\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"1august\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/1august/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"1august\" score=\"1\")==',9356,'round: 1august',NULL,NULL),('runda/1august/clasament','Clasament 1august','2009-07-21 19:55:14','2009-07-21 19:55:14','h1. Clasament ==roundparam(round_id=\"1august\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"1august\")==',9356,'round: 1august',NULL,NULL),('runda/august_contest','august_contest','2009-07-21 19:56:12','2009-07-21 19:56:12','h1. == roundparam(round_id=\"august_contest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"august_contest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"august_contest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"august_contest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/august_contest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"august_contest\" score=\"1\")==',9356,'round: august_contest',NULL,NULL),('runda/august_contest/clasament','Clasament august_contest','2009-07-21 19:56:12','2009-07-21 19:56:12','h1. Clasament ==roundparam(round_id=\"august_contest\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"august_contest\")==',9356,'round: august_contest',NULL,NULL),('runda/splunge3','splunge3','2009-07-22 07:04:10','2009-07-22 07:04:10','h1. == roundparam(round_id=\"splunge3\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"splunge3\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"splunge3\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"splunge3\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/splunge3/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"splunge3\" score=\"1\")==',4439,'round: splunge3',NULL,NULL),('runda/splunge3/clasament','Clasament splunge3','2009-07-22 07:04:10','2009-07-22 07:04:10','h1. Clasament ==roundparam(round_id=\"splunge3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"splunge3\")==',4439,'round: splunge3',NULL,NULL),('runda/lol_contest_round_01','lol_contest_round_01','2009-07-22 16:25:50','2009-07-22 16:25:50','h1. == roundparam(round_id=\"lol_contest_round_01\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"lol_contest_round_01\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"lol_contest_round_01\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"lol_contest_round_01\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/lol_contest_round_01/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"lol_contest_round_01\" score=\"1\")==',6245,'round: lol_contest_round_01',NULL,NULL),('runda/lol_contest_round_01/clasament','Clasament lol_contest_round_01','2009-07-22 16:25:50','2009-07-22 16:25:50','h1. Clasament ==roundparam(round_id=\"lol_contest_round_01\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"lol_contest_round_01\")==',6245,'round: lol_contest_round_01',NULL,NULL),('runda/lol_contest_02','lol_contest_02','2009-07-22 16:42:22','2009-07-22 16:42:22','h1. == roundparam(round_id=\"lol_contest_02\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"lol_contest_02\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"lol_contest_02\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"lol_contest_02\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/lol_contest_02/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"lol_contest_02\" score=\"1\")==',3333,'round: lol_contest_02',NULL,NULL),('runda/lol_contest_02/clasament','Clasament lol_contest_02','2009-07-22 16:42:22','2009-07-22 16:42:22','h1. Clasament ==roundparam(round_id=\"lol_contest_02\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"lol_contest_02\")==',3333,'round: lol_contest_02',NULL,NULL),('runda/lol_contest_try2','lol_contest_try2','2009-07-22 16:42:45','2009-07-22 16:42:45','h1. == roundparam(round_id=\"lol_contest_try2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"lol_contest_try2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"lol_contest_try2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"lol_contest_try2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/lol_contest_try2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"lol_contest_try2\" score=\"1\")==',6245,'round: lol_contest_try2',NULL,NULL),('runda/lol_contest_try2/clasament','Clasament lol_contest_try2','2009-07-22 16:42:45','2009-07-22 16:42:45','h1. Clasament ==roundparam(round_id=\"lol_contest_try2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"lol_contest_try2\")==',6245,'round: lol_contest_try2',NULL,NULL),('summer-challenge-2009','Summer Challenge 2009','2009-07-19 18:27:40','2009-07-27 16:09:25','h1. Summer Challenge 2009\r\n\r\n(htabs)*(active) \'Detalii\':summer-challenge-2009/\r\n* \'Runda 1\':summer-challenge-2009/runda-1\r\n* \'Runda 2\':summer-challenge-2009/runda-2\r\n* \'Runda 3\':summer-challenge-2009/runda-3\r\n* \'Clasament\':summer-challenge-2009/clasament\r\n\r\nConcursul Summer Challenge revine dupa un an de pauza si e gata sa loveasca din nou! ;)\r\n\r\nTe plictisesti in mijlocul verii sau ti-e dor de concursurile din timpul anului? Inca nu ai plecat la mare sau la munte? Vrei sa iti masori fortele cu ceilalti membri infoarena?\r\n\r\nTe invitam sa participi la seria de concursuri {*Summer Challenge 2009*}. Vom organiza 3 runde online, de cate 5h fiecare, cu probleme de nivel mediu spre greu. Continuand traditia, editia din anul acesta se doreste a fi atat un ultim test pentru delegatia Romaniei la IOI (Bulgaria), cat si o buna ocazie de antrenament pentru utilizatorii infoarena. In toiul verii, suntem singurii care organizeaza concursuri! ;)\r\n\r\nIntra in competitie alaturi de cei mai buni!\r\n\r\nh2. Program concurs\r\n\r\ntable{width: 50%}. |_. Runda|_. Data |_. Ora |\r\n|\"*Runda 1*\":summer-challenge-2009/runda-1|*Sambata, 25 iulie 2009*| *10^00^ - 15^00^* |\r\n|\"*Runda 2*\":summer-challenge-2009/runda-2|*Vineri, 31 iulie 2009*| *08^30^ - 13^30^* |\r\n|\"*Runda 3*\":summer-challenge-2009/runda-3|*Miercuri, 5 august 2009*| *10^00^ - 15^00^* |\r\n\r\nClick pe titlul unei runde pentru informatii detaliate.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"75\" count=\"10\")==\r\n\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru.\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti probleme, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nh2. Prima data pe infoarena?\r\n\r\ninfoarena ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi.\r\n\r\nVezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n',1792,'protected',NULL,NULL),('summer-challenge-2009/clasament/runda-2','Clasament Summer Challenge 2009, Runda 2','2009-07-24 23:29:17','2009-07-24 23:29:17','h1. Clasament \'Summer Challenge 2009, Runda 2\':summer-challenge-2009/runda-2\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2009/\r\n* \'Runda 1\':summer-challenge-2009/runda-1\r\n*(active) \'Runda 2\':summer-challenge-2009/runda-2\r\n* \'Runda 3\':summer-challenge-2009/runda-3\r\n*(active) \'Clasament\':summer-challenge-2009/clasament\r\n\r\n== Rankings(rounds=\"summer2009-runda2\") == ',2028,'protected',NULL,NULL),('summer-challenge-2009/clasament/runda-3','Clasament Summer Challenge 2009, Runda 3','2009-07-24 23:34:03','2009-07-24 23:34:03','h1. Clasament \'Summer Challenge 2009, Runda 3\':summer-challenge-2009/runda-3\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2009/\r\n* \'Runda 1\':summer-challenge-2009/runda-1\r\n* \'Runda 2\':summer-challenge-2009/runda-2\r\n*(active) \'Runda 3\':summer-challenge-2009/runda-3\r\n*(active) \'Clasament\':summer-challenge-2009/clasament\r\n\r\n== Rankings(rounds=\"summer2009-runda3\") == ',2028,'protected',NULL,NULL),('runda/summer_challenge_intarziat','summer_challenge_intarziat','2009-07-25 11:59:36','2009-07-25 12:02:25','h1. == roundparam(round_id=\"summer_challenge_intarziat\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"summer_challenge_intarziat\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"summer_challenge_intarziat\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"summer_challenge_intarziat\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/summer_challenge_intarziat/clasament.\r\n\r\nAcest concurs este adresat celor care au fost ocupati in timpul concursului summer challenge si vor sa il simuleze.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"summer_challenge_intarziat\" score=\"1\")==',2993,'round: summer_challenge_intarziat',NULL,NULL),('runda/summer_challenge_intarziat/clasament','Clasament summer_challenge_intarziat','2009-07-25 11:59:36','2009-07-25 11:59:36','h1. Clasament ==roundparam(round_id=\"summer_challenge_intarziat\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer_challenge_intarziat\")==',2993,'round: summer_challenge_intarziat',NULL,NULL),('summer-challenge-2009/solutii/runda-1/joc11','summer-challenge-2009/solutii/runda-1/joc11','2009-07-25 13:26:16','2009-07-27 09:29:28','h2(#joc11). \'Joc11\':problema/joc11\r\n\r\nh3. Soluţie: $O(N^3^)$ Timp, $O(N^2^)$ Memorie\r\n\r\nSă notăm cu $D$ distanţa dintre locurile de start ale celor doi jucători. Cum ambii jucători au de parcurs aceeaşi distanţă, putem presupune, prin absurd, fără a restrânge generalitatea, că jucătorul A va efectua cel puţin $D + 1$ mutări. Rezultă că, deoarece jucătorul $B$ are un traseu de lungime $D$, jucătorul A va pierde, efectuând mai multe mutări. Deci, ambii jucători vor căuta să se deplaseze pe unul din drumurile de lungime $D$ dintre locurile de start.\r\n\r\nCum jucătorul A mută primul, acesta va câştiga dacă şi numai dacă jucătorul B nu poate ajunge în acelaşi loc cu jucătorul A în $D / 2$ mutări. Astfel, dacă $D$ este număr impar, A câştigă. În continuare, vom presupune că $D = 2d$.\r\n\r\nRezolvăm problema cu ajutorul metodei programării dinamice. Notăm cu $LA{~k~}$ şi $LB{~k~}$ listele de pătrate în care pot ajunge cei doi jucători în $k$ mutări iar adversarul său în $D - k$ mutări. Fie $T{~k,i,j~}$ $true$ dacă după $d - k$ mutări jucătorul A are strategie sigură de câştig iar cei doi participanţi se află pe poziţiile $LA{~d-k~}[i]$, respectiv $LB{~d-k~}[j]$. Dacă jucătorul B are strategie sigură de câştig atunci $T{~k,i,j~}$ este $false$. Observăm că listele $LA{~d~}$ şi $LB{~d~}$ sunt identice iar $T{~0,i,j~}$ este $true$ pentru toţi $i$ şi $j$ pentru care $LA{~d~}[i] &ne; LB{~d~}[j]$, condiţie echivalentă cu faptul că cei doi jucători nu sunt în acelaşi pătrat. Recurenţa se deduce din observaţia următoarele: „A are strategie sigură de câştig dacă poate muta într-o poziţie din care oriunde B ar muta acesta ar pierde”. Notăm cu $NextA{~k,i~}$ lista poziţiilor din $LA{~d-k+1~}$ în care jucătorul A poate muta din poziţia $LA{~d-k~}[i]$. Fie $NextB{~k,i~}$ lista definită în mod asemănător pentru jucătorul B. Observaţia precedentă se traduce prin: dacă există un $i\' din NextA{~k,i~}$, oricare ar fi $j\' din NextB{~k,j~}$, să avem $T{~k-1,i\',j\'~} = true$, atunci $T{~k,i,j~}$ este $true$. Altfel, $T{~k,i,j~}$ este $false$. Vom calcula valorile matricei $T$ pentru $k = 1,2,..,d$. În concluzie, jucătorul A are strategie sigură de câştig dacă $T{~d,1,1~}$ este $true$.\r\n\r\nSoluţia obţine punctajul maxim.\r\n\r\nh3. Soluţie: $O(N^3^logN)$ Timp, $O(N^3^)$ Memorie\r\n\r\nAceastă soluţie este similară cu cea precedentă, cu diferenţa că vom ţine un dicţionar, cu semnificaţia $T{~a{~x~}, a{~y~}, b{~x~}, b{~y~}~} = true$ dacă şi numai dacă jucătorul A are strategie sigură de câştig când acesta se află în poziţia $(a{~x~}, a{~y~})$ iar B în $(b{~x~}, b{~y~})$. Dicţionarul adaugă un factor de $logN$ la complexitatea soluţiei şi reţine $O(N^3^)$ memorie. \r\n\r\nSoluţia obţine 60 de puncte.\r\n\r\nh3. Soluţie: $O(N^3^)$ Timp, $O(N^4^)$ Memorie\r\n\r\nAceastă soluţie este cea precedentă cu excepţia faptului că foloseşte un tablou 4-dimensional pentru reţinerea stărilor. \r\n\r\nSoluţia obţine 40 de puncte.\r\n',3146,'public',NULL,NULL),('summer-challenge-2009/solutii/runda-1/posta','summer-challenge-2009/solutii/runda-1/posta','2009-07-25 13:26:50','2009-07-25 13:26:50','h2(#posta). \'Posta\':problema/posta\r\n\r\nPosta solution here.',2028,'public',NULL,NULL),('blog/problema-saptamanii-stream-solutie','Problema saptamanii - Stream (Solutie)','2009-07-27 01:33:38','2009-07-27 08:51:30','Am gasit problema in cartea \"Introduction to Algorithms: A Creative Approach\" de Udi Manber. Udi e VP of engineering la Google si daca stiti de suffix arrays, el a publicat o metoda eficienta pentru a determina LCP (longest common prefix) a doua sufixe. Cartea imi place mai mult decat Cormen-ul pentru ca partea de teorie e orientata mai mult spre intelegerea lucrurilor decat spre demonstratii matematice stufoase si pe langa asta fiecare capitol are foarte multe probleme interesante la sfarsit. Eu cred ca problemele sunt esentiale cand inveti un subiect tehnic, pentru ca intelegi bine ideile din un domeniu cand esti obligat sa le aplici in contexte diverse.\r\n\r\nPana sa vad cerinta din cartea respectiva credeam ca problema selectiei celor mai mici k numere din un stream se poate face doar in O(n log k) daca esti obligat sa folosesti O(k) memorie, dar citind-o mi-am dat seama ca nu e greu sa scoti o solutie in O(n) timp si O(k) spatiu. E o diferenta mare intre a sti ca o problema e rezolvabila sau nu :), de aceea munca de cercetare e foarte dura.\r\n\r\nCei ce au rezolvat corect problema sunt urmatorii: Stefan Istrate, Andrei Marius Teodorescu, Adrian Vladu, Marius Pungaru, Marius Buzea, Daniel Pasaila si Alexandru Mosoi.\r\n\r\nVa dau si solutia:\r\n_Pastram un sir A in care avem cele mai mici k numere din stream pana la momentul curent. Apoi la fiecare pas citim k noi elemente din stream in sirul B. Acum in sirul C punem elementele din ambele siruri si aplicam \'algoritmul de gasire a medianei\':http://en.wikipedia.org/wiki/Selection_algorithm#Partition-based_general_selection_algorithm care are complexitate O(k), vom pastra in A elementele din C mai mici sau egale cu mediana. Astfel obtinem un algoritm de complexitate O(n) timp si O(k) spatiu._',58,'protected',4053,NULL),('runda/simulare_upb_2009','simulare_upb_2009','2009-07-27 16:18:03','2009-07-27 16:18:03','h1. == roundparam(round_id=\"simulare_upb_2009\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"simulare_upb_2009\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"simulare_upb_2009\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"simulare_upb_2009\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/simulare_upb_2009/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"simulare_upb_2009\" score=\"1\")==',3333,'round: simulare_upb_2009',NULL,NULL),('runda/simulare_upb_2009/clasament','Clasament simulare_upb_2009','2009-07-27 16:18:03','2009-07-27 16:18:03','h1. Clasament ==roundparam(round_id=\"simulare_upb_2009\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"simulare_upb_2009\")==',3333,'round: simulare_upb_2009',NULL,NULL),('runda/concursul_lui_mati','concursul_lui_mati','2009-07-27 18:06:54','2009-07-27 18:06:54','h1. == roundparam(round_id=\"concursul_lui_mati\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"concursul_lui_mati\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"concursul_lui_mati\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"concursul_lui_mati\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/concursul_lui_mati/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"concursul_lui_mati\" score=\"1\")==',10565,'round: concursul_lui_mati',NULL,NULL),('runda/concursul_lui_mati/clasament','Clasament concursul_lui_mati','2009-07-27 18:06:54','2009-07-27 18:06:54','h1. Clasament ==roundparam(round_id=\"concursul_lui_mati\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"concursul_lui_mati\")==',10565,'round: concursul_lui_mati',NULL,NULL),('blog/problema-saptamanii-mediana-de-pe-disc','Problema saptamanii - Mediana pe disc','2009-07-27 23:27:17','2009-07-28 09:18:43','Cum numarul de rezolvari atat bune cat si rele a fost mare la problema anterioara, va mai zic o problema cu statistici de ordine pe care am auzit-o de la Mihai Patrascu.\r\n\r\n_Se dau n numere intregi scrise pe disc. Se cere sa se detemine mediana lor in timp O(n), citind fiecare numar de pe disc de O(1) ori si folosind O(sqrt(n)) memorie totala. Mediana unui sir de numere cu n elemente e elementul de pe pozitia n/2 din sirul rezultat in urma sortarii sirului initial._\r\n\r\nCa de obicei imi puteti trimite solutii pe adresa cosminn at gmail.com',58,'protected',4054,NULL),('runda/splunge5','splunge5','2009-07-28 06:01:35','2009-07-28 06:01:35','h1. == roundparam(round_id=\"splunge5\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"splunge5\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"splunge5\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"splunge5\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/splunge5/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"splunge5\" score=\"1\")==',4439,'round: splunge5',NULL,NULL),('runda/splunge5/clasament','Clasament splunge5','2009-07-28 06:01:35','2009-07-28 06:01:35','h1. Clasament ==roundparam(round_id=\"splunge5\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"splunge5\")==',4439,'round: splunge5',NULL,NULL),('summer-challenge-2009/solutii/runda-1/drepte3','summer-challenge-2009/solutii/runda-1/drepte3','2009-07-25 13:25:05','2009-07-28 09:07:29','h2(#drepte3). \'Drepte3\':problema/drepte3\r\n\r\nDacă avem un algoritm eficient de a găsi intersecţia cu $x$ minim pentru setul nostru de drepte atunci problema este rezolvată, pentru că putem aplica de $4$ ori acelaşi algoritm pentru a găsi valorile minime şi maxime pentru $x$ şi $y$.\r\n\r\nSortăm toate dreptele după ordinea lor pe y dacă ar fi intersectate de o dreaptă verticală cu $x$-ul foarte mic. Dacă avem două drepte $ax + by + c = 0$ şi $a{~1~}x + b{~1~}y{~1~} + c{~1~} = 0$, avem $y = (-ax - c) / b$ şi $y{~1~} = (-a{~1~}x - c{~1~}) / b{~1~}$. Dacă $x$ este foarte mic (tinde spre minus infinit) atunci $y > y{~1~}$ dacă $-a/b > -a{~1~}/b{~1~}$. După ce avem dreptele în ordine sortată, pentru a determina intersecţia dintre ele cu cel mai mic $x$, este de ajuns să ne uităm la intersecţiile între drepte consecutive în această ordine.\r\n\r\nAstfel, soluţia se reduce la o simplă sortare de pante şi un _for_ pe care facem intersecţii de drepte. Complexitatea soluţiei va fi $O(n log n)$.',3146,'public',NULL,NULL),('newsletter/summer-2009-2','Summer Challenge 2009, Runda 2','2009-07-28 18:25:15','2009-07-28 19:34:04','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎn curând va începe cea de a doua rundă a concursului \'Summer Challenge 2009\':summer-challenge-2009. Nu rata oportunitatea de te menţine în formă pe perioada vacanţei, când adversarii tăi cei mai aprigi sunt la mare ;).\r\n\r\nSummer Challenge este o ocazie bună de antrenament pentru tine, dar şi un ultim test pentru delegaţia României la \'Olimpiada Internaţională de Informatică 2009\':http://www.ioi2009.org (Bulgaria). Continuând seria de concursuri anunţate, ţi-am pregătit o nouă rundă în care să-ţi măsori forţele cu cei mai buni. De această dată, vei avea de rezolvat *4* probleme de dificultate variată şi vei putea beneficia de sistemul de detailed feedback. Astfel, vei putea şti încă din timpul concursului dacă soluţiile tale vor trece o parte din teste! :D\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Runda 2 se desfăşoară\r\n*Vineri, 31 Iulie 2009, orele 08^30^ - 13^30^*. |\r\n\r\nOrganizatorii celei de a doua runde Summer Challenge 2009 sunt:\r\n\r\n* \'Marius Stroe\':utilizator/marius\r\n* \'Paul - Dan Baltescu\':utilizator/pauldb\r\n* \'Andrei Grigorean\':utilizator/wefgef\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"summer-challenge-2009/runda-2\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. \'Rezultate Summer Challenge 2009, Runda 1\':summer-challenge-2009/clasament/runda-1\r\n\r\nAvând în faţă un set de subiecte foarte dificil, partipanţii care fac parte din delegaţia României la Olimpiada Internaţională s-au descurcat admirabil!\r\n\r\n# \'Cosmin Gheorghe\':utilizator/gcosmin - 300 pct\r\n# \'Bogdan Tătăroiu\':utilizator/bogdan2412 - 200 pct\r\n# \'Marius Drăguş\':utilizator/mariusdrg - 100 pct\r\n\r\nFelicitări atât lor, cât şi celorlalţi care s-au străduit să rezolve problemele de la \'Runda 1\':summer-challenge-2009/runda-1! Vă aşteptăm pe toţi cu punctaje mai mari la \'Runda 2\':summer-challenge-2009/runda-2!\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==',2028,'protected',NULL,NULL),('planificare/sedinta-20090727','Ședință 2009-07-27','2009-07-14 07:30:58','2009-08-01 20:23:51','h1. Şedinţă 2009-07-27\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *luni, 27 iulie* la ora *19:00* la *Hotel Marriott* _(sala \"Oradea\", etaj I)_\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"Marius\" type=\"tiny\")== (Nu se ştie, pentru că nu am tren de întoarcere...)\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== (Nu cred ca mai ajung, nu ma simt prea bine momentan)\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"greco\" type=\"tiny\")== (De la ora 20:00)\r\n* ==user(user=\"filipb\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţa anterioară\':planificare/sedinta-20090403| ==user(user=\"Prostu\" type=\"tiny\")== |\r\n|Chestiuni organizatorice (despre următorul Preşedinte Infoarena)| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n|OKRs| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Development| ==user(user=\"domino\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\nh3. OKRs\r\n\r\n* Notele pentru \'Q1 2009\':okr/20091 nu sunt finalizate.\r\n* Nu avem obiective şi nici rezultate pe Q2. Sărim peste?\r\n* Obiective pentru Q3 (doar 2 luni: august si septembrie)?\r\n\r\nh3. Development\r\n\r\n* Trebuie un nou sef\r\n* Ne blocam in \'review-uri\':http://reviewboard.infoarena.ro/dashboard/\r\n* Trebuie updatat \'roadmap-ul\':http://hackers.devnet.ro/roadmap\r\n\r\nh3. Misc\r\n\r\n* Silviu şi Cristi concretizează IAP 7 (1 şedinţă).\r\n* Ştefan şi Vali îşi vor diplomele de onoare de la Algoritmiada cu care apar în \'registrul de diplome\':registru-diplome. :)\r\n* Ştefan (19.40 RON) şi Vali (22.75 RON) trebuie să-şi deconteze biletele de tren de întoarcere de la finala Algoritmiada. Si Prostu are de decontat niste bilete de la Brasov (cred ca 43 RON, dus-intors) si nu sunt sigur daca si un bilet de 38.8 RON, cine a avut bilet intreg la intoarcere? Şi Marius mai are un bilet de decontat de la Braşov de 14 lei.\r\n* Silviu are de recuperat 17 RON (goodies de la o şedinţă).\r\n* Cristi are de recuperat nişte 60-something lei (scrie în notiţele unei şedinţe anterioare).\r\n* Card-uri noi\r\n* Noi membri in echipa?\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Algoritmiada Post War structurat pe capitole: probleme tehnice (Bogdan?), funding (Cristi), probleme (Wefgef), logistica (Wefgef), PR (Silviu).\r\n* Wefgef vorbeste cu Bogdan daca vrea sa scrie despre problemele tehnice de la Algorimiada.\r\n* Cristi il anunta pe Pasaila si il scoate de pe lista de consilieri.\r\n* Urmatorul presedinte se alege pana la 1 iunie. Mandatul incepe la 1 septembrie si dureaza 1 an.\r\n* Candidaturile se anunta pe mail pana la urmatoarea sedinta.\r\n* Procedura pe viitor se face in 3 sedinte: anuntarea candidaturilor, prezentarea programelor, vot.\r\n* Cristi baga IAP despre alegerea presedintelui.  %{color:red}(done)%\r\n* Vali si Prostu si-au anuntat candidaturile.\r\n* Marius il informeaza pe Paul despre ce s-a discutat la sedinta.\r\n* Wefgef vorbeste cu Cristina despre implicarea in Infoarena. %{color:red}(done - she\'s in for it)%\r\n* Bogdan e noul sef pe development.\r\n* Mircea si Cristi fac code review-uri.\r\n* Sedinta urmatoare: 17 august?\r\n* OKRs reportate\r\n\r\nh2. Notite\r\n\r\n* Vali stie unde sunt cupe.\r\n* S-au decontat biletele de tren de la Marius, Prostu (x 2), Wefgef, Stefan.\r\n* I s-au decontat 39.6 RON lui Cosmin (de la scrisori recomandate pentru 2%).',13,'protected',NULL,NULL),('summer-challenge-2009/solutii/runda-2/biti4','Soluție Biți4','2009-07-29 13:29:13','2009-08-01 10:40:53','h2(#biti4). \'Biti4\':problema/biti4\r\n\r\nSoluţia foloseşte metoda programării dinamice. Pentru început, considerăm un şir binar canonic ca fiind un şir _corect_ şi orice două poziţii consecutive care conţin cifre diferite o _schimbare de cifră_.\r\n\r\nVom determina succesiv cifrele şirului căutat. Definim $cw(a{~1~}a{~2~}..a{~m~})$ ca fiind numărul şirurilor corecte care au prefixul $a{~1~}a{~2~}..a{~m~}$. Prefixul de lungime $0$ îl vom nota cu $eps$. Astfel, modelul soluţiei este următorul:\r\n\r\n== code(cpp) |\r\nprefix := eps;\r\npentru i = 0, N - 1 execută:\r\n    dacă I <= cw(prefix0) atunci:\r\n        prefix := prefix0;\r\n    altfel:\r\n        I -= cw(prefix0);\r\n        prefix := prefix1;\r\n    sfârşit_dacă;\r\nsfârşit_pentru;\r\nreturn prefix;\r\n==\r\n\r\nIntroducem încă o notaţie: $cw(a{~1~}..a{~m~},b{~l~}..b{~1~})$, desemnând numărul şirurilor corecte care au prefixul $a{~1~}..a{~m~}$ şi sufixul $b{~l~}..b{~1~}$. Dacă $m + l > n$ atunci prefixul şi sufixul se suprapun. Astfel, fiecare şir corect care începe cu prefixul $a{~1~}..a{~m~}$ are una din următoarele forme:\r\n\r\n* ultimele $l$ cifre ale şirului $(0 &le; l &lt; m)$ citite de la sfârşit spre început sunt primele $l$ cifre ale şirului, $0$ este a $(l+1)$-a cifră a prefixului, iar $1$ a $(l+1)$-a cifră a sufixului.\r\n* ultimele $m$ cifre ale şirului citite în sens invers sunt primele $m$ cifre ale şirului.\r\n\r\nÎntrucât, când calculăm valoarea lui $cw(prefix)$ întotdeauna vom extinde prefixul cu cifra $0$, putem presupune că $a{~m~} = 0$. Aceste observaţii ne conduc la formula:\r\n<tex> cw(a_1a_2..a_m) = \\displaystyle \\sum_{l=0}^{m-1} ([a_{l+1} = 0] * cw(a_1..a_m,1a_l..a_1)) + cw(a_1..a_m,a_m..a_1) </tex>\r\n\r\nunde $[a{~l+1~} = 0]$ are valoarea $1$ dacă egalitatea are loc şi $0$ în caz contrar. Notăm cu $k{~m~}$ numărul schimbările de cifră în şirul $a{~1~}a{~2~}..a{~m~}$ iar cu $k{~l~}$ numărul schimbărilor de cifră în şirul $1a{~l~}..a{~1~}$.\r\n\r\nÎn continuare, observăm că $cw(a{~1~}..a{~m~},a{~m~}..a{~1~})$ este egal cu numărul _şirurilor corecte_ de lungime $n-2m+2$ care încep şi se termină cu cifra $a{~m~}$ şi care au cel mult $k-2k{~m~}$ schimbări de cifră. Pe de altă parte, $cw(a{~1~}..a{~m~},1a{~l~}..a{~1~})$ este egal cu numărul _tuturor şirurilor_ de lungime $n-(m-1)-l$ care încep cu cifra $a{~m~}$ şi se termină cu cifra $1$ şi care au cel mult $k-k{~m~}-k{~l~}$ schimbări de cifră. Pentru a determina aceste valori, calculăm două matrici $C$ şi $A$, $C$ contorizând şirurile corecte iar $A$ toate şirurile. Matricile sunt 4-dimensionale. <tex> C[n][k][b][e] </tex> reprezintă numărul şirurilor corecte de lungime $n$, cu cel mult $k$ schimbări de cifră, începând cu cifra $b$ şi terminându-se cu cifra $e$. <tex> A[n][k][b][e] </tex> se defineşte similar. Ne vom concentra asupra calculării elementelor matricii $C$. Matricea $A$ se calculează asemănător şi se lasă temă cititorului. Cazurile limită sunt:\r\n\r\n* <tex> C[n][k][b][e] = 0, \\forall n \\leq 0,  \\forall k < 0 </tex>;\r\n* <tex> C[1][k][b][e] = [b = e], \\forall k > 0 </tex>;\r\n* <tex> C[2][k][b][e] = [b \\le e], \\forall k > 0 </tex>;\r\n* <tex> C[n][0][b][e] = [b = e], \\forall n > 0 </tex>;\r\n\r\nDacă niciunul din cazurile limită nu are loc, atunci pentru $n &ge; 3$ şi $k &ge; 1$ avem:\r\n\r\n* <tex> b > e \\Rightarrow C[n][k][b][e] = 0 </tex>;\r\n* <tex> b < e \\Rightarrow C[n][k][b][e] = A[n][k][b][e] </tex>;\r\n* <tex> b = e \\Rightarrow C[n][k][b][e] = \\displaystyle \\sum_{b\'=0}^{1} \\sum_{e\'=0}^{1} C[n-2][k-[b \\neq b\']-[e \\neq e\']][b\'][e\'] </tex>.\r\n\r\nÎn final, dacă prefixul şi sufixul se suprapun ({$2m &gt; n$} sau {$m+l+1 &gt; n$}) atunci numărul şirurilor cu prefixul şi sufixul dorite este egal cu $0$ sau cu $1$, număr ce se poate determina direct.\r\n\r\nComplexitatea soluţiei este $O(n^2^)$.',3146,'public',NULL,NULL),('runda/clasa_a_5_a','clasa_a_5_a','2009-07-31 16:01:25','2009-07-31 16:01:25','h1. == roundparam(round_id=\"clasa_a_5_a\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"clasa_a_5_a\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"clasa_a_5_a\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"clasa_a_5_a\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/clasa_a_5_a/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"clasa_a_5_a\" score=\"1\")==',10565,'round: clasa_a_5_a',NULL,NULL),('runda/clasa_a_5_a/clasament','Clasament clasa_a_5_a','2009-07-31 16:01:25','2009-07-31 16:01:25','h1. Clasament ==roundparam(round_id=\"clasa_a_5_a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"clasa_a_5_a\")==',10565,'round: clasa_a_5_a',NULL,NULL),('summer-challenge-2009/solutii/runda-2/centru2','Soluție Centru2','2009-07-29 13:30:14','2009-08-01 10:41:20','h2(#centru2). \'Centru2\':problema/centru2\r\n\r\nConsiderăm intervalele noduri ale unui graf şi vom adăuga muchie între două noduri dacă intervalele corespunzatoare se suprapun. Pe acest graf, ne propunem sa determinăm cea mai mică lexicografic mulţime independentă maximală de vârfuri (maximum independence set sau $MIS$). \r\nPentru claritatea explicaţiei vom presupune ca nu există intervale complet incluse unul în celălalt. Algoritmul care tratează şi acest caz urmează aproximativ la fel paşii celui prezentat în continuare.\r\nSortăm intervalele după capătul din dreapta. Definim $D[i] = min{j > i | i si j nu sunt legate printr-o muchie}$. Vom construi o subrutina $MIS{i,j}$ pe care o vom utiliza ulterior şi care va determina cardinalul $MIS$-ului vârfurilor din graf curprinse între $i$ şi $j$, $i &le; j$. Se observă că $MIS{i,j} = 1 + max{k | D^k^[i] &le; j}$. Vom construi o matrice <tex>R[i][j] = D^{2^i}[j]</tex>, cu ajutorul căreia vom determina biţii rezultatului (asemănător cu modul de funcţionare al căutarii binare bazate pe ideea lui Mihai Pătraşcu prezentată în acest \'articol\':multe-smenuri-de-programare-in-cc-si-nu-numai). \r\nParcurgem nodurile în ordinea iniţială. Fie $i{~0~}$ primul nod. Fie $i, i+1, ..., j$ vecinii nodului $i{~0~}$. Aceştia pot fi determinaţi în $O(logN)$ folosind cautare binară. Nodul $i{~0~}$ poate face parte din soluţie dacă şi numai dacă $MIS{1, i-1} + 1 + MIS{j+1, N} = MIS{1, N}$. Această verificare poate fi făcută în complexitate $O(logN)$ folosind subrutina descrisă mai sus. Să presupunem în continuare că nodul $i{~0~}$ a trecut testul. Luăm apoi nodul $i{~1~}$, următorul în ordinea iniţială. Dacă $i{~1~}$ aparţine intervalului $[i, j]$, el nu aparţine soluţiei deoarece ar intra în conflict cu nodul ales precedent. Să presupunem că $i{~1~}$ apartine intervalului $[j+1, N]$ şi vecinii acestuia sunt $p, p+1, ..., q$, unde $j < p &le; q &le; N$. Trebuie din nou verificat dacă $MIS{j+1, N} = MIS{j+1, p-1} + 1 + MIS{q+1, N}$. Este intuitiv că acest algoritm conduce la obţinerea $MIS$-ului minim lexicografic.\r\nPentru a realiza operaţiile descrise mai sus in timp logaritmic este nevoie de un arbore de intervale cu ajutorul căruia sa verificăm dacă noile intervale se intersectează cu cele deja existente în soluţie şi un arbore binar echilibrat de căutare (\'treap\':treapuri, $AVL$ sau $set$ din STL) pentru a localiza intervalele pe care trebuie făcute verificările.',3146,'public',NULL,NULL),('summer-challenge-2009/solutii/runda-2/padurari','Soluție Pădurari','2009-07-29 13:29:45','2009-08-01 10:41:06','h2(#padurari). \'Padurari\':problema/padurari\r\n\r\nO primă observaţie aproape evidentă este că pădurarii vor alege mereu copaci consecutivi. Pornind de la această observaţie se poate construi un algoritm trivial bazat pe programare dinamică având complexitatea $O(N*K)$ şi care ar fi obţinut $20$ de puncte.\r\nPentru a ajunge la un algoritm eficient, o abordare posibilă este să modelăm problema ca un graf. Nodurile vor fi reprezentate de copaci, iar muchiile de posibilităţile de alegere ale pădurarilor. Astfel, va exista muchie între două noduri dacă şi numai dacă acestea sunt consecutive. Se observa uşor ca acest graf este unul bipartit. Problema se reduce acum la găsirea unui cuplaj de cardinal $K$ si cost minim în graful construit. Daca studiem modul de comportare al algoritmului pentru determinarea cuplajului de cost minim pe acest graf, se observă ca o muchie de întoarcere va fi folosită doar în cazul în care dorim să selectăm ulterior cele două muchii vecine. Folosind această observaţie, putem prevedea comportarea algoritmului în acest pas, înlocuind muchia de întoarcere ce ar trebui introdusă şi cele două muchii vecine, cu o nouă muchie ca in desenul următor:\r\n\r\np=. ! summer-challenge-2009/solutii/runda-2/padurari?padurari.png 55%!\r\n\r\nAcum se poate construi un nou algoritm care selectează la fiecare din cei $K$ pasi muchia minimă din graf si face transformările necesare. Inserările şi ştergerile muchiilor se pot face în timp logaritmic folosind un \'heap\':problema/heapuri, astfel algoritmul având complexitatea $O(K*logN)$.\r\nExistă un caz particular ce trebuie tratat cu atenţie. Când muchia aleasă este prima sau ultima din graf, abordarea de mai sus nu funcţionează. Totuşi, în acest caz este uşor de observat că va fi mereu de preferat să alegem această muchie în locul vecinei, deoarece are costul mai mic şi nu crează restricţii asupra altor muchii din graf.',3146,'public',NULL,NULL),('summer-challenge-2009/solutii/runda-2','Soluții Summer Challenge 2009, Runda 2','2009-07-29 12:38:32','2009-08-01 10:40:42','h1. Soluţii \'Summer Challenge 2009, Runda 2\':summer-challenge-2009/runda-2\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Biti4\':summer-challenge-2009/solutii/runda-2#biti4\r\n* \'Padurari\':summer-challenge-2009/solutii/runda-2#padurari\r\n* \'Centru2\':summer-challenge-2009/solutii/runda-2#centru2\r\n* \'Simpla\':summer-challenge-2009/solutii/runda-2#simpla\r\n\r\n==include(page=\"summer-challenge-2009/solutii/runda-2/biti4\")==\r\n\r\n==include(page=\"summer-challenge-2009/solutii/runda-2/padurari\")==\r\n\r\n==include(page=\"summer-challenge-2009/solutii/runda-2/centru2\")==\r\n\r\n==include(page=\"summer-challenge-2009/solutii/runda-2/simpla\")==',3146,'public',NULL,NULL),('newsletter/summer-2009-3','Summer Challenge 2009, Runda 3','2009-08-01 08:43:09','2009-08-01 12:41:02','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎn curând va începe \'ultima rundă\':summer-challenge-2009/runda-3 a concursului \'Summer Challenge 2009\':summer-challenge-2009. Răcoreşte-te la umbra monitorului rezolvând un nou set de probleme foarte interesante!\r\n\r\nSummer Challenge este o ocazie bună de antrenament pentru tine, dar şi un ultim test pentru delegaţia României la \'Olimpiada Internaţională de Informatică 2009\':http://www.ioi2009.org (Bulgaria). Continuând seria de concursuri anunţate, ţi-am pregătit o nouă rundă în care să-ţi măsori forţele cu cei mai buni. Vom promova în continuare modelul setului de probleme de la IOI format din $4$ probleme, una fiind de un nivel de dificultate mai scăzut, cu sistemul detailed feedback din nou disponibil. Astfel, vei putea concura în condiţii similare cu cele de la Olimpiada Internaţională de Informatică.\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Runda 3 se desfăşoară\r\n*Miecuri, 5 August 2009, orele 10^00^ - 15^00^*. |\r\n\r\nOrganizatorii celei de a treia runde Summer Challenge 2009 sunt:\r\n\r\n* \'Marius Stroe\':utilizator/marius\r\n* \'Paul - Dan Baltescu\':utilizator/pauldb\r\n* \'Stefan Istrate\':utilizator/stef2n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"summer-challenge-2009/runda-3\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. \'Rezultatele Summer Challenge 2009, în urma primelor două runde\':summer-challenge-2009/clasament\r\n\r\nRunda precendentă a avut nişte \'rezultate\':summer-challenge-2009/clasament/runda-2 mult mai echilibrate, dovedind că puteţi oricând face parte dintre cei mai buni. Iată primii 6 concurenţi:\r\n\r\n# \'Bogdan Tătăroiu\':utilizator/bogdan2412 - 230 pct\r\n# \'Cătălin Perţicaş\':utilizator/perticas_catalin - 205 pct\r\n# \'Vlad Gavrilă\':utilizator/gavrilavlad - 170 pct\r\n# \'Florin Pogocsan\':utilizator/binary_fire - 155 pct\r\n# \'Alexandru Cazacu\':utilizator/katakuna - 150 pct\r\n# \'Cosmin Gheorghe\':utilizator/gcosmin - 150 pct\r\n\r\nFelicitări atât lor, cât şi celorlalţi care s-au străduit să rezolve problemele de la primele doua runde! Mult succes şi vă aşteptăm să participaţi în număr cât mai mare la \'Runda 3\':summer-challenge-2009/runda-3!\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==',13,'protected',NULL,NULL),('runda/c_gimnaziu','c_gimnaziu','2009-08-01 10:32:57','2009-08-01 10:32:57','h1. == roundparam(round_id=\"c_gimnaziu\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"c_gimnaziu\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"c_gimnaziu\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"c_gimnaziu\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/c_gimnaziu/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"c_gimnaziu\" score=\"1\")==',3680,'round: c_gimnaziu',NULL,NULL),('runda/c_gimnaziu/clasament','Clasament c_gimnaziu','2009-08-01 10:32:57','2009-08-01 10:32:57','h1. Clasament ==roundparam(round_id=\"c_gimnaziu\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"c_gimnaziu\")==',3680,'round: c_gimnaziu',NULL,NULL),('runda/m','m','2009-08-01 16:53:54','2009-08-01 16:53:54','h1. == roundparam(round_id=\"m\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"m\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"m\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"m\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/m/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"m\" score=\"1\")==',10565,'round: m',NULL,NULL),('runda/m/clasament','Clasament m','2009-08-01 16:53:54','2009-08-01 16:53:54','h1. Clasament ==roundparam(round_id=\"m\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"m\")==',10565,'round: m',NULL,NULL),('propuneri/13-presedinte','IAP #13: Alegerea Președintelui infoarena','2009-08-01 19:33:33','2009-10-27 20:48:33','h1. IAP #13: Alegerea Preşedintelui infoarena\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2009-08-01                             |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"wickedman\")== şi echipa infoarena |\r\n|_. Stare     | *_APROBAT_*                     |\r\n\r\nh2(#abstract). Abstract\r\n\r\nProcedura de alegere a Preşedintelui şi a Vicepreşedintelui infoarena.\r\n\r\nh2(#motivatie). Motivaţie\r\n\r\nEste în spiritul infoarena ca pe măsură ce un membru se implică în proiectele infoarena, acesta să primească credit, responsabilitate şi autoritate ca să influenţeze direcţia în care se îndreaptă comunitatea noastră. În acest sens, Preşedintele are o influenţă importantă deoarece el este ales pe baza obiectivelor pe care le propune pentru următorul an de zile.\r\n\r\nAvem nevoie de o procedură care să funcţioneze în beneficiul comunităţii infoarena şi care să fie transparentă şi corectă.\r\n\r\nh2(#grafic). Grafic\r\n\r\n* Preşedintele se alege în fiecare an până la data de *1 Iunie*.\r\n* Mandatul durează un an şi începe de la data de *1 Septembrie*.\r\n\r\nh2(#alegeri). Organizarea alegerilor\r\n\r\nAlegerile se desfăşoară pe parcursul a 3 şedinţe, după cum urmează:\r\n\r\n* *Şedinţa 1*: Cei care doresc să candideze îşi declară intenţia.\r\n* *Şedinţa 2 (Adunare Generală)*: Fiecare candidat propune un set de obiective şi rezultate cheie pentru următorul an de zile, pe care acesta şi le asumă în cazul în care este ales Preşedinte. Obiectivele vor fi redactate astfel încât să poată fi studiate individual de către membrii Adunării Generale în afara şedinţei.\r\n* *Şedinţa 3 (Adunare Generală)*:\r\n** Se ţine o dezbatere în care fiecare candidat răspunde la întrebări din partea Adunării Generale.\r\n** Se alege Preşedintele prin vot secret. În caz de egalitate la număr de voturi, se dezbate şi apoi se votează din nou.\r\n** Un membru cu drept de vot se poate abţine dacă doreşte, lucru care se va consemna în notiţele şedinţei.\r\n\r\nPreşedintele ales desemnează 3 Vicepreşedinţi, câte unul pentru fiecare din rolurile: Content (arhivă, concursuri online, articole), Development, şi Algoritmiada. Preşedintele se ocupă şi de obiectivele legate de comunitate.\r\n\r\nOrganizarea alegerilor este responsabilitatea Preşedintelui în funcţie.\r\n\r\nAm selectat câteva articole relevante din \'statutul Asociaţiei infoarena\':asociatia-infoarena?statut.pdf:\r\n\r\nbq. _ART. 12._ Adunarea Generala reprezinta organul de conducere al AI. Adunarea Generala este compusa din\r\nmembrii fondatori si consilieri ai Asociatiei.\r\n\r\nbq. _ART. 13._ [...] Adunarea Generala este legal constituita în prezenta a jumatate plus unu dintre componentii ei.\r\n\r\nbq. _ART. 9, Alin. (5)_ [...] Unui membru consilier i se schimba automat statutul in consilier emerit daca, timp de 6 luni\r\nconsecutive, nu mai contribuie semnificativ la proiectele AI. Schimbarea statutului din consilier in\r\nconsilieri emerit se face de la sine, fara a fi necesara o decizie in Adunarea Generala.\r\n',13,'protected',4074,NULL),('summer-challenge-2009/runda-3','Summer Challenge 2009, Runda 3','2009-07-19 18:47:28','2009-08-04 18:23:58','h1. Summer Challenge 2009, Runda 3\r\n\r\n(htabs)* \'Detalii\':summer-challenge-2009\r\n* \'Runda 1\':summer-challenge-2009/runda-1\r\n* \'Runda 2\':summer-challenge-2009/runda-2\r\n*(active) \'Runda 3\':summer-challenge-2009/runda-3\r\n* \'Clasament\':summer-challenge-2009/clasament\r\n\r\nRunda se va desfasura Miercuri 5 august, la ora {*10^00^*} si va dura *5h*. Participantii vor avea de rezolvat 4 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"summer2009-runda3\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"summer2009-runda3\" score=\"1\")==\r\n\r\nSolutiile le gasiti \'aici\':summer-challenge-2009/solutii/runda-3\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 3\':summer-challenge-2009/clasament/runda-3\r\n\r\nh2. Organizatori\r\n\r\n* ==user(user=\"marius\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"devilkind\" type=\"tiny\")==',3146,'protected',NULL,NULL),('runda/summerchallenge2renasterea','summerchallenge2renasterea','2009-08-04 06:13:39','2009-08-04 06:13:39','h1. == roundparam(round_id=\"summerchallenge2renasterea\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"summerchallenge2renasterea\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"summerchallenge2renasterea\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"summerchallenge2renasterea\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/summerchallenge2renasterea/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"summerchallenge2renasterea\" score=\"1\")==',3219,'round: summerchallenge2renasterea',NULL,NULL),('runda/summerchallenge2renasterea/clasament','Clasament summerchallenge2renasterea','2009-08-04 06:13:39','2009-08-04 06:13:39','h1. Clasament ==roundparam(round_id=\"summerchallenge2renasterea\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summerchallenge2renasterea\")==',3219,'round: summerchallenge2renasterea',NULL,NULL),('summer-challenge-2009/solutii/runda-3','Soluții Summer Challenge 2009, Runda 3','2009-08-04 17:49:09','2009-08-06 18:52:13','h1. Soluţii \'Summer Challenge 2009, Runda 3\':summer-challenge-2009/runda-3\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Easy Choice\':summer-challenge-2009/solutii/runda-3#easychoice\r\n* \'Poligon3\':summer-challenge-2009/solutii/runda-3#poligon3\r\n* \'Copaci3\':summer-challenge-2009/solutii/runda-3#copaci3\r\n* \'Negustori\':summer-challenge-2009/solutii/runda-3#negustori\r\n\r\n==include(page=\"summer-challenge-2009/solutii/runda-3/easychoice\")==\r\n\r\n==include(page=\"summer-challenge-2009/solutii/runda-3/poligon3\")==\r\n\r\n==include(page=\"summer-challenge-2009/solutii/runda-3/copaci3\")==\r\n\r\n==include(page=\"summer-challenge-2009/solutii/runda-3/negustori\")==',1792,'public',NULL,NULL),('summer-challenge-2009/solutii/runda-3/easychoice','Soluție Easy Choice','2009-08-04 17:53:20','2009-08-06 18:54:13','h2(#easychoice). \'Easy choice\':problema/easychoice\r\n\r\nPentru rezolvarea problemei, vom sorta mai întâi crescător şirul înălţimilor. Se poate observa uşor că o divizie va fi un interval compact în şirul sortat, de lungime $C$. Ne propunem să alegem $R$ astfel de intervale care să nu se suprapună şi care să minimizeze dezechilibrul armatei.\r\n\r\nVom fixa printr-o căutare binară dezechilibrul $D$ şi vom verifica dacă se pot plasa cel puţin $R$ intervale disjuncte, fiecare cu dezechilibru cel mult $D$. Această verificare se poate realiza prin metoda programării dinamice, observând relaţia\r\n\r\n* $A[i] = max(A[i - 1], A[i - C] + 1)$, dacă $H[i] - H[i - C + 1] &le; D$\r\n* $A[i] = A[i - 1]$, altfel\r\n\r\nunde $A[i]$ = numărul maxim de divizii cu dezechilibru cel mult $D$ ce se pot crea folosind doar primii $i$ candidaţi, iar $H$ = şirul sortat al înălţimilor.\r\n\r\nComplexitatea rezolvării de mai sus este $O(N * log N + N * log H)$.',1792,'public',NULL,NULL),('summer-challenge-2009/solutii/runda-3/poligon3','Soluție Poligon 3','2009-08-04 17:53:50','2009-08-06 18:46:29','h2(#poligon3). \'Poligon3\':problema/poligon3\r\n\r\nVom fixa pe rând fiecare punct din cele $N$ date ca cel mai din stânga şi, în caz de egalitate, cel mai de sus punct ce poate fi pe poligon. După ce am fixat un anume punct de referinţă, ne mai interesează doar punctele cu absicsa strict mai mare sau cu abscisa mai mare sau egală şi ordonata strict mai mică ca a punctului fixat. Notăm punctul de referinţă cu $0$. Sortăm punctele rămase în funcţie de panta segmentului pe care îl formează cu punctul de referinţă. Vom parcurge punctele rămase în această ordine şi folosind metoda programării dinamice vom construi o matrice $C[i][j] =$ aria maximă a unui poligon care are ultimele două vârfuri în punctele $j$ şi $i$. Recurenţa este $C[i][j] = max{C[j][k] + Arie(0, i, j) | i, j, k păstrează forma convexă a poligonului şi triunghiul (0, i, j) nu conţine nici un alt punct în interior}$. Testul de păstrare a convexităţii este explicat pe larg în acest \"articol\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=geometry1. Verificarea ca triunghiul $0, i, j$ să nu conţină nici un alt punct se poate face in $O(1)$ cu ajutorul unei preprocesari, conducând la o complexitate totală de $O(N^4^)$. \r\nPentru a obţine complexitatea $O(N^3^)$, vom modifica semnificaţia matricii astfel: $C[i][j] = $ aria maxima a unui poligon ce are ultimul vârf în punctul $i$ şi penultimul vârf în unul dintre punctele dintre $1$ şi $j$. Având un punct $i$ fixat ca ultimul vârf al poligonului până în momentul respectiv, vom determina acele puncte $j$ pentru care triunghiul $(0, i, j)$ nu conţine nici un punct în interior. Punctul $i-1$ se află mereu printre aceste puncte $j$, deoarece este imposibil să existe vreun punct în triunghiul $(0, i-1, i)$ din cauza sortării iniţiale. Apoi vom determina restul punctelor $j$ cu o parcurgere în ordine inversă şi bazându-ne pe observaţia ca următorul punct $j$ pe care îl vom determina va verifica testul de păstrare al convexităţii relativ la punctul $i$ şi la ultimul punct de tip $j$ pe care l-am determinat pâna acum. Punem toate aceste puncte $j$ in multimea $s$ în ordinea sortării (sau în ordinea inversă determinării lor). Recurenţa devine $C[i][s{~k~}] = max{C[i][s{~k-1~}], C[s{~k~}][s{~k-1~}] + Arie(0, s{~k~}, i)}$.',1792,'public',NULL,NULL),('summer-challenge-2009/solutii/runda-3/negustori','Soluție Negustori','2009-08-04 17:52:12','2009-08-06 18:46:04','h2(#negustori). \'Negustori\':problema/negustori\r\n\r\nVom rezolva problema folosind metoda programării dinamice.\r\n\r\nPornim de la reprezentarea unei modalităţi de repartizare a tuturor celor $n$ negustori la cele $n$ locaţii de pe aleea comercială. O repartizare presupune să avem $0$ sau mai mulţi negustori străini plus cei locali repartizaţi la locaţia $1$, $0$ sau mai mulţi negustori străini plus cei locali la locaţia $2$, etc. Ulterior, negustorii se vor deplasa spre următoarele poziţii spre finalul aleii pentru a găsi un loc liber. Astfel, o stare constă în completarea cu negustori a locurilor $k, .., n$, rămânând $m$ locuri libere pentru completări ulterioare.\r\n\r\nFie <tex> dp[k][m] </tex> numărul de repartizări ale negustorilor pe locurile $k, .., n$, rămânând $m$ locuri libere. Vom face următoarele notaţii: $l[k]$ numărul de negustori locali care preferă locaţia $k$, $cl[k]$ numărul de negustori locali care preferă una din locaţiile între 1 şi $k (cl[k] = l[&#49;] + .. + l[k])$. Pentru a calcula <tex> dp[k][m] </tex>, ne rămâne să repartizăm negustori străini pe locul $k-1$ pe lângă cei $l[k-1]$ negustori locali. Această repartizare se realizează în limita locurilor disponibile. Numărul locurilor disponibile este egal cu $locuriLibere = m+1-l[k-1]$ (cele $m$ locuri libere la care adăugăm locul $k-1$ şi scădem pe cele ocupate de negustorii locali, $l[k-1]$). Numărul total de negustori străini rămaşi se obţine scăzând din numărul total de negustori pe cei repartizaţi pe locaţiile $k, .., n$ şi pe cei locali repartizaţi pe una din locaţiile preferate dintre $1, .., k-1$, adică $negustoriStraini = n-(n-k+1-m)-cl[k-1]$. Astfel, numărul total de negustori străini este $m+k-1-cl[k-1]$. Rezultă că vom alege $i$ negustori străini, fără a depăşi numărul locurilor libere, pe care îi vom repartiza pe poziţia $k-1$. Astfel, recurenţa este: <tex> dp[k][m] = \\displaystyle\\sum_{i=0}^{locuriLibere} \\dbinom{negustoriStraini}{locuriLibere-i} * dp[k-1][i] </tex>. Avem <tex> dp[1][i] = 1, \\forall i \\ge 0 </tex>. Rezultatul se găseşte în <tex> dp[n][0] </tex>.\r\n\r\nComplexitatea soluţiei: $O(n^3^)$.',1792,'public',NULL,NULL),('summer-challenge-2009/solutii/runda-3/copaci3','summer-challenge-2009/solutii/runda-3/copaci3','2009-08-04 17:56:49','2009-08-06 22:43:11','h2(#copaci3). \'Copaci3\':problema/copaci3\r\n\r\nO prima observatie pe care o putem face este faptul ca daca diferenta dintre primul si ultimul copac este mai mare decat $N * D$ atunci nu exista solutie. Pentru celelalte cazuri putem construi o dinamica $D[i][j]$ insemnand costul minim pentru a aduce copacul $i$ la inaltimea $j$, iar primi $i$ copaci formeaza o configuratie estetica. O implementare brute force a acestei solutii are complexitate $O(N * H^2^)$ putand fi redusa la $O(N * H)$ folosind un deque pentru a calcula recurenta. Aceasta solutie ar fi adus ~20 de puncte.\r\nPentru 100 de puncte se observa faptul ca singurele inaltimi care conteaza sunt inaltimile de forma $H[i] * X$ unde $X$ se afla in intervalul $[-N...N]$. Astfel ajungem la $N^2^$ inaltimi care conteaza, si astfel putem aduce solutia $O(N * H)$ la complexitatea $O(N^3^)$.',1792,'public',NULL,NULL),('runda/summer_contest_1','summer_contest_1','2009-08-10 09:51:27','2009-08-10 09:51:27','h1. == roundparam(round_id=\"summer_contest_1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"summer_contest_1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"summer_contest_1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"summer_contest_1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/summer_contest_1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"summer_contest_1\" score=\"1\")==',7148,'round: summer_contest_1',NULL,NULL),('runda/summer_contest_1/clasament','Clasament summer_contest_1','2009-08-10 09:51:27','2009-08-10 09:51:27','h1. Clasament ==roundparam(round_id=\"summer_contest_1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer_contest_1\")==',7148,'round: summer_contest_1',NULL,NULL),('runda/summer_contest_2','summer_contest_2','2009-08-10 09:56:23','2009-08-10 09:56:23','h1. == roundparam(round_id=\"summer_contest_2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"summer_contest_2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"summer_contest_2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"summer_contest_2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/summer_contest_2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"summer_contest_2\" score=\"1\")==',7148,'round: summer_contest_2',NULL,NULL),('runda/summer_contest_2/clasament','Clasament summer_contest_2','2009-08-10 09:56:23','2009-08-10 09:56:23','h1. Clasament ==roundparam(round_id=\"summer_contest_2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer_contest_2\")==',7148,'round: summer_contest_2',NULL,NULL),('runda/contest1','contest1','2009-08-10 13:08:53','2009-08-10 13:08:53','h1. == roundparam(round_id=\"contest1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"contest1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"contest1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"contest1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/contest1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"contest1\" score=\"1\")==',6245,'round: contest1',NULL,NULL),('runda/contest1/clasament','Clasament contest1','2009-08-10 13:08:53','2009-08-10 13:08:53','h1. Clasament ==roundparam(round_id=\"contest1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"contest1\")==',6245,'round: contest1',NULL,NULL),('runda/w2','w2','2009-08-12 12:07:38','2009-08-13 11:19:07','h1. %{color:red}_Runda w2_%       \r\n\r\nh4. %{color:green}**t r a i n i n g   m o d e**%\r\n\r\nh3. _In primul rand felicitari concurentilor din \"+runda w1+\":http://infoarena.ro/runda/w1 ._\r\n\r\nh3. _Aici se afla \"+clasamentul+\":http://infoarena.ro/runda/w1/clasament rundei trecute._\r\n\r\nh3. _Astazi am atasat alte trei probleme pentru a fi rezolvate._\r\n\r\nh3. _Sper ca tu sa participi si sa obtii punctajul maxim( %{color:purple}300% )._\r\n\r\nh3. _De asemenea punctajul poate fi vazut in timpul concursului imediat dupe ce trimiti sursa(c,cpp,pas)._\r\n\r\nh3. _Runda w2 va dura %{color:red}DOAR 3 ore% si nu 4 cu toate ca sunt 3 probleme._\r\n\r\nh1. %{color:red}Succes!%\r\n\r\n== roundregister(round_id=\"w2\") ==\r\n\r\nh3. Concursul incepe ==roundparam(round_id=\"w2\" param=\"start_time\" strong=\"true\")== \r\n\r\nh3. Dupa ce se termina runda w2, vei putea analiza \'*clasamentul*\':runda/w2/clasament.\r\n\r\nh1. %{color:red}Probleme%\r\n\r\nh3. _Aceasta lista va deveni vizibila doar in momentul inceperii concursului._\r\n\r\n==Tasks(round_id=\"w2\" score=\"1\")==\r\n\r\nh4. Concurs creat de ==user(user=\"zethpix\" type=\"tiny\")==',10498,'round: w2',4100,NULL),('runda/w1','w1','2009-08-12 11:40:04','2009-08-12 12:26:18','h1. **Concursul W.**\r\n\r\nh4.     +Concursul W.+ a fost creat in scopul antrenarii programatorilor.\r\n\r\nh4.     De asemenea ofera o sansa de a mari punctajul tau in clasamentul arhivei.\r\n\r\nh2. **Runda w1**\r\n\r\nh4.     \"+Runda w0+\":http://infoarena.ro/runda/w0 a trecut.\r\n\r\nh4.     Pentru aceasta runda am folosit problemele care nu au fost rezolvate randul trecut\r\n\r\nh4.     si inca una noua :) .\r\n\r\nh4.     Runda w1 este \"o a doua sansa\", cum s-ar zice.\r\n\r\nh4.     Daca nu ai ce face (si nu prea ai :P e \"Caldura Mare\") sau\r\n\r\nh4.     daca te plictisesti incearca concursul W.\r\n\r\nh4.     si nu vei regreta ;) \r\n\r\nh1. Succes! >:)\r\n\r\n\r\nh4. Runda w1 incepe ==roundparam(round_id=\"w1\" param=\"start_time\" strong=\"true\")==.\r\n\r\nh4. Ea dureaza ==roundparam(round_id=\"w1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nh4. Nu uita sa vezi unde te afli in \'*W.clasamentul*\':runda/w1/clasament.\r\n\r\nh1. **W.Problemele**\r\n\r\nProblemele vor aparea in momentul inceperii +concursului W.+\r\n\r\n==Tasks(round_id=\"w1\" score=\"1\")==',10498,'round: w1',NULL,NULL),('runda/pregatire_vianu','pregatire_vianu','2009-08-17 15:43:37','2009-08-17 15:43:37','h1. == roundparam(round_id=\"pregatire_vianu\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"pregatire_vianu\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"pregatire_vianu\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"pregatire_vianu\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/pregatire_vianu/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"pregatire_vianu\" score=\"1\")==',3904,'round: pregatire_vianu',NULL,NULL),('runda/w1/clasament','Clasament w1','2009-08-12 11:40:04','2009-08-12 14:02:36','h1. **+W.Clasamentul+**\r\n\r\nh2. +Felicitari tuturor W.concurentilor+ :))\r\n\r\n\r\n==Rankings(rounds = \"w1\")==\r\n\r\nh4. +App.+ Diseara e o ploaie de Perseide ;)\r\n\r\nh4. Mai multe informatii gasesti \"**aici**\":http://www.astro-info.ro/home/perseide2009.html\r\n\r\nh4. Uita-te si tu! Pare interesant :)\r\n\r\nh4. %{color:blue}+Sa nu uiti sa iti o dorinta ;)+%\r\n',10498,'round: w1',NULL,NULL),('runda/w2/clasament','Clasament w2','2009-08-12 12:07:38','2009-08-17 11:51:46','h1. %{color:red}W2-Clasament%\r\n\r\nh3. _Felicitari primilor clasati!!!_\r\n\r\nh3. **;)**\r\n\r\n==Rankings(rounds = \"w2\")==',10498,'round: w2',NULL,NULL),('runda/w3/clasament','Clasament w3','2009-08-13 16:38:14','2009-08-13 17:10:37','h1. Clasament ==roundparam(round_id=\"w3\" param=\"title\") ==\r\n\r\nh3. Felicitari tuturor participantilor :)\r\n\r\nh3. Si multumiri pentru participare ;)\r\n\r\n==Rankings(rounds = \"w3\")==',10498,'round: w3',NULL,NULL),('runda/w3','w3','2009-08-13 16:38:14','2009-08-13 18:00:44','h1. **Runda w3**\r\n\r\nh2. %{color:green} _**r a c e & w i n**_ %\r\n\r\n== roundregister(round_id=\"w3\") ==\r\n\r\nh3. Felicitari castigatorilor editiei \"w2\":http://infoarena.ro/runda/w2\r\n\r\nh3. In aceasta seara deschid ultimul concurs din seria %{color:green}**W**%\r\n\r\nh3. Cele 3 concursuri care s-au desfasurat pana acum au avut rezultate frumoase\r\n\r\nh3. Aici puteti accesa urmatoarele pagini :\r\n\r\nh4. Concurs \"w0\":http://infoarena.ro/runda/w0 --- Clasament \"w0\":http://infoarena.ro/runda/w0/clasament\r\n\r\nh4. Concurs \"w1\":http://infoarena.ro/runda/w1 --- Clasament \"w1\":http://infoarena.ro/runda/w1/clasament\r\n\r\nh4. Concurs \"w2\":http://infoarena.ro/runda/w2 --- Clasament \"w2\":http://infoarena.ro/runda/w2/clasament\r\n\r\nh4. %{color:green}Concurs \"w3\":http://infoarena.ro/runda/w3 --- Clasament \"w3\":http://infoarena.ro/runda/w3/clasament %\r\n\r\nh3. w2 incepe ==roundparam(round_id=\"w3\" param=\"start_time\" strong=\"true\")== \r\n\r\nh3. si dureaza ==roundparam(round_id=\"w3\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nh3. Runda w3 poate fi numita si %{color:green}\"Night&Day Challenge\"%\r\n\r\nh3. A fost creat pentru cei cu nervii de otel care doresc cu orice pret punctajul maxim %{color:red}600%\r\n\r\nh3. De data aceasta am propus spre rezolvare %{color:red}6% probleme\r\n\r\nh3. care sper sa nu va dea bataie de cap :)\r\n\r\nh1. %{color:red}Succes in ultima Wrunda ;)%\r\n\r\nh1. Fi si tu in \"W.clasament\":http://infoarena.ro/runda/w3/clasament\r\n\r\nh1. Probleme\r\n\r\nh3. Problemele vor fi vizibile cand incepe concursul.\r\n\r\n==Tasks(round_id=\"w3\" score=\"1\")==',10498,'round: w3',4101,NULL),('utilizator/gcosmin','Profil gcosmin','2006-11-24 21:00:42','2010-01-30 16:18:51','h2. Despre mine\r\n\r\n* Student anul I in cadrul Universitatii Bucuresti, sectia Matematica-Informatica.\r\n* Am inceput informatica in clasa a 5-a, mi-a placut si am incercat sa fac performanta in acest domeniu\r\n\r\nh2. Distinctii primite\r\n\r\n* Clasa a 9-a (2005-2006) : locul I la ONI; medalie de argint in Yakutia\r\n* Clasa a 10-a (2006-2007) : locul I la ONI; medalie de argint la IOI\r\n* Clasa a 11-a (2007-2008) : locul I la ONI; medalie de aur la CEOI; medalie de aur la IOI\r\n* Clasa a 12-a (2008-2009) : locul I la ONI; medalie de argint la CEOI; medalie de aur la IOI\r\n\r\nh2. Despre infoarena\r\n\r\n* Infoarena a fost pentru mine cel mai important site de pregatire. De aici am lucrat cele mai multe probleme si am invatat cele mai multe \"smenuri\". M-a ajutat enorm in clasa a 9-a sa cresc in cunostinte si inca este site-ul cu probleme preferat.\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"mariusdrg\" type=\"tiny\")==\r\n* ==user(user=\"greco\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"prostu\" type=\"tiny\")==\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n\r\n',2038,'protected',NULL,NULL),('utilizator/bogdan2412','Profil Bogdan2412','2006-11-24 20:59:24','2009-08-16 10:27:19','h2. Despre mine\r\n\r\nAm aflat prima oara de informatica in clasa a 5-a la CNITV si in clasa a 6-a m-am inscris la clubul de informatica Cygnus Computer, unde am invatat baza.\r\n\r\nAm inceput sa lucrez serios pe infoarena din clasa a 7-a, dupa ce am luat premiu la nationala. Infoarena a fost primul site pe care am inceput sa lucrez. Eram membru de pe vremea cand arhiva avea 50-60 de probleme. Imi placea mai mult cand arhiva avea mai putine probleme, apucai sa citesti majoritatea sa-ti alegi la care sa te gandesti, erau toate originale, pe idei de rezolvare foarte diferite. Ma chinuiam sa urc in clasamentul arhivei, stateam si zile intregi pe o problema. Mi-a fost destul de greu la inceput, cu fiecare problema invatam cate ceva nou. Era de la inceput o comunitate foarte tare, puneam intrebari pe forum si tot timpul se gasea cineva sa-mi raspunda.\r\n\r\nIn clasa a 9-a m-am mutat la \'ICHB\':http://www.ichb.ro/, unde am intalnit majoritatea oamenilor care au avut un cuvant de spus in pregatirea mea. In prezent sunt elev in clasa a 12-a.\r\n\r\nh2. Distinctii primite\r\n\r\n* 2007, Iulie - Argint la BOI, Chisinau, Moldova\r\n* 2007, August - Argint la IOI, Zagreb, Croatia\r\n* 2008, Iulie - Argint la CEOI, Dresden, Germania\r\n* 2008, August - Bronz la IOI, Cairo, Egipt\r\n* 2009, Iulie - Argint la CEOI, Targu Mures, Romania\r\n* 2009, August - Aur la IOI, Plovdiv, Bulgaria\r\n* 2005, 2007, 2008, 2009 - Locul I la ONI\r\n\r\nh2. Articole\r\n\r\n* \"Minimal Enclosing Circle\":minimal-enclosing-circle, infoarena\r\n\r\nh2. Profesori\r\n\r\n* ==User(user=\"azotlichid\" type=\"tiny\")== \r\n* ==User(user=\"mugurelionut\" type=\"tiny\")==\r\n* ==User(user=\"silviug\" type=\"tiny\")== \r\n* ==User(user=\"domino\" type=\"tiny\")== \r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n* ==User(user=\"Adriana_S\" type=\"tiny\")==\r\n* ==User(user=\"victorsb\" type=\"tiny\")==\r\n* ==User(user=\"alexthero\" type=\"tiny\")==\r\n* ==User(user=\"mariusdrg\" type=\"tiny\")==\r\n* ==User(user=\"Prostu\" type=\"tiny\")==\r\n* ==User(user=\"filipb\" type=\"tiny\")==\r\n* ==User(user=\"sims_gl\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"cimi\" type=\"tiny\")==\r\n* ==User(user=\"greco\" type=\"tiny\")==\r\n* ==User(user=\"slayer4u\" type=\"tiny\")==\r\n* ==User(user=\"CezarMocan\" type=\"tiny\")==\r\n* ==User(user=\"savim\" type=\"tiny\")==\r\n* ==User(user=\"raduzer\" type=\"tiny\")==\r\n* ==User(user=\"devilkind\" type=\"tiny\")==\r\n* ==User(user=\"gabitzish1\" type=\"tiny\")==\r\n',1490,'protected',NULL,NULL),('runda/redsnow_1/clasament','Clasament redsnow_1','2009-08-17 10:31:38','2009-08-17 11:31:08','h1. %{color:red}Red% **snow Challenge #1**\r\n\r\nh4. Aici sunt scrise doar numele Maestrilor pescuitului de probleme ;)\r\n\r\n==Rankings(rounds = \"redsnow_1\")==',10498,'round: redsnow_1',NULL,NULL),('runda/redsnow_1','redsnow_1','2009-08-17 10:31:38','2009-08-17 12:02:03','h1. %{color:red}Red% **snow**\r\n\r\nh3. %{color:red}Redsnow% %{color:red}challenge% %{color:red}este% %{color:red}un% %{color:red}concurs% %{color:red}nou.%\r\n\r\nh3. %{color:red}El% %{color:red}va% %{color:red}avea% %{color:red}4% %{color:red}runde% %{color:red}inclusiv% %{color:red}cea% %{color:red}finala.%\r\n\r\nh3. %{color:red}Sper% %{color:red}ca% %{color:red}acest% %{color:red}challenge% %{color:red}sa% %{color:red}te% %{color:red}ajute% %{color:red}si% %{color:red}sa%\r\n\r\nh3. %{color:red}iti% %{color:red}aduca% %{color:red}cunostinte% %{color:red}noi.%\r\n\r\nh1. %{color:red}**Runda 1**%\r\n\r\n== roundregister(round_id=\"redsnow_1\") ==\r\n\r\nh4. Mr.Smith este un programator excelent.Deoarece zilele trecute a fost chinuit de construirea unui program a decis ca aztazi %{color:red}**17 august 2009**% sa isi ia o zi libera de la lucru.\r\n\r\nh4. Hobby-ul sau este pescuitul si de aceea el se duce la Balta de Aur sa pescuiasca.El ajunge acolo la ora %{color:red}**14:30**% .\r\n\r\nh4. Aici se intalneste cu prietenul sau Mr.Fisher, care este de asmenea cel care l-a invatat sa pescuiasca.\r\n\r\nh4. Mr.Fisher il provoaca pe Mr.Smith sa gaseasca in balta %{color:red}**3**% pesti de aur si 10 pesti de argint.\r\n\r\nh4. Mr.Smith nu se pricepe sa prinda pestii de aur ci pe aceia de argint.El se hotaraste sa te cheme pe %{color:red}**tine**% sa il ajuti.\r\n\r\nh4. Totodata Mr.Smith iti da recompensa pentru fiecare peste prins %{color:red}**(100 de verzisori)**% .\r\n\r\nh4. Daca tu doresti recompensa nu mai sta pe ganduri si ajuta-l pe Smith si gaseste cei 3 pestisori in timp de %{color:red}**4**% ore.\r\n\r\nh4. Fii unul din %{color:red}maestrii pescuitului de probleme% in \'*Clasamentul din oras*\':runda/redsnow_1/clasament.\r\n\r\nh1. **S u %{color:red}c% c e s**\r\n\r\nh1. **Probleme**\r\n\r\nh4. Aceasta lista va deveni vizibila doar cand Mr.Smith ajunge la Balta de aur.\r\n\r\nh4. \r\n\r\n==Tasks(round_id=\"redsnow_1\" score=\"1\")==',10498,'round: redsnow_1',4106,NULL),('runda/pregatire_vianu/clasament','Clasament pregatire_vianu','2009-08-17 15:43:37','2009-08-17 15:43:37','h1. Clasament ==roundparam(round_id=\"pregatire_vianu\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pregatire_vianu\")==',3904,'round: pregatire_vianu',NULL,NULL),('runda/redsnow_2/clasament','Clasament redsnow_2','2009-08-17 16:26:25','2009-08-17 16:26:25','h1. Clasament ==roundparam(round_id=\"redsnow_2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"redsnow_2\")==',10498,'round: redsnow_2',NULL,NULL),('runda/redsnow_2','redsnow_2','2009-08-17 16:26:25','2009-08-18 12:25:56','h1. %{color:red}**Red**% **Snow**\r\n\r\n== roundregister(round_id=\"redsnow_2\") ==\r\n\r\nh4. Felicitari participantilor \"rundei 1\":http://infoarena.ro/runda/redsnow_1 a concursului.\r\n\r\nh4. \"Aici\":http://infoarena.ro/runda/redsnow_1/clasament se gaseste clasamentul rundei.\r\n\r\nh4. In runda aceasta am propus 4 probleme si nu 3, iar durata va fi de 6 ore ;)\r\n\r\nh1. %{color:red}**Runda 2**%\r\n\r\nh4. Astronautul %{color:red}Jimi% se pregateste sa dea un interviu la NASA pentru a fi ales sa mearga cu nava Apollo %{color:red}2009% pe luna, satelitul natural al pamantului.\r\n\r\nh4. El este programat sa mearga pe data de %{color:red}18 august% la ora %{color:red}10:00 a.m.%\r\n\r\nh4. Comisia il supune pe Jimi la %{color:red}4 teste(probleme)% care vor dura %{color:red}6 ore% in total.\r\n\r\nh4. Dupa ce primeste testele el ramane confuz.\r\n\r\nh4. El nu reuseste sa faca testele 100% perfect.\r\n\r\nh4. De aceea el iti cere tie ajutor.\r\n\r\nh4. Daca tu reusesti sa iei %{color:red}100 de puncte% pe fiecare test Jimi te va lua cu el pe luna.\r\n\r\nh4. Daca nu reusesti vei primi un %{color:red}banut magic% pentru fiecare test incercat.\r\n\r\nh4. Jimi a pregatit un \'*clasament*\':runda/redsnow_2/clasament cu cei care l-au ajutat.\r\n\r\n!runda/redsnow_2?nasa_logo.jpg!\r\n\r\nh1. **S u c c e %{color:red}s% !**\r\n\r\nh1. %{color:red}**Teste NASA**%\r\n\r\nh4. Testele vor fi disponibile cand Jimi se prezinta la interviu.\r\n\r\n==Tasks(round_id=\"redsnow_2\" score=\"1\")==',10498,'round: redsnow_2',4107,NULL),('utilizator/ste_fanus','Profil ste_fanus','2006-11-24 20:56:12','2009-08-18 11:26:19','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\nAm lucrat inca de la inceputul facultatii ca Software Engineer la Krogos Software Development apoi la BitDefender SRL iar in prezent sunt Senior Software Engineer la Arnia Software.\r\n\r\nh2. Distinctii primite\r\n\r\n* Membru in comisia pregatirii lotului national de informatica 2005\r\n* Participare la etapa pe SE Europei a concursului ACM 2006 si 2007\r\n* Locul 8 la ONI 2003\r\n* Calificare în lotul lărgit de informatică 2003\r\n\r\nh2. Studii\r\n\r\n* Academia de Studii Economice - Facultatea de Cibernetica, Statistica si Informatica Economica (specializarea Informatica economica)\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n\r\n',21,'protected',NULL,NULL),('runda/redsnow_3/clasament','Clasament redsnow_3','2009-08-18 16:12:22','2009-08-19 04:50:34','h1. %{color:red}**Pergamentul de foc si viata al lumii**%\r\n\r\nh4. Aici sunt trecuti toti eroii care au luptat pentru salvarea lumii.\r\n\r\nh4.  \r\n\r\n==Rankings(rounds = \"redsnow_3\")==',10498,'round: redsnow_3',NULL,NULL),('runda/redsnow_3','redsnow_3','2009-08-18 16:12:22','2009-08-19 05:09:52','== roundregister(round_id=\"redsnow_3\") ==\r\n\r\nh1. %{color:red}**Red**% **Snow**\r\n\r\nh4. Felicitari tuturor participantilor a concursului %{color:red}**RedSnow**% de pana acum.\r\n\r\nh4. Acest concurs a fost creat pentru antrenament si rezolvare a problemelor contra timp.\r\n\r\nh4. Aici am alcatuit un tabel cu rundele trecute:\r\n\r\nh4. %{color:red}Runda 3% incepe la ora %{color:red}10:00 a.m.% si dureaza %{color:red}5 ore.%\r\n\r\nh4. Vor fi propuse %{color:red}3% probleme spre rezolvare.\r\n\r\n|_. %{color:red}**Runda**% |_. %{color:red}**Clasament**% |\r\n|\"**RedSnow 1**\":http://infoarena.ro/runda/redsnow_1|\"**Ranks 1**\":http://infoarena.ro/runda/redsnow_1/clasament|\r\n|\"**RedSnow 2**\":http://infoarena.ro/runda/redsnow_2|\"**Ranks 2**\":http://infoarena.ro/runda/redsnow_2/clasament|\r\n\r\nh1. **S** %{color:red}**u**% **c c e s**\r\n\r\nh1. %{color:red}**Runda 3**%\r\n\r\nh5. %{color:green}_N e w W a r c r a f t S t o r y_%\r\n\r\nh4. Pacea a fost instaurata in lume. Razboaiele dintre orci si oameni au incetat de mult. Invazia strigoilor a esuat, iar elfii isi traiesc vesnicia in liniste.\r\n\r\nh4. Totusi si in aceste timpuri fericite forta raului nu a disparut. %{color:green}Arthas, cavalerul mortii,% a fost alungat in tinutul inghetului. Chinul lui era vesnic, iar el cauta o cale de scapare.\r\n\r\nh4. Intre timp %{color:green}paladinul Granis, aducatorul de lumina,% descopera impreuna cu un grup de arcasi elfi si cavaleri de-ai oamenilor un nou tinut nelocuit.\r\n\r\nh4. Ei l-au numit tinutul %{color:green}Ukondor.% Oamenii s-au colonizat aici si au trait multi ani trai bun. Pamanturile erau fertile si vremea era perfecta.\r\n\r\nh4. Lucrurile astea s-au intamplat pe la anul 253b din calendarul elfilor, 721 calendarul strigoilor si 101 calendarul oamenilor.\r\n\r\nh4. Timp de 721 de atunci lumea a evoluat. Rasa orcilor se crede ca a disparut de tot. Se spune ca lucru acesta era inevitabil.\r\n\r\nh4. Oamenii aveau pe elfi langa ei si de aceea comportamentul lor autodistructiv era din ce in ce mai redus. Ei erau cea mai numeroasa rasa.\r\n\r\nh4. Strigoii traiau alaturi de oameni in umbra si nevazuti de nimeni. Ei se aflau in anul 0 care era anul reintoarcerii lor in lumea vazuta.\r\n\r\nh4. Ei erau condusi de %{color:green}Morbent, cel de gheata,% care punea totul in randuiala pentru revenirea lor. Strigoii il asteptau pe %{color:green}Arthas% sa scape din tinutul inghetat.\r\n\r\nh4. Elfii isi construiau armata, deoarece zvonurile despre strigoi ii speriau. Ei isi protejau Lumina Lunii cea care ii tinea in viata. Fara ea ei deveneau slugi ale strigoilor.\r\n\r\nh4. In tinutul de frig, %{color:green}Arthas% descopera o colonie de strigoi dintre cei mai rai. Ei erau elfi, orci si oameni care si-au tradat viata.\r\n\r\nh4. Acestia il recunosc ca stapan si ii spun ca totul era pregatit. Anul 0 sosea. Ei i-au dat un %{color:green}Dragon de gheata% drept cadou pentru reintoarecerea lui in lumea celor vii.\r\n\r\nh4. In acest timp oamenii erau in sarbatoare. Un nou rege era ales. %{color:green}Hale, vrajitorul focului,% era acela.\r\n\r\nh4. Elfii sufereau de o boala ciudata la care nu au gasit leac. Din ce in ce mai multi mureau. Ei au verificat daca Lumina Lunii era unde trebuie. Totul era in regula.\r\n\r\nh4. %{color:green}Varedis, vanatorul de demoni,% era si el pe moarte. Dar el era singurul care vedea ca strigoii se pregateau de lupta. Elfii l-au considerat nebun cand le-a spus ca %{color:green}Arthas% scapa si l-au aruncat langa fratele sau %{color:green}Illidan.%\r\n\r\nh4. La %{color:red}**ora 10:00 a.m**%(masura de timp a oamenilor)  anul 0 sosea la strigoi. In toate tinuturile locuite de oameni a inceput un haos total.\r\n\r\nh4. Strigoii au fost invocati pretutindeni. Lumina elfilor a fost furata. Vrajile malefice ale strigoilor au provocat boli mortale tuturor raselor.\r\n\r\nh4. %{color:green}Arthas% soseste cu intreaga lui armata si in cateva clipe distruge tot ce era construit de oameni. El invoca un %{color:green}Infernal% care captureaza regele oamenilor si il \r\nduce in tinutul de gheata.\r\n\r\nh4. Elfii n-au incotro si readuc in lume pe %{color:green}Illidan% si %{color:green}Varedis% sa ii ajute. Ei aduna toate fortele ramase ale oamenilor si elfilor si se duc sa caute cele %{color:red}**3 chei**% ale lumii.\r\n\r\nh4. Deoarece %{color:green}Hale, vrajitorul de foc,% era singurul descifrator ale cheilor, %{color:green}Illidan% cere ajutor %{color:green}tie, ucenicul lui Hale,% sa ii ajuti sa descopere cele %{color:red}**100 de semne**% sacre ale fiecarei chei.\r\n\r\nh4. Fara Lumina Lunii rasa elfilor e pe cale de disparitie. Tu ai timp %{color:red}**5 ore**% pana cand toti elfii mor.Ajuta-i!\r\n\r\nh4. De aceea salvarea lumii depinde de tine. Daca reusesti sa descifrezi cheile, %{color:green}Arthas% si intreaga lui imparatie de strigoi va disparea pentru totdeauna de pe Pamant.\r\n\r\nh4. Eroii aceste lupte sunt scrisii in \"Pergamentul de foc si viata al lumii\":http://infoarena.ro/runda/redsnow_3/clasament\r\n\r\nh1. %{color:red}**Cele trei chei ale lumii**%\r\n\r\nh4.  \r\n\r\nh4.  \r\n\r\n==Tasks(round_id=\"redsnow_3\" score=\"1\")==\r\n\r\nh4.  \r\n\r\nh4.  \r\n\r\n|_. %{color:red}**Erou**% |_. %{color:red}**Imagine**% |_. %{color:red}**Rasa**% |\r\n|**Hale, noul rege**|!runda/redsnow_3?bloodmage.gif!|**human**|\r\n|**Granis, paladinul**|!runda/redsnow_3?paladin.gif!|**human**|\r\n|**Varedis, vanatorul de demoni**|!runda/redsnow_3?demonhunter.gif!|**night elf**|\r\n|**Arthas, cavalerul mortii**|!runda/redsnow_3?deathknight.gif!|**undead**|\r\n|**Morbent, cel de gheata**|!runda/redsnow_3?lich.gif!|**undead**|\r\n|**Dragonul de gheata**|!runda/redsnow_3?frostwyrm.gif!|**undead unit**|\r\n|**Infernal**|!runda/redsnow_3?infernal.gif!|**summonable**|',10498,'round: redsnow_3',4110,NULL),('runda/redsnow_4','redsnow_4','2009-08-20 11:39:52','2009-08-20 11:58:43','h1. %{color:red}**Red**% **Snow**\r\n\r\nConcursul RedSnow a ajuns la final.\r\nAceasta este ultima runda.\r\nSper ca acest concurs v-a adus mai multa experienta si cateva puncte in plus.\r\nMultumes pentru participare.\r\n\r\nh1. **S u c c** %{color:red}**e**% **s**\r\n\r\n== roundregister(round_id=\"redsnow_4\") ==\r\n\r\nh1. %{color:red}**Runda Finala**% **(4)**\r\n\r\nConcursul incepe ==roundparam(round_id=\"redsnow_4\" param=\"start_time\" strong=\"true\")==.\r\nRunda dureaza ==roundparam(round_id=\"redsnow_4\" param=\"duration\" strong=\"true\")== ore.\r\nDe data aceasta am propus doar 2 probleme.\r\nSper sa reusesti sa iei punctajul maxim.\r\n\'*Ranks*\':runda/redsnow_4/clasament.\r\n\r\nh1. **Probleme**\r\n\r\n==Tasks(round_id=\"redsnow_4\" score=\"1\")==',10498,'round: redsnow_4',4114,NULL),('runda/redsnow_4/clasament','Clasament redsnow_4','2009-08-20 11:39:52','2009-08-20 11:49:15','h1. Ranks\r\n\r\nFelicitari tuturor concurentilor.\r\nSucces in continuare.\r\n\r\n==Rankings(rounds = \"redsnow_4\")==',10498,'round: redsnow_4',NULL,NULL),('runda/summer_camp_6','summer_camp_6','2009-08-21 07:14:57','2009-08-21 07:14:57','h1. == roundparam(round_id=\"summer_camp_6\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"summer_camp_6\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"summer_camp_6\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"summer_camp_6\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/summer_camp_6/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"summer_camp_6\" score=\"1\")==',6957,'round: summer_camp_6',NULL,NULL),('runda/summer_camp_6/clasament','Clasament summer_camp_6','2009-08-21 07:14:57','2009-08-21 07:14:57','h1. Clasament ==roundparam(round_id=\"summer_camp_6\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer_camp_6\")==',6957,'round: summer_camp_6',NULL,NULL),('runda/onisim2009-7/clasament','Clasament onisim2009-7','2009-08-23 10:13:27','2009-08-23 10:32:43','h1. %{color:blue}ONiSiM% 2009 clasa a VII-a\r\n\r\nh1. Felicitari !\r\n\r\n==Rankings(rounds = \"onisim2009-7\")==',10498,'round: onisim2009-7',4117,NULL),('runda/just_4_me','just_4_me','2009-08-23 10:18:32','2009-08-23 10:18:32','h1. == roundparam(round_id=\"just_4_me\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"just_4_me\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"just_4_me\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"just_4_me\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/just_4_me/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"just_4_me\" score=\"1\")==',6958,'round: just_4_me',NULL,NULL),('runda/just_4_me/clasament','Clasament just_4_me','2009-08-23 10:18:32','2009-08-23 10:18:32','h1. Clasament ==roundparam(round_id=\"just_4_me\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"just_4_me\")==',6958,'round: just_4_me',NULL,NULL),('codeblocks','Scurt ghid pentru folosirea mediului Code::Blocks','2009-08-23 15:23:46','2009-08-23 16:50:03','h1. Scurt ghid pentru folosirea mediului Code::Blocks\r\n\r\nh2. Configurarea tastaturii\r\n\r\nUna dintre facilitatile care ne pot simplifica mult activitatea in Code::Blocks este posibilitea de configurare a tastaturii, incat sa realizam simplu actiunile cele mai frecvente.\r\nAstfel, daca suntem obisnuiti cu Visual Studio sau Borland C++, putem sa avem la dispozitie in Code::Blocks combinatiile de taste preferate.\r\nVom vedea, de exemplu, cum putem sa stabilim o scurtatura pentru a deschide usor fereastra de editare a expresiilor care vor fi urmarite la depanere.\r\n\r\n# Alegem: Settings -> Editor ...\r\n# In lista din stanga alegem **Keyboard shortcuts**.\r\n# In zona **Commands** deschidem **Debug** si alegem **Edit watches...**\r\n# In casuta **New shortcut** tastam F10 (desigur, putem tasta orice dorim).\r\n# Click pe **Add** si pe **OK**.\r\n\r\n!codeblocks?KeyboardShortcuts.png!\r\n\r\nFolosind aceasta fereastra am configurat pentru exemplificare cateva scurtaturi, asemanatoare cu cele din Borland C++:\r\n\r\n| F2 | salvarea sursei din fereastra curenta |\r\n| Ctrl+Y | stergerea liniei curente |\r\n| F12 | Comment |\r\n| F11 | Uncomment |\r\n| F9 | Build |\r\n| Ctrl+F9 | Run |\r\n| Ctrl+F8 | setarea/eliminarea unui breakpoint |\r\n| Alt+W | Watches |\r\n| Ctrl+F2 | Stop debugger |\r\n\r\nDaca deschidem un meniu pentru care am stabilit scurtaturi, vom observa ca langa numele comenzilor apar noile combinatii de taste.\r\n\r\n!codeblocks?Keys.png!\r\n\r\nCombinatiile de taste stabilite asa cum am aratat mai sus vor fi salvate automat in fisierul\r\nC:\\Documents and Settings\\ **[user curent]** \\Application Data\\codeblocks\\cbKeyBinder10.ini\r\n(Adaptati calea pentru instarea de Windows pe care o aveti.)\r\n\r\nAm atasat \"aici\":cbKeyBinder10 fisierul care contine scurtarile descrise in tabel, pe care il puteti pune in locul fisierului creat implicit la instalarea Code::Blocks.\r\n[cbKeyBinder10]http://infoarena.ro/codeblocks?action=download&file=cbKeyBinder10.ini&safe_only=false',3689,'public',NULL,NULL),('runda/splunge6/clasament','Clasament splunge6','2009-08-24 18:18:48','2009-08-24 18:18:48','h1. Clasament ==roundparam(round_id=\"splunge6\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"splunge6\")==',4439,'round: splunge6',NULL,NULL),('utilizator/floringh06','Profil floringh06','2007-01-14 12:13:14','2009-08-30 13:31:42','h2. Despre mine\r\n\r\n* 2005 - 2009 - Colegiul National \"Samuel von Brukenthal\" - Sibiu\r\n* 2009 - prezent - \"Friedrich Alexander\" University - Nuernberg\r\n* Infoarena a fost si este principala mea sursa de pregatire, m-a invatat ce inseamna un concurs de informatica si o pregatire temeinica.\r\n\r\n*Profesori indrumatori:*\r\n      Ciurea Stelian \r\n\r\n*Oameni de baza pe infoarena:*\r\n      Florian MOGA :)\r\n\r\n!utilizator/floringh06?poza.jpg  500x500!. \r\nVisul meu...\r\n\r\nh2. Distinctii primite\r\n\r\n* Locul 1 OJI 2008\r\n* Locul 2 OJI 2009\r\n* Calificare ONI 2006, ONM 2006, ONM 2007, ONF 2004, ONM 2008...\r\n* Participare ONF 2006, ONI 2007, ONI 2008, ONI 2009\r\n* Participare BARAJ la ONI 2007, ONI 2008, ONI 2009\r\n* Participare ACSL 2008 - Maryland\r\n  Locul 6 la echipe si locul 1 la Individual Continental Division\r\n* Mentiune si medalie de argint ONI 2008 Ploiesti\r\n* Calificare in Finala .Campion 2009 (Locul 7)\r\n* Premiul 2 - \"Micul Programator\" Targu Mures 2008\r\n* Coautor - \"Variante Bacalaureat - Informatica Intensiv 2008\"\r\n* Propunator probleme locala Cl. 9 - Judetul Brasov 2007 - 2008\r\n* Premiul special la Finala Campion 2009 - Relatia Euler :)\r\n\r\n**Prieteni pe infoarena**\r\n==user(user=\"moga_florian\" type=\"tiny\")==\r\n==user(user=\"andrei_info\" type=\"tiny\")== \r\n==user(user=\"luana_0105\" type=\"tiny\")== \r\n==user(user=\"pepelea_flaviu\" type=\"tiny\")==\r\n==user(user=\"vlad_popa\" type=\"tiny\")==\r\n==user(user=\"StTwister\" type=\"tiny\")==\r\n==user(user=\"mishu91\" type=\"tiny\")==\r\n==user(user=\"Robybrasov\" type=\"tiny\")==\r\n==user(user=\"cotofana\" type=\"tiny\")==\r\n==user(user=\"alexandru.mosoi\" type=\"tiny\")==\r\n==user(user=\"mugurelionut\" type=\"tiny\")==\r\n==user(user=\"wefgef\" type=\"tiny\")==\r\n==user(user=\"victorsb\" type=\"tiny\")==\r\n==user(user=\"andreitheo87\" type=\"tiny\")==\r\n==user(user=\"Vman\" type=\"tiny\")==\r\n==user(user=\"mariusdrg\" type=\"tiny\")==\r\n==user(user=\"bogdan2412\" type=\"tiny\")==\r\n',5653,'public',NULL,NULL),('runda/cena','cena','2009-08-25 11:45:26','2009-08-25 11:45:26','h1. == roundparam(round_id=\"cena\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cena\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cena\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cena\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cena/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cena\" score=\"1\")==',10155,'round: cena',NULL,NULL),('runda/cena/clasament','Clasament cena','2009-08-25 11:45:26','2009-08-25 11:45:26','h1. Clasament ==roundparam(round_id=\"cena\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"cena\")==',10155,'round: cena',NULL,NULL),('schimbare-borland/alternativa/mingw','schimbare-borland/alternativa/mingw','2008-10-29 18:07:29','2009-08-28 14:39:49','h2(#mingw). \'Mingw\':http://www.mingw.org/\r\n\r\nMinGW (Minimalist Gnu for Windows) este o colectia gratuita de librarii imbogatind GNU Compliler Collection cu fisiere si librarii specifice Windows. Scopul proiectului initial a fost integrarea facilitatilor oferite de Windows32 in compilatorul gcc si binutils, practic portarea acestora pe Windows. Mare parte din codul MinGW este distribuit sub licenta GPL, insa nu in intregime, detalii gasiti \'aici\':http://www.mingw.org/license.\r\n\r\nh3. Comparatie intre MinGW GCC si GNU GCC\r\n\r\nh4. Asemanari\r\n\r\n* Uneltele MinGW pot fi folosite de sine statatoare, asemanator cu uneltele echivalente din Linux. Asadar putem compila si depana (cu ajutorul MinGW gcc/g++ si gdb) orice sursa C/C++ care poate fi scrisa cu un editor de texte. Exista mai multe editoare cu syntax highlighting pentru windows: notepad++, vim, jedit.\r\n\r\nh4. Deosebiri\r\n\r\n* Pentru a citi/afisa numere pe 64 de biti cu libraria <stdio.h> se foloseste specificatorul de format non-standard \"%I64d\". Cateva detalii \'aici\':http://ascending.wordpress.com/2008/04/22/long-long-on-windows-dev-c-mingw/.\r\n\r\nh3. IDE-uri pentru MinGW\r\n\r\nUn IDE (Integrated Development Enviroment) contine:\r\n\r\n* editor performant (syntax highlighting, code completion)\r\n* debugger\r\n* utilitar pentru linkarea surselor si librariilor\r\n\r\nExemple de IDE pentru MinGW: Dev-cpp, MinGW Developer Studio, Code::Blocks (pe site-ul MinGW este recomandat Code::Blocks ca IDE).\r\n\r\nh3. \'MinGW Developer Studio\':http://infoarena.ro/schimbare-borland/alternativa?action=attach-list\r\n\r\n[site-ul nu mai merge de vreo 3 saptamani, arhiva e momentan pe infoarena, o voi pune ulterior la downloads, numai sa mearga pusa intreaga si nu pe parti]\r\n\r\nh4. Avantaje\r\n\r\n* Simplu de instalat si folosit\r\n* Ultima versiunea (2.0.5) vine in mod normal cu MinGW gcc 3.3.1, insa acesta poate fi inlocuit daca utilizatorul doreste acest lucru\r\n* Este freeware (Poate fi folosit gratuit in scopuri non-comerciale dar nu avem acces la surse. Pe viitor putem contacta autorul programului si cere accesul la surse.)\r\n* Editorul este foarte bun, are si hints pentru functiile din librariile standard\r\n* Este stabil in general, fiind putine cazurile cand crapa\r\n* Debugger-ul este unu relativ solid\r\n\r\nh4. Dezavantaje\r\n\r\n* Ultima versiune aparuta dateaza din ianuarie 2005, si reprezinta versiune 2.0.5 a produsului. Asadar, software-ul nu mai este in dezvoltare activa.\r\n* Utilizatorul trebuie sa creeze proiect ca sa poate compila/depana o sursa. Totusi, proiectele create sunt minimaliste (comparativ cu Visual C++ spre exemplu) si nu sunt foarte greu de folosit.\r\n\r\nh3. \'Code::Blocks\':http://www.codeblocks.org/\r\n\r\nUn IDE mai complicat, insa este mai complicat doar pentru ca ofera mai multe unelte. Ruleaza sursele fara proiect insa pentru a face debug trebuie creat un proiect si sursa trebuie importata in acesta. Debuggerul este insa unul puternic. Watchul permite evaluarea variabilelor, dar si a functiilor. De asemeni se pot observa si apelurile functiilor pe stiva sistem.\r\n\r\n\r\nh4. Avantaje\r\n\r\n* Este un proiect aflat in development\r\n* Este usor de instalat si contine multe feature-uri\r\n* Editorul este foarte bun, are hints pentru functiile si obiectele (vector, deque etc) din librariile standard, dar nu ofera hints pentru clasele create de user [TODO: de testat daca mingw studio face asta]\r\n\r\nh4. Dezavantaje\r\n\r\n* Are nevoie de un proiect pentru debug\r\n* Nu pare un produs bine pus la punct si bine finalizat. (doar un feeling nu e un argument)\r\n* *bogdan*: mi-a crapat pe windows de vreo 2 ori cand faceam proiecte fara sa inteleg de ce (nu prea pot reproduce).\r\n* *bogdan*: mi se pare prea complicat de folosit si deloc intuitiv. am preferat sa bag printfuri decat sa incerc sa debughez.\r\n* *silviu*: am debugat eu cu el si nu e super complicat; totusi, nu e la fel de usable debugul ca in Visual Studio\r\n* *silviu*: impresia mea a fost una foarte buna dupa ce m-am jucat un pic cu el; intr-adevar, nu pare foarte bine pus la punct dar are cateva chestii super tari (scrieti \"for\" si apoi dati CTRL+J).\r\n\r\nBug: Am folosit Windowsul, si la un moment dat cand trebuia sa compileze, imi tot zice mingw32-g++.exe ca \"No Disk\": \"There is no disk in the drive. Please insert a dist into drive D:\" (unitate optiva). Si trebuie sa-i dau Cancel de cateva zeci de ori, stresant.\r\n\r\n* In privinta acestui bug exista o observatie si o solutie \'aici\':forum/index.php?topic=2684.msg35110#msg35110 .\r\n\r\nh3. \'Dev-cpp\':http://www.bloodshed.net/index.html\r\n\r\nh4. Avantaje\r\n\r\n* Simplu de instalat si folosit\r\n* Ultima versiunea (4.9.9.2) vine in mod normal cu MinGW gcc 3.4.2, insa acesta poate fi inlocuit daca utilizatorul doreste acest lucru.\r\n* Daca nu se creeaza nici un proiect, sursele sunt trimise automat intr-un proiect fictiv.\r\n\r\nh4. Dezavantaje\r\n\r\n* Editorul nu este grozav, necesitand setari speciale pentru a merge\r\n* Debuggerul crapa si este destul de greu de folosit [Silviu: Eu stiam ca e ca si cum n-ar fi acolo :)]\r\n* Ultima versiune aparuta dateaza din februarie 2005, si reprezinta versiune 4.9.9.2 a produsului. Asadar, software-ul nu mai este in dezvoltare activa.\r\n* Desi usor de folosit in prima faza, nu este foarte stabil.\r\n\r\nh4. Verdict\r\n\r\nAcest IDE este de departe cea mai instabila solutie din cele 3 IDE posibile pentru MinGW. In plus, MinGW Developer Studio ii este net superior. Propunem ca acest IDE sa fie *evitat* in solutia de inlocuire a compilatoarelor Borland.',1490,'public',NULL,NULL),('metoda-greedy-si-problema-fractionara-a-rucsacului','Metoda Greedy si problema fractionara a rucsacului','2009-08-31 18:52:22','2009-09-04 09:51:17','h1. Metoda Greedy si problema fractionara a rucsacului\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"miculprogramator\") ==\r\n\r\n(Categoria _Algoritmi si tehnici de programare_, Autor Albulescu Cosmina)\r\n\r\n(toc){width: 25em}*{text-align:center} *Conţinut:*\r\n* \'Despre algoritmii Greedy\':metoda-greedy-si-problema-fractionara-a-rucsacului#despre-algoritmii-greedy\r\n* \'Problema spectacolelor\':metoda-greedy-si-problema-fractionara-a-rucsacului#problema-spectacolelor\r\n* \'Problema fractionara a rucsacului\':metoda-greedy-si-problema-fractionara-a-rucsacului#problema-fractionara-a-rucsacului\r\n* \'Precizari\':metoda-greedy-si-problema-fractionara-a-rucsacului#precizari\r\n\r\n\r\n\r\n\r\nh1. Despre algoritmii Greedy\r\n\r\nAlgoritmii Greedy sunt caracterizati de metoda lor de functionare: la fiecare pas se alege cel mai bun candidat posibil, dupa evaluarea tuturor acestora. Metoda determina intotdeauna o singura solutie, asigurand un optim local, dar nu intotdeauna si global. Tehnica Greedy este una de optimizare, ruland mai rapid decat un Backtraking, dar nefiind intotdeauna cea mai buna.\r\n\r\nCand nu aveti o idee mai buna legata de o problema, in timpul unui concurs, o implementare Greedy ar putea aduce in jur de 30% din punctaj. \r\nExista situatii in care acesti algoritmi clacheaza, cum ar fi problema comisului voiajor sau problemele NP-complete.\r\n\r\nMetoda Greedy are si avantaje: poate fi aplicata multor probleme: determinarea celor mai scurte drumuri in grafuri (Dijkstra), determinarea arborelui minimal de acoperire (Prim, Kruskal), codificare arborilor Huffmann, planificarea activitatilor, problema spectacolelor si problema fractionara a rucsacului. Dintre acestea, articolul le trateaza numai pe ultimele doua pentru a da un exemplu cat mai bun a modului de functionare si aplicare a algoritmilor Greedy.\r\n\r\n*Mishu91*: Nu ştiu dacă sunt cea mai în măsură persoană să îmi dau cu părerea, însă eu zic că prezentarea este mult prea sumară, iar problemele alese sunt cam puţine la număr(doar 2) şi nu foarte relevante. În plus, identarea nu este cea mai fericită, insă asta nu este o problemă foarte mare. \r\n\r\nh1. Problema spectacolelor\r\n\r\n Managerul artistic al unui festival trebuie sa selecteze o multime cat mai ampla de spectacole ce pot fi jucate in singura sala pe care o are la dispozitie.Stiind ca i s-au propus n spectacole si pentru fiecare spectacol i-a fost anuntat intervalul in care se poate desfasura [Si, Fi] (Si reprezinta ora si minutul de inceput, iar Fi ora si minutul de final al spectacolului i), scrieti un program care sa permita spectatorilor vizionarea unui numar cat mai mare de spectacole.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare _spectacole.in_ se afla numarul n, numarul de spectacole propus. Pe urmatoarele n linii se vor afla 4 valori, primele doua reprezentand ora si minutul inceperii spectacolului curent, iar ultimele doua reprezentand ora si minutul terminarii spectacolului.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire _spectacole.out_ contine o singura linie, pe aceasta vor fi scrise numerele de ordine ale spectacolelor care indeplinesc solutia problemei, printr-un spatiu. \r\n\r\nh2. Restrictii\r\n\r\n* n <= 100\r\n\r\nh2. Exemplu\r\n\r\n|_. spectacole.in | |_. spectacole.out |\r\n| 5                 \r\n12 30 16 30        \r\n15 0 18 0            \r\n10 0 18 30\r\n18 0 20 45\r\n12 15 13 0 |         | 5 2 4 |\r\n\r\nh2. Descrierea solutiei\r\n\r\nVom sorta crescator spectacolele dupa ora de final. Vom selecta initial primul spectacol (cel care se termina cel mai devreme). In continuare vom selecta, la fiecare pasa, primul spectacol neselectat, care nu se suprapune peste cele deja selectate. \r\n\r\nO implementare intuitiva a acestui algoritm va fi prezentata in continuare. Pentru sortat vom folosi metoda BubbleSort, care este indeajuns de buna pentru limitele impuse de problema.\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\nusing namespace std;\r\n\r\nifstream f(\"spectacole.in\");\r\nofstream g(\"spectacole.out\");\r\n\r\nint n,inceput[100],sfarsit[100],nr[100];\r\n\r\nvoid citeste()\r\n{\r\n	int ora,min,i;\r\n	f>>n;\r\n	for (i=0;i<n;++i)\r\n	{\r\n		nr[i]=i+1;\r\n		f>>ora>>min;\r\n		inceput[i]=ora*60+min;\r\n		f>>ora>>min;\r\n		sfarsit[i]=ora*60+min;\r\n	}\r\n	f.close();\r\n}\r\n\r\nvoid sorteaza()\r\n{\r\n	int aux,schimb,i;\r\n	do\r\n	{\r\n		schimb=0;\r\n		for (i=0;i<n-1;++i)\r\n			if (sfarsit[nr[i]]>sfarsit[nr[i+1]])\r\n			{\r\n				aux=nr[i];\r\n				nr[i]=nr[i+1];\r\n				nr[i+1]=aux;\r\n				schimb=1;\r\n			}\r\n	}\r\n	while (schimb);\r\n}\r\n\r\nvoid rezolva()\r\n{\r\n	int ultim,i;\r\n	for (ultim=0,i=1;i<n;++i)\r\n		if (inceput[nr[i]]>=sfarsit[nr[ultim]])\r\n		{\r\n			g<<nr[i]+1<<\" \";\r\n			ultim=i;\r\n		}\r\n	g<<endl;\r\n}\r\n\r\nint main()\r\n{\r\n	citeste();\r\n	sorteaza();\r\n	rezolva();\r\n	return 0;\r\n}\r\n==\r\n\r\nh1. Problema fractionara a rucsacului\r\n\r\nSe considera ca dispunem de un rucsac cu capacitatea M si de N obiecte, definite fiecare prin greutate si valoare, ce trebuie introduce in rucsac. Se cere o modalitate de a umple rucsacul cu obiecte , astfel incat valoarea totala sa fie maxima. Este posibil ca oricate obiecte si bucati din obiecte sa fie introduse.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare _rucsac.in_ se gasesc doua numere, primul fiind N, iar al doilea M (cu specificatiile din enunt). Pe urmatoarele N linii se gasesc, despartite printr-un spatiu valoarea obiectului curent si greutatea acestuia.\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul de iesire _rucsac.out_ vor fi specificate numarul de ordine al obiectului, precum si procentul in care acesta poate fi introdus in rucsac.\r\n\r\nh2. Exemplu\r\n\r\n|_. rucsac.in | |_. rucsac.out |\r\n| 5 100\r\n1000 120\r\n500 20\r\n400 200\r\n1000 100\r\n25 1|          | 2 100\r\n                 4 79\r\n                 5 100 |\r\n\r\nh2. Descrierea solutiei\r\n\r\nVom reprezenta solutia problemei ca pe un vector x. Vom ordona obictele descrescator tinand cont de valoarea/greutate. Atata timp cat obiectele incap in rucsac, le vom adauga in intregime. Completam rucsacul cu un fragment din urmatorul obiect ce nu a fost deja selectat.\r\n\r\nO implementare simpla a acestui algoritm este urmatoarea:\r\n\r\n\r\n==code(cpp) |\r\n\r\n#include <iostream>\r\n#include <fstream>\r\nusing namespace std;\r\n\r\nifstream f(\"rucsac.in\");\r\nofstream g(\"rucsac.out\");\r\n\r\nint o[100],N,M;\r\nfloat val[100],greu[100],x[100],Gr;\r\n\r\nvoid  citeste()\r\n{\r\n	int i;\r\n	f>>N>>M;\r\n	for (i=0;i<N;++i)\r\n	{\r\n		o[i]=i;\r\n		f>>val[i]>>greu[i];\r\n	}\r\n	f.close();\r\n}\r\n\r\nvoid sort()\r\n{\r\n	int i,aux,schimb;\r\n	do\r\n	{\r\n		schimb=0;\r\n		for (i=0;i<N-1;++i)\r\n			if (val[o[i]]/greu[o[i]]<val[o[i+1]]/greu[o[i+1]])\r\n			{\r\n				aux=o[i];\r\n				o[i]=o[i+1];\r\n				o[i+1]=aux;\r\n				schimb=1;\r\n			}\r\n	}\r\n	while (schimb);\r\n}\r\n\r\nvoid rezolva()\r\n{\r\n	int i;\r\n	for (i=0,Gr=M;i<N && Gr>greu[o[i]];++i)\r\n	{\r\n		x[o[i]]=1;\r\n		Gr-=greu[o[i]];\r\n	}\r\n}\r\n\r\nvoid afisare()\r\n{\r\n	int i;\r\n	for (i=0;i<N;++i)\r\n		if (x[i]) g<<i+1<<\" \"<<x[i]*100<<endl;\r\n	g.close();\r\n}\r\n\r\nint main()\r\n{\r\n	citeste();\r\n	sort();\r\n	rezolva();\r\n	afisare();\r\n	return 0;\r\n}\r\n\r\n==\r\n\r\nh1. Precizari\r\n\r\nDesi tehnica Greedy poate fi abordata cu succes in abordarea problemei fractionare a rucsacului, nu la fel se poate spune si in cazul problemei discrete a rucsacului. Aceasta se poate rezolva optim cu ajutorul programarii dinamice.\r\n\r\nIn cazul problemei comisului voiajor, putem aplica metoda Backtracking, Greedy nefiind optim. Spre deosebire de algoritmii \"lacomi\", tehnicile Backtracking revin mereu inapoi, la nivel de predeceosor, de aici rezultand timpul mare de executie in comparatie cu Greedy. Un lucru pe care il au comun ambele metode este acela ca solutia se construieste progresiv, pas cu pas.\r\n',2044,'public',NULL,NULL),('runda/4_me','4_me','2009-09-02 07:17:39','2009-09-02 07:27:43','h1. == roundparam(round_id=\"4_me\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"4_me\") ==\r\n\r\nConcursul incepe miercuri 2 septembrie 2009 10:00:00 si dureaza ==roundparam(round_id=\"4_me\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/4_me/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"4_me\" score=\"1\")==',6958,'round: 4_me',NULL,NULL),('runda/4_me/clasament','Clasament 4_me','2009-09-02 07:17:39','2009-09-02 07:17:39','h1. Clasament ==roundparam(round_id=\"4_me\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"4_me\")==',6958,'round: 4_me',NULL,NULL),('runda/worldcup_info','worldcup_info','2009-09-03 07:56:15','2009-09-03 07:56:15','h1. == roundparam(round_id=\"worldcup_info\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"worldcup_info\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"worldcup_info\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"worldcup_info\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/worldcup_info/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"worldcup_info\" score=\"1\")==',10515,'round: worldcup_info',NULL,NULL),('runda/worldcup_info/clasament','Clasament worldcup_info','2009-09-03 07:56:15','2009-09-03 07:56:15','h1. Clasament ==roundparam(round_id=\"worldcup_info\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"worldcup_info\")==',10515,'round: worldcup_info',NULL,NULL),('runda/summer_camp_7','summer_camp_7','2009-09-04 12:56:09','2009-09-04 12:56:09','h1. == roundparam(round_id=\"summer_camp_7\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"summer_camp_7\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"summer_camp_7\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"summer_camp_7\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/summer_camp_7/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"summer_camp_7\" score=\"1\")==',6957,'round: summer_camp_7',NULL,NULL),('runda/summer_camp_7/clasament','Clasament summer_camp_7','2009-09-04 12:56:09','2009-09-04 12:56:09','h1. Clasament ==roundparam(round_id=\"summer_camp_7\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer_camp_7\")==',6957,'round: summer_camp_7',NULL,NULL),('runda/info.conc','info.conc','2009-09-05 13:09:28','2009-09-05 13:09:28','h1. == roundparam(round_id=\"info.conc\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"info.conc\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"info.conc\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"info.conc\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/info.conc/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"info.conc\" score=\"1\")==',7465,'round: info.conc',NULL,NULL),('runda/info.conc/clasament','Clasament info.conc','2009-09-05 13:09:28','2009-09-05 13:09:28','h1. Clasament ==roundparam(round_id=\"info.conc\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"info.conc\")==',7465,'round: info.conc',NULL,NULL),('runda/info.con.sept','info.con.sept','2009-09-05 13:10:44','2009-09-05 13:10:44','h1. == roundparam(round_id=\"info.con.sept\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"info.con.sept\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"info.con.sept\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"info.con.sept\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/info.con.sept/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"info.con.sept\" score=\"1\")==',7465,'round: info.con.sept',NULL,NULL),('runda/info.con.sept/clasament','Clasament info.con.sept','2009-09-05 13:10:44','2009-09-05 13:10:44','h1. Clasament ==roundparam(round_id=\"info.con.sept\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"info.con.sept\")==',7465,'round: info.con.sept',NULL,NULL),('implica-te/extinde-arhiva/acord','Lista propunatorilor infoarena-friendly','2007-04-21 21:41:18','2010-03-10 20:47:15','h1. Lista propunatorilor infoarena-friendly\r\n\r\nPentru a adauga in arhiva infoarena probleme in cadrul programului \'Extinde Arhiva!\':implica-te/extinde-arhiva este necesar acordul din partea autorului pentru fiecare problema. Astfel, am intocmit aceasta lista cu propunatorii care ne-au oferit acordul pentru problemelor dumnealor. \r\nDaca autorul problemei pe care vrei s-o adaugi nu se gaseste pe lista, vorbeste cu un \'administrator\':echipa-infoarena pentru a intra in contact cu autorul respectiv.\r\nMultumim tuturor persoanelor care ajuta la dezvoltarea \'comunitatii infoarena\':implica-te!\r\n\r\n* Maria Nita\r\n* Adrian Nita\r\n* Mihai Patrascu\r\n* Stelian Ciurea\r\n* Rodica Pintea\r\n* Roxana Tamplaru\r\n* Fechete Dan Ionut\r\n* Mugurel Ionut Andreica\r\n* Marius Andrei\r\n* Mihai Stroe\r\n* Radu Berinde\r\n* Tiberiu Danet\r\n* Dana Lica\r\n* Emilian Miron\r\n* Catalin Francu\r\n* Cristian Cadar\r\n* Nistor Mot\r\n* Alexandru Mosoi\r\n* Victor Manz\r\n* Carmen Popescu\r\n* Marius Nicoli\r\n* Ciprian Chesca\r\n* Cristina Iordaiche\r\n* Horatiu Cristurean\r\n* Radu Boriga\r\n* Orice membru al echipei \'infoarena\':echipa-infoarena',2044,'protected',NULL,NULL),('runda/summer_camp_8','summer_camp_8','2009-09-09 09:09:24','2009-09-09 09:09:24','h1. == roundparam(round_id=\"summer_camp_8\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"summer_camp_8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"summer_camp_8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"summer_camp_8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/summer_camp_8/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"summer_camp_8\" score=\"1\")==',6957,'round: summer_camp_8',NULL,NULL),('runda/summer_camp_8/clasament','Clasament summer_camp_8','2009-09-09 09:09:24','2009-09-09 09:09:24','h1. Clasament ==roundparam(round_id=\"summer_camp_8\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer_camp_8\")==',6957,'round: summer_camp_8',NULL,NULL),('runda/september_contest/clasament','Clasament september_contest','2009-09-10 08:58:43','2009-09-10 08:58:43','h1. Clasament ==roundparam(round_id=\"september_contest\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"september_contest\")==',9356,'round: september_contest',NULL,NULL),('runda/super_tare','super_tare','2009-09-10 15:43:31','2009-09-10 15:43:31','h1. == roundparam(round_id=\"super_tare\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"super_tare\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"super_tare\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"super_tare\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/super_tare/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"super_tare\" score=\"1\")==',4453,'round: super_tare',NULL,NULL),('runda/super_tare/clasament','Clasament super_tare','2009-09-10 15:43:31','2009-09-10 15:43:31','h1. Clasament ==roundparam(round_id=\"super_tare\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"super_tare\")==',4453,'round: super_tare',NULL,NULL),('runda/uh','uh','2009-09-29 09:11:04','2009-09-29 09:11:04','h1. == roundparam(round_id=\"uh\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"uh\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"uh\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"uh\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/uh/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"uh\" score=\"1\")==',8710,'round: uh',NULL,NULL),('runda/porc4','porc4','2009-09-11 17:11:37','2009-09-11 17:11:37','h1. == roundparam(round_id=\"porc4\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"porc4\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"porc4\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"porc4\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/porc4/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"porc4\" score=\"1\")==',6333,'round: porc4',NULL,NULL),('runda/porc4/clasament','Clasament porc4','2009-09-11 17:11:37','2009-09-11 17:11:37','h1. Clasament ==roundparam(round_id=\"porc4\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"porc4\")==',6333,'round: porc4',NULL,NULL),('runda/acm_upb_echipe_2009','acm_upb_echipe_2009','2009-09-13 06:52:35','2009-09-13 06:52:35','h1. == roundparam(round_id=\"acm_upb_echipe_2009\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"acm_upb_echipe_2009\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"acm_upb_echipe_2009\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"acm_upb_echipe_2009\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/acm_upb_echipe_2009/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"acm_upb_echipe_2009\" score=\"1\")==',256,'round: acm_upb_echipe_2009',NULL,NULL),('runda/acm_upb_echipe_2009/clasament','Clasament acm_upb_echipe_2009','2009-09-13 06:52:36','2009-09-13 06:52:36','h1. Clasament ==roundparam(round_id=\"acm_upb_echipe_2009\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"acm_upb_echipe_2009\")==',256,'round: acm_upb_echipe_2009',NULL,NULL),('runda/summer_camp_9','summer_camp_9','2009-09-13 08:14:23','2009-09-13 08:14:23','h1. == roundparam(round_id=\"summer_camp_9\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"summer_camp_9\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"summer_camp_9\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"summer_camp_9\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/summer_camp_9/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"summer_camp_9\" score=\"1\")==',6957,'round: summer_camp_9',NULL,NULL),('runda/summer_camp_9/clasament','Clasament summer_camp_9','2009-09-13 08:14:23','2009-09-13 08:14:23','h1. Clasament ==roundparam(round_id=\"summer_camp_9\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"summer_camp_9\")==',6957,'round: summer_camp_9',NULL,NULL),('utilizator/tabara','Profil tabara','2006-11-24 20:58:19','2009-09-13 09:18:42','h2. Despre mine\r\n\r\nStudent in anul II la \"Universitatea Politehnica Bucuresti\":http://www.pub.ro/, \"[Facultatea de Automatica si Calculatoare]\":http://acs.pub.ro/, sectia \"Calculatoare\":http://www.acs.pub.ro/\r\n\r\nh2. Rezultate la concursurile de informatica\r\n\r\nInvitatie pentru \"TCHS\":http://www.topcoder.com/tc?module=Static&d1=hs&d2=home \"Tournament 2007 Finals\"\r\n(calificare cu echipa )\r\n\r\nh2. Suport pentru infoarena\r\n\r\nProbleme adaugate:\r\n\r\nArhiva de probleme: \"Munte2\":http://infoarena.ro/problema/munte2\r\nArhiva educationala: \"Sortare Topologica\":http://infoarena.ro/problema/sortaret\r\n\r\n\r\n\r\n\r\n\r\n\r\n',1024,'protected',NULL,NULL),('runda/simularecnitv2/clasament','Clasament simularecnitv2','2010-03-24 21:44:29','2010-03-24 21:44:29','h1. Clasament ==roundparam(round_id=\"simularecnitv2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"simularecnitv2\")==',256,'round: simularecnitv2',NULL,NULL),('runda/simularecnitv3','simularecnitv3','2010-03-24 21:47:35','2010-03-24 21:47:35','h1. == roundparam(round_id=\"simularecnitv3\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"simularecnitv3\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"simularecnitv3\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"simularecnitv3\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"simularecnitv3\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/simularecnitv3/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"simularecnitv3\" score=\"1\")==',256,'round: simularecnitv3',NULL,NULL),('runda/simularecnitv3/clasament','Clasament simularecnitv3','2010-03-24 21:47:35','2010-03-24 21:47:35','h1. Clasament ==roundparam(round_id=\"simularecnitv3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"simularecnitv3\")==',256,'round: simularecnitv3',NULL,NULL),('runda/problemiada_14','problemiada_14','2010-03-24 22:01:38','2010-03-24 22:01:38','h1. == roundparam(round_id=\"problemiada_14\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"problemiada_14\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"problemiada_14\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"problemiada_14\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"problemiada_14\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/problemiada_14/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"problemiada_14\" score=\"1\")==',5748,'round: problemiada_14',NULL,NULL),('runda/problemiada_14/clasament','Clasament problemiada_14','2010-03-24 22:01:38','2010-03-24 22:01:38','h1. Clasament ==roundparam(round_id=\"problemiada_14\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"problemiada_14\")==',5748,'round: problemiada_14',NULL,NULL),('runda/porc_log','porc_log','2009-09-13 14:04:38','2009-09-13 14:04:38','h1. == roundparam(round_id=\"porc_log\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"porc_log\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"porc_log\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"porc_log\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/porc_log/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"porc_log\" score=\"1\")==',6333,'round: porc_log',NULL,NULL),('runda/porc_log/clasament','Clasament porc_log','2009-09-13 14:04:38','2009-09-13 14:04:38','h1. Clasament ==roundparam(round_id=\"porc_log\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"porc_log\")==',6333,'round: porc_log',NULL,NULL),('runda/info.conc.sept.2','info.conc.sept.2','2009-09-14 09:00:08','2009-09-14 09:00:08','h1. == roundparam(round_id=\"info.conc.sept.2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"info.conc.sept.2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"info.conc.sept.2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"info.conc.sept.2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/info.conc.sept.2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"info.conc.sept.2\" score=\"1\")==',7465,'round: info.conc.sept.2',NULL,NULL),('runda/info.conc.sept.2/clasament','Clasament info.conc.sept.2','2009-09-14 09:00:08','2009-09-14 09:00:08','h1. Clasament ==roundparam(round_id=\"info.conc.sept.2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"info.conc.sept.2\")==',7465,'round: info.conc.sept.2',NULL,NULL),('runda/papiu_contest_1','papiu_contest_1','2009-09-14 18:13:17','2009-09-14 18:13:17','h1. == roundparam(round_id=\"papiu_contest_1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"papiu_contest_1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"papiu_contest_1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"papiu_contest_1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/papiu_contest_1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"papiu_contest_1\" score=\"1\")==',6957,'round: papiu_contest_1',NULL,NULL),('runda/papiu_contest_1/clasament','Clasament papiu_contest_1','2009-09-14 18:13:17','2009-09-14 18:13:17','h1. Clasament ==roundparam(round_id=\"papiu_contest_1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"papiu_contest_1\")==',6957,'round: papiu_contest_1',NULL,NULL),('runda/papiu_contest_2','papiu_contest_2','2009-09-25 15:24:30','2009-09-25 15:24:30','h1. == roundparam(round_id=\"papiu_contest_2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"papiu_contest_2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"papiu_contest_2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"papiu_contest_2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/papiu_contest_2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"papiu_contest_2\" score=\"1\")==',6957,'round: papiu_contest_2',NULL,NULL),('runda/papiu_contest_2/clasament','Clasament papiu_contest_2','2009-09-25 15:24:30','2009-09-25 15:24:30','h1. Clasament ==roundparam(round_id=\"papiu_contest_2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"papiu_contest_2\")==',6957,'round: papiu_contest_2',NULL,NULL),('runda/cnrv_1/clasament','Clasament cnrv_1','2009-09-26 16:48:03','2009-10-06 18:55:27','h1. Clasament ==roundparam(round_id=\"cnrv_1\" param=\"title\") ==\r\n\r\n\r\n==Rankings(rounds = \"cnrv_1\")==',5748,'round: cnrv_1',NULL,NULL),('runda/cnrv_1','CNRV - pregatire la info - Editia #1','2009-09-26 16:48:03','2009-09-26 17:00:57','h1. == roundparam(round_id=\"cnrv_1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cnrv_1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cnrv_1\" param=\"start_time\" strong=\"true\")== si dureaza o saptamana.\r\n\r\nConcursul este unul de incalzire si se adreseaza in special elevilor de clasa a 10-a, CNRV. Dificultatea problemelor este scazuta.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cnrv_1/clasament.\r\n\r\nh2. Probleme\r\n\r\n\r\n==Tasks(round_id=\"cnrv_1\" score=\"1\")==',5748,'round: cnrv_1',NULL,NULL),('runda/trie','trie','2010-03-08 17:39:09','2010-03-08 17:39:09','h1. == roundparam(round_id=\"trie\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"trie\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"trie\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"trie\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"trie\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/trie/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"trie\" score=\"1\")==',6305,'round: trie',NULL,NULL),('utilizator/andreii_93','Profil andreii_93','2009-09-28 05:10:42','2009-09-28 05:10:42','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',10730,'public',NULL,NULL),('runda/uh/clasament','Clasament uh','2009-09-29 09:11:04','2009-09-29 09:11:04','h1. Clasament ==roundparam(round_id=\"uh\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"uh\")==',8710,'round: uh',NULL,NULL),('runda/div1','div1','2009-09-29 09:11:09','2009-09-29 09:11:09','h1. == roundparam(round_id=\"div1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"div1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"div1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"div1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/div1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"div1\" score=\"1\")==',4861,'round: div1',NULL,NULL),('runda/div1/clasament','Clasament div1','2009-09-29 09:11:09','2009-09-29 09:11:09','h1. Clasament ==roundparam(round_id=\"div1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"div1\")==',4861,'round: div1',NULL,NULL),('runda/100','100','2009-09-29 10:08:44','2009-09-29 10:08:44','h1. == roundparam(round_id=\"100\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"100\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"100\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"100\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/100/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"100\" score=\"1\")==',10739,'round: 100',NULL,NULL),('runda/100/clasament','Clasament 100','2009-09-29 10:08:45','2009-09-29 10:08:45','h1. Clasament ==roundparam(round_id=\"100\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"100\")==',10739,'round: 100',NULL,NULL),('runda/supers','supers','2009-09-30 17:41:00','2009-09-30 18:48:18','h1. == roundparam(round_id=\"supers\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"supers\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"supers\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"supers\" param=\"duration\" strong=\"true\")== ore.\r\n    In acest concurs se reprezinta viata unui erou. Incearca sa intre in societatea OTPB(problema Atac) ,recupereaza oameni(problema Barbar ) si trece granita(problema granita si perle) cu Tara Erathiei(problema Heroes of Might & Magic) din care pleaca nava Enterprise(problema Poarta). El trebuie sa antreneze o armata de soldati(problema Soldati),sa se lupte cu extraterestri(problema Razboiul lumilor ).In final el ajunge acasa(problema Calatorie interplanetara) si este aclamat impreuna cu ajutoarele lui.\r\n    Puteti fi si voi unul dintre ajutoare. El ofera 100 de dolari pentru un ajutor complet sau cat merita.\r\n\r\n\'*Lista ajutoarelor si dolarilor incasati*\':runda/supers/clasament.\r\n\r\nh2. Lista de misiuni.\r\n\r\n==Tasks(round_id=\"supers\" score=\"1\")==',7700,'round: supers',NULL,NULL),('runda/supers/clasament','Clasament supers','2009-09-30 17:41:00','2009-09-30 17:41:00','h1. Clasament ==roundparam(round_id=\"supers\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"supers\")==',7700,'round: supers',NULL,NULL),('runda/practice_arena','practice_arena','2009-10-01 11:25:10','2009-10-01 11:25:10','h1. == roundparam(round_id=\"practice_arena\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"practice_arena\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"practice_arena\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"practice_arena\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/practice_arena/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"practice_arena\" score=\"1\")==',4230,'round: practice_arena',NULL,NULL),('runda/practice_arena/clasament','Clasament practice_arena','2009-10-01 11:25:10','2009-10-01 11:25:10','h1. Clasament ==roundparam(round_id=\"practice_arena\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"practice_arena\")==',4230,'round: practice_arena',NULL,NULL),('mugur','mugur','2009-10-01 12:47:45','2009-10-01 12:47:45','a fost o data un mugur',1021,'public',NULL,NULL),('utilizator/bringiton','Profil BringitON','2009-10-03 12:28:38','2009-10-03 12:28:38','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',10783,'public',NULL,NULL),('runda/back_in/clasament','Clasament back_in','2009-10-03 17:26:54','2009-10-03 17:26:54','h1. Clasament ==roundparam(round_id=\"back_in\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"back_in\")==',9356,'round: back_in',NULL,NULL),('runda/two_week_contest','two_week_contest','2009-10-04 12:23:28','2009-10-04 12:28:00','h1. == roundparam(round_id=\"two_week_contest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"two_week_contest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"two_week_contest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"two_week_contest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/two_week_contest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"two_week_contest\" score=\"1\")==',10515,'round: two_week_contest',NULL,NULL),('runda/two_week_contest/clasament','Clasament two_week_contest','2009-10-04 12:23:28','2009-10-04 12:23:28','h1. Clasament ==roundparam(round_id=\"two_week_contest\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"two_week_contest\")==',10515,'round: two_week_contest',NULL,NULL),('runda/cnrv_2','CNRV - pregatire la info - Editia #2','2009-10-08 11:47:58','2009-10-08 11:52:01','h1. == roundparam(round_id=\"cnrv_2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cnrv_2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cnrv_2\" param=\"start_time\" strong=\"true\")==. Este adresat elevilor de clasa a X-a CNRV, si este de dificultate scazuta.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cnrv_2/clasament.\r\n\r\nh2. Probleme\r\n\r\n\r\n==Tasks(round_id=\"cnrv_2\" score=\"1\")==',5748,'round: cnrv_2',NULL,NULL),('runda/cnrv_2/clasament','Clasament cnrv_2','2009-10-08 11:47:58','2009-10-08 11:47:58','h1. Clasament ==roundparam(round_id=\"cnrv_2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"cnrv_2\")==',5748,'round: cnrv_2',NULL,NULL),('runda/bkt1','bkt1','2009-10-09 05:07:15','2009-10-09 05:07:15','h1. == roundparam(round_id=\"bkt1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"bkt1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"bkt1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"bkt1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/bkt1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"bkt1\" score=\"1\")==',4861,'round: bkt1',NULL,NULL),('runda/bkt1/clasament','Clasament bkt1','2009-10-09 05:07:15','2009-10-09 05:07:15','h1. Clasament ==roundparam(round_id=\"bkt1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"bkt1\")==',4861,'round: bkt1',NULL,NULL),('runda/cautb1','cautb1','2009-10-09 08:13:37','2009-10-09 08:13:37','h1. == roundparam(round_id=\"cautb1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cautb1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cautb1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cautb1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cautb1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cautb1\" score=\"1\")==',4861,'round: cautb1',NULL,NULL),('runda/cautb1/clasament','Clasament cautb1','2009-10-09 08:13:37','2009-10-09 08:13:37','h1. Clasament ==roundparam(round_id=\"cautb1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"cautb1\")==',4861,'round: cautb1',NULL,NULL),('utilizator/danielg','Profil DanielG','2007-12-05 13:13:25','2010-03-16 16:14:05','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\nElev in clasa a XI-a la Colegiul National \"Mircea cel Batran\" Rm. Valcea \r\n\r\nh2. Rezultate\r\n\r\n2007-2008 \r\nPremiul I, OJI 2008\r\nMedalie de Bronz, ONI 2008 Ploiesti\r\nPremiul I, CEX 2008 Suceava\r\n\r\n2008-2009\r\nPremiul al III-lea, Concursul Interjudetean de Programare \"Stefan Odobleja\" 2009 Craiova\r\nPremiul I, Info-Oltenia 2009 Turnu-Severin(proba pe echipe - Andrei Vacaroiu)\r\nPremiu Special, Istorie si civilizatie in dimensiune virtuala 2009 Vaslui\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n',7280,'public',NULL,NULL),('runda/porc_e','porc_e','2009-10-13 12:56:38','2009-10-13 12:56:38','h1. == roundparam(round_id=\"porc_e\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"porc_e\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"porc_e\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"porc_e\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/porc_e/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"porc_e\" score=\"1\")==',6333,'round: porc_e',NULL,NULL),('runda/porc_e/clasament','Clasament porc_e','2009-10-13 12:56:38','2009-10-13 12:56:38','h1. Clasament ==roundparam(round_id=\"porc_e\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"porc_e\")==',6333,'round: porc_e',NULL,NULL),('planificare/sedinta-20091015','Ședință 2009-10-15','2009-09-28 19:00:23','2009-10-15 18:28:51','h1. Şedinţă 2009-10-15\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Joi* la ora *19^00^* la \'Cafepedia 3, Zona Romană\':http://metropotam.ro/Cluburi/loc0483273064-Cafepedia-3/.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"devilkind\" type=\"tiny\")==\r\n* ==user(user=\"DITzoneC\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ... Tu?\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Sponsorizare Amazon | ==user(user=\"astronomy\" type=\"tiny\")== |\r\n| Recapitulare \'sedinţa anterioară\':planificare/sedinta-20090727 | ? |\r\n| Alegerea preşedintelui infoarena | ? |\r\n| OKRs si planuri pentru urmatorul an scolar | ? |\r\n| Algoritmiada 2010 | ? |\r\n| Tabăra infoarena | ? |\r\n\r\nh2. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Cristian vorbeste cu Buraga legat de sponsorizare\r\n* Cristian modifică IAP de alegere a Preşedintelui: Preşedintele desemnează câte un Vicepreşedinte pentru Content (arhivă, concursuri online, articole), Development şi Algoritmiada. Preşedintele se ocupă şi de obiectivele legate de comunitate.\r\n* Am votat noul Presedinte infoarena: ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* Cosmin organizeaza sedinta saptamana viitoare.\r\n* Silviu face blog post despre noul Presedinte.\r\n* Cristian ii face card Cristinei si lui Cosmin.\r\n\r\nh2(#notite). Notite\r\n\r\n...',961,'protected',NULL,NULL),('utilizator/andrei29','Profil Andrei29','2009-10-16 06:45:13','2009-10-16 06:45:13','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',10888,'public',NULL,NULL),('runda/cnrv_3','CNRV - pregatire la info - Editia #3','2009-10-17 08:46:09','2009-10-17 10:46:58','h1. == roundparam(round_id=\"cnrv_3\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cnrv_3\") ==\r\n\r\nConcursul pune accent pe cautare binara si pe numere prime. Problema \"Cautare binara\" este din arhiva educationala si e obligatorie [ usoara, clasica, facuta in clasa, etc ]. Problema \"Factorial\" este o aplicatie a cautarii binare ( in loc de vector, se cauta pe un interval din multimea numerelor naturale ). \r\n\r\nLa \"sortare prin comparare\" va rog sa utilizati functia \"sort\" din STL. La \"Submat\" aveti nevoie de sortare.\r\n\r\n\"Fractii\" si \"Numere prime\" sunt optionale. Aveti nevoie de ciurul lui Erathostene si de functia lui Euler. Cine are bunavointa, le poate invata singur (vezi sectiunea Articole de pe infoarena, respectiv site-ul infocnrv). :)\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cnrv_3/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cnrv_3\" score=\"1\")==',5748,'round: cnrv_3',NULL,NULL),('runda/cnrv_3/clasament','Clasament cnrv_3','2009-10-17 08:46:09','2009-10-17 08:46:09','h1. Clasament ==roundparam(round_id=\"cnrv_3\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"cnrv_3\")==',5748,'round: cnrv_3',NULL,NULL),('runda/cls_10c','cls_10c','2009-10-17 13:45:39','2009-10-17 13:45:39','h1. == roundparam(round_id=\"cls_10c\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cls_10c\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cls_10c\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cls_10c\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cls_10c/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cls_10c\" score=\"1\")==',10901,'round: cls_10c',NULL,NULL),('runda/cls_10c/clasament','Clasament cls_10c','2009-10-17 13:45:39','2009-10-17 13:45:39','h1. Clasament ==roundparam(round_id=\"cls_10c\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"cls_10c\")==',10901,'round: cls_10c',NULL,NULL),('runda/clasa_a10a','clasa_a10a','2009-10-21 05:36:53','2009-10-21 05:36:53','h1. == roundparam(round_id=\"clasa_a10a\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"clasa_a10a\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"clasa_a10a\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"clasa_a10a\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/clasa_a10a/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"clasa_a10a\" score=\"1\")==',10774,'round: clasa_a10a',NULL,NULL),('runda/clasa_a10a/clasament','Clasament clasa_a10a','2009-10-21 05:36:53','2009-10-21 05:36:53','h1. Clasament ==roundparam(round_id=\"clasa_a10a\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"clasa_a10a\")==',10774,'round: clasa_a10a',NULL,NULL),('prezentare','Prezentare infoarena','2007-05-14 22:22:49','2009-10-29 00:00:34','h1. Prezentare infoarena\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nPe infoarena invatam informatica si programare, unii de la altii. Organizam concursuri de informatica, scriem articole, dezvoltam software, facem schimb de experienta si idei. Suntem viitorii specialisti IT ai Romaniei. Impreuna invatam mai bine!\r\n\r\nDaca te pasioneaza informatica, daca vrei sa fii printre cei mai buni, daca iti place sa-i ajuti pe altii sa invete, te primim cu drag in comunitatea noastra.\r\n\r\ninfoarena este un proiect sustinut de elevi, studenti si profesori din toata tara. Promovam excelenta in informatica si programare organizand concursuri online si redactand materiale educationale in domeniu.\r\n\r\nDupa aproape 5 ani de activitate, infoarena numara ~10000 membri, ~40 concursuri online, o arhiva impresionanta de 900+ probleme si continut intins pe cateva mii de pagini wiki.\r\n\r\nIn martie 2007 am aparut pe \'prima pagina a ziarului Adevarul\':stiri/infoarena-in-adevarul.\r\n\r\nSuntem reprezentati juridic de catre \'Asociatia infoarena\':asociatia-infoarena.\r\n\r\nh2. Cine lucreaza la infoarena?\r\n\r\nSite-ul este \'dezvoltat\':implica-te/development si intretinut de \'echipa infoarena\':echipa-infoarena alaturi de intreaga comunitate de utilizatori. O buna parte din ceea ce ofera infoarena astazi este rezultatul muncii a zeci de \'voluntari\':colaboratori. Incurajam utilizatorii \'sa se implice\':implica-te in dezvoltarea site-ului.\r\n\r\nh2. Demn de mentionat\r\n\r\n* infoarena dispune de un \'evaluator automat\':documentatie/evaluator care iti spune cat de bine rezolvi problemele\r\n* infoarena foloseste un sistem de \'rating\':documentatie/rating care reflecta performantele utilizatorilor in regim de concurs. \'Iata clasamentul\':clasament-rating celor mai bine cotati membri\r\n* infoarena este un \'wiki\':documentatie/wiki - oricine poate imbunatati si corecta continutul site-ului\r\n* infoarena are \'forum\':forum in care vorbim despre informatica si programare\r\n* infoarena este \'open source\':implica-te/development, codul sursa al site-ului si al evaluatorului este \'public\':http://hackers.devnet.ro/\r\n\r\nh2. Sponsori\r\n\r\ninfoarena nu are sponsori permanenti insa de-a lungul timpului am primit sprijin din partea \'Adobe Romania\':http://myadobe.ro/, \'ORACLE Romania\':http://oracle.ro/, \'Hostway\':http://www.hostwaylab.ro/, \'Microsoft Romania\':http://www.microsoft.ro/, \'IP Devel\':http://www.ipdevel.ro/, \'ICHB\':http://www.ichb.ro/, \'iRealSoft\':http://www.irealsoft.ro/, \'Totalsoft\':http://totalsoft.ro/, \'Softwin\':http://softwin.ro/ si \'SoftHost\':http://softhost.ro/. Site-ul este gazduit de \'Hostway\':http://www.hostwaylab.ro/.\r\n\r\n\'Contacteaza-ne!\':contact',75,'public',NULL,NULL),('template/algoritmiada-2010','template/algoritmiada-2010','2009-10-25 13:43:56','2009-10-27 19:27:07','==include(page=\"template/algoritmiada-2010/header\")==\r\n\r\n(vmenu)*(section) \'*Algoritmiada 2010*\':algoritmiada-2010\r\n* \'Clasament\':algoritmiada-2010/clasament\r\n* \'Organizatori\':algoritmiada-2010/comisie\r\n* \'Sponsori si premii\':algoritmiada-2010/premii\r\n* \'Regulament\':algoritmiada-2010/regulament\r\n* &nbsp;\r\n* \'Runda 1\':algoritmiada-2010/runda-1\r\n* \'Runda 2\':algoritmiada-2010/runda-2\r\n* \'Runda 3\':algoritmiada-2010/runda-3\r\n* \'Runda 4\':algoritmiada-2010/runda-4\r\n* \'Runda finala\':algoritmiada-2010/runda-finala\r\n\r\n',1792,'protected',NULL,NULL),('template/algoritmiada-2010/footer','template/algoritmiada-2010/footer','2009-10-25 13:46:53','2010-03-27 22:03:46','p{margin: 2em 1em 1em 1em; padding: 1em; height: 70px; border-top: 1px solid silver;}. \r\n!{margin-right: 1em;}<template/algoritmiada-2010?adobe.png 15%!:http://myadobe.ro/\r\n!{margin-right: 1em;}<template/algoritmiada-2010?amazon.png!:http://romania.amazon.com/\r\n!{margin-right: 1em;}<template/algoritmiada-2010?ClickBirotica.jpg 55%!:http://www.clickbirotica.ro/\r\n!{margin-right: 1em;}<template/algoritmiada-2010?Compexit.jpg!:http://www.compexit.ro/\r\n\r\nConcurs organizat in parteneriat cu \'*Amazon Romania*\':http://romania.amazon.com si \'*Adobe Romania*\':http://myadobe.ro/ si sprijinit de \'Click Birotica\':http://www.clickbirotica.ro/ si \'Compexit\':http://www.compexit.ro.\r\n',1792,'protected',NULL,NULL),('template/algoritmiada-2010/clasament-header','template/algoritmiada-2009/clasament-header','2009-10-25 14:07:52','2009-10-25 14:07:52','&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;',1792,'protected',NULL,NULL),('algoritmiada-2010/clasament/11-12','Algoritmiada 2010 - Clasament general, Clasele 11-12','2009-10-25 14:00:10','2010-03-16 21:39:08','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Clasament clasele 11-12\r\n\r\n(htabs)* \'Pe runde...\':algoritmiada-2010/clasament\r\n* \'Clasele 5-8\':algoritmiada-2010/clasament/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2010/clasament/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/studenti\r\n\r\n==include(page=\"template/algoritmiada-2010/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda1-11-12:Runda 1|algoritmiada2010-runda2-11-12:Runda 2|algoritmiada2010-runda3-11-12:Runda 3|algoritmiada2010-runda4-11-12:Runda 4\" detail_round=\"true\") == \r\n\r\n==Include(page=\"template/algoritmiada-2010/footer\")==',1490,'protected',NULL,NULL),('algoritmiada-2010/clasament/runda-1/9-10','Algoritmiada 2010 - Clasament Runda 1, Clasele 9-10','2009-10-25 14:00:10','2009-10-25 14:27:43','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda1-9-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-1\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-1/studenti\r\n*(active) \'Rezultate\':algoritmiada-2010/clasament/runda-1/9-10\r\n\r\n==include(page=\"template/algoritmiada-2010/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-1/5-8\r\n*(active) \'Clasele 9-10\':algoritmiada-2010/clasament/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-1/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda1-9-10\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1792,'protected',NULL,NULL),('algoritmiada-2010/clasament/runda-1/5-8','Algoritmiada 2010 - Clasament Runda 1, Clasele 5-8','2009-10-25 14:00:10','2009-10-25 14:36:49','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda1-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-1\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-1/studenti\r\n*(active) \'Rezultate\':algoritmiada-2010/clasament/runda-1/5-8\r\n\r\n==include(page=\"template/algoritmiada-2010/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasele 5-8\':algoritmiada-2010/clasament/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-1/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda1-5-8\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1490,'protected',NULL,NULL),('algoritmiada-2010/runda-1/11-12','Algoritmiada 2010 Runda 1, Clasele 11-12','2009-10-25 16:37:51','2009-10-25 17:26:51','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda1-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-1 \r\n* \'Clasele 5-8\':algoritmiada-2010/runda-1/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-1/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2010/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-1/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-1/11-12\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda1-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2010-runda1-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2010-runda1-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-1/11-12.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda1-11-12\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'round: algoritmiada2010-runda1-11-12',NULL,NULL),('algoritmiada-2010/runda-1/studenti','Algoritmiada 2010 Runda 1, Studenti','2009-10-25 16:37:51','2009-10-25 17:28:47','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda1-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-1 \r\n* \'Clasele 5-8\':algoritmiada-2010/runda-1/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-1/11-12\r\n*(active) \'Studenti\':algoritmiada-2010/runda-1/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-1/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda1-studenti\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2010-runda1-studenti\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2010-runda1-studenti\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-1/studenti.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda1-studenti\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'round: algoritmiada2010-runda1-studenti',NULL,NULL),('algoritmiada-2010/runda-1/solutii','Solutii Algoritmiada 2010 Runda 1','2009-10-25 16:37:52','2009-11-22 21:09:55','h1. Solutii Algoritmiada 2010, Runda 1\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Iopds\':algoritmiada-2010/runda-1/solutii#iopds\r\n* \'Perle2\':algoritmiada-2010/runda-1/solutii#perle2\r\n* \'Studenti\':algoritmiada-2010/runda-1/solutii#studenti\r\n* \'Pitici4\':algoritmiada-2010/runda-1/solutii#pitici4\r\n* \'Vrejuri\':algoritmiada-2010/runda-1/solutii#vrejuri\r\n* \'Arborest\':algoritmiada-2010/runda-1/solutii#arborest\r\n* \'Kss\':algoritmiada-2010/runda-1/solutii#kss\r\n* \'Tester\':algoritmiada-2010/runda-1/solutii#tester\r\n\r\n==include(page=\"algoritmiada-2010/runda-1/solutii/iopds\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-1/solutii/perle2\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-1/solutii/studenti\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-1/solutii/pitici4\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-1/solutii/vrejuri\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-1/solutii/arborest\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-1/solutii/kss\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-1/solutii/tester\")==',1792,'public',NULL,NULL),('algoritmiada-2009/clasament/runda-1/5-8','Algoritmiada 2009 - Clasament Runda 1, Clasele 5-8','2008-11-30 18:03:47','2008-11-30 18:03:47','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda1-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-1\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-1/studenti\r\n*(active) \'Rezultate\':algoritmiada-2009/clasament/runda-1/5-8\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasele 5-8\':algoritmiada-2009/clasament/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-1/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda1-5-8\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('algoritmiada-2010/runda-1/5-8','Algoritmiada 2010 - Runda 1, Clasele 5-8','2009-10-25 16:37:51','2009-10-25 17:23:32','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda1-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-1 \r\n*(active) \'Clasele 5-8\':algoritmiada-2010/runda-1/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-1/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-1/5-8\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda1-5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2010-runda1-5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2010-runda1-5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-1/5-8.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda1-5-8\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'round: algoritmiada2010-runda1-5-8',NULL,NULL),('algoritmiada-2010/runda-1/9-10','Algoritmiada 2010 - Runda 1, Clasele 9-10','2009-10-25 16:37:51','2009-10-25 17:25:30','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda1-9-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-1 \r\n* \'Clasele 5-8\':algoritmiada-2010/runda-1/5-8 \r\n*(active) \'Clasele 9-10\':algoritmiada-2010/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-1/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-1/9-10\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda1-9-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2010-runda1-9-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2010-runda1-9-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-1/9-10.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda1-9-10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'round: algoritmiada2010-runda1-9-10',NULL,NULL),('algoritmiada-2010/clasament/runda-3/5-8','Algoritmiada 2010 - Clasament Runda 3, Clasele 5-8','2010-01-18 11:55:37','2010-03-16 21:31:30','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda3-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-3\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-3/studenti\r\n*(active) \'Rezultate\':algoritmiada-2010/clasament/runda-3/5-8\r\n\r\n==include(page=\"template/algoritmiada-2010/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasele 5-8\':algoritmiada-2010/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-3/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda3-5-8\" detail_task=\"true\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1490,'protected',NULL,NULL),('algoritmiada-2010/runda-4','Algoritmiada 2010 - Runda 4','2009-10-25 16:32:24','2010-03-21 08:27:47','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Algoritmiada 2010, Runda 4\r\n\r\n(htabs)*(active) \'Despre...\':algoritmiada-2010/runda-4 \r\n* \'Clasele 5-8\':algoritmiada-2010/runda-4/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-4/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-4/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-4/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-4/5-8 \r\n\r\nRunda va incepe *Duminica 21 martie*, la ora {*11^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 11^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-4/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-4/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-4/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-4/studenti\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':algoritmiada-2010/runda-4/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-4/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-4/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-4/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-4/studenti\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"77\" count=\"5\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"ditzonec\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"filipb\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"victorsb\" type=\"tiny\")==\r\n* ==User(user=\"devilkind\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica sau tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('algoritmiada-2010/runda-4/5-8','Algoritmiada 2010 - Runda 4, Clasele 5-8','2010-02-21 12:43:08','2010-02-21 13:18:49','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda4-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-4 \r\n*(active) \'Clasele 5-8\':algoritmiada-2010/runda-4/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-4/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-4/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-4/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-4/5-8\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda4-5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2010-runda4-5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2010-runda4-5-8\" param=\"duration\" strong=\"true\")== ore. \r\n\r\n== RoundTimer(round_id=\"algoritmiada2010-runda4-5-8\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-4/5-8.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda4-5-8\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'round: algoritmiada2010-runda4-5-8',NULL,NULL),('algoritmiada-2010/clasament/runda-1/11-12','Algoritmiada 2010 - Clasament Runda 1, Clasele 11-12','2009-10-25 14:00:10','2009-10-25 14:30:02','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda1-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-1\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-1/studenti\r\n*(active) \'Rezultate\':algoritmiada-2010/clasament/runda-1/11-12\r\n\r\n==include(page=\"template/algoritmiada-2010/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-1/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2010/clasament/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-1/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda1-11-12\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1792,'protected',NULL,NULL),('algoritmiada-2010/clasament/runda-1/studenti','Algoritmiada 2010 - Clasament Runda 1, Studenti','2009-10-25 14:00:10','2009-10-25 14:31:55','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda1-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-1\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-1/studenti\r\n*(active) \'Rezultate\':algoritmiada-2010/clasament/runda-1/studenti\r\n\r\n==include(page=\"template/algoritmiada-2010/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-1/11-12\r\n*(active) \'Studenti\':algoritmiada-2010/clasament/runda-1/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda1-studenti\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1792,'protected',NULL,NULL),('algoritmiada-2010/regulament','Algoritmiada 2010 - Regulament','2009-10-25 15:56:28','2009-10-26 17:12:04','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Regulament\r\n\r\nSe recomanda, pe langa citirea acestui regulament, citirea \"regulamentului\":regulament general infoarena.\r\n\r\n\'Echipa infoarena\':echipa-infoarena isi rezerva dreptul de a modifica prezentul regulament pe parcursul desfasurarii concursului. Daca apar prevederi noi sau daca anumite prevederi ale regulamentului sunt modificate sau eliminate, atunci acestea vor fi anuntate pe site-ul concursului. Orice modificare a regulamentului va intra in vigoare, in functie de situatie, fie din momentul publicarii ei, fie dupa incheierea rundei aflate in desfasurare. In momentul anuntarii modificarii va fi precizat si momentul din care aceasta intra in vigoare.\r\n\r\nh2. Dreptul de participare\r\n\r\nPersoanele care fac parte din \'echipa infoarena\':echipa-infoarena cat si alti contribuitori implicati direct in organizarea concursului *Algoritmiada 2010* nu au dreptul de a participa. Exceptie la aceasta regula sunt acele persoane din afara \'echipei infoarena\':echia-infoarena care propun probleme la alte categorii de varsta decat categoriile la care participa. De asemenea, orice concurent care are un comportament considerat inadecvat fata de echipa infoarena sau fata de alti concurenti va fi descalificat. Un concurent se poate califica la finala doar daca se incadreaza ca varsta in grupa la care a concurat (aceasta verificare se va face prin prezentarea unei dovezi legale care il incadreaza pe concurent la acea grupa).\r\n\r\nh2. Repartizarea\r\n\r\nToti participantii vor fi repartizati in *4* grupe, in concordanta cu varsta lor. Repartizarea se face astfel:\r\n\r\n* Clasele 5-8\r\n* Clasele 9-10\r\n* Clasele 11-12 \r\n* Studenti (facultate, masterat, doctorat)\r\n\r\nOricine poate participa la o alta grupa decat cea la care se incadreaza, dar calificarea la finala cat si impartirea premiilor se va face conform regulamentului, fara nici o exceptie.\r\n\r\nh2. Inscriere\r\n\r\nTot ce trebuie sa faceti pentru a participa la concursul *Algoritmiada 2010* este sa aveti un cont la infoarena. Inregistrarea se poate face pe site-ul infoarena. Acelasi cont va fi folosit pentru a accesa forum-ul.\r\n\r\nh2. Runde\r\n\r\nVor exista *4* runde de calificare, iar in urma clasamentului stabilit primii de la fiecare grupa vor fi selectati pentru etapa finala desfasurata in cadrul unei tabere. Cele *4* runde vor avea loc duminica, incepand cu ora 9:00, desi pot interveni exceptii. Durata lor va fi de 4 ore. Un program detaliat poate fi gasit pe pagina \"principala a concursului\":algoritmiada-2010. La runda finala se vor califica un numar variabil de participanti in functie de categorie, cei mai bine clasati in clasamentul total al rundelor online. La fiecare categorie, vor exista minim 10 finalisti.\r\n\r\nh2. Intrebari\r\n\r\nIn prima ora vor putea fi formulate eventualele intrebari, pe forum, in topicurile special create. Orice intrebare pusa in alt mod (primita ca personal message, pe mail, etc.) va fi ignorata. Raspunsuri vor fi oferite doar la intrebarile puse in prima ora . Intrebarile trebuie formulate astfel incat sa se poate raspunda cu _DA_ sau _NU_. In caz contrar sau in cazul in care raspunsul se afla in textul problemei se va raspunde cu _NO COMMENT_. Nu vor exista exceptii de la aceste reguli. Daca echipa va considera ca raspunsul la o anumita intrebare este de interes general si clarifica anumite aspecte, atunci se va face un anunt general prin intermediul forumului. \r\n\r\nh2. Trimiterea solutiilor\r\n\r\nTrimiterea solutiilor se va face prin intermediul interfetei site-ului infoarena.\r\nOdata autentificati in contul vostru, veti putea selecta arhiva la care doriti sa lucrati (in cazul acesta una din arhivele {*Algoritmiada 2010*}) si veti putea folosi link-ul \"Trimite solutii\".\r\n\r\nh2. Evaluare\r\n\r\nEvaluarea solutiilor (\"mai multe detalii aici\":documentatie/evaluator) trimise se face in timp real, insa punctajele nu vor fi facute publice decat la incheirea rundei de concurs. Veti putea vizualiza pozitia ocupata in clasament dupa terminarea rundei in rubrica Clasament.\r\n\r\nSe recomanda sa instalati pe calculatorul vostru aceleasi versiuni de compilatoare ca cele specificate la link-ul de mai sus. \'Echipa infoarena\':echipa-infoarena nu este responsabila pentru diferentele intre versiuni de compilatoare si nu va efectua reevaluari in astfel de cazuri.\r\n\r\nh2. Contestatii\r\n\r\nEchipa infoarena isi rezerva dreptul de a reevalua orice problema in situatia in care se detecteaza erori in teste sau in programul de verificare dupa evaluare. Cum testele problemelor nu vor fi facute publice, posibilitatile de a contesta sunt limitate. Pentru a asigura o evaluarea corecta, echipa infoarena va garanteaza ca va testa intens toate problemele inainte de concurs si ca va verifica corectitudinea procesului de evaluare dupa terminare. In caz ca totusi aveti o contestatie, aceasta trebuie trimisa pe mail la adresa _paul -at- infoarena.ro_ in termen de 24 de ore de la afisarea rezultatelor rundei curente pe site. Ele vor fi rezolvate in termen de maxim 5 zile, iar dupa rezolvarea lor rezultatele vor fi declarate finale.\r\n\r\nh2. Solutii\r\n\r\nLa scurt timp dupa terminarea evaluarii se va publica un articol cu solutiile pentru problemele rundei respective. Testele utilizate pentru evaluare nu vor fi facute publice.\r\n\r\nh2. Transferul problemelor\r\n\r\nProblemele vor fi mutate dupa evaluare in \'Arhiva de probleme\':arhiva infoarena, avand astfel la dispozitie un evaluator 24 din 24 si posiblitatea de a finisa solutiile la problemele nerezolvate in timpul concursului.\r\n\r\nh2. Trisare\r\n\r\n*Algoritmiada 2010* este un concurs individual, asadar orice tentativa de colaborare va aduce descalificarea celor implicati. \'Echipa infoarena\':echipa-infoarena isi rezerva dreptul de a verifica sursele concurentilor, iar in caz ca se descopera surse aproximativ identice, concurentii respectivi vor fi descalificati din concurs. Aceeasi masura va fi aplicata si celor care concureaza sub un alt nume decat cel adevarat. In cazul unui atac asupra sistemului de evaluare sau asupra paginilor infoarena utilizatorul vinovat va fi descalificat din concurs, iar contul sau infoarena va fi suspendat definitiv. Echipa infoarena mai poate stabili si alte masuri de pedepsire in alte situatii, in functie de gravitatea prejudiciilor cauzate.\r\n\r\n==Include(page=\"template/algoritmiada-2010/footer\")==',3146,'protected',NULL,NULL),('blog/conducere-noua','Conducere nouă pentru infoarena!','2009-10-26 21:31:33','2009-11-11 15:40:30','Că tot se apropie alegerile prezendiţiale, avem veşti bune pentru voi: infoarena şi-a ales deja preşedintele :) El este: ==user(user=\"gcosmin\")==!\r\n\r\nCosmin a preluat ştafeta de la ==user(user=\"wickedman\")==, care a fost preşedintele infoarena încă din 2003. Sub mandatul lui Cristi s-au realizat multe lucruri, dar aşa cum a spus chiar el, cel mai important este faptul că infoarena este un proiect viu! În jurul site-ului şi al Asociaţiei v-aţi adunat voi, tinerii pasionaţi de informatică din România. Acest lucru ne dă încredere ca infoarena va exista pentru multe generaţii de acum încolo şi că va rămâne o sursă importantă în pregătirea voastră, a viitorilor specialişti IT ai României.\r\n\r\nÎncepând cu anul acesta, conducerea infoarena este aleasă în fiecare an conform procedurii descrise \'aici\':propuneri/13-presedinte. Noi sperăm că acest lucru să asigure continuitate şi, în acelaşi timp, o infuzie de idei noi şi de energie în proiectele întreprinse de echipa infoarena. \r\n\r\nLa primele alegeri \"prezidenţiale\" infoarena, Cosmin a câştigat mandatul în unanimitate. El ne-a convins prin seriozitate şi prin iniţiativă pe tot parcursul anului trecut.\r\n\r\nCosmin a ales 3 vicepreşedinţi care sunt responsabili de cele 3 mari \"direcţii\" infoarena:\r\n\r\n* Algoritmiada -- ==user(user=\"pauldb\")==\r\n* Content (arhivă, concursuri online, articole) -- ==user(user=\"stef2n\")==\r\n* Development -- ==user(user=\"bogdan2412\")==\r\n\r\nBogdan, Ştefan şi Paul s-au remarcat prin contribuţii substanţiale la infoarena încă de când s-au alăturat echipei.\r\n\r\nSă le urăm cu toţii cât mai multe realizări pe parcursul următorului mandat!\r\n\r\nÎn final aş vrea să subliniez că orice vor întreprinde ei, în calitate de lideri infoarena, poate avea un impact mult mai mare dacă vă implicaţi şi voi. Nu uitaţi că oricine contribuie consistent poate ajunge în echipa şi chiar preşedintele infoarena!',15,'protected',4215,NULL),('utilizator/leva','Profil leva','2009-10-29 10:41:50','2009-10-29 10:41:50','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',11024,'public',NULL,NULL),('utilizator/andrei-alpha','Profil andrei-alpha','2007-12-03 16:13:32','2009-12-16 12:57:00','',7271,'public',NULL,NULL),('blog/problema-saptamanii-subgrup-de-persoane','Problema saptamanii - Subgrupuri de 3 persoane','2009-10-30 19:44:38','2009-10-30 19:51:36','Recent am aflat urmatoarea problema draguta de la ==user(user=\"Cosmin\")==:\r\n\r\n_Sa se demonstreze ca intr-un grup de 6 persoane, exista cel putin un subgrup de 3 persoane in care toti membri subgrupului se cunosc intre ei sau niciun membru nu ii cunoaste pe ceilalti doi._\r\n\r\nEu va propun urmatoarea varianta modificata:\r\n\r\n_Sa se demonstreze ca intr-un grup de 6 persoane, exista cel putin *doua* subgrupuri de 3 persoane in care toti membri subgrupului se cunosc intre ei sau niciun membru nu ii cunoaste pe ceilalti doi._\r\n\r\nAstept solutiile voastre la adresa andrei.grigorean at gmail.com',2028,'protected',4219,NULL),('runda/cnrv_4/clasament','Clasament cnrv_4','2009-10-31 10:42:01','2009-10-31 10:42:01','h1. Clasament ==roundparam(round_id=\"cnrv_4\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"cnrv_4\")==',5748,'round: cnrv_4',NULL,NULL),('runda/cnrv_4','CNRV - pregatire la info - Editia #4','2009-10-31 10:42:01','2009-10-31 10:48:39','h1. == roundparam(round_id=\"cnrv_4\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cnrv_4\") ==\r\n\r\n\"Factorial\", \"Numarare triunghiuri\", \"Ciurul lui Erathostene\" si \"Alee\" au fost discutate in clasa. \"Romeo si Julieta\" si \"Muzeu\" se rezolva cu Lee. Spor la lucru!\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cnrv_4/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cnrv_4\" score=\"1\")==',5748,'round: cnrv_4',NULL,NULL),('utilizator/maoo','Profil maoo','2009-10-31 19:22:12','2009-10-31 19:22:12','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',11046,'public',NULL,NULL),('runda/a_b','a_b','2010-03-26 12:14:04','2010-03-26 12:14:04','h1. == roundparam(round_id=\"a_b\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"a_b\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"a_b\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"a_b\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"a_b\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/a_b/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"a_b\" score=\"1\")==',8967,'round: a_b',NULL,NULL),('okr/20094/organizeaza-concursuri','okr/20094/organizeaza-concursuri','2009-11-02 19:31:57','2009-11-02 19:31:57','(okr)* Organizam 1 concurs cu probleme propuse de comunitate',1490,'public',NULL,NULL),('okr/20094/devel-ia2','okr/20094/devel-ia2','2009-11-02 19:35:18','2009-11-27 08:42:11','(okr)* Lansam infoarena 2.3\r\n** Implementam taguri\r\n** Organizam un Coding Camp cu echipa infoarena',1490,'public',NULL,NULL),('l','Hobby','2009-11-03 10:33:40','2009-11-03 10:33:40','Football\r\nGym\r\nClubbing',8774,'public',NULL,NULL),('okr/20094/adauga-probleme','okr/20094/adauga-probleme','2009-11-03 12:13:56','2009-11-03 12:13:56','(okr)* Sporirea numarului de probleme din cele 2 arhive\r\n** Adaugarea a 10 noi probleme in arhiva educationala.\r\n** Identificarea a 3 surse de probleme importante pentru arhiva principala.',2044,'public',NULL,NULL),('okr/20094/articole','okr/20094/articole','2009-11-03 12:34:06','2009-11-03 12:34:06','(okr)* Crearea de nou continut educational.\r\n** Aparitia a 4 articole noi.\r\n** Transformarea \'training path-ului\':training-path intr-o serie de pagini in care sa fie agregate resursele externe pentru categoria respectiva.',2044,'public',NULL,NULL),('okr/20094/tagging','okr/20094/tagging','2009-11-03 14:33:35','2009-11-27 08:42:41','(okr)* Avem sistem de taguri functional pentru probleme\r\n** Redactat IAP pentru cum ar trebui sa arate interfata pentru utilizatori\r\n** Implementat efectiv interfata si functionalitate de search\r\n** Adaugat tag-uri unui subset de probleme si lansam\r\n',1490,'public',NULL,NULL),('art','art','2009-11-03 15:13:04','2010-02-17 20:40:24','Nimic in aceasta pagina.',11775,'public',NULL,NULL),('planificare/sedinta-20091023','Ședință 2009-10-23','2009-10-20 12:14:02','2009-11-04 00:20:53','h1. Şedinţă 2009-10-23\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Vineri* la ora *19^00^* la Cafepedia de la Universitate.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== dupa 16:00\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada 2010 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| Parteneriat media cu AI contest in Poli | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| Tabăra infoarena | ==user(user=\"wickedman\" type=\"tiny\")== |\r\n| Stare Evaluator | ==user(user=\"svalentin\" type=\"tiny\")== |\r\n| Colaborare Poli | ==user(user=\"svalentin\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* S-a votat IAP #13\r\n* Cristi vorbeste cu Buraga legat de sponsorizare %{color:red}(mail sent)%\r\n* Silviu face blog post despre noul Presedinte %{color:red}(done)%\r\n* Cristian ii face card Cristinei si lui Cosmin.\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")== vicepresedinte responsabil cu Development\r\n* ==user(user=\"pauldb\" type=\"tiny\")== vicepresedinte responsabil cu Algoritmiada\r\n* ==user(user=\"stef2n\" type=\"tiny\")== vicepresedinte responsabil cu Content\r\n* Bogdan se ocupa de organizat concursuri\r\n* Bogdan scrie tickete pentru fixuri la Virtual Contest %{color:red}(done)%\r\n* Prostu se ocupa de Calendar\r\n* Stefan vorbeste cu Marius despre Articole %{color:red}(done)%\r\n* Moare \"IAP #7\":propuneri/7-community-ladder, Cristi actualizeaza status %{color:red}(done)%\r\n* Cosmin scrie newsletter de acum\r\n* Cosmin se ocupa de Strangere Fonduri\r\n* Cosmin vorbeste cu Tibi despre Development %{color:red}(done)%\r\n* Bogdan e responsabil de Taguri\r\n* Cristi intreaba la Hostway daca ne mai dau o masina virtuala %{color:red}(done, ne dă Sergiu)%\r\n* Vali face testing pe masina virtuala\r\n* pe 22 noiembrie va fi prima runda de Algoritmiada\r\n* Cosmin, Silviu si Vali fac mapa pentru sponsori pana la *sfarsitul lunii*\r\n* Silviu trimite bugetul lui Paul %{color:red}(done)%\r\n* Cristi da reply la Amazon %{color:red}(done)%\r\n* Paul face pagini si buget pentru algoritmiada pana la sfarsitul lunii %{color:red}(2/2 done)%\r\n* Cosmin vorbeste cu Cristina despre comunicate de presa %{color:red}(done)%\r\n* Cosmin vorbeste la Orange Concept Store %{color:red}(done)%\r\n* Vali vorbeste cu Vlad Posea despre colaborare si daca ne poate ajuta cineva cu jailrun java\r\n* Silviu vorbeste cu Octavian Voicu despre AI Contest %{color:red}(mail sent)%\r\n\r\nh2(#notite). Notite\r\n\r\n* Cristi i-a dat lui Vali 23 RON pentru bilet tren Algoritmiada 2009\r\n* Se scrie retry loop pentru eval\r\n* Cristi plateste 120 RON pentru consumatie',1792,'protected',NULL,NULL),('okr/20094/algoritmiada','OKR 2009-4 Algoritmiada','2009-11-02 18:17:39','2009-12-15 17:02:12','(okr)* Organizare Algoritmiada 2010, chestiuni generale\r\n** Stabilirea unei echipe (~10 oameni) care sa formeze comisia stiintifica a concursului\r\n** Crearea si organizarea paginilor necesare pentru concurs\r\n** Stabilirea bugetului\r\n** Contactarea unor posibili sponsori\r\n** Promovarea concursului\r\n\r\n(okr)* Organizare Algoritmiada 2010, Runda 1\r\n** Newsletter Runda 1\r\n** Blogpost Runda 1\r\n\r\n(okr)* Organizare Algoritmiada 2010, Runda 2\r\n** Newsletter Runda 2\r\n** Blogpost Runda 2',1792,'protected',NULL,NULL),('algoritmiada-2010/comisie','Algoritmiada 2010 - Organizatori','2009-10-25 15:48:30','2010-03-27 16:50:42','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Organizatori\r\n\r\n\'Echipa infoarena\':echipa-infoarena se ocupa de organizarea si desfasurarea concursului *Algoritmiada 2010*.\r\n\r\nh2. Organizare \r\n\r\n* == user(user=\"pauldb\" type=\"tiny\") == : coordonator concurs\r\n* == user(user=\"gcosmin\" type=\"tiny\") == : fonduri, sponsori, presa\r\n* == user(user=\"bogdan2412\" type=\"tiny\") == : coordonator tehnic (site-ul, evaluatorul etc.)\r\n\r\nh2. Echipa stiintifica\r\n\r\nCei care se vor ocupa de buna desfasurarea a concursului din punct de vedere stiintific (redactarea si compunerea problemelor, realizarea testelor, clarificarea intrebarilor, etc.) sunt:\r\n\r\n* ==user(user=\"pauldb\" type=\"tiny\")== \r\n* ==user(user=\"prostu\" type=\"tiny\")== \r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"marius\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"ditzoneC\" type=\"tiny\")==\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"cosmin\" type=\"tiny\")==\r\n* == user(user=\"devilkind\" type=\"tiny\") ==\r\n\r\nh2. Multumim\r\n\r\n* Si in acest an ii multumim lui ==user(user=\"vlad_D\")== pentru logo-ul concursului.\r\n\r\n==Include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('sidebar-ad','Sidebar ','2007-09-17 07:15:20','2009-11-22 11:09:42','p=. !http://infoarena.ro/static/images/stars/small-full.png! \'*Fii un bun _infoarenaut_! Implica-te!*\':implica-te',1490,'protected',NULL,NULL),('pd','Tehnici avansate de programare dinamică','2007-12-04 21:25:10','2010-03-28 01:11:52','h1. Tehnici avansate de programare dinamică\r\n\r\n(Categoria _Tehnici de programare_, autori _Catalin Tiseanu_, _Andrei Homescu_)\r\n\r\nTODO://ok..to do...dar do mai repede...k e foarte bun articolul si vreau sa citesc si partea cealalta...e pacat sa lasati articolul neterminat asa...vede lumea...bine..e si funny ;)) peace out ;)  \r\n\r\n1. Reparat link de la ugly numbers\r\n\r\nPlan de atac (probleme-candidat):\r\n\r\n1. http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en (Reducerea complexitatii, transformarea problemei intr-una de construire a unui arbore binar.)\r\n\r\n2. http://code.google.com/codejam/contest/dashboard?c=32001#s=p0&a=3 (Boolean tree, programare dinamica simpla pe arbore binar.)\r\n\r\n3. http://code.google.com/codejam/contest/dashboard?c=32001#s=p3&a=3 (PermRLE, permutari cu N*2^N)\r\n\r\n4. http://code.google.com/codejam/contest/dashboard?c=32010#s=p3&a=3 (problema cu DP pe matrici, aplicam ridicarea la putere pt calcul rapid)\r\n\r\n5. http://infoarena.ro/problema/doipatru (joc cu solutie DP, stare in 6 dimensiuni)\r\n\r\nh2. Sugestii Silviu\r\n\r\n* poate ca nu trebuie sa spunem tot despre programare dinamica intr-un singur articol; spre exemplu putem facem doua articole: PD basic si PD advanced\r\n* cred ca era si ceva prin Cartea lui Francu\' despre programare dinamica; ar merge incorporat (eventual in pd_basic).\r\n\r\nh2. Introducere\r\n\r\nProgramarea dinamică este o metodă utilă pentru a rezolva probleme care pot fi obţinute prin compunerea a mai multor bucăţi, a căror soluţie poate fi apoi determinată optim. Se bazează în principal pe proprietatea unei probleme de a putea fi rezolvată optim dacă se cunosc soluţii optime la sub-problemele ei.\r\nDe menţionat că \'programare\' nu se referă aici la scrierea de cod într-un limbaj de programare, ci la \'programare matematica\', care constă în optimizarea unei funcţii prin alegerea de valori dintr-o mulţime anume. \r\n\r\nScopul acestui articol nu este să ofere o introducere in programare dinamică (pentru aceasta poate fi consultat excelentul tutorial de pe TopCoder \"Dynamic Programming : From novice to advanced\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg). În schimb, acest articol îşi propune să ofere nişte \'smenuri\' mai avansate de rezolvare a problemelor cu programare dinamică. \r\n\r\nh2. Reducerea loop-ului interior\r\n\r\nÎn problemele de programare dinamică de multe ori prima complexitate obţinută nu este optimă. Mai exact, recurenţa obţinută iniţial poate fi îmbunătăţită sau calculată mai rapid. De multe ori, pentru aceasta se optimizeaza loop-ul interior din calculul recurenţei. Acest lucru se poate face bazat fie pe observaţii specifice problemei, fie pe tehnici mai clasice.\r\n\r\nSă considerăm următoarea problema:\r\n\r\nh3(#problema-1). Problema 1: \'Drilling\':http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en (Algorithmic Engagements 2009, Round 3)\r\n\r\nbq. Se da un şir de $N$ numere naturale $(a{~1~}, a{~2~}, ..., a{~N~})$. Se ştie că un prefix al acestui şir (adică o subsecvenţă de la începutul şirului, posibil nulă) este **defect**. Toate elementele din acel prefix (şi doar din acel prefix) sunt defecte. Se ştie de asemenea că se poate testa orice poziţie $i$ în timp $a{~i~}$ pentru a afla dacă este defectă. Să se determine timpul minim în cazul cel mai defavorabil pentru aflarea lungimii maxime a prefixului şirului care este defect.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(8 24 12 6)$, răspunsul ar fi $42$. Astfel, se testează mai întâi poziţia $2$. Dacă nu este defectă, mai rămâne de testat poziţia $1$. Altfel, în cel mai rău caz mai trebuie testate poziţiile $3$ şi $4$, aducând timpul total la $24 + 12 + 6 = 42$.\r\n\r\nh3. Rezolvare:\r\n\r\nO să începem prin a da altă îmbrăcăminte problemei. Astfel, să ne imaginăm că am construi un arbore binar de căutare pe şirul dat, având drept chei poziţiile din şir, şi drept valori auxiliare valorile poziţiilor respective din şir (un nod cu cheia $i$ va avea valoarea auxiliara $a{~i~}$.\r\nAcum, există mulţi arbori binari de căutare posibile pentru şirul iniţial. Totuşi, să presupunem că am construit unul, pe care îl considerăm de acum ca fixat. Atunci, strategia noastra de testare a elementelor din şir se va desfăşura conforma arborelui. Astfel, testăm mai întâi în poziţia din rădăcină. Dacă poziţia respectivă este defectă, ne ducem în fiul drept. Altfel, mergem in fiul stâng. În ambele cazuri se reia procedeul. Căutarea se termină cand nu mai putem merge într-un fiu. \r\n\r\nSă observăm că dacă considerăm costul unui drum în arbore de la rădăcină la o frunză ca suma valorilor auxiliare din drumul (unic) respectiv, atunci se observă că costul strategiei bazate pe acest arbore este chiar costul maxim al unui drum ! De acum încolo, vom defini costul unui arbore ca costul maxim al unui drum de la rădăcină la o frunză. Să exemplificăm pe şirul din exemplu:\r\n\r\np=. !pd?Diagram1.png!\r\n\r\np=. _Fig. 1: În paranteză sunt valorile auxiliare ataşate cheilor_\r\n\r\nSe observă că costul maxim al unui drum este $42$, minim posibil, exact ca răspunsul din exemplu. Deci, am redus problema la construirea unui arbore binar de căutare, care are costul minim.\r\n\r\nAcum devine clară o primă soluţie folosind programarea dinamică. Astfel, să presupunem că notăm cu $opt[ i ][ j ]$ costul minim al unui arbore construit pe cheile din $[i,j]$ (prin asta notăm (i, i + 1, ..., j). Fie $r[ i ][ j ]$ poziţia rădăcinii arborelui cu costul minim. În cazul existenţei mai multor rădăcini posibile, se alege cea mai din stânga. Cum am putea construi arborele de cost minim pe cheile $[i,j]$ ştiind răspunsul pentru instanţele mai mici (subsecvenţele de lungime mai mică ca $j-i+1$ pe $[i,j]$)? (!) Simplu, arborele de cost minim pe $[i,j]$ se obţine alegând drept rădăcină în mod optim o poziţie $k$, cu <tex>$i \\le k \\le j$</tex>, la care se pune ca fiul stâng arborele optim pentru $[i, k-1]$, şi ca fiu drept arborele optim pentru $[k+1, j]$. Relaţia de recurenţă devine:\r\n\r\n$opt[ i ][ j ]$ = <tex>\\displaystyle\\min_{i \\le k \\le j} \\{a_{k} + \\max( opt[i][k-1], opt[k+1][j] )\\} </tex>   \r\n$r[ i ][ j ]$ = <tex>\\displaystyle\\arg \\min_{i \\le k \\le j}\\{a_{k} + \\max (opt[i][k-1], opt[k+1][j] )\\} </tex> \r\n\r\nAvem @opt[i][j] = 0@, pentru $j < i$.\r\nCazurile de bază sunt @opt[i][i]@ = a{~i~} si @r[i][i] = i@.\r\n\r\nSe observă că răspunsul problemei se află în @opt[1][N]@.\r\nAstfel, am obţinut o soluţie în timp $O(N^3)$.\r\n\r\nAici trebuie remarcată asemănarea acestei probleme cu cea a determinării arborelui de căutare optim, atunci cand se dau probabilităţile relative de căutare a cheilor. Această problemă se numeşte \'Optimal Binary Search Tree\' în literatura de specialitate şi poate fi găsită şi în _Introduction to Algorithms_. În aceasta problemă, se poate aplica o reducere a complexităţii datorită faptului că <tex>$ r[i][j-1] \\le r[i][j] \\le r[i+1][j] $</tex> pentru a reduce complexitatea la $O(N^2)$. Această proprietate nu se poate aplica din păcate şi în cazul problemei noastre.\r\n\r\nPână acum avem următorul pseudocod pentru calculul recurenţei:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    iniţializează opt şi r\r\n    pentru len = 1, N execută\r\n        pentru i = 1, N - len + 1 execută\r\n            j = i + len - 1;\r\n            opt[i][j] = inf;\r\n            pentru k = i, j execută\r\n                dacă opt[i][j] < a[k] + max(opt[i][k-1], opt[k+1][j]) atunci\r\n                    opt[i][j] = a[k] + max(opt[i][k-1], opt[k+1][j]);\r\n                    r[i][j] = k;\r\n            sfârşit_pentru;\r\n       sfârşit_pentru;\r\n    sfârşit_pentru;\r\n\r\n    return opt[1][N];\r\nSfârşit.\r\n==\r\n\r\nAcum ca să obţinem o complexitate mai bună, ţinând cont şi de numele capitolului, vom încerca să reducem complexitatea loop-ului interior (cel după $k$).\r\nSă ne uităm mai atent la acest loop.\r\n\r\nFie un interval $[i,j]$ fixat. Acum, $opt[i][j] < opt[i][j\']$, pentru orice $j < j\'$. Similar, $opt[i][j] < opt[i\'][j]$, pentru orice $i\' < i$.\r\nAtunci, există un indice $k$, <tex>$i \\le k \\le j$</tex> astfel încât $max(opt[i][o-1], opt[o+1][j]) = opt[o+1][j]$, pentru orice <tex>$i \\le o \\le k$</tex>, şi $max(opt[i][o-1], opt[o+1][j]) = opt[i][o-1]$ pentru orice <tex>$k \\le o \\le j$</tex>. După cum ştim, trebuie să aflăm <tex>\\displaystyle\\min_{i \\le k \\le j} \\{a_{k} + \\max( opt[i][k-1], opt[k+1][j] )\\} </tex>. Să definim acum 3 matrici auxiliare:\r\n\r\n@to_left[ i ][ j ]@ = $a{~i~} + opt[ i + 1 ][ j ]$\r\n@to_right[ i ][ j ]@ = $a{~j~} + opt[ i ][ j - 1 ]$\r\n@inter[ i ][ j ]@ = <tex>\\displaystyle\\arg \\max_{i \\le k \\le j}\\{opt[i][k-1] \\le opt[k+1][j]\\} </tex>\r\n\r\nSe observă că $inter[i][j]$ nu reprezintă altceva decât indicele $k$ tratat in paragraful precedent.\r\nDe asemenea, $inter$ poate fi calculată în $O(N^2)$ observând o proprietate simplă: <tex>$ inter[i][j-1] \\le inter[i][j] \\le inter[i+1][j] $</tex>. Aceasta reiese imediat din monotonia lui $opt$ discutată mai sus. Pseudocodul pentru calculul lui $inter$ este:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    iniţializează opt, inter şi r\r\n    pentru len = 1, N execută\r\n        pentru i = 1, N - len + 1 execută\r\n            j = i + len - 1;\r\n            calculează opt[i][j]\r\n            pentru k = inter[i][j-1], inter[i+1][j] execută\r\n                dacă opt[i][k-1] <= opt[k+1][j] atunci\r\n                    inter[i][j] = k;\r\n            sfârşit_pentru;\r\n       sfârşit_pentru;\r\n    sfârşit_pentru;\r\nSfârşit.\r\n==\r\n\r\nDe menţionat că trebuie avut grijă la cazul când $len$ este mai mic ca $3$. Pseudocodul prezentat mai sus este orientativ.\r\nSă vedem acum de ce această modalitate de calcul a lui $inter$ duce la o complexitate de $O(N^2)$.\r\n\r\nAlternativ, se poate căuta binar $inter[i][j]$ pentru orice $[i,j]$.\r\n\r\nAcum vine ideea decisivă pentru a reduce complexitatea loop-ului: pentru a afla $opt[i][j]$, este suficient să aflăm minimul dintre 2 valori:\r\n\r\n* <tex>\\displaystyle\\min_{i \\le k \\le inter[i][j]} \\{$to\\_left[k][j]$\\} </tex> şi\r\n* <tex>\\displaystyle\\min_{inter[i][j] < k \\le j } \\{$to\\_right[i][k]$\\} </tex>\r\n\r\nMai exact,\r\n\r\n@opt[ i ][ j ]@ = <tex> \\min( \\displaystyle\\min_{i \\le k \\le inter[i][j]} \\{$to\\_left[k][j]$\\},\r\n                              \\displaystyle\\min_{inter[i][j] < k \\le j } \\{$to\\_right[i][k]$\\} ) </tex>\r\n\r\nDiferenţa faţă de prima recurentă este evidentă: acum trebuie să aflăm minimul pe un interval de linii, în cazul $to_left$, şi minimul pe un interval de coloane, în cazul $to_right$. Atât aflarea mnimului pe un interval, cât şi update-ul acestei valori se poate face în $O(logN)$, folosind \'arbori de intervale\':http://infoarena.ro/arbori-de-intervale.\r\n\r\nAstfel, am redus complexitatea loopului interior de la $O(N)$ la $O(logN)$.\r\n\r\n\r\n\r\nh2. Programare dinamică folosind măşti de biţi şi codificări $k$-are\r\n\r\nUnele probleme de programare dinamica au drept componentă a stării unei subprobleme o mulţime de elemente care fac parte din subproblemă. Astfel, subproblema nu este o reducere a problemei iniţiale la un subset continuu de elemente ({$1..i$} sau $i..j$) ci la un subset oarecare. În acest caz, codificăm submulţimea curentă în stare, ca vector sau ca număr întreg. Dacă dimensiunea submulţimii este suficient de mic putem folosi un întreg pentru a codifica această informaţie astfel:\r\n\r\nFie mulţimea $A$ = { x{~1~}, x{~2~}, ... x{~n~} }.\r\nAtunci masca de biţi a unei partitii a lui $A$, $MASK$, va avea bitul $i$ egal cu 1 dacă şi numai dacă x{~i~} apartine partitiei. Desigur, această reprezentare duce la o complexitate direct proporţională cu $2 ^card(A)^$. Putem intui dacă trebuie să folosim o astfel de rezolvare din limitele valorilor de intrare; pentru $N$ cu valori cuprinse între $10-20$, deducem că trebuie să căutăm o astfel de soluţie.\r\n\r\nPentru multe probleme, fiecare element poate face parte din subproblemă în mai mult de 2 feluri. De exemplu, dacă starea reprezintă o linie de maxim $K$ elemente dintr-o matrice iar fiecare element de pe linie poate avea valorile 0, 1 sau 2 atunci există $3^K$ variante distincte posibile pentru o astfel de linie. Un alt exemplu este o problemă de optimizare în care fiecare element (participant) se poate afla în una din câteva stări (dacă $N$ persoane trebuie să treacă un pod peste un râu, cele 3 stări pot fi: _pe malul stâng_, _pe pod_ şi _pe malul drept_).\r\n\r\n\r\nh3(#problema-1). Problema 1: \'Be a Smart Raftsman\':http://acm.sgu.ru/problem.php?contest=0&problem=475 (SGU)\r\n\r\nbq. Sunteţi membri ai unui echipaj de rafting care constă din $N ≤ 10$ participanţi. Puteţi naviga pe râu, şi scopul vostru este să treceţi de $M ≤ 1000$ curenţi consecutivi şi să ajungi de la punctul de început la punctul de sfârşit în timp minim. Cel de-al $i$-lea curent se caracterizează prin greutatea critică $c{~i~}$, iar al $j$-lea participant este caracterizat greutatea sa $w{~j~}$. În cazul în care pluta trece prin al $i$-lea curent cu oameni la bord cu greutatea totală mai mare de $c{~i~}$, ea se răstoarnă. Această parte a rafting-ului este cea mai interesantă, dar este nevoie de timp suplimentar pentru a te urca pe plută după răsturnare. Deci, uneori este mai bine să se urce un grup de oameni cu greutate totală care nu depăşeşte greutatea critică a plutei, în timp ce restul parcurg distanţa pe jos.\r\nMai formal, vom considera $M + 1$ puncte $P{~0~}, P{~1~} ,..., P{~M~}$, în cazul în care $P{~0~}$ este începutul şi $P{~M~}$ este punctul final. Fiecare dintre punctele intermediare $P{~i~} (1 ≤ i ≤ M-1)$ este situat între $i$-lea şi $(i + 1)$-lea curent. Dacă pluta se răstoarnă, sunt necesare $D{~i~}$ minute pentru a ajunge de la $P{~i-1~}$ la $P{~i~}$, altfel sunt necesare $d{~i~}$ minute. Cel de-al $j$-lea participant poate merge pe jos de la $P{~i-1~}$ la $P{~i~}$ în $t{~j~}$ minute, iar pentru a se urca sau a coborî din plută are nevoie de $s{~j~}$ minute. Înainte de fiecare curent, grupul vostru este împărţit în două părţi. Prima parte trece prin curent cu pluta, iar a doua parte merge pe mal spre următorul punct. Cei care ajung primii îi aşteaptă pe toţi ceilalţi. Apoi, unii participanţi care sunt pe plută se pot da jos, în timp ce alţi participanti care sunt pe mal se pot urca pe plută. Această activitate începe când ajung pluta şi toţi cei de pe mal la punctul stabilit. Timpul total necesar pentru această acţiune este egal cu suma valorilor $s{~j~}$ pentru toate persoanele care schimbă locul (persoanele urcă şi coboară pe rând). Nimeni nu poate începe deplasarea la următorul punct, până când nu s-au mutat toţi membrii.\r\nîncepeţi de la punctul de $P{~0~}$ cu tot grupul pe mal şi trebuie să terminaţi la punctul $P{~M~}$ cu toţi participanţii şi pluta pe mal. Nu aveţi voie să părăsiţi pluta la început sau într-un un punct intermediar şi să mergeţi pe jos spre linia de sosire fără ea. Aveţi posibilitatea să urcaţi tot grupul de salvare în plută, dar nu puteţi lăsa pluta goală în timpul călătoriei printr-un curent. \r\nSarcina voastră este să calculaţi timpul minim necesar pentru a ajunge la linia de sosire.\r\n\r\nh3. Rezolvare:\r\n\r\nDin enunţ intuim că o componentă a stării trebuie să fie submulţimea participanţilor aflaţi în plută în punctul curent, intuiţie confirmată de numărul mic al participanţilor ({$N ≤ 10$}). Există $2^10^$ astfel de variante, din care vom exclude varianta în care pluta este goală. O stare a problemei, reprezentănd soluţia unei subprobleme, va fi alcătuită din poziţia curentă a plutei (punctul $P{~i~}$ unde se află) şi submulţimea oamenilor care se află în plută. Observăm că de la punctul precedent pluta a traversat curentul, au urcat nişte oameni apoi au coborât alţii; aceşti paşi contribuie la timpul total şi reprezintă 2 părţi ale recurenţei soluţiei. Dacă notăm cu $T{~m~}[i][S]$ timpul minim necesar pentru a ajunge în punctul $i$ cu submulţimea $S$ a oamenilor din plută, putem descrie problema prin relaţiile:\r\n\r\n<tex> $T_m[0][0] = 0$ </tex>\r\n<tex> $T_m[0][S] = T_u[0][S], \\forall S \\neq 0$ </tex>\r\n<tex> $T_m[i][S] = \\min_{S\' \\neq \\emptyset} \\{T_m[i-1][S\'] + T_t[i][S\'] + T_u[S\'][S] + T_c[S\'][S]\\}, \\forall 1 \\le i \\le M$ </tex>\r\n\r\nunde $T{~u~}[S\'][S]$ este timpul necesar pentru urcarea participanţilor care se găsesc în mulţimea $S$ dar nu fac parte din mulţimea $S\'$ (aceşti participanţi alcătuiesc mulţimea $S{~u~}$), $T{~c~}[S\'][S]$ este timpul necesar pentru coborârea participanţilor din plută (participanţii din mulţimea $S{~c~}$), iar $T{~t~}[i][S]$ este timpul necesar traversării curentului de la punctul $i-1$ la punctul $i$ dacă în plută se află participanţii din $S$. Formulele pentru valorile $T{~u~}$, $T{~c~}$ şi $T{~t~}$ sunt:\r\n\r\n<tex> $T_u[S_1][S_2] = \\sum_{i \\in S_2 - S_1}{s_i} = \\sum_{i \\in S_u}{s_i}$ </tex>\r\n<tex> $T_c[S_1][S_2] = \\sum_{i \\in S_1 - S_2}{s_i} = \\sum_{i \\in S_c}{s_i}$ </tex>\r\n<tex> $T_t[i][S] = \\left\\{ \r\n\\begin{array}{l l}\r\n  D_i & \\quad \\sum_{j \\in S}{w_j} > c_i\\\\\r\n  d_i & \\quad \\sum_{j \\in S}{w_j} \\le c_i\\\\ \r\n\\end{array} \\right. $</tex>\r\n\r\nCalcularea directă a soluţiei pe baza recurenţelor de mai sus are complexitatea $O(M*N*2^N^ + M*2^N^*2^N^)$. Primul termen al complexităţii este dat de calcularea valorilor $T{~t~}$, iar al doilea de calcularea matricii $T{~m~}$.\r\n\r\nValoarea rezultatului nu depinde de ordinea în care urcă şi coboară participanţii din plută, deci o putem alege noi. Dacă aranjăm ordinea în doi paşi astfel încât în primul pas doar să urce, apoi în al doilea pas doar să coboare, vom obţine o îmbunătăţire semnificativă a timpului de execuţie. Se observă că dacă am efectua doar adăugări de elemente (daca în plută s-ar putea doar urca persoane, fără să poată coborî), atunci <tex> $S\' \\in S$ </tex> şi deci reprezentarea în cod binar a mulţimii $S\'$ ar avea o valoare mai mică decât reprezentarea binară a mulţimii $S$. Dacă ar avea voie doar să coboare persoane, relaţia ar fi inversă. De aceea, vom ordona operaţiile de urcare şi coborâre astfel încât să aibă loc întâi toate urcările (astfel încât să putem parcurge crescător valorile binare ale mulţimilor) apoi toate coborârile (astfel încât să putem efectua a doua parcurgere, în ordine descrescătoare). Introducem matricea auxiliară $T{~um~}[i][S]$ care reprezintă timpul minim necesar la care se poate afla pluta în punctul $i$ cu mulţimea $S$ de oameni, dacă după ultima traversare nu a coborât încă nici o persoană. Starea $S$ a fost obţinută prin una sau mai multe urcări de persoane în plută sau direct prin traversarea curentului. Recurenţele pentru $T{~um~}[i][S]$ sunt:\r\n\r\n<tex> $T_{um}[i][S] = \\min \\left(T_m[i-1][S] + T_t[i][S], \\min_{j \\in S}\\{T_{um}[i][S - j] + s_j\\} \\right) </tex>\r\n<tex> $T_m[i][S] = \\min \\left(T_{um}[i][S], \\min_{j \\not\\in S}\\{T_m[i][S \\cup j] + s_j\\} \\right) </tex>\r\n\r\nAm eliminat calcularea matricilor $T{~u~}$, $T{~c~}$. Toate matricile rămase au dimensiunea $Mx2^N^$ iar calcularea fiecărui element necesită un timp $O(N)$, deci soluţia astfel obţinută are complexitatea $O(M*N*2^N^)$.\r\n\r\n== code(cpp)    |\r\n    iniţializează toate Tm[0];\r\n    pentru i = 1, M execută\r\n        calculează toate Tt[i];\r\n        pentru fiecare S în ordine crescătoare a reprezentării binare execută\r\n            Tum[i][S] = Tm[i-1][S] + Tt[i][S];\r\n            pentru fiecare j din S execută\r\n                Tum[i][S] = min(Tum[i][S], Tum[i][S - j] + s[j]);\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n        pentru fiecare S în ordine descrescătoare a reprezentării binare execută\r\n            Tm[i][S] = Tum[i][S];\r\n            pentru fiecare j care nu există în S execută\r\n                Tm[i][S] = min(Tm[i][S], Tm[i][S + j] + s[j]);\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează Tm[M][0];\r\n==\r\n\r\nMai există două optimizări de spaţiu pe care le putem efectua în soluţia prezentată. Putem elimina matricea $T{~um~}$, calculând toate valorile direct pe matricea $T{~m~}$, deoarece aceasta va fi parcursă în ambii paşi în câte o singură direcţie. A doua optimizare se bazează pe observaţia că nu avem niciodată nevoie de alte linii în afară de ultimele 2 ({$i$} si {$i-1$}), deci putem înlocui matricea cu 2 vectori de dimensiune $2^N^$. Valorile $T{~t~}$ pot fi calculate în cadrul primei bucle, reducând astfel spaţiul necesar soluţiei la $O(2^N^)$.\r\n\r\n\r\n\r\nh2. Programare dinamica pe mai multe dimensiuni\r\n\r\nUnele probleme nu pot fi împărţite în subprobleme doar după o submulţime a datelor de intrare ale problemei curente, ci trebuie adăugate criterii suplimentare. De multe ori, aceste valori sunt similare sumei din _problema rucsacului_, dar calculele se fac pe 2 sau chiar mai multe dimensiuni, obţinând o descriere destul de complexă a unei subprobleme. De exemplu, o subproblemă poate fi reprezentată printr-un vector de valori de dimensiuni variate.\r\n\r\n\r\nh3(#problema-1). Problema 1: \'Ugly numbers\':http://code.google.com/codejam/contest/dashboard?c=32015#s=p1&a=1 (Google Code Jam 2008, Round 1C)\r\n\r\nbq. Un număr se numeşte *urât* dacă este divizibil prin oricare dintre numerele prime de o singură cifră, mai exact $2, 3, 5, 7$. Se dă un şir de $N$ cifre. Între fiecare 2 cifre consecutive se poate insera unul dintre semnele + sau -. Dacă nu se inserează un semn, cele 2 cifre sunt concatentate astfel încât să se obţină un număr. Pentru un şir dat de cifre si o variantă de a adăuga semne, prin evaluarea expresiei matematice obţinute prin inserarea semnelor se obţine un număr, numit numărul generat. Să se calculeze câte dintre cele $3^N-1^$ variante de a insera semnele generează numere urâte.\r\n\r\nh3. Exemplu: \r\n\r\nPentru cifrele $123456$, expresia $1+234-5+6 = 236$ care este număr urât, iar $123+4-56 = 71$ nu este număr urât.\r\n\r\nh3. Rezolvare:\r\n\r\nObservăm că un număr este urât dacă dă cel puţin o dată restul 0 la împărţirea la numerele $2, 3, 5, 7$. O abordare a problemei este parcurgerea tuturor variantelor de inserare şi calcularea celor 4 resturi, verificând dacă cel puţin unul este 0.\r\nVom folosi aritmetica modulară pentru a obţine o soluţie mai eficientă a problemei. Vom împărţi cele $3^N-1^$ variante în clase, fiecare clasă reprezentând toate numerele care dau resturile $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ la împărţirea la cele 4 numere. Calculând pentru fiecare clasă numărul de numere generate, rezultatul final va fi suma valorilor calculate pentru toate clasele pentru care cel puţin un rest este egal cu 0. Intuim că putem utiliza clasele de resturi într-o soluţie cu programare dinamică.\r\nVom utiliza şirul auxiliar $V[i][j]$ reprezentând numărul format prin concatenarea cifrelor de pe poziţiile consecutive $i, i+1, ..., j$ din şirul dat, fără inserarea unor semne între cifre. De exemplu, @V[2][4] = 234@. Dacă notăm cu $C[i][r{~2~}][r{~3~}][r{~5~}][r{~7~}]$ numărul de variante formate cu primele $i$ cifre pentru care clasa de resturi este $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$. Observăm că orice astfel de variantă se obţine dintr-o variantă cu $j < i$ cifre după care adăugam + sau - apoi concatenăm restul cifrelor până la $i$ fără semne. Dacă resturile pentru varianta cu $j$ cifre erau $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ atunci resturile pentru varianta nouă $(r\'{~2~}, r\'{~3~}, r\'{~5~}, r\'{~7~})$ sunt:\r\n<tex> $r_2\' = (r_2 +/- V[j+1][i])\\% 2$</tex>\r\n<tex> $r_3\' = (r_3 +/- V[j+1][i])\\% 3$</tex>\r\n<tex> $r_5\' = (r_5 +/- V[j+1][i])\\% 5$</tex>\r\n<tex> $r_7\' = (r_7 +/- V[j+1][i])\\% 7$</tex>\r\nAtunci numărul total de variante cu $i$ cifre este suma după toate valorile $j$ ale numerelor de variante cu $j$ cifre:\r\n<tex> $C[i][r_2\'][r_3\'][r_5\'][r_7\'] = \\sum_{j<i} C[j][r_2][r_3][r_5][r_7]$ </tex>\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i]\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = V[i][j - 1] + A[i];\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0][0][0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r_2 = 0, 1 execută\r\n            pentru r_3 = 0, 2 execută\r\n                pentru r_5 = 0, 4 execută\r\n                    pentru r_7 = 0, 6 execută\r\n                        C[i][r_2][r_3][r_5][r_7] = 0;\r\n                        pentru j = 0, i - 1 execută\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + 2 - V[j+1][i])%2)][(r_3 + 3 - V[j+1][i])%3)]\r\n                                                            [(r_5 + 5 - V[j+1][i])%5)][(r_7 + 7 - V[j+1][i])%7)];\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + V[j+1][i])%2)][(r_3 + V[j+1][i])%3)]\r\n                                                            [(r_5 + V[j+1][i])%5)][(r_7 + V[j+1][i])%7)];\r\n                        sfârşit pentru;\r\n\r\n                        dacă i == N şi (r_2 == 0 sau r_3 == 0 sau r_5 == 0 sau r_7 == 0)\r\n                            S += C[i][r_2][r_3][r_5][r_7]\r\n                        sfârşit pentru;\r\n                    sfârşit pentru;\r\n                sfârşit pentru;\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează S;\r\n==\r\n\r\nO problemă în abordarea precedentă este calcularea matricii $V$, ale cărei valori devin foarte mari şi ies din precizia tipurilor de date disponibile. O soluţie posibilă este calcularea câte unei matrici de sume modulo $R$ pentru fiecare rest $R$, adica a 4 matrici $V{~2~}$, $V{~3~}$, $V{~5~}$ si $V{~7~}$ ale resturilor împărţirii valorilor lui $V$ la cele 4 numere prime. Folosind aritmetica modulară, aceste matrici pot fi calculate direct, fără a calcula $V$. Altă variantă este utilizarea teoremei chineze a resturilor, prin care un sistem de ecuaţii modulo câteva numere prime între ele poate fi redus la o ecuaţie modulo produsul numerelor date. În cazul nostru, numerele sunt prime, deci putem aplica teorema. Astfel, putem reduce problema resturilor împărţirii la $(2, 3, 5, 7)$ la problema restului împărţirii la $2*3*5*7=210$, deci fiecare clasa $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ se reduce la un rest $R < 210$. Modificăm pseudocodul astfel:\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i] % 210\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = (V[i][j - 1] + A[i]) % 210;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r = 0, 209 execută\r\n            C[i][r] = 0;\r\n            pentru j = 0, i - 1 execută\r\n                C[i][r] += C[j][(r + 210 - V[j+1][i]) % 210];\r\n                C[i][r] += C[j][(r + V[j+1][i]) % 210];\r\n            sfârşit pentru;\r\n\r\n            dacă i == N şi (r % 2 == 0 sau r % 3 == 0 sau r % 5 == 0 sau r % 7 == 0)\r\n                S += C[i][r];\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează S;   \r\n==\r\n\r\n\r\nh3(#problema-2). Problema 2: \'Doipatru\':http://infoarena.ro/problema/doipatru\r\n\r\nbq. Membrii Lotului Naţional de Informatică sunt foarte mândri de noul joc inventat de ei, pe care l-au denumit asemănător cu o problemă de la Olimpiada Internaţională de Informatică din anul 2001, care le-a plăcut foarte mult. Astfel, jocul se numeşte DoiPatru.\r\nPentru acest joc se folosesc $3 ≤ N ≤ 30$ grămezi, fiecare conţinând cel puţin 0 şi cel mult 4 bile. Numărul total de bile din toate grămezile este $2*N$. Doi jucători mută alternativ. Atunci când ii vine rândul, fiecare jucător este obligat să efectueze o mutare validă.\r\nO mutare validă constă din alegerea a două grămezi, dintre care prima grămadă are mai multe bile decât cea de a doua. Jucătorul ia o bilă din prima grămadă şi o mută în cealaltă. Mutarea se consideră validă, doar dacă numărul de bile rezultat în a doua grămadă după mutarea bilei nu este mai mare decât numărul de bile rămas în prima grămadă.\r\nJocul se termină atunci când nu mai poate fi efectuată nici o mutare validă (dacă vă gândiţi puţin, veţi constata că acest lucru se întâmplă atunci când fiecare grămadă conţine două bile).\r\nCâştigătorul jocului este desemnat cel care deţine mai multe grămezi la sfârşitul jocului. Bineînţeles, dacă cei doi jucători deţin un număr egal de grămezi, jocul se consideră a fi remiză.\r\nUn jucător deţine o grămadă dacă grămada are două bile, iar acest număr (de două bile) a rezultat în urma unei mutări efectuate de jucătorul respectiv. De exemplu, dacă un jucător alege o grămadă cu 4 bile şi una cu o bilă, în urma efectuării mutării, el va deţine cea de-a doua grămadă (care va avea două bile), dar prima nu va aparţine deocamdată nici unuia dintre jucători. Dacă alege o grămadă cu 3 bile şi una cu 0 bile, jucătorul va deveni proprietarul primei grămezi, deoarece, în urma mutării efectuate, grămada respectivă va rămâne cu două bile. În cazul în care alege o grămadă cu 3 bile şi una cu o bilă, după efectuarea mutării, el va deţine ambele grămezi (amândouă au acum doua bile).\r\nDacă un jucător este proprietarul unei grămezi la un moment dat în timpul jocului, nu înseamnă că această grămadă va rămâne în posesia lui până la sfârşit. De exemplu, să presupunem că jucătorul 1 deţine o grămadă cu două bile şi este rândul jucătorului 2 să mute. Dacă acesta alege o grămadă cu 4 bile şi grămada cu două bile ce aparţine jucătorului 1, după efectuarea mutării, ambele grămezi vor avea 3 bile, iar numărul de grămezi aflate în posesia jucătorului 1 va scădea cu 1 (grămada deţinută de el anterior nu mai aparţine nici unuia din cei doi jucători, căci nu mai are doua bile).\r\nDacă la începutul jocului există unele grămezi având două bile, acestea sunt distribuite în mod egal celor doi jucători. Dacă numărul de grămezi cu două bile este impar, atunci jucătorul 2 va primi cu o grămadă mai mult decât jucatorul 1. Jucătorul 1 este cel care efectuează prima mutare.\r\nScrieţi un program care, pentru un $N$ dat şi un set de configuraţii iniţiale ale jocului cu $N$ grămezi, decide rezultatul fiecărei configuraţii de joc.\r\n\r\nh3. Rezolvare:\r\n\r\nÎncepem rezolvarea cu observaţia că există 5 tipuri de grămezi (0, 1, 2, 3 şi 4 bile), dar pentru fiecare grămadă de 2 bile aparţine doar unuia dintre jucători, informaţie esenţială pentru stabilirea câştigătorului. Vom separa deci toate grămezile de 2 bile în 2 categorii: $2A$ care reprezintă grămezile de 2 bile deţinute de primul jucător şi $2B$ care sunt grămezile de 2 bile deţinute de al doilea jucător. Orice moment al jocului poate fi reprezentat identificând jucătorul care urmează la mutare şi numărul de bile din fiecare dintre cele $N$ grămezi. O variantă alternativă este de a reprezenta numerele de grămezi din fiecare tip, starea fiind reprezentată prin valorile $(J, n{~0~}, n{~1~}, n{~2A~}, n{~2B~}, n{~3~}, n{~4~})$, unde $n{~k~}$ reprezintă numărul de grămezi care au $k$ bile (cu excepţiile $2A$ şi $2B$, descrise înainte).\r\nVom nota prin $R[J, n{~0~}, n{~1~}, n{~2A~}, n{~2B~}, n{~3~}, n{~4~}]$ cel mai bun rezultat pe care îl poate obţine jucătorul care urmează ({$J$}). Valorile posibile ale rezultatului vor fi alese ca numere întregi crescătoare, astfel: 0 dacă din configuraţia curentă jucătorul nu are nici o şansă să câştige, 1 dacă jucătorul poate obţine o remiză şi 2 dacă jucătorul are o strategie sigură de câştig. Fiecare jucător va alege mutarea potrivită astfel încât să maximizeze valoarea $R$, care este în acelaşi timp rezultatul cel mai prost pentru celălalt jucător. Vom nota jucătorii prin 0 şi 1 şi putem calcula valoarea optimă pentru $R$ astfel:\r\n\r\n<tex> $R[J, n_0, n_1, n_{2A}, n_{2B}, n_3, n_4] = 2 - \\min\\{R[\\(1 - J\\), n_0\', n_1\', n_{2A}\', n_{2B}\', n_3\', n_4\'] \\}$</tex> dacă $(n\'{~0~}, n\'{~1~}, n\'{~2A~}, n\'{~2B~}, n\'{~3~}, n\'{~4~})$ reprezintă o stare accesibilă din starea curentă printr-o singură mutare. Observăm că rezultatul este cu atât mai bun pentru unul dintre jucători cu cât este mai prost pentru celălalt, deci rezultatele sunt invers proporţionale, $2$ pentru $J$ reprezentănd $0$ pentru jucătorul $1 - J$. Fiecare jucător alege mutarea care îi va obţine rezultatul maxim, acesta fiind corespunzător rezultatului defavorabil (de valoare minimă) pentru celălalt.\r\n\r\nStările pentru care nu mai există decât grămezi de tipuri $2A$ şi $2B$ sunt, conform enunţului, stări finale. \r\n<tex> $R[J, 0, 0, n_{2A}, n_{2B}, 0, 0] = \\left\\{ \r\n\\begin{array}{l l}\r\n  0 & \\quad J = 0, n_{2A} < n_{2B}\\\\\r\n  0 & \\quad J = 1, n_{2A} > n_{2B}\\\\ \r\n  1 & \\quad n_{2A} = n_{2B}\\\\\r\n  2 & \\quad J = 0, n_{2A} > n_{2B}\\\\ \r\n  2 & \\quad J = 1, n_{2A} < n_{2B}\\\\\r\n\\end{array} \\right. $</tex>\r\n\r\nNotând cu $S$ tuplul distribuţiei bilelor în grămezi $(J, n{~0~}, n{~1~}, n{~2A~}, n{~2B~}, n{~3~}, n{~4~})$ atunci vom folosi o notaţie echivalentă dar mai scurtă, $R[J, S]$. Vom iniţializa toate valorile din acest tablou multidimensional la -1 şi apoi vom calcula recursiv valorile, obţinând o complexitate polinomială prin memoizare.\r\n\r\n== code(cpp)  |\r\ncalculR(J, S)\r\n  dacă R[J, S] != -1 atunci\r\n    returnează R[J, S];\r\n  dacă S e stare finală\r\n    returnează 0, 1 sau 2 în funcţie de câştigător;\r\n\r\n  R[J, S] = 0;\r\n  pentru toate stările S\' în care se poate ajunge din S printr-o mutare\r\n    R[J, S] = max(R[J, S], 2 - calculR(1 - J, S\'));\r\n  sfârşit pentru;\r\n  returnează R[J, S];\r\n==\r\n\r\nLa prima vedere, numărul stărilor este $2 * (2N)^6^ = 2 * 60^6^ = 93,312 * 10^9^$, deci numărul stărilor este prea mare pentru a intra în limite rezonabile de spaţiu şi timp. Observăm totuşi că toate stările îndeplinesc condiţia $n{~0~} + n{~1~} + n{~2A~} + n{~2B~} + n{~3~} + n{~4~} = N$. Numărul total al stărilor este numărul tuplurilor care îndeplinesc egalitatea şi condiţiile $n{~k~} ≥ 0$. Vom numerota cele 6 tipuri de grămezi prin numere de la 0 la 5. Vom calcula valorile $N{~S~}[g, b, v]$ care reprezintă numărul de variante de a grupa $b$ bile în $g$ grămezi, astfel încât cea mai mică grămadă să aibă cel puţin mărimea tipului de indice $0 ≤ v ≤ 5$. Notăm cu $D$ şirul dimensiunilor tipurilor, $(0, 1, 2, 2, 3, 4)$ şi observăm că o stare descrisă prin $(g, b, v)$ ori are o grămadă de dimensiune $D{~v~}$ ori toate grămezile sunt mai mari decât această dimensiune. Atunci recurenţa de calcul pentru $N{~S~}$ este: $N{~S~}[g, b, v] = N{~S~}[g, b, v + 1] + N{~S~}[g - 1, b - D{~v~}, v]$ cu cazul particular $N{~S~}[0, 0, 5] = 1$. Numărul total de stări este valoarea $N{~S~}[N, 2*N, 0]$. Pentru valoarea maximă a lui $N$ din enunţ, am obţinut $N{~S~}(30) = N{~S~}[30, 60, 0] = 8266$. Rezultă deci că numărul total real al stărilor este relativ mic, iar soluţia noastră se încadrează în limitele de timp şi spaţiu date.\r\n\r\nPentru o stare $S$ dată, numărul stărilor posibile $S\'$ în care putem ajunge este foarte mic. În cel mai rău caz, perechile de grămezi care reprezintă mutarea din pasul curent sunt din mulţimea ${(0, 2A), (0, 2B), (0, 3), (0, 4), (1, 3), (1, 4), (2A, 4), (2B, 4)}$, deci un jucător are maxim 8 mutări posibile de efectuat. După ce am ales tipurile de grămezi pe care efectuăm mutarea, este irelevantă alegerea grămezilor cu dimensiunile date, deoarece toate alegerile duc la aceeaşi stare următoare. \r\n\r\nUn mod de a stoca tabloul $R$ astfel încât spaţiul necesar să fie minim este folosirea unui dicţionar care să stocheze valorile $R[J, n{~0~}, n{~1~}, n{~2A~}, n{~2B~}, n{~3~}, n{~4~}]$ pentru toate stările valide, folosind astfel doar $O(N{~S~}(N))$ spaţiu. Dicţionarul poate fi implementat printr-o tabelă de dispersie sau arbori binari de căutare, în C++ folosind chiar $map$ sau $hash_map$ din STL. Altă opţiune este codificarea fiecărei stări $S$ printr-un număr întreg cuprins între 1 şi $N{~S~}(N)$, caz în care tabloul $R$ poate fi stocat într-o matrice de dimensiune $2xN{~S~}(N)$. Asocierea dintre descrierea unei stări (numărul de grămezi de fiecare tip) şi numărul său de ordine poate fi precalculată şi stocată într-un dicţionar sau poate fi calculată în $O(N)$ cu ajutorul unor formule. În primul caz, vom genera prin backtracking toate variantele posibile de stări într-o ordine oarecare şi vom aloca fiecărei stări câte un număr, stocând izomorfismul într-un dicţionar.\r\n\r\nVarianta mai complexă, dar mai elegantă presupune stabilirea unei ordini fixe a stărilor şi apoi folosirea unor tehnici combinatoriale pentru a calcula numărul corespunzător unei stări sau starea corespunzătoare unui număr. Vom defini mai formal o stare ca un 6-tuplu $(n{~0~}, n{~1~}, n{~2A~}, n{~2B~}, n{~3~}, n{~4~})$ şi vom ordona toate stările lexicografic (stările sunt ordonate după $n{~0~}$; în caz de egalitate, sortarea se face după $n{~1~}$ ş.a.m.d.). Atunci numărul de ordine al unei stări calculat de formula de mai sus este numărul de stări care au o valoare mai mică pentru $n{~0~}$ plus numărul de stări care au aceeaşi valoare pentru $n{~0~}$ dar o valoare mai mică pentru $n{~1~}$ ş.a.m.d. \r\n\r\n==code(cpp)  |\r\n  IS = 1;\r\n  G = N;\r\n  B = 2 * N;\r\n  pentru k = 0, 4 execută\r\n    dacă n[k] > 0 atunci\r\n       pentru i = 1, n[k] execută\r\n         IS = IS + S[G][B][k + 1];\r\n         G = G - 1;\r\n         B = B - D[k];\r\n       sfârşit pentru;\r\n  sfârşit pentru;\r\n  returnează IS;\r\n==\r\n\r\nOperaţia inversă calculează o stare $S$ pe baza valorii $I(S)$ a indicelui stării.\r\n\r\n==code(cpp)  |\r\n  G = N;\r\n  B = 2 * N;\r\n  pentru k = 0, 4 execută\r\n    n[k] = 0;\r\n    cât timp IS > S[G][B][k + 1] execută\r\n      IS = IS - S[G][B][k + 1];\r\n      G = G - 1;\r\n      B = B - D[k];\r\n      n[k] = n[k] + 1;\r\n    sfârşit cât timp;\r\n  sfârşit pentru;\r\n  n[5] = G;\r\n  returnează n;\r\n==\r\n\r\nAceşti algoritmi pot fi integraţi în funcţia recursivă de calcul a matricii $R$.\r\n\r\n\r\nTo be continued ... \r\n\r\n',11775,'public',NULL,NULL),('runda/very.easy','very.easy','2009-11-07 18:17:39','2009-11-07 18:17:39','h1. == roundparam(round_id=\"very.easy\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"very.easy\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"very.easy\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"very.easy\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/very.easy/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"very.easy\" score=\"1\")==',10703,'round: very.easy',NULL,NULL),('runda/very.easy/clasament','Clasament very.easy','2009-11-07 18:17:39','2009-11-07 18:17:39','h1. Clasament ==roundparam(round_id=\"very.easy\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"very.easy\")==',10703,'round: very.easy',NULL,NULL),('runda/cnrv_5','CNRV - Editia #5','2009-11-09 15:05:12','2009-11-09 15:10:02','h1. == roundparam(round_id=\"cnrv_5\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cnrv_5\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cnrv_5\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cnrv_5\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cnrv_5/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cnrv_5\" score=\"1\")==',5748,'round: cnrv_5',NULL,NULL),('runda/cnrv_5/clasament','Clasament cnrv_5','2009-11-09 15:05:12','2009-11-09 15:05:12','h1. Clasament ==roundparam(round_id=\"cnrv_5\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"cnrv_5\")==',5748,'round: cnrv_5',NULL,NULL),('dot-com/2009/clasament','Clasament .com 2009','2009-11-09 15:44:14','2009-11-15 09:05:57','h1. Clasament \'.com 2009\':dot-com/2009\r\n\r\n(htabs)* \'Detalii\':dot-com/2009\r\n* \'Runda 1\':dot-com/2009/runda-1\r\n* \'Runda 2\':dot-com/2009/runda-2\r\n*(active) \'Clasament\':dot-com/2009/clasament\r\n\r\nAcesta este clasamentul cumulat pentru cele 2 runde online.\r\n\r\n== Rankings(rounds=\"dotcom2009-runda1 | dotcom2009-runda2\") ==',1490,'public',NULL,NULL),('dot-com/2009/clasament/runda-1','Clasament .com 2009, Runda 1','2009-11-09 15:38:36','2009-11-10 11:51:10','h1. Clasament ==roundparam(round_id=\"dotcom2009-runda1\" param=\"title\") ==\r\n\r\n(htabs)* \'Detalii\':dot-com/2009\r\n*(active) \'Runda 1\':dot-com/2009/runda-1\r\n* \'Runda 2\':dot-com/2009/runda-2\r\n*(active) \'Clasament\':dot-com/2009/clasament\r\n\r\n==Rankings(rounds = \"dotcom2009-runda1\")==\r\n',1490,'round: dotcom2009-runda1',NULL,NULL),('newsletter/dot-com-2009-1','.com 2009, Runda 1','2009-11-09 16:18:48','2009-11-10 18:20:11','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nIată că vacanţa de vară s-a terminat şi o bună parte din toamnă a trecut şi ea. Infoarena dă startul unor noi serii de concursuri ce iţi vor reda apetitul pentru informatică.\r\n\r\nTe invităm să participi la un nou concurs organizat de membrii comunităţii, .com 2009.\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Prima rundă se desfăşoară\r\n*Duminică, 15 Noiembrie, orele 10^00^ - 15^00^*. |\r\n\r\nVezi \'pagina concursului\':dot-com/2009 ca să afli cum poţi participa.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"dot-com/2009/runda-1\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre .com 2009\r\n\r\nConcursul are o singură grupă valorica dar cele 4 probleme propuse au dificultăţi variind între gimnaziu şi liceu clasele 11-12.\r\n\r\nOrganizatorii concursului sunt:\r\n\r\n* \'Stan Şerban Andrei\':utilizator/savim\r\n* \'Cezar Mocan\':utilizator/cezarmocan\r\n* \'Radu Zernoveanu\':utilizator/raduzer\r\n* \'Teodor Anton Pripoae\':utilizator/toni2007\r\n* \'Mihai Gheorghe\':utilizator/gheorghemihai\r\n\r\nh2{font-size: 12pt}. Algoritmiada 2010\r\n\r\nAntrenează-te cât mai este timp pentru că în curând începe Algoritmiada 2010.\r\n\r\nPentru mai multe detalii intră pe \'pagina concursului\':algoritmiada-2010.\r\n\r\nh2{font-size: 12pt}. O nouă conducere\r\n\r\nA sosit şi acest moment. Veteranii echipei infoarena au predat ştafeta conducerii generaţiei mai tinere. Să sperăm ca ne vom putea ridica la aşteptările comunitaţii şi vom fi cel puţin la fel de buni ca cei de înaintea noastră.\r\n\r\nCitiţi mai multe despre asta pe \'blog\':blog/conducere-noua.\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==',2970,'public',NULL,NULL),('dot-com/2009/clasament/runda-2','Clasament .com 2009, Runda 2','2009-11-09 16:03:40','2009-11-10 11:51:23','h1. Clasament ==roundparam(round_id=\"dotcom2009-runda2\" param=\"title\") ==\r\n\r\n(htabs)* \'Detalii\':dot-com/2009\r\n* \'Runda 1\':dot-com/2009/runda-1\r\n*(active) \'Runda 2\':dot-com/2009/runda-2\r\n*(active) \'Clasament\':dot-com/2009/clasament\r\n\r\n==Rankings(rounds = \"dotcom2009-runda2\")==\r\n',1490,'round: dotcom2009-runda2',NULL,NULL),('dot-com/list','dot-com/list','2009-11-09 21:36:00','2010-03-09 11:20:48','h%header_size%. .com 2009 (\"Pagina concursului\":dot-com/2009)\r\n\r\n* Primul concurs din seria *.com* cu două runde de concurs organizat de către\r\n** ==user(user=\"savim\" type=\"tiny\")==\r\n** ==user(user=\"cezarmocan\" type=\"tiny\")==\r\n** ==user(user=\"raduzer\" type=\"tiny\")==\r\n** ==user(user=\"toni2007\" type=\"tiny\")==\r\n** ==user(user=\"gheorghemihai\" type=\"tiny\")==\r\n** ==user(user=\"stocarul\" type=\"tiny\")==',1490,'public',NULL,NULL),('runda/cls6','cls6','2009-11-09 17:00:50','2009-11-09 17:00:50','h1. == roundparam(round_id=\"cls6\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cls6\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cls6\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cls6\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cls6/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cls6\" score=\"1\")==',7375,'round: cls6',NULL,NULL),('runda/cls6/clasament','Clasament cls6','2009-11-09 17:00:50','2009-11-09 17:00:50','h1. Clasament ==roundparam(round_id=\"cls6\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"cls6\")==',7375,'round: cls6',NULL,NULL),('dot-com','.com','2009-11-09 21:27:46','2009-11-09 21:41:10','h1. .com\r\n\r\n==include(page=\"dot-com/description\")==\r\n\r\n==include(page=\"dot-com/list\" header_size=\"2\")==',1490,'public',NULL,NULL),('dot-com/description','dot-com/description','2009-11-09 21:39:04','2009-11-10 17:31:26','O nouă serie de concursuri infoarena organizate de către membrii comunităţii infoarena.',1490,'public',NULL,NULL),('dot-com/2009/runda-1','.com 2009, Runda 1','2009-11-09 15:38:36','2009-11-15 11:38:30','h1. == roundparam(round_id=\"dotcom2009-runda1\" param=\"title\") ==\r\n\r\n(htabs)* \'Detalii\':dot-com/2009\r\n*(active) \'Runda 1\':dot-com/2009/runda-1\r\n* \'Runda 2\':dot-com/2009/runda-2\r\n* \'Clasament\':dot-com/2009/clasament\r\n\r\nRunda se va desfasura ==roundparam(round_id=\"dotcom2009-runda1\" param=\"start_time\" strong=\"true\")==, si va dura ==roundparam(round_id=\"dotcom2009-runda1\" param=\"duration\" strong=\"true\")== ore. Participantii vor avea de rezolvat 4 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"dotcom2009-runda1\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"dotcom2009-runda1\" score=\"1\")==\r\n\r\nSolutiile le veti gasi \'aici\':dot-com/2009/solutii/runda-1 dupa ce runda va lua sfarsit.\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 1\':dot-com/2009/clasament/runda-1\r\n\r\nh2. Organizatori\r\n\r\n* ==user(user=\"savim\" type=\"tiny\")==\r\n* ==user(user=\"cezarmocan\" type=\"tiny\")==\r\n* ==user(user=\"raduzer\" type=\"tiny\")==\r\n* ==user(user=\"toni2007\" type=\"tiny\")==\r\n* ==user(user=\"gheorghemihai\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n\r\n',1490,'round: dotcom2009-runda1',NULL,NULL),('runda/training_round_1','training_round_1','2009-11-12 07:21:21','2009-11-12 07:21:21','h1. == roundparam(round_id=\"training_round_1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"training_round_1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"training_round_1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"training_round_1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/training_round_1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"training_round_1\" score=\"1\")==',6957,'round: training_round_1',NULL,NULL),('runda/training_round_1/clasament','Clasament training_round_1','2009-11-12 07:21:21','2009-11-12 07:21:21','h1. Clasament ==roundparam(round_id=\"training_round_1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"training_round_1\")==',6957,'round: training_round_1',NULL,NULL),('planificare/sedinta-20091103','Ședință 2009-11-03','2009-11-02 16:31:40','2009-11-26 09:41:59','h1. Şedinţă 2009-11-03\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Marti* la ora *18^00^* la ICHB.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"pauldb\" type=\"tiny\")== \r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== (ajung la 18:20)\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20091023 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| Algoritmiada 2010 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Evaluator nou | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Sala sedinta | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n* Algoritmiada 2010:\r\n** Contractul de sponsorizare \r\n** Proiecte de finantari\r\n** Comisie?\r\n** Mapa\r\n** Alti sponsori?\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* **Cosmin si Paul** reorganizeaza mapa si **Vali** face design.\r\n* **Cosmin** vorbeste cu Cristi despre carduri la banca. %{color:red}(done)%\r\n* **Cosmin** scrie newsletter. %{color:red}(done)%\r\n* **Vali** face testing pe masina virtuala.\r\n* **Cosmin** vorbeste cu Cristina despre comunicat de presa.\r\n* **Vali** vorbeste cu Vlad Posea despre jailrun java.\r\n* **Bogdan** scrie retry loop pentru eval. %{color:red}(done)%\r\n* **Bogdan** scrie IAP pentru tagging. %{color:red}(done)%\r\n* **Bogdan** deschide thread cu poll pe forum sa stabilim urmatorul coding camp. %{color:red}(done, failed)%\r\n* **Paul** pune pe grup linkurile de la proiectele de finantare guvernamentale. %{color:red}(done)%\r\n* **Cosmin, Paul si Prostu** se ocupa de proiectele de finantare.\r\n* **Cosmin** vorbeste cu Mircea, Cristi, Silviu si Cosmin sa bage spam la studenti cu Algoritmiada. %{color:red}(done)%\r\n* **Se scrie** text pentru poster si spam pe forumuri.\r\n* **Paul** lanseaza Algorimiada 2010. %{color:red}(done)%\r\n* **Prostu** vorbeste la Unibuc despre sala.\r\n\r\nh2(#notite). Notite\r\n\r\n* **Cosmin** deconteaza mancare pentru sedinta asta.\r\n',1490,'protected',NULL,NULL),('runda/veryeasy','veryeasy','2009-11-13 15:29:53','2009-11-13 15:29:53','h1. == roundparam(round_id=\"veryeasy\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"veryeasy\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"veryeasy\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"veryeasy\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/veryeasy/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"veryeasy\" score=\"1\")==',10036,'round: veryeasy',NULL,NULL),('runda/veryeasy/clasament','Clasament veryeasy','2009-11-13 15:29:53','2009-11-13 15:29:53','h1. Clasament ==roundparam(round_id=\"veryeasy\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"veryeasy\")==',10036,'round: veryeasy',NULL,NULL),('runda/487531','487531','2009-11-15 12:00:25','2009-11-15 12:00:25','h1. == roundparam(round_id=\"487531\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"487531\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"487531\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"487531\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/487531/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"487531\" score=\"1\")==',11219,'round: 487531',NULL,NULL),('runda/487531/clasament','Clasament 487531','2009-11-15 12:00:25','2009-11-15 12:00:25','h1. Clasament ==roundparam(round_id=\"487531\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"487531\")==',11219,'round: 487531',NULL,NULL),('runda/olimpiada1','olimpiada1','2009-11-15 12:01:16','2009-11-15 12:01:16','h1. == roundparam(round_id=\"olimpiada1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"olimpiada1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"olimpiada1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"olimpiada1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/olimpiada1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"olimpiada1\" score=\"1\")==',11219,'round: olimpiada1',NULL,NULL),('runda/olimpiada1/clasament','Clasament olimpiada1','2009-11-15 12:01:18','2009-11-15 12:01:18','h1. Clasament ==roundparam(round_id=\"olimpiada1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"olimpiada1\")==',11219,'round: olimpiada1',NULL,NULL),('dot-com/2009/solutii/runda-1/floare','dot-com/2009/solutii/runda-1/floare','2009-11-15 11:47:13','2010-01-02 22:04:34','h1(#floare). \'Floare\':problema/floare\r\n\r\nVom construi sirul $D$~i~, cu semnificatia $a cata dintre jucatoare (considerand ca jucatoarea 1 muta prima) va castiga jocul pentru o floare cu $i$ petale$. Observam ca dintr-o stare cu $i$ petale putem ajunge in oricare dintre starile $i-1$, $i-2$, ... $i-K$, luand $1$, $2$... $K$ din petalele florii. Fata $1$ va alege starea din care poate sa castige cat mai multi trandafiri, adica $A[M - D[j]]$ sa fie maxim, $i-K &le; j &le; i-1$. \r\nPentru 30 de puncte recurenta se rezolva direct, iar pentru 100 de puncte se foloseste un \'deque\':problema/deque.\r\n',9232,'public',NULL,NULL),('dot-com/2009/solutii/runda-1','Solutii .com 2009, Runda 1','2009-11-15 11:46:12','2009-11-15 12:53:09','h1. Solutii .com 2009, Runda 1\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Tabara2\':dot-com/2009/solutii/runda-1#tabara2\r\n* \'Floare\':dot-com/2009/solutii/runda-1#floare\r\n* \'Galerie\':dot-com/2009/solutii/runda-1#galerie\r\n* \'Trilant\':dot-com/2009/solutii/runda-1#trilant\r\n\r\n==include(page=\"dot-com/2009/solutii/runda-1/tabara2\")==\r\n\r\n==include(page=\"dot-com/2009/solutii/runda-1/floare\")==\r\n\r\n==include(page=\"dot-com/2009/solutii/runda-1/galerie\")==\r\n\r\n==include(page=\"dot-com/2009/solutii/runda-1/trilant\")==\r\n',1490,'public',NULL,NULL),('algoritmiada-2010/runda-1','Algoritmiada 2010 - Runda 1','2009-10-25 16:37:51','2009-11-28 15:37:53','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Algoritmiada 2010, Runda 1\r\n\r\n(htabs)*(active) \'Despre...\':algoritmiada-2010/runda-1 \r\n* \'Clasele 5-8\':algoritmiada-2010/runda-1/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-1/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-1/5-8 \r\n\r\nRunda va incepe *Duminica 22 noiembrie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-1/studenti\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':algoritmiada-2010/runda-1/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-1/studenti\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==User(user=\"prostu\" type=\"tiny\")==\r\n* ==User(user=\"ditzoneC\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"marius\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica sau tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('newsletter/algoritmiada-2010-1','Algoritmiada revine! Participă și tu!','2009-11-15 22:24:10','2009-11-16 18:15:57','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎncepe o nouă ediţie a concursului Algoritmiada, cel mai mare şi mai important concurs organizat de infoarena!\r\n\r\nLa Algoritmiada participă elevi de gimnaziu, de liceu, dar şi studenţi (inclusiv masteranzi sau doctoranzi)! Avem grupe separate pentru fiecare.\r\n\r\nAlgoritmiada se desfăşoară în 5 runde: 4 runde online de calificare şi o rundă finală on-site la care invităm concurenţii cu cele mai bune punctaje de la fiecare grupă. Cei mai buni vor fi răsplătiţi cu premii serioase, în bani şi obiecte, dar toată lumea are de câştigat: îţi oferim şansa să cunoşti experţi în domeniu de a căror experienţă vastă poţi profita!\r\n\r\nRunda 1 are loc chiar în acest weekend şi reprezintă şi un ultim test pentru delegaţia României la Olimpiada Balcanică de Informatică 2009 (Bulgaria). Întrece-te cu ei! Dovedeşte-ţi talentul şi cunoştinţele la Algoritmiada!\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Prima rundă se desfăşoară\r\n*Duminică, 22 Noiembrie 2009, orele 09^00^ - 13^00^*. |\r\n\r\nVezi \'pagina concursului\':algoritmiada-2010 ca să afli cum poţi participa.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"algoritmiada-2010/runda-1\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre Algoritmiada\r\n\r\nAlgoritmiada este unicul concurs din România unde pot participa tinerii pasionaţi de informatică de toate vârstele: de la elevi de gimnaziu până la studenţi şi doctoranzi.\r\n\r\nConcursul are patru grupe valorice: gimnaziu, clasele 9-10, clasele 11-12, studenţi (inclusiv masteranzi şi doctoranzi). Participanţii vor avea ocazia să-şi demonstreze talentul, cunostinţele şi ascuţimea minţii în 4 probe online urmând ca cei mai buni sa fie invitaţi la finala on-site. În fiecare rundă vei avea la dispoziţie 4h să rezolvi 3 probleme de natură algoritmică.\r\n\r\nSubiectele vor fi propuse de către o echipă de foşti şi actuali olimpici la informatică: Cosmin Gheorghe, Bogdan Tătăroiu, Paul Băltescu, Filip Ştefan, Marius Stroe, Adrian Airinei, Andrei Grigorean, Ştefan Istrate, Adrian Diaconu şi Filip Buruiană. De ce ei? Intră pe \'pagina organizatorilor\':algoritmiada-2010/comisie şi citeşte câte ceva despre experienţa fiecăruia.\r\n\r\nIntră pe \'pagina concursului\':algoritmiada-2010 ca să afli mai multe informaţii.\r\n\r\nIţi urăm succes şi te asteptăm în arenă!\r\n\r\nh2{font-size: 12pt}. Despre BOI/JBOI 2009\r\n\r\nA XVII-a ediţie a Olimpiadei Balcanice de Informatică (BOI) este găzduită de Bulgaria (în Shumen) şi se desfăşoară în perioada 27-29 noiembrie. Tot în acelaşi timp va avea loc şi cea de-a III-a ediţie a Olimpiadei Balcanice de Informatică pentru Juniori (JBOI). Delegaţiile României sunt alcătuite din:\r\n\r\n* Seniori:\r\n** \'Andrei Pârvu\':utilizator/andrei.12\r\n** \'Şerban Stan\':utilizator/savim\r\n** \'Tiberiu Savin\':utilizator/devilkind\r\n** \'Florin Perţicaş\':utilizator/perticas_catalin\r\n* Juniori:\r\n** \'Vlad Găvrilă\':utilizator/GavrilaVlad\r\n** \'Radu Voroneanu\':utilizator/radu_voroneanu\r\n** \'Marius Petcu\':utilizator/marius21\r\n** \'Mihai Gheorghe\':utilizator/GheorgheMihai\r\n\r\nCele două echipe sunt conduse de către Prof. Constatin Galaţan şi de către prof. Alin Burţă. \r\n\r\nUrăm succes celor două delegaţii ale României! Sperăm ca reprezentanţii noştri să facă ce ştiu cel mai bine, să obţină rezultate excepţionale.\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==',1490,'protected',NULL,NULL),('dot-com/2009/solutii/runda-1/tabara2','dot-com/2009/solutii/runda-1/tabara2','2009-11-15 11:46:57','2009-11-19 08:30:31','h1(#tabara2). \'Tabara2\':problema/tabara2\r\n\r\nSolutia optima este de complexitate $O(M logN + M log*S)$.\r\n\r\n* Pentru a face update-ul de tipul $1$ in complexitate $O(log*S)$ ne vom folosi de \'multimi disjuncte\':problema/disjoint. Astfel, cand trebuie sa unim nodurile $i$ si $j$, unim multimea lui $i$ cu multimea lui $j$. In fiecare radacina a unei multimi disjuncte vom tine si valoarea maxima din multimea respectiva.\r\n\r\n* La update-ul de tipul $2$ vom uni nodul $i$ cu radacina multimii in care se afla nodul $j$. Ca si la update-ul de tipul $1$, vom tine in radacina (in cazul nostru, nodul $i$) valoarea maxima din multimea nou formata. Tot aici vom updata valoarea maxima din nodul i intr-un \'arbore de intervale\':problema/arbint tinut pe nodurile $1 - N$. Complexitatea pentru aceste operatii va fi $O(log*S + logN)$.\r\n\r\n* Fiecare query va fi rezolvat in $O(logN)$ cu ajutorul arborelui de intervale.\r\n',3997,'public',NULL,NULL),('newsletter/algoritmiada-2010-1-rectificare','Rectificare dată Algoritmiada','2009-11-16 18:30:57','2009-11-16 18:32:39','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nNe cerem scuze, dar in newsletter-ul nostru precedent s-a strecurat o greşeală. Prima rundă Algoritmiada 2010 are loc Duminică, 22 *Noiembrie* 2009 între orele 09^00^ - 13^00^, nu Decembrie.\r\n\r\nPuteţi citi newsletterul original făcând click aici: \'newsletter/algoritmiada-2010-1\':newsletter/algoritmiada-2010-1',1490,'public',NULL,NULL),('dot-com/2009/solutii/runda-1/trilant','dot-com/2009/solutii/runda-1/trilant','2009-11-15 11:49:09','2009-11-20 08:12:43','h1(#trilant). \'Trilant\':problema/trilant\r\n\r\nPentru doua noduri $P,Q$ din graf, vom defini $d(P,Q)$ ca fiind drumul de cost minim de la $P$ la $Q$. Pe noi ne intereseaza sa gasim un nod $X$ astfel incat suma $d(A,X)+d(B,X)+d(C,X)$ sa fie minima. Pentru a realiza acest lucru trebuie sa calculam pentru orice nod $K$ din graf $d(A,K),d(B,K) si d(C,K)$. Putem face acest lucru folsind \'Algoritmul lui Dijsktra\':/problema/dijkstra. Nodul solutie va fi acel nod $X$ cu proprietatea ca suma $d(A,X)+d(B,X)+d(C,X)$ sa fie minima.\r\n\r\nPresupunem ca am ales nodul $X$ cu proprietatea de mai sus. Daca drumurile $(X,A)$ si $(X,B)$ nu ar fi disjuncte, atunci stim sigur ca exista un nod $K$ pe lantul de la $X$ la $A$, astfel incat drumurile $(K,A)$ si $(K,B)$ sunt disjuncte. Inseamna ca pe drumul de la $K$ la $X$, vom numara muchiile care apar de doua ori, rezulta ca $X$ nu ar avea proprietatea ca suma $d(A,X)+d(B,X)+d(C,X)$ sa fie minima. Analog daca $(X,A)$ si $(X,C)$ sau $(X,B)$ si $(X,C)$ nu ar fi disjuncte.\r\n\r\nComplexitatea solutiei este O(MlogN).\r\n',9232,'public',NULL,NULL),('blog/problema-saptamanii-subgrup-de-persoane-solutie','Problema saptamanii - Subgrupuri de 3 persoane (Solutie)','2009-11-18 06:04:46','2009-11-18 06:27:05','Voi reformula problema in termeni de grafuri pentru a usura intelegerea explicatiei:\r\n\r\n_Se da un graf complet cu 6 noduri in care fiecare muchie este colorata sau in rosu, sau in albastru. Spunem ca un triplet de noduri (a, b, c) este monocromatic daca muchiile (a, b), (b, c) si (a, c) au acceasi culoare. Se cere sa se demonstreze ca exista cel putin *2* triplete monocromatice._\r\n\r\nSolutia mea este urmatoarea: Numarul total de triplete este egal cu 20. Voi incerca sa demonstrez ca pot fi maxim 18 triplete care nu sunt monocromatice. Pentru a numara cate astfel de triplete sunt, putem sa folosim jmenul de la problema \'Color\':problema/color. Pentru fiecare nod vom inmulti numarul de muchii albastre incidente cu numarul de muchii rosii incidente. Adunand aceste valori si impartind la 2, obtinem numarul de triplete nemonocromatice. Va voi lasa pe voi sa demonstrati aceasta afirmatie :P. Numarul maxim de triplete nemonocromatice se obtine atunci cand pentru fiecare nod in parte produsul dintre numarul de muchii albastre si rosii este cat mai mare. Cum gradul unui nod este egal cu 5, rezulta ca produsul poate fi \'maxim 6\':http://www.youtube.com/watch?v=9DW_jvxbDQs. Deci, numarul maxim de triplete ce nu sunt monocromatice este 6 * 6 / 2 = 18.\r\n\r\nRezolvarea poate fi generalizata pentru grafuri mari.\r\n\r\nSolutii corecte constructive au fost oferite de: Alex Mosoi, Andrei Dragus, Daniel Anghel.',2028,'protected',4273,NULL),('runda/buzesti/clasament','Clasament buzesti','2009-12-14 10:50:20','2009-12-14 10:50:20','h1. Clasament ==roundparam(round_id=\"buzesti\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"buzesti\")==',9859,'round: buzesti',NULL,NULL),('utilizator/gheorghemihai','Profil Gheorghe Mihai','2007-11-21 08:53:27','2010-01-31 18:18:00','h2. Despre mine\r\n\r\nElev in clasa a 8-a la ICHB.\r\n\r\nh2. Distinctii primite\r\n\r\nLocul III ONI 2008, Bacau\r\nLocul I ONI 2009, Galati\r\nLocul I ONI 2010, Slatina\r\n\r\nMedalie de argint la JBOI 2009, Shumen, Bulgaria\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n==user(user=\"savim\" type=\"normal\")==\r\n\r\n==user(user=\"gavrilavlad\" type=\"normal\")==\r\n\r\n==user(user=\"victor.ionescu\" type=\"normal\")==\r\n\r\n==user(user=\"cezarmocan\" type=\"normal\")==\r\n\r\n==user(user=\"raduzer\" type=\"normal\")==\r\n\r\n==user(user=\"protoman\" type=\"normal\")==\r\n\r\n==user(user=\"taloibogdan\" type=\"normal\")==\r\n',7148,'public',NULL,NULL),('template/algoritmiada-2010/header','template/algoritmiada-2010/header','2009-10-25 13:46:02','2010-03-11 15:37:33','p{margin: 2em 0 1em 0; padding: .2em; border: 1px solid silver; -moz-border-radius: 10px;}. !{padding: 1em}>template/algoritmiada-2010?amazon.png!:http://romania.amazon.com/ !{padding: 0.25em 1em}>template/algoritmiada-2010?adobe.png 13%!:http://myadobe.ro/ \'!template/algoritmiada-2010/header?logo2010.jpg 100%!\':algoritmiada-2010',2028,'protected',NULL,NULL),('propuneri/14-grupuri-probleme','IAP #14: Grupuri probleme','2009-11-20 16:54:18','2009-11-20 16:58:15','h1. IAP #14: Grupuri probleme\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2009-11-20 |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"toni2007\")== |\r\n|_. Stare     | *_IN-CONSTRUCTIE_* |\r\n\r\nh2(#abstract). Abstract\r\n\r\nPropun ca pentru fiecare problema sa poata fi asociat un grup de useri care sa poate fi administratori pe acea problema.\r\n\r\nh2(#motivatie). Motivatie\r\n\r\nAceasta functionalitate este utila concursurilor organizate de comunitate, unde un helper nu poate vedea problemele adaugate de un alt helper sau admin pana acestea nu apar in arhiva sau in concurs si nici nu poate trimite solutii.\r\n\r\nh2(#detalii). Detalii\r\n\r\n* Autorul problemei, sau un administrator va putea selecta un grup de useri carora le va acorda drepturi pe acea problema.\r\n* Orice helper / admin va putea adauga un grup nou.\r\n* Helperii vor putea edita doar grupurile create de ei, adaugand sau eliminand utilizatorii din acel grup.\r\n* Orice user din grup va putea edita, atasa fisiere si trimite solutii la acea problema.\r\n* Orice user din grup va putea descarca testele si va putea vedea toate sursele trimise la acea problema.\r\n* Un user din grupul unei probleme nu va putea sterge problema decat daca este cel care a creat-o.\r\n\r\nh2(#implementare). Implementare\r\n\r\n* Se va crea un tabel ia_groups care va contine id-ul grupului, numele grupului si autorul. De asemenea va exista si un tabel ia_groups_users care va contine linii de forma: id-ul grupului si user-ul. Cand se va verifica daca un user este intr-un grup, se va cauta in tabelul ia_groups_users daca exista o linie cu id-ul grupului respectiv si numele user-ului. Cand se vor cauta utilizatorii care apartin unui grup se vor selecta din ia_groups_users toate liniile cu id-ul egal cu cel al grupului.',6061,'public',NULL,NULL),('algoritmiada-2010/runda-1/solutii/arborest','Solutie Arborest','2009-11-21 17:44:13','2009-11-22 21:51:41','h1(#arborest). \'Arborest\':problema/arborest\r\n\r\nSe poate observa usor ca atunci cand modificam tatal unui nod, este cel mai bine sa il modificam in radacina arborelului, $1$. Putem cauta binar adancimea maxima a arborelui. Vrem ca pentru o anumita adancime maxima $q$ sa aflam $nr$ numarul de mutari necesar pentru a aduce arborele la adancimea maxima $q$. Daca $nr$ > $K$ atunci $q$ este prea mic. Altfel $q$ poate scadea in continuare. Pentru a afla $nr$ vom proceda in felul urmator. Fie $Di$ distanta de la radacina la nodul $i$. Sortam toate nodurile descrescator dupa $Di$. Parcurgem nodurile in ordinea sortarii. Sa zicem ca ne aflam la nodul $x$. Daca $Dx$ > $q$ atunci nodul $x$ trebuie urcat. Dar pentru ca nodul $x$ este cel mai de jos nod neurcat inca, vrem sa ducem nodul $x$ la nivelul $q$ schimband tatal celui de al $q-1$-lea tata al lui $x$. Facem acest lucru pentru a ridica cat mai multe noduri deasupra nivelului $q$. Fie $T$ al $q-1$-lea tata al lui $x$. Pentru a urca intreg subarborele lui $T$ parcurgem acest surarbore si marcam toate nodurile din subarbore ca fiind vizitate. Incrementam $nr$. Cand trecem la urmatorul nod ce trebuie ridicat, trebuie sa verificam in plus daca a fost vizitat (daca a fost in subarborele vreunui nod ridicat) ca sa stim ca nu trebuie ridicat. Trebuie de asemenea sa avem grija ca atunci cand parcurgem subarborele unui nod ce trebuie ridicat, sa nu revizitam nodurile ce au fost ridicate inainte pentru ca este inutil (sa nu parcurgem subarborii deja ridicati ai subarborelui ce vrem sa il ridicam in acest moment pentru ca nu este necesar; acest lucru ar duce la o complexitate mult mai mare). \r\n\r\nAceasta abordare duce la o complexitate $N$ log $N$.',2038,'public',NULL,NULL),('algoritmiada-2010/runda-1/solutii/tester','Solutie Tester','2009-11-21 17:44:51','2010-02-08 12:25:05','h1(#tester). \'Tester\':problema/tester\r\n\r\nVom transforma graful rezultat din starile si tastele date astfel: fiecarei taste $i$ ii vom asocia un nod $i$ in noul graf. Oricare doua taste $i$ si $j$ ce pot aparea una dupa alta (sunt de forma ( $x$, $y$ ) si ( $y$, $z$ ) ) le vom lega in noul graf cu o muchie orientata de la $i$ la $j$. Se observa ca in noul graf un combo este reprezentat de o muchie. Faptul ca dorim sa obtinem o secventa cu toate combourile exact odata, adica ce contine toate muchiile exact odata, ne duce cu gandul la o parcurgere euleriana a noului graf. Inainte de a incerca sa construim o parcurgere euleriana a grafului trebuie sa transformam graful intr-unul eulerian. Pentru aceasta procedam in felul urmator. Fie $GINi$ numarul de muchii care intra in nodul $i$ si $GOUTi$ numarul de muchii care ies din nodul $I$. Stim ca intr-un graf eulerian $GINi$ trebuie sa fie egal $GOUTi$. Cream un nou nod $R$ din care si spre care tragem cate muchii sunt necesare pentru a satisface conditia de egalitate intre $GINi$ si $GOUTi$ pentru fiecare nod $i$. Acum putem sa construim un ciclu eulerian incepand din nodul $R$. Secventa creata este exact secventa de taste ce vor fi apasate de Paraschiva. Orice trecere prin nodul $R$ va reprezenta o resetare a jocului (ea denota trecerea printr-o muchie inexistenta din graf), mai putin prima si ultima care nu sunt treceri ci doar marcheaza inceputul si sfarsitul secventei. Secventa rezultata respecta conditia ca fiecare muchie sa fie parcursa exact odata (fiecare combo sa apara exact odata) si numarul de resetari al jocului va fi minim (nu se poate obtine o secventa cu mai putine resetari din cauza naturii grafului).\r\n\r\nSolutia are complexitate $N$ * $M$.',2038,'public',NULL,NULL),('runda/splunge7','splunge7','2009-11-21 20:03:23','2009-11-21 20:03:23','h1. == roundparam(round_id=\"splunge7\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"splunge7\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"splunge7\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"splunge7\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/splunge7/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"splunge7\" score=\"1\")==',4439,'round: splunge7',NULL,NULL),('runda/splunge7/clasament','Clasament splunge7','2009-11-21 20:03:23','2009-11-21 20:03:23','h1. Clasament ==roundparam(round_id=\"splunge7\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"splunge7\")==',4439,'round: splunge7',NULL,NULL),('algoritmiada-2010/runda-1/solutii/perle2','Solutie Perle2','2009-11-21 17:41:36','2009-11-22 21:08:44','h1(#perle2). \'Perle2\':problema/perle2\r\n\r\nSe observă că găsirea unei subsecvenţe $[i,j]$ care maximizează valoarea $(A[i]+A[i+1]+...+A[j]) - K*(j-i+1)$ este echivalentă cu găsirea unei subsecvenţe care maximizează valoarea $A[i]-K+A[i+1]-K+...+A[j]-K$. Această observaţie duce la ideea de a scădea K din fiecare element al vectorului iniţial şi de a căuta apoi subsecvenţa de sumă maximă. Subsecvenţa de sumă maximă (mai multe detalii \'aici\':problema/ssm) poate fi localizată în complexitate timp $O(N)$, iar o soluţie ce ar fi implementat această idee ar fi obţinut $100$ de puncte.',1792,'public',NULL,NULL),('algoritmiada-2010/runda-1/solutii/iopds','Solutie Iopds','2009-11-21 17:41:03','2009-11-22 21:08:16','h1(#iopds). \'Iopds\':problema/iopds\r\n\r\nSe pot obtine $30$ de puncte folosind o abordare de tip backtracking, construind pe rand toate sirurile care respecta conditia din enunt.\r\nDe asemeni, $30$ de puncte se obtin folosindu-ne de propritatea $A = B = 0.000$ si $C > 0.000$. Atunci relatia se transforma in $C * X{~i~} * X{~i-1~} > 0$, pentru ca aceasta sa fie respectata atunci atat $X{~i~}$ cat si $X{~i-1~}$ trebuie sa aiba aceiasi signatura, de unde rezulta ca subsirul va fi format fie numai din numere pozitive, fie numai din numere negative. Fie $poz$ numarul de numere pozitive din sirul initial, atunci ele pot forma $2^poz^-poz-1$ subsiruri. Pentru a afla subsirurile de numere negative se procedeaza asemanator.\r\nUn program care pentru $N < 12$ calculeaza rezultatul folosind backtracking iar pentru $A = B = 0.000$ calculeaza rezultatul cu ajutorul formulei ar obtine $50$ de puncte.\r\nSolutia de 100 de puncte contruieste rezultatul folosind programarea dinamica, sa consideram $D[i] = numarul de subsiruri care il au pe ultima pozitia pe V{~i~}$. Pe $D$ il putem calcula astfel $D[i] = suma(D[j] + 1)$ daca $A * V{~i~}^2^ + B * V{~j~}^2^ + C * V{~i~} * V{~j~} > 0$. Aceasta formula reiese din observatia ca daca $V{~i~}$ si $V{~j~}$ respecta conditia, atunci il putem pune pe $V{~i~}$ la sfarsitul oricarui subsir care se termina cu $V{~j~}$. Aceasta solutia are complexitatea O(N^2^).\r\nProblema poate fi rezolvata si in complexitate $O(NlogN)$ rezolvand inegalitatea in functie de parametrul $X{~i~}$ si folosind o structura de date care permite calcularea sumei pe un interval si update-ul unui element in $logN$, ramane ca tema pentru cei interesati.',1792,'public',NULL,NULL),('utilizator/ionut.pic','Profil ionut.pic','2009-11-22 13:18:12','2009-11-22 13:18:12','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',11322,'public',NULL,NULL),('runda/page1contest/clasament','Clasament page1contest','2009-11-22 19:59:06','2009-11-22 19:59:06','h1. Clasament ==roundparam(round_id=\"page1contest\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"page1contest\")==',7156,'round: page1contest',NULL,NULL),('runda/page1supercontest','page1supercontest','2009-11-22 20:00:09','2009-11-22 20:00:09','h1. == roundparam(round_id=\"page1supercontest\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"page1supercontest\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"page1supercontest\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"page1supercontest\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/page1supercontest/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"page1supercontest\" score=\"1\")==',7156,'round: page1supercontest',NULL,NULL),('runda/page1supercontest/clasament','Clasament page1supercontest','2009-11-22 20:00:09','2009-11-22 20:00:09','h1. Clasament ==roundparam(round_id=\"page1supercontest\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"page1supercontest\")==',7156,'round: page1supercontest',NULL,NULL),('algoritmiada-2010/runda-1/solutii/pitici4','Solutie Pitici4','2009-11-21 17:43:35','2009-12-12 22:30:03','h1(#pitici4). \'Pitici4\':problema/pitici4\r\n\r\nObservăm că este util să ordonăm piticii în funcţie de $A$ şi în caz de egalitate în funcţie de $B$ pentru ca piticii cu aceleaşi informaţii să fie grupaţi. Vom folosi apoi metoda programării dinamice pentru a determina răspunsul căutat. Fie $C[i] = numărul maxim de pitici a căror informaţii nu se contrazic care aparţin unor grupuri care se termină înainte de poziţia i$. Pentru a obţine recurenţa, ne gândim că la poziţia $i+1$ vom încerca să formăm un nou grup. Are rost să luăm în considerare în acest moment doar acei pitici $j$ cu propritatea că $A[j] = i$. Găsirea acestora nu presupune o iteraţie liniară, datorită sortării iniţiale. Vom crea mai multe grupuri noi conţinând piticii cu acelaşi $B$. Să presupunem că un astfel de grup conţine $nr$ pitici. Atunci recurenţa va fi $C[N-B[j]] = max(C[N-B[j]], C[i] + min(N-A[j]-B[j], nr))$, deoarece grupul se va termina la poziţia $N-B[j]$ şi numărul de pitici din noul grup nu poate depăşi $N-A[j]-B[j]$. Nu trebuie uitat cazul în care grupul format conţine un singur pitic care minte, caz banal de tratat: $C[i+1] = max(C[i+1], C[i])$.',7148,'public',NULL,NULL),('algoritmiada-2010/runda-1/solutii/vrejuri','Solutie Vrejuri','2009-11-21 17:43:54','2009-11-22 21:28:32','h1(#vrejuri). \'Vrejuri\':problema/vrejuri\r\n\r\nFie $Sm$ suma totala a vrejurilor la finalul celor $K$ zile daca nu ar fi taiate. Trebuie ca in total sa scadem $Sm$ - $S$ din vrejuri. Pentru ca efortul depus pentru o operatie este patratul a cat taiem, trebuie sa incercam ca suma totala ce trebuie scazuta sa o impartim in taieri cat mai echilibrate (de exemplu daca vrem sa taiem un total de $7$ in 3 operatii cel mai bine este $2$, $2$ si $3$). Asadar fie $xi$ totalul pe care vrem sa il taiem din planta $i$. Vrem ca suma toturor $xi$-urilor sa fie egala cu $Sm$ - $S$ si $xi$-ul maxim sa fie cat mai mic posibil. In acelasi timp vrem ca fiecare $xi$ sa fie impartit in cele $K$ zile cat mai echilibrat posibil. \r\n\r\nPentru aceasta putem cauta binar $xi$-ul maxim pe care il taiem. Fie $q$ aceasta valoare. Din fiecare planta vom taia min( $q$, $Hi$ + $K$ * $Pi$ ). Fie $ST$ = suma dupa $i=1,N$ din min( $q$, $Hi$ + $K$ * $Pi$ ). Daca $ST$ < $Sm$ - $S$ atunci $q$ este prea mic. Daca $ST$ > $Sm$ - $S$ atunci $q$ este prea mare. Daca cele doua sunt egale atunci $q$ este valoarea cautata si am descoperit $xi$ = min( $q$, $Hi$ + $K$ * $Pi$ ), cat taiem din fiecare planta. Tot ce ramane de facut este sa impartim fiecare $xi$ in $K$ valori cat mai egale. Vom avea $K$ - $xi mod K$ valori egale cu $xi$ / $K$ si $xi mod K$ valori egale cu $xi$ / $K$ + $1$ (exemplu de mai sus cu valoarea $7$ impartita in $3$ valori cat mai egale este concludenta). Costul total va fi suma patratelor fiecarei taieturi individuale.\r\n\r\nAceasta solutie are o complexitate $N$ * $log val_max$, unde $val_max$ este valoarea maxima pe care o poate atinge un vrej. O solutie $N$ * $log N$ se poate obtine daca sortam vrejurile dupa inaltimea finala la care ajung netaiate, si aflam $q$ fara o cautare binara.',2038,'public',NULL,NULL),('algoritmiada-2010/runda-1/solutii/studenti','Solutie Studenti','2009-11-21 17:42:57','2009-11-25 09:04:02','h1(#studenti). \'Studenti\':problema/studenti\r\n\r\nFie $Gmax$ si $Hmax$ greutatea maxima a unui student, respectiv inaltimea maxima a unui student. Distingem doua cazuri elementare de a repartiza studentii in sali. Primul caz este sa plasam atat studentul cu cea mai mare inaltime cat si studentul cu cea mai mare greutate in aceiasi sala, sa spunem ca ii plasam in sala $S1$. Atunci este clar ca in celelalte doua sali se va afla cate un singur student, deoarece orice student poate intra in sala $S1$ fara sa modifice greutatea sau intaltimea maxima din sala. Astfel complexitatea pentru acest caz este $O(N^2^)$. Al doilea caz elementar este cand $Gmax$ si $Hmax$ se afla in sali diferite. Sa spunem ca studentul cu greutatea $Gmax$ il vom repartiza in sala $S1$ iar cel cu intaltimea $Hmax$ in sala $S2$. Vom lua fiecare posibilitate de a fixa inaltimea maxima din sala $S1$ si greutatea maxima din sala $S2$. Apoi iteram prin fiecare student in parte si vedem daca el poate fi repartizat in $S1$ sau $S2$ fara sa modifice greutatea maxima sau inaltimea maxima din sala respectiva. Daca nu poate fi repartizat in $S1$ sau $S2$ il repartizam in $S3$. Complexitatea acestui caz este $O(N^3^)$.',3689,'public',NULL,NULL),('algoritmiada-2010/runda-1/solutii/kss','Solutie Kss','2009-11-21 17:44:35','2010-02-08 12:22:43','h1(#kss). \'Kss\':problema/kss\r\n\r\nPentru a rezolva aceasta problema vom incerca o abordare de genul urmator. Daca am putea raspunde la intrebarea: \"Avand un prefix oarecare, cate subsiruri distincte incep cu acest prefix?\", putem incerca sa cautam fiecare litera pe rand din solutie pana cand gasim intregul sir cerut. Construim o dinamica $din[ i ]$ = numarul de subsiruri distincte care incep de pe pozitia $i$ si contin litera de pe pozitia $i$. Ca sa rezolvam aceasta dinamica mai intai definim $next[ c ][ i ]$ = prima pozitie dupa $i$ pe care apare caracterul $c$ (daca $c$ apare fix pe pozitia $i$ atunci $next[ c ][ i ]$ = $i$). Vom calcula dinamica de la pozitia $N$ spre pozitia $1$, iar recurenta este: $din[ i ]$ = $1$ + suma dupa $c = a,z$ din $din[ next[ c ][ i + 1 ] ]$. Luam doar prima aparatie a fiecarui caracter pentru ca subsirurile sunt distincte dupa valoare, si nu dupa pozitiile pe care apar caracterele in sirul initial; luam in calcul si cazul cand subsirul contine doar caracterul curent. Avand aceasta dinamica putem incepe sa cautam solutia, pentru ca putem raspunde la intrebarea intiala astfel: daca avem un prefix $p$, il potrivim ca subsir peste sirul $S$ astfel incat ultimul caracter al lui $p$ apare cat mai repede in $S$ (de exemplu pentru $p = a b$ si $S = c a b b$ vom potrivi $c **a b** b$ si nu $c **a** b **b**$ ). Fie $q$ aceasta pozitie a ultimul caracter din $p$. Numarul de subsiruri care incep cu acest prefix $p$ este din[ q ] si se observa usor de ce. \r\n\r\nIn continuare voi explica mai detaliat cum gasim propriu-zis solutia. Dorim sa gasim al $K$-lea subsir. Sa presupunem mai intai ca sirul nostru incepe cu litera $a$. Determinam acel $q$ (am explicat mai sus ce reprezinta). Daca cumva $din[q]$ < $K$ atunci inseamna ca solutia nu va incepe cu $a$ ci cu o litera mai mare (lexicografic) pentru ca nu sunt suficiente subsiruri care incep cu $a$. Scadem din $K$, $din[q]$ si incercam urmatoarea litera $b$ pentru ca aplicam acelasi rationament (incercam sa gasim al $K-din[q]$-lea subsir care nu incepe cu $a$ ). Cand $din[q]$ >= $K$ inseamna ca litera curenta este cea buna si atunci trebuie sa gasim urmatoarea (la acest pas trebuie sa scadem $1$ din $K$ pentru ca sirul care se termina fix cu litera curenta apare lexicografic inaintea celor ce vor urma, mai lungi). Pentru urmatoarea litera aplicam acelasi rationament decat ca trebuie sa avem grija ca acum inceputul solutiei este un prefix si nu doar o litera. Ne oprim atunci cand $K$-ul ramas devine $0$ (adica tocmai am pus ultima litera).\r\n\r\nSolutia aceasta are o complexitate $N$ * $sigma$ pe fiecare test ( $sigma$ este numarul de caractere din alfabet).',2038,'public',NULL,NULL),('runda/splunge8','splunge8','2009-11-23 17:40:54','2009-11-23 17:40:54','h1. == roundparam(round_id=\"splunge8\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"splunge8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"splunge8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"splunge8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/splunge8/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"splunge8\" score=\"1\")==',4439,'round: splunge8',NULL,NULL),('runda/splunge8/clasament','Clasament splunge8','2009-11-23 17:40:54','2009-11-23 17:40:54','h1. Clasament ==roundparam(round_id=\"splunge8\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"splunge8\")==',4439,'round: splunge8',NULL,NULL),('runda/i1-reloaded','Reloaded Contest 1','2009-11-23 17:57:02','2009-11-23 18:03:13','h1. Reloaded Contest 1\r\n\r\nh3. Problemele propuse sunt cele de la Algoritmiada 2010 Runda 1 clasele 5-8.\r\n\r\nh3. Cei care n-au avut ocazia sa participe la concursul initial pot participa la varianta reloaded a lui :))\r\n\r\nh1. \'*Clasamentul*\':runda/i1-reloaded/clasament\r\n\r\n==Tasks(round_id=\"i1-reloaded\" score=\"1\")==',10498,'round: i1-reloaded',NULL,NULL),('runda/i1-reloaded/clasament','Clasament Reloaded Contest 1','2009-11-23 17:57:02','2009-11-23 18:03:45','h1. Felicitari !\r\n\r\n==Rankings(rounds = \"i1-reloaded\")==',10498,'round: i1-reloaded',NULL,NULL),('propuneri/15-task-tagging','IAP #15: Task tagging','2009-11-26 08:50:05','2010-01-12 20:45:35','h1. IAP #15: Task tagging\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2009-11-26 |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"bogdan2412\")== |\r\n|_. Stare     | *APROBAT* |\r\n\r\nh2(#abstract). Abstract\r\n\r\nSe propune crearea unui sistem prin care fiecarei probleme ii vor fi asociate informatii sub forma de taguri si a unui sistem de cautare bazat pe aceste taguri.\r\n\r\nh2(#motivatie). Motivatie\r\n\r\nArhiva de probleme devine din ce in ce mai mare si din ce in ce mai greu de navigat. Un astfel de sistem ar ajuta utilizatorii sa filtreze mult mai usor probleme in functie de mai multe informatii.\r\n\r\nPropun ca urmatoarele informatii sa fie asociate fiecarei probleme:\r\n\r\n* Autorul sau autorii problemelor (daca o problema a fost propusa de catre mai multi autori, fiecare autor va avea un tag separat).\r\n* Concursul (si runda) la care a fost data problema. Pentru problemele date la concursuri pe infoarena ar fi bine de mentinut si un tag cu grupa de varsta la care a fost data problema (din nou, daca o problema a fost data la mai multe grupe de varsta, fiecare grupa de varsta va avea un tag separat).\r\n** Spre exemplu tagurile asociate problemei \"vrejuri\":problema/vrejuri ar fi \"Algoritmiada 2010\", \"Algoritmiada 2010, Runda 1\", \"Algoritmiada 2010, Runda 1, 9-10\"\r\n* Cunostintele necesare rezolvarii problemelor. In aceasta categorie intra orice fel de algoritm classic cunoscut (un punct bun de plecare ar fi \"Training Path\":training-path).\r\n** Propun sa impartim aceste taguri in doua categorii: \"Generale\" (Grafuri, Programare Dinamica, Greedy, Structuri de date, Geometrie) si \"Specifice\" (Deque, Arbori echilibrati, Codul Gray, Minimal enclosing circle). Tag-urile generale nu iti ofera foarte multe informatii care ar putea strica farmecul problemelor, in timp ce cele \"specifice\" iti zic exact ce algoritmi sunt necesari pentru rezolvarea problemei. Fiecare din tagurile \"specifice\" se va incadra intr-o categorie denumita de un tag general. (spre exemplu Deque intra sub Structuri de date)\r\n** In momentul in care utilizatorul deschide o problema, tagurile sunt ascunse by default. Daca acesta vrea un hint de rezolvare, ii aratam intai tagurile generale. Daca vrea si mai multe hinturi, ii aratam toate tagurile.\r\n\r\nh2(#implementare). Implementare\r\n\r\nUn astfel de sistem implica adaugarea unei noi coloane in tabelul $ia_tags$ sau $ia_task_tags$ care sa mentina pentru fiecare tag de ce tip este. Pentru a putea face o interfata frumoasa, ne trebuie sa stim pentru fiecare tag daca el este pentru:\r\n\r\n* un \"autor\"\r\n* un \"concurs\"\r\n* o \"runda din concurs\"\r\n* o \"grupa de varsta\"\r\n* o \"categorie de algoritmi\" (tag-urile de cunostinte generale)\r\n* un \"algoritm\".\r\n\r\nInterfata de filtrare dupa taguri ar trebui sa-ti dea o lista frumoasa cu toate tagurile pentru un autor, concurs, algoritm etc. Datorita separarii intre taguri de \"concurs\", de \"runda\" si de \"grupa de varsta\", odata ce utilizatorul a selectat un concurs dupa care vrea sa filtreze i se da optiunea de a filtra si dupa o runda a acelui concurs (daca acesta doreste), si dupa aceea i se da optiunea de a selecta si o anumita grupa de varsta.\r\n\r\nh2(#feedback). Feedback\r\n',1490,'public',4309,NULL),('utilizator/petru000','Profil petru000','2009-11-27 08:36:47','2009-11-27 08:36:47','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',11349,'public',NULL,NULL),('runda/suma1/clasament','Clasament suma1','2009-12-25 21:56:13','2009-12-25 21:56:13','h1. Clasament ==roundparam(round_id=\"suma1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"suma1\")==',11514,'round: suma1',NULL,NULL),('runda/vlad','vlad','2009-12-13 15:39:36','2009-12-13 15:39:36','h1. == roundparam(round_id=\"vlad\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"vlad\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"vlad\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"vlad\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/vlad/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"vlad\" score=\"1\")==',11272,'round: vlad',NULL,NULL),('runda/vlad/clasament','Clasament vlad','2009-12-13 15:39:36','2009-12-13 15:39:36','h1. Clasament ==roundparam(round_id=\"vlad\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"vlad\")==',11272,'round: vlad',NULL,NULL),('utilizator/alecss','Profil AlecSs','2009-11-28 10:20:58','2009-11-28 10:20:58','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',11356,'public',NULL,NULL),('runda/proba','proba','2009-11-28 12:02:29','2009-11-28 12:02:29','h1. == roundparam(round_id=\"proba\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"proba\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"proba\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"proba\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/proba/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"proba\" score=\"1\")==',11055,'round: proba',NULL,NULL),('runda/proba/clasament','Clasament proba','2009-11-28 12:02:29','2009-11-28 12:02:29','h1. Clasament ==roundparam(round_id=\"proba\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"proba\")==',11055,'round: proba',NULL,NULL),('algoritmiada-2010/runda-2/11-12','Algoritmiada 2010 Runda 2, Clasele 11-12','2009-11-28 15:29:53','2009-11-28 15:48:56','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda2-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-1 \r\n* \'Clasele 5-8\':algoritmiada-2010/runda-2/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-2/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2010/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-2/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-2/11-12\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda2-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2010-runda2-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2010-runda2-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-2/11-12.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda2-11-12\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'round: algoritmiada2010-runda2-11-12',NULL,NULL),('runda/teqquila_shot','teqquila_shot','2009-11-28 16:06:15','2009-11-28 16:06:15','h1. == roundparam(round_id=\"teqquila_shot\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"teqquila_shot\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"teqquila_shot\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"teqquila_shot\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/teqquila_shot/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"teqquila_shot\" score=\"1\")==',6957,'round: teqquila_shot',NULL,NULL),('algoritmiada-2010/runda-2/5-8','Algoritmiada 2010 - Runda 2, Clasele 5-8','2009-11-28 15:29:53','2009-11-28 15:49:29','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda2-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-2 \r\n*(active) \'Clasele 5-8\':algoritmiada-2010/runda-2/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-2/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-2/5-8\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda2-5-8\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2010-runda2-5-8\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2010-runda2-5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-2/5-8.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda2-5-8\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'round: algoritmiada2010-runda2-5-8',NULL,NULL),('runda/teqquila_shot/clasament','Clasament teqquila_shot','2009-11-28 16:06:15','2009-11-28 16:06:15','h1. Clasament ==roundparam(round_id=\"teqquila_shot\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"teqquila_shot\")==',6957,'round: teqquila_shot',NULL,NULL),('algoritmiada-2010/runda-2/9-10','Algoritmiada 2010 - Runda 2, Clasele 9-10','2009-11-28 15:29:53','2009-11-28 15:49:14','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda2-9-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-2 \r\n* \'Clasele 5-8\':algoritmiada-2010/runda-2/5-8 \r\n*(active) \'Clasele 9-10\':algoritmiada-2010/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-2/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-2/9-10\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda2-9-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2010-runda2-9-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2010-runda2-9-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-2/9-10.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda2-9-10\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'round: algoritmiada2010-runda2-9-10',NULL,NULL),('algoritmiada-2010/runda-2/studenti','Algoritmiada 2010 Runda 2, Studenti','2009-11-28 15:29:53','2009-11-28 15:51:55','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda2-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-2\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-2/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-2/11-12\r\n*(active) \'Studenti\':algoritmiada-2010/runda-2/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-2/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda2-studenti\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2010-runda2-studenti\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2010-runda2-studenti\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-2/studenti.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda2-studenti\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'round: algoritmiada2010-runda2-studenti',NULL,NULL),('utilizator/savim','Stan Serban Andrei','2006-11-24 21:08:05','2010-04-13 16:27:14','h2. Despre mine\r\n\r\nSunt elev in clasa a X-a la ICHB. \r\n\r\nh2. Distincţii primite \r\n\r\nMenţiune ONI 2005(locul 5), Galaţi\r\nMenţiune ONI 2006(locul 10), Târgovişte\r\nLocul III ONI 2007, Cluj\r\nLocul I ONI 2008, Bacau\r\nLocul III ONI 2009, Galati\r\nMedalie de argint la CEOI 2009, Târgu Mureş, România\r\nMedalie de bronz la BOI 2009, Shumen, Bulgaria\r\n\r\nLocul I la finala Algortimiada 2009\r\nLocul II la finala .campion 2009\r\n\r\nPremii la concursurile judeţene si interjudeţene de matematică\r\n\r\nh2. Profesori \r\n\r\n==user(user=\"pauldb\" type=\"tiny\")== \r\n==user(user=\"wefgef\" type=\"tiny\")== \r\n==user(user=\"silviug\" type=\"tiny\")== \r\n==user(user=\"bogdan2412\" type=\"tiny\")== \r\n==user(user=\"gcosmin\" type=\"tiny\")== \r\n\r\nh2. Prieteni \r\n\r\n==user(user=\"gavrilavlad\" type=\"tiny\")== \r\n==user(user=\"andrei-alpha\" type=\"tiny\")==  \r\n==user(user=\"raduzer\" type=\"tiny\")== \r\n==user(user=\"Protoman\" type=\"tiny\")== \r\n==user(user=\"gheorghemihai\" type=\"tiny\")== \r\n==user(user=\"toni2007\" type=\"tiny\")== \r\n==user(user=\"CezarMocan\" type=\"tiny\")== \r\n==user(user=\"radu_voroneanu\" type=\"tiny\")== \r\n==user(user=\"perticas_catalin\" type=\"tiny\")== \r\n==user(user=\"devilkind\" type=\"tiny\")== \r\n==user(user=\"andrei.12\" type=\"tiny\")== \r\n==user(user=\"tamas_iulia\" type=\"tiny\")== \r\n==user(user=\"ilinca\" type=\"tiny\")== \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n',4827,'protected',NULL,NULL),('algoritmiada-2010/clasament/runda-2/9-10','Algoritmiada 2010 - Clasament Runda 2, Clasele 9-10','2009-11-28 15:30:17','2009-11-28 15:54:39','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda2-9-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-2\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-2/studenti\r\n*(active) \'Rezultate\':algoritmiada-2010/clasament/runda-2/9-10\r\n\r\n==include(page=\"template/algoritmiada-2010/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-2/5-8\r\n*(active) \'Clasele 9-10\':algoritmiada-2010/clasament/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-2/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda2-9-10\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1792,'protected',NULL,NULL),('algoritmiada-2010/clasament/runda-2/5-8','Algoritmiada 2010 - Clasament Runda 2, Clasele 5-8','2009-11-28 15:30:17','2009-11-28 15:55:18','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda2-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-2\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-2/studenti\r\n*(active) \'Rezultate\':algoritmiada-2010/clasament/runda-2/5-8\r\n\r\n==include(page=\"template/algoritmiada-2010/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasele 5-8\':algoritmiada-2010/clasament/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-2/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda2-5-8\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1792,'protected',NULL,NULL),('algoritmiada-2010/clasament/runda-2/11-12','Algoritmiada 2010 - Clasament Runda 2, Clasele 11-12','2009-11-28 15:30:17','2009-11-28 15:53:58','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda2-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-2\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-2/studenti\r\n*(active) \'Rezultate\':algoritmiada-2010/clasament/runda-2/11-12\r\n\r\n==include(page=\"template/algoritmiada-2010/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-2/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2010/clasament/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-2/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda2-11-12\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1792,'protected',NULL,NULL),('algoritmiada-2010/clasament/runda-2/studenti','Algoritmiada 2010 - Clasament Runda 2, Studenti','2009-11-28 15:30:17','2009-11-28 15:53:14','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda2-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-2\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-2/studenti\r\n*(active) \'Rezultate\':algoritmiada-2010/clasament/runda-2/studenti\r\n\r\n==include(page=\"template/algoritmiada-2010/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-2/11-12\r\n*(active) \'Studenti\':algoritmiada-2010/clasament/runda-2/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda2-studenti\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1792,'protected',NULL,NULL),('runda/drg','drg','2009-11-30 16:46:01','2009-11-30 16:46:01','h1. == roundparam(round_id=\"drg\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"drg\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"drg\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"drg\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/drg/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"drg\" score=\"1\")==',3775,'round: drg',NULL,NULL),('runda/drg/clasament','Clasament drg','2009-11-30 16:46:01','2009-11-30 16:46:01','h1. Clasament ==roundparam(round_id=\"drg\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"drg\")==',3775,'round: drg',NULL,NULL),('runda/preoji_2010','preoji_2010','2009-12-01 05:52:27','2009-12-01 05:52:27','h1. == roundparam(round_id=\"preoji_2010\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"preoji_2010\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoji_2010\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoji_2010\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/preoji_2010/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"preoji_2010\" score=\"1\")==',9902,'round: preoji_2010',NULL,NULL),('runda/preoji_2010/clasament','Clasament preoji_2010','2009-12-01 05:52:27','2009-12-01 05:52:27','h1. Clasament ==roundparam(round_id=\"preoji_2010\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoji_2010\")==',9902,'round: preoji_2010',NULL,NULL),('runda/preoji2010','preoji2010','2009-12-01 05:52:56','2009-12-01 05:52:56','h1. == roundparam(round_id=\"preoji2010\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"preoji2010\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"preoji2010\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"preoji2010\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/preoji2010/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"preoji2010\" score=\"1\")==',9902,'round: preoji2010',NULL,NULL),('runda/preoji2010/clasament','Clasament preoji2010','2009-12-01 05:52:56','2009-12-01 05:52:56','h1. Clasament ==roundparam(round_id=\"preoji2010\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"preoji2010\")==',9902,'round: preoji2010',NULL,NULL),('utilizator/cezarmocan','Cezar','2006-11-24 20:59:14','2010-02-04 15:35:54','h2. Despre mine\r\n\r\n* Elev in clasa a 10-a la ICHB\r\n* Pana in clasa a 8-a am studiat la Colegiul National Emil Racovita Cluj-Napoca, iar din clasa a 9-a invat la Liceul International de Informatica Bucuresti. \r\n* Am inceput sa fac programare din clasa a 3-a si intr-a 4-a am luat mentiune la nationala\r\n* Lucrez pe infoarena de prin clasa a 5-a, si pot spune ca e una din principalele mele surse de pregatire\r\n* Imi place sa citesc si sa ascult muzica buna (rock si nu numai)\r\n* Practic cu placere sporturi ca tenis, inot, ciclism, fotbal, ski, patinaj\r\n\r\n\r\nh2. Distinctii primite\r\n\r\nh3. Clasa a IV-a\r\n\r\n* Mentiune la ONI Buzau 2004 la clasa a V-a\r\n\r\nh3. Clasa a V-a\r\n\r\n* Locul 1 la ONI Galati 2005\r\n* Locul 2 la Concursul Interjudetean de Matematica Grigore Moisil\r\n\r\nh3. Clasa a VI-a\r\n\r\n* Mentiune (locul 4) la ONI Targoviste 2006\r\n* Locul 1 la Concursul Palatelor Copiilor Satu Mare 2006\r\n* Locul 1 la PACO Bucuresti 2006\r\n* Locul 5 la finala preONI 2006\r\n* Participare la finala .Campion 2006\r\n* Locul 1 la Concursul Interjudetean de Matematica Dumitru Tiganetea\r\n\r\nh3. Clasa a VII-a\r\n\r\n* Locul 1 la Grigore Moisil 2007 Oradea\r\n* Locul 1 la ONI 2007 Cluj-Napoca\r\n* Locul 4 la Finala .Campion 2007\r\n* Calificare la Finala preONI 2007\r\n* Locul 5 cu echipa scolii la concursul ACSL 2007 - Houston\r\n* Mentiune la JBOI 2007 (locul 13, primul sub bronz)\r\n* Participare la Olimpiada Nationala de Matematica\r\n* Calificare la faza nationala a concursului de matematica \"Cangurul\"\r\n\r\nh3. Clasa a VIII-a\r\n\r\n* Locul 1 la concursul \"Stelele Informaticii\" 2007 la clasa a 9-a (locul 3 la general)\r\n* Locul 9 (mentiune) la ONIGim Bacau 2008\r\n* Locul 1 la Grigore Moisil 2008 Cluj-Napoca\r\n* Locul 1 la finala preONI 2008 cls. 5-8\r\n* Locul 1 la finala .Campion 2008 grupa S\r\n* Locul 5 cu echipa scolii la concursul ACSL 2008 - Baltimore\r\n* Locul 1 (cu punctaj maxim) la JBOI 2008 by NET\r\n* Locul 1 la Concursul Palatelor Copiilor Satu Mare 2008\r\n* Calificare la faza nationala a concursului de matematica \"Cangurul\"\r\n\r\nh3. Clasa a IX-a\r\n\r\n* Calificare in finala concursului Topcoder Highschool Tournament 2009\r\n* Locul 2 la concursul \"Stelele Informaticii 2009\" \r\n* Premiul 3 (locul 4) la ONI Galati 2009\r\n* Locul 3 la finala Algoritmiada 2009\r\n* Calificat la finala .Campion 2009 la grupele Small si Medium\r\n* Locul 3 la CCEX 2009\r\n* Primul clasat la loturile online\r\n\r\nh4. Toate aceste rezultate se datoreaza pregatirii temeinice cu profesorii mei de pana acum: Negreanu-Maior Lucia, Negreanu-Maior Adrian, Ilea Lucian, Ali Yuksel, Baltescu Paul, Ganceanu Silviu, Grigorean Andrei.\r\nTot respectul si consideratia pentru acesti oameni deosebiti.\r\n\r\n\r\nh2. Profesori pe infoarena\r\n\r\n ==User(user=\"pauldb\" type=\"tiny\")==\r\n ==User(user=\"silviug\" type=\"tiny\")== \r\n ==User(user=\"wefgef\" type=\"tiny\")== \r\n ==User(user=\"gcosmin\" type=\"tiny\")==\r\n ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n ==User(user=\"raduzer\" type=\"tiny\")==\r\n ==User(user=\"victor.ionescu\" type=\"tiny\")==\r\n ==User(user=\"savim\" type=\"tiny\")==\r\n ==User(user=\"GavrilaVlad\" type=\"tiny\")==\r\n ==User(user=\"tvlad\" type=\"tiny\")==\r\n ==User(user=\"toni2007\" type=\"tiny\")==\r\n ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n ==User(user=\"GheorgheMihai\" type=\"tiny\")==\r\n ==User(user=\"mariusdrg\" type=\"tiny\")==\r\n ==User(user=\"devilkind\" type=\"tiny\")==\r\n ==User(user=\"alexthero\" type=\"tiny\")==\r\n ==User(user=\"protoman\" type=\"tiny\")==\r\n ==User(user=\"radu_voroneanu\" type=\"tiny\")==\r\n ==User(user=\"freak93\" type=\"tiny\")==\r\n ==User(user=\"andrei.12\" type=\"tiny\")==\r\n ==User(user=\"gabitzish1\" type=\"tiny\")==\r\n',1430,'protected',NULL,NULL),('probleme/hamilton','probleme/hamilton','2009-12-05 08:55:22','2009-12-05 08:58:16','Dându-se un graf orientat, să se determine un ciclu hamiltonian (dacă există).\r\nInput: 6 6 (nr varfuri (n=6), nr muchi (m=6))\r\n1 2 ( legaturile )\r\n2 3  ...\r\n3 4\r\n4 5\r\n5 6\r\n6 1 ',11399,'public',NULL,NULL),('runda/problemiada_6/clasament','Clasament problemiada_6','2009-12-05 12:41:59','2009-12-11 20:59:39','h1. Clasament ==roundparam(round_id=\"problemiada_6\" param=\"title\") ==\r\n\r\n\r\n==Rankings(rounds = \"problemiada_6\")==',5748,'round: problemiada_6',NULL,NULL),('runda/problemiada_6','\" Inca nu ma clatin, picioarele ma tin. \"','2009-12-05 12:41:59','2009-12-05 12:45:42','h1. == roundparam(round_id=\"problemiada_6\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"problemiada_6\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"problemiada_6\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"problemiada_6\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/problemiada_6/clasament.\r\n\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"problemiada_6\" score=\"1\")==',5748,'round: problemiada_6',NULL,NULL),('schimbare-borladnd','schimbare-borladnd','2009-12-06 12:09:59','2009-12-06 12:09:59','Scrie aici despre schimbare-borladnd',11409,'public',NULL,NULL),('runda/prima','prima','2009-12-07 13:05:12','2009-12-07 13:05:12','h1. == roundparam(round_id=\"prima\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"prima\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"prima\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"prima\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/prima/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"prima\" score=\"1\")==',11400,'round: prima',NULL,NULL),('runda/prima/clasament','Clasament prima','2009-12-07 13:05:12','2009-12-07 13:05:12','h1. Clasament ==roundparam(round_id=\"prima\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"prima\")==',11400,'round: prima',NULL,NULL),('runda/razvy_round1','razvy_round1','2009-12-07 16:29:32','2009-12-07 16:37:44','h1. == roundparam(round_id=\"razvy_round1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"razvy_round1\") ==\r\n\r\nProblemele de la acest concurs sunt generate de softul pe care-l puteti gasi \'*aici*\':/utilizator/pavelrazvan?action=download&file=Informatica.rar&safe_only=false.\r\n\r\nConcursul incepe ==roundparam(round_id=\"razvy_round1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"razvy_round1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/razvy_round1/clasament.\r\n\r\nh2.                          Succes !\r\nProbleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"razvy_round1\" score=\"1\")==',6958,'round: razvy_round1',NULL,NULL),('runda/razvy_round1/clasament','Clasament razvy_round1','2009-12-07 16:29:32','2009-12-07 16:29:32','h1. Clasament ==roundparam(round_id=\"razvy_round1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"razvy_round1\")==',6958,'round: razvy_round1',NULL,NULL),('runda/buzesti','buzesti','2009-12-14 10:50:19','2009-12-14 10:50:19','h1. == roundparam(round_id=\"buzesti\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"buzesti\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"buzesti\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"buzesti\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/buzesti/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"buzesti\" score=\"1\")==',9859,'round: buzesti',NULL,NULL),('runda/maxhit1','maxhit1','2009-12-09 08:09:34','2009-12-09 08:09:34','h1. == roundparam(round_id=\"maxhit1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"maxhit1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"maxhit1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"maxhit1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/maxhit1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"maxhit1\" score=\"1\")==',11425,'round: maxhit1',NULL,NULL),('runda/maxhit1/clasament','Clasament maxhit1','2009-12-09 08:09:34','2009-12-09 08:09:34','h1. Clasament ==roundparam(round_id=\"maxhit1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"maxhit1\")==',11425,'round: maxhit1',NULL,NULL),('runda/lion_2000','lion_2000','2009-12-09 08:30:10','2009-12-09 08:30:10','h1. == roundparam(round_id=\"lion_2000\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"lion_2000\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"lion_2000\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"lion_2000\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/lion_2000/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"lion_2000\" score=\"1\")==',11434,'round: lion_2000',NULL,NULL),('runda/lion_2000/clasament','Clasament lion_2000','2009-12-09 08:30:10','2009-12-09 08:30:10','h1. Clasament ==roundparam(round_id=\"lion_2000\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"lion_2000\")==',11434,'round: lion_2000',NULL,NULL),('utilizator/vyperboy','Profil VyperBoy','2009-12-09 14:00:27','2009-12-09 14:00:27','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',11437,'public',NULL,NULL),('runda/problemiada_7','Inca nu ma clatin, picioarele ma tin.','2009-12-10 18:43:42','2009-12-10 18:46:12','h1. == roundparam(round_id=\"problemiada_7\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"problemiada_7\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"problemiada_7\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"problemiada_7\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/problemiada_7/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"problemiada_7\" score=\"1\")==',5748,'round: problemiada_7',NULL,NULL),('runda/problemiada_7/clasament','Clasament problemiada_7','2009-12-10 18:43:42','2009-12-10 18:43:42','h1. Clasament ==roundparam(round_id=\"problemiada_7\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"problemiada_7\")==',5748,'round: problemiada_7',NULL,NULL),('runda/primul','primul','2009-12-11 14:41:11','2009-12-11 14:41:11','h1. == roundparam(round_id=\"primul\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"primul\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"primul\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"primul\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/primul/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"primul\" score=\"1\")==',11400,'round: primul',NULL,NULL),('runda/primul/clasament','Clasament primul','2009-12-11 14:41:11','2009-12-11 14:41:11','h1. Clasament ==roundparam(round_id=\"primul\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"primul\")==',11400,'round: primul',NULL,NULL),('planificare/camp-2.3','Coding Camp \"A 2nd New Day\"','2009-11-27 18:41:08','2009-12-22 18:02:15','h1. Coding Camp _\"A 2nd New Day\"_\r\n\r\nNe intalnim in weekend-ul *12-13 decembrie 2009*, in fiecare zi intre orele *10:00* si *18:00*, la *ICHB*.\r\n\r\nScopul final al coding camp-ului este lansarea versiunii \'*infoarena 2.3*\':http://hackers.devnet.ro/milestone/2.3%20A%20New%20Day. \r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu Linux instalat pe el.\r\n* \'Asociatia infoarena\':asociatia-infoarena (sper ca) asigura masa, bautura, snacks-uri\r\n\r\nh2. Participanti\r\n\r\nSpecifica cand poti veni si cat poti sta.\r\n\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"devilkind\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"victorsb\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"prostu\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"toni2007\" type=\"tiny\")==: sambata\r\n* ==user(user=\"pauldb\" type=\"tiny\")==: sambata\r\n\r\nh2. Agenda\r\n\r\nh3. Must have \r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n| \'Tagging pentru probleme\':propuneri/15-task-tagging | ==user(user=\"bogdan2412\" type=\"tiny\")== ==user(user=\"devilkind\" type=\"tiny\")== | Done fara search |\r\n| Script de recalculat timpii de evaluare | 0 | 0 |\r\n| \'Ales intre ş si ş pentru paginile textile\':http://hackers.devnet.ro/ticket/379 | ==user(user=\"gcosmin\" type=\"tiny\")== | \'Done\':http://reviewboard.infoarena.ro/r/107/ |\r\n| \'Constrangeri pentru concursurile virtuale\':http://hackers.devnet.ro/ticket/372 | ==user(user=\"gcosmin\" type=\"tiny\")== | \'Done\':http://reviewboard.infoarena.ro/r/116/ |\r\n\r\nh3. Nice to have\r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n| \'Javascript RoundStatus() macro\':http://hackers.devnet.ro/ticket/226 | ==user(user=\"victorsb\" type=\"tiny\")== | \'Done\':http://reviewboard.infoarena.ro/r/113/ |\r\n| \'Checkbox pentru selectat toate atasamentele paginii\':http://hackers.devnet.ro/ticket/381 | ==user(user=\"gcosmin\" type=\"tiny\")== | \'Done\':http://reviewboard.infoarena.ro/r/110/ |\r\n| \'Functionalitate de sters runde\':http://hackers.devnet.ro/ticket/373 | ==user(user=\"prostu\" type=\"tiny\")== | \'Done 1/2\':http://reviewboard.infoarena.ro/r/115/ |\r\n| \'Sters automat concursuri virtuale nefolosite\':http://hackers.devnet.ro/ticket/376 | 0 | 0 |\r\n| \'Logheaza IP cand se inregistreaza utilizator\':http://hackers.devnet.ro/ticket/377 | ==user(user=\"toni2007\" type=\"tiny\")== | \'Done\':http://reviewboard.infoarena.ro/r/105/ |\r\n| \'Optimizeaza pagina de changes\':http://hackers.devnet.ro/ticket/383 | 0 | 0 |\r\n| \'Add PRIMARY KEY to ia_textblock_revision\':http://hackers.devnet.ro/ticket/380 | ==user(user=\"gcosmin\" type=\"tiny\")== | \'Done\':http://reviewboard.infoarena.ro/r/111/ |\r\n\r\nh3. De terminat de la \"Coding Camp 2.2.1 A New Day\":planificare/camp-2.2.1\r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n| Scoruri detaliate | 0 | \'La review\':http://reviewboard.infoarena.ro/r/64/ |\r\n| \'Interfata de updatat rating-uri\':http://hackers.devnet.ro/ticket/239 | ==user(user=\"victorsb\" type=\"tiny\")== | \'Reviewed\':http://reviewboard.infoarena.ro/r/83/ |\r\n| \'Script pentru topic-uri de pe forum la probleme\':http://hackers.devnet.ro/ticket/367 | 0 | \'Reviewed\':http://reviewboard.infoarena.ro/r/74/ |\r\n| Script de backup: stergere automata de backup-uri vechi | 0 | 0 |\r\n\r\nh3. Others, reportate coding camp trecut\r\n\r\n|_. Task|_. Cine lucreaza |_. Status |\r\n| \'Licenta CC\':http://hackers.devnet.ro/ticket/343 | 0 | 0 |\r\n| \'Run YSlow and improve performance\':http://hackers.devnet.ro/ticket/351 | 0 | 0 |\r\n| \'Sistem de monitorizare\':http://hackers.devnet.ro/ticket/179 | 0 | 0 |\r\n| Probleme interactive | 0 | 0 |\r\n| \'Feed-uri pe Feedburner\':http://hackers.devnet.ro/ticket/344 | 0 | 0 |\r\n| Community Dashboard | 0 | 0 |\r\n| Reorganizat sidebar si topnav | 0 | 0 |\r\n| \'Pagina de changes mai detaliata\':http://hackers.devnet.ro/ticket/155 | 0 | 0 |\r\n| \'Permisiuni in pagina de changes\':http://hackers.devnet.ro/ticket/363 | 0 | 0 |',1490,'public',NULL,NULL),('implica-te/arhiva-educationala/membri-emeritus','implica-te/arhiva-educationala/membri-emeritus','2009-12-12 00:25:56','2009-12-12 00:29:49','h2. Membri implicaţi în trecut\r\n\r\nMulţumim următoarelor persoane pentru efortul depus în dezvoltarea \'Arhivei Educaţionale\':arhiva-educationala...\r\n\r\n* == user(user=\"pauldb\" type=\"tiny\") ==, fost coordonator de proiect\r\n* == user(user=\"filipb\" type=\"tiny\") ==, fost coordonator de proiect\r\n* == user(user=\"devilkind\" type=\"tiny\") ==\r\n* == user(user=\"mariusdrg\" type=\"tiny\") ==\r\n* == user(user=\"bogdan2412\" type=\"tiny\") ==\r\n* == user(user=\"Florian\" type=\"tiny\") ==\r\n* == user(user=\"gabitzish1\" type=\"tiny\") ==\r\n* == user(user=\"Tabara\" type=\"tiny\") ==\r\n* == user(user=\"Dastas\" type=\"tiny\") ==\r\n* == user(user=\"fireatmyself\" type=\"tiny\") ==\r\n* == user(user=\"cos_min\" type=\"tiny\") ==\r\n* == user(user=\"tudalex\" type=\"tiny\") ==\r\n* == user(user=\"toni2007\" type=\"tiny\") ==\r\n* == user(user=\"tm_radu\" type=\"tiny\") ==\r\n* == user(user=\"floringh06\" type=\"tiny\") ==\r\n* == user(user=\"prostu\" type=\"tiny\") ==\r\n* == user(user=\"amadaeus\" type=\"tiny\") ==\r\n* == user(user=\"sima_cotizo\" type=\"tiny\") ==',3146,'public',NULL,NULL),('blog/algoritmiada-2010-runda-1','Algoritmiada 2010: Analiza rundei 1','2009-11-27 00:57:30','2009-11-29 19:38:07','Prima runda a concursului \'Algoritmiada\':algoritmiada-2010 a avut loc pe 22 noiembrie, marcând astfel debutul celei de-a doua ediţii a celei mai importante competiţii organizate de info{_arena_}. Anul acesta am început concursul mai devreme cu gândul de a vă oferi 4 runde de calificare în loc de 3. Sperăm ca această decizie să ne ajute la obţinerea unui clasament general mai exact, în urma căruia să putem selecta cei mai bine pregătiţi concurenţi pentru finală.\r\n\r\nDupă cum v-am obişnuit până acum, vom arunca o privire asupra statisticilor acestei runde:\r\n\r\ntable. |_. &nbsp; |_. Runda 1 (2009) |_. Runda 1 (2010) |\r\n| Cati concurenti au trimis solutii | 223 | 181 |\r\n| Cati concurenti s-au inscris | 356 | 308 |\r\n| Surse trimise | 1245 | 765 |\r\n| Surse cu punctaj pozitiv | 685 | 345 |\r\n| Concurenti cu punctaj pozitiv | 162 | 122 |\r\n| Punctaj mediu al concurentilor care au trimis solutii | 75.09 | 58.07 |\r\n| Punctaj mediu al concurentilor cu punctaj strict mai mare ca 0 | 103.36 | 86.15 |\r\n\r\nSe observă o scădere semnificativă a numărului de participanţi faţă de anul trecut. O justificare posibilă a acestui fenomen este faptul că Algoritmiada şi-a creat un \"brand\", rămânând cu noi doar acei tineri care au găsit în concursul nostru ceea ce căutau. Sperăm, totuşi, că aceştia se vor dovedi temeinici, luptându-se pentru şansa lor până la sfârşitul competiţiei.\r\n\r\nJudecând după rezultate, gradul de dificultate a fost, în general, unul potrivit, obţinându-se o distribuţie bună a punctajelor. În fruntea clasamentului de la gimnaziu, avem o surpriză: == User(user=\"liana\") == reuşind să obţină punctajul maxim (singurul din această rundă). Ne bucură să constatăm că sunt şi fete interesate de performanţă în informatică. Felicitări, la cât mai multe rezultate frumoase pe viitor! Pe podium au mai urcat == User(user=\"eudanip\") == şi == User(user=\"GheorgheMihai\") ==, ambii cu câte 230 de puncte. \r\n\r\nLa grupa 9-10, runda a fost adjudecată clar de == User(user=\"freak93\") == cu 290 de puncte, fiind singurul care a reuşit să rezolve aproape corect problema $vrejuri$. El a fost urmat de == User(user=\"savim\") == (200 de puncte) şi == User(user=\"gavrilavlad\") == (170 de puncte).\r\n\r\nLa grupa 11-12 au fost punctaje mai mici ca la celelalte grupe, fapt care îl punem pe seama absenţei unei probleme mai accesibile. Vom încerca să remediem acest lucru începând de runda viitoare. La aceasta grupă, primul clasat a fost == User(user=\"andrei-alpha\") == cu 210 puncte, fiind urmat de == User(user=\"Mishu91\") == cu 170 de puncte şi == User(user=\"AndreyP\") == cu 120 de puncte.\r\n\r\nLa grupa de studenţi, în fruntea clasamentului îl găsim pe veteranul info{_arena_} == User(user=\"mugurelionut\") == cu 260 de puncte. El este urmat de un grup compact format din 9 studenţi: == User(user=\"Vman\") ==, == User(user=\"diac_paul\") ==, == User(user=\"CommanderK\") ==, == User(user=\"seal\") ==, == User(user=\"MarcvsHdr\") ==, == User(user=\"mihai_florea\") ==, == User(user=\"rss1987\") ==, == User(user=\"Pepelea_Flaviu\") == şi == User(user=\"andreitheo87\") ==, toţi cumulând câte 200 de puncte. La această grupă mai notăm un rezultat remarcabil: 38 de participanţi au reuşit să depăşească pragul de 100 de puncte. \r\n\r\nJudecând după punctajele apropiate din clasament, se pare că vom avea o luptă acerbă pentru calificare şi în acest an. Cu toate acestea, cei care au obţinut rezultate mai puţin bune nu trebuie să vă simţiţi descurajaţi deoarece în trei runde nu este dificil să recuperaţi diferenţa care vă separă de plutonul fruntaş. \r\n\r\nPe partea ştiinţifică fost sesizată o singură imperfecţiune: testele de la problema $studenţi$ nu au fost suficient de bine construite şi astfel, unele soluţii incorecte au obţinut 100 de puncte. Problema a fost corectată imediat, unul din teste fiind înlocuit când problema a fost adaugată în arhiva de probleme. În rest, comisia ştiinţifică s-a mobilizat exemplar, reuşind să organizeze un concurs interesant şi atractiv. Site-ul s-a comportat şi el bine pe aproape toată durata concursului, cu mici excepţii la final, când a cedat puţin presiunii numărului mare de utilizatori nerăbdători să-şi vadă rezultatele. \r\n\r\nÎn vederea selectării concurenţilor pentru finală, vă recomandăm să vă completaţi/updataţi profilul cu date despre clasa/anul în care sunteţi, precum şi informaţii despre instituţia de învăţământ. De fapt, am fi bucuroşi dacă toţi utilizatorii şi-ar completa profilul, aceasta fiind una din modalităţile prin care putem să ne cunoaştem între noi. Exemple de profile completate puteţi găsi la mai toţi membrii echipei infoarena.\r\n\r\nÎnchei prin a vă reaminti că în acest weekend are loc Olimpiada Balcanică de Informatică pentru Juniori şi Seniori. Membrii echipelor ce reprezintă România la această competiţie sunt, bineînţeles, utilizatori activi info{_arena_}, unii dintre ei reuşind performanţe deosebite chiar în această rundă de concurs. Ei sunt: == User(user=\"gavrilavlad\") ==, == User(user=\"radu_cpp\") ==, == User(user=\"marius21\") ==, == User(user=\"GheorgheMihai\") ==, == User(user=\"andrei.12\") ==, == User(user=\"savim\") == şi == User(user=\"devilkind\") ==, == User(user=\"perticas_catalin\") ==. Le dorim mult succes şi să obţină medalii cât mai strălucitoare!\r\n\r\n_Vouă cum vi s-a părut concursul? Ce a mers bine şi ce a mers rău pentru voi? Este important pentru noi să ne lasaţi impresiile voastre despre concurs, pentru a reuşi o organizare şi mai bună în continuare._',1792,'protected',4316,NULL),('runda/winter_challenge_1','winter_challenge_1','2009-12-14 16:55:02','2009-12-14 16:55:02','h1. == roundparam(round_id=\"winter_challenge_1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"winter_challenge_1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"winter_challenge_1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"winter_challenge_1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/winter_challenge_1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"winter_challenge_1\" score=\"1\")==',6957,'round: winter_challenge_1',NULL,NULL),('runda/winter_challenge_1/clasament','Clasament winter_challenge_1','2009-12-14 16:55:02','2009-12-14 16:55:02','h1. Clasament ==roundparam(round_id=\"winter_challenge_1\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"winter_challenge_1\")==',6957,'round: winter_challenge_1',NULL,NULL),('newsletter/algoritmiada-2010-2','Algoritmiada 2010 Runda 2; Rezultate BOI/JBOI','2009-12-14 22:32:52','2009-12-15 08:04:01','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎn curând începe cea de-a \'doua rundă\':algoritmiada-2010/runda-2 a concursului \'Algoritmiada\':algoritmiada-2010, cel mai mare şi mai important concurs organizat de infoarena!\r\n\r\nLa Algoritmiada participă elevi de gimnaziu, de liceu, dar şi studenţi (inclusiv masteranzi sau doctoranzi)! Există grupe separate pentru fiecare.\r\n\r\n\'Runda 2\':algoritmiada-2010/runda-2 are loc chiar în acest weekend. Întrece-te cu cei mai buni! Dovedeşte-ţi talentul şi cunoştinţele şi asigură-ţi un loc în finală!\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Runda a doua se desfăşoară\r\n*Duminică, 20 Decembrie 2009, orele 09^00^ - 13^00^*. |\r\n\r\nVezi \'pagina concursului\':algoritmiada-2010 ca să afli cum poţi participa.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"algoritmiada-2010/runda-2\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre runda anterioara\r\n\r\nPe blog găseşti o \'analiză\':blog/algoritmiada-2010-runda-1 a primei runde. Află câti concurenţi au participat, câte surse s-au trimis şi impresii despre rundă!\r\n\r\nVezi rezultatele şi clasamentul \'aici\':algoritmiada-2010/clasament.\r\n\r\nh2{font-size: 12pt}. Despre Algoritmiada\r\n\r\nAlgoritmiada este unicul concurs din România unde pot participa tinerii pasionaţi de informatică de toate vârstele: de la elevi de gimnaziu până la studenţi şi doctoranzi.\r\n\r\nConcursul are patru grupe valorice: gimnaziu, clasele 9-10, clasele 11-12, studenţi (inclusiv masteranzi şi doctoranzi). Participanţii vor avea ocazia să-şi demonstreze talentul, cunostinţele şi ascuţimea minţii în 4 probe online urmând ca cei mai buni sa fie invitaţi la finala on-site. În fiecare rundă vei avea la dispoziţie 4h să rezolvi 3 probleme de natură algoritmică.\r\n\r\nSubiectele vor fi propuse de către o echipă de foşti şi actuali olimpici la informatică: Cosmin Gheorghe, Bogdan Tătăroiu, Paul Băltescu, Filip Ştefan, Marius Stroe, Adrian Airinei, Andrei Grigorean, Ştefan Istrate, Adrian Diaconu, Cosmin Negruşeri şi Filip Buruiană. De ce ei? Intră pe \'pagina organizatorilor\':algoritmiada-2010/comisie şi citeşte câte ceva despre experienţa fiecăruia.\r\n\r\nIntră pe \'pagina concursului\':algoritmiada-2010 ca să afli mai multe informaţii.\r\n\r\nIţi urăm succes şi te asteptăm în arenă!\r\n\r\nh2{font-size: 12pt}. Rezultate BOI/JBOI 2009\r\n\r\nÎn perioada 27-29 noiembrie a avut loc a XVII-a ediţie a Olimpiadei Balcanice de Informatică (BOI) în Shumen, Bulgaria. Tot atunci a avut loc şi cea de-a III-a ediţie a Olimpiadei Balcanice de Informatică pentru Juniori (JBOI). Echipele României s-au prezentat excelent la ambele competiţii:\r\n\r\n* Juniori:\r\n** \'Vlad Gavrilă\':utilizator/GavrilaVlad - Aur absolut\r\n** \'Mihai Gheorghe\':utilizator/GheorgheMihai - Argint\r\n** \'Radu Voroneanu\':utilizator/radu_cpp - Argint\r\n** \'Marius Petcu\':utilizator/marius21 - Bronz\r\n* Seniori:\r\n** \'Andrei Pârvu\':utilizator/andrei.12 - Bronz\r\n** \'Şerban Stan\':utilizator/savim - Bronz\r\n** \'Tiberiu Savin\':utilizator/devilkind - Bronz\r\n** \'Florin Perţicaş\':utilizator/perticas_catalin - Bronz\r\n\r\nFelicitări, băieţi! Aţi obţinut nişte rezultate foarte frumoase cu care ne mândrim!\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==',1792,'protected',NULL,NULL),('planificare/sedinta-20091126','Ședință 2009-11-26','2009-11-23 14:30:08','2009-12-15 09:07:35','h1. Şedinţă 2009-11-26\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Joi* la ora *19:00* la Cafepedia Romana.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"stef2n\" type=\"tiny\")==\r\n* ==User(user=\"prostu\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"victorsb\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20091103 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Algoritmiada Runda 2 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Probleme cu site-ul | ? |\r\n| Coding Camp | ==User(user=\"bogdan2412\" type=\"tiny\")== |\r\n| Evaluator nou | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Sala sedinta | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| IAP #15: Tagging | ==User(user=\"bogdan2412\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n* &hellip;\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Vali face design la mapa.\r\n* Cosmin vorbeste cu Cristi de cardul lui.\r\n* Vali face testing pe masina virtuala.\r\n* Vali vorbeste cu Vlad Posea despre jailrun java.\r\n* Facem runda 2 la Algoritmiada pe 20 decembrie.\r\n* S-au stabilit sefi de grupe: Prostu (gimnaziu), Stefan (9-10), Bogdan (11-12).\r\n* Paul scrie blog post pentru runda 1. %{color:red}(done)%\r\n* Cosmin vorbeste cu Astronomy despre Amazon.\r\n* Paul vorbeste cu Cristina despre bilant Infoarena. %{color:red}(done: Mama lui Cristi se ocupa in continuare de bilant.)%\r\n* Stefan cauta paginile despre noi care sunt outdated.\r\n* Bogdan rezolva problemele cu reviziile vechi (fara securitate). %{color:red}(done)%\r\n* Bogdan gaseste paginile pe care sta diff-ul la 100% procesor. %{color:red}(done)%\r\n* Facem coding camp pe 12-13 decembrie. %{color:red}(done)%\r\n* Cosmin cauta loc pentru sedinta si coding camp. %{color:red}(done)%\r\n* Cosmin vorbeste cu Vali de evaluator.\r\n* Bogdan cere drepturi pentru Google Analytics si Google Apps. %{color:red}(done)%\r\n* Cosmin vorbeste cu Cristi de newsletter@infoarena.ro si no-reply@infoarena.\r\n* Cosmin face IAP pentru dificultate.\r\n\r\nh2(#notite). Notite\r\n\r\n* Prostu inspecteaza diff-ul din Linux.\r\n',1490,'protected',NULL,NULL),('algoritmiada-2010/runda-2','Algoritmiada 2010 - Runda 2','2009-10-25 16:32:04','2009-12-19 19:17:25','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Algoritmiada 2010, Runda 2\r\n\r\n(htabs)*(active) \'Despre...\':algoritmiada-2010/runda-2 \r\n* \'Clasele 5-8\':algoritmiada-2010/runda-2/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-2/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-2/5-8 \r\n\r\nRunda va incepe *Duminica 20 decembrie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-2/studenti\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':algoritmiada-2010/runda-2/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-2/studenti\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==User(user=\"prostu\" type=\"tiny\")==\r\n* ==User(user=\"stef2n\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"ditzoneC\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"Cosmin\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"marius\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"victorsb\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica sau tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('algoritmiada-2010/runda-2/solutii/redu','Redu','2009-12-20 13:53:53','2009-12-21 08:38:02','h1(#redu). \'Redu\':problema/redu\r\n\r\n\r\nProblema se poate rezolva cu programare dinamica. Fie $din[i][j]$ = costul minim cu care pot sa reduc secventa dintre pozitiile $i$ si $j$. Ca sa determinam $din[i][j]$ putem sa ne gandim in urmatorul fel: primul caracter (cel de pe pozitia $i$) il putem reduce ultimul cu un alt caracter de pe o pozitie oarecare $k$ din subsecventa, fara a afecta in nici un fel optimalitatea solutiei. Dar pentru aceasta trebuie mai intai sa reducem secventa $(i + 1, k - 1)$ si secventa $(k + 1, j)$ si apoi sa reducem cele doua caractere ramase. Vizual:\r\n\r\n**i** ___S1___ **k** _____S2_____j\r\n\r\nPentru a reduce caracterul de pe pozitia $i$ cu cel de pe pozitia $k$ trebuie sa reducem $S1$, $S2$ (incluzand pozitia $j$) si apoi cele doua caractere ramase $S[i]$, $S[k]$.\r\n\r\nAsadar pentru a gasi solutia optima trebuie doar sa incercam toate $k$-urile posibile si sa o alegem pe cea mai buna. Astfel recurenta dinamicii se contureaza in acest mod: $din[i][j] = MIN ( din[i + 1][k - 1] + din[k + 1][j] + C[ S[i] ][ S[k] ])$ pentru oricare $k=i+1,j$. Trebuie sa avem atentie la cateva cazuri particulare: \r\n\r\n* din[i][j], unde j - i + 1 nu este par este INFINIT (nu se poate reduce o secventa de lungime impara)\r\n* din[i][j], unde i > j este 0 (ajungem in aceste cazuri prin recurenta noastra, dar ele reprezinta siruri vide)\r\n* din[i][j], unde i + 1 = j este C[ S[i] ][ S[j] ] (cazul cel mai mic din dinamica ce poate fi rezolvat imediat).\r\n\r\nRezultatul se va gasi in $din[ 1 ][ N ]$.\r\nComplexitatea acestei dinamici este $O(N^3^)$.',2038,'public',NULL,NULL),('algoritmiada-2010/runda-2/solutii/recurenta2','Recurenta2','2009-12-20 13:54:47','2009-12-22 08:59:58','h1(#recurenta2). \'Recurenta2\':problema/recurenta2\r\n\r\nNotăm $S{~i~} = 1*X{~1~} + 2*X{~2~} + ... + i*X{~i~}$. Recurenţa pentru $S{~i~}$ este uşor de găsit: $S{~i+1~} = S{~i~} + (i+1)*X{~i+1~}$. Putem să-l explicităm pe $X{~i+1~}$ în funcţie de termenii anteriori şi obţinem: $S{~i+1~} = S{~i~} + (i+1)*X{~i-1~}*B + (i+1)*X{~i~}*A + (i+1)*C$. Aşadar, observăm că la pasul $i$ nu ne dorim să cunoaştem doar valorile $X{~i-1~}$, $X{~i~}$ şi $S{~i~}$, ci şi pe $(i+1)*X{~i-1~}$ şi $(i+1)*X{~i~}$. Recurenţele pentru aceşti $2$ noi termeni sunt şi ele uşor de găsit: $(i+1)*X{~i-1~} = i*X{~i-1~} + X{~i-1~}$, iar $(i+1)*X{~i~} = i*X{~i~} + X{~i~} = X{~i-2~}*A + i*X{~i-1~}*B + i*C + X{~i-2~}*A + X{~i-1~}*B + C$. Observăm că putem aşeza aceste recurenţe în urmatoarea matrice de trecere de la pasul $i-1$ la pasul $i$:\r\n\r\n<tex>\\begin{pmatrix} X_{i-2} & X_{i-1} & 1 & S_{i-1} & i*X_{i-2} & i*X_{i-1}& i \\end{pmatrix} *</tex><tex>\\begin{pmatrix} 0 & B & 0 & 0 & 0 & B & 0 \\\\ 1 & A & 0 & 0 & 1 & A & 0 \\\\ 0 & C & 1 & 0 & 0 & C & 1 \\\\ 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & B & 0 & B & 0 \\\\ 0 & 0 & 0 & A & 1 & A & 0 \\\\ 0 & 0 & 0 & C & 0 & C & 1 \\end{pmatrix} </tex><tex>= \\begin{pmatrix} X_{i-1} & X_{i} & 1 & S_{i} & (i+1)*X_{i-1} & (i+1)*X_{i}& i+1 \\end{pmatrix}</tex>.\r\n\r\nPutem aplica proprietatea de asociativitate a înmulţirii matricilor şi să înmulţim matricea de trecere cu ea însăşi de $N$ ori şi abia după aceea să înmulţim matricea iniţială cu matricea rezultată. Complexitatea totală este $O(logN)$, folosind \'exponenţierea în timp logaritmic\':problema/lgput.',2044,'public',NULL,NULL),('algoritmiada-2010/runda-2/solutii/palmieri','Palmieri','2009-12-20 13:55:16','2009-12-20 15:33:06','h1(#palmieri). \'Palmieri\':problema/palmieri\r\n\r\nProblema se rezolvă cu o abordare de tip greedy. Iniţial, ordonăm crescător punctele după abscisă. Primul punct trebuie să fie acoperit de un dreptunghi şi observăm că este inutil să plasăm acest dreptunghi atlfel decât cu latura verticală stângă pe acest punct. Continuăm să parcurgem punctele mai departe şi să le acoperim cu acelaşi dreptunghi până când acesta depăşeşte aria $A$. În acest moment, putem ignora punctele deja acoperite şi observăm că rămâne de rezolvat aceeaşi problemă pentru un număr strict mai mic de puncte. Pasul pentru determinarea numărului de dreptunghiuri necesare are complexitate $O(N)$, deoarece vom parcurge fiecare punct în parte o singură dată. Complexitatea totală este $O(NlogN)$ din cauza sortării iniţiale.',1792,'public',NULL,NULL),('algoritmiada-2010/runda-2/solutii/secv9','Secv9','2009-12-20 13:53:32','2009-12-21 10:22:34','h1(#secv9). \'Secv9\':problema/secv9\r\n\r\nFie $A$ vectorul iniţial şi $Sum$ vectorul sumelor parţiale. Vectorul $Sum$ se calculează după următoarea recurenţă: $Sum{~i~} = Sum{~i-1~}+A{~i~}$. O subsecvenţă $[i, j]$ a vectorului iniţal are suma mai mare sau egală ca $S$ dacă $Sum{~j~}-Sum{~i-1~} &ge; S$. Ordonăm crescător vectorul sumelor parţiale. Parcurgem apoi vectorul cu doi indici $i$ şi $j$, unde $i$ reprezintă indicele sumei curente, iar $j$ indicele celei mai mari sume care respectă proprietatea $Sum{~i~}-Sum{~j~} >= S$. Această parcurgere are complexitate $O(N)$, deoarece iteraţia cu $j$ se continuă de la valoarea lui $j$ pentru $i-1$, fiecare element al vectorului fiind astfel vizitat o singură dată. Este evident că cea mai lungă subsecvenţă cu proprietatea dorită care se termină pe poziţia $i$ are lungimea egală cu $i - min{pozitia lui Sum{~k~} | k &le; j}$. Acest minim poate fi actualizat în $O(1)$ la fiecare incrementare a lui $j$. Rezultatul căutat este maximul lungimilor subsecvenţelor pentru fiecare $i$.\r\n\r\nComplexitatea totală este $O(NlogN)$ din cauza sortării.',1792,'public',NULL,NULL),('algoritmiada-2010/runda-2/solutii/jap2','Jap2','2009-12-20 13:54:19','2009-12-22 09:53:05','h1(#jap2). \'Jap2\':problema/jap2\r\n\r\nŞtim că putem afla puterea la care apare numărul prim $P$ în $N!$ folosind formula $[^N^/{~P~}] + [^N^/{~P^2^~}] + [^N^/{~P^3^~}] + ...$, unde $[x]$ reprezintă partea întreagă a lui $x$. Pentru un query $A, B$ putem determina puterea la care apare $P$ în $A!$, $B!$ şi $A-B!$ şi deci putem afla puterea la care apare $P$ în $Combinări(A, B)$.\r\n\r\nÎn cazul în care $C(A, B)$ este divizibil cu P, răspunsul este, evident, 0. În cazul în care $C(A, B)$ nu este divizibil, vom încerca să determinăm rapid valoarea lui $N!$ ignorând toţi factorii lui P.\r\n\r\nSă luăm un exemplu pentru $P = 3$ şi să vedem cum arată valorile din $2!$, $8!$ şi $26!$. Vom ignora toţi factorii lui $3$, deci $3$ devine 1, $6$ devine 2, $9$ devine 1, $12$ devine 4 modulo 3 = 1, etc.\r\n\r\nPentru $2$ produsul este egal cu $1*2$.\r\nPentru $8$ produsul este egal cu $(1*2)*1*(1*2)*2*(1*2)$.\r\nPentru $26$ produsul este egal cu: $(1*2*1*1*2*2*1*2)*1*(1*2*1*1*2*2*1*2)*2*(1*2*1*1*2*2*1*2)$.\r\n\r\nPutem observa că pentru numere de forma $P^k^-1$, cu $k$ număr natural, valoarea lui $P^k-1^-1$ se repetă de $P$ ori şi în plus pe poziţiile de forma $l * P^k-1^$ din şir se află numerele de la $1$ la $P-1$.\r\n\r\nDe aici, reiese o idee de rezolvare: Când vrem sa calculăm $N!$ factorial încercăm să-l reducem la probleme mai mici folosindu-ne de faptul că produsurile de mai sus se repetă.\r\n\r\nVom precalcula toate valorile lui $x!$, cu $x$ între $1$ şi $P-1$ şi toate valorile factorialelor pentru numere de forma $P^k^-1$ (se poate găsi uşor relaţie de recunrenţă între $P^k-1^-1$ şi $P^k^-1$).\r\n\r\nPentru a calcula $N!$, ne vom uita la cel mai mare număr de forma $P^k^-1$, care e mai mic strict ca $N$. Putem determina de câte ori se repetă produsul de lungime $P^k^-1$ în desfăşurarea lui $N!$ printr-o împărţire şi câti din factorii $1, 2, ..., P-1$ din afara produsurilor există. Dacă $N$ nu este la rândul lui de forma $P^k+1^-1$, atunci ultimul dintre produsele de forma $P^k^-1$ va fi incomplet şi va trebui să-l calculăm recursiv în acelaşi mod descris. Adâncimea maximă pe care o avea funcţia va fi egală cu $O(log{~P~} N)$ şi pentru că vom avea nevoie de o funcţie care să ridice o valoare la orice putere în timp logaritmic complexitatea finală va fi $O(log{~P~} N * log{~2~} P)$ pe test.\r\n\r\nAvând calculate factorialele $A!$, $B!$ şi $A-B!$ simplificate putem calcula combinările folosind conceptul de \'invers modular\':http://en.wikipedia.org/wiki/Modular_multiplicative_inverse, care ne permite să simulăm împărţirea pe numere naturale in aritmetica modulară.\r\n\r\nÎn timpul concursului am aflat din sursele concurenţilor de existenţa \'Teoremei lui Lucas\':http://en.wikipedia.org/wiki/Lucas_theorem care rezolvă aceeasi problemă, spre dezamăgirea autorului. :( Soluţia oficială prezentată mai sus poate fi extinsă însă pentru calcularea Aranjamentelor sau doar a Factorialului.',1490,'public',NULL,NULL),('algoritmiada-2010/runda-2/solutii/dinti','Dinti','2009-12-20 13:52:44','2009-12-21 12:43:52','h1(#dinti). \'Dinti\':problema/dinti\r\n\r\nFie $inv(s)$ inversul sirului $s$ (spre exemplu: $inv(100)$ = $011$). Fie $S$ un sir determinat de $L$ caractere consecutive din sirul $A$. Putem observa ca $inv(S)$ si orice alt sir obtinut din $inv(S)$ prin modificarea oricator valori $1$ din $inv(S)$ in $0$ se potriveste peste $S$ (exemplu: peste $S = 100$ se potrivesc $011$, $001$, $010$, si $000$). \r\n\r\nNumarul total de siruri ce se pot potrivi peste $A$ nu depaseste $2^L^$ asa ca putem tine un vector V, de valori adevarat/fals de marime $2^L^$,\r\nastfel incat $V[cod(s)] = 1/0$ daca sirul $s$ se poate suprapune peste sirul $A$ ( $cod(s)$ reprezinta codificarea sirului $s$ intr-un numar in baza 10 a carei reprezentare binara este egala cu sirul $s$). Ca sa obtinem acest vector putem lua pe rand toate sirurile $S$, parcurgand sirul $A$ si tinand ultimele $L$ caractere, si printr-un backtracking sa obtinem toate valorile ce se pot potrivi peste $S$ (calculam $inv(S)$ si apoi schimbam prin backtracking $1$-urile in $0$-uri in toate modurile posibile). Aceste siruri \"bune\" le putem stoca in sirul $V$ si apoi putem raspunde la oricare intrebare in $O(1)$. Singura problema este ca aceasta solutie are o complexitate prea mare (cam $3^L^$) si iese din timp. Pentru a nu folosi backtracking in generarea sirurilor bune vom face urmatorul lucru. Pentru toate sirurile $S$ vom tine ca sir bun in $V$ doar $inv(S)$, iar dupa aceea vom folosi o dinamica pentru a afla toate sirurile bune. Pentru toate starile $st$, de la $2^L^-1$ la $0$ (de la $11..1$ la $00..0$) putem zice ca daca $V[st] = 1$ atunci si $V[st ^ (1 << k)] = 1$, pentru toate $k$-urile pentru care $st & (1 << k) != 0$ (adica pentru toti bitii de $1$ din $st$). Aceasta dinamica este echivalentul backtracking-ului pentru toate starile $S$.\r\n\r\nDupa ce obtinem sirul $V$ putem raspunde la orice intrebare in $O(1)$. Complexitatea totala a solutie este O( $N + M + 2^L^ * L$ ).',2038,'public',NULL,NULL),('problema-majoritatii-votului','Problema Majoritatii Votului','2009-04-06 05:09:46','2009-12-21 17:15:03','h1. Problema majorităţii votului\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"andrici_cezar\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'Enunţ\':problema-majoritatii-votului#enunt\r\n** \'Soluţie $O(n^2^)$\':problema-majoritatii-votului#solutie-1\r\n** \'Soluţie $O(n + k)$ particulară\':problema-majoritatii-votului#solutie-2\r\n** \'Soluţie $O(n)$ cu tabele de dispersie\':problema-majoritatii-votului#solutie-3\r\n** \'Soluţie $O(n log{~2~}n)$\':problema-majoritatii-votului#solutie-4\r\n** \'Soluţie $O(n)$ cu statistici de ordine\':problema-majoritatii-votului#solutie-5\r\n** \'Soluţie $O(n log{~b~} k)$ particulară\':problema-majoritatii-votului#solutie-6\r\n** \'Soluţie $O(n + k)$ probabilistică\':problema-majoritatii-votului#solutie-7\r\n** \'Soluţie $O(n)$\':problema-majoritatii-votului#solutie-8\r\n* \'Generalizare\':problema-majoritatii-votului#generalizare\r\n** \'Soluţii $O(n*k)$\':problema-majoritatii-votului#solutie-9\r\n* \'Bibliografie\':problema-majoritatii-votului#bibliografie\r\n\r\n\r\nÎn acest articol dezbatem problema dezvoltării de algoritmi eficienţi pentru determinarea candidatului care a întrunit un număr majoritar de voturi.\r\n\r\nh2(#enunt). Enunţ\r\n\r\nbq. Se dă un şir de $n$ numere naturale. Se cere determinarea unui element care apare de cel puţin $[n/2]+1$ ori în şir dacă există un astfel de element în şir.\r\n\r\nh3(#solutie-1). Soluţie O(n^2^)\r\n\r\nUn algoritm naiv ar verifica pentru fiecare element din şir de câte ori mai apare acesta. O astfel de rezolvare are complexitatea $O(n^2^)$ ca timp şi $O(n)$ ca memorie.\r\n== code(cpp) |\r\nint bruteForceMajority(int n, int[] a)\r\n    for (int i = 0; i < n; i++) {\r\n        int nr = 0;\r\n        for (int j = 0; j < n; j++) {\r\n            if (a[j]==a[i])\r\n                nr++;\r\n        }\r\n        if  (nr > n / 2)\r\n            return a[i];      \r\n    }\r\n    return -1;\r\n}\r\n==\r\n\r\nh3(#solutie-2). Soluţie O(n + k) particulară\r\n\r\nDacă numerele din şir aparţin unei mulţimi ${1, 2, ... k}$ iar acest $k$ este mic comparativ cu $n$, atunci putem să îmbunătăţim ideea de mai devreme şi să folosim un şir auxiliar $b$, unde $b[x]$ va număra de câte ori apare un număr $x$ în şirul nostru. Această soluţie are complexitate $O(n + k)$ ca timp şi $O(n + k)$ ca spaţiu.\r\n\r\n== code(cpp) |\r\nint countMajority(int n, int[] a, int k) {\r\n    int[] b = new int[k];\r\n    for (int i = 0; i < n; i++) {\r\n        b[a[i]]++;    // incrementăm numărul de apariţii al elementului a[i]\r\n    }\r\n    for (int i = 0; i < k; i++) {\r\n         if (b[i] > n/2)\r\n             return i;\r\n    }\r\n    return -1;\r\n}\r\n==\r\n\r\nh3(#solutie-3). Soluţie O(n) cu \'tabele de dispersie\':tabele-hash-prezentare-detaliata\r\n\r\nSoluţia precedentă este destul de eficientă în cazul menţionat anterior, dar când $k$ este mult mai mare decât $n$, atunci această rezolvare ajunge să fie foarte lentă. Însă folosind o structură avansată de date putem să facem soluţia din nou eficientă. Această structură are la bază o tabelă de dispersie: ea mapează perechi de numere $<cheie, valoare>$, unde cheile vor fi numerele din şir, iar valorile vor fi numărul de apariţii al cheilor în şirul nostru.\r\n\r\n== code(cpp) |\r\nint hashMajority(int n, int[] a) {\r\n    HashMap<Integer, Integer> b = new HashMap<Integer, Integer>();\r\n    for (int i = 0; i < n; i++) {\r\n         if (b.get(a[i]) == null) {\r\n             b.put(a[i], 1);\r\n         } else {\r\n             int num = b.get(a[i]);\r\n             b.remove(a[i]);\r\n             b.put(a[i], num + 1);\r\n         }\r\n    }\r\n    for (int i = 0; i < n; i++) {\r\n         if (b.get(a[i]) > n/2)\r\n             return i;\r\n    }\r\n    return -1;\r\n}\r\n==\r\n\r\nAceastă soluţie are complexitate $O(n)$ ca timp, şi $O(n)$ memorie suplimentară. Menţionăm că un dezavantaj al acestei soluţii ar fi că este una randomizată.\r\n\r\nh3(#solutie-4). Soluţie O(n log{~2~}n)\r\n\r\nO altă soluţie care ar permite numărarea eficientă a numărului de apariţii al unui element în acest şir ar fi să sortăm şirul pentru că apoi elementele egale vor fi în poziţii consecutive.\r\n\r\n== code(cpp) |\r\nint sortMajority(int n, int[] a) {\r\n    Arrays.sort(a);\r\n    int i = 0;\r\n    while (i < n) {\r\n          int j = i;\r\n          while (j < n && a[j + 1] == a[i])\r\n              j++;\r\n          if (j–i+1 > n/2) \r\n              return a[i];\r\n          i = j + 1;\r\n    }\r\n    return -1;\r\n}\r\n==\r\n\r\nAceastă soluţie are complexitatea O(n log n), nu foloseşte memorie suplimentară, dar suprascrie şirul iniţial.\r\n\r\nh3(#solutie-5). Soluţie O(n) cu \'statistici de ordine\':problema/sdo\r\n\r\nO idee ce ne vine pe urma acestei rezolvări este aceea că în şirul sortat, un element majoritar se va afla în şirul sortat şi pe poziţia $n/2$. Ştim că există algoritmi de selecţie care ne găsesc elemente de o poziţie fixată $k$ din şirul sortat în complexitate $O(n)$. Astfel, vom găsi întâi elementul de pe poziţia $n/2$ iar apoi vom verifica dacă acesta este elementul majoritar al şirului. Astfel avem o soluţie de complexitate $O(n)$ iar şirul iniţial va fi modificat. Există metode de selecţie nerandomizate, dar pentru uşurinţa implementării vom folosi una randomizată.\r\n\r\n== code(cpp) |\r\nint  select(int n, int[] a, int left, int right, int k) {\r\n    Random ran = new Random(System.currentTimeMilis());\r\n    int i, j, aux, q; \r\n    while (left != right) {\r\n        i = left + ran.nextInt(right – left + 1);\r\n        aux = a[left]; a[left] = a[i]; a[i] = aux;\r\n        int x = a[left];\r\n        i = left - 1;\r\n        j = right + 1;\r\n        while (true) {\r\n           do { i++; } while a[i] < x;\r\n           do { j--; } while a[j] > x;\r\n           if (i < j) {\r\n               aux = a[i]; a[i] = a[j]; a[j] = aux;\r\n           } else\r\n               break;\r\n        }\r\n        q = right - left + 1;\r\n        if (k <= q) {\r\n            right = j;\r\n        } else {\r\n           k -= q;\r\n           left = j + 1;\r\n        }\r\n    }\r\n    return a[left];\r\n}\r\n\r\nint selectMajority(int n, int[] a) {\r\n   int x = select(n,  a,  0, n - 1, n / 2 - 1), nr = 0;\r\n   for (int i = 0; i < n; i++) {\r\n       if (a[i] == x)\r\n           nr++;\r\n   }\r\n   if (nr > n/2)\r\n       return x;\r\n   else\r\n       return -1;\r\n}\r\n==\r\n\r\nh3(#solutie-6). Soluţie O(n log{~b~} k) particulară\r\n\r\nO altă idee de rezolvare porneşte de la observaţia următoare: dacă există un element majoritar în şir, atunci ultima lui cifră va fi elementul majoritar în şirul format din ultimele cifre a numerelor din şirul iniţial. Această observaţie este valabilă pentru orice cifră a numerelor nu doar ultima. Astfel putem determina pentru fiecare a $x$-a cifră a numerelor care este cifra majoritară şi apoi să punem cap la cap cifrele majoritare pentru a forma numărul majoritar. Evident putem să folosim orice bază, dacă folosim baza $b$ şi valoarea maximă a unui număr ar fi $k$ atunci algoritmul va avea complexitatea $O(n log{~b~} k)$ şi foloseşte memorie suplimentară $O(b * log{~b~}k)$.  În practică putem considera acest algoritm ca fiind liniar. Să vedem o implementare a algoritmului pentru $b = 1000$ şi $k = 999 999 999$.\r\n\r\n== code(cpp) |\r\nint digitMajority(int n, int[] a) {\r\n    int[][] dig = new int[3][1000];\r\n    for (int i = 0; i < n; i++) {\r\n        int tmp = a[i];\r\n        for (int j = 0; j < 3; j++) {\r\n            dig[j][tmp % 1000]++;\r\n            tmp /= 1000;\r\n        } \r\n    }\r\n    int ret = 0;\r\n    for (int i = 0; i < 999; i++) {\r\n        if (dig[0][i] > n/2)\r\n            ret += i;\r\n        if (dig[1][i] > n/2) \r\n            ret += i * 1000;\r\n        if (dig[2][i] > n/2) \r\n            ret += i * 1000000;\r\n     }\r\n     int nr = 0;\r\n     for (int I = 0; I < n; i++) {\r\n         if (a[i] == ret)\r\n             nr++;\r\n     }\r\n     if (nr > n/2) \r\n         return ret;\r\n     else \r\n         return -1;\r\n}\r\n==\r\n\r\nh3(#solutie-7). Soluţie O(n + k) probabilistică\r\n\r\nPutem aborda probabilistic. Astfel dacă alegem un număr aleator şi există o celebritate, avem probabilitatea $0.5$ să nu îl nimerim. Dacă alegem $k$ numere aleatoare din şirul respectiv, atunci avem probabilitatea <tex> (\\frac{1}{2})^k </tex> să nu îl nimerim. Astfel algoritmul nostru va fi să luăm $k$ numere aleatoare, iar apoi să numărăm de câte ori apare fiecare din aceste $k$ numere în şirul nostru. Dacă folosim o structură ce mapează $<chei, valori>$ atunci algoritmul va avea complexitate $O(n + k)$ şi probabilitate de reuşită <tex> P = 1 - (\\frac{1}{2})^k </tex>. În practică o valoare de $10$ pentru $k$ ne dă o probabilitate de reuşită de $0.999$. Să vedem mai departe codul:\r\n\r\n== code(cpp) |\r\nint probabilisticMajority(int n, int[] a) {\r\n    Random ran = new Random(System.currentTimeMilis());\r\n    HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();\r\n    for (int i = 0; i < 10; i++) {\r\n        map.put(a[ran.nextInt(n)], 0);         \r\n    }\r\n    for (int i = 0; i < 10; i++) {\r\n        if (map.contains(a[i])) {\r\n            int num = map.get(a[i]);\r\n            if (num + 1 > n/2) return a[i];\r\n            map.remove(a[i]);\r\n            map.add(a[i], num + 1);\r\n        }\r\n    }\r\n    return -1;\r\n}\r\n==\r\n\r\nh3(#solutie-8). Soluţie O(n)\r\n\r\nUn ultim algoritm şi cel mai eficient dintre cele prezentate apare în lucrarea [1] şi probabil acesta este cunoscut cititorilor. Autorii au un mod plastic de a prezenta algoritmul: \r\n\r\n„Imaginaţi-vă o sală de conferinţă în care votanţii ţin fiecare o placă ce poartă numele candidatului preferat. Să presupunem că se ajunge la o bătaie generală în care votanţii cu convingeri diferite încep să se lovească reciproc cu plăcile. Să mai presupunem că fiecare votant care pune la pământ un membru cu alte convingeri este simultan şi el pus la pământ de adversar. Este evident că dacă ar fi vreun candidat care are mai multe voturi decât toate voturile celorlalţi candidaţi, atunci această luptă va fi câştigată de acest candidat şi la dispariţia haosului din urma luptei, votanţii ce au rămas în picioare vor fi susţinători ai candidatului amintit. În caz că nu există o majoritate clară pentru un candidat sau altul, la finalul luptei rămân în picioare votanţi care susţin acelaşi candidat, dar acesta poate să nu fie reprezentantul majorităţii. Deci, în general, dacă cineva rămâne în picioare, preşedintele conferinţei este obligat să verifice dacă într-adevar candidatul întruneşte votul a jumătate plus unu din votanţi. Algoritmul practic folosit de noi va fi un fel de joc al împerecherilor între candidaţi de opinii diferite până când toţi votanţii rămaşi necuplaţi vor susţine acelaşi candidat.”\r\n\r\nRealizăm acest algoritm parcurgând lista votanţilor şi ţinând un contor cu numărul de candidaţi $k$ neîmperecheaţi până la pasul curent, evident dacă ei sunt neîmperecheaţi trebuie să susţină acelaşi candidat pentru că altfel am fi putut să cuplăm câţiva dintre ei.\r\nMenţionăm că această rezolvare are doar operaţii în care se verifică dacă două valori sunt identice, fapt ce se poate dovedi util pentru obiecte complexe care ar substitui candidaţii din problemă. Rezolvările anterioare s-au folosit de faptul că între elementele şirului ar exista o relaţie de ordine sau că am putea efectua asupra lor operaţii aritmetice.\r\n\r\n== code(cpp) |\r\nint mooreMajority(int n, int[]  a) {\r\n    int cand = -1, k = 0;\r\n    for (int i = 0; i < n; i++) {\r\n        if (k == 0) {\r\n            cand = a[i];\r\n            k = 1;\r\n        } else if (a[i] == cand) {\r\n            k++;   // nu am putut împerechea pe votantul i şi astfel trebuie să mărim numărul de votanţi necuplaţi\r\n        } else\r\n            k--;   // cuplăm votantul i cu orice votant ce îl susţine pe cand şi micşorăm astfel numărul de votanţi necuplaţi\r\n    }\r\n    if (cand < 0)\r\n        return cand;\r\n    // verificare\r\n    int nr = 0;\r\n    for (int i = 0; i < n; i++) {\r\n        if (a[i] == cand) \r\n            nr++;\r\n    }\r\n    if (nr > n / 2)\r\n        return cand;\r\n    else\r\n        return – 1;\r\n}\r\n==\r\n\r\nAceastă problemă a fost propusă în prima rundă a concursului Bursele Agora în 2005. Atunci nu era posibilă ţinerea tuturor numerelor din fişier în memorie şi citirea numerelor era greoaie. Doar doi concurenţi au reuşit obţinerea unui punctaj maxim la acea rundă. Autorul a fost unul dintre aceştia. El a evitat citirea de două ori a fişierului de intrare prin folosirea soluţiei cu cifre, în care calcula două rezultate pentru două baze diferite b1 şi b2 alese aleator la startul rulării, iar apoi verifica dacă candidaţii care erau probabil câştigatori erau egali. Aceasta rezolvare făcea improbabilă scrierea unui răspuns incorect.\r\n\r\nh2(#generalizare). Generalizare\r\n\r\nbq. Se dă un şir de $n$ numere naturale şi un număr întreg $k$, se cere determinarea tuturor elementelor care apar de cel puţin $[n/k]+1$ ori în şir.\r\n\r\nh3(#solutie-9). Soluţii O(n*k)\r\n\r\nPrimele trei rezolvări prezentate pentru problema iniţială pot fi evident generalizate şi folosite şi pentru această problemă. Generalizarea abordării care implica folosirea cifrelor pentru a rezolva noua problemă pare imposibilă. Vom vorbi mai departe de două din celelalte trei abordări.\r\n\r\nEvident dacă un număr apare de cel puţin [n/k] + 1 ori în şir atunci el va apărea în şirul sortat pe una din poziţiile i * [n/k] cu i de la 1 la k. De aici se conturează algoritmul următor: determinăm în O(n * k) elementele de pe poziţiile i * [n/k] iar apoi verificăm care dintre acestea sunt elemente majoritare în sensul menţionat mai sus. Acest algoritm are complexitate liniară daca îl considerăm pe k o constantă.\r\n\r\nA doua soluţie este similară cu cea mai bună soluţie pentru prima problemă, numai că în loc să grupăm câte doi votanţi diferiţi vom grupa câte k votanţi cu păreri diferite.\r\n\r\n== code(cpp) |\r\nint[] mooreKMajority(int n, int[]  a, int k) {\r\n    int[] cand = new int[k - 1], notMatched = new int[k - 1],  num = new int[k-1];\r\n    Arrays.fill(cand, -1);\r\n    int num = 0;\r\n    // cuplare\r\n    for (int i = 0; i < n; i++) {\r\n        boolean found = false;\r\n        for (int j = 0; j < k - 1; j++) {\r\n            if (cand[j] == a[i]) {\r\n                notMatched[j]++;\r\n                found = true;\r\n                break;\r\n            }                \r\n        }\r\n        if (!found) {\r\n            for (int j = 0; j < k - 1; j++) {\r\n                if (notMatched[j] == 0) {\r\n                    cand[j] = a[i];\r\n                    notMatched[j] = 1;\r\n                    found = true;\r\n                    break;\r\n                }                \r\n            }\r\n            if (!found) {\r\n                for (int  j = 0; j < k – 1; j++) notMatched[j]--;                \r\n            }\r\n        }\r\n    }\r\n\r\n   // verificare\r\n   for (int i = 0; i < n; i++) {\r\n       for (int j = 0; j < k - 1; j++) {\r\n           if (a[i] == cand[j] && notMatched[j] != 0)  num[j]++;                  \r\n       }\r\n   }\r\n\r\n   int numMaj = 0;\r\n   for (int j = 0; j < k - 1; j++) {\r\n       if (num[j] > n/k) numMaj++;\r\n   }\r\n\r\n   int[] ret = new int[numMaj];\r\n   numMaj = 0;\r\n   for (int j = 0; j < k - 1; j++) {\r\n       if (num[j] > n/k) {\r\n           ret[numMaj] = cand[j];\r\n           numMaj++;\r\n       }     \r\n   }\r\n\r\n   return ret;\r\n}\r\n==\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# T.H.Cormen, C. E. Leiserson, R. R. Rivest, _Introducere în algoritmi_, ed. Agora 2000\r\n# R. S. Boyer, J. S. Moore, _A Fast Majority Vote Algorithm_\r\n\r\n!probleme-majoritatii-votului?IA_bug_in_FF2.jpg!',3146,'public',4383,NULL),('articole/template-algoritmi','articole/template-algoritmi','2008-12-13 15:07:56','2009-12-27 20:30:40','* !>articole/template-algoritmi?tree-decomposition.jpg! {\'Probleme de tăietură\':probleme-de-taietura}\r\n* \'Problema majorităţii votului\':problema-majoritatii-votului\r\n* {\'Problema 2-satisfiabilitatii\':2-sat}\r\n* \'Probleme cu secvente\':probleme-cu-secvente\r\n* \'Probleme de acoperire &#40;partea I&#41;\':probleme-de-acoperire-1\r\n* \'Probleme de acoperire &#40;partea a II-a&#41;\':probleme-de-acoperire-2\r\n* \'Tree decompositions\':tree-decompositions\r\n* \'Rotatie lexicografic minima\':rotatie-lexicografic-minima\r\n* \'Missing Numbers\':missing-numbers\r\n*{display: %display%} \'Algoritmul lui Kuhn (Ungar)\':algoritm-kuhn\r\n*{display: %display%} \'Taietura minima in graf cu costuri\':taietura-minima\r\n*{display: %display%} \'Lowest common ancestor\':lowest-common-ancestor\r\n*{display: %display%} \'Automate finite si KMP\':automate-finite-si-kmp\r\n*{display: %display%} \'Aplicatii ale cautarii binare\':aplicatii-ale-cautarii-binare\r\n*{display: %display%} \'Al K-lea drum minim\':al-k-lea-drum-minim\r\n*{display: %display%} \'Ciclu hamiltonian in graf dens\':ciclu-hamiltonian-in-graf-dens',3146,'protected',NULL,NULL),('algoritmiada-2010/runda-2/solutii/popularitate','Popularitate','2009-12-20 13:52:11','2009-12-21 23:25:50','h1(#popularitate). \'Popularitate\':problema/popularitate\r\n\r\nPrima varianta pentru rezolvarea acestei probleme este folosirea numerelor mari. Inmultim in prima faza toate numerele dintr-un grup si apoi le impartim la $K$ atata timp cat restul impartirii este $0$. Aceasta abordare obtine $30$ de puncte.\r\nAtunci cand $K$ este prim, este de ajuns sa calculam puterea la care apare $K$ in fiecare numar al grupului, fie acesta $T{~j~}$. Atunci popularitatea grupului este $P = T{~1~} + T{~2~} + ... + T{~N{~i~}~}$. Aceasta abordare obtine $30$ de puncte.\r\nUn program care pentru K compus calculeaza P folosind prima metoda si pentru K prim calculeaza P folosind metoda a doua obtine $50$ de puncte.\r\nSolutia de 100 de puncte a problemei se bazeaza pe reducerea cazului in care K este compus la o varianta modificata a rezolvarii pentru K prim. Fie $K = K{~1~}^F{~1~}^ * K{~2~}^F{~2~}^ * ... * K{~Q~}^F{~Q~}^$ unde $K{~1~}, K{~2~} ... K{~Q~}$ sunt factori primi distincti si presupunem ca $F{~1~}, F{~2~} ... F{~Q~} > 0$, In acest caz $Q < log(K)$. Fie $P{~i~}$ popularitatea grupului calculata pentru $K{~i~}$, atunci popularitatea grupului pentru $K$ este $min( [P{~i~} / F{~i~}] )$ cu $1 &le; i &le; Q$. Complexitatea finala este $O(sqrt(K) + M*N*log(K))$.',2970,'public',NULL,NULL),('template/taskheader','template/taskheader','2006-11-05 16:43:46','2009-12-22 14:25:46','&nbsp;\r\n\r\ntable{margin-left:auto;margin-right:auto;}. | *Fişierul intrare/ieşire:* | ==TaskParam(param=\"id\" task_id=\"%task_id%\")==.in, ==TaskParam(param=\"id\" task_id=\"%task_id%\")==.out | *Sursă* | ==TaskParam(param=\"source\" task_id=\"%task_id%\")== |\r\n| *Autor* | ==TaskParam(param=\"author\" task_id=\"%task_id%\")== | \'*Adăugată de*\':implica-te/extinde-arhiva/ | ==TaskParam(param=\"formatted_owner\" task_id=\"%task_id%\")== |\r\n| *Timp execuţie pe test* | ==TaskParam(param=\"timelimit\" task_id=\"%task_id%\")== sec | *Limită de memorie* | ==TaskParam(param=\"memlimit\" task_id=\"%task_id%\")== kbytes|\r\n\r\n==TaskOpen(task_id=\"%task_id%\")==\r\n\r\np{float: right; margin-right: 1em}. \'Vezi solutiile trimise\':monitor?task=%task_id%\r\n\r\nh1. ==TaskParam(param=\"title\" task_id=\"%task_id%\")==\r\n \r\n\r\n',1490,'protected',NULL,NULL),('runda/suma','suma','2009-12-25 21:49:09','2009-12-25 21:49:09','h1. == roundparam(round_id=\"suma\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"suma\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"suma\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"suma\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"suma\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/suma/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"suma\" score=\"1\")==',11514,'round: suma',NULL,NULL),('runda/suma/clasament','Clasament suma','2009-12-25 21:49:09','2009-12-25 21:49:09','h1. Clasament ==roundparam(round_id=\"suma\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"suma\")==',11514,'round: suma',NULL,NULL),('runda/suma1','suma1','2009-12-25 21:56:13','2009-12-25 21:56:13','h1. == roundparam(round_id=\"suma1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"suma1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"suma1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"suma1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"suma1\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/suma1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"suma1\" score=\"1\")==',11514,'round: suma1',NULL,NULL),('template/taskfooter','template/taskfooter','2006-11-05 16:40:55','2009-12-23 23:26:34','== TaskSubmit(task_id=\"%task_id%\") ==\r\n\r\n==AlgorithmTags(task_id=\"%task_id%\")==\r\n\r\n\"Cum se trimit solutii?\":documentatie/tutorial',1490,'protected',NULL,NULL),('notiuni-de-geometrie-si-aplicatii/arii','Arii','2009-06-28 22:36:19','2009-12-24 10:58:02','(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'0. Introducere\':notiuni-de-geometrie-si-aplicatii#introducere\r\n* \'**1. Arii**\':notiuni-de-geometrie-si-aplicatii/arii\r\n** \'- triunghi\':notiuni-de-geometrie-si-aplicatii/arii#triunghi\r\n** \'- patrulater\':notiuni-de-geometrie-si-aplicatii/arii#patrulater\r\n** \'- poligon\':notiuni-de-geometrie-si-aplicatii/arii#poligon\r\n* \'2. Drepte\':notiuni-de-geometrie-si-aplicatii/drepte\r\n** \'- elemente generale\':notiuni-de-geometrie-si-aplicatii/drepte#general\r\n** \'- ecuaţii\':notiuni-de-geometrie-si-aplicatii/drepte#ecuatii\r\n** \'- distanţa punct-linie\':notiuni-de-geometrie-si-aplicatii/drepte#dpl\r\n** \'- distanţa punct-segment(semidreaptă)\':notiuni-de-geometrie-si-aplicatii/drepte#dps\r\n* \'3. Punct în poligon\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon\r\n** \'- crossing-number\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon#cn\r\n** \'- winding-number (?)\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon#wn\r\n** \'- şmenuri\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon#smen\r\n* \'4. Intersecţii de drepte şi segmente\':notiuni-de-geometrie-si-aplicati/intersectii-drepte-si-segmente\r\n* 5. Distanţe\r\n** - între linii\r\n** - între segmente şi semidrepte\r\n** - cea mai mică distanţă între două mobile\r\n* 6. Bounding ...\r\n** - ... box\r\n** - ... circle\r\n* \'7. Infaşurătoare convexă\':notiuni-de-geometrie-si-aplicatii/infasuratoare-convexa\r\n* 8. Puncte extreme şi distanţa poligon-linie\r\n* 9. Tangente\r\n* 10. Probleme de concurs\r\n\r\nh2. 1. Arii\r\n\r\nNoţiunea de arie este una de bază în geometria analitică. Este necesară însă o prezentare a diferitelor metode de a calcula ariile in contextul prelucrarii datelor pe calculator.\r\n\r\nh2(#triunghi). Aria unui triunghi\r\n\r\nÎn determinarea ariei unui triunghi se poate folosi **formula lui Heron**:\r\n<tex>\\begin{math} A=\\sqrt{s\\cdot(s-a)\\cdot(s-b)\\cdot(s-c)}\\end</tex>\r\nÎn formulă, $s$ reprezintă semiperimetrul triunghiului, iar $a, b, c$ lungimile laturilor triunghiului. Această formulă apare şi într-o altă formă, mult mai adecvată algoritmilor prin faptul că se evită calcularea lungimii laturilor cu radical:\r\n<tex>\\begin{math} A=\\frac{1}{4}\\sqrt{4a^{2}b^{2}-\\left(a^{2}+b^{2}-c^{2}\\right)^{2}}\\end</tex>\r\n\r\nÎn contextul geometriei vectoriale, modulul produsului vectorial a doi vectori o reprezintă aria paralelogramului cuprins între vectori. Aplicând raţionamentul la triunghiuri, obţinem relaţia:\r\n<tex>\\begin{math} A = \\frac{1}{2}\\|\\vec{v}\\times\\vec{w}\\| = \\frac{1}{2}\\cdot abs\\left(\\left|\\begin{array}{ccc}\r\n\\ x_1 & y_1 & 1\\\\\r\nx_2 & y_2 & 1\\\\\r\nx_3 & y_3 & 1\\end{array}\\right|\\right)\\end{math}</tex>\r\n\r\n!notiuni-de-geometrie-si-aplicatii/arii?vector.jpg!\r\n\r\n\r\nh2(#patrulater). Aria unui patrulater\r\n\r\nDupă cum am văzut în cazul unui triunghi, aria unui paralelogram $ABCD$ este egală cu modulul produsului vectorial al vectorilor reprezentaţi de 2 laturi neparalele.\r\n<tex>\r\n\\begin{math} \r\nA = \\|\\overrightarrow{AB}\\times\\overrightarrow{AD}\\|\r\n\\end{math}\r\n</tex>\r\n\r\nPentru un patrulater oarecare $ABCD$, putem considera {$M{~1~}$}, {$M{~2~}$}, {$M{~3~}$}, {$M{~4~}$} mijloacele laturilor acestuia. Se poate demonstra că patrulaterul {$M{~1~}M{~2~}M{~3~}M{~4~}$} este un paralelogram cu aria jumătate din aria lui $ABCD$:\r\n<tex> \\begin{math}\r\nA = 2\\cdot\\|\\left(\\overrightarrow{r_{M_{2}}}-\\overrightarrow{r_{M_{1}}}\\right)\\times\\left(\\overrightarrow{r_{M_{4}}}-\\overrightarrow{r_{M_{1}}}\\right)\\|\\end{math}</tex>\r\n<tex> \\begin{math}\r\nA = 2\\cdot\\|\r\n\\left(\\frac{ \\vec{r_{B}}+\\vec{r_{C}} }{2}-\\frac{ \\vec{r_{A}}+\\vec{r_{B}} }{2}\\right)\r\n\\times\r\n\\left(\\frac{ \\vec{r_{A}}+\\vec{r_{D}} }{2}-\\frac{ \\vec{r_{A}}+\\vec{r_{B}} }{2}\\right)\\|\r\n\\end{math} </tex>\r\n<tex>\\begin{math}\r\nA = \\frac{1}{2}\\cdot\\|\r\n\\left(\\overrightarrow{r_{C}}-\\overrightarrow{r_{A}}\\right)\\times\\left(\\overrightarrow{r_{D}}-\\overrightarrow{r_{B}}\\right)\r\n\\|\r\n\\end{math}</tex>\r\n<tex>\\begin{math}A = \\frac{1}{2}\\cdot\\|\\overrightarrow{AC}\\times\\overrightarrow{BD}\\|\\end{math}</tex>\r\n\r\n!notiuni-de-geometrie-si-aplicatii/arii?patrulater.jpg!\r\n\r\nh2(#poligon). Aria unui poligon\r\n\r\nPentru a calcula aria unui poligon oarecare {$A{~1~}A{~2~}A{~3~}..A{~n~}$}, vom considera un punct P arbitrar ales în plan. Vom \"împărţi\" poligonul în triunghiuri de forma $PA{~i~}A{~i+1~}$ (considerăm că A{~1~}=A{~n+1~}) şi vom calcula \"aria cu semn\" $T{~i~}$ a fiecărui triunghi (în formula ariei nu vom folosi funcţia de valoare absolută). Distingem în acest moment două cazuri:\r\n\r\n* Poligonul are vârfurile orientate trigonometric. Pentru fiecare latură \"spre dreapta\", aria $T{~i~}$ corespunzătoare va fi negativă, iar pentru fiecare latură \"spre stânga\", aria $T{~i~}$ corespunzătoare va fi pozitivă.\r\n* Poligonul are vârfurile orientate antitrigonometric. Pentru fiecare latură \"spre dreapta\", aria $T{~i~}$ corespunzătoare va fi pozitivă, iar pentru fiecare latură \"spre stânga\", aria $T{~i~}$ corespunzătoare va fi negativă.\r\n\r\nÎn ambele cazuri, efectuând suma algebrică a ariilor $T{~i~}$ vom obţine aria poligonului (deoarece ariile negative vor \"anula\" zonele corespunzătoare ariilor pozitive care se află în afara poligonului).\r\n\r\n!notiuni-de-geometrie-si-aplicatii/arii?poligon2.jpg!\r\n\r\nDacă alegem punctul $P(0,0)$, fiecare arie $T{~i~}$ devine: \r\n<tex>\\begin{math}T_{i} = \\frac{1}{2}\\cdot abs\\left(\\left|\\begin{array}{ccc}\r\n\\ 0 & 0 & 1\\\\\r\nx_i & y_i & 1\\\\\r\nx_i+1 & y_i+1 & 1\\end{array}\\right|\\right) = \\frac{1}{2}\\cdot\\left(x_i\\cdot y_{i+1}-x_{i+1}\\cdot y_i\\right)\r\n\\end{math}</tex>\r\n\r\nFormula finală devine:\r\n<tex>\\begin{math}\r\nA = \\displaystyle\\sum_{i=1}^n T_i = \\frac{1}{2}\\cdot\\displaystyle\\sum_{i=1}^n \\left(x_i\\cdot y_{i+1}-x_{i+1}\\cdot y_i\\right)\r\n\\end{math}</tex>\r\n\r\nAceastă formulă reprezintă \"aria cu semn\" a poligonului (o arie pozitivă indică parcurgerea vârfurilor în ordine trigonometrică, iar o arie negativă, parcurgerea in ordine antitrigonometrică).',9232,'public',NULL,NULL),('runda/porc_revelion','porc_revelion','2009-12-30 11:02:17','2009-12-30 11:02:17','h1. == roundparam(round_id=\"porc_revelion\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"porc_revelion\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"porc_revelion\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"porc_revelion\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"porc_revelion\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/porc_revelion/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"porc_revelion\" score=\"1\")==',6333,'round: porc_revelion',NULL,NULL),('utilizator/pauldb','Profil PaulDB','2006-11-24 21:00:07','2009-12-27 14:43:46','h2. Despre mine\r\n\r\n* Vicepresedinte infoarena si presedinte Algoritmiada 2010\r\n* Student in anul II la Universitatea Bucuresti, \"Facultatea de Matematica si Informatica\":http://fmi.unibuc.ro/ro/, sectia Informatica\r\n* Absolvent al \"Liceului International de Informatica Bucuresti\":http://www.ichb.ro/\r\n* Presedinte al comisiei stiintifice a concursului \"Stelele Informaticii 2009\"\r\n* Membru in comisii: \"ICPO 2008\":http://www.icpo2008.org/, ONI 2009, Lot Bistrita 2009, Lot Cluj-Napoca 2009, CEOI 2009\r\n* Antrenor al echipei de informatica a Liceului International de Informatica Bucuresti din 2007\r\n* Coordonator al echipei de informatica a Liceului International de Informatica Bucuresti din 2009\r\n* Cei ce m-au ajutat de-a lungul timpului au fost: Edmond Butyka, \"Mugurel Ionut Andreica\":/utilizator/mugurelionut, \"Sorin Stancu Mara\":/utilizator/maxdamage, \"Alexandru Mosoi\":/utilizator/alexandru.mosoi, \"Mircea Pasoi\":/utilizator/domino, \"Silviu Ganceanu\":/utilizator/silviug si \"Andrei Grigorean\":/utilizator/wefgef.\r\n\r\nh2. Distinctii primite\r\n\r\n* Mentiune (Locul 7), ONI 2004, Buzau\r\n* Mentiune (Locul 18), ONI 2005, Galati\r\n* Mentiune (Locul 9), ONI 2006, Targoviste\r\n* Participant la finala preONI 2006\r\n* Premiul 3, ONI 2007, Cluj - Napoca\r\n* Membru in lotul national in 2007\r\n* Participant la finala .campion 2007\r\n* Participant la finala preONI 2007\r\n* Locul 3 la finala preONI 2008\r\n* Mentiune si medalie de aur (locul 6), ONI 2008, Ploiesti\r\n* Premiu special la finala .campion 2008\r\n* Membru in lotul national in 2008\r\n* Argint la CEOI 2008, Dresda, Germania\r\n* Argint la IOI 2008, Cairo, Egipt',1792,'protected',NULL,NULL),('probleme-de-taietura','Probleme de tăietură','2009-04-06 05:48:04','2009-12-27 20:33:14','h1. Probleme de tăietură\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"andrici_cezar\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n\r\n(toc){width: 25em}*{text-align:center} *Conţinut:*\r\n* \'Aplicaţia 1\':probleme-de-taietura#aplicatia-1\r\n* \'Aplicaţia 2\':probleme-de-taietura#aplicatia-2\r\n* \'Aplicaţia 3 Really Strange\':probleme-de-taietura#aplicatia-3\r\n* \'Aplicaţia 4\':probleme-de-taietura#aplicatia-4\r\n* \'Aplicaţia 5\':probleme-de-taietura#aplicatia-5\r\n* \'Aplicaţia 6\':probleme-de-taietura#aplicatia-6\r\n* \'Aplicaţia 7 Bursele Agora 2001\':probleme-de-taietura#aplicatia-7\r\n* \'Aplicaţia 8 Thinking Backward\':probleme-de-taietura#aplicatia-8\r\n* \'Aplicaţia 9 Internet Problem Solving Contest 2000\':probleme-de-taietura#aplicatia-9\r\n* \'Aplicaţia 10 The partition of a cake\':probleme-de-taietura#aplicatia-10\r\n* \'Aplicaţia 11 Count the faces\':probleme-de-taietura#aplicatia-11\r\n* \'Aplicaţia 12 Cercuri,Algoritmus\':probleme-de-taietura#aplicatia-12\r\n* \'Bibliografie\':probleme-de-taietura#bibliografie\r\n\r\n\r\nÎn cadrul acestui articol vom prezenta câteva enunţuri, împreună cu soluţiile corespunzătoare, reprezentative pentru clasa problemelor de tăietură.\r\n\r\nh2(#aplicatia-1). Aplicaţia #1\r\n\r\nbq. Pentru un număr natural $n$ dat, se cere numărul maxim de regiuni în care se poate împărţi planul folosind $n$ drepte.\r\n\r\np=. !probleme-de-taietura?poza-1.bmp!\r\n\r\nh3. Rezolvare\r\n\r\nMai întâi vom prezenta două observaţii:\r\n\r\n# în configuraţia cu număr maxim de regiuni nu vom avea două drepte paralele, deoarece două drepte care se intersectează formează în plan patru regiuni, în timp ce două drepte paralele formează în plan doar trei regiuni;\r\n# pentru a obţine un număr maxim de regiuni nu vor exista trei drepte care să se intersecteze într-un punct deoarece astfel am „pierde” o regiune triunghiulară formată din punctele de intersecţie ale celor trei drepte.\r\n\r\nDacă aceste două condiţii sunt îndeplinite, vom vedea în continuare că orice configuraţie de $n$ drepte împarte planul în acelaşi număr de regiuni. Notăm cu <tex> d_{n} </tex> acest număr. \r\n\r\nPresupunem că valoarea <tex> d_{n} </tex> este cunoscută; să vedem acum ce se întâmplă dacă mai adăugăm o dreaptă. \r\n\r\nAceastă nouă dreaptă va fi intersectată de celelalte drepte în $n$ puncte distincte. Fiecare segment de dreaptă şi semidreaptă în care este împărţită a $(n + 1)$-a dreaptă taie o regiune veche în două regiuni noi. De aici obţinem că <tex> d_{n+1} = d_{n} + n + 1 </tex>. \r\n\r\nAşadar, vom avea <tex> d_{n} = n + (n - 1) + (n - 2) + \\ldots + 2 + d_{1} </tex>. Astfel, folosind indentitatea <tex> 1 + 2 + 3 + \\ldots + n = \\dfrac{n(n+1)}{2} </tex>, obţinem <tex> d_{n} = \\dfrac{n(n + 1)}{2} + 1 </tex>.\r\n\r\nMenţionăm că problemele în care se cere maximizarea numărului de regiuni în care un pătrat, un triunghi sau un cerc este împărţit de $n$ drepte, au aceeaşi soluţie.\r\n\r\np=. !probleme-de-taietura?poza-2.bmp!\r\n\r\nh2(#aplicatia-2). Aplicaţia #2\r\n\r\nbq. Dându-se un număr natural $n$, se cere numărul maxim de regiuni în care $n$ cercuri pot împărţi planul.\r\n\r\np=. !probleme-de-taietura?poza-4.bmp!\r\n\r\nh3. Rezolvare\r\n\r\nEste evident că oricare două cercuri trebuie să se intersecteze în exact două puncte, nu să fie tangente sau să nu se intersecteze deloc pentru că astfel am „pierde” o regiune, iar oricare trei cercuri nu au niciun punct comun. \r\n\r\nOrice configuraţie care satisface această cerinţă va împărţi planul într-un număr maxim de regiuni. Vom nota cu <tex> c_{n} </tex> numărul maxim de regiuni în care este împărţit planul de $n$ cercuri. \r\n\r\nSă vedem ce se întîmplă când adăugăm un nou cerc la această configuraţie. Cercul nou va fi intersectat de cele $n$ cercuri în $2n$ puncte distincte, şi astfel va fi împărţit în $2n$ arce.\r\n\r\nFiecare dintre aceste arce împarte o zonă veche în două zone noi. De aici tragem concluzia că <tex> c_{n+1} = 2n + c_{n} </tex>. \r\n\r\nAstfel, putem să scriem valoarea <tex> c_{n} </tex> ca <tex> 2(n-1) + 2(n-2) + \\ldots + 2 + c_{1} </tex>. \r\n\r\nDe aici, folosind din nou identitatea <tex> 1 + 2 + \\ldots + n = \\dfrac{n(n+1)}{2} </tex>, avem că <tex> c_{n} = n(n-1) + 2 </tex>.\r\n\r\nEste evident că şi problema în care se cere maximizarea numărului de regiuni în care este împărţită suprafaţa unei sfere de $n$ cercuri are aceeaşi soluţie.\r\n\r\np=. !probleme-de-taietura?poza-5.bmp!\r\n\r\nh2(#aplicatia-3). Aplicaţia #3: \'!! Really Strange !!\':http://online-judge.uva.es/p/v105/10519.html (UVA)\r\n\r\nbq. Se dau $n$ cercuri care se intersectează oricare două în două puncte şi nu există trei care se intersectează într-un punct; se cere să se determine numărul zonelor în care este împarţit planul de aceste $n$ cercuri.\r\nRestricţii: $n &le; 10^100^$.\r\n\r\nh3. Rezolvare\r\n\r\nObservăm ca sunt indeplinite condiţiile de maximalitate cerute mai sus (vezi aplicaţia \'#2\':probleme-de-taietura#aplicatia-2), deci rezultatul este <tex> c_{n} </tex>. Singura problemă care rămâne este implementarea operaţiilor cu numere mari (dacă soluţia nu este implementată în _Java_).\r\n\r\nh2(#aplicatia-4). Aplicaţia #4\r\n\r\nbq. Avem un număr natural $n$. Vrem să determinăm numărul maxim de regiuni în care $n$ elipse pot împărţi planul.\r\n\r\np=. !probleme-de-taietura?poza-6.bmp!\r\n\r\nh3. Rezolvare\r\n\r\nLa fel ca şi în cazul cercurilor, nici aici nu trebuie să avem elipse tangente, elipse care să nu se intersecteze sau trei elipse care să se intersecteze într-un acelaşi punct. Elipsele trebuie să se intersecteze în patru puncte; dacă s-ar intersecta numai în două puncte, atunci configuraţia nu ar avea număr maxim de regiuni.\r\n\r\nNotăm cu <tex> e_{n} </tex> numărul pe care îl căutăm. Câte regiuni noi apar cand adăugăm o nouă elipsă? O nouă elipsă va fi intersectată de fiecare dintre celelalte elipse în patru puncte, deci <tex> e_{n+1} = 4n + e_{n} </tex>. De aici obţinem că <tex> e_{n} = 2n(n-1) + 2 </tex>.\r\n\r\np=. !probleme-de-taietura?poza-7.bmp!\r\n\r\nh2(#aplicatia-5). Aplicaţia #5\r\n\r\nbq. Dându-se un număr natural $n$, se cere numărul maxim de regiuni în care $n$ triunghiuri pot împărţi planul.\r\n\r\np=. !probleme-de-taietura?poza-9.bmp!\r\n\r\nh3. Rezolvare\r\n\r\nRepetând raţionamentul de la problemele anterioare avem <tex> t_{n+1} = 6n + t_{n} </tex>, de unde <tex> t_{n} = 3n(n-1) + 2 </tex>. \r\n\r\nh2(#aplicatia-6). Aplicaţia #6\r\n\r\nbq. Pentru $n$ plane determinaţi numărul maxim de zone în care poate fi împărţit spaţiul folosind aceste plane.\r\n\r\nh3. Rezolvare\r\n\r\nŞi în această problemă urmăm acelaşi raţionament. Este evident că trebuie ca fiecare plan să se intersecteze cu toate celelalte, că oricare trei plane trebuie să nu aibă nicio dreaptă comună, că oricare trei plane nu trebuie să fie paralele cu nicio dreaptă şi oricare patru plane nu trebuie să aibă niciun punct comun. \r\n\r\nNotăm <tex> p_{n} </tex> numărul maxim de zone în care $n$ plane împart spaţiul. Dacă adăugăm un nou plan, acesta va fi intersectat de celelalte plane în $n$ drepte, drepte printre care, datorită restricţiilor pe care le-am pus, nu vom avea două paralele sau trei care să se intersecteze într-un punct.\r\n\r\nAcest plan va fi împărţit în <tex> d_{n} </tex> regiuni de aceste drepte datorită restricţiilor impuse. Fiecare regiune din plan taie o zonă din spaţiu în două noi zone, de unde <tex> p_{n+1} = d_{n} + p_{n} </tex>. \r\n\r\nAstfel avem:\r\n<tex> p_{n} = \\dfrac{n(n-1)}{2} + 1 + \\dfrac{(n-1)(n-2)}{2} + 1 + \\ldots + \\dfrac{2*1}{2} + 1 + p_{1} </tex>\r\n<tex> p_{n} = \\dfrac{n^2 - n + (n-1)^2 - (n-1) + \\ldots + 2^2 - 2 + 1 - 1 + (n-1)}{2} + 2 </tex>\r\n<tex> p_{n} = \\dfrac{ \\dfrac{n(n+1)(2n+1)}{6} - \\dfrac{n(n+1)}{2} + (n-1)}{2} + 2 </tex>\r\n<tex> p_{n} = \\dfrac{ \\dfrac{n^3}{3} + \\dfrac{n^2}{2} + \\dfrac{n}{6} - \\dfrac{n^2}{2} - \\dfrac{n}{2} }{2} + n + 1 </tex>\r\n<tex> p_{n} = \\dfrac{n^3}{6} + \\dfrac{5n}{6} + 1 </tex>.\r\n\r\nAm folosit identităţile <tex> 1 + 2 + \\ldots + n = \\dfrac{n(n+1)}{2} </tex> şi <tex> 1 + 2^2 + 3^2 + \\ldots + n^2 = \\dfrac{n(n+1)(2n+1)}{6} </tex>, identităţi care se pot demonstra uşor prin inducţie.\r\n\r\nMenţionăm că dacă vrem să împărţim un cub, un cilindru, o sferă etc. în număr maxim de regiuni folosind $n$ plane, formula se păstrează.\r\n\r\nh2(#aplicatia-7). Aplicaţia #7 (Bursele Agora, 2001)\r\n\r\nbq. Dându-se un număr natural $n$, să se determine numărul maxim de zone în care $n$ sfere pot împărţi spaţiul.\r\n\r\nh3. Rezolvare\r\n\r\nPornim la fel ca în cazul problemei anterioare; oricare două sfere se vor intersecta şi nu vor exista trei sfere care să se intersecteze în acelaşi punct. Vom nota cu <tex> s_{n} </tex> numărul maxim de regiuni în care poate fi împărţit spaţiul cu $n$ sfere. Să vedem ce se întâmplă când adăugăm o sferă.\r\n\r\nAceastă sferă va fi intersectată de toate celelalte $n$ sfere în $n$ cercuri; pentru ca numărul de regiuni noi să fie maxim aceste cercuri vor împărţi sfera într-un număr maxim de regiuni; acest număr este <tex> c_{n} </tex> aşa cum am discutat în aplicaţia \'#2\':probleme-de-taietura#aplicatia-2.\r\n\r\nObţinem astfel:\r\n<tex> s_{n+1} = c_{n} + s_{n} </tex>\r\n<tex> s_{n+1} = c_{n} + c_{n-1} + \\ldots + c_{1} </tex>\r\n<tex> s_{n+1} = n(n-1) + 2 + (n-1)(n-2) + 2 + \\ldots + 2 </tex>\r\n<tex> s_{n+1} = 1 + 2^2 + \\ldots + n^2 - 1 - 2 - 3 - \\ldots - n + 2n </tex>, de unde <tex> s_{n} = \\dfrac{n(n^2 - 3n + 8)}{3} </tex>.\r\n\r\nh2(#aplicatia-8). Aplicaţia #8: \'Thinking Backward\':http://uva.onlinejudge.org/external/106/10623.html (UVA)\r\n\r\nbq. Se consideră un număr $N$ care reprezintă numărul maxim de regiuni în care poate fi împărţit planul de către $m$ elipse, $n$ cercuri şi $p$ triunghiuri. Se cere să se determine toate valorile posibile pentru $m$, $n$ şi $p$.\r\nRestricţii: $N$ întreg, fără semn, reprezentabil pe $32$ biţi; $0 &le; m < 100$; $0 &le; n < 20 000$; $0 &le; p < 100$.\r\n\r\nh3. Rezolvare\r\n\r\nDacă am cunoaşte pentru trei parametri $m$, $n$ şi $p$ care este numărul maxim de părţi în care poate fi împărţit planul de către $m$ elipse, $n$ cercuri şi $p$ triunghiuri, atunci am putea încerca toate posibilităţile pentru $m$, $n$ şi $p$ şi am găsi şi tripletele pentru care rezultatul ar fi egal cu $N$. \r\n\r\nAm putea optimiza puţin acest algoritm iterând doar pe toate valorile $m$ şi $p$; astfel vom obţine o ecuaţie cu necunoscuta $n$ şi vom efectua $10 000$ de rezolvări de ecuaţii în loc de $200 000 000$ de comparaţii.\r\n\r\nSă vedem cum găsim numărul maxim de zone. Din nou, oricare două figuri se intersectează în număr maxim de intersecţii, un cerc cu o elipsă în patru puncte, un cerc sau o elipsă cu un triunghi în şase puncte.\r\n\r\nMai întâi punem cele $m$ elipse în plan; ele vor împărţi planul în <tex> e_{m} = 2m(m-1) + 2 </tex> regiuni.\r\n\r\nÎn continuare adăugăm cercurile. Să notăm numărul maxim de zone în care $n$ cercuri şi $m$ elipse pot împărţi planul prin <tex> ec_{m ,n} </tex>. Dacă valoarea <tex> e(m,n-1) </tex> este cunoscută, atunci, în momentul în care adăugăm un nou cerc, acesta va fi intersectat de $m$ elipse în $4m$ puncte şi de $n-1$ cercuri în $2(n-1)$ puncte, deci cercul va fi împărţit în $4m + 2(n-1)$ arce care vor împărţi tot atâtea regiuni care existau deja în câte două regiuni noi. \r\n\r\nAşadar, avem:\r\n<tex> ec_{m,n} = 4m + 2(n-1) + ec_{m,n-1} </tex>\r\n<tex> ec_{m,n} = 4m + 2(n-1) + 4m + 2(n-2) + \\ldots + 4m + 2 + ec_{m,0} </tex>\r\n<tex> ec_{m,n} = 4m(n-1) + n (n-1) + 2m(m-1) + 2 </tex>.\r\n\r\nSă vedem ce se întâmplă când adăugăm triunghiurile. Vom nota prin <tex> ect_{m, n, p} </tex> numărul maxim de zone în care poate fi împărţit planul de $m$ elipse, $n$ cercuri şi $p$ triunghiuri.\r\n\r\nDacă valoarea <tex> ect_{m, n, p - 1} </tex> este cunoscută, atunci, în momentul în care vom adăuga un nou triunghi acesta va intersecta cele $m$ cercuri în $6m$ puncte, cele $n$ elipse în $6n$ puncte şi cele $p-1$ triunghiuri în $6(p-1)$ puncte, formându-se $6m + 6n + 6(p-1)$ noi zone. \r\n\r\nAşadar, obţinem: \r\n<tex> ect_{m, n, p} = 6(m + n + p - 1) + ect_{m, n, p - 1} </tex>\r\n<tex> ect_{m, n, p} = 6(m + n + p - 1 + m + n + p - 2 + \\ldots + m + n + 1) + ect_{n, m, 0} </tex>\r\n<tex> ect_{m, n, p} = 6(p-1)(m+n) + 3p(p-1) + 4m(n-1) + n(n-1) + 2m(m-1) + 2 </tex>.\r\n\r\nProblemele anterioare au fost cam matematice şi ele sunt numite de obicei de olimpici peiorativ ca „probleme de formulă”. Majoritatea olimpicilor la informatică participă aici pentru că matematica nu le „place atât de mult” şi, deci, nici apariţia unor probleme ca cele de mai sus care sunt „mai mult de mate decât de info” nu îi prea încântă. \r\n\r\nCum poate fi rezolvată o problemă de formulă fără să avem intuiţia matematică sau cunoţinţele matematice necesare?\r\n\r\nUneori elevii apelează la următorul truc: determină primele câteva valori manual sau cu ajutorul unor algoritmi _brute force_ şi apoi speră ca formula să fie de o anumită formă; de exemplu ar putea fi un polinom de un grad mic. De exemplu, am putea presupune că formula este de forma <tex> f(n) = An^3 + Bn^2 + Cn + D </tex>. Calculând primele patru valori, vom cunoaşte valorile $f(1)$, $f(2)$, $f(3)$, $f(4)$. Atribuind pe rând lui $n$ valorile $1$, $2$, $3$ şi $4$ putem obţine un sistem de ecuaţii cu necunoscutele $A$, $B$, $C$ şi $D$.\r\n\r\nO altă posibilitate este să încercăm să vedem cum se comportă şirul de numere: are o creştere polinomială sau exponenţială, apar valorile lui în triunghiul lui _Pascal_ etc. Dacă aveţi la dispoziţie o conexiune la internet (participaţi la un concurs online sau vă antrenaţi), puteţi căuta valorile din şirul de soluţii la \'_Eciclopedia Online a şirurilor de întregi_\':http://www.research.att.com/~njas/sequences/ care este o resursă foarte utilă în cazul problemelor de acest gen.\r\n\r\nh2(#aplicatia-9). Aplicaţia #9: \'Internet Problem Solving Contest, 2000\':http://plg1.cs.uwaterloo.ca/~acm00/ipsc/\r\n\r\nbq. Se consideră $n$ drepte în plan, fiecare dreaptă este descrisă prin două puncte distincte aflate pe acea dreaptă. Se cere să se determine pentru această configuraţie în câte zone este împărţit planul.\r\nRestricţii: $n &le; 1000$.\r\n\r\nh3. Rezolvare\r\n\r\nÎn sfârşit o problemă în care avem nevoie să folosim calculatorul şi talentul de programator... Vom folosi aceeaşi idee ca şi în cazul celorlalte probleme, adică numărăm pe rând în câte zone este împărţit planul de prima dreaptă, primele două drepte până ajungem la toate cele $n$ drepte. Aşadar, vom adăuga în ordine dreptele la configuraţia noastră.\r\n\r\nCând adăugăm o dreaptă, aceasta va fi intersectată de dreptele deja adăugate în $k$ puncte nu neapărat distincte; pe noi ne intereseaza punctele distincte şi, pentru a le număra, putem sorta punctele (în complexitate $O(k log k)$) sau putem folosi o tabelă de dispersie, caz în care timpul necesar devine $O(k)$.\r\n\r\nDacă numărul de puncte distincte este egal cu $m$, atunci numărul total de zone va creşte cu $m$.\r\n\r\nAstfel, algoritmul are complexitatea $O(n^2^ log n)$ dacă folosim sortarea sau $O(n^2^)$ dacă folosim tabela de dispersie.\r\n\r\nh2(#aplicatia-10). Aplicaţia #10: \'The partition of a cake\':http://uva.onlinejudge.org/external/5/527.html (UVA)\r\n\r\nbq. Avem un tort în formă pătratică; dimensiunea acestuia este $1000 x 1000$. Folosim un cuţit pentru a tăia tortul. Va trebui să determinăm în câte bucăţi a fost împărţit tortul după o serie de tăieturi. Numărul tăieturilor nu va fi mai mare de $8$. După tăiere, lungimea oricărei laturi a partiţiei nu va fi mai mică decât unu. Coordonatele vârfurilor tortului vor fi $(0,0) (0,1000) (1000,1000) (1000,0)$. Tăieturile se vor intersecta în două puncte cu marginile tortului. În imagine este prezentat un tort tăiat în zece bucăţi.\r\n\r\np=. !probleme-de-taietura?poza-10.bmp!\r\n\r\nh3. Rezolvare\r\n\r\nSoluţia este asemănătoare celei pentru problema anterioară. Dimensiunile datelor de intrare sunt foarte mici pentru problema aceasta; este posibil ca autorii să fi vrut ca problema să fie rezolvabilă şi folosind împărţiri efective în poligoane a pătratului.\r\n\r\nh2(#aplicatia-11). Aplicaţia #11: \'Count the faces\':http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=44&page=show_problem&problem=1119 (UVA):\r\n\r\nbq. Se dă un graf planar descris prin noduri şi muchii (un graf este planar dacă există o modalitate de a-l desena în plan fără ca muchiile să se intersecteze decât în noduri). Se cere să se determine în câte regiuni împarte planul graful dat. În imagine este prezentat un graf în care feţele sunt numerotate.\r\n\r\np=. !probleme-de-taietura?poza-12.bmp!\r\n\r\nh3. Rezolvare\r\n\r\nEste interesant faptul că în această problemă nu este dată configuraţia în plan a grafului, ci doar structura lui. Un graf poate fi reprezentat în mai multe moduri în plan, ceea ce ne poate face să credem că ar exista o formulă pentru rezolvarea problemei. \r\n\r\nExistă într-adevăr o astfel de formulă care poartă denumirea de _formula lui Euler pentru grafurile planare_. Dacă graful este conex, această formulă este $f - m + n = 2$, unde prin $f$ am notat numărul de feţe, prin $m$ numărul de muchii şi prin $n$ numărul de vârfuri. Formula include faţa exterioară. Această formulă poate fi demonstrată în foarte multe moduri. Dacă doriţi să vedeţi 19 metode de demonstrare puteţi să vizitaţi \'_Nouăsprezece demonstraţii ale formulei lui Euler: V-E+F=2_\':http://www.ics.uci.edu/~eppstein/junkyard/euler/. \r\n\r\nO demonstraţie simplă se bazează metoda inducţie matematice pornind de la un arbore şi adăugând pe rând câte o muchie. La început avem o singură faţă, cea infinită, deci ipoteza de inducţie se verifică: $1 - (n - 1) + n = 2$. Fiecare muchie adăugată împarte o faţă în două, deci, dacă inainte aveam $f - m + n = 2$, acum vom avea $f{~1~} - m{~1~} + n = 2$, unde $f{~1~} = f + 1$ şi $m{~1~} = m + 1$. Aşadar, am demonstrat formula şi putem foarte uşor să rezolvăm problema. Mai trebuie numai să avem grijă ca pentru fiecare componentă conexă să numărăm faţa infinită. Această formulă este adevarată şi în spaţiu pentru poliedre.\r\n\r\nh2(#aplicatia-12). Aplicaţia 12: Cercuri (Algoritmus)\r\n\r\nbq. Se consideră $n$ cercuri în plan. Se cere să se determine numărul zonelor finite în care cercurile date împart planul. Cercurile sunt date prin coordonatele centrului şi rază. În figură este prezentat un exemplu. Numărul căutat al zonelor este 11.\r\n\r\np=. !probleme-de-taietura?poza-13.bmp!\r\n\r\nh3. Rezolvare\r\n\r\nProblema nu poate fi rezolvată folosind aceleaşi idei deoarece aici apar cazuri speciale, cum ar fi punctele de tangenţă, faptul că nu toate cercurile trebuie să se intersecteze între ele (ceea ce duce la apariţia unor zone ca rezultat al unui ciclu de cercuri, aceste zone neputând fi numărate prin procedeul folosit).\r\n\r\nO altă idee ar fi folosirea geometriei computaţionale, dar aceasta pare destul de anevoioasă; lucrurile se simplifică mult dacă abordăm problema prin prisma unor noţiuni de teoria grafurilor.\r\n\r\nFiecare punct de intersecţie va fi considerat un nod. Două noduri vor fi legate printr-o muchie dacă există un cerc pe care să se afle amândouă, iar între ele să nu existe niciun alt punct de intersecţie. Acum vom folosi identitatea lui _Euler_, prezentată în cadrul soluţiei problemei anterioare.\r\n\r\nPentru această problemă nu trebuie să numărăm şi faţa exterioară, deci formula folosită va fi $F = M - V + 1$. Această formulă este adevărată doar în cazul unei singure componente conexe. Pentru mai multe componente, formula devine $F = M - V + C$, unde $C$ este numărul de componente conexe.\r\n\r\nO atenţie deosebită trebuie acordată punctelor de intersecţie prin care trec mai mult de două cercuri, pentru a nu le număra de mai multe ori. Putem rezolva această problemă prin sortarea punctelor de intersecţie ale unui cerc cu toate celelalte cercuri.\r\n\r\nDe asemenea, este necesară eliminarea cercurilor identice (cu acelaşi centru şi raze egale). Din orice mulţime formată din astfel de cercuri este păstrat doar un singur element.\r\n\r\nDeoarece pentru fiecare cerc este necesară o sortare a punctelor de intersecţie, complexitatea algoritmului va fi $O(n^2^ log n)$.\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# A.M. Iaglom, I. M. Iaglom, _Probleme neelementare tratate elementar_, Editura Tehnică, Bucureşti, 1962;\r\n# I. Tomescu, _Probleme de combinatorică şi teoria grafurilor_, Editura Didactică şi Pedagogică. Bucureşti, 1981;\r\n# _Colecţia GInfo_;\r\n',3146,'public',4398,NULL),('runda/cosmin96','cosmin96','2009-12-28 16:59:43','2009-12-28 16:59:43','h1. == roundparam(round_id=\"cosmin96\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cosmin96\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cosmin96\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cosmin96\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"cosmin96\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cosmin96/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cosmin96\" score=\"1\")==',11527,'round: cosmin96',NULL,NULL),('runda/cosmin96/clasament','Clasament cosmin96','2009-12-28 16:59:43','2009-12-28 16:59:43','h1. Clasament ==roundparam(round_id=\"cosmin96\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"cosmin96\")==',11527,'round: cosmin96',NULL,NULL);
@@ -1724,7 +1724,7 @@
 INSERT INTO `ia_textblock_revision` VALUES ('blog/dexonline','DEX online sub capotă','2008-11-14 23:44:46','2008-11-15 05:46:01','_Discutam de mai multă vreme cu_ \'Cătălin Frâncu\':http://www.google.com/search?hl=en&q=catalin+francu&btnG=Search _despre proiecte personale şi despre_ \'Dex Online\':http://dexonline.ro _. Cu Cătălin am mai discutat pe blogul infoarena_ \'aici\':http://infoarena.ro/blog/interviu-cu-catalin-francu _şi_ \'aici\':http://infoarena.ro/blog/interviu-cu-catalin-francu-partea-a-doua _. Acum, la mai bine de un an dupa acele discuţii el a scris un articol foarte interesant despre traiectoria acestui proiect. Articolul este destul de lung, dar cred că e foarte interesant şi puteţi învăţa mult din el. De obicei înveţi din experienta proprie şi durează o perioada până treci prin destule proiecte incât să ai o privire de ansamblu. Articolul ăsta poate să vă scurteze acea perioadă. Aşa că luaţi o cană de cafea sau ceai şi vă urez lectură plăcută!_\r\n\r\n*Scopul articolului*\r\n\r\nAcest articol prezintă diverse aspecte din existenţa de şapte ani a proiectului DEX online. Totuşi, articolul nu este în primul rând despre DEX online. Îl scriu la sugestia lui Cosmin Negruşeri pentru comunitatea infoarena.ro. Intenţia articolului este să disece, pentru foştii şi actualii olimpici la informatică, un exemplu de proiect din lumea reală, pentru a sublinia diferenţele între 1000 de progrămele de câte 100 de linii şi un program de 100.000 de linii, între programarea de unul singur şi lucrul în echipă, într-un proiect cu multe alte faţete decât cea informatică.\r\n\r\nTextul pune în lumină particularităţi de natură tehnică, socială, etică şi financiară ale proiectului DEX online. Dintre acestea, voi insista pe latura etică şi socială a proiectului, pentru că de acolo au venit mai multe provocări şi realizări decât din domeniile tehnic şi financiar. Documentul se lansează adesea în judecăţi de natură morală, cu riscul de a plictisi. Sunt de părere că administratorul unui proiect cu oarecare utilitate practică nu poate rămâne amoral, ci trebuie să ia nişte decizii.\r\n\r\nNu recomand nimănui să facă lucrurile exact aşa cum le-am făcut noi. DEX online ar putea fi mai prezentabil. Sau ar putea oferi un corector ortografic pentru Word. Sau ar putea costa 5€/lună pentru accesul nelimitat la definiţii. Sau şi-ar putea răsplăti colaboratorii cu 10 centi pentru fiecare definiţie trimisă. Sau ar putea include un dicţionar urban. Acestea toate sunt hotărâri pe care le ia coordonatorul unui proiect în funcţie de timpul disponibil şi de scopurile echipei sale.\r\n\r\n\r\n*Auto organizarea proiectului*\r\n\r\nDEX online nu are manageri, nu are avocaţi, nu are contabili, nu are şedinţe, nu are ore fixe. Într-un cuvânt, DEX online nu are o ierarhie. DEX online are un website şi o listă de discuţii pentru voluntari, plus alte câteva unelte secundare (un sistem de gestiune a bug-urilor, un sistem de gestiune a emailurilor de la utilizatori, o pagină wiki practic nefolosită). Oamenii sunt cei mai productivi atunci când le oferi o listă de lucruri pe care le pot face în folosul proiectului şi îi laşi să facă ce le place cel mai mult. Ca urmare, avem unele definiţii care stau necorectate de luni de zile, deşi între timp am corectat mii de alte definiţii. Mie, ca programator, îmi revine sarcina de a crea o interfaţă în care voluntarii să poată lucra eficient. De aceea, îmi petrec mai mult timp lucrând la pagina moderatorului (invizibilă publicului larg) decât la paginile publice.\r\n\r\nEste surprinzător ce oameni de calitate poţi aduna dacă menţii o listă de email activă timp de 7 ani. Ei rezolvă multe din problemele care pe mine mă depăşesc. De fapt, am încetat să mă mai consider „conducătorul” proiectului după primele 6 luni; prefer titlul istoric de „fondator” sau pe cel de „coordonator”. De exemplu, primim zilnic emailuri cu întrebări de natură lingvistică la care eu nu aş şti să răspund. Sau ne-am izbit de fineţuri legale. Sau a trebuit să creez o schemă MySQL pentru nişte date pe care nu le înţelegeam la nivel conceptual. Din fericire, pe lista noastră de discuţii există lingvişti, avocaţi şi programatori care ne-au scos întotdeauna din impas. Cu timpul, separarea funcţiilor s-a produs de la sine. De exemplu, sistemul de email are o coadă de mesaje destinate mie, cu cerinţe la care numai eu pot răspunde. La restul mesajelor aproape nu mă mai uit, pentru că alţi voluntari şi-au însuşit această parte a sistemului şi se ocupă impecabil de ea.\r\n\r\nDEX online nu a avut niciodată ambiţii pe termen lung sau OKR-uri _(obiective şi rezultate cheie)_. Sună un pic paradoxal, dar poţi avea nişte idei generale despre ce ar trebui făcut, fără să faci din asta o obligaţie. Poţi să te aştepţi să atingi obiectivul X la momenul T fără să promiţi că vei îndeplini obiectivul Y, care depinde de X, la momentul T + 1. De exemplu, am început prin a culege definiţii din DEX. Bazându-ne pe progresul zilnic, am estimat că va dura cam 5 ani să culegem tot DEX-ul (până la urmă a durat doar 3). Dar nu ne-am gândit la modul serios cu ce ne vom ocupa timpul după aceea sau ce vom face cu baza de date odată ce va fi completă. Nu mi-a plăcut niciodată acest gen de presiune, am preferat să nu le-o induc voluntarilor, şi nu se poate spune că am bătut pasul pe loc din cauza asta. Nici unui voluntar nu i s-a părut inacceptabil că am muncit trei ani pentru a culege un dicţionar, nici nu ne-am trezit în vreo dimineaţă sâcâiţi de gândul că trebuie să mai introducem 50 de definiţii şi poate n-avem chef.\r\n\r\nUn aspect care poate dezamăgi, dar aşa s-a întâmplat, a fost începutul întâmplător al proiectului. Nu am stat zile în şir să mă gândesc „la ce-aş putea eu munci care să aibă un impact seminificativ pe internetul românesc?”. Abia după ce lucrasem la el vreun an am conştientizat că DEX online ar putea ajunge un site de referinţă. Ideea proiectului mi-a venit în 2001, când eram student în Boston şi foloseam zilnic dicţionare explicative englezeşti online pentru a-mi scrie temele. Pe de altă parte, duceam lipsa unui dicţionar explicativ românesc. Odată am avut o dispută cu un prieten asupra pluralului lui „cratiţă”: el susţinea că este „cratiţe”, iar eu „crătiţi”. Răspunsul, care i-a dat dreptate, a trebuit să aştepte câteva luni până am mers în vacanţă în România. De acolo am venit înapoi cu un DEX, dar m-am gândit că ar fi frumos să existe o variantă pe internet, de pe urma căreia să profite toată lumea, nu doar eu. Dar, având în vedere că după 6 luni de existenţă DEX online cuprindea vreo 50 de definiţii, din care vreo 45 introduse de mine, nu l-am luat foarte în serios. Ulterior, Federaţia Română de Scrabble (F.R.Sc.) a descoperit site-ul şi a început să contribuie masiv cu definiţii. Probabil acolo a fost punctul critic al proiectului şi, privind înapoi, mi se pare că s-a întâmplat un lucru nemaipomenit de improbabil ca 10 oameni să-şi pună încrederea într-un proiect cvasianonim, care ar fi putut merge prost din nenumărate motive. Concluzia acestui paragraf este că inspiraţia vine de unde nu te aştepţi.\r\n\r\n\r\n*Finanţe*\r\n\r\nDEX online nu vehiculează nici un fel de sume băneşti. Am evitat ca proiectul să aducă orice fel de venituri, din motive multiple.\r\n\r\n# Banii aduc discordie. Singurul caz în care poate aş accepta să caut profit de pe urma siteului ar fi dacă toţi colaboratorii proiectului ne-am umple de bani, ceea ce o judecată la rece arată că nu e cazul. Veniturile ar fi imposibil de repartizat echitabil, deoarece natura muncii depusă de fiecare voluntar este diferită şi deci greu de cuantificat. Unii răspund la emailuri, alţii introduc sau corectează definiţii, alţii scriu cod, alţii lucrează la generarea flexiunilor.\r\n# Veniturile vin din reclamă, iar reclama strică un site. Îl strică mai mult (dacă este o reclamă cu „daţi click pe maimuţă”) sau mai puţin (dacă este Google AdSense), dar îl strică, pentru că prin natura ei reclama are scopul de a distrage utilizatorul de la conţinutul paginii.\r\n# O altă sursă de venituri ar fi limitarea accesului gratuit şi introducerea de costuri pentru accesul complet la baza de date, care nu intră în discuţie, deoarece nu se potriveşte filozofiei noastre.\r\n# Veniturile trebuie contorizate, raportate la Fisc, impozitate, ceea ce duce la nevoia înregistrării unei firme, la angajarea unui contabil şi alte probleme cu care preferăm să nu ne dăm bătăi de cap.\r\n# Odată ce un serviciu generează venituri, apare automat nevoia de mai multe venituri în flux continuu pentru a acoperi nişte cheltuieli periodice (tot ceea ce înseamnă cheltuielile unei firme). Ori, DEX online a ajuns acolo unde este tocmai pentru că nu l-am împins în nici un fel de la spate şi nu l-am tratat ca pe un serviciu, ceva de care trebuie să te ocupi în fiecare zi la oră fixă.\r\n\r\nDEX online nu are nici cheltuieli seminificative. Am obţinut tot ce ne-a trebuit de la oameni şi firme care au apreciat calitatea proiectului: găzduirea, unele dintre dicţionare, fonduri pentru cumpărarea unui software de OCR. Cea mai mare donaţie însă este timpul liber al fiecăruia dintre participanţi.\r\n\r\n\r\n*Free as in freedom*\r\n\r\nÎn prezent, baza de date şi codul DEX online sunt disponibile sub licenţa GPL, dar am trecut prin diferite stadii până a ajunge aici.\r\n\r\nPână în 2004, când DEX online conţinea cam 30.000 de definiţii, nici nu ne-am pus problema unei licenţe, mai ales că încă nu ştiam cu ce ochi priveşte Academia Română proiectul DEX online. Intenţia mea era în continuare să aştept până la reglementarea situaţiei cu Academia şi, eventual, DEX online să intre sub tutela acestui for.\r\n\r\nTotuşi, în timp ce Academia nu manifesta nici un interes pentru DEX online, restul internetului românesc începuse să ne remarce. Apăruseră multe concepţii greşite şi critici la adresa DEX online, iar noi, ocupaţi cu introducerea datelor, neglijasem să ne expunem clar principiile într-un document. În paralel, interesul pentru baza de date era în creştere şi fusesem de mai multe ori vizitaţi de crawlere web a căror intenţie părea să fie să transfere toate definiţiile (comportamentul era evident diferit de al unui motor de căutare general). De asemenea, se punea problema dacă definiţiile preluate din DEX reprezintă un furt intelectual sau nu.\r\n\r\nÎn acest context, am petrecut câteva zile schimbând emailuri cu ceilalţi membri ai proiectului şi, în final, am pus licenţa GFDL (GNU Free Documentation Licence) pe baza de date. Ulterior, am înlocuit GFDL cu GPL (General Public License), care se aplică la fel de bine scopurilor noastre şi evită nişte neajunsuri ale GFDL (în privinţa traducerilor şi a incompatibilităţii cu unele distribuţii de Linux). Licenţierea bazei de date a rezolvat multe probleme de natură etică, dar şi tehnică:\r\n\r\n* Am demonstrat că scopul primar al DEX online este să-i ajute pe vorbitorii de limbă română, nu să obţină profit material.\r\n* Am preîntâmpinat crearea unei pieţe negre pentru baza de date. Este imposibil să împiedici copierea unei definiţii odată ce o afişezi pe ecran.\r\n* Am permis programatorilor să folosească baza noastră de date pentru diverse aplicaţii interesante, ei având garanţia că nu putem să ne răzgândim mâine şi să le spunem „accesul la baza de date nu mai este liber” (în acest sens, licenţa GPL protejează mai degrabă documentul decât pe autorul său).\r\n* Deşi relaţia noastră cu Academia Română are încă un semn de întrebare, cel puţin am eliminat orice alte părţi din această dispută.\r\n* Din punct de vedere etic, am oferit în mod liber rodul unui proiect care, la rândul lui, s-a folosit din plin de resurse libere şi gratuite (nu doar software, dar şi munca voluntarilor, găzduirea, lista modelelor de flexiune, dicţionarele de la firma Siveco sau -- de ce nu -- educaţia mea, pentru care n-am cheltuit niciodată vreun ban).\r\n\r\n\r\n*Proiecte externe bazate pe DEX online*\r\n\r\nCa dovadă că decizia de a redistribui liber baza de date a fost bună, iată ce unelte externe folosesc baza de date a DEX online (numai cele despre care am aflat noi):\r\n\r\n* Clienţi pentru consultarea offline a bazei de definiţii (vezi secţiunea de unelte)\r\n* Dicţionar pentru telefoanele mobile: http://www.jarcraft.com/page.php?9\r\n* Corector ortografic pentru OpenOffice, Firefox şi Thunderbird: http://www.archeus.ro/lingvistica/CorectorOrtografic\r\n* Dicţionar de rime: http://stefann22.lx.ro/\r\n* Client de Google Talk: http://www.archeus.ro/lingvistica/CautareGTalk\r\n* Spânzurătoarea: http://www.roportal.ro/jocuri/joaca-online/54.htm\r\n\r\n\r\n*Momente semnificative*\r\n\r\nNefiind împovărat de griji financiare sau de obiective pe termen lung, DEX online a avut o existenţă destul de liniştită. Din acest punct de vedere, mă bucur că DEX online a rămas în stadiul de proiect făcut în timpul liber. Au existat totuşi câteva momente când viitorul proiectului a fost foarte nesigur sau, dimpotrivă, când proiectul a avansat în salturi foarte mari.\r\n\r\nÎn primul rând, după cum am arătat, începutul a fost greoi. Mulţi factori făceau proiectul să arate cam neviabil. Cuprindea cu totul cam 50 de definiţii. Nu era disponibil tot timpul, deoarece era găzduit pe calculatorul meu din cămin, pe care îl mai şi rebootam uneori în Windows ca să mă joc câte ceva. Iar aspectul grafic era de-a dreptul îngrozitor: în primii 2 ani, DEX oline nu a folosit nici un fel de CSS, pentru că nu ştiam ce este acela. Mai exact, când am început proiectul DEX online, ştiam doar în mare ce este aceea o „pagină dinamică”: un program care e de presupus să producă ieşire HTML, care este servită clientului. Restul (HTML, formulare HTML, MySQL, Perl / PHP) le-am învăţat din mers. DEX online avea un fundal violet, fonturi negre şi tabele cu chenare groase. În diverse browsere, diverse caractere Unicode apăreau mai mari, mai mici, mai groase decât caracterele ASCII sau erau înlocuite de pătrăţele. Probabil că dacă aş vedea astăzi o iniţiativă asemănătoare, aş cataloga-o drept neserioasă. Este admirabil că primii noştri voluntari au reuşit să vadă dincolo de prezentare şi să se axeze pe conţinut.\r\n\r\nDe un alt impas ne-am izbit în 2004, când am reuşit să luăm legătura cu editura care a publicat DEX ediţiile 1996 şi 1998 (motivul pentru care nu le-am scris mai devreme a fost că aveau un website făcut complet în Flash, neindexat, la vremea aceea, de nici un motor de căutare; nu aveau nici legături către site, deci nu i-am putut găsi). Prima reacţie a editurii când le-am prezentat proiectul a fost „trebuie să închideţi siteul acum, altfel veţi suporta consecinţele legale”. Ca urmare, prima măsură pe care am luat-o a fost să aplicăm licenţa GFDL pe date, pentru ca în cazul în care ar fi trebuit să închidem siteul, datele să aibă o şansă să se răspândească. Ulterior, am ajuns la concluzia că ediţiile 1996 şi 1998 ale DEX sunt 99% identice cu ediţiile 1984 şi chiar 1975, care, fiind publicate în perioada comunistă, nu conţineau nici un fel de informaţii de copyright. Editura nu şi-a dat nici până astăzi acordul expres pentru DEX online, dar nici nu ne-a mai pus beţe în roate şi îi suntem recunoscători pentru aceasta.\r\n\r\nÎn septembrie 2004, DEX online a sărit brusc de la 65.000 de definţii la vreo 240,000. Firma Siveco, care deţine drepturile de copiere asupra mai multor dicţionare (de sinonime, de antonime etc.) ne-a acordat permisiunea de a le republica sub licenţa GFDL. Câştigul a fost substanţial, dar ne-a dat şi foarte mult de lucru în lunile următoare. Am muncit mult la scripturile care au importat aceste definiţii, dar chiar şi aşa datele au fost importate cu destule erori, care au trebuit depistate şi corectate manual. Paradoxal, mulţi dintre oamenii cu pregătire lingvistică din jurul DEX online consideră aceste dicţionare ca fiind slabe calitativ (nu neapărat prin definiţii incorecte, cât prin definiţii inconsistente, neînchiderea tranzitivă a setului de sinonime şi alte motive). Totuşi, la acel moment erau cele mai bune date pe care le aveam la dispoziţie. E drept că pentru 1% din căutări rezultatele sunt nemulţumitoare, dar eu consider că acesta este un procentaj foarte bun.\r\n\r\nUn eveniment interesant s-a petrecut în noiembrie 2006, când a apărut primul dicţionar urban pentru limba română (http://123urban.ro). Băieţii de la 123urban au o misiune foarte coerent definită: de a continua consemnarea limbii române de acolo de unde a lăsat-o Academia. Efortul lor este unul necesar: cel de a documenta termenii din nişa argotică. Apariţia lor ne-a făcut şi pe noi să ne întrebăm care ne sunt, de fapt scopurile şi cât de departe suntem dispuşi să mergem pentru a ne îmbogăţi baza de cuvinte definite. O variantă de colaborare, din punctul nostru de vedere, ar fi fost să includem baza lor de date ca pe o „sursă” separată (cot la cot cu DEX, DOOM şi celelalte). Până la urmă, colaborarea nu s-a materializat şi nu am mai urmărit-o de atunci. Noi nu am fost siguri că moderarea lor şi sistemul lor de votare funcţionează bine. Dacă o persoană propune o sintagmă, dar nimeni nu o coroborează printr-un vot pozitiv, DEX online trebuie să accepte acea sintagmă sau nu? În plus, baza de date a 123urban nu este disponibilă sub o licenţă compatibilă cu GPL, ceea îngreunează colaborarea din punct de vedere tehnic şi principial.\r\n\r\n\r\n*Evoluţia generatorului de flexiuni*\r\n\r\nÎn prezent, DEX online oferă flexiunile majorităţii cuvintelor limbii române. Dar procesul prin care am ajuns la acest stadiu este un exemplu tipic de colaborare într-un proiect deschis. Încep cu un mini-glosar pentru lămurirea termenilor tehnici:\r\n\r\n* *lexem*: unitate lexicală; suport minim al semnificaţiei; pentru toate scopurile practice, este cam totuna cu „cuvânt”.\r\n* *formă flexionară*: formă modificată a unui cuvânt pentru a exprima un raport gramatical (număr, gen, timp etc.). De exemplu, copilul este o formă flexionară a lexemului copil.\r\n* *paradigmă*: totalitatea formelor flexionare ale unui cuvânt.\r\n* *model de flexiune*: paradigmă comună tuturor lexemelor care se flexionează la fel (de exemplu, _a lucra_, _a forma_ şi _a cresta_ au toate acelaşi model de flexiune). Este practic o clasă de echivalenţă.\r\n\r\nÎn 2006 am început să ne gândim serios să adăugăm flexiuni la cuvintele din DEX online. Cel mai complex aspect este reprezentarea diferitelor transformări pe care le suferă un cuvânt. Flexionarea în limba română se face, în general, prin adăugarea unor sufixe, dar aceste sufixe pot fi foarte variate. Ca exemplu, pluralul substantivelor feminine poate fi format cu _-e (case)_, cu _-i (inimi)_, cu _-uri (ierburi)_, cu _-ele (acadele)_, cu _-ale (macarale)_ etc. În plus, Limba română abundă în fenomene morfologice care transformă un sunet într-altul la aplicarea unei flexiuni. Exemple de transformări comune sunt _t → ţ (bărbat → bărbaţi)_ sau _o → oa (uşor → uşoară)_. Unele flexiuni suferă mai multe transformări _(sămânţă → seminţe)_. În plus, dorim să stocăm şi informaţii despre accentul fiecărui lexem şi cum se mută el în timpul flexionării _(a împrumutá → eu împrumút)_, ceea ce duce la o varietate exponenţială de modele de flexiune.\r\n\r\nPrima versiune a generatorului de flexiuni, pe care am implementat-o fără să mă consult cu nimeni (şi rău am făcut), indica în forma de bază a cuvântului fenomenele morfologice care apar la flexionare. De exemplu, pentru _bărbat_ stocam forma de bază _bărbaT_, unde _T_ indică transformarea _t →ţ_. Pentru _băiat_ stocam forma de bază _băiAT_ pentru a indica transformările _a → e_ şi _t → ţ (băieţi)_. Această informaţie referitoare la fiecare cuvânt trebuia cuplată cu nişte meta-cunoştinţe referitoare la partea de vorbire. De exemplu, transformarea _t → ţ_ nu se aplică decât la pluralul substantivelor (forma de singular articulat este tot _bărbatul_, nu _bărbaţul_).\r\n\r\nImplementarea acestui sistem a fost relativ uşoară, dar concepţia a fost greşită. Cineva ar fi trebuit să treacă prin toate cuvintele limbii române şi să indice aceste fenomene morfologice. Volumul de muncă ar fi fost mic comparabil cu tastarea unui dicţionar întreg, dar ar fi fost oricum considerabil. Argumentul care a demolat complet această implementare a fost că ea nu putea reprezenta toate modelele de flexiune. În primul rând, numărul de fenomene morfologice depăşeşte cu mult numărul de litere şi simboluri Unicode convenabile pentru notaţie, iar în al doilea rând, flexionarea bazată pe sufixe este inerent ambiguă. De exemplu, _roditor_ şi _chior_ au acelaşi sufix _-or_, dar se flexionează diferit ( _roditoare_, respectiv _chioară_).\r\n\r\nDe-abia în acest moment am început să caut alte soluţii. Astfel am aflat că lista de forme flexionare exista deja de zeci de ani. Alf Lombard (1902-1996), un lingvist suedez, a prins drag de limba română şi i-a studiat gramatica în amănunt. După care a creat nişte aşa-numite „modele de flexiune”. Adică a împărţit cuvintele limbii române în clase de echivalenţă cu flexionare identică, atâtea câte a putut identifica. Pentru fiecare clasă, a ales un cuvânt-exponent căruia i-a înşirat explicit paradigma. Prin studierea transformărilor exponentului, se poate deduce paradigma altui cuvânt cu acelaşi model de flexiune. De exemplu, _ceapă_ şi _damigeană_ au acelaşi model de flexionare. _Ceapă_ este exponent şi pluralul lui, definit explicit, este _cepe_. Observăm transformările _ea → e_ şi _ă → e_. Prin analogie, pluralul lui _damigeană_ este _damigene_. În final, s-a dovedit că limba română are cam 800 de modele de flexiune (circa 280 pentru verbe, 320 pentru substantive, 120 pentru adjective şi altele). Aceste modele au fost publicate în Dictionnaire morphologique de la langue roumaine, apărut în 1981.\r\n\r\nDe aici datele au fost preluate de F.R.Sc. Ei aveau nevoie de lista flexiunilor pentru a stabili dacă un cuvânt depus în timpul jocului de scrabble este corect. Au adus deci lista de modele de flexiune la zi, conform cu ultimele norme ortografice, şi au etichetat toate cuvintele nou intrate în limbă cu modelul corespunzător. Această listă exista în format digital, dar era menţinută manual, într-un fişier Word. Pentru concursurile de scrabble, arbitrul dispunea de două cărţulii tipărite: una cu cuvintele acceptate, etichetate cu modelul de flexiune, şi una cu modelele de flexiune desfăşurate explicit.\r\n\r\nDEX online a preluat listele de la F.R.Sc., beneficiind aşadar, complet gratuit, de rodul unei munci de zeci de ani. Ulterior, am continuat să etichetăm multe alte lexeme pe care F.R.Sc nu le tratase, deoarece din cele 130,000 de lexeme din DEX online, numai jumătate provin din DEX, restul provenind din alte dicţionare de specific (în special de neologisme şi de arhaisme).\r\n\r\nÎn prezent, lista de flexiuni are foarte multe aplicaţii utile:\r\n\r\n* Pe baza ei am generat un corector ortografic.\r\n* Ea permite căutarea „full-text”, care altfel nu ar putea funcţiona prea bine. În absenţa listei de flexiuni, am putea căuta „carte” prin tot textul definiţiilor, dar căutarea nu ar înapoia definiţiile care conţin textul „cărţi” sau „cărţilor”.\r\n* Ea ne permite să răspundem la un click pe orice cuvânt dintr-o definiţie, trimiţând la definiţia acelui cuvânt. Din nou, fără această listă nu am şti ce să facem când utilizatorul ar da click pe cuvântul „cărţi”, pentru că nu am şti care este forma de bază a cuvântului.\r\n\r\nPentru a ne revanşa faţă de F.R.Sc., am decis să creăm un subsistem al DEX online (numit intern Flex online) în care F.R.Sc. să poată gestiona, mai bine decât într-un fişier Word, lista de cuvinte acceptate. De exemplu, dacă se dovedeşte că două lexeme nu se flexionează chiar identic, sistemul permite spargerea unui model de flexiune în două, modificarea clonei şi reasignarea lexemelor într-unul din cele două modele. Când F.R.Sc. emite o versiune nouă a listei de cuvinte (la fiecare câţiva ani), sistemul Flex online le permite să compare cele două versiuni, ceea ce ajută la eliminarea erorilor.\r\n\r\n\r\n*Ce am învăţat din asta*\r\n\r\nCând cineva vă oferă ajutorul, faceţi-vă luntre şi puntre ca să-i creaţi condiţii de muncă. Colaboratorii nu cresc pe toate drumurile şi trebuie preţuiţi. Dacă cineva vrea să scrie cod pentru proiect, daţi-i acces la repository şi asiguraţi-vă că vă poate trimite patch-uri. Dacă vrea să raporteze bug-uri, asiguraţi-vă că aveţi un sistem gen Bugzilla. Dacă se oferă să vă creeze un skin sau o interfaţă grafică mai bună, asiguraţi-vă că există o separare bună între extragerea datelor şi prezentarea lor (respectiv, folosiţi un template engine). Dacă vă pune la dispoziţie date, luaţi-le. O bună parte din programarea pentru DEX online am petrecut-o scriind scripturi care să importe diverse documente. A fost plicticos, dar a meritat.\r\n\r\nBriciul lui Occam este o regulă foarte bună pentru a delimita munca manuală de scripting. Dacă durează X ore să prelucraţi manual nişte date şi Y ore să scrieţi un script care să le proceseze automat, scriptul merită scris doar dacă X > Y. De nenumărate ori am depistat nişte erori sistematice în definiţiile din DEX, dar le-am corectat manual, una câte una.\r\n\r\nProgramarea este frumoasă, dar reimplementarea a ceva ce există şi funcţionează, doar pentru că nu v-aţi informat şi nu aţi întrebat pe nimeni, este o risipă de talent.\r\n\r\n20% din oameni fac 80% din muncă. Fiecare ţine cont cum vrea de acest fapt. La DEX online am încercat să le creez condiţii şi celorlalţi 80% dintre voluntari, dar recunosc că nu am reuşit întotdeauna. De exemplu, mulţi dintre voluntari, deşi au dorit să ne ajute, nu au învăţat niciodată cum să formateze corect definiţiile (avem un mini-set de notaţii pentru bold, italic, exponenţi ş.a.m.d.). Practic trebuia să trecem prin toată definiţia, să-i adăugăm diacritice şi să o formatăm, ceea ce dura cam la fel de mult ca şi rescrierea ei de la zero. De la un punct încolo am renunţat să îi mai trimit la documentaţie -- le respingeam pur şi simplu definiţiile trimise.\r\n\r\nÎn marea lor majoritate, oamenii sunt buni şi vor să ajute; foarte puţini sunt cei care încearcă să facă rău sistemului. Problema este că oamenii răi sunt mai perseverenţi, iar efectele pot fi foarte grave („dacă amesteci o linguriţă de bălegar într-un butoi de vin, obţii un butoi de bălegar”). Trebuie deci să fiţi pregătiţi să vă petreceţi o bună parte din timp scriind cod care nu creează conţinut util, ci previne vandalismul. Este supărător, dar cu timpul vă veţi obişnui. De exemplu, nici un programator nu se supără că trebuie să implementeze autentificarea cu parole, deşi acel cod este destinat numai să-i blocheze pe cei 1% dintre utilizatori care s-ar gândi să se lege în contul altcuiva.\r\n\r\nOricât de intuitiv de folosit este proiectul vostru, marea majoritate a utilizatorilor nu vor şti să-l folosească sau îi vor folosi numai un subset mic de funcţii. De exemplu, puţină lume dă click pe legătura către conjugări / declinări care apare după rezultatele căutării în DEX online. Trebuie să fiţi pregătiţi să răspundeţi la multe, multe întrebări. Este bine să aveţi un sistem semiautomat de gestionare a emailurilor, unde să puteţi crea şabloane, pentru că multe din întrebări vor necesita răspunsuri identice. DEX online foloseşte OTRS, dar există multe alte soluţii.\r\n\r\nFaceţi-vă cât mai dispensabili. Cu cât proiectul este mai descentralizat, cu atât va evolua mai uşor. Să nu ajungeţi niciodată la stadiul în care nu vă puteţi lua o vacanţă că se duce totul de râpă. În general, dacă alţi membri ai proiectului au mai multă energie ca voi, aveţi datoria morală să configuraţi sistemul astfel încât să nu-i ţineţi în loc. La DEX online, unica componentă de care mă ocup singur este scrierea codului. Corectarea definiţiilor şi a lexemelor şi răspunsul la emailuri merg foarte bine (sau chiar mai bine) în lipsa mea.\r\n\r\nUn proiect util nu este neapărat dificil din punct de vedere tehnic. DEX online este exemplul perfect în acest sens. Sunt puţine locuri în cod unde am avut nevoie să implementez un algoritm „deştept”. Poate un exemplu ar fi diff-ul între două versiuni ale unei definiţii, pe care până la urmă nici nu îl folosim la nimic în practică. Un alt lucru la care ne-am gândit destul de mult înainte de a-l implementa este schema bazei de date care stochează modelele de flexiune. În rest însă, DEX online excelează prin răbdare, prin volumul de date adunate şi prin calitatea voluntarilor implicaţi, dar mai puţin prin algoritmii şi structurile de date folosite.\r\n\r\nConcluzia este că sunt oameni care vorbesc şi sunt oameni care fac. DEX online nu a fost creat în cel mai eficient mod posibil (am tastat de mână o mulţime de definiţii); nu excelează la nivel tehnic (baza de date conţine, în esenţă, nişte cuvinte asociate cu nişte definiţii şi cu nişte forme flexionare); a fost adesea luat în râs şi criticat, mai ales în primii 3 ani de existenţă; are şi acum suficiente greşeli de tipar; şi, fiind vorba de un instrument lingvistic, nu va fi niciodată complet. Dar, în ritmul nostru şi cu neajunsurile noastre, o mână de oameni cu multă răbdare am reuşit să producem un document remarcabil.',58,'protected',NULL,NULL),('problema/datorii','Datorii','2006-11-11 11:23:34','2007-11-08 20:44:59','==Include(page=\"template/taskheader\" task_id=\"datorii\")==\r\n\r\nTatal si mama lui Gigel se ocupa cu vanzarea de sisteme de calcul. Afacerea s-a dovedit a fi foarte profitabila datorita unui sistem incredibil de creditare a clientilor: un client care cumpara un calculator in ziua $X$ (in acest moment au trecut $N$ zile de la infiintarea magazinului, zilele se numeroteaza de la 1 la $N$, {$0<X&le;N$}) poate returna banii oricand doreste acesta, neexistand o limita de timp impusa. Astfel, aproape in fiecare zi, la magazinul familiei se prezinta diversi clienti care achita integral sau partial un sistem de calcul cumparat in zilele anterioare. Deoarece vor sa inceapa o noua afacere, Mama si Tata doresc sa il insarcineze pe Gigel cu administrarea magazinului de calculatoare. Pentru aceasta Gigel trebuie sa indeplineasca o conditie esentiala: in orice moment al sederii lui la magazin el poate fi solicitat prin telefon de catre tatal sa raspunda cat mai repede la urmatoarea familie de intrebari: ce suma de bani a ramas inca neachitata luand in considerare achizitiile facute de clienti in zilele $P$, $P+1$, {$P+2$}... {$Q-1$}, {$Q$} ({$0<P&le;Q&le;N$}). Se stie ca niciodata nu s-au cumparat doua calculatoare in aceeasi zi. Ajuta-l pe Gigel sa demonstreze parintilor ca poate administra magazinul.\r\n\r\nh2. Cerinta\r\n\r\nSe dau: $N$, $M$, un sir de numere {$A{~1~}$}, {$A{~2~}$}... {$A{~N~}$} si $M$ operatii. {$A{~i~}$} ({$1&le;A{~i~}&le;1000$}, {$1&le;i&le;N$}) reprezinta suma de bani inca neachitata pentru o comanda efectuata in ziua $i$. O operatie poate fi de doua feluri:\r\n\r\n* $A$ (achitare - se scade o valoare din suma restanta a unei zile anume)\r\n* $B$ (interogare - se cere suma tuturor sumelor restante ale unui interval de zile). Programul trebuie sa scrie in fisierul de iesire suma ceruta de fiecare operatie de tip $B$ in momentul interogarii.\r\n\r\nh2. Date de intrare\r\n\r\nFisierul $datorii.in$ va contine pe prima linie numerele $N$ si $M$. Pe urmatoarea linie se afla valorile sirului {$A{~1~}$}, {$A{~2~}$}... {$A{~N~}$} separate prin cate un spatiu. Urmatoarele $M$ linii descriu operatiile (achitari sau interogari) efectuate in ordinea data. Fiecare linie care descrie o operatie incepe cu un cod binar (un numar intreg cu valoarea 0 sau 1) si continua cu 2 numere intregi.\r\n\r\n* Un cod 0 urmat de doua numere intregi $T$, $V$ ({$1&le;T&le;N$}, {$1&le;V&le;1000$}) reprezinta o operatie de tip $A$ (in momentul respectiv s-a achitat o valoare $V$ din suma restanta a zilei $T$)\r\n* Un cod 1 urmat de doua numere intregi $P$, $Q$ ({$1&le;P&le;Q&le;N$}) o operatie de tip $B$ (se cere suma tuturor sumelor restante din zilele $P$, {$P+1$}, {$P+2$}... $Q$ in momentul respectiv).\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul $datorii.out$ se vor scrie pe cate o linie sumele cerute de fiecare operatie de tip $B$ (sumele se cer in ordinea aparitiei operatiilor in fisierul de intrare).\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 15 000$\r\n* {$0 < M &le; 100 000$}\r\n* In orice moment, {$A{~i~}$} ({$1&le;i&le;N$}) este nenegativ.\r\n\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. datorii.in|_. datorii.out|\r\n|6 6\r\n1 3 2 0 0 10\r\n1 3 6\r\n1 1 4\r\n0 3 1\r\n1 1 6\r\n0 6 2\r\n1 1 6\r\n|12\r\n6\r\n15\r\n13|\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"datorii\")==\n\n==SmfTopic(topic_id=\"34\")==\n',1,'task: datorii',NULL,NULL),('problema/petrica','Petrica','2006-11-11 11:23:34','2007-11-08 20:44:59','==Include(page=\"template/taskheader\" task_id=\"petrica\")==\r\n\r\n\r\nPetrica este presedintele unei tari cu $N$ orase conectate prin strazi bidirectionale astfel incat exista un drum unic intre oricare doua dintre ele. Aceste orase sunt numerotate de la $1$ la $N$ astfel incat nu exista doua orase cu acelasi numar. Petrica vrea sa le imparta in patru districte blocand exact trei strazi. De asemenea vrea ca populatia oraselor sa fie distribuita cat mai uniform: diferenta dintre numarul de locuitori din distructul cu cea mai mare populatie si numarul de locuitori din districtul cu cea mai mica populatie sa fie cat mai mica. Aflati pentru presedintele Petrica aceasta diferenta.\r\n\r\nh2. Data de intrare\r\n\r\nPrima linie a fisierului $petrica.in$ va contine numarul $N$ reprezentand numarul de orase. A doua linie contine populatia fiecarui oras ({$N$} valori intregi). Urmatoarele linii contin cate doi intregi $A$ si $B$ cu semnificatia: exista o strada intre orasele $A$ si $B$.\r\n\r\nh2. Data de iesire\r\n\r\nPe prima linie a fisierului $petrica.out$ se va afla un numar natural reprezentand diferenta minima pe care vrea sa o afle Petrica.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $4 &le; N &le; 200$\r\n* Populatia fiecarui oras este un numar intreg din intervalul $[1, 10000]$\r\n* Populatia unui district se calculeaza ca suma populatiei oraselor din districtul respectiv\r\n* Doua orase sunt in acelasi district daca se poate ajunge de la unul la altul mergand pe strazi care nu au fost blocate\r\n* Pentru $50%$ din teste $N &le; 70$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. petrica.in |_. petrica.out |\r\n| 4\r\n2 1 1 1\r\n1 2\r\n1 3\r\n1 4\r\n| 1 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"petrica\")==\n\n==SmfTopic(topic_id=\"40\")==\n',1,'task: petrica',NULL,NULL),('problema/pavare','Pavare','2006-11-11 11:23:35','2007-11-08 20:44:59','==Include(page=\"template/taskheader\" task_id=\"pavare\")==\r\n\r\nGigel, primar in orasul sau, s-a gandit sa renoveze strada principala, strada de dimensiuni $M*N$ compusa din bucati de dimensiuni $1*1$. Majoritatea bucatilor sunt stricate, dar mai exista $K$ bucati care sunt considerate bune. Dorind sa plateasca cat mai putini bani, Gigel a luat de la un negustor blocuri de dimensiuni $2*2$ la pretul unui bloc de dimensiuni $1*1$. Pentru a pava strada trebuie sa amplaseze cat mai multe din aceste blocuri pe bucati stricate, fara sa paveze vreo bucata buna deoarece ar aparea denivelari, si fara sa se suprapuna blocurile $2*2$. El si-a dat seama ca mai bine ar fi cumparat blocuri $1*1$, pentru ca ar fi acoperit toata strada fara batai de cap, dar acum nu mai are de ales si are nevoie de ajutorul tau!\r\n\r\nh2. Cerinta\r\n\r\nDeterminati numarul maxim de blocuri $2*2$ pe care le poate pune primarul pentru a repara strada.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie din fisierul $pavare.in$ se vor afla trei numere intregi separate prin cate un spatiu: $N, M$ si $K$. Pe urmatoarele $K$ linii se vor afla perechi de numere intregi reprezentand linia si coloana pe care se afla o bucata buna.\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie in fisierul $pavare.out$ se va afla un numar natural reprezentand numarul maxim de blocuri $2*2$ care pot fi amplasate pe strada.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 150$\r\n* $1 &le; M &le; 15$\r\n* $1 &le; K &le; N*M$\r\n* Liinile sunt numerotate de la $1$ la $N$, iar coloanele de la $1$ la $M$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. pavare.in |_. pavare.out |\r\n| 4 6 3\r\n1 1\r\n2 6\r\n3 3 | 4 | \r\n\r\nh3. Explicatie\r\n\r\nAcesta este un amplasament posibil al blocurilor:\r\n!problema/pavare?untitled.gif! \r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"pavare\")==\n\n==SmfTopic(topic_id=\"46\")==\n',1,'task: pavare',NULL,NULL),('problema/secv2','Secventa 2','2006-11-11 11:23:35','2007-11-08 20:44:59','==Include(page=\"template/taskheader\" task_id=\"secv2\")==\r\n\r\n==Include(page=\"template/badtests\")==\r\n\r\nGigel s-a decis sa devina olimpic la informatica, poate asa va reusi sa-si rezolve singur problemele, si nu va mai cere ajutorul vostru! La ora de informatica, profesoara lui i-a dat sa rezolve problema secventei de suma maxima: \"Gigele, eu iti dau un sir de $N$ numere intregi, iar tu trebuie sa gasesti o secventa (adica un subsir de numere care apar pe pozitii consecutive in sirul initial) cu suma elementelor maxima!\". Dupa vreo 30 de minute, Gigel s-a ridicat mandru si a zis: \"Am gasit algoritmul de complexitate optima, doamna profesoara!\"\r\nCa tema pentru acasa Gigel are de rezolvat aproape aceeasi problema: trebuie sa gaseasca secventa de suma maxima de lungime cel putin $K$!\r\n\r\nh2. Cerinta\r\n\r\nGigel inca nu stie destul de multa informatica ca sa poata rezolva aceasta problema, dar poate il ajutati voi! Scrieti un program care rezolva problema din tema lui Gigel.\r\n\r\nh2. Date de intrare\r\n\r\nFisierul de intrare $secv2.in$ contine pe prima linie numerele $N$ si $K$, separate prin spatiu. Pe cea de a doua linie se afla elementele sirului separate prin cate un spatiu.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $secv2.out$ trebuie sa contina o singura linie cu trei numere: pozitia de inceput si de sfarsit a secventei de suma maxima de lungime cel putin $K$ si suma secventei.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; K &le; N &le; 50.000$\r\n* Elementele din vector sunt numere intregi din intervalul $[-25.000, 25.000]$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. secv2.in |_. secv2.out |\r\n| 8 3\r\n0 -6 2 1 4 -1 3 -5 |  3 7 9 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"secv2\")==\n\n==SmfTopic(topic_id=\"89\")==\n',1,'task: secv2',NULL,NULL),('problema/bool','Bool','2006-11-11 11:23:36','2007-11-08 20:45:00','==Include(page=\"template/taskheader\" task_id=\"bool\")==\r\n\r\nHaralambie a primit la scoala o tema destul de dificila. El trebuie sa evalueze o expresie logica. Aceasta expresie contine variabile (litere mari ale alfabetului englez de la $A$ la $Z$), constante ({$TRUE$} si {$FALSE$}), paranteze rotunde {$($} si {$)$}, si operatorii logici $NOT$, $AND$ si $OR$. $NOT$ are prioritatea cea mai mare, $OR$ are prioritatea cea mai mica. Initial toate variabilele au valoarea $FALSE$. Lui Haralambie ii place sa evalueze expresii, dar variabilele isi mai schimba uneori valoarea si expresia trebuie reevaluata. Speriat din aceasta cauza, a decis sa apeleze la ajutorul vostru!\r\n\r\nDupa cum este mentionat mai sus o expresie logica este definita in unul din modurile urmatoare:\r\n\r\ntable. |_. expresie |_. explicatie |\r\n| $TRUE$ | $&nbsp;$ |\r\n| $FALSE$ | $&nbsp;$ |\r\n| $c$     |  $c - litera mare a alfabetului englez$ |\r\n| $(e)$   |  $e - expresie logica$ |\r\n| $NOT e$ |  $e - expresie logica$ |\r\n| $e1 AND e2$ | $e1 si e2 - expresii logice$ |\r\n| $e1 OR e2$ | $e1 si e2 - expresii logice$ |\r\n\r\nh2. Cerinta\r\n\r\nSe da expresia ce trebuie evaluata si modificarile ce apar la valorile variabilelor. Pentru fiecare modificare de variabila trebuie reevaluata expresia si afisat rezultatul ({$1$} pentru adevarat si $0$ pentru fals).\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $bool.in$ este scrisa expresia logica definita ca mai sus. Pe a doua linie este dat numarul $N$ de modificari ale variabilelor. Pe linia a treia sunt date $N$ caractere intre $A$ si $Z$, reprezentand variabilele a caror valoare este modificata.\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul $bool.out$ va contine o singura linie de lungime $N$. Pentru fiecare modificare de variabila se va afisa un caracter reprezentand valoarea logica a expresiei: $1$ pentru adevarat si $0$ pentru fals.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 100$\r\n* $1 &le; Lungime expresiei &le; 1.000$\r\n* Toate literele care apar in expresie vor fi majuscule\r\n* Nu va exista mai mult de un spatiu intre doua caractere din expresie\r\n* O variabila care are valoarea $TRUE$ isi schimba valoarea in $FALSE$, iar o variabila $FALSE$ se schimba in $TRUE$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. bool.in |_. bool.out |\r\n| A AND ((B OR NOT C) OR ((TRUE)))\r\n4\r\nABCA\r\n| 1110 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"bool\")==\n\n==SmfTopic(topic_id=\"94\")==\n',1,'task: bool',NULL,NULL),('problema/party','Party','2006-11-11 11:23:36','2007-11-08 20:45:00','==Include(page=\"template/taskheader\" task_id=\"party\")==\r\n\r\nGeorge vrea sa isi organizeze majoratul, si vrea ca petrecerea sa fie de neuitat, mancarea, bautura, locatia si sonorizarea sunt deja asigurate, si mai ramane problema chemarii prietenilor. El si cu prietenul lui cel mai bun Lucian au preferinte diferite si pentru a nu se certa au pus la punct o lista de cerinte care vor trebui sa fie indeplinite toate astfel incat cheful sa se desfasoare in cele mai bune conditii! Pentru usurinta, prietenii lui George vor fi indentificati prin numere intregi de la $1$ la $N$ si cerintele vor fi de tipurile $0, 1, 2$ sau $3$.\r\nO cerinta de genul $x y 0$ are semnificatia ca $x$ sau $y$ trebuie sa participe la petrecere ; $x y 1$ are semnificatia ca daca $x$ participa nu exista nici o restrictie pentru $y$, dar daca $x$ nu participa atunci nici $y$ nu participa ; $x y 2$ are semnificatia simetrica cu cerinta $1$ ; iar cerinta $x y 3$ are semnificatia ca cel putin unul dintre $x$ si $y$ nu participa la petrecere. Scrieti un program care sa-i ajute pe cei doi sa determine care persoane vor fi invitate la petrecere ; se garanteaza ca va fi posibila intotdeauna organizarea unei petreceri !\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie se vor afisa numerele $N$ si $M$ care reprezinta numarul de prieteni si numarul de cerinte de indeplinit. Pe urmatoarele $M$ linii vor fi cerinte de forma $x y z$ unde $1<=x,y<=N$ iar $0<=z<=3$.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie va fi un numar $Nr$ ce reprezinta numarul de invitati la petrecere, iar pe urmatoarele $Nr$ linii cate un invitat pe linie.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; N &le; 100$\r\n* $1 &le; M &le; 1.000$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. party.in |_. party.out |\r\n| 4 4            \r\n1 4 3          \r\n2 3 3\r\n1 2 1\r\n2 4 1\r\n|2\r\n 1\r\n3 |\r\n| 3 7          \r\n3 2 1          \r\n3 1 1          \r\n2 1 1          \r\n2 3 1\r\n3 1 1\r\n3 2 1\r\n2 3 2\r\n| 3\r\n1\r\n2\r\n3 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"party\")==\n\n==SmfTopic(topic_id=\"96\")==\n',1,'task: party',NULL,NULL),('problema/pascal','Pascal','2006-11-11 11:23:37','2007-11-08 20:45:00','==Include(page=\"template/taskheader\" task_id=\"pascal\")==\r\n\r\nIon a invatat la ora de matematica despre triunghiul lui Pascal. Fiecare rand din acest triunghi are primul si ultimul element egal cu $0$. Un element din triunghi se calculeaza ca fiind suma celor $2$ elemente exact deasupra acestuia. Randurile sunt numerotate de la $0$, deci, spre exemplu, randul $2$ contine: $1 2 1$. Este un fapt binecunoscut ca valoarea elementului $j$ (cu indexarea elementelor de la $0$) de pe linia $i$ se poate calcula si cu ajutorul formulei: $i!/((i-j)!*j!$) . (Prin $i!$ se intelege produsul $1*2*...*i$).\r\n\r\nh2. Cerinta\r\n\r\nAjutati-l pe Ion sa calculeze cate numere de pe randul $R$ sunt divizibile la $D$.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare $pascal.in$ se gasesc numerele $R$ si $D$.\r\n\r\nh2. Date de iesire\r\n\r\nPe prima linie a fisierului de iesire $pascal.out$ se va gasi numarul cerut.\r\n\r\nh2. Restrictii\r\n\r\n* $0 &le; R &le; 5.000.000$\r\n* $2 &le; D &le; 6$\r\n* Observatie: $0 != 1$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. pascal.in |_. pascal.out |\r\n| 4 2\r\n| 3 |\r\n\r\nh3. Explicatii \r\n\r\n!problema/pascal?pascal.gif! \r\n\r\nRandul $4$ contine elementele :\r\n$1 4 6 4 1$\r\ndintre care $4$, $6$ si $4$ sunt divizible la $2$ \r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"pascal\")==\n\n==SmfTopic(topic_id=\"241\")==\n',1,'task: pascal',NULL,NULL),('problema/critice','Critice','2006-11-11 11:23:38','2007-11-08 20:45:00','==Include(page=\"template/taskheader\" task_id=\"critice\")==\r\n\r\nAlgorel are in pivnita o retea subterana prin care misuna sobolani. Reteau consta din $N$ adaposturi numerotate de la $1$ la $N$ si $M$ tunele intre acestea. Adaposturile $1$ si $N$ comunica cu suprafata fiind singurele locuri din retea cu aceasta propietate (nici un alt adapost sau tunel nu mai are iesire la suprafata). Algorel vrea sa trimita un numar maxim de pisici in retea. Pisicile intra prin adapostul $1$ si ies prin adapostul $N$. Nici o pisica nu poate ramane in retea. Pentru fiecare tunel se stie rezistenta lui, adica numarul maxim de pisici care pot trece prin el fara ca sa se darame. Daca printr-un tunel cu rezistenta nenula a trecut o pisica atunci rezistenta acestuia scade cu o unitate. Algorel a observat ca exista anumite tunele care au propietatea ca daca rezistenta lor creste in timp ce rezistenta celorlalte tunele ramane la fel atunci va creste si numarul maxim de pisici pe care le poate trimite prin retea. El a denumit tunelele cu aceastra propietate tunele critice.\r\n\r\nh2. Cerinta\r\n\r\nFiind data reteaua din pivnita lui Algorel determinati tunelele critice.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului $critice.in$ se gasesc numerele naturale $N$ si $M$ reprezentand numarul de adaposturi si numarul de tunele din reteaua subterana. Urmeaza $M$ linii continand trei numere naturale separate prin spatii, $A B C$, cu semnificatia: intre adaposturile $A$ si $B$ ({$A != B$}) exista un tunel cu rezistenta $C$.\r\n\r\nh2. Date de Iesire\r\n\r\nPrima linie a fisierului de iesire $critice.out$ contine un numar natural $K$ reprezentand numarul de tunele critice din reteaua lui Algorel. Urmatoarele $K$ linii contin cate un numar natural reprezentand indicii muchiilor critice. Indicii vor fi sortati crescator. Muchiile sunt numerotate de la $1$ la $M$ dupa ordinea din fisierul de intrare.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; N &le; 1000$\r\n* $1 &le; M &le; 10000$\r\n* Rezistentele sunt numere naturale mai mici sau egale cu $10000$\r\n* Intre oricare doua noduri exista cel mult un tunel\r\n* Orice tunel poate fi parcurs in ambele sensuri\r\n* Petru $50%$ din teste $M <= 1000$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. critice.in |_. critice.out |\r\n| 5 6\r\n2 1 2\r\n2 3 3\r\n3 5 4\r\n1 4 7\r\n4 3 2\r\n4 5 6\r\n| 2\r\n1\r\n4 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"critice\")==\n\n==SmfTopic(topic_id=\"306\")==\n',1,'task: critice',NULL,NULL),('problema/concert','Concert','2006-11-11 11:23:39','2008-03-17 17:38:24','==Include(page=\"template/taskheader\" task_id=\"concert\")==\r\n\r\nUn grup de $N$ artisti a primit invitatii sa cante la un concert. Fiecarui artist i s-a trimis o invitatie pe care acesta era invitat sa cante intre orele $A$ si $B$. Insa organizatorii acestui eveniment au gresit invitatiile si timpurile in care trebuiau sa cante anumiti artisti se suprapuneau. Artistii, fiind renumiti, nu accepta sa cante decat singuri. De asemenea ei cer despagubiri daca li se cere sa inceapa sa cante dupa ora $A+1$ sau sa termine inainte de ora $B$. Un anumit artist poate sa cante doar intre orele $A$ si $B$ de pe invitatie. Unele invitatii pot fi anulate, asa ca unii artisti pot sa nu cante deloc.\r\n\r\nh2. Cerinta\r\n\r\nCunoscandu-se intervalele intre care poate sa cante fiecare artist, profitul pe care il aduce fiecare artist pe unitatea de timp si despagubirile cerut in ambele cazuri mentionate mai sus, voi trebuie sa aflati care este suma maxima care poate fi obtinuta in concertul respectiv, si cum poate fi ea obtinuta.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierul $concert.in$ se va afla $N$. Pe urmatoarele $N$ linii ale fisierulul se vor gasi cate 5 numere separate prin cate un spatiu. Ele reprezinta $A$, $B$, profitul pe unitatea de timp si despagubirile in cazul in care artistul nu incepe sa cante in $A+1$ si respectiv daca nu termina de cantat in $B$.\r\n\r\nh2. Date de Iesire\r\n\r\nPe prima linie a fisierul $concert.out$ se va afla suma maxima care poate fi obtinuta din concert.\r\n\r\nh2. Restrictii\r\n\r\n* $1 &le; N &le; 1.000$\r\n* $1 &le; A{~i~} < B{~i~} &le; 2.000.000.000$\r\n* profitul adus de fiecare artist sau despagubirile cerute de fiecare dintre ei nu vor trece de valoare 500. Despagubirile se platesc o data, nu pe unitate de timp.\r\n* daca artistul $i$ are in contract intervalul $(A{~i~},B{~i~})$ el poate canta intre momentele $A{~i~}+1$ si $B{~i~}$ inclusiv.\r\n* oricare doi artisti au intervalele diferite\r\n* solutia nu va trece de valoare 2^31^-1\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. concert.in |_. concert.out |\r\n| 5 \r\n0 5 10 10 15\r\n3 8 8 8 20\r\n4 10 12 4 10\r\n8 16 7 4 7\r\n12 20 10 5 50 | 189 |\r\n\r\nh3. Explicatie\r\n\r\nArtistul $1$ canta intre orele $1$ si $5$, aducand un profit de $(5-1+1)*10 = 50$ si nu cere despagubiri, pentru ca a cantat intre orele stabilite in invitatie. Artistul $2$ nu canta de loc. Artistul $3$ canta intre orele $6$ si $10$, aducand un profit de $(10-6+1)*12 = 60$, insa i se platesc despagubiri in valoare de $4$, pentru ca nu a inceput la ora la care i s-a spus in invitatie ca va incepe, ora $A+1 = 4$. Astfel artistul $3$ aduce un profit de $60-4 = 56$. Artistul $4$ canta intre orele $11$ si $12$. Aducand un profit de $2*7 = 14$, insa cere ambele despagubiri deci aduca un profit de $14-7-4 = 3$. Artistul cu numarul $5$ aduce un profitde $8*10 = 80$, si nu cere despagubiri, pentru ca a cantat intre orele stabilite. Astfel, totalul se ridica la: $50+56+3+80=189$.\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"concert\")==\r\n\r\n==SmfTopic(topic_id=\"385\")==\r\n',1,'task: concert',NULL,NULL),('problema/perm3','Permutari 3','2006-11-11 11:23:39','2007-11-08 20:45:00','==Include(page=\"template/taskheader\" task_id=\"perm3\")==\r\n\r\nPentru o multime oarecare de numere intregi cu $N$ elemente se poate defini o permutare a acesteia ca fiind o varianta de a aseza elementele multimii. De exemplu pentru multimea $M={4,12,81}$ vom avea permutarile:\r\n\r\n# ${ 4 , 12 , 81 }$\r\n# ${ 4 , 81 , 12 }$\r\n# ${ 12 , 4 , 81 }$\r\n# ${ 12 , 81 , 4 }$\r\n# ${ 81 , 4 , 12 }$\r\n# ${ 81 , 12 , 4 }$\r\n\r\nIn grupul format de toate permutarile unei multimi se poate defini o ordine a acestora astfel incat elementele aflate pe prima pozitie sa fie in ordine crescatoare, elementele de pe a doua pozitie sa fie in ordine crescatoare pentru permutarile care au primul element identic, etc. asa cum se vede in figura. O astfel de ordine se numeste ordine lexicografica. Permutarilor asezate in ordine lexicografica li se pot asocia numere de ordine, in cazul exemplului de mai sus de la $1$ la {$6$}.\r\n\r\nh2. Cerinta\r\n\r\nDandu-se o multime de numere intregi si o permutare a ei concepeti un program care determina numarul de ordine al permutarii in ordine lexicografica\r\n\r\nh2. Date de Intrare\r\n\r\nFisierul de intrare $perm3.in$ contine:\r\n\r\n|_. Valori |_. Semnificatie |\r\n|{$N$} |prima linie: $N$ = numarul de elemente al multimii,  |\r\n|{$m{~1~} m{~2~} m{~3~}$} ... {$m{~N~}$}|a doua linie: elementele multimii, in ordine crescatoare|\r\n|{$p{~1~} p{~2~} p{~3~}$} ... {$p{~N~}$}|a treia linie: elementele permutarii (elementele {$m{~1~} m{~2~} m{~3~}$} ... {$m{~N~}$} dar in alta ordine) |\r\n\r\nh2. Date de Iesire\r\n\r\nFisierul de iesire $perm3.out$ va contine numarul permutarii in ordine lexicografica.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; N &le; 1.000$\r\n* $1 &le; m{~i~} &le; 2.000.000.000$\r\n\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. perm3.in |_. perm3.out |\r\n| 3\r\n1 23 25\r\n23 1 25\r\n| 3 |\r\n| 4\r\n1 2 3 4\r\n3 4 1 2\r\n| 17 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"perm3\")==\n\n==SmfTopic(topic_id=\"386\")==\n',1,'task: perm3',NULL,NULL),('problema/trapeze','Trapeze','2006-11-11 11:23:40','2007-11-08 20:45:00','==Include(page=\"template/taskheader\" task_id=\"trapeze\")==\r\n\r\nDaca te joci cu $N$ obiecte identice de forma rotunda si incerci sa formezi diferite forme cu toate obiectele, apar figuri interesante. Una dintre figurile cele mai frumoase este trapezul. El este format din mai multe linii (cel putin una). Pe prima linie stau $A$ obiecte ({$A &ge; 1$}). Pe urmatoarea linie (daca exista) stau $A+1$ obiecte, si tot asa pana se folosesc toate obiectele. De exemplu, cu $15$ obiecte putem forma $4$ trapeze distincte:\r\n\r\n# {$&nbsp;&nbsp;&nbsp;&nbsp;*$}\r\n{$&nbsp;&nbsp;&nbsp;* *$}\r\n{$&nbsp;&nbsp;* * *$}\r\n{$&nbsp;* * * *$}\r\n{$* * * * *$}\r\n# {$&nbsp;&nbsp;* * * *$}\r\n{$&nbsp;* * * * *$}\r\n{$* * * * * *$}\r\n# {$&nbsp;&nbsp;* * * * * * *$}\r\n{$&nbsp;* * * * * * * *$}\r\n# {$* * * * * * * * * * * * * * *$}\r\n\r\nEste important ca toate piesele sa fie folosite in constructia oricarui trapez si toate liniile sa fie complete. Este foarte usor sa determini pentru un numar dat de obiecte care este numarul total de trapeze distincte ce se pot forma. De exemplu, pentru $15$ obiecte numarul total de trapeze este $4$. Mai greu este sa determini care este numarul minim de obiecte necesare pentru a putea forma in total exact $K$ trapeze distincte.\r\n\r\nh2. Cerinta\r\n\r\nPentru valoarea lui $K$ data, determinati numarul minim de obiecte necesare pentru a forma exact $K$ trapeze.\r\n\r\nh2. Date de intrare\r\n\r\nFisierul de intrare $trapeze.in$ va contine pe prima linie numarul natural $K$.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire $trapeze.out$ va contine o singura linie pe care va fi scris numarul minim de obiecte necesare pentru a forma in total exact $K$ trapeze.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $1 &le; K &le; 100$\r\n\r\nh2. Exemple\r\n\r\ntable(example). |_. trapeze.in |_. trapeze.out |\r\n|4|15|\r\n|5|81|\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"trapeze\")==\n\n==SmfTopic(topic_id=\"420\")==\n',1,'task: trapeze',NULL,NULL),('problema/pal','Pal','2006-11-11 11:23:40','2008-01-31 07:24:00','==Include(page=\"template/taskheader\" task_id=\"pal\")==\r\n\r\nPrintul Algorel este in incurcatura din nou: a fost prins de Spanul cel Negru in incercarea sa de a o salva pe printesa si acum este inchis in Turnul cel Mare. Algorel poate evada daca gaseste combinatia magica cu care poate deschide poarta turnului. Printul stie cum se formeaza aceasta combinatie magica: trebuie sa utilizeze toate cifrele scrise pe usa turnului pentru a obtine doua numere palindroame, astfel incat suma lor sa fie minima, iar aceasta suma este combinatia magica ce va deschide usa. Primul numar palindrom trebuie sa aiba cel putin $L$ cifre, iar cel de-al doilea poate avea orice lungime diferita de $0$. Numerele palindroame formate nu pot incepe cu cifra $0$. Acum interveniti dumneavoastra in poveste, fiind prietenul sau cel mai priceput in algoritmi. Prin noul super-telefon al sau, printul transmite numarul de aparitii a fiecarei cifre de pe usa turnului precum si lungimea minima $L$ a primului numar, iar dumneavoastra trebuie sa-i trimiteti cat mai repede numerele cu care poate obtine combinatia magica.\r\n\r\nh2. Cerinta\r\n\r\nAvand datele necesare, aflati doua numere palindroame cu care se poate obtine combinatia magica.\r\n\r\nh2. Date de Intrare\r\n\r\nPrima linie a fisierului $pal.in$ contine un numar intreg $L$ reprezentand lungimea minima a primului numar. Urmeaza 10 linii: pe linia $i+2$ se va afla un numar intreg reprezentand numarul de aparitii ale cifrei $i$, pentru $i$ cu valori de la $0$ la $9$.\r\n\r\nh2. Date de Iesire\r\n\r\nPrima linie a fisierului de iesire $pal.out$ contine primul numar palidrom, iar cea de-a doua linie contine cel de-al doilea numar palindrom. Daca exista mai multe solutii se va scrie doar una dintre ele.\r\n\r\nh2. Restrictii si precizari\r\n\r\n* In total vor fi cel mult $100$ de cifre\r\n* $1 &le; L < 100$ si $L$ va fi mai mic decat numarul total de cifre\r\n* Pentru datele de test va exista intotdeauna solutie: se vor putea forma din cifrele scrise pe usa turnului doua numere care incep cu o cifra diferita de $0$, iar primul numar sa aiba cel putin $L$ cifre\r\n* Un numar este palindrom daca el coincide cu rasturnatul sau. De exemplu $12321$ si $7007$ sunt numere palindroame, in timp ce $109$ si $35672$ nu sunt.\r\n* Pentru $30%$ dintre teste, numarul total de cifre va fi cel mult $7$; pentru alte $40%$ din teste numarul total de cifre va fi cel mult $18$, iar pentru restul de $30%$ din teste numarul total de cifre va fi mai mare sau egal cu $30$\r\n* Fiecare linie din fisierul de intrare si din fisierul de iesire se termina cu marcaj de sfarsit de linie.\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. pal.in |_. pal.out |\r\n| 5 \r\n  3\r\n  2\r\n  3\r\n  0\r\n  0\r\n  0\r\n  0\r\n  0\r\n  0\r\n  0\r\n| 10001\r\n  222 |\r\n\r\nh3. Explicatii\r\n\r\nPentru acest exemplu avem L = 5, 3 cifre de 0, 2 cifre de 1 si 3 cifre de 2. Cifrele de la 3 la 9 lipsesc de pe usa turnului.\r\nCele doua palindroame cu care se genereaza combinatia magica sunt 10001 si 222. Combinatia magica va fi suma acestora si anume 10223 (care este suma minima pe care o putem obtine).\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"pal\")==\r\n\r\n==SmfTopic(topic_id=\"424\")==\r\n',15,'task: pal',NULL,NULL),('problema/delay','Delay','2006-11-11 11:23:41','2008-04-20 12:19:22','==Include(page=\"template/taskheader\" task_id=\"delay\")==\r\n\r\n==include(page=\"template/badtests\")==\r\n\r\nGigel a cumparat $N$ calculatoare cu care vrea sa deschida un Internet Cafe. Pentru aceasta, el trebuie sa conecteze toate calculatoarele in retea, in asa fel incat oricare doua calculatoare sa poata comunica intre ele, direct sau indirect. Comunicatia dintre calculatoare se realizeaza prin intermediul cablurilor de legatura. Un cablu leaga doua calculatoare, iar transferul de date prin cablu se poate realiza in ambele sensuri. Fiind la inceput si neavand prea multi bani, Gigel a legat calculatoarele intre ele astfel incat intre oricare doua calculatoare exista un singur traseu pe care se pot transmite date.\r\nCurand si-a dat seama ca transferul de date se realizeaza cu viteza foarte mica. Acest lucru se datoreaza faptului ca fiecare pachet de date care trece prin calculatorul $i$ este pus sa astepte un timp {$T{~i~}$}. In aceste conditii, timpul dupa care un pachet de date ajunge de la un calculator la altul este egal cu suma timpilor de asteptare ai fiecarui calculator de pe traseu (inclusiv ai calculatoarelor sursa si destinatie).\r\nDin cand in cand, configuratia anumitor calculatoare este modificata si timpii de asteptare corespunzatori acelor calculatoare se schimba. Cum Gigel are grija foarte mare de calculatoarele sale, el trebuie sa fie mereu informat in legatura cu starea retelei. Mai precis, el trebuie sa poata afla repede care este timpul de transmitere a unui pachet de date intre oricare doua calculatoare din reteaua sa.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care trateaza in mod eficient urmatoarele doua tipuri de operatii:\r\n\r\n* tipul 1: modificarea timpului de asteptare al unui calculator\r\n* tipul 2: determinarea timpului de transmitere a unui pachet de date intre doua calculatoare specificate.\r\n\r\nh2. Date de Intrare\r\n\r\nPe prima linie a fisierului de intrare $delay.in$ se afla numarul $N$ de calculatoare. Pe fiecare dintre urmatoarele $N$ linii se afla cate un numar intreg {$T{~i~}$}, reprezentand timpul initial de asteptare al calculatorului corespunzator. Pe urmatoarele $N-1$ linii se afla cate doua numere intregi $a$ si {$b$}, reprezentand numerele a doua calculatoare legate printr-un cablu direct. Pe urmatoarea linie se afla numarul intreg {$M$}, reprezentand numarul de operatii descrise in continuare. Fiecare dintre urmatoarele $M$ linii contine cate $3$ numere intregi separate prin spatii: {$a b c$}.\r\n\r\n* Daca {$a=1$}, atunci $b$ reprezinta numarul de ordine al unui calculator nou configurat, iar $c$ reprezinta noul timp de asteptare al calculatorului $b$\r\n* Daca {$a=2$}, atunci $b$ si $c$ reprezinta numerele de ordine a doua calculatoare diferite, iar programul va trebui sa afiseze in fisierul de iesire timpul de transmitere a unui pachet de date intre calculatoarele $b$ si $c$\r\n\r\nh2. Date de Iesire\r\n\r\nIn fisierul $delay.out$ veti afisa, pe cate o linie separata, timpii determinati in cazul fiecarei operatii de tipul {$2$}, in ordinea in care sunt intalnite in fisierul de intrare. Atunci cand calculati timpul de transmitere a unui pachet de date intre doua calculatoare, trebuie sa considerati timpii de asteptare de la momentul respectiv (care sunt determinati de valorile initiale sau de operatiile de tipul $1$ descrise in fisierul de intrare inaintea operatiei curente).\r\n\r\nh2. Restrictii si precizari\r\n\r\n* $2 &le; N &le; 16.000$\r\n* $0 &le; T{~i~} &le; 1.000$\r\n* $2 &le; M &le; 200.000$\r\n* Calculatoarele sunt numerotate de la $1$ la $N$\r\n* In fisierul de intrare va exista cel putin o operatie de tipul $2$\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. delay.in |_. delay.out |\r\n| 5\r\n1\r\n2\r\n3\r\n4\r\n5\r\n1 2\r\n1 3\r\n2 4\r\n3 5\r\n6\r\n2 1 4\r\n2 3 1\r\n1 1 100\r\n2 1 4\r\n2 2 4\r\n2 2 3\r\n| 7\r\n4\r\n106\r\n6\r\n105 |\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"delay\")==\r\n\r\n==SmfTopic(topic_id=\"456\")==\r\n',961,'task: delay',NULL,NULL),('utilizator/svalentin','svalentin\'s page','2006-11-24 20:56:19','2008-11-15 17:17:29','h2. infoarena development\r\n\r\n* Buguri, sugestii, etc pe ==smflink(link=\"board\" board=\"33\" caption=\"forum\")==\r\n* contact: valentin - at - infoarena.ro\r\n\r\nh2. Despre mine\r\n\r\n(vmenu)* !utilizator/svalentin?poza.jpg!\r\n\r\n* Anul I la facultatea de Automatica si Calculatoare din cadrul Universitatii Politehnice Bucuresti\r\n\r\n* Cont pe TopCoder - \'svalentin\':http://www.topcoder.com/tc?module=MemberProfile&cr=11931649\r\n* Poze de la diferite evenimente - \'picasaweb\':http://picasaweb.google.com/valentin.stanciu\r\n* Cont pe deviantart - \'svnightblade\':http://svnightblade.deviantart.com (fotografii)\r\n** samples:\r\n*** !utilizator/svalentin?School_Musician_by_svNightBlade.jpg!:http://www.deviantart.com/deviation/28295559/\r\n*** !Panoramic_mountains_by_svNightBlade.jpg!:http://www.deviantart.com/deviation/35987288/\r\n\r\nh2. Distinctii primite\r\n\r\n* premiul I ONI in clasa a 8-a  (2004)\r\n* premiul I ONI in clasa a 10-a (2005)\r\n* Medalie de argint la concursul Tuymaada din Yakutia (2005)\r\n* premiul I ONI in clasa a 11-a (2006)\r\n* membru al lotului national de informatica din 2006\r\n* premiul II ONI clasa a 12-a (2007) --> Felicitari wefgef ;)\r\n* membru al lotului national de informatica din 2007\r\n* more small stuff',75,'protected',NULL,NULL),('probleme-de-acoperire-2','probleme-de-acoperire2','2008-11-15 18:53:30','2008-11-15 19:54:45','h1. Probleme de acoperire 2\r\n\r\n(Categoria _Algoritmi_, autor _Cosmin Negruşeri_)\r\n\r\nSubiectul acestui articol sunt acoperirile cu o abordare bazată pe tehnici de programare.\r\n\r\nh2. Problema 1 (MagicBoxes, TopCoder)\r\n\r\nbq. Să se determine numărul $N$ maxim astfel ca într-un dreptunghi de dimensiuni $L x W (1 <= L , W <= 30)$ să poată fi dispuse paralel cu axele de coordonate $N$ pătrate de laturi $1 .. N$ astfel ca oricare două pătrate să nu aibă porţiuni care se suprapun.\r\n\r\nh3. Soluţie:\r\n\r\n* Această problemă, deşi clasică, este dificil de rezolvat în cazul general si singura abordare a ei este aceea de a folosi metoda $backtracking$. \r\n* Întâi putem stabili o limită superioară a numarului $N$: este evident că $N <= W, N <= L$ şi că $1^2^ + 2^2^ + .. + N^2^ <= L x W$. Putem porni cu $N$ de la limita superioară dată de aceste inegalităţi şi să încercăm să dispunem cele $N$ pătrate în interiorul dreptunghiului. O optimizare simplă care ne-ar fi ajutat să rezolvăm problema, precalculând toate rezultatele, ar fi fost să punem în dreptunghi pătratele în ordinea descrescătoare a înălţimii. Altă observaţie ce reduce timpul de execuţie este că piesa cea mai mare nu trebuie pusă în toate poziţiile posibile ci în un sfert din ele, din cauza soluţiilor simetrice, iar între ea şi margine nu trebuie lăsat spaţiu puţin pentru că acel spaţiu va rămâne nefolosit. Observaţia care ne-ar fi dus la o soluţie care să rezolve un test în două secunde, cât era limita de timp în concurs, este că procedura $backtraking$ pierde mult timp pentru verificarea dacă o piesă poate fi pusă pe o anumită poziţie. Dacă în loc de reprezentarea pe matrice folosim $L$ întregi astfel ca bitul al $j$-lea din întregul $i$ este $1$ dacă celula $(i, j)$ este deja ocupată şi $0$ altfel, vom putea verifica dacă pătratul de latură $i$ poate fi plasat pe o anumită poziţie în $i$ paşi, şi nu în $i^2^$ paşi ca înainte. \r\n* Această reprezentare pe biţi este foarte utilă în probleme de acest gen, şi cum avem întregi de $64$ de biţi pe care îi putem folosi, avem o metodă foarte simplă de reprezentare a tablelor de mărime până la $64$.\r\n\r\nh2. Problema 2 (IOI 2001 Pavement, problemă de rezervă [1])\r\n\r\nbq. Se dă o matrice de dimensiuni $N x M (1 <= N <= 7 şi 1 <= M <= 100)$. Unele celule ale acestei matrici sunt distruse şi trebuie acoperite cu piese de forma din $Fig. 1$. Fiecare celulă rămasă neacoperită se consideră o greşeală, iar dacă o piesă cu care am acoperit celule distruse a trebuit să fie tăiată pentru a acoperi numai celule distruse, fiecare pătrăţel din partea nefolosită a piesei este considerată o greşeală. Se cere acoperirea tablei astfel ca numărul de greşeli să fie minimizat. În $Fig. 2$, pentru prima tablă, acoperirea optimă are două greşeli, aşa cum vedem în al doilea desen.\r\n\r\np=. _Fig. 1_ !probleme-de-acoperire2?P221.jpg!       _Fig. 2_ !probleme-de-acoperire2?P222.jpg!\r\n\r\nh3. Soluţie:\r\n\r\n* Aşa cum am zis şi în articolul anterior, problemele de acoperire sunt în general $NP complete$, deci prima idee ar fi să încercăm o rezolvare prin metoda $backtraking$, dar dimensiunile datelor de intrare ne arată că o asemenea rezolvare nu ne rezolvă problema.\r\n\r\n* Strategii polinomiale de tip $greedy$ sau de tip $programare dinamică$ nu vor rezolva această problemă pe toate cazurile de intrare, şi pentru orice strategie se poate găsi câte un contraexemplu. Totuşi vom putea să folosim o rezolvare bazată pe combinarea tehnicilor de $programare dinamică$ şi $backtraking$. Să vedem cum.\r\n* Construim soluţia optimă coloană cu coloană, dar este evident din următorul exemplu că pentru a construi soluţia optimă pentru coloana $j + 1$ nu este de ajuns să acoperim optim primele $j$ coloane.\r\n\r\np=. !probleme-de-acoperire2?P223.jpg!\r\n\r\n* Evident soluţia optimă pe primele trei coloane ale tablei foloseşte piesa în formă de cruce şi se obţine o acoperire cu $0$ greşeli, dar când vrem să acoperim toate $4$ coloanele tablei folosind prima acoperire obţinem o tablă cu $2$ greşeli, iar folosind două piese de tipul doi orientate înspre stânga, obţinem o acoperire cu o singură greşeală.\r\n* Pentru a obţine o soluţie cu $j + 1$ coloane ne trebuie toate soluţiile cu $j$ coloane la care ştim configuraţia coloanelor $j – 1$ şi $j$ (o piesă poate influenţa configuraţia a cel mult trei coloane). De aici se conturează ideea de a folosi un tablou $best$ unde $best[j][config1][config2]$ conţine numărul minim de greşeli astfel încât coloana $j$ are pătratele rămase neacoperite date de mulţimea $config1$, iar coloana $j - 1$ are pătratele neacoperite date de mulţimea $config2$. Pentru a trece de la $j$ la $j + 1$, facem un $backtracking$ pe o tablă de trei coloane dintre care prima are pătrăţelele ocupate date de $config2$, a doua pătrăţelele ocupate date de $config1$, iar a treia nu are nici un pătrăţel ocupat. După ce am plasat în procedura $backtraking$ nişte piese ajungem la configuraţiile pentru coloane date de mulţimile $c1 c2 c3$ şi actualizăm dacă am obţinut un număr mai mic pe $best[j + 1][c3][c2]$. În procedura recursivă ţinem cont atunci când vom acoperi cu piese un pătraţel deja acoperit sau un pătraţel ce nu este stricat. Ambele mulţimi $config1$ şi $config2$ pot fi reprezentate cu biţii unui întreg, $N$ fiind mic, astfel: primii $7$ biţi ai unui întreg vor reprezenta elementele primei mulţimi iar următorii $7$ biţi elementele celei de a două mulţimi. Memoria folosită de algoritmul nostru are ordinul de complexitate $O(M * 4^N^)$, acesta putând fi uşor micşorat la $O(4^N^)$ pentru că la pasul $j + 1$ avem nevoie numai de linia $j$ a matricii. Pentru a reduce numărul de stări folosite ne vom folosi de observaţia că putem să facem o restricţie asupra acoperirilor, aceea că atunci când ajungem la linia $j$ orice piesă nouă amplasată trebuie să acopere cel puţin un pătrăţel neacoperit de pe linia $j – 1$. Fie $newBest[j][confing12]$ structura care păstrează cele mai bune acoperiri cu această restricţie, atunci soluţia optimă va fi în $newBest[M + 1]$ unde am considerat o nouă coloană $M + 1$ a tablei ce nu are niciun pătrăţel stricat. Pentru tablele astfel acoperite, configuraţiile ultimelor două pătrăţele de pe o linie de forma $11$ şi $10$ şi $00$, configuraţia $01$ nu apare pentru că este evident că nu există o piesă care să acopere un pătrat din ultima coloană, un pătrat cu două coloane înainte şi să nu acopere pătratul imediat în stânga pătratului de pe ultima linie. Astfel avem $O(3^N^)$ configuraţii posibile pentru ultimele două coloane. Mai există multe configuraţii de două coloane la care nu se poate ajunge folosind piesele din problemă, dar o analiză exactă ar fi dificilă şi probabil ar complica inutil implementarea. Să vedem cum arată configuraţiile pe un exemplu:\r\n\r\np=. !probleme-de-acoperire2?P224.jpg!\r\n\r\n* Putem reprezenta această acoperire astfel:\r\n\r\np=. **00010**\r\n**01110**\r\n**11110**\r\n**00011**\r\n\r\n* Iar ultimele două coloane arată în felul următor:\r\n\r\np=. **10**\r\n**10**\r\n**10**\r\n**10**\r\n**11**\r\n\r\n* În acest caz $config$ are valoarea $1 * 3^0^ + 1 * 3^1^ + 1 * 3^2^ + 1 * 3^3^ + 2 * 3^4^ = 202$. Acum, la fiecare pas noi vrem să punem pe coloana $j – 1$ câte o piesă pentru a obţine rezultatele pentru $newBest[j + 1]$, sau să nu punem o piesă acolo. Deci, avem $9$ posibilităţi de a pune piese (fiecare rotaţie şi reflexie a pieselor din problemă) şi posibilitatea de a nu pune piesă în pătrăţelul curent, deci în total $10$ posibilităţi. Astfel, complexitatea algoritmului nostru devine $O(M * 3^N^ * 10^N^)$, constanta din faţă acestei complexităţi este subunitară din cauză că nu vom trece prin stări imposibile.\r\n\r\nh2. Problema 3 (ACM ICPC 1997)\r\n\r\nbq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $N x M (N <= 15, M <= 15)$ cu dominouri.\r\n\r\n\r\n\r\n',3146,'public',NULL,NULL),('probleme-de-acoperire-2','probleme-de-acoperire2','2008-11-15 18:53:30','2008-11-16 08:48:42','h1. Probleme de acoperire 2\r\n\r\n(Categoria _Algoritmi_, autor _Cosmin Negruşeri_)\r\n\r\nSubiectul acestui articol sunt acoperirile cu o abordare bazată pe tehnici de programare.\r\n\r\nh2. Problema 1 (MagicBoxes, TopCoder)\r\n\r\nbq. Să se determine numărul $N$ maxim astfel ca într-un dreptunghi de dimensiuni $L x W (1 <= L , W <= 30)$ să poată fi dispuse paralel cu axele de coordonate $N$ pătrate de laturi $1 .. N$ astfel ca oricare două pătrate să nu aibă porţiuni care se suprapun.\r\n\r\nh3. Soluţie:\r\n\r\n* Această problemă, deşi clasică, este dificil de rezolvat în cazul general si singura abordare a ei este aceea de a folosi metoda $backtracking$. \r\n* Întâi putem stabili o limită superioară a numarului $N$: este evident că $N <= W, N <= L$ şi că $1^2^ + 2^2^ + .. + N^2^ <= L x W$. Putem porni cu $N$ de la limita superioară dată de aceste inegalităţi şi să încercăm să dispunem cele $N$ pătrate în interiorul dreptunghiului. O optimizare simplă care ne-ar fi ajutat să rezolvăm problema, precalculând toate rezultatele, ar fi fost să punem în dreptunghi pătratele în ordinea descrescătoare a înălţimii. Altă observaţie ce reduce timpul de execuţie este că piesa cea mai mare nu trebuie pusă în toate poziţiile posibile ci în un sfert din ele, din cauza soluţiilor simetrice, iar între ea şi margine nu trebuie lăsat spaţiu puţin pentru că acel spaţiu va rămâne nefolosit. Observaţia care ne-ar fi dus la o soluţie care să rezolve un test în două secunde, cât era limita de timp în concurs, este că procedura $backtraking$ pierde mult timp pentru verificarea dacă o piesă poate fi pusă pe o anumită poziţie. Dacă în loc de reprezentarea pe matrice folosim $L$ întregi astfel ca bitul al $j$-lea din întregul $i$ este $1$ dacă celula $(i, j)$ este deja ocupată şi $0$ altfel, vom putea verifica dacă pătratul de latură $i$ poate fi plasat pe o anumită poziţie în $i$ paşi, şi nu în $i^2^$ paşi ca înainte. \r\n* Această reprezentare pe biţi este foarte utilă în probleme de acest gen, şi cum avem întregi de $64$ de biţi pe care îi putem folosi, avem o metodă foarte simplă de reprezentare a tablelor de mărime până la $64$.\r\n\r\nh2. Problema 2 (IOI 2001 Pavement, problemă de rezervă [1])\r\n\r\nbq. Se dă o matrice de dimensiuni $N x M (1 <= N <= 7 şi 1 <= M <= 100)$. Unele celule ale acestei matrici sunt distruse şi trebuie acoperite cu piese de forma din $Fig. 1$. Fiecare celulă rămasă neacoperită se consideră o greşeală, iar dacă o piesă cu care am acoperit celule distruse a trebuit să fie tăiată pentru a acoperi numai celule distruse, fiecare pătrăţel din partea nefolosită a piesei este considerată o greşeală. Se cere acoperirea tablei astfel ca numărul de greşeli să fie minimizat. În $Fig. 2$, pentru prima tablă, acoperirea optimă are două greşeli, aşa cum vedem în al doilea desen.\r\n\r\np=. _Fig. 1_ !probleme-de-acoperire2?P221.jpg!       _Fig. 2_ !probleme-de-acoperire2?P222.jpg!\r\n\r\nh3. Soluţie:\r\n\r\n* Aşa cum am zis şi în articolul anterior, problemele de acoperire sunt în general $NP complete$, deci prima idee ar fi să încercăm o rezolvare prin metoda $backtraking$, dar dimensiunile datelor de intrare ne arată că o asemenea rezolvare nu ne rezolvă problema.\r\n\r\n* Strategii polinomiale de tip $greedy$ sau de tip $programare dinamică$ nu vor rezolva această problemă pe toate cazurile de intrare, şi pentru orice strategie se poate găsi câte un contraexemplu. Totuşi vom putea să folosim o rezolvare bazată pe combinarea tehnicilor de $programare dinamică$ şi $backtraking$. Să vedem cum.\r\n* Construim soluţia optimă coloană cu coloană, dar este evident din următorul exemplu că pentru a construi soluţia optimă pentru coloana $j + 1$ nu este de ajuns să acoperim optim primele $j$ coloane.\r\n\r\np=. !probleme-de-acoperire2?P223.jpg!\r\n\r\n* Evident soluţia optimă pe primele trei coloane ale tablei foloseşte piesa în formă de cruce şi se obţine o acoperire cu $0$ greşeli, dar când vrem să acoperim toate $4$ coloanele tablei folosind prima acoperire obţinem o tablă cu $2$ greşeli, iar folosind două piese de tipul doi orientate înspre stânga, obţinem o acoperire cu o singură greşeală.\r\n* Pentru a obţine o soluţie cu $j + 1$ coloane ne trebuie toate soluţiile cu $j$ coloane la care ştim configuraţia coloanelor $j – 1$ şi $j$ (o piesă poate influenţa configuraţia a cel mult trei coloane). De aici se conturează ideea de a folosi un tablou $best$ unde $best[j][config1][config2]$ conţine numărul minim de greşeli astfel încât coloana $j$ are pătratele rămase neacoperite date de mulţimea $config1$, iar coloana $j - 1$ are pătratele neacoperite date de mulţimea $config2$. Pentru a trece de la $j$ la $j + 1$, facem un $backtracking$ pe o tablă de trei coloane dintre care prima are pătrăţelele ocupate date de $config2$, a doua pătrăţelele ocupate date de $config1$, iar a treia nu are nici un pătrăţel ocupat. După ce am plasat în procedura $backtraking$ nişte piese ajungem la configuraţiile pentru coloane date de mulţimile $c1 c2 c3$ şi actualizăm dacă am obţinut un număr mai mic pe $best[j + 1][c3][c2]$. În procedura recursivă ţinem cont atunci când vom acoperi cu piese un pătraţel deja acoperit sau un pătraţel ce nu este stricat. Ambele mulţimi $config1$ şi $config2$ pot fi reprezentate cu biţii unui întreg, $N$ fiind mic, astfel: primii $7$ biţi ai unui întreg vor reprezenta elementele primei mulţimi iar următorii $7$ biţi elementele celei de a două mulţimi. Memoria folosită de algoritmul nostru are ordinul de complexitate $O(M * 4^N^)$, acesta putând fi uşor micşorat la $O(4^N^)$ pentru că la pasul $j + 1$ avem nevoie numai de linia $j$ a matricii. Pentru a reduce numărul de stări folosite ne vom folosi de observaţia că putem să facem o restricţie asupra acoperirilor, aceea că atunci când ajungem la linia $j$ orice piesă nouă amplasată trebuie să acopere cel puţin un pătrăţel neacoperit de pe linia $j – 1$. Fie $newBest[j][confing12]$ structura care păstrează cele mai bune acoperiri cu această restricţie, atunci soluţia optimă va fi în $newBest[M + 1]$ unde am considerat o nouă coloană $M + 1$ a tablei ce nu are niciun pătrăţel stricat. Pentru tablele astfel acoperite, configuraţiile ultimelor două pătrăţele de pe o linie de forma $11$ şi $10$ şi $00$, configuraţia $01$ nu apare pentru că este evident că nu există o piesă care să acopere un pătrat din ultima coloană, un pătrat cu două coloane înainte şi să nu acopere pătratul imediat în stânga pătratului de pe ultima linie. Astfel avem $O(3^N^)$ configuraţii posibile pentru ultimele două coloane. Mai există multe configuraţii de două coloane la care nu se poate ajunge folosind piesele din problemă, dar o analiză exactă ar fi dificilă şi probabil ar complica inutil implementarea. Să vedem cum arată configuraţiile pe un exemplu:\r\n\r\np=. !probleme-de-acoperire2?P224.jpg!\r\n\r\n* Putem reprezenta această acoperire astfel:\r\n\r\np=. **00010**\r\n**01110**\r\n**11110**\r\n**00011**\r\n\r\n* Iar ultimele două coloane arată în felul următor:\r\n\r\np=. **10**\r\n**10**\r\n**10**\r\n**10**\r\n**11**\r\n\r\n* În acest caz $config$ are valoarea $1 * 3^0^ + 1 * 3^1^ + 1 * 3^2^ + 1 * 3^3^ + 2 * 3^4^ = 202$. Acum, la fiecare pas noi vrem să punem pe coloana $j – 1$ câte o piesă pentru a obţine rezultatele pentru $newBest[j + 1]$, sau să nu punem o piesă acolo. Deci, avem $9$ posibilităţi de a pune piese (fiecare rotaţie şi reflexie a pieselor din problemă) şi posibilitatea de a nu pune piesă în pătrăţelul curent, deci în total $10$ posibilităţi. Astfel, complexitatea algoritmului nostru devine $O(M * 3^N^ * 10^N^)$, constanta din faţă acestei complexităţi este subunitară din cauză că nu vom trece prin stări imposibile.\r\n\r\nh2. Problema 3 (ACM ICPC 1997)\r\n\r\nbq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $N x M (N <= 15, M <= 15)$ cu dominouri.\r\n\r\nh3. Soluţie:\r\n\r\n* Am văzut în numărul anterior că există o formulă pentru acest număr. Abordarea matematică poate fi generalizată şi pentru mai multe probleme asemănătoare de acoperire, dar cunoştinţele necesare sunt avansate, deci această abordare nu ne prea ajută pe noi ca informaticieni.\r\n* O soluţie care ne va da numărul exact şi ar fi putut fi folosită în concurs este asemănătoare celei expuse mai sus. Vom folosi o combinaţie a metodei $backtracking$ cu metoda $programării dinamice$. Tabloul $numWays[i][config]$ va fi numărul de posibilităţi de a acoperi complet primele $i - 1$ coloane ale unei table, iar pe coloana $i$ pătratele ocupate sunt reprezentate de mulţimea $config$. Astfel, $numWays[i + 1][config1]$  va fi egal cu suma de $numWays[i][config]$ unde putem acoperi cu dominouri două coloane astfel ca pe prima coloană să nu fie acoperite celulele date de $config$ şi pe a doua coloană să fie acoperite celulele date de $config1$. De exemplu, starea dată de $(4, 100100)$ este prezentată în următoarea figură:\r\n\r\np=. !probleme-de-acoperire2?P231.jpg!\r\n\r\n* Dacă procedura aşezăm trei dominouri pe linia $4$ şi linia $5$ aşa cum vedem mai sus, atunci vom trece în starea $(5, 011000)$. La final, vom returna valoarea aflată în $numWays[N + 1][0]$ <tex> !! </tex>. Complexitatea ca timp a acestei rezolvări este $O(M * 4^N^)$, iar ca spaţiu este $O(2^N^)$.\r\n\r\nh2. Problema 4 (Hardwood Floor, acm.sgu.ru)\r\n\r\nbq. Determinaţi numărul de acoperiri ale unei table de dimensiuni $N x M (1<= N <= 9, 1 <= M <= 9)$ cu piese de tipul:\r\n\r\np=. !probleme-de-acoperire?P241.jpg!\r\n\r\nh3. Soluţie:\r\n\r\n* Exemplu: Pentru $N = 3$ şi $M = 2$ avem $5$ acoperiri posibile.\r\n* În rezolvare putem folosi direct ideea de rezolvare a problemei anterioare.\r\n\r\nh2. Problema 5 (TopCoder, CaseysArt)\r\n\r\nbq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $N x M (N <= 18, M <= 15)$ cu piese de forma:\r\n\r\np=. !probleme-de-acoperire2?P251.jpg!\r\n\r\nh3. Soluţie:\r\n\r\n* De exemplu, pentru avem $N = 3, M = 4$ următoarele acoperiri:\r\n\r\np=. !probleme-de-acoperire2?P252.jpg!\r\n\r\n* Din nou, ideea de rezolvare este cea prezentată în $Problema 2$. Complexitatea soluţiei este $O(N * 4^M^)$, dar trebuie să fim conştienţi că aceasta este o limită superioară mult mai mare decât complexitatea reală. Să vedem şi implementarea unei asemenea soluţii:\r\n\r\n== code(java) |\r\npublic class CaseysArt {\r\n    double[][] num;\r\n    int step, w;\r\n    int[][][] p = {{{0, 1}, {1, 1}},\r\n        {{1, 0},{1, 1}},\r\n        {{1, 1},{0, 1}},\r\n        {{1, 1},{1, 0}}};\r\n    int[][] sol;\r\n    void checksol() {\r\n        int config = 0,config1 = 0;\r\n        for (int i = 0;i < w; i++) {\r\n            if (sol[i][0] == 0) config |= (1<<i);\r\n            if (sol[i][1] == 1) config1 |= (1<<i);\r\n        }\r\n        num[1 ^ step][config1] += num[step][config];\r\n    }\r\n    void doit(int x) {\r\n        if (x == w) checksol();\r\n        else {\r\n            if (x < w - 1) {\r\n                int i, j, k;\r\n                boolean bool;\r\n                for (k = 0; k < 4; k++) {\r\n                    bool=true;\r\n                    for (i = 0; i < 2; i++) {\r\n                        for (j = 0; j < 2; j++) {\r\n                            if (p[k][i][j] == 1)\r\n                                bool = bool && (sol[x + i][j] == 0);\r\n                        }\r\n                    }\r\n                    if (bool) {\r\n                        for (i = 0; i < 2; i++) {\r\n                            for (j = 0; j < 2; j++) {\r\n                                if (p[k][i][j] == 1)\r\n                                    sol[x + i][j] = 1;\r\n                            }\r\n                        }\r\n                        doit(x + 1);\r\n                        for (i = 0; i < 2; i++) {\r\n                            for (j = 0; j < 2; j++) {\r\n                                if (p[k][i][j] == 1)\r\n                                    sol[x + i][j]=0;\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            doit(x+1);\r\n        }\r\n    }\r\n    public double howManyWays(int l, int w) {\r\n        num = new double[2][1 << w];\r\n        this.w = w;\r\n        num[0][0] = 1;\r\n        step = 0;\r\n        sol = new int[w][2];\r\n        for (int i = 1; i < l; i++) {\r\n            Arrays.fill(num[1 ^ step], 0);\r\n            doit(0);\r\n            step ^= 1;\r\n        }\r\n        return num[step][(1 << w) - 1];\r\n    }\r\n==\r\n\r\n* În $num[i][config]$ ţinem minte câte posibilităţi sunt să acoperim $i - 1$ linii cu piesele date în problemă, iar linia $i$ să fie ocupată aşa cum arată reprezentarea în baza $2$ a numărului întreg $config$. Se observă folosirea variabilei $step$ care de la un pas la altul se transformă astfel $step ^= 1$, aceast mic truc ne face să putem folosi o matrice de doar $2$ linii în loc să folosim $N$ linii. La momentul $i$, în $num[step][config]$ avem informaţia ce ar fi fost în mod normal în $num[i][config]$, iar în $num[1 ^ step][config1]$ vom calcula ce ar fi fost normal în $num[i + 1][config1]$. În şirul $p$ ţinem minte forma pieselor din problemă.\r\n* În procedura $doit$ punem pe două linii consecutive piese în toate modurile posibile. Această procedură face ca pe prima linie să avem o configuraţie de pătrăţele libere $config$ şi o configuraţie de pătrăţele ocupate pe a doua linie $config1$. Dacă pătrăţelele reprezentate de $config$ nu au fost ocupate la pasul curent ele trebuie să fi fost ocupate la pasul anterior. Astfel, pentru fiecare pereche de configuraţii $config$ şi $config1$ trebuie să efectuăm operaţia $num[i + 1][config1] += num[i][config]$.\r\n* Dacă această rezolvare ar fi fost folosită în timpul concursului ea ar fi ieşit din timp. Pentru optimizarea ei putem face mai multe optimizări. Un exemplu ar fi să generăm direct cele două configuraţii de biţi în procedura $backtraking$ şi să nu mai folosim şirul $sol$. O altă idee care ar fi dus la rezolvarea problemei ar fi fost calcularea tuturor rezultatelor posibile în timpul concursului şi trimiterea unei soluţii care returna aceste rezultate precalculate. Această abordare ar fi fost posibilă pentru că numărul de configuraţii iniţiale este mic.\r\n* Menţionăm că această problemă a apărut ca întrebare la miniconcursul online de pe forumul \"GInfo\":http://www.ginfo.ro.\r\n\r\n\r\n\r\n\r\n',3146,'public',NULL,NULL),('template/badtests','template/badtests','2007-02-19 00:43:29','2008-02-04 20:56:47','table{margin:0.5em auto;}. |={background-color:#F8EABA;}. !<template/badtests?attention.gif! _Testele pentru aceasta problema nu sunt destul de bine construite pentru a departaja corect solutii ineficiente sau gresite._\r\n\'*Intra aici*\':implica-te/imbunatatire-teste _daca vrei sa ne ajuti sa imbunatatim calitatea testelor pentru aceasta problema!_ |',1,'protected',NULL,NULL),('utilizator/domino','Profil Mircea Pasoi','2006-11-24 15:55:10','2008-11-16 11:11:43','h2. Despre mine\r\n\r\n\r\n\'!utilizator/domino?btn_viewmy_160x33.gif!\':http://www.linkedin.com/in/mirceapasoi\r\n\r\n* Sunt membru fondator si vicepresedinte al Asociatiei infoarena\r\n* Membru in echipa \'.campion\':http://campion.edu.ro\r\n* Membru in Comisia Nationala de Informatica la ONI 2007, ONI 2008, Lot Suceava 2007, Lot Alba 2007\r\n* Membru in echipa \'USACO\':http://usaco.org care selecteaza si propune problemele pentru concursurile online USACO si pentru tabara de pregatire USAICO\r\n* Am fost la internship in perioada iulie-septembrie 2007 la Microsoft, Redmond \r\n* Am fost la internship in perioada iulie-septembrie 2008 la Google, Mountain View\r\n* Am fost la \"Surprize, Surprize\" si am primit un Renault Scenic din 2003 :)\r\n\r\nh2. Studii\r\n\r\n* 2006-prezent: Universitatea Bucuresti, Facultatea de informatica\r\n* 1998-2006: Colegiul National \"I. L. Caragiale\" Ploiesti (Matematica-Informatica)\r\n\r\nh2. Trivia\r\n\r\n* Am predat informatica la ICHB in perioada 2007-2008\r\n* Am participat la organizarea concursurilor \"Stelele Informaticii 2006\" si \"Stelele Informaticii 2007\"\r\n\r\nh2. Premii (cele mai importante)\r\n\r\n* 2007, Noiembrie - Locul 8 la Finala TopCoder Collegiate Challenge, Orlando, USA\r\n* 2007, Martie - Finalist la ACM world finals in Tokyo\r\n* 2006, Noiembrie - Finalist TopCoder Collegiate Challenge, San Diego, USA\r\n* 2006, Octombrie - Locul 2 la regionala ACM South-Eastern, Bucuresti, Romania \r\n* 2006, August - Aur (locul 7) la IOI, Merida, Mexico\r\n* 2006, Iulie - Argint la CEOI, Vrsar, Croatia \r\n* 2006, Iunie - Invitat la tabara de pregatire a lotului america (USAICO), Colorado Springs, USA\r\n* 2005, August - Argint la IOI, Nowy Sacz, Polonia\r\n* 2004, Iulie - Argint la BOI, Plovdiv, Bulgaria\r\n* 2003, 2005, 2006 - Locul I la ONI\r\n\r\nh2. Publicatii\r\n\r\n* 2006 \"Fundamentele programarii - culegere de probleme pentru clasa a 11-a\", autori Dana Lica si Mircea Pasoi, Editura L&S Info-mat, ISBN 973-88073-2-1\r\n* 2005 \"Fundamentele programarii - culegere de probleme pentru clasa a 10-a\", autori Dana Lica si Mircea Pasoi, Editura L&S Info-mat, ISBN 973-86022-9-7\r\n* 2005 \"Fundamentele programarii - culegere de probleme pentru clasa a 9-a\", autori Dana Lica si Mircea Pasoi, Editura L&S Info-mat, ISBN 973-7658-02-7\r\n* 2005, Decembrie \"Rotatie minim lexicografica\", GInfo, vol. 15/8\r\n* 2005, Octombrie \"Ghid complet pentru concursurile de informatica\", GInfo, vol. 15/6 \r\n\r\nh2. Mentori\r\n\r\n* == User(user=\"danal\" type=\"tiny\") ==\r\n* == User(user=\"cosmin\" type=\"tiny\") ==\r\n* == User(user=\"mugurelionut\" type=\"tiny\") ==\r\n',1,'protected',NULL,NULL),('utilizator/wickedman','Cristian George Strat (wickedman)','2006-11-24 20:56:12','2008-10-27 15:01:54','h2. Despre mine\r\n\r\n* Membru fondator si Presedinte al Asociatiei infoarena <a href=\"http://www.linkedin.com/in/cristiangeorgestrat\" style=\"float: right\"><img src=\"http://www.linkedin.com/img/webpromo/btn_viewmy_120x33.gif\" width=\"120\" height=\"33\" border=\"0\" alt=\"View Cristian George Strat\'s profile on LinkedIn\"></a>\r\n* Co-fondator INNOVATE CONSULT, companie ce ofera servicii software si networking\r\n* Google internship, summer 2008, Zurich, Switzerland\r\n* Google internship, summer 2007, Mountain View, California\r\n* Presedinte al juriului de _Pagini Web_, \"InfoEducatie\":http://infoeducatie.ro/ 2006\r\n* Membru al juriului de _Programare_ \"InfoMatrix 2008\":http://infomatrix.ro/\r\n* Membru al juriului de _Pagini Web_ \"InfoEducatie\":http://infoeducatie.ro/ 2005 si Unirea 2005\r\n* Locurile I, I, II, III la concursul national de software si pagini web \"InfoEducatie\":http://infoeducatie.ro/\r\n* Locul II la concursul pe echipe EESTEC Olympics 2006\r\n* Finalist la \'Challenge24\':http://challenge24.org/\r\n* Locul 4 la ONI 2004\r\n* Finalist \'.campion\':http://campion.edu.ro/ 2004 \r\n* Calificare in lotul largit de informatica 2004\r\n\r\nh3. Studii\r\n\r\n* C.N. \"Gh. Rosca Codreanu\", Barlad, Jud. Vaslui\r\n* -Student in anul IV la- Absolvent \"FMI\":http://fmi.unibuc.ro/ 2008, Universitatea Bucuresti\r\n\r\nh3. Trivia\r\n\r\n* infoarena a fost initial un proiect pentru concursul national \'InfoEducatie\':http://infoeducatie.ro/, sectiunea pagini web. La prima participare (in 2002) am primit locul III, iar in 2003 am castigat locul I.\r\n* l-am cunoscut pe \'Mircea Pasoi\':utilizator/domino si pe \'Crestez Leonard\':utilizator/fluffy pe canalul IRC #olimpada. Ei vroiau sa faca un site de probleme\r\n* am fost coleg de clasa cu \'Silviu Ganceanu\':utilizator/silviug in 9-11\r\n* ce vedeti acum este site-ul infoarena versiunea 2. \'Inainte era albastru\':http://web.archive.org/web/20060307025837/http://infoarena.devnet.ro/\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* == User(user=\"chucknorris\" type=\"tiny\") ==\r\n* == User(user=\"eval\" type=\"tiny\") ==\r\n',13,'protected',NULL,NULL),('blog/alt-demo-de-la-microsoft','Alt demo de la Microsoft','2007-11-28 05:00:49','2008-11-15 13:41:14','Inca un demo foarte tare de la Microsoft Research. Imi plac ideile astea istete si foarte simplu de pus in practica.\r\n\r\n<object width=\"425\" height=\"355\"><param name=\"movie\" value=\"http://www.youtube.com/v/AtmwQnUlEmc&rel=1\"></param><param name=\"wmode\" value=\"transparent\"></param><embed src=\"http://www.youtube.com/v/AtmwQnUlEmc&rel=1\" type=\"application/x-shockwave-flash\" wmode=\"transparent\" width=\"425\" height=\"355\"></embed></object>\r\n\r\n',1490,'protected',2423,NULL),('blog/jake-jarvis-si-aplicatia-lui-de-facebook','Jake Jarvis si aplicatia lui de Facebook','2008-03-19 16:19:51','2008-11-15 13:41:14','Toata lumea a auzit de \'Mark Zuckerberg\':http://en.wikipedia.org/wiki/Mark_Zuckerberg, studentul care a renuntat la Harvard pentru a se ocupa de \'site-ul pe care il lansase\':http://www.facebook.com/ (si care s-a imbogatit, cu ocazia asta).\r\n\r\nMai interesant pentru elevii pasionati de informatica mi se pare totusi exemplul lui Jake Jarvis, un pusti de 16 ani care a programat o aplicatie care se integreaza cu Facebook si a vandut-o pe o suma consistenta. Majoritatea romanilor au acum la dispozitie resursele pe care le-a avut el. E mult mai usor sa faci lucruri importante decat cu cativa ani in urma, iar cunostintele programare si algoritmi va ofera ocazia de a va face cunoscuti chiar inainte de a atinge varsta majoratului. Va dati seama?\r\n\r\n<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\"437\" height=\"370\" id=\"viddler_pop17_9\"><param name=\"movie\" value=\"http://www.viddler.com/player/725841df/\" /><param name=\"allowScriptAccess\" value=\"always\" /><param name=\"allowFullScreen\" value=\"true\" /><embed src=\"http://www.viddler.com/player/725841df/\" width=\"437\" height=\"370\" type=\"application/x-shockwave-flash\" allowScriptAccess=\"always\" allowFullScreen=\"true\" name=\"viddler_pop17_9\" ></embed></object>\r\n\r\n*Tiberiu Florea* - \'greco.ro\':http://www.greco.ro',1490,'public',2895,NULL),('blog/alta-problema-misto-solutie','Alta problema misto - solutie','2007-10-22 08:00:03','2008-11-15 13:41:14','Problema cu lanternele a fost rezolvata de Radu Cebanu, Dumitru Daniliuc, \'Stefan Istrate\':http://infoarena.ro/utilizator/stef2n , Catalin Francu si Stefan Ciobaca.\r\n\r\nVa prezint in continuare solutiile. Este interesant de urmarit cum sunt gandite solutiile, care desi sunt echivalente sunt prezentate putin diferit.\r\n\r\n*Stefan Ciobaca* generalizeaza problema:\r\n<i>Eu as fi propus generalizarea: ai <tex>2^n</tex> triedre drepte in n dimensiuni.\r\n\r\nRezolvarea prin divide et impera: iei cele <tex>2^n</tex> puncte si le separi printr-un hiperplan astfel incat jumate sa fie de-o parte, jumate de cealalta parte s.a.m.d., avand in vedere ca toate hiperplanele sa fie perpendiculare intre ele. Evident, chestia asta se poate. Apoi, fiecare triedru il orientezi spre semisemisemi...semi spatiul total opus si cu marginile paralele cu axele de coordonate q.e.d.</i>\r\nImi place cum se vede defectul profesional de programator citind demonstratia.\r\n\r\nSolutia lui *Radu*:\r\n\r\n<i>Rezolvam prin inductie dupa nr de dimensiuni.\r\n\r\nIn primul rand: fixezi o directie pt primul plan, il muti paralelel cu el insusi astfel incat sa separe punctele in 2 parti egale, 4 de o parte, 4 de alta (daca stau mai multe pe planul ala exact,nu conteaza, alegi cateva si le declari de o parte, sa fie 4 si restul de cealalta). \r\nApoi sa zicem ca le luam pe alea de deasupra:\r\n proiectiile lor pe planul respectiv sunt 4 puncte care conform inductiei (pt doua dimensiuni) acopera planul. Cu diedrele din plan faci triedre cu a 3-a dreapta in jos ca sa acopere semispatiul inferior. La fel pt alea de sub plan, pui dreapta a 3-a din triedru in sus ca sa acopere semispatiul superior.</i>\r\nRadu a lasat demonstratia putin incompleta avand incredere ca ma prind singur de cazul 2d si 1d.\r\n\r\nSolutia lui *Catalin*:\r\n<i>Ideea mea e sa gasesc o solutie in care triedrele au laturile orientate paralel cu axele, pentru simplitate.\r\n\r\n- Rotim sistemul astfel incat sa nu existe doua lanterne cu coordonate X, Y sau Z egale (pentru a scapa de cazuri particulare).\r\n\r\n- Parcurgem lanternele in ordine crescatoare a coordonatei x. Pe primele 4 le marcam cu X+, pe ultimele 4 cu X-.\r\n\r\n- Parcurgem cele patru lanterne X+ in ordine crescatoare a coordonatei y. Pe primele doua le marcam cu Y+, pe celelalte doua cu Y-. La fel si\r\npentru cele patru lanterne X-.\r\n\r\n- Parcurgem cele doua lanterne X+Y+ in ordine crescatoare a coordonatei z. Pe prima o marcam cu Z+, pe a doua cu Z-. La fel si pentru celelalte 6 lanterne marcate cu X+Y-, X-Y+, X-Y-.\r\n\r\nAvem opt lanterne marcate cu X+Y+Z+, X+Y+Z-, pana la X-Y-Z-. Acum le pozitionam paralel cu axele Ox, Oy, Oz si in sensurile indicate de semne. De exemplu, lanterna X+Y-Z- \r\n\r\nva lumina catre sensul pozitiv al axei Ox si catre sensurile negative ale axelor Oy si Oz; cu alte cuvinte, ea va lumina punctul de coordonate (+inf, -inf, -inf).\r\n\r\nDandu-se un punct P(x,y,z), trebuie demonstrat ca exista o lanterna care il lumineaza. Analizam coordonata x. Datorita constructiei, x va fi fie mai mare decat toate coordonatele x ale lanternelor marcate cu X+, fie mai mic decat toate coordonatele x ale lanternelor marcate cu X- (fie ambele, daca x este situat intre cele doua grupuri de 4 lanterne). Alegem acel set de 4 lanterne si reluam rationamentul pe axele Oy si Oz. in final, obtinem minim o lanterna care lumineaza punctul P.</i>\r\n\r\nSi la Catalin se vede programatorul din spatele solutiei. Se observa cum structura rezolvarii este bazata pe vectorii de cate 3 elemente in baza 2.\r\n\r\n*Stefan Istrate* are o solutie foarte misto, cu desene dragute, pe care o gasiti pe \'forum\':http://infoarena.ro/forum/index.php?topic=2218.0 . Merita sa o cititi!\r\n\r\nSolutia lui *Dumitru* nu o am scrisa.\r\n\r\nLa solutia lui Stefan Ciobaca si cea a lui Catalin Francu nu e demonstrata ipoteza ca _putem gasi un sistem de coordonate in care toate punctele au coordonatele x1, x2, .. respectiv diferite_ . Va incurajez sa va incercati puterile pe aceasta subproblema in sectiunea de \'comentarii\':http://infoarena.ro/forum/index.php?topic=2222.0\r\n\r\nO problema similara a fost propusa la un ACM in regiunea din Nord Estul Europei: _Se cere iluminarea planului cu n lanterne (n <= 30) de coordonate date, ce pot fi rotite, al caror fascicul emite lumina sub un unghi de marime 2pi/n. Pentru fiecare lanterna trebuie returnata orientarea ei._ La aceasta problema, pe langa solutia ei, e interesant si algoritmul folosit pentru evaluarea corectitudinii unui rezultat.\r\n\r\nPentru mai multe probleme interesante cu lanterne puteti citi urmatoarele lucrari:\r\n\r\n<i>Bose, J., L. Guibas, A. Lubiw, M. Overmars, D. Souvaine and J. Urrutia, \'\"The floodlight illumination problem\"\':blog/alta-problema-misto-solutie?TheFloodProb.ps\r\nCzyzowicz, J., E. Rivera-Campo and J. Urrutia, \'\"Optimal floodlight illumination of stages\"\':blog/alta-problema-misto-solutie?OptFloStages.ps </i>\r\n\r\n\r\n',1490,'protected',2222,NULL),('probleme-de-acoperire-1','Probleme de acoperire','2008-11-14 08:56:52','2008-11-16 20:27:44','h1. Probleme de acoperire\r\n\r\n(Categoria _Algoritmi_, autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 33em}*{text-align:left} *Cuprins:*\r\n* \'Problema 1 ( _Olimpiada de informatică, Bucureşti, etapa pe sector, 1995,_ [1] ) \':probleme-de-acoperire#prob1\r\n* \'Problema 2 ( _Lot 2001,_ [1] ) \':probleme-de-acoperire#prob2\r\n* \'Problema 3 ( _Concursul naţional de informatică Lugoj, 1998_ ) \':probleme-de-acoperire#prob3\r\n* \'Problema 4\':probleme-de-acoperire#prob4\r\n* \'Problema 5\':probleme-de-acoperire#prob5\r\n* \'Problema 6 ( _ONI 2001, clasa a X-a,_ [3] ) \':probleme-de-acoperire#prob6\r\n* \'Problema 7 ( _ACM ICPC 1997_ ) \':probleme-de-acoperire#prob7\r\n* \'Problema 8 ( _Lot matematică 2001, acm.uva.es - 10644 Floor tiles_ ) \':probleme-de-acoperire#prob8\r\n* \'Problema 9\':probleme-de-acoperire#prob9\r\n* \'Concluzii\':probleme-de-acoperire#concl\r\n* \'Bibliografie\':probleme-de-acoperire#biblio\r\n\r\nÎn acest prim articol vom prezenta o serie de probleme apărute la concursurile de programare care au o tematică similară şi anume aceea de acoperire în plan. În general acest tip de probleme sunt $NP complete$, dar pentru cazurile particulare prezentate problemele sunt rezolvabile. Cea de a doua parte a articolului o puteţi găsi \"aici\":probleme-de-acoperire2.\r\n\r\nh2(#prob1). Problema 1 ( _Olimpiada de informatică, Bucureşti, etapa pe sector, 1995,_ [1] )\r\n\r\nbq. Se dă un pătrat de latură $2^n^$ care se împarte în pătrate disjuncte de latură $1$. Unul dintre aceste pătrate se elimină. Se cere acoperirea suprafeţei rămase cu piese de forma: \r\n\r\np=. !probleme-de-acoperire?OlimpBuc1.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nPrima întrebare care ne vine în minte este dacă aria ce trebuie acoperită este divizibilă cu $3$. Aria este $4^n^ – 1 = (4 – 1)(4^n-1^ + 4^n-2^ + … + 4 + 1)$, deci este multiplu de $3$. Să trecem acum la ideea rezolvării.\r\n\r\nÎmpărţim pătratul în $4$ pătrate de dimensiuni egale. Unul dintre ele are un pătrat lipsă. Facem ca celelalte trei pătrate să aibă şi ele un pătrat lipsă prin plasarea unei piese care să acopere câte un colţ al fiecăruia dintre cele trei pătrate rămase, după cum observăm în figură.\r\n\r\np=. !probleme-de-acoperire?OlimpBuc2.jpg!\r\n\r\nAstfel am redus problema la patru noi probleme de dimensiuni mai mici.\r\n\r\np=. !probleme-de-acoperire?OlimpBuc3.jpg!\r\n\r\nSe vede clar acum, cum prin metoda $divide et impera$ putem să acoperim întreg pătratul cu piesele cerute.\r\n\r\nh2(#prob2). Problema 2 ( _Lot 2001,_ [1] )\r\n\r\nbq. Se dă un pătrat de latură $6N + 1$ care se împarte în pătrate disjuncte de latură $1$. Unul dintre aceste pătrate se elimină. Se cere acoperirea suprafeţei rămase cu piese de forma:\r\n\r\np=. !probleme-de-acoperire?OlimpBuc1.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nSă vedem întâi cum rezolvăm cazul minim în care $N = 1$.\r\n\r\np=. !probleme-de-acoperire?P21.JPG!\r\n\r\nÎn aceste trei figuri am epuizat toate cazurile pentru table de dimensiune $7$ unde lipseşte un pătrat. În fiecare desen am lăsat un pătrat de latură doi liber pentru a trata astfel cele patru cazuri în care pătrăţelul lipsă ar face parte din acest pătrat. Recurgând şi la rotaţiile acestor soluţii acoperim toate cazurile posibile pentru pătrăţelul lipsă. Menţionăm că cele trei soluţii au fost găsite cu uşurinţă de mână de autor.\r\n\r\nSă presupunem că ştim cum să acoperim un pătrat de latură $6N + 1$. Să vedem acum cum acoperim un pătrat de latură $6N + 7$. În acest nou pătrat putem plasa într-un colţ de al lui un pătrat de latură $6N + 1$, care are un pătrăţel lipsă. Pătratul acesta îl ştim acoperi şi după cum arată şi figura următoare ne mai rămâne să acoperim două dreptunghiuri de dimensiuni $6 x 6n$, respectiv $6n x 6$ şi un pătrat de latură $7$ cu patrăţelul din colţ lipsă. Dreptunghiurile le putem acoperi cu dreptunghiuri de dimensiuni $2 x 3$ formate din câte două piese, iar pătratul de $7 x 7$ cu un colţ lipsă este un caz pentru $N = 1$ al problemei noastre.\r\n\r\np=. !probleme-de-acoperire?P22.jpg! \r\n\r\nh2(#prob3). Problema 3 ( _Concursul naţional de informatică Lugoj, 1998_ )\r\n\r\nbq. Să se acopere complet un pătrat de latură $N >= 6$ cu următoarele piese, astfel ca fiecare piesă să fie folosită cel puţin o dată.\r\n\r\np=. !probleme-de-acoperire?P31doi.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nObservăm că fiecare piesă este formată din patru pătrăţele. De aici deducem că $N^2^$ este multiplu de $4$ deci $N$ e multiplu de $2$. Pentru $N = 6$ avem următoarea soluţie:\r\n\r\np=. !probleme-de-acoperire?P32.jpg!\r\n\r\nPentru $N > 6$ putem împărţi pătratul într-un pătrat de latură $6$ şi două dreptunghiuri de dimensiuni $6 x (N – 6)$ şi $(N – 6) x N$, după cum observăm în figura următoare. Dreptunghiurile pot fi acoperite cu piese de tip $3$.\r\n\r\np=. !probleme-de-acoperire?P33.jpg!\r\n\r\nh2(#prob4). Problema 4\r\n\r\nbq. Să se determine dacă putem acoperi o tablă de dimensiune $N x N$ cu dominouri după ce îi eliminăm două colţuri opuse.\r\n\r\nh3. Soluţie:\r\n\r\nPrima observaţie pe care o facem este aceea că $N$ trebuie să fie par pentru ca tabla să poată fi acoperită. Este evident pentru cazurile $N = 2$ sau $N = 4$ că problema nu are soluţie, dar pentru cazuri mai mari demonstraţia faptului că există sau nu există soluţie pare dificilă, şi valorile lui $N$ pentru care o abordare exhaustivă a posibilităţilor de  acoperire a tablei cu dominouri ar fi eficientă sunt destul de mici. \r\n\r\nO idee interesantă este aceea de a colora pătratele tablei în acelaşi mod în care se colorează o tablă de şah, aşa cum vedem în figura următoare. \r\n\r\np=. !probleme-de-acoperire?P41.jpg!\r\n\r\nOrice domino amplasat pe tablă va acoperi două pătrăţele de culori diferite, deci tabla trebuie să aibă un număr egal de pătrăţele colorate alb şi negru, fapt care nu se întâmplă în problema noastră. De aici deducem că nu putem acoperi tabla din care au fost eliminate două colţuri opuse. O problemă ce se poate aborda cu o tehnică asemănătoare este următoarea: „Se dă un dreptunghi de dimensiuni $7 x 10$. Din colţurile lui scoatem câte un pătrat de latură $1$. Să se arate că figura rămasă nu poate fi pardosită cu dreptunghiuri de laturi $3$ şi $1$. Pentru probleme de acelaşi gen şi soluţia la această problemă puteţi să consultaţi în [1] secţiunea 1.1 $Invariant$, sau în [2] secţiunea $Probleme de colorare şi acoperire$. Problema în care eliminăm două pătrate de aceiaşi culoare sau chiar cazul generalizat în care eliminăm un număr mai mare de pătrăţele o vom discuta în numărul viitor.\r\n\r\nh2(#prob5). Problema 5\r\n\r\nbq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $2 x N$ cu dominouri.\r\n\r\nh3. Soluţie:\r\n\r\nPentru $N = 1$ avem o posibilitate, pentru $N = 2$ avem două posibilităţi, iar în cazul general daca notăm cu <tex> F[n] </tex> numărul de posibilităţi avem, aşa cum putem observa şi din figură, <tex> F[n] = F[n - 1] + F[n - 2] </tex>, deci exact şirul lui Fibonacci.\r\n\r\np=. !probleme-de-acoperire?P51.jpg!\r\n\r\nh2(#prob6). Problema 6 ( _ONI 2001, clasa a X-a,_ [3] )\r\n\r\nbq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $3 x N$ cu dominouri.\r\n\r\nh3. Soluţie:\r\n\r\nŞi în această problemă $N$ trebuie să fie par pentru ca tabla să poată fi acoperită. Avem următoarele posibilităţi la început:\r\n\r\np=. !probleme-de-acoperire?P61.jpg!\r\n\r\nObservăm că în ultimele două cazuri pătrăţelul rămas gol poate fi acoperit într-un singur mod de un nou domino, aşa cum ne arată dominoul haşurat. Numim <tex> A[n] </tex> numărul de moduri în care poate fi acoperit un dreptunghi de dimensiune $3 x n$ de dominouri, şi <tex> B[n] </tex> numărul de moduri în care putem acoperi un dreptunghi de $3 x n$ dominouri la care se mai lipeşte pe margine un domino vertical aşa cum vedem în figura următoare.\r\n\r\np=. !probleme-de-acoperire?P62.jpg!\r\n\r\nPutem observa uşor că <tex> A[2n + 2] = 3A[2n] + 2B[2n - 2] </tex>, iar <tex> B[2n] = A[2n] + B[2n - 2] </tex>. Aceste două recurenţe ar fi fost de ajuns pentru a rezolva problema în concurs. În cartea [3] rezolvarea continuă pentru a determina un număr explicit: <tex> A[2n + 2] = 3 A[2n] + 2A[2n - 2] + 2B[2n - 4] </tex> (am înlocuit pe <tex> B[2n - 2] </tex>). Mai departe obţinem <tex> A[2n + 2] = 4 A[2n] - A[2n - 2] </tex>. Putem uşor afla că <tex> A[2] = 3 </tex> şi <tex> A[4] = 11 </tex>. Ecuaţia caracteristică a ecuaţiei liniare este <tex> X^{2} - 4X + 1 = 0 </tex>, iar de aici obţinem că <tex> A[2n] = 1/{2\\sqrt{3}} * ((\\sqrt{3} + 1) * (2 + \\sqrt{3})^{n} + (\\sqrt{3} - 1) * (2 - \\sqrt{3})^{n}) </tex>. (metoda rezolvării recurenţelor liniare este prezentată în manualul de clasa a 11-a de matematică). Un astfel de răspuns nu ne prea ajută pe noi ca programatori pentru că ar trebui să putem efectua operaţii cu numere reale cu o precizie destul de mare pentru a ajunge la rezultatul dorit. Totuşi, faptul că am găsit o recurenţa lineară ne ajută să determinăm mult mai repede numărul de posibilităţi folosindu-ne de următorul raţionament:\r\n\r\nDacă avem o recurenţa <tex> X[n] = aX[n - 1] + bX[n - 2] </tex> atunci avem că:\r\n\r\n<tex>\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\na & b \\\\\r\n1 & 0 \\end{array} \\right)\\]\r\n\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\nX[n - 1] \\\\\r\nX[n - 2] \\end{array} \\right)\\]  </tex>\r\n\r\n<tex> = </tex>\r\n\r\n<tex>\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\nX[n] \\\\\r\nX[n - 1] \\end{array} \\right)\\]  </tex>\r\n\r\n<tex> \\Leftrightarrow </tex>\r\n\r\n<tex>\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\na & b \\\\\r\n1 & 0 \\end{array} \\right)\\]^{(n-1)}\r\n\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\nX[1] \\\\\r\nX[0] \\end{array} \\right)\\]  </tex>\r\n\r\n<tex> = </tex>\r\n\r\n<tex>\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\nX[n] \\\\\r\nX[n - 1] \\end{array} \\right)\\]  </tex>\r\n\r\nIar cum o matrice o putem ridica la o putere în număr logaritmic de paşi, putem afla <tex> X[n] </tex> mult mai repede.\r\n\r\nh2(#prob7). Problema 7 ( _ACM ICPC 1997_ )\r\n\r\nbq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $N x M (N <= 20, M <= 20)$ cu dominouri.\r\n\r\nh3. Soluţie:\r\n\r\nPoate părea surprinzător, dar pentru această problemă, deşi pare foarte grea, există o formulă: <tex> {2}^{\\frac{M*N}{2}} * {(\\cos^{2}\\frac{m*pi}{M+1} + cos^{2}\\frac{n*pi}{N+1})}^{\\frac{1}{4}} </tex> pentru $0 < m < M+1, 0 < n < N+1$. Şi mai surprinzător este că această expresie ce conţine numere iraţionale are ca rezultat un număr întreg. Pentru o demonstraţie a acestei formule puteţi să intraţi pe adresa [4]. Ar fi anormal ca să ştim o asemenea formulă pe de rost în speranţa că vom primi problema la vreun concurs. Dimensiunile mici ale problemei o făceau abordabilă printr-un algoritm ce combină $programarea dinamică$ cu $backtrackingul$ pe care îl vom prezenta în numărul următor.\r\n\r\nh2(#prob8). Problema 8 ( _Lot matematică 2001, acm.uva.es - 10644 Floor tiles_ )\r\n\r\nbq. Se dă un dreptunghi de dimensiuni $M x N$, să se determine dacă el se poate acoperi cu piese de forma:\r\n\r\np=. !probleme-de-acoperire?OlimpBuc1.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nSă considerăm pe rând:\r\n\r\n* Tablele de $2 x n$ le putem acoperi doar dacă $n$ este multiplu de $3$, pentru că aria dreptunghiului trebuie să fie multiplu de $3$.\r\n* Tablele de $3 x n$ le putem acoperi doar dacă $n$ este par, pentru că suntem obligaţi să acoperim dreptunghiul cu dreptunghiuri verticale de dimensiuni $2 x 3$.\r\n* Tablele de $4 x n$ le putem acoperi doar dacă $n$ este multiplu de $3$, şi putem face acest lucru folosind dreptunghiuri de $2 x 3$.\r\n* Tabla de $5 x 3$ nu poate fi acoperită după cum am văzut la tablele de $3 x n$. \r\n* Tabla de $5 x 6$ poate fi acoperită cu dreptunghiuri de $2 x 3$ aşa cum vedem în figură. \r\n\r\np=. !probleme-de-acoperire?P81.jpg!\r\n\r\n* Pentru tabla de $5 x 9$ este uşor să determinăm o acoperire de mână, una găsită de autor apare în figură. Menţionăm că tabla de $5 x 9$ este cea mai mică tablă de dimensiuni impare pe care o putem acoperi complet. Putem acoperi table de dimensiuni $5 x n$ cand $n$ e multiplu de $3$ şi e diferit de $3$({$n = 9 + 6k$} sau $n = 6 + 6k$ unde $k >= 0$ deci adăugăm la o soluţie de $5 x (n – 6)$ un dreptunghi de dimensiuni $5 x 6$).\r\n\r\np=. !probleme-de-acoperire?P82.jpg!\r\n\r\n* Pentru cazul general $M x N$, presupunem fără a reduce generalizarea că $N$ e multiplu de $3$. Pentru $M <= 5$ problema e deja rezolvată. Să vedem acum rezolvarea pentru $M > 5$: dacă $M$ e par atunci putem obţine uşor o soluţie folosind dreptunghiuri de dimensiune $2 x 3$, iar dacă $M$ e impar atunci obţinem întâi o soluţie pentru $(M – 2) x N$ la care adăugăm o bandă de dimensiune $2 x N$ formată din dreptunghiuri $2 x 3$.\r\n\r\nh2(#prob9). Problema 9\r\n\r\nbq. Pentru un dreptunghi de dimensiuni $N x M$ să se determine o acoperire cu dominouri a lui astfel încât să nu existe vreo linie verticală sau orizontală care să taie dreptunghiul în două fără să intersecteze vreun domino.\r\n\r\nh3. Soluţie:\r\n\r\nÎn figura următoare avem o soluţie greşită:\r\n\r\np=. !probleme-de-acoperire?P91.jpg!\r\n\r\nEste evident că pentru dreptunghiuri de dimensiuni $2 x N$, $3 x N$ şi $4 x N$ nu există soluţie. Pentru $5 x 6$ şi $6 x 8$ este foarte uşor să găsim o soluţie de mână; avem o solutie pentru $5 x 6$ în următoarea figură. Pentru $6 x 6$ nu există soluţie. Pentru aceasta putem folosi o demonstraţie matematică care se găseşte în [6] sau putem folosi un algoritm de tip backtracking pentru a ne asigura că nu există vreo soluţie.\r\n\r\np=. !probleme-de-acoperire?P92.jpg!\r\n\r\nUn dreptunghi de dimensiune $N x M$ îl putem mări la unul de dimensiune $(N + 2) x M$ folosind procedeul prezentat în ultima figură.\r\n\r\np=. !probleme-de-acoperire?P93.jpg!\r\n\r\nh2(#concl). Concluzii\r\n\r\nAcest articol a pus accentul mai mult asupra gândirii matematice în problemele de acoperire. În articolul următor vom încerca o abordare orientată spre algoritmică.\r\n\r\nh2(#biblio). Bibliografie\r\n\r\n* [1] Mircea Ganga, Teme şi probleme de matematică, ed.tehnică, Bucuresti, 1991\r\n* [2] Valentin Vornicu, Olimpiada de matematică de la provocare la experienţa, ed. Gil, 2003\r\n* [3] Ioan Tomescu, Probleme de combinatorică şi teoria grafurilor, ed. Didactică şi pedagogică, 1981\r\n* [4] http://rec-puzzles.org/new/sol.pl/geometry/tiling/count.1x2\r\n* [5] Romanian mathematical competitions 2001, ed Theta, Bucureşti 2001\r\n* [6] Probleme de matematică traduse din revista sovietica KVANT, ed didactică şi pedagogică, Bucureşti, 1983',3146,'public',NULL,NULL),('probleme-de-acoperire-1','Probleme de acoperire','2008-11-14 08:56:52','2008-11-17 21:15:09','h1. Probleme de acoperire\r\n\r\n(Categoria _Algoritmi_, autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 33em}*{text-align:left} *Cuprins:*\r\n* \'Problema 1 ( _Olimpiada de informatică, Bucureşti, etapa pe sector, 1995,_ [1] ) \':probleme-de-acoperire#prob1\r\n* \'Problema 2 ( _Lot 2001,_ [1] ) \':probleme-de-acoperire#prob2\r\n* \'Problema 3 ( _Concursul naţional de informatică Lugoj, 1998_ ) \':probleme-de-acoperire#prob3\r\n* \'Problema 4\':probleme-de-acoperire#prob4\r\n* \'Problema 5\':probleme-de-acoperire#prob5\r\n* \'Problema 6 ( _ONI 2001, clasa a X-a,_ [3] ) \':probleme-de-acoperire#prob6\r\n* \'Problema 7 ( _ACM ICPC 1997_ ) \':probleme-de-acoperire#prob7\r\n* \'Problema 8 ( _Lot matematică 2001, acm.uva.es - 10644 Floor tiles_ ) \':probleme-de-acoperire#prob8\r\n* \'Problema 9\':probleme-de-acoperire#prob9\r\n* \'Concluzii\':probleme-de-acoperire#concl\r\n* \'Bibliografie\':probleme-de-acoperire#biblio\r\n\r\nÎn acest prim articol vom prezenta o serie de probleme apărute la concursurile de programare care au o tematică similară şi anume aceea de acoperire în plan. În general acest tip de probleme sunt $NP complete$, dar pentru cazurile particulare prezentate problemele sunt rezolvabile. Cea de a doua parte a articolului o puteţi găsi în \"secţiunea următoare...\":probleme-de-acoperire2.\r\n\r\nh2(#prob1). Problema 1 ( _Olimpiada de informatică, Bucureşti, etapa pe sector, 1995,_ [1] )\r\n\r\nbq. Se dă un pătrat de latură $2^n^$ care se împarte în pătrate disjuncte de latură $1$. Unul dintre aceste pătrate se elimină. Se cere acoperirea suprafeţei rămase cu piese de forma: \r\n\r\np=. !probleme-de-acoperire?OlimpBuc1.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nPrima întrebare care ne vine în minte este dacă aria ce trebuie acoperită este divizibilă cu $3$. Aria este $4^n^ – 1 = (4 – 1)(4^n-1^ + 4^n-2^ + … + 4 + 1)$, deci este multiplu de $3$. Să trecem acum la ideea rezolvării.\r\n\r\nÎmpărţim pătratul în $4$ pătrate de dimensiuni egale. Unul dintre ele are un pătrat lipsă. Facem ca celelalte trei pătrate să aibă şi ele un pătrat lipsă prin plasarea unei piese care să acopere câte un colţ al fiecăruia dintre cele trei pătrate rămase, după cum observăm în figură.\r\n\r\np=. !probleme-de-acoperire?OlimpBuc2.jpg!\r\n\r\nAstfel am redus problema la patru noi probleme de dimensiuni mai mici.\r\n\r\np=. !probleme-de-acoperire?OlimpBuc3.jpg!\r\n\r\nSe vede clar acum, cum prin metoda $divide et impera$ putem să acoperim întreg pătratul cu piesele cerute.\r\n\r\nh2(#prob2). Problema 2 ( _Lot 2001,_ [1] )\r\n\r\nbq. Se dă un pătrat de latură $6N + 1$ care se împarte în pătrate disjuncte de latură $1$. Unul dintre aceste pătrate se elimină. Se cere acoperirea suprafeţei rămase cu piese de forma:\r\n\r\np=. !probleme-de-acoperire?OlimpBuc1.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nSă vedem întâi cum rezolvăm cazul minim în care $N = 1$.\r\n\r\np=. !probleme-de-acoperire?P21.JPG!\r\n\r\nÎn aceste trei figuri am epuizat toate cazurile pentru table de dimensiune $7$ unde lipseşte un pătrat. În fiecare desen am lăsat un pătrat de latură doi liber pentru a trata astfel cele patru cazuri în care pătrăţelul lipsă ar face parte din acest pătrat. Recurgând şi la rotaţiile acestor soluţii acoperim toate cazurile posibile pentru pătrăţelul lipsă. Menţionăm că cele trei soluţii au fost găsite cu uşurinţă de mână de autor.\r\n\r\nSă presupunem că ştim cum să acoperim un pătrat de latură $6N + 1$. Să vedem acum cum acoperim un pătrat de latură $6N + 7$. În acest nou pătrat putem plasa într-un colţ de al lui un pătrat de latură $6N + 1$, care are un pătrăţel lipsă. Pătratul acesta îl ştim acoperi şi după cum arată şi figura următoare ne mai rămâne să acoperim două dreptunghiuri de dimensiuni $6 x 6n$, respectiv $6n x 6$ şi un pătrat de latură $7$ cu patrăţelul din colţ lipsă. Dreptunghiurile le putem acoperi cu dreptunghiuri de dimensiuni $2 x 3$ formate din câte două piese, iar pătratul de $7 x 7$ cu un colţ lipsă este un caz pentru $N = 1$ al problemei noastre.\r\n\r\np=. !probleme-de-acoperire?P22.jpg! \r\n\r\nh2(#prob3). Problema 3 ( _Concursul naţional de informatică Lugoj, 1998_ )\r\n\r\nbq. Să se acopere complet un pătrat de latură $N >= 6$ cu următoarele piese, astfel ca fiecare piesă să fie folosită cel puţin o dată.\r\n\r\np=. !probleme-de-acoperire?P31doi.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nObservăm că fiecare piesă este formată din patru pătrăţele. De aici deducem că $N^2^$ este multiplu de $4$ deci $N$ e multiplu de $2$. Pentru $N = 6$ avem următoarea soluţie:\r\n\r\np=. !probleme-de-acoperire?P32.jpg!\r\n\r\nPentru $N > 6$ putem împărţi pătratul într-un pătrat de latură $6$ şi două dreptunghiuri de dimensiuni $6 x (N – 6)$ şi $(N – 6) x N$, după cum observăm în figura următoare. Dreptunghiurile pot fi acoperite cu piese de tip $3$.\r\n\r\np=. !probleme-de-acoperire?P33.jpg!\r\n\r\nh2(#prob4). Problema 4\r\n\r\nbq. Să se determine dacă putem acoperi o tablă de dimensiune $N x N$ cu dominouri după ce îi eliminăm două colţuri opuse.\r\n\r\nh3. Soluţie:\r\n\r\nPrima observaţie pe care o facem este aceea că $N$ trebuie să fie par pentru ca tabla să poată fi acoperită. Este evident pentru cazurile $N = 2$ sau $N = 4$ că problema nu are soluţie, dar pentru cazuri mai mari demonstraţia faptului că există sau nu există soluţie pare dificilă, şi valorile lui $N$ pentru care o abordare exhaustivă a posibilităţilor de  acoperire a tablei cu dominouri ar fi eficientă sunt destul de mici. \r\n\r\nO idee interesantă este aceea de a colora pătratele tablei în acelaşi mod în care se colorează o tablă de şah, aşa cum vedem în figura următoare. \r\n\r\np=. !probleme-de-acoperire?P41.jpg!\r\n\r\nOrice domino amplasat pe tablă va acoperi două pătrăţele de culori diferite, deci tabla trebuie să aibă un număr egal de pătrăţele colorate alb şi negru, fapt care nu se întâmplă în problema noastră. De aici deducem că nu putem acoperi tabla din care au fost eliminate două colţuri opuse. O problemă ce se poate aborda cu o tehnică asemănătoare este următoarea: „Se dă un dreptunghi de dimensiuni $7 x 10$. Din colţurile lui scoatem câte un pătrat de latură $1$. Să se arate că figura rămasă nu poate fi pardosită cu dreptunghiuri de laturi $3$ şi $1$. Pentru probleme de acelaşi gen şi soluţia la această problemă puteţi să consultaţi în [1] secţiunea 1.1 $Invariant$, sau în [2] secţiunea $Probleme de colorare şi acoperire$. Problema în care eliminăm două pătrate de aceiaşi culoare sau chiar cazul generalizat în care eliminăm un număr mai mare de pătrăţele o vom discuta în numărul viitor.\r\n\r\nh2(#prob5). Problema 5\r\n\r\nbq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $2 x N$ cu dominouri.\r\n\r\nh3. Soluţie:\r\n\r\nPentru $N = 1$ avem o posibilitate, pentru $N = 2$ avem două posibilităţi, iar în cazul general daca notăm cu <tex> F[n] </tex> numărul de posibilităţi avem, aşa cum putem observa şi din figură, <tex> F[n] = F[n - 1] + F[n - 2] </tex>, deci exact şirul lui Fibonacci.\r\n\r\np=. !probleme-de-acoperire?P51.jpg!\r\n\r\nh2(#prob6). Problema 6 ( _ONI 2001, clasa a X-a,_ [3] )\r\n\r\nbq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $3 x N$ cu dominouri.\r\n\r\nh3. Soluţie:\r\n\r\nŞi în această problemă $N$ trebuie să fie par pentru ca tabla să poată fi acoperită. Avem următoarele posibilităţi la început:\r\n\r\np=. !probleme-de-acoperire?P61.jpg!\r\n\r\nObservăm că în ultimele două cazuri pătrăţelul rămas gol poate fi acoperit într-un singur mod de un nou domino, aşa cum ne arată dominoul haşurat. Numim <tex> A[n] </tex> numărul de moduri în care poate fi acoperit un dreptunghi de dimensiune $3 x n$ de dominouri, şi <tex> B[n] </tex> numărul de moduri în care putem acoperi un dreptunghi de $3 x n$ dominouri la care se mai lipeşte pe margine un domino vertical aşa cum vedem în figura următoare.\r\n\r\np=. !probleme-de-acoperire?P62.jpg!\r\n\r\nPutem observa uşor că <tex> A[2n + 2] = 3A[2n] + 2B[2n - 2] </tex>, iar <tex> B[2n] = A[2n] + B[2n - 2] </tex>. Aceste două recurenţe ar fi fost de ajuns pentru a rezolva problema în concurs. În cartea [3] rezolvarea continuă pentru a determina un număr explicit: <tex> A[2n + 2] = 3 A[2n] + 2A[2n - 2] + 2B[2n - 4] </tex> (am înlocuit pe <tex> B[2n - 2] </tex>). Mai departe obţinem <tex> A[2n + 2] = 4 A[2n] - A[2n - 2] </tex>. Putem uşor afla că <tex> A[2] = 3 </tex> şi <tex> A[4] = 11 </tex>. Ecuaţia caracteristică a ecuaţiei liniare este <tex> X^{2} - 4X + 1 = 0 </tex>, iar de aici obţinem că <tex> A[2n] = 1/{2\\sqrt{3}} * ((\\sqrt{3} + 1) * (2 + \\sqrt{3})^{n} + (\\sqrt{3} - 1) * (2 - \\sqrt{3})^{n}) </tex>. (metoda rezolvării recurenţelor liniare este prezentată în manualul de clasa a 11-a de matematică). Un astfel de răspuns nu ne prea ajută pe noi ca programatori pentru că ar trebui să putem efectua operaţii cu numere reale cu o precizie destul de mare pentru a ajunge la rezultatul dorit. Totuşi, faptul că am găsit o recurenţa lineară ne ajută să determinăm mult mai repede numărul de posibilităţi folosindu-ne de următorul raţionament:\r\n\r\nDacă avem o recurenţa <tex> X[n] = aX[n - 1] + bX[n - 2] </tex> atunci avem că:\r\n\r\n<tex>\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\na & b \\\\\r\n1 & 0 \\end{array} \\right)\\]\r\n\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\nX[n - 1] \\\\\r\nX[n - 2] \\end{array} \\right)\\]  </tex>\r\n\r\n<tex> = </tex>\r\n\r\n<tex>\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\nX[n] \\\\\r\nX[n - 1] \\end{array} \\right)\\]  </tex>\r\n\r\n<tex> \\Leftrightarrow </tex>\r\n\r\n<tex>\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\na & b \\\\\r\n1 & 0 \\end{array} \\right)\\]^{(n-1)}\r\n\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\nX[1] \\\\\r\nX[0] \\end{array} \\right)\\]  </tex>\r\n\r\n<tex> = </tex>\r\n\r\n<tex>\r\n\\emph{}\r\n\\[ \\left( \\begin{array}{ccc}\r\nX[n] \\\\\r\nX[n - 1] \\end{array} \\right)\\]  </tex>\r\n\r\nIar cum o matrice o putem ridica la o putere în număr logaritmic de paşi, putem afla <tex> X[n] </tex> mult mai repede.\r\n\r\nh2(#prob7). Problema 7 ( _ACM ICPC 1997_ )\r\n\r\nbq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $N x M (N <= 20, M <= 20)$ cu dominouri.\r\n\r\nh3. Soluţie:\r\n\r\nPoate părea surprinzător, dar pentru această problemă, deşi pare foarte grea, există o formulă: <tex> {2}^{\\frac{M*N}{2}} * {(\\cos^{2}\\frac{m*pi}{M+1} + cos^{2}\\frac{n*pi}{N+1})}^{\\frac{1}{4}} </tex> pentru $0 < m < M+1, 0 < n < N+1$. Şi mai surprinzător este că această expresie ce conţine numere iraţionale are ca rezultat un număr întreg. Pentru o demonstraţie a acestei formule puteţi să intraţi pe adresa [4]. Ar fi anormal ca să ştim o asemenea formulă pe de rost în speranţa că vom primi problema la vreun concurs. Dimensiunile mici ale problemei o făceau abordabilă printr-un algoritm ce combină $programarea dinamică$ cu $backtrackingul$ pe care îl vom prezenta în numărul următor.\r\n\r\nh2(#prob8). Problema 8 ( _Lot matematică 2001, acm.uva.es - 10644 Floor tiles_ )\r\n\r\nbq. Se dă un dreptunghi de dimensiuni $M x N$, să se determine dacă el se poate acoperi cu piese de forma:\r\n\r\np=. !probleme-de-acoperire?OlimpBuc1.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nSă considerăm pe rând:\r\n\r\n* Tablele de $2 x n$ le putem acoperi doar dacă $n$ este multiplu de $3$, pentru că aria dreptunghiului trebuie să fie multiplu de $3$.\r\n* Tablele de $3 x n$ le putem acoperi doar dacă $n$ este par, pentru că suntem obligaţi să acoperim dreptunghiul cu dreptunghiuri verticale de dimensiuni $2 x 3$.\r\n* Tablele de $4 x n$ le putem acoperi doar dacă $n$ este multiplu de $3$, şi putem face acest lucru folosind dreptunghiuri de $2 x 3$.\r\n* Tabla de $5 x 3$ nu poate fi acoperită după cum am văzut la tablele de $3 x n$. \r\n* Tabla de $5 x 6$ poate fi acoperită cu dreptunghiuri de $2 x 3$ aşa cum vedem în figură. \r\n\r\np=. !probleme-de-acoperire?P81.jpg!\r\n\r\n* Pentru tabla de $5 x 9$ este uşor să determinăm o acoperire de mână, una găsită de autor apare în figură. Menţionăm că tabla de $5 x 9$ este cea mai mică tablă de dimensiuni impare pe care o putem acoperi complet. Putem acoperi table de dimensiuni $5 x n$ cand $n$ e multiplu de $3$ şi e diferit de $3$({$n = 9 + 6k$} sau $n = 6 + 6k$ unde $k >= 0$ deci adăugăm la o soluţie de $5 x (n – 6)$ un dreptunghi de dimensiuni $5 x 6$).\r\n\r\np=. !probleme-de-acoperire?P82.jpg!\r\n\r\n* Pentru cazul general $M x N$, presupunem fără a reduce generalizarea că $N$ e multiplu de $3$. Pentru $M <= 5$ problema e deja rezolvată. Să vedem acum rezolvarea pentru $M > 5$: dacă $M$ e par atunci putem obţine uşor o soluţie folosind dreptunghiuri de dimensiune $2 x 3$, iar dacă $M$ e impar atunci obţinem întâi o soluţie pentru $(M – 2) x N$ la care adăugăm o bandă de dimensiune $2 x N$ formată din dreptunghiuri $2 x 3$.\r\n\r\nh2(#prob9). Problema 9\r\n\r\nbq. Pentru un dreptunghi de dimensiuni $N x M$ să se determine o acoperire cu dominouri a lui astfel încât să nu existe vreo linie verticală sau orizontală care să taie dreptunghiul în două fără să intersecteze vreun domino.\r\n\r\nh3. Soluţie:\r\n\r\nÎn figura următoare avem o soluţie greşită:\r\n\r\np=. !probleme-de-acoperire?P91.jpg!\r\n\r\nEste evident că pentru dreptunghiuri de dimensiuni $2 x N$, $3 x N$ şi $4 x N$ nu există soluţie. Pentru $5 x 6$ şi $6 x 8$ este foarte uşor să găsim o soluţie de mână; avem o solutie pentru $5 x 6$ în următoarea figură. Pentru $6 x 6$ nu există soluţie. Pentru aceasta putem folosi o demonstraţie matematică care se găseşte în [6] sau putem folosi un algoritm de tip backtracking pentru a ne asigura că nu există vreo soluţie.\r\n\r\np=. !probleme-de-acoperire?P92.jpg!\r\n\r\nUn dreptunghi de dimensiune $N x M$ îl putem mări la unul de dimensiune $(N + 2) x M$ folosind procedeul prezentat în ultima figură.\r\n\r\np=. !probleme-de-acoperire?P93.jpg!\r\n\r\nh2(#concl). Concluzii\r\n\r\nAcest articol a pus accentul mai mult asupra gândirii matematice în problemele de acoperire. În articolul următor vom încerca o abordare orientată spre algoritmică.\r\n\r\nh2(#biblio). Bibliografie\r\n\r\n* [1] Mircea Ganga, Teme şi probleme de matematică, ed.tehnică, Bucuresti, 1991\r\n* [2] Valentin Vornicu, Olimpiada de matematică de la provocare la experienţa, ed. Gil, 2003\r\n* [3] Ioan Tomescu, Probleme de combinatorică şi teoria grafurilor, ed. Didactică şi pedagogică, 1981\r\n* [4] http://rec-puzzles.org/new/sol.pl/geometry/tiling/count.1x2\r\n* [5] Romanian mathematical competitions 2001, ed Theta, Bucureşti 2001\r\n* [6] Probleme de matematică traduse din revista sovietica KVANT, ed didactică şi pedagogică, Bucureşti, 1983',3146,'public',NULL,NULL),('schimbare-borland','Schimbarea compilatoarelor Borland la OJI','2008-10-22 10:18:36','2008-11-14 18:12:28','h1. Schimbarea compilatoarelor Borland la OJI\r\n\r\nh2. Despre ce e vorba\r\n\r\n* \'Argumentatia\':schimbare-borland/argumentatie\r\n* \'Alternative\':schimbare-borland/alternativa\r\n* \'Ghid MinGW Developer Studio\':schimbare-borland/ghid\r\n* \'Ghid FreePascal\':schimbare-borland/ghid-freepascal\r\n* \'Pachet\':schimbare-borland/pachet\r\n\r\nh2. Altele\r\n\r\n* \'Jurnal de lucru\':schimbare-borland/jurnal',1,'public',NULL,NULL),('blog/harta-politicii','Senatorii si Deputatii lucreaza part time','2008-11-18 06:04:08','2008-11-18 06:04:08','!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/harta-politicii?badge_hpol_150x100.png! \'Vivi\':http://vivi.ro/blog recidiveaza. Dupa ce a facut o gramada de siteuri, printre care doizece.ro cel mai mare site de jocuri din Romania sau initiativa cu harta publicitatii acum are un nou proiect personal interesant la care lucreaza. Acesta este \'harta politicii din Romania\':http://vivi.ro/politica in care a agregat date legate de prezenta si legile votate de senatori si deputati. Concluzia in mare e ca prezenta la vot e penibila si ca senatorii si deputatii lucreaza part time. Puteti vedea datele stranse de el \'aici\':http://vivi.ro/politica si posturi care analizeaza putin datele \'aici\':http://www.vivi.ro/blog/?p=1015 , \'aici\':http://www.vivi.ro/blog/?p=1080 , \'aici\':http://www.vivi.ro/blog/?p=1099  si \'aici\':http://www.vivi.ro/blog/?p=1128 . Ideea proiectului e misto si e o modalitate obiectiva de a prezenta niste date, fara a cobora la nivelul scandalurilor de presa.\r\n\r\nIn contextul in care in postul anterior vorbeam despre DEX online ce a inceput ca un proiect personal, avem inca un exemplu cu ce poate face un programator. Noi avem capacitatea colectam date, sa le analizam si sa le prezentam in o forma in care pot fi intelese foarte usor. Ar fi misto sa apara multe initiative de genul asta, pornite poate chiar de la membrii infoarena.',58,'private',NULL,NULL),('blog/harta-politicii','Senatorii si Deputatii lucreaza part time','2008-11-18 06:04:08','2008-11-18 06:04:42','!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/harta-politicii?badge_hpol_150x100.png! \'Vivi\':http://vivi.ro/blog recidiveaza. Dupa ce a facut o gramada de siteuri, printre care doizece.ro cel mai mare site de jocuri din Romania sau initiativa cu harta publicitatii acum are un nou proiect personal interesant la care lucreaza. Acesta este \'harta politicii din Romania\':http://vivi.ro/politica in care a agregat date legate de prezenta si legile votate de senatori si deputati. Concluzia in mare e ca prezenta la vot e penibila si ca senatorii si deputatii lucreaza part time!\r\n\r\nPuteti vedea datele stranse de el \'aici\':http://vivi.ro/politica si posturi care analizeaza putin datele \'aici\':http://www.vivi.ro/blog/?p=1015 , \'aici\':http://www.vivi.ro/blog/?p=1080 , \'aici\':http://www.vivi.ro/blog/?p=1099  si \'aici\':http://www.vivi.ro/blog/?p=1128 . Ideea proiectului e misto si e o modalitate obiectiva de a prezenta niste date, fara a cobora la nivelul scandalurilor de presa.\r\n\r\nIn contextul in care in postul anterior vorbeam despre DEX online ce a inceput ca un proiect personal, avem inca un exemplu cu ce poate face un programator. Noi avem capacitatea colectam date, sa le analizam si sa le prezentam in o forma in care pot fi intelese foarte usor. Ar fi misto sa apara multe initiative de genul asta, pornite poate chiar de la membrii infoarena.',58,'private',NULL,NULL),('implica-te/scrie-articole','Scrie articole','2007-03-28 22:23:46','2008-11-14 20:07:19','h1. Scrie articole ==Stars(rating=\"4\")==\r\n\r\nFolosind modelul de \'wiki\':documentatie/wiki, infoarena ofera sansa tuturor membrilor sai sa contribuie la realizarea de articole sau la imbunatatirea celor existente. Daca vrei sa afli mai multe despre conceptul de wiki intra \'aici\':http://en.wikipedia.org/wiki/Wiki, iar daca vrei sa contribui la acesta initiativa citeste mai jos ce trebuie sa faci.\r\n\r\nh2. De ce m-as baga?\r\n\r\n* O cariera in cercetare in informatica poate debuta cu niste articole online!\r\n* Vei invata care sunt elementele cheie pentru a scrie un articol.\r\n* Vei invata pe altii ceea ce stii, asa cum probabil si tu ai invatat din articolele deja \'existente\':articole.\r\n\r\nh2. Ce pot sa fac?\r\n\r\nDe-a lungul timpului, utilizatorii infoarena si-au manifestat interesul in a scrie articole pentru intreaga comunitate. In momentul de fata ne concentram eforturile atat pe completarea si aducerea la o forma prezentabila a acestor articole vechi, cat si pe scrierea de articole noi. Sunt 3 moduri in care poti contribui:\r\n\r\nh3. 1. Ajuta-ne la ce lucram acum\r\n\r\nIn tabelul de mai jos poti gasi articolele incepute, impreuna cu stadiul in care se gaseste fiecare. Daca esti dornic sa ne ajuti, alege-ti unul din articolele de care nu se ocupa nimeni si ia legatura cu coordonatorul proiectului ca sa afli ce mai e de facut la el.\r\n\r\ntable. |_. Titlu |_. Autor |_. Stadiu |_. Voluntar(i) |_. Data finalizarii |\r\n| \'Flux si cuplaj\':flux-si-cuplaj | ==user(user=\"blasterz\" type=\"tiny\")== | IN LUCRU | ==user(user=\"blasterz\" type=\"tiny\")== | ? |\r\n| \'Teoria jocurilor\':teoria-jocurilor | ==user(user=\"filipb\" type=\"tiny\")== | IN LUCRU | ==user(user=\"filipb\" type=\"tiny\")== | ? |\r\n| \'Treap-uri\':treapuri | ==user(user=\"Marius\" type=\"tiny\")== | IN_LUCRU | ==user(user=\"Marius\" type=\"tiny\")== | ? |\r\n| \'Psihologia concursurilor de informatica - Concursul de informatica\':concursul-de-informatica | ==user(user=\"cata00\" type=\"tiny\")== | IMBUNATATIRE CONTINUT | ? | ? |\r\n| \'Psihologia concursurilor de informatica - Lucrul cu numere mari\':lucrul-cu-nr-mari | ==user(user=\"cata00\" type=\"tiny\")== | IMBUNATATIRE CONTINUT | ? | ? |\r\n| Psihologia concursurilor de informatica - Lucrul cu structuri mari de date | ==user(user=\"cata00\" type=\"tiny\")== | NETRANSCRIS | ? | ? |\r\n| Psihologia concursurilor de informatica - \'Heap-uri\':heapuri si \'tabele de dispersie\':tabele-hash-prezentare-detaliata | ==user(user=\"cata00\" type=\"tiny\")== | IMBUNATATIRE CONTINUT | ? | ? |\r\n| Psihologia concursurilor de informatica - Probleme de concurs | ==user(user=\"cata00\" type=\"tiny\")== | NETRANSCRIS | ? | ? |\r\n| \'Problema satisfiabilitatii formulelor logice de ordinul doi\':downloads?action=download&file=2SAT.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | NETRANSCRIS | ? | ? |\r\n| \'Probleme de acoperire\':probleme-de-acoperire | ==user(user=\"Cosmin\" type=\"tiny\")== | IMBUNATATIRE CONTINUT | ==user(user=\"Marius\" type=\"tiny\")== | 21-11-2008 |\r\n| \'Probleme cu puncte laticeale\':downloads?action=download&file=puncte_laticeale.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | NETRANSCRIS | ? | ? |\r\n| \'Probleme cu secvente\':downloads?action=download&file=secvente.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | NETRANSCRIS | ? | ? |\r\n| \'Teoria jocurilor: numerele Sprague Grundy\':downloads?action=download&file=SpragueGrundy.pdf | ==user(user=\"Cosmin\" type=\"tiny\")== | NETRANSCRIS | ? | ? |\r\n| \'Probleme de taietura\':downloads?action=download&file=taietura.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | NETRANSCRIS | ? | ? |\r\n| \'Transformari geometrice\':downloads?action=download&file=transformari_geometrice.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | NETRANSCRIS | ? | ? |\r\n| \'Problema majoritatii votului\':downloads?action=download&file=problema_majoritatii.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | NETRANSCRIS | ? | ? |\r\n\r\nh3. 2. Preia si dezvolta un subiect mai vechi\r\n\r\nAi nevoie de un impuls pentru a-ti da drumul la scris? Sunt cateva articole pe infoarena incepute, dar abandonate, precum si niste schite. Poti folosi ideile de start ale autorului si il poti transforma intr-un articol bine documentat. In plus, poti lua legatura cu autorul initial si poti afla viziunea sa asupra subiectului. Iata o lista de articole abandonate si de schite:\r\n\r\ntable. |_. Titlu |_. Autor initial |\r\n| \'Probleme de geometrie si solutii\':downloads?geometrie.zip | ==user(user=\"Cosmin\" type=\"tiny\")== |\r\n| \'Diagrame Voronoi\':voronoi | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| \'Algoritmi de baleiere\':algoritmi-de-baleiere | ==user(user=\"stef2n\" type=\"tiny\")== |\r\n\r\nh3. 3. Creeaza ceva nou\r\n\r\nAi o idee noua de articol? Sau pur si simplu vrei sa te apuci de la 0 de un subiect? Ia legatura cu coordonatorul proiectului sau anunta pe \'forum\':forum. Este posibil sa primesti ajutor si de la alti utilizatori infoarena. In plus, noi iti propunem o lista de articole pe care ni le-am dori scrise, in caz ca nu te-ai decis asupra temei:\r\n\r\ntable. |_. Titlu |\r\n| Deque si aplicatii |\r\n| Depanarea programelor C/C++ cu gdb in Linux |\r\n| Testarea surselor in timp de concurs sau Cum sa reduci buselile |\r\n| Tutorial LaTeX |\r\n\r\nNe rezervam dreptul sa nu acceptam sau sa stergem articolele care nu se potrivesc cu tema si target-ul site-ului.\r\n\r\nh2. Cu cine iau legatura?\r\n\r\nCu coordonatorul proiectului:\r\n\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n\r\nSau daca vrei sa contribui la un articol la care se lucreaza deja, poti vorbi direct cu voluntarii care se ocupa de el.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"43\")==\r\n\r\n*TODO*\r\n\r\ntable. |_. Subiect |_. Voluntar(i) |_. Progres |\r\n| Notiuni de geometrie analitica si aplicatii | ==user(user=\"devilkind\" type=\"tiny\")== \r\n==user(user=\"sima_cotizo\" type=\"tiny\")== | \'50%\':notiuni-de-geometrie-si-aplicatii |\r\n| Programare dinamica / memoizare (trading space for time) - introductiv | ==user(user=\"Zeus\" type=\"tiny\")== | 1%, \'link1\':programare-dinamica, \'link2\':pd |\r\n| Programare dinamica / memoizare (trading space for time) - avansat | ==user(user=\"Zeus\" type=\"tiny\")== | 0% |\r\n| Arbori indexati binar | ==user(user=\"Skipy\" type=\"tiny\")== | \'2%\':aib |\r\n| Dinic | ==user(user=\"alexandru.mosoi\" type=\"tiny\")== | \'?%\':dinic |',2044,'public',NULL,NULL),('schimbare-borland/ghid','Scurt ghid pentru folosirea MinGW Developer Studio','2008-11-10 16:02:04','2008-11-13 15:39:26','h1. Scurt ghid pentru folosirea MinGW Developer Studio\r\n\r\n==include(page=\"schimbare-borland/ghid/menu\")==\r\n\r\nMinGW Developer Studio este un mediu de dezvoltare intregrat (Integrated Development Environment, pe scurt IDE) pentru C/C++. Mediul este unul light-weight folosind resurse putine si oferind posibilatea dezvoltarii programelor in mod stabil.\r\n\r\nDesi proiectul a fost abandonat de cativa ani el este intr-o forma stabila si suporta schimbarea compilatorului MinGW (care este in dezvoltare activa) avand astfel posibilitatea mentinerii unui pachet modern, in pas cu standardele C/C++. In plus, compilatorul si debuggerul MinGW (vezi detalii in urmatoarea sectiune) pot fi folosite independent de MinGW Developer Studio impreuna cu un alt editor la alegere.\r\n\r\nh2. Despre MinGW\r\n\r\nMinGW (Minimalist Gnu for Windows) este o colectia gratuita de librarii imbogatind GNU Compliler Collection cu fisiere si librarii specifice Windows. Scopul proiectului initial a fost integrarea facilitatilor oferite de Windows32 in compilatorul gcc si binutils (inclusiv debugger-ul gdb) si portarea acestora pe Windows. Mare parte din codul MinGW este distribuit sub licenta GPL, insa nu in intregime, detalii gasiti \'aici\':http://www.mingw.org/license.',15,'public',NULL,NULL),('schimbare-borland/ghid','Scurt ghid pentru folosirea MinGW Developer Studio','2008-11-10 16:02:04','2008-11-18 20:47:41','h1. Scurt ghid pentru folosirea MinGW Developer Studio\r\n\r\n==include(page=\"schimbare-borland/ghid/menu\")==\r\n\r\nMinGW Developer Studio este un mediu de dezvoltare intregrat (Integrated Development Environment, pe scurt IDE) pentru C/C++. Mediul este unul light-weight folosind resurse putine si oferind posibilatea dezvoltarii programelor in mod stabil.\r\n\r\nDesi proiectul a fost abandonat de cativa ani el este intr-o forma stabila si suporta schimbarea compilatorului MinGW (care este in dezvoltare activa) avand astfel posibilitatea mentinerii unui pachet modern, in pas cu standardele C/C++. In plus, compilatorul si debuggerul MinGW (vezi detalii in urmatoarea sectiune) pot fi folosite independent de MinGW Developer Studio impreuna cu un alt editor la alegere.\r\n\r\nh2. Despre MinGW\r\n\r\nMinGW (Minimalist Gnu for Windows) este o colectia gratuita de librarii imbogatind GNU Compliler Collection cu fisiere si librarii specifice Windows. Scopul proiectului initial a fost integrarea facilitatilor oferite de Windows32 in compilatorul gcc si binutils (inclusiv debugger-ul gdb) si portarea acestora pe Windows. Mare parte din codul MinGW este distribuit sub licenta GPL, insa nu in intregime, detalii gasiti \'aici\':http://www.mingw.org/license.\r\n\r\nh2. Diferente intre compilatoarele BorlandC 3.1 si MinGW 3.3.1\r\n\r\n* Compilatorul MinGW cere in cazul executiei corecte a programului codul 0. Asadar nu se accepta ca **main()** sa fie declarat **void**, este obligatoriu ca sa fie declarat ca **int**. De exemplu:\r\n\r\n== code(cpp) |\r\n#include <iostream.h>\r\n\r\nusing namespace std;\r\n\r\nint main(void) {\r\n    cout << \"acest program compileaza\";\r\n    return 0;\r\n}\r\n==\r\n\r\n* Tipul de date **int** este reprezentat pe 4 bytes, asadar **int** ia valori intre -2147483647 si 2147483647. In BorlandC tipul de date **int** ocupa 2 bytes.\r\n* Exista tipul de date **long long** care este reprezentat pe 8 bytes care ia valori intre -2^62^+1 pana la 2^62^-1. In BorlandC acest tip de date nu exista.\r\n* Pointerii ocupa 4 bytes, astfel incat memoria totala disponibila este de 4 GB, care in anul 2008 inseamna oricat, trebuie totusi sa aveti grija la dimensiunea stivei sistem (aceasta insa poate fi marita usor). In BorlandC pointerii ocupa 2 bytes si memoria disponibila este de 64 KB, folosindu-se modificatorii huge sau far pointeri aveau 4 bytes dar totusi memoria disponibila era limitata la 640 KB.\r\n* MinGW ofera suport pentru \'Standard Template Library\':http://www.sgi.com/tech/stl/. Dintre structurile implementate fac parte vectorii, cozile, stivele, arborii echlibrati, cozile de prioritate, etc; iar dintre algoritmii implementati sunt sortarea, cautarea binara, generarea permutarilor, etc.\r\n',2970,'public',NULL,NULL),('blog/problema-saptamanii-probabilitati-solutie','Problema saptamanii - Probabilitati (solutie)','2008-11-20 08:40:51','2008-11-20 08:53:50','_Problema curenta a fost rezolvat de Ovidiu Ghiorghioiu, Delia David, Andrei Olariu si de Radu Grigore._\r\n\r\nNu exista nici o modalitate prin care sa obtinem rezultate uniform aleatoare folosind un numar finit de aruncari pentru ca se poate intampla ca la orice aruncare a monedei sa obtinem cap la infinit si atunci nu avem cum sa obtinem rezultate diferite.\r\n\r\nSolutiile lui Andrei:\r\n\r\n1. Se arunca moneda de cate 2 ori. Daca pica pajura si apoi cap -> pajura, daca avem cap si apoi pajura -> cap, daca avem 2 rezultate egale, repetam ambele aruncari.\r\n\r\n2. Generam doua numere din multimea {0, 1} folosind metoda de la pct 1. Obtinem 00 -> mar, 01 -> para, 10 -> portocala, 11 -> repetam cele 2 generari.\r\n\r\nPrima problema are mai mult de 50 de ani fiind rezolvata de unul dintre pionierii informaticii, \'John Von Neumann\':http://en.wikipedia.org/wiki/John_von_Neumann#Computer_science\r\n\r\nA doua e interesanta in contextul generatoarelor de numere aleatoare. De exemplu in C++ unii folosim, pentru a genera numere aleatoare de la 0 la n - 1, instructiunile rand() % n. Acum dupa ce ati vazut problema 2 este clar ca unele rezultate sunt mai probabile ca altele.\r\n\r\nIn java sau Python generatoarele aleatoare sunt mai bune.\r\n\r\nVarianta implementata in java:\r\n\r\n== code(c) |\r\n public int nextInt(int n) {\r\n     if (n<=0)\r\n                throw new IllegalArgumentException(\"n must be positive\");\r\n\r\n     if ((n & -n) == n)  // i.e., n is a power of 2\r\n         return (int)((n * (long)next(31)) >> 31);\r\n\r\n     int bits, val;\r\n     do {\r\n         bits = next(31);\r\n         val = bits % n;\r\n     } while(bits - val + (n-1) < 0);\r\n     return val;\r\n }\r\n==\r\n\r\nputeti citi \'aici\':http://java.sun.com/j2se/1.5.0/docs/api/java/util/Random.html#nextInt() explicatia codului.\r\n\r\nO varianta care foloseste ceva mai multe dintre rezultatele aruncarilor pentru prima problema ar fi sa consideram orice rezultate de genul cap cap, pajura, pajura etc ca 0 si pajura, pajura, cap, cap ca 1.\r\n\r\nOvidiu sugera urmatoarea generalizare pentru problema 2: Care e numarul mediu maxim de numere aleatoare intre 0 si k - 1 pe care le putem obtine dintr-un stream de biti uniform aleatori.\r\n\r\n',58,'private',NULL,NULL),('blog/imaginecup','Imagine Cup','2008-02-20 07:25:43','2008-11-20 17:19:29','Microsoft promoveaza pe \'trilulilu\':http://www.trilulilu.ro/ concursul pentru elevi si studenti Imagine Cup. Concursul are sectiuni diverse precum cea de algoritmi, software design si embedded development. Studentii romani au obtinut rezultate destul de bune anul trecut, cativa calificandu-se in etapa finala a concursului desfasurata la Seul.\r\n\r\nPuteti vedea un mic promo al concursului de anul acesta:\r\n\r\n==TriluliluVideo(user=\"microsoft\" id=\"4bbc23d5de1524\")==\r\n\r\nAici un interviu cu echipa 921UBB finalista a sectiunii de software design:\r\n\r\n==Trilulilu(user=\"microsoft\" id=\"fea6e79eb1abc3\")==\r\n\r\n(fac treaba buna colegii mei de la Babes :) )\r\n\r\nIar aici un interviu cu echipa TechOwls finalista a sectiunii embeded development (Liviu Ciortea, un membru al echipei, e si un utilizator vechi al comunitatii infoarena si a propus cateva probleme):\r\n\r\n==Trilulilu(user=\"microsoft\" id=\"73a203269b3a7b\")==\r\n\r\nImi place sa vad ca se promoveaza astfel de concursuri si studentii care obtin rezultate. Incercati si voi sa participati anul asta!',1851,'protected',2727,NULL),('blog/human-computation','Human Computation','2007-11-10 06:26:47','2008-11-15 13:41:14','In cel mai tare tech-talk de pe google video (350.000 de vizionari), Luis Von Ahn ne prezinta o metoda ingenioasa de a folosi oameni pentru a rezolva problemele dificile pentru un calculator. Metoda aleasa e inspirata din o practica a hackerilor. Acestia ii pun pe utilizatorii unui site deochiat sa scrie ce text contine un \'CAPTCHA\':http://en.wikipedia.org/wiki/Captcha inainte de a vedea urmatoarea imagine. Ei reusesc astfel sa treaca de protectia siteurilor de mail, obtinand astfel o gramada de casute din care pot trimite spam. Acum ii respect mai mult pe indivizi chiar daca nu respect motivatia lor.\r\n\r\nGoogle a cumparat cu bani grei idea lui Luis si a implementat-o in \'Google Image Labeler\':http://images.google.com/imagelabeler/ . Poate de acuma il veti juca  in loc de minesweeper :).\r\n\r\nAveti videoul aici. Dureaza o ora, daca nu aveti atata timp uitati-va neaparat la primele 15 minute ca nu trebuie ratat.\r\n\r\n<embed style=\"width:400px; height:326px;\" id=\"VideoPlayback\" type=\"application/x-shockwave-flash\" src=\"http://video.google.com/googleplayer.swf?docId=-8246463980976635143&hl=en\" flashvars=\"&subtitle=on\"> </embed>\r\n\r\n',1490,'protected',2331,NULL),('preoni-2008','preONI 2008','2007-11-08 01:35:25','2008-03-14 15:09:12','==Include(page=\"template/preoni-2008\")==\r\n\r\nh2. Detalii\r\n\r\n*preONI*, concursul de pregatire pentru \'Olimpiada Nationala de Informatica\':http://olimpiada.info, a ajuns la a *5-a* editie!\r\n\r\n*preONI 2008* incepe cu 4 runde online de calificare. Cei mai buni de la fiecare grupa sunt invitati la finala on-site. Castigatorii rundei finale sunt premiati in bani si obiecte.\r\n\r\nEditia 2008 aduce ca noutate o *grupa separata pentru elevii de gimnaziu*!\r\n\r\np=. <span style=\"background-color: #fafafa\">Remember... \'*preONI 2007*\':preoni-2007 *|* \'*preONI 2006*\':preoni-2006</span>\r\n\r\nh2. Program concurs\r\n\r\nFaceti click pe titlul unei runde pentru informatii detaliate.\r\n\r\ntable{width:50%}. |_. Runda |_. Data |_. Ora |\r\n| \'*Runda 1*\':preoni-2008/runda-1 | *25 Noiembrie 2007, Duminica* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 2*\':preoni-2008/runda-2 | *16 Decembrie 2007, Duminica* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 3*\':preoni-2008/runda-3 | *20 Ianuarie 2008, Duminica* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 4*\':preoni-2008/runda-4 | *17 Februarie 2008, Duminica* |=. *09^00^ - 13^00^* |\r\n| \'*Runda Finala*\':preoni-2008/runda-finala |=. *21-23 Martie 2008* | |\r\n\r\nh2. Despre preONI\r\n\r\n*preONI*, concursul de marca al comunitatii infoarena, este dedicat elevilor de gimnaziu si de liceu ce se pregatesc pentru ONI (\'Olimpiada Nationala de Informatica\':http://olimpiada.info/).\r\n\r\nConcursul este impartit in *4* grupe: gimanziu (pentru clasele V-VIII), clasa a IX-a, clasa a X-a si clasele XI-XII. Se organizeaza 4 runde online de calificare. In urma acestora, cei mai buni de la fiecare grupa sunt invitati la o \'runda finala\':preoni-2008/runda-finala.\r\n\r\nIn cadrul unei runde, concurentii au de rezolvat 3 probleme in 4 ore. Castigatorii rundei finale sunt premiati cu bani si/sau obiecte.\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru!\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti probleme, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':documentatie/evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nPoti sa rezolvi probleme de la orice grupa de varsta. Totusi, te vei califica la runda finala numai daca te incadrezi in grupa la care ai concurat!\r\n\r\nh2. Prima data pe _infoarena_?\r\n\r\n\'infoarena\':/ ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi si vezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n\r\n==include(page=\"template/preoni-2008/footer\")==\r\n',1,'protected',NULL,NULL),('template/preoni-2008/header','template/preoni-2008/header','2007-11-08 01:10:19','2007-11-25 20:21:46','<div style=\"margin: 2em 0 1em 0; padding: .5em; border: 1px solid silver; -moz-border-radius: 10px;\">\r\n!>preoni-2008?adobe.png 13%!:http://myadobe.ro\r\n!template/preoni-2008/header?a.jpg!:/preoni-2008\r\n</div>\r\n',1,'protected',NULL,NULL),('treapuri','Treap-uri','2008-01-21 16:18:25','2008-11-20 10:44:43','h1. Treap-uri\r\n\r\nÎn acest articol voi prezenta o alternativă pentru arbori binari de căutare echilibraţi, precum $AVL$, $Red-Black Trees$, $Splay Trees$ şi $B-Trees$.\r\n\r\nh2. Ce este un _Treap_?\r\n\r\nTreap-ul este un arbore binar în care fiecare nod conţine două informaţii:\r\n\r\n* $cheie$;\r\n\r\n* $prioritate$.\r\n\r\nStructura de date respectă doi invarianţi:\r\n\r\n* _dacă parcurgem arborele în inordine, atunci vom obţine nodurile sortate_; (invariantul arborilor de căutare)\r\n\r\n* _prioritatea fiecărui nod este mai mare decât cea a fiilor săi_. (invariantul heapurilor)\r\n\r\nÎn consecinţă, treap-ul este un arbore binar de căutare pentru chei şi un max-heap pentru priorităţi.\r\n\r\nÎn continuare, vom presupune, pentru uşurinţă, că toate cheile din treap-ul $T$ sunt distincte. Cazul în care avem nevoie să inserăm şi valori ce se repetă se va trata cu uşurinţă după ce acest articol va fi înţeles.\r\n\r\nAstfel, din moment ce $T$ este un heap, nodul $v$ cu prioritatea cea mai mare trebuie să fie rădăcina. Cum este şi un arbore binar de căutare, orice nod $u$ cu $cheie(u) < cheie(v)$ se găseşte în subarborele stâng al lui $v$, şi orice nod $w$ cu $cheie(w) > cheie(v)$ se găseşte în subarborele drept.\r\n\r\nh2. Operaţii\r\n\r\nVor urma în curând... :)\r\n\r\nh2. Avantaje\r\n\r\nHeapurile şi arborii de căutare sunt uşor de implementat şi de înţeles, iar treapurile sunt o combinaţie a acestor două concepte. Astfel, e suficient să fie înţeles invariantul, după care implementarea unui treap se poate face cu uşurinţă în 20 de minute, fără antrenament. De obicei, la structuri ca arbori roşu negrii trebuie folosite serii de rotaţii stânga şi dreapta complexe şi analizate o mulţime de cazuri, pe când la treapuri facem doar câte o rotaţie stânga sau o rotaţie dreapta la fiecare pas al algoritmului. Ei nu sunt predaţi pentru că arborii roşu negrii sau AVL au demonstraţia că merg în $O(log N)$ şi sunt exemple didactice, dar treapurile deşi cu o demonstraţie mai grea sunt mult mai uşori de implementat şi poate şi puţin mai rapizi ca arborii AVL.\r\n\r\n== code(cpp) |\r\n#include <cstdio>\r\n#include <algorithm>\r\n\r\nusing namespace std;\r\n\r\nstruct T {\r\n    int key;\r\n    int priority;\r\n    T *left, *right;\r\n} *R, *nil;     // R radacina; nil arata un nod `gol`\r\n\r\nvoid init(T* &R)\r\n{\r\n    srand(unsigned(time(0)));\r\n    R = nil = new T();\r\n    nil->key = nil->priority = 0,\r\n        nil->left = nil->right = NULL;\r\n}\r\n\r\nvoid rotleft(T* &n)    // roteste fiul stang\r\n{\r\n    T *t = n->left;\r\n    n->left = t->right, t->right = n;\r\n    n = t;             // noua radacina\r\n}\r\n\r\nvoid rotright(T* &n)   // roteste fiul drept\r\n{\r\n    T *t = n->right;\r\n    n->right = t->left, t->left = n;\r\n    n = t;             // noua radacina\r\n}\r\n\r\nvoid balance(T* &n)    // restabileste invariantul heapurilor\r\n{\r\n    // balance() e apelat dupa un insert(), astfel doar cel mult unul din cei doi fii nu respecta invariantul heapurilor\r\n    if (n->left->priority > n->priority)\r\n        rotleft(n);\r\n    else if (n->right->priority > n->priority)\r\n        rotright(n);\r\n    // altfel nu face nimic\r\n}\r\n\r\nvoid insert(T* &n, int key)    // insereaza cheia \'key\'\r\n{\r\n    if (n == nil)\r\n    {\r\n        // adaugam cheia \'key\' prin crearea unui nou nod\r\n        n = new T();\r\n        n->key = key, n->priority = rand() + 1,\r\n                    n->left = n->right = nil;\r\n        return;\r\n    }\r\n    if (key < n->key)\r\n        insert(n->left, key);\r\n    else if (key > n->key)\r\n        insert(n->right, key);\r\n    // altfel e un duplicat; nu face nimic\r\n\r\n    balance(n);\r\n}\r\n\r\nvoid erase(T* &n, int key)\r\n{\r\n    if (n == nil)   return ;\r\n\r\n    if (key < n->key)\r\n        erase(n->left, key);\r\n    else if (key > n->key)\r\n        erase(n->right, key);\r\n    else {    // am gasit cheia\r\n        // pune fiul cu prioritatea cea mai mare ca radacina in locul lui \'n\'\r\n        (n->left->priority > n->right->priority) ? rotleft(n) : rotright(n);\r\n        if (n != nil)   // continua\r\n            erase(n, key);\r\n        else {\r\n            delete n->left;\r\n            n->left = NULL;\r\n        }\r\n    }\r\n}\r\n\r\nvoid _empty(T* &n)\r\n{\r\n    if (n != nil)\r\n    {\r\n        _empty(n->left), _empty(n->right);\r\n        delete n;\r\n    }\r\n}\r\n\r\nvoid empty(T* &R)\r\n{\r\n    _empty(R), R = nil;\r\n}\r\n\r\nvoid print(T *n)\r\n{\r\n    if (n != nil)\r\n    {\r\n        print(n->left);\r\n        printf(\"%d \", n->key);\r\n        print(n->right);\r\n    }\r\n}\r\n\r\nint main(void)\r\n{\r\n    init(R);\r\n    // 1 s pentru a insera un milion de numere\r\n    for (int i = 1 << 20; i >= 1; -- i)\r\n        insert(R, i);\r\n    // 0.5 s pentru a sterge un milion de numere\r\n    for (int i = 1; i <= 1 << 20; ++ i) if (i < 11 || i > 25)\r\n        erase(R, i);\r\n    print(R);\r\n    empty(R);\r\n    print(R);\r\n    return 0;\r\n}\r\n\r\n==\r\n',3146,'public',NULL,NULL),('blog/problema-saptamanii-cartofi','Problema saptamanii - Cartofi','2008-11-21 19:48:26','2008-11-21 19:50:41','Sa se demonstreze ca, dandu-se doi cartofi, exista o curba in trei dimensiuni care se poate desena pe suprafetele ambilor cartofi.\r\n\r\n_Ca de obicei, puteti trimite solutii pe mail la adresa cosmin at gmail.com_',58,'protected',3367,NULL),('treapuri','Treap-uri','2008-01-21 16:18:25','2008-11-21 20:30:57','h1. Treap-uri\r\n\r\nÎn acest articol voi prezenta o alternativă pentru arbori binari de căutare echilibraţi, precum $AVL$, $Red-Black Trees$, $Splay Trees$ şi $B-Trees$.\r\n\r\nh2. Ce este un _Treap_?\r\n\r\nTreap-ul este un arbore binar în care fiecare nod conţine două informaţii:\r\n\r\n* $cheie$;\r\n\r\n* $prioritate$.\r\n\r\nStructura de date respectă doi invarianţi:\r\n\r\n* _dacă parcurgem arborele în inordine, atunci vom obţine nodurile sortate_; (invariantul arborilor de căutare)\r\n\r\n* _prioritatea fiecărui nod este mai mare decât cea a fiilor săi_. (invariantul heapurilor)\r\n\r\nÎn consecinţă, treap-ul este un arbore binar de căutare pentru chei şi un max-heap pentru priorităţi.\r\n\r\nÎn continuare, vom presupune, pentru uşurinţă, că toate cheile din treap-ul $T$ sunt distincte. Cazul în care avem nevoie să inserăm şi valori ce se repetă se va trata cu uşurinţă după ce acest articol va fi înţeles.\r\n\r\nAstfel, din moment ce $T$ este un heap, nodul $v$ cu prioritatea cea mai mare trebuie să fie rădăcina. Cum este şi un arbore binar de căutare, orice nod $u$ cu $cheie(u) < cheie(v)$ se găseşte în subarborele stâng al lui $v$, şi orice nod $w$ cu $cheie(w) > cheie(v)$ se găseşte în subarborele drept.\r\n\r\nh2. Avantaje\r\n\r\nHeapurile şi Arborii Binari de Căutare sunt uşor de implementat şi de înţeles, iar treapurile sunt o combinaţie a acestor două concepte. Astfel, e suficient să fie înţeles invariantul, după care implementarea unui treap se poate face cu uşurinţă în 20 de minute, fără antrenament. De obicei, la structuri ca Arbori Roşu-Negrii trebuie folosite serii de rotaţii stânga şi dreapta complexe şi analizate o mulţime de cazuri, pe când la Treapuri facem doar câte o rotaţie stânga sau o rotaţie dreapta la fiecare pas al algoritmului. Ei nu sunt predaţi pentru că Arborii Roşu-Negrii sau AVL au demonstraţia că merg în $O(log N)$ şi sunt exemple didactice, dar Treapurile, deşi cu o demonstraţie mai grea, sunt mult mai uşori de implementat şi poate şi puţin mai rapizi ca arborii AVL.\r\n\r\nh2. Operaţii\r\n\r\nCostul operaţiilor de mai jos este proporţional cu adâncimea unui nod din Treap. Cu ajutorul probabilităţilor se poate deduce că adâncimea aşteptată a oricărui nod este $O(log N)$, ceea ce implică costul unei operaţii să fie $O(log N)$.\r\n\r\nh3. Căutare\r\n\r\nCăutarea într-un Treap este identică cu cea într-un Arbore Binar de Căutare. Priorităţile din noduri sunt folosite pentru a menţine arborele echilibrat. Pentru a verifica dacă o valoare există putem proceda în felul următor:\r\n\r\n== code(cpp) |\r\nint search(T* n, int key)\r\n{\r\n    if (n == nil)  return 0;\r\n    if (key == n->key)  return 1;\r\n    if (key < n->key)\r\n        return search(n->left, key);\r\n    else\r\n        return search(n->right, key);\r\n}\r\n==\r\n\r\nSe observă că algoritmul poate fi scris şi iterativ, lucru care este indicat.\r\n\r\nh3. Inserare\r\n\r\nÎn cadrul operaţiei de inserare vom atribui unui nod nou o prioritate şi îl vom insera conform algoritmului standard de inserare într-un arbore binar la baza arborelui. Cheile formează un arbore de căutare, dar priorităţile pot să nu mai formeze un heap. Pentru a redobândi această proprietate, cât timp nodul $z$ are prioritate mai mare decât părintele său, se execută o $rotaţie$ în $z$, o operaţie locală care scade nivelul lui $z$ cu $1$ şi creşte nivelul părintelui lui $z$ cu $1$, timp în care invariantul arborilor de căutare este menţinut. Timpul de inserare a lui $z$ este proporţional cu adâncimea lui înainte de rotaţii - trebuie să coborâm după care să urcăm înapoi efectuând rotaţiile necesare. Se poate spune că timpul de inserare al lui $z$ este de două ori timpul necesar pentru căutarea cheii, $key(z)$.\r\n\r\nCu cât generatorul de numere pseudoaleatoare distribuie uniform priorităţi, astfel încât să nu existe două noduri cu aceeaşi prioritate, cu atât arborele este mai bine balansat.\r\n\r\nh3. Ştergere\r\n\r\nOperaţia de ştergere, după eliminarea unui nod, va reconstrui arborele astfel încât cei doi invarianţi să fie menţinuţi. Cum fiecare set de priorităţi asociat nodurilor va reprezenta arborele într-un singur mod şi numai într-unul singur, probabilitatea ca arborele să fie echilibrat este rezonabil de mare. Acest lucru se datorează faptului că arborii rău echilibraţi sunt puţini comparativ cu cei echilibraţi.\r\n\r\nDe adăugat: insert, remove, split, join, lookup, rotleft, rotright, print, balance, meld {$O(mlog(n/m))$} - unirea a două treapuri T1 şi T2 fără nicio relaţie de ordine între ele, difference $O(mlog(n/m))$ - din T1 şi T2 rezultă un T care conţine cheile din T1 care nu sunt în T2, interpretarea geometrică.\r\n\r\nh2. Coding\r\n\r\nVă puteţi uita, ca şi comparaţie, la funcţiile $erase$ sau $balance$ din articolul următor despre arborii \"AVL\":multe-smenuri-de-programare-in-cc-si-nu-numai#AVL.\r\n\r\n== code(cpp) |\r\n\r\nstruct T {\r\n    int key;\r\n    int priority;\r\n    T *left, *right;\r\n} *R, *nil;\r\n\r\nvoid init(T* &R) \r\n{\r\n    srand(unsigned(time(0)));\r\n\r\n    R = nil = new T();\r\n    nil->key = nil->priority = 0,\r\n        nil->left = nil->right = NULL;\r\n}\r\n\r\nvoid rotleft(T* &n) \r\n{\r\n    T *t = n->left;\r\n    n->left = t->right, t->right = n;\r\n    n = t;           \r\n}\r\n\r\nvoid rotright(T* &n) \r\n{\r\n    T *t = n->right;\r\n    n->right = t->left, t->left = n;\r\n    n = t;           \r\n}\r\n\r\nvoid balance(T* &n) \r\n{\r\n    if (n->left->priority > n->priority)\r\n        rotleft(n);\r\n    else if (n->right->priority > n->priority)\r\n        rotright(n);\r\n}\r\n\r\nvoid insert(T* &n, int key) \r\n{\r\n    if (n == nil) \r\n    {\r\n        n = new T();\r\n        n->key = key, n->priority = rand() + 1,\r\n                    n->left = n->right = nil;\r\n        return;\r\n    }\r\n    if (key < n->key)\r\n        insert(n->left, key);\r\n    else if (key > n->key)\r\n        insert(n->right, key);\r\n\r\n    balance(n);\r\n}\r\n\r\nvoid erase(T* &n, int key) \r\n{\r\n    if (n == nil)   return ;\r\n\r\n    if (key < n->key)\r\n        erase(n->left, key);\r\n    else if (key > n->key)\r\n        erase(n->right, key);\r\n    else {    \r\n        (n->left->priority > n->right->priority) ? rotleft(n) : rotright(n);\r\n        if (n != nil)  \r\n            erase(n, key);\r\n        else {\r\n            delete n->left;\r\n            n->left = NULL;\r\n        }\r\n    }\r\n}\r\n==\r\n',3146,'public',NULL,NULL),('numerele-sprague-grundy','Teoria jocurilor: numerele Sprague Grundy','2008-11-18 17:10:41','2008-11-18 20:55:28','h1. Teoria jocurilor: numerele Sprague Grundy\r\n\r\n\'Articol de transcris\':downloads?action=download&file=SpragueGrundy.pdf\r\n\r\nTeoria jocurilor: numerele\r\nSprague Grundy\r\nCosmin-Silvestru Negruşeri\r\n\r\n\r\nDomeniu relativ nou şi încã necercetat în adâncime, teoria jocurilor este o ramurã a matematicii în care de multe ori primeazã inventivitatea şi nu cunoştinţele. Tocmai din acest motiv, în cadrul acestui articol vom introduce câteva noţiuni teoretice care ne vor ajuta în rezolvarea uner probleme din teoria jocurilor.\r\nIngeniozitatea celor pasionaţi poate fi testatã prin introducerea unor probleme de teoria jocurilor la concursurile de matematicã şi informaticã. Deoarece în România, teoria jocurilor nu este studiatã în şcoli, problemele din acest domeniu pot pune în dificultate concurenţii.\r\n\r\n\r\nNIM\r\nPentru început ne vom familiariza cu jocul clasic NIM:\r\n\r\nSe considerã n grãmezi de pietre. Doi jucãtori, vor ridica (alternativ) oricâte pietre dintr-o singurã grãmadã. Câştigãtorul este cel care ia ultima piatrã.\r\n\r\nPentru cazul trivial în care numãrul de grãmezi este egal cu 1, primul jucator are evident strategie de câştig, el putând lua toate pietrele din grãmadã.\r\nDacã numãrul de grãmezi este egal cu 2, primul jucãtor are strategie de câştig atunci când numãrul de pietre din prima grãmadã este diferit de numãrul de pietre din cea de-a doua, strategia lui fiind cea de a aduce tot timpul grãmada mai mare la numãrul de pietre al grãmezii mai mici, şi cum jocul este finit, înseamnã cã primul jucãtor o sã aducã jocul în starea (0, 0).\r\nDacã numãrul de grãmezi este mai mare decât doi strategia se complicã şi nu se mai observã cu \"ochiul liber\". Stãrile câştigãtoare pentru mai multe grãmezi sunt acele stãri pentru care suma XOR a numerelor de pietre din grãmezi este diferitã de 0, restul stãrilor fiind de pierdere.\r\nDe exemplu, dacã avem o gramadã cu o piatrã, o gramadã cu trei pietre, o gramadã cu cinci pietre şi o gramadã cu şapte pietre:\r\no\r\nooo\r\nooooo\r\noooooo\r\nAtunci vom avea:\r\n1 = (0001) \r\n3 = (0011) \r\n5 = (0101)  \r\n7 = (0111) \r\nEfectuând XOR (operatorul ^ în C/C++) între reprezentãrile binare ale numerelor  obţinem 0 = (0000) .\r\nConform propoziţiei de mai sus aceastã stare este de pierdere.\r\nSã demonstrãm cele afirmate. Dintr-o poziţie cu suma XOR egalã cu 0, pentru orice mutare ajungem evident la o poziţie cu suma XOR diferitã de 0, pentru cã luând dintr-o grãmadã un numãr x de pietre, în suma XOR corespunzãtoare noii stãri bitul cel mai semnificativ al lui x va avea valoarea 1.\r\nMai rãmâne de demonstrat cã din orice poziţie cu suma XOR diferitã de 0 putem trece printr-o mutare convenabilã într-o poziţie cu suma XOR egalã cu 0. Cãutãm o grãmadã care are un numãr de pietre mai mare sau egal cu cea mai mare putere a lui 2 care apare în suma XOR. Fie x valoarea sumei XOR a tuturor grãmezilor şi y numãrul de pietre din grãmada gãsitã mai devreme. O mutare \"câştigãtoare\" este extragerea din grãmada gãsitã care are y pietre a y - (x XOR y) pietre (x XOR y este mai mic decât y pentru cã se anuleazã biţii cei mai semnificativi ai lui y şi x). Atunci noua sumã XOR va fi egalã cu 0.\r\nDe exemplu: 4 ^ 8 ^ 17 = (00100) ^ (01000) ^(10001) = (11101) = 29.\r\nMutarea câştigãtoare constã în a lua din cea de-a treia gramadã un numãr de pietre egal cu: \r\n17 - (17 ^ 29) = 17 - 17 ^ 29 = 5 = (00101) .\r\nDupã acest pas grãmezile vor avea 4, 8, 12 pietre. Ne aflãm astfel într-o stare cu suma XOR egalã cu 0.\r\n\r\n\r\n\r\nExemplificãm în continuare câteva probleme în care se foloseşte strategia de la jocul NIM.\r\n\r\nProblema 1\r\nPe o tablã de şah, care are n • m cãsuţe, sunt plasaţi pe prima linie n pioni albi şi pe ultima linie n pioni negri. Fiecare dintre cei doi jucãtori poate muta un singur pion, care îi aparţine, un numãr strict pozitiv de cãsuţe în sus sau în jos, astfel încât sã nu ajungã vreun pion alb sã fie mai jos decât pionul negru de pe aceeaşi coloanã. Pierde jucãtorul care nu mai poate muta.	\r\n\r\nAceastã problemã este o deghizare a jocului NIM, numãrul de pãtrãţele libere între pionul alb şi pionul negru de pe coloana i putând fi considerat numãrul de pietre din grãmada i. Singura diferenţã este cã se pot adãuga pietre la grãmadã (existând posibilitatea mutãrii înapoi).\r\nAceastã problemã se rezolvã uşor, jucãtorul care are strategie de câştig putând evita asemenea mutãri. O astfel de mutare poate fi utilã numai pentru jucãtorul care este întro poziţie de pierdere.\r\nCând jucatorul care nu are strategie de câştig mutã înapoi x casuţe, celãlalt jucãtor va muta pionul propriu de pe aceeaşi coloanã cu x cãsuţe în faţã, astfel ajungându-se la aceeaşi stare cu cea existentã cu douã mutãri anterior (considerând diferenţa poziţiilor).\r\n\r\nProblema 2\r\nAceastã problemã a fost propusã spre rezolvare participanţilor la barajul pentru lãrgirea  lotului naţional din 1997.\r\n\r\nPe o linie sunt plasate la coordonate întregi 2 • n piese roşii şi albastre. \r\nFiecare piesã roşie poate fi mutatã în dreapta oricâte poziţii astfel încât sã nu sarã peste o piesã albastrã, iar piesele albastre pot fi mutate oricâte poziţii la stânga astfel încât sã nu depãşeascã vreo piesã roşie. Piesele vor alterna: roşu, albastru, roşu, albastru etc. Pierde jucãtorul care nu mai poate muta.\r\n\r\nAceastã problemã poate fi, de asemenea, redusã la jocul NIM. Diferenţele poziţiilor perechilor de piese roşii şi albastre consecutive constituie numãrul de pietre al grãmezilor din jocul NIM.\r\n\r\nProblema 3\r\n(El Judge MIPT online programming contest Nim Game Give Away!)\r\n\r\nSe considerã n grãmezi de pietre, jucãtorii mutã alternativ, fiecare jucãtor extrãgând oricâte pietre dintr-o singurã grãmadã. Cel care ia ultima piatrã pierde jocul.\r\n\r\nStrategia acestui joc este similarã cu cea aplicatã în jocul NIM cu câteva mici diferenţe. Jucãtorul care are strategie de câştig în poziţia curentã în cadrul jocului NIM face aceeaşi mutare pe care ar face-o în cazul jocului NIM, exceptând cazul în care aceastã mutare lasã doar grãmezi cu o singurã piatrã şi numãrul acestor grãmezi este par.  În aceastã situaţie, dacã ar trebui sã ia x pietre, jucãtorul poate lua x - 1 pietre din grãmada actualã, pentru ca numãrul de grãmezi sã fie impar şi el sã facã ultima mutare.\r\nNumerele Sprague Grundy\r\nJocurile care prezintã interes pentru jucãtori sunt acelea care necesitã examinarea unui numãr foarte mare de stãri pentru determinarea strategiei de câştig, deoarece în caz contrar câştigãtorul s-ar cunoaşte chiar de la început. Spre deosebire de aceştia, matematicienii sau informaticienii sunt interesaţi de determinarea unor strategii pentru astfel de jocuri.\r\nToate jocurile imparţiale cu doi jucãtori cu informaţie totalã pot fi reduse la jocul NIM care se joacã cu nişte grãmezi virtuale, în care mutãrile posibile sunt extragerea oricâtor pietre dintr-o grãmadã sau adãugarea oricâtor pietre la o grãmadã (aşa cum am menţionat anterior, adãugarea de pietre la o grãmadã nu complicã analiza jocului).\r\nAfirmaţia anterioarã constituie un rezultat al Teoriei Sprague-Grundy. Roland Percival Sprague (1936) şi Patrick Michael Grundy (1939) sunt doi matematicieni care s-au ocupat, independent, de teoria jocurilor imparţiale. \r\nMajoritatea jocurilor imparţiale se pot reduce la jocul prezentat în problema Pioni de la runda 47 a concursului de programare Bursele Agora. Acolo se menţiona urmãtorul joc: \r\nSe considerã un graf aciclic care conţine în noduri câţiva pioni, jucãtorii alterneazã la mutare şi fiecare poate muta câte un pion pe un arc care iese din nodul în care este situat pionul. Pierde jucãtorul care nu poate muta.\r\nCum graful este aciclic, jocul este finit şi are întotdeauna un câştigãtor. Practic, acest joc este suma unor jocuri, mai precis suma a mai multor jocuri cu un singur pion pe graful aciclic.\r\nJocul cu un singur pion poate fi analizat destul de uşor, fiecare nod al grafului putând fi colorat cu alb sau negru dupã cum existã sau nu strategie de câştig dacã în nodul curent ar fi poziţionat pionul. Aceastã colorare poate fi realizatã uşor dacã se porneşte de la nodurile fãrã urmaş şi la fiecare pas se coloreazã câte un nod ai cãrui urmaşi sunt deja coloraţi.\r\nOrice joc imparţial poate fi redus la un joc cu un singur pion. Nodurile sunt poziţiile jocului şi arcele grafului sunt mutãrile posibile din fiecare poziţie. Jocul iniţial poate fi şi el transformat, dar numãrul de noduri creşte foarte mult (pentru n pioni şi m noduri, numãrul de noduri din jocul transformat este nm) şi nu este practic sã colorãm graful rezultat. Folosind teoria dezvoltatã de Sprague şi Grundy, putem reduce complexitatea analizei jocului cu n pioni la complexitatea analizei jocului cu un pion.\r\nVom introduce funcţia mex cu semnificaţia: mex(S) este elementul minimal natural care nu aparţine mulţimii S. Pentru fiecare nod x al grafului aciclic considerat, vom calcula valoarea funcţiei gx = mex(gx1, gx2, …, gxk), unde x1, x2, …, xk sunt urmaşii nodului x în graf. Pentru nodurile fãrã urmaşi gx = 0.\r\nAnalog jocului cu un singur pion, graful poate fi etichetat din aproape în aproape, pornind de la nodurile fãrã urmaşi.\r\nObservãm cã, dacã gx = 0 în jocul cu un singur pion situat în nodul x nu avem strategie de câştig, iar dacã gx este diferit de 0 avem strategie de câştig. Restul informaţiei ne ajutã la determinarea unei strategii pentru jocul cu n pioni.\r\nObservãm cã putem reduce acest joc la jocul NIM în care grãmada virtualã asociatã pionului i are un numãr de pietre egal cu valoarea g a nodului în care este situat pionul i.\r\nDe ce este acest joc echivalent cu jocul NIM?\r\nAşa cum la NIM puteam lua oricâte pietre dintr-o grãmadã, aici putem muta pionul dintr-un nod cu valoarea g într-un nod astfel încât noua valoare pentru pionul i poate fi orice numãr de la 0 la g - 1. Prin urmare, pentru a verifica dacã suntem într-o poziţie de câştig în jocul cu pionii, putem aplica strategia jocului NIM şi obţinem cã suntem într-o poziţie de câştig dacã suma XOR a numerelor din nodurile ocupate de cei n pioni este diferitã de 0. Aceastã sumã se numeşte funcţia Sprague Grundy, SG(i1, …, in) = gi1^ gi2 ^gi3 ^ … ^ gin.\r\nProblema de la runda 47 se rezolvã acum uşor efectuând o sortare topologicã a nodurilor grafului aciclic şi numerotând nodurile folosind funcţia mex.\r\n\r\n\r\nSã studiem acum alte probleme care se pot rezolva folosind numerele Sprague Grundy:\r\n\r\nProblema 4\r\nProblema Joc a rundei 13 a concursului de programare Bursele Agora putea fi rezolvatã în acest mod.\r\nÎn acea problemã se cerea sã verificãm existenţa unei strategii de câştig pentru un joc similar cu NIM în care se putea lua dintr-o grãmadã o piatrã sau un numãr prim de pietre.\r\nDacã determinãm valorile Sprague Grundy pentru grãmezi de dimensiuni mici putem observa cã se repeta o succesiune de numere: 0 1 2 3 0 1 2 3 …\r\nPutem demonstra prin inducţie cã aceastã secvenţã se va repeta la nesfârşit.\r\nPentru o grãmadã de dimensiune n valoarea asociatã va fi n modulo 4. Pentru 0 ≤n ≤3 afirmaţia este adevãratã.\r\nVom presupune afirmaţia adevãratã pentru toate valorile m < n. Sã demonstrãm acum cã este adevãratã şi pentru n. Deoarece putem lua din n pietre una, douã sau trei pietre, mai rãmâne valoarea n modulo 4 care nu este eliminate încã din valorile potenţiale asociate grãmezii de dimensiune n.\r\nVom arãta în continuare cã aceastã valoare nici nu va fi eliminatã. Eliminarea ei ar însemna cã putem lua din n un numãr p de pietre şi atunci din (n - p) modulo 4 = n modulo 4, am avea: p modulo 4 = 0, dar p este un numãr prim, deci valoarea Sprague Grundy asociatã unei grãmezi de dimensiune n este n modulo 4.\r\nProblema 5\r\n(El Judge MIPT online programming contest, Stone game)\r\n\r\nSe considerã k grãmezi cu n1, n2, …, nk pietre fiecare. Când este rândul sãu, un jucãtor poate lua dintr-o gramadã 2m pietre. Jucãtorul care ia ultima piatrã câştigã.\r\nRestricţii: k ≤50, ni ≤10200.\r\n\r\nSã determinãm valorile Sprague Grundy pentru grãmezi mici:\r\n0 : 0;    1 : 1;    2 : 2;    3 : 0;    4 : 1;    5 : 2;    6 : 0\r\nObservãm şi aici secvenţa repetitivã 0 1 2 0 1 2, deci am putea trage concluzia cã valoarea Sprague Grundy asociatã unei grãmezi de dimensiune n este n modulo 3. Aceastã afirmaţie este adevaratã şi urmeazã aceeaşi demonstraţie ca în cazul problemei anterioare, iar restul modulo 3 pentru n numãr cu 200 de cifre este simplu de gãsit determinând suma cifrelor numãrului.\r\n\r\nProblema 6\r\n(El Judge MIPT online programming contest, Stone game II)\r\n\r\nSe considerã k grãmezi de pietre cu n1, n2, …, nk pietre. Un jucãtor poate lua dintr-o grãmadã la mutarea lui un numãr pozitiv de pietre dar nu mai mult de jumãtate din pietrele din grãmadã. Jucãtorul care nu mai poate muta pierde.\r\nRestricţii: k ≤50, ni ≤100000.\r\n\r\nNumãrul 100000 nu este foarte mare şi valorile Sprague Grundy pot fi determinate off-line şi incluse în programul nostru ca şi constante.\r\nPutem scrie pentru valori mici secvenţa Sprague Grundy:\r\n1 2 3 4 5 6 7 8 9 10 11 12 13 14\r\n0 1 0 2 1 3 0 4 2   5   1   6   3   7\r\nPentru n impar valoarea asociatã este aceeaşi cu valoarea asociatã lui n/2, şi pentru n par valoarea asociatã este n/2. Acest lucru se poate demonstra prin inducţie matematicã.\r\n\r\nProblema 7\r\n(CEOI 2000, Cluj-Napoca, problema Sticks)\r\n\r\nSe considerã n (n ≤10) rânduri de beţe pe o masã, cu S  (S  ≤10) beţe aliniate pe fiecare rând şi doi jucãtori. Beţele de pe rândul i sunt numerotate secvenţial de la 1 la S .\r\nCei doi jucãtori mutã alternativ. Fiecare mişcare constã în eliminarea a unu, douã sau trei beţe de pe acelaşi rând. Beţele trebuie sã fie numerotate secvenţial, adicã sã fie consecutive.\r\nDe exemplu, un rând are 10 beţe şi primul jucãtor eliminã beţele 4, 5, 6, deci vor rãmâne numai beţele 1, 2, 3, 4, 8, 9, 10. Al doilea jucãtor poate lua la rândul sãu beţele 1, 2, 3, dar nu beţele 3, 7, 8 pentru cã acestea nu sunt numerotate consecutiv (bineînţeles cã existã şi alte mutãri valide).\r\nCâştigã jucãtorul care ia ultimul bãţ de pe masã.\r\n\r\nProblema generalã are o soluţie ingenioasã care ţine seama de paritãţile rândurilor, dar la aceastã problemã, datoritã mãrginirii lui Si (Si ≤10) nu este necesar sã fim ingenioşi. Restricţia Si ≤10, ne ajutã prin faptul cã numãrul total de poziţii (dacã jucãm pe o singurã gramadã), este 210. Vom reprezenta o poziţie printr-un întreg, iar dacã acel întreg are în codificarea lui binarã pe poziţia i un bit de 1 înseamnã cã el reprezintã un rând de beţe care conţine în el bãţul numerotat cu i. Este uşor de realizat un graf aciclic al mişcãrilor pentru un rând (graful este aciclic pentru cã la fiecare mutare luãm beţe din configuraţie). Numerotãm fiecare poziţie cu numerele Sprague Grundy, şi acum problema\r\ndeciderii dacã suntem sau nu într-o poziţie câştigãtoare devine banalã. În problema iniţialã trebuia sã jucãm împotriva calculatorului şi sã câştigãm. Putem realiza aceasta folosind mutarea câştigãtoare prezentatã la jocul NIM.\r\n\r\nProblema 8\r\nAceastã problemã a fost propusã spre rezolvare la concursul Internet Problem Solving Contest (cel mai prestigios concurs online) şi o puteţi gãsi la adresa http://ipsc.ksp.sk/xxproblems/ipsc2003/g.php. Ea a fost folositã şi la concursul organizat de .campion la o rundã online. Rezolvarea ei, complicatã, folosind numerele Sprague Grundy prezentate în acest articol, se poate gãsi în [3], pe site-ul [7], sau pe siteul concursului .campion.\r\n\r\nProblema 9\r\nAceastã problemã a fost propusã spre rezolvare la ediţia din acest an a Olimpiadei Naţionale de Informaticã din Ucraina. \r\n\r\nDoi participanţi mãnâncã alternant din nişte tablete de ciocolatã dupã urmãtoarele reguli:\r\n	taie o tabletã în douã, tãietura trebuie sã fie paralelã cu una din laturile tabletei şi trebuie sã nu taie pãtrãţelele de ciocolatã;\r\n	poate sã rupã şi sã mãnânce orice linie sau coloanã de pãtrãţele care nu se aflã pe marginea tabletei;\r\n	poate sã rupã şi sã mãnânce toate patrãţelele de pe marginea tabletei, cu condiţia ca tableta rãmasã sã aibã cel puţin dimensiunea 1×1.      \r\nNici una dintre aceste trei mutãri nu poate fi efectuatã asupra unei tablete de dimensiune 1×1. Pierde jucãtorul care nu mai poate efectua nici o mutare.\r\nÎn fişierul de intrare se va afla numãrul N (1 ≤N ≤100) de tablete, iar pe urmãtoarea linie sunt N perechi de numere întregi care reprezintã dimensiunile tabletelor.\r\nÎn fişierul de ieşire se va afla un singur numãr întreg reprezentând numãrul mutãrilor câştigãtoare pentru primul jucãtor.\r\n\r\nPentru aceastã problemã vom calcula matricea SG  care reprezintã valoarea Sprague-Grundy asociatã unei tablete de dimensiuni (i, j).\r\nSã vedem care este recurenţa care va satisface elementele matricei SG:\r\nSGi,j = mex(SGi,k ^ SGi,j-k, (1 ≤k < j) mutarea întâi\r\n  SGk,j ^ SGi-k,j, (1 ≤k < i)\r\n            SGi,k ^ SGi,j-k-1, (1 ≤k < j - 1) mutarea a doua\r\n            SGk,j ^ SGi-k-1,j, (1 ≤k < i - 1)\r\n            SGi-2,j-2) (i > 2 şi j > 2) mutarea a treia\r\nAcum, pentru a calcula numãrul de mutãri câştigãtoare efectuãm asupra fiecãrei tablete din fişierul de intrare toate mutãrile posibile care sunt cel mult de 4 • 100 + 1 şi facem suma XOR a valorilor Sprague Grundy pentru restul tabletelor neimplicate în mutare şi a tabletelor rezultate din mutare. Pentru a calcula SGi,j trebuie sã parcurgem cel\r\nmult 2 • i + 2 • j + 1 valori obţinute. Astfel, algoritmul de determinare al valorilor matricei SG are ordinul de complexitatea O(N3).\r\nComplexitatea algoritmului care determinã numãrul de mutãri câştigãtoare este O(N2).\r\nAm vãzut cã aceste numere sunt folositoare pentru rezolvarea unor probleme de jocuri combinatorice. Chiar dacã numãrul stãrilor grafului nostru aciclic poate sã fie foarte mare, putem sã ne dãm seama, câteodatã, din valorile mici de o regulã pe care o urmeazã numerele, sau mãcar putem determina mai uşor configuraţii pentru care jocul are sau nu strategie de câştig, fapt care ne poate ajuta în descoperirea rezolvãrii generale.\r\n\r\nBibliografie\r\n1. ***, colecţia GInfo\r\n2. Mihai Oltean, Programarea Jocurilor Matematice, Editura\r\nAlbastrã, Cluj-Napoca, 1996\r\n3. Thomas S. Ferguson, Game Theory Text (online)\r\nhttp://www.math.ucla.edu/~tom/gamescourse.html\r\n4. http://www.ams.org/new-in-math/cover/games1.html\r\n5. http://www.cut-the-knot.com\r\n6. http://www.mathworld.wolfram.com\r\n7. http://ipsc.ksp.sk/\r\nCosmin-Silvestru Negruşeri este student în anul III la Universitatea\r\nBabeş-Bolyai din Cluj-Napoca. El poate fi contactat prin e-mail la adresa\r\nkosmin_2000@yahoo.com.\r\n\r\n',5700,'public',NULL,NULL),('the-monty-hall-problem','The Monty Hall Problem','2004-11-20 00:00:00','2008-11-21 00:58:42','h1. The Monty Hall Problem\r\n\r\n(Categoria _Matematica_, Autor _Alexandra Gartu_)\r\n\r\n(toc){width: 20em}*{text-align:center;} *Continut*\r\n* \'Problema\':the-monty-hall-problem#problema\r\n* \'Argumentul 1\':the-monty-hall-problem#argument1\r\n* \'Argumentul 2\':the-monty-hall-problem#argument2\r\n* \'Putina matematica... sau Argumentul 3\':the-monty-hall-problem#argument3\r\n* \'Putina istorie...\':the-monty-hall-problem#istorie\r\n\r\nIn acest articol nu vom discuta despre algoritmi clasici, structuri de date sau competitii de informatica. Vreau sa va prezint o problema de logica ce presupune doar cunostinte elementare de matematica. Scopul este de a ne \"antrena\" mintea / perspicacitatea, iar legatura cu informatica vine din faptul ca multe din problemele pe care le rezolvati la informatica presupun idei mai mult decat cunostinte clasice.\r\n\r\nh2(#problema). Problema\r\n\r\nProblema celor trei porti se refera la faimoasa situatie din show-urile televizate (in speta \"Let\'s Make a Deal\", prezentat de americanul Monty Hall) cand unul dintre concurenti trebuie sa aleaga una din cele $3$ porti: in spatele a doua dintre ele se afla cate o capra, iar in spatele celei de-a treia se afla un Rolls Royce. Dupa ce concurentul a ales prima data, prezentatorul (stiind unde se gaseste Rolls Royce-ul) ii arata una din capre, din spatele uneia din usile pe care NU le-a ales. Intrebarea care se pune este daca respectivul concurent ar trebui sau nu sa-si schimbe optiunea dupa aceasta dezvaluire.\r\n\r\nh2(#argument1). Argumentul 1\r\n\r\nInitial, sansele de a alege poarta corecta sunt de {$1/3$}. Faptul ca ti-a fost aratata o capra nu schimba cu nimic probabilitatea ca prima oara sa fi ales corect. Sansele ca prima decizie sa fie corecta inca sunt de {$1/3$}, deci ar trebui sa iti modifici decizia fiindca acum in spatele celei de-a treia porti exista {$2/3$} sanse sa se afle un Rolls Royce.\r\n\r\nExista asadar doua cazuri:\r\n\r\n# ai ghicit corect prima oara - sanse $1/3$\r\n# ai ghicit incorect prima oara - sanse $2/3$\r\n\r\nSa presupunem acum ca iti schimbi decizia:\r\n\r\n# avusesei dreptate la prima decizie - sansele sa pierzi sunt $1/3$\r\n# gresisei prima oara - sansele sa castigi sunt $2/3$\r\n\r\nh2(#argument2). Argumentul 2\r\n\r\nModificam ipoteza considerand ca avem initial $100$ de usi. Alegem una dintre ele avand $99/100$ sanse sa ghicim gresit. Din nou moderatorul emisiunii stie unde este Rolls Royce-ul, asa ca ne arata $98$ de capre. Dupa acest pas inca nu stim in spatele careia din usi se afla masina: asta inseamna ca sansele de a ghici sunt $1/2$? In mod cert, nu: sansa de a ghici a fost initial si a ramas {$1/100$}. Deci, in mod sigur este indicat sa schimbam decizia initiala.\r\n\r\nh2(#argument3). Putina matematica... sau Argumentul 3\r\n\r\nSa numim cele $3$ porti {$A, B, C$}. Sa presupunem ca ai ales poarta $A$ si ca Monty Hall ti-a aratat o capra in spatele usii {$B$}.\r\n\r\n* Probabilitate ca masina sa se afle in spatele portii {$X = P(X) = 1/3$}\r\n* Probabilitatea ca moderatorul sa deschida poarta $B$ daca premiul se afla la {$A$}: $P(moderatorul deschide B | A) = 1/2$\r\n* Probabilitatea ca moderatorul sa deschida poarta $B$ daca premiul se afla la {$B$}: $P(moderatorul deschide B | B) = 0$\r\n* Probabilitatea ca moderatorul sa deschida poarta $B$ daca premiul se afla la {$C$}: $P(moderatorul deschide B | C) = 1$\r\n\r\nh3. Concluzii\r\n\r\nProbabilitatea ca moderatorul sa deschida poarta $B$ este:\r\n\r\n$P(moderatorul deschide B) =$\r\n$P(A) * P(moderatorul deschide B|A) +$\r\n$P(B) * P(moderatorul deschide B|B) +$\r\n$P(C) * P(moderatorul deschide B|C)$\r\n$= 1/6 + 0 + 1/3$\r\n\r\n$P(A|moderatorul deschide B) = P(A) * P(moderatorul deschide B|A) / P(moderatorul deschide B)$\r\n$= (1/6) / (1/2) = 1/3$\r\n\r\n$P(C|moderatorul deschide B) = P&#0040;C) * P(moderatorul deschide B|C) /P(moderatorul deschide B)$\r\n$= (1/3) / (1/2) = 2/3$\r\n\r\nDeci, probabilitate ca in spatele usii C sa se afle o masina este {$2/3$}.\r\n\r\nh2(#istorie). Putina istorie...\r\n\r\nProblema a fost publicata mai intai de Martin Gardener in octombrie $1959$ si se referea la $3$ detinuti dintre care unul, ales aleator, va fi eliberat. Sa numim cei trei prizonieri {$A, B, C$}. $A$ ii cere gardianului sa-i spuna care dintre colegii lui *NU* va fi eliberat. Desigur, asta nu inseamna ca sansele lui de a fi eliberat cresc (ele fiind tot {$1/3$}) in timp ce sansele celui de-al treilea condamnat (cel nenominalizat) cresc la {$2/3$}.\r\n\r\nMarlyn Vos Savant\'s, considerata omul cu cel mai ridicat IQ pana in momentul de fata, a publicat aceasta problema, in prima forma din acest articol in anul $1990$ in rubrica sa din Parade Magazine. Solutia ei (cel de-al doilea argument) a fost contestata in numeroase randuri (a primit peste $10000$ de scrisori care sustineau ca demonstratia este eronata) si a aparut pe prima pagina in {@21 iulie 1991@} in New York Times ( \"Her answer... has been debated in the halls of the C.I.A. and the barracks of fighter pilots in the Persian Gulf. It has been analyzed by mathematicians at M.I.T. and computer programmers at Los Alamos National Laboratory in New Mexico. It has been tested in classes ranging from second grade to graduate level at more than 1000 schools across the country.\" ).\r\n\r\n',2044,'public',NULL,NULL),('probleme-cu-secvente','Probleme cu secvente','2008-11-23 19:46:37','2008-11-28 21:20:31','h1. Probleme cu secvente\r\n\r\n(Categoria _Diverse_, autor _Cosmin Negruseri_)\r\n\r\n(toc){width: 25em}*{text-align:center} *Cuprins*\r\n* \'Introducere \':probleme-cu-secvente#intro\r\n* \'Problema 1 ( _Subsecventa de suma maxima_ ) \':probleme-cu-secvente#prob1\r\n\r\nh2(#intro). Introducere\r\n\r\nAcest articol prezinta o serie de probleme inrudite cu problema subsecventei de suma maxima, insotite de rezolvari eficiente. Problemele prezentate pot aparea oricand ca subprobleme in concursurile de programare, studierea lor marind in mod util bagajul de cunostinte al unui elev pasionat de algoritmica.\r\n\r\nh2(#prob1). Problema 1 ( _Subsecventa de suma maxima_ )\r\n\r\nSe da un şir $A$ = ( $a{~1~}$, $a{~2~}$, ... , $a{~N~}$) de numere intregi. Sa se determine o subsecventa ( $a{~i~}$, $a{~i+1~}$, ... , $a{~j~}$) care sa aiba suma maxima.\r\n\r\nh4. Exemplu\r\n\r\nPentru secventa de numere $(-1, 2, 3, -4, -2, 2, 1, -3, -2, -3, -4, 9, -2, 1, 7, 8, -19, -7, 2, 4, 3)$, o subsecventa de suma maxima este $(9, -2, 1, 7, 8)$.\r\n\r\nh3. Rezolvare\r\n\r\nPrima rezolvare care ne vine in minte este: pentru orice subsecventa sa ii determinam suma, iar apoi sa determinam maximul acestor sume. Aceasta solutie are complexitatea $O(N^3)$. \r\n\r\n== code(cpp) |\r\nbestSum = -infinit;\r\nfor (i = 1; i <= N; i++) {\r\n   for (j = i; j <= N; j++) {\r\n         sum = 0;\r\n         for (k = i; k <= j; k++) sum += a[ k ];\r\n         if (bestSum < sum) bestSum = sum;         \r\n   }\r\n}\r\n==\r\n\r\nEste evident ca se calculeaza anumite sume partiale de mai multe ori. Pentru a reduce complexitatea la $O(N^2^)$ este necesar sa observam ca suma subsecventei $a[ i..j ]$ este egala cu suma subsecventei $a[ i..j-1 ]$, la care se aduna $a[ j ]$.\r\nAlta idee este de a pastra intr-un sir $sum[ i ]$ - suma elementelor din subsecventa $a[ 1..i ]$. Pentru a determina suma elementelor din subsecventa $a[ i..j ]$ putem face calculul $sum[ i ] - sum[ j-1 ]$ (complexitate $O(N^2^)$).\r\n\r\n== code(cpp) |\r\nsum[ 0 ] = 0;\r\nfor (i = 1; i <= N; i++) sum[ i ] = a[ i ] + sum[ i - 1 ];\r\nbestSum = -infinit;\r\nfor (i = 1; i <= N; i++) {\r\n   for (j = i; j <= N; j++) {\r\n         if (bestSum < sum[ i ] – sum[ j - 1 ]) bestSum = sum[ i ] - sum[ j - 1 ];\r\n   }\r\n}\r\n==\r\n\r\nPutem sa rafinam aceasta idee calculand pentru fiecare indice $i$ numarul $best[ i ]$ ( subsecventa de suma maxima ce are capatul drept in $i$ ). Este usor de observat ca $best[ i ] = max( sum[ i ] - sum[ j-1 ] )$, unde $j$ ia valori de la $1$ la $i$. Relatia anterioara este echivalenta cu $best[ i ] = sum[ i ] – min( sum[ j-1 ] )$. Obtinem astfel un algoritm liniar care ne determina subsecventa de suma maxima.\r\n\r\n== code(cpp) |\r\nsum[ 0 ] = 0;\r\nfor (i = 1; i <= N; i++) sum[ i ] = a[ i ] + sum[ i-1 ];\r\nmin = sum[ 0 ];\r\nbestSum = -infinit;\r\nfor (i = 1; i <= N; i++) {\r\n     best[ i ] = sum[ i ] - min;\r\n     if (min > sum[ i ]) min = sum[ i ];\r\n     if (bestSum < best[ i ]) bestSum = best[ i ];\r\n}\r\n==\r\n\r\nPutem incerca o abordare bazata pe paradigma _divide et impera_. La fiecare pas impartim sirul in jumatate si aflam subsecventele de suma maxima din cele doua jumatati. Dupa aceea trebuie sa gasim subsecventa de suma maxima care are cate un capat in fiecare din cele doua jumatati ale sirului. Gasim aceasta secventa prin alipirea sufixului de suma maxima a primei jumatati cu prefixul de suma maxima a celei de-a doua.\r\n\r\n== code(cpp) |\r\nint getMaxSubsequence(int l, int r) {\r\n     if (l == r) return a[ l ];\r\n     mid = (l + r) / 2;\r\n     bestL = getMaxSubsequence(l, mid);\r\n     bestR = getMaxSubsequence(mid + 1, r);\r\n     suf = 0; \r\n     pre = 0; \r\n     maxSuf = -infinity; \r\n     maxPre = -infinity;\r\n     for (i = mid; i >= l; i--) {\r\n           suf += a[ i ];\r\n           if (maxSuf < suf) maxSuf = suf;\r\n     }\r\n     for (i = mid + 1; i <= r; i++) {\r\n           pre += a[ i ];\r\n           if (maxPre < pre) maxPre = pre;    \r\n     }\r\n     return max(bestL, max( bestR, maxPre + maxSuf ));\r\n}\r\n==\r\n\r\nO idee bazata pe paradigma programarii dinamice ar fi sa folosim un sir $best[ i ]$, reprezentand suma maxima a unei subsecvente ce se termina in $a[ i ]$. Se poate demonstra prin inductie ca sirul $best$ satisface urmatoarea recurenta $best[ i ] = max( a[ i ], best[ i-1 ] + a[ i ] )$.\r\n\r\n== code(cpp) |\r\nbestSum = a[ 1 ];\r\nfor (i = 1; i <= N; i++) {\r\n     best[ i ] = a[ i ];\r\n     if (best[ i ] < best[ i-1 ] + a[ i ]) best[ i ] = best[ i-1 ] + a[ i ];\r\n     if (bestSum < best[ i ]) bestSum = best[ i ];\r\n}\r\n==\r\n\r\nAlta idee ar fi sa partitionam sirul in subsecvente, astfel incat fiecare dintre acestea sa aiba ambele capete cat mai mici posibile si suma elementelor subsecventei sa fie negativa. Pe exemplul data avem $[-1], [2, 3, -4, -2], [2, 1, -3, -2], [-3], [-4], [9, -2, 1, 7, 8, -19, -7], [2, 4, 3]$. Este evident ca o subsecventa de suma maxima va avea primul capat la inceputul unei astfel de subsecvente. Acest lucru se explica prin faptul ca in caz contrar secventa poate fi marita in stanga ( orice secventa din cele alese pentru partitionare are toate prefixele de suma pozitiva, in afara de prefixul ce reprezinta intreaga subsecventa ). De asemenea, orice subsecventa de suma maxima nu va contine elemente din alta parte a partitiei, pentru ca daca subsecventa se intinde pe mai multe parti, atunci putem elimina prefixul subsecventei care reprezinta o parte a partitiei, acea parte avand suma negativa.\r\n\r\n== code(cpp) |\r\nsum = -infinit; bestSum = -infinit;\r\nfor (i = 1; i <= N; i++) {\r\n      sum += a[ i ];\r\n      if (sum < 0) {\r\n         sum = 0;\r\n         continue;\r\n      } else if (sum >= bestSum) bestSum = sum;      \r\n}\r\n==\r\n\r\nh2(#prob2). Problema 2 ({_Maximum Sum_}) - 104 acm.uva.es\r\n\r\nSe da o matrice de dimensiuni $NxN$ cu elemente intregi. Se cere determinarea unei submatrici a carei elemente au suma maxima. \r\n\r\nh4. Exemplu\r\n\r\nPentru matricea<tex>\\[ \\left( \\begin{array}{cccc}0 & -2 & -7 & 0 \\\\9 & 2 & -6 & 2 \\\\-4 & 1 & -4 & 1 \\\\-1 & 8 & 0 & -2 \\end{array} \\right)\\]</tex>submatricea de sumă maximă este următoarea:<tex>\\[ \\left( \\begin{array}{cc}9 & 2 \\\\-4 & 1 \\\\-1 & 8 \\end{array} \\right)\\]</tex>\r\n\r\nh3. Rezolvare\r\n\r\nPutem folosi trucul construirii sumelor partiale prezentat in rezolvarea anterioara, pentru cazul *2D*. Pastram in $sum[i][j]$ suma tuturor elementelor $a[i{~1~}][j{~1~}]$ cu proprietatea ca $1 <= i{~1~} <= i$, si $1 <= j{~1~} <= j$. Putem calcula sumele prin metoda programarii dinamice (complexitate $O(N^2^)$) folosind formula $sum[i][j] = a[i][j] + sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1]$. Acum pentru a calcula suma elementelor din matricea cu colturile $(i{~1~}, j{~1~}), (i{~2~}, j{~2~})$, unde $i{~1~} <= i{~2~} si j{~1~} <= j{~2~}$ este suficient sa facem calculul $sum[i{~2~}][j{~2~}] - sum[i{~1~}-1][j{~2~}] - sum[i{~2~}][j{~1~}-1] + sum[i{~1~}-1][j{~1~}-1]$. Astfel putem evalua suma din fiecare submatrice in timp constant, deci rezolvarea are ordinul de complexitate $O(N^4^)$.\r\nO alta idee ar fi ca pentru fiecare pereche $(i{~1~}, i{~2~})$ fixate sa determinam perechea optima $(j{~1~}, j{~2~})$. Daca avem liniile $i{~1~}$ si $i{~2~}$ fixate atunci problema se transforma din una bidimensionala in una unidimensionala. Astfel pentru fiecare coloana $j$ vom considera $b[j]$ ca suma a elementelor $a[i][j]$ cu proprietatea ca $i{~1~} <= i <= i{~2~}$. In exemplul nostru daca $i{~1~} = 2$ si $i{~2~} = 3$, atunci avem $b{~1~} = 9 + (-4)$, $b{~2~} = 2 + 1$, $b{~3~} = (-6) + (-4)$ si $b{~4~} = 2 + 1$. Pentru a rezolva problema unidimensionala folosim unul din algoritmii liniari prezentati mai sus, astfel obtinandu-se un algoritm de complexitate totala $O(N^3^)$. Acest truc de a fixa doua linii pentru a transforma problema in una unidimensionala este util in multe probleme pe matrice sau cu puncte in plan.\r\nCel mai bun algoritm cunoscut pentru aceasta problema are complexitatea <tex>O(N^{3((\\log \\log N)/\\log N)^{1/2}})</tex> si este mai mult un algoritm teoretic decat unul practic, usor implementabil.\r\n',4297,'public',NULL,NULL),('concursuri','Concursuri organizate de infoarena','2006-11-05 23:17:11','2008-09-08 12:18:02','h1. Concursuri organizate de infoarena\r\n\r\nIn aproape 4 ani de activitate, infoarena a organizat cateva zeci de concursuri/runde online. Fiecare concurs are un format aparte. De la o runda la cinci, de la cateva ore la cateva zile sau chiar o saptamana, de la cateva probleme la 20, concursurile infoarena variaza in amploare, dificultate si popularitate.\r\n\r\n(toc)*{text-align:center} *Concursuri*\r\n* \'preONI\':concursuri#preoni\r\n* \'Happy Coding\':concursuri#happy\r\n* \'Autumn Warmup\':concursuri#autumn\r\n** \'Autumn Warmup 2007\':concursuri#autumn2007\r\n** \'Autumn Warmup 2006\':concursuri#autumn2006\r\n* \'Summer Challenge\':concursuri#summer\r\n** \'Summer Challenge 2007\':concursuri#summer2007\r\n** \'Summer Challenge 2006\':concursuri#summer2006\r\n* \'Alte concursuri\':concursuri#others\r\n\r\nh2(#preoni). Seria preONI\r\n\r\nConcursul _de marca_ infoarena se organizeaza anual si pregateste elevii pentru \"Olimpiada Nationala de Informatica\":http://olimpiada.info/. Este cel mai popular concurs al nostru.\r\n\r\ntable(layout). |_. preONI 2008 (\'pagina concursului\':preoni-2008)|\r\n|* !>template/preoni-2008/header?a.jpg! *{\'Runda 1\':preoni-2008/runda-1}*\r\n* *{\'Runda 2\':preoni-2008/runda-2}*\r\n* *{\'Runda 3\':preoni-2008/runda-3}*\r\n* *{\'Runda 4\':preoni-2008/runda-4}*\r\n* *{\'Runda Finala\':preoni-2008/runda-finala}*|\r\n\r\ntable(layout). \r\n|_. preONI 2007 (\'pagina concursului\':preoni-2007)|_. preONI 2006 (\'pagina concursului\':preoni-2006) |\r\n|*  !>template/preoni-2007/header?logo.jpg 70%! *{\'Runda 1\':preoni-2007/runda-1}* \r\n* *{\'Runda 2\':preoni-2007/runda-2}*\r\n* *{\'Runda 3\':preoni-2007/runda-3}*\r\n* *{\'Runda 4\':preoni-2007/runda-4}*\r\n* *{\'Runda Finala\':preoni-2007/runda-finala}*\r\n|*  !>template/preoni-2006?hlogo.gif! *{\'Runda 1\':preoni-2006/runda-1}*\r\n* *{\'Runda 2\':preoni-2006/runda-2}*\r\n* *{\'Runda 3\':preoni-2006/runda-3}*\r\n* *{\'Runda 4\':preoni-2006/runda-4}*\r\n* *{\'Finala in Focsani\':preoni-2006/finala}*|\r\n|_. preONI 2005 (\'pagina concursului\':preoni-2005)|_. preONI 2004 (\'pagina concursului\':preoni-2004)|\r\n|* *{\'Runda 1\':preoni-2005/runda-1}*\r\n* *{\'Runda 2\':preoni-2005/runda-2}*\r\n* *{\'Runda 3\':preoni-2005/runda-3}*\r\n|* *{\'Runda 1\':preoni-2004/runda-1}*\r\n* *{\'Runda 2\':preoni-2004/runda-2}*|\r\n\r\nh2(#happy). Happy Coding\r\n\r\nUn concurs infoarena mai neobisnuit. _Happy Coding inseamna programare cu zambetul pe buze, placere si distractie pura!_\r\n\r\nConcursurile Happy Coding dispun de evaluator live si au timp de lucru lejer. Nu vei mai fi stresat de pana la aflarea rezultatelor. Afli pe loc daca solutiile tale sunt bune. In plus, poti lucra si ziua si noaptea, dupa sau in timpul orelor de scoala.\r\n\r\n!>happy-coding-2005-1?logo.jpeg!\r\n\r\n* \'*Happy Coding 2008*\':happy-coding-2008\r\n* \'*Happy Coding 2007*\':happy-coding-2007\r\n* *{\'Happy coding 1 (2005)\':happy-coding-2005-1}*\r\n* *{\'Happy coding 2\':happy-coding-2005-2}*\r\n* *{\'Happy coding 3 (2006)\':happy-coding-2006}*\r\n\r\nh2(#autumn). Autumn Warmup\r\n\r\nh3(#autumn2007). Autumn Warmp 2007 (\'pagina concursului\':autumn-warmup-2007)\r\n\r\n* *{\'Runda 1\':autumn-warmup-2007/runda-1}*\r\n* *{\'Runda 2\':autumn-warmup-2007/runda-2}*\r\n* *{\'Runda 3\':autumn-warmup-2007/runda-3}*\r\n\r\nh3(#autumn2006). {\'Autumn Warmup 2006\':warm-up-2006}\r\n\r\nh2(#summer). Summer Challenge\r\n\r\nO serie noua de concursuri infoarena. Acestea se organizeaza in timpul vacantei de vara pentru cei care nu vor _sa-si iasa din mana_. :)\r\n\r\nh3(#summer2007). Summer Challenge 2007 (\'pagina concursului\':summer-challenge-2007)\r\n\r\n* *{\'Runda 1\':summer-challenge-2007/runda-1}*\r\n* *{\'Runda 2\':summer-challenge-2007/runda-2}*\r\n* *{\'Runda 3\':summer-challenge-2007/runda-3}*\r\n\r\nh3(#summer2006). Summer Challenge 2006\r\n\r\n!>summer-challenge-unu?logo!\r\n\r\n* *{\'Runda 1\':summer-challenge-unu}*\r\n* *{\'Runda 2\':summer-challenge-2}*\r\n* *{\'Runda 3\':summer-challenge-3}*\r\n\r\nh2(#others). Alte concursuri infoarena\r\n\r\n* *{\'Junior Challenge 2008\':junior-challenge-2008}*\r\n* *{\'Grigore Moisil 2008\':grigore-moisil-2008}*\r\n* *{\'Winter Challenge 2008\':winter-challenge-2008}*\r\n* *{\'Junior Challenge 2007\':junior-challenge}*\r\n* *{\'Winter Challenge\':winter-challenge-1}*\r\n* *{\'Unirea 2007\':unirea-2007}*\r\n* *{\'Grigore Moisil By Net 2006\':moisil-by-net-2006}*\r\n!>agora-finala?logo.gif! !>warm-up-2006?logo.jpeg! \r\n* *{\'Bursele agora, editia 6, finala online\':agora-finala}* \r\n* *{\'Bacalaureat 2005\':bacalaureat-2005}* \r\n* *{\'Concurs de incalzire\':warm-up-2004}* \r\n* *{\'preOJI 2004\':preoji-2004}*',13,'protected',NULL,NULL),('treapuri','Treapuri','2008-01-21 16:18:25','2008-11-28 21:42:59','h1. Treapuri\r\n\r\n(toc){width: 23em}*{text-align:center} *Conţinut:*\r\n* \'{*} Introducere\':treapuri#introducere\r\n* \'{*} Avantaje\':treapuri#avantaje\r\n* \'{*} Operaţii\':treapuri#operatii\r\n** \'- Căutare\':treapuri#cautare\r\n** \'- Rotaţii\':treapuri#rotatii\r\n** \'- Inserare\':treapuri#inserare\r\n** \'- Ştergere\':treapuri#stergere\r\n** \'- Split\':treapuri#split\r\n** \'- Join\':treapuri#join\r\n* \'{*} Concluzii\':treapuri#concluzii\r\n* \'{*} Aplicaţii\':treapuri#aplicatii\r\n* \'{*} Bibliografie\':treapuri#bibliografie\r\n\r\n\r\nÎn acest articol voi prezenta o alternativă pentru arborii binari de căutare echilibraţi, precum $AVL$, $Red-Black Trees$, $Splay Trees$ şi $B-Trees$.\r\n\r\nh2(#introducere). Introducere\r\n\r\nTreapul este un arbore binar în care fiecare nod conţine două informaţii:\r\n\r\n* $cheie$\r\n\r\n* $prioritate$\r\n\r\nStructura de date respectă doi invarianţi:\r\n\r\n* $dacă parcurgem arborele în inordine, atunci vom obţine nodurile sortate (invariantul arborilor de căutare)$\r\n\r\n* $prioritatea fiecărui nod este mai mare decât cea a fiilor săi (invariantul heapurilor)$\r\n\r\nÎn consecinţă, treapul este un arbore binar de căutare pentru chei şi un max-heap pentru priorităţi.\r\n\r\nÎn continuare, vom presupune că toate cheile şi priorităţile din treapul $T$ sunt distincte. În practică, presupunerea aceasta are un impact neglijabil.\r\n\r\nAstfel, din moment ce $T$ este un heap, nodul $v$ cu prioritatea cea mai mare trebuie să fie rădăcina. Cum este şi un arbore binar de căutare, orice nod $u$ cu $cheie(u) < cheie(v)$ se găseşte în subarborele stâng al lui $v$, şi orice nod $w$ cu $cheie(w) > cheie(v)$ se găseşte în subarborele drept.\r\n\r\nCheile şi priorităţile determină în mod unic forma unui treap. Prin inducţie se demonstrează că treapul este arborele binar obţinut prin inserarea cheilor în ordinea descrescătoare a priorităţilor. Algoritmul de inserare este cel obişnuit pentru arborii de căutare. Astfel, cum fiecare set de priorităţi asociat nodurilor va aranja arborele într-un singur mod, probabilitatea ca arborele să fie echilibrat este rezonabil de mare, fapt datorat numărului mic al arborilor rău echilibraţi în comparaţie cu cei echilibraţi. Iată şi secretul acestei structuri de date: probabilitatea infimă de a se găsi o serie de priorităţi generate aleator care să nu menţină arborele echilibrat.\r\n\r\nh2(#avantaje). Avantaje\r\n\r\nStructurile de date de heap şi de arbori binari de căutare sunt uşor de implementat şi de înţeles, iar treapurile sunt o combinaţie a acestor două concepte. Astfel, este suficient să fie înţeleşi cei doi invarianţi, după care implementarea se poate face cu uşurinţă în 20 de minute, fără antrenament. De obicei, la structuri ca $Arbori Roşu-Negrii$ trebuie folosite serii de rotaţii stânga şi dreapta complexe şi analizate o multitudine de cazuri, pe când la treapuri facem doar câte o rotaţie stânga sau dreapta la fiecare pas al algoritmului. Ei nu sunt predaţi pentru că $Arborii Roşu-Negrii$ sau $AVL$ au demonstraţia că limita celei mai lente operaţii este $O(log N)$ şi sunt exemple didactice, dar treapurile, deşi cu o demonstraţie mai grea pentru limita de $O(log N)$, ce implică probabilităţi, sunt mult mai uşor de implementat iar în practică, cu siguranţă este greu de decis care sunt mai rapizi. Sunt deci, o opţiune demnă de luat în seamă. Pe de altă parte, treapurile suportă şi alte două operaţii pe care nu le putem face cu $Arborii Roşu-Negrii$ sau cu arborii $AVL$. Aceste operaţii sunt \'$join$\':treapuri#join şi \'$split$\':treapuri#split.\r\n\r\nh2(#operatii). Operaţii\r\n\r\nCostul operaţiilor de mai jos este proporţional cu adâncimea unui nod din treap. După cum am menţionat mai sus, cu ajutorul teoriei probabilităţilor se poate deduce că adâncimea aşteptată a oricărui nod este $O(log N)$, ceea ce implică costul celor mai lente operaţii să fie $O(log N)$.\r\n\r\nMai jos avem definiţia în cod $C++$ a unui treap şi o funcţie de iniţializare, care marchează că treapul cu rădăcina $R$ este gol.\r\n\r\n== code(cpp) |\r\nstruct T {\r\n    int key;\r\n    int priority;\r\n    T *left, *right;\r\n    T() {}\r\n    T(int key, int priority, T* left, T* right) {\r\n        this->key = key, this->priority = priority,\r\n                    this->left = left, this->right = right;\r\n    }\r\n} *R, *nil;     // R radacina; nil arata un nod `gol`\r\n\r\nvoid init(T* &R) \r\n{\r\n    srand(unsigned(time(0)));\r\n\r\n    R = nil = new T();\r\n    nil->key = nil->priority = 0,\r\n        nil->left = nil->right = NULL;\r\n}\r\n==\r\n\r\nh3(#cautare). Căutare\r\n\r\nCăutarea într-un treap este identică cu cea într-un arbore binar de căutare. Pentru a verifica dacă o cheie există putem proceda în felul următor:\r\n\r\n== code(cpp) |\r\nint search(T* n, int key)\r\n{\r\n    if (n == nil)  return 0;\r\n    if (key == n->key)  return 1;\r\n    if (key < n->key)\r\n        return search(n->left, key);\r\n    else\r\n        return search(n->right, key);\r\n}\r\n==\r\n\r\nh3(#rotatii). Rotaţii\r\n\r\nRotaţiile sunt cărămizile de la baza structurii de Treap.\r\n\r\np=. !treapuri?Fig1d.png!\r\n\r\np=. _*Figura 1*: Rotaţiile într-un arbore binar de căutare. Nodurile sunt reprezentate de cercuri iar subarborii de triunghiuri. Ambele operaţii de rotaţie menţin invariantul arborilor de căutare._\r\n\r\nSă urmărim efectul rotaţiilor asupra structurii de heap a unui treap care respectă doar invariantul arborilor de căutare. Aşadar, să presupunem că arborele din figura din stânga are o structură de heap cu excepţia lui $w$ care are o prioritate mai mare decât a lui $z$. Dacă îl rotim pe $w$ spre dreapta vedem în figura din dreapta că structura de heap este satisfăcută. Din moment ce $A$ era un subarbore valid al lui $w$, va rămâne în continuare un subarbore valid. Cum $B$ şi $C$ se aflau iniţial sub $z$ ei aveau o prioritate mai mică decât a lui $z$, şi, astfel, după rotaţie ei sunt subarbori valizi pentru $z$. Este clar că $z$ este un fiu valid al lui $w$, prin presupunerea făcută iniţial. \r\n\r\nSă urmărim dacă invariantul arborilor de căutare se menţine în urma unei astfel de rotaţii.\r\n\r\n* În arborele din figura din stânga avem inegalităţile următoare: $A < w < B; z < C; w, A, B < z$. Din acestea se obţine: $A < w < B < z < C$.\r\n* În arborele din figura din dreapta avem inegalităţile următoare: $A < w; B < z < C; w < z, B, C$. Din acestea se obţine: $A < w < B < z < C$.\r\n\r\nCum am obţinut acelaşi şir de inegalităţi, am arătat existenţa invariantului arborilor de căutare.\r\n\r\nReţineţi că această rotaţie împreună cu imaginea sa în oglindă, rotaţia spre stânga dacă urmărim desenul de la dreapta spre stânga, stau la baza algoritmilor de \'$inserare$\':treapuri#inserare şi \'$ştergere$\':treapuri#stergere!\r\n\r\nPentru o rotaţie sunt necesare doar câteva operaţii cu pointeri.\r\n\r\n== code(cpp) |\r\nvoid rotleft(T* &n) \r\n{\r\n    T *t = n->left;\r\n    n->left = t->right, t->right = n;\r\n    n = t;           \r\n}\r\n\r\nvoid rotright(T* &n) \r\n{\r\n    T *t = n->right;\r\n    n->right = t->left, t->left = n;\r\n    n = t;           \r\n}\r\n\r\nvoid balance(T* &n) \r\n{\r\n    if (n->left->priority > n->priority)\r\n        rotleft(n);\r\n    else if (n->right->priority > n->priority)\r\n        rotright(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(1)$.\r\n\r\nh3(#inserare). Inserare\r\n\r\nÎn cadrul operaţiei de inserare vom atribui unui nod nou o prioritate aleatoare şi îl vom insera, conform algoritmului standard de inserare într-un arbore binar, la baza arborelui. Să presupunem că dorim să inserăm nodul $z$ cu cheia $9$ şi prioritatea $51$.\r\n\r\np=. !treapuri?Fig2c.png!\r\n\r\np=. _*Figura 2*: De la stânga la dreapta: inserarea nodului $z$. De la dreapta la stânga: ştergerea nodului $z$. Deoarece $z$ are prioritatea cea mai mare dintre toate nodurile, această inserare poate fi privită şi ca o operaţie de $split$. Subarborii stâng şi drept ai rădăcinii din ultima figură sunt chiar treapurile căutate: $T{~<~}$ şi $T{~>~}$. Invers, din $T{~<~}$ şi $T{~>~}$ se obţine, prin ştergerea rădăcinii, rezultatul operaţiei $join$._\r\n\r\nCheile formează un arbore de căutare, dar priorităţile pot să nu mai formeze un heap. Pentru a redobândi această proprietate, cât timp nodul de inserat, are prioritatea mai mare decât a părintelui său, se va executa o \'$rotaţie$\':treapuri#rotatii în $z$, o operaţie locală care scade nivelul lui $z$ cu $1$ şi creşte nivelul părintelui lui $z$ cu $1$, şi care menţine invariantul arborilor de căutare. Timpul de inserare al lui $z$ este proporţional cu adâncimea lui înainte de rotaţii - trebuie să coborâm după care să urcăm înapoi efectuând rotaţiile necesare.\r\n\r\n== code(cpp) |\r\nvoid insert(T* &n, int key, int priority)\r\n{\r\n    if (n == nil) {\r\n        n = new T(key, priority, nil, nil);\r\n        return;\r\n    }\r\n    if (key <= n->key)\r\n        insert(n->left, key, priority);\r\n    else if (key > n->key)\r\n        insert(n->right, key, priority);\r\n\r\n    balance(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#stergere). Ştergere\r\n\r\nOperaţia de ştergere este inversul operaţiei de inserare. Scopul este să aducem acest nod, fie el $z$, în poziţia unei frunze pentru a-l şterge. Astfel, pentru a menţine cei doi invarianţi (făcând excepţie de $z$) vom alege fiul cu prioritatea mai mare şi îl vom \'$roti$\':treapuri#rotatii în locul lui $z$, cât timp acesta nu este frunză. Atunci când $z$ devine frunză îl vom şterge.\r\n\r\n== code(cpp) |\r\nvoid erase(T* &n, int key) \r\n{\r\n    if (n == nil)   return ;\r\n\r\n    if (key < n->key)\r\n        erase(n->left, key);\r\n    else if (key > n->key)\r\n        erase(n->right, key);\r\n    else {    \r\n        (n->left->priority > n->right->priority) ? rotleft(n) : rotright(n);\r\n        if (n != nil)  \r\n            erase(n, key);\r\n        else {\r\n            delete n->left;\r\n            n->left = NULL;\r\n        }\r\n    }\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#split). Split\r\n\r\nUneori dorim să despărţim treapul $T$ în două treapuri $T{~<~}$ şi $T{~>~}$ astfel încât cheile din $T{~<~}$ să conţină cheile din $T$ mai mici decât o cheie $key$ dată, iar $T{~>~}$ să conţină cheile din $T$ mai mari decât aceeaşi cheie $key$. Soluţia constă în inserarea unui nod ajutător $z$ a cărui cheie este $key$ şi prioritate $infinit$. După inserare, $z$ va fi rădăcina arborelui, având prioritatea cea mai mare. Dacă ştergem rădăcina, subarborele stâng şi cel drept vor fi exact treapurile căutate.\r\n\r\nCostul operaţiei $split$ este egal cu costul operaţiei de \'$inserare$\':treapuri#inserare a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid split(T* &R, T* &Ts, T* &Tg, int key) \r\n{\r\n    insert(R, key, infinity);\r\n    Ts = R->left, Tg = R->right;\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#join). Join\r\n\r\nOperaţia $join$ constă în unirea a două treapuri $T{~<~}$ şi $T{~>~}$, unde fiecare cheie din $T{~<~}$ este mai mică decât o cheie $key$ iar oricare cheie din $T{~>~}$ este mai mare decât aceeaşi cheie $key$, într-un singur super-treap. $Join$ se realizează în mod invers operaţiei de $split$ prin crearea unei rădăcini $z$ cu cheia $key$ şi prioritate oricât, ce are ca subarbore stâng pe $T{~<~}$ iar ca subarbore drept pe $T{~>~}$, pe care o vom suprima.\r\n\r\nCostul operaţiei $join$ este egal cu costul operaţiei de \'$ştergere$\':treapuri#stergere a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid join(T* &R, T* Ts, T* Tg, int key) \r\n{\r\n    R = new T(key, 0, Ts, Tg);\r\n    erase(R, R->key);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nMai sus aţi văzut codul în $C++$ pentru cele mai importante operaţii. Puteţi face o comparaţie între funcţiile \'$erase$\':treapuri#stergere sau \'$balance$\':treapuri#rotatii cu cele din articolul următor despre arborii \'$AVL$\':multe-smenuri-de-programare-in-cc-si-nu-numai#AVL. Structura de date de Treap suportă, pe lângă operaţiile prezentate, şi operaţii precum determinarea maximului, a minimului, a succesorului sau predecesorului unei chei, sau de tipărire a conţinutului cheilor pe baza relaţiei de ordine stabilite. Şi s-ar putea să mai existe. :-) Chinezii şi ruşii foloseau intens această structură de date, în special în $Pascal$ unde nu există o librărie echivalentă cu $STL$.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\n* \'Order\':http://infoarena.ro/problema/order, info{_arena_}\r\n* \'Schi\':http://infoarena.ro/problema/schi, info{_arena_}\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* \'Eternally Confuzzled\':http://eternallyconfuzzled.com/jsw_home.aspx\r\n* \'Fast Set Operations Using Treaps\':treapuri?FastSetOperationsUsingTreaps.pdf, operaţiile \'$split$\':treapuri#split şi \'$join$\':treapuri#join sub altă formă\r\n* \'Treaps and Skip Lists\':treapuri?TreapsAndSkipLists.pdf\r\n* \'Balanced Search Trees\':treapuri?BalancedSearchTrees.pdf',3146,'public',NULL,NULL),('utilizator/andrici_cezar','Profil andrici_cezar','2008-02-20 11:15:10','2008-11-27 18:51:37','== include(page=\"template/noprofile\") ==\r\n *Despre mine*\r\n\r\n *Sunt un elev din clasa a VI aB de la Liceul de Informatica Gr.C.Moisil Iasi. Am ajuns la Nationala de Informatica si am luat mentiune. Am concurat si la olimpiada de la cls a 9a de la informatica si am luat punctajul maxim. Profesorii care m-au indrumat pe un drum bun sunt: Cornelia Ivasc si Mirela Tibu.*\r\n\r\n *Distinctii primite*\r\n\r\n_Premiul I la Informatica la ,,Urmasii lui Moisil\", la clasa a 4a!!!`````````anul 2007_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 5a!!!```````anul 2008_\r\n_Premiul III la Informatica Faza Judeteana-98 puncte, la clasa a 5a!!!````anul 2008_\r\n_Mentiune la Informatica Faza Nationala-160 puncte, la clasa a 5a!!!````anul 2008_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 9a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 5a!!!`````````anul 2008_\r\n_Premiul I la Informatica la ,,Concursul National al centrelor de Excelenta\", la clasa a 5a!!!```````anul 2008_\r\n_136 de puncte la Runda 1 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_180 de puncte la Runda 2 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_180 de puncte la Ronda 3 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n *Prieteni pe infoarena*\r\n==user(user=\"mironalex2005\" type=\"tiny\")== \r\n==user(user=\"marta_dianna\" type=\"tiny\")== \r\n==user(user=\"ancutza96\" type=\"tiny\")== \r\n==user(user=\"netedu_andrei\" type=\"tiny\")==\r\n==user(user=\"sofia_kiss\" type=\"tiny\")== \r\n==user(user=\"cezarbotolan\" type=\"tiny\")== \r\n==user(user=\"diabolik\" type=\"tiny\")== \r\n',7668,'public',NULL,NULL),('utilizator/raduzer','Radu Zernoveanu','2006-11-24 21:05:46','2008-11-14 12:38:41','h1. Despre mine\r\n\r\nSunt elev in clasa a VIII-a la Liceul International de Informatica. Ca-mi place informatica, nu cred ca mai este nevoie sa spun!... Imi place sa skiez, sa joc tenis (de masa si de camp), sa joc biliard, sa inot si imi mai plac multe alte sporturi de echipa. A... era sa uit de role, tiroliana si toate jocurile de rope course!\r\n!>utilizator/raduzer?IA.jpg!\r\n\r\n<b>Motto</b>: \"Crezi ca poti sau crezi ca nu poti, in ambele cazuri ai dreptate!\"- Henry Ford  \r\n \r\n __________( Exercitii de venit mintea la cap...........din \'Tabara Mastermind\':http://mastermind.ro )---->\r\n\r\nh2. Probleme adaugate pe Infoarena\r\n\r\n\'Submat\':problema/submat , \'Reteta\':problema/reteta , \'Pm\':problema/pm , \'2Numere\':problema/2numere , \'Puzzle\':problema/puzzle , \'Fi\':problema/fi , \'Joc7\':problema/joc7 , \'Rezervatie Naturala\':problema/rezervatie , \'Joc6\':problema/joc6\r\n\r\nh1. Profesori\r\n\r\n==user(user=\"pauldb\" type=\"tiny\")==\r\n==user(user=\"wefgef\" type=\"tiny\")==\r\n==user(user=\"silviug\" type=\"tiny\")== \r\n==user(user=\"greco\" type=\"tiny\")== \r\n==user(user=\"alexandru.mosoi\" type=\"tiny\")== si ==user(user=\"svalentin\" type=\"tiny\")==  (cei care m-au pregatit pentru JBOI 2007) \r\n\r\n\r\nh1. Distinctii primite\r\n\r\n* ONI 2008- Premiul III\r\n* JBOI 2007- Medalie de argint\r\n* ONI 2007- Premiul II\r\n* ONI 2005- mentiune(locul 4)\r\n\r\nh1. Prieteni pe Infoarena\r\n\r\n==user(user=\"CezarMocan\" type=\"tiny\")== \r\n==user(user=\"tvlad\" type=\"tiny\")== \r\n==user(user=\"savim\" type=\"tiny\")== \r\n==user(user=\"Vman\" type=\"tiny\")== \r\n==user(user=\"Protoman\" type=\"tiny\")== \r\n==user(user=\"gcosmin\" type=\"tiny\")== \r\n==user(user=\"snaked31\" type=\"tiny\")== \r\n==user(user=\"svalentin\" type=\"tiny\")==\r\n==user(user=\"bogdan2412\" type=\"tiny\")== \r\n==user(user=\"greco\" type=\"tiny\")== \r\n==user(user=\"wefgef\" type=\"tiny\")== \r\n==user(user=\"mariusdrg\" type=\"tiny\")== \r\n==user(user=\"gabitzish1\" type=\"tiny\")==\r\n==user(user=\"slayer4u\" type=\"tiny\")==\r\n==user(user=\"gavrilavlad\" type=\"tiny\")==\r\n==user(user=\"silviug\" type=\"tiny\")== \r\n==user(user=\"Florian\" type=\"tiny\")== \r\n==user(user=\"MaxDamage\" type=\"tiny\")== \r\nSper ca nu am uitat pe nimeni...\r\n\r\nh2. Prieteni din fostii colegi de la Colegiul National Tudor Vianu:\r\n\r\n==user(user=\"alexmilu\" type=\"tiny\")== \r\n==user(user=\"ye_kai008\" type=\"tiny\")== \r\n==user(user=\"Radu_Bumbacea\" type=\"tiny\")== \r\n==user(user=\"alexandra_nae\" type=\"tiny\")== \r\n==user(user=\"roberta_raileanu\" type=\"tiny\")== \r\n\r\n',3997,'protected',NULL,NULL),('probleme-cu-secvente','Probleme cu secvente','2008-11-23 19:46:37','2008-11-29 06:39:23','h1. Probleme cu secvente\r\n\r\n(Categoria _Diverse_, autor _Cosmin Negruseri_)\r\n\r\n(toc){width: 30em}*{text-align:center} *Cuprins*\r\n* \'Introducere \':probleme-cu-secvente#intro\r\n* \'Problema 1 ( _Subsecventa de suma maxima_ ) \':probleme-cu-secvente#prob1\r\n* \'Problema 2 ({_Maximum Sum_}) - 104 acm.uva.es \':probleme-cu-secvente#prob2\r\n* \'Problema 3 ({_Interogare_}) - Bursele Agora 2005/2006 Runda 1 \':probleme-cu-secvente#prob3\r\n\r\nh2(#intro). Introducere\r\n\r\nAcest articol prezinta o serie de probleme inrudite cu problema subsecventei de suma maxima, insotite de rezolvari eficiente. Problemele prezentate pot aparea oricand ca subprobleme in concursurile de programare, studierea lor marind in mod util bagajul de cunostinte al unui elev pasionat de algoritmica.\r\n\r\nh2(#prob1). Problema 1 ( _Subsecventa de suma maxima_ )\r\n\r\nSe da un şir $A$ = ( $a{~1~}$, $a{~2~}$, ... , $a{~N~}$) de numere intregi. Sa se determine o subsecventa ( $a{~i~}$, $a{~i+1~}$, ... , $a{~j~}$) care sa aiba suma maxima.\r\n\r\nh4. Exemplu\r\n\r\nPentru secventa de numere $(-1, 2, 3, -4, -2, 2, 1, -3, -2, -3, -4, 9, -2, 1, 7, 8, -19, -7, 2, 4, 3)$, o subsecventa de suma maxima este $(9, -2, 1, 7, 8)$.\r\n\r\nh3. Rezolvare\r\n\r\nPrima rezolvare care ne vine in minte este: pentru orice subsecventa sa ii determinam suma, iar apoi sa determinam maximul acestor sume. Aceasta solutie are complexitatea $O(N^3)$. \r\n\r\n== code(cpp) |\r\nbestSum = -infinit;\r\nfor (i = 1; i <= N; i++) {\r\n   for (j = i; j <= N; j++) {\r\n         sum = 0;\r\n         for (k = i; k <= j; k++) sum += a[ k ];\r\n         if (bestSum < sum) bestSum = sum;         \r\n   }\r\n}\r\n==\r\n\r\nEste evident ca se calculeaza anumite sume partiale de mai multe ori. Pentru a reduce complexitatea la $O(N^2^)$ este necesar sa observam ca suma subsecventei $a[ i..j ]$ este egala cu suma subsecventei $a[ i..j-1 ]$, la care se aduna $a[ j ]$.\r\nAlta idee este de a pastra intr-un sir $sum[ i ]$ - suma elementelor din subsecventa $a[ 1..i ]$. Pentru a determina suma elementelor din subsecventa $a[ i..j ]$ putem face calculul $sum[ i ] - sum[ j-1 ]$ (complexitate $O(N^2^)$).\r\n\r\n== code(cpp) |\r\nsum[ 0 ] = 0;\r\nfor (i = 1; i <= N; i++) sum[ i ] = a[ i ] + sum[ i - 1 ];\r\nbestSum = -infinit;\r\nfor (i = 1; i <= N; i++) {\r\n   for (j = i; j <= N; j++) {\r\n         if (bestSum < sum[ i ] – sum[ j - 1 ]) bestSum = sum[ i ] - sum[ j - 1 ];\r\n   }\r\n}\r\n==\r\n\r\nPutem sa rafinam aceasta idee calculand pentru fiecare indice $i$ numarul $best[ i ]$ ( subsecventa de suma maxima ce are capatul drept in $i$ ). Este usor de observat ca $best[ i ] = max( sum[ i ] - sum[ j-1 ] )$, unde $j$ ia valori de la $1$ la $i$. Relatia anterioara este echivalenta cu $best[ i ] = sum[ i ] – min( sum[ j-1 ] )$. Obtinem astfel un algoritm liniar care ne determina subsecventa de suma maxima.\r\n\r\n== code(cpp) |\r\nsum[ 0 ] = 0;\r\nfor (i = 1; i <= N; i++) sum[ i ] = a[ i ] + sum[ i-1 ];\r\nmin = sum[ 0 ];\r\nbestSum = -infinit;\r\nfor (i = 1; i <= N; i++) {\r\n     best[ i ] = sum[ i ] - min;\r\n     if (min > sum[ i ]) min = sum[ i ];\r\n     if (bestSum < best[ i ]) bestSum = best[ i ];\r\n}\r\n==\r\n\r\nPutem incerca o abordare bazata pe paradigma _divide et impera_. La fiecare pas impartim sirul in jumatate si aflam subsecventele de suma maxima din cele doua jumatati. Dupa aceea trebuie sa gasim subsecventa de suma maxima care are cate un capat in fiecare din cele doua jumatati ale sirului. Gasim aceasta secventa prin alipirea sufixului de suma maxima a primei jumatati cu prefixul de suma maxima a celei de-a doua.\r\n\r\n== code(cpp) |\r\nint getMaxSubsequence(int l, int r) {\r\n     if (l == r) return a[ l ];\r\n     mid = (l + r) / 2;\r\n     bestL = getMaxSubsequence(l, mid);\r\n     bestR = getMaxSubsequence(mid + 1, r);\r\n     suf = 0; \r\n     pre = 0; \r\n     maxSuf = -infinity; \r\n     maxPre = -infinity;\r\n     for (i = mid; i >= l; i--) {\r\n           suf += a[ i ];\r\n           if (maxSuf < suf) maxSuf = suf;\r\n     }\r\n     for (i = mid + 1; i <= r; i++) {\r\n           pre += a[ i ];\r\n           if (maxPre < pre) maxPre = pre;    \r\n     }\r\n     return max(bestL, max( bestR, maxPre + maxSuf ));\r\n}\r\n==\r\n\r\nO idee bazata pe paradigma programarii dinamice ar fi sa folosim un sir $best[ i ]$, reprezentand suma maxima a unei subsecvente ce se termina in $a[ i ]$. Se poate demonstra prin inductie ca sirul $best$ satisface urmatoarea recurenta $best[ i ] = max( a[ i ], best[ i-1 ] + a[ i ] )$.\r\n\r\n== code(cpp) |\r\nbestSum = a[ 1 ];\r\nfor (i = 1; i <= N; i++) {\r\n     best[ i ] = a[ i ];\r\n     if (best[ i ] < best[ i-1 ] + a[ i ]) best[ i ] = best[ i-1 ] + a[ i ];\r\n     if (bestSum < best[ i ]) bestSum = best[ i ];\r\n}\r\n==\r\n\r\nAlta idee ar fi sa partitionam sirul in subsecvente, astfel incat fiecare dintre acestea sa aiba ambele capete cat mai mici posibile si suma elementelor subsecventei sa fie negativa. Pe exemplul data avem $[-1], [2, 3, -4, -2], [2, 1, -3, -2], [-3], [-4], [9, -2, 1, 7, 8, -19, -7], [2, 4, 3]$. Este evident ca o subsecventa de suma maxima va avea primul capat la inceputul unei astfel de subsecvente. Acest lucru se explica prin faptul ca in caz contrar secventa poate fi marita in stanga ( orice secventa din cele alese pentru partitionare are toate prefixele de suma pozitiva, in afara de prefixul ce reprezinta intreaga subsecventa ). De asemenea, orice subsecventa de suma maxima nu va contine elemente din alta parte a partitiei, pentru ca daca subsecventa se intinde pe mai multe parti, atunci putem elimina prefixul subsecventei care reprezinta o parte a partitiei, acea parte avand suma negativa.\r\n\r\n== code(cpp) |\r\nsum = -infinit; bestSum = -infinit;\r\nfor (i = 1; i <= N; i++) {\r\n      sum += a[ i ];\r\n      if (sum < 0) {\r\n         sum = 0;\r\n         continue;\r\n      } else if (sum >= bestSum) bestSum = sum;      \r\n}\r\n==\r\n\r\nh2(#prob2). Problema 2 ({_Maximum Sum_}) - 104 acm.uva.es\r\n\r\nSe da o matrice de dimensiuni $NxN$ cu elemente intregi. Se cere determinarea unei submatrici a carei elemente au suma maxima. \r\n\r\nh4. Exemplu\r\n\r\nPentru matricea<tex>\\[ \\left( \\begin{array}{cccc}0 & -2 & -7 & 0 \\\\9 & 2 & -6 & 2 \\\\-4 & 1 & -4 & 1 \\\\-1 & 8 & 0 & -2 \\end{array} \\right)\\]</tex>submatricea de sumă maximă este următoarea:<tex>\\[ \\left( \\begin{array}{cc}9 & 2 \\\\-4 & 1 \\\\-1 & 8 \\end{array} \\right)\\]</tex>\r\n\r\nh3. Rezolvare\r\n\r\nPutem folosi trucul construirii sumelor partiale prezentat in rezolvarea anterioara, pentru cazul *2D*. Pastram in $sum[i][j]$ suma tuturor elementelor $a[i{~1~}][j{~1~}]$ cu proprietatea ca $1 <= i{~1~} <= i$, si $1 <= j{~1~} <= j$. Putem calcula sumele prin metoda programarii dinamice (complexitate $O(N^2^)$) folosind formula $sum[i][j] = a[i][j] + sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1]$. Acum pentru a calcula suma elementelor din matricea cu colturile $(i{~1~}, j{~1~}), (i{~2~}, j{~2~})$, unde $i{~1~} <= i{~2~} si j{~1~} <= j{~2~}$ este suficient sa facem calculul $sum[i{~2~}][j{~2~}] - sum[i{~1~}-1][j{~2~}] - sum[i{~2~}][j{~1~}-1] + sum[i{~1~}-1][j{~1~}-1]$. Astfel putem evalua suma din fiecare submatrice in timp constant, deci rezolvarea are ordinul de complexitate $O(N^4^)$.\r\nO alta idee ar fi ca pentru fiecare pereche $(i{~1~}, i{~2~})$ fixate sa determinam perechea optima $(j{~1~}, j{~2~})$. Daca avem liniile $i{~1~}$ si $i{~2~}$ fixate atunci problema se transforma din una bidimensionala in una unidimensionala. Astfel pentru fiecare coloana $j$ vom considera $b[j]$ ca suma a elementelor $a[i][j]$ cu proprietatea ca $i{~1~} <= i <= i{~2~}$. In exemplul nostru daca $i{~1~} = 2$ si $i{~2~} = 3$, atunci avem $b{~1~} = 9 + (-4)$, $b{~2~} = 2 + 1$, $b{~3~} = (-6) + (-4)$ si $b{~4~} = 2 + 1$. Pentru a rezolva problema unidimensionala folosim unul din algoritmii liniari prezentati mai sus, astfel obtinandu-se un algoritm de complexitate totala $O(N^3^)$. Acest truc de a fixa doua linii pentru a transforma problema in una unidimensionala este util in multe probleme pe matrice sau cu puncte in plan.\r\nCel mai bun algoritm cunoscut pentru aceasta problema are complexitatea <tex>O(N^{3((\\log \\log N)/\\log N)^{1/2}})</tex> si este mai mult un algoritm teoretic decat unul practic, usor implementabil.\r\n\r\nh2(#prob3). Problema 3 ({_Interogare_}) - Bursele Agora 2005/2006 Runda 1\r\n\r\nSe considera un sir $A = (a{~1~}, a{~2~}, ..., a{~N~}) (-100.000 <= a{~i~} <= 100.000)$, format din $N$ numere intregi, precum si $M$ perechi de numere $(x, y) (1 <= N, M <= 100.000)$. Pentru fiecare pereche de indici $(x, y) (1 <= x <= y <= N)$ trebuie determinata subsecventa de suma maxima a subsirului $a{~x~}, a{~x+1~}, ..., a{~y~}$ , subsecventele alese trebuie ss contins cel putin un element. \r\n\r\nh4. Exemplu\r\n\r\nPentru sirul $(-1, 2, 3, -2, 4, -3, 8, -3, 1)$ si intervalele $[1, 5]$, $[4, 8]$ si $[6, 6]$ avem solutiile $7, 9, -3$, date de numerele ingrosate $([-1, *2*, *3*, *-2*, *4*], -3, 8, -3, 1, -1, 2, 3, [-2, *4*, *-3*, *8*, -3], 1, -1, 2, 3, -2, 4, [*-3*], 8, -3, 1)$.\r\n\r\nh3. Rezolvare\r\n\r\nFolosind algoritmii liniari din prima problema obtinem un algoritm de complexitate $O(MN)$. Sa vedem cum putem reduce complexitatea folosind alte abordari. Mai intai calculam sirul $sum$ al sumelor partiale. Apoi impartim sirul in $k$ subsecvente de lungimi egale $[n/k]$, pentru fiecare secventa pastrand urmatoarele informatii:\r\n * $max[i]$ - cea mai mare valoare $sum[j]$, unde $n/k * (i-1) < j <= n/k * i$;\r\n * $min[i]$ - cel mai mic $sum[j-1]$, unde $n/k * (i-1) < j <= n/k * i$;\r\n * $best[i]$ - valoarea subsecventei de suma maxima a secventei curente.\r\nAcum, daca vrem sa aflam subsecventa de suma maxima a subsecventei $a[x..y]$, avem doua cazuri posibile:\r\n 1. Daca elementele de indice $x$ si $y$ apartin aceleiasi subsecvente din partitie, atunci putem gasi subsecventa de suma maxima folosind algoritmul liniar direct pe sirul $a[x..y]$ (complexitate $O(n/k)$). \r\n 2. Daca ele nu sunt in aceeasi secventa atunci vom imparti sirul $a[x..y]$ in un prefix de subsecventa din cele ce apartin partitionarii, in un sufix de subsecventa si in zero sau mai multe subsecvente complete ce apartin partitionarii. Acum vom rezolva problema pentru sufix si prefix metoda liniara ( {$O(n/k)$} ), iar apoi in $O(1)$ vom determina pentru fiecare bucata în care este spart sirul $a[x..y]$, subsecventa ei de suma maxima.\r\nMai ramane sa gasim subsecventa de suma maxima cu capatul in bucati diferite. Pentru doua bucati fixate $i <= j$, subsecventa de suma maxima ce are un capat apartinand primei bucati si $j$ apartinand celei de a doua bucati, subsecventa de suma maxima are valoarea $max[j] – min[i]$. Determinarea subsecventei de suma maxima cu capetele in bucati diferite devine astfel de complexitate $O(k)$. Deci pentru a rezolva o intrebare trebuie sa facem $O(n/k + k)$ calcule. Pentru a reduce complexitatea problemei obtinem pe $k = sqrt(n)$. Complexitatea totala a acestei solutii este $O(N + M sqrt(N))$.\r\n\r\nSa vedem ce se intampla pe exemplu:\r\n a:     $-1 2 3 -2 4 -3  8  -3 1$\r\n sum: $0 -1 1 4  2 6  3  11  8 9$\r\n\r\nSirul e impartit in trei subsecvente $[-1, 2, 3], [-2, 4, -3], [8, -3, 1]$.\r\n max:  $ 4 6 11$\r\n min:  $-1 2 8$\r\n best: $ 5 4 8$ \r\nPentru a raspunde la intrebarea $[1, 5]$ vedem ca acest interval e inpartit in $[1..3]$ si $[4..5]$. Solutia optima pentru $[1..3]$ o avem deja in $best[1] = 5$. Solutia optima pentru $[4..5]$ o determinam folosind algoritmul liniar, ea fiind 4. Acum pentru a determina subsecventa de suma maxima cu un capat in intervalul $[1, 3]$ si celalalt in intervalul $[4, 5]$ folosim $max(sum[i]) - min(sum[j-1])$, unde $4 <= i <= 5$ si $1 <= j <= 3$. Valoarea $max(sum[i])$ o gasim ca fiind $6$ parcurgand intervalul $[4, 5]$, iar valoarea $min(sum[j-1])$ o avem deja calculata in $min[1]$. De aici obtinem rezultatul $7$.\r\n\r\nO solutie similara poate fi realizata cu ajutorul arborilor de intervale. Mai intai cream arborele de intervale. Pentru fiecare interval aflam elementele $min$, $max$ si $best$ astfel $min[x..y] = minim(min[x..(x+y)/2], min[(x+y)/2 + 1 .. y])$, $max[x..y] = maxim(max[x..(x+y)/2], max[(x+y)/2 + 1 .. y])$, $best[x..y] = maxim(best[x..(x+y)/2], maxim(best[(x+y)/2 + 1 .. y], max[(x+y)/2 + 1 .. y] - min[x..(x+y)/2]))$. Acum pentru a raspunde la intrebarile din problema fiecare interval va fi impartit in $O(log N)$ subintervale canonice care apar in arborele de intervale. Apoi printr-o parcurgere asemanatoare celei din rezolvarea anterioara se poate obtine rezultatul pentru fiecare intrebare in $O(log N)$. Solutia va avea complexitatea $O(N + M log N)$.\r\nIn urmatorul desen observam structura unui arbore de intervale pentru un sir cu $16$ elemente. Daca se pune intrebarea $[2, 11]$ acest interval va fi spart in intervalele $[2, 2], [3, 4], [5, 8], [9, 10], [11, 11]$.\r\n\r\nPrezentam procedura de construire a arborelui, implementata in _java_:\r\n\r\n== code(java) |\r\npublic void build_tree(int index, int low, int high) {\r\n    if (low == high) {\r\n        if (low != 0) aint[index] = new Node(low, high, a[low] - a[low - 1], a[low], a[low]);\r\n        else aint[index] = new Node(low, high, 0, 0, 0);\r\n    }\r\n    else {\r\n        aint[index] = new Node(low, high, -infinity, -infinity, infinity);\r\n        int mid = (low + high) / 2;\r\n        build_tree(2 * index, low, mid);\r\n        build_tree(2 * index + 1, mid + 1, high);\r\n        aint[index].maxS = Math.max(aint[2 * index].maxS,Math.max(aint[2 * index + 1].maxS,aint[2 * index + 1].max - aint[2 * index].min));\r\n        aint[index].max = Math.max(aint[2 * index].max,aint[2 * index + 1].max);\r\n        aint[index].min = Math.min(aint[2 * index].min,aint[2 * index + 1].min);\r\n    }\r\n}\r\n==\r\n\r\nSi procedura care raspunde la intrebari tot in _java_:\r\n\r\n== code(java) |\r\nlong minPrefix; \r\nint x, y;\r\npublic long queryTree(int index, int low, int high) {\r\n    if (x <= low && high <= y) {\r\n        long maxRet = aint[index].maxS;\r\n        if (minPrefix != infinity) {\r\n            maxRet = Math.max(maxRet, aint[index].max - minPrefix);\r\n        }\r\n        minPrefix = Math.min(minPrefix, aint[index].min);\r\n        return maxRet;\r\n    }\r\n    else {\r\n        int mid = (low + high) / 2;\r\n        if (x <= mid && mid < y) return  Math.max(queryTree(2 * index, low, mid), queryTree(2 * index + 1, mid + 1, high));\r\n        else if (x > mid) return queryTree(2 * index + 1, mid + 1, high);\r\n            else return queryTree(2 * index, low, mid);\r\n    }\r\n}\r\n==\r\n\r\nh2(#prob4). Problema 4 - ACM ICPC NWERC 97, olimpiada online 2000, campion 2001\r\n\r\nSe da un sir $(a{~1~}, a{~2~}, ..., a{~N~})$ format din $N$ numere intregi. Se cere sa se determine subsecventa $a[i..j]$ care are modulul sumei elementelor minim.\r\n\r\nh4. Exemplu\r\n\r\nPentru sirul $(2, 8, -6, -6, 9, 4, -3)$, subsecventa este $(4, -3)$, avand suma in modul $1 = |4 - 3|$.\r\n\r\nh3. Rezolvare\r\n\r\nFacem mai intai sirul sumelor partiale. Pentru oricare doua elemente $sum[i]$ si $sum[j]$ ($i != j$) modulul sumei unei subsecvente din sir va fi $|sum[i] - sum[j]|$. Daca $i < j$ atunci secventa va fi $a[i+1..j]$, iar daca $j < i$ atunci secventa va fi $a[j+1 .. i]$. Astfel, pentru a gasi subsecventa de modul minim trebuie de fapt sa gasim perechea de indici $i$ si $j$ astfel ca $|sum[i] - sum[j]|$ sa fie minim. Sortand sirul sumelor partiale si luand o pereche de indici $i < j$, atunci $sum[i] < sum[j]$, iar $|sum[j] - sum[i]| = sum[j] - sum[i]$. Pentru a gasi perechea $(i, j)$ pentru care $i < j$ si $sum[j] - sum[i]$ este minim, trebuie ca $i$ sa fie egal cu $j + 1$. Astfel obtinem un algoritm de complexitate $O(N log N)$.\r\n\r\nSa vedem cum merge pe exemplul prezentat:\r\n a:     $2  8 -6 -6 9  4 -3$\r\n sum: $0 2 10  4 -2 7 11  8$\r\n ind: $0 1  2  3  4 5  6  7$\r\nIn sirul $ind$ vom pastra indicii reali ai sumelor parţiale.\r\n\r\nDupa sortare avem:\r\n sum:  $ -2  0 2 4 7 8 10 11$ \r\n ind:   $ 4  0 1 4 5 7  2  6$ \r\nO secventa de modul $2$ ar fi cea reprezentata de sumele $8$ si $10$ cu indicii $7$ si $2$. Aceasta secventa este $(-6, -6, 9, 4, -3)$.\r\nObservam ca cea mai mica diferenta intre termeni consecutivi e cea dintre $8$ si $7$ care au indicii $7$ si $5$, de unde obtinem ca subsecventa de modul minim este $(4, -3)$. ',4297,'public',NULL,NULL),('treapuri','Treapuri','2008-01-21 16:18:25','2008-11-29 11:50:05','h1. Treapuri\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'{*} Introducere\':treapuri#introducere\r\n* \'{*} Avantaje\':treapuri#avantaje\r\n* \'{*} Operaţii\':treapuri#operatii\r\n** \'- Căutare\':treapuri#cautare\r\n** \'- Rotaţii\':treapuri#rotatii\r\n** \'- Inserare\':treapuri#inserare\r\n** \'- Ştergere\':treapuri#stergere\r\n** \'- Split\':treapuri#split\r\n** \'- Join\':treapuri#join\r\n* \'{*} Concluzii\':treapuri#concluzii\r\n* \'{*} Aplicaţii\':treapuri#aplicatii\r\n* \'{*} Bibliografie\':treapuri#bibliografie\r\n\r\n\r\nÎn acest articol voi prezenta o alternativă pentru arborii binari de căutare echilibraţi, precum $AVL$, $Red-Black Trees$, $Splay Trees$ şi $B-Trees$.\r\n\r\nh2(#introducere). Introducere\r\n\r\nTreapul este un arbore binar în care fiecare nod conţine două informaţii:\r\n\r\n* $cheie$\r\n\r\n* $prioritate$\r\n\r\nStructura de date respectă doi invarianţi:\r\n\r\n* $dacă parcurgem arborele în inordine, atunci vom obţine nodurile sortate (invariantul arborilor de căutare)$\r\n\r\n* $prioritatea fiecărui nod este mai mare decât cea a fiilor săi (invariantul heapurilor)$\r\n\r\nÎn consecinţă, treapul este un arbore binar de căutare pentru chei şi un max-heap pentru priorităţi.\r\n\r\nÎn continuare, vom presupune că toate cheile şi priorităţile din treapul $T$ sunt distincte. În practică, presupunerea aceasta are un impact neglijabil.\r\n\r\nAstfel, din moment ce $T$ este un heap, nodul $v$ cu prioritatea cea mai mare trebuie să fie rădăcina. Cum este şi un arbore binar de căutare, orice nod $u$ cu $cheie(u) < cheie(v)$ se găseşte în subarborele stâng al lui $v$, şi orice nod $w$ cu $cheie(w) > cheie(v)$ se găseşte în subarborele drept.\r\n\r\nCheile şi priorităţile determină în mod unic forma unui treap. Prin inducţie se demonstrează că treapul este arborele binar obţinut prin inserarea cheilor în ordinea descrescătoare a priorităţilor. Algoritmul de inserare este cel obişnuit pentru arborii de căutare. Astfel, cum fiecare set de priorităţi asociat nodurilor va aranja arborele într-un singur mod, probabilitatea ca arborele să fie echilibrat este rezonabil de mare, fapt datorat numărului mic al arborilor rău echilibraţi în comparaţie cu cei echilibraţi. Iată şi secretul acestei structuri de date: probabilitatea infimă de a se găsi o serie de priorităţi generate aleator care să nu menţină arborele echilibrat.\r\n\r\nh2(#avantaje). Avantaje\r\n\r\nStructurile de date de heap şi de arbori binari de căutare sunt uşor de implementat şi de înţeles, iar treapurile sunt o combinaţie a acestor două concepte. Astfel, este suficient să fie înţeleşi cei doi invarianţi, după care implementarea se poate face cu uşurinţă în 20 de minute, fără antrenament. De obicei, la structuri ca $Arbori Roşu-Negrii$ trebuie folosite serii de rotaţii stânga şi dreapta complexe şi analizate o multitudine de cazuri, pe când la treapuri facem doar câte o rotaţie stânga sau dreapta la fiecare pas al algoritmului. Ei nu sunt predaţi pentru că $Arborii Roşu-Negrii$ sau $AVL$ au demonstraţia că limita celei mai lente operaţii este $O(log N)$ şi sunt exemple didactice, dar treapurile, deşi cu o demonstraţie mai grea pentru limita de $O(log N)$, ce implică probabilităţi, sunt mult mai uşor de implementat iar în practică, cu siguranţă este greu de decis care sunt mai rapizi. Sunt deci, o opţiune demnă de luat în seamă. Pe de altă parte, treapurile suportă şi alte două operaţii pe care nu le putem face cu $Arborii Roşu-Negrii$ sau cu arborii $AVL$. Aceste operaţii sunt \'$join$\':treapuri#join şi \'$split$\':treapuri#split.\r\n\r\nh2(#operatii). Operaţii\r\n\r\nCostul operaţiilor de mai jos este proporţional cu adâncimea unui nod din treap. După cum am menţionat mai sus, cu ajutorul teoriei probabilităţilor se poate deduce că adâncimea aşteptată a oricărui nod este $O(log N)$, ceea ce implică costul celor mai lente operaţii să fie $O(log N)$.\r\n\r\nMai jos avem definiţia în cod $C++$ a unui treap şi o funcţie de iniţializare, care marchează că treapul cu rădăcina $R$ este gol.\r\n\r\n== code(cpp) |\r\nstruct T {\r\n    int key;\r\n    int priority;\r\n    T *left, *right;\r\n    T() {}\r\n    T(int key, int priority, T* left, T* right) {\r\n        this->key = key, this->priority = priority,\r\n                    this->left = left, this->right = right;\r\n    }\r\n} *R, *nil;     // R radacina; nil arata un nod `gol`\r\n\r\nvoid init(T* &R) \r\n{\r\n    srand(unsigned(time(0)));\r\n\r\n    R = nil = new T();\r\n    nil->key = nil->priority = 0,\r\n        nil->left = nil->right = NULL;\r\n}\r\n==\r\n\r\nh3(#cautare). Căutare\r\n\r\nCăutarea într-un treap este identică cu cea într-un arbore binar de căutare. Pentru a verifica dacă o cheie există putem proceda în felul următor:\r\n\r\n== code(cpp) |\r\nint search(T* n, int key)\r\n{\r\n    if (n == nil)  return 0;\r\n    if (key == n->key)  return 1;\r\n    if (key < n->key)\r\n        return search(n->left, key);\r\n    else\r\n        return search(n->right, key);\r\n}\r\n==\r\n\r\nh3(#rotatii). Rotaţii\r\n\r\nRotaţiile sunt cărămizile de la baza structurii de Treap.\r\n\r\np=. !treapuri?Fig1d.png!\r\n\r\np=. _*Figura 1*: Rotaţiile într-un arbore binar de căutare. Nodurile sunt reprezentate de cercuri iar subarborii de triunghiuri. Ambele operaţii de rotaţie menţin invariantul arborilor de căutare._\r\n\r\nSă urmărim efectul rotaţiilor asupra structurii de heap a unui treap care respectă doar invariantul arborilor de căutare. Aşadar, să presupunem că arborele din figura din stânga are o structură de heap cu excepţia lui $w$ care are o prioritate mai mare decât a lui $z$. Dacă îl rotim pe $w$ spre dreapta vedem în figura din dreapta că structura de heap este satisfăcută. Din moment ce $A$ era un subarbore valid al lui $w$, va rămâne în continuare un subarbore valid. Cum $B$ şi $C$ se aflau iniţial sub $z$ ei aveau o prioritate mai mică decât a lui $z$, şi, astfel, după rotaţie ei sunt subarbori valizi pentru $z$. Este clar că $z$ este un fiu valid al lui $w$, prin presupunerea făcută iniţial. \r\n\r\nSă urmărim dacă invariantul arborilor de căutare se menţine în urma unei astfel de rotaţii.\r\n\r\n* În arborele din figura din stânga avem inegalităţile următoare: $A < w < B; z < C; w, A, B < z$. Din acestea se obţine: $A < w < B < z < C$.\r\n* În arborele din figura din dreapta avem inegalităţile următoare: $A < w; B < z < C; w < z, B, C$. Din acestea se obţine: $A < w < B < z < C$.\r\n\r\nCum am obţinut acelaşi şir de inegalităţi, am arătat existenţa invariantului arborilor de căutare.\r\n\r\nReţineţi că această rotaţie împreună cu imaginea sa în oglindă, rotaţia spre stânga dacă urmărim desenul de la dreapta spre stânga, stau la baza algoritmilor de \'$inserare$\':treapuri#inserare şi \'$ştergere$\':treapuri#stergere!\r\n\r\nPentru o rotaţie sunt necesare doar câteva operaţii cu pointeri.\r\n\r\n== code(cpp) |\r\nvoid rotleft(T* &n) \r\n{\r\n    T *t = n->left;\r\n    n->left = t->right, t->right = n;\r\n    n = t;           \r\n}\r\n\r\nvoid rotright(T* &n) \r\n{\r\n    T *t = n->right;\r\n    n->right = t->left, t->left = n;\r\n    n = t;           \r\n}\r\n\r\nvoid balance(T* &n) \r\n{\r\n    if (n->left->priority > n->priority)\r\n        rotleft(n);\r\n    else if (n->right->priority > n->priority)\r\n        rotright(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(1)$.\r\n\r\nh3(#inserare). Inserare\r\n\r\nÎn cadrul operaţiei de inserare vom atribui unui nod nou o prioritate aleatoare şi îl vom insera, conform algoritmului standard de inserare într-un arbore binar, la baza arborelui. Să presupunem că dorim să inserăm nodul $z$ cu cheia $9$ şi prioritatea $51$.\r\n\r\np=. !treapuri?Fig2c.png!\r\n\r\np=. _*Figura 2*: De la stânga la dreapta: inserarea nodului $z$. De la dreapta la stânga: ştergerea nodului $z$. Deoarece $z$ are prioritatea cea mai mare dintre toate nodurile, această inserare poate fi privită şi ca o operaţie de $split$. Subarborii stâng şi drept ai rădăcinii din ultima figură sunt chiar treapurile căutate: $T{~<~}$ şi $T{~>~}$. Invers, din $T{~<~}$ şi $T{~>~}$ se obţine, prin ştergerea rădăcinii, rezultatul operaţiei $join$._\r\n\r\nCheile formează un arbore de căutare, dar priorităţile pot să nu mai formeze un heap. Pentru a redobândi această proprietate, cât timp nodul de inserat, are prioritatea mai mare decât a părintelui său, se va executa o \'$rotaţie$\':treapuri#rotatii în $z$, o operaţie locală care scade nivelul lui $z$ cu $1$ şi creşte nivelul părintelui lui $z$ cu $1$, şi care menţine invariantul arborilor de căutare. Timpul de inserare al lui $z$ este proporţional cu adâncimea lui înainte de rotaţii - trebuie să coborâm după care să urcăm înapoi efectuând rotaţiile necesare.\r\n\r\n== code(cpp) |\r\nvoid insert(T* &n, int key, int priority)\r\n{\r\n    if (n == nil) {\r\n        n = new T(key, priority, nil, nil);\r\n        return;\r\n    }\r\n    if (key <= n->key)\r\n        insert(n->left, key, priority);\r\n    else if (key > n->key)\r\n        insert(n->right, key, priority);\r\n\r\n    balance(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#stergere). Ştergere\r\n\r\nOperaţia de ştergere este inversul operaţiei de inserare. Scopul este să aducem acest nod, fie el $z$, în poziţia unei frunze pentru a-l şterge. Astfel, pentru a menţine cei doi invarianţi (făcând excepţie de $z$) vom alege fiul cu prioritatea mai mare şi îl vom \'$roti$\':treapuri#rotatii în locul lui $z$, cât timp acesta nu este frunză. Atunci când $z$ devine frunză îl vom şterge.\r\n\r\n== code(cpp) |\r\nvoid erase(T* &n, int key) \r\n{\r\n    if (n == nil)   return ;\r\n\r\n    if (key < n->key)\r\n        erase(n->left, key);\r\n    else if (key > n->key)\r\n        erase(n->right, key);\r\n    else {    \r\n        (n->left->priority > n->right->priority) ? rotleft(n) : rotright(n);\r\n        if (n != nil)  \r\n            erase(n, key);\r\n        else {\r\n            delete n->left;\r\n            n->left = NULL;\r\n        }\r\n    }\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#split). Split\r\n\r\nUneori dorim să despărţim treapul $T$ în două treapuri $T{~<~}$ şi $T{~>~}$ astfel încât cheile din $T{~<~}$ să conţină cheile din $T$ mai mici decât o cheie $key$ dată, iar $T{~>~}$ să conţină cheile din $T$ mai mari decât aceeaşi cheie $key$. Soluţia constă în inserarea unui nod ajutător $z$ a cărui cheie este $key$ şi prioritate $infinit$. După inserare, $z$ va fi rădăcina arborelui, având prioritatea cea mai mare. Dacă ştergem rădăcina, subarborele stâng şi cel drept vor fi exact treapurile căutate.\r\n\r\nCostul operaţiei $split$ este egal cu costul operaţiei de \'$inserare$\':treapuri#inserare a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid split(T* &R, T* &Ts, T* &Tg, int key) \r\n{\r\n    insert(R, key, infinity);\r\n    Ts = R->left, Tg = R->right;\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#join). Join\r\n\r\nOperaţia $join$ constă în unirea a două treapuri $T{~<~}$ şi $T{~>~}$, unde fiecare cheie din $T{~<~}$ este mai mică decât o cheie $key$ iar oricare cheie din $T{~>~}$ este mai mare decât aceeaşi cheie $key$, într-un singur super-treap. $Join$ se realizează în mod invers operaţiei de $split$ prin crearea unei rădăcini $z$ cu cheia $key$ şi prioritate oricât, ce are ca subarbore stâng pe $T{~<~}$ iar ca subarbore drept pe $T{~>~}$, pe care o vom suprima.\r\n\r\nCostul operaţiei $join$ este egal cu costul operaţiei de \'$ştergere$\':treapuri#stergere a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid join(T* &R, T* Ts, T* Tg, int key) \r\n{\r\n    R = new T(key, 0, Ts, Tg);\r\n    erase(R, R->key);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nMai sus aţi văzut codul în $C++$ pentru cele mai importante operaţii. Puteţi face o comparaţie între funcţiile \'$erase$\':treapuri#stergere sau \'$balance$\':treapuri#rotatii cu cele din articolul următor despre arborii \'$AVL$\':multe-smenuri-de-programare-in-cc-si-nu-numai#AVL. Structura de date de Treap suportă, pe lângă operaţiile prezentate, şi operaţii precum determinarea maximului, a minimului, a succesorului sau predecesorului unei chei, sau de tipărire a conţinutului cheilor pe baza relaţiei de ordine stabilite. Şi s-ar putea să mai existe. :-) Chinezii şi ruşii foloseau intens această structură de date, în special în $Pascal$ unde nu există o librărie echivalentă cu $STL$.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\n* \'Order\':http://infoarena.ro/problema/order, info{_arena_}\r\n* \'Schi\':http://infoarena.ro/problema/schi, info{_arena_}\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* \'Eternally Confuzzled\':http://eternallyconfuzzled.com/jsw_home.aspx\r\n* \'Fast Set Operations Using Treaps\':http://www.cs.cmu.edu/afs/cs.cmu.edu/project/scandal/public/papers/treaps-spaa98.pdf, operaţiile \'$split$\':treapuri#split şi \'$join$\':treapuri#join sub altă formă\r\n* \'Treaps and Skip Lists\':http://compgeom.cs.uiuc.edu/~jeffe/teaching/algorithms/notes/06-treaps.pdf\r\n* \'Balanced Search Trees\':http://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15451-s07/www/lecture_notes/lect0208.pdf',3146,'public',NULL,NULL),('treapuri','Treapuri','2008-01-21 16:18:25','2008-11-29 11:50:27','h1. Treapuri\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'{*} Introducere\':treapuri#introducere\r\n* \'{*} Avantaje\':treapuri#avantaje\r\n* \'{*} Operaţii\':treapuri#operatii\r\n** \'- Căutare\':treapuri#cautare\r\n** \'- Rotaţii\':treapuri#rotatii\r\n** \'- Inserare\':treapuri#inserare\r\n** \'- Ştergere\':treapuri#stergere\r\n** \'- Split\':treapuri#split\r\n** \'- Join\':treapuri#join\r\n* \'{*} Concluzii\':treapuri#concluzii\r\n* \'{*} Aplicaţii\':treapuri#aplicatii\r\n* \'{*} Bibliografie\':treapuri#bibliografie\r\n\r\n\r\nÎn acest articol voi prezenta o alternativă pentru arborii binari de căutare echilibraţi, precum $AVL$, $Red-Black Trees$, $Splay Trees$ şi $B-Trees$.\r\n\r\nh2(#introducere). Introducere\r\n\r\nTreapul este un arbore binar în care fiecare nod conţine două informaţii:\r\n\r\n* $cheie$\r\n\r\n* $prioritate$\r\n\r\nStructura de date respectă doi invarianţi:\r\n\r\n* $dacă parcurgem arborele în inordine, atunci vom obţine nodurile sortate (invariantul arborilor de căutare)$\r\n\r\n* $prioritatea fiecărui nod este mai mare decât cea a fiilor săi (invariantul heapurilor)$\r\n\r\nÎn consecinţă, treapul este un arbore binar de căutare pentru chei şi un max-heap pentru priorităţi.\r\n\r\nÎn continuare, vom presupune că toate cheile şi priorităţile din treapul $T$ sunt distincte. În practică, presupunerea aceasta are un impact neglijabil.\r\n\r\nAstfel, din moment ce $T$ este un heap, nodul $v$ cu prioritatea cea mai mare trebuie să fie rădăcina. Cum este şi un arbore binar de căutare, orice nod $u$ cu $cheie(u) < cheie(v)$ se găseşte în subarborele stâng al lui $v$, şi orice nod $w$ cu $cheie(w) > cheie(v)$ se găseşte în subarborele drept.\r\n\r\nCheile şi priorităţile determină în mod unic forma unui treap. Prin inducţie se demonstrează că treapul este arborele binar obţinut prin inserarea cheilor în ordinea descrescătoare a priorităţilor. Algoritmul de inserare este cel obişnuit pentru arborii de căutare. Astfel, cum fiecare set de priorităţi asociat nodurilor va aranja arborele într-un singur mod, probabilitatea ca arborele să fie echilibrat este rezonabil de mare, fapt datorat numărului mic al arborilor rău echilibraţi în comparaţie cu cei echilibraţi. Iată şi secretul acestei structuri de date: probabilitatea infimă de a se găsi o serie de priorităţi generate aleator care să nu menţină arborele echilibrat.\r\n\r\nh2(#avantaje). Avantaje\r\n\r\nStructurile de date de heap şi de arbori binari de căutare sunt uşor de implementat şi de înţeles, iar treapurile sunt o combinaţie a acestor două concepte. Astfel, este suficient să fie înţeleşi cei doi invarianţi, după care implementarea se poate face cu uşurinţă în 20 de minute, fără antrenament. De obicei, la structuri ca $Arbori Roşu-Negrii$ trebuie folosite serii de rotaţii stânga şi dreapta complexe şi analizate o multitudine de cazuri, pe când la treapuri facem doar câte o rotaţie stânga sau dreapta la fiecare pas al algoritmului. Ei nu sunt predaţi pentru că $Arborii Roşu-Negrii$ sau $AVL$ au demonstraţia că limita celei mai lente operaţii este $O(log N)$ şi sunt exemple didactice, dar treapurile, deşi cu o demonstraţie mai grea pentru limita de $O(log N)$, ce implică probabilităţi, sunt mult mai uşor de implementat iar în practică, cu siguranţă este greu de decis care sunt mai rapizi. Sunt deci, o opţiune demnă de luat în seamă. Pe de altă parte, treapurile suportă şi alte două operaţii pe care nu le putem face cu $Arborii Roşu-Negrii$ sau cu arborii $AVL$. Aceste operaţii sunt \'$join$\':treapuri#join şi \'$split$\':treapuri#split.\r\n\r\nh2(#operatii). Operaţii\r\n\r\nCostul operaţiilor de mai jos este proporţional cu adâncimea unui nod din treap. După cum am menţionat mai sus, cu ajutorul teoriei probabilităţilor se poate deduce că adâncimea aşteptată a oricărui nod este $O(log N)$, ceea ce implică costul celor mai lente operaţii să fie $O(log N)$.\r\n\r\nMai jos avem definiţia în cod $C++$ a unui treap şi o funcţie de iniţializare, care marchează că treapul cu rădăcina $R$ este gol.\r\n\r\n== code(cpp) |\r\nstruct T {\r\n    int key;\r\n    int priority;\r\n    T *left, *right;\r\n    T() {}\r\n    T(int key, int priority, T* left, T* right) {\r\n        this->key = key, this->priority = priority,\r\n                    this->left = left, this->right = right;\r\n    }\r\n} *R, *nil;     // R radacina; nil arata un nod `gol`\r\n\r\nvoid init(T* &R) \r\n{\r\n    srand(unsigned(time(0)));\r\n\r\n    R = nil = new T();\r\n    nil->key = nil->priority = 0,\r\n        nil->left = nil->right = NULL;\r\n}\r\n==\r\n\r\nh3(#cautare). Căutare\r\n\r\nCăutarea într-un treap este identică cu cea într-un arbore binar de căutare. Pentru a verifica dacă o cheie există putem proceda în felul următor:\r\n\r\n== code(cpp) |\r\nint search(T* n, int key)\r\n{\r\n    if (n == nil)  return 0;\r\n    if (key == n->key)  return 1;\r\n    if (key < n->key)\r\n        return search(n->left, key);\r\n    else\r\n        return search(n->right, key);\r\n}\r\n==\r\n\r\nh3(#rotatii). Rotaţii\r\n\r\nRotaţiile sunt cărămizile de la baza structurii de Treap.\r\n\r\np=. !treapuri?Fig1d.png!\r\n\r\np=. _*Figura 1*: Rotaţiile într-un arbore binar de căutare. Nodurile sunt reprezentate de cercuri iar subarborii de triunghiuri. Ambele operaţii de rotaţie menţin invariantul arborilor de căutare._\r\n\r\nSă urmărim efectul rotaţiilor asupra structurii de heap a unui treap care respectă doar invariantul arborilor de căutare. Aşadar, să presupunem că arborele din figura din stânga are o structură de heap cu excepţia lui $w$ care are o prioritate mai mare decât a lui $z$. Dacă îl rotim pe $w$ spre dreapta vedem în figura din dreapta că structura de heap este satisfăcută. Din moment ce $A$ era un subarbore valid al lui $w$, va rămâne în continuare un subarbore valid. Cum $B$ şi $C$ se aflau iniţial sub $z$ ei aveau o prioritate mai mică decât a lui $z$, şi, astfel, după rotaţie ei sunt subarbori valizi pentru $z$. Este clar că $z$ este un fiu valid al lui $w$, prin presupunerea făcută iniţial. \r\n\r\nSă urmărim dacă invariantul arborilor de căutare se menţine în urma unei astfel de rotaţii.\r\n\r\n* În arborele din figura din stânga avem inegalităţile următoare: $A < w < B; z < C; w, A, B < z$. Din acestea se obţine: $A < w < B < z < C$.\r\n* În arborele din figura din dreapta avem inegalităţile următoare: $A < w; B < z < C; w < z, B, C$. Din acestea se obţine: $A < w < B < z < C$.\r\n\r\nCum am obţinut acelaşi şir de inegalităţi, am arătat existenţa invariantului arborilor de căutare.\r\n\r\nReţineţi că această rotaţie împreună cu imaginea sa în oglindă, rotaţia spre stânga dacă urmărim desenul de la dreapta spre stânga, stau la baza algoritmilor de \'$inserare$\':treapuri#inserare şi \'$ştergere$\':treapuri#stergere!\r\n\r\nPentru o rotaţie sunt necesare doar câteva operaţii cu pointeri.\r\n\r\n== code(cpp) |\r\nvoid rotleft(T* &n) \r\n{\r\n    T *t = n->left;\r\n    n->left = t->right, t->right = n;\r\n    n = t;           \r\n}\r\n\r\nvoid rotright(T* &n) \r\n{\r\n    T *t = n->right;\r\n    n->right = t->left, t->left = n;\r\n    n = t;           \r\n}\r\n\r\nvoid balance(T* &n) \r\n{\r\n    if (n->left->priority > n->priority)\r\n        rotleft(n);\r\n    else if (n->right->priority > n->priority)\r\n        rotright(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(1)$.\r\n\r\nh3(#inserare). Inserare\r\n\r\nÎn cadrul operaţiei de inserare vom atribui unui nod nou o prioritate aleatoare şi îl vom insera, conform algoritmului standard de inserare într-un arbore binar, la baza arborelui. Să presupunem că dorim să inserăm nodul $z$ cu cheia $9$ şi prioritatea $51$.\r\n\r\np=. !treapuri?Fig2c.png!\r\n\r\np=. _*Figura 2*: De la stânga la dreapta: inserarea nodului $z$. De la dreapta la stânga: ştergerea nodului $z$. Deoarece $z$ are prioritatea cea mai mare dintre toate nodurile, această inserare poate fi privită şi ca o operaţie de $split$. Subarborii stâng şi drept ai rădăcinii din ultima figură sunt chiar treapurile căutate: $T{~<~}$ şi $T{~>~}$. Invers, din $T{~<~}$ şi $T{~>~}$ se obţine, prin ştergerea rădăcinii, rezultatul operaţiei $join$._\r\n\r\nCheile formează un arbore de căutare, dar priorităţile pot să nu mai formeze un heap. Pentru a redobândi această proprietate, cât timp nodul de inserat, are prioritatea mai mare decât a părintelui său, se va executa o \'$rotaţie$\':treapuri#rotatii în $z$, o operaţie locală care scade nivelul lui $z$ cu $1$ şi creşte nivelul părintelui lui $z$ cu $1$, şi care menţine invariantul arborilor de căutare. Timpul de inserare al lui $z$ este proporţional cu adâncimea lui înainte de rotaţii - trebuie să coborâm după care să urcăm înapoi efectuând rotaţiile necesare.\r\n\r\n== code(cpp) |\r\nvoid insert(T* &n, int key, int priority)\r\n{\r\n    if (n == nil) {\r\n        n = new T(key, priority, nil, nil);\r\n        return;\r\n    }\r\n    if (key <= n->key)\r\n        insert(n->left, key, priority);\r\n    else if (key > n->key)\r\n        insert(n->right, key, priority);\r\n\r\n    balance(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#stergere). Ştergere\r\n\r\nOperaţia de ştergere este inversul operaţiei de inserare. Scopul este să aducem acest nod, fie el $z$, în poziţia unei frunze pentru a-l şterge. Astfel, pentru a menţine cei doi invarianţi (făcând excepţie de $z$) vom alege fiul cu prioritatea mai mare şi îl vom \'$roti$\':treapuri#rotatii în locul lui $z$, cât timp acesta nu este frunză. Atunci când $z$ devine frunză îl vom şterge.\r\n\r\n== code(cpp) |\r\nvoid erase(T* &n, int key) \r\n{\r\n    if (n == nil)   return ;\r\n\r\n    if (key < n->key)\r\n        erase(n->left, key);\r\n    else if (key > n->key)\r\n        erase(n->right, key);\r\n    else {    \r\n        (n->left->priority > n->right->priority) ? rotleft(n) : rotright(n);\r\n        if (n != nil)  \r\n            erase(n, key);\r\n        else {\r\n            delete n->left;\r\n            n->left = NULL;\r\n        }\r\n    }\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#split). Split\r\n\r\nUneori dorim să despărţim treapul $T$ în două treapuri $T{~<~}$ şi $T{~>~}$ astfel încât cheile din $T{~<~}$ să conţină cheile din $T$ mai mici decât o cheie $key$ dată, iar $T{~>~}$ să conţină cheile din $T$ mai mari decât aceeaşi cheie $key$. Soluţia constă în inserarea unui nod ajutător $z$ a cărui cheie este $key$ şi prioritate $infinit$. După inserare, $z$ va fi rădăcina arborelui, având prioritatea cea mai mare. Dacă ştergem rădăcina, subarborele stâng şi cel drept vor fi exact treapurile căutate.\r\n\r\nCostul operaţiei $split$ este egal cu costul operaţiei de \'$inserare$\':treapuri#inserare a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid split(T* &R, T* &Ts, T* &Tg, int key) \r\n{\r\n    insert(R, key, infinity);\r\n    Ts = R->left, Tg = R->right;\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#join). Join\r\n\r\nOperaţia $join$ constă în unirea a două treapuri $T{~<~}$ şi $T{~>~}$, unde fiecare cheie din $T{~<~}$ este mai mică decât o cheie $key$ iar oricare cheie din $T{~>~}$ este mai mare decât aceeaşi cheie $key$, într-un singur super-treap. $Join$ se realizează în mod invers operaţiei de $split$ prin crearea unei rădăcini $z$ cu cheia $key$ şi prioritate oricât, ce are ca subarbore stâng pe $T{~<~}$ iar ca subarbore drept pe $T{~>~}$, pe care o vom suprima.\r\n\r\nCostul operaţiei $join$ este egal cu costul operaţiei de \'$ştergere$\':treapuri#stergere a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid join(T* &R, T* Ts, T* Tg, int key) \r\n{\r\n    R = new T(key, 0, Ts, Tg);\r\n    erase(R, R->key);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nMai sus aţi văzut codul în $C++$ pentru cele mai importante operaţii. Puteţi face o comparaţie între funcţiile \'$erase$\':treapuri#stergere sau \'$balance$\':treapuri#rotatii cu cele din articolul următor despre arborii \'$AVL$\':multe-smenuri-de-programare-in-cc-si-nu-numai#AVL. Structura de date de Treap suportă, pe lângă operaţiile prezentate, şi operaţii precum determinarea maximului, a minimului, a succesorului sau predecesorului unei chei, sau de tipărire a conţinutului cheilor pe baza relaţiei de ordine stabilite. Şi s-ar putea să mai existe. :-) Chinezii şi ruşii foloseau intens această structură de date, în special în $Pascal$ unde nu există o librărie echivalentă cu $STL$.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\n* \'Order\':http://infoarena.ro/problema/order, info{_arena_}\r\n* \'Schi\':http://infoarena.ro/problema/schi, info{_arena_}\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* \'Eternally Confuzzled\':http://eternallyconfuzzled.com/jsw_home.aspx\r\n* \'Fast Set Operations Using Treaps\':http://www.cs.cmu.edu/afs/cs.cmu.edu/project/scandal/public/papers/treaps-spaa98.pdf, operaţiile \'$split$\':treapuri#split şi \'$join$\':treapuri#join sub altă formă\r\n* \'Treaps and Skip Lists\':http://compgeom.cs.uiuc.edu/~jeffe/teaching/algorithms/notes/06-treaps.pdf\r\n* \'Balanced Search Trees\':http://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15451-s07/www/lecture_notes/lect0208.pdf',3146,'public',NULL,NULL),('treapuri','Treapuri','2008-01-21 16:18:25','2008-11-29 18:25:00','h1. Treapuri\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'{*} Introducere\':treapuri#introducere\r\n* \'{*} Avantaje\':treapuri#avantaje\r\n* \'{*} Operaţii\':treapuri#operatii\r\n** \'- Căutare\':treapuri#cautare\r\n** \'- Rotaţii\':treapuri#rotatii\r\n** \'- Inserare\':treapuri#inserare\r\n** \'- Ştergere\':treapuri#stergere\r\n** \'- Split\':treapuri#split\r\n** \'- Join\':treapuri#join\r\n* \'{*} Concluzii\':treapuri#concluzii\r\n* \'{*} Aplicaţii\':treapuri#aplicatii\r\n* \'{*} Bibliografie\':treapuri#bibliografie\r\n\r\n\r\nÎn acest articol voi prezenta o alternativă pentru arborii binari de căutare echilibraţi, precum $AVL$, $Red-Black Trees$, $Splay Trees$ şi $B-Trees$.\r\n\r\nh2(#introducere). Introducere\r\n\r\nTreapul este un arbore binar în care fiecare nod conţine două informaţii:\r\n\r\n* $cheie$\r\n\r\n* $prioritate$\r\n\r\nStructura de date respectă doi invarianţi:\r\n\r\n* $dacă parcurgem arborele în inordine, atunci vom obţine nodurile sortate (invariantul arborilor de căutare)$\r\n\r\n* $prioritatea fiecărui nod este mai mare decât cea a fiilor săi (invariantul heapurilor)$\r\n\r\nÎn consecinţă, treapul este un arbore binar de căutare pentru chei şi un max-heap pentru priorităţi.\r\n\r\nÎn continuare, vom presupune că toate cheile şi priorităţile din treapul $T$ sunt distincte. În practică, presupunerea aceasta are un impact neglijabil.\r\n\r\nAstfel, din moment ce $T$ este un heap, nodul $v$ cu prioritatea cea mai mare trebuie să fie rădăcina. Cum este şi un arbore binar de căutare, orice nod $u$ cu $cheie(u) < cheie(v)$ se găseşte în subarborele stâng al lui $v$, şi orice nod $w$ cu $cheie(w) > cheie(v)$ se găseşte în subarborele drept.\r\n\r\nCheile şi priorităţile determină în mod unic forma unui treap. Prin inducţie se demonstrează că treapul este arborele binar obţinut prin inserarea cheilor în ordinea descrescătoare a priorităţilor. Algoritmul de inserare este cel obişnuit pentru arborii de căutare. Astfel, cum fiecare set de priorităţi asociat nodurilor va aranja arborele într-un singur mod, probabilitatea ca arborele să fie echilibrat este rezonabil de mare, fapt datorat numărului mic al arborilor rău echilibraţi în comparaţie cu cei echilibraţi. Iată şi secretul acestei structuri de date: probabilitatea infimă de a se găsi o serie de priorităţi generate aleator care să nu menţină arborele echilibrat.\r\n\r\nh2(#avantaje). Avantaje\r\n\r\nStructurile de date de heap şi de arbori binari de căutare sunt uşor de implementat şi de înţeles, iar treapurile sunt o combinaţie a acestor două concepte. Astfel, este suficient să fie înţeleşi cei doi invarianţi, după care implementarea se poate face cu uşurinţă în 20 de minute, fără antrenament. De obicei, la structuri ca $Arbori Roşu-Negrii$ trebuie folosite serii de rotaţii stânga şi dreapta complexe şi analizate o multitudine de cazuri, pe când la treapuri facem doar câte o rotaţie stânga sau dreapta la fiecare pas al algoritmului. Ei nu sunt predaţi pentru că $Arborii Roşu-Negrii$ sau $AVL$ au demonstraţia că limita celei mai lente operaţii este $O(log N)$ şi sunt exemple didactice, dar treapurile, deşi cu o demonstraţie mai grea pentru limita de $O(log N)$, ce implică probabilităţi, sunt mult mai uşor de implementat iar în practică, cu siguranţă este greu de decis care sunt mai rapizi. Sunt deci, o opţiune demnă de luat în seamă. Pe de altă parte, treapurile suportă şi alte două operaţii pe care nu le putem face cu $Arborii Roşu-Negrii$ sau cu arborii $AVL$. Aceste operaţii sunt \'$join$\':treapuri#join şi \'$split$\':treapuri#split.\r\n\r\nh2(#operatii). Operaţii\r\n\r\nCostul operaţiilor de mai jos este proporţional cu adâncimea unui nod din treap. După cum am menţionat mai sus, cu ajutorul teoriei probabilităţilor se poate deduce că adâncimea aşteptată a oricărui nod este $O(log N)$, ceea ce implică costul celor mai lente operaţii să fie $O(log N)$.\r\n\r\nMai jos avem definiţia în cod $C++$ a unui treap şi o funcţie de iniţializare, care marchează că treapul cu rădăcina $R$ este gol.\r\n\r\n== code(cpp) |\r\nstruct T {\r\n    int key;\r\n    int priority;\r\n    T *left, *right;\r\n    T() {}\r\n    T(int key, int priority, T* left, T* right) {\r\n        this->key = key, this->priority = priority,\r\n                    this->left = left, this->right = right;\r\n    }\r\n} *R, *nil;     // R radacina; nil arata un nod `gol`\r\n\r\nvoid init(T* &R) \r\n{\r\n    srand(unsigned(time(0)));\r\n\r\n    R = nil = new T();\r\n    nil->key = nil->priority = 0,\r\n        nil->left = nil->right = NULL;\r\n}\r\n==\r\n\r\nh3(#cautare). Căutare\r\n\r\nCăutarea într-un treap este identică cu cea într-un arbore binar de căutare. Pentru a verifica dacă o cheie există putem proceda în felul următor:\r\n\r\n== code(cpp) |\r\nint search(T* n, int key)\r\n{\r\n    if (n == nil)  return 0;\r\n    if (key == n->key)  return 1;\r\n    if (key < n->key)\r\n        return search(n->left, key);\r\n    else\r\n        return search(n->right, key);\r\n}\r\n==\r\n\r\nh3(#rotatii). Rotaţii\r\n\r\nRotaţiile sunt cărămizile de la baza structurii de Treap.\r\n\r\np=. !treapuri?Fig1d.png!\r\n\r\np=. _*Figura 1*: Rotaţiile într-un arbore binar de căutare. Nodurile sunt reprezentate de cercuri iar subarborii de triunghiuri. Ambele operaţii de rotaţie menţin invariantul arborilor de căutare._\r\n\r\nSă urmărim efectul rotaţiilor asupra structurii de heap a unui treap care respectă doar invariantul arborilor de căutare. Aşadar, să presupunem că arborele din figura din stânga are o structură de heap cu excepţia lui $w$ care are o prioritate mai mare decât a lui $z$. Dacă îl rotim pe $w$ spre dreapta vedem în figura din dreapta că structura de heap este satisfăcută. Din moment ce $A$ era un subarbore valid al lui $w$, va rămâne în continuare un subarbore valid. Cum $B$ şi $C$ se aflau iniţial sub $z$ ei aveau o prioritate mai mică decât a lui $z$, şi, astfel, după rotaţie ei sunt subarbori valizi pentru $z$. Este clar că $z$ este un fiu valid al lui $w$, prin presupunerea făcută iniţial. \r\n\r\nSă urmărim dacă invariantul arborilor de căutare se menţine în urma unei astfel de rotaţii.\r\n\r\n* În arborele din figura din stânga avem inegalităţile următoare: $A < w < B; z < C; w, A, B < z$. Din acestea se obţine: $A < w < B < z < C$.\r\n* În arborele din figura din dreapta avem inegalităţile următoare: $A < w; B < z < C; w < z, B, C$. Din acestea se obţine: $A < w < B < z < C$.\r\n\r\nCum am obţinut acelaşi şir de inegalităţi, am arătat existenţa invariantului arborilor de căutare.\r\n\r\nReţineţi că această rotaţie împreună cu imaginea sa în oglindă, rotaţia spre stânga dacă urmărim desenul de la dreapta spre stânga, stau la baza algoritmilor de \'$inserare$\':treapuri#inserare şi \'$ştergere$\':treapuri#stergere!\r\n\r\nPentru o rotaţie sunt necesare doar câteva operaţii cu pointeri.\r\n\r\n== code(cpp) |\r\nvoid rotleft(T* &n) \r\n{\r\n    T *t = n->left;\r\n    n->left = t->right, t->right = n;\r\n    n = t;           \r\n}\r\n\r\nvoid rotright(T* &n) \r\n{\r\n    T *t = n->right;\r\n    n->right = t->left, t->left = n;\r\n    n = t;           \r\n}\r\n\r\nvoid balance(T* &n) \r\n{\r\n    if (n->left->priority > n->priority)\r\n        rotleft(n);\r\n    else if (n->right->priority > n->priority)\r\n        rotright(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(1)$.\r\n\r\nh3(#inserare). Inserare\r\n\r\nÎn cadrul operaţiei de inserare vom atribui unui nod nou o prioritate aleatoare şi îl vom insera, conform algoritmului standard de inserare într-un arbore binar, la baza arborelui. Să presupunem că dorim să inserăm nodul $z$ cu cheia $9$ şi prioritatea $51$.\r\n\r\np=. !treapuri?Fig2c.png!\r\n\r\np=. _*Figura 2*: De la stânga la dreapta: inserarea nodului $z$. De la dreapta la stânga: ştergerea nodului $z$. Deoarece $z$ are prioritatea cea mai mare dintre toate nodurile, această inserare poate fi privită şi ca o operaţie de $split$. Subarborii stâng şi drept ai rădăcinii din ultima figură sunt chiar treapurile căutate: $T{~<~}$ şi $T{~>~}$. Invers, din $T{~<~}$ şi $T{~>~}$ se obţine, prin ştergerea rădăcinii, rezultatul operaţiei $join$._\r\n\r\nCheile formează un arbore de căutare, dar priorităţile pot să nu mai formeze un heap. Pentru a redobândi această proprietate, cât timp nodul de inserat, are prioritatea mai mare decât a părintelui său, se va executa o \'$rotaţie$\':treapuri#rotatii în $z$, o operaţie locală care scade nivelul lui $z$ cu $1$ şi creşte nivelul părintelui lui $z$ cu $1$, şi care menţine invariantul arborilor de căutare. Timpul de inserare al lui $z$ este proporţional cu adâncimea lui înainte de rotaţii - trebuie să coborâm după care să urcăm înapoi efectuând rotaţiile necesare.\r\n\r\n== code(cpp) |\r\nvoid insert(T* &n, int key, int priority)\r\n{\r\n    if (n == nil) {\r\n        n = new T(key, priority, nil, nil);\r\n        return;\r\n    }\r\n    if (key <= n->key)\r\n        insert(n->left, key, priority);\r\n    else if (key > n->key)\r\n        insert(n->right, key, priority);\r\n\r\n    balance(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#stergere). Ştergere\r\n\r\nOperaţia de ştergere este inversul operaţiei de inserare. Scopul este să aducem acest nod, fie el $z$, în poziţia unei frunze pentru a-l şterge. Astfel, pentru a menţine cei doi invarianţi (făcând excepţie de $z$) vom alege fiul cu prioritatea mai mare şi îl vom \'$roti$\':treapuri#rotatii în locul lui $z$, cât timp acesta nu este frunză. Atunci când $z$ devine frunză îl vom şterge.\r\n\r\n== code(cpp) |\r\nvoid erase(T* &n, int key) \r\n{\r\n    if (n == nil)   return ;\r\n\r\n    if (key < n->key)\r\n        erase(n->left, key);\r\n    else if (key > n->key)\r\n        erase(n->right, key);\r\n    else {    \r\n        (n->left->priority > n->right->priority) ? rotleft(n) : rotright(n);\r\n        if (n != nil)  \r\n            erase(n, key);\r\n        else {\r\n            delete n->left;\r\n            n->left = NULL;\r\n        }\r\n    }\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#split). Split\r\n\r\nUneori dorim să despărţim treapul $T$ în două treapuri $T{~<~}$ şi $T{~>~}$ astfel încât cheile din $T{~<~}$ să conţină cheile din $T$ mai mici decât o cheie $key$ dată, iar $T{~>~}$ să conţină cheile din $T$ mai mari decât aceeaşi cheie $key$. Soluţia constă în inserarea unui nod ajutător $z$ a cărui cheie este $key$ şi prioritate $infinit$. După inserare, $z$ va fi rădăcina arborelui, având prioritatea cea mai mare iar subarborii stâng şi drept ai rădăcănii vor fi exact treapurile căutate.\r\n\r\nCostul operaţiei $split$ este egal cu costul operaţiei de \'$inserare$\':treapuri#inserare a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid split(T* &R, T* &Ts, T* &Tg, int key) \r\n{\r\n    insert(R, key, infinity);\r\n    Ts = R->left, Tg = R->right;\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#join). Join\r\n\r\nOperaţia $join$ constă în unirea a două treapuri $T{~<~}$ şi $T{~>~}$, unde fiecare cheie din $T{~<~}$ este mai mică decât o cheie $key$ iar oricare cheie din $T{~>~}$ este mai mare decât aceeaşi cheie $key$, într-un singur super-treap. $Join$ se realizează în mod invers operaţiei de $split$ prin crearea unei rădăcini $z$ cu cheia $key$ şi prioritate oricât, ce are ca subarbore stâng pe $T{~<~}$ iar ca subarbore drept pe $T{~>~}$, pe care o vom suprima.\r\n\r\nCostul operaţiei $join$ este egal cu costul operaţiei de \'$ştergere$\':treapuri#stergere a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid join(T* &R, T* Ts, T* Tg, int key) \r\n{\r\n    R = new T(key, 0, Ts, Tg);\r\n    erase(R, R->key);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nMai sus aţi văzut codul în $C++$ pentru cele mai importante operaţii. Puteţi face o comparaţie între funcţiile \'$erase$\':treapuri#stergere sau \'$balance$\':treapuri#rotatii cu cele din articolul următor despre arborii \'$AVL$\':multe-smenuri-de-programare-in-cc-si-nu-numai#AVL. Structura de date de Treap suportă, pe lângă operaţiile prezentate, şi operaţii precum determinarea maximului, a minimului, a succesorului sau predecesorului unei chei, sau de tipărire a conţinutului cheilor pe baza relaţiei de ordine stabilite. Şi s-ar putea să mai existe. :-) Chinezii şi ruşii foloseau intens această structură de date, în special în $Pascal$ unde nu există o librărie echivalentă cu $STL$.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\n* \'Order\':http://infoarena.ro/problema/order, info{_arena_}\r\n* \'Schi\':http://infoarena.ro/problema/schi, info{_arena_}\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* \'Eternally Confuzzled\':http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_bst2.aspx\r\n* \'Fast Set Operations Using Treaps\':http://www.cs.cmu.edu/afs/cs.cmu.edu/project/scandal/public/papers/treaps-spaa98.pdf, operaţiile \'$split$\':treapuri#split şi \'$join$\':treapuri#join sub altă formă\r\n* \'Treaps and Skip Lists\':http://compgeom.cs.uiuc.edu/~jeffe/teaching/algorithms/notes/06-treaps.pdf\r\n* \'Balanced Search Trees\':http://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15451-s07/www/lecture_notes/lect0208.pdf',3146,'public',NULL,NULL),('treapuri','Treapuri','2008-01-21 16:18:25','2008-11-29 18:51:27','h1. Treapuri\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'{*} Introducere\':treapuri#introducere\r\n* \'{*} Avantaje\':treapuri#avantaje\r\n* \'{*} Operaţii\':treapuri#operatii\r\n** \'- Căutare\':treapuri#cautare\r\n** \'- Rotaţii\':treapuri#rotatii\r\n** \'- Inserare\':treapuri#inserare\r\n** \'- Ştergere\':treapuri#stergere\r\n** \'- Split\':treapuri#split\r\n** \'- Join\':treapuri#join\r\n* \'{*} Concluzii\':treapuri#concluzii\r\n* \'{*} Aplicaţii\':treapuri#aplicatii\r\n* \'{*} Bibliografie\':treapuri#bibliografie\r\n\r\n\r\nÎn acest articol voi prezenta o alternativă pentru arborii binari de căutare echilibraţi, precum $AVL$, $Red-Black Trees$, $Splay Trees$ şi $B-Trees$.\r\n\r\nh2(#introducere). Introducere\r\n\r\nTreapul este un arbore binar în care fiecare nod conţine două informaţii:\r\n\r\n* $cheie$\r\n\r\n* $prioritate$\r\n\r\nStructura de date respectă doi invarianţi:\r\n\r\n* $dacă parcurgem arborele în inordine, atunci vom obţine nodurile sortate (invariantul arborilor de căutare)$\r\n\r\n* $prioritatea fiecărui nod este mai mare decât cea a fiilor săi (invariantul heapurilor)$\r\n\r\nÎn consecinţă, treapul este un arbore binar de căutare pentru chei şi un max-heap pentru priorităţi.\r\n\r\nÎn continuare, vom presupune că oricare două chei din treapul $T$ sunt distincte.\r\n\r\nAstfel, din moment ce $T$ este un heap, nodul $v$ cu prioritatea cea mai mare trebuie să fie rădăcina. Cum este şi un arbore binar de căutare, orice nod $u$ cu $cheie(u) < cheie(v)$ se găseşte în subarborele stâng al lui $v$, şi orice nod $w$ cu $cheie(w) > cheie(v)$ se găseşte în subarborele drept.\r\n\r\nCheile şi priorităţile determină în mod unic forma unui treap. Prin inducţie se demonstrează că treapul este arborele binar obţinut prin inserarea cheilor în ordinea descrescătoare a priorităţilor. Algoritmul de inserare este cel obişnuit pentru arborii de căutare. Astfel, cum fiecare set de priorităţi asociat nodurilor va aranja arborele într-un singur mod, probabilitatea ca arborele să fie echilibrat este rezonabil de mare, fapt datorat numărului mic al arborilor rău echilibraţi în comparaţie cu cei echilibraţi. Iată şi secretul acestei structuri de date: probabilitatea infimă de a se găsi o serie de priorităţi generate aleator care să nu menţină arborele echilibrat.\r\n\r\nh2(#avantaje). Avantaje\r\n\r\nStructurile de date de heap şi de arbori binari de căutare sunt uşor de implementat şi de înţeles, iar treapurile sunt o combinaţie a acestor două concepte. Astfel, este suficient să fie înţeleşi cei doi invarianţi, după care implementarea se poate face cu uşurinţă în 20 de minute, fără antrenament. De obicei, la structuri ca $Arbori Roşu-Negrii$ trebuie folosite serii de rotaţii stânga şi dreapta complexe şi analizate o multitudine de cazuri, pe când la treapuri facem doar câte o rotaţie stânga sau dreapta la fiecare pas al algoritmului. Ei nu sunt predaţi pentru că $Arborii Roşu-Negrii$ sau $AVL$ au demonstraţia că limita celei mai lente operaţii este $O(log N)$ şi sunt exemple didactice, dar treapurile, deşi cu o demonstraţie mai grea pentru limita de $O(log N)$, ce implică probabilităţi, sunt mult mai uşor de implementat iar în practică, cu siguranţă este greu de decis care sunt mai rapizi. Sunt deci, o opţiune demnă de luat în seamă. Pe de altă parte, treapurile suportă şi alte două operaţii pe care nu le putem face cu $Arborii Roşu-Negrii$ sau cu arborii $AVL$. Aceste operaţii sunt \'$join$\':treapuri#join şi \'$split$\':treapuri#split.\r\n\r\nh2(#operatii). Operaţii\r\n\r\nCostul operaţiilor de mai jos este proporţional cu adâncimea unui nod din treap. După cum am menţionat mai sus, cu ajutorul teoriei probabilităţilor se poate deduce că adâncimea aşteptată a oricărui nod este $O(log N)$, ceea ce implică costul celor mai lente operaţii să fie $O(log N)$.\r\n\r\nMai jos avem definiţia în cod $C++$ a unui treap şi o funcţie de iniţializare, care marchează că treapul cu rădăcina $R$ este gol.\r\n\r\n== code(cpp) |\r\nstruct T {\r\n    int key;\r\n    int priority;\r\n    T *left, *right;\r\n    T() {}\r\n    T(int key, int priority, T* left, T* right) {\r\n        this->key = key, this->priority = priority,\r\n                    this->left = left, this->right = right;\r\n    }\r\n} *R, *nil;     // R radacina; nil arata un nod `gol`\r\n\r\nvoid init(T* &R) \r\n{\r\n    srand(unsigned(time(0)));\r\n\r\n    R = nil = new T();\r\n    nil->key = nil->priority = 0,\r\n        nil->left = nil->right = NULL;\r\n}\r\n==\r\n\r\nh3(#cautare). Căutare\r\n\r\nCăutarea într-un treap este identică cu cea într-un arbore binar de căutare. Pentru a verifica dacă o cheie există putem proceda în felul următor:\r\n\r\n== code(cpp) |\r\nint search(T* n, int key)\r\n{\r\n    if (n == nil)  return 0;\r\n    if (key == n->key)  return 1;\r\n    if (key < n->key)\r\n        return search(n->left, key);\r\n    else\r\n        return search(n->right, key);\r\n}\r\n==\r\n\r\nh3(#rotatii). Rotaţii\r\n\r\nRotaţiile sunt cărămizile de la baza structurii de Treap.\r\n\r\np=. !treapuri?Fig1d.png!\r\n\r\np=. _*Figura 1*: Rotaţiile într-un arbore binar de căutare. Nodurile sunt reprezentate de cercuri iar subarborii de triunghiuri. Ambele operaţii de rotaţie menţin invariantul arborilor de căutare._\r\n\r\nSă urmărim efectul rotaţiilor asupra structurii de heap a unui treap care respectă doar invariantul arborilor de căutare. Aşadar, să presupunem că arborele din figura din stânga are o structură de heap cu excepţia lui $w$ care are o prioritate mai mare decât a lui $z$. Dacă îl rotim pe $w$ spre dreapta vedem în figura din dreapta că structura de heap este satisfăcută. Din moment ce $A$ era un subarbore valid al lui $w$, va rămâne în continuare un subarbore valid. Cum $B$ şi $C$ se aflau iniţial sub $z$ ei aveau o prioritate mai mică decât a lui $z$, şi, astfel, după rotaţie ei sunt subarbori valizi pentru $z$. Este clar că $z$ este un fiu valid al lui $w$, prin presupunerea făcută iniţial. \r\n\r\nSă urmărim dacă invariantul arborilor de căutare se menţine în urma unei astfel de rotaţii.\r\n\r\n* În arborele din figura din stânga avem inegalităţile următoare: $A < w < B; z < C; w, A, B < z$. Din acestea se obţine: $A < w < B < z < C$.\r\n* În arborele din figura din dreapta avem inegalităţile următoare: $A < w; B < z < C; w < z, B, C$. Din acestea se obţine: $A < w < B < z < C$.\r\n\r\nCum am obţinut acelaşi şir de inegalităţi, am arătat existenţa invariantului arborilor de căutare.\r\n\r\nReţineţi că această rotaţie împreună cu imaginea sa în oglindă, rotaţia spre stânga dacă urmărim desenul de la dreapta spre stânga, stau la baza algoritmilor de \'$inserare$\':treapuri#inserare şi \'$ştergere$\':treapuri#stergere!\r\n\r\nPentru o rotaţie sunt necesare doar câteva operaţii cu pointeri.\r\n\r\n== code(cpp) |\r\nvoid rotleft(T* &n) \r\n{\r\n    T *t = n->left;\r\n    n->left = t->right, t->right = n;\r\n    n = t;           \r\n}\r\n\r\nvoid rotright(T* &n) \r\n{\r\n    T *t = n->right;\r\n    n->right = t->left, t->left = n;\r\n    n = t;           \r\n}\r\n\r\nvoid balance(T* &n) \r\n{\r\n    if (n->left->priority > n->priority)\r\n        rotleft(n);\r\n    else if (n->right->priority > n->priority)\r\n        rotright(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(1)$.\r\n\r\nh3(#inserare). Inserare\r\n\r\nÎn cadrul operaţiei de inserare vom atribui unui nod nou o prioritate aleatoare şi îl vom insera, conform algoritmului standard de inserare într-un arbore binar, la baza arborelui. Să presupunem că dorim să inserăm nodul $z$ cu cheia $9$ şi prioritatea $51$.\r\n\r\np=. !treapuri?Fig2c.png!\r\n\r\np=. _*Figura 2*: De la stânga la dreapta: inserarea nodului $z$. De la dreapta la stânga: ştergerea nodului $z$. Deoarece $z$ are prioritatea cea mai mare dintre toate nodurile, această inserare poate fi privită şi ca o operaţie de $split$. Subarborii stâng şi drept ai rădăcinii din ultima figură sunt chiar treapurile căutate: $T{~<~}$ şi $T{~>~}$. Invers, din $T{~<~}$ şi $T{~>~}$ se obţine, prin ştergerea rădăcinii, rezultatul operaţiei $join$._\r\n\r\nCheile formează un arbore de căutare, dar priorităţile pot să nu mai formeze un heap. Pentru a redobândi această proprietate, cât timp nodul de inserat, are prioritatea mai mare decât a părintelui său, se va executa o \'$rotaţie$\':treapuri#rotatii în $z$, o operaţie locală care scade nivelul lui $z$ cu $1$ şi creşte nivelul părintelui lui $z$ cu $1$, şi care menţine invariantul arborilor de căutare. Timpul de inserare al lui $z$ este proporţional cu adâncimea lui înainte de rotaţii - trebuie să coborâm după care să urcăm înapoi efectuând rotaţiile necesare.\r\n\r\n== code(cpp) |\r\nvoid insert(T* &n, int key, int priority)\r\n{\r\n    if (n == nil) {\r\n        n = new T(key, priority, nil, nil);\r\n        return;\r\n    }\r\n    if (key <= n->key)\r\n        insert(n->left, key, priority);\r\n    else if (key > n->key)\r\n        insert(n->right, key, priority);\r\n\r\n    balance(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#stergere). Ştergere\r\n\r\nOperaţia de ştergere este inversul operaţiei de inserare. Scopul este să aducem acest nod, fie el $z$, în poziţia unei frunze pentru a-l şterge. Astfel, pentru a menţine cei doi invarianţi (făcând excepţie de $z$) vom alege fiul cu prioritatea mai mare şi îl vom \'$roti$\':treapuri#rotatii în locul lui $z$, cât timp acesta nu este frunză. Atunci când $z$ devine frunză îl vom şterge.\r\n\r\n== code(cpp) |\r\nvoid erase(T* &n, int key) \r\n{\r\n    if (n == nil)   return ;\r\n\r\n    if (key < n->key)\r\n        erase(n->left, key);\r\n    else if (key > n->key)\r\n        erase(n->right, key);\r\n    else {    \r\n        (n->left->priority > n->right->priority) ? rotleft(n) : rotright(n);\r\n        if (n != nil)  \r\n            erase(n, key);\r\n        else {\r\n            delete n->left;\r\n            n->left = NULL;\r\n        }\r\n    }\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#split). Split\r\n\r\nUneori dorim să despărţim treapul $T$ în două treapuri $T{~<~}$ şi $T{~>~}$ astfel încât cheile din $T{~<~}$ să conţină cheile din $T$ mai mici decât o cheie $key$ dată, iar $T{~>~}$ să conţină cheile din $T$ mai mari decât aceeaşi cheie $key$. Soluţia constă în inserarea unui nod ajutător $z$ a cărui cheie este $key$ şi prioritate $infinit$. După inserare, $z$ va fi rădăcina arborelui, având prioritatea cea mai mare iar subarborii stâng şi drept ai rădăcănii vor fi exact treapurile căutate. Pe $z$ îl vom şterge, deoarece nu mai avem nevoie de el.\r\n\r\nCostul operaţiei $split$ este egal cu costul operaţiei de \'$inserare$\':treapuri#inserare a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid split(T* &R, T* &Ts, T* &Tg, int key) \r\n{\r\n    insert(R, key, infinity);\r\n    Ts = R->left, Tg = R->right;\r\n    delete R, R = nil;\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#join). Join\r\n\r\nOperaţia $join$ constă în unirea a două treapuri $T{~<~}$ şi $T{~>~}$, unde fiecare cheie din $T{~<~}$ este mai mică decât o cheie $key$ iar oricare cheie din $T{~>~}$ este mai mare decât aceeaşi cheie $key$, într-un singur super-treap. $Join$ se realizează în mod invers operaţiei de $split$ prin crearea unei rădăcini $z$ cu cheia $key$ şi prioritate oricât, ce are ca subarbore stâng pe $T{~<~}$ iar ca subarbore drept pe $T{~>~}$, pe care o vom suprima.\r\n\r\nCostul operaţiei $join$ este egal cu costul operaţiei de \'$ştergere$\':treapuri#stergere a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid join(T* &R, T* Ts, T* Tg, int key) \r\n{\r\n    R = new T(key, 0, Ts, Tg);\r\n    erase(R, R->key);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nMai sus aţi văzut codul în $C++$ pentru cele mai importante operaţii. Puteţi face o comparaţie între funcţiile \'$erase$\':treapuri#stergere sau \'$balance$\':treapuri#rotatii cu cele din articolul următor despre arborii \'$AVL$\':multe-smenuri-de-programare-in-cc-si-nu-numai#AVL. Structura de date de Treap suportă, pe lângă operaţiile prezentate, şi operaţii precum determinarea maximului, a minimului, a succesorului sau predecesorului unei chei, sau de tipărire a conţinutului cheilor pe baza relaţiei de ordine stabilite. Şi s-ar putea să mai existe. :-) Chinezii şi ruşii foloseau intens această structură de date, în special în $Pascal$ unde nu există o librărie echivalentă cu $STL$.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\n* \'Order\':http://infoarena.ro/problema/order, info{_arena_}\r\n* \'Schi\':http://infoarena.ro/problema/schi, info{_arena_}\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* \'Eternally Confuzzled\':http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_bst2.aspx\r\n* \'Fast Set Operations Using Treaps\':http://www.cs.cmu.edu/afs/cs.cmu.edu/project/scandal/public/papers/treaps-spaa98.pdf, operaţiile \'$split$\':treapuri#split şi \'$join$\':treapuri#join sub altă formă\r\n* \'Treaps and Skip Lists\':http://compgeom.cs.uiuc.edu/~jeffe/teaching/algorithms/notes/06-treaps.pdf\r\n* \'Balanced Search Trees\':http://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15451-s07/www/lecture_notes/lect0208.pdf',3146,'public',NULL,NULL),('treapuri','Treapuri','2008-01-21 16:18:25','2008-11-29 19:38:03','h1. Treapuri\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'{*} Introducere\':treapuri#introducere\r\n* \'{*} Avantaje\':treapuri#avantaje\r\n* \'{*} Operaţii\':treapuri#operatii\r\n** \'- Căutare\':treapuri#cautare\r\n** \'- Rotaţii\':treapuri#rotatii\r\n** \'- Inserare\':treapuri#inserare\r\n** \'- Ştergere\':treapuri#stergere\r\n** \'- Split\':treapuri#split\r\n** \'- Join\':treapuri#join\r\n* \'{*} Concluzii\':treapuri#concluzii\r\n* \'{*} Aplicaţii\':treapuri#aplicatii\r\n* \'{*} Bibliografie\':treapuri#bibliografie\r\n\r\n\r\nÎn acest articol voi prezenta o alternativă pentru arborii binari de căutare echilibraţi, precum $AVL$, $Red-Black Trees$, $Splay Trees$ şi $B-Trees$.\r\n\r\nh2(#introducere). Introducere\r\n\r\nTreapul este un arbore binar în care fiecare nod conţine două informaţii:\r\n\r\n* $cheie$\r\n\r\n* $prioritate$\r\n\r\nStructura de date respectă doi invarianţi:\r\n\r\n* $dacă parcurgem arborele în inordine, atunci vom obţine nodurile sortate (invariantul arborilor de căutare)$\r\n\r\n* $prioritatea fiecărui nod este mai mare decât cea a fiilor săi (invariantul heapurilor)$\r\n\r\nÎn consecinţă, treapul este un arbore binar de căutare pentru chei şi un max-heap pentru priorităţi.\r\n\r\nÎn continuare, vom presupune că oricare două chei din treapul $T$ sunt distincte. Cazul când avem nevoie de chei egale se va trata relativ uşor după ce acest articol va fi înţeles.\r\n\r\nAstfel, din moment ce $T$ este un heap, nodul $v$ cu prioritatea cea mai mare trebuie să fie rădăcina. Cum este şi un arbore binar de căutare, orice nod $u$ cu $cheie(u) < cheie(v)$ se găseşte în subarborele stâng al lui $v$, şi orice nod $w$ cu $cheie(w) > cheie(v)$ se găseşte în subarborele drept.\r\n\r\nCheile şi priorităţile determină în mod unic forma unui treap. Prin inducţie se demonstrează că treapul este arborele binar obţinut prin inserarea cheilor în ordinea descrescătoare a priorităţilor. Algoritmul de inserare este cel obişnuit pentru arborii de căutare. Astfel, cum fiecare set de priorităţi asociat nodurilor va aranja arborele într-un singur mod, probabilitatea ca arborele să fie echilibrat este rezonabil de mare, fapt datorat numărului mic al arborilor rău echilibraţi în comparaţie cu cei echilibraţi. Iată şi secretul acestei structuri de date: probabilitatea infimă de a se găsi o serie de priorităţi generate aleator care să nu menţină arborele echilibrat.\r\n\r\nh2(#avantaje). Avantaje\r\n\r\nStructurile de date de heap şi de arbori binari de căutare sunt uşor de implementat şi de înţeles, iar treapurile sunt o combinaţie a acestor două concepte. Astfel, este suficient să fie înţeleşi cei doi invarianţi, după care implementarea se poate face cu uşurinţă în 20 de minute, fără antrenament. De obicei, la structuri ca $Arbori Roşu-Negrii$ trebuie folosite serii de rotaţii stânga şi dreapta complexe şi analizate o multitudine de cazuri, pe când la treapuri facem doar câte o rotaţie stânga sau dreapta la fiecare pas al algoritmului. Ei nu sunt predaţi pentru că $Arborii Roşu-Negrii$ sau $AVL$ au demonstraţia că limita celei mai lente operaţii este $O(log N)$ şi sunt exemple didactice, dar treapurile, deşi cu o demonstraţie mai grea pentru limita de $O(log N)$, ce implică probabilităţi, sunt mult mai uşor de implementat iar în practică, cu siguranţă este greu de decis care sunt mai rapizi. Sunt deci, o opţiune demnă de luat în seamă. Pe de altă parte, treapurile suportă şi alte două operaţii pe care nu le putem face cu $Arborii Roşu-Negrii$ sau cu arborii $AVL$. Aceste operaţii sunt \'$join$\':treapuri#join şi \'$split$\':treapuri#split.\r\n\r\nh2(#operatii). Operaţii\r\n\r\nCostul operaţiilor de mai jos este proporţional cu adâncimea unui nod din treap. După cum am menţionat mai sus, cu ajutorul teoriei probabilităţilor se poate deduce că adâncimea medie aşteptată a oricărui nod este $O(log N)$, ceea ce implică costul celor mai lente operaţii să fie, în medie, $O(log N)$.\r\n\r\nMai jos avem definiţia în cod $C++$ a unui treap şi o funcţie de iniţializare, care marchează că treapul cu rădăcina $R$ este gol.\r\n\r\n== code(cpp) |\r\nstruct T {\r\n    int key;\r\n    int priority;\r\n    T *left, *right;\r\n    T() {}\r\n    T(int key, int priority, T* left, T* right) {\r\n        this->key = key, this->priority = priority,\r\n                    this->left = left, this->right = right;\r\n    }\r\n} *R, *nil;     // R radacina; nil arata un nod `gol`\r\n\r\nvoid init(T* &R) \r\n{\r\n    srand(unsigned(time(0)));\r\n\r\n    R = nil = new T();\r\n    nil->key = nil->priority = 0,\r\n        nil->left = nil->right = NULL;\r\n}\r\n==\r\n\r\nh3(#cautare). Căutare\r\n\r\nCăutarea într-un treap este identică cu cea într-un arbore binar de căutare. Pentru a verifica dacă o cheie există putem proceda în felul următor:\r\n\r\n== code(cpp) |\r\nint search(T* n, int key)\r\n{\r\n    if (n == nil)  return 0;\r\n    if (key == n->key)  return 1;\r\n    if (key < n->key)\r\n        return search(n->left, key);\r\n    else\r\n        return search(n->right, key);\r\n}\r\n==\r\n\r\nh3(#rotatii). Rotaţii\r\n\r\nRotaţiile sunt cărămizile de la baza structurii de Treap.\r\n\r\np=. !treapuri?Fig1d.png!\r\n\r\np=. _*Figura 1*: Rotaţiile într-un arbore binar de căutare. Nodurile sunt reprezentate de cercuri iar subarborii de triunghiuri. Ambele operaţii de rotaţie menţin invariantul arborilor de căutare._\r\n\r\nSă urmărim efectul rotaţiilor asupra structurii de heap a unui treap care respectă doar invariantul arborilor de căutare. Aşadar, să presupunem că arborele din figura din stânga are o structură de heap cu excepţia lui $w$ care are o prioritate mai mare decât a lui $z$. Dacă îl rotim pe $w$ spre dreapta vedem în figura din dreapta că structura de heap este satisfăcută. Din moment ce $A$ era un subarbore valid al lui $w$, va rămâne în continuare un subarbore valid. Cum $B$ şi $C$ se aflau iniţial sub $z$ ei aveau o prioritate mai mică decât a lui $z$, şi, astfel, după rotaţie ei sunt subarbori valizi pentru $z$. Este clar că $z$ este un fiu valid al lui $w$, prin presupunerea făcută iniţial. \r\n\r\nSă urmărim dacă invariantul arborilor de căutare se menţine în urma unei astfel de rotaţii.\r\n\r\n* În arborele din figura din stânga avem inegalităţile următoare: $A < w < B; z < C; w, A, B < z$. Din acestea se obţine: $A < w < B < z < C$.\r\n* În arborele din figura din dreapta avem inegalităţile următoare: $A < w; B < z < C; w < z, B, C$. Din acestea se obţine: $A < w < B < z < C$.\r\n\r\nCum am obţinut acelaşi şir de inegalităţi, am arătat existenţa invariantului arborilor de căutare.\r\n\r\nReţineţi că această rotaţie împreună cu imaginea sa în oglindă, rotaţia spre stânga dacă urmărim desenul de la dreapta spre stânga, stau la baza algoritmilor de \'$inserare$\':treapuri#inserare şi \'$ştergere$\':treapuri#stergere!\r\n\r\nPentru o rotaţie sunt necesare doar câteva operaţii cu pointeri.\r\n\r\n== code(cpp) |\r\nvoid rotleft(T* &n) \r\n{\r\n    T *t = n->left;\r\n    n->left = t->right, t->right = n;\r\n    n = t;           \r\n}\r\n\r\nvoid rotright(T* &n) \r\n{\r\n    T *t = n->right;\r\n    n->right = t->left, t->left = n;\r\n    n = t;           \r\n}\r\n\r\nvoid balance(T* &n) \r\n{\r\n    if (n->left->priority > n->priority)\r\n        rotleft(n);\r\n    else if (n->right->priority > n->priority)\r\n        rotright(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(1)$.\r\n\r\nh3(#inserare). Inserare\r\n\r\nÎn cadrul operaţiei de inserare vom atribui unui nod nou o prioritate aleatoare şi îl vom insera, conform algoritmului standard de inserare într-un arbore binar, la baza arborelui. Să presupunem că dorim să inserăm nodul $z$ cu cheia $9$ şi prioritatea $51$.\r\n\r\np=. !treapuri?Fig2c.png!\r\n\r\np=. _*Figura 2*: De la stânga la dreapta: inserarea nodului $z$. De la dreapta la stânga: ştergerea nodului $z$. Deoarece $z$ are prioritatea cea mai mare dintre toate nodurile, această inserare poate fi privită şi ca o operaţie de $split$. Subarborii stâng şi drept ai rădăcinii din ultima figură sunt chiar treapurile căutate: $T{~<~}$ şi $T{~>~}$. Invers, din $T{~<~}$ şi $T{~>~}$ se obţine, prin ştergerea rădăcinii, rezultatul operaţiei $join$._\r\n\r\nCheile formează un arbore de căutare, dar priorităţile pot să nu mai formeze un heap. Pentru a redobândi această proprietate, cât timp nodul de inserat, are prioritatea mai mare decât a părintelui său, se va executa o \'$rotaţie$\':treapuri#rotatii în $z$, o operaţie locală care scade nivelul lui $z$ cu $1$ şi creşte nivelul părintelui lui $z$ cu $1$, şi care menţine invariantul arborilor de căutare. Timpul de inserare al lui $z$ este proporţional cu adâncimea lui înainte de rotaţii - trebuie să coborâm după care să urcăm înapoi efectuând rotaţiile necesare.\r\n\r\n== code(cpp) |\r\nvoid insert(T* &n, int key, int priority)\r\n{\r\n    if (n == nil) {\r\n        n = new T(key, priority, nil, nil);\r\n        return;\r\n    }\r\n    if (key <= n->key)\r\n        insert(n->left, key, priority);\r\n    else if (key > n->key)\r\n        insert(n->right, key, priority);\r\n\r\n    balance(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#stergere). Ştergere\r\n\r\nOperaţia de ştergere este inversul operaţiei de inserare. Scopul este să aducem acest nod, fie el $z$, în poziţia unei frunze pentru a-l şterge. Astfel, pentru a menţine cei doi invarianţi (făcând excepţie de $z$) vom alege fiul cu prioritatea mai mare şi îl vom \'$roti$\':treapuri#rotatii în locul lui $z$, cât timp acesta nu este frunză. Atunci când $z$ devine frunză îl vom şterge.\r\n\r\n== code(cpp) |\r\nvoid erase(T* &n, int key) \r\n{\r\n    if (n == nil)   return ;\r\n\r\n    if (key < n->key)\r\n        erase(n->left, key);\r\n    else if (key > n->key)\r\n        erase(n->right, key);\r\n    else {    \r\n        (n->left->priority > n->right->priority) ? rotleft(n) : rotright(n);\r\n        if (n != nil)  \r\n            erase(n, key);\r\n        else {\r\n            delete n->left;\r\n            n->left = NULL;\r\n        }\r\n    }\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#split). Split\r\n\r\nUneori dorim să despărţim treapul $T$ în două treapuri $T{~<~}$ şi $T{~>~}$ astfel încât cheile din $T{~<~}$ să conţină cheile din $T$ mai mici decât o cheie $key$ dată, iar $T{~>~}$ să conţină cheile din $T$ mai mari decât aceeaşi cheie $key$. Soluţia constă în inserarea unui nod ajutător $z$ a cărui cheie este $key$ şi prioritate $infinit$. După inserare, $z$ va fi rădăcina arborelui, având prioritatea cea mai mare iar subarborii stâng şi drept ai rădăcănii vor fi exact treapurile căutate. Pe $z$ îl vom şterge, deoarece nu mai avem nevoie de el.\r\n\r\nCostul operaţiei $split$ este egal cu costul operaţiei de \'$inserare$\':treapuri#inserare a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid split(T* &R, T* &Ts, T* &Tg, int key) \r\n{\r\n    insert(R, key, infinity);\r\n    Ts = R->left, Tg = R->right;\r\n    delete R, R = nil;\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#join). Join\r\n\r\nOperaţia $join$ constă în unirea a două treapuri $T{~<~}$ şi $T{~>~}$, unde fiecare cheie din $T{~<~}$ este mai mică decât o cheie $key$ iar oricare cheie din $T{~>~}$ este mai mare decât aceeaşi cheie $key$, într-un singur super-treap. $Join$ se realizează în mod invers operaţiei de $split$ prin crearea unei rădăcini $z$ cu cheia $key$ şi prioritate oricât, ce are ca subarbore stâng pe $T{~<~}$ iar ca subarbore drept pe $T{~>~}$, pe care o vom suprima.\r\n\r\nCostul operaţiei $join$ este egal cu costul operaţiei de \'$ştergere$\':treapuri#stergere a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid join(T* &R, T* Ts, T* Tg, int key) \r\n{\r\n    R = new T(key, 0, Ts, Tg);\r\n    erase(R, R->key);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nMai sus aţi văzut codul în $C++$ pentru cele mai importante operaţii. Puteţi face o comparaţie între funcţiile \'$erase$\':treapuri#stergere sau \'$balance$\':treapuri#rotatii cu cele din articolul următor despre arborii \'$AVL$\':multe-smenuri-de-programare-in-cc-si-nu-numai#AVL. Structura de date de Treap suportă, pe lângă operaţiile prezentate, şi operaţii precum determinarea maximului, a minimului, a succesorului sau predecesorului unei chei, sau de tipărire a conţinutului cheilor pe baza relaţiei de ordine stabilite. Şi s-ar putea să mai existe. :-) Chinezii şi ruşii foloseau intens această structură de date, în special în $Pascal$ unde nu există o librărie echivalentă cu $STL$.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\n* \'Order\':http://infoarena.ro/problema/order, info{_arena_}\r\n* \'Schi\':http://infoarena.ro/problema/schi, info{_arena_}\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* \'Eternally Confuzzled\':http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_bst2.aspx\r\n* \'Fast Set Operations Using Treaps\':http://www.cs.cmu.edu/afs/cs.cmu.edu/project/scandal/public/papers/treaps-spaa98.pdf, operaţiile \'$split$\':treapuri#split şi \'$join$\':treapuri#join sub altă formă\r\n* \'Treaps and Skip Lists\':http://compgeom.cs.uiuc.edu/~jeffe/teaching/algorithms/notes/06-treaps.pdf\r\n* \'Balanced Search Trees\':http://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15451-s07/www/lecture_notes/lect0208.pdf',3146,'public',NULL,NULL),('algoritmiada-2009/clasament/11-12','preONI 2008 - Clasament general, Clasele 11-12','2008-11-30 15:44:31','2008-11-30 15:44:31','Scrie aici despre algoritmiada-2009/clasament/11-12',2028,'protected',NULL,NULL),('algoritmiada-2009/clasament/9-10','preONI 2008 - Clasament general, Clasele 9-10','2008-11-30 15:39:40','2008-11-30 15:46:44','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Clasament clasele 9-10\r\n\r\n(htabs)* \'Pe runde...\':algoritmiada-2009/clasament\r\n* \'Clasele 5-8\':algoritmiada-2009/clasament/5-8\r\n*(active) \'Clasele 9-10\':algoritmiada-2009/clasament/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/studenti\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda1-9-10|algoritmiada2009-runda2-9-10|algoritmiada2009-runda3-9-10\") == \r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('algoritmiada-2009/runda-2','Algoritmiada 2009 - Runda 2','2008-11-30 16:35:07','2008-11-30 16:35:07','Scrie aici despre algoritmiada-2009/runda-2',2028,'public',NULL,NULL),('algoritmiada-2009/runda-1/11-12','Algoritmiada 2009 - Runda 1, Clasele 11-12','2008-11-30 17:33:43','2008-11-30 17:39:35','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda1-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-1 \r\n* \'Clasele 5-8\':algoritmiada-2009/runda-1/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2009/runda-1/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2009/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-1/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-1/11-12\r\n\r\n== roundregister(round_id=\"algoritmiada2009-runda1-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2009-runda1-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2009-runda1-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2009/clasament/runda-1/11-12.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2009-runda1-11-12\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"57\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',1490,'round: algoritmiada2009-runda1-11-12',NULL,NULL),('treapuri','Treapuri','2008-01-21 16:18:25','2008-11-30 13:07:16','h1. Treapuri\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'{*} Introducere\':treapuri#introducere\r\n* \'{*} Avantaje\':treapuri#avantaje\r\n* \'{*} Operaţii\':treapuri#operatii\r\n** \'- Căutare\':treapuri#cautare\r\n** \'- Rotaţii\':treapuri#rotatii\r\n** \'- Inserare\':treapuri#inserare\r\n** \'- Ştergere\':treapuri#stergere\r\n** \'- Split\':treapuri#split\r\n** \'- Join\':treapuri#join\r\n** \'- Alte operaţii\':treapuri#alteoperatii\r\n* \'{*} Concluzii\':treapuri#concluzii\r\n* \'{*} Aplicaţii\':treapuri#aplicatii\r\n* \'{*} Bibliografie\':treapuri#bibliografie\r\n\r\n\r\nÎn acest articol voi prezenta o alternativă pentru arborii binari de căutare echilibraţi, precum $AVL$, $Red-Black Trees$, $Splay Trees$ şi $B-Trees$.\r\n\r\nh2(#introducere). Introducere\r\n\r\nTreapul este un arbore binar în care fiecare nod conţine două informaţii:\r\n\r\n* $cheie$\r\n\r\n* $prioritate$\r\n\r\nStructura de date respectă doi invarianţi:\r\n\r\n* $dacă parcurgem arborele în inordine, atunci vom obţine nodurile sortate (invariantul arborilor de căutare)$\r\n\r\n* $prioritatea fiecărui nod este mai mare decât cea a fiilor săi (invariantul heapurilor)$\r\n\r\nÎn consecinţă, treapul este un arbore binar de căutare pentru chei şi un max-heap pentru priorităţi.\r\n\r\nÎn continuare, vom presupune că oricare două chei din treapul $T$ sunt distincte. Cazul când avem nevoie de chei egale se va trata relativ uşor după ce acest articol va fi înţeles.\r\n\r\nAstfel, din moment ce $T$ este un heap, nodul $v$ cu prioritatea cea mai mare trebuie să fie rădăcina. Cum este şi un arbore binar de căutare, orice nod $u$ cu $cheie(u) < cheie(v)$ se găseşte în subarborele stâng al lui $v$, şi orice nod $w$ cu $cheie(w) > cheie(v)$ se găseşte în subarborele drept.\r\n\r\nCheile şi priorităţile determină în mod unic forma unui treap. Prin inducţie se demonstrează că treapul este arborele binar obţinut prin inserarea cheilor în ordinea descrescătoare a priorităţilor. Algoritmul de inserare este cel obişnuit pentru arborii de căutare. Astfel, cum fiecare set de priorităţi asociat nodurilor va aranja arborele într-un singur mod, probabilitatea ca arborele să fie echilibrat este rezonabil de mare, fapt datorat numărului mic al arborilor rău echilibraţi în comparaţie cu cei echilibraţi. Iată şi secretul acestei structuri de date: probabilitatea infimă de a se găsi o serie de priorităţi generate aleator care să nu menţină arborele echilibrat.\r\n\r\nh2(#avantaje). Avantaje\r\n\r\nStructurile de date de heap şi de arbori binari de căutare sunt uşor de implementat şi de înţeles, iar treapurile sunt o combinaţie a acestor două concepte. Astfel, este suficient să fie înţeleşi cei doi invarianţi, după care implementarea se poate face cu uşurinţă în 20 de minute, fără antrenament. De obicei, la structuri ca $Arbori Roşu-Negrii$ trebuie folosite serii de rotaţii stânga şi dreapta complexe şi analizate o multitudine de cazuri, pe când la treapuri facem doar câte o rotaţie stânga sau dreapta la fiecare pas al algoritmului. Ei nu sunt predaţi pentru că $Arborii Roşu-Negrii$ sau $AVL$ au demonstraţia că limita celei mai lente operaţii este $O(log N)$ şi sunt exemple didactice, dar treapurile, deşi cu o demonstraţie mai grea pentru limita de $O(log N)$, ce implică probabilităţi, sunt mult mai uşor de implementat iar în practică, cu siguranţă este greu de decis care sunt mai rapizi. Sunt deci, o opţiune demnă de luat în seamă. Pe de altă parte, treapurile suportă şi alte două operaţii pe care nu le putem face cu $Arborii Roşu-Negrii$ sau cu arborii $AVL$. Aceste operaţii sunt \'$join$\':treapuri#join şi \'$split$\':treapuri#split.\r\n\r\nh2(#operatii). Operaţii\r\n\r\nCostul operaţiilor de mai jos este proporţional cu adâncimea unui nod din treap. După cum am menţionat mai sus, cu ajutorul teoriei probabilităţilor se poate deduce că adâncimea medie aşteptată a oricărui nod este $O(log N)$, ceea ce implică costul celor mai lente operaţii să fie, în medie, $O(log N)$.\r\n\r\nMai jos avem definiţia în cod $C++$ a unui treap şi o funcţie de iniţializare, care marchează că treapul cu rădăcina $R$ este gol.\r\n\r\n== code(cpp) |\r\nstruct T {\r\n    int key;\r\n    int priority;\r\n    T *left, *right;\r\n    T() {}\r\n    T(int key, int priority, T* left, T* right) {\r\n        this->key = key, this->priority = priority,\r\n                    this->left = left, this->right = right;\r\n    }\r\n} *R, *nil;     // nil indica un nod \'gol\'\r\n\r\nvoid init(T* &R) \r\n{\r\n    srand(unsigned(time(0)));\r\n\r\n    R = nil = new T();\r\n    nil->key = nil->priority = 0,\r\n        nil->left = nil->right = NULL;\r\n}\r\n==\r\n\r\nh3(#cautare). Căutare\r\n\r\nCăutarea într-un treap este identică cu cea într-un arbore binar de căutare. Pentru a verifica dacă o cheie există putem proceda în felul următor:\r\n\r\n== code(cpp) |\r\nint search(T* n, int key)\r\n{\r\n    if (n == nil)  return 0;\r\n    if (key == n->key)  return 1;\r\n    if (key < n->key)\r\n        return search(n->left, key);\r\n    else\r\n        return search(n->right, key);\r\n}\r\n==\r\n\r\nh3(#rotatii). Rotaţii\r\n\r\nRotaţiile sunt cărămizile de la baza structurii de Treap.\r\n\r\np=. !treapuri?Fig1d.png!\r\n\r\np=. _*Figura 1*: Rotaţiile într-un arbore binar de căutare. Nodurile sunt reprezentate de cercuri iar subarborii de triunghiuri. Ambele operaţii de rotaţie menţin invariantul arborilor de căutare._\r\n\r\nSă urmărim efectul rotaţiilor asupra structurii de heap a unui treap care respectă doar invariantul arborilor de căutare. Aşadar, să presupunem că arborele din figura din stânga are o structură de heap cu excepţia lui $w$ care are o prioritate mai mare decât a lui $z$. Dacă îl rotim pe $w$ spre dreapta vedem în figura din dreapta că structura de heap este satisfăcută. Din moment ce $A$ era un subarbore valid al lui $w$, va rămâne în continuare un subarbore valid. Cum $B$ şi $C$ se aflau iniţial sub $z$ ei aveau o prioritate mai mică decât a lui $z$, şi, astfel, după rotaţie ei sunt subarbori valizi pentru $z$. Este clar că $z$ este un fiu valid al lui $w$, prin presupunerea făcută iniţial. \r\n\r\nSă urmărim dacă invariantul arborilor de căutare se menţine în urma unei astfel de rotaţii.\r\n\r\n* În arborele din figura din stânga avem inegalităţile următoare: $A < w < B; z < C; w, A, B < z$. Din acestea se obţine: $A < w < B < z < C$.\r\n* În arborele din figura din dreapta avem inegalităţile următoare: $A < w; B < z < C; w < z, B, C$. Din acestea se obţine: $A < w < B < z < C$.\r\n\r\nCum am obţinut acelaşi şir de inegalităţi, am arătat existenţa invariantului arborilor de căutare.\r\n\r\nReţineţi că această rotaţie împreună cu imaginea sa în oglindă, rotaţia spre stânga dacă urmărim desenul de la dreapta spre stânga, stau la baza algoritmilor de \'$inserare$\':treapuri#inserare şi \'$ştergere$\':treapuri#stergere!\r\n\r\nPentru o rotaţie sunt necesare doar câteva operaţii cu pointeri.\r\n\r\n== code(cpp) |\r\nvoid rotleft(T* &n) \r\n{\r\n    T *t = n->left;\r\n    n->left = t->right, t->right = n;\r\n    n = t;           \r\n}\r\n\r\nvoid rotright(T* &n) \r\n{\r\n    T *t = n->right;\r\n    n->right = t->left, t->left = n;\r\n    n = t;           \r\n}\r\n\r\nvoid balance(T* &n) \r\n{\r\n    if (n->left->priority > n->priority)\r\n        rotleft(n);\r\n    else if (n->right->priority > n->priority)\r\n        rotright(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(1)$.\r\n\r\nh3(#inserare). Inserare\r\n\r\nÎn cadrul operaţiei de inserare vom atribui unui nod nou o prioritate aleatoare şi îl vom insera, conform algoritmului standard de inserare într-un arbore binar, la baza arborelui. Să presupunem că dorim să inserăm nodul $z$ cu cheia $9$ şi prioritatea $51$.\r\n\r\np=. !treapuri?Fig2c.png!\r\n\r\np=. _*Figura 2*: De la stânga la dreapta: inserarea nodului $z$. De la dreapta la stânga: ştergerea nodului $z$. Deoarece $z$ are prioritatea cea mai mare dintre toate nodurile, această inserare poate fi privită şi ca o operaţie de $split$. Subarborii stâng şi drept ai rădăcinii din ultima figură sunt chiar treapurile căutate: $T{~<~}$ şi $T{~>~}$. Invers, din $T{~<~}$ şi $T{~>~}$ se obţine, prin ştergerea rădăcinii, rezultatul operaţiei $join$._\r\n\r\nCheile formează un arbore de căutare, dar priorităţile pot să nu mai formeze un heap. Pentru a redobândi această proprietate, cât timp nodul de inserat, are prioritatea mai mare decât a părintelui său, se va executa o \'$rotaţie$\':treapuri#rotatii în $z$, o operaţie locală care scade nivelul lui $z$ cu $1$ şi creşte nivelul părintelui lui $z$ cu $1$, şi care menţine invariantul arborilor de căutare. Timpul de inserare al lui $z$ este proporţional cu adâncimea lui înainte de rotaţii - trebuie să coborâm după care să urcăm înapoi efectuând rotaţiile necesare.\r\n\r\n== code(cpp) |\r\nvoid insert(T* &n, int key, int priority)\r\n{\r\n    if (n == nil) {\r\n        n = new T(key, priority, nil, nil);\r\n        return;\r\n    }\r\n    if (key <= n->key)\r\n        insert(n->left, key, priority);\r\n    else if (key > n->key)\r\n        insert(n->right, key, priority);\r\n\r\n    balance(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#stergere). Ştergere\r\n\r\nOperaţia de ştergere este inversul operaţiei de inserare. Scopul este să aducem acest nod, fie el $z$, în poziţia unei frunze pentru a-l şterge. Astfel, pentru a menţine cei doi invarianţi (făcând excepţie de $z$) vom alege fiul cu prioritatea mai mare şi îl vom \'$roti$\':treapuri#rotatii în locul lui $z$, cât timp acesta nu este frunză. Atunci când $z$ devine frunză îl vom şterge.\r\n\r\n== code(cpp) |\r\nvoid erase(T* &n, int key) \r\n{\r\n    if (n == nil)   return ;\r\n\r\n    if (key < n->key)\r\n        erase(n->left, key);\r\n    else if (key > n->key)\r\n        erase(n->right, key);\r\n    else {    \r\n        (n->left->priority > n->right->priority) ? rotleft(n) : rotright(n);\r\n        if (n != nil)  \r\n            erase(n, key);\r\n        else {\r\n            delete n->left;\r\n            n->left = NULL;\r\n        }\r\n    }\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#split). Split\r\n\r\nUneori dorim să despărţim treapul $T$ în două treapuri $T{~<~}$ şi $T{~>~}$ astfel încât cheile din $T{~<~}$ să conţină cheile din $T$ mai mici decât o cheie $key$ dată, iar $T{~>~}$ să conţină cheile din $T$ mai mari decât aceeaşi cheie $key$. Soluţia constă în inserarea unui nod ajutător $z$ a cărui cheie este $key$ şi prioritate $infinit$. După inserare, $z$ va fi rădăcina arborelui, având prioritatea cea mai mare iar subarborii stâng şi drept ai rădăcănii vor fi exact treapurile căutate. Pe $z$ îl vom şterge, deoarece nu mai avem nevoie de el.\r\n\r\nCostul operaţiei $split$ este egal cu costul operaţiei de \'$inserare$\':treapuri#inserare a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid split(T* &R, T* &Ts, T* &Tg, int key) \r\n{\r\n    insert(R, key, infinity);\r\n    Ts = R->left, Tg = R->right;\r\n    delete R, R = nil;\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#join). Join\r\n\r\nOperaţia $join$ constă în unirea a două treapuri $T{~<~}$ şi $T{~>~}$, unde fiecare cheie din $T{~<~}$ este mai mică decât o cheie $key$ iar oricare cheie din $T{~>~}$ este mai mare decât aceeaşi cheie $key$, într-un singur super-treap. $Join$ se realizează în mod invers operaţiei de $split$ prin crearea unei rădăcini $z$ cu cheia $key$ şi prioritate oricât, ce are ca subarbore stâng pe $T{~<~}$ iar ca subarbore drept pe $T{~>~}$, pe care o vom suprima.\r\n\r\nCostul operaţiei $join$ este egal cu costul operaţiei de \'$ştergere$\':treapuri#stergere a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid join(T* &R, T* Ts, T* Tg, int key) \r\n{\r\n    R = new T(key, 0, Ts, Tg);\r\n    erase(R, R->key);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#alteoperatii). Alte operaţii\r\n\r\nStructura de date de Treap suportă, pe lângă operaţiile prezentate, şi operaţia de determinarea a celei de a $K$-a chei, precum şi determinarea maximului, a minimului, a succesorului sau predecesorului unei chei, sau de tipărire a conţinutului cheilor pe baza relaţiei de ordine stabilite.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nNu întotdeauna $STL$ ne scapă din încurcătură. Nu avem în această librărie o structură de date pentru determinarea celei de a $K$-a chei în timp logaritmic şi nici nu ne putem folosi de structura arborescentă a lui $set$ şamd. Exemple grăitoare, în care se foloseşte structura arborescentă a treapurilor, sunt aplicaţiile prezentate mai jos. Cât despre alternative, puteţi face o comparaţie între funcţiile \'$erase$\':treapuri#stergere sau \'$balance$\':treapuri#rotatii cu cele din articolul următor despre arborii \'$AVL$\':multe-smenuri-de-programare-in-cc-si-nu-numai#AVL.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\n* \'Order\':problema/order, info{_arena_}\r\n* \'Schi\':problema/schi, info{_arena_}\r\n* \'Zeap\':problema/zeap, info{_arena_}\r\n* \'Vmem\':http://campion.edu.ro/problems/3/444/vmem_ro.htm, .campion\r\n* \'Bile\':http://campion.edu.ro/problems/3/443/bile_ro.htm, .campion\r\n* \'Trains\':http://campion.edu.ro/problems/3/432/trains_ro.htm, .campion\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* \'Eternally Confuzzled\':http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_bst2.aspx\r\n* \'Fast Set Operations Using Treaps\':http://www.cs.cmu.edu/afs/cs.cmu.edu/project/scandal/public/papers/treaps-spaa98.pdf, operaţiile \'$split$\':treapuri#split şi \'$join$\':treapuri#join sub altă formă\r\n* \'Treaps and Skip Lists\':http://compgeom.cs.uiuc.edu/~jeffe/teaching/algorithms/notes/06-treaps.pdf\r\n* \'Balanced Search Trees\':http://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15451-s07/www/lecture_notes/lect0208.pdf',3146,'public',NULL,NULL),('treapuri','Treapuri','2008-01-21 16:18:25','2008-12-01 21:19:28','h1. Treapuri\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'{*} Introducere\':treapuri#introducere\r\n* \'{*} Avantaje\':treapuri#avantaje\r\n* \'{*} Operaţii\':treapuri#operatii\r\n** \'- Căutare\':treapuri#cautare\r\n** \'- Rotaţii\':treapuri#rotatii\r\n** \'- Inserare\':treapuri#inserare\r\n** \'- Ştergere\':treapuri#stergere\r\n** \'- Split\':treapuri#split\r\n** \'- Join\':treapuri#join\r\n** \'- Alte operaţii\':treapuri#alte-operatii\r\n* \'{*} Concluzii\':treapuri#concluzii\r\n* \'{*} Aplicaţii\':treapuri#aplicatii\r\n* \'{*} Bibliografie\':treapuri#bibliografie\r\n\r\n\r\nÎn acest articol voi prezenta o alternativă pentru arborii binari de căutare echilibraţi, precum $AVL$, $Red-Black Trees$, $Splay Trees$ şi $B-Trees$.\r\n\r\nh2(#introducere). Introducere\r\n\r\nTreapul este un arbore binar în care fiecare nod conţine două informaţii:\r\n\r\n* $cheie$\r\n\r\n* $prioritate$\r\n\r\nStructura de date respectă doi invarianţi:\r\n\r\n* $dacă parcurgem arborele în inordine, atunci vom obţine nodurile sortate (invariantul arborilor de căutare)$\r\n\r\n* $prioritatea fiecărui nod este mai mare decât cea a fiilor săi (invariantul heapurilor)$\r\n\r\nÎn consecinţă, treapul este un arbore binar de căutare pentru chei şi un max-heap pentru priorităţi.\r\n\r\nÎn continuare, vom presupune că oricare două chei din treapul $T$ sunt distincte. Cazul când avem nevoie de chei egale se va trata relativ uşor după ce acest articol va fi înţeles.\r\n\r\nAstfel, din moment ce $T$ este un heap, nodul $v$ cu prioritatea cea mai mare trebuie să fie rădăcina. Întrucât este şi un arbore binar de căutare, orice nod $u$ cu $cheie(u) < cheie(v)$ se găseşte în subarborele stâng al lui $v$, şi orice nod $w$ cu $cheie(w) > cheie(v)$ se găseşte în subarborele drept.\r\n\r\nCheile şi priorităţile asociate lor, in condiţiile în care ambele sunt distincte, determină în mod unic forma unui treap. Prin inducţie se demonstrează că treapul este arborele binar obţinut prin inserarea cheilor în ordinea descrescătoare a priorităţilor. Algoritmul de inserare este cel obişnuit pentru arborii de căutare. Astfel, cum fiecare set de priorităţi asociat nodurilor va aranja arborele într-un singur mod, probabilitatea ca arborele să fie echilibrat este rezonabil de mare, fapt datorat numărului mic al arborilor rău echilibraţi în comparaţie cu cei echilibraţi. Iată şi secretul acestei structuri de date: probabilitatea infimă de a se găsi o serie de priorităţi generate aleator care să nu menţină arborele echilibrat.\r\n\r\nh2(#avantaje). Avantaje\r\n\r\nStructurile de date de heap şi de arbori binari de căutare sunt uşor de implementat şi de înţeles, iar treapurile sunt o combinaţie a acestor două concepte. Astfel, este suficient să fie înţeleşi cei doi invarianţi, după care implementarea se poate face cu uşurinţă în 20 de minute, fără antrenament. De obicei, la structuri ca $Arborii Roşu-Negru$ trebuie folosite serii de rotaţii stânga şi dreapta complexe şi analizată o multitudine de cazuri, pe când la treapuri facem doar câte o rotaţie stânga sau dreapta la fiecare pas al algoritmului. Ei nu sunt predaţi pentru că se preferă ca exemple didactice $Arborii Roşu-Negru$ sau cei $AVL$ care au o demonstraţie accesibilă că limita celei mai lente operaţii este $O(log N)$. Dar treapurile, deşi cu o demonstraţie mai grea pentru limita de $O(log N)$, ce implică probabilităţi, sunt mult mai uşor de implementat, iar în practică, cu siguranţă este greu de decis care sunt mai rapizi. Sunt, deci, o opţiune demnă de luat în seamă. Pe de altă parte, treapurile suportă şi alte două operaţii pe care nu le putem face cu $Arborii Roşu-Negru$ sau cu arborii $AVL$. Aceste operaţii sunt \'$join$\':treapuri#join şi \'$split$\':treapuri#split.\r\n\r\nh2(#operatii). Operaţii\r\n\r\nCostul operaţiilor de mai jos este proporţional cu adâncimea unui nod din treap. După cum am menţionat mai sus, cu ajutorul teoriei probabilităţilor se poate deduce că adâncimea medie aşteptată a oricărui nod este $O(log N)$, ceea ce implică costul celor mai lente operaţii să fie, în medie, $O(log N)$.\r\n\r\nMai jos avem definiţia în cod $C++$ a unui treap şi o funcţie de iniţializare, care marchează că treapul cu rădăcina $R$ este gol.\r\n\r\n== code(cpp) |\r\nstruct T {\r\n    int key;\r\n    int priority;\r\n    T *left, *right;\r\n    T() {}\r\n    T(int key, int priority, T* left, T* right) {\r\n        this->key = key, this->priority = priority;\r\n        this->left = left, this->right = right;\r\n    }\r\n} *R, *nil; // nil indica un nod \'gol\'\r\n\r\nvoid init(T* &R) {\r\n    srand(unsigned(time(0)));\r\n    R = nil = new T(0, 0, NULL, NULL);\r\n}\r\n==\r\n\r\nh3(#cautare). Căutare\r\n\r\nCăutarea într-un treap este identică cu cea într-un arbore binar de căutare. Pentru a verifica dacă o cheie există putem proceda în felul următor:\r\n\r\n== code(cpp) |\r\nint search(T* n, int key) {\r\n    if (n == nil) return 0;\r\n    if (key == n->key) return 1;\r\n    if (key < n->key)\r\n        return search(n->left, key);\r\n    else\r\n        return search(n->right, key);\r\n}\r\n==\r\n\r\nh3(#rotatii). Rotaţii\r\n\r\nRotaţiile sunt cărămizile de la baza structurii de treap.\r\n\r\np=. !treapuri?Fig1.png!\r\n\r\np=. _*Descriere:* Rotaţiile într-un arbore binar de căutare. Nodurile sunt reprezentate de cercuri, iar subarborii de triunghiuri. Ambele operaţii de rotaţie menţin invariantul arborilor de căutare._\r\n\r\nSă urmărim efectul rotaţiilor asupra structurii de heap a unui treap care respectă doar invariantul arborilor de căutare. Aşadar, să presupunem că arborele din figura din stânga are o structură de heap cu excepţia lui $w$ care are o prioritate mai mare decât a lui $z$. Dacă îl rotim pe $w$ spre dreapta vedem în figura a doua că structura de heap este satisfăcută. Din moment ce $A$ era un subarbore valid al lui $w$, va rămâne în continuare un subarbore valid. Cum $B$ şi $C$ se aflau iniţial sub $z$, ei aveau o prioritate mai mică decât a lui $z$, şi, astfel, după rotaţie ei sunt subarbori valizi pentru $z$. Este clar că $z$ este un fiu valid al lui $w$, prin presupunerea făcută iniţial. \r\n\r\nSă urmărim dacă invariantul arborilor de căutare se menţine în urma unei astfel de rotaţii.\r\n\r\n* În arborele din figura din stânga avem inegalităţile următoare: $A < w < B; z < C; w, A, B < z$. Din acestea se obţine: $A < w < B < z < C$.\r\n* În arborele din figura din dreapta avem inegalităţile următoare: $A < w; B < z < C; w < z, B, C$. Din acestea se obţine: $A < w < B < z < C$.\r\n\r\nÎntrucât am obţinut acelaşi şir de inegalităţi, am arătat existenţa invariantului arborilor de căutare.\r\n\r\nReţineţi că această rotaţie împreună cu imaginea sa în oglindă stau la baza algoritmilor de \'$inserare$\':treapuri#inserare şi \'$ştergere$\':treapuri#stergere!\r\n\r\nPentru o rotaţie este necesar un număr constant de operaţii cu pointeri.\r\n\r\n== code(cpp) |\r\nvoid rotleft(T* &n) {\r\n    T *t = n->left;\r\n    n->left = t->right, t->right = n;\r\n    n = t;\r\n}\r\n\r\nvoid rotright(T* &n) {\r\n    T *t = n->right;\r\n    n->right = t->left, t->left = n;\r\n    n = t;\r\n}\r\n\r\nvoid balance(T* &n) {\r\n    if (n->left->priority > n->priority)\r\n        rotleft(n);\r\n    else if (n->right->priority > n->priority)\r\n        rotright(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(1)$.\r\n\r\nh3(#inserare). Inserare\r\n\r\nÎn cadrul operaţiei de inserare vom atribui unui nod nou o prioritate aleatoare şi îl vom insera, conform algoritmului standard de inserare într-un arbore binar, la baza arborelui. Să presupunem că dorim să inserăm nodul $z$ cu cheia $9$ şi prioritatea $51$.\r\n\r\np=. !treapuri?Fig2.png!\r\n\r\np=. _*Descriere:* De la stânga la dreapta: inserarea nodului $z$. De la dreapta la stânga: ştergerea nodului $z$. Deoarece $z$ are prioritatea cea mai mare dintre toate nodurile, această inserare poate fi privită şi ca o operaţie de $split$. Subarborii stâng şi drept ai rădăcinii din ultima figură sunt chiar treapurile căutate: $T{~<~}$ şi $T{~>~}$. Invers, din $T{~<~}$ şi $T{~>~}$ se obţine, prin ştergerea rădăcinii, rezultatul operaţiei $join$._\r\n\r\nCheile formează un arbore de căutare, dar priorităţile pot să nu mai formeze un heap. Pentru a redobândi această proprietate, cât timp nodul de inserat, are prioritatea mai mare decât a părintelui său, se va executa o \'$rotaţie$\':treapuri#rotatii în $z$, o operaţie locală care scade nivelul lui $z$ cu $1$ şi creşte nivelul părintelui lui $z$ cu $1$, şi care menţine invariantul arborilor de căutare. Timpul de inserare al lui $z$ este proporţional cu adâncimea lui înainte de rotaţii - trebuie să coborâm, după care să urcăm înapoi efectuând rotaţiile necesare.\r\n\r\n== code(cpp) |\r\nvoid insert(T* &n, int key, int priority) {\r\n    if (n == nil) {\r\n        n = new T(key, priority, nil, nil);\r\n        return;\r\n    }\r\n    if (key < n->key)\r\n        insert(n->left, key, priority);\r\n    else if (key > n->key)\r\n        insert(n->right, key, priority);\r\n\r\n    balance(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#stergere). Ştergere\r\n\r\nOperaţia de ştergere este inversul operaţiei de inserare. Scopul este să aducem acest nod, fie el $z$, în poziţia unei frunze pentru a-l şterge. Astfel, pentru a menţine cei doi invarianţi (făcând excepţie de $z$) vom alege fiul cu prioritatea mai mare şi îl vom \'$roti$\':treapuri#rotatii în locul lui $z$, cât timp acesta nu este frunză. Atunci când $z$ devine frunză îl vom şterge.\r\n\r\n== code(cpp) |\r\nvoid erase(T* &n, int key) {\r\n    if (n == nil) return ;\r\n\r\n    if (key < n->key)\r\n        erase(n->left, key);\r\n    else if (key > n->key)\r\n        erase(n->right, key);\r\n    else {\r\n        (n->left->priority > n->right->priority) ? rotleft(n) : rotright(n);\r\n        if (n != nil)\r\n            erase(n, key);\r\n        else {\r\n            delete n->left;\r\n            n->left = NULL;\r\n        }\r\n    }\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#split). Split\r\n\r\nUneori dorim să despărţim treapul $T$ în două treapuri $T{~<~}$ şi $T{~>~}$ astfel încât cheile din $T{~<~}$ să conţină cheile din $T$ mai mici decât o cheie $key$ dată, iar $T{~>~}$ să conţină cheile din $T$ mai mari decât aceeaşi cheie $key$. Soluţia constă în inserarea unui nod ajutător $z$ a cărui cheie este $key$ şi prioritate $infinit$. După inserare, $z$ va fi rădăcina arborelui, având prioritatea cea mai mare, iar subarborii stâng şi drept ai rădăcănii vor fi exact treapurile căutate. Pe $z$ îl vom şterge, deoarece nu mai avem nevoie de el.\r\n\r\nCostul operaţiei $split$ este egal cu costul operaţiei de \'$inserare$\':treapuri#inserare a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid split(T* &R, T* &Ts, T* &Tg, int key) {\r\n    insert(R, key, infinity);\r\n    Ts = R->left, Tg = R->right;\r\n    delete R, R = nil;\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#join). Join\r\n\r\nOperaţia $join$ constă în unirea a două treapuri $T{~<~}$ şi $T{~>~}$, unde fiecare cheie din $T{~<~}$ este mai mică decât o cheie $key$, iar fiecare cheie din $T{~>~}$ este mai mare decât aceeaşi cheie $key$, într-un singur super-treap. $Join$ se realizează în mod invers operaţiei de $split$ prin crearea unei rădăcini $z$ cu cheia $key$ şi o prioritate aleatoare, ce are ca subarbore stâng pe $T{~<~}$, iar ca subarbore drept pe $T{~>~}$, pe care o vom suprima.\r\n\r\nCostul operaţiei $join$ este egal cu costul operaţiei de \'$ştergere$\':treapuri#stergere a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid join(T* &R, T* Ts, T* Tg, int key) {\r\n    R = new T(key, 0, Ts, Tg);\r\n    erase(R, R->key);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#alte-operatii). Alte operaţii\r\n\r\nStructura de date de treap suportă, pe lângă operaţiile prezentate, şi operaţia de determinare a celei de a $K$-a chei, precum şi determinarea maximului, a minimului, a succesorului sau predecesorului unei chei, sau de tipărire a conţinutului cheilor pe baza relaţiei de ordine stabilite.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nNu întotdeauna $STL$ ne scapă din încurcătură. Nu avem în această bibliotecă o structură de date pentru determinarea celei de a $K$-a chei în timp logaritmic şi nici nu ne putem folosi de structura arborescentă a lui $set$. Exemple grăitoare, în care se foloseşte structura arborescentă a treapurilor, sunt aplicaţiile prezentate mai jos. Cât despre alternative, puteţi face o comparaţie a funcţiilor \'$erase$\':treapuri#stergere sau \'$balance$\':treapuri#rotatii cu cele din articolul următor despre arborii \'$AVL$\':multe-smenuri-de-programare-in-cc-si-nu-numai#AVL.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\n* \'Order\':problema/order, info{_arena_}\r\n* \'Schi\':problema/schi, info{_arena_}\r\n* \'Zeap\':problema/zeap, info{_arena_}\r\n* \'Vmem\':http://campion.edu.ro/problems/3/444/vmem_ro.htm, .campion\r\n* \'Bile\':http://campion.edu.ro/problems/3/443/bile_ro.htm, .campion\r\n* \'Trains\':http://campion.edu.ro/problems/3/432/trains_ro.htm, .campion\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* \'Eternally Confuzzled\':http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_bst2.aspx\r\n* \'Fast Set Operations Using Treaps\':http://www.cs.cmu.edu/afs/cs.cmu.edu/project/scandal/public/papers/treaps-spaa98.pdf, operaţiile \'$split$\':treapuri#split şi \'$join$\':treapuri#join sub altă formă\r\n* \'Treaps and Skip Lists\':http://compgeom.cs.uiuc.edu/~jeffe/teaching/algorithms/notes/06-treaps.pdf\r\n* \'Balanced Search Trees\':http://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15451-s07/www/lecture_notes/lect0208.pdf',2044,'public',NULL,NULL),('utilizator/cosser','Profil','2007-12-10 17:02:46','2008-11-28 12:21:20','h2. Despre mine si ce ascult\r\n\r\n* _(Clasa a XII-a)_\r\n%{color green}...%\r\n%{color:blue} Xiu Xiu, Blonde Redhead, Radiohead, Animal Collective, Tv on the Radio, IBOPA, Velvet Undergound, Led Zeppelin..........%\r\n\r\nh2. Distinctii primite\r\n\r\n* _(NULL)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(NULL)_\r\n\r\n',7333,'public',NULL,NULL),('template/algoritmiada-2009/header','template/algoritmiada-2009/header','2008-11-30 14:05:56','2008-12-02 23:43:07','p{margin: 2em 0 1em 0; padding: .5em; border: 1px solid silver; -moz-border-radius: 10px;}. !template/algoritmiada-2009/header?a.jpg?logo.jpg 0%!:home',15,'protected',NULL,NULL),('template/algoritmiada-2009/header','template/algoritmiada-2009/header','2008-11-30 14:05:56','2008-12-02 23:43:40','p{margin: 2em 0 1em 0; padding: .5em; border: 1px solid silver; -moz-border-radius: 10px;}. !template/algoritmiada-2009/header?logo.jpg 0%!:home',15,'protected',NULL,NULL),('template/algoritmiada-2009/header','template/algoritmiada-2009/header','2008-11-30 14:05:56','2008-12-03 00:38:46','p{margin: 2em 0 1em 0; padding: .5em; border: 1px solid silver; -moz-border-radius: 10px;}. !template/algoritmiada-2009/header?logo.jpg 100%!:home',15,'protected',NULL,NULL),('blog/modele','Modele','2008-12-03 05:35:53','2008-12-03 06:15:02','Discutam cu \'Mircea\':http://www.google.com/search?hl=en&q=Mircea+Pasoi&btnG=Google+Search&aq=f&oq= vara asta despre Erich Schmidt si Steve Jobs. Ii comparam noi si lui Mircea ii placea mai mult de Steve pe cand mie imi placea de Erich. \r\n\r\nPe \'Eric Schmidt\':http://en.wikipedia.org/wiki/Eric_Schmidt am senzatia ca il pot intelege. El este la origine programator. Pe parcursul doctoratului el a implementat \'Lex\':http://dinosaur.compilertools.net/lex/ un generator de analizatoare lexicografice (probabil ati auzit de lex daca ati facut un curs de compilatoare). A fost Chief Technical Officer al Sun Microsistems, apoi Chief Executive Officer al Novell si ultimul job pe care il detine e CEO al Google.   Lui Eric ii place sa vorbeasca si se gasesc o \'gramada\':http://www.youtube.com/results?search_query=Eric+Schmidt&search_type=&aq=f de interviuri. El isi exprima clar opiniile ele sunt bine gandite si sunt argumentate. \r\n\r\nIn schimb, pe Steve Jobs nu il inteleg. El ca personaj e foarte cool si are in spate multe realizari. A revolutionat industria calculatoarelor personale, apoi creand Pixar a revolutionat industria filmelor de animatie. Mai tarziu revenind la Apple a revolutionat industria de mp3 playere si mai recent prin iPhone a revolutionat industria telefoanelor mobile. Sunt mai putine \'materiale\':http://www.youtube.com/results?search_query=Steve+Jobs&search_type=&aq=-1&oq=Steve+Job online despre el, si e mai greu sa vezi de ce Steve are succes.\r\n\r\nPe de o parte Eric e la baza un inginer care a devenit un manager foarte bun. Steve e un product manager exceptional care are o privire de ansamblu foarte buna. Pentru mine e putin mai greu sa inteleg partile de strategie si de marketing pentru produse, si acolo exceleaza Steve. Pe langa viziunea macro pe care o are el este se concentreaza foarte mult si pe detalii. Am auzit indirect de oameni ce lucreaza la Apple la care Steve a venit in birou fara sa fi vorbit cu ei vreodata inainte, si le-a cerut sa mute un buton din aplicatia lor cativa milimetri la stanga.\r\n',58,'private',NULL,NULL),('blog/modele','Modele','2008-12-03 05:35:53','2008-12-03 06:33:19','Discutam cu \'Mircea\':http://www.google.com/search?hl=en&q=Mircea+Pasoi&btnG=Google+Search&aq=f&oq= vara asta despre Erich Schmidt si Steve Jobs. Ii comparam noi si lui Mircea ii placea mai mult de Steve pe cand mie imi placea de Eric. \r\n\r\nPe \'Eric Schmidt\':http://en.wikipedia.org/wiki/Eric_Schmidt am senzatia ca il pot intelege. El este la origine programator. Pe parcursul doctoratului a fost unul dintre creatorii \'Lex\':http://dinosaur.compilertools.net/lex/ un generator de analizatoare lexicografice (probabil ati auzit de lex daca ati facut un curs de compilatoare). A fost Chief Technical Officer la Sun Microsistems, apoi Chief Executive Officer la Novell . Ultimul job pe care il detine e CEO al Google. Lui Eric ii place sa vorbeasca si se gasesc o \'gramada\':http://www.youtube.com/results?search_query=Eric+Schmidt&search_type=&aq=f de interviuri. Opiniile lui sunt bine gandite si argumentate, iar prin ele ma convinge ca este un om valoros.\r\n\r\nPe Steve Jobs in schimb nu il inteleg. El ca personaj e \'foarte cool\':http://www.google.com/search?q=steve+jobs+reality+distortion+field&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-US:official&client=firefox-a si are in spate multe realizari. A revolutionat industria calculatoarelor personale, apoi creand Pixar a revolutionat industria filmelor de animatie. Mai tarziu revenind la Apple a revolutionat industria de mp3 playere si mai recent prin iPhone a revolutionat industria telefoanelor mobile. Sunt mai putine \'materiale\':http://www.youtube.com/results?search_query=Steve+Jobs&search_type=&aq=-1&oq=Steve+Job online despre el, si e mai greu sa vezi de ce Steve are succes.\r\n\r\nPe de o parte Eric e la baza un inginer care a devenit un manager foarte bun. Steve e un product manager exceptional care are o privire de ansamblu foarte buna. Pentru mine e putin mai greu sa inteleg partile de strategie si de marketing, si acolo exceleaza Steve. Pe langa viziunea macro pe care o are el este se concentreaza foarte mult si pe detalii. Am auzit indirect de oameni ce lucreaza la Apple la care Steve a venit in birou fara sa fi vorbit cu ei vreodata inainte, si le-a cerut sa mute un buton din aplicatia lor cativa milimetri la stanga.\r\n\r\nConsider discutii de genul asta interesante. Oamenii pe care ii respecti si pe care ii consideri modele, spun ceva despre tine. Acestia arata intr-o anumita masura directia in care vrei sa te indrepti, calitatile pe care le consideri importante si pe care ti-ai dori sa le ai.\r\n\r\nVoi ce parere aveti despre Eric sau Steve si pe ce alti oameni din IT ii respectati?',58,'private',3441,NULL),('algoritmiada-2009','Algoritmiada 2009 - olimpiada algoritmilor','2008-11-30 14:01:47','2008-12-03 20:42:28','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh2. Despre Algoritmiada\r\n\r\nIncepand de anul acesta, infoarena organizeaza concursul de programare Algoritmiada. La acest concurs pot participa, in premiera pe tara, tineri pasionati de informatica de toate varstele: de la elevi de gimnaziu pana la studenti si doctoranzi.\r\n\r\nConcursul are patru grupe valorice: gimnaziu, clasele 9-10, clasele 11-12, studenti (inclusiv masteranzi si doctoranzi). Participantii vor avea ocazia sa-si demonstreze talentul, cunostintele si iutimea de minte in 3 probe online urmand ca cei mai buni sa fie invitati la finala on-site.\r\n\r\nh2. Cum particip?\r\n\r\nPentru a participa la concurs trebuie sa \'te inregistrezi\':register pe site-ul nostru.\r\n\r\nIn ziua de concurs intri pe site, citesti problemele de la grupa ta de varsta si trimiti solutiile inainte de expirarea timpului. \'Evaluatorul\':documentatie/evaluator nostru iti va testa automat solutiile iar punctajul il afli la sfarsitul concursului. Tot atunci vei putea consulta clasamentul pentru a vedea ce au facut si ceilalti concurenti.\r\n\r\nh2. Program\r\n\r\nFaceti click pe titlul unei runde pentru informatii detaliate.\r\n\r\ntable{width:50%}. |_. Runda |_. Data |_. Durata |\r\n| \'*Runda 1*\':algoritmiada-2009/runda-1 | *14 Decembrie 2008, Duminica* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 2*\':algoritmiada-2009/runda-2 | _Ianuarie 2009_ |=. &nbsp; |\r\n| \'*Runda 3*\':algoritmiada-2009/runda-3 | _Februarie 2009_ |=. &nbsp; |\r\n| \'*Runda Finala*\':algoritmiada-2009/runda-finala |=. _Martie 2009_ | |\r\n\r\n\r\nh2. Prima data pe _infoarena_?\r\n\r\n\'infoarena\':/ ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi si vezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',15,'protected',NULL,NULL),('documentatie/pentru-utilizatori','Ghidul utilizatorului','2006-12-11 02:14:57','2008-12-03 21:56:05','h1. Ghid utilizatori\r\n\r\nNe bucuram ca ai ajuns pe infoarena! Pe site-ul nostru vei gasi o comunitate entuziasta si o colectie interesanta de materiale educationale care te vor ajuta sa inveti informatica. Ramai cu noi!\r\n\r\nAcesta este un ghid scurt menit sa-ti explice cum te poti pregati pe infoarena. Iti recomandam sa incepi cu {\'tutorialul infoarena\':documentatie/tutorial} daca vrei sa rezolvi probleme sau vrei sa afli despre resursele educationale infoarena (forum, articole, download-uri).\r\n\r\nDaca ai o intrebare viziteaza-ne pe \'forum\':forum. Nu uita sa-ti completezi \'profilul\':documentatie/pagina-de-profil pentru a te integra cat mai bine in comunitatea infoarena. \r\n\r\nPentru informatii specifice despre o anumita functionalitate a site-ului urmareste una din legaturile de mai jos.\r\n\r\n* {\'Monitorul de evaluare\':documentatie/monitorul-de-evaluare}: Ce este si cum se foloseste monitorul de evaluare.\r\n* {\'Borderoul de evaluare\':documentatie/borderoul-de-evaluare}: Cum se interpreteaza borderoul de evaluare.\r\n* {\'Evaluatorul infoarena\':documentatie/evaluator}: Ce configuratie si ce compilatoare foloseste infoarena.\r\n* {\'Trimiterea solutiilor\':documentatie/trimiterea-solutiilor}: Cum se trimit solutii pe infoarena.\r\n* {\'Pagina de profil\':documentatie/pagina-de-profil}: Cum poti sa-ti editeazi profilul pe infoarena.\r\n* {\'Rating\':documentatie/rating}: Ce este si cum functioneaza sistemul de rating\r\n\r\n',15,'public',NULL,NULL),('schimbare-borland/ghid/proiect','Crearea unui proiect in MinGW Developer Studio','2008-11-10 17:27:32','2008-11-13 15:44:59','h1. Crearea unui proiect in MinGW Developer Studio\r\n\r\n==include(page=\"schimbare-borland/ghid/menu\")==\r\n\r\n[ TODO cand dai click pe imagine sa te duca pe ?action=download&file=... ]\r\n\r\nPentru a compila si a rula surse folosind mediul MinGW Developer Studio este necesara crearea unui proiect. Majoritatea mediilor de dezvoltare folosite in programare folosesc proiecte pentru a oferi o usoara administrare a programului aflat in dezvoltare.\r\n\r\nDaca lucrati la o solutie ce foloseste un singur fisier, un proiect poate parea sa va ingreuneze munca, insa din momentul in care veti implementa un proiect mai complex, conceptul de proiect o sa capete mai mult sens.\r\n\r\nPentru a crea un proiect nou puteti alege din urmatoarele trei optiuni:\r\n\r\n# Da-ti click pe prima icona din toolbar\r\n# Selectati File->New\r\n# Tastati Ctrl-N\r\n\r\n\'!schimbare-borland/ghid/proiect?creare_proiect_1.JPG 30%!\':schimbare-borland/ghid/proiect?action=download&file=creare_proiect_1.JPG \'!schimbare-borland/ghid/proiect?creare_proiect_2.JPG 30%!\':schimbare-borland/ghid/proiect?action=download&file=creare_proiect_2.JPG\r\n\r\nVom crea un proiect simplu, care interactioneaza cu consola din Windows. Alegeti locatia in care vreti sa se salveze proiectul vostru si datii un nume si selectati \"Win32 Console Application\" si apoi dati click pe butonul \"OK\".\r\n\r\n\r\n\'!schimbare-borland/ghid/proiect?creare_proiect_3.JPG 30%!\':schimbare-borland/ghid/proiect?action=download&file=creare_proiect_3.JPG \r\n\r\nFelicitari, ati creat un proiect in MinGW Developer Studio.\r\n\r\n\'!schimbare-borland/ghid/proiect?creare_proiect_4.JPG 30%!\':schimbare-borland/ghid/proiect?action=download&file=creare_proiect_4.JPG \r\n\r\n',15,'public',NULL,NULL),('template/algoritmiada-2009/header','template/algoritmiada-2009/header','2008-11-30 14:05:56','2008-12-04 18:26:11','p{margin: 2em 0 1em 0; padding: .2em; border: 1px solid silver; -moz-border-radius: 10px;}. \'!template/algoritmiada-2009/header?logo.jpg 100%!\':algoritmiada-2009',15,'protected',NULL,NULL),('template/taskfooter','template/taskfooter','2006-11-05 16:40:55','2006-11-24 16:38:05','== TaskSubmit(task_id=\"%task_id%\") ==\r\n\r\n\"Cum se trimit solutii?\":documentatie/pentru-utilizatori',1142,'protected',NULL,NULL),('echipa-infoarena','Echipa infoarena','2006-11-27 08:20:21','2008-10-14 10:34:43','h1. Echipa infoarena\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nMembrii echipei infoarena s-au remarcat prin activitate sustinuta in cadrul proiectelor infoarena. Acestia detin functii oficiale in \'Asociatia infoarena\':asociatia-infoarena. Echipa infoarena este responsabila de dezvoltarea si intretinerea site-ului infoarena precum si de desfasurarea altor proiecte ale Asociatiei. Coordonarea eforturilor echipei se face pe pagina de \'planificare\':planificare.\r\n\r\nEchipa infoarena se bucura de \'*sprijinul a zeci de voluntari*\':implica-te. O buna parte din continutul infoarena este rezultatul muncii lor. Suntem onorati sa primim ajutorul lor si le multumim sincer pentru efortul pe care l-au depus!\r\n\r\n\r\nh2. Membri fondatori\r\n\r\n* ==user(user=\"wickedman\" type=\"normal\")==  \r\n* ==user(user=\"silviug\" type=\"normal\")== \r\n* ==user(user=\"domino\" type=\"normal\")==\r\n* ==user(user=\"fluffy\" type=\"normal\")== \r\n\r\nh2. Consilieri\r\n\r\ntable(layout).\r\n|* ==user(user=\"ditzoneC\" type=\"normal\")==\r\n* ==user(user=\"filipb\" type=\"normal\")== \r\n* ==user(user=\"danielp\" type=\"normal\")==\r\n* ==user(user=\"Cosmin\" type=\"normal\")== \r\n* ==user(user=\"svalentin\" type=\"normal\")==  \r\n* ==user(user=\"astronomy\" type=\"normal\")==\r\n* ==user(user=\"wefgef\" type=\"normal\")==\r\n|* ==user(user=\"alexthero\" type=\"normal\")== \r\n* ==user(user=\"gcosmin\" type=\"normal\")== \r\n* ==user(user=\"bogdan2412\" type=\"normal\")== \r\n* ==user(user=\"pauldb\" type=\"normal\")== \r\n* ==user(user=\"Prostu\" type=\"normal\")== \r\n* ==user(user=\"stef2n\" type=\"normal\")== \r\n* ==user(user=\"victorsb\" type=\"normal\")==| \r\n\r\nh2. Consilieri emeritus\r\n\r\n* ==user(user=\"azotlichid\" type=\"normal\")==\r\n* ==user(user=\"greco\" type=\"normal\")==\r\n',1,'protected',NULL,NULL),('algoritmiada-2009','Algoritmiada 2009 - olimpiada algoritmilor','2008-11-30 14:01:47','2008-12-04 09:32:31','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh2. Despre Algoritmiada\r\n\r\nIncepând de anul acesta, _infoarena_ organizează concursul de programare Algoritmiada. La acest concurs pot participa, în premieră pe ţară, tineri pasionaţi de informatică de toate vârstele: de la elevi de gimnaziu până la studenţi şi doctoranzi.\r\n\r\nConcursul are patru grupe valorice: gimnaziu, clasele 9-10, clasele 11-12, studenţi (inclusiv masteranzi şi doctoranzi). Participanţii vor avea ocazia să-şi demonstreze talentul, cunostinţele şi iuţimea minţii în 3 probe online urmând ca cei mai buni sa fie invitaţi la finala on-site.\r\n\r\nh2. Cum particip?\r\n\r\nPentru a participa la concurs trebuie să fii \'înregistrat\':register pe site-ul nostru.\r\n\r\nÎn ziua de concurs intri pe site, citeşti problemele de la grupa ta de vârstă şi trimiţi soluţiile înainte de expirarea timpului. \'Evaluatorul\':documentatie/evaluator nostru iţi va testa automat soluţiile iar punctajul îl vei afla la sfârşitul concursului. Tot atunci vei putea consulta clasamentul pentru a vedea ce au făcut şi ceilalţi concurenţi.\r\n\r\nh2. Program\r\n\r\nFaceţi click pe titlul unei runde pentru informaţii detaliate.\r\n\r\ntable{width:50%}. |_. Runda |_. Data |_. Durata |\r\n| \'*Runda 1*\':algoritmiada-2009/runda-1 | *14 Decembrie 2008, Duminică* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 2*\':algoritmiada-2009/runda-2 | _Ianuarie 2009_ |=. &nbsp; |\r\n| \'*Runda 3*\':algoritmiada-2009/runda-3 | _Februarie 2009_ |=. &nbsp; |\r\n| \'*Runda Finală*\':algoritmiada-2009/runda-finala |=. _Martie 2009_ | |\r\n\r\n\r\nh2. Prima dată pe _infoarena_?\r\n\r\n\'infoarena\':/ ajută elevi şi studenţi să devină excelenţi în informatică! Gratuit ;) Citeşte \'ghidul utilizatorului\':documentatie/pentru-utilizatori şi află mai multe \'despre noi\':despre-infoarena.\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',1490,'protected',NULL,NULL),('blog/problema-saptamanii-cartofi-solutie','blog/problema-saptamanii-cartofi-solutie','2008-12-06 07:18:29','2008-12-06 07:18:29','_Problema curenta a fost rezolvata de Marius Andrei, Igor Na... Delia David, Dumitru Daniliuc_',58,'private',NULL,NULL),('blog/problema-saptamanii-cartofi-solutie','Problema saptamanii Cartofi (Solutie)','2008-12-06 07:18:29','2008-12-07 10:08:46','Problema curenta a fost rezolvata de Alexandru Mosoi, Marius Andrei, Igor Naverniouk, Delia David, Dumitru Daniliuc.\r\n\r\nProblema cerea _sa se demonstreze ca, dandu-se doi cartofi, exista o curba inchisa in trei dimensiuni care se poate desena pe suprafetele ambilor cartofi_.\r\n\r\nAceasta e una dintre problemele care par foarte grele la prima vedere si apoi daca auzi sau te prinzi de solutie pare foarte simpla.\r\n\r\nNe imaginam \"fantomele\" cartofilor. Le intersectam. O curba de intersectie a celor doua corpuri ne va da o curba ce poate fi desenata pe suprafete ambilor cartofi.',58,'protected',3453,NULL),('utilizator/floringh06','Profil floringh06','2007-01-14 12:13:14','2008-12-08 06:53:21','h2. Despre mine\r\n\r\nprin clasa a 12-a la un liceu de pe colt din sibiu...\r\n\r\n** Profesori indrumatori: **\r\n      Ciurea Stelian \r\n\r\n** Oameni de baza pe infoarena: **\r\n      Florian MOGA :)\r\n\r\n!utilizator/floringh06?poza.jpg  500x500!. \r\nVisul meu...\r\n\r\nh2. Distinctii primite\r\n\r\nCalificare ONI 2006, ONM 2006, ONM 2007, ONF 2004, ONM 2008...\r\nParticipare ONF 2006, ONI 2007, ONI 2008\r\nParticipare BARAJ la ONI 2007, ONI 2008\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n...Gasca de la ONI...\r\n==user(user=\"moga_florian\" type=\"normal\")==  \r\n==user(user=\"andrei_info\" type=\"normal\")== \r\n==user(user=\"luana_0105\" type=\"normal\")== \r\n==user(user=\"StTwister\" type=\"normal\")==\r\n==user(user=\"vlad_popa\" type=\"normal\")==\r\n\r\n\r\n\r\n',5653,'public',NULL,NULL),('2-sat','Problema satisfiabilităţii formulelor logice de ordinul doi','2008-12-09 15:55:03','2008-12-09 17:36:02','h1. Problema satisfiabilităţii formulelor logice de ordinul doi\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\nh2. Introducere\r\n\r\nProblema satisfiabiltăiţii, notată prescurtat cu $SAT$, cere determinarea existenţei pentru o formulă booleană <tex> \\phi </tex> a unei artibuiri satisfiabile. O formulă booleană <tex> \\phi </tex> este compusă din $variabile$ logice <tex> (x_{1}, x_{2}, ...) </tex>, $operatori$ logici ( <tex> \\wedge </tex> şi,  <tex> \\vee </tex> sau, <tex> \\sim </tex> non, <tex> \\rightarrow </tex> implicaţie şi <tex> \\leftrightarrow </tex> echivalenţă), şi $paranteze$. O atribuire de valori booleene pentru variabilele acestei expresii se numeşte $atribuire satisfiabilă$ dacă evaluarea expresiei după atribuirea valorilor dă ca rezultat valoarea de adevăr $adevărat$. De acum încolo vom folosi pentru simplitate valorile <tex> 1 </tex> şi <tex> 0 </tex> în loc de $adevărat$ şi $fals$.\r\n\r\nUn exemplu de formulă ar fi <tex> \\phi = ((x_{1} \\rightarrow x_{2}) \\vee \\sim((\\sim x_{1} \\leftrightarrow x_{3}) \\vee x_{4})) \\wedge \\sim x_{2} </tex>. Aceasta are atribuirea satisfiabilă <tex> \\langle x_{1} = 0, x_{2} = 0, x_{3} = 1, x_{4} = 1 \\rangle </tex> pentru că <tex> \\phi = ((0 \\rightarrow 0) \\vee \\sim((\\sim 0 \\leftrightarrow 1) \\vee 1)) \\wedge \\sim 0 = (1 \\vee \\sim (1 \\vee 1)) \\wedge 1 = (1 \\vee 0) \\wedge 1 = 1</tex>. \r\n\r\nh2. Forme normale ale formulelor logice\r\n\r\nOrice formulă booleană poate fi transformată în două forme:\r\n\r\n* $Forma normal conjunctivă$ în care expresia este exprimată ca o conjuncţie de propoziţii, iar fiecare propoziţie este formată din o disjuncţie de $literali$. Un $literal$ este o variabilă care poate fi sau nu negată. Un exemplu de expresie în forma normal conjunctivă ar fi: <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) \\wedge (x_{3} \\vee x_{2} \\vee x_{4}) \\wedge (\\sim x_{1} \\vee \\sim x_{3} \\vee \\sim x_{4}) </tex> care are pe <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) </tex> ca primă propoziţie cu literalii <tex> x_{1} </tex>, <tex> \\sim x_{1} </tex>, <tex> \\sim x_{2} </tex>.\r\n\r\n* $Forma normal disjunctivă$ este formată ca o disjuncţie de propoziţii, fiecare dintre aceste propoziţii fiind o conjuncţie de literali. Un exemplu de o asemenea formulă ar fi următoarea: <tex> (x_{1} \\wedge x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge \\sim x_{3}) \\vee (\\sim x_{1} \\wedge x_{2} \\wedge \\sim x_{2}) </tex>.\r\n\r\nh2. SAT, 3-SAT, 2-SAT\r\n\r\nProblema $SAT$ este $NP-completă$. Defapt, este prima problemă $NP-completă$ găsită. Stephen Cook a demonstrat $NP-completitudinea$ ei în 1971. Pe vremea aceea nu se ştia nici măcar că problemele $NP-complete$ există. Această problemă rămâne $NP-completă$ chiar dacă restricţionăm expresiile la unele care în forma normal conjunctivă au doar trei literali. Problema satisfiabilităţii pentru asemenea expresii se numeşte $3SAT$, şi multe probleme pot fi demonstrate a fi $NP-complete$ prin reducerea la această problemă. Din fericire, problema $2SAT$, adică cea pentru care în fiecare propoziţie există doar $2$ literali se poate rezolva eficient. Restul articolului va prezenta trei metode de rezolvare a problemei $2SAT$ şi câteva aplicaţii ale acesteia la concursuri de programare.\r\n\r\nUn exemplu de problemă $2SAT$ ar fi satisfiabilitatea formulei <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Această formulă este satisfăcută de valorile <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>. Pentru a satisface întreaga expresie trebuie ca în fiecare propoziţie cel puţin unul din cei doi literali să aibă valoarea de adevăr $1$.\r\n\r\nh3. Soluţie $O(M * 2^N^)$\r\n\r\nO primă metodă de rezolvare ar fi să încercăm toate cele $2^4^$ posibilităţi de atribuire posibilă, dar această metodă are ordinul de complexitate $O(M * 2^N^)$ şi este eficientă doar pentru instanţe mici ale problemei.\r\n\r\nh3. Soluţie $O(N * M)$\r\n\r\nUrmătoarea soluţie pare trivială, dar găsirea acestui algoritm şi realizarea faptului că el rezolvă corect problema este mai grea decât impresia lăsată după citirea ei. Considerăm o propoziţie oarecare cu două variabile $p$ şi $q$, apoi una dintre ele, de exemplu $p$. Dacă literalul în care apare $p$ este negat atunci îi atribuim valoarea $1$. Pentru ca propoziţia respectivă să aibă $1$ valoarea de adevăr atunci valoarea lui $q$ este fixată. Fixând şi valoarea lui $q$, probabil şi alte propoziţii ce conţin literalul $q$ vor avea celălalt literal fixat. Propagăm astfel o serie de schimbări. După ce toate schimbările forţate au fost făcute propoziţiile rezultate vor fi de următoarele tipuri: <tex> a \\vee b </tex>, <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex>. Propoziţii de tip <tex> 0 \\vee b </tex> nu pot apărea pentru că toate schimbările forţate au fost deja propagate. Dacă apare o propoziţie <tex> 0 \\vee 0 </tex> atunci alegerea făcută pentru valoarea lui $p$ este greşită. Vom încerca şi alegerea opusă. Dacă ambele duc la o propoziţie de tip <tex> 0 \\vee 0 </tex> atunci expresia nu poate fi satisfăcută. Propoziţiile de forma <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex> pot fi ignorate. În acest fel am eliminat cel puţin o variabilă şi o propoziţie din expresie. Dacă expresia iniţială era satisfiabilă, atunci şi expresia din care s-au eliminate câteva propoziţii a rămas satisfiabilă. Continuând pe această idee obţinem un algoritm de complexitate $O(N * M)$, pentru că la fiecare atribuire de valoare pentru o variabilă parcurgem şirul de propoziţii o dată. \r\n\r\nSă vedem cum funcţionează algoritmul pentru expresia: <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Considerăm propoziţia <tex> (x_{1} \\vee \\sim x_{2}) </tex> şi <tex> \\langle x_{2} = 1 \\rangle </tex>. Astfel, vom obţine mai departe <tex> (x_{1} \\vee 0) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee 1) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. În propoziţia <tex> (x_{1} \\vee 0) </tex> <tex> x_{1} </tex> trebuie să fie egal cu <tex> 1 </tex>. Acum, expresia devine: <tex> (0 \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee 0) </tex>. Din propoziţia <tex> (0 \\vee \\sim x_{3}) </tex> obţinem <tex> \\langle x_{3} = 0 \\rangle </tex>, iar din <tex> (x_{4} \\vee 0) </tex> obţinem <tex> \\langle x_{4} = 1 \\rangle </tex>. Deci, atribuirea satisfiabilă este <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>.\r\n\r\nh3. Soluţie O(N^2^)\r\n\r\nO altă soluţie elegantă se bazează pe o metodă randomizată: \r\n\r\n# pornim întâi cu o atribuire de valori booleene oarecare variabilelor;\r\n# găsim o propoziţie cu valoarea de adevăr <tex> 0 </tex>;\r\n# vom schimba valoarea de adevăr a oricăreia dintre cele două variabile prezente în propoziţie, ceea ce va face ca acea propoziţie să aibă noua valoare de adevăr <tex> 1 </tex>;\r\n# cât timp expresia nu este satisfăcută repetăm acest procedeu de schimbare a valorii unei variabile dintr-o propoziţie nesatisfăcută, deci revenim la pasul $2$.\r\n\r\n\r\n\r\n\r\n\r\n\r\n',3146,'public',NULL,NULL),('sandbox','Sandbox (cutiuţa cu năsip)','2006-11-11 18:59:57','2008-12-09 21:14:33','h1=. Sandbox (cutiuţa cu năsip)\r\n\r\nTabel mic:\r\n\r\ntable{width:20px}. |A|B|C|\r\n|1|2|3|\r\n\r\nDiacritice:\r\n\r\nStraşnic de îngâmfat, ţăranul crapă streaşina.\r\nStraşnic de îngâmfat, ţăranul crapă streaşina.\r\n\r\nIn Windows XP sp2 cu IE6 fara update de font se vede asa:\r\n!sandbox?diacritice-IE6.jpg!\r\n\r\nOrdered list:\r\n\r\n# 1st item\r\n# 2nd item\r\n\r\nh3. Use only F/OSS, Microsft sucks ;) just because they like design NOT the code itself.\r\n\r\nHowever, on a GNU system NEVER type <b>sudo make me sandwich</b> , and expect the results...\r\n\r\n\r\nx\r\n\r\n ==calendar()==\r\n\r\ny\r\n\r\n* A[1]\r\n* B[2]\r\n* C[3]\r\n\r\np(#fn1). <tex>2^n    * 2^n</tex>\r\n\"Vivi\'s blog\":http://vivi.ro\r\n<tex> d/(2\\\"a)=d/(2\\Omega^2) </tex>\r\n* <tex> d = \\sqrt{(c_{2}-c_{1})^{2} + 1 } </tex>\r\np. <tex> \r\n\\displaystyle \\sigma_{\\lambda} = \r\n	  \\frac{24 \\pi^3}{\\lambda^4 N^2}\r\n	  \\left(\\frac{n^2-1}{n^2+2}\\right)^{\\!2}\r\n</tex> \r\n\r\nAvem suport pentru <tex> \\LaTeX </tex> !\r\n\r\n<tex> \\frac{a^2 - b^2}{a + b} = a - b </tex>\r\n<tex>n! \\approx \\sqrt{2 \\pi n} (\\frac n e) ^n</tex>\r\n\r\n\r\n==Include(page=\"template/implica-te/scrie-articole\" user_id=\"domino\")==\r\n\r\np(#fn2). | test | test |\r\n\r\n\"User macro bug\":sandbox/usermacrobug\r\n\r\n*Worship me*\r\n\r\nFeel free to plghay around, but \'Big Brother\':/changes is watching you.\r\n\r\nTralalalala cu capsunele pe campii si elefanti pe pulele marete si ciupercute si bomboane.\r\n\r\n\'codetest\':sandbox/code-test\r\n\r\nWhat does \'this\':sandbox?action=edit button do?\r\n\r\nlalallaa\r\n\r\nIntrebare: cum poti seta culoarea cu care scrii?\r\nUite asa: %{color:violet}scris cu rosu%\r\n\r\nSiteul sub IE 7 -- vezi \'pagina dedicata\':ia_in_ie7\r\n\r\nSiteul sub FF 2 - -mica problema panoul de \'editeaza\', \'vezi istoria\', \'sterge\' etc (in IE7 panoul nu se suprapune)-\r\n!sandbox?IA_bug_in_FF2.jpg!\r\n\r\n[test]\r\n*OMG* test, good work people :D\r\nAcuma doar trebuie putin stimulata comunitatea\r\n[/test]\r\n\r\nInteresting choice of words.\r\na very bold **MAN**\r\n_CAPSOMANII-I DESPISE THEM_\r\n\r\ngasise pe-un teren viran,\r\nun geamantan.\r\n\r\nsi-n geamantan,\r\nun pachet.\r\n\r\nsi in pachet,\r\nun pachetel gasise el.\r\n\r\nsi-n pachetel,\r\nalt pachetel.\r\n\r\nsi-un pachetel in pachetel,\r\nlegat cu funde elegante.\r\n\r\nsi-n pachetel...vreo 40 de diamante...\r\n...\r\nAdio voi...va las si plec fiindca mi-e dor...\r\nsi a plecat Apolodor\r\n!!!<>\r\n\r\ntralalala blablabla lala\r\n\r\n_salut, aici poate sa scrie oricine ce vrea?_ ~Robert~\r\n\r\n|_. 1|_. 2|_. 3|\r\n|unu|doi|trei|\r\n|1... unu|2... doi|3... trei|\r\n\r\nMoraru Ionut has been here. :))\r\n\r\n:) gosh...\r\n\r\ninca unul, de tipul cel mai         heyyyyyyyyyy prost din corcodus, se joaca cu  in nisip.. ura ...\r\ncel mai prost din corcodus a terminat... altcineva?:D\r\ntot el: atentie fratilor ne urmareste big brother 3 (sau 4)\r\n\r\n== code(cpp) |\r\n#include <cstdio> // comment1\r\n// comment2\r\n\r\nint main()\r\n{\r\n    return 0;\r\n}\r\n==\r\n\r\nEu vreau să scriu cu ŢŢŢŢŢ dublu ţ mic şi tripul Ţ mare! Iată un Ţ ţŢŞ ! Are virgulă sau sedilă?',2044,'public',NULL,NULL),('tree-decompositions','Tree decompositions','2008-01-10 13:06:32','2008-12-12 14:01:31','h1. Tree decompositions\r\n\r\n(Categoria _Algoritmi_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Continut:*\r\n* \'{*} Liniarizare\':tree-decompositions#liniarizare\r\n** \'Solutie $O((M+N)*log(N))$\':tree-decompositions#solutie-liniarizare\r\n* \'{*} Descompunere in lanturi\':tree-decompositions#descompunere-in-lanturi\r\n** \'Solutie $O(M*N)$\':tree-decompositions#solutie-descompunere-brute\r\n** \'Solutia $O(M*log(N)*sqrt(N))$\':tree-decompositions#solutie-log-sqrt\r\n** \'Solutie $O(M*log^2^(N))$\':tree-decompositions#solutie-log-log\r\n* \'{*} Aplicatii\':tree-decompositions#aplicatii\r\n* \'{*} Bibliografie\':tree-decompositions#bibliografie\r\n\r\nAcest articol prezinta studiul transformarii unui arbore pentru calcularea eficienta a unei insumari si a valorii maxime/minime aflata pe lantul elementar dintre doua noduri. Mentionez ca, in acest articol, $lant$ va insemna intotdeauna $lant elementar$ (un nod poate aparea cel mult odata).\r\n\r\nh2(#liniarizare). Liniarizare\r\n\r\nUn enunt care apare frecvent la concursurile de informatica este urmatorul:\r\n\r\nFie <tex> G = (V, E) </tex> un graf neorientat conex, <tex> |E| = |V| - 1 </tex> (pe scurt, un arbore). Vom considera ca fiecare nod <tex> x \\in V </tex> are asociata o valoare <tex> value[x] </tex> din multimea numerelor reale. Se dau $M$ instructiuni, $M <= 200000$, de doua tipuri: \r\n\r\n* primul tip cere sa se afiseze suma valorilor tuturor nodurilor ce se afla pe lantul dintre <tex> x, y \\in V </tex> (practic, daca <tex> P = (x_{0}, x_{1}, x_{2}, ..., x_{n}), x_{0} = x, x_{n} = y </tex>, este lantul ce uneste cele doua noduri, atunci se cere <tex> \\Delta = \\displaystyle\\sum_{u \\in P} value[u] </tex>\r\n* al doilea tip modifica valoarea atasata unui nod.\r\n\r\nh3(#solutie-liniarizare). Solutia $O((M+N)*log(N))$\r\n\r\nSolutia se foloseste de o tehnica numita liniarizarea arborelui. Aceasta presupune o parcurgere in adancime si retinerea unor informatii necesare pentru interogare si actualizare: <tex> seq[] </tex>, <tex> firstPos[] </tex>, <tex> lastPos[] </tex>. Iata pseudocodul acestei parcurgeri:\r\n\r\n== code(c) |\r\nPARCURGE(x)\r\n    seq_len ++;\r\n    seq[seq_len] = value[x];\r\n    firstPos[x] = seq_len;\r\n    pentru fiecare fiu y al lui x executa\r\n        PARCURGE(y); // apeleaza recursiv pentru y\r\n    sfarsit pentru\r\n    seq_len ++;\r\n    seq[seq_len] = -value[x];\r\n    lastPos[x] = seq_len;\r\n==\r\n\r\n_Fig. 1: Pentru arborele din figura de mai jos si vectorul de valori_ <tex> value[] = \\{3, 5, 7, 1, 2, 4\\} </tex>, <tex> seq[] </tex> _construit este ilustrat mai jos. Se observa usor ca tot subarborele unui nod se anuleaza cand este explorat in intregime._\r\n\r\np=. !tree-decompositions?fig1.jpg!\r\n\r\nAstfel, s-a construit vectorul <tex> seq[] </tex> care are urmatoarea proprietate: &#34;daca <tex> \\Delta = \\displaystyle\\sum_{i = firstPos[x]}^{firstPos[y]} seq[i] </tex>, <tex> x </tex> fiind un stramos al lui <tex> y </tex>, atunci <tex> \\Delta </tex> reprezinta <tex> \\Delta = \\displaystyle\\sum_{u \\in P} value[u] </tex>, <tex> P = (x_{0}, x_{1}, x_{2}, ..., x_{n}), x_{0} = x, x_{n} = y </tex>&#34;. Conform acesteia, daca vom determina cel mai apropiat stramos comun dintre doua noduri, atunci nu va fi nevoie decat de o structura de date ce permite calcularea intr-un mod eficient a sumei pe un interval din <tex> seq[] </tex> si modificarea unei valori din acest vector. Putem obtine complexitatea $O(log(N))$ pe fiecare din cele doua operatii folosind structura de date numita arbori de intervale. Pentru determinarea eficienta a celui mai apropiat stramos comun si pentru detalii despre arborii de intervale consultati \'bibliografia\':tree-decompositions#bibliografie.\r\n\r\nh2(#descompunere-in-lanturi). Descompunere in lanturi\r\n\r\nAcum ne vom concentra asupra urmatoarei sarcini, de determinare a valorii de maxim/minim. Sa urmarim enuntul de mai jos.\r\n\r\nFie <tex> G = (V, E) </tex> un graf neorientat conex, <tex> |E| = |V| - 1 </tex> (tot un arbore). Vom considera, bineinteles, ca fiecare nod <tex> x \\in V </tex> are asociata o valoare <tex> value[x] </tex> din multimea numerelor reale. Se dau $M$ instructiuni, $M <= 200000$, de doua tipuri:\r\n\r\n* primul tip cere sa se scrie maximul dintre valorile nodurilor ce se afla pe lantul dintre <tex> x, y \\in V </tex> (daca <tex> P = (x_{0}, x_{1}, x_{2}, ..., x_{n}), x_{0} = x, x_{n} = y </tex>,  atunci se cere <tex> \\Delta = \\displaystyle Maxim_{u \\in P} value[u] </tex>)\r\n* al doilea tip modifica valoarea asociata unui nod.\r\n\r\nh3(#solutie-descompunere-brute). Solutia $O(M*N)$\r\n\r\nSunt o multitudine de solutii simple ce ne pot trece prin minte. Pentru cea aleasa de mine voi retine un vector <tex> parent[] </tex> semnificand parintele unui nod calculat printr-un $depth-search$, si un vector <tex> depth[] </tex> ce retine adancimea, adica numarul de muchii de la radacina pana la nodul interogat. Cu ajutorul lor, prima cerinta se rezolva in $O(N)$ astfel: merg \"in sus\" in arbore pana cand ajung in cel mai apropiat stramos comun, retinand pe parcurs valoarea maxima ceruta. Rezolvarea cerintei a doua se face simplu in $O(1)$ modificand direct <tex> value[] </tex>.\r\n\r\nh3(#solutie-log-sqrt). Solutia $O(M*log(N)*sqrt(N))$\r\n\r\nTehnica liniarizarii arborelui nu ne este de folos, deoarece modul de reprezentare a informatiilor nu permite obtinerea unei complexitati mai bune fata de \'solutia lenta\':tree-decompositions##solutie-descompunere-brute prezentata mai sus.\r\n\r\nAceasta solutie foloseste asa numita tehnica $longest path decomposition$, tehnica ce necesita cunostine minime despre grafuri si cu care vom obtine complexitatea $O(M*sqrt(N)*log(N))$ urmand pasii de mai jos:\r\n\r\n# Elimina cel mai lung lant radacina-frunza din arbore si apeleaza recursiv pentru restul componentelor conexe;\r\n# Retine fiecare lant ca un vector <tex> Path[].array[] </tex> cu noduri ordonate crescator dupa adancime si pastreaza un pointer catre nodul din lantul sau parinte <tex> Path[].parent </tex>;\r\n# Pentru fiecare nod retine lantul caruia apartine <tex> whatPath[] </tex> si pozitia in vectorul lantului <tex> whatPos[] </tex>.\r\n\r\nEste evident ca memoria ocupata este $O(N)$, fiecare nod fiind inclus intr-un singur lant. Numarul maxim de lanturi prin care putem trece pornind din radacina pana intr-una din frunze, este $O(sqrt(N))$.\r\n\r\n_Fig. 2: Cazul defavorabil cand sunt $O(sqrt(N))$ lanturi elementare._\r\n\r\n!tree-decompositions?Figura2.jpg!\r\n\r\nFie  <tex> x, y \\in V </tex>, <tex> x </tex> stramos al lui <tex> y </tex>. Functia care determina valoarea maxima pe lantul dintre <tex> x </tex> si <tex> y </tex> este prezentata in urmatorul pseudocod:\r\n\r\n== code(c) |\r\nQUERY(x, y)\r\n    ret = value[x];\r\n    cat timp x diferit de y executa\r\n        daca whatPath[x] = whatPath[y] atunci\r\n            ret = Maxim(ret, QUERYAi(Path[ whatPath[y] ], whatPos[x], whatPos[y]));\r\n            y = x;\r\n        altfel\r\n            ret = Maxim(ret, QUERYAi(Path[ whatPath[y] ], 1, whatPos[y]));\r\n            y = Path[ whatPath[y] ].parent;\r\n        sfarsit daca\r\n    sfarsit cat timp\r\n    returneaza ret;\r\n==\r\nFunctia $QUERYAi(Path[], lo, hi)$ returneaza in $O(log(N))$, cu ajutorul structurii de date arbori de intervale, maximul dintre valorile cuprinse in intervalul $[lo, hi]$. \r\nRaspunsul cerintei de primul tip va fi  {$Maxim(QUERY (lca, x), QUERY (lca, y))$}, variabila <tex> lca </tex> fiind cel mai apropiat stramos comun al lui <tex> x </tex> si <tex> y </tex>. \r\nPentru rezolvarea cerintei de tipul doi, vom folosi aceiasi arbori de intervale care vor obtine un cost de $O(log(N))$ pe operatie. Nu voi prezenta aceasta functie, ea fiind in detaliu prezentata in una din sursele afisate in \'bibliografie\':tree-decompositions#bibliografie.\r\n\r\nComplexitatea finala: $O(M*sqrt(N)*log(N))$. Cel mai rau caz pentru un query este cand se trece prin toate lanturile (in numar de $sqrt(N)$) efectuandu-se cate un query pe fiecare arbore de intervale asociat ({$O(log(N))$}).\r\n\r\nh3(#solutie-log-log). Solutia $O(M*log^2^(N))$\r\n\r\nO imbunatatire la solutia \'precedenta\':tree-decompositions#solutie-log-sqrt o reprezinta $heavy path decomposition$, care se foloseste de acelasi algoritm, cu exceptia faptului ca fiul ales pentru determinarea unui lant este cel cu numar maxim de noduri in subarborele sau (heavy) si nu cel cu inaltimea maxima (longest). Prin urmare, numarul maxim de lanturi prin care se trece pentru a ajunge de la un nod la radacina este cel mult $O(log(N))$ dupa cum se poate vedea si din figura urmatoare:\r\n\r\n_Fig. 3: Fiecare nod apartine unui singur lant. Lanturile sunt reprezentate de muchii solide._\r\n\r\n!tree-decompositions?Figura3.jpg!\r\n\r\nComplexitatea finala: $O(M log^2^(N))$. In practica, aceasta tehnica se comporta foarte bine si poate fi folosita cu succes. Singurul inconvenient este numarul mare de linii de cod scrise.\r\n\r\nh2(#aplicatii). Aplicatii\r\n\r\n* \"Query on a tree\":http://www.spoj.pl/problems/QTREE/\r\n* \"Caves and tunnels\":http://acm.timus.ru/problem.aspx?space=1&num=1553 - Petrozavodsk training camp, September, 2007\r\n* \"Delay\":problema/delay - Lotul national de informatica, 2002\r\n* \"Omizi\":problema/omizi - .campion, 2005\r\n* \"Arbfind\":problema/arbfind - Lotul national de informatica, 2006\r\n* \"CT\":problema/ct - Happy Coding, 2006\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* \"Introducere in algoritmi\", autori Thomas H. Cormen, Charles E. Leiserson, Ronald R. Rivest\r\n* \"Arbori de intervale si aplicatii in geometrie\":arbori-de-intervale, autor Dana Lica\r\n* \"Range Minimum Query and Lowest Common Ancestor\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=lowestCommonAncestor, autor Daniel Pasaila\r\n* \"LCA: Lowest Common Ancestor\":LCA-Lowest-common-ancestor, autor Emilian Miron\r\n* \"The level ancestor problem simplified\":http://cs.sunysb.edu/~bender/pub/latin02-level.ps, autori Michael A. Bender, Martin Farach-Colton\r\n* \"Advanced data structures\":http://courses.csail.mit.edu/6.851/spring07/scribe/lec09.pdf, autor Oren Weimann',2044,'public',NULL,NULL),('newsletter/algoritmiada-2009-1','Incepe Algoritmiada! Acum si pentru studenti','2008-07-02 17:51:25','2008-12-12 16:29:37','Buna, %full_name%!\r\n\r\nA inceput Algoritmiada, cel mai mare si mai important concurs organizat\r\nde infoarena!\r\n\r\nLa Algoritmiada participa elevi de gimnaziu, elevi de liceu, *dar si\r\nstudenti,* si chiar masteranzi sau doctoranzi! (Avem grupe separate\r\npentru fiecare.)\r\n\r\nAlgoritmiada se desfasoara in 4 runde: 3 runde online de calificare, si\r\no runda finala on-site la care invitam concurentii cu cele mai bune\r\npunctaje. Cei mai buni vor castiga premii serioase, in bani si obiecte.\r\n\r\nRunda 1 se desfasoara in acest weekend. Te asteptam in arena! Arata ce\r\nstii la Algoritmiada.\r\n\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Runda 1 se desfasoara\r\n\r\n        Duminica, 14 Decembrie 2008, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\r\nVezi pagina concursului: %url_infoarena%algoritmiada-2009\r\npentru mai multe informatii.\r\n\r\nSucces!\r\n\r\n\r\n== Atentie! Concurs cu rating! ==\r\n\r\nDaca vrei sa ti se modifice rating-ul in urma acestei runde trebuie sa\r\niti anunti participarea din timp. Intra pe\r\n%url_infoarena%algoritmiada-2009/runda-1 si inscrie-te.\r\n\r\nPoti sa participi la concurs chiar si daca nu te-ai inscris in prealabil\r\ninsa nu ti se va modifica rating-ul. %your_rating_is%\r\nCiteste despre rating: %url_infoarena%documentatie/rating.\r\n\r\n\r\n== Despre Algoritmiada ==\r\n\r\nAlgoritmiada este un concurs nou, cu premii, organizat de infoarena.\r\n\r\nAi participat in anii trecuti la preONI? Algoritmiada este continuarea\r\nseriei preONI, un concurs mai mare, mai distractiv, si cu premii mai\r\nfrumoase.\r\n\r\nSubiectele vor fi propuse de catre o echipa de fosti si actuali olimpici\r\nla informatica: Airinei Adrian, Bogdan Tataroiu, Adrian Diaconu, Andrei\r\nGrigorean, Gheorghe Cosmin, Filip Stefan, si Stefan Istrate. De ce ei?\r\nIntra pe pagina rundei (%url_infoarena%algoritmiada-2009/runda-1)\r\nsi poti citi cate ceva despre experienta fiecaruia.\r\n\r\nLa Runda 1 vei avea la dispozitie 4h sa rezolvi 3 probleme de natura\r\nalgoritmica. Concurentii sunt impartiti in 4 grupe de varsta: gimnaziu,\r\nclasele 9-10, clasele 11-12, si studenti (inclusiv masteranzi si\r\ndoctoranzi).\r\n\r\nIntra pe pagina concursului ca sa afli mai multe:\r\n%url_infoarena%algoritmiada-2009\r\n\r\nIti uram succes si te asteptam in arena!\r\n\r\n\r\n== Seria de concursuri preONI s-a incheiat ==\r\n\r\nDupa 5 ani, seria de concursuri preONI se retrage. Cel mai longeviv\r\nconcurs infoarena, cel mai amplu eveniment organizat de noi pana acum,\r\ncu o traditie lunga si cu mii de participanti, se incheie.\r\n\r\nDe anul acesta incepe Algoritmiada. Vom incerca sa aplicam lectiile\r\ninvatate pana acum, insa avem nevoie de ajutorul tau. Fii alaturi de\r\nnoi, contacteaza-ne pe forum, ajuta-ne sa facem din Algoritmiada o\r\ncompetitie la care ti-ar placea sa participi oricand.\r\n\r\nAi participat vreodata la preONI? Iti mai aduce aminte ce fel a fost, ce\r\nprobleme ai primit? Ti-am facut poze la finala? Viziteaza inca odata\r\npaginile editiilor anterioare:\r\n\r\n    *   preONI 2008, finala la Univ. Politehnica, Bucuresti\r\n        %url_infoarena%preoni-2008\r\n\r\n    *   preONI 2007, finala la Lic. Int. de Informatica, Bucuresti\r\n        %url_infoarena%preoni-2007\r\n\r\n    *   preONI 2006, finala la C. N. \"Unirea\", Focsani\r\n        %url_infoarena%preoni-2006\r\n\r\n    *   preONI 2005, finala online\r\n        %url_infoarena%preoni-2005\r\n\r\n    *   preONI 2004, finala online\r\n        %url_infoarena%preoni-2004\r\n\r\n\r\n== Blogul infoarena ==\r\n\r\nAfla de ce concursurile la care participi acum iti vor fi de folos in\r\nviitor, ce fac fostii olimpici ai Romaniei, cum e sa lucrezi la Google,\r\nMicrosoft, si altele. Cosmin Negruseri, gazda blogului, si invitatii lui\r\nte asteapta cu ganduri si insemnari din experienta lor.\r\n\r\nIata trei dintre insemnarile recente. Ia-ti o pauza bine meritata si\r\nciteste-le. Asteptam comentariile tale.\r\n\r\n    *   DEX online sub capota\r\n        %url_infoarena%blog/dexonline\r\n\r\n    *   De ce Python?\r\n        %url_infoarena%blog/de-ce-python\r\n\r\n    *   De ce este bun un curs de compilatoare si cunoasterea pe net\r\n        %url_infoarena%blog/cunoasterea-pe-net\r\n\r\nBlog-ul infoarena poate fi urmarit si prin RSS! Adresa\r\nfeed-ului este: %url_infoarena%blog?action=rss\r\n\r\n\r\n== Prima data la infoarena? ==\r\n\r\nDespre infoarena: %url_infoarena%despre-infoarena\r\nTutorial infoarena: %url_infoarena%documentatie/tutorial\r\n\r\n\r\n== Fii un bun infoarenaut! Implica-te! ==\r\n\r\nMai mult ca oricand, infoarena are nevoie de ajutorul tau! infoarena\r\neste un efort colectiv, munca a zeci de voluntari pe parcursul a 5 ani\r\nde zile.  Vrem sa-i sprijinim pe toti cei care, pasionati de informatica\r\nsi programare, vor sa invete mai mult, vor sa isi perfectioneze\r\nabilitatile.\r\n\r\nVrei sa compui problemele tale? Vrei sa organizezi concursuri? Iti place\r\nsa programezi, doresti sa inveti cum se dezvolta un site precum\r\ninfoarena?  Vrei sa redactezi articole despre algoritmi si structuri de\r\ndate? Pentru toate acestea, si pentru multe altele, infoarena are nevoie\r\nde ajutorul tau!\r\n\r\nAfla cum te poti implica in comunitatea infoarena:\r\n%url_infoarena%implica-te\r\n\r\n\r\n== Mesaj nesolicitat? ==\r\n\r\nEsti inscris pe %url_infoarena% cu numele\r\n\"%full_name%\", utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\r\nDaca nu mai doresti instiintari, da click pe acest link:\r\n%url_unsubscribe%\r\n\r\n',13,'protected',NULL,NULL),('tree-decompositions','Tree decompositions','2008-01-10 13:06:32','2008-12-12 15:19:34','h1. Tree decompositions\r\n\r\n(Categoria _Algoritmi_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Continut:*\r\n* \'Liniarizare\':tree-decompositions#liniarizare\r\n** \'{*} Solutie $O((M+N)*log(N))$\':tree-decompositions#solutie-liniarizare\r\n* \'Descompunere in lanturi\':tree-decompositions#descompunere-in-lanturi\r\n** \'{*} Solutie $O(M*N)$\':tree-decompositions#solutie-brute\r\n** \'{*} Solutie $O(M*log(N)*sqrt(N))$\':tree-decompositions#solutie-log-sqrt\r\n** \'{*} Solutie $O(M*log^2^(N))$\':tree-decompositions#solutie-log-log\r\n* \'Aplicatii\':tree-decompositions#aplicatii\r\n* \'Bibliografie\':tree-decompositions#bibliografie\r\n\r\nAcest articol prezinta studiul transformarii unui arbore pentru calcularea eficienta a unei insumari si a valorii maxime / minime aflate pe lantul elementar dintre doua noduri. Mentionez ca, in acest articol, $lant$ va insemna intotdeauna $lant elementar$ (un nod poate aparea cel mult o data).\r\n\r\nh2(#liniarizare). Liniarizare\r\n\r\nUn enunt care apare frecvent la concursurile de informatica este urmatorul:\r\n\r\nFie <tex> G = (V, E) </tex> un graf neorientat conex, <tex> |E| = |V| - 1 </tex> (pe scurt, un arbore). Vom considera ca fiecare nod <tex> x \\in V </tex> are asociata o valoare <tex> value[x] </tex> din multimea numerelor reale. Se dau $M$ instructiuni, $M &le; 200000$, de doua tipuri: \r\n\r\n* primul tip cere sa se afiseze suma valorilor tuturor nodurilor ce se afla pe lantul dintre <tex> x, y \\in V </tex> (practic, daca <tex> P = (x_{0}, x_{1}, x_{2}, ..., x_{n}), x_{0} = x, x_{n} = y </tex>, este lantul ce uneste cele doua noduri, atunci se cere <tex> \\Delta = \\displaystyle\\sum_{u \\in P} value[u] </tex>\r\n* al doilea tip modifica valoarea atasata unui nod.\r\n\r\nh3(#solutie-liniarizare). Solutie $O((M+N)*log(N))$\r\n\r\nSolutia se foloseste de o tehnica numita liniarizarea arborelui. Aceasta presupune o parcurgere in adancime si retinerea unor informatii necesare pentru interogare si actualizare: <tex> seq[] </tex>, <tex> firstPos[] </tex>, <tex> lastPos[] </tex>. Iata pseudocodul acestei parcurgeri:\r\n\r\n== code(c) |\r\nPARCURGE(x)\r\n    seq_len ++;\r\n    seq[seq_len] = value[x];\r\n    firstPos[x] = seq_len;\r\n    pentru fiecare fiu y al lui x executa\r\n        PARCURGE(y); // apeleaza recursiv pentru y\r\n    sfarsit pentru\r\n    seq_len ++;\r\n    seq[seq_len] = -value[x];\r\n    lastPos[x] = seq_len;\r\n==\r\n\r\n_Fig. 1: Pentru arborele din figura de mai jos si vectorul de valori_ <tex> value[] = \\{3, 5, 7, 1, 2, 4\\} </tex>, <tex> seq[] </tex> _construit este ilustrat mai jos. Se observa usor ca tot subarborele unui nod se anuleaza cand este explorat in intregime._\r\n\r\np=. !tree-decompositions?fig1.jpg!\r\n\r\nAstfel, s-a construit vectorul <tex> seq[] </tex> care are urmatoarea proprietate: &#34;daca <tex> \\Delta = \\displaystyle\\sum_{i = firstPos[x]}^{firstPos[y]} seq[i] </tex>, <tex> x </tex> fiind un stramos al lui <tex> y </tex>, atunci <tex> \\Delta </tex> reprezinta <tex> \\Delta = \\displaystyle\\sum_{u \\in P} value[u] </tex>, <tex> P = (x_{0}, x_{1}, x_{2}, ..., x_{n}), x_{0} = x, x_{n} = y </tex>&#34;. Conform acesteia, daca vom determina cel mai apropiat stramos comun dintre doua noduri, atunci nu va fi nevoie decat de o structura de date ce permite calcularea intr-un mod eficient a sumei pe un interval din <tex> seq[] </tex> si modificarea unei valori din acest vector. Putem obtine complexitatea $O(log(N))$ pe fiecare din cele doua operatii folosind structura de date numita arbori de intervale. Pentru determinarea eficienta a celui mai apropiat stramos comun si pentru detalii despre arborii de intervale consultati \'bibliografia\':tree-decompositions#bibliografie.\r\n\r\nh2(#descompunere-in-lanturi). Descompunere in lanturi\r\n\r\nAcum ne vom concentra asupra urmatoarei sarcini, de determinare a valorii de maxim/minim. Sa urmarim enuntul de mai jos.\r\n\r\nFie <tex> G = (V, E) </tex> un graf neorientat conex, <tex> |E| = |V| - 1 </tex> (tot un arbore). Vom considera, bineinteles, ca fiecare nod <tex> x \\in V </tex> are asociata o valoare <tex> value[x] </tex> din multimea numerelor reale. Se dau $M$ instructiuni, $M &le; 200000$, de doua tipuri:\r\n\r\n* primul tip cere sa se scrie maximul dintre valorile nodurilor ce se afla pe lantul dintre <tex> x, y \\in V </tex> (daca <tex> P = (x_{0}, x_{1}, x_{2}, ..., x_{n}), x_{0} = x, x_{n} = y </tex>,  atunci se cere <tex> \\Delta = \\displaystyle Maxim_{u \\in P} value[u] </tex>)\r\n* al doilea tip modifica valoarea asociata unui nod.\r\n\r\nh3(#solutie-brute). Solutie $O(M*N)$\r\n\r\nSunt o multitudine de solutii simple ce ne pot trece prin minte. Pentru cea aleasa de mine voi retine un vector <tex> parent[] </tex> semnificand parintele unui nod calculat printr-un $depth-search$, si un vector <tex> depth[] </tex> ce retine adancimea, adica numarul de muchii de la radacina pana la nodul interogat. Cu ajutorul lor, prima cerinta se rezolva in $O(N)$ astfel: merg \"in sus\" in arbore pana cand ajung in cel mai apropiat stramos comun, retinand pe parcurs valoarea maxima ceruta. Rezolvarea cerintei a doua se face simplu in $O(1)$ modificand direct <tex> value[] </tex>.\r\n\r\nh3(#solutie-log-sqrt). Solutie $O(M*log(N)*sqrt(N))$\r\n\r\nTehnica liniarizarii arborelui nu ne este de folos, deoarece modul de reprezentare a informatiilor nu permite obtinerea unei complexitati mai bune fata de \'solutia lenta\':tree-decompositions##solutie-descompunere-brute prezentata mai sus.\r\n\r\nAceasta solutie foloseste asa numita tehnica $longest path decomposition$, tehnica ce necesita cunostine minime despre grafuri si cu care vom obtine complexitatea $O(M*sqrt(N)*log(N))$ urmand pasii de mai jos:\r\n\r\n# Elimina cel mai lung lant radacina-frunza din arbore si apeleaza recursiv pentru restul componentelor conexe;\r\n# Retine fiecare lant ca un vector <tex> Path[].array[] </tex> cu noduri ordonate crescator dupa adancime si pastreaza un pointer catre nodul din lantul sau parinte <tex> Path[].parent </tex>;\r\n# Pentru fiecare nod retine lantul caruia apartine <tex> whatPath[] </tex> si pozitia in vectorul lantului <tex> whatPos[] </tex>.\r\n\r\nEste evident ca memoria ocupata este $O(N)$, fiecare nod fiind inclus intr-un singur lant. Numarul maxim de lanturi prin care putem trece pornind din radacina pana intr-una din frunze, este $O(sqrt(N))$.\r\n\r\n_Fig. 2: Cazul defavorabil cand sunt $O(sqrt(N))$ lanturi elementare._\r\n\r\n!tree-decompositions?Figura2.jpg!\r\n\r\nFie  <tex> x, y \\in V </tex>, <tex> x </tex> stramos al lui <tex> y </tex>. Functia care determina valoarea maxima pe lantul dintre <tex> x </tex> si <tex> y </tex> este prezentata in urmatorul pseudocod:\r\n\r\n== code(c) |\r\nQUERY(x, y)\r\n    ret = value[x];\r\n    cat timp x diferit de y executa\r\n        daca whatPath[x] = whatPath[y] atunci\r\n            ret = Maxim(ret, QUERYAi(Path[ whatPath[y] ], whatPos[x], whatPos[y]));\r\n            y = x;\r\n        altfel\r\n            ret = Maxim(ret, QUERYAi(Path[ whatPath[y] ], 1, whatPos[y]));\r\n            y = Path[ whatPath[y] ].parent;\r\n        sfarsit daca\r\n    sfarsit cat timp\r\n    returneaza ret;\r\n==\r\nFunctia $QUERYAi(Path[], lo, hi)$ returneaza in $O(log(N))$, cu ajutorul structurii de date arbori de intervale, maximul dintre valorile cuprinse in intervalul $[lo, hi]$. \r\nRaspunsul cerintei de primul tip va fi  {$Maxim(QUERY (lca, x), QUERY (lca, y))$}, variabila <tex> lca </tex> fiind cel mai apropiat stramos comun al lui <tex> x </tex> si <tex> y </tex>. \r\nPentru rezolvarea cerintei de tipul doi, vom folosi aceiasi arbori de intervale care vor obtine un cost de $O(log(N))$ pe operatie. Nu voi prezenta aceasta functie, ea fiind in detaliu prezentata in una din sursele afisate in \'bibliografie\':tree-decompositions#bibliografie.\r\n\r\nComplexitatea finala: $O(M*sqrt(N)*log(N))$. Cel mai rau caz pentru un query este cand se trece prin toate lanturile (in numar de $sqrt(N)$) efectuandu-se cate un query pe fiecare arbore de intervale asociat ({$O(log(N))$}).\r\n\r\nh3(#solutie-log-log). Solutie $O(M*log^2^(N))$\r\n\r\nO imbunatatire la solutia \'precedenta\':tree-decompositions#solutie-log-sqrt o reprezinta $heavy path decomposition$, care se foloseste de acelasi algoritm, cu exceptia faptului ca fiul ales pentru determinarea unui lant este cel cu numar maxim de noduri in subarborele sau (heavy) si nu cel cu inaltimea maxima (longest). Prin urmare, numarul maxim de lanturi prin care se trece pentru a ajunge de la un nod la radacina este cel mult $O(log(N))$ dupa cum se poate vedea si din figura urmatoare:\r\n\r\n_Fig. 3: Fiecare nod apartine unui singur lant. Lanturile sunt reprezentate de muchii solide._\r\n\r\n!tree-decompositions?Figura3.jpg!\r\n\r\nComplexitatea finala: $O(M log^2^(N))$. In practica, aceasta tehnica se comporta foarte bine si poate fi folosita cu succes. Singurul inconvenient este numarul mare de linii de cod scrise.\r\n\r\nh2(#aplicatii). Aplicatii\r\n\r\n* \"Query on a tree\":http://www.spoj.pl/problems/QTREE/\r\n* \"Caves and tunnels\":http://acm.timus.ru/problem.aspx?space=1&num=1553 - Petrozavodsk training camp, September, 2007\r\n* \"Delay\":problema/delay - Lotul national de informatica, 2002\r\n* \"Omizi\":problema/omizi - .campion, 2005\r\n* \"Arbfind\":problema/arbfind - Lotul national de informatica, 2006\r\n* \"CT\":problema/ct - Happy Coding, 2006\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* Thomas H. Cormen, Charles E. Leiserson, Ronald R. Rivest - _\"Introducere in Algoritmi\"_\r\n* Dana Lica - \"_Arbori de intervale si aplicatii in geometria computationala_\":arbori-de-intervale\r\n* Daniel Pasaila - \"_Range Minimum Query and Lowest Common Ancestor_\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=lowestCommonAncestor\r\n* Emilian Miron - \"_Lowest Common Ancestor_\":lowest-common-ancestor\r\n* Michael A. Bender, Martin Farach-Colton - \"_The level ancestor problem simplified_\":http://cs.sunysb.edu/~bender/pub/latin02-level.ps\r\n* Oren Weimann - \"_Advanced data structures_\":http://courses.csail.mit.edu/6.851/spring07/scribe/lec09.pdf',2044,'public',NULL,NULL),('newsletter/algoritmiada-2009-1','Incepe Algoritmiada! Acum si pentru studenti','2008-07-02 17:51:25','2008-12-12 16:37:51','Buna, %full_name%!\r\n\r\nIncepe Algoritmiada, cel mai mare si mai important concurs\r\norganizat de infoarena!\r\n\r\nLa Algoritmiada participa elevi de gimnaziu, elevi de liceu, *dar si\r\nstudenti,* si chiar masteranzi sau doctoranzi! (Avem grupe separate\r\npentru fiecare.)\r\n\r\nAlgoritmiada se desfasoara in 4 runde: 3 runde online de calificare,\r\nsi o runda finala on-site la care invitam concurentii cu cele mai\r\nbune punctaje. Cei mai buni vor castiga premii serioase, in bani si\r\nobiecte.\r\n\r\nRunda 1 se desfasoara in acest weekend. Te asteptam in arena! Arata\r\nce stii la Algoritmiada.\r\n\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Runda 1 se desfasoara\r\n\r\n        Duminica, 14 Decembrie 2008, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\r\nVezi pagina concursului: %url_infoarena%algoritmiada-2009\r\npentru mai multe informatii.\r\n\r\nSucces!\r\n\r\n\r\n== Atentie! Concurs cu rating! ==\r\n\r\nDaca vrei sa ti se modifice rating-ul in urma acestei runde trebuie\r\nsa iti anunti participarea din timp. Intra pe\r\n%url_infoarena%algoritmiada-2009/runda-1 si inscrie-te.\r\n\r\nPoti sa participi la concurs chiar si daca nu te-ai inscris in\r\nprealabil insa nu ti se va modifica rating-ul. %your_rating_is%\r\nCiteste despre rating: %url_infoarena%documentatie/rating.\r\n\r\n\r\n== Despre Algoritmiada ==\r\n\r\nAlgoritmiada este un concurs nou, cu premii, organizat de infoarena.\r\n\r\nAi participat in anii trecuti la preONI? Algoritmiada este\r\ncontinuarea seriei preONI, un concurs mai mare, mai distractiv, si cu\r\npremii mai frumoase.\r\n\r\nSubiectele vor fi propuse de catre o echipa de fosti si actuali\r\nolimpici la informatica: Airinei Adrian, Bogdan Tataroiu, Adrian\r\nDiaconu, Andrei Grigorean, Gheorghe Cosmin, Filip Stefan, si Stefan\r\nIstrate. De ce ei? Intra pe pagina rundei si citeste cate ceva despre\r\nexperienta fiecaruia: %url_infoarena%algoritmiada-2009/runda-1\r\n\r\nLa Runda 1 vei avea la dispozitie 4h sa rezolvi 3 probleme de natura\r\nalgoritmica. Concurentii sunt impartiti in 4 grupe de varsta:\r\ngimnaziu, clasele 9-10, clasele 11-12, si studenti (inclusiv\r\nmasteranzi si doctoranzi).\r\n\r\nIntra pe pagina concursului ca sa afli mai multe:\r\n%url_infoarena%algoritmiada-2009\r\n\r\nIti uram succes si te asteptam in arena!\r\n\r\n\r\n== Seria de concursuri preONI s-a incheiat ==\r\n\r\nDupa 5 ani, seria de concursuri preONI se retrage. Cel mai longeviv\r\nconcurs infoarena, cel mai amplu eveniment organizat de noi pana\r\nacum, cu o traditie lunga si cu mii de participanti, se incheie.\r\n\r\nDe anul acesta incepe Algoritmiada. Vom incerca sa aplicam lectiile\r\ninvatate pana acum, insa avem nevoie de ajutorul tau. Fii alaturi de\r\nnoi, contacteaza-ne pe forum, ajuta-ne sa facem din Algoritmiada o\r\ncompetitie la care ti-ar placea sa participi oricand.\r\n\r\nAi participat vreodata la preONI? Iti mai aduce aminte ce fel a fost,\r\nce probleme ai primit? Ti-am facut poze la finala? Viziteaza inca\r\nodata paginile editiilor anterioare:\r\n\r\n    *   preONI 2008, finala la Univ. Politehnica, Bucuresti\r\n        %url_infoarena%preoni-2008\r\n\r\n    *   preONI 2007, finala la Lic. Int. de Informatica, Bucuresti\r\n        %url_infoarena%preoni-2007\r\n\r\n    *   preONI 2006, finala la C. N. \"Unirea\", Focsani\r\n        %url_infoarena%preoni-2006\r\n\r\n    *   preONI 2005, finala online\r\n        %url_infoarena%preoni-2005\r\n\r\n    *   preONI 2004, finala online\r\n        %url_infoarena%preoni-2004\r\n\r\n\r\n== Blogul infoarena ==\r\n\r\nAfla de ce concursurile la care participi acum iti vor fi de folos in\r\nviitor, ce fac fostii olimpici ai Romaniei, cum e sa lucrezi la\r\nGoogle, Microsoft, si altele. Cosmin Negruseri, gazda blogului, si\r\ninvitatii lui te asteapta cu ganduri si insemnari din experienta lor.\r\n\r\nIata trei dintre insemnarile recente. Ia-ti o pauza bine meritata si\r\nciteste-le. Asteptam comentariile tale.\r\n\r\n    *   DEX online sub capota\r\n        %url_infoarena%blog/dexonline\r\n\r\n    *   De ce Python?\r\n        %url_infoarena%blog/de-ce-python\r\n\r\n    *   De ce este bun un curs de compilatoare si cunoasterea pe net\r\n        %url_infoarena%blog/cunoasterea-pe-net\r\n\r\nBlog-ul infoarena poate fi urmarit si prin RSS! Adresa\r\nfeed-ului este: %url_infoarena%blog?action=rss\r\n\r\n\r\n== Prima data la infoarena? ==\r\n\r\n\r\nDespre infoarena: %url_infoarena%despre-infoarena\r\nTutorial infoarena: %url_infoarena%documentatie/tutorial\r\n\r\n\r\n== Fii un bun infoarenaut! Implica-te! ==\r\n\r\nMai mult ca oricand, infoarena are nevoie de ajutorul tau! infoarena\r\neste un efort colectiv, munca a zeci de voluntari pe parcursul a 5\r\nani de zile.  Vrem sa-i sprijinim pe toti cei care, pasionati de\r\ninformatica si programare, vor sa invete mai mult, vor sa isi\r\nperfectioneze abilitatile.\r\n\r\nVrei sa compui problemele tale? Vrei sa organizezi concursuri? Iti\r\nplace sa programezi, doresti sa inveti cum se dezvolta un site precum\r\ninfoarena?  Vrei sa redactezi articole despre algoritmi si structuri\r\nde date? Pentru toate acestea, si pentru multe altele, infoarena are\r\nnevoie de ajutorul tau!\r\n\r\nAfla cum te poti implica in comunitatea infoarena:\r\n%url_infoarena%implica-te\r\n\r\n\r\n== Mesaj nesolicitat? ==\r\n\r\nEsti inscris pe %url_infoarena% cu numele\r\n\"%full_name%\", utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\r\nDaca nu mai doresti instiintari, da click pe acest link:\r\n%url_unsubscribe%\r\n\r\n',13,'protected',NULL,NULL),('propuneri/11-rating','IAP #11: Revizuirea functionalitatii ratingului','2008-12-09 22:34:33','2008-12-12 20:18:59','h1. IAP #11: Revizuirea functionalitatii ratingului\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2008-12-10 |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"bogdan2412\")== |\r\n|_. Stare     | *IN CONSTRUCTIE* |\r\n\r\nh2(#abstract). Abstract\r\n\r\nSe propune revizuirea sistemului de inregistrare si de calculare a ratingului. Acest IAP nu isi propune sa redreseze problemele existente la nivel de algoritm de calculare a ratingului (ratingul actual nu respecta curba lui Gauss), ci problemele cauzate de faptul ca doar o parte din utilizatorii participanti la un concurs conteaza in calcularea ratingului.\r\n\r\nh2(#motivatie). Motivatie\r\n\r\nConform \'documentatiei\':documentatie/rating, ratingul reprezinta un mod de a masura performantele unui concurent in regim de concurs in raport cu ceilalti concurenti. Sistemul actual de inregistrare / rating permite utiliatorilor sa participe la un concurs fara ca ratingul lor sa fie afectat, fapt ce scade din relevanta ratingului din mai multe motive:\r\n\r\n* In primul rand, pe plan individual, unii concurenti putand fi tentati sa se inregistreze doar la concursurile la care sunt siguri ca vor face bine (elevi de clasele 11-12 care participa la concursuri de gen Junior Challenge), dar nu la concursurile corespunzatoare varstei lor.\r\n* In al doilea rand, pe plan global, datorita faptului ca ratingul pentru un concurent este calculat in functie de rezultatele concurentilor *inregistrati* raportat la rezultatul lui, nu in functie de rezultatele tuturor concurentilor.\r\n\r\nh2(#implementare). Implementare\r\n\r\nIn cadrul \'sedintei din 25 noiembrie 2008\':planificare/sedinta-20081125 au fost propuse doua alternative, fiecare cu avataje si dezavantaje.\r\n\r\nh3(#propunere1). Propunerea 1\r\n\r\nUtilizatorii sunt obligati sa se inregistreze la un concurs pentru a putea submita solutii. Ei vor putea in continuare sa citeasca problemele, dar vor trebui sa astepte pana cand concursul s-a incheiat pentru a putea trimite solutii. Alternativ, se poate implementa posibilitatea trimiterii solutiilor si de catre utilizatorii neinregistrati, dar acestia sa nu apara in clasament.\r\n\r\nh4. Avantaje\r\n\r\n* Cea mai mare relevanta a sistemului de rating\r\n\r\nh4. Dezavantaje\r\n\r\n* Unii concurenti uita sa se inregistreze (pentru concursuri gen Algoritmiada asta poate fi o problema destul de serioasa). Pana acum, insa, rundele au fost anuntate cu mult timp inainte (1-2 saptamani), deci utilizatorii ar trebui sa aiba destul timp.\r\n\r\nh3(#propunere2). Propunerea 2\r\n\r\nEliminam facilitatea de inscriere. In schimb, cand un utilizator trimite o sursa, acesta este automat considerat participant la concurs si ratingul lui va fi modificat la sfarsit.\r\n\r\nh4. Avantaje\r\n\r\n* Utilizatorii nu mai pot sa uite sa se inregistreze.\r\n* Utilizatorilor carora le pica netul si nu apuca nici sa citeasca problemele, dar care s-au inregistrat cu o zi inainte, nu le mai este modificat ratingul.\r\n\r\nh4. Dezavantaje\r\n\r\n* Concurentii care participa la concurs dar nu reusesc sa rezolve nici o problema nu sunt luati in calcul pentru rating, desi acestia au citit problemele si ar trebui sa fie.\r\n* Pentru concursuri lungi de genul Happy Coding, All you can code, utilizatorii (in special studenti, fosti olimpici) nu vor mai putea trimite solutii doar la problemele grele sau care li se par mai interesante fara sa fie considerati ca participanti.\r\n\r\nh3(#propunere3). Propunerea 3\r\n\r\nEliminam toate functionalitatea de rating / inregistrare pentru ca ne creaza prea multe probleme. :)\r\n\r\nh2(#feedback). Feedback\r\n\r\nIntra pe \'forum\':forum/index.php?topic= pentru a da feedback.',2028,'public',NULL,NULL),('treapuri','Treapuri','2008-01-21 16:18:25','2008-12-12 22:55:04','h1. Treapuri\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'{*} Introducere\':treapuri#introducere\r\n* \'{*} Avantaje\':treapuri#avantaje\r\n* \'{*} Operaţii\':treapuri#operatii\r\n** \'- Căutare\':treapuri#cautare\r\n** \'- Rotaţii\':treapuri#rotatii\r\n** \'- Inserare\':treapuri#inserare\r\n** \'- Ştergere\':treapuri#stergere\r\n** \'- Split\':treapuri#split\r\n** \'- Join\':treapuri#join\r\n** \'- Alte operaţii\':treapuri#alte-operatii\r\n* \'{*} Concluzii\':treapuri#concluzii\r\n* \'{*} Aplicaţii\':treapuri#aplicatii\r\n* \'{*} Bibliografie\':treapuri#bibliografie\r\n\r\n\r\nÎn acest articol voi prezenta o alternativă pentru arborii binari de căutare echilibraţi, precum $AVL$, $Red-Black Trees$, $Splay Trees$ şi $B-Trees$.\r\n\r\nh2(#introducere). Introducere\r\n\r\nTreapul este un arbore binar în care fiecare nod conţine două informaţii:\r\n\r\n* $cheie$\r\n\r\n* $prioritate$\r\n\r\nStructura de date respectă doi invarianţi:\r\n\r\n* $dacă parcurgem arborele în inordine, atunci vom obţine nodurile sortate (invariantul arborilor de căutare)$\r\n\r\n* $prioritatea fiecărui nod este mai mare decât cea a fiilor săi (invariantul heapurilor)$\r\n\r\nÎn consecinţă, treapul este un arbore binar de căutare pentru chei şi un max-heap pentru priorităţi.\r\n\r\nÎn continuare, vom presupune că oricare două chei din treapul $T$ sunt distincte. Cazul când avem nevoie de chei egale se va trata relativ uşor după ce acest articol va fi înţeles.\r\n\r\nAstfel, din moment ce $T$ este un heap, nodul $v$ cu prioritatea cea mai mare trebuie să fie rădăcina. Întrucât este şi un arbore binar de căutare, orice nod $u$ cu $cheie(u) < cheie(v)$ se găseşte în subarborele stâng al lui $v$, şi orice nod $w$ cu $cheie(w) > cheie(v)$ se găseşte în subarborele drept.\r\n\r\nCheile şi priorităţile asociate lor, in condiţiile în care ambele sunt distincte, determină în mod unic forma unui treap. Prin inducţie se demonstrează că treapul este arborele binar obţinut prin inserarea cheilor în ordinea descrescătoare a priorităţilor. Algoritmul de inserare este cel obişnuit pentru arborii de căutare. Astfel, cum fiecare set de priorităţi asociat nodurilor va aranja arborele într-un singur mod, probabilitatea ca arborele să fie echilibrat este rezonabil de mare, fapt datorat numărului mic al arborilor rău echilibraţi în comparaţie cu cei echilibraţi. Iată şi secretul acestei structuri de date: probabilitatea infimă de a se găsi o serie de priorităţi generate aleator care să nu menţină arborele echilibrat.\r\n\r\nh2(#avantaje). Avantaje\r\n\r\nStructurile de date de heap şi de arbori binari de căutare sunt uşor de implementat şi de înţeles, iar treapurile sunt o combinaţie a acestor două concepte. Astfel, este suficient să fie înţeleşi cei doi invarianţi, după care implementarea se poate face cu uşurinţă în 20 de minute, fără antrenament. De obicei, la structuri ca $Arborii Roşu-Negru$ trebuie folosite serii de rotaţii stânga şi dreapta complexe şi analizată o multitudine de cazuri, pe când la treapuri facem doar câte o rotaţie stânga sau dreapta la fiecare pas al algoritmului. Ei nu sunt predaţi pentru că se preferă ca exemple didactice $Arborii Roşu-Negru$ sau cei $AVL$ care au o demonstraţie accesibilă că limita celei mai lente operaţii este $O(log N)$. Dar treapurile, deşi cu o demonstraţie mai grea pentru limita de $O(log N)$, ce implică probabilităţi, sunt mult mai uşor de implementat, iar în practică, cu siguranţă este greu de decis care sunt mai rapizi. Sunt, deci, o opţiune demnă de luat în seamă. Pe de altă parte, treapurile suportă şi alte două operaţii pe care nu le putem face cu $Arborii Roşu-Negru$ sau cu arborii $AVL$. Aceste operaţii sunt \'$join$\':treapuri#join şi \'$split$\':treapuri#split.\r\n\r\nh2(#operatii). Operaţii\r\n\r\nCostul operaţiilor de mai jos este proporţional cu adâncimea unui nod din treap. După cum am menţionat mai sus, cu ajutorul teoriei probabilităţilor se poate deduce că adâncimea medie aşteptată a oricărui nod este $O(log N)$, ceea ce implică costul celor mai lente operaţii să fie, în medie, $O(log N)$.\r\n\r\nMai jos avem definiţia în cod $C++$ a unui treap şi o funcţie de iniţializare, care marchează că treapul cu rădăcina $R$ este gol.\r\n\r\n== code(cpp) |\r\nstruct T {\r\n    int key;\r\n    int priority;\r\n    T *left, *right;\r\n    T() {}\r\n    T(int key, int priority, T* left, T* right) {\r\n        this->key = key, this->priority = priority;\r\n        this->left = left, this->right = right;\r\n    }\r\n} *R, *nil; // nil indică un nod \'gol\'\r\n\r\nvoid init(T* &R) {\r\n    srand(unsigned(time(0)));\r\n    R = nil = new T(0, 0, NULL, NULL);\r\n}\r\n==\r\n\r\nh3(#cautare). Căutare\r\n\r\nCăutarea într-un treap este identică cu cea într-un arbore binar de căutare. Pentru a verifica dacă o cheie există putem proceda în felul următor:\r\n\r\n== code(cpp) |\r\nint search(T* n, int key) {\r\n    if (n == nil) return 0;\r\n    if (key == n->key) return 1;\r\n    if (key < n->key)\r\n        return search(n->left, key);\r\n    else\r\n        return search(n->right, key);\r\n}\r\n==\r\n\r\nh3(#rotatii). Rotaţii\r\n\r\nRotaţiile sunt cărămizile de la baza structurii de treap.\r\n\r\np=. !treapuri?Fig1.png!\r\n\r\np=. _*Descriere:* Rotaţiile într-un arbore binar de căutare. Nodurile sunt reprezentate de cercuri, iar subarborii de triunghiuri. Ambele operaţii de rotaţie menţin invariantul arborilor de căutare._\r\n\r\nSă urmărim efectul rotaţiilor asupra structurii de heap a unui treap care respectă doar invariantul arborilor de căutare. Aşadar, să presupunem că arborele din figura din stânga are o structură de heap cu excepţia lui $w$ care are o prioritate mai mare decât a lui $z$. Dacă îl rotim pe $w$ spre dreapta vedem în figura a doua că structura de heap este satisfăcută. Din moment ce $A$ era un subarbore valid al lui $w$, va rămâne în continuare un subarbore valid. Cum $B$ şi $C$ se aflau iniţial sub $z$, ei aveau o prioritate mai mică decât a lui $z$, şi, astfel, după rotaţie ei sunt subarbori valizi pentru $z$. Este clar că $z$ este un fiu valid al lui $w$, prin presupunerea făcută iniţial. \r\n\r\nSă urmărim dacă invariantul arborilor de căutare se menţine în urma unei astfel de rotaţii.\r\n\r\n* În arborele din figura din stânga avem inegalităţile următoare: $A < w < B; z < C; w, A, B < z$. Din acestea se obţine: $A < w < B < z < C$.\r\n* În arborele din figura din dreapta avem inegalităţile următoare: $A < w; B < z < C; w < z, B, C$. Din acestea se obţine: $A < w < B < z < C$.\r\n\r\nÎntrucât am obţinut acelaşi şir de inegalităţi, am arătat existenţa invariantului arborilor de căutare.\r\n\r\nReţineţi că această rotaţie împreună cu imaginea sa în oglindă stau la baza algoritmilor de \'$inserare$\':treapuri#inserare şi \'$ştergere$\':treapuri#stergere!\r\n\r\nPentru o rotaţie este necesar un număr constant de operaţii cu pointeri.\r\n\r\n== code(cpp) |\r\nvoid rotleft(T* &n) {\r\n    T *t = n->left;\r\n    n->left = t->right, t->right = n;\r\n    n = t;\r\n}\r\n\r\nvoid rotright(T* &n) {\r\n    T *t = n->right;\r\n    n->right = t->left, t->left = n;\r\n    n = t;\r\n}\r\n\r\nvoid balance(T* &n) {\r\n    if (n->left->priority > n->priority)\r\n        rotleft(n);\r\n    else if (n->right->priority > n->priority)\r\n        rotright(n);\r\n}\r\n==\r\n\r\nComplexitate: $O(1)$.\r\n\r\nh3(#inserare). Inserare\r\n\r\nÎn cadrul operaţiei de inserare vom atribui unui nod nou o prioritate aleatoare şi îl vom insera, conform algoritmului standard de inserare într-un arbore binar, la baza arborelui. Să presupunem că dorim să inserăm nodul $z$ cu cheia $9$ şi prioritatea $51$.\r\n\r\np=. !treapuri?Fig2.png!\r\n\r\np=. _*Descriere:* De la stânga la dreapta: inserarea nodului $z$. De la dreapta la stânga: ştergerea nodului $z$. Deoarece $z$ are prioritatea cea mai mare dintre toate nodurile, această inserare poate fi privită şi ca o operaţie de $split$. Subarborii stâng şi drept ai rădăcinii din ultima figură sunt chiar treapurile căutate: $T{~<~}$ şi $T{~>~}$. Invers, din $T{~<~}$ şi $T{~>~}$ se obţine, prin ştergerea rădăcinii, rezultatul operaţiei $join$._\r\n\r\nCheile formează un arbore de căutare, dar priorităţile pot să nu mai formeze un heap. Pentru a redobândi această proprietate, cât timp nodul de inserat, are prioritatea mai mare decât a părintelui său, se va executa o \'$rotaţie$\':treapuri#rotatii a lui $z$, o operaţie locală care scade nivelul lui $z$ cu $1$ şi creşte nivelul părintelui lui $z$ cu $1$, şi care menţine invariantul arborilor de căutare. Timpul de inserare al lui $z$ este proporţional cu adâncimea lui înainte de rotaţii - trebuie să coborâm, după care să urcăm înapoi efectuând rotaţiile necesare.\r\n\r\n== code(cpp) |\r\nvoid insert(T* &n, int key, int priority) {\r\n    if (n == nil) {\r\n        n = new T(key, priority, nil, nil);\r\n        return;\r\n    }\r\n    if (key < n->key)\r\n        insert(n->left, key, priority);\r\n    else if (key > n->key)\r\n        insert(n->right, key, priority);\r\n\r\n    balance(n);\r\n}\r\n==\r\n\r\nUn nod poate fi inserat în modul următor:\r\n== code(cpp) |\r\n...\r\ninsert(R, key, rand() + 1); // adăugăm 1 deoarece prioritatea 0 o are doar nodul nil\r\n...\r\n==\r\n\r\nunde $R$ este rădăcina, iar $key$ este cheia de inserat.\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#stergere). Ştergere\r\n\r\nOperaţia de ştergere este inversul operaţiei de inserare. Scopul este să aducem acest nod, fie el $z$, în poziţia unei frunze pentru a-l şterge. Astfel, pentru a menţine cei doi invarianţi (făcând excepţie de $z$) vom alege fiul cu prioritatea mai mare şi îl vom \'$roti$\':treapuri#rotatii în locul lui $z$, cât timp acesta nu este frunză. Atunci când $z$ devine frunză îl vom şterge.\r\n\r\n== code(cpp) |\r\nvoid erase(T* &n, int key) {\r\n    if (n == nil) return ;\r\n\r\n    if (key < n->key)\r\n        erase(n->left, key);\r\n    else if (key > n->key)\r\n        erase(n->right, key);\r\n    else {\r\n        (n->left->priority > n->right->priority) ? rotleft(n) : rotright(n);\r\n        if (n != nil)\r\n            erase(n, key);\r\n        else {\r\n            delete n->left;\r\n            n->left = NULL;\r\n        }\r\n    }\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#split). Split\r\n\r\nUneori dorim să despărţim treapul $T$ în două treapuri $T{~<~}$ şi $T{~>~}$ astfel încât cheile din $T{~<~}$ să conţină cheile din $T$ mai mici decât o cheie $key$ dată, iar $T{~>~}$ să conţină cheile din $T$ mai mari decât aceeaşi cheie $key$. Soluţia constă în inserarea unui nod ajutător $z$ a cărui cheie este $key$ şi prioritate $infinit$. După inserare, $z$ va fi rădăcina arborelui, având prioritatea cea mai mare, iar subarborii stâng şi drept ai rădăcănii vor fi exact treapurile căutate. Pe $z$ îl vom şterge, deoarece nu mai avem nevoie de el.\r\n\r\nCostul operaţiei $split$ este egal cu costul operaţiei de \'$inserare$\':treapuri#inserare a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid split(T* &R, T* &Ts, T* &Tg, int key) {\r\n    insert(R, key, infinity);\r\n    Ts = R->left, Tg = R->right;\r\n    delete R, R = nil;\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#join). Join\r\n\r\nOperaţia $join$ constă în unirea a două treapuri $T{~<~}$ şi $T{~>~}$, unde fiecare cheie din $T{~<~}$ este mai mică decât o cheie $key$, iar fiecare cheie din $T{~>~}$ este mai mare decât aceeaşi cheie $key$, într-un singur super-treap. $Join$ se realizează în mod invers operaţiei de $split$ prin crearea unei rădăcini $z$ cu cheia $key$ şi o prioritate aleatoare, ce are ca subarbore stâng pe $T{~<~}$, iar ca subarbore drept pe $T{~>~}$, pe care o vom suprima.\r\n\r\nCostul operaţiei $join$ este egal cu costul operaţiei de \'$ştergere$\':treapuri#stergere a lui $z$.\r\n\r\n== code(cpp) |\r\nvoid join(T* &R, T* Ts, T* Tg, int key) {\r\n    R = new T(key, 0, Ts, Tg);\r\n    erase(R, R->key);\r\n}\r\n==\r\n\r\nComplexitate: $O(log N)$.\r\n\r\nh3(#alte-operatii). Alte operaţii\r\n\r\nStructura de date de treap suportă, pe lângă operaţiile prezentate, şi operaţia de determinare a celei de a $K$-a chei, precum şi determinarea maximului, a minimului, a succesorului sau predecesorului unei chei, sau de tipărire a conţinutului cheilor pe baza relaţiei de ordine stabilite.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nNu întotdeauna $STL$ ne scapă din încurcătură. Nu avem în această bibliotecă o structură de date pentru determinarea celei de a $K$-a chei în timp logaritmic şi nici nu ne putem folosi de structura arborescentă a lui $set$. Exemple grăitoare, în care se foloseşte structura arborescentă a treapurilor, sunt aplicaţiile prezentate mai jos. Cât despre alternative, puteţi face o comparaţie a funcţiilor \'$erase$\':treapuri#stergere sau \'$balance$\':treapuri#rotatii cu cele din articolul următor despre arborii \'$AVL$\':multe-smenuri-de-programare-in-cc-si-nu-numai#AVL.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\n* \'Order\':problema/order, info{_arena_}\r\n* \'Schi\':problema/schi, info{_arena_}\r\n* \'Zeap\':problema/zeap, info{_arena_}\r\n* \'Vmem\':http://campion.edu.ro/problems/3/444/vmem_ro.htm, .campion\r\n* \'Bile\':http://campion.edu.ro/problems/3/443/bile_ro.htm, .campion\r\n* \'Trains\':http://campion.edu.ro/problems/3/432/trains_ro.htm, .campion\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* \'Eternally Confuzzled\':http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_bst2.aspx\r\n* \'Fast Set Operations Using Treaps\':http://www.cs.cmu.edu/afs/cs.cmu.edu/project/scandal/public/papers/treaps-spaa98.pdf, operaţiile \'$split$\':treapuri#split şi \'$join$\':treapuri#join sub altă formă\r\n* \'Treaps and Skip Lists\':http://compgeom.cs.uiuc.edu/~jeffe/teaching/algorithms/notes/06-treaps.pdf\r\n* \'Balanced Search Trees\':http://www.cs.cmu.edu/afs/cs.cmu.edu/academic/class/15451-s07/www/lecture_notes/lect0208.pdf\r\n\r\nh2. Discutii pe forum',2044,'public',3442,NULL),('articole','Articole de informatica, algoritmi, structuri de date','2006-11-05 23:22:34','2008-12-12 14:53:14','h1. Articole\r\n\r\nAceste pagini, ca intreg site-ul infoarena, sunt intr-o continua miscare. Utilizatorii infoarena pot edita pagini sau sa creeze altele noi.  \r\n\r\n\"Afla cum poti edita si tu articole\":implica-te/scrie-articole.\r\n\r\ntable(layout). \r\n|\\2_. Solutii (oficiale) la diverse competitii |\r\n|* \'Junior Challenge 2008\':junior-challenge-2008/solutii\r\n* \'Grigore Moisil 2008\':grigore-moisil-2008/solutii\r\n* !>template/preoni-2008/header?a.jpg 60%! \'preONI 2008, Runda finala\':preoni-2008/runda-finala/solutii\r\n* \'preONI 2008, Runda 4\':preoni-2008/runda-4/solutii\r\n* \'preONI 2008, Runda 3\':preoni-2008/runda-3/solutii\r\n* \'preONI 2008, Runda 2\':preoni-2008/runda-2/solutii\r\n* \'preONI 2008, Runda 1\':preoni-2008/runda-1/solutii\r\n* \'Winter Challenge 2008, Runda 2\':winter-challenge-2008/runda-2/solutii\r\n* \'Winter Challenge 2008, Runda 1\':winter-challenge-2008/runda-1/solutii\r\n* \'Happy Coding 2007\':happy-coding-2007/solutii\r\n* \'Autumn Warmup 2007 runda 3\':autumn-warmup-2007/solutii/runda-3\r\n* \'Autumn Warmup 2007 runda 2\':autumn-warmup-2007/solutii/runda-2\r\n* \'Autumn Warmup 2007 runda 1\':autumn-warmup-2007/solutii/runda-1\r\n* \'Summer Challenge 2007 runda #3\':summer-challenge-2007/solutii/runda-3\r\n* \'Summer Challenge 2007 runda #2\':summer-challenge-2007/solutii/runda-2\r\n* \'Summer Challenge 2007 runda #1\':summer-challenge-2007/solutii/runda-1\r\n* \'Junior Challenge 2007\':junior-challenge/solutii\r\n* \'preONI 2007 runda finala - solutii\':preoni-2007/runda-finala/solutii\r\n* \'preONI 2007 runda #4 - solutii\':preoni-2007/runda-4/solutii\r\n* !>template/preoni-2007/header?logo.jpg 70%! \'preONI 2007 runda #3 - solutii\':preoni-2007/runda-3/solutii\r\n* \'preONI 2007 runda #2 - solutii\':preoni-2007/runda-2/solutii\r\n* \'preONI 2007 runda #1 - solutii\':preoni-2007/runda-1/solutii\r\n* \'Winter Challenge 1\':winter-challenge-1/solutii\r\n* \'Unirea 2007\':unirea-2007/solutii\r\n* \'Solutii Autumn WarmUp 2006\':warm-up-2006/solutii\r\n|* \'Solutii - Summer Challenge Trei\':summer-challenge-3/solutii\r\n* \'Solutii - Summer Challenge Doi\':summer-challenge-2/solutii\r\n* \'Solutii - Summer Challenge Unu\':summer-challenge-unu/solutii\r\n* \'Solutii preONI 2006, Runda finala\':preoni-2006/finala/solutii\r\n* \'Solutii preONI 2006, Runda a 4-a\':preoni-2006/runda-4/solutii\r\n* \'Solutii preONI 2006 - Runda a 3-a\':preoni-2006/runda-3/solutii\r\n* \'Solutii preONI 2006 - Runda a 2-a\':preoni-2006/runda-2/solutii\r\n* \'Solutii preONI 2006 - Runda 1\':preoni-2006/runda-1/solutii\r\n* \'preONI 2005 runda #3 - solutii\':preoni-2005/runda-3/solutii\r\n* \'preONI 2005 runda #2 - solutii\':preoni-2005/runda-2/solutii\r\n* \'preONI 2005 runda #1 - solutii\':preoni-2005/runda-1/solutii\r\n* \'Happy Coding 3 [2006]\':happy-coding-2006/solutii\r\n* \'Happy Coding 2 [2005]\':happy-coding-2005-2/solutii\r\n* \'Happy Coding 1 [2005]\':happy-coding-2005-1/solutii\r\n* \'Concursul Agora - Etapa Finala - Solutii\':agora-finala/solutii\r\n* \'Doua probleme de la runda 6 a concursului Algoritmus\':doua-probleme-de-la-runda-6-a-concursului-algoritmus\r\n* \'USACO dec 2005, divizia GOLD\':usaco-dec-2005-divizia-gold \r\n* \'USACO nov 2005, divizia GOLD\':usaco-nov-2005-divizia-gold\r\n* \'USACO oct 2005, divizia GOLD\':usaco-oct-2005-divizia-gold\r\n* \'USACO ian 2005, divizia GOLD\':usaco-ian-2005-divizia-gold\r\n* \'USACO dec 2004, divizia GOLD\':usaco-dec-2004-divizia-gold\r\n* \'Solutiile oficiale pentru Concursul &quot;de incalzire&quot;\':warm-up-2004/solutii|\r\n|_. Algoritmi |_. Structuri de date |\r\n| * \'Probleme de acoperire &#40;partea I&#41;\':probleme-de-acoperire-1\r\n* \'Probleme de acoperire &#40;partea a II-a&#41;\':probleme-de-acoperire-2\r\n* \'Tree decompositions\':heavy-path-decomposition\r\n* \'Rotatie lexicografic minima\':rotatie-lexicografic-minima\r\n* \'Algoritmul lui Kuhn (Ungar)\':algoritm-kuhn\r\n* \'Taietura minima in graf cu costuri\':taietura-minima\r\n* !>Al-K-lea-drum-minim?kshortest_tree.png 40%! \'Automate finite si KMP\':automate-finite-si-kmp\r\n* \'Aplicatii ale cautarii binare\':aplicatii-ale-cautarii-binare\r\n* \'Al K-lea drum minim\':al-k-lea-drum-minim\r\n* \'Ciclu hamiltonian in graf dens\':ciclu-hamiltonian-in-graf-dens\r\n|* \'Treapuri\':treapuri\r\n* \'Cautari ortogonale\':cautari-ortogonale\r\n* \'Siruri de sufixe\':siruri-de-sufixe\r\n* \'Suffix array in timp liniar\':suffix-array-liniar\r\n* !>Lowest-common-ancestor?euler.jpg 40%! \'Lowest common ancestor\':lowest-common-ancestor\r\n* \'Skiplists\':skiplists\r\n* \'Tabele hash\':tabele-hash-scurta-prezentare\r\n* \'Arbori de intervale si aplicatii in geometrie\':arbori-de-intervale |\r\n|_. Limbaje |_. Matematica|\r\n|* \'STL\':stl\r\n* \'Introducere in asamblare\':introducere-in-asamblare\r\n* {\'12 ponturi pentru programatorii C/C++\':12-ponturi-pentru-programatorii-cc}\r\n* \'Multe &quot;smenuri&quot; de programare in C/C++... si nu numai!\':multe-smenuri-de-programare-in-cc-si-nu-numai\r\n|* \'Teorema chineza a resturilor\':teorema-chineza-a-resturilor\r\n* \'Algoritmul lui Euclid\':algoritmul-lui-euclid\r\n* \'Ciurul lui Eratostene\':ciurul-lui-eratostene\r\n* \'Coduri Gray\':coduri-gray|\r\n|_. Diverse |_. Geometrie |\r\n|* \'Ghid complet pentru concursurile de informatica\':ghid-complet-pentru-concursurile-de-informatica\r\n* \'Missing Numbers\':missing-numbers\r\n* \'F.A.Q. Pregatire bacalaureat 2005\':faq-pregatire-bacalaureat-2005\r\n* \'DJGPP - instalarea de la A la Z\':djgpp-instalarea-de-la-a-la-z\r\n* \'The Monty Hall Problem\':the-monty-hall-problem\r\n|* !>articole?geometry.gif 100%! \'Minimal enclosing circle\':minimal-enclosing-circle |\r\n',2044,'public',NULL,NULL),('hash','hash','2008-03-28 16:38:33','2008-03-28 16:42:58','Download \'aici\':http://infoarena.ro/hash?action=download&file=hash.zip',2092,'public',NULL,NULL),('articole/structuri-de-date','Structuri de date','2008-12-13 14:26:32','2008-12-13 14:26:32','==include(page=\"articole/template-structuri-de-date\" display=\"list-item\")==',2044,'public',NULL,NULL),('articole/template-limbaje-de-programare','articole/template-limbaje-de-programare','2008-12-13 14:59:53','2008-12-13 14:59:53','* \'STL\':stl\r\n* \'Introducere in asamblare\':introducere-in-asamblare\r\n* \'12 ponturi pentru programatorii C/C++\':12-ponturi-pentru-programatorii-cc\r\n* \'Multe &quot;smenuri&quot; de programare in C/C++... si nu numai!\':multe-smenuri-de-programare-in-cc-si-nu-numai',2044,'protected',NULL,NULL),('articole/template-algoritmi','articole/template-algoritmi','2008-12-13 15:07:56','2008-12-13 15:09:39','* \'Probleme de acoperire &#40;partea I&#41;\':probleme-de-acoperire-1\r\n* \'Probleme de acoperire &#40;partea a II-a&#41;\':probleme-de-acoperire-2\r\n* \'Tree decompositions\':tree-decompositions\r\n* \'Rotatie lexicografic minima\':rotatie-lexicografic-minima\r\n* \'Algoritmul lui Kuhn (Ungar)\':algoritm-kuhn\r\n*{display: %display%} \'Taietura minima in graf cu costuri\':taietura-minima\r\n*{display: %display%} !>Al-K-lea-drum-minim?kshortest_tree.png 40%! \'Automate finite si KMP\':automate-finite-si-kmp\r\n*{display: %display%} \'Aplicatii ale cautarii binare\':aplicatii-ale-cautarii-binare\r\n*{display: %display%} \'Al K-lea drum minim\':al-k-lea-drum-minim\r\n*{display: %display%} \'Ciclu hamiltonian in graf dens\':ciclu-hamiltonian-in-graf-dens',2044,'protected',NULL,NULL),('articole/template-structuri-de-date','articole/template-structuri-de-date','2008-12-13 14:24:20','2008-12-13 14:55:45','* \'Treapuri\':treapuri\r\n* \'Cautari ortogonale\':cautari-ortogonale\r\n* \'Siruri de sufixe\':siruri-de-sufixe\r\n* \'Suffix array in timp liniar\':suffix-array-liniar\r\n* !>Lowest-common-ancestor?euler.jpg 40%! \'Lowest common ancestor\':lowest-common-ancestor\r\n*{display: %display%} \'Skiplists\':skiplists\r\n*{display: %display%} \'Tabele hash\':tabele-hash-scurta-prezentare\r\n*{display: %display%} \'Arbori de intervale si aplicatii in geometrie\':arbori-de-intervale',2044,'protected',NULL,NULL),('ciclu-hamiltonian-in-graf-dens','Ciclu hamiltonian in graf dens','2004-11-09 00:00:00','2007-03-31 09:39:29','h1. Ciclu hamiltonian in graf dens\r\n\r\n(Categoria _Grafuri_, autor(i) _Crestez Leonard_)\r\n\r\nIn acest articol va voi prezenta un algoritm pentru gasirea unui ciclu hamiltonian intr-un graf neorientat dens - in care fiecare nod are macar $(N + 1) / 2$ muchii.\r\n\r\nIn general, gasirea unui ciclu hamiltonian intr-un graf neorientat este un exemplu clasic de problema NP - completa. Insa, daca graful este dens - fiecare nod are cel putin $(N+1) / 2$ muchii incidente ({$N$} este numarul de noduri) - se poate gasi o solutie de complexitate {$O(N^2^)$}.\r\n\r\nh2. Algoritm\r\n\r\nLa inceput formam un ciclu la intamplare, fara a tine cont daca muchiile luate in considerare chiar exista in graf. Astfel, putem alege chiar ciclul {$1, 2, 3, 4, ... N$}. Daca acest ciclu este valid, atunci avem noroc si solutia a fost gasita. Altfel, trebuie sa incercam sa \"umplem gaurile\" din ciclu (adica muchiile pe care le-am ales la intamplare si care nu exista in graf).\r\n\r\nGasim prima muchie de acest fel, fie ea ({$A, B$}). Cautam apoi doua alte noduri adiacente in ciclul nostru, notate cu $C$ si {$D$}, astfel incat sa avem muchie de la $A$ la $C$ si de la $B$ la {$D$}. Se poate demonstra ca vom gasi mereu $C$ si {$D$}. Acum vom \"incrucisa\" $A B$ cu {$C D$}. Prin \"incrucisare\" se intelege transfromarea unui ciclu $...AB...CD...$ in $...AC...BD...$ (sau $...CD...AB...$ in $...CA...DB...$) . Atentie, secventa de la $B$ la $C$ (respectiv de la $D$ la {$A$}) va fi inversata complet!\r\n\r\nSe observa ca a scazut numarul de \"gauri\" din sir, $AB$ a fost eliminata si nu au fost adaugate \"gauri\" noi. Repetam \"umplerea gaurilor\" pana nu mai avem ce umple, deci am gasit solutie.\r\n\r\nDesi suna complicat, \"umplerea unei gauri\" necesita doar $O(N)$ timp pentru cautarea nodurile {$AB$}, {$CD$}, si incrucisare. Avand in vedere ca sunt maxim $N$ gauri la inceput, algoritmul necesita $O(N^2^)$ ca timp de executie.\r\n\r\nMai sus am folosit o afirmatie fara a o demonstra. Demonstratia e relativ intuitiva. Daca nu o descoperiti singuri, puteti sa intrebati pe \"forum\":http://infoarena.ro/forum.\r\n\r\nProblema luata in discutie este propusa pe lista \"sgu\":http://acm.sgu.ru/, nr. \"122\":http://acm.sgu.ru/problem.php?contest=0&problem=122, unde exista si evaluator online. Atentie la implementare! Citirea si scrierea folosind functii standard pot iesi din timp!\r\n\r\n',354,'public',NULL,NULL),('home','infoarena -  comunitate informatica, concursuri de programare','2006-11-05 14:45:56','2008-12-07 09:18:20','h1. Bine ai venit pe infoarena!\r\n\r\nSuntem o comunitate de tineri pasionati de informatica si programare.\r\nInvatam impreuna participand la concursuri online de programare, citind stiri si articole despre informatica sau discutand pe forum.\r\n\r\n\'*&raquo; Afla mai multe despre noi!*\':despre-infoarena\r\n\r\ntable{width:99%; margin:auto}. |={background-color: rgb(210, 244, 219); border: 0; padding: 0.3em; -moz-border-radius:7px}. Concursul \'*Algoritmiada 2009*\':algoritmiada-2009 va incepe *duminica, 14 decembrie 2008*. Inscrie-te si tu la \'*Runda 1*\':algoritmiada-2009/runda-1 acum!|\r\n\r\nh1. Ultimele insemnari de pe \'blog\':blog \'!{vertical-align:middle}home?rss_icon.jpg!\':blog?action=rss\r\n\r\n==BlogPreview(display_entries=\"10\")==\r\n',1490,'protected',NULL,NULL),('2-sat','Problema satisfiabilităţii formulelor logice de ordinul doi','2008-12-09 15:55:03','2008-12-14 16:38:05','h1. Problema satisfiabilităţii formulelor logice de ordinul doi\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 37em}*{text-align:center} *Conţinut:*\r\n* {\'Introducere\':2-sat#introducere}\r\n* {\'Forme normale ale formulelor logice\':2-sat#forme-normale}\r\n* {\'SAT, 3-SAT, 2-SAT\':2-sat#overview-sat}\r\n* {\'Soluţii pentru 2-SAT\':2-sat#solutii-2-sat}\r\n** {\'Soluţie $O(M * 2^N^)$\':2-sat#solutie1}\r\n** {\'Soluţie $O(N * M)$\':2-sat#solutie2}\r\n** {\'Soluţie $O(N^2^)$\':2-sat#solutie3}\r\n** {\'Soluţie $O(M + N)$\':2-sat#solutie4}\r\n* {\'Aplicaţii\':2-sat#aplicatii}\r\n** {\'Party &#40;preOni 2003/2004&#41;\':2-sat#party}\r\n** {\'Cigraf\':2-sat#cigraf}\r\n** {\'Peace Commission &#40;Polish Olympiad in Informatics, 2001&#41;\':2-sat#peace-commission}\r\n** {\'Excursion &#40;Baltic Olympiad in Informatics, 2001&#41;\':2-sat#excursion}\r\n** {\'Orpath &#40;Olimpiadă Rusia&#41;\':2-sat#orpath}\r\n** {\'Aladdin &#40;Bursele Agora 2005/2006, Runda 1&#41;\':2-sat#aladdin}\r\n* {\'Bibliografie\':2-sat#bibliografie}\r\n\r\nh2(#introducere). Introducere\r\n\r\nProblema satisfiabilităţii, notată prescurtat cu $SAT$, cere determinarea existenţei pentru o formulă booleană <tex> \\phi </tex> a unei artibuiri satisfiabile. O formulă booleană <tex> \\phi </tex> este compusă din $variabile$ logice <tex> (x_{1}, x_{2}, ...) </tex>, $operatori$ logici ( <tex> \\wedge </tex> şi,  <tex> \\vee </tex> sau, <tex> \\sim </tex> non, <tex> \\rightarrow </tex> implicaţie şi <tex> \\leftrightarrow </tex> echivalenţă), şi $paranteze$. O atribuire de valori booleene pentru variabilele acestei expresii se numeşte $atribuire satisfiabilă$ dacă evaluarea expresiei după atribuirea valorilor dă ca rezultat valoarea de adevăr $adevărat$. De acum încolo vom folosi pentru simplitate valorile <tex> 1 </tex> şi <tex> 0 </tex> în loc de $adevărat$ şi $fals$.\r\n\r\nUn exemplu de formulă ar fi <tex> \\phi = ((x_{1} \\rightarrow x_{2}) \\vee \\sim((\\sim x_{1} \\leftrightarrow x_{3}) \\vee x_{4})) \\wedge \\sim x_{2} </tex>. Aceasta are atribuirea satisfiabilă <tex> \\langle x_{1} = 0, x_{2} = 0, x_{3} = 1, x_{4} = 1 \\rangle </tex> pentru că <tex> \\phi = ((0 \\rightarrow 0) \\vee \\sim((\\sim 0 \\leftrightarrow 1) \\vee 1)) \\wedge \\sim 0 = (1 \\vee \\sim (1 \\vee 1)) \\wedge 1 = (1 \\vee 0) \\wedge 1 = 1</tex>. \r\n\r\nh2(#forme-normale). Forme normale ale formulelor logice\r\n\r\nOrice formulă booleană poate fi transformată în două forme:\r\n\r\n* $Forma normal conjunctivă$ în care expresia este exprimată ca o conjuncţie de propoziţii, iar fiecare propoziţie este formată din o disjuncţie de $literali$. Un $literal$ este o variabilă care poate fi sau nu negată. Un exemplu de expresie în forma normal conjunctivă ar fi: <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) \\wedge (x_{3} \\vee x_{2} \\vee x_{4}) \\wedge (\\sim x_{1} \\vee \\sim x_{3} \\vee \\sim x_{4}) </tex> care are pe <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) </tex> ca primă propoziţie cu literalii <tex> x_{1} </tex>, <tex> \\sim x_{1} </tex>, <tex> \\sim x_{2} </tex>.\r\n\r\n* $Forma normal disjunctivă$ este formată ca o disjuncţie de propoziţii, fiecare dintre aceste propoziţii fiind o conjuncţie de literali. Un exemplu de o asemenea formulă ar fi următoarea: <tex> (x_{1} \\wedge x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge \\sim x_{3}) \\vee (\\sim x_{1} \\wedge x_{2} \\wedge \\sim x_{2}) </tex>.\r\n\r\nh2(#overview-sat). SAT, 3-SAT, 2-SAT\r\n\r\nProblema $SAT$ este $NP-completă$. Defapt, este prima problemă $NP-completă$ găsită. Stephen Cook a demonstrat $NP-completitudinea$ ei în 1971. Pe vremea aceea nu se ştia nici măcar că problemele $NP-complete$ există. Această problemă rămâne $NP-completă$ chiar dacă restricţionăm expresiile la unele care în forma normal conjunctivă au doar trei literali. Problema satisfiabilităţii pentru asemenea expresii se numeşte $3-SAT$, şi multe probleme pot fi demonstrate a fi $NP-complete$ prin reducerea la această problemă. Din fericire, problema $2-SAT$, adică cea pentru care în fiecare propoziţie există doar $2$ literali se poate rezolva eficient. Restul articolului va prezenta trei metode de rezolvare a problemei $2-SAT$ şi câteva aplicaţii ale acesteia la concursuri de programare.\r\n\r\nh2(#solutii-2-sat). Soluţii pentru 2-SAT\r\n\r\nUn exemplu de problemă $2-SAT$ ar fi satisfiabilitatea formulei <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Această formulă este satisfăcută de valorile <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>. Pentru a satisface întreaga expresie trebuie ca în fiecare propoziţie cel puţin unul din cei doi literali să aibă valoarea de adevăr <tex> 1 </tex>.\r\n\r\nh3(#solutie1). Soluţie $O(M * 2^N^)$\r\n\r\nO primă metodă de rezolvare ar fi să încercăm toate cele $2^N^$ posibilităţi de atribuire posibilă, dar această metodă are ordinul de complexitate $O(M * 2^N^)$ şi este eficientă doar pentru instanţe mici ale problemei.\r\n\r\nh3(#solutie2). Soluţie $O(N * M)$\r\n\r\nUrmătoarea soluţie pare trivială, dar găsirea acestui algoritm şi realizarea faptului că el rezolvă corect problema este mai grea decât impresia lăsată după citirea ei. Considerăm o propoziţie oarecare cu două variabile $p$ şi $q$, apoi una dintre ele, de exemplu $p$. Dacă literalul în care apare $p$ este negat atunci îi atribuim valoarea $1$. Pentru ca propoziţia respectivă să aibă $1$ valoarea de adevăr atunci valoarea lui $q$ este fixată. Fixând şi valoarea lui $q$, probabil şi alte propoziţii ce conţin literalul $q$ vor avea celălalt literal fixat. Propagăm astfel o serie de schimbări. După ce toate schimbările forţate au fost făcute propoziţiile rezultate vor fi de următoarele tipuri: <tex> a \\vee b </tex>, <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex>. Propoziţii de tip <tex> 0 \\vee b </tex> nu pot apărea pentru că toate schimbările forţate au fost deja propagate. Dacă apare o propoziţie <tex> 0 \\vee 0 </tex> atunci alegerea făcută pentru valoarea lui $p$ este greşită. Vom încerca şi alegerea opusă. Dacă ambele duc la o propoziţie de tip <tex> 0 \\vee 0 </tex> atunci expresia nu poate fi satisfăcută. Propoziţiile de forma <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex> pot fi ignorate. În acest fel am eliminat cel puţin o variabilă şi o propoziţie din expresie. Dacă expresia iniţială era satisfiabilă, atunci şi expresia din care s-au eliminate câteva propoziţii a rămas satisfiabilă. Continuând pe această idee obţinem un algoritm de complexitate $O(N * M)$, pentru că la fiecare atribuire de valoare pentru o variabilă parcurgem şirul de propoziţii o dată. \r\n\r\nSă vedem cum funcţionează algoritmul pentru expresia: <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Considerăm propoziţia <tex> (x_{1} \\vee \\sim x_{2}) </tex> şi <tex> \\langle x_{2} = 1 \\rangle </tex>. Astfel, vom obţine mai departe <tex> (x_{1} \\vee 0) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee 1) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. În propoziţia <tex> (x_{1} \\vee 0) </tex> <tex> x_{1} </tex> trebuie să fie egal cu <tex> 1 </tex>. Acum, expresia devine: <tex> (0 \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee 0) </tex>. Din propoziţia <tex> (0 \\vee \\sim x_{3}) </tex> obţinem <tex> \\langle x_{3} = 0 \\rangle </tex>, iar din <tex> (x_{4} \\vee 0) </tex> obţinem <tex> \\langle x_{4} = 1 \\rangle </tex>. Deci, atribuirea satisfiabilă este <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>.\r\n\r\nh3(#solutie3). Soluţie $O(N^2^)$\r\n\r\nO altă soluţie elegantă se bazează pe o metodă randomizată:\r\n\r\n== code(cpp) |\r\natribuim valori booleene arbitrare variabilelor;\r\ncât timp expresia nu este satisfăcută execută\r\n    găsim o propoziţie cu valoarea de adevăr 0;\r\n    schimbăm valoarea de adevăr a oricăreia dintre cele două variabile prezente în propoziţie;\r\nsfcâttimp\r\n==\r\n\r\nLinia $4$ va face ca acea propoziţie să aibă noua valoare de adevăr <tex> 1 </tex>.\r\n\r\nDe ce ar merge acest algoritm? Să presupunem că există o soluţie a problemei, o notăm cu <tex> S </tex>, iar cu <tex> X </tex> notăm şirul valorilor curente ale variabilelor. Ne uităm la fiecare pas al algoritmului la numărul de variabile care au valori diferite în soluţie faţă de cele din <tex> X </tex> (acest număr de diferenţe între elementele de acelaşi index pentru două şiruri se mai numeşte şi \'distanţă Hamming\':http://en.wikipedia.org/wiki/Hamming_distance între şiruri). Fie această valoare la pasul current $K$. Noi am vrea să avem $K = 0$. Cum va evolua $K$ pe parcursul algoritmului? La un moment dat noi schimbăm valoarea unei variabile luate aleator dintr-o propoziţie nesatisfăcută. Pentru că în <tex> S </tex> propoziţia este satisfăcută, înseamnă că cel puţin una dintre cele două variabile ale propoziţiei are valori diferite în <tex> X </tex> faţă de <tex> S </tex>. Astfel, operaţia făcută de noi are probabilitate de cel puţin $0.5$ să ne aducă mai aproape de soluţie. Vom nota cu <tex> T(i) </tex> numărul probabil de paşi în care un şir <tex> X </tex> aflat la distanţa Hamming egală cu $i$ faţă de <tex> S </tex>, va fi transformat în <tex> S </tex>. Evident:\r\n\r\n<tex> T(0) = 0 </tex>.\r\n\r\n<tex> T(i) \\le (T(i + 1) + T(i - 1)) / 2 + 1 </tex> pentru $0 < i < N$ ({$N$} e numărul de variabile booleene ale expresiei)\r\n\r\nSe pune semnul de inegalitate pentru că ambele variabile pot avea valori diferite faţă de cele din soluţie, deci schimbarea valorii oricăreia ar putea să ne aducă mai aproape de soluţie.\r\n\r\nPentru că dacă toate variabilele diferă de soluţie, orice schimbare ne aduce mai aproape de soluţie:\r\n\r\n<tex> T(N) = T(N - 1) + 1 </tex>\r\n\r\nNe interesează numai limitele superioare, deci folosim doar egalităţi în loc de inegalităţi:\r\n\r\n<tex> X(0) = 0, X(i) = (X(i + 1) + X(i - 1))/2 + 1, X(N) = X(N - 1) + 1 </tex>\r\n\r\nDacă adunăm toate ecuaţiile obţinem:\r\n\r\n<tex> X(0) + X(1) + ... + X(N) </tex> <tex> = (X(0) + X(1) + 2X(2) + ... + 2X(N - 2) + X(N - 1) + X(N))/2 + X(N) + N-1 </tex>\r\n\r\nDe aici avem că <tex> (X(1) + X(N - 1) - X(N)) / 2 = N - 1 </tex>, din <tex> X(N) = X(N - 1) + 1 </tex> avem <tex> X(1) = 2N - 1 </tex>. Mai departe avem că <tex> X(2) = 4n - 2 ... X(i) = 2iN - i </tex> de unde, când <tex> i = N </tex> avem că <tex> X(N) = 2N^2 - N </tex>.\r\n\r\nAstfel, numărul mediu de paşi ai algoritmului este $2N^2^ - N$ iar dacă aplicăm algoritmul în mod aleator de mai multe ori avem o probabilitate foarte mare să ajungem la rezultat.\r\n\r\nh3(#solutie4). Soluţie $O(M + N)$\r\n\r\nO a treia soluţie se bazează pe relaţia de implicaţie. Relaţia <tex> \\rightarrow </tex> are următoarea tabelă de adevăr:\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> A \\rightarrow B </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nRelaţia de implicaţie are semnificaţia dacă <tex> A </tex> este adevărat atunci şi <tex> B </tex> este adevărat. Scriem tabelul expresiei <tex> \\sim A \\vee B </tex> şi observăm că acesta este egal cu cel al relaţiei de implicaţie.\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> \\sim A \\vee B </tex>|\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nFiecare clauză <tex> A \\vee B </tex> poate fi scrisă ca două implicaţii <tex> \\sim A \\rightarrow B </tex> şi <tex> \\sim B \\rightarrow A </tex>. Realizăm un graf al implicaţiilor. Astfel, nodurile grafului vor fi variabilele <tex> A </tex>, <tex> B </tex> ... şi negaţiile lor <tex> \\sim A </tex>, <tex> \\sim B </tex> ... iar muchiile acestui graf vor fi implicaţiile echivalente cu propoziţiile din expresie. Deci, dacă expresia are $M$ propoziţii graful va avea $2M$ muchii. Acestea fiind zise, expresiei <tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) </tex> îi corespunde graful:\r\n\r\np=. !2-sat?Graf.png!\r\n\r\nDacă avem <tex> A \\longrightarrow B </tex> o muchie în graful nostru, atunci dacă literalul <tex> A </tex> este adevărat atunci şi literalul <tex> B </tex> trebuie să fie adevărat pentru ca propoziţia reprezentată de muchie să fie satisfăcută. Putem demonstra prin inducţie că dacă există un drum în graf de la literalul <tex> A </tex> la literalul <tex> B </tex>, atunci dacă <tex> A </tex> este adevărat şi <tex> B </tex> trebuie să fie adevărat. Dacă există un drum de la un literal <tex> X </tex> la <tex> \\sim X </tex> atunci nu va exista soluţie pentru că nu putem seta în acelaşi timp o variabilă şi valoarea ei negată la valoarea adevărat. De aici rezultă că dacă în graful asociat expresiei există o variabilă <tex> X </tex> în aceiaşi componentă tare conexă cu <tex> \\sim X </tex> atunci instanţa problemei satisfiabilităţii nu poate fi satisfăcută. Dacă nu există o asemenea variabilă, vom vedea în continuare cum putem rezolva problema. Întâi, facem observaţia că dacă în graf există muchia <tex> A \\longrightarrow B </tex> atunci există şi muchia <tex> \\sim B \\longrightarrow \\sim A </tex>. Astfel, dacă există un drum de la <tex> A </tex> la <tex> B </tex> în graf, aplicând proprietatea menţionată pentru fiecare muchie a drumului, vom găsi un drum de la <tex> \\sim B </tex> la <tex> \\sim A </tex>. Evident, afirmaţia este valabilă şi reciproc: dacă există drum de la <tex> B </tex> la <tex> A </tex> atunci vom avea un drum de la nodul <tex> \\sim A </tex> la <tex> \\sim B </tex>. Astfel, dacă avem că <tex> A </tex> şi <tex> B </tex> sunt în aceeaşi componentă tare conexă atunci şi nodurile <tex> \\sim A </tex> şi <tex> \\sim B </tex> sunt în aceeaşi componentă tare conexă. Deci, dacă nu există doi literali <tex> X </tex> şi <tex> \\sim X </tex> în aceeaşi componentă tare conexă, putem să împărţim graful în componente tari conexe şi să împerechem componentele câte două astfel ca în fiecare pereche să apară o componentă <tex> U </tex> cu nişte literali şi altă componentă <tex> \\sim U </tex> cu aceiaşi literali negaţi. Pentru a găsi o soluţie vom determina mai întâi componentele tari conexe ale grafului. Apoi putem contracta fiecare componentă într-un nod. Graful obţinut va fi acciclic. Alegem un nod <tex> u </tex> în care nu intră nicio muchie (un asemenea nod trebuie să existe pentru a nu exista cicluri), din considerente de simetrie, din nodul lui pereche <tex> \\sim u </tex> nu va ieşi nicio muchie. Literalilor componentei <tex> U </tex> putem să le dăm valoarea de adevăr <tex> 0 </tex>, iar literalilor din componenta pereche <tex> \\sim U </tex>  putem să le dăm valoarea de adevăr <tex> 1 </tex>. Această alegere nu impune restricţii asupra celorlalţi literali şi elimină câteva variabile din problemă. Repetarea recursivă a acestui pas pe graful rămas va duce la rezolvarea problemei. Determinarea componentelor tari conexe se poate face în complexitatea $O(N + M)$. Pentru a vedea acest algoritm puteţi consulta secţiunea $23.5$ a [1]. Iar eliminarea  nodurilor de care vorbeam mai sus se poate face în $O(N + M)$ folosind o sortare topologică. \r\n\r\nSă urmărim cum merge algoritmul nostru pe exemplul de mai sus. Componentele tari conexe sunt următoarele: <tex> \\{A\\} </tex>, <tex> \\{\\sim A\\} </tex>, <tex> \\{B, C, \\sim D\\} </tex>, <tex> \\{\\sim B, \\sim C, D\\} </tex>. În nodul asociat componentei <tex> \\{A\\} </tex> nu intră nici o muchie. Astfel, putem să îi atribuim lui <tex> A </tex> valoarea <tex> 0 </tex>, iar în nodul asociat componentei <tex> \\{\\sim B, \\sim C, D\\} </tex> nu intră nicio muchie, deci putem să îi atribuim lui <tex> B </tex> valoarea <tex> 1 </tex>, lui <tex> C </tex> valoarea <tex> 0 </tex> şi lui <tex> D </tex> valoarea <tex> 1 </tex>. Această atribuire este satisfiabilă după cum vedem în continuare:\r\n\r\n<tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) </tex> <tex> = (\\sim 0 \\vee \\sim 1) \\wedge (1 \\vee \\sim 1) \\wedge (1 \\vee 1) \\wedge (\\sim 1 \\vee \\sim 0) \\wedge (1 \\vee 0) </tex> <tex> = 1 \\wedge 1 \\wedge 1 \\wedge 1 \\wedge 1 = 1 </tex>\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\nRestul articolului va prezenta aplicaţii ale problemei $2-SAT$ la concursurile de programare.\r\n\r\nh2(#party). \'Party\':problema/party (preOni 2003/2004)\r\n\r\nbq. George vrea să îşi organizeze majoratul, şi vrea ca petrecerea să fie de neuitat, mâncarea, băutura, locaţia şi sonorizarea sunt deja asigurate, mai rămâne problema chemării prietenilor. El şi cu prietenul lui cel mai bun Lucian au preferinte diferite şi pentru a nu se certa au pus la punct o listă de cerinţe care vor trebui să fie îndeplinite astfel încât cheful să se desfăşoare în cele mai bune condiţii! Pentru uşurinţă,  prietenii lui George vor fi indentificaţi prin numere întregi de la $1$ la $N (1 ≤ N ≤ 100)$ şi cerinţele în număr de $M  (1 ≤ M ≤ 1.000)$ vor fi de tipurile 0, 1, 2 sau 3. O cerinţă de genul <tex> x \\ y </tex> 0 are semnificaţia că <tex> x </tex> sau <tex> y </tex> trebuie să participe la petrecere; <tex> x \\ y </tex> 1 are semnificaţia că dacă <tex> x </tex> participă nu există nici o restricţie pentru <tex> y </tex>, dar dacă <tex> x </tex> nu participă atunci nici <tex> y </tex> nu participa; <tex> x \\ y </tex> 2 are semnificaţia simetrică cu cerinţa 1; iar cerinţa <tex> x \\ y </tex> 3 are semnificaţia că cel puţin unul dintre <tex> x </tex> şi <tex> y </tex> nu participă la petrecere. Scrieţi un program care să-i ajute pe cei doi să determine care persoane vor fi invitate la petrecere. Se garantează că va fi posibilă întotdeauna organizarea unei petreceri!\r\n\r\nh3. Soluţie\r\n\r\nAceastă problemă este inspirită din o problemă de la $CEOI 2002$ şi este evident că ne cere să determinăm o atribuire satisfiabilă pentru o formulă logică formată ca conjuncţie între cerinţele care se transformă astfel:\r\n\r\n* cerinţa de tip 0 corespunde propoziţiei <tex> x \\vee y </tex>;\r\n* cerinţa de tip 1 corespunde propoziţiei <tex> x \\vee \\sim y </tex>;\r\n* cerinţa de tip 2 corespunde propoziţiei <tex> \\sim x \\vee y </tex>;\r\n* cerinţa de tip 3 corespunde propoziţiei <tex> \\sim x \\vee \\sim y </tex>.\r\n\r\nUna din primele două rezolvări ar fi putut soluţiona această problemă, dar problema de la $CEOI$ avea limite mai mari şi pentru rezolvarea ei ar fi trebuit un algoritm de complexitate $O(N + M)$.\r\n\r\nh2(#cigraf). Cigraf\r\n\r\n_Autor: Mugurel Ionuţ Andreica_\r\n\r\nbq. Se dă un graf neorientat cu $N (1 <= N <= 1000)$ noduri şi $M (0 <= M <= N*(N-1)/2)$ muchii. Se doreşte împărţirea nodurilor acestui graf în $2$ mulţimi, <tex> C </tex> şi <tex> I </tex>, având următoarele proprietăţi: fiecare nod face parte din exact una din cele $2$ mulţimi, există muchie între oricare $2$ noduri din mulţimea <tex> C </tex>, nu există nicio muchie între $2$ noduri din mulţimea <tex> I </tex>. Este posibil ca una dintre cele $2$ mulţimi să fie vidă. Soluţia nu este neaparat unică. Numele celor două mulţimi provin de la $clică$ şi $mulţime independentă$. De exemplu, pentru graful de $6$ noduri ce are muchiile <tex> \\{\\{1, 4\\}, \\{4, 6\\}, \\{6, 1\\}, \\{2, 4\\}, \\{2, 6\\}, \\{3, 4\\}, \\{1, 3\\}\\} </tex> o împărţire posibilă ar fi <tex> C = \\{1, 4, 6\\} </tex>, <tex> I = \\{2, 3, 5\\} </tex>.\r\n\r\nh3. Soluţie\r\n\r\nDacă între două noduri există muchie atunci nu pot fi amândouă în mulţimea <tex> I </tex>, iar dacă între două noduri nu există muchie nu pot fi amândouă în mulţimea <tex> C </tex>. \r\nTransformăm această problemă într-o instanţă de $2-SAT$ astfel: faptul că nodul <tex> x </tex> aparţine mulţimii <tex> C </tex> îl reprezentăm dândui lui <tex> x </tex> valoarea <tex> 1 </tex>, iar apartenenţa mulţimii <tex> I </tex> se codifică prin valoarea <tex> 0 </tex>. Acum existenţa unei muchii <tex> (x, y) </tex> corespunde expresiei <tex> x \\vee y </tex>, astfel cel puţin unul din nodurile <tex> x </tex> şi <tex> y </tex> nu va fi în mulţimea <tex> I </tex>. Dacă nu există muchia <tex> (x, y) </tex> putem scrie <tex> \\sim x \\vee \\sim y </tex>, această expresie va fi adevărată dacă cel puţin un nod din cele două nu va fi în mulţimea <tex> C </tex>.\r\nAceastă soluţie este liniară ca şi complexitate în numărul de elemente citite la intrare.\r\n\r\nh2(#peace-commission). Peace Commission (Polish Olympiad in Informatics, 2001)\r\n\r\nbq. Comisia Publică a Păcii trebuie să fie compusă în parlamentul Republicii Democrate a ţării Byteland după regulile impuse de Legea Foarte Importantă. Din păcate, unul dintre obstacole este acela că unii deputaţi nu se înţeleg cu ceilalţi. Comisia trebuie realizată astfel ca următoarele condiţii să fie îndeplinite: fiecare partid trebuie să aibă exact un reprezentant în comisie; dacă doi deputaţi nu se înţeleg, ei nu pot fi ambii membrii ai comisiei. Fiecare partid are exact doi deputaţi în parlament. Toţi număraţi de la $1$ până la $2n (1 <= n <= 8000)$. Deputaţii cu numerele $2i-1$ şi $2i$ aparţin celui de al $i$-lea partid. Se vor da $m (0 <= m <= 20 000)$ perechi de deputaţi <tex> (a, b) </tex> care nu se înţeleg. Se cere realizarea unei comisii dacă acest lucru este posibil. Un exemplu ar fi pentru trei partide şi perechile <tex> (1, 3) </tex> şi <tex> (2, 4) </tex> care nu se înţeleg comisia alcătuită din membrii <tex> \\{1, 4, 5\\} </tex>.\r\n\r\nh3. Soluţie\r\n\r\nFiecărui partid îi vom asocia o variabilă; variabila va lua valoarea <tex> 1 </tex> dacă membrul $2i - 1$ al partidului va aparţine comisiei şi valoarea <tex> 0 </tex> dacă membrul $2i$ va aparţine comisiei. Pentru ca din partidul $x$ să existe exact un membru în expresie introducem  <tex> A_{x} \\wedge \\sim A_{x} </tex>. \r\nPutem exprima că doi membrii ai parlamentului $(2i, 2j)$ nu se înţeleg prin expresia logică <tex> \\sim A_{i} \\vee \\sim A_{j} </tex>. Astfel nu pot ambele variabile <tex> A_{i} </tex> şi <tex> A_{j} </tex> să aibă în acelaşi timp valoarea <tex> 1 </tex> adică $2i$ şi $2j$ nu pot face parte în acelaşi timp din comisie. Dacă cei doi membrii sunt $(2i - 1, 2j - 1)$ atunci îi putem codifica prin expresia <tex> A_{i} \\vee A_{j} </tex> astfel <tex> A_{i} </tex> şi <tex> A_{j} </tex> nu pot avea în acelaşi timp valoarea <tex> 0 </tex>, iar dacă membrii sunt $(2i , 2j - 1)$ se poate scrie ca <tex> \\sim A_{i} \\vee A_{j} </tex> astfel <tex> A_{i} </tex> nu poate avea valoarea <tex> 1 </tex> când <tex> A_{j} </tex> are valoarea <tex> 0 </tex>.\r\nExemplul din problemă poate fi scris ca expresia logică în modul următor: <tex> A_{1} \\wedge \\sim A_{1} \\wedge A_{2} \\wedge \\sim A_{2} \\wedge A_{3} \\wedge \\sim A_{3} \\wedge (A_{1} \\vee A_{2}) \\wedge (\\sim A_{1} \\vee \\sim A_{2}) </tex>. \r\nDin nou vom putea folosi cel de al {\'patrulea algoritm\':2-sat#solutie4} explicat pentru a obţine o rezolvare de complexitate $O(N + M)$. \r\n\r\nh2(#excursion). Excursion (Baltic Olympiad in Informatics, 2001)\r\n\r\nbq. Un grup de turişti are ocazia să viziteze mai multe oraşe. Fiecare turist spune două dorinţe ale sale despre ce oraş ar vrea sau nu ar vrea să viziteze. O dorinţă a turistului  va spune despre exact un oraş dacă vrea sau nu vrea să îl viziteze. Este posibil ca ambele dorinţe ale unui turist să exprime acelaşi lucru sau să exprime lucruri opuse (de exemplu „Vreau să vizitez oraşul A!” şi „Nu vreau să vizitez oraşul A!”). Va trebui să determinaţi după citirea cerinţelor celor $n$ turişti despre $m$ oraşe dacă există o mulţime a oraşelor pentru care cel puţin o dorinţă a fiecărui turist este îndeplinită $(1 <= n <= 20 000, 1 <= m <= 8 000)$. De exemplu, să presupunem că avem $3$ turişti, $4$ oraşe şi primul turist are dorinţele de a vizita oraşul întâi şi de a nu vizita oraşul doi, al doilea turist are dorinţele de a vizita oraşul doi şi de a vizita oraşul patru, iar al treilea turist are dorinţele de a vizita oraşul trei şi de a vizita oraşul unu. O soluţie pentru acest exemplu ar fi vizitarea tuturor oraşelor.\r\n\r\nh3. Soluţie\r\n\r\nEste evident că şi această problemă se poate uşor transforma într-o instanţă de $2-SAT$. Fiecare turist ne dă prin dorinţele sale o expresie literală cu doi literali. Vizitarea sau nevizitarea oraşului de index $i$ va fi reprezentată prin variabila booleană <tex> A_{i} </tex>.  Exemplul din problemă poate fi transformat astfel: <tex> (A_{1} \\vee \\sim A_{2}) \\wedge (A_{2} \\vee A_{4}) \\wedge (A_{3} \\vee A_{1}) </tex>.\r\n\r\nh2(#orpath). Orpath (Olimpiadă Rusia)\r\n\r\nbq. Într-o ţară pacifistă, există $N$ oraşe şi $K$ autobuze $(1 <= N, K <= 100)$. La orele aglomerate ale zilei, nu trebuie să existe două autobuze care merg în acelaşi timp în sensuri opuse. Traseul fiecărui autobuz este un ciclu. Spunem că el merge în sens pozitiv dacă va parcurge oraşele în ordinea $1 2 3 4 1 2 3 4 1 2$ ... sau în sens negativ dacă le parcurge în ordinea $1 4 3 2 1 4 3 2 1 4$ ... Găsiţi o posibilitate de atribuire a sensului fiecărui autobuz astfel ca accidentele de trafic să fie evitate (nu vor exista două autobuze care să se întâlnească şi să aibă sensuri de mers opuse). Pentru fiecare autobuz se vor şti oraşele de pe ruta lui, şi pentru fiecare două oraşe vecine pe rută se va şti timpul necesar autobuzului pentru a ajunge dintr-un oraş în altul. De exemplu, pentru $4$ oraşe unde oricare două sunt la timp de mers egal cu $10$, şi pentru două autobuze cu rutele $1 2 4$ şi $3 4 2$, o soluţie ar fi ca primul autobuz să meargă în sens pozitiv iar celălalt în sens negativ.\r\n\r\nh3. Soluţie\r\n\r\nPentru orice două autobuze vom găsi care sunt sensurile de mers pentru ele astfel ca cele două autobuze să nu se întâlnească şi să provoace un accident. Pentru un sens fixat putem afla pentru un autobuz pe ce interval de timp va fi pe o anumită stradă. El va fi în general pe o stradă $(i, j)$ pe un interval de tipul $[t1 + k*T … t2 + k*T]$ unde $t1$ este timpul din prima rută parcursă pentru a ajunge la $i$, $t2$ timpul pentru a ajunge la $j$ iar $T$ este durata totală a unei rute. Acum, pentru a determina dacă două autobuze se vor întâlni pe o rută $(i, j)$ trebuie ca ele să se deplaseze în sensuri opuse pe această rută, iar intervalele lor $[t1 + k*T1 .. t2 + k*T1]$ se intersectează cu intervalele $[tt1 + p*T2 … tt2 + p*T2]$. Este clar acum că putem transforma problema într-o instanţă de $2-SAT$ prin maparea autobuzelor în variabile logice, a sensurilor de mers în valorile $adevărat$ şi $fals$, iar pentru orice pereche de autobuze să fie o propoziţie logică ce ia valoarea $adevărat$ doar dacă sensurile de mers determinate de variabilele logice asociate autobuzelor sunt compatibile. Mai trebuie determinat într-un mod eficient dacă două clase de intervale de timp se intersectează. Aceasta rămâne ca temă cititorului.\r\n\r\nh2(#aladdin). \'Aladdin\':problema/aladdin (Bursele Agora 2005/2006, Runda 1)\r\n\r\nbq. Aladdin, aşa cum ştiaţi, este un mare magnat în afacerea de comercializare a covoarelor magice. Acesta doreşte să o cucerească pe prinţesa Iasmina, iar aceasta, pentru a-i testa inteligenţa îl roagă să îi facă un covor dreptunghiular împărţit în pătrăţele, asemănator unei table de şah cu $N$ linii şi $M$ coloane $(1 <= N, M <= 1000)$. Fiecare pătrăţel de pe covor trebuie colorat cu alb sau cu negru. Pentru fiecare pătrat care conţine $4$ pătrăţele Iasmina pune condiţia să aibă un număr fixat de pătrăţele colorate cu negru. Ajutaţi-l pe Aladdin să realizeze un covor care satisface condiţiile impuse de prinţesa Iasmina!\r\n\r\nh3. Soluţie\r\n\r\nÎntâi, să considerăm un exemplu. Pentru o cerinţă de forma:\r\n\r\ntable{width: 90px; text-align: center}.\r\n| <tex> 3 </tex> | <tex> 2 </tex> | <tex> 3 </tex> |\r\n| <tex> 2 </tex> | <tex> 3 </tex> | <tex> 3 </tex> |\r\n| <tex> 1 </tex> | <tex> 2 </tex> | <tex> 1 </tex> |\r\n\r\nuna din soluţii este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nFie <tex> A </tex> o matrice soluţie a problemei noastre. Vom numerota rândurile matricii de la $0$ la $N - 1$ şi coloanele de la $0$ la $M - 1$. Matricea de intrare <tex> S </tex> reprezintă de fapt sumele din fiecare pătrat de câte $2 x 2$ elemente. Facem observaţia că dacă ştim într-un pătrat de $2 x 2$ valorile pentru trei dintre celule, atunci valoarea din a patra celulă este unic determinată pentru că ştim suma elementelor din pătrat. Vedem astfel, că dacă ştim valorile elementelor din prima linie a matricii <tex> A </tex> şi din prima coloană, restul valorilor sunt unic determinate. \r\nPentru a rezolva problema vom presupune <tex> A[0][0] </tex> cunoscut (de fapt, mai întâi vom rezolva problema presupunând că <tex> A[0][0] = 1 </tex>, iar dacă nu obţinem nicio soluţie vom încerca cu <tex> A[0][0] = 0 </tex>). Vom nota celulele <tex> A[0][1] </tex>, <tex> A[0][2]</tex>, … <tex> A[0][M - 1] </tex> cu <tex> x_{1} </tex>, <tex> x_{2} </tex>, … <tex> x_{M-1} </tex> iar celulele <tex> A[1][0] </tex>, <tex> A[2][0] </tex>, … <tex> A[N - 1][0] </tex> cu <tex> y_{1} </tex>, <tex> y_{2} </tex>, … <tex> y_{N-1} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> A[0][0] </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> ... </tex> | <tex> x_{M-1} </tex> |\r\n| <tex> y_{1} </tex> | <tex> 1 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n| <tex> y_{2} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 0 </tex> |\r\n| ... | ... | ... | ... | ... |\r\n| <tex> y_{N-1} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n\r\nAcum, pentru fiecare celulă putem demonstra prin inducţie că <tex> A[i][j] = (-1)^i x_{j} + (-1)^j y_{i} + b[i][j] </tex>. Unde <tex> b[i][j] </tex> sunt nişte constante ce sunt calculate în funcţie de matricea primită la intrare.\r\nEste uşor de observat că dacă:\r\n<tex> A[i-1][j] = (-1)^{(i-1)} x_{j} + (-1)^j y_{i-1} + b[i-1][j] </tex>, \r\n<tex> A[i-1][j-1] = (-1)^{(i-1)} x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i-1][j-1] </tex>, \r\n<tex> A[i][j-1] = (-1)^i x_{j-1} + (-1)^{(j-1)} y_{i} + b[i][j-1] </tex>, \r\n\r\natunci:\r\n\r\n<tex> A[i][j] = S[i-1][j-1] - A[i-1][j] - A[i][j-1] - A[i-1][j-1] = </tex> \r\n<tex> = S[i-1][j-1] - ((-1)^{(i-1)} x_{j} + (-1)^j y_{i-1} + b[i-1][j]) - </tex> <tex> ((-1)^{(i-1)} x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i-1][j-1]) - ((-1)^i x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i][j-1]) = </tex> \r\n<tex> = (-1)^i x_{j} - (-1)^j y_{i-1} + (-1)^i x_{j-1} + (-1)^j y_{i-1} - </tex> <tex> (-1)^i x_{j-1} + (-1)^j y_{i} + S[i-1][j-1] - b[i-1][j] - b[i][j-1] - b[i-1][j-1] = </tex> \r\n<tex> = (-1)^i x_{j} + (-1)^j y_{i} + b[i][j] </tex>. \r\n\r\nDe aici concluzionăm că <tex> b[i][j] = S[i-1][j-1] - b[i-1][j] - b[i][j-1] - b[i-1][j-1] \\ (*)</tex>.\r\n\r\nAvem un sistem format din inecuaţiile:\r\n\r\n<tex> 0 \\le x_{j} \\le 1 </tex>\r\n<tex> 0 \\le y_{i} \\le 1 </tex>\r\n<tex> -b[i][j] \\le (-1)^i x_{j} + (-1)^j y_{i} \\le 1 - b[i][j] </tex>\r\n\r\nEste uşor acum să transformăm acest sistem într-o formulă booleană în {\'formă normal conjunctivă\':2-sat#forme-normale} în care fiecare expresie are cel mult $2$ literali. Fiecare relaţie o putem înmulţi sau nu cu $-1$ astfel ca părţile constante ale relaţiei să fie pozitive. Observăm că <tex> | b[i][j] | \\le 2 </tex>, altfel nu avem soluţie. Dacă <tex> | b[i][j] | = 2 </tex> atunci ambele variabile au valori fixe, iar dacă <tex> | b[i][j] | = 1 </tex> sau <tex> | b[i][j] | = 0 </tex> atunci relaţia o putem scrie ca o disjuncţie logică cu doi literali.\r\n\r\nO relaţie precum <tex> 0 \\le x + y \\le 1 </tex> poate fi tansformată logic în <tex> \\sim x \\vee \\sim y </tex>, astfel <tex> x </tex> şi <tex> y </tex> nu vor fi în acelaşi timp <tex> 1 </tex>, una de genul <tex> 1 \\le x + y \\le 2 </tex> va fi transformată în <tex> (x \\vee y) </tex>, astfel cel puţin <tex> x </tex> sau <tex> y </tex> va fi egal cu <tex> 1 </tex>, alta de tipul <tex> 0 \\le x - y \\le 1 </tex> poate fi scrisă ca <tex> x \\vee \\sim y </tex>, una de tipul <tex> 2 \\le x + y \\le 3 </tex> în <tex> x \\wedge y </tex>, iar una de tipul <tex> 0 \\le -x -y \\le 1 </tex> în <tex> \\sim x \\wedge \\sim y </tex>, una de tipul <tex> 1 \\le x - y  \\le 2 </tex> în <tex> x \\wedge \\sim y </tex>.\r\n\r\nAstfel am redus problema la rezolvarea unei instanţe de $2-SAT$. Avem $N+M-1$ necunoscute şi {$(N-1)$}{$(M-1)$} propoziţii. Folosind a treia metodă de rezolvare vom obţine un algoritm de complexitate $O(N * M)$ care soluţionează problema noastră.\r\n\r\nSă vedem cum merge acestă rezolvare pe exemplul din problemă:\r\n\r\nAlegem <tex> A[0][0] = 1 </tex>. Necunoscutele vor fi <tex> x_{1} </tex>, <tex> x_{2} </tex>, <tex> x_{3} </tex> şi <tex> y_{1} </tex>, <tex> y_{2} </tex>, <tex> y_{3} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> x_{3} </tex> |\r\n| <tex> y_{1} </tex> | <tex> A[1][1] </tex> | <tex> A[1][2] </tex> | <tex> A[1][3] </tex> |\r\n| <tex> y_{2} </tex> | <tex> A[2][1] </tex> | <tex> A[2][2] </tex> | <tex> A[2][3] </tex> |\r\n| <tex> y_{3} </tex> | <tex> A[3][1] </tex> | <tex> A[3][2] </tex> | <tex> A[3][3] </tex> |\r\n\r\nFolosind recurenţa <tex> (*) </tex> obţinem că matricea <tex> b </tex> este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 2 </tex> | <tex> 0 </tex> | <tex> 3 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> -1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n\r\nDe aici obţinem sistemul de inegalităţi:\r\n\r\n<tex> 0 \\le x_{1} \\le 1,  0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le 1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, -2 \\le -x_{1} - y_{1} \\le -1, 0 \\le -x_{2} + y_{1} \\le 1, -3 \\le -x_{3} - y_{1} \\le -2, </tex>\r\n<tex> 0 \\le y_{2} \\le 1,  0 \\le  x_{1} - y_{2} \\le  1,-1 \\le  x_{2} + y_{2} \\le 0,  1 \\le  x_{3} - y_{2} \\le  2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, -1 \\le -x_{1} - y_{3} \\le  0, 0 \\le -x_{2} + y_{3} \\le 1, -1 \\le -x_{3} - y_{3} \\le  0 </tex>\r\n\r\nTransformăm relaţiile astfel ca să nu apară nici o constantă negativă:\r\n\r\n<tex> 0 \\le x_{1} < = 1, 0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le  1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, 1 \\le x_{1} + y_{1} \\le 2, 0 \\le -x_{2} + y_{1} \\le 1, 2 \\le x_{3} + y_{1} \\le 3, </tex>\r\n<tex> 0 \\le y_{2} \\le 1, 0 \\le x_{1} - y_{2} \\le 1, 0 \\le -x_{2} - y_{2} \\le 1, 1 \\le x_{3} - y_{2} \\le 2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, 0 \\le x_{1} + y_{3} \\le 1, 0 \\le -x_{2} + y_{3} \\le 1, 0 \\le x_{3} + y_{3} \\le 1 </tex>\r\n\r\nAcest sistem poate fi transformat într-o expresie booleană:\r\n\r\n<tex> (x_{1} \\vee y_{1}) \\wedge (\\sim x_{2} \\vee y_{1}) \\wedge (x_{3} \\wedge y_{1}) \\wedge </tex>\r\n<tex> (x_{1} \\vee \\sim y_{2}) \\wedge (\\sim x_{2} \\wedge \\sim y_{2}) \\wedge (x_{3} \\wedge \\sim y_{2}) \\wedge </tex>\r\n<tex> (\\sim x_{1} \\vee \\sim y_{3}) \\wedge (\\sim x_{2} \\vee y_{3}) \\wedge (\\sim x_{3} \\vee \\sim y_{3}) </tex>.\r\n\r\nAcestă expresie e satisfăcută de valorile: <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 1, y_{1} = 1, y_{2} = 0, y_{3} = 0 \\rangle </tex>, iar de aici putem determina o soluţie a problemei noastre iniţiale ca fiind:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nh2(#bibliografie). Bibliografie:\r\n\r\n* [1] \'\"Introducere in algoritmi\"\':http://zhuzeyuan.hp.infoseek.co.jp/ita/toc.htm, T. H. Cormen, C. E. Leiserson, R. R. Rivest\r\n* [2] \'Satisfiability\':http://en.wikipedia.org/wiki/Satisfiability, Wikipedia\r\n* [3] \"BOI\'01 Competition material\":http://www.oi.edu.pl/download/boi-2001.pdf\r\n* [4] \"CEOI\'02 Competition material\":http://ics.upjs.sk/ceoi/\r\n',3146,'public',NULL,NULL),('2-sat','Problema satisfiabilităţii formulelor logice de ordinul doi','2008-12-09 15:55:03','2008-12-14 17:42:20','h1. Problema satisfiabilităţii formulelor logice de ordinul doi\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 37em}*{text-align:center} *Conţinut:*\r\n* {\'Introducere\':2-sat#introducere}\r\n* {\'Forme normale ale formulelor logice\':2-sat#forme-normale}\r\n* {\'SAT, 3-SAT, 2-SAT\':2-sat#overview-sat}\r\n* {\'Soluţii pentru 2-SAT\':2-sat#solutii-2-sat}\r\n** {\'Soluţie $O(M * 2^N^)$\':2-sat#solutie1}\r\n** {\'Soluţie $O(N * M)$\':2-sat#solutie2}\r\n** {\'Soluţie $O(N^2^)$\':2-sat#solutie3}\r\n** {\'Soluţie $O(M + N)$\':2-sat#solutie4}\r\n* {\'Aplicaţii\':2-sat#aplicatii}\r\n** {\'Party &#40;preOni 2003/2004&#41;\':2-sat#party}\r\n** {\'Cigraf\':2-sat#cigraf}\r\n** {\'Peace Commission &#40;Polish Olympiad in Informatics, 2001&#41;\':2-sat#peace-commission}\r\n** {\'Excursion &#40;Baltic Olympiad in Informatics, 2001&#41;\':2-sat#excursion}\r\n** {\'Orpath &#40;Olimpiadă Rusia&#41;\':2-sat#orpath}\r\n** {\'Aladdin &#40;Bursele Agora 2005/2006, Runda 1&#41;\':2-sat#aladdin}\r\n* {\'Bibliografie\':2-sat#bibliografie}\r\n\r\nh2(#introducere). Introducere\r\n\r\nProblema satisfiabilităţii, notată prescurtat cu $SAT$, cere determinarea existenţei pentru o formulă booleană <tex> \\phi </tex> a unei artibuiri satisfiabile. O formulă booleană <tex> \\phi </tex> este compusă din $variabile$ logice <tex> (x_{1}, x_{2}, ...) </tex>, $operatori$ logici ( <tex> \\wedge </tex> şi,  <tex> \\vee </tex> sau, <tex> \\sim </tex> non, <tex> \\rightarrow </tex> implicaţie şi <tex> \\leftrightarrow </tex> echivalenţă), şi $paranteze$. O atribuire de valori booleene pentru variabilele acestei expresii se numeşte $atribuire satisfiabilă$ dacă evaluarea expresiei după atribuirea valorilor dă ca rezultat valoarea de adevăr $adevărat$. De acum încolo vom folosi pentru simplitate valorile <tex> 1 </tex> şi <tex> 0 </tex> în loc de $adevărat$ şi $fals$.\r\n\r\nUn exemplu de formulă ar fi <tex> \\phi = ((x_{1} \\rightarrow x_{2}) \\vee \\sim((\\sim x_{1} \\leftrightarrow x_{3}) \\vee x_{4})) \\wedge \\sim x_{2} </tex>. Aceasta are atribuirea satisfiabilă <tex> \\langle x_{1} = 0, x_{2} = 0, x_{3} = 1, x_{4} = 1 \\rangle </tex> pentru că <tex> \\phi = ((0 \\rightarrow 0) \\vee \\sim((\\sim 0 \\leftrightarrow 1) \\vee 1)) \\wedge \\sim 0 = (1 \\vee \\sim (1 \\vee 1)) \\wedge 1 = (1 \\vee 0) \\wedge 1 = 1</tex>. \r\n\r\nh2(#forme-normale). Forme normale ale formulelor logice\r\n\r\nOrice formulă booleană poate fi transformată în două forme:\r\n\r\n* $Forma normal conjunctivă$ în care expresia este exprimată ca o conjuncţie de propoziţii, iar fiecare propoziţie este formată din o disjuncţie de $literali$. Un $literal$ este o variabilă care poate fi sau nu negată. Un exemplu de expresie în forma normal conjunctivă ar fi: <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) \\wedge (x_{3} \\vee x_{2} \\vee x_{4}) \\wedge (\\sim x_{1} \\vee \\sim x_{3} \\vee \\sim x_{4}) </tex> care are pe <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) </tex> ca primă propoziţie cu literalii <tex> x_{1} </tex>, <tex> \\sim x_{1} </tex>, <tex> \\sim x_{2} </tex>.\r\n\r\n* $Forma normal disjunctivă$ este formată ca o disjuncţie de propoziţii, fiecare dintre aceste propoziţii fiind o conjuncţie de literali. Un exemplu de o asemenea formulă ar fi următoarea: <tex> (x_{1} \\wedge x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge \\sim x_{3}) \\vee (\\sim x_{1} \\wedge x_{2} \\wedge \\sim x_{2}) </tex>.\r\n\r\nh2(#overview-sat). SAT, 3-SAT, 2-SAT\r\n\r\nProblema $SAT$ este $NP-completă$. Defapt, este prima problemă $NP-completă$ găsită. Stephen Cook a demonstrat $NP-completitudinea$ ei în 1971. Pe vremea aceea nu se ştia nici măcar că problemele $NP-complete$ există. Această problemă rămâne $NP-completă$ chiar dacă restricţionăm expresiile la unele care în forma normal conjunctivă au doar trei literali. Problema satisfiabilităţii pentru asemenea expresii se numeşte $3-SAT$, şi multe probleme pot fi demonstrate a fi $NP-complete$ prin reducerea la această problemă. Din fericire, problema $2-SAT$, adică cea pentru care în fiecare propoziţie există doar $2$ literali se poate rezolva eficient. Restul articolului va prezenta trei metode de rezolvare a problemei $2-SAT$ şi câteva aplicaţii ale acesteia la concursuri de programare.\r\n\r\nh2(#solutii-2-sat). Soluţii pentru 2-SAT\r\n\r\nUn exemplu de problemă $2-SAT$ ar fi satisfiabilitatea formulei <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Această formulă este satisfăcută de valorile <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>. Pentru a satisface întreaga expresie trebuie ca în fiecare propoziţie cel puţin unul din cei doi literali să aibă valoarea de adevăr <tex> 1 </tex>.\r\n\r\nh3(#solutie1). Soluţie $O(M * 2^N^)$\r\n\r\nO primă metodă de rezolvare ar fi să încercăm toate cele $2^N^$ posibilităţi de atribuire posibilă, dar această metodă are ordinul de complexitate $O(M * 2^N^)$ şi este eficientă doar pentru instanţe mici ale problemei.\r\n\r\nh3(#solutie2). Soluţie $O(N * M)$\r\n\r\nUrmătoarea soluţie pare trivială, dar găsirea acestui algoritm şi realizarea faptului că el rezolvă corect problema este mai grea decât impresia lăsată după citirea ei. Considerăm o propoziţie oarecare cu două variabile $p$ şi $q$, apoi una dintre ele, de exemplu $p$. Dacă literalul în care apare $p$ este negat atunci îi atribuim valoarea $1$. Pentru ca propoziţia respectivă să aibă $1$ valoarea de adevăr atunci valoarea lui $q$ este fixată. Fixând şi valoarea lui $q$, probabil şi alte propoziţii ce conţin literalul $q$ vor avea celălalt literal fixat. Propagăm astfel o serie de schimbări. După ce toate schimbările forţate au fost făcute propoziţiile rezultate vor fi de următoarele tipuri: <tex> a \\vee b </tex>, <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex>. Propoziţii de tip <tex> 0 \\vee b </tex> nu pot apărea pentru că toate schimbările forţate au fost deja propagate. Dacă apare o propoziţie <tex> 0 \\vee 0 </tex> atunci alegerea făcută pentru valoarea lui $p$ este greşită. Vom încerca şi alegerea opusă. Dacă ambele duc la o propoziţie de tip <tex> 0 \\vee 0 </tex> atunci expresia nu poate fi satisfăcută. Propoziţiile de forma <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex> pot fi ignorate. În acest fel am eliminat cel puţin o variabilă şi o propoziţie din expresie. Dacă expresia iniţială era satisfiabilă, atunci şi expresia din care s-au eliminate câteva propoziţii a rămas satisfiabilă. Continuând pe această idee obţinem un algoritm de complexitate $O(N * M)$, pentru că la fiecare atribuire de valoare pentru o variabilă parcurgem şirul de propoziţii o dată. \r\n\r\nSă vedem cum funcţionează algoritmul pentru expresia: <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Considerăm propoziţia <tex> (x_{1} \\vee \\sim x_{2}) </tex> şi <tex> \\langle x_{2} = 1 \\rangle </tex>. Astfel, vom obţine mai departe <tex> (x_{1} \\vee 0) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee 1) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. În propoziţia <tex> (x_{1} \\vee 0) </tex> <tex> x_{1} </tex> trebuie să fie egal cu <tex> 1 </tex>. Acum, expresia devine: <tex> (0 \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee 0) </tex>. Din propoziţia <tex> (0 \\vee \\sim x_{3}) </tex> obţinem <tex> \\langle x_{3} = 0 \\rangle </tex>, iar din <tex> (x_{4} \\vee 0) </tex> obţinem <tex> \\langle x_{4} = 1 \\rangle </tex>. Deci, atribuirea satisfiabilă este <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>.\r\n\r\nh3(#solutie3). Soluţie $O(N^2^)$\r\n\r\nO altă soluţie elegantă se bazează pe o metodă randomizată:\r\n\r\n== code(cpp) |\r\natribuim valori booleene arbitrare variabilelor;\r\ncât timp expresia nu este satisfăcută execută\r\n    găsim o propoziţie cu valoarea de adevăr 0;\r\n    schimbăm valoarea de adevăr a oricăreia dintre cele două variabile prezente în propoziţie;\r\nsfcâttimp\r\n==\r\n\r\nLinia $4$ va face ca acea propoziţie să aibă noua valoare de adevăr <tex> 1 </tex>.\r\n\r\nDe ce ar merge acest algoritm? Să presupunem că există o soluţie a problemei, o notăm cu <tex> S </tex>, iar cu <tex> X </tex> notăm şirul valorilor curente ale variabilelor. Ne uităm la fiecare pas al algoritmului la numărul de variabile care au valori diferite în soluţie faţă de cele din <tex> X </tex> (acest număr de diferenţe între elementele de acelaşi index pentru două şiruri se mai numeşte şi \'distanţă Hamming\':http://en.wikipedia.org/wiki/Hamming_distance între şiruri). Fie această valoare la pasul current $K$. Noi am vrea să avem $K = 0$. Cum va evolua $K$ pe parcursul algoritmului? La un moment dat noi schimbăm valoarea unei variabile luate aleator dintr-o propoziţie nesatisfăcută. Pentru că în <tex> S </tex> propoziţia este satisfăcută, înseamnă că cel puţin una dintre cele două variabile ale propoziţiei are valori diferite în <tex> X </tex> faţă de <tex> S </tex>. Astfel, operaţia făcută de noi are probabilitate de cel puţin $0.5$ să ne aducă mai aproape de soluţie. Vom nota cu <tex> T(i) </tex> numărul probabil de paşi în care un şir <tex> X </tex> aflat la distanţa Hamming egală cu $i$ faţă de <tex> S </tex>, va fi transformat în <tex> S </tex>. Evident:\r\n\r\n<tex> T(0) = 0 </tex>.\r\n\r\n<tex> T(i) \\le (T(i + 1) + T(i - 1)) / 2 + 1 </tex> pentru $0 < i < N$ ({$N$} e numărul de variabile booleene ale expresiei)\r\n\r\nSe pune semnul de inegalitate pentru că ambele variabile pot avea valori diferite faţă de cele din soluţie, deci schimbarea valorii oricăreia ar putea să ne aducă mai aproape de soluţie.\r\n\r\nPentru că dacă toate variabilele diferă de soluţie, orice schimbare ne aduce mai aproape de soluţie:\r\n\r\n<tex> T(N) = T(N - 1) + 1 </tex>\r\n\r\nNe interesează numai limitele superioare, deci folosim doar egalităţi în loc de inegalităţi:\r\n\r\n<tex> X(0) = 0, X(i) = (X(i + 1) + X(i - 1))/2 + 1, X(N) = X(N - 1) + 1 </tex>\r\n\r\nDacă adunăm toate ecuaţiile obţinem:\r\n\r\n<tex> X(0) + X(1) + ... + X(N) </tex> <tex> = (X(0) + X(1) + 2X(2) + ... + 2X(N - 2) + X(N - 1) + X(N))/2 + X(N) + N-1 </tex>\r\n\r\nDe aici avem că <tex> (X(1) + X(N - 1) - X(N)) / 2 = N - 1 </tex>, din <tex> X(N) = X(N - 1) + 1 </tex> avem <tex> X(1) = 2N - 1 </tex>. Mai departe avem că <tex> X(2) = 4n - 2 ... X(i) = 2iN - i </tex> de unde, când <tex> i = N </tex> avem că <tex> X(N) = 2N^2 - N </tex>.\r\n\r\nAstfel, numărul mediu de paşi ai algoritmului este $2N^2^ - N$ iar dacă aplicăm algoritmul în mod aleator de mai multe ori avem o probabilitate foarte mare să ajungem la rezultat.\r\n\r\nh3(#solutie4). Soluţie $O(M + N)$\r\n\r\nO a treia soluţie se bazează pe relaţia de implicaţie. Relaţia <tex> \\rightarrow </tex> are următoarea tabelă de adevăr:\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> A \\rightarrow B </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nRelaţia de implicaţie are semnificaţia dacă <tex> A </tex> este adevărat atunci şi <tex> B </tex> este adevărat. Scriem tabelul expresiei <tex> \\sim A \\vee B </tex> şi observăm că acesta este egal cu cel al relaţiei de implicaţie.\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> \\sim A \\vee B </tex>|\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nFiecare clauză <tex> A \\vee B </tex> poate fi scrisă ca două implicaţii <tex> \\sim A \\rightarrow B </tex> şi <tex> \\sim B \\rightarrow A </tex>. Realizăm un graf al implicaţiilor. Astfel, nodurile grafului vor fi variabilele <tex> A </tex>, <tex> B </tex> ... şi negaţiile lor <tex> \\sim A </tex>, <tex> \\sim B </tex> ... iar muchiile acestui graf vor fi implicaţiile echivalente cu propoziţiile din expresie. Deci, dacă expresia are $M$ propoziţii graful va avea $2M$ muchii. Acestea fiind zise, expresiei <tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) </tex> îi corespunde graful:\r\n\r\np=. !2-sat?Graf.png!\r\n\r\nDacă avem <tex> A \\longrightarrow B </tex> o muchie în graful nostru, atunci dacă literalul <tex> A </tex> este adevărat atunci şi literalul <tex> B </tex> trebuie să fie adevărat pentru ca propoziţia reprezentată de muchie să fie satisfăcută. Putem demonstra prin inducţie că dacă există un drum în graf de la literalul <tex> A </tex> la literalul <tex> B </tex>, atunci dacă <tex> A </tex> este adevărat şi <tex> B </tex> trebuie să fie adevărat. Dacă există un drum de la un literal <tex> X </tex> la <tex> \\sim X </tex> atunci nu va exista soluţie pentru că nu putem seta în acelaşi timp o variabilă şi valoarea ei negată la valoarea adevărat. De aici rezultă că dacă în graful asociat expresiei există o variabilă <tex> X </tex> în aceiaşi componentă tare conexă cu <tex> \\sim X </tex> atunci instanţa problemei satisfiabilităţii nu poate fi satisfăcută. Dacă nu există o asemenea variabilă, vom vedea în continuare cum putem rezolva problema. Întâi, facem observaţia că dacă în graf există muchia <tex> A \\longrightarrow B </tex> atunci există şi muchia <tex> \\sim B \\longrightarrow \\sim A </tex>. Astfel, dacă există un drum de la <tex> A </tex> la <tex> B </tex> în graf, aplicând proprietatea menţionată pentru fiecare muchie a drumului, vom găsi un drum de la <tex> \\sim B </tex> la <tex> \\sim A </tex>. Evident, afirmaţia este valabilă şi reciproc: dacă există drum de la <tex> B </tex> la <tex> A </tex> atunci vom avea un drum de la nodul <tex> \\sim A </tex> la <tex> \\sim B </tex>. Astfel, dacă avem că <tex> A </tex> şi <tex> B </tex> sunt în aceeaşi componentă tare conexă atunci şi nodurile <tex> \\sim A </tex> şi <tex> \\sim B </tex> sunt în aceeaşi componentă tare conexă. Deci, dacă nu există doi literali <tex> X </tex> şi <tex> \\sim X </tex> în aceeaşi componentă tare conexă, putem să împărţim graful în componente tari conexe şi să împerechem componentele câte două astfel ca în fiecare pereche să apară o componentă <tex> U </tex> cu nişte literali şi altă componentă <tex> \\sim U </tex> cu aceiaşi literali negaţi. Pentru a găsi o soluţie vom determina mai întâi componentele tari conexe ale grafului. Apoi putem contracta fiecare componentă într-un nod. Graful obţinut va fi acciclic. Alegem un nod <tex> u </tex> în care nu intră nicio muchie (un asemenea nod trebuie să existe pentru a nu exista cicluri), din considerente de simetrie, din nodul lui pereche <tex> \\sim u </tex> nu va ieşi nicio muchie. Literalilor componentei <tex> U </tex> putem să le dăm valoarea de adevăr <tex> 0 </tex>, iar literalilor din componenta pereche <tex> \\sim U </tex>  putem să le dăm valoarea de adevăr <tex> 1 </tex>. Această alegere nu impune restricţii asupra celorlalţi literali şi elimină câteva variabile din problemă. Repetarea recursivă a acestui pas pe graful rămas va duce la rezolvarea problemei. Determinarea componentelor tari conexe se poate face în complexitatea $O(N + M)$. Pentru a vedea acest algoritm puteţi consulta secţiunea \'$23.5$ din [1]\':http://zhuzeyuan.hp.infoseek.co.jp/ita/chap23.htm. Iar eliminarea  nodurilor de care vorbeam mai sus se poate face în $O(N + M)$ folosind o \'sortare topologică\':problema/sortaret. \r\n\r\nSă urmărim cum merge algoritmul nostru pe exemplul de mai sus. Componentele tari conexe sunt următoarele: <tex> \\{A\\} </tex>, <tex> \\{\\sim A\\} </tex>, <tex> \\{B, C, \\sim D\\} </tex>, <tex> \\{\\sim B, \\sim C, D\\} </tex>. În nodul asociat componentei <tex> \\{A\\} </tex> nu intră nici o muchie. Astfel, putem să îi atribuim lui <tex> A </tex> valoarea <tex> 0 </tex>, iar în nodul asociat componentei <tex> \\{\\sim B, \\sim C, D\\} </tex> nu intră nicio muchie, deci putem să îi atribuim lui <tex> B </tex> valoarea <tex> 1 </tex>, lui <tex> C </tex> valoarea <tex> 0 </tex> şi lui <tex> D </tex> valoarea <tex> 1 </tex>. Această atribuire este satisfiabilă după cum vedem în continuare:\r\n\r\n<tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) </tex> <tex> = (\\sim 0 \\vee \\sim 1) \\wedge (1 \\vee \\sim 1) \\wedge (1 \\vee 1) \\wedge (\\sim 1 \\vee \\sim 0) \\wedge (1 \\vee 0) </tex> <tex> = 1 \\wedge 1 \\wedge 1 \\wedge 1 \\wedge 1 = 1 </tex>\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\nRestul articolului va prezenta aplicaţii ale problemei $2-SAT$ la concursurile de programare.\r\n\r\nh2(#party). \'Party\':problema/party (preOni 2003/2004)\r\n\r\nbq. George vrea să îşi organizeze majoratul, şi vrea ca petrecerea să fie de neuitat, mâncarea, băutura, locaţia şi sonorizarea sunt deja asigurate, mai rămâne problema chemării prietenilor. El şi cu prietenul lui cel mai bun Lucian au preferinte diferite şi pentru a nu se certa au pus la punct o listă de cerinţe care vor trebui să fie îndeplinite astfel încât cheful să se desfăşoare în cele mai bune condiţii! Pentru uşurinţă,  prietenii lui George vor fi indentificaţi prin numere întregi de la $1$ la $N (1 ≤ N ≤ 100)$ şi cerinţele în număr de $M  (1 ≤ M ≤ 1.000)$ vor fi de tipurile 0, 1, 2 sau 3. O cerinţă de genul <tex> x \\ y </tex> 0 are semnificaţia că <tex> x </tex> sau <tex> y </tex> trebuie să participe la petrecere; <tex> x \\ y </tex> 1 are semnificaţia că dacă <tex> x </tex> participă nu există nici o restricţie pentru <tex> y </tex>, dar dacă <tex> x </tex> nu participă atunci nici <tex> y </tex> nu participa; <tex> x \\ y </tex> 2 are semnificaţia simetrică cu cerinţa 1; iar cerinţa <tex> x \\ y </tex> 3 are semnificaţia că cel puţin unul dintre <tex> x </tex> şi <tex> y </tex> nu participă la petrecere. Scrieţi un program care să-i ajute pe cei doi să determine care persoane vor fi invitate la petrecere. Se garantează că va fi posibilă întotdeauna organizarea unei petreceri!\r\n\r\nh3. Soluţie\r\n\r\nAceastă problemă este inspirită din o problemă de la $CEOI 2002$ şi este evident că ne cere să determinăm o atribuire satisfiabilă pentru o formulă logică formată ca conjuncţie între cerinţele care se transformă astfel:\r\n\r\n* cerinţa de tip 0 corespunde propoziţiei <tex> x \\vee y </tex>;\r\n* cerinţa de tip 1 corespunde propoziţiei <tex> x \\vee \\sim y </tex>;\r\n* cerinţa de tip 2 corespunde propoziţiei <tex> \\sim x \\vee y </tex>;\r\n* cerinţa de tip 3 corespunde propoziţiei <tex> \\sim x \\vee \\sim y </tex>.\r\n\r\nUna din primele două rezolvări ar fi putut soluţiona această problemă, dar problema de la $CEOI$ avea limite mai mari şi pentru rezolvarea ei ar fi trebuit un algoritm de complexitate $O(N + M)$.\r\n\r\nh2(#cigraf). Cigraf\r\n\r\n_Autor: Mugurel Ionuţ Andreica_\r\n\r\nbq. Se dă un graf neorientat cu $N (1 <= N <= 1000)$ noduri şi $M (0 <= M <= N*(N-1)/2)$ muchii. Se doreşte împărţirea nodurilor acestui graf în $2$ mulţimi, <tex> C </tex> şi <tex> I </tex>, având următoarele proprietăţi: fiecare nod face parte din exact una din cele $2$ mulţimi, există muchie între oricare $2$ noduri din mulţimea <tex> C </tex>, nu există nicio muchie între $2$ noduri din mulţimea <tex> I </tex>. Este posibil ca una dintre cele $2$ mulţimi să fie vidă. Soluţia nu este neaparat unică. Numele celor două mulţimi provin de la $clică$ şi $mulţime independentă$. De exemplu, pentru graful de $6$ noduri ce are muchiile <tex> \\{\\{1, 4\\}, \\{4, 6\\}, \\{6, 1\\}, \\{2, 4\\}, \\{2, 6\\}, \\{3, 4\\}, \\{1, 3\\}\\} </tex> o împărţire posibilă ar fi <tex> C = \\{1, 4, 6\\} </tex>, <tex> I = \\{2, 3, 5\\} </tex>.\r\n\r\nh3. Soluţie\r\n\r\nDacă între două noduri există muchie atunci nu pot fi amândouă în mulţimea <tex> I </tex>, iar dacă între două noduri nu există muchie nu pot fi amândouă în mulţimea <tex> C </tex>. \r\nTransformăm această problemă într-o instanţă de $2-SAT$ astfel: faptul că nodul <tex> x </tex> aparţine mulţimii <tex> C </tex> îl reprezentăm dândui lui <tex> x </tex> valoarea <tex> 1 </tex>, iar apartenenţa mulţimii <tex> I </tex> se codifică prin valoarea <tex> 0 </tex>. Acum existenţa unei muchii <tex> (x, y) </tex> corespunde expresiei <tex> x \\vee y </tex>, astfel cel puţin unul din nodurile <tex> x </tex> şi <tex> y </tex> nu va fi în mulţimea <tex> I </tex>. Dacă nu există muchia <tex> (x, y) </tex> putem scrie <tex> \\sim x \\vee \\sim y </tex>, această expresie va fi adevărată dacă cel puţin un nod din cele două nu va fi în mulţimea <tex> C </tex>.\r\nAceastă soluţie este liniară ca şi complexitate în numărul de elemente citite la intrare.\r\n\r\nh2(#peace-commission). Peace Commission (Polish Olympiad in Informatics, 2001)\r\n\r\nbq. Comisia Publică a Păcii trebuie să fie compusă în parlamentul Republicii Democrate a ţării Byteland după regulile impuse de Legea Foarte Importantă. Din păcate, unul dintre obstacole este acela că unii deputaţi nu se înţeleg cu ceilalţi. Comisia trebuie realizată astfel ca următoarele condiţii să fie îndeplinite: fiecare partid trebuie să aibă exact un reprezentant în comisie; dacă doi deputaţi nu se înţeleg, ei nu pot fi ambii membrii ai comisiei. Fiecare partid are exact doi deputaţi în parlament. Toţi număraţi de la $1$ până la $2n (1 <= n <= 8000)$. Deputaţii cu numerele $2i-1$ şi $2i$ aparţin celui de al $i$-lea partid. Se vor da $m (0 <= m <= 20 000)$ perechi de deputaţi <tex> (a, b) </tex> care nu se înţeleg. Se cere realizarea unei comisii dacă acest lucru este posibil. Un exemplu ar fi pentru trei partide şi perechile <tex> (1, 3) </tex> şi <tex> (2, 4) </tex> care nu se înţeleg comisia alcătuită din membrii <tex> \\{1, 4, 5\\} </tex>.\r\n\r\nh3. Soluţie\r\n\r\nFiecărui partid îi vom asocia o variabilă; variabila va lua valoarea <tex> 1 </tex> dacă membrul $2i - 1$ al partidului va aparţine comisiei şi valoarea <tex> 0 </tex> dacă membrul $2i$ va aparţine comisiei. Pentru ca din partidul $x$ să existe exact un membru în expresie introducem  <tex> A_{x} \\wedge \\sim A_{x} </tex>. \r\nPutem exprima că doi membrii ai parlamentului $(2i, 2j)$ nu se înţeleg prin expresia logică <tex> \\sim A_{i} \\vee \\sim A_{j} </tex>. Astfel nu pot ambele variabile <tex> A_{i} </tex> şi <tex> A_{j} </tex> să aibă în acelaşi timp valoarea <tex> 1 </tex> adică $2i$ şi $2j$ nu pot face parte în acelaşi timp din comisie. Dacă cei doi membrii sunt $(2i - 1, 2j - 1)$ atunci îi putem codifica prin expresia <tex> A_{i} \\vee A_{j} </tex> astfel <tex> A_{i} </tex> şi <tex> A_{j} </tex> nu pot avea în acelaşi timp valoarea <tex> 0 </tex>, iar dacă membrii sunt $(2i , 2j - 1)$ se poate scrie ca <tex> \\sim A_{i} \\vee A_{j} </tex> astfel <tex> A_{i} </tex> nu poate avea valoarea <tex> 1 </tex> când <tex> A_{j} </tex> are valoarea <tex> 0 </tex>.\r\nExemplul din problemă poate fi scris ca expresia logică în modul următor: <tex> A_{1} \\wedge \\sim A_{1} \\wedge A_{2} \\wedge \\sim A_{2} \\wedge A_{3} \\wedge \\sim A_{3} \\wedge (A_{1} \\vee A_{2}) \\wedge (\\sim A_{1} \\vee \\sim A_{2}) </tex>. \r\nDin nou vom putea folosi cel de al {\'patrulea algoritm\':2-sat#solutie4} explicat pentru a obţine o rezolvare de complexitate $O(N + M)$. \r\n\r\nh2(#excursion). Excursion (Baltic Olympiad in Informatics, 2001)\r\n\r\nbq. Un grup de turişti are ocazia să viziteze mai multe oraşe. Fiecare turist spune două dorinţe ale sale despre ce oraş ar vrea sau nu ar vrea să viziteze. O dorinţă a turistului  va spune despre exact un oraş dacă vrea sau nu vrea să îl viziteze. Este posibil ca ambele dorinţe ale unui turist să exprime acelaşi lucru sau să exprime lucruri opuse (de exemplu „Vreau să vizitez oraşul A!” şi „Nu vreau să vizitez oraşul A!”). Va trebui să determinaţi după citirea cerinţelor celor $n$ turişti despre $m$ oraşe dacă există o mulţime a oraşelor pentru care cel puţin o dorinţă a fiecărui turist este îndeplinită $(1 <= n <= 20 000, 1 <= m <= 8 000)$. De exemplu, să presupunem că avem $3$ turişti, $4$ oraşe şi primul turist are dorinţele de a vizita oraşul întâi şi de a nu vizita oraşul doi, al doilea turist are dorinţele de a vizita oraşul doi şi de a vizita oraşul patru, iar al treilea turist are dorinţele de a vizita oraşul trei şi de a vizita oraşul unu. O soluţie pentru acest exemplu ar fi vizitarea tuturor oraşelor.\r\n\r\nh3. Soluţie\r\n\r\nEste evident că şi această problemă se poate uşor transforma într-o instanţă de $2-SAT$. Fiecare turist ne dă prin dorinţele sale o expresie literală cu doi literali. Vizitarea sau nevizitarea oraşului de index $i$ va fi reprezentată prin variabila booleană <tex> A_{i} </tex>.  Exemplul din problemă poate fi transformat astfel: <tex> (A_{1} \\vee \\sim A_{2}) \\wedge (A_{2} \\vee A_{4}) \\wedge (A_{3} \\vee A_{1}) </tex>.\r\n\r\nh2(#orpath). Orpath (Olimpiadă Rusia)\r\n\r\nbq. Într-o ţară pacifistă, există $N$ oraşe şi $K$ autobuze $(1 <= N, K <= 100)$. La orele aglomerate ale zilei, nu trebuie să existe două autobuze care merg în acelaşi timp în sensuri opuse. Traseul fiecărui autobuz este un ciclu. Spunem că el merge în sens pozitiv dacă va parcurge oraşele în ordinea $1 2 3 4 1 2 3 4 1 2$ ... sau în sens negativ dacă le parcurge în ordinea $1 4 3 2 1 4 3 2 1 4$ ... Găsiţi o posibilitate de atribuire a sensului fiecărui autobuz astfel ca accidentele de trafic să fie evitate (nu vor exista două autobuze care să se întâlnească şi să aibă sensuri de mers opuse). Pentru fiecare autobuz se vor şti oraşele de pe ruta lui, şi pentru fiecare două oraşe vecine pe rută se va şti timpul necesar autobuzului pentru a ajunge dintr-un oraş în altul. De exemplu, pentru $4$ oraşe unde oricare două sunt la timp de mers egal cu $10$, şi pentru două autobuze cu rutele $1 2 4$ şi $3 4 2$, o soluţie ar fi ca primul autobuz să meargă în sens pozitiv iar celălalt în sens negativ.\r\n\r\nh3. Soluţie\r\n\r\nPentru orice două autobuze vom găsi care sunt sensurile de mers pentru ele astfel ca cele două autobuze să nu se întâlnească şi să provoace un accident. Pentru un sens fixat putem afla pentru un autobuz pe ce interval de timp va fi pe o anumită stradă. El va fi în general pe o stradă $(i, j)$ pe un interval de tipul $[t1 + k*T … t2 + k*T]$ unde $t1$ este timpul din prima rută parcursă pentru a ajunge la $i$, $t2$ timpul pentru a ajunge la $j$ iar $T$ este durata totală a unei rute. Acum, pentru a determina dacă două autobuze se vor întâlni pe o rută $(i, j)$ trebuie ca ele să se deplaseze în sensuri opuse pe această rută, iar intervalele lor $[t1 + k*T1 .. t2 + k*T1]$ se intersectează cu intervalele $[tt1 + p*T2 … tt2 + p*T2]$. Este clar acum că putem transforma problema într-o instanţă de $2-SAT$ prin maparea autobuzelor în variabile logice, a sensurilor de mers în valorile $adevărat$ şi $fals$, iar pentru orice pereche de autobuze să fie o propoziţie logică ce ia valoarea $adevărat$ doar dacă sensurile de mers determinate de variabilele logice asociate autobuzelor sunt compatibile. Mai trebuie determinat într-un mod eficient dacă două clase de intervale de timp se intersectează. Aceasta rămâne ca temă cititorului.\r\n\r\nh2(#aladdin). \'Aladdin\':problema/aladdin (Bursele Agora 2005/2006, Runda 1)\r\n\r\nbq. Aladdin, aşa cum ştiaţi, este un mare magnat în afacerea de comercializare a covoarelor magice. Acesta doreşte să o cucerească pe prinţesa Iasmina, iar aceasta, pentru a-i testa inteligenţa îl roagă să îi facă un covor dreptunghiular împărţit în pătrăţele, asemănator unei table de şah cu $N$ linii şi $M$ coloane $(1 <= N, M <= 1000)$. Fiecare pătrăţel de pe covor trebuie colorat cu alb sau cu negru. Pentru fiecare pătrat care conţine $4$ pătrăţele Iasmina pune condiţia să aibă un număr fixat de pătrăţele colorate cu negru. Ajutaţi-l pe Aladdin să realizeze un covor care satisface condiţiile impuse de prinţesa Iasmina!\r\n\r\nh3. Soluţie\r\n\r\nÎntâi, să considerăm un exemplu. Pentru o cerinţă de forma:\r\n\r\ntable{width: 90px; text-align: center}.\r\n| <tex> 3 </tex> | <tex> 2 </tex> | <tex> 3 </tex> |\r\n| <tex> 2 </tex> | <tex> 3 </tex> | <tex> 3 </tex> |\r\n| <tex> 1 </tex> | <tex> 2 </tex> | <tex> 1 </tex> |\r\n\r\nuna din soluţii este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nFie <tex> A </tex> o matrice soluţie a problemei noastre. Vom numerota rândurile matricii de la $0$ la $N - 1$ şi coloanele de la $0$ la $M - 1$. Matricea de intrare <tex> S </tex> reprezintă de fapt sumele din fiecare pătrat de câte $2 x 2$ elemente. Facem observaţia că dacă ştim într-un pătrat de $2 x 2$ valorile pentru trei dintre celule, atunci valoarea din a patra celulă este unic determinată pentru că ştim suma elementelor din pătrat. Vedem astfel, că dacă ştim valorile elementelor din prima linie a matricii <tex> A </tex> şi din prima coloană, restul valorilor sunt unic determinate. \r\nPentru a rezolva problema vom presupune <tex> A[0][0] </tex> cunoscut (de fapt, mai întâi vom rezolva problema presupunând că <tex> A[0][0] = 1 </tex>, iar dacă nu obţinem nicio soluţie vom încerca cu <tex> A[0][0] = 0 </tex>). Vom nota celulele <tex> A[0][1] </tex>, <tex> A[0][2]</tex>, … <tex> A[0][M - 1] </tex> cu <tex> x_{1} </tex>, <tex> x_{2} </tex>, … <tex> x_{M-1} </tex> iar celulele <tex> A[1][0] </tex>, <tex> A[2][0] </tex>, … <tex> A[N - 1][0] </tex> cu <tex> y_{1} </tex>, <tex> y_{2} </tex>, … <tex> y_{N-1} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> A[0][0] </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> ... </tex> | <tex> x_{M-1} </tex> |\r\n| <tex> y_{1} </tex> | <tex> 1 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n| <tex> y_{2} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 0 </tex> |\r\n| ... | ... | ... | ... | ... |\r\n| <tex> y_{N-1} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n\r\nAcum, pentru fiecare celulă putem demonstra prin inducţie că <tex> A[i][j] = (-1)^i x_{j} + (-1)^j y_{i} + b[i][j] </tex>. Unde <tex> b[i][j] </tex> sunt nişte constante ce sunt calculate în funcţie de matricea primită la intrare.\r\nEste uşor de observat că dacă:\r\n<tex> A[i-1][j] = (-1)^{(i-1)} x_{j} + (-1)^j y_{i-1} + b[i-1][j] </tex>, \r\n<tex> A[i-1][j-1] = (-1)^{(i-1)} x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i-1][j-1] </tex>, \r\n<tex> A[i][j-1] = (-1)^i x_{j-1} + (-1)^{(j-1)} y_{i} + b[i][j-1] </tex>, \r\n\r\natunci:\r\n\r\n<tex> A[i][j] = S[i-1][j-1] - A[i-1][j] - A[i][j-1] - A[i-1][j-1] = </tex> \r\n<tex> = S[i-1][j-1] - ((-1)^{(i-1)} x_{j} + (-1)^j y_{i-1} + b[i-1][j]) - </tex> <tex> ((-1)^{(i-1)} x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i-1][j-1]) - ((-1)^i x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i][j-1]) = </tex> \r\n<tex> = (-1)^i x_{j} - (-1)^j y_{i-1} + (-1)^i x_{j-1} + (-1)^j y_{i-1} - </tex> <tex> (-1)^i x_{j-1} + (-1)^j y_{i} + S[i-1][j-1] - b[i-1][j] - b[i][j-1] - b[i-1][j-1] = </tex> \r\n<tex> = (-1)^i x_{j} + (-1)^j y_{i} + b[i][j] </tex>. \r\n\r\nDe aici concluzionăm că <tex> b[i][j] = S[i-1][j-1] - b[i-1][j] - b[i][j-1] - b[i-1][j-1] \\ (*)</tex>.\r\n\r\nAvem un sistem format din inecuaţiile:\r\n\r\n<tex> 0 \\le x_{j} \\le 1 </tex>\r\n<tex> 0 \\le y_{i} \\le 1 </tex>\r\n<tex> -b[i][j] \\le (-1)^i x_{j} + (-1)^j y_{i} \\le 1 - b[i][j] </tex>\r\n\r\nEste uşor acum să transformăm acest sistem într-o formulă booleană în {\'formă normal conjunctivă\':2-sat#forme-normale} în care fiecare expresie are cel mult $2$ literali. Fiecare relaţie o putem înmulţi sau nu cu $-1$ astfel ca părţile constante ale relaţiei să fie pozitive. Observăm că <tex> | b[i][j] | \\le 2 </tex>, altfel nu avem soluţie. Dacă <tex> | b[i][j] | = 2 </tex> atunci ambele variabile au valori fixe, iar dacă <tex> | b[i][j] | = 1 </tex> sau <tex> | b[i][j] | = 0 </tex> atunci relaţia o putem scrie ca o disjuncţie logică cu doi literali.\r\n\r\nO relaţie precum <tex> 0 \\le x + y \\le 1 </tex> poate fi tansformată logic în <tex> \\sim x \\vee \\sim y </tex>, astfel <tex> x </tex> şi <tex> y </tex> nu vor fi în acelaşi timp <tex> 1 </tex>, una de genul <tex> 1 \\le x + y \\le 2 </tex> va fi transformată în <tex> (x \\vee y) </tex>, astfel cel puţin <tex> x </tex> sau <tex> y </tex> va fi egal cu <tex> 1 </tex>, alta de tipul <tex> 0 \\le x - y \\le 1 </tex> poate fi scrisă ca <tex> x \\vee \\sim y </tex>, una de tipul <tex> 2 \\le x + y \\le 3 </tex> în <tex> x \\wedge y </tex>, iar una de tipul <tex> 0 \\le -x -y \\le 1 </tex> în <tex> \\sim x \\wedge \\sim y </tex>, una de tipul <tex> 1 \\le x - y  \\le 2 </tex> în <tex> x \\wedge \\sim y </tex>.\r\n\r\nAstfel am redus problema la rezolvarea unei instanţe de $2-SAT$. Avem $N+M-1$ necunoscute şi {$(N-1)$}{$(M-1)$} propoziţii. Folosind a treia metodă de rezolvare vom obţine un algoritm de complexitate $O(N * M)$ care soluţionează problema noastră.\r\n\r\nSă vedem cum merge acestă rezolvare pe exemplul din problemă:\r\n\r\nAlegem <tex> A[0][0] = 1 </tex>. Necunoscutele vor fi <tex> x_{1} </tex>, <tex> x_{2} </tex>, <tex> x_{3} </tex> şi <tex> y_{1} </tex>, <tex> y_{2} </tex>, <tex> y_{3} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> x_{3} </tex> |\r\n| <tex> y_{1} </tex> | <tex> A[1][1] </tex> | <tex> A[1][2] </tex> | <tex> A[1][3] </tex> |\r\n| <tex> y_{2} </tex> | <tex> A[2][1] </tex> | <tex> A[2][2] </tex> | <tex> A[2][3] </tex> |\r\n| <tex> y_{3} </tex> | <tex> A[3][1] </tex> | <tex> A[3][2] </tex> | <tex> A[3][3] </tex> |\r\n\r\nFolosind recurenţa <tex> (*) </tex> obţinem că matricea <tex> b </tex> este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 2 </tex> | <tex> 0 </tex> | <tex> 3 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> -1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n\r\nDe aici obţinem sistemul de inegalităţi:\r\n\r\n<tex> 0 \\le x_{1} \\le 1,  0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le 1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, -2 \\le -x_{1} - y_{1} \\le -1, 0 \\le -x_{2} + y_{1} \\le 1, -3 \\le -x_{3} - y_{1} \\le -2, </tex>\r\n<tex> 0 \\le y_{2} \\le 1,  0 \\le  x_{1} - y_{2} \\le  1,-1 \\le  x_{2} + y_{2} \\le 0,  1 \\le  x_{3} - y_{2} \\le  2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, -1 \\le -x_{1} - y_{3} \\le  0, 0 \\le -x_{2} + y_{3} \\le 1, -1 \\le -x_{3} - y_{3} \\le  0 </tex>\r\n\r\nTransformăm relaţiile astfel ca să nu apară nici o constantă negativă:\r\n\r\n<tex> 0 \\le x_{1} âle 1, 0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le  1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, 1 \\le x_{1} + y_{1} \\le 2, 0 \\le -x_{2} + y_{1} \\le 1, 2 \\le x_{3} + y_{1} \\le 3, </tex>\r\n<tex> 0 \\le y_{2} \\le 1, 0 \\le x_{1} - y_{2} \\le 1, 0 \\le -x_{2} - y_{2} \\le 1, 1 \\le x_{3} - y_{2} \\le 2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, 0 \\le x_{1} + y_{3} \\le 1, 0 \\le -x_{2} + y_{3} \\le 1, 0 \\le x_{3} + y_{3} \\le 1 </tex>\r\n\r\nAcest sistem poate fi transformat într-o expresie booleană:\r\n\r\n<tex> (x_{1} \\vee y_{1}) \\wedge (\\sim x_{2} \\vee y_{1}) \\wedge (x_{3} \\wedge y_{1}) \\wedge </tex>\r\n<tex> (x_{1} \\vee \\sim y_{2}) \\wedge (\\sim x_{2} \\wedge \\sim y_{2}) \\wedge (x_{3} \\wedge \\sim y_{2}) \\wedge </tex>\r\n<tex> (\\sim x_{1} \\vee \\sim y_{3}) \\wedge (\\sim x_{2} \\vee y_{3}) \\wedge (\\sim x_{3} \\vee \\sim y_{3}) </tex>.\r\n\r\nAcestă expresie e satisfăcută de valorile: <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 1, y_{1} = 1, y_{2} = 0, y_{3} = 0 \\rangle </tex>, iar de aici putem determina o soluţie a problemei noastre iniţiale ca fiind:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nh2(#bibliografie). Bibliografie:\r\n\r\n* [1] \'\"Introducere in algoritmi\"\':http://zhuzeyuan.hp.infoseek.co.jp/ita/toc.htm, T. H. Cormen, C. E. Leiserson, R. R. Rivest\r\n* [2] \'Satisfiability\':http://en.wikipedia.org/wiki/Satisfiability, Wikipedia\r\n* [3] \"BOI\'01 Competition material\":http://www.oi.edu.pl/download/boi-2001.pdf\r\n* [4] \"CEOI\'02 Competition material\":http://ics.upjs.sk/ceoi/\r\n* [5] \'Componente tare conexe\':problema/ctc\r\n',3146,'public',NULL,NULL),('algoritmiada-2009/runda-1/solutii/sprim','Sprim','2008-12-14 13:15:11','2008-12-16 16:45:22','h1(#sprim). \'Sprim\':problema/sprim\r\n\r\nFie $A[i]$ vectorul citit. Consideram pentru fiecare pozitie $i$ vectorul $P[i]$ pozitia cea mai din dreapta pana in pozitia $i$, astfel incat $A[i]$ nu e prim cu $A[P[i]]$. Vrem sa calculam $S[i]$ = pozitia unde incepe subsecventa maximala (ce respecta conditiile din enunt) care contine $i$ pe ultima pozitie. Raspunsul este suma tuturor $i - S[i]$ cu $1 &le; i &le; N$.\r\nPresupunem ca avem calculat $S[i-1]$ si vrem sa calculam $S[i]$. Se observa doua conditii necesare si suficiente pentru S[i]:\r\n\r\n# $S[i] > P[i]$ (e clar ca subsecventa care contine $i$ nu poate sa treaca sau sa contina $P[i]$ pentru ca astfel nu se respecta conditia)\r\n# $S[i] &ge; S[i-1]$ (trebuie ca subsecventa care contine $i$ sa nu treaca mai departe de subsecventa care contine $i-1$ pentru ca iar nu se respecta conditia)\r\n\r\nDe aici rezulta ca $S[i] = max(S[i-1], P[i] + 1)$. Tot ce ramane de calculat este $P[i]$ si dupa aceea $S[i]$ se poate calcula secvential de la $1$ la $N$.\r\n\r\nPentru a calcula $P[i]$ eficient vom proceda in felul urmator: ca ca stim cel mai din dreapta pozitie pana in $i$ astfel incat $A[i]$ nu e prim cu $A[P[i]]$ ne intereseaza cel mai din dreapta numar care contine un factor prim al lui $A[i]$. Aceasta este usor de facut tinand un vector cu ultima aparitie al fiearui factor prim pana la pozitia $i$. $P[i]$ va fi maximul dintre ultimele pozitii ale factorilor primi ai numarului $A[i]$. Dupa ce terminam de procesat numarul $A[i]$ modificam vectorul cu aparitiile factorilor primi ai lui $A[i]$ cu pozitia $i$.\r\n\r\nAveti grija la descompunerea numerelor in factori primi. Pentru a lua punctaj maxim se recomanda incercarea secventiala a fiecarui numar prim pana in $sqrt(A[i])$.',2038,'public',NULL,NULL),('numerele-sprague-grundy','Teoria jocurilor: numerele Sprague Grundy','2008-11-18 17:10:41','2008-12-04 11:37:15','h1. Teoria jocurilor: numerele Sprague Grundy\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"portocala\") ==\r\n\r\n(Categoria _Matematică_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 28em}*{text-align:center;} *Conţinut*\r\n* \'Introducere\':numerele-sprague-grundy#introducere\r\n* \'Ce este jocul NIM?\':numerele-sprague-grundy#nim\r\n* \'Probleme care folosesc strategia NIM\':numerele-sprague-grundy#probleme-nim\r\n* \'Numerele Sprague Grundy\':numerele-sprague-grundy#sprague-grundy\r\n* \'Probleme care se rezolvă cu numerele Sprague Grundy\':numerele-sprague-grundy#probleme-sg\r\n* \'Bibliografie\':numerele-sprague-grundy#bibliografie\r\n\r\nh2(#introducere). Introducere\r\n\r\nDomeniu relativ nou şi încă necercetat în adâncime, $teoria jocurilor$ este o ramură a matematicii în care de multe ori primează inventivitatea şi nu cunoştinţele. Tocmai din acest motiv, în cadrul acestui articol vom introduce câteva noţiuni teoretice care ne vor ajuta în rezolvarea unor probleme din teoria jocurilor. Ingeniozitatea celor pasionaţi poate fi testată prin introducerea unor probleme de teoria jocurilor la concursurile de matematică şi informatică. Deoarece în România teoria jocurilor nu este studiată în şcoli, problemele din acest domeniu pot pune în dificultate concurenţii.\r\n\r\nh2(#nim). Ce este jocul NIM?\r\n\r\nPentru început ne vom familiariza cu jocul clasic $NIM$:\r\n\r\nbq. Se consideră $n$ grămezi de pietre. Doi jucători, vor ridica (alternativ) oricâte pietre dintr-o singură grămadă. Câştigătorul este cel care ia ultima piatră.\r\n\r\nh3. Soluţie\r\n\r\n* Pentru cazul trivial în care numărul de grămezi este egal cu $1$, primul jucător are, evident, strategie de câştig, el putând lua toate pietrele din grămadă.\r\n* Dacă numărul de grămezi este egal cu $2$, primul jucător are strategie de câştig atunci când numărul de pietre din prima grămadă este diferit de numărul de pietre din cea de-a doua, strategia lui fiind cea de a aduce tot timpul grămada mai mare la numărul de pietre al grãmezii mai mici, şi cum jocul este finit, înseamnă că primul jucător o să aducă jocul în starea $(0, 0)$.\r\n* Dacă numărul de grămezi este mai mare decât doi, strategia se complică şi nu se mai observă cu \"ochiul liber\". Stările câştigătoare pentru mai multe grămezi sunt acele stări pentru care suma $XOR$ a numerelor de pietre din grămezi este diferită de $0$, restul stărilor fiind de pierdere.\r\n\r\nDe exemplu, dacă avem o gramadă cu o piatră, o gramadă cu trei pietre, o gramadă cu cinci pietre şi o gramadă cu şapte pietre:\r\n\r\n$o$\r\n$ooo$\r\n$ooooo$\r\n$ooooooo$\r\n\r\nAtunci vom avea:\r\n\r\n$1 = (0001){~2~}$\r\n$3 = (0011){~2~}$\r\n$5 = (0101){~2~}$\r\n$7 = (0111){~2~}$\r\n\r\nEfectuând \'$XOR$\':http://www.fredosaurus.com/notes-cpp/expressions/bitops.html (operatorul $^$ în $C/C++$) între reprezentãrile binare ale numerelor  obţinem $0 = (0000){~2~}$. Conform propoziţiei de mai sus această stare este de pierdere.\r\n\r\nSă demonstrăm cele afirmate. Dintr-o poziţie cu suma $XOR$ egală cu $0$, pentru orice mutare ajungem evident la o poziţie cu suma $XOR$ diferită de $0$, pentru că luând dintr-o grămadă un număr $x$ de pietre, în suma $XOR$ corespunzătoare noii stări bitul cel mai semnificativ al lui $x$ va avea valoarea $1$.\r\n\r\nMai rămâne de demonstrat că din orice poziţie cu suma $XOR$ diferită de $0$ putem trece printr-o mutare convenabilă într-o poziţie cu suma $XOR$ egală cu $0$. Căutăm o grămadă care are un număr de pietre mai mare sau egal cu cea mai mare putere a lui $2$ care apare în suma $XOR$. Fie $x$ valoarea sumei $XOR$ a tuturor grămezilor şi $y$ numărul de pietre din grămada găsită mai devreme. O mutare \"câştigătoare\" este extragerea din grămada găsită care are $y$ pietre a {$y - (x XOR y)$} pietre ({$x XOR y$} este mai mic decât $y$ pentru că se anulează biţii cei mai semnificativi ai lui $y$ şi $x$). Atunci noua sumă $XOR$ va fi egală cu $0$.\r\n\r\nDe exemplu:\r\n\r\n$4{@ ^ 8 ^ @}17 = (00100){~2~}{@ ^ @}(01000){~2~}{@ ^ @}(10001){~2~} = (11101){~2~} = 29$.\r\n\r\nMutarea câştigătoare constă în a lua din cea de-a treia gramadă un număr de pietre egal cu:\r\n\r\n$17 - (17 @^ 29) = 17 - 17 ^@ 29 = 5 = (00101){~2~}$.\r\n\r\nDupă acest pas grămezile vor avea $4$, $8$, $12$ pietre. Ne aflăm astfel într-o stare cu suma $XOR$ egală cu $0$.\r\n\r\nh2(#probleme-nim). Probleme care folosesc strategia NIM\r\n\r\nh3. Problema 1\r\n\r\nbq. Pe o tablă de şah, care are $n × m$ căsuţe, sunt plasaţi pe prima linie $n$ pioni albi şi pe ultima linie $n$ pioni negri. Fiecare dintre cei doi jucători poate muta un singur pion, care îi aparţine, un număr strict pozitiv de căsuţe în sus sau în jos, astfel încât să nu ajungă vreun pion alb să fie mai jos decât pionul negru de pe aceeaşi coloanã. Pierde jucătorul care nu mai poate muta.\r\n\r\nAceastă problemă este o deghizare a jocului $NIM$, numărul de pătrăţele libere între pionul alb şi pionul negru de pe coloana $i$ putând fi considerat numărul de pietre din grămada $i$. Singura diferenţă este că se pot adăuga pietre la grămadă (existând posibilitatea mutării înapoi). Această problemă se rezolvă uşor, jucătorul care are strategie de câştig putând evita asemenea mutări. O astfel de mutare poate fi utilă numai pentru jucãtorul care este într-o poziţie de pierdere. Când jucătorul care nu are strategie de câştig mută înapoi $x$ căsuţe, celălalt jucător va muta pionul propriu de pe aceeaşi coloanã cu $x$ căsuţe în faţă, astfel ajungându-se la aceeaşi stare cu cea existentă cu două mutări anterior (considerând diferenţa poziţiilor).\r\n\r\nh3. Problema 2\r\n\r\nAceastă problemă a fost propusă spre rezolvare participanţilor la barajul pentru lărgirea lotului naţional din 1997.\r\n\r\nbq. Pe o linie sunt plasate la coordonate întregi $2 × n$ piese roşii şi albastre. Fiecare piesă roşie poate fi mutată în dreapta oricâte poziţii astfel încât să nu sară peste o piesă albastră, iar piesele albastre pot fi mutate oricâte poziţii la stânga astfel încât să nu depăşească vreo piesă roşie. Piesele vor alterna: roşu, albastru, roşu, albastru etc. Pierde jucătorul care nu mai poate muta.\r\n\r\nAceastă problemă poate fi, de asemenea, redusă la jocul $NIM$. Diferenţele poziţiilor perechilor de piese roşii şi albastre consecutive constituie numărul de pietre al grămezilor din jocul $NIM$.\r\n\r\nh3. Problema 3 (El Judge MIPT online programming contest Nim Game Give Away!)\r\n\r\nbq. Se consideră $n$ grămezi de pietre, jucătorii mută alternativ, fiecare jucător extrăgând oricâte pietre dintr-o singură grămadă. Cel care ia ultima piatră pierde jocul.\r\n\r\nStrategia acestui joc este similară cu cea aplicată în jocul $NIM$ cu câteva mici diferenţe. Jucătorul care are strategie de câştig în poziţia curentă în cadrul jocului $NIM$ face aceeaşi mutare pe care ar face-o în cazul jocului $NIM$, exceptând cazul în care această mutare lasă doar grămezi cu o singură piatră şi numărul acestor grămezi este par.  În această situaţie, dacă ar trebui să ia $x$ pietre, jucătorul poate lua $x - 1$ pietre din grămada actuală, pentru ca numărul de grămezi să fie impar şi el să facă ultima mutare.\r\n\r\nh2(#sprague-grundy). Numerele Sprague Grundy\r\n\r\nJocurile care prezintă interes pentru jucători sunt acelea care necesită examinarea unui număr foarte mare de stări pentru determinarea strategiei de câştig, deoarece în caz contrar câştigătorul s-ar cunoaşte chiar de la început. Spre deosebire de aceştia, matematicienii sau informaticienii sunt interesaţi de determinarea unor strategii pentru astfel de jocuri.\r\nToate jocurile imparţiale cu doi jucători cu informaţie totală pot fi reduse la jocul *$NIM$* care se joacă cu nişte grămezi virtuale, în care mutările posibile sunt extragerea oricâtor pietre dintr-o grămadă sau adăugarea oricâtor pietre la o grămadă (aşa cum am menţionat anterior, adãugarea de pietre la o grămadă nu complică analiza jocului).\r\n\r\nAfirmaţia anterioară constituie un rezultat al *Teoriei Sprague-Grundy. _Roland Percival Sprague_* (1936) şi _*Patrick Michael Grundy*_ (1939) sunt doi matematicieni care s-au ocupat, independent, de teoria jocurilor imparţiale.\r\n\r\nMajoritatea jocurilor imparţiale se pot reduce la jocul prezentat în problema _Pioni_ de la runda 47 a concursului de programare Bursele Agora. Acolo se menţiona următorul joc:\r\n\r\n_Se consideră un graf aciclic care conţine în noduri câţiva pioni, jucătorii alternează la mutare şi fiecare poate muta câte un pion pe un arc care iese din nodul în care este situat pionul. Pierde jucătorul care nu poate muta._\r\n\r\nCum graful este aciclic, jocul este finit şi are întotdeauna un câştigător. Practic, acest joc este suma unor jocuri, mai precis suma a mai multor jocuri cu un singur pion pe graful aciclic. Jocul cu un singur pion poate fi analizat destul de uşor, fiecare nod al grafului putând fi colorat cu alb sau negru după cum există sau nu strategie de câştig dacă în nodul curent ar fi poziţionat pionul. Această colorare poate fi realizată uşor dacă se porneşte de la nodurile fără urmaş şi la fiecare pas se colorează câte un nod ai cărui urmaşi sunt deja coloraţi. Orice joc imparţial poate fi redus la un joc cu un singur pion. Nodurile sunt poziţiile jocului şi arcele grafului sunt mutările posibile din fiecare poziţie. Jocul iniţial poate fi şi el transformat, dar numărul de noduri creşte foarte mult (pentru $n$ pioni şi $m$ noduri, numărul de noduri din jocul transformat este {$n^m^$}) şi nu este practic să colorăm graful rezultat. Folosind teoria dezvoltatã de Sprague şi Grundy, putem reduce complexitatea analizei jocului cu $n$ pioni la complexitatea analizei jocului cu un pion.\r\n\r\nVom introduce funcţia *$mex$* cu semnificaţia: $mex(S)$ este elementul minimal natural care nu aparţine mulţimii $S$. Pentru fiecare nod $x$ al grafului aciclic considerat, vom calcula valoarea funcţiei $gx = mex(gx{~1~}, gx{~2~}, …, gx{~k~})$, unde $x{~1~}$, $x{~2~}$, …, $x{~k~}$ sunt urmaşii nodului $x$ în graf. Pentru nodurile fără urmaşi $gx = 0$.\r\n\r\nAnalog jocului cu un singur pion, graful poate fi etichetat din aproape în aproape, pornind de la nodurile fără urmaşi. Observăm că, dacă $gx = 0$ în jocul cu un singur pion situat în nodul $x$ nu avem strategie de câştig, iar dacă $gx$ este diferit de $0$ avem strategie de câştig. Restul informaţiei ne ajută la determinarea unei strategii pentru jocul cu $n$ pioni. Observăm că putem reduce acest joc la jocul $NIM$ în care grămada virtuală asociată pionului $i$ are un număr de pietre egal cu valoarea $g$ a nodului în care este situat pionul $i$.\r\n\r\nh4. _De ce este acest joc echivalent cu jocul NIM?_\r\n\r\nAşa cum la $NIM$ puteam lua oricâte pietre dintr-o grămadă, aici putem muta pionul dintr-un nod cu valoarea $g$ într-un nod astfel încât noua valoare pentru pionul $i$ poate fi orice număr de la $0$ la $g - 1$. Prin urmare, pentru a verifica dacă suntem într-o poziţie de câştig în jocul cu pionii, putem aplica strategia jocului $NIM$ şi obţinem că suntem într-o poziţie de câştig dacă suma $XOR$ a numerelor din nodurile ocupate de cei $n$ pioni este diferită de $0$. Această sumă se numeşte funcţia _Sprague Grundy,_ <tex>SG(i_{1}, ..., i_{n}) = g_{i_1} \\verb|^| g_{i_2} \\verb|^| g_{i_3} \\verb|^| ... \\verb|^| g_{i_n}</tex>.\r\n\r\nProblema de la runda 47 ({_Pioni_}) se rezolvă acum uşor efectuând o sortare topologică a nodurilor grafului aciclic şi numerotând nodurile folosind funcţia $mex$.\r\n\r\n\r\nh2(#probleme-sg). Probleme care se pot rezolva folosind numerele Sprague Grundy\r\n\r\nh3. Problema 4\r\n\r\nProblema Joc a rundei 13 a concursului de programare Bursele Agora putea fi rezolvatã în acest mod.\r\nÎn acea problemă se cerea să verificăm existenţa unei strategii de câştig pentru un joc similar cu $NIM$ în care se putea lua dintr-o grămadă o piatră sau un număr prim de pietre.\r\n\r\nDacă determinăm valorile $Sprague Grundy$ pentru grămezi de dimensiuni mici putem observa că se repeta o succesiune de numere: $0 1 2 3 0 1 2 3 ...$\r\nPutem demonstra prin inducţie că această secvenţă se va repeta la nesfărşit.\r\nPentru o grămadă de dimensiune $n$ valoarea asociată va fi $n modulo 4$. Pentru $0 ≤ n ≤ 3$ afirmaţia este adevărată. Vom presupune afirmaţia adevărată pentru toate valorile $m < n$. Să demonstrăm acum că este adevărată şi pentru $n$. Deoarece putem lua din $n$ pietre una, două sau trei pietre, mai rămâne valoarea $n modulo 4$ care nu este eliminată încă din valorile potenţiale asociate grămezii de dimensiune $n$. Vom arăta în continuare că această valoare nici nu va fi eliminată. Eliminarea ei ar însemna că putem lua din $n$ un număr $p$ de pietre şi atunci din $(n - p) modulo 4 = n modulo 4$, am avea: $p modulo 4 = 0$, dar $p$ este un număr prim, deci valoarea _Sprague Grundy_ asociată unei grămezi de dimensiune $n$ este $n modulo 4$.\r\n\r\nh3. Problema 5 (El Judge MIPT online programming contest, Stone game)\r\n\r\n_Se consideră k grămezi cu n{~1~}, n{~2~}, …, n{~k~} pietre fiecare. Când este rândul său, un jucător poate lua dintr-o gramadă 2^m^ pietre. Jucătorul care ia ultima piatră câştigă._\r\n_Restricţii: k ≤ 50, n{~i~} ≤ 10200._\r\n\r\nSă determinăm valorile Sprague Grundy pentru grămezi mici:\r\n\r\n$0 : 0;    1 : 1;    2 : 2;    3 : 0;    4 : 1;    5 : 2;    6 : 0$\r\n\r\nObservăm şi aici secvenţa repetitivă $0 1 2 0 1 2$, deci am putea trage concluzia că valoarea _Sprague Grundy_ asociată unei grămezi de dimensiune $n$ este $n modulo 3$. Această afirmaţie este adevarată şi urmează aceeaşi demonstraţie ca în cazul problemei anterioare, iar restul $modulo 3$ pentru $n$ număr cu 200 de cifre este simplu de găsit determinând suma cifrelor numărului.\r\n\r\nh3. Problema 6 (El Judge MIPT online programming contest, Stone game II)\r\n\r\n_Se consideră k grămezi de pietre cu n{~1~}, n,{~2~} …, n{~k~} pietre. Un jucător poate lua dintr-o grămadă la mutarea lui un număr pozitiv de pietre dar nu mai mult de jumătate din pietrele din grămadă. Jucătorul care nu mai poate muta pierde._\r\n_Restricţii: k ≤ 50, n{~i~} ≤ 100000._\r\n\r\nNumărul $100000$ nu este foarte mare şi valorile $Sprague Grundy$ pot fi determinate _off-line_ şi incluse în programul nostru ca şi constante. Putem scrie pentru valori mici secvenţa $Sprague Grundy$:\r\n\r\n$1 2 3 4 5 6 7 8 9 10 11 12 13 14$\r\n$0 1 0 2 1 3 0 4 2  5  1  6  3  7$\r\n\r\nPentru $n$ impar valoarea asociată este aceeaşi cu valoarea asociată lui $n/2$, şi pentru $n$ par valoarea asociată este $n/2$. Acest lucru se poate demonstra prin inducţie matematică.\r\n\r\nh3. Problema 7 (CEOI 2000, problema Sticks)\r\n\r\n_Se consideră n (n ≤ 10) rânduri de beţe pe o masă, cu S{~i~} (S{~i~} ≤ 10) beţe aliniate pe fiecare rând şi doi jucători. Beţele de pe rândul i sunt numerotate secvenţial de la 1 la S{~i~}. Cei doi jucători mută alternativ. Fiecare mişcare constă în eliminarea a unu, două sau trei beţe de pe acelaşi rând. Beţele trebuie sã fie numerotate secvenţial, adică să fie consecutive. De exemplu, un rând are 10 beţe şi primul jucător elimină beţele 4, 5, 6, deci vor rămâne numai beţele 1, 2, 3, 4, 8, 9, 10. Al doilea jucător poate lua la rândul său beţele 1, 2, 3, dar nu beţele 3, 7, 8 pentru că acestea nu sunt numerotate consecutiv (bineînţeles că există şi alte mutări valide). Câştigă jucătorul care ia ultimul băţ de pe masă._\r\n\r\nProblema generală are o soluţie ingenioasă care ţine seama de parităţile rândurilor, dar la această problemă, datorită mărginirii lui $S{~i~}$ ({$S{~i~} ≤ 10$}) nu este necesar să fim ingenioşi. Restricţia $S{~i~} ≤ 10$, ne ajută prin faptul cã numărul total de poziţii (dacă jucăm pe o singură gramadă), este $2^10^$. Vom reprezenta o poziţie printr-un întreg, iar dacă acel întreg are în codificarea lui binară pe poziţia $i$ un bit de 1 înseamnă că el reprezintă un rând de beţe care conţine în el băţul numerotat cu $i$. Este uşor de realizat un graf aciclic al mişcărilor pentru un rând (graful este aciclic pentru că la fiecare mutare luăm beţe din configuraţie). Numerotăm fiecare poziţie cu numerele _Sprague Grundy,_ şi acum problema deciderii dacă suntem sau nu într-o poziţie câştigătoare devine banală. În problema iniţială trebuia să jucăm împotriva calculatorului şi să câştigăm. Putem realiza aceasta folosind mutarea câştigătoare prezentată la jocul $NIM$.\r\n\r\nh3. Problema 8\r\n\r\nAceastă problemă a fost propusă spre rezolvare la concursul Internet Problem Solving Contest (cel mai prestigios concurs online) şi o puteţi găsi la \'această adresă\':http://ipsc.ksp.sk/xxproblems/ipsc2003/g.php. Ea a fost folosită şi la concursul organizat de \'.campion\':http://campion.edu.ro la o rundă online. Rezolvarea ei, complicată, folosind numerele _Sprague Grundy_ prezentate în acest articol, se poate găsi în \'[3]\':numerele-sprague-grundy#bibliografie, pe site-ul \'[7]\':numerele-sprague-grundy#bibliografie, sau pe siteul concursului \'.campion\':http://campion.edu.ro.\r\n\r\nh3. Problema 9\r\n\r\nAceastă problemă a fost propusă spre rezolvare la ediţia din acest an a Olimpiadei Naţionale de Informatică din Ucraina. \r\n\r\n_Doi participanţi mănâncă alternant din nişte tablete de ciocolată după următoarele reguli:_\r\n{*} _taie o tabletă în două, tăietura trebuie să fie paralelă cu una din laturile tabletei şi trebuie să nu taie pătrăţelele de ciocolată;_\r\n{*} _poate să rupă şi să mănânce orice linie sau coloană de pătrăţele care nu se aflã pe marginea tabletei;_\r\n{*} _poate să rupă şi să mănânce toate patrăţelele de pe marginea tabletei, cu condiţia ca tableta rămasă să aibă cel puţin dimensiunea 1×1._\r\n_Nici una dintre aceste trei mutări nu poate fi efectuată asupra unei tablete de dimensiune 1×1. Pierde jucătorul care nu mai poate efectua nici o mutare._\r\n_În fişierul de intrare se va afla numărul N (1 ≤ N ≤ 100) de tablete, iar pe următoarea linie sunt N perechi de numere întregi care reprezintă dimensiunile tabletelor._\r\n_În fişierul de ieşire se va afla un singur număr întreg reprezentând numărul mutărilor câştigătoare pentru primul jucător._\r\n\r\nPentru această problemă vom calcula matricea $SG{~i,j~}$ care reprezintă valoarea _Sprague-Grundy_ asociată unei tablete de dimensiuni ({$i$}, $j$). Să vedem care este recurenţa care va satisface elementele matricei $SG$:\r\n\r\n<tex>SG_{i,j} = mex(SG_{i,k} \\verb|^| SG_{i,j-k}, (1 \\leq k < j)</tex> mutarea întâi\r\n<tex>\\hspace{20mm}SG_{k,j} \\verb|^| SG_{i-k,j}, (1 \\leq k < i)</tex>\r\n<tex>SG_{i,k} \\verb|^| SG_{i,j-k-1}, (1 \\leq k < j - 1)</tex> mutarea a doua\r\n<tex>SG_{k,j} \\verb|^| SG_{i-k-1,j}, (1 \\leq k < i - 1)</tex>\r\n<tex>SG_{i-2,j-2}) (i > 2 , j > 2)</tex> mutarea a treia\r\n\r\nAcum, pentru a calcula numărul de mutări câştigătoare efectuăm asupra fiecărei tablete din fişierul de intrare toate mutările posibile care sunt cel mult de $4 • 100 + 1$ şi facem suma $XOR$ a valorilor Sprague Grundy pentru restul tabletelor neimplicate în mutare şi a tabletelor rezultate din mutare. Pentru a calcula $SG{~i,j~}$ trebuie sã parcurgem cel mult $2 • i + 2 • j + 1$ valori obţinute. Astfel, algoritmul de determinare al valorilor matricei $SG$ are ordinul de complexitatea $O(N^3^)$.\r\nComplexitatea algoritmului care determină numărul de mutări câştigătoare este $O(N^2^)$.\r\n\r\nAm văzut că aceste numere sunt folositoare pentru rezolvarea unor probleme de jocuri combinatorice. Chiar dacă numărul stărilor grafului nostru aciclic poate să fie foarte mare, putem să ne dăm seama, câteodată, din valorile mici de o regulă pe care o urmează numerele, sau măcar putem determina mai uşor configuraţii pentru care jocul are sau nu strategie de câştig, fapt care ne poate ajuta în descoperirea rezolvării generale.\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n1. ***, colecţia GInfo\r\n2. Mihai Oltean, Programarea Jocurilor Matematice, Editura Albastră, Cluj-Napoca, 1996\r\n3. \'Thomas S. Ferguson, Game Theory Text (online)\':http://www.math.ucla.edu/~tom/gamescourse.html\r\n4. \'http://www.ams.org/new-in-math/cover/games1.html\':http://www.ams.org/new-in-math/cover/games1.html\r\n5. \'http://www.cut-the-knot.com\':http://www.cut-the-knot.com\r\n6. \'http://www.mathworld.wolfram.com\':http://www.mathworld.wolfram.com\r\n7. \'http://ipsc.ksp.sk/\':http://ipsc.ksp.sk/\r\n',2044,'public',NULL,NULL),('planificare/sedinta-20081125','Sedinta 2008-11-25','2008-11-24 15:06:43','2008-12-04 15:57:15','h1. Sedinta 2008-11-25\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *marti, 25 noiembrie* la ora *19:00* la \'*Retro Cafe*\':http://metropotam.ro/Unde-iesim/2008/07/art2701725520-Millennium-Bank-recomanda-Retro-Cafe/\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"astronomy\" type=\"tiny\")== Il rog pe ==user(user=\"wefgef\" type=\"tiny\")== sa ma reprezinte\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioare\':planificare/sedinta-20081107\r\n* Update OJI\r\n* Tricouri Junior Challenge\r\n* All you can code\r\n* Algoritmiada\r\n* Feedback Coding Camp\r\n* Stabilit urmatorul Coding Camp\r\n* Stelele powered by infoarena\r\n* OKR-uri\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Vali mai are 2 tricouri. Le da lui Paul sa le livreze. %{color:red;}(1/2 done)%\r\n* E lume available pentru \"All you can code\".\r\n* All you can code: primele 4 ore sunt fara evaluare \r\n** Astronomy actualizeaza pagina concursului\r\n* Algoritmiada:\r\n** Bagam grupa de studenti si unim clasele 9-10.\r\n** Prima runda pe 14 decembrie\r\n** Facem 3 runde: dec, ian, feb, martie finala\r\n** Trebuie sa anuntam pana pe 1 decembrie\r\n** Suntem deja in prima saptamana din program. Sefi de grupe:\r\n*** Gimnaziu: ==user(user=\"astronomy\" type=\"tiny\")==\r\n*** 9-10: ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n*** 11-12: ==user(user=\"ditzonec\" type=\"tiny\")==\r\n*** Studenti: ==user(user=\"wefgef\" type=\"tiny\")==\r\n** Wegef bate lumea la cap sa citeasca rolurile, sa propuna probleme, etc.\r\n* Mircea si Bogdan fac release la 2.2 vineri %{color:red;}(done, duminica after contest)%\r\n* Mircea se ocupa sa organizeze urmatorul coding camp pe 13-14 decembrie\r\n** Probabil facem la ICHB, ca nu incapem la Hostway\r\n* Punem stire ca nu mai ai voie cu HTML si sa-si actualizeze lumea profilele\r\n* Stelele:\r\n** Facem Stelele pe infoarena\r\n** La fiecare submit retinem IP-ul ca sa detectam cine triseaza (in 2.2.1)\r\n* Avem probleme la rating:\r\n** Inregistrarea is broken\r\n** Nu avem curba lui Gauss\r\n** Trebuie sa facem posiblitatea sa te deinscrii pana incepe concursul (2.2.1)\r\n** Cosmin, Wefgef si Bogdan redacteaza IAP pentru rating\r\n\r\nh2. Notite\r\n\r\n...',1792,'public',NULL,NULL),('algoritmiada-2009/runda-1/solutii/densitate','Densitate','2008-12-14 13:09:54','2008-12-16 16:31:06','h1(#densitate). \'Densitate\':problema/densitate\r\n\r\nProblema cere sa raspundeti la intrebari de forma: \"Cate numere prime sunt intre $a$ si $b$?\" ({$a$} si $b$ inclusiv), cu $0 < a &le; b &le; N < 500000$. Complexitatea dorita pentru preprocesare este $O(NlogN)$ si cea pentru query este de $O(1)$. \r\nIn primul rand trebuie sa stim care sunt numele prime intre 1 si N. Algoritmul clasic de verificare a divizibilitatii unui numar $x$ cu toate valorile pana la $x/2$ este ineficient, avand complexitate $O(x)$, acesta poate fi optimizat pana la $O(sqrt(x))$ daca se verifica numai numerele intre $2$ si $sqrt(x)$, dar acesta este eficient doar daca se testeaza primalitatea unui singur numar. Noi insa dorim sa stim toate numrele prime intre $1$ si $N$ si pentru asta se foloseste \'Ciurul lui Eratosthenes\':problema/ciur . Acest algoritm tine un sir $V$ in care $V[i]=0$ are semnificatia ca $i$ este prim si $V[i] = 1$ inseamna ca $i$ nu e prim. La pasul $i$, daca $i$ este prim, se seteaza $V[k] = 1$ pentru toti multiplii $k$ lui $i$ pana la $N$. Complexitatea acestui algoritm este $O(N/2 + N/3 + ... + N / N) = O(NlogN)$\r\nLa pasul al doilea trebuie sa raspundem la intrebari. Sa parcurgem toate valorile intre a si b ar fi ineficient. Tinem insa un sir de sume partiale $S$ unde $S[i]$ reprezinta numarul de numere prime mai mici sau egale decat $i$, daca $V[i] = 0, S[i] = S[i-1] + 1$ altfel $V[i] = 1, S[i] = S[i-1]$. Raspunsul se calculeaza ca $S[b] - S[a-1]$.\r\nMetoda sumelor partile poate fi extinsa pentru un spatiu $N^k^$, pentru detalii vedeti \'Smenul lui Mars\':multe-smenuri-de-programare-in-cc-si-nu-numai',1490,'public',NULL,NULL),('algoritmiada-2009/runda-1/solutii/densitate','Densitate','2008-12-14 13:09:54','2008-12-17 04:55:19','h1(#densitate). \'Densitate\':problema/densitate\r\n\r\nProblema cere sa raspundeti la intrebari de forma: \"Cate numere prime sunt intre $a$ si $b$?\" ({$a$} si $b$ inclusiv), cu $0 < a &le; b &le; N < 500000$. Complexitatea dorita pentru preprocesare este $O(N log logN)$ si cea pentru query este de $O(1)$. \r\nIn primul rand trebuie sa stim care sunt numele prime intre 1 si N. Algoritmul clasic de verificare a divizibilitatii unui numar $x$ cu toate valorile pana la $x/2$ este ineficient, avand complexitate $O(x)$, acesta poate fi optimizat pana la $O(sqrt(x))$ daca se verifica numai numerele intre $2$ si $sqrt(x)$, dar acesta este eficient doar daca se testeaza primalitatea unui singur numar. Noi insa dorim sa stim toate numrele prime intre $1$ si $N$ si pentru asta se foloseste \'Ciurul lui Eratostene\':problema/ciur . Acest algoritm tine un sir $V$ in care $V[i]=1$ are semnificatia ca $i$ este prim si $V[i] = 0$ inseamna ca $i$ nu e prim. La pasul $i$, daca $i$ este prim, se seteaza $V[k] = 0$ pentru toti multiplii $k$ lui $i$ pana la $N$. Complexitatea acestui algoritm este $O(N/2 + N/3 + N/5 ... ) = O(N log logN)$\r\nLa pasul al doilea trebuie sa raspundem la intrebari. Sa parcurgem toate valorile intre a si b ar fi ineficient. Tinem insa un sir de sume cumulate $S$ unde $S[i]$ reprezinta numarul de numere prime mai mici sau egale decat $i$, astfel $S[i] = S[i-1] + V[i]$. Raspunsul se calculeaza ca $S[b] - S[a-1]$. Metoda sumelor partile poate fi extinsa pentru un spatiu $N^k^$.',58,'public',NULL,NULL),('algoritmiada-2009/runda-1/solutii/scandura','Scandura','2008-12-14 13:13:33','2008-12-17 11:20:10','h1(#scandura). \'Scandura\':problema/scandura\r\n\r\nNotam lungimea scandurei finale $i$ cu $l[i]$.\r\n\r\nVom incerca sa reprezentam taieturile scandurilor sub forma unui arbore. Radacina arborelui va fi scandura initiala de lungime <tex>L = \\sum{l[i]}</tex>. In urma unei taieturi, dintr-o scandura de lungime $A$ vor porni maxim $M$ alte muchii catre noduri a caror suma a lungimilor va fi tot $A$. Frunzele arborelui vor reprezenta cele $N$ lungimi de scanduri finale. Costul unei modalitati de taiere a scandurii mari va fi atunci egal cu suma valorilor nodurilor din arbore care nu sunt frunze. Datorita faptului ca un nod in arbore are costul egal cu suma costurilor fiilor, putem reprezenta costul fiecarui nod in functie de costul frunzelor. Daca drumul de la frunza $i$ pana la radacina trece prin $k$ noduri (incluzand radacina, neincluzand frunza), atunci costul total produs de frunza $i$ va fi egal cu $k$ * $l[i]$.\r\n\r\nPentru $M = 2$, putem echivala imediat problema cu cea a determinarii unei \'codari Huffman\':http://en.wikipedia.org/wiki/Huffman_coding optime: fiecarei scanduri initiale de lungime $l[i]$ ii putem asocia un caracter distinct cu o frecventa de $l[i]$.\r\n\r\n\r\n\r\n',1490,'public',NULL,NULL),('algoritmiada-2009/runda-1/solutii/propozitie','Propozitie','2008-12-14 13:10:58','2008-12-17 19:57:38','h1(#propozitie). \'Propozitie\':problema/propozitie\r\n\r\nFie $S$ sirul initial de caractere. Vom rezolva problema cu ajutorul programarii dinamice. Vom construi o matrice $A$, in care $A[i][j]$ va reprezenta numarul de posibilitati de a obtine propozitii valide cu primele $i$ caractere, iar ultimul cuvant din propozitie sa aibe exact $j$ vocale. Pentru a calcula valorile $A[i][j]$ putem proceda in urmatorul fel: alegem intai subsecventa de litere $S{~j~}S{~j+1~}...S{~i~}$ si o vom considera pe aceasta ultimul cuvant dintr-o propozitie valida. Daca subsecventa de litere de la $k$ la $i$ contine $p$ vocale atunci va trebui sa adunam la $A[i][p]$ toate valorile $A[j-1][q]$, unde $q$ este cuprins intre $0$ si $K$. Evident vom considera doar subsecventele pentru care $p &le; K$. O implementare bruta a acestei solutii va avea complexitatea $O(N*N*K)$. Putem reduce complexitatea la $O(N*N)$ daca vom precalcula $B[i] = A[i][0] + A[i][1] + ... + A[i][k]$. Plecand de la aceasta idee putem dezvolta o solutie de complexitate $O(N*K)$. Vom calcula $A[i][j][0]$ numarul de propozitii valide formate cu primele $i$ caractere in care ultimul cuvant are $j$ vocale si se termina pe pozitia $i$ si $A[i][j][1]$ numarul de propozitii valide cu primele $i$ caractere in care ultimul cuvant are $j$ vocale si nu se termina pe pozitia $i$. Relatiile de recurenta se obtin usor in $O(1)$ si complexitatea va fi $O(N*K)$ ca timp si $O(K)$ ca memorie (observam ca sunt suficiente doar ultimele doua linii din matrice). Putem optimiza si mai mult aceasta solutie observand ca de fapt daca am calcula $B[i]$ fiind numarul de propozitii valide continand doar primele $i$ caractere, $B[i] = B[i-1]+B[i-2]+...+B[j]$, unde $j$ este cel mai mic posibil astfel incat $S{~j+1~}S{~j+2~}..S{~i~}$ are cel mult $K$ vocale. Cand suntem la pasul $i$ vom avea un indice $j$, la trecerea la pasul $i+1$ se observa ca acest indice ori ramane la fel, ori in cazul in care $S{~i+1~}$ este vocala si aveam deja $K$ vocale indicele $j$ creste pana cand vom avea din nou cel mult $K$ vocale. Astfel putem obtine o solutie in complexitate $O(N)$ ca timp si de asemenea $O(N)$ ca memorie. Oricare din aceste ultime doua solutii obtinea punctajul maxim.',2092,'public',NULL,NULL),('algoritmiada-2009/runda-1/solutii/propozitie','Propozitie','2008-12-14 13:10:58','2008-12-17 20:15:40','h1(#propozitie). \'Propozitie\':problema/propozitie\r\n\r\nFie $S$ sirul initial de caractere. Vom rezolva problema cu ajutorul programarii dinamice. Vom construi o matrice $A$, in care $A[i][j]$ va reprezenta numarul de posibilitati de a obtine propozitii valide cu primele $i$ caractere, iar ultimul cuvant din propozitie sa aibe exact $j$ vocale. Pentru a calcula valorile $A[i][j]$ putem proceda in urmatorul fel: alegem intai subsecventa de litere $S{~j~}S{~j+1~}...S{~i~}$ si o vom considera pe aceasta ultimul cuvant dintr-o propozitie valida. Daca subsecventa de litere de la $k$ la $i$ contine $p$ vocale atunci va trebui sa adunam la $A[i][p]$ toate valorile $A[j-1][q]$, unde $q$ este cuprins intre $0$ si $K$. Evident vom considera doar subsecventele pentru care $p &le; K$. O implementare bruta a acestei solutii va avea complexitatea $O(N*N*K)$. Putem reduce complexitatea la $O(N*N)$ daca vom precalcula $B[i] = A[i]{@ [0] @} + A[i]{@ [1] @} + ... + A[i]{@ [K] @}$. Plecand de la aceasta idee putem dezvolta o solutie de complexitate $O(N*K)$. Vom calcula $A[i][j]{@[0]@}$ numarul de propozitii valide formate cu primele $i$ caractere in care ultimul cuvant are $j$ vocale si se termina pe pozitia $i$ si $A[i][j]{@[1]@}$ numarul de propozitii valide cu primele $i$ caractere in care ultimul cuvant are $j$ vocale si nu se termina pe pozitia $i$. Relatiile de recurenta se obtin usor in $O(1)$ si complexitatea va fi $O(N*K)$ ca timp si $O(K)$ ca memorie (observam ca sunt suficiente doar ultimele doua linii din matrice). Putem optimiza si mai mult aceasta solutie observand ca de fapt daca am calcula $B[i]$ fiind numarul de propozitii valide continand doar primele $i$ caractere, $B[i] = B[i-1]+B[i-2]+...+B[j]$, unde $j$ este cel mai mic posibil astfel incat $S{~j+1~}S{~j+2~}..S{~i~}$ are cel mult $K$ vocale. Cand suntem la pasul $i$ vom avea un indice $j$, la trecerea la pasul $i+1$ se observa ca acest indice ori ramane la fel, ori in cazul in care $S{~i+1~}$ este vocala si aveam deja $K$ vocale indicele $j$ creste pana cand vom avea din nou cel mult $K$ vocale. Astfel putem obtine o solutie in complexitate $O(N)$ ca timp si de asemenea $O(N)$ ca memorie. Oricare din aceste ultime doua solutii obtinea punctajul maxim.',2092,'public',NULL,NULL),('utilizator/florian','Marcu Florian','2007-01-24 13:36:08','2008-12-07 20:20:50','h2. Despre mine...\r\n\r\n* Nume si prenume: Marcu Florian\r\n* elev la Colegiul National Roman-Voda din Roman, clasa a 11-a B,profil mate-info, profesori de info : Florin Moldovanu si Gavril Petru Florin.\r\n* Nascut pe 14 iulie 1991...\r\n* \"Blog\":http://marcuflorian.uv.ro .\r\n* ID mess: floryan_marq\r\n\r\nh2. Premii, reusite, castiguri,etc..\r\n\r\n* Premiul I la concursul international Pro-Soft@NT decembrie, 2007.\r\n* Mentiune la Concursul de Programare DataS-NMG Targu Secuiesc, mai 2007.\r\n* Premiul III OJI 2008, martie 2008.\r\n* Premiul I la concursul Infokid, iunie 2008.\r\n* Mentiune OJI 2007. \r\n\r\nh2. Prieteni pe infoarena \r\n\r\n* ==user(user=\"tabara\" type=\"tiny\")== @\r\n* ==user(user=\"gabitzish1\" type=\"tiny\")== @\r\n* ==user(user=\"blasterz\" type=\"tiny\")== @\r\n* ==user(user=\"c_e_manu\" type=\"tiny\")== @\r\n* ==user(user=\"omega91\" type=\"tiny\")== @\r\n* ==user(user=\"raduzer\" type=\"tiny\")== @\r\n* ==user(user=\"petro\" type=\"tiny\")== @\r\n\r\n\r\n',5748,'public',NULL,NULL),('probleme-cu-secvente','Probleme cu secvente','2008-11-23 19:46:37','2008-12-20 17:12:06','h1. Probleme cu secvenţe\r\n\r\n(Categoria _Diverse_, autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 30em}*{text-align:center} *Cuprins*\r\n* \'Introducere \':probleme-cu-secvente#intro\r\n* \'Problema 1 ( _Subsecvenţa de sumă maximă_ ) \':probleme-cu-secvente#prob1\r\n* \'Problema 2 ( _Maximum Sum_ ) \':probleme-cu-secvente#prob2\r\n* \'Problema 3 ( _SequenceQuery_ ) \':probleme-cu-secvente#prob3\r\n* \'Problema 4 \':probleme-cu-secvente#prob4\r\n* \'Problema 5 \':probleme-cu-secvente#prob5\r\n* \'Problema 6 ( _Secvenţă_ ) \':probleme-cu-secvente#prob6\r\n* \'Problema 7 ( _Agricultura_ )\':probleme-cu-secvente#prob7\r\n* \'Problema 8 ( _Secvenţa 2_ )\':probleme-cu-secvente#prob8\r\n* \'Problema 9 ( _Sum_ )\':probleme-cu-secvente#prob9\r\n* \'Problema 10 ( _Secvenţa 3_ )\':probleme-cu-secvente#prob10\r\n* \'Problema 11 ( _XorMax_ )\':probleme-cu-secvente#prob11\r\n\r\nh2(#intro). Introducere\r\n\r\nAcest articol prezintă o serie de probleme înrudite cu problema subsecvenţei de sumă maximă, însoţite de rezolvări eficiente. Problemele prezentate pot apărea oricând ca subprobleme în concursurile de programare, studierea lor mărind în mod util bagajul de cunoştinţe al unui elev pasionat de algoritmică.\r\n\r\nh2(#prob1). Problema 1 ( _Subsecvenţa de sumă maximă_ )\r\n\r\nSe dă un şir de $N$ numere întregi $(a{~1~}, a{~2~}, ..., a{~N~})$. Să se determine o subsecvenţă $(a{~i~}, a{~i+1~}, ..., a{~j~})$ care să aibă suma maximă.\r\n\r\nh4. Exemplu\r\n\r\nPentru secvenţa de numere $(-1, 2, 3, -4, -2, 2, 1, -3, -2, -3, -4, 9, -2, 1, 7, 8, -19, -7, 2, 4, 3)$, o subsecvenţă de sumă maximă este $(9, -2, 1, 7, 8)$.\r\n\r\nh3. Rezolvare\r\n\r\nPrima rezolvare care ne vine în minte are complexitatea $O(N^3^)$ şi constă în determinarea sumei fiecărei subsecvenţe posibile şi reţinerea maximului acestor sume. Este evident că anumite sume parţiale sunt calculate de mai multe ori.\r\n\r\nPutem reduce complexitatea la $O(N^2^)$ ţinând cont de faptul că suma subsecvenţei $a[i..j]$ este egală cu suma subsecvenţei $a[i..j-1]$, la care se adună $a[j]$. Păstrăm într-un şir $sum[i]$ - suma elementelor din subsecvenţa $a[1..i]$. Pentru a determina suma elementelor din subsecvenţa $a[i..j]$ facem diferenţa $sum[i] - sum[j-1]$.\r\n\r\nIdeea poate fi rafinată calculând pentru fiecare indice $i$ numărul $best[i]$, reprezentând subsecvenţa de sumă maximă cu capătul drept în $i$. Este uşor de observat că $best[i] = max(sum[i] - sum[j-1])$, unde $j$ ia valori de la $1$ la $i$. Relaţia anterioară se mai poate scrie $best[i] = sum[i] - min(sum[j-1 ])$. Obţinem astfel un algoritm liniar care ne determină subsecvenţa de sumă maximă cerută.\r\n\r\n== code(cpp) |\r\nsum[0] = 0;\r\nfor (i = 1; i <= N; i++) sum[i] = a[i] + sum[i-1];\r\nmin = sum[0];\r\nbestSum = -INFINIT;\r\nfor (i = 1; i <= N; i++) {\r\n    best[i] = sum[i] - min;\r\n    if (min > sum[i]) min = sum[i];\r\n    if (bestSum < best[i]) bestSum = best[i];\r\n}\r\n==\r\n\r\nO altă metodă de calcul poate fi dedusă folosind paradigma _Divide Et Impera_. La fiecare pas împărţim şirul în jumătate şi aflăm subsecvenţele de sumă maximă din cele două jumătăţi. După aceea trebuie să găsim subsecvenţa de sumă maximă ce are un capăt în fiecare din cele două jumătăţi ale sirului. Pentru aceasta alipim sufixul de sumă maximă a primei jumătăţi cu prefixul de sumă maximă a celei de-a doua.\r\n\r\n== code(cpp) |\r\nint getMaxSubsequence(int l, int r) {\r\n    if (l == r) return a[l];\r\n    mid = (l + r) / 2;\r\n    bestL = getMaxSubsequence(l, mid);\r\n    bestR = getMaxSubsequence(mid + 1, r);\r\n    suf = 0; \r\n    pre = 0; \r\n    maxSuf = -INFINIT; \r\n    maxPre = -INFINIT;\r\n    for (i = mid; i >= l; i--) {\r\n        suf += a[i];\r\n        if (maxSuf < suf) maxSuf = suf;\r\n    }\r\n    for (i = mid + 1; i <= r; i++) {\r\n        pre += a[i];\r\n        if (maxPre < pre) maxPre = pre;    \r\n    }\r\n    return max(bestL, max(bestR, maxPre + maxSuf));\r\n}\r\n==\r\n\r\nO idee bazată pe paradigma programării dinamice ar fi să folosim un şir $best[ i ]$, reprezentând suma maximă a unei subsecvenţe ce se termină în $a[i]$. Problema se rezolvă cu următoarea formulă de recurenţă: $best[i] = max(a[i], best[i-1] + a[i])$. Formula poate fi demonstrată prin inducţie matematică.\r\n\r\nO ultimă idee ar fi să partiţionăm şirul în subsecvenţe încât fiecare să aibă ambele capete cât mai mici posibile şi suma elementelor subsecvenţei să fie negativă. Pentru exemplul dat avem următoarea partiţionare $[-1], [2, 3, -4, -2], [2, 1, -3, -2], [-3], [-4], [9, -2, 1, 7, 8, -19, -7], [2, 4, 3]$. O subsecvenţă de sumă maximă va avea primul capăt la începutul unei astfel de subsecvenţe, acest lucru explicându-se prin faptul că în caz contrar secvenţa poate fi mărită în stânga (orice secvenţă din cele alese pentru partiţionare are toate prefixele de sumă pozitivă, în afară de prefixul ce reprezintă întreaga subsecvenţă). De asemenea, orice subsecvenţă de sumă maximă nu va conţine elemente din altă parte a partiţiei, pentru că dacă subsecvenţa se întinde pe mai multe părţi, atunci putem elimina prefixul subsecvenţei care reprezintă o parte a partiţiei, acea parte având suma negativă.\r\n\r\n== code(cpp) |\r\nsum = -INFINIT;\r\nbestSum = -INFINIT;\r\nfor (i = 1; i <= N; i++) {\r\n    sum += a[i];\r\n    if (sum < 0) {\r\n        sum = 0;\r\n        continue;\r\n    } else \r\n    if (sum >= bestSum) bestSum = sum;      \r\n}\r\n==\r\n\r\nh2(#prob2). Problema 2 ( \"_Maximum Sum_\":http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&Itemid=8&category=3&page=show_problem&problem=44 )\r\n\r\nSe dă o matrice de dimensiuni $NxN$ cu elemente întregi. Se cere determinarea unei submatrici a cărei elemente au suma maximă. \r\n\r\nh4. Exemplu\r\n\r\nPentru matricea<tex>\\[ \\left( \\begin{array}{cccc}0 & -2 & -7 & 0 \\\\9 & 2 & -6 & 2 \\\\-4 & 1 & -4 & 1 \\\\-1 & 8 & 0 & -2 \\end{array} \\right)\\]</tex>submatricea de sumă maximă este următoarea:<tex>\\[ \\left( \\begin{array}{cc}9 & 2 \\\\-4 & 1 \\\\-1 & 8 \\end{array} \\right)\\]</tex>\r\n\r\nh3. Rezolvare\r\n\r\nPutem folosi trucul construirii sumelor parţiale din rezolvarea anterioară, pentru cazul *2D*. Păstrăm în $sum[i][j]$ suma tuturor elementelor $a[i{~1~}][j{~1~}]$ cu proprietatea că $1 <= i{~1~} <= i$, şi $1 <= j{~1~} <= j$. Putem calcula sumele prin metoda programării dinamice (complexitate $O(N^2^)$) folosind formula $sum[i][j] = a[i][j] + sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1]$. Acum pentru a calcula suma elementelor din matricea cu colţurile $(i{~1~}, j{~1~})$ şi $(i{~2~}, j{~2~})$, unde $i{~1~} <= i{~2~}$ şi $j{~1~} <= j{~2~}$, este suficient să facem calculul $sum[i{~2~}][j{~2~}] - sum[i{~1~}-1][j{~2~}] - sum[i{~2~}][j{~1~}-1] + sum[i{~1~}-1][j{~1~}-1]$. Astfel putem evalua suma din fiecare submatrice în timp constant, deci rezolvarea are ordinul de complexitate $O(N^4^)$.\r\n\r\nO altă idee ar fi ca pentru fiecare pereche $(i{~1~}, i{~2~})$ fixată să determinăm perechea optimă $(j{~1~}, j{~2~})$. Dacă avem liniile $i{~1~}$ şi $i{~2~}$ fixate atunci problema se transformă din una bidimensională în una unidimensională. Astfel pentru fiecare coloană $j$ vom considera $b[j]$ ca sumă a elementelor $a[i][j]$ cu proprietatea că $i{~1~} <= i <= i{~2~}$. În exemplul nostru, dacă $i{~1~} = 2$ şi $i{~2~} = 3$, atunci avem $b{~1~} = 9 + (-4)$, $b{~2~} = 2 + 1$, $b{~3~} = (-6) + (-4)$ şi $b{~4~} = 2 + 1$. Pentru a rezolva problema unidimensională folosim unul din algoritmii liniari prezentaţi mai sus, astfel obţinându-se un algoritm de complexitate totală $O(N^3^)$. Acest truc de a fixa două linii pentru a transforma problema în una unidimensională este util în multe probleme pe matrice sau cu puncte în plan.\r\n\r\nCel mai bun algoritm cunoscut pentru această problemă are complexitatea <tex>O(N^{3\\sqrt{\\frac{\\log \\log N}{\\log N}}})</tex> şi este mai mult un algoritm teoretic decât unul practic, uşor implementabil.\r\n\r\nh2(#prob3). Problema 3 (\'SequenceQuery\':problema/sequencequery - Bursele Agora 2005/2006 Runda 1)\r\n\r\nSe consideră un şir $A = (a{~1~}, a{~2~}, ..., a{~N~})$, format din numere întregi $(-100.000 <= a{~i~} <= 100.000)$, şi $M$ perechi de numere $(x, y)$ $(1 <= N, M <= 100.000)$. Pentru fiecare pereche ordonată de indici $(x, y)$ trebuie determinată subsecvenţa de sumă maximă a subşirului $a{~x~}, a{~x+1~}, ..., a{~y~}$. Subsecvenţele alese trebuie să conţină cel puţin un element. \r\n\r\nh4. Exemplu\r\n\r\nPentru şirul $(-1, 2, 3, -2, 4, -3, 8, -3, 1)$ şi intervalele $[1, 5]$, $[4, 8]$ si $[6, 6]$ avem soluţiile: \r\n\r\n* $7$ pentru subsecvenţa $(-1, *2*, *3*, *-2*, *4*)$;\r\n\r\n* $9$ pentru subsecvenţa $(-2, *4*, *-3*, *8*, -3)$;\r\n\r\n* $-3$ pentru subsecvenţa $({*-3*})$.\r\n\r\nh3. Rezolvare\r\n\r\nPutem obţine un algoritm de complexitate $O(MN)$ folosind algoritmii liniari din prima problemă, dar să vedem cum putem reduce complexitatea folosind alte abordări. Mai întâi calculăm şirul $sum$ al sumelor parţiale, după care împărţim şirul în $k$ subsecvenţe de lungimi egale $[n/k]$, şi păstrăm următoarele informaţii pentru fiecare din ele:\r\n\r\n* $max[i]$ - cea mai mare valoare $sum[j]$, unde $n/k * (i-1) < j <= n/k * i$;\r\n\r\n* $min[i]$ - cel mai mic $sum[j-1]$, unde $n/k * (i-1) < j <= n/k * i$;\r\n\r\n* $best[i]$ - valoarea subsecventei de suma maxima a secventei curente.\r\n\r\nAcum, pentru a afla subsecvenţa de sumă maximă a subsecvenţei $a[x..y]$ studiem cele două cazuri posibile:\r\n\r\n1. Dacă elementele de indice $x$ şi $y$ aparţin aceleiaşi subsecvenţe, atunci putem găsi ceea ce căutăm folosind algoritmul liniar direct pe şirul $a[x..y]$ (complexitate $O(n/k)$).\r\n\r\n2. Dacă nu sunt în aceeaşi secvenţă, atunci vom împărţi şirul $a[x..y]$ în:\r\n\r\n* un prefix de subsecvenţă din cele ce aparţin partiţionării,\r\n\r\n* un sufix de subsecvenţă,\r\n\r\n* zero sau mai multe subsecvenţe complete ce aparţin partiţionării,\r\n\r\ndupă care rezolvăm problema pentru sufix şi prefix prin metoda liniară ( {$O(n/k)$} ), şi determinăm în $O(1)$ pentru fiecare bucată în care este spart şirul $a[x..y]$ subsecvenţa ei de sumă maximă.\r\n\r\nMai rămâne să găsim subsecvenţa de sumă maximă cu capătul în bucăţi diferite. Pentru două bucăţi fixate $i <= j$, subsecvenţa de sumă maximă ce are câte un capăt în fiecare bucatăm are valoarea $max[j] - min[i]$. Determinarea subsecvenţei de sumă maximă cu capetele în bucăţi diferite devine astfel de complexitate $O(k)$. Deci pentru a rezolva o întrebare trebuie să facem $O(n/k + k)$ calcule. Pentru a reduce complexitatea problemei considerăm pe $k = sqrt(n)$. Complexitatea totală a acestei soluţii este $O(N + M sqrt(N))$.\r\n\r\nSă vedem ce se întâmplă pe exemplu:\r\n\r\n|_. $a$ | - | $-1$ | $2$ | $3$ | $-2$ | $4$ | $-3$ | $8$ | $-3$ | $1$ |\r\n|_. $sum$ | $0$ | $-1$ | $1$ | $4$ | $2$ | $6$ | $3$ | $11$ | $8$ | $9$ |\r\n\r\nŞirul e împărţit în trei subsecvenţe $[-1, 2, 3], [-2, 4, -3], [8, -3, 1]$:\r\n\r\n|_. $max$ | $4$ | $6$ | $11$ |\r\n|_. $min$ | $-1$ | $2$ | $8$ |\r\n|_. $best$ | $5$ | $4$ | $8$ |\r\n\r\nPentru a răspunde la întrebarea $[1, 5]$ trebuie să răspundem la cele două subsecvenţe componente $[1..3]$ şi $[4..5]$. Soluţia optimă pentru $[1..3]$ este $best[1] = 5$. Soluţia optimă pentru $[4..5]$ o determinăm folosind algoritmul liniar, ea fiind $4$. Acum, pentru a determina subsecvenţa de sumă maximă cu câte un capăt în fiecare interval folosim formula $max(sum[i]) - min(sum[j-1])$, unde $4 <= i <= 5$ şi $1 <= j <= 3$. Valoarea $max(sum[i])$ o găsim parcurgând intervalul $[4, 5]$ ca fiind $6$, iar valoarea $min(sum[j-1])$ o avem deja calculată în $min[1]$. De aici obţinem rezultatul $7$.\r\n\r\nO soluţie similară poate fi obţinută cu ajutorul arborilor de intervale. Mai întâi creăm arborele de intervale. Pentru fiecare interval aflăm elementele $min$, $max$ şi $best$ astfel:\r\n\r\n* $min[x..y] = minim(min[x..(x+y)/2], min[(x+y)/2 + 1 .. y])$;\r\n\r\n* $max[x..y] = maxim(max[x..(x+y)/2], max[(x+y)/2 + 1 .. y])$;\r\n\r\n* $best[x..y] = maxim(best[x..(x+y)/2], maxim(best[(x+y)/2 + 1 .. y], max[(x+y)/2 + 1 .. y] - min[x..(x+y)/2]))$.\r\n\r\nAcum pentru a răspunde la întrebările din problemă fiecare interval va fi împărţit în $O(log N)$ subintervale canonice care apar în arborele de intervale. Apoi printr-o parcurgere asemănătoare celei din rezolvarea anterioară se poate obţine rezultatul pentru fiecare întrebare în $O(log N)$. Soluţia va avea complexitatea $O(N + M log N)$.\r\n\r\nÎn următorul desen observăm structura unui arbore de intervale pentru un şir cu $16$ elemente. Daca se pune întrebarea $[2, 11]$ acest interval va fi spart în intervalele $[2, 2], [3, 4], [5, 8], [9, 10], [11, 11]$.\r\n\r\nPrezentăm procedura de construire a arborelui, implementată în _java_:\r\n\r\n== code(java) |\r\npublic void build_tree(int index, int low, int high) {\r\n    if (low == high) {\r\n        if (low != 0) aint[index] = new Node(low, high, a[low] - a[low - 1], a[low], a[low]);\r\n        else aint[index] = new Node(low, high, 0, 0, 0);\r\n    }\r\n    else {\r\n        aint[index] = new Node(low, high, -INFINIT, -INFINIT, INFINIT);\r\n        int mid = (low + high) / 2;\r\n        build_tree(2 * index, low, mid);\r\n        build_tree(2 * index + 1, mid + 1, high);\r\n        aint[index].maxS = Math.max(aint[2 * index].maxS,Math.max(aint[2 * index + 1].maxS,aint[2 * index + 1].max - aint[2 * index].min));\r\n        aint[index].max = Math.max(aint[2 * index].max,aint[2 * index + 1].max);\r\n        aint[index].min = Math.min(aint[2 * index].min,aint[2 * index + 1].min);\r\n    }\r\n}\r\n==\r\n\r\nŞi procedura care răspunde la întrebări tot în _java_:\r\n\r\n== code(java) |\r\nlong minPrefix; \r\nint x, y;\r\npublic long queryTree(int index, int low, int high) {\r\n    if (x <= low && high <= y) {\r\n        long maxRet = aint[index].maxS;\r\n        if (minPrefix != infinity) {\r\n            maxRet = Math.max(maxRet, aint[index].max - minPrefix);\r\n        }\r\n        minPrefix = Math.min(minPrefix, aint[index].min);\r\n        return maxRet;\r\n    }\r\n    else {\r\n        int mid = (low + high) / 2;\r\n        if (x <= mid && mid < y) return  Math.max(queryTree(2 * index, low, mid), queryTree(2 * index + 1, mid + 1, high));\r\n        else if (x > mid) return queryTree(2 * index + 1, mid + 1, high);\r\n            else return queryTree(2 * index, low, mid);\r\n    }\r\n}\r\n==\r\n\r\nh2(#prob4). Problema 4 ( ACM ICPC NWERC 97, olimpiada online 2000, campion 2001 )\r\n\r\nSe dă un şir $(a{~1~}, a{~2~}, ..., a{~N~})$ format din numere întregi. Se cere să se determine subsecvenţa $a[i..j]$ care are modulul sumei elementelor minim.\r\n\r\nh4. Exemplu\r\n\r\nPentru şirul $(2, 8, -6, -6, 9, 4, -3)$, subsecvenţa este $(4, -3)$, având suma în modul $1 = |4 - 3|$.\r\n\r\nh3. Rezolvare\r\n\r\nFacem mai întâi şirul sumelor parţiale. Pentru oricare două elemente $sum[i]$ şi $sum[j]$ ($i != j$) modulul sumei unei subsecvenţe din şir va fi $|sum[i] - sum[j]|$. Dacă $i < j$, atunci secvenţa va fi $a[i+1..j]$, iar dacă $j < i$, atunci secvenţa va fi $a[j+1 .. i]$. Astfel, pentru a găsi subsecvenţa de modul minim trebuie, de fapt, să găsim perechea de indici $i$ şi $j$ astfel ca $|sum[i] - sum[j]|$ să fie minim. Sortând şirul sumelor parţiale şi luând o pereche de indici $i < j$, atunci $sum[i] < sum[j]$, iar $|sum[j] - sum[i]| = sum[j] - sum[i]$. Pentru a găsi perechea $(i, j)$ pentru care $i < j$ şi $sum[j] - sum[i]$ este minim, trebuie ca $i$ să fie egal cu $j + 1$. Astfel obţinem un algoritm de complexitate $O(N log N)$.\r\n\r\nSă vedem cum merge pe exemplul prezentat:\r\n\r\n|_. $a$ | - | $2$ | $8$ | $-6$ | $-6$ | $9$ | $4$ | $-3$ |\r\n|_. $sum$ | $0$ | $2$ | $10$ | $4$ | $-2$ | $7$ | $11$ | $8$ |\r\n|_. $ind$ | $0$ | $1$ | $2$ | $3$ | $4$ | $5$ | $6$ | $7$ |\r\n\r\nÎn şirul $ind$ vom păstra indicii reali ai sumelor parţiale. După sortare avem:\r\n\r\n|_. $sum$ | $-2$ | $0$ | $2$ | $4$ | $7$ | $8$ | $10$ | $11$ | \r\n|_. $ind$ | $4$ | $0$ | $1$ | $4$ | $5$ | $7$ | $2$ | $6$ |\r\n\r\nO secvenţă de modul $2$ ar fi cea reprezentată de sumele $8$ şi $10$, cu indicii $7$ şi $2$. Această secvenţă este $(-6, -6, 9, 4, -3)$. Observăm ca cea mai mică diferenţă între termeni consecutivi e cea dintre $8$ şi $7$, care au indicii $7$ şi $5$, de unde obţinem că subsecvenţa de modul minim este $(4, -3)$. \r\n\r\nh2(#prob5). Problema 5 ( USACO )\r\n\r\nSe dă un şir $(a{~1~}, a{~2~}, ..., a{~N~})$ format din $N (1 <= N <= 100 000)$ numere întregi ($1 <= a{~i~} <= 2 000$). Se cere să se determine subsecvenţa $a[i..i + K - 1]$ cu media aritmetică a elementelor maximă ( $K >= F, 1 <= F <= N$). \r\n\r\nh4. Exemplu\r\n\r\nPentru şirul $(6, 4, 2, 10, 3, 8, 5, 9, 4, 1)$ şi $F = 6$ soluţia optimă este $(10, 3, 8, 5, 9, 4)$, cu media $6.5$.\r\n\r\nh3. Rezolvare\r\n\r\nFie $X$ un număr real. Considerând şirul $b$, obţinut prin transformarea $b{~i~} = a{~i~} - X$, atunci toate subsecvenţele şirului $b$ vor avea valoarea mediei elementelor lor cu $X$ mai mică decât valoarea subsecvenţelor corespunzătoare din şirul $a$. Observăm apariţia a trei cazuri:\r\n\r\n* Dacă subsecvenţa de sumă maximă din $b$ are valoarea mai mare ca $0$, atunci şi media ei va fi mai mare ca $0$. Rezultă astfel că şi media subsecvenţei corespunzătoare din şirul $a$ va fi mai mare decât $X$, deci media maximă a unei subsecvenţe din $a$ va fi mai mare ca $X$. \r\n\r\n* Cand subsecvenţa de sumă maximă din şirul $b$ are media mai mică decât $0$, atunci orice subsecvenţă din şirul $a$ va avea media mai mică decât $X$. \r\n\r\n* În cazul în care subsecvenţa de sumă maximă a şirului $b$ are valoarea egală cu zero, atunci subsecvenţa de medie maximă a şirului $a$ are media $X$.\r\n\r\nAstfel putem face o căutare binară pentru a determina valoarea $X$ a mediei maxime. Ne mai rămâne să determinăm un algoritm eficient pentru găsirea subsecvenţei de sumă maximă de lungime cel puţin $F$. O asemenea soluţie urmăreşte una din ideile din prima problemă: fie $best[i]$ subsecvenţa de sumă maximă ce se termină în $a[i]$. Evident $best[i] = max(a[i], best[i - 1] + a[i])$. Acum secvenţa de sumă maximă ce se termină în $a[i]$, de lungime cel puţin $F$ se găseşte ca $a[i] + a[i - 1] + .. + a[i - F + 2] + best[i - F + 1]$. Această relaţie poate fi calculată în $O(1)$ dacă ne folosim de trucul sumelor parţiale. Complexitatea finală este $O(N log C)$, unde $C$ e valoarea maximă a lui $a{~i~}$.\r\n\r\nh2(#prob6). Problema 6 (\'Secvenţă\':problema/secventa)\r\n\r\nGigel are un şir de $N$ numere întregi. Toată lumea ştie că o secvenţă este un subşir de numere care apar pe poziţii consecutive în şirul iniţial. Gigel a definit baza unei secvenţe ca fiind minimul valorilor elementelor din secvenţa respectivă. Fiind dat un număr natural $K$, determinaţi pentru Gigel o secvenţă de lungime cel puţin $K$, cu baza maximă. $( 1 <= K <= N <= 500 000)$\r\n\r\nh4. Exemplu\r\n\r\nPentru $K = 3$ şi şirul $(-1, 2, 3, 1, 0, 4, 8, 6)$, secvenţa de bază maximă este $(4, 8, 6)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPresupunem că orice secvenţă optimă ar avea lungimea mai mare decât $K$. Atunci putem obţine o secvenţă mai mică, cu aceeaşi bază eliminând unul din capetele unei secvenţe optime. Deci este de ajuns să cautăm secvenţele optime de lungime exact $K$.\r\n\r\nAcum putem face o parcurgere a şirului pentru a rezolva problema. Mai întâi punem într-un $min-heap$ $K$ elemente, verificăm vârful heapului şi obţinem astfel minimul secvenţei $a[1..k]$. Apoi eliminăm elementul $a[ 1 ]$ din heap şi inserăm elementul $a[K+1]$. Prin verificarea vârfului heapului obţinem minimul secvenţei $a[2..K+1]$. Continuăm procedeul până aflăm elementul minim pentru fiecare subsecvenţă de lungime $K$ a şirului $a$ ( complexitate $O(N log N)$ ). Există şi alte soluţii pentru găsirea elementului minim al unei subsecvenţe, precum folosirea unui arbore de intervale sau folosirea tehnicii $O(n log n)/O(1)$ pentru problema _RMQ_, dar obţinem tot soluţii de complexitate $O(N log N)$.\r\n\r\nO observaţie importantă este aceea că dacă vrem să vedem minimul secvenţei ce se termină în $i$ şi avem $j{~1~} < j{~2~} <= i$ şi $a[j{~1~}] >= a[j{~2~}]$, atunci evident $a[j{~1~}]$ nu va fi minimul secvenţei ce se termină în $i$. Folosim o structură de date ca la soluţia cu heapuri, care adaugă elemente noi şi şterge elemente vechi, dar pe lângă elementele ce au fost inserate acum $k$ paşi şi trebuie şterse, mai ştergem şi elementele mai noi care nu ne vor mai fi utile, după cum este $a[j{~2~}]$ mai sus. Ca structură de date folosim o listă în care putem insera şi şterge de la ambele capete ( *deque* ). Fiecare element inserat în deque va fi o pereche de valori, valoarea din şir şi indexul din şir $(a[i], i)$. Când o valoare este inserată în şir, ea este pusă la capătul din dreapta al şirului, dar înainte de inserare cât timp elementul din capătul şirului are valoarea mai mare decât $a[i]$ el este eliminat. La fiecare pas după o inserţie se verifică dacă elementul din capătul din stânga este mai bătrân de $K$ iteraţii.\r\n\r\nDin cauza modului în care se fac inserţiile şi ştergerile, şirul va fi sortat totdeauna crescător după indecşi şi crescător după valori. Tot timpul ultimul element din stivă va conţine valoarea bazei. Acest algoritm are complexitatea $O(N)$ pentru că fiecare element este inserat şi şters din deque cel mult o dată.\r\n\r\nSă vedem cum funcţionează rezolvarea pe un exemplu : $a = (-1, 2, 3, 1, 0, 4, 8, 6)$\r\n\r\n* inserăm $(-1, 1)$\r\nlista devine: $(-1, 1)$\r\n \r\n\r\n* inserăm $(2, 2)$\r\nlista devine: $(-1, 1) (2, 2)$\r\n\r\n\r\n* inserăm $(3, 3)$\r\nlista devine: $(-1, 1) (2, 2) (3, 3)$\r\nelementul minim al secvenţei $a[1..3]$ este $-1$\r\n\r\n\r\n* inserăm $(1, 4)$\r\nştergem $(3, 3)$ şi $(2, 2)$\r\nştergem $(-1, 1)$ ( inserat acum $4$ paşi )\r\nlista de vine: $(1, 4)$\r\nelementul minim al secvenţei $a[2..4]$ este $1$\r\n\r\n\r\n* inserăm $(0, 5)$\r\nştergem $(1, 4)$\r\nlista devine: $(0, 5)$\r\nelementul minim al secvenţei $a[3..5]$ este $0$.\r\n\r\n\r\n* inserăm $(4, 6)$\r\nlista devine: $(0, 5) (4, 6)$\r\nelementul minim al secvenţei $a[4..6]$ este $0$\r\n\r\n\r\n* inserăm $(8, 7)$\r\nlista devine: $(0, 5) (4, 6) (8, 7)$\r\nelementul minim al secvenţei $a[5..7]$ este $0$\r\n\r\n\r\n* inserăm $(6, 8)$\r\nştergem $(8, 7)$\r\nştergem $(0, 5)$ ( inserat acum $4$ paşi )\r\nlista devine: $(4, 6) (6, 8)$\r\nelementul minim al secvenţei $a[6..8]$ este $4$\r\n\r\nh2(#prob7). Problema 7 ( _Agricultura_ - Algoritmus )\r\n\r\nVasilica vrea să se apuce de agricultură şi, prin urmare, să cumpere o parcelă de teren. Harta pusă la dispoziţie de către primăria oraşului în care locuieşte Vasilică se poate reprezenta sub forma unei matrice de dimensiuni $NxM (2 <= N, M <= 150)$, fiecare $m^2^$ de teren fiind reprezentat printr-un element din matrice. Pentru fiecare $m^2^$ de pământ se cunoaşte altitudinea (faţă de nivelul mării) la care se află acesta. Agricultorul nostru doreşte să cumpere o parcelă de formă dreptunghiulară dar, deoarece are de gând să se ocupe de culturi foarte pretenţioase la modificări de nivel, diferenţa dintre valorile care indică altitudinea maximă şi cea minimă din parcelă trebuie să fie mai mică decât o valoare dată $K (1 <= K <= 1 000)$. Mai mult, suprafaţa pe care Vasilică o va achiziţiona trebuie să fie cât mai mare posibil.\r\n\r\nh4. Exemplu\r\n\r\nDe exemplu pentru $K = 3$ şi matricea <tex>\\[ \\left( \\begin{array}{cccccc}1 & 1 & 3 & 1 & 2 & 7 \\\\9 & 2 & 3 & 2 & 3 & 2 \\\\7 & 8 & 2 & 3 & 1 & 5 \\\\4 & 5 & 6 & 0 & 1 & 4 \\end{array} \\right)\\]</tex>, soluţia optimă va avea $9$ celule.\r\n\r\nh3. Rezolvare:\r\n\r\nProblema constă în determinarea submatricei cu număr maxim de celule în care diferenţa între valoarea maximă şi valoarea minimă este mai mică decât $K$. Vom folosi ideea de la problema cu subsecvenţa de sumă maximă pe matrice, adică vom fixa două linii $i{~1~}$ şi $i{~2~}$. Acum pentru fiecare coloană $j$ păstrăm în $m[j]$ elementul minim şi în $M[j]$ elementul maxim $a[i][j]$ cu $i{~1~} <= i <= i{~2~}$. Astfel la fiecare pas trebuie acum să rezolvăm problema determinării unei subsecvenţe de lungime maximă pentru care diferenţa între elementul maxim şi minim este mai mică decât $K$. Folosind un *max-heap* şi un *min-heap* putem parcurge elementele şirurilor $M$ şi $m$ în ordine inserând la fiecare pas elemente în heap şi determinând cea mai lungă secvenţă ce se termină în $i$ cu proprietatea dată. Vom ţine un al 2-lea indice $j$, iniţial $0$, care atâta timp cât diferenţa între elementul maxim din *max-heap* cu elementul minim din *min-heap* este mai mare sau egală cu $K$, vom scoate din heapuri elementele $M[j]$, respectiv $m[j]$ şi îl vom incrementa pe $j$ ( complexitate $O(N^3^ log N)$ ). Dacă în loc de heapuri folosim *deque*-uri, atunci acest algoritm va avea complexitatea $O(N^3^)$.\r\n\r\nh2(#prob8). Problema 8 ( \'Secvenţa 2\':problema/secv2 )\r\n\r\nGigel s-a decis să devină olimpic la informatică, poate aşa va reuşi să-şi rezolve singur problemele, şi nu va mai cere ajutorul vostru! La ora de informatică, profesoara lui i-a dat să rezolve problema secvenţei de sumă maximă: \"Gigele, eu iţi dau un şir de $N$ numere întregi, iar tu trebuie să găseşti o secvenţă ( adică un subşir de numere care apar pe poziţii consecutive în şirul iniţial ) cu suma elementelor maximă!\". După vreo $30$ de minute, Gigel s-a ridicat mândru şi a zis: \"Am găsit algoritmul de complexitate optimă, doamna profesoară!\". Ca temă pentru acasă Gigel are de rezolvat aproape aceeaşi problemă: trebuie să găsească secvenţa de sumă maximă de lungime cel puţin $K (1 <= k <= N <= 50 000)$. Gigel încă nu ştie destul de multă informatică ca să poata rezolva această problemă, dar poate îl ajutaţi voi! Scrieţi un program care rezolvă problema din tema lui Gigel.\r\n\r\nh4. Exemplu\r\n\r\nDe exemplu pentru şirul $(0, -6, 2, 1, 4, -1,  3, -5)$ şi $K = 3$, soluţia optimă este $(2, 1, 4, -1, 3)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPutem folosi rezolvarea liniară bazată pe programare dinamică prezentată ca subalgoritm în soluţia problemei $5$, dar putem simplifica logica din acea rezolvare. Vom folosi şirul sumelor parţiale $sum$, iar pentru a determina subsecvenţa de sumă maximă ce se termină în $i$ şi are lungimea cel puţin $K$ trebuie să găsim $sum[j]$ minim astfel ca $j < i - K$. Parcurgem lista, şi la pasul $i$ determinăm $best[i] = sum[i] - min(sum[j])$, $j < i - K$. Comparăm minimul curent cu $sum[i-K]$ şi trecem la pasul următor ( complexitate $O(N)$ ).\r\n\r\nh2(#prob9). Problema 9 ( _Sum_ - Stelele Informaticii 2003 )\r\n\r\nSe dă un şir de numere întregi. Se caută un subşir cu lungimea cuprinsă între $L$ şi $U$, format din elemente consecutive ale şirului iniţial, cu suma elementelor maximă $(1 <= L <= U <= N <= 100 000)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPentru fiecare $i$ este de ajuns să aflăm valoarea expresiei $sum[i] - sum[j]$, unde $i - L > j >= i - U$. Pentru a determina valoarea optimă pentru $sum[j]$ putem folosi un heap de dimensiune $U - L$, sau putem folosi tehnici de determinare a valorii minime într-un interval dat ( complexitate $O(N log (U - L)$ ) ).\r\n\r\nAltă abordare de aflare a minimelor unor secvenţe de lungime dată (în cazul acesta lungimea este $U - L$ ) a fost prezentată în rezolvarea problemei $6$. Folosind acea tehnică obţinem o rezolvare de complexitate liniară.\r\n\r\nO altă rezolvare frumoasă prezentată în [4] este următoarea: Spunem că o secvenţă este negativă spre stânga dacă suma oricărui prefix ( în afară de secvenţa în sine ) al secvenţei este negativ sau zero. O partiţie a secvenţei $A = (A{~1~},A{~2~},...,A{~k~})$ este minimală negativă spre stânga dacă fiecare $A{~i~}$ este negativă spre stânga, iar suma elementelor lui $A{~i~}$ este strict pozitivă dacă $i != k$. De exemplu secvenţa $(-4, 1, -2, 3)$ este negativă la stânga, pe când secvenţa $(5, -3, 4, -1, 2, -6)$ nu este. Partiţia $(5) (-3, 4) (-1, 2) (-6)$ este minimală negativă la stânga.\r\n\r\nPentru fiecare element din partiţie ţinem minte un pointer $p[i]$ spre ultimul element din subsecvenţa din care face parte. Fiecare interval $(i, p[i])$ va corespunde celei mai scurte subsecvenţe care începe în $i$ şi are suma pozitivă. Pentru a determina o soluţie a problemei pentru fiecare $i$ din care poate începe o subsecvenţă de sumă maximă, ne vom plimba cu un pointer $j$ astfel ca $j$ să fie cât mai depărtat de $i$ şi $j - i + 1 <= U$. Obţinem astfel de fiecare dată o subsecvenţă de sumă maximă ce începe în $i$, cu lungimea mai mică sau egală cu $U$. Indicele $j$ va fi întotdeauna un capăt de secvenţă negativă la stânga şi la fiecare mărire a lui $i$ verificăm dacă lui $j$ îi putem atribui valoarea $p[j+1]$ ( adică dacă $p[j+1] - i + 1 <= U$ ). Dacă secvenţa de sumă maximă de lungime cel mult $U$ ce începe în $i$ are lungimea mai mică decât $L$, atunci secvenţa de sumă maximă cu lungimea cuprinsă între $L$ şi $U$ are lungimea exact $L$ ( complexitate $O(N)$ ).\r\n\r\nh2(#prob10). Problema 10 ( \'Secvenţa 3\':problema/secv3)\r\n\r\nGigel este o persoană cu o imaginaţie foarte bogată, mai ales când doarme! Într-o noapte a visat că are de îndeplinit o sarcină foarte bizară: trebuie să aleagă o secvenţă (adica un subşir de elemente care apar pe poziţii consecutive în şirul iniţial) din $N$ elemente pentru care se cunosc costul şi timpul. Secvenţa aleasă trebuia să fie de lungime minim $L$ şi maxim $U$, iar suma costurilor elementelor secvenţei împărţiţă la suma timpurilor elementelor secvenţei să fie maximă $(1 <= L <= U <= N <= 30 000)$.\r\n\r\nh4. Exemplu\r\n\r\nPentru $L = 1, R = 2$ şi şirurile $c = ( 1, 1, 3, 2, 5 )$ şi $t = ( 4, 2, 5, 3, 6 )$, subsecvenţa cea mai eficientă are costul $0.83$.\r\n\r\nh3. Rezolvare:\r\n\r\nProcedăm ca la problema $5$ şi căutăm binar valoarea optimă. Şirul va fi transformat în $b[i] = c[i] - t[i]*X$. Acum trebuie să mai rezolvăm subproblema care cere să determinăm o subsecvenţă de sumă maximă pentru care lungimea se află între $L$ şi $U$. Această subproblemă a fost soluţionată în problema anterioară, unde s-a găsit un algoritm liniar. Astfel soluţia acestei probleme are complexitatea $O(N log C)$.\r\n\r\nh2(#prob11). Problema 11 ( \'XorMax\':problema/xormax )\r\n\r\nPaftenie este un elev eminent. De multe ori îşi pune întrebări care au sau nu răspunsuri. De data aceasta i-a venit o idee nouă. El are un şir de $N$ numere întregi nenegative şi vrea să aleagă o secvenţă a şirului $(a{~i~}, a{~i+1~}, ..., a{~j~})$ astfel încât $a{~i~} xor a{~i+1~} xor ... xor a{~j~}$ să fie maxim ( $1 <= N <= 100 000$, numerele şirului sunt strict mai mici decât $221$ ).\r\n\r\nh4. Exemplu\r\n\r\nPentru şirul $(1, 0, 5, 4, 2)$, secvenţa cu valoarea sumei _xor_ maximă este $(4, 2)$, cu suma $6$. \r\n\r\nh3. Rezolvare:\r\n\r\nSuma _xor_ a două numere este de fapt adunare binară fără transport, fapt care o face similară operaţiei _modulo_. Problema e asemănătoare cu cea a subsecvenţei de modul maxim. Vom obţine toate sumele _xor_ parţiale şi pentru a vedea pentru $sum[i]$ perechea optimă cu care crează o sumă cât mai mare trebuie să găsim acea sumă $sum[j]$ astfel că fiecare bit al lui $sum[i]$ să fie diferit de fiecare bit al lui $sum[j]$, dacă acest lucru este posibil. Pentru a face această căutare cât mai eficientă, putem menţine sumele $sum[i]$ ca şiruri de caractere $0$ sau $1$ într-un trie [5]. Structura de trie pentru cazul când alfabetul are dimensiunea $2$ este identică cu cea de heap. Această soluţie are complexitatea $O(N log C)$.\r\n',4297,'public',NULL,NULL),('2-sat','Problema satisfiabilității formulelor logice de ordinul doi','2008-12-09 15:55:03','2008-12-21 12:58:09','h1. Problema satisfiabilităţii formulelor logice de ordinul doi\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"marius\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 30em}*{text-align:center} *Conţinut:*\r\n* {\'Introducere\':2-sat#introducere}\r\n* {\'Forme normale ale formulelor logice\':2-sat#forme-normale}\r\n* {\'SAT, 3-SAT, 2-SAT\':2-sat#overview-sat}\r\n* {\'Soluţii pentru 2-SAT\':2-sat#solutii-2-sat}\r\n** {\'Soluţie $O(M * 2^N^)$\':2-sat#solutie-1}\r\n** {\'Soluţie $O(N * M)$\':2-sat#solutie-2}\r\n** {\'Soluţie $O(N^2^)$\':2-sat#solutie-3}\r\n** {\'Soluţie $O(M + N)$\':2-sat#solutie-4}\r\n* {\'Aplicaţii\':2-sat#aplicatii}\r\n** {\'Party &#40;preONI 2003/2004&#41;\':2-sat#party}\r\n** {\'Cigraf\':2-sat#cigraf}\r\n** {\'Peace Commission &#40;Polish Olympiad in Informatics, 2001&#41;\':2-sat#peace-commission}\r\n** {\'Excursion &#40;Baltic Olympiad in Informatics, 2001&#41;\':2-sat#excursion}\r\n** {\'Orpath &#40;Olimpiadă Rusia&#41;\':2-sat#orpath}\r\n** {\'Aladdin &#40;Bursele Agora 2005/2006, Runda 1&#41;\':2-sat#aladdin}\r\n* {\'Bibliografie\':2-sat#bibliografie}\r\n\r\nh2(#introducere). Introducere\r\n\r\nProblema satisfiabilităţii, notată prescurtat cu $SAT$, cere determinarea existenţei pentru o formulă booleană <tex> \\phi </tex> a unei atribuiri satisfiabile. O formulă booleană <tex> \\phi </tex> este compusă din $variabile$ logice <tex> (x_{1}, x_{2}, ...) </tex>, $operatori$ logici ( <tex> \\wedge </tex> şi,  <tex> \\vee </tex> sau, <tex> \\sim </tex> non, <tex> \\rightarrow </tex> implicaţie, <tex> \\leftrightarrow </tex> echivalenţă), şi $paranteze$. O atribuire de valori booleene pentru variabilele acestei expresii se numeşte $atribuire satisfiabilă$ dacă evaluarea expresiei după atribuirea valorilor dă ca rezultat valoarea de adevăr $adevărat$. De acum încolo vom folosi pentru simplitate valorile <tex> 1 </tex> şi <tex> 0 </tex> în loc de $adevărat$ şi $fals$.\r\n\r\nUn exemplu de formulă ar fi <tex> \\phi = ((x_{1} \\rightarrow x_{2}) \\vee \\sim((\\sim x_{1} \\leftrightarrow x_{3}) \\vee x_{4})) \\wedge \\sim x_{2} </tex>. Aceasta are atribuirea satisfiabilă <tex> \\langle x_{1} = 0, x_{2} = 0, x_{3} = 1, x_{4} = 1 \\rangle </tex> pentru că <tex> \\phi = ((0 \\rightarrow 0) \\vee \\sim((\\sim 0 \\leftrightarrow 1) \\vee 1)) \\wedge \\sim 0 = (1 \\vee \\sim (1 \\vee 1)) \\wedge 1 = (1 \\vee 0) \\wedge 1 = 1</tex>. \r\n\r\nh2(#forme-normale). Forme normale ale formulelor logice\r\n\r\nOrice formulă booleană poate fi transformată în două forme:\r\n\r\n* $Forma normal conjunctivă$ în care expresia este exprimată ca o conjuncţie de propoziţii, iar fiecare propoziţie este formată dintr-o disjuncţie de $literali$. Un $literal$ este o variabilă care poate fi sau nu negată. Un exemplu de expresie în forma normal conjunctivă ar fi: <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) \\wedge (x_{3} \\vee x_{2} \\vee x_{4}) \\wedge (\\sim x_{1} \\vee \\sim x_{3} \\vee \\sim x_{4}) </tex> care are pe <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) </tex> ca primă propoziţie cu literalii <tex> x_{1} </tex>, <tex> \\sim x_{1} </tex>, <tex> \\sim x_{2} </tex>.\r\n\r\n* $Forma normal disjunctivă$ este formată ca o disjuncţie de propoziţii, fiecare dintre aceste propoziţii fiind o conjuncţie de literali. Un exemplu de o asemenea formulă ar fi următoarea: <tex> (x_{1} \\wedge x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge \\sim x_{3}) \\vee (\\sim x_{1} \\wedge x_{2} \\wedge \\sim x_{2}) </tex>.\r\n\r\nh2(#overview-sat). SAT, 3-SAT, 2-SAT\r\n\r\nProblema $SAT$ este $NP-completă$. De fapt, este prima problemă $NP-completă$ găsită. Stephen Cook a demonstrat $NP-completitudinea$ ei în 1971. Pe vremea aceea nu se ştia nici măcar că problemele $NP-complete$ există. Această problemă rămâne $NP-completă$ chiar dacă restricţionăm expresiile la unele care în forma normal conjunctivă au doar trei literali. Problema satisfiabilităţii pentru asemenea expresii se numeşte $3-SAT$, şi multe probleme pot fi demonstrate a fi $NP-complete$ prin reducerea lui $3-SAT$ la problemele respective în timp polinomial. Din fericire, problema $2-SAT$, adică cea pentru care în fiecare propoziţie există doar $2$ literali, se poate rezolva eficient. Restul articolului va prezenta trei metode de rezolvare a problemei $2-SAT$ şi câteva aplicaţii ale acesteia din concursuri de programare.\r\n\r\nh2(#solutii-2-sat). Soluţii pentru 2-SAT\r\n\r\nUn exemplu de problemă $2-SAT$ ar fi satisfiabilitatea formulei <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Această formulă este satisfăcută de valorile <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>. Pentru a satisface întreaga expresie trebuie ca în fiecare propoziţie cel puţin unul din cei doi literali să aibă valoarea de adevăr <tex> 1 </tex>.\r\n\r\nh3(#solutie-1). Soluţie $O(M * 2^N^)$\r\n\r\nO primă metodă de rezolvare ar fi să încercăm toate cele $2^N^$ posibilităţi de atribuire posibilă, dar această metodă are ordinul de complexitate $O(M * 2^N^)$ şi este eficientă doar pentru instanţe mici ale problemei.\r\n\r\nh3(#solutie-2). Soluţie $O(N * M)$\r\n\r\nUrmătoarea soluţie pare trivială, dar găsirea acestui algoritm şi realizarea faptului că el rezolvă corect problema sunt mai grele decât impresia lăsată după citirea ei. Considerăm o propoziţie oarecare cu două variabile $p$ şi $q$, apoi una dintre ele, de exemplu $p$. Îi atribuim literalului în care apare $p$ valoarea $0$. Pentru ca propoziţia respectivă să aibă $1$ valoarea de adevăr, atunci valoarea lui $q$ trebuie fixată. Fixând şi valoarea lui $q$, probabil şi alte propoziţii ce conţin literalul $q$ vor avea celălalt literal fixat. Propagăm astfel o serie de schimbări. După ce toate schimbările forţate au fost făcute, propoziţiile rezultate vor fi de următoarele tipuri: <tex> a \\vee b </tex>, <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex>. Propoziţii de tip <tex> 0 \\vee b </tex> nu pot apărea pentru că toate schimbările forţate au fost deja propagate. Dacă apare o propoziţie <tex> 0 \\vee 0 </tex> atunci alegerea făcută pentru valoarea lui $p$ este greşită. Vom încerca şi alegerea opusă pentru $p$. Dacă ambele duc la o propoziţie de tip <tex> 0 \\vee 0 </tex> atunci expresia nu poate fi satisfăcută. Propoziţiile de forma <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex> pot fi ignorate. În acest fel am eliminat cel puţin o variabilă şi o propoziţie din expresie. Dacă expresia iniţială era satisfiabilă, atunci şi expresia din care s-au eliminat câteva propoziţii a rămas satisfiabilă. Continuând pe această idee obţinem un algoritm de complexitate $O(N * M)$, pentru că la fiecare atribuire de valoare pentru o variabilă parcurgem şirul de propoziţii o dată. \r\n\r\nSă vedem cum funcţionează algoritmul pentru expresia: <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Considerăm propoziţia <tex> (x_{1} \\vee \\sim x_{2}) </tex> şi <tex> \\langle x_{2} = 1 \\rangle </tex>. Astfel, vom obţine mai departe <tex> (x_{1} \\vee 0) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee 1) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. În propoziţia <tex> (x_{1} \\vee 0) </tex>, <tex> x_{1} </tex> trebuie să fie egal cu <tex> 1 </tex>. Acum, expresia devine: <tex> (0\\ \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee 0) </tex>. Din propoziţia <tex> (0\\ \\vee \\sim x_{3}) </tex> obţinem <tex> \\langle x_{3} = 0 \\rangle </tex>, iar din <tex> (x_{4} \\vee 0) </tex> obţinem <tex> \\langle x_{4} = 1 \\rangle </tex>. Deci, atribuirea satisfiabilă este <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>.\r\n\r\nh3(#solutie-3). Soluţie $O(N^2^)$\r\n\r\nO altă soluţie elegantă se bazează pe o metodă randomizată:\r\n\r\n== code(cpp) |\r\natribuim valori booleene arbitrare variabilelor;\r\ncât timp expresia nu este satisfăcută, execută\r\n    găsim o propoziţie cu valoarea de adevăr 0;\r\n    schimbăm valoarea de adevăr a oricăreia dintre cele două variabile prezente în propoziţie;\r\nsfârşit cât timp\r\n==\r\n\r\nLinia $4$ va face ca acea propoziţie să aibă noua valoare de adevăr <tex> 1 </tex>.\r\n\r\nDe ce ar merge acest algoritm? Să presupunem că există o soluţie a problemei, o notăm cu <tex> S </tex>, iar cu <tex> X </tex> notăm şirul valorilor curente ale variabilelor. Ne uităm la fiecare pas al algoritmului la numărul de variabile care au valori diferite în soluţie faţă de cele din <tex> X </tex> (acest număr de diferenţe între elementele de acelaşi index pentru două şiruri se mai numeşte şi \'distanţă Hamming\':http://en.wikipedia.org/wiki/Hamming_distance între şiruri). Fie această valoare la pasul current $K$. Noi am vrea să avem $K = 0$. Cum va evolua $K$ pe parcursul algoritmului? La un moment dat noi schimbăm valoarea unei variabile luate aleator dintr-o propoziţie nesatisfăcută. Pentru că în <tex> S </tex> propoziţia este satisfăcută, înseamnă că cel puţin una dintre cele două variabile ale propoziţiei are valori diferite în <tex> X </tex> faţă de <tex> S </tex>. Astfel, operaţia făcută de noi are probabilitate de cel puţin $0.5$ să ne aducă mai aproape de soluţie. Vom nota cu <tex> T(i) </tex> numărul probabil de paşi în care un şir <tex> X </tex> aflat la distanţa Hamming egală cu $i$ faţă de <tex> S </tex>, va fi transformat în <tex> S </tex>. Evident:\r\n\r\n<tex> T(0) = 0 </tex>\r\n\r\n<tex> T(i) \\le \\frac {T(i + 1) + T(i - 1)}{2} + 1 </tex> pentru $0 < i < N$ ({$N$} e numărul de variabile booleene ale expresiei)\r\n\r\nSe pune semnul de inegalitate pentru că ambele variabile pot avea valori diferite faţă de cele din soluţie, deci schimbarea valorii oricăreia ar putea să ne aducă mai aproape de soluţie.\r\n\r\nDacă toate variabilele diferă de soluţie, orice schimbare ne aduce mai aproape de aceasta:\r\n\r\n<tex> T(N) = T(N - 1) + 1 </tex>\r\n\r\nNe interesează numai limitele superioare, deci folosim doar egalităţi în loc de inegalităţi:\r\n\r\n<tex> X(0) = 0 </tex>, <tex> X(i) = \\frac {X(i + 1) + X(i - 1)}{2} + 1 </tex>, <tex> X(N) = X(N - 1) + 1 </tex>\r\n\r\nDacă adunăm toate ecuaţiile obţinem:\r\n\r\n<tex> X(0) + X(1) + ... + X(N) = </tex> <tex> \\frac {X(0) + X(1) + 2X(2) + ... + 2X(N - 2) + X(N - 1) + X(N)}{2} + X(N) + N - 1 </tex>\r\n\r\nDe aici avem că <tex> \\frac {X(1) + X(N - 1) - X(N)}{2} = N - 1 </tex>, iar din <tex> X(N) = X(N - 1) + 1 </tex> rezultă că <tex> X(1) = 2N - 1 </tex>. Mai departe avem că <tex> X(2) = 4N - 4 </tex> <tex> ... </tex> <tex> X(i) = 2iN - i^2 </tex>, de unde, când <tex> i = N </tex>, avem că <tex> X(N) = N^2 </tex>.\r\n\r\nAstfel, numărul mediu de paşi ai algoritmului este pătratic în numărul $N$ de variabile. Lăsând algoritmul să ruleze de 2-3 ori mai mulţi paşi decât numărul mediu, avem o probabilitate foarte mare să ajungem la rezultat.\r\n\r\nh3(#solutie-4). Soluţie $O(M + N)$\r\n\r\nO a treia soluţie se bazează pe relaţia de implicaţie. Relaţia <tex> \\rightarrow </tex> are următoarea tabelă de adevăr:\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> A \\rightarrow B </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nRelaţia de implicaţie are semnificaţia dacă <tex> A </tex> este adevărat atunci şi <tex> B </tex> este adevărat. Scriem tabelul expresiei <tex> \\sim A \\vee B </tex> şi observăm că acesta este egal cu cel al relaţiei de implicaţie.\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> \\sim A \\vee B </tex>|\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nFiecare clauză <tex> A \\vee B </tex> poate fi scrisă ca două implicaţii <tex> \\sim A \\rightarrow B </tex> şi <tex> \\sim B \\rightarrow A </tex>. Realizăm un graf al implicaţiilor. Astfel, nodurile grafului vor fi variabilele <tex> A </tex>, <tex> B </tex> ... şi negaţiile lor <tex> \\sim A </tex>, <tex> \\sim B </tex> ... iar muchiile acestui graf vor fi implicaţiile echivalente cu propoziţiile din expresie. Deci, dacă expresia are $M$ propoziţii graful va avea $2M$ muchii. Acestea fiind zise, expresiei <tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) </tex> îi corespunde graful:\r\n\r\np=. !2-sat?Graf.png!\r\n\r\nDacă avem <tex> A \\longrightarrow B </tex> o muchie în graful nostru, atunci dacă literalul <tex> A </tex> este adevărat atunci şi literalul <tex> B </tex> trebuie să fie adevărat pentru ca propoziţia reprezentată de muchie să fie satisfăcută. Putem demonstra prin inducţie că dacă există un drum în graf de la literalul <tex> A </tex> la literalul <tex> B </tex>, atunci dacă <tex> A </tex> este adevărat şi <tex> B </tex> trebuie să fie adevărat. Dacă există un drum de la un literal <tex> X </tex> la <tex> \\sim X </tex> atunci nu va exista soluţie pentru că nu putem seta în acelaşi timp o variabilă şi valoarea ei negată la valoarea adevărat. De aici rezultă că dacă în graful asociat expresiei există o variabilă <tex> X </tex> în aceiaşi componentă tare conexă cu <tex> \\sim X </tex> atunci instanţa problemei satisfiabilităţii nu poate fi satisfăcută. Dacă nu există o asemenea variabilă, vom vedea în continuare cum putem rezolva problema. Întâi, facem observaţia că dacă în graf există muchia <tex> A \\longrightarrow B </tex> atunci există şi muchia <tex> \\sim B \\longrightarrow \\sim A </tex>. Astfel, dacă există un drum de la <tex> A </tex> la <tex> B </tex> în graf, aplicând proprietatea menţionată pentru fiecare muchie a drumului, vom găsi un drum de la <tex> \\sim B </tex> la <tex> \\sim A </tex>. Evident, afirmaţia este valabilă şi reciproc: dacă există drum de la <tex> B </tex> la <tex> A </tex> atunci vom avea un drum de la nodul <tex> \\sim A </tex> la <tex> \\sim B </tex>. Astfel, dacă avem că <tex> A </tex> şi <tex> B </tex> sunt în aceeaşi componentă tare conexă atunci şi nodurile <tex> \\sim A </tex> şi <tex> \\sim B </tex> sunt în aceeaşi componentă tare conexă. Deci, dacă nu există doi literali <tex> X </tex> şi <tex> \\sim X </tex> în aceeaşi componentă tare conexă, putem să împărţim graful în componente tari conexe şi să împerechem componentele câte două astfel ca în fiecare pereche să apară o componentă <tex> U </tex> cu nişte literali şi altă componentă <tex> \\sim U </tex> cu aceiaşi literali negaţi. Pentru a găsi o soluţie vom determina mai întâi componentele tari conexe ale grafului. Apoi putem contracta fiecare componentă într-un nod. Graful obţinut va fi acciclic. Alegem un nod <tex> u </tex> în care nu intră nicio muchie (un asemenea nod trebuie să existe pentru a nu exista cicluri), din considerente de simetrie, din nodul lui pereche <tex> \\sim u </tex> nu va ieşi nicio muchie. Literalilor componentei <tex> U </tex> putem să le dăm valoarea de adevăr <tex> 0 </tex>, iar literalilor din componenta pereche <tex> \\sim U </tex>  putem să le dăm valoarea de adevăr <tex> 1 </tex>. Această alegere nu impune restricţii asupra celorlalţi literali şi elimină câteva variabile din problemă. Repetarea recursivă a acestui pas pe graful rămas va duce la rezolvarea problemei. Determinarea componentelor tari conexe se poate face în complexitatea $O(N + M)$. Pentru a vedea acest algoritm puteţi consulta \'secţiunea $23.5$\':http://zhuzeyuan.hp.infoseek.co.jp/ita/chap23.htm din {\'[1]\':2-sat#bibliografie}. Iar eliminarea  nodurilor de care vorbeam mai sus se poate face în $O(N + M)$ folosind o sortare topologică.\r\n\r\nSă urmărim cum merge algoritmul nostru pe exemplul de mai sus. Componentele tari conexe sunt următoarele: <tex> \\{A\\} </tex>, <tex> \\{\\sim A\\} </tex>, <tex> \\{B, C, \\sim D\\} </tex>, <tex> \\{\\sim B, \\sim C, D\\} </tex>. În nodul asociat componentei <tex> \\{A\\} </tex> nu intră nici o muchie. Astfel, putem să îi atribuim lui <tex> A </tex> valoarea <tex> 0 </tex>, iar în nodul asociat componentei <tex> \\{\\sim B, \\sim C, D\\} </tex> nu intră nicio muchie, deci putem să îi atribuim lui <tex> B </tex> valoarea <tex> 1 </tex>, lui <tex> C </tex> valoarea <tex> 0 </tex> şi lui <tex> D </tex> valoarea <tex> 1 </tex>. Această atribuire este satisfiabilă după cum vedem în continuare:\r\n\r\n<tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) </tex> <tex> = (\\sim 0 \\vee \\sim 1) \\wedge (1 \\vee \\sim 1) \\wedge (1 \\vee 1) \\wedge (\\sim 1 \\vee \\sim 0) \\wedge (1 \\vee 0) </tex> <tex> = 1 \\wedge 1 \\wedge 1 \\wedge 1 \\wedge 1 = 1 </tex>\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\nRestul articolului va prezenta aplicaţii ale problemei $2-SAT$ din concursurile de programare.\r\n\r\nh2(#party). \'Party\':problema/party (preONI 2003/2004)\r\n\r\nbq. George vrea să îşi organizeze majoratul, şi vrea ca petrecerea să fie de neuitat, mâncarea, băutura, locaţia şi sonorizarea sunt deja asigurate, mai rămâne problema chemării prietenilor. El şi cu prietenul lui cel mai bun Lucian au preferinte diferite şi pentru a nu se certa au pus la punct o listă de cerinţe care vor trebui să fie îndeplinite astfel încât cheful să se desfăşoare în cele mai bune condiţii! Pentru uşurinţă,  prietenii lui George vor fi indentificaţi prin numere întregi de la $1$ la $N (1 ≤ N ≤ 100)$ şi cerinţele în număr de $M  (1 ≤ M ≤ 1.000)$ vor fi de tipurile 0, 1, 2 sau 3. O cerinţă de genul <tex> x \\ y </tex> 0 are semnificaţia că <tex> x </tex> sau <tex> y </tex> trebuie să participe la petrecere; <tex> x \\ y </tex> 1 are semnificaţia că dacă <tex> x </tex> participă nu există nici o restricţie pentru <tex> y </tex>, dar dacă <tex> x </tex> nu participă atunci nici <tex> y </tex> nu participa; <tex> x \\ y </tex> 2 are semnificaţia simetrică cu cerinţa 1; iar cerinţa <tex> x \\ y </tex> 3 are semnificaţia că cel puţin unul dintre <tex> x </tex> şi <tex> y </tex> nu participă la petrecere. Scrieţi un program care să-i ajute pe cei doi să determine care persoane vor fi invitate la petrecere. Se garantează că va fi posibilă întotdeauna organizarea unei petreceri!\r\n\r\nh3. Soluţie\r\n\r\nAceastă problemă este inspirită din o problemă de la $CEOI 2002$ şi este evident că ne cere să determinăm o atribuire satisfiabilă pentru o formulă logică formată ca conjuncţie între cerinţele care se transformă astfel:\r\n\r\n* cerinţa de tip 0 corespunde propoziţiei <tex> x \\vee y </tex>;\r\n* cerinţa de tip 1 corespunde propoziţiei <tex> x \\vee \\sim y </tex>;\r\n* cerinţa de tip 2 corespunde propoziţiei <tex> \\sim x \\vee y </tex>;\r\n* cerinţa de tip 3 corespunde propoziţiei <tex> \\sim x \\vee \\sim y </tex>.\r\n\r\nUna din primele două rezolvări ar fi putut soluţiona această problemă, dar problema de la $CEOI$ avea limite mai mari şi pentru rezolvarea ei ar fi trebuit un algoritm de complexitate $O(N + M)$.\r\n\r\nh2(#cigraf). Cigraf\r\n\r\n_Autor: Mugurel Ionuţ Andreica_\r\n\r\nbq. Se dă un graf neorientat cu $N (1 <= N <= 1000)$ noduri şi $M (0 <= M <= N*(N-1)/2)$ muchii. Se doreşte împărţirea nodurilor acestui graf în $2$ mulţimi, <tex> C </tex> şi <tex> I </tex>, având următoarele proprietăţi: fiecare nod face parte din exact una din cele $2$ mulţimi, există muchie între oricare $2$ noduri din mulţimea <tex> C </tex>, nu există nicio muchie între $2$ noduri din mulţimea <tex> I </tex>. Este posibil ca una dintre cele $2$ mulţimi să fie vidă. Soluţia nu este neaparat unică. Numele celor două mulţimi provin de la $clică$ şi $mulţime independentă$. De exemplu, pentru graful de $6$ noduri ce are muchiile <tex> \\{\\{1, 4\\}, \\{4, 6\\}, \\{6, 1\\}, \\{2, 4\\}, \\{2, 6\\}, \\{3, 4\\}, \\{1, 3\\}\\} </tex> o împărţire posibilă ar fi <tex> C = \\{1, 4, 6\\} </tex>, <tex> I = \\{2, 3, 5\\} </tex>.\r\n\r\nh3. Soluţie\r\n\r\nDacă între două noduri există muchie atunci nu pot fi amândouă în mulţimea <tex> I </tex>, iar dacă între două noduri nu există muchie nu pot fi amândouă în mulţimea <tex> C </tex>. \r\nTransformăm această problemă într-o instanţă de $2-SAT$ astfel: faptul că nodul <tex> x </tex> aparţine mulţimii <tex> C </tex> îl reprezentăm dândui lui <tex> x </tex> valoarea <tex> 1 </tex>, iar apartenenţa mulţimii <tex> I </tex> se codifică prin valoarea <tex> 0 </tex>. Acum existenţa unei muchii <tex> (x, y) </tex> corespunde expresiei <tex> x \\vee y </tex>, astfel cel puţin unul din nodurile <tex> x </tex> şi <tex> y </tex> nu va fi în mulţimea <tex> I </tex>. Dacă nu există muchia <tex> (x, y) </tex> putem scrie <tex> \\sim x \\vee \\sim y </tex>, această expresie va fi adevărată dacă cel puţin un nod din cele două nu va fi în mulţimea <tex> C </tex>.\r\nAceastă soluţie este liniară ca şi complexitate în numărul de elemente citite la intrare.\r\n\r\nh2(#peace-commission). Peace Commission (Polish Olympiad in Informatics, 2001)\r\n\r\nbq. Comisia Publică a Păcii trebuie să fie compusă în parlamentul Republicii Democrate a ţării Byteland după regulile impuse de Legea Foarte Importantă. Din păcate, unul dintre obstacole este acela că unii deputaţi nu se înţeleg cu ceilalţi. Comisia trebuie realizată astfel ca următoarele condiţii să fie îndeplinite: fiecare partid trebuie să aibă exact un reprezentant în comisie; dacă doi deputaţi nu se înţeleg, ei nu pot fi ambii membrii ai comisiei. Fiecare partid are exact doi deputaţi în parlament. Toţi număraţi de la $1$ până la $2n (1 <= n <= 8000)$. Deputaţii cu numerele $2i-1$ şi $2i$ aparţin celui de al $i$-lea partid. Se vor da $m (0 <= m <= 20 000)$ perechi de deputaţi <tex> (a, b) </tex> care nu se înţeleg. Se cere realizarea unei comisii dacă acest lucru este posibil. Un exemplu ar fi pentru trei partide şi perechile <tex> (1, 3) </tex> şi <tex> (2, 4) </tex> care nu se înţeleg comisia alcătuită din membrii <tex> \\{1, 4, 5\\} </tex>.\r\n\r\nh3. Soluţie\r\n\r\nFiecărui partid îi vom asocia o variabilă; variabila va lua valoarea <tex> 1 </tex> dacă membrul $2i - 1$ al partidului va aparţine comisiei şi valoarea <tex> 0 </tex> dacă membrul $2i$ va aparţine comisiei. Pentru ca din partidul $x$ să existe exact un membru în expresie introducem  <tex> A_{x} \\wedge \\sim A_{x} </tex>. \r\nPutem exprima că doi membrii ai parlamentului $(2i, 2j)$ nu se înţeleg prin expresia logică <tex> \\sim A_{i} \\vee \\sim A_{j} </tex>. Astfel nu pot ambele variabile <tex> A_{i} </tex> şi <tex> A_{j} </tex> să aibă în acelaşi timp valoarea <tex> 1 </tex> adică $2i$ şi $2j$ nu pot face parte în acelaşi timp din comisie. Dacă cei doi membrii sunt $(2i - 1, 2j - 1)$ atunci îi putem codifica prin expresia <tex> A_{i} \\vee A_{j} </tex> astfel <tex> A_{i} </tex> şi <tex> A_{j} </tex> nu pot avea în acelaşi timp valoarea <tex> 0 </tex>, iar dacă membrii sunt $(2i , 2j - 1)$ se poate scrie ca <tex> \\sim A_{i} \\vee A_{j} </tex> astfel <tex> A_{i} </tex> nu poate avea valoarea <tex> 1 </tex> când <tex> A_{j} </tex> are valoarea <tex> 0 </tex>.\r\nExemplul din problemă poate fi scris ca expresia logică în modul următor: <tex> A_{1} \\wedge \\sim A_{1} \\wedge A_{2} \\wedge \\sim A_{2} \\wedge A_{3} \\wedge \\sim A_{3} \\wedge (A_{1} \\vee A_{2}) \\wedge (\\sim A_{1} \\vee \\sim A_{2}) </tex>. \r\nDin nou vom putea folosi cel de al {\'patrulea algoritm\':2-sat#solutie4} explicat pentru a obţine o rezolvare de complexitate $O(N + M)$. \r\n\r\nh2(#excursion). Excursion (Baltic Olympiad in Informatics, 2001)\r\n\r\nbq. Un grup de turişti are ocazia să viziteze mai multe oraşe. Fiecare turist spune două dorinţe ale sale despre ce oraş ar vrea sau nu ar vrea să viziteze. O dorinţă a turistului  va spune despre exact un oraş dacă vrea sau nu vrea să îl viziteze. Este posibil ca ambele dorinţe ale unui turist să exprime acelaşi lucru sau să exprime lucruri opuse (de exemplu „Vreau să vizitez oraşul A!” şi „Nu vreau să vizitez oraşul A!”). Va trebui să determinaţi după citirea cerinţelor celor $n$ turişti despre $m$ oraşe dacă există o mulţime a oraşelor pentru care cel puţin o dorinţă a fiecărui turist este îndeplinită $(1 <= n <= 20 000, 1 <= m <= 8 000)$. De exemplu, să presupunem că avem $3$ turişti, $4$ oraşe şi primul turist are dorinţele de a vizita oraşul întâi şi de a nu vizita oraşul doi, al doilea turist are dorinţele de a vizita oraşul doi şi de a vizita oraşul patru, iar al treilea turist are dorinţele de a vizita oraşul trei şi de a vizita oraşul unu. O soluţie pentru acest exemplu ar fi vizitarea tuturor oraşelor.\r\n\r\nh3. Soluţie\r\n\r\nEste evident că şi această problemă se poate uşor transforma într-o instanţă de $2-SAT$. Fiecare turist ne dă prin dorinţele sale o expresie literală cu doi literali. Vizitarea sau nevizitarea oraşului de index $i$ va fi reprezentată prin variabila booleană <tex> A_{i} </tex>.  Exemplul din problemă poate fi transformat astfel: <tex> (A_{1} \\vee \\sim A_{2}) \\wedge (A_{2} \\vee A_{4}) \\wedge (A_{3} \\vee A_{1}) </tex>.\r\n\r\nh2(#orpath). Orpath (Olimpiadă Rusia)\r\n\r\nbq. Într-o ţară pacifistă, există $N$ oraşe şi $K$ autobuze $(1 <= N, K <= 100)$. La orele aglomerate ale zilei, nu trebuie să existe două autobuze care merg în acelaşi timp în sensuri opuse. Traseul fiecărui autobuz este un ciclu. Spunem că el merge în sens pozitiv dacă va parcurge oraşele în ordinea $1 2 3 4 1 2 3 4 1 2$ ... sau în sens negativ dacă le parcurge în ordinea $1 4 3 2 1 4 3 2 1 4$ ... Găsiţi o posibilitate de atribuire a sensului fiecărui autobuz astfel ca accidentele de trafic să fie evitate (nu vor exista două autobuze care să se întâlnească şi să aibă sensuri de mers opuse). Pentru fiecare autobuz se vor şti oraşele de pe ruta lui, şi pentru fiecare două oraşe vecine pe rută se va şti timpul necesar autobuzului pentru a ajunge dintr-un oraş în altul. De exemplu, pentru $4$ oraşe unde oricare două sunt la timp de mers egal cu $10$, şi pentru două autobuze cu rutele $1 2 4$ şi $3 4 2$, o soluţie ar fi ca primul autobuz să meargă în sens pozitiv iar celălalt în sens negativ.\r\n\r\nh3. Soluţie\r\n\r\nPentru orice două autobuze vom găsi care sunt sensurile de mers pentru ele astfel ca cele două autobuze să nu se întâlnească şi să provoace un accident. Pentru un sens fixat putem afla pentru un autobuz pe ce interval de timp va fi pe o anumită stradă. El va fi în general pe o stradă $(i, j)$ pe un interval de tipul $[t1 + k*T … t2 + k*T]$ unde $t1$ este timpul din prima rută parcursă pentru a ajunge la $i$, $t2$ timpul pentru a ajunge la $j$ iar $T$ este durata totală a unei rute. Acum, pentru a determina dacă două autobuze se vor întâlni pe o rută $(i, j)$ trebuie ca ele să se deplaseze în sensuri opuse pe această rută, iar intervalele lor $[t1 + k*T1 .. t2 + k*T1]$ se intersectează cu intervalele $[tt1 + p*T2 … tt2 + p*T2]$. Este clar acum că putem transforma problema într-o instanţă de $2-SAT$ prin maparea autobuzelor în variabile logice, a sensurilor de mers în valorile $adevărat$ şi $fals$, iar pentru orice pereche de autobuze să fie o propoziţie logică ce ia valoarea $adevărat$ doar dacă sensurile de mers determinate de variabilele logice asociate autobuzelor sunt compatibile. Mai trebuie determinat într-un mod eficient dacă două clase de intervale de timp se intersectează. Aceasta rămâne ca temă cititorului.\r\n\r\nh2(#aladdin). \'Aladdin\':problema/aladdin (Bursele Agora 2005/2006, Runda 1)\r\n\r\nbq. Aladdin, aşa cum ştiaţi, este un mare magnat în afacerea de comercializare a covoarelor magice. Acesta doreşte să o cucerească pe prinţesa Iasmina, iar aceasta, pentru a-i testa inteligenţa îl roagă să îi facă un covor dreptunghiular împărţit în pătrăţele, asemănator unei table de şah cu $N$ linii şi $M$ coloane $(1 <= N, M <= 1000)$. Fiecare pătrăţel de pe covor trebuie colorat cu alb sau cu negru. Pentru fiecare pătrat care conţine $4$ pătrăţele Iasmina pune condiţia să aibă un număr fixat de pătrăţele colorate cu negru. Ajutaţi-l pe Aladdin să realizeze un covor care satisface condiţiile impuse de prinţesa Iasmina!\r\n\r\nh3. Soluţie\r\n\r\nÎntâi, să considerăm un exemplu. Pentru o cerinţă de forma:\r\n\r\ntable{width: 90px; text-align: center}.\r\n| <tex> 3 </tex> | <tex> 2 </tex> | <tex> 3 </tex> |\r\n| <tex> 2 </tex> | <tex> 3 </tex> | <tex> 3 </tex> |\r\n| <tex> 1 </tex> | <tex> 2 </tex> | <tex> 1 </tex> |\r\n\r\nuna din soluţii este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nFie <tex> A </tex> o matrice soluţie a problemei noastre. Vom numerota rândurile matricii de la $0$ la $N - 1$ şi coloanele de la $0$ la $M - 1$. Matricea de intrare <tex> S </tex> reprezintă de fapt sumele din fiecare pătrat de câte $2 x 2$ elemente. Facem observaţia că dacă ştim într-un pătrat de $2 x 2$ valorile pentru trei dintre celule, atunci valoarea din a patra celulă este unic determinată pentru că ştim suma elementelor din pătrat. Vedem astfel, că dacă ştim valorile elementelor din prima linie a matricii <tex> A </tex> şi din prima coloană, restul valorilor sunt unic determinate. \r\nPentru a rezolva problema vom presupune <tex> A[0][0] </tex> cunoscut (de fapt, mai întâi vom rezolva problema presupunând că <tex> A[0][0] = 1 </tex>, iar dacă nu obţinem nicio soluţie vom încerca cu <tex> A[0][0] = 0 </tex>). Vom nota celulele <tex> A[0][1] </tex>, <tex> A[0][2]</tex>, … <tex> A[0][M - 1] </tex> cu <tex> x_{1} </tex>, <tex> x_{2} </tex>, … <tex> x_{M-1} </tex> iar celulele <tex> A[1][0] </tex>, <tex> A[2][0] </tex>, … <tex> A[N - 1][0] </tex> cu <tex> y_{1} </tex>, <tex> y_{2} </tex>, … <tex> y_{N-1} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> A[0][0] </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> ... </tex> | <tex> x_{M-1} </tex> |\r\n| <tex> y_{1} </tex> | <tex> 1 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n| <tex> y_{2} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 0 </tex> |\r\n| ... | ... | ... | ... | ... |\r\n| <tex> y_{N-1} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n\r\nAcum, pentru fiecare celulă putem demonstra prin inducţie că <tex> A[i][j] = (-1)^i x_{j} + (-1)^j y_{i} + b[i][j] </tex>. Unde <tex> b[i][j] </tex> sunt nişte constante ce sunt calculate în funcţie de matricea primită la intrare.\r\nEste uşor de observat că dacă:\r\n<tex> A[i-1][j] = (-1)^{(i-1)} x_{j} + (-1)^j y_{i-1} + b[i-1][j] </tex>, \r\n<tex> A[i-1][j-1] = (-1)^{(i-1)} x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i-1][j-1] </tex>, \r\n<tex> A[i][j-1] = (-1)^i x_{j-1} + (-1)^{(j-1)} y_{i} + b[i][j-1] </tex>, \r\n\r\natunci:\r\n\r\n<tex> A[i][j] = S[i-1][j-1] - A[i-1][j] - A[i][j-1] - A[i-1][j-1] = </tex> \r\n<tex> = S[i-1][j-1] - ((-1)^{(i-1)} x_{j} + (-1)^j y_{i-1} + b[i-1][j]) - </tex> <tex> ((-1)^{(i-1)} x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i-1][j-1]) - ((-1)^i x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i][j-1]) = </tex> \r\n<tex> = (-1)^i x_{j} - (-1)^j y_{i-1} + (-1)^i x_{j-1} + (-1)^j y_{i-1} - </tex> <tex> (-1)^i x_{j-1} + (-1)^j y_{i} + S[i-1][j-1] - b[i-1][j] - b[i][j-1] - b[i-1][j-1] = </tex> \r\n<tex> = (-1)^i x_{j} + (-1)^j y_{i} + b[i][j] </tex>. \r\n\r\nDe aici concluzionăm că <tex> b[i][j] = S[i-1][j-1] - b[i-1][j] - b[i][j-1] - b[i-1][j-1] \\ (*)</tex>.\r\n\r\nAvem un sistem format din inecuaţiile:\r\n\r\n<tex> 0 \\le x_{j} \\le 1 </tex>\r\n<tex> 0 \\le y_{i} \\le 1 </tex>\r\n<tex> -b[i][j] \\le (-1)^i x_{j} + (-1)^j y_{i} \\le 1 - b[i][j] </tex>\r\n\r\nEste uşor acum să transformăm acest sistem într-o formulă booleană în {\'formă normal conjunctivă\':2-sat#forme-normale} în care fiecare expresie are cel mult $2$ literali. Fiecare relaţie o putem înmulţi sau nu cu $-1$ astfel ca părţile constante ale relaţiei să fie pozitive. Observăm că <tex> | b[i][j] | \\le 2 </tex>, altfel nu avem soluţie. Dacă <tex> | b[i][j] | = 2 </tex> atunci ambele variabile au valori fixe, iar dacă <tex> | b[i][j] | = 1 </tex> sau <tex> | b[i][j] | = 0 </tex> atunci relaţia o putem scrie ca o disjuncţie logică cu doi literali.\r\n\r\nO relaţie precum <tex> 0 \\le x + y \\le 1 </tex> poate fi tansformată logic în <tex> \\sim x \\vee \\sim y </tex>, astfel <tex> x </tex> şi <tex> y </tex> nu vor fi în acelaşi timp <tex> 1 </tex>, una de genul <tex> 1 \\le x + y \\le 2 </tex> va fi transformată în <tex> (x \\vee y) </tex>, astfel cel puţin <tex> x </tex> sau <tex> y </tex> va fi egal cu <tex> 1 </tex>, alta de tipul <tex> 0 \\le x - y \\le 1 </tex> poate fi scrisă ca <tex> x \\vee \\sim y </tex>, una de tipul <tex> 2 \\le x + y \\le 3 </tex> în <tex> x \\wedge y </tex>, iar una de tipul <tex> 0 \\le -x -y \\le 1 </tex> în <tex> \\sim x \\wedge \\sim y </tex>, una de tipul <tex> 1 \\le x - y  \\le 2 </tex> în <tex> x \\wedge \\sim y </tex>.\r\n\r\nAstfel am redus problema la rezolvarea unei instanţe de $2-SAT$. Avem $N+M-1$ necunoscute şi {$(N-1)$}{$(M-1)$} propoziţii. Folosind a treia metodă de rezolvare vom obţine un algoritm de complexitate $O(N * M)$ care soluţionează problema noastră.\r\n\r\nSă vedem cum merge acestă rezolvare pe exemplul din problemă:\r\n\r\nAlegem <tex> A[0][0] = 1 </tex>. Necunoscutele vor fi <tex> x_{1} </tex>, <tex> x_{2} </tex>, <tex> x_{3} </tex> şi <tex> y_{1} </tex>, <tex> y_{2} </tex>, <tex> y_{3} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> x_{3} </tex> |\r\n| <tex> y_{1} </tex> | <tex> A[1][1] </tex> | <tex> A[1][2] </tex> | <tex> A[1][3] </tex> |\r\n| <tex> y_{2} </tex> | <tex> A[2][1] </tex> | <tex> A[2][2] </tex> | <tex> A[2][3] </tex> |\r\n| <tex> y_{3} </tex> | <tex> A[3][1] </tex> | <tex> A[3][2] </tex> | <tex> A[3][3] </tex> |\r\n\r\nFolosind recurenţa <tex> (*) </tex> obţinem că matricea <tex> b </tex> este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 2 </tex> | <tex> 0 </tex> | <tex> 3 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> -1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n\r\nDe aici obţinem sistemul de inegalităţi:\r\n\r\n<tex> 0 \\le x_{1} \\le 1,  0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le 1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, -2 \\le -x_{1} - y_{1} \\le -1, 0 \\le -x_{2} + y_{1} \\le 1, -3 \\le -x_{3} - y_{1} \\le -2, </tex>\r\n<tex> 0 \\le y_{2} \\le 1,  0 \\le  x_{1} - y_{2} \\le  1,-1 \\le  x_{2} + y_{2} \\le 0,  1 \\le  x_{3} - y_{2} \\le  2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, -1 \\le -x_{1} - y_{3} \\le  0, 0 \\le -x_{2} + y_{3} \\le 1, -1 \\le -x_{3} - y_{3} \\le  0 </tex>\r\n\r\nTransformăm relaţiile astfel ca să nu apară nici o constantă negativă:\r\n\r\n<tex> 0 \\le x_{1} \\le 1, 0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le  1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, 1 \\le x_{1} + y_{1} \\le 2, 0 \\le -x_{2} + y_{1} \\le 1, 2 \\le x_{3} + y_{1} \\le 3, </tex>\r\n<tex> 0 \\le y_{2} \\le 1, 0 \\le x_{1} - y_{2} \\le 1, 0 \\le -x_{2} - y_{2} \\le 1, 1 \\le x_{3} - y_{2} \\le 2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, 0 \\le x_{1} + y_{3} \\le 1, 0 \\le -x_{2} + y_{3} \\le 1, 0 \\le x_{3} + y_{3} \\le 1 </tex>\r\n\r\nAcest sistem poate fi transformat într-o expresie booleană:\r\n\r\n<tex> (x_{1} \\vee y_{1}) \\wedge (\\sim x_{2} \\vee y_{1}) \\wedge (x_{3} \\wedge y_{1}) \\wedge </tex>\r\n<tex> (x_{1} \\vee \\sim y_{2}) \\wedge (\\sim x_{2} \\wedge \\sim y_{2}) \\wedge (x_{3} \\wedge \\sim y_{2}) \\wedge </tex>\r\n<tex> (\\sim x_{1} \\vee \\sim y_{3}) \\wedge (\\sim x_{2} \\vee y_{3}) \\wedge (\\sim x_{3} \\vee \\sim y_{3}) </tex>.\r\n\r\nAcestă expresie e satisfăcută de valorile: <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 1, y_{1} = 1, y_{2} = 0, y_{3} = 0 \\rangle </tex>, iar de aici putem determina o soluţie a problemei noastre iniţiale ca fiind:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nh2(#bibliografie). Bibliografie:\r\n\r\n* [1] T. H. Cormen, C. E. Leiserson, R. R. Rivest - \'_Introducere in Algoritmi_\':http://zhuzeyuan.hp.infoseek.co.jp/ita/toc.htm\r\n* [2] \'_Satisfiability_\':http://en.wikipedia.org/wiki/Satisfiability, Wikipedia\r\n* [3] \'_BOI 2001 Competition Material_\':http://www.oi.edu.pl/download/boi-2001.pdf\r\n* [4] \'_CEOI 2002 Competition Material_\':http://ics.upjs.sk/ceoi/Documents.html\r\n',2044,'public',NULL,NULL),('algoritmiada-2009/runda-2','Algoritmiada 2009 - Runda 2','2008-11-30 16:35:07','2008-12-22 15:43:33','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Algoritmiada 2009, Runda 2\r\n\r\n(htabs)*(active) \'Despre...\':algoritmiada-2009/runda-2 \r\n* \'Clasele 5-8\':algoritmiada-2009/runda-2/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2009/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-2/studenti\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-2/5-8 \r\n\r\nRunda va incepe *Duminica 11 ianuarie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-2/studenti\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':algoritmiada-2009/runda-2/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-2/studenti\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"70\" count=\"20\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"domino\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',2028,'protected',NULL,NULL),('2-sat','Problema satisfiabilității formulelor logice de ordinul doi','2008-12-09 15:55:03','2008-12-23 09:16:22','h1. Problema satisfiabilităţii formulelor logice de ordinul doi\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"marius\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 30em}*{text-align:center} *Conţinut:*\r\n* {\'Introducere\':2-sat#introducere}\r\n* {\'Forme normale ale formulelor logice\':2-sat#forme-normale}\r\n* {\'SAT, 3-SAT, 2-SAT\':2-sat#overview-sat}\r\n* {\'Soluţii pentru 2-SAT\':2-sat#solutii-2-sat}\r\n** {\'Soluţie $O(M * 2^N^)$\':2-sat#solutie-1}\r\n** {\'Soluţie $O(N * M)$\':2-sat#solutie-2}\r\n** {\'Soluţie $O(N^2^)$\':2-sat#solutie-3}\r\n** {\'Soluţie $O(M + N)$\':2-sat#solutie-4}\r\n* {\'Aplicaţii\':2-sat#aplicatii}\r\n** {\'Party &#40;preONI 2003/2004&#41;\':2-sat#party}\r\n** {\'Cigraf\':2-sat#cigraf}\r\n** {\'Peace Commission &#40;Polish Olympiad in Informatics, 2001&#41;\':2-sat#peace-commission}\r\n** {\'Excursion &#40;Baltic Olympiad in Informatics, 2001&#41;\':2-sat#excursion}\r\n** {\'Orpath &#40;Olimpiadă Rusia&#41;\':2-sat#orpath}\r\n** {\'Aladdin &#40;Bursele Agora 2005/2006, Runda 1&#41;\':2-sat#aladdin}\r\n* {\'Bibliografie\':2-sat#bibliografie}\r\n\r\nh2(#introducere). Introducere\r\n\r\nProblema satisfiabilităţii, notată prescurtat cu $SAT$, cere determinarea existenţei pentru o formulă booleană <tex> \\phi </tex> a unei atribuiri satisfiabile. O formulă booleană <tex> \\phi </tex> este compusă din $variabile$ logice <tex> (x_{1}, x_{2}, ...) </tex>, $operatori$ logici ( <tex> \\wedge </tex> şi,  <tex> \\vee </tex> sau, <tex> \\sim </tex> non, <tex> \\rightarrow </tex> implicaţie, <tex> \\leftrightarrow </tex> echivalenţă), şi $paranteze$. O atribuire de valori booleene pentru variabilele acestei expresii se numeşte $atribuire satisfiabilă$ dacă evaluarea expresiei după atribuirea valorilor dă ca rezultat valoarea de adevăr $adevărat$. De acum încolo vom folosi pentru simplitate valorile <tex> 1 </tex> şi <tex> 0 </tex> în loc de $adevărat$ şi $fals$.\r\n\r\nUn exemplu de formulă ar fi <tex> \\phi = ((x_{1} \\rightarrow x_{2}) \\vee \\sim((\\sim x_{1} \\leftrightarrow x_{3}) \\vee x_{4})) \\wedge \\sim x_{2} </tex>. Aceasta are atribuirea satisfiabilă <tex> \\langle x_{1} = 0, x_{2} = 0, x_{3} = 1, x_{4} = 1 \\rangle </tex> pentru că <tex> \\phi = ((0 \\rightarrow 0) \\vee \\sim((\\sim 0 \\leftrightarrow 1) \\vee 1)) \\wedge \\sim 0 = (1 \\vee \\sim (1 \\vee 1)) \\wedge 1 = (1 \\vee 0) \\wedge 1 = 1</tex>. \r\n\r\nh2(#forme-normale). Forme normale ale formulelor logice\r\n\r\nOrice formulă booleană poate fi transformată în două forme:\r\n\r\n* $Forma normal conjunctivă$ în care expresia este exprimată ca o conjuncţie de propoziţii, iar fiecare propoziţie este formată dintr-o disjuncţie de $literali$. Un $literal$ este o variabilă care poate fi sau nu negată. Un exemplu de expresie în forma normal conjunctivă ar fi: <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) \\wedge (x_{3} \\vee x_{2} \\vee x_{4}) \\wedge (\\sim x_{1} \\vee \\sim x_{3} \\vee \\sim x_{4}) </tex> care are pe <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) </tex> ca primă propoziţie cu literalii <tex> x_{1} </tex>, <tex> \\sim x_{1} </tex>, <tex> \\sim x_{2} </tex>.\r\n\r\n* $Forma normal disjunctivă$ este formată ca o disjuncţie de propoziţii, fiecare dintre aceste propoziţii fiind o conjuncţie de literali. Un exemplu de o asemenea formulă ar fi următoarea: <tex> (x_{1} \\wedge x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge \\sim x_{3}) \\vee (\\sim x_{1} \\wedge x_{2} \\wedge \\sim x_{2}) </tex>.\r\n\r\nh2(#overview-sat). SAT, 3-SAT, 2-SAT\r\n\r\nProblema $SAT$ este $NP-completă$. De fapt, este prima problemă $NP-completă$ găsită. Stephen Cook a demonstrat $NP-completitudinea$ ei în 1971. Pe vremea aceea nu se ştia nici măcar că problemele $NP-complete$ există. Această problemă rămâne $NP-completă$ chiar dacă restricţionăm expresiile la unele care în forma normal conjunctivă au doar trei literali. Problema satisfiabilităţii pentru asemenea expresii se numeşte $3-SAT$, şi multe probleme pot fi demonstrate a fi $NP-complete$ prin reducerea lui $3-SAT$ la problemele respective în timp polinomial. Din fericire, problema $2-SAT$, adică cea pentru care în fiecare propoziţie există doar $2$ literali, se poate rezolva eficient. Restul articolului va prezenta trei metode de rezolvare a problemei $2-SAT$ şi câteva aplicaţii ale acesteia din concursuri de programare.\r\n\r\nh2(#solutii-2-sat). Soluţii pentru 2-SAT\r\n\r\nUn exemplu de problemă $2-SAT$ ar fi satisfiabilitatea formulei <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Această formulă este satisfăcută de valorile <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>. Pentru a satisface întreaga expresie trebuie ca în fiecare propoziţie cel puţin unul din cei doi literali să aibă valoarea de adevăr <tex> 1 </tex>.\r\n\r\nh3(#solutie-1). Soluţie $O(M * 2^N^)$\r\n\r\nO primă metodă de rezolvare ar fi să încercăm toate cele $2^N^$ posibilităţi de atribuire posibilă, dar această metodă are ordinul de complexitate $O(M * 2^N^)$ şi este eficientă doar pentru instanţe mici ale problemei.\r\n\r\nh3(#solutie-2). Soluţie $O(N * M)$\r\n\r\nUrmătoarea soluţie pare trivială, dar găsirea acestui algoritm şi realizarea faptului că el rezolvă corect problema sunt mai grele decât impresia lăsată după citirea ei. Considerăm o propoziţie oarecare cu două variabile $p$ şi $q$, apoi una dintre ele, de exemplu $p$. îi atribuim literalului în care apare $p$ valoarea $0$. Pentru ca propoziţia respectivă să aibă $1$ valoarea de adevăr, atunci valoarea lui $q$ trebuie fixată. Fixând şi valoarea lui $q$, probabil şi alte propoziţii ce conţin literalul $q$ vor avea celălalt literal fixat. Propagăm astfel o serie de schimbări. După ce toate schimbările forţate au fost făcute, propoziţiile rezultate vor fi de următoarele tipuri: <tex> a \\vee b </tex>, <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex>. Propoziţii de tip <tex> 0 \\vee b </tex> nu pot apărea pentru că toate schimbările forţate au fost deja propagate. Dacă apare o propoziţie <tex> 0 \\vee 0 </tex> atunci alegerea făcută pentru valoarea lui $p$ este greşită. Vom încerca şi alegerea opusă pentru $p$. Dacă ambele duc la o propoziţie de tip <tex> 0 \\vee 0 </tex> atunci expresia nu poate fi satisfăcută. Propoziţiile de forma <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex> pot fi ignorate. în acest fel am eliminat cel puţin o variabilă şi o propoziţie din expresie. Dacă expresia iniţială era satisfiabilă, atunci şi expresia din care s-au eliminat câteva propoziţii a rămas satisfiabilă. Continuând pe această idee obţinem un algoritm de complexitate $O(N * M)$, pentru că la fiecare atribuire de valoare pentru o variabilă parcurgem şirul de propoziţii o dată. \r\n\r\nSă vedem cum funcţionează algoritmul pentru expresia: <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Considerăm propoziţia <tex> (x_{1} \\vee \\sim x_{2}) </tex> şi <tex> \\langle x_{2} = 1 \\rangle </tex>. Astfel, vom obţine mai departe <tex> (x_{1} \\vee 0) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee 1) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. în propoziţia <tex> (x_{1} \\vee 0) </tex>, <tex> x_{1} </tex> trebuie să fie egal cu <tex> 1 </tex>. Acum, expresia devine: <tex> (0\\ \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee 0) </tex>. Din propoziţia <tex> (0\\ \\vee \\sim x_{3}) </tex> obţinem <tex> \\langle x_{3} = 0 \\rangle </tex>, iar din <tex> (x_{4} \\vee 0) </tex> obţinem <tex> \\langle x_{4} = 1 \\rangle </tex>. Deci, atribuirea satisfiabilă este <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>.\r\n\r\nh3(#solutie-3). Soluţie $O(N^2^)$\r\n\r\nO altă soluţie elegantă se bazează pe o metodă randomizată:\r\n\r\n== code(cpp) |\r\natribuim valori booleene arbitrare variabilelor;\r\ncât timp expresia nu este satisfăcută, execută\r\n    găsim o propoziţie cu valoarea de adevăr 0;\r\n    schimbăm valoarea de adevăr a oricăreia dintre cele două variabile prezente în propoziţie;\r\nsfârşit cât timp\r\n==\r\n\r\nLinia $4$ va face ca acea propoziţie să aibă noua valoare de adevăr <tex> 1 </tex>.\r\n\r\nDe ce ar merge acest algoritm? Să presupunem că există o soluţie a problemei, o notăm cu <tex> S </tex>, iar cu <tex> X </tex> notăm şirul valorilor curente ale variabilelor. Ne uităm la fiecare pas al algoritmului la numărul de variabile care au valori diferite în soluţie faţă de cele din <tex> X </tex> (acest număr de diferenţe între elementele de acelaşi index pentru două şiruri se mai numeşte şi \'distanţă Hamming\':http://en.wikipedia.org/wiki/Hamming_distance între şiruri). Fie această valoare la pasul current $K$. Noi am vrea să avem $K = 0$. Cum va evolua $K$ pe parcursul algoritmului? La un moment dat noi schimbăm valoarea unei variabile luate aleator dintr-o propoziţie nesatisfăcută. Pentru că în <tex> S </tex> propoziţia este satisfăcută, înseamnă că cel puţin una dintre cele două variabile ale propoziţiei are valori diferite în <tex> X </tex> faţă de <tex> S </tex>. Astfel, operaţia făcută de noi are probabilitate de cel puţin $0.5$ să ne aducă mai aproape de soluţie. Vom nota cu <tex> T(i) </tex> numărul probabil de paşi în care un şir <tex> X </tex> aflat la distanţa Hamming egală cu $i$ faţă de <tex> S </tex>, va fi transformat în <tex> S </tex>. Evident:\r\n\r\n<tex> T(0) = 0 </tex>\r\n\r\n<tex> T(i) \\le \\frac {T(i + 1) + T(i - 1)}{2} + 1 </tex> pentru $0 < i < N$ ({$N$} e numărul de variabile booleene ale expresiei)\r\n\r\nSe pune semnul de inegalitate pentru că ambele variabile pot avea valori diferite faţă de cele din soluţie, deci schimbarea valorii oricăreia ar putea să ne aducă mai aproape de soluţie.\r\n\r\nDacă toate variabilele diferă de soluţie, orice schimbare ne aduce mai aproape de aceasta:\r\n\r\n<tex> T(N) = T(N - 1) + 1 </tex>\r\n\r\nNe interesează numai limitele superioare, deci folosim doar egalităţi în loc de inegalităţi:\r\n\r\n<tex> X(0) = 0 </tex>, <tex> X(i) = \\frac {X(i + 1) + X(i - 1)}{2} + 1 </tex>, <tex> X(N) = X(N - 1) + 1 </tex>\r\n\r\nDacă adunăm toate ecuaţiile obţinem:\r\n\r\n<tex> X(0) + X(1) + ... + X(N) = </tex> <tex> \\frac {X(0) + X(1) + 2X(2) + ... + 2X(N - 2) + X(N - 1) + X(N)}{2} + X(N) + N - 1 </tex>\r\n\r\nDe aici avem că <tex> \\frac {X(1) + X(N - 1) - X(N)}{2} = N - 1 </tex>, iar din <tex> X(N) = X(N - 1) + 1 </tex> rezultă că <tex> X(1) = 2N - 1 </tex>. Mai departe avem că <tex> X(2) = 4N - 4 </tex> <tex> ... </tex> <tex> X(i) = 2iN - i^2 </tex>, de unde, când <tex> i = N </tex>, avem că <tex> X(N) = N^2 </tex>.\r\n\r\nAstfel, numărul mediu de paşi ai algoritmului este pătratic în numărul $N$ de variabile. Lăsând algoritmul să ruleze de 2-3 ori mai mulţi paşi decât numărul mediu, avem o probabilitate foarte mare să ajungem la rezultat.\r\n\r\nh3(#solutie-4). Soluţie $O(M + N)$\r\n\r\nO a treia soluţie se bazează pe relaţia de implicaţie. Relaţia <tex> \\rightarrow </tex> are următoarea tabelă de adevăr:\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> A \\rightarrow B </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nRelaţia de implicaţie are următoarea semnificaţie: dacă <tex> A </tex> este adevărat atunci şi <tex> B </tex> este adevărat. Scriem tabela expresiei <tex> \\sim A \\vee B </tex> şi observăm că aceasta este egală cu cea a relaţiei de implicaţie.\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> \\sim A \\vee B </tex>|\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nFiecare clauză <tex> A \\vee B </tex> poate fi scrisă ca două implicaţii <tex> \\sim A \\rightarrow B </tex> şi <tex> \\sim B \\rightarrow A </tex>. Realizăm un graf al implicaţiilor. Astfel, nodurile grafului vor fi variabilele <tex> A </tex>, <tex> B </tex> <tex> ... </tex> şi negaţiile lor <tex> \\sim A </tex>, <tex> \\sim B </tex> <tex> ... </tex> iar muchiile acestui graf vor fi implicaţiile echivalente cu propoziţiile din expresie. Deci, dacă expresia are $M$ propoziţii, graful va avea $2M$ muchii. Acestea fiind zise, expresiei <tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) </tex> îi corespunde graful:\r\n\r\np=. !2-sat?Graf.png!\r\n\r\nDacă avem <tex> A \\longrightarrow B </tex> o muchie în graful nostru şi literalul <tex> A </tex> este adevărat, atunci şi literalul <tex> B </tex> trebuie să fie adevărat pentru ca propoziţia reprezentată de muchie să fie satisfăcută. Putem demonstra prin inducţie că dacă există un drum în graf de la literalul <tex> A </tex> la literalul <tex> B </tex>, atunci dacă <tex> A </tex> este adevărat şi <tex> B </tex> trebuie să fie adevărat. Dacă există un drum de la un literal <tex> X </tex> la <tex> \\sim X </tex>, precum şi un drum invers, atunci nu va exista soluţie pentru că nu putem seta în acelaşi timp o variabilă şi valoarea ei negată la valoarea adevărat. De aici rezultă că dacă în graful asociat expresiei există o variabilă <tex> X </tex> în aceeaşi componentă tare conexă cu <tex> \\sim X </tex> atunci instanţa problemei satisfiabilităţii nu poate fi satisfăcută. Dacă nu există o asemenea variabilă, vom vedea în continuare cum putem rezolva problema. întâi, facem observaţia că dacă în graf există muchia <tex> A \\longrightarrow B </tex> atunci există şi muchia <tex> \\sim B \\longrightarrow \\sim A </tex>. Astfel, dacă există un drum de la <tex> A </tex> la <tex> B </tex> în graf, aplicând proprietatea menţionată pentru fiecare muchie a drumului, vom găsi un drum de la <tex> \\sim B </tex> la <tex> \\sim A </tex>. Evident, afirmaţia este valabilă şi reciproc: dacă există drum de la <tex> B </tex> la <tex> A </tex> atunci vom avea un drum de la nodul <tex> \\sim A </tex> la <tex> \\sim B </tex>. Astfel, dacă avem că <tex> A </tex> şi <tex> B </tex> sunt în aceeaşi componentă tare conexă atunci şi nodurile <tex> \\sim A </tex> şi <tex> \\sim B </tex> sunt în aceeaşi componentă tare conexă. Deci, dacă nu există doi literali <tex> X </tex> şi <tex> \\sim X </tex> în aceeaşi componentă tare conexă, putem să împărţim graful în componente tare conexe şi să împerechem componentele câte două astfel ca în fiecare pereche să apară o componentă <tex> U </tex> cu nişte literali şi altă componentă <tex> \\sim U </tex> cu aceiaşi literali negaţi. Pentru a găsi o soluţie vom determina mai întâi componentele tare conexe ale grafului. Apoi putem contracta fiecare componentă într-un nod. Graful obţinut va fi aciclic. Alegem un nod <tex> u </tex> în care nu intră nicio muchie (un asemenea nod trebuie să existe pentru a nu exista cicluri). Din considerente de simetrie, din nodul lui pereche <tex> \\sim u </tex> nu va ieşi nicio muchie. Literalilor componentei <tex> U </tex> putem să le dăm valoarea de adevăr <tex> 0 </tex>, iar literalilor din componenta pereche <tex> \\sim U </tex>  putem să le dăm valoarea de adevăr <tex> 1 </tex>. Această alegere nu impune restricţii asupra celorlalţi literali şi elimină câteva variabile din problemă. Repetarea recursivă a acestui pas pe graful rămas va duce la rezolvarea problemei. Determinarea componentelor tare conexe se poate face în complexitatea $O(N + M)$. Pentru a vedea acest algoritm puteţi consulta \'secţiunea $23.5$\':http://zhuzeyuan.hp.infoseek.co.jp/ita/chap23.htm din {\'[1]\':2-sat#bibliografie}. Iar eliminarea  nodurilor de care vorbeam mai sus se poate face în $O(N + M)$ folosind o sortare topologică.\r\n\r\nSă urmărim cum merge algoritmul nostru pe exemplul de mai sus. Componentele tare conexe sunt următoarele: <tex> \\{A\\} </tex>, <tex> \\{\\sim A\\} </tex>, <tex> \\{B, C, \\sim D\\} </tex>, <tex> \\{\\sim B, \\sim C, D\\} </tex>. în nodul asociat componentei <tex> \\{A\\} </tex> nu intră nici o muchie. Astfel, putem să îi atribuim lui <tex> A </tex> valoarea <tex> 0 </tex>, iar după eliminarea lui <tex> \\{A\\} </tex> şi <tex> \\{\\sim A\\} </tex>în nodul asociat componentei <tex> \\{\\sim B, \\sim C, D\\} </tex> nu intră nicio muchie, deci putem să îi atribuim lui <tex> B </tex> valoarea <tex> 1 </tex>, lui <tex> C </tex> valoarea <tex> 1 </tex> şi lui <tex> D </tex> valoarea <tex> 0 </tex>. Această atribuire este satisfiabilă după cum vedem în continuare:\r\n\r\n<tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) = </tex> <tex> (\\sim 0 \\vee \\sim 1) \\wedge (1 \\vee \\sim 1) \\wedge (1 \\vee 1) \\wedge (\\sim 1 \\vee \\sim 0) \\wedge (1 \\vee 0) = </tex> <tex> 1 \\wedge 1 \\wedge 1 \\wedge 1 \\wedge 1 = 1 </tex>\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\nRestul articolului va prezenta aplicaţii ale problemei $2-SAT$ din concursurile de programare.\r\n\r\nh2(#party). \'Party\':problema/party (preONI 2003/2004)\r\n\r\nbq. George vrea să îşi organizeze majoratul, şi vrea ca petrecerea să fie de neuitat, mâncarea, băutura, locaţia şi sonorizarea sunt deja asigurate, mai rămâne problema chemării prietenilor. El şi cu prietenul lui cel mai bun Lucian au preferinte diferite şi pentru a nu se certa au pus la punct o listă de cerinţe care vor trebui să fie îndeplinite astfel încât cheful să se desfăşoare în cele mai bune condiţii! Pentru uşurinţă,  prietenii lui George vor fi indentificaţi prin numere întregi de la $1$ la $N (1 ≤ N ≤ 100)$ şi cerinţele în număr de $M  (1 ≤ M ≤ 1.000)$ vor fi de tipurile 0, 1, 2 sau 3. O cerinţă de genul <tex> x \\ y </tex> 0 are semnificaţia că <tex> x </tex> sau <tex> y </tex> trebuie să participe la petrecere; <tex> x \\ y </tex> 1 are semnificaţia că dacă <tex> x </tex> participă nu există nici o restricţie pentru <tex> y </tex>, dar dacă <tex> x </tex> nu participă atunci nici <tex> y </tex> nu participa; <tex> x \\ y </tex> 2 are semnificaţia simetrică cu cerinţa 1; iar cerinţa <tex> x \\ y </tex> 3 are semnificaţia că cel puţin unul dintre <tex> x </tex> şi <tex> y </tex> nu participă la petrecere. Scrieţi un program care să-i ajute pe cei doi să determine care persoane vor fi invitate la petrecere. Se garantează că va fi posibilă întotdeauna organizarea unei petreceri!\r\n\r\nh3. Soluţie\r\n\r\nAceastă problemă este inspirită din o problemă de la $CEOI 2002$ şi este evident că ne cere să determinăm o atribuire satisfiabilă pentru o formulă logică formată ca conjuncţie între cerinţele care se transformă astfel:\r\n\r\n* cerinţa de tip 0 corespunde propoziţiei <tex> x \\vee y </tex>;\r\n* cerinţa de tip 1 corespunde propoziţiei <tex> x \\vee \\sim y </tex>;\r\n* cerinţa de tip 2 corespunde propoziţiei <tex> \\sim x \\vee y </tex>;\r\n* cerinţa de tip 3 corespunde propoziţiei <tex> \\sim x \\vee \\sim y </tex>.\r\n\r\nUna din primele două rezolvări ar fi putut soluţiona această problemă, dar problema de la $CEOI$ avea limite mai mari şi pentru rezolvarea ei ar fi trebuit un algoritm de complexitate $O(N + M)$.\r\n\r\nh2(#cigraf). Cigraf\r\n\r\n_Autor: Mugurel Ionuţ Andreica_\r\n\r\nbq. Se dă un graf neorientat cu $N (1 <= N <= 1000)$ noduri şi $M (0 <= M <= N*(N-1)/2)$ muchii. Se doreşte împărţirea nodurilor acestui graf în $2$ mulţimi, <tex> C </tex> şi <tex> I </tex>, având următoarele proprietăţi: fiecare nod face parte din exact una din cele $2$ mulţimi, există muchie între oricare $2$ noduri din mulţimea <tex> C </tex>, nu există nicio muchie între $2$ noduri din mulţimea <tex> I </tex>. Este posibil ca una dintre cele $2$ mulţimi să fie vidă. Soluţia nu este neaparat unică. Numele celor două mulţimi provin de la $clică$ şi $mulţime independentă$. De exemplu, pentru graful de $6$ noduri ce are muchiile <tex> \\{\\{1, 4\\}, \\{4, 6\\}, \\{6, 1\\}, \\{2, 4\\}, \\{2, 6\\}, \\{3, 4\\}, \\{1, 3\\}\\} </tex> o împărţire posibilă ar fi <tex> C = \\{1, 4, 6\\} </tex>, <tex> I = \\{2, 3, 5\\} </tex>.\r\n\r\nh3. Soluţie\r\n\r\nDacă între două noduri există muchie atunci nu pot fi amândouă în mulţimea <tex> I </tex>, iar dacă între două noduri nu există muchie nu pot fi amândouă în mulţimea <tex> C </tex>. \r\nTransformăm această problemă într-o instanţă de $2-SAT$ astfel: faptul că nodul <tex> x </tex> aparţine mulţimii <tex> C </tex> îl reprezentăm dândui lui <tex> x </tex> valoarea <tex> 1 </tex>, iar apartenenţa mulţimii <tex> I </tex> se codifică prin valoarea <tex> 0 </tex>. Acum existenţa unei muchii <tex> (x, y) </tex> corespunde expresiei <tex> x \\vee y </tex>, astfel cel puţin unul din nodurile <tex> x </tex> şi <tex> y </tex> nu va fi în mulţimea <tex> I </tex>. Dacă nu există muchia <tex> (x, y) </tex> putem scrie <tex> \\sim x \\vee \\sim y </tex>, această expresie va fi adevărată dacă cel puţin un nod din cele două nu va fi în mulţimea <tex> C </tex>.\r\nAceastă soluţie este liniară ca şi complexitate în numărul de elemente citite la intrare.\r\n\r\nh2(#peace-commission). Peace Commission (Polish Olympiad in Informatics, 2001)\r\n\r\nbq. Comisia Publică a Păcii trebuie să fie compusă în parlamentul Republicii Democrate a ţării Byteland după regulile impuse de Legea Foarte Importantă. Din păcate, unul dintre obstacole este acela că unii deputaţi nu se înţeleg cu ceilalţi. Comisia trebuie realizată astfel ca următoarele condiţii să fie îndeplinite: fiecare partid trebuie să aibă exact un reprezentant în comisie; dacă doi deputaţi nu se înţeleg, ei nu pot fi ambii membrii ai comisiei. Fiecare partid are exact doi deputaţi în parlament. Toţi număraţi de la $1$ până la $2n (1 <= n <= 8000)$. Deputaţii cu numerele $2i-1$ şi $2i$ aparţin celui de al $i$-lea partid. Se vor da $m (0 <= m <= 20 000)$ perechi de deputaţi <tex> (a, b) </tex> care nu se înţeleg. Se cere realizarea unei comisii dacă acest lucru este posibil. Un exemplu ar fi pentru trei partide şi perechile <tex> (1, 3) </tex> şi <tex> (2, 4) </tex> care nu se înţeleg comisia alcătuită din membrii <tex> \\{1, 4, 5\\} </tex>.\r\n\r\nh3. Soluţie\r\n\r\nFiecărui partid îi vom asocia o variabilă; variabila va lua valoarea <tex> 1 </tex> dacă membrul $2i - 1$ al partidului va aparţine comisiei şi valoarea <tex> 0 </tex> dacă membrul $2i$ va aparţine comisiei. Pentru ca din partidul $x$ să existe exact un membru în expresie introducem  <tex> A_{x} \\wedge \\sim A_{x} </tex>. \r\nPutem exprima că doi membrii ai parlamentului $(2i, 2j)$ nu se înţeleg prin expresia logică <tex> \\sim A_{i} \\vee \\sim A_{j} </tex>. Astfel nu pot ambele variabile <tex> A_{i} </tex> şi <tex> A_{j} </tex> să aibă în acelaşi timp valoarea <tex> 1 </tex> adică $2i$ şi $2j$ nu pot face parte în acelaşi timp din comisie. Dacă cei doi membrii sunt $(2i - 1, 2j - 1)$ atunci îi putem codifica prin expresia <tex> A_{i} \\vee A_{j} </tex> astfel <tex> A_{i} </tex> şi <tex> A_{j} </tex> nu pot avea în acelaşi timp valoarea <tex> 0 </tex>, iar dacă membrii sunt $(2i , 2j - 1)$ se poate scrie ca <tex> \\sim A_{i} \\vee A_{j} </tex> astfel <tex> A_{i} </tex> nu poate avea valoarea <tex> 1 </tex> când <tex> A_{j} </tex> are valoarea <tex> 0 </tex>.\r\nExemplul din problemă poate fi scris ca expresia logică în modul următor: <tex> A_{1} \\wedge \\sim A_{1} \\wedge A_{2} \\wedge \\sim A_{2} \\wedge A_{3} \\wedge \\sim A_{3} \\wedge (A_{1} \\vee A_{2}) \\wedge (\\sim A_{1} \\vee \\sim A_{2}) </tex>. \r\nDin nou vom putea folosi cel de al {\'patrulea algoritm\':2-sat#solutie4} explicat pentru a obţine o rezolvare de complexitate $O(N + M)$. \r\n\r\nh2(#excursion). Excursion (Baltic Olympiad in Informatics, 2001)\r\n\r\nbq. Un grup de turişti are ocazia să viziteze mai multe oraşe. Fiecare turist spune două dorinţe ale sale despre ce oraş ar vrea sau nu ar vrea să viziteze. O dorinţă a turistului  va spune despre exact un oraş dacă vrea sau nu vrea să îl viziteze. Este posibil ca ambele dorinţe ale unui turist să exprime acelaşi lucru sau să exprime lucruri opuse (de exemplu „Vreau să vizitez oraşul A!” şi „Nu vreau să vizitez oraşul A!”). Va trebui să determinaţi după citirea cerinţelor celor $n$ turişti despre $m$ oraşe dacă există o mulţime a oraşelor pentru care cel puţin o dorinţă a fiecărui turist este îndeplinită $(1 <= n <= 20 000, 1 <= m <= 8 000)$. De exemplu, să presupunem că avem $3$ turişti, $4$ oraşe şi primul turist are dorinţele de a vizita oraşul întâi şi de a nu vizita oraşul doi, al doilea turist are dorinţele de a vizita oraşul doi şi de a vizita oraşul patru, iar al treilea turist are dorinţele de a vizita oraşul trei şi de a vizita oraşul unu. O soluţie pentru acest exemplu ar fi vizitarea tuturor oraşelor.\r\n\r\nh3. Soluţie\r\n\r\nEste evident că şi această problemă se poate uşor transforma într-o instanţă de $2-SAT$. Fiecare turist ne dă prin dorinţele sale o expresie literală cu doi literali. Vizitarea sau nevizitarea oraşului de index $i$ va fi reprezentată prin variabila booleană <tex> A_{i} </tex>.  Exemplul din problemă poate fi transformat astfel: <tex> (A_{1} \\vee \\sim A_{2}) \\wedge (A_{2} \\vee A_{4}) \\wedge (A_{3} \\vee A_{1}) </tex>.\r\n\r\nh2(#orpath). Orpath (Olimpiadă Rusia)\r\n\r\nbq. într-o ţară pacifistă, există $N$ oraşe şi $K$ autobuze $(1 <= N, K <= 100)$. La orele aglomerate ale zilei, nu trebuie să existe două autobuze care merg în acelaşi timp în sensuri opuse. Traseul fiecărui autobuz este un ciclu. Spunem că el merge în sens pozitiv dacă va parcurge oraşele în ordinea $1 2 3 4 1 2 3 4 1 2$ ... sau în sens negativ dacă le parcurge în ordinea $1 4 3 2 1 4 3 2 1 4$ ... Găsiţi o posibilitate de atribuire a sensului fiecărui autobuz astfel ca accidentele de trafic să fie evitate (nu vor exista două autobuze care să se întâlnească şi să aibă sensuri de mers opuse). Pentru fiecare autobuz se vor şti oraşele de pe ruta lui, şi pentru fiecare două oraşe vecine pe rută se va şti timpul necesar autobuzului pentru a ajunge dintr-un oraş în altul. De exemplu, pentru $4$ oraşe unde oricare două sunt la timp de mers egal cu $10$, şi pentru două autobuze cu rutele $1 2 4$ şi $3 4 2$, o soluţie ar fi ca primul autobuz să meargă în sens pozitiv iar celălalt în sens negativ.\r\n\r\nh3. Soluţie\r\n\r\nPentru orice două autobuze vom găsi care sunt sensurile de mers pentru ele astfel ca cele două autobuze să nu se întâlnească şi să provoace un accident. Pentru un sens fixat putem afla pentru un autobuz pe ce interval de timp va fi pe o anumită stradă. El va fi în general pe o stradă $(i, j)$ pe un interval de tipul $[t1 + k*T … t2 + k*T]$ unde $t1$ este timpul din prima rută parcursă pentru a ajunge la $i$, $t2$ timpul pentru a ajunge la $j$ iar $T$ este durata totală a unei rute. Acum, pentru a determina dacă două autobuze se vor întâlni pe o rută $(i, j)$ trebuie ca ele să se deplaseze în sensuri opuse pe această rută, iar intervalele lor $[t1 + k*T1 .. t2 + k*T1]$ se intersectează cu intervalele $[tt1 + p*T2 … tt2 + p*T2]$. Este clar acum că putem transforma problema într-o instanţă de $2-SAT$ prin maparea autobuzelor în variabile logice, a sensurilor de mers în valorile $adevărat$ şi $fals$, iar pentru orice pereche de autobuze să fie o propoziţie logică ce ia valoarea $adevărat$ doar dacă sensurile de mers determinate de variabilele logice asociate autobuzelor sunt compatibile. Mai trebuie determinat într-un mod eficient dacă două clase de intervale de timp se intersectează. Aceasta rămâne ca temă cititorului.\r\n\r\nh2(#aladdin). \'Aladdin\':problema/aladdin (Bursele Agora 2005/2006, Runda 1)\r\n\r\nbq. Aladdin, aşa cum ştiaţi, este un mare magnat în afacerea de comercializare a covoarelor magice. Acesta doreşte să o cucerească pe prinţesa Iasmina, iar aceasta, pentru a-i testa inteligenţa îl roagă să îi facă un covor dreptunghiular împărţit în pătrăţele, asemănator unei table de şah cu $N$ linii şi $M$ coloane $(1 <= N, M <= 1000)$. Fiecare pătrăţel de pe covor trebuie colorat cu alb sau cu negru. Pentru fiecare pătrat care conţine $4$ pătrăţele Iasmina pune condiţia să aibă un număr fixat de pătrăţele colorate cu negru. Ajutaţi-l pe Aladdin să realizeze un covor care satisface condiţiile impuse de prinţesa Iasmina!\r\n\r\nh3. Soluţie\r\n\r\nîntâi, să considerăm un exemplu. Pentru o cerinţă de forma:\r\n\r\ntable{width: 90px; text-align: center}.\r\n| <tex> 3 </tex> | <tex> 2 </tex> | <tex> 3 </tex> |\r\n| <tex> 2 </tex> | <tex> 3 </tex> | <tex> 3 </tex> |\r\n| <tex> 1 </tex> | <tex> 2 </tex> | <tex> 1 </tex> |\r\n\r\nuna din soluţii este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nFie <tex> A </tex> o matrice soluţie a problemei noastre. Vom numerota rândurile matricii de la $0$ la $N - 1$ şi coloanele de la $0$ la $M - 1$. Matricea de intrare <tex> S </tex> reprezintă de fapt sumele din fiecare pătrat de câte $2 x 2$ elemente. Facem observaţia că dacă ştim într-un pătrat de $2 x 2$ valorile pentru trei dintre celule, atunci valoarea din a patra celulă este unic determinată pentru că ştim suma elementelor din pătrat. Vedem astfel, că dacă ştim valorile elementelor din prima linie a matricii <tex> A </tex> şi din prima coloană, restul valorilor sunt unic determinate. \r\nPentru a rezolva problema vom presupune <tex> A[0][0] </tex> cunoscut (de fapt, mai întâi vom rezolva problema presupunând că <tex> A[0][0] = 1 </tex>, iar dacă nu obţinem nicio soluţie vom încerca cu <tex> A[0][0] = 0 </tex>). Vom nota celulele <tex> A[0][1] </tex>, <tex> A[0][2]</tex>, … <tex> A[0][M - 1] </tex> cu <tex> x_{1} </tex>, <tex> x_{2} </tex>, … <tex> x_{M-1} </tex> iar celulele <tex> A[1][0] </tex>, <tex> A[2][0] </tex>, … <tex> A[N - 1][0] </tex> cu <tex> y_{1} </tex>, <tex> y_{2} </tex>, … <tex> y_{N-1} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> A[0][0] </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> ... </tex> | <tex> x_{M-1} </tex> |\r\n| <tex> y_{1} </tex> | <tex> 1 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n| <tex> y_{2} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 0 </tex> |\r\n| ... | ... | ... | ... | ... |\r\n| <tex> y_{N-1} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n\r\nAcum, pentru fiecare celulă putem demonstra prin inducţie că <tex> A[i][j] = (-1)^i x_{j} + (-1)^j y_{i} + b[i][j] </tex>. Unde <tex> b[i][j] </tex> sunt nişte constante ce sunt calculate în funcţie de matricea primită la intrare.\r\nEste uşor de observat că dacă:\r\n<tex> A[i-1][j] = (-1)^{(i-1)} x_{j} + (-1)^j y_{i-1} + b[i-1][j] </tex>, \r\n<tex> A[i-1][j-1] = (-1)^{(i-1)} x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i-1][j-1] </tex>, \r\n<tex> A[i][j-1] = (-1)^i x_{j-1} + (-1)^{(j-1)} y_{i} + b[i][j-1] </tex>, \r\n\r\natunci:\r\n\r\n<tex> A[i][j] = S[i-1][j-1] - A[i-1][j] - A[i][j-1] - A[i-1][j-1] = </tex> \r\n<tex> = S[i-1][j-1] - ((-1)^{(i-1)} x_{j} + (-1)^j y_{i-1} + b[i-1][j]) - </tex> <tex> ((-1)^{(i-1)} x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i-1][j-1]) - ((-1)^i x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i][j-1]) = </tex> \r\n<tex> = (-1)^i x_{j} - (-1)^j y_{i-1} + (-1)^i x_{j-1} + (-1)^j y_{i-1} - </tex> <tex> (-1)^i x_{j-1} + (-1)^j y_{i} + S[i-1][j-1] - b[i-1][j] - b[i][j-1] - b[i-1][j-1] = </tex> \r\n<tex> = (-1)^i x_{j} + (-1)^j y_{i} + b[i][j] </tex>. \r\n\r\nDe aici concluzionăm că <tex> b[i][j] = S[i-1][j-1] - b[i-1][j] - b[i][j-1] - b[i-1][j-1] \\ (*)</tex>.\r\n\r\nAvem un sistem format din inecuaţiile:\r\n\r\n<tex> 0 \\le x_{j} \\le 1 </tex>\r\n<tex> 0 \\le y_{i} \\le 1 </tex>\r\n<tex> -b[i][j] \\le (-1)^i x_{j} + (-1)^j y_{i} \\le 1 - b[i][j] </tex>\r\n\r\nEste uşor acum să transformăm acest sistem într-o formulă booleană în {\'formă normal conjunctivă\':2-sat#forme-normale} în care fiecare expresie are cel mult $2$ literali. Fiecare relaţie o putem înmulţi sau nu cu $-1$ astfel ca părţile constante ale relaţiei să fie pozitive. Observăm că <tex> | b[i][j] | \\le 2 </tex>, altfel nu avem soluţie. Dacă <tex> | b[i][j] | = 2 </tex> atunci ambele variabile au valori fixe, iar dacă <tex> | b[i][j] | = 1 </tex> sau <tex> | b[i][j] | = 0 </tex> atunci relaţia o putem scrie ca o disjuncţie logică cu doi literali.\r\n\r\nO relaţie precum <tex> 0 \\le x + y \\le 1 </tex> poate fi tansformată logic în <tex> \\sim x \\vee \\sim y </tex>, astfel <tex> x </tex> şi <tex> y </tex> nu vor fi în acelaşi timp <tex> 1 </tex>, una de genul <tex> 1 \\le x + y \\le 2 </tex> va fi transformată în <tex> (x \\vee y) </tex>, astfel cel puţin <tex> x </tex> sau <tex> y </tex> va fi egal cu <tex> 1 </tex>, alta de tipul <tex> 0 \\le x - y \\le 1 </tex> poate fi scrisă ca <tex> x \\vee \\sim y </tex>, una de tipul <tex> 2 \\le x + y \\le 3 </tex> în <tex> x \\wedge y </tex>, iar una de tipul <tex> 0 \\le -x -y \\le 1 </tex> în <tex> \\sim x \\wedge \\sim y </tex>, una de tipul <tex> 1 \\le x - y  \\le 2 </tex> în <tex> x \\wedge \\sim y </tex>.\r\n\r\nAstfel am redus problema la rezolvarea unei instanţe de $2-SAT$. Avem $N+M-1$ necunoscute şi {$(N-1)$}{$(M-1)$} propoziţii. Folosind a treia metodă de rezolvare vom obţine un algoritm de complexitate $O(N * M)$ care soluţionează problema noastră.\r\n\r\nSă vedem cum merge acestă rezolvare pe exemplul din problemă:\r\n\r\nAlegem <tex> A[0][0] = 1 </tex>. Necunoscutele vor fi <tex> x_{1} </tex>, <tex> x_{2} </tex>, <tex> x_{3} </tex> şi <tex> y_{1} </tex>, <tex> y_{2} </tex>, <tex> y_{3} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> x_{3} </tex> |\r\n| <tex> y_{1} </tex> | <tex> A[1][1] </tex> | <tex> A[1][2] </tex> | <tex> A[1][3] </tex> |\r\n| <tex> y_{2} </tex> | <tex> A[2][1] </tex> | <tex> A[2][2] </tex> | <tex> A[2][3] </tex> |\r\n| <tex> y_{3} </tex> | <tex> A[3][1] </tex> | <tex> A[3][2] </tex> | <tex> A[3][3] </tex> |\r\n\r\nFolosind recurenţa <tex> (*) </tex> obţinem că matricea <tex> b </tex> este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 2 </tex> | <tex> 0 </tex> | <tex> 3 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> -1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n\r\nDe aici obţinem sistemul de inegalităţi:\r\n\r\n<tex> 0 \\le x_{1} \\le 1,  0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le 1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, -2 \\le -x_{1} - y_{1} \\le -1, 0 \\le -x_{2} + y_{1} \\le 1, -3 \\le -x_{3} - y_{1} \\le -2, </tex>\r\n<tex> 0 \\le y_{2} \\le 1,  0 \\le  x_{1} - y_{2} \\le  1,-1 \\le  x_{2} + y_{2} \\le 0,  1 \\le  x_{3} - y_{2} \\le  2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, -1 \\le -x_{1} - y_{3} \\le  0, 0 \\le -x_{2} + y_{3} \\le 1, -1 \\le -x_{3} - y_{3} \\le  0 </tex>\r\n\r\nTransformăm relaţiile astfel ca să nu apară nici o constantă negativă:\r\n\r\n<tex> 0 \\le x_{1} \\le 1, 0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le  1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, 1 \\le x_{1} + y_{1} \\le 2, 0 \\le -x_{2} + y_{1} \\le 1, 2 \\le x_{3} + y_{1} \\le 3, </tex>\r\n<tex> 0 \\le y_{2} \\le 1, 0 \\le x_{1} - y_{2} \\le 1, 0 \\le -x_{2} - y_{2} \\le 1, 1 \\le x_{3} - y_{2} \\le 2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, 0 \\le x_{1} + y_{3} \\le 1, 0 \\le -x_{2} + y_{3} \\le 1, 0 \\le x_{3} + y_{3} \\le 1 </tex>\r\n\r\nAcest sistem poate fi transformat într-o expresie booleană:\r\n\r\n<tex> (x_{1} \\vee y_{1}) \\wedge (\\sim x_{2} \\vee y_{1}) \\wedge (x_{3} \\wedge y_{1}) \\wedge </tex>\r\n<tex> (x_{1} \\vee \\sim y_{2}) \\wedge (\\sim x_{2} \\wedge \\sim y_{2}) \\wedge (x_{3} \\wedge \\sim y_{2}) \\wedge </tex>\r\n<tex> (\\sim x_{1} \\vee \\sim y_{3}) \\wedge (\\sim x_{2} \\vee y_{3}) \\wedge (\\sim x_{3} \\vee \\sim y_{3}) </tex>.\r\n\r\nAcestă expresie e satisfăcută de valorile: <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 1, y_{1} = 1, y_{2} = 0, y_{3} = 0 \\rangle </tex>, iar de aici putem determina o soluţie a problemei noastre iniţiale ca fiind:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nh2(#bibliografie). Bibliografie:\r\n\r\n* [1] T. H. Cormen, C. E. Leiserson, R. R. Rivest - \'_Introducere in Algoritmi_\':http://zhuzeyuan.hp.infoseek.co.jp/ita/toc.htm\r\n* [2] \'_Satisfiability_\':http://en.wikipedia.org/wiki/Satisfiability, Wikipedia\r\n* [3] \'_BOI 2001 Competition Material_\':http://www.oi.edu.pl/download/boi-2001.pdf\r\n* [4] \'_CEOI 2002 Competition Material_\':http://ics.upjs.sk/ceoi/Documents.html',3146,'public',NULL,NULL),('heapuri','Heap-uri','2008-01-18 16:31:03','2008-12-26 19:31:21','h1. Heap-uri\r\n\r\n== include(page=\"template/implica-te/scrie-articole-2-autori\" user_id1=\"Cyber\" user_id2=\"silviug\") ==\r\n\r\n(Categoria _Structuri de date_, Autor _Catalin Francu_, Versiunea originala preluata din cartea _\"Psihologia concursurilor de informatica\"_)\r\n\r\n(toc){width: 30em}*{text-align:center;} *Continut*\r\n* \'Definirea notiunii de _heap_\':heapuri#definirea\r\n* \'Structura de heap si metode ajutatoare\':heapuri#structura\r\n* \'Cautarea maximului\':heapuri#cautarea_maximului\r\n* \'Crearea unei structuri de heap dintr-un vector oarecare\':heapuri#build_heap\r\n* \'Eliminarea unui element stiind pozitia lui in heap\':heapuri#cut\r\n* \'Inserarea unui element\':heapuri#insert\r\n* \'Sortarea unui vector (heapsort)\':heapuri#heap_sort\r\n* \'Cautarea unui element\':heapuri#find\r\n* \'STL\':heapuri#stl\r\n\r\n\r\nIn acest articol prezentam structura de date numita heap, cum poate fi aceasta implementata precum si alternative STL. Desi este putin probabil sa ajungeti sa implementati heap-urile de la \"zero\" daca stiti STL, consideram ca prezentarea acestora nu este de prisos. Aici atingem problema mai generala a \"de ce trebuie sa inteleg X (poate fi vorba de un algoritm, o structura de date, s.a.m.d.) daca il am deja implementat?\" Iata cateva motive:\r\n\r\n* va antreneaza mintea\r\n* va veti putea descurca in situatii in care aveti nevoie de o structura de date similara dar nu la fel\r\n* veti fi utilizatori informati ai bibliotecii STL\r\n* veti intelege cand este bine sa folosoti o structura de date si cand nu\r\n* veti avea avantajul de a sti precis de ce operatiile au anumite complexitati\r\n\r\nAcum ca avem o motivatie, sa studiem impreuna heap-urile.\r\n\r\nh2(#definirea). Definirea notiunii de _heap_\r\n\r\nUn heap (engl. gramada) este un vector care poate fi privit si ca un arbore binar, asa cum se vede in figura de mai jos:\r\n\r\n!heapuri?heap.JPG!\r\n\r\nLanga fiecare nod din arbore se afla cate un numar, reprezentand pozitia in vector pe care ar avea-o nodul respectiv. Pentru cazul considerat, vectorul echivalent ar fi  {$H = (12 10 11 10 7 9 3 2 8 1 4 3)$}.\r\n\r\nSe observa ca nodurile sunt parcurse de la stanga la dreapta si de sus in jos. O proprietate necesara pentru ca un arbore binar sa se poata numi heap este ca toate nivelele sa fie complete, cu exceptia ultimului, care se completeaza incepand de la stanga si continuand pana la un punct. De aici deducem ca inaltimea unui heap cu $N$ noduri este <tex> h=[\\log_2 N] </tex> (reamintim ca inaltimea unui arbore este adancimea maxima a unui nod, considerand radacina drept nodul de adancime 0). Reciproc, numarul de noduri ale unui heap de inaltime $h$ este <tex> N\\in [2^h, 2^{h+1}-1]</tex>.\r\n\r\nTot din aceasta organizare mai putem deduce ca tatal unui nod $k > 1$ este nodul $[k/2]$, iar fiii nodului k sunt nodurile $2k$ si $2k+1$. Daca $2k = N$, atunci nodul $2k+1$ nu exista, iar nodul $k$ are un singur fiu; daca $2k > N$, atunci nodul $k$ este frunza si nu are nici un fiu. Exemple: tatal nodului 5 este nodul 2, iar fiii sai sunt nodurile 10 si 11. Tatal nodului 6 este nodul 3, iar unicul sau fiu este nodul 12. Tatal nodului 9 este nodul 4, iar fii nu are, fiind frunza in heap.\r\n\r\nDar cea mai importanta proprietate a heap-ului, cea care il face util in operatiile de aflarea a maximului, este aceea ca valoarea oricarui nod este mai mare sau egala cu valoarea oricarui fiu al sau. Dupa cum se vede mai sus, nodul 2 are valoarea 10, iar fiii sai - nodurile 4 si 5 - au valorile 10 si respectiv 7. Intrucat operatorul &ge; este tranzitiv, putem trage concluzia ca un nod este mai mare sau egal decat oricare din nepotii sai si, generalizand, va rezulta ca orice nod este mai mare sau egal decat toate nodurile din subarborele a carui radacina este el.\r\n\r\nAceasta afirmatie nu decide in nici un fel intre valorile a doua noduri dispuse astfel incat nici unul nu este descendent al celuilalt. Cu alte cuvinte, nu inseamna ca orice nod de pe un nivel mic are valoare mai mare decat nodurile mai apropiate de frunze. Este cazul nodului 7, care are valoarea 3 si este mai mic decat nodul 9 de valoare 8, care este totusi asezat ma jos in heap. In orice caz, o prima concluzie care rezulta din aceasta proprietate este ca radacina are cea mai mare valoare din tot heap-ul.\r\n\r\nStructura de heap permite efectuarea multor operatii intr-un timp foarte bun:\r\n\r\n* Cautarea maximului in $O(1)$\r\n* Crearea unei structuri de heap dintr-un vector oarecare in $O(N)$\r\n* Eliminarea unui element in $O(log N)$\r\n* Inserarea unui element in $O(log N)$\r\n* Sortarea elementelor din heap in $O(N log N)$\r\n\r\nMentionam ca operatia de cautarea a unui element are complexitatea $O(N)$ dar, de obicei, heap-ul nu este folosit cand acest tip de operatii este frecvent.\r\n\r\nDesigur, toate aceste operatii se fac mentinand permanent structura de heap a arborelui, adica respectand modul de repartizare a nodurilor pe nivele si plasarea mai sus a elementelor de valoare mai mare. Este de la sine inteles ca datele nu se vor reprezenta in memorie in forma arborescenta, ci in cea vectoriala.\r\n\r\nPrecizam de asemenea ca heap-ul poate fi organizat si pe baza operatorului de $&le;$. In acest caz, in varful heap-ului vom avea minimul dintre elementele pastrate in heap. In functie de operatorul folosit, putem numi structura de date max-heap sau min-heap. In continuare vom prezenta operatiile intr-un max-heap, adaptarea lor pentru min-heap-uri fiind usoara.\r\n\r\nh2(#structura). Structura de heap si metode ajutatoare\r\n\r\nIn blocul de cod de mai jos prezentam cum se defineste un heap ca vector si cateva metode ajutatoare:\r\n\r\n==code(c) |\r\nconst int MAX_HEAP_SIZE = 16 * 1024;\r\ntypedef int Heap[MAX_HEAP_SIZE];\r\n\r\ninline int father(int nod) {\r\n    return nod / 2;\r\n}\r\n\r\ninline int left_son(int nod) {\r\n    return nod * 2;\r\n}\r\n\r\ninline int right_son(int nod) {\r\n    return nod * 2 + 1;\r\n}\r\n==\r\n\r\nh2(#cautarea_maximului). Cautarea maximului\r\n\r\nPractic operatia aceasta nu are de facut decat sa intoarca valoarea primului element din vector:\r\n==code(c) |\r\ninline int max(Heap H) {\r\n    return H[1];\r\n}\r\n==\r\n\r\nh2(#build_heap). Crearea unei structuri de heap dintr-un vector oarecare\r\n\r\nPentru a discuta acest aspect, vom vorbi mai intai despre doua proceduri specifice heap-urilor, _sift_ (engl. a cerne) si _percolate_ (engl. a se infiltra). Sa presupunem ca un vector are o structura de heap, cu exceptia unui nod care este mai mic decat unul din fiii sai. Este cazul nodului 3 din figura de mai jos, care are o valoare mai mica decat fii sai (nodurile 6 si 7):\r\n\r\n!heapuri?create1.JPG!\r\n\r\nCe e de facut ? Desigur, nodul va trebui coborat in arbore, iar in locul lui vom aduce alt nod, mai exact unul dintre fiii sai. Intrebarea este: care din fiii sai ? Daca vom aduce nodul 7 in locul lui, acesta fiind mai mic decat nodul 6, anomalia se va pastra. Trebuie deci sa schimbam nodul 3 cu nodul 6:\r\n\r\n!heapuri?create2.JPG!\r\n\r\nProblema nu este insa rezolvata, deoarece noul nod 6, proaspat \"retrogradat\", este inca mai mic decat fiul sau, nodul 12. De data aceasta avem un singur fiu, deci o singura optiune: schimbam nodul 6 cu nodul 12 si obtinem o structura de heap corecta:\r\n\r\n!heapuri?create3.JPG!\r\n\r\nProcedura sift primeste ca parametri un heap $H$ cu $N$ noduri si un nod $K$ si presupune ca ambii subarbori ai nodului $K$ au structura de heap corecta. Misiunea ei este sa \"cearna\" nodul $K$ pana la locul potrivit, interschimband mereu nodul cu cel mai mare fiu al sau pana cand nodul nu mai are fii (ajunge pe ultimul nivel in arbore) sau pana cand fiii sai au valori mai mici decat el.\r\n\r\n==code(c) |\r\nvoid sift(Heap H, int N, int K) {\r\n    int son;\r\n    do {\r\n        son = 0;\r\n        // Alege un fiu mai mare ca tatal.\r\n        if (left_son(K) <= N) {\r\n            son = left_son(K);\r\n            if (right_son(K) <= N && H[right_son(K)] > H[left_son(K)]) {\r\n                son = right_son(K);\r\n            }\r\n            if (H[son] <= H[K]) {\r\n                son = 0;\r\n            }\r\n        }\r\n\r\n        if (son) {\r\n            swap(H[K], H[son]);  // Functie STL ce interschimba H[K] cu H[son].\r\n            K = son;\r\n        }\r\n    } while (son);\r\n}\r\n==\r\n\r\nProcedura percolate se va ocupa tocmai de fenomenul invers. Sa presupunem ca un heap are o \"defectiune\" in sensul ca observam un nod care are o valoare mai mare decat tatal sau. Atunci, va trebui sa interschimbam cele doua noduri. Este cazul nodului 10 din figura care urmeaza. Deoarece fiul care trebuie urcat este mai mare ca tatal, care la randul lui (presupunand ca restul heap-ului e corect) este mai mare decat celalalt fiu al sau, rezulta ca dupa interschimbare fiul devenit tata este mai mare decat ambii sai fii. Trebuie totusi sa privim din nou in sus si sa continuam sa urcam nodul in arbore fie pana ajungem la radacina, fie pana ii gasim un tata mai mare ca el. Iata ce se intampla cu nodul 10:\r\n\r\n!heapuri?create4.JPG!\r\n\r\n==code(c) |\r\nvoid percolate(Heap H, int N, int K) {\r\n    int key = H[K];\r\n\r\n    while ((K > 1) && (key > H[father(K)])) {\r\n        H[K] = H[father(K)];\r\n        K = father(K);\r\n    }\r\n\r\n    H[K] = key;\r\n}\r\n==\r\n\r\nAcum ne putem ocupa efectiv de construirea unui heap. Am spus ca procedura sift presupune ca ambii fii ai nodului pentru care este ea apelata au structura de heap. Aceasta inseamna ca putem apela procedura sift pentru orice nod imediat superior nivelului frunzelor, deoarece frunzele sunt arbori cu un singru nod, si deci heap-uri corecte. Apeland procedura sift pentru toate nodurile de deasupra frunzelor, vom obtine deja o structura mai organizata, asigurandu-ne ca pe ultimele doua nivele avem de-a face numai cu heap-uri. Apoi apelam aceeasi procedura pentru nodurile de pe al treilea nivel incepand de la frunze, apoi pentru cele de deasupra lor si asa mai departe pana ajungem la radacina. In acest moment, heap-ul este construit. Iata cum functioneaza algoritmul pentru un arbore total dezorganizat:\r\n\r\n!heapuri?create5.JPG!\r\n\r\nNivelul frunzelor este organizat\r\n\r\n!heapuri?create6.JPG!\r\n\r\nUltimele doua nivele sunt organizate\r\n\r\n!heapuri?create7.JPG!\r\n\r\nUltimele trei nivele sunt organizate\r\n\r\n!heapuri?create8.JPG!\r\n\r\nStructura de heap\r\n\r\n==code(c) |\r\nvoid build_heap(Heap H, int N) {\r\n    for (int i = N/2; i > 0; --i) {\r\n        sift(H, N, i);\r\n    }\r\n}\r\n==\r\n\r\nS-a apelat caderea incepand de la al $N/2$ - lea nod, deoarece s-a aratat ca acesta este ultimul nod care mai are fii, restul fiind frunze. Sa calculam acum complexitatea acestui algoritm. Un calcul sumar ar putea spune: exista $N$ noduri, fiecare din ele se \"cerne\" pe $O(log N)$ nivele, deci timpul de constructie a heap-ului este $O(N log N)$. Totusi nu este asa. Presupunem ca ultimul nivel al heap-ului este plin. In acest caz, jumatate din noduri vor fi frunze si nu se vor cerne deloc. Un sfert din noduri se vor afla deasupra lor si se vor cerne cel mult un nivel. O optime din noduri se vor putea cerne cel mult doua nivele, si asa mai departe, pana ajungem la radacina care se afla singura pe nivelul ei si va putea cadea maxim h nivele (reamintim <tex> h=[\\log_2 N] </tex>). Rezulta ca timpul total de calcul este dat de formula <tex> O({\\sum_{k=1}^{[\\log_2 N]} k} \\times \\frac{N}{2^{k+1}}) = O(N) </tex>. Demonstrarea egalitatii se poate face facand substitutia $N=2^h^$ si continuand calculele. Se va obtine tocmai complexitatea $O(2^h^)$. Lasam aceasta verificare ca tema cititorului.\r\n\r\nh2(#cut). Eliminarea unui element stiind pozitia lui in heap\r\n\r\nDaca eliminam un element din heap, trebuie numai sa refacem structura de heap. In locul nodului eliminat s-a creat un gol, pe care trebuie sa il umplem cu un alt nod. Care ar putea fi acela? Intrucat trebuie ca toate nivelele sa fie complet ocupate, cu exceptia ultimului, care poate fi gol numai in partea sa dreapta, rezulta ca singurul nod pe care il putem pune in locul celui eliminat este ultimul din heap. Odata ce l-am pus in gaura facuta, trebuie sa ne asiguram ca acest nod \"de umplutura\" nu strica proprietatea de heap. Deci vom verifica: daca nodul pus in loc este mai mare ca tatal sau, vom apela procedura percolate. Altfel vom apela procedura sift, in eventualitatea ca nodul este mai mic decat unul din fiii sai. Iata exemplul de mai jos:\r\n\r\n!heapuri?delete1.JPG!\r\n\r\nSa presupunem ca vrem sa eliminam nodul de valoare 9, aducand in locul lui nodul de valoare X. Insa X poate fi orice numar mai mic sau egal cu 18. Spre exemplu, X poate fi 16, caz in care va trebui urcat deasupra nodului de valoare 10, sau poate fi 1, caz in care va trebui cernut pana la nivelul frunzelor. Deoarece caderea si urcarea se pot face pe cel mult $(log N)$ nivele, rezulta o complexitate a procedeului de $O(log N)$.\r\n\r\n==code(c) |\r\nvoid cut(Heap H, int& N, int K) {\r\n    H[K] = H[N];\r\n    --N;\r\n\r\n    if ((K > 1) && (H[K] > H[father(K)])) {\r\n        percolate(H, N, K);\r\n    } else {\r\n        sift(H, N, K);\r\n    }\r\n}\r\n==\r\n\r\nh2(#insert). Inserarea unui element\r\n\r\nDaca vrem sa inseram un nou element in heap, lucrurile sunt mult mai simple. Nu avem decat sa-l asezam pe a $N+1$-a pozitie in vector si apoi sa-l \"promovam\" pana la locul potrivit. Din nou, urcarea se poate face pe maxim $(log N)$ nivele, de unde complexitatea logaritmica.\r\n\r\n==code(c) |\r\nvoid insert(Heap H, int N, int key) {\r\n    H[++N] = key;\r\n    percolate(H, N, N);\r\n}\r\n==\r\n\r\nh2(#heap_sort). Sortarea unui vector (heapsort)\r\n\r\nAcum, ca am stabilit toate aceste lucruri, ideea algoritmului de sortare vine de la sine. Incepem prin a construi un heap. Apoi extragem maximul (adica varful heap-ului) si refacem heap-ul. Cele doua operatii luate la un loc dureaza $O(1)+O(log N) = O(log N)$. Apoi extragem din nou maximul, (care va fi al doilea element ca marime din vector) si refacem din nou heap-ul. Din nou, complexitatea operatiei compuse este $O(log N)$. Daca facem acest lucru de $N$ ori, vom obtine vectorul sortat intr-o complexitate de $O(N log N)$.\r\n\r\nPartea cea mai frumoasa a acestui algoritm, la prima vedere destul de mare consumator de memorie, este ca el nu foloseste deloc memorie suplimentara. Iata explicatia: cand heap-ul are $N$ elemente, vom extrage maximul si il vom tine minte undeva in memorie. Pe de alta parte, in locul maximului (adica in radacina arborelui) trebuie adus ultimul element al vectorului, adica $H[N]$. Dupa aceasta operatie, heap-ul va avea $N-1$ noduri, al $N$-lea ramanand liber. Ce alt loc mai inspirat decat acest al $N$-lea nod ne-am putea dori pentru a stoca maximul? Practic, am interschimbat radacina, adica pe $H[1]$ cu $H[N]$. Acelasi lucru se face la fiecare pas, tinand cont de micsorarea permanenta a heap-ului.\r\n\r\n==code(c) |\r\nvoid heap_sort(Heap H, int N) {\r\n    build_heap(H, N);\r\n\r\n    // Sorteaza vectorul.\r\n    for (int i = N; i >= 2; --i) {\r\n        swap(H[1], H[i]);\r\n        sift(H, i, 1);\r\n    }\r\n}\r\n==\r\n\r\nh2(#find). Cautarea unui element\r\n\r\nAceasta operatie este singura care nu poate fi optimizata (in sensul reducerii complexitatii sub $O(N)$). Aceasta deoarece putem fi siguri ca un nod mai mic este descendentul unuia mai mare, dar nu putem sti daca se afla in subarborele stang sau drept; din aceasta cauza, nu putem face o cautare binara. Totusi, o oarecare imbunatatire se poate aduce fata de cautarea secventiala. Daca radacina unui subarbore este mai mica decat valoarea cautata de noi, cu atat mai mult putem fi convinsi ca descendentii radacinii vor fi si mai mici, deci putem sa renuntam la a cauta acea valoare in tot subarborele. In felul acesta, se poate intampla ca bucati mari din heap sa nu mai fie explorate inutil. Pe cazul cel mai defavorabil, insa, parcurgerea intregului heap este necesara. Lasam scrierea unei proceduri de cautare pe seama cititorului.\r\n\r\nh2(#stl). STL\r\n\r\n*TODO*: HEAP-uri implementate de mana VS priority_queue<> VS set<>\r\n\r\nDesi nu sunt greu de implementat, avem vesti bune pentru programatorii in C++. In STL, cozile de prioritate (adica max-heap-urile) sunt deja implementate. Totusi, mentionam ca priority_queue nu este in standard-ul STL, aceasta inseamnand ca nu vor fi gasite neaparat in toate implementarile STL. Desi asta reprezinta un risc (e posibil sa nu gasitit priority_queue pe calculatoarele de la concurs) acesta esta minin.\r\n\r\nO alternativa la priority_queue-uri sunt set-urile si multiset-urile din STL. Acestea au doua avantaje: sunt in standard STL (deci nu riscati nimic) si pot efectua si cautari in O(logN) fiindca sunt implementate ca \'arbori binari echilibrati\':arbori-binari-echilibrati. Totusi avantajele vin cu un cost: set-urile si multiset-urile pot fi mai incete decat cozile de prioritate.\r\n\r\nDaca nu sunteti familiari cu aceste structuri de date, va recomandam sa cititi paginile lor de documentatie: \'priority_queue<>\':http://www.sgi.com/tech/stl/priority_queue.html, \'set<>\':http://www.sgi.com/tech/stl/set.html si \'multiset\':http://www.sgi.com/tech/stl/multiset.html. Daca nu intelegeti chiar tot de la inceput (pentru ca nu stiti clase si template-uri in C++), uitati-va pe exemple si pe lista de functii membre si invatati cum se folosesc.\r\n\r\nIn continuare vom ilustra cum putem implementa operatiile de extragere a maximului, extragere a minimului, inserare, stergere si cautare folosind un $multi_set$. Vom folosi un multiset pentru ca toate copiile unui numar vor fi pastrate daca el va fi inserat de mai multe ori (spre deosebire de set, care il va pastra o singura data).\r\n\r\nh2(#aplicatii). Aplicatii\r\n\r\n* \'Dijkstra cu heap-uri\':http://infoarena.ro/problema/dijkstra\r\n_(\'codul sursa:\':http://infoarena.ro/job_detail/144766?action=view-source)_\r\n* \'Magnetic storms\':http://acm.timus.ru/problem.aspx?space=1&num=1126 - timus, 1126\r\n* Sea (Berinde), Baraj ONI 2004 TODO: Pus pe infoareana, fortat o structura de date care intretine dinamic evenimentele (de exemplu heap) prin micsorarea limitei de memorie.\r\n* Pe astea le-am rezolvat cu set-uri, nu stiu daca merge si cu heap-uri ca au nevoie si de stergere in log(N) -- smenul de la Dijkstra?:\r\n** \'Manager\':http://acm.tju.edu.cn/toj/showp1675.html - tju, 1675\r\n** \'Supermarket\':http://acm.tju.edu.cn/toj/showp1681.html \r\n\r\nh2. TODO: Prezentam sau nu problema de mai jos?\r\n\r\nPRO:\r\n\r\n* E interesanta si este o aplicatie a heapurilor\r\n\r\nCONTRA:\r\n\r\n* Este o aplicatie teoretica/fortata\r\n* Mareste prea mult articolul\r\n\r\n*Feedback (Stefan):* As sugera transformarea problemei intr-una mai utila si mai putin fortata: Sa se interclaseze in mod eficient $K$ vectori sortati.\r\n\r\n*Feedback (Cosmin):* Merge problema, zic ca trebuie bagata, eventual daca e prea artificiala o punem ultima. E misto problema lui Stefan, alta problema ar fi sa se determine cele mai mici k elemente dintr-un sir de lungime n daca ai memorie << O(n). In cod ar trebui schimbate siftarile cu 1 cu inmultiri si impartiri cu 2, si pare mai putin exoteric codul. Alta chestie, am putea numi articolul cozi de prioritati si sa mentionam heapuri interclasabile, sau cozi de prioritati cand costurile sunt mici. Am putea sa bagam observatiile cu celelalte cozi de prioritati ca si in Cormen intr-o sectiune la sfarsitul articolului cu extinderi.\r\n\r\nExemple vreicat mai multe sa dai,pt calumea crede ca heapurile folosesc numai la heap sort si e bine sa schimbam ideea asta. Parerea mea e ca orice concept nou trebuie explicat cu 3 exemple care nu sunt inrudite ca sa il intelegi k lumea.\r\n\r\nDaca articolul e prea lung ar fimisto sa avem ceva butoane care expandeaza bucati din articol, sau celputin un cuprins la inceput, daca te intereseaza implementarea sau aplicatiile sa poti sari rapid la ce te intereseaza.\r\n\r\nh2. Problema\r\n\r\nSperand ca am reusit sa explicam modul de functionare al unui heap, . \r\n\r\nUn vector se numeste $k-sortat$ daca orice element al sau se gaseste la o distanta cel mult egala cu $k$ de locul care i s-ar cuveni in vectorul sortat. Iata un exemplu de vector 2-sortat cu 5 elemente:\r\n\r\n$V=(6 2 7 4 10)$\r\n$V{~sortat~} =(2 4 6 7 10)$\r\n\r\nSe observa ca elementele 4 si 6 se afla la doua pozitii distanta de locul lor in vectorul sortat, elementele 2 si 7 se afla la o pozitie distanta, iar elementul 10 se afla chiar pe pozitia corecta. Distanta maxima este 2, deci vectorul V este 2-sortat. Desigur, un vector $k-sortat$ este in acelasi timp si un vector $(k+1)-sortat$, si un vector $(k+2)-sortat$ etc., deoarece, daca orice element se afla la o distanta mai mica sau egala cu $k$ de locul potrivit, cu atat mai mult el se va afla la o distanta mai mica sau egala cu $k+1$, $k+2$ etc. In continuare, cand vom spune ca vectorul este $k-sortat$, ne vom referi la cel mai mic $k$ pentru care afirmatia este adevarata. Prin urmare, un vector cu $N$ elemente poate fi $N-1$ sortat in cazul cel mai defavorabil. Mai facem precizarea ca un vector 0-sortat este un vector sortat in intelesul obisnuit al cuvantului, deoarece fiecare element se afla la o distanta egala cu 0 de locul sau.\r\n\r\nProblema este: dandu-se un vector $k-sortat$ cu $N$ elemente numere intregi, se cere sa-l sortam intr-un timp mai bun decat $O(N*log N)$.\r\n\r\nDate sunt citite din fisierul $input.txt$ care contine pe prima linie valorile lui $N$ si $K$ ({$2 &le; K < N &le; 10000$}), despartite printr-un spatiu. Pe a doua linie se dau cele $N$ elemente ale vectorului, despartite prin spatii. In fisierul $output.txt$ se vor tipari pe o singura linie elementele vectorului sortat, separate prin spatii.\r\n\r\nIata un exemplu:\r\n\r\ntable(example). |_. input.txt |_. output.txt |\r\n| 5 \r\n6 2 7 4 10| 2 4 6 7 10 | \r\n\r\nNe propunem obtinerea unei complexitati $O(N*logK)$. Evident, putem sorta vectorul fara sa tinem cont de propietatile sale dar am obtine o complexitate $O(N*logN)$. Diferentierea intre aceasta solutie si cea prezentata in continuare este probabil imposibil de facut in regim de concurs. Prezentam totusi solutia $O(N*logK)$ de amorul artei si pentru a ilustra conceptual heapurile :)\r\n\r\nh2. Rezolvare\r\n\r\nChiar faptul ca ni se cere o complexitate de ordinul $O(N*log k)$ ne sugereaza construirea unui heap cu $O(k)$ noduri. Sa ne inchipuim ca am construi un heap $H$ format din primele $k+1$ elemente ale vectorului $V$.  Diferenta fata de ce am spus pana acum este ca orice nod va trebui sa fie mai mic decat fiii sai. Acest heap va servi deci la extragerea minimului.\r\n\r\nDeoarece vectorul este $k-sortat$, rezulta ca elementul care s-ar gasi pe prima pozitie in vectorul sortat se poate afla in vectorul nesortat pe oricare din pozitiile $1$, $2$, ..., $k+1$. El se afla asadar in heap-ul $H$; in plus, fiind cel mai mic, stim exact de unde sa-l luam: din varful heap-ului. Deci vom elimina acest element din heap si il vom trece \"undeva\" separat (vom vedea mai tarziu unde). In loc sa punem in locul lui ultimul element din heap, insa, vom aduce al $k+2$-lea element din vector si il vom lasa sa se cearna. Acum putem fi siguri ca al doilea element ca valoare in vectorul sortat se afla in heap, deoarece el se putea afla in vectorul nesortat undeva pe pozitiile $1$, $2$, ..., $k+2$, toate aceste elemente figurand in heap (bineinteles ca minimul deja extras se exclude din discutie). Putem sa mergem la sigur, luand al doilea minim direct din varful heap-ului. \r\n\r\nVom proceda la fel pana cand toate elementele vectorului vor fi adaugate in heap. Din acel moment vom continua sa extragem din varful heap-ului, revenind la vechea modalitate de a umple locul ramas gol cu ultimul nod disponibil. Continuam si cu acest procedeu pana cand heap-ul se goleste. In acest moment am obtinut vectorul sortat \"undeva\" in memorie. De fapt, daca ne gandim putin, vom constata ca, odata ce primele $k+1$ elemente din vector au fost trecute in heap, ordinea lor in vectorul $V$ nu mai conteaza, ele putand servi chiar la stocarea minimelor gasite pe parcurs. Pe masura ce aceste locuri se vor umple, altele noi se vor crea prin trecerea altor elemente in heap. Iata deci cum nici acest algoritm nu necesita memorie suplimentara.\r\n',15,'public',NULL,NULL),('heapuri','Heap-uri','2008-01-18 16:31:03','2008-12-26 19:31:05','h1. Heap-uri\r\n\r\n== include(page=\"template/implica-te/scrie-articole-2-autori\" user_id1=\"Cyber\" user_id2=\"silviug\") ==\r\n\r\n(Categoria _Structuri de date_, Autor _Catalin Francu_, Versiunea originala preluata din cartea _\"Psihologia concursurilor de informatica\"_)\r\n\r\n(toc){width: 30em}*{text-align:center;} *Continut*\r\n* \'Definirea notiunii de _heap_\':heapuri#definirea\r\n* \'Structura de heap si metode ajutatoare\':heapuri#structura\r\n* \'Cautarea maximului\':heapuri#cautarea_maximului\r\n* \'Crearea unei structuri de heap dintr-un vector oarecare\':heapuri#build_heap\r\n* \'Eliminarea unui element stiind pozitia lui in heap\':heapuri#cut\r\n* \'Inserarea unui element\':heapuri#insert\r\n* \'Sortarea unui vector (heapsort)\':heapuri#heap_sort\r\n* \'Cautarea unui element\':heapuri#find\r\n* \'STL\':heapuri#stl\r\n\r\n\r\nIn acest articol prezentam structura de date numita heap, cum poate fi aceasta implementata precum si alternative STL. Desi este putin probabil sa ajungeti sa implementati heap-urile de la \"zero\" daca stiti STL, consideram ca prezentarea acestora nu este de prisos. Aici atingem problema mai generala a \"de ce trebuie sa inteleg X (poate fi vorba de un algoritm, o structura de date, s.a.m.d.) daca il am deja implementat?\" Iata cateva motive:\r\n\r\n* va antreneaza mintea\r\n* va veti putea descurca in situatii in care aveti nevoie de o structura de date similara dar nu la fel\r\n* veti fi utilizatori informati ai bibliotecii STL\r\n* veti intelege cand este bine sa folosoti o structura de date si cand nu\r\n* veti avea avantajul de a sti precis de ce operatiile au anumite complexitati\r\n\r\nAcum ca avem o motivatie, sa studiem impreuna heap-urile.\r\n\r\nh2(#definirea). Definirea notiunii de _heap_\r\n\r\nUn heap (engl. gramada) este un vector care poate fi privit si ca un arbore binar, asa cum se vede in figura de mai jos:\r\n\r\n!heapuri?heap.JPG!\r\n\r\nLanga fiecare nod din arbore se afla cate un numar, reprezentand pozitia in vector pe care ar avea-o nodul respectiv. Pentru cazul considerat, vectorul echivalent ar fi  {$H = (12 10 11 10 7 9 3 2 8 1 4 3)$}.\r\n\r\nSe observa ca nodurile sunt parcurse de la stanga la dreapta si de sus in jos. O proprietate necesara pentru ca un arbore binar sa se poata numi heap este ca toate nivelele sa fie complete, cu exceptia ultimului, care se completeaza incepand de la stanga si continuand pana la un punct. De aici deducem ca inaltimea unui heap cu $N$ noduri este <tex> h=[\\log_2 N] </tex> (reamintim ca inaltimea unui arbore este adancimea maxima a unui nod, considerand radacina drept nodul de adancime 0). Reciproc, numarul de noduri ale unui heap de inaltime $h$ este <tex> N\\in [2^h, 2^{h+1}-1]</tex>.\r\n\r\nTot din aceasta organizare mai putem deduce ca tatal unui nod $k > 1$ este nodul $[k/2]$, iar fiii nodului k sunt nodurile $2k$ si $2k+1$. Daca $2k = N$, atunci nodul $2k+1$ nu exista, iar nodul $k$ are un singur fiu; daca $2k > N$, atunci nodul $k$ este frunza si nu are nici un fiu. Exemple: tatal nodului 5 este nodul 2, iar fiii sai sunt nodurile 10 si 11. Tatal nodului 6 este nodul 3, iar unicul sau fiu este nodul 12. Tatal nodului 9 este nodul 4, iar fii nu are, fiind frunza in heap.\r\n\r\nDar cea mai importanta proprietate a heap-ului, cea care il face util in operatiile de aflarea a maximului, este aceea ca valoarea oricarui nod este mai mare sau egala cu valoarea oricarui fiu al sau. Dupa cum se vede mai sus, nodul 2 are valoarea 10, iar fiii sai - nodurile 4 si 5 - au valorile 10 si respectiv 7. Intrucat operatorul &ge; este tranzitiv, putem trage concluzia ca un nod este mai mare sau egal decat oricare din nepotii sai si, generalizand, va rezulta ca orice nod este mai mare sau egal decat toate nodurile din subarborele a carui radacina este el.\r\n\r\nAceasta afirmatie nu decide in nici un fel intre valorile a doua noduri dispuse astfel incat nici unul nu este descendent al celuilalt. Cu alte cuvinte, nu inseamna ca orice nod de pe un nivel mic are valoare mai mare decat nodurile mai apropiate de frunze. Este cazul nodului 7, care are valoarea 3 si este mai mic decat nodul 9 de valoare 8, care este totusi asezat ma jos in heap. In orice caz, o prima concluzie care rezulta din aceasta proprietate este ca radacina are cea mai mare valoare din tot heap-ul.\r\n\r\nStructura de heap permite efectuarea multor operatii intr-un timp foarte bun:\r\n\r\n* Cautarea maximului in $O(1)$\r\n* Crearea unei structuri de heap dintr-un vector oarecare in $O(N)$\r\n* Eliminarea unui element in $O(log N)$\r\n* Inserarea unui element in $O(log N)$\r\n* Sortarea elementelor din heap in $O(N log N)$\r\n\r\nMentionam ca operatia de cautarea a unui element are complexitatea $O(N)$ dar, de obicei, heap-ul nu este folosit cand acest tip de operatii este frecvent.\r\n\r\nDesigur, toate aceste operatii se fac mentinand permanent structura de heap a arborelui, adica respectand modul de repartizare a nodurilor pe nivele si plasarea mai sus a elementelor de valoare mai mare. Este de la sine inteles ca datele nu se vor reprezenta in memorie in forma arborescenta, ci in cea vectoriala.\r\n\r\nPrecizam de asemenea ca heap-ul poate fi organizat si pe baza operatorului de $&le;$. In acest caz, in varful heap-ului vom avea minimul dintre elementele pastrate in heap. In functie de operatorul folosit, putem numi structura de date max-heap sau min-heap. In continuare vom prezenta operatiile intr-un max-heap, adaptarea lor pentru min-heap-uri fiind usoara.\r\n\r\nh2(#structura). Structura de heap si metode ajutatoare\r\n\r\nIn blocul de cod de mai jos prezentam cum se defineste un heap ca vector si cateva metode ajutatoare:\r\n\r\n==code(c) |\r\nconst int MAX_HEAP_SIZE = 16 * 1024;\r\ntypedef int Heap[MAX_HEAP_SIZE];\r\n\r\ninline int father(int nod) {\r\n    return nod / 2;\r\n}\r\n\r\ninline int left_son(int nod) {\r\n    return nod * 2;\r\n}\r\n\r\ninline int right_son(int nod) {\r\n    return nod * 2 + 1;\r\n}\r\n==\r\n\r\nh2(#cautarea_maximului). Cautarea maximului\r\n\r\nPractic operatia aceasta nu are de facut decat sa intoarca valoarea primului element din vector:\r\n==code(c) |\r\ninline int max(Heap H) {\r\n    return H[1];\r\n}\r\n==\r\n\r\nh2(#build_heap). Crearea unei structuri de heap dintr-un vector oarecare\r\n\r\nPentru a discuta acest aspect, vom vorbi mai intai despre doua proceduri specifice heap-urilor, _sift_ (engl. a cerne) si _percolate_ (engl. a se infiltra). Sa presupunem ca un vector are o structura de heap, cu exceptia unui nod care este mai mic decat unul din fiii sai. Este cazul nodului 3 din figura de mai jos, care are o valoare mai mica decat fii sai (nodurile 6 si 7):\r\n\r\n!heapuri?create1.JPG!\r\n\r\nCe e de facut ? Desigur, nodul va trebui coborat in arbore, iar in locul lui vom aduce alt nod, mai exact unul dintre fiii sai. Intrebarea este: care din fiii sai ? Daca vom aduce nodul 7 in locul lui, acesta fiind mai mic decat nodul 6, anomalia se va pastra. Trebuie deci sa schimbam nodul 3 cu nodul 6:\r\n\r\n!heapuri?create2.JPG!\r\n\r\nProblema nu este insa rezolvata, deoarece noul nod 6, proaspat \"retrogradat\", este inca mai mic decat fiul sau, nodul 12. De data aceasta avem un singur fiu, deci o singura optiune: schimbam nodul 6 cu nodul 12 si obtinem o structura de heap corecta:\r\n\r\n!heapuri?create3.JPG!\r\n\r\nProcedura sift primeste ca parametri un heap $H$ cu $N$ noduri si un nod $K$ si presupune ca ambii subarbori ai nodului $K$ au structura de heap corecta. Misiunea ei este sa \"cearna\" nodul $K$ pana la locul potrivit, interschimband mereu nodul cu cel mai mare fiu al sau pana cand nodul nu mai are fii (ajunge pe ultimul nivel in arbore) sau pana cand fiii sai au valori mai mici decat el.\r\n\r\n==code(c) |\r\nvoid sift(Heap H, int N, int K) {\r\n    int son;\r\n    do {\r\n        son = 0;\r\n        // Alege un fiu mai mare ca tatal.\r\n        if (left_son(K) <= N) {\r\n            son = left_son(K);\r\n            if (right_son(K) <= N && H[right_son(K)] > H[left_son(K)]) {\r\n                son = right_son(K);\r\n            }\r\n            if (H[son] <= H[K]) {\r\n                son = 0;\r\n            }\r\n        }\r\n\r\n        if (son) {\r\n            swap(H[K], H[son]);  // Functie STL ce interschimba H[K] cu H[son].\r\n            K = son;\r\n        }\r\n    } while (son);\r\n}\r\n==\r\n\r\nProcedura percolate se va ocupa tocmai de fenomenul invers. Sa presupunem ca un heap are o \"defectiune\" in sensul ca observam un nod care are o valoare mai mare decat tatal sau. Atunci, va trebui sa interschimbam cele doua noduri. Este cazul nodului 10 din figura care urmeaza. Deoarece fiul care trebuie urcat este mai mare ca tatal, care la randul lui (presupunand ca restul heap-ului e corect) este mai mare decat celalalt fiu al sau, rezulta ca dupa interschimbare fiul devenit tata este mai mare decat ambii sai fii. Trebuie totusi sa privim din nou in sus si sa continuam sa urcam nodul in arbore fie pana ajungem la radacina, fie pana ii gasim un tata mai mare ca el. Iata ce se intampla cu nodul 10:\r\n\r\n!heapuri?create4.JPG!\r\n\r\n==code(c) |\r\nvoid percolate(Heap H, int N, int K) {\r\n    int key = H[K];\r\n\r\n    while ((K > 1) && (key > H[father(K)])) {\r\n        H[K] = H[father(K)];\r\n        K = father(K);\r\n    }\r\n\r\n    H[K] = key;\r\n}\r\n==\r\n\r\nAcum ne putem ocupa efectiv de construirea unui heap. Am spus ca procedura sift presupune ca ambii fii ai nodului pentru care este ea apelata au structura de heap. Aceasta inseamna ca putem apela procedura sift pentru orice nod imediat superior nivelului frunzelor, deoarece frunzele sunt arbori cu un singru nod, si deci heap-uri corecte. Apeland procedura sift pentru toate nodurile de deasupra frunzelor, vom obtine deja o structura mai organizata, asigurandu-ne ca pe ultimele doua nivele avem de-a face numai cu heap-uri. Apoi apelam aceeasi procedura pentru nodurile de pe al treilea nivel incepand de la frunze, apoi pentru cele de deasupra lor si asa mai departe pana ajungem la radacina. In acest moment, heap-ul este construit. Iata cum functioneaza algoritmul pentru un arbore total dezorganizat:\r\n\r\n!heapuri?create5.JPG!\r\n\r\nNivelul frunzelor este organizat\r\n\r\n!heapuri?create6.JPG!\r\n\r\nUltimele doua nivele sunt organizate\r\n\r\n!heapuri?create7.JPG!\r\n\r\nUltimele trei nivele sunt organizate\r\n\r\n!heapuri?create8.JPG!\r\n\r\nStructura de heap\r\n\r\n==code(c) |\r\nvoid build_heap(Heap H, int N) {\r\n    for (int i = N/2; i > 0; --i) {\r\n        sift(H, N, i);\r\n    }\r\n}\r\n==\r\n\r\nS-a apelat caderea incepand de la al $N/2$ - lea nod, deoarece s-a aratat ca acesta este ultimul nod care mai are fii, restul fiind frunze. Sa calculam acum complexitatea acestui algoritm. Un calcul sumar ar putea spune: exista $N$ noduri, fiecare din ele se \"cerne\" pe $O(log N)$ nivele, deci timpul de constructie a heap-ului este $O(N log N)$. Totusi nu este asa. Presupunem ca ultimul nivel al heap-ului este plin. In acest caz, jumatate din noduri vor fi frunze si nu se vor cerne deloc. Un sfert din noduri se vor afla deasupra lor si se vor cerne cel mult un nivel. O optime din noduri se vor putea cerne cel mult doua nivele, si asa mai departe, pana ajungem la radacina care se afla singura pe nivelul ei si va putea cadea maxim h nivele (reamintim <tex> h=[\\log_2 N] </tex>). Rezulta ca timpul total de calcul este dat de formula <tex> O({\\sum_{k=1}^{[\\log_2 N]} k} \\times \\frac{N}{2^{k+1}}) = O(N) </tex>. Demonstrarea egalitatii se poate face facand substitutia $N=2^h^$ si continuand calculele. Se va obtine tocmai complexitatea $O(2^h^)$. Lasam aceasta verificare ca tema cititorului.\r\n\r\nh2(#cut). Eliminarea unui element stiind pozitia lui in heap\r\n\r\nDaca eliminam un element din heap, trebuie numai sa refacem structura de heap. In locul nodului eliminat s-a creat un gol, pe care trebuie sa il umplem cu un alt nod. Care ar putea fi acela? Intrucat trebuie ca toate nivelele sa fie complet ocupate, cu exceptia ultimului, care poate fi gol numai in partea sa dreapta, rezulta ca singurul nod pe care il putem pune in locul celui eliminat este ultimul din heap. Odata ce l-am pus in gaura facuta, trebuie sa ne asiguram ca acest nod \"de umplutura\" nu strica proprietatea de heap. Deci vom verifica: daca nodul pus in loc este mai mare ca tatal sau, vom apela procedura percolate. Altfel vom apela procedura sift, in eventualitatea ca nodul este mai mic decat unul din fiii sai. Iata exemplul de mai jos:\r\n\r\n!heapuri?delete1.JPG!\r\n\r\nSa presupunem ca vrem sa eliminam nodul de valoare 9, aducand in locul lui nodul de valoare X. Insa X poate fi orice numar mai mic sau egal cu 18. Spre exemplu, X poate fi 16, caz in care va trebui urcat deasupra nodului de valoare 10, sau poate fi 1, caz in care va trebui cernut pana la nivelul frunzelor. Deoarece caderea si urcarea se pot face pe cel mult $(log N)$ nivele, rezulta o complexitate a procedeului de $O(log N)$.\r\n\r\n==code(c) |\r\nvoid cut(Heap H, int& N, int K) {\r\n    H[K] = H[N];\r\n    --N;\r\n\r\n    if ((K > 1) && (H[K] > H[father(K)])) {\r\n        percolate(H, N, K);\r\n    } else {\r\n        sift(H, N, K);\r\n    }\r\n}\r\n==\r\n\r\nh2(#insert). Inserarea unui element\r\n\r\nDaca vrem sa inseram un nou element in heap, lucrurile sunt mult mai simple. Nu avem decat sa-l asezam pe a $N+1$-a pozitie in vector si apoi sa-l \"promovam\" pana la locul potrivit. Din nou, urcarea se poate face pe maxim $(log N)$ nivele, de unde complexitatea logaritmica.\r\n\r\n==code(c) |\r\nvoid insert(Heap H, int N, int key) {\r\n    H[++N] = key;\r\n    percolate(H, N, N);\r\n}\r\n==\r\n\r\nh2(#heap_sort). Sortarea unui vector (heapsort)\r\n\r\nAcum, ca am stabilit toate aceste lucruri, ideea algoritmului de sortare vine de la sine. Incepem prin a construi un heap. Apoi extragem maximul (adica varful heap-ului) si refacem heap-ul. Cele doua operatii luate la un loc dureaza $O(1)+O(log N) = O(log N)$. Apoi extragem din nou maximul, (care va fi al doilea element ca marime din vector) si refacem din nou heap-ul. Din nou, complexitatea operatiei compuse este $O(log N)$. Daca facem acest lucru de $N$ ori, vom obtine vectorul sortat intr-o complexitate de $O(N log N)$.\r\n\r\nPartea cea mai frumoasa a acestui algoritm, la prima vedere destul de mare consumator de memorie, este ca el nu foloseste deloc memorie suplimentara. Iata explicatia: cand heap-ul are $N$ elemente, vom extrage maximul si il vom tine minte undeva in memorie. Pe de alta parte, in locul maximului (adica in radacina arborelui) trebuie adus ultimul element al vectorului, adica $H[N]$. Dupa aceasta operatie, heap-ul va avea $N-1$ noduri, al $N$-lea ramanand liber. Ce alt loc mai inspirat decat acest al $N$-lea nod ne-am putea dori pentru a stoca maximul? Practic, am interschimbat radacina, adica pe $H[1]$ cu $H[N]$. Acelasi lucru se face la fiecare pas, tinand cont de micsorarea permanenta a heap-ului.\r\n\r\n==code(c) |\r\nvoid heap_sort(Heap H, int N) {\r\n    build_heap(H, N);\r\n\r\n    // Sorteaza vectorul.\r\n    for (int i = N; i >= 2; --i) {\r\n        swap(H[1], H[i]);\r\n        sift(H, i, 1);\r\n    }\r\n}\r\n==\r\n\r\nh2(#find). Cautarea unui element\r\n\r\nAceasta operatie este singura care nu poate fi optimizata (in sensul reducerii complexitatii sub $O(N)$). Aceasta deoarece putem fi siguri ca un nod mai mic este descendentul unuia mai mare, dar nu putem sti daca se afla in subarborele stang sau drept; din aceasta cauza, nu putem face o cautare binara. Totusi, o oarecare imbunatatire se poate aduce fata de cautarea secventiala. Daca radacina unui subarbore este mai mica decat valoarea cautata de noi, cu atat mai mult putem fi convinsi ca descendentii radacinii vor fi si mai mici, deci putem sa renuntam la a cauta acea valoare in tot subarborele. In felul acesta, se poate intampla ca bucati mari din heap sa nu mai fie explorate inutil. Pe cazul cel mai defavorabil, insa, parcurgerea intregului heap este necesara. Lasam scrierea unei proceduri de cautare pe seama cititorului.\r\n\r\nh2(#stl). STL\r\n\r\n*TODO*: HEAP-uri implementate de mana VS priority_queue<> VS set<>\r\n\r\nDesi nu sunt greu de implementat, avem vesti bune pentru programatorii in C++. In STL, cozile de prioritate (adica max-heap-urile) sunt deja implementate. Totusi, mentionam ca priority_queue nu este in standard-ul STL, aceasta inseamnand ca nu vor fi gasite neaparat in toate implementarile STL. Desi asta reprezinta un risc (e posibil sa nu gasitit priority_queue pe calculatoarele de la concurs) acesta esta minin.\r\n\r\nO alternativa la priority_queue-uri sunt set-urile si multiset-urile din STL. Acestea au doua avantaje: sunt in standard STL (deci nu riscati nimic) si pot efectua si cautari in O(logN) fiindca sunt implementate ca \'arbori binari echilibrati\':arbori-binari-echilibrati. Totusi avantajele vin cu un cost: set-urile si multiset-urile pot fi mai incete decat cozile de prioritate.\r\n\r\nDaca nu sunteti familiari cu aceste structuri de date, va recomandam sa cititi paginile lor de documentatie: \'priority_queue<>\':http://www.sgi.com/tech/stl/priority_queue.html, \'set<>\':http://www.sgi.com/tech/stl/set.html si \'multiset\':http://www.sgi.com/tech/stl/multiset.html. Daca nu intelegeti chiar tot de la inceput (pentru ca nu stiti clase si template-uri in C++), uitati-va pe exemple si pe lista de functii membre si invatati cum se folosesc.\r\n\r\nIn continuare vom ilustra cum putem implementa operatiile de extragere a maximului, extragere a minimului, inserare, stergere si cautare folosind un $multi_set$. Vom folosi un multiset pentru ca toate copiile unui numar vor fi pastrate daca el va fi inserat de mai multe ori (spre deosebire de set, care il va pastra o singura data).\r\n\r\nh2(#aplicatii). Aplicatii\r\n\r\n* \'Dijkstra cu heap-uri\':http://infoarena.ro/problema/dijkstra\r\n_(\'codul sursa:\':http://infoarena.ro/job_detail/144766?action=view-source)_\r\n* \'Magnetic storms\':http://acm.timus.ru/problem.aspx?space=1&num=1126 - timus, 1126\r\n* Sea (Berinde), Baraj ONI 2004 TODO: Pus pe infoareana, fortat o structura de date care intretine dinamic evenimentele (de exemplu heap) prin micsorarea limitei de memorie.\r\n* Pe astea le-am rezolvat cu set-uri, nu stiu daca merge si cu heap-uri ca au nevoie si de stergere in log(N) -- smenul de la Dijkstra?:\r\n** \'Manager\':http://acm.tju.edu.cn/toj/showp1675.html - tju, 1675\r\n** \'Supermarket\':http://acm.tju.edu.cn/toj/showp1681.html \r\n\r\nh2. TODO: Prezentam sau nu problema de mai jos?\r\n\r\nPRO:\r\n\r\n* E interesanta si este o aplicatie a heapurilor\r\n\r\nCONTRA:\r\n\r\n* Este o aplicatie teoretica/fortata\r\n* Mareste prea mult articolul\r\n\r\n*Feedback (Stefan):* As sugera transformarea problemei intr-una mai utila si mai putin fortata: Sa se interclaseze in mod eficient $K$ vectori sortati.\r\n\r\n*Feedback (Cosmin):* Merge problema, zic ca trebuie bagata, eventual daca e prea artificiala o punem ultima. E misto problema lui Stefan, alta problema ar fi sa se determine cele mai mici k elemente dintr-un sir de lungime n daca ai memorie << O(n). In cod ar trebui schimbate siftarile cu 1 cu inmultiri si impartiri cu 2, si pare mai putin exoteric codul. Alta chestie, am putea numi articolul cozi de prioritati si sa mentionam heapuri interclasabile, sau cozi de prioritati cand costurile sunt mici. Am putea sa bagam observatiile cu celelalte cozi de prioritati ca si in Cormen intr-o sectiune la sfarsitul articolului cu extinderi.\r\n\r\nExemple vreicat mai multe sa dai,pt calumea crede ca heapurile folosesc numai la heap sort si e bine sa schimbam ideea asta. Parerea mea e ca orice concept nou trebuie explicat cu 3 exemple care nu sunt inrudite ca sa il intelegi k lumea.\r\n\r\nDaca articolul e prea lung ar fimisto sa avem ceva butoane care expandeaza bucati din articol, sau celputin un cuprins la inceput, daca te intereseaza implementarea sau aplicatiile sa poti sari rapid la ce te intereseaza.\r\n\r\nh2. Problema\r\n\r\nSperand ca am reusit sa explicam modul de functionare al unui heap, . \r\n\r\nUn vector se numeste $k-sortat$ daca orice element al sau se gaseste la o distanta cel mult egala cu $k$ de locul care i s-ar cuveni in vectorul sortat. Iata un exemplu de vector 2-sortat cu 5 elemente:\r\n\r\n$V=(6 2 7 4 10)$\r\n$V{~sortat~} =(2 4 6 7 10)$\r\n\r\nSe observa ca elementele 4 si 6 se afla la doua pozitii distanta de locul lor in vectorul sortat, elementele 2 si 7 se afla la o pozitie distanta, iar elementul 10 se afla chiar pe pozitia corecta. Distanta maxima este 2, deci vectorul V este 2-sortat. Desigur, un vector $k-sortat$ este in acelasi timp si un vector $(k+1)-sortat$, si un vector $(k+2)-sortat$ etc., deoarece, daca orice element se afla la o distanta mai mica sau egala cu $k$ de locul potrivit, cu atat mai mult el se va afla la o distanta mai mica sau egala cu $k+1$, $k+2$ etc. In continuare, cand vom spune ca vectorul este $k-sortat$, ne vom referi la cel mai mic $k$ pentru care afirmatia este adevarata. Prin urmare, un vector cu $N$ elemente poate fi $N-1$ sortat in cazul cel mai defavorabil. Mai facem precizarea ca un vector 0-sortat este un vector sortat in intelesul obisnuit al cuvantului, deoarece fiecare element se afla la o distanta egala cu 0 de locul sau.\r\n\r\nProblema este: dandu-se un vector $k-sortat$ cu $N$ elemente numere intregi, se cere sa-l sortam intr-un timp mai bun decat $O(N*log N)$.\r\n\r\nDate sunt citite din fisierul $input.txt$ care contine pe prima linie valorile lui $N$ si $K$ ({$2 &le; K < N &le; 10000$}), despartite printr-un spatiu. Pe a doua linie se dau cele $N$ elemente ale vectorului, despartite prin spatii. In fisierul $output.txt$ se vor tipari pe o singura linie elementele vectorului sortat, separate prin spatii.\r\n\r\nIata un exemplu:\r\n\r\ntable(example). |_. input.txt |_. output.txt |\r\n| 5 \r\n6 2 7 4 10| 2 4 6 7 10 | \r\n\r\nNe propunem obtinerea unei complexitati $O(N*logK)$. Evident, putem sorta vectorul fara sa tinem cont de propietatile sale dar am obtine o complexitate $O(N*logN)$. Diferentierea intre aceasta solutie si cea prezentata in continuare este probabil imposibil de facut in regim de concurs. Prezentam totusi solutia $O(N*logK)$ de amorul artei si pentru a ilustra conceptual heapurile :)\r\n\r\nh2. Rezolvare\r\n\r\nChiar faptul ca ni se cere o complexitate de ordinul $O(N*log k)$ ne sugereaza construirea unui heap cu $O(k)$ noduri. Sa ne inchipuim ca am construi un heap $H$ format din primele $k+1$ elemente ale vectorului $V$.  Diferenta fata de ce am spus pana acum este ca orice nod va trebui sa fie mai mic decat fiii sai. Acest heap va servi deci la extragerea minimului.\r\n\r\nDeoarece vectorul este $k-sortat$, rezulta ca elementul care s-ar gasi pe prima pozitie in vectorul sortat se poate afla in vectorul nesortat pe oricare din pozitiile $1$, $2$, ..., $k+1$. El se afla asadar in heap-ul $H$; in plus, fiind cel mai mic, stim exact de unde sa-l luam: din varful heap-ului. Deci vom elimina acest element din heap si il vom trece \"undeva\" separat (vom vedea mai tarziu unde). In loc sa punem in locul lui ultimul element din heap, insa, vom aduce al $k+2$-lea element din vector si il vom lasa sa se cearna. Acum putem fi siguri ca al doilea element ca valoare in vectorul sortat se afla in heap, deoarece el se putea afla in vectorul nesortat undeva pe pozitiile $1$, $2$, ..., $k+2$, toate aceste elemente figurand in heap (bineinteles ca minimul deja extras se exclude din discutie). Putem sa mergem la sigur, luand al doilea minim direct din varful heap-ului. \r\n\r\nVom proceda la fel pana cand toate elementele vectorului vor fi adaugate in heap. Din acel moment vom continua sa extragem din varful heap-ului, revenind la vechea modalitate de a umple locul ramas gol cu ultimul nod disponibil. Continuam si cu acest procedeu pana cand heap-ul se goleste. In acest moment am obtinut vectorul sortat \"undeva\" in memorie. De fapt, daca ne gandim putin, vom constata ca, odata ce primele $k+1$ elemente din vector au fost trecute in heap, ordinea lor in vectorul $V$ nu mai conteaza, ele putand servi chiar la stocarea minimelor gasite pe parcurs. Pe masura ce aceste locuri se vor umple, altele noi se vor crea prin trecerea altor elemente in heap. Iata deci cum nici acest algoritm nu necesita memorie suplimentara.\r\n',15,'public',NULL,NULL),('planificare','Planificare infoarena','2007-02-16 17:54:49','2008-11-24 15:04:26','h1. Planificare infoarena\r\n\r\n==include(page=\"planificare/sidebar\")==\r\n\r\nAici discutam despre planurile si proiectele infoarena (deadlines, echipe, bugete etc.). Majoritatea acestor pagini sunt publice si vizibile pentru toti utilizatorii. Este bine sa lucram cat mai transparent pentru a \'atrage si alti oameni\':implica-te. Este inevitabil sa exista si niste informatii confidentiale (surprise, sau enunturi de probleme), pentru care putem face si \'pagini private\':documentatie/administrare.\r\n\r\nToate subpaginile acestei sectiuni vor avea titlul de forma: planificare/sedinte, planificare/sponsori etc. \r\n\r\nh2. Sedinte\r\n\r\nDin cand in cand facem sedinte ale \'asociatiei\':asociatia-infoarena unde discutam live diverse lucruri. Aici avem note de la niste sedinte trecute.\r\n\r\nEste ok sa modificam pagini de sedinte cu update-uri asupra task-urilor.\r\n\r\n* \'*2008-11-25*\':planificare/sedinta-20081125\r\n* \'2008-11-07\':planificare/sedinta-20081107\r\n* \'2008-10-21\':planificare/sedinta-20081021\r\n* \'2008-10-10\':planificare/sedinta-20081010\r\n* \'2008-04-11\':planificare/sedinta-20080411\r\n* \'2008-03-14\':planificare/sedinta-20080314\r\n* \'2008-03-03\':planificare/sedinta-20080303\r\n* \'2008-02-18\':planificare/sedinta-20080218\r\n* \'2008-02-01\':planificare/sedinta-20080201\r\n* \'2008-01-18\':planificare/sedinta-20080118\r\n* \'2007-12-18\':planificare/sedinta-20071218\r\n* \'2007-11-28\':planificare/sedinta-20071128\r\n* \'2007-11-07\':planificare/sedinta-20071107\r\n* \'2007-10-27\':planificare/sedinta-20071027\r\n* \'2007-10-24\':planificare/sedinta-20071024\r\n* \'2007-06-15\':planificare/sedinta_20070615\r\n* \'2007-05-07\':planificare/sedinta_20070507\r\n* \'2007-04-24\':planificare/sedinta_20070424\r\n* \'2007-03-03\':planificare/sedinta_20070303\r\n* \'2007-02-15\':planificare/sedinta_20070215\r\n* \'2007-01-04\':planificare/sedinta_20070104\r\n* \'2006-12-14\':planificare/sedinta_20061214\r\n* \'2006-11-21\':planificare/sedinta_20061121\r\n* \'2006-11-01\':planificare/sedinta-20061101\r\n\r\nh2. Coding Camps\r\n\r\n* \'*Coding Camp Alcatraz*\':planificare/camp-alcatraz\r\n* \'Coding Camp Karate-Kids\':planificare/karate-kids\r\n* \'Coding Camp Noname\':planificare/camp-noname\r\n* \'Coding Camp Chuckie\':planificare/camp-chuckie\r\n\r\nh2. Proiecte trecute\r\n\r\n* \'Asociatia infoarena, infiintare\':planificare/asociatia-infoarena\r\n',1,'public',NULL,NULL),('planificare/sedinta-20090112','Sedinta 2009-01-12','2009-01-05 15:03:20','2009-01-05 15:03:20','h1. Sedinta 2009-01-12\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *luni, 12 ianuarie* la ora *19:00* la \'*Retro Cafe*\':http://metropotam.ro/Unde-iesim/2008/07/art2701725520-Millennium-Bank-recomanda-Retro-Cafe/\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioare\':planificare/sedinta-20081125\r\n* Algoritmiada (sponsorizari)\r\n* OKR-uri (Q4 2008 si Q1 2009)\r\n* Coding camp\r\n* \'IAP 11\':propuneri/11-rating\r\n* \'IAP 10\':propuneri/10-virtual-contest\r\n* Stelele?\r\n* ONIbyNET\r\n\r\nh2(#rezolutii). Rezolutii\r\n...\r\n\r\nh2. Notite\r\n\r\n...',1,'public',NULL,NULL),('planificare/sedinta-20090112','Sedinta 2009-01-12','2009-01-05 15:03:20','2009-01-05 15:03:42','h1. Sedinta 2009-01-12\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *luni, 12 ianuarie* la ora *19:00* la \'*Retro Cafe*\':http://metropotam.ro/Unde-iesim/2008/07/art2701725520-Millennium-Bank-recomanda-Retro-Cafe/\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioara\':planificare/sedinta-20081125\r\n* Algoritmiada (sponsorizari)\r\n* OKR-uri (Q4 2008 si Q1 2009)\r\n* Coding camp\r\n* \'IAP 11\':propuneri/11-rating\r\n* \'IAP 10\':propuneri/10-virtual-contest\r\n* Stelele?\r\n* ONIbyNET\r\n\r\nh2(#rezolutii). Rezolutii\r\n...\r\n\r\nh2. Notite\r\n\r\n...',1,'public',NULL,NULL),('planificare/sedinta-20090112','Sedinta 2009-01-12','2009-01-05 15:03:20','2009-01-05 15:52:58','h1. Sedinta 2009-01-12\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *luni, 12 ianuarie* la ora *?* la *?*\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== - pe seara as prefera\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioara\':planificare/sedinta-20081125\r\n* Algoritmiada (sponsorizari)\r\n* OKR-uri (Q4 2008 si Q1 2009)\r\n* Coding camp\r\n* \'IAP 11\':propuneri/11-rating\r\n* \'IAP 10\':propuneri/10-virtual-contest\r\n* Stelele?\r\n* ONIbyNET\r\n\r\nh2(#rezolutii). Rezolutii\r\n...\r\n\r\nh2. Notite\r\n\r\n...',1490,'public',NULL,NULL),('planificare/sedinta-20090112','Sedinta 2009-01-12','2009-01-05 15:03:20','2009-01-05 20:16:14','h1. Sedinta 2009-01-12\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *luni, 12 ianuarie* la ora *?* la *?*\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== - pe seara as prefera\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== - as prefera dupa 18:30\r\n* ==user(user=\"prostu\" type=\"tiny\")== - as prefera dupa 16:00\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioara\':planificare/sedinta-20081125\r\n* Algoritmiada (sponsorizari)\r\n* OKR-uri (Q4 2008 si Q1 2009)\r\n* Coding camp\r\n* \'IAP 11\':propuneri/11-rating\r\n* \'IAP 10\':propuneri/10-virtual-contest\r\n* Stelele?\r\n** Go international: desi la stadiul de idee, Ali se gandeste sa invite bulgarii cei mai tari la stele; ce-ar presupune asta din partea noastra?\r\n** Va avea loc in vacanta inter-semestriala (perioada 31 ianuarie - 7 februarie)\r\n** Masuri de securitate, probleme cu adminii (Bogdan are parola pe live)\r\n* ONIbyNET\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n...\r\n\r\nh2. Notite\r\n\r\n...',2970,'public',NULL,NULL),('planificare/sedinta-20090112','Sedinta 2009-01-12','2009-01-05 15:03:20','2009-01-05 21:32:49','h1. Sedinta 2009-01-12\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *luni, 12 ianuarie* la ora *?* la *?*\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== - pe seara as prefera\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== - as prefera dupa 18:30\r\n* ==user(user=\"prostu\" type=\"tiny\")== - as prefera dupa 16:00\r\n* ==user(user=\"stef2n\" type=\"tiny\")== - prezent doar daca nu are loc in intervalul 18-20, din cauza unei lucrari\r\n* ==user(user=\"gcosmin\" type=\"tiny\")== - ar merge mai spre seara\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioara\':planificare/sedinta-20081125\r\n* Algoritmiada (sponsorizari)\r\n* OKR-uri (Q4 2008 si Q1 2009)\r\n* Coding camp\r\n* \'IAP 11\':propuneri/11-rating\r\n* \'IAP 10\':propuneri/10-virtual-contest\r\n* Stelele?\r\n** Go international: desi la stadiul de idee, Ali se gandeste sa invite bulgarii cei mai tari la stele; ce-ar presupune asta din partea noastra?\r\n** Va avea loc in vacanta inter-semestriala (perioada 31 ianuarie - 7 februarie)\r\n** Masuri de securitate, probleme cu adminii (Bogdan are parola pe live)\r\n* ONIbyNET\r\n* Fix it Week (experiment: declararea unei saptamani in care toata comunitatea trage tare la articole)\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n...\r\n\r\nh2. Notite\r\n\r\n...',2038,'public',NULL,NULL),('planificare/sedinta-20090112','Sedinta 2009-01-12','2009-01-05 15:03:20','2009-01-06 14:42:00','h1. Sedinta 2009-01-12\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *luni, 12 ianuarie* la ora *?* la *?*\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== - pe seara as prefera\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")== - mai spre 16:00 ar fi mai bine\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== - as prefera dupa 18:30\r\n* ==user(user=\"prostu\" type=\"tiny\")== - as prefera dupa 16:00\r\n* ==user(user=\"stef2n\" type=\"tiny\")== - prezent doar daca nu are loc in intervalul 18-20, din cauza unei lucrari\r\n* ==user(user=\"gcosmin\" type=\"tiny\")== - ar merge mai spre seara (dupa 6:30-7:00 asa)\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\n* Recapitulare \'sedinta anterioara\':planificare/sedinta-20081125\r\n* Algoritmiada (sponsorizari)\r\n* OKR-uri (Q4 2008 si Q1 2009)\r\n* Coding camp\r\n* \'IAP 11\':propuneri/11-rating\r\n* \'IAP 10\':propuneri/10-virtual-contest\r\n* Stelele? - _speaker:_ Silviu\r\n** Go international: desi la stadiul de idee, Ali se gandeste sa invite bulgarii cei mai tari la stele; ce-ar presupune asta din partea noastra?\r\n** Va avea loc in vacanta inter-semestriala (perioada 31 ianuarie - 7 februarie)\r\n** Masuri de securitate, probleme cu adminii (Bogdan are parola pe live)\r\n* ONIbyNET\r\n* Fix it week/camp - _speaker:_ Silviu\r\n** Scop: imbogatirea si imbunatatirea continutului site-ului, implicarea comunitatii in activitatile noastre, identificarea de noi colaboratori \"de baza\"\r\n** Fix it week: declararea unei saptamani in care toata comunitatea trage tare pentru content; cel mai simplu exemplu sunt articole de transcris; putem include si task-uri mai specializate ca finalizarea de probleme in arhiva [educationala]?, documentatie pentru diverse parti din site, etc.\r\n** Fix it camp: in paralel sau ca alternativa la fix it week; membrii infoarena se imbraca in salopete cu harlete in spate si se aduna intr-un loc prestabilit; chemam membrii comunitatii care vor sa se implice si \"plantam\" articole, documentatie, etc. o zi sau un week-end intr-o locatie precum ICHB.\r\n** In sedinta aceasta as dori sa primesc feedback si sugestii noi despre:\r\n*** Forma acestui eveniment: week or/and camp or/and ??\r\n*** Ce putem realiza cu un astfel de eveniment? (in materie de continut si implicare a comunitatii; care din scopuri sunt SF?)\r\n** Ma ofer (Silviu) eu sa organizez evenimentul in Q1-09, intr-o forma in care cadem cu totii de acord.\r\n* Misc\r\n** Silviu: De ce nu avem (inca) comentarii la articole? Mai sunt alte pagini la care am vrea comentarii (in stil de blog)?\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n...\r\n\r\nh2. Notite\r\n\r\n...',15,'public',NULL,NULL),('planificare/sedinta-20090112','Sedinta 2009-01-12','2009-01-05 15:03:20','2009-01-06 15:22:34','h1. Sedinta 2009-01-12\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *luni, 12 ianuarie* la ora *?* la *?*\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== - pe seara as prefera\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")== - mai spre 16:00 ar fi mai bine\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== - as prefera dupa 18:30\r\n* ==user(user=\"prostu\" type=\"tiny\")== - as prefera dupa 16:00\r\n* ==user(user=\"stef2n\" type=\"tiny\")== - prezent doar daca nu are loc in intervalul 18-20, din cauza unei lucrari\r\n* ==user(user=\"gcosmin\" type=\"tiny\")== - ar merge mai spre seara (dupa 6:30-7:00 asa)\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinta anterioara\':planificare/sedinta-20081125| ==user(user=\"domino\" type=\"tiny\")==|\r\n| Algoritmiada (sponsorizari)| ? |\r\n| OKR-uri (Q4 2008 si Q1 2009)|  ==user(user=\"domino\" type=\"tiny\")== |\r\n| Coding camp |  ==user(user=\"domino\" type=\"tiny\")== |\r\n| \'IAP 11\':propuneri/11-rating | ? |\r\n| \'IAP 10\':propuneri/10-virtual-contest | ? |\r\n| Stelele |  ==user(user=\"silviug\" type=\"tiny\")== |\r\n| ONIbyNET | ==user(user=\"domino\" type=\"tiny\")== |\r\n| Fix it week/camp | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| Misc | ==user(user=\"silviug\" type=\"tiny\")== |\r\n\r\nh3. Detalii\r\n\r\n* Stelele:\r\n** Go international: desi la stadiul de idee, Ali se gandeste sa invite bulgarii cei mai tari la stele; ce-ar presupune asta din partea noastra?\r\n** Va avea loc in vacanta inter-semestriala (perioada 31 ianuarie - 7 februarie)\r\n** Masuri de securitate, probleme cu adminii (Bogdan are parola pe live) \r\n* Fix it week/camp:\r\n** Scop: imbogatirea si imbunatatirea continutului site-ului, implicarea comunitatii in activitatile noastre, identificarea de noi colaboratori \"de baza\"\r\n** Fix it week: declararea unei saptamani in care toata comunitatea trage tare pentru content; cel mai simplu exemplu sunt articole de transcris; putem include si task-uri mai specializate ca finalizarea de probleme in arhiva [educationala]?, documentatie pentru diverse parti din site, etc.\r\n** Fix it camp: in paralel sau ca alternativa la fix it week; membrii infoarena se imbraca in salopete cu harlete in spate si se aduna intr-un loc prestabilit; chemam membrii comunitatii care vor sa se implice si \"plantam\" articole, documentatie, etc. o zi sau un week-end intr-o locatie precum ICHB. \r\n** In sedinta aceasta as dori sa primesc feedback si sugestii noi despre:\r\n*** Forma acestui eveniment: week or/and camp or/and ??\r\n*** Ce putem realiza cu un astfel de eveniment? (in materie de continut si implicare a comunitatii; care din scopuri sunt SF?)\r\n* Misc:\r\n** Ma ofer (Silviu) eu sa organizez evenimentul in Q1-09, intr-o forma in care cadem cu totii de acord. \r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n...\r\n\r\nh2. Notite\r\n\r\n...',1,'public',NULL,NULL),('heapuri','Heap-uri','2008-01-18 16:31:03','2008-12-29 19:05:13','h1. Heap-uri\r\n\r\n== include(page=\"template/implica-te/scrie-articole-2\" user_id1=\"Cyber\" user_id2=\"silviug\") ==\r\n\r\n(Categoria _Structuri de date_, Autor _Catalin Francu_, Versiunea originala preluata din cartea _\"Psihologia concursurilor de informatica\"_)\r\n\r\n(toc){width: 30em}*{text-align:center;} *Continut*\r\n* \'Definirea notiunii de _heap_\':heapuri#definire\r\n* \'Structura de heap si metode ajutatoare\':heapuri#structura\r\n* \'Cautarea maximului\':heapuri#cautarea-maximului\r\n* \'Crearea unei structuri de heap dintr-un vector oarecare\':heapuri#creare-heap\r\n* \'Eliminarea unui element, stiind pozitia lui in heap\':heapuri#stergere\r\n* \'Inserarea unui element\':heapuri#inserare\r\n* \'Sortarea unui vector (heapsort)\':heapuri#heapsort\r\n* \'Cautarea unui element\':heapuri#cautare\r\n* \'Alternative STL\':heapuri#stl\r\n* \'Aplicatii\':heapuri#aplicatii\r\n\r\nIn acest articol vom prezenta structura de date numita $heap$, cum poate fi aceasta implementata, precum si alternative STL. Desi este putin probabil sa ajungeti sa implementati heap-urile de la \"zero\" daca stiti STL, consideram ca prezentarea acestora nu este de prisos. Aici atingem problema mai generala \"de ce trebuie sa inteleg X (poate fi vorba de un algoritm, o structura de date, s.a.m.d.) daca il am deja implementat?\". Iata cateva motive:\r\n\r\n* va antreneaza mintea\r\n* va veti putea descurca in situatii in care aveti nevoie de o structura de date asemanatoare, dar nu la fel\r\n* veti fi utilizatori informati ai bibliotecii STL\r\n* veti intelege cand este bine sa folositi o structura de date si cand nu\r\n* veti avea avantajul de a sti precis de ce operatiile de baza au anumite complexitati\r\n\r\nAcum ca avem o motivatie, sa studiem impreuna heap-urile.\r\n\r\nh2(#definire). Definirea notiunii de _heap_\r\n\r\nUn heap ({_engl._} gramada) este un vector care poate fi privit si ca un arbore binar, asa cum se vede in figura de mai jos:\r\n\r\n!heapuri?heap.JPG!\r\n\r\nLanga fiecare nod din arbore se afla cate un numar, reprezentand pozitia in vector pe care ar avea-o nodul respectiv. Pentru cazul considerat, vectorul echivalent ar fi {$H = (12 10 11 10 7 9 3 2 8 1 4 3)$}.\r\n\r\nSe observa ca nodurile sunt parcurse de la stanga la dreapta si de sus in jos. O proprietate necesara pentru ca un arbore binar sa se poata numi $heap$ este ca toate nivelurile sa fie complete, cu exceptia ultimului, care se completeaza incepand de la stanga si continuand pana la un anume punct. De aici deducem ca inaltimea unui heap cu $N$ noduri este <tex> h=[\\log_2 N] </tex> (reamintim ca inaltimea unui arbore este adancimea maxima a unui nod, considerand radacina drept nodul de adancime $0$). Reciproc, numarul de noduri ale unui heap de inaltime $h$ este <tex> N\\in [2^h, 2^{h+1}-1]</tex>.\r\n\r\nTot din aceasta organizare mai putem deduce ca tatal unui nod $k > 1$ este nodul $[k/2]$, iar fiii nodului $k$ sunt nodurile $2k$ si $2k+1$. Daca $2k = N$, atunci nodul $2k+1$ nu exista, iar nodul $k$ are un singur fiu; daca $2k > N$, atunci nodul $k$ este frunza si nu are niciun fiu. Exemple: tatal nodului $5$ este nodul $2$, iar fiii sai sunt nodurile $10$ si $11$. Tatal nodului $6$ este nodul $3$, iar unicul sau fiu este nodul $12$. Tatal nodului $9$ este nodul $4$, iar fii nu are, fiind frunza in heap.\r\n\r\nDar cea mai importanta proprietate a heap-ului, cea care il face util in operatiile de aflarea a maximului, este aceea ca valoarea oricarui nod este mai mare sau egala cu valoarea oricarui fiu al sau. Dupa cum se vede mai sus, nodul $2$ are valoarea $10$, iar fiii sai - nodurile $4$ si $5$ - au valorile $10$ si respectiv $7$. Intrucat operatorul $&ge;$ este tranzitiv, putem trage concluzia ca un nod este mai mare sau egal decat oricare din nepotii sai si, generalizand, va rezulta ca orice nod este mai mare sau egal decat toate nodurile din subarborele a carui radacina este.\r\n\r\nAceasta afirmatie nu decide in niciun fel intre valorile a doua noduri dispuse astfel incat niciunul nu este descendent al celuilalt. Cu alte cuvinte, nu inseamna ca orice nod de pe un nivel mic are valoare mai mare decat nodurile mai apropiate de frunze. Este cazul nodului $7$, care are valoarea $3$ si este mai mic decat nodul $9$ de valoare $8$, nod asezat totusi mai jos in heap. In orice caz, o prima concluzie care rezulta din aceasta proprietate este ca radacina are cea mai mare valoare din tot heap-ul.\r\n\r\nStructura de heap permite efectuarea multor operatii intr-un timp foarte bun:\r\n\r\n* Cautarea maximului in $O(1)$\r\n* Crearea unei structuri de heap dintr-un vector oarecare in $O(N)$\r\n* Eliminarea unui element in $O(log N)$\r\n* Inserarea unui element in $O(log N)$\r\n* Sortarea elementelor din heap in $O(N log N)$\r\n\r\nMentionam ca operatia de cautare a unui element are complexitatea $O(N)$ dar, de obicei, heap-ul nu este folosit cand acest tip de operatii este frecvent.\r\n\r\nDesigur, toate aceste operatii se fac mentinand permanent structura de heap a arborelui, adica respectand modul de repartizare a nodurilor pe niveluri si plasarea mai sus a elementelor de valoare mai mare. Este de la sine inteles ca datele nu se vor reprezenta in memorie in forma arborescenta, ci in cea vectoriala.\r\n\r\nPrecizam de asemenea ca heap-ul poate fi organizat si pe baza operatorului de $&le;$. In acest caz, in varful heap-ului vom avea minimul dintre elementele pastrate in heap. In functie de operatorul folosit, putem numi structura de date $max-heap$ sau $min-heap$. In continuare vom prezenta operatiile intr-un max-heap, adaptarea lor pentru min-heap-uri fiind usoara.\r\n\r\nh2(#structura). Structura de heap si metode ajutatoare\r\n\r\nIn blocul de cod de mai jos prezentam cum se defineste un heap ca vector si cateva metode ajutatoare:\r\n\r\n==code(cpp) |\r\nconst int MAX_HEAP_SIZE = 16384;\r\ntypedef int Heap[MAX_HEAP_SIZE];\r\n\r\ninline int father(int nod) {\r\n    return nod / 2;\r\n}\r\n\r\ninline int left_son(int nod) {\r\n    return nod * 2;\r\n}\r\n\r\ninline int right_son(int nod) {\r\n    return nod * 2 + 1;\r\n}\r\n==\r\n\r\nh2(#cautarea-maximului). Cautarea maximului\r\n\r\nPractic, operatia aceasta nu are de facut decat sa intoarca valoarea primului element din vector:\r\n==code(cpp) |\r\ninline int max(Heap H) {\r\n    return H[1];\r\n}\r\n==\r\n\r\nh2(#creare-heap). Crearea unei structuri de heap dintr-un vector oarecare\r\n\r\nPentru a discuta acest aspect, vom vorbi mai intai despre doua proceduri specifice heap-urilor, $sift$ ({_engl._} a cerne) si $percolate$ ({_engl._} a se infiltra). Sa presupunem ca un vector are o structura de heap, cu exceptia unui nod care este mai mic decat unul din fiii sai. Este cazul nodului $3$ din figura de mai jos, care are o valoare mai mica decat fiii sai (nodurile $6$ si $7$):\r\n\r\n!heapuri?create1.JPG!\r\n\r\nCe e de facut? Desigur, nodul va trebui coborat in arbore, iar in locul lui vom aduce alt nod, mai exact unul dintre fiii sai. Intrebarea este: care din fiii sai? Daca vom aduce nodul $7$ in locul lui, acesta fiind mai mic decat nodul $6$, anomalia se va pastra. Trebuie deci sa schimbam nodul $3$ cu nodul $6$:\r\n\r\n!heapuri?create2.JPG!\r\n\r\nProblema nu este insa rezolvata, deoarece noul nod $6$, proaspat \"retrogradat\", este inca mai mic decat fiul sau, nodul $12$. De data aceasta avem un singur fiu, deci o singura optiune: schimbam nodul $6$ cu nodul $12$ si obtinem o structura de heap corecta:\r\n\r\n!heapuri?create3.JPG!\r\n\r\nProcedura $sift$ primeste ca parametri un heap $H$ cu $N$ noduri si un nod $K$ si presupune ca ambii subarbori ai nodului $K$ au structura de heap corecta. Misiunea ei este sa \"cearna\" nodul $K$ pana la locul potrivit, interschimband mereu nodul cu cel mai mare fiu al sau pana cand nodul nu mai are fii (ajunge pe ultimul nivel in arbore) sau pana cand fiii sai au valori mai mici decat el.\r\n\r\n==code(cpp) |\r\nvoid sift(Heap H, int N, int K) {\r\n    int son;\r\n    do {\r\n        son = 0;\r\n        // Alege un fiu mai mare ca tatal.\r\n        if (left_son(K) <= N) {\r\n            son = left_son(K);\r\n            if (right_son(K) <= N && H[right_son(K)] > H[left_son(K)]) {\r\n                son = right_son(K);\r\n            }\r\n            if (H[son] <= H[K]) {\r\n                son = 0;\r\n            }\r\n        }\r\n\r\n        if (son) {\r\n            swap(H[K], H[son]);  // Functie STL ce interschimba H[K] cu H[son].\r\n            K = son;\r\n        }\r\n    } while (son);\r\n}\r\n==\r\n\r\nProcedura $percolate$ se va ocupa tocmai de fenomenul invers. Sa presupunem ca un heap are o \"defectiune\" in sensul ca observam un nod care are o valoare mai mare decat tatal sau. Atunci, va trebui sa interschimbam cele doua noduri. Este cazul nodului $10$ din figura care urmeaza. Deoarece fiul care trebuie urcat este mai mare ca tatal, care la randul lui (presupunand ca restul heap-ului e corect) este mai mare decat celalalt fiu al sau, rezulta ca dupa interschimbare fiul devenit tata este mai mare decat ambii sai fii. Trebuie totusi sa privim din nou in sus si sa continuam sa urcam nodul in arbore fie pana ajungem la radacina, fie pana ii gasim un tata mai mare ca el. Iata ce se intampla cu nodul $10$:\r\n\r\n!heapuri?create4.JPG!\r\n\r\n==code(cpp) |\r\nvoid percolate(Heap H, int N, int K) {\r\n    int key = H[K];\r\n\r\n    while ((K > 1) && (key > H[father(K)])) {\r\n        H[K] = H[father(K)];\r\n        K = father(K);\r\n    }\r\n\r\n    H[K] = key;\r\n}\r\n==\r\n\r\nAcum ne putem ocupa efectiv de construirea unui heap. Am spus ca procedura $sift$ presupune ca ambii fii ai nodului pentru care este ea apelata au structura de heap. Aceasta inseamna ca putem apela procedura $sift$ pentru orice nod imediat superior nivelului frunzelor, deoarece frunzele sunt arbori cu un singur nod, si deci heap-uri corecte. Apeland procedura $sift$ pentru toate nodurile de deasupra frunzelor, vom obtine deja o structura mai organizata, asigurandu-ne ca pe ultimele doua niveluri avem de-a face numai cu heap-uri. Apoi apelam aceeasi procedura pentru nodurile de pe al treilea nivel incepand de la frunze, apoi pentru cele de deasupra lor si asa mai departe pana ajungem la radacina. In acest moment, heap-ul este construit. Iata cum functioneaza algoritmul pentru un arbore total dezorganizat:\r\n\r\n!heapuri?create5.JPG!\r\n\r\np{padding-left: 4em}. _Nivelul frunzelor este organizat_\r\n\r\n!heapuri?create6.JPG!\r\n\r\np{padding-left: 3em}. _Ultimele doua niveluri sunt organizate_\r\n\r\n!heapuri?create7.JPG!\r\n\r\np{padding-left: 3.5em}. _Ultimele trei niveluri sunt organizate_\r\n\r\n!heapuri?create8.JPG!\r\n\r\np{padding-left: 7em}. _Structura de heap_\r\n\r\n==code(cpp) |\r\nvoid build_heap(Heap H, int N) {\r\n    for (int i = N / 2; i > 0; --i) {\r\n        sift(H, N, i);\r\n    }\r\n}\r\n==\r\n\r\nS-a apelat caderea incepand de la al $N / 2$ - lea nod, deoarece acesta este ultimul nod care mai are fii, restul cu indici mai mari fiind frunze. Sa calculam acum complexitatea acestui algoritm. Un calcul sumar ar putea spune: exista $N$ noduri, fiecare din ele se \"cerne\" pe $O(log N)$ niveluri, deci timpul de constructie a heap-ului este $O(N log N)$. Totusi nu este asa. Presupunem ca ultimul nivel al heap-ului este plin. In acest caz, jumatate din noduri vor fi frunze si nu se vor cerne deloc. Un sfert din noduri se vor afla deasupra lor si se vor cerne cel mult un nivel. O optime din noduri se vor putea cerne cel mult doua niveluri, si asa mai departe, pana ajungem la radacina care se afla singura pe nivelul ei si va putea cadea maxim $h$ niveluri (reamintim ca <tex> h=[\\log_2 N] </tex>). Rezulta ca timpul total de calcul este dat de formula <tex>O(\\displaystyle {\\sum_{k=1}^{[\\log_2 N]} k} \\times \\frac{N}{2^{k+1}}) = O(N)</tex>. Demonstrarea egalitatii se poate face facand substitutia $N = 2^h^$ si continuand calculele. Se va obtine tocmai complexitatea $O(2^h^)$. Lasam aceasta verificare ca tema cititorului.\r\n\r\nh2(#stergere). Eliminarea unui element, stiind pozitia lui in heap\r\n\r\nDaca eliminam un element din heap, trebuie numai sa refacem structura de heap. In locul nodului eliminat s-a creat un gol, pe care trebuie sa il umplem cu un alt nod. Care ar putea fi acela? Intrucat trebuie ca toate nivelurile sa fie complet ocupate, cu exceptia ultimului, care poate fi gol numai in partea sa dreapta, rezulta ca singurul nod pe care il putem pune in locul celui eliminat este ultimul din heap. O data ce l-am pus in gaura facuta, trebuie sa ne asiguram ca acest nod \"de umplutura\" nu strica proprietatea de heap. Deci vom verifica: daca nodul pus in loc este mai mare ca tatal sau, vom apela procedura $percolate$. Altfel vom apela procedura $sift$, in eventualitatea ca nodul este mai mic decat unul din fiii sai. Iata exemplul de mai jos:\r\n\r\n!heapuri?delete1.JPG!\r\n\r\n\r\n\r\n\r\n\r\nSa presupunem ca vrem sa eliminam nodul de valoare $9$, aducand in locul lui nodul de valoare $X$. Insa $X$ poate fi orice numar mai mic sau egal cu $18$. Spre exemplu, $X$ poate fi $16$, caz in care va trebui urcat deasupra nodului de valoare $10$, sau poate fi $1$, caz in care va trebui cernut pana la nivelul frunzelor. Deoarece caderea si urcarea se pot face pe cel mult $[log N]$ niveluri, rezulta o complexitate a procedeului de $O(log N)$.\r\n\r\n==code(cpp) |\r\nvoid cut(Heap H, int& N, int K) {\r\n    H[K] = H[N];\r\n    --N;\r\n\r\n    if ((K > 1) && (H[K] > H[father(K)])) {\r\n        percolate(H, N, K);\r\n    } else {\r\n        sift(H, N, K);\r\n    }\r\n}\r\n==\r\n\r\nh2(#inserare). Inserarea unui element\r\n\r\nDaca vrem sa inseram un nou element in heap, lucrurile sunt mult mai simple. Nu avem decat sa-l asezam pe a $N + 1$ - a pozitie in vector si apoi sa-l \"promovam\" pana la locul potrivit. Din nou, urcarea se poate face pe maxim $[log N]$ niveluri, de unde complexitatea logaritmica.\r\n\r\n==code(cpp) |\r\nvoid insert(Heap H, int N, int key) {\r\n    H[++N] = key;\r\n    percolate(H, N, N);\r\n}\r\n==\r\n\r\nh2(#heapsort). Sortarea unui vector (heapsort)\r\n\r\nAcum ca am stabilit toate aceste lucruri, ideea algoritmului de sortare vine de la sine. Incepem prin a construi un heap. Apoi extragem maximul (adica varful heap-ului) si refacem heap-ul. Cele doua operatii luate la un loc dureaza $O(1) + O(log N) = O(log N)$. Apoi extragem din nou maximul (care va fi al doilea element ca marime din vector) si refacem din nou heap-ul. Din nou, complexitatea operatiei compuse este $O(log N)$. Daca facem acest lucru de $N$ ori, vom obtine vectorul sortat intr-o complexitate de $O(N log N)$.\r\n\r\nPartea cea mai frumoasa a acestui algoritm este ca el nu foloseste deloc memorie suplimentara. Iata explicatia: cand heap-ul are $N$ elemente, vom extrage maximul si il vom tine minte undeva in memorie. Pe de alta parte, in locul maximului (adica in radacina arborelui) trebuie adus ultimul element al vectorului, adica $H[N]$. Dupa aceasta operatie, heap-ul va avea $N - 1$ noduri, al $N$-lea ramanand liber. Ce alt loc mai inspirat decat acest al $N$-lea nod ne-am putea dori pentru a stoca maximul? Practic, am interschimbat radacina, adica pe $H[&#49;]$ cu $H[N]$. Acelasi lucru se face la fiecare pas, tinand cont de micsorarea permanenta a heap-ului.\r\n\r\n==code(cpp) |\r\nvoid heapsort(Heap H, int N) {\r\n    build_heap(H, N);\r\n\r\n    // Sorteaza vectorul.\r\n    for (int i = N; i >= 2; --i) {\r\n        swap(H[1], H[i]);\r\n        sift(H, i, 1);\r\n    }\r\n}\r\n==\r\n\r\nh2(#cautare). Cautarea unui element\r\n\r\nAceasta operatie este singura care nu poate fi optimizata (in sensul reducerii complexitatii sub $O(N)$). Aceasta deoarece putem fi siguri ca un nod mai mic este descendentul unuia mai mare, dar nu putem sti daca se afla in subarborele stang sau drept; din aceasta cauza, nu putem face o cautare binara. Totusi, o oarecare imbunatatire se poate aduce fata de cautarea secventiala. Daca radacina unui subarbore este mai mica decat valoarea cautata de noi, cu atat mai mult putem fi convinsi ca descendentii radacinii vor fi si ei mai mici, deci putem sa renuntam la a cauta acea valoare in tot subarborele. In felul acesta, se poate intampla ca bucati mari din heap sa nu mai fie explorate inutil. Pe cazul cel mai defavorabil, insa, parcurgerea intregului heap este necesara. Lasam scrierea unei proceduri de cautare pe seama cititorului.\r\n\r\nh2(#stl). Alternative STL\r\n\r\nDesi nu sunt greu de implementat, avem vesti bune pentru programatorii in C++: heap-urile sunt deja implementate in STL. Containerul se numeste \'$priority_queue$\':http://www.sgi.com/tech/stl/priority_queue.html si implementeaza toate operatiile prezentate, mai putin operatiile de cautare a unei valori si de stergere a unui nod. Aceste doua operatii sunt destul de atipice pentru o coada de prioritati si in general nu sunt asociate cu aceasta structura de date in cartile de algoritmi.\r\n\r\nTotusi, in unele aplicatii avem nevoie de o structura de date care suporta toate operatiile amintite in timp cel mult logaritmic (inclusiv stergerea si cautarea unei valori). Aceasta structura exista deja in STL: $set$-urile. Acestea sunt de fapt multimi mentinute ca arbori binari echilibrati. Singurele dezavantaje sunt ca de obicei merg mai incet decat cozile de prioritate si folosesc mai multa memorie.\r\n\r\nDaca nu sunteti familiari cu aceste structuri de date, va recomandam sa cititi paginile lor de documentatie: \'$priority_queue$\':http://www.sgi.com/tech/stl/priority_queue.html, \'$set$\':http://www.sgi.com/tech/stl/set.html si \'$multiset$\':http://www.sgi.com/tech/stl/multiset.html. Daca nu intelegeti totul de la inceput (pentru ca nu stiti clase si template-uri in C++), uitati-va pe exemple si pe lista de functii membre si invatati cum se folosesc.\r\n\r\nIn continuare vom ilustra cum putem implementa operatiile de extragere a maximului, extragere a minimului, inserare, stergere si cautare folosind un $multiset$. Vom folosi un $multiset$ pentru ca toate copiile unui numar vor fi pastrate daca el va fi inserat de mai multe ori (spre deosebire de $set$, care il va pastra o singura data). Va recomandam cu caldura sa copiati codul pe calculatorul vostru si sa experimentati cu el pentru a vedea ce afiseaza si a intelege ce se intampla.\r\n\r\n==code(cpp) |\r\n#include <set>\r\nusing namespace std;\r\n\r\nint main() {\r\n    multiset <int> my_set;\r\n    my_set.insert(1); // Insereaza o valoare.\r\n    my_set.insert(1);\r\n\r\n    if (my_set.find(1) != my_set.end()) { // Cauta o valoare.\r\n        printf(\"Am gasit 1 in set!\\n\");\r\n    } else {\r\n        printf(\"1 nu se afla set!\\n\");\r\n    }\r\n\r\n    // Sterge o valoare din set. Daca aceasta se afla de\r\n    // mai multe ori in set, este stearsa numai o copie.\r\n    my_set.erase(my_set.find(1));\r\n    printf(\"Exista %d elemente in set\\n\", my_set.size());\r\n\r\n    my_set.insert(1);\r\n    my_set.insert(1);\r\n\r\n    // Sterge o valoare din set. Daca aceasta se afla de\r\n    // mai multe ori in set, sunt sterse toate copiile.\r\n    my_set.erase(1);\r\n    printf(\"Exista %d elemente in set\\n\", my_set.size());\r\n\r\n    my_set.insert(1);\r\n    my_set.insert(-3);\r\n    my_set.insert(7);\r\n\r\n    // Valoarea minima.\r\n    multiset <int> :: iterator it = my_set.begin();\r\n    printf(\"Valoarea cea mai mica din set este %d\\n\", *it);\r\n\r\n    // Valoarea maxima.\r\n    it = my_set.end();\r\n    --it;\r\n    printf(\"Valoarea cea mai mare din set este %d\\n\", *it);\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#aplicatii). Aplicatii\r\n\r\n* \'Dijkstra cu heap-uri\':http://infoarena.ro/problema/dijkstra\r\n* \'Magnetic storms\':http://acm.timus.ru/problem.aspx?space=1&num=1126\r\n* \'Manager\':http://acm.tju.edu.cn/toj/showp1675.html\r\n* \'Supermarket\':http://acm.tju.edu.cn/toj/showp1681.html\r\n* Sea - Baraj ONI 2004 (Autor: Radu Berinde)\r\n* Interclasati $K$ vectori sortati. (Sugestie: complexitatea dorita este $O(N * log K)$, unde $N$ este lungimea sirului rezultat prin interclasare)\r\n* Determinati cele mai mici $K$ elemente dintr-un sir cu $N$ elemente cand dispuneti de memorie mult mai putina ca $O(N)$. ({$K$} este mult mai mic decat $N$)\r\n\r\nh2. Discutii pe forum',2044,'public',3528,NULL),('heapuri','Heap-uri','2008-01-18 16:31:03','2009-01-08 01:16:56','h1. Heap-uri\r\n\r\n== include(page=\"template/implica-te/scrie-articole-2\" user_id1=\"Cyber\" user_id2=\"silviug\") ==\r\n\r\n(Categoria _Structuri de date_, Autor _Catalin Francu_, Versiunea originala preluata din cartea _\"Psihologia concursurilor de informatica\"_)\r\n\r\n(toc){width: 30em}*{text-align:center;} *Continut*\r\n* \'Definirea notiunii de _heap_\':heapuri#definire\r\n* \'Structura de heap si metode ajutatoare\':heapuri#structura\r\n* \'Cautarea maximului\':heapuri#cautarea-maximului\r\n* \'Crearea unei structuri de heap dintr-un vector oarecare\':heapuri#creare-heap\r\n* \'Eliminarea unui element, stiind pozitia lui in heap\':heapuri#stergere\r\n* \'Inserarea unui element\':heapuri#inserare\r\n* \'Sortarea unui vector (heapsort)\':heapuri#heapsort\r\n* \'Cautarea unui element\':heapuri#cautare\r\n* \'Alternative STL\':heapuri#stl\r\n* \'Aplicatii\':heapuri#aplicatii\r\n\r\nIn acest articol vom prezenta structura de date numita $heap$, cum poate fi aceasta implementata, precum si alternative STL. Desi este putin probabil sa ajungeti sa implementati heap-urile de la \"zero\" daca stiti STL, consideram ca prezentarea acestora nu este de prisos. Aici atingem problema mai generala \"de ce trebuie sa inteleg X (poate fi vorba de un algoritm, o structura de date, s.a.m.d.) daca il am deja implementat?\". Iata cateva motive:\r\n\r\n* va antreneaza mintea\r\n* va veti putea descurca in situatii in care aveti nevoie de o structura de date asemanatoare, dar nu la fel\r\n* veti fi utilizatori informati ai bibliotecii STL\r\n* veti intelege cand este bine sa folositi o structura de date si cand nu\r\n* veti avea avantajul de a sti precis de ce operatiile de baza au anumite complexitati\r\n\r\nAcum ca avem o motivatie, sa studiem impreuna heap-urile.\r\n\r\nh2(#definire). Definirea notiunii de _heap_\r\n\r\nUn heap ({_engl._} gramada) este un vector care poate fi privit si ca un arbore binar, asa cum se vede in figura de mai jos:\r\n\r\n!heapuri?heap.JPG!\r\n\r\nLanga fiecare nod din arbore se afla cate un numar, reprezentand pozitia in vector pe care ar avea-o nodul respectiv. Pentru cazul considerat, vectorul echivalent ar fi {$H = (12 10 11 10 7 9 3 2 8 1 4 3)$}.\r\n\r\nSe observa ca nodurile sunt parcurse de la stanga la dreapta si de sus in jos. O proprietate necesara pentru ca un arbore binar sa se poata numi $heap$ este ca toate nivelurile sa fie complete, cu exceptia ultimului, care se completeaza incepand de la stanga si continuand pana la un anume punct. De aici deducem ca inaltimea unui heap cu $N$ noduri este <tex> h=[\\log_2 N] </tex> (reamintim ca inaltimea unui arbore este adancimea maxima a unui nod, considerand radacina drept nodul de adancime $0$). Reciproc, numarul de noduri ale unui heap de inaltime $h$ este <tex> N\\in [2^h, 2^{h+1}-1]</tex>.\r\n\r\nTot din aceasta organizare mai putem deduce ca tatal unui nod $k > 1$ este nodul $[k/2]$, iar fiii nodului $k$ sunt nodurile $2k$ si $2k+1$. Daca $2k = N$, atunci nodul $2k+1$ nu exista, iar nodul $k$ are un singur fiu; daca $2k > N$, atunci nodul $k$ este frunza si nu are niciun fiu. Exemple: tatal nodului $5$ este nodul $2$, iar fiii sai sunt nodurile $10$ si $11$. Tatal nodului $6$ este nodul $3$, iar unicul sau fiu este nodul $12$. Tatal nodului $9$ este nodul $4$, iar fii nu are, fiind frunza in heap.\r\n\r\nDar cea mai importanta proprietate a heap-ului, cea care il face util in operatiile de aflarea a maximului, este aceea ca valoarea oricarui nod este mai mare sau egala cu valoarea oricarui fiu al sau. Dupa cum se vede mai sus, nodul $2$ are valoarea $10$, iar fiii sai - nodurile $4$ si $5$ - au valorile $10$ si respectiv $7$. Intrucat operatorul $&ge;$ este tranzitiv, putem trage concluzia ca un nod este mai mare sau egal decat oricare din nepotii sai si, generalizand, va rezulta ca orice nod este mai mare sau egal decat toate nodurile din subarborele a carui radacina este.\r\n\r\nAceasta afirmatie nu decide in niciun fel intre valorile a doua noduri dispuse astfel incat niciunul nu este descendent al celuilalt. Cu alte cuvinte, nu inseamna ca orice nod de pe un nivel mic are valoare mai mare decat nodurile mai apropiate de frunze. Este cazul nodului $7$, care are valoarea $3$ si este mai mic decat nodul $9$ de valoare $8$, nod asezat totusi mai jos in heap. In orice caz, o prima concluzie care rezulta din aceasta proprietate este ca radacina are cea mai mare valoare din tot heap-ul.\r\n\r\nStructura de heap permite efectuarea multor operatii intr-un timp foarte bun:\r\n\r\n* Cautarea maximului in $O(1)$\r\n* Crearea unei structuri de heap dintr-un vector oarecare in $O(N)$\r\n* Eliminarea unui element in $O(log N)$\r\n* Inserarea unui element in $O(log N)$\r\n* Sortarea elementelor din heap in $O(N log N)$\r\n\r\nMentionam ca operatia de cautare a unui element are complexitatea $O(N)$ dar, de obicei, heap-ul nu este folosit cand acest tip de operatii este frecvent.\r\n\r\nDesigur, toate aceste operatii se fac mentinand permanent structura de heap a arborelui, adica respectand modul de repartizare a nodurilor pe niveluri si plasarea mai sus a elementelor de valoare mai mare. Este de la sine inteles ca datele nu se vor reprezenta in memorie in forma arborescenta, ci in cea vectoriala.\r\n\r\nPrecizam de asemenea ca heap-ul poate fi organizat si pe baza operatorului de $&le;$. In acest caz, in varful heap-ului vom avea minimul dintre elementele pastrate in heap. In functie de operatorul folosit, putem numi structura de date $max-heap$ sau $min-heap$. In continuare vom prezenta operatiile intr-un max-heap, adaptarea lor pentru min-heap-uri fiind usoara.\r\n\r\nh2(#structura). Structura de heap si metode ajutatoare\r\n\r\nIn blocul de cod de mai jos prezentam cum se defineste un heap ca vector si cateva metode ajutatoare:\r\n\r\n==code(cpp) |\r\nconst int MAX_HEAP_SIZE = 16384;\r\ntypedef int Heap[MAX_HEAP_SIZE];\r\n\r\ninline int father(int nod) {\r\n    return nod / 2;\r\n}\r\n\r\ninline int left_son(int nod) {\r\n    return nod * 2;\r\n}\r\n\r\ninline int right_son(int nod) {\r\n    return nod * 2 + 1;\r\n}\r\n==\r\n\r\nh2(#cautarea-maximului). Cautarea maximului\r\n\r\nPractic, operatia aceasta nu are de facut decat sa intoarca valoarea primului element din vector:\r\n==code(cpp) |\r\ninline int max(Heap H) {\r\n    return H[1];\r\n}\r\n==\r\n\r\nh2(#creare-heap). Crearea unei structuri de heap dintr-un vector oarecare\r\n\r\nPentru a discuta acest aspect, vom vorbi mai intai despre doua proceduri specifice heap-urilor, $sift$ ({_engl._} a cerne) si $percolate$ ({_engl._} a se infiltra). Sa presupunem ca un vector are o structura de heap, cu exceptia unui nod care este mai mic decat unul din fiii sai. Este cazul nodului $3$ din figura de mai jos, care are o valoare mai mica decat fiii sai (nodurile $6$ si $7$):\r\n\r\n!heapuri?create1.JPG!\r\n\r\nCe e de facut? Desigur, nodul va trebui coborat in arbore, iar in locul lui vom aduce alt nod, mai exact unul dintre fiii sai. Intrebarea este: care din fiii sai? Daca vom aduce nodul $7$ in locul lui, acesta fiind mai mic decat nodul $6$, anomalia se va pastra. Trebuie deci sa schimbam nodul $3$ cu nodul $6$:\r\n\r\n!heapuri?create2.JPG!\r\n\r\nProblema nu este insa rezolvata, deoarece noul nod $6$, proaspat \"retrogradat\", este inca mai mic decat fiul sau, nodul $12$. De data aceasta avem un singur fiu, deci o singura optiune: schimbam nodul $6$ cu nodul $12$ si obtinem o structura de heap corecta:\r\n\r\n!heapuri?create3.JPG!\r\n\r\nProcedura $sift$ primeste ca parametri un heap $H$ cu $N$ noduri si un nod $K$ si presupune ca ambii subarbori ai nodului $K$ au structura de heap corecta. Misiunea ei este sa \"cearna\" nodul $K$ pana la locul potrivit, interschimband mereu nodul cu cel mai mare fiu al sau pana cand nodul nu mai are fii (ajunge pe ultimul nivel in arbore) sau pana cand fiii sai au valori mai mici decat el.\r\n\r\n==code(cpp) |\r\nvoid sift(Heap H, int N, int K) {\r\n    int son;\r\n    do {\r\n        son = 0;\r\n        // Alege un fiu mai mare ca tatal.\r\n        if (left_son(K) <= N) {\r\n            son = left_son(K);\r\n            if (right_son(K) <= N && H[right_son(K)] > H[left_son(K)]) {\r\n                son = right_son(K);\r\n            }\r\n            if (H[son] <= H[K]) {\r\n                son = 0;\r\n            }\r\n        }\r\n\r\n        if (son) {\r\n            swap(H[K], H[son]);  // Functie STL ce interschimba H[K] cu H[son].\r\n            K = son;\r\n        }\r\n    } while (son);\r\n}\r\n==\r\n\r\nProcedura $percolate$ se va ocupa tocmai de fenomenul invers. Sa presupunem ca un heap are o \"defectiune\" in sensul ca observam un nod care are o valoare mai mare decat tatal sau. Atunci, va trebui sa interschimbam cele doua noduri. Este cazul nodului $10$ din figura care urmeaza. Deoarece fiul care trebuie urcat este mai mare ca tatal, care la randul lui (presupunand ca restul heap-ului e corect) este mai mare decat celalalt fiu al sau, rezulta ca dupa interschimbare fiul devenit tata este mai mare decat ambii sai fii. Trebuie totusi sa privim din nou in sus si sa continuam sa urcam nodul in arbore fie pana ajungem la radacina, fie pana ii gasim un tata mai mare ca el. Iata ce se intampla cu nodul $10$:\r\n\r\n!heapuri?create4.JPG!\r\n\r\n==code(cpp) |\r\nvoid percolate(Heap H, int N, int K) {\r\n    int key = H[K];\r\n\r\n    while ((K > 1) && (key > H[father(K)])) {\r\n        H[K] = H[father(K)];\r\n        K = father(K);\r\n    }\r\n\r\n    H[K] = key;\r\n}\r\n==\r\n\r\nAcum ne putem ocupa efectiv de construirea unui heap. Am spus ca procedura $sift$ presupune ca ambii fii ai nodului pentru care este ea apelata au structura de heap. Aceasta inseamna ca putem apela procedura $sift$ pentru orice nod imediat superior nivelului frunzelor, deoarece frunzele sunt arbori cu un singur nod, si deci heap-uri corecte. Apeland procedura $sift$ pentru toate nodurile de deasupra frunzelor, vom obtine deja o structura mai organizata, asigurandu-ne ca pe ultimele doua niveluri avem de-a face numai cu heap-uri. Apoi apelam aceeasi procedura pentru nodurile de pe al treilea nivel incepand de la frunze, apoi pentru cele de deasupra lor si asa mai departe pana ajungem la radacina. In acest moment, heap-ul este construit. Iata cum functioneaza algoritmul pentru un arbore total dezorganizat:\r\n\r\n!heapuri?create5.JPG!\r\n\r\np{padding-left: 4em}. _Nivelul frunzelor este organizat_\r\n\r\n!heapuri?create6.JPG!\r\n\r\np{padding-left: 3em}. _Ultimele doua niveluri sunt organizate_\r\n\r\n!heapuri?create7.JPG!\r\n\r\np{padding-left: 3.5em}. _Ultimele trei niveluri sunt organizate_\r\n\r\n!heapuri?create8.JPG!\r\n\r\np{padding-left: 7em}. _Structura de heap_\r\n\r\n==code(cpp) |\r\nvoid build_heap(Heap H, int N) {\r\n    for (int i = N / 2; i > 0; --i) {\r\n        sift(H, N, i);\r\n    }\r\n}\r\n==\r\n\r\nS-a apelat caderea incepand de la al $N / 2$ - lea nod, deoarece acesta este ultimul nod care mai are fii, restul cu indici mai mari fiind frunze. Sa calculam acum complexitatea acestui algoritm. Un calcul sumar ar putea spune: exista $N$ noduri, fiecare din ele se \"cerne\" pe $O(log N)$ niveluri, deci timpul de constructie a heap-ului este $O(N log N)$. Totusi nu este asa. Presupunem ca ultimul nivel al heap-ului este plin. In acest caz, jumatate din noduri vor fi frunze si nu se vor cerne deloc. Un sfert din noduri se vor afla deasupra lor si se vor cerne cel mult un nivel. O optime din noduri se vor putea cerne cel mult doua niveluri, si asa mai departe, pana ajungem la radacina care se afla singura pe nivelul ei si va putea cadea maxim $h$ niveluri (reamintim ca <tex> h=[\\log_2 N] </tex>). Rezulta ca timpul total de calcul este dat de formula <tex>O(\\displaystyle {\\sum_{k=1}^{[\\log_2 N]} k} \\times \\frac{N}{2^{k+1}}) = O(N)</tex>. Demonstrarea egalitatii se poate face facand substitutia $N = 2^h^$ si continuand calculele. Se va obtine tocmai complexitatea $O(2^h^)$. Lasam aceasta verificare ca tema cititorului.\r\n\r\nh2(#stergere). Eliminarea unui element, stiind pozitia lui in heap\r\n\r\nDaca eliminam un element din heap, trebuie numai sa refacem structura de heap. In locul nodului eliminat s-a creat un gol, pe care trebuie sa il umplem cu un alt nod. Care ar putea fi acela? Intrucat trebuie ca toate nivelurile sa fie complet ocupate, cu exceptia ultimului, care poate fi gol numai in partea sa dreapta, rezulta ca singurul nod pe care il putem pune in locul celui eliminat este ultimul din heap. O data ce l-am pus in gaura facuta, trebuie sa ne asiguram ca acest nod \"de umplutura\" nu strica proprietatea de heap. Deci vom verifica: daca nodul pus in loc este mai mare ca tatal sau, vom apela procedura $percolate$. Altfel vom apela procedura $sift$, in eventualitatea ca nodul este mai mic decat unul din fiii sai. Iata exemplul de mai jos:\r\n\r\n!heapuri?delete1.JPG!\r\n\r\n\r\n\r\n\r\n\r\n\r\nSa presupunem ca vrem sa eliminam nodul de valoare $9$, aducand in locul lui nodul de valoare $X$. Insa $X$ poate fi orice numar mai mic sau egal cu $18$. Spre exemplu, $X$ poate fi $16$, caz in care va trebui urcat deasupra nodului de valoare $10$, sau poate fi $1$, caz in care va trebui cernut pana la nivelul frunzelor. Deoarece caderea si urcarea se pot face pe cel mult $[log N]$ niveluri, rezulta o complexitate a procedeului de $O(log N)$.\r\n\r\n==code(cpp) |\r\nvoid cut(Heap H, int& N, int K) {\r\n    H[K] = H[N];\r\n    --N;\r\n\r\n    if ((K > 1) && (H[K] > H[father(K)])) {\r\n        percolate(H, N, K);\r\n    } else {\r\n        sift(H, N, K);\r\n    }\r\n}\r\n==\r\n\r\nh2(#inserare). Inserarea unui element\r\n\r\nDaca vrem sa inseram un nou element in heap, lucrurile sunt mult mai simple. Nu avem decat sa-l asezam pe a $N + 1$ - a pozitie in vector si apoi sa-l \"promovam\" pana la locul potrivit. Din nou, urcarea se poate face pe maxim $[log N]$ niveluri, de unde complexitatea logaritmica.\r\n\r\n==code(cpp) |\r\nvoid insert(Heap H, int N, int key) {\r\n    H[++N] = key;\r\n    percolate(H, N, N);\r\n}\r\n==\r\n\r\nh2(#heapsort). Sortarea unui vector (heapsort)\r\n\r\nAcum ca am stabilit toate aceste lucruri, ideea algoritmului de sortare vine de la sine. Incepem prin a construi un heap. Apoi extragem maximul (adica varful heap-ului) si refacem heap-ul. Cele doua operatii luate la un loc dureaza $O(1) + O(log N) = O(log N)$. Apoi extragem din nou maximul (care va fi al doilea element ca marime din vector) si refacem din nou heap-ul. Din nou, complexitatea operatiei compuse este $O(log N)$. Daca facem acest lucru de $N$ ori, vom obtine vectorul sortat intr-o complexitate de $O(N log N)$.\r\n\r\nPartea cea mai frumoasa a acestui algoritm este ca el nu foloseste deloc memorie suplimentara. Iata explicatia: cand heap-ul are $N$ elemente, vom extrage maximul si il vom tine minte undeva in memorie. Pe de alta parte, in locul maximului (adica in radacina arborelui) trebuie adus ultimul element al vectorului, adica $H[N]$. Dupa aceasta operatie, heap-ul va avea $N - 1$ noduri, al $N$-lea ramanand liber. Ce alt loc mai inspirat decat acest al $N$-lea nod ne-am putea dori pentru a stoca maximul? Practic, am interschimbat radacina, adica pe $H[&#49;]$ cu $H[N]$. Acelasi lucru se face la fiecare pas, tinand cont de micsorarea permanenta a heap-ului.\r\n\r\n==code(cpp) |\r\nvoid heapsort(Heap H, int N) {\r\n    build_heap(H, N);\r\n\r\n    // Sorteaza vectorul.\r\n    for (int i = N; i >= 2; --i) {\r\n        swap(H[1], H[i]);\r\n        sift(H, i-1, 1);\r\n    }\r\n}\r\n==\r\n\r\nh2(#cautare). Cautarea unui element\r\n\r\nAceasta operatie este singura care nu poate fi optimizata (in sensul reducerii complexitatii sub $O(N)$). Aceasta deoarece putem fi siguri ca un nod mai mic este descendentul unuia mai mare, dar nu putem sti daca se afla in subarborele stang sau drept; din aceasta cauza, nu putem face o cautare binara. Totusi, o oarecare imbunatatire se poate aduce fata de cautarea secventiala. Daca radacina unui subarbore este mai mica decat valoarea cautata de noi, cu atat mai mult putem fi convinsi ca descendentii radacinii vor fi si ei mai mici, deci putem sa renuntam la a cauta acea valoare in tot subarborele. In felul acesta, se poate intampla ca bucati mari din heap sa nu mai fie explorate inutil. Pe cazul cel mai defavorabil, insa, parcurgerea intregului heap este necesara. Lasam scrierea unei proceduri de cautare pe seama cititorului.\r\n\r\nh2(#stl). Alternative STL\r\n\r\nDesi nu sunt greu de implementat, avem vesti bune pentru programatorii in C++: heap-urile sunt deja implementate in STL. Containerul se numeste \'$priority_queue$\':http://www.sgi.com/tech/stl/priority_queue.html si implementeaza toate operatiile prezentate, mai putin operatiile de cautare a unei valori si de stergere a unui nod. Aceste doua operatii sunt destul de atipice pentru o coada de prioritati si in general nu sunt asociate cu aceasta structura de date in cartile de algoritmi.\r\n\r\nTotusi, in unele aplicatii avem nevoie de o structura de date care suporta toate operatiile amintite in timp cel mult logaritmic (inclusiv stergerea si cautarea unei valori). Aceasta structura exista deja in STL: $set$-urile. Acestea sunt de fapt multimi mentinute ca arbori binari echilibrati. Singurele dezavantaje sunt ca de obicei merg mai incet decat cozile de prioritate si folosesc mai multa memorie.\r\n\r\nDaca nu sunteti familiari cu aceste structuri de date, va recomandam sa cititi paginile lor de documentatie: \'$priority_queue$\':http://www.sgi.com/tech/stl/priority_queue.html, \'$set$\':http://www.sgi.com/tech/stl/set.html si \'$multiset$\':http://www.sgi.com/tech/stl/multiset.html. Daca nu intelegeti totul de la inceput (pentru ca nu stiti clase si template-uri in C++), uitati-va pe exemple si pe lista de functii membre si invatati cum se folosesc.\r\n\r\nIn continuare vom ilustra cum putem implementa operatiile de extragere a maximului, extragere a minimului, inserare, stergere si cautare folosind un $multiset$. Vom folosi un $multiset$ pentru ca toate copiile unui numar vor fi pastrate daca el va fi inserat de mai multe ori (spre deosebire de $set$, care il va pastra o singura data). Va recomandam cu caldura sa copiati codul pe calculatorul vostru si sa experimentati cu el pentru a vedea ce afiseaza si a intelege ce se intampla.\r\n\r\n==code(cpp) |\r\n#include <set>\r\nusing namespace std;\r\n\r\nint main() {\r\n    multiset <int> my_set;\r\n    my_set.insert(1); // Insereaza o valoare.\r\n    my_set.insert(1);\r\n\r\n    if (my_set.find(1) != my_set.end()) { // Cauta o valoare.\r\n        printf(\"Am gasit 1 in set!\\n\");\r\n    } else {\r\n        printf(\"1 nu se afla set!\\n\");\r\n    }\r\n\r\n    // Sterge o valoare din set. Daca aceasta se afla de\r\n    // mai multe ori in set, este stearsa numai o copie.\r\n    my_set.erase(my_set.find(1));\r\n    printf(\"Exista %d elemente in set\\n\", my_set.size());\r\n\r\n    my_set.insert(1);\r\n    my_set.insert(1);\r\n\r\n    // Sterge o valoare din set. Daca aceasta se afla de\r\n    // mai multe ori in set, sunt sterse toate copiile.\r\n    my_set.erase(1);\r\n    printf(\"Exista %d elemente in set\\n\", my_set.size());\r\n\r\n    my_set.insert(1);\r\n    my_set.insert(-3);\r\n    my_set.insert(7);\r\n\r\n    // Valoarea minima.\r\n    multiset <int> :: iterator it = my_set.begin();\r\n    printf(\"Valoarea cea mai mica din set este %d\\n\", *it);\r\n\r\n    // Valoarea maxima.\r\n    it = my_set.end();\r\n    --it;\r\n    printf(\"Valoarea cea mai mare din set este %d\\n\", *it);\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#aplicatii). Aplicatii\r\n\r\n* \'Dijkstra cu heap-uri\':http://infoarena.ro/problema/dijkstra\r\n* \'Magnetic storms\':http://acm.timus.ru/problem.aspx?space=1&num=1126\r\n* \'Manager\':http://acm.tju.edu.cn/toj/showp1675.html\r\n* \'Supermarket\':http://acm.tju.edu.cn/toj/showp1681.html\r\n* Sea - Baraj ONI 2004 (Autor: Radu Berinde)\r\n* Interclasati $K$ vectori sortati. (Sugestie: complexitatea dorita este $O(N * log K)$, unde $N$ este lungimea sirului rezultat prin interclasare)\r\n* Determinati cele mai mici $K$ elemente dintr-un sir cu $N$ elemente cand dispuneti de memorie mult mai putina ca $O(N)$. ({$K$} este mult mai mic decat $N$)\r\n\r\nh2. Discutii pe forum',2086,'public',3528,NULL),('missing-numbers','Missing Numbers','2008-03-15 17:15:50','2009-01-08 18:52:43','h1. Probleme cu numere lipsa si nu numai ...\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"alecman\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruseri_)\r\n\r\n(toc){width: 25em}*{text-align:center} *Cuprins*\r\n* \'Problema 1 ( _interviu Microsoft_ ) \':missing-numbers#prob1\r\n* \'Problema 2 ( _interviu Microsoft_ ) \':missing-numbers#prob2\r\n* \'Problema 3 ( _interviu Microsoft, lot 1999_ ) \':missing-numbers#prob3\r\n* \'Problema 4 ( _IBM Research: Ponder This_ ) \':missing-numbers#prob4\r\n* \'Problema 5 \':missing-numbers#prob5\r\n* \'Problema 6 ( _interviu Microsoft_ ) \':missing-numbers#prob6\r\n* \'Problema 7 \':missing-numbers#prob7\r\n* \'Problema 8 \':missing-numbers#prob8\r\n* \'Problema 9 \':missing-numbers#prob9\r\n* \'Problema 10 ( _el judge_) \':missing-numbers#prob10\r\n* \'Problema 11 ( _Info-Oltenia 2005, clasa a IX-a_) \':missing-numbers#prob11\r\n* \'Bibliografie\':missing-numbers#biblio\r\n\r\nh2(#prob1). Problema 1 ( _interviu Microsoft_ )\r\n\r\nSe dau $n-1$ numere distincte de la $1$ la $n$, sa se dea un algoritm cat mai eficient care sa determine numarul lipsa.\r\n\r\nh3. Rezolvare\r\n\r\nPrima rezolvare ce ne poate veni in minte este aceea de a verifica daca fiecare numar $1 -> n$ este prezent in sirul nostru, printr-o parcurgere (acest algoritm are complexitatea $O(n^2^)$ ). O alta rezolvare triviala ar fi sa sortam numerele si sa determinam prin parcurgere numarul $i$ pentru care $a[i] != i$ (pentru sortari rapide algoritmul are complexitatea $O(n log n)$ ).\r\n\r\nO rezolvare mai eficienta poate fi data folosind _Divide et Impera_. Putem imparti numerele in doua multimi, una in care vom pune mumerele mai mici sau egale cu $n/2$, iar in cealalta restul. Acum vom sti din care din cele doua multimi lipseste numarul, dupa numarul de elemente al acestora. Considerand $T(n)$ timpul de executie al algoritmului, atunci complexitatea devine $T(n) = T(n/2) + O(n) = O(n)$. Deci algoritmul este liniar, si foloseste memorie $O(n)$, ignorand memoria consumata de stiva din algoritmul Divide et Impera ( $O(log n)$ ). O alta idee este de a folosi un tabel de dispersie sau un sir de valori booleene care va folosi memorie suplimentara $O(n)$ (poate fi redusa la $O(n/log n)$ daca se lucreaza pe biti).\r\n\r\nO rezolvare eleganta se foloseste de proprietatea ca suma numerelor naturale de la $1$ la $n$ este $n(n + 1)/2$. Numarul lipsa este egal cu diferenta dintre $n(n + 1 )/2$ si suma numerelor noastre. Aceasta solutie are complexitatea $O(n)$ (parcurgem sirul pentru a determina suma) ca timp si $O(1)$ ca memorie. Daca $n$ este destul de mare, s-ar putea ca $n(n+1)/2$ sa depaseasca domeniul de reprezentare al intregilor, rezultand in necesitatea implementarii operatiilor cu numere mari. Pentru a evita acest lucru folosim operatia **xor** (notata prin ^&and;^ ) si proprietatile ei $a ^&and;^ a = 0$ si $a ^&and;^ b = b ^&and;^ a$. Vom face suma xor a numerelor $a[i] ^&and;^ i$ (1 <= i <= n):\r\n$S = a[ 1 ] ^&and;^ 1 ^&and;^ a[ 2 ] ^&and;^ 2 ^&and;^ ... ^&and;^ a[ n - 1 ] ^&and;^ n - 1 ^&and;^ n$\r\n\r\nAstfel fiecare numar care apare in sir va fi in suma de doua ori si va fi anulat, iar rezultatul final va fi indicele numarului lipsa. Solutia are compexitatea $O(n)$ ca timp si $O(1)$ ca spatiu.\r\n\r\nh2(#prob2). Problema 2 ( _interviu Microsoft_ )\r\n\r\nSe da un sir de $n+1$ numere de la $1$ la $n$ in care unul se repeta, iar restul sunt distincte. Sa se dea un algoritm cat mai eficient care sa determine numarul ce se repeta.\r\n\r\nh3. Rezolvare\r\n\r\nEvident, abordarile de la problema anterioara se aplica si aici.\r\n\r\nh2(#prob3). Problema 3 ( lot 1999, _interviu Microsoft_ )\r\n\r\nSe da o lista inlantuita prin primul ei element. Se cere un algoritm cat mai eficient care sa determine daca lista are sau nu ciclu.\r\n\r\nh3. Rezolvare\r\n\r\nFie $n$ numarul total de elemente ale listei. O solutie triviala in $O(n)$ timp si $O(n)$ memorie ar fi sa parcurgem lista si sa adaugam pe rand elementele unui tabel de dispersie (cand apare de doua ori acelasi element rezulta ca am gasit un ciclu). O metoda folosita de unii concurenti este parcurgerea listei pe o perioada de timp determinata (timpul de executie fixat), fiind sanse mari ca un ciclu sa nu existe daca nu s-a gasit nici unul pana la momentul incheierii executiei.\r\n\r\nExista un algoritm mai elegant, care ruleaza tot in timp liniar. El se numeste _Algoritmul lui Floyd de detectie a ciclului intr-o lista_. O aplicatie importanta este _Algoritmul Pollard &rho;_, folosit pentru factorizarea intregilor cu multe cifre. Se folosesc doi pointeri $a$ si $b$, unde $a$ se misca de doua ori mai repede decat $b$ in lista (denumit si _Algoritmul iepurelui si testoasei_). Reprezentarea grafica seamana cu litera greceasca &rho;. Notam lungimea lantului cu &lambda; si lungimea ciclului cu &mu;.\r\n\r\n!missing-numbers?missing_numbers_pic2.png!\r\n\r\n== code(c) |\r\n//cap - pointer spre capatul listei\r\na = b = cap;\r\ndo{\r\n    b = b -> next;\r\n    a = a -> next -> next;\r\n}while(a != b);\r\n==\r\n\r\nCand $a$ si $b$ sunt amandoi in ciclu, este evident ca la un moment dat $a = b$. In exemplul desenat, dupa sase iteratii cei doi pointeri vor indica acelasi element. Pentru determinarea lungimii ciclului se mai poate face o parcurgere in care doar un pointer se misca. Acum dupa ce stim lungimea &mu; a ciclului, putem afla si lungimea &lambda; a lantului astfel: luam un pointer la inceputul listei si al doilea care a facut deja &mu; pasi in lista (amandoi pointerii au aceeasi viteza). Dupa &lambda; pasi ei vor fi egali. Astfel am obtinut o rezolvare liniara.\r\n\r\nh2(#prob4). Problema 4 ( _IBM Research: Ponder This_ )\r\n\r\nUn sir de lungime $n$ contine numere intregi din multimea ${1, 2, ..., n-1}$. Folosind _Principiul lui Dirichlet_ deducem ca cel putin un element se repeta. Gasiti un algoritm liniar care afiseaza o valoare ce se repeta, folosind memorie suplimentara constanta si nemodificand la nici un pas vreun element din sir.\r\n\r\nh3. Rezolvare\r\n\r\nAici nu merge solutia cu suma xor de la problemele $1$ si $2$ pentru ca numerele pot fi repetate oricum si nu putem folosi relatiile obtinute pentru a determina un numar care se repeta. Daca toate elementele din sir ar fi distincte, atunci sirul ar avea structura unei permutari. Cum ele nu sunt neaparat distincte ne vine ideea de a vedea care este diferenta intre un asemenea sir si o permutare, pentru a folosi idei care apar la permutari (ciclurile acestora). Fiecare element din sirul nostru indica inspre altul, deci il putem considera un graf orientat in care arcele sunt $(i, a[i])$. De exemplu putem face urmatoarea reprezentare pentru sirul $3, 2, 1, 3, 4$:\r\n\r\n!missing-numbers?missing_numbers_pic3.png!\r\n\r\nDin fiecare nod iese cate un arc si cum sunt un numar finit de noduri rezulta ca din orice nod pornim ajungem intr-un ciclu. In momentul in care intram in ciclu, acel numar se va repeta, deci vrem ca primul nod sa nu apartina nici unui ciclu. Un astfel de nod e nodul $n$, pentru ca nici un element $a[i]$ nu va fi egal cu $n$. Deci, daca pornim de la nodul $n$ suntem in afara oricarui ciclu si putem sa mergem pe drumul pe care il indica pentru a ajunge eventual intr-un ciclu. Am vazut in problema anterioara cum determinam lungimea lantului pentru o lista ce contine un ciclu. Putem determina astfel elementul de la intrarea in ciclu in complexitate $O(n)$ si problema noastra este rezolvata.\r\n\r\nh2(#prob5). Problema 5\r\n\r\nSe da un sir de $N$ intregi ce contine numere intre $1$ si $N$. Sa se determine cat mai eficient daca acest numar este o permutare, fara a distruge sirul.\r\n\r\nh3. Rezolvare\r\n\r\nPentru ca valorile sirului sunt intregi, iar valorile elementelor unei permutari sunt pozitive, rezulta ca putem folosi bitul de semn al fiecarui numar pentru ca acesta ramane liber. Verificam mai intai daca exista vreun element negativ in sir. Apoi, daca nu exista, vom marca elementele parcurse din ciclurile permutarii astfel $a[i] = -a[i]$. Daca un element este marcat de doua ori sau am gasit initial un numar negativ, atunci cele $N$ numere nu reprezinta o permutare. Pentru a reface sirul initial, vom schimba toate elementele ce au semn negativ din sir cu valorile lor in modul. Astfel am obtinut o rezolvare liniara ce foloseste spatiu suplimentar $O(1)$.\r\n\r\nh2(#prob6). Problema 6 ( _interviu Microsoft_ )\r\n\r\nSe dau n numere de la 1 la n. Unul din ele unul apare de doua ori in sir, iar restul sunt distincte. Evident ca un numar nu va aparea niciodata. Sa se dea un algoritm cat mai eficient care sa determine numarul lipsa si numarul ce apare de doua ori.\r\n\r\nh3. Rezolvare\r\n\r\nNotam cu $a$ numarul lipsa si cu $b$ numarul ce apare de doua ori. Majoritatea celor care stiu sa rezolve problema $1$ prin cele doua solutii optime (suma numerelor si suma xor) incearca sa rezolve aceasta problema determinand doua relatii diferite asupra lui $a$ si $b$, din care apoi incearca sa obtina valorile cerute. Scazand din $n(n + 1)/2$ suma numerelor din fisier obtinem valoarea pentru $a - b$, iar facand suma xor a numerelor din fisier si a numerelor de la $1$ la $n$ obtinem valoarea pentru $a ^&and;^ b$. In acest moment putem considera ca problema este rezolvata, dar la o analiza mai atenta se poate observa ca numerele care verifica relatiile respective nu sunt unice. De exemplu pentru $a = 10$ si $b = 9$ obtinem valorile $a - b = 1$ si $a ^&and;^ b = 3$. Aceleasi valori le obtinem si pentru $a = 6$ si $b = 5$. Se observa de aici ca cele doua relatii nu pot fi folosite pentru a rezolva problema.\r\nStim care este valoarea diferentei $D{~1~} = a - b$, dar mai avem nevoie de o relatie pentru a determina numerele $a$ si $b$. Vom incerca in continuare sa folosim operatia de inmultire pentru a obtine cea de-a doua relatie. Vom avea: $a/b = n! / (a[ 1 ] * a[ 2 ] * ... * a[ n ])$. Aceasta relatie nu poate fi calculata in $O(n)$ pentru ca numarul de cifre al lui $n!$ nu este constant. Pentru a evita lucrul cu numere mari am putea sa logaritmam intreaga relatie, obtinand $lg a - lg b = lg 1 + lg 2 + ... + lg n - lg a[ 1 ] - lg a[ 2 ] - ... - lg a[ n ]$. Aceasta rezolvare ar fi buna daca ar fi posibila realizarea unor calcule perfecte cu numere reale. Din pacate acest lucru nu este posibil si rezolvarea are mari probleme cu precizia. \r\nO a doua relatie o putem obtine ca diferenta intre suma patratelor numerelor de la $1$ la $n$ si suma patratelor numerelor din fisier. Obtinem astfel $D{~2~} = a^2^ - b^2^$. Din aceste doua relatii putem usor afla ca $a = (D{~1~} + D{~2~}/D{~1~})/2$ si $b = (D{~2~}/D{~1~} - D{~1~})/2$. Aceasta rezolvare are complexitatea $O(n)$ ca timp si $O(1)$ ca spatiu.\r\n\r\nh2(#prob7). Problema 7\r\n\r\nSe dau $n - k$  numere distincte de la $1$ la $n$. Sa se dea un algoritm cat mai eficient care sa determine numerele lipsa.\r\n\r\nh3. Rezolvare\r\n\r\nFie $a, b, c, ...$ numerele ce lipsesc. Am putea extinde ideea din problema anterioara pentru a obtine in $O(n*k)$ sumele $S{~1~} = a + b + c + ..., S{~2~} = a^2^ + b^2^ + c^2^ + ..., ..., S{~k~} = a^k^ + b^k^ + c^k^ + ...$ si sa obtinem valorile elementelor $a, b, c, ...$, dar in general daca valoarea lui $k$ este variabila, atunci putem gasi solutia ce satisface toate cele $k$ relatii in timp exponential. O metoda este de a transforma relatiile intr-un polinom de radacini $a, b, c, ...$. Pentru a gasi $P(x) = a{~0~}X^k^ + a{~1~}X^k-1^ + ... + a{~k~}$ putem folosi relatiile lui Viete[1]\r\n$s{~1~} = a + b + c + d + ...$ \r\n$s{~2~} = ab + ac + ad + bc + bd + cd + ...$\r\n$s{~3~} = abc + acd + bcd + ...$\r\n$s{~4~} = abcd + ...$\r\n...\r\n$s{~i~} = (-1)^i^ a{~n-i~}/a{~n~}$\r\n\r\nAceste sume $s{~k~}$ sunt numite polinoame simetrice si sunt strans legate de sumele de puteri $k S{~k~}$ prin relatiile Newton Girard[2]. Astfel avem un algoritm ce determina polinomul in $O(nk)$ si spatiu $O(k)$ (daca se ignora faptul ca numerele ar putea depasi intervalul numerelor reprezentabile pe un intreg), dar determinarea solutiei finale se poate face in $O(1)$ doar pentru ecuatii de gradul doi sau trei, pentru care stim formule de calcul. Pentru ecuatii de grad mai mare nu exista formule generale si trebuie aplicate metode care aproximeaza solutiile. O astfel de metoda ar fi sa derivam polinomul, sa gasim solutiile pentru $P\'(x) = 0$, iar apoi sa folosim cate o cautare binara pentru a gasi solutiile $P(x) = 0$.\r\nDe exemplu pentru trei numere lipsa $a, b, c$ este usor sa determinam $S{~1~} = a + b + c, S{~2~} = a^2^ + b^2^ + c^2^, S{~3~} = a^3^ + b^3^ + c^3^$. $S{~1~}^2^ = a^2^ + b^2^ + c^2^ + 2ab + 2bc + 2ac = S{~2~} + 2s{~2~}, S{~1~}^3^ = a^3^ + b^3^ + c^3^ + 3a^2^b + 3a^2^c + 3b^2^a + 3b^2^a + 3c^2^a + 3c^2^b + 6abc = S{~3~} + 3(a^2^b + b^2^a + abc) + 3(a^2^c + c^2^a + abc) + 3(b^2^c + c^2^b + abc) - 3abc = S{~3~} + 3ab*s{~1~} + 3ac*s{~1~} + 3bc*s{~1~} - s{~3~} = S{~3~} + 3s{~2~}*s{~1~} - s{~3~}$. Din aceste relatii putem sa obtinem usor $s{~1~}, s{~2~}, s{~3~}$ si apoi putem aplica formulele lui Cardano de rezolvare a ecuatiei de gradul trei pe ecuatia $x^3^ - s{~1~} x^2^ + s{~2~} x - s{~3~} = 0$.\r\n\r\nh2(#prob8). Problema 8\r\n\r\nIntr-o structura de date avem $n - 1$ numere intregi (pentru simplitate $n = 2^b^ - 1$, cu numere distincte de la $0$ la $n$). Asupra elementelor din structura de date putem face urmatoarea operatie getBit(i, j), care returneaza al $j$-lea bit din reprezentarea binara a numarului $a[ i ]$. Astfel daca $a[ 4 ] = 11$, atunci getBit(4, 3) returneaza $0$ pentru ca $11$ se scrie in baza $2$ ca $1011$. Sa se dea o solutie eficienta care gaseste numarul lipsa.\r\n\r\nh3. Rezolvare\r\n\r\nAcum vom folosi din nou un algoritm bazat pe Divide et Impera. La primul pas impartim multimea in doua submultimi - cea a numerelor pare si cea a numerelor impare, si vedem in care din ele se gaseste numarul nostru lipsa (am aflat astfel ultimul bit al rezultatului). Acum putem aplica recursiv procedura aceasta pe numerele din o lista cu jumatate din lungimea listei initiale impartite la doi (ignoram ultimul bit al numerelor). Aceasta solutie are complexitate $O(n)$ pentru ca dupa fiecare pas executat in timp liniar, dimensiunea problemei se injumatateste. Memoria suplimentara e $O(n)$ (doi vectori care sa pastreze indicii elementelor pare, respectiv impare).\r\n \r\nh2(#prob9). Problema 9\r\n \r\nGeneralizam problema anterioara si se cere un algoritm eficient pentru un sir din care lipsesc $n - k$ numere.\r\n \r\nh3. Rezolvare\r\n \r\nDin nou vedem cate numere din sir au ultima cifra $0$ si cate au $1$. Astfel putem determina $k{~0~}$ - numarul de valori lipsa cu ultima cifra $0$, si $k{~1~}$ - numarul de valori lipsa care au ultima cifra $1$. Daca notam timpul de rezolvare al problemei noastre $T(n, k)$, acum avem de rezolvat doua subprobleme cu timpii $T(n/2, k{~0~})$ si $T(n/2, k{~1~})$. Acum impartim cele $k{~0~}$ numere in $k{~00~}$ si $k{~10~}$ valori care se termina in $00$, respectiv $10$ in reprezentarea in baza $2$. Aceasta solutie are complexitate $O(n log n)$ si nu imbunatateste cu nimic solutia in care sortam elementele sirului.\r\n \r\nh2(#prob10). Problema 10 ( _el judge_ )\r\n \r\nSe dau $n$ numere intregi astfel incat fiecare numar apare de un numar par de ori, in afara de unul singur, care apare de un numar impar de ori. Se cere determinarea acelui numar. De exemplu in sirul $1 2 2 3 1 2 2 2 3 3 3$, numai elementul $2$ apare de un numar impar de ori.\r\n \r\nh3. Rezolvare\r\n \r\nEste evident ca daca facem suma xor a tuturor numerelor, rezultatul va fi numarul ce apare de numar impar de ori. Astfel solutia are complexitatea $O(n)$ ca timp si $O(1)$ ca memorie folosita.\r\n \r\nh2(#prob11). Problema 11 ( _Info-Oltenia 2005, clasa a IX-a_ )\r\n \r\nSe dau $n$ siruri formate din cifre de la $1$ la $8$ (inclusiv), de lungime maxima $500$. Toate sirurile sunt repetate de $k$ ori sau de multiplu de $k$ ori, cu exceptia unui singur sir, care nu este repetat de $k$ ori, sau de multiplu de $k$ ori. Sa se afiseze sirul care nu se repeta. ( $1 <= n <= 32000, k < 2005$ )\r\n \r\nh3. Rezolvare\r\n \r\nPutem face o solutie similara cu cea de mai sus. Consideram un tablou $A$ cu $500 * 8$ elemente, fiecare linie $i$ corespunzand cifrelor de pe pozitia $i$ din sirurile de cifre date la intrare. Cand procesam un sir dintre cele date la intrare, daca el are pe pozitia $i$ cifra $j$ atunci incrementam elementul $A[ i ][ j ]$. In acest tablou, pe fiecare linie $i$, toate elementele in afara de unul vor fi $0$ sau multiplu de $k$, iar elementul $A[ i ][ j ]$ care nu e multiplu de $k$ este a $j$-a cifra a numarului care se repeta de un numar de ori ce nu este divizibil cu $k$. Aceasta solutie are complexitate ca timp $O(n*L)$, iar ca spatiu $O(L)$, unde $L$ este lungimea maxima a unui sir de cifre.\r\n \r\nh2(#biblio). Bibliografie\r\n \r\n*(#fn1) 1. http://mathworld.wolfram.com/VietasFormulas.html\r\n*(#fn2) 2. http://mathworld.wolfram.com/Newton-GirardFormulas.html\r\n*(#fn3) 3. http://en.wikipedia.org/wiki/Floyd\'s_cycle-finding_algorithm',4297,'public',NULL,NULL),('algoritmiada-2009/runda-2/solutii/colier','algoritmiada-2009/runda-2/solutii/colier','2009-01-03 17:07:03','2009-01-08 20:27:16','h1(#colier). \'Colier\':problema/colier\r\n\r\nFaci asa',2038,'private',NULL,NULL),('newsletter/algoritmiada-2009-2','Algoritmiada, Runda 2','2009-01-08 19:05:51','2009-01-08 23:48:06','Buna, %full_name%!\r\n\r\nIn curand incepe a doua runda a concursului Algoritmiada, cel mai\r\nmare si mai important concurs organizat de infoarena!\r\n\r\nLa Algoritmiada participa elevi de gimnaziu, elevi de liceu, *dar si\r\nstudenti,* si chiar masteranzi sau doctoranzi! (Avem grupe separate\r\npentru fiecare.)\r\n\r\nRunda 2 se desfasoara in acest weekend. Intrece-te cu cei mai buni!\r\nAsigura-ti locul la finala si castiga premii serioase!\r\n\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Runda 2 se desfasoara\r\n\r\n        Duminica, 11 Ianuarie 2009, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\r\nVezi pagina concursului: %url_infoarena%algoritmiada-2009\r\npentru mai multe informatii.\r\n\r\nSucces!\r\n\r\n\r\n== Atentie! Concurs cu rating! ==\r\n\r\nDaca vrei sa ti se modifice rating-ul in urma acestei runde trebuie\r\nsa iti anunti participarea din timp. Intra pe\r\n%url_infoarena%algoritmiada-2009/runda-2 si inscrie-te.\r\n\r\nPoti sa participi la concurs chiar si daca nu te-ai inscris in\r\nprealabil insa nu ti se va modifica rating-ul. %your_rating_is%\r\nCiteste despre rating: %url_infoarena%documentatie/rating.\r\n\r\n\r\n== Despre Algoritmiada, Runda 2 ==\r\n\r\nAlgoritmiada este un concurs nou, cu premii, organizat de infoarena.\r\nConcursul se desfasoara in 3 runde online de calificare, si o\r\nfinala on-site. Cei mai buni vor castiga premii serioase, in bani si\r\nobiecte.\r\n\r\nLa Runda 2 vei avea la dispozitie 4h sa rezolvi 3 probleme de natura\r\nalgoritmica. Concurentii sunt impartiti in 4 grupe de varsta:\r\ngimnaziu, clasele 9-10, clasele 11-12, si studenti (inclusiv\r\nmasteranzi si doctoranzi).\r\n\r\nSubiectele vor fi propuse de catre o echipa de fosti si actuali\r\nolimpici la informatica: Airinei Adrian, Bogdan Tataroiu, Andrei\r\nGrigorean, Gheorghe Cosmin, Paul-Dan Baltescu, si Stefan Istrate.\r\nDe ce ei? Intra pe pagina rundei si citeste cate ceva despre\r\nexperienta fiecaruia: %url_infoarena%algoritmiada-2009/runda-2\r\n\r\nIti uram succes si te asteptam in arena!\r\n\r\n\r\n== Despre runda anterioara ==\r\n\r\nSilviu Ganceanu a facut o analiza a primei runde Algoritmiada.\r\nAfla cati concurenti au participat, cate surse s-au trimis, si\r\nimpresii despre runda aici:\r\n%url_infoarena%blog/algoritmiada-runda1\r\n\r\nVezi rezultatele si clasamentul aici:\r\n%url_infoarena%algoritmiada-2009/clasament\r\n\r\n\r\n== Seria de concursuri preONI s-a incheiat ==\r\n\r\nDupa 5 ani, seria de concursuri preONI se retrage. Cel mai longeviv\r\nconcurs infoarena, cel mai amplu eveniment organizat de noi pana\r\nacum, cu o traditie lunga si cu mii de participanti, se incheie.\r\n\r\nDe anul acesta incepe Algoritmiada. Vom incerca sa aplicam lectiile\r\ninvatate pana acum, insa avem nevoie de ajutorul tau. Fii alaturi de\r\nnoi, contacteaza-ne pe forum, ajuta-ne sa facem din Algoritmiada o\r\ncompetitie la care ti-ar placea sa participi oricand.\r\n\r\nAi participat vreodata la preONI? Iti mai aduce aminte ce fel a fost,\r\nce probleme ai primit? Ti-am facut poze la finala? Viziteaza inca\r\nodata paginile editiilor anterioare:\r\n\r\n    *   preONI 2008, finala la Univ. Politehnica, Bucuresti\r\n        %url_infoarena%preoni-2008\r\n\r\n    *   preONI 2007, finala la Lic. Int. de Informatica, Bucuresti\r\n        %url_infoarena%preoni-2007\r\n\r\n    *   preONI 2006, finala la C. N. \"Unirea\", Focsani\r\n        %url_infoarena%preoni-2006\r\n\r\n    *   preONI 2005, finala online\r\n        %url_infoarena%preoni-2005\r\n\r\n    *   preONI 2004, finala online\r\n        %url_infoarena%preoni-2004\r\n\r\n\r\n== Prima data la infoarena? ==\r\n\r\n\r\nDespre infoarena: %url_infoarena%despre-infoarena\r\nTutorial infoarena: %url_infoarena%documentatie/tutorial\r\n\r\n\r\n== Fii un bun infoarenaut! Implica-te! ==\r\n\r\nMai mult ca oricand, infoarena are nevoie de ajutorul tau! infoarena\r\neste un efort colectiv, munca a zeci de voluntari pe parcursul a 5\r\nani de zile.  Vrem sa-i sprijinim pe toti cei care, pasionati de\r\ninformatica si programare, vor sa invete mai mult, vor sa isi\r\nperfectioneze abilitatile.\r\n\r\nVrei sa compui problemele tale? Vrei sa organizezi concursuri? Iti\r\nplace sa programezi, doresti sa inveti cum se dezvolta un site precum\r\ninfoarena?  Vrei sa redactezi articole despre algoritmi si structuri\r\nde date? Pentru toate acestea, si pentru multe altele, infoarena are\r\nnevoie de ajutorul tau!\r\n\r\nAfla cum te poti implica in comunitatea infoarena:\r\n%url_infoarena%implica-te\r\n\r\nInvata alaturi de noi!\r\n\r\n\r\n== Mesaj nesolicitat? ==\r\n\r\nEsti inscris pe %url_infoarena% cu numele\r\n\"%full_name%\", utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\r\nDaca nu mai doresti instiintari, da click pe acest link:\r\n%url_unsubscribe%\r\n\r\n',13,'protected',NULL,NULL),('probleme-cu-secvente','Probleme cu secvente','2008-11-23 19:46:37','2009-01-08 18:56:23','h1. Probleme cu secvenţe\r\n\r\n(Categoria _Diverse_, autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 30em}*{text-align:center} *Cuprins*\r\n* \'Introducere \':probleme-cu-secvente#intro\r\n* \'Problema 1 (Subsecvenţa de sumă maximă) \':probleme-cu-secvente#prob1\r\n* \'Problema 2 (Maximum Sum) \':probleme-cu-secvente#prob2\r\n* \'Problema 3 (SequenceQuery) \':probleme-cu-secvente#prob3\r\n* \'Problema 4 \':probleme-cu-secvente#prob4\r\n* \'Problema 5 \':probleme-cu-secvente#prob5\r\n* \'Problema 6 (Secvenţă) \':probleme-cu-secvente#prob6\r\n* \'Problema 7 (Agricultura) \':probleme-cu-secvente#prob7\r\n* \'Problema 8 (Secvenţa 2) \':probleme-cu-secvente#prob8\r\n* \'Problema 9 (Sum) \':probleme-cu-secvente#prob9\r\n* \'Problema 10 (Secvenţa 3) \':probleme-cu-secvente#prob10\r\n* \'Problema 11 (XorMax) \':probleme-cu-secvente#prob11\r\n* \'Probleme propuse\':probleme-cu-secvente#probp\r\n* \'Bibliografie\':probleme-cu-secvente#bibliografie\r\n\r\nh2(#intro). Introducere\r\n\r\nAcest articol prezintă o serie de probleme înrudite cu problema subsecvenţei de sumă maximă, însoţite de rezolvări eficiente. Problemele prezentate pot apărea oricând ca subprobleme în concursurile de programare, studierea lor mărind în mod util bagajul de cunoştinţe al unui elev pasionat de algoritmică.\r\n\r\nh2(#prob1). Problema 1 (Subsecvenţa de sumă maximă)\r\n\r\nSe dă un şir de $N$ numere întregi $(a{~1~}, a{~2~}, ..., a{~N~})$. Să se determine o subsecvenţă $(a{~i~}, a{~i+1~}, ..., a{~j~})$ care să aibă suma maximă.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(-1, 2, 3, -4, -2, 2, 1, -3, -2, -3, -4, 9, -2, 1, 7, 8, -19, -7, 2, 4, 3)$, o subsecvenţă de sumă maximă este $(9, -2, 1, 7, 8)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPrima rezolvare care ne vine în minte are complexitatea $O(N^3^)$ şi constă în determinarea sumei fiecărei subsecvenţe posibile şi reţinerea maximului acestor sume. Este evident că anumite sume parţiale sunt calculate de mai multe ori.\r\n\r\nPutem reduce complexitatea la $O(N^2^)$ ţinând cont de faptul că suma subsecvenţei $a[i..j]$ este egală cu suma subsecvenţei $a[i..j-1]$, la care se adună $a[j]$. Păstrăm într-un şir $sum[i]$ - suma elementelor din subsecvenţa $a[1..i]$. Pentru a determina suma elementelor din subsecvenţa $a[i..j]$ facem diferenţa $sum[i] - sum[j-1]$.\r\n\r\nIdeea poate fi rafinată calculând pentru fiecare indice $i$ numărul $best[i]$, reprezentând subsecvenţa de sumă maximă cu capătul drept în $i$. Este uşor de observat că $best[i] = max(sum[i] - sum[j-1])$, unde $j$ ia valori de la $1$ la $i$. Relaţia anterioară se mai poate scrie $best[i] = sum[i] - min(sum[j-1])$. Obţinem astfel un algoritm liniar care ne determină subsecvenţa de sumă maximă cerută.\r\n\r\n== code(cpp) |\r\nsum[0] = 0;\r\nfor (i = 1; i <= N; i++) sum[i] = a[i] + sum[i-1];\r\nmin = sum[0];\r\nbestSum = -INFINIT;\r\nfor (i = 1; i <= N; i++) {\r\n    best[i] = sum[i] - min;\r\n    if (min > sum[i]) min = sum[i];\r\n    if (bestSum < best[i]) bestSum = best[i];\r\n}\r\n==\r\n\r\nO altă metodă de calcul poate fi dedusă folosind paradigma _Divide Et Impera_. La fiecare pas împărţim şirul în jumătate şi aflăm subsecvenţele de sumă maximă din cele două jumătăţi. După aceea trebuie să găsim subsecvenţa de sumă maximă ce are un capăt în fiecare din cele două jumătăţi ale sirului. Pentru aceasta alipim sufixul de sumă maximă a primei jumătăţi cu prefixul de sumă maximă a celei de-a doua.\r\n\r\n== code(cpp) |\r\nint getMaxSubsequence(int l, int r) {\r\n    if (l == r) return a[l];\r\n    mid = (l + r) / 2;\r\n    bestL = getMaxSubsequence(l, mid);\r\n    bestR = getMaxSubsequence(mid + 1, r);\r\n    suf = 0; \r\n    pre = 0; \r\n    maxSuf = -INFINIT; \r\n    maxPre = -INFINIT;\r\n    for (i = mid; i >= l; i--) {\r\n        suf += a[i];\r\n        if (maxSuf < suf) maxSuf = suf;\r\n    }\r\n    for (i = mid + 1; i <= r; i++) {\r\n        pre += a[i];\r\n        if (maxPre < pre) maxPre = pre;    \r\n    }\r\n    return max(bestL, max(bestR, maxPre + maxSuf));\r\n}\r\n==\r\n\r\nO idee bazată pe paradigma programării dinamice ar fi să folosim un şir $best[i]$, reprezentând suma maximă a unei subsecvenţe ce se termină în $a[i]$. Problema se rezolvă cu următoarea formulă de recurenţă: $best[i] = max(a[i], best[i-1] + a[i])$. Formula poate fi demonstrată prin inducţie matematică.\r\n\r\nO ultimă idee ar fi să partiţionăm şirul în subsecvenţe încât fiecare să aibă ambele capete cât mai mici posibile şi suma elementelor subsecvenţei să fie negativă. Pentru exemplul dat avem următoarea partiţionare $[-1], [2, 3, -4, -2], [2, 1, -3, -2], [-3], [-4], [9, -2, 1, 7, 8, -19, -7], [2, 4, 3]$. O subsecvenţă de sumă maximă va avea primul capăt la începutul unei astfel de subsecvenţe, acest lucru explicându-se prin faptul că în caz contrar secvenţa poate fi mărită în stânga (orice secvenţă din cele alese pentru partiţionare are toate prefixele de sumă pozitivă, în afară de prefixul ce reprezintă întreaga subsecvenţă). De asemenea, orice subsecvenţă de sumă maximă nu va conţine elemente din altă parte a partiţiei, pentru că dacă subsecvenţa se întinde pe mai multe părţi, atunci putem elimina prefixul subsecvenţei care reprezintă o parte a partiţiei, acea parte având suma negativă.\r\n\r\n== code(cpp) |\r\nsum = -INFINIT;\r\nbestSum = -INFINIT;\r\nfor (i = 1; i <= N; i++) {\r\n    sum += a[i];\r\n    if (sum < 0) {\r\n        sum = 0;\r\n        continue;\r\n    } else \r\n    if (sum >= bestSum) bestSum = sum;      \r\n}\r\n==\r\n\r\nh2(#prob2). Problema 2 (\'Maximum Sum\':http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&Itemid=8&category=3&page=show_problem&problem=44, UVa)\r\n\r\nSe dă o matrice de dimensiuni $N x N$ cu elemente întregi. Se cere determinarea unei submatrici a cărei elemente au suma maximă. \r\n\r\nh3. Exemplu:\r\n\r\nPentru matricea<tex>\\[ \\left( \\begin{array}{cccc}0 & -2 & -7 & 0 \\\\9 & 2 & -6 & 2 \\\\-4 & 1 & -4 & 1 \\\\-1 & 8 & 0 & -2 \\end{array} \\right)\\]</tex>submatricea de sumă maximă este următoarea:<tex>\\[ \\left( \\begin{array}{cc}9 & 2 \\\\-4 & 1 \\\\-1 & 8 \\end{array} \\right)\\]</tex>\r\n\r\nh3. Rezolvare:\r\n\r\nPutem folosi trucul construirii sumelor parţiale din rezolvarea anterioară, pentru cazul $2D$. Păstrăm în $sum[i][j]$ suma tuturor elementelor $a[i{~1~}][j{~1~}]$ cu proprietatea că $1 <= i{~1~} <= i$, şi $1 <= j{~1~} <= j$. Putem calcula sumele prin metoda programării dinamice (complexitate $O(N^2^)$) folosind formula $sum[i][j] = a[i][j] + sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1]$. Acum pentru a calcula suma elementelor din matricea cu colţurile $(i{~1~}, j{~1~})$ şi $(i{~2~}, j{~2~})$, unde $i{~1~} <= i{~2~}$ şi $j{~1~} <= j{~2~}$, este suficient să facem calculul $sum[i{~2~}][j{~2~}] - sum[i{~1~}-1][j{~2~}] - sum[i{~2~}][j{~1~}-1] + sum[i{~1~}-1][j{~1~}-1]$. Astfel putem evalua suma din fiecare submatrice în timp constant, deci rezolvarea are ordinul de complexitate $O(N^4^)$.\r\n\r\nO altă idee ar fi ca pentru fiecare pereche $(i{~1~}, i{~2~})$ fixată să determinăm perechea optimă $(j{~1~}, j{~2~})$. Dacă avem liniile $i{~1~}$ şi $i{~2~}$ fixate atunci problema se transformă din una bidimensională în una unidimensională. Astfel pentru fiecare coloană $j$ vom considera $b[j]$ ca sumă a elementelor $a[i][j]$ cu proprietatea că $i{~1~} <= i <= i{~2~}$. În exemplul nostru, dacă $i{~1~} = 2$ şi $i{~2~} = 3$, atunci avem $b{~1~} = 9 + (-4)$, $b{~2~} = 2 + 1$, $b{~3~} = (-6) + (-4)$ şi $b{~4~} = 2 + 1$. Pentru a rezolva problema unidimensională folosim unul din algoritmii liniari prezentaţi mai sus, astfel obţinându-se un algoritm de complexitate totală $O(N^3^)$. Acest truc de a fixa două linii pentru a transforma problema în una unidimensională este util în multe probleme pe matrice sau cu puncte în plan.\r\n\r\nCel mai bun algoritm cunoscut pentru această problemă are complexitatea <tex>O(N^{3\\sqrt{\\frac{\\log \\log N}{\\log N}}})</tex> [3] şi este mai mult un algoritm teoretic decât unul practic, uşor implementabil.\r\n\r\nh2(#prob3). Problema 3 (\'SequenceQuery\':problema/sequencequery, Bursele Agora 2005/2006 Runda 1)\r\n\r\nSe consideră un şir $A = (a{~1~}, a{~2~}, ..., a{~N~})$, format din numere întregi $(-100.000 <= a{~i~} <= 100.000)$, şi $M$ perechi de numere $(x, y)$ $(1 <= N, M <= 100.000)$. Pentru fiecare pereche ordonată de indici $(x, y)$ trebuie determinată subsecvenţa de sumă maximă a subşirului $a{~x~}, a{~x+1~}, ..., a{~y~}$. Subsecvenţele alese trebuie să conţină cel puţin un element. \r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(-1, 2, 3, -2, 4, -3, 8, -3)$ şi intervalele $[1, 5]$, $[4, 8]$ si $[6, 6]$ avem soluţiile: \r\n\r\n* $7$ pentru subsecvenţa $(-1, *2*, *3*, *-2*, *4*)$;\r\n\r\n* $9$ pentru subsecvenţa $(-2, *4*, *-3*, *8*, -3)$;\r\n\r\n* $-3$ pentru subsecvenţa $({*-3*})$.\r\n\r\nh3. Rezolvare:\r\n\r\nPutem obţine un algoritm de complexitate $O(M * N)$ folosind algoritmii liniari din prima problemă, dar să vedem cum putem reduce complexitatea folosind alte abordări. Mai întâi calculăm şirul $sum$ al sumelor parţiale, după care împărţim şirul în $k$ subsecvenţe de lungimi egale $[n / k]$, şi păstrăm următoarele informaţii pentru fiecare din ele:\r\n\r\n* $max[i]$ - cea mai mare valoare $sum[j]$, unde: $n/k * (i-1) < j <= n/k * i$;\r\n\r\n* $min[i]$ - cel mai mic $sum[j-1]$, unde: $n/k * (i-1) < j <= n/k * i$;\r\n\r\n* $best[i]$ - valoarea subsecventei de suma maxima a secventei curente.\r\n\r\nAcum, pentru a afla subsecvenţa de sumă maximă a subsecvenţei $a[x..y]$ studiem cele două cazuri posibile:\r\n\r\n1. Dacă elementele de indice $x$ şi $y$ aparţin aceleiaşi subsecvenţe, atunci putem găsi ceea ce căutăm folosind algoritmul liniar direct pe şirul $a[x..y]$ (complexitate $O(n/k)$).\r\n\r\n2. Dacă nu sunt în aceeaşi secvenţă, atunci vom împărţi şirul $a[x..y]$ în:\r\n\r\n* un prefix de subsecvenţă din cele ce aparţin partiţionării,\r\n\r\n* un sufix de subsecvenţă,\r\n\r\n* zero sau mai multe subsecvenţe complete ce aparţin partiţionării,\r\n\r\ndupă care rezolvăm problema pentru sufix şi prefix prin metoda liniară în $O(n/k)$, şi determinăm în $O(1)$ pentru fiecare bucată în care este spart şirul $a[x..y]$ subsecvenţa ei de sumă maximă.\r\n\r\nMai rămâne să găsim subsecvenţa de sumă maximă cu capătul în bucăţi diferite. Pentru două bucăţi fixate $i <= j$, subsecvenţa de sumă maximă ce are câte un capăt în fiecare bucatăm are valoarea $max[j] - min[i]$. Determinarea subsecvenţei de sumă maximă cu capetele în bucăţi diferite devine astfel de complexitate $O(k)$. Deci pentru a rezolva o întrebare trebuie să facem $O(n/k + k)$ calcule. Pentru a reduce complexitatea problemei considerăm pe $k = sqrt(n)$. Complexitatea totală a acestei soluţii este $O(N + M sqrt(N))$.\r\n\r\nSă vedem ce se întâmplă pe exemplu:\r\n\r\n|_. $a$ | - | $-1$ | $2$ | $3$ | $-2$ | $4$ | $-3$ | $8$ | $-3$ | $1$ |\r\n|_. $sum$ | $0$ | $-1$ | $1$ | $4$ | $2$ | $6$ | $3$ | $11$ | $8$ | $9$ |\r\n\r\nŞirul e împărţit în trei subsecvenţe $[-1, 2, 3], [-2, 4, -3], [8, -3, 1]$:\r\n\r\n|_. $max$ | $4$ | $6$ | $11$ |\r\n|_. $min$ | $-1$ | $2$ | $8$ |\r\n|_. $best$ | $5$ | $4$ | $8$ |\r\n\r\nPentru a răspunde la întrebarea $[1, 5]$ trebuie să răspundem la cele două subsecvenţe componente $[1..3]$ şi $[4..5]$. Soluţia optimă pentru $[1..3]$ este $best[&#49;] = 5$. Soluţia optimă pentru $[4..5]$ o determinăm folosind algoritmul liniar, ea fiind $4$. Acum, pentru a determina subsecvenţa de sumă maximă cu câte un capăt în fiecare interval folosim formula $max(sum[i]) - min(sum[j-1])$, unde $4 <= i <= 5$ şi $1 <= j <= 3$. Valoarea $max(sum[i])$ o găsim parcurgând intervalul $[4, 5]$ ca fiind $6$, iar valoarea $min(sum[j-1])$ o avem deja calculată în $min[&#49;]$. De aici obţinem rezultatul $7$.\r\n\r\nO soluţie similară poate fi obţinută cu ajutorul arborilor de intervale. Mai întâi creăm arborele de intervale. Pentru fiecare interval aflăm elementele $min$, $max$ şi $best$ astfel:\r\n\r\n* $min[x..y] = minim(min[x..(x+y)/2], min[(x+y)/2 + 1 .. y])$;\r\n\r\n* $max[x..y] = maxim(max[x..(x+y)/2], max[(x+y)/2 + 1 .. y])$;\r\n\r\n* $best[x..y] = maxim(best[x..(x+y)/2], maxim(best[(x+y)/2 + 1 .. y], max[(x+y)/2 + 1 .. y] - min[x..(x+y)/2]))$.\r\n\r\nAcum pentru a răspunde la întrebările din problemă fiecare interval va fi împărţit în $O(log N)$ subintervale canonice care apar în arborele de intervale. Apoi printr-o parcurgere asemănătoare celei din rezolvarea anterioară se poate obţine rezultatul pentru fiecare întrebare în $O(log N)$. Soluţia va avea complexitatea $O(N + M log N)$.\r\n\r\nÎn următorul desen observăm structura unui arbore de intervale pentru un şir cu $16$ elemente. Daca se pune întrebarea $[2, 11]$ acest interval va fi spart în intervalele $[2, 2], [3, 4], [5, 8], [9, 10], [11, 11]$.\r\n\r\n!probleme-cu-secvente?numere2.png!\r\n\r\nPrezentăm procedura de construire a arborelui, implementată în _java_:\r\n\r\n== code(java) |\r\npublic void build_tree(int index, int low, int high) {\r\n    if (low == high) {\r\n        if (low != 0) aint[index] = new Node(low, high, a[low] - a[low - 1], a[low], a[low]);\r\n        else aint[index] = new Node(low, high, 0, 0, 0);\r\n    }\r\n    else {\r\n        aint[index] = new Node(low, high, -INFINIT, -INFINIT, INFINIT);\r\n        int mid = (low + high) / 2;\r\n        build_tree(2 * index, low, mid);\r\n        build_tree(2 * index + 1, mid + 1, high);\r\n        aint[index].maxS = Math.max(aint[2 * index].maxS,Math.max(aint[2 * index + 1].maxS,aint[2 * index + 1].max - aint[2 * index].min));\r\n        aint[index].max = Math.max(aint[2 * index].max,aint[2 * index + 1].max);\r\n        aint[index].min = Math.min(aint[2 * index].min,aint[2 * index + 1].min);\r\n    }\r\n}\r\n==\r\n\r\nŞi procedura care răspunde la întrebări tot în _java_:\r\n\r\n== code(java) |\r\nlong minPrefix; \r\nint x, y;\r\npublic long queryTree(int index, int low, int high) {\r\n    if (x <= low && high <= y) {\r\n        long maxRet = aint[index].maxS;\r\n        if (minPrefix != infinity) {\r\n            maxRet = Math.max(maxRet, aint[index].max - minPrefix);\r\n        }\r\n        minPrefix = Math.min(minPrefix, aint[index].min);\r\n        return maxRet;\r\n    }\r\n    else {\r\n        int mid = (low + high) / 2;\r\n        if (x <= mid && mid < y) return  Math.max(queryTree(2 * index, low, mid), queryTree(2 * index + 1, mid + 1, high));\r\n        else if (x > mid) return queryTree(2 * index + 1, mid + 1, high);\r\n            else return queryTree(2 * index, low, mid);\r\n    }\r\n}\r\n==\r\n\r\nAutorul vă recomandă articolele [1] şi [2] pentru o înţelegere mai profundă a structurii de date numită arbori de intervale. Problema poate fi soluţionată şi în $O(N + M)$, dar algoritmul este mult prea complicat pentru un concurs de programare; cei interesaţi pot să îl găsească în [4].\r\n\r\nh2(#prob4). Problema 4 (ACM ICPC NWERC 97, olimpiada online 2000, campion 2001)\r\n\r\nSe dă un şir $(a{~1~}, a{~2~}, ..., a{~N~})$ format din numere întregi. Se cere să se determine subsecvenţa $a[i..j]$ care are modulul sumei elementelor minim.\r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(2, 8, -6, -6, 9, 4, -3)$, subsecvenţa este $(4, -3)$, având suma în modul $1 = |4 - 3|$.\r\n\r\nh3. Rezolvare:\r\n\r\nFacem mai întâi şirul sumelor parţiale. Pentru oricare două elemente $sum[i]$ şi $sum[j]$ cu $(i != j)$ modulul sumei unei subsecvenţe din şir va fi $|sum[i] - sum[j]|$. Dacă $i < j$, atunci secvenţa va fi $a[i+1..j]$, iar dacă $j < i$, atunci secvenţa va fi $a[j+1 .. i]$. Astfel, pentru a găsi subsecvenţa de modul minim trebuie, de fapt, să găsim perechea de indici $i$ şi $j$ astfel ca $|sum[i] - sum[j]|$ să fie minim. Sortând şirul sumelor parţiale şi luând o pereche de indici $i < j$, atunci $sum[i] < sum[j]$, iar $|sum[j] - sum[i]| = sum[j] - sum[i]$. Pentru a găsi perechea $(i, j)$ pentru care $i < j$ şi $sum[j] - sum[i]$ este minim, trebuie ca $i$ să fie egal cu $j + 1$. Astfel obţinem un algoritm de complexitate $O(N log N)$.\r\n\r\nSă vedem cum merge pe exemplul prezentat:\r\n\r\n|_. $a$ | - | $2$ | $8$ | $-6$ | $-6$ | $9$ | $4$ | $-3$ |\r\n|_. $sum$ | $0$ | $2$ | $10$ | $4$ | $-2$ | $7$ | $11$ | $8$ |\r\n|_. $ind$ | $0$ | $1$ | $2$ | $3$ | $4$ | $5$ | $6$ | $7$ |\r\n\r\nÎn şirul $ind$ vom păstra indicii reali ai sumelor parţiale. După sortare avem:\r\n\r\n|_. $sum$ | $-2$ | $0$ | $2$ | $4$ | $7$ | $8$ | $10$ | $11$ | \r\n|_. $ind$ | $4$ | $0$ | $1$ | $4$ | $5$ | $7$ | $2$ | $6$ |\r\n\r\nO secvenţă de modul $2$ ar fi cea reprezentată de sumele $8$ şi $10$, cu indicii $7$ şi $2$. Această secvenţă este $(-6, -6, 9, 4, -3)$. Observăm ca cea mai mică diferenţă între termeni consecutivi e cea dintre $8$ şi $7$, care au indicii $7$ şi $5$, de unde obţinem că subsecvenţa de modul minim este $(4, -3)$. \r\n\r\nh2(#prob5). Problema 5 (USACO)\r\n\r\nSe dă un şir $(a{~1~}, a{~2~}, ..., a{~N~})$ format din $N (1 <= N <= 100 000)$ numere întregi $(1 <= a{~i~} <= 2 000)$. Se cere să se determine subsecvenţa $a[i..i + K - 1]$ cu media aritmetică a elementelor maximă $(K >= F, 1 <= F <= N)$. \r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(6, 4, 2, 10, 3, 8, 5, 9, 4, 1)$ şi $F = 6$ soluţia optimă este $(10, 3, 8, 5, 9, 4)$, cu media $6.5$.\r\n\r\nh3. Rezolvare:\r\n\r\nFie $X$ un număr real. Considerând şirul $b$, obţinut prin transformarea $b{~i~} = a{~i~} - X$, atunci toate subsecvenţele şirului $b$ vor avea valoarea mediei elementelor lor cu $X$ mai mică decât valoarea subsecvenţelor corespunzătoare din şirul $a$. Observăm apariţia a trei cazuri:\r\n\r\n* Dacă subsecvenţa de sumă maximă din $b$ are valoarea mai mare ca $0$, atunci şi media ei va fi mai mare ca $0$. Rezultă astfel că şi media subsecvenţei corespunzătoare din şirul $a$ va fi mai mare decât $X$, deci media maximă a unei subsecvenţe din $a$ va fi mai mare ca $X$. \r\n\r\n* Cand subsecvenţa de sumă maximă din şirul $b$ are media mai mică decât $0$, atunci orice subsecvenţă din şirul $a$ va avea media mai mică decât $X$. \r\n\r\n* În cazul în care subsecvenţa de sumă maximă a şirului $b$ are valoarea egală cu zero, atunci subsecvenţa de medie maximă a şirului $a$ are media $X$.\r\n\r\nAstfel putem face o căutare binară pentru a determina valoarea $X$ a mediei maxime. Ne mai rămâne să determinăm un algoritm eficient pentru găsirea subsecvenţei de sumă maximă de lungime cel puţin $F$. O asemenea soluţie urmăreşte una din ideile din prima problemă: fie $best[i]$ subsecvenţa de sumă maximă ce se termină în $a[i]$. Evident $best[i] = max(a[i], best[i - 1] + a[i])$. Acum secvenţa de sumă maximă ce se termină în $a[i]$, de lungime cel puţin $F$ se găseşte ca $a[i] + a[i - 1] + .. + a[i - F + 2] + best[i - F + 1]$. Această relaţie poate fi calculată în $O(1)$ dacă ne folosim de trucul sumelor parţiale. Complexitatea finală este $O(N log C)$, unde $C$ e valoarea maximă a lui $a{~i~}$.\r\n\r\nh2(#prob6). Problema 6 (\'Secvenţă\':problema/secventa)\r\n\r\nGigel are un şir de $N$ numere întregi. Toată lumea ştie că o secvenţă este un subşir de numere care apar pe poziţii consecutive în şirul iniţial. Gigel a definit baza unei secvenţe ca fiind minimul valorilor elementelor din secvenţa respectivă. Fiind dat un număr natural $K$, determinaţi pentru Gigel o secvenţă de lungime cel puţin $K$, cu baza maximă. $(1 <= K <= N <= 500 000)$\r\n\r\nh3. Exemplu:\r\n\r\nPentru $K = 3$ şi şirul $(-1, 2, 3, 1, 0, 4, 8, 6)$, secvenţa de bază maximă este $(4, 8, 6)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPresupunem că orice secvenţă optimă ar avea lungimea mai mare decât $K$. Atunci putem obţine o secvenţă mai mică, cu aceeaşi bază eliminând unul din capetele unei secvenţe optime. Deci este de ajuns să cautăm secvenţele optime de lungime exact $K$.\r\n\r\nAcum putem face o parcurgere a şirului pentru a rezolva problema. Mai întâi punem într-un $min-heap$ $K$ elemente, verificăm vârful heapului şi obţinem astfel minimul secvenţei $a[1..k]$. Apoi eliminăm elementul $a[&#49;]$ din heap şi inserăm elementul $a[K+1]$. Prin verificarea vârfului heapului obţinem minimul secvenţei $a[2..K+1]$. Continuăm procedeul până aflăm elementul minim pentru fiecare subsecvenţă de lungime $K$ a şirului $a$ (complexitate $O(N log N)$). Există şi alte soluţii pentru găsirea elementului minim al unei subsecvenţe, precum folosirea unui arbore de intervale sau folosirea tehnicii $O(N log N)/O(1)$ pentru problema _RMQ_, dar obţinem tot soluţii de complexitate $O(N log N)$.\r\n\r\nO observaţie importantă este aceea că dacă vrem să vedem minimul secvenţei ce se termină în $i$ şi avem $j{~1~} < j{~2~} <= i$ şi $a[j{~1~}] >= a[j{~2~}]$, atunci evident $a[j{~1~}]$ nu va fi minimul secvenţei ce se termină în $i$. Folosim o structură de date ca la soluţia cu heapuri, care adaugă elemente noi şi şterge elemente vechi, dar pe lângă elementele ce au fost inserate acum $k$ paşi şi trebuie şterse, mai ştergem şi elementele mai noi care nu ne vor mai fi utile, după cum este $a[j{~2~}]$ mai sus. Ca structură de date folosim o listă în care putem insera şi şterge de la ambele capete, un _deque_. Fiecare element inserat în deque va fi o pereche de valori, valoarea din şir şi indexul din şir $(a[i], i)$. Când o valoare este inserată în şir, ea este pusă la capătul din dreapta al şirului, dar înainte de inserare cât timp elementul din capătul şirului are valoarea mai mare decât $a[i]$ el este eliminat. La fiecare pas după o inserţie se verifică dacă elementul din capătul din stânga este mai bătrân de $K$ iteraţii.\r\n\r\nDin cauza modului în care se fac inserţiile şi ştergerile, şirul va fi sortat totdeauna crescător după indecşi şi crescător după valori. Tot timpul ultimul element din stivă va conţine valoarea bazei. Acest algoritm are complexitatea $O(N)$ pentru că fiecare element este inserat şi şters din deque cel mult o dată.\r\n\r\nSă vedem cum funcţionează rezolvarea pe un exemplu : $a = (-1, 2, 3, 1, 0, 4, 8, 6)$\r\n\r\n* inserăm $(-1, 1)$\r\nlista devine: $(-1, 1)$\r\n \r\n\r\n* inserăm $(2, 2)$\r\nlista devine: $(-1, 1) (2, 2)$\r\n\r\n\r\n* inserăm $(3, 3)$\r\nlista devine: $(-1, 1) (2, 2) (3, 3)$\r\nelementul minim al secvenţei $a[1..3]$ este $-1$\r\n\r\n\r\n* inserăm $(1, 4)$\r\nştergem $(3, 3)$ şi $(2, 2)$\r\nştergem $(-1, 1)$ ( inserat acum $4$ paşi )\r\nlista de vine: $(1, 4)$\r\nelementul minim al secvenţei $a[2..4]$ este $1$\r\n\r\n\r\n* inserăm $(0, 5)$\r\nştergem $(1, 4)$\r\nlista devine: $(0, 5)$\r\nelementul minim al secvenţei $a[3..5]$ este $0$.\r\n\r\n\r\n* inserăm $(4, 6)$\r\nlista devine: $(0, 5) (4, 6)$\r\nelementul minim al secvenţei $a[4..6]$ este $0$\r\n\r\n\r\n* inserăm $(8, 7)$\r\nlista devine: $(0, 5) (4, 6) (8, 7)$\r\nelementul minim al secvenţei $a[5..7]$ este $0$\r\n\r\n\r\n* inserăm $(6, 8)$\r\nştergem $(8, 7)$\r\nştergem $(0, 5)$ ( inserat acum $4$ paşi )\r\nlista devine: $(4, 6) (6, 8)$\r\nelementul minim al secvenţei $a[6..8]$ este $4$\r\n\r\nh2(#prob7). Problema 7 (Agricultura, Algoritmus)\r\n\r\nVasilica vrea să se apuce de agricultură şi, prin urmare, să cumpere o parcelă de teren. Harta pusă la dispoziţie de către primăria oraşului în care locuieşte Vasilică se poate reprezenta sub forma unei matrice de dimensiuni $N x M (2 <= N, M <= 150)$, fiecare $m^2^$ de teren fiind reprezentat printr-un element din matrice. Pentru fiecare $m^2^$ de pământ se cunoaşte altitudinea (faţă de nivelul mării) la care se află acesta. Agricultorul nostru doreşte să cumpere o parcelă de formă dreptunghiulară dar, deoarece are de gând să se ocupe de culturi foarte pretenţioase la modificări de nivel, diferenţa dintre valorile care indică altitudinea maximă şi cea minimă din parcelă trebuie să fie mai mică decât o valoare dată $K (1 <= K <= 1 000)$. Mai mult, suprafaţa pe care Vasilică o va achiziţiona trebuie să fie cât mai mare posibil.\r\n\r\nh3. Exemplu:\r\n\r\nDe exemplu pentru $K = 3$ şi matricea <tex>\\[ \\left( \\begin{array}{cccccc}1 & 1 & 3 & 1 & 2 & 7 \\\\9 & 2 & 3 & 2 & 3 & 2 \\\\7 & 8 & 2 & 3 & 1 & 5 \\\\4 & 5 & 6 & 0 & 1 & 4 \\end{array} \\right)\\]</tex>, soluţia optimă va avea $9$ celule.\r\n\r\nh3. Rezolvare:\r\n\r\nProblema constă în determinarea submatricei cu număr maxim de celule în care diferenţa între valoarea maximă şi valoarea minimă este mai mică decât $K$. Vom folosi ideea de la problema cu subsecvenţa de sumă maximă pe matrice, adică vom fixa două linii $i{~1~}$ şi $i{~2~}$. Acum pentru fiecare coloană $j$ păstrăm în $m[j]$ elementul minim şi în $M[j]$ elementul maxim $a[i][j]$ cu $i{~1~} <= i <= i{~2~}$. Astfel la fiecare pas trebuie acum să rezolvăm problema determinării unei subsecvenţe de lungime maximă pentru care diferenţa între elementul maxim şi minim este mai mică decât $K$. Folosind un _max-heap_ şi un _min-heap_ putem parcurge elementele şirurilor $M$ şi $m$ în ordine inserând la fiecare pas elemente în heap şi determinând cea mai lungă secvenţă ce se termină în $i$ cu proprietatea dată. Vom ţine un al 2-lea indice $j$, iniţial $0$, care atâta timp cât diferenţa între elementul maxim din max-heap cu elementul minim din min-heap este mai mare sau egală cu $K$, vom scoate din heapuri elementele $M[j]$, respectiv $m[j]$ şi îl vom incrementa pe $j$ ( complexitate $O(N^3^ log N)$ ). Dacă în loc de heapuri folosim deque-uri, atunci acest algoritm va avea complexitatea $O(N^3^)$.\r\n\r\nh2(#prob8). Problema 8 (\'Secvenţa 2\':problema/secv2)\r\n\r\nGigel s-a decis să devină olimpic la informatică, poate aşa va reuşi să-şi rezolve singur problemele, şi nu va mai cere ajutorul vostru! La ora de informatică, profesoara lui i-a dat să rezolve problema secvenţei de sumă maximă: \"Gigele, eu iţi dau un şir de $N$ numere întregi, iar tu trebuie să găseşti o secvenţă ( adică un subşir de numere care apar pe poziţii consecutive în şirul iniţial ) cu suma elementelor maximă!\". După vreo $30$ de minute, Gigel s-a ridicat mândru şi a zis: \"Am găsit algoritmul de complexitate optimă, doamna profesoară!\". Ca temă pentru acasă Gigel are de rezolvat aproape aceeaşi problemă: trebuie să găsească secvenţa de sumă maximă de lungime cel puţin $K (1 <= k <= N <= 50 000)$. Gigel încă nu ştie destul de multă informatică ca să poata rezolva această problemă, dar poate îl ajutaţi voi! Scrieţi un program care rezolvă problema din tema lui Gigel.\r\n\r\nh3. Exemplu:\r\n\r\nDe exemplu pentru şirul $(0, -6, 2, 1, 4, -1,  3, -5)$ şi $K = 3$, soluţia optimă este $(2, 1, 4, -1, 3)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPutem folosi rezolvarea liniară bazată pe programare dinamică prezentată ca subalgoritm în soluţia problemei $5$, dar putem simplifica logica din acea rezolvare. Vom folosi şirul sumelor parţiale $sum$, iar pentru a determina subsecvenţa de sumă maximă ce se termină în $i$ şi are lungimea cel puţin $K$ trebuie să găsim $sum[j]$ minim astfel ca $j < i - K$. Parcurgem lista, şi la pasul $i$ determinăm $best[i] = sum[i] - min(sum[j])$, $j < i - K$. Comparăm minimul curent cu $sum[i-K]$ şi trecem la pasul următor. Complexitate: $O(N)$.\r\n\r\nh2(#prob9). Problema 9 (\'Sum\':problema/sum2, Stelele Informaticii 2003 )\r\n\r\nSe dă un şir de numere întregi. Se caută un subşir cu lungimea cuprinsă între $L$ şi $U$, format din elemente consecutive ale şirului iniţial, cu suma elementelor maximă $(1 <= L <= U <= N <= 100 000)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPentru fiecare $i$ este de ajuns să aflăm valoarea expresiei $sum[i] - sum[j]$, unde $i - L > j >= i - U$. Pentru a determina valoarea optimă pentru $sum[j]$ putem folosi un heap de dimensiune $U - L$, sau putem folosi tehnici de determinare a valorii minime într-un interval dat ( complexitate $O(N log (U - L)$ ) ).\r\n\r\nAltă abordare de aflare a minimelor unor secvenţe de lungime dată (în cazul acesta lungimea este $U - L$ ) a fost prezentată în rezolvarea \'problemei $6$\':probleme-cu-secvente@prob6. Folosind acea tehnică obţinem o rezolvare de complexitate liniară.\r\n\r\nO altă rezolvare frumoasă prezentată în [4] este următoarea: spunem că o secvenţă este negativă spre stânga dacă suma oricărui prefix ( în afară de secvenţa în sine ) al secvenţei este negativ sau zero. O partiţie a secvenţei $A = (A{~1~}, A{~2~}, ..., A{~k~})$ este minimală negativă spre stânga dacă fiecare $A{~i~}$ este negativă spre stânga, iar suma elementelor lui $A{~i~}$ este strict pozitivă dacă $i != k$. De exemplu secvenţa $(-4, 1, -2, 3)$ este negativă la stânga, pe când secvenţa $(5, -3, 4, -1, 2, -6)$ nu este. Partiţia $(5) (-3, 4) (-1, 2) (-6)$ este minimală negativă la stânga.\r\n\r\nPentru fiecare element din partiţie ţinem minte un pointer $p[i]$ spre ultimul element din subsecvenţa din care face parte. Fiecare interval $[i, p[i]]$ va corespunde celei mai scurte subsecvenţe care începe în $i$ şi are suma pozitivă. Pentru a determina o soluţie a problemei pentru fiecare $i$ din care poate începe o subsecvenţă de sumă maximă, ne vom plimba cu un pointer $j$ astfel ca $j$ să fie cât mai depărtat de $i$ şi $j - i + 1 <= U$. Obţinem astfel de fiecare dată o subsecvenţă de sumă maximă ce începe în $i$, cu lungimea mai mică sau egală cu $U$. Indicele $j$ va fi întotdeauna un capăt de secvenţă negativă la stânga şi la fiecare mărire a lui $i$ verificăm dacă lui $j$ îi putem atribui valoarea $p[j + 1]$ ( adică dacă $p[j + 1] - i + 1 <= U$ ). Dacă secvenţa de sumă maximă de lungime cel mult $U$ ce începe în $i$ are lungimea mai mică decât $L$, atunci secvenţa de sumă maximă cu lungimea cuprinsă între $L$ şi $U$ are lungimea exact $L$. Complexitate: $O(N)$.\r\n\r\nh2(#prob10). Problema 10 (\'Secvenţa 3\':problema/secv3)\r\n\r\nGigel este o persoană cu o imaginaţie foarte bogată, mai ales când doarme! Într-o noapte a visat că are de îndeplinit o sarcină foarte bizară: trebuie să aleagă o secvenţă (adica un subşir de elemente care apar pe poziţii consecutive în şirul iniţial) din $N$ elemente pentru care se cunosc costul şi timpul. Secvenţa aleasă trebuia să fie de lungime minim $L$ şi maxim $U$, iar suma costurilor elementelor secvenţei împărţiţă la suma timpurilor elementelor secvenţei să fie maximă $(1 <= L <= U <= N <= 30 000)$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru $L = 1, R = 2$ şi şirurile $c = ( 1, 1, 3, 2, 5 )$ şi $t = ( 4, 2, 5, 3, 6 )$, subsecvenţa cea mai eficientă are costul $0.83$.\r\n\r\nh3. Rezolvare:\r\n\r\nProcedăm ca la problema $5$ şi căutăm binar valoarea optimă. Şirul va fi transformat în $b[i] = c[i] - t[i] * X$. Acum trebuie să mai rezolvăm subproblema care cere să determinăm o subsecvenţă de sumă maximă pentru care lungimea se află între $L$ şi $U$. Această subproblemă a fost soluţionată în problema anterioară, unde s-a găsit un algoritm liniar. Astfel soluţia acestei probleme are complexitatea $O(N log C)$.\r\n\r\nh2(#prob11). Problema 11 (\'XorMax\':problema/xormax)\r\n\r\nPaftenie este un elev eminent. De multe ori îşi pune întrebări care au sau nu răspunsuri. De data aceasta i-a venit o idee nouă. El are un şir de $N$ numere întregi nenegative şi vrea să aleagă o secvenţă a şirului $(a{~i~}, a{~i+1~}, ..., a{~j~})$ astfel încât $a{~i~} xor a{~i+1~} xor ... xor a{~j~}$ să fie maxim ({$1 <= N <= 100 000$}, numerele şirului sunt strict mai mici decât $221$ ).\r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(1, 0, 5, 4, 2)$, secvenţa cu valoarea sumei _xor_ maximă este $(4, 2)$, cu suma $6$. \r\n\r\nh3. Rezolvare:\r\n\r\nSuma _xor_ a două numere este de fapt adunare binară fără transport, fapt care o face similară operaţiei _modulo_. Problema e asemănătoare cu cea a subsecvenţei de modul maxim. Vom obţine toate sumele _xor_ parţiale şi pentru a vedea pentru $sum[i]$ perechea optimă cu care crează o sumă cât mai mare trebuie să găsim acea sumă $sum[j]$ astfel că fiecare bit al lui $sum[i]$ să fie diferit de fiecare bit al lui $sum[j]$, dacă acest lucru este posibil. Pentru a face această căutare cât mai eficientă, putem menţine sumele $sum[i]$ ca şiruri de caractere $0$ sau $1$ într-un _trie_ [5]. Structura de trie pentru cazul când alfabetul are dimensiunea $2$ este identică cu cea de heap. Această soluţie are complexitatea $O(N log C)$.\r\n\r\nh2(#probp). Probleme propuse\r\n\r\nPentru a vă însuşi mai bine tehnicile învăţate în acest articol, autorul vă sugerează să rezolvaţi următoarele două probleme:\r\n\r\n* \'Balans\':problema/balans\r\n* \'Struţi\':problema/struti\r\n* \'Deque\':problema/deque\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n1. Lica Dana, _Arbori de intervale (Segment Trees)_, GInfo 15/4\r\n2. Negruşeri Cosmin, _Căutări Ortogonale, Structuri de date şi aplicaţii_, GInfo 15/5\r\n3. Takaoka T., _Efficient Algorithms for the Maximum Subarray Problem by Distance Matrix Multiplication_\r\n4. Kuan Yu Chen, Kun Mao Chao, _On the Range Maximum-Sum Segment Query_\r\n5. Yaw Ling Liu, Tao Jiang, Kun Mao Chao, _Efficient Algorithms for Locating the Length-Constrained Heaviest Segments, with Applications to Biomolecolar Sequence Analysis_\r\n6. Vladu Adrian, Negruşeri Cosmin, Ginfo Noiembrie 2005\r\n7. T. H. Cormen, C. E. Leiserson, R. R. Rivest - \'_Introducere in Algoritmi_\':http://zhuzeyuan.hp.infoseek.co.jp/ita/toc.htm\r\n',3146,'public',NULL,NULL),('planificare/sedinta-20090112','Sedinta 2009-01-12','2009-01-05 15:03:20','2009-01-07 19:16:00','h1. Sedinta 2009-01-12\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe intalnim *luni, 12 ianuarie* la ora *?* la *?*\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== - pe seara as prefera\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")== - ar fi mai bine mai spre 16:00 si nu la retro cafe\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== - as prefera dupa 18:30\r\n* ==user(user=\"prostu\" type=\"tiny\")== - as prefera dupa 16:00\r\n* ==user(user=\"stef2n\" type=\"tiny\")== - prezent doar daca nu are loc in intervalul 18-20, din cauza unei lucrari\r\n* ==user(user=\"gcosmin\" type=\"tiny\")== - ar merge mai spre seara (dupa 6:30-7:00 asa)\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinta anterioara\':planificare/sedinta-20081125| ==user(user=\"domino\" type=\"tiny\")==|\r\n| Algoritmiada (sponsorizari)| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n| OKR-uri (Q4 2008 si Q1 2009)|  ==user(user=\"domino\" type=\"tiny\")== |\r\n| Coding camp |  ==user(user=\"domino\" type=\"tiny\")== |\r\n| \'IAP 11\':propuneri/11-rating | ==user(user=\"bogdan2412\" type=\"tiny\")== |\r\n| \'IAP 10\':propuneri/10-virtual-contest | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Stelele |  ==user(user=\"silviug\" type=\"tiny\")== |\r\n| ONIbyNET si sistem de submit | ==user(user=\"domino\" type=\"tiny\")== |\r\n| Fix it week/camp | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| Misc | ==user(user=\"silviug\" type=\"tiny\")== |\r\n\r\nh3. Detalii\r\n\r\n* Stelele:\r\n** Go international: desi la stadiul de idee, Ali se gandeste sa invite bulgarii cei mai tari la stele; ce-ar presupune asta din partea noastra?\r\n** Va avea loc in vacanta inter-semestriala (perioada 31 ianuarie - 7 februarie)\r\n** Masuri de securitate, probleme cu adminii (Bogdan are parola pe live) \r\n* Fix it week/camp:\r\n** Scop: imbogatirea si imbunatatirea continutului site-ului, implicarea comunitatii in activitatile noastre, identificarea de noi colaboratori \"de baza\"\r\n** Fix it week: declararea unei saptamani in care toata comunitatea trage tare pentru content; cel mai simplu exemplu sunt articole de transcris; putem include si task-uri mai specializate ca finalizarea de probleme in arhiva [educationala]?, documentatie pentru diverse parti din site, etc.\r\n** Fix it camp: in paralel sau ca alternativa la fix it week; membrii infoarena se imbraca in salopete cu harlete in spate si se aduna intr-un loc prestabilit; chemam membrii comunitatii care vor sa se implice si \"plantam\" articole, documentatie, etc. o zi sau un week-end intr-o locatie precum ICHB. \r\n** In sedinta aceasta as dori sa primesc feedback si sugestii noi despre:\r\n*** Forma acestui eveniment: week or/and camp or/and ??\r\n*** Ce putem realiza cu un astfel de eveniment? (in materie de continut si implicare a comunitatii; care din scopuri sunt SF?)\r\n*** Ma ofer (Silviu) eu sa organizez evenimentul in Q1-09, intr-o forma in care cadem cu totii de acord. \r\n* Misc:\r\n** Silviu: De ce nu avem (inca) comentarii la articole? Mai sunt alte pagini la care am vrea comentarii (in stil de blog)?\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n...\r\n\r\nh2. Notite\r\n\r\n...',1851,'public',NULL,NULL),('probleme-cu-secvente','Probleme cu secvențe','2008-11-23 19:46:37','2009-01-09 22:20:16','h1. Probleme cu secvenţe\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"alecman\") ==\r\n\r\n(Categoria _Algoritmi şi tehnici de programare_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut*\r\n* \'Introducere \':probleme-cu-secvente#introducere\r\n* \'Problema 1 (Subsecvenţa de sumă maximă) \':probleme-cu-secvente#problema-1\r\n* \'Problema 2 (Maximum Sum) \':probleme-cu-secvente#problema-2\r\n* \'Problema 3 (SequenceQuery) \':probleme-cu-secvente#problema-3\r\n* \'Problema 4 \':probleme-cu-secvente#problema-4\r\n* \'Problema 5 \':probleme-cu-secvente#problema-5\r\n* \'Problema 6 (Secvenţă) \':probleme-cu-secvente#problema-6\r\n* \'Problema 7 (Agricultura) \':probleme-cu-secvente#problema-7\r\n* \'Problema 8 (Secvenţa 2) \':probleme-cu-secvente#problema-8\r\n* \'Problema 9 (Sum) \':probleme-cu-secvente#problema-9\r\n* \'Problema 10 (Secvenţa 3) \':probleme-cu-secvente#problema-10\r\n* \'Problema 11 (XorMax) \':probleme-cu-secvente#problema-11\r\n* \'Probleme propuse\':probleme-cu-secvente#probleme-propuse\r\n* \'Bibliografie\':probleme-cu-secvente#bibliografie\r\n\r\nh2(#introducere). Introducere\r\n\r\nAcest articol prezintă o serie de probleme înrudite cu problema subsecvenţei de sumă maximă, însoţite de rezolvări eficiente. Problemele prezentate pot apărea oricând ca subprobleme în concursurile de programare, studierea lor mărind în mod util bagajul de cunoştinţe al unui elev pasionat de algoritmică.\r\n\r\nh2(#problema-1). Problema 1 (Subsecvenţa de sumă maximă)\r\n\r\nbq. Se dă un şir de $N$ numere întregi $(a{~1~}, a{~2~}, ..., a{~N~})$. Să se determine o subsecvenţă $(a{~i~}, a{~i+1~}, ..., a{~j~})$ care să aibă suma maximă.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(-1, 2, 3, -4, -2, 2, 1, -3, -2, -3, -4, 9, -2, 1, 7, 8, -19, -7, 2, 4, 3)$, o subsecvenţă de sumă maximă este $(9, -2, 1, 7, 8)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPrima rezolvare care ne vine în minte are complexitatea $O(N^3^)$ şi constă în determinarea sumei fiecărei subsecvenţe posibile şi reţinerea maximului acestor sume. Este evident că anumite sume parţiale sunt calculate de mai multe ori.\r\n\r\nPutem reduce complexitatea la $O(N^2^)$ ţinând cont de faptul că suma subsecvenţei $a[i..j]$ este egală cu suma subsecvenţei $a[i..j-1]$, la care se adună $a[j]$. Păstrăm într-un şir $sum[i]$ suma elementelor din subsecvenţa $a[1..i]$. Pentru a determina suma elementelor din subsecvenţa $a[i..j]$ facem diferenţa: $sum[i] - sum[j-1]$.\r\n\r\nIdeea poate fi rafinată calculând pentru fiecare indice $i$ numărul $best[i]$, reprezentând subsecvenţa de sumă maximă cu capătul drept în $i$. Este uşor de observat că $best[i] = max(sum[i] - sum[j-1])$, unde $j$ ia valori de la $1$ la $i$. Relaţia anterioară se mai poate scrie: $best[i] = sum[i] - min(sum[j-1])$. Obţinem astfel un algoritm liniar care ne determină subsecvenţa de sumă maximă cerută.\r\n\r\n== code(cpp) |\r\nsum[0] = 0;\r\nfor (i = 1; i <= N; i++) sum[i] = a[i] + sum[i-1];\r\nmin = sum[0];\r\nbestSum = -INFINIT;\r\nfor (i = 1; i <= N; i++) {\r\n    best[i] = sum[i] - min;\r\n    if (min > sum[i]) min = sum[i];\r\n    if (bestSum < best[i]) bestSum = best[i];\r\n}\r\n==\r\n\r\nO altă metodă de calcul poate fi dedusă folosind paradigma _Divide et Impera_. La fiecare pas împărţim şirul în jumătate şi aflăm subsecvenţele de sumă maximă din cele două jumătăţi. După aceea trebuie să găsim subsecvenţa de sumă maximă ce are un capăt în fiecare din cele două jumătăţi ale sirului. Pentru aceasta alipim sufixul de sumă maximă a primei jumătăţi cu prefixul de sumă maximă a celei de a doua.\r\n\r\n== code(cpp) |\r\nint getMaxSubsequence(int l, int r) {\r\n    if (l == r) return a[l];\r\n    mid = (l + r) / 2;\r\n    bestL = getMaxSubsequence(l, mid);\r\n    bestR = getMaxSubsequence(mid + 1, r);\r\n    suf = 0; \r\n    pre = 0; \r\n    maxSuf = -INFINIT; \r\n    maxPre = -INFINIT;\r\n    for (i = mid; i >= l; i--) {\r\n        suf += a[i];\r\n        if (maxSuf < suf) maxSuf = suf;\r\n    }\r\n    for (i = mid + 1; i <= r; i++) {\r\n        pre += a[i];\r\n        if (maxPre < pre) maxPre = pre;    \r\n    }\r\n    return max(bestL, max(bestR, maxPre + maxSuf));\r\n}\r\n==\r\n\r\nO idee bazată pe paradigma programării dinamice ar fi să folosim un şir $best[i]$, reprezentând suma maximă a unei subsecvenţe ce se termină în $a[i]$. Problema se rezolvă cu următoarea formulă de recurenţă: $best[i] = max(a[i], best[i-1] + a[i])$. Formula poate fi demonstrată prin inducţie matematică.\r\n\r\nO ultimă idee ar fi să partiţionăm şirul în subsecvenţe încât fiecare să aibă ambele capete cât mai mici posibile şi suma elementelor subsecvenţei să fie negativă. Pentru exemplul dat avem următoarea partiţionare: $[-1], [2, 3, -4, -2], [2, 1, -3, -2], [-3], [-4], [9, -2, 1, 7, 8, -19, -7], [2, 4, 3]$. O subsecvenţă de sumă maximă va avea primul capăt la începutul unei astfel de subsecvenţe, acest lucru explicându-se prin faptul că în caz contrar secvenţa poate fi mărită în stânga (orice secvenţă din cele alese pentru partiţionare are toate prefixele de sumă pozitivă, în afară de prefixul ce reprezintă întreaga subsecvenţă). De asemenea, orice subsecvenţă de sumă maximă nu va conţine elemente din altă parte a partiţiei, pentru că dacă subsecvenţa se întinde pe mai multe părţi, atunci putem elimina prefixul subsecvenţei care reprezintă o parte a partiţiei, acea parte având suma negativă.\r\n\r\n== code(cpp) |\r\nsum = -INFINIT;\r\nbestSum = -INFINIT;\r\nfor (i = 1; i <= N; i++) {\r\n    sum += a[i];\r\n    if (sum < 0)\r\n        sum = 0;\r\n    else if (sum >= bestSum) \r\n        bestSum = sum;      \r\n}\r\n==\r\n\r\nh2(#problema-2). Problema 2 (\'Maximum Sum\':http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&Itemid=8&category=3&page=show_problem&problem=44, UVa)\r\n\r\nbq. Se dă o matrice de dimensiuni $N x N$ cu elemente întregi. Se cere determinarea unei submatrici a cărei elemente au suma maximă. \r\n\r\nh3. Exemplu:\r\n\r\nPentru matricea<tex>\\[ \\left( \\begin{array}{cccc}0 & -2 & -7 & 0 \\\\9 & 2 & -6 & 2 \\\\-4 & 1 & -4 & 1 \\\\-1 & 8 & 0 & -2 \\end{array} \\right)\\]</tex>submatricea de sumă maximă este următoarea:<tex>\\[ \\left( \\begin{array}{cc}9 & 2 \\\\-4 & 1 \\\\-1 & 8 \\end{array} \\right)\\]</tex>\r\n\r\nh3. Rezolvare:\r\n\r\nPutem folosi trucul construirii sumelor parţiale din rezolvarea anterioară, pentru cazul $2D$. Păstrăm în $sum[i][j]$ suma tuturor elementelor $a[i{~1~}][j{~1~}]$ cu proprietatea că $1 &le; i{~1~} &le; i$, şi $1 &le; j{~1~} &le; j$. Putem calcula sumele prin metoda programării dinamice în complexitate $O(N^2^)$ folosind formula: $sum[i][j] = a[i][j] + sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1]$. Acum, pentru a calcula suma elementelor din matricea cu colţurile $(i{~1~}, j{~1~})$ şi $(i{~2~}, j{~2~})$, unde $i{~1~} &le; i{~2~}$ şi $j{~1~} &le; j{~2~}$, este suficient să facem calculul $sum[i{~2~}][j{~2~}] - sum[i{~1~}-1][j{~2~}] - sum[i{~2~}][j{~1~}-1] + sum[i{~1~}-1][j{~1~}-1]$. Astfel putem evalua suma din fiecare submatrice în timp constant, deci rezolvarea are ordinul de complexitate $O(N^4^)$.\r\n\r\nO altă idee ar fi ca pentru fiecare pereche $(i{~1~}, i{~2~})$ fixată să determinăm perechea optimă $(j{~1~}, j{~2~})$. Dacă avem liniile $i{~1~}$ şi $i{~2~}$ fixate atunci problema se transformă din una bidimensională în una unidimensională. Astfel pentru fiecare coloană $j$ vom considera $b[j]$ ca sumă a elementelor $a[i][j]$ cu proprietatea că $i{~1~} &le; i &le; i{~2~}$. În exemplul nostru, dacă $i{~1~} = 2$ şi $i{~2~} = 3$, atunci avem: $b{~1~} = 9 + (-4)$, $b{~2~} = 2 + 1$, $b{~3~} = (-6) + (-4)$ şi $b{~4~} = 2 + 1$. Pentru a rezolva problema unidimensională folosim unul din algoritmii liniari prezentaţi mai sus, astfel obţinându-se un algoritm de complexitate totală $O(N^3^)$. Acest truc de a fixa două linii pentru a transforma problema în una unidimensională este util în multe probleme pe matrice sau cu puncte în plan.\r\n\r\nCel mai bun algoritm cunoscut pentru această problemă are complexitatea <tex>O(N^{3\\sqrt{\\frac{\\log \\log N}{\\log N}}})</tex> şi este mai mult un algoritm teoretic decât unul practic, uşor implementabil. Pentru detalii puteti consulta lucrarea [3].\r\n\r\nh2(#problema-3). Problema 3 (\'SequenceQuery\':problema/sequencequery, Bursele Agora 2006)\r\n\r\nbq. Se consideră un şir $A = (a{~1~}, a{~2~}, ..., a{~N~})$, format din numere întregi $(-100.000 &le; a{~i~} &le; 100.000)$, şi $M$ perechi de numere $(x, y)$ $(1 &le; N, M &le; 100.000)$. Pentru fiecare pereche ordonată de indici $(x, y)$ trebuie determinată subsecvenţa de sumă maximă a subşirului $a{~x~}, a{~x+1~}, ..., a{~y~}$. Subsecvenţele alese trebuie să conţină cel puţin un element. \r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(-1, 2, 3, -2, 4, -3, 8, -3)$ şi intervalele $[1, 5]$, $[4, 8]$ si $[6, 6]$ avem soluţiile: \r\n\r\n* $7$ pentru subsecvenţa $(-1, *2*, *3*, *-2*, *4*)$;\r\n\r\n* $9$ pentru subsecvenţa $(-2, *4*, *-3*, *8*, -3)$;\r\n\r\n* $-3$ pentru subsecvenţa $({*-3*})$.\r\n\r\nh3. Rezolvare:\r\n\r\nPutem obţine un algoritm de complexitate $O(M * N)$ folosind algoritmii liniari din prima problemă, dar să vedem cum putem reduce complexitatea folosind alte abordări. Mai întâi calculăm şirul $sum[]$ al sumelor parţiale, după care împărţim şirul în $K$ subsecvenţe de lungimi egale $[N / K]$, şi păstrăm următoarele informaţii pentru fiecare din ele:\r\n\r\n* $max[i]$ - cea mai mare valoare $sum[j]$, unde: $N / K * (i - 1) < j &le; N / K * i$;\r\n\r\n* $min[i]$ - cel mai mic $sum[j - 1]$, unde: $N / K * (i - 1) < j &le; N / K * i$;\r\n\r\n* $best[i]$ - valoarea subsecventei de suma maxima a secventei curente.\r\n\r\nAcum, pentru a afla subsecvenţa de sumă maximă a subsecvenţei $a[x..y]$ studiem cele două cazuri posibile:\r\n\r\n1. Dacă elementele de indice $x$ şi $y$ aparţin aceleiaşi subsecvenţe, atunci putem găsi ceea ce căutăm folosind algoritmul liniar direct pe şirul $a[x..y]$. Complexitate: $O(N / K)$.\r\n\r\n2. Dacă nu sunt în aceeaşi secvenţă, atunci vom împărţi şirul $a[x..y]$ în:\r\n\r\n* un prefix de subsecvenţă din cele ce aparţin partiţionării,\r\n\r\n* un sufix de subsecvenţă,\r\n\r\n* zero sau mai multe subsecvenţe complete ce aparţin partiţionării,\r\n\r\ndupă care rezolvăm problema pentru sufix şi prefix prin metoda liniară în $O(N / K)$, şi determinăm în $O(1)$ pentru fiecare bucată în care este spart şirul $a[x..y]$ subsecvenţa ei de sumă maximă.\r\n\r\nMai rămâne să găsim subsecvenţa de sumă maximă cu capătul în bucăţi diferite. Pentru două bucăţi fixate $i < j$, subsecvenţa de sumă maximă ce are câte un capăt în fiecare bucată are valoarea: $max[j] - min[i]$. Determinarea subsecvenţei de sumă maximă cu capetele în bucăţi diferite devine astfel de complexitate $O(K)$. Deci, pentru a rezolva o întrebare trebuie să facem $O(N / K + K)$ calcule. Pentru a reduce complexitatea problemei considerăm pe $K = sqrt(N)$. Complexitatea totală a acestei soluţii este $O(N + M * sqrt(N))$.\r\n\r\nSă vedem ce se întâmplă pe exemplu:\r\n\r\ntable{width:300px; text-align:right;}.\r\n|_. $a$ | - | $-1$ | $2$ | $3$ | $-2$ | $4$ | $-3$ | $8$ | $-3$ | $1$ |\r\n|_. $sum$ | $0$ | $-1$ | $1$ | $4$ | $2$ | $6$ | $3$ | $11$ | $8$ | $9$ |\r\n\r\nşirul e împărţit în trei subsecvenţe $[-1, 2, 3], [-2, 4, -3], [8, -3, 1]$:\r\n\r\ntable{width:100px; text-align:right;}.\r\n|_. $max$ | $4$ | $6$ | $11$ |\r\n|_. $min$ | $-1$ | $2$ | $8$ |\r\n|_. $best$ | $5$ | $4$ | $8$ |\r\n\r\nPentru a răspunde la întrebarea $[1, 5]$ trebuie să răspundem la cele două subsecvenţe componente $[1..3]$ şi $[4..5]$. Soluţia optimă pentru $[1..3]$ este $best[&#49;] = 5$. Soluţia optimă pentru $[4..5]$ o determinăm folosind algoritmul liniar, ea fiind $4$. Acum, pentru a determina subsecvenţa de sumă maximă cu câte un capăt în fiecare interval folosim formula: $max(sum[i]) - min(sum[j - 1])$, unde $4 &le; i &le; 5$ şi $1 &le; j &le; 3$. Valoarea $max(sum[i])$ o găsim parcurgând intervalul $[4, 5]$ ca fiind $6$, iar valoarea $min(sum[j - 1])$ o avem deja calculată în $min[&#49;]$. De aici obţinem rezultatul $7$.\r\n\r\nO soluţie similară poate fi obţinută cu ajutorul arborilor de intervale. Mai întâi creăm arborele de intervale. Pentru fiecare interval aflăm elementele $min$, $max$ şi $best$ astfel:\r\n\r\n* $min[x..y] = minim(min[x..(x+y)/2], min[(x+y)/2 + 1 .. y])$;\r\n\r\n* $max[x..y] = maxim(max[x..(x+y)/2], max[(x+y)/2 + 1 .. y])$;\r\n\r\n* $best[x..y] = maxim(best[x..(x+y)/2], maxim(best[(x+y)/2 + 1 .. y], max[(x+y)/2 + 1 .. y] - min[x..(x+y)/2]))$.\r\n\r\nAcum pentru a răspunde la întrebările din problemă fiecare interval va fi împărţit în $O(log N)$ subintervale canonice care apar în arborele de intervale. Apoi printr-o parcurgere asemănătoare celei din rezolvarea anterioară se poate obţine rezultatul pentru fiecare întrebare în $O(log N)$. Soluţia va avea complexitatea $O(N + M * log N)$.\r\n\r\nÎn următorul desen observăm structura unui arbore de intervale pentru un şir cu $16$ elemente. Daca se pune întrebarea $[2, 11]$ acest interval va fi spart în intervalele $[2, 2], [3, 4], [5, 8], [9, 10], [11, 11]$.\r\n\r\n!probleme-cu-secvente?numere2.png!\r\n\r\nPrezentăm procedura de construire a arborelui, implementată în _java_:\r\n\r\n== code(java) |\r\npublic void build_tree(int index, int low, int high) {\r\n    if (low == high) {\r\n        if (low != 0) aint[index] = new Node(low, high, a[low] - a[low - 1], a[low], a[low]);\r\n        else aint[index] = new Node(low, high, 0, 0, 0);\r\n    }\r\n    else {\r\n        aint[index] = new Node(low, high, -INFINIT, -INFINIT, INFINIT);\r\n        int mid = (low + high) / 2;\r\n        build_tree(2 * index, low, mid);\r\n        build_tree(2 * index + 1, mid + 1, high);\r\n        aint[index].maxS = Math.max(aint[2 * index].maxS,\r\n                Math.max(aint[2 * index + 1].maxS, aint[2 * index + 1].max - aint[2 * index].min));\r\n        aint[index].max = Math.max(aint[2 * index].max, aint[2 * index + 1].max);\r\n        aint[index].min = Math.min(aint[2 * index].min, aint[2 * index + 1].min);\r\n    }\r\n}\r\n==\r\n\r\nşi procedura care răspunde la întrebări tot în _java_:\r\n\r\n== code(java) |\r\nlong minPrefix;\r\nint x, y;\r\npublic long queryTree(int index, int low, int high) {\r\n    if (x <= low && high <= y) {\r\n        long maxRet = aint[index].maxS;\r\n        if (minPrefix != INFINIT) {\r\n            maxRet = Math.max(maxRet, aint[index].max - minPrefix);\r\n        }\r\n        minPrefix = Math.min(minPrefix, aint[index].min);\r\n        return maxRet;\r\n    }\r\n    else {\r\n        int mid = (low + high) / 2;\r\n        if (x <= mid && mid < y) \r\n            return Math.max(queryTree(2 * index, low, mid), queryTree(2 * index + 1, mid + 1, high));\r\n        else if (x > mid) \r\n            return queryTree(2 * index + 1, mid + 1, high);\r\n        else \r\n            return queryTree(2 * index, low, mid);\r\n    }\r\n}\r\n==\r\n\r\nAutorul vă recomandă articolele [1] şi [2] pentru o înţelegere mai profundă a structurii de date numită arbori de intervale. Problema poate fi soluţionată şi în $O(N + M)$, dar algoritmul este mult prea complicat pentru un concurs de programare; cei interesaţi pot să îl găsească în [4].\r\n\r\nh2(#problema-4). Problema 4 (ACM ICPC NWERC 97, olimpiada online 2000, .campion 2001)\r\n\r\nbq. Se dă un şir $(a{~1~}, a{~2~}, ..., a{~N~})$ format din numere întregi. Se cere să se determine subsecvenţa $a[i..j]$ care are modulul sumei elementelor minim.\r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(2, 8, -6, -6, 9, 4, -3)$, subsecvenţa este $(4, -3)$, având suma în modul $1 = |4 - 3|$.\r\n\r\nh3. Rezolvare:\r\n\r\nConstruim întâi şirul sumelor parţiale. Pentru oricare două elemente $sum[i]$ şi $sum[j]$ cu $(i != j)$ modulul sumei unei subsecvenţe din şir va fi $|sum[i] - sum[j]|$. Dacă $i < j$, atunci secvenţa va fi $a[i+1..j]$, iar dacă $j < i$, atunci secvenţa va fi $a[j+1 .. i]$. Astfel, pentru a găsi subsecvenţa de modul minim trebuie, de fapt, să găsim perechea de indici $i$ şi $j$ astfel ca $|sum[i] - sum[j]|$ să fie minim. Sortând şirul sumelor parţiale şi luând o pereche de indici $i < j$, atunci $sum[i] < sum[j]$, iar $|sum[j] - sum[i]| = sum[j] - sum[i]$. Pentru a găsi perechea $(i, j)$ pentru care $i < j$ şi $sum[j] - sum[i]$ este minim, trebuie ca $i$ să fie egal cu $j + 1$. Astfel obţinem un algoritm de complexitate $O(N * log N)$.\r\n\r\nSă vedem cum merge pe exemplul prezentat:\r\n\r\ntable{width:300px; text-align:right;}.\r\n|_. $a$ | - | $2$ | $8$ | $-6$ | $-6$ | $9$ | $4$ | $-3$ |\r\n|_. $sum$ | $0$ | $2$ | $10$ | $4$ | $-2$ | $7$ | $11$ | $8$ |\r\n|_. $ind$ | $0$ | $1$ | $2$ | $3$ | $4$ | $5$ | $6$ | $7$ |\r\n\r\nÎn şirul $ind$ vom păstra indicii reali ai sumelor parţiale. După sortare avem:\r\n\r\ntable{width:300px; text-align:right;}.\r\n|_. $sum$ | $-2$ | $0$ | $2$ | $4$ | $7$ | $8$ | $10$ | $11$ | \r\n|_. $ind$ | $4$ | $0$ | $1$ | $4$ | $5$ | $7$ | $2$ | $6$ |\r\n\r\nO secvenţă de modul $2$ ar fi cea reprezentată de sumele $8$ şi $10$, cu indicii $7$ şi $2$. Această secvenţă este $(-6, -6, 9, 4, -3)$. Observăm ca cea mai mică diferenţă între termeni consecutivi e cea dintre $8$ şi $7$, care au indicii $7$ şi $5$, de unde obţinem că subsecvenţa de modul minim este $(4, -3)$. \r\n\r\nh2(#problema-5). Problema 5 (USACO)\r\n\r\nbq. Se dă un şir $(a{~1~}, a{~2~}, ..., a{~N~})$ format din $N (1 &le; N &le; 100 000)$ numere întregi $(1 &le; a{~i~} &le; 2 000)$ si un numar natural $F$. Se cere să se determine subsecvenţa $a[i..i + K - 1]$ cu media aritmetică a elementelor maximă, unde $K$ are proprietatea $K &ge; F$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(6, 4, 2, 10, 3, 8, 5, 9, 4, 1)$ şi $F = 6$ soluţia optimă este $(10, 3, 8, 5, 9, 4)$, cu media $6.5$.\r\n\r\nh3. Rezolvare:\r\n\r\nFie $X$ un număr real. Considerând şirul $b$, obţinut prin transformarea $b{~i~} = a{~i~} - X$, atunci toate subsecvenţele şirului $b$ vor avea valoarea mediei elementelor lor cu $X$ mai mică decât valoarea subsecvenţelor corespunzătoare din şirul $a$. Observăm apariţia a trei cazuri:\r\n\r\n* Dacă subsecvenţa de sumă maximă din $b$ are valoarea mai mare ca $0$, atunci şi media ei va fi mai mare ca $0$. Rezultă astfel că şi media subsecvenţei corespunzătoare din şirul $a$ va fi mai mare decât $X$, deci media maximă a unei subsecvenţe din $a$ va fi mai mare ca $X$. \r\n\r\n* Cand subsecvenţa de sumă maximă din şirul $b$ are media mai mică decât $0$, atunci orice subsecvenţă din şirul $a$ va avea media mai mică decât $X$. \r\n\r\n* În cazul în care subsecvenţa de sumă maximă a şirului $b$ are valoarea egală cu zero, atunci subsecvenţa de medie maximă a şirului $a$ are media $X$.\r\n\r\nAstfel putem face o căutare binară pentru a determina valoarea $X$ a mediei maxime. Ne mai rămâne să determinăm un algoritm eficient pentru găsirea subsecvenţei de sumă maximă de lungime cel puţin $F$. O asemenea soluţie urmăreşte una din ideile din prima problemă: fie $best[i]$ subsecvenţa de sumă maximă ce se termină în $a[i]$. Evident $best[i] = max(a[i], best[i - 1] + a[i])$. Acum secvenţa de sumă maximă ce se termină în $a[i]$, de lungime cel puţin $F$ se găseşte ca $a[i] + a[i - 1] + .. + a[i - F + 2] + best[i - F + 1]$. Această relaţie poate fi calculată în $O(1)$ dacă ne folosim de trucul sumelor parţiale. Complexitatea finală este $O(N * log C)$, unde $C$ e valoarea maximă a lui $a{~i~}$.\r\n\r\nh2(#problema-6). Problema 6 (\'Secvenţă\':problema/secventa)\r\n\r\nbq. Se da un şir de $N$ numere întregi. O secvenţă este un subşir de numere care apar pe poziţii consecutive în şirul iniţial. Definim baza unei secvenţe ca fiind minimul valorilor elementelor din secvenţa respectivă. Fiind dat un număr natural $K$, determinaţi o secvenţă de lungime cel puţin $K$, cu baza maximă. Restrictii: $1 &le; K &le; N &le; 500 000$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru $K = 3$ şi şirul $(-1, 2, 3, 1, 0, 4, 8, 6)$, secvenţa de bază maximă este $(4, 8, 6)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPresupunem că orice secvenţă optimă ar avea lungimea mai mare decât $K$. Atunci putem obţine o secvenţă mai mică, cu aceeaşi bază eliminând unul din capetele unei secvenţe optime. Deci este de ajuns să cautăm secvenţele optime de lungime exact $K$.\r\n\r\nAcum putem face o parcurgere a şirului pentru a rezolva problema. Mai întâi punem într-un $min-heap$ $K$ elemente, verificăm vârful heapului şi obţinem astfel minimul secvenţei $a[1..K]$. Apoi eliminăm elementul $a[&#49;]$ din heap şi inserăm elementul $a[K + 1]$. Prin verificarea vârfului heapului obţinem minimul secvenţei $a[2..K + 1]$. Continuăm procedeul până aflăm elementul minim pentru fiecare subsecvenţă de lungime $K$ a şirului $a$ (complexitate $O(N * log K)$). Există şi alte soluţii pentru găsirea elementului minim al unei subsecvenţe, precum folosirea unui arbore de intervale sau folosirea tehnicii $O(N * log N) / O(1)$ pentru problema _RMQ_.\r\n\r\nO observaţie importantă este aceea că dacă vrem să vedem minimul secvenţei ce se termină în $i$ şi avem $j{~1~} < j{~2~} &le; i$ şi $a[j{~1~}] &ge; a[j{~2~}]$, atunci evident $a[j{~1~}]$ nu va fi minimul secvenţei ce se termină în $i$. Folosim o structură de date ca la soluţia cu heapuri, care adaugă elemente noi şi şterge elemente vechi, dar pe lângă elementele ce au fost inserate acum $K$ paşi şi trebuie şterse, mai ştergem şi elementele mai noi care nu ne vor mai fi utile, după cum este $a[j{~2~}]$ mai sus. Ca structură de date folosim o listă în care putem insera şi şterge de la ambele capete, un _deque_. Fiecare element inserat în deque va fi o pereche de valori, valoarea din şir şi indexul din şir $(a[i], i)$. Când o valoare este inserată în şir, ea este pusă la capătul din dreapta al şirului, dar înainte de inserare cât timp elementul din capătul şirului are valoarea mai mare decât $a[i]$ el este eliminat. La fiecare pas după o inserţie se verifică dacă elementul din capătul din stânga este mai „bătrân” de $K$ iteraţii.\r\n\r\nDin cauza modului în care se fac inserţiile şi ştergerile, şirul va fi sortat totdeauna crescător după indecşi şi crescător după valori. Tot timpul ultimul element din stivă va conţine valoarea bazei. Acest algoritm are complexitatea $O(N)$ pentru că fiecare element este inserat şi şters din deque cel mult o dată.\r\n\r\nSă vedem cum funcţionează rezolvarea pe un exemplu : $a = (-1, 2, 3, 1, 0, 4, 8, 6)$\r\n\r\n* inserăm $(-1, 1)$\r\nlista devine: $(-1, 1)$\r\n \r\n\r\n* inserăm $(2, 2)$\r\nlista devine: $(-1, 1) (2, 2)$\r\n\r\n\r\n* inserăm $(3, 3)$\r\nlista devine: $(-1, 1) (2, 2) (3, 3)$\r\nelementul minim al secvenţei $a[1..3]$ este $-1$\r\n\r\n\r\n* inserăm $(1, 4)$\r\nştergem $(3, 3)$ şi $(2, 2)$\r\nştergem $(-1, 1)$ ( inserat acum $4$ paşi )\r\nlista de vine: $(1, 4)$\r\nelementul minim al secvenţei $a[2..4]$ este $1$\r\n\r\n\r\n* inserăm $(0, 5)$\r\nştergem $(1, 4)$\r\nlista devine: $(0, 5)$\r\nelementul minim al secvenţei $a[3..5]$ este $0$.\r\n\r\n\r\n* inserăm $(4, 6)$\r\nlista devine: $(0, 5) (4, 6)$\r\nelementul minim al secvenţei $a[4..6]$ este $0$\r\n\r\n\r\n* inserăm $(8, 7)$\r\nlista devine: $(0, 5) (4, 6) (8, 7)$\r\nelementul minim al secvenţei $a[5..7]$ este $0$\r\n\r\n\r\n* inserăm $(6, 8)$\r\nştergem $(8, 7)$\r\nştergem $(0, 5)$ ( inserat acum $4$ paşi )\r\nlista devine: $(4, 6) (6, 8)$\r\nelementul minim al secvenţei $a[6..8]$ este $4$\r\n\r\nh2(#problema-7). Problema 7 (Agricultura, Algoritmus)\r\n\r\nbq. Se dă o matrice de dimensiuni $N x M$ de numere naturale. Se cere determinarea unei submatrici cu număr maxim de celule în care diferenţa între valoarea maximă şi valoarea minimă este mai mică decât o valoare dată $K$. Restrictii: $2 &le; N, M &le; 150$, $1 &le; K &le; 1 000$.\r\n\r\nh3. Exemplu:\r\n\r\nDe exemplu pentru $K = 3$ şi matricea <tex>\\[ \\left( \\begin{array}{cccccc}1 & 1 & 3 & 1 & 2 & 7 \\\\9 & 2 & 3 & 2 & 3 & 2 \\\\7 & 8 & 2 & 3 & 1 & 5 \\\\4 & 5 & 6 & 0 & 1 & 4 \\end{array} \\right)\\]</tex>, soluţia optimă va avea $9$ celule.\r\n\r\nh3. Rezolvare:\r\n\r\nProblema constă în determinarea submatricei cu număr maxim de celule în care diferenţa între valoarea maximă şi valoarea minimă este mai mică decât $K$. Vom folosi ideea de la problema cu subsecvenţa de sumă maximă pe matrice, adică vom fixa două linii $i{~1~}$ şi $i{~2~}$. Acum pentru fiecare coloană $j$ păstrăm în $m[j]$ elementul minim şi în $M[j]$ elementul maxim $a[i][j]$ cu $i{~1~} &le; i &le; i{~2~}$. Astfel la fiecare pas trebuie acum să rezolvăm problema determinării unei subsecvenţe de lungime maximă pentru care diferenţa între elementul maxim şi minim este mai mică decât $K$. Folosind un _max-heap_ şi un _min-heap_ putem parcurge elementele şirurilor $M$ şi $m$ în ordine inserând la fiecare pas elemente în heap şi determinând cea mai lungă secvenţă ce se termină în $i$ cu proprietatea dată. Vom ţine un al $2$-lea indice $j$, iniţial $0$, care atâta timp cât diferenţa între elementul maxim din max-heap cu elementul minim din min-heap este mai mare sau egală cu $K$, vom scoate din heapuri elementele $M[j]$, respectiv $m[j]$ şi îl vom incrementa pe $j$. Complexitate: $O(N^3^ log N)$. Dacă în loc de heapuri folosim deque-uri, atunci acest algoritm va avea complexitatea $O(N^3^)$.\r\n\r\nh2(#problema-8). Problema 8 (\'Secvenţa 2\':problema/secv2)\r\n\r\nbq. Se da un şir de $N$ numere întregi şi un număr natural $K$. O secvenţă este un subşir de numere care apar pe poziţii consecutive în şirul iniţial. Se cere să se găsească secvenţa de sumă maximă de lungime cel puţin $K$. Restrictii: $1 &le; K &le; N &le; 50 000$.\r\n\r\nh3. Exemplu:\r\n\r\nDe exemplu pentru şirul $(0, -6, 2, 1, 4, -1,  3, -5)$ şi $K = 3$, soluţia optimă este $(2, 1, 4, -1, 3)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPutem folosi rezolvarea liniară bazată pe programare dinamică prezentată ca subalgoritm în soluţia \'problemei $5$\':probleme-cu-secvente#problema-5, dar putem simplifica logica din acea rezolvare. Vom folosi şirul sumelor parţiale $sum[]$, iar pentru a determina subsecvenţa de sumă maximă ce se termină în $i$ şi are lungimea cel puţin $K$ trebuie să găsim $sum[j]$ minim astfel ca $j < i - K$. Parcurgem lista, şi la pasul $i$ determinăm $best[i] = sum[i] - min(sum[j])$, $j < i - K$. Comparăm minimul curent cu $sum[i - K]$ şi trecem la pasul următor. Complexitate: $O(N)$.\r\n\r\nh2(#problema-9). Problema 9 (\'Sum\':problema/sum2, Stelele Informaticii 2003 )\r\n\r\nbq. Se dă un şir de $N$ numere întregi. Se caută un subşir cu lungimea cuprinsă între $L$ şi $U$, format din elemente consecutive ale şirului iniţial, cu suma elementelor maximă. Restrictii: $1 &le; L &le; U &le; N &le; 100 000$.\r\n\r\nh3. Rezolvare:\r\n\r\nPentru fiecare $i$ este de ajuns să aflăm valoarea expresiei $sum[i] - sum[j]$, unde $i - L > j &ge; i - U$. Pentru a determina valoarea optimă pentru $sum[j]$ putem folosi un heap de dimensiune $U - L$, sau putem folosi tehnici de determinare a valorii minime într-un interval dat. Complexitate: $O(N * log(U - L))$.\r\n\r\nAltă abordare de aflare a minimelor unor secvenţe de lungime dată (în cazul acesta lungimea este $U - L$ ) a fost prezentată în rezolvarea \'problemei $6$\':probleme-cu-secvente#problema-6. Folosind acea tehnică obţinem o rezolvare de complexitate liniară.\r\n\r\nO altă rezolvare frumoasă prezentată în [4] este următoarea: spunem că o secvenţă este negativă spre stânga dacă suma oricărui prefix ( în afară de secvenţa în sine ) al secvenţei este negativ sau zero. O partiţie a secvenţei $A = (A{~1~}, A{~2~}, ..., A{~k~})$ este minimală negativă spre stânga dacă fiecare $A{~i~}$ este negativă spre stânga, iar suma elementelor lui $A{~i~}$ este strict pozitivă dacă $i != k$. De exemplu secvenţa $(-4, 1, -2, 3)$ este negativă la stânga, pe când secvenţa $(5, -3, 4, -1, 2, -6)$ nu este. Partiţia $(5) (-3, 4) (-1, 2) (-6)$ este minimală negativă la stânga.\r\n\r\nPentru fiecare element din partiţie ţinem minte un pointer $p[i]$ spre ultimul element din subsecvenţa din care face parte. Fiecare interval $[i, p[i]]$ va corespunde celei mai scurte subsecvenţe care începe în $i$ şi are suma pozitivă. Pentru a determina o soluţie a problemei pentru fiecare $i$ din care poate începe o subsecvenţă de sumă maximă, ne vom plimba cu un pointer $j$ astfel ca $j$ să fie cât mai depărtat de $i$ şi $j - i + 1 &le; U$. Obţinem astfel de fiecare dată o subsecvenţă de sumă maximă ce începe în $i$, cu lungimea mai mică sau egală cu $U$. Indicele $j$ va fi întotdeauna un capăt de secvenţă negativă la stânga şi la fiecare mărire a lui $i$ verificăm dacă lui $j$ îi putem atribui valoarea $p[j + 1]$ ( adică dacă $p[j + 1] - i + 1 &le; U$ ). Dacă secvenţa de sumă maximă de lungime cel mult $U$ ce începe în $i$ are lungimea mai mică decât $L$, atunci secvenţa de sumă maximă cu lungimea cuprinsă între $L$ şi $U$ are lungimea exact $L$. Complexitate: $O(N)$.\r\n\r\nh2(#problema-10). Problema 10 (\'Secvenţa 3\':problema/secv3)\r\n\r\nbq. Se dă un şir de $N$ elemente pentru care se cunosc două informaţii: costul şi timpul. O secvenţă este un subşir de numere care apar pe poziţii consecutive în şirul iniţial. Se caută o secvenţă din cele $N$ elemente care să fie de lungime minim $L$ şi maxim $U$, iar suma costurilor elementelor secvenţei împărţiţă la suma timpurilor elementelor secvenţei să fie maximă. Restrictii: $1 &le; L &le; U &le; N &le; 30 000$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru $L = 1, R = 2$ şi şirurile $c = ( 1, 1, 3, 2, 5 )$ şi $t = ( 4, 2, 5, 3, 6 )$, subsecvenţa cea mai eficientă are costul $0.83$.\r\n\r\nh3. Rezolvare:\r\n\r\nProcedăm ca la \'problema $5$\':probleme-cu-secvente#problema-5 şi căutăm binar valoarea optimă. şirul va fi transformat în: $b[i] = c[i] - t[i] * X$, $i = 1..N$. Acum trebuie să mai rezolvăm subproblema care cere să determinăm o subsecvenţă de sumă maximă pentru care lungimea se află între $L$ şi $U$. Această subproblemă a fost soluţionată în \'problema anterioară\':probleme-cu-secvente#problema-9, unde s-a găsit un algoritm liniar. Astfel soluţia acestei probleme are complexitatea $O(N * log C)$.\r\n\r\nh2(#problema-11). Problema 11 (\'XorMax\':problema/xormax)\r\n\r\nbq. Se dă un şir de $N$ numere întregi nenegative. Să se aleagă o secvenţă a şirului, $(a{~i~}, a{~i+1~}, ..., a{~j~})$, astfel încât $a{~i~} xor a{~i+1~} xor ... xor a{~j~}$ să fie maxim. Restrictii: $1 &le; N &le; 100 000$ si $a{~i~} < 221$ cu $i = 1..N$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(1, 0, 5, 4, 2)$, secvenţa cu valoarea sumei _xor_ maximă este $(4, 2)$, cu suma $6$. \r\n\r\nh3. Rezolvare:\r\n\r\nSuma _xor_ a două numere este de fapt adunare binară fără transport, fapt care o face similară operaţiei _modulo_. Problema e asemănătoare cu cea a subsecvenţei de modul maxim. Vom obţine toate sumele _xor_ parţiale şi pentru a vedea pentru $sum[i]$ perechea optimă cu care crează o sumă cât mai mare trebuie să găsim acea sumă $sum[j]$ astfel că fiecare bit al lui $sum[i]$ să fie diferit de fiecare bit al lui $sum[j]$, dacă acest lucru este posibil. Pentru a face această căutare cât mai eficientă, putem menţine sumele $sum[i]$ ca şiruri de caractere $0$ sau $1$ într-un _trie_ [5]. Structura de trie pentru cazul când alfabetul are dimensiunea $2$ este identică cu cea de heap. Această soluţie are complexitatea $O(N * log C)$.\r\n\r\nh2(#problema-propuse). Probleme propuse\r\n\r\nPentru a vă însuşi mai bine tehnicile învăţate în acest articol, puteţi rezolva următoarele probleme:\r\n\r\n* \'Balans\':problema/balans\r\n* \'Struţi\':problema/struti\r\n* \'Deque\':problema/deque\r\n* \'Trie\':problema/trie\r\n* \'Maxq\':problema/maxq\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Dana Lica - \'_Arbori de intervale şi aplicaţii în geometria computaţională_\':arbori-de-intervale\r\n# Cosmin Negruşeri - \'_Căutări Ortogonale: Structuri de date şi aplicaţii_\':cautari-ortogonale\r\n# Takaoka T. - \'_Efficient Algorithms for the Maximum Subarray Problem by Distance Matrix Multiplication_\':http://www.cosc.canterbury.ac.nz/tad.takaoka/cats02.pdf\r\n# Kuan Yu Chen, Kun Mao Chao - \'_On the Range Maximum-Sum Segment Query_\':http://www.csie.ntu.edu.tw/~kmchao/papers/2007_DAM_RMSQ.pdf\r\n# Yaw Ling Liu, Tao Jiang, Kun Mao Chao - \'_Efficient Algorithms for Locating the Length-Constrained Heaviest Segments, with Applications to Biomolecolar Sequence Analysis_\':http://www.csie.ntu.edu.tw/~kmchao/seq2003/mslc.pdf\r\n# T. H. Cormen, C. E. Leiserson, R. R. Rivest - \'_Introducere in Algoritmi_\':http://zhuzeyuan.hp.infoseek.co.jp/ita/toc.htm',2044,'public',NULL,NULL),('probleme-cu-secvente','Probleme cu secvențe','2008-11-23 19:46:37','2009-01-09 22:33:36','h1. Probleme cu secvenţe\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"alecman\") ==\r\n\r\n(Categoria _Algoritmi şi tehnici de programare_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut*\r\n* \'Introducere \':probleme-cu-secvente#introducere\r\n* \'Problema 1 (Subsecvenţa de sumă maximă) \':probleme-cu-secvente#problema-1\r\n* \'Problema 2 (Maximum Sum) \':probleme-cu-secvente#problema-2\r\n* \'Problema 3 (SequenceQuery) \':probleme-cu-secvente#problema-3\r\n* \'Problema 4 \':probleme-cu-secvente#problema-4\r\n* \'Problema 5 \':probleme-cu-secvente#problema-5\r\n* \'Problema 6 (Secvenţă) \':probleme-cu-secvente#problema-6\r\n* \'Problema 7 (Agricultura) \':probleme-cu-secvente#problema-7\r\n* \'Problema 8 (Secvenţa 2) \':probleme-cu-secvente#problema-8\r\n* \'Problema 9 (Sum) \':probleme-cu-secvente#problema-9\r\n* \'Problema 10 (Secvenţa 3) \':probleme-cu-secvente#problema-10\r\n* \'Problema 11 (XorMax) \':probleme-cu-secvente#problema-11\r\n* \'Probleme propuse\':probleme-cu-secvente#probleme-propuse\r\n* \'Bibliografie\':probleme-cu-secvente#bibliografie\r\n\r\nh2(#introducere). Introducere\r\n\r\nAcest articol prezintă o serie de probleme înrudite cu problema subsecvenţei de sumă maximă, însoţite de rezolvări eficiente. Problemele prezentate pot apărea oricând ca subprobleme în concursurile de programare, studierea lor mărind în mod util bagajul de cunoştinţe al unui elev pasionat de algoritmică.\r\n\r\nh2(#problema-1). Problema 1 (Subsecvenţa de sumă maximă)\r\n\r\nbq. Se dă un şir de $N$ numere întregi $(a{~1~}, a{~2~}, ..., a{~N~})$. Să se determine o subsecvenţă $(a{~i~}, a{~i+1~}, ..., a{~j~})$ care să aibă suma maximă.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(-1, 2, 3, -4, -2, 2, 1, -3, -2, -3, -4, 9, -2, 1, 7, 8, -19, -7, 2, 4, 3)$, o subsecvenţă de sumă maximă este $(9, -2, 1, 7, 8)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPrima rezolvare care ne vine în minte are complexitatea $O(N^3^)$ şi constă în determinarea sumei fiecărei subsecvenţe posibile şi reţinerea maximului acestor sume. Este evident că anumite sume parţiale sunt calculate de mai multe ori.\r\n\r\nPutem reduce complexitatea la $O(N^2^)$ ţinând cont de faptul că suma subsecvenţei $a[i..j]$ este egală cu suma subsecvenţei $a[i..j-1]$, la care se adună $a[j]$. Păstrăm într-un şir $sum[i]$ suma elementelor din subsecvenţa $a[1..i]$. Pentru a determina suma elementelor din subsecvenţa $a[i..j]$ facem diferenţa: $sum[i] - sum[j-1]$.\r\n\r\nIdeea poate fi rafinată calculând pentru fiecare indice $i$ numărul $best[i]$, reprezentând subsecvenţa de sumă maximă cu capătul drept în $i$. Este uşor de observat că $best[i] = max(sum[i] - sum[j-1])$, unde $j$ ia valori de la $1$ la $i$. Relaţia anterioară se mai poate scrie: $best[i] = sum[i] - min(sum[j-1])$. Obţinem astfel un algoritm liniar care ne determină subsecvenţa de sumă maximă cerută.\r\n\r\n== code(cpp) |\r\nsum[0] = 0;\r\nfor (i = 1; i <= N; i++) sum[i] = a[i] + sum[i-1];\r\nmin = sum[0];\r\nbestSum = -INFINIT;\r\nfor (i = 1; i <= N; i++) {\r\n    best[i] = sum[i] - min;\r\n    if (min > sum[i]) min = sum[i];\r\n    if (bestSum < best[i]) bestSum = best[i];\r\n}\r\n==\r\n\r\nO altă metodă de calcul poate fi dedusă folosind paradigma _Divide et Impera_. La fiecare pas împărţim şirul în jumătate şi aflăm subsecvenţele de sumă maximă din cele două jumătăţi. După aceea trebuie să găsim subsecvenţa de sumă maximă ce are un capăt în fiecare din cele două jumătăţi ale sirului. Pentru aceasta alipim sufixul de sumă maximă a primei jumătăţi cu prefixul de sumă maximă a celei de a doua.\r\n\r\n== code(cpp) |\r\nint getMaxSubsequence(int l, int r) {\r\n    if (l == r) return a[l];\r\n    mid = (l + r) / 2;\r\n    bestL = getMaxSubsequence(l, mid);\r\n    bestR = getMaxSubsequence(mid + 1, r);\r\n    suf = 0; \r\n    pre = 0; \r\n    maxSuf = -INFINIT; \r\n    maxPre = -INFINIT;\r\n    for (i = mid; i >= l; i--) {\r\n        suf += a[i];\r\n        if (maxSuf < suf) maxSuf = suf;\r\n    }\r\n    for (i = mid + 1; i <= r; i++) {\r\n        pre += a[i];\r\n        if (maxPre < pre) maxPre = pre;    \r\n    }\r\n    return max(bestL, max(bestR, maxPre + maxSuf));\r\n}\r\n==\r\n\r\nO idee bazată pe paradigma programării dinamice ar fi să folosim un şir $best[i]$, reprezentând suma maximă a unei subsecvenţe ce se termină în $a[i]$. Problema se rezolvă cu următoarea formulă de recurenţă: $best[i] = max(a[i], best[i-1] + a[i])$. Formula poate fi demonstrată prin inducţie matematică.\r\n\r\nO ultimă idee ar fi să partiţionăm şirul în subsecvenţe încât fiecare să aibă ambele capete cât mai mici posibile şi suma elementelor subsecvenţei să fie negativă. Pentru exemplul dat avem următoarea partiţionare: $[-1], [2, 3, -4, -2], [2, 1, -3, -2], [-3], [-4], [9, -2, 1, 7, 8, -19, -7], [2, 4, 3]$. O subsecvenţă de sumă maximă va avea primul capăt la începutul unei astfel de subsecvenţe, acest lucru explicându-se prin faptul că în caz contrar secvenţa poate fi mărită în stânga (orice secvenţă din cele alese pentru partiţionare are toate prefixele de sumă pozitivă, în afară de prefixul ce reprezintă întreaga subsecvenţă). De asemenea, orice subsecvenţă de sumă maximă nu va conţine elemente din altă parte a partiţiei, pentru că dacă subsecvenţa se întinde pe mai multe părţi, atunci putem elimina prefixul subsecvenţei care reprezintă o parte a partiţiei, acea parte având suma negativă.\r\n\r\n== code(cpp) |\r\nsum = -INFINIT;\r\nbestSum = -INFINIT;\r\nfor (i = 1; i <= N; i++) {\r\n    sum += a[i];\r\n    if (sum < 0)\r\n        sum = 0;\r\n    else if (sum >= bestSum) \r\n        bestSum = sum;      \r\n}\r\n==\r\n\r\nh2(#problema-2). Problema 2 (\'Maximum Sum\':http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&Itemid=8&category=3&page=show_problem&problem=44, UVa)\r\n\r\nbq. Se dă o matrice de dimensiuni $N x N$ cu elemente întregi. Se cere determinarea unei submatrici a cărei elemente au suma maximă. \r\n\r\nh3. Exemplu:\r\n\r\nPentru matricea<tex>\\[ \\left( \\begin{array}{cccc}0 & -2 & -7 & 0 \\\\9 & 2 & -6 & 2 \\\\-4 & 1 & -4 & 1 \\\\-1 & 8 & 0 & -2 \\end{array} \\right)\\]</tex>submatricea de sumă maximă este următoarea:<tex>\\[ \\left( \\begin{array}{cc}9 & 2 \\\\-4 & 1 \\\\-1 & 8 \\end{array} \\right)\\]</tex>\r\n\r\nh3. Rezolvare:\r\n\r\nPutem folosi trucul construirii sumelor parţiale din rezolvarea anterioară, pentru cazul $2D$. Păstrăm în $sum[i][j]$ suma tuturor elementelor $a[i{~1~}][j{~1~}]$ cu proprietatea că $1 &le; i{~1~} &le; i$, şi $1 &le; j{~1~} &le; j$. Putem calcula sumele prin metoda programării dinamice în complexitate $O(N^2^)$ folosind formula: $sum[i][j] = a[i][j] + sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1]$. Acum, pentru a calcula suma elementelor din matricea cu colţurile $(i{~1~}, j{~1~})$ şi $(i{~2~}, j{~2~})$, unde $i{~1~} &le; i{~2~}$ şi $j{~1~} &le; j{~2~}$, este suficient să facem calculul $sum[i{~2~}][j{~2~}] - sum[i{~1~}-1][j{~2~}] - sum[i{~2~}][j{~1~}-1] + sum[i{~1~}-1][j{~1~}-1]$. Astfel putem evalua suma din fiecare submatrice în timp constant, deci rezolvarea are ordinul de complexitate $O(N^4^)$.\r\n\r\nO altă idee ar fi ca pentru fiecare pereche $(i{~1~}, i{~2~})$ fixată să determinăm perechea optimă $(j{~1~}, j{~2~})$. Dacă avem liniile $i{~1~}$ şi $i{~2~}$ fixate atunci problema se transformă din una bidimensională în una unidimensională. Astfel pentru fiecare coloană $j$ vom considera $b[j]$ ca sumă a elementelor $a[i][j]$ cu proprietatea că $i{~1~} &le; i &le; i{~2~}$. În exemplul nostru, dacă $i{~1~} = 2$ şi $i{~2~} = 3$, atunci avem: $b{~1~} = 9 + (-4)$, $b{~2~} = 2 + 1$, $b{~3~} = (-6) + (-4)$ şi $b{~4~} = 2 + 1$. Pentru a rezolva problema unidimensională folosim unul din algoritmii liniari prezentaţi mai sus, astfel obţinându-se un algoritm de complexitate totală $O(N^3^)$. Acest truc de a fixa două linii pentru a transforma problema în una unidimensională este util în multe probleme pe matrice sau cu puncte în plan.\r\n\r\nCel mai bun algoritm cunoscut pentru această problemă are complexitatea <tex>O(N^{3\\sqrt{\\frac{\\log \\log N}{\\log N}}})</tex> şi este mai mult un algoritm teoretic decât unul practic, uşor implementabil. Pentru detalii puteti consulta lucrarea [3].\r\n\r\nh2(#problema-3). Problema 3 (\'SequenceQuery\':problema/sequencequery, Bursele Agora 2006)\r\n\r\nbq. Se consideră un şir $A = (a{~1~}, a{~2~}, ..., a{~N~})$, format din numere întregi $(-100.000 &le; a{~i~} &le; 100.000)$, şi $M$ perechi de numere $(x, y)$ $(1 &le; N, M &le; 100.000)$. Pentru fiecare pereche ordonată de indici $(x, y)$ trebuie determinată subsecvenţa de sumă maximă a subşirului $a{~x~}, a{~x+1~}, ..., a{~y~}$. Subsecvenţele alese trebuie să conţină cel puţin un element. \r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(-1, 2, 3, -2, 4, -3, 8, -3)$ şi intervalele $[1, 5]$, $[4, 8]$ si $[6, 6]$ avem soluţiile: \r\n\r\n* $7$ pentru subsecvenţa $(-1, *2*, *3*, *-2*, *4*)$;\r\n\r\n* $9$ pentru subsecvenţa $(-2, *4*, *-3*, *8*, -3)$;\r\n\r\n* $-3$ pentru subsecvenţa $({*-3*})$.\r\n\r\nh3. Rezolvare:\r\n\r\nPutem obţine un algoritm de complexitate $O(M * N)$ folosind algoritmii liniari din prima problemă, dar să vedem cum putem reduce complexitatea folosind alte abordări. Mai întâi calculăm şirul $sum[]$ al sumelor parţiale, după care împărţim şirul în $K$ subsecvenţe de lungimi egale $[N / K]$, şi păstrăm următoarele informaţii pentru fiecare din ele:\r\n\r\n* $max[i]$ - cea mai mare valoare $sum[j]$, unde: $N / K * (i - 1) < j &le; N / K * i$;\r\n\r\n* $min[i]$ - cel mai mic $sum[j - 1]$, unde: $N / K * (i - 1) < j &le; N / K * i$;\r\n\r\n* $best[i]$ - valoarea subsecventei de suma maxima a secventei curente.\r\n\r\nAcum, pentru a afla subsecvenţa de sumă maximă a subsecvenţei $a[x..y]$ studiem cele două cazuri posibile:\r\n\r\n1. Dacă elementele de indice $x$ şi $y$ aparţin aceleiaşi subsecvenţe, atunci putem găsi ceea ce căutăm folosind algoritmul liniar direct pe şirul $a[x..y]$. Complexitate: $O(N / K)$.\r\n\r\n2. Dacă nu sunt în aceeaşi secvenţă, atunci vom împărţi şirul $a[x..y]$ în:\r\n\r\n* un prefix de subsecvenţă din cele ce aparţin partiţionării,\r\n\r\n* un sufix de subsecvenţă,\r\n\r\n* zero sau mai multe subsecvenţe complete ce aparţin partiţionării,\r\n\r\ndupă care rezolvăm problema pentru sufix şi prefix prin metoda liniară în $O(N / K)$, şi determinăm în $O(1)$ pentru fiecare bucată în care este spart şirul $a[x..y]$ subsecvenţa ei de sumă maximă.\r\n\r\nMai rămâne să găsim subsecvenţa de sumă maximă cu capătul în bucăţi diferite. Pentru două bucăţi fixate $i < j$, subsecvenţa de sumă maximă ce are câte un capăt în fiecare bucată are valoarea: $max[j] - min[i]$. Determinarea subsecvenţei de sumă maximă cu capetele în bucăţi diferite devine astfel de complexitate $O(K)$. Deci, pentru a rezolva o întrebare trebuie să facem $O(N / K + K)$ calcule. Pentru a reduce complexitatea problemei considerăm pe $K = sqrt(N)$. Complexitatea totală a acestei soluţii este $O(N + M * sqrt(N))$.\r\n\r\nSă vedem ce se întâmplă pe exemplu:\r\n\r\ntable{width:300px; text-align:right;}.\r\n|_. $a$ | - | $-1$ | $2$ | $3$ | $-2$ | $4$ | $-3$ | $8$ | $-3$ | $1$ |\r\n|_. $sum$ | $0$ | $-1$ | $1$ | $4$ | $2$ | $6$ | $3$ | $11$ | $8$ | $9$ |\r\n\r\nşirul e împărţit în trei subsecvenţe $[-1, 2, 3], [-2, 4, -3], [8, -3, 1]$:\r\n\r\ntable{width:100px; text-align:right;}.\r\n|_. $max$ | $4$ | $6$ | $11$ |\r\n|_. $min$ | $-1$ | $2$ | $8$ |\r\n|_. $best$ | $5$ | $4$ | $8$ |\r\n\r\nPentru a răspunde la întrebarea $[1, 5]$ trebuie să răspundem la cele două subsecvenţe componente $[1..3]$ şi $[4..5]$. Soluţia optimă pentru $[1..3]$ este $best[&#49;] = 5$. Soluţia optimă pentru $[4..5]$ o determinăm folosind algoritmul liniar, ea fiind $4$. Acum, pentru a determina subsecvenţa de sumă maximă cu câte un capăt în fiecare interval folosim formula: $max(sum[i]) - min(sum[j - 1])$, unde $4 &le; i &le; 5$ şi $1 &le; j &le; 3$. Valoarea $max(sum[i])$ o găsim parcurgând intervalul $[4, 5]$ ca fiind $6$, iar valoarea $min(sum[j - 1])$ o avem deja calculată în $min[&#49;]$. De aici obţinem rezultatul $7$.\r\n\r\nO soluţie similară poate fi obţinută cu ajutorul arborilor de intervale. Mai întâi creăm arborele de intervale. Pentru fiecare interval aflăm elementele $min$, $max$ şi $best$ astfel:\r\n\r\n* $min[x..y] = minim(min[x..(x+y)/2], min[(x+y)/2 + 1 .. y])$;\r\n\r\n* $max[x..y] = maxim(max[x..(x+y)/2], max[(x+y)/2 + 1 .. y])$;\r\n\r\n* $best[x..y] = maxim(best[x..(x+y)/2], maxim(best[(x+y)/2 + 1 .. y], max[(x+y)/2 + 1 .. y] - min[x..(x+y)/2]))$.\r\n\r\nAcum pentru a răspunde la întrebările din problemă fiecare interval va fi împărţit în $O(log N)$ subintervale canonice care apar în arborele de intervale. Apoi printr-o parcurgere asemănătoare celei din rezolvarea anterioară se poate obţine rezultatul pentru fiecare întrebare în $O(log N)$. Soluţia va avea complexitatea $O(N + M * log N)$.\r\n\r\nÎn următorul desen observăm structura unui arbore de intervale pentru un şir cu $16$ elemente. Daca se pune întrebarea $[2, 11]$ acest interval va fi spart în intervalele $[2, 2], [3, 4], [5, 8], [9, 10], [11, 11]$.\r\n\r\n!probleme-cu-secvente?numere2.png!\r\n\r\nPrezentăm procedura de construire a arborelui, implementată în _java_:\r\n\r\n== code(java) |\r\npublic void build_tree(int index, int low, int high) {\r\n    if (low == high) {\r\n        if (low != 0) aint[index] = new Node(low, high, a[low] - a[low - 1], a[low], a[low]);\r\n        else aint[index] = new Node(low, high, 0, 0, 0);\r\n    }\r\n    else {\r\n        aint[index] = new Node(low, high, -INFINIT, -INFINIT, INFINIT);\r\n        int mid = (low + high) / 2;\r\n        build_tree(2 * index, low, mid);\r\n        build_tree(2 * index + 1, mid + 1, high);\r\n        aint[index].maxS = Math.max(aint[2 * index].maxS,\r\n                Math.max(aint[2 * index + 1].maxS, aint[2 * index + 1].max - aint[2 * index].min));\r\n        aint[index].max = Math.max(aint[2 * index].max, aint[2 * index + 1].max);\r\n        aint[index].min = Math.min(aint[2 * index].min, aint[2 * index + 1].min);\r\n    }\r\n}\r\n==\r\n\r\nşi procedura care răspunde la întrebări tot în _java_:\r\n\r\n== code(java) |\r\nlong minPrefix;\r\nint x, y;\r\npublic long queryTree(int index, int low, int high) {\r\n    if (x <= low && high <= y) {\r\n        long maxRet = aint[index].maxS;\r\n        if (minPrefix != INFINIT) {\r\n            maxRet = Math.max(maxRet, aint[index].max - minPrefix);\r\n        }\r\n        minPrefix = Math.min(minPrefix, aint[index].min);\r\n        return maxRet;\r\n    }\r\n    else {\r\n        int mid = (low + high) / 2;\r\n        if (x <= mid && mid < y) \r\n            return Math.max(queryTree(2 * index, low, mid), queryTree(2 * index + 1, mid + 1, high));\r\n        else if (x > mid) \r\n            return queryTree(2 * index + 1, mid + 1, high);\r\n        else \r\n            return queryTree(2 * index, low, mid);\r\n    }\r\n}\r\n==\r\n\r\nAutorul vă recomandă articolele [1] şi [2] pentru o înţelegere mai profundă a structurii de date numită arbori de intervale. Problema poate fi soluţionată şi în $O(N + M)$, dar algoritmul este mult prea complicat pentru un concurs de programare; cei interesaţi pot să îl găsească în [4].\r\n\r\nh2(#problema-4). Problema 4 (ACM ICPC NWERC 97, olimpiada online 2000, .campion 2001)\r\n\r\nbq. Se dă un şir $(a{~1~}, a{~2~}, ..., a{~N~})$ format din numere întregi. Se cere să se determine subsecvenţa $a[i..j]$ care are modulul sumei elementelor minim.\r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(2, 8, -6, -6, 9, 4, -3)$, subsecvenţa este $(4, -3)$, având suma în modul $1 = |4 - 3|$.\r\n\r\nh3. Rezolvare:\r\n\r\nConstruim întâi şirul sumelor parţiale. Pentru oricare două elemente $sum[i]$ şi $sum[j]$ cu $(i != j)$ modulul sumei unei subsecvenţe din şir va fi $|sum[i] - sum[j]|$. Dacă $i < j$, atunci secvenţa va fi $a[i+1..j]$, iar dacă $j < i$, atunci secvenţa va fi $a[j+1 .. i]$. Astfel, pentru a găsi subsecvenţa de modul minim trebuie, de fapt, să găsim perechea de indici $i$ şi $j$ astfel ca $|sum[i] - sum[j]|$ să fie minim. Sortând şirul sumelor parţiale şi luând o pereche de indici $i < j$, atunci $sum[i] < sum[j]$, iar $|sum[j] - sum[i]| = sum[j] - sum[i]$. Pentru a găsi perechea $(i, j)$ pentru care $i < j$ şi $sum[j] - sum[i]$ este minim, trebuie ca $i$ să fie egal cu $j + 1$. Astfel obţinem un algoritm de complexitate $O(N * log N)$.\r\n\r\nSă vedem cum merge pe exemplul prezentat:\r\n\r\ntable{width:300px; text-align:right;}.\r\n|_. $a$ | - | $2$ | $8$ | $-6$ | $-6$ | $9$ | $4$ | $-3$ |\r\n|_. $sum$ | $0$ | $2$ | $10$ | $4$ | $-2$ | $7$ | $11$ | $8$ |\r\n|_. $ind$ | $0$ | $1$ | $2$ | $3$ | $4$ | $5$ | $6$ | $7$ |\r\n\r\nÎn şirul $ind$ vom păstra indicii reali ai sumelor parţiale. După sortare avem:\r\n\r\ntable{width:300px; text-align:right;}.\r\n|_. $sum$ | $-2$ | $0$ | $2$ | $4$ | $7$ | $8$ | $10$ | $11$ | \r\n|_. $ind$ | $4$ | $0$ | $1$ | $4$ | $5$ | $7$ | $2$ | $6$ |\r\n\r\nO secvenţă de modul $2$ ar fi cea reprezentată de sumele $8$ şi $10$, cu indicii $7$ şi $2$. Această secvenţă este $(-6, -6, 9, 4, -3)$. Observăm ca cea mai mică diferenţă între termeni consecutivi e cea dintre $8$ şi $7$, care au indicii $7$ şi $5$, de unde obţinem că subsecvenţa de modul minim este $(4, -3)$. \r\n\r\nh2(#problema-5). Problema 5 (USACO)\r\n\r\nbq. Se dă un şir $(a{~1~}, a{~2~}, ..., a{~N~})$ format din $N (1 &le; N &le; 100 000)$ numere întregi $(1 &le; a{~i~} &le; 2 000)$ si un numar natural $F$. Se cere să se determine subsecvenţa $a[i..i + K - 1]$ cu media aritmetică a elementelor maximă, unde $K$ are proprietatea $K &ge; F$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(6, 4, 2, 10, 3, 8, 5, 9, 4, 1)$ şi $F = 6$ soluţia optimă este $(10, 3, 8, 5, 9, 4)$, cu media $6.5$.\r\n\r\nh3. Rezolvare:\r\n\r\nFie $X$ un număr real. Considerând şirul $b$, obţinut prin transformarea $b{~i~} = a{~i~} - X$, atunci toate subsecvenţele şirului $b$ vor avea valoarea mediei elementelor lor cu $X$ mai mică decât valoarea subsecvenţelor corespunzătoare din şirul $a$. Observăm apariţia a trei cazuri:\r\n\r\n* Dacă subsecvenţa de sumă maximă din $b$ are valoarea mai mare ca $0$, atunci şi media ei va fi mai mare ca $0$. Rezultă astfel că şi media subsecvenţei corespunzătoare din şirul $a$ va fi mai mare decât $X$, deci media maximă a unei subsecvenţe din $a$ va fi mai mare ca $X$. \r\n\r\n* Cand subsecvenţa de sumă maximă din şirul $b$ are media mai mică decât $0$, atunci orice subsecvenţă din şirul $a$ va avea media mai mică decât $X$. \r\n\r\n* În cazul în care subsecvenţa de sumă maximă a şirului $b$ are valoarea egală cu zero, atunci subsecvenţa de medie maximă a şirului $a$ are media $X$.\r\n\r\nAstfel putem face o căutare binară pentru a determina valoarea $X$ a mediei maxime. Ne mai rămâne să determinăm un algoritm eficient pentru găsirea subsecvenţei de sumă maximă de lungime cel puţin $F$. O asemenea soluţie urmăreşte una din ideile din prima problemă: fie $best[i]$ subsecvenţa de sumă maximă ce se termină în $a[i]$. Evident $best[i] = max(a[i], best[i - 1] + a[i])$. Acum secvenţa de sumă maximă ce se termină în $a[i]$, de lungime cel puţin $F$ se găseşte ca $a[i] + a[i - 1] + .. + a[i - F + 2] + best[i - F + 1]$. Această relaţie poate fi calculată în $O(1)$ dacă ne folosim de trucul sumelor parţiale. Complexitatea finală este $O(N * log C)$, unde $C$ e valoarea maximă a lui $a{~i~}$.\r\n\r\nh2(#problema-6). Problema 6 (\'Secvenţă\':problema/secventa)\r\n\r\nbq. Se da un şir de $N$ numere întregi. O secvenţă este un subşir de numere care apar pe poziţii consecutive în şirul iniţial. Definim baza unei secvenţe ca fiind minimul valorilor elementelor din secvenţa respectivă. Fiind dat un număr natural $K$, determinaţi o secvenţă de lungime cel puţin $K$, cu baza maximă. Restrictii: $1 &le; K &le; N &le; 500 000$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru $K = 3$ şi şirul $(-1, 2, 3, 1, 0, 4, 8, 6)$, secvenţa de bază maximă este $(4, 8, 6)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPresupunem că orice secvenţă optimă ar avea lungimea mai mare decât $K$. Atunci putem obţine o secvenţă mai mică, cu aceeaşi bază eliminând unul din capetele unei secvenţe optime. Deci este de ajuns să cautăm secvenţele optime de lungime exact $K$.\r\n\r\nAcum putem face o parcurgere a şirului pentru a rezolva problema. Mai întâi punem într-un $min-heap$ $K$ elemente, verificăm vârful heapului şi obţinem astfel minimul secvenţei $a[1..K]$. Apoi eliminăm elementul $a[&#49;]$ din heap şi inserăm elementul $a[K + 1]$. Prin verificarea vârfului heapului obţinem minimul secvenţei $a[2..K + 1]$. Continuăm procedeul până aflăm elementul minim pentru fiecare subsecvenţă de lungime $K$ a şirului $a$ (complexitate $O(N * log K)$). Există şi alte soluţii pentru găsirea elementului minim al unei subsecvenţe, precum folosirea unui arbore de intervale sau folosirea tehnicii $O(N * log N) / O(1)$ pentru problema _RMQ_.\r\n\r\nO observaţie importantă este aceea că dacă vrem să vedem minimul secvenţei ce se termină în $i$ şi avem $j{~1~} < j{~2~} &le; i$ şi $a[j{~1~}] &ge; a[j{~2~}]$, atunci evident $a[j{~1~}]$ nu va fi minimul secvenţei ce se termină în $i$. Folosim o structură de date ca la soluţia cu heapuri, care adaugă elemente noi şi şterge elemente vechi, dar pe lângă elementele ce au fost inserate acum $K$ paşi şi trebuie şterse, mai ştergem şi elementele mai noi care nu ne vor mai fi utile, după cum este $a[j{~2~}]$ mai sus. Ca structură de date folosim o listă în care putem insera şi şterge de la ambele capete, un _deque_. Fiecare element inserat în deque va fi o pereche de valori, valoarea din şir şi indexul din şir $(a[i], i)$. Când o valoare este inserată în şir, ea este pusă la capătul din dreapta al şirului, dar înainte de inserare cât timp elementul din capătul şirului are valoarea mai mare decât $a[i]$ el este eliminat. La fiecare pas după o inserţie se verifică dacă elementul din capătul din stânga este mai „bătrân” de $K$ iteraţii.\r\n\r\nDin cauza modului în care se fac inserţiile şi ştergerile, şirul va fi sortat totdeauna crescător după indecşi şi crescător după valori. Tot timpul ultimul element din stivă va conţine valoarea bazei. Acest algoritm are complexitatea $O(N)$ pentru că fiecare element este inserat şi şters din deque cel mult o dată.\r\n\r\nSă vedem cum funcţionează rezolvarea pe un exemplu : $a = (-1, 2, 3, 1, 0, 4, 8, 6)$\r\n\r\n* inserăm $(-1, 1)$\r\nlista devine: $(-1, 1)$\r\n \r\n\r\n* inserăm $(2, 2)$\r\nlista devine: $(-1, 1) (2, 2)$\r\n\r\n\r\n* inserăm $(3, 3)$\r\nlista devine: $(-1, 1) (2, 2) (3, 3)$\r\nelementul minim al secvenţei $a[1..3]$ este $-1$\r\n\r\n\r\n* inserăm $(1, 4)$\r\nştergem $(3, 3)$ şi $(2, 2)$\r\nştergem $(-1, 1)$ ( inserat acum $4$ paşi )\r\nlista de vine: $(1, 4)$\r\nelementul minim al secvenţei $a[2..4]$ este $1$\r\n\r\n\r\n* inserăm $(0, 5)$\r\nştergem $(1, 4)$\r\nlista devine: $(0, 5)$\r\nelementul minim al secvenţei $a[3..5]$ este $0$.\r\n\r\n\r\n* inserăm $(4, 6)$\r\nlista devine: $(0, 5) (4, 6)$\r\nelementul minim al secvenţei $a[4..6]$ este $0$\r\n\r\n\r\n* inserăm $(8, 7)$\r\nlista devine: $(0, 5) (4, 6) (8, 7)$\r\nelementul minim al secvenţei $a[5..7]$ este $0$\r\n\r\n\r\n* inserăm $(6, 8)$\r\nştergem $(8, 7)$\r\nştergem $(0, 5)$ ( inserat acum $4$ paşi )\r\nlista devine: $(4, 6) (6, 8)$\r\nelementul minim al secvenţei $a[6..8]$ este $4$\r\n\r\nh2(#problema-7). Problema 7 (Agricultura, Algoritmus)\r\n\r\nbq. Se dă o matrice de dimensiuni $N x M$ de numere naturale. Se cere determinarea unei submatrici cu număr maxim de celule în care diferenţa între valoarea maximă şi valoarea minimă este mai mică decât o valoare dată $K$. Restrictii: $2 &le; N, M &le; 150$, $1 &le; K &le; 1 000$.\r\n\r\nh3. Exemplu:\r\n\r\nDe exemplu pentru $K = 3$ şi matricea <tex>\\[ \\left( \\begin{array}{cccccc}1 & 1 & 3 & 1 & 2 & 7 \\\\9 & 2 & 3 & 2 & 3 & 2 \\\\7 & 8 & 2 & 3 & 1 & 5 \\\\4 & 5 & 6 & 0 & 1 & 4 \\end{array} \\right)\\]</tex>, soluţia optimă va avea $9$ celule.\r\n\r\nh3. Rezolvare:\r\n\r\nProblema constă în determinarea submatricei cu număr maxim de celule în care diferenţa între valoarea maximă şi valoarea minimă este mai mică decât $K$. Vom folosi ideea de la problema cu subsecvenţa de sumă maximă pe matrice, adică vom fixa două linii $i{~1~}$ şi $i{~2~}$. Acum pentru fiecare coloană $j$ păstrăm în $m[j]$ elementul minim şi în $M[j]$ elementul maxim $a[i][j]$ cu $i{~1~} &le; i &le; i{~2~}$. Astfel la fiecare pas trebuie acum să rezolvăm problema determinării unei subsecvenţe de lungime maximă pentru care diferenţa între elementul maxim şi minim este mai mică decât $K$. Folosind un _max-heap_ şi un _min-heap_ putem parcurge elementele şirurilor $M$ şi $m$ în ordine inserând la fiecare pas elemente în heap şi determinând cea mai lungă secvenţă ce se termină în $i$ cu proprietatea dată. Vom ţine un al $2$-lea indice $j$, iniţial $0$, care atâta timp cât diferenţa între elementul maxim din max-heap cu elementul minim din min-heap este mai mare sau egală cu $K$, vom scoate din heapuri elementele $M[j]$, respectiv $m[j]$ şi îl vom incrementa pe $j$. Complexitate: $O(N^3^ log N)$. Dacă în loc de heapuri folosim deque-uri, atunci acest algoritm va avea complexitatea $O(N^3^)$.\r\n\r\nh2(#problema-8). Problema 8 (\'Secvenţa 2\':problema/secv2)\r\n\r\nbq. Se da un şir de $N$ numere întregi şi un număr natural $K$. O secvenţă este un subşir de numere care apar pe poziţii consecutive în şirul iniţial. Se cere să se găsească secvenţa de sumă maximă de lungime cel puţin $K$. Restrictii: $1 &le; K &le; N &le; 50 000$.\r\n\r\nh3. Exemplu:\r\n\r\nDe exemplu pentru şirul $(0, -6, 2, 1, 4, -1,  3, -5)$ şi $K = 3$, soluţia optimă este $(2, 1, 4, -1, 3)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPutem folosi rezolvarea liniară bazată pe programare dinamică prezentată ca subalgoritm în soluţia \'problemei $5$\':probleme-cu-secvente#problema-5, dar putem simplifica logica din acea rezolvare. Vom folosi şirul sumelor parţiale $sum[]$, iar pentru a determina subsecvenţa de sumă maximă ce se termină în $i$ şi are lungimea cel puţin $K$ trebuie să găsim $sum[j]$ minim astfel ca $j < i - K$. Parcurgem lista, şi la pasul $i$ determinăm $best[i] = sum[i] - min(sum[j])$, $j < i - K$. Comparăm minimul curent cu $sum[i - K]$ şi trecem la pasul următor. Complexitate: $O(N)$.\r\n\r\nh2(#problema-9). Problema 9 (\'Sum\':problema/sum2, Stelele Informaticii 2003 )\r\n\r\nbq. Se dă un şir de $N$ numere întregi. Se caută un subşir cu lungimea cuprinsă între $L$ şi $U$, format din elemente consecutive ale şirului iniţial, cu suma elementelor maximă. Restrictii: $1 &le; L &le; U &le; N &le; 100 000$.\r\n\r\nh3. Rezolvare:\r\n\r\nPentru fiecare $i$ este de ajuns să aflăm valoarea expresiei $sum[i] - sum[j]$, unde $i - L > j &ge; i - U$. Pentru a determina valoarea optimă pentru $sum[j]$ putem folosi un heap de dimensiune $U - L$, sau putem folosi tehnici de determinare a valorii minime într-un interval dat. Complexitate: $O(N * log(U - L))$.\r\n\r\nAltă abordare de aflare a minimelor unor secvenţe de lungime dată (în cazul acesta lungimea este $U - L$ ) a fost prezentată în rezolvarea \'problemei $6$\':probleme-cu-secvente#problema-6. Folosind acea tehnică obţinem o rezolvare de complexitate liniară.\r\n\r\nO altă rezolvare frumoasă prezentată în [4] este următoarea: spunem că o secvenţă este negativă spre stânga dacă suma oricărui prefix ( în afară de secvenţa în sine ) al secvenţei este negativ sau zero. O partiţie a secvenţei $A = (A{~1~}, A{~2~}, ..., A{~k~})$ este minimală negativă spre stânga dacă fiecare $A{~i~}$ este negativă spre stânga, iar suma elementelor lui $A{~i~}$ este strict pozitivă dacă $i != k$. De exemplu secvenţa $(-4, 1, -2, 3)$ este negativă la stânga, pe când secvenţa $(5, -3, 4, -1, 2, -6)$ nu este. Partiţia $(5) (-3, 4) (-1, 2) (-6)$ este minimală negativă la stânga.\r\n\r\nPentru fiecare element din partiţie ţinem minte un pointer $p[i]$ spre ultimul element din subsecvenţa din care face parte. Fiecare interval $[i, p[i]]$ va corespunde celei mai scurte subsecvenţe care începe în $i$ şi are suma pozitivă. Pentru a determina o soluţie a problemei pentru fiecare $i$ din care poate începe o subsecvenţă de sumă maximă, ne vom plimba cu un pointer $j$ astfel ca $j$ să fie cât mai depărtat de $i$ şi $j - i + 1 &le; U$. Obţinem astfel de fiecare dată o subsecvenţă de sumă maximă ce începe în $i$, cu lungimea mai mică sau egală cu $U$. Indicele $j$ va fi întotdeauna un capăt de secvenţă negativă la stânga şi la fiecare mărire a lui $i$ verificăm dacă lui $j$ îi putem atribui valoarea $p[j + 1]$ ( adică dacă $p[j + 1] - i + 1 &le; U$ ). Dacă secvenţa de sumă maximă de lungime cel mult $U$ ce începe în $i$ are lungimea mai mică decât $L$, atunci secvenţa de sumă maximă cu lungimea cuprinsă între $L$ şi $U$ are lungimea exact $L$. Complexitate: $O(N)$.\r\n\r\nh2(#problema-10). Problema 10 (\'Secvenţa 3\':problema/secv3)\r\n\r\nbq. Se dă un şir de $N$ elemente pentru care se cunosc două informaţii: costul şi timpul. O secvenţă este un subşir de numere care apar pe poziţii consecutive în şirul iniţial. Se caută o secvenţă din cele $N$ elemente care să fie de lungime minim $L$ şi maxim $U$, iar suma costurilor elementelor secvenţei împărţiţă la suma timpurilor elementelor secvenţei să fie maximă. Restrictii: $1 &le; L &le; U &le; N &le; 30 000$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru $L = 1, R = 2$ şi şirurile $c = ( 1, 1, 3, 2, 5 )$ şi $t = ( 4, 2, 5, 3, 6 )$, subsecvenţa cea mai eficientă are costul $0.83$.\r\n\r\nh3. Rezolvare:\r\n\r\nProcedăm ca la \'problema $5$\':probleme-cu-secvente#problema-5 şi căutăm binar valoarea optimă. şirul va fi transformat în: $b[i] = c[i] - t[i] * X$, $i = 1..N$. Acum trebuie să mai rezolvăm subproblema care cere să determinăm o subsecvenţă de sumă maximă pentru care lungimea se află între $L$ şi $U$. Această subproblemă a fost soluţionată în \'problema anterioară\':probleme-cu-secvente#problema-9, unde s-a găsit un algoritm liniar. Astfel soluţia acestei probleme are complexitatea $O(N * log C)$.\r\n\r\nh2(#problema-11). Problema 11 (\'XorMax\':problema/xormax)\r\n\r\nbq. Se dă un şir de $N$ numere întregi nenegative. Să se aleagă o secvenţă a şirului, $(a{~i~}, a{~i+1~}, ..., a{~j~})$, astfel încât $a{~i~} xor a{~i+1~} xor ... xor a{~j~}$ să fie maxim. Restrictii: $1 &le; N &le; 100 000$ si $a{~i~} < 221$ cu $i = 1..N$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(1, 0, 5, 4, 2)$, secvenţa cu valoarea sumei _xor_ maximă este $(4, 2)$, cu suma $6$. \r\n\r\nh3. Rezolvare:\r\n\r\nSuma _xor_ a două numere este de fapt adunare binară fără transport, fapt care o face similară operaţiei _modulo_. Problema e asemănătoare cu cea a subsecvenţei de modul maxim. Vom obţine toate sumele _xor_ parţiale şi pentru a vedea pentru $sum[i]$ perechea optimă cu care crează o sumă cât mai mare trebuie să găsim acea sumă $sum[j]$ astfel că fiecare bit al lui $sum[i]$ să fie diferit de fiecare bit al lui $sum[j]$, dacă acest lucru este posibil. Pentru a face această căutare cât mai eficientă, putem menţine sumele $sum[i]$ ca şiruri de caractere $0$ sau $1$ într-un _trie_ [5]. Structura de trie pentru cazul când alfabetul are dimensiunea $2$ este identică cu cea de heap. Această soluţie are complexitatea $O(N * log C)$.\r\n\r\nh2(#problema-propuse). Probleme propuse\r\n\r\nPentru a vă însuşi mai bine tehnicile învăţate în acest articol, puteţi rezolva următoarele probleme:\r\n\r\n* \'Balans\':problema/balans\r\n* \'Struţi\':problema/struti\r\n* \'Deque\':problema/deque\r\n* \'Trie\':problema/trie\r\n* \'Maxq\':problema/maxq\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Dana Lica - \'_Arbori de intervale şi aplicaţii în geometria computaţională_\':arbori-de-intervale\r\n# Cosmin Negruşeri - \'_Căutări Ortogonale: Structuri de date şi aplicaţii_\':cautari-ortogonale\r\n# Takaoka T. - \'_Efficient Algorithms for the Maximum Subarray Problem by Distance Matrix Multiplication_\':http://www.cosc.canterbury.ac.nz/tad.takaoka/cats02.pdf\r\n# Kuan Yu Chen, Kun Mao Chao - \'_On the Range Maximum-Sum Segment Query_\':http://www.csie.ntu.edu.tw/~kmchao/papers/2007_DAM_RMSQ.pdf\r\n# Yaw Ling Liu, Tao Jiang, Kun Mao Chao - \'_Efficient Algorithms for Locating the Length-Constrained Heaviest Segments, with Applications to Biomolecolar Sequence Analysis_\':http://www.csie.ntu.edu.tw/~kmchao/seq2003/mslc.pdf\r\n# T. H. Cormen, C. E. Leiserson, R. R. Rivest - \'_Introducere in Algoritmi_\':http://zhuzeyuan.hp.infoseek.co.jp/ita/toc.htm\r\n\r\nh2. Discuţii pe forum',2044,'public',3553,NULL),('probleme-cu-secvente','Probleme cu secvențe','2008-11-23 19:46:37','2009-01-09 22:37:02','h1. Probleme cu secvenţe\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"alecman\") ==\r\n\r\n(Categoria _Algoritmi şi tehnici de programare_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut*\r\n* \'Introducere \':probleme-cu-secvente#introducere\r\n* \'Problema 1 (Subsecvenţa de sumă maximă) \':probleme-cu-secvente#problema-1\r\n* \'Problema 2 (Maximum Sum) \':probleme-cu-secvente#problema-2\r\n* \'Problema 3 (SequenceQuery) \':probleme-cu-secvente#problema-3\r\n* \'Problema 4 \':probleme-cu-secvente#problema-4\r\n* \'Problema 5 \':probleme-cu-secvente#problema-5\r\n* \'Problema 6 (Secvenţă) \':probleme-cu-secvente#problema-6\r\n* \'Problema 7 (Agricultura) \':probleme-cu-secvente#problema-7\r\n* \'Problema 8 (Secvenţa 2) \':probleme-cu-secvente#problema-8\r\n* \'Problema 9 (Sum) \':probleme-cu-secvente#problema-9\r\n* \'Problema 10 (Secvenţa 3) \':probleme-cu-secvente#problema-10\r\n* \'Problema 11 (XorMax) \':probleme-cu-secvente#problema-11\r\n* \'Probleme propuse\':probleme-cu-secvente#probleme-propuse\r\n* \'Bibliografie\':probleme-cu-secvente#bibliografie\r\n\r\nh2(#introducere). Introducere\r\n\r\nAcest articol prezintă o serie de probleme înrudite cu problema subsecvenţei de sumă maximă, însoţite de rezolvări eficiente. Problemele prezentate pot apărea oricând ca subprobleme în concursurile de programare, studierea lor mărind în mod util bagajul de cunoştinţe al unui elev pasionat de algoritmică.\r\n\r\nh2(#problema-1). Problema 1 (Subsecvenţa de sumă maximă)\r\n\r\nbq. Se dă un şir de $N$ numere întregi $(a{~1~}, a{~2~}, ..., a{~N~})$. Să se determine o subsecvenţă $(a{~i~}, a{~i+1~}, ..., a{~j~})$ care să aibă suma maximă.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(-1, 2, 3, -4, -2, 2, 1, -3, -2, -3, -4, 9, -2, 1, 7, 8, -19, -7, 2, 4, 3)$, o subsecvenţă de sumă maximă este $(9, -2, 1, 7, 8)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPrima rezolvare care ne vine în minte are complexitatea $O(N^3^)$ şi constă în determinarea sumei fiecărei subsecvenţe posibile şi reţinerea maximului acestor sume. Este evident că anumite sume parţiale sunt calculate de mai multe ori.\r\n\r\nPutem reduce complexitatea la $O(N^2^)$ ţinând cont de faptul că suma subsecvenţei $a[i..j]$ este egală cu suma subsecvenţei $a[i..j-1]$, la care se adună $a[j]$. Păstrăm într-un şir $sum[i]$ suma elementelor din subsecvenţa $a[1..i]$. Pentru a determina suma elementelor din subsecvenţa $a[i..j]$ facem diferenţa: $sum[i] - sum[j-1]$.\r\n\r\nIdeea poate fi rafinată calculând pentru fiecare indice $i$ numărul $best[i]$, reprezentând subsecvenţa de sumă maximă cu capătul drept în $i$. Este uşor de observat că $best[i] = max(sum[i] - sum[j-1])$, unde $j$ ia valori de la $1$ la $i$. Relaţia anterioară se mai poate scrie: $best[i] = sum[i] - min(sum[j-1])$. Obţinem astfel un algoritm liniar care ne determină subsecvenţa de sumă maximă cerută.\r\n\r\n== code(cpp) |\r\nsum[0] = 0;\r\nfor (i = 1; i <= N; i++) sum[i] = a[i] + sum[i-1];\r\nmin = sum[0];\r\nbestSum = -INFINIT;\r\nfor (i = 1; i <= N; i++) {\r\n    best[i] = sum[i] - min;\r\n    if (min > sum[i]) min = sum[i];\r\n    if (bestSum < best[i]) bestSum = best[i];\r\n}\r\n==\r\n\r\nO altă metodă de calcul poate fi dedusă folosind paradigma _Divide et Impera_. La fiecare pas împărţim şirul în jumătate şi aflăm subsecvenţele de sumă maximă din cele două jumătăţi. După aceea trebuie să găsim subsecvenţa de sumă maximă ce are un capăt în fiecare din cele două jumătăţi ale sirului. Pentru aceasta alipim sufixul de sumă maximă a primei jumătăţi cu prefixul de sumă maximă a celei de a doua.\r\n\r\n== code(cpp) |\r\nint getMaxSubsequence(int l, int r) {\r\n    if (l == r) return a[l];\r\n    mid = (l + r) / 2;\r\n    bestL = getMaxSubsequence(l, mid);\r\n    bestR = getMaxSubsequence(mid + 1, r);\r\n    suf = 0; \r\n    pre = 0; \r\n    maxSuf = -INFINIT; \r\n    maxPre = -INFINIT;\r\n    for (i = mid; i >= l; i--) {\r\n        suf += a[i];\r\n        if (maxSuf < suf) maxSuf = suf;\r\n    }\r\n    for (i = mid + 1; i <= r; i++) {\r\n        pre += a[i];\r\n        if (maxPre < pre) maxPre = pre;    \r\n    }\r\n    return max(bestL, max(bestR, maxPre + maxSuf));\r\n}\r\n==\r\n\r\nO idee bazată pe paradigma programării dinamice ar fi să folosim un şir $best[i]$, reprezentând suma maximă a unei subsecvenţe ce se termină în $a[i]$. Problema se rezolvă cu următoarea formulă de recurenţă: $best[i] = max(a[i], best[i-1] + a[i])$. Formula poate fi demonstrată prin inducţie matematică.\r\n\r\nO ultimă idee ar fi să partiţionăm şirul în subsecvenţe încât fiecare să aibă ambele capete cât mai mici posibile şi suma elementelor subsecvenţei să fie negativă. Pentru exemplul dat avem următoarea partiţionare: $[-1], [2, 3, -4, -2], [2, 1, -3, -2], [-3], [-4], [9, -2, 1, 7, 8, -19, -7], [2, 4, 3]$. O subsecvenţă de sumă maximă va avea primul capăt la începutul unei astfel de subsecvenţe, acest lucru explicându-se prin faptul că în caz contrar secvenţa poate fi mărită în stânga (orice secvenţă din cele alese pentru partiţionare are toate prefixele de sumă pozitivă, în afară de prefixul ce reprezintă întreaga subsecvenţă). De asemenea, orice subsecvenţă de sumă maximă nu va conţine elemente din altă parte a partiţiei, pentru că dacă subsecvenţa se întinde pe mai multe părţi, atunci putem elimina prefixul subsecvenţei care reprezintă o parte a partiţiei, acea parte având suma negativă.\r\n\r\n== code(cpp) |\r\nsum = -INFINIT;\r\nbestSum = -INFINIT;\r\nfor (i = 1; i <= N; i++) {\r\n    sum += a[i];\r\n    if (sum < 0)\r\n        sum = 0;\r\n    else if (sum >= bestSum) \r\n        bestSum = sum;      \r\n}\r\n==\r\n\r\nh2(#problema-2). Problema 2 (\'Maximum Sum\':http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&Itemid=8&category=3&page=show_problem&problem=44, UVa)\r\n\r\nbq. Se dă o matrice de dimensiuni $N x N$ cu elemente întregi. Se cere determinarea unei submatrici a cărei elemente au suma maximă. \r\n\r\nh3. Exemplu:\r\n\r\nPentru matricea<tex>\\[ \\left( \\begin{array}{cccc}0 & -2 & -7 & 0 \\\\9 & 2 & -6 & 2 \\\\-4 & 1 & -4 & 1 \\\\-1 & 8 & 0 & -2 \\end{array} \\right)\\]</tex>submatricea de sumă maximă este următoarea:<tex>\\[ \\left( \\begin{array}{cc}9 & 2 \\\\-4 & 1 \\\\-1 & 8 \\end{array} \\right)\\]</tex>\r\n\r\nh3. Rezolvare:\r\n\r\nPutem folosi trucul construirii sumelor parţiale din rezolvarea anterioară, pentru cazul $2D$. Păstrăm în $sum[i][j]$ suma tuturor elementelor $a[i{~1~}][j{~1~}]$ cu proprietatea că $1 &le; i{~1~} &le; i$, şi $1 &le; j{~1~} &le; j$. Putem calcula sumele prin metoda programării dinamice în complexitate $O(N^2^)$ folosind formula: $sum[i][j] = a[i][j] + sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1]$. Acum, pentru a calcula suma elementelor din matricea cu colţurile $(i{~1~}, j{~1~})$ şi $(i{~2~}, j{~2~})$, unde $i{~1~} &le; i{~2~}$ şi $j{~1~} &le; j{~2~}$, este suficient să facem calculul $sum[i{~2~}][j{~2~}] - sum[i{~1~}-1][j{~2~}] - sum[i{~2~}][j{~1~}-1] + sum[i{~1~}-1][j{~1~}-1]$. Astfel putem evalua suma din fiecare submatrice în timp constant, deci rezolvarea are ordinul de complexitate $O(N^4^)$.\r\n\r\nO altă idee ar fi ca pentru fiecare pereche $(i{~1~}, i{~2~})$ fixată să determinăm perechea optimă $(j{~1~}, j{~2~})$. Dacă avem liniile $i{~1~}$ şi $i{~2~}$ fixate atunci problema se transformă din una bidimensională în una unidimensională. Astfel pentru fiecare coloană $j$ vom considera $b[j]$ ca sumă a elementelor $a[i][j]$ cu proprietatea că $i{~1~} &le; i &le; i{~2~}$. În exemplul nostru, dacă $i{~1~} = 2$ şi $i{~2~} = 3$, atunci avem: $b{~1~} = 9 + (-4)$, $b{~2~} = 2 + 1$, $b{~3~} = (-6) + (-4)$ şi $b{~4~} = 2 + 1$. Pentru a rezolva problema unidimensională folosim unul din algoritmii liniari prezentaţi mai sus, astfel obţinându-se un algoritm de complexitate totală $O(N^3^)$. Acest truc de a fixa două linii pentru a transforma problema în una unidimensională este util în multe probleme pe matrice sau cu puncte în plan.\r\n\r\nCel mai bun algoritm cunoscut pentru această problemă are complexitatea <tex>O(N^{3\\sqrt{\\frac{\\log \\log N}{\\log N}}})</tex> şi este mai mult un algoritm teoretic decât unul practic, uşor implementabil. Pentru detalii puteti consulta lucrarea [3].\r\n\r\nh2(#problema-3). Problema 3 (\'SequenceQuery\':problema/sequencequery, Bursele Agora 2006)\r\n\r\nbq. Se consideră un şir $A = (a{~1~}, a{~2~}, ..., a{~N~})$, format din numere întregi $(-100.000 &le; a{~i~} &le; 100.000)$, şi $M$ perechi de numere $(x, y)$ $(1 &le; N, M &le; 100.000)$. Pentru fiecare pereche ordonată de indici $(x, y)$ trebuie determinată subsecvenţa de sumă maximă a subşirului $a{~x~}, a{~x+1~}, ..., a{~y~}$. Subsecvenţele alese trebuie să conţină cel puţin un element. \r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(-1, 2, 3, -2, 4, -3, 8, -3)$ şi intervalele $[1, 5]$, $[4, 8]$ si $[6, 6]$ avem soluţiile: \r\n\r\n* $7$ pentru subsecvenţa $(-1, *2*, *3*, *-2*, *4*)$;\r\n\r\n* $9$ pentru subsecvenţa $(-2, *4*, *-3*, *8*, -3)$;\r\n\r\n* $-3$ pentru subsecvenţa $({*-3*})$.\r\n\r\nh3. Rezolvare:\r\n\r\nPutem obţine un algoritm de complexitate $O(M * N)$ folosind algoritmii liniari din prima problemă, dar să vedem cum putem reduce complexitatea folosind alte abordări. Mai întâi calculăm şirul $sum[]$ al sumelor parţiale, după care împărţim şirul în $K$ subsecvenţe de lungimi egale $[N / K]$, şi păstrăm următoarele informaţii pentru fiecare din ele:\r\n\r\n* $max[i]$ - cea mai mare valoare $sum[j]$, unde: $N / K * (i - 1) < j &le; N / K * i$;\r\n\r\n* $min[i]$ - cel mai mic $sum[j - 1]$, unde: $N / K * (i - 1) < j &le; N / K * i$;\r\n\r\n* $best[i]$ - valoarea subsecventei de suma maxima a secventei curente.\r\n\r\nAcum, pentru a afla subsecvenţa de sumă maximă a subsecvenţei $a[x..y]$ studiem cele două cazuri posibile:\r\n\r\n1. Dacă elementele de indice $x$ şi $y$ aparţin aceleiaşi subsecvenţe, atunci putem găsi ceea ce căutăm folosind algoritmul liniar direct pe şirul $a[x..y]$. Complexitate: $O(N / K)$.\r\n\r\n2. Dacă nu sunt în aceeaşi secvenţă, atunci vom împărţi şirul $a[x..y]$ în:\r\n\r\n* un prefix de subsecvenţă din cele ce aparţin partiţionării,\r\n\r\n* un sufix de subsecvenţă,\r\n\r\n* zero sau mai multe subsecvenţe complete ce aparţin partiţionării,\r\n\r\ndupă care rezolvăm problema pentru sufix şi prefix prin metoda liniară în $O(N / K)$, şi determinăm în $O(1)$ pentru fiecare bucată în care este spart şirul $a[x..y]$ subsecvenţa ei de sumă maximă.\r\n\r\nMai rămâne să găsim subsecvenţa de sumă maximă cu capătul în bucăţi diferite. Pentru două bucăţi fixate $i < j$, subsecvenţa de sumă maximă ce are câte un capăt în fiecare bucată are valoarea: $max[j] - min[i]$. Determinarea subsecvenţei de sumă maximă cu capetele în bucăţi diferite devine astfel de complexitate $O(K)$. Deci, pentru a rezolva o întrebare trebuie să facem $O(N / K + K)$ calcule. Pentru a reduce complexitatea problemei considerăm pe $K = sqrt(N)$. Complexitatea totală a acestei soluţii este $O(N + M * sqrt(N))$.\r\n\r\nSă vedem ce se întâmplă pe exemplu:\r\n\r\ntable{width:300px; text-align:right;}.\r\n|_. $a$ | - | $-1$ | $2$ | $3$ | $-2$ | $4$ | $-3$ | $8$ | $-3$ | $1$ |\r\n|_. $sum$ | $0$ | $-1$ | $1$ | $4$ | $2$ | $6$ | $3$ | $11$ | $8$ | $9$ |\r\n\r\nşirul e împărţit în trei subsecvenţe $[-1, 2, 3], [-2, 4, -3], [8, -3, 1]$:\r\n\r\ntable{width:100px; text-align:right;}.\r\n|_. $max$ | $4$ | $6$ | $11$ |\r\n|_. $min$ | $-1$ | $2$ | $8$ |\r\n|_. $best$ | $5$ | $4$ | $8$ |\r\n\r\nPentru a răspunde la întrebarea $[1, 5]$ trebuie să răspundem la cele două subsecvenţe componente $[1..3]$ şi $[4..5]$. Soluţia optimă pentru $[1..3]$ este $best[&#49;] = 5$. Soluţia optimă pentru $[4..5]$ o determinăm folosind algoritmul liniar, ea fiind $4$. Acum, pentru a determina subsecvenţa de sumă maximă cu câte un capăt în fiecare interval folosim formula: $max(sum[i]) - min(sum[j - 1])$, unde $4 &le; i &le; 5$ şi $1 &le; j &le; 3$. Valoarea $max(sum[i])$ o găsim parcurgând intervalul $[4, 5]$ ca fiind $6$, iar valoarea $min(sum[j - 1])$ o avem deja calculată în $min[&#49;]$. De aici obţinem rezultatul $7$.\r\n\r\nO soluţie similară poate fi obţinută cu ajutorul arborilor de intervale. Mai întâi creăm arborele de intervale. Pentru fiecare interval aflăm elementele $min$, $max$ şi $best$ astfel:\r\n\r\n* $min[x..y] = minim(min[x..(x+y)/2], min[(x+y)/2 + 1 .. y])$;\r\n\r\n* $max[x..y] = maxim(max[x..(x+y)/2], max[(x+y)/2 + 1 .. y])$;\r\n\r\n* $best[x..y] = maxim(best[x..(x+y)/2], maxim(best[(x+y)/2 + 1 .. y], max[(x+y)/2 + 1 .. y] - min[x..(x+y)/2]))$.\r\n\r\nAcum pentru a răspunde la întrebările din problemă fiecare interval va fi împărţit în $O(log N)$ subintervale canonice care apar în arborele de intervale. Apoi printr-o parcurgere asemănătoare celei din rezolvarea anterioară se poate obţine rezultatul pentru fiecare întrebare în $O(log N)$. Soluţia va avea complexitatea $O(N + M * log N)$.\r\n\r\nÎn următorul desen observăm structura unui arbore de intervale pentru un şir cu $16$ elemente. Daca se pune întrebarea $[2, 11]$ acest interval va fi spart în intervalele $[2, 2], [3, 4], [5, 8], [9, 10], [11, 11]$.\r\n\r\n!probleme-cu-secvente?numere2.png!\r\n\r\nPrezentăm procedura de construire a arborelui, implementată în _java_:\r\n\r\n== code(java) |\r\npublic void build_tree(int index, int low, int high) {\r\n    if (low == high) {\r\n        if (low != 0) aint[index] = new Node(low, high, a[low] - a[low - 1], a[low], a[low]);\r\n        else aint[index] = new Node(low, high, 0, 0, 0);\r\n    }\r\n    else {\r\n        aint[index] = new Node(low, high, -INFINIT, -INFINIT, INFINIT);\r\n        int mid = (low + high) / 2;\r\n        build_tree(2 * index, low, mid);\r\n        build_tree(2 * index + 1, mid + 1, high);\r\n        aint[index].maxS = Math.max(aint[2 * index].maxS,\r\n                Math.max(aint[2 * index + 1].maxS, aint[2 * index + 1].max - aint[2 * index].min));\r\n        aint[index].max = Math.max(aint[2 * index].max, aint[2 * index + 1].max);\r\n        aint[index].min = Math.min(aint[2 * index].min, aint[2 * index + 1].min);\r\n    }\r\n}\r\n==\r\n\r\nşi procedura care răspunde la întrebări tot în _java_:\r\n\r\n== code(java) |\r\nlong minPrefix;\r\nint x, y;\r\npublic long queryTree(int index, int low, int high) {\r\n    if (x <= low && high <= y) {\r\n        long maxRet = aint[index].maxS;\r\n        if (minPrefix != INFINIT) {\r\n            maxRet = Math.max(maxRet, aint[index].max - minPrefix);\r\n        }\r\n        minPrefix = Math.min(minPrefix, aint[index].min);\r\n        return maxRet;\r\n    }\r\n    else {\r\n        int mid = (low + high) / 2;\r\n        if (x <= mid && mid < y) \r\n            return Math.max(queryTree(2 * index, low, mid), queryTree(2 * index + 1, mid + 1, high));\r\n        else if (x > mid) \r\n            return queryTree(2 * index + 1, mid + 1, high);\r\n        else \r\n            return queryTree(2 * index, low, mid);\r\n    }\r\n}\r\n==\r\n\r\nAutorul vă recomandă articolele [1] şi [2] pentru o înţelegere mai profundă a structurii de date numită arbori de intervale. Problema poate fi soluţionată şi în $O(N + M)$, dar algoritmul este mult prea complicat pentru un concurs de programare; cei interesaţi pot să îl găsească în [4].\r\n\r\nh2(#problema-4). Problema 4 (ACM ICPC NWERC 97, olimpiada online 2000, .campion 2001)\r\n\r\nbq. Se dă un şir $(a{~1~}, a{~2~}, ..., a{~N~})$ format din numere întregi. Se cere să se determine subsecvenţa $a[i..j]$ care are modulul sumei elementelor minim.\r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(2, 8, -6, -6, 9, 4, -3)$, subsecvenţa este $(4, -3)$, având suma în modul $1 = |4 - 3|$.\r\n\r\nh3. Rezolvare:\r\n\r\nConstruim întâi şirul sumelor parţiale. Pentru oricare două elemente $sum[i]$ şi $sum[j]$ cu $(i != j)$ modulul sumei unei subsecvenţe din şir va fi $|sum[i] - sum[j]|$. Dacă $i < j$, atunci secvenţa va fi $a[i+1..j]$, iar dacă $j < i$, atunci secvenţa va fi $a[j+1 .. i]$. Astfel, pentru a găsi subsecvenţa de modul minim trebuie, de fapt, să găsim perechea de indici $i$ şi $j$ astfel ca $|sum[i] - sum[j]|$ să fie minim. Sortând şirul sumelor parţiale şi luând o pereche de indici $i < j$, atunci $sum[i] < sum[j]$, iar $|sum[j] - sum[i]| = sum[j] - sum[i]$. Pentru a găsi perechea $(i, j)$ pentru care $i < j$ şi $sum[j] - sum[i]$ este minim, trebuie ca $i$ să fie egal cu $j + 1$. Astfel obţinem un algoritm de complexitate $O(N * log N)$.\r\n\r\nSă vedem cum merge pe exemplul prezentat:\r\n\r\ntable{width:300px; text-align:right;}.\r\n|_. $a$ | - | $2$ | $8$ | $-6$ | $-6$ | $9$ | $4$ | $-3$ |\r\n|_. $sum$ | $0$ | $2$ | $10$ | $4$ | $-2$ | $7$ | $11$ | $8$ |\r\n|_. $ind$ | $0$ | $1$ | $2$ | $3$ | $4$ | $5$ | $6$ | $7$ |\r\n\r\nÎn şirul $ind$ vom păstra indicii reali ai sumelor parţiale. După sortare avem:\r\n\r\ntable{width:300px; text-align:right;}.\r\n|_. $sum$ | $-2$ | $0$ | $2$ | $4$ | $7$ | $8$ | $10$ | $11$ | \r\n|_. $ind$ | $4$ | $0$ | $1$ | $4$ | $5$ | $7$ | $2$ | $6$ |\r\n\r\nO secvenţă de modul $2$ ar fi cea reprezentată de sumele $8$ şi $10$, cu indicii $7$ şi $2$. Această secvenţă este $(-6, -6, 9, 4, -3)$. Observăm ca cea mai mică diferenţă între termeni consecutivi e cea dintre $8$ şi $7$, care au indicii $7$ şi $5$, de unde obţinem că subsecvenţa de modul minim este $(4, -3)$. \r\n\r\nh2(#problema-5). Problema 5 (USACO)\r\n\r\nbq. Se dă un şir $(a{~1~}, a{~2~}, ..., a{~N~})$ format din $N (1 &le; N &le; 100 000)$ numere întregi $(1 &le; a{~i~} &le; 2 000)$ si un numar natural $F$. Se cere să se determine subsecvenţa $a[i..i + K - 1]$ cu media aritmetică a elementelor maximă, unde $K$ are proprietatea $K &ge; F$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(6, 4, 2, 10, 3, 8, 5, 9, 4, 1)$ şi $F = 6$ soluţia optimă este $(10, 3, 8, 5, 9, 4)$, cu media $6.5$.\r\n\r\nh3. Rezolvare:\r\n\r\nFie $X$ un număr real. Considerând şirul $b$, obţinut prin transformarea $b{~i~} = a{~i~} - X$, atunci toate subsecvenţele şirului $b$ vor avea valoarea mediei elementelor lor cu $X$ mai mică decât valoarea subsecvenţelor corespunzătoare din şirul $a$. Observăm apariţia a trei cazuri:\r\n\r\n* Dacă subsecvenţa de sumă maximă din $b$ are valoarea mai mare ca $0$, atunci şi media ei va fi mai mare ca $0$. Rezultă astfel că şi media subsecvenţei corespunzătoare din şirul $a$ va fi mai mare decât $X$, deci media maximă a unei subsecvenţe din $a$ va fi mai mare ca $X$. \r\n\r\n* Cand subsecvenţa de sumă maximă din şirul $b$ are media mai mică decât $0$, atunci orice subsecvenţă din şirul $a$ va avea media mai mică decât $X$. \r\n\r\n* În cazul în care subsecvenţa de sumă maximă a şirului $b$ are valoarea egală cu zero, atunci subsecvenţa de medie maximă a şirului $a$ are media $X$.\r\n\r\nAstfel putem face o căutare binară pentru a determina valoarea $X$ a mediei maxime. Ne mai rămâne să determinăm un algoritm eficient pentru găsirea subsecvenţei de sumă maximă de lungime cel puţin $F$. O asemenea soluţie urmăreşte una din ideile din prima problemă: fie $best[i]$ subsecvenţa de sumă maximă ce se termină în $a[i]$. Evident $best[i] = max(a[i], best[i - 1] + a[i])$. Acum secvenţa de sumă maximă ce se termină în $a[i]$, de lungime cel puţin $F$ se găseşte ca $a[i] + a[i - 1] + .. + a[i - F + 2] + best[i - F + 1]$. Această relaţie poate fi calculată în $O(1)$ dacă ne folosim de trucul sumelor parţiale. Complexitatea finală este $O(N * log C)$, unde $C$ e valoarea maximă a lui $a{~i~}$.\r\n\r\nh2(#problema-6). Problema 6 (\'Secvenţă\':problema/secventa)\r\n\r\nbq. Se da un şir de $N$ numere întregi. O secvenţă este un subşir de numere care apar pe poziţii consecutive în şirul iniţial. Definim baza unei secvenţe ca fiind minimul valorilor elementelor din secvenţa respectivă. Fiind dat un număr natural $K$, determinaţi o secvenţă de lungime cel puţin $K$, cu baza maximă. Restrictii: $1 &le; K &le; N &le; 500 000$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru $K = 3$ şi şirul $(-1, 2, 3, 1, 0, 4, 8, 6)$, secvenţa de bază maximă este $(4, 8, 6)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPresupunem că orice secvenţă optimă ar avea lungimea mai mare decât $K$. Atunci putem obţine o secvenţă mai mică, cu aceeaşi bază eliminând unul din capetele unei secvenţe optime. Deci este de ajuns să cautăm secvenţele optime de lungime exact $K$.\r\n\r\nAcum putem face o parcurgere a şirului pentru a rezolva problema. Mai întâi punem într-un $min-heap$ $K$ elemente, verificăm vârful heapului şi obţinem astfel minimul secvenţei $a[1..K]$. Apoi eliminăm elementul $a[&#49;]$ din heap şi inserăm elementul $a[K + 1]$. Prin verificarea vârfului heapului obţinem minimul secvenţei $a[2..K + 1]$. Continuăm procedeul până aflăm elementul minim pentru fiecare subsecvenţă de lungime $K$ a şirului $a$ (complexitate $O(N * log K)$). Există şi alte soluţii pentru găsirea elementului minim al unei subsecvenţe, precum folosirea unui arbore de intervale sau folosirea tehnicii $O(N * log N) / O(1)$ pentru problema _RMQ_.\r\n\r\nO observaţie importantă este aceea că dacă vrem să vedem minimul secvenţei ce se termină în $i$ şi avem $j{~1~} < j{~2~} &le; i$ şi $a[j{~1~}] &ge; a[j{~2~}]$, atunci evident $a[j{~1~}]$ nu va fi minimul secvenţei ce se termină în $i$. Folosim o structură de date ca la soluţia cu heapuri, care adaugă elemente noi şi şterge elemente vechi, dar pe lângă elementele ce au fost inserate acum $K$ paşi şi trebuie şterse, mai ştergem şi elementele mai noi care nu ne vor mai fi utile, după cum este $a[j{~2~}]$ mai sus. Ca structură de date folosim o listă în care putem insera şi şterge de la ambele capete, un _deque_. Fiecare element inserat în deque va fi o pereche de valori, valoarea din şir şi indexul din şir $(a[i], i)$. Când o valoare este inserată în şir, ea este pusă la capătul din dreapta al şirului, dar înainte de inserare cât timp elementul din capătul şirului are valoarea mai mare decât $a[i]$ el este eliminat. La fiecare pas după o inserţie se verifică dacă elementul din capătul din stânga este mai „bătrân” de $K$ iteraţii.\r\n\r\nDin cauza modului în care se fac inserţiile şi ştergerile, şirul va fi sortat totdeauna crescător după indecşi şi crescător după valori. Tot timpul ultimul element din stivă va conţine valoarea bazei. Acest algoritm are complexitatea $O(N)$ pentru că fiecare element este inserat şi şters din deque cel mult o dată.\r\n\r\nSă vedem cum funcţionează rezolvarea pe un exemplu : $a = (-1, 2, 3, 1, 0, 4, 8, 6)$\r\n\r\n* inserăm $(-1, 1)$\r\nlista devine: $(-1, 1)$\r\n \r\n\r\n* inserăm $(2, 2)$\r\nlista devine: $(-1, 1) (2, 2)$\r\n\r\n\r\n* inserăm $(3, 3)$\r\nlista devine: $(-1, 1) (2, 2) (3, 3)$\r\nelementul minim al secvenţei $a[1..3]$ este $-1$\r\n\r\n\r\n* inserăm $(1, 4)$\r\nştergem $(3, 3)$ şi $(2, 2)$\r\nştergem $(-1, 1)$ ( inserat acum $4$ paşi )\r\nlista de vine: $(1, 4)$\r\nelementul minim al secvenţei $a[2..4]$ este $1$\r\n\r\n\r\n* inserăm $(0, 5)$\r\nştergem $(1, 4)$\r\nlista devine: $(0, 5)$\r\nelementul minim al secvenţei $a[3..5]$ este $0$.\r\n\r\n\r\n* inserăm $(4, 6)$\r\nlista devine: $(0, 5) (4, 6)$\r\nelementul minim al secvenţei $a[4..6]$ este $0$\r\n\r\n\r\n* inserăm $(8, 7)$\r\nlista devine: $(0, 5) (4, 6) (8, 7)$\r\nelementul minim al secvenţei $a[5..7]$ este $0$\r\n\r\n\r\n* inserăm $(6, 8)$\r\nştergem $(8, 7)$\r\nştergem $(0, 5)$ ( inserat acum $4$ paşi )\r\nlista devine: $(4, 6) (6, 8)$\r\nelementul minim al secvenţei $a[6..8]$ este $4$\r\n\r\nh2(#problema-7). Problema 7 (Agricultura, Algoritmus)\r\n\r\nbq. Se dă o matrice de dimensiuni $N x M$ de numere naturale. Se cere determinarea unei submatrici cu număr maxim de celule în care diferenţa între valoarea maximă şi valoarea minimă este mai mică decât o valoare dată $K$. Restrictii: $2 &le; N, M &le; 150$, $1 &le; K &le; 1 000$.\r\n\r\nh3. Exemplu:\r\n\r\nDe exemplu pentru $K = 3$ şi matricea <tex>\\[ \\left( \\begin{array}{cccccc}1 & 1 & 3 & 1 & 2 & 7 \\\\9 & 2 & 3 & 2 & 3 & 2 \\\\7 & 8 & 2 & 3 & 1 & 5 \\\\4 & 5 & 6 & 0 & 1 & 4 \\end{array} \\right)\\]</tex>, soluţia optimă va avea $9$ celule.\r\n\r\nh3. Rezolvare:\r\n\r\nProblema constă în determinarea submatricei cu număr maxim de celule în care diferenţa între valoarea maximă şi valoarea minimă este mai mică decât $K$. Vom folosi ideea de la problema cu subsecvenţa de sumă maximă pe matrice, adică vom fixa două linii $i{~1~}$ şi $i{~2~}$. Acum pentru fiecare coloană $j$ păstrăm în $m[j]$ elementul minim şi în $M[j]$ elementul maxim $a[i][j]$ cu $i{~1~} &le; i &le; i{~2~}$. Astfel la fiecare pas trebuie acum să rezolvăm problema determinării unei subsecvenţe de lungime maximă pentru care diferenţa între elementul maxim şi minim este mai mică decât $K$. Folosind un _max-heap_ şi un _min-heap_ putem parcurge elementele şirurilor $M$ şi $m$ în ordine inserând la fiecare pas elemente în heap şi determinând cea mai lungă secvenţă ce se termină în $i$ cu proprietatea dată. Vom ţine un al $2$-lea indice $j$, iniţial $0$, care atâta timp cât diferenţa între elementul maxim din max-heap cu elementul minim din min-heap este mai mare sau egală cu $K$, vom scoate din heapuri elementele $M[j]$, respectiv $m[j]$ şi îl vom incrementa pe $j$. Complexitate: $O(N^3^ log N)$. Dacă în loc de heapuri folosim deque-uri, atunci acest algoritm va avea complexitatea $O(N^3^)$.\r\n\r\nh2(#problema-8). Problema 8 (\'Secvenţa 2\':problema/secv2)\r\n\r\nbq. Se da un şir de $N$ numere întregi şi un număr natural $K$. O secvenţă este un subşir de numere care apar pe poziţii consecutive în şirul iniţial. Se cere să se găsească secvenţa de sumă maximă de lungime cel puţin $K$. Restrictii: $1 &le; K &le; N &le; 50 000$.\r\n\r\nh3. Exemplu:\r\n\r\nDe exemplu pentru şirul $(0, -6, 2, 1, 4, -1,  3, -5)$ şi $K = 3$, soluţia optimă este $(2, 1, 4, -1, 3)$.\r\n\r\nh3. Rezolvare:\r\n\r\nPutem folosi rezolvarea liniară bazată pe programare dinamică prezentată ca subalgoritm în soluţia \'problemei $5$\':probleme-cu-secvente#problema-5, dar putem simplifica logica din acea rezolvare. Vom folosi şirul sumelor parţiale $sum[]$, iar pentru a determina subsecvenţa de sumă maximă ce se termină în $i$ şi are lungimea cel puţin $K$ trebuie să găsim $sum[j]$ minim astfel ca $j < i - K$. Parcurgem lista, şi la pasul $i$ determinăm $best[i] = sum[i] - min(sum[j])$, $j < i - K$. Comparăm minimul curent cu $sum[i - K]$ şi trecem la pasul următor. Complexitate: $O(N)$.\r\n\r\nh2(#problema-9). Problema 9 (\'Sum\':problema/sum2, Stelele Informaticii 2003 )\r\n\r\nbq. Se dă un şir de $N$ numere întregi. Se caută un subşir cu lungimea cuprinsă între $L$ şi $U$, format din elemente consecutive ale şirului iniţial, cu suma elementelor maximă. Restrictii: $1 &le; L &le; U &le; N &le; 100 000$.\r\n\r\nh3. Rezolvare:\r\n\r\nPentru fiecare $i$ este de ajuns să aflăm valoarea expresiei $sum[i] - sum[j]$, unde $i - L > j &ge; i - U$. Pentru a determina valoarea optimă pentru $sum[j]$ putem folosi un heap de dimensiune $U - L$, sau putem folosi tehnici de determinare a valorii minime într-un interval dat. Complexitate: $O(N * log(U - L))$.\r\n\r\nAltă abordare de aflare a minimelor unor secvenţe de lungime dată (în cazul acesta lungimea este $U - L$ ) a fost prezentată în rezolvarea \'problemei $6$\':probleme-cu-secvente#problema-6. Folosind acea tehnică obţinem o rezolvare de complexitate liniară.\r\n\r\nO altă rezolvare frumoasă prezentată în [4] este următoarea: spunem că o secvenţă este negativă spre stânga dacă suma oricărui prefix ( în afară de secvenţa în sine ) al secvenţei este negativ sau zero. O partiţie a secvenţei $A = (A{~1~}, A{~2~}, ..., A{~k~})$ este minimală negativă spre stânga dacă fiecare $A{~i~}$ este negativă spre stânga, iar suma elementelor lui $A{~i~}$ este strict pozitivă dacă $i != k$. De exemplu secvenţa $(-4, 1, -2, 3)$ este negativă la stânga, pe când secvenţa $(5, -3, 4, -1, 2, -6)$ nu este. Partiţia $(5) (-3, 4) (-1, 2) (-6)$ este minimală negativă la stânga.\r\n\r\nPentru fiecare element din partiţie ţinem minte un pointer $p[i]$ spre ultimul element din subsecvenţa din care face parte. Fiecare interval $[i, p[i]]$ va corespunde celei mai scurte subsecvenţe care începe în $i$ şi are suma pozitivă. Pentru a determina o soluţie a problemei pentru fiecare $i$ din care poate începe o subsecvenţă de sumă maximă, ne vom plimba cu un pointer $j$ astfel ca $j$ să fie cât mai depărtat de $i$ şi $j - i + 1 &le; U$. Obţinem astfel de fiecare dată o subsecvenţă de sumă maximă ce începe în $i$, cu lungimea mai mică sau egală cu $U$. Indicele $j$ va fi întotdeauna un capăt de secvenţă negativă la stânga şi la fiecare mărire a lui $i$ verificăm dacă lui $j$ îi putem atribui valoarea $p[j + 1]$ ( adică dacă $p[j + 1] - i + 1 &le; U$ ). Dacă secvenţa de sumă maximă de lungime cel mult $U$ ce începe în $i$ are lungimea mai mică decât $L$, atunci secvenţa de sumă maximă cu lungimea cuprinsă între $L$ şi $U$ are lungimea exact $L$. Complexitate: $O(N)$.\r\n\r\nh2(#problema-10). Problema 10 (\'Secvenţa 3\':problema/secv3)\r\n\r\nbq. Se dă un şir de $N$ elemente pentru care se cunosc două informaţii: costul şi timpul. O secvenţă este un subşir de numere care apar pe poziţii consecutive în şirul iniţial. Se caută o secvenţă din cele $N$ elemente care să fie de lungime minim $L$ şi maxim $U$, iar suma costurilor elementelor secvenţei împărţiţă la suma timpurilor elementelor secvenţei să fie maximă. Restrictii: $1 &le; L &le; U &le; N &le; 30 000$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru $L = 1, R = 2$ şi şirurile $c = ( 1, 1, 3, 2, 5 )$ şi $t = ( 4, 2, 5, 3, 6 )$, subsecvenţa cea mai eficientă are costul $0.83$.\r\n\r\nh3. Rezolvare:\r\n\r\nProcedăm ca la \'problema $5$\':probleme-cu-secvente#problema-5 şi căutăm binar valoarea optimă. şirul va fi transformat în: $b[i] = c[i] - t[i] * X$, $i = 1..N$. Acum trebuie să mai rezolvăm subproblema care cere să determinăm o subsecvenţă de sumă maximă pentru care lungimea se află între $L$ şi $U$. Această subproblemă a fost soluţionată în \'problema anterioară\':probleme-cu-secvente#problema-9, unde s-a găsit un algoritm liniar. Astfel soluţia acestei probleme are complexitatea $O(N * log C)$.\r\n\r\nh2(#problema-11). Problema 11 (\'XorMax\':problema/xormax)\r\n\r\nbq. Se dă un şir de $N$ numere întregi nenegative. Să se aleagă o secvenţă a şirului, $(a{~i~}, a{~i+1~}, ..., a{~j~})$, astfel încât $a{~i~} xor a{~i+1~} xor ... xor a{~j~}$ să fie maxim. Restrictii: $1 &le; N &le; 100 000$ si $a{~i~} < 221$ cu $i = 1..N$.\r\n\r\nh3. Exemplu:\r\n\r\nPentru şirul $(1, 0, 5, 4, 2)$, secvenţa cu valoarea sumei _xor_ maximă este $(4, 2)$, cu suma $6$. \r\n\r\nh3. Rezolvare:\r\n\r\nSuma _xor_ a două numere este de fapt adunare binară fără transport, fapt care o face similară operaţiei _modulo_. Problema e asemănătoare cu cea a subsecvenţei de modul maxim. Vom obţine toate sumele _xor_ parţiale şi pentru a vedea pentru $sum[i]$ perechea optimă cu care crează o sumă cât mai mare trebuie să găsim acea sumă $sum[j]$ astfel că fiecare bit al lui $sum[i]$ să fie diferit de fiecare bit al lui $sum[j]$, dacă acest lucru este posibil. Pentru a face această căutare cât mai eficientă, putem menţine sumele $sum[i]$ ca şiruri de caractere $0$ sau $1$ într-un _trie_ [5]. Structura de trie pentru cazul când alfabetul are dimensiunea $2$ este identică cu cea de heap. Această soluţie are complexitatea $O(N * log C)$.\r\n\r\nh2(#probleme-propuse). Probleme propuse\r\n\r\nPentru a vă însuşi mai bine tehnicile învăţate în acest articol, puteţi rezolva următoarele probleme:\r\n\r\n* \'Balans\':problema/balans\r\n* \'Struţi\':problema/struti\r\n* \'Deque\':problema/deque\r\n* \'Trie\':problema/trie\r\n* \'Maxq\':problema/maxq\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Dana Lica - \'_Arbori de intervale şi aplicaţii în geometria computaţională_\':arbori-de-intervale\r\n# Cosmin Negruşeri - \'_Căutări Ortogonale: Structuri de date şi aplicaţii_\':cautari-ortogonale\r\n# Takaoka T. - \'_Efficient Algorithms for the Maximum Subarray Problem by Distance Matrix Multiplication_\':http://www.cosc.canterbury.ac.nz/tad.takaoka/cats02.pdf\r\n# Kuan Yu Chen, Kun Mao Chao - \'_On the Range Maximum-Sum Segment Query_\':http://www.csie.ntu.edu.tw/~kmchao/papers/2007_DAM_RMSQ.pdf\r\n# Yaw Ling Liu, Tao Jiang, Kun Mao Chao - \'_Efficient Algorithms for Locating the Length-Constrained Heaviest Segments, with Applications to Biomolecolar Sequence Analysis_\':http://www.csie.ntu.edu.tw/~kmchao/seq2003/mslc.pdf\r\n# T. H. Cormen, C. E. Leiserson, R. R. Rivest - \'_Introducere in Algoritmi_\':http://zhuzeyuan.hp.infoseek.co.jp/ita/toc.htm\r\n\r\nh2. Discuţii pe forum',3146,'public',3553,NULL),('numerele-sprague-grundy','Teoria jocurilor: numerele Sprague Grundy','2008-11-18 17:10:41','2009-01-10 14:41:26','h1. Teoria jocurilor: numerele Sprague Grundy\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"portocala\") ==\r\n\r\n(Categoria _Matematică_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 28em}*{text-align:center;} *Conţinut*\r\n* \'Introducere\':numerele-sprague-grundy#introducere\r\n* \'Ce este jocul NIM?\':numerele-sprague-grundy#jocul-nim\r\n* \'Aplicatii ale strategiei NIM\':numerele-sprague-grundy#aplicatii-nim\r\n* \'Numerele Sprague Grundy\':numerele-sprague-grundy#sprague-grundy\r\n* \'Probleme care se rezolvă cu numerele Sprague Grundy\':numerele-sprague-grundy#aplicatii-sg\r\n* \'Concluzii\':numerele-sprague-grundy#concluzii\r\n* \'Probleme propuse\':numerele-sprague-grundy#probleme-propuse\r\n* \'Bibliografie\':numerele-sprague-grundy#bibliografie\r\n\r\nh2(#introducere). Introducere\r\n\r\nDomeniu relativ nou şi încă necercetat în adâncime, $teoria jocurilor$ este o ramură a matematicii în care de multe ori primează inventivitatea şi nu cunoştinţele. Tocmai din acest motiv, în cadrul acestui articol vom introduce câteva noţiuni teoretice care ne vor ajuta în rezolvarea unor probleme din teoria jocurilor. Ingeniozitatea celor pasionaţi poate fi testată prin introducerea unor probleme de teoria jocurilor la concursurile de matematică şi informatică. Deoarece în România teoria jocurilor nu este studiată în şcoli, problemele din acest domeniu pot pune în dificultate concurenţii.\r\n\r\nh2(#jocul-nim). Ce este jocul NIM?\r\n\r\nPentru început ne vom familiariza cu jocul clasic $NIM$:\r\n\r\nbq. Se consideră $N$ grămezi de pietre. Doi jucători, vor ridica alternativ oricâte pietre dintr-o singură grămadă. Câştigătorul este cel care ia ultima piatră.\r\n\r\nh3. Soluţie\r\n\r\n* Pentru cazul trivial în care numărul de grămezi este egal cu $1$, primul jucător are, evident, strategie de câştig, el putând lua toate pietrele din grămadă.\r\n* Dacă numărul de grămezi este egal cu $2$, primul jucător are strategie de câştig atunci când numărul de pietre din prima grămadă este diferit de numărul de pietre din cea de-a doua, strategia lui fiind cea de a aduce tot timpul grămada mai mare la numărul de pietre al grămezii mai mici, şi cum jocul este finit, înseamnă că primul jucător o să aducă jocul în starea $(0, 0)$.\r\n* Dacă numărul de grămezi este mai mare decât doi, strategia se complică şi nu se mai observă cu \"ochiul liber\". Stările câştigătoare pentru mai multe grămezi sunt acele stări pentru care suma $XOR$ a numerelor de pietre din grămezi este diferită de $0$, restul stărilor fiind de pierdere.\r\n\r\nDe exemplu, dacă avem $4$ grămezi cu $1$, $3$, $5$ respectiv $7$ pietre:\r\n\r\n* $*O*$\r\n* $*OOO*$\r\n* $*OOOOO*$\r\n* $*OOOOOOO*$\r\n\r\nAtunci vom avea:\r\n\r\n* $*1 = (0001){~2~}*$\r\n* $*3 = (0011){~2~}*$\r\n* $*5 = (0101){~2~}*$\r\n* $*7 = (0111){~2~}*$\r\n\r\nEfectuând \'$XOR$\':http://www.fredosaurus.com/notes-cpp/expressions/bitops.html (operatorul $^$ în $C/C++$) între reprezentările binare ale numerelor  obţinem $*0 = (0000){~2~}*$. Conform propoziţiei de mai sus această stare este de pierdere.\r\n\r\nSă demonstrăm cele afirmate. Dintr-o poziţie cu suma $XOR$ egală cu $*0*$, pentru orice mutare ajungem evident la o poziţie cu suma $XOR$ diferită de $*0*$, pentru că luând dintr-o grămadă un număr $x$ de pietre, în suma $XOR$ corespunzătoare noii stări bitul cel mai semnificativ al lui $x$ va avea valoarea $*1*$.\r\n\r\nMai rămâne de demonstrat că din orice poziţie cu suma $XOR$ diferită de $*0*$ putem trece printr-o mutare convenabilă într-o poziţie cu suma $XOR$ egală cu $*0*$. Căutăm o grămadă care are un număr de pietre mai mare sau egal cu cea mai mare putere a lui $2$ care apare în suma $XOR$. Fie $x$ valoarea sumei $XOR$ a tuturor grămezilor şi $y$ numărul de pietre din grămada găsită mai devreme. O mutare \"câştigătoare\" este extragerea din grămada găsită care are $y$ pietre a {$y - (x XOR y)$} pietre ({$x XOR y$} este mai mic decât $y$ pentru că se anulează biţii cei mai semnificativi ai lui $y$ şi $x$). Atunci noua sumă $XOR$ va fi egală cu $*0*$.\r\n\r\nDe exemplu:\r\n\r\n* $*4{@ ^ 8 ^ @}17 = (00100){~2~}{@ ^ @}(01000){~2~}{@ ^ @}(10001){~2~} = (11101){~2~} = 29*$.\r\n\r\nMutarea câştigătoare constă în a lua din cea de-a treia gramadă un număr de pietre egal cu:\r\n\r\n* $*17 - (17 @^ 29) = 17 - 17 ^@ 29 = 5 = (00101){~2~}*$.\r\n\r\nDupă acest pas grămezile vor avea $4$, $8$, $12$ pietre. Ne aflăm astfel într-o stare cu suma $XOR$ egală cu $*0*$.\r\n\r\nh2(#aplicatii-nim). Aplicatii ale strategiei NIM\r\n\r\nExemplificăm în continuare câteva probleme în care se foloseste strategia jocului $NIM$.\r\n\r\nh3(#problema-1). Problema 1\r\n\r\nbq. Pe o tablă de şah, care are $N x M$ căsuţe, sunt plasaţi pe prima linie $N$ pioni albi şi pe ultima linie $N$ pioni negri. Fiecare dintre cei doi jucători poate muta un singur pion, care îi aparţine, un număr strict pozitiv de căsuţe în sus sau în jos, astfel încât să nu ajungă vreun pion alb să fie mai jos decât pionul negru de pe aceeaşi coloană. Pierde jucătorul care nu mai poate muta.\r\n\r\nh3. Solutie\r\n\r\nAceastă problemă este o deghizare a jocului $NIM$, numărul de pătrăţele libere între pionul alb şi pionul negru de pe coloana $i$ putând fi considerat numărul de pietre din grămada $i$. Singura diferenţă este că se pot adăuga pietre la grămadă (existând posibilitatea mutării înapoi). Această problemă se rezolvă uşor, jucătorul care are strategie de câştig putând evita asemenea mutări. O astfel de mutare poate fi utilă numai pentru jucătorul care este într-o poziţie de pierdere. Când jucătorul care nu are strategie de câştig mută înapoi $x$ căsuţe, celălalt jucător va muta pionul propriu de pe aceeaşi coloanã cu $x$ căsuţe în faţă, astfel ajungându-se la aceeaşi stare cu cea existentă cu două mutări anterior (considerând diferenţa poziţiilor).\r\n\r\nh3(#problema-2). Problema 2 (Baraj, ONI 1997)\r\n\r\nbq. Pe o linie sunt plasate la coordonate întregi $2 x N$ piese roşii şi albastre. Fiecare piesă roşie poate fi mutată în dreapta oricâte poziţii astfel încât să nu sară peste o piesă albastră, iar piesele albastre pot fi mutate oricâte poziţii la stânga astfel încât să nu depăşească vreo piesă roşie. Piesele vor alterna: roşu, albastru, roşu, albastru etc. Pierde jucătorul care nu mai poate muta.\r\n\r\nh3. Solutie\r\n\r\nAceastă problemă poate fi, de asemenea, redusă la jocul $NIM$. Diferenţele poziţiilor perechilor de piese roşii şi albastre consecutive constituie numărul de pietre al grămezilor din jocul $NIM$.\r\n\r\nh3(#problema-3). Problema 3 (\'Nim Game - Give Away!\':http://acm.mipt.ru/judge/problems.pl?problem=103&CGISESSID=b4a5b84bd176d84796a209dc7c8002b8, El Judge)\r\n\r\nbq. Se consideră $N$ grămezi de pietre, jucătorii mută alternativ, fiecare jucător extrăgând oricâte pietre dintr-o singură grămadă. Cel care ia ultima piatră pierde jocul.\r\n\r\nh3. Solutie\r\n\r\nStrategia acestui joc este similară cu cea aplicată în jocul $NIM$ cu câteva mici diferenţe. Jucătorul care are strategie de câştig în poziţia curentă în cadrul jocului $NIM$ face aceeaşi mutare pe care ar face-o în cazul jocului $NIM$, exceptând cazul în care această mutare lasă doar grămezi cu o singură piatră şi numărul acestor grămezi este par. În această situaţie, dacă ar trebui să ia $x$ pietre, jucătorul poate lua $x - 1$ pietre din grămada actuală, pentru ca numărul de grămezi să fie impar şi el să facă ultima mutare.\r\n\r\nh2(#sprague-grundy). Numerele Sprague Grundy\r\n\r\nJocurile care prezintă interes pentru jucători sunt acelea care necesită examinarea unui număr foarte mare de stări pentru determinarea strategiei de câştig, deoarece în caz contrar câştigătorul s-ar cunoaşte chiar de la început. Spre deosebire de aceştia, matematicienii sau informaticienii sunt interesaţi de determinarea unor strategii pentru astfel de jocuri. Toate jocurile imparţiale cu doi jucători cu informaţie totală pot fi reduse la jocul *$NIM$* care se joacă cu nişte grămezi virtuale, în care mutările posibile sunt extragerea oricâtor pietre dintr-o grămadă sau adăugarea oricâtor pietre la o grămadă (aşa cum am menţionat anterior, adăugarea de pietre la o grămadă nu complică analiza jocului).\r\n\r\nAfirmaţia anterioară constituie un rezultat al _Teoriei Sprague-Grundy_. _Roland Percival Sprague_ (1936) şi _Patrick Michael Grundy_ (1939) sunt doi matematicieni care s-au ocupat, independent, de teoria jocurilor imparţiale.\r\n\r\nMajoritatea jocurilor imparţiale se pot reduce la jocul prezentat în problema _Pioni_ de la runda 47 a concursului de programare Bursele Agora. Acolo se menţiona următorul joc:\r\n\r\nbq. Se consideră un graf aciclic care conţine în noduri câţiva pioni, jucătorii alternează la mutare şi fiecare poate muta câte un pion pe un arc care iese din nodul în care este situat pionul. Pierde jucătorul care nu poate muta.\r\n\r\nCum graful este aciclic, jocul este finit şi are întotdeauna un câştigător. Practic, acest joc este suma unor jocuri, mai precis suma a mai multor jocuri cu un singur pion pe graful aciclic. Jocul cu un singur pion poate fi analizat destul de uşor, fiecare nod al grafului putând fi colorat cu alb sau negru după cum există sau nu strategie de câştig dacă în nodul curent ar fi poziţionat pionul. Această colorare poate fi realizată uşor dacă se porneşte de la nodurile fără urmaş şi la fiecare pas se colorează câte un nod ai cărui urmaşi sunt deja coloraţi. Orice joc imparţial poate fi redus la un joc cu un singur pion. Nodurile sunt poziţiile jocului şi arcele grafului sunt mutările posibile din fiecare poziţie. Jocul iniţial poate fi şi el transformat, dar numărul de noduri creşte foarte mult (pentru $N$ pioni şi $M$ noduri, numărul de noduri din jocul transformat este {$N^M^$}) şi nu este practic să colorăm graful rezultat. Folosind teoria dezvoltată de Sprague şi Grundy, putem reduce complexitatea analizei jocului cu $N$ pioni la complexitatea analizei jocului cu un pion.\r\n\r\nVom introduce funcţia *$mex$* cu semnificaţia: $mex(S)$ este elementul minimal natural care nu aparţine mulţimii $S$. Pentru fiecare nod $x$ al grafului aciclic considerat, vom calcula valoarea funcţiei $gx = mex(gx{~1~}, gx{~2~}, …, gx{~k~})$, unde $x{~1~}$, $x{~2~}$, …, $x{~k~}$ sunt urmaşii nodului $x$ în graf. Pentru nodurile fără urmaşi $gx = 0$.\r\n\r\nAnalog jocului cu un singur pion, graful poate fi etichetat din aproape în aproape, pornind de la nodurile fără urmaşi. Observăm că, dacă $gx = 0$ în jocul cu un singur pion situat în nodul $x$ nu avem strategie de câştig, iar dacă $gx$ este diferit de $0$ avem strategie de câştig. Restul informaţiei ne ajută la determinarea unei strategii pentru jocul cu $N$ pioni. Observăm că putem reduce acest joc la jocul $NIM$ în care grămada virtuală asociată pionului $i$ are un număr de pietre egal cu valoarea $g$ a nodului în care este situat pionul $i$.\r\n\r\n_De ce este acest joc echivalent cu jocul NIM?_\r\n\r\nAşa cum la $NIM$ puteam lua oricâte pietre dintr-o grămadă, aici putem muta pionul dintr-un nod cu valoarea $g$ într-un nod astfel încât noua valoare pentru pionul $i$ poate fi orice număr de la $0$ la $g - 1$. Prin urmare, pentru a verifica dacă suntem într-o poziţie de câştig în jocul cu pionii, putem aplica strategia jocului $NIM$ şi obţinem că suntem într-o poziţie de câştig dacă suma $XOR$ a numerelor din nodurile ocupate de cei $N$ pioni este diferită de $0$. Această sumă se numeşte funcţia _Sprague Grundy_: <tex>SG(i_{1}, ..., i_{n}) = g_{i_1} \\verb|^| g_{i_2} \\verb|^| g_{i_3} \\verb|^| ... \\verb|^| g_{i_n}</tex>.\r\n\r\nProblema de la runda 47 ({_Pioni_}) se rezolvă acum uşor efectuând o sortare topologică a nodurilor grafului aciclic şi numerotând nodurile folosind funcţia $mex$.\r\n\r\nh2(#aplicatii-sg). Aplicatii ale numerelor Sprague Grundy\r\n\r\nÎn continuare, sa studiem alte probleme ce se pot rezolva cu numerele $Sprague Grundy$.\r\n\r\nh3(#problema-4). Problema 4 (Joc, Bursele Agora 2003/2004, Runda 13)\r\n\r\nÎn acestă problemă se cere să verificăm existenţa unei strategii de câştig pentru un joc similar cu $NIM$ în care se putea lua dintr-o grămadă o piatră sau un număr prim de pietre.\r\n\r\nDacă determinăm valorile $Sprague Grundy$ pentru grămezi de dimensiuni mici putem observa că se repeta o succesiune de numere: $0 1 2 3 0 1 2 3 ...$\r\nPutem demonstra prin inducţie că această secvenţă se va repeta la nesfărşit.\r\nPentru o grămadă de dimensiune $n$ valoarea asociată va fi $n modulo 4$. Pentru $0 ≤ n ≤ 3$ afirmaţia este adevărată. Vom presupune afirmaţia adevărată pentru toate valorile $m < n$. Să demonstrăm acum că este adevărată şi pentru $n$. Deoarece putem lua din $n$ pietre una, două sau trei pietre, mai rămâne valoarea $n modulo 4$ care nu este eliminată încă din valorile potenţiale asociate grămezii de dimensiune $n$. Vom arăta în continuare că această valoare nici nu va fi eliminată. Eliminarea ei ar însemna că putem lua din $n$ un număr $p$ de pietre şi atunci din $(n - p) modulo 4 = n modulo 4$, am avea: $p modulo 4 = 0$, dar $p$ este un număr prim, deci valoarea $Sprague Grundy$ asociată unei grămezi de dimensiune $n$ este $n modulo 4$.\r\n\r\nh3(#problema-5). Problema 5 (\'Stone game\':http://acm.mipt.ru/judge/problems.pl?problem=101&CGISESSID=b4a5b84bd176d84796a209dc7c8002b8, El Judge)\r\n\r\nbq. Se consideră $K$ grămezi cu $n{~1~}, n{~2~}, …, n{~K~}$ pietre fiecare. Când este rândul său, un jucător poate lua dintr-o gramadă $2^m^$ pietre. Jucătorul care ia ultima piatră câştigă. Restricţii: $K ≤ 50, n{~i~} ≤ 10^200^$.\r\n\r\nh3. Solutie\r\n\r\nSă determinăm valorile $Sprague Grundy$ pentru grămezi mici:\r\n\r\n$0 : 0;    1 : 1;    2 : 2;    3 : 0;    4 : 1;    5 : 2;    6 : 0$\r\n\r\nObservăm şi aici secvenţa repetitivă $0 1 2 0 1 2$, deci am putea trage concluzia că valoarea $Sprague Grundy$ asociată unei grămezi de dimensiune $n$ este $n modulo 3$. Această afirmaţie este adevarată şi urmează aceeaşi demonstraţie ca în cazul problemei anterioare, iar restul $modulo 3$ pentru $n$ număr cu $200$ de cifre este simplu de găsit determinând suma cifrelor numărului.\r\n\r\nh3(#problema-6). Problema 6 (\'Stone game II\':http://acm.mipt.ru/judge/problems.pl?problem=102&CGISESSID=b4a5b84bd176d84796a209dc7c8002b8, El Judge)\r\n\r\nbq. Se consideră $K$ grămezi de pietre cu $n{~1~}, n,{~2~} …, n{~K~}$ pietre. Un jucător poate lua dintr-o grămadă la mutarea lui un număr pozitiv de pietre dar nu mai mult de jumătate din pietrele din grămadă. Jucătorul care nu mai poate muta pierde.\r\nRestricţii: $K ≤ 50, n{~i~} ≤ 100000$.\r\n\r\nh3. Solutie\r\n\r\nNumărul $100000$ nu este foarte mare şi valorile $Sprague Grundy$ pot fi determinate _off-line_ şi incluse în programul nostru ca şi constante. Putem scrie pentru valori mici secvenţa $Sprague Grundy$:\r\n\r\n$1 2 3 4 5 6 7 8 9 10 11 12 13 14$\r\n$0 1 0 2 1 3 0 4 2  5  1  6  3  7$\r\n\r\nPentru $n$ impar valoarea asociată este aceeaşi cu valoarea asociată lui $n/2$, şi pentru $n$ par valoarea asociată este $n/2$. Acest lucru se poate demonstra prin inducţie matematică.\r\n\r\nh3(#problema-7). Problema 7 (Sticks, CEOI 2000)\r\n\r\nbq. Se consideră $n (n ≤ 10)$ rânduri de beţe pe o masă, cu $S{~i~} (S{~i~} ≤ 10)$ beţe aliniate pe fiecare rând şi doi jucători. Beţele de pe rândul $i$ sunt numerotate secvenţial de la $1$ la $S{~i~}$. Cei doi jucători mută alternativ. Fiecare mişcare constă în eliminarea a unu, două sau trei beţe de pe acelaşi rând. Beţele trebuie sã fie numerotate secvenţial, adică să fie consecutive. De exemplu, un rând are $10$ beţe şi primul jucător elimină beţele $4$, $5$, $6$, deci vor rămâne numai beţele $1$, $2$, $3$, $4$, $8$, $9$, $10$. Al doilea jucător poate lua la rândul său beţele $1$, $2$, $3$, dar nu beţele $3$, $7$, $8$ pentru că acestea nu sunt numerotate consecutiv (bineînţeles că există şi alte mutări valide). Câştigă jucătorul care ia ultimul băţ de pe masă.\r\n\r\nh3. Solutie\r\n\r\nProblema generală are o soluţie ingenioasă care ţine seama de parităţile rândurilor, dar la această problemă, datorită mărginirii lui $S{~i~} (S{~i~} ≤ 10)$ nu este necesar să fim ingenioşi. Restricţia $S{~i~} ≤ 10$, ne ajută prin faptul cã numărul total de poziţii (dacă jucăm pe o singură gramadă), este $2^10^$. Vom reprezenta o poziţie printr-un întreg, iar dacă acel întreg are în codificarea lui binară pe poziţia $i$ un bit de $1$ înseamnă că el reprezintă un rând de beţe care conţine în el băţul numerotat cu $i$. Este uşor de realizat un graf aciclic al mişcărilor pentru un rând (graful este aciclic pentru că la fiecare mutare luăm beţe din configuraţie). Numerotăm fiecare poziţie cu numerele $Sprague Grundy$, şi acum problema deciderii dacă suntem sau nu într-o poziţie câştigătoare devine banală. În problema iniţială trebuia să jucăm împotriva calculatorului şi să câştigăm. Putem realiza aceasta folosind mutarea câştigătoare prezentată la jocul $NIM$.\r\n\r\nh3(#problema-8). Problema 8 (\'Joc\':problema/joc2, Bursele Agora 2006)\r\n\r\nbq. Doi participanţi mănâncă alternant din nişte tablete de ciocolată după următoarele reguli:\r\n{*} taie o tabletă în două, tăietura trebuie să fie paralelă cu una din laturile tabletei şi trebuie să nu taie pătrăţelele de ciocolată;\r\n{*} poate să rupă şi să mănânce orice linie sau coloană de pătrăţele care nu se află pe marginea tabletei;\r\n{*} poate să rupă şi să mănânce toate patrăţelele de pe marginea tabletei, cu condiţia ca tableta rămasă să aibă cel puţin dimensiunea $1 x 1$.\r\nNici una dintre aceste trei mutări nu poate fi efectuată asupra unei tablete de dimensiune $1 x 1$. Pierde jucătorul care nu mai poate efectua nici o mutare.\r\n\r\nh3. Solutie\r\n\r\nPentru această problemă vom calcula matricea $SG{~i,j~}$ care reprezintă valoarea $Sprague-Grundy$ asociată unei tablete de dimensiuni $(i, j)$. Să vedem care este recurenţa care va satisface elementele matricei $SG$:\r\n\r\n<tex> SG_{i,j} = mex(SG_{i,k} \\verb|^| SG_{i,j-k}, (1 \\leq k < j) </tex> mutarea întâi\r\n<tex> SG_{k,j} \\verb|^| SG_{i-k,j}, \\hspace{21 mm}(1 \\leq k < i) </tex>\r\n<tex> SG_{i,k} \\verb|^| SG_{i,j-k-1}, \\hspace{17.5 mm} (1 \\leq k < j - 1) </tex> mutarea a doua\r\n<tex> SG_{k,j} \\verb|^| SG_{i-k-1,j}, \\hspace{17 mm} (1 \\leq k < i - 1) </tex>\r\n<tex> SG_{i-2,j-2}) \\hspace{28 mm} (i > 2 , j > 2 )</tex> mutarea a treia\r\n\r\nAcum, pentru a calcula numărul de mutări câştigătoare efectuăm asupra fiecărei tablete din fişierul de intrare toate mutările posibile care sunt cel mult de $4 x 100 + 1$ şi facem suma $XOR$ a valorilor $Sprague Grundy$ pentru restul tabletelor neimplicate în mutare şi a tabletelor rezultate din mutare. Pentru a calcula $SG{~i,j~}$ trebuie sã parcurgem cel mult $2 x i + 2 x j + 1$ valori obţinute. Astfel, algoritmul de determinare al valorilor matricei $SG$ are ordinul de complexitatea $O(N^3^)$. Complexitatea algoritmului care determină numărul de mutări câştigătoare este $O(N^2^)$.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nAm văzut că aceste numere sunt folositoare pentru rezolvarea unor probleme de jocuri combinatorice. Chiar dacă numărul stărilor grafului nostru aciclic poate să fie foarte mare, putem să ne dăm seama, câteodată, din valorile mici de o regulă pe care o urmează numerele, sau măcar putem determina mai uşor configuraţii pentru care jocul are sau nu strategie de câştig, fapt care ne poate ajuta în descoperirea rezolvării generale.\r\n\r\nh2(#probleme-propuse). Probleme suplimentare\r\n\r\n* \'Got Root?\':http://ipsc.ksp.sk/contests/ipsc2003/real/problems/g.php, _IPSC 2003_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# \'Colecţia GInfo\':http://www.ginfo.ro/\r\n# Mihai Oltean, _Programarea Jocurilor Matematice_, Editura Albastră, Cluj-Napoca, 1996\r\n# \'Thomas S. Ferguson, Game Theory Text (online)\':http://www.math.ucla.edu/~tom/gamescourse.html\r\n# \'Interactive Mathematics\':http://www.cut-the-knot.com\r\n# \'Wolfram MathWorld\':http://www.mathworld.wolfram.com\r\n# \'IPSC\':http://ipsc.ksp.sk/\r\n',3146,'public',NULL,NULL),('algoritmiada-2009/runda-2/solutii/jap','algoritmiada-2009/runda-2/solutii/jap','2009-01-03 17:08:08','2009-01-11 09:10:22','h1(#jap). \'Jap\':problema/jap\r\n\r\nVom considera toate numerele naturale intre $2$ si $N$ inclusiv care nu pot fi scrise sub forma $x^y^$, unde $y diferit de 1$. Notam aceasta multime cu numere $S$. Pentru fiecare din aceste numere vom calcula puterea maxima la care poate fi ridicat astfel incat rezultatul sa fie $&le; N$. Pentru un numar $i$, vom considera ca aceasta putere este $j$ (deci $i^j^ &le; N$) si vom incerca sa calculam cate elemente distincte se pot genera ridicand fiecare din elementele $i^1^$, $i^2^$, $i^3^$, ..., $i^j^$ la puteri intre $1$ si $M$. Astfel pentru $i$ va trebui sa calculam cate elemente distincte are secventa $i^1^$, $i^2^$, ..., $i^M^$, $i^2*1^$, $i^2*2^$, ..., $i^2*M^$, ..., $i^j*1^$, $i^j*2^$, ..., $i^j*M^$. Observam ca oricare ar fi $i$ si $j$ din multimea $S$, secventele generate cu regula de mai sus vor fi complet disjuncte, si in plus reuniunea lor va constitui intreaga secventa data in enunt. Astfel, suma numarului de elemente distincte determinate pentru fiecare $i$ din $S$ va reprezenta numarul cerut in enunt.\r\n\r\nSetul $S$ poate fi determinat, parcurgand elementele de la $2$ la $N$ si marcand toate puterile mai mari ca 1 al elementului curent ca nefacand parte din set\r\n\r\nDe aici putem elabora mai multe solutii de complexitati diferite:\r\n\r\n- $O(N * M * log(N * M))$ - $20$ de puncte\r\n... to be continued ...\r\n\r\n==User(user=\"Prostu\" type=\"tiny\")== trebuie sa scrie aici solutia lui :)',1490,'private',NULL,NULL),('algoritmiada-2009/runda-2/solutii/colier','algoritmiada-2009/runda-2/solutii/colier','2009-01-03 17:07:03','2009-01-08 20:43:23','h1(#colier). \'Colier\':problema/colier\r\n\r\nSe observa destul de usor ca starea de castigare pentru $N = 2$ este $01$ sau $10$. Acum sa vedem ce se intampla cand avem un colier cu $N > 2$ perle. In primul rand trebuie sa avem cel putin o perla $1$. De fiecare data cand alegem un $1$, putem sa avem vecinii $0 **1** 0$, $0 **1** 1$, $1 **1** 0$, $1 **1** 1$. Putem observa ca in urma unei astfel de operatii paritatea perlelor $0$ ramane aceeasi. De aici tragem concluzia ca numarul de perle $0$ trebuie sa fie impar (pentru ca la un moment dat trebuie sa ajungem in una din starile castigatoare pentru $N = 2$). Tot la fel de usor se observa ca sigur exista o secventa de alegeri care sa ne duca la sfarsit, daca avem numar impar de perle $0$ (singurul caz particular ar fi cand avem doar trei perle $1$ una langa alta si o alegem pe cea din mijloc, atunci ramanem fara perle $1$, dar daca alegem de fiecare data o perla $1$ care are cel putin un vecin $0$ sigur o sa fie totul bine, si cum trebuie sa existe cel putin o perla $0$ sigur putem face aceasta alegere). De aici solutia iese foarte usor. Aveti grija, exista cateva cazuri particulare usoare, pe care va las sa le descoperiti singuri :).',2038,'private',NULL,NULL),('algoritmiada-2009/runda-2/solutii/jap','algoritmiada-2009/runda-2/solutii/jap','2009-01-03 17:08:08','2009-01-11 12:46:14','h1(#jap). \'Jap\':problema/jap\r\n\r\nVom considera toate numerele naturale intre $2$ si $N$ inclusiv care nu pot fi scrise sub forma $x^y^$, unde $y diferit de 1$. Notam aceasta multime cu numere $S$. Pentru fiecare din aceste numere vom calcula puterea maxima la care poate fi ridicat astfel incat rezultatul sa fie $&le; N$. Pentru un numar $i$, vom considera ca aceasta putere este $j$ (deci $i^j^ &le; N$) si vom incerca sa calculam cate elemente distincte se pot genera ridicand fiecare din elementele $i^1^$, $i^2^$, $i^3^$, ..., $i^j^$ la puteri intre $1$ si $M$. Astfel pentru $i$ va trebui sa calculam cate elemente distincte are secventa $i^1^$, $i^2^$, ..., $i^M^$, $i^2*1^$, $i^2*2^$, ..., $i^2*M^$, ..., $i^j*1^$, $i^j*2^$, ..., $i^j*M^$. Observam ca oricum am alege $x$ si $y$ din multimea $S$, secventele generate cu regula de mai sus vor fi complet disjuncte, si in plus reuniunea tuturor secventelor va constitui intreaga secventa data in enunt. Astfel, suma numarului de elemente distincte determinate pentru fiecare $x$ din $S$ va reprezenta numarul cerut in enunt.\r\n\r\nSetul $S$ poate fi determinat, parcurgand elementele de la $2$ la $N$ si marcand toate puterile mai mari ca 1 al elementului curent ca nefacand parte din set. Determinarea setului $S$ are complexitate $O(N)$.\r\n\r\nDe aici putem elabora mai multe solutii de complexitati diferite:\r\n\r\n* $O(N)$ precalculare, $O(N * M * log(N * M))$ pe test - $20$ de puncte\r\n\r\nPentru fiecare $i$ din $S$, calculam $j$, cel mai mare numar natural astfel incat $i^j^ &le; N$, adaugam puterile $1, 2, 3, ..., M, 2, 4, 6, ..., 2M, ..., j, 2j, 3j, ..., jM$ intr-un vector, il sortam si adunam la rezultat numarul de elemente distincte din el.\r\n\r\n* $O(N)$ precalculare, $O(N log N)$ pe test - $50$ de puncte\r\n\r\nPentru fiecare $i$, vom calcula numarul de elemente distincte din secventa corespunzatoare lui folosind principiul includerii si excluderii. Fie $A$ un subset al multimii $[1, 2, 3, ..., j]$. Vom calcula $comun[A]$ = numarul de puteri aflate in intersectia tuturor secventelor $(x*1, x*2, x*3, ..., x*M)$, pentru $x apartinand lui A$. Intersectia acestor secvente trebuie sa contina numai elemente $&le; M * min(A)$, unde $min(A)$ = elementul minim din subsetul A, si numai elemente divizibile cu $lcm(A)$, unde $lcm(A)$ reprezinta cel mai mic multiplu comun al elementelor din $A$. Astfel $comun[A]$ va fi egal cu $[M * min(A) / lcm(A)]$, unde $[x]$ reprezinta partea intreaga a lui $x$.\r\n\r\nAcum, conform principiului includerii si excluderii. putem determina numarul de elemente distincte ale secventei corespunzatoare lui $i$, adunand $comun[A]$ pentru toate subseturile $A$ avand numar impar de elemente si scazand $comun[A]$ pentru toate subseturile $A$ avand numar par de elemente.\r\n\r\nObservam ca pentru multe numere din setul $S$, puterea maxima $j$ la care poate fi ridicat astfel incat rezultatul sa fie $&le; N$ se repeta si vom calcula $comun[A]$ de multe ori pentru aceleasi subseturi. Pentru a evita acest lucru putem calcula valorile lui $comun$ la inceput, pentru orice subset al multimii $[1, 2, 3, ..., log{~2~} N]$ si mentine $rez[x]$ = numarul de elemente distincte din secventa generata de un element $i$ din $S$ pentru care puterea maxima este egala cu $x$.\r\n\r\nComplexitatea totala devine O(2^log N^ log N)) precalcularea lui $comun$ + $O(N)$ adunarea sumelor, deci $O(N log N)$.\r\n\r\n* $O(N + nr_M_distinct * N log N)$ precalculare, $O(N)$ pe test - $70$ de puncte\r\n\r\nObservam ca valorile lui $comun$ si $rez$ depind doar de $M$ si deci le putem calcula doar pentru fiecare $M$ diferit din fisierul de intrare.\r\n\r\n* $O(N + nr_M_distinct * N log N)$ precalculare, $O(log^2^ N)$ pe test - $100$ de puncte\r\n\r\nAm observat deja ca daca $2$ numere diferite $i$ si $j$ din setul $S$ au aceeasi putere maxim $j$ la care pot fi ridicate fara sa depaseasca $N$, numarul de elemente distincte din secventa generata de fiecare dintre ele este egal.\r\n\r\nIn loc sa parcurgem toate elementele din $S$, putem numara pentru fiecare putere $j$ de la $1$ la $log{~2~} N$ cate numere din $S$ au aceasta putere maxima. Pentru fiecare putere putem determina limitele sale inferioare si superioare prin cautare binara si, precalculand $nrInS[i]$ = cate numere naturale $&le; i$ sunt in setul $S$, putem determina cate elemente sunt in $S$ intre cele 2 limite. Complexitate finala pe test $O(log^2^ N)$.\r\n\r\nh2. Observatie\r\n\r\nEste posibil sa ajungem la un query time de $O(1).\r\nAstfel, sa presupunem ca pentru fiecare putere pana in logN stim cate duplicate sunt generate de un numar care este putere maxima.\r\n( exemplu: pentru exponentul egal cu 4, stim ca avem x duplicate. Atunci daca inmultim numarul de numere care sunt puteri la a patra ( 16, 81, etc )\r\ncu x o sa avem numarul de duplicate date de puterile la a patra. Daca facem asta pentru fiecare putere p pana in logN, si adaugam la rezultat, obtinem rezultatul query-ului pentru un N dat. \r\nIn primul rand, pentru fiecare n <= N si p <= logN, putem precalcula cate puteri la a p-a sunt <= n, in $O( N log N ). De asemenea, putem\r\npreprocesa fiecare query posibil in $O(N log N) [ nu avem decat sa stocam produsul \"cate puteri la a p-a sunt <= n\" * \"cate duplicate sunt pentru p\" ]. \r\nTinand cont ca $O(N log N) necesitam oricum pentru fiecare M distinct, ajungem la un query time de $O(1).\r\n\r\nSper ca s-a inteles :)\r\n\r\nh2. Solutie alternativa\r\n\r\nA doua solutie calculeaza care sunt puterile $i$ pentru care $u^i^$ poate fi scris ca $v^j^$ cu $v < u$ si $j &le; M$. Prima conditie pe care trebuie sa o indeplineasca $u$, este sa se scrie de forma $p{~1~}^f1^ * ... * p{~t~}^ft^$ unde $cmmdc(f{~1~}, ..., f{~t~}) = d$, $d != 1$. Daca notam $w$ radicalul de ordin $d$ al lui $u$, atunci $u^i^$ se va scrie ca $w^d*i^$, ba chiar mai mult se va scrie ca $(w^q^)^i*d/q^$ unde $q$ divide $d$.\r\nPornind de la aceste observatii putem calcula pentru un M fixat cate numere distincte generaza $(w^d^)^i^$ pentru fiecare d in parte ( $d$ este maxim $log{~2~}N$, adica $16$). $(w^d^)^i^$ se poate scrie in functie de $w^q^$ cu $q < d$, daca $i$ e divizibil cu $q/cmmdc(d, q)$, adica $i*d$ multiplu al lui $cmmmc(d, q)$. Asadar pentru fiecare $d$ intre $2$ si $16$ si $q$ intre $1$ si $d$, vom insemna intr-un tablou ca puterea $k*cmmmmc(d, q)$, unde $k * cmmmc(d, q) / q <= M$ este duplicat pentru orice $u = w^d^$.\r\nAcum mai trebuie sa calculam pentru toate valorile de la $1$ la $N$ care este cmmdc-ul puterilor factorilor (adica $d$). Aceasta se poate face foarte repede sub forma asemanatoare cu ciurul lui Eratostene, numerele care au $d > 1$ pot fi scrise ca un numar mai mic ridicat la o putere si in loc sa adunam, inmultim.\r\nCu acest algoritm calculam dintr-o data toate query-urile care au acelasi $M$. \r\nComplexitatea finala este $O(nr_M_distinct * (M log^2^ N + N log N))$. O implementare atenta a acestei solutii va lua $100$ de puncte.\r\n\r\n',958,'public',NULL,NULL),('algoritmiada-2009/runda-2/solutii/jap','algoritmiada-2009/runda-2/solutii/jap','2009-01-03 17:08:08','2009-01-11 12:47:51','h1(#jap). \'Jap\':problema/jap\r\n\r\nVom considera toate numerele naturale intre $2$ si $N$ inclusiv care nu pot fi scrise sub forma $x^y^$, unde $y diferit de 1$. Notam aceasta multime cu numere $S$. Pentru fiecare din aceste numere vom calcula puterea maxima la care poate fi ridicat astfel incat rezultatul sa fie $&le; N$. Pentru un numar $i$, vom considera ca aceasta putere este $j$ (deci $i^j^ &le; N$) si vom incerca sa calculam cate elemente distincte se pot genera ridicand fiecare din elementele $i^1^$, $i^2^$, $i^3^$, ..., $i^j^$ la puteri intre $1$ si $M$. Astfel pentru $i$ va trebui sa calculam cate elemente distincte are secventa $i^1^$, $i^2^$, ..., $i^M^$, $i^2*1^$, $i^2*2^$, ..., $i^2*M^$, ..., $i^j*1^$, $i^j*2^$, ..., $i^j*M^$. Observam ca oricum am alege $x$ si $y$ din multimea $S$, secventele generate cu regula de mai sus vor fi complet disjuncte, si in plus reuniunea tuturor secventelor va constitui intreaga secventa data in enunt. Astfel, suma numarului de elemente distincte determinate pentru fiecare $x$ din $S$ va reprezenta numarul cerut in enunt.\r\n\r\nSetul $S$ poate fi determinat, parcurgand elementele de la $2$ la $N$ si marcand toate puterile mai mari ca 1 al elementului curent ca nefacand parte din set. Determinarea setului $S$ are complexitate $O(N)$.\r\n\r\nDe aici putem elabora mai multe solutii de complexitati diferite:\r\n\r\n* $O(N)$ precalculare, $O(N * M * log(N * M))$ pe test - $20$ de puncte\r\n\r\nPentru fiecare $i$ din $S$, calculam $j$, cel mai mare numar natural astfel incat $i^j^ &le; N$, adaugam puterile $1, 2, 3, ..., M, 2, 4, 6, ..., 2M, ..., j, 2j, 3j, ..., jM$ intr-un vector, il sortam si adunam la rezultat numarul de elemente distincte din el.\r\n\r\n* $O(N)$ precalculare, $O(N log N)$ pe test - $50$ de puncte\r\n\r\nPentru fiecare $i$, vom calcula numarul de elemente distincte din secventa corespunzatoare lui folosind principiul includerii si excluderii. Fie $A$ un subset al multimii $[1, 2, 3, ..., j]$. Vom calcula $comun[A]$ = numarul de puteri aflate in intersectia tuturor secventelor $(x*1, x*2, x*3, ..., x*M)$, pentru $x apartinand lui A$. Intersectia acestor secvente trebuie sa contina numai elemente $&le; M * min(A)$, unde $min(A)$ = elementul minim din subsetul A, si numai elemente divizibile cu $lcm(A)$, unde $lcm(A)$ reprezinta cel mai mic multiplu comun al elementelor din $A$. Astfel $comun[A]$ va fi egal cu $[M * min(A) / lcm(A)]$, unde $[x]$ reprezinta partea intreaga a lui $x$.\r\n\r\nAcum, conform principiului includerii si excluderii. putem determina numarul de elemente distincte ale secventei corespunzatoare lui $i$, adunand $comun[A]$ pentru toate subseturile $A$ avand numar impar de elemente si scazand $comun[A]$ pentru toate subseturile $A$ avand numar par de elemente.\r\n\r\nObservam ca pentru multe numere din setul $S$, puterea maxima $j$ la care poate fi ridicat astfel incat rezultatul sa fie $&le; N$ se repeta si vom calcula $comun[A]$ de multe ori pentru aceleasi subseturi. Pentru a evita acest lucru putem calcula valorile lui $comun$ la inceput, pentru orice subset al multimii $[1, 2, 3, ..., log{~2~} N]$ si mentine $rez[x]$ = numarul de elemente distincte din secventa generata de un element $i$ din $S$ pentru care puterea maxima este egala cu $x$.\r\n\r\nComplexitatea totala devine O(2^log N^ log N)) precalcularea lui $comun$ + $O(N)$ adunarea sumelor, deci $O(N log N)$.\r\n\r\n* $O(N + nr_M_distinct * N log N)$ precalculare, $O(N)$ pe test - $70$ de puncte\r\n\r\nObservam ca valorile lui $comun$ si $rez$ depind doar de $M$ si deci le putem calcula doar pentru fiecare $M$ diferit din fisierul de intrare.\r\n\r\n* $O(N + nr_M_distinct * N log N)$ precalculare, $O(log^2^ N)$ pe test - $100$ de puncte\r\n\r\nAm observat deja ca daca $2$ numere diferite $i$ si $j$ din setul $S$ au aceeasi putere maxim $j$ la care pot fi ridicate fara sa depaseasca $N$, numarul de elemente distincte din secventa generata de fiecare dintre ele este egal.\r\n\r\nIn loc sa parcurgem toate elementele din $S$, putem numara pentru fiecare putere $j$ de la $1$ la $log{~2~} N$ cate numere din $S$ au aceasta putere maxima. Pentru fiecare putere putem determina limitele sale inferioare si superioare prin cautare binara si, precalculand $nrInS[i]$ = cate numere naturale $&le; i$ sunt in setul $S$, putem determina cate elemente sunt in $S$ intre cele 2 limite. Complexitate finala pe test $O(log^2^ N)$.\r\n\r\nh2. Observatie\r\n\r\nEste posibil sa ajungem la un query time de $O(1)$.\r\nAstfel, sa presupunem ca pentru fiecare putere pana in $logN$ stim cate duplicate sunt generate de un numar care este putere maxima.\r\n( exemplu: pentru exponentul egal cu 4, stim ca avem $x$ duplicate. Atunci daca inmultim numarul de numere care sunt puteri la a patra ( 16, 81, etc ) cu $x$ o sa avem numarul de duplicate date de puterile la a patra. Daca facem asta pentru fiecare putere $p$ pana in $logN$, si adaugam la rezultat, obtinem rezultatul query-ului pentru un $N$ dat. \r\nIn primul rand, pentru fiecare $n <= N$ si $p <= logN$, putem precalcula cate puteri la a p-a sunt $<= n$, in $O( N log N )$. De asemenea, putem\r\npreprocesa fiecare query posibil in $O(N log N)$ [ nu avem decat sa stocam produsul \"cate puteri la a $p$a sunt $<= n$\" * \"cate duplicate sunt pentru $p$\"]. \r\nTinand cont ca $O(N log N)$ necesitam oricum pentru fiecare $M$ distinct, ajungem la un query time de $O(1)$.\r\n\r\nSper ca s-a inteles :)\r\n\r\nh2. Solutie alternativa\r\n\r\nA doua solutie calculeaza care sunt puterile $i$ pentru care $u^i^$ poate fi scris ca $v^j^$ cu $v < u$ si $j &le; M$. Prima conditie pe care trebuie sa o indeplineasca $u$, este sa se scrie de forma $p{~1~}^f1^ * ... * p{~t~}^ft^$ unde $cmmdc(f{~1~}, ..., f{~t~}) = d$, $d != 1$. Daca notam $w$ radicalul de ordin $d$ al lui $u$, atunci $u^i^$ se va scrie ca $w^d*i^$, ba chiar mai mult se va scrie ca $(w^q^)^i*d/q^$ unde $q$ divide $d$.\r\nPornind de la aceste observatii putem calcula pentru un M fixat cate numere distincte generaza $(w^d^)^i^$ pentru fiecare d in parte ( $d$ este maxim $log{~2~}N$, adica $16$). $(w^d^)^i^$ se poate scrie in functie de $w^q^$ cu $q < d$, daca $i$ e divizibil cu $q/cmmdc(d, q)$, adica $i*d$ multiplu al lui $cmmmc(d, q)$. Asadar pentru fiecare $d$ intre $2$ si $16$ si $q$ intre $1$ si $d$, vom insemna intr-un tablou ca puterea $k*cmmmmc(d, q)$, unde $k * cmmmc(d, q) / q <= M$ este duplicat pentru orice $u = w^d^$.\r\nAcum mai trebuie sa calculam pentru toate valorile de la $1$ la $N$ care este cmmdc-ul puterilor factorilor (adica $d$). Aceasta se poate face foarte repede sub forma asemanatoare cu ciurul lui Eratostene, numerele care au $d > 1$ pot fi scrise ca un numar mai mic ridicat la o putere si in loc sa adunam, inmultim.\r\nCu acest algoritm calculam dintr-o data toate query-urile care au acelasi $M$. \r\nComplexitatea finala este $O(nr_M_distinct * (M log^2^ N + N log N))$. O implementare atenta a acestei solutii va lua $100$ de puncte.\r\n\r\n',958,'public',NULL,NULL),('home','infoarena -  comunitate informatica, concursuri de programare','2006-11-05 14:45:56','2009-01-11 07:07:29','h1. Bine ai venit pe infoarena!\r\n\r\nSuntem o comunitate de tineri pasionati de informatica si programare.\r\nInvatam impreuna participand la concursuri online de programare, citind stiri si articole despre informatica sau discutand pe forum.\r\n\r\n\'*&raquo; Afla mai multe despre noi!*\':despre-infoarena\r\n\r\ntable{width:99%; margin:auto}. |={background-color: rgb(210, 244, 219); border: 0; padding: 0.3em; -moz-border-radius:7px}. \'*Runda 2*\':algoritmiada-2009/runda-2 a concursului \'*Algoritmiada 2009*\':algoritmiada-2009 a inceput. Participa acum!|\r\n\r\n\r\nh1. Ultimele insemnari de pe \'blog\':blog \'!{vertical-align:middle}home?rss_icon.jpg!\':blog?action=rss\r\n\r\n==BlogPreview(display_entries=\"10\")==\r\n',2028,'protected',NULL,NULL),('2-sat','Problema satisfiabilității formulelor logice de ordinul doi','2008-12-09 15:55:03','2009-01-10 16:38:19','h1. Problema satisfiabilităţii formulelor logice de ordinul doi\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"marius\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 30em}*{text-align:center} *Conţinut:*\r\n* {\'Introducere\':2-sat#introducere}\r\n* {\'Forme normale ale formulelor logice\':2-sat#forme-normale}\r\n* {\'SAT, 3-SAT, 2-SAT\':2-sat#overview-sat}\r\n* {\'Soluţii pentru 2-SAT\':2-sat#solutii-2-sat}\r\n** {\'Soluţie $O(M * 2^N^)$\':2-sat#solutie-1}\r\n** {\'Soluţie $O(N * M)$\':2-sat#solutie-2}\r\n** {\'Soluţie $O(N^2^)$\':2-sat#solutie-3}\r\n** {\'Soluţie $O(M + N)$\':2-sat#solutie-4}\r\n* {\'Aplicaţii\':2-sat#aplicatii}\r\n** {\'Party &#40;preONI 2003/2004&#41;\':2-sat#party}\r\n** {\'Cigraf\':2-sat#cigraf}\r\n** {\'Peace Commission &#40;Polish Olympiad in Informatics, 2001&#41;\':2-sat#peace-commission}\r\n** {\'Orpath &#40;Olimpiadă Rusia&#41;\':2-sat#orpath}\r\n** {\'Aladdin &#40;Bursele Agora 2005/2006, Runda 1&#41;\':2-sat#aladdin}\r\n* {\'Bibliografie\':2-sat#bibliografie}\r\n\r\nh2(#introducere). Introducere\r\n\r\nProblema satisfiabilităţii, notată prescurtat cu $SAT$, cere determinarea existenţei pentru o formulă booleană <tex> \\phi </tex> a unei atribuiri satisfiabile. O formulă booleană <tex> \\phi </tex> este compusă din $variabile$ logice <tex> (x_{1}, x_{2}, ...) </tex>, $operatori$ logici ( <tex> \\wedge </tex> şi,  <tex> \\vee </tex> sau, <tex> \\sim </tex> non, <tex> \\rightarrow </tex> implicaţie, <tex> \\leftrightarrow </tex> echivalenţă), şi $paranteze$. O atribuire de valori booleene pentru variabilele acestei expresii se numeşte $atribuire satisfiabilă$ dacă evaluarea expresiei după atribuirea valorilor dă ca rezultat valoarea de adevăr $adevărat$. De acum încolo vom folosi pentru simplitate valorile <tex> 1 </tex> şi <tex> 0 </tex> în loc de $adevărat$ şi $fals$.\r\n\r\nUn exemplu de formulă ar fi <tex> \\phi = ((x_{1} \\rightarrow x_{2}) \\vee \\sim((\\sim x_{1} \\leftrightarrow x_{3}) \\vee x_{4})) \\wedge \\sim x_{2} </tex>. Aceasta are atribuirea satisfiabilă <tex> \\langle x_{1} = 0, x_{2} = 0, x_{3} = 1, x_{4} = 1 \\rangle </tex> pentru că <tex> \\phi = ((0 \\rightarrow 0) \\vee \\sim((\\sim 0 \\leftrightarrow 1) \\vee 1)) \\wedge \\sim 0 = (1 \\vee \\sim (1 \\vee 1)) \\wedge 1 = (1 \\vee 0) \\wedge 1 = 1</tex>. \r\n\r\nh2(#forme-normale). Forme normale ale formulelor logice\r\n\r\nOrice formulă booleană poate fi transformată în două forme:\r\n\r\n* $Forma normal conjunctivă$ în care expresia este exprimată ca o conjuncţie de propoziţii, iar fiecare propoziţie este formată dintr-o disjuncţie de $literali$. Un $literal$ este o variabilă care poate fi sau nu negată. Un exemplu de expresie în forma normal conjunctivă ar fi: <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) \\wedge (x_{3} \\vee x_{2} \\vee x_{4}) \\wedge (\\sim x_{1} \\vee \\sim x_{3} \\vee \\sim x_{4}) </tex> care are pe <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) </tex> ca primă propoziţie cu literalii <tex> x_{1} </tex>, <tex> \\sim x_{1} </tex>, <tex> \\sim x_{2} </tex>.\r\n\r\n* $Forma normal disjunctivă$ este formată ca o disjuncţie de propoziţii, fiecare dintre aceste propoziţii fiind o conjuncţie de literali. Un exemplu de o asemenea formulă ar fi următoarea: <tex> (x_{1} \\wedge x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge \\sim x_{3}) \\vee (\\sim x_{1} \\wedge x_{2} \\wedge \\sim x_{2}) </tex>.\r\n\r\nh2(#overview-sat). SAT, 3-SAT, 2-SAT\r\n\r\nProblema $SAT$ este $NP-completă$. De fapt, este prima problemă $NP-completă$ găsită. Stephen Cook a demonstrat $NP-completitudinea$ ei în 1971. Pe vremea aceea nu se ştia nici măcar că problemele $NP-complete$ există. Această problemă rămâne $NP-completă$ chiar dacă restricţionăm expresiile la unele care în forma normal conjunctivă au doar trei literali. Problema satisfiabilităţii pentru asemenea expresii se numeşte $3-SAT$, şi multe probleme pot fi demonstrate a fi $NP-complete$ prin reducerea lui $3-SAT$ la problemele respective în timp polinomial. Din fericire, problema $2-SAT$, adică cea pentru care în fiecare propoziţie există doar $2$ literali, se poate rezolva eficient. Restul articolului va prezenta trei metode de rezolvare a problemei $2-SAT$ şi câteva aplicaţii ale acesteia din concursuri de programare.\r\n\r\nh2(#solutii-2-sat). Soluţii pentru 2-SAT\r\n\r\nUn exemplu de problemă $2-SAT$ ar fi satisfiabilitatea formulei <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Această formulă este satisfăcută de valorile <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>. Pentru a satisface întreaga expresie trebuie ca în fiecare propoziţie cel puţin unul din cei doi literali să aibă valoarea de adevăr <tex> 1 </tex>.\r\n\r\nh3(#solutie-1). Soluţie $O(M * 2^N^)$\r\n\r\nO primă metodă de rezolvare ar fi să încercăm toate cele $2^N^$ posibilităţi de atribuire posibilă, dar această metodă are ordinul de complexitate $O(M * 2^N^)$ şi este eficientă doar pentru instanţe mici ale problemei.\r\n\r\nh3(#solutie-2). Soluţie $O(N * M)$\r\n\r\nUrmătoarea soluţie pare trivială, dar găsirea acestui algoritm şi realizarea faptului că el rezolvă corect problema sunt mai grele decât impresia lăsată după citirea ei. Considerăm o propoziţie oarecare cu două variabile $p$ şi $q$, apoi una dintre ele, de exemplu $p$. Îi atribuim literalului în care apare $p$ valoarea $0$. Pentru ca propoziţia respectivă să aibă $1$ valoarea de adevăr, atunci valoarea lui $q$ trebuie fixată. Fixând şi valoarea lui $q$, probabil şi alte propoziţii ce conţin literalul $q$ vor avea celălalt literal fixat. Propagăm astfel o serie de schimbări. După ce toate schimbările forţate au fost făcute, propoziţiile rezultate vor fi de următoarele tipuri: <tex> a \\vee b </tex>, <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex>. Propoziţii de tip <tex> 0 \\vee b </tex> nu pot apărea pentru că toate schimbările forţate au fost deja propagate. Dacă apare o propoziţie <tex> 0 \\vee 0 </tex> atunci alegerea făcută pentru valoarea lui $p$ este greşită. Vom încerca şi alegerea opusă pentru $p$. Dacă ambele duc la o propoziţie de tip <tex> 0 \\vee 0 </tex> atunci expresia nu poate fi satisfăcută. Propoziţiile de forma <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex> pot fi ignorate. În acest fel am eliminat cel puţin o variabilă şi o propoziţie din expresie. Dacă expresia iniţială era satisfiabilă, atunci şi expresia din care s-au eliminat câteva propoziţii a rămas satisfiabilă. Continuând pe această idee obţinem un algoritm de complexitate $O(N * M)$, pentru că la fiecare atribuire de valoare pentru o variabilă parcurgem şirul de propoziţii o dată. \r\n\r\nSă vedem cum funcţionează algoritmul pentru expresia: <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Considerăm propoziţia <tex> (x_{1} \\vee \\sim x_{2}) </tex> şi <tex> \\langle x_{2} = 1 \\rangle </tex>. Astfel, vom obţine mai departe <tex> (x_{1} \\vee 0) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee 1) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. În propoziţia <tex> (x_{1} \\vee 0) </tex>, <tex> x_{1} </tex> trebuie să fie egal cu <tex> 1 </tex>. Acum, expresia devine: <tex> (0\\ \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee 0) </tex>. Din propoziţia <tex> (0\\ \\vee \\sim x_{3}) </tex> obţinem <tex> \\langle x_{3} = 0 \\rangle </tex>, iar din <tex> (x_{4} \\vee 0) </tex> obţinem <tex> \\langle x_{4} = 1 \\rangle </tex>. Deci, atribuirea satisfiabilă este <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>.\r\n\r\nh3(#solutie-3). Soluţie $O(N^2^)$\r\n\r\nO altă soluţie elegantă se bazează pe o metodă randomizată:\r\n\r\n== code(cpp) |\r\natribuim valori booleene arbitrare variabilelor;\r\ncât timp expresia nu este satisfăcută, execută\r\n    găsim o propoziţie cu valoarea de adevăr 0;\r\n    schimbăm valoarea de adevăr a oricăreia dintre cele două variabile prezente în propoziţie;\r\nsfârşit cât timp\r\n==\r\n\r\nLinia $4$ va face ca acea propoziţie să aibă noua valoare de adevăr <tex> 1 </tex>.\r\n\r\nDe ce ar merge acest algoritm? Să presupunem că există o soluţie a problemei, o notăm cu <tex> S </tex>, iar cu <tex> X </tex> notăm şirul valorilor curente ale variabilelor. Ne uităm la fiecare pas al algoritmului la numărul de variabile care au valori diferite în soluţie faţă de cele din <tex> X </tex> (acest număr de diferenţe între elementele de acelaşi index pentru două şiruri se mai numeşte şi \'distanţă Hamming\':http://en.wikipedia.org/wiki/Hamming_distance între şiruri). Fie această valoare la pasul current $K$. Noi am vrea să avem $K = 0$. Cum va evolua $K$ pe parcursul algoritmului? La un moment dat noi schimbăm valoarea unei variabile luate aleator dintr-o propoziţie nesatisfăcută. Pentru că în <tex> S </tex> propoziţia este satisfăcută, înseamnă că cel puţin una dintre cele două variabile ale propoziţiei are valori diferite în <tex> X </tex> faţă de <tex> S </tex>. Astfel, operaţia făcută de noi are probabilitate de cel puţin $0.5$ să ne aducă mai aproape de soluţie. Vom nota cu <tex> T(i) </tex> numărul probabil de paşi în care un şir <tex> X </tex> aflat la distanţa Hamming egală cu $i$ faţă de <tex> S </tex>, va fi transformat în <tex> S </tex>. Evident:\r\n\r\n<tex> T(0) = 0 </tex>\r\n\r\n<tex> T(i) \\le \\frac {T(i + 1) + T(i - 1)}{2} + 1 </tex> pentru $0 < i < N$ ({$N$} e numărul de variabile booleene ale expresiei)\r\n\r\nSe pune semnul de inegalitate pentru că ambele variabile pot avea valori diferite faţă de cele din soluţie, deci schimbarea valorii oricăreia ar putea să ne aducă mai aproape de soluţie.\r\n\r\nDacă toate variabilele diferă de soluţie, orice schimbare ne aduce mai aproape de aceasta:\r\n\r\n<tex> T(N) = T(N - 1) + 1 </tex>\r\n\r\nNe interesează numai limitele superioare, deci folosim doar egalităţi în loc de inegalităţi:\r\n\r\n<tex> X(0) = 0 </tex>, <tex> X(i) = \\frac {X(i + 1) + X(i - 1)}{2} + 1 </tex>, <tex> X(N) = X(N - 1) + 1 </tex>\r\n\r\nDacă adunăm toate ecuaţiile obţinem:\r\n\r\n<tex> X(0) + X(1) + ... + X(N) = </tex> <tex> \\frac {X(0) + X(1) + 2X(2) + ... + 2X(N - 2) + X(N - 1) + X(N)}{2} + X(N) + N - 1 </tex>\r\n\r\nDe aici avem că <tex> \\frac {X(1) + X(N - 1) - X(N)}{2} = N - 1 </tex>, iar din <tex> X(N) = X(N - 1) + 1 </tex> rezultă că <tex> X(1) = 2N - 1 </tex>. Mai departe avem că <tex> X(2) = 4N - 4 </tex> <tex> ... </tex> <tex> X(i) = 2iN - i^2 </tex>, de unde, când <tex> i = N </tex>, avem că <tex> X(N) = N^2 </tex>.\r\n\r\nAstfel, numărul mediu de paşi ai algoritmului este pătratic în numărul $N$ de variabile. Lăsând algoritmul să ruleze de 2-3 ori mai mulţi paşi decât numărul mediu, avem o probabilitate foarte mare să ajungem la rezultat.\r\n\r\nh3(#solutie-4). Soluţie $O(M + N)$\r\n\r\nO a treia soluţie se bazează pe relaţia de implicaţie. Relaţia <tex> \\rightarrow </tex> are următoarea tabelă de adevăr:\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> A \\rightarrow B </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nRelaţia de implicaţie are următoarea semnificaţie: dacă <tex> A </tex> este adevărat atunci şi <tex> B </tex> este adevărat. Scriem tabela expresiei <tex> \\sim A \\vee B </tex> şi observăm că aceasta este egală cu cea a relaţiei de implicaţie.\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> \\sim A \\vee B </tex>|\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nFiecare clauză <tex> A \\vee B </tex> poate fi scrisă ca două implicaţii <tex> \\sim A \\rightarrow B </tex> şi <tex> \\sim B \\rightarrow A </tex>. Realizăm un graf al implicaţiilor. Astfel, nodurile grafului vor fi variabilele <tex> A </tex>, <tex> B </tex> <tex> ... </tex> şi negaţiile lor <tex> \\sim A </tex>, <tex> \\sim B </tex> <tex> ... </tex> iar muchiile acestui graf vor fi implicaţiile echivalente cu propoziţiile din expresie. Deci, dacă expresia are $M$ propoziţii, graful va avea $2M$ muchii. Acestea fiind zise, expresiei <tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) </tex> îi corespunde graful:\r\n\r\np=. !2-sat?Graf.png!\r\n\r\nDacă avem <tex> A \\longrightarrow B </tex> o muchie în graful nostru şi literalul <tex> A </tex> este adevărat, atunci şi literalul <tex> B </tex> trebuie să fie adevărat pentru ca propoziţia reprezentată de muchie să fie satisfăcută. Putem demonstra prin inducţie că dacă există un drum în graf de la literalul <tex> A </tex> la literalul <tex> B </tex>, atunci dacă <tex> A </tex> este adevărat şi <tex> B </tex> trebuie să fie adevărat. Dacă există un drum de la un literal <tex> X </tex> la <tex> \\sim X </tex>, precum şi un drum invers, atunci nu va exista soluţie pentru că nu putem seta în acelaşi timp o variabilă şi valoarea ei negată la valoarea adevărat. De aici rezultă că dacă în graful asociat expresiei există o variabilă <tex> X </tex> în aceeaşi componentă tare conexă cu <tex> \\sim X </tex> atunci instanţa problemei satisfiabilităţii nu poate fi satisfăcută. Dacă nu există o asemenea variabilă, vom vedea în continuare cum putem rezolva problema. Întâi, facem observaţia că dacă în graf există muchia <tex> A \\longrightarrow B </tex> atunci există şi muchia <tex> \\sim B \\longrightarrow \\sim A </tex>. Astfel, dacă există un drum de la <tex> A </tex> la <tex> B </tex> în graf, aplicând proprietatea menţionată pentru fiecare muchie a drumului, vom găsi un drum de la <tex> \\sim B </tex> la <tex> \\sim A </tex>. Evident, afirmaţia este valabilă şi reciproc: dacă există drum de la <tex> B </tex> la <tex> A </tex> atunci vom avea un drum de la nodul <tex> \\sim A </tex> la <tex> \\sim B </tex>. Astfel, dacă avem că <tex> A </tex> şi <tex> B </tex> sunt în aceeaşi componentă tare conexă atunci şi nodurile <tex> \\sim A </tex> şi <tex> \\sim B </tex> sunt în aceeaşi componentă tare conexă. Deci, dacă nu există doi literali <tex> X </tex> şi <tex> \\sim X </tex> în aceeaşi componentă tare conexă, putem să împărţim graful în componente tare conexe şi să împerechem componentele câte două astfel ca în fiecare pereche să apară o componentă <tex> U </tex> cu nişte literali şi altă componentă <tex> \\sim U </tex> cu aceiaşi literali negaţi. Pentru a găsi o soluţie vom determina mai întâi componentele tare conexe ale grafului. Apoi putem contracta fiecare componentă într-un nod. Graful obţinut va fi aciclic. Alegem un nod <tex> u </tex> în care nu intră nicio muchie (un asemenea nod trebuie să existe pentru a nu exista cicluri). Din considerente de simetrie, din nodul lui pereche <tex> \\sim u </tex> nu va ieşi nicio muchie. Literalilor componentei <tex> U </tex> putem să le dăm valoarea de adevăr <tex> 0 </tex>, iar literalilor din componenta pereche <tex> \\sim U </tex>  putem să le dăm valoarea de adevăr <tex> 1 </tex>. Această alegere nu impune restricţii asupra celorlalţi literali şi elimină câteva variabile din problemă. Repetarea recursivă a acestui pas pe graful rămas va duce la rezolvarea problemei. Determinarea componentelor tare conexe se poate face în complexitatea $O(N + M)$. Pentru a vedea acest algoritm puteţi consulta \'secţiunea $23.5$\':http://zhuzeyuan.hp.infoseek.co.jp/ita/chap23.htm din {\'[1]\':2-sat#bibliografie}. Iar eliminarea  nodurilor de care vorbeam mai sus se poate face în $O(N + M)$ folosind o sortare topologică.\r\n\r\nSă urmărim cum merge algoritmul nostru pe exemplul de mai sus. Componentele tare conexe sunt următoarele: <tex> \\{A\\} </tex>, <tex> \\{\\sim A\\} </tex>, <tex> \\{B, C, \\sim D\\} </tex>, <tex> \\{\\sim B, \\sim C, D\\} </tex>. În nodul asociat componentei <tex> \\{A\\} </tex> nu intră nici o muchie. Astfel, putem să îi atribuim lui <tex> A </tex> valoarea <tex> 0 </tex>, iar după eliminarea lui <tex> \\{A\\} </tex> şi <tex> \\{\\sim A\\} </tex>în nodul asociat componentei <tex> \\{\\sim B, \\sim C, D\\} </tex> nu intră nicio muchie, deci putem să îi atribuim lui <tex> B </tex> valoarea <tex> 1 </tex>, lui <tex> C </tex> valoarea <tex> 1 </tex> şi lui <tex> D </tex> valoarea <tex> 0 </tex>. Această atribuire este satisfiabilă după cum vedem în continuare:\r\n\r\n<tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) = </tex> <tex> (\\sim 0 \\vee \\sim 1) \\wedge (1 \\vee \\sim 1) \\wedge (1 \\vee 1) \\wedge (\\sim 1 \\vee \\sim 0) \\wedge (1 \\vee 0) = </tex> <tex> 1 \\wedge 1 \\wedge 1 \\wedge 1 \\wedge 1 = 1 </tex>\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\nRestul articolului va prezenta aplicaţii ale problemei $2-SAT$ din concursurile de programare.\r\n\r\nh2(#party). \'Party\':problema/party (preONI 2003/2004)\r\n\r\nbq. George vrea să îşi organizeze majoratul, şi vrea ca petrecerea să fie de neuitat, mâncarea, băutura, locaţia şi sonorizarea sunt deja asigurate, mai rămâne problema chemării prietenilor. El şi cu prietenul lui cel mai bun Lucian au preferinte diferite şi pentru a nu se certa au pus la punct o listă de cerinţe care vor trebui să fie îndeplinite astfel încât cheful să se desfăşoare în cele mai bune condiţii! Pentru uşurinţă,  prietenii lui George vor fi indentificaţi prin numere întregi de la $1$ la $N (1 ≤ N ≤ 100)$ şi cerinţele în număr de $M  (1 ≤ M ≤ 1.000)$ vor fi de tipurile 0, 1, 2 sau 3. O cerinţă de genul <tex> x \\ y </tex> 0 are semnificaţia că <tex> x </tex> sau <tex> y </tex> trebuie să participe la petrecere; <tex> x \\ y </tex> 1 are semnificaţia că dacă <tex> x </tex> participă nu există nici o restricţie pentru <tex> y </tex>, dar dacă <tex> x </tex> nu participă atunci nici <tex> y </tex> nu participa; <tex> x \\ y </tex> 2 are semnificaţia simetrică cu cerinţa 1; iar cerinţa <tex> x \\ y </tex> 3 are semnificaţia că cel puţin unul dintre <tex> x </tex> şi <tex> y </tex> nu participă la petrecere. Scrieţi un program care să-i ajute pe cei doi să determine care persoane vor fi invitate la petrecere. Se garantează că va fi posibilă întotdeauna organizarea unei petreceri!\r\n\r\nh3. Soluţie\r\n\r\nAceastă problemă este inspirită din o problemă de la $CEOI 2002$ şi este evident că ne cere să determinăm o atribuire satisfiabilă pentru o formulă logică formată ca conjuncţie între cerinţele care se transformă astfel:\r\n\r\n* _cerinţa de tip 0_ corespunde propoziţiei <tex> x \\vee y </tex>;\r\n* _cerinţa de tip 1_ corespunde propoziţiei <tex> x \\vee \\sim y </tex>;\r\n* _cerinţa de tip 2_ corespunde propoziţiei <tex> \\sim x \\vee y </tex>;\r\n* _cerinţa de tip 3_ corespunde propoziţiei <tex> \\sim x \\vee \\sim y </tex>.\r\n\r\nUna din primele două rezolvări ar fi putut soluţiona această problemă, dar problema de la $CEOI$ avea limite mai mari şi pentru rezolvarea ei ar fi trebuit un algoritm de complexitate $O(N + M)$.\r\n\r\nh2(#cigraf). Cigraf\r\n\r\n_Autor: Mugurel Ionuţ Andreica_\r\n\r\nbq. Se dă un graf neorientat cu $N (1 <= N <= 1000)$ noduri şi $M (0 <= M <= N*(N-1)/2)$ muchii. Se doreşte împărţirea nodurilor acestui graf în $2$ mulţimi, <tex> C </tex> şi <tex> I </tex>, având următoarele proprietăţi: fiecare nod face parte din exact una din cele $2$ mulţimi, există muchie între oricare $2$ noduri din mulţimea <tex> C </tex>, nu există nicio muchie între $2$ noduri din mulţimea <tex> I </tex>. Este posibil ca una dintre cele $2$ mulţimi să fie vidă. Soluţia nu este neaparat unică. Numele celor două mulţimi provin de la $clică$ şi $mulţime independentă$. De exemplu, pentru graful de $6$ noduri ce are muchiile <tex> \\{\\{1, 4\\}, \\{4, 6\\}, \\{6, 1\\}, \\{2, 4\\}, \\{2, 6\\}, \\{3, 4\\}, \\{1, 3\\}\\} </tex> o împărţire posibilă ar fi <tex> C = \\{1, 4, 6\\} </tex>, <tex> I = \\{2, 3, 5\\} </tex>.\r\n\r\nh3. Soluţie\r\n\r\nDacă între două noduri există muchie atunci nu pot fi amândouă în mulţimea <tex> I </tex>, iar dacă între două noduri nu există muchie nu pot fi amândouă în mulţimea <tex> C </tex>. \r\nTransformăm această problemă într-o instanţă de $2-SAT$ astfel: faptul că nodul <tex> x </tex> aparţine mulţimii <tex> C </tex> îl reprezentăm dândui lui <tex> x </tex> valoarea <tex> 1 </tex>, iar apartenenţa mulţimii <tex> I </tex> se codifică prin valoarea <tex> 0 </tex>. Acum existenţa unei muchii <tex> (x, y) </tex> corespunde expresiei <tex> x \\vee y </tex>, astfel cel puţin unul din nodurile <tex> x </tex> şi <tex> y </tex> nu va fi în mulţimea <tex> I </tex>. Dacă nu există muchia <tex> (x, y) </tex> putem scrie <tex> \\sim x \\vee \\sim y </tex>, această expresie va fi adevărată dacă cel puţin un nod din cele două nu va fi în mulţimea <tex> C </tex>.\r\nAceastă soluţie este liniară ca şi complexitate în numărul de elemente citite la intrare.\r\n\r\nh2(#peace-commission). Peace Commission (Polish Olympiad in Informatics, 2001)\r\n\r\nbq. Comisia Publică a Păcii trebuie să fie compusă în parlamentul Republicii Democrate a ţării Byteland după regulile impuse de Legea Foarte Importantă. Din păcate, unul dintre obstacole este acela că unii deputaţi nu se înţeleg cu ceilalţi. Comisia trebuie realizată astfel ca următoarele condiţii să fie îndeplinite: fiecare partid trebuie să aibă exact un reprezentant în comisie; dacă doi deputaţi nu se înţeleg, ei nu pot fi ambii membrii ai comisiei. Fiecare partid are exact doi deputaţi în parlament. Toţi număraţi de la $1$ până la $2n (1 <= n <= 8000)$. Deputaţii cu numerele $2i-1$ şi $2i$ aparţin celui de al $i$-lea partid. Se vor da $m (0 <= m <= 20 000)$ perechi de deputaţi <tex> (a, b) </tex> care nu se înţeleg. Se cere realizarea unei comisii dacă acest lucru este posibil. Un exemplu ar fi pentru trei partide şi perechile <tex> (1, 3) </tex> şi <tex> (2, 4) </tex> care nu se înţeleg comisia alcătuită din membrii <tex> \\{1, 4, 5\\} </tex>.\r\n\r\nh3. Soluţie\r\n\r\nFiecărui partid îi vom asocia o variabilă; variabila va lua valoarea <tex> 1 </tex> dacă membrul $2i - 1$ al partidului va aparţine comisiei şi valoarea <tex> 0 </tex> dacă membrul $2i$ va aparţine comisiei. Pentru ca din partidul $x$ să existe exact un membru în expresie introducem  <tex> A_{x} \\wedge \\sim A_{x} </tex>. \r\nPutem exprima că doi membrii ai parlamentului $(2i, 2j)$ nu se înţeleg prin expresia logică <tex> \\sim A_{i} \\vee \\sim A_{j} </tex>. Astfel nu pot ambele variabile <tex> A_{i} </tex> şi <tex> A_{j} </tex> să aibă în acelaşi timp valoarea <tex> 1 </tex> adică $2i$ şi $2j$ nu pot face parte în acelaşi timp din comisie. Dacă cei doi membrii sunt $(2i - 1, 2j - 1)$ atunci îi putem codifica prin expresia <tex> A_{i} \\vee A_{j} </tex> astfel <tex> A_{i} </tex> şi <tex> A_{j} </tex> nu pot avea în acelaşi timp valoarea <tex> 0 </tex>, iar dacă membrii sunt $(2i , 2j - 1)$ se poate scrie ca <tex> \\sim A_{i} \\vee A_{j} </tex> astfel <tex> A_{i} </tex> nu poate avea valoarea <tex> 1 </tex> când <tex> A_{j} </tex> are valoarea <tex> 0 </tex>.\r\nExemplul din problemă poate fi scris ca expresia logică în modul următor: <tex> A_{1} \\wedge \\sim A_{1} \\wedge A_{2} \\wedge \\sim A_{2} \\wedge A_{3} \\wedge \\sim A_{3} \\wedge (A_{1} \\vee A_{2}) \\wedge (\\sim A_{1} \\vee \\sim A_{2}) </tex>. \r\nDin nou vom putea folosi cel de al {\'patrulea algoritm\':2-sat#solutie4} explicat pentru a obţine o rezolvare de complexitate $O(N + M)$. \r\n\r\nh2(#orpath). Orpath (Olimpiadă Rusia)\r\n\r\nbq. Într-o ţară pacifistă, există $N$ oraşe şi $K$ autobuze $(1 <= N, K <= 100)$. La orele aglomerate ale zilei, nu trebuie să existe două autobuze care merg în acelaşi timp în sensuri opuse. Traseul fiecărui autobuz este un ciclu. Spunem că el merge în sens pozitiv dacă va parcurge oraşele în ordinea $1 2 3 4 1 2 3 4 1 2$ ... sau în sens negativ dacă le parcurge în ordinea $1 4 3 2 1 4 3 2 1 4$ ... Găsiţi o posibilitate de atribuire a sensului fiecărui autobuz astfel ca accidentele de trafic să fie evitate (nu vor exista două autobuze care să se întâlnească şi să aibă sensuri de mers opuse). Pentru fiecare autobuz se vor şti oraşele de pe ruta lui, şi pentru fiecare două oraşe vecine pe rută se va şti timpul necesar autobuzului pentru a ajunge dintr-un oraş în altul. De exemplu, pentru $4$ oraşe unde oricare două sunt la timp de mers egal cu $10$, şi pentru două autobuze cu rutele $1 2 4$ şi $3 4 2$, o soluţie ar fi ca primul autobuz să meargă în sens pozitiv iar celălalt în sens negativ.\r\n\r\nh3. Soluţie\r\n\r\nPentru orice două autobuze vom găsi care sunt sensurile de mers pentru ele astfel ca cele două autobuze să nu se întâlnească şi să provoace un accident. Pentru un sens fixat putem afla pentru un autobuz pe ce interval de timp va fi pe o anumită stradă. El va fi în general pe o stradă $(i, j)$ pe un interval de tipul $[t1 + k*T … t2 + k*T]$ unde $t1$ este timpul din prima rută parcursă pentru a ajunge la $i$, $t2$ timpul pentru a ajunge la $j$ iar $T$ este durata totală a unei rute. Acum, pentru a determina dacă două autobuze se vor întâlni pe o rută $(i, j)$ trebuie ca ele să se deplaseze în sensuri opuse pe această rută, iar intervalele lor $[t1 + k*T1 .. t2 + k*T1]$ se intersectează cu intervalele $[tt1 + p*T2 … tt2 + p*T2]$. Este clar acum că putem transforma problema într-o instanţă de $2-SAT$ prin maparea autobuzelor în variabile logice, a sensurilor de mers în valorile $adevărat$ şi $fals$, iar pentru orice pereche de autobuze să fie o propoziţie logică ce ia valoarea $adevărat$ doar dacă sensurile de mers determinate de variabilele logice asociate autobuzelor sunt compatibile. Mai trebuie determinat într-un mod eficient dacă două clase de intervale de timp se intersectează. Aceasta rămâne ca temă cititorului.\r\n\r\nh2(#aladdin). \'Aladdin\':problema/aladdin (Bursele Agora 2005/2006, Runda 1)\r\n\r\nbq. Aladdin, aşa cum ştiaţi, este un mare magnat în afacerea de comercializare a covoarelor magice. Acesta doreşte să o cucerească pe prinţesa Iasmina, iar aceasta, pentru a-i testa inteligenţa îl roagă să îi facă un covor dreptunghiular împărţit în pătrăţele, asemănator unei table de şah cu $N$ linii şi $M$ coloane $(1 <= N, M <= 1000)$. Fiecare pătrăţel de pe covor trebuie colorat cu alb sau cu negru. Pentru fiecare pătrat care conţine $4$ pătrăţele Iasmina pune condiţia să aibă un număr fixat de pătrăţele colorate cu negru. Ajutaţi-l pe Aladdin să realizeze un covor care satisface condiţiile impuse de prinţesa Iasmina!\r\n\r\nh3. Soluţie\r\n\r\nÎntâi, să considerăm un exemplu. Pentru o cerinţă de forma:\r\n\r\ntable{width: 90px; text-align: center}.\r\n| <tex> 3 </tex> | <tex> 2 </tex> | <tex> 3 </tex> |\r\n| <tex> 2 </tex> | <tex> 3 </tex> | <tex> 3 </tex> |\r\n| <tex> 1 </tex> | <tex> 2 </tex> | <tex> 1 </tex> |\r\n\r\nuna din soluţii este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nFie <tex> A </tex> o matrice soluţie a problemei noastre. Vom numerota rândurile matricii de la $0$ la $N - 1$ şi coloanele de la $0$ la $M - 1$. Matricea de intrare <tex> S </tex> reprezintă de fapt sumele din fiecare pătrat de câte $2 x 2$ elemente. Facem observaţia că dacă ştim într-un pătrat de $2 x 2$ valorile pentru trei dintre celule, atunci valoarea din a patra celulă este unic determinată pentru că ştim suma elementelor din pătrat. Vedem astfel, că dacă ştim valorile elementelor din prima linie a matricii <tex> A </tex> şi din prima coloană, restul valorilor sunt unic determinate. \r\nPentru a rezolva problema vom presupune <tex> A[0][0] </tex> cunoscut (de fapt, mai întâi vom rezolva problema presupunând că <tex> A[0][0] = 1 </tex>, iar dacă nu obţinem nicio soluţie vom încerca cu <tex> A[0][0] = 0 </tex>). Vom nota celulele <tex> A[0][1] </tex>, <tex> A[0][2]</tex>, … <tex> A[0][M - 1] </tex> cu <tex> x_{1} </tex>, <tex> x_{2} </tex>, … <tex> x_{M-1} </tex> iar celulele <tex> A[1][0] </tex>, <tex> A[2][0] </tex>, … <tex> A[N - 1][0] </tex> cu <tex> y_{1} </tex>, <tex> y_{2} </tex>, … <tex> y_{N-1} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> A[0][0] </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> ... </tex> | <tex> x_{M-1} </tex> |\r\n| <tex> y_{1} </tex> | <tex> 1 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n| <tex> y_{2} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 0 </tex> |\r\n| ... | ... | ... | ... | ... |\r\n| <tex> y_{N-1} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n\r\nAcum, pentru fiecare celulă putem demonstra prin inducţie că <tex> A[i][j] = (-1)^i x_{j} + (-1)^j y_{i} + b[i][j] </tex>. Unde <tex> b[i][j] </tex> sunt nişte constante ce sunt calculate în funcţie de matricea primită la intrare.\r\nEste uşor de observat că dacă:\r\n<tex> A[i-1][j] = (-1)^{(i-1)} x_{j} + (-1)^j y_{i-1} + b[i-1][j] </tex>, \r\n<tex> A[i-1][j-1] = (-1)^{(i-1)} x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i-1][j-1] </tex>, \r\n<tex> A[i][j-1] = (-1)^i x_{j-1} + (-1)^{(j-1)} y_{i} + b[i][j-1] </tex>, \r\n\r\natunci:\r\n\r\n<tex> A[i][j] = S[i-1][j-1] - A[i-1][j] - A[i][j-1] - A[i-1][j-1] = </tex> \r\n<tex> = S[i-1][j-1] - ((-1)^{(i-1)} x_{j} + (-1)^j y_{i-1} + b[i-1][j]) - </tex> <tex> ((-1)^{(i-1)} x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i-1][j-1]) - ((-1)^i x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i][j-1]) = </tex> \r\n<tex> = (-1)^i x_{j} - (-1)^j y_{i-1} + (-1)^i x_{j-1} + (-1)^j y_{i-1} - </tex> <tex> (-1)^i x_{j-1} + (-1)^j y_{i} + S[i-1][j-1] - b[i-1][j] - b[i][j-1] - b[i-1][j-1] = </tex> \r\n<tex> = (-1)^i x_{j} + (-1)^j y_{i} + b[i][j] </tex>. \r\n\r\nDe aici concluzionăm că <tex> b[i][j] = S[i-1][j-1] - b[i-1][j] - b[i][j-1] - b[i-1][j-1] \\ (*)</tex>.\r\n\r\nAvem un sistem format din inecuaţiile:\r\n\r\n<tex> 0 \\le x_{j} \\le 1 </tex>\r\n<tex> 0 \\le y_{i} \\le 1 </tex>\r\n<tex> -b[i][j] \\le (-1)^i x_{j} + (-1)^j y_{i} \\le 1 - b[i][j] </tex>\r\n\r\nEste uşor acum să transformăm acest sistem într-o formulă booleană în {\'formă normal conjunctivă\':2-sat#forme-normale} în care fiecare expresie are cel mult $2$ literali. Fiecare relaţie o putem înmulţi sau nu cu $-1$ astfel ca părţile constante ale relaţiei să fie pozitive. Observăm că <tex> | b[i][j] | \\le 2 </tex>, altfel nu avem soluţie. Dacă <tex> | b[i][j] | = 2 </tex> atunci ambele variabile au valori fixe, iar dacă <tex> | b[i][j] | = 1 </tex> sau <tex> | b[i][j] | = 0 </tex> atunci relaţia o putem scrie ca o disjuncţie logică cu doi literali.\r\n\r\nO relaţie precum <tex> 0 \\le x + y \\le 1 </tex> poate fi tansformată logic în <tex> \\sim x \\vee \\sim y </tex>, astfel <tex> x </tex> şi <tex> y </tex> nu vor fi în acelaşi timp <tex> 1 </tex>, una de genul <tex> 1 \\le x + y \\le 2 </tex> va fi transformată în <tex> (x \\vee y) </tex>, astfel cel puţin <tex> x </tex> sau <tex> y </tex> va fi egal cu <tex> 1 </tex>, alta de tipul <tex> 0 \\le x - y \\le 1 </tex> poate fi scrisă ca <tex> x \\vee \\sim y </tex>, una de tipul <tex> 2 \\le x + y \\le 3 </tex> în <tex> x \\wedge y </tex>, iar una de tipul <tex> 0 \\le -x -y \\le 1 </tex> în <tex> \\sim x \\wedge \\sim y </tex>, una de tipul <tex> 1 \\le x - y  \\le 2 </tex> în <tex> x \\wedge \\sim y </tex>.\r\n\r\nAstfel am redus problema la rezolvarea unei instanţe de $2-SAT$. Avem $N+M-1$ necunoscute şi {$(N-1)$}{$(M-1)$} propoziţii. Folosind a treia metodă de rezolvare vom obţine un algoritm de complexitate $O(N * M)$ care soluţionează problema noastră.\r\n\r\nSă vedem cum merge acestă rezolvare pe exemplul din problemă:\r\n\r\nAlegem <tex> A[0][0] = 1 </tex>. Necunoscutele vor fi <tex> x_{1} </tex>, <tex> x_{2} </tex>, <tex> x_{3} </tex> şi <tex> y_{1} </tex>, <tex> y_{2} </tex>, <tex> y_{3} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> x_{3} </tex> |\r\n| <tex> y_{1} </tex> | <tex> A[1][1] </tex> | <tex> A[1][2] </tex> | <tex> A[1][3] </tex> |\r\n| <tex> y_{2} </tex> | <tex> A[2][1] </tex> | <tex> A[2][2] </tex> | <tex> A[2][3] </tex> |\r\n| <tex> y_{3} </tex> | <tex> A[3][1] </tex> | <tex> A[3][2] </tex> | <tex> A[3][3] </tex> |\r\n\r\nFolosind recurenţa <tex> (*) </tex> obţinem că matricea <tex> b </tex> este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 2 </tex> | <tex> 0 </tex> | <tex> 3 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> -1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n\r\nDe aici obţinem sistemul de inegalităţi:\r\n\r\n<tex> 0 \\le x_{1} \\le 1,  0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le 1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, -2 \\le -x_{1} - y_{1} \\le -1, 0 \\le -x_{2} + y_{1} \\le 1, -3 \\le -x_{3} - y_{1} \\le -2, </tex>\r\n<tex> 0 \\le y_{2} \\le 1,  0 \\le  x_{1} - y_{2} \\le  1,-1 \\le  x_{2} + y_{2} \\le 0,  1 \\le  x_{3} - y_{2} \\le  2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, -1 \\le -x_{1} - y_{3} \\le  0, 0 \\le -x_{2} + y_{3} \\le 1, -1 \\le -x_{3} - y_{3} \\le  0 </tex>\r\n\r\nTransformăm relaţiile astfel ca să nu apară nici o constantă negativă:\r\n\r\n<tex> 0 \\le x_{1} \\le 1, 0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le  1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, 1 \\le x_{1} + y_{1} \\le 2, 0 \\le -x_{2} + y_{1} \\le 1, 2 \\le x_{3} + y_{1} \\le 3, </tex>\r\n<tex> 0 \\le y_{2} \\le 1, 0 \\le x_{1} - y_{2} \\le 1, 0 \\le -x_{2} - y_{2} \\le 1, 1 \\le x_{3} - y_{2} \\le 2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, 0 \\le x_{1} + y_{3} \\le 1, 0 \\le -x_{2} + y_{3} \\le 1, 0 \\le x_{3} + y_{3} \\le 1 </tex>\r\n\r\nAcest sistem poate fi transformat într-o expresie booleană:\r\n\r\n<tex> (x_{1} \\vee y_{1}) \\wedge (\\sim x_{2} \\vee y_{1}) \\wedge (x_{3} \\wedge y_{1}) \\wedge </tex>\r\n<tex> (x_{1} \\vee \\sim y_{2}) \\wedge (\\sim x_{2} \\wedge \\sim y_{2}) \\wedge (x_{3} \\wedge \\sim y_{2}) \\wedge </tex>\r\n<tex> (\\sim x_{1} \\vee \\sim y_{3}) \\wedge (\\sim x_{2} \\vee y_{3}) \\wedge (\\sim x_{3} \\vee \\sim y_{3}) </tex>.\r\n\r\nAcestă expresie e satisfăcută de valorile: <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 1, y_{1} = 1, y_{2} = 0, y_{3} = 0 \\rangle </tex>, iar de aici putem determina o soluţie a problemei noastre iniţiale ca fiind:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nh2(#bibliografie). Bibliografie:\r\n\r\n* [1] T. H. Cormen, C. E. Leiserson, R. R. Rivest - \'_Introducere in Algoritmi_\':http://zhuzeyuan.hp.infoseek.co.jp/ita/toc.htm\r\n* [2] \'_Satisfiability_\':http://en.wikipedia.org/wiki/Satisfiability, Wikipedia\r\n* [3] \'_BOI 2001 Competition Material_\':http://www.oi.edu.pl/download/boi-2001.pdf\r\n* [4] \'_CEOI 2002 Competition Material_\':http://ics.upjs.sk/ceoi/Documents.html',3146,'public',NULL,NULL),('utilizator/motty','Welcome to the Hall of Fame - motty','2008-10-24 09:08:52','2008-12-12 10:08:26','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n* _Elev al Colegiului National de Informatica \"Tudor Vianu\"_\r\n* _In God we trust!_\r\n* _Anything is posible if you just belive!_\r\n\r\nh2. Distinctii primite\r\nh3. Prieteni pe infoarena\r\n\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"rapidu36\" type=\"tiny\")==\r\n* ==user(user=\"cosmin79\" type=\"tiny\")==\r\n* ==user(user=\"ira\" type=\"tiny\")==\r\n* ==user(user=\"drag0s93\" type=\"tiny\")==\r\n* ==user(user=\"ooctav\" type=\"tiny\")==',8690,'public',NULL,NULL),('planificare/sedinta-20090112','Sedinta 2009-01-12','2009-01-05 15:03:20','2009-01-09 16:42:06','h1. Sedinta 2009-01-12\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe întâlnim *luni, 12 ianuarie* la ora *18^00^* la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932.)\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== - pe seara as prefera\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")== - ar fi mai bine mai spre 16:00 si nu la retro cafe\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== - as prefera dupa 18:30\r\n* ==user(user=\"prostu\" type=\"tiny\")== - as prefera dupa 16:00\r\n* ==user(user=\"stef2n\" type=\"tiny\")== - prezent doar daca nu are loc in intervalul 18-20, din cauza unei lucrari\r\n* ==user(user=\"gcosmin\" type=\"tiny\")== - ar merge mai spre seara (dupa 6:30-7:00 asa)\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinta anterioara\':planificare/sedinta-20081125| ==user(user=\"domino\" type=\"tiny\")==|\r\n| Algoritmiada (sponsorizari)| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n| OKR-uri (Q4 2008 si Q1 2009)|  ==user(user=\"domino\" type=\"tiny\")== |\r\n| Coding camp |  ==user(user=\"domino\" type=\"tiny\")== |\r\n| \'IAP 11\':propuneri/11-rating | ==user(user=\"bogdan2412\" type=\"tiny\")== |\r\n| \'IAP 10\':propuneri/10-virtual-contest | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Stelele |  ==user(user=\"silviug\" type=\"tiny\")== |\r\n| ONIbyNET si sistem de submit | ==user(user=\"domino\" type=\"tiny\")== |\r\n| Fix it week/camp | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| Misc | ==user(user=\"silviug\" type=\"tiny\")== |\r\n\r\nh3. Detalii\r\n\r\n* Stelele:\r\n** Go international: desi la stadiul de idee, Ali se gandeste sa invite bulgarii cei mai tari la stele; ce-ar presupune asta din partea noastra?\r\n** Va avea loc in vacanta inter-semestriala (perioada 31 ianuarie - 7 februarie)\r\n** Masuri de securitate, probleme cu adminii (Bogdan are parola pe live) \r\n* Fix it week/camp:\r\n** Scop: imbogatirea si imbunatatirea continutului site-ului, implicarea comunitatii in activitatile noastre, identificarea de noi colaboratori \"de baza\"\r\n** Fix it week: declararea unei saptamani in care toata comunitatea trage tare pentru content; cel mai simplu exemplu sunt articole de transcris; putem include si task-uri mai specializate ca finalizarea de probleme in arhiva [educationala]?, documentatie pentru diverse parti din site, etc.\r\n** Fix it camp: in paralel sau ca alternativa la fix it week; membrii infoarena se imbraca in salopete cu harlete in spate si se aduna intr-un loc prestabilit; chemam membrii comunitatii care vor sa se implice si \"plantam\" articole, documentatie, etc. o zi sau un week-end intr-o locatie precum ICHB. \r\n** In sedinta aceasta as dori sa primesc feedback si sugestii noi despre:\r\n*** Forma acestui eveniment: week or/and camp or/and ??\r\n*** Ce putem realiza cu un astfel de eveniment? (in materie de continut si implicare a comunitatii; care din scopuri sunt SF?)\r\n*** Ma ofer (Silviu) eu sa organizez evenimentul in Q1-09, intr-o forma in care cadem cu totii de acord. \r\n* Misc:\r\n** Silviu: De ce nu avem (inca) comentarii la articole? Mai sunt alte pagini la care am vrea comentarii (in stil de blog)?\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n...\r\n\r\nh2. Notite\r\n\r\n...',13,'public',NULL,NULL),('planificare/sedinta-20090112','Sedinta 2009-01-12','2009-01-05 15:03:20','2009-01-12 14:37:41','h1. Sedinta 2009-01-12\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe întâlnim *luni, 12 ianuarie* la ora *18^00^* la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== - pe seara as prefera\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")== - ar fi mai bine mai spre 16:00 si nu la retro cafe\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== - as prefera dupa 18:30\r\n* ==user(user=\"prostu\" type=\"tiny\")== - as prefera dupa 16:00\r\n* ==user(user=\"stef2n\" type=\"tiny\")== - prezent doar daca nu are loc in intervalul 18-20, din cauza unei lucrari\r\n* ==user(user=\"gcosmin\" type=\"tiny\")== - ar merge mai spre seara (dupa 6:30-7:00 asa)\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinta anterioara\':planificare/sedinta-20081125| ==user(user=\"domino\" type=\"tiny\")==|\r\n| Algoritmiada (sponsorizari)| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n| OKR-uri (Q4 2008 si Q1 2009)|  ==user(user=\"domino\" type=\"tiny\")== |\r\n| Coding camp |  ==user(user=\"domino\" type=\"tiny\")== |\r\n| \'IAP 11\':propuneri/11-rating | ==user(user=\"bogdan2412\" type=\"tiny\")== |\r\n| \'IAP 10\':propuneri/10-virtual-contest | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Stelele |  ==user(user=\"silviug\" type=\"tiny\")== |\r\n| ONIbyNET si sistem de submit | ==user(user=\"domino\" type=\"tiny\")== |\r\n| Fix it week/camp | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| CCS pe viitor? | ==user(user=\"wickedman\" type=\"tiny\")== |\r\n| Misc | ==user(user=\"silviug\" type=\"tiny\")== |\r\n\r\nh3. Detalii\r\n\r\n* Stelele:\r\n** Go international: desi la stadiul de idee, Ali se gandeste sa invite bulgarii cei mai tari la stele; ce-ar presupune asta din partea noastra?\r\n** Va avea loc in vacanta inter-semestriala (perioada 31 ianuarie - 7 februarie)\r\n** Masuri de securitate, probleme cu adminii (Bogdan are parola pe live) \r\n* Fix it week/camp:\r\n** Scop: imbogatirea si imbunatatirea continutului site-ului, implicarea comunitatii in activitatile noastre, identificarea de noi colaboratori \"de baza\"\r\n** Fix it week: declararea unei saptamani in care toata comunitatea trage tare pentru content; cel mai simplu exemplu sunt articole de transcris; putem include si task-uri mai specializate ca finalizarea de probleme in arhiva [educationala]?, documentatie pentru diverse parti din site, etc.\r\n** Fix it camp: in paralel sau ca alternativa la fix it week; membrii infoarena se imbraca in salopete cu harlete in spate si se aduna intr-un loc prestabilit; chemam membrii comunitatii care vor sa se implice si \"plantam\" articole, documentatie, etc. o zi sau un week-end intr-o locatie precum ICHB. \r\n** In sedinta aceasta as dori sa primesc feedback si sugestii noi despre:\r\n*** Forma acestui eveniment: week or/and camp or/and ??\r\n*** Ce putem realiza cu un astfel de eveniment? (in materie de continut si implicare a comunitatii; care din scopuri sunt SF?)\r\n*** Ma ofer (Silviu) eu sa organizez evenimentul in Q1-09, intr-o forma in care cadem cu totii de acord. \r\n* Misc:\r\n** Silviu: De ce nu avem (inca) comentarii la articole? Mai sunt alte pagini la care am vrea comentarii (in stil de blog)?\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n...\r\n\r\nh2. Notite\r\n\r\n...',13,'public',NULL,NULL),('propuneri','Propuneri infoarena','2007-11-07 01:42:16','2008-12-12 20:31:06','h1. Propuneri infoarena\r\n\r\nAceasta pagina centralizeaza toate documentele IAP (infoarena Proposal).\r\n\r\nUn IAP (infoarena Proposal) este un document care propune \'Asociatiei infoarena\':asociatia-infoarena sa adopte un proiect semnificativ sau sa creeze / modifice politici si procese.\r\n\r\nMai multe informatii despre sistemul IAP gasesti chiar in \'IAP #0\':propuneri/0-sistemul-iap ;)\r\n\r\nh2. Cum fac o noua propunere?\r\n\r\n*Trebuie sa ceri un numar IAP* de la un \'consilier infoarena\':echipa-infoarena. Explica in mare ideea ta si, daca acel consilier este de acord, vei primi un numar IAP si permsiunea sa-l scrii. In general, consilierii infoarena sunt deschisi la aproape orice idee bine argumentata.\r\n\r\nNu poti crea un IAP fara acordul unui consilier infoarena!\r\n\r\nh2.  Registrul IAP\r\n\r\n*Atentie!* Doar o parte din propunerile de mai jos au fost aprobate! Orice IAP ramane in registru, chiar si daca este respins.\r\n\r\nDeschide fiecare IAP in parte pentru a afla verdictul sau starea in care se afla.\r\n\r\n|_. IAP # |_. Titlu                                                       |_. Autor(i) |_. Stare |\r\n| 0&nbsp; | \'Sistemul IAP (infoarena proposals)\':propuneri/0-sistemul-iap | ==User(type=\"tiny\" user=\"wickedman\")== | *Aprobat* |\r\n| 1       | \'Concurs \"hackaton\"\':propuneri/1-hackaton                     | ==User(type=\"tiny\" user=\"wickedman\")==  \r\n==User(type=\"tiny\" user=\"silviug\")== | In constructie |\r\n| 2       | \'Concurs de informatica pentru studenti\':propuneri/2-concurs-studenti | ==User(type=\"tiny\" user=\"wickedman\")== \r\n==User(type=\"tiny\" user=\"silviug\")== | In constructie  |\r\n| 3       | \'Infoarena 3.0\':propuneri/3-infoarena3 | ==User(type=\"tiny\" user=\"fluffy\")== | In dezbatere |\r\n| 4       | \'Restructurare forum\':propuneri/4-forum | ==User(user=\"wefgef\" type=\"tiny\")== | *Respins* |\r\n| 5       | \'Open surse\':propuneri/5-open-surse | ==User(user=\"domino\" type=\"tiny\")== | *Aprobat* |\r\n| 6       | \'Arhiva educationala\':propuneri/6-arhiva-educationala | ==User(user=\"domino\" type=\"tiny\")== | *Aprobat* |\r\n| 7       | \'Community Ladder\':propuneri/7-community-ladder | ==User(user=\"wickedman\" type=\"tiny\")== | In constructie |\r\n| 8       | \'\"Almanah\" infoarena\':propuneri/8-almanah | ==User(user=\"wickedman\" type=\"tiny\")== | In constructie |\r\n| 9       | \'OKR\':propuneri/9-okr | ==User(user=\"domino\" type=\"tiny\")== | *Aprobat* |\r\n| 10       | \'Virtual Contests\':propuneri/10-virtual-contest | ==User(user=\"gcosmin\" type=\"tiny\")== | In constructie |\r\n| 11       | \'Revizuirea functionalitatii ratingului\':propuneri/11-rating | ==User(user=\"bogdan2412\" type=\"tiny\")== | In constructie |\r\n',1490,'public',NULL,NULL),('propuneri/10-virtual-contest','IAP #10: Virtual Contest','2008-10-21 17:33:19','2009-01-12 11:18:41','h1. IAP #10: Virtual contest\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2008-10-21 |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"gcosmin\")== |\r\n|_. Stare     | *IN CONSTRUCTIE* |\r\n\r\nh2(#abstract). Abstract\r\n\r\nSe propune crearea unui sistem prin care orice membru infoarena isi poate crea propriul concurs cu probleme alese din arhiva.\r\n\r\nh2(#motivatie). Motivatie\r\n\r\nCum arhiva de probleme devine din ce in ce mai mare si mai diversificata, crearea unui concurs cu probleme necunoscute de catre un anumit grup de oameni este mai usoara. \r\nAceasta optiune ar avea un mare impact in pregatirea concurentilor in regim de concurs :\r\n\r\n* pe plan individual : prin auto-testare\r\n* pe plan de grup : in acest caz avem posibilitati multiple \r\n** cativa membrii ai comunitatii decid sa isi masoare \"fortele\" intre ei\r\n** la un concurs creat de un concurent cu scopuri individuale, se strang mai multi oameni dornici de participare si pregatire\r\n** un profesor decide sa isi supuna elevii unei testari folosind aceasta optiune de pe infoarena\r\n\r\nDe asemenea un concurent ce a ratat un concurs infoarena il poate simula pentru a-si compara rezultate cu ceilalti participanti.\r\nAvantajele sunt evidente mai ales ca avem exemplul unor site-uri acm cu functii asemanatoare : sgu, tju, etc.\r\n\r\nh2(#implementare). Implementare\r\n\r\nEste nevoie de un sistem usor de folosit, intuitiv care sa atraga comunitatea spre aceasta noua modalitate de pregatire.\r\n\r\nOrice concurs va avea urmatorii parametrii, pe care creatorul concursului are dreptul sa ii aleaga dupa bunul plac :\r\n\r\n# Numele rundei\r\n# Data si ora inceperii\r\n# Durata\r\n# Problemele (acestea vor putea fi selectate din arhiva de probleme in orice numar si oricare)\r\n# Starea evaluatorului, daca acesta este oprit sau pornit\r\n# Un clasament propriu ce se creaza in functie de optiunea de mai sus la sfarsitul sau in timpul rundei\r\n\r\nPagina destinata concursurilor virtuale va contine doua lucruri esentiale :\r\n\r\n# O lista cu toate concursurile programate, sortate dupa data si ora inceperii. Un concurent trebuie doar sa caute concursul dorit in aceasta lista, sa il selecteze si va fi directionat catre pagina concursului unde poate vedea problemele, clasamentul sau poate trimite solutii (similar oricarui concurs normal). In caz ca respectivul concurs nu a inceput inca va fi anuntat :)\r\n# Optiunea \"Creaza concurs\" ce va directiona utilizatorul catre o pagina destinata creari unui concurs. Aici stabilteste toti parametrii descrisi mai sus, dupa dorintele proprii. El poate modifica apoi acesti parametrii oricand.\r\n\r\nh2(#Alte mentionar). Alte mentionari\r\n\r\n* Nu exista optiunea ca aceste concursuri sa conteze pentru rating.\r\n* Nu se va crea topic special pentru ele in forum si nici nu vor fi anuntate in calendarul infoarena al concursurilor. O posibilitate ar fi crearea unui calendar specific concursurilor virtuale dar aceast \"feature\" ramane pentru a fi discutat.\r\n* Concurentii vor putea \"trisa\" la aceste concursuri trimitand sursele deja implementate la problemele din concurs. Nu se poate face nimic in acest sens dar nu conteaza, concursurile virtuale fiind doar pentru pregatirea celor binevoitori si dornici :)\r\n* Concursurile ce s-au terminat de mai mult de doua saptamanani vor fi sterse automat din baza de date (nu are nici un rost sa fie tinute prea mult)\r\n\r\nh2(#feedback). Feedback\r\n\r\nIntra pe \'forum\':forum/index.php?topic=3313.0 pentru a da feedback.',2044,'public',NULL,NULL),('trie-forest-based-sort','trie-forest-based-sort','2009-01-12 18:52:31','2009-01-12 22:23:54','h1. Sorting Big Numbers using Trie-Forest based sort\r\n\r\nh2. authors : Serban Lupulescu and Mircea Dima\r\n\r\n \r\n\r\nh3. The first idea is that if you have a string of length h, you can insert it in a trie of height h. We could maintain a list of tries,\r\n\r\nh3. trie H[N], where H[i] is a trie with height i so when we insert a string with lenght i, we insert it in H[i].\r\n\r\nh3. But what happens when we have, say 2 strings, one of length 3, and one with length 10^20^? We can\'t declare H[10^20^].\r\n\r\nh3. Instead we can keep an optimal binary search tree, where the keys are the length of the trie, and the additional information is the\r\n\r\nh3. trie itself.\r\n\r\nh3. Now if we have a string with length h we have 2 possibilities:\r\n\r\nh3. 1) if there is a trie with height h in the binary search tree, we insert the string in that trie\r\n\r\nh3. 2) if there isn\'t a trie with height h in the binary search tree, we create it, we insert the string in an empty trie, and then we insert the trie in\r\n\r\nh3. the binary search tree.\r\n\r\n\r\n== code(c) |\r\n\r\n// Sorting Big Numbers using Trie-Forest based sort indexed in a STL set (Red-Black Tree)\r\n// copyright(c)   idea :          Serban Lupulescu\r\n//             implementation: Mircea Dima\r\n// Time Complexity: O(n*max_len)\r\n// Faculty of Mathematics and Computer Science, University of Bucharest\r\n// :D\r\n#include <cstdio>\r\n#include <string>\r\n#include <set>\r\n#include <vector>\r\n#define N 10024\r\n\r\nusing namespace std;\r\n\r\ninline int length(char a[])\r\n{\r\n      int n=0;\r\n      while(a[n] >= \'0\' && a[n] <= \'9\') ++n;\r\n      return n;\r\n}\r\n\r\nstruct nod { int nr; nod *next[10];};\r\n\r\ntypedef nod* trie;\r\n\r\ninline void init(trie &n)\r\n{\r\n      n=new nod;\r\n      n->nr=0;\r\n      memset(n->next, 0, sizeof(n->next));\r\n}\r\n\r\nstruct cmp{\r\n      bool operator()(const pair<int, trie> &a, const pair<int, trie> &b)const\r\n      {\r\n            if(a.first < b.first) return 1;\r\n            return 0;\r\n      }\r\n};\r\n\r\ntypedef set<pair<int, trie> , cmp > Tree;\r\ntypedef set<pair<int, trie> , cmp >:: iterator Tree_it;\r\n\r\n \r\n\r\nTree R; // Red-Black binary search tree with key values = pointers\r\n\r\ninline trie find(int len) // find a trie in RBTREE\r\n{\r\n      Tree_it i= R.find(make_pair(len, (trie)0));\r\n      if(i == R.end()) return (trie) 0;\r\n      return i->second;\r\n}\r\n\r\ninline void insert(trie t, int len)\r\n{\r\n      R.insert(make_pair(len, t));\r\n}\r\n\r\ninline void erase(trie t, int len)\r\n{\r\n      R.erase(make_pair(len, t));\r\n}\r\n\r\ninline void insert(trie T,char a[], int n)\r\n{\r\n      for(int i=0; i < n; ++i)\r\n      {\r\n            if(T->next[a[i]] == 0)\r\n            //if I don\'t have an edge, I creat it\r\n            {\r\n                  T->next[a[i]]=new nod;\r\n                  T->next[a[i]]->nr=0;\r\n                  memset(T->next[a[i]]->next, 0, sizeof(T->next));\r\n            }\r\n            T=T->next[a[i]]; // go down the edge\r\n      }          \r\n      ++T->nr;\r\n}\r\n\r\nchar sol[N];\r\n\r\ninline void afis(trie T, int n)\r\n{\r\n      for(int i=0; i < 10; ++i)\r\n            if(T->next[i])\r\n            {\r\n                  sol[n]=i;\r\n                 \r\n                  if(T->next[i]->nr)//has a number ended?\r\n                  {\r\n                        for(int j=1; j <= T->next[i]->nr; ++j)\r\n                        {\r\n                              int k;\r\n                              for(k=0; k <= n && sol[k] == 0; ++k);\r\n                             \r\n                              for(; k <= n; ++k) printf(\"%d\", sol[k]);\r\n                              printf(\"\\n\");\r\n                        }\r\n                  }    \r\n                  afis(T->next[i], n+1);\r\n            }\r\n}\r\n\r\nvoid read()\r\n{\r\n      freopen(\"sort.in\",\"r\",stdin);\r\n      freopen(\"sort.out\",\"w\",stdout);\r\n      while(!feof(stdin))\r\n      {\r\n            char a[N];\r\n            memset(a, 0, sizeof(a));\r\n            gets(a);\r\n            int n=length(a);\r\n            for(int i=0; i < n; ++i) a[i]-=\'0\';\r\n            trie t=find(n);\r\n           \r\n            if(t == 0)\r\n            {\r\n                  t= new nod;\r\n                  init(t);\r\n                  insert(t, n);\r\n            }\r\n           \r\n            insert(t, a, n);\r\n      }\r\n     \r\n      for(Tree_it i = R.begin(); i != R.end(); ++i) afis(i->second, 0);\r\n           \r\n}\r\n\r\nint main()\r\n{\r\n      read();    \r\n      return 0;\r\n}\r\n==',1204,'public',NULL,NULL),('numerele-sprague-grundy','Teoria jocurilor: numerele Sprague Grundy','2008-11-18 17:10:41','2009-01-14 07:04:03','h1. Teoria jocurilor: numerele Sprague Grundy\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"portocala\") ==\r\n\r\n(Categoria _Matematică_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 28em}*{text-align:center;} *Conţinut*\r\n* \'Introducere\':numerele-sprague-grundy#introducere\r\n* \'Ce este jocul NIM?\':numerele-sprague-grundy#jocul-nim\r\n* \'Aplicaţii ale strategiei NIM\':numerele-sprague-grundy#aplicatii-nim\r\n* \'Numerele Sprague Grundy\':numerele-sprague-grundy#sprague-grundy\r\n* \'Aplicaţii ale numerelor Sprague Grundy\':numerele-sprague-grundy#aplicatii-sg\r\n* \'Concluzii\':numerele-sprague-grundy#concluzii\r\n* \'Probleme suplimentare\':numerele-sprague-grundy#probleme-suplimentare\r\n* \'Bibliografie\':numerele-sprague-grundy#bibliografie\r\n\r\nh2(#introducere). Introducere\r\n\r\nDomeniu relativ nou şi încă necercetat în adâncime, $teoria jocurilor$ este o ramură a matematicii în care de multe ori primează inventivitatea şi nu cunoştinţele. Tocmai din acest motiv, în cadrul acestui articol vom introduce câteva noţiuni teoretice care ne vor ajuta în rezolvarea unor probleme din teoria jocurilor. Ingeniozitatea celor pasionaţi poate fi testată prin introducerea unor probleme de teoria jocurilor la concursurile de matematică şi informatică. Deoarece în România teoria jocurilor nu este studiată în şcoli, problemele din acest domeniu pot pune în dificultate concurenţii.\r\n\r\nh2(#jocul-nim). Ce este jocul NIM?\r\n\r\nPentru început ne vom familiariza cu jocul clasic $NIM$:\r\n\r\nbq. Se consideră $N$ grămezi de pietre. Doi jucători, vor ridica alternativ oricâte pietre dintr-o singură grămadă. Câştigătorul este cel care ia ultima piatră.\r\n\r\nÎn rezolvare distingem mai multe cazuri:\r\n\r\n* Pentru cazul trivial în care numărul de grămezi este egal cu $1$, primul jucător are, evident, strategie de câştig, el putând lua toate pietrele din grămadă.\r\n* Dacă numărul de grămezi este egal cu $2$, primul jucător are strategie de câştig atunci când numărul de pietre din prima grămadă este diferit de numărul de pietre din cea de-a doua, strategia lui fiind cea de a aduce tot timpul grămada mai mare la numărul de pietre al grămezii mai mici, şi cum jocul este finit, înseamnă că primul jucător o să aducă jocul în starea $(0, 0)$.\r\n* Dacă numărul de grămezi este mai mare decât doi, strategia se complică şi nu se mai observă cu \"ochiul liber\". Stările câştigătoare pentru mai multe grămezi sunt acele stări pentru care suma $XOR$ a numerelor de pietre din grămezi este diferită de $0$, restul stărilor fiind de pierdere.\r\n\r\nDe exemplu, dacă avem $4$ grămezi cu $1$, $3$, $5$ respectiv $7$ pietre:\r\n\r\n* $*O*$\r\n* $*OOO*$\r\n* $*OOOOO*$\r\n* $*OOOOOOO*$\r\n\r\nAtunci vom avea:\r\n\r\n* $*1 = (0001){~2~}*$\r\n* $*3 = (0011){~2~}*$\r\n* $*5 = (0101){~2~}*$\r\n* $*7 = (0111){~2~}*$\r\n\r\nEfectuând \'$XOR$\':http://www.fredosaurus.com/notes-cpp/expressions/bitops.html (operatorul $^$ în $C/C++$) între reprezentările binare ale numerelor  obţinem $*0 = (0000){~2~}*$. Conform propoziţiei de mai sus această stare este de pierdere.\r\n\r\nSă demonstrăm cele afirmate. Dintr-o poziţie cu suma $XOR$ egală cu $*0*$, pentru orice mutare ajungem evident la o poziţie cu suma $XOR$ diferită de $*0*$, pentru că luând dintr-o grămadă un număr $x$ de pietre, în suma $XOR$ corespunzătoare noii stări bitul cel mai semnificativ al lui $x$ va avea valoarea $*1*$.\r\n\r\nMai rămâne de demonstrat că din orice poziţie cu suma $XOR$ diferită de $*0*$ putem trece printr-o mutare convenabilă într-o poziţie cu suma $XOR$ egală cu $*0*$. Căutăm o grămadă care are un număr de pietre mai mare sau egal cu cea mai mare putere a lui $2$ care apare în suma $XOR$. Fie $x$ valoarea sumei $XOR$ a tuturor grămezilor şi $y$ numărul de pietre din grămada găsită mai devreme. O mutare \"câştigătoare\" este extragerea din grămada găsită care are $y$ pietre a {$y - (x XOR y)$} pietre ({$x XOR y$} este mai mic decât $y$ pentru că se anulează biţii cei mai semnificativi ai lui $y$ şi $x$). Atunci noua sumă $XOR$ va fi egală cu $*0*$.\r\n\r\nDe exemplu:\r\n\r\n* $*4{@ ^ 8 ^ @}17 = (00100){~2~}{@ ^ @}(01000){~2~}{@ ^ @}(10001){~2~} = (11101){~2~} = 29*$.\r\n\r\nMutarea câştigătoare constă în a lua din cea de-a treia gramadă un număr de pietre egal cu:\r\n\r\n* $*17 - (17 @^ 29) = 17 - 17 ^@ 29 = 5 = (00101){~2~}*$.\r\n\r\nDupă acest pas grămezile vor avea $4$, $8$, $12$ pietre. Ne aflăm astfel într-o stare cu suma $XOR$ egală cu $*0*$.\r\n\r\nh2(#aplicatii-nim). Aplicaţii ale strategiei NIM\r\n\r\nExemplificăm în continuare câteva probleme în care se foloseşte strategia jocului $NIM$.\r\n\r\nh3(#problema-1). Problema 1\r\n\r\nbq. Pe o tablă de şah, care are $N x M$ căsuţe, sunt plasaţi pe prima linie $N$ pioni albi şi pe ultima linie $N$ pioni negri. Fiecare dintre cei doi jucători poate muta un singur pion, care îi aparţine, un număr strict pozitiv de căsuţe în sus sau în jos, astfel încât să nu ajungă vreun pion alb să fie mai jos decât pionul negru de pe aceeaşi coloană. Pierde jucătorul care nu mai poate muta.\r\n\r\nh3. Soluţie\r\n\r\nAceastă problemă este o deghizare a jocului $NIM$, numărul de pătrăţele libere între pionul alb şi pionul negru de pe coloana $i$ putând fi considerat numărul de pietre din grămada $i$. Singura diferenţă este că se pot adăuga pietre la grămadă (existând posibilitatea mutării înapoi). Această problemă se rezolvă uşor, jucătorul care are strategie de câştig putând evita asemenea mutări. O astfel de mutare poate fi utilă numai pentru jucătorul care este într-o poziţie de pierdere. Când jucătorul care nu are strategie de câştig mută înapoi $x$ căsuţe, celălalt jucător va muta pionul propriu de pe aceeaşi coloanã cu $x$ căsuţe în faţă, astfel ajungându-se la aceeaşi stare cu cea existentă cu două mutări anterior (considerând diferenţa poziţiilor).\r\n\r\nh3(#problema-2). Problema 2 (Baraj, ONI 1997)\r\n\r\nbq. Pe o linie sunt plasate la coordonate întregi $2 x N$ piese roşii şi albastre. Fiecare piesă roşie poate fi mutată în dreapta oricâte poziţii astfel încât să nu sară peste o piesă albastră, iar piesele albastre pot fi mutate oricâte poziţii la stânga astfel încât să nu depăşească vreo piesă roşie. Piesele vor alterna: roşu, albastru, roşu, albastru etc. Pierde jucătorul care nu mai poate muta.\r\n\r\nh3. Soluţie\r\n\r\nAceastă problemă poate fi, de asemenea, redusă la jocul $NIM$. Diferenţele poziţiilor perechilor de piese roşii şi albastre consecutive constituie numărul de pietre al grămezilor din jocul $NIM$.\r\n\r\nh3(#problema-3). Problema 3 (\'Nim Game - Give Away!\':http://acm.mipt.ru/judge/problems.pl?problem=103&CGISESSID=b4a5b84bd176d84796a209dc7c8002b8, El Judge)\r\n\r\nbq. Se consideră $N$ grămezi de pietre, jucătorii mută alternativ, fiecare jucător extrăgând oricâte pietre dintr-o singură grămadă. Cel care ia ultima piatră pierde jocul.\r\n\r\nh3. Soluţie\r\n\r\nStrategia acestui joc este similară cu cea aplicată în jocul $NIM$ cu câteva mici diferenţe. Jucătorul care are strategie de câştig în poziţia curentă în cadrul jocului $NIM$ face aceeaşi mutare pe care ar face-o în cazul jocului $NIM$, exceptând cazul în care această mutare lasă doar grămezi cu o singură piatră şi numărul acestor grămezi este par. În această situaţie, dacă ar trebui să ia $x$ pietre, jucătorul poate lua $x - 1$ pietre din grămada actuală, pentru ca numărul de grămezi să fie impar şi el să facă ultima mutare.\r\n\r\nh2(#sprague-grundy). Numerele Sprague Grundy\r\n\r\nJocurile care prezintă interes pentru jucători sunt acelea care necesită examinarea unui număr foarte mare de stări pentru determinarea strategiei de câştig, deoarece în caz contrar câştigătorul s-ar cunoaşte chiar de la început. Spre deosebire de aceştia, matematicienii sau informaticienii sunt interesaţi de determinarea unor strategii pentru astfel de jocuri. Toate jocurile imparţiale cu doi jucători cu informaţie totală pot fi reduse la jocul *$NIM$* care se joacă cu nişte grămezi virtuale, în care mutările posibile sunt extragerea oricâtor pietre dintr-o grămadă sau adăugarea oricâtor pietre la o grămadă (aşa cum am menţionat anterior, adăugarea de pietre la o grămadă nu complică analiza jocului).\r\n\r\nAfirmaţia anterioară constituie un rezultat al _Teoriei Sprague-Grundy_. _Roland Percival Sprague_ (1936) şi _Patrick Michael Grundy_ (1939) sunt doi matematicieni care s-au ocupat, independent, de teoria jocurilor imparţiale.\r\n\r\nÎn continuare, considerăm următorul enunţ:\r\n\r\nbq. Se consideră un graf aciclic care conţine în noduri câţiva pioni, jucătorii alternează la mutare şi fiecare poate muta câte un pion pe un arc care iese din nodul în care este situat pionul. Pierde jucătorul care nu poate muta.\r\n\r\nÎntrucât graful este aciclic, jocul este finit şi are întotdeauna un câştigător. Practic, acest joc este suma unor jocuri, mai precis suma a mai multor jocuri cu un singur pion pe graful aciclic. Jocul cu un singur pion poate fi analizat destul de uşor, fiecare nod al grafului putând fi colorat cu alb sau negru după cum există sau nu strategie de câştig dacă în nodul curent ar fi poziţionat pionul. Această colorare poate fi realizată uşor dacă se porneşte de la nodurile fără urmaş şi la fiecare pas se colorează câte un nod ai cărui urmaşi sunt deja coloraţi. Orice joc imparţial poate fi redus la un joc cu un singur pion. Nodurile sunt poziţiile jocului şi arcele grafului sunt mutările posibile din fiecare poziţie. Jocul iniţial poate fi şi el transformat, dar numărul de noduri creşte foarte mult (pentru $N$ pioni şi $M$ noduri, numărul de noduri din jocul transformat este {$N^M^$}) şi nu este practic să colorăm graful rezultat. Folosind teoria dezvoltată de Sprague şi Grundy, putem reduce complexitatea analizei jocului cu $N$ pioni la complexitatea analizei jocului cu un pion.\r\n\r\nVom introduce funcţia *$mex$* cu semnificaţia: $mex(S)$ este elementul minimal natural care nu aparţine mulţimii $S$. Pentru fiecare nod $x$ al grafului aciclic considerat, vom calcula valoarea funcţiei $gx = mex(gx{~1~}, gx{~2~}, …, gx{~k~})$, unde $x{~1~}$, $x{~2~}$, …, $x{~k~}$ sunt urmaşii nodului $x$ în graf. Pentru nodurile fără urmaşi $gx = 0$.\r\n\r\nAnalog jocului cu un singur pion, graful poate fi etichetat din aproape în aproape, pornind de la nodurile fără urmaşi. Observăm că, dacă $gx = 0$ în jocul cu un singur pion situat în nodul $x$ nu avem strategie de câştig, iar dacă $gx$ este diferit de $0$ avem strategie de câştig. Restul informaţiei ne ajută la determinarea unei strategii pentru jocul cu $N$ pioni. Observăm că putem reduce acest joc la jocul $NIM$ în care grămada virtuală asociată pionului $i$ are un număr de pietre egal cu valoarea $g$ a nodului în care este situat pionul $i$.\r\n\r\n_De ce este acest joc echivalent cu jocul NIM?_\r\n\r\nAşa cum la $NIM$ puteam lua oricâte pietre dintr-o grămadă, aici putem muta pionul dintr-un nod cu valoarea $g$ într-un nod astfel încât noua valoare pentru pionul $i$ poate fi orice număr de la $0$ la $g - 1$. Prin urmare, pentru a verifica dacă suntem într-o poziţie de câştig în jocul cu pionii, putem aplica strategia jocului $NIM$ şi obţinem că suntem într-o poziţie de câştig dacă suma $XOR$ a numerelor din nodurile ocupate de cei $N$ pioni este diferită de $0$. Această sumă se numeşte funcţia _Sprague Grundy_: <tex>SG(i_{1}, ..., i_{n}) = g_{i_1} \\verb|^| g_{i_2} \\verb|^| g_{i_3} \\verb|^| ... \\verb|^| g_{i_n}</tex>.\r\n\r\nProblema se rezolvă acum uşor efectuând o sortare topologică a nodurilor grafului aciclic şi numerotând nodurile folosind funcţia $mex$.\r\n\r\nh2(#aplicatii-sg). Aplicaţii ale numerelor Sprague Grundy\r\n\r\nÎn continuare, să studiem alte probleme ce se pot rezolva cu numerele $Sprague Grundy$.\r\n\r\nh3(#problema-4). Problema 4 (Joc, Bursele Agora 2003/2004, Runda 13)\r\n\r\nÎn acestă problemă se cere să verificăm existenţa unei strategii de câştig pentru un joc similar cu $NIM$ în care se poate lua dintr-o grămadă o piatră sau un număr prim de pietre.\r\n\r\nDacă determinăm valorile $Sprague Grundy$ pentru grămezi de dimensiuni mici putem observa că se repeta o succesiune de numere: $0 1 2 3 0 1 2 3 ...$\r\nPutem demonstra prin inducţie că această secvenţă se va repeta la nesfărşit.\r\nPentru o grămadă de dimensiune $n$ valoarea asociată va fi $n modulo 4$. Pentru $0 ≤ n ≤ 3$ afirmaţia este adevărată. Vom presupune afirmaţia adevărată pentru toate valorile $m < n$. Să demonstrăm acum că este adevărată şi pentru $n$. Deoarece putem lua din $n$ pietre una, două sau trei pietre, mai rămâne valoarea $n modulo 4$ care nu este eliminată încă din valorile potenţiale asociate grămezii de dimensiune $n$. Vom arăta în continuare că această valoare nici nu va fi eliminată. Eliminarea ei ar însemna că putem lua din $n$ un număr $p$ de pietre şi atunci din $(n - p) modulo 4 = n modulo 4$, am avea: $p modulo 4 = 0$, dar $p$ este un număr prim, deci valoarea $Sprague Grundy$ asociată unei grămezi de dimensiune $n$ este $n modulo 4$.\r\n\r\nh3(#problema-5). Problema 5 (\'Stone game\':http://acm.mipt.ru/judge/problems.pl?problem=101&CGISESSID=b4a5b84bd176d84796a209dc7c8002b8, El Judge)\r\n\r\nbq. Se consideră $K$ grămezi cu $n{~1~}, n{~2~}, …, n{~K~}$ pietre fiecare. Când este rândul său, un jucător poate lua dintr-o gramadă $2^m^$ pietre. Jucătorul care ia ultima piatră câştigă. Restricţii: $K ≤ 50, n{~i~} ≤ 10^200^$.\r\n\r\nh3. Soluţie\r\n\r\nSă determinăm valorile $Sprague Grundy$ pentru grămezi mici:\r\n\r\n$0 : 0;    1 : 1;    2 : 2;    3 : 0;    4 : 1;    5 : 2;    6 : 0$\r\n\r\nObservăm şi aici secvenţa repetitivă $0 1 2 0 1 2$, deci am putea trage concluzia că valoarea $Sprague Grundy$ asociată unei grămezi de dimensiune $n$ este $n modulo 3$. Această afirmaţie este adevarată şi urmează aceeaşi demonstraţie ca în cazul problemei anterioare, iar restul $modulo 3$ pentru $n$ număr cu $200$ de cifre este simplu de găsit determinând suma cifrelor numărului.\r\n\r\nh3(#problema-6). Problema 6 (\'Stone game II\':http://acm.mipt.ru/judge/problems.pl?problem=102&CGISESSID=b4a5b84bd176d84796a209dc7c8002b8, El Judge)\r\n\r\nbq. Se consideră $K$ grămezi de pietre cu $n{~1~}, n,{~2~} …, n{~K~}$ pietre. Un jucător poate lua dintr-o grămadă la mutarea lui un număr pozitiv de pietre dar nu mai mult de jumătate din pietrele din grămadă. Jucătorul care nu mai poate muta pierde. Restricţii: $K ≤ 50, n{~i~} ≤ 100000$.\r\n\r\nh3. Soluţie\r\n\r\nNumărul $100000$ nu este foarte mare şi valorile $Sprague Grundy$ pot fi determinate _off-line_ şi incluse în programul nostru ca şi constante. Putem scrie pentru valori mici secvenţa $Sprague Grundy$:\r\n\r\n$1 2 3 4 5 6 7 8 9 10 11 12 13 14$\r\n$0 1 0 2 1 3 0 4 2  5  1  6  3  7$\r\n\r\nPentru $n$ impar valoarea asociată este aceeaşi cu valoarea asociată lui $n/2$, şi pentru $n$ par valoarea asociată este $n/2$. Acest lucru se poate demonstra prin inducţie matematică.\r\n\r\nh3(#problema-7). Problema 7 (Sticks, CEOI 2000)\r\n\r\nbq. Se consideră $n (n ≤ 10)$ rânduri de beţe pe o masă, cu $S{~i~} (S{~i~} ≤ 10)$ beţe aliniate pe fiecare rând şi doi jucători. Beţele de pe rândul $i$ sunt numerotate secvenţial de la $1$ la $S{~i~}$. Cei doi jucători mută alternativ. Fiecare mişcare constă în eliminarea a unu, două sau trei beţe de pe acelaşi rând. Beţele trebuie sã fie numerotate secvenţial, adică să fie consecutive. De exemplu, un rând are $10$ beţe şi primul jucător elimină beţele $4$, $5$, $6$, deci vor rămâne numai beţele $1$, $2$, $3$, $4$, $8$, $9$, $10$. Al doilea jucător poate lua la rândul său beţele $1$, $2$, $3$, dar nu beţele $3$, $7$, $8$ pentru că acestea nu sunt numerotate consecutiv (bineînţeles că există şi alte mutări valide). Câştigă jucătorul care ia ultimul băţ de pe masă.\r\n\r\nh3. Soluţie\r\n\r\nProblema generală are o soluţie ingenioasă care ţine seama de parităţile rândurilor, dar la această problemă, datorită mărginirii lui $S{~i~} (S{~i~} ≤ 10)$ nu este necesar să fim ingenioşi. Restricţia $S{~i~} ≤ 10$, ne ajută prin faptul cã numărul total de poziţii (dacă jucăm pe o singură gramadă), este $2^10^$. Vom reprezenta o poziţie printr-un întreg, iar dacă acel întreg are în codificarea lui binară pe poziţia $i$ un bit de $1$ înseamnă că el reprezintă un rând de beţe care conţine în el băţul numerotat cu $i$. Este uşor de realizat un graf aciclic al mişcărilor pentru un rând (graful este aciclic pentru că la fiecare mutare luăm beţe din configuraţie). Numerotăm fiecare poziţie cu numerele $Sprague Grundy$, şi acum problema deciderii dacă suntem sau nu într-o poziţie câştigătoare devine banală. În problema iniţială trebuia să jucăm împotriva calculatorului şi să câştigăm. Putem realiza aceasta folosind mutarea câştigătoare prezentată la jocul $NIM$.\r\n\r\nh3(#problema-8). Problema 8 (\'Joc\':problema/joc2, Bursele Agora 2006)\r\n\r\nbq. Doi participanţi mănâncă alternant din nişte tablete de ciocolată după următoarele reguli:\r\n{*} taie o tabletă în două, tăietura trebuie să fie paralelă cu una din laturile tabletei şi trebuie să nu taie pătrăţelele de ciocolată;\r\n{*} poate să rupă şi să mănânce orice linie sau coloană de pătrăţele care nu se află pe marginea tabletei;\r\n{*} poate să rupă şi să mănânce toate patrăţelele de pe marginea tabletei, cu condiţia ca tableta rămasă să aibă cel puţin dimensiunea $1 x 1$.\r\nNici una dintre aceste trei mutări nu poate fi efectuată asupra unei tablete de dimensiune $1 x 1$. Pierde jucătorul care nu mai poate efectua nici o mutare.\r\n\r\nh3. Soluţie\r\n\r\nPentru această problemă vom calcula matricea $SG{~i,j~}$ care reprezintă valoarea $Sprague-Grundy$ asociată unei tablete de dimensiuni $(i, j)$. Să vedem care este recurenţa care va satisface elementele matricei $SG$:\r\n\r\n<tex> SG_{i,j} = mex(SG_{i,k} \\verb|^| SG_{i,j-k}, (1 \\leq k < j) </tex> mutarea întâi\r\n<tex> SG_{k,j} \\verb|^| SG_{i-k,j}, \\hspace{21 mm}(1 \\leq k < i) </tex>\r\n<tex> SG_{i,k} \\verb|^| SG_{i,j-k-1}, \\hspace{17.5 mm} (1 \\leq k < j - 1) </tex> mutarea a doua\r\n<tex> SG_{k,j} \\verb|^| SG_{i-k-1,j}, \\hspace{17 mm} (1 \\leq k < i - 1) </tex>\r\n<tex> SG_{i-2,j-2}) \\hspace{28 mm} (i > 2 , j > 2 )</tex> mutarea a treia\r\n\r\nAcum, pentru a calcula numărul de mutări câştigătoare efectuăm asupra fiecărei tablete din fişierul de intrare toate mutările posibile care sunt cel mult de $4 * 100 + 1$ şi facem suma $XOR$ a valorilor $Sprague Grundy$ pentru restul tabletelor neimplicate în mutare şi a tabletelor rezultate din mutare. Pentru a calcula $SG{~i,j~}$ trebuie sã parcurgem cel mult $2 * i + 2 * j + 1$ valori obţinute. Astfel, algoritmul de determinare al valorilor matricei $SG$ are ordinul de complexitatea $O(N^3^)$. Complexitatea algoritmului care determină numărul de mutări câştigătoare este $O(N^2^)$.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nAm văzut că aceste numere sunt folositoare pentru rezolvarea unor probleme de jocuri combinatorice. Chiar dacă numărul stărilor grafului nostru aciclic poate să fie foarte mare, putem să ne dăm seama, câteodată, din valorile mici de o regulă pe care o urmează numerele, sau măcar putem determina mai uşor configuraţii pentru care jocul are sau nu strategie de câştig, fapt care ne poate ajuta în descoperirea rezolvării generale.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\n* \'Joc3\':problema/joc3\r\n* \'Got Root?\':http://ipsc.ksp.sk/contests/ipsc2003/real/problems/g.php, _IPSC 2003_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# \'Colecţia GInfo\':http://www.ginfo.ro/\r\n# Mihai Oltean, _Programarea Jocurilor Matematice_, Editura Albastră, Cluj-Napoca, 1996\r\n# \'Thomas S. Ferguson, Game Theory Text (online)\':http://www.math.ucla.edu/~tom/gamescourse.html\r\n# \'Interactive Mathematics\':http://www.cut-the-knot.com\r\n# \'Wolfram MathWorld\':http://www.mathworld.wolfram.com\r\n# \'IPSC\':http://ipsc.ksp.sk/\r\n',5700,'public',NULL,NULL);
 INSERT INTO `ia_textblock_revision` VALUES ('training-path','Training path','2008-01-22 17:36:01','2008-12-16 17:05:41','h1. Training path\r\n\r\nVrem sa intocmim o baza de cunostinte fara precendent! Vrem ca aceasta pagina sa contina o lista cat mai completa cu ce trebuie sa stie un olimpic pentru a avea succes. \'Ajuta-ne\':implica-te/scrie-articole si tu!\r\n\r\n*Cosmin:* ar trebui sa facem o lista mai mica cu chestiile importante ca sa ajungi la ONI, ca sa nu se sperie cei ce abia incep.\r\n\r\nh2. Structuri de date\r\n\r\n* Liste, stive, cozi\r\n* Smenul cu deque\r\n* \'Tabele de dispersie\':hashing\r\n** \'Cuckoo hashing\':http://en.wikipedia.org/wiki/Cuckoo_hashing\r\n* \'Bloom filters\':http://en.wikipedia.org/wiki/Bloom_filter\r\n* \'Skiplists\':skiplists\r\n\r\n* \'Arbori indexati binar\':aib\r\n* Cozi de prioritati\r\n** \'Heap-uri\':heapuri\r\n** Mergeable heaps (maxophobic heaps sunt cel mai simple)\r\n** Pentru costuri intregi mici, un array de liste\r\n\r\n* Structuri de multimi disjuncte\r\n* \'Arbori de intervale\':arbori-de-intervale\r\n* \'Tries\':http://infoarena.ro/problema/trie\r\n* Arbori binari de cautare (\'treaps\':treapuri, AVL, red-black trees)\r\n* \'Cautari ortogonale. Quad trees, kD-trees\':cautari-ortogonale\r\n\r\nh2. Algoritmi si tehnici de programare\r\n\r\nh3. Matematica\r\n\r\n* Inductie matematica\r\n* \'Algoritmul lui Euclid\':algoritmul-lui-euclid\r\n* CMMDC binar\r\n* \'Ciurul lui Erathostene\':ciurul-lui-erathostene\r\n* \'Gray code\':coduri-gray\r\n* Rezolvare de ecuatii liniare modulare\r\n* Teorema mica a lui Fermat\r\n* \'Teorema chineza a resturilor\':teorema-chineza-a-resturilor\r\n** Probleme: \'eval\':problema/eval \'resturi\':problema/resturi \'gears in action\':http://ipsc.ksp.sk/contests/ipsc2005/real/problems/g.php\r\n* \"Numere mari: adunare, scadere, inmultire, impartire, radical\":lucrul-cu-nr-mari\r\n* Recurente si exponentiere rapida de matrici (+evaluare rapida a expresiilor folosind exponentiere in timp logaritmic)\r\n* \'Principiul includerii si excluderii\':principiul-includerii-si-excluderii\r\n** Probleme: \'cowfood\':problema/cowfood, \'indep\':problema/indep, \'frac\':problema/frac\r\n* Sisteme de ecuatii liniare (Gauss)\r\n** Teorie:\r\n*** \'Gaussian elimination\':http://en.wikipedia.org/wiki/Gaussian_elimination\r\n*** \'Row echelon form\':http://en.wikipedia.org/wiki/Row_echelon_form\r\n** Probleme: \'SGU 275 To xor or not to xor\':http://acm.sgu.ru/problem.php?contest=0&problem=275 \'.campion Xor\':http://campion.edu.ro/problems/3/323/xor_ro.htm \'SGU 260 Puzzle\':http://acm.sgu.ru/problem.php?contest=0&problem=260 \'UVA 10808\':http://online-judge.uva.es/p/v108/10808.html \'UVA 326\':http://online-judge.uva.es/p/v3/326.html \'UVA 10014\':http://online-judge.uva.es/p/v100/10014.html \'BColor\':problema/bcolor \'Laser\':problema/laser \'TC XORing\':http://www.topcoder.com/stat?c=problem_statement&pm=4829&rd=8095&rm=246636&cr=270505 \'TC Escape the jail\':http://www.topcoder.com/stat?c=problem_statement&pm=7353 \'Register CEOI 2003\':http://ceoi.inf.elte.hu/probarch/03/register-en.pdf \'Tunelul groazei\':problema/tunel \'SGU 200\':http://acm.sgu.ru/problem.php?contest=0&problem=200 \'TC CoinGame\':http://www.topcoder.com/stat?c=problem_statement&pm=6005 \r\n* Simplex (pur si simplu un hill climbing pe mai multe variabile)\r\n* \"Floyd\'s cycle finding\":http://en.wikipedia.org/wiki/Cycle_detection\r\n* Combinatorica\r\n** Permutari, permutari cu repetitii, aranjamente, combinari, Stirling, Catalan, Bell, Fibonacci\r\n** Trecere de la combinare/permutare la indexul ei si invers\r\n** \'Codul Prufer. Numarare de arbori\':http://en.wikipedia.org/wiki/Pr%C3%BCfer_sequence\r\n\r\nh3. Geometrie\r\n\r\n\'computer graphics FAQ\':http://www.faqs.org/faqs/graphics/algorithms-faq/\r\n\'cursuri dupa Computational Geometry: Algorithms and Applications, Mark de Berg, M. van Krefeld, M. Overmars, O. Schwarzkopf\':http://www.cs.umd.edu/class/spring2007/cmsc754/Lects/754lects.pdf\r\n\r\n\r\n* Intersectie a doua segmente\r\n* Punct in interiorul unui poligon\r\n** http://geometryalgorithms.com/Archive/algorithm_0103/algorithm_0103.htm\r\n** http://tog.acm.org/editors/erich/ptinpoly/\r\n* Punct in poligon convex in $O(log n)$\r\n** http://geometryalgorithms.com/Archive/algorithm_0103/algorithm_0103.htm#Monotone%20Polygons\r\n* \'Teorema lui Pick\':http://www.cut-the-knot.org/ctk/Pick_proof.shtml\r\n** problema \'copaci\':problema/copaci\r\n* Aria unui poligon\r\n* Centrul de greutate al unui poligon\r\n* \'Triangularizare de poligon in $O(n^2)$\':http://people.csail.mit.edu/indyk/6.838-old/handouts/lec4.pdf\r\n* \'Intersectia a doua cercuri\':http://local.wasp.uwa.edu.au/~pbourke/geometry/2circle/\r\n* \'Minimal enclosing circle\':minimal-enclosing-circle\r\n* Convex hull\r\n** http://www.algorithmist.com/index.php/Monotone_Chain_Convex_Hull\r\n** http://en.wikipedia.org/wiki/Gift_wrapping_algorithm\r\n** Aplicatie - onion peeling in O(n^2^)\r\n* \'Baleiere verticala / radiala\':algoritmi-de-baleiere\r\n** baleiere radiala\r\n*** Se da un set S de n punct in plan. Sa se determine cercul de raza R fixata care acopera cat mai multe puncte din S. O(n^2 log n)\r\n*** Se da un set S de n puncte in plan. Sa se gaseasca o dreapta ce trece prin nr maxim de puncte din S. O(n^2^) cu hashuri pt unghiuri sau O(n^2 log n) cu baleiere radiala.\r\n*** Se da un set S de n segmente in plan. Sa se gaseasca o dreapta ce intersecteaza numarul maxim de segmente din S. O(n^2 log n) cu baleiere radiala.\r\n*** \'Construirea grafului de vizibilitate.\':http://en.wikipedia.org/wiki/Visibility_graph\r\n* \'Rotating calipers\':http://cgm.cs.mcgill.ca/~orm/rotcal.html\r\n** problema \'rubarba\':problema/rubarba\r\n** problema \'popandai2\':problema/popandai2\r\n* Intersectie de poligoane convexe\r\n* Intersectie de semiplane (fara dualizare)\r\n** problema \'camera\':problema/camera\r\n* \'Dualizare (intersectie de semiplane, diagrame Voronoi)\':http://infoarena.ro/voronoi\r\n\r\n* \'thread pe forum\':http://infoarena.ro/forum/index.php?topic=3007.0\r\n\r\nh3. Sortari si cautari\r\n\r\n* Shell sort, merge sort, heapsort, quicksort, counting sort, radix sort\r\n* Statistici de ordine\r\n* Cautare binara/ternara si \'aplicatii\':aplicatii-ale-cautarii-binare\r\n* Hill climbing\r\n\r\nh3. Greedy\r\n\r\n* Huffman\r\n* Job scheduling\r\n\r\nh3. Programare dinamica\r\n\r\n* Parantezare optima de matrici\r\n* Cel mai lung subsir crescator $O(N*log N)$\r\n* Knapsack\r\n** Knapsack pe biti\r\n* Cel mai lung subsir comun\r\n* Distanta de editare\r\n* Ciclu hamiltonian in $O(n^2^ * 2^n^)$\r\n** problema \'adn\':problema/adn\r\n* Dinamicile in $3^n^$\r\n** \'explicatie\':http://forums.topcoder.com/?module=Thread&threadID=512824&start=0, \'problema\':http://www.topcoder.com/stat?c=problem_statement&pm=6678&rd=9998&rm=249548&cr=8547850\r\n* \'Arbore de cautare optim in $O(n^2)$\':http://www.ics.uci.edu/~dan/class/165/notes/OptBST.html\r\n* Dinamici pe arbori\r\n* Numarul posibilitatilor de acoperire a unei table cu dominouri\r\n* Memoizare (trading space for time)\r\n\r\nh3. Grafuri\r\n\r\n* Parcurgeri\r\n** dfs, bfs, meet in the middle bfs\r\n** Componente biconexe\r\n** Componente tare-conexe\r\n** Sortare topologica\r\n** Ciclu eulerian\r\n* Drumuri minime\r\n** Dijkstra (cu heapuri, cu set-uri, cu AINT-uri, cu coada ca pe TC - Cosmin stie)\r\n** \'Dijkstra cu costuri mici ;)\':http://www.ginfo.ro/revista/13_6/focus2.pdf cum se foloseste la problema \'car\':problema/car\r\n** A* has a lot of intuitive appeal for me. If you compare Dijkstra\'s vs. A*, Dijkstra\'s is like a puddle of water flooding outwards on a flat floor, whereas A* is like the same puddle expanding on a bumpy and graded floor toward a drain (the target node) at the lowest point in the floor. Instead of spreading out evenly on all sides, the water seeks the path of least resistance, only trying new paths when something gets in its way. The heuristic function is what provides the \'grade\' of the hypothetical floor.\r\n*** A* se foloseste foarte mult in industria jocurilor, fiind un algoritm foarte rapid in practica. Un exemplu unde este folosit este jocul de strategie Starcraft.\r\n** Floyd-Warshall\r\n** Bellman-Ford\r\n*** De obicei mai simplu de implementat si cam aceeasi viteza ca si Dijkstra cu heapuri\r\n*** Sistem de inegalitati\r\n*** \'Ciclu de cost mediu minim\':ciclu-de-cost-mediu-minim\r\n* Flux\r\n** Edmonds-Karp\r\n** \'Taietura minima\':taietura-minima\r\n** Dinic\r\n** Flux maxim de cost minim\r\n** Flux cu capacitati inferioare\r\n** Circulatii\r\n** Problema postasului chinez\r\n*** problema \'traseu\':problema/traseu\r\n* Arbori\r\n** \'Diametrul, centrul unui arbore\':http://online-judge.uva.es/board/viewtopic.php?p=36766&highlight=#36766\r\n** \'Testare daca doi arbori sunt izomorfi\':http://online-judge.uva.es/board/viewtopic.php?p=22754&highlight=#22754\r\n** Cod Prufer\r\n* APM\r\n** Prim\r\n** Kruskal\r\n** Al doilea APM\r\n** APM in graf orientat\r\n** Kirchhoff\'s matrix tree theorem\r\n* Pentru grafuri bipartite: \'cuplaj maxim\':problema/cuplaj, suport minim, multime independenta maxima\r\n* \'LCA\':lowest-common-ancestor, RMQ, Level Ancestor, \'Path Decomposition\':heavy-path-decomposition\r\n* Colorari de muchii, graf complet/bipartit/oarecare (teorema lui Vizing)\r\n* Grafuri planare\r\n** problema \'count\':problema/count\r\n* Grafuri turneu/ciclu hamiltonian\r\n** problema \'plimbare\':problema/plimbare\r\n* \'Implication graph si 2-SAT\':downloads?action=download&file=2SAT.doc\r\n** problema \'aladdin\':problema/aladdin\r\n\r\n\r\nh3. Siruri de caractere\r\n\r\n* Hashuri\r\n* \'KMP\':automate-finite-si-kmp\r\n* \'Siruri de sufixe\':siruri-de-sufixe\r\n** \'In timp liniar\':suffix-array-liniar\r\n* \'Aho-Corasick\':http://www.cs.uku.fi/~kilpelai/BSA05/lectures/slides04.pdf .\r\n\r\nh3. Limbaje formale si automate finite\r\n\r\n* Evaluari de expresii aritmetice\r\n* \'CYK\':http://en.wikipedia.org/wiki/CYK\r\n* Matching with wildcards\r\n* Construirea unui automat care sa accepte un set de cuvinte\r\n* Simplificare de automate\r\n* Echivalenta de automate\r\n* \'thread pe forum\':http://infoarena.ro/forum/index.php?topic=3005.0\r\n\r\nh3. Teoria jocurilor\r\n\r\n* Nim\r\n* \'Numere Sprague-Grundy\':http://www.ginfo.ro/revista/14_5/mate.pdf\r\n* Min-max\r\n* Alpha-beta\r\n\r\nh2. Diverse\r\n\r\nh3. \'STL @(Standard Template Library)@\':stl\r\n\r\n* vector, deque, stack, list\r\n* string\r\n* set, map, hash_map\r\n* pair\r\n* sort\r\n* priority_queue\r\n* bitset\r\n* iteratori\r\n\r\nh3. Cautari\r\n\r\n* backtracking\r\n* iterative deepening\r\n* branch and bound\r\n\r\nh3. Optimizari\r\n\r\n* Parsare\r\n* Lucru cu biti\r\n* Brute force\r\n** \'dancing links\':http://en.wikipedia.org/wiki/Dancing_Links\r\n\r\nh3. Lucrul cu memoria\r\n\r\n* \'Cacheuri de memorie\':http://en.wikipedia.org/wiki/CPU_cache\r\n** problema \'stramosi\':problema/stramosi\r\n*  \'free lists\':http://www.memorymanagement.org/glossary/f.html#free.list\r\n** problema \'eprubeta\':problema/eprubeta\r\n\r\nh3. Bulanit\r\n\r\n* Randomizare (2-opt, k-opt)\r\n* Constante\r\n* Interpolare Taylor / Gauss pentru formule polinomiale\r\n\r\nh3.  Smenuri\r\n\r\n* Smenu\' lui Batog (+ lca in $sqrt(n)$)\r\n** probleme: \'schi\':problema/schi, \r\n* Smenu\' lui Mars\r\n** problema \'cuburi\':http://campion.edu.ro/do_download.php?problem_id=122&type=application/pdf&year=2003&lang=ro\r\n* \'Meet in the middle\':meet-in-the-middle\r\n\r\nh2. Carti utile\r\n\r\n* Ioan Tomescu\r\n** \"Probleme de combinatorica si teoria grafurilor\" (din care s-a dat la ONI sau lot aproape in fiecare an cate o problema sau mai multe)\r\n** \"Combinatorica si teoria grafurilor\"\r\n* Ioan Cuculescu\r\n** \"Olimpiadele Internationale de Matematica ale Elevilor\"\r\n* E. A. Morozova, I. S. Petracov, V. A. Skvortov\r\n** \"Olimpiade internationale de matematica\"\r\n* \"Probleme de matematica traduse din revista sovietica KVANT\"\r\n* A. M. Iaglom, I. M. Iaglom\r\n** \"Probleme neelementare tratate elementar\"\r\n* Thomas H. Cormen, Charles E. Leiserson, Ronald R. Rivest\r\n** \'\"Introducere in algoritmi\"\':http://libris.agora.ro/algoritmi.html\r\n* D. E. Knuth\r\n** \"Arta programarii calculatoarelor\" (\"The Art of Computer Programming\")\r\n** \"Concrete Mathematics\"\r\n* Jon Bentley\r\n** \"Programming Pearls\"\r\n* Steven Skiena\r\n** \"The Algorithm Design Manual\"\r\n* W. Rytter\r\n** \"Jewels of Stringology\"\r\n* Mark de Berg\r\n** \"Computational geometry\"\r\n',2044,'public',NULL,NULL),('numerele-sprague-grundy','Teoria jocurilor: numerele Sprague-Grundy','2008-11-18 17:10:41','2009-01-19 00:13:27','h1. Teoria jocurilor: numerele Sprague-Grundy\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"portocala\") ==\r\n\r\n(Categoria _Matematică_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 25em}*{text-align:center;} *Conţinut*\r\n* \'Introducere\':numerele-sprague-grundy#introducere\r\n* \'Ce este jocul NIM?\':numerele-sprague-grundy#jocul-nim\r\n* \'Aplicaţii ale strategiei NIM\':numerele-sprague-grundy#aplicatii-nim\r\n* \'Numerele Sprague-Grundy\':numerele-sprague-grundy#sprague-grundy\r\n* \'Aplicaţii ale numerelor Sprague-Grundy\':numerele-sprague-grundy#aplicatii-sg\r\n* \'Concluzii\':numerele-sprague-grundy#concluzii\r\n* \'Probleme suplimentare\':numerele-sprague-grundy#probleme-suplimentare\r\n* \'Bibliografie\':numerele-sprague-grundy#bibliografie\r\n\r\nh2(#introducere). Introducere\r\n\r\nDomeniu relativ nou şi încă necercetat în adâncime, $teoria jocurilor$ este o ramură a matematicii în care de multe ori primează inventivitatea şi nu cunoştinţele. Tocmai din acest motiv, în cadrul acestui articol vom introduce câteva noţiuni teoretice care ne vor ajuta în rezolvarea unor probleme din teoria jocurilor. Ingeniozitatea celor pasionaţi poate fi testată prin introducerea unor probleme de teoria jocurilor la concursurile de matematică şi informatică. Deoarece în România teoria jocurilor nu este studiată în şcoli, problemele din acest domeniu pot pune în dificultate concurenţii.\r\n\r\nh2(#jocul-nim). Ce este jocul NIM?\r\n\r\nPentru început ne vom familiariza cu jocul clasic $NIM$:\r\n\r\nbq. Se consideră $N$ grămezi de pietre. Doi jucători, vor ridica alternativ oricâte pietre dintr-o singură grămadă. Câştigătorul este cel care ia ultima piatră.\r\n\r\nÎn rezolvare distingem mai multe cazuri:\r\n\r\n* Pentru cazul trivial în care numărul de grămezi este egal cu $1$, primul jucător are, evident, strategie de câştig, el putând lua toate pietrele din grămadă.\r\n* Dacă numărul de grămezi este egal cu $2$, primul jucător are strategie de câştig atunci când numărul de pietre din prima grămadă este diferit de numărul de pietre din cea de-a doua, strategia lui fiind cea de a aduce tot timpul grămada mai mare la numărul de pietre al grămezii mai mici, şi cum jocul este finit, înseamnă că primul jucător o să aducă jocul în starea $(0, 0)$.\r\n* Dacă numărul de grămezi este mai mare decât doi, strategia se complică şi nu se mai observă cu \"ochiul liber\". Stările câştigătoare pentru mai multe grămezi sunt acele stări pentru care suma $XOR$ a numerelor de pietre din grămezi este diferită de $0$, restul stărilor fiind de pierdere.\r\n\r\nDe exemplu, dacă avem $4$ grămezi cu $1$, $3$, $5$, respectiv $7$ pietre:\r\n\r\n* $*O*$\r\n* $*OOO*$\r\n* $*OOOOO*$\r\n* $*OOOOOOO*$\r\n\r\nAtunci vom avea:\r\n\r\n* $*1 = (0001){~2~}*$\r\n* $*3 = (0011){~2~}*$\r\n* $*5 = (0101){~2~}*$\r\n* $*7 = (0111){~2~}*$\r\n\r\nEfectuând \'$XOR$\':http://www.fredosaurus.com/notes-cpp/expressions/bitops.html (operatorul $^$ în $C/C++$) între reprezentările binare ale numerelor, obţinem $*0 = (0000){~2~}*$. Conform propoziţiei de mai sus, această stare este de pierdere.\r\n\r\nSă demonstrăm cele afirmate. Dintr-o poziţie cu suma $XOR$ egală cu $*0*$, pentru orice mutare ajungem evident la o poziţie cu suma $XOR$ diferită de $*0*$, pentru că luând dintr-o grămadă un număr $x$ de pietre, suma $XOR$ corespunzătoare noii stări, pe poziţia bitului de $*1*$ cel mai din dreapta în reprezentarea lui $x$, va avea valoarea $*1*$.\r\n\r\nMai rămâne de demonstrat că din orice poziţie cu suma $XOR$ diferită de $*0*$ putem trece printr-o mutare convenabilă într-o poziţie cu suma $XOR$ egală cu $*0*$. Căutăm o grămadă al cărui număr de pietre are bitul $*1*$ pe poziţia celei mai mari puteri a lui $2$ care apare în suma $XOR$. Fie $x$ valoarea sumei $XOR$ a tuturor grămezilor şi $y$ numărul de pietre din grămada găsită mai devreme. O mutare \"câştigătoare\" este extragerea din grămada găsită care are $y$ pietre a {$y - (x XOR y)$} pietre ({$x XOR y$} este mai mic decât $y$ pentru că în $y$ se anulează bitul cel mai semnificativ al lui $x$). Atunci noua sumă $XOR$ va fi egală cu $*0*$.\r\n\r\nDe exemplu:\r\n\r\n* $*4{@ ^ 8 ^ @}17 = (00100){~2~}{@ ^ @}(01000){~2~}{@ ^ @}(10001){~2~} = (11101){~2~} = 29*$.\r\n\r\nMutarea câştigătoare constă în a lua din cea de-a treia gramadă un număr de pietre egal cu:\r\n\r\n* $*17 - (17 ^ 29) = 17 - 12 = 5 = (00101){~2~}*$.\r\n\r\nDupă acest pas grămezile vor avea $4$, $8$, $12$ pietre. Ne aflăm astfel într-o stare cu suma $XOR$ egală cu $*0*$.\r\n\r\nh2(#aplicatii-nim). Aplicaţii ale strategiei NIM\r\n\r\nExemplificăm în continuare câteva probleme în care se foloseşte strategia jocului $NIM$.\r\n\r\nh3(#problema-1). Problema 1\r\n\r\nbq. Pe o tablă de şah, care are $N x M$ căsuţe, sunt plasaţi pe prima linie $N$ pioni albi şi pe ultima linie $N$ pioni negri. Fiecare dintre cei doi jucători poate muta un singur pion, care îi aparţine, un număr strict pozitiv de căsuţe în sus sau în jos, astfel încât să nu ajungă vreun pion alb să fie mai jos decât pionul negru de pe aceeaşi coloană. Pierde jucătorul care nu mai poate muta.\r\n\r\nh3. Soluţie\r\n\r\nAceastă problemă este o deghizare a jocului $NIM$, numărul de pătrăţele libere între pionul alb şi pionul negru de pe coloana $i$ putând fi considerat numărul de pietre din grămada $i$. Singura diferenţă este că se pot adăuga pietre la grămadă (existând posibilitatea mutării înapoi). Această problemă se rezolvă uşor, jucătorul care are strategie de câştig putând evita asemenea mutări. O astfel de mutare poate fi utilă numai pentru jucătorul care este într-o poziţie de pierdere. Când jucătorul care nu are strategie de câştig mută înapoi $x$ căsuţe, celălalt jucător va muta pionul propriu de pe aceeaşi coloanã cu $x$ căsuţe în faţă, astfel ajungându-se la aceeaşi stare cu cea existentă cu două mutări anterior (considerând diferenţa poziţiilor).\r\n\r\nh3(#problema-2). Problema 2 (Baraj ONI 1997)\r\n\r\nbq. Pe o linie sunt plasate la coordonate întregi $2 x N$ piese roşii şi albastre. Fiecare piesă roşie poate fi mutată în dreapta oricâte poziţii astfel încât să nu sară peste o piesă albastră, iar piesele albastre pot fi mutate oricâte poziţii la stânga astfel încât să nu depăşească vreo piesă roşie. Piesele vor alterna: roşu, albastru, roşu, albastru etc. Pierde jucătorul care nu mai poate muta.\r\n\r\nh3. Soluţie\r\n\r\nAceastă problemă poate fi, de asemenea, redusă la jocul $NIM$. Diferenţele poziţiilor perechilor de piese roşii şi albastre consecutive constituie numărul de pietre al grămezilor din jocul $NIM$.\r\n\r\nh3(#problema-3). Problema 3 (\'Nim Game - Give Away!\':http://acm.mipt.ru/judge/problems.pl?problem=103, El Judge)\r\n\r\nbq. Se consideră $N$ grămezi de pietre, jucătorii mută alternativ, fiecare jucător extrăgând oricâte pietre dintr-o singură grămadă. Cel care ia ultima piatră pierde jocul.\r\n\r\nh3. Soluţie\r\n\r\nStrategia acestui joc este similară cu cea aplicată în jocul $NIM$ cu câteva mici diferenţe. Jucătorul care are strategie de câştig în poziţia curentă în cadrul jocului $NIM$ face aceeaşi mutare pe care ar face-o în cazul jocului $NIM$, exceptând cazul în care această mutare lasă doar grămezi cu o singură piatră şi numărul acestor grămezi este par. În această situaţie, dacă ar trebui să distrugă o grămadă de $x$ pietre, jucătorul poate lua $x - 1$, iar dacă ar trebui să lase o singură piatră din grămada actuală, poate lua întreaga grămadă. Astfel, numărul de grămezi rămase va fi impar şi el nu va face ultima mutare.\r\n\r\nh2(#sprague-grundy). Numerele Sprague-Grundy\r\n\r\nJocurile care prezintă interes pentru jucători sunt acelea care necesită examinarea unui număr foarte mare de stări pentru determinarea strategiei de câştig, deoarece în caz contrar câştigătorul s-ar cunoaşte chiar de la început. Spre deosebire de aceştia, matematicienii sau informaticienii sunt interesaţi de determinarea unor strategii pentru astfel de jocuri. Toate jocurile imparţiale cu doi jucători cu informaţie totală pot fi reduse la jocul *$NIM$* care se joacă cu nişte grămezi virtuale, în care mutările posibile sunt extragerea oricâtor pietre dintr-o grămadă sau adăugarea oricâtor pietre la o grămadă (aşa cum am menţionat anterior, adăugarea de pietre la o grămadă nu complică analiza jocului).\r\n\r\nAfirmaţia anterioară constituie un rezultat al _Teoriei Sprague-Grundy_. _Roland Percival Sprague_ (1936) şi _Patrick Michael Grundy_ (1939) sunt doi matematicieni care s-au ocupat, independent, de teoria jocurilor imparţiale.\r\n\r\nÎn continuare, considerăm următorul enunţ:\r\n\r\nbq. Se consideră un graf aciclic care conţine în noduri câţiva pioni, jucătorii alternează la mutare şi fiecare poate muta câte un pion pe un arc care iese din nodul în care este situat pionul. Pierde jucătorul care nu mai poate muta.\r\n\r\nÎntrucât graful este aciclic, jocul este finit şi are întotdeauna un câştigător. Practic, acest joc este suma unor jocuri, mai precis suma a mai multor jocuri cu un singur pion pe graful aciclic. Jocul cu un singur pion poate fi analizat destul de uşor, fiecare nod al grafului putând fi colorat cu alb sau negru după cum există sau nu strategie de câştig dacă în nodul curent ar fi poziţionat pionul. Această colorare poate fi realizată uşor dacă se porneşte de la nodurile fără urmaş şi la fiecare pas se colorează câte un nod ai cărui urmaşi sunt deja coloraţi. Orice joc imparţial poate fi redus la un joc cu un singur pion. Nodurile sunt poziţiile jocului şi arcele grafului sunt mutările posibile din fiecare poziţie. Jocul iniţial poate fi şi el transformat, dar numărul de noduri creşte foarte mult (pentru $N$ pioni şi $M$ noduri, numărul de noduri din jocul transformat este {$N^M^$}) şi nu este practic să colorăm graful rezultat. Folosind teoria dezvoltată de Sprague şi Grundy, putem reduce complexitatea analizei jocului cu $N$ pioni la complexitatea analizei jocului cu un pion.\r\n\r\nVom introduce funcţia *$mex$* cu semnificaţia: $mex(S)$ este elementul minimal natural care nu aparţine mulţimii $S$. Pentru fiecare nod $x$ al grafului aciclic considerat, vom calcula valoarea funcţiei $gx = mex(gx{~1~}, gx{~2~}, …, gx{~k~})$, unde $x{~1~}$, $x{~2~}$, …, $x{~k~}$ sunt urmaşii nodului $x$ în graf. Pentru nodurile fără urmaşi $gx = 0$.\r\n\r\nAnalog jocului cu un singur pion, graful poate fi etichetat din aproape în aproape, pornind de la nodurile fără urmaşi. Observăm că, dacă $gx = 0$, în jocul cu un singur pion situat în nodul $x$ nu avem strategie de câştig, iar dacă $gx$ este diferit de $0$ avem strategie de câştig. Restul informaţiei ne ajută la determinarea unei strategii pentru jocul cu $N$ pioni. Observăm că putem reduce acest joc la jocul $NIM$ în care grămada virtuală asociată pionului $i$ are un număr de pietre egal cu valoarea $g$ a nodului în care este situat pionul $i$.\r\n\r\n_De ce este acest joc echivalent cu jocul NIM?_\r\n\r\nAşa cum la $NIM$ puteam lua oricâte pietre dintr-o grămadă, aici putem muta pionul dintr-un nod cu valoarea $g$ într-un nod astfel încât noua valoare pentru pionul $i$ poate fi orice număr de la $0$ la $g - 1$. Prin urmare, pentru a verifica dacă suntem într-o poziţie de câştig în jocul cu pionii, putem aplica strategia jocului $NIM$ şi obţinem că suntem într-o poziţie de câştig dacă suma $XOR$ a numerelor din nodurile ocupate de cei $N$ pioni este diferită de $0$. Această sumă se numeşte _funcţia Sprague-Grundy_: <tex> SG(i_{1}, ..., i_{n}) = g_{i_1} {\\mathbin{\\char`\\^}} g_{i_2} {\\mathbin{\\char`\\^}} g_{i_3} {\\mathbin{\\char`\\^}} ... {\\mathbin{\\char`\\^}} g_{i_n}</tex>.\r\n\r\nProblema se rezolvă acum uşor efectuând o sortare topologică a nodurilor grafului aciclic şi numerotând nodurile folosind funcţia $mex$.\r\n\r\nh2(#aplicatii-sg). Aplicaţii ale numerelor Sprague-Grundy\r\n\r\nÎn continuare, să studiem alte probleme ce se pot rezolva cu numerele $Sprague-Grundy$.\r\n\r\nh3(#problema-4). Problema 4 (Joc, Bursele Agora 2003/2004, Runda 13)\r\n\r\nbq. Să se verifice existenţa unei strategii de câştig pentru un joc similar cu $NIM$ în care se poate lua dintr-o grămadă o piatră sau un număr prim de pietre.\r\n\r\nDacă determinăm valorile $Sprague-Grundy$ pentru grămezi de dimensiuni mici putem observa că se repeta o succesiune de numere: $0 1 2 3 0 1 2 3 ...$ Putem demonstra prin inducţie că această secvenţă se va repeta la nesfârşit. Pentru o grămadă de dimensiune $n$, valoarea asociată va fi $n modulo 4$. Pentru $0 ≤ n ≤ 3$ afirmaţia este adevărată. Vom presupune afirmaţia adevărată pentru toate valorile $m < n$. Să demonstrăm acum că este adevărată şi pentru $n$. Deoarece putem lua din $n$ pietre una, două sau trei pietre, mai rămâne valoarea $n modulo 4$ care nu este eliminată încă din valorile potenţiale asociate grămezii de dimensiune $n$. Vom arăta în continuare că această valoare nici nu va fi eliminată. Eliminarea ei ar însemna că putem lua din $n$ un număr $p$ de pietre şi atunci din $(n - p) modulo 4 = n modulo 4$, am avea: $p modulo 4 = 0$, dar $p$ este un număr prim, deci valoarea $Sprague-Grundy$ asociată unei grămezi de dimensiune $n$ este $n modulo 4$.\r\n\r\nh3(#problema-5). Problema 5 (\'Stone game\':http://acm.mipt.ru/judge/problems.pl?problem=101, El Judge)\r\n\r\nbq. Se consideră $K$ grămezi cu $n{~1~}, n{~2~}, ..., n{~K~}$ pietre fiecare. Când este rândul său, un jucător poate lua dintr-o gramadă $2^m^$ pietre. Jucătorul care ia ultima piatră câştigă. Restricţii: $K ≤ 50, n{~i~} ≤ 10^200^$.\r\n\r\nh3. Soluţie\r\n\r\nSă determinăm valorile $Sprague-Grundy$ pentru grămezi mici:\r\n\r\n$0 : 0;    1 : 1;    2 : 2;    3 : 0;    4 : 1;    5 : 2;    6 : 0$\r\n\r\nObservăm şi aici secvenţa repetitivă $0 1 2 0 1 2$, deci am putea trage concluzia că valoarea $Sprague-Grundy$ asociată unei grămezi de dimensiune $n$ este $n modulo 3$. Această afirmaţie este adevarată şi urmează aceeaşi demonstraţie ca în cazul problemei anterioare, iar restul $modulo 3$ pentru un număr cu $200$ de cifre este simplu de găsit determinând suma cifrelor numărului.\r\n\r\nh3(#problema-6). Problema 6 (\'Stone game II\':http://acm.mipt.ru/judge/problems.pl?problem=102, El Judge)\r\n\r\nbq. Se consideră $K$ grămezi de pietre cu $n{~1~}, n{~2~} ..., n{~K~}$ pietre. Un jucător poate lua dintr-o grămadă la mutarea lui un număr pozitiv de pietre, dar nu mai mult de jumătate din pietrele din grămadă. Jucătorul care nu mai poate muta pierde. Restricţii: $K ≤ 50, n{~i~} ≤ 100000$.\r\n\r\nh3. Soluţie\r\n\r\nNumărul $100000$ nu este foarte mare şi valorile $Sprague-Grundy$ pot fi determinate _off-line_ şi incluse în programul nostru sub formă de constante. Putem scrie pentru valori mici secvenţa $Sprague-Grundy$:\r\n\r\n$1 2 3 4 5 6 7 8 9 10 11 12 13 14$\r\n$0 1 0 2 1 3 0 4 2  5  1  6  3  7$\r\n\r\nPentru $n$ impar valoarea asociată este aceeaşi cu valoarea asociată lui $n/2$, şi pentru $n$ par valoarea asociată este $n/2$. Acest lucru se poate demonstra prin inducţie matematică.\r\n\r\nh3(#problema-7). Problema 7 (Sticks, CEOI 2000)\r\n\r\nbq. Se consideră $n$ ({$n ≤ 10$}) rânduri de beţe pe o masă, cu $S{~i~}$ ({$S{~i~} ≤ 10$}) beţe aliniate pe fiecare rând şi doi jucători. Beţele de pe rândul $i$ sunt numerotate secvenţial de la $1$ la $S{~i~}$. Cei doi jucători mută alternativ. Fiecare mişcare constă în eliminarea a unu, două sau trei beţe de pe acelaşi rând. Beţele trebuie sã fie numerotate secvenţial, adică să fie consecutive. De exemplu, un rând are $10$ beţe şi primul jucător elimină beţele $4$, $5$, $6$, deci vor rămâne numai beţele $1$, $2$, $3$, $7$, $8$, $9$, $10$. Al doilea jucător poate lua la rândul său beţele $1$, $2$, $3$, dar nu beţele $3$, $7$, $8$ pentru că acestea nu sunt numerotate consecutiv (bineînţeles că există şi alte mutări valide). Câştigă jucătorul care ia ultimul băţ de pe masă.\r\n\r\nh3. Soluţie\r\n\r\nProblema generală are o soluţie ingenioasă care ţine seama de parităţile rândurilor, dar la această problemă, datorită mărginirii lui $S{~i~}$ ({$S{~i~} ≤ 10$}) nu este necesar să fim ingenioşi. Restricţia $S{~i~} ≤ 10$ ne ajută prin faptul cã numărul total de poziţii (dacă jucăm pe o singură gramadă), este $2^10^$. Vom reprezenta o poziţie printr-un întreg, iar dacă acel întreg are în codificarea lui binară pe poziţia $i$ un bit de $1$ înseamnă că el reprezintă un rând de beţe care conţine în el băţul numerotat cu $i$. Este uşor de realizat un graf aciclic al mişcărilor pentru un rând (graful este aciclic pentru că la fiecare mutare luăm beţe din configuraţie). Numerotăm fiecare poziţie cu numerele $Sprague-Grundy$, şi acum problema deciderii dacă suntem sau nu într-o poziţie câştigătoare devine banală. În problema iniţială trebuia să jucăm împotriva calculatorului şi să câştigăm. Putem realiza aceasta folosind mutarea câştigătoare prezentată la jocul $NIM$.\r\n\r\nh3(#problema-8). Problema 8 (\'Joc\':problema/joc2, Bursele Agora 2006)\r\n\r\nbq. Doi participanţi mănâncă alternant din nişte tablete de ciocolată după următoarele reguli:\r\n{*} taie o tabletă în două, tăietura trebuie să fie paralelă cu una din laturile tabletei şi trebuie să nu taie pătrăţelele de ciocolată;\r\n{*} pot să rupă şi să mănânce orice linie sau coloană de pătrăţele care nu se află pe marginea tabletei;\r\n{*} pot să rupă şi să mănânce toate patrăţelele de pe marginea tabletei, cu condiţia ca tableta rămasă să aibă cel puţin dimensiunea $1 x 1$.\r\nNiciuna dintre aceste trei mutări nu poate fi efectuată asupra unei tablete de dimensiune $1 x 1$. Pierde jucătorul care nu mai poate efectua nicio mutare. În fişierul de intrare se va afla numărul $N$ ({$1 ≤ N ≤ 100$}) de tablete, iar pe următoarea linie vor fi $N$ perechi de numere întregi care reprezintă dimensiunile tabletelor. În fişierul de ieşire se va afla un singur număr întreg reprezentând numărul mutărilor câştigătoare pentru primul jucător.\r\n\r\nh3. Soluţie\r\n\r\nPentru această problemă vom calcula matricea $SG{~i,j~}$ care reprezintă valoarea $Sprague-Grundy$ asociată unei tablete de dimensiuni $(i, j)$. Să vedem care este recurenţa care va satisface elementele matricei $SG$:\r\n\r\n<tex> SG_{i,j} = mex( \\underbrace{ \\underbrace{SG_{i,k} {\\mathbin{\\char`\\^}} SG_{i,j-k},}_{1 \\leq k < j} \\underbrace{SG_{k,j} {\\mathbin{\\char`\\^}} SG_{i-k,j},}_{1 \\leq k < i} }_{mutarea\\ \\^{i}nt\\^{a}i } </tex> <tex> \\underbrace{ \\underbrace{SG_{i,k} {\\mathbin{\\char`\\^}} SG_{i,j-k-1},}_{1 \\leq k < j - 1} \\underbrace{SG_{k,j} {\\mathbin{\\char`\\^}} SG_{i-k-1,j},}_{1 \\leq k < i - 1} }_{mutarea\\ a\\ doua} </tex> <tex> \\underbrace{ \\underbrace{SG_{i-2,j-2}}_{i > 2,\\ j > 2} }_{mutarea\\ a\\ treia} )</tex>\r\n\r\nAcum, pentru a calcula numărul de mutări câştigătoare efectuăm asupra fiecărei tablete din fişierul de intrare toate mutările posibile care sunt cel mult de $4 * 100 + 1$ şi facem suma $XOR$ a valorilor $Sprague-Grundy$ pentru restul tabletelor neimplicate în mutare şi a tabletelor rezultate din mutare. Pentru a calcula $SG{~i,j~}$ trebuie sã parcurgem cel mult $2 * i + 2 * j + 1$ valori obţinute. Astfel, algoritmul de determinare al valorilor matricei $SG$ are ordinul de complexitatea $O(N^3^)$. Complexitatea algoritmului care determină numărul de mutări câştigătoare este $O(N^2^)$.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nAm văzut că aceste numere sunt folositoare pentru rezolvarea unor probleme de jocuri combinatorice. Chiar dacă numărul stărilor grafului nostru aciclic poate să fie foarte mare, putem să ne dăm seama, câteodată, din valorile mici de o regulă pe care o urmează numerele, sau măcar putem determina mai uşor configuraţii pentru care jocul are sau nu strategie de câştig, fapt care ne poate ajuta în descoperirea rezolvării generale.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\n* \'Joc3\':problema/joc3\r\n* \'Got Root?\':http://ipsc.ksp.sk/contests/ipsc2003/real/problems/g.php, _IPSC 2003_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* \'Colecţia GInfo\':http://www.ginfo.ro/\r\n* Mihai Oltean - _Programarea Jocurilor Matematice_, Editura Albastră, Cluj-Napoca, 1996\r\n* Thomas S. Ferguson - \'Game Theory Text\':http://www.math.ucla.edu/~tom/gamescourse.html\r\n* \'Interactive Mathematics\':http://www.cut-the-knot.com\r\n* \'Wolfram MathWorld\':http://www.mathworld.wolfram.com\r\n* \'IPSC\':http://ipsc.ksp.sk/',2044,'public',NULL,NULL),('sandbox','Sandbox (cutiuţa cu năsip)','2006-11-11 18:59:57','2009-01-19 10:01:19','h1=. Sandbox (cutiuţa cu năsip)\r\n\r\n\r\n\r\nTabel mic:\r\n\r\ntable{width:60px}. |A|B|A->B|\r\n| 0 |2|3|\r\n\r\nTabel mare:\r\n\r\ntable{width:120px}. |A|B|A->B|\r\n|1|2|3|\r\n\r\nTabel si mai mare:\r\n\r\ntable{width:240px}. |A|B|A->B|\r\n|1|2|3|\r\n\r\nDiacritice:\r\n\r\nStraşnic de îngâmfat, ţăranul crapă streaşina.\r\nStraşnic de îngâmfat, ţăranul crapă streaşina.\r\n\r\nIn Windows XP sp2 cu IE6 fara update de font se vede asa:\r\n!sandbox?diacritice-IE6.jpg!\r\n\r\nOrdered list:\r\n\r\n# 1st item\r\n# 2nd item\r\n\r\nh3. Use only F/OSS, Microsft sucks ;) just because they like design NOT the code itself.\r\n\r\nHowever, on a GNU system NEVER type <b>sudo make me sandwich</b> , and expect the results...\r\n\r\n\r\nx\r\n\r\n ==calendar()==\r\n\r\ny\r\n\r\n* A[1]\r\n* B[2]\r\n* C[3]\r\n\r\np(#fn1). <tex>2^n    * 2^n</tex>\r\n\"Vivi\'s blog\":http://vivi.ro\r\n<tex> d/(2\\\"a)=d/(2\\Omega^2) </tex>\r\n* <tex> d = \\sqrt{(c_{2}-c_{1})^{2} + 1 } </tex>\r\np. <tex> \r\n\\displaystyle \\sigma_{\\lambda} = \r\n	  \\frac{24 \\pi^3}{\\lambda^4 N^2}\r\n	  \\left(\\frac{n^2-1}{n^2+2}\\right)^{\\!2}\r\n</tex> \r\n\r\nAvem suport pentru <tex> \\LaTeX </tex> !\r\n\r\n<tex> \\frac{a^2 - b^2}{a + b} = a - b </tex>\r\n<tex>n! \\approx \\sqrt{2 \\pi n} (\\frac n e) ^n</tex>\r\n\r\n\r\n==Include(page=\"template/implica-te/scrie-articole\" user_id=\"domino\")==\r\n\r\np(#fn2). | test | test |\r\n\r\n\"User macro bug\":sandbox/usermacrobug\r\n\r\n*Worship me*\r\n\r\nFeel free to plghay around, but \'Big Brother\':/changes is watching you.\r\n\r\nTralalalala cu capsunele pe campii si elefanti pe pulele marete si ciupercute si bomboane.\r\n\r\n\'codetest\':sandbox/code-test\r\n\r\nWhat does \'this\':sandbox?action=edit button do?\r\n\r\nlalallaa\r\n\r\nIntrebare: cum poti seta culoarea cu care scrii?\r\nUite asa: %{color:violet}scris cu rosu%\r\n\r\nSiteul sub IE 7 -- vezi \'pagina dedicata\':ia_in_ie7\r\n\r\nSiteul sub FF 2 - -mica problema panoul de \'editeaza\', \'vezi istoria\', \'sterge\' etc (in IE7 panoul nu se suprapune)-\r\n!sandbox?IA_bug_in_FF2.jpg!\r\n\r\n[test]\r\n*OMG* test, good work people :D\r\nAcuma doar trebuie putin stimulata comunitatea\r\n[/test]\r\n\r\nInteresting choice of words.\r\na very bold **MAN**\r\n_CAPSOMANII-I DESPISE THEM_\r\n\r\ngasise pe-un teren viran,\r\nun geamantan.\r\n\r\nsi-n geamantan,\r\nun pachet.\r\n\r\nsi in pachet,\r\nun pachetel gasise el.\r\n\r\nsi-n pachetel,\r\nalt pachetel.\r\n\r\nsi-un pachetel in pachetel,\r\nlegat cu funde elegante.\r\n\r\nsi-n pachetel...vreo 40 de diamante...\r\n...\r\nAdio voi...va las si plec fiindca mi-e dor...\r\nsi a plecat Apolodor\r\n!!!<>\r\n\r\ntralalala blablabla lala\r\n\r\n_salut, aici poate sa scrie oricine ce vrea?_ ~Robert~\r\n\r\n|_. 1|_. 2|_. 3|\r\n|unu|doi|trei|\r\n|1... unu|2... doi|3... trei|\r\n\r\nMoraru Ionut has been here. :))\r\n\r\n:) gosh...\r\n\r\ninca unul, de tipul cel mai         heyyyyyyyyyy prost din corcodus, se joaca cu  in nisip.. ura ...\r\ncel mai prost din corcodus a terminat... altcineva?:D\r\ntot el: atentie fratilor ne urmareste big brother 3 (sau 4)\r\n\r\n== code(cpp) |\r\n// comentariu\r\n#include <cstdio> // comment1\r\n// comment2\r\n\r\nint main()\r\n{\r\n    return 0;\r\n}\r\n==\r\n\r\nEu vreau să scriu cu ŢŢŢŢŢ dublu ţ mic şi tripul Ţ mare! Iată un Ţ ţŢŞ ! Are virgulă sau sedilă?',1792,'public',NULL,NULL),('sandbox','Sandbox (cutiuţa cu năsip)','2006-11-11 18:59:57','2009-01-19 10:01:55','h1=. Sandbox (cutiuţa cu năsip)\r\n\r\n\r\n\r\nTabel mic:\r\n\r\ntable{width:60px}. |A|B|A->B|\r\n{|0|2|3|}\r\n\r\nTabel mare:\r\n\r\ntable{width:120px}. |A|B|A->B|\r\n|1|2|3|\r\n\r\nTabel si mai mare:\r\n\r\ntable{width:240px}. |A|B|A->B|\r\n|1|2|3|\r\n\r\nDiacritice:\r\n\r\nStraşnic de îngâmfat, ţăranul crapă streaşina.\r\nStraşnic de îngâmfat, ţăranul crapă streaşina.\r\n\r\nIn Windows XP sp2 cu IE6 fara update de font se vede asa:\r\n!sandbox?diacritice-IE6.jpg!\r\n\r\nOrdered list:\r\n\r\n# 1st item\r\n# 2nd item\r\n\r\nh3. Use only F/OSS, Microsft sucks ;) just because they like design NOT the code itself.\r\n\r\nHowever, on a GNU system NEVER type <b>sudo make me sandwich</b> , and expect the results...\r\n\r\n\r\nx\r\n\r\n ==calendar()==\r\n\r\ny\r\n\r\n* A[1]\r\n* B[2]\r\n* C[3]\r\n\r\np(#fn1). <tex>2^n    * 2^n</tex>\r\n\"Vivi\'s blog\":http://vivi.ro\r\n<tex> d/(2\\\"a)=d/(2\\Omega^2) </tex>\r\n* <tex> d = \\sqrt{(c_{2}-c_{1})^{2} + 1 } </tex>\r\np. <tex> \r\n\\displaystyle \\sigma_{\\lambda} = \r\n	  \\frac{24 \\pi^3}{\\lambda^4 N^2}\r\n	  \\left(\\frac{n^2-1}{n^2+2}\\right)^{\\!2}\r\n</tex> \r\n\r\nAvem suport pentru <tex> \\LaTeX </tex> !\r\n\r\n<tex> \\frac{a^2 - b^2}{a + b} = a - b </tex>\r\n<tex>n! \\approx \\sqrt{2 \\pi n} (\\frac n e) ^n</tex>\r\n\r\n\r\n==Include(page=\"template/implica-te/scrie-articole\" user_id=\"domino\")==\r\n\r\np(#fn2). | test | test |\r\n\r\n\"User macro bug\":sandbox/usermacrobug\r\n\r\n*Worship me*\r\n\r\nFeel free to plghay around, but \'Big Brother\':/changes is watching you.\r\n\r\nTralalalala cu capsunele pe campii si elefanti pe pulele marete si ciupercute si bomboane.\r\n\r\n\'codetest\':sandbox/code-test\r\n\r\nWhat does \'this\':sandbox?action=edit button do?\r\n\r\nlalallaa\r\n\r\nIntrebare: cum poti seta culoarea cu care scrii?\r\nUite asa: %{color:violet}scris cu rosu%\r\n\r\nSiteul sub IE 7 -- vezi \'pagina dedicata\':ia_in_ie7\r\n\r\nSiteul sub FF 2 - -mica problema panoul de \'editeaza\', \'vezi istoria\', \'sterge\' etc (in IE7 panoul nu se suprapune)-\r\n!sandbox?IA_bug_in_FF2.jpg!\r\n\r\n[test]\r\n*OMG* test, good work people :D\r\nAcuma doar trebuie putin stimulata comunitatea\r\n[/test]\r\n\r\nInteresting choice of words.\r\na very bold **MAN**\r\n_CAPSOMANII-I DESPISE THEM_\r\n\r\ngasise pe-un teren viran,\r\nun geamantan.\r\n\r\nsi-n geamantan,\r\nun pachet.\r\n\r\nsi in pachet,\r\nun pachetel gasise el.\r\n\r\nsi-n pachetel,\r\nalt pachetel.\r\n\r\nsi-un pachetel in pachetel,\r\nlegat cu funde elegante.\r\n\r\nsi-n pachetel...vreo 40 de diamante...\r\n...\r\nAdio voi...va las si plec fiindca mi-e dor...\r\nsi a plecat Apolodor\r\n!!!<>\r\n\r\ntralalala blablabla lala\r\n\r\n_salut, aici poate sa scrie oricine ce vrea?_ ~Robert~\r\n\r\n|_. 1|_. 2|_. 3|\r\n|unu|doi|trei|\r\n|1... unu|2... doi|3... trei|\r\n\r\nMoraru Ionut has been here. :))\r\n\r\n:) gosh...\r\n\r\ninca unul, de tipul cel mai         heyyyyyyyyyy prost din corcodus, se joaca cu  in nisip.. ura ...\r\ncel mai prost din corcodus a terminat... altcineva?:D\r\ntot el: atentie fratilor ne urmareste big brother 3 (sau 4)\r\n\r\n== code(cpp) |\r\n// comentariu\r\n#include <cstdio> // comment1\r\n// comment2\r\n\r\nint main()\r\n{\r\n    return 0;\r\n}\r\n==\r\n\r\nEu vreau să scriu cu ŢŢŢŢŢ dublu ţ mic şi tripul Ţ mare! Iată un Ţ ţŢŞ ! Are virgulă sau sedilă?',1792,'public',NULL,NULL),('probleme-de-acoperire-2','Probleme de acoperire (partea a II-a)','2008-11-15 18:53:30','2008-12-12 23:06:03','h1. Probleme de acoperire (partea a II-a)\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"marius\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 37em}*{text-align:center} *Conţinut:*\r\n* \'Problema 1 &#40;TC MagicBoxes&#41;\':probleme-de-acoperire-2#problema1\r\n* \'Problema 2 &#40;IOI 2001 Pavement&#41;\':probleme-de-acoperire-2#problema2\r\n* \'Problema 3 &#40;ACM ICPC 1997&#41;\':probleme-de-acoperire-2#problema3\r\n* \'Problema 4 &#40;SGU Hardwood Floor&#41;\':probleme-de-acoperire-2#problema4\r\n* \'Problema 5 &#40;TC CaseysArt&#41;\':probleme-de-acoperire-2#problema5\r\n* \'Problema 6 &#40;SGU Another chocolate maniac&#41;\':probleme-de-acoperire-2#problema6\r\n* \'Problema 7 &#40;CEOI 2002 Bugs&#41;\':probleme-de-acoperire-2#problema7\r\n* \'Problema 8 &#40;Lot 2001, SGU Domino, IPSC 2004, Algoritmus 2005, IOI 2005&#41;\':probleme-de-acoperire-2#problema8\r\n* \'Aplicaţii\':probleme-de-acoperire-2#aplicatii\r\n* \'Bibliografie\':probleme-de-acoperire-2#bibliografie\r\n\r\nSubiectul acestui articol sunt acoperirile in plan, cu o abordare bazată pe tehnici de programare. În \"$...secţiunea precedentă$\":probleme-de-acoperire-1 am studiat problemele de acoperire care nu necesită cunoştinţe avansate de algoritmi.\r\n\r\nh2(#problema1). Problema 1 (\'TC MagicBoxes\':http://www.topcoder.com/stat?c=problem_statement&pm=932)\r\n\r\nbq. Să se determine numărul $N$ maxim astfel ca într-un dreptunghi de dimensiuni $L x W (1 &le; L, W &le; 30)$ să poată fi dispuse paralel cu axele de coordonate $N$ pătrate de laturi $1, 2, ..., N$ astfel ca oricare două pătrate să nu aibă porţiuni care se suprapun.\r\n\r\nh3. Soluţie:\r\n\r\nAceastă problemă, deşi clasică, este dificil de rezolvat în cazul general şi singura abordare a ei este aceea de a folosi metoda $backtracking$. \r\n\r\nÎntâi putem stabili o limită superioară a numarului $N$: este evident că $N &le; W, N &le; L$ şi că $1^2^ + 2^2^ + ... + N^2^ &le; L x W$. Putem porni cu $N$ de la limita superioară dată de aceste inegalităţi şi să încercăm să dispunem cele $N$ pătrate în interiorul dreptunghiului. O optimizare simplă care ne-ar fi ajutat să rezolvăm problema, precalculând toate rezultatele, ar fi fost să punem în dreptunghi pătratele în ordinea descrescătoare a înălţimii. Altă observaţie ce reduce timpul de execuţie este că piesa cea mai mare nu trebuie pusă în toate poziţiile posibile, ci într-un sfert din ele, din cauza soluţiilor simetrice, iar între ea şi margine nu trebuie lăsat spaţiu puţin pentru că acela va rămâne nefolosit. Observaţia care ne-ar fi dus la o soluţie care să rezolve un test în două secunde, cât era limita de timp în concurs, este că procedura $backtracking$ pierde mult timp pentru verificarea dacă o piesă poate fi pusă pe o anumită poziţie. Dacă în loc de reprezentarea pe matrice folosim $L$ întregi, astfel ca bitul al $j$-lea din întregul $i$ sa fie $1$ dacă celula $(i, j)$ este deja ocupată şi $0$ altfel, vom putea verifica dacă pătratul de latură $i$ poate fi plasat pe o anumită poziţie în $i$ paşi, şi nu în $i^2^$ paşi ca înainte.\r\n\r\nAceastă reprezentare pe biţi este foarte utilă în probleme de acest gen, şi cum avem întregi de $64$ de biţi pe care îi putem folosi, avem o metodă foarte simplă de reprezentare a tablelor de mărime până la $64$.\r\n\r\nh2(#problema2). Problema 2 (IOI 2001 Pavement)\r\n\r\nbq. Se dă o matrice de dimensiuni $N x M (1 &le; N &le; 7 şi 1 &le; M &le; 100)$. Unele celule ale acestei matrici sunt distruse şi trebuie acoperite cu piese de forma din $Fig. 1$. Fiecare celulă rămasă neacoperită se consideră o greşeală, iar dacă o piesă cu care am acoperit celule distruse a trebuit să fie tăiată pentru a acoperi numai celule distruse, fiecare pătrăţel din partea nefolosită a piesei este considerată o greşeală. Se cere acoperirea tablei astfel ca numărul de greşeli să fie minimizat. În $Fig. 2$, pentru prima tablă, acoperirea optimă are două greşeli, aşa cum vedem în al doilea desen.\r\n\r\np=. _Fig. 1_ !probleme-de-acoperire-2?P221.jpg!       _Fig. 2_ !probleme-de-acoperire-2?P222.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nAşa cum am zis şi în articolul anterior, problemele de acoperire sunt în general $NP-complete$, deci prima idee ar fi să încercăm o rezolvare prin metoda $backtracking$, dar dimensiunile datelor de intrare ne arată că o asemenea rezolvare nu ne rezolvă problema.\r\n\r\nStrategii polinomiale de tip $greedy$ sau de tip $programare dinamică$ nu vor rezolva această problemă pe toate cazurile de intrare, şi pentru orice strategie se poate găsi câte un contraexemplu. Totuşi vom putea să folosim o rezolvare bazată pe combinarea tehnicilor de $programare dinamică$ şi $backtracking$. Să vedem cum.\r\n\r\nConstruim soluţia optimă coloană cu coloană, dar este evident din următorul exemplu că pentru a construi soluţia optimă pentru coloana $j + 1$ nu este de ajuns să acoperim optim primele $j$ coloane.\r\n\r\np=. !probleme-de-acoperire-2?P223.jpg!\r\n\r\nEvident soluţia optimă pe primele trei coloane ale tablei foloseşte piesa în formă de cruce şi se obţine o acoperire cu $0$ greşeli, dar când vrem să acoperim toate $4$ coloanele tablei folosind prima acoperire obţinem o tablă cu $2$ greşeli, iar folosind două piese de tipul doi orientate înspre stânga, obţinem o acoperire cu o singură greşeală.\r\n\r\nPentru a obţine o soluţie cu $j + 1$ coloane ne trebuie toate soluţiile cu $j$ coloane la care ştim configuraţia coloanelor $j – 1$ şi $j$ (o piesă poate influenţa configuraţia a cel mult trei coloane). De aici se conturează ideea de a folosi un tablou $best$ unde $best[j][config1][config2]$ conţine numărul minim de greşeli astfel încât coloana $j$ are pătratele rămase neacoperite date de mulţimea $config1$, iar coloana $j - 1$ are pătratele neacoperite date de mulţimea $config2$. Pentru a trece de la $j$ la $j + 1$, facem un $backtracking$ pe o tablă de trei coloane dintre care prima are pătrăţelele ocupate date de $config2$, a doua pătrăţelele ocupate date de $config1$, iar a treia nu are nici un pătrăţel ocupat. După ce am plasat în procedura $backtracking$ nişte piese ajungem la configuraţiile pentru coloane date de mulţimile $c1 c2 c3$ şi actualizăm dacă am obţinut un număr mai mic pe $best[j + 1][c3][c2]$. În procedura recursivă ţinem cont atunci când vom acoperi cu piese un pătraţel deja acoperit sau un pătraţel ce nu este stricat. Ambele mulţimi $config1$ şi $config2$ pot fi reprezentate cu biţii unui întreg, $N$ fiind mic, astfel: primii $7$ biţi ai unui întreg vor reprezenta elementele primei mulţimi iar următorii $7$ biţi elementele celei de a două mulţimi. Memoria folosită de algoritmul nostru are ordinul de complexitate $O(M * 4^N^)$, acesta putând fi uşor micşorat la $O(4^N^)$ pentru că la pasul $j + 1$ avem nevoie numai de linia $j$ a matricii. Pentru a reduce numărul de stări folosite ne vom folosi de observaţia că putem să facem o restricţie asupra acoperirilor, aceea că atunci când ajungem la coloana $j$ orice piesă nouă amplasată trebuie să acopere cel puţin un pătrăţel neacoperit de pe coloana $j – 1$. Fie $newBest[j][config12]$ structura care păstrează cele mai bune acoperiri cu această restricţie. Atunci soluţia optimă va fi în $newBest[M + 1]$ unde am considerat o nouă coloană $M + 1$ a tablei ce nu are niciun pătrăţel stricat. Pentru tablele astfel acoperite, configuraţiile ultimelor două pătrăţele de pe o linie sunt de forma: $11$ şi $10$ şi $00$, configuraţia $01$ nu apare pentru că este evident că nu există o piesă care să acopere un pătrat din ultima coloană, un pătrat cu două coloane înainte şi să nu acopere pătratul imediat în stânga pătratului de pe ultima linie. Astfel avem $O(3^N^)$ configuraţii posibile pentru ultimele două coloane. Mai există multe configuraţii de două coloane la care nu se poate ajunge folosind piesele din problemă, dar o analiză exactă ar fi dificilă şi probabil ar complica inutil implementarea. Să vedem cum arată configuraţiile pe un exemplu:\r\n\r\np=. !probleme-de-acoperire-2?P224.jpg!\r\n\r\nPutem reprezenta această acoperire astfel:\r\n\r\np=. **00010**\r\n**01110**\r\n**11110**\r\n**00011**\r\n\r\nIar ultimele două coloane arată în felul următor:\r\n\r\np=. **10**\r\n**10**\r\n**10**\r\n**10**\r\n**11**\r\n\r\nÎn acest caz $config$ are valoarea $1 * 3^0^ + 1 * 3^1^ + 1 * 3^2^ + 1 * 3^3^ + 2 * 3^4^ = 202$. Acum, la fiecare pas vrem să punem pe coloana $j – 1$ câte o piesă pentru a obţine rezultatele pentru $newBest[j + 1]$, sau să nu punem o piesă acolo. Avem $9$ posibilităţi de a pune piese (fiecare rotaţie şi reflexie a pieselor din problemă) şi posibilitatea de a nu pune piesă în pătrăţelul curent, deci în total $10$ posibilităţi. Astfel, complexitatea algoritmului nostru devine $O(M * 3^N^ * 10^N^)$, dar constanta din faţă este subunitară (mult mai mică decât 1) din cauză că nu vom trece prin stări imposibile.\r\n\r\nh2(#problema3). Problema 3 (ACM ICPC 1997)\r\n\r\nbq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $N x M (N &le; 15, M &le; 15)$ cu dominouri.\r\n\r\nh3. Soluţie:\r\n\r\nAm văzut în \'partea I a articolului\':probleme-de-acoperire-1 că există o formulă pentru acest număr. Abordarea matematică poate fi generalizată şi pentru mai multe probleme asemănătoare de acoperire, dar cunoştinţele necesare sunt avansate, deci această abordare nu ne prea ajută pe noi ca informaticieni.\r\n\r\nO soluţie care ne va da numărul exact şi ar fi putut fi folosită în concurs este asemănătoare celei expuse mai sus. Vom folosi o combinaţie a metodei $backtracking$ cu metoda $programării dinamice$. Tabloul $numWays[i][config]$ va fi numărul de posibilităţi de a acoperi complet primele $i - 1$ coloane ale unei table, iar pe coloana $i$ pătratele ocupate să fie reprezentate de $config$. Astfel, $numWays[i + 1][config1]$ va fi egal cu suma de $numWays[i][config]$, unde putem acoperi cu dominouri două coloane astfel ca pe prima coloană să fie acoperite toate celulele, în afara celor date de $config$, iar pe a doua coloană să fie acoperite celulele date de $config1$. De exemplu, starea dată de $(4, 100100)$ este prezentată în următoarea figură:\r\n\r\np=. !probleme-de-acoperire-2?P231.jpg!\r\n\r\nDacă algoritmul pune trei dominouri pe liniile $4$ şi $5$ aşa cum vedem mai sus, atunci vom trece în starea $(5, 011000)$. La final, vom returna valoarea aflată în $numWays[N + 1][&#48;]$. Complexitatea ca timp a acestei rezolvări este $O(M * 4^N^)$, iar ca spaţiu $O(2^N^)$.\r\n\r\nh2(#problema4). Problema 4 (\'SGU Hardwood Floor\':http://acm.sgu.ru/problem.php?contest=0&problem=131)\r\n\r\nbq. Determinaţi numărul de acoperiri ale unei table de dimensiuni $N x M (1&le; N &le; 9, 1 &le; M &le; 9)$ cu piese de tipul:\r\n\r\np=. !probleme-de-acoperire-2?P241b.jpg!\r\n\r\nExemplu: Pentru $N = 3$ şi $M = 2$ avem $5$ acoperiri posibile.\r\n\r\nh3. Soluţie:\r\n\r\nÎn rezolvare putem folosi direct ideea de la problema anterioară.\r\n\r\nh2(#problema5). Problema 5 (\'TC CaseysArt\':http://www.topcoder.com/stat?c=problem_statement&pm=1706)\r\n\r\nbq. Determinaţi numărul de moduri în care poate fi acoperit un dreptunghi de dimensiuni $N x M (N &le; 18, M &le; 15)$ cu piese de forma:\r\n\r\np=. !probleme-de-acoperire-2?P251.jpg!\r\n\r\nDe exemplu, pentru $N = 3, M = 4$ avem următoarele acoperiri:\r\n\r\np=. !probleme-de-acoperire-2?P252.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nDin nou, ideea de rezolvare este cea prezentată în \'$Problema 2$\':probleme-de-acoperire-2#problema2. Complexitatea soluţiei este $O(N * 4^M^)$, dar trebuie să fim conştienţi că aceasta este o limită superioară mult mai mare decât complexitatea reală. Să vedem şi implementarea unei asemenea soluţii:\r\n\r\n== code(java) |\r\nimport java.util.*;\r\n\r\npublic class CaseysArt {\r\n    double[][] num;\r\n    int step, w;\r\n    int[][][] p = {{{0, 1}, {1, 1}},\r\n        {{1, 0},{1, 1}},\r\n        {{1, 1},{0, 1}},\r\n        {{1, 1},{1, 0}}};\r\n    int[][] sol;\r\n\r\n    void checksol() {\r\n        int config = 0, config1 = 0;\r\n        for (int i = 0; i < w; i++) {\r\n            if (sol[i][0] == 0) config |= (1 << i);\r\n            if (sol[i][1] == 1) config1 |= (1 << i);\r\n        }\r\n        num[1 ^ step][config1] += num[step][config];\r\n    }\r\n\r\n    void doit(int x) {\r\n        if (x == w)\r\n            checksol();\r\n        else {\r\n            if (x < w - 1) {\r\n                int i, j, k;\r\n                boolean bool;\r\n\r\n                for (k = 0; k < 4; k++) {\r\n                    bool = true;\r\n                    for (i = 0; i < 2; i++) {\r\n                        for (j = 0; j < 2; j++) {\r\n                            if (p[k][i][j] == 1)\r\n                                bool = bool && (sol[x + i][j] == 0);\r\n                        }\r\n                    }\r\n\r\n                    if (bool) {\r\n                        for (i = 0; i < 2; i++) {\r\n                            for (j = 0; j < 2; j++) {\r\n                                if (p[k][i][j] == 1)\r\n                                    sol[x + i][j] = 1;\r\n                            }\r\n                        }\r\n                        doit(x + 1);\r\n                        for (i = 0; i < 2; i++) {\r\n                            for (j = 0; j < 2; j++) {\r\n                                if (p[k][i][j] == 1)\r\n                                    sol[x + i][j]=0;\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            doit(x+1);\r\n        }\r\n    }\r\n\r\n    public double howManyWays(int l, int w) {\r\n        num = new double[2][1 << w];\r\n        this.w = w;\r\n        num[0][0] = 1;\r\n        step = 0;\r\n        sol = new int[w][2];\r\n        for (int i = 1; i < l; i++) {\r\n            Arrays.fill(num[1 ^ step], 0);\r\n            doit(0);\r\n            step ^= 1;\r\n        }\r\n        return num[step][(1 << w) - 1];\r\n    }\r\n}\r\n==\r\n\r\nÎn $num[i][config]$ ţinem minte câte posibilităţi sunt să acoperim $i - 1$ linii cu piesele date în problemă, iar linia $i$ să fie ocupată aşa cum arată reprezentarea în baza $2$ a numărului întreg $config$. Se observă folosirea variabilei $step$ care de la un pas la altul se transformă astfel: $step &#94;= 1$. Acest mic truc ne face să putem folosi o matrice de doar $2$ linii în loc să folosim $N$ linii. La momentul $i$, în $num[step][config]$ avem informaţia ce ar fi fost în mod normal în $num[i][config]$, iar în $num[1 &#94; step][config1]$ vom calcula ce ar fi fost normal în $num[i + 1][config1]$. În şirul $p$ ţinem minte forma pieselor din problemă.\r\n\r\nÎn procedura $doit$ punem pe două linii consecutive piese în toate modurile posibile. Această procedură face ca pe prima linie să avem o configuraţie de pătrăţele libere $config$, iar pe a doua o configuraţie de pătrăţele ocupate $config1$. Dacă pătrăţelele reprezentate de $config$ nu au fost ocupate la pasul curent ele trebuie să fi fost ocupate la pasul anterior. Astfel, pentru fiecare pereche de configuraţii $config$ şi $config1$ trebuie să efectuăm operaţia $num[i + 1][config1] += num[i][config]$.\r\n\r\nDacă această rezolvare ar fi fost folosită în timpul concursului, ea ar fi ieşit din timp. Pentru optimizare putem face mai multe îmbunătăţiri. Un exemplu ar fi să generăm direct cele două configuraţii de biţi în procedura $backtracking$ şi să nu mai folosim şirul $sol$. O altă idee care ar fi dus la rezolvarea problemei în timpul concursului ar fi fost calcularea tuturor rezultatelor posibile şi trimiterea unei soluţii care returna aceste rezultate precalculate. Această abordare ar fi fost posibilă pentru că numărul de configuraţii iniţiale este mic.\r\n\r\nh2(#problema6). Problema 6 (\'SGU Another chocolate maniac\':http://acm.sgu.ru/problem.php?contest=0&problem=132)\r\n\r\nbq. Se dă o tablă de dimensiuni $M x N (1 &le; M &le; 70, 1 &le; N &le; 7)$ cu unele pătrate lipsă. Se cere numărul minim de dominouri ce pot fi plasate pe tablă fară să se suprapună între ele sau să acopere vreun pătrat ce nu aparţine tablei, astfel ca nici o altă piesă de domino să nu se poată adăuga la configuraţie fără ca aceasta să se suprapună peste una veche. Pentru tabla următoare vedem uşor în a doua figură că soluţia optimă va conţine 4 dominouri.\r\n\r\np=. !probleme-de-acoperire-2?P261.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nDin nou vom folosi $metoda programării dinamice$ îmbinată cu metoda $backtracking$. \r\n\r\nVom umple tabla linie cu linie şi la fiecare pas putem pune dominouri orizontale pe linia curentă şi verticale pe linia curentă şi linia următoare. Trebuie să fim atenţi când trecem de la linia curentă la următoarea să nu lăsăm pe linia curentă loc liber unde poate fi amplasat un domino orizontal, pentru că acest loc nu va putea fi ocupat de piese amplasate mai târziu. Se poate lăsa spaţiu gol pe linia curentă şi linia următoare pentru că o celulă a acestei poziţii va putea fi acoperită la pasul următor. Vedem astfel că dacă linia curentă este linia $i$ atunci avem trei stări posibile pentru ultimele două pătrăţele de pe fiecare coloană: $00$ (celule neocupate), $10$ (penultima celulă ocupată şi ultima goală), $11$ (ambele celule ocupate de dominouri). Starea $01$ nu poate exista. În procedura $backtracking$ care generează configuraţiile la care putem ajunge de la o configuraţie dată trebuie să mai avem grijă să nu ocupăm cu un domino o celulă ce nu aparţine tablei. Astfel, pentru a găsi soluţia problemei vom folosi un tablou $min[i][config]$ care va păstra numărul minim de dominouri care trebuie amplasate pe tablă astfel ca pe liniile $1, 2, ..., i - 1$ să nu poată fi amplasat vreun domino pe celulele rămase goale, iar $config$ va fi un număr întreg care atunci când e transformat în baza $3$ arată configuraţia liniilor $i - 1$ şi $i$.\r\n\r\nLa fiecare pas, procedura $backtracking$ alege dacă să pună un domino orizontal, unul vertical sau să treacă mai departe, deci o limită superioară ar fi $O(3^M^)$ operaţii (nu toate configuraţiile vor fi posibile). În tablou avem $N x 3^M^$ stări, deci complexitatea algoritmului este $O(N * 9^M^)$. Menţionăm din nou că aceasta este o limită superioară şi că algoritmul se va comporta mult mai bine în practică.\r\n\r\nh2(#problema7). Problema 7 (\'CEOI 2002 Bugs\':http://acm.pku.edu.cn/JudgeOnline/problem?id=1038)\r\n\r\nbq. Să se acopere o tablă de dimensiuni $M x N (1 &le; M &le; 10, 1 &le; N &le; 150)$ cu un număr maxim de piese de dimensiuni $3 x 2$ şi $2 x 3$. Tabla are unele celule ce trebuie să nu fie acoperite, iar oricare două piese nu se pot suprapune. Pentru tabla de mai jos, numărul maxim de piese cu care se poate acoperi este $3$.\r\n\r\np=. !probleme-de-acoperire-2?P272.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nEvident, putem încerca o soluţie identică cu cea a \'$Problemei 1$\':probleme-de-acoperire-2#problema1, dar aici limitele sunt puţin mai mari şi avem nevoie de un algoritm mai eficient.\r\n\r\nExistă o rezolvare de complexitate $O(N * M * 3^M^)$ care, aşa cum deja v-aţi obişnuit, combină metoda $backtracking$ cu metoda $programării dinamice$. Folosim un tablou $max[N][M + 1][3^(M + 1)^]$ care conţine numărul maxim de dale puse pentru o anumită stare. Fiecare element al matricii va fi iniţial egal cu $0$. Iterăm rândurile în ordinea $1 ... N$, coloanele în ordinea $1 ... M$ şi configuraţiile în ordine lexicografică. Când vom procesa starea reprezentată de parametrii $(i, j, config)$ vom decide dacă punem una dintre piese cu colţul din stânga sus în $(i, j)$ sau dacă lăsăm celula $(i, j)$ liberă. O stare $(i, j, config)$ se referă la un pătrăţel din matrice şi la o bandă „activă” de pătrăţele ce are lăţimea $2$. Banda conţine celulele $(i1, j + 1), (i1, j + 2)$ pentru $i1 < i$ şi celulele $(i2, j), (i2, j + 1)$ pentru $i &le; i2$. Cifrele în baza $3$ ale parametrului $config$ ne spun starea perechilor de pătrate de pe banda activă: $00$ este reprezentat în $config$ de cifra $0$, $10$ de cifra $1$ şi $11$ de cifra $2$ (configuraţia $01$ nu poate apărea). De exemplu, starea $(4, 3, 1000212)$ va reprezenta configuraţia prezentată în următoarea imagine (ultima cifră corespunde primei perechi de pătrăţele, penultima cifră celei de-a doua perechi ş.a.m.d.):\r\n\r\np=. !probleme-de-acoperire-2?P273.jpg!\r\n\r\nDacă decidem să nu punem piesă în pătrăţelul $(4, 3)$ atunci din starea $(4, 3, 1000212)$ trecem în starea $(5, 3, 1000212)$.\r\n\r\np=. !probleme-de-acoperire-2?P274.jpg!\r\n\r\nDacă punem o piesă verticală ajungem în starea $(7, 3, 1111212)$.\r\n\r\np=. !probleme-de-acoperire-2?P275.jpg!\r\n\r\nIar dacă punem o piesă orizontală atunci ajungem în starea $(6, 3, 1022212)$.\r\n\r\np=. !probleme-de-acoperire-2?P276.jpg!\r\n\r\nTablei îi adăugăm la sfârşit o coloană pe care nu pot fi aşezate piese. Rezultatul cerut de problemă se va afla în $max[N][M + 1][&#48;]$. Menţionăm că problemele \'$2$\':probleme-de-acoperire-2#problema2, \'$3$\':probleme-de-acoperire-2#problema3 şi \'$4$\':probleme-de-acoperire-2#problema4 pot fi rezolvate în mod asemănător în complexitate $O(N * M * 2^M^)$.\r\n\r\nh2(#problema8). Problema 8 (Lot 2001, \'SGU Domino\':http://acm.sgu.ru/problem.php?contest=0&problem=101, \'IPSC 2004\':http://ipsc.ksp.sk/contests/ipsc2004/practice/problems/t.php, Algoritmus 2005, IOI 2005)\r\n\r\nbq. Se dă o tablă de dimensiuni $N x M$, din care unele pătrate sunt eliminate. Se cere să se determine o acoperire a tablei cu număr maxim de dominouri $(1 &le; N, M &le; 200)$. De exemplu, o tablă ce nu are nicio celulă eliminată, de $3 x 3$ pătrăţele, poate fi acoperită cu cel mult $4$ dominouri care nu se suprapun. O soluţie posibilă este prezentată în a doua figură.\r\n\r\np=. !probleme-de-acoperire-2?P281.jpg!\r\n\r\nh3. Soluţie:\r\n\r\nAceasta este o problemă celebră, sau aşa se pare după numărul de concursuri în care a fost folosită, şi este o generalizare a unei probleme din \'articolul precedent\':probleme-de-acoperire-1.\r\n\r\nPrima idee ar fi să încercăm o abordare $greedy$ şi să punem piese pe tablă într-o ordine oarecare cât timp mai este loc. Dar putem găsi uşor contraexemple pentru acest tip de abordare. Limitele sunt mult prea mari pentru ca o rezolvare bazată pe $programare dinamică$ combinată cu $backtracking$ să meargă. O idee ce am utilizat-o în articolul anterior ne va fi folositoare şi aici. Colorăm tabla noastră în mod asemănător unei table de şah şi numerotăm pătrăţelele tablei.\r\n\r\np=. !probleme-de-acoperire-2?P282.jpg!\r\n\r\nAcum vedem că un domino amplasat pe tablă trebuie să ocupe o celulă colorată alb şi una negru, celule care sunt adiacente. Dacă realizăm un graf în care nodurile sunt celulele, iar între două noduri există muchie dacă ele sunt adiacente vertical sau orizontal pe tablă, observăm că graful este bipartit. O acoperire cu dominouri corespunde în acest graf unei mulţimi de muchii pentru care nu există două muchii cu acelaşi capăt (o muchie corespunde amplasării posibile a unui domino, iar restricţia menţionată face să nu existe dominouri care se suprapun). Deci pentru a găsi o soluţie maximală pentru problema iniţială, trebuie să găsim o mulţime de muchii neadiacente de cardinal maxim. În acest mod am transformat cerinţa într-o problemă clasică de teoria grafurilor cunoscută sub numele de $cuplaj maxim într-un graf bipartit$. Vedem în imaginea următoare cum a fost transformată tabla într-un graf şi cum soluţia prezentată în exemplu corespunde unui $cuplaj maxim$ în graful asociat tablei.\r\n\r\np=. !probleme-de-acoperire-2?P283.jpg!\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\n* \'Pavare\':problema/pavare, info{_arena_}\r\n* \'Choco\':problema/choco, info{_arena_}\r\n* \'Little Kings\':http://acm.sgu.ru/problem.php?contest=0&problem=223, SGU\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* [1] \"IOI\'01 Competition\":http://olympiads.win.tue.nl/ioi/ioi2001/contest/A-2001-7.pdf\r\n* [2] \"CEOI\'02 Competition material\":http://ics.upjs.sk/ceoi/\r\n* [3] \'SGU\':http://acm.sgu.ru\r\n* [4] \'TopCoder\':http://www.topcoder.com/tc\r\n\r\nh2. Discuţii pe forum',2044,'public',3384,NULL),('newsletter/winter-challenge-2008/runda-2','Winter Challenge, Runda 2 - antrenament inainte de OJI','2008-02-22 12:47:59','2008-02-22 16:08:22','Buna, %full_name%!\r\n\r\nTe invit sa participi la a doua (si ultima) runda a concursului\r\nWinter Challenge.\r\n\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Runda 2 se desfasoara...\r\n\r\n    Duminica, 24 februarie 2008, orele 09:00 - 12:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\r\nSe apropie OJI.  Runda aceasta este o ocazie buna de antrenament!\r\n\r\nVezi pagina concursului: %url_infoarena%winter-challenge-2008\r\nca sa afli cum poti participa.\r\n\r\nSucces!\r\n\r\n\r\n== Atentie! Concurs cu rating! ==\r\n\r\nDaca vrei sa ti se modifice rating-ul in urma acestei runde\r\ntrebuie sa iti anunti participarea din timp.  Intra pe\r\n%url_infoarena%winter-challenge-2008 si inscrie-te la Runda 2.\r\n\r\nPoti sa participi la concurs chiar si daca nu te-ai inscris in\r\nprealabil insa nu ti se va modifica rating-ul.\r\n%your_rating_is%\r\nCiteste despre rating: %url_infoarena%documentatie/rating.\r\n\r\n\r\n== Despre Winter Challenge, Runda 2 ==\r\n\r\nDe data aceasta vei primi doua probleme de dificultate comparabila\r\ncu cele de la Olimpiada Judeteana de Informatica.\r\nTimpul de lucru este de 3h.\r\n\r\nOrganizatorii rundei 2 sunt:\r\n\r\n    Bogdan A. Stoica\r\n    [ %url_infoarena%/utilizator/fireatmyself ]\r\n\r\n    Andrei Grigorean\r\n    [ %url_infoarena%/utilizator/wefgef ]\r\n\r\n    Airinei Adrian\r\n    [ %url_infoarena%/utilizator/astronomy ]\r\n\r\n\r\n== Prima data la infoarena? ==\r\n\r\nDespre infoarena: %url_infoarena%despre-infoarena\r\nPrezentare infoarena: %url_infoarena%prezentare\r\nTutorial infoarena: %url_infoarena%documentatie/tutorial\r\n\r\n\r\nRamai alaturi de noi.  Te ajutam sa devii olimpic!\r\nEchipa infoarena iti ureaza succes!\r\n\r\n\r\n== Mesaj nesolicitat? ==\r\n\r\nEsti inscris pe %url_infoarena% cu numele\r\n\"%full_name%\", utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\r\nDaca nu mai doresti instiintari, da click pe acest link:\r\n%url_unsubscribe%\r\n',13,'protected',NULL,NULL),('newsletter/autumn-warmup-2007/runda-1','Autumn Warm-Up, Runda 1; Rezultate IOI si SC 2007','2007-09-09 18:33:52','2009-01-20 00:55:47','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\nVacanta de vara a ajuns la sfarsit.  Ai nevoie de un concurs\r\nde incalzire, inainte sa inceapa scoala, si, o data cu ea,\r\npregatirile pentru un nou an de olimpiade.\r\n\nE timpul sa te revezi cu vechii tai prieteni de la concursurile\r\nde info si sa le demonstrezi ca ai ramas in forma.  :)\r\n\nTe invit sa participi la runda 1 a concursului Autumn Warm Up\r\ncu probleme propuse de utilizatori infoarena.\r\n\np{padding-left: 2em;}. Runda 1\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Marti, 11 septembrie 2007, orele 10:00 - 15:00\r\n\np{padding-left: 2em;}. Pagina rundei:\r\n    \'autumn-warmup-2007/runda-1\':autumn-warmup-2007/runda-1\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nh2.  Atentie! Concurs cu rating! \n\nParticiparea la aceasta runda iti va afecta rating-ul pe infoarena.\r\nO prestatie buna te va aduce mai aproape de varful clasamentului.\r\n==NewsletterRating(username=\"%username%\")==\r\nAfla mai multe despre rating: \'documentatie/rating\':documentatie/rating\r\n\nh2.  Despre Autumn Warm Up, Runda 1 =\n\nVei avea de rezolvat 4 probleme de natura algoritmica.\r\nTimpul de lucru este de 5h iar evaluarea se face la sfarsit.\r\n\nVor propune probleme: Paul-Dan Baltescu, Savin Tiberiu,\r\nAirinei Adrian si Vlad Dumitriu.\r\n\nConcursul este supravegheat de Adrian Diaconu.\r\n\nPentru informatii suplimentare (cum particip, intrebari etc.)\r\nviziteaza pagina concursului: \'autumn-warmup-2007\':autumn-warmup-2007\r\n\nh2.  Rezultate Summer Challenge 2007 \n\nIata castigatorii concursului Summer Challenge (30 iul - 12 aug),\r\nin urma celor 3 runde online organizate de infoarena:\r\n\np{padding-left: 2em;}. Loc    Nume                    Scor (max 900)\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n      1    Gheorghe Cosmin          755\r\n      2    Bogdan Tataroiu          682\r\n      3    Andrei Grigorean         574\r\n      4    Airinei Adrian           488\r\n      5    Victor Rusu              480\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\nVezi clasamentul complet:\r\n\'summer-challenge-2007/clasament\':summer-challenge-2007/clasament\r\n\nh2.  Rezultate IOI 2007 \n\nA 19-a editie a Olimpiadei Internationale de Informatica a fost\r\ngazduita de Croatia (in Zagreb) in perioada 15-22 august.\r\n\nPagina web: \'http://www.hsin.hr/ioi2007/\':http://www.hsin.hr/ioi2007/\r\n\nDelegatia Romaniei, condusa de Prof. Emanuela Cerchez, a obtinut\r\n4 medalii de argint.  Felicitari!\r\n\nMedaliatii Romaniei la IOI sunt:  Cosmin Gheorghe, Bogdan Tataroiu,\r\nAdrian Airinei si Andrei Grigorean.\r\n\nDaca simti nevoia sa ii feliciti, probabil ca ii poti gasi pe\r\nforum-ul infoarena:\r\n\'http://infoarena.ro/forum/index.php?topic=2076.0\':http://infoarena.ro/forum/index.php?topic=2076.0  ;)\r\n\nh2.  Prima data la infoarena? \n\nDespre infoarena: \'despre-infoarena\':despre-infoarena\r\nPrezentare infoarena: \'prezentare\':prezentare\r\nTutorial infoarena: \'documentatie/tutorial\':documentatie/tutorial\r\n\nRamai alaturi de noi.  Te ajutam sa devii olimpic!\r\n\nSucces!\r\nEchipa infoarena\r\n\nh2.  Mesaj nesolicitat? \n\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n\n\n',13,'protected',NULL,NULL),('utilizator/motty','Welcome to the Hall of Fame - motty','2008-10-24 09:08:52','2009-01-14 08:56:21','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n* _Elev in clasa a 9-a la Colegiul National de Informatica \"Tudor Vianu\"_\r\n* _Am inceput informatica in a 9-a in octombrie._\r\n* _{*In God we trust!*}_\r\n* _Anything is posible if you just belive!_\r\n\r\nh2. Distinctii primite\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* ==user(user=\"motty\" type=\"tiny\")==\r\n* ==user(user=\"rapidu36\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"andrei-alpha\" type=\"tiny\")==\r\n* ==user(user=\"cosmin79\" type=\"tiny\")==\r\n* ==user(user=\"ira\" type=\"tiny\")==\r\n* ==user(user=\"drag0s93\" type=\"tiny\")==\r\n* ==user(user=\"ooctav\" type=\"tiny\")==',8690,'public',NULL,NULL),('blog/algoritmiada-runda2','Algoritmiada - analiza rundei 2','2009-01-21 10:34:36','2009-01-21 10:34:36','A doua runda a concursului Algoritmiada a avut loc pe 11 ianuarie, fiind primul concurs organizat de infoarena in 2009. Acesta s-a desfasurat fara nicio problema tehnica sau stiintifica, marcand un inceput in forta a echipei infoarena. Speram sa o tinem tot asa pe parcursul anului.\r\n\r\nMai intai de toate sa vedem cum arata statisticile rundei in comparatie cu cele din runda precedenta:\r\n\r\ntable. |_. &nbsp; |_. Runda 1 |_. Runda 2 |\r\n| Cati concurenti au trimis solutii | 223 | 157 |\r\n| Cati concurenti s-au inscris | 356 | 232 |\r\n| Surse trimise | 1245 | 894 |\r\n| Surse cu punctaj pozitiv | 685 | 408 |\r\n| Concurenti cu punctaj pozitiv | 162 | 113 |\r\n| Punctaj mediu al concurentilor care au trimis solutii | 75.09 | 43.85 |\r\n| Punctaj mediu al concurentilor cu punctaj strict mai mare ca 0 | 103.36 | 60.93 |\r\n\r\nIn primul rand observam ca au participat mai putini concurenti fata de prima runda. Este posibil ca inceputul de an sa-i fi prinsi nepregatiti pe unii participanti. Pentru a nu specula mai departe asupra motivelor, i-as ruga pe cei care nu au participat sa ne spuna ce s-a intamplat.\r\n\r\nIn al doilea rand observam ca problemele au fost ceva mai grele fata de runda precedenta. Aceasta a fost o decizie luata de comisia stiintifica pentru a va oferi probleme ceva mai interesante si pentru a va departaja.\r\n\r\nAcest lucru s-a vazut imediat si la varful clasamentului pentru mai toate grupele. Mai putin grupa 5-8, unde ==user(user=\"GavrilaVlad\")== si-a vazut de treaba si in runda aceasta, reusind din nou punctajul maxim. Felicitari Vlad pentru o performanta notabila. Pe podium au mai urcat ==user(user=\"radu_voroneanu\")== si ==user(user=\"taloibogdan\")== care s-au descurcat foarte bine reusind 250 si respectiv 220 de puncte.\r\n\r\nLa grupa 9-10, runda a fost adjudecata de ==user(user=\"raduzer\")== cu 150 de puncte. Imediat in spatele lui s-a clasat ==user(user=\"savim\")== (140 de puncte) si apoi doi concurenti cu 120 de puncte: ==user(user=\"jean\")== si ==user(user=\"andrei-alpha\")==.\r\n\r\nLa grupa 11-12 pe primul loc au terminat ==user(user=\"runnaway90\")== si ==user(user=\"cotofana\")== ambii cu 130 de puncte. La o diferenta de 5 puncte urmeaza ==user(user=\"stocarul\")== si ==user(user=\"Mishu91\")==.\r\n\r\nIn grupa de studenti ==user(user=\"Zeus\")== a iesit pe primul loc cu un punctaj frumos: 215 puncte. El a venit cu o solutie ingenioasa la problema \'jap\':problema/jap fiind singurul concurent care a reusit sa o rezolve. Pe locul 2 s-a clasat ==user(user=\"skipy\")== cu 200 de puncte fiind urmat de ==user(user=\"mugurelionut\")== cu 170 de puncte.\r\n\r\nIn urma acestei runde singurele nemultumiri au fost pe tema dificultatii problemelor. Judecand dupa punctaje, seturile de la 9-10 si 11-12 au fost un pic peste puterile concurentilor. In grupa studenti distributia punctajelor la varf este una buna, pe cand in grupa 5-8 este perfecta: cei mici merita motivati prin punctaje mai mari si probleme mai abordabile.\r\n\r\nInca sunt relativ multi utilizatori care au punctaje nule (~28%). Pe acestia ii sfatuiesc sa persevereze si sa incerce sa impuste punctele ce pot fi obtinute cu solutii _brute force_. Tehnica e simpla: \r\n\r\n==code(cpp) |\r\nif (N <= BRUTE_FORCE_LIMIT) {\r\n    do_brute_force();\r\n} else {\r\n    do_something_else();\r\n}\r\n==\r\n\r\nTragand linia, organizarea a fost buna. Comisia stiintifica a facut o treaba temeinica, ca de obicei, singurele aspecte care trebuie reglate in viitor fiind dificultatea problemelor si combaterea punctajelor nule. In aceasta runda, comisia ne-a surprins in mod placut cu publicarea solutiilor mult mai prompt fata de runda trecuta.\r\n\r\nInainte de runda 3, as vrea sa va aduc aminte ca aceasta este ultima sansa sa va calificati in finala. Cand va fi anuntata data desfasurarii, marcati-o in calendar si pregatiti-va sa dati tot ce aveti mai bun pentru a prinde un loc de finalist. Daca ne uitam la \'clasamentele generale\':algoritmiada-2009/clasament sunt foarte multi concurenti care au sanse sa se califice. Spre exemplu, in \'grupa 5-6\':algoritmiada-2009/clasament/5-8 diferenta dintre locul 7 si locul 60 este de numai 100 de puncte, foarte usor recupelabila in urma unei performante bune in runda 3. O situatie similara avem si in \'grupa 9-10\':algoritmiada-2009/clasament/9-10. Cum punctajele primilor 10 concurenti sunt la mai toate grupele sub 300, si un concurent cu 0 puncte dupa primele 2 runde are sanse de calificare la finala.\r\n\r\nIn vederea selectarii finalistilor dupa runda 3, va recomandam sa va completati/updatati profilul cu date despre clasa/anul in care sunteti precum si informatii despre institutia de invatamant. De fapt, am fi bucurosi daca toti utilizatorii si-ar completa profilul, aceasta fiind una din modalitatile prin care putem sa ne cunoastem intre noi. Exemple de profile completate puteti gasi la mai toti membrii echipei infoarena.\r\n\r\nInchei prin a va ura putini gandaci si multa inspiratie in runda 3! Fie ca cei mai buni sa castige!',15,'private',NULL,NULL),('deque-si-aplicatii','Deque și aplicații','2009-01-22 22:28:12','2009-01-24 22:42:10','h1. Deque şi aplicaţii\r\n\r\n(Categoria _Structuri de date_, Autor _Xulescu_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'Introducere\':deque-si-aplicatii#introducere\r\n* \'Operaţii\':deque-si-aplicatii#operatii\r\n\r\nÎn acest articol voi prezenta o structură de date de tip listă numită deque şi o serie de aplicaţii utile care vă vor demonstra simplitatea şi utilitatea folosirii acesteia, în special în concursurile de informatică.\r\n\r\nh2(#introducere). Introducere\r\n\r\n_Dequeul_ (pronunţat de obicei _deck_) poate fi privit ca o colecţie de tip listă ce are două capete prin care se şterg sau inserează noi elemente. În literatura de specialitate, aceste capete se numesc _head_ şi _tail_, iar dequeul mai este recunoscut şi ca fiind o coadă cu două capete _(double ended queue)_.\r\n\r\np=. !deque-si-aplicatii?deque0.png 70%!\r\n\r\nUn deque poate fi implementat folosind liste dublu înlănţuite, sau cu un vector static când se cunoaşte numărul elementelor din colecţie. Ce trebuie reţinut este că limbajul C++ pune la dispoziţia utilizatorilor prin intermediul headerului _#include <deque>_ clasa _std::deque_.\r\n\r\nh2(#operatii). Operaţii\r\n\r\nMai jos sunt operaţii ce se pot efectua cu un deque, iar în stânga corespondentul lor în limbajul C++:\r\n\r\n* _front()_:	    întoarce primul element;\r\n* _back()_:	    întoarce ultimul element;\r\n* _push_front()_: inserează un element în faţă;\r\n* _push_back()_:  inserează un element în spate;\r\n* _pop_front()_:  scoate primul element;\r\n* _pop_back()_:   scoate ultimul element.\r\n\r\nToate aceste operaţii se execută în timp $O(1)$ \'amortizat\':http://en.wikipedia.org/wiki/Amortized_analysis.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\nUnde-i folosit dequeul? :-?\r\n\r\nh3. \'Book Pile\':http://acm.sgu.ru/problem.php?contest=0&problem=271 (SGU)\r\n\r\nbq. Se dau $N$ cărţi aşezate una deasupra celeilalte asupra cărora se vor efecta $M$ operaţii de două tipuri: 1. $ADD${$(nume)$} : se adaugă cartea $nume$ deasupra celorlalte; 2. $ROTATE$ : primele $K$ cărţi de deasupra se rotesc (dacă sunt mai puţin de $K$ cărţi atunci se vor roti toate). Se cere să se afişeze cărţile în ordine, prima fiind cea de deasupra, după efectuarea celor $M$ operaţii.\r\nRestricţii: $0 &le; N, K &le; 40 000$, $0 &le; M &le; 100 000$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se poate deduce urmând paşii următori. Să presupunem că avem cărţile $A B C$ iniţial şi $K = 3$. Dacă îl vom adăuga pe $D$, atunci nu vor rămâne importante decât cărţile $D A B$, deoarece, dacă vom roti ulterior ultimele $K$ cărţi, $C$ nu va mai fi niciodată considerat, cărţile fiind doar adăugate, iar o dată ce o carte iese din „top {$K$}” cărţi nu va mai fi posibil să i se schimbe poziţia pe raft. Să rotim acum „top {$K$}” cărţi. Noua ordine va fi $B A D$ şi $C$ pe raft la loc sigur. Dacă îl vom adăuga pe $E$, topul se va schimba în $E B A$ iar pe raft, în mod sigur vor fi, în această ordine, $D C$. Proprietatea celor $K$ cărţi din vârf este: o secvenţă continuă de elemente, la care se adaugă noi elemente sau se elimină dintre acestea numai pe la _capete_. Aceste capete sunt chiar head şi tail ale unui deque.\r\n\r\np=. !deque-si-aplicatii?bookpile.png 40%!\r\n\r\nLa final, când se vor termina operaţiile, cărţilor de pe raft li se vor adăuga cele din deque şi se va afişa soluţia. În cazul presupus, soluţia va fi: $E B A D C$.\r\n\r\nÎntrucât operaţiile unui deque se execută în $O(1)$ amortizat, soluţia are complexitatea $O(N + M)$.\r\n\r\nh3. \'Sir\':problema/sir\r\n\r\n(dequeuri pure)\r\n... \r\n\r\n\r\nh3. \'Trans\':problema/trans (ONI 2004)\r\n\r\n(gen bun de problema)\r\n...\r\n\r\nh3. \'Otilia\':problema/otilia  (.campion)\r\n\r\n(deque la o problema de teoria jocurilor)\r\n...\r\n\r\nh3. \'Cut the Sequence\':http://acm.pku.edu.cn/JudgeOnline/problem?id=3017 (PKU) \r\n\r\n(deque cu arbori de intervale, zice Paul)\r\n...\r\n\r\nh3. \'Bcrc\':problema/bcrc (Stelele Informaticii 2006)\r\n\r\n(deque la programare dinamica)\r\n...',3146,'public',NULL,NULL),('planificare/sedinta-20090126','Sedinta 2009-01-26','2009-01-22 17:34:00','2009-01-25 18:57:06','h1. Sedinta 2009-01-26\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe întâlnim *luni, 26 ianuarie* la ora *19^00^* la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")== (inca nu stiu cand scap de la examen)\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"alexthero\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinta anterioara\':planificare/sedinta-20090112| ==user(user=\"domino\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n...\r\n\r\nh2. Notite\r\n\r\n...',1792,'public',NULL,NULL),('planificare/sedinta-20090126','Sedinta 2009-01-26','2009-01-22 17:34:00','2009-01-26 13:53:49','h1. Sedinta 2009-01-26\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe întâlnim *luni, 26 ianuarie* la ora *19^00^* la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")== (inca nu stiu cand scap de la examen)\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"alexthero\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinta anterioara\':planificare/sedinta-20090112| ==user(user=\"domino\" type=\"tiny\")==|\r\n|OKRs Q2| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n|Algoritmiada| ... |\r\n|Stelele| ==user(user=\"silviug\" type=\"tiny\")==|\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n* Despre Stele\r\n** Sunt ok datele: 31-1 pentru 9-10 si 6-7 pentru 11-12?\r\n** Seturi de probleme\r\n*** Se dau ~120 RON pe problema (e pe bani!)\r\n*** Avem probleme pentru 9-10? Cate?\r\n*** Pentru 11-12 trebuie sa ne intalnim (fara Bogdan si Cosmin) la ICHB. Marti/miercuri?\r\n\r\nDiscutii despre probleme la 9-10. Intalnire marti-miercuri pentru 11-12.\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n...\r\n\r\nh2. Notite\r\n\r\n...',13,'public',NULL,NULL),('okr','Organigrama','2008-10-15 20:31:25','2009-01-26 14:27:32','h1. Organigrama infoarena\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nPe baza \'propunerii de OKR-uri\':propuneri/9-okr, infoarena este impartita in mai multe unitati organizationale. Pe aceasta pagina gasiti structura exacta a acestor unitati, impreuna cu persoanele responsabile si cu OKR-urile stabilite. In aceasta pagina gasiti si OKR-urile globale pentru tot proiectul infoarena.\r\n\r\n==include(page=\"okr/20094\")==',13,'public',NULL,NULL),('okr/20091/devel-ia2','okr/20084/devel-ia2','2009-01-26 14:47:01','2009-01-26 14:47:01','(okr)* infoarena stabil cu concursuri automate\r\n** organizam 2-3 coding camp-uri cu echipa infoarena\r\n** alegem tickete relevante pentru 2.2 si le rezolvam pe toate; facem release\r\n** organizam runde de preONI pe noul sistem complet automat si fara incidente',13,'public',NULL,NULL),('okr/20091/extinde-arhiva','okr/2009q/extinde-arhiva','2009-01-26 14:47:38','2009-01-26 14:52:46','(okr)* Adaugarea in arhiva a 20 de probleme noi\r\n** adaugat baraje juniori\r\n** adaugat lot Iasi 2008',13,'public',NULL,NULL),('okr/20091/imbunatatire-teste','okr/20084/imbunatatire-teste','2009-01-26 14:48:14','2009-01-26 14:48:14','(okr)* Detectarea problemelor cu teste slabe\r\n** Marcarea tuturor problemelor cu teste slabe din primele 3 pagini',13,'public',NULL,NULL),('okr/20084','OKRs 2008Q4','2009-01-26 14:02:53','2009-01-26 14:51:00','h2. 2008Q4\r\n\r\nh3(#arhiva). Arhiva de probleme\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Extinde arhiva\':implica-te/extinde-arhiva | ==user(user=\"ditzonec\" type=\"tiny\")== | ==include(page=\"okr/20084/extinde-arhiva\")== | 0.5 |\r\n| \'Imbunatateste teste\':implica-te/imbunatatire-teste | ==user(user=\"ditzonec\" type=\"tiny\")== | ==include(page=\"okr/20084/imbunatatire-teste\")== | 1 |\r\n|\'Open surse\':propuneri/5-open-surse | ==user(user=\"gcosmin\" type=\"tiny\")== | ==include(page=\"okr/20084/open-surse\")== | 0.25 |\r\n| \'Arhiva educationala\':implica-te/arhiva-educationala | ==user(user=\"filipb\" type=\"tiny\")==, ==user(user=\"pauldb\" type=\"tiny\")== | ==include(page=\"okr/20084/arhiva-educationala\")== | 0.75 |\r\n| Tagging|==user(user=\"bogdan2412\" type=\"tiny\")== | ==include(page=\"okr/20084/tagging\")== | 0.5 |\r\n\r\nh3(#concursuri). Concursuri\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Organizeaza concursuri | ==user(user=\"astronomy\" type=\"tiny\")== | ==include(page=\"okr/20084/organizeaza-concursuri\")== | 0.75 |\r\n| Algoritmiada | ==user(user=\"wefgef\" type=\"tiny\")== | ==include(page=\"okr/20084/algoritmiada\")== | 1 |\r\n| \'Virtual contests\':propuneri/10-virtual-contest | ? | ? | ? |\r\n| \'Rating\':documentatie/rating | ==user(user=\"victorsb\" type=\"tiny\")== | ? | ? |\r\n| \'Hackaton\':propuneri/1-hackaton| ? | ? | ? |\r\n| \'Calendar\':forum?action=calendar | ==user(user=\"pauldb\" type=\"tiny\")== | ==include(page=\"okr/20084/arhiva-educationala\")== | 1 |\r\n\r\nh3(#continut). Continut educational\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Scrie articole\':implica-te/scrie-articole | ==user(user=\"stef2n\" type=\"tiny\")== | ==include(page=\"okr/20084/articole\")== | 0.75 |\r\n| \'Downloads\':downloads, \'Links\':links | ==user(user=\"Prostu\" type=\"tiny\")== | ==include(page=\"okr/20084/downloads\")== | 0.1 | \r\n| \'Almanah infoarena\':propuneri/8-almanah | ? | ? | ? |\r\n\r\nh3(#development). Development\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'infoarena 2.x Stable\':http://hackers.devnet.ro/roadmap | ==user(user=\"domino\" type=\"tiny\")== | ==include(page=\"okr/20084/devel-ia2\")== | 0.5 |\r\n| \'infoarena 3.0\':propuneri/3-infoarena3 | ==user(user=\"domino\" type=\"tiny\")== | ==include(page=\"okr/20084/devel-ia3\")== | 0.25 |\r\n\r\nh3(#comunitate). Comunitate\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Blog\':blog | ==user(user=\"Cosmin\" type=\"tiny\")== | ? | ? |\r\n| \'Forum\':forum | ==user(user=\"wefgef\" type=\"tiny\")== | ==include(page=\"okr/20084/forum\")== | 0.3 |\r\n| \'Community Ladder\':propuneri/7-community-ladder | ==user(user=\"wickedman\" type=\"tiny\")== | ==include(page=\"okr/20084/community-ladder\")== | 0.75 |\r\n\r\nh3(#administrativ). Administrativ\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Newsletter | ==user(user=\"wickedman\" type=\"tiny\")==| ==include(page=\"okr/20084/newsletter\")== | 0.6 |\r\n| Strangere fonduri | ==user(user=\"wickedman\" type=\"tiny\")== | ==include(page=\"okr/20084/fund-raising\")== | 0 |\r\n| Contabilitate | ? | ? | ? |\r\n| Hosting, data center ops. | ? | ? | ? |\r\n| Marketing si relatii publice | ? | ? | ? |\r\n\r\n',13,'public',NULL,NULL),('planificare/sedinta-20090126','Sedinta 2009-01-26','2009-01-22 17:34:00','2009-01-26 17:26:00','h1. Sedinta 2009-01-26\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe întâlnim *luni, 26 ianuarie* la ora *19^00^* la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")== (inca nu stiu cand scap de la examen)\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"alexthero\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinta anterioara\':planificare/sedinta-20090112| ==user(user=\"domino\" type=\"tiny\")==|\r\n|OKRs Q12009| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n|Algoritmiada| ... |\r\n|Stelele| ==user(user=\"silviug\" type=\"tiny\")==|\r\n|Fix-it camp| ... |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n* Despre Stele\r\n** Sunt ok datele: 31-1 pentru 9-10 si 6-7 pentru 11-12?\r\n** Seturi de probleme\r\n*** Se dau ~120 RON pe problema (e pe bani!)\r\n*** Avem probleme pentru 9-10? Cate?\r\n*** Pentru 11-12 trebuie sa ne intalnim (fara Bogdan si Cosmin) la ICHB. Marti/miercuri?\r\n\r\nDiscutii despre probleme la 9-10. Intalnire marti-miercuri pentru 11-12.\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Cristi face blog post despre OKR-uri\r\n* Silviu stabileste contacte cu Poli\r\n\r\n\r\nh2. Notite\r\n\r\n* Punem stire ca nu mai ai voie cu HTML si sa-si actualizeze lumea profilele\r\n\r\n...',1,'public',NULL,NULL),('planificare/sedinta-20090126','Sedinta 2009-01-26','2009-01-22 17:34:00','2009-01-26 19:20:52','h1. Sedinta 2009-01-26\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe întâlnim *luni, 26 ianuarie* la ora *19^00^* la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")== (inca nu stiu cand scap de la examen)\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"alexthero\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinta anterioara\':planificare/sedinta-20090112| ==user(user=\"domino\" type=\"tiny\")==|\r\n|OKRs Q12009| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n|Algoritmiada| ... |\r\n|Stelele| ==user(user=\"silviug\" type=\"tiny\")==|\r\n|Fix-it camp| ... |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n* Despre Stele\r\n** Sunt ok datele: 31-1 pentru 9-10 si 6-7 pentru 11-12?\r\n** Seturi de probleme\r\n*** Se dau ~120 RON pe problema (e pe bani!)\r\n*** Avem probleme pentru 9-10? Cate?\r\n*** Pentru 11-12 trebuie sa ne intalnim (fara Bogdan si Cosmin) la ICHB. Marti/miercuri?\r\n\r\nDiscutii despre probleme la 9-10. Intalnire marti-miercuri pentru 11-12.\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Cristi face blog post despre OKR-uri\r\n* Silviu stabileste contacte cu Poli\r\n* Fixit camp:\r\n** Cristi si Silviu vorbesc de premii\r\n* Stele:\r\n** Ne intalnim maine la 10 la ICHB sa vorbim de probleme: Silviu, Adi, Paul, Victor, Stefan. Victor vorbeste cu Wef\r\n** Cristi baga newsletter si Silviu ii zice din timp (minim 3 zile)\r\n** Cristi vorbeste cu Ali pentru configurarea proxy-ului\r\n** Cristi face .htaccess pentru a bana forumul\r\n* Algoritmiada:\r\n** Se face pe 15 februarie\r\n** Sponsori posibili: Adobe, Microsoft, iRealSoft\r\n* Il iertam pe Mort de datorie (a gresit la calcule)\r\n* Coding camp:\r\n** 28 februarie - 1 martie\r\n** Cine vine: Cristi, Vali, Prostu, Bogdan, Victor, Cosmin, Stefan, Mircea\r\n** Probabil: Silviu, Paul, Adi, Wef\r\n** Tero baga de acasa\r\n** Mircea face planul de coding camp (Virtual Contest e prioritar)\r\n*** Reorganizat sidebar si topnav (Cristi are idei, link la index de newsletter)\r\n** Cristi se ocupa de locatie\r\n* Nu facem fixit camp in Q1\r\n* Cristi se uita sa vada cati oameni au trimis doar in Arhiva Educationala\r\n* Vali face IAP si OKR despre ordonarea problemelor (vezi formula de la IMDB)\r\n* Incercam \"video sedinta\" cu Airinei (webcam/Skype)\r\n* Lumea da feedback la IAP 7 pana la urmatoarea sedinta\r\n* Cristi face blog post despre 2%\r\n* Silviu vorbeste cu Mars despre evaluator\r\n\r\nh2. Notite\r\n\r\n* Punem stire ca nu mai ai voie cu HTML si sa-si actualizeze lumea profilele\r\n* Stefan discuta cu Marius Stroe dupa finala\r\n* Cristi se ocupa de Paypal\r\n',1,'public',NULL,NULL),('planificare/sedinta-20090126','Sedinta 2009-01-26','2009-01-22 17:34:00','2009-01-26 19:29:30','h1. Sedinta 2009-01-26\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe întâlnim *luni, 26 ianuarie* la ora *19^00^* la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")== (inca nu stiu cand scap de la examen)\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"alexthero\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinta anterioara\':planificare/sedinta-20090112| ==user(user=\"domino\" type=\"tiny\")==|\r\n|OKRs Q12009| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n|Algoritmiada| ... |\r\n|Stelele| ==user(user=\"silviug\" type=\"tiny\")==|\r\n|Fix-it camp| ... |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n* Despre Stele\r\n** Sunt ok datele: 31-1 pentru 9-10 si 6-7 pentru 11-12?\r\n** Seturi de probleme\r\n*** Se dau ~120 RON pe problema (e pe bani!)\r\n*** Avem probleme pentru 9-10? Cate?\r\n*** Pentru 11-12 trebuie sa ne intalnim (fara Bogdan si Cosmin) la ICHB. Marti/miercuri?\r\n\r\nDiscutii despre probleme la 9-10. Intalnire marti-miercuri pentru 11-12.\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Cristi face blog post despre OKR-uri\r\n* Silviu stabileste contacte cu Poli\r\n* Fixit camp:\r\n** Cristi si Silviu vorbesc de premii\r\n* Stele:\r\n** Ne intalnim maine la 10 la ICHB sa vorbim de probleme: Silviu, Adi, Paul, Victor, Stefan. Victor vorbeste cu Wef\r\n** Cristi baga newsletter si Silviu ii zice din timp (minim 3 zile)\r\n** Cristi vorbeste cu Ali pentru configurarea proxy-ului\r\n** Cristi face .htaccess pentru a bana forumul\r\n* Algoritmiada:\r\n** Se face pe 15 februarie\r\n** Sponsori posibili: Adobe, Microsoft, iRealSoft\r\n* Il iertam pe Mort de datorie (a gresit la calcule)\r\n* Coding camp:\r\n** 28 februarie - 1 martie\r\n** Cine vine: Cristi, Vali, Prostu, Bogdan, Victor, Cosmin, Stefan, Mircea\r\n** Probabil: Silviu, Paul, Adi, Wef\r\n** Tero baga de acasa\r\n** Mircea face planul de coding camp (Virtual Contest e prioritar)\r\n*** Reorganizat sidebar si topnav (Cristi are idei, link la index de newsletter)\r\n*** Solutie de backup\r\n** Cristi se ocupa de locatie\r\n* Nu facem fixit camp in Q1\r\n* Cristi se uita sa vada cati oameni au trimis doar in Arhiva Educationala\r\n* Vali face IAP si OKR despre ordonarea problemelor (vezi formula de la IMDB)\r\n* Incercam \"video sedinta\" cu Airinei (webcam/Skype)\r\n* Lumea da feedback la IAP 7 pana la urmatoarea sedinta\r\n* Cristi face blog post despre 2%\r\n* Silviu vorbeste cu Mars despre evaluator\r\n* Mircea trimite mail pentru cine nu si-a completat OKR-urile\r\n* Facem sedinta pe 16 februarie. Cristi se ocupa de sala.\r\n\r\nh2. Notite\r\n\r\n* Punem stire ca nu mai ai voie cu HTML si sa-si actualizeze lumea profilele\r\n* Stefan discuta cu Marius Stroe dupa finala\r\n',1,'public',NULL,NULL),('deque-si-aplicatii','Deque și aplicații','2009-01-22 22:28:12','2009-01-26 20:40:47','h1. Deque şi aplicaţii\r\n\r\n(Categoria _Structuri de date_, Autor _Xulescu_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'Introducere\':deque-si-aplicatii#introducere\r\n* \'Operaţii\':deque-si-aplicatii#operatii\r\n* \'Aplicaţii\':deque-si-aplicatii#aplicatii\r\n** \'Problema 1: Book Pile &#40;SGU&#41;\':deque-si-aplicatii#problema-1\r\n** \'Problema 2: Şir\':deque-si-aplicatii#problema-2\r\n** \'Problema 3: Trans &#40;ONI 2004&#41;\':deque-si-aplicatii#problema-3\r\n** \'Problema 4: Otilia &#40;.campion&#41;\':deque-si-aplicatii#problema-4\r\n** \'Problema 5: Cut the Sequence &#40;PKU&#41;\':deque-si-aplicatii#problema-5\r\n** \'Problema 6: Bcrc &#40;Stelele Informaticii 2006&#41;\':deque-si-aplicatii#problema-6\r\n* \'Concluzii\':deque-si-aplicatii#concluzii\r\n* \'Probleme suplimentare\':deque-si-aplicatii#probleme-suplimentare\r\n* \'Bibliografie\':deque-si-aplicatii#bibliografie\r\n\r\nÎn acest articol voi prezenta o structură de date de tip listă numită deque şi o serie de aplicaţii utile care vă vor demonstra simplitatea şi utilitatea folosirii acesteia, în special în concursurile de informatică.\r\n\r\nh2(#introducere). Introducere\r\n\r\n_Dequeul_ (pronunţat de obicei _deck_) poate fi privit ca o colecţie de tip listă ce are două capete prin care se şterg sau inserează noi elemente. În literatura de specialitate, aceste capete se numesc _head_ şi _tail_, iar dequeul mai este recunoscut şi ca fiind o coadă cu două capete _(double ended queue)_.\r\n\r\np=. !deque-si-aplicatii?deque0.png 70%!\r\n\r\nUn deque poate fi implementat folosind liste dublu înlănţuite, sau cu un vector static când se cunoaşte numărul elementelor din colecţie. Ce trebuie reţinut este că limbajul C++ pune la dispoziţia utilizatorilor prin intermediul headerului _#include <deque>_ clasa _std::deque_.\r\n\r\nh2(#operatii). Operaţii\r\n\r\nMai jos sunt operaţii ce se pot efectua cu un deque, iar în stânga corespondentul lor în limbajul C++:\r\n\r\n* _front()_:	    întoarce primul element;\r\n* _back()_:	    întoarce ultimul element;\r\n* _push_front()_: inserează un element în faţă;\r\n* _push_back()_:  inserează un element în spate;\r\n* _pop_front()_:  scoate primul element;\r\n* _pop_back()_:   scoate ultimul element.\r\n\r\nToate aceste operaţii se execută în timp $O(1)$ \'amortizat\':http://en.wikipedia.org/wiki/Amortized_analysis.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\nUnde-i folosit dequeul? :-?\r\n\r\nh3(#problema-1). Problema 1: \'Book Pile\':http://acm.sgu.ru/problem.php?contest=0&problem=271 (SGU)\r\n\r\nbq. Se dau $N$ cărţi aşezate una deasupra celeilalte asupra cărora se vor efecta $M$ operaţii de două tipuri: 1. $ADD${$(nume)$} : se adaugă cartea $nume$ deasupra celorlalte; 2. $ROTATE$ : primele $K$ cărţi de deasupra se rotesc (dacă sunt mai puţin de $K$ cărţi atunci se vor roti toate). Se cere să se afişeze cărţile în ordine, prima fiind cea de deasupra, după efectuarea celor $M$ operaţii.\r\nRestricţii: $0 &le; N, K &le; 40 000$, $0 &le; M &le; 100 000$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se poate deduce urmând paşii următori. Să presupunem că avem cărţile $A B C$ iniţial şi $K = 3$. Dacă îl vom adăuga pe $D$, atunci nu vor rămâne importante decât cărţile $D A B$, deoarece, dacă vom roti ulterior ultimele $K$ cărţi, $C$ nu va mai fi niciodată considerat, cărţile fiind doar adăugate, iar o dată ce o carte iese din „top {$K$}” cărţi nu va mai fi posibil să i se schimbe poziţia pe raft. Să rotim acum „top {$K$}” cărţi. Noua ordine va fi $B A D$ şi $C$ pe raft la loc sigur. Dacă îl vom adăuga pe $E$, topul se va schimba în $E B A$ iar pe raft, în mod sigur vor fi, în această ordine, $D C$. Proprietatea celor $K$ cărţi din vârf este: o secvenţă continuă de elemente, la care se adaugă noi elemente sau se elimină dintre acestea numai pe la _capete_. Aceste capete sunt chiar head şi tail ale unui deque.\r\n\r\np=. !deque-si-aplicatii?bookpile.png 40%!\r\n\r\nLa final, când se vor termina operaţiile, cărţilor de pe raft li se vor adăuga cele din deque şi se va afişa soluţia. În cazul presupus, soluţia va fi: $E B A D C$.\r\n\r\nÎntrucât operaţiile unui deque se execută în $O(1)$ amortizat, soluţia are complexitatea $O(N + M)$.\r\n\r\nh3(#problema-2). Problema 2: \'Sir\':problema/sir\r\n\r\nbq. Se dă un şir $S$ de numere întregi de lungime $N$. Se cere să se găsească secvenţa de lungime maximă cuprinsă între $X$ şi $Y$ astfel încât $MAX - MIN &le; Z$, unde $MAX$ este maximul dintre toate numerele întregi din secvenţă iar $MIN$ minimul dintre acestea. Secvenţa soluţie va fi cea cu poziţia de început maximă dintre toate secvenţele de lungime maximă.\r\nRestricţii: $3 &le; N &le; 100 000$, $1 &le; X &le; Y &le; N$, $0 &le; Z &le; 30 000$.\r\n\r\nh3. Soluţie\r\n\r\nVoi prezenta mai jos o rafinare a soluţiei în trei paşi.\r\n\r\nPrima rezolvare se găseşte uşor, deoarece nu facem decât să urmărim textul: pentru fiecare poziţie $i$ fixată ({$i$} ia valorile $1$, $2$, .., $N$ succesiv) vom determina pentru aceasta secvenţa cerută, adică vom plimba un $j$ între poziţiile $i - Y$ şi $i - X$. Pentru un interval $(j, i]$ vom determina $MAX$ şi $MIN$ în $O(log{~2~}N)$ cu un arbore de intervale, iar daca diferenţa dintre acestea nu depăşeşte $Z$ vom compara cu soluţia finală. Complexitatea finală va fi $O(N * (Y - X) * log{~2~}Y)$.\r\n\r\np=. !deque-si-aplicatii?sir.png 60%!\r\n\r\nSă presupunem că pentru poziţia curentă $i$, l-am găsit pe $j$ cuprins între $i - Y$ şi $i - X$ care îndeplineşte optimul. Ce proprietăţi are $j$?\r\n\r\n* $i - Y &le; j &le; i - X$ şi $MAX - MIN &le; Z$;\r\n* dacă îl incrementăm pe $j$ la $j + 1$ atunci dacă $j &le; i - X$ cu siguranţă $MAX - MIN &le; Z$ şi astfel soluţia va fi mai scurtă;\r\n* dacă îl decrementăm pe $j$, atunci ori $j < i - Y$ ori $MAX - MIN > Z$;\r\n* dacă îl incrementăm pe $i$ la $i + 1$, atunci se poate întâmpla ca $j < i - Y$; cum $MAX$ nu poate decât să crească, iar $MIN$ decât să scadă, se mai poate de asemenea întâmpla ca $MAX - MIN > Z$.\r\n\r\nDatorită proprietăţilor de mai sus, când trecem de la $i$ la $i + 1$, valoarea lui $j$ nu poate decât să crească cât timp $MAX - MIN > Z$ şi $j$ nu a depăşit poziţia $i - X$. Pentru determinarea lui $MAX$, respectiv lui $MIN$ se poate folosi un arbore de intervale. Complexitatea finală va fi $O(N * log{~2~}(Y))$.\r\n\r\nCu cei doi indici $i$ şi $j$ vom accesa fiecare element din cele $N$ de cel mult $2$ ori, o dată cu $i$ şi o dată cu $j$. Destul de eficient. Să vedem cum putem îmbunătăţi complexitatea $O(log{~2~}Y)$ pentru determinarea maximului şi minimului.\r\n\r\nPentru fixarea ideilor să urmărim cum îl calculăm pe $MAX$. Observaţia care ne ajută în multe probleme pentru reducerea complexităţii de la $O(log{~2~}N)$ la $O(1)$ amortizat este următoarea: „Fixăm $i{~1~}$ şi $i{~2~}$ astfel încât $j < i{~1~} < i{~2~} &le; i$. Atunci, dacă $S[i{~2~}] > S[i{~1~}]$ poziţia $i{~2~}$ va fi întotdeauna mai importantă decât poziţia $i{~1~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ şi $i{~2~}$ nu vor mai fi în intervalul $(j, i]$, poziţia eliminată va fi {$i{~1~}$}”. Rezultă din această observaţie că în intervalul $(j, i]$ poziţiile importante vor fi $j < i{~1~} < i{~2~} < .. < i{~k~} <= i$ astfel încât $S[i{~1~}] > S[i{~2~}] > .. > S[i{~k~}]$. Astfel $MAX$ va fi $S[i{~1~}]$. Când îl vom incrementa pe $i$ la $i + 1$ vom şterge din poziţiile $i{~k~}$, $i{~k-1~}$, ... atâta timp cât $S[i + 1]$ este mai important, adică mai mare decât valorile de pe aceste poziţii, şi vom şterge $i{~1~}$, $i{~2~}$, ... atâta timp cât aceste poziţii sunt mai mici sau egale decât $j\'$. Indicele $j\'$ este noul optim pentru poziţia $i + 1$. Proprietatea şirului de poziţii $i{~1~}, i{~2~}, .., i{~k~}$ este că se reprezintă ca un şir contiguu de numere care permite inserarea elementelor prin dreapta şi ştergerea prin stânga, adică se adaugă elemente la tail şi se şterg elemente de la head. Îl putem deci reprezenta printr-un deque. Complexitatea $O(1)$ amortizat provine de la faptul că fiecare poziţie dintre cele $N$ nu trece decât o singură dată prin deque şi este şters tot cel mult o singură dată. \r\n\r\nÎn practică, programul poate arăta în felul următor:\r\n\r\n== code(cpp) |\r\n#include <fstream>\r\n#include <deque>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\ntypedef int (*PF)(const int , const int ) ;\r\n\r\nint V[100005];  \r\n\r\ndeque <int> min_deq, max_deq;\r\n\r\n\r\nint min_fct(const int a, const int b) { return a < b; }\r\n\r\nint max_fct(const int a, const int b) { return a > b; }\r\n\r\nvoid push_in(deque <int>& deq, const int p, PF compare) {\r\n    for (; !deq.empty() && compare(V[p], V[deq.back()]); deq.pop_back()) ;\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque <int>& deq, const int j) {\r\n    for (; !deq.empty() && deq.front() <= j; deq.pop_front()) ;\r\n    return V[deq.front()];\r\n}\r\n\r\nint main(void)\r\n{\r\n    ifstream in(\"sir.in\");  ofstream out(\"sir.out\");\r\n    int N, X, Y, Z;\r\n    int length = 0, start, stop, j = 0;\r\n\r\n    in >> N >> X >> Y >> Z;\r\n    for (int i = 1; i <= N; ++ i) {\r\n        in >> V[i];\r\n        push_in(min_deq, i, min_fct);\r\n        push_in(max_deq, i, max_fct);\r\n        while ((j < i - Y || query(max_deq, j) - query(min_deq, j) > Z) && j < i - X)\r\n            j ++;\r\n        // (j, i] este intervalul candidat la soluţia pentru pozitia i\r\n        if (j <= i - X) if (query(max_deq, j) - query(min_deq, j) <= Z)\r\n            if (i - j >= length)\r\n                length = i - j, start = j + 1, stop = i;\r\n    }\r\n    length > 0 ? out << length << \" \" << start << \" \" << stop : out << -1;\r\n    in.close(), out.close();\r\n    return 0;\r\n}\r\n==\r\n\r\nComplexitatea finală va fi $O(N)$.\r\n\r\nh3(#problema-3). Problema 3: \'Trans\':problema/trans (ONI 2004)\r\n\r\nbq. Se dau $N$ blocuri de piatră, de culoare albă sau neagră aşezate în ordinea $1$, $2$,.., $N$. Blocurile de piatră trebuie să fie transportate în ordinea în care sunt, iar pentru aceasta va trebui închiriat un camion. Se mai dau $Q$ tipuri de camioane. Camionul de tipul $i (1 &le; i &le; Q)$ poate transporta maxim $K{~i~}$ blocuri de piatră la un moment dat şi pentru un transport se percepe taxa $T{~i~}$. Se impune condiţia ca toate blocurile de piatră plasate în camion la un transport sa aibă aceeaşi culoare. Aşadar, pentru a fi transportate toate blocurile, se va alege un camion de un anumit tip, iar camionul va efectua unul sau mai multe transporturi. Pentru a micşora suma totală plătită, există posibilitatea de a schimba culoarea oricărui bloc de piatră (din alb în negru sau din negru în alb); pentru fiecare bloc $i (1 &le; i &le; N)$ se cunoaşte suma $S{~i~}$ ce trebuie plătită pentru a-i schimba culoarea $C{~i~}$.\r\nCerinţă: Pentru fiecare dintre cele $Q$ tipuri de camioane, determinaţi suma minimă plătită pentru a transporta toate cele $N$ blocuri.\r\nRestricţii: $1 &le; N &le; 16 000$, $1 &le; Q &le; 100$, $1 &le; K{~i~} &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se bazează pe găsirea unei formule de recurenţă ce respectă principiul optimalităţii al metodei programării dinamice.\r\n\r\nPentru început, fixăm un camion dintre cele $Q$. Fie $K$ numărul maxim de pietre pe care acesta le poate transporta şi $T$ taxa percepută. Notăm $sum[i][&#99;]$ costul pentru a schimba toate pietrele $1$, $2$, .., $i$ în culoarea $c$ ({$c = 0$} pentru alb şi $c = 1$ pentru negru). În $sum[i][&#99;]$ se vor aduna toate valorile $S[j]$, cu $j &le; i$ pentru care $C[j] = 1 - c$. \r\n\r\nÎn continuare, considerăm $bst[i][&#99;]$ costul minim pentru a transporta pietrele $1$, $2$, .., $i$, iar ultimul transport conţine pietre de culoare $c$. Întrucât nu putem transporta mai mult de $K$ pietre, $bst[i][&#99;]$ depinde doar de poziţiile $i - K$, $i - K + 1$, ..., $i - 1$. Cunoaştem că ultimul camion va transporta o secvenţă continuă de pietre începând de la o poziţie $j + 1$ până la poziţia $i$, unde $i - K &le; j &le; i - 1$. Astfel, pentru fiecare $j$ în intervalul precedent, costul va fi $Min(bst[j][&#48;], bst[j][&#49;])$ (transportăm primele j pietre cât mai ieftin) adunat cu $sum[i][&#99;] - sum[j][&#99;]$ (costul transformării pietrelor $j + 1$, .., $i$ în culoarea $c$) şi plus taxa $T$. Rezultă recurenţa:\r\n\r\n* $bst[i][&#99;] = Min{ Min(bst[j][&#48;], bst[j][&#49;]) + sum[i][&#99;] - sum[j][&#99;] } + T$, unde $i - K &le; j &le; i - 1$.\r\n\r\nDacă ne vom opri aici, complexitatea soluţiei va fi $O(Q * N^2^)$.\r\n\r\nRelaţia de recurenţă poate fi îmbunătăţită. Observăm că pentru poziţia $i$, $sum[i][&#99;]$ este o valoare constantă, ca şi $T$. Astfel, deducem următoarea relaţie de recurenţă:\r\n\r\n* $bst[i][&#99;] = Min{ Min(bst[j][&#48;], bst[j][&#49;]) - sum[j][&#99;] } + sum[i][&#99;] + T$, unde $i - K &le; j &le; i - 1$.\r\n\r\nNotez în continuare, pentru uşurinţă în scriere, $X[j][&#99;] = Min(bst[j][&#48;], bst[j][&#49;]) - sum[j][&#99;]$. Să fixăm doi indici $i{~1~}$ şi $i{~2~}$, astfel încât $i - K &le; $i{~1~}$ < $i{~2~}$ &le; i - 1$. Dacă $X[i{~1~}][&#99;] > X[i{~2~}][&#99;]$ atunci, întotdeauna poziţia $i{~2~}$ va fi preferată poziţiei $i{~1~}$. Când cele două nu se vor mai afla în intervalul $[i - K, i - 1]$, poziţia eliminată va fi poziţia $i{~1~}$. Dacă $X[i{~1~}][&#99;] < X[i{~2~}][&#99;]$, atunci nu putem decide care poziţie este mai bună în viitor, aşa că le vom păstra pe ambele. Rezultă mai departe că în intervalul $[i - K, i - 1]$ vom avea o serie de indecşi candidaţi la minim $i - K &le; i{~1~} < i{~2~} < .. < i{~n~} &le; i - 1$ astfel încât $X[i{~1~}][&#99;] < X[i{~2~}][&#99;] <  .. < X[i{~n~}][&#99;]$. Mai departe, găsim $bst[i][&#99;]$ ca fiind $X[i{~1~}][&#99;] + sum[i][&#99;] + T$. Urmează să îl introducem şi pe $X[i][&#99;]$, el fiind egal cu $Min(bst[i][&#48;], bst[i][&#49;]) - sum[i][&#99;]$, în şirul de indecşi de mai sus. Acest lucru se va face în felul următor: se vor elimina din $i{~n~}$, $i{~n-1~}$, ... atâta timp cât $X[$i{~n~}$][&#99;] > X[i][&#99;]$, $X[$i{~n-1~}$][&#99;] > X[i][&#99;]$, ... adică atâta timp cât poziţia $i$ este preferată lui $i{~n~}$, $i{~n-1~}$... Fiind la poziţia $i + 1$, intervalul se va transforma în $[i - K + 1, i]$, aşadar, vom mai elimina din primii indici $i{~1~}$, $i{~2~}$,... atâta timp cât $i{~1~} < i - K + 1$, $i{~2~} < i - K + 1$...\r\n\r\nDupă cum am arătat şi la problema precedentă, acest şir de indecşi $i{~1~}$, $i{~2~}$, .., $i{~n~}$ are proprietatea că este un şir continuu de numere care admite inserări prin dreapta (tail) şi ştergeri prin stânga (head). Şir ce poate fi reprezentat printr-un deque. Cum fiecare index dintre $1$, $2$, .., $N$ va trece o singură dată prin deque şi va fi şters cel mult o dată, complexitatea soluţiei în acest caz va fi $O(Q * N)$.\r\n\r\nÎn practică, programul poate arăta în felul următor:\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\n#include <vector>\r\n#include <deque>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\nconst char iname[] = \"trans.in\";\r\nconst char oname[] = \"trans.out\";\r\n\r\n#define MAXN  16005\r\n#define Min(a, b) ((a) < (b) ? (a) : (b))\r\n#define FOR(i, a, b)  for (int i = (a); i <= (b); ++ i)\r\n\r\nint C[MAXN], S[MAXN], bst[MAXN][2], sum[MAXN][2], N;\r\n\r\nvoid insert(deque < pair <int, int> >& deq, const pair <int, int>& p) {\r\n    while (!deq.empty() && deq.back().second > p.second)\r\n        deq.pop_back();\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque < pair <int, int> >& deq, const int idx) {\r\n    while (deq.front().first < idx)\r\n        deq.pop_front();\r\n    return deq.front().second;\r\n}\r\n\r\nint work(const int K, const int T) {\r\n    deque < pair <int, int> > deq[2];       // pair (idx, value)\r\n    FOR (c, 0, 1)\r\n        insert(deq[c], pair <int, int>(0, 0));\r\n    FOR (i, 1, N) {   // obiectul i\r\n        FOR (c, 0, 1) // culoare\r\n            bst[i][c] = query(deq[c], i - K) + sum[i][c] + T;\r\n        FOR (c, 0, 1)\r\n            insert(deq[c], pair <int, int>(i, Min(bst[i][0], bst[i][1]) - sum[i][c]));\r\n    }\r\n    return Min(bst[N][0], bst[N][1]);\r\n}\r\n\r\nint main(void)\r\n{\r\n    ifstream in(iname);  ofstream out(oname);\r\n    in >> N;\r\n    FOR (i, 1, N) {\r\n        in >> C[i] >> S[i];\r\n        FOR (c, 0, 1)\r\n            sum[i][c] += sum[i - 1][c];\r\n        sum[i][1 - C[i]] += S[i];\r\n    }\r\n    int cnt;\r\n    in >> cnt;\r\n    FOR (i, 1, cnt) {\r\n        int K, T;\r\n        in >> K >> T;\r\n        out << work(K, T) << \"\\n\";\r\n    }\r\n    in.close(), out.close();\r\n    return 0;\r\n}\r\n==\r\n\r\nh3(#problema-4). Problema 4: \'Otilia\':problema/otilia  (.campion)\r\n\r\n(deque la o problema de teoria jocurilor)\r\n...\r\n\r\nh3(#problema-5). Problema 5: \'Cut the Sequence\':http://acm.pku.edu.cn/JudgeOnline/problem?id=3017 (PKU) \r\n\r\n(deque cu arbori de intervale, zice Paul)\r\n...\r\n\r\nh3(#problema-6). Problema 6: \'Bcrc\':problema/bcrc (Stelele Informaticii 2006)\r\n\r\n(deque la programare dinamica)\r\n...\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nNicio concluzie până acum.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\n* \'Secvenţă\':problema/secventa\r\n* \'Secvenţă 3\':problema/secv3\r\n* \'Secvenţă 4\':problema/secv4\r\n* \'Brânză\':problema/branza\r\n* \'Struţi\':problema/struti\r\n* \'Trompetă\':problema/trompeta\r\n* \'Buline\':problema/buline\r\n* \'Balans\':problema/balans\r\n* \'Gard\':problema/gard, _ONI 2002_ (Cred că ar merge mai bine la aplicaţii)\r\n* \'Ghiozdan\':problema/ghiozdan\r\n* \'Munte4\':problema/munte4, _Lotul Naţional de Informatică, 2005_\r\n* \'Cover\':problema/cover, _Baraj ONI 2007_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Cosmin Negruşeri, \"_Probleme cu secvenţe_\":probleme-cu-secvente\r\n# Dana Lica, \"_Arbori de intervale şi aplicaţii în geometria computaţională_\":arbori-de-intervale',3146,'public',NULL,NULL),('okr/20091','OKRs 2009Q1','2009-01-26 14:41:23','2009-01-26 19:23:03','h2. 2009Q1\r\n\r\nh3(#arhiva). Arhiva de probleme\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Extinde arhiva\':implica-te/extinde-arhiva | ==user(user=\"ditzonec\" type=\"tiny\")== | ==include(page=\"okr/20091/extinde-arhiva\")== | ? |\r\n| \'Imbunatateste teste\':implica-te/imbunatatire-teste | ==user(user=\"ditzonec\" type=\"tiny\")== | ==include(page=\"okr/20091/imbunatatire-teste\")== | ? |\r\n| \'Arhiva educationala\':implica-te/arhiva-educationala | ==user(user=\"filipb\" type=\"tiny\")==, ==user(user=\"pauldb\" type=\"tiny\")== | ==include(page=\"okr/20091/arhiva-educationala\")== | ? |\r\n| Tagging|==user(user=\"bogdan2412\" type=\"tiny\")== | ==include(page=\"okr/20091/tagging\")== | ? |\r\n\r\nh3(#concursuri). Concursuri\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Organizeaza concursuri | ==user(user=\"astronomy\" type=\"tiny\")== | ==include(page=\"okr/20091/organizeaza-concursuri\")== | ? |\r\n| Algoritmiada | ==user(user=\"wefgef\" type=\"tiny\")== | ==include(page=\"okr/20091/algoritmiada\")== | ? |\r\n| \'Virtual contests\':propuneri/10-virtual-contest | ==user(user=\"ditzonec\" type=\"tiny\")== | ==include(page=\"okr/20091/virtual-contest\")== | ? |\r\n| \'Calendar\':forum?action=calendar | ==user(user=\"pauldb\" type=\"tiny\")== | ==include(page=\"okr/20091/calendar\")== | ? |\r\n\r\nh3(#continut). Continut educational\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Scrie articole\':implica-te/scrie-articole | ==user(user=\"stef2n\" type=\"tiny\")== | ==include(page=\"okr/20091/articole\")== | ? |\r\n\r\nh3(#development). Development\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'infoarena 2.x Stable\':http://hackers.devnet.ro/roadmap | ==user(user=\"domino\" type=\"tiny\")== | ==include(page=\"okr/20091/devel-ia2\")== | ? |\r\n\r\nh3(#comunitate). Comunitate\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Forum\':forum | ==user(user=\"wefgef\" type=\"tiny\")== | ==include(page=\"okr/20091/forum\")== | ? |\r\n| \'Community Ladder\':propuneri/7-community-ladder | ==user(user=\"wickedman\" type=\"tiny\")==, ==user(user=\"silviug\" type=\"tiny\")==  | ==include(page=\"okr/20091/community\")== | ? |\r\n\r\nh3(#administrativ). Administrativ\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Newsletter | ==user(user=\"wickedman\" type=\"tiny\")==| ==include(page=\"okr/20091/newsletter\")== | ? |\r\n| Strangere fonduri | ==user(user=\"wickedman\" type=\"tiny\")== | ==include(page=\"okr/20091/fund-raising\")== | ? |\r\n',1,'public',NULL,NULL),('trie-forest-based-sort','trie-forest-based-sort','2009-01-12 18:52:31','2009-01-28 16:30:42','h1. Sorting Big Numbers using Trie-Forest based sort\r\n\r\nh2. authors : Serban Lupulescu and Mircea Dima\r\n\r\n \r\n\r\nh3. The first idea is that if you have a string of length h, you can insert it in a trie of height h. We could maintain a list of tries,\r\n\r\nh3. trie H[N], where H[i] is a trie with height i so when we insert a string with length i, we insert it in H[i].\r\n\r\nh3. But what happens when we have, say 2 strings, one of length 3, and one with length 10^20^? We can\'t declare H[10^20^].\r\n\r\nh3. Instead we can keep an optimal binary search tree, where the keys are the length of the trie, and the additional information is the\r\n\r\nh3. trie itself.\r\n\r\nh3. Now if we have a string with length h we have 2 possibilities:\r\n\r\nh3. 1) if there is a trie with height h in the binary search tree, we insert the string in that trie\r\n\r\nh3. 2) if there isn\'t a trie with height h in the binary search tree, we create it, we insert the string in an empty trie, and then we insert the trie in\r\n\r\nh3. the binary search tree.\r\n\r\n\r\n== code(c) |\r\n\r\n// Sorting Big Numbers using Trie-Forest based sort indexed in a STL set (Red-Black Tree)\r\n// copyright(c) Serban Lupulescu\r\n & Mircea Dima\r\n// Time Complexity: O(n*max_len)\r\n// Faculty of Mathematics and Computer Science, University of Bucharest\r\n// :D\r\n#include <cstdio>\r\n#include <string>\r\n#include <set>\r\n#include <vector>\r\n#define N 10024\r\n\r\nusing namespace std;\r\n\r\ninline int length(char a[])\r\n{\r\n      int n=0;\r\n      while(a[n] >= \'0\' && a[n] <= \'9\') ++n;\r\n      return n;\r\n}\r\n\r\nstruct nod { int nr; nod *next[10];};\r\n\r\ntypedef nod* trie;\r\n\r\ninline void init(trie &n)\r\n{\r\n      n=new nod;\r\n      n->nr=0;\r\n      memset(n->next, 0, sizeof(n->next));\r\n}\r\n\r\nstruct cmp{\r\n      bool operator()(const pair<int, trie> &a, const pair<int, trie> &b)const\r\n      {\r\n            if(a.first < b.first) return 1;\r\n            return 0;\r\n      }\r\n};\r\n\r\ntypedef set<pair<int, trie> , cmp > Tree;\r\ntypedef set<pair<int, trie> , cmp >:: iterator Tree_it;\r\n\r\n \r\n\r\nTree R; // Red-Black binary search tree with key values = pointers\r\n\r\ninline trie find(int len) // find a trie in RBTREE\r\n{\r\n      Tree_it i= R.find(make_pair(len, (trie)0));\r\n      if(i == R.end()) return (trie) 0;\r\n      return i->second;\r\n}\r\n\r\ninline void insert(trie t, int len)\r\n{\r\n      R.insert(make_pair(len, t));\r\n}\r\n\r\ninline void erase(trie t, int len)\r\n{\r\n      R.erase(make_pair(len, t));\r\n}\r\n\r\ninline void insert(trie T,char a[], int n)\r\n{\r\n      for(int i=0; i < n; ++i)\r\n      {\r\n            if(T->next[a[i]] == 0) //if I don\'t have an edge, I create it\r\n            {\r\n                  T->next[a[i]]=new nod;\r\n                  T->next[a[i]]->nr=0;\r\n                  memset(T->next[a[i]]->next, 0, sizeof(T->next));\r\n            }\r\n            T=T->next[a[i]]; // go down the edge\r\n      }          \r\n      ++T->nr;\r\n}\r\n\r\nchar sol[N];\r\n\r\ninline void afis(trie T, int n)\r\n{\r\n      for(int i=0; i < 10; ++i)\r\n            if(T->next[i])\r\n            {\r\n                  sol[n]=i;\r\n                 \r\n                  if(T->next[i]->nr)//has a number ended here?\r\n                  {\r\n                        for(int j=1; j <= T->next[i]->nr; ++j)\r\n                        {\r\n                              int k;\r\n                              for(k=0; k <= n && sol[k] == 0; ++k);\r\n                             \r\n                              for(; k <= n; ++k) printf(\"%d\", sol[k]);\r\n                              printf(\"\\n\");\r\n                        }\r\n                  }    \r\n                  afis(T->next[i], n+1);\r\n            }\r\n}\r\n\r\nvoid read()\r\n{\r\n      freopen(\"sort.in\",\"r\",stdin);\r\n      freopen(\"sort.out\",\"w\",stdout);\r\n      while(!feof(stdin))\r\n      {\r\n            char a[N];\r\n            memset(a, 0, sizeof(a));\r\n            gets(a);\r\n            int n=length(a);\r\n            for(int i=0; i < n; ++i) a[i]-=\'0\';\r\n            trie t=find(n);\r\n           \r\n            if(t == 0)\r\n            {\r\n                  t= new nod;\r\n                  init(t);\r\n                  insert(t, n);\r\n            }\r\n           \r\n            insert(t, a, n);\r\n      }\r\n     \r\n      for(Tree_it i = R.begin(); i != R.end(); ++i) afis(i->second, 0);\r\n           \r\n}\r\n\r\nint main()\r\n{\r\n      read();    \r\n      return 0;\r\n}\r\n==',1204,'public',NULL,NULL),('deque-si-aplicatii','Deque și aplicații','2009-01-22 22:28:12','2009-01-28 21:45:03','h1. Deque şi aplicaţii\r\n\r\n(Categoria _Structuri de date_, Autor _Xulescu_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'Introducere\':deque-si-aplicatii#introducere\r\n* \'Operaţii\':deque-si-aplicatii#operatii\r\n* \'Aplicaţii\':deque-si-aplicatii#aplicatii\r\n** \'Problema 1: Book Pile &#40;SGU&#41;\':deque-si-aplicatii#problema-1\r\n** \'Problema 2: Şir\':deque-si-aplicatii#problema-2\r\n** \'Problema 3: Trans &#40;ONI 2004&#41;\':deque-si-aplicatii#problema-3\r\n** \'Problema 4: Otilia &#40;.campion&#41;\':deque-si-aplicatii#problema-4\r\n** \'Problema 5: Cut the Sequence &#40;PKU&#41;\':deque-si-aplicatii#problema-5\r\n** \'Problema 6: Bcrc &#40;Stelele Informaticii 2006&#41;\':deque-si-aplicatii#problema-6\r\n* \'Concluzii\':deque-si-aplicatii#concluzii\r\n* \'Probleme suplimentare\':deque-si-aplicatii#probleme-suplimentare\r\n* \'Bibliografie\':deque-si-aplicatii#bibliografie\r\n\r\nÎn acest articol voi prezenta o structură de date de tip listă numită _deque_. Simplitatea acestei structuri poate nu are multe de spus şi din acest motiv am prezentat şi o serie de aplicaţii care vor arăta neaşteptata sa utilitate şi apariţie în locurile unde am fi crezut că nu se mai poate face nimic pentru a reduce complexitatea.\r\n\r\nh2(#introducere). Introducere\r\n\r\n_Dequeul_ (pronunţat de obicei _deck_) poate fi privit ca o colecţie de tip listă ce are două capete prin care se şterg sau inserează noi elemente. În literatura de specialitate, aceste capete se numesc _head_ şi _tail_, iar dequeul mai este recunoscut şi ca fiind o coadă cu două capete _(double ended queue)_.\r\n\r\nUn deque poate fi implementat folosind liste dublu înlănţuite, sau cu un vector static când se cunoaşte numărul elementelor din colecţie. Ce trebuie reţinut este că limbajul C++ pune la dispoziţia utilizatorilor prin intermediul headerului _#include <deque>_ clasa _std::deque_.\r\n\r\nh2(#operatii). Operaţii\r\n\r\nMai jos sunt enumerate operaţiile care pot fi efectuate asupra unui deque împreună cu corespondentul lor în limbajul C++:\r\n\r\n* _front()_:	    întoarce primul element;\r\n* _back()_:	    întoarce ultimul element;\r\n* _push_front()_: inserează un element în faţă;\r\n* _push_back()_:  inserează un element în spate;\r\n* _pop_front()_:  scoate primul element;\r\n* _pop_back()_:   scoate ultimul element;\r\n* _empty()_:      întoarce _true_ dacă dequel este gol.\r\n\r\np=. !deque-si-aplicatii?new_deque.png 75%!\r\n\r\nToate aceste operaţii se execută în timp $O(1)$ \'amortizat\':http://en.wikipedia.org/wiki/Amortized_analysis. Pentru un plus de viteză va trebui să folosim un vector static cu dimensiunea egală cu numărul maxim de elemente ce pot trece prin deque, iar operaţiile implementate „de mână”, cu doi indecşi ce indică către head şi tail. Însă, în majoritatea aplicaţiilor limita de timp permite folosirea lejerităţii şi siguranţei clasei _std::deque_.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\nFolosiţi deque! Foarte sănătos! :)\r\n\r\nh3(#problema-1). Problema 1: \'Book Pile\':http://acm.sgu.ru/problem.php?contest=0&problem=271 (SGU)\r\n\r\nbq. Se dau $N$ cărţi aşezate una deasupra celeilalte asupra cărora se vor efecta $M$ operaţii de două tipuri: 1. $ADD${$(nume)$} : se adaugă cartea $nume$ deasupra celorlalte; 2. $ROTATE$ : primele $K$ cărţi de deasupra se rotesc (dacă sunt mai puţin de $K$ cărţi atunci se vor roti toate). Se cere să se afişeze cărţile în ordine, prima fiind cea de deasupra, după efectuarea celor $M$ operaţii.\r\nRestricţii: $0 &le; N, K &le; 40 000$, $0 &le; M &le; 100 000$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se poate deduce urmând paşii următori. Să presupunem că avem cărţile $A B C$ iniţial şi $K = 3$. Dacă îl vom adăuga pe $D$, atunci nu vor rămâne importante decât cărţile $D A B$, deoarece, dacă vom roti ulterior ultimele $K$ cărţi, $C$ nu va mai fi niciodată considerat, cărţile fiind doar adăugate, iar o dată ce o carte iese din „top {$K$}” cărţi nu va mai fi posibil să i se schimbe poziţia pe raft. Să rotim acum „top {$K$}” cărţi. Noua ordine va fi $B A D$ şi $C$ pe raft la loc sigur. Dacă îl vom adăuga pe $E$, topul se va schimba în $E B A$ iar pe raft, în mod sigur vor fi, în această ordine, $D C$. Proprietatea celor $K$ cărţi din vârf este: o secvenţă continuă de elemente, la care se adaugă noi elemente sau se elimină dintre acestea numai pe la _capete_. Aceste capete sunt chiar head şi tail ale unui deque.\r\n\r\np=. !deque-si-aplicatii?bookpile.png 40%!\r\n\r\nLa final, când se vor termina operaţiile, cărţilor de pe raft li se vor adăuga cele din deque şi se va afişa soluţia. În cazul presupus, soluţia va fi: $E B A D C$.\r\n\r\nÎntrucât operaţiile unui deque se execută în $O(1)$ amortizat, soluţia are complexitatea $O(N + M)$.\r\n\r\nh3(#problema-2). Problema 2: \'Sir\':problema/sir\r\n\r\nbq. Se dă un şir $S$ de numere întregi de lungime $N$. Se cere să se găsească secvenţa de lungime maximă cuprinsă între $X$ şi $Y$ astfel încât $MAX - MIN &le; Z$, unde $MAX$ este maximul dintre toate numerele întregi din secvenţă iar $MIN$ minimul dintre acestea. Secvenţa soluţie va fi cea cu poziţia de început maximă dintre toate secvenţele de lungime maximă.\r\nRestricţii: $3 &le; N &le; 100 000$, $1 &le; X &le; Y &le; N$, $0 &le; Z &le; 30 000$.\r\n\r\nh3. Soluţie\r\n\r\nVoi prezenta mai jos o rafinare a soluţiei în trei paşi.\r\n\r\nPrima rezolvare se găseşte uşor, deoarece nu facem decât să urmărim textul: pentru fiecare poziţie $i$ fixată ({$i$} ia valorile $1$, $2$, .., $N$ succesiv) vom determina pentru aceasta secvenţa cerută, adică vom plimba un $j$ între poziţiile $i - Y$ şi $i - X$. Pentru un interval $(j, i]$ vom determina $MAX$ şi $MIN$ în $O(log{~2~}N)$ cu un arbore de intervale, iar daca diferenţa dintre acestea nu depăşeşte $Z$ vom compara cu soluţia finală. Complexitatea finală va fi $O(N * (Y - X) * log{~2~}Y)$.\r\n\r\np=. !deque-si-aplicatii?sir.png 60%!\r\n\r\nSă presupunem că pentru poziţia curentă $i$, l-am găsit pe $j$ cuprins între $i - Y$ şi $i - X$ care îndeplineşte optimul. Ce proprietăţi are $j$?\r\n\r\n* $i - Y &le; j &le; i - X$ şi $MAX - MIN &le; Z$;\r\n* dacă îl incrementăm pe $j$ la $j + 1$ atunci dacă $j &le; i - X$ cu siguranţă $MAX - MIN &le; Z$ şi astfel soluţia va fi mai scurtă;\r\n* dacă îl decrementăm pe $j$, atunci ori $j < i - Y$ ori $MAX - MIN > Z$;\r\n* dacă îl incrementăm pe $i$ la $i + 1$, atunci se poate întâmpla ca $j < i - Y$; cum $MAX$ nu poate decât să crească, iar $MIN$ decât să scadă, se mai poate de asemenea întâmpla ca $MAX - MIN > Z$.\r\n\r\nDatorită proprietăţilor de mai sus, când trecem de la $i$ la $i + 1$, valoarea lui $j$ nu poate decât să crească cât timp $j < i - Y$ sau $MAX - MIN > Z$ şi $j$ nu a depăşit poziţia $i - X$. Pentru determinarea lui $MAX$, respectiv lui $MIN$ se poate folosi un arbore de intervale. Complexitatea finală va fi $O(N * log{~2~}(Y))$.\r\n\r\nCu cei doi indici $i$ şi $j$ vom accesa fiecare element din cele $N$ de cel mult $2$ ori, o dată cu $i$ şi o dată cu $j$. Să vedem cum putem îmbunătăţi complexitatea $O(log{~2~}Y)$ pentru determinarea maximului şi minimului.\r\n\r\nPentru fixarea ideilor să urmărim cum îl calculăm pe $MAX$. Observaţia care ne ajută în multe probleme pentru reducerea complexităţii de la $O(log{~2~}N)$ la $O(1)$ amortizat este următoarea: \r\n\r\n_Observaţie_: „Fixăm $i{~1~}$ şi $i{~2~}$ astfel încât $j < i{~1~} < i{~2~} &le; i$. Atunci, dacă $S[i{~2~}] > S[i{~1~}]$ poziţia $i{~2~}$ va fi întotdeauna mai importantă decât poziţia $i{~1~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ şi $i{~2~}$ nu vor mai fi ambele în intervalul $(j, i]$, poziţia eliminată va fi {$i{~1~}$}. Dacă însă $S[i{~1~}] > S[i{~2~}]$, atunci poziţia $i{~1~}$ va umbri poziţia $i{~2~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ va fi eliminat, atunci e posibil ca $i{~2~}$ să fie un candidat la $MAX$ dintre restul elementelor de la dreapta sa. În acest caz, nu putem afirma nimic şi vom păstra cele două poziţii.”\r\n\r\nRezultă din această observaţie că în intervalul $(j, i]$ poziţiile importante vor fi $j < i{~1~} < i{~2~} < .. < i{~k~} <= i$ astfel încât $S[i{~1~}] > S[i{~2~}] > .. > S[i{~k~}]$. Astfel, $MAX$ va fi $S[i{~1~}]$. Când îl vom incrementa pe $i$ la $i + 1$ vom şterge din poziţiile $i{~k~}$, $i{~k-1~}$, ... atâta timp cât $S[i + 1]$ este mai important, adică mai mare decât valorile de pe aceste poziţii, şi vom şterge $i{~1~}$, $i{~2~}$, ... atâta timp cât aceste poziţii sunt mai mici sau egale decât $j\'$. Indicele $j\'$ este noul optim pentru poziţia $i + 1$. Proprietatea şirului de poziţii $i{~1~}, i{~2~}, .., i{~k~}$ este că se reprezintă ca un şir contiguu de numere care permite inserarea elementelor prin dreapta şi ştergerea prin stânga, adică se adaugă elemente la tail şi se şterg elemente de la head. Îl putem deci reprezenta printr-un deque. Complexitatea $O(1)$ amortizat provine de la faptul că fiecare poziţie dintre cele $N$ nu trece decât o singură dată prin deque şi este şters tot cel mult o singură dată. \r\n\r\nÎn practică, programul poate arăta în felul următor:\r\n\r\n== code(cpp) |\r\n// ...\r\n\r\ndeque <int> min_deq, max_deq;\r\n\r\ntypedef int (*PF)(const int , const int ) ;\r\n\r\nint min_fct(const int a, const int b) { return a < b; }\r\n\r\nint max_fct(const int a, const int b) { return a > b; }\r\n\r\nvoid push_in(deque <int>& deq, const int p, PF compare) {\r\n    for (; !deq.empty() && compare(S[p], S[deq.back()]); deq.pop_back()) ;\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque <int>& deq, const int j) {\r\n    for (; !deq.empty() && deq.front() <= j; deq.pop_front()) ;\r\n    return S[deq.front()];\r\n}\r\n\r\nint main(void) {\r\n    // ...\r\n    for (int i = 1; i <= N; ++ i) {\r\n        push_in(min_deq, i, min_fct);\r\n        push_in(max_deq, i, max_fct);\r\n        while ((j < i - Y || query(max_deq, j) - query(min_deq, j) > Z) && j < i - X)\r\n            j ++;\r\n        // (j, i] este intervalul candidat la soluţia pentru pozitia i\r\n        if (j <= i - X) if (query(max_deq, j) - query(min_deq, j) <= Z)\r\n            // compară cu rezultatul de până acum\r\n    }\r\n    // ...\r\n}\r\n==\r\n\r\nComplexitatea finală va fi $O(N)$.\r\n\r\nh3(#problema-3). Problema 3: \'Trans\':problema/trans (ONI 2004)\r\n\r\nbq. Se dau $N$ blocuri de piatră, de culoare albă sau neagră aşezate în ordinea $1$, $2$,.., $N$. Blocurile de piatră trebuie să fie transportate în ordinea în care sunt, iar pentru aceasta va trebui închiriat un camion. Se mai dau $Q$ tipuri de camioane. Camionul de tipul $i (1 &le; i &le; Q)$ poate transporta maxim $K{~i~}$ blocuri de piatră la un moment dat şi pentru un transport se percepe taxa $T{~i~}$. Se impune condiţia ca toate blocurile de piatră plasate în camion la un transport sa aibă aceeaşi culoare. Aşadar, pentru a fi transportate toate blocurile, se va alege un camion de un anumit tip, iar camionul va efectua unul sau mai multe transporturi. Pentru a micşora suma totală plătită, există posibilitatea de a schimba culoarea oricărui bloc de piatră (din alb în negru sau din negru în alb); pentru fiecare bloc $i (1 &le; i &le; N)$ se cunoaşte suma $S{~i~}$ ce trebuie plătită pentru a-i schimba culoarea $C{~i~}$.\r\nCerinţă: Pentru fiecare dintre cele $Q$ tipuri de camioane, determinaţi suma minimă plătită pentru a transporta toate cele $N$ blocuri.\r\nRestricţii: $1 &le; N &le; 16 000$, $1 &le; Q &le; 100$, $1 &le; K{~i~} &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se bazează pe găsirea unei formule de recurenţă ce respectă principiul optimalităţii al metodei programării dinamice.\r\n\r\nPentru început, fixăm un camion dintre cele $Q$. Fie $K$ numărul maxim de pietre pe care acesta le poate transporta şi $T$ taxa percepută. Notăm $sum[i][&#99;]$ costul pentru a schimba toate pietrele $1$, $2$, .., $i$ în culoarea $c$ ({$c = 0$} pentru alb şi $c = 1$ pentru negru). În $sum[i][&#99;]$ se vor aduna toate valorile $S[j]$, cu $j &le; i$ pentru care $C[j] = 1 - c$. \r\n\r\nÎn continuare, considerăm $bst[i][&#99;]$ costul minim pentru a transporta pietrele $1$, $2$, .., $i$, iar ultimul transport conţine pietre de culoare $c$. Întrucât nu putem transporta mai mult de $K$ pietre, $bst[i][&#99;]$ depinde doar de poziţiile $i - K$, $i - K + 1$, ..., $i - 1$. Cunoaştem că ultimul camion va transporta o secvenţă continuă de pietre începând de la o poziţie $j + 1$ până la poziţia $i$, unde $i - K &le; j &le; i - 1$. Astfel, pentru fiecare $j$ în intervalul precedent, costul va fi $Min(bst[j][&#48;], bst[j][&#49;])$ (transportăm primele j pietre cât mai ieftin) adunat cu $sum[i][&#99;] - sum[j][&#99;]$ (costul transformării pietrelor $j + 1$, .., $i$ în culoarea $c$) şi plus taxa $T$. Rezultă recurenţa:\r\n\r\n* $bst[i][&#99;] = Min{ Min(bst[j][&#48;], bst[j][&#49;]) + sum[i][&#99;] - sum[j][&#99;] } + T$, unde $i - K &le; j &le; i - 1$.\r\n\r\nDacă ne vom opri aici, complexitatea soluţiei va fi $O(Q * N^2^)$.\r\n\r\nRelaţia de recurenţă poate fi îmbunătăţită. Observăm că pentru poziţia $i$, $sum[i][&#99;]$ este o valoare constantă, ca şi $T$. Astfel, deducem următoarea relaţie de recurenţă:\r\n\r\n* $bst[i][&#99;] = Min{ Min(bst[j][&#48;], bst[j][&#49;]) - sum[j][&#99;] } + sum[i][&#99;] + T$, unde $i - K &le; j &le; i - 1$.\r\n\r\nNotez în continuare, pentru uşurinţă în scriere, $X[j][&#99;] = Min(bst[j][&#48;], bst[j][&#49;]) - sum[j][&#99;]$. Să fixăm doi indici $i{~1~}$ şi $i{~2~}$, astfel încât $i - K &le; $i{~1~}$ < $i{~2~}$ &le; i - 1$. Dacă $X[i{~1~}][&#99;] > X[i{~2~}][&#99;]$ atunci, întotdeauna poziţia $i{~2~}$ va fi preferată poziţiei $i{~1~}$. Când cele două nu se vor mai afla în intervalul $[i - K, i - 1]$, poziţia eliminată va fi poziţia $i{~1~}$. Dacă $X[i{~1~}][&#99;] < X[i{~2~}][&#99;]$, atunci nu putem decide care poziţie este mai bună în viitor, aşa că le vom păstra pe ambele. Rezultă mai departe că în intervalul $[i - K, i - 1]$ vom avea o serie de indecşi candidaţi la minim $i - K &le; i{~1~} < i{~2~} < .. < i{~n~} &le; i - 1$ astfel încât $X[i{~1~}][&#99;] < X[i{~2~}][&#99;] <  .. < X[i{~n~}][&#99;]$. Mai departe, găsim $bst[i][&#99;]$ ca fiind $X[i{~1~}][&#99;] + sum[i][&#99;] + T$. Urmează să îl introducem şi pe $X[i][&#99;]$, el fiind egal cu $Min(bst[i][&#48;], bst[i][&#49;]) - sum[i][&#99;]$, în şirul de indecşi de mai sus. Acest lucru se va face în felul următor: se vor elimina din $i{~n~}$, $i{~n-1~}$, ... atâta timp cât $X[$i{~n~}$][&#99;] > X[i][&#99;]$, $X[$i{~n-1~}$][&#99;] > X[i][&#99;]$, ... adică atâta timp cât poziţia $i$ este preferată lui $i{~n~}$, $i{~n-1~}$... Fiind la poziţia $i + 1$, intervalul se va transforma în $[i - K + 1, i]$, aşadar, vom mai elimina din primii indici $i{~1~}$, $i{~2~}$,... atâta timp cât $i{~1~} < i - K + 1$, $i{~2~} < i - K + 1$...\r\n\r\nDupă cum am arătat şi la problema precedentă, acest şir de indecşi $i{~1~}$, $i{~2~}$, .., $i{~n~}$ are proprietatea că este un şir continuu de numere care admite inserări prin dreapta (tail) şi ştergeri prin stânga (head). Şir ce poate fi reprezentat printr-un deque. Cum fiecare index dintre $1$, $2$, .., $N$ va trece o singură dată prin deque şi va fi şters cel mult o dată, complexitatea soluţiei în acest caz va fi $O(Q * N)$.\r\n\r\nÎn practică, programul este scurt, clar şi foarte eficient:\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\n#include <vector>\r\n#include <deque>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\nconst char iname[] = \"trans.in\";\r\nconst char oname[] = \"trans.out\";\r\n\r\n#define MAXN  16005\r\n#define Min(a, b) ((a) < (b) ? (a) : (b))\r\n#define FOR(i, a, b)  for (int i = (a); i <= (b); ++ i)\r\n\r\nint C[MAXN], S[MAXN], bst[MAXN][2], sum[MAXN][2], N;\r\n\r\nvoid insert(deque < pair <int, int> >& deq, const pair <int, int>& p) {\r\n    while (!deq.empty() && deq.back().second > p.second)\r\n        deq.pop_back();\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque < pair <int, int> >& deq, const int idx) {\r\n    while (deq.front().first < idx)\r\n        deq.pop_front();\r\n    return deq.front().second;\r\n}\r\n\r\nint work(const int K, const int T) {\r\n    deque < pair <int, int> > deq[2];       // pair (idx, value)\r\n    FOR (c, 0, 1)\r\n        insert(deq[c], pair <int, int>(0, 0));\r\n    FOR (i, 1, N) {   // obiectul i\r\n        FOR (c, 0, 1) // culoare\r\n            bst[i][c] = query(deq[c], i - K) + sum[i][c] + T;\r\n        FOR (c, 0, 1)\r\n            insert(deq[c], pair <int, int>(i, Min(bst[i][0], bst[i][1]) - sum[i][c]));\r\n    }\r\n    return Min(bst[N][0], bst[N][1]);\r\n}\r\n\r\nint main(void)\r\n{\r\n    ifstream in(iname);  ofstream out(oname);\r\n    in >> N;\r\n    FOR (i, 1, N) {\r\n        in >> C[i] >> S[i];\r\n        FOR (c, 0, 1)\r\n            sum[i][c] += sum[i - 1][c];\r\n        sum[i][1 - C[i]] += S[i];\r\n    }\r\n    int cnt, K, T;\r\n    in >> cnt;\r\n    FOR (i, 1, cnt)\r\n        in >> K >> T, out << work(K, T) << \"\\n\";\r\n\r\n    in.close(), out.close();\r\n    return 0;\r\n}\r\n==\r\n\r\nh3(#problema-4). Problema 4: \'Otilia\':problema/otilia  (.campion)\r\n\r\nbq. Otilia şi Burbucel au o grămadă de $N$ pietre şi vor juca un joc cu următoarele trei reguli: 1. Primul jucător are voie să ia din gramadă cel mult $K$ piese; 2. Cu excepţia primei mutări, fiecare jucător are voie să ia maxim $P * t$ pietre, unde $t$ este numărul de pietre care au fost substituite din grămadă la mutarea precedentă; 3. Pierde cel care mută ultimul (cel care ia ultimele pietre din grămadă).\r\nCerinţă: Se dau $M$ jocuri prin numerele $N$, $K$ şi $P$. Se cere să se determină dacă Otilia va câştiga fiecare din jocuri sau nu.\r\nRestricţii: $1 &le; M &le; 30 000$, $1 &le; N &le; 5 000 000$, $1 &le; K &le; N$, $1 &le; P &le; 10$.\r\n\r\nh3. Soluţie:\r\n\r\nProblema se rezolvă prin programare dinamică. Soluţia se bazează pe observaţia de mai jos. Considerăm $P$-ul fixat şi notăm cu $stare(X, Y)$ poziţia de start în care avem $X$ pietre şi numărul maxim de pietre care se pot lua la prima mutare este $Y$.\r\n\r\n_Observaţia 1_: „Dacă există strategie sigură de câştig pentru $stare(X, Y)$ atunci există şi pentru orice $stare(X, T)$ cu $T &ge; Y$.” \r\n\r\nDe ce? Pentru că orice mutare validă pentru $stare(X, Y)$ este validă şi pentru $stare(X, T)$. Având această observaţie notăm cu $MinY[X] = Y$, $Y$ minim astfel încât avem strategie de câştig pentru $stare(X, Y)$.\r\n\r\n_Observaţia 2_: „$stare(X, Y)$ este pierzătoare dacă şi numai dacă $Y < MinY[X]$.” \r\n\r\nAceasta reiese din definiţia lui $MinY[X]$.\r\n\r\n$MinY[X]$ se calculează după următoarea recurenţă, care rezultă din regulile jocului: \r\n\r\n* $MinY[X]$ este cel mai mic $i$ pentru care avem $MinY[X - i] > P * i$.\r\n\r\nDe aici se naşte prima soluţie, care este implementarea directă a recurenţei. Deşi complexitatea acesteia pare a fi $O(N^2^)$ ea se comportă foarte bine pentru $N &le; 500 000$. Aşadar, această soluţie acoperă aproximativ $50%$ din testele de intrare. Printr-o rafinare a acestei soluţii se obţine un algoritm de complexitate $O(N)$. Rafinarea se bazează pe: \r\n\r\n_Observaţia 3_: „Să presupunem că dorim să calculăm $MinY[X]$. Facem următoarea afirmaţie: orice poziţie \"rea\" pentru $X$ (în care dacă mutăm pierdem) va fi _rea_ şi pentru $X + 1$.”\r\n\r\nAcest lucru este simplu de observat dacă privim ce înseamnă că o poziţie $Q$ e rea pentru $X$: \r\n\r\n* $MinY[Q] > X - Q$, pentru $X$;\r\n* $MinY[Q] > X - Q + 1$, pentru $X + 1$.\r\n\r\nEste evident că prima relaţie o implică pe cea de-a doua. În momentul acesta se poate construi următorul algoritm: având lista de poziţii care pot fi bune pentru $X$ (sortată descrescător) o căutăm pe cea mai mare ca valoare care este într-adevăr bună. În principiu, scoatem din capul listei poziţiile rele până când dăm de o poziţie bună. La listă se va adăuga şi $X$ şi se va trece la pasul următor. Operaţiile algoritmului sunt chiar operaţiile asupra unui deque.\r\n\r\nh3(#problema-5). Problema 5: \'Cut the Sequence\':http://acm.pku.edu.cn/JudgeOnline/problem?id=3017 (PKU) \r\n\r\n(deque cu arbori de intervale, zice Paul)\r\n...\r\n\r\nh3(#problema-6). Problema 6: \'Bcrc\':problema/bcrc (Stelele Informaticii 2006)\r\n\r\nbq. Se consideră $N$ camere, numerotate de la $1$ la $N$, aşezate în cerc. Iniţial (la momentul de timp 0), ne aflăm în camera $1$. În fiecare moment de timp, putem alege să rămânem în camera în care ne aflăm sau să ne deplasăm într-o cameră vecină într-o unitate de timp. Se dă o listă de $M$ cutii ce conţin bomboane prin $T$, $C$ şi $B$: cutia apare la momentul $T$ în camera $C$ şi conţine $B$ bomboane. Cutia va dispărea la momentul $T + 1$.\r\nCerinţă: Cunoscând numărul de camere din labirint şi momentele de timp la care apar cutiile cu bomboane, determinaţi care este numărul maxim de bomboane pe care le putem culege.\r\nRestricţii: $3 &le; N &le; 2 048$, $0 &le; M &le; 50 000$, $1 &le; T &le; 1 000 000 000$, $1 &le; C &le; N$, $1 &le; B &le; 9 999$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia foloseşte metoda programării dinamice.\r\n\r\np=. !deque-si-aplicatii?bcrc.png 40%!\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nFilozofia din spatele structurii de deque devine utilă, de obicei, în momentele finale ale rezolvării unei probleme. Însă, ce pot spune cu certitudine este că această structură de date pe cât este de simplă pe atât este de eficientă.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\nÎnţelegerea profundă a acestei structuri simple nu se poate realiza decât prin rezolvarea a cât mai multe probleme. Succes!\r\n\r\n* \'Deque\':problema/deque, _Arhiva educaţională_\r\n* \'Secvenţă\':problema/secventa\r\n* \'Secvenţă 3\':problema/secv3\r\n* \'Secvenţă 4\':problema/secv4\r\n* \'Vila 2\':problema/vila2, _.campion_\r\n* \'Sum 2\':problema/sum2, _Stelele Informaticii 2003_\r\n* \'Drept 2\':problema/drept2, _Lotul Naţional de Informatică, 2006_\r\n* \'Copaci 2\':problema/copaci2, _.campion_\r\n* \'Brânză\':problema/branza\r\n* \'Struţi\':problema/struti\r\n* \'Trompetă\':problema/trompeta\r\n* \'Buline\':problema/buline\r\n* \'Balans\':problema/balans\r\n* \'Gard\':problema/gard, _ONI 2002_\r\n* \'Ghiozdan\':problema/ghiozdan\r\n* \'Munte4\':problema/munte4, _Lotul Naţional de Informatică, 2005_\r\n* \'Cover\':problema/cover, _ONI 2007, Baraj_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Cosmin Negruşeri, \"_Probleme cu secvenţe_\":probleme-cu-secvente\r\n# Dana Lica, \"_Arbori de intervale şi aplicaţii în geometria computaţională_\":arbori-de-intervale',3146,'public',NULL,NULL),('deque-si-aplicatii','Deque și aplicații','2009-01-22 22:28:12','2009-01-28 22:01:01','h1. Deque şi aplicaţii\r\n\r\n(Categoria _Structuri de date_, Autor _Xulescu_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'Introducere\':deque-si-aplicatii#introducere\r\n* \'Operaţii\':deque-si-aplicatii#operatii\r\n* \'Aplicaţii\':deque-si-aplicatii#aplicatii\r\n** \'Problema 1: Book Pile &#40;SGU&#41;\':deque-si-aplicatii#problema-1\r\n** \'Problema 2: Şir\':deque-si-aplicatii#problema-2\r\n** \'Problema 3: Trans &#40;ONI 2004&#41;\':deque-si-aplicatii#problema-3\r\n** \'Problema 4: Otilia &#40;.campion&#41;\':deque-si-aplicatii#problema-4\r\n** \'Problema 5: Cut the Sequence &#40;PKU&#41;\':deque-si-aplicatii#problema-5\r\n** \'Problema 6: Bcrc &#40;Stelele Informaticii 2006&#41;\':deque-si-aplicatii#problema-6\r\n* \'Concluzii\':deque-si-aplicatii#concluzii\r\n* \'Probleme suplimentare\':deque-si-aplicatii#probleme-suplimentare\r\n* \'Bibliografie\':deque-si-aplicatii#bibliografie\r\n\r\nÎn acest articol voi prezenta o structură de date de tip listă numită _deque_. Simplitatea acestei structuri poate nu are multe de spus şi din acest motiv am prezentat şi o serie de aplicaţii care vor arăta neaşteptata sa utilitate şi apariţie în locurile unde am fi crezut că nu se mai poate face nimic pentru a reduce complexitatea.\r\n\r\nh2(#introducere). Introducere\r\n\r\n_Dequeul_ (pronunţat de obicei _deck_) poate fi privit ca o colecţie de tip listă ce are două capete prin care se şterg sau inserează noi elemente. În literatura de specialitate, aceste capete se numesc _head_ şi _tail_, iar dequeul mai este recunoscut şi ca fiind o coadă cu două capete _(double ended queue)_.\r\n\r\nUn deque poate fi implementat folosind liste dublu înlănţuite, sau cu un vector static când se cunoaşte numărul elementelor din colecţie. Ce trebuie reţinut este că limbajul C++ pune la dispoziţia utilizatorilor prin intermediul headerului _#include <deque>_ clasa _std::deque_.\r\n\r\nh2(#operatii). Operaţii\r\n\r\nMai jos sunt enumerate operaţiile care pot fi efectuate asupra unui deque împreună cu corespondentul lor în limbajul C++:\r\n\r\n* _front()_:	    întoarce primul element;\r\n* _back()_:	    întoarce ultimul element;\r\n* _push_front()_: inserează un element în faţă;\r\n* _push_back()_:  inserează un element în spate;\r\n* _pop_front()_:  scoate primul element;\r\n* _pop_back()_:   scoate ultimul element;\r\n* _empty()_:      întoarce _true_ dacă dequel este gol.\r\n\r\np=. !deque-si-aplicatii?new_deque.png 75%!\r\n\r\nToate aceste operaţii se execută în timp $O(1)$ \'amortizat\':http://en.wikipedia.org/wiki/Amortized_analysis. Pentru un plus de viteză va trebui să folosim un vector static cu dimensiunea egală cu numărul maxim de elemente ce pot trece prin deque, iar operaţiile implementate „de mână”, cu doi indecşi ce indică către head şi tail. Însă, în majoritatea aplicaţiilor limita de timp permite folosirea lejerităţii şi siguranţei clasei _std::deque_.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\nFolosiţi deque! Foarte sănătos! :)\r\n\r\nh3(#problema-1). Problema 1: \'Book Pile\':http://acm.sgu.ru/problem.php?contest=0&problem=271 (SGU)\r\n\r\nbq. Se dau $N$ cărţi aşezate una deasupra celeilalte asupra cărora se vor efecta $M$ operaţii de două tipuri: 1. $ADD${$(nume)$} : se adaugă cartea $nume$ deasupra celorlalte; 2. $ROTATE$ : primele $K$ cărţi de deasupra se rotesc (dacă sunt mai puţin de $K$ cărţi atunci se vor roti toate). Se cere să se afişeze cărţile în ordine, prima fiind cea de deasupra, după efectuarea celor $M$ operaţii.\r\nRestricţii: $0 &le; N, K &le; 40 000$, $0 &le; M &le; 100 000$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se poate deduce urmând paşii următori. Să presupunem că avem cărţile $A B C$ iniţial şi $K = 3$. Dacă îl vom adăuga pe $D$, atunci nu vor rămâne importante decât cărţile $D A B$, deoarece, dacă vom roti ulterior ultimele $K$ cărţi, $C$ nu va mai fi niciodată considerat, cărţile fiind doar adăugate, iar o dată ce o carte iese din „top {$K$}” cărţi nu va mai fi posibil să i se schimbe poziţia pe raft. Să rotim acum „top {$K$}” cărţi. Noua ordine va fi $B A D$ şi $C$ pe raft la loc sigur. Dacă îl vom adăuga pe $E$, topul se va schimba în $E B A$ iar pe raft, în mod sigur vor fi, în această ordine, $D C$. Proprietatea celor $K$ cărţi din vârf este: o secvenţă continuă de elemente, la care se adaugă noi elemente sau se elimină dintre acestea numai pe la _capete_. Aceste capete sunt chiar head şi tail ale unui deque.\r\n\r\np=. !deque-si-aplicatii?bookpile.png 40%!\r\n\r\nLa final, când se vor termina operaţiile, cărţilor de pe raft li se vor adăuga cele din deque şi se va afişa soluţia. În cazul presupus, soluţia va fi: $E B A D C$.\r\n\r\nÎntrucât operaţiile unui deque se execută în $O(1)$ amortizat, soluţia are complexitatea $O(N + M)$.\r\n\r\nh3(#problema-2). Problema 2: \'Sir\':problema/sir\r\n\r\nbq. Se dă un şir $S$ de numere întregi de lungime $N$. Se cere să se găsească secvenţa de lungime maximă cuprinsă între $X$ şi $Y$ astfel încât $MAX - MIN &le; Z$, unde $MAX$ este maximul dintre toate numerele întregi din secvenţă iar $MIN$ minimul dintre acestea. Secvenţa soluţie va fi cea cu poziţia de început maximă dintre toate secvenţele de lungime maximă.\r\nRestricţii: $3 &le; N &le; 100 000$, $1 &le; X &le; Y &le; N$, $0 &le; Z &le; 30 000$.\r\n\r\nh3. Soluţie\r\n\r\nVoi prezenta mai jos o rafinare a soluţiei în trei paşi.\r\n\r\nPrima rezolvare se găseşte uşor, deoarece nu facem decât să urmărim textul: pentru fiecare poziţie $i$ fixată ({$i$} ia valorile $1$, $2$, .., $N$ succesiv) vom determina pentru aceasta secvenţa cerută, adică vom plimba un $j$ între poziţiile $i - Y$ şi $i - X$. Pentru un interval $(j, i]$ vom determina $MAX$ şi $MIN$ în $O(log{~2~}N)$ cu un arbore de intervale, iar daca diferenţa dintre acestea nu depăşeşte $Z$ vom compara cu soluţia finală. Complexitatea finală va fi $O(N * (Y - X) * log{~2~}Y)$.\r\n\r\np=. !deque-si-aplicatii?sir.png 60%!\r\n\r\nSă presupunem că pentru poziţia curentă $i$, l-am găsit pe $j$ cuprins între $i - Y$ şi $i - X$ care îndeplineşte optimul. Ce proprietăţi are $j$?\r\n\r\n* $i - Y &le; j &le; i - X$ şi $MAX - MIN &le; Z$;\r\n* dacă îl incrementăm pe $j$ la $j + 1$ atunci dacă $j &le; i - X$ cu siguranţă $MAX - MIN &le; Z$ şi astfel soluţia va fi mai scurtă;\r\n* dacă îl decrementăm pe $j$, atunci ori $j < i - Y$ ori $MAX - MIN > Z$;\r\n* dacă îl incrementăm pe $i$ la $i + 1$, atunci se poate întâmpla ca $j < i - Y$; cum $MAX$ nu poate decât să crească, iar $MIN$ decât să scadă, se mai poate de asemenea întâmpla ca $MAX - MIN > Z$.\r\n\r\nDatorită proprietăţilor de mai sus, când trecem de la $i$ la $i + 1$, valoarea lui $j$ nu poate decât să crească cât timp $j < i - Y$ sau $MAX - MIN > Z$ şi $j$ nu a depăşit poziţia $i - X$. Pentru determinarea lui $MAX$, respectiv lui $MIN$ se poate folosi un arbore de intervale. Complexitatea finală va fi $O(N * log{~2~}(Y))$.\r\n\r\nCu cei doi indici $i$ şi $j$ vom accesa fiecare element din cele $N$ de cel mult $2$ ori, o dată cu $i$ şi o dată cu $j$. Să vedem cum putem îmbunătăţi complexitatea $O(log{~2~}Y)$ pentru determinarea maximului şi minimului.\r\n\r\nPentru fixarea ideilor să urmărim cum îl calculăm pe $MAX$. Observaţia care ne ajută în multe probleme pentru reducerea complexităţii de la $O(log{~2~}N)$ la $O(1)$ amortizat este următoarea: \r\n\r\n_Observaţie_: „Fixăm $i{~1~}$ şi $i{~2~}$ astfel încât $j < i{~1~} < i{~2~} &le; i$. Atunci, dacă $S[i{~2~}] > S[i{~1~}]$ poziţia $i{~2~}$ va fi întotdeauna mai importantă decât poziţia $i{~1~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ şi $i{~2~}$ nu vor mai fi ambele în intervalul $(j, i]$, poziţia eliminată va fi {$i{~1~}$}. Dacă însă $S[i{~1~}] > S[i{~2~}]$, atunci poziţia $i{~1~}$ va umbri poziţia $i{~2~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ va fi eliminat, atunci e posibil ca $i{~2~}$ să fie un candidat la $MAX$ dintre restul elementelor de la dreapta sa. În acest caz, nu putem afirma nimic şi vom păstra cele două poziţii.”\r\n\r\nRezultă din această observaţie că în intervalul $(j, i]$ poziţiile importante vor fi $j < i{~1~} < i{~2~} < .. < i{~k~} <= i$ astfel încât $S[i{~1~}] > S[i{~2~}] > .. > S[i{~k~}]$. Astfel, $MAX$ va fi $S[i{~1~}]$. Când îl vom incrementa pe $i$ la $i + 1$ vom şterge din poziţiile $i{~k~}$, $i{~k-1~}$, ... atâta timp cât $S[i + 1]$ este mai important, adică mai mare decât valorile de pe aceste poziţii, şi vom şterge $i{~1~}$, $i{~2~}$, ... atâta timp cât aceste poziţii sunt mai mici sau egale decât $j\'$. Indicele $j\'$ este noul optim pentru poziţia $i + 1$. Proprietatea şirului de poziţii $i{~1~}, i{~2~}, .., i{~k~}$ este că se reprezintă ca un şir contiguu de numere care permite inserarea elementelor prin dreapta şi ştergerea prin stânga, adică se adaugă elemente la tail şi se şterg elemente de la head. Îl putem deci reprezenta printr-un deque. Complexitatea $O(1)$ amortizat provine de la faptul că fiecare poziţie dintre cele $N$ nu trece decât o singură dată prin deque şi este şters tot cel mult o singură dată. \r\n\r\nÎn practică, programul poate arăta în felul următor:\r\n\r\n== code(cpp) |\r\n// ...\r\n\r\ndeque <int> min_deq, max_deq;\r\n\r\ntypedef int (*PF)(const int , const int ) ;\r\n\r\nint min_fct(const int a, const int b) { return a < b; }\r\n\r\nint max_fct(const int a, const int b) { return a > b; }\r\n\r\nvoid push_in(deque <int>& deq, const int p, PF compare) {\r\n    for (; !deq.empty() && compare(S[p], S[deq.back()]); deq.pop_back()) ;\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque <int>& deq, const int j) {\r\n    for (; !deq.empty() && deq.front() <= j; deq.pop_front()) ;\r\n    return S[deq.front()];\r\n}\r\n\r\nint main(void) {\r\n    // ...\r\n    for (int i = 1; i <= N; ++ i) {\r\n        push_in(min_deq, i, min_fct);\r\n        push_in(max_deq, i, max_fct);\r\n        while ((j < i - Y || query(max_deq, j) - query(min_deq, j) > Z) && j < i - X)\r\n            j ++;\r\n        // (j, i] este intervalul candidat la soluţia pentru pozitia i\r\n        if (j <= i - X) if (query(max_deq, j) - query(min_deq, j) <= Z)\r\n            // compară cu rezultatul de până acum\r\n    }\r\n    // ...\r\n}\r\n==\r\n\r\nComplexitatea finală va fi $O(N)$.\r\n\r\nh3(#problema-3). Problema 3: \'Trans\':problema/trans (ONI 2004)\r\n\r\nbq. Se dau $N$ blocuri de piatră, de culoare albă sau neagră aşezate în ordinea $1$, $2$,.., $N$. Blocurile de piatră trebuie să fie transportate în ordinea în care sunt, iar pentru aceasta va trebui închiriat un camion. Se mai dau $Q$ tipuri de camioane. Camionul de tipul $i (1 &le; i &le; Q)$ poate transporta maxim $K{~i~}$ blocuri de piatră la un moment dat şi pentru un transport se percepe taxa $T{~i~}$. Se impune condiţia ca toate blocurile de piatră plasate în camion la un transport sa aibă aceeaşi culoare. Aşadar, pentru a fi transportate toate blocurile, se va alege un camion de un anumit tip, iar camionul va efectua unul sau mai multe transporturi. Pentru a micşora suma totală plătită, există posibilitatea de a schimba culoarea oricărui bloc de piatră (din alb în negru sau din negru în alb); pentru fiecare bloc $i (1 &le; i &le; N)$ se cunoaşte suma $S{~i~}$ ce trebuie plătită pentru a-i schimba culoarea $C{~i~}$.\r\nCerinţă: Pentru fiecare dintre cele $Q$ tipuri de camioane, determinaţi suma minimă plătită pentru a transporta toate cele $N$ blocuri.\r\nRestricţii: $1 &le; N &le; 16 000$, $1 &le; Q &le; 100$, $1 &le; K{~i~} &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se bazează pe găsirea unei formule de recurenţă ce respectă principiul optimalităţii al metodei programării dinamice.\r\n\r\nPentru început, fixăm un camion dintre cele $Q$. Fie $K$ numărul maxim de pietre pe care acesta le poate transporta şi $T$ taxa percepută. Notăm $sum[i][&#99;]$ costul pentru a schimba toate pietrele $1$, $2$, .., $i$ în culoarea $c$ ({$c = 0$} pentru alb şi $c = 1$ pentru negru). În $sum[i][&#99;]$ se vor aduna toate valorile $S[j]$, cu $j &le; i$ pentru care $C[j] = 1 - c$. \r\n\r\nÎn continuare, considerăm $bst[i][&#99;]$ costul minim pentru a transporta pietrele $1$, $2$, .., $i$, iar ultimul transport conţine pietre de culoare $c$. Întrucât nu putem transporta mai mult de $K$ pietre, $bst[i][&#99;]$ depinde doar de poziţiile $i - K$, $i - K + 1$, ..., $i - 1$. Cunoaştem că ultimul camion va transporta o secvenţă continuă de pietre începând de la o poziţie $j + 1$ până la poziţia $i$, unde $i - K &le; j &le; i - 1$. Astfel, pentru fiecare $j$ în intervalul precedent, costul va fi $Min(bst[j][&#48;], bst[j][&#49;])$ (transportăm primele j pietre cât mai ieftin) adunat cu $sum[i][&#99;] - sum[j][&#99;]$ (costul transformării pietrelor $j + 1$, .., $i$ în culoarea $c$) şi plus taxa $T$. Rezultă recurenţa:\r\n\r\n* $bst[i][&#99;] = Min{ Min(bst[j][&#48;], bst[j][&#49;]) + sum[i][&#99;] - sum[j][&#99;] } + T$, unde $i - K &le; j &le; i - 1$.\r\n\r\nDacă ne vom opri aici, complexitatea soluţiei va fi $O(Q * N^2^)$.\r\n\r\nRelaţia de recurenţă poate fi îmbunătăţită. Observăm că pentru poziţia $i$, $sum[i][&#99;]$ este o valoare constantă, ca şi $T$. Astfel, deducem următoarea relaţie de recurenţă:\r\n\r\n* $bst[i][&#99;] = Min{ Min(bst[j][&#48;], bst[j][&#49;]) - sum[j][&#99;] } + sum[i][&#99;] + T$, unde $i - K &le; j &le; i - 1$.\r\n\r\nNotez în continuare, pentru uşurinţă în scriere, $X[j][&#99;] = Min(bst[j][&#48;], bst[j][&#49;]) - sum[j][&#99;]$. Să fixăm doi indici $i{~1~}$ şi $i{~2~}$, astfel încât $i - K &le; $i{~1~}$ < $i{~2~}$ &le; i - 1$. Dacă $X[i{~1~}][&#99;] > X[i{~2~}][&#99;]$ atunci, întotdeauna poziţia $i{~2~}$ va fi preferată poziţiei $i{~1~}$. Când cele două nu se vor mai afla în intervalul $[i - K, i - 1]$, poziţia eliminată va fi poziţia $i{~1~}$. Dacă $X[i{~1~}][&#99;] < X[i{~2~}][&#99;]$, atunci nu putem decide care poziţie este mai bună în viitor, aşa că le vom păstra pe ambele. Rezultă mai departe că în intervalul $[i - K, i - 1]$ vom avea o serie de indecşi candidaţi la minim $i - K &le; i{~1~} < i{~2~} < .. < i{~n~} &le; i - 1$ astfel încât $X[i{~1~}][&#99;] < X[i{~2~}][&#99;] <  .. < X[i{~n~}][&#99;]$. Mai departe, găsim $bst[i][&#99;]$ ca fiind $X[i{~1~}][&#99;] + sum[i][&#99;] + T$. Urmează să îl introducem şi pe $X[i][&#99;]$, el fiind egal cu $Min(bst[i][&#48;], bst[i][&#49;]) - sum[i][&#99;]$, în şirul de indecşi de mai sus. Acest lucru se va face în felul următor: se vor elimina din $i{~n~}$, $i{~n-1~}$, ... atâta timp cât $X[$i{~n~}$][&#99;] > X[i][&#99;]$, $X[$i{~n-1~}$][&#99;] > X[i][&#99;]$, ... adică atâta timp cât poziţia $i$ este preferată lui $i{~n~}$, $i{~n-1~}$... Fiind la poziţia $i + 1$, intervalul se va transforma în $[i - K + 1, i]$, aşadar, vom mai elimina din primii indici $i{~1~}$, $i{~2~}$,... atâta timp cât $i{~1~} < i - K + 1$, $i{~2~} < i - K + 1$...\r\n\r\nDupă cum am arătat şi la problema precedentă, acest şir de indecşi $i{~1~}$, $i{~2~}$, .., $i{~n~}$ are proprietatea că este un şir continuu de numere care admite inserări prin dreapta (tail) şi ştergeri prin stânga (head). Şir ce poate fi reprezentat printr-un deque. Cum fiecare index dintre $1$, $2$, .., $N$ va trece o singură dată prin deque şi va fi şters cel mult o dată, complexitatea soluţiei în acest caz va fi $O(Q * N)$.\r\n\r\nÎn practică, programul este scurt, clar şi foarte eficient:\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\n#include <vector>\r\n#include <deque>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\nconst char iname[] = \"trans.in\";\r\nconst char oname[] = \"trans.out\";\r\n\r\n#define MAXN  16005\r\n#define Min(a, b) ((a) < (b) ? (a) : (b))\r\n#define FOR(i, a, b)  for (int i = (a); i <= (b); ++ i)\r\n\r\nint C[MAXN], S[MAXN], bst[MAXN][2], sum[MAXN][2], N;\r\n\r\nvoid insert(deque < pair <int, int> >& deq, const pair <int, int>& p) {\r\n    while (!deq.empty() && deq.back().second > p.second)\r\n        deq.pop_back();\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque < pair <int, int> >& deq, const int idx) {\r\n    while (deq.front().first < idx)\r\n        deq.pop_front();\r\n    return deq.front().second;\r\n}\r\n\r\nint work(const int K, const int T) {\r\n    deque < pair <int, int> > deq[2];       // pair (idx, value)\r\n    FOR (c, 0, 1)\r\n        insert(deq[c], pair <int, int>(0, 0));\r\n    FOR (i, 1, N) {   // obiectul i\r\n        FOR (c, 0, 1) // culoare\r\n            bst[i][c] = query(deq[c], i - K) + sum[i][c] + T;\r\n        FOR (c, 0, 1)\r\n            insert(deq[c], pair <int, int>(i, Min(bst[i][0], bst[i][1]) - sum[i][c]));\r\n    }\r\n    return Min(bst[N][0], bst[N][1]);\r\n}\r\n\r\nint main(void)\r\n{\r\n    ifstream in(iname);  ofstream out(oname);\r\n    in >> N;\r\n    FOR (i, 1, N) {\r\n        in >> C[i] >> S[i];\r\n        FOR (c, 0, 1)\r\n            sum[i][c] += sum[i - 1][c];\r\n        sum[i][1 - C[i]] += S[i];\r\n    }\r\n    int cnt, K, T;\r\n    in >> cnt;\r\n    FOR (i, 1, cnt)\r\n        in >> K >> T, out << work(K, T) << \"\\n\";\r\n\r\n    in.close(), out.close();\r\n    return 0;\r\n}\r\n==\r\n\r\nh3(#problema-4). Problema 4: \'Otilia\':problema/otilia  (.campion)\r\n\r\nbq. Otilia şi Burbucel au o grămadă de $N$ pietre şi vor juca un joc cu următoarele trei reguli: 1. Primul jucător are voie să ia din gramadă cel mult $K$ piese; 2. Cu excepţia primei mutări, fiecare jucător are voie să ia maxim $P * t$ pietre, unde $t$ este numărul de pietre care au fost substituite din grămadă la mutarea precedentă; 3. Pierde cel care mută ultimul (cel care ia ultimele pietre din grămadă).\r\nCerinţă: Se dau $M$ jocuri prin numerele $N$, $K$ şi $P$. Se cere să se determină dacă Otilia va câştiga fiecare din jocuri sau nu.\r\nRestricţii: $1 &le; M &le; 30 000$, $1 &le; N &le; 5 000 000$, $1 &le; K &le; N$, $1 &le; P &le; 10$.\r\n\r\nh3. Soluţie:\r\n\r\nProblema se rezolvă prin programare dinamică. Soluţia se bazează pe observaţia de mai jos. Considerăm $P$-ul fixat şi notăm cu $stare(X, Y)$ poziţia de start în care avem $X$ pietre şi numărul maxim de pietre care se pot lua la prima mutare este $Y$.\r\n\r\n_Observaţia 1_: „Dacă există strategie sigură de câştig pentru $stare(X, Y)$ atunci există şi pentru orice $stare(X, T)$ cu $T &ge; Y$.” \r\n\r\nDe ce? Pentru că orice mutare validă pentru $stare(X, Y)$ este validă şi pentru $stare(X, T)$. Având această observaţie notăm cu $MinY[X] = Y$, $Y$ minim astfel încât avem strategie de câştig pentru $stare(X, Y)$.\r\n\r\n_Observaţia 2_: „$stare(X, Y)$ este pierzătoare dacă şi numai dacă $Y < MinY[X]$.” \r\n\r\nAceasta reiese din definiţia lui $MinY[X]$.\r\n\r\n$MinY[X]$ se calculează după următoarea recurenţă, care rezultă din regulile jocului: \r\n\r\n* $MinY[X]$ este cel mai mic $i$ pentru care avem $MinY[X - i] > P * i$.\r\n\r\nDe aici se naşte prima soluţie, care este implementarea directă a recurenţei. Deşi complexitatea acesteia pare a fi $O(N^2^)$ ea se comportă foarte bine pentru $N &le; 500 000$. Aşadar, această soluţie acoperă aproximativ $50%$ din testele de intrare. Printr-o rafinare a acestei soluţii se obţine un algoritm de complexitate $O(N)$. Rafinarea se bazează pe: \r\n\r\n_Observaţia 3_: „Să presupunem că dorim să calculăm $MinY[X]$. Facem următoarea afirmaţie: orice poziţie \"rea\" pentru $X$ (în care dacă mutăm pierdem) va fi _rea_ şi pentru $X + 1$.”\r\n\r\nAcest lucru este simplu de observat dacă privim ce înseamnă că o poziţie $Q$ e rea pentru $X$: \r\n\r\n* $MinY[Q] > X - Q$, pentru $X$;\r\n* $MinY[Q] > X - Q + 1$, pentru $X + 1$.\r\n\r\nEste evident că prima relaţie o implică pe cea de-a doua. În momentul acesta se poate construi următorul algoritm: având lista de poziţii care pot fi bune pentru $X$ (sortată descrescător) o căutăm pe cea mai mare ca valoare care este într-adevăr bună. În principiu, scoatem din capul listei poziţiile rele până când dăm de o poziţie bună. La listă se va adăuga şi $X$ şi se va trece la pasul următor. Operaţiile algoritmului sunt chiar operaţiile asupra unui deque.\r\n\r\nh3(#problema-5). Problema 5: \'Cut the Sequence\':http://acm.pku.edu.cn/JudgeOnline/problem?id=3017 (PKU) \r\n\r\n(deque cu arbori de intervale, zice Paul)\r\n...\r\n\r\nh3(#problema-6). Problema 6: \'Bcrc\':problema/bcrc (Stelele Informaticii 2006)\r\n\r\nbq. Se consideră $N$ camere, numerotate de la $1$ la $N$, aşezate în cerc. Iniţial (la momentul de timp 0), ne aflăm în camera $1$. În fiecare moment de timp, putem alege să rămânem în camera în care ne aflăm sau să ne deplasăm într-o cameră vecină într-o unitate de timp. Se dă o listă de $M$ cutii ce conţin bomboane prin $T$, $C$ şi $B$: cutia apare la momentul $T$ în camera $C$ şi conţine $B$ bomboane. Cutia va dispărea la momentul $T + 1$.\r\nCerinţă: Cunoscând numărul de camere din labirint şi momentele de timp la care apar cutiile cu bomboane, determinaţi care este numărul maxim de bomboane pe care le putem culege.\r\nRestricţii: $3 &le; N &le; 2 048$, $0 &le; M &le; 50 000$, $1 &le; T &le; 1 000 000 000$, $1 &le; C &le; N$, $1 &le; B &le; 9 999$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia foloseşte metoda programării dinamice.\r\n\r\nO stare se reprezintă prin camera în care ne aflăm şi momentul de timp. Fie $bst[i][j]$ numărul maxim de bomboane culese până în momentul $i$ când ne găsim în camera $j$. O observaţie evidentă este că $bst[i][j]$ se poate modifica doar în momentele în care apar cutiile. Prin urmare, vom considera momentele de timp $j$ când apar cutiile, momente ce sunt în număr de $M$. De cine depinde această stare? Ştim că $bst[i - 1][1 ... N]$ a fost deja calculat în mod optim. Atunci, legătura se va realiza între momentele de timp. Să notăm cu $T$ diferenţa de timp dintre momentele la care apare cutia $i$ şi cutia la care apare cutia $i - 1$. Din acest moment $j$ şi camera $i$ ne putem deplasa maxim $T$ camere spre stânga sau spre dreapta. De unde deducem că:\r\n\r\n* $bst[i][j] = Min { bst[i - 1][j - T], bst[i - 1][j - T + 1], ..., bst[i - 1][j], ..., bst[i - 1][j + T - 1], bst[i - 1][j + T] }$.\r\n\r\nVa urma...\r\n\r\np=. !deque-si-aplicatii?bcrc.png 40%!\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nFilozofia din spatele structurii de deque devine utilă, de obicei, în momentele finale ale rezolvării unei probleme. Însă, ce pot spune cu certitudine este că această structură de date pe cât este de simplă pe atât este de eficientă.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\nÎnţelegerea profundă a acestei structuri simple nu se poate realiza decât prin rezolvarea a cât mai multe probleme. Succes!\r\n\r\n* \'Deque\':problema/deque, _Arhiva educaţională_\r\n* \'Secvenţă\':problema/secventa\r\n* \'Secvenţă 3\':problema/secv3\r\n* \'Secvenţă 4\':problema/secv4\r\n* \'Vila 2\':problema/vila2, _.campion_\r\n* \'Sum 2\':problema/sum2, _Stelele Informaticii 2003_\r\n* \'Drept 2\':problema/drept2, _Lotul Naţional de Informatică, 2006_\r\n* \'Copaci 2\':problema/copaci2, _.campion_\r\n* \'Brânză\':problema/branza\r\n* \'Struţi\':problema/struti\r\n* \'Trompetă\':problema/trompeta\r\n* \'Buline\':problema/buline\r\n* \'Balans\':problema/balans\r\n* \'Gard\':problema/gard, _ONI 2002_\r\n* \'Ghiozdan\':problema/ghiozdan\r\n* \'Munte4\':problema/munte4, _Lotul Naţional de Informatică, 2005_\r\n* \'Cover\':problema/cover, _ONI 2007, Baraj_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Cosmin Negruşeri, \"_Probleme cu secvenţe_\":probleme-cu-secvente\r\n# Dana Lica, \"_Arbori de intervale şi aplicaţii în geometria computaţională_\":arbori-de-intervale',3146,'public',NULL,NULL),('deque-si-aplicatii','Deque și aplicații','2009-01-22 22:28:12','2009-01-28 22:13:22','h1. Deque şi aplicaţii\r\n\r\n(Categoria _Structuri de date_, Autor _Xulescu_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'Introducere\':deque-si-aplicatii#introducere\r\n* \'Operaţii\':deque-si-aplicatii#operatii\r\n* \'Aplicaţii\':deque-si-aplicatii#aplicatii\r\n** \'Problema 1: Book Pile &#40;SGU&#41;\':deque-si-aplicatii#problema-1\r\n** \'Problema 2: Şir\':deque-si-aplicatii#problema-2\r\n** \'Problema 3: Trans &#40;ONI 2004&#41;\':deque-si-aplicatii#problema-3\r\n** \'Problema 4: Otilia &#40;.campion&#41;\':deque-si-aplicatii#problema-4\r\n** \'Problema 5: Cut the Sequence &#40;PKU&#41;\':deque-si-aplicatii#problema-5\r\n** \'Problema 6: Bcrc &#40;Stelele Informaticii 2006&#41;\':deque-si-aplicatii#problema-6\r\n* \'Concluzii\':deque-si-aplicatii#concluzii\r\n* \'Probleme suplimentare\':deque-si-aplicatii#probleme-suplimentare\r\n* \'Bibliografie\':deque-si-aplicatii#bibliografie\r\n\r\nÎn acest articol voi prezenta o structură de date de tip listă numită _deque_. Simplitatea acestei structuri poate nu are multe de spus şi din acest motiv am prezentat şi o serie de aplicaţii care vor arăta neaşteptata sa utilitate şi apariţie în locurile unde am fi crezut că nu se mai poate face nimic pentru a reduce complexitatea.\r\n\r\nh2(#introducere). Introducere\r\n\r\n_Dequeul_ (pronunţat de obicei _deck_) poate fi privit ca o colecţie de tip listă ce are două capete prin care se şterg sau inserează noi elemente. În literatura de specialitate, aceste capete se numesc _head_ şi _tail_, iar dequeul mai este recunoscut şi ca fiind o coadă cu două capete _(double ended queue)_.\r\n\r\nUn deque poate fi implementat folosind liste dublu înlănţuite, sau cu un vector static când se cunoaşte numărul elementelor din colecţie. Ce trebuie reţinut este că limbajul C++ pune la dispoziţia utilizatorilor prin intermediul headerului _#include <deque>_ clasa _std::deque_.\r\n\r\nh2(#operatii). Operaţii\r\n\r\nMai jos sunt enumerate operaţiile care pot fi efectuate asupra unui deque împreună cu corespondentul lor în limbajul C++:\r\n\r\n* _front()_:	    întoarce primul element;\r\n* _back()_:	    întoarce ultimul element;\r\n* _push_front()_: inserează un element în faţă;\r\n* _push_back()_:  inserează un element în spate;\r\n* _pop_front()_:  scoate primul element;\r\n* _pop_back()_:   scoate ultimul element;\r\n* _empty()_:      întoarce _true_ dacă dequel este gol.\r\n\r\np=. !deque-si-aplicatii?new_deque.png 75%!\r\n\r\nToate aceste operaţii se execută în timp $O(1)$ \'amortizat\':http://en.wikipedia.org/wiki/Amortized_analysis. Pentru un plus de viteză va trebui să folosim un vector static cu dimensiunea egală cu numărul maxim de elemente ce pot trece prin deque, iar operaţiile implementate „de mână”, cu doi indecşi ce indică către head şi tail. Însă, în majoritatea aplicaţiilor limita de timp permite folosirea lejerităţii şi siguranţei clasei _std::deque_.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\nFolosiţi deque! Foarte sănătos! :)\r\n\r\nh3(#problema-1). Problema 1: \'Book Pile\':http://acm.sgu.ru/problem.php?contest=0&problem=271 (SGU)\r\n\r\nbq. Se dau $N$ cărţi aşezate una deasupra celeilalte asupra cărora se vor efecta $M$ operaţii de două tipuri: 1. $ADD${$(nume)$} : se adaugă cartea $nume$ deasupra celorlalte; 2. $ROTATE$ : primele $K$ cărţi de deasupra se rotesc (dacă sunt mai puţin de $K$ cărţi atunci se vor roti toate). Se cere să se afişeze cărţile în ordine, prima fiind cea de deasupra, după efectuarea celor $M$ operaţii.\r\nRestricţii: $0 &le; N, K &le; 40 000$, $0 &le; M &le; 100 000$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se poate deduce urmând paşii următori. Să presupunem că avem cărţile $A B C$ iniţial şi $K = 3$. Dacă îl vom adăuga pe $D$, atunci nu vor rămâne importante decât cărţile $D A B$, deoarece, dacă vom roti ulterior ultimele $K$ cărţi, $C$ nu va mai fi niciodată considerat, cărţile fiind doar adăugate, iar o dată ce o carte iese din „top {$K$}” cărţi nu va mai fi posibil să i se schimbe poziţia pe raft. Să rotim acum „top {$K$}” cărţi. Noua ordine va fi $B A D$ şi $C$ pe raft la loc sigur. Dacă îl vom adăuga pe $E$, topul se va schimba în $E B A$ iar pe raft, în mod sigur vor fi, în această ordine, $D C$. Proprietatea celor $K$ cărţi din vârf este: o secvenţă continuă de elemente, la care se adaugă noi elemente sau se elimină dintre acestea numai pe la _capete_. Aceste capete sunt chiar head şi tail ale unui deque.\r\n\r\np=. !deque-si-aplicatii?bookpile.png 40%!\r\n\r\nLa final, când se vor termina operaţiile, cărţilor de pe raft li se vor adăuga cele din deque şi se va afişa soluţia. În cazul presupus, soluţia va fi: $E B A D C$.\r\n\r\nÎntrucât operaţiile unui deque se execută în $O(1)$ amortizat, soluţia are complexitatea $O(N + M)$.\r\n\r\nh3(#problema-2). Problema 2: \'Sir\':problema/sir\r\n\r\nbq. Se dă un şir $S$ de numere întregi de lungime $N$. Se cere să se găsească secvenţa de lungime maximă cuprinsă între $X$ şi $Y$ astfel încât $MAX - MIN &le; Z$, unde $MAX$ este maximul dintre toate numerele întregi din secvenţă iar $MIN$ minimul dintre acestea. Secvenţa soluţie va fi cea cu poziţia de început maximă dintre toate secvenţele de lungime maximă.\r\nRestricţii: $3 &le; N &le; 100 000$, $1 &le; X &le; Y &le; N$, $0 &le; Z &le; 30 000$.\r\n\r\nh3. Soluţie\r\n\r\nVoi prezenta mai jos o rafinare a soluţiei în trei paşi.\r\n\r\nPrima rezolvare se găseşte uşor, deoarece nu facem decât să urmărim textul: pentru fiecare poziţie $i$ fixată ({$i$} ia valorile $1$, $2$, .., $N$ succesiv) vom determina pentru aceasta secvenţa cerută, adică vom plimba un $j$ între poziţiile $i - Y$ şi $i - X$. Pentru un interval $(j, i]$ vom determina $MAX$ şi $MIN$ în $O(log{~2~}N)$ cu un arbore de intervale, iar daca diferenţa dintre acestea nu depăşeşte $Z$ vom compara cu soluţia finală. Complexitatea finală va fi $O(N * (Y - X) * log{~2~}Y)$.\r\n\r\np=. !deque-si-aplicatii?sir.png 60%!\r\n\r\nSă presupunem că pentru poziţia curentă $i$, l-am găsit pe $j$ cuprins între $i - Y$ şi $i - X$ care îndeplineşte optimul. Ce proprietăţi are $j$?\r\n\r\n* $i - Y &le; j &le; i - X$ şi $MAX - MIN &le; Z$;\r\n* dacă îl incrementăm pe $j$ la $j + 1$ atunci dacă $j &le; i - X$ cu siguranţă $MAX - MIN &le; Z$ şi astfel soluţia va fi mai scurtă;\r\n* dacă îl decrementăm pe $j$, atunci ori $j < i - Y$ ori $MAX - MIN > Z$;\r\n* dacă îl incrementăm pe $i$ la $i + 1$, atunci se poate întâmpla ca $j < i - Y$; cum $MAX$ nu poate decât să crească, iar $MIN$ decât să scadă, se mai poate de asemenea întâmpla ca $MAX - MIN > Z$.\r\n\r\nDatorită proprietăţilor de mai sus, când trecem de la $i$ la $i + 1$, valoarea lui $j$ nu poate decât să crească cât timp $j < i - Y$ sau $MAX - MIN > Z$ şi $j$ nu a depăşit poziţia $i - X$. Pentru determinarea lui $MAX$, respectiv lui $MIN$ se poate folosi un arbore de intervale. Complexitatea finală va fi $O(N * log{~2~}(Y))$.\r\n\r\nCu cei doi indici $i$ şi $j$ vom accesa fiecare element din cele $N$ de cel mult $2$ ori, o dată cu $i$ şi o dată cu $j$. Să vedem cum putem îmbunătăţi complexitatea $O(log{~2~}Y)$ pentru determinarea maximului şi minimului.\r\n\r\nPentru fixarea ideilor să urmărim cum îl calculăm pe $MAX$. Observaţia care ne ajută în multe probleme pentru reducerea complexităţii de la $O(log{~2~}N)$ la $O(1)$ amortizat este următoarea: \r\n\r\n_Observaţie_: „Fixăm $i{~1~}$ şi $i{~2~}$ astfel încât $j < i{~1~} < i{~2~} &le; i$. Atunci, dacă $S[i{~2~}] > S[i{~1~}]$ poziţia $i{~2~}$ va fi întotdeauna mai importantă decât poziţia $i{~1~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ şi $i{~2~}$ nu vor mai fi ambele în intervalul $(j, i]$, poziţia eliminată va fi {$i{~1~}$}. Dacă însă $S[i{~1~}] > S[i{~2~}]$, atunci poziţia $i{~1~}$ va umbri poziţia $i{~2~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ va fi eliminat, atunci e posibil ca $i{~2~}$ să fie un candidat la $MAX$ dintre restul elementelor de la dreapta sa. În acest caz, nu putem afirma nimic şi vom păstra cele două poziţii.”\r\n\r\nRezultă din această observaţie că în intervalul $(j, i]$ poziţiile importante vor fi $j < i{~1~} < i{~2~} < .. < i{~k~} <= i$ astfel încât $S[i{~1~}] > S[i{~2~}] > .. > S[i{~k~}]$. Astfel, $MAX$ va fi $S[i{~1~}]$. Când îl vom incrementa pe $i$ la $i + 1$ vom şterge din poziţiile $i{~k~}$, $i{~k-1~}$, ... atâta timp cât $S[i + 1]$ este mai important, adică mai mare decât valorile de pe aceste poziţii, şi vom şterge $i{~1~}$, $i{~2~}$, ... atâta timp cât aceste poziţii sunt mai mici sau egale decât $j\'$. Indicele $j\'$ este noul optim pentru poziţia $i + 1$. Proprietatea şirului de poziţii $i{~1~}, i{~2~}, .., i{~k~}$ este că se reprezintă ca un şir contiguu de numere care permite inserarea elementelor prin dreapta şi ştergerea prin stânga, adică se adaugă elemente la tail şi se şterg elemente de la head. Îl putem deci reprezenta printr-un deque. Complexitatea $O(1)$ amortizat provine de la faptul că fiecare poziţie dintre cele $N$ nu trece decât o singură dată prin deque şi este şters tot cel mult o singură dată. \r\n\r\nÎn practică, programul poate arăta în felul următor:\r\n\r\n== code(cpp) |\r\n// ...\r\n\r\ndeque <int> min_deq, max_deq;\r\n\r\ntypedef int (*PF)(const int , const int ) ;\r\n\r\nint min_fct(const int a, const int b) { return a < b; }\r\n\r\nint max_fct(const int a, const int b) { return a > b; }\r\n\r\nvoid push_in(deque <int>& deq, const int p, PF compare) {\r\n    for (; !deq.empty() && compare(S[p], S[deq.back()]); deq.pop_back()) ;\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque <int>& deq, const int j) {\r\n    for (; !deq.empty() && deq.front() <= j; deq.pop_front()) ;\r\n    return S[deq.front()];\r\n}\r\n\r\nint main(void) {\r\n    // ...\r\n    for (int i = 1; i <= N; ++ i) {\r\n        push_in(min_deq, i, min_fct);\r\n        push_in(max_deq, i, max_fct);\r\n        while ((j < i - Y || query(max_deq, j) - query(min_deq, j) > Z) && j < i - X)\r\n            j ++;\r\n        // (j, i] este intervalul candidat la soluţia pentru pozitia i\r\n        if (j <= i - X) if (query(max_deq, j) - query(min_deq, j) <= Z)\r\n            // compară cu rezultatul de până acum\r\n    }\r\n    // ...\r\n}\r\n==\r\n\r\nComplexitatea finală va fi $O(N)$.\r\n\r\nh3(#problema-3). Problema 3: \'Trans\':problema/trans (ONI 2004)\r\n\r\nbq. Se dau $N$ blocuri de piatră, de culoare albă sau neagră aşezate în ordinea $1$, $2$,.., $N$. Blocurile de piatră trebuie să fie transportate în ordinea în care sunt, iar pentru aceasta va trebui închiriat un camion. Se mai dau $Q$ tipuri de camioane. Camionul de tipul $i (1 &le; i &le; Q)$ poate transporta maxim $K{~i~}$ blocuri de piatră la un moment dat şi pentru un transport se percepe taxa $T{~i~}$. Se impune condiţia ca toate blocurile de piatră plasate în camion la un transport sa aibă aceeaşi culoare. Aşadar, pentru a fi transportate toate blocurile, se va alege un camion de un anumit tip, iar camionul va efectua unul sau mai multe transporturi. Pentru a micşora suma totală plătită, există posibilitatea de a schimba culoarea oricărui bloc de piatră (din alb în negru sau din negru în alb); pentru fiecare bloc $i (1 &le; i &le; N)$ se cunoaşte suma $S{~i~}$ ce trebuie plătită pentru a-i schimba culoarea $C{~i~}$.\r\nCerinţă: Pentru fiecare dintre cele $Q$ tipuri de camioane, determinaţi suma minimă plătită pentru a transporta toate cele $N$ blocuri.\r\nRestricţii: $1 &le; N &le; 16 000$, $1 &le; Q &le; 100$, $1 &le; K{~i~} &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se bazează pe găsirea unei formule de recurenţă ce respectă principiul optimalităţii al metodei programării dinamice.\r\n\r\nPentru început, fixăm un camion dintre cele $Q$. Fie $K$ numărul maxim de pietre pe care acesta le poate transporta şi $T$ taxa percepută. Notăm $sum[i][&#99;]$ costul pentru a schimba toate pietrele $1$, $2$, .., $i$ în culoarea $c$ ({$c = 0$} pentru alb şi $c = 1$ pentru negru). În $sum[i][&#99;]$ se vor aduna toate valorile $S[j]$, cu $j &le; i$ pentru care $C[j] = 1 - c$. \r\n\r\nÎn continuare, considerăm $bst[i][&#99;]$ costul minim pentru a transporta pietrele $1$, $2$, .., $i$, iar ultimul transport conţine pietre de culoare $c$. Întrucât nu putem transporta mai mult de $K$ pietre, $bst[i][&#99;]$ depinde doar de poziţiile $i - K$, $i - K + 1$, ..., $i - 1$. Cunoaştem că ultimul camion va transporta o secvenţă continuă de pietre începând de la o poziţie $j + 1$ până la poziţia $i$, unde $i - K &le; j &le; i - 1$. Astfel, pentru fiecare $j$ în intervalul precedent, costul va fi $Min(bst[j][&#48;], bst[j][&#49;])$ (transportăm primele j pietre cât mai ieftin) adunat cu $sum[i][&#99;] - sum[j][&#99;]$ (costul transformării pietrelor $j + 1$, .., $i$ în culoarea $c$) şi plus taxa $T$. Rezultă recurenţa:\r\n\r\n* $bst[i][&#99;] = Min{ Min(bst[j][&#48;], bst[j][&#49;]) + sum[i][&#99;] - sum[j][&#99;] } + T$, unde $i - K &le; j &le; i - 1$.\r\n\r\nDacă ne vom opri aici, complexitatea soluţiei va fi $O(Q * N^2^)$.\r\n\r\nRelaţia de recurenţă poate fi îmbunătăţită. Observăm că pentru poziţia $i$, $sum[i][&#99;]$ este o valoare constantă, ca şi $T$. Astfel, deducem următoarea relaţie de recurenţă:\r\n\r\n* $bst[i][&#99;] = Min{ Min(bst[j][&#48;], bst[j][&#49;]) - sum[j][&#99;] } + sum[i][&#99;] + T$, unde $i - K &le; j &le; i - 1$.\r\n\r\nNotez în continuare, pentru uşurinţă în scriere, $X[j][&#99;] = Min(bst[j][&#48;], bst[j][&#49;]) - sum[j][&#99;]$. Să fixăm doi indici $i{~1~}$ şi $i{~2~}$, astfel încât $i - K &le; $i{~1~}$ < $i{~2~}$ &le; i - 1$. Dacă $X[i{~1~}][&#99;] > X[i{~2~}][&#99;]$ atunci, întotdeauna poziţia $i{~2~}$ va fi preferată poziţiei $i{~1~}$. Când cele două nu se vor mai afla în intervalul $[i - K, i - 1]$, poziţia eliminată va fi poziţia $i{~1~}$. Dacă $X[i{~1~}][&#99;] < X[i{~2~}][&#99;]$, atunci nu putem decide care poziţie este mai bună în viitor, aşa că le vom păstra pe ambele. Rezultă mai departe că în intervalul $[i - K, i - 1]$ vom avea o serie de indecşi candidaţi la minim $i - K &le; i{~1~} < i{~2~} < .. < i{~n~} &le; i - 1$ astfel încât $X[i{~1~}][&#99;] < X[i{~2~}][&#99;] <  .. < X[i{~n~}][&#99;]$. Mai departe, găsim $bst[i][&#99;]$ ca fiind $X[i{~1~}][&#99;] + sum[i][&#99;] + T$. Urmează să îl introducem şi pe $X[i][&#99;]$, el fiind egal cu $Min(bst[i][&#48;], bst[i][&#49;]) - sum[i][&#99;]$, în şirul de indecşi de mai sus. Acest lucru se va face în felul următor: se vor elimina din $i{~n~}$, $i{~n-1~}$, ... atâta timp cât $X[$i{~n~}$][&#99;] > X[i][&#99;]$, $X[$i{~n-1~}$][&#99;] > X[i][&#99;]$, ... adică atâta timp cât poziţia $i$ este preferată lui $i{~n~}$, $i{~n-1~}$... Fiind la poziţia $i + 1$, intervalul se va transforma în $[i - K + 1, i]$, aşadar, vom mai elimina din primii indici $i{~1~}$, $i{~2~}$,... atâta timp cât $i{~1~} < i - K + 1$, $i{~2~} < i - K + 1$...\r\n\r\nDupă cum am arătat şi la problema precedentă, acest şir de indecşi $i{~1~}$, $i{~2~}$, .., $i{~n~}$ are proprietatea că este un şir continuu de numere care admite inserări prin dreapta (tail) şi ştergeri prin stânga (head). Şir ce poate fi reprezentat printr-un deque. Cum fiecare index dintre $1$, $2$, .., $N$ va trece o singură dată prin deque şi va fi şters cel mult o dată, complexitatea soluţiei în acest caz va fi $O(Q * N)$.\r\n\r\nÎn practică, programul este scurt, clar şi foarte eficient:\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\n#include <vector>\r\n#include <deque>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\nconst char iname[] = \"trans.in\";\r\nconst char oname[] = \"trans.out\";\r\n\r\n#define MAXN  16005\r\n#define Min(a, b) ((a) < (b) ? (a) : (b))\r\n#define FOR(i, a, b)  for (int i = (a); i <= (b); ++ i)\r\n\r\nint C[MAXN], S[MAXN], bst[MAXN][2], sum[MAXN][2], N;\r\n\r\nvoid insert(deque < pair <int, int> >& deq, const pair <int, int>& p) {\r\n    while (!deq.empty() && deq.back().second > p.second)\r\n        deq.pop_back();\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque < pair <int, int> >& deq, const int idx) {\r\n    while (deq.front().first < idx)\r\n        deq.pop_front();\r\n    return deq.front().second;\r\n}\r\n\r\nint work(const int K, const int T) {\r\n    deque < pair <int, int> > deq[2];       // pair (idx, value)\r\n    FOR (c, 0, 1)\r\n        insert(deq[c], pair <int, int>(0, 0));\r\n    FOR (i, 1, N) {   // obiectul i\r\n        FOR (c, 0, 1) // culoare\r\n            bst[i][c] = query(deq[c], i - K) + sum[i][c] + T;\r\n        FOR (c, 0, 1)\r\n            insert(deq[c], pair <int, int>(i, Min(bst[i][0], bst[i][1]) - sum[i][c]));\r\n    }\r\n    return Min(bst[N][0], bst[N][1]);\r\n}\r\n\r\nint main(void)\r\n{\r\n    ifstream in(iname);  ofstream out(oname);\r\n    in >> N;\r\n    FOR (i, 1, N) {\r\n        in >> C[i] >> S[i];\r\n        FOR (c, 0, 1)\r\n            sum[i][c] += sum[i - 1][c];\r\n        sum[i][1 - C[i]] += S[i];\r\n    }\r\n    int cnt, K, T;\r\n    in >> cnt;\r\n    FOR (i, 1, cnt)\r\n        in >> K >> T, out << work(K, T) << \"\\n\";\r\n\r\n    in.close(), out.close();\r\n    return 0;\r\n}\r\n==\r\n\r\nh3(#problema-4). Problema 4: \'Otilia\':problema/otilia  (.campion)\r\n\r\nbq. Otilia şi Burbucel au o grămadă de $N$ pietre şi vor juca un joc cu următoarele trei reguli: 1. Primul jucător are voie să ia din gramadă cel mult $K$ piese; 2. Cu excepţia primei mutări, fiecare jucător are voie să ia maxim $P * t$ pietre, unde $t$ este numărul de pietre care au fost substituite din grămadă la mutarea precedentă; 3. Pierde cel care mută ultimul (cel care ia ultimele pietre din grămadă).\r\nCerinţă: Se dau $M$ jocuri prin numerele $N$, $K$ şi $P$. Se cere să se determină dacă Otilia va câştiga fiecare din jocuri sau nu.\r\nRestricţii: $1 &le; M &le; 30 000$, $1 &le; N &le; 5 000 000$, $1 &le; K &le; N$, $1 &le; P &le; 10$.\r\n\r\nh3. Soluţie:\r\n\r\nProblema se rezolvă prin programare dinamică. Soluţia se bazează pe observaţia de mai jos. Considerăm $P$-ul fixat şi notăm cu $stare(X, Y)$ poziţia de start în care avem $X$ pietre şi numărul maxim de pietre care se pot lua la prima mutare este $Y$.\r\n\r\n_Observaţia 1_: „Dacă există strategie sigură de câştig pentru $stare(X, Y)$ atunci există şi pentru orice $stare(X, T)$ cu $T &ge; Y$.” \r\n\r\nDe ce? Pentru că orice mutare validă pentru $stare(X, Y)$ este validă şi pentru $stare(X, T)$. Având această observaţie notăm cu $MinY[X] = Y$, $Y$ minim astfel încât avem strategie de câştig pentru $stare(X, Y)$.\r\n\r\n_Observaţia 2_: „$stare(X, Y)$ este pierzătoare dacă şi numai dacă $Y < MinY[X]$.” \r\n\r\nAceasta reiese din definiţia lui $MinY[X]$.\r\n\r\n$MinY[X]$ se calculează după următoarea recurenţă, care rezultă din regulile jocului: \r\n\r\n* $MinY[X]$ este cel mai mic $i$ pentru care avem $MinY[X - i] > P * i$.\r\n\r\nDe aici se naşte prima soluţie, care este implementarea directă a recurenţei. Deşi complexitatea acesteia pare a fi $O(N^2^)$ ea se comportă foarte bine pentru $N &le; 500 000$. Aşadar, această soluţie acoperă aproximativ $50%$ din testele de intrare. Printr-o rafinare a acestei soluţii se obţine un algoritm de complexitate $O(N)$. Rafinarea se bazează pe: \r\n\r\n_Observaţia 3_: „Să presupunem că dorim să calculăm $MinY[X]$. Facem următoarea afirmaţie: orice poziţie \"rea\" pentru $X$ (în care dacă mutăm pierdem) va fi _rea_ şi pentru $X + 1$.”\r\n\r\nAcest lucru este simplu de observat dacă privim ce înseamnă că o poziţie $Q$ e rea pentru $X$: \r\n\r\n* $MinY[Q] > X - Q$, pentru $X$;\r\n* $MinY[Q] > X - Q + 1$, pentru $X + 1$.\r\n\r\nEste evident că prima relaţie o implică pe cea de-a doua. În momentul acesta se poate construi următorul algoritm: având lista de poziţii care pot fi bune pentru $X$ (sortată descrescător) o căutăm pe cea mai mare ca valoare care este într-adevăr bună. În principiu, scoatem din capul listei poziţiile rele până când dăm de o poziţie bună. La listă se va adăuga şi $X$ şi se va trece la pasul următor. Operaţiile algoritmului sunt chiar operaţiile asupra unui deque.\r\n\r\nh3(#problema-5). Problema 5: \'Cut the Sequence\':http://acm.pku.edu.cn/JudgeOnline/problem?id=3017 (PKU) \r\n\r\n(deque cu arbori de intervale, zice Paul)\r\n...\r\n\r\nh3(#problema-6). Problema 6: \'Bcrc\':problema/bcrc (Stelele Informaticii 2006)\r\n\r\nbq. Se consideră $N$ camere, numerotate de la $1$ la $N$, aşezate în cerc. Iniţial (la momentul de timp 0), ne aflăm în camera $1$. În fiecare moment de timp, putem alege să rămânem în camera în care ne aflăm sau să ne deplasăm într-o cameră vecină într-o unitate de timp. Se dă o listă de $M$ cutii ce conţin bomboane prin $T$, $C$ şi $B$: cutia apare la momentul $T$ în camera $C$ şi conţine $B$ bomboane. Cutia va dispărea la momentul $T + 1$.\r\nCerinţă: Cunoscând numărul de camere din labirint şi momentele de timp la care apar cutiile cu bomboane, determinaţi care este numărul maxim de bomboane pe care le putem culege.\r\nRestricţii: $3 &le; N &le; 2 048$, $0 &le; M &le; 50 000$, $1 &le; T &le; 1 000 000 000$, $1 &le; C &le; N$, $1 &le; B &le; 9 999$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia foloseşte metoda programării dinamice.\r\n\r\nO stare se reprezintă prin camera în care ne aflăm şi momentul de timp. Fie $bst[i][j]$ numărul maxim de bomboane culese până în momentul $i$ când ne găsim în camera $j$. O observaţie evidentă este că $bst[i][j]$ se poate modifica doar în momentele în care apar cutiile. Prin urmare, vom considera momentele de timp $i$ când apar cutiile, momente ce sunt în număr de $M$. De cine depinde această stare? Ştim că $bst[i - 1][1 ... N]$ a fost deja calculat în mod optim. Să notăm cu $T$ diferenţa de timp dintre momentele la care apare cutia $i$ şi cutia $i - 1$. În acest moment $i$ şi cameră $j$ putem ajunge din maxim $T$ camere spre stânga sau spre dreapta, întrucât fiecare deplasare între două camere costă o unitate de timp. De unde deducem că:\r\n\r\n* $bst[i][j] = Min { bst[i - 1][j - T], bst[i - 1][j - T + 1], ..., bst[i - 1][j], ..., bst[i - 1][j + T - 1], bst[i - 1][j + T] }$.\r\n\r\nMetoda directă şi, aparent eficientă, constă în folosirea unui arbore de intervale pentru aflarea acestui minim. Însă, intervalul se deplasează, dacă vom considera indicii $j$ în ordine $1$, $2$, ..., $N$, constant spre dreapta, fiind reprezentat de un şir de valori de lungime constantă în care noile elemente se introduc prin dreapta şi altele se elimină prin stânga. Vom folosi un deque şi vom proceda ca în problemele precedente, eliminând poziţiile care nu sunt candidate la soluţie.\r\n\r\np=. !deque-si-aplicatii?bcrc.png 40%!\r\n\r\nComplexitatea finală: $O(M * N)$.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nFilozofia din spatele structurii de deque devine utilă, de obicei, în momentele finale ale rezolvării unei probleme. Însă, ce pot spune cu certitudine este că această structură de date pe cât este de simplă pe atât este de eficientă.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\nÎnţelegerea profundă a acestei structuri simple nu se poate realiza decât prin rezolvarea a cât mai multe probleme. Succes!\r\n\r\n* \'Deque\':problema/deque, _Arhiva educaţională_\r\n* \'Secvenţă\':problema/secventa\r\n* \'Secvenţă 3\':problema/secv3\r\n* \'Secvenţă 4\':problema/secv4\r\n* \'Vila 2\':problema/vila2, _.campion_\r\n* \'Sum 2\':problema/sum2, _Stelele Informaticii 2003_\r\n* \'Drept 2\':problema/drept2, _Lotul Naţional de Informatică, 2006_\r\n* \'Copaci 2\':problema/copaci2, _.campion_\r\n* \'Brânză\':problema/branza\r\n* \'Struţi\':problema/struti\r\n* \'Trompetă\':problema/trompeta\r\n* \'Buline\':problema/buline\r\n* \'Balans\':problema/balans\r\n* \'Gard\':problema/gard, _ONI 2002_\r\n* \'Ghiozdan\':problema/ghiozdan\r\n* \'Munte4\':problema/munte4, _Lotul Naţional de Informatică, 2005_\r\n* \'Cover\':problema/cover, _ONI 2007, Baraj_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Cosmin Negruşeri, \"_Probleme cu secvenţe_\":probleme-cu-secvente\r\n# Dana Lica, \"_Arbori de intervale şi aplicaţii în geometria computaţională_\":arbori-de-intervale',3146,'public',NULL,NULL),('planificare/sedinta-20090126','Sedinta 2009-01-26','2009-01-22 17:34:00','2009-01-26 22:27:01','h1. Sedinta 2009-01-26\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe întâlnim *luni, 26 ianuarie* la ora *19^00^* la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")== (inca nu stiu cand scap de la examen)\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"alexthero\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinta anterioara\':planificare/sedinta-20090112| ==user(user=\"domino\" type=\"tiny\")==|\r\n|OKRs Q12009| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n|Algoritmiada| ... |\r\n|Stelele| ==user(user=\"silviug\" type=\"tiny\")==|\r\n|Fix-it camp| ... |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n* Despre Stele\r\n** Sunt ok datele: 31-1 pentru 9-10 si 6-7 pentru 11-12?\r\n** Seturi de probleme\r\n*** Se dau ~120 RON pe problema (e pe bani!)\r\n*** Avem probleme pentru 9-10? Cate?\r\n*** Pentru 11-12 trebuie sa ne intalnim (fara Bogdan si Cosmin) la ICHB. Marti/miercuri?\r\n\r\nDiscutii despre probleme la 9-10. Intalnire marti-miercuri pentru 11-12.\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Cristi face blog post despre OKR-uri\r\n* Silviu stabileste contacte cu Poli\r\n* Fixit camp:\r\n** Cristi si Silviu vorbesc de premii\r\n* Stele:\r\n** Ne intalnim maine la 10 la ICHB sa vorbim de probleme: Silviu, Adi, Paul, Victor, Stefan. Victor vorbeste cu Wef\r\n** Cristi baga newsletter si Silviu ii zice din timp (minim 3 zile)\r\n** Cristi vorbeste cu Ali pentru configurarea proxy-ului\r\n** Cristi face .htaccess pentru a bana forumul\r\n* Algoritmiada:\r\n** Se face pe 15 februarie\r\n** Sponsori posibili: Adobe, Microsoft, iRealSoft\r\n* Il iertam pe Mort de datorie (a gresit la calcule)\r\n* Coding camp:\r\n** 28 februarie - 1 martie\r\n** Cine vine: Cristi, Vali, Prostu, Bogdan, Victor, Cosmin, Stefan, Mircea\r\n** Probabil: Silviu, Paul, Adi, Wef\r\n** Tero baga de acasa\r\n** Mircea face planul de coding camp (Virtual Contest e prioritar)\r\n*** Reorganizat sidebar si topnav (Cristi are idei, link la index de newsletter)\r\n*** Solutie de backup\r\n** Cristi se ocupa de locatie\r\n* Nu facem fixit camp in Q1\r\n* Mircea se uita sa vada cati oameni au trimis doar in Arhiva Educationala\r\n* Vali face IAP si OKR despre ordonarea problemelor (vezi formula de la IMDB)\r\n* Incercam \"video sedinta\" cu Airinei (webcam/Skype)\r\n* Lumea da feedback la IAP 7 pana la urmatoarea sedinta\r\n* Cristi face blog post despre 2%\r\n* Silviu vorbeste cu Mars despre evaluator\r\n* Mircea trimite mail pentru cine nu si-a completat OKR-urile\r\n* Facem sedinta pe 16 februarie. Cosmin cumpara apa, suc si pahare (bon cu stampila). Cristi se ocupa de sala.\r\n* Paul, Prostu, Tero & Co trimit poza si descriere lui Cosmin pentru blog despre membri noi.\r\n\r\nh2. Notite\r\n\r\n* Punem stire ca nu mai ai voie cu HTML si sa-si actualizeze lumea profilele\r\n* Stefan discuta cu Marius Stroe dupa finala\r\n',716,'public',NULL,NULL),('arbori-de-intervale','Arbori de intervale si aplicatii in geometria computationala','2007-04-17 20:24:45','2008-12-13 18:27:32','h1. Arbori de intervale si aplicatii in geometria computationala\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"sima_cotizo\") ==\r\n\r\n(Categoria _Structuri de date_, Autor _Dana Lica_)\r\n\r\nh2. Problema 1\r\n\r\np<>. Se considera $N (N &le; 50 000)$ segmente in plan, dispuse paralel cu axele $OX$ si $OY$. Sa se determine care este numarul total de intersectii dintre segmente.\r\n\r\np<>. In fisierul $_segment.in_$ se gaseste pe prima linie numarul $N$ de segmente, iar pe fiecare dintre urmatoarele $N$ linii cate patru numere naturale mai mici decat $50 000$, reprezentand coordonatele carteziene ale extremitatilor fiecarui segment.\r\nRezultatul se va scrie in $_segment.out_$.\r\nTimp de executie: $1 secunda/test$\r\nExemplu:\r\n\r\ntable(example). |_. segment.in |_. segment.out |_. Figura |\r\n|^. 5\r\n2 9 13 9\r\n4 6 12 6\r\n1 2 6 2\r\n5 0 5 8\r\n7 5 7 11  |^. 4 |=. !arbori-de-intervale?figure-1.jpg! |\r\n\r\nh2. Algoritmi de \"baleiere\" _(line sweeping)_\r\n\r\np<>. Folosind cunostinte generale de geometrie analitica se poate obtine un algoritm $O(N^2^)$ dar acesta nu se va incadra in limita de timp. \r\n\r\np<>. Pentru rezolvarea acestei probleme vom folosi o tehnica cunoscuta sub numele de \"baleiere\" _(sweeping)_ care este comuna multor algoritmi de geometrie computationala. In baleiere, o dreapta de baleiere verticala, imaginara, traverseaza multimea obiectelor geometrice, de obicei de la stanga la dreapta.  Baleierea ofera o metoda pentru ordonarea obiectelor geometrice, plasandu-le intr-o structura de date, pentru obtinerea relatiilor dintre ele.\r\n\r\nAlgoritmii de baleiere gestioneaza doua multimi de date: \r\n\r\n# +Starea liniei+ de baleiere da relatia dintre obiectele intersectate de linia de baleiere \r\n# +Lista punct-eveniment+ este o secventa de coordonate $x$, ordonate de la stanga la dreapta de obicei, care definesc pozitiile de oprire ale dreptei de baleiere; fiecare astfel de pozitie de oprire se numeste _punct eveniment_; numai in punctele eveniment se intalnesc modificari ale starii liniei de baleiere; pentru unii algoritmi, lista punct-eveniment este determinata dinamic in timpul executiei algoritmului. \r\n\r\np<>. Pentru a rezolva problema, vom deplasa o dreapta de baleiere verticala, imaginara de la stanga la dreapta. Lista punct-eveniment va contine capetele segmentelor orizontale, ce fel de tip sunt (cap stanga sau cap dreapta) si segmentele verticale. Pe masura ce ne deplasam de la stanga la dreapta vom efectua urmatoarele operatii:\r\n\r\n* cand intalnim un capat stang, inseram capatul in starile dreptei de baleiere; \r\n* cand intalnim un capat drept, stergem capatul din starile dreptei de baleiere; \r\n* cand intalnim un segment vertical, numarul de intersectii ale acestui segment cu alte segmente orizontale va fi dat de numarul capetelor de intervale care se afla in starile dreptei de baleiere cuprinse intre coordonatele $y$ ale segmentului vertical. \r\n\r\np<>. Astfel, starile dreptei de baleiere sunt o structura de date pentru care avem nevoie de urmatoarele operatii:\r\n\r\n* **INSEREAZA(y)** : insereaza capatul $y$\r\n* **STERGE(y)** : sterge capatul $y$\r\n* **INTEROGARE(y1,y2)** : intoarce numarul de capete cuprinse in intervalul $[y{~1~}, y{~2~}]$\r\n\r\np<>. Fie $MAXC$ valoarea maxima a coordonatelor capetelor de segmente. Folosind un vector pentru a implementa aceste operatiile descrise mai sus vom obtine o complexitate $O(1)$ pentru primele doua operatii si $O(MAXC)$ pentru cea de-a treia. Astfel, complexitatea  va fi $O(N*MAXC)$ in cazul cel mai defavorabil. Putem comprima spatiul $[0...MAXC]$ observand ca doar maxim N din valori din acest interval conteaza, si anume capetele segmentelor orizontale, astfel reducand a treia operatie la $O(N)$, dar algoritmul va avea complexitatea $O(N^2^)$, ceea ce nu aduce nici o imbunatatire fata de algoritmul trivial. \r\n\r\np<>. Aceasta situatie ne indeamna sa cautam o structura de date mai eficienta. O prima varianta ar fi impartirea vectorului in bucati de sqrt(N) reducand complexitatea totala la $O(N*&radic;N)$. In continuare vom prezenta o structura de date care ofera o complexitate logaritmica pentru operatiile descrise mai sus.\r\n\r\nh2. Arbori de intervale\r\n\r\np<>. Un arbore de intervale este un arbore binar in care fiecare nod poate avea asociata o structura auxiliara(anumite informatii). Dandu-se doua numere intregi $st$ si $dr$, cu $st<dr$, atunci arborele de intervale T(st,dr) se construieste recursiv astfel:\r\n\r\n* consideram radacina $nod$ avand asociat intervalul $[st,dr]$\r\n* daca $st<dr$ atunci vom avea asociat subarborele stang T(st,mij), respectiv subarborele drept T(mij+1,dr), unde $mij$ este mijlocul intervalului $[st,dr]$\r\n\r\np<>. Intervalul $[st,dr]$ asociat unui nod se numeste interval standard. Frunzele arborelui sunt considerate intervale elementare, ele avand lungimea $1$.\r\n\r\nh3. Proprietate: \r\n\r\np<>. Un arbore de intervale este un arbore binar echilibrat(diferenta absoluta intre adancimea subarborelui stang si cea a subarborelui drept este cel mult 1). Astfel, adancimea unui arbore de intervale care contine N intervale este $[log{~2~}N]+1$.\r\n\r\np=. !arbori-de-intervale?figure2.jpg!\r\n\r\nh2. Operatii efectuate asupra unui arbore de intervale:\r\n\r\nh3. Actualizare unui interval intr-un arbore de intervale\r\n\r\np<>. Vom prezenta pseudocodul unei proceduri recursive care insereaza un interval $[a,b]$ intr-un arbore de intervale T(st,dr) cu radacina in nodul $nod$. Cea mai eficienta metoda de stocare in memorie a unui arbore de intervale este sub forma unui vector folosind aceeasi codificare a nodurilor ca si la heap-uri :\r\n\r\n==code(c) |\r\nprocedura ACTUALIZARE(nod, st, dr, a, b)\r\n   daca (a<=st) si (dr<=b) atunci\r\n      modifica structura auxiliara din nod \r\n   altfel \r\n      mij = (st+dr)/2\r\n      daca (a <= mij) atunci ACTUALIZARE(2*nod, st, mij, a, b)\r\n      daca (b > mij) atunci ACTUALIZARE(2*nod+1, mij+1, dr, a, b)\r\n      actualizeaza structura auxiliara din nodul nod\r\n==\r\n\r\nh3. Interogarea unui interval intr-un arbore de intervale\r\n\r\np<>. Vom prezenta pseudocodul unei proceduri recursive care returneaza informatiile asociate unui interval $[a,b]$ intr-un arbore de intervale T(st,dr) cu radacina in nodul $nod$.\r\n\r\n==code(c) |\r\nprocedura INTEROGARE(nod, st, dr, a, b)\r\n   daca (a<=st) si (dr<=b) atunci\r\n      returneaza structura auxiliara din nod \r\n   altfel \r\n      mij = (st+dr)/2\r\n      daca (a <= mij) atunci INTEROGARE(2*nod, st, mij, a, b)\r\n      daca (b > mij) atunci INTEROGARE(2*nod+1, mij+1, dr, a, b)\r\n      returneaza structura auxiliara din fiul stang combinata cu cea din fiul drept\r\n==\r\n\r\np<>. Vom demonstra in continuare ca operatiile prezentate mai sus au complexitatea $O(log{~2~} N)$ pentru un arbore de $N$ intervale. Este posibil ca intr-un nod sa aiba loc apel atat in fiul stang cat si in cel drept. Acest lucru produce un cost aditional doar prima data cand are loc. Dupa prima \"rupere in doua\", oricare astfel de \"rupere\" nu va aduce cost aditional, deoarece unul din fii va fi mereu inclus complet in intervalul $[a,b]$. Cum inaltimea arborelui, pentru $N$ intervale, este $[log{~2~}N]+1$, complexitatea operatiilor va fi tot $O(log{~2~} N)$.\r\n\r\np<>. Pentru a retine in memorie un arbore de intervale pentru $N$ valori, vom aveam de nevoie de $N+N/2+N/4+N/8...=2*N-1$ locatii de memorie (sunt $2*N-1$ noduri). Deoarece arborele nu este complet, trebuie verificat de fiecare data daca fii unui nod exista in arbore (aceasta verificare a fost omisa in pseudocodul de mai sus), altfel s-ar incerca accesarea de valori din vector care nu exista. Daca memorie disponibila in timpul concursului este suficienta, se poate declara vectorul care retine arborele de intervale de lungime $2^K^$ astfel incat $2^K^&ge;2*N-1$, simuland astfel un arbore complet si nefiind necesare verificarile mentionate mai sus.\r\n\r\np<>. Pentru a rezolva in continuare problema, vom folosi un arbore de intervale pentru a simula in timp logaritmic operatiile facute inainte pe un vector obisnuit. Astfel, in fiecare nod din arborele din intervale vom retine cate capete exista in acel interval. Primele doua operatii vor fi implementate folosind procedura ACTUALIZARE() de mai sus pentru intervalul $[y,y]$ in arborele T(0, MAXC) si adunand $1$, respectiv scazand $1$ la fiecare nod actualizat. Cea de-a treia operatie poate fi realizata folosind procedura INTEROGARE() pe intervalul $[y{~1~},y{~2~}]$. Astfel complexitatea se reduce la $O(N*log{~2~} MAXC)$  Folosind aceeasi tehnica de \"comprimare\" a coordonatelor se poate obtine o complexitate $O(N*log{~2~} N)$.\r\n\r\nIn figura urmatoare este descrisa structura arborelui de intervale, dupa actualizarea pentru intervalele $[2,2]$, $[6,6]$ si $[9,9]$. Sunt marcate intervalele care conduc la obtinerea numarului de segmente intersectate de primul segment vertical, obtinute in urma interogarii pe intervalul $[0,8]$.\r\n\r\np=. !arbori-de-intervale?figure3.jpg!\r\n\r\nh2. Problema 2 (Preluata de la IOI 1998, Ziua 2)\r\n\r\np<>. Se considera $N&le;50 000$ dreptunghiuri in plan, fiecare avand laturile paralele cu axele $OX, OY$. Lungimea marginilor (contururilor) reuniunii tuturor dreptunghiurilor se va numi \"perimetru\". Sa se calculeze perimetrul celor $N$ dreptunghiuri. \r\n\r\np<>. In fisierul $drept.in$ se gaseste pe prima linie numarul $N$ de dreptunghiuri, iar pe fiecare din urmatoarele $N$ linii cate patru numere naturale mai mici ca $50 000$, reprezentand coordonatele carteziene ale coltului stanga sus, respectiv dreapta jos ale fiecarui dreptunghi. Rezultatul se va scrie in fisierul $drept.out$.\r\n\r\np<>. Timp maxim de executie: $1 secunda / test$\r\n\r\nExemplu:\r\n\r\ntable(example). |_. drept.in |_. drept.out |_. Figura |\r\n|^. 3\r\n3 8 8 3\r\n6 10 12 6\r\n12 4 15 1 |^. 44 |=. !arbori-de-intervale?figure4.jpg! |\r\n\r\nFolosind un rationament asemanator ca si la prima problema, constatam necesitatea unui algoritm de baleiere. Vom descompune problema in doua parti: prima data calculam perimetrul folosind doar laturile stanga si dreapta ale dreptunghiurilor pentru a calcula perimetrul pe $OY$; apoi putem sa rotim dreptunghiurile si folosind aceeasi procedura pt a calcula perimetrul pe $OX$, folosind doar laturile sus si jos ale dreptunghiurilor. \r\n\r\nFiecare latura (stanga sau dreapta) va fi un punct eveniment. Sortam laturile crescator dupa coordonata $x$ si parcurgem de la stanga la dreapta. Cand intalnim o latura stanga adaugam in starile dreptei de baleiere, intervalul de unitati ocupat de latura pe OY, iar cand intalnim o latura dreapta, eliminam din starile dreptei de baleiere intervalul de unitati ocupat de latura. Intre oricare doua puncte eveniment consecutive are loc o modificare a perimetrului total pe $OY$. Astfel, dupa fiecare actualizare a starilor dreptei de baleiere se va retine care este numarul de unitati adaugate pana in prezent (nu se tine cont daca o unitate este adaugata de mai multe ori). Vom aduna la perimetrul pe $OY$ total de fiecare data, diferenta absoluta intre numarul de unitati adaugate pana in prezent si valoarea imediat anterioara (dinaintea actualizarii). Asadar, este necesara o structura de date care se efectueze urmatoarele operatii in timp eficient (preferabil logaritmic):\r\n\r\n* MARCHEAZA(a,b) : adauga intervalul $[a, b]$\r\n* DEMARCHEAZA(a,b) : elimina intervalul $[a, b]$\r\n* INTEROGARE() : returneaza numarul total de coordonate adaugate pana in prezent\r\n\r\np<>. Putem folosi un arbore de intervale pentru a obtine o complexitate $O(log{~2~} MAXC)$ sau $O(log{~2~} N)$ pentru primele doua operatii si $O(1)$ pentru ce-a de treia. In fiecare nod din arbore retinem de cate ori a fost marcat intervalul respectiv si cate unitati din intervalul respectiv au fost marcate. Primele doua operatii pot fi implementate folosind procedura ACTUALIZARE() iar a treia operatie va returna valoarea numarul de unitati care au fost marcate din radacina arborelui de intervale. \r\n\r\np<>. In figura urmatoare este descrisa structura arborelui de intervale, dupa adaugarea intervalelor $[3,8]$ si $[6,10]$ (un interval $[y{~1~},y{~2~}]$ reprezinta intervalul de unitati $[y{~1~}, y{~2~}-1]$ din arbore). \r\n\r\np=. !arbori-de-intervale?figure-8.jpg!\r\n\r\nh2. Problema 3\r\n\r\np<>. Se dau $N&le;100 000$ puncte in plan de coordonate numere naturale mai mici ca $2 000 000 000$. Sa se raspunda la $M&le;1 000 000$ intrebari de forma \"cate puncte din cele $N$ exista in dreptunghiul cu coltul stanga sus in $(x{~1~},y{~1~})$ si coltul dreapta jos in $(x{~2~},y{~2~})$?\".\r\n\r\np<>. In fisierul $puncte.in$ se vor gasi pe prima linie numerele $N$ si $M$. Pe urmatoarele $N$ linii se vor gasi coordonatele punctelor. Pe urmatoarele $M$ linii se vor gasi cate patru numere naturale reprezentand coordonatele colturilor dreptunghiurilor. \r\n\r\np<>. In fisierul $puncte.out$ se vor gasi $M$ numere naturale reprezentand raspunsurile la intrebari.\r\n\r\np<>. Timp maxim de executie: $1 secunda / test$\r\n\r\np<>. Exemplu:\r\n\r\ntable(example). |_. puncte.in |_. puncte.out |_. Figura |\r\n|^. 6 1\r\n2 8\r\n5 3\r\n6 5\r\n8 7\r\n8 1\r\n10 10\r\n4 8 9 4 |^. 2 |=. !arbori-de-intervale?figure5.jpg! |\r\n\r\np<>. Problema determinarii numarului de puncte din interiorul unui dreptunghi este o particularizare bidimensionala pentru problema numita in literatura de specialitate \"Orthogonal Range Search\". Varianta aleasa pentru acest caz consta intr-un arbore de intervale, care permite determinarea numarului de puncte din interiorul unui dreptunghi cu o complexitate $O(log{~2~}^2^ N)$. \r\n\r\np<>. Astfel, se sorteaza coordonatele $x$ ale punctelor si se construieste un arbore de intervale. Primul nivel al arborelui va contine toate coordonatele $x$. Cei doi fii ai lui vor contine prima jumatate, respectiv a doua jumatate a punctelor (sortate dupa coordonata $x$) si asa mai departe. Pentru fiecare interval de coordonate $x$, se mentin sortate coordonatele $y$ corespunzatoare punctelor care au coordonatele $x$ in intervalul respectiv. Astfel, memoria folosita este $O(N*log{~2~} N)$. Pentru a construi efectiv se foloseste o abordare asemanatoare algoritmului de sortare prin interclasare: in fiecare nod, pentru a obtine lista de coordonate $y$ ordonate, se interclaseaza listelele celor doi fii (deja ordonate). Cand se ajunge intr-o frunza, lista nodului este formata dintr-un singur punct.\r\n\r\np=. !arbori-de-intervale?figure6.jpg!\r\n\r\np<>. Pentru fiecare dreptunghi, se executa cautarea in arborele de intervale pentru segmentul $[x1, x2]$ (deoarece se folosesc doar cele $N$ coordonate $x$ ale punctelor, se vor potrivi capetele acestui interval folosind cautarea binara la cea mai apropiata coordonata $x$ de fiecare capat). Pentru fiecare interval din arbore atins, se executa doua cautari binare printre coordonatele y corespunzatoare coordonatelor x din acel interval, pentru a determina cate puncte din intervalul respectiv se afla in intervalul $[y{~1~}, y{~2~}]$ (adica in interiorul dreptunghiului).\r\n\r\np<>. Complexitatea $O(log{~2~}^2^ N)$ poate fi redusa, folosind o metoda descoperita independent de Willard si Lueker in anul $1978$. Se observa ca pentru fiecare coordonata $y$ dintr-un nod, daca presupunem ca se efectueaza o cautare binara, atunci putem determina in timpul interclasarii pozitia din fiecare fiu pe care o va returna cautarea binara pentru aceeasi valoare. Este evident ca pentru o valoare $y$ dintr-un nod care a provenit dintr-un fiu in timpul interclasarii, exista o unica valoare maxima $y\'$ din celalalt fiu astfel incat $y\'&le;y$. Asadar, tinem pentru fiecare valoare $y$ dintr-un nod doi indici care identifica pozitiile corespunzatoare efectuarii unei cautari binare in fii pentru valoarea $y$. Astfel, in timpul cautarii, in loc sa se efectueze cautari binare, se pot parcurge acesti indici, care ofera in $O(1)$ pozitia in lista cautata, reducand complexitatea totala la $O(log{~2~} N)$.\r\n\r\np=. !arbori-de-intervale?figure7.jpg!\r\n\r\nh2. Probleme propuse \r\n\r\n1) (preluata de la Olimpiada Baltica de Informatica, Polonia  2001)\r\n\r\np<>. Se considera $N&le;50 000$ dreptunghiuri in plan, fiecare avand laturile paralele cu axele $OX, OY$. Sa se calculeze aria ocupata de reuniunea celor $N$ dreptunghiuri. \r\n\r\np<>. In fisierul $drept2.in$ se gaseste pe prima linie numarul $N$ de dreptunghiuri, iar pe fiecare din urmatoarele $N$ linii cate patru numere naturale mai mici ca $50 000$, reprezentand coordonatele carteziene ale coltului stanga sus, respectiv dreapta jos ale fiecarui dreptunghi. Rezultatul se va scrie in fisierul $drept2.out$.\r\n\r\np<>. Timp maxim de executie: $1 secunda / test$\r\n\r\n2) (preluata de la Olimpiada Nationala de Informatica, Polonia 2001)\r\n\r\np<>. Se considera $N&le;50 000$ puncte in plan de coordonate numere naturale mai mici ca $50 000$. Sa se determine unde se poate aseza un dreptunghi de lungime $DX$ si latime $DY$ astfel incat numarul de puncte incluse in dreptunghi sa fie maxim.\r\n\r\np<>. In fisierul $puncte.in$ se gasesc pe prima linie numerele $N$, $DX$ si $DY$. Pe urmatoarele $N$ linii se gasesc coordonatele punctelor. \r\n\r\np<>. In fisierul $puncte.out$ se vor gasi cinci numere naturale reprezentand coordonatele colturilor stanga sus si dreapta jos ale asezarii dreptunghiului si numarul maxim de puncte din dreptunghi.\r\n\r\np<>. Timp maxim de executie: $1 secunda / test$\r\n\r\n3) (preluata de la Barajul pentru Lotul National, Romania 2003)\r\n\r\np<>. Se considera $N&le;100 000$ puncte in plan de coordonate numere naturale mai mici ca $100 000$. Sa se determine unde se pot aseza doua dreptunghiuri de lungime $DX$ si latime $DY$, fara sa se intersecteze, astfel incat numarul de puncte incluse in cele doua dreptunghiuri sa fie maxim. \r\n\r\np<>. In fisierul $puncte2.in$ se gasesc pe prima linie numerele $N$, $DX$ si $DY$. Pe urmatoarele $N$ linii se gasesc coordonatele punctelor. \r\n\r\np<>. In fisierul $puncte2.out$ se vor gasi $9$ numere naturale reprezentand coordonatele colturilor stanga sus si dreapta jos ale asezarii primului dreptunghi, respectiv a celui de-al doilea, cat si numarul maxim de puncte incluse in ambele dreptunghiuri.\r\n\r\np<>. Timp maxim de executie: $1 secunda / test$\r\n\r\n4) (preluata de la concursul international USACO January Open, 2004)\r\n\r\np<>. Se considera $N&le;250 000$ dreptunghiuri in plan, fiecare avand laturile paralele cu axele $OX/OY$, care nu se intersecteaza si nu se ating, dar pot fi incluse unul in altul. Se numeste \"inchisoare\" un dreptunghi inconjurat de alte dreptunghiuri. Sa se determine numarul maxim de dreptunghiuri de care poate fi inconjurata o \"inchisoare\" si cate astfel de \"inchisori\" maxime exista. \r\n\r\np<>. In fisierul $inchis.in$ se gaseste pe prima linie numarul $N$ de dreptunghiuri, iar pe fiecare din urmatoarele $N$ linii cate patru numere naturale mai mici ca $1 000 000 000$, reprezentand coordonatele carteziene ale coltului stanga sus, respectiv dreapta jos ale fiecarui dreptunghi.\r\n\r\np<>. In fisierul $inchis.out$ se gasesc doua numere naturale: numarul maxim de dreptunghiuri de care poate fi inconjurata o \"inchisoare\" si cate astfel de \"inchisori\" maxime exista. \r\n\r\np<>. Timp maxim de executie: $1 secunda / test$\r\n\r\n\r\np<>. Au fost adaugate si implementarile in limbaj pascal/c ale catorva dintre problemele explicate in articol. Acestea pot fi accesate prin intermediul optiunii \"Listeaza atasamente\"',2044,'public',NULL,NULL),('planificare/camp-2.2.1','Coding Camp \"A New Day\"','2009-02-01 22:33:19','2009-02-01 22:49:37','h1. Coding Camp _\"A New Day\"_\r\n\r\nh2. Locatie\r\n\r\nh2. Detalii\r\n\r\nh2. Participanti\r\n\r\nh2. Agenda\r\n\r\nh3. Must have\r\n\r\nh3. Nice to have\r\n\r\nh3. Others\r\n\r\nh2. Plan ',1,'public',NULL,NULL),('planificare/camp-2.2.1','Coding Camp \"A New Day\"','2009-02-01 22:33:19','2009-02-01 23:12:11','h1. Coding Camp _\"A New Day\"_\r\n\r\nNe intalnim in weekend-ul *28 februarie-1 martie 2009* la ...\r\n\r\nh2. Locatie\r\n\r\n...\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu Linux (preferabil Ubuntu) instalat pe el\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri\r\n\r\nh2. Participanti\r\n\r\nSpecifica cand poti veni si cat poti sta.\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==: tot weekend-ul\r\n\r\nh2. Agenda\r\n\r\nh3. Must have\r\n\r\n|_. Task|_. Estimare de timp |\r\n| \'Comentarii la orice pagina ca la blog\':http://hackers.devnet.ro/ticket/362 | ? |\r\n| Reorganizat sidebar si topnav | ? |\r\n| Script de backup | ? |\r\n| Virtual Contests | ? |\r\n| \'Sistem de monitorizare\':http://hackers.devnet.ro/ticket/179 | ? |\r\n| \'Pagina de submit desteapta\':http://hackers.devnet.ro/ticket/366 | ? |\r\n\r\n\r\nh3. Nice to have\r\n\r\n|_. Task|_. Estimare de timp |\r\n| \'Run YSlow and improve performance\':http://hackers.devnet.ro/ticket/351 | ? |\r\n| \'Interfata de updatat rating-uri\':http://hackers.devnet.ro/ticket/239 | ? |\r\n| \'Permisiuni in pagina de changes\':http://hackers.devnet.ro/ticket/363 | ? |\r\n| \'Scoruri detaliate\':http://hackers.devnet.ro/ticket/263 | ? |\r\n| \'Sterge o revizie\':http://hackers.devnet.ro/ticket/132 | ? |\r\n| \'Pagina de changes mai detaliana\':http://hackers.devnet.ro/ticket/155 | ? |\r\n\r\nh3. Others\r\n\r\n|_. Task|_. Estimare de timp |\r\n| \'Grafice rating\':http://hackers.devnet.ro/ticket/263 | ? |\r\n| \'Optimizat diff-ul\':http://hackers.devnet.ro/ticket/360 | ? |\r\n',1,'public',NULL,NULL),('doi-la-suta','Sprijina Asociatia infoarena! Directioneaza 2%','2008-01-28 21:09:12','2008-02-22 16:19:39','h1. Sprijina Asociatia infoarena!\r\n\r\n*_Directioneaza catre noi 2% din impozitul pe venit datorat la stat._*\r\n\r\nIn conformitate cu prevederile \'Codului Fiscal, art. 84\':http://www.edex.ro/articol_cod_fiscal_16661_Art.%2084:%20Stabilirea%20si%20plata%20impozitului%20pe%20venitul%20net%20anual%20impozabil.html poti directiona 2% din impozitul pe venit datorat la stat catre o entitate non-profit:\r\n\r\nbq. Contribuabilii pot dispune asupra destinatiei unei sume reprezentand *2%* din impozitul datorat pe venitul net anual impozabil, castigul net anual din transferul titlurilor de valoare, castigul din operatiuni din vanzare-cumparare de valuta si orice operatiune de acest gen, pentru sustinerea entitatilor nonprofit.\r\n\r\n*Nu te costa nimic!* Impozitul pe venit ramane acelasi.\r\n\r\nh2. La ce folosim contributiile\r\n\r\ninfoarena ajuta elevi si studenti sa invete informatica si programare. De mai bine de 4 ani de zile organizam concursuri de informatica, scriem articole, dezvoltam software, facem schimb de experienta si idei. Ne-am organizat pe acest site deoarece impreuna invatam mai bine.\r\n\r\nPoti sa citesti mai mult despre ce facem noi \'aici\':prezentare si \'aici\':despre-infoarena. Am aparut si in  \'Adevarul\':http://www.adevarulonline.ro/articole/fostii-olimpici-ii-antreneaza-pe-concurentii-de-la-olimpiade/305061 (pe \'prima pagina\':http://www.adevarulonline.ro/usr/main_news/2042/1.pdf).\r\n\r\nVom folosi contributiile venite pe aceasta cale sa...\r\n\r\n* oferim premii: Elevii sunt mult mai motivati sa se pregateasca si sa participe la un concurs online de informatica atunci cand se dau premii.\r\n* finantam \'proiecte infoarena\':propuneri\r\n* motivam comunitatea sa se \'implice\':implica-te\r\n\r\nIn plus - presupunand ca extrasele bancare ne furnizeaza aceste informatii - vom publica pe site o lista cu toti contribuabilii care au directionat 2% din impozit catre noi.\r\n\r\nh2. Ce trebuie sa faci\r\n\r\nProcedura este foarte simpla. Ai grija sa te incadrezi in *termenul limita: 15 mai 2008*.\r\n\r\n# In functie de sursa ta de venit, descarca, printeaza si completeaza una din declaratiile urmatoare:\r\n** *Daca ai venituri numai din salarii*: \'Declaratia 230\':http://www.doilasuta.ro/doilasuta/Resurse_files/decl_230_2008.pdf\r\n** Daca ai venituri (si) din alte surse (cedarea folosintei bunurilor, drepturi de autor, etc): \'Declaratia 200\':http://www.doilasuta.ro/doilasuta/Resurse_files/decl_200_2008.pdf\r\n# Foloseste urmatoarele date de identificare pentru Asociatia infoarena:\r\n** CUI: 21752294\r\n** IBAN: RO15&nbsp;RZBR&nbsp;0000&nbsp;0600&nbsp;0919&nbsp;4268, Deschis la: Raiffeisen, Ag. Unirea, Bucuresti\r\n** Adresa sediu social: Str. Dragos Voda Nr. 49, Bl. P9, Ap. 11, Barlad, Jud. Vaslui\r\n# Depune declaratiile completate la administratia financiara de care apartine domiciliul tau. Optional poti sa trimiti declaratia prin scrisoare recomandata catre administratia financiara.\r\n\r\nNu e nici o problema daca nu stii exact suma care trebuie virata. Lasa rubrica \"Suma\" necompletata si organul fiscal va calcula si va vira suma admisa, conform legii.\r\n\r\nCompleteaza in doua exemplare declaratia corespunzatoare. Unul din exemplare trebuie depus la administratia financiara iar celalalt ramane la tine.\r\n\r\n\'Adrese si numere de telefon pentru administratiile financiare din Bucuresti\':http://www.miculparis.ro/utile/administratie/administratii_financiare_bucuresti.html\r\n\r\nh2. Intrebari, sugestii\r\n\r\nDaca ai nelamuriri putem discuta pe forum:\r\n\r\n==SmfTopic(topic_id=\"2725\")==',13,'protected',NULL,NULL),('doi-la-suta','Sprijină Asociaţia infoarena! Direcţionează 2%','2008-01-28 21:09:12','2009-02-02 21:22:43','h1. Sprijină Asociaţia infoarena!\r\n\r\n*_Direcţionează către noi 2% din impozitul pe venit datorat la stat._*\r\n\r\nÎn conformitate cu prevederile \'Codului Fiscal, art. 84\':http://www.edex.ro/articol_cod_fiscal_16661_Art.%2084:%20Stabilirea%20si%20plata%20impozitului%20pe%20venitul%20net%20anual%20impozabil.html poţi direcţiona 2% din impozitul pe venit datorat la stat către o entitate non-profit:\r\n\r\nbq. Contribuabilii pot dispune asupra destinaţiei unei sume reprezentând *2%* din impozitul datorat pe venitul net anual impozabil, câştigul net anual din transferul titlurilor de valoare, câştigul din operaţiuni din vânzare-cumparare de valută şi orice operaţiune de acest gen, pentru susţinerea entităţilor nonprofit.\r\n\r\n*Nu te costă nimic!* Impozitul pe venit rămâne acelaşi.\r\n\r\nÎn anul fiscal 2008 procedura \'a funcţionat\':/blog/doi-la-suta-2008-raport.\r\n\r\nh2. La ce folosim contribuţiile\r\n\r\ninfoarena ajută elevi şi studenţi să înveţe informatică şi programare. De mai bine de 4 ani de zile organizăm concursuri de informatică, scriem articole, dezvoltăm software, facem schimb de experienţă şi idei. Ne-am organizat pe acest site deoarece împreună învăţăm mai bine.\r\n\r\nPoţi să citeşti mai mult despre ce facem noi \'aici\':prezentare şi \'aici\':despre-infoarena. Am apărut şi în \'Adevărul\':http://www.adevarulonline.ro/articole/fostii-olimpici-ii-antreneaza-pe-concurentii-de-la-olimpiade/305061 (pe \'prima pagină\':doi-la-suta?1.pdf).\r\n\r\nVom folosi contribuţiile venite pe această cale să:\r\n\r\n* oferim premii: membrii comunităţii sunt mai motivaţi să se pregătească şi să participe la un concurs online de informatică atunci când se dau premii\r\n* finanţăm \'proiecte infoarena\':propuneri\r\n* motivăm comunitatea să se \'implice\':implica-te\r\n\r\n\'Aici\':okr poţi vedea ce ne propunem pentru trimestrul următor.\r\n\r\nh2. Ce trebuie să faci\r\n\r\nProcedura este foarte simplă. Ai grijă să te încadrezi în *termenul limită: 15 mai 2008*.\r\n\r\n# În funcţie de sursa ta de venit, descarcă, printează şi completează una din declaraţiile următoare:\r\n** *Dacă ai venituri numai din salarii*: \'Declaratia 230\':http://www.doilasuta.ro/doilasuta/Resurse_files/decl_230_2008.pdf\r\n** Dacă ai venituri (şi) din alte surse (cedarea folosinţei bunurilor, drepturi de autor, etc): \'Declaratia 200\':http://www.doilasuta.ro/doilasuta/Resurse_files/decl_200_2008.pdf\r\n# Foloseşte următoarele date de identificare pentru Asociaţia infoarena:\r\n** CUI: 21752294\r\n** IBAN: RO15&nbsp;RZBR&nbsp;0000&nbsp;0600&nbsp;0919&nbsp;4268, Deschis la: Raiffeisen, Ag. Unirea, Bucureşti\r\n** Adresa sediu social: Str. Dragos Voda Nr. 49, Bl. P9, Ap. 11, Barlad, Jud. Vaslui\r\n# Depune declaraţiile completate la administraţia financiară de care aparţine domiciliul tău. Opţional poţi să trimiţi declaraţia prin scrisoare recomandată către administraţia financiară.\r\n\r\nNu e nici o problemă dacă nu ştii exact suma care trebuie virată. Lasă rubrica \"Suma\" necompletată şi organul fiscal va calcula şi va vira suma admisă, conform legii.\r\n\r\nCompletează în două exemplare declaraţia corespunzătoare. Unul din exemplare trebuie depus la administraţia financiară iar celălalt rămâne la tine.\r\n\r\n\'Adrese şi numere de telefon pentru administraţiile financiare din Bucureşti\':http://www.miculparis.ro/utile/administratie/administratii_financiare_bucuresti.html\r\n\r\nPresupunând că extrasele bancare ne furnizează aceste informaţii, vom publica pe site o listă cu toţi contribuabilii care au direcţionat 2% din impozit către noi.\r\n\r\nh2. Intrebări, sugestii\r\n\r\nDacă ai nelămuriri putem discuta pe forum:\r\n\r\n==SmfTopic(topic_id=\"2725\")==',15,'protected',NULL,NULL),('blog/doi-la-suta-2008-raport','Vă mulțumim pentru sprijin! 2% pentru infoarena','2009-02-02 19:53:16','2009-02-02 23:14:50','h1. Vă mulţumim pentru sprijin!\r\n\r\nPeste 50 de persoane au sprijinit \'Asociaţia infoarena\':asociatia-infoarena direcţionând 2% din impozitul pe venit în anul fiscal 2008. Direcţionările au însumat 4.619 lei.\r\n\r\nAm fost surprinşi în mod plăcut de aceste contribuţii. Am simţit că apreciaţi infoarena şi munca pe care o depunem. Vă mulţumim pentru sprijin! Vom folosi banii aceştia la organizarea finalei \'Algoritmiada\':algoritmiada-2009, principala cheltuială anuală a \'Asociaţia infoarena\':asociatia-infoarena.\r\n\r\nh4. Ce este „2%”?\r\n\r\nbq. Sistemul „2%” permite contribuabililor persoane fizice să direcţioneze 2% din impozitul lor pe venit către o organizaţie neguvernamentală. Este un sistem prin care cetăţenii au posibilitatea să decidă în mod direct ce se întamplă cu impozitele lor. [...] Direcţionarea nu costă nimic. \'(Sursa)\':http://www.doilasuta.ro\r\n\r\nVă rugăm să vizitaţi pagină dedicată \'sistemului 2%\':doi-la-suta.\r\n\r\nh4. Contribuabili în 2008\r\n\r\nNu avem o listă nominală cu toţi contribuabilii, din cauză că programul „2%” prevede ca identitatea acestora să rămână secretă. Avem însă un tabel cu instituţiile fiscale ce au efectuat viramente în contul \'Asociaţiei infoarena\':asociatia-infoarena.\r\n\r\ntable{width:auto}. |_. Data |_. Instituţie |_. Sumă (lei) |\r\n| 2008-11-12 | Ministerul Finanţelor, acţiuni generale 2% |>. 1.334,42 |\r\n| 2008-12-17 | Sector 3, Bucureşti |>. 637,42 |\r\n| 2008-11-26 | Trezoreria Bugetului de Stat |>. 540,42 |\r\n| 2008-12-22 | Sector 5, Bucureşti |>. 475,42 |\r\n| 2008-11-25 | Sector 1, Bucureşti |>. 411,42 |\r\n| 2008-11-17 | Sibiu |>. 347,72 |\r\n| 2008-11-03 | AF Plopeni |>. 315,42 |\r\n| 2008-11-27 | Slatina |>. 228,42 |\r\n| 2008-11-05 | Bugetul de Stat |>. 144,42 |\r\n| 2008-11-27 | Sector 6 |>. 117,42 |\r\n| 2008-12-18 | Galaţi |>. 67,42 |\r\n|>\\2. *Total* |>. *4619,92* |\r\n\r\nDacă nu vă regăsiţi în lista de mai sus deşi v-aţi exercitat dreptul de a direcţiona 2% din impozit, vă rog să mă \'contactaţi\':mailto:cristian@infoarena.ro.\r\n\r\nh3. Ce facem cu banii primiţi?\r\n\r\nPrincipala cheltuială a \'Asociaţiei infoarena\':asociatia-infoarena o reprezintă organizarea anuală a finalei \'Algoritmiada\':algoritmiada-2009, eveniment la care sunt invitate 60 de persoane pentru care asigurăm cazare, masă, şi premii. În funcţie de locaţia pe care o alegem, bugetul finalei poate să depăşească 20.000 lei, astfel că toate aceste contribuţii sunt foarte bine venite.\r\n\r\nAlte direcţii în care vrem să investim resurse financiare ţin de stimularea comunităţii, în special a membrilor care se implică semnificativ în \'proiectele infoarena\':implica-te şi de organizarea \'întrunirilor\':planificare echipei infoarena. Spre exemplu, în week-endul 28 Februarie - 1 Martie, echipa infoarena organizează un „coding camp” - un „hei rup” la care reparăm bug-uri şi implementăm noi facilităţi pentru site şi evaluator.\r\n\r\nh3. „2%” în 2009\r\n\r\nDacă apreciaţi proiectul infoarena, vă rugăm să ne sprijiniţi şi în 2009. Procedura de direcţionare este simplă şi nu vă costă nimic! *Termenul limită este 15 mai 2009.*\r\n\r\n\'*Aflaţi ce trebuie să faceţi şi la ce vom folosi contribuţiile*\':doi-la-suta.\r\n\r\np. &nbsp;\r\n\r\nSunteţi unul dintre contribuabili? Spuneţi-ne cum a decurs procedura de direcţionare.\r\nAveţi nelămuriri? Lăsaţi-ne un comentariu.',13,'private',NULL,NULL),('blog/doi-la-suta-2008-raport','Vă mulțumim pentru sprijin! 2% pentru infoarena','2009-02-02 19:53:16','2009-02-02 23:17:32','h1. Vă mulţumim pentru sprijin!\r\n\r\nPeste 50 de persoane au sprijinit \'Asociaţia infoarena\':asociatia-infoarena direcţionând 2% din impozitul pe venit în anul fiscal 2008. Direcţionările au însumat 4.619 lei.\r\n\r\nAm fost surprinşi în mod plăcut de aceste contribuţii. Am simţit că apreciaţi infoarena şi munca pe care o depunem. Vă mulţumim pentru sprijin! Vom folosi banii aceştia la organizarea finalei \'Algoritmiada\':algoritmiada-2009, principala cheltuială anuală a \'Asociaţia infoarena\':asociatia-infoarena.\r\n\r\nh4. Ce este „2%”?\r\n\r\nbq. Sistemul „2%” permite contribuabililor persoane fizice să direcţioneze 2% din impozitul lor pe venit către o organizaţie neguvernamentală. Este un sistem prin care cetăţenii au posibilitatea să decidă în mod direct ce se întamplă cu impozitele lor. [...] Direcţionarea nu costă nimic. \'(Sursa)\':http://www.doilasuta.ro\r\n\r\nVă rugăm să vizitaţi pagină dedicată \'sistemului 2%\':doi-la-suta.\r\n\r\nh4. Contribuabili în 2008\r\n\r\nNu avem o listă nominală cu toţi contribuabilii din cauză că programul „2%” prevede ca identitatea acestora să rămână secretă. Avem însă un tabel cu instituţiile fiscale ce au efectuat viramente în contul \'Asociaţiei infoarena\':asociatia-infoarena.\r\n\r\ntable{width:auto}. |_. Data |_. Instituţie |_. Sumă (lei) |\r\n| 2008-11-12 | Ministerul Finanţelor, acţiuni generale 2% |>. 1.334,42 |\r\n| 2008-12-17 | Sector 3, Bucureşti |>. 637,42 |\r\n| 2008-11-26 | Trezoreria Bugetului de Stat |>. 540,42 |\r\n| 2008-12-22 | Sector 5, Bucureşti |>. 475,42 |\r\n| 2008-11-25 | Sector 1, Bucureşti |>. 411,42 |\r\n| 2008-11-17 | Sibiu |>. 347,72 |\r\n| 2008-11-03 | AF Plopeni |>. 315,42 |\r\n| 2008-11-27 | Slatina |>. 228,42 |\r\n| 2008-11-05 | Bugetul de Stat |>. 144,42 |\r\n| 2008-11-27 | Sector 6 |>. 117,42 |\r\n| 2008-12-18 | Galaţi |>. 67,42 |\r\n|>\\2. *Total* |>. *4.619,92* |\r\n\r\nDacă nu vă regăsiţi în lista de mai sus deşi v-aţi exercitat dreptul de a direcţiona 2% din impozit, vă rog să mă \'contactaţi\':mailto:cristian@infoarena.ro.\r\n\r\nh3. Ce facem cu banii primiţi?\r\n\r\nPrincipala cheltuială a \'Asociaţiei infoarena\':asociatia-infoarena o reprezintă organizarea anuală a finalei \'Algoritmiada\':algoritmiada-2009, eveniment la care sunt invitate 60 de persoane pentru care asigurăm cazare, masă şi premii. În funcţie de locaţia pe care o alegem şi de partenerii care ne sprijină, bugetul finalei poate să depăşească 20.000 lei, astfel că toate aceste contribuţii sunt foarte bine venite, chiar necesare.\r\n\r\nAlte direcţii în care vrem să investim resurse financiare ţin de stimularea comunităţii, în special a membrilor care se implică semnificativ în \'proiectele infoarena\':implica-te şi de organizarea \'întrunirilor\':planificare echipei infoarena. Spre exemplu, în week-endul 28 Februarie - 1 Martie, echipa infoarena organizează un „coding camp” - un „hei rup” la care reparăm bug-uri şi implementăm noi facilităţi pentru site şi evaluator.\r\n\r\nh3. „2%” în 2009\r\n\r\nDacă apreciaţi proiectul infoarena, vă rugăm să ne sprijiniţi şi în 2009. Procedura de direcţionare este simplă şi nu vă costă nimic! *Termenul limită este 15 mai 2009.*\r\n\r\n\'*Aflaţi ce trebuie să faceţi şi la ce vom folosi contribuţiile*\':doi-la-suta.\r\n\r\np. &nbsp;\r\n\r\nSunteţi unul dintre contribuabili? Spuneţi-ne cum a decurs procedura de direcţionare.\r\nAveţi nelămuriri? Lăsaţi-ne un comentariu.',13,'private',NULL,NULL),('doi-la-suta','Sprijină Asociaţia infoarena! Direcţionează 2%','2008-01-28 21:09:12','2009-02-02 23:49:05','h1. Sprijină Asociaţia infoarena!\r\n\r\n*_Direcţionează către noi 2% din impozitul pe venit datorat la stat._*\r\n\r\nbq. Sistemul „2%” permite contribuabililor persoane fizice să direcţioneze 2% din impozitul lor pe venit către o organizaţie neguvernamentală. Este un sistem prin care cetăţenii au posibilitatea să decidă în mod direct ce se întamplă cu impozitele lor. [...] Direcţionarea nu costă nimic. \'(Sursa)\':http://www.doilasuta.ro\r\n\r\n*Nu te costă nimic!* Impozitul pe venit rămâne acelaşi. \r\n\r\nÎn anul fiscal 2008 procedura \'a funcţionat\':/blog/doi-la-suta-2008-raport.\r\n\r\nh2. La ce folosim contribuţiile\r\n\r\ninfoarena ajută elevi şi studenţi să înveţe informatică şi programare. De mai bine de 5 ani de zile organizăm concursuri de informatică, scriem articole, dezvoltăm software, facem schimb de experienţă şi idei. Ne-am organizat pe acest site deoarece împreună învăţăm mai bine.\r\n\r\nPoţi să citeşti mai mult despre ce facem noi \'aici\':prezentare şi \'aici\':despre-infoarena. Am apărut şi în \'Adevărul\':http://www.adevarulonline.ro/articole/fostii-olimpici-ii-antreneaza-pe-concurentii-de-la-olimpiade/305061 (pe \'prima pagină\':doi-la-suta?infoarena-adevarul-prima-pagina.pdf).\r\n\r\nVom folosi contribuţiile venite pe această cale să:\r\n\r\n* oferim premii: membrii comunităţii sunt mai motivaţi să se pregătească şi să participe la un concurs online de informatică atunci când se dau premii\r\n* organizăm finale de concursuri: în fiecare an organizăm \'un concurs\':algoritmiada-2009 cu finală; finala are menirea să ne strangă la un loc cu ce mai buni dintre elevii şi studenţii României pentru câteva zile şi să formăm noi prietenii\r\n* motivăm comunitatea să se \'implice\':implica-te\r\n* finanţăm \'proiecte infoarena\':propuneri\r\n\r\nVezi \'obiectivele infoarena\':okr pentru trimestrul curent şi \'rezoluţiile şi notiţele fiecărei şedinţe de consiliu\':planificare.\r\n\r\nh2. Ce trebuie să faci\r\n\r\nProcedura este foarte simplă. Ai grijă să te încadrezi în *termenul limită: 15 mai 2008*.\r\n\r\n# În funcţie de sursa ta de venit, descarcă, printează şi completează una din declaraţiile următoare:\r\n** Dacă ai venituri numai din salarii: \'declaratia 230\':http://doilasuta.ro/pagini/resurse/decl_230_2008.pdf\r\n** Dacă ai venituri (şi) din alte surse (cedarea folosinţei bunurilor, drepturi de autor, etc): \'declaratia 200\':http://doilasuta.ro/pagini/resurse/decl_200_2008.pdf\r\n# Foloseşte următoarele date de identificare pentru Asociaţia infoarena:\r\n** *CUI*: 21752294\r\n** *IBAN*: RO15&nbsp;RZBR&nbsp;0000&nbsp;0600&nbsp;0919&nbsp;4268, *Deschis la*: Raiffeisen, Ag. Unirea, Bucureşti\r\n** *Adresa sediu social*: Str. Dragoş Vodă Nr. 49, Bl. P9, Ap. 11, Bârlad, Jud. Vaslui\r\n# Depune declaraţiile completate la administraţia financiară de care aparţine domiciliul tău. Alternativ poţi să trimiţi declaraţia prin scrisoare recomandată către administraţia financiară.\r\n\r\nAlte informaţii utile:\r\n\r\n* Completează în două exemplare declaraţia corespunzătoare. Unul din exemplare trebuie depus la administraţia financiară iar celălalt rămâne la tine.\r\n\r\n* Nu e nici o problemă dacă nu ştii exact suma care trebuie virată. Lasă rubrica „Suma” necompletată şi organul fiscal va calcula şi va vira suma admisă, conform legii\r\n\r\n* \'Adrese şi numere de telefon pentru administraţiile financiare din Bucureşti\':http://www.miculparis.ro/utile/administratie/administratii_financiare_bucuresti.html\r\n\r\nh2. Intrebări, sugestii\r\n\r\nDacă ai nelămuriri putem discuta pe forum:\r\n\r\n==SmfTopic(topic_id=\"2725\")==\r\n',13,'protected',NULL,NULL),('stelele-2009/9-10/clasament/runda-1','Stelele Informaticii 2009, clasele 9-10, ziua 1','2009-02-03 21:45:34','2009-02-03 21:55:35','h1. Stelele Informaticii 2009, clasele 9-10, ziua 1\r\n\r\np<. == Rankings(rounds=\"stelele-2009-runda1-9-10\") == ',1792,'protected',NULL,NULL),('template/newsletter/prima-data','template/prima-data','2009-02-04 00:11:25','2009-02-04 00:20:23','h2{font-size: 12pt}. Prima dată la infoarena? \r\n\r\nEste prima dată când participi la un concurs pe infoarena? Citeşte \'tutorialul infoarena\':documentatie/tutorial.\r\n',13,'protected',NULL,NULL),('template/newsletter/rating','template/newsletter/rating','2009-02-04 00:08:21','2009-02-04 00:20:28','h2{font-size: 12pt}. Atenţie! Concurs cu rating!\r\n\r\nDacă vrei să ţi se modifice \'rating-ul\':documentatie/rating în urma acestei runde trebuie să îţi anunţi participarea din timp. \'Intră pe pagina concursului şi înscrie-te\':%round_url%. ==NewsletterRating(username=\"%username%\")==\r\n\r\nPoţi să participi la concurs chiar şi dacă nu te-ai înscris în prealabil însă nu ţi se va modifica \'rating-ul\':documentatie/rating.\r\n',13,'protected',NULL,NULL),('newsletter/stelele-2009-9-10','Stelele Informaticii, clasele IX - X și gimnaziu','2009-02-04 00:15:25','2009-02-04 01:31:43','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎn acest weekend se desfăşoară la Bucureşti concursul „Stelele Informaticii” pentru clasele IX-X şi gimnaziu, organizat de \'ICHB\':http://ichb.ro/. Deşi „stelele” este un concurs pe bază de invitaţie, anul acesta se va ţine în premieră pe infoarena, iar tu poţi să concurezi cot la cot cu participanţii on-site. Este o ocazie excelentă să-ţi verifici cunostinţele înainte de debutul olimpiadelor!\r\n\r\nProgram „Stelele Informaticii” clasele IX-X şi gimnaziu:\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt}. Proba 1 - 6 Februarie 2009 între orele 09^00^ şi 13^00^\r\nProba 2 - 7 Februarie 2009 între orele 10^00^ şi 14^00^ |\r\n\r\nConcursul pentru clasele XI-XII va fi anunţat şi organizat într-una din săptămânile viitoare. Află mai multe informaţii de pe \'pagina concursului\':stelele-2009.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"stelele-2009\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre „Stelele Informaticii”\r\n\r\n„Stelele Informaticii” este un concurs anual organizat şi găzduit de \'Liceul Internaţional de Informatică Bucureşti\':http://www.ichb.ro/. Prima ediţie a concursului a avut loc în noiembrie 2003.\r\n\r\nLa acest concurs sunt invitaţi să participe toţi elevii care au obţinut premii la Olimpiadele Naţionale de Informatică sau care au fost incluşi în loturile de pregătire pentru concursurile internaţionale. În funcţie de locurile disponibile mai participă şi alţi elevi. Scopul competiţiei este de a constitui o primă întrecere a elevilor talentaţi în programare, o avanpremieră a competiţiilor care vor urma pe parcursul anului şcolar. Concursul se desfăşoară separat pentru clasele IX-X şi gimnaziu, respectiv XI-XII.\r\n\r\nLa clasele IX - X vor propune probleme ...\r\n\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==\r\n',13,'protected',NULL,NULL),('newsletter/stelele-2009-9-10','Stelele Informaticii, clasele IX - X și gimnaziu','2009-02-04 00:15:25','2009-02-04 01:46:43','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎn acest weekend se desfăşoară la Bucureşti concursul „Stelele Informaticii” pentru clasele IX-X şi gimnaziu, organizat de \'ICHB\':http://ichb.ro/. Deşi „stelele” este un concurs pe bază de invitaţie, anul acesta se va ţine în premieră pe infoarena, iar tu poţi să concurezi cot la cot cu participanţii on-site. Este o ocazie excelentă să-ţi verifici cunostinţele înainte de debutul olimpiadelor!\r\n\r\nProgram „Stelele Informaticii” clasele IX-X şi gimnaziu:\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt}. \'Proba 1\':stelele-2009/9-10/runda-1 - 6 Februarie 2009 între orele 09^00^ şi 13^00^\r\n\'Proba 2\':stelele-2009/9-10/runda-2 - 7 Februarie 2009 între orele 10^00^ şi 14^00^ |\r\n\r\nConcursul pentru clasele XI-XII va fi anunţat şi organizat într-una din săptămânile viitoare. Află mai multe informaţii de pe pagina \'„Stelele Informaticii”\':stelele-2009.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"stelele-2009\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre „Stelele Informaticii”\r\n\r\n„Stelele Informaticii” este un concurs anual organizat şi găzduit de \'Liceul Internaţional de Informatică Bucureşti\':http://www.ichb.ro/. Prima ediţie a concursului a avut loc în noiembrie 2003.\r\n\r\nLa acest concurs sunt invitaţi să participe toţi elevii care au obţinut premii la Olimpiadele Naţionale de Informatică sau care au fost incluşi în loturile de pregătire pentru concursurile internaţionale. În funcţie de locurile disponibile mai participă şi alţi elevi. Scopul competiţiei este de a constitui o primă întrecere a elevilor talentaţi în programare, o avanpremieră a competiţiilor care vor urma pe parcursul anului şcolar. Concursul se desfăşoară separat pentru clasele IX-X şi gimnaziu, respectiv XI-XII, pe parcursul a două probe, în două zile diferite. \r\n\r\nLa fiecare probă vei avea de rezolvat 3 probleme de natură algoritmică. Subiectele vor fi propuse şi pregătite de către:\r\n\r\n* ==User(user=\"silviug\" type=\"link\")==\r\n* ==User(user=\"pauldb\" type=\"link\")==\r\n* ==User(user=\"wefgef\" type=\"link\")==\r\n* ==User(user=\"efer\" type=\"link\")==\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/doi-la-suta\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==\r\n',13,'protected',NULL,NULL),('deque-si-aplicatii','Deque și aplicații','2009-01-22 22:28:12','2009-02-04 14:34:39','h1. Deque şi aplicaţii\r\n\r\n(Categoria _Structuri de date_, Autor _Xulescu_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'Introducere\':deque-si-aplicatii#introducere\r\n* \'Operaţii\':deque-si-aplicatii#operatii\r\n* \'Aplicaţii\':deque-si-aplicatii#aplicatii\r\n** \'Problema 1: Book Pile &#40;SGU&#41;\':deque-si-aplicatii#problema-1\r\n** \'Problema 2: Vila 2\':deque-si-aplicatii#problema-2\r\n** \'Problema 3: Şir\':deque-si-aplicatii#problema-3\r\n** \'Problema 4: Trans &#40;ONI 2004&#41;\':deque-si-aplicatii#problema-4\r\n** \'Problema 5: Otilia &#40;.campion&#41;\':deque-si-aplicatii#problema-5\r\n** \'Problema 6: Bcrc &#40;Stelele Informaticii 2006&#41;\':deque-si-aplicatii#problema-6\r\n** \'Problema 7: Cut the Sequence &#40;PKU&#41;\':deque-si-aplicatii#problema-7\r\n* \'Concluzii\':deque-si-aplicatii#concluzii\r\n* \'Probleme suplimentare\':deque-si-aplicatii#probleme-suplimentare\r\n* \'Bibliografie\':deque-si-aplicatii#bibliografie\r\n\r\nÎn acest articol voi prezenta o structură de date de tip listă numită _deque_. Simplitatea acestei structuri poate nu are multe de spus şi din acest motiv am prezentat şi o serie de aplicaţii care vor arăta neaşteptata sa utilitate şi apariţie în locurile unde am fi crezut că nu se mai poate face nimic pentru a reduce complexitatea.\r\n\r\nh2(#introducere). Introducere\r\n\r\n_Dequeul_ (pronunţat de obicei _deck_) poate fi privit ca o colecţie de tip listă ce are două capete prin care se şterg sau inserează noi elemente. În literatura de specialitate, aceste capete se numesc _head_ şi _tail_, iar dequeul mai este recunoscut şi ca fiind o coadă cu două capete _(double ended queue)_.\r\n\r\nUn deque poate fi implementat folosind liste dublu înlănţuite, sau cu un vector static când se cunoaşte numărul elementelor din colecţie. Ce trebuie reţinut este că limbajul C++ pune la dispoziţia utilizatorilor prin intermediul headerului _#include <deque>_ clasa _std::deque_.\r\n\r\nh2(#operatii). Operaţii\r\n\r\nMai jos sunt enumerate operaţiile care pot fi efectuate asupra unui deque împreună cu corespondentul lor în limbajul C++:\r\n\r\n* _front()_:	    întoarce primul element;\r\n* _back()_:	    întoarce ultimul element;\r\n* _push_front()_: inserează un element în faţă;\r\n* _push_back()_:  inserează un element în spate;\r\n* _pop_front()_:  scoate primul element;\r\n* _pop_back()_:   scoate ultimul element;\r\n* _empty()_:      întoarce _true_ dacă dequel este gol.\r\n\r\np=. !deque-si-aplicatii?new_deque.png 75%!\r\n\r\nToate aceste operaţii se execută în timp $O(1)$ \'amortizat\':http://en.wikipedia.org/wiki/Amortized_analysis. Pentru un plus de viteză va trebui să folosim un vector static cu dimensiunea egală cu numărul maxim de elemente ce pot trece prin deque, iar operaţiile implementate „de mână”, cu doi indecşi ce indică către head şi tail. Însă, în majoritatea aplicaţiilor limita de timp permite folosirea lejerităţii şi siguranţei clasei _std::deque_.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\nÎn multe aplicaţii unde soluţiile parţiale se reprezintă sub forma unui şir continuu de valori care permite inserarea şi ştergerea doar pe la capete (în general inserări pe la un capăt şi ştergeri pe la celălalt) se poate folosi un deque. Să urmărim în continuare cazuri concrete în care simplitatea unui deque duce la soluţii de multe ori optime şi implementări foarte scurte şi clare.\r\n\r\nh3(#problema-1). Problema 1: \'Book Pile\':http://acm.sgu.ru/problem.php?contest=0&problem=271 (SGU)\r\n\r\nbq. Se dau $N$ cărţi aşezate una deasupra celeilalte asupra cărora se vor efecta $M$ operaţii de două tipuri: 1. $ADD${$(nume)$} : se adaugă cartea $nume$ deasupra celorlalte; 2. $ROTATE$ : primele $K$ cărţi de deasupra se rotesc (dacă sunt mai puţin de $K$ cărţi atunci se vor roti toate). Se cere să se afişeze cărţile în ordine, prima fiind cea de deasupra, după efectuarea celor $M$ operaţii.\r\nRestricţii: $0 &le; N, K &le; 40 000$, $0 &le; M &le; 100 000$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se poate deduce urmând paşii următori. Să presupunem că avem cărţile $A B C$ iniţial şi $K = 3$. Dacă îl vom adăuga pe $D$, atunci nu vor rămâne importante decât cărţile $D A B$, deoarece, dacă vom roti ulterior ultimele $K$ cărţi, $C$ nu va mai fi niciodată considerat, cărţile fiind doar adăugate, iar o dată ce o carte iese din „top {$K$}” cărţi nu va mai fi posibil să i se schimbe poziţia pe raft. Să rotim acum „top {$K$}” cărţi. Noua ordine va fi $B A D$ şi $C$ pe raft la loc sigur. Dacă îl vom adăuga pe $E$, topul se va schimba în $E B A$ iar pe raft, în mod sigur vor fi, în această ordine, $D C$. Proprietatea celor $K$ cărţi din vârf este: o secvenţă continuă de elemente, la care se adaugă noi elemente sau se elimină dintre acestea numai pe la _capete_. Aceste capete sunt chiar head şi tail ale unui deque.\r\n\r\np=. !deque-si-aplicatii?bookpile.png 40%!\r\n\r\nLa final, când se vor termina operaţiile, cărţilor de pe raft li se vor adăuga cele din deque şi se va afişa soluţia. În cazul presupus, soluţia va fi: $E B A D C$.\r\n\r\nÎntrucât operaţiile unui deque se execută în $O(1)$ amortizat, soluţia are complexitatea $O(N + M)$.\r\n\r\nh3(#problema-2). Problema 2: \'Vila 2\':problema/vila2 (.campion)\r\n\r\nbq. Se dă un şir $S$ de $N$ numere întregi şi un $D$ număr natural. Se cere să determine diferenţa maximă dintre oricare două numere din şir cu proprietatea că diferenţa indicilor nu depăşeşte $D$.\r\nRestricţii: $2 &le; N &le; 100 000$, $1 &le; D &le; N/2$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia nu e greu de intuit. Considerăm indicii succesiv $1$, $2$, .. , $N$. Va trebuie ca pentru fiecare secvenţă $(i - D, i]$ să determinăm valoarea maximă şi pe cea minimă, iar diferenţa lor să o comparăm cu rezultatul obţinut până în acel moment. Pentru fixarea ideilor, să urmărim cum putem determina valoarea maximă din fiecare secvenţă $(i - D, i]$.\r\n\r\n_Observaţie_: „Fie $i{~1~}$, $i{~2~}$ doi indici din astfel încât $i - D &lt; i{~1~} &lt; i{~2~} &le; i$.\r\n\r\n# Dacă $S[i{~1~}] &lt; S[i{~2~}]$ atunci, cât timp cei doi indici vor fi în intervalul $(i - D, i]$, valoarea de pe poziţia $i{~2~}$ va fi întotdeauna preferată valorii de pe poziţiei $i{~1~}$. Când unul din indici nu va mai fi în acest interval, cel expediat va fi $i{~1~}$ şi, astfel, $i{~2~}$ rămâne în continuare preferat.\r\n# Dacă $S[i{~1~}] &gt; S[i{~2~}]$ atunci îl vom păstra pe $i{~2~}$, deoarece este candidat la maxim în viitor.”\r\n\r\nCu această observaţie deducem că într-o secvenţă $(i - D, i]$ vom avea un şir $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$ astfel încât $S[i{~1~}] &gt; S[i{~2~}] &gt; ... &gt; S[i{~K~}]$. Când vom avansa la secvenţa următoare, $(i - D + 1, i + 1]$, vom şterge din indici $i{~1~}$, $i{~2~}$... atâta timp cât nu se găsesc în intervalul curent şi vom şterge din poziţiile $i{~K~}$, $i{~K-1~}$... cât timp $S[i + 1] &gt; S[i{~K~}]$, $S[i + 1] &gt; S[i{~K-1~}]$... adică cât timp se îndeplineşte primul punct din observaţia anterioară.\r\n\r\nŞirul $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$ este continuu iar operaţiile se efectuează doar pe la cele două capete. Rezultă că şirul poate fi implementat cu ajutorul unui deque.\r\n\r\nPentru $S[] = {5, 9, 4, 7, 4, 1}$ şi $D = 3$ obţinem următoarele stări ale unui deque:\r\n\r\np=. !deque-si-aplicatii?vila2.png 60%!\r\n\r\nCum fiecare indice din $1$, $2$, .., $N$ trece cel mult o dată prin deque complexitatea finală este $O(N)$ amortizat.\r\n\r\nh3(#problema-3). Problema 3: \'Şir\':problema/sir\r\n\r\nbq. Se dă un şir $S$ de numere întregi de lungime $N$. Se cere să se găsească secvenţa de lungime maximă cuprinsă între $X$ şi $Y$ astfel încât $MAX - MIN &le; Z$, unde $MAX$ este maximul dintre toate numerele întregi din secvenţă iar $MIN$ minimul dintre acestea. Secvenţa soluţie va fi cea cu poziţia de început maximă dintre toate secvenţele de lungime maximă.\r\nRestricţii: $3 &le; N &le; 100 000$, $1 &le; X &le; Y &le; N$, $0 &le; Z &le; 30 000$.\r\n\r\nh3. Soluţie\r\n\r\nVoi prezenta mai jos o rafinare a soluţiei în trei paşi.\r\n\r\nPrima rezolvare se găseşte uşor, deoarece nu facem decât să urmărim textul: pentru fiecare poziţie $i$ fixată ({$i$} ia valorile $1$, $2$, .., $N$ succesiv) vom determina pentru aceasta secvenţa cerută, adică vom plimba un $j$ între poziţiile $i - Y$ şi $i - X$. Pentru un interval $(j, i]$ vom determina $MAX$ şi $MIN$ în $O(log{~2~}N)$ cu un arbore de intervale, iar daca diferenţa dintre acestea nu depăşeşte $Z$ vom compara cu soluţia finală. Complexitatea finală va fi $O(N * (Y - X) * log{~2~}Y)$.\r\n\r\nSă presupunem că pentru poziţia curentă $i$, l-am găsit pe $j$ cuprins între $i - Y$ şi $i - X$ care îndeplineşte optimul. Ce proprietăţi are $j$?\r\n\r\n* $i - Y &le; j &le; i - X$ şi $MAX - MIN &le; Z$;\r\n* dacă îl incrementăm pe $j$ la $j + 1$ atunci dacă $j &le; i - X$ cu siguranţă $MAX - MIN &le; Z$ şi astfel soluţia va fi mai scurtă;\r\n* dacă îl decrementăm pe $j$, atunci ori $j < i - Y$ ori $MAX - MIN > Z$;\r\n* dacă îl incrementăm pe $i$ la $i + 1$, atunci se poate întâmpla ca $j < i - Y$; cum $MAX$ nu poate decât să crească, iar $MIN$ decât să scadă, se mai poate de asemenea întâmpla ca $MAX - MIN > Z$.\r\n\r\nDatorită proprietăţilor de mai sus, când trecem de la $i$ la $i + 1$, valoarea lui $j$ nu poate decât să crească cât timp $j < i - Y$ sau $MAX - MIN > Z$ şi $j$ nu a depăşit poziţia $i - X$. Pentru determinarea lui $MAX$, respectiv lui $MIN$ se poate folosi un arbore de intervale. Complexitatea finală va fi $O(N * log{~2~}(Y))$.\r\n\r\nCu cei doi indici $i$ şi $j$ vom accesa fiecare element din cele $N$ de cel mult $2$ ori, o dată cu $i$ şi o dată cu $j$. Să vedem cum putem îmbunătăţi complexitatea $O(log{~2~}Y)$ pentru determinarea maximului şi minimului.\r\n\r\nPentru fixarea ideilor să urmărim cum îl calculăm pe $MAX$. Observaţia care ne ajută în multe probleme pentru reducerea complexităţii de la $O(log{~2~}N)$ la $O(1)$ amortizat este următoarea: \r\n\r\n_Observaţie_: „Fixăm $i{~1~}$ şi $i{~2~}$ astfel încât $j < i{~1~} < i{~2~} &le; i$. Atunci, dacă $S[i{~2~}] > S[i{~1~}]$ poziţia $i{~2~}$ va fi întotdeauna mai importantă decât poziţia $i{~1~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ şi $i{~2~}$ nu vor mai fi ambele în intervalul $(j, i]$, poziţia eliminată va fi {$i{~1~}$}. Dacă însă $S[i{~1~}] > S[i{~2~}]$, atunci poziţia $i{~1~}$ va umbri poziţia $i{~2~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ va fi eliminat, atunci e posibil ca $i{~2~}$ să fie un candidat la $MAX$ dintre restul elementelor de la dreapta sa. În acest caz, nu putem afirma nimic şi vom păstra cele două poziţii.”\r\n\r\nRezultă din această observaţie că în intervalul $(j, i]$ poziţiile importante vor fi $j < i{~1~} < i{~2~} < .. < i{~k~} <= i$ astfel încât $S[i{~1~}] > S[i{~2~}] > .. > S[i{~k~}]$. Astfel, $MAX$ va fi $S[i{~1~}]$. Când îl vom incrementa pe $i$ la $i + 1$ vom şterge din poziţiile $i{~k~}$, $i{~k-1~}$, ... atâta timp cât $S[i + 1]$ este mai important, adică mai mare decât valorile de pe aceste poziţii, şi vom şterge $i{~1~}$, $i{~2~}$, ... atâta timp cât aceste poziţii sunt mai mici sau egale decât $j\'$. Indicele $j\'$ este noul optim pentru poziţia $i + 1$. Proprietatea şirului de poziţii $i{~1~}, i{~2~}, .., i{~k~}$ este că se reprezintă ca un şir continuu de numere care permite inserarea elementelor prin dreapta şi ştergerea prin stânga, adică se adaugă elemente la tail şi se şterg elemente de la head. Îl putem deci reprezenta printr-un deque. Complexitatea $O(1)$ amortizat provine de la faptul că fiecare poziţie dintre cele $N$ nu trece decât o singură dată prin deque şi este şters tot cel mult o singură dată. \r\n\r\nÎn practică, pseudocodul poate arăta în felul următor:\r\n\r\n== code(cpp) |\r\n// S şirul de numere iniţial şi N lungimea sa\r\n\r\nSubalgoritmul push_in(deque, întreg p, funcţia fct) este:\r\n    cât timp (!deque.empty() şi fct(S[p], S[deque.back()])) execută\r\n        deque.pop_back();\r\n    deque.push_back(p);\r\nSfârşit;\r\n\r\nFuncţia query(deque, întreg j) este:\r\n    cât timp (!deque.empty() şi deque.front() <= j) execută\r\n        deque.pop_front();\r\n    return S[deque.front()];\r\nSfârşit;\r\n\r\nAlgoritmul este:\r\n    lg = 0;\r\n    pentru i = 1, N execută\r\n        // funcţia min(a, b) întoarce true dacă a < b\r\n        inserează(min_deq, i, min);\r\n        // funcţia max(a, b) întoarce true dacă a > b\r\n        inserează(max_deq, i, max);\r\n        cât timp ((j < i - Y sau query(max_deq, j) - query(min_deq, j) > Z) şi j < i - X) execută\r\n            j = j + 1;\r\n        // (j, i] este intervalul candidat la soluţia optimă pentru poziţia i\r\n        dacă (j <= i - X) şi (query(max_deq, j) - query(min_deq, j) <= Z) atunci\r\n            dacă (lg >= i - j) atunci\r\n                lg = i - j, start = j + 1, stop = i;\r\n    sfârşit_pentru\r\n\r\n    dacă (lg > 0) atunci\r\n        scrie lg, start, stop;\r\n    altfel\r\n        scrie -1;\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală va fi $O(N)$.\r\n\r\nh3(#problema-4). Problema 4: \'Trans\':problema/trans (ONI 2004)\r\n\r\nbq. Se dau $N$ blocuri de piatră, de culoare albă sau neagră aşezate în ordinea $1$, $2$,.., $N$. Blocurile de piatră trebuie să fie transportate în ordinea în care sunt, iar pentru aceasta va trebui închiriat un camion. Se mai dau $Q$ tipuri de camioane. Camionul de tipul $i (1 &le; i &le; Q)$ poate transporta maxim $K{~i~}$ blocuri de piatră la un moment dat şi pentru un transport se percepe taxa $T{~i~}$. Se impune condiţia ca toate blocurile de piatră plasate în camion la un transport sa aibă aceeaşi culoare. Aşadar, pentru a fi transportate toate blocurile, se va alege un camion de un anumit tip, iar camionul va efectua unul sau mai multe transporturi. Pentru a micşora suma totală plătită, există posibilitatea de a schimba culoarea oricărui bloc de piatră (din alb în negru sau din negru în alb); pentru fiecare bloc $i (1 &le; i &le; N)$ se cunoaşte suma $S{~i~}$ ce trebuie plătită pentru a-i schimba culoarea $C{~i~}$.\r\nCerinţă: Pentru fiecare dintre cele $Q$ tipuri de camioane, determinaţi suma minimă plătită pentru a transporta toate cele $N$ blocuri.\r\nRestricţii: $1 &le; N &le; 16 000$, $1 &le; Q &le; 100$, $1 &le; K{~i~} &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se bazează pe găsirea unei formule de recurenţă ce respectă principiul optimalităţii al metodei programării dinamice.\r\n\r\nPentru început, fixăm un camion dintre cele $Q$. Fie $K$ numărul maxim de pietre pe care acesta le poate transporta şi $T$ taxa percepută. Notăm $sum[i][&#99;]$ costul pentru a schimba toate pietrele $1$, $2$, .., $i$ în culoarea $c$ ({$c = 0$} pentru alb şi $c = 1$ pentru negru). În $sum[i][&#99;]$ se vor aduna toate valorile $S[j]$, cu $j &le; i$ pentru care $C[j] = 1 - c$. \r\n\r\nÎn continuare, considerăm $bst[i][&#99;]$ costul minim pentru a transporta pietrele $1$, $2$, .., $i$, iar ultimul transport conţine pietre de culoare $c$. Întrucât nu putem transporta mai mult de $K$ pietre, $bst[i][&#99;]$ depinde doar de poziţiile $i - K$, $i - K + 1$, ..., $i - 1$. Cunoaştem că ultimul camion va transporta o secvenţă continuă de pietre începând de la o poziţie $j + 1$ până la poziţia $i$, unde $i - K &le; j &le; i - 1$. Astfel, pentru fiecare $j$ în intervalul precedent, costul va fi $Min(bst[j][&#48;], bst[j][&#49;])$ (transportăm primele j pietre cât mai ieftin) adunat cu $sum[i][&#99;] - sum[j][&#99;]$ (costul transformării pietrelor $j + 1$, .., $i$ în culoarea $c$) şi plus taxa $T$. Rezultă recurenţa:\r\n\r\n* $bst[i][&#99;] = Min{ Min(bst[j][&#48;], bst[j][&#49;]) + sum[i][&#99;] - sum[j][&#99;] } + T$, unde $i - K &le; j &le; i - 1$.\r\n\r\nDacă ne vom opri aici, complexitatea soluţiei va fi $O(Q * N^2^)$.\r\n\r\nRelaţia de recurenţă poate fi îmbunătăţită. Observăm că pentru poziţia $i$, $sum[i][&#99;]$ este o valoare constantă, ca şi $T$. Astfel, deducem următoarea relaţie de recurenţă:\r\n\r\n* $bst[i][&#99;] = Min{ Min(bst[j][&#48;], bst[j][&#49;]) - sum[j][&#99;] } + sum[i][&#99;] + T$, unde $i - K &le; j &le; i - 1$.\r\n\r\nNotez în continuare, pentru uşurinţă în scriere, $X[j][&#99;] = Min(bst[j][&#48;], bst[j][&#49;]) - sum[j][&#99;]$. Să fixăm doi indici $i{~1~}$ şi $i{~2~}$, astfel încât $i - K &le; $i{~1~}$ < $i{~2~}$ &le; i - 1$. Dacă $X[i{~1~}][&#99;] > X[i{~2~}][&#99;]$ atunci, întotdeauna poziţia $i{~2~}$ va fi preferată poziţiei $i{~1~}$. Când cele două nu se vor mai afla în intervalul $[i - K, i - 1]$, poziţia eliminată va fi poziţia $i{~1~}$. Dacă $X[i{~1~}][&#99;] < X[i{~2~}][&#99;]$, atunci nu putem decide care poziţie este mai bună în viitor, aşa că le vom păstra pe ambele. Rezultă mai departe că în intervalul $[i - K, i - 1]$ vom avea o serie de indecşi candidaţi la minim $i - K &le; i{~1~} < i{~2~} < .. < i{~n~} &le; i - 1$ astfel încât $X[i{~1~}][&#99;] < X[i{~2~}][&#99;] <  .. < X[i{~n~}][&#99;]$. Mai departe, găsim $bst[i][&#99;]$ ca fiind $X[i{~1~}][&#99;] + sum[i][&#99;] + T$. Urmează să îl introducem şi pe $X[i][&#99;]$, el fiind egal cu $Min(bst[i][&#48;], bst[i][&#49;]) - sum[i][&#99;]$, în şirul de indecşi de mai sus. Acest lucru se va face în felul următor: se vor elimina din $i{~n~}$, $i{~n-1~}$, ... atâta timp cât $X[$i{~n~}$][&#99;] > X[i][&#99;]$, $X[$i{~n-1~}$][&#99;] > X[i][&#99;]$, ... adică atâta timp cât poziţia $i$ este preferată lui $i{~n~}$, $i{~n-1~}$... Fiind la poziţia $i + 1$, intervalul se va transforma în $[i - K + 1, i]$, aşadar, vom mai elimina din primii indici $i{~1~}$, $i{~2~}$,... atâta timp cât $i{~1~} < i - K + 1$, $i{~2~} < i - K + 1$...\r\n\r\nDupă cum am arătat şi la problema precedentă, acest şir de indecşi $i{~1~}$, $i{~2~}$, .., $i{~n~}$ are proprietatea că este un şir continuu de numere care admite inserări prin dreapta (tail) şi ştergeri prin stânga (head). Şir ce poate fi reprezentat printr-un deque. Cum fiecare index dintre $1$, $2$, .., $N$ va trece o singură dată prin deque şi va fi şters cel mult o dată, complexitatea soluţiei în acest caz va fi $O(Q * N)$.\r\n\r\nÎn practică, programul este scurt, clar şi foarte eficient:\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\n#include <vector>\r\n#include <deque>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\nconst char iname[] = \"trans.in\";\r\nconst char oname[] = \"trans.out\";\r\n\r\n#define MAXN  16005\r\n#define Min(a, b) ((a) < (b) ? (a) : (b))\r\n#define FOR(i, a, b)  for (int i = (a); i <= (b); ++ i)\r\n\r\nint C[MAXN], S[MAXN], bst[MAXN][2], sum[MAXN][2], N;\r\n\r\nvoid insert(deque < pair <int, int> >& deq, const pair <int, int>& p) {\r\n    while (!deq.empty() && deq.back().second > p.second)\r\n        deq.pop_back();\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque < pair <int, int> >& deq, const int idx) {\r\n    while (deq.front().first < idx)\r\n        deq.pop_front();\r\n    return deq.front().second;\r\n}\r\n\r\nint work(const int K, const int T) {\r\n    deque < pair <int, int> > deq[2];       // pair (idx, value)\r\n    FOR (c, 0, 1)\r\n        insert(deq[c], pair <int, int>(0, 0));\r\n    FOR (i, 1, N) {   // obiectul i\r\n        FOR (c, 0, 1) // culoare\r\n            bst[i][c] = query(deq[c], i - K) + sum[i][c] + T;\r\n        FOR (c, 0, 1)\r\n            insert(deq[c], pair <int, int>(i, Min(bst[i][0], bst[i][1]) - sum[i][c]));\r\n    }\r\n    return Min(bst[N][0], bst[N][1]);\r\n}\r\n\r\nint main(void)\r\n{\r\n    ifstream in(iname);  ofstream out(oname);\r\n    in >> N;\r\n    FOR (i, 1, N) {\r\n        in >> C[i] >> S[i];\r\n        FOR (c, 0, 1)\r\n            sum[i][c] += sum[i - 1][c];\r\n        sum[i][1 - C[i]] += S[i];\r\n    }\r\n    int cnt, K, T;\r\n    in >> cnt;\r\n    FOR (i, 1, cnt)\r\n        in >> K >> T, out << work(K, T) << \"\\n\";\r\n\r\n    in.close(), out.close();\r\n    return 0;\r\n}\r\n==\r\n\r\nh3(#problema-5). Problema 5: \'Otilia\':problema/otilia  (.campion)\r\n\r\nbq. Otilia şi Burbucel au o grămadă de $N$ pietre şi vor juca un joc cu următoarele trei reguli: 1. Primul jucător are voie să ia din gramadă cel mult $K$ piese; 2. Cu excepţia primei mutări, fiecare jucător are voie să ia maxim $P * t$ pietre, unde $t$ este numărul de pietre care au fost substituite din grămadă la mutarea precedentă; 3. Pierde cel care mută ultimul (cel care ia ultimele pietre din grămadă).\r\nCerinţă: Se dau $M$ jocuri prin numerele $N$, $K$ şi $P$. Se cere să se determină dacă Otilia va câştiga fiecare din jocuri sau nu.\r\nRestricţii: $1 &le; M &le; 30 000$, $1 &le; N &le; 5 000 000$, $1 &le; K &le; N$, $1 &le; P &le; 10$.\r\n\r\nh3. Soluţie:\r\n\r\nProblema se rezolvă prin programare dinamică. Soluţia se bazează pe observaţia de mai jos. Considerăm $P$-ul fixat şi notăm cu $stare(X, Y)$ poziţia de start în care avem $X$ pietre şi numărul maxim de pietre care se pot lua la prima mutare este $Y$.\r\n\r\n_Observaţia 1_: „Dacă există strategie sigură de câştig pentru $stare(X, Y)$ atunci există şi pentru orice $stare(X, T)$ cu $T &ge; Y$.” \r\n\r\nDe ce? Pentru că orice mutare validă pentru $stare(X, Y)$ este validă şi pentru $stare(X, T)$. Având această observaţie notăm cu $MinY[X] = Y$, $Y$ minim astfel încât avem strategie de câştig pentru $stare(X, Y)$.\r\n\r\n_Observaţia 2_: „{$stare(X, Y)$} este pierzătoare dacă şi numai dacă $Y < MinY[X]$.” \r\n\r\nAceasta reiese din definiţia lui $MinY[X]$.\r\n\r\n$MinY[X]$ se calculează după următoarea recurenţă, care rezultă din regulile jocului: \r\n\r\n* $MinY[X]$ este cel mai mic $i$ pentru care avem $MinY[X - i] > P * i$.\r\n\r\nDe aici se naşte prima soluţie, care este implementarea directă a recurenţei. Deşi complexitatea acesteia pare a fi $O(N^2^)$ ea se comportă foarte bine pentru $N &le; 500 000$. Aşadar, această soluţie acoperă aproximativ $50%$ din testele de intrare. Printr-o rafinare a acestei soluţii se obţine un algoritm de complexitate $O(N)$. Rafinarea se bazează pe: \r\n\r\n_Observaţia 3_: „Să presupunem că dorim să calculăm $MinY[X]$. Facem următoarea afirmaţie: orice poziţie _rea_ pentru $X$ (în care dacă mutăm pierdem) va fi _rea_ şi pentru $X + 1$.”\r\n\r\nAcest lucru este simplu de observat dacă privim ce înseamnă că o poziţie $Q$ e rea pentru $X$: \r\n\r\n* $MinY[Q] > X - Q$, pentru $X$;\r\n* $MinY[Q] > X - Q + 1$, pentru $X + 1$.\r\n\r\nEste evident că prima relaţie o implică pe cea de-a doua. În momentul acesta se poate construi următorul algoritm: având lista de poziţii care pot fi bune pentru $X$ (sortată descrescător) o căutăm pe cea mai mare ca valoare care este într-adevăr bună. În principiu, scoatem din capul listei poziţiile rele până când dăm de o poziţie bună. La listă se va adăuga şi $X$ şi se va trece la pasul următor. Operaţiile algoritmului sunt chiar operaţiile asupra unui deque.\r\n\r\nh3(#problema-6). Problema 6: \'Bcrc\':problema/bcrc (Stelele Informaticii 2006)\r\n\r\nbq. Se consideră $N$ camere, numerotate de la $1$ la $N$, aşezate în cerc. Iniţial (la momentul de timp 0), ne aflăm în camera $1$. În fiecare moment de timp, putem alege să rămânem în camera în care ne aflăm sau să ne deplasăm într-o cameră vecină într-o unitate de timp. Se dă o listă de $M$ cutii ce conţin bomboane prin $T$, $C$ şi $B$: cutia apare la momentul $T$ în camera $C$ şi conţine $B$ bomboane. Cutia va dispărea la momentul $T + 1$.\r\nCerinţă: Cunoscând numărul de camere din labirint şi momentele de timp la care apar cutiile cu bomboane, determinaţi care este numărul maxim de bomboane pe care le putem culege.\r\nRestricţii: $3 &le; N &le; 2 048$, $0 &le; M &le; 50 000$, $1 &le; T &le; 1 000 000 000$, $1 &le; C &le; N$, $1 &le; B &le; 9 999$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia foloseşte metoda programării dinamice.\r\n\r\nO stare se reprezintă prin camera în care ne aflăm şi momentul de timp. Fie $bst[i][j]$ numărul maxim de bomboane culese până în momentul $i$ când ne găsim în camera $j$. O observaţie evidentă este că $bst[i][j]$ se poate modifica doar în momentele în care apar cutiile. Prin urmare, vom considera momentele de timp când apar cutiile, momente ce sunt în număr de $M$, $bst[i][j]$ însemnând numărul maxim de bomboane culese ştiind că ne aflăm în camera $j$ unde am cules cutia $i$. De cine depinde această stare? Ştim că $bst[i - 1][1 ... N]$ a fost deja calculat în mod optim. Să notăm cu $T$ diferenţa de timp dintre momentele la care apare cutia $i$ şi cutia $i - 1$. În acest moment $i$ şi cameră $j$ putem ajunge din maxim $T$ camere spre stânga sau spre dreapta, întrucât fiecare deplasare între două camere costă o unitate de timp. De unde deducem că:\r\n\r\n* $bst[i][j] = Min { bst[i - 1][j - T], bst[i - 1][j - T + 1], ..., bst[i - 1][j], ..., bst[i - 1][j + T - 1], bst[i - 1][j + T] }$.\r\n\r\nMetoda directă şi, aparent eficientă, constă în folosirea unui arbore de intervale pentru aflarea acestui minim. Însă, intervalul se deplasează, dacă vom considera indicii $j$ în ordine $1$, $2$, $3$, ... constant spre dreapta, fiind reprezentat de un şir de valori de lungime constantă în care noile elemente se introduc prin dreapta şi altele se elimină prin stânga. Vom folosi un deque de lungime $2 * T$ şi vom proceda ca în problemele precedente, eliminând poziţiile care nu sunt candidate la soluţie. Mai jos este o reprezentare grafică a acestei explicaţii.\r\n\r\np=. !deque-si-aplicatii?bcrc.png 40%!\r\n\r\nComplexitatea finală: $O(M * N)$.\r\n\r\nh3(#problema-7). Problema 7: \'Cut the Sequence\':http://acm.pku.edu.cn/JudgeOnline/problem?id=3017 (PKU) \r\n\r\nbq. Se dă o secvenţă $S$ de numere întregi de lungime $N$. Va trebui să se împartă secvenţa în mai multe subsecvenţe astfel încât suma valorilor din fiecare parte să nu depăşească un număr întreg $M$ dat, iar dacă însumăm maximul din fiecare subsecvenţă să obţinem o sumă cât mai mică.\r\nRestricţii: $0 &lt; N &le; 100 000$, $0 &le; S{~i~} &le; 1 000 000$.\r\n\r\nh3. Soluţie:\r\n\r\nVoi face un desen pentru explicaţii. :)\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    // S[] şirul iniţial de numere iar N lungimea sa\r\n    // (last, i] este intervalul de lungime maximă care se termină în i a cărui sumă nu depăşeşte M\r\n    sum  = 0;\r\n    last = 0;\r\n    // indicii head si tail ai dequeului\r\n    deque[head = tail = 1] = 0;\r\n    pentru i = 1, N execută\r\n        sum += S[i];\r\n        temp = bst[ deque[tail] ];\r\n        cât timp (head <= tail) şi S[ deque[tail] ] <= S[i] execută\r\n            temp = Min(temp, iMin[tail]);\r\n            tail --;\r\n        sfcâttimp\r\n        // adaug poziţia i la deque\r\n        tail ++;\r\n        deque[tail] = i;\r\n        // actualizez iMin[]\r\n        iMin[tail]  = temp;\r\n        // actualizez T[]\r\n        update(T, tail, iMin[tail] + S[i]);\r\n\r\n        cât timp (head <= tail) şi (sum > M) execută\r\n            sum -= S[last];\r\n            dacă (deque[head] == last) atunci\r\n                head ++;\r\n            sfdacă\r\n            last ++;\r\n        sfcâttimp\r\n        // actualizez iMin[]\r\n        iMin[head] = query(bst, last - 1, deque[head] - 1);\r\n        // actualizez T[]\r\n        update(T, head, iMin[head] + S[ deque[head] ]);\r\n        // reţin optimul pentru poziţia curentă\r\n        bst[i] = query(T, head, tail);\r\n    sfpentru\r\n    scrie bst[N];\r\nSfârşit.\r\n==\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nFilozofia din spatele structurii de deque devine utilă, de obicei, în părţile finale ale rezolvării unei probleme. Însă, ce pot spune cu certitudine este că această structură de date pe cât este de simplă pe atât este de eficientă.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\nÎnţelegerea profundă a acestei structuri simple nu se poate realiza decât prin rezolvarea a cât mai multe probleme. Succes!\r\n\r\n* \'Deque\':problema/deque, _Arhiva educaţională_\r\n* \'Secvenţă\':problema/secventa\r\n* \'Secvenţă 3\':problema/secv3\r\n* \'Secvenţă 4\':problema/secv4\r\n* \'Vila 2\':problema/vila2, _.campion_\r\n* \'Sum 2\':problema/sum2, _Stelele Informaticii 2003_\r\n* \'Drept 2\':problema/drept2, _Lotul Naţional de Informatică, 2006_\r\n* \'Copaci 2\':problema/copaci2, _.campion_\r\n* \'Brânză\':problema/branza\r\n* \'Struţi\':problema/struti\r\n* \'Trompetă\':problema/trompeta\r\n* \'Buline\':problema/buline\r\n* \'Balans\':problema/balans\r\n* \'Gard\':problema/gard, _ONI 2002_\r\n* \'Ghiozdan\':problema/ghiozdan\r\n* \'Munte4\':problema/munte4, _Lotul Naţional de Informatică, 2005_\r\n* \'Cover\':problema/cover, _ONI 2007, Baraj_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Cosmin Negruşeri, \"_Probleme cu secvenţe_\":probleme-cu-secvente\r\n# Dana Lica, \"_Arbori de intervale şi aplicaţii în geometria computaţională_\":arbori-de-intervale\r\n# \'C++ Reference, _deque_\':http://www.cplusplus.com/reference/stl/deque/',3146,'public',NULL,NULL),('deque-si-aplicatii','Deque și aplicații','2009-01-22 22:28:12','2009-02-04 14:51:03','h1. Deque şi aplicaţii\r\n\r\n(Categoria _Structuri de date_, Autor _Xulescu_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'Introducere\':deque-si-aplicatii#introducere\r\n* \'Aplicaţii\':deque-si-aplicatii#aplicatii\r\n** \'Problema 1: Book Pile &#40;SGU&#41;\':deque-si-aplicatii#problema-1\r\n** \'Problema 2: Vila 2 &#40;.campion&#41;\':deque-si-aplicatii#problema-2\r\n** \'Problema 3: Şir\':deque-si-aplicatii#problema-3\r\n** \'Problema 4: Trans &#40;ONI 2004&#41;\':deque-si-aplicatii#problema-4\r\n** \'Problema 5: Otilia &#40;.campion&#41;\':deque-si-aplicatii#problema-5\r\n** \'Problema 6: Bcrc &#40;Stelele Informaticii 2006&#41;\':deque-si-aplicatii#problema-6\r\n** \'Problema 7: Cut the Sequence &#40;PKU&#41;\':deque-si-aplicatii#problema-7\r\n* \'Concluzii\':deque-si-aplicatii#concluzii\r\n* \'Probleme suplimentare\':deque-si-aplicatii#probleme-suplimentare\r\n* \'Bibliografie\':deque-si-aplicatii#bibliografie\r\n\r\nÎn acest articol voi prezenta o structură de date de tip listă numită _deque_. Simplitatea acestei structuri poate nu are multe de spus şi din acest motiv am prezentat şi o serie de aplicaţii care vor arăta neaşteptata sa utilitate şi apariţie în locurile unde am fi crezut că nu se mai poate face nimic pentru a reduce complexitatea.\r\n\r\nh2(#introducere). Introducere\r\n\r\n_Dequeul_ (pronunţat de obicei _deck_) poate fi privit ca o colecţie de tip listă ce are două capete prin care se şterg sau inserează noi elemente. În literatura de specialitate, aceste capete se numesc _head_ şi _tail_, iar dequeul mai este recunoscut şi ca fiind o coadă cu două capete _(double ended queue)_.\r\n\r\nUn deque poate fi implementat folosind liste dublu înlănţuite ori cu un vector static când se cunoaşte numărul elementelor din colecţie. Ce trebuie reţinut este că limbajul C++ pune la dispoziţia utilizatorilor prin intermediul headerului _#include <deque>_ containerul \'_std::deque_\':http://www.cplusplus.com/reference/stl/deque/.\r\n\r\nh3(#operatii). Operaţii\r\n\r\nMai jos sunt enumerate operaţiile care pot fi efectuate asupra unui deque împreună cu corespondentul lor în limbajul C++:\r\n\r\n* _front()_:	    întoarce primul element;\r\n* _back()_:	    întoarce ultimul element;\r\n* _push_front()_: inserează un element în faţă;\r\n* _push_back()_:  inserează un element în spate;\r\n* _pop_front()_:  scoate primul element;\r\n* _pop_back()_:   scoate ultimul element;\r\n* _empty()_:      întoarce _true_ dacă dequel este gol.\r\n\r\np=. !deque-si-aplicatii?new_deque.png 75%!\r\n\r\nToate aceste operaţii se execută în timp $O(1)$ \'amortizat\':http://en.wikipedia.org/wiki/Amortized_analysis. Pentru un plus de viteză va trebui să folosim un vector static cu dimensiunea egală cu numărul maxim de elemente ce pot trece prin deque, iar operaţiile implementate „de mână”, cu doi indecşi ce indică către head şi tail. Însă, în majoritatea aplicaţiilor limita de timp permite folosirea lejerităţii şi siguranţei clasei _std::deque_.\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\nÎn multe aplicaţii unde soluţiile parţiale se reprezintă sub forma unui şir continuu de valori care permite inserarea şi ştergerea doar pe la capete (în general inserări pe la un capăt şi ştergeri pe la celălalt) se poate folosi un deque. Să urmărim în continuare cazuri concrete în care simplitatea unui deque duce la soluţii de multe ori optime şi implementări foarte scurte şi clare.\r\n\r\nh2(#problema-1). Problema 1: \'Book Pile\':http://acm.sgu.ru/problem.php?contest=0&problem=271 (SGU)\r\n\r\nbq. Se dau $N$ cărţi aşezate una deasupra celeilalte asupra cărora se vor efecta $M$ operaţii de două tipuri: 1. $ADD${$(nume)$} : se adaugă cartea $nume$ deasupra celorlalte; 2. $ROTATE$ : primele $K$ cărţi de deasupra se rotesc (dacă sunt mai puţin de $K$ cărţi atunci se vor roti toate). Se cere să se afişeze cărţile în ordine, prima fiind cea de deasupra, după efectuarea celor $M$ operaţii.\r\nRestricţii: $0 &le; N, K &le; 40 000$, $0 &le; M &le; 100 000$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se poate deduce urmând paşii următori. Să presupunem că avem cărţile $A B C$ iniţial şi $K = 3$. Dacă îl vom adăuga pe $D$, atunci nu vor rămâne importante decât cărţile $D A B$, deoarece, dacă vom roti ulterior ultimele $K$ cărţi, $C$ nu va mai fi niciodată considerat, cărţile fiind doar adăugate, iar o dată ce o carte iese din „top {$K$}” cărţi nu va mai fi posibil să i se schimbe poziţia pe raft. Să rotim acum „top {$K$}” cărţi. Noua ordine va fi $B A D$ şi $C$ pe raft la loc sigur. Dacă îl vom adăuga pe $E$, topul se va schimba în $E B A$ iar pe raft, în mod sigur vor fi, în această ordine, $D C$. Proprietatea celor $K$ cărţi din vârf este: o secvenţă continuă de elemente, la care se adaugă noi elemente sau se elimină dintre acestea numai pe la _capete_. Aceste capete sunt chiar head şi tail ale unui deque.\r\n\r\np=. !deque-si-aplicatii?bookpile.png 40%!\r\n\r\nLa final, când se vor termina operaţiile, cărţilor de pe raft li se vor adăuga cele din deque şi se va afişa soluţia. În cazul presupus, soluţia va fi: $E B A D C$.\r\n\r\nÎntrucât operaţiile unui deque se execută în $O(1)$ amortizat, soluţia are complexitatea $O(N + M)$.\r\n\r\nh2(#problema-2). Problema 2: \'Vila 2\':problema/vila2 (.campion)\r\n\r\nbq. Se dă un şir $S$ de $N$ numere întregi şi un $D$ număr natural. Se cere să determine diferenţa maximă dintre oricare două numere din şir cu proprietatea că diferenţa indicilor nu depăşeşte $D$.\r\nRestricţii: $2 &le; N &le; 100 000$, $1 &le; D &le; N/2$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia nu e greu de intuit. Considerăm indicii succesiv $1$, $2$, .. , $N$. Va trebuie ca pentru fiecare secvenţă $(i - D, i]$ să determinăm valoarea maximă şi pe cea minimă, iar diferenţa lor să o comparăm cu rezultatul obţinut până în acel moment. Pentru fixarea ideilor, să urmărim cum putem determina valoarea maximă din fiecare secvenţă $(i - D, i]$.\r\n\r\n_Observaţie_: „Fie $i{~1~}$, $i{~2~}$ doi indici din astfel încât $i - D &lt; i{~1~} &lt; i{~2~} &le; i$.\r\n\r\n# Dacă $S[i{~1~}] &lt; S[i{~2~}]$ atunci, cât timp cei doi indici vor fi în intervalul $(i - D, i]$, valoarea de pe poziţia $i{~2~}$ va fi întotdeauna preferată valorii de pe poziţiei $i{~1~}$. Când unul din indici nu va mai fi în acest interval, cel expediat va fi $i{~1~}$ şi, astfel, $i{~2~}$ rămâne în continuare preferat.\r\n# Dacă $S[i{~1~}] &gt; S[i{~2~}]$ atunci îl vom păstra pe $i{~2~}$, deoarece este candidat la maxim în viitor.”\r\n\r\nCu această observaţie deducem că într-o secvenţă $(i - D, i]$ vom avea un şir $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$ astfel încât $S[i{~1~}] &gt; S[i{~2~}] &gt; ... &gt; S[i{~K~}]$. Când vom avansa la secvenţa următoare, $(i - D + 1, i + 1]$, vom şterge din indici $i{~1~}$, $i{~2~}$... atâta timp cât nu se găsesc în intervalul curent şi vom şterge din poziţiile $i{~K~}$, $i{~K-1~}$... cât timp $S[i + 1] &gt; S[i{~K~}]$, $S[i + 1] &gt; S[i{~K-1~}]$... adică cât timp se îndeplineşte primul punct din observaţia anterioară.\r\n\r\nŞirul $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$ este continuu iar operaţiile se efectuează doar pe la cele două capete. Rezultă că şirul poate fi implementat cu ajutorul unui deque.\r\n\r\nPentru $S[] = {5, 9, 4, 7, 4, 1}$ şi $D = 3$ obţinem următoarele stări ale unui deque:\r\n\r\np=. !deque-si-aplicatii?vila2.png 60%!\r\n\r\nCum fiecare indice din $1$, $2$, .., $N$ trece cel mult o dată prin deque complexitatea finală este $O(N)$ amortizat.\r\n\r\nh2(#problema-3). Problema 3: \'Şir\':problema/sir\r\n\r\nbq. Se dă un şir $S$ de numere întregi de lungime $N$. Se cere să se găsească secvenţa de lungime maximă cuprinsă între $X$ şi $Y$ astfel încât $MAX - MIN &le; Z$, unde $MAX$ este maximul dintre toate numerele întregi din secvenţă iar $MIN$ minimul dintre acestea. Secvenţa soluţie va fi cea cu poziţia de început maximă dintre toate secvenţele de lungime maximă.\r\nRestricţii: $3 &le; N &le; 100 000$, $1 &le; X &le; Y &le; N$, $0 &le; Z &le; 30 000$.\r\n\r\nh3. Soluţie\r\n\r\nVoi prezenta mai jos o rafinare a soluţiei în trei paşi.\r\n\r\nPrima rezolvare se găseşte uşor, deoarece nu facem decât să urmărim textul: pentru fiecare poziţie $i$ fixată ({$i$} ia valorile $1$, $2$, .., $N$ succesiv) vom determina pentru aceasta secvenţa cerută, adică vom plimba un $j$ între poziţiile $i - Y$ şi $i - X$. Pentru un interval $(j, i]$ vom determina $MAX$ şi $MIN$ în $O(log{~2~}N)$ cu un arbore de intervale, iar daca diferenţa dintre acestea nu depăşeşte $Z$ vom compara cu soluţia finală. Complexitatea finală va fi $O(N * (Y - X) * log{~2~}Y)$.\r\n\r\nSă presupunem că pentru poziţia curentă $i$, l-am găsit pe $j$ cuprins între $i - Y$ şi $i - X$ care îndeplineşte optimul. Ce proprietăţi are $j$?\r\n\r\n* $i - Y &le; j &le; i - X$ şi $MAX - MIN &le; Z$;\r\n* dacă îl incrementăm pe $j$ la $j + 1$ atunci dacă $j &le; i - X$ cu siguranţă $MAX - MIN &le; Z$ şi astfel soluţia va fi mai scurtă;\r\n* dacă îl decrementăm pe $j$, atunci ori $j < i - Y$ ori $MAX - MIN > Z$;\r\n* dacă îl incrementăm pe $i$ la $i + 1$, atunci se poate întâmpla ca $j < i - Y$; cum $MAX$ nu poate decât să crească, iar $MIN$ decât să scadă, se mai poate de asemenea întâmpla ca $MAX - MIN > Z$.\r\n\r\nDatorită proprietăţilor de mai sus, când trecem de la $i$ la $i + 1$, valoarea lui $j$ nu poate decât să crească cât timp $j < i - Y$ sau $MAX - MIN > Z$ şi $j$ nu a depăşit poziţia $i - X$. Pentru determinarea lui $MAX$, respectiv lui $MIN$ se poate folosi un arbore de intervale. Complexitatea finală va fi $O(N * log{~2~}(Y))$.\r\n\r\nCu cei doi indici $i$ şi $j$ vom accesa fiecare element din cele $N$ de cel mult $2$ ori, o dată cu $i$ şi o dată cu $j$. Să vedem cum putem îmbunătăţi complexitatea $O(log{~2~}Y)$ pentru determinarea maximului şi minimului.\r\n\r\nPentru fixarea ideilor să urmărim cum îl calculăm pe $MAX$. Observaţia care ne ajută în multe probleme pentru reducerea complexităţii de la $O(log{~2~}N)$ la $O(1)$ amortizat este următoarea: \r\n\r\n_Observaţie_: „Fixăm $i{~1~}$ şi $i{~2~}$ astfel încât $j < i{~1~} < i{~2~} &le; i$. Atunci, dacă $S[i{~2~}] > S[i{~1~}]$ poziţia $i{~2~}$ va fi întotdeauna mai importantă decât poziţia $i{~1~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ şi $i{~2~}$ nu vor mai fi ambele în intervalul $(j, i]$, poziţia eliminată va fi {$i{~1~}$}. Dacă însă $S[i{~1~}] > S[i{~2~}]$, atunci poziţia $i{~1~}$ va umbri poziţia $i{~2~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ va fi eliminat, atunci e posibil ca $i{~2~}$ să fie un candidat la $MAX$ dintre restul elementelor de la dreapta sa. În acest caz, nu putem afirma nimic şi vom păstra cele două poziţii.”\r\n\r\nRezultă din această observaţie că în intervalul $(j, i]$ poziţiile importante vor fi $j < i{~1~} < i{~2~} < .. < i{~k~} <= i$ astfel încât $S[i{~1~}] > S[i{~2~}] > .. > S[i{~k~}]$. Astfel, $MAX$ va fi $S[i{~1~}]$. Când îl vom incrementa pe $i$ la $i + 1$ vom şterge din poziţiile $i{~k~}$, $i{~k-1~}$, ... atâta timp cât $S[i + 1]$ este mai important, adică mai mare decât valorile de pe aceste poziţii, şi vom şterge $i{~1~}$, $i{~2~}$, ... atâta timp cât aceste poziţii sunt mai mici sau egale decât $j\'$. Indicele $j\'$ este noul optim pentru poziţia $i + 1$. Proprietatea şirului de poziţii $i{~1~}, i{~2~}, .., i{~k~}$ este că se reprezintă ca un şir continuu de numere care permite inserarea elementelor prin dreapta şi ştergerea prin stânga, adică se adaugă elemente la tail şi se şterg elemente de la head. Îl putem deci reprezenta printr-un deque. Complexitatea $O(1)$ amortizat provine de la faptul că fiecare poziţie dintre cele $N$ nu trece decât o singură dată prin deque şi este şters tot cel mult o singură dată. \r\n\r\nÎn practică, pseudocodul poate arăta în felul următor:\r\n\r\n== code(cpp) |\r\n// S şirul de numere iniţial şi N lungimea sa\r\n\r\nSubalgoritmul push_in(deque, întreg p, funcţia fct) este:\r\n    cât timp (!deque.empty() şi fct(S[p], S[deque.back()])) execută\r\n        deque.pop_back();\r\n    deque.push_back(p);\r\nSfârşit;\r\n\r\nFuncţia query(deque, întreg j) este:\r\n    cât timp (!deque.empty() şi deque.front() <= j) execută\r\n        deque.pop_front();\r\n    return S[deque.front()];\r\nSfârşit;\r\n\r\nAlgoritmul este:\r\n    lg = 0;\r\n    pentru i = 1, N execută\r\n        // funcţia min(a, b) întoarce true dacă a < b\r\n        inserează(min_deq, i, min);\r\n        // funcţia max(a, b) întoarce true dacă a > b\r\n        inserează(max_deq, i, max);\r\n        cât timp ((j < i - Y sau query(max_deq, j) - query(min_deq, j) > Z) şi j < i - X) execută\r\n            j = j + 1;\r\n        // (j, i] este intervalul candidat la soluţia optimă pentru poziţia i\r\n        dacă (j <= i - X) şi (query(max_deq, j) - query(min_deq, j) <= Z) atunci\r\n            dacă (lg >= i - j) atunci\r\n                lg = i - j, start = j + 1, stop = i;\r\n    sfârşit_pentru\r\n\r\n    dacă (lg > 0) atunci\r\n        scrie lg, start, stop;\r\n    altfel\r\n        scrie -1;\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală va fi $O(N)$.\r\n\r\nh2(#problema-4). Problema 4: \'Trans\':problema/trans (ONI 2004)\r\n\r\nbq. Se dau $N$ blocuri de piatră, de culoare albă sau neagră aşezate în ordinea $1$, $2$,.., $N$. Blocurile de piatră trebuie să fie transportate în ordinea în care sunt, iar pentru aceasta va trebui închiriat un camion. Se mai dau $Q$ tipuri de camioane. Camionul de tipul $i (1 &le; i &le; Q)$ poate transporta maxim $K{~i~}$ blocuri de piatră la un moment dat şi pentru un transport se percepe taxa $T{~i~}$. Se impune condiţia ca toate blocurile de piatră plasate în camion la un transport sa aibă aceeaşi culoare. Aşadar, pentru a fi transportate toate blocurile, se va alege un camion de un anumit tip, iar camionul va efectua unul sau mai multe transporturi. Pentru a micşora suma totală plătită, există posibilitatea de a schimba culoarea oricărui bloc de piatră (din alb în negru sau din negru în alb); pentru fiecare bloc $i (1 &le; i &le; N)$ se cunoaşte suma $S{~i~}$ ce trebuie plătită pentru a-i schimba culoarea $C{~i~}$.\r\nCerinţă: Pentru fiecare dintre cele $Q$ tipuri de camioane, determinaţi suma minimă plătită pentru a transporta toate cele $N$ blocuri.\r\nRestricţii: $1 &le; N &le; 16 000$, $1 &le; Q &le; 100$, $1 &le; K{~i~} &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se bazează pe găsirea unei formule de recurenţă ce respectă principiul optimalităţii al metodei programării dinamice.\r\n\r\nPentru început, fixăm un camion dintre cele $Q$. Fie $K$ numărul maxim de pietre pe care acesta le poate transporta şi $T$ taxa percepută. Notăm $sum[i][&#99;]$ costul pentru a schimba toate pietrele $1$, $2$, .., $i$ în culoarea $c$ ({$c = 0$} pentru alb şi $c = 1$ pentru negru). În $sum[i][&#99;]$ se vor aduna toate valorile $S[j]$, cu $j &le; i$ pentru care $C[j] = 1 - c$. \r\n\r\nÎn continuare, considerăm $bst[i][&#99;]$ costul minim pentru a transporta pietrele $1$, $2$, .., $i$, iar ultimul transport conţine pietre de culoare $c$. Întrucât nu putem transporta mai mult de $K$ pietre, $bst[i][&#99;]$ depinde doar de poziţiile $i - K$, $i - K + 1$, ..., $i - 1$. Cunoaştem că ultimul camion va transporta o secvenţă continuă de pietre începând de la o poziţie $j + 1$ până la poziţia $i$, unde $i - K &le; j &le; i - 1$. Astfel, pentru fiecare $j$ în intervalul precedent, costul va fi $Min(bst[j][&#48;], bst[j][&#49;])$ (transportăm primele j pietre cât mai ieftin) adunat cu $sum[i][&#99;] - sum[j][&#99;]$ (costul transformării pietrelor $j + 1$, .., $i$ în culoarea $c$) şi plus taxa $T$. Rezultă recurenţa:\r\n\r\n* $bst[i][&#99;] = Min{ Min(bst[j][&#48;], bst[j][&#49;]) + sum[i][&#99;] - sum[j][&#99;] } + T$, unde $i - K &le; j &le; i - 1$.\r\n\r\nDacă ne vom opri aici, complexitatea soluţiei va fi $O(Q * N^2^)$.\r\n\r\nRelaţia de recurenţă poate fi îmbunătăţită. Observăm că pentru poziţia $i$, $sum[i][&#99;]$ este o valoare constantă, ca şi $T$. Astfel, deducem următoarea relaţie de recurenţă:\r\n\r\n* $bst[i][&#99;] = Min{ Min(bst[j][&#48;], bst[j][&#49;]) - sum[j][&#99;] } + sum[i][&#99;] + T$, unde $i - K &le; j &le; i - 1$.\r\n\r\nNotez în continuare, pentru uşurinţă în scriere, $X[j][&#99;] = Min(bst[j][&#48;], bst[j][&#49;]) - sum[j][&#99;]$. Să fixăm doi indici $i{~1~}$ şi $i{~2~}$, astfel încât $i - K &le; $i{~1~}$ < $i{~2~}$ &le; i - 1$. Dacă $X[i{~1~}][&#99;] > X[i{~2~}][&#99;]$ atunci, întotdeauna poziţia $i{~2~}$ va fi preferată poziţiei $i{~1~}$. Când cele două nu se vor mai afla în intervalul $[i - K, i - 1]$, poziţia eliminată va fi poziţia $i{~1~}$. Dacă $X[i{~1~}][&#99;] < X[i{~2~}][&#99;]$, atunci nu putem decide care poziţie este mai bună în viitor, aşa că le vom păstra pe ambele. Rezultă mai departe că în intervalul $[i - K, i - 1]$ vom avea o serie de indecşi candidaţi la minim $i - K &le; i{~1~} < i{~2~} < .. < i{~n~} &le; i - 1$ astfel încât $X[i{~1~}][&#99;] < X[i{~2~}][&#99;] <  .. < X[i{~n~}][&#99;]$. Mai departe, găsim $bst[i][&#99;]$ ca fiind $X[i{~1~}][&#99;] + sum[i][&#99;] + T$. Urmează să îl introducem şi pe $X[i][&#99;]$, el fiind egal cu $Min(bst[i][&#48;], bst[i][&#49;]) - sum[i][&#99;]$, în şirul de indecşi de mai sus. Acest lucru se va face în felul următor: se vor elimina din $i{~n~}$, $i{~n-1~}$, ... atâta timp cât $X[$i{~n~}$][&#99;] > X[i][&#99;]$, $X[$i{~n-1~}$][&#99;] > X[i][&#99;]$, ... adică atâta timp cât poziţia $i$ este preferată lui $i{~n~}$, $i{~n-1~}$... Fiind la poziţia $i + 1$, intervalul se va transforma în $[i - K + 1, i]$, aşadar, vom mai elimina din primii indici $i{~1~}$, $i{~2~}$,... atâta timp cât $i{~1~} < i - K + 1$, $i{~2~} < i - K + 1$...\r\n\r\nDupă cum am arătat şi la problema precedentă, acest şir de indecşi $i{~1~}$, $i{~2~}$, .., $i{~n~}$ are proprietatea că este un şir continuu de numere care admite inserări prin dreapta (tail) şi ştergeri prin stânga (head). Şir ce poate fi reprezentat printr-un deque. Cum fiecare index dintre $1$, $2$, .., $N$ va trece o singură dată prin deque şi va fi şters cel mult o dată, complexitatea soluţiei în acest caz va fi $O(Q * N)$.\r\n\r\nÎn practică, programul este scurt, clar şi foarte eficient:\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\n#include <vector>\r\n#include <deque>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\nconst char iname[] = \"trans.in\";\r\nconst char oname[] = \"trans.out\";\r\n\r\n#define MAXN  16005\r\n#define Min(a, b) ((a) < (b) ? (a) : (b))\r\n#define FOR(i, a, b)  for (int i = (a); i <= (b); ++ i)\r\n\r\nint C[MAXN], S[MAXN], bst[MAXN][2], sum[MAXN][2], N;\r\n\r\nvoid insert(deque < pair <int, int> >& deq, const pair <int, int>& p) {\r\n    while (!deq.empty() && deq.back().second > p.second)\r\n        deq.pop_back();\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque < pair <int, int> >& deq, const int idx) {\r\n    while (deq.front().first < idx)\r\n        deq.pop_front();\r\n    return deq.front().second;\r\n}\r\n\r\nint work(const int K, const int T) {\r\n    deque < pair <int, int> > deq[2];       // pair (idx, value)\r\n    FOR (c, 0, 1)\r\n        insert(deq[c], pair <int, int>(0, 0));\r\n    FOR (i, 1, N) {   // obiectul i\r\n        FOR (c, 0, 1) // culoare\r\n            bst[i][c] = query(deq[c], i - K) + sum[i][c] + T;\r\n        FOR (c, 0, 1)\r\n            insert(deq[c], pair <int, int>(i, Min(bst[i][0], bst[i][1]) - sum[i][c]));\r\n    }\r\n    return Min(bst[N][0], bst[N][1]);\r\n}\r\n\r\nint main(void)\r\n{\r\n    ifstream in(iname);  ofstream out(oname);\r\n    in >> N;\r\n    FOR (i, 1, N) {\r\n        in >> C[i] >> S[i];\r\n        FOR (c, 0, 1)\r\n            sum[i][c] += sum[i - 1][c];\r\n        sum[i][1 - C[i]] += S[i];\r\n    }\r\n    int cnt, K, T;\r\n    in >> cnt;\r\n    FOR (i, 1, cnt)\r\n        in >> K >> T, out << work(K, T) << \"\\n\";\r\n\r\n    in.close(), out.close();\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#problema-5). Problema 5: \'Otilia\':problema/otilia  (.campion)\r\n\r\nbq. Otilia şi Burbucel au o grămadă de $N$ pietre şi vor juca un joc cu următoarele trei reguli: 1. Primul jucător are voie să ia din gramadă cel mult $K$ piese; 2. Cu excepţia primei mutări, fiecare jucător are voie să ia maxim $P * t$ pietre, unde $t$ este numărul de pietre care au fost substituite din grămadă la mutarea precedentă; 3. Pierde cel care mută ultimul (cel care ia ultimele pietre din grămadă).\r\nCerinţă: Se dau $M$ jocuri prin numerele $N$, $K$ şi $P$. Se cere să se determină dacă Otilia va câştiga fiecare din jocuri sau nu.\r\nRestricţii: $1 &le; M &le; 30 000$, $1 &le; N &le; 5 000 000$, $1 &le; K &le; N$, $1 &le; P &le; 10$.\r\n\r\nh3. Soluţie:\r\n\r\nProblema se rezolvă prin programare dinamică. Soluţia se bazează pe observaţia de mai jos. Considerăm $P$-ul fixat şi notăm cu $stare(X, Y)$ poziţia de start în care avem $X$ pietre şi numărul maxim de pietre care se pot lua la prima mutare este $Y$.\r\n\r\n_Observaţia 1_: „Dacă există strategie sigură de câştig pentru $stare(X, Y)$ atunci există şi pentru orice $stare(X, T)$ cu $T &ge; Y$.” \r\n\r\nDe ce? Pentru că orice mutare validă pentru $stare(X, Y)$ este validă şi pentru $stare(X, T)$. Având această observaţie notăm cu $MinY[X] = Y$, $Y$ minim astfel încât avem strategie de câştig pentru $stare(X, Y)$.\r\n\r\n_Observaţia 2_: „{$stare(X, Y)$} este pierzătoare dacă şi numai dacă $Y < MinY[X]$.” \r\n\r\nAceasta reiese din definiţia lui $MinY[X]$.\r\n\r\n$MinY[X]$ se calculează după următoarea recurenţă, care rezultă din regulile jocului: \r\n\r\n* $MinY[X]$ este cel mai mic $i$ pentru care avem $MinY[X - i] > P * i$.\r\n\r\nDe aici se naşte prima soluţie, care este implementarea directă a recurenţei. Deşi complexitatea acesteia pare a fi $O(N^2^)$ ea se comportă foarte bine pentru $N &le; 500 000$. Aşadar, această soluţie acoperă aproximativ $50%$ din testele de intrare. Printr-o rafinare a acestei soluţii se obţine un algoritm de complexitate $O(N)$. Rafinarea se bazează pe: \r\n\r\n_Observaţia 3_: „Să presupunem că dorim să calculăm $MinY[X]$. Facem următoarea afirmaţie: orice poziţie _rea_ pentru $X$ (în care dacă mutăm pierdem) va fi _rea_ şi pentru $X + 1$.”\r\n\r\nAcest lucru este simplu de observat dacă privim ce înseamnă că o poziţie $Q$ e rea pentru $X$: \r\n\r\n* $MinY[Q] > X - Q$, pentru $X$;\r\n* $MinY[Q] > X - Q + 1$, pentru $X + 1$.\r\n\r\nEste evident că prima relaţie o implică pe cea de-a doua. În momentul acesta se poate construi următorul algoritm: având lista de poziţii care pot fi bune pentru $X$ (sortată descrescător) o căutăm pe cea mai mare ca valoare care este într-adevăr bună. În principiu, scoatem din capul listei poziţiile rele până când dăm de o poziţie bună. La listă se va adăuga şi $X$ şi se va trece la pasul următor. Operaţiile algoritmului sunt chiar operaţiile asupra unui deque.\r\n\r\nh2(#problema-6). Problema 6: \'Bcrc\':problema/bcrc (Stelele Informaticii 2006)\r\n\r\nbq. Se consideră $N$ camere, numerotate de la $1$ la $N$, aşezate în cerc. Iniţial (la momentul de timp 0), ne aflăm în camera $1$. În fiecare moment de timp, putem alege să rămânem în camera în care ne aflăm sau să ne deplasăm într-o cameră vecină într-o unitate de timp. Se dă o listă de $M$ cutii ce conţin bomboane prin $T$, $C$ şi $B$: cutia apare la momentul $T$ în camera $C$ şi conţine $B$ bomboane. Cutia va dispărea la momentul $T + 1$.\r\nCerinţă: Cunoscând numărul de camere din labirint şi momentele de timp la care apar cutiile cu bomboane, determinaţi care este numărul maxim de bomboane pe care le putem culege.\r\nRestricţii: $3 &le; N &le; 2 048$, $0 &le; M &le; 50 000$, $1 &le; T &le; 1 000 000 000$, $1 &le; C &le; N$, $1 &le; B &le; 9 999$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia foloseşte metoda programării dinamice.\r\n\r\nO stare se reprezintă prin camera în care ne aflăm şi momentul de timp. Fie $bst[i][j]$ numărul maxim de bomboane culese până în momentul $i$ când ne găsim în camera $j$. O observaţie evidentă este că $bst[i][j]$ se poate modifica doar în momentele în care apar cutiile. Prin urmare, vom considera momentele de timp când apar cutiile, momente ce sunt în număr de $M$, $bst[i][j]$ însemnând numărul maxim de bomboane culese ştiind că ne aflăm în camera $j$ unde am cules cutia $i$. De cine depinde această stare? Ştim că $bst[i - 1][1 ... N]$ a fost deja calculat în mod optim. Să notăm cu $T$ diferenţa de timp dintre momentele la care apare cutia $i$ şi cutia $i - 1$. În acest moment $i$ şi cameră $j$ putem ajunge din maxim $T$ camere spre stânga sau spre dreapta, întrucât fiecare deplasare între două camere costă o unitate de timp. De unde deducem că:\r\n\r\n* $bst[i][j] = Min { bst[i - 1][j - T], bst[i - 1][j - T + 1], ..., bst[i - 1][j], ..., bst[i - 1][j + T - 1], bst[i - 1][j + T] }$.\r\n\r\nMetoda directă şi, aparent eficientă, constă în folosirea unui arbore de intervale pentru aflarea acestui minim. Însă, intervalul se deplasează, dacă vom considera indicii $j$ în ordine $1$, $2$, $3$, ... constant spre dreapta, fiind reprezentat de un şir de valori de lungime constantă în care noile elemente se introduc prin dreapta şi altele se elimină prin stânga. Vom folosi un deque de lungime $2 * T$ şi vom proceda ca în problemele precedente, eliminând poziţiile care nu sunt candidate la soluţie. Mai jos este o reprezentare grafică a acestei explicaţii.\r\n\r\np=. !deque-si-aplicatii?bcrc.png 40%!\r\n\r\nComplexitatea finală: $O(M * N)$.\r\n\r\nh2(#problema-7). Problema 7: \'Cut the Sequence\':http://acm.pku.edu.cn/JudgeOnline/problem?id=3017 (PKU) \r\n\r\nbq. Se dă o secvenţă $S$ de numere întregi de lungime $N$. Va trebui să se împartă secvenţa în mai multe subsecvenţe astfel încât suma valorilor din fiecare parte să nu depăşească un număr întreg $M$ dat, iar dacă însumăm maximul din fiecare subsecvenţă să obţinem o sumă cât mai mică.\r\nRestricţii: $0 &lt; N &le; 100 000$, $0 &le; S{~i~} &le; 1 000 000$.\r\n\r\nh3. Soluţie:\r\n\r\nVoi face un desen pentru explicaţii. :)\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    // S[] şirul iniţial de numere iar N lungimea sa\r\n    // (last, i] este intervalul de lungime maximă care se termină în i a cărui sumă nu depăşeşte M\r\n    sum  = 0;\r\n    last = 0;\r\n    // indicii head si tail ai dequeului\r\n    deque[head = tail = 1] = 0;\r\n    pentru i = 1, N execută\r\n        sum += S[i];\r\n        temp = bst[ deque[tail] ];\r\n        cât timp (head <= tail) şi S[ deque[tail] ] <= S[i] execută\r\n            temp = Min(temp, iMin[tail]);\r\n            tail --;\r\n        sfcâttimp\r\n        // adaug poziţia i la deque\r\n        tail ++;\r\n        deque[tail] = i;\r\n        // actualizez iMin[]\r\n        iMin[tail]  = temp;\r\n        // actualizez T[]\r\n        update(T, tail, iMin[tail] + S[i]);\r\n\r\n        cât timp (head <= tail) şi (sum > M) execută\r\n            sum -= S[last];\r\n            dacă (deque[head] == last) atunci\r\n                head ++;\r\n            sfdacă\r\n            last ++;\r\n        sfcâttimp\r\n        // actualizez iMin[]\r\n        iMin[head] = query(bst, last - 1, deque[head] - 1);\r\n        // actualizez T[]\r\n        update(T, head, iMin[head] + S[ deque[head] ]);\r\n        // reţin optimul pentru poziţia curentă\r\n        bst[i] = query(T, head, tail);\r\n    sfpentru\r\n    scrie bst[N];\r\nSfârşit.\r\n==\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nFilozofia din spatele structurii de deque devine utilă, de obicei, în părţile finale ale rezolvării unei probleme. Însă, ce pot spune cu certitudine este că această structură de date pe cât este de simplă pe atât este de eficientă.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\nÎnţelegerea profundă nu se poate realiza decât prin rezolvarea a cât mai multe probleme. Succes!\r\n\r\n* \'Deque\':problema/deque, _Arhiva educaţională_\r\n* \'Secvenţă\':problema/secventa\r\n* \'Secvenţă 3\':problema/secv3\r\n* \'Secvenţă 4\':problema/secv4\r\n* \'Sum 2\':problema/sum2, _Stelele Informaticii 2003_\r\n* \'Drept 2\':problema/drept2, _Lotul Naţional de Informatică, 2006_\r\n* \'Copaci 2\':problema/copaci2, _.campion_\r\n* \'Brânză\':problema/branza\r\n* \'Struţi\':problema/struti\r\n* \'Trompetă\':problema/trompeta\r\n* \'Buline\':problema/buline\r\n* \'Balans\':problema/balans\r\n* \'Gard\':problema/gard, _ONI 2002_\r\n* \'Ghiozdan\':problema/ghiozdan\r\n* \'Munte4\':problema/munte4, _Lotul Naţional de Informatică, 2005_\r\n* \'Cover\':problema/cover, _ONI 2007, Baraj_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Cosmin Negruşeri, \"_Probleme cu secvenţe_\":probleme-cu-secvente\r\n# Dana Lica, \"_Arbori de intervale şi aplicaţii în geometria computaţională_\":arbori-de-intervale\r\n# \'C++ Reference, _deque_\':http://www.cplusplus.com/reference/stl/deque/',3146,'public',NULL,NULL),('concursuri','Concursuri organizate de infoarena','2006-11-05 23:17:11','2008-12-01 12:17:25','h1. Concursuri organizate de infoarena\r\n\r\nIn aproape 4 ani de activitate, infoarena a organizat cateva zeci de concursuri/runde online. Fiecare concurs are un format aparte. De la o runda la cinci, de la cateva ore la cateva zile sau chiar o saptamana, de la cateva probleme la 20, concursurile infoarena variaza in amploare, dificultate si popularitate.\r\n\r\n(toc)*{text-align:center} *Concursuri*\r\n* \'preONI\':concursuri#preoni\r\n* \'Happy Coding\':concursuri#happy\r\n* \'Autumn Warmup\':concursuri#autumn\r\n** \'Autumn Warmup 2007\':concursuri#autumn2007\r\n** \'Autumn Warmup 2006\':concursuri#autumn2006\r\n* \'Summer Challenge\':concursuri#summer\r\n** \'Summer Challenge 2007\':concursuri#summer2007\r\n** \'Summer Challenge 2006\':concursuri#summer2006\r\n* \'Alte concursuri\':concursuri#others\r\n\r\nh2(#preoni). Seria preONI\r\n\r\nConcursul _de marca_ infoarena se organizeaza anual si pregateste elevii pentru \"Olimpiada Nationala de Informatica\":http://olimpiada.info/. Este cel mai popular concurs al nostru.\r\n\r\ntable(layout). |_. preONI 2008 (\'pagina concursului\':preoni-2008)|\r\n|* !>template/preoni-2008/header?a.jpg! *{\'Runda 1\':preoni-2008/runda-1}*\r\n* *{\'Runda 2\':preoni-2008/runda-2}*\r\n* *{\'Runda 3\':preoni-2008/runda-3}*\r\n* *{\'Runda 4\':preoni-2008/runda-4}*\r\n* *{\'Runda Finala\':preoni-2008/runda-finala}*|\r\n\r\ntable(layout). \r\n|_. preONI 2007 (\'pagina concursului\':preoni-2007)|_. preONI 2006 (\'pagina concursului\':preoni-2006) |\r\n|*  !>template/preoni-2007/header?logo.jpg 70%! *{\'Runda 1\':preoni-2007/runda-1}* \r\n* *{\'Runda 2\':preoni-2007/runda-2}*\r\n* *{\'Runda 3\':preoni-2007/runda-3}*\r\n* *{\'Runda 4\':preoni-2007/runda-4}*\r\n* *{\'Runda Finala\':preoni-2007/runda-finala}*\r\n|*  !>template/preoni-2006?hlogo.gif! *{\'Runda 1\':preoni-2006/runda-1}*\r\n* *{\'Runda 2\':preoni-2006/runda-2}*\r\n* *{\'Runda 3\':preoni-2006/runda-3}*\r\n* *{\'Runda 4\':preoni-2006/runda-4}*\r\n* *{\'Finala in Focsani\':preoni-2006/finala}*|\r\n|_. preONI 2005 (\'pagina concursului\':preoni-2005)|_. preONI 2004 (\'pagina concursului\':preoni-2004)|\r\n|* *{\'Runda 1\':preoni-2005/runda-1}*\r\n* *{\'Runda 2\':preoni-2005/runda-2}*\r\n* *{\'Runda 3\':preoni-2005/runda-3}*\r\n|* *{\'Runda 1\':preoni-2004/runda-1}*\r\n* *{\'Runda 2\':preoni-2004/runda-2}*|\r\n\r\nh2(#happy). Happy Coding\r\n\r\nUn concurs infoarena mai neobisnuit. _Happy Coding inseamna programare cu zambetul pe buze, placere si distractie pura!_\r\n\r\nConcursurile Happy Coding dispun de evaluator live si au timp de lucru lejer. Nu vei mai fi stresat de pana la aflarea rezultatelor. Afli pe loc daca solutiile tale sunt bune. In plus, poti lucra si ziua si noaptea, dupa sau in timpul orelor de scoala.\r\n\r\n!>happy-coding-2005-1?logo.jpeg!\r\n\r\n* \'*Happy Coding 2008*\':happy-coding-2008\r\n* \'*Happy Coding 2007*\':happy-coding-2007\r\n* *{\'Happy coding 1 (2005)\':happy-coding-2005-1}*\r\n* *{\'Happy coding 2\':happy-coding-2005-2}*\r\n* *{\'Happy coding 3 (2006)\':happy-coding-2006}*\r\n\r\nh2(#autumn). Autumn Warmup\r\n\r\nh3(#autumn2007). Autumn Warmp 2007 (\'pagina concursului\':autumn-warmup-2007)\r\n\r\n* *{\'Runda 1\':autumn-warmup-2007/runda-1}*\r\n* *{\'Runda 2\':autumn-warmup-2007/runda-2}*\r\n* *{\'Runda 3\':autumn-warmup-2007/runda-3}*\r\n\r\nh3(#autumn2006). {\'Autumn Warmup 2006\':warm-up-2006}\r\n\r\nh2(#summer). Summer Challenge\r\n\r\nO serie noua de concursuri infoarena. Acestea se organizeaza in timpul vacantei de vara pentru cei care nu vor _sa-si iasa din mana_. :)\r\n\r\nh3(#summer2007). Summer Challenge 2007 (\'pagina concursului\':summer-challenge-2007)\r\n\r\n* *{\'Runda 1\':summer-challenge-2007/runda-1}*\r\n* *{\'Runda 2\':summer-challenge-2007/runda-2}*\r\n* *{\'Runda 3\':summer-challenge-2007/runda-3}*\r\n\r\nh3(#summer2006). Summer Challenge 2006\r\n\r\n!>summer-challenge-unu?logo!\r\n\r\n* *{\'Runda 1\':summer-challenge-unu}*\r\n* *{\'Runda 2\':summer-challenge-2}*\r\n* *{\'Runda 3\':summer-challenge-3}*\r\n\r\nh2(#others). Alte concursuri infoarena\r\n\r\n* *{\'All you can code 2008\':all-you-can-code-2008}*\r\n* *{\'Selectie echipe ACM ICPC, UPB 2008\':acm-icpc-upb-2008}*\r\n* *{\'Junior Challenge 2008\':junior-challenge-2008}*\r\n* *{\'Grigore Moisil 2008\':grigore-moisil-2008}*\r\n* *{\'Winter Challenge 2008\':winter-challenge-2008}*\r\n* *{\'Junior Challenge 2007\':junior-challenge}*\r\n* *{\'Winter Challenge\':winter-challenge-1}*\r\n* *{\'Unirea 2007\':unirea-2007}*\r\n* *{\'Grigore Moisil By Net 2006\':moisil-by-net-2006}*\r\n!>agora-finala?logo.gif! !>warm-up-2006?logo.jpeg! \r\n* *{\'Bursele agora, editia 6, finala online\':agora-finala}* \r\n* *{\'Bacalaureat 2005\':bacalaureat-2005}* \r\n* *{\'Concurs de incalzire\':warm-up-2004}* \r\n* *{\'preOJI 2004\':preoji-2004}*',2028,'protected',NULL,NULL),('deque-si-aplicatii','Deque și aplicații','2009-01-22 22:28:12','2009-02-05 15:12:00','h1. Deque şi aplicaţii\r\n\r\n(Categoria _Structuri de date_, Autor _Xulescu_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'_Introducere_\':deque-si-aplicatii#introducere\r\n* \'_Aplicaţii:_\':deque-si-aplicatii#problema-1\r\n** \'1. Book Pile &#40;SGU&#41;\':deque-si-aplicatii#problema-1\r\n** \'2. Vila 2 &#40;.campion&#41;\':deque-si-aplicatii#problema-2\r\n** \'3. Şir\':deque-si-aplicatii#problema-3\r\n** \'4. Trans &#40;ONI 2004&#41;\':deque-si-aplicatii#problema-4\r\n** \'5. Otilia &#40;.campion&#41;\':deque-si-aplicatii#problema-5\r\n** \'6. Bcrc &#40;Stelele Informaticii 2006&#41;\':deque-si-aplicatii#problema-6\r\n** \'7. Cut the Sequence &#40;PKU&#41;\':deque-si-aplicatii#problema-7\r\n* \'_Concluzii_\':deque-si-aplicatii#concluzii\r\n* \'_Probleme suplimentare_\':deque-si-aplicatii#probleme-suplimentare\r\n* \'_Bibliografie_\':deque-si-aplicatii#bibliografie\r\n\r\nÎn acest articol voi prezenta o structură de date de tip listă numită _deque_. Simplitatea acestei structuri poate nu are multe de spus şi din acest motiv am prezentat şi o serie de aplicaţii care vor arăta neaşteptata sa utilitate şi apariţie în locurile unde am fi crezut că nu se mai poate face nimic pentru a reduce complexitatea.\r\n\r\nh2(#introducere). Introducere\r\n\r\n_Dequeul_ (pronunţat de obicei _deck_) poate fi privit ca o colecţie de tip listă ce are două capete prin care se şterg sau inserează noi elemente. În literatura de specialitate, aceste capete se numesc _head_ şi _tail_, iar dequeul mai este recunoscut şi ca fiind o coadă cu două capete _(double ended queue)_.\r\n\r\nUn deque poate fi implementat folosind liste dublu înlănţuite ori cu un vector static când se cunoaşte numărul elementelor din colecţie. Ce trebuie reţinut este că limbajul C++ pune la dispoziţia utilizatorilor prin intermediul headerului _#include <deque>_ containerul \'_std::deque_\':http://www.cplusplus.com/reference/stl/deque/.\r\n\r\nh3(#operatii). Operaţii:\r\n\r\nMai jos sunt enumerate operaţiile care pot fi efectuate asupra unui deque împreună cu corespondentul lor în limbajul C++:\r\n\r\n* _front()_:	    întoarce primul element;\r\n* _back()_:	    întoarce ultimul element;\r\n* _push_front()_: inserează un element în faţă;\r\n* _push_back()_:  inserează un element în spate;\r\n* _pop_front()_:  scoate primul element;\r\n* _pop_back()_:   scoate ultimul element;\r\n* _empty()_:      întoarce _true_ dacă dequel este gol.\r\n\r\np=. !deque-si-aplicatii?new_deque.png 75%!\r\n\r\nToate aceste operaţii se execută în timp $O(1)$ \'amortizat\':http://en.wikipedia.org/wiki/Amortized_analysis. Pentru un plus de viteză va trebui să folosim un vector static cu dimensiunea egală cu numărul maxim de elemente ce pot trece prin deque, iar operaţiile implementate „de mână”, cu doi indecşi ce indică către head şi tail. Însă, în majoritatea aplicaţiilor limita de timp permite folosirea lejerităţii şi siguranţei clasei _std::deque_.\r\n\r\nÎn multe aplicaţii unde soluţiile parţiale se reprezintă sub forma unui şir continuu de valori care permite inserarea şi ştergerea doar pe la capete (în general inserări pe la un capăt şi ştergeri pe la celălalt) se poate folosi un deque. Să urmărim în continuare cazuri concrete în care simplitatea unui deque duce la soluţii de multe ori optime şi implementări foarte scurte şi clare.\r\n\r\nh2(#problema-1). \'1. Book Pile\':http://acm.sgu.ru/problem.php?contest=0&problem=271 (SGU)\r\n\r\nbq. Se dau $N$ cărţi aşezate una deasupra celeilalte asupra cărora se vor efecta $M$ operaţii de două tipuri: 1. $ADD${$(nume)$} : se adaugă cartea $nume$ deasupra celorlalte; 2. $ROTATE$ : primele $K$ cărţi de deasupra se rotesc (dacă sunt mai puţin de $K$ cărţi atunci se vor roti toate). Se cere să se afişeze cărţile în ordine, prima fiind cea de deasupra, după efectuarea celor $M$ operaţii.\r\nRestricţii: $0 &le; N, K &le; 40 000$, $0 &le; M &le; 100 000$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se poate deduce urmând paşii următori. Să presupunem că avem cărţile $A B C$ iniţial şi $K = 3$. Dacă îl vom adăuga pe $D$, atunci nu vor rămâne importante decât cărţile $D A B$, deoarece, dacă vom roti ulterior ultimele $K$ cărţi, $C$ nu va mai fi niciodată considerat, cărţile fiind doar adăugate, iar o dată ce o carte iese din „top {$K$}” cărţi nu va mai fi posibil să i se schimbe poziţia pe raft. Să rotim acum „top {$K$}” cărţi. Noua ordine va fi $B A D$ şi $C$ pe raft la loc sigur. Dacă îl vom adăuga pe $E$, topul se va schimba în $E B A$ iar pe raft, în mod sigur vor fi, în această ordine, $D C$. Proprietatea celor $K$ cărţi din vârf este: o secvenţă continuă de elemente, la care se adaugă noi elemente sau se elimină dintre acestea numai pe la _capete_. Aceste capete sunt chiar head şi tail ale unui deque.\r\n\r\np=. !deque-si-aplicatii?bookpile.png 40%!\r\n\r\nLa final, când se vor termina operaţiile, cărţilor de pe raft li se vor adăuga cele din deque şi se va afişa soluţia. În cazul presupus, soluţia va fi: $E B A D C$.\r\n\r\nÎntrucât operaţiile unui deque se execută în $O(1)$ amortizat, soluţia are complexitatea $O(N + M)$.\r\n\r\nh2(#problema-2). \'2. Vila 2\':problema/vila2 (.campion)\r\n\r\nbq. Se dă un şir $S$ de $N$ numere întregi şi un $D$ număr natural. Se cere să determine diferenţa maximă dintre oricare două numere din şir cu proprietatea că diferenţa indicilor nu depăşeşte $D$.\r\nRestricţii: $2 &le; N &le; 100 000$, $1 &le; D &le; N/2$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia nu este greu de intuit. Considerăm indicii succesiv $1$, $2$, .. , $N$. Va trebuie ca pentru fiecare secvenţă $(i - D, i]$ să determinăm valoarea maximă şi pe cea minimă, iar diferenţa lor să o comparăm cu rezultatul obţinut până în acel moment. Pentru fixarea ideilor, să urmărim cum putem determina valoarea maximă din fiecare secvenţă $(i - D, i]$.\r\n\r\n_Observaţie_: „Fie $i{~1~}$, $i{~2~}$ doi indici astfel încât $i - D &lt; i{~1~} &lt; i{~2~} &le; i$.\r\n\r\n# Dacă $S[i{~1~}] &lt; S[i{~2~}]$ atunci, cât timp cei doi indici vor fi în intervalul $(i - D, i]$, valoarea de pe poziţia $i{~2~}$ va fi întotdeauna preferată valorii de pe poziţiei $i{~1~}$. Când unul din indici nu va mai fi în acest interval, cel expediat va fi $i{~1~}$ şi, astfel, $i{~2~}$ rămâne în continuare preferat.\r\n# Dacă $S[i{~1~}] &gt; S[i{~2~}]$ atunci îl vom păstra pe $i{~2~}$, deoarece este candidat la maxim în viitor.”\r\n\r\nCu această observaţie deducem că într-o secvenţă $(i - D, i]$ vom avea un şir $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$ astfel încât $S[i{~1~}] &gt; S[i{~2~}] &gt; ... &gt; S[i{~K~}]$. Când vom avansa la secvenţa următoare, $(i - D + 1, i + 1]$, vom şterge din indicii $i{~1~}$, $i{~2~}$... atâta timp cât nu se găsesc în intervalul curent şi vom şterge din poziţiile $i{~K~}$, $i{~K-1~}$... cât timp $S[i + 1] &gt; S[i{~K~}]$, $S[i + 1] &gt; S[i{~K-1~}]$... adică cât timp se îndeplineşte primul punct din observaţia anterioară.\r\n\r\nŞirul $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$ este continuu iar operaţiile se efectuează doar pe la cele două capete. Rezultă că şirul poate fi implementat cu ajutorul unui deque.\r\n\r\nPentru $S[] = {5, 9, 4, 7, 4, 1}$ şi $D = 3$ obţinem următoarele stări ale unui deque:\r\n\r\n* <tex> \\langle \\widehat{5\\ [1]} \\rangle; </tex>\r\n* <tex> \\langle 5\\ [1] \\rangle \\Leftarrow 9\\ [2] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]} \\rangle; </tex>\r\n* <tex> \\langle 9\\ [2] \\rangle \\Leftarrow 4\\ [3] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 4\\ [3] \\rangle; </tex>\r\n* <tex> \\langle 9\\ [2],\\ 4\\ [3] \\rangle \\Leftarrow 7\\ [4] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 7\\ [4] \\rangle; </tex>\r\n* <tex> 9\\ [2] \\Leftarrow \\langle 7\\ [4] \\rangle \\Leftarrow 4\\ [5] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5] \\rangle; </tex>\r\n* <tex> \\langle 7\\ [4],\\ 4\\ [5] \\rangle \\Leftarrow 1\\ [6] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5],\\ 1\\ [6] \\rangle; </tex>\r\n\r\nCum fiecare indice din $1$, $2$, .., $N$ trece cel mult o dată prin deque, complexitatea finală este $O(N)$ amortizat.\r\n\r\nh2(#problema-3). \'3. Şir\':problema/sir\r\n\r\nbq. Se dă un şir $S$ de numere întregi de lungime $N$. Se cere să se găsească secvenţa de lungime maximă cuprinsă între $X$ şi $Y$ astfel încât $MAX - MIN &le; Z$, unde $MAX$ este maximul dintre toate numerele întregi din secvenţă iar $MIN$ minimul dintre acestea. Secvenţa soluţie va fi cea cu poziţia de început maximă dintre toate secvenţele de lungime maximă.\r\nRestricţii: $3 &le; N &le; 100 000$, $1 &le; X &le; Y &le; N$, $0 &le; Z &le; 30 000$.\r\n\r\nh3. Soluţie\r\n\r\nVoi prezenta mai jos o rafinare a soluţiei în trei paşi.\r\n\r\nPrima rezolvare se găseşte uşor, deoarece nu facem decât să urmărim textul: pentru fiecare poziţie $i$ fixată ({$i$} ia valorile $1$, $2$, .., $N$ succesiv) vom determina pentru aceasta secvenţa cerută, adică vom plimba un $j$ între poziţiile $i - Y$ şi $i - X$. Pentru un interval $(j, i]$ vom determina $MAX$ şi $MIN$ în $O(log{~2~}N)$ cu un arbore de intervale, iar daca diferenţa dintre acestea nu depăşeşte $Z$ vom compara cu soluţia finală. Complexitatea finală va fi $O(N * (Y - X) * log{~2~}Y)$.\r\n\r\nSă presupunem că pentru poziţia curentă $i$, l-am găsit pe $j$ cuprins între $i - Y$ şi $i - X$ care îndeplineşte optimul. Ce proprietăţi are $j$?\r\n\r\n* $i - Y &le; j &le; i - X$ şi $MAX - MIN &le; Z$;\r\n* dacă îl incrementăm pe $j$ la $j + 1$ atunci dacă $j &le; i - X$ cu siguranţă $MAX - MIN &le; Z$ şi astfel soluţia va fi mai scurtă;\r\n* dacă îl decrementăm pe $j$, atunci ori $j < i - Y$ ori $MAX - MIN > Z$;\r\n* dacă îl incrementăm pe $i$ la $i + 1$, atunci se poate întâmpla ca $j < i - Y$; cum $MAX$ nu poate decât să crească, iar $MIN$ decât să scadă, se mai poate de asemenea întâmpla ca $MAX - MIN > Z$.\r\n\r\nDatorită proprietăţilor de mai sus, când trecem de la $i$ la $i + 1$, valoarea lui $j$ nu poate decât să crească cât timp $j < i - Y$ sau $MAX - MIN > Z$ şi $j$ nu a depăşit poziţia $i - X$. Pentru determinarea lui $MAX$, respectiv lui $MIN$ se poate folosi un arbore de intervale. Complexitatea finală va fi $O(N * log{~2~}(Y))$.\r\n\r\nCu cei doi indici $i$ şi $j$ vom accesa fiecare element din cele $N$ de cel mult $2$ ori, o dată cu $i$ şi o dată cu $j$. Să vedem cum putem îmbunătăţi complexitatea $O(log{~2~}Y)$ pentru determinarea maximului şi minimului.\r\n\r\nPentru fixarea ideilor să urmărim cum îl calculăm pe $MAX$. Observaţia care ne ajută în multe probleme pentru reducerea complexităţii de la $O(log{~2~}N)$ la $O(1)$ amortizat este următoarea: \r\n\r\n_Observaţie_: „Fixăm $i{~1~}$ şi $i{~2~}$ astfel încât $j < i{~1~} < i{~2~} &le; i$. Atunci, dacă $S[i{~2~}] > S[i{~1~}]$ poziţia $i{~2~}$ va fi întotdeauna mai importantă decât poziţia $i{~1~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ şi $i{~2~}$ nu vor mai fi ambele în intervalul $(j, i]$, poziţia eliminată va fi {$i{~1~}$}. Dacă însă $S[i{~1~}] > S[i{~2~}]$, atunci poziţia $i{~1~}$ va umbri poziţia $i{~2~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ va fi eliminat, atunci e posibil ca $i{~2~}$ să fie un candidat la $MAX$ dintre restul elementelor de la dreapta sa. În acest caz, nu putem afirma nimic şi vom păstra cele două poziţii.”\r\n\r\nRezultă din această observaţie că în intervalul $(j, i]$ poziţiile importante vor fi $j < i{~1~} < i{~2~} < .. < i{~k~} <= i$ astfel încât $S[i{~1~}] > S[i{~2~}] > .. > S[i{~k~}]$. Astfel, $MAX$ va fi $S[i{~1~}]$. Când îl vom incrementa pe $i$ la $i + 1$ vom şterge din poziţiile $i{~k~}$, $i{~k-1~}$, ... atâta timp cât $S[i + 1]$ este mai important, adică mai mare decât valorile de pe aceste poziţii, şi vom şterge $i{~1~}$, $i{~2~}$, ... atâta timp cât aceste poziţii sunt mai mici sau egale decât $j\'$. Indicele $j\'$ este noul optim pentru poziţia $i + 1$. Proprietatea şirului de poziţii $i{~1~}, i{~2~}, .., i{~k~}$ este că se reprezintă ca un şir continuu de numere care permite inserarea elementelor prin dreapta şi ştergerea prin stânga, adică se adaugă elemente la tail şi se şterg elemente de la head. Îl putem deci reprezenta printr-un deque. Complexitatea $O(1)$ amortizat provine de la faptul că fiecare poziţie dintre cele $N$ nu trece decât o singură dată prin deque şi este şters tot cel mult o singură dată. \r\n\r\nÎn practică, pseudocodul poate arăta în felul următor:\r\n\r\n== code(cpp) |\r\n// S şirul de numere iniţial şi N lungimea sa\r\n\r\nSubalgoritmul push_in(deque, întreg p, funcţia fct) este:\r\n    cât timp (!deque.empty() şi fct(S[p], S[deque.back()])) execută\r\n        deque.pop_back();\r\n    deque.push_back(p);\r\nSfârşit;\r\n\r\nFuncţia query(deque, întreg j) este:\r\n    cât timp (!deque.empty() şi deque.front() <= j) execută\r\n        deque.pop_front();\r\n    return S[deque.front()];\r\nSfârşit;\r\n\r\nAlgoritmul este:\r\n    lg = 0;\r\n    pentru i = 1, N execută\r\n        // funcţia min(a, b) întoarce true dacă a < b\r\n        inserează(min_deq, i, min);\r\n        // funcţia max(a, b) întoarce true dacă a > b\r\n        inserează(max_deq, i, max);\r\n        cât timp ((j < i - Y sau query(max_deq, j) - query(min_deq, j) > Z) şi j < i - X) execută\r\n            j = j + 1;\r\n        // (j, i] este intervalul candidat la soluţia optimă pentru poziţia i\r\n        dacă (j <= i - X) şi (query(max_deq, j) - query(min_deq, j) <= Z) atunci\r\n            dacă (lg >= i - j) atunci\r\n                lg = i - j, start = j + 1, stop = i;\r\n    sfârşit_pentru\r\n\r\n    dacă (lg > 0) atunci\r\n        scrie lg, start, stop;\r\n    altfel\r\n        scrie -1;\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală va fi $O(N)$.\r\n\r\nh2(#problema-4). \'4. Trans\':problema/trans (ONI 2004)\r\n\r\nbq. Se dau $N$ blocuri de piatră, de culoare albă sau neagră aşezate în ordinea $1$, $2$,.., $N$. Blocurile de piatră trebuie să fie transportate în ordinea în care sunt, iar pentru aceasta va trebui închiriat un camion. Se mai dau $Q$ tipuri de camioane. Camionul de tipul $i (1 &le; i &le; Q)$ poate transporta maxim $K{~i~}$ blocuri de piatră la un moment dat şi pentru un transport se percepe taxa $T{~i~}$. Se impune condiţia ca toate blocurile de piatră plasate în camion la un transport sa aibă aceeaşi culoare. Aşadar, pentru a fi transportate toate blocurile, se va alege un camion de un anumit tip, iar camionul va efectua unul sau mai multe transporturi. Pentru a micşora suma totală plătită, există posibilitatea de a schimba culoarea oricărui bloc de piatră (din alb în negru sau din negru în alb); pentru fiecare bloc $i (1 &le; i &le; N)$ se cunoaşte suma $S{~i~}$ ce trebuie plătită pentru a-i schimba culoarea $C{~i~}$.\r\nCerinţă: Pentru fiecare dintre cele $Q$ tipuri de camioane, determinaţi suma minimă plătită pentru a transporta toate cele $N$ blocuri.\r\nRestricţii: $1 &le; N &le; 16 000$, $1 &le; Q &le; 100$, $1 &le; K{~i~} &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se bazează pe găsirea unei formule de recurenţă ce respectă principiul optimalităţii al metodei programării dinamice.\r\n\r\nPentru început, fixăm un camion dintre cele $Q$. Fie $K$ numărul maxim de pietre pe care acesta le poate transporta şi $T$ taxa percepută. Notăm $sum[i][&#99;]$ costul pentru a schimba toate pietrele $1$, $2$, .., $i$ în culoarea $c$ ({$c = 0$} pentru alb şi $c = 1$ pentru negru). În $sum[i][&#99;]$ se vor aduna toate valorile $S[j]$, cu $j &le; i$ pentru care $C[j] = 1 - c$. \r\n\r\nÎn continuare, considerăm $bst[i][&#99;]$ costul minim pentru a transporta pietrele $1$, $2$, .., $i$, iar ultimul transport conţine pietre de culoare $c$. Întrucât nu putem transporta mai mult de $K$ pietre, $bst[i][&#99;]$ depinde doar de poziţiile $i - K$, $i - K + 1$, ..., $i - 1$. Cunoaştem că ultimul camion va transporta o secvenţă continuă de pietre începând de la o poziţie $j + 1$ până la poziţia $i$, unde $i - K &le; j &le; i - 1$. Astfel, pentru fiecare $j$ în intervalul precedent, costul va fi $Minim(bst[j][&#48;], bst[j][&#49;])$ (transportăm primele j pietre cât mai ieftin) adunat cu $sum[i][&#99;] - sum[j][&#99;]$ (costul transformării pietrelor $j + 1$, .., $i$ în culoarea $c$) şi plus taxa $T$. Rezultă recurenţa:\r\n\r\n* <tex> bst[i][c] = Min\\ \\{\\ Minim(bst[j][0],\\ bst[j][1]) + sum[i][c] - sum[j][c] + T\\ |\\ i - K \\le j \\le i - 1\\ \\}; </tex>\r\n\r\nDacă ne vom opri aici, complexitatea soluţiei va fi $O(Q * N^2^)$.\r\n\r\nRelaţia de recurenţă poate fi îmbunătăţită. Observăm că pentru poziţia $i$, $sum[i][&#99;]$ este o valoare constantă, ca şi $T$. Astfel, deducem următoarea relaţie de recurenţă:\r\n\r\n* <tex> bst[i][c] = Min\\ \\{\\ Minim(bst[j][0],\\ bst[j][1]) - sum[j][c]\\ |\\ i - K \\le j \\le i - 1\\ \\} + sum[i][c] + T; </tex>\r\n\r\nNotez în continuare, pentru uşurinţă în scriere, $X[j][&#99;] = Min(bst[j][&#48;], bst[j][&#49;]) - sum[j][&#99;]$. Să fixăm doi indici $i{~1~}$ şi $i{~2~}$, astfel încât $i - K &le; $i{~1~}$ < $i{~2~}$ &le; i - 1$. Dacă $X[i{~1~}][&#99;] > X[i{~2~}][&#99;]$ atunci, întotdeauna poziţia $i{~2~}$ va fi preferată poziţiei $i{~1~}$. Când cele două nu se vor mai afla în intervalul $[i - K, i - 1]$, poziţia eliminată va fi poziţia $i{~1~}$. Dacă $X[i{~1~}][&#99;] < X[i{~2~}][&#99;]$, atunci nu putem decide care poziţie este mai bună în viitor, aşa că le vom păstra pe ambele. Rezultă mai departe că în intervalul $[i - K, i - 1]$ vom avea o serie de indecşi candidaţi la minim $i - K &le; i{~1~} < i{~2~} < .. < i{~n~} &le; i - 1$ astfel încât $X[i{~1~}][&#99;] < X[i{~2~}][&#99;] <  .. < X[i{~n~}][&#99;]$. Mai departe, găsim $bst[i][&#99;]$ ca fiind $X[i{~1~}][&#99;] + sum[i][&#99;] + T$. Urmează să îl introducem şi pe $X[i][&#99;]$, el fiind egal cu $Min(bst[i][&#48;], bst[i][&#49;]) - sum[i][&#99;]$, în şirul de indecşi de mai sus. Acest lucru se va face în felul următor: se vor elimina din $i{~n~}$, $i{~n-1~}$, ... atâta timp cât $X[$i{~n~}$][&#99;] > X[i][&#99;]$, $X[$i{~n-1~}$][&#99;] > X[i][&#99;]$, ... adică atâta timp cât poziţia $i$ este preferată lui $i{~n~}$, $i{~n-1~}$... Fiind la poziţia $i + 1$, intervalul se va transforma în $[i - K + 1, i]$, aşadar, vom mai elimina din primii indici $i{~1~}$, $i{~2~}$,... atâta timp cât $i{~1~} < i - K + 1$, $i{~2~} < i - K + 1$...\r\n\r\nDupă cum am arătat şi la problema precedentă, acest şir de indecşi $i{~1~}$, $i{~2~}$, .., $i{~n~}$ are proprietatea că este un şir continuu de numere care admite inserări prin dreapta (tail) şi ştergeri prin stânga (head). Şir ce poate fi reprezentat printr-un deque. Cum fiecare index dintre $1$, $2$, .., $N$ va trece o singură dată prin deque şi va fi şters cel mult o dată, complexitatea soluţiei în acest caz va fi $O(Q * N)$.\r\n\r\nÎn practică, programul este scurt, clar şi foarte eficient:\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\n#include <vector>\r\n#include <deque>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\nconst char iname[] = \"trans.in\";\r\nconst char oname[] = \"trans.out\";\r\n\r\n#define MAXN  16005\r\n#define Min(a, b) ((a) < (b) ? (a) : (b))\r\n#define FOR(i, a, b)  for (int i = (a); i <= (b); ++ i)\r\n\r\nint C[MAXN], S[MAXN], bst[MAXN][2], sum[MAXN][2], N;\r\n\r\nvoid insert(deque < pair <int, int> >& deq, const pair <int, int>& p) {\r\n    while (!deq.empty() && deq.back().second > p.second)\r\n        deq.pop_back();\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque < pair <int, int> >& deq, const int idx) {\r\n    while (deq.front().first < idx)\r\n        deq.pop_front();\r\n    return deq.front().second;\r\n}\r\n\r\nint work(const int K, const int T) {\r\n    deque < pair <int, int> > deq[2];       // pair (idx, value)\r\n    FOR (c, 0, 1)\r\n        insert(deq[c], pair <int, int>(0, 0));\r\n    FOR (i, 1, N) {   // obiectul i\r\n        FOR (c, 0, 1) // culoare\r\n            bst[i][c] = query(deq[c], i - K) + sum[i][c] + T;\r\n        FOR (c, 0, 1)\r\n            insert(deq[c], pair <int, int>(i, Min(bst[i][0], bst[i][1]) - sum[i][c]));\r\n    }\r\n    return Min(bst[N][0], bst[N][1]);\r\n}\r\n\r\nint main(void)\r\n{\r\n    ifstream in(iname);  ofstream out(oname);\r\n    in >> N;\r\n    FOR (i, 1, N) {\r\n        in >> C[i] >> S[i];\r\n        FOR (c, 0, 1)\r\n            sum[i][c] += sum[i - 1][c];\r\n        sum[i][1 - C[i]] += S[i];\r\n    }\r\n    int cnt, K, T;\r\n    in >> cnt;\r\n    FOR (i, 1, cnt)\r\n        in >> K >> T, out << work(K, T) << \"\\n\";\r\n\r\n    in.close(), out.close();\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#problema-5). \'5. Otilia\':problema/otilia  (.campion)\r\n\r\nbq. Otilia şi Burbucel au o grămadă de $N$ pietre şi vor juca un joc cu următoarele trei reguli: 1. Primul jucător are voie să ia din gramadă cel mult $K$ piese; 2. Cu excepţia primei mutări, fiecare jucător are voie să ia maxim $P * t$ pietre, unde $t$ este numărul de pietre care au fost substituite din grămadă la mutarea precedentă; 3. Pierde cel care mută ultimul (cel care ia ultimele pietre din grămadă).\r\nCerinţă: Se dau $M$ jocuri prin numerele $N$, $K$ şi $P$. Se cere să se determină dacă Otilia va câştiga fiecare din jocuri sau nu.\r\nRestricţii: $1 &le; M &le; 30 000$, $1 &le; N &le; 5 000 000$, $1 &le; K &le; N$, $1 &le; P &le; 10$.\r\n\r\nh3. Soluţie:\r\n\r\nProblema se rezolvă prin programare dinamică. Soluţia se bazează pe observaţia de mai jos. Considerăm $P$-ul fixat şi notăm cu $stare(X, Y)$ poziţia de start în care avem $X$ pietre şi numărul maxim de pietre care se pot lua la prima mutare este $Y$.\r\n\r\n_Observaţia 1_: „Dacă există strategie sigură de câştig pentru $stare(X, Y)$ atunci există şi pentru orice $stare(X, T)$ cu $T &ge; Y$.” \r\n\r\nDe ce? Pentru că orice mutare validă pentru $stare(X, Y)$ este validă şi pentru $stare(X, T)$. Având această observaţie notăm cu $MinY[X] = Y$, $Y$ minim astfel încât avem strategie de câştig pentru $stare(X, Y)$.\r\n\r\n_Observaţia 2_: „{$stare(X, Y)$} este pierzătoare dacă şi numai dacă $Y < MinY[X]$.” \r\n\r\nAceasta reiese din definiţia lui $MinY[X]$.\r\n\r\n$MinY[X]$ se calculează după următoarea recurenţă, care rezultă din regulile jocului: \r\n\r\n* $MinY[X]$ este cel mai mic $i$ pentru care avem $MinY[X - i] > P * i$.\r\n\r\nDe aici se naşte prima soluţie, care este implementarea directă a recurenţei. Deşi complexitatea acesteia pare a fi $O(N^2^)$ ea se comportă foarte bine pentru $N &le; 500 000$. Aşadar, această soluţie acoperă aproximativ $50%$ din testele de intrare. Printr-o rafinare a acestei soluţii se obţine un algoritm de complexitate $O(N)$. Rafinarea se bazează pe: \r\n\r\n_Observaţia 3_: „Să presupunem că dorim să calculăm $MinY[X]$. Facem următoarea afirmaţie: orice poziţie _rea_ pentru $X$ (în care dacă mutăm pierdem) va fi _rea_ şi pentru $X + 1$.”\r\n\r\nAcest lucru este simplu de observat dacă privim ce înseamnă că o poziţie $Q$ e rea pentru $X$: \r\n\r\n* $MinY[Q] > X - Q$, pentru $X$;\r\n* $MinY[Q] > X - Q + 1$, pentru $X + 1$.\r\n\r\nEste evident că prima relaţie o implică pe cea de-a doua. În momentul acesta se poate construi următorul algoritm: având lista de poziţii care pot fi bune pentru $X$ (sortată descrescător) o căutăm pe cea mai mare ca valoare care este într-adevăr bună. În principiu, scoatem din capul listei poziţiile rele până când dăm de o poziţie bună. La listă se va adăuga şi $X$ şi se va trece la pasul următor. Operaţiile algoritmului sunt chiar operaţiile asupra unui deque.\r\n\r\nh2(#problema-6). \'6. Bcrc\':problema/bcrc (Stelele Informaticii 2006)\r\n\r\nbq. Se consideră $N$ camere, numerotate de la $1$ la $N$, aşezate în cerc. Iniţial (la momentul de timp 0), ne aflăm în camera $1$. În fiecare moment de timp, putem alege să rămânem în camera în care ne aflăm sau să ne deplasăm într-o cameră vecină într-o unitate de timp. Se dă o listă de $M$ cutii ce conţin bomboane prin $T$, $C$ şi $B$: cutia apare la momentul $T$ în camera $C$ şi conţine $B$ bomboane. Cutia va dispărea la momentul $T + 1$.\r\nCerinţă: Cunoscând numărul de camere din labirint şi momentele de timp la care apar cutiile cu bomboane, determinaţi care este numărul maxim de bomboane pe care le putem culege.\r\nRestricţii: $3 &le; N &le; 2 048$, $0 &le; M &le; 50 000$, $1 &le; T &le; 1 000 000 000$, $1 &le; C &le; N$, $1 &le; B &le; 9 999$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia foloseşte metoda programării dinamice.\r\n\r\nO stare se reprezintă prin camera în care ne aflăm şi momentul de timp. Fie $bst[i][j]$ numărul maxim de bomboane culese până în momentul $i$ când ne găsim în camera $j$. O observaţie evidentă este că $bst[i][j]$ se poate modifica doar în momentele în care apar cutiile. Prin urmare, vom considera momentele de timp când apar cutiile, momente ce sunt în număr de $M$, $bst[i][j]$ însemnând numărul maxim de bomboane culese ştiind că ne aflăm în camera $j$ unde am cules cutia $i$. De cine depinde această stare? Ştim că $bst[i - 1][1..N]$ a fost deja calculat în mod optim. Să notăm cu $T$ diferenţa de timp dintre momentele la care apare cutia $i$ şi cutia $i - 1$. În acest moment $i$ şi cameră $j$ putem ajunge din maxim $T$ camere spre stânga sau spre dreapta, întrucât fiecare deplasare între două camere costă o unitate de timp. De unde deducem că:\r\n\r\n* <tex> bst[i][j] = Min\\{\\ bst[i - 1][j - T],\\ bst[i - 1][j - T + 1]...\\ bst[i - 1][j]...\\ bst[i - 1][j + T - 1],\\ bst[i - 1][j + T]\\ \\}; </tex>\r\n\r\nMetoda directă şi, aparent eficientă, constă în folosirea unui arbore de intervale pentru aflarea acestui minim. Însă, intervalul se deplasează, dacă vom considera indicii $j$ în ordine $1$, $2$, $3$, ... constant spre dreapta, fiind reprezentat de un şir de valori de lungime constantă în care noile elemente se introduc prin dreapta şi altele se elimină prin stânga. Vom folosi un deque de lungime $2 * T$ şi vom proceda ca în problemele precedente, eliminând poziţiile care nu sunt candidate la soluţie. Mai jos este o reprezentare grafică a acestei explicaţii.\r\n\r\np=. !deque-si-aplicatii?bcrc.png 40%!\r\n\r\nComplexitatea finală: $O(M * N)$.\r\n\r\nh2(#problema-7). \'7. Cut the Sequence\':http://acm.pku.edu.cn/JudgeOnline/problem?id=3017 (PKU) \r\n\r\nbq. Se dă o secvenţă $S$ de numere întregi de lungime $N$. Va trebui să se împartă secvenţa în mai multe subsecvenţe astfel încât suma valorilor din fiecare parte să nu depăşească un număr întreg $M$ dat, iar dacă însumăm maximul din fiecare subsecvenţă să obţinem o sumă cât mai mică.\r\nRestricţii: $0 &lt; N &le; 100 000$, $0 &le; S{~i~} &le; 1 000 000$.\r\n\r\nh3. Soluţie:\r\n\r\nŞi această soluţie foloseşte metoda programării dinamice. Construim <tex> bst_{i} </tex> egal cu costul minim de a împărţi primele <tex> i </tex> numere din <tex> S </tex>. Pentru a calcula <tex> bst_{i} </tex> alegem toate secvenţele posibile care se termină pe o poziţia <tex> j </tex>, <tex> j < i </tex>, şi adunăm valorile corespunzătoare:\r\n\r\n* <tex> bst_{i} = Min\\{bst_{j} + Max\\{S_{j+1},.., S_{i}\\}\\ :\\ 0 \\le j < i, \\displaystyle\\sum_{k=j+1}^{i} S_{k} \\le M\\}; </tex>\r\n\r\nImplementarea directă a acestei recurenţe conduce la un algoritm de complexitate <tex> O(N^{2}) </tex>, dar care pentru restricţiile impuse nu este de ajuns.\r\n\r\nSă obţinem în continuare alte informaţii. Fie indicele <tex> j </tex> minim astfel încât <tex> \\displaystyle\\sum_{k=j+1}^{i} \\le M </tex>. Maximul obţinut din mulţimea <tex> \\{S_{j+1},.., S_{i}\\} </tex> se găseşte pe o poziţie <tex> j^{\'} </tex> unde <tex> j < j^{\'} \\le i </tex>. Însă, orice indice <tex> k </tex> cu <tex> j \\le k < j^{\'} </tex> are proprietatea că rezultatul expresiei <tex> Max\\{S_{k+1},.., S_{i}\\} </tex> se găseşte pe poziţia <tex> j^{\'} </tex>. Rezultă că <tex> \\forall k \\in \\{j, j+1,.., j^{\'}-1\\} </tex>, <tex> bst_{i} </tex> poate fi îmbunătăţit cu valoarea <tex> bst_{k} + S_{j^{\'}} </tex>. Minimul mulţimii <tex> \\{bst_{k} + S_{j^{\'}} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} </tex> este egal cu minimul expresiei <tex> \\{bst_{k} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} + S_{j^{\'}} (*) </tex>, deci, schimbând reperele, pentru maximul de pe poziţia <tex> j^{\'} </tex>, dacă lungimea secvenţei care se termină în <tex> i </tex> este cel puţin <tex> i-j^{\'}+1 </tex>, atunci optimul se obţine calculând rezultatul expresiei <tex> (*) </tex>. Pentru minimul pe un interval, <tex> [j, j^{\'}-1] </tex> al valorile vectorului <tex> bst </tex>, putem folosi un arbore de intervale pentru <tex> O(log_{2}N) </tex> pe interogare.\r\n\r\nDar, lungimea optimă a ultimei secvenţe ce se termină în <tex> i </tex> poate fi mai mică decât <tex> i-j^{\'}+1 </tex>, deci poate fi cel mult <tex> i-j^{\'} </tex>. Optimul se găseşte printre elementele mulţimii <tex> \\{bst_{k} + Max\\{S_{k+1},..,S_{i}\\} : j^{\'} \\le k < i\\} </tex>. Dacă procedăm ca la pasul anterior vom obţine un alt indice <tex> j^{\'\'} </tex> cu aceleaşi proprietăţi pentru secvenţa <tex> [j^{\'}, i] </tex> precum <tex> j^{\'} </tex> pentru secvenţa <tex> [j, i] </tex>.\r\n\r\nInductiv obţinem un şir de indici <tex> j_{0} = j < j_{1} < j_{2} < .. < j_{K} = i </tex> astfel încât <tex> S_{j_{1}} </tex> este cel mai mare element al secvenţei <tex> (j, i] </tex>, <tex> S_{j_{2}} </tex> cel mai mare element al secvenţei <tex> (j_{1}, i] </tex>, şi aşa mai departe, când <tex> j_{K} </tex> este chiar <tex> i </tex>.\r\n\r\nCu ajutorul relaţiei <tex> (*) </tex> şi a şirului <tex> j_{1} < j_{2} < .. < j_{K} = i </tex> vom construi un alt vector <tex> iMin </tex> cu proprietatea că <tex> iMin_{p} = Min\\{bst_{r} + S_{j_{p}} : j_{p-1} \\le r < j_{p}\\} </tex>. În final, <tex> bst_{i} = Minim\\{iMin_{1}, iMin_{2}, .., iMin_{K}\\} </tex>, rezultat pe care îl putem obţine în <tex> O(log_{2}N) </tex> dacă folosim un arbore de intervale.\r\n\r\nÎnsă, cum se construieşte şirul <tex> j_{1} < j_{2} < .. < j_{K} = i </tex>? În \'a doua problemă\':deque-si-aplicatii#problema2 am construit cu ajutorul unui deque exact şirul de indici de care avem nevoie aici. Când vom înainta la indicele <tex> i + 1 </tex> vom modifica şirul astfel încât să respecte proprietăţile de mai sus utilizând operaţiile normale asupra unui deque. Mai sus am menţionat cum se obţine <tex> bst_{i} </tex> lucru care implică combinarea structurilor de deque şi arbore de intervale. Arborele de intervale reţine valorile lui <tex> iMin </tex> pentru fiecare element al dequelui. Mai jos se vede o figură în care elementele unui deque sunt defapt o secvenţă „continuă” de frunze ale unui arbore de intervale.\r\n\r\np=. !deque-si-aplicatii?PKU.png 60%!\r\n\r\np=. _Numărul maxim de elemente ce pot trece prin deque este $8$. În figură, arborele ţine evidenţa elementelor $3$, $4$, $5$, $6$ din deque._\r\n\r\nAlgoritmul în pseudocod arată în felul următor:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    sum  = 0;\r\n    last = 0;\r\n    // indicii head si tail ai dequeului\r\n    deque[head = tail = 1] = 0;\r\n    pentru i = 1, N execută\r\n        sum += S[i];\r\n        temp = bst[ deque[tail] ];\r\n        cât timp (head <= tail) şi S[ deque[tail] ] <= S[i] execută\r\n            temp = Min(temp, iMin[tail]);\r\n            tail --;\r\n        sfcâttimp\r\n        // adaug poziţia i la deque\r\n        tail ++;\r\n        deque[tail] = i;\r\n        // actualizez iMin[]\r\n        iMin[tail]  = temp;\r\n        // actualizez T[]\r\n        update(T, tail, iMin[tail] + S[i]);\r\n\r\n        cât timp (head <= tail) şi (sum > M) execută\r\n            sum -= S[last];\r\n            dacă (deque[head] == last) atunci\r\n                head ++;\r\n            sfdacă\r\n            last ++;\r\n        sfcâttimp\r\n        // actualizez iMin[]\r\n        iMin[head] = query(bst, last - 1, deque[head] - 1);\r\n        // actualizez T[]\r\n        update(T, head, iMin[head] + S[ deque[head] ]);\r\n        // reţin optimul pentru poziţia curentă\r\n        bst[i] = query(T, head, tail);\r\n    sfpentru\r\n    scrie bst[N];\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală este <tex> O(N*log_{2}N) </tex>.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nFilozofia din spatele structurii de deque devine utilă, de obicei, în părţile finale ale rezolvării unei probleme. Însă, ce pot spune cu certitudine este că această structură de date pe cât este de simplă pe atât este de eficientă.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\nÎnţelegerea profundă nu se poate realiza decât prin rezolvarea a cât mai multe probleme. Succes!\r\n\r\n* \'Deque\':problema/deque, _Arhiva educaţională_\r\n* \'Secvenţă\':problema/secventa\r\n* \'Secvenţă 3\':problema/secv3\r\n* \'Secvenţă 4\':problema/secv4\r\n* \'Sum 2\':problema/sum2, _Stelele Informaticii 2003_\r\n* \'Drept 2\':problema/drept2, _Lotul Naţional de Informatică, 2006_\r\n* \'Copaci 2\':problema/copaci2, _.campion_\r\n* \'Brânză\':problema/branza\r\n* \'Struţi\':problema/struti\r\n* \'Trompetă\':problema/trompeta\r\n* \'Buline\':problema/buline\r\n* \'Balans\':problema/balans\r\n* \'Gard\':problema/gard, _ONI 2002_\r\n* \'Ghiozdan\':problema/ghiozdan\r\n* \'Munte4\':problema/munte4, _Lotul Naţional de Informatică, 2005_\r\n* \'Cover\':problema/cover, _ONI 2007, Baraj_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Cosmin Negruşeri, \"_Probleme cu secvenţe_\":probleme-cu-secvente\r\n# Dana Lica, \"_Arbori de intervale şi aplicaţii în geometria computaţională_\":arbori-de-intervale\r\n# Cătălin Frâncu, \"_Heapuri_\":heapuri\r\n# Marius Stroe, \"_Treapuri_\":treapuri\r\n# \'C++ Reference\':http://www.cplusplus.com/',3146,'public',NULL,NULL),('algoritmiada-2009/clasament/runda-3/studenti','Algoritmiada 2009 - Clasament Runda 3, Clasele 5-8','2009-02-05 16:03:23','2009-02-05 16:03:23','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda3-5-8\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-3\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-3/studenti\r\n*(active) \'Rezultate\':algoritmiada-2009/clasament/runda-3/5-8\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\n(htabs)*(active) \'Clasele 5-8\':algoritmiada-2009/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-3/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda3-5-8\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('pd','Programare dinamica','2007-12-04 21:25:10','2009-11-01 17:05:40','h1. Programare dinamica\r\n\r\n(Categoria _Tehnici de programare_, autor _Catalin Tiseanu_)\r\n\r\nPlan de atac (probleme-candidat):\r\n\r\n1. http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en\r\nReducerea complexitatii, transformarea problemei intr-una de construire a unui arbore binar.\r\n\r\n2. http://code.google.com/codejam/contest/dashboard?c=32001#s=p0&a=3\r\n\r\n\r\n3. http://code.google.com/codejam/contest/dashboard?c=32001#s=p3&a=3\r\n\r\n\r\n4. http://code.google.com/codejam/contest/dashboard?c=32015#s=p1&a=1\r\n\r\n\r\n5. http://code.google.com/codejam/contest/dashboard?c=32010#s=p3&a=3\r\n\r\nh2. Sugestii Silviu\r\n\r\n* poate ca nu trebuie sa spunem tot despre programare dinamica intr-un singur articol; spre exemplu putem facem doua articole: PD basic si PD advanced\r\n* cred ca era si ceva prin Cartea lui Francu\' despre programare dinamica; ar merge incorporat (eventual in pd_basic).\r\n\r\nh2. Introducere\r\n\r\nProgramarea dinamică este o metodă utilă pentru a rezolva probleme care pot fi obţinute prin compunerea a mai multor bucăţi, a căror soluţie poate fi apoi determinată optim. Se bazează în principal pe proprietatea unei probleme de a putea fi rezolvată optim dacă se cunosc soluţii optime la sub-problemele ei.\r\nDe menţionat că \'programare\' nu se referă aici la scrierea de cod într-un limbaj de programare, ci la \'programare matematica\', care constă în optimizarea unei funcţii prin alegerea de valori dintr-o mulţime anume. \r\n\r\nScopul acestui articol nu este să ofere o introducere in programare dinamică (pentru aceasta poate fi consultat excelentul tutorial de pe TopCoder \"Dynamic Programming : From novice to advanced\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg). În schimb, acest articol îşi propune să ofere nişte \'smenuri\' mai avansate de rezolvare a problemelor cu programare dinamică. \r\n\r\nh2. Programare dinamică cu reducerea loop-ului interior\r\n\r\nSă considerăm următoarea problema:\r\n\r\nh3(#problema-1). Problema 1: \'Drilling\':http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en\r\n\r\nbq. Se da un şir de $N$ numere naturale $(a{~1~}, a{~2~}, ..., a{~N~})$. Se ştie că un prefix al acestui şir (adică o subsecvenţă de la începutul şirului, posibil nulă) este **defect**. Toate elementele din acel prefix (şi doar din acel prefix) sunt defecte. Se ştie de asemenea că se poate testa orice poziţie $i$ în timp $a{~i~}$ pentru a afla dacă este defectă. Să se determine timpul minim în cazul cel mai defavorabil pentru aflarea lungimii maxime a prefixului şirului care este defect.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(8 24 12 6)$, răspunsul ar fi $42$. Astfel, se testează mai întâi poziţia $2$. Dacă nu este defectă, mai rămâne de testat poziţia $1$. Altfel, în cel mai rău caz mai trebuie testate poziţiile $3$ şi $4$, aducând timpul total la $24 + 12 + 6 = 42$.\r\n\r\nh3. Rezolvare:\r\n\r\nO să începem prin a da altă îmbrăcăminte problemei. Astfel, să ne imaginăm că am construi un arbore binar de căutare pe şirul dat, având drept chei poziţiile din şir, şi drept valori auxiliare valorile poziţiilor respective din şir (un nod cu cheia $i$ va avea valoarea auxiliara $a{~i~}$.\r\nAcum, există mulţi arbori binari de căutare posibile pentru şirul iniţial. Totuşi, să presupunem că am construit unul, pe care îl considerăm de acum ca fixat. Atunci, strategia noastra de testare a elementelor din şir se va desfăşura conforma arborelui. Astfel, testăm mai întâi în poziţia din rădăcină. Dacă poziţia respectivă este defectă, ne ducem în fiul drept. Altfel, mergem in fiul stâng. În ambele cazuri se reia procedeul. Căutarea se termină cand nu mai putem merge într-un fiu. \r\n\r\nSă observăm că dacă considerăm costul unui drum în arbore de la rădăcină la o frunză ca suma valorilor auxiliare din drumul (unic) respectiv, atunci se observă că costul strategiei bazate pe acest arbore este chiar costul maxim al unui drum ! De acum încolo, vom defini costul unui arbore ca costul maxim al unui drum din el. Să exemplificăm pe şirul din exemplu:\r\n\r\n$BAGA POZA$\r\n\r\nSe observă că costul maxim al unui drum este $42$, minim posibil, exact ca răspunsul din exemplu.\r\nDeci, am redus problema la construirea unui arbore binar de căutare, care are costul minim.\r\n\r\nAcum devine clară o primă soluţie folosind programarea dinamică. Astfel, să presupunem că notăm cu @opt[ i ][ j ]@ costul minim al unui arbore construit pe cheile din $[i,j]$ (prin asta notăm (i, i + 1, ..., j). Fie $r[ i ][ j ]$ poziţia rădăcinii arborelui cu costul minim. În cazul existenţei mai multor rădăcini posibile, se alege cea mai din stânga. Cum am putea construi arborele de cost minim pe cheile $[i,j]$ ştiind răspunsul pentru instanţele mai mici (subsecvenţele de lungime mai mică ca $j-i+1$ pe $[i,j]$)? (!) Simplu, arborele de cost minim pe $[i,j]$ se obţine alegând drept rădăcină în mod optim o poziţie $k$, cu <tex>$i \\le k \\le j$</tex>, la care se pune ca fiul stâng arborele optim pentru $[i, k-1]$, şi ca fiu drept arborele optim pentru $[k+1, j]$. Relaţia de recurenţă devine:\r\n\r\n@opt[ i ][ j ]@ = <tex>\\displaystyle\\min_{i \\le k \\le j} \\{a_{k} + \\max( opt[i][k-1], opt[k+1][j] )\\} </tex>   \r\n@r[ i ][ j ]@ = <tex>\\displaystyle\\arg \\min_{i \\le k \\le j}\\{a_{k} + \\max (opt[i][k-1], opt[k+1][j] )\\} </tex> \r\n\r\nAvem @opt[i][j] = 0@, pentru $j < i$.\r\nCazurile de bază sunt @opt[i][i]@ = a{~i~} si @r[i][i] = i@.\r\n\r\nSe observă că răspunsul problemei se află în @opt[1][N]@.\r\nAstfel, am obţinut o soluţie în timp $O(N^3)$.\r\n\r\nAici trebuie remarcată asemănarea acestei probleme cu cea a determinării arborelui de căutare optim, atunci cand se dau probabilităţile relative de căutare a cheilor. Această problemă se numeşte \'Optimal Binary Search Tree\' în literatura de specialitate şi poate fi găsită şi în _Introduction to Algorithms_. În aceasta problemă, se poate aplica o proprietate specială, numită _convexitate_, pentru a reduce complexitatea la $O(N^2)$. Această proprietate reprezintă un concept avansat, care nu se poate aplica în cazul problemei noastre, şi nu va fi discutat în continuare.\r\n\r\nPână acum avem următorul pseudocod pentru calculul recurenţei:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    iniţializează opt şi r\r\n    pentru len = 1, N execută\r\n        pentru i = 1, N - len + 1 execută\r\n            j = i + len - 1;\r\n            opt[i][j] = inf;\r\n            pentru k = i, j execută\r\n                dacă opt[i][j] < a[k] + max(opt[i][k-1], opt[k+1][j]) atunci\r\n                    opt[i][j] = a[k] + max(opt[i][k-1], opt[k+1][j]);\r\n                    r[i][j] = k;\r\n            sfârşit_pentru;\r\n       sfârşit_pentru;\r\n    sfârşit_pentru;\r\n\r\n    return opt[1][N];\r\nSfârşit.\r\n==\r\n\r\nAcum ca să obţinem o complexitate mai bună, ţinând cont şi de numele capitolului, vom încerca să reducem complexitatea loop-ului interior (cel după $k$).\r\n\r\nh3(#problema-2). Problema 2: \'Ugly numbers\':http://code.google.com/codejam/contest/dashboard?c=32015#s=p1&a=1 (Google Code Jam 2008, Round 1C)\r\n\r\nbq. Un număr se numeşte *urât* dacă este divizibil prin oricare dintre numerele prime de o singură cifră, mai exact 2, 3, 5, 7. Se dă un şir de N cifre. Între fiecare 2 cifre consecutive se poate insera unul dintre semnele + sau -. Dacă nu se inserează un semn, cele 2 cifre sunt concatentate astfel încât să se obţină un număr. Pentru un şir dat de cifre si o variantă de a adăuga semne, prin evaluarea expresiei matematice obţinute prin inserarea semnelor se obţine un număr, numit numărul generat. Să se calculeze câte dintre cele 3^N-1^ variante de a insera semnele generează numerele urâte.\r\n\r\nh3. Exemplu: \r\n\r\nPentru cifrele *123456*, expresia *1+234-5+6 = 236* care este număr urât, iar *123+4-56 = 71* nu este număr urât.\r\n\r\nh3. Soluţie:\r\n\r\nObservăm că un număr este urât dacă dă cel puţin o dată restul 0 la împărţirea la numerele 2, 3, 5, 7. O abordare a problemei este parcurgerea tuturor variantelor de inserare şi calcularea celor 4 resturi, verificând dacă cel puţin unul este 0.\r\nVom folosi aritmetica modulară pentru a obţine o soluţie mai eficientă a problemei. Vom împărţi cele 3^N-1^ variante în clase, fiecare clasă reprezentând toate numerele care dau resturile $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ la împărţirea la cele 4 numere. Calculând pentru fiecare clasă numărul de numere generate, rezultatul final va fi suma valorilor calculate pentru toate clasele pentru care cel puţin un rest este egal cu 0. Intuim că putem utiliza clasele de resturi într-o soluţie cu programare dinamică.\r\nVom utiliza şirul auxiliar $V[i][j]$ reprezentând numărul format prin concatenarea cifrelor de pe poziţiile consecutive $i, i+1, ..., j$ din şirul dat, fără inserarea unor semne între cifre. De exemplu, @V[2][4] = 234@. Dacă notăm cu $C[i][r{~2~}][r{~3~}][r{~5~}][r{~7~}]$ numărul de variante formate cu primele *i* cifre pentru care clasa de resturi este $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$. Observăm că orice astfel de variantă se obţine dintr-o variantă cu $j < i$ cifre după care adăugam + sau - apoi concatenăm restul cifrelor până la *i* fără semne. Dacă resturile pentru varianta cu *j* cifre erau $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ atunci resturile pentru varianta nouă sunt:\r\n<tex> $(r_2\', r_3\', r_5\', r_7\') = ((r_2 +/- V[j+1][i])\\% 2, (r_3 +/- V[j+1][i])\\% 3, (r_5 +/- V[j+1][i])\\% 5, (r_7 +/- V[j+1][i])\\% 7)$</tex>. \r\nAtunci numărul total de variante cu *i* cifre este suma după toate valorile *j* ale numerelor de variante cu *j* cifre:\r\n<tex> $C[i][r_2\'][r_3\'][r_5\'][r_7\'] = \\sum_{j<i} C[j][r_2][r_3][r_5][r_7]$ </tex>\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i]\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = V[i][j - 1] + A[i];\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0][0][0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r_2 = 0, 1 execută\r\n            pentru r_3 = 0, 2 execută\r\n                pentru r_5 = 0, 4 execută\r\n                    pentru r_7 = 0, 6 execută\r\n                        C[i][r_2][r_3][r_5][r_7] = 0;\r\n                        pentru j = 0, i - 1 execută\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + 2 - V[j+1][i])%2)][(r_3 + 3 - V[j+1][i])%3)]\r\n                                                                             [(r_5 + 5 - V[j+1][i])%5)][(r_7 + 7 - V[j+1][i])%7)];\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + V[j+1][i])%2)][(r_3 + V[j+1][i])%3)]\r\n                                                                             [(r_5 + V[j+1][i])%5)][(r_7 + V[j+1][i])%7)];\r\n                        sfârşit pentru;\r\n\r\n                        dacă i == N şi (r_2 == 0 sau r_3 == 0 sau r_5 == 0 sau r_7 == 0)\r\n                            S += C[i][r_2][r_3][r_5][r_7]\r\n                        sfârşit pentru;\r\n                    sfârşit pentru;\r\n                sfărşit pentru;\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează S;\r\n==\r\n\r\nO problemă în abordarea precedentă este calcularea matricii V, ale cărei valori devin foarte mari şi ies din precizia tipurilor de date disponibile. O soluţie posibilă este calcularea câte unei matrici de sume modulo R pentru fiecare rest R, adica a 4 matrici V_2, V_3, V_5 si V_7 ale resturilor împărţirii valorilor lui V la cele 4 numere prime. Folosind aritmetica modulară, aceste matrici pot fi calculate direct, fără a calcula V. Altă variantă este utilizarea teoremei chineze a resturilor, prin care un sistem de ecuaţii modulo câteva numere prime între ele poate fi redus la o ecuaţie modulo produsul numerelor date. În cazul nostru, numerele sunt prime, deci putem aplica teorema. Astfel, putem reduce problema resturilor împărţirii la (2, 3, 5, 7) la problema restului împărţirii la 2*3*5*7=210, deci fiecare clasa (r_2, r_3, r_5, r_7) se reduce la un rest R < 210. Modificăm pseudocodul astfel:\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i] % 210\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = (V[i][j - 1] + A[i]) % 210;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r = 0, 209 execută\r\n            C[i][r] = 0;\r\n            pentru j = 0, i - 1 execută\r\n                C[i][r] += C[j][(r + 210 - V[j+1][i]) % 210];\r\n                C[i][r] += C[j][(r + V[j+1][i]) % 210];\r\n            sfârşit pentru;\r\n\r\n            dacă i == N şi (r % 2 == 0 sau r % 3 == 0 sau r % 5 == 0 sau r % 7 == 0)\r\n                S += C[i][r];\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfărşit pentru;\r\n    returnează S;   \r\n==\r\n\r\n\r\nh2. Programare dinamica folosind bitmask\r\n\r\nIn continuare vom vedea un exemplu de programare dinamica unde vom folosi un bitmask (codificat pe un intreg) pentru a tine spatiul starilor.\r\n\r\nAstfel sa presupunem ca avem nevoie sa tinem un vector caracteristic pentru o multime.\r\nDaca cardinalul acesteia este suficient de mic putem folosi un intreg pentru a codifica aceasta informatie astfel:\r\n\r\nFie multimea A = { x{~1~}, x{~2~}, ... x{~n~} }.\r\nAtunci bitmaskul unei partitii a lui A, MASK, va avea bitul i egal cu 1 numai si numai daca x{~i~} apartine partitiei.\r\n\r\nDesigur, aceasta reprezentare duce la o complexitate direct proportionala cu 2 ^card(A)^.\r\n\r\nh3. Exemplu\r\n\r\n\r\nh2. Programare dinamica folosind vectori de numere intregi\r\n\r\nTo be continued ... \r\n\r\n',2996,'public',NULL,NULL),('pd','Programare dinamica','2007-12-04 21:25:10','2009-11-01 16:50:43','h1. Programare dinamica\r\n\r\n(Categoria _Tehnici de programare_, autor _Catalin Tiseanu_)\r\n\r\nPlan de atac (probleme-candidat):\r\n\r\n1. http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en\r\nReducerea complexitatii, transformarea problemei intr-una de construire a unui arbore binar.\r\n\r\n2. http://code.google.com/codejam/contest/dashboard?c=32001#s=p0&a=3\r\n\r\n\r\n3. http://code.google.com/codejam/contest/dashboard?c=32001#s=p3&a=3\r\n\r\n\r\n4. http://code.google.com/codejam/contest/dashboard?c=32015#s=p1&a=1\r\n\r\n\r\n5. http://code.google.com/codejam/contest/dashboard?c=32010#s=p3&a=3\r\n\r\nh2. Sugestii Silviu\r\n\r\n* poate ca nu trebuie sa spunem tot despre programare dinamica intr-un singur articol; spre exemplu putem facem doua articole: PD basic si PD advanced\r\n* cred ca era si ceva prin Cartea lui Francu\' despre programare dinamica; ar merge incorporat (eventual in pd_basic).\r\n\r\nh2. Introducere\r\n\r\nProgramarea dinamică este o metodă utilă pentru a rezolva probleme care pot fi obţinute prin compunerea a mai multor bucăţi, a căror soluţie poate fi apoi determinată optim. Se bazează în principal pe proprietatea unei probleme de a putea fi rezolvată optim dacă se cunosc soluţii optime la sub-problemele ei.\r\nDe menţionat că \'programare\' nu se referă aici la scrierea de cod într-un limbaj de programare, ci la \'programare matematica\', care constă în optimizarea unei funcţii prin alegerea de valori dintr-o mulţime anume. \r\n\r\nScopul acestui articol nu este să ofere o introducere in programare dinamică (pentru aceasta poate fi consultat excelentul tutorial de pe TopCoder \"Dynamic Programming : From novice to advanced\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg). În schimb, acest articol îşi propune să ofere nişte \'smenuri\' mai avansate de rezolvare a problemelor cu programare dinamică. \r\n\r\nh2. Programare dinamică cu reducerea loop-ului interior\r\n\r\nSă considerăm următoarea problema:\r\n\r\nh3(#problema-1). Problema 1: \'Drilling\':http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en\r\n\r\nbq. Se da un şir de $N$ numere naturale $(a{~1~}, a{~2~}, ..., a{~N~})$. Se ştie că un prefix al acestui şir (adică o subsecvenţă de la începutul şirului, posibil nulă) este **defect**. Toate elementele din acel prefix (şi doar din acel prefix) sunt defecte. Se ştie de asemenea că se poate testa orice poziţie $i$ în timp $a{~i~}$ pentru a afla dacă este defectă. Să se determine timpul minim în cazul cel mai defavorabil pentru aflarea lungimii maxime a prefixului şirului care este defect.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(8 24 12 6)$, răspunsul ar fi $42$. Astfel, se testează mai întâi poziţia $2$. Dacă nu este defectă, mai rămâne de testat poziţia $1$. Altfel, în cel mai rău caz mai trebuie testate poziţiile $3$ şi $4$, aducând timpul total la $24 + 12 + 6 = 42$.\r\n\r\nh3. Rezolvare:\r\n\r\nO să începem prin a da altă îmbrăcăminte problemei. Astfel, să ne imaginăm că am construi un arbore binar de căutare pe şirul dat, având drept chei poziţiile din şir, şi drept valori auxiliare valorile poziţiilor respective din şir (un nod cu cheia $i$ va avea valoarea auxiliara $a{~i~}$.\r\nAcum, există mulţi arbori binari de căutare posibile pentru şirul iniţial. Totuşi, să presupunem că am construit unul, pe care îl considerăm de acum ca fixat. Atunci, strategia noastra de testare a elementelor din şir se va desfăşura conforma arborelui. Astfel, testăm mai întâi în poziţia din rădăcină. Dacă poziţia respectivă este defectă, ne ducem în fiul drept. Altfel, mergem in fiul stâng. În ambele cazuri se reia procedeul. Căutarea se termină cand nu mai putem merge într-un fiu. \r\n\r\nSă observăm că dacă considerăm costul unui drum în arbore de la rădăcină la o frunză ca suma valorilor auxiliare din drumul (unic) respectiv, atunci se observă că costul strategiei bazate pe acest arbore este chiar costul maxim al unui drum ! De acum încolo, vom defini costul unui arbore ca costul maxim al unui drum din el. Să exemplificăm pe şirul din exemplu:\r\n\r\n$BAGA POZA$\r\n\r\nSe observă că costul maxim al unui drum este $42$, minim posibil, exact ca răspunsul din exemplu.\r\nDeci, am redus problema la construirea unui arbore binar de căutare, care are costul minim.\r\n\r\nAcum devine clară o primă soluţie folosind programarea dinamică. Astfel, să presupunem că notăm cu @opt[ i ][ j ]@ costul minim al unui arbore construit pe cheile din $[i,j]$ (prin asta notăm (i, i + 1, ..., j). Fie $r[ i ][ j ]$ poziţia rădăcinii arborelui cu costul minim. În cazul existenţei mai multor rădăcini posibile, se alege cea mai din stânga. Cum am putea construi arborele de cost minim pe cheile $[i,j]$ ştiind răspunsul pentru instanţele mai mici (subsecvenţele de lungime mai mică ca $j-i+1$ pe $[i,j]$)? (!) Simplu, arborele de cost minim pe $[i,j]$ se obţine alegând drept rădăcină în mod optim o poziţie $k$, cu <tex>$i \\le k \\le j$</tex>, la care se pune ca fiul stâng arborele optim pentru $[i, k-1]$, şi ca fiu drept arborele optim pentru $[k+1, j]$. Relaţia de recurenţă devine:\r\n\r\n@opt[ i ][ j ]@ = <tex>\\displaystyle\\min_{i \\le k \\le j} \\{a_{k} + \\max( opt[i][k-1], opt[k+1][j] )\\} </tex>   \r\n@r[ i ][ j ]@ = <tex>\\displaystyle\\arg \\min_{i \\le k \\le j}\\{a_{k} + \\max (opt[i][k-1], opt[k+1][j] )\\} </tex> \r\n\r\nAvem @opt[i][j] = 0@, pentru $j < i$.\r\nCazurile de bază sunt @opt[i][i]@ = a{~i~} si @r[i][i] = i@.\r\n\r\nSe observă că răspunsul problemei se află în @opt[1][N]@.\r\nAstfel, am obţinut o soluţie în timp $O(N^3)$.\r\n\r\nAici trebuie remarcată asemănarea acestei probleme cu cea a determinării arborelui de căutare optim, atunci cand se dau probabilităţile relative de căutare a cheilor. Această problemă se numeşte \'Optimal Binary Search Tree\' în literatura de specialitate şi poate fi găsită şi în _Introduction to Algorithms_. În aceasta problemă, se poate aplica o proprietate specială, numită _convexitate_, pentru a reduce complexitatea la $O(N^2)$. Această proprietate reprezintă un concept avansat, care nu se poate aplica în cazul problemei noastre, şi nu va fi discutat în continuare.\r\n\r\nPână acum avem următorul pseudocod pentru calculul recurenţei:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    iniţializează opt şi r\r\n    pentru len = 1, N execută\r\n        pentru i = 1, N - len + 1 execută\r\n            j = i + len - 1;\r\n            opt[i][j] = inf;\r\n            pentru k = i, j execută\r\n                dacă opt[i][j] < a[k] + max(opt[i][k-1], opt[k+1][j]) atunci\r\n                    opt[i][j] = a[k] + max(opt[i][k-1], opt[k+1][j]);\r\n                    r[i][j] = k;\r\n            sfârşit_pentru;\r\n       sfârşit_pentru;\r\n    sfârşit_pentru;\r\n\r\n    return opt[1][N];\r\nSfârşit.\r\n==\r\n\r\nAcum ca să obţinem o complexitate mai bună, ţinând cont şi de numele capitolului, vom încerca să reducem complexitatea loop-ului interior (cel după $k$).\r\n\r\nh3(#problema-2). Problema 2: \'Ugly numbers\':http://code.google.com/codejam/contest/dashboard?c=32015#s=p1&a=1 (Google Code Jam 2008, Round 1C)\r\n\r\nbq. Un număr se numeşte *urât* dacă este divizibil prin oricare dintre numerele prime de o singură cifră, mai exact 2, 3, 5, 7. Se dă un şir de N cifre. Între fiecare 2 cifre consecutive se poate insera unul dintre semnele + sau -. Dacă nu se inserează un semn, cele 2 cifre sunt concatentate astfel încât să se obţină un număr. Pentru un şir dat de cifre si o variantă de a adăuga semne, prin evaluarea expresiei matematice obţinute prin inserarea semnelor se obţine un număr, numit numărul generat. Să se calculeze câte dintre cele 3^N-1^ variante de a insera semnele generează numerele urâte.\r\n\r\nh3. Exemplu: \r\n\r\nPentru cifrele *123456*, expresia *1+234-5+6 = 236* care este număr urât, iar *123+4-56 = 71* nu este număr urât.\r\n\r\nh3. Soluţie:\r\n\r\nObservăm că un număr este urât dacă dă cel puţin o dată restul 0 la împărţirea la numerele 2, 3, 5, 7. O abordare a problemei este parcurgerea tuturor variantelor de inserare şi calcularea celor 4 resturi, verificând dacă cel puţin unul este 0.\r\nVom folosi aritmetica modulară pentru a obţine o soluţie mai eficientă a problemei. Vom împărţi cele 3^N-1^ variante în clase, fiecare clasă reprezentând toate numerele care dau resturile @(r~2~, r~3~, r~5~, r~7~)@ la împărţirea la cele 4 numere. Calculând pentru fiecare clasă numărul de numere generate, rezultatul final va fi suma valorilor calculate pentru toate clasele pentru care cel puţin un rest este egal cu 0. Intuim că putem utiliza clasele de resturi într-o soluţie cu programare dinamică.\r\nVom utiliza şirul auxiliar @V[i][j]@ reprezentând numărul format prin concatenarea cifrelor de pe poziţiile consecutive @i, i+1, ..., j@ din şirul dat, fără inserarea unor semne între cifre. De exemplu, @V[2][4] = 234@. Dacă notăm cu @C[i][r~2~][r~3~][r~5~][r~7~]@ numărul de variante formate cu primele i cifre pentru care clasa de resturi este @(r~2~, r~3~, r~5~, r~7~)@. Observăm că orice astfel de variantă se obţine dintr-o variantă cu j < i cifre după care adăugam + sau - apoi concatenăm restul cifrelor până la i fără semne. Dacă resturile pentru varianta cu j cifre erau (r_2, r_3, r_5, r_7) atunci resturile pentru varianta nouă sunt (r\'_2, r\'_3, r\'_5, r\'_7) = ((r_2 +/- V[j+1][i])%2, (r_3 +/- V[j+1][i])%3, (r_5 +/- V[j+1][i])%5, (r_7 +/- V[j+1][i])%7). Atunci numărul total de variante cu i cifre este suma după toate valorile j ale numerelor de variante cu j cifre.\r\nC[i][r\'_2][r\'_3][r\'_5][r\'_7] = sum_{j<i} C[j][r_2][r_3][r_5][r_7]\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i]\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = V[i][j - 1] + A[i];\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0][0][0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r_2 = 0, 1 execută\r\n            pentru r_3 = 0, 2 execută\r\n                pentru r_5 = 0, 4 execută\r\n                    pentru r_7 = 0, 6 execută\r\n                        C[i][r_2][r_3][r_5][r_7] = 0;\r\n                        pentru j = 0, i - 1 execută\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + 2 - V[j+1][i])%2)][(r_3 + 3 - V[j+1][i])%3)]\r\n                                                                             [(r_5 + 5 - V[j+1][i])%5)][(r_7 + 7 - V[j+1][i])%7)];\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + V[j+1][i])%2)][(r_3 + V[j+1][i])%3)]\r\n                                                                             [(r_5 + V[j+1][i])%5)][(r_7 + V[j+1][i])%7)];\r\n                        sfârşit pentru;\r\n\r\n                        dacă i == N şi (r_2 == 0 sau r_3 == 0 sau r_5 == 0 sau r_7 == 0)\r\n                            S += C[i][r_2][r_3][r_5][r_7]\r\n                        sfârşit pentru;\r\n                    sfârşit pentru;\r\n                sfărşit pentru;\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează S;\r\n==\r\n\r\nO problemă în abordarea precedentă este calcularea matricii V, ale cărei valori devin foarte mari şi ies din precizia tipurilor de date disponibile. O soluţie posibilă este calcularea câte unei matrici de sume modulo R pentru fiecare rest R, adica a 4 matrici V_2, V_3, V_5 si V_7 ale resturilor împărţirii valorilor lui V la cele 4 numere prime. Folosind aritmetica modulară, aceste matrici pot fi calculate direct, fără a calcula V. Altă variantă este utilizarea teoremei chineze a resturilor, prin care un sistem de ecuaţii modulo câteva numere prime între ele poate fi redus la o ecuaţie modulo produsul numerelor date. În cazul nostru, numerele sunt prime, deci putem aplica teorema. Astfel, putem reduce problema resturilor împărţirii la (2, 3, 5, 7) la problema restului împărţirii la 2*3*5*7=210, deci fiecare clasa (r_2, r_3, r_5, r_7) se reduce la un rest R < 210. Modificăm pseudocodul astfel:\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i] % 210\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = (V[i][j - 1] + A[i]) % 210;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r = 0, 209 execută\r\n            C[i][r] = 0;\r\n            pentru j = 0, i - 1 execută\r\n                C[i][r] += C[j][(r + 210 - V[j+1][i]) % 210];\r\n                C[i][r] += C[j][(r + V[j+1][i]) % 210];\r\n            sfârşit pentru;\r\n\r\n            dacă i == N şi (r % 2 == 0 sau r % 3 == 0 sau r % 5 == 0 sau r % 7 == 0)\r\n                S += C[i][r];\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfărşit pentru;\r\n    returnează S;   \r\n==\r\n\r\n\r\nh2. Programare dinamica folosind bitmask\r\n\r\nIn continuare vom vedea un exemplu de programare dinamica unde vom folosi un bitmask (codificat pe un intreg) pentru a tine spatiul starilor.\r\n\r\nAstfel sa presupunem ca avem nevoie sa tinem un vector caracteristic pentru o multime.\r\nDaca cardinalul acesteia este suficient de mic putem folosi un intreg pentru a codifica aceasta informatie astfel:\r\n\r\nFie multimea A = { x{~1~}, x{~2~}, ... x{~n~} }.\r\nAtunci bitmaskul unei partitii a lui A, MASK, va avea bitul i egal cu 1 numai si numai daca x{~i~} apartine partitiei.\r\n\r\nDesigur, aceasta reprezentare duce la o complexitate direct proportionala cu 2 ^card(A)^.\r\n\r\nh3. Exemplu\r\n\r\n\r\nh2. Programare dinamica folosind vectori de numere intregi\r\n\r\nTo be continued ... \r\n\r\n',2996,'public',NULL,NULL),('planificare/camp-2.2.1','Coding Camp \"A New Day\"','2009-02-01 22:33:19','2009-02-08 16:10:56','h1. Coding Camp _\"A New Day\"_\r\n\r\nNe intalnim in weekend-ul *28 februarie-1 martie 2009* la ...\r\n\r\nScopul final al coding camp-ului este lansarea versiunii \'*infoarena 2.2.1*\':http://hackers.devnet.ro/milestone/2.2.1%20A%20New%20Day.\r\n\r\nh2. Locatie\r\n\r\n...\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu Linux (preferabil Ubuntu) instalat pe el\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri\r\n\r\nh2. Participanti\r\n\r\nSpecifica cand poti veni si cat poti sta.\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"alexthero\" type=\"tiny\")==: de acasa - tot weekend-ul\r\n\r\nh2. Agenda\r\n\r\nh3. Must have\r\n\r\n|_. Task|_. Estimare de timp |\r\n| \'Comentarii la orice pagina ca la blog\':http://hackers.devnet.ro/ticket/362 | ? |\r\n| Reorganizat sidebar si topnav | ? |\r\n| Script de backup | ? |\r\n| \'Virtual Contests\':propuneri/10-virtual-contest | ? |\r\n| \'Sistem de monitorizare\':http://hackers.devnet.ro/ticket/179 | ? |\r\n| \'Pagina de submit desteapta\':http://hackers.devnet.ro/ticket/366 | ? |\r\n\r\n\r\nh3. Nice to have\r\n\r\n|_. Task|_. Estimare de timp |\r\n| \'Run YSlow and improve performance\':http://hackers.devnet.ro/ticket/351 | ? |\r\n| \'Interfata de updatat rating-uri\':http://hackers.devnet.ro/ticket/239 | ? |\r\n| \'Permisiuni in pagina de changes\':http://hackers.devnet.ro/ticket/363 | ? |\r\n| \'Scoruri detaliate\':http://hackers.devnet.ro/ticket/263 | ? |\r\n| \'Sterge o revizie\':http://hackers.devnet.ro/ticket/132 | ? |\r\n| \'Pagina de changes mai detaliata\':http://hackers.devnet.ro/ticket/155 | ? |\r\n\r\nh3. Others\r\n\r\n|_. Task|_. Estimare de timp |\r\n| \'Grafice rating\':http://hackers.devnet.ro/ticket/263 | ? |\r\n| \'Optimizat diff-ul\':http://hackers.devnet.ro/ticket/360 | ? |\r\n',716,'public',NULL,NULL),('implica-te/arhiva-educationala','Arhiva Educationala','2008-02-23 13:13:01','2009-02-08 18:31:31','h1. Arhiva educationala ==Stars(rating=\"5\")==\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie. Mai multe despre acest proiect gasiti \'aici\':propuneri/6-arhiva-educationala.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Cum ne poti ajuta?\':implica-te/arhiva-educationala#cum\r\n* \'Echipa implicata in proiect\':implica-te/arhiva-educationala#echipa\r\n* \'Documentatie\':implica-te/arhiva-educationala#documentatie\r\n* \'Continutul arhivei\':implica-te/arhiva-educationala#probleme\r\n\r\nh2(#cum). Cum ne poti ajuta?\r\n\r\n1. Ofera sugestii la dezvoltarea proiectului.\r\n2. Contribuie cu feedback pentru a imbunatati calitatea problemelor existente.\r\n3. Vino cu idei pentru probleme noi.\r\nAjuta si tu la randul tau comunitatea infoarena! \r\n\r\nh2(#echipa). Echipa implicata in proiect\r\n\r\nMomentan, pentru a obtine o eficienta mai buna, recrutarea voluntarilor pentru dezvoltarea arhivei educationale a fost oprita. Echipa care este implicata activ in proiect este alcatuita din:\r\n\r\n* == user(user=\"pauldb\" type=\"tiny\") == (coordonator de proiect)\r\n* == user(user=\"marius\" type=\"tiny\") ==\r\n* == user(user=\"amadaeus\" type=\"tiny\") ==\r\n\r\nMultumim celor care ne-au ajutat pana acum:\r\n\r\n* == user(user=\"filipb\" type=\"tiny\") == (fost coordonator de proiect)\r\n* == user(user=\"devilkind\" type=\"tiny\") ==\r\n* == user(user=\"mariusdrg\" type=\"tiny\") ==\r\n* == user(user=\"bogdan2412\" type=\"tiny\") ==\r\n* == user(user=\"cezarmocan\" type=\"tiny\") ==\r\n* == user(user=\"Florian\" type=\"tiny\") ==\r\n* == user(user=\"gabitzish1\" type=\"tiny\") ==\r\n* == user(user=\"Tabara\" type=\"tiny\") ==\r\n* == user(user=\"Dastas\" type=\"tiny\") ==\r\n* == user(user=\"fireatmyself\" type=\"tiny\") ==\r\n* == user(user=\"cos_min\" type=\"tiny\") ==\r\n* == user(user=\"tudalex\" type=\"tiny\") ==\r\n* == user(user=\"sima_cotizo\" type=\"tiny\") ==\r\n* == user(user=\"toni2007\" type=\"tiny\") ==\r\n* == user(user=\"tm_radu\" type=\"tiny\") ==\r\n* == user(user=\"GavrilaVlad\" type=\"tiny\") ==\r\n* == user(user=\"savim\" type=\"tiny\") ==\r\n* == user(user=\"floringh06\" type=\"tiny\") ==\r\n\r\nh2(#documentatie). Documentatie\r\n\r\nFiecare voluntar are obligatia sa citeasca urmatoarele materiale inainte de a putea trece efectiv la lucru:\r\n\r\n* \'Editare de probleme\':documentatie/editare-de-probleme\r\n* \'Ghid evaluator\':documentatie/ghid-evaluator\r\n* \'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala\r\n\r\nh2(#probleme). Continutul arhivei\r\n\r\nIn tabelul de mai jos se afla probleme la care se lucreaza in momentul de fata. Finalizarea lor reprezinta unul dintre $KR$-urile din trimestrul I, 2009. Pentru a va familiariza si cu restul obiectivelor din acest trimestru, cititi \'aici\':okr.\r\n\r\ntable(example). |_. Denumire problema|_. Voluntar|_. Finalizat|\r\n| Lant hamiltonian | == user(user=\"pauldb\" type=\"tiny\") == | |\r\n| Lowest Common Ancestor | == user(user=\"pauldb\" type=\"tiny\") == | |\r\n| Algoritmul Bellman-Ford | == user(user=\"pauldb\" type=\"tiny\") == | |\r\n\r\n\r\nIn tabelul de mai jos se afla sugestii privind algoritmii care trebuie sa se gaseasca sub forma de probleme in arhiva educationala. Puteti veni oricand cu propuneri si sugestii de probleme noi pe \"forum\":/forum/index.php?topic=3401.0.\r\n\r\ntable(example). |_. Denumire problema|_. Categoria|\r\n|Algoritmul lui Gauss|Matematica|\r\n|Principiul includerii si excluderii|Matematica|\r\n|Submultimi|Backtracking|\r\n|Knapsack|Programare dinamica|\r\n|Subsecventa de suma maxima|Programare dinamica|\r\n|Parantezare optima|Programare dinamica|\r\n|Cuplaj maxim de cost minim|Algoritmi pe grafuri|\r\n|Lowest Common Ancestor|Algoritmi pe grafuri|\r\n|Algoritmul Stoer-Wagner|Algoritmi pe grafuri|\r\n|Coduri Huffman|Algoritmi pe grafuri|\r\n|Arbore -> cod Prufer|Algoritmi pe grafuri|\r\n|Cod Prufer -> arbore|Algoritmi pe grafuri|\r\n|Siruri de sufixe|Siruri de caractere|\r\n|Arbori de sufixe|Siruri de caractere|\r\n|Automate - Aho Corasick|Siruri de caractere|\r\n|Arbori de intervale aplicatie 1|Structuri de date|\r\n|Arbori de intervale aplicatie 2|Structuri de date|\r\n|Arbori de intervale aplicatie 3|Structuri de date|\r\n|Arbori de intervale aplicatie 4|Structuri de date|\r\n|Algoritmi {$O(sqrtN)$}|Structuri de date|\r\n|Ortogonal Range Search|Structuri de date|\r\n|Treapuri|Structuri de date|\r\n|Intersectia a doua drepte|Geometrie|\r\n|Aria unui poligon|Geometrie|\r\n|Punct in poligon|Geometrie|\r\n|Punct in poligon convex|Geometrie|\r\n|Diagrame Voronoi|Geometrie|\r\n|Distanta minima intre doua puncte in plan|Geometrie|\r\n|Distanta maxima intre doua puncte in plan|Geometrie|\r\n|Minimum enclosing circle|Geometrie|\r\n|NIM|Jocuri|\r\n|Sprague-Grundy|Jocuri|\r\n|Statistici de ordine|Diverse|\r\n|Operatii pe numere mari|Diverse|\r\n|Soratare prin numarare|Diverse|\r\n|RadixSort|Diverse|\r\n|Interclasare a doua siruri sortate|Diverse|\r\n\r\n',1792,'protected',NULL,NULL),('implica-te/arhiva-educationala','Arhiva Educationala','2008-02-23 13:13:01','2009-02-08 18:42:31','h1. Arhiva educationala ==Stars(rating=\"5\")==\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie. Mai multe despre acest proiect gasiti \'aici\':propuneri/6-arhiva-educationala.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Cum ne poti ajuta?\':implica-te/arhiva-educationala#cum\r\n* \'Echipa implicata in proiect\':implica-te/arhiva-educationala#echipa\r\n* \'Documentatie\':implica-te/arhiva-educationala#documentatie\r\n* \'Continutul arhivei\':implica-te/arhiva-educationala#probleme\r\n\r\nh2(#cum). Cum ne poti ajuta?\r\n\r\n1. Ofera sugestii la dezvoltarea proiectului.\r\n2. Contribuie cu feedback pentru a imbunatati calitatea problemelor existente.\r\n3. Vino cu idei pentru probleme noi.\r\nAjuta si tu la randul tau comunitatea infoarena! \r\n\r\nh2(#echipa). Echipa implicata in proiect\r\n\r\nMomentan, pentru a obtine o eficienta mai buna, recrutarea voluntarilor pentru dezvoltarea arhivei educationale a fost oprita. Echipa care este implicata activ in proiect este alcatuita din:\r\n\r\n* == user(user=\"pauldb\" type=\"tiny\") == (coordonator de proiect)\r\n* == user(user=\"marius\" type=\"tiny\") ==\r\n* == user(user=\"amadaeus\" type=\"tiny\") ==\r\n* == user(user=\"sima_cotizo\" type=\"tiny\") ==\r\n\r\nMultumim celor care ne-au ajutat pana acum:\r\n\r\n* == user(user=\"filipb\" type=\"tiny\") == (fost coordonator de proiect)\r\n* == user(user=\"devilkind\" type=\"tiny\") ==\r\n* == user(user=\"mariusdrg\" type=\"tiny\") ==\r\n* == user(user=\"bogdan2412\" type=\"tiny\") ==\r\n* == user(user=\"cezarmocan\" type=\"tiny\") ==\r\n* == user(user=\"Florian\" type=\"tiny\") ==\r\n* == user(user=\"gabitzish1\" type=\"tiny\") ==\r\n* == user(user=\"Tabara\" type=\"tiny\") ==\r\n* == user(user=\"Dastas\" type=\"tiny\") ==\r\n* == user(user=\"fireatmyself\" type=\"tiny\") ==\r\n* == user(user=\"cos_min\" type=\"tiny\") ==\r\n* == user(user=\"tudalex\" type=\"tiny\") ==\r\n* == user(user=\"sima_cotizo\" type=\"tiny\") ==\r\n* == user(user=\"toni2007\" type=\"tiny\") ==\r\n* == user(user=\"tm_radu\" type=\"tiny\") ==\r\n* == user(user=\"GavrilaVlad\" type=\"tiny\") ==\r\n* == user(user=\"savim\" type=\"tiny\") ==\r\n* == user(user=\"floringh06\" type=\"tiny\") ==\r\n\r\nh2(#documentatie). Documentatie\r\n\r\nFiecare voluntar are obligatia sa citeasca urmatoarele materiale inainte de a putea trece efectiv la lucru:\r\n\r\n* \'Editare de probleme\':documentatie/editare-de-probleme\r\n* \'Ghid evaluator\':documentatie/ghid-evaluator\r\n* \'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala\r\n\r\nh2(#probleme). Continutul arhivei\r\n\r\nIn tabelul de mai jos se afla probleme la care se lucreaza in momentul de fata. Finalizarea lor reprezinta unul dintre $KR$-urile din trimestrul I, 2009. Pentru a va familiariza si cu restul obiectivelor din acest trimestru, cititi \'aici\':okr.\r\n\r\ntable(example). |_. Denumire problema|_. Voluntar|_. Finalizat|\r\n| Lant hamiltonian | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Lowest Common Ancestor | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Algoritmul Bellman-Ford | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n\r\n\r\nIn tabelul de mai jos se afla sugestii privind algoritmii care trebuie sa se gaseasca sub forma de probleme in arhiva educationala. Puteti veni oricand cu propuneri si sugestii de probleme noi pe \"forum\":/forum/index.php?topic=3401.0.\r\n\r\ntable(example). |_. Denumire problema|_. Categoria|\r\n|Algoritmul lui Gauss|Matematica|\r\n|Principiul includerii si excluderii|Matematica|\r\n|Submultimi|Backtracking|\r\n|Knapsack|Programare dinamica|\r\n|Subsecventa de suma maxima|Programare dinamica|\r\n|Parantezare optima|Programare dinamica|\r\n|Cuplaj maxim de cost minim|Algoritmi pe grafuri|\r\n|2SAT|Algoritmi pe grafuri|\r\n|Algoritmul Stoer-Wagner|Algoritmi pe grafuri|\r\n|Heavy Path Decomposition|Algoritmi pe grafuri|\r\n|Coduri Huffman|Algoritmi pe grafuri|\r\n|Arbore -> cod Prufer|Algoritmi pe grafuri|\r\n|Cod Prufer -> arbore|Algoritmi pe grafuri|\r\n|Siruri de sufixe|Siruri de caractere|\r\n|Arbori de sufixe|Siruri de caractere|\r\n|Automate - Aho Corasick|Siruri de caractere|\r\n|Arbori de intervale aplicatie 1|Structuri de date|\r\n|Arbori de intervale aplicatie 2|Structuri de date|\r\n|Arbori de intervale aplicatie 3|Structuri de date|\r\n|Arbori de intervale aplicatie 4|Structuri de date|\r\n|Algoritmi {$O(sqrtN)$}|Structuri de date|\r\n|Ortogonal Range Search|Structuri de date|\r\n|Treapuri|Structuri de date|\r\n|Intersectia a doua drepte|Geometrie|\r\n|Aria unui poligon|Geometrie|\r\n|Punct in poligon|Geometrie|\r\n|Punct in poligon convex|Geometrie|\r\n|Diagrame Voronoi|Geometrie|\r\n|Distanta minima intre doua puncte in plan|Geometrie|\r\n|Distanta maxima intre doua puncte in plan|Geometrie|\r\n|Minimum enclosing circle|Geometrie|\r\n|NIM|Jocuri|\r\n|Sprague-Grundy|Jocuri|\r\n|Statistici de ordine|Diverse|\r\n|Operatii pe numere mari|Diverse|\r\n|Soratare prin numarare|Diverse|\r\n|RadixSort|Diverse|\r\n|Interclasare a doua siruri sortate|Diverse|\r\n\r\n',1792,'protected',NULL,NULL),('planificare/camp-2.2.1','Coding Camp \"A New Day\"','2009-02-01 22:33:19','2009-02-08 18:00:15','h1. Coding Camp _\"A New Day\"_\r\n\r\nNe intalnim in weekend-ul *28 februarie-1 martie 2009* la ...\r\n\r\nScopul final al coding camp-ului este lansarea versiunii \'*infoarena 2.2.1*\':http://hackers.devnet.ro/milestone/2.2.1%20A%20New%20Day.\r\n\r\nh2. Locatie\r\n\r\n...\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu Linux (preferabil Ubuntu) instalat pe el\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri\r\n\r\nh2. Participanti\r\n\r\nSpecifica cand poti veni si cat poti sta.\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"alexthero\" type=\"tiny\")==: de acasa - tot weekend-ul\r\n* ==user(user=\"wickedman\" type=\"tiny\")==: tot weekend-ul\r\n\r\nh2. Agenda\r\n\r\nh3. Must have\r\n\r\n|_. Task|_. Estimare de timp |\r\n| \'Comentarii la orice pagina ca la blog\':http://hackers.devnet.ro/ticket/362 | ? |\r\n| Reorganizat sidebar si topnav | ? |\r\n| Script de backup | ? |\r\n| \'Virtual Contests\':propuneri/10-virtual-contest | ? |\r\n| \'Sistem de monitorizare\':http://hackers.devnet.ro/ticket/179 | ? |\r\n| \'Pagina de submit desteapta\':http://hackers.devnet.ro/ticket/366 | ? |\r\n| Tagging pentru probleme | ? |\r\n\r\nh3. Nice to have\r\n\r\n|_. Task|_. Estimare de timp |\r\n| \'Run YSlow and improve performance\':http://hackers.devnet.ro/ticket/351 | ? |\r\n| \'Interfata de updatat rating-uri\':http://hackers.devnet.ro/ticket/239 | ? |\r\n| \'Permisiuni in pagina de changes\':http://hackers.devnet.ro/ticket/363 | ? |\r\n| \'Scoruri detaliate\':http://hackers.devnet.ro/ticket/263 | ? |\r\n| \'Sterge o revizie\':http://hackers.devnet.ro/ticket/132 | ? |\r\n| \'Pagina de changes mai detaliata\':http://hackers.devnet.ro/ticket/155 | ? |\r\n\r\nh3. Others\r\n\r\n|_. Task|_. Estimare de timp |\r\n| \'Grafice rating\':http://hackers.devnet.ro/ticket/263 | ? |\r\n| \'Optimizat diff-ul\':http://hackers.devnet.ro/ticket/360 | ? |\r\n',13,'public',NULL,NULL),('deque-si-aplicatii','Deque și aplicații','2009-01-22 22:28:12','2009-02-09 10:13:33','h1. Deque şi aplicaţii\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'_Introducere_\':deque-si-aplicatii#introducere\r\n* \'_Aplicaţii:_\':deque-si-aplicatii#problema-1\r\n** \'1. Book Pile &#40;SGU&#41;\':deque-si-aplicatii#problema-1\r\n** \'2. Vila 2 &#40;.campion&#41;\':deque-si-aplicatii#problema-2\r\n** \'3. Şir\':deque-si-aplicatii#problema-3\r\n** \'4. Trans &#40;ONI 2004&#41;\':deque-si-aplicatii#problema-4\r\n** \'5. Otilia &#40;.campion&#41;\':deque-si-aplicatii#problema-5\r\n** \'6. Bcrc &#40;Stelele Informaticii&#41;\':deque-si-aplicatii#problema-6\r\n** \'7. Cut the Sequence &#40;PKU&#41;\':deque-si-aplicatii#problema-7\r\n* \'_Concluzii_\':deque-si-aplicatii#concluzii\r\n* \'_Probleme suplimentare_\':deque-si-aplicatii#probleme-suplimentare\r\n* \'_Bibliografie_\':deque-si-aplicatii#bibliografie\r\n\r\nÎn acest articol voi prezenta o structură de date de tip listă numită _deque_. Simplitatea acestei structuri poate că nu are multe de spus iar din acest motiv am prezentat şi o serie de aplicaţii care vor arăta surprinzătoarea sa utilitate în locurile unde am fi crezut că nu se mai poate face nimic pentru a reduce complexitatea.\r\n\r\nh2(#introducere). Introducere\r\n\r\nStructura de _deque_ (pronunţat de obicei _deck_) poate fi privit ca o colecţie de tip listă ce are două capete prin care se şterg sau inserează noi elemente. În literatura de specialitate aceste capete se numesc _head_ şi _tail_, iar dequeul mai este recunoscut şi ca fiind o coadă cu două capete _(double ended queue)_.\r\n\r\nImplementarea unui deque se poate face cu liste dublu înlănţuite ori cu un vector static când se cunoaşte numărul elementelor din colecţie. Ce trebuie reţinut este că limbajul C++ pune la dispoziţia utilizatorilor prin intermediul headerului _#include <deque>_ containerul \'_std::deque_\':http://www.cplusplus.com/reference/stl/deque/.\r\n\r\nh3(#operatii). Operaţii:\r\n\r\nMai jos sunt enumerate operaţiile care pot fi efectuate asupra unui deque împreună cu corespondentul lor în limbajul C++:\r\n\r\n* _front()_:	    întoarce primul element;\r\n* _back()_:	    întoarce ultimul element;\r\n* _push_front()_: inserează un element în faţă;\r\n* _push_back()_:  inserează un element în spate;\r\n* _pop_front()_:  scoate primul element;\r\n* _pop_back()_:   scoate ultimul element;\r\n* _empty()_:      întoarce _true_ dacă în deque nu se găseşte niciun element şi _false_ în caz contrar.\r\n\r\np=. !deque-si-aplicatii?new_deque.png 75%!\r\n\r\nToate aceste operaţii se execută în timp $O(1)$ \'amortizat\':http://en.wikipedia.org/wiki/Amortized_analysis. Pentru un plus de viteză va trebui să folosim un vector static cu dimensiunea egală cu numărul maxim de elemente ce pot trece prin deque, iar operaţiile implementate „de mână”, cu doi indecşi ce indică către head şi tail. Însă, în majoritatea aplicaţiilor limita de timp permite folosirea lejerităţii şi siguranţei clasei _std::deque_.\r\n\r\nÎn multe aplicaţii unde soluţiile parţiale se reprezintă sub forma unui şir continuu de valori care permite inserarea şi ştergerea doar pe la capete se poate folosi un deque. În general, se fac inserări pe la un capăt şi ştergeri pe la celălalt. Să urmărim în continuare cazuri concrete în care simplitatea unui deque duce la soluţii de multe ori optime şi implementări foarte scurte şi clare.\r\n\r\nh2(#problema-1). \'1. Book Pile\':http://acm.sgu.ru/problem.php?contest=0&problem=271 (SGU)\r\n\r\nbq. Se dau $N$ cărţi aşezate una deasupra celeilalte asupra cărora se vor efecta $M$ operaţii de două tipuri: 1. $ADD${$(nume)$} : se adaugă cartea $nume$ deasupra celorlalte; 2. $ROTATE$ : primele $K$ cărţi de deasupra se rotesc (dacă sunt mai puţin de $K$ cărţi atunci se vor roti toate). Se cere să se afişeze cărţile în ordine, prima fiind cea de deasupra, după efectuarea celor $M$ operaţii.\r\nRestricţii: $0 &le; N, K &le; 40 000$, $0 &le; M &le; 100 000$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se poate deduce urmând paşii următori. Să presupunem că avem cărţile $A B C$ iniţial şi $K = 3$. Dacă îl vom adăuga pe $D$, atunci nu vor rămâne importante decât cărţile $D A B$, deoarece, dacă vom roti ulterior ultimele $K$ cărţi, $C$ nu va mai fi niciodată considerat, cărţile fiind doar adăugate, iar o dată ce o carte iese din „top {$K$}” cărţi nu va mai fi posibil să i se schimbe poziţia pe raft. Să rotim acum „top {$K$}” cărţi. Noua ordine va fi $B A D$ şi $C$ pe raft la loc sigur. Dacă îl vom adăuga pe $E$, topul se va schimba în $E B A$ iar pe raft, în mod sigur vor fi, în această ordine, $D C$. Proprietatea celor $K$ cărţi din vârf este: o secvenţă continuă de elemente, la care se adaugă noi elemente sau se elimină dintre acestea numai pe la _capete_. Aceste capete sunt chiar head şi tail ale unui deque.\r\n\r\np=. !deque-si-aplicatii?bookpile.png 40%!\r\n\r\nLa final, când se vor termina operaţiile, cărţilor de pe raft li se vor adăuga cele din deque şi se va afişa soluţia. În cazul presupus, soluţia va fi: $E B A D C$.\r\n\r\nÎntrucât operaţiile unui deque se execută în $O(1)$ amortizat, soluţia are complexitatea $O(N + M)$.\r\n\r\nh2(#problema-2). \'2. Vila 2\':problema/vila2 (.campion)\r\n\r\nbq. Se dă un şir $S$ de $N$ numere întregi şi un $D$ număr natural. Se cere să determine diferenţa maximă dintre oricare două numere din şir cu proprietatea că diferenţa indicilor nu depăşeşte $D$.\r\nRestricţii: $2 &le; N &le; 100 000$, $1 &le; D &le; N/2$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia nu este greu de intuit. Considerăm indicii succesiv $1$, $2$, .. , $N$. Va trebuie ca pentru fiecare secvenţă $(i - D, i]$ să determinăm valoarea maximă şi pe cea minimă, iar diferenţa lor să o comparăm cu rezultatul obţinut până în acel moment. Pentru fixarea ideilor, să urmărim cum putem determina valoarea maximă din fiecare secvenţă $(i - D, i]$.\r\n\r\n_Observaţie_: „Fie $i{~1~}$, $i{~2~}$ doi indici astfel încât $i - D &lt; i{~1~} &lt; i{~2~} &le; i$.\r\n\r\n# Dacă $S[i{~1~}] &lt; S[i{~2~}]$ atunci, cât timp cei doi indici vor fi în intervalul $(i - D, i]$, valoarea de pe poziţia $i{~2~}$ va fi întotdeauna preferată valorii de pe poziţiei $i{~1~}$. Când unul din indici nu va mai fi în acest interval, cel expediat va fi $i{~1~}$ şi, astfel, $i{~2~}$ rămâne în continuare preferat.\r\n# Dacă $S[i{~1~}] &gt; S[i{~2~}]$ atunci îl vom păstra pe $i{~2~}$, deoarece este candidat la maxim în viitor.”\r\n\r\nCu această observaţie deducem că într-o secvenţă $(i - D, i]$ vom avea un şir $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$ astfel încât $S[i{~1~}] &gt; S[i{~2~}] &gt; ... &gt; S[i{~K~}]$. Când vom avansa la secvenţa următoare, $(i - D + 1, i + 1]$, vom şterge din indicii $i{~1~}$, $i{~2~}$... atâta timp cât nu se găsesc în intervalul curent şi vom şterge din poziţiile $i{~K~}$, $i{~K-1~}$... cât timp $S[i + 1] &gt; S[i{~K~}]$, $S[i + 1] &gt; S[i{~K-1~}]$... adică cât timp se îndeplineşte primul punct din observaţia anterioară.\r\n\r\nŞirul $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$ este continuu iar operaţiile se efectuează doar pe la cele două capete. Rezultă că şirul poate fi implementat cu ajutorul unui deque.\r\n\r\nPentru $S[] = {5, 9, 4, 7, 4, 1}$ şi $D = 3$ obţinem următoarele stări ale unui deque:\r\n\r\n* <tex> \\langle \\widehat{5\\ [1]} \\rangle; </tex>\r\n* <tex> \\langle 5\\ [1] \\rangle \\Leftarrow 9\\ [2] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]} \\rangle; </tex>\r\n* <tex> \\langle 9\\ [2] \\rangle \\Leftarrow 4\\ [3] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 4\\ [3] \\rangle; </tex>\r\n* <tex> \\langle 9\\ [2],\\ 4\\ [3] \\rangle \\Leftarrow 7\\ [4] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 7\\ [4] \\rangle; </tex>\r\n* <tex> 9\\ [2] \\Leftarrow \\langle 7\\ [4] \\rangle \\Leftarrow 4\\ [5] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5] \\rangle; </tex>\r\n* <tex> \\langle 7\\ [4],\\ 4\\ [5] \\rangle \\Leftarrow 1\\ [6] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5],\\ 1\\ [6] \\rangle; </tex>\r\n\r\nCum fiecare indice din $1$, $2$, .., $N$ trece cel mult o dată prin deque, complexitatea finală este $O(N)$ amortizat.\r\n\r\nh2(#problema-3). \'3. Şir\':problema/sir\r\n\r\nbq. Se dă un şir $S$ de numere întregi de lungime $N$. Se cere să se găsească secvenţa de lungime maximă cuprinsă între $X$ şi $Y$ astfel încât $MAX - MIN &le; Z$, unde $MAX$ este maximul dintre toate numerele întregi din secvenţă iar $MIN$ minimul dintre acestea. Secvenţa soluţie va fi cea cu poziţia de început maximă dintre toate secvenţele de lungime maximă.\r\nRestricţii: $3 &le; N &le; 100 000$, $1 &le; X &le; Y &le; N$, $0 &le; Z &le; 30 000$.\r\n\r\nh3. Soluţie\r\n\r\nVoi prezenta mai jos o rafinare a soluţiei în trei paşi.\r\n\r\nPrima rezolvare se găseşte uşor, deoarece nu facem decât să urmărim textul: pentru fiecare poziţie $i$ fixată ({$i$} ia valorile $1$, $2$, .., $N$ succesiv) vom determina pentru aceasta secvenţa cerută, adică vom plimba un $j$ între poziţiile $i - Y$ şi $i - X$. Pentru un interval $(j, i]$ vom determina $MAX$ şi $MIN$ în $O(log{~2~}N)$ cu un arbore de intervale, iar daca diferenţa dintre acestea nu depăşeşte $Z$ vom compara cu soluţia finală. Complexitatea finală va fi $O(N * (Y - X) * log{~2~}Y)$.\r\n\r\nSă presupunem că pentru poziţia curentă $i$, l-am găsit pe $j$ cuprins între $i - Y$ şi $i - X$ care îndeplineşte optimul. Ce proprietăţi are $j$?\r\n\r\n* $i - Y &le; j &le; i - X$ şi $MAX - MIN &le; Z$;\r\n* dacă îl incrementăm pe $j$ la $j + 1$ atunci dacă $j &le; i - X$ cu siguranţă $MAX - MIN &le; Z$ şi astfel soluţia va fi mai scurtă;\r\n* dacă îl decrementăm pe $j$, atunci ori $j < i - Y$ ori $MAX - MIN > Z$;\r\n* dacă îl incrementăm pe $i$ la $i + 1$, atunci se poate întâmpla ca $j < i - Y$; cum $MAX$ nu poate decât să crească, iar $MIN$ decât să scadă, se mai poate de asemenea întâmpla ca $MAX - MIN > Z$.\r\n\r\nDatorită proprietăţilor de mai sus, când trecem de la $i$ la $i + 1$, valoarea lui $j$ nu poate decât să crească cât timp $j < i - Y$ sau $MAX - MIN > Z$ şi $j$ nu a depăşit poziţia $i - X$. Pentru determinarea lui $MAX$, respectiv lui $MIN$ se poate folosi un arbore de intervale. Complexitatea finală va fi $O(N * log{~2~}(Y))$.\r\n\r\nCu cei doi indici $i$ şi $j$ vom accesa fiecare element din cele $N$ de cel mult $2$ ori, o dată cu $i$ şi o dată cu $j$. Să vedem cum putem îmbunătăţi complexitatea $O(log{~2~}Y)$ pentru determinarea maximului şi minimului.\r\n\r\nPentru fixarea ideilor să urmărim cum îl calculăm pe $MAX$. Observaţia care ne ajută în multe probleme pentru reducerea complexităţii de la $O(log{~2~}N)$ la $O(1)$ amortizat este următoarea: \r\n\r\n_Observaţie_: „Fixăm $i{~1~}$ şi $i{~2~}$ astfel încât $j < i{~1~} < i{~2~} &le; i$. Atunci, dacă $S[i{~2~}] > S[i{~1~}]$ poziţia $i{~2~}$ va fi întotdeauna mai importantă decât poziţia $i{~1~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ şi $i{~2~}$ nu vor mai fi ambele în intervalul $(j, i]$, poziţia eliminată va fi {$i{~1~}$}. Dacă însă $S[i{~1~}] > S[i{~2~}]$, atunci poziţia $i{~1~}$ va umbri poziţia $i{~2~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ va fi eliminat, atunci e posibil ca $i{~2~}$ să fie un candidat la $MAX$ dintre restul elementelor de la dreapta sa. În acest caz, nu putem afirma nimic şi vom păstra cele două poziţii.”\r\n\r\nRezultă din această observaţie că în intervalul $(j, i]$ poziţiile importante vor fi $j < i{~1~} < i{~2~} < .. < i{~k~} <= i$ astfel încât $S[i{~1~}] > S[i{~2~}] > .. > S[i{~k~}]$. Astfel, $MAX$ va fi $S[i{~1~}]$. Când îl vom incrementa pe $i$ la $i + 1$ vom şterge din poziţiile $i{~k~}$, $i{~k-1~}$, ... atâta timp cât $S[i + 1]$ este mai important, adică mai mare decât valorile de pe aceste poziţii, şi vom şterge $i{~1~}$, $i{~2~}$, ... atâta timp cât aceste poziţii sunt mai mici sau egale decât $j\'$. Indicele $j\'$ este noul optim pentru poziţia $i + 1$. Proprietatea şirului de poziţii $i{~1~}, i{~2~}, .., i{~k~}$ este că se reprezintă ca un şir continuu de numere care permite inserarea elementelor prin dreapta şi ştergerea prin stânga, adică se adaugă elemente la tail şi se şterg elemente de la head. Îl putem deci reprezenta printr-un deque. Complexitatea $O(1)$ amortizat provine de la faptul că fiecare poziţie dintre cele $N$ nu trece decât o singură dată prin deque şi este şters tot cel mult o singură dată. \r\n\r\nÎn practică, pseudocodul poate arăta în felul următor:\r\n\r\n== code(cpp) |\r\n// S şirul de numere iniţial şi N lungimea sa\r\n\r\nSubalgoritmul push_in(deque, întreg p, funcţia fct) este:\r\n    cât timp (!deque.empty() şi fct(S[p], S[deque.back()])) execută\r\n        deque.pop_back();\r\n    deque.push_back(p);\r\nSfârşit;\r\n\r\nFuncţia query(deque, întreg j) este:\r\n    cât timp (!deque.empty() şi deque.front() <= j) execută\r\n        deque.pop_front();\r\n    return S[deque.front()];\r\nSfârşit;\r\n\r\nAlgoritmul este:\r\n    lg = 0;\r\n    pentru i = 1, N execută\r\n        // funcţia min(a, b) întoarce true dacă a < b\r\n        inserează(min_deq, i, min);\r\n        // funcţia max(a, b) întoarce true dacă a > b\r\n        inserează(max_deq, i, max);\r\n        cât timp ((j < i - Y sau query(max_deq, j) - query(min_deq, j) > Z) şi j < i - X) execută\r\n            j = j + 1;\r\n        // (j, i] este intervalul candidat la soluţia optimă pentru poziţia i\r\n        dacă (j <= i - X) şi (query(max_deq, j) - query(min_deq, j) <= Z) atunci\r\n            dacă (lg >= i - j) atunci\r\n                lg = i - j, start = j + 1, stop = i;\r\n    sfârşit_pentru\r\n\r\n    dacă (lg > 0) atunci\r\n        scrie lg, start, stop;\r\n    altfel\r\n        scrie -1;\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală va fi $O(N)$.\r\n\r\nh2(#problema-4). \'4. Trans\':problema/trans (ONI 2004)\r\n\r\nbq. Se dau $N$ blocuri de piatră, de culoare albă sau neagră aşezate în ordinea $1$, $2$,.., $N$. Blocurile de piatră trebuie să fie transportate în ordinea în care sunt, iar pentru aceasta va trebui închiriat un camion. Se mai dau $Q$ tipuri de camioane. Camionul de tipul $i (1 &le; i &le; Q)$ poate transporta maxim $K{~i~}$ blocuri de piatră la un moment dat şi pentru un transport se percepe taxa $T{~i~}$. Se impune condiţia ca toate blocurile de piatră plasate în camion la un transport sa aibă aceeaşi culoare. Aşadar, pentru a fi transportate toate blocurile, se va alege un camion de un anumit tip, iar camionul va efectua unul sau mai multe transporturi. Pentru a micşora suma totală plătită, există posibilitatea de a schimba culoarea oricărui bloc de piatră (din alb în negru sau din negru în alb); pentru fiecare bloc $i (1 &le; i &le; N)$ se cunoaşte suma $S{~i~}$ ce trebuie plătită pentru a-i schimba culoarea $C{~i~}$.\r\nCerinţă: Pentru fiecare dintre cele $Q$ tipuri de camioane, determinaţi suma minimă plătită pentru a transporta toate cele $N$ blocuri.\r\nRestricţii: $1 &le; N &le; 16 000$, $1 &le; Q &le; 100$, $1 &le; K{~i~} &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se bazează pe găsirea unei formule de recurenţă ce respectă principiul optimalităţii al metodei programării dinamice.\r\n\r\nPentru început, fixăm un camion dintre cele <tex> Q </tex>. Fie <tex> K </tex> numărul maxim de pietre pe care acesta le poate transporta şi <tex> T </tex> taxa percepută. Notăm <tex> sum_{i,c} </tex> costul pentru a schimba toate pietrele <tex> 1, 2, \\ldots, i </tex> în culoarea <tex> c </tex> (<tex> c = 0 </tex> pentru alb şi <tex> c = 1 </tex> pentru negru). Rezultă că în <tex> sum_{i,c} </tex> se vor însuma toate valorile <tex> S_{j} </tex>, cu <tex> j \\le i </tex> pentru care <tex> C_{j} = 1 - c </tex>. \r\n\r\nÎn continuare, considerăm <tex> bst_{i,c} </tex> costul minim pentru a transporta pietrele <tex> 1, 2, \\ldots, i </tex>, iar ultimul transport conţine pietre de culoare <tex> c </tex>. Întrucât nu putem transporta mai mult de <tex> K </tex> pietre, <tex> bst_{i,c} </tex> depinde doar de poziţiile <tex> i - K, i - K + 1, \\ldots, i - 1 </tex>. Cunoaştem că ultimul camion va transporta o secvenţă continuă de pietre începând de la o poziţie <tex> j + 1 </tex> până la poziţia <tex> i </tex>, unde <tex> i - K \\le j \\le i - 1 </tex>. Astfel, pentru  fiecare <tex> j </tex> în intervalul precedent, costul va fi <tex> Min(bst_{j,0}, bst_{j,1}) </tex> (transportăm primele <tex> j </tex> pietre cât mai ieftin) adunat cu <tex> sum_{i,c} - sum_{j,c} </tex> (costul transformării pietrelor <tex> j + 1, \\ldots, i </tex> în culoarea <tex> c </tex>) şi plus taxa <tex> T </tex>. Rezultă recurenţa:\r\n\r\n* <tex> bst_{i,c} = Min\\ \\{\\ Minim(bst_{j,0},\\ bst_{j,1}) + sum_{i,c} - sum_{j,c} + T\\ :\\ i - K \\le j \\le i - 1\\ \\}; </tex>\r\n\r\nDacă ne vom opri aici, complexitatea soluţiei va fi <tex> O(Q * N^{2}) </tex>.\r\n\r\nRelaţia de recurenţă poate fi îmbunătăţită. Observăm că pentru poziţia <tex> i </tex>, <tex> sum_{i,c} </tex> este o valoare constantă, ca şi <tex> T </tex>. Astfel, deducem următoarea relaţie de recurenţă:\r\n\r\n* <tex> bst_{i,c} = Min\\ \\{\\ Minim(bst_{j,0},\\ bst_{j,1}) - sum_{j,c}\\ :\\ i - K \\le j \\le i - 1\\ \\} + sum_{i,c} + T; </tex>\r\n\r\nNotez în continuare, pentru uşurinţă în scriere, <tex> T_{j,c} = Min(bst_{j,0}, bst_{j,1}) - sum_{j,c} </tex>. Să fixăm doi indici <tex> i_{1} </tex> şi <tex> i_{2} </tex>, astfel încât <tex> i - K \\le i_{1} < i_{2} \\le i - 1 </tex>. Dacă <tex> T_{i_{1},c} > T_{i_{2},c} </tex> atunci, întotdeauna poziţia <tex> i_{2} </tex> va fi preferată poziţiei <tex> i_{1} </tex>. Când cele două nu se vor mai afla ambele în intervalul <tex> [i - K, i - 1] </tex>, poziţia eliminată va fi poziţia <tex> i_{1} </tex>. Dacă <tex> T_{i_{1},c} < T_{i_{2},c} </tex>, atunci nu putem decide care poziţie este mai bună în viitor, aşa că le vom păstra pe ambele. Rezultă mai departe că în intervalul <tex> [i - K, i - 1] </tex> vom avea o serie de indecşi candidaţi la minim <tex> i - K \\le i_{1} < i_{2} < \\ldots < i_{n} \\le i - 1 </tex> astfel încât <tex> T_{i_{1},c} < T_{i_{2},c} <  .. < T_{i_{n},c} </tex>. Mai departe, găsim <tex> bst_{i,c} = T_{i_{1},c} + sum_{i,c} + T </tex>. Urmează să îl introducem şi pe <tex> T_{i,c} </tex>, el fiind egal cu <tex> Minim(bst_{i,0}, bst_{i,1}) - sum_{i,c} </tex>, în şirul de indecşi de mai sus. Acest lucru se va face în felul următor: se vor elimina din <tex> i_{n}, , i_{n-1}, \\ldots </tex> atâta timp cât <tex> T_{i_{n},c} > T_{i,c} </tex>, <tex> T_{i_{n-1},c} > T_{i,c} \\ldots </tex> adică atâta timp cât poziţia <tex> i </tex> este preferată lui <tex> i_{n}, i_{n-1}, \\ldots </tex>. Fiind la poziţia <tex> i + 1 </tex>, intervalul se va transforma în <tex> [i - K + 1, i] </tex>, aşadar, vom mai elimina din primii indici <tex> i_{1}, i_{2}, \\ldots </tex> atâta timp cât <tex> i_{1} < i - K + 1, i_{2} < i - K + 1, \\ldots </tex>.\r\n\r\nDupă cum am arătat şi la problema precedentă, acest şir de indecşi <tex> i_{1}, i_{2}, \\ldots, i_{n} </tex> are proprietatea că este un şir continuu de numere care admite inserări prin dreapta (tail) şi ştergeri prin stânga (head). Şir ce poate fi reprezentat printr-un deque. Cum fiecare index dintre <tex> 1, 2, \\ldots, N </tex> va trece o singură dată prin deque şi va fi şters cel mult o dată, complexitatea soluţiei în acest caz va fi <tex> O(Q * N) </tex>.\r\n\r\nÎn practică, programul este scurt, clar şi foarte eficient:\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\n#include <vector>\r\n#include <deque>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\nconst char iname[] = \"trans.in\";\r\nconst char oname[] = \"trans.out\";\r\n\r\n#define MAXN  16005\r\n#define Min(a, b) ((a) < (b) ? (a) : (b))\r\n#define FOR(i, a, b)  for (int i = (a); i <= (b); ++ i)\r\n\r\nint C[MAXN], S[MAXN], bst[MAXN][2], sum[MAXN][2], N;\r\n\r\nvoid insert(deque < pair <int, int> >& deq, const pair <int, int>& p) {\r\n    while (!deq.empty() && deq.back().second > p.second)\r\n        deq.pop_back();\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque < pair <int, int> >& deq, const int idx) {\r\n    while (deq.front().first < idx)\r\n        deq.pop_front();\r\n    return deq.front().second;\r\n}\r\n\r\nint work(const int K, const int T) {\r\n    deque < pair <int, int> > deq[2];       // pair (idx, value)\r\n    FOR (c, 0, 1)\r\n        insert(deq[c], pair <int, int>(0, 0));\r\n    FOR (i, 1, N) {   // obiectul i\r\n        FOR (c, 0, 1) // culoare\r\n            bst[i][c] = query(deq[c], i - K) + sum[i][c] + T;\r\n        FOR (c, 0, 1)\r\n            insert(deq[c], pair <int, int>(i, Min(bst[i][0], bst[i][1]) - sum[i][c]));\r\n    }\r\n    return Min(bst[N][0], bst[N][1]);\r\n}\r\n\r\nint main(void)\r\n{\r\n    ifstream in(iname);  ofstream out(oname);\r\n    in >> N;\r\n    FOR (i, 1, N) {\r\n        in >> C[i] >> S[i];\r\n        FOR (c, 0, 1)\r\n            sum[i][c] += sum[i - 1][c];\r\n        sum[i][1 - C[i]] += S[i];\r\n    }\r\n    int cnt, K, T;\r\n    in >> cnt;\r\n    FOR (i, 1, cnt)\r\n        in >> K >> T, out << work(K, T) << \"\\n\";\r\n\r\n    in.close(), out.close();\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#problema-5). \'5. Otilia\':problema/otilia  (.campion)\r\n\r\nbq. Otilia şi Burbucel au o grămadă de $N$ pietre şi vor juca un joc cu următoarele trei reguli: 1. Primul jucător are voie să ia din gramadă cel mult $K$ piese; 2. Cu excepţia primei mutări, fiecare jucător are voie să ia maxim $P * t$ pietre, unde $t$ este numărul de pietre care au fost substituite din grămadă la mutarea precedentă; 3. Pierde cel care mută ultimul (cel care ia ultimele pietre din grămadă).\r\nCerinţă: Se dau $M$ jocuri prin numerele $N$, $K$ şi $P$. Se cere să se determină dacă Otilia va câştiga fiecare din jocuri sau nu.\r\nRestricţii: $1 &le; M &le; 30 000$, $1 &le; N &le; 5 000 000$, $1 &le; K &le; N$, $1 &le; P &le; 10$.\r\n\r\nh3. Soluţie (Silviu Ganceanu):\r\n\r\nProblema se rezolvă prin programare dinamică. Soluţia se bazează pe observaţia de mai jos. Considerăm $P$-ul fixat şi notăm cu $stare(X, Y)$ poziţia de start în care avem $X$ pietre şi numărul maxim de pietre care se pot lua la prima mutare este $Y$.\r\n\r\n_Observaţia 1_: „Dacă există strategie sigură de câştig pentru $stare(X, Y)$ atunci există şi pentru orice $stare(X, T)$ cu $T &ge; Y$.” \r\n\r\nDe ce? Pentru că orice mutare validă pentru $stare(X, Y)$ este validă şi pentru $stare(X, T)$. Având această observaţie notăm cu $MinY[X] = Y$, $Y$ minim astfel încât avem strategie de câştig pentru $stare(X, Y)$.\r\n\r\n_Observaţia 2_: „{$stare(X, Y)$} este pierzătoare dacă şi numai dacă $Y < MinY[X]$.” \r\n\r\nAceasta reiese din definiţia lui $MinY[X]$.\r\n\r\n$MinY[X]$ se calculează după următoarea recurenţă, care rezultă din regulile jocului: \r\n\r\n* $MinY[X]$ este cel mai mic $i$ pentru care avem $MinY[X - i] > P * i$.\r\n\r\nDe aici se naşte prima soluţie, care este implementarea directă a recurenţei. Deşi complexitatea acesteia pare a fi $O(N^2^)$ ea se comportă foarte bine pentru $N &le; 500 000$. Aşadar, această soluţie acoperă aproximativ $50%$ din testele de intrare. Printr-o rafinare a acestei soluţii se obţine un algoritm de complexitate $O(N)$. Rafinarea se bazează pe: \r\n\r\n_Observaţia 3_: „Să presupunem că dorim să calculăm $MinY[X]$. Facem următoarea afirmaţie: orice poziţie _rea_ pentru $X$ (în care dacă mutăm pierdem) va fi _rea_ şi pentru $X + 1$.”\r\n\r\nAcest lucru este simplu de observat dacă privim ce înseamnă că o poziţie $Q$ e rea pentru $X$: \r\n\r\n* $MinY[Q] > X - Q$, pentru $X$;\r\n* $MinY[Q] > X - Q + 1$, pentru $X + 1$.\r\n\r\nEste evident că prima relaţie o implică pe cea de-a doua. În momentul acesta se poate construi următorul algoritm: având lista de poziţii care pot fi bune pentru $X$ (sortată descrescător) o căutăm pe cea mai mare ca valoare care este într-adevăr bună. În principiu, scoatem din capul listei poziţiile rele până când dăm de o poziţie bună. La listă se va adăuga şi $X$ şi se va trece la pasul următor. Operaţiile algoritmului sunt chiar operaţiile asupra unui deque.\r\n\r\nh2(#problema-6). \'6. Bcrc\':problema/bcrc (Stelele Informaticii)\r\n\r\nbq. Se consideră $N$ camere, numerotate de la $1$ la $N$, aşezate în cerc. Iniţial (la momentul de timp 0), ne aflăm în camera $1$. În fiecare moment de timp, putem alege să rămânem în camera în care ne aflăm sau să ne deplasăm într-o cameră vecină într-o unitate de timp. Se dă o listă de $M$ cutii ce conţin bomboane prin $T$, $C$ şi $B$: cutia apare la momentul $T$ în camera $C$ şi conţine $B$ bomboane. Cutia va dispărea la momentul $T + 1$.\r\nCerinţă: Cunoscând numărul de camere din labirint şi momentele de timp la care apar cutiile cu bomboane, determinaţi care este numărul maxim de bomboane pe care le putem culege.\r\nRestricţii: $3 &le; N &le; 2 048$, $0 &le; M &le; 50 000$, $1 &le; T &le; 1 000 000 000$, $1 &le; C &le; N$, $1 &le; B &le; 9 999$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia foloseşte metoda programării dinamice.\r\n\r\nO stare se reprezintă prin camera în care ne aflăm şi momentul de timp. Fie <tex> bst_{i,j} </tex> numărul maxim de bomboane culese până în momentul <tex> i </tex> când ne găsim în camera <tex> j </tex>. O observaţie evidentă este că <tex> bst_{i,j} </tex> se poate modifica doar în momentele în care apar cutiile. Prin urmare, vom considera momentele de timp când apar cutiile, momente ce sunt în număr de <tex> M </tex>, <tex> bst_{i,j} </tex> însemnând numărul maxim de bomboane culese ştiind că ne aflăm în camera <tex> j </tex> unde am cules cutia <tex> i </tex>. De cine depinde această stare? Ştim că <tex> bst_{i-1,1\\ldotsN} </tex> a fost deja calculat în mod optim. Să notăm cu <tex> T </tex> diferenţa de timp dintre momentele la care apare cutia <tex> i </tex> şi cutia <tex> i - 1 </tex>. În acest moment, <tex> i </tex> şi cameră <tex> j </tex> putem ajunge din maxim <tex> T </tex> camere spre stânga sau spre dreapta, întrucât fiecare deplasare între două camere costă o unitate de timp. De unde deducem că:\r\n\r\n* <tex> bst_{i,j} = Min\\{\\ bst_{i-1,j-T},\\ bst_{i-1,j-T+1}, \\ldots,\\ bst_{i-1,j}, \\ldots,\\ bst_{i-1,j+T-1},\\ bst_{i-1,j+T}\\ \\}; </tex>\r\n\r\nMetoda directă şi, aparent eficientă, constă în folosirea unui arbore de intervale pentru aflarea acestui minim. Însă, intervalul se deplasează constant spre dreapta, dacă vom considera indicii <tex> j </tex> în ordine <tex> 1, 2, 3, \\ldots </tex>, fiind reprezentat de un şir de valori de lungime constantă în care noile elemente se introduc prin dreapta şi altele se elimină prin stânga. Vom folosi un deque de lungime <tex> T * 2 </tex> şi vom proceda ca în problemele precedente, eliminând poziţiile care nu sunt candidate la soluţie. Mai jos este o reprezentare grafică a acestei explicaţii.\r\n\r\np=. !deque-si-aplicatii?bcrc.png 40%!\r\n\r\nComplexitatea finală: <tex> O(M * N) </tex>.\r\n\r\nh2(#problema-7). \'7. Cut the Sequence\':http://acm.pku.edu.cn/JudgeOnline/problem?id=3017 (PKU) \r\n\r\nbq. Se dă o secvenţă $S$ de numere întregi de lungime $N$. Va trebui să se împartă secvenţa în mai multe subsecvenţe astfel încât suma valorilor din fiecare parte să nu depăşească un număr întreg $M$ dat, iar dacă însumăm maximul din fiecare subsecvenţă să obţinem o sumă cât mai mică.\r\nRestricţii: $0 &lt; N &le; 100 000$, $0 &le; S{~i~} &le; 1 000 000$.\r\n\r\nh3. Soluţie:\r\n\r\nŞi această soluţie foloseşte metoda programării dinamice. Construim <tex> bst_{i} </tex> egal cu costul minim de a împărţi primele <tex> i </tex> numere din <tex> S </tex>. Pentru a calcula <tex> bst_{i} </tex> alegem toate secvenţele posibile care se termină pe o poziţia <tex> j </tex>, <tex> j < i </tex>, şi adunăm valorile corespunzătoare:\r\n\r\n* <tex> bst_{i} = Min\\{bst_{j} + Max\\{S_{j+1},.., S_{i}\\}\\ :\\ 0 \\le j < i, \\displaystyle\\sum_{k=j+1}^{i} S_{k} \\le M\\}; </tex>\r\n\r\nImplementarea directă a acestei recurenţe conduce la un algoritm de complexitate <tex> O(N^{2}) </tex>, dar care pentru restricţiile impuse nu este de ajuns.\r\n\r\nSă obţinem în continuare alte informaţii. Fie indicele <tex> j </tex> minim astfel încât <tex> \\displaystyle\\sum_{k=j+1}^{i} \\le M </tex>. Maximul obţinut din mulţimea <tex> \\{S_{j+1},.., S_{i}\\} </tex> se găseşte pe o poziţie <tex> j^{\'} </tex> unde <tex> j < j^{\'} \\le i </tex>. Însă, orice indice <tex> k </tex> cu <tex> j \\le k < j^{\'} </tex> are proprietatea că rezultatul expresiei <tex> Max\\{S_{k+1},.., S_{i}\\} </tex> se găseşte pe poziţia <tex> j^{\'} </tex>. Rezultă că <tex> \\forall k \\in \\{j, j+1,.., j^{\'}-1\\} </tex>, <tex> bst_{i} </tex> poate fi îmbunătăţit cu valoarea <tex> bst_{k} + S_{j^{\'}} </tex>. Minimul mulţimii <tex> \\{bst_{k} + S_{j^{\'}} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} </tex> este egal cu minimul expresiei <tex> \\{bst_{k} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} + S_{j^{\'}} (*) </tex>, deci, schimbând reperele, pentru maximul de pe poziţia <tex> j^{\'} </tex>, dacă lungimea secvenţei care se termină în <tex> i </tex> este cel puţin <tex> i-j^{\'}+1 </tex>, atunci optimul se obţine calculând rezultatul expresiei <tex> (*) </tex>. Pentru minimul pe un interval, <tex> [j, j^{\'}-1] </tex> al valorile vectorului <tex> bst </tex>, putem folosi un arbore de intervale pentru <tex> O(log_{2}N) </tex> pe interogare.\r\n\r\nDar, lungimea optimă a ultimei secvenţe ce se termină în <tex> i </tex> poate fi mai mică decât <tex> i-j^{\'}+1 </tex>, deci poate fi cel mult <tex> i-j^{\'} </tex>. Optimul se găseşte printre elementele mulţimii <tex> \\{bst_{k} + Max\\{S_{k+1},..,S_{i}\\} : j^{\'} \\le k < i\\} </tex>. Dacă procedăm ca la pasul anterior vom obţine un alt indice <tex> j^{\'\'} </tex> cu aceleaşi proprietăţi pentru secvenţa <tex> [j^{\'}, i] </tex> precum <tex> j^{\'} </tex> pentru secvenţa <tex> [j, i] </tex>.\r\n\r\nInductiv obţinem un şir de indici <tex> j_{0} = j < j_{1} < j_{2} < .. < j_{K} = i </tex> astfel încât <tex> S_{j_{1}} </tex> este cel mai mare element al secvenţei <tex> (j, i] </tex>, <tex> S_{j_{2}} </tex> cel mai mare element al secvenţei <tex> (j_{1}, i] </tex>, şi aşa mai departe, când <tex> j_{K} </tex> este chiar <tex> i </tex>.\r\n\r\nCu ajutorul relaţiei <tex> (*) </tex> şi a şirului <tex> j_{1} < j_{2} < .. < j_{K} = i </tex> vom construi un alt vector <tex> iMin </tex> cu proprietatea că <tex> iMin_{p} = Min\\{bst_{r} + S_{j_{p}} : j_{p-1} \\le r < j_{p}\\} </tex>. În final, <tex> bst_{i} = Minim\\{iMin_{1}, iMin_{2}, .., iMin_{K}\\} </tex>, rezultat pe care îl putem obţine în <tex> O(log_{2}N) </tex> dacă folosim un arbore de intervale.\r\n\r\nÎnsă, cum se construieşte şirul <tex> j_{1} < j_{2} < .. < j_{K} = i </tex>? În \'a doua problemă\':deque-si-aplicatii#problema-2 am construit cu ajutorul unui deque exact şirul de indici de care avem nevoie aici. Când vom înainta la indicele <tex> i + 1 </tex> vom modifica şirul astfel încât să respecte proprietăţile de mai sus utilizând operaţiile normale asupra unui deque. Mai sus am menţionat cum se obţine <tex> bst_{i} </tex> lucru care implică combinarea structurilor de deque şi arbore de intervale. Arborele de intervale reţine valorile lui <tex> iMin </tex> pentru fiecare element al dequelui. \r\n\r\nPentru a înţelege cum funcţionează acest algoritm să considerăm ca date de intrare şirul <tex> S = \\{5, 9, 4, 7, 4, 1, 6, 3\\} </tex> şi <tex> M = 15 </tex>. Perechile din deque sunt de forma <tex> (S_{i}, iMin_{p}) </tex>. Fie <tex> i = 1, 2, \\ldots 8 </tex>:\r\n\r\n* <tex> i = 1: j = 0, head = 1, tail = 1, deque = \\{\\ (5, 0)\\ \\} \\Rightarrow bst_{1} = 5; </tex>\r\n* <tex> i = 2: j = 0, head = 1, tail = 1, deque = \\{\\ (9, 0)\\ \\} \\Rightarrow bst_{2} = 9; </tex>\r\n* <tex> i = 3: j = 1, head = 1, tail = 2, deque = \\{\\ (9, 5),\\ (4, 9)\\ \\} \\Rightarrow bst_{3} = 13; </tex>\r\n* <tex> i = 4: j = 2, head = 2, tail = 2, deque = \\{\\ (7, 9)\\ \\} \\Rightarrow bst_{4} = 16; </tex>\r\n* <tex> i = 5: j = 2, head = 2, tail = 3, deque = \\{\\ (7, 9),\\ (4, 16)\\ \\} \\Rightarrow bst_{5} = 16; </tex>\r\n* <tex> i = 6: j = 3, head = 2, tail = 4, deque = \\{\\ (7, 13),\\ (4, 16),\\ (1, 16)\\ \\} \\Rightarrow bst_{6} = 17; </tex>\r\n* <tex> i = 7: j = 4, head = 3, tail = 3, deque = \\{\\ (6, 16)\\ \\} \\Rightarrow bst_{7} = 22; </tex>\r\n* <tex> i = 8: j = 4, head = 3, tail = 4, deque = \\{\\ (6, 16),\\ (3, 22)\\ \\} \\Rightarrow bst_{8} = 22; </tex>\r\n\r\nMai jos se vede o figură în care elementele unui deque sunt defapt o secvenţă „continuă” de frunze ale unui arbore de intervale pentru cazul <tex> i = 6 </tex>.\r\n\r\np=. !deque-si-aplicatii?PKU0.png 60%!\r\n\r\np=. _Numărul maxim de elemente ce pot trece prin deque este $8$. În figură, arborele ţine minimul de pe poziţiile $2$, $3$, $4$ din deque._\r\n\r\nAlgoritmul în pseudocod arată în felul următor:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    sum  = 0;\r\n    last = 0;\r\n    // indicii head si tail ai dequeului\r\n    head = tail = 1;\r\n    // poziţia lui bst[0] se inserează în deque\r\n    deque[1] = 0;\r\n    pentru i = 1, N execută\r\n        sum += S[i];\r\n        temp = bst[ deque[tail] ];\r\n        cât timp (head <= tail) şi (S[ deque[tail] ] <= S[i]) execută\r\n            temp = Min(temp, iMin[tail]);\r\n            tail --;\r\n        sfârşit;\r\n        // adaug poziţia i la deque\r\n        tail ++;\r\n        deque[tail] = i;\r\n        // actualizez iMin[]\r\n        iMin[tail]  = temp;\r\n        // actualizez T[], arborele de intervale pe deque[]\r\n        Update(T, tail, iMin[tail] + S[i]);\r\n        // suma valorilor din [last, i] trebuie să nu depăşească M\r\n        cât timp (sum > M) execută\r\n            sum -= S[last];\r\n            dacă (deque[head] == last) atunci\r\n                head ++;\r\n            sfârşit;\r\n            last ++;\r\n        sfârşit;\r\n        // actualizez iMin[], Tb[] arborele de intervale pe bst[]\r\n        iMin[head] = Query(Tb, Max(last - 1, 0), deque[head] - 1);\r\n        // actualizez T[]\r\n        Update(T, head, iMin[head] + S[ deque[head] ]);\r\n        // reţin optimul pentru poziţia curentă\r\n        bst[i] = Query(T, head, tail);\r\n        // actualizez Tb[]\r\n        Update(Tb, i, bst[i]);\r\n    sfârşit;\r\n    scrie bst[N];\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală este <tex> O(N*log_{2}N) </tex>.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nFilozofia din spatele structurii de deque devine utilă, de obicei, în părţile finale ale rezolvării unei probleme. Însă, ce pot spune cu certitudine este că această structură de date pe cât este de simplă pe atât este de eficientă.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\nÎnţelegerea profundă nu se poate realiza decât prin rezolvarea a cât mai multe probleme. Succes!\r\n\r\n* \'Deque\':problema/deque, _Arhiva educaţională_\r\n* \'Secvenţă\':problema/secventa\r\n* \'Secvenţă 3\':problema/secv3\r\n* \'Secvenţă 4\':problema/secv4\r\n* \'Sum 2\':problema/sum2, _Stelele Informaticii 2003_\r\n* \'Drept 2\':problema/drept2, _Lotul Naţional de Informatică, 2006_\r\n* \'Copaci 2\':problema/copaci2, _.campion_\r\n* \'Brânză\':problema/branza\r\n* \'Struţi\':problema/struti\r\n* \'Trompetă\':problema/trompeta\r\n* \'Buline\':problema/buline\r\n* \'Balans\':problema/balans\r\n* \'Gard\':problema/gard, _ONI 2002_\r\n* \'Ghiozdan\':problema/ghiozdan\r\n* \'Munte4\':problema/munte4, _Lotul Naţional de Informatică, 2005_\r\n* \'Cover\':problema/cover, _ONI 2007, Baraj_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Cosmin Negruşeri, \"_Probleme cu secvenţe_\":probleme-cu-secvente\r\n# Dana Lica, \"_Arbori de intervale şi aplicaţii în geometria computaţională_\":arbori-de-intervale\r\n# Cătălin Frâncu, \"_Heapuri_\":heapuri\r\n# Marius Stroe, \"_Treapuri_\":treapuri\r\n# \'C++ Reference\':http://www.cplusplus.com/',3146,'public',NULL,NULL),('planificare/sedinta-20090216','Sedinta 2009-02-16','2009-02-09 14:25:39','2009-02-09 14:29:31','h1. Sedinta 2009-02-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Februarie* la ora *19^00^*, _cel mai probabil_ la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* Tu?\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţa anterioara\':planificare/sedinta-20090126| ==user(user=\"domino\" type=\"tiny\")==|\r\n|Algoritmiada| ... |\r\n|Coding Camp| ... |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n...\r\n\r\nh2. Notiţe\r\n\r\n...\r\n',13,'public',NULL,NULL),('planificare/sedinta-20090216','Sedinta 2009-02-16','2009-02-09 14:25:39','2009-02-09 16:14:32','h1. Sedinta 2009-02-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Februarie* la ora *19^00^*, _cel mai probabil_ la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* Tu?\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090126| ...|\r\n|Algoritmiada| ... |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n...\r\n\r\nh2. Notiţe\r\n\r\n...\r\n',1,'public',NULL,NULL),('planificare/sedinta-20090216','Sedinta 2009-02-16','2009-02-09 14:25:39','2009-02-09 19:31:30','h1. Sedinta 2009-02-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Februarie* la ora *19^00^*, _cel mai probabil_ la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* Tu?\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090126| ...|\r\n|Algoritmiada| ... |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n* Ce se mai aude cu initiativa in care donam calculatoare utilizate?\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n...\r\n\r\nh2. Notiţe\r\n\r\n...\r\n',2970,'public',NULL,NULL),('pd','Programare dinamica','2007-12-04 21:25:10','2009-11-01 15:14:37','h1. Programare dinamica\r\n\r\n(Categoria _Tehnici de programare_, autor _Catalin Tiseanu_)\r\n\r\nPlan de atac (probleme-candidat):\r\n\r\n1. http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en\r\nReducerea complexitatii, transformarea problemei intr-una de construire a unui arbore binar.\r\n\r\n2. http://code.google.com/codejam/contest/dashboard?c=32001#s=p0&a=3\r\n\r\n\r\n3. http://code.google.com/codejam/contest/dashboard?c=32001#s=p3&a=3\r\n\r\n\r\n4. http://code.google.com/codejam/contest/dashboard?c=32015#s=p1&a=1\r\n\r\n\r\n5. http://code.google.com/codejam/contest/dashboard?c=32010#s=p3&a=3\r\n\r\nh2. Sugestii Silviu\r\n\r\n* poate ca nu trebuie sa spunem tot despre programare dinamica intr-un singur articol; spre exemplu putem facem doua articole: PD basic si PD advanced\r\n* cred ca era si ceva prin Cartea lui Francu\' despre programare dinamica; ar merge incorporat (eventual in pd_basic).\r\n\r\nh2. Introducere\r\n\r\nProgramarea dinamică este o metodă utilă pentru a rezolva probleme care pot fi obţinute prin compunerea a mai multor bucăţi, a căror soluţie poate fi apoi determinată optim. Se bazează în principal pe proprietatea unei probleme de a putea fi rezolvată optim dacă se cunosc soluţii optime la sub-problemele ei.\r\nDe menţionat că \'programare\' nu se referă aici la scrierea de cod într-un limbaj de programare, ci la \'programare matematica\', care constă în optimizarea unei funcţii prin alegerea de valori dintr-o mulţime anume. \r\n\r\nScopul acestui articol nu este să ofere o introducere in programare dinamică (pentru aceasta poate fi consultat excelentul tutorial de pe TopCoder \"Dynamic Programming : From novice to advanced\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg). În schimb, acest articol îşi propune să ofere nişte \'smenuri\' mai avansate de rezolvare a problemelor cu programare dinamică. \r\n\r\nh2. Programare dinamică cu reducerea loop-ului interior\r\n\r\nSă considerăm următoarea problema:\r\n\r\nh3(#problema-1). Problema 1: \'Drilling\':http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en\r\n\r\nbq. Se da un şir de $N$ numere naturale $(a{~1~}, a{~2~}, ..., a{~N~})$. Se ştie că un prefix al acestui şir (adică o subsecvenţă de la începutul şirului, posibil nulă) este **defect**. Toate elementele din acel prefix (şi doar din acel prefix) sunt defecte. Se ştie de asemenea că se poate testa orice poziţie $i$ în timp $a{~i~}$ pentru a afla dacă este defectă. Să se determine timpul minim în cazul cel mai defavorabil pentru aflarea lungimii maxime a prefixului şirului care este defect.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(8 24 12 6)$, răspunsul ar fi $42$. Astfel, se testează mai întâi poziţia $2$. Dacă nu este defectă, mai rămâne de testat poziţia $1$. Altfel, în cel mai rău caz mai trebuie testate poziţiile $3$ şi $4$, aducând timpul total la $24 + 12 + 6 = 42$.\r\n\r\nh3. Rezolvare:\r\n\r\nO să începem prin a da altă îmbrăcăminte problemei. Astfel, să ne imaginăm că am construi un arbore binar de căutare pe şirul dat, având drept chei poziţiile din şir, şi drept valori auxiliare valorile poziţiilor respective din şir (un nod cu cheia $i$ va avea valoarea auxiliara $a{~i~}$.\r\nAcum, există mulţi arbori binari de căutare posibile pentru şirul iniţial. Totuşi, să presupunem că am construit unul, pe care îl considerăm de acum ca fixat. Atunci, strategia noastra de testare a elementelor din şir se va desfăşura conforma arborelui. Astfel, testăm mai întâi în poziţia din rădăcină. Dacă poziţia respectivă este defectă, ne ducem în fiul drept. Altfel, mergem in fiul stâng. În ambele cazuri se reia procedeul. Căutarea se termină cand nu mai putem merge într-un fiu. \r\n\r\nSă observăm că dacă considerăm costul unui drum în arbore de la rădăcină la o frunză ca suma valorilor auxiliare din drumul (unic) respectiv, atunci se observă că costul strategiei bazate pe acest arbore este chiar costul maxim al unui drum ! De acum încolo, vom defini costul unui arbore ca costul maxim al unui drum din el. Să exemplificăm pe şirul din exemplu:\r\n\r\n$BAGA POZA$\r\n\r\nSe observă că costul maxim al unui drum este $42$, minim posibil, exact ca răspunsul din exemplu.\r\nDeci, am redus problema la construirea unui arbore binar de căutare, care are costul minim.\r\n\r\nAcum devine clară o primă soluţie folosind programarea dinamică. Astfel, să presupunem că notăm cu @opt[ i ][ j ]@ costul minim al unui arbore construit pe cheile din $[i,j]$ (prin asta notăm (i, i + 1, ..., j). Fie $r[ i ][ j ]$ poziţia rădăcinii arborelui cu costul minim. În cazul existenţei mai multor rădăcini posibile, se alege cea mai din stânga. Cum am putea construi arborele de cost minim pe cheile $[i,j]$ ştiind răspunsul pentru instanţele mai mici (subsecvenţele de lungime mai mică ca $j-i+1$ pe $[i,j]$)? (!) Simplu, arborele de cost minim pe $[i,j]$ se obţine alegând drept rădăcină în mod optim o poziţie $k$, cu <tex>$i \\le k \\le j$</tex>, la care se pune ca fiul stâng arborele optim pentru $[i, k-1]$, şi ca fiu drept arborele optim pentru $[k+1, j]$. Relaţia de recurenţă devine:\r\n\r\n<tex>opt[ i ][ j ] = \\displaystyle\\min_{i \\le k \\le j} \\{a_{k} + \\max( opt[i][k-1], opt[k+1][j] )\\} </tex>   \r\n<tex>r[ i ][ j ] = \\displaystyle\\arg \\min_{i \\le k \\le j}\\{a_{k} + \\max (opt[i][k-1], opt[k+1][j] )\\} </tex> \r\n\r\nAvem @opt[i][j] = 0@, pentru $j < i$.\r\nCazurile de bază sunt @opt[i][i]@ = a{~i~} si @r[i][i] = i@.\r\n\r\nSe observă că răspunsul problemei se află în @opt[1][N]@.\r\nAstfel, am obţinut o soluţie în timp O(N^3).\r\n\r\nAici trebuie remarcată asemănarea acestei probleme cu cea a determinării arborelui de căutare optim, atunci cand se dau probabilităţile relative de căutare a cheilor. Această problemă se numeşte \'Optimal Binary Search Tree\' în literatura de specialitate şi poate fi găsită şi în _Introduction to Algorithms_. În aceasta problemă, se poate aplica o proprietate specială, numită _convexitate_, pentru a reduce complexitatea la $O(N^2)$. Această proprietate reprezintă un concept avansat, care nu se poate aplica în cazul problemei noastre, şi nu va fi discutat în continuare.\r\n[]\r\n\r\n\r\nh2. Programare dinamica folosind bitmask\r\n\r\nIn continuare vom vedea un exemplu de programare dinamica unde vom folosi un bitmask (codificat pe un intreg) pentru a tine spatiul starilor.\r\n\r\nAstfel sa presupunem ca avem nevoie sa tinem un vector caracteristic pentru o multime.\r\nDaca cardinalul acesteia este suficient de mic putem folosi un intreg pentru a codifica aceasta informatie astfel:\r\n\r\nFie multimea A = { x{~1~}, x{~2~}, ... x{~n~} }.\r\nAtunci bitmaskul unei partitii a lui A, MASK, va avea bitul i egal cu 1 numai si numai daca x{~i~} apartine partitiei.\r\n\r\nDesigur, aceasta reprezentare duce la o complexitate direct proportionala cu 2 ^card(A)^.\r\n\r\nh3. Exemplu\r\n\r\n\r\nh2. Programare dinamica folosind vectori de numere intregi\r\n\r\nTo be continued ... \r\n\r\n',2996,'public',NULL,NULL),('deque-si-aplicatii','Deque și aplicații','2009-01-22 22:28:12','2009-02-09 11:05:01','h1. Deque şi aplicaţii\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'_Introducere_\':deque-si-aplicatii#introducere\r\n* \'_Aplicaţii:_\':deque-si-aplicatii#problema-1\r\n** \'1. Book Pile &#40;SGU&#41;\':deque-si-aplicatii#problema-1\r\n** \'2. Vila 2 &#40;.campion&#41;\':deque-si-aplicatii#problema-2\r\n** \'3. Şir\':deque-si-aplicatii#problema-3\r\n** \'4. Trans &#40;ONI 2004&#41;\':deque-si-aplicatii#problema-4\r\n** \'5. Otilia &#40;.campion&#41;\':deque-si-aplicatii#problema-5\r\n** \'6. Bcrc &#40;Stelele Informaticii&#41;\':deque-si-aplicatii#problema-6\r\n** \'7. Cut the Sequence &#40;PKU&#41;\':deque-si-aplicatii#problema-7\r\n* \'_Concluzii_\':deque-si-aplicatii#concluzii\r\n* \'_Probleme suplimentare_\':deque-si-aplicatii#probleme-suplimentare\r\n* \'_Bibliografie_\':deque-si-aplicatii#bibliografie\r\n\r\nÎn acest articol voi prezenta o structură de date de tip listă numită _deque_. Simplitatea acestei structuri poate că nu are multe de spus iar din acest motiv am prezentat şi o serie de aplicaţii care vor arăta surprinzătoarea sa utilitate în locurile unde am fi crezut că nu se mai poate face nimic pentru a reduce complexitatea.\r\n\r\nh2(#introducere). Introducere\r\n\r\nStructura de _deque_ (pronunţat de obicei _deck_) poate fi privit ca o colecţie de tip listă ce are două capete prin care se şterg sau inserează noi elemente. În literatura de specialitate aceste capete se numesc _head_ şi _tail_, iar dequeul mai este recunoscut şi ca fiind o coadă cu două capete _(double ended queue)_.\r\n\r\nImplementarea unui deque se poate face cu liste dublu înlănţuite ori cu un vector static când se cunoaşte numărul elementelor din colecţie. Ce trebuie reţinut este că limbajul C++ pune la dispoziţia utilizatorilor prin intermediul headerului _#include <deque>_ containerul \'_std::deque_\':http://www.cplusplus.com/reference/stl/deque/.\r\n\r\nh3(#operatii). Operaţii:\r\n\r\nMai jos sunt enumerate operaţiile care pot fi efectuate asupra unui deque împreună cu corespondentul lor în limbajul C++:\r\n\r\n* _front()_:	    întoarce primul element;\r\n* _back()_:	    întoarce ultimul element;\r\n* _push_front()_: inserează un element în faţă;\r\n* _push_back()_:  inserează un element în spate;\r\n* _pop_front()_:  scoate primul element;\r\n* _pop_back()_:   scoate ultimul element;\r\n* _empty()_:      întoarce _true_ dacă în deque nu se găseşte niciun element şi _false_ în caz contrar.\r\n\r\np=. !deque-si-aplicatii?new_deque.png 75%!\r\n\r\nToate aceste operaţii se execută în timp $O(1)$ \'amortizat\':http://en.wikipedia.org/wiki/Amortized_analysis. Pentru un plus de viteză va trebui să folosim un vector static cu dimensiunea egală cu numărul maxim de elemente ce pot trece prin deque, iar operaţiile implementate „de mână”, cu doi indecşi ce indică către head şi tail. Însă, în majoritatea aplicaţiilor limita de timp permite folosirea lejerităţii şi siguranţei clasei _std::deque_.\r\n\r\nÎn multe aplicaţii unde soluţiile parţiale se reprezintă sub forma unui şir continuu de valori care permite inserarea şi ştergerea doar pe la capete se poate folosi un deque. În general, se fac inserări pe la un capăt şi ştergeri pe la celălalt. Să urmărim în continuare cazuri concrete în care simplitatea unui deque duce la soluţii de multe ori optime şi implementări foarte scurte şi clare. Aplicaţiile sunt prezentate în ordinea crescătoare a dificultăţii şi din acest motiv recomand cu căldură tuturor celor care au de învăţat din acest articol să le parcurgă în ordine.\r\n\r\nh2(#problema-1). \'1. Book Pile\':http://acm.sgu.ru/problem.php?contest=0&problem=271 (SGU)\r\n\r\nbq. Se dau $N$ cărţi aşezate una deasupra celeilalte asupra cărora se vor efecta $M$ operaţii de două tipuri: 1. $ADD${$(nume)$} : se adaugă cartea $nume$ deasupra celorlalte; 2. $ROTATE$ : primele $K$ cărţi de deasupra se rotesc (dacă sunt mai puţin de $K$ cărţi atunci se vor roti toate). Se cere să se afişeze cărţile în ordine, prima fiind cea de deasupra, după efectuarea celor $M$ operaţii.\r\nRestricţii: $0 &le; N, K &le; 40 000$, $0 &le; M &le; 100 000$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se poate deduce urmând paşii următori. Să presupunem că iniţial avem cărţile $A B C$ şi $K = 3$. Dacă îl vom adăuga pe $D$, atunci nu vor rămâne importante decât cărţile $D A B$, deoarece, dacă vom roti ulterior ultimele $K$ cărţi, $C$ nu va mai fi niciodată considerat, cărţile fiind doar adăugate, iar o dată ce o carte iese din „top {$K$}” cărţi nu va mai fi posibil să i se schimbe poziţia pe raft. Să rotim acum „top {$K$}” cărţi. Noua ordine va fi $B A D$ şi $C$ pe raft la loc sigur. Dacă îl vom adăuga pe $E$, topul se va schimba în $E B A$ iar pe raft, în mod sigur vor fi, în această ordine, $D C$. Proprietatea celor $K$ cărţi din vârf este: o secvenţă continuă de elemente, la care se adaugă noi elemente sau se elimină dintre acestea numai pe la _capete_. Aceste capete sunt chiar head şi tail ale unui deque.\r\n\r\np=. !deque-si-aplicatii?bookpile.png 40%!\r\n\r\nLa final, când se vor termina operaţiile, cărţilor de pe raft li se vor adăuga cele din deque şi se va afişa soluţia. În cazul presupus, soluţia va fi: $E B A D C$.\r\n\r\nÎntrucât operaţiile unui deque se execută în $O(1)$ amortizat, soluţia are complexitatea $O(N + M)$.\r\n\r\nh2(#problema-2). \'2. Vila 2\':problema/vila2 (.campion)\r\n\r\nbq. Se dă un şir $S$ de $N$ numere întregi şi un $D$ număr natural. Se cere să determine diferenţa maximă dintre oricare două numere din şir cu proprietatea că diferenţa indicilor nu depăşeşte $D$.\r\nRestricţii: $2 &le; N &le; 100 000$, $1 &le; D &le; N/2$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia nu este greu de intuit. Dacă vom considera indicii $1$, $2$, .. , $N$ succesiv va trebuie ca pentru fiecare secvenţă $(i - D, i]$ să determinăm valoarea maximă şi pe cea minimă, iar diferenţa lor să o comparăm cu rezultatul obţinut până în acel moment. Pentru fixarea ideilor, să urmărim cum putem determina valoarea maximă din fiecare secvenţă $(i - D, i]$.\r\n\r\n_Observaţie_: „Fie $i{~1~}$, $i{~2~}$ doi indici astfel încât $i - D &lt; i{~1~} &lt; i{~2~} &le; i$.\r\n\r\n# Dacă $S[i{~1~}] &lt; S[i{~2~}]$ atunci, cât timp cei doi indici vor fi în intervalul $(i - D, i]$, valoarea de pe poziţia $i{~2~}$ va fi întotdeauna preferată valorii de pe poziţia $i{~1~}$. Când unul din indici nu va mai fi în acest interval, cel expediat va fi $i{~1~}$ şi, astfel, $i{~2~}$ rămâne în continuare preferat.\r\n# Dacă $S[i{~1~}] &gt; S[i{~2~}]$ atunci îl vom păstra pe $i{~2~}$, deoarece este candidat la maxim în viitor.”\r\n\r\nCu această observaţie deducem că într-o secvenţă $(i - D, i]$ vom avea un şir $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$ astfel încât $S[i{~1~}] &gt; S[i{~2~}] &gt; ... &gt; S[i{~K~}]$. Când vom avansa la secvenţa următoare, $(i - D + 1, i + 1]$, vom şterge din indicii $i{~1~}$, $i{~2~}$... atâta timp cât nu se găsesc în intervalul curent şi vom şterge din poziţiile $i{~K~}$, $i{~K-1~}$... cât timp $S[i + 1] &gt; S[i{~K~}]$, $S[i + 1] &gt; S[i{~K-1~}]$... adică cât timp se îndeplineşte primul punct din observaţia anterioară.\r\n\r\nŞirul $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$ este continuu iar operaţiile se efectuează doar pe la cele două capete. Rezultă că şirul poate fi implementat cu ajutorul unui deque.\r\n\r\nPentru $S[] = {5, 9, 4, 7, 4, 1}$ şi $D = 3$ obţinem următoarele stări ale unui deque:\r\n\r\n* <tex> \\langle \\widehat{5\\ [1]} \\rangle; </tex>\r\n* <tex> \\langle 5\\ [1] \\rangle \\Leftarrow 9\\ [2] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]} \\rangle; </tex>\r\n* <tex> \\langle 9\\ [2] \\rangle \\Leftarrow 4\\ [3] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 4\\ [3] \\rangle; </tex>\r\n* <tex> \\langle 9\\ [2],\\ 4\\ [3] \\rangle \\Leftarrow 7\\ [4] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 7\\ [4] \\rangle; </tex>\r\n* <tex> 9\\ [2] \\Leftarrow \\langle 7\\ [4] \\rangle \\Leftarrow 4\\ [5] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5] \\rangle; </tex>\r\n* <tex> \\langle 7\\ [4],\\ 4\\ [5] \\rangle \\Leftarrow 1\\ [6] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5],\\ 1\\ [6] \\rangle; </tex>\r\n\r\nCum fiecare indice din $1$, $2$, .., $N$ trece cel mult o dată prin deque, complexitatea finală este $O(N)$ amortizat.\r\n\r\nh2(#problema-3). \'3. Şir\':problema/sir\r\n\r\nbq. Se dă un şir $S$ de numere întregi de lungime $N$. Se cere să se găsească secvenţa de lungime maximă cuprinsă între $X$ şi $Y$ astfel încât $MAX - MIN &le; Z$, unde $MAX$ este maximul dintre toate numerele întregi din secvenţă iar $MIN$ minimul dintre acestea. Secvenţa soluţie va fi cea cu poziţia de început maximă dintre toate secvenţele de lungime maximă.\r\nRestricţii: $3 &le; N &le; 100 000$, $1 &le; X &le; Y &le; N$, $0 &le; Z &le; 30 000$.\r\n\r\nh3. Soluţie\r\n\r\nVoi prezenta mai jos o rafinare a soluţiei în trei paşi.\r\n\r\nPrima rezolvare se găseşte uşor, deoarece nu facem decât să urmărim textul: pentru fiecare poziţie $i$ fixată ({$i$} ia valorile $1$, $2$, .., $N$ succesiv) vom determina pentru aceasta secvenţa cerută, adică vom plimba un $j$ între poziţiile $i - Y$ şi $i - X$. Pentru un interval $(j, i]$ vom determina $MAX$ şi $MIN$ în $O(log{~2~}N)$ cu un arbore de intervale, iar daca diferenţa dintre acestea nu depăşeşte $Z$ vom compara cu soluţia finală. Complexitatea finală va fi $O(N * (Y - X) * log{~2~}Y)$.\r\n\r\nSă presupunem că pentru poziţia curentă $i$, l-am găsit pe $j$ cât mai mic cuprins între $i - Y$ şi $i - X$ astfel încât secvenţa $(j, i]$ este candidată la soluţie. Ce proprietăţi are $j$?\r\n\r\n* $i - Y &le; j &le; i - X$ şi $MAX - MIN &le; Z$;\r\n* dacă îl incrementăm pe $j$ la $j + 1$ atunci dacă $j &le; i - X$ cu siguranţă $MAX - MIN &le; Z$ şi astfel soluţia va fi mai scurtă;\r\n* dacă îl decrementăm pe $j$, atunci ori $j < i - Y$ ori $MAX - MIN > Z$;\r\n* dacă îl incrementăm pe $i$ la $i + 1$, atunci se poate întâmpla ca $j < i - Y$; cum $MAX$ nu poate decât să crească, iar $MIN$ decât să scadă, se mai poate de asemenea întâmpla ca $MAX - MIN > Z$.\r\n\r\nDatorită proprietăţilor de mai sus, când trecem de la $i$ la $i + 1$, valoarea lui $j$ nu poate decât să crească cât timp $j < i - Y$ sau $MAX - MIN > Z$ şi $j$ nu a depăşit poziţia $i - X$. Pentru determinarea lui $MAX$, respectiv lui $MIN$ se poate folosi un arbore de intervale. Complexitatea finală va fi $O(N * log{~2~}(Y))$.\r\n\r\nCu cei doi indici $i$ şi $j$ vom accesa fiecare element din cele $N$ de cel mult $2$ ori, o dată cu $i$ şi o dată cu $j$. Să vedem cum putem îmbunătăţi complexitatea $O(log{~2~}Y)$ pentru determinarea maximului şi minimului.\r\n\r\nPentru fixarea ideilor să urmărim cum îl vom calcula pe $MAX$. Observaţia care ne ajută în multe probleme pentru reducerea complexităţii de la $O(log{~2~}N)$ la $O(1)$ amortizat este următoarea: \r\n\r\n_Observaţie_: „Fixăm $i{~1~}$ şi $i{~2~}$ astfel încât $j < i{~1~} < i{~2~} &le; i$. Atunci, dacă $S[i{~2~}] > S[i{~1~}]$ poziţia $i{~2~}$ va fi întotdeauna mai importantă decât poziţia $i{~1~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ şi $i{~2~}$ nu vor mai fi ambele în intervalul $(j, i]$, poziţia eliminată va fi {$i{~1~}$}. Dacă însă $S[i{~1~}] > S[i{~2~}]$, atunci poziţia $i{~1~}$ va umbri poziţia $i{~2~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ va fi eliminat, atunci e posibil ca $i{~2~}$ să fie un candidat la $MAX$ dintre restul elementelor de la dreapta sa. În acest caz, nu putem afirma nimic şi vom păstra cele două poziţii.”\r\n\r\nRezultă din această observaţie că în intervalul $(j, i]$ poziţiile importante vor fi $j < i{~1~} < i{~2~} < .. < i{~k~} <= i$ astfel încât $S[i{~1~}] > S[i{~2~}] > .. > S[i{~k~}]$. Astfel, $MAX$ va fi $S[i{~1~}]$. Când îl vom incrementa pe $i$ la $i + 1$ vom şterge din poziţiile $i{~k~}$, $i{~k-1~}$, ... atâta timp cât $S[i + 1]$ este mai important, adică mai mare decât valorile de pe aceste poziţii, şi vom şterge $i{~1~}$, $i{~2~}$, ... atâta timp cât aceste poziţii sunt mai mici sau egale decât $j\'$. Indicele $j\'$ este noul optim pentru poziţia $i + 1$. Proprietatea şirului de poziţii $i{~1~}, i{~2~}, .., i{~k~}$ este că se reprezintă ca un şir continuu de numere care permite inserarea elementelor prin dreapta şi ştergerea prin stânga, adică se adaugă elemente la tail şi se şterg elemente de la head. Îl putem deci reprezenta printr-un deque. Complexitatea $O(1)$ amortizat provine de la faptul că fiecare poziţie dintre cele $N$ nu trece decât o singură dată prin deque şi este şters tot cel mult o singură dată. \r\n\r\nÎn practică, pseudocodul poate arăta în felul următor:\r\n\r\n== code(cpp) |\r\n// S şirul de numere iniţial şi N lungimea sa\r\n\r\nSubalgoritmul push_in(deque, întreg p, funcţia fct) este:\r\n    cât timp (!deque.empty() şi fct(S[p], S[deque.back()])) execută\r\n        deque.pop_back();\r\n    deque.push_back(p);\r\nSfârşit;\r\n\r\nFuncţia query(deque, întreg j) este:\r\n    cât timp (!deque.empty() şi deque.front() <= j) execută\r\n        deque.pop_front();\r\n    return S[deque.front()];\r\nSfârşit;\r\n\r\nAlgoritmul este:\r\n    lg = 0;\r\n    pentru i = 1, N execută\r\n        // funcţia min(a, b) întoarce true dacă a < b\r\n        inserează(min_deq, i, min);\r\n        // funcţia max(a, b) întoarce true dacă a > b\r\n        inserează(max_deq, i, max);\r\n        cât timp ((j < i - Y sau query(max_deq, j) - query(min_deq, j) > Z) şi j < i - X) execută\r\n            j = j + 1;\r\n        // (j, i] este intervalul candidat la soluţia optimă pentru poziţia i\r\n        dacă (j <= i - X) şi (query(max_deq, j) - query(min_deq, j) <= Z) atunci\r\n            dacă (lg >= i - j) atunci\r\n                lg = i - j, start = j + 1, stop = i;\r\n    sfârşit_pentru\r\n\r\n    dacă (lg > 0) atunci\r\n        scrie lg, start, stop;\r\n    altfel\r\n        scrie -1;\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală va fi $O(N)$.\r\n\r\nh2(#problema-4). \'4. Trans\':problema/trans (ONI 2004)\r\n\r\nbq. Se dau $N$ blocuri de piatră, de culoare albă sau neagră aşezate în ordinea $1$, $2$,.., $N$. Blocurile de piatră trebuie să fie transportate în ordinea în care sunt, iar pentru aceasta va trebui închiriat un camion. Se mai dau $Q$ tipuri de camioane. Camionul de tipul $i (1 &le; i &le; Q)$ poate transporta maxim $K{~i~}$ blocuri de piatră la un moment dat şi pentru un transport se percepe taxa $T{~i~}$. Se impune condiţia ca toate blocurile de piatră plasate în camion la un transport sa aibă aceeaşi culoare. Aşadar, pentru a fi transportate toate blocurile, se va alege un camion de un anumit tip, iar camionul va efectua unul sau mai multe transporturi. Pentru a micşora suma totală plătită, există posibilitatea de a schimba culoarea oricărui bloc de piatră (din alb în negru sau din negru în alb); pentru fiecare bloc $i (1 &le; i &le; N)$ se cunoaşte suma $S{~i~}$ ce trebuie plătită pentru a-i schimba culoarea $C{~i~}$.\r\nCerinţă: Pentru fiecare dintre cele $Q$ tipuri de camioane, determinaţi suma minimă plătită pentru a transporta toate cele $N$ blocuri.\r\nRestricţii: $1 &le; N &le; 16 000$, $1 &le; Q &le; 100$, $1 &le; K{~i~} &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se bazează pe găsirea unei formule de recurenţă ce respectă principiul optimalităţii al metodei programării dinamice.\r\n\r\nPentru început, fixăm un camion dintre cele <tex> Q </tex>. Fie <tex> K </tex> numărul maxim de pietre pe care acesta le poate transporta şi <tex> T </tex> taxa percepută. Notăm <tex> sum_{i,c} </tex> costul pentru a schimba toate pietrele <tex> 1, 2, \\ldots, i </tex> în culoarea <tex> c </tex> (<tex> c = 0 </tex> pentru alb şi <tex> c = 1 </tex> pentru negru). Rezultă că în <tex> sum_{i,c} </tex> se vor însuma toate valorile <tex> S_{j} </tex>, cu <tex> j \\le i </tex> pentru care <tex> C_{j} = 1 - c </tex>. \r\n\r\nÎn continuare, considerăm <tex> bst_{i,c} </tex> costul minim pentru a transporta pietrele <tex> 1, 2, \\ldots, i </tex>, iar ultimul transport conţine pietre de culoare <tex> c </tex>. Întrucât nu putem transporta mai mult de <tex> K </tex> pietre, <tex> bst_{i,c} </tex> depinde doar de poziţiile <tex> i - K, i - K + 1, \\ldots, i - 1 </tex>. Cunoaştem că ultimul camion va transporta o secvenţă continuă de pietre începând de la o poziţie <tex> j + 1 </tex> până la poziţia <tex> i </tex>, unde <tex> i - K \\le j \\le i - 1 </tex>. Astfel, pentru  fiecare <tex> j </tex> în intervalul precedent, costul va fi <tex> Min(bst_{j,0}, bst_{j,1}) </tex> (transportăm primele <tex> j </tex> pietre cât mai ieftin) adunat cu <tex> sum_{i,c} - sum_{j,c} </tex> (costul transformării pietrelor <tex> j + 1, \\ldots, i </tex> în culoarea <tex> c </tex>) şi plus taxa <tex> T </tex>. Rezultă recurenţa:\r\n\r\n* <tex> bst_{i,c} = Min\\ \\{\\ Minim(bst_{j,0},\\ bst_{j,1}) + sum_{i,c} - sum_{j,c} + T\\ :\\ i - K \\le j \\le i - 1\\ \\}; </tex>\r\n\r\nDacă ne vom opri aici, complexitatea soluţiei va fi <tex> O(Q * N^{2}) </tex>.\r\n\r\nRelaţia de recurenţă poate fi îmbunătăţită. Observăm că pentru poziţia <tex> i </tex>, <tex> sum_{i,c} </tex> este o valoare constantă, ca şi <tex> T </tex>. Astfel, deducem următoarea relaţie de recurenţă:\r\n\r\n* <tex> bst_{i,c} = Min\\ \\{\\ Minim(bst_{j,0},\\ bst_{j,1}) - sum_{j,c}\\ :\\ i - K \\le j \\le i - 1\\ \\} + sum_{i,c} + T; </tex>\r\n\r\nNotez în continuare, pentru uşurinţă în scriere, <tex> T_{j,c} = Min(bst_{j,0}, bst_{j,1}) - sum_{j,c} </tex>. Să fixăm doi indici <tex> i_{1} </tex> şi <tex> i_{2} </tex>, astfel încât <tex> i - K \\le i_{1} < i_{2} \\le i - 1 </tex>. Dacă <tex> T_{i_{1},c} > T_{i_{2},c} </tex> atunci întotdeauna poziţia <tex> i_{2} </tex> va fi preferată poziţiei <tex> i_{1} </tex>. Când cele două nu se vor mai afla ambele în intervalul <tex> [i - K, i - 1] </tex>, poziţia eliminată va fi poziţia <tex> i_{1} </tex>. Dacă <tex> T_{i_{1},c} < T_{i_{2},c} </tex>, atunci nu putem decide care poziţie este mai bună în viitor, aşa că le vom păstra pe ambele. Rezultă mai departe că în intervalul <tex> [i - K, i - 1] </tex> vom avea o serie de indecşi candidaţi la minim <tex> i - K \\le i_{1} < i_{2} < \\ldots < i_{n} \\le i - 1 </tex> astfel încât <tex> T_{i_{1},c} < T_{i_{2},c} <  .. < T_{i_{n},c} </tex>. Mai departe, găsim <tex> bst_{i,c} = T_{i_{1},c} + sum_{i,c} + T </tex>. Urmează să îl introducem şi pe <tex> T_{i,c} </tex> în şirul de indecşi de mai sus, el fiind egal cu <tex> Minim(bst_{i,0}, bst_{i,1}) - sum_{i,c} </tex>. Acest lucru se va face în felul următor: se vor elimina din <tex> i_{n}, , i_{n-1}, \\ldots </tex> atâta timp cât <tex> T_{i_{n},c} > T_{i,c} </tex>, <tex> T_{i_{n-1},c} > T_{i,c} \\ldots </tex> adică atâta timp cât poziţia <tex> i </tex> este preferată lui <tex> i_{n}, i_{n-1}, \\ldots </tex>. Fiind la poziţia <tex> i + 1 </tex>, intervalul se va transforma în <tex> [i - K + 1, i] </tex>, aşadar, vom mai elimina din primii indici <tex> i_{1}, i_{2}, \\ldots </tex> atâta timp cât <tex> i_{1} < i - K + 1, i_{2} < i - K + 1, \\ldots </tex>.\r\n\r\nDupă cum am arătat şi la problema precedentă, acest şir de indecşi <tex> i_{1}, i_{2}, \\ldots, i_{n} </tex> are proprietatea că este un şir continuu de numere care admite inserări prin dreapta (tail) şi ştergeri prin stânga (head). Şir ce poate fi reprezentat printr-un deque. Cum fiecare index dintre <tex> 1, 2, \\ldots, N </tex> va trece o singură dată prin deque, complexitatea soluţiei va fi <tex> O(N) </tex> pentru fiecare camion, deci <tex> O(Q * N) </tex> în total.\r\n\r\nÎn practică, programul este scurt, clar şi eficient:\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\n#include <vector>\r\n#include <deque>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\nconst char iname[] = \"trans.in\";\r\nconst char oname[] = \"trans.out\";\r\n\r\n#define MAXN  16005\r\n#define Min(a, b) ((a) < (b) ? (a) : (b))\r\n#define FOR(i, a, b)  for (int i = (a); i <= (b); ++ i)\r\n\r\nint C[MAXN], S[MAXN], bst[MAXN][2], sum[MAXN][2], N;\r\n\r\nvoid insert(deque < pair <int, int> >& deq, const pair <int, int>& p) {\r\n    while (!deq.empty() && deq.back().second > p.second)\r\n        deq.pop_back();\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque < pair <int, int> >& deq, const int idx) {\r\n    while (deq.front().first < idx)\r\n        deq.pop_front();\r\n    return deq.front().second;\r\n}\r\n\r\nint work(const int K, const int T) {\r\n    deque < pair <int, int> > deq[2];       // pair (idx, value)\r\n    FOR (c, 0, 1)\r\n        insert(deq[c], pair <int, int>(0, 0));\r\n    FOR (i, 1, N) {   // obiectul i\r\n        FOR (c, 0, 1) // culoare\r\n            bst[i][c] = query(deq[c], i - K) + sum[i][c] + T;\r\n        FOR (c, 0, 1)\r\n            insert(deq[c], pair <int, int>(i, Min(bst[i][0], bst[i][1]) - sum[i][c]));\r\n    }\r\n    return Min(bst[N][0], bst[N][1]);\r\n}\r\n\r\nint main(void)\r\n{\r\n    ifstream in(iname);  ofstream out(oname);\r\n    in >> N;\r\n    FOR (i, 1, N) {\r\n        in >> C[i] >> S[i];\r\n        FOR (c, 0, 1)\r\n            sum[i][c] += sum[i - 1][c];\r\n        sum[i][1 - C[i]] += S[i];\r\n    }\r\n    int cnt, K, T;\r\n    in >> cnt;\r\n    FOR (i, 1, cnt)\r\n        in >> K >> T, out << work(K, T) << \"\\n\";\r\n\r\n    in.close(), out.close();\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#problema-5). \'5. Otilia\':problema/otilia  (.campion)\r\n\r\nbq. Otilia şi Burbucel au o grămadă de $N$ pietre şi vor juca un joc cu următoarele trei reguli: 1. Primul jucător are voie să ia din gramadă cel mult $K$ piese; 2. Cu excepţia primei mutări, fiecare jucător are voie să ia maxim $P * t$ pietre, unde $t$ este numărul de pietre care au fost substituite din grămadă la mutarea precedentă; 3. Pierde cel care mută ultimul (cel care ia ultimele pietre din grămadă).\r\nCerinţă: Se dau $M$ jocuri prin numerele $N$, $K$ şi $P$. Se cere să se determină dacă Otilia va câştiga fiecare din jocuri sau nu.\r\nRestricţii: $1 &le; M &le; 30 000$, $1 &le; N &le; 5 000 000$, $1 &le; K &le; N$, $1 &le; P &le; 10$.\r\n\r\nh3. Soluţie (Silviu Ganceanu):\r\n\r\nProblema se rezolvă prin programare dinamică. Soluţia se bazează pe observaţia de mai jos. Considerăm $P$-ul fixat şi notăm cu $stare(X, Y)$ poziţia de start în care avem $X$ pietre şi numărul maxim de pietre care se pot lua la prima mutare este $Y$.\r\n\r\n_Observaţia 1_: „Dacă există strategie sigură de câştig pentru $stare(X, Y)$ atunci există şi pentru orice $stare(X, T)$ cu $T &ge; Y$.” \r\n\r\nDe ce? Pentru că orice mutare validă pentru $stare(X, Y)$ este validă şi pentru $stare(X, T)$. Având această observaţie notăm cu $MinY[X] = Y$, $Y$ minim astfel încât avem strategie de câştig pentru $stare(X, Y)$.\r\n\r\n_Observaţia 2_: „{$stare(X, Y)$} este pierzătoare dacă şi numai dacă $Y < MinY[X]$.” \r\n\r\nAceasta reiese din definiţia lui $MinY[X]$.\r\n\r\n$MinY[X]$ se calculează după următoarea recurenţă, care rezultă din regulile jocului: \r\n\r\n* $MinY[X]$ este cel mai mic $i$ pentru care avem $MinY[X - i] > P * i$.\r\n\r\nDe aici se naşte prima soluţie, care este implementarea directă a recurenţei. Deşi complexitatea acesteia pare a fi $O(N^2^)$ ea se comportă foarte bine pentru $N &le; 500 000$. Aşadar, această soluţie acoperă aproximativ $50%$ din testele de intrare. Printr-o rafinare a acestei soluţii se obţine un algoritm de complexitate $O(N)$. Rafinarea se bazează pe: \r\n\r\n_Observaţia 3_: „Să presupunem că dorim să calculăm $MinY[X]$. Facem următoarea afirmaţie: orice poziţie _rea_ pentru $X$ (în care dacă mutăm pierdem) va fi _rea_ şi pentru $X + 1$.”\r\n\r\nAcest lucru este simplu de observat dacă privim ce înseamnă că o poziţie $Q$ e rea pentru $X$: \r\n\r\n* $MinY[Q] > X - Q$, pentru $X$;\r\n* $MinY[Q] > X - Q + 1$, pentru $X + 1$.\r\n\r\nEste evident că prima relaţie o implică pe cea de-a doua. În momentul acesta se poate construi următorul algoritm: având lista de poziţii care pot fi bune pentru $X$ (sortată descrescător) o căutăm pe cea mai mare ca valoare care este într-adevăr bună. În principiu, scoatem din capul listei poziţiile rele până când dăm de o poziţie bună. La listă se va adăuga şi $X$ şi se va trece la pasul următor. Operaţiile algoritmului sunt chiar operaţiile asupra unui deque.\r\n\r\nh2(#problema-6). \'6. Bcrc\':problema/bcrc (Stelele Informaticii)\r\n\r\nbq. Se consideră $N$ camere, numerotate de la $1$ la $N$, aşezate în cerc. Iniţial (la momentul de timp 0), ne aflăm în camera $1$. În fiecare moment de timp, putem alege să rămânem în camera în care ne aflăm sau să ne deplasăm într-o cameră vecină într-o unitate de timp. Se dă o listă de $M$ cutii ce conţin bomboane prin $T$, $C$ şi $B$: cutia apare la momentul $T$ în camera $C$ şi conţine $B$ bomboane. Cutia va dispărea la momentul $T + 1$.\r\nCerinţă: Cunoscând numărul de camere din labirint şi momentele de timp la care apar cutiile cu bomboane, determinaţi care este numărul maxim de bomboane pe care le putem culege.\r\nRestricţii: $3 &le; N &le; 2 048$, $0 &le; M &le; 50 000$, $1 &le; T &le; 1 000 000 000$, $1 &le; C &le; N$, $1 &le; B &le; 9 999$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia foloseşte metoda programării dinamice.\r\n\r\nO stare se reprezintă prin camera în care ne aflăm şi momentul de timp. Fie <tex> bst_{i,j} </tex> numărul maxim de bomboane culese până în momentul <tex> i </tex> când ne găsim în camera <tex> j </tex>. O observaţie evidentă este că <tex> bst_{i,j} </tex> se poate modifica doar în momentele în care apar cutiile. Prin urmare, vom considera momentele de timp când apar cutiile, momente ce sunt în număr de <tex> M </tex>, <tex> bst_{i,j} </tex> însemnând numărul maxim de bomboane culese ştiind că ne aflăm în camera <tex> j </tex> unde am cules cutia <tex> i </tex>. De cine depinde această stare? Ştim că <tex> bst_{i-1,1 \\ldots N} </tex> a fost deja calculat în mod optim. Să notăm cu <tex> T </tex> diferenţa de timp dintre momentele la care apare cutia <tex> i </tex> şi cutia <tex> i - 1 </tex>. În această stare, <tex> i </tex> şi cameră <tex> j </tex>, putem ajunge din maxim <tex> T </tex> camere spre stânga sau spre dreapta, întrucât fiecare deplasare între două camere costă o unitate de timp. De unde deducem că:\r\n\r\n* <tex> bst_{i,j} = Min\\{\\ bst_{i-1,j-T},\\ bst_{i-1,j-T+1}, \\ldots,\\ bst_{i-1,j}, \\ldots,\\ bst_{i-1,j+T-1},\\ bst_{i-1,j+T}\\ \\}; </tex>\r\n\r\nMetoda directă, şi aparent eficientă, constă în folosirea unui arbore de intervale pentru aflarea acestui minim. Însă, intervalul <tex> [j-T,j+T] </tex> se deplasează constant spre dreapta, dacă vom considera indicii <tex> j </tex> în ordine <tex> 1, 2, 3, \\ldots </tex>. În acest interval noile elemente se introduc prin dreapta şi altele se elimină prin stânga. Însă, cum am arătat în problemele precedente, nu avem nevoie de toate valorile din acest interval. Şi din acest motiv vom folosi un deque de lungime <tex> T * 2 + 1 </tex> cu care vom elimina poziţiile care nu sunt candidate la soluţie. Mai jos este o reprezentare grafică a acestei explicaţii.\r\n\r\np=. !deque-si-aplicatii?bcrc.png 40%!\r\n\r\nComplexitatea finală: <tex> O(M * N) </tex>.\r\n\r\nh2(#problema-7). \'7. Cut the Sequence\':http://acm.pku.edu.cn/JudgeOnline/problem?id=3017 (PKU) \r\n\r\nbq. Se dă o secvenţă $S$ de numere întregi de lungime $N$. Va trebui să se împartă secvenţa în mai multe subsecvenţe astfel încât suma valorilor din fiecare parte să nu depăşească un număr întreg $M$ dat, iar dacă însumăm maximul din fiecare subsecvenţă să obţinem o sumă cât mai mică.\r\nRestricţii: $0 &lt; N &le; 100 000$, $0 &le; S{~i~} &le; 1 000 000$.\r\n\r\nh3. Soluţie:\r\n\r\nŞi această soluţie foloseşte metoda programării dinamice. Construim <tex> bst_{i} </tex> egal cu costul minim de a împărţi primele <tex> i </tex> numere din <tex> S </tex>. Pentru a calcula <tex> bst_{i} </tex> alegem toate secvenţele posibile care încep la o poziţie <tex> j+1 </tex>, <tex> j < i </tex>, şi adunăm valorile corespunzătoare:\r\n\r\n* <tex> bst_{i} = Min\\{bst_{j} + Max\\{S_{j+1},.., S_{i}\\}\\ :\\ 0 \\le j < i, \\displaystyle\\sum_{k=j+1}^{i} S_{k} \\le M\\}; </tex>\r\n\r\nImplementarea directă a acestei recurenţe conduce la un algoritm de complexitate <tex> O(N^{2}) </tex>, dar care pentru restricţiile impuse nu este de ajuns.\r\n\r\nSă obţinem în continuare alte informaţii. Fie indicele <tex> j </tex> minim astfel încât <tex> \\displaystyle\\sum_{k=j+1}^{i} \\le M </tex>. Maximul obţinut din mulţimea <tex> \\{S_{j+1},.., S_{i}\\} </tex> se găseşte pe o poziţie <tex> j^{\'} </tex> unde <tex> j < j^{\'} \\le i </tex>. Însă, orice indice <tex> k </tex> cu <tex> j \\le k < j^{\'} </tex> are proprietatea că rezultatul expresiei <tex> Max\\{S_{k+1},.., S_{i}\\} </tex> se găseşte pe poziţia <tex> j^{\'} </tex>. Rezultă că <tex> \\forall k \\in \\{j, j+1,.., j^{\'}-1\\} </tex>, <tex> bst_{i} </tex> poate fi îmbunătăţit cu valoarea <tex> bst_{k} + S_{j^{\'}} </tex>. Minimul mulţimii <tex> \\{bst_{k} + S_{j^{\'}} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} </tex> este egal cu minimul expresiei <tex> \\{bst_{k} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} + S_{j^{\'}} (*) </tex>, deci, schimbând reperele, pentru maximul de pe poziţia <tex> j^{\'} </tex>, dacă lungimea secvenţei care se termină în <tex> i </tex> este cel puţin <tex> i-j^{\'}+1 </tex>, atunci optimul se obţine calculând rezultatul expresiei <tex> (*) </tex>. Pentru minimul pe un interval, <tex> [j, j^{\'}-1] </tex> al valorile vectorului <tex> bst </tex>, putem folosi un arbore de intervale pentru <tex> O(log_{2}N) </tex> pe interogare.\r\n\r\nDar, lungimea optimă a ultimei secvenţe ce se termină în <tex> i </tex> poate fi mai mică decât <tex> i-j^{\'}+1 </tex>, deci poate fi cel mult <tex> i-j^{\'} </tex>. Optimul se găseşte printre elementele mulţimii <tex> \\{bst_{k} + Max\\{S_{k+1},..,S_{i}\\} : j^{\'} \\le k < i\\} </tex>. Dacă procedăm ca la pasul anterior vom obţine un alt indice <tex> j^{\'\'} </tex> cu aceleaşi proprietăţi pentru secvenţa <tex> [j^{\'}, i] </tex> precum <tex> j^{\'} </tex> pentru secvenţa <tex> [j, i] </tex>.\r\n\r\nInductiv obţinem un şir de indici <tex> j_{0} = j < j_{1} < j_{2} < .. < j_{K} = i </tex> astfel încât <tex> S_{j_{1}} </tex> este cel mai mare element al secvenţei <tex> (j, i] </tex>, <tex> S_{j_{2}} </tex> cel mai mare element al secvenţei <tex> (j_{1}, i] </tex>, şi aşa mai departe, când <tex> j_{K} </tex> este chiar <tex> i </tex>.\r\n\r\nCu ajutorul relaţiei <tex> (*) </tex> şi a şirului <tex> j_{1} < j_{2} < .. < j_{K} = i </tex> vom construi un alt vector <tex> iMin </tex> cu proprietatea că <tex> iMin_{p} = Min\\{bst_{r} + S_{j_{p}} : j_{p-1} \\le r < j_{p}\\} </tex>. În final, <tex> bst_{i} = Minim\\{iMin_{1}, iMin_{2}, .., iMin_{K}\\} </tex>, rezultat pe care îl putem obţine în <tex> O(log_{2}N) </tex> dacă folosim un arbore de intervale.\r\n\r\nÎnsă, cum se construieşte şirul <tex> j_{1} < j_{2} < .. < j_{K} = i </tex>? În \'a doua problemă\':deque-si-aplicatii#problema-2 am construit cu ajutorul unui deque exact şirul de indici de care avem nevoie aici. Când vom înainta la indicele <tex> i + 1 </tex> vom modifica şirul astfel încât să respecte proprietăţile de mai sus utilizând operaţiile normale asupra unui deque. Mai sus am menţionat cum se obţine <tex> bst_{i} </tex> lucru care implică combinarea structurilor de deque şi arbore de intervale. Arborele de intervale reţine valorile lui <tex> iMin </tex> pentru fiecare element al dequelui. \r\n\r\nPentru a înţelege cum funcţionează acest algoritm să considerăm ca date de intrare şirul <tex> S = \\{5, 9, 4, 7, 4, 1, 6, 3\\} </tex> şi <tex> M = 15 </tex>. Perechile din deque sunt de forma <tex> (S_{i}, iMin_{p}) </tex>. Fie <tex> i = 1, 2, \\ldots 8 </tex>:\r\n\r\n* <tex> i = 1: j = 0, head = 1, tail = 1, deque = \\{\\ (5, 0)\\ \\} \\Rightarrow bst_{1} = 5; </tex>\r\n* <tex> i = 2: j = 0, head = 1, tail = 1, deque = \\{\\ (9, 0)\\ \\} \\Rightarrow bst_{2} = 9; </tex>\r\n* <tex> i = 3: j = 1, head = 1, tail = 2, deque = \\{\\ (9, 5),\\ (4, 9)\\ \\} \\Rightarrow bst_{3} = 13; </tex>\r\n* <tex> i = 4: j = 2, head = 2, tail = 2, deque = \\{\\ (7, 9)\\ \\} \\Rightarrow bst_{4} = 16; </tex>\r\n* <tex> i = 5: j = 2, head = 2, tail = 3, deque = \\{\\ (7, 9),\\ (4, 16)\\ \\} \\Rightarrow bst_{5} = 16; </tex>\r\n* <tex> i = 6: j = 3, head = 2, tail = 4, deque = \\{\\ (7, 13),\\ (4, 16),\\ (1, 16)\\ \\} \\Rightarrow bst_{6} = 17; </tex>\r\n* <tex> i = 7: j = 4, head = 3, tail = 3, deque = \\{\\ (6, 16)\\ \\} \\Rightarrow bst_{7} = 22; </tex>\r\n* <tex> i = 8: j = 4, head = 3, tail = 4, deque = \\{\\ (6, 16),\\ (3, 22)\\ \\} \\Rightarrow bst_{8} = 22; </tex>\r\n\r\nMai jos se vede o figură în care elementele unui deque sunt defapt o secvenţă „continuă” de frunze ale unui arbore de intervale pentru cazul <tex> i = 6 </tex>.\r\n\r\np=. !deque-si-aplicatii?PKU0.png 60%!\r\n\r\np=. _Numărul maxim de elemente ce pot trece prin deque este $8$. În figură, arborele ţine minimul de pe poziţiile $2$, $3$, $4$ din deque._\r\n\r\nAlgoritmul în pseudocod arată în felul următor:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    sum  = 0;\r\n    last = 0;\r\n    // indicii head si tail ai dequeului\r\n    head = tail = 1;\r\n    // poziţia lui bst[0] se inserează în deque\r\n    deque[1] = 0;\r\n    pentru i = 1, N execută\r\n        sum += S[i];\r\n        temp = bst[ deque[tail] ];\r\n        cât timp (head <= tail) şi (S[ deque[tail] ] <= S[i]) execută\r\n            temp = Min(temp, iMin[tail]);\r\n            tail --;\r\n        sfârşit;\r\n        // adaug poziţia i la deque\r\n        tail ++;\r\n        deque[tail] = i;\r\n        // actualizez iMin[]\r\n        iMin[tail]  = temp;\r\n        // actualizez T[], arborele de intervale pe deque[]\r\n        Update(T, tail, iMin[tail] + S[i]);\r\n        // suma valorilor din [last, i] trebuie să nu depăşească M\r\n        cât timp (sum > M) execută\r\n            sum -= S[last];\r\n            dacă (deque[head] == last) atunci\r\n                head ++;\r\n            sfârşit;\r\n            last ++;\r\n        sfârşit;\r\n        // actualizez iMin[], Tb[] arborele de intervale pe bst[]\r\n        iMin[head] = Query(Tb, Max(last - 1, 0), deque[head] - 1);\r\n        // actualizez T[]\r\n        Update(T, head, iMin[head] + S[ deque[head] ]);\r\n        // reţin optimul pentru poziţia curentă\r\n        bst[i] = Query(T, head, tail);\r\n        // actualizez Tb[]\r\n        Update(Tb, i, bst[i]);\r\n    sfârşit;\r\n    scrie bst[N];\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală este <tex> O(N*log_{2}N) </tex>.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nFilozofia din spatele structurii de deque devine utilă, de obicei, în părţile finale ale rezolvării unei probleme. Însă, ce pot spune cu certitudine este că această structură de date pe cât este de simplă pe atât este de eficientă şi necesară.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\nÎnţelegerea profundă nu se poate realiza decât prin rezolvarea a cât mai multe probleme. Succes!\r\n\r\n* \'Deque\':problema/deque, _Arhiva educaţională_\r\n* \'Secvenţă\':problema/secventa\r\n* \'Secvenţă 3\':problema/secv3\r\n* \'Secvenţă 4\':problema/secv4\r\n* \'Sum 2\':problema/sum2, _Stelele Informaticii 2003_\r\n* \'Drept 2\':problema/drept2, _Lotul Naţional de Informatică, 2006_\r\n* \'Copaci 2\':problema/copaci2, _.campion_\r\n* \'Brânză\':problema/branza\r\n* \'Struţi\':problema/struti\r\n* \'Trompetă\':problema/trompeta\r\n* \'Buline\':problema/buline\r\n* \'Balans\':problema/balans\r\n* \'Gard\':problema/gard, _ONI 2002_\r\n* \'Ghiozdan\':problema/ghiozdan\r\n* \'Munte4\':problema/munte4, _Lotul Naţional de Informatică, 2005_\r\n* \'Cover\':problema/cover, _ONI 2007, Baraj_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Cosmin Negruşeri, \"_Probleme cu secvenţe_\":probleme-cu-secvente\r\n# Dana Lica, \"_Arbori de intervale şi aplicaţii în geometria computaţională_\":arbori-de-intervale\r\n# Cătălin Frâncu, \"_Heapuri_\":heapuri\r\n# Marius Stroe, \"_Treapuri_\":treapuri\r\n# \'C++ Reference\':http://www.cplusplus.com/',3146,'public',NULL,NULL),('planificare/sedinta-20090216','Sedinta 2009-02-16','2009-02-09 14:25:39','2009-02-10 16:11:05','h1. Sedinta 2009-02-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Februarie* la ora *19^00^*, _cel mai probabil_ la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")== (nu s-ar putea un pic mai devreme ca sa prindem si metroul la intoarcere?)\r\n* Tu?\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090126| ...|\r\n|Algoritmiada| ... |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Concursul Centrelor de Excelenta | ==user(user=\"filipb\" type=\"tiny\")== ?? |\r\n|Concurs infoarena in engleza/infoarena.org | ... |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n* Ce se mai aude cu initiativa in care donam calculatoare utilizate?\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n...\r\n\r\nh2. Notiţe\r\n\r\n...\r\n',15,'public',NULL,NULL),('pd','Programare dinamica','2007-12-04 21:25:10','2009-11-01 13:47:53','h1. Programare dinamica\r\n\r\n(Categoria _Tehnici de programare_, autor _Catalin Tiseanu_)\r\n\r\nPlan de atac (probleme-candidat):\r\n\r\n1. http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en\r\nReducerea complexitatii, transformarea problemei intr-una de construire a unui arbore binar.\r\n\r\n2. http://code.google.com/codejam/contest/dashboard?c=32001#s=p0&a=3\r\n\r\n\r\n3. http://code.google.com/codejam/contest/dashboard?c=32001#s=p3&a=3\r\n\r\n\r\n4. http://code.google.com/codejam/contest/dashboard?c=32015#s=p1&a=1\r\n\r\n\r\n5. http://code.google.com/codejam/contest/dashboard?c=32010#s=p3&a=3\r\n\r\nh2. Sugestii Silviu\r\n\r\n* poate ca nu trebuie sa spunem tot despre programare dinamica intr-un singur articol; spre exemplu putem facem doua articole: PD basic si PD advanced\r\n* cred ca era si ceva prin Cartea lui Francu\' despre programare dinamica; ar merge incorporat (eventual in pd_basic).\r\n\r\nh2. Introducere\r\n\r\nProgramarea dinamică este o metodă utilă pentru a rezolva probleme care pot fi obţinute prin compunerea a mai multor bucăţi, a căror soluţie poate fi apoi determinată optim. Se bazează în principal pe proprietatea unei probleme de a putea fi rezolvată optim dacă se cunosc soluţii optime la sub-problemele ei.\r\nDe menţionat că \'programare\' nu se referă aici la scrierea de cod într-un limbaj de programare, ci la \'programare matematica\', care constă în optimizarea unei funcţii prin alegerea de valori dintr-o mulţime anume. \r\n\r\nScopul acestui articol nu este să ofere o introducere in programare dinamică (pentru aceasta poate fi consultat excelentul tutorial de pe TopCoder \"Dynamic Programming : From novice to advanced\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg). În schimb, acest articol îşi propune să ofere nişte \'smenuri\' mai avansate de rezolvare a problemelor cu programare dinamică. \r\n\r\nh2. Programare dinamică cu reducerea loop-ului interior\r\n\r\nSă considerăm următoarea problema:\r\n\r\nh3(#problema-1). Problema 1: \'Drilling\':http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en\r\n\r\nbq. Se da un şir de $N$ numere naturale $(a{~1~}, a{~2~}, ..., a{~N~})$. Se ştie că un prefix al acestui şir (posibil chiar prefixul nul) este prost. Se ştie de asemenea că se poate testa orice poziţie $i$ în timp $a{~i~}$ dacă este proastă. Să se determine timpul minim în cazul cel mai defavorabil pentru aflarea lungimii maxime a prefixului şirului care este prost.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(8 24 12 6)$, răspunsul ar fi $42$. Astfel, se testează mai întâi poziţia $2$. Dacă nu este proastă, mai rămâne de testat poziţia $1$. Altfel, în cel mai rău caz mai trebuie testate poziţiile $3$ şi $4$, aducând timpul total la $24 + 12 + 6 = 42$.\r\n\r\nh3. Rezolvare:\r\n\r\nO să începem prin a da altă îmbrăcăminte problemei. Astfel, să ne imaginăm că am construi un arbore binar de căutare pe şirul dat, având drept chei poziţiile din şir, şi drept valori auxiliare valorile poziţiilor respective din şir (un nod cu cheia $i$ va avea valoarea auxiliara $a{~i~}$.\r\nAcum, există mulţi arbori binari de căutare posibile pentru şirul iniţial. Totuşi, să presupunem că am construit unul, pe care îl considerăm de acum ca fixat. Atunci, strategia noastra de testare a elementelor din şir se va desfăşura conforma arborelui. Astfel, testăm mai întâi în poziţia din rădăcină. Dacă poziţia respectivă este proastă, ne ducem în fiul drept. Altfel, mergem in fiul stâng. În ambele cazuri se reia procedeul. Căutarea se termină cand nu mai putem merge într-un fiu. \r\n\r\nAcum, să observăm că dacă considerăm costul unui drum în arbore de la rădăcină la o frunză ca suma valorilor auxiliare din drumul (unic) respectiv, atunci se observă că costul strategiei bazate pe acest arbore este chiar costul maxim al unui drum ! De acum încolo, vom defini costul unui arbore ca costul maxim al unui drum din el. Să exemplificăm pe şirul din exemplu:\r\n\r\nSe observă că costul maxim al unui drum este $42$, minim posibil, exact ca răspunsul din exemplu.\r\nDeci, am redus problema la construirea unui arbore binar de căutare, care are costul minim.\r\n\r\nAcum devine clară o primă soluţie folosind programarea dinamică. Astfel, să presupunem că notăm cu $opt[i][j]$ costul minim al unui arbore construit pe cheile $(i, i + 1, ..., j)$. Fie $r[i][j]$\r\n\r\npoziţia rădăcinii arborelui cu costul minim. În cazul existenţei mai multor rădăcini posibile, se alege cea mai din stânga.\r\n\r\nh2. Programare dinamica folosind bitmask\r\n\r\nIn continuare vom vedea un exemplu de programare dinamica unde vom folosi un bitmask (codificat pe un intreg) pentru a tine spatiul starilor.\r\n\r\nAstfel sa presupunem ca avem nevoie sa tinem un vector caracteristic pentru o multime.\r\nDaca cardinalul acesteia este suficient de mic putem folosi un intreg pentru a codifica aceasta informatie astfel:\r\n\r\nFie multimea A = { x{~1~}, x{~2~}, ... x{~n~} }.\r\nAtunci bitmaskul unei partitii a lui A, MASK, va avea bitul i egal cu 1 numai si numai daca x{~i~} apartine partitiei.\r\n\r\nDesigur, aceasta reprezentare duce la o complexitate direct proportionala cu 2 ^card(A)^.\r\n\r\nh3. Exemplu\r\n\r\n\r\nh2. Programare dinamica folosind vectori de numere intregi\r\n\r\nTo be continued ... \r\n\r\n',958,'public',NULL,NULL),('pd','Programare dinamica','2007-12-04 21:25:10','2009-11-01 13:18:21','h1. Programare dinamica\r\n\r\n(Categoria _Tehnici de programare_, autor _Catalin Tiseanu_)\r\n\r\nPlan de atac (probleme-candidat):\r\n\r\n1. http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en\r\nReducerea complexitatii, transformarea problemei intr-una de construire a unui arbore binar.\r\n\r\nAlo Alo Andrane\r\n\r\n2. http://code.google.com/codejam/contest/dashboard?c=32001#s=p0&a=3\r\n\r\n\r\n3. http://code.google.com/codejam/contest/dashboard?c=32001#s=p3&a=3\r\n\r\n\r\n4. http://code.google.com/codejam/contest/dashboard?c=32015#s=p1&a=1\r\n\r\n\r\n5. http://code.google.com/codejam/contest/dashboard?c=32010#s=p3&a=3\r\n\r\nh2. Sugestii Silviu\r\n\r\n* poate ca nu trebuie sa spunem tot despre programare dinamica intr-un singur articol; spre exemplu putem facem doua articole: PD basic si PD advanced\r\n* cred ca era si ceva prin Cartea lui Francu\' despre programare dinamica; ar merge incorporat (eventual in pd_basic).\r\n\r\nh2. Introducere\r\n\r\nProgramarea dinamică este o metodă utilă pentru a rezolva probleme care pot fi obţinute prin compunerea a mai multor bucăţi, a căror soluţie poate fi apoi determinată optim. Se bazează în principal pe proprietatea unei probleme de a putea fi rezolvată optim dacă se cunosc soluţii optime la sub-problemele ei.\r\nDe menţionat că \'programare\' nu se referă aici la scrierea de cod într-un limbaj de programare, ci la \'programare matematica\', care constă în optimizarea unei funcţii prin alegerea de valori dintr-o mulţime anume. \r\n\r\nScopul acestui articol nu este să ofere o introducere in programare dinamică (pentru aceasta poate fi consultat excelentul tutorial de pe TopCoder \"Dynamic Programming : From novice to advanced\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg). În schimb, acest articol îşi propune să ofere nişte \'smenuri\' mai avansate de rezolvare a problemelor cu programare dinamică. \r\n\r\nh2. Programare dinamică cu reducerea loop-ului interior\r\n\r\nSă considerăm următoarea problema:\r\n\r\nh3(#problema-1). Problema 1: \'Drilling\':http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en\r\n\r\nbq. Se da un şir de $N$ numere naturale $(a{~1~}, a{~2~}, ..., a{~N~})$. Se ştie că un prefix al acestui şir (posibil chiar prefixul nul) este prost. Se ştie de asemenea că se poate testa orice poziţie $i$ în timp $a{~i~}$ dacă este proastă. Să se determine timpul minim în cazul cel mai defavorabil pentru aflarea lungimii maxime a prefixului şirului care este prost.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(8 24 12 6)$, răspunsul ar fi $42$. Astfel, se testează mai întâi poziţia $2$. Dacă nu este proastă, mai rămâne de testat poziţia $1$. Altfel, în cel mai rău caz mai trebuie testate poziţiile $3$ şi $4$, aducând timpul total la $24 + 12 + 6 = 42$.\r\n\r\nh3. Rezolvare:\r\n\r\nO să începem prin a da altă îmbrăcăminte problemei. Astfel, să ne imaginăm că am construi un arbore binar de căutare pe şirul dat, având drept chei poziţiile din şir, şi drept valori auxiliare valorile poziţiilor respective din şir (un nod cu cheia $i$ va avea valoarea auxiliara $a{~i~}$.\r\nAcum, există mulţi arbori binari de căutare posibile pentru şirul iniţial. Totuşi, să presupunem că am construit unul, pe care îl considerăm de acum ca fixat. Atunci, strategia noastra de testare a elementelor din şir se va desfăşura conforma arborelui. Astfel, testăm mai întâi în poziţia din rădăcină. Dacă poziţia respectivă este proastă, ne ducem în fiul drept. Altfel, mergem in fiul stâng. În ambele cazuri se reia procedeul. Căutarea se termină cand nu mai putem merge într-un fiu. \r\n\r\nAcum, să observăm că dacă considerăm costul unui drum în arbore de la rădăcină la o frunză să fie suma valorilor auxiliare din drumul (unic) respectiv, atunci se observă că costul strategiei bazate pe acest arbore este chiar costul maxim al unui drum ! Să exemplificăm pe şirul din exemplu:\r\n\r\nSe observă că cel mai lung \r\n\r\n\r\n\r\nh2. Programare dinamica folosind bitmask\r\n\r\nIn continuare vom vedea un exemplu de programare dinamica unde vom folosi un bitmask (codificat pe un intreg) pentru a tine spatiul starilor.\r\n\r\nAstfel sa presupunem ca avem nevoie sa tinem un vector caracteristic pentru o multime.\r\nDaca cardinalul acesteia este suficient de mic putem folosi un intreg pentru a codifica aceasta informatie astfel:\r\n\r\nFie multimea A = { x{~1~}, x{~2~}, ... x{~n~} }.\r\nAtunci bitmaskul unei partitii a lui A, MASK, va avea bitul i egal cu 1 numai si numai daca x{~i~} apartine partitiei.\r\n\r\nDesigur, aceasta reprezentare duce la o complexitate direct proportionala cu 2 ^card(A)^.\r\n\r\nh3. Exemplu\r\n\r\n\r\nh2. Programare dinamica folosind vectori de numere intregi\r\n\r\nTo be continued ... \r\n\r\n',958,'public',NULL,NULL),('pd','Programare dinamica','2007-12-04 21:25:10','2009-11-01 12:04:57','h1. Programare dinamica\r\n\r\n(Categoria _Tehnici de programare_, autor _Catalin Tiseanu_)\r\n\r\nPlan de atac (probleme-candidat):\r\n\r\n1. http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en\r\n2. http://code.google.com/codejam/contest/dashboard?c=32001#s=p0&a=3\r\n3. http://code.google.com/codejam/contest/dashboard?c=32001#s=p3&a=3\r\n4. http://code.google.com/codejam/contest/dashboard?c=32015#s=p1&a=1\r\n5. http://code.google.com/codejam/contest/dashboard?c=32010#s=p3&a=3\r\n\r\nh2. Sugestii Silviu\r\n\r\n* poate ca nu trebuie sa spunem tot despre programare dinamica intr-un singur articol; spre exemplu putem facem doua articole: PD basic si PD advanced\r\n* cred ca era si ceva prin Cartea lui Francu\' despre programare dinamica; ar merge incorporat (eventual in pd_basic).\r\n\r\nh2. Introducere\r\n\r\nProgramarea dinamica este o metoda utila pentru a rezolva probleme care pot fi obtinute prin compunerea a mai multor bucati, a caror solutie poate fi apoi determinata optim. Se bazeaza in principal pe proprietatea unei probleme de a putea fi rezolvata optim daca se cunosc solutii optime la sub-problemele ei.\r\nDe mentionat ca \'programare\' nu se refera aici la scrierea de cod intr-un limbaj de programare, si la \'programare matematica\', care consta in optimizarea unei functii prin alegerea de valori dintr-un multime anume. \r\n\r\nScopul acestui articol nu este sa ofere o introducere in programare dinamica (pentru aceasta poate fi consultat excelentul tutorial de pe TopCoder \'Dynamic Programming: From novice to advanced\' http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg). In schimb, acest articol isi propune sa ofere niste \'smenuri\' mai avansate de rezolvare a problemelor cu programare dinamica, \r\n\r\nh2. Programare dinamica cu reducerea loop-ului interior\r\n\r\nSa incepem cu urmatoarea problema:\r\n\r\n\r\n\r\nh2. Programare dinamica folosind bitmask\r\n\r\nIn continuare vom vedea un exemplu de programare dinamica unde vom folosi un bitmask (codificat pe un intreg) pentru a tine spatiul starilor.\r\n\r\nAstfel sa presupunem ca avem nevoie sa tinem un vector caracteristic pentru o multime.\r\nDaca cardinalul acesteia este suficient de mic putem folosi un intreg pentru a codifica aceasta informatie astfel:\r\n\r\nFie multimea A = { x{~1~}, x{~2~}, ... x{~n~} }.\r\nAtunci bitmaskul unei partitii a lui A, MASK, va avea bitul i egal cu 1 numai si numai daca x{~i~} apartine partitiei.\r\n\r\nDesigur, aceasta reprezentare duce la o complexitate direct proportionala cu 2 ^card(A)^.\r\n\r\nh3. Exemplu\r\n\r\n\r\nh2. Programare dinamica folosind vectori de numere intregi\r\n\r\nTo be continued ... \r\n\r\n',958,'public',NULL,NULL),('algoritmiada-2009/runda-3/solutii','Solutii Algoritmiada 2009, Runda 2','2009-02-11 14:15:33','2009-02-11 14:15:33','h1. Solutii Algoritmiada 2009, Runda 2\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Marmote\':algoritmiada-2009/runda-2/solutii#marmote\r\n* \'Ejoc\':algoritmiada-2009/runda-2/solutii#ejoc\r\n* \'Bazaconii\':algoritmiada-2009/runda-2/solutii#bazaconii\r\n* \'Colier\':algoritmiada-2009/runda-2/solutii#colier\r\n* \'Papuci\':algoritmiada-2009/runda-2/solutii#papuci\r\n* \'Nrsec\':algoritmiada-2009/runda-2/solutii#nrsec\r\n* \'Jap\':algoritmiada-2009/runda-2/solutii#jap\r\n\r\n==include(page=\"algoritmiada-2009/runda-2/solutii/marmote\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-2/solutii/ejoc\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-2/solutii/bazaconii\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-2/solutii/colier\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-2/solutii/papuci\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-2/solutii/nrsec\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-2/solutii/jap\")==\r\n',1490,'public',NULL,NULL),('planificare/sedinta-20091023','Ședință 2009-10-23','2009-10-20 12:14:02','2009-10-28 20:21:23','h1. Şedinţă 2009-10-23\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Vineri* la ora *19^00^* la Cafepedia de la Universitate.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== dupa 16:00\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada 2010 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| Parteneriat media cu AI contest in Poli | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| Tabăra infoarena | ==user(user=\"wickedman\" type=\"tiny\")== |\r\n| Stare Evaluator | ==user(user=\"svalentin\" type=\"tiny\")== |\r\n| Colaborare Poli | ==user(user=\"svalentin\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* S-a votat IAP #13\r\n* Cristi vorbeste cu Buraga legat de sponsorizare\r\n* Silviu face blog post despre noul Presedinte %{color:red}(done)%\r\n* Cristian ii face card Cristinei si lui Cosmin.\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")== vicepresedinte responsabil cu Development\r\n* ==user(user=\"pauldb\" type=\"tiny\")== vicepresedinte responsabil cu Algoritmiada\r\n* ==user(user=\"stef2n\" type=\"tiny\")== vicepresedinte responsabil cu Content\r\n* Bogdan se ocupa de organizat concursuri\r\n* Bogdan scrie tickete pentru fixuri la Virtual Contest %{color:red}(done)%\r\n* Prostu se ocupa de Calendar\r\n* Stefan vorbeste cu Marius despre Articole %{color:red}(done)%\r\n* Moare \"IAP #7\":propuneri/7-community-ladder, Cristi actualizeaza status\r\n* Cosmin scrie newsletter de acum\r\n* Cosmin se ocupa de Strangere Fonduri\r\n* Cosmin vorbeste cu Tibi despre Development\r\n* Bogdan e responsabil de Taguri\r\n* Cristi intreaba la Hostway daca ne mai dau o masina virtuala\r\n* Vali face testing pe masina virtuala\r\n* pe 22 noiembrie va fi prima runda de Algoritmiada\r\n* Cosmin, Silviu si Vali fac mapa pentru sponsori pana la *sfarsitul lunii*\r\n* Silviu trimite bugetul lui Paul %{color:red}(done)%\r\n* Cristi da reply la Amazon\r\n* Paul face pagini si buget pentru algoritmiada pana la sfarsitul lunii %{color:red}(1/2 done)%\r\n* Cosmin vorbeste cu Cristina despre comunicate de presa\r\n* Cosmin vorbeste la Orange Concept Store\r\n* Vali vorbeste cu Vlad Posea despre colaborare si daca ne poate ajuta cineva cu jailrun java\r\n* Silviu vorbeste cu Octavian Voicu despre AI Contest %{color:red}(mail sent)%\r\n\r\nh2(#notite). Notite\r\n\r\n* Cristi i-a dat lui Vali 23 RON pentru bilet tren Algoritmiada 2009\r\n* Se scrie retry loop pentru eval\r\n* Cristi plateste 120 RON pentru consumatie',2044,'protected',NULL,NULL),('planificare/sedinta-20091023','Ședință 2009-10-23','2009-10-20 12:14:02','2009-10-26 22:14:33','h1. Şedinţă 2009-10-23\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Vineri* la ora *19^00^* la Cafepedia de la Universitate.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== dupa 16:00\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada 2010 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| Parteneriat media cu AI contest in Poli | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| Tabăra infoarena | ==user(user=\"wickedman\" type=\"tiny\")== |\r\n| Stare Evaluator | ==user(user=\"svalentin\" type=\"tiny\")== |\r\n| Colaborare Poli | ==user(user=\"svalentin\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* S-a votat IAP #13\r\n* Cristi vorbeste cu Buraga legat de sponsorizare\r\n* Silviu face blog post despre noul Presedinte %{color:red}(done)%\r\n* Cristian ii face card Cristinei si lui Cosmin.\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")== vicepresedinte responsabil cu Development\r\n* ==user(user=\"pauldb\" type=\"tiny\")== vicepresedinte responsabil cu Algoritmiada\r\n* ==user(user=\"stef2n\" type=\"tiny\")== vicepresedinte responsabil cu Content\r\n* Bogdan se ocupa de organizat concursuri\r\n* Bogdan scrie tickete pentru fixuri la Virtual Contest %{color:red}(done)%\r\n* Prostu se ocupa de Calendar\r\n* Stefan vorbeste cu Marius despre Articole\r\n* Moare \"IAP #7\":propuneri/7-community-ladder, Cristi actualizeaza status\r\n* Cosmin scrie newsletter de acum\r\n* Cosmin se ocupa de Strangere Fonduri\r\n* Cosmin vorbeste cu Tibi despre Development\r\n* Bogdan e responsabil de Taguri\r\n* Cristi intreaba la Hostway daca ne mai dau o masina virtuala\r\n* Vali face testing pe masina virtuala\r\n* pe 22 noiembrie va fi prima runda de Algoritmiada\r\n* Cosmin, Silviu si Vali fac mapa pentru sponsori pana la *sfarsitul lunii*\r\n* Silviu trimite bugetul lui Paul %{color:red}(done)%\r\n* Cristi da reply la Amazon\r\n* Paul face pagini si buget pentru algoritmiada pana la sfarsitul lunii %{color:red}(1/2 done)%\r\n* Cosmin vorbeste cu Cristina despre comunicate de presa\r\n* Cosmin vorbeste la Orange Concept Store\r\n* Vali vorbeste cu Vlad Posea despre colaborare si daca ne poate ajuta cineva cu jailrun java\r\n* Silviu vorbeste cu Octavian Voicu despre AI Contest %{color:red}(mail sent)%\r\n\r\nh2(#notite). Notite\r\n\r\n* Cristi i-a dat lui Vali 23 RON pentru bilet tren Algoritmiada 2009\r\n* Se scrie retry loop pentru eval\r\n* Cristi plateste 120 RON pentru consumatie',1490,'protected',NULL,NULL),('implica-te/scrie-articole','Scrie articole','2007-03-28 22:23:46','2009-05-30 13:39:43','h1. Scrie articole ==Stars(rating=\"4\")==\r\n\r\nFolosind modelul de \'wiki\':documentatie/wiki, infoarena ofera sansa tuturor membrilor sai sa contribuie la realizarea de articole sau la imbunatatirea celor existente. Daca vrei sa afli mai multe despre conceptul de wiki intra \'aici\':http://en.wikipedia.org/wiki/Wiki, iar daca vrei sa contribui la acesta initiativa citeste mai jos ce trebuie sa faci.\r\n\r\nh2. De ce m-as baga?\r\n\r\n* O cariera in cercetare in informatica poate debuta cu niste articole online!\r\n* Vei invata care sunt elementele cheie pentru a scrie un articol.\r\n* Vei invata pe altii ceea ce stii, asa cum probabil si tu ai invatat din articolele deja \'existente\':articole.\r\n\r\nh2. Ce pot sa fac?\r\n\r\nDe-a lungul timpului, utilizatorii infoarena si-au manifestat interesul in a scrie articole pentru intreaga comunitate. In momentul de fata ne concentram eforturile atat pe completarea si aducerea la o forma prezentabila a acestor articole vechi, cat si pe scrierea de articole noi. Sunt 3 moduri in care poti contribui:\r\n\r\nh3. 1. Ajuta-ne la ce lucram acum\r\n\r\nIn tabelul de mai jos poti gasi articolele incepute, impreuna cu stadiul in care se gaseste fiecare. Daca esti dornic sa ne ajuti, alege-ti unul din articolele de care nu se ocupa nimeni si ia legatura cu coordonatorul proiectului ca sa afli ce mai e de facut la el.\r\n\r\ntable. |_. Titlu |_. Autor |_. Stadiu |_. Voluntar(i) |\r\n| \'Flux si cuplaj\':flux-si-cuplaj | ==user(user=\"blasterz\" type=\"tiny\")== | IN LUCRU | ==user(user=\"blasterz\" type=\"tiny\")== |\r\n| \'Teoria jocurilor\':teoria-jocurilor | ==user(user=\"filipb\" type=\"tiny\")== | IN LUCRU | ==user(user=\"filipb\" type=\"tiny\")== |\r\n| \'Psihologia concursurilor de informatica - Lucrul cu numere mari\':lucrul-cu-nr-mari | ==user(user=\"cata00\" type=\"tiny\")== | IMBUNATATIRE CONTINUT | ? |\r\n| Psihologia concursurilor de informatica - Lucrul cu structuri mari de date | ==user(user=\"cata00\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| Psihologia concursurilor de informatica - Probleme de concurs | ==user(user=\"cata00\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Probleme de taietura\':downloads?action=download&file=taietura.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Transformari geometrice\':downloads?action=download&file=transformari_geometrice.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | IN LUCRU |  ==user(user=\"Marius\" type=\"tiny\")== |\r\n| \'Problema majoritatii votului\':downloads?action=download&file=problema_majoritatii.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n\r\nh3. 2. Preia si dezvolta un subiect mai vechi\r\n\r\nAi nevoie de un impuls pentru a-ti da drumul la scris? Sunt cateva articole pe infoarena incepute, dar abandonate, precum si niste schite. Poti folosi ideile de start ale autorului si il poti transforma intr-un articol bine documentat. In plus, poti lua legatura cu autorul initial si poti afla viziunea sa asupra subiectului. Iata o lista de articole abandonate si de schite:\r\n\r\ntable. |_. Titlu |_. Autor initial |\r\n| Programare dinamica / memoizare (trading space for time): \'link1\':programare-dinamica, \'link2\':pd | ==user(user=\"Zeus\" type=\"tiny\")== |\r\n| \'Arbori indexati binar\':aib | ==user(user=\"Skipy\" type=\"tiny\")== |\r\n| \'Dinic\':dinic | ==user(user=\"alexandru.mosoi\" type=\"tiny\")== |\r\n| \'Probleme de geometrie si solutii\':downloads?geometrie.zip | ==user(user=\"Cosmin\" type=\"tiny\")== |\r\n| \'Diagrame Voronoi\':voronoi | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| \'Algoritmi de baleiere\':algoritmi-de-baleiere | ==user(user=\"stef2n\" type=\"tiny\")== |\r\n\r\nh3. 3. Creeaza ceva nou\r\n\r\nAi o idee noua de articol? Sau pur si simplu vrei sa te apuci de la 0 de un subiect? Ia legatura cu coordonatorul proiectului sau anunta pe \'forum\':forum. Este posibil sa primesti ajutor si de la alti utilizatori infoarena. In plus, noi iti propunem o lista de articole pe care ni le-am dori scrise, in caz ca nu te-ai decis asupra temei:\r\n\r\ntable. |_. Titlu |\r\n| Depanarea programelor C/C++ cu gdb in Linux |\r\n| Testarea surselor in timp de concurs sau Cum sa reduci buselile |\r\n| Tutorial LaTeX |\r\n\r\nNe rezervam dreptul sa nu acceptam sau sa stergem articolele care nu se potrivesc cu tema si target-ul site-ului.\r\n\r\nh2. Cu cine iau legatura?\r\n\r\nCu coordonatorul proiectului:\r\n\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n\r\nSau daca vrei sa contribui la un articol la care se lucreaza deja, poti vorbi direct cu voluntarii care se ocupa de el.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"43\")==\r\n\r\n*TODO*\r\n\r\ntable. |_. Subiect |_. Voluntar(i) |_. Progres |\r\n| Notiuni de geometrie analitica si aplicatii | ==user(user=\"devilkind\" type=\"tiny\")== \r\n==user(user=\"sima_cotizo\" type=\"tiny\")== | \'50%\':notiuni-de-geometrie-si-aplicatii |',3146,'public',NULL,NULL),('utilizator/gavrilavlad','Gavrila Vlad','2007-09-21 12:07:43','2009-10-22 18:34:54','   \r\n\r\nh2. Despre mine\r\n\r\nMa numesc Gavrila Vlad Alexandru si sunt elev in clasa a IX-a la ICHB. Particip de mult timp la concursuri de informatica, iar principala mea sursa de pregatire este infoarena.\r\n\r\nh2. Distinctii primite\r\n\r\nOlimpiada Nationala de Informatica\r\n\r\n* 2004 - Buzau - Mentiune\r\n* 2005 - Galati - Premiul special\r\n* 2006 - Targoviste - Mentiunea I\r\n* 2007 - Cluj - Premiul II\r\n* 2008 - Bacau - Premiul I\r\n* 2009 - Galati - Premiul II\r\n\r\nBaraje\r\n\r\n* 2008 - Ploiesti / Iasi - Calificat (locul I) la JBOI\r\n* 2009 - Bistrita / Cluj - Calificat (locul I, cu maxim de puncte) la JBOI\r\n\r\nJunior Balkan Olympiad in Informatics\r\n\r\n* 2008 - Shumen - Argint\r\n\r\nPreONI, Algoritmiada si .Campion\r\n\r\n* 2008 - PreONI - Finalist\r\n* 2009 - .Campion - Locul II\r\n* 2009 - Algoritmiada - Locul I\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* Profesori:\r\n\r\n==user(user=\"pauldb\" type=\"normal\")==\r\n\r\n==user(user=\"wefgef\" type=\"normal\")==\r\n\r\n==user(user=\"bogdan2412\" type=\"normal\")==\r\n\r\n==user(user=\"silviug\" type=\"normal\")==\r\n\r\n\r\n* Prieteni:\r\n\r\n==user(user=\"savim\" type=\"normal\")==\r\n\r\n==user(user=\"CezarMocan\" type=\"normal\")==\r\n\r\n==user(user=\"raduzer\" type=\"normal\")==\r\n\r\n==user(user=\"toni2007\" type=\"normal\")==\r\n\r\n==user(user=\"gcosmin\" type=\"normal\")==\r\n\r\n==user(user=\"GheorgheMihai\" type=\"normal\")==\r\n\r\n==user(user=\"radu_voroneanu\" type=\"normal\")==\r\n\r\n==user(user=\"protoman\" type=\"normal\")==\r\n\r\n==user(user=\"matemariaescu\" type=\"normal\")==\r\n\r\n==user(user=\"tvlad\" type=\"normal\")==\r\n\r\n==user(user=\"taloibogdan\" type=\"normal\")==\r\n',6800,'public',NULL,NULL),('utilizator/gavrilavlad','Gavrila Vlad','2007-09-21 12:07:43','2009-10-28 18:52:41','   \r\n\r\nh2. Despre mine\r\n\r\nMa numesc Gavrila Vlad Alexandru si sunt elev in clasa a IX-a la ICHB. Particip de mult timp la concursuri de informatica, iar principala mea sursa de pregatire este infoarena.\r\n\r\nh2. Distinctii primite\r\n\r\nOlimpiada Nationala de Informatica\r\n\r\n* 2004 - Buzau - Mentiune\r\n* 2005 - Galati - Premiul special\r\n* 2006 - Targoviste - Mentiunea I\r\n* 2007 - Cluj - Premiul II\r\n* 2008 - Bacau - Premiul I\r\n* 2009 - Galati - Premiul II\r\n\r\nBaraje\r\n\r\n* 2008 - Ploiesti / Iasi - Calificat (locul I) la JBOI\r\n* 2009 - Bistrita / Cluj - Calificat (locul I, cu maxim de puncte) la JBOI\r\n\r\nJunior Balkan Olympiad in Informatics\r\n\r\n* 2008 - Shumen - Argint\r\n\r\nPreONI, Algoritmiada si .Campion\r\n\r\n* 2008 - PreONI - Finalist\r\n* 2009 - .Campion - Locul II\r\n* 2009 - Algoritmiada - Locul I\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* Profesori:\r\n\r\n==user(user=\"pauldb\" type=\"normal\")==\r\n\r\n==user(user=\"wefgef\" type=\"normal\")==\r\n\r\n==user(user=\"bogdan2412\" type=\"normal\")==\r\n\r\n==user(user=\"silviug\" type=\"normal\")==\r\n\r\n\r\n* Prieteni:\r\n\r\n==user(user=\"savim\" type=\"normal\")==\r\n\r\n==user(user=\"CezarMocan\" type=\"normal\")==\r\n\r\n==user(user=\"raduzer\" type=\"normal\")==\r\n\r\n==user(user=\"toni2007\" type=\"normal\")==\r\n\r\n==user(user=\"gcosmin\" type=\"normal\")==\r\n\r\n==user(user=\"GheorgheMihai\" type=\"normal\")==\r\n\r\n==user(user=\"radu_voroneanu\" type=\"normal\")==\r\n\r\n==user(user=\"protoman\" type=\"normal\")==\r\n\r\n==user(user=\"matemariaescu\" type=\"normal\")==\r\n\r\n==user(user=\"tvlad\" type=\"normal\")==\r\n\r\n==user(user=\"taloibogdan\" type=\"normal\")==\r\n',6800,'public',NULL,NULL),('planificare/sedinta-20090126','Sedinta 2009-01-26','2009-01-22 17:34:00','2009-02-11 17:41:45','h1. Sedinta 2009-01-26\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe întâlnim *luni, 26 ianuarie* la ora *19^00^* la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")== (inca nu stiu cand scap de la examen)\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"alexthero\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinta anterioara\':planificare/sedinta-20090112| ==user(user=\"domino\" type=\"tiny\")==|\r\n|OKRs Q12009| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n|Algoritmiada| ... |\r\n|Stelele| ==user(user=\"silviug\" type=\"tiny\")==|\r\n|Fix-it camp| ... |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n* Despre Stele\r\n** Sunt ok datele: 31-1 pentru 9-10 si 6-7 pentru 11-12?\r\n** Seturi de probleme\r\n*** Se dau ~120 RON pe problema (e pe bani!)\r\n*** Avem probleme pentru 9-10? Cate?\r\n*** Pentru 11-12 trebuie sa ne intalnim (fara Bogdan si Cosmin) la ICHB. Marti/miercuri?\r\n\r\nDiscutii despre probleme la 9-10. Intalnire marti-miercuri pentru 11-12.\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Cristi face blog post despre OKR-uri\r\n* Silviu stabileste contacte cu Poli\r\n* Fixit camp:\r\n** Cristi si Silviu vorbesc de premii\r\n* Stele %{color:red;}(done)%:\r\n** Ne intalnim maine la 10 la ICHB sa vorbim de probleme: Silviu, Adi, Paul, Victor, Stefan. Victor vorbeste cu Wef\r\n** Cristi baga newsletter si Silviu ii zice din timp (minim 3 zile)\r\n** Cristi vorbeste cu Ali pentru configurarea proxy-ului\r\n** Cristi face .htaccess pentru a bana forumul\r\n* Algoritmiada:\r\n** Se face pe 15 februarie\r\n** Sponsori posibili: Adobe, Microsoft, iRealSoft\r\n* Il iertam pe Mort de datorie (a gresit la calcule)\r\n* Coding camp:\r\n** 28 februarie - 1 martie\r\n** Cine vine: Cristi, Vali, Prostu, Bogdan, Victor, Cosmin, Stefan, Mircea\r\n** Probabil: Silviu, Paul, Adi, Wef\r\n** Tero baga de acasa\r\n** Mircea face planul de coding camp (Virtual Contest e prioritar)\r\n*** Reorganizat sidebar si topnav (Cristi are idei, link la index de newsletter)\r\n*** Solutie de backup\r\n** Cristi se ocupa de locatie\r\n* Nu facem fixit camp in Q1\r\n* Mircea se uita sa vada cati oameni au trimis doar in Arhiva Educationala\r\n* Vali face IAP si OKR despre ordonarea problemelor (vezi formula de la IMDB)\r\n* Incercam \"video sedinta\" cu Airinei (webcam/Skype)\r\n* Lumea da feedback la IAP 7 pana la urmatoarea sedinta\r\n* Cristi face blog post despre 2% %{color:red;}(done)%:\r\n* Silviu vorbeste cu Mars despre evaluator ( %{color:red;}(done)%: ce facea Mars nu adreseaza problema noastra)\r\n* Mircea trimite mail pentru cine nu si-a completat OKR-urile\r\n* Facem sedinta pe 16 februarie. Cosmin cumpara apa, suc si pahare (bon cu stampila). Cristi se ocupa de sala.\r\n* Paul, Prostu, Tero & Co trimit poza si descriere lui Cosmin pentru blog despre membri noi. %{color:red;}(Paul, Tero done)%\r\n\r\nh2. Notite\r\n\r\n* Punem stire ca nu mai ai voie cu HTML si sa-si actualizeze lumea profilele\r\n* Stefan discuta cu Marius Stroe dupa finala\r\n',15,'public',NULL,NULL),('newsletter/algoritmiada-2009-3','Algoritmiada, Runda 3; Rezultate runde anterioara','2009-02-12 08:27:32','2009-02-12 08:31:08','Buna, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nIn curand incepe a treia si ultima runda online a concursului Algoritmiada, cel mai\r\nmare si mai important concurs organizat de infoarena!\r\n\r\nLa Algoritmiada participa elevi de gimnaziu, elevi de liceu, *dar si\r\nstudenti*! (Avem grupe separate pentru fiecare. Studentii pot fi\r\nchiar masteranzi sau doctoranzi.)\r\n\r\nRunda 3 se desfasoara in acest weekend. Intrece-te cu cei mai buni!\r\nAsigura-ti locul la finala si castiga premii serioase!\r\n\r\np{padding-left: 2em;}. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n    Runda 3 se desfasoara\r\n\r\np{padding-left: 4em;}. Duminica, 15 Februarie 2009, orele 09:00 - 13:00\r\n    ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\r\n\r\nVezi pagina concursului: \'algoritmiada-2009\':algoritmiada-2009\r\npentru mai multe informatii.\r\n\r\nSucces!\r\n\r\nh2.  Atentie! Concurs cu rating! \r\n\r\nDaca vrei sa ti se modifice rating-ul in urma acestei runde trebuie\r\nsa iti anunti participarea din timp. Intra pe\r\n\'algoritmiada-2009/runda-2\':algoritmiada-2009/runda-2 si inscrie-te.\r\n\r\nPoti sa participi la concurs chiar si daca nu te-ai inscris in\r\nprealabil insa nu ti se va modifica rating-ul. ==NewsletterRating(username=\"%username%\")==\r\nCiteste despre rating: \'documentatie/rating\':documentatie/rating.\r\n\r\nh2.  Despre Algoritmiada, Runda 2 \r\n\r\nAlgoritmiada este un concurs nou, cu premii, organizat de infoarena.\r\nConcursul se desfasoara in 3 runde online de calificare si o\r\nfinala on-site. Cei mai buni vor castiga premii serioase, in bani si\r\nobiecte.\r\n\r\nLa Runda 2 vei avea la dispozitie 4h sa rezolvi 3 probleme de natura\r\nalgoritmica. Concurentii sunt impartiti in 4 grupe de varsta:\r\ngimnaziu, clasele 9-10, clasele 11-12 si studenti (inclusiv\r\nmasteranzi si doctoranzi).\r\n\r\nSubiectele vor fi propuse de catre o echipa de fosti si actuali\r\nolimpici la informatica: Airinei Adrian, Bogdan Tataroiu, Andrei\r\nGrigorean, Gheorghe Cosmin, Paul-Dan Baltescu si Stefan Istrate.\r\nDe ce ei? Intra pe pagina rundei si citeste cate ceva despre\r\nexperienta fiecaruia: \'algoritmiada-2009/runda-2\':algoritmiada-2009/runda-2\r\n\r\nIti uram succes si te asteptam in arena!\r\n\r\nh2.  Despre rundele anterioara \r\n\r\nSilviu Ganceanu a facut o analiza a primelor doua runde Algoritmiada.\r\nAfla cati concurenti au participat, cate surse s-au trimis si\r\nimpresii despre runda:\r\n* \'blog/algoritmiada-runda1\':blog/algoritmiada-runda1\r\n* \'blog/algoritmiada-runda2\':blog/algoritmiada-runda2\r\n\r\nVezi rezultatele si clasamentul total aici:\r\n\'algoritmiada-2009/clasament\':algoritmiada-2009/clasament\r\n\r\nh2.  Seria de concursuri preONI s-a incheiat \r\n\r\nDupa 5 ani, seria de concursuri preONI se retrage. Cel mai longeviv\r\nconcurs infoarena, cel mai amplu eveniment organizat de noi pana\r\nacum, cu o traditie lunga si cu mii de participanti, se incheie.\r\n\r\nDe anul acesta incepe Algoritmiada. Vom incerca sa aplicam lectiile\r\ninvatate pana acum, insa avem nevoie de ajutorul tau. Fii alaturi de\r\nnoi, contacteaza-ne pe forum, ajuta-ne sa facem din Algoritmiada o\r\ncompetitie la care ti-ar placea sa participi oricand.\r\n\r\nAi participat vreodata la preONI? Iti mai aduce aminte ce fel a fost,\r\nce probleme ai primit? Ti-am facut poze la finala? Viziteaza inca\r\nodata paginile editiilor anterioare:\r\n\r\np{padding-left: 2em;}. *   preONI 2008, finala la Univ. Politehnica, Bucuresti\r\n        \'preoni-2008\':preoni-2008\r\n\r\np{padding-left: 2em;}. *   preONI 2007, finala la Lic. Int. de Informatica, Bucuresti\r\n        \'preoni-2007\':preoni-2007\r\n\r\np{padding-left: 2em;}. *   preONI 2006, finala la C. N. \"Unirea\", Focsani\r\n        \'preoni-2006\':preoni-2006\r\n\r\np{padding-left: 2em;}. *   preONI 2005, finala online\r\n        \'preoni-2005\':preoni-2005\r\n\r\np{padding-left: 2em;}. *   preONI 2004, finala online\r\n        \'preoni-2004\':preoni-2004\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/doi-la-suta\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==\r\n\r\nh2.  Mesaj nesolicitat? \r\n\r\nEsti inscris pe \'infoarena\':home cu numele\r\n==UserInfo(user=\"%username%\" info=\"fullname\")==, utilizator \"%username%\"\r\nsi ai acceptat sa primesti mesaje de instiintare.\r\n\r\nDaca nu mai doresti instiintari, da click pe acest link:\r\n\'account/%username%\':account/%username%\r\n',1490,'protected',NULL,NULL),('blog/conducere-noua','Conducere nouă pentru infoarena!','2009-10-26 21:31:33','2009-10-26 21:40:34','Că tot se apropie alegerile prezendiţiale, avem veşti bune pentru voi: infoarena şi-a ales deja preşedintele :) El este: ==user(user=\"gcosmin\")==!\r\n\r\nCosmin a preluat ştafeta de la ==user(user=\"wickedman\")==, care a fost preşedintele infoarena încă din 2003. Sub mandatul lui Cristi s-au realizat multe lucruri, dar aşa cum a spus chiar el, cel mai important este faptul că infoarena este un proiect viu! În jurul site-ului şi a Asociaţiei v-aţi adunat voi, tinerii pasionaţi de informatică din România. Acest lucru ne dă încredere ca inforena va exista pentru multe generaţii de acum încolo şi că va rămâne o sursă importantă în pregătirea voastră, a viitorilor specialişti IT ai României.\r\n\r\nÎncepând cu anul acesta, conducerea infoarena este aleasă în fiecare an conform procedurii descrise \'aici\':propuneri/13-presedinte. Noi sperăm că acest lucru să asigure continuitate şi, în acelaşi timp, o infuzie de idei noi şi de energie în proiectele întreprinse de echipa infoarena. \r\n\r\nLa primele alegeri \"prezidenţiale\" infoarena, Cosmin a câştigat mandatul în unanimitate. El ne-a convins prin seriozitate şi prin iniţiativă pe tot parcursul anului trecut.\r\n\r\nCosmin a ales 3 vicepreşedinţi care sunt responsabili de cele 3 mari \"direcţii\" infoarena:\r\n\r\n* Algoritmiada -- ==user(user=\"pauldb\")==\r\n* Content (arhivă, concursuri online, articole) -- ==user(user=\"stef2n\")==\r\n* Development -- ==user(user=\"bogdan2412\")==\r\n\r\nBogdan, Ştefan şi Paul s-au remarcat prin contribuţii substanţiale la infoarena încă de când s-au alăturat echipei.\r\n\r\nSă le urăm cu toţii cât mai multe realizări pe parcursul următorului mandat!\r\n\r\nÎn final aş vrea să subliniez că orice vor întreprinde ei, în calitate de lideri infoarena, poate avea un impact mult mai mare dacă vă implicaţi şi voi. Nu uitaţi că oricine contribuie consistent poate ajunge în echipa şi chiar preşedintele infoarena!',15,'protected',4215,NULL),('planificare/camp-2.2.1','Coding Camp \"A New Day\"','2009-02-01 22:33:19','2009-02-09 10:36:22','h1. Coding Camp _\"A New Day\"_\r\n\r\nNe intalnim in weekend-ul *28 februarie-1 martie 2009* la ...\r\n\r\nScopul final al coding camp-ului este lansarea versiunii \'*infoarena 2.2.1*\':http://hackers.devnet.ro/milestone/2.2.1%20A%20New%20Day.\r\n\r\nh2. Locatie\r\n\r\n...\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu Linux (preferabil Ubuntu) instalat pe el\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri\r\n\r\nh2. Participanti\r\n\r\nSpecifica cand poti veni si cat poti sta.\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"alexthero\" type=\"tiny\")==: de acasa - tot weekend-ul\r\n* ==user(user=\"wickedman\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"stef2n\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"devilkind\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"silviug\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"prostu\" type=\"tiny\")==: tot weekend-ul\r\n\r\nh2. Agenda\r\n\r\nh3. Must have\r\n\r\n|_. Task|_. Estimare de timp |\r\n| \'Comentarii la orice pagina ca la blog\':http://hackers.devnet.ro/ticket/362 | ? |\r\n| Reorganizat sidebar si topnav | ? |\r\n| Script de backup | ? |\r\n| \'Virtual Contests\':propuneri/10-virtual-contest | ? |\r\n| \'Sistem de monitorizare\':http://hackers.devnet.ro/ticket/179 | ? |\r\n| \'Pagina de submit desteapta\':http://hackers.devnet.ro/ticket/366 | ? |\r\n| Tagging pentru probleme | ? |\r\n\r\nh3. Nice to have\r\n\r\n|_. Task|_. Estimare de timp |\r\n| \'Run YSlow and improve performance\':http://hackers.devnet.ro/ticket/351 | ? |\r\n| \'Interfata de updatat rating-uri\':http://hackers.devnet.ro/ticket/239 | ? |\r\n| \'Permisiuni in pagina de changes\':http://hackers.devnet.ro/ticket/363 | ? |\r\n| \'Scoruri detaliate\':http://hackers.devnet.ro/ticket/263 | ? |\r\n| \'Sterge o revizie\':http://hackers.devnet.ro/ticket/132 | ? |\r\n| \'Pagina de changes mai detaliata\':http://hackers.devnet.ro/ticket/155 | ? |\r\n\r\nh3. Others\r\n\r\n|_. Task|_. Estimare de timp |\r\n| \'Grafice rating\':http://hackers.devnet.ro/ticket/263 | ? |\r\n| \'Optimizat diff-ul\':http://hackers.devnet.ro/ticket/360 | ? |\r\n',2970,'public',NULL,NULL),('blog/conducere-noua','Infoarena are o conducere nouă','2009-10-26 21:31:33','2009-10-26 21:32:05','Că tot se apropie alegerile prezendiţiale, avem veşti bune pentru voi: infoarena şi-a ales deja preşedintele :) El este: ==user(user=\"gcosmin\" type=\"tiny\")==!\r\n\r\nCosmin a preluat ştafeta de la ==user(user=\"wickedman\" type=\"tiny\")==, care a fost preşedintele infoarena încă din 2003. Sub mandatul lui Cristi s-au realizat multe lucruri, dar aşa cum a spus chiar el, cel mai important este faptul că infoarena este un proiect viu! În jurul site-ului şi a Asociaţiei v-aţi adunat voi, tinerii pasionaţi de informatică din România. Acest lucru ne dă încredere ca inforena va exista pentru multe generaţii de acum încolo şi că va rămâne o sursă importantă în pregătirea voastră, a viitorilor specialişti IT ai României.\r\n\r\nÎncepând cu anul acesta, conducerea infoarena este aleasă în fiecare an conform procedurii descrise \'aici\':propuneri/13-presedinte. Noi sperăm că acest lucru să asigure continuitate şi, în acelaşi timp, o infuzie de idei noi şi de energie în proiectele întreprinse de echipa infoarena. \r\n\r\nLa primele alegeri \"prezidenţiale\" infoarena, Cosmin a câştigat mandatul în unanimitate. El ne-a convins prin seriozitate şi prin iniţiativă pe tot parcursul anului trecut.\r\n\r\nCosmin a ales 3 vicepreşedinţi care sunt responsabili de cele 3 mari \"direcţii\" infoarena:\r\n\r\n* Algoritmiada -- ==user(user=\"pauldb\" type=\"normal\")==\r\n* Content (arhivă, concursuri online, articole) -- ==user(user=\"stef2n\" type=\"normal\")==\r\n* Development -- ==user(user=\"stef2n\" type=\"normal\")==\r\n\r\nBogdan, Ştefan şi Paul s-au remarcat prin contribuţii substanţiale la infoarena încă de când s-au alăturat echipei.\r\n\r\nSă le urăm cu toţii cât mai multe realizări pe parcursul următorului mandat!\r\n\r\nÎn final aş vrea să subliniez că orice vor întreprinde ei, în calitate de lideri infoarena, poate avea un impact mult mai mare dacă vă implicaţi şi voi. Nu uitaţi că oricine contribuie consistent poate ajunge în echipa şi, de ce nu, preşedintele infoarena!',15,'private',NULL,NULL),('algoritmiada-2010/runda-1/solutii','Solutii Algoritmiada 2009 Runda 1','2009-10-25 16:37:52','2009-10-25 16:37:52','h1. Solutii Algoritmiada 2009, Runda 1\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Tablete\':algoritmiada-2009/runda-1/solutii#tablete\r\n* \'Densitate\':algoritmiada-2009/runda-1/solutii#densitate\r\n* \'Propozitie\':algoritmiada-2009/runda-1/solutii#propozitie\r\n* \'Jstc\':algoritmiada-2009/runda-1/solutii#jstc\r\n* \'Coprime\':algoritmiada-2009/runda-1/solutii#coprime\r\n* \'Scandura\':algoritmiada-2009/runda-1/solutii#scandura\r\n* \'Piese2\':algoritmiada-2009/runda-1/solutii#piese2\r\n* \'Sprim\':algoritmiada-2009/runda-1/solutii#sprim\r\n* \'Kprime\':algoritmiada-2009/runda-1/solutii#kprime\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/tablete\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/densitate\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/propozitie\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/jstc\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/coprime\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/scandura\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/piese2\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/sprim\")==\r\n\r\n==include(page=\"algoritmiada-2009/runda-1/solutii/kprime\")==',1490,'public',NULL,NULL),('algoritmiada-2010/runda-4','Stelele Informaticii 2009, clasele 11-12','2009-10-25 16:32:24','2009-10-25 16:32:24','h1. Stelele Informaticii 2009, clasele 11-12\r\n\r\np=. !template/todo?progress.gif! _In curand..._\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!',1792,'protected',NULL,NULL),('algoritmiada-2010/regulament','Algoritmiada 2010 - Regulament','2009-10-25 15:56:28','2009-10-25 16:13:49','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Regulament\r\n\r\nSe recomanda, pe langa citirea acestui regulament, citirea \"regulamentului\":regulament general infoarena.\r\n\r\n\'Echipa infoarena\':echipa-infoarena isi rezerva dreptul de a modifica prezentul regulament pe parcursul desfasurarii concursului. Daca apar prevederi noi sau daca anumite prevederi ale regulamentului sunt modificate sau eliminate, atunci acestea vor fi anuntate pe site-ul concursului. Orice modificare a regulamentului va intra in vigoare, in functie de situatie, fie din momentul publicarii ei, fie dupa incheierea rundei aflate in desfasurare. In momentul anuntarii modificarii va fi precizat si momentul din care aceasta intra in vigoare.\r\n\r\nh2. Dreptul de participare\r\n\r\nPersoanele care fac parte din \'echipa infoarena\':echipa-infoarena cat si alti contribuitori implicati direct in organizarea concursului *Algoritmiada 2010* nu au dreptul de a participa. Exceptie la aceasta regula sunt acele persoane din afara \'echipei infoarena\':echia-infoarena care propun probleme la alte grupe de varsta decat grupele la care participa. De asemenea, orice concurent care are un comportament considerat inadecvat fata de echipa infoarena sau fata de alti concurenti va fi descalificat. Un concurent se poate califica la finala doar daca se incadreaza in grupa la care a concurat (aceasta verificare se va face prin prezentarea unei dovezi legale care il incadreaza pe concurent la aceea grupa).\r\n\r\nh2. Repartizarea\r\n\r\nToti participantii vor fi repartizati in *4* grupe, in concordanta cu varsta lor. Repartizarea se face astfel\r\n\r\n* Clasele 5-8\r\n* Clasele 9-10\r\n* Clasele 11-12 \r\n* Studenti (facultate, mastrat, doctorat)\r\n\r\nOricine poate participa la o alta grupa decat cea la care se incadreaza, dar calificarea la finala cat si impartirea premiilor se va face conform regulamentului, fara nici o exceptie.\r\n\r\nh2. Inscriere\r\n\r\nTot ce trebuie sa faceti pentru a participa la concursul *Algoritmiada 2010* este sa aveti un cont la infoarena. Inregistrarea se poate face pe site-ul infoarena. Acelasi cont va fi folosit pentru a accesa forum-ul.\r\n\r\nh2. Runde\r\n\r\nVor exista *4* runde de calficare, iar in urma clasamentului stabilit primii de la fiecare grupa vor fi selectati pentru etapa finala desfasurata in cadrul unei tabere. Cele *4* runde vor avea loc duminica, incepand cu ora 9:00, desi pot interveni exceptii. Durata lor va fi de 4 ore. Un program detaliat poate fi gasit pe pagina \"principala a concursului\":algoritmiada-2010.\r\n\r\nh2. Intrebari\r\n\r\nIn prima ora vor putea fi formulate eventualele intrebari, pe forum, in topicurile special create. Orice intrebare pusa in alt mod (primita ca personal message, pe mail, etc.) va fi ignorata. Raspunsuri vor fi oferite doar la intrebarile puse in prima ora . Intrebarile trebuie formulate astfel incat sa se poate raspunda cu _DA_ sau _NU_. In caz contrar sau in cazul in care raspunsul se afla in textul problemei se va raspunde cu _NO COMMENT_. Nu vor exista exceptii de la aceaste reguli. Daca echipa va considera ca raspunsul la o anumita intrebare este de interes general si clarifica anumite aspecte, atunci se va face un anunt general care va aparea atat pe forum cat si in sectiunea Mesaje de la organizatori a grupei respective. \r\n\r\nh2. Trimiterea solutiilor\r\n\r\nTrimitrea solutiilor se va face prin intermediul interfetei site-ului infoarena.\r\nOdata autentificati in contul vostru, veti putea selecta arhiva la care doriti sa lucrati (in cazul acesta una din arhivele {*Algoritmiada 2010*}) si veti putea folosi link-ul \"Trimite solutii\".\r\n\r\nh2. Evaluare\r\n\r\nEvaluarea solutiilor (\"mai multe detalii aici\":documentatie/evaluator) trimise se face in timp real, insa punctajele nu vor fi facute publice decat la incheirea rundei de concurs. Veti putea vizualiza pozitia ocupata in clasament dupa terminarea rundei in rubrica Concurs.\r\n\r\nSe recomanda sa instalati pe calculatorul vostru aceleasi versiuni de compilatoare ca cele specificate la link-ul de mai sus. \'Echipa infoarena\':echipa-infoarena nu este responsabila pentru diferentele intre versiuni de compilatoare si nu va efectua reevaluaari in astfel de cazuri.\r\n\r\nh2. Contestatii\r\n\r\nEchipa infoarena isi rezerva dreptul de a reevalua orice problema in situatia in care se detecteaza erori in teste sau in programul de verificare dupa evaluare. Cum testele problemelor nu vor fi facute publice, posiblitatile de a contesta sunt limitate. Pentru a asigura o evaluarea corecta, echipa infoarena va garanteaza ca va testa intens toate problemele inainte de concurs si ca va verifica corectitudinea procesului de evaluare dupa terminare. In caz ca totusi aveti o contestatie, aceasta trebuie trimisa pe mail la adresa _paul -at- infoarena.ro_ in termen de 24 de ore de la afisarea rezultatelor rundei curente pe site. Ele vor fi rezolvate in termen de maxim 5 zile, iar dupa rezolvarea lor rezultatele vor fi declarate finale.\r\n\r\nh2. Solutii\r\n\r\nLa scurt timp dupa terminarea evaluarii se va publica un articol cu solutiile pentru problemele rundei respective. Testele utilizate pentru evaluare nu vor fi facute publice.\r\n\r\nh2. Transferul problemelor\r\n\r\nProblemele vor fi mutate dupa evaluare in \'Arhiva de probleme\':arhiva infoarena, avand astfel la dispozitie un evaluator 24 din 24 si posiblitatea de a finisa solutiile la problemele nerezolvate in timpul concursului.\r\n\r\nh2. Trisare\r\n\r\n*Algoritmiada 2010* este un concurs individual, asadar orice tentativa de colaborare va aduce descalificarea celor implicati. \'Echipa infoarena\':echipa-infoarena isi rezerva dreptul de a verifica sursele concurentilor, iar in caz ca se descopera surse aproximativ identice, concurentii respectivi vor fi descalificati din concurs. Aceeasi masura va fi aplicata si celor care concureaza sub un alt nume decat cel adevarat. In cazul unui atac asupra sistemului de evaluare sau asupra paginilor infoarena utilizatorul vinovat va fi descalificat din concurs, iar contul sau infoarena va fi eliminat definitiv.\r\n\r\n==Include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('algoritmiada-2010/clasament/runda-1/11-12','Algoritmiada 2009 - Clasament Runda 1, Clasele 11-12','2009-10-25 14:00:10','2009-10-25 14:00:10','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda1-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2009/runda-1\r\n* \'Clasele 5-8\':algoritmiada-2009/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/runda-1/studenti\r\n*(active) \'Rezultate\':algoritmiada-2009/clasament/runda-1/11-12\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-1/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2009/clasament/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-1/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda1-11-12\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',1490,'protected',NULL,NULL),('algoritmiada-2010/clasament/9-10','Algoritmiada 2009 - Clasament general, Clasele 9-10','2009-10-25 14:00:09','2009-10-25 14:00:09','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Clasament clasele 9-10\r\n\r\n(htabs)* \'Pe runde...\':algoritmiada-2009/clasament\r\n* \'Clasele 5-8\':algoritmiada-2009/clasament/5-8\r\n*(active) \'Clasele 9-10\':algoritmiada-2009/clasament/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/studenti\r\n\r\n==include(page=\"template/algoritmiada-2009/clasament-header\")==\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda1-9-10|algoritmiada2009-runda2-9-10|algoritmiada2009-runda3-9-10\") == \r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',1490,'protected',NULL,NULL),('algoritmiada-2010','Algoritmiada 2009 - olimpiada algoritmilor','2009-10-25 13:38:22','2009-10-25 13:38:22','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh2. Despre Algoritmiada\r\n\r\nIncepând de anul acesta, _infoarena_ organizează concursul de programare Algoritmiada. La acest concurs pot participa, în premieră pe ţară, tineri pasionaţi de informatică de toate vârstele: de la elevi de gimnaziu până la studenţi şi doctoranzi.\r\n\r\nConcursul are patru grupe valorice: gimnaziu, clasele 9-10, clasele 11-12, studenţi (inclusiv masteranzi şi doctoranzi). Participanţii vor avea ocazia să-şi demonstreze talentul, cunostinţele şi iuţimea minţii în 3 probe online urmând ca cei mai buni sa fie invitaţi la finala on-site.\r\n\r\nh2. Cum particip?\r\n\r\nPentru a participa la concurs trebuie să fii \'înregistrat\':register pe site-ul nostru.\r\n\r\nÎn ziua de concurs intri pe site, citeşti problemele de la grupa ta de vârstă şi trimiţi soluţiile înainte de expirarea timpului. \'Evaluatorul\':documentatie/evaluator nostru iţi va testa automat soluţiile iar punctajul îl vei afla la sfârşitul concursului. Tot atunci vei putea consulta clasamentul pentru a vedea ce au făcut şi ceilalţi concurenţi.\r\n\r\nh3. Prima dată pe _infoarena_?\r\n\r\n_infoarena_ ajută elevi şi studenţi să devină excelenţi în informatică! Gratuit ;) Citeşte \'ghidul utilizatorului\':documentatie/pentru-utilizatori şi află mai multe \'despre noi\':despre-infoarena.\r\n\r\nh2. Program\r\n\r\nFaceţi click pe titlul unei runde pentru informaţii detaliate.\r\n\r\ntable{width:50%}. |_. Runda |_. Data |_. Durata |\r\n| \'*Runda 1*\':algoritmiada-2009/runda-1 | *14 Decembrie 2008, Duminică* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 2*\':algoritmiada-2009/runda-2 | *11 Ianuarie 2009, Duminică* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 3*\':algoritmiada-2009/runda-3 | *15 Februarie 2009, Duminică* |=. *09^00^ - 13^00^* |\r\n| \'*Runda Finală*\':algoritmiada-2009/runda-finala | *2 Mai 2009, Sâmbătă* |=. *09^00^ - 13^00^*|\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',1792,'protected',NULL,NULL),('template/algoritmiada-2010','template/algoritmiada-2010','2009-10-25 13:43:56','2009-10-25 13:45:45','==include(page=\"template/algoritmiada-2010/header\")==\r\n\r\n(vmenu)*(section) \'*Algoritmiada 2010*\':algoritmiada-2010\r\n* \'Clasament\':algoritmiada-2010/clasament\r\n* \'Organizatori\':algoritmiada-2010/comisie\r\n* \'Sponsori si premii\':algoritmiada-2010/premii\r\n* \'Regulament\':algoritmiada-2010/regulament\r\n* &nbsp;\r\n* \'Runda 1\':algoritmiada-2010/runda-1\r\n* \'Runda 2\':algoritmiada-2010/runda-2\r\n* \'Runda 3\':algoritmiada-2010/runda-3\r\n* \'Runda 4\':algoritmiada-2010/runda-4\r\n* \'Runda finala\':algoritmiada-2010/runda-finala\r\n\r\n',1792,'protected',NULL,NULL),('algoritmiada-2009/runda-3/solutii/kino','Kino','2009-02-11 14:24:45','2009-02-11 14:24:45','h1(#kino). \'Kino\':problema/kino\r\n\r\nh2. Verificati sa fie pagina private pana dupa terminarea concursului',1490,'private',NULL,NULL),('algoritmiada-2009/runda-3/solutii/par','Par','2009-02-11 14:20:35','2009-02-14 09:42:19','h1(#par). \'Par\':problema/par\r\n\r\nExista mai multe solutii la aceasta problema. Folosind programare dinamica putem calcula $A[i][j]$, numarul minim de inversari care trebuie facut pentru a obtine o secventa corect parantezata. $A[i][j]$ se poate obtine din $A[i+1][j-1]$ (avem o secventa corect parantezata in interior) sau din $A[i][k]+A[k+1][j]$ (concatenam doua secvente corect parantezate) pentru $k$ intre $i+1$ si $j-1$. Complexitatea va fi $O(N^3)$. O idee mai buna ar fi sa calculam $C[i][j]$ numarul minim de inversari astfel incat daca am luat in calcul doar primele $i$ caractere vor ramane $j$ paranteze deschise care trebuie inchise in continuare.\r\n$C[i][j]$ poate proveni doar din $C[i-1][j-1]$ sau $C[i-1][j-1]$, deci complexitatea va fi $O(N^2)$, suficienta pentru a obtine 100 puncte. Aceasta nu este insa cea mai buna solutie, exista si o solutie greedy care ruleaza in timp liniar. Ne imaginam ca avem o stiva in care tinem parantezele deschise care le avem la un moment dat. Procesam apoi sirul initial de paranteze. Daca paranteza curenta este inchisa si in stiva se afla macar o paranteza deschisa, eliminam din stiva o paranteza deschisa si trecem mai departe. Daca paranteza curenta este inchisa si in stiva nu se afla nicio paranteza deschisa atunci inversam paranteza curenta si o introducem in stiva. Daca paranteza curenta este deschisa o introducem in stiva. Dupa ce am parcurs tot sirul initial trebuie ca in stiva sa existe un numar par de paranteze deschise. Pentru a obtine un numar minim de inversari trebuie inversate exact jumatate din ele.',2092,'private',NULL,NULL),('template/detailed-feedback','template/detailed-feedback','2009-02-14 15:07:32','2009-02-14 15:21:46','table{margin:0.5em auto;}. |={background-color:#EFEFFF; border:1px solid #9F9FFF; padding: 0.5em;}. !<template/detailed-feedback?report.png! In momentul in care trimiti o sursa, vei putea vedea scorul obtinut pe o parte din testele folosite la evaluare. |',1490,'public',NULL,NULL),('okr/20091/algoritmiada','okr/20091/algoritmiada','2009-01-26 14:45:51','2009-01-26 18:40:34','(okr)* organizare runda 3 si finala\r\n',1,'public',NULL,NULL),('algoritmiada-2009/runda-3/solutii/gminmax','Gminmax','2009-02-11 14:21:24','2009-02-11 14:53:24','h1(#gminmax). \'Gminmax\':problema/gminmax\r\n\r\nSe observa ca daca vrem ca un subgraf sa aibe gradul minim al unui nod $X$ trebuie ca toate nodurile cu grad mai mic ca $X$ sa fie scoase inainte. De aici ne vine ideea sa scoatem nodurile cu grad minim pe rand. La fiecare nod scos avem grija sa actualizam gradele nodurilor vecine nodului scos. La fiecare pas verificam daca gradul minim al unui nod ramas e mai mare ca rezultatul si actualizam. Este destul de evident ca asa descoperim si cel mai mare subgraf optim.\r\nO solutie ar fi sa folosim un arbore de intervale care sa suporte operatiile necesare. Aceasta abordare duce la o complexitate $O(M log N)$.\r\nO alta solutie este un algoritm in complexitate $O(N + M)$ unde ne folosim de $N$ liste in care tinem nodurile (in a $i$-a lista tinem nodurile cu gradul $i$). Parcurgem listele in ordine si actualizam pe parcurs (copiem unele noduri intr-o lista inferioara; ca sa nu stergem nodurile din lista initiala doar le vom copia si mai tarziu vom trece peste ele pentru ca vor fi scoase inainte).\r\nDin pacate nu se poate face o diferenta clara intre cele doua solutii (la timp), astfel incat ambele iau punctajul maxim (de asemenea ambele ocupa memorie $O(N + M)$).',2038,'private',NULL,NULL),('utilizator/mathboy','Profil mathboy','2008-12-24 18:43:37','2009-02-14 19:13:25','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\nElev in clasa a IX-a D,Matematica-Informatica,Informatica Intensiv\r\n Colegiul National Unirea Focsani\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n==user(user=\"bogdanhm999\" type=\"normal\")==\r\n\r\n==user(user=\"StefanGeo\" type=\"normal\")==\r\n\r\n==user(user=\"lucianvn\" type=\"normal\")==',9232,'public',NULL,NULL),('algoritmiada-2009/runda-3/solutii/secvmax','Secvmax','2009-02-11 14:24:05','2009-02-15 11:16:46','h1(#secvmax). \'Secvmax\':problema/secvmax\r\n\r\nO sa sortam query-urile crescator. Cand parcurgem query-urile in ordinea sortarii unele pozitii din vectorul initial vor putea fi folosite (apar pe parcurs). Acum ne intereseaza sa tinem o structura care sa sa suporte adaugarea unei pozitii intr-un vector si sa ne zica cea mai lunga subsecventa \"lipita\". Pentru aceasta ori putem sa folosim o structura de date gen \"paduri de multimi disjuncte\" ori pentru fiecare capat al unei bucati \"lipite\" tinem celalat capat si de fiecare daca cand introducem o pozitie noua actualizam aceste informatii uitandu-ne la pozitia din stanga si cea din dreapta.\r\nComplexitatea acestor solutii este $O(N log N + M log M)$ ambele luand punctajul maxim.',1490,'public',NULL,NULL),('deque-si-aplicatii','Deque și aplicații','2009-01-22 22:28:12','2009-02-10 13:32:55','h1. Deque şi aplicaţii\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'_Introducere_\':deque-si-aplicatii#introducere\r\n* \'_Aplicaţii:_\':deque-si-aplicatii#problema-1\r\n** \'1. Book Pile &#40;SGU&#41;\':deque-si-aplicatii#problema-1\r\n** \'2. Vila 2 &#40;.campion&#41;\':deque-si-aplicatii#problema-2\r\n** \'3. Şir\':deque-si-aplicatii#problema-3\r\n** \'4. Trans &#40;ONI 2004&#41;\':deque-si-aplicatii#problema-4\r\n** \'5. Otilia &#40;.campion&#41;\':deque-si-aplicatii#problema-5\r\n** \'6. Bcrc &#40;Stelele Informaticii&#41;\':deque-si-aplicatii#problema-6\r\n** \'7. Cut the Sequence &#40;PKU&#41;\':deque-si-aplicatii#problema-7\r\n* \'_Concluzii_\':deque-si-aplicatii#concluzii\r\n* \'_Probleme suplimentare_\':deque-si-aplicatii#probleme-suplimentare\r\n* \'_Bibliografie_\':deque-si-aplicatii#bibliografie\r\n\r\nÎn acest articol voi prezenta o structură de date de tip listă numită _deque_. Simplitatea acestei structuri poate că nu are multe de spus iar din acest motiv am prezentat şi o serie de aplicaţii care vor arăta surprinzătoarea sa utilitate în locurile unde am fi crezut că nu se mai poate face nimic pentru a reduce complexitatea.\r\n\r\nh2(#introducere). Introducere\r\n\r\nStructura de _deque_ (pronunţat de obicei _deck_) poate fi privit ca o colecţie de tip listă ce are două capete prin care se şterg sau inserează noi elemente. În literatura de specialitate aceste capete se numesc _head_ şi _tail_, iar dequeul mai este recunoscut şi ca fiind o coadă cu două capete _(double ended queue)_.\r\n\r\nImplementarea unui deque se poate face cu liste dublu înlănţuite ori cu un vector static când se cunoaşte numărul elementelor din colecţie. Ce trebuie reţinut este că limbajul C++ pune la dispoziţia utilizatorilor prin intermediul headerului _#include <deque>_ containerul \'_std::deque_\':http://www.cplusplus.com/reference/stl/deque/.\r\n\r\nh3(#operatii). Operaţii:\r\n\r\nMai jos sunt enumerate operaţiile care pot fi efectuate asupra unui deque împreună cu corespondentul lor în limbajul C++:\r\n\r\n* _front()_:	    întoarce primul element;\r\n* _back()_:	    întoarce ultimul element;\r\n* _push_front()_: inserează un element în faţă;\r\n* _push_back()_:  inserează un element în spate;\r\n* _pop_front()_:  scoate primul element;\r\n* _pop_back()_:   scoate ultimul element;\r\n* _empty()_:      întoarce _true_ dacă în deque nu se găseşte niciun element şi _false_ în caz contrar.\r\n\r\np=. !deque-si-aplicatii?new_deque.png 75%!\r\n\r\nToate aceste operaţii se execută în timp $O(1)$ \'amortizat\':http://en.wikipedia.org/wiki/Amortized_analysis. Pentru un plus de viteză va trebui să folosim un vector static cu dimensiunea egală cu numărul maxim de elemente ce pot trece prin deque, iar operaţiile implementate „de mână”, cu doi indecşi ce indică către head şi tail. Însă, în majoritatea aplicaţiilor limita de timp permite folosirea lejerităţii şi siguranţei clasei _std::deque_.\r\n\r\nÎn multe aplicaţii unde soluţiile parţiale se reprezintă sub forma unui şir continuu de valori care permite inserarea şi ştergerea doar pe la capete se poate folosi un deque. În general, se fac inserări pe la un capăt şi ştergeri pe la celălalt. Să urmărim în continuare cazuri concrete în care simplitatea unui deque duce la soluţii de multe ori optime şi implementări foarte scurte şi clare. Aplicaţiile sunt prezentate în ordinea crescătoare a dificultăţii şi din acest motiv recomand cu căldură tuturor celor care au de învăţat din acest articol să le parcurgă în ordine.\r\n\r\nh2(#problema-1). \'1. Book Pile\':http://acm.sgu.ru/problem.php?contest=0&problem=271 (SGU)\r\n\r\nbq. Se dau $N$ cărţi aşezate una deasupra celeilalte asupra cărora se vor efecta $M$ operaţii de două tipuri: 1. $ADD${$(nume)$} : se adaugă cartea $nume$ deasupra celorlalte; 2. $ROTATE$ : primele $K$ cărţi de deasupra se rotesc (dacă sunt mai puţin de $K$ cărţi atunci se vor roti toate). Se cere să se afişeze cărţile în ordine, prima fiind cea de deasupra, după efectuarea celor $M$ operaţii.\r\nRestricţii: $0 &le; N, K &le; 40 000$, $0 &le; M &le; 100 000$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se poate deduce urmând paşii următori. Să presupunem că iniţial avem cărţile $A B C$ şi $K = 3$. Dacă îl vom adăuga pe $D$, atunci nu vor rămâne importante decât cărţile $D A B$, deoarece, dacă vom roti ulterior ultimele $K$ cărţi, $C$ nu va mai fi niciodată considerat, cărţile fiind doar adăugate, iar o dată ce o carte iese din „top {$K$}” cărţi nu va mai fi posibil să i se schimbe poziţia pe raft. Să rotim acum „top {$K$}” cărţi. Noua ordine va fi $B A D$ şi $C$ pe raft la loc sigur. Dacă îl vom adăuga pe $E$, topul se va schimba în $E B A$ iar pe raft, în mod sigur vor fi, în această ordine, $D C$. Proprietatea celor $K$ cărţi din vârf este: o secvenţă continuă de elemente, la care se adaugă noi elemente sau se elimină dintre acestea numai pe la _capete_. Aceste capete sunt chiar head şi tail ale unui deque.\r\n\r\np=. !deque-si-aplicatii?bookpile.png 40%!\r\n\r\nLa final, când se vor termina operaţiile, cărţilor de pe raft li se vor adăuga cele din deque şi se va afişa soluţia. În cazul presupus, soluţia va fi: $E B A D C$.\r\n\r\nÎntrucât operaţiile unui deque se execută în $O(1)$ amortizat, soluţia are complexitatea $O(N + M)$.\r\n\r\nh2(#problema-2). \'2. Vila 2\':problema/vila2 (.campion)\r\n\r\nbq. Se dă un şir $S$ de $N$ numere întregi şi un $D$ număr natural. Se cere să determine diferenţa maximă dintre oricare două numere din şir cu proprietatea că diferenţa indicilor nu depăşeşte $D$.\r\nRestricţii: $2 &le; N &le; 100 000$, $1 &le; D &le; N/2$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia nu este greu de intuit. Dacă vom considera indicii $1$, $2$, .. , $N$ succesiv va trebuie ca pentru fiecare secvenţă $(i - D, i]$ să determinăm valoarea maximă şi pe cea minimă, iar diferenţa lor să o comparăm cu rezultatul obţinut până în acel moment. Pentru fixarea ideilor, să urmărim cum putem determina valoarea maximă din fiecare secvenţă $(i - D, i]$.\r\n\r\n_Observaţie_: „Fie $i{~1~}$, $i{~2~}$ doi indici astfel încât $i - D &lt; i{~1~} &lt; i{~2~} &le; i$.\r\n\r\n# Dacă $S[i{~1~}] &lt; S[i{~2~}]$ atunci, cât timp cei doi indici vor fi în intervalul $(i - D, i]$, valoarea de pe poziţia $i{~2~}$ va fi întotdeauna preferată valorii de pe poziţia $i{~1~}$. Când unul din indici nu va mai fi în acest interval, cel expediat va fi $i{~1~}$ şi, astfel, $i{~2~}$ rămâne în continuare preferat.\r\n# Dacă $S[i{~1~}] &gt; S[i{~2~}]$ atunci îl vom păstra pe $i{~2~}$, deoarece este candidat la maxim în viitor.”\r\n\r\nCu această observaţie deducem că într-o secvenţă $(i - D, i]$ vom avea un şir $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$ astfel încât $S[i{~1~}] &gt; S[i{~2~}] &gt; ... &gt; S[i{~K~}]$. Când vom avansa la secvenţa următoare, $(i - D + 1, i + 1]$, vom şterge din indicii $i{~1~}$, $i{~2~}$... atâta timp cât nu se găsesc în intervalul curent şi vom şterge din poziţiile $i{~K~}$, $i{~K-1~}$... cât timp $S[i + 1] &gt; S[i{~K~}]$, $S[i + 1] &gt; S[i{~K-1~}]$... adică cât timp se îndeplineşte primul punct din observaţia anterioară.\r\n\r\nŞirul $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$ este continuu iar operaţiile se efectuează doar pe la cele două capete. Rezultă că şirul poate fi implementat cu ajutorul unui deque.\r\n\r\nPentru $S[] = {5, 9, 4, 7, 4, 1}$ şi $D = 3$ obţinem următoarele stări ale unui deque:\r\n\r\n* <tex> \\langle \\widehat{5\\ [1]} \\rangle; </tex>\r\n* <tex> \\langle 5\\ [1] \\rangle \\Leftarrow 9\\ [2] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]} \\rangle; </tex>\r\n* <tex> \\langle 9\\ [2] \\rangle \\Leftarrow 4\\ [3] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 4\\ [3] \\rangle; </tex>\r\n* <tex> \\langle 9\\ [2],\\ 4\\ [3] \\rangle \\Leftarrow 7\\ [4] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 7\\ [4] \\rangle; </tex>\r\n* <tex> 9\\ [2] \\Leftarrow \\langle 7\\ [4] \\rangle \\Leftarrow 4\\ [5] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5] \\rangle; </tex>\r\n* <tex> \\langle 7\\ [4],\\ 4\\ [5] \\rangle \\Leftarrow 1\\ [6] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5],\\ 1\\ [6] \\rangle; </tex>\r\n\r\nCum fiecare indice din $1$, $2$, .., $N$ trece cel mult o dată prin deque, complexitatea finală este $O(N)$ amortizat.\r\n\r\nh2(#problema-3). \'3. Şir\':problema/sir\r\n\r\nbq. Se dă un şir $S$ de numere întregi de lungime $N$. Se cere să se găsească secvenţa de lungime maximă cuprinsă între $X$ şi $Y$ astfel încât $MAX - MIN &le; Z$, unde $MAX$ este maximul dintre toate numerele întregi din secvenţă iar $MIN$ minimul dintre acestea. Secvenţa soluţie va fi cea cu poziţia de început maximă dintre toate secvenţele de lungime maximă.\r\nRestricţii: $3 &le; N &le; 100 000$, $1 &le; X &le; Y &le; N$, $0 &le; Z &le; 30 000$.\r\n\r\nh3. Soluţie\r\n\r\nVoi prezenta mai jos o rafinare a soluţiei în trei paşi.\r\n\r\nPrima rezolvare se găseşte uşor, deoarece nu facem decât să urmărim textul: pentru fiecare poziţie $i$ fixată ({$i$} ia valorile $1$, $2$, .., $N$ succesiv) vom determina pentru aceasta secvenţa cerută, adică vom plimba un $j$ între poziţiile $i - Y$ şi $i - X$. Pentru un interval $(j, i]$ vom determina $MAX$ şi $MIN$ în $O(log{~2~}N)$ cu un arbore de intervale, iar daca diferenţa dintre acestea nu depăşeşte $Z$ vom compara cu soluţia finală. Complexitatea finală va fi $O(N * (Y - X) * log{~2~}Y)$.\r\n\r\nSă presupunem că pentru poziţia curentă $i$, l-am găsit pe $j$ cât mai mic cuprins între $i - Y$ şi $i - X$ astfel încât secvenţa $(j, i]$ este candidată la soluţie. Ce proprietăţi are $j$?\r\n\r\n* $i - Y &le; j &le; i - X$ şi $MAX - MIN &le; Z$;\r\n* dacă îl incrementăm pe $j$ la $j + 1$ atunci dacă $j &le; i - X$ cu siguranţă $MAX - MIN &le; Z$ şi astfel soluţia va fi mai scurtă;\r\n* dacă îl decrementăm pe $j$, atunci ori $j < i - Y$ ori $MAX - MIN > Z$;\r\n* dacă îl incrementăm pe $i$ la $i + 1$, atunci se poate întâmpla ca $j < i - Y$; cum $MAX$ nu poate decât să crească, iar $MIN$ decât să scadă, se mai poate de asemenea întâmpla ca $MAX - MIN > Z$.\r\n\r\nDatorită proprietăţilor de mai sus, când trecem de la $i$ la $i + 1$, valoarea lui $j$ nu poate decât să crească cât timp $j < i - Y$ sau $MAX - MIN > Z$ şi $j$ nu a depăşit poziţia $i - X$. Pentru determinarea lui $MAX$, respectiv lui $MIN$ se poate folosi un arbore de intervale. Complexitatea finală va fi $O(N * log{~2~}(Y))$.\r\n\r\nCu cei doi indici $i$ şi $j$ vom accesa fiecare element din cele $N$ de cel mult $2$ ori, o dată cu $i$ şi o dată cu $j$. Să vedem cum putem îmbunătăţi complexitatea $O(log{~2~}Y)$ pentru determinarea maximului şi minimului.\r\n\r\nPentru fixarea ideilor să urmărim cum îl vom calcula pe $MAX$. Observaţia care ne ajută în multe probleme pentru reducerea complexităţii de la $O(log{~2~}N)$ la $O(1)$ amortizat este următoarea: \r\n\r\n_Observaţie_: „Fixăm $i{~1~}$ şi $i{~2~}$ astfel încât $j < i{~1~} < i{~2~} &le; i$. Atunci, dacă $S[i{~2~}] > S[i{~1~}]$ poziţia $i{~2~}$ va fi întotdeauna mai importantă decât poziţia $i{~1~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ şi $i{~2~}$ nu vor mai fi ambele în intervalul $(j, i]$, poziţia eliminată va fi {$i{~1~}$}. Dacă însă $S[i{~1~}] > S[i{~2~}]$, atunci poziţia $i{~1~}$ va umbri poziţia $i{~2~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ va fi eliminat, atunci e posibil ca $i{~2~}$ să fie un candidat la $MAX$ dintre restul elementelor de la dreapta sa. În acest caz, nu putem afirma nimic şi vom păstra cele două poziţii.”\r\n\r\nRezultă din această observaţie că în intervalul $(j, i]$ poziţiile importante vor fi $j < i{~1~} < i{~2~} < .. < i{~k~} <= i$ astfel încât $S[i{~1~}] > S[i{~2~}] > .. > S[i{~k~}]$. Astfel, $MAX$ va fi $S[i{~1~}]$. Când îl vom incrementa pe $i$ la $i + 1$ vom şterge din poziţiile $i{~k~}$, $i{~k-1~}$, ... atâta timp cât $S[i + 1]$ este mai important, adică mai mare decât valorile de pe aceste poziţii, şi vom şterge $i{~1~}$, $i{~2~}$, ... atâta timp cât aceste poziţii sunt mai mici sau egale decât $j\'$. Indicele $j\'$ este noul optim pentru poziţia $i + 1$. Proprietatea şirului de poziţii $i{~1~}, i{~2~}, .., i{~k~}$ este că se reprezintă ca un şir continuu de numere care permite inserarea elementelor prin dreapta şi ştergerea prin stânga, adică se adaugă elemente la tail şi se şterg elemente de la head. Îl putem deci reprezenta printr-un deque. Complexitatea $O(1)$ amortizat provine de la faptul că fiecare poziţie dintre cele $N$ nu trece decât o singură dată prin deque şi este şters tot cel mult o singură dată. \r\n\r\nÎn practică, pseudocodul poate arăta în felul următor:\r\n\r\n== code(cpp) |\r\n// S şirul de numere iniţial şi N lungimea sa\r\n\r\nSubalgoritmul push_in(deque, întreg p, funcţia fct) este:\r\n    cât timp (!deque.empty() şi fct(S[p], S[deque.back()])) execută\r\n        deque.pop_back();\r\n    deque.push_back(p);\r\nSfârşit;\r\n\r\nFuncţia query(deque, întreg j) este:\r\n    cât timp (!deque.empty() şi deque.front() <= j) execută\r\n        deque.pop_front();\r\n    return S[deque.front()];\r\nSfârşit;\r\n\r\nAlgoritmul este:\r\n    lg = 0;\r\n    pentru i = 1, N execută\r\n        // funcţia min(a, b) întoarce true dacă a < b\r\n        inserează(min_deq, i, min);\r\n        // funcţia max(a, b) întoarce true dacă a > b\r\n        inserează(max_deq, i, max);\r\n        cât timp ((j < i - Y sau query(max_deq, j) - query(min_deq, j) > Z) şi j < i - X) execută\r\n            j = j + 1;\r\n        // (j, i] este intervalul candidat la soluţia optimă pentru poziţia i\r\n        dacă (j <= i - X) şi (query(max_deq, j) - query(min_deq, j) <= Z) atunci\r\n            dacă (lg >= i - j) atunci\r\n                lg = i - j, start = j + 1, stop = i;\r\n    sfârşit_pentru\r\n\r\n    dacă (lg > 0) atunci\r\n        scrie lg, start, stop;\r\n    altfel\r\n        scrie -1;\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală va fi $O(N)$.\r\n\r\nh2(#problema-4). \'4. Trans\':problema/trans (ONI 2004)\r\n\r\nbq. Se dau $N$ blocuri de piatră, de culoare albă sau neagră aşezate în ordinea $1$, $2$,.., $N$. Blocurile de piatră trebuie să fie transportate în ordinea în care sunt, iar pentru aceasta va trebui închiriat un camion. Se mai dau $Q$ tipuri de camioane. Camionul de tipul $i (1 &le; i &le; Q)$ poate transporta maxim $K{~i~}$ blocuri de piatră la un moment dat şi pentru un transport se percepe taxa $T{~i~}$. Se impune condiţia ca toate blocurile de piatră plasate în camion la un transport sa aibă aceeaşi culoare. Aşadar, pentru a fi transportate toate blocurile, se va alege un camion de un anumit tip, iar camionul va efectua unul sau mai multe transporturi. Pentru a micşora suma totală plătită, există posibilitatea de a schimba culoarea oricărui bloc de piatră (din alb în negru sau din negru în alb); pentru fiecare bloc $i (1 &le; i &le; N)$ se cunoaşte suma $S{~i~}$ ce trebuie plătită pentru a-i schimba culoarea $C{~i~}$.\r\nCerinţă: Pentru fiecare dintre cele $Q$ tipuri de camioane, determinaţi suma minimă plătită pentru a transporta toate cele $N$ blocuri.\r\nRestricţii: $1 &le; N &le; 16 000$, $1 &le; Q &le; 100$, $1 &le; K{~i~} &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se bazează pe găsirea unei formule de recurenţă ce respectă principiul optimalităţii al metodei programării dinamice.\r\n\r\nPentru început, fixăm un camion dintre cele <tex> Q </tex>. Fie <tex> K </tex> numărul maxim de pietre pe care acesta le poate transporta şi <tex> T </tex> taxa percepută. Notăm <tex> sum_{i,c} </tex> costul pentru a schimba toate pietrele <tex> 1, 2, \\ldots, i </tex> în culoarea <tex> c </tex> (<tex> c = 0 </tex> pentru alb şi <tex> c = 1 </tex> pentru negru). Rezultă că în <tex> sum_{i,c} </tex> se vor însuma toate valorile <tex> S_{j} </tex>, cu <tex> j \\le i </tex> pentru care <tex> C_{j} = 1 - c </tex>. \r\n\r\nÎn continuare, considerăm <tex> bst_{i,c} </tex> costul minim pentru a transporta pietrele <tex> 1, 2, \\ldots, i </tex>, iar ultimul transport conţine pietre de culoare <tex> c </tex>. Întrucât nu putem transporta mai mult de <tex> K </tex> pietre, <tex> bst_{i,c} </tex> depinde doar de poziţiile <tex> i - K, i - K + 1, \\ldots, i - 1 </tex>. Cunoaştem că ultimul camion va transporta o secvenţă continuă de pietre începând de la o poziţie <tex> j + 1 </tex> până la poziţia <tex> i </tex>, unde <tex> i - K \\le j \\le i - 1 </tex>. Astfel, pentru  fiecare <tex> j </tex> în intervalul precedent, costul va fi <tex> Min(bst_{j,0}, bst_{j,1}) </tex> (transportăm primele <tex> j </tex> pietre cât mai ieftin) adunat cu <tex> sum_{i,c} - sum_{j,c} </tex> (costul transformării pietrelor <tex> j + 1, \\ldots, i </tex> în culoarea <tex> c </tex>) şi plus taxa <tex> T </tex>. Rezultă recurenţa:\r\n\r\n* <tex> bst_{i,c} = Min\\ \\{\\ Minim(bst_{j,0},\\ bst_{j,1}) + sum_{i,c} - sum_{j,c} + T\\ :\\ i - K \\le j \\le i - 1\\ \\}; </tex>\r\n\r\nDacă ne vom opri aici, complexitatea soluţiei va fi <tex> O(Q * N^{2}) </tex>.\r\n\r\nRelaţia de recurenţă poate fi îmbunătăţită. Observăm că pentru poziţia <tex> i </tex>, <tex> sum_{i,c} </tex> este o valoare constantă, ca şi <tex> T </tex>. Astfel, deducem următoarea relaţie de recurenţă:\r\n\r\n* <tex> bst_{i,c} = Min\\ \\{\\ Minim(bst_{j,0},\\ bst_{j,1}) - sum_{j,c}\\ :\\ i - K \\le j \\le i - 1\\ \\} + sum_{i,c} + T; </tex>\r\n\r\nNotez în continuare, pentru uşurinţă în scriere, <tex> T_{j,c} = Min(bst_{j,0}, bst_{j,1}) - sum_{j,c} </tex>. Să fixăm doi indici <tex> i_{1} </tex> şi <tex> i_{2} </tex>, astfel încât <tex> i - K \\le i_{1} < i_{2} \\le i - 1 </tex>. Dacă <tex> T_{i_{1},c} > T_{i_{2},c} </tex> atunci întotdeauna poziţia <tex> i_{2} </tex> va fi preferată poziţiei <tex> i_{1} </tex>. Când cele două nu se vor mai afla ambele în intervalul <tex> [i - K, i - 1] </tex>, poziţia eliminată va fi poziţia <tex> i_{1} </tex>. Dacă <tex> T_{i_{1},c} < T_{i_{2},c} </tex>, atunci nu putem decide care poziţie este mai bună în viitor, aşa că le vom păstra pe ambele. Rezultă mai departe că în intervalul <tex> [i - K, i - 1] </tex> vom avea o serie de indecşi candidaţi la minim <tex> i - K \\le i_{1} < i_{2} < \\ldots < i_{n} \\le i - 1 </tex> astfel încât <tex> T_{i_{1},c} < T_{i_{2},c} <  .. < T_{i_{n},c} </tex>. Mai departe, găsim <tex> bst_{i,c} = T_{i_{1},c} + sum_{i,c} + T </tex>. Urmează să îl introducem şi pe <tex> T_{i,c} </tex> în şirul de indecşi de mai sus, el fiind egal cu <tex> Minim(bst_{i,0}, bst_{i,1}) - sum_{i,c} </tex>. Acest lucru se va face în felul următor: se vor elimina din <tex> i_{n}, , i_{n-1}, \\ldots </tex> atâta timp cât <tex> T_{i_{n},c} > T_{i,c} </tex>, <tex> T_{i_{n-1},c} > T_{i,c} \\ldots </tex> adică atâta timp cât poziţia <tex> i </tex> este preferată lui <tex> i_{n}, i_{n-1}, \\ldots </tex>. Fiind la poziţia <tex> i + 1 </tex>, intervalul se va transforma în <tex> [i - K + 1, i] </tex>, aşadar, vom mai elimina din primii indici <tex> i_{1}, i_{2}, \\ldots </tex> atâta timp cât <tex> i_{1} < i - K + 1, i_{2} < i - K + 1, \\ldots </tex>.\r\n\r\nDupă cum am arătat şi la problema precedentă, acest şir de indecşi <tex> i_{1}, i_{2}, \\ldots, i_{n} </tex> are proprietatea că este un şir continuu de numere care admite inserări prin dreapta (tail) şi ştergeri prin stânga (head). Şir ce poate fi reprezentat printr-un deque. Cum fiecare index dintre <tex> 1, 2, \\ldots, N </tex> va trece o singură dată prin deque, complexitatea soluţiei va fi <tex> O(N) </tex> pentru fiecare camion, deci <tex> O(Q * N) </tex> în total.\r\n\r\nÎn practică, programul este scurt, clar şi eficient:\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\n#include <vector>\r\n#include <deque>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\nconst char iname[] = \"trans.in\";\r\nconst char oname[] = \"trans.out\";\r\n\r\n#define MAXN  16005\r\n#define Min(a, b) ((a) < (b) ? (a) : (b))\r\n#define FOR(i, a, b)  for (int i = (a); i <= (b); ++ i)\r\n\r\nint C[MAXN], S[MAXN], bst[MAXN][2], sum[MAXN][2], N;\r\n\r\nvoid insert(deque < pair <int, int> >& deq, const pair <int, int>& p) {\r\n    while (!deq.empty() && deq.back().second > p.second)\r\n        deq.pop_back();\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque < pair <int, int> >& deq, const int idx) {\r\n    while (deq.front().first < idx)\r\n        deq.pop_front();\r\n    return deq.front().second;\r\n}\r\n\r\nint work(const int K, const int T) {\r\n    deque < pair <int, int> > deq[2];       // pair (idx, value)\r\n    FOR (c, 0, 1)\r\n        insert(deq[c], pair <int, int>(0, 0));\r\n    FOR (i, 1, N) {   // obiectul i\r\n        FOR (c, 0, 1) // culoare\r\n            bst[i][c] = query(deq[c], i - K) + sum[i][c] + T;\r\n        FOR (c, 0, 1)\r\n            insert(deq[c], pair <int, int>(i, Min(bst[i][0], bst[i][1]) - sum[i][c]));\r\n    }\r\n    return Min(bst[N][0], bst[N][1]);\r\n}\r\n\r\nint main(void)\r\n{\r\n    ifstream in(iname);  ofstream out(oname);\r\n    in >> N;\r\n    FOR (i, 1, N) {\r\n        in >> C[i] >> S[i];\r\n        FOR (c, 0, 1)\r\n            sum[i][c] += sum[i - 1][c];\r\n        sum[i][1 - C[i]] += S[i];\r\n    }\r\n    int cnt, K, T;\r\n    in >> cnt;\r\n    FOR (i, 1, cnt)\r\n        in >> K >> T, out << work(K, T) << \"\\n\";\r\n\r\n    in.close(), out.close();\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#problema-5). \'5. Otilia\':problema/otilia  (.campion)\r\n\r\nbq. Otilia şi Burbucel au o grămadă de $N$ pietre şi vor juca un joc cu următoarele trei reguli: 1. Primul jucător are voie să ia din gramadă cel mult $K$ piese; 2. Cu excepţia primei mutări, fiecare jucător are voie să ia maxim $P * t$ pietre, unde $t$ este numărul de pietre care au fost substituite din grămadă la mutarea precedentă; 3. Pierde cel care mută ultimul (cel care ia ultimele pietre din grămadă).\r\nCerinţă: Se dau $M$ jocuri prin numerele $N$, $K$ şi $P$. Se cere să se determină dacă Otilia va câştiga fiecare din jocuri sau nu.\r\nRestricţii: $1 &le; M &le; 30 000$, $1 &le; N &le; 5 000 000$, $1 &le; K &le; N$, $1 &le; P &le; 10$.\r\n\r\nh3. Soluţie (Silviu Ganceanu):\r\n\r\nProblema se rezolvă prin programare dinamică. Soluţia se bazează pe observaţia de mai jos. Considerăm $P$-ul fixat şi notăm cu $stare(X, Y)$ poziţia de start în care avem $X$ pietre şi numărul maxim de pietre care se pot lua la prima mutare este $Y$.\r\n\r\n_Observaţia 1_: „Dacă există strategie sigură de câştig pentru $stare(X, Y)$ atunci există şi pentru orice $stare(X, T)$ cu $T &ge; Y$.” \r\n\r\nDe ce? Pentru că orice mutare validă pentru $stare(X, Y)$ este validă şi pentru $stare(X, T)$. Având această observaţie notăm cu $MinY[X] = Y$, $Y$ minim astfel încât avem strategie de câştig pentru $stare(X, Y)$.\r\n\r\n_Observaţia 2_: „{$stare(X, Y)$} este pierzătoare dacă şi numai dacă $Y < MinY[X]$.” \r\n\r\nAceasta reiese din definiţia lui $MinY[X]$.\r\n\r\n$MinY[X]$ se calculează după următoarea recurenţă, care rezultă din regulile jocului: \r\n\r\n* $MinY[X]$ este cel mai mic $i$ pentru care avem $MinY[X - i] > P * i$.\r\n\r\nDe aici se naşte prima soluţie, care este implementarea directă a recurenţei. Deşi complexitatea acesteia pare a fi $O(N^2^)$ ea se comportă foarte bine pentru $N &le; 500 000$. Aşadar, această soluţie acoperă aproximativ $50%$ din testele de intrare. Printr-o rafinare a acestei soluţii se obţine un algoritm de complexitate $O(N)$. Rafinarea se bazează pe: \r\n\r\n_Observaţia 3_: „Să presupunem că dorim să calculăm $MinY[X]$. Facem următoarea afirmaţie: orice poziţie _rea_ pentru $X$ (în care dacă mutăm pierdem) va fi _rea_ şi pentru $X + 1$.”\r\n\r\nAcest lucru este simplu de observat dacă privim ce înseamnă că o poziţie $Q$ e rea pentru $X$: \r\n\r\n* $MinY[Q] > X - Q$, pentru $X$;\r\n* $MinY[Q] > X - Q + 1$, pentru $X + 1$.\r\n\r\nEste evident că prima relaţie o implică pe cea de-a doua. În momentul acesta se poate construi următorul algoritm: având lista de poziţii care pot fi bune pentru $X$ (sortată descrescător) o căutăm pe cea mai mare ca valoare care este într-adevăr bună. În principiu, scoatem din capul listei poziţiile rele până când dăm de o poziţie bună. La listă se va adăuga şi $X$ şi se va trece la pasul următor. Operaţiile algoritmului sunt chiar operaţiile asupra unui deque.\r\n\r\nh2(#problema-6). \'6. Bcrc\':problema/bcrc (Stelele Informaticii)\r\n\r\nbq. Se consideră $N$ camere, numerotate de la $1$ la $N$, aşezate în cerc. Iniţial (la momentul de timp 0), ne aflăm în camera $1$. În fiecare moment de timp, putem alege să rămânem în camera în care ne aflăm sau să ne deplasăm într-o cameră vecină într-o unitate de timp. Se dă o listă de $M$ cutii ce conţin bomboane prin $T$, $C$ şi $B$: cutia apare la momentul $T$ în camera $C$ şi conţine $B$ bomboane. Cutia va dispărea la momentul $T + 1$.\r\nCerinţă: Cunoscând numărul de camere din labirint şi momentele de timp la care apar cutiile cu bomboane, determinaţi care este numărul maxim de bomboane pe care le putem culege.\r\nRestricţii: $3 &le; N &le; 2 048$, $0 &le; M &le; 50 000$, $1 &le; T &le; 1 000 000 000$, $1 &le; C &le; N$, $1 &le; B &le; 9 999$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia foloseşte metoda programării dinamice.\r\n\r\nO stare se reprezintă prin camera în care ne aflăm şi momentul de timp. Fie <tex> bst_{i,j} </tex> numărul maxim de bomboane culese până în momentul <tex> i </tex> când ne găsim în camera <tex> j </tex>. O observaţie evidentă este că <tex> bst_{i,j} </tex> se poate modifica doar în momentele în care apar cutiile. Prin urmare, vom considera momentele de timp când apar cutiile, momente ce sunt în număr de <tex> M </tex>, <tex> bst_{i,j} </tex> însemnând numărul maxim de bomboane culese ştiind că ne aflăm în camera <tex> j </tex> unde am cules cutia <tex> i </tex>. De cine depinde această stare? Ştim că <tex> bst_{i-1,1 \\ldots N} </tex> a fost deja calculat în mod optim. Să notăm cu <tex> T </tex> diferenţa de timp dintre momentele la care apare cutia <tex> i </tex> şi cutia <tex> i - 1 </tex>. În această stare, <tex> i </tex> şi cameră <tex> j </tex>, putem ajunge din maxim <tex> T </tex> camere spre stânga sau spre dreapta, întrucât fiecare deplasare între două camere costă o unitate de timp. De unde deducem că:\r\n\r\n* <tex> bst_{i,j} = Min\\{\\ bst_{i-1,j-T},\\ bst_{i-1,j-T+1}, \\ldots,\\ bst_{i-1,j}, \\ldots,\\ bst_{i-1,j+T-1},\\ bst_{i-1,j+T}\\ \\}; </tex>\r\n\r\nMetoda directă, şi aparent eficientă, constă în folosirea unui arbore de intervale pentru aflarea acestui minim. Însă, intervalul <tex> [j-T,j+T] </tex> se deplasează constant spre dreapta, dacă vom considera indicii <tex> j </tex> în ordine <tex> 1, 2, 3, \\ldots </tex>. În acest interval noile elemente se introduc prin dreapta şi altele se elimină prin stânga. Însă, cum am arătat în problemele precedente, nu avem nevoie de toate valorile din acest interval. Şi din acest motiv vom folosi un deque de lungime <tex> T * 2 + 1 </tex> cu care vom elimina poziţiile care nu sunt candidate la soluţie. Mai jos este o reprezentare grafică a acestei explicaţii.\r\n\r\np=. !deque-si-aplicatii?bcrc.png 40%!\r\n\r\nComplexitatea finală: <tex> O(M * N) </tex>.\r\n\r\nh2(#problema-7). \'7. Cut the Sequence\':http://acm.pku.edu.cn/JudgeOnline/problem?id=3017 (PKU) \r\n\r\nbq. Se dă o secvenţă $S$ de numere întregi de lungime $N$. Va trebui să se împartă secvenţa în mai multe subsecvenţe astfel încât suma valorilor din fiecare parte să nu depăşească un număr întreg $M$ dat, iar dacă însumăm maximul din fiecare subsecvenţă să obţinem o sumă cât mai mică.\r\nRestricţii: $0 &lt; N &le; 100 000$, $0 &le; S{~i~} &le; 1 000 000$.\r\n\r\nh3. Soluţie:\r\n\r\nŞi această soluţie foloseşte metoda programării dinamice. Construim <tex> bst_{i} </tex> egal cu costul minim de a împărţi primele <tex> i </tex> numere din <tex> S </tex>. Pentru a calcula <tex> bst_{i} </tex> alegem toate secvenţele posibile care încep la o poziţie <tex> j+1 </tex>, <tex> j < i </tex>, şi adunăm valorile corespunzătoare:\r\n\r\n* <tex> bst_{i} = Min\\{bst_{j} + Max\\{S_{j+1},.., S_{i}\\}\\ :\\ 0 \\le j < i, \\displaystyle\\sum_{k=j+1}^{i} S_{k} \\le M\\}; </tex>\r\n\r\nImplementarea directă a acestei recurenţe conduce la un algoritm de complexitate <tex> O(N^{2}) </tex>, dar care pentru restricţiile impuse nu este de ajuns.\r\n\r\nSă obţinem în continuare alte informaţii. Fie indicele <tex> j </tex> minim astfel încât <tex> \\displaystyle\\sum_{k=j+1}^{i} \\le M </tex>. Maximul obţinut din mulţimea <tex> \\{S_{j+1},.., S_{i}\\} </tex> se găseşte pe o poziţie <tex> j^{\'} </tex> unde <tex> j < j^{\'} \\le i </tex>. Însă, orice indice <tex> k </tex> cu <tex> j \\le k < j^{\'} </tex> are proprietatea că rezultatul expresiei <tex> Max\\{S_{k+1},.., S_{i}\\} </tex> se găseşte pe poziţia <tex> j^{\'} </tex>. Rezultă că <tex> \\forall k \\in \\{j, j+1,.., j^{\'}-1\\} </tex>, <tex> bst_{i} </tex> poate fi îmbunătăţit cu valoarea <tex> bst_{k} + S_{j^{\'}} </tex>. Minimul mulţimii <tex> \\{bst_{k} + S_{j^{\'}} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} </tex> este egal cu minimul expresiei <tex> \\{bst_{k} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} + S_{j^{\'}} (*) </tex>, deci, schimbând reperele, pentru maximul de pe poziţia <tex> j^{\'} </tex>, dacă lungimea secvenţei care se termină în <tex> i </tex> este cel puţin <tex> i-j^{\'}+1 </tex>, atunci optimul se obţine calculând rezultatul expresiei <tex> (*) </tex>. Pentru minimul pe un interval, <tex> [j, j^{\'}-1] </tex> al valorile vectorului <tex> bst </tex>, putem folosi un arbore de intervale pentru <tex> O(log_{2}N) </tex> pe interogare.\r\n\r\nDar, lungimea optimă a ultimei secvenţe ce se termină în <tex> i </tex> poate fi mai mică decât <tex> i-j^{\'}+1 </tex>, deci poate fi cel mult <tex> i-j^{\'} </tex>. Optimul se găseşte printre elementele mulţimii <tex> \\{bst_{k} + Max\\{S_{k+1},..,S_{i}\\} : j^{\'} \\le k < i\\} </tex>. Dacă procedăm ca la pasul anterior vom obţine un alt indice <tex> j^{\'\'} </tex> cu aceleaşi proprietăţi pentru secvenţa <tex> [j^{\'}, i] </tex> precum <tex> j^{\'} </tex> pentru secvenţa <tex> [j, i] </tex>.\r\n\r\nInductiv obţinem un şir de indici <tex> j_{0} = j < j_{1} < j_{2} < .. < j_{K} = i </tex> astfel încât <tex> S_{j_{1}} </tex> este cel mai mare element al secvenţei <tex> (j, i] </tex>, <tex> S_{j_{2}} </tex> cel mai mare element al secvenţei <tex> (j_{1}, i] </tex>, şi aşa mai departe, când <tex> j_{K} </tex> este chiar <tex> i </tex>.\r\n\r\nCu ajutorul relaţiei <tex> (*) </tex> şi a şirului <tex> j_{1} < j_{2} < .. < j_{K} = i </tex> vom construi un alt vector <tex> iMin </tex> cu proprietatea că <tex> iMin_{p} = Min\\{bst_{r} + S_{j_{p}} : j_{p-1} \\le r < j_{p}\\} </tex>. În final, <tex> bst_{i} = Minim\\{iMin_{1}, iMin_{2}, .., iMin_{K}\\} </tex>, rezultat pe care îl putem obţine în <tex> O(log_{2}N) </tex> dacă folosim un arbore de intervale.\r\n\r\nÎnsă, cum se construieşte şirul <tex> j_{1} < j_{2} < .. < j_{K} = i </tex>? În \'a doua problemă\':deque-si-aplicatii#problema-2 am construit cu ajutorul unui deque exact şirul de indici de care avem nevoie aici. Când vom înainta la indicele <tex> i + 1 </tex> vom modifica şirul astfel încât să respecte proprietăţile de mai sus utilizând operaţiile normale asupra unui deque. Mai sus am menţionat cum se obţine <tex> bst_{i} </tex> lucru care implică combinarea structurilor de deque şi arbore de intervale. Arborele de intervale reţine valorile lui <tex> iMin </tex> pentru fiecare element al dequelui. \r\n\r\nPentru a înţelege cum funcţionează acest algoritm să considerăm ca date de intrare şirul <tex> S = \\{5, 9, 4, 7, 4, 1, 6, 3\\} </tex> şi <tex> M = 15 </tex>. Perechile din deque sunt de forma <tex> (S_{i}, iMin_{p}) </tex>. Fie <tex> i = 1, 2, \\ldots 8 </tex>:\r\n\r\n* <tex> i = 1: j = 0, head = 1, tail = 1, deque = \\{\\ (5, 0)\\ \\} \\Rightarrow bst_{1} = 5; </tex>\r\n* <tex> i = 2: j = 0, head = 1, tail = 1, deque = \\{\\ (9, 0)\\ \\} \\Rightarrow bst_{2} = 9; </tex>\r\n* <tex> i = 3: j = 1, head = 1, tail = 2, deque = \\{\\ (9, 5),\\ (4, 9)\\ \\} \\Rightarrow bst_{3} = 13; </tex>\r\n* <tex> i = 4: j = 2, head = 2, tail = 2, deque = \\{\\ (7, 9)\\ \\} \\Rightarrow bst_{4} = 16; </tex>\r\n* <tex> i = 5: j = 2, head = 2, tail = 3, deque = \\{\\ (7, 9),\\ (4, 16)\\ \\} \\Rightarrow bst_{5} = 16; </tex>\r\n* <tex> i = 6: j = 3, head = 2, tail = 4, deque = \\{\\ (7, 13),\\ (4, 16),\\ (1, 16)\\ \\} \\Rightarrow bst_{6} = 17; </tex>\r\n* <tex> i = 7: j = 4, head = 3, tail = 3, deque = \\{\\ (6, 16)\\ \\} \\Rightarrow bst_{7} = 22; </tex>\r\n* <tex> i = 8: j = 4, head = 3, tail = 4, deque = \\{\\ (6, 16),\\ (3, 22)\\ \\} \\Rightarrow bst_{8} = 22; </tex>\r\n\r\nMai jos se vede o figură în care elementele unui deque sunt defapt o secvenţă „continuă” de frunze ale unui arbore de intervale pentru cazul <tex> i = 6 </tex>.\r\n\r\np=. !deque-si-aplicatii?PKU0.png 60%!\r\n\r\np=. _Numărul maxim de elemente ce pot trece prin deque este $8$. În figură, arborele ţine minimul de pe poziţiile $2$, $3$, $4$ din deque._\r\n\r\nAlgoritmul în pseudocod arată în felul următor:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    sum  = 0;\r\n    last = 0;\r\n    // indicii head si tail ai dequeului\r\n    head = tail = 1;\r\n    // poziţia lui bst[0] se inserează în deque\r\n    deque[1] = 0;\r\n    pentru i = 1, N execută\r\n        sum += S[i];\r\n        temp = bst[ deque[tail] ];\r\n        cât timp (head <= tail) şi (S[ deque[tail] ] <= S[i]) execută\r\n            temp = Min(temp, iMin[tail]);\r\n            tail --;\r\n        sfârşit;\r\n        // adaug poziţia i la deque\r\n        tail ++;\r\n        deque[tail] = i;\r\n        // actualizez iMin[]\r\n        iMin[tail]  = temp;\r\n        // actualizez T[], arborele de intervale pe deque[]\r\n        Update(T, tail, iMin[tail] + S[i]);\r\n        // suma valorilor din [last, i] trebuie să nu depăşească M\r\n        cât timp (sum > M) execută\r\n            sum -= S[last];\r\n            dacă (deque[head] == last) atunci\r\n                head ++;\r\n            sfârşit;\r\n            last ++;\r\n        sfârşit;\r\n        // actualizez iMin[], Tb[] arborele de intervale pe bst[]\r\n        iMin[head] = Query(Tb, Max(last - 1, 0), deque[head] - 1);\r\n        // actualizez T[]\r\n        Update(T, head, iMin[head] + S[ deque[head] ]);\r\n        // reţin optimul pentru poziţia curentă\r\n        bst[i] = Query(T, head, tail);\r\n        // actualizez Tb[]\r\n        Update(Tb, i, bst[i]);\r\n    sfârşit;\r\n    scrie bst[N];\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală este <tex> O(N*log_{2}N) </tex>.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nFilozofia din spatele structurii de deque devine utilă, de obicei, în părţile finale ale rezolvării unei probleme. Însă, ce pot spune cu certitudine este că această structură de date pe cât este de simplă pe atât este de eficientă şi necesară.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\nÎnţelegerea profundă nu se poate realiza decât prin rezolvarea a cât mai multe probleme. Succes!\r\n\r\n* \'Deque\':problema/deque, _Arhiva educaţională_\r\n* \'Secvenţă\':problema/secventa\r\n* \'Secvenţă 3\':problema/secv3\r\n* \'Secvenţă 4\':problema/secv4\r\n* \'Sum 2\':problema/sum2, _Stelele Informaticii 2003_\r\n* \'Drept 2\':problema/drept2, _Lotul Naţional de Informatică, 2006_\r\n* \'Copaci 2\':problema/copaci2, _.campion_\r\n* \'Struţi\':problema/struti\r\n* \'Brânză\':problema/branza\r\n* \'Trompetă\':problema/trompeta\r\n* \'Buline\':problema/buline\r\n* \'Balans\':problema/balans\r\n* \'Munte4\':problema/munte4, _Lotul Naţional de Informatică, 2005_\r\n* \'Gard\':problema/gard, _ONI 2002_\r\n* \'Ghiozdan\':problema/ghiozdan\r\n* \'Cover\':problema/cover, _ONI 2007, Baraj_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Cosmin Negruşeri, \"_Probleme cu secvenţe_\":probleme-cu-secvente\r\n# Dana Lica, \"_Arbori de intervale şi aplicaţii în geometria computaţională_\":arbori-de-intervale\r\n# Cătălin Frâncu, \"_Heapuri_\":heapuri\r\n# Marius Stroe, \"_Treapuri_\":treapuri\r\n# \'C++ Reference\':http://www.cplusplus.com/',3146,'public',NULL,NULL),('planificare/sedinta-20090216','Sedinta 2009-02-16','2009-02-09 14:25:39','2009-02-16 10:17:53','h1. Sedinta 2009-02-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Februarie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")== (nu s-ar putea un pic mai devreme ca sa prindem si metroul la intoarcere?)\r\n* ==user(user=\"silviug\" type=\"tiny\")== (@Filip: cred că terminăm pe la 22:00, deci prinzi metrou)\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"danielp\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090126| ==user(user=\"silviug\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Concursul Centrelor de Excelenta/Concurs in engleza | ==user(user=\"filipb\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n\r\nh3. Misc\r\n\r\n* OKRs Q12009\r\n\r\n* Community ladder\r\n\r\n* Ce se mai aude cu initiativa in care donam calculatoare utilizate?\r\n\r\n* Tutorial C/C++\r\n** E nevoie de un tutorial introductiv de C/C++ cu exemple de rezolvari din arhiva\r\n** Ideea Thero. Vrea sa-l faca chiar el. Si Paul vrea sa se implice.\r\n** Va fi video!\r\n** Facem IAP?\r\n\r\n* Infoarena \"educational tool\"\r\n** Are rost sa ne propunem o infoarena utila si pentru elevul mediu de nationala?\r\n** Profesori pe care ii putem contacta sa le cerem parerea/sa se implice in infoarena.\r\n** Paul: \"Ar fi bine sa incercam sa convingem pe cati mai multi dintre profesori ca nu suntem interesati sa ii concuram, ci dimpotriva suntem dispusi sa ii ajutam in pregatirea elevilor lor mai buni.\" Cum facem asta?\r\n\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n...\r\n\r\nh2. Notiţe\r\n\r\n...\r\n',13,'protected',NULL,NULL),('planificare/sedinta-20090216','Sedinta 2009-02-16','2009-02-09 14:25:39','2009-02-16 12:08:03','h1. Sedinta 2009-02-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Februarie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")== (nu s-ar putea un pic mai devreme ca sa prindem si metroul la intoarcere?)\r\n* ==user(user=\"silviug\" type=\"tiny\")== (@Filip: cred că terminăm pe la 22:00, deci prinzi metrou)\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"danielp\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090126| ==user(user=\"silviug\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Concursul Centrelor de Excelenta/Concurs in engleza | ==user(user=\"filipb\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n\r\nh3. Misc\r\n\r\n* OKRs Q12009\r\n\r\n* Community ladder\r\n\r\n* Ce se mai aude cu initiativa in care donam calculatoare utilizate?\r\n\r\n* Tutorial C/C++\r\n** E nevoie de un tutorial introductiv de C/C++ cu exemple de rezolvari din arhiva\r\n** Ideea Thero. Vrea sa-l faca chiar el. Si Paul vrea sa se implice. Later edit: Lui Paul ii ajunge Arhiva educationala deocamdata. :)\r\n** Va fi video!\r\n** Facem IAP?\r\n\r\n* Infoarena \"educational tool\"\r\n** Are rost sa ne propunem o infoarena utila si pentru elevul mediu de nationala?\r\n** Profesori pe care ii putem contacta sa le cerem parerea/sa se implice in infoarena.\r\n** Paul: \"Ar fi bine sa incercam sa convingem pe cati mai multi dintre profesori ca nu suntem interesati sa ii concuram, ci dimpotriva suntem dispusi sa ii ajutam in pregatirea elevilor lor mai buni.\" Cum facem asta?\r\n\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n...\r\n\r\nh2. Notiţe\r\n\r\n...\r\n',1792,'protected',NULL,NULL),('blog/okrs-20091','Obiective infoarena','2009-02-16 15:39:49','2009-02-16 15:41:33','Ştiaţi că, încă din 2006, \'echipa infoarena\':echipa-infoarena se întruneşte periodic pentru a pune la cale proiectele şi evenimentele infoarena? \'Concursurile infoarena\':concursuri, coding camp-urile, \'facilităţile site-ului\':http://hackers.devnet.ro/report/1, finalele preONI* şi promovarea membrilor infoarena sunt deseori stabilite în astfel de şedinţe. Dacă vrei să-ţi faci o idee despre ce se întâmplă la o şedinţă infoarena şi ce se hotărăşte acolo, aruncă o privire în \'secţiunea planificare\':planificare.\r\n\r\nBineînţeles, şedinţele în sine nu sunt foarte importante. Munca „adevărată” se face între ele şi cu ajutorul nelipsit al voluntarilor. Dacă un voluntar se implică semnificativ în comunitatea infoarena îl invităm de cele mai multe ori să facă parte din echipa noastră şi să îşi spună cuvântul în cadrul şedinţelor, să decidă alături de noi ce vom face în continuare.\r\n\r\nCu timpul, echipa infoarena s-a mărit, la fel şi numărul de proiecte pe care le-am început. A devenit din ce în ce mai greu să lucrăm bine împreună, motiv pentru care am decis să adoptăm \'sistemul OKRs\':propuneri/9-okr pe care mai mulţi dintre noi l-am văzut şi l-am folosit la Google în internship-uri.\r\n\r\nDespre OKR-uri puteţi citi mai multe în pagina dedicată. Pe scurt însă, OKR-urile (Objectives and Key Results) sunt o serie de obiective şi rezultate cheie măsurabile pe care ni le stabilim trimestrial. La sfârşitul fiecărui trimestru tragem linie şi facem bilanţul.\r\n\r\nSă nu înţelegeţi greşit; urîm birocraţia la fel de mult ca şi voi, în special pentru că suntem programatori şi pentru că obişnuim să căutăm soluţii eficiente la problemele din jurul nostru. Adoptarea OKR-urilor vine dintr-o nevoie reală de a lucra eficient împreună pentru un scop comun.\r\n\r\nAm testat marea cu degetul în octombrie 2008 asumându-ne \'o serie de obiective\':okr/20084, iar la sfârşitul trimestrului am tras linie şi am numărat că am îndeplinit doar jumătate din ce ne-am propus. Dacă sună dezamăgitor, să ştiţi că nu e. În realitate, am fost prea optimişti şi ne-am asumat obiective prea ambiţioase. Experientia docet :)\r\n\r\nAm stabilit obiective şi pentru \'2009, trimestrul I\':okr/20091 şi vă invit să le citiţi dacă sunteţi interesaţi de direcţia în care se îndreaptă infoarena.\r\n\r\n    Vreau să ştiu ce aţi dori voi să facă infoarena în continuare şi vreau mai ales să vă implicaţi alături de noi. infoarena este o meritocraţie, cine aduce valoare are un cuvânt de spus.\r\n',13,'private',NULL,NULL),('planificare/sedinta-20090216','Sedinta 2009-02-16','2009-02-09 14:25:39','2009-02-16 17:41:59','h1. Sedinta 2009-02-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Februarie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala -8- 22.)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")== (nu s-ar putea un pic mai devreme ca sa prindem si metroul la intoarcere?)\r\n* ==user(user=\"silviug\" type=\"tiny\")== (@Filip: cred că terminăm pe la 22:00, deci prinzi metrou)\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"danielp\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090126| ==user(user=\"silviug\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Concursul Centrelor de Excelenta/Concurs in engleza | ==user(user=\"filipb\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n|Rezoluţii pentru IAP-uri antice (1, 2, 8)| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n\r\nh3. Misc\r\n\r\n* OKRs Q12009\r\n\r\n* Community ladder\r\n\r\n* Ce se mai aude cu initiativa in care donam calculatoare utilizate?\r\n\r\n* Tutorial C/C++\r\n** E nevoie de un tutorial introductiv de C/C++ cu exemple de rezolvari din arhiva\r\n** Ideea Thero. Vrea sa-l faca chiar el. Si Paul vrea sa se implice. Later edit: Lui Paul ii ajunge Arhiva educationala deocamdata. :)\r\n** Va fi video!\r\n** Facem IAP?\r\n\r\n* Infoarena \"educational tool\"\r\n** Are rost sa ne propunem o infoarena utila si pentru elevul mediu de nationala?\r\n** Profesori pe care ii putem contacta sa le cerem parerea/sa se implice in infoarena.\r\n** Paul: \"Ar fi bine sa incercam sa convingem pe cati mai multi dintre profesori ca nu suntem interesati sa ii concuram, ci dimpotriva suntem dispusi sa ii ajutam in pregatirea elevilor lor mai buni.\" Cum facem asta?\r\n* Centrul de Excelenţă Bucureşti\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Reportat review la blog post\r\n* Vali face IAP si OKR despre ordonarea problemelor (vezi formula de la IMDB)\r\n* Wefgef ia mancare si bautura (limita 30 RON)\r\n* Wefgef numara cati nu sunt din Bucuresti la Algoritmiada\r\n* Wefgef vorbeste in Tg. Mures cu Universitatea Sapientia\r\n* Wefgef face lista de cerinte\r\n* Silviu face rost de contact in Brasov\r\n* Silviu vorbeste la Poli iara, cu Tapus\r\n* Mort face mail spam pentru sponsori (Silviu si Wef review)\r\n* \r\n\r\nh2. Notiţe\r\n\r\n* Ne trebuie mapa cu prezentare infoarena pentru sponsori\r\n* Silviu pune stire ca nu mai ai voie cu HTML si sa-si actualizeze lumea profilele\r\n\r\n',1,'protected',NULL,NULL),('planificare/sedinta-20090216','Sedinta 2009-02-16','2009-02-09 14:25:39','2009-02-16 18:01:57','h1. Sedinta 2009-02-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Februarie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala -8- 22.)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")== (nu s-ar putea un pic mai devreme ca sa prindem si metroul la intoarcere?)\r\n* ==user(user=\"silviug\" type=\"tiny\")== (@Filip: cred că terminăm pe la 22:00, deci prinzi metrou)\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"danielp\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090126| ==user(user=\"silviug\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Concursul Centrelor de Excelenta/Concurs in engleza | ==user(user=\"filipb\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n|Rezoluţii pentru IAP-uri antice (1, 2, 8)| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n\r\nh3. Misc\r\n\r\n* OKRs Q12009\r\n\r\n* Community ladder\r\n\r\n* Ce se mai aude cu initiativa in care donam calculatoare utilizate?\r\n\r\n* Tutorial C/C++\r\n** E nevoie de un tutorial introductiv de C/C++ cu exemple de rezolvari din arhiva\r\n** Ideea Thero. Vrea sa-l faca chiar el. Si Paul vrea sa se implice. Later edit: Lui Paul ii ajunge Arhiva educationala deocamdata. :)\r\n** Va fi video!\r\n** Facem IAP?\r\n\r\n* Infoarena \"educational tool\"\r\n** Are rost sa ne propunem o infoarena utila si pentru elevul mediu de nationala?\r\n** Profesori pe care ii putem contacta sa le cerem parerea/sa se implice in infoarena.\r\n** Paul: \"Ar fi bine sa incercam sa convingem pe cati mai multi dintre profesori ca nu suntem interesati sa ii concuram, ci dimpotriva suntem dispusi sa ii ajutam in pregatirea elevilor lor mai buni.\" Cum facem asta?\r\n* Centrul de Excelenţă Bucureşti\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Reportat review la blog post\r\n* Vali face IAP si OKR despre ordonarea problemelor (vezi formula de la IMDB)\r\n* Wefgef ia mancare si bautura (limita 30 RON)\r\n* Wefgef numara cati nu sunt din Bucuresti la Algoritmiada\r\n* Wefgef vorbeste in Tg. Mures cu Universitatea Sapientia\r\n* Wefgef face lista de cerinte\r\n* Silviu face rost de contact in Brasov\r\n* Silviu vorbeste la Poli iara, cu Tapus\r\n* Mort face mail spam pentru sponsori (Silviu si Wef review)\r\n* Wefgef da drumul la pregatirea problemelor pentru runda finala & pagini\r\n* Mircea vorbeste cu Vali si Paul de Coding Camp\r\n* Airinei trebuie sa confirme ca vine la Coding Camp\r\n* Cristi se ocupa de locatie Coding Camp\r\n* Mircea mai pune task-uri pe agenda de Coding Camp\r\n\r\nh2. Notiţe\r\n\r\n* Ne trebuie mapa cu prezentare infoarena pentru sponsori\r\n* Silviu pune stire ca nu mai ai voie cu HTML si sa-si actualizeze lumea profilele\r\n\r\n',1,'protected',NULL,NULL),('planificare/sedinta-20090216','Sedinta 2009-02-16','2009-02-09 14:25:39','2009-02-16 18:50:45','h1. Sedinta 2009-02-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Februarie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala -8- 22.)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"filipb\" type=\"tiny\")== (nu s-ar putea un pic mai devreme ca sa prindem si metroul la intoarcere?)\r\n* ==user(user=\"silviug\" type=\"tiny\")== (@Filip: cred că terminăm pe la 22:00, deci prinzi metrou)\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"danielp\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090126| ==user(user=\"silviug\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Concursul Centrelor de Excelenta/Concurs in engleza | ==user(user=\"filipb\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n|Rezoluţii pentru IAP-uri antice (1, 2, 8)| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh2. Detalii\r\n\r\n\r\nh3. Misc\r\n\r\n* OKRs Q12009\r\n\r\n* Community ladder\r\n\r\n* Ce se mai aude cu initiativa in care donam calculatoare utilizate?\r\n\r\n* Tutorial C/C++\r\n** E nevoie de un tutorial introductiv de C/C++ cu exemple de rezolvari din arhiva\r\n** Ideea Thero. Vrea sa-l faca chiar el. Si Paul vrea sa se implice. Later edit: Lui Paul ii ajunge Arhiva educationala deocamdata. :)\r\n** Va fi video!\r\n** Facem IAP?\r\n\r\n* Infoarena \"educational tool\"\r\n** Are rost sa ne propunem o infoarena utila si pentru elevul mediu de nationala?\r\n** Profesori pe care ii putem contacta sa le cerem parerea/sa se implice in infoarena.\r\n** Paul: \"Ar fi bine sa incercam sa convingem pe cati mai multi dintre profesori ca nu suntem interesati sa ii concuram, ci dimpotriva suntem dispusi sa ii ajutam in pregatirea elevilor lor mai buni.\" Cum facem asta?\r\n* Centrul de Excelenţă Bucureşti\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Reportat review la blog post\r\n* Vali face IAP si OKR despre ordonarea problemelor (vezi formula de la IMDB)\r\n* Wefgef ia mancare si bautura (limita 30 RON)\r\n* Wefgef numara cati nu sunt din Bucuresti la Algoritmiada\r\n* Wefgef vorbeste in Tg. Mures cu Universitatea Sapientia\r\n* Wefgef face lista de cerinte\r\n* Silviu face rost de contact in Brasov\r\n* Silviu vorbeste la Poli iara, cu Tapus\r\n* Mort face mail spam pentru sponsori (Silviu si Wef review)\r\n* Wefgef da drumul la pregatirea problemelor pentru runda finala & pagini\r\n* Mircea vorbeste cu Vali si Paul de Coding Camp\r\n* Airinei trebuie sa confirme ca vine la Coding Camp\r\n* Cristi se ocupa de locatie Coding Camp\r\n* Mircea mai pune task-uri pe agenda de Coding Camp\r\n* Wefgef stabileste contact cu Florentina\r\n* Cristi reinoieste domeniul infoarena.org\r\n* infoarena in engleza e prioritar pentru urmatorul Coding Camp\r\n* Silviu vorbeste cu Tero despre .org\r\n* S-a respins IAP 1, 2, 3 si 8 este fara resurse\r\n* Silviu face la Coding Camp task-uri interactive\r\n* Wefgef scoate forum-ul de la OKR-uri\r\n* Silviu si Cristi concretizeaza IAP 7 (2 sedinte)\r\n* Urmatoarea sedinta pe 2 martie\r\n* Silviu vorbeste cu Blonda despre donat calculatoare\r\n\r\nh2. Notiţe\r\n\r\n* Ne trebuie mapa cu prezentare infoarena pentru sponsori\r\n* Silviu pune stire ca nu mai ai voie cu HTML si sa-si actualizeze lumea profileleb',1,'protected',NULL,NULL),('documentatie/backup','Backup infoarena','2009-03-02 17:58:32','2009-03-03 01:38:36','h1. Backup infoarena\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nUna dintre responsabilităţile administratorilor infoarena este aceea de păstra conţinutul site-ului în siguranţă, astfel încât să poată fi recuperat în urma unor evenimente excepţionale nedorite. Este posibil ca server-ul pe care găzduim site-ul să pice, este posibil să pierdem informaţii importante, fie accidental, fie din cauza unor persoane rău intenţionate. În orice caz, este necesar să ne protejăm de astfel de evenimente cu ajutorul unui backup periodic.\r\n\r\nCâţiva administratori infoarena vor face backup periodic folosind calculatoarele lor personale. Scopul este să obţinem un sistem redundant de backup, complet automatizat şi uşor de monitorizat. Pagina aceasta explică acestor administratori ce trebuie să facă pentru a-şi configura staţiile de lucru personale în acest sens.\r\n\r\nh2. Cerinţe\r\n\r\n* Sistem de operare Linux\r\n* $rsync$, şi client $ssh$ %{color:gray}(Cel mai probabil sunt deja instalate.)%\r\n* \'O copie locală de infoarena\':http://hackers.devnet.ro/wiki/HackingTutorial, instalată, configurată şi funcţională. Ai grijă să o menţii la o versiune actuală, întrucât scriptul de backup se poate modifica în timp. %{color:gray}(Este OK să foloseşti chiar copia pe care în mod normal dezvolţi cod pentru infoarena. Nu e nevoie să configurezi şi evaluatorul. Nu este necesar ca server-ul Apache sau MySQL să ruleze.)%\r\n* Cel puţin $10 GB$ spaţiu de stocare disponibil.\r\n\r\nh2. Basic Setup\r\n\r\nProcesul de backup va rula cu permisiunile unui utilizator oarecare de pe sistemul tău. Nu are importanţă ce utilizator e, însă e mai simplu să fie chiar utilizatorul pe care îl foloseşti în mod obişnuit când lucrezi la calculator. În continuare voi presupune că numele tău de utilizator este *$wickedman$* şi că eşti logat pe calculator.\r\n\r\n# Generează o cheie privată *fără parolă* pentru acces la contul de backup de pe server-ul infoarena.\r\n$ $ssh-keygen -f ~/.ssh/ia-backup$\r\n# Autorizează cheia ta pentru backup. Acest pas necesită acces root@infoarena.ro. Un mod de a-ţi autoriza cheia este să execuţi comanda următoare de pe calculatorul tău:\r\n$ $ssh -p 21883 root@infoarena.ro echo `cat ~/.ssh/ia-backup.pub` \'>> /home/backup/.ssh/authorized_keys\'$\r\n# Testează accesul la backup@infoarena.ro:\r\n$ $ssh -i ~/.ssh/ia-backup -p 21883 backup@infoarena.ro \'echo `whoami`@`hostname`\'$\r\nar trebui să afişeze $backup@infoarena$.\r\n# Crează un director pentru backup şi asigură-te că ai suficient spaţiu liber pe partiţia respectivă. (Vezi cerinţe.) Scriptul de backup e configurat să folosească în mod implicit $~/backup/infoarena$. Dacă vrei să foloseşti alt director va trebui să îl modifici corespunzător.\r\n$ $mkdir -p ~/backup/infoarena$\r\n# Execută scriptul de backup. Mai jos presupun că eşti în directorul în care ai făcut checkout la infoarena, dar nu e obligatoriu.\r\n$ $./scripts/mirror-backup$\r\n%{color:red}*Atenţie!*% Scriptul va începe să copieze toate ataşamentele de pe infoarena.ro, adică peste 6.7GB! Asigură-te că ai o conexiune cât poţi de bună ca să nu dureze o veşnicie. Desigur, următoarele apelări vor transfera mult mai puţine date.\r\n# În final ar trebui să ai o structură de directoare similară cu cea de mai jos:\r\n$ $find ~/backup/infoarena -type d$\r\n$/home/wickedman/backup/infoarena$\r\n$/home/wickedman/backup/infoarena/attach$\r\n$/home/wickedman/backup/infoarena/attach/200910$\r\n$/home/wickedman/backup/infoarena/archive$\r\n$/home/wickedman/backup/infoarena/archive/db$\r\n$/home/wickedman/backup/infoarena/archive/hackers$\r\n$/home/wickedman/backup/infoarena/archive/hackers/trac$\r\n$/home/wickedman/backup/infoarena/archive/hackers/reviewboard$\r\n$/home/wickedman/backup/infoarena/archive/hackers/svn$\r\n$/home/wickedman/backup/infoarena/archive/conf$\r\n\r\nCu fiecare lansare, $./scripts/mirror-backup$ sincronizează ultimele versiuni de backup locale cu cele de pe infoarena.ro şi poate fi rulat cu încredere de oricâte ori.\r\n\r\nh2. Backup automat zilnic\r\n\r\nÎn continuare vom configura calculatorul să facă backup automat în fiecare zi folosind utilitarul $anacron$. Spre deosebire de $cron$, acesta nu necesită ca staţia de lucru să fie deschisă la o anumită oră din zi. Eşti liber să închizi şi să deschizi calculatorul oricând doreşti.\r\n\r\n# Instalează anacron. (Pe Ubuntu merge $apt-get install anacron$.)\r\n# Editează $/etc/anacrontab$\r\n$ $sudo vim /etc/anacrontab$\r\nşi adaugă la sfârşitul fişierului linia următoare. %{color:red}*Atenţie!*% Ajustează corespunzător textul îngroşat!\r\n$1	30	infoarena-backup	 sudo -H -u *wickedman* /home/{*wickedman/d/infoarena*}/scripts/mirror-backup$ | mail -s \"infoarena backup notice\" *cristian@infoarena.ro*\r\n%{color:gray}(Asta înseamnă că job-ul „infoarena-backup” se execută odată pe zi, la 30 de minute după ce ai pornit calculatorul. Folosesc $sudo -u$ ca să execut job-ul cu permisiuni de utilizator obişnuit.)%\r\n# Testează configuraţia $anacron$.\r\n$ $sudo anacron -fnd infoarena-backup$\r\n$Anacron 2.3 started on 2009-03-03$\r\n$Will run job `infoarena-backup\'$\r\n$Jobs will be executed sequentially$\r\n$Job `infoarena-backup\' started$\r\n$Job `infoarena-backup\' terminated (mailing output)$\r\n$Normal exit (1 job run)$\r\n\r\n\r\n',13,'public',NULL,NULL),('okr/20091','OKRs 2009Q1','2009-01-26 14:41:23','2009-01-28 13:06:59','h2. 2009Q1\r\n\r\nh3(#arhiva). Arhiva de probleme\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Extinde arhiva\':implica-te/extinde-arhiva | ==user(user=\"ditzonec\" type=\"tiny\")== | ==include(page=\"okr/20091/extinde-arhiva\")== | ? |\r\n| \'Imbunatateste teste\':implica-te/imbunatatire-teste | ==user(user=\"ditzonec\" type=\"tiny\")== | ==include(page=\"okr/20091/imbunatatire-teste\")== | ? |\r\n| \'Arhiva educationala\':implica-te/arhiva-educationala | ==user(user=\"pauldb\" type=\"tiny\")== | ==include(page=\"okr/20091/arhiva-educationala\")== | ? |\r\n| Tagging|==user(user=\"bogdan2412\" type=\"tiny\")== | ==include(page=\"okr/20091/tagging\")== | ? |\r\n\r\nh3(#concursuri). Concursuri\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Organizeaza concursuri | ==user(user=\"astronomy\" type=\"tiny\")== | ==include(page=\"okr/20091/organizeaza-concursuri\")== | ? |\r\n| Algoritmiada | ==user(user=\"wefgef\" type=\"tiny\")== | ==include(page=\"okr/20091/algoritmiada\")== | ? |\r\n| \'Virtual contests\':propuneri/10-virtual-contest | ==user(user=\"gcosmin\" type=\"tiny\")== | ==include(page=\"okr/20091/virtual-contest\")== | ? |\r\n| \'Calendar\':forum?action=calendar | ==user(user=\"pauldb\" type=\"tiny\")== | ==include(page=\"okr/20091/calendar\")== | ? |\r\n\r\nh3(#continut). Continut educational\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Scrie articole\':implica-te/scrie-articole | ==user(user=\"stef2n\" type=\"tiny\")== | ==include(page=\"okr/20091/articole\")== | ? |\r\n\r\nh3(#development). Development\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'infoarena 2.x Stable\':http://hackers.devnet.ro/roadmap | ==user(user=\"domino\" type=\"tiny\")== | ==include(page=\"okr/20091/devel-ia2\")== | ? |\r\n\r\nh3(#comunitate). Comunitate\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Forum\':forum | ==user(user=\"wefgef\" type=\"tiny\")== | ==include(page=\"okr/20091/forum\")== | ? |\r\n| \'Community Ladder\':propuneri/7-community-ladder | ==user(user=\"wickedman\" type=\"tiny\")==, ==user(user=\"silviug\" type=\"tiny\")==  | ==include(page=\"okr/20091/community\")== | ? |\r\n\r\nh3(#administrativ). Administrativ\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Newsletter | ==user(user=\"wickedman\" type=\"tiny\")==| ==include(page=\"okr/20091/newsletter\")== | ? |\r\n| Strangere fonduri | ==user(user=\"wickedman\" type=\"tiny\")== | ==include(page=\"okr/20091/fund-raising\")== | ? |\r\n',961,'public',NULL,NULL),('grigore-moisil-2009/10','Grigore Moisil 2009, clasa a 10a','2009-03-31 18:59:30','2009-03-31 19:34:10','h1. == roundparam(round_id=\"moisil2009-10\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':grigore-moisil-2009 \r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n*(active) \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n* \'Rezultate\':grigore-moisil-2009/clasament/\r\n\r\n== roundregister(round_id=\"moisil2009-10\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2009-10\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2009-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/moisil2009-10/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"moisil2009-10\" score=\"1\")==',2092,'protected',NULL,NULL),('doi-la-suta','Sprijină Asociaţia infoarena! Direcţionează 2%','2008-01-28 21:09:12','2009-02-03 13:23:38','h1. Sprijină Asociaţia infoarena!\r\n\r\n*_Direcţionează către noi 2% din impozitul pe venit datorat la stat._*\r\n\r\nbq. Sistemul „2%” permite contribuabililor persoane fizice să direcţioneze 2% din impozitul lor pe venit către o organizaţie neguvernamentală. Este un sistem prin care cetăţenii au posibilitatea să decidă în mod direct ce se întamplă cu impozitele lor. [...] Direcţionarea nu costă nimic. \'(Sursa)\':http://www.doilasuta.ro\r\n\r\n*Nu te costă nimic!* Impozitul pe venit rămâne acelaşi. \r\n\r\nÎn anul fiscal 2008 procedura \'a funcţionat\':/blog/doi-la-suta-2008-raport.\r\n\r\nh2. La ce folosim contribuţiile\r\n\r\ninfoarena ajută elevi şi studenţi să înveţe informatică şi programare. De mai bine de 5 ani de zile organizăm concursuri de informatică, scriem articole, dezvoltăm software, facem schimb de experienţă şi idei. Ne-am organizat pe acest site deoarece împreună învăţăm mai bine.\r\n\r\nPoţi să citeşti mai mult despre ce facem noi \'aici\':prezentare şi \'aici\':despre-infoarena. Am apărut şi în \'Adevărul\':http://www.adevarulonline.ro/articole/fostii-olimpici-ii-antreneaza-pe-concurentii-de-la-olimpiade/305061 (pe \'prima pagină\':doi-la-suta?infoarena-adevarul-prima-pagina.pdf).\r\n\r\nVom folosi contribuţiile venite pe această cale să:\r\n\r\n* oferim premii: membrii comunităţii sunt mai motivaţi să se pregătească şi să participe la un concurs online de informatică atunci când se dau premii\r\n* organizăm finale de concursuri: în fiecare an organizăm \'un concurs\':algoritmiada-2009 cu finală; finala are menirea să ne strangă la un loc cu ce mai buni dintre elevii şi studenţii României pentru câteva zile şi să formăm noi prietenii\r\n* motivăm comunitatea să se \'implice\':implica-te\r\n* finanţăm \'proiecte infoarena\':propuneri\r\n\r\nVezi \'obiectivele infoarena\':okr pentru trimestrul curent şi \'rezoluţiile şi notiţele fiecărei şedinţe de consiliu\':planificare.\r\n\r\nh2. Ce trebuie să faci\r\n\r\nProcedura este foarte simplă. Ai grijă să te încadrezi în *termenul limită: 15 mai 2009*.\r\n\r\n# În funcţie de sursa ta de venit, descarcă, printează şi completează una din declaraţiile următoare:\r\n** Dacă ai venituri numai din salarii: \'declaratia 230 precompletata cu datele infoarena\':doi-la-suta?decl_230_2008-infoarena.pdf\r\n** Dacă ai venituri (şi) din alte surse (cedarea folosinţei bunurilor, drepturi de autor, etc): \'declaratia 200 precompletata cu datele infoarena\':doi-la-suta?decl_200_2008-infoarena.pdf\r\n# Foloseşte următoarele date de identificare pentru Asociaţia infoarena:\r\n** *CUI*: 21752294\r\n** *IBAN*: RO15&nbsp;RZBR&nbsp;0000&nbsp;0600&nbsp;0919&nbsp;4268, *Deschis la*: Raiffeisen, Ag. Unirea, Bucureşti\r\n** *Adresa sediu social*: Str. Dragoş Vodă Nr. 49, Bl. P9, Ap. 11, Bârlad, Jud. Vaslui\r\n# Depune declaraţiile completate la administraţia financiară de care aparţine domiciliul tău. Alternativ poţi să trimiţi declaraţia prin scrisoare recomandată către administraţia financiară.\r\n\r\nAlte informaţii utile:\r\n\r\n* Completează în două exemplare declaraţia corespunzătoare. Unul din exemplare trebuie depus la administraţia financiară iar celălalt rămâne la tine.\r\n\r\n* Nu e nici o problemă dacă nu ştii exact suma care trebuie virată. Lasă rubrica „Suma” necompletată şi organul fiscal va calcula şi va vira suma admisă, conform legii\r\n\r\n* \'Adrese şi numere de telefon pentru administraţiile financiare din Bucureşti\':http://www.miculparis.ro/utile/administratie/administratii_financiare_bucuresti.html\r\n\r\n* \'declaratia 230 originala\':http://doilasuta.ro/pagini/resurse/decl_230_2008.pdf si \'declaratia 200 originala\':http://doilasuta.ro/pagini/resurse/decl_200_2008.pdf\r\n\r\nh2. Intrebări, sugestii\r\n\r\nDacă ai nelămuriri putem discuta pe forum:\r\n\r\n==SmfTopic(topic_id=\"2725\")==\r\n',75,'protected',NULL,NULL),('introducere-in-asamblare','Introducere in asamblare','2005-08-15 00:00:00','2009-01-22 17:19:53','h1. Introducere in asamblare\r\n\r\n(Categoria _Limbaje de programare_, Autor _Cristian Botau_)\r\n\r\n(toc){width: 35em}*{text-align:center} *Conţinut:*\r\n* \'Limbajul de asamblare: avantaje si dezavantaje in folosirea lui\':introducere-in-asamblare#limbajul-de-asamblare\r\n** \'Avantaje ale limbajului de asamblare\':introducere-in-asamblare#avantaje-limbaj-asamblare\r\n** \'Dezavantaje ale limbajului de asamblare\':introducere-in-asamblare#dezavantaje-limbaj-asamblare\r\n* \'Notiuni de baza ale limbajului de asamblare\':introducere-in-asamblare#notiuni-de-baza\r\n** \'Registrii\':introducere-in-asamblare#registrii\r\n*** \'Registrii de uz general\':introducere-in-asamblare#registrii-de-uz-general\r\n*** \'Registrii de segment si index\':introducere-in-asamblare#registrii-de-segment-si-index\r\n*** \'Registrii speciali\':introducere-in-asamblare#registrii-speciali\r\n*** \'Flagurile microprocesorului\':introducere-in-asamblare#flagurile-microprocesorului\r\n** \'Instructiunile de baza ale microprocesorului 8086\':introducere-in-asamblare#instructiuni-de-baza-8086\r\n*** \'Instructiunea MOV\':introducere-in-asamblare#instructiune-MOV\r\n*** \'Instructiuni aritmetice. Instructiunile ADD, SUB, INC, DEC\':introducere-in-asamblare#instructiuni-aritmetice\r\n*** \'Instructiuni pe biti. Instructiunile AND, TEST, OR, XOR, NOT\':introducere-in-asamblare#instructiuni-pe-biti\r\n*** \'Instructiunile PUSH/POP\':introducere-in-asamblare#instructiuni-PUSH-POP\r\n*** \'Instructiunea CMP\':introducere-in-asamblare#instructiune-CMP\r\n*** \'Jump-urile neconditionate (JMP) si jump-urile conditionate (JE, JNE, JB, JBE, JA, JAE, JZ, JNZ)\':introducere-in-asamblare#jumpuri\r\n*** \'Instructiunea LOOP\':introducere-in-asamblare#instructiune-loop\r\n*** \'Instructiunea INT\':introducere-in-asamblare#instructiune-INT\r\n* \'Transcrierea unor instructiuni C/PASCAL in asamblare\':introducere-in-asamblare#instructiuni-CPascal-in-asamblare\r\n** \'IF cond THEN instr\':introducere-in-asamblare#if-then\r\n** \'IF cond THEN instr1 ELSE instr2\':introducere-in-asamblare#if-then-else\r\n** \'DO { inst } WHILE\':introducere-in-asamblare#do-while\r\n* \'Program demonstrativ\':introducere-in-asamblare#program-demonstrativ\r\n* \'Linkuri\':introducere-in-asamblare#linkuri\r\n* \'Doua cuvinte conclusive...\':introducere-in-asamblare#concluzie\r\n\r\nAcest articol prezinta un limbaj mai putin folosit : limbajul de asamblare. Este folosit de cele mai multe ori pentru marirea vitezei de rulare a programelor. In prima sectiune sunt prezentate cateva avantaje / dezavantaje in folosirea acestui limbaj, iar ulterior sunt definite notiunile elementare ce trebuie stiute inainte de a trece la tratarea limbajului propriu-zis. De asemenea, sunt prezentate cateva intructiuni si transcrieri ale unor structuri din C/Pascal in limbaj de asamblare. In final sunt comparati timpii de executie intre varianta pascal si varianta assembler ale unei proceduri de {$Bubble Sort$}.\r\n\r\nh2(#limbajul-de-asamblare). Limbajul de asamblare : avantaje si dezavantaje in folosirea lui\r\n\r\nDesi este unul dintre cele mai vechi limbaje de programare, limbajul de asamblare este incorporat si in cele mai noi compilatoare cum ar fi Visual C++ si Delphi. Codul de asamblare este foarte apropiat de codul executabil al programelor, asamblorul avand rolul de a codifica instructiunile din limbaj de asamblare in cod masina.\r\n\r\nIn prezent, limbajul de asamblare este din ce in ce mai putin folosit in scrierea programelor, deoarece compilatoarele de ultima generatie au functiile cele mai folosite de programatori deja scrise si optimizate in limbaj de asamblare (gen memmove, memset / fillchar, etc.) incluse in unit-uri si biblioteci. Bineinteles, daca se doreste atingerea unor timpi de executie foarte mici, folosirea limbajului de asamblare este preferabila (cand avem algoritmul de complexitate optima).\r\n\r\nh3(#avantaje-limbaj-asamblare). Avantaje ale limbajului de asamblare\r\n\r\n* Viteza foarte mare de executie a programelor (unele programe scrise si optimizate in asamblare au viteza de executie pana la 5-10 de ori mai mare decat cele scrise in C sau Pascal);\r\n* Marimea codului executabil este foarte mica;\r\n* Ajuta utilizatorul sa inteleaga mai bine cum functioneaza microprocesorul si sa scrie programe eficiente si in High Level Languages.\r\n\r\nh3(#dezavantaje-limbaj-asamblare). Dezavantaje ale limbajului de asamblare\r\n\r\n* nu este portabil; un program scris pentru calculatoare IBM PC nu va rula pe un Apple Macintosh (difera unele instructiuni);\r\n* un program in asamblare este mai greu de scris si ia mai mult timp decat un program scris in Pascal sau C;\r\n* un program scris in asamblare este mai greu de depanat;\r\n\r\nMajoritatea compilatoarelor din prezent permit programatorului sa scrie anumite parti de cod sau subprograme in asamblare, astfel incat programatorul sa poata scrie in asamblare doar partea din program care se executa de cele mai multe ori, programul ruland astfel mult mai rapid. Sunt si compilatoare dedicate exclusiv limbajului de asamblare, cum ar fi TASM - Turbo Assembler (il gasiti in directorul BP/Bin), MASM - Microsoft Assembler, etc.\r\n\r\nPentru a scrie o secventa de limbaj de asamblare intr-un program $C$ se foloseste cuvantul rezervat $asm$ :\r\n\r\n== code(cpp) |asm { instructiuni in asamblare };\r\n==\r\n\r\niar in pascal :\r\n\r\n== code(pas) |asm\r\n    cod asamblare\r\nend.\r\n==\r\n\r\nh2(#notiuni-de-baza). Notiuni de baza ale limbajului de asamblare\r\n\r\nh3(#registrii). Registrii\r\n\r\nLimbajul de asamblare este foarte apropiat de codul executabil, deci pentru ca programatorul sa fie capabil sa scrie codul in asamblare trebuie sa cunoasca modul in care functioneaza microprocesorul si modul in care acesta executa instructiunile.\r\n\r\nToate operatiile aritmetice/logice/acces la memorie se fac prin intermediul registrilor. Registrii microprocesorului sunt asemanatori variabilelor (pot fi initializati cu anumite valori, se pot efectua operatii asupra lor, pot fi accesati (cititi/modificati)).\r\nRegistrii microprocesorului sunt clasificati in mai multe categorii :\r\n\r\n* registri de uz general : {$eax$}, {$ebx$}, {$ecx$}, {$edx$} si subregistrii lor;\r\n* registri segment : {$cs$} (code segment), {$ds$} (data segment), {$es$} (extra segment), {$ss$} (stack segment) - sunt folositi pentru adresarea memoriei in cazul modelului de memorie segmentat\r\n* registrii index : {$esi$}, $edi$ (source index, destination index);\r\n* registri speciali : {$ebp$}, {$esp$}, {$ip$};\r\n\r\nRegistrii de uz general sunt folositi in executia operatiilor aritmetice si logice. Registrii de segment si cei index sunt folositi in adresarea memoriei, iar cei speciali sunt folositi de microprocesor si S.O. pentru rularea programelor.\r\n\r\nh4(#registrii-de-uz-general). Registrii de uz general\r\n\r\nAcestia sunt :\r\n\r\n* $eax$ - numit si \"accumulator\" - acesta este cel mai folosit in executarea operatiilor aritmetice (adunare, scadere, inmultire, impartire);\r\n* $ebx$ - numit si \"base\" - acesta registru este folosit pentru adresarea indirecta a memoriei;\r\n* $ecx$ - numit si \"count\" - acest registru este folosit mai ales in cadrul \"buclelor\" (in instructiunile repetitive : for/ while do/ do while/ repeat until);\r\n* $edx$ - numit si \"data\" - retine anumite variabile, si este folosit impreuna cu $eax$ in executarea operatiei \"div\", impartire intreaga (avand rolul de a retine restul impartirii).\r\n\r\nDupa cum ati observat, fiecare registru general are o functie specifica, insa oricare din ei pot fi folositi si la operatii aritmetice/logice, adresare memorie sau ca si variabile.\r\n\r\nRegistrii precedati de prefixul \"{$e$}\" sunt pe $32$ de biti, deci pot fi tratati ca si variabile {$unsigned long$}/{$signed long$} ({$doubleword$}). Acestia pot fi folositi si ca registri pe $16$ biti ({$word$}) sau pe $8$ biti ({$byte$}) prin intermediul \"subregistrilor\" : {$ax$}, {$bx$}, {$cx$}, $dx$ (reprezinta word-ul nesemnificativ = cel din dreapta)., {$ah$}, {$bh$}, {$ch$}, $dh$ (byte-ul cel mai semnificativ al {$ax$}, {$bx$}, {$cx$}, {$dx$}), {$al$}, {$bl$}, {$cl$}, {$dl$}(registrii pe 8 biti).\r\n\r\nh4(#registrii-de-segment-si-index). Registrii de segment si index\r\n\r\nAcesti registri sunt folositi la adresarea memoriei.\r\nDe exemplu\r\nAvem variabila {$void *x;$}({$x : pointer$} in pascal);\r\npentru modelul de memorie segmentata, in adresarea memoriei adresate de $x$ se folosesc intructiunile (vezi \"Intructiunile de baza ale unui microprocesor 8086\") :\r\n\r\n== code(cpp) |// es:[di] va accesa adresa pointata de x;\r\nles di, x\r\n// se copiaza in ax primul word\r\n// de la adresa es:[di]\r\nmov ax, es:[di]\r\n// se copiaza in al cel de-al 3-lea byte\r\n// de la adresa es:[di]\r\nmov al, es:[di+2]\r\n==\r\n\r\nParantezele drepte se refera la zona de memorie adresata de registru.\r\nExemplu :\r\n\r\n\"{$[esi]$}\" se refera la valoarea aflata la adresa de memorie cu offset-ul esi, iar \"{$esi$}\" se refera la valoarea stocata in registrul esi;\r\n\r\ndaca $esi = 100$ atunci [{$esi$}] va reprezenta valoarea care se afla la adresa cu offset-ul {$100$}, iar esi va reprezenta valoarea {$100$}.\r\n\r\nVa sfatuiesc sa NU incercati sa modificati urmatorii registri : $cs$ (care contine segmentul la care se afla incarcat codul executabilului, $ss$ contine segmentul de memorie in care se afla stiva sistemului).\r\n\r\nh4(#registrii-speciali). Registrii speciali\r\n\r\nSunt folositi foarte rar in scrierea efectiva a programelor, deci nu veti accesa prea des acesti registri.De exemplu, $ip$ (instruction pointer) care retine adresa (de fapt offset-ul) la care se afla instructiunea care urmeaza sa fie executata.\r\n\r\nh4(#flagurile-microprocesorului). Flagurile microprocesorului\r\n\r\nFlag-urile microprocesorului sunt asemanatoare unor variabile boolene. Cu ajutorul lor putem afla rezultatul unei comparatii sau daca o operatie a produs \"overflow\", etc. Aceste flag-uri nu pot fi accesate direct ca si registrii, ci testarea daca un flag este activat se face prin intermediul \"jump\"-urilor conditionate.(vezi instructiunea {$cmp$}).\r\n\r\nExemplu :\r\nFie {$ax = 1$}. Decrementarea lui $ax$ cu $1$ va duce la activarea flagului numit Zero-Flag.(rezultatul operatiei a fost {$0$}).\r\nFie {$ax = 65535$} ({$0xFFFF$}). Incrementarea lui $ax$ cu $2$ va duce la setarea flagului numit Overflow-Flag (rezultatul operatiei nu \"incape\" in $16$ biti);\r\n\r\nh3(#instructiuni-de-baza-8086). Instructiunile de baza ale microprocesorului 8086\r\n\r\nSunt folosite urmatoarele prescurtari :\r\n\r\n* {$reg8$}/ {$reg16$}/ {$reg32$} - se refera la registri pe {$8$}/{$16$}/{$32$} biti;\r\n* {$imm8$}/ {$imm16$}/ {$imm32$} - se refera la valori imediate (constante);\r\n* {$mem8$}/ {$mem16$}/ {$mem32$} - zona memorie de memorie sau variabile pe {$8$}/{$16$}/{$32$} biti;\r\n\r\nh4(#instructiune-MOV). Instructiunea MOV\r\n\r\n_Sintaxa_:\r\n\r\n* $mov dest, source$ // echivalenta cu dest = source\r\n\r\n_Variante_:\r\n\r\n* $mov reg8/16/32, mem8/16/32$\r\n* $mov reg8/16/32, reg8/16/32$\r\n* $mov mem8/16/32, reg8/16/32$\r\n* $mov reg8/16/32, imm8/16/32$\r\n* $mov mem8/16/32, imm8/16/32$\r\n\r\n_Descriere_:\r\n\r\nInstructiunea copiaza o valoare dintr-o locatie in alta locatie. Aceasta locatie poate fi zona de memorie, variabila, registru. De retinut este ca nu exista variante ale instructiunii care copiaza direct dintr-o zona de memorie in alta.\r\n\r\n_Flaguri afectate_:\r\n\r\nInstructiunea mov nu modifica nici un flag.\r\n\r\n_Restrictii_:\r\n\r\nAmbii operanzi trebuie sa aiba aceeasi marime. De exemplu pentru ultima varianta a instructiunii mov trebuie specificata marimea zonei de memorie. Instructiunea \"mov [bx], 0\" nu este corecta deoarece compilatorul nu stie ce vrea sa faca instructiunea: sa copieze valoarea 0 in byte-ul, in word-ul sau in doubleword-ul de la adresa bx. Astfel variantele corecte sunt:\r\n\r\n== code(cpp) |mov byte ptr [bx], 0\r\nmov word ptr [bx], 0\r\nmov dword ptr [bx], 0\r\n==\r\n\r\n_Exemplu_:\r\n\r\n== code(cpp) |mov ax, 3 // ax = 3\r\nmov bx, ax // bx = ax\r\n==\r\n\r\nh4(#instructiuni-aritmetice). Instructiuni aritmetice. Instructiunile ADD, SUB, INC, DEC\r\n\r\n_Sintaxa_:\r\n\r\n* $add dest, source$ // echivalenta cu dest+=source\r\n* $sub dest, source$ // echivalenta cu dest-=source\r\n* $inc dest$ // echivalenta cu dest++\r\n* $dec dest$ // echivalenta cu dest--\r\n\r\n_Variante_:\r\n\r\n* $add(sub) reg8/16/32, mem8/16/32$\r\n* $add(sub) reg8/16/32, reg8/16/32$\r\n* $add(sub) mem8/16/32, reg8/16/32$\r\n* $add(sub) reg8/16/32, imm8/16/32$\r\n* $add(sub) mem8/16/32, imm8/16/32$\r\n\r\n_Descriere_:\r\n\r\nInstructiunea \"{$add$}\" este folosita pentru a aduna doua valori, \"{$sub$}\" pentru a scadea o valoare din alta, \"{$inc$}\" - incrementarea unei variabile, \"{$dec$}\" - decrementarea unei variabile (registru/memorie).\r\n\r\n_Flaguri afectate_:\r\n\r\n* $carry flag$ - pentru \"signed overflow\"\r\n* $overflow flag$ - pentru overflow\r\n* $sign flag$ - activat daca rezultatul este negativ\r\n* $zero flag$ - activat daca rezultatul operatiei a fost 0\r\n* $parity flag$ - este setat in functie de paritatea rezultatului\r\n\r\n_Restrictii_:\r\n\r\nDestinatia trebuie sa aiba aceeasi marime ca si sursa.\r\n\r\n_Exemplu_:\r\n\r\n== code(cpp) |mov ax, 3 // ax = 3\r\nadd bx, ax // bx = ax+3\r\n==\r\n\r\nh4(#instructiuni-pe-biti). Instructiuni pe biti. Instructiunile AND, TEST, OR, XOR, NOT\r\n\r\n_Sintaxa_:\r\n\r\n* $and dest, source$ // echivalenta cu dest&=source\r\n* $test dest, source$ // dest & source\r\n* $or dest, source$ // echivalenta cu dest|=source\r\n* $xor dest, source$ // echivalenta cu dest^=source\r\n* $not dest$ // ~dest\r\n\r\n_Variante_:\r\n\r\nPentru \"{$and$}\", \"{$or$}\", \"{$test$}\", \"{$xor$}\" sunt ca si cele de la \"{$add$}\". Pentru \"{$not$}\" avem doua variante :\r\n\r\n* $not reg8/16/32$\r\n* $not mem$\r\n\r\n_Descriere_:\r\n\r\nExecuta operatiile pe biti corespunzatoare. Instructiunea test (non-destructive and) este asemanatoare lui and, dar nu afecteaza rezultatul ci doar flagurile.\r\n\r\n_Flaguri afectate_:\r\n\r\nInstructiunea \"{$not$}\" nu afecteaza nici un flag.\r\nFlagurile afectate de celalalte instructiuni sunt :\r\n\r\n* {$carry$}, $overflow$ - le dezactiveaza\r\n* $sign flag$ - este copiat bitul cel mai semnificativ din rezultat (semnul rezultatului, de fapt)\r\n* $zero flag$ - activat daca rezultatul operatiei a fost 0\r\n* $parity flag$ - este setat in functie de paritatea rezultatului\r\n\r\n_Restrictii_:\r\n\r\nDestinatia trebuie sa aiba aceeasi marime ca si sursa.\r\nInstructinile $OR/XOR/INC/DEC$ modifica flag-urile microprocesorului: {$Carry$}(numai {$ADD/SUB$}), {$Overflow$}, {$Zero$}, {$Parity$}.\r\n\r\n_Exemplu_:\r\n\r\n== code(cpp) |mov ax, 5 // ax = 3\r\ntest ax, 1 // daca (ax & 1)\r\njz @skip // daca ax este nu este impar sari la @skip\r\n// executa instructiuni\r\n@skip\r\nand bx, FFFEh // bx = bx & 0xFFFE (se sterge bitul cel mai nesemnificativ)\r\n==\r\n\r\nh4(#instructiuni-PUSH-POP). Instructiunile PUSH/POP\r\n\r\n_Descriere_:\r\n\r\nAceste instructiuni sunt folosite pentru accesarea stivei sistemului. Instructiunea PUSH pune pe stiva sistemului o valoare, iar instructiunea POP extrage valoarea din varful stivei.\r\n\r\n_Sintaxa_:\r\n\r\n* $push val$\r\n* $pop val$\r\n\r\n_Variante_:\r\n\r\n* $push reg8/16/32$\r\n* $pop reg8/16/32$\r\n\r\n_Exemplu_:\r\n\r\n== code(cpp) |@lp:\r\npush cx // salvam valoarea cx\r\n... // prelucreaza datele, se poate modifica cx\r\npop cx // scoate de pe stiva valoarea cx\r\ndec cx\r\njnz @lp // daca (cx != 0) atunci sari inapoi la @lp\r\n==\r\n\r\nh4(#instructiune-CMP). Instructiunea CMP\r\n\r\n_Descriere_:\r\n\r\nCompara doua valori si seteaza flag-urile microprocesorului cu rezultatele compararii. De cele mai multe ori este folosita in combinatie cu jump-urile (vezi mai jos).\r\n\r\n_Sintaxa_:\r\n\r\n* $cmp val1, val2$\r\n\r\n_Variante_:\r\n\r\n* $cmp reg8/16/32, reg8/16/32$\r\n* $cmp reg8/16/32, imm8/16/32$\r\n* $cmp mem8/16/32, reg8/16/32$\r\n* $cmp mem8/16/32, imm8/16/32$\r\n\r\nh4(#jumpuri). Jump-urile neconditionate (JMP) si jump-urile conditionate (JE, JNE, JB, JBE, JA, JAE, JZ, JNZ)\r\n\r\nAceste instructiuni sunt folosite pentru generarea instructiunilor If /while do /do while /repeat /for.Sunt asemanatoare instructiunii goto din C/Pascal.\r\n\r\n_Sintaxa_:\r\n\r\n$instructiune label$\r\n\r\n* $JE$ * \"sare\" cu executia programului la label daca flag-ul equality este setat;\r\n* $JNE$ * \"sare\" cu executia programului la label daca flag-ul equality nu este setat;\r\n* $JB$ * \"sare\" cu executia programului la label daca flag-ul below este setat;\r\n* $JBE$ * \"sare\" cu executia programului la label daca flag-ul below sau flagul equality este setat;\r\n* $JA$ * \"sare\" cu executia programului la label daca flag-ul below nu este setat;\r\n* $JAE$ * \"sare\" cu executia programului la label daca flag-ul equality este setat sau flag-ul below nu este setat;\r\n* $JZ$ * \"sare\" cu executia programului la label daca flag-ul zero este setat;\r\n* $JNZ$ * \"sare\" cu executia programului la label daca flag-ul zero nu este setat;\r\n* $JMP$ * \"sare\" cu executia programului la label;\r\n\r\n_Exemplu_:\r\n\r\n== code(cpp) |mov ax, 1\r\n@loop :\r\n    instr1\r\n    instr2\r\n    *\r\n    inc ax\r\n    // compara ax cu valoarea 10 si seteaza flagurile\r\n    cmp ax, 10\r\n    // daca ax != 10 sari inapoi la @loop\r\n\r\njne @loop\r\n\r\n== code(cpp) |instr1\r\njmp @label1\r\n    instr2\r\n    instr3\r\n@label1 :\r\n==\r\n\r\nIn ultimul exemplu instr2 si instr3 nu vor fi executate deoarece inaintea lor se afla instructiunea jump care face ca programul sa sara cu executia la instructiunea imediat urmatoare etichetei \"label1\".\r\n\r\nh4(#instructiune-loop). Instructiunea LOOP\r\n\r\nInstructiunea \"loop\" este folosita de obicei in transcrierea for-urilor si a buclelor.\r\n\r\n_Sintaxa_:\r\n\r\n* $loop label$\r\n\r\n_Descriere_:\r\n\r\nEchivalenta cu :\r\n\r\n== code(cpp) |dec ecx (sau dec cx)\r\njz label\r\n==\r\n\r\nh4(#instructiune-INT). Instructiunea INT\r\n\r\n_Descriere_:\r\n\r\nInstructiunea INT apealeaza o intrerupere.\r\n\r\n_Sintaxa_:\r\n\r\n* $INT nr_intrerupere$ (un numar cuprins intre 0 si 255);\r\n\r\nIntreruperile opresc programul din rulare, executa un anumit cod si apoi permit continuarea rularii programului. Cu ajutorul apelului intreruperilor aplicatia poate sa comunice cu sistemul de operare, si cu unele componente hardware ale calculatorului (mouse-ul, tastatura, imprimanta, etc). Fiecare intrerupere are asociat un numar.\r\n\r\n_Exemple_:\r\n\r\n* $0x9$ : intreruperea pentru tastatura;\r\n* $0x10$ : intreruperea care ofera serviciile BIOS pentru accesul la placa video;\r\n* $0x21$ : intreruperea sistemului de operare DOS;\r\n* $0x33$ : intreruperea pentru mouse;\r\n\r\nIn DOS pentru initializarea mouse-ului se va apela functia numarul $0$ a intreruperii $0x33$ :\r\n\r\n== code(cpp) |asm\r\n{\r\n    mov ax, 0\r\n    // seteaza registrul ax cu valoarea 0 pentru ca\r\n    // driverul ce gestioneaza intreruperea 0x33\r\n    //sa stie ca trebuie sa initializeze mouse-ul\r\n    int 0x33\r\n}\r\n==\r\n\r\nPentru afisarea mouse-ului :\r\n\r\n== code(cpp) |asm\r\n{\r\n    mov ax, 1\r\n    int 0x33\r\n}\r\n==\r\n\r\nPentru ascunderea cursorului de la mouse :\r\n\r\n== code(cpp) |asm\r\n{\r\n    mov ax, 2\r\n    int 0x33;\r\n}\r\n==\r\n\r\nh2(#instructiuni-CPascal-in-asamblare). Transcrierea unor instructiuni C/PASCAL in asamblare\r\n\r\nh3(#if-then). IF cond THEN instr\r\n\r\nExemplu : \r\n\r\n== code(cpp) |if (a==5) b=a; // a, b : integer\r\n==\r\n\r\n== code(cpp) |mov ax, a\r\ncmp ax, 5\r\n// ne intrebam daca !cond\r\njnz @skip_if\r\nmov b, ax\r\n@skip_if :\r\n==\r\n\r\nh3(#if-then-else). IF cond THEN instr1 ELSE instr2\r\n\r\nExemplu: \r\n\r\n== code(cpp) |if (a==b) a-=b; else b-=a;\r\n==\r\n\r\nTranscrierea in asamblare :\r\n\r\n== code(cpp) |mov ax, a\r\nmov bx, b\r\n// compara ax cu bx si seteaza flag-urile\r\ncmp ax, bx\r\nje @if_then\r\n// if (ax == bx) sari la @if_then\r\nsub b, ax\r\njmp @end_if :\r\n@if_then :\r\nsub a, bx\r\n@end_if :\r\n==\r\n\r\n\r\nh3(#do-while). DO { inst } WHILE\r\n\r\nExemplu :\r\n\r\n== code(cpp) |int i, a, n;\r\ni = 0;\r\na = 0;\r\ndo\r\n{\r\n    i++;\r\n    a+=i;\r\n} while (i<=n);\r\n==\r\n\r\nCodul in asamblare :\r\n\r\n== code(cpp) |// cx = 0, instructiunea xor cx, cx este\r\n// mai rapida decat mov cx, 0\r\nxor cx, cx\r\nxor ax, ax\r\nmov bx, n\r\n@while :\r\n    inc cx\r\n    add ax, cx\r\n    cmp cx, bx\r\n    jne @while\r\nmov a, ax\r\nmov I, cx\r\n==\r\n\r\nSau folosind instructiunea loop (pornim invers) :\r\n\r\n== code(cpp) |mov cx, n\r\n@while:\r\n    add ax, cx\r\nloop @while\r\n==\r\n\r\nIn codul de mai sus (prima varianta) puteti observa cateva mici optimizari : retinerea variabilelor in registri (accesul la registri este mult mai rapid decat la memorie), inlocuirea instructiunii {$mov reg, 0$ cu {$xor reg, reg$}. Varianta \"xor\" este mai rapida (desi $mov$ si $xor$ \"teoretic\" au tot atatea ceasuri de procesor) deoarece instructiunea $mov reg, 0$ transcrisa in cod masina este mai \"lunga\" (are cu $2-4$ bytes mai mult decat {$xor reg, reg$}). Aceeasi regula se aplica si in cazul \"{$or reg, reg$}\" in testarea daca valoarea unui registru este egala cu {$0$}, intrucat instructiunea \"{$or$}\" modifica flagurile procesorului ({$ZeroFlag$}). O alta optimizare este folosirea registrului $ax$ pentru calcule (in majoritatea cazurilor instructiunile care folosesc registrul $(e)ax$ sunt mai rapide).\r\n\r\nh2(#program-demonstrativ). Program demonstrativ\r\n\r\nExemplu de functie in realizata in C/Asamblare (compilator folosit BC++ 3.1):\r\n\r\n== code(cpp) |// BSort.CPP\r\n#include <stdio.h>\r\n#include <conio.h>\r\n\r\nint a[20], n;\r\n\r\nvoid bsort()\r\n{\r\n	asm {\r\n		mov di,seg a\r\n		mov es,di\r\n		mov di,offset a\r\n		// es:[di] inceputul vectorului\r\n		// es - adresa segment\r\n		// di - adresa offset\r\n	};\r\n\r\ndo_while_not_ok :\r\n	asm {\r\n		// ok = 1;\r\n		mov dx, 1\r\n		// cx = n;\r\n		mov cx, n\r\n		// cx = n-1\r\n\r\n		dec cx\r\n		// ax = a[0]\r\n		mov ax, es:[di]\r\n		// punem di pe stiva\r\n		push di\r\n	}\r\ninner_for :\r\n	asm {\r\n		// bx = a[i-1]\r\n		mov bx, ax\r\n		// ne mutam pe noua pozitie in vector\r\n		add di, 2\r\n		// ax = a[i]\r\n		mov ax, es:[di]\r\n		// comparam ax cu bx (a[i-1] cu a[i])\r\n		cmp bx, ax\r\n		// if (a[i-1] <= a[i]) don\'t swap\r\n		jbe if_not\r\n		// interschimbam a[i-1] cu a[i]\r\n		xchg bx, ax\r\n		// le scriem in memorie\r\n		mov es:[di], ax\r\n		mov es:[di-2], bx\r\n		// ok = 0\r\n		xor dx, dx\r\n	}\r\nif_not :\r\n	asm {\r\n		// cx--;\r\n		dec cx\r\n		jnz inner_for\r\n		// daca cx != 0 atunci continuam for-ul\r\n		pop di\r\n		// compara dx cu 0\r\n		// (mai rapid decat cmp dx, 0)\r\n		or dx, dx\r\n		// if (ok) executam inca odata while-ul\r\n		jz do_while_not_ok\r\n	}\r\n}\r\n\r\nvoid citire()\r\n{\r\n	printf(\"Numarul de elemente : \");\r\n	scanf(\"%d\", &n);\r\n	for (int i=0; i<n; i++)\r\n	{\r\n		printf(\"a[%d] = \", i);\r\n		scanf(\"%d\", &a[i]);\r\n	}\r\n}\r\n\r\nvoid afis()\r\n{\r\n	for (int i=0; i<n; i++)\r\n		printf(\"%d \", a[i]);\r\n}\r\n\r\nint main()\r\n{\r\n	citire();\r\n	bsort();\r\n	afis();\r\n	return 0;\r\n}\r\n==\r\n\r\nVarianta Pascal + Asm (compilata cu BP 7.0):\r\n\r\n== code(pas) |program b_sort;\r\n\r\nconst   max_N = 1000;\r\n        n_tests = 100;\r\n\r\nvar N : Integer;\r\n    a, b : array [1..max_N] of Integer;\r\n\r\nprocedure citire;\r\nvar f : Text;\r\n    i : Integer;\r\nbegin\r\n    Assign(f, \'bsort.in\'); Reset(f);\r\n    readln(f, N);\r\n    for i := 1 to N do\r\n        read(f, b[i]);\r\n    Close(f)\r\nend;\r\n\r\nprocedure flip;\r\nvar i : Integer;\r\nbegin\r\n    for i:=1 to N do\r\n        a[i] := b[i];\r\nend;\r\n\r\nvar p : pointer;\r\n\r\nprocedure bsort; assembler;\r\nasm\r\n{ les <=> es = seg(p), di = offset(p) }\r\n    les di, p\r\n    @do_while_not_ok :\r\n        mov dx, 1\r\n        mov cx, N\r\n        dec cx\r\n        mov ax, es:[di]\r\n        push di\r\n        @inner_for :\r\n            mov bx, ax\r\n            add di, 2\r\n            mov ax, es:[di]\r\n            cmp bx, ax\r\n            jbe @if_not\r\n            xchg bx, ax\r\n            mov es:[di], ax\r\n            mov es:[di-2], bx\r\n            xor dx, dx\r\n            @if_not :\r\n                dec cx\r\n                jnz @inner_for\r\n        pop di\r\n        or dx, dx\r\n    jz @do_while_not_ok\r\nend;\r\n\r\nprocedure bsort2;\r\nvar ok : Boolean;\r\n    i, aux : Integer;\r\nbegin\r\n    repeat\r\n        ok := true;\r\n        for i := 1 to n-1 do\r\n            if (a[i] > a[i+1]) then\r\n            begin\r\n                aux := a[i];\r\n                a[i] := a[i+1];\r\n                a[i+1] := aux;\r\n                ok := false;\r\n            end;\r\n    until ok;\r\nend;\r\n\r\nvar i : Integer;\r\n    starttick, endtick : LongInt;\r\n    time : Longint absolute $0000:$046C;\r\n\r\n{ timer pentru masurarea timpului }\r\nconst tickspersecond = 18.206;\r\n\r\nprocedure starttimer;\r\nbegin\r\n    starttick := time;\r\nend;\r\n\r\nfunction elapsedtime : real;\r\nbegin\r\n    endtick := time;\r\n    elapsedtime := (endtick - starttick)*\r\n        (1 / tickspersecond);\r\nend;\r\n\r\nbegin\r\n    citire;\r\n    p := @a;\r\n    starttimer;\r\n    for i:=1 to n_tests do\r\n    begin\r\n        flip;\r\n        bsort;\r\n    end;\r\n    writeln(n_tests, \' rulari ale bsort in asamblare\r\n        au rulat in : \', elapsedtime : 6:3, \' secunde\');\r\n    starttimer;\r\n    for i:=1 to n_tests do\r\n    begin\r\n        flip;\r\n        bsort2;\r\n    end;\r\n    writeln(n_tests, \' rulari ale bsort obisnuit\r\n            au rulat in : \',elapsedtime : 6:3, \' secunde\');\r\nend.\r\n==\r\n\r\nOutput program pascal (pe pc-ul meu: Duron $750$ Mhz):\r\n\r\n* $100$ rulari ale bsort in asamblare au rulat in : $1.263$ secunde\r\n* $100$ rulari ale bsort obisnuit au rulat in : $4.614$ secunde\r\n\r\nDe precizat este ca nu am optimizat programul aproape deloc (am transcris codul din pascal in asm). Cu optimizari \"hardcore\" se pot obtine timpi mult mai buni. Diferenta dintre varianta asm si varianta high level language este mai mica pe compilatoarele mai noi, cum ar fi GCC sau FreePascal deoarece acestea stiu genera un cod mai optimizat. Totusi, nici un compilator nu poate bate creierul uman.\r\n\r\nh2(#linkuri). Linkuri\r\n\r\n* \'_The Art of Assembly Language_\':http://www.scribd.com/doc/6498072/Art-of-Assembly. O carte detaliata si foarte buna atat pentru incepatori cat si pentru avansati.\r\n\r\n* \'_How to optimize for the Pentium processor_\':http://www.goof.com/pcg/doc/pentopt.txt. Un tutorial bun pentru optimizarea programelor in asamblare pentru procesoarele din familia Pentium. Tutorialul este pentru avansati.\r\n\r\n* \'_Assembly Tutorials_\':http://www.techtutorials.info/assembly.html. Mai multe tutoriale despre assembly language.\r\n\r\nh2(#concluzie). Doua cuvinte conclusive...\r\n\r\nAcest articol trateaza \"bazele\" programarii in asamblare, dupa cum ii zice numele este doar o introducere. Pentru a sti sa programezi in _asm_, trebuie invatate mult mai multe lucruri. Scopul articolului este de a starni interesul cititorilor si de a le oferi o imagine asupra acestui limbaj. Cei ce doresc sa invete mai multe despre _assembly language_ sunt invitati sa citeasca cartile / tutorialele din sectiunea \'linkuri\':introducere-in-asamblare#linkuri.',3146,'public',NULL,NULL),('djgpp-instalarea-de-la-a-la-z','DJGPP - instalarea de la A la Z','2006-03-12 00:00:00','2008-12-13 18:52:20','h1. DJGPP - instalarea de la A la Z\r\n\r\n(Categoria _Diverse_, Autor _Tudor Aursulesei_)\r\n\r\nProbabil ca ai auzit de puternicul compilator $Gnu C$. Este acela folosit pe la mai toate competitiile mai mari de nationala (inclusiv). Avantaje:\r\n\r\n* lucreaza pe 32 de biti; asta inseamna ca programele compilate cu el vor merge mult mai repede!\r\n* stiva mai mare &#8658; erorile gen $stack overflow$ vor apare mult mai rar.\r\n* memorie mai mare &#8658; @long x[10000000]@ chiar exista\r\n\r\nAcest ghid este valabil pentru $Windows XP$.\r\nInainte sa incepem, trebuie sa raspundem la cateva intrebari:\r\n\r\nh2. Ce este DJGPP?\r\n\r\nO colectie de programe de $UNIX$ portate pentru $DOS$. Vizitati \"http://delorie.com/djgpp\":http://delorie.com/djgpp pentru detalii. Cel mai important, dupa ce veti instala corect $DJGPP$, veti putea scrie din linia de comanda in $DOS$ comenzi gen $gcc test.c *o test.exe$.\r\n\r\nh2. Ce este RHIDE?\r\n\r\nEste un $IDE (Integrated Development Environment)$ pentru $DJGPP$. Deosebit de puternic si seamana cu $Borland C 3.1$ la culoare ${:)}$. Se impaca de minune cu $GCC$! Important; ${NU}$ vom folosi versiunea de ${RHIDE}$ pe care ne-o ofera ${DJGPP}$, ci vom folosi una mai noua, dezvoltata de \"SET\":http://setedit.sourceforge.net. Are propriul lui editor, $Setedit$, dar a dezvoltat si $RHIDE$, eliminand o parte din buguri.\r\n\r\nVersiunea lui se gaseste la \"http://sourceforge.net/project/showfiles.php?group_id=32835\":http://sourceforge.net/project/showfiles.php?group_id=32835 , sectiunea extra! Recomand sa o luati acum: $pachetul RHIDE 1.5 + Ed 0.5.4 + gdb 6.1.1$ \r\n\r\nh2. Sa incepem\r\n\r\nAccesam link-ul \"http://www.delorie.com/djgpp/zip-picker.html\":http://www.delorie.com/djgpp/zip-picker.html si alegem optiunile (pe rand)\r\n\r\n* Build and run programs with DJGPP\r\n* Windows 2000/XP\r\n* Yes\r\n* C si C++\r\n\r\nLa $Integrated Development Environments and Tools$ aveti grija sa nu fie selectat $RHIDE$ (dupa cum am zis si mai sus, vom folosi o alta versiune).\r\n\r\nDe asemenea, alegem $No$ la Optiunea $Would you like GDB?$ (daca folositi GDB, atunci luati si acest pachet). Contiunam cu $\"Tell me which files I need\"$\r\n\r\nAr trebui sa obtinem urmatoarea lista:\r\n\r\n* unzip32.exe to unzip the zip files 95kb\r\n* v2/copying.dj Copyright info 3kb\r\n* v2/djdev203.zip Basic Development Kit 1.5mb\r\n* v2/faq230b.zip F.A.Q. 664kb\r\n* v2/readme.1st Installation instructions 22kb\r\n* v2gnu/bnu2161b.zip Basic assembler, linker 3.3mb\r\n* v2gnu/gcc401b.zip Basic GCC compiler 4.0mb\r\n* v2gnu/gdb611b.zip GNU debugger 1.5mb\r\n* v2gnu/gpp401b.zip C++ compiler 4.4mb\r\n* v2gnu/mak3791b.zip Make (processes makefiles)267b\r\n* v2gnu/txi48b.zip Info file viewer 779kb\r\n\r\nDownloadati-le!\r\n\r\nIncercati sa le puneti pe toate intr-un director gen $c:\\djgpp\\$ (de altfel, pe acesta il folosesc eu si vi-l recomand; articolul presupune in continuare ca aceasta este calea unde ati instalat programul). Deschideti o fereastra de $Explorer$ si faceti drag-n-drop la fiecare arhiva peste executabilul $unzip32.exe$. Ar trebui sa va apara directoare gen $bin$ si $include$. Sa nu uitam de versiunea de $RHIDE$ pe care am mentionat-o mai sus. Despachetati-o si pe aceasta in acelasi mod!\r\n\r\nVom contiuna cu setarea variabilei de mediu $DJGPP$. (foarte important)\r\nClick dreapta pe $My Computer &#8594; Properties &#8594; Advanced &#8594; Environment Variables$. In sectiunea System variables, editati variabila $PATH$ astfel incat aceasta sa arate si spre calea $C:\\DJGPP\\BIN$. Separati caile cu $;$ (ex: $C:\\DJGPP\\BIN;C:\\WINDOWS\\system32;...$. De asemenea, creeati o variabila noua numita $DJGPP$ care aibe valoarea $C:\\DJGPP\\DJGPP.ENV$ (daca ati instalat in alta parte, modificati caile dupa caz). Dupa ce ati modificat variabilele de sistem, calculatorul trebuie restartat.\r\n\r\nDaca nu doriti sa modificati variabilele de sistem, se recomanda crearea unui fisier batch care sa lanseze $RHIDE$. Va prezint un exemplu:\r\n\r\n== code(c) |@echo off\r\nset PATH=c:/djgpp/bin;%PATH%\r\nset DJGPP=c:/djgpp/djgpp.env\r\nchdir c:/djgpp/lucru\r\nc:/djgpp/bin/rhide.exe\r\n==\r\n\r\nRulati batch-ul. Ar trebui *sa nu dati* de o eroare care zice ceva de variabila $PATH$ pusa gresit sau de variabila $DJGPP$. Daca va apare, recititi partea de variabile de sistem din articol sau cititi fisierul $readme.1st$ (deschideti-l cu $Word$, nu cu $Notepad$). Daca nu aveti nici o eroare, ar trebui sa fiti intampinati de o fereastra in care se zice ceva de $Robert Hohne (RH din RHIDE) si Salvador Eduardo Tropea (omul care a imbunatatit RHIDE)$. Creeati un fisier nou in care sa bagati cateva linii de test.\r\n\r\n== code(c) |#include <stdio.h>\r\nint main()\r\n{\r\n    printf(\"%d %d %d\" , 1, 2, 3);\r\n    return 0;\r\n}\r\n==\r\n\r\n$Ctrl+F9$ ca sa compilati. $Ctrl+F2$ reset la program. $Shift + F4 $ruleaza pana la linia la care se afla cursorul. $Shift+F8$ e $Step Over$ fara sa se schimbe modul monitorului (fara flick la monitor). $Shift+F7$ e $Run Into$ fara sa se schimbe modul monitorului. $Shift+F2$ e $GREP$ (utilitar UNIX portat). $Alt + F5$ arata rezultatul rularii programului (in versiunea de $RHIDE$ de pe $DJGPP$, nu prea mergea aceasta functie). Recomand optiunile din $Options &#8594; Environment &#8594; Preferences$.\r\n\r\n* Screen Mode 80 x 50\r\n* Syntax highlighting\r\n\r\nIar tot din $Options &#8594; Environment &#8594; Editor &#8594; Editor Options$\r\n\r\n* Autoindent\r\n* Use Tabs\r\n* Intelligent C indent\r\n* Match pair on the fly\r\n\r\n...Si altele , pe care va las sa le descoperiti singuri.\r\n\r\nAvertizare. Desi aceasta versiune de $RHIDE$ este mai stabila decat cea de pe $DJGPP$, este sansa sa se prabuseasca la $Debugging$ ceva mai complex (crash ${:)}$). Nimic nu este perfect. De aceea este recomandat sa salvati din 15 in 15 minute.\r\nPuteti incerca si alte versiuni de RHIDE de la http://rhide.sourceforge.net/snapshots/index.html Unele dau eroare intr-un loc, altele in alt loc. Puteti sa le incercati pe rand.\r\n\r\nAmintiti-va totusi sa salvati cat mai des si sa nu urmariti evolutia unor variabile prea mari gen @x[10000000]@ ${:)}$. De asemenea nu incercati sa afisati pe ecran si sa vedeti ce rezultat a iesit cu $Alt+F5$. S-ar putea sa nu mearga. Daca aveti probleme $MARI$ cu programul, stergeti fisierele\r\n\r\n* rh_opt.gpr\r\n* rh_opt.gdt\r\n\r\nAsta o sa il faca ca nou, in caz ca refuza sa porneasca sau e mai instabil decat era cand l-ati instalat.\r\n\r\nRecomand de asemenea sa explorati fiecare meniu si scurtatura a programului, deoarece eu v-am prezentat sumar aproximativ $30%$ din functii si $30%$ din optiunile lui optime de functionare! Insist sa verificati sistematic si metodic optiunile; Nu o sa regretati! De asemenea, poate lucra cu $FPC (Free Pascal Compiler)$ , insa va recomand $IDE$-ul din $Free Pascal$. Este o opera de arta pentru pascalisti!\r\n',2044,'public',NULL,NULL),('ghid-complet-pentru-concursurile-de-informatica','Ghid complet pentru concursurile de informatica','2007-06-30 09:09:40','2008-12-13 18:51:40','h1. Ghid complet pentru concursurile de informatica\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"sims_gl\") ==\r\n\r\n(Categoria _Diverse_, Autor _Mircea Pasoi_)\r\n\r\n**Acest articol se adreseaza pasionatilor de informatica si celor care au de gand sa participe la concursurile si olimpiadele de informatica. Observatiile din cadrul acestui articol sunt, in mare parte, rezultatul experientei autorului.**\r\n\r\nh2. 1. Ce sunt concursurile?\r\n\r\nConcursurile de informatica, ca la orice alta disciplina, vor sa fie o metoda de clasificare a participantilor in functie de abilitatile de programare si de cunostintele de algoritmica. In plus, exista unele concursuri in care cei mai buni concurenti sunt rasplatiti. Probabil cel mai important aspect, concursul include aparitia unui factor suplimentar care rastoarna multe din obisnuintele programarii \"la domiciliu\" sau \"la locul de munca\" (de obicei programatorii care lucreaza in firme au perioade mult mai lungi de timp pentru a-si duce la final sarcina): **timpul**. Autorul a avut la dispozitie mai mult de sapte ani ca sa descopere pe propria piele importanta foarte mare a acestui factor; si, mai mult decat durata de timp in sine a concursului, care este aceeasi pentru toti concurentii, conteaza capacitatea fiecaruia de a gestiona bine acest timp. Daca in fata calculatorului de acasa, cu o sticla de suc alaturi si cu muzica mergand, este intr-adevar un lucru laudabil sa justificam matematic fiecare pas al algoritmului, sa nu ne lasam inselati de intuitie si sa scriem programul fara sa ne grabim, alocandu-ne o mare parte din timp numai pentru depanarea lui, in schimb, in timp de concurs lucrurile  stau tocmai invers: de demonstratii riguroase din punct de vedere matematic rar are timp cineva, intuitia fiind la mare pret si de nenumarate ori fiind criteriul care aduce victoria; iar timpul la un concurs serios este suficient doar pentru implementarea tuturor programelor, pentru depanare alocandu-se de obicei o perioada destul de mica.\r\n\r\nIn multe cazuri, cele doua etape principale ale programarii - conceperea si implementare algoritmului - incep sa se bata cap in cap. Exista situatii in care avem la dispozitie un algoritm foarte eficient, dar implementarea acestuia este extrem de dificila, alteori algoritmul ales nu va face fata volumului maxim de date de intrare, iar alteori ne dam seama ca am putea foarte usor sa scriem un program, dar nu suntem in stare sa demonstram ca el merge sigur pe orice set de date de intrare. Foarte des se renunta la implementarea algoritmilor de complexitate optima, care in multe cazuri constituie adevarate focare de \"bug\"-uri, preferandu-se un algoritm mai lent dar care sa se poate implementa mai rapid si fara dureri de cap. Multi concurenti pierd primii ani de concursuri descoperind aceste lucruri. Desigur, aceste lucruri variaza foarte mult in functie de viteza fiecaruia de a implementa in limbajul preferat (atentie, viteza mare de tastare a unui text normal nu garanteaza neaparat o viteza mare de tastare a unui program!), cat si de abilitatea de a te concentra la toate detaliile care apar in implementare (acest lucru depinde foarte mult de cat de antrenata este mintea fiecaruia). De fapt, concurentii care ies pe primele locuri de obicei, sunt cei care au reusit sa formeze un echilibru intre cele doua etape ale programarii: pot sa conceapa algoritmi eficienti, care sa se incadreze in limitele de timp si memorie, cat si sa implementeze acesti algoritmi intr-un timp acceptabil, depanand foarte putin.\r\n\r\nO intrebare pe care cineva, care citeste aceste randuri, si-o poate pune este urmatoarea: _De ce sa particip la astfel de concursuri?_ Principalele avantaje sunt formarea unei gandiri algoritmice, intelegerea metodelor de rezolvare pentru anumite probleme (care pot aparea si in cadrul dezvoltarii de aplicatii), dezvoltarea capacitatii de a reactiona rapid intr-un timp scurt. In timp, experienta acumulata in cadrul pregatirii si a concursurilor va conduce la eficienta mai mare in cadrul proiectelor de dezvoltare de software si, de ce nu, la obtinerea unor salarii mai mari la angajare. Exista multe companii care iau in considerare participarile la concursuri la interviurile pentru angajare, cat si multe facultati din strainatate care le considera un criteriu pentru primirea unei burse (asta nu inseamna ca o astfel de participare garanteaza neaparat o bursa!). Un alt avantaj ce nu este de neglijat este reprezentat de premiile puse in joc, atat cele materiale (calculatoare, diferite componente hardware, excursii in strainatate, carti, etc.), cat si intrarea fara examen la facultate, in cazut obtinerii unor rezultate bune la olimpiadele nationale sau internationale.\r\n\r\nh2. 2. Care sunt concursurile?\r\n\r\nO alta intrebare la care doresc sa afle raspunsul cei care vor sa participe la concursurile de informatica este: _Care sunt cele mai importante concursuri de programare?_ Se pot clasifica doua mari tipuri de concursuri: cele pentru gimnaziu si liceeni si cele pentru studenti.\r\n\r\nh3. Concursuri pentru liceu\r\n\r\n* **Olimpiada Locala de Informatica** - Se desfasoara in fiecare judet de obicei la inceputul anului (lunile ianuarie-februarie) si, in general, nivelul de dificultate este foarte redus (exceptie facand poate Bucuresti si alte cateva judete), subiectele fiind propuse de profesorii din judetul respectiv.\r\n* **Olimpiada Judeteana de Informatica** - Incepand cu anul 2003 subiectele pentru olimpiada judeteana au fost aceleasi in toata tara; de obicei se desfasoara cu o luna dupa olimpiada locala si cu cel putin o luna inainte de olimpiada nationala; subiectele sunt de un nivel mediu in general.\r\n* \"**Olimpiada Nationala de Informatica**\":http://olimpiada.info - Se organizeaza o data pe an, de obicei in prima vacanta din semestrul II al anului scolar; probele pentru liceu se desfasoara timp de 2 zile, in fiecare zi concurentii avand de rezolvat 3 probleme in 4 ore, iar probele pentru gimnaziu dureaza doar o zi, cate 2 probleme in 3 ore. De asemenea, prima jumatate din clasamentul pentru fiecare clasa de liceu participa la barajele pentru selectia lotului largit de informatica - aici, toti concurentii, indiferent de varsta, au de rezolvat aceleasi probleme. Primii ~20 selectati in urma acestei probe (care se desfasoara tot timp de 2 zile) vor forma lotul national largit; acestia vor participa la mai multe pregatiri, in cadrul carora sunt incluse baraje pentru selectarea echipelor de cate 4 elevi care vor reprezenta Romania la BOI, CEOI si IOI.\r\n* **Balcaniada de Informatica** (BOI) - Prima editie a avut loc la Constanta in anul 1993. Standardele acestui concurs nu erau foarte ridicate, iar concurentii romani se claseaza foarte des pe primele locuri. Cel mai concludent exemplu in acest sens este faptul ca la editia din anul 2001 toate cele patru medalii de aur au fost obtinute de reprezentantii nostri, iar in 2005 ambele medalii de aur acordate au revenit iarasi romanilor. Exista si ani cand nivelul de dificultate al problemelor este mai ridicat, spre exemplu in 2003(Romania) si 2004(Bulgaria).\r\n* **Olimpiada de Informatica a Europei Centrale** (CEOI) - Prima editie a avut loc la Cluj-Napoca in anul 1994. Editia din 2000 a acestui concurs a avut loc tot la Cluj-Napoca si foarte probabil editia din 2009 va fi tot in Romania. Standardele acestui concurs sunt mai ridicate decat cele de la BOI, deoarece elevii din tarile participante sunt intotdeauna foarte bine pregatiti.\r\n* **Olimpiada Internationala de Informatica** (IOI) - Acest concurs reuneste anual elevi din ~80 tari ale lumii. Fiecare tara este reprezentata de cel mult patru concurenti, iar numarul tarilor participante creste in fiecare an. Organizarea concursului este asemanatoare cu cea a celorlalte concursuri internationale mentionate. Concursul este individual si se desfasoara sub forma a doua probe. La fiecare proba concurentii au la dispozitie 5 ore pentru a rezolva 3 probleme cu un grad ridicat de dificultate. Dupa fiecare proba, programele concurentilor sunt evaluate automat, cu ajutorul unor programe de evaluare. Dupa cele doua zile de concurs se stabileste clasamentul final si se acorda medaliile. Rezultatele sunt secrete pana in momentul decernarii premiilor. La aproape toate editiile acestui concurs, echipa Romaniei a avut rezultate excelente. Astfel, incepand din anul 1993, cu doar doua exceptii, toti cei patru componenti ai echipei tarii noastre au obtinut medalii; conform punctajelor individuale, s-au obtinut doua locuri I (1993 si 1998) cu punctaj maxim si un loc II (2001), iar in clasamentul pe natiuni Romania este o prezenta constanta in primele 10 locuri.\r\n\r\nMai exista si alte concursuri internationale, cum ar fi **Olimpiada Tarilor Baltice**, la care Romania nu participa. Puteti gasi detalii mai multe despre aceste concursuri, cat si problemele propuse, folosind \"Google\":http://www.google.com. De asemenea problemele si solutiile din ultimii ani pentru concursurile importante pot fi gasite la sectiunea \"Downloads\":http://infoarena.ro/downloads a site-ului \"infoarena\":http://infoarena.ro, acesta fiind actualizat periodic.\r\n\r\nExista cateva concursuri regionale si nationale similare olimpiadelor (difera timpul de concurs, numarul de probe si dificultatea problemelor). Cateva dintre acestea sunt:\r\n\r\n* **Marele Premiu al Palatului Copiilor** - concurs organizat la Palatul National al Copiilor din Bucuresti; participa echipe ale Cluburilor Copiilor din mai multe judete ale tarii\r\n* **Concursul \"Grigore C. Moisil\"** - organizat anual la Lugoj; are o desfasurare similara\r\n* diferite concursuri interjudetene organizate in anumite regiuni ale tarii; mai multe astfel de concursuri poarta numele lui Grigore Moisil; alte concursuri sunt **Info-Oltenia**, **LInfo@SV**, **Urmasii lui Moisil**, etc.\r\n* Stelele Informaticii - concurs cu organizare asemanatoare cu Olimpiada Nationala de Informatica; participarea la acesta se face doar pe baza de invitatie.\r\n\r\nDe obicei aceste manifestari sunt mai ample; la aceste concursuri exista si alte sectiuni, cum ar fi cele dedicate dezvoltarii de aplicatii software sau de pagini web.\r\n\r\nExista de asemenea numeroase concursuri on-line, la care concurentii participa de acasa si isi trimit solutiile prin intermediul internetului. Desigur, nu se pot acoperi integral toate concursurile disponibile pe internet in acest articol. Este foarte importanta citirea regulamentului inainte de rezolvarea problemelor, deoarece pot exista restrictii care difera de la caz la caz. Datorita faptului ca majoritatea acestor concursuri sunt internationale, cunoasterea limbii engleze devine o necesitate pentru a putea participa. Pentru o pregatire cat mai eficienta, se recomanda participarea la acest tip de concursuri, atat pentru valoarea premiilor puse in joc, cat si ca modalitate de antrenament.\r\n\r\n* \"**preONI**\":http://infoarena.ro - Un concurs organizat in scopul pregatirii pentru Olimpiada Nationala de Informatica, organizat de catre studenti si elevi, actuali si fosti olimpici nationali si internationali. In ultimii 3 ani acest concurs a fost organizat de \"echipa infoarena\":http://infoarena.ro/echipa-infoarena, un grup de olimpici care administreaza primul (si singurul la momentul acesta) site din Romania cu evaluator disponibil 24 din 24. Acest concurs este intr-o continua expansiune, devenind din ce in ce mai complex de la an la an. Pe langa preONI, echipa infoarena organizeaza si alte concursuri; calitatea si valoarea concursurilor organizate precum si a materialelor educationale ce sunt puse la dispozitie este recunoscuta atat de elevi cat si de profesori de renume in informatica.\r\n* \"**.campion**\":http://campion.edu.ro - Problemele de pe acest site sunt propuse de membri ai Comisiei Olimpiadei Nationale; concursul este structurat in runde de pregatire care dureaza in mod normal 10 zile, si in runde de concurs, care dureaza doar 3 ore; tipul rundei alterneaza. Primii clasati se intalnesc la \"marea finala\", care se desfasoara sub forma unei probe de concurs, similara cu olimpiadele - castigatorii primesc premii.\r\n* \"**Bursele Agora**\":http://www.ginfo.ro - Printre cele mai vechi concursuri care inca se desfasoara, este organizat de redactia GInfo; formatul acestuia difera de la an la an, in ultimii doi ani fiind structurat in 50 de runde normale + o runda finala. La acest concurs se acorda burse pentru primii doi clasati in valoare de 50$ si 30$\r\n* \"**USACO**\":http://www.usaco.org - Un concurs prin intermediul caruia se selecteaza lotul national largit al SUA. Concursul consta in mai multe faze, desfasurate pe parcursul anului. Prin bunavointa organizatorilor, concursul a devenit international, iar ultimele editii au adus ca noutate traducerea problemelor in mai multe limbi, printre care, uneori, si limba romana.\r\n* **site-uri ACM** - exista site-uri care va pun la dispozitie si cate o arhiva foarte bogata de probleme si pot fi folosite cu succes in pregatirea pentru olimpiade, si care organizeaza concursuri, mai ales in perioada dinaintea concursurilor regionale ACM: astfel de site-uri sunt: http://acm.uva.es, http://acm.timus.ru, http://acm.sgu.ru, http://spoj.sphere.pl, http://acm.pku.edu.cn, http://acm.zju.edu.cn. Pentru o lista mai mare de site-uri de pregatire accesati sectiunea \"Links\":http://infoarena.ro/links, o lista permanent actualizata.\r\n* \"**Internet Problem Solving Contest**\":http://ipsc.ksp.sk - concurs organizat o data pe an. In cadrul acestui concurs se pun la dispozitie enunturile problemelor si fisierele de intrare si se asteapta fisierele de iesire corespunzatoare, fara a se cere si programele care rezolva problemele.\r\n\r\nAlte concursuri de programare, dar pe echipe, sunt **Bits\'n\'Bytes**, **BitWise** si **International Online Programming Contest**; la acestea pot participa si studenti. In anii precedenti au mai fost organizate si alte concursuri la noi in tara asemanatoare cu cele precizate mai sus precum **Lista lui Francu**, **Cupa Compaq**, **Cupa Fujitsu-Siemens**, **OlimpiadaOnline**, **Algoritmus**.\r\n\r\nh3. Concursuri pentru studenti\r\n\r\n* \"**ACM**\":http://www.acm.ro - un concurs organizat pentru studenti, de natura algoritmica. Diferentele majore fata de concursurile de liceu sunt reprezentate de faptul ca un program trebuie sa rezolve toate seturile de date de intrare prezentate pentru a se acorda puncte (nu se mai acorda punctaje partiale) si viteza cu care se rezolva problemele conteaza, iar evaluarea programelor este imediata. Concursul este pe echipe de cate 3 persoane, toate la un singur calculator. Concursul are loc pe regiuni initial (Centrul Europei, Sudul Europei, etc.) iar echipele calificate se intalnesc la marea finala.\r\n* \"**TopCoder**\":http://www.topcoder.com - un site care organizeaza concursuri saptamanal, cat si turnee. Formatul este diferit fata de orice concurs intalnit pana acum, si anume fiecare concurent are de rezolvat 3 probleme in 75 de minute: o problema usoara de 250 puncte, una medie de 500 puncte si una grea de 1000 puncte. Punctajul efectiv pentru o problema se da in functie de viteza cu care aceasta este rezolvata. De asemenea, exista si o etapa de \"challenge\", in care concurentii pot vedea sursele celorlalti si, in caz ca determina un bug intr-o sursa, pot sa ruleze sursa respectiva, iar daca da raspuns gresit concurentul primeste 50 de puncte, altfel este penalizat cu 25 de puncte. Aceste concursuri sunt diferite fata de cele din liceu in care accentul este pe realizarea unui algoritm eficient, deoarece aici se pune accentul mai mult pe o implementare rapida si corecta a unor probleme care folosesc variatii ale unor algoritmi destul de cunoscuti, dar fiind necesara tratarea diferitelor cazuri speciale ce pot aparea. Ca avantaje, premiile la turnee sunt foarte mari (20.000$ pentru primul clasat), iar intregul sistem de punctare este mult mai complex si mai eficient. Google organizeaza impreuna cu TopCoder concursul \"**Google Code Jam**\":http://www.google.com/codejam.\r\n\r\nh2. 3. Inainte de concurs\r\n\r\nDin fericire pentru unii si din nefericire pentru altii, majoritatea examenelor iti cer sa dovedesti nu ca esti bine pregatit, ci ca esti mai bine pregatit decat altii. Aceasta inseamna ca si la olimpiada de informatica se aplica legea concurentei. Valoarea absoluta a fiecaruia nu conteaza chiar in totalitate, ceea ce constituie sarea si piperul concursului. Intr-adevar, ce farmec ar avea sa mergi la un concurs la care sa se stie inca dinainte cine este cel mai bun? Este destul de amuzant sa observi cum fiecare spera sa prinda \"o zi buna\", iar adversarii sai \"o zi proasta\". Expresia \"de la extaz la agonie\" se potriveste foarte bine uneori cu ceea ce se poate intampla la concursurile de informatica.\r\n\r\nExperienta demonstreaza ca, oricat de mare ar fi bagajul de cunostinte acumulat de un elev, mai e nevoie de ceva pentru a-i asigura succesul la olimpiada de informatica. Aceasta deoarece in timp de concurs lucrurile stau cu totul altfel decat in fata calculatorului de acasa sau de la scoala. Reusita depinde, desigur, in cea mai mare masura de puterea fiecaruia de a pune in practica ceea ce a invatat acasa. Numai ca in acest proces intervin o serie de factori care tin de temperament, de experienta individuala, de numarul de ore dormite in noaptea dinaintea concursului (care in taberele nationale este ingrijorator de mic) si asa mai departe. Trebuie spus ca un concurs de informatica presupune mai mult decat un simplu act de prezenta la locul desfasurarii ostilitatilor. Este chiar trist de remarcat cum spiritul competitiv capata de multe ori tente malitioase.\r\n\r\nPrimul si cel mai de seama lucru pe care trebuie sa il stiti este ca e important si sa participi, dar e si mai important sa participi onorabil, sa dai dovada de fair-play, iar daca se poate, sa si castigi! :) Nu trebuie sa porniti la drum cu ingamfare; modestia e buna, dar nu trebuie in nici un caz sa duca la neincredere in sine! Fiecare trebuie sa stie clar de ce e in stare si, mai presus de toate, sa se gandeasca ca la urma urmei nu dificultatea concursului conteaza, caci concursul, greu sau usor, este acelasi pentru toti. Mult mai importanta este valoarea individuala si nu in ultimul rand pregatirea psihologica. Fiecare concurs reprezinta de asemenea un prilej de perfectionare: fiecare concurent trebuie sa-si analizeze comportamentul din timpul concursului, si sa determine ce aspecte pot fi imbunatatite pentru a obtine performante mai bune la urmatoarele concursuri. Pregatirea psihologica este de multe ori neglijata si reprezinta pentru unii exact acel lucru care il impiedica sa obtina performantele dorite. Exista destui concurenti care uita faptul ca aceste concursuri sunt doar niste concursuri, si ajung sa creada ca cel mai important lucru din viata lor este performanta lor la concursuri - fapt care poate fi foarte daunator in cazul unor esecuri. Asadar, recomand tuturor concurentilor sa adopte o atitudine relaxata si optimista la concursuri, sa realizeze ca acestea reprezinta doar o mica parte din viata, si nu in ultimul rand sa se distreze!\r\n\r\nO pregatire intensa inaintea unui concurs este foarte importanta deoarece imbunatateste viteza de implementare si reduce riscul aparitie erorilor, dar nu poate rezolva anumite lacune teoretice. Formula pentru succes poate fi descrisa ca \"90% munca, 10% talent\". Pentru a obtine performante mari trebuie neaparat o pregatire intensa adecvata. Exista mai multe aspecte ale pregatirii:\r\n\r\n* Pregatirea teoretica\r\n* Pregatirea psihica\r\n* Organizarea globala a pregatirii\r\n* Simularea unor probe de concurs\r\n* Discutiile cu alti elevi si profesori referitor la anumite probleme\r\n* Pregatirea de la locul desfasurarii probei\r\n\r\nDesigur, un alt aspect care trebuie luat in considerare este supra-antrenamentul! Da, acest concept exista si in concursurile de informatica. Se intampla de obicei ca dupa un antrenament prea greu, mintea sa nu reactioneze la fel de bine ca inainte, fiindca este obosita. De aceea, se si recomanda minim o saptamana de pauza si relaxare totala inainte de orice concurs major.\r\n\r\nh3. Pregatirea teoretica\r\n\r\nMajoritatea problemelor propuse spre rezolvare la concursuri depasesc cu mult nivelul manualelor de informatica. De exemplu, desi se propun o multime de probleme a caror rezolvare implica detinerea de cunostinte din domeniul teoriei grafurilor, nu toti algoritmii necesari sunt cuprinsi in programa de invatamant. Pentru a rezolva lacunele teoretice, este necesara studierea unor carti care sa acopere un spatiu teoretic cat mai vast.\r\n\r\nUnele carti isi propun sa initieze cititorul in tainele diverselor limbaje de programare, altele pun accentul mai cu seama pe tehnicile de programare si structurile de date folosite in rezolvarea problemelor. In general, cele din prima categorie contin exemple cu caracter didactic si exercitii cu un grad nu foarte ridicat de dificultate, iar celelalte demonstreaza matematic fiecare algoritm prezentat, insa neglijeaza partea de implementare, considerand scrierea codului drept un ultim pas lipsit de orice dificultate. Desigur, fiecare din aceste carti isi are rostul ei in formarea unui elev bine pregatit in domeniul informaticii. Totusi, trebuie considerata observatia ca scrierea unui program impune atat conceperea algoritmului si demonstrarea corectitudinii, cat si implementarea lui, ambele etape fiind complexe si nu lipsite de obstacole.\r\n\r\nCateva dintre cartile care ar trebui parcurse sunt in special cele scrise de fosti olimpici; prin intermediul acestora, autorii va impartasesc o parte din experienta acumulata. Cele mai folositoare carti (unele nu se mai gasesc) pentru pregatire sunt (unele nu sunt disponibile in Romania):\r\n\r\n* **Introducere in Algoritmi (Cormen, Leiserson, Rivest)** - \"Biblia\" algoritmilor; mai este numita si CLR. Traducerea in limba romana a primei editii a acestei carti este disponibila la editura Agora Computer Libris si acum oricine este interesat o poate achizitiona. Contine o descriere amanuntita a tuturor algoritmilor de baza care pot fi folositi in rezolvarea problemelor de concurs.\r\n* **Arta Programarii Calculatoarelor Vol. 1-3 (Donald Knuth)** - Donald E. Knuth este celebru datorita muncii sale de pionierat in domeniul algoritmilor si al tehnicilor de programare; \"Daca te crezi un bun programator... citeste Arta Programarii Calculatoarelor de Knuth... Daca poti citi toata cartea, trimite-mi neaparat un C.V.\" - Bill Gates. Cartile se pot gasi la noi in tara la editura Teora\r\n* **Proiectarea si implementarea algoritmilor (Mihai Oltean)** - aparuta la editura Computer Libris Agora din Cluj-Napoca; este o resursa foarte buna pentru programare dinamica\r\n* **Culegere de probleme si programe PASCAL (Mihai Stroe, Cristian Cadar)** - aparuta la editura Petrion din Bucuresti, contine un capitol introductiv bun despre geometrie, cat si diverse solutii interesante la probleme din concursuri\r\n* **Psihologia concursurilor de informatica (Catalin Francu)** - aparuta la editura L&S din Bucuresti; de asemenea contine solutii interesante la anumite probleme\r\n* **Informatica - culegere de probleme pentru liceu (Emanuela Cerchez)** - aparuta la editura Polirom, contine diverse aplicatii pentru metodele principale de programare\r\n* **Probleme de informatica date la concursurile internationale (Radu Berinde, Dan Ghinea, Horia Andrei Ciochina, Cornel Margine)** - aparuta la editura Fundatiei Pro, contine rezolvari pentru problemele de la principalele concursuri internationale din ultimii ani\r\n* **Fundamentele programarii - Culegere de probleme pentru clasa a IX-a / clasa a X-a (Dana Lica, Mircea Pasoi)** - aparute la editura L&S din Bucuresti, ambele contin un capitol mare de probleme propuse pe la concursuri impreuna cu solutii\r\n* **Arbori (Emanuela Cerchez)** - aparuta la editura Tara Fagilor, trateaza in detaliu arborii\r\n* **Probleme de combinatorica si teoria grafurilor (Ioan Tomescu)** - desi este o carte in principal de matematica multe probleme de acolo au aparut la concursurile romanesti\r\n* **Provocarea algoritmilor (Victor Mitrana)** - aparuta la editura Agni, Bucuresti\r\n* **Computational Geometry: An Introduction (Shamos, Preparata)** - o carte de baza pentru geometria computationala\r\n* **Computational Geometry in C (Joseph O\'Rourke)** - alta carte de baza pentru geometria computationala\r\n* **Algorithms (Robert Sedgewick)** - contine informatii despre algoritmii clasici si despre structurile de date cele mai folosite\r\n* **The Algorithm Design Manual (Steven Skiena)** - o carte de referinta, continand implementari ale unui numar mare de algoritmi\r\n* **Programming Challenges: The Programming Contest Training Manual (Steven Skiena, Miguel Revilla)** - o carte folositoare mai ales pentru concursurile ACM\r\n\r\nIn afara de cartile mentionate, internetul se dovedeste din nou o resursa foarte importanta. O cautare pe internet poate localiza informatii interesante: descrierea unor anumiti algoritmi impreuna cu performantele lor, tratari ale unor probleme clasice prin mai multe metode etc. Desigur pe langa carti este recomandat sa se si lucreze cat mai multe probleme de la editiile anterioare ale concursurilor principale si de pe site-urile cu evaluator disponibil 24 din 24. Astfel de site-uri sunt:\r\n\r\n* \"infoarena\":http://infoarena.ro\r\n* http://acm.timus.ru\r\n* http://acm.sgu.ru\r\n* http://spoj.sphere.pl\r\n* http://acm.pku.edu.cn\r\n* http://acm.zju.edu.cn\r\n* http://ace.delos.com/usacogate\r\n* http://www.oi.edu.pl/php/show.php?ac=e100000 (Site cu problemele polonezilor - o resursa foarte buna de pregatire, desi nu detine evaluator online)\r\n\r\nh3. Pregatirea psihica\r\n\r\nDupa cum s-a mai zis, este cunoscut faptul ca o atitudine mentala pozitiva este cheia succesului in cele mai multe situatii. Din nefericire, unii concurenti incep proba cu un moral nu tocmai ridicat. Iata cateva din falsele probleme cu care se confrunta anumiti concurenti:\r\n\r\n* _Participa si X, care e mai bun ca mine, deci nu am nici o sansa sa castig!_\r\nFals! Nu s-a demonstrat ca X este mai bun, cel mult a obtinut rezultate mai bune pana acum si poate avea sanse mai mari. Problemele din concursul curent sunt aceleasi pentru toti, conditiile de desfasurare sunt aceleasi si antecedentele nu conteaza. Totul se reia de la zero. In plus, participarea la un concurs puternic poate aduce mai multa experienta pentru viitor. Pentru a ajunge la valoarea necesara castigarii unor concursuri, trebuie sa participati la cat mai multe si sa le tratati cu seriozitate.\r\n* _Am obtinut prea putine puncte in prima zi, nu mai am nici o sansa la premii!_\r\nProblemele de la concursurile cu mai multe probe sunt, in general, destul de dificile. De multe ori, la Olimpiada Nationala sau la concursurile internationale, obtinerea a jumatate din punctele puse in joc inseamna castigarea unui premiu. Daca in prima zi rezultatele obtinute sunt nesatisfacatoare, un rezultat foarte bun in ziua a doua poate aduce premiul dorit. In ultimii ani pentru intrarea in lotul national largit, la barajele de selectie, a fost suficienta obtinerea a mai putin de 200 puncte, dintre cele 600 posibile.\r\n* _Nu sunt suficient de bine pregatit!_\r\nAceasta apreciere este, uneori, mai realista. Totusi, trebuie sa stiti ca o foarte mare importanta o are inspiratia de moment sau norocul (poate problemele vor fi similare cu unele rezolvate anterior). Evident, optimismul exagerat poate, la randul sau, sa fie daunator. Cel mai bine ar fi sa adoptati atitudinea cea mai potrivita pentru propria personalitate. Veti observa, in timp, care este aceasta.\r\n* _Problema asta e grea si n-am s-o pot rezolva perfect, asa ca nu ma mai apuc deloc de ea!_\r\nEste usor sa fii printre cei mai buni atunci cand concursul este usor. Mai greu e sa fii cel mai bun atunci cand concursul este dur, pentru ca atunci intervine - inevitabil - dramul de noroc al fiecaruia. Niciodata insa nu se poate invoca greutatea concursului drept o scuza pentru un eventual esec. Concursul este la fel de greu pentru toti. Se poate intampla, mai ales daca probele dureaza mai multe zile (2-3) ca nici unul din concurenti sa nu acumuleze mai mult de 50-60% din punctajul maxim. Totusi, aceasta nu inseamna ca ei nu sunt bine pregatiti; mai mult, unul dintre ei trebuie sa fie primul. Asadar, niciodata nu trebuie adoptata o strategie de genul acesta. Nu trebuie sa va impacientati daca vi se intampla sa nu aveti o idee geniala de rezolvare a unei probleme. Nu va cere nimeni sa faceti perfect o problema, ci numai sa prezentati o solutie care sa acumuleze cat mai multe puncte. Evident, prima varianta este intotdeauna preferabila, dar nu obligatorie. De multe ori se intampla ca un elev sa gaseasca o solutie cat de cat buna la o problema si, macar ca stie ca nu va lua punctajul maxim, ci doar o parte, sa renunte sa caute o solutie mai eficienta, deoarece timpul pierdut astfel ar aduce un castig prea mic si ar putea fi folosit la rezolvarea altor probleme. Desigur, daca nu faci toate problemele perfect, nu mai poti fi sigur de locul I, pentru ca altcineva poate sa te intreaca. Dar pe de alta parte, locul pe care te clasezi conteaza numai la etapa nationala a olimpiadei sau la concursurile internationale. In rest, important e numai sa te califici, adica sa intri in primele cateva locuri.\r\n\r\nPregatirea psihica nu are legatura numai cu concursul propriu-zis. O atitudine mentala pozitiva, de invingator, este utila pe tot timpul pregatirii pentru concursuri.\r\n\r\nh3. Organizarea globala a pregatirii\r\n\r\nAcest aspect poate contribui la obtinerea unor rezultate excelente. O parte foarte importanta a unei pregatiri sistematice consta in elaborarea unei liste cu metodele si tehnicile cunoscute si necunoscute, punctele slabe, etc. Lista trebuie sa contina algoritmii care apar in mod frecvent in cadrul problemelor de concurs, problemele care apar la implementare, la organizarea timpului in concurs, etc. Continului listei se modifica in timp; o parte din algoritmii necunoscuti sunt invatati si devin cunoscuti, se descopera noi puncte slabe, se evidentiaza existenta unor algoritmi necunoscuti care trebuie invatati, etc. Aceasta este o modalitate excelenta de a masura progresul si de a gasi noi directii de urmat in pregatire.\r\n\r\nh3. Simularea unor probe de concurs\r\n\r\nCea mai potrivita modalitate de pregatire pentru a face fata unei situatii este simularea ei, adica tratarea unei situatii asemanatoare. Acest principiu este valabil in orice tip de competitie, aplicandu-se si in domeniul concursurilor de programare. Daca va pregatiti pentru un concurs, citirea unor carti nu este suficienta! Trebuie sa va analizati comportamentul in situatii similare. Situatia cea mai asemanatoare unui anumit concurs este un alt concurs de acelasi tip. Participarea la N concursuri creste sansele obtinerii unui rezultat mai bun la al N+1-lea.\r\n\r\nConcursurile de pe internet sunt destul de dese si sunt organizate foarte bine. Din nefericire, nivelul de dificultate al acestor concursuri nu este intotdeauna cel dorit de cel care se pregateste. O posibilitate de simulare a unui concurs este rezolvarea problemelor de la o editie precedenta! De exemplu, cineva care se pregateste pentru Olimpiada Nationala ar trebui sa rezolve problemele date la Olimpiada Nationala din anul anterior la clasa respectiva (exista si cazuri in care simulari de acest tip nu sunt foarte concludente; de exemplu, intre 2000 si 2001 programa scolara a suferit cateva variatii, care s-au reflectat in tipul problemelor de la clasa a X-a). Pentru ca simularea sa reflecte cat mai bine realitatea, problemele se rezolva in timpul stabilit, fara pauze, la prima citire (sau, daca au fost citite anterior, nu se recitesc in zilele premergatoare simularii). Experienta obtinuta este apropiata de cea a concursului propriu-zis, dar lipseste stresul care apare, inevitabil, in timpul competitiei. Este important ca, dupa fiecare simulare sau concurs real, sa va analizati comportarea si sa invatati din eventualele greseli de abordare (de exemplu, puteti ajunge la concluzii de genul _Aceasta problema trebuia abordata prima_ sau _Nu am citit integral enuntul si am rezolvat o alta problema_). Concluziile analizei duc la detectarea actiunilor necesare pentru a imbunatati situatia.\r\n\r\nIn plus, se recomanda notarea celor mai frecvente greseli de implementare si examinarea periodica a listei (inclusiv in timpul depanarii programelor, in cadrul simularii concursurilor); in acest fel, greselile respective vor disparea in timp.\r\n\r\nh3. Discutiile cu alti elevi si profesori\r\n\r\nPuteti invata foarte mult de la profesori, si in special de la elevi mai experimentati! Exista foarte multe exemple de elevi pentru care a contat foarte mult pregatirea individuala, dar exista unii care au fost ajutati de pregatirea organizata, in grupuri de elevi, sub indrumarea unor profesori cu preocupari de acest gen. In cadrul pregatirilor de acest tip se discuta algoritmi, se propun probleme spre rezolvare, se discuta diversele modalitati de rezolvare, se obtin mai multe informatii despre concursuri, etc. In plus, elevii aduc in discutie diverse probleme cu care s-au intalnit in cadrul pregatirii individuale. Daca doriti sa participati la astfel de pregatiri, trebuie sa luati legatura cu alti elevi interesati de concursuri, sau cu profesori care se ocupa de pregatirea elevilor pentru olimpiade. In prezent se organizeaza pregatiri la nivel de liceu, oras, judet, etc. in anumite zone. Astfel de pregatiri cresc valoarea tuturor participantilor, deci sunt foarte importante. Pregatirile organizate au luat amploare odata cu infiintarea centrelor de excelenta. Pentru a intra in contact cu alti elevi interesati puteti folosi \"forumul infoarena\":http://infoarena.ro/forum si \"forumul revistei GInfo\":http://ba.toptalent.ro/forum.\r\n\r\nh3. Pregatirea de la locul desfasurarii probei\r\n\r\nDesi ar putea parea bizar, acest aspect este foarte important, dar este neglijat de multe ori de catre concurenti. Aceasta pregatire consta in:\r\n\r\n* somn odihnitor in noaptea care precede ziua concursului **(foarte important!)**\r\n* obtinerea atitudinii mentale dorite\r\n* prezentarea la timp in sala, cu toate obiectele necesare\r\n\r\nExista cateva obiecte pe care ar trebui sa le aveti la voi. In timpul concursului trebuie tinuta o evidenta drastica a timpului scurs si a celui ramas. E drept ca in general supraveghetorii anunta din cand in cand timpul care a trecut, dar e bine sa nu va bazati pe nimeni si nimic altceva decat pe voi insiva. Unii pot spune _Ei, ce nevoie am de ceas, oricum am ceasul calculatorului la indemana_. Asa e, dar e incomod sa te opresti mereu la jumatatea unei idei si sa verifici cat e ceasul schimband consola sau minimizand fereastra de lucru. In ceea ce priveste hartia de scris, ea este in mod sigur necesara. De fapt, o parte importanta a rezolvarii unei probleme este proiectarea matematica a algoritmului, lucru care nu se poate face decat cu creionul pe hartie. Pe langa aceasta, majoritatea problemelor opereaza cu vectori, matrice, arbori, grafuri, etc., iar exemplele pe care este testat programul realizat trebuie neaparat verificate \"de mana\". Este recomandat sa aveti mereu si hartie de matematica; este foarte folositoare pentru problemele de geometrie analitica, precum si pentru reprezentarea matricelor. Nu in ultimul rand, ar fi bine sa aveti o sticla de suc si o ciocolata; din nefericire, concursul incepe deseori cu intarziere si este bine ca foamea sau setea sa nu va preocupe in timpul rezolvarii problemelor.\r\n\r\nh2. 4. In timpul concursului\r\n\r\nImediat ce primiti problemele, cititi toate enunturile si faceti-va o idee aproximativa despre gradul de dificultate al fiecarei probleme. Neaparat verificati daca se dau limite pentru datele de intrare (numarul maxim de elemente ale unui vector si valoarea maxima a acestora, numarul maxim de noduri dintr-un graf, etc.) si pentru timpii de executie pentru fiecare test. Dimensiunea input-ului poate schimba radical dificultatea problemei. Spre exemplu, pentru un vector cu N &le; 200 elemente, un algoritm O(N^3^) merge rezonabil, pe cand pentru N &le; 2000 acelasi algoritm ar depasi cu mult cele cateva sutimi de secunda care se acorda de obicei. In primele zece minute (sau mai mult) nu se atinge calculatorul. Intotdeauna, cand cititi o problema, este indicat sa intoarceti foaia pentru a vedea daca enuntul continua si pe verso. De obicei, in primele 30 sau 60 de minute ale concursului pot fi adresate intrebari comisiei, pentru a clarifica eventualele ambiguitati din enunturi. Acestea sunt redactate in scris, foile sunt preluate de supraveghetorul din sala si trimise la comisie. Raspunsul s-ar putea sa intarzie, deci este indicat sa nu irositi timpul asteptand raspunsul fara a mai face nimic altceva. Puteti fie sa va ganditi la rezolvarea unei probleme, fie sa incepeti sa implementati (daca exista ceva usor de implementat, cum ar fi o problema simpla sau o rutina pentru citirea datelor de intrare). In majoritatea situatiilor, intrebarile trebuie formulate in asa fel incat raspunsul sa fie _Da_ sau _Nu_. Daca intrebarea nu este astfel exprimata sau daca raspunsul se gaseste in textul problemei, veti primi raspunsul _Fara comentarii_, caz in care va trebui mai intai sa studiati corectitudinea intrebarii si, daca aceasta este corect formulata, sa recititi enuntul problemei. Concurentii trebuie sa profite cat mai mult de aceasta perioada, pentru a clarifica eventualele nelamuriri. Un lucru important este ca nu trebuie sa acceptati raspunsuri daca acestea nu sunt insotite de semnatura unui membru al comisiei.\r\n\r\nFaceti o impartire a timpului pentru problemele ramase proportional cu dificultatea aparenta a fiecarei probleme. In general problemele au punctaje egale. Incercati sa nu depasiti niciodata limitele de timp pe care le-ati fixat. Daca in schimb reusiti sa economisiti timp fata de cat v-ati propus, cu atat mai bine, veti face o realocare a timpului si veti avea mai mult pentru celelalte probleme. Apucati-va de problema **cea mai simpla**. Mai bine sa duceti la bun sfarsit o problema usoara, decat sa va apucati de o problema grea si sa nu terminati nici una. Daca toate problemele par grele, alegeti-o pe cea din domeniul care va este cel mai familiar, in care ati lucrat cel mai mult. Daca va este indiferent si acest lucru, alegeti o problema unde simtiti ca aveti o idee simpla de rezolvare.\r\n\r\nIncepeti sa va ganditi la algoritmi cat mai buni, estimand in acelasi timp si cat v-ar lua ca sa-i implementati. Faceti, pentru fiecare idee care va vine, calculul complexitatii. Nu trebuie neaparat sa gasiti cel mai eficient algoritm, ci numai unul suficient de bun. In general, trebuie ca, dintre toti algoritmii care se incadreaza in timpul de rulare, sa-l alegeti pe cel care este cel mai usor de implementat. Daca algoritmul gasit este greu de implementat, mai cautati altul o vreme. Trebuie insa ca timpul petrecut pentru gasirea unui nou algoritm plus timpul necesar pentru scrierea programului sa nu depaseasca timpul necesar pentru implementarea primului algoritm, altfel nu castigati nimic. Deci nu exagerati cu cautarile si nu incercati sa reduceti dincolo de limita imposibilului complexitatea algoritmului. Mai ales, nu uitati ca programul nu poate avea o complexitate mai mica decat dimensiunea input-ului sau a output-ului. De exemplu, daca programul citeste sau scrie matrice de dimensiune N*N, nu are sens sa va bateti capul ca sa gasiti un algoritm mai bun decat O(N^2^). Dintre toate ideile de implementare gasite (care se incadreaza fara probleme in timp), o veti alege pe cea mai scurta ca lungime de cod.\r\n\r\nIn general, pentru orice problema exista cel putin o solutie, fie si una slaba. Sunt numeroase cazurile cand nu va vine alta idee de rezolvare decat cea slaba. De regula, cand nu aveti in minte decat o rezolvare neeficienta a problemei, care stiti ca nu o sa treaca toate testele (un backtracking, sau un O(N^5^), O(N^6^), etc.) e bine sa incercati urmatorul lucru:\r\n\r\n* Calculati cam cat timp v-ar trebui ca sa implementati rezolvarea slaba. In acest calcul trebuie sa includeti si un timp estimativ de depanare a programului (care variaza de la persoana la persoana) si pe cel de testare. Daca sunteti foarte siguri pe voi, puteti sa neglijati timpul de testare, dar orice program trebuie testat cel putin pe exemplul de pe foaie.\r\n* Pentru a avea sanse mai mari sa gasiti o alta solutie, este indicat sa incercati sa ignorati complet solutia slaba, sa nu o luati ca punct de plecare. Incercati sa va \"goliti\" mintea si sa gasiti ceva nou, altfel va veti invarti mereu in cerc.\r\n* Daca va vine vreo idee mai buna, ati scapat de griji si va apucati de implementare (daca aveti timpul necesar).\r\n\r\nDin acest moment, pentru varianta aleasa veti scrie programul, fara a va mai gandi la altceva, chiar daca pe parcurs va vin alte idei. Iata unele lucruri pe care e bine sa le stiti despre scrierea unui program:\r\n\r\n* Datele de intrare se presupun a fi corecte. Aceasta este o regula nescrisa (uneori) a concursului de informatica.\r\n* Efectul optiunilor de compilare asupra vitezei este semnificativ.\r\n* Daca se poate, evitati lucrul cu pointeri. Programele care ii folosesc sunt mai greu de depanat si se pot bloca mult mai usor.\r\n* Evitati lucrul cu numere reale (comparatii, impartiri, etc.), daca puteti. Operatiile in virgula mobila sunt mult mai lente.\r\n* Alegeti-va numele de variabile in asa fel incat programul sa fie clar. Sunt permise mai mult de doua litere! Numele fiecarei proceduri, functii, variabile trebuie sa-i explice clar utilitatea. E drept, lungimea programului creste, dar codul devine mult mai limpede si timpul de depanare scade foarte mult. Ca o regula generala, claritatea programelor face mult mai usoara intelegerea lor chiar si dupa o perioada mai indelungata de timp (luni, ani). Nu trebuie nici sa cadeti in cealalta extrema. De exemplu, nu depasiti 10 caractere pentru un nume de variabila.\r\n* Salvati programul cat mai des. Daca va obisnuiti, chiar la fiecare 2-3 linii. Dupa ce o sa va intre in reflex n-o sa va mai incomodeze  cu nimic acest obicei. Au fost cazuri in care o pana de curent prindea pe picior gresit multi concurenti, iar dupa aceea nu mai este absolut nimic de facut, pentru ca nimeni nu va va crede pe cuvant ca ati facut programul si ca el mergea.\r\n* Obisnuiti-va sa programati modular. Faceti proceduri separate pentru citirea si initializarea datelor, pentru sortare, pentru afisarea rezultatelor, etc. In general nu se recomanda sa scrieti proceduri in alte proceduri (adica e bine ca toate procedurile sa apartina direct de programul principal). Procedurile, acolo unde e posibil, nu trebuie sa depaseasca un ecran, pentru a putea avea o viziune de ansamblu asupra fiecareia in parte. Acest lucru ajuta mult la depanare.\r\n* Rulati programul cat mai des, daca timpul va permite. In primul rand dupa ce scrieti procedura de citire a datelor. Daca e nevoie de sortarea datelor de intrare, nu strica sa va convingeti ca programul sorteaza bine, ruland 2-3 teste oarecare. E pacat sa pierdeti puncte dintr-o greseala copilareasca.\r\n* O situatie mai delicata apare cand fisierul de intrare contine mai multe seturi de date (teste). In acest caz, atentia trebuie sporita, deoarece daca la primul sau al doilea test programul vostru da eroare si se opreste din executie, veti pierde automat si toate celelalte teste care urmeaza. Daca in fisierul de intrare exista un singur set de date, atunci pierderea din vedere a unui caz particular al problemei nu putea duce, in cel mai rau caz, decat la picarea unui test. Asa insa, picarea unui test poate atrage dupa sine picarea tuturor celor care il urmeaza. Pe langa corectitudinea strict necesara, programul trebuie sa se incadreze si in timp pentru orice fel de test. Daca la primul sau al doilea test din suita programul depaseste timpul (sau, si mai rau, se blocheaza), e foarte probabil sa fie oprit din executie de catre comisie, deci din nou veti pierde toate testele care au ramas neexecutate.\r\n* Tot in situatia in care exista mai multe seturi de date in fisierul de intrare, daca iesirea se face intr-un fisier, este bine ca dupa afisarea rezultatului pentru fiecare test sa actualizati fisierul de iesire. In felul acesta, chiar daca la unul din teste programul se blocheaza sau da eroare, rezultatele deja scrise raman scrise. Altfel, e posibil ca rezultatele de la testele anterioare sa ramana intr-un buffer in memorie, fara a fi \"varsate\" pe disc.\r\n\r\nTot la partea de implementare, este bine ca codul sa fie cat mai scurt si cat mai optimizat - dar, despre scrierea unui cod cat mai eficient se poate face un articol cam la fel de mare cat acesta, deci nu se va trata acest subiect aici - metoda cea mai buna in acest sens este sa invatati din sursele altora. Puteti incepe cu articolele \"_12 ponturi pentru programatorii C/C++_\":http://infoarena.ro/12-ponturi-pentru-programatorii-CC si \"_Multe smenuri de programare in C/C++... si nu numai!_\":http://infoarena.ro/Multe-smenuri-de-programare-in-CC-si-nu-numai si sectiunea \"Links\":http://infoarena.ro/links.\r\n\r\nMai ramane doar partea de depanare. O metoda buna de depanare este urmatoarea:\r\n\r\n* Incepeti cu un test nici prea simplu, nici prea complicat (si usor de urmarit cu creionul pe hartie) si executati-l de la cap la coada. Daca merge perfect, treceti la teste mai complexe (se recomanda **minim** 4 test si maxim 7-8). Daca le trece si pe acestea, puteti zambi. Totusi, daca programul vostru a mers perfect pe 7-8 teste date la intamplare, exista sanse (dar nu extrem de mari!) sa mearga pe majoritatea testelor comisiei, sau chiar pe toate.\r\n* Exemplul dat in enunt nu are in general nici o semnificatie deosebita (de fapt, are mai curand darul de a semana confuzie printre concurenti), iar daca programul merge pe acest test particular, nu inseamna ca o sa mearga si pe alte teste.\r\n* Daca la unul din teste programul nu merge corespunzator, rulati din nou testul , dar de data aceasta procedura cu procedura. Dupa fiecare procedura evaluati variabilele si vedeti daca au valorile asteptate. In felul acesta puteti localiza cu precizie procedura, apoi linia unde se afla eroarea. Corectati in aceasta maniera toate erorile, pana cand testul este trecut.\r\n* In acest moment, luati de la capat toate testele pe care programul le-a trecut deja. In urma depanarii, s-ar putea ca alte greseli sa iasa la suprafata si programul sa nu mai mearga pe vechile teste.\r\n* Repetati procedeul de mai sus pana cand toate testele merg. Daca va obisnuiti sa programati modular si ingrijit, depanarea si testarea n-ar trebui sa dureze mai mult de 5-25 minute. Din acest moment, nu mai modificati nici macar o litera in program, sau daca o faceti pastrati-va in prealabil o copie. Nu va bazati pe faptul ca puteti sa tineti minte modificarile facute si sa refaceti oricand forma initiala a programului in caz ca noua versiune nu va fi buna.\r\n* Daca totusi nu-i puteti \"da de cap\" programului, iar timpul alocat problemei respective expira, aduceti programul la o forma in care sa mearga macar pe o parte din teste si treceti la problema urmatoare.\r\n\r\nFeriti-va ca de foc de criza de timp. E mare pacat sa ratezi o problema intreaga pentru ca n-ai avut timp sa scrii procedura de afisare a solutiei, sau lucruri asemanatoare. Rezervati-va intotdeauna timpul pe care il socotiti necesar pentru implementare si depanare. De asemenea, chiar daca concursul este usor, nu e recomandat sa iesiti din sala de concurs inainte de expirarea timpului. Oricat ati fi de convinsi ca ati facut totul perfect, mai verificati-va; veti avea de furca cu remuscarile daca descoperiti dupa aceea ca ceva, totusi, nu a mers bine. Puteti face o multime de lucruri daca mai aveti timp (desi acest lucru se intampla rar). Iata o serie de metode de a exploata timpul:\r\n\r\n* Verificati-va programul cu cat mai multe teste de mici dimensiuni. Sa presupunem ca programul vostru lucreaza cu vectori de maxim 10.000 de elemente. E o idee buna sa il rulati pentru vectori de unul sau doua elemente.\r\n* Treceti la polul opus si creati-va un test de dimensiune maxima, dar cu o structura particulara, pentru care este usor de calculat rezultatul si de mana. De exemplu, vectori de 10.000 de elemente cu toate elementele egale, sau vectori de forma (1, 2, ..., 9999, 10000). Daca nu puteti sa editati un asemenea fisier de mana, copiind si multiplicand blocuri, puteti scrie un program care sa-l genereze.\r\n* Daca inca v-a mai ramas timp, creati-va un program care sa genereze teste aleatoare. Spre exemplu, un program care sa citeasca N si sa creeze un fisier in care sa scrie N numere aleatoare. Intr-o prima faza, puteti folosi aceste teste pentru a verifica daca nu cumva la valori mai mari programul nu da eroare, nu se blocheaza (la alocarea unor zone mari de memorie) sau nu depaseste limita de timp, caz in care mai aveti de lucru.\r\n* Daca tot nu va da nimeni afara din sala, puteti scrie un alt program auxiliar care, primind fisierul de intrare si fisierul de iesire produs de programul vostru, verifica daca iesirea este corecta. Aceasta deoarece, de obicei, este mult mai usor de verificat o solutie decat de produs una. Folosind \"generatorul\" de teste si \"verificatorul\", puteti testa programul mult mai bine. De altfel, la multe probleme chiar testele rulate de comisia de corectare sunt create tot aleator.\r\n\r\nh2. 5. Dupa concurs\r\n\r\nDupa ce ati terminat problemele (se intampla destul de rar) nu iesiti din sala! Este momentul ultimelor teste. La iesirea din sala trebuie sa fiti convinsi ca ati facut tot ce era posibil in conditiile date. Concursul nu s-a terminat inca! Urmeaza corectarea. Va trebui sa verificati punctajul obtinut si sa fiti pregatit sa depuneti o contestatie daca aveti impresia ca ceva nu este in regula. La unele concursuri, corectarea se face in prezenta concurentului; aici aveti ocazia sa solicitati sa vi se arate testele si iesirile furnizate de programul vostru, sa cereti testarea din afara mediului de evaluare, etc. La alte concursuri, comisia ofera, mai tarziu, testele si raspunsurile corecte pentru autoevaluare. Nu ratati ocazia de a va evalua rezolvarile si nu depuneti contestatii decat daca in urma autoevaluarii obtineti un punctaj mai mare. Fiecare concurs este o experienta in plus! Discutati, dupa proba, cu alti concurenti, aflati cum ar fi trebuit rezolvate problemele pe care nu le-ati stiut aborda si ce au gresit ceilalti (este bine sa invatati si din greselile altora).\r\n\r\nDe multe ori, primul an de participare la olimpiada se soldeaza cu un rezultat cel mult mediu, deoarece, oricat ar spune cineva _Ei, nu-i asa mare lucru sa mergi la un concurs_, experienta acumulata conteaza mult. De aceea, abia de la a doua participare si uneori chiar de mai tarziu incep sa apara rezultatele. Intentia autorului a fost sa va usureze misiunea si sa va dezvaluie cateva din dificultatile de toate felurile care apar la orice concurs, pentru a nu va da ocazia sa le descoperiti pe propria piele. Speram ca aceste ponturi va vor fi de folos!\r\n\r\nh2. Bibliografie\r\n\r\n# **Psihologia concursurilor de informatica**, Catalin Francu, Editura L&S Bucuresti\r\n# \"**Despre Concursuri**\":http://www.ginfo.ro/revista/13_4/babel.pdf, Mihai Stroe, Gazeta de Informatica, numarul 13/4, anul 2003\r\n# \"infoarena\":http://infoarena.ro\r\n# \"Google\":http://www.google.com',2044,'public',NULL,NULL),('coduri-gray','Coduri Gray','2008-02-23 08:00:17','2009-01-10 21:38:24','h1. Coduri Gray\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"alecman\") ==\r\n\r\n(Categoria _Matematica_, Autor _Cosmin Negruseri_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Cuprins*\r\n* \'Introducere\':coduri-gray#introducere\r\n* \'Problema 1: Turnurile din Hanoi\':coduri-gray#hanoi\r\n* \'Problema 2: Becuri\':coduri-gray#becuri\r\n* \'Problema 3: Matrix\':coduri-gray#matrix\r\n* \'Problema 4: Divizori\':coduri-gray#divizori\r\n* \'Problema 5: Sortnet\':coduri-gray#sortnet\r\n* \'Bibliografie\':coduri-gray#biblio\r\n\r\nh2(#introducere). Introducere\r\n\r\nUn cod Gray de ordin $n$ este un sir care contine toate numerele de la $0$ la $2^n-1^$, astfel incat orice doua numere consecutive din sir sa difere in reprezentarea lor binara prin exact un bit. Exista mai multe coduri Gray distincte, cel mai des intalnit fiind asa-numitul **\"binary reflected Gray code\"** (in continuare cand vom vorbi despre codul Gray ne vom referi de fapt la acest cod). Modul de constructie este destul de intuitiv: fiecare numar nou este format din cel anterior prin modificarea celui mai putin semnificativ bit, astfel incat numarul sa nu mai fi fost adaugat inainte la sir (de exemplu, pentru $n = 2$ si primul numar $0$, sirul obtinut va fi $0, 1, 3, 2$).\r\n\r\nIn continuare vom nota acest cod cu $G{~n~}$. Putem da astfel o noua metoda de constructie. Fie $G\'{~n-1~}$ sirul $G{~n-1~}$ inversat, atunci obtinem $G{~n~}$ daca punem cate un bit $0$ in fata fiecarui numar din $G{~n-1~}$, urmat de numerele din $G\'{~n-1~}$, carora le adaugam cate un $1$ ca bit semnificativ ( pe scurt $G{~n~} = 0G{~n-1~},1G\'{~n-1~} (1)$). Se poate observa ca acest cod este circular, diferenta intre ultimul si primul numar fiind de exact un bit. De asemenea, orice cod de ordin $n$ il contine pe cel de $n-1$ ca prefix, deci am putea nota prin $G{~&infin;~}$ sirul numerelor naturale in care orice doua numere consecutive difera in reprezentarea binara prin exact un bit si pentru care sirul primelor $2^n^$ elemente coincide cu $G{~n~}$ (&forall; $n$ &isin; _**N**_). \r\n\r\nFie $g(x)$ al $x$-lea numar din $G{~&infin;~}$ si $g-1(y)$ pozitia la care apare numarul $y$ in sirul $G{~&infin;~}$. Se pune problema calcularii eficiente a celor doua functii. Se poate demonstra prin inductie ca daca avem un numar $x$ cu reprezentarea binara $(...a{~2~}a{~1~}a{~0~}){~2~}$ si codul lui Gray $(...b{~2~}b{~1~}b{~0~}){~2~}$, atunci avem $b{~i~} = a{~i~} ^&and;^ a{~i+1~}$ (2). De exemplu, pentru numarul $6$ cu reprezentarea binara $110$, atunci $g(110) = 101$. De aici se deduce ca $g(i) = x ^&and;^ (x / 2)$. Din (2) obtinem ca $b{~i~} ^&and;^ b{~i+1~} ^&and;^ b{~i+2~} ^&and;^ ... = (a{~i~} ^&and;^ a{~i+1~}) ^&and;^ (a{~i+1~} ^&and;^ a{~i+2~}) ^&and;^ (a{~i+2~} ^&and;^ a{~i+3~}) ^&and;^ ... = a{~i~}$. Suma este finita deoarece va exista un $b{~i~}$ egal cu $0$ si un $a{~i~}$ egal cu $0$ (daca $i$ este indeajuns de mare). Rezulta astfel ca $g-1(y) = y ^&and;^ y/2 ^&and;^ y/4 ^&and;^ ...$\r\n\r\nDin cele de mai sus obtinem urmatoarele metode:\r\n\r\n== code(cpp) |\r\nint binToGray(int x) {\r\n    return x ^ (x >> 1);\r\n}\r\n==\r\n\r\n== code(cpp) |\r\nint grayToBin(int y) {\r\n    int ret = 0;\r\n    while (y > 0) {\r\n        ret ^= y;\r\n        y >>= 1;\r\n    }\r\n    return ret;     \r\n}\r\n==\r\n\r\nh2(#hanoi). Problema 1: _Turnurile din Hanoi_\r\n\r\nAvem trei tije si $n$ discuri de dimensiuni diferite plasate in ordinea descrescatoare a dimensiunilor pe prima tija. Se doreste mutarea tuturor discurilor pe cea de a doua tija, singurul tip de miscare posibila fiind mutarea unui disc de pe o tija pe alta, cu conditia ca pe tija destinatie discul din varf (daca exista un asemenea disc) sa fie mai mare decat discul pe care il mutam acum.\r\n\r\nh3. Rezolvare\r\n\r\nAceasta este o problema clasica in predarea recursivitatii, dar ea are o solutie care se foloseste de codul Gray. Urmarim la fiecare pas ce bit se schimba de la numerele consecutive ale lui $G{~n~}$ - acest bit corespunde discului pe care il vom muta (cel mai putin semnificativ bit corespunde celui mai mic disc etc). Problema este ca nu stim pe ce tija trebuie sa mutam discul respectiv. Exista o regula simpla care ne poate ajuta: un disc nu trebuie plasat pe alt disc cu aceeasi paritate. Folosind aceasta strategie, putem rezolva problema in numar minim de pasi ( $2^n^ - 1$ ).\r\n\r\nh2(#becuri). Problema 2: _Becuri_\r\n\r\nUn bec este conectat la $n$ intrerupatoare. Fiecarui astfel de intrerupator ii poate fi schimbata starea prin apasare. Problema este ca nu stim starea lor initiala. Se cere sa se determine o strategie care ar face numar minim de apasari in cazul cel mai defavorabil, pentru a aprinde becul.\r\n\r\nh3. Rezolvare\r\n\r\nPentru a fi siguri ca aprindem becul trebuie in cel mai rau caz sa trecem prin toate configuratiile apasat/ne-apasat ale intrerupatoarelor. Pentru a schimba starea curenta trebuie sa apasam cel putin un buton, deci in cazul cel mai defavorabil va trebui sa facem cel putin $2^n^ - 1$ apasari. Codul Gray ne da o posibilitate de a trece prin toate configuratiile trecand de la una la alta prin o apasare de buton, rezolvandu-ne problema.\r\n\r\nh2(#matrix). Problema 3: \'_Matrix_\':http://acm.sgu.ru/problem.php?contest=0&problem=249 (SGU)\r\n\r\nTrebuie sa aranjati numerele de la $0$ la $2^(n + m)^ - 1$ intr-o matrice cu $2^n^$ randuri si $2^m^$ coloane. De asemenea, numerele care sunt situate in celule adiacente pe verticala sau orizontala trebuie sa difere prin exact un bit in reprezentarea lor binara. Matricea este ciclica, adica pentru fiecare rand celula cea mai din stanga se considera invecinata cu cea mai din dreapta, de asemenea pentru fiecare coloana celula cea mai de sus se considera invecinata cu celula cea mai de jos. La intrare se dau numerele $n$ si $m$ ( $0 < n, m; n + m <= 20$ ). Trebuie sa afisati o asemenea matrice. De exemplu daca $n = 1$ si $m = 1$ o matrice ar fi\r\n( $0$ $2$ )\r\n( $1$ $3$ )\r\n\r\nh3. Rezolvare\r\n\r\nO prima metoda ar fi de a determina codului $G{~n+m~}$, iar apoi de a-l scrie serpuit in matrice (liniile de index par de la stanga la dreapta, cele de index impar in sens invers).\r\n\r\nDe exemplu, daca $n = 2$ si $m = 2$ avem:\r\n$G{~4~} = {0000, 0001, 0011, 0010, 0110, 0111, 0101, 0100, 1100, 1101, 1111, 1110, 1010, 1011, 1001, 1000}$\r\n\r\n| 0000 | 0001 | 0011 | 0010 |\r\n| 0100 | 0101 | 0111 | 0110 |\r\n| 1100 | 1101 | 1111 | 1110 |\r\n| 1000 | 1001 | 1011 | 1010 |\r\n\r\nAlta modalitate de rezolvare care ne da de fapt aceeasi matrice este urmatoarea: in celula $(i,j)$ vom avea rezultatul concatenarii reprezentarilor binare ale lui $i$ (din codul $G{~n~}$) si $j$ (din codul $G{~m~}$).\r\n\r\nDe exemplu, matricea pentru $n = 3$ si $m = 2$ este:\r\n\r\n|_. - |_. 00 |_. 01 |_. 11 |_. 10 |\r\n|_. 000 | 00000 | 00001 | 00011 | 00010 |\r\n|_. 001 | 00100 | 00101 | 00111	| 00110 |\r\n|_. 011 | 01100 | 01101 | 01111 | 01110 |\r\n|_. 010 | 01000 | 01001 | 01011 | 01010 |\r\n|_. 110 | 11000 | 11001 | 11011 | 11010 |\r\n|_. 111 | 11100 | 11101 | 11111 | 11110 |\r\n|_. 101 | 10100 | 10101 | 10111 | 10111 |\r\n|_. 100 | 10000 | 10001 | 10011 | 10010 |\r\n\r\nEste evident ca orice doua numere adiacente in matrice sunt diferite in reprezentarea binara prin exact un bit. In concurs limita de timp era foarte stransa si trebuia folosita functia prezentata anterior. Deci pe linia $i$, coloana $j$ a matricei scriem numarul (binToGray(i) << M) | binToGray(j).\r\n\r\nh2(#divizori). Problema 4: \'_Divizori_\':problema/divizori\r\n\r\nVom considera un numar natural $N$. In sirul $A$ vom aseza toti divizorii lui $N (2 <= N <= 2.000.000.000)$. Se cere sa se permute elementele sirului $A$ astfel incat pentru oricare doua elemente consecutive $A[i]$ si $A[i+1]$ sa avem fie $A[i] = A[i+1] * p$, fie $A[i+1] = A[i] * p$ ( $p$ numar prim oarecare). Valoarea $p$ poate diferi de la o pereche de elemente la alta. De exemplu, pentru $N = 12$ o posibila solutie ar fi $1, 2, 3, 4, 12, 6, 3$.\r\n\r\nh3. Rezolvare\r\n\r\nNumarul $N$ are maxim $2*N^1/2^$ divizori. Descompunerea lui $N$ in factori primi are forma $P{~1~}^E{~1~}^ * P{~2~}^E{~2~}^ * ... * P{~k~}^E{~k~}^$ ( $P{~1~}, P{~2~}, ..., P{~k~}$ - numere prime, si $E{~i~} &isin; _**N**_, E{~i~} &gt; 0$ ). Un divizor al lui $N$ va fi reprezentat printr-un vector de exponenti $(e{~1~}, e{~2~}, ..., e{~k~})$ unde $0<=e{~i~}<=E{~k~}$. Prin urmare, problema noastra poate fi usor redusa la urmatoarea cerinta: ordonati toti vectorii $(e{~1~}, e{~2~}, ..., e{~k~})$ intr-un sir cu proprietatea ca diferenta intre doi vectori consecutivi se realizeaza la o singura pozitie a vectorilor si cele doua elemente ale vectorilor de pe pozitia respectiva difera prin o unitate.\r\nExemplul din enuntul problemei se poate reprezenta astfel:\r\n$1, 2, 4, 12, 6, 3$\r\n$P{~1~} = 2 E{~1~} = 2$\r\n$P{~2~} = 3 E{~2~} = 1$\r\n$(0,0), (1,0), (2,0), (2,1), (1,1), (0,1)$\r\n\r\nAceasta problema este o generalizare a determinarii codului Gray si poate fi rezolvata generalizand metoda expusa mai sus. Presupunem ca stim sa generam o solutie pentru $M = N/(P{~k~}E{~k~})$ (o solutie pentru un numar cu $k-1$ factori primi). Sa vedem cum generam o solutie pentru $N$. Fie $C$ vectorul solutie pentru $M$ si $R$ vectorul $C$ inversat. O solutie poate fi:\r\n$C, P{~k~}*R, P{~k~}^2^*C, P{~k~}^3^*R ...$\r\nAstfel am concatenat $E{~k~}$ coduri pentru $M$, inmultind cu $P{~k~}$ si pe fiecare pozitie impara am pus secventa inversata pentru $M$. Am facut aceasta pentru ca cele doua capete ce vor ajunge in codul final consecutive sa difere numai prin $P{~k~}$.\r\n\r\nExemplu: $E{~1~} = 3; E{~2~} = 2; E{~3~} = 1$\r\n$(0,0,0) (1,0,0) (2,0,0) (3,0,0)$ - Solutia pentru un factor prim.\r\n$(0,0,0) (1,0,0) (2,0,0) (3,0,0) (3,1,0) (2,1,0) (1,1,0) (0,1,0) (0,2,0) (1,2,0) (2,2,0) (3,2,0)$ - Solutia pentru doi factori primi.\r\n$(0,0,0) (1,0,0) (2,0,0) (3,0,0) (3,1,0) (2,1,0) (1,1,0) (0,1,0) (0,2,0) (1,2,0) (2,2,0) (3,2,0)$\r\n$(3,2,1) (2,2,1) (1,2,1) (0,2,1) (0,1,1) (1,1,1) (2,1,1) (3,1,1) (3,0,1) (2,0,1) (1,0,1) (0,0,1)$ - Solutia pentru cei trei factori primi.\r\n\r\nComplexitatea finala a solutiei este $O(T)$ unde $T$ reprezinta numarul de divizori ai lui $N$.\r\n\r\nh2(#sortnet). Problema 5: \'_Sortnet_\':problema/sortnet (Lot 2002)\r\n\r\nO retea completa de sortare este o retea de sortare cu $N$ fire de adancime $D$ ce are $D * (N/2)$ comparatori. Amintim principiul $0-1$ care spune ca o retea de sortare sorteaza orice $N$ numere daca aceasta sorteaza orice secventa de $N$ numere $0-1$. Problema noastra cere sa se determine cate astfel de secvente de $0-1$ nu sunt sortate corect.\r\n\r\nh3. Rezolvarea lui Mihai Patrascu\r\n\r\nObservam ca dupa primul strat de comparatori sunt exact $3^(N/2)^$ rezultate posibile, pentru ca intrarile trecute printr-un comparator se transforma astfel:\r\n\r\n| (0,0) -> (0,0) | (0,1) -> (1,0) | (1,0) -> (1,0) | (1,1) -> (1,1) |\r\n\r\nPentru a testa fiecare astfel de rezultat daca e sortat sau nu de urmatoarele $D-1$ straturi, nu vor trebui simulate toate in complexitate $O(N * 3^N/2^ * D)$. Prin generarea secventelor conform codului Gray in baza 3 putem doar sa urmarim modificarea rezultatului pentru doua rezultate succesive in $O(D)$. Un numar in baza trei il transformam in baza doi cu numar dublu de cifre, astfel:\r\n\r\n| 0 -> 00 | 1 -> 10 | 2 - > 11 |\r\n\r\nacest cod reprezentand un rezultat posibil dupa evaluarea unei secvente binare de catre primul strat al retelei. Modificarea unei cifre in baza trei conform codului Gray generalizat pentru numere in aceasta baza, duce la modificarea unei cifre in codul binar a unui bit. Urmarirea modificarilor facute de acest bit schimbat in evaluarile facute de reteaua de sortare o putem face in complexitate $O(D)$. Astfel complexitatea finala este $O(3^N/2^ * D)$.\r\n\r\nMentionam ca problema este pe site-ul InfoArena (\'Sortnet\':problema/sortnet) si acolo o rezolvare $O(2^N^ * D)$ intra in timp, dar si pentru aceasta trebuie sa folosim codul Gray si sa urmarim modificarile date de schimbarea unui bit in evaluare. Dam mai jos rezolvarea eleganta si usor de inteles a lui Mircea Pasoi:\r\n\r\n== code(cpp) |\r\n#include <stdio.h>\r\n\r\nint N, M, G[ 33 ][ 20 ], V[ 33 ], V2[ 33 ], Res;\r\n\r\ninline int GRAY(int x)\r\n{\r\n    return x ^ ( x >> 1 );\r\n}\r\n\r\ninline int BIT(int a, int b)\r\n{\r\n    return (a & (1 << b)) > 0;\r\n}\r\n\r\ninline int MIN(int a, int b)\r\n{\r\n    return (a < b) ? a : b;\r\n}\r\n\r\ninline int MAX(int a, int b)\r\n{\r\n    return (a > b) ? a : b;\r\n}\r\n\r\ninline int SORTED(int x)\r\n{\r\n    return (x & (x+1)) == 0;\r\n}\r\n\r\nint works(int n, int a)\r\n{\r\n    int i, b, t;\r\n\r\n    V2[0] = n;\r\n    for (i = 0; i < M; i++)\r\n    {\r\n        b = G[i][a];\r\n        if ((BIT(V[i], MAX(a, b)) && !BIT(V[i], MIN(a, b))) ||\r\n            (BIT(V2[i], MAX(a, b)) && !BIT(V2[i], MIN(a, b))))\r\n            a = b;\r\n        V[i] = V2[i];\r\n        V2[i+1] = V[i+1]^(1<<a);\r\n    }\r\n    V[M] = V2[M];\r\n\r\n    return SORTED(V[M]);\r\n}\r\n\r\nint main(void)\r\n{\r\n    int i, j, k, a, b, bit;\r\n\r\n    freopen(\"sortnet.in\", \"r\", stdin);\r\n    freopen(\"sortnet.out\", \"w\", stdout);\r\n\r\n    scanf(\"%d %d\\n\", &N, &M);\r\n    for (i = 0; i < M; i++)\r\n        for (j = 0; j < N/2; j++)\r\n        {\r\n            scanf(\"<%d,%d> \", &a, &b);\r\n            a--; b--;\r\n            G[i][a] = b; G[i][b] = a;\r\n        }\r\n\r\n    Res = 1;\r\n    for (i = 1; i < (1 << N); i++) \r\n    {\r\n        k = GRAY(i) ^ GRAY(i-1);\r\n        for (bit = 0; (1<<bit) < k; bit++);\r\n        Res += works(GRAY(i), bit);\r\n    }\r\n    printf(\"%d\\n\", Res);\r\n\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#biblio). Bibliografie\r\n\r\n# D.E.Knuth TAOC Prefascicle 2A\r\n# W.H. Press et. all. Numerical Recipies in C, Cambridge University Press\r\n# \'Gray code, wikipedia\':http://en.wikipedia.org/wiki/Gray_code\r\n',3146,'public',NULL,NULL),('tabele-hash-scurta-prezentare','Tabele hash - scurta prezentare','2008-01-30 12:30:09','2008-12-13 18:06:36','h1. Tabele hash - scurta prezentare\r\n\r\n(Categoria _Structuri de date_, Autor _Mihnea Giurgea_)\r\n\r\n(toc){width: 20em}*{text-align:center;} *Continut*\r\n* \'Scopul tabelelor de dispersie\':tabele-hash-scurta-prezentare#scop\r\n* \'Adresare directa\':tabele-hash-scurta-prezentare#adresare_directa\r\n* \'Standard hashing\':tabele-hash-scurta-prezentare#standard_hashing\r\n* \'Functii de hash\':tabele-hash-scurta-prezentare#functii\r\n* \'In loc de concluzie\':tabele-hash-scurta-prezentare#concluzie\r\n\r\nh2(#scop). Scopul tabelelor de dispersie (hash tables)\r\n\r\nNe propunem sa cream o structura de date eficienta care sa poata face urmatoarele operatii cat mai repede posibil: _Insereaza_, _Cauta_ si _Sterge_. Ideea din spatele hashing-ului este memorarea unui element intr-un tablou sau lista, in functie de cheia sa. Pe cazul mediu toate aceste operatii necesita $O(1)$ timp. Sa vedem cum:\r\n\r\nh2(#adresare_directa). Adresare directa\r\n\r\nElementele sunt puse intr-un tablou alocat static pe pozitiile cheilor lor. Prin adresare directa, un element cu cheia $k$ va fi memorat in locatia $k$. Toate cele 3 operatii sunt extrem de simple (necesita doar o accesare de memorie), dar dezavantajul este ca aceasta tehnica \"mananca\" foarte multa memorie: $O(|U|)$, unde $U$ este universul de chei.\r\n\r\nh2(#standard_hashing). Standard hashing\r\n\r\nPrimul pas in a rezolva problema memoriei este de a folosi $O(N)$ memorie in loc de $O(|U|)$, unde $N$ este numarul de elemente adaugate in hash. Astfel, un element cu cheia $k$ nu va fi memorat in locatia $k$, ci $h(k)$, unde $h: U -> {0, 1, ..., N-1}$ - o functie aleasa aleator, dar determinista ({$h(x)$} va returna mereu aceeasi valoare pentru un anumit $x$ in cursul rularii unui program). Daca functia este aleasa aleator, elementele vor fi \"imprastiate\" in hash in mod egal. Ideal ar fi ca fiecare element sa fie stocat singur in locatia lui. Acest lucru insa nu este posibil, pentru ca $N < |U|$ si, deci, de multe ori mai multe elemente vor fi repartizate in aceeasi locatie. Aceasta problema se numeste coliziune.\r\n\r\nCum rezolvam coliziunile?\r\n\r\nh3. Inlantuire\r\n\r\nIn fiecare locatie din hash tinem o lista inlantuita; astfel, la oricare din cele 3 operatii se va parcurge toata lista. Pe un caz pur teoretic, toate cele $N$ elemente ar putea fi repartizate in aceeasi locatie, insa pe cazuri practice lungimea medie a celui mai lung lant este de {$lg(N)$}.\r\n\r\n* Memorie: $O(N)$\r\n* Pointeri: DA\r\n\r\nh3. Liste statice\r\n\r\nAceasta metoda este o imbunatatire a punctului anterior: pentru ca lungimea unui lant este cel mult {$lg(N)$}, putem sa folosim, in loc de liste inlantuite, vectori alocati dinamic de lungime $lg(N)$ - sau {$lg(N) + 3$}, ca sa fim siguri :). Scapam astfel de lucrul cu pointerii.\r\n\r\n* Memorie: $O(N*lg(N))$\r\n* Pointeri: NU\r\n\r\nh3. Adresare deschisa\r\n\r\nPrin adresare deschisa, toate elementele sunt memorate in tabela de hash. Pentru a realiza operatiile cerute, verificam succesiv tabela de hash pana cand fie gasim o locatie libera (in cazul _Inserarii_), fie gasim elementul cautat (pentru _Cauta_, _Sterge_). Insa, in loc sa cautam tabela de hash in ordinea $0, 1, ..., N-1$, sirul de pozitii examinate depinde de cheia ce se insereaza. Pentru a determina locatiile corespunzatoare, extindem functia de hash astfel incat sa contina si numarul de verificare ca un al doilea parametru $h: U * {0, 1, ..., N-1} -> {0, 1, ..., N-1}$. Astfel, cand vom insera un element, verificam mai intai locatia {$h(k, 0)$}, apoi {$h(k, 1)$} etc. Cand ajungem sa verificam {$h(k, N)$} putem sa ne oprim pentru ca tabela de hash este plina. Pentru cautare aplicam aceeasi metoda; daca ajungem la {$h(k, N)$} sau la o pozitie goala, inseamna ca elementul nu exista. Stergerile se fac insa mai greu, pentru ca nu se poate \"sterge\" pur si simplu un element deoarece ar strica tot hash-ul. In schimb, se marcheaza locatia ce trebuie stearsa cu o valoare $STERS$ si se modifica functia _Insereaza_ astfel incat sa vada locatiile cu valoarea $STERS$ ca pozitii goale.\r\n\r\n* Memorie: $O(N)$\r\n* Pointeri: NU\r\n\r\nh3. Double hashing-ul lui Mihai Patrascu\r\n\r\nO imbunatatire foarte mare la tabela de hashing este... inca o tabela de hashing. Vom avea 2 tabele, fiecare cu propria ei functie de hash, iar coliziunile le rezolvam prin inlantuire; cand inseram un element, il vom adauga in tabela in care intra intr-un lant mai scurt. Cautarea se face in ambele tabele in locatiile returnate de cele 2 functii de hash; stergerea la fel. Astfel, lungimea celui mai lung lant va fi, in medie, {$lg(lg(N))$}. Dar, in practica, lungimea unui astfel de lant nu va depasi $4$ elemente, pentru ca cel mai mic $N$ pentru care $lg(lg(N)) = 5$ este {$2^32^ ~ 4.000.000.000$}!!! Deci, in loc de liste folosim vectori statici de dimensiune $4$.\r\n\r\n* Memorie: $O(N)$\r\n* Pointeri: NU\r\n\r\nh2(#functii). Functii de hash\r\n\r\nToate functiile de hash intorc un numar intre $0$ si {$M-1$}, unde $M$ este dimensiunea maxima a tabelei de hash. Este recomandat ca $M$ sa fie ales un numar prim si sa se evite alegerea lui {$M=2^k^$}.\r\n\r\nh3. Pentru numere intregi:\r\n\r\n* $h(x) = x % M$\r\n* {$h(x) = (x * r) % M$}, $r$ - numar aleator ales la inceputul programului\r\n\r\nh3. Pentru numere reale\r\n\r\n* {$h(x) = [ {A * x} * M ]$}, $0 < A < 1$\r\n\r\n${x}$ - partea fractionara a lui $x$\r\n$[x]$ - partea intreaga a lui $x$\r\n$[x] + {x} = x$ - prin definitie\r\n$A$ este un numar care trebuie ales inainte sau la inceputul rularii programului. Alegerea lui influenteaza eficienta functiei. Knuth propune valoarea <tex>A = \\frac{(\\sqrt{5}-1)}{2} \\approx 0.6180339887...</tex>\r\n\r\nh3. Pentru adresarea deschisa\r\n\r\n* $h(x, i) = (h\'(x) + i) % M$\r\n* $h(x, i) = (h\'(x) + r1 * i + r2 * i^2^) % M$\r\n* $h(x, i) = (h1(x) + i * h2(x)) % M$\r\n$r1$, $r2$ - numere alese aleator la inceputul programului.\r\n\r\nh2(#concluzie). In loc de concluzie\r\n\r\nDesi o tabela hash poate fi implementata in diverse moduri (cu pointeri sau fara, cu mai multa sau mai putina memorie etc), nu pentru toate situatiile e la fel de usor de ales o functia eficienta. Implementarile mai complexe necesita mai multe sapaturi dupa functii bune. Iar de multe ori se prefera implementari concise si clare in locul celor stufoase care maresc eficienta, dar nu suficient. De aceea, cel mai frecvent mod de tratare al coliziunilor ramane inlantuirea. Mai multe detalii despre acesta, precum si anumite precizari despre cum sa alegi o functie hash buna in cazul diverselor tipuri de date, gasiti in articolul \'Tabele hash - prezentare detaliata\':tabele-hash-prezentare-detaliata preluat din cartea \"Psihologia concursurilor de informatica\" a lui Catalin Francu. In acelasi articol gasiti si o lista de aplicatii pentru aceasta structura de date eficienta.',2044,'public',NULL,NULL),('heapuri','Heap-uri','2008-01-18 16:31:03','2009-01-08 08:05:57','h1. Heap-uri\r\n\r\n== include(page=\"template/implica-te/scrie-articole-2\" user_id1=\"Cyber\" user_id2=\"silviug\") ==\r\n\r\n(Categoria _Structuri de date_, Autor _Catalin Francu_, Versiunea originala preluata din cartea _\"Psihologia concursurilor de informatica\"_)\r\n\r\n(toc){width: 30em}*{text-align:center;} *Continut*\r\n* \'Definirea notiunii de _heap_\':heapuri#definire\r\n* \'Structura de heap si metode ajutatoare\':heapuri#structura\r\n* \'Cautarea maximului\':heapuri#cautarea-maximului\r\n* \'Crearea unei structuri de heap dintr-un vector oarecare\':heapuri#creare-heap\r\n* \'Eliminarea unui element, stiind pozitia lui in heap\':heapuri#stergere\r\n* \'Inserarea unui element\':heapuri#inserare\r\n* \'Sortarea unui vector (heapsort)\':heapuri#heapsort\r\n* \'Cautarea unui element\':heapuri#cautare\r\n* \'Alternative STL\':heapuri#stl\r\n* \'Aplicatii\':heapuri#aplicatii\r\n\r\nIn acest articol vom prezenta structura de date numita $heap$, cum poate fi aceasta implementata, precum si alternative STL. Desi este putin probabil sa ajungeti sa implementati heap-urile de la \"zero\" daca stiti STL, consideram ca prezentarea acestora nu este de prisos. Aici atingem problema mai generala \"de ce trebuie sa inteleg X (poate fi vorba de un algoritm, o structura de date, s.a.m.d.) daca il am deja implementat?\". Iata cateva motive:\r\n\r\n* va antreneaza mintea\r\n* va veti putea descurca in situatii in care aveti nevoie de o structura de date asemanatoare, dar nu la fel\r\n* veti fi utilizatori informati ai bibliotecii STL\r\n* veti intelege cand este bine sa folositi o structura de date si cand nu\r\n* veti avea avantajul de a sti precis de ce operatiile de baza au anumite complexitati\r\n\r\nAcum ca avem o motivatie, sa studiem impreuna heap-urile.\r\n\r\nh2(#definire). Definirea notiunii de _heap_\r\n\r\nUn heap ({_engl._} gramada) este un vector care poate fi privit si ca un arbore binar, asa cum se vede in figura de mai jos:\r\n\r\n!heapuri?heap.JPG!\r\n\r\nLanga fiecare nod din arbore se afla cate un numar, reprezentand pozitia in vector pe care ar avea-o nodul respectiv. Pentru cazul considerat, vectorul echivalent ar fi {$H = (12 10 11 10 7 9 3 2 8 1 4 3)$}.\r\n\r\nSe observa ca nodurile sunt parcurse de la stanga la dreapta si de sus in jos. O proprietate necesara pentru ca un arbore binar sa se poata numi $heap$ este ca toate nivelurile sa fie complete, cu exceptia ultimului, care se completeaza incepand de la stanga si continuand pana la un anume punct. De aici deducem ca inaltimea unui heap cu $N$ noduri este <tex> h=[\\log_2 N] </tex> (reamintim ca inaltimea unui arbore este adancimea maxima a unui nod, considerand radacina drept nodul de adancime $0$). Reciproc, numarul de noduri ale unui heap de inaltime $h$ este <tex> N\\in [2^h, 2^{h+1}-1]</tex>.\r\n\r\nTot din aceasta organizare mai putem deduce ca tatal unui nod $k > 1$ este nodul $[k/2]$, iar fiii nodului $k$ sunt nodurile $2k$ si $2k+1$. Daca $2k = N$, atunci nodul $2k+1$ nu exista, iar nodul $k$ are un singur fiu; daca $2k > N$, atunci nodul $k$ este frunza si nu are niciun fiu. Exemple: tatal nodului $5$ este nodul $2$, iar fiii sai sunt nodurile $10$ si $11$. Tatal nodului $6$ este nodul $3$, iar unicul sau fiu este nodul $12$. Tatal nodului $9$ este nodul $4$, iar fii nu are, fiind frunza in heap.\r\n\r\nDar cea mai importanta proprietate a heap-ului, cea care il face util in operatiile de aflarea a maximului, este aceea ca valoarea oricarui nod este mai mare sau egala cu valoarea oricarui fiu al sau. Dupa cum se vede mai sus, nodul $2$ are valoarea $10$, iar fiii sai - nodurile $4$ si $5$ - au valorile $10$ si respectiv $7$. Intrucat operatorul $&ge;$ este tranzitiv, putem trage concluzia ca un nod este mai mare sau egal decat oricare din nepotii sai si, generalizand, va rezulta ca orice nod este mai mare sau egal decat toate nodurile din subarborele a carui radacina este.\r\n\r\nAceasta afirmatie nu decide in niciun fel intre valorile a doua noduri dispuse astfel incat niciunul nu este descendent al celuilalt. Cu alte cuvinte, nu inseamna ca orice nod de pe un nivel mic are valoare mai mare decat nodurile mai apropiate de frunze. Este cazul nodului $7$, care are valoarea $3$ si este mai mic decat nodul $9$ de valoare $8$, nod asezat totusi mai jos in heap. In orice caz, o prima concluzie care rezulta din aceasta proprietate este ca radacina are cea mai mare valoare din tot heap-ul.\r\n\r\nStructura de heap permite efectuarea multor operatii intr-un timp foarte bun:\r\n\r\n* Cautarea maximului in $O(1)$\r\n* Crearea unei structuri de heap dintr-un vector oarecare in $O(N)$\r\n* Eliminarea unui element in $O(log N)$\r\n* Inserarea unui element in $O(log N)$\r\n* Sortarea elementelor din heap in $O(N log N)$\r\n\r\nMentionam ca operatia de cautare a unui element are complexitatea $O(N)$ dar, de obicei, heap-ul nu este folosit cand acest tip de operatii este frecvent.\r\n\r\nDesigur, toate aceste operatii se fac mentinand permanent structura de heap a arborelui, adica respectand modul de repartizare a nodurilor pe niveluri si plasarea mai sus a elementelor de valoare mai mare. Este de la sine inteles ca datele nu se vor reprezenta in memorie in forma arborescenta, ci in cea vectoriala.\r\n\r\nPrecizam de asemenea ca heap-ul poate fi organizat si pe baza operatorului de $&le;$. In acest caz, in varful heap-ului vom avea minimul dintre elementele pastrate in heap. In functie de operatorul folosit, putem numi structura de date $max-heap$ sau $min-heap$. In continuare vom prezenta operatiile intr-un max-heap, adaptarea lor pentru min-heap-uri fiind usoara.\r\n\r\nh2(#structura). Structura de heap si metode ajutatoare\r\n\r\nIn blocul de cod de mai jos prezentam cum se defineste un heap ca vector si cateva metode ajutatoare:\r\n\r\n==code(cpp) |\r\nconst int MAX_HEAP_SIZE = 16384;\r\ntypedef int Heap[MAX_HEAP_SIZE];\r\n\r\ninline int father(int nod) {\r\n    return nod / 2;\r\n}\r\n\r\ninline int left_son(int nod) {\r\n    return nod * 2;\r\n}\r\n\r\ninline int right_son(int nod) {\r\n    return nod * 2 + 1;\r\n}\r\n==\r\n\r\nh2(#cautarea-maximului). Cautarea maximului\r\n\r\nPractic, operatia aceasta nu are de facut decat sa intoarca valoarea primului element din vector:\r\n==code(cpp) |\r\ninline int max(Heap H) {\r\n    return H[1];\r\n}\r\n==\r\n\r\nh2(#creare-heap). Crearea unei structuri de heap dintr-un vector oarecare\r\n\r\nPentru a discuta acest aspect, vom vorbi mai intai despre doua proceduri specifice heap-urilor, $sift$ ({_engl._} a cerne) si $percolate$ ({_engl._} a se infiltra). Sa presupunem ca un vector are o structura de heap, cu exceptia unui nod care este mai mic decat unul din fiii sai. Este cazul nodului $3$ din figura de mai jos, care are o valoare mai mica decat fiii sai (nodurile $6$ si $7$):\r\n\r\n!heapuri?create1.JPG!\r\n\r\nCe e de facut? Desigur, nodul va trebui coborat in arbore, iar in locul lui vom aduce alt nod, mai exact unul dintre fiii sai. Intrebarea este: care din fiii sai? Daca vom aduce nodul $7$ in locul lui, acesta fiind mai mic decat nodul $6$, anomalia se va pastra. Trebuie deci sa schimbam nodul $3$ cu nodul $6$:\r\n\r\n!heapuri?create2.JPG!\r\n\r\nProblema nu este insa rezolvata, deoarece noul nod $6$, proaspat \"retrogradat\", este inca mai mic decat fiul sau, nodul $12$. De data aceasta avem un singur fiu, deci o singura optiune: schimbam nodul $6$ cu nodul $12$ si obtinem o structura de heap corecta:\r\n\r\n!heapuri?create3.JPG!\r\n\r\nProcedura $sift$ primeste ca parametri un heap $H$ cu $N$ noduri si un nod $K$ si presupune ca ambii subarbori ai nodului $K$ au structura de heap corecta. Misiunea ei este sa \"cearna\" nodul $K$ pana la locul potrivit, interschimband mereu nodul cu cel mai mare fiu al sau pana cand nodul nu mai are fii (ajunge pe ultimul nivel in arbore) sau pana cand fiii sai au valori mai mici decat el.\r\n\r\n==code(cpp) |\r\nvoid sift(Heap H, int N, int K) {\r\n    int son;\r\n    do {\r\n        son = 0;\r\n        // Alege un fiu mai mare ca tatal.\r\n        if (left_son(K) <= N) {\r\n            son = left_son(K);\r\n            if (right_son(K) <= N && H[right_son(K)] > H[left_son(K)]) {\r\n                son = right_son(K);\r\n            }\r\n            if (H[son] <= H[K]) {\r\n                son = 0;\r\n            }\r\n        }\r\n\r\n        if (son) {\r\n            swap(H[K], H[son]);  // Functie STL ce interschimba H[K] cu H[son].\r\n            K = son;\r\n        }\r\n    } while (son);\r\n}\r\n==\r\n\r\nProcedura $percolate$ se va ocupa tocmai de fenomenul invers. Sa presupunem ca un heap are o \"defectiune\" in sensul ca observam un nod care are o valoare mai mare decat tatal sau. Atunci, va trebui sa interschimbam cele doua noduri. Este cazul nodului $10$ din figura care urmeaza. Deoarece fiul care trebuie urcat este mai mare ca tatal, care la randul lui (presupunand ca restul heap-ului e corect) este mai mare decat celalalt fiu al sau, rezulta ca dupa interschimbare fiul devenit tata este mai mare decat ambii sai fii. Trebuie totusi sa privim din nou in sus si sa continuam sa urcam nodul in arbore fie pana ajungem la radacina, fie pana ii gasim un tata mai mare ca el. Iata ce se intampla cu nodul $10$:\r\n\r\n!heapuri?create4.JPG!\r\n\r\n==code(cpp) |\r\nvoid percolate(Heap H, int N, int K) {\r\n    int key = H[K];\r\n\r\n    while ((K > 1) && (key > H[father(K)])) {\r\n        H[K] = H[father(K)];\r\n        K = father(K);\r\n    }\r\n\r\n    H[K] = key;\r\n}\r\n==\r\n\r\nAcum ne putem ocupa efectiv de construirea unui heap. Am spus ca procedura $sift$ presupune ca ambii fii ai nodului pentru care este ea apelata au structura de heap. Aceasta inseamna ca putem apela procedura $sift$ pentru orice nod imediat superior nivelului frunzelor, deoarece frunzele sunt arbori cu un singur nod, si deci heap-uri corecte. Apeland procedura $sift$ pentru toate nodurile de deasupra frunzelor, vom obtine deja o structura mai organizata, asigurandu-ne ca pe ultimele doua niveluri avem de-a face numai cu heap-uri. Apoi apelam aceeasi procedura pentru nodurile de pe al treilea nivel incepand de la frunze, apoi pentru cele de deasupra lor si asa mai departe pana ajungem la radacina. In acest moment, heap-ul este construit. Iata cum functioneaza algoritmul pentru un arbore total dezorganizat:\r\n\r\n!heapuri?create5.JPG!\r\n\r\np{padding-left: 4em}. _Nivelul frunzelor este organizat_\r\n\r\n!heapuri?create6.JPG!\r\n\r\np{padding-left: 3em}. _Ultimele doua niveluri sunt organizate_\r\n\r\n!heapuri?create7.JPG!\r\n\r\np{padding-left: 3.5em}. _Ultimele trei niveluri sunt organizate_\r\n\r\n!heapuri?create8.JPG!\r\n\r\np{padding-left: 7em}. _Structura de heap_\r\n\r\n==code(cpp) |\r\nvoid build_heap(Heap H, int N) {\r\n    for (int i = N / 2; i > 0; --i) {\r\n        sift(H, N, i);\r\n    }\r\n}\r\n==\r\n\r\nS-a apelat caderea incepand de la al $N / 2$ - lea nod, deoarece acesta este ultimul nod care mai are fii, restul cu indici mai mari fiind frunze. Sa calculam acum complexitatea acestui algoritm. Un calcul sumar ar putea spune: exista $N$ noduri, fiecare din ele se \"cerne\" pe $O(log N)$ niveluri, deci timpul de constructie a heap-ului este $O(N log N)$. Totusi nu este asa. Presupunem ca ultimul nivel al heap-ului este plin. In acest caz, jumatate din noduri vor fi frunze si nu se vor cerne deloc. Un sfert din noduri se vor afla deasupra lor si se vor cerne cel mult un nivel. O optime din noduri se vor putea cerne cel mult doua niveluri, si asa mai departe, pana ajungem la radacina care se afla singura pe nivelul ei si va putea cadea maxim $h$ niveluri (reamintim ca <tex> h=[\\log_2 N] </tex>). Rezulta ca timpul total de calcul este dat de formula <tex>O(\\displaystyle {\\sum_{k=1}^{[\\log_2 N]} k} \\times \\frac{N}{2^{k+1}}) = O(N)</tex>. Demonstrarea egalitatii se poate face facand substitutia $N = 2^h^$ si continuand calculele. Se va obtine tocmai complexitatea $O(2^h^)$. Lasam aceasta verificare ca tema cititorului.\r\n\r\nh2(#stergere). Eliminarea unui element, stiind pozitia lui in heap\r\n\r\nDaca eliminam un element din heap, trebuie numai sa refacem structura de heap. In locul nodului eliminat s-a creat un gol, pe care trebuie sa il umplem cu un alt nod. Care ar putea fi acela? Intrucat trebuie ca toate nivelurile sa fie complet ocupate, cu exceptia ultimului, care poate fi gol numai in partea sa dreapta, rezulta ca singurul nod pe care il putem pune in locul celui eliminat este ultimul din heap. O data ce l-am pus in gaura facuta, trebuie sa ne asiguram ca acest nod \"de umplutura\" nu strica proprietatea de heap. Deci vom verifica: daca nodul pus in loc este mai mare ca tatal sau, vom apela procedura $percolate$. Altfel vom apela procedura $sift$, in eventualitatea ca nodul este mai mic decat unul din fiii sai. Iata exemplul de mai jos:\r\n\r\n!heapuri?delete1.JPG!\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nSa presupunem ca vrem sa eliminam nodul de valoare $9$, aducand in locul lui nodul de valoare $X$. Insa $X$ poate fi orice numar mai mic sau egal cu $18$. Spre exemplu, $X$ poate fi $16$, caz in care va trebui urcat deasupra nodului de valoare $10$, sau poate fi $1$, caz in care va trebui cernut pana la nivelul frunzelor. Deoarece caderea si urcarea se pot face pe cel mult $[log N]$ niveluri, rezulta o complexitate a procedeului de $O(log N)$.\r\n\r\n==code(cpp) |\r\nvoid cut(Heap H, int& N, int K) {\r\n    H[K] = H[N];\r\n    --N;\r\n\r\n    if ((K > 1) && (H[K] > H[father(K)])) {\r\n        percolate(H, N, K);\r\n    } else {\r\n        sift(H, N, K);\r\n    }\r\n}\r\n==\r\n\r\nh2(#inserare). Inserarea unui element\r\n\r\nDaca vrem sa inseram un nou element in heap, lucrurile sunt mult mai simple. Nu avem decat sa-l asezam pe a $N + 1$ - a pozitie in vector si apoi sa-l \"promovam\" pana la locul potrivit. Din nou, urcarea se poate face pe maxim $[log N]$ niveluri, de unde complexitatea logaritmica.\r\n\r\n==code(cpp) |\r\nvoid insert(Heap H, int& N, int key) {\r\n    H[++N] = key;\r\n    percolate(H, N, N);\r\n}\r\n==\r\n\r\nh2(#heapsort). Sortarea unui vector (heapsort)\r\n\r\nAcum ca am stabilit toate aceste lucruri, ideea algoritmului de sortare vine de la sine. Incepem prin a construi un heap. Apoi extragem maximul (adica varful heap-ului) si refacem heap-ul. Cele doua operatii luate la un loc dureaza $O(1) + O(log N) = O(log N)$. Apoi extragem din nou maximul (care va fi al doilea element ca marime din vector) si refacem din nou heap-ul. Din nou, complexitatea operatiei compuse este $O(log N)$. Daca facem acest lucru de $N$ ori, vom obtine vectorul sortat intr-o complexitate de $O(N log N)$.\r\n\r\nPartea cea mai frumoasa a acestui algoritm este ca el nu foloseste deloc memorie suplimentara. Iata explicatia: cand heap-ul are $N$ elemente, vom extrage maximul si il vom tine minte undeva in memorie. Pe de alta parte, in locul maximului (adica in radacina arborelui) trebuie adus ultimul element al vectorului, adica $H[N]$. Dupa aceasta operatie, heap-ul va avea $N - 1$ noduri, al $N$-lea ramanand liber. Ce alt loc mai inspirat decat acest al $N$-lea nod ne-am putea dori pentru a stoca maximul? Practic, am interschimbat radacina, adica pe $H[&#49;]$ cu $H[N]$. Acelasi lucru se face la fiecare pas, tinand cont de micsorarea permanenta a heap-ului.\r\n\r\n==code(cpp) |\r\nvoid heapsort(Heap H, int N) {\r\n    build_heap(H, N);\r\n\r\n    // Sorteaza vectorul.\r\n    for (int i = N; i >= 2; --i) {\r\n        swap(H[1], H[i]);\r\n        sift(H, i - 1, 1);\r\n    }\r\n}\r\n==\r\n\r\nh2(#cautare). Cautarea unui element\r\n\r\nAceasta operatie este singura care nu poate fi optimizata (in sensul reducerii complexitatii sub $O(N)$). Aceasta deoarece putem fi siguri ca un nod mai mic este descendentul unuia mai mare, dar nu putem sti daca se afla in subarborele stang sau drept; din aceasta cauza, nu putem face o cautare binara. Totusi, o oarecare imbunatatire se poate aduce fata de cautarea secventiala. Daca radacina unui subarbore este mai mica decat valoarea cautata de noi, cu atat mai mult putem fi convinsi ca descendentii radacinii vor fi si ei mai mici, deci putem sa renuntam la a cauta acea valoare in tot subarborele. In felul acesta, se poate intampla ca bucati mari din heap sa nu mai fie explorate inutil. Pe cazul cel mai defavorabil, insa, parcurgerea intregului heap este necesara. Lasam scrierea unei proceduri de cautare pe seama cititorului.\r\n\r\nh2(#stl). Alternative STL\r\n\r\nDesi nu sunt greu de implementat, avem vesti bune pentru programatorii in C++: heap-urile sunt deja implementate in STL. Containerul se numeste \'$priority_queue$\':http://www.sgi.com/tech/stl/priority_queue.html si implementeaza toate operatiile prezentate, mai putin operatiile de cautare a unei valori si de stergere a unui nod. Aceste doua operatii sunt destul de atipice pentru o coada de prioritati si in general nu sunt asociate cu aceasta structura de date in cartile de algoritmi.\r\n\r\nTotusi, in unele aplicatii avem nevoie de o structura de date care suporta toate operatiile amintite in timp cel mult logaritmic (inclusiv stergerea si cautarea unei valori). Aceasta structura exista deja in STL: $set$-urile. Acestea sunt de fapt multimi mentinute ca arbori binari echilibrati. Singurele dezavantaje sunt ca de obicei merg mai incet decat cozile de prioritate si folosesc mai multa memorie.\r\n\r\nDaca nu sunteti familiari cu aceste structuri de date, va recomandam sa cititi paginile lor de documentatie: \'$priority_queue$\':http://www.sgi.com/tech/stl/priority_queue.html, \'$set$\':http://www.sgi.com/tech/stl/set.html si \'$multiset$\':http://www.sgi.com/tech/stl/multiset.html. Daca nu intelegeti totul de la inceput (pentru ca nu stiti clase si template-uri in C++), uitati-va pe exemple si pe lista de functii membre si invatati cum se folosesc.\r\n\r\nIn continuare vom ilustra cum putem implementa operatiile de extragere a maximului, extragere a minimului, inserare, stergere si cautare folosind un $multiset$. Vom folosi un $multiset$ pentru ca toate copiile unui numar vor fi pastrate daca el va fi inserat de mai multe ori (spre deosebire de $set$, care il va pastra o singura data). Va recomandam cu caldura sa copiati codul pe calculatorul vostru si sa experimentati cu el pentru a vedea ce afiseaza si a intelege ce se intampla.\r\n\r\n==code(cpp) |\r\n#include <set>\r\nusing namespace std;\r\n\r\nint main() {\r\n    multiset <int> my_set;\r\n    my_set.insert(1); // Insereaza o valoare.\r\n    my_set.insert(1);\r\n\r\n    if (my_set.find(1) != my_set.end()) { // Cauta o valoare.\r\n        printf(\"Am gasit 1 in set!\\n\");\r\n    } else {\r\n        printf(\"1 nu se afla set!\\n\");\r\n    }\r\n\r\n    // Sterge o valoare din set. Daca aceasta se afla de\r\n    // mai multe ori in set, este stearsa numai o copie.\r\n    my_set.erase(my_set.find(1));\r\n    printf(\"Exista %d elemente in set\\n\", my_set.size());\r\n\r\n    my_set.insert(1);\r\n    my_set.insert(1);\r\n\r\n    // Sterge o valoare din set. Daca aceasta se afla de\r\n    // mai multe ori in set, sunt sterse toate copiile.\r\n    my_set.erase(1);\r\n    printf(\"Exista %d elemente in set\\n\", my_set.size());\r\n\r\n    my_set.insert(1);\r\n    my_set.insert(-3);\r\n    my_set.insert(7);\r\n\r\n    // Valoarea minima.\r\n    multiset <int> :: iterator it = my_set.begin();\r\n    printf(\"Valoarea cea mai mica din set este %d\\n\", *it);\r\n\r\n    // Valoarea maxima.\r\n    it = my_set.end();\r\n    --it;\r\n    printf(\"Valoarea cea mai mare din set este %d\\n\", *it);\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#aplicatii). Aplicatii\r\n\r\n* \'Dijkstra cu heap-uri\':http://infoarena.ro/problema/dijkstra\r\n* \'Magnetic storms\':http://acm.timus.ru/problem.aspx?space=1&num=1126\r\n* \'Manager\':http://acm.tju.edu.cn/toj/showp1675.html\r\n* \'Supermarket\':http://acm.tju.edu.cn/toj/showp1681.html\r\n* Sea - Baraj ONI 2004 (Autor: Radu Berinde)\r\n* Interclasati $K$ vectori sortati. (Sugestie: complexitatea dorita este $O(N * log K)$, unde $N$ este lungimea sirului rezultat prin interclasare)\r\n* Determinati cele mai mici $K$ elemente dintr-un sir cu $N$ elemente cand dispuneti de memorie mult mai putina ca $O(N)$. ({$K$} este mult mai mic decat $N$)\r\n\r\nh2. Discutii pe forum',2044,'public',3528,NULL),('al-k-lea-drum-minim','Al K-lea drum minim','2004-11-29 00:00:00','2008-12-13 19:02:35','h1. Al K-lea drum minim\r\n\r\n(Categoria _Algoritmi_, Autor _Leonard Crestez_)\r\n\r\nExista un numar mare de algoritmi pentru a calcula cel mai scurt drum intre $2$ noduri intr-un graf, dar chiar si al {$2$}-lea cel mai scurt drum este o extindere non-triviala. Pentru a afla al {$k$}-lea drum minim se foloseste un algoritm total diferit fata de cei pentru drum minim. Algoritmul este dificil de implementat, iar sursa rezultata este de obicei voluminoasa, asa ca acest algoritm nu prea intervine in problemele de concurs. Am considerat totusi ca este destul de interesant, si merita prezentat.\r\n\r\nO nota importanta este ca nu se determina drumul cu al {$k$}-lea cost. Doua drumuri se considera diferita daca au noduri diferite, nu neaparat si cost diferit. Astfel, daca exista $5$ drumuri distincte de cost minim, oricare dintre ele poate fi solutie pentru al {$4$}-lea sau al {$5$}-lea drum minim. Astfel, aceasta problema are de fapt mai multe solutii posibile.\r\n\r\nExista $2$ cazuri pentru aceasta problema, iar algoritmul prezentat necesita mici modificari pentru a se adapta, dar ideea de baza ramane aceeasi. Cele doua cazuri sunt daca drumul trebuie neaparat sa fie elementar sau nu. Cazul in care se accepta doar drumuri elementare este mai restrictiv, si, astfel, un pic mai dificil.\r\n\r\nh2. Mod de functionare\r\n\r\nDaca pentru drumul minim intre $2$ noduri de obicei se calculeaza drumul minim dintre primul nod si celelalte noduri din graf, pentru a afla al {$k$}-lea drum minim se calculeaza toate primele $k - 1$ drumuri minime, in ordine. Un pas al algortimului consta in aflarea celul de-al {$k$}-lea drum minim cand primele $k$ sunt cunoscute. Drumul minim este folosit de mai multe ori in algoritm, pentru a intelege acest algoritm este necesara o anumita familiaritate cu algoritmul lui Dijkstra.\r\n\r\nDrumurile minime pana la $k-1$ sunt stocate compactate intr-un arbore de drumuri. Fiecarui nod din acel arbore ii corespunde un nod din graf, dar nu si invers, un nod din graf poate aparea de mai multe ori in arbore. Radacina arborelui corespunde nodului de start, iar toate frunzele arborelui corespund nodului de final, iar drumurile de la radacina catre frunze reprezinta fiecare cate un drum minim. Vezi in figura cum se compacteaza drumurile ({$1, 7, 4, 5$}), ({$1, 7, 3, 5$}), ({$1, 2, 4, 5$}) si ({$1, 2, 6, 4, 5$}). Drumurile sunt primele $4$ drumuri din graful desenat mai sus si luat drept exemplu.\r\n\r\n!Al-K-lea-drum-minim?kshortest_graph.png!\r\n!Al-K-lea-drum-minim?kshortest_tree.png!\r\n\r\nAl {$k$}-lea drum minim trebuie sa corespund pana intr-un anumit punct cu un drum aflat deja in arbore, chiar daca punctul acela este de fapt nodul de start. Pentru a gasi urmatorul drum minim, incercam sa \"deviem\" din fiecare nod din arbore. Un drum de deviatie pentru un anume nod $X$ este un drum identic cu drumul de la radacina pana la nodul {$X$}, care apoi continua (deviaza) pe cel mai scurt drum pana la destinatie care nu a fost inca luat in cosiderare. Spre exemplu pentru nodul $4$ din drumul ({$1, 2, 4, 5$}) putem sa deviem din $4$ prin ({$7, 3, 5$}), formand drumul ({$1, 2, 4, 7, 3, 5$}). Este intuitiv ca, la fiecare pas, pentru fiecare nod din arbore este interesant doar cel mai scurt drum de deviatie.\r\n\r\nAlgoritmul mentine o multime, eventual ca un heap, de deviatii. Se tine pentru fiecare drum de deviatie nodul din care deviaza si lungimea drumului. La fiecare pas extragem drumul de deviatie minim si reconstituim drumul. Sa zicem ca drumul scos din heap este ({$a{~1~} a{~2~} ... a{~d~}, a{~d+1~} ... a{~n~}$}), unde $a{~d~}$ este nodul de unde s-a facut deviatia. Introducem acest drum in arborele de drumuri, si pentru fiecare nod de la $a{~d~}$ la $a{~n-1~}$ calculam deviatia minima si o introducem in heap. Pentru restul nodurilor este evident ca deviatia minima nu se modifica.\r\n\r\nAlgoritmul odata inteles este relativ logic. Al {$k$}-lea drum minim trebuie sa coincida cu unul dintre cele $k-1$ drumuri deja existente pana intr-un anumit punct, dupa care \"ia un viraj\" nevizitat si continua cel mai scurt drumul inca neparcurs.\r\n\r\nDupa cum am zis mai sus, algoritmul are $2$ variante, daca este necesar ca drumurile sa fie elementare sau nu. Pentru cele $2$ variante se modifica modul in care se calculeaza deviatia minima dintr-un nod. Cazul cel mai simplu este atunci cand nu este necesar ca drumurile sa fie elementare. Pentru nodul $X$ din care trebuie sa deviem, vom lua cel mai scurt drum care inca nu este in arbore. Putem sa calculam de dinainte un arbore de drumuri inversat, de la toate nodurile la destinatie, si sa luam minimul de la nodurile adiacente care NU sunt printre copii in arbore. Pentru arborele din desen, daca ar fi sa deviem din ({$1, 2$}) am putea lua in considerare doar nodul {$1$}.\r\n\r\nDaca trebuie sa luam in considerare doar drumurile elementare, algoritmul simplu de mai sus da erori. Spre exemplu, daca ar fi sa deviem din ({$1, 7$}) in desen, drumul optim ar fi prin {$1$}, adica ({$1, 7, 1, 7, 4, 5$}), care drum nu este elementar. Pentru a genera doar drumurile elementare, este nevoie sa marcam nodurile de la radacina pana la deviatie ca \"ocupate\" si sa rulam un algoritm de drum minim pana la destinatie. Acest lucru creste foarte mult complexitatea in timp si in implementare.\r\n\r\nh2. Exemplu\r\n\r\nAlgoritmul prezentat este destul de complex, asa ca vom detalia rularea algoritmului pe graful din desen. Vom incerca sa calculam toate cele mai scurte $5$ drumuri elementare intre nodurile $1$ si {$5$}. Punem si conditia ca drumurile sa fie elementare (cazul mai dificil).\r\n\r\n* Primul drum minim este ({$1, 7, 4, 5$}), de lungime {$9$}.\r\n* Incercam sa deviem din {$1$}. Drumul minim de la $1$ la $5$ care nu trece imediat prin $7$ este ({$1, 2, 4, 5$}), cu cost {$10$}.\r\n* Incercam sa deviem din {$7$}. Drumul minim de la $7$ la $5$ care nu trece imediat prin $4$ este ({$7, 3, 5$}), cu cost {$10$}. Atentie, adaugam si costul de la $1$ la {$7$}.\r\n* Incercam sa deviem din {$4$}. Nu exista alt drum de la {$4$} la {$5$}. Ar putea fi drumul ({$4, 7, 3, 5$}), dar nu ar fi elementar, deoarece avem prefixul ({$1, 7$}), noduri pe care le-am marcat blocate.\r\n* Din $5$ nu are sens sa deviem, asa ca..\r\n* Al doilea drum minim este ({$1, 2, 4, 5$}), de lungime {$10$}.\r\n* Incercam sa deviem din {$1$}, dar nu exista drum de la $1$ la $5$ care sa nu o ia imediat nici prin $2$ si nici prin {$7$}.\r\n* Incercam sa deviem din {$2$}. Drumul minim de la $2$ la $5$ care nu trece imediat prin $4$ este ({$2, 6, 4, 5$}), cu cost {$10$}. Atentie, drumul trece prin {$4$}, dar nu imediat.\r\n* Incercam sa deviam din {$4$}. Drumul minim de la $4$ la $5$ care nu trece imediat prin $5$ este ({$4, 7, 3, 5$}), cu cost {$15$}. Acest drum nu a fost valid mai inainte, dar acum prefixul lui $4$ este ({$1, 2$}), asa ca drumul e valid.\r\n* Al treilea drum minim este ({$1, 7, 3, 5$}), tot de lungime {$10$}. Al doilea si al treilea drum minim sunt interschimbabile.\r\n* Acest drum a fost derivat din {$7$}, asa ca nu trebie incercam sa derivam din {$1$}.\r\n* Incercam sa deviem din {$7$}, dar nu exista drum de la $7$ la $5$ care sa nu treaca imediat nici prin $3$ nici prin {$4$}. Ar fi ({$7, 1, 2, 4, 5$}), dar avem $1$ ca prefix si marcat blocat. Astfel, evitam un drum neelementar.\r\n* Incercam sa deviem din {$3$}, fara succes(si fara explicatii kilometrice.).\r\n* Al patrulea drum minim este ({$1, 2, 6, 4, 5$}), de lungime {$11$}.\r\n* Incercam sa deviem din {$2$}, dar fara succes.\r\n* Incercam sa deviem din {$6$}, dar tot fara succes.\r\n* Incercam sa deviam din {$4$}. Drumul minim de la $4$ la $5$ care nu trece imediat prin $5$ este ({$4, 7, 3, 5$}), cu cost {$16$}. Noi am mai gasit odata acest drum, dar de data asta e cu un alt prefix, si alt cost. Drumul complet este ({$1, 2, 6, 4, 7, 3, 5$}), nu ({$1, 2, 4, 7, 3, 5$}).\r\n* Al cincilea drum minim este ({$1, 2, 4, 7, 3, 5$}), de lungime {$15$}.\r\n* Astfel se termina exemplul nostru. Puteti sa incercati, nu mai exista deviatii posibile. Al {$6$}-lea si ultimul drum este ({$1, 2, 6, 4, 7, 3, 5$}) , care se intample sa fie si cel mai lung drum, si hamiltonian.\r\n\r\nh2. Analiza complexitatii\r\n\r\nComplexitatea algoritmului este diferita in cele $2$ variante. In ambele cazuri putem considera la lugimea fiecarui drum este de {$O(n)$}, si ca heap-ul contine $O(k * n)$ valori. Luam cazul cel mai defavorabil, cu graf complet, si consideram ca un algoritm de drumuri minime necesita timp {$O(n * n)$}. Astfel, daca nu este nevoie ca drumurile sa fie elementare:\r\n\r\n* Precalculam drumurile de la orice nod la destinatie, {$O(n * n)$}.\r\n* La fiecare dintre cei k pasi.\r\n** Extragem din heap, $O(log(k * n))$\r\n** Reconstituim drumul, $O(n)$\r\n** Pentru fiecare dintre cele maxim $n$ noduri din drum:\r\n*** Vedem cel mai scurt drum de continuare, $O(n)$\r\n*** Il adaugam in heap, $O(log(k * n))$\r\n\r\nComplexitatea ajunge astfel la {$O(k * n * (n + log(k * n)))$}. Trebuie avut in vedere ca in general drumurile minime vor avea noduri relativ putine, asa ca algorimtul e mai rapid decat pare. Daca punem conditia ca drumurile determinate sa fie elementare, complexitatea creste:\r\n\r\n* La fiecare dintre cei $k$ pasi.\r\n** Extragem din heap, $O(log(k * n))$\r\n** Reconstituim drumul, $O(n * n)$ (il calculam iarasi)\r\n** Blocam nodurile de la start pana la nodul de deviatie, $O(n)$\r\n** Pentru fiecare dintre cele maxim $n$ noduri din drum:\r\n*** Vedem cel mai scurt drum de continuare, $O(n * n)$\r\n*** Il adaugam in heap, $O(log(k * n))$\r\n\r\nComplexitatea ajunge acum la {$O(k * n * (n * n + log(k * n)))$}, aproximativ {$O(k * n^3^)$}. Iarasi, algoritmul se comporta mai bine in practica decat pare in complexitate.\r\n\r\nh2. Observatii, indicatii, completari\r\n\r\nAlgoritmul poate fi mai incet sau mai rapid. Se poate folosi ceva mai simplu de implementat in loc de heap, sau un algoritm de drumuri minime mai evoluat. Daca va intrebati daca algoritmul poate fi folosit pentru a determina un drum hamiltonian, raspunsul este da, dar asta necesita determinarea tuturor drumurile lor dintre $2$ muchii, care este exponential in functie de {$n$}.\r\n\r\nDaca sunteti interesati si, bineinteles, daca \"va tine\", incercati se rezolvati problema \"SGU 145\":http://acm.sgu.ru/problem.php?contest=0&problem=145 , de unde a pornit de fapt acest articol. Se cere cazul cel dificil, cu drumuri elementare.\r\n\r\n',2044,'public',NULL,NULL),('utilizator/motty','Profil motty','2008-10-24 09:08:52','2009-02-20 16:06:00','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n* _Sunt elev in clasa a 9-a la Colegiul National de Informatica \"Tudor Vianu\"_\r\n* _Am inceput informatica in octombrie 2008._\r\n* _{*In God we Trust!*}_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"gabitzish\" type=\"tiny\")==\r\n* ==User(user=\"drag0s93\" type=\"tiny\")==',8690,'public',NULL,NULL),('2-sat','Problema 2-satisfiabilității','2008-12-09 15:55:03','2009-02-20 22:08:13','h1. Problema 2-satisfiabilităţii\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"marius\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 30em}*{text-align:center} *Conţinut:*\r\n* {\'Introducere\':2-sat#introducere}\r\n* {\'Forme normale ale formulelor logice\':2-sat#forme-normale}\r\n* {\'SAT, 3-SAT, 2-SAT\':2-sat#overview-sat}\r\n* {\'Soluţii pentru 2-SAT\':2-sat#solutii-2-sat}\r\n** {\'Soluţie $O(M * 2^N^)$\':2-sat#solutie-1}\r\n** {\'Soluţie $O(N * M)$\':2-sat#solutie-2}\r\n** {\'Soluţie $O(N^2^)$\':2-sat#solutie-3}\r\n** {\'Soluţie $O(M + N)$\':2-sat#solutie-4}\r\n* {\'Aplicaţii\':2-sat#aplicatii}\r\n** {\'Party &#40;preONI 2003/2004&#41;\':2-sat#party}\r\n** {\'Cigraf\':2-sat#cigraf}\r\n** {\'Orpath &#40;Olimpiadă Rusia&#41;\':2-sat#orpath}\r\n** {\'Aladdin &#40;Bursele Agora 2005/2006, Runda 1&#41;\':2-sat#aladdin}\r\n* {\'Probleme propuse\':2-sat#probleme}\r\n* {\'Bibliografie\':2-sat#bibliografie}\r\n\r\nh2(#introducere). Introducere\r\n\r\nProblema satisfiabilităţii, notată prescurtat cu $SAT$, cere determinarea existenţei pentru o formulă booleană <tex> \\phi </tex> a unei atribuiri satisfiabile. O formulă booleană <tex> \\phi </tex> este compusă din $variabile$ logice <tex> (x_{1}, x_{2}, ...) </tex>, $operatori$ logici ( <tex> \\wedge </tex> şi,  <tex> \\vee </tex> sau, <tex> \\sim </tex> non, <tex> \\rightarrow </tex> implicaţie, <tex> \\leftrightarrow </tex> echivalenţă), şi $paranteze$. O atribuire de valori booleene pentru variabilele acestei expresii se numeşte $atribuire satisfiabilă$ dacă evaluarea expresiei după atribuirea valorilor dă ca rezultat valoarea de adevăr $adevărat$. De acum încolo vom folosi pentru simplitate valorile <tex> 1 </tex> şi <tex> 0 </tex> în loc de $adevărat$ şi $fals$.\r\n\r\nUn exemplu de formulă ar fi <tex> \\phi = ((x_{1} \\rightarrow x_{2}) \\vee \\sim((\\sim x_{1} \\leftrightarrow x_{3}) \\vee x_{4})) \\wedge \\sim x_{2} </tex>. Aceasta are atribuirea satisfiabilă <tex> \\langle x_{1} = 0, x_{2} = 0, x_{3} = 1, x_{4} = 1 \\rangle </tex> pentru că <tex> \\phi = ((0 \\rightarrow 0) \\vee \\sim((\\sim 0 \\leftrightarrow 1) \\vee 1)) \\wedge \\sim 0 = (1 \\vee \\sim (1 \\vee 1)) \\wedge 1 = (1 \\vee 0) \\wedge 1 = 1</tex>. \r\n\r\nh2(#forme-normale). Forme normale ale formulelor logice\r\n\r\nOrice formulă booleană poate fi transformată în două forme:\r\n\r\n* $Forma normal conjunctivă$ în care expresia este exprimată ca o conjuncţie de propoziţii, iar fiecare propoziţie este formată dintr-o disjuncţie de $literali$. Un $literal$ este o variabilă care poate fi sau nu negată. Un exemplu de expresie în forma normal conjunctivă ar fi: <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) \\wedge (x_{3} \\vee x_{2} \\vee x_{4}) \\wedge (\\sim x_{1} \\vee \\sim x_{3} \\vee \\sim x_{4}) </tex> care are pe <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) </tex> ca primă propoziţie cu literalii <tex> x_{1} </tex>, <tex> \\sim x_{1} </tex>, <tex> \\sim x_{2} </tex>.\r\n\r\n* $Forma normal disjunctivă$ este formată ca o disjuncţie de propoziţii, fiecare dintre aceste propoziţii fiind o conjuncţie de literali. Un exemplu de o asemenea formulă ar fi următoarea: <tex> (x_{1} \\wedge x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge \\sim x_{3}) \\vee (\\sim x_{1} \\wedge x_{2} \\wedge \\sim x_{2}) </tex>.\r\n\r\nh2(#overview-sat). SAT, 3-SAT, 2-SAT\r\n\r\nProblema $SAT$ este $NP-completă$. De fapt, este prima problemă $NP-completă$ găsită. Stephen Cook a demonstrat $NP-completitudinea$ ei în 1971. Pe vremea aceea nu se ştia nici măcar că problemele $NP-complete$ există. Această problemă rămâne $NP-completă$ chiar dacă restricţionăm expresiile la unele care în forma normal conjunctivă au doar trei literali. Problema satisfiabilităţii pentru asemenea expresii se numeşte $3-SAT$, şi multe probleme pot fi demonstrate a fi $NP-complete$ prin reducerea lui $3-SAT$ la problemele respective în timp polinomial. Din fericire, problema $2-SAT$, adică cea pentru care în fiecare propoziţie există doar $2$ literali, se poate rezolva eficient. Restul articolului va prezenta trei metode de rezolvare a problemei $2-SAT$ şi câteva aplicaţii ale acesteia din concursuri de programare.\r\n\r\nh2(#solutii-2-sat). Soluţii pentru 2-SAT\r\n\r\nUn exemplu de problemă $2-SAT$ ar fi satisfiabilitatea formulei <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Această formulă este satisfăcută de valorile <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>. Pentru a satisface întreaga expresie trebuie ca în fiecare propoziţie cel puţin unul din cei doi literali să aibă valoarea de adevăr <tex> 1 </tex>.\r\n\r\nh3(#solutie-1). Soluţie $O(M * 2^N^)$\r\n\r\nO primă metodă de rezolvare ar fi să încercăm toate cele $2^N^$ posibilităţi de atribuire posibilă, dar această metodă are ordinul de complexitate $O(M * 2^N^)$ şi este eficientă doar pentru instanţe mici ale problemei.\r\n\r\nh3(#solutie-2). Soluţie $O(N * M)$\r\n\r\nUrmătoarea soluţie pare trivială, dar găsirea acestui algoritm şi realizarea faptului că el rezolvă corect problema sunt mai grele decât impresia lăsată după citirea ei. Considerăm o propoziţie oarecare cu două variabile $p$ şi $q$, apoi una dintre ele, de exemplu $p$. Îi atribuim literalului în care apare $p$ valoarea $0$. Pentru ca propoziţia respectivă să aibă $1$ valoarea de adevăr, atunci valoarea lui $q$ trebuie fixată. Fixând şi valoarea lui $q$, probabil şi alte propoziţii ce conţin literalul $q$ vor avea celălalt literal fixat. Propagăm astfel o serie de schimbări. După ce toate schimbările forţate au fost făcute, propoziţiile rezultate vor fi de următoarele tipuri: <tex> a \\vee b </tex>, <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex>. Propoziţii de tip <tex> 0 \\vee b </tex> nu pot apărea pentru că toate schimbările forţate au fost deja propagate. Dacă apare o propoziţie <tex> 0 \\vee 0 </tex> atunci alegerea făcută pentru valoarea lui $p$ este greşită. Vom încerca şi alegerea opusă pentru $p$. Dacă ambele duc la o propoziţie de tip <tex> 0 \\vee 0 </tex> atunci expresia nu poate fi satisfăcută. Propoziţiile de forma <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex> pot fi ignorate. În acest fel am eliminat cel puţin o variabilă şi o propoziţie din expresie. Dacă expresia iniţială era satisfiabilă, atunci şi expresia din care s-au eliminat câteva propoziţii a rămas satisfiabilă. Continuând pe această idee obţinem un algoritm de complexitate $O(N * M)$, pentru că la fiecare atribuire de valoare pentru o variabilă parcurgem şirul de propoziţii o dată. \r\n\r\nSă vedem cum funcţionează algoritmul pentru expresia: <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Considerăm propoziţia <tex> (x_{1} \\vee \\sim x_{2}) </tex> şi <tex> \\langle x_{2} = 1 \\rangle </tex>. Astfel, vom obţine mai departe <tex> (x_{1} \\vee 0) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee 1) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. În propoziţia <tex> (x_{1} \\vee 0) </tex>, <tex> x_{1} </tex> trebuie să fie egal cu <tex> 1 </tex>. Acum, expresia devine: <tex> (0\\ \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee 0) </tex>. Din propoziţia <tex> (0\\ \\vee \\sim x_{3}) </tex> obţinem <tex> \\langle x_{3} = 0 \\rangle </tex>, iar din <tex> (x_{4} \\vee 0) </tex> obţinem <tex> \\langle x_{4} = 1 \\rangle </tex>. Deci, atribuirea satisfiabilă este <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>.\r\n\r\nh3(#solutie-3). Soluţie $O(N^2^)$\r\n\r\nO altă soluţie elegantă se bazează pe o metodă randomizată:\r\n\r\n== code(cpp) |\r\natribuim valori booleene arbitrare variabilelor;\r\ncât timp expresia nu este satisfăcută, execută\r\n    găsim o propoziţie cu valoarea de adevăr 0;\r\n    schimbăm valoarea de adevăr a oricăreia dintre cele două variabile prezente în propoziţie;\r\nsfârşit cât timp\r\n==\r\n\r\nLinia $4$ va face ca acea propoziţie să aibă noua valoare de adevăr <tex> 1 </tex>.\r\n\r\nDe ce ar merge acest algoritm? Să presupunem că există o soluţie a problemei, o notăm cu <tex> S </tex>, iar cu <tex> X </tex> notăm şirul valorilor curente ale variabilelor. Ne uităm la fiecare pas al algoritmului la numărul de variabile care au valori diferite în soluţie faţă de cele din <tex> X </tex> (acest număr de diferenţe între elementele de acelaşi index pentru două şiruri se mai numeşte şi \'distanţă Hamming\':http://en.wikipedia.org/wiki/Hamming_distance între şiruri). Fie această valoare la pasul current $K$. Noi am vrea să avem $K = 0$. Cum va evolua $K$ pe parcursul algoritmului? La un moment dat noi schimbăm valoarea unei variabile luate aleator dintr-o propoziţie nesatisfăcută. Pentru că în <tex> S </tex> propoziţia este satisfăcută, înseamnă că cel puţin una dintre cele două variabile ale propoziţiei are valori diferite în <tex> X </tex> faţă de <tex> S </tex>. Astfel, operaţia făcută de noi are probabilitate de cel puţin $0.5$ să ne aducă mai aproape de soluţie. Vom nota cu <tex> T(i) </tex> numărul probabil de paşi în care un şir <tex> X </tex> aflat la distanţa Hamming egală cu $i$ faţă de <tex> S </tex>, va fi transformat în <tex> S </tex>. Evident:\r\n\r\n<tex> T(0) = 0 </tex>\r\n\r\n<tex> T(i) \\le \\dfrac {T(i + 1) + T(i - 1)}{2} + 1 </tex> pentru $0 < i < N$ ({$N$} e numărul de variabile booleene ale expresiei)\r\n\r\nSe pune semnul de inegalitate pentru că ambele variabile pot avea valori diferite faţă de cele din soluţie, deci schimbarea valorii oricăreia ar putea să ne aducă mai aproape de soluţie.\r\n\r\nDacă toate variabilele diferă de soluţie, orice schimbare ne aduce mai aproape de aceasta:\r\n\r\n<tex> T(N) = T(N - 1) + 1 </tex>\r\n\r\nNe interesează numai limitele superioare, deci folosim doar egalităţi în loc de inegalităţi:\r\n\r\n<tex> X(0) = 0 </tex>, <tex> X(i) = \\dfrac {X(i + 1) + X(i - 1)}{2} + 1 </tex>, <tex> X(N) = X(N - 1) + 1 </tex>\r\n\r\nDacă adunăm toate ecuaţiile obţinem:\r\n\r\n<tex> X(0) + X(1) + ... + X(N) = </tex> <tex> \\dfrac {X(0) + X(1) + 2X(2) + ... + 2X(N - 2) + X(N - 1) + X(N)}{2} + X(N) + N - 1 </tex>\r\n\r\nDe aici avem că <tex> \\dfrac {X(1) + X(N - 1) - X(N)}{2} = N - 1 </tex>, iar din <tex> X(N) = X(N - 1) + 1 </tex> rezultă că <tex> X(1) = 2N - 1 </tex>. Mai departe avem că <tex> X(2) = 4N - 4 </tex> <tex> ... </tex> <tex> X(i) = 2iN - i^2 </tex>, de unde, când <tex> i = N </tex>, avem că <tex> X(N) = N^2 </tex>.\r\n\r\nAstfel, numărul mediu de paşi ai algoritmului este pătratic în numărul $N$ de variabile. Lăsând algoritmul să ruleze de 2-3 ori mai mulţi paşi decât numărul mediu, avem o probabilitate foarte mare să ajungem la rezultat.\r\n\r\nh3(#solutie-4). Soluţie $O(M + N)$\r\n\r\nO a treia soluţie se bazează pe relaţia de implicaţie. Relaţia <tex> \\rightarrow </tex> are următoarea tabelă de adevăr:\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> A \\rightarrow B </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nRelaţia de implicaţie are următoarea semnificaţie: dacă <tex> A </tex> este adevărat atunci şi <tex> B </tex> este adevărat. Scriem tabela expresiei <tex> \\sim A \\vee B </tex> şi observăm că aceasta este egală cu cea a relaţiei de implicaţie.\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> \\sim A \\vee B </tex>|\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nFiecare clauză <tex> A \\vee B </tex> poate fi scrisă ca două implicaţii <tex> \\sim A \\rightarrow B </tex> şi <tex> \\sim B \\rightarrow A </tex>. Realizăm un graf al implicaţiilor. Astfel, nodurile grafului vor fi variabilele <tex> A </tex>, <tex> B </tex> <tex> ... </tex> şi negaţiile lor <tex> \\sim A </tex>, <tex> \\sim B </tex> <tex> ... </tex> iar muchiile acestui graf vor fi implicaţiile echivalente cu propoziţiile din expresie. Deci, dacă expresia are $M$ propoziţii, graful va avea $2M$ muchii. Acestea fiind zise, expresiei <tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) </tex> îi corespunde graful:\r\n\r\np=. !2-sat?Graf.png!\r\n\r\nDacă avem <tex> A \\longrightarrow B </tex> o muchie în graful nostru şi literalul <tex> A </tex> este adevărat, atunci şi literalul <tex> B </tex> trebuie să fie adevărat pentru ca propoziţia reprezentată de muchie să fie satisfăcută. Putem demonstra prin inducţie că dacă există un drum în graf de la literalul <tex> A </tex> la literalul <tex> B </tex>, atunci dacă <tex> A </tex> este adevărat şi <tex> B </tex> trebuie să fie adevărat. Dacă există un drum de la un literal <tex> X </tex> la <tex> \\sim X </tex>, precum şi un drum invers, atunci nu va exista soluţie pentru că nu putem seta în acelaşi timp o variabilă şi valoarea ei negată la valoarea adevărat. De aici rezultă că dacă în graful asociat expresiei există o variabilă <tex> X </tex> în aceeaşi componentă tare conexă cu <tex> \\sim X </tex> atunci instanţa problemei satisfiabilităţii nu poate fi satisfăcută. Dacă nu există o asemenea variabilă, vom vedea în continuare cum putem rezolva problema. Întâi, facem observaţia că dacă în graf există muchia <tex> A \\longrightarrow B </tex> atunci există şi muchia <tex> \\sim B \\longrightarrow \\sim A </tex>. Astfel, dacă există un drum de la <tex> A </tex> la <tex> B </tex> în graf, aplicând proprietatea menţionată pentru fiecare muchie a drumului, vom găsi un drum de la <tex> \\sim B </tex> la <tex> \\sim A </tex>. Evident, afirmaţia este valabilă şi reciproc: dacă există drum de la <tex> B </tex> la <tex> A </tex> atunci vom avea un drum de la nodul <tex> \\sim A </tex> la <tex> \\sim B </tex>. Astfel, dacă avem că <tex> A </tex> şi <tex> B </tex> sunt în aceeaşi componentă tare conexă atunci şi nodurile <tex> \\sim A </tex> şi <tex> \\sim B </tex> sunt în aceeaşi componentă tare conexă. Deci, dacă nu există doi literali <tex> X </tex> şi <tex> \\sim X </tex> în aceeaşi componentă tare conexă, putem să împărţim graful în componente tare conexe şi să împerechem componentele câte două astfel ca în fiecare pereche să apară o componentă <tex> U </tex> cu nişte literali şi altă componentă <tex> \\sim U </tex> cu aceiaşi literali negaţi. Pentru a găsi o soluţie vom determina mai întâi componentele tare conexe ale grafului. Apoi putem contracta fiecare componentă într-un nod. Graful obţinut va fi aciclic. Alegem un nod <tex> u </tex> în care nu intră nicio muchie (un asemenea nod trebuie să existe pentru a nu exista cicluri). Din considerente de simetrie, din nodul lui pereche <tex> \\sim u </tex> nu va ieşi nicio muchie. Literalilor componentei <tex> U </tex> putem să le dăm valoarea de adevăr <tex> 0 </tex>, iar literalilor din componenta pereche <tex> \\sim U </tex>  putem să le dăm valoarea de adevăr <tex> 1 </tex>. Această alegere nu impune restricţii asupra celorlalţi literali şi elimină câteva variabile din problemă. Repetarea recursivă a acestui pas pe graful rămas va duce la rezolvarea problemei. Determinarea componentelor tare conexe se poate face în complexitatea $O(N + M)$. Pentru a vedea acest algoritm puteţi consulta \'secţiunea $23.5$\':http://zhuzeyuan.hp.infoseek.co.jp/ita/chap23.htm din {\'[1]\':2-sat#bibliografie}. Iar eliminarea nodurilor de care vorbeam mai sus se poate face în $O(N + M)$ folosind o sortare topologică.\r\n\r\nSă urmărim cum merge algoritmul nostru pe exemplul de mai sus. Componentele tare conexe sunt următoarele: <tex> \\{A\\} </tex>, <tex> \\{\\sim A\\} </tex>, <tex> \\{B, C, \\sim D\\} </tex>, <tex> \\{\\sim B, \\sim C, D\\} </tex>. În nodul asociat componentei <tex> \\{A\\} </tex> nu intră nicio muchie. Astfel, putem să îi atribuim lui <tex> A </tex> valoarea <tex> 0 </tex>, iar după eliminarea lui <tex> \\{A\\} </tex> şi <tex> \\{\\sim A\\} </tex>în nodul asociat componentei <tex> \\{\\sim B, \\sim C, D\\} </tex> nu intră nicio muchie, deci putem să îi atribuim lui <tex> B </tex> valoarea <tex> 1 </tex>, lui <tex> C </tex> valoarea <tex> 1 </tex> şi lui <tex> D </tex> valoarea <tex> 0 </tex>. Această atribuire este satisfiabilă după cum vedem în continuare:\r\n\r\n<tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) = </tex> <tex> (\\sim 0 \\vee \\sim 1) \\wedge (1 \\vee \\sim 1) \\wedge (1 \\vee 1) \\wedge (\\sim 1 \\vee \\sim 0) \\wedge (1 \\vee 0) = </tex> <tex> 1 \\wedge 1 \\wedge 1 \\wedge 1 \\wedge 1 = 1 </tex>\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\nRestul articolului va prezenta aplicaţii ale problemei $2-SAT$ din concursurile de programare.\r\n\r\nh2(#party). \'Party\':problema/party (preONI 2003/2004)\r\n\r\nbq. George vrea să îşi organizeze majoratul şi îşi doreşte ca petrecerea să fie de neuitat. Mâncarea, băutura, locaţia şi sonorizarea sunt deja asigurate, mai rămâne problema chemării prietenilor. El şi cu prietenul lui cel mai bun, Lucian, au preferinţe diferite şi pentru a nu se certa au pus la punct o listă de cerinţe care vor trebui să fie îndeplinite astfel încât cheful să se desfăşoare în cele mai bune condiţii! Pentru uşurinţă, prietenii lui George vor fi identificaţi prin numere întregi de la $1$ la $N$ ({$1 ≤ N ≤ 100$}) şi cerinţele în număr de $M$ ({$1 ≤ M ≤ 1.000$}) vor fi de tipurile 0, 1, 2 sau 3. O cerinţă de genul <tex> x \\ y </tex> 0 are semnificaţia că <tex> x </tex> sau <tex> y </tex> trebuie să participe la petrecere; <tex> x \\ y </tex> 1 are semnificaţia că dacă <tex> x </tex> participă nu există nicio restricţie pentru <tex> y </tex>, dar dacă <tex> x </tex> nu participă atunci nici <tex> y </tex> nu participa; <tex> x \\ y </tex> 2 are semnificaţia simetrică cu cerinţa 1; iar cerinţa <tex> x \\ y </tex> 3 are semnificaţia că cel puţin unul dintre <tex> x </tex> şi <tex> y </tex> nu participă la petrecere. Scrieţi un program care să-i ajute pe cei doi să determine care persoane vor fi invitate la petrecere. Se garantează că va fi posibilă întotdeauna organizarea unei petreceri!\r\n\r\nh3. Soluţie\r\n\r\nAceastă problemă este inspirată dintr-o problemă de la $CEOI 2002$ şi este evident că ne cere să determinăm o atribuire satisfiabilă pentru o formulă logică formată ca conjuncţie între cerinţele care se transformă astfel:\r\n\r\n* _cerinţa de tip 0_ corespunde propoziţiei <tex> x \\vee y </tex>;\r\n* _cerinţa de tip 1_ corespunde propoziţiei <tex> x \\vee \\sim y </tex>;\r\n* _cerinţa de tip 2_ corespunde propoziţiei <tex> \\sim x \\vee y </tex>;\r\n* _cerinţa de tip 3_ corespunde propoziţiei <tex> \\sim x \\vee \\sim y </tex>.\r\n\r\nUna din primele două rezolvări ar fi putut soluţiona această problemă, dar problema de la $CEOI$ avea limite mai mari şi pentru rezolvarea ei ar fi trebuit un algoritm de complexitate $O(N + M)$.\r\n\r\nh2(#cigraf). Cigraf\r\n\r\n_Autor: Mugurel Ionuţ Andreica_\r\n\r\nbq. Se dă un graf neorientat cu $N$ ({$1 &le; N &le; 1000$}) noduri şi $M$ ({$0 &le; M &le; N*(N-1)/2$}) muchii. Se doreşte împărţirea nodurilor acestui graf în $2$ mulţimi, <tex> C </tex> şi <tex> I </tex>, având următoarele proprietăţi: fiecare nod face parte din exact una din cele $2$ mulţimi, există muchie între oricare $2$ noduri din mulţimea <tex> C </tex>, nu există nicio muchie între $2$ noduri din mulţimea <tex> I </tex>. Este posibil ca una dintre cele $2$ mulţimi să fie vidă. Soluţia nu este neapărat unică. Numele celor două mulţimi provin de la $clică$ şi $mulţime independentă$. De exemplu, pentru graful de $6$ noduri ce are muchiile <tex> \\{\\{1, 4\\}, \\{4, 6\\}, \\{6, 1\\}, \\{2, 4\\}, \\{2, 6\\}, \\{3, 4\\}, \\{1, 3\\}\\} </tex> o împărţire posibilă ar fi <tex> C = \\{1, 4, 6\\} </tex>, <tex> I = \\{2, 3, 5\\} </tex>.\r\n\r\nh3. Soluţie\r\n\r\nDacă între două noduri există muchie atunci nu pot fi amândouă în mulţimea <tex> I </tex>, iar dacă între două noduri nu există muchie nu pot fi amândouă în mulţimea <tex> C </tex>. Transformăm această problemă într-o instanţă de $2-SAT$ astfel: faptul că nodul <tex> x </tex> aparţine mulţimii <tex> C </tex> îl reprezentăm dându-i lui <tex> x </tex> valoarea <tex> 1 </tex>, iar apartenenţa la mulţimea <tex> I </tex> se codifică prin valoarea <tex> 0 </tex>. Acum existenţa unei muchii <tex> (x, y) </tex> corespunde expresiei <tex> x \\vee y </tex>, astfel cel puţin unul din nodurile <tex> x </tex> şi <tex> y </tex> nu va fi în mulţimea <tex> I </tex>. Dacă nu există muchia <tex> (x, y) </tex> putem scrie <tex> \\sim x \\vee \\sim y </tex>, această expresie va fi adevărată dacă cel puţin un nod din cele două nu va fi în mulţimea <tex> C </tex>.\r\n\r\nh2(#orpath). Orpath (Olimpiadă Rusia)\r\n\r\nbq. Într-o ţară pacifistă, există $N$ oraşe şi $K$ autobuze $(1 &le; N, K &le; 100)$. La orele aglomerate ale zilei, nu trebuie să existe două autobuze care merg în acelaşi timp în sensuri opuse. Traseul fiecărui autobuz este un ciclu. Spunem că el merge în sens pozitiv dacă va parcurge oraşele în ordinea $1 2 3 4 1 2 3 4 1 2$ ... sau în sens negativ dacă le parcurge în ordinea $1 4 3 2 1 4 3 2 1 4$ ... Găsiţi o posibilitate de atribuire a sensului fiecărui autobuz astfel ca accidentele de trafic să fie evitate (nu vor exista două autobuze care să se întâlnească şi să aibă sensuri de mers opuse). Pentru fiecare autobuz se vor şti oraşele de pe ruta lui, şi pentru fiecare două oraşe vecine pe rută se va şti timpul necesar autobuzului pentru a ajunge dintr-un oraş în altul. De exemplu, pentru $4$ oraşe unde oricare două sunt la timp de mers egal cu $10$, şi pentru două autobuze cu rutele $1 2 4$ şi $3 4 2$, o soluţie ar fi ca primul autobuz să meargă în sens pozitiv iar celălalt în sens negativ.\r\n\r\nh3. Soluţie\r\n\r\nPentru orice două autobuze vom găsi care sunt sensurile de mers pentru ele astfel ca cele două autobuze să nu se întâlnească şi să provoace un accident. Pentru un sens fixat putem afla pentru un autobuz pe ce interval de timp va fi pe o anumită stradă. El va fi în general pe o stradă $(i, j)$ pe un interval de tipul $[t1 + k*T … t2 + k*T]$ unde $t1$ este timpul din prima rută parcursă pentru a ajunge la $i$, $t2$ timpul pentru a ajunge la $j$ iar $T$ este durata totală a unei rute. Acum, pentru a determina dacă două autobuze se vor întâlni pe o rută $(i, j)$ trebuie ca ele să se deplaseze în sensuri opuse pe această rută, iar intervalele lor $[t1 + k*T1 .. t2 + k*T1]$ se intersectează cu intervalele $[tt1 + p*T2 … tt2 + p*T2]$. Este clar acum că putem transforma problema într-o instanţă de $2-SAT$ prin maparea autobuzelor în variabile logice, a sensurilor de mers în valorile $adevărat$ şi $fals$, iar pentru orice pereche de autobuze să fie o propoziţie logică ce ia valoarea $adevărat$ doar dacă sensurile de mers determinate de variabilele logice asociate autobuzelor sunt compatibile. Mai trebuie determinat într-un mod eficient dacă două clase de intervale de timp se intersectează. Aceasta rămâne ca temă cititorului.\r\n\r\nh2(#aladdin). \'Aladdin\':problema/aladdin (Bursele Agora 2005/2006, Runda 1)\r\n\r\nbq. Aladdin, aşa cum ştiaţi, este un mare magnat în afacerea de comercializare a covoarelor magice. Acesta doreşte să o cucerească pe prinţesa Iasmina, iar aceasta, pentru a-i testa inteligenţa îl roagă să îi facă un covor dreptunghiular împărţit în pătrăţele, asemănator unei table de şah cu $N$ linii şi $M$ coloane $(1 &le; N, M &le; 1000)$. Fiecare pătrăţel de pe covor trebuie colorat cu alb sau cu negru. Pentru fiecare pătrat care conţine $4$ pătrăţele Iasmina pune condiţia să aibă un număr fixat de pătrăţele colorate cu negru. Ajutaţi-l pe Aladdin să realizeze un covor care satisface condiţiile impuse de prinţesa Iasmina!\r\n\r\nh3. Soluţie\r\n\r\nÎntâi, să considerăm un exemplu. Pentru o cerinţă de forma:\r\n\r\ntable{width: 90px; text-align: center}.\r\n| <tex> 3 </tex> | <tex> 2 </tex> | <tex> 3 </tex> |\r\n| <tex> 2 </tex> | <tex> 3 </tex> | <tex> 3 </tex> |\r\n| <tex> 1 </tex> | <tex> 2 </tex> | <tex> 1 </tex> |\r\n\r\nuna din soluţii este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nFie <tex> A </tex> o matrice soluţie a problemei noastre. Vom numerota rândurile matricii de la $0$ la $N - 1$ şi coloanele de la $0$ la $M - 1$. Matricea de intrare <tex> S </tex> reprezintă de fapt sumele din fiecare pătrat de câte $2 x 2$ elemente. Facem observaţia că dacă ştim într-un pătrat de $2 x 2$ valorile pentru trei dintre celule, atunci valoarea din a patra celulă este unic determinată pentru că ştim suma elementelor din pătrat. Vedem astfel, că dacă ştim valorile elementelor din prima linie a matricii <tex> A </tex> şi din prima coloană, restul valorilor sunt unic determinate. \r\nPentru a rezolva problema vom presupune <tex> A[0][0] </tex> cunoscut (de fapt, mai întâi vom rezolva problema presupunând că <tex> A[0][0] = 1 </tex>, iar dacă nu obţinem nicio soluţie vom încerca cu <tex> A[0][0] = 0 </tex>). Vom nota celulele <tex> A[0][1] </tex>, <tex> A[0][2]</tex>, … <tex> A[0][M - 1] </tex> cu <tex> x_{1} </tex>, <tex> x_{2} </tex>, … <tex> x_{M-1} </tex> iar celulele <tex> A[1][0] </tex>, <tex> A[2][0] </tex>, … <tex> A[N - 1][0] </tex> cu <tex> y_{1} </tex>, <tex> y_{2} </tex>, … <tex> y_{N-1} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> A[0][0] </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> ... </tex> | <tex> x_{M-1} </tex> |\r\n| <tex> y_{1} </tex> | <tex> 1 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n| <tex> y_{2} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 0 </tex> |\r\n| ... | ... | ... | ... | ... |\r\n| <tex> y_{N-1} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n\r\nAcum, pentru fiecare celulă putem demonstra prin inducţie că <tex> A[i][j] = (-1)^i x_{j} + (-1)^j y_{i} + b[i][j] </tex>. Unde <tex> b[i][j] </tex> sunt nişte constante ce sunt calculate în funcţie de matricea primită la intrare.\r\nEste uşor de observat că dacă:\r\n<tex> A[i-1][j] = (-1)^{(i-1)} x_{j} + (-1)^j y_{i-1} + b[i-1][j] </tex>, \r\n<tex> A[i-1][j-1] = (-1)^{(i-1)} x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i-1][j-1] </tex>, \r\n<tex> A[i][j-1] = (-1)^i x_{j-1} + (-1)^{(j-1)} y_{i} + b[i][j-1] </tex>, \r\n\r\natunci:\r\n\r\n<tex> A[i][j] = S[i-1][j-1] - A[i-1][j] - A[i][j-1] - A[i-1][j-1] = </tex> \r\n<tex> = S[i-1][j-1] - ((-1)^{(i-1)} x_{j} + (-1)^j y_{i-1} + b[i-1][j]) - </tex> <tex> ((-1)^{(i-1)} x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i-1][j-1]) - ((-1)^i x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i][j-1]) = </tex> \r\n<tex> = (-1)^i x_{j} - (-1)^j y_{i-1} + (-1)^i x_{j-1} + (-1)^j y_{i-1} - </tex> <tex> (-1)^i x_{j-1} + (-1)^j y_{i} + S[i-1][j-1] - b[i-1][j] - b[i][j-1] - b[i-1][j-1] = </tex> \r\n<tex> = (-1)^i x_{j} + (-1)^j y_{i} + b[i][j] </tex>. \r\n\r\nDe aici concluzionăm că <tex> b[i][j] = S[i-1][j-1] - b[i-1][j] - b[i][j-1] - b[i-1][j-1] \\ (*)</tex>.\r\n\r\nAvem un sistem format din inecuaţiile:\r\n\r\n<tex> 0 \\le x_{j} \\le 1 </tex>\r\n<tex> 0 \\le y_{i} \\le 1 </tex>\r\n<tex> -b[i][j] \\le (-1)^i x_{j} + (-1)^j y_{i} \\le 1 - b[i][j] </tex>\r\n\r\nEste uşor acum să transformăm acest sistem într-o formulă booleană în {\'formă normal conjunctivă\':2-sat#forme-normale} în care fiecare expresie are cel mult $2$ literali. Fiecare relaţie o putem înmulţi sau nu cu $-1$ astfel ca părţile constante ale relaţiei să fie pozitive. Observăm că <tex> | b[i][j] | \\le 2 </tex>, altfel nu avem soluţie. Dacă <tex> | b[i][j] | = 2 </tex> atunci ambele variabile au valori fixe, iar dacă <tex> | b[i][j] | = 1 </tex> sau <tex> | b[i][j] | = 0 </tex> atunci relaţia o putem scrie ca o disjuncţie logică cu doi literali.\r\n\r\nO relaţie precum <tex> 0 \\le x + y \\le 1 </tex> poate fi tansformată logic în <tex> \\sim x \\vee \\sim y </tex>, astfel <tex> x </tex> şi <tex> y </tex> nu vor fi în acelaşi timp <tex> 1 </tex>, una de genul <tex> 1 \\le x + y \\le 2 </tex> va fi transformată în <tex> (x \\vee y) </tex>, astfel cel puţin <tex> x </tex> sau <tex> y </tex> va fi egal cu <tex> 1 </tex>, alta de tipul <tex> 0 \\le x - y \\le 1 </tex> poate fi scrisă ca <tex> x \\vee \\sim y </tex>, una de tipul <tex> 2 \\le x + y \\le 3 </tex> în <tex> x \\wedge y </tex>, iar una de tipul <tex> 0 \\le -x -y \\le 1 </tex> în <tex> \\sim x \\wedge \\sim y </tex>, una de tipul <tex> 1 \\le x - y  \\le 2 </tex> în <tex> x \\wedge \\sim y </tex>.\r\n\r\nAstfel am redus problema la rezolvarea unei instanţe de $2-SAT$. Avem $N+M-1$ necunoscute şi {$(N-1)$}{$(M-1)$} propoziţii. Folosind a treia metodă de rezolvare vom obţine un algoritm de complexitate $O(N * M)$ care soluţionează problema noastră.\r\n\r\nSă vedem cum merge acestă rezolvare pe exemplul din problemă:\r\n\r\nAlegem <tex> A[0][0] = 1 </tex>. Necunoscutele vor fi <tex> x_{1} </tex>, <tex> x_{2} </tex>, <tex> x_{3} </tex> şi <tex> y_{1} </tex>, <tex> y_{2} </tex>, <tex> y_{3} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> x_{3} </tex> |\r\n| <tex> y_{1} </tex> | <tex> A[1][1] </tex> | <tex> A[1][2] </tex> | <tex> A[1][3] </tex> |\r\n| <tex> y_{2} </tex> | <tex> A[2][1] </tex> | <tex> A[2][2] </tex> | <tex> A[2][3] </tex> |\r\n| <tex> y_{3} </tex> | <tex> A[3][1] </tex> | <tex> A[3][2] </tex> | <tex> A[3][3] </tex> |\r\n\r\nFolosind recurenţa <tex> (*) </tex> obţinem că matricea <tex> b </tex> este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 2 </tex> | <tex> 0 </tex> | <tex> 3 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> -1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n\r\nDe aici obţinem sistemul de inegalităţi:\r\n\r\n<tex> 0 \\le x_{1} \\le 1,  0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le 1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, -2 \\le -x_{1} - y_{1} \\le -1, 0 \\le -x_{2} + y_{1} \\le 1, -3 \\le -x_{3} - y_{1} \\le -2, </tex>\r\n<tex> 0 \\le y_{2} \\le 1,  0 \\le  x_{1} - y_{2} \\le  1,-1 \\le  x_{2} + y_{2} \\le 0,  1 \\le  x_{3} - y_{2} \\le  2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, -1 \\le -x_{1} - y_{3} \\le  0, 0 \\le -x_{2} + y_{3} \\le 1, -1 \\le -x_{3} - y_{3} \\le  0 </tex>\r\n\r\nTransformăm relaţiile astfel ca să nu apară nicio constantă negativă:\r\n\r\n<tex> 0 \\le x_{1} \\le 1, 0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le  1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, 1 \\le x_{1} + y_{1} \\le 2, 0 \\le -x_{2} + y_{1} \\le 1, 2 \\le x_{3} + y_{1} \\le 3, </tex>\r\n<tex> 0 \\le y_{2} \\le 1, 0 \\le x_{1} - y_{2} \\le 1, 0 \\le -x_{2} - y_{2} \\le 1, 1 \\le x_{3} - y_{2} \\le 2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, 0 \\le x_{1} + y_{3} \\le 1, 0 \\le -x_{2} + y_{3} \\le 1, 0 \\le x_{3} + y_{3} \\le 1 </tex>\r\n\r\nAcest sistem poate fi transformat într-o expresie booleană:\r\n\r\n<tex> (x_{1} \\vee y_{1}) \\wedge (\\sim x_{2} \\vee y_{1}) \\wedge (x_{3} \\wedge y_{1}) \\wedge </tex>\r\n<tex> (x_{1} \\vee \\sim y_{2}) \\wedge (\\sim x_{2} \\wedge \\sim y_{2}) \\wedge (x_{3} \\wedge \\sim y_{2}) \\wedge </tex>\r\n<tex> (\\sim x_{1} \\vee \\sim y_{3}) \\wedge (\\sim x_{2} \\vee y_{3}) \\wedge (\\sim x_{3} \\vee \\sim y_{3}) </tex>.\r\n\r\nAcestă expresie e satisfăcută de valorile: <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 1, y_{1} = 1, y_{2} = 0, y_{3} = 0 \\rangle </tex>, iar de aici putem determina o soluţie a problemei noastre iniţiale ca fiind:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nh2(#probleme). Probleme propuse\r\n\r\nPentru a vă familiariza cu subiectul prezentat în acest articol, vă propunem să încercaţi să rezolvaţi următoarele probleme:\r\n\r\n# \'Excursion\':http://www.oi.edu.pl/download/boi-2001.pdf - Baltic Olympiad in Informatics, 2001\r\n# \'Peace Commision\':http://www.oi.edu.pl/php/show.php?ac=e100000&module=show&file=zadania/oi8/spokojna - Polish Olympiad in Informatics, 2001\r\n\r\nh2(#bibliografie). Bibliografie:\r\n\r\n# T. H. Cormen, C. E. Leiserson, R. R. Rivest - \'_Introducere in Algoritmi_\':http://zhuzeyuan.hp.infoseek.co.jp/ita/toc.htm\r\n# \'_Satisfiability_\':http://en.wikipedia.org/wiki/Satisfiability, Wikipedia\r\n# \'_BOI 2001 Competition Material_\':http://www.oi.edu.pl/download/boi-2001.pdf\r\n# \'_CEOI 2002 Competition Material_\':http://ics.upjs.sk/ceoi/Documents.html',2044,'public',NULL,NULL),('deque-si-aplicatii','Deque și aplicații','2009-01-22 22:28:12','2009-02-16 12:53:40','h1. Deque şi aplicaţii\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'_Introducere_\':deque-si-aplicatii#introducere\r\n* \'_Aplicaţii:_\':deque-si-aplicatii#problema-1\r\n** \'1. Book Pile &#40;SGU&#41;\':deque-si-aplicatii#problema-1\r\n** \'2. Vila 2 &#40;.campion, 2005&#41;\':deque-si-aplicatii#problema-2\r\n** \'3. Şir\':deque-si-aplicatii#problema-3\r\n** \'4. Platforma &#40;.campion, 2009&#41;\':deque-si-aplicatii#problema-4\r\n** \'5. Trans &#40;ONI 2004&#41;\':deque-si-aplicatii#problema-5\r\n** \'6. Otilia &#40;.campion, 2005&#41;\':deque-si-aplicatii#problema-6\r\n** \'7. Bcrc &#40;Stelele Informaticii, 2006&#41;\':deque-si-aplicatii#problema-7\r\n** \'8. Cut the Sequence &#40;PKU&#41;\':deque-si-aplicatii#problema-8\r\n* \'_Concluzii_\':deque-si-aplicatii#concluzii\r\n* \'_Probleme suplimentare_\':deque-si-aplicatii#probleme-suplimentare\r\n* \'_Bibliografie_\':deque-si-aplicatii#bibliografie\r\n\r\nÎn acest articol voi prezenta o structură de date de tip listă numită _deque_. Simplitatea acestei structuri poate că nu are multe de spus iar din acest motiv am prezentat şi o serie de aplicaţii care vor arăta surprinzătoarea sa utilitate în locurile unde am fi crezut că nu se mai poate face nimic pentru a reduce complexitatea.\r\n\r\nh2(#introducere). Introducere\r\n\r\nStructura de _deque_ (pronunţat de obicei _deck_) poate fi privit ca o colecţie de tip listă ce are două capete prin care se şterg sau inserează noi elemente. În literatura de specialitate aceste capete se numesc _head_ şi _tail_, iar dequeul mai este recunoscut şi ca fiind o coadă cu două capete _(double ended queue)_.\r\n\r\nImplementarea unui deque se poate face cu liste dublu înlănţuite ori cu un vector static când se cunoaşte numărul elementelor din colecţie. Ce trebuie reţinut este că limbajul C++ pune la dispoziţia utilizatorilor prin intermediul headerului _#include <deque>_ containerul \'_std::deque_\':http://www.cplusplus.com/reference/stl/deque/.\r\n\r\nh3(#operatii). Operaţii:\r\n\r\nMai jos sunt enumerate operaţiile care pot fi efectuate asupra unui deque împreună cu corespondentul lor în limbajul C++:\r\n\r\n* _front()_:	    întoarce primul element;\r\n* _back()_:	    întoarce ultimul element;\r\n* _push_front()_: inserează un element în faţă;\r\n* _push_back()_:  inserează un element în spate;\r\n* _pop_front()_:  scoate primul element;\r\n* _pop_back()_:   scoate ultimul element;\r\n* _empty()_:      întoarce _true_ dacă în deque nu se găseşte niciun element şi _false_ în caz contrar.\r\n\r\np=. !deque-si-aplicatii?new_deque.png 75%!\r\n\r\nToate aceste operaţii se execută în timp $O(1)$ \'amortizat\':http://en.wikipedia.org/wiki/Amortized_analysis. Pentru un plus de viteză va trebui să folosim un vector static cu dimensiunea egală cu numărul maxim de elemente ce pot trece prin deque, iar operaţiile implementate „de mână”, cu doi indecşi ce indică către head şi tail. Însă, în majoritatea aplicaţiilor limita de timp permite folosirea lejerităţii şi siguranţei clasei _std::deque_.\r\n\r\nÎn multe aplicaţii unde soluţiile parţiale se reprezintă sub forma unui şir continuu de valori care permite inserarea şi ştergerea doar pe la capete se poate folosi un deque. În general, se fac inserări pe la un capăt şi ştergeri pe la celălalt. Să urmărim în continuare cazuri concrete în care simplitatea unui deque duce la soluţii de multe ori optime şi implementări foarte scurte şi clare. Aplicaţiile sunt prezentate în ordinea crescătoare a dificultăţii şi din acest motiv recomand cu căldură tuturor celor care au de învăţat din acest articol să le parcurgă în ordine.\r\n\r\nh2(#problema-1). \'1. Book Pile\':http://acm.sgu.ru/problem.php?contest=0&problem=271 (SGU)\r\n\r\nbq. Se dau $N$ cărţi aşezate una deasupra celeilalte asupra cărora se vor efecta $M$ operaţii de două tipuri: 1. $ADD${$(nume)$} : se adaugă cartea $nume$ deasupra celorlalte; 2. $ROTATE$ : primele $K$ cărţi de deasupra se rotesc (dacă sunt mai puţin de $K$ cărţi atunci se vor roti toate). Se cere să se afişeze cărţile în ordine, prima fiind cea de deasupra, după efectuarea celor $M$ operaţii.\r\nRestricţii: $0 &le; N, K &le; 40 000$, $0 &le; M &le; 100 000$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se poate deduce urmând paşii următori. Să presupunem că iniţial avem cărţile $A B C$ şi $K = 3$. Dacă îl vom adăuga pe $D$, atunci nu vor rămâne importante decât cărţile $D A B$, deoarece, dacă vom roti ulterior ultimele $K$ cărţi, $C$ nu va mai fi niciodată considerat, cărţile fiind doar adăugate, iar o dată ce o carte iese din „top {$K$}” cărţi nu va mai fi posibil să i se schimbe poziţia pe raft. Să rotim acum „top {$K$}” cărţi. Noua ordine va fi $B A D$ şi $C$ pe raft la loc sigur. Dacă îl vom adăuga pe $E$, topul se va schimba în $E B A$ iar pe raft, în mod sigur vor fi, în această ordine, $D C$. Proprietatea celor $K$ cărţi din vârf este: o secvenţă continuă de elemente, la care se adaugă noi elemente sau se elimină dintre acestea numai pe la _capete_. Aceste capete sunt chiar head şi tail ale unui deque.\r\n\r\np=. !deque-si-aplicatii?bookpile.png 40%!\r\n\r\nLa final, când se vor termina operaţiile, cărţilor de pe raft li se vor adăuga cele din deque şi se va afişa soluţia. În cazul presupus, soluţia va fi: $E B A D C$.\r\n\r\nÎntrucât operaţiile unui deque se execută în $O(1)$ amortizat, soluţia are complexitatea $O(N + M)$.\r\n\r\nh2(#problema-2). \'2. Vila 2\':problema/vila2 (.campion, 2005)\r\n\r\nbq. Se dă un şir $S$ de $N$ numere întregi şi un $D$ număr natural. Se cere să determine diferenţa maximă dintre oricare două numere din şir cu proprietatea că diferenţa indicilor nu depăşeşte $D$.\r\nRestricţii: $2 &le; N &le; 100 000$, $1 &le; D &le; N/2$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia nu este greu de intuit. Dacă vom considera indicii $1$, $2$, .. , $N$ succesiv va trebuie ca pentru fiecare secvenţă $(i - D, i]$ să determinăm valoarea maximă şi pe cea minimă, iar diferenţa lor să o comparăm cu rezultatul obţinut până în acel moment. Pentru fixarea ideilor, să urmărim cum putem determina valoarea maximă din fiecare secvenţă $(i - D, i]$.\r\n\r\n_Observaţie_: „Fie $i{~1~}$, $i{~2~}$ doi indici astfel încât $i - D &lt; i{~1~} &lt; i{~2~} &le; i$.\r\n\r\n# Dacă $S[i{~1~}] &lt; S[i{~2~}]$ atunci, cât timp cei doi indici vor fi în intervalul $(i - D, i]$, valoarea de pe poziţia $i{~2~}$ va fi întotdeauna preferată valorii de pe poziţia $i{~1~}$. Când unul din indici nu va mai fi în acest interval, cel expediat va fi $i{~1~}$ şi, astfel, $i{~2~}$ rămâne în continuare preferat.\r\n# Dacă $S[i{~1~}] &gt; S[i{~2~}]$ atunci îl vom păstra pe $i{~2~}$, deoarece este candidat la maxim în viitor.”\r\n\r\nCu această observaţie deducem că într-o secvenţă $(i - D, i]$ vom avea un şir $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$ astfel încât $S[i{~1~}] &gt; S[i{~2~}] &gt; ... &gt; S[i{~K~}]$. Când vom avansa la secvenţa următoare, $(i - D + 1, i + 1]$, vom şterge din indicii $i{~1~}$, $i{~2~}$... atâta timp cât nu se găsesc în intervalul curent şi vom şterge din poziţiile $i{~K~}$, $i{~K-1~}$... cât timp $S[i + 1] &gt; S[i{~K~}]$, $S[i + 1] &gt; S[i{~K-1~}]$... adică cât timp se îndeplineşte primul punct din observaţia anterioară.\r\n\r\nŞirul $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$ este continuu iar operaţiile se efectuează doar pe la cele două capete. Rezultă că şirul poate fi implementat cu ajutorul unui deque.\r\n\r\nPentru $S[] = {5, 9, 4, 7, 4, 1}$ şi $D = 3$ obţinem următoarele stări ale unui deque:\r\n\r\n* <tex> \\langle \\widehat{5\\ [1]} \\rangle; </tex>\r\n* <tex> \\langle 5\\ [1] \\rangle \\Leftarrow 9\\ [2] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]} \\rangle; </tex>\r\n* <tex> \\langle 9\\ [2] \\rangle \\Leftarrow 4\\ [3] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 4\\ [3] \\rangle; </tex>\r\n* <tex> \\langle 9\\ [2],\\ 4\\ [3] \\rangle \\Leftarrow 7\\ [4] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 7\\ [4] \\rangle; </tex>\r\n* <tex> 9\\ [2] \\Leftarrow \\langle 7\\ [4] \\rangle \\Leftarrow 4\\ [5] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5] \\rangle; </tex>\r\n* <tex> \\langle 7\\ [4],\\ 4\\ [5] \\rangle \\Leftarrow 1\\ [6] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5],\\ 1\\ [6] \\rangle; </tex>\r\n\r\nCum fiecare indice din $1$, $2$, .., $N$ trece cel mult o dată prin deque, complexitatea finală este $O(N)$ amortizat.\r\n\r\nh2(#problema-3). \'3. Şir\':problema/sir\r\n\r\nbq. Se dă un şir $S$ de numere întregi de lungime $N$. Se cere să se găsească secvenţa de lungime maximă cuprinsă între $X$ şi $Y$ astfel încât $MAX - MIN &le; Z$, unde $MAX$ este maximul dintre toate numerele întregi din secvenţă iar $MIN$ minimul dintre acestea. Secvenţa soluţie va fi cea cu poziţia de început maximă dintre toate secvenţele de lungime maximă.\r\nRestricţii: $3 &le; N &le; 100 000$, $1 &le; X &le; Y &le; N$, $0 &le; Z &le; 30 000$.\r\n\r\nh3. Soluţie:\r\n\r\nVoi prezenta mai jos o rafinare a soluţiei în trei paşi.\r\n\r\nPrima rezolvare se găseşte uşor, deoarece nu facem decât să urmărim textul: pentru fiecare poziţie $i$ fixată ({$i$} ia valorile $1$, $2$, .., $N$ succesiv) vom determina pentru aceasta secvenţa cerută, adică vom plimba un $j$ între poziţiile $i - Y$ şi $i - X$. Pentru un interval $(j, i]$ vom determina $MAX$ şi $MIN$ în $O(log{~2~}N)$ cu un arbore de intervale, iar daca diferenţa dintre acestea nu depăşeşte $Z$ vom compara cu soluţia finală. Complexitatea finală va fi $O(N * (Y - X) * log{~2~}Y)$.\r\n\r\nSă presupunem că pentru poziţia curentă $i$, l-am găsit pe $j$ cât mai mic cuprins între $i - Y$ şi $i - X$ astfel încât secvenţa $(j, i]$ este candidată la soluţie. Ce proprietăţi are $j$?\r\n\r\n* $i - Y &le; j &le; i - X$ şi $MAX - MIN &le; Z$;\r\n* dacă îl incrementăm pe $j$ la $j + 1$ atunci dacă $j &le; i - X$ cu siguranţă $MAX - MIN &le; Z$ şi astfel soluţia va fi mai scurtă;\r\n* dacă îl decrementăm pe $j$, atunci ori $j < i - Y$ ori $MAX - MIN > Z$;\r\n* dacă îl incrementăm pe $i$ la $i + 1$, atunci se poate întâmpla ca $j < i - Y$; cum $MAX$ nu poate decât să crească, iar $MIN$ decât să scadă, se mai poate de asemenea întâmpla ca $MAX - MIN > Z$.\r\n\r\nDatorită proprietăţilor de mai sus, când trecem de la $i$ la $i + 1$, valoarea lui $j$ nu poate decât să crească cât timp $j < i - Y$ sau $MAX - MIN > Z$ şi $j$ nu a depăşit poziţia $i - X$. Pentru determinarea lui $MAX$, respectiv lui $MIN$ se poate folosi un arbore de intervale. Complexitatea finală va fi $O(N * log{~2~}(Y))$.\r\n\r\nCu cei doi indici $i$ şi $j$ vom accesa fiecare element din cele $N$ de cel mult $2$ ori, o dată cu $i$ şi o dată cu $j$. Să vedem cum putem îmbunătăţi complexitatea $O(log{~2~}Y)$ pentru determinarea maximului şi minimului.\r\n\r\nPentru fixarea ideilor să urmărim cum îl vom calcula pe $MAX$. Observaţia care ne ajută în multe probleme pentru reducerea complexităţii de la $O(log{~2~}N)$ la $O(1)$ amortizat este următoarea: \r\n\r\n_Observaţie_: „Fixăm $i{~1~}$ şi $i{~2~}$ astfel încât $j < i{~1~} < i{~2~} &le; i$. Atunci, dacă $S[i{~2~}] > S[i{~1~}]$ poziţia $i{~2~}$ va fi întotdeauna mai importantă decât poziţia $i{~1~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ şi $i{~2~}$ nu vor mai fi ambele în intervalul $(j, i]$, poziţia eliminată va fi {$i{~1~}$}. Dacă însă $S[i{~1~}] > S[i{~2~}]$, atunci poziţia $i{~1~}$ va umbri poziţia $i{~2~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ va fi eliminat, atunci e posibil ca $i{~2~}$ să fie un candidat la $MAX$ dintre restul elementelor de la dreapta sa. În acest caz, nu putem afirma nimic şi vom păstra cele două poziţii.”\r\n\r\nRezultă din această observaţie că în intervalul $(j, i]$ poziţiile importante vor fi $j < i{~1~} < i{~2~} < .. < i{~k~} <= i$ astfel încât $S[i{~1~}] > S[i{~2~}] > .. > S[i{~k~}]$. Astfel, $MAX$ va fi $S[i{~1~}]$. Când îl vom incrementa pe $i$ la $i + 1$ vom şterge din poziţiile $i{~k~}$, $i{~k-1~}$, ... atâta timp cât $S[i + 1]$ este mai important, adică mai mare decât valorile de pe aceste poziţii, şi vom şterge $i{~1~}$, $i{~2~}$, ... atâta timp cât aceste poziţii sunt mai mici sau egale decât $j\'$. Indicele $j\'$ este noul optim pentru poziţia $i + 1$. Proprietatea şirului de poziţii $i{~1~}, i{~2~}, .., i{~k~}$ este că se reprezintă ca un şir continuu de numere care permite inserarea elementelor prin dreapta şi ştergerea prin stânga, adică se adaugă elemente la tail şi se şterg elemente de la head. Îl putem deci reprezenta printr-un deque. Complexitatea $O(1)$ amortizat provine de la faptul că fiecare poziţie dintre cele $N$ nu trece decât o singură dată prin deque şi este şters tot cel mult o singură dată. \r\n\r\nÎn practică, pseudocodul poate arăta în felul următor:\r\n\r\n== code(cpp) |\r\n// S şirul de numere iniţial şi N lungimea sa\r\n\r\nSubalgoritmul push_in(deque, întreg p, funcţia fct) este:\r\n    cât timp (!deque.empty() şi fct(S[p], S[deque.back()])) execută\r\n        deque.pop_back();\r\n    deque.push_back(p);\r\nSfârşit;\r\n\r\nFuncţia query(deque, întreg j) este:\r\n    cât timp (!deque.empty() şi deque.front() <= j) execută\r\n        deque.pop_front();\r\n    return S[deque.front()];\r\nSfârşit;\r\n\r\nAlgoritmul este:\r\n    lg = 0;\r\n    pentru i = 1, N execută\r\n        // funcţia min(a, b) întoarce true dacă a < b\r\n        inserează(min_deq, i, min);\r\n        // funcţia max(a, b) întoarce true dacă a > b\r\n        inserează(max_deq, i, max);\r\n        cât timp ((j < i - Y sau query(max_deq, j) - query(min_deq, j) > Z) şi j < i - X) execută\r\n            j = j + 1;\r\n        // (j, i] este intervalul candidat la soluţia optimă pentru poziţia i\r\n        dacă (j <= i - X) şi (query(max_deq, j) - query(min_deq, j) <= Z) atunci\r\n            dacă (lg >= i - j) atunci\r\n                lg = i - j, start = j + 1, stop = i;\r\n    sfârşit_pentru\r\n\r\n    dacă (lg > 0) atunci\r\n        scrie lg, start, stop;\r\n    altfel\r\n        scrie -1;\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală va fi $O(N)$.\r\n\r\nh2(#problema-4). \'4. Platforma\':http://campion.edu.ro/problems/3/509/platforma_ro.htm (.campion, 2009)\r\n\r\nbq. Se dă o matrice $P$ de dimensiuni $M x N$ cu elemente numere întregi. Se defineşte valoarea maximă dintr-un dreptunghi de dimensiuni $R x C$ ca fiind valoarea maximă dintre elementele aflate în acel dreptunghi.\r\nCerinţă: Să se găsească un dreptunghi de dimensiuni $R x C$ cu valoarea maximă minimă.\r\nRestricţii: $1 &le; M, N &le; 1000$, $1 &le; R &le; M$, $1 &le; C &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nAceastă problemă reprezintă o extindere în două dimensiuni a problemei anterioare \'Vila 2\':deque-si-aplicatii#problema-2, unde am studiat cazul unidimensional al determinării pe un vector a maximului / minimului pentru fiecare subsecvenţă de o lungime fixată.\r\n\r\nCerinţa constă în amplasarea unui dreptunghi $R x C$ astfel încât valoarea maximă din interiorul său să fie cât mai mică. Una din ideile simple constă în fixarea colţului din stânga sus în toate cele $(M - R) x (N - C)$ poziţii şi determinarea maximului din interiorul său cu o altă parcurgere a celor $R x C$ elemente. Dar, să fixăm o linie $i$. Atunci, pentru a fixa colţul din stânga sus mai iterăm cu un indice $j$ între coloanele $1$ şi $N-C+1$. De aici devine clar că atunci când avansăm indicele coloanei în dreptunghiul curent apare o nouă coloană, $j + C$, şi dispare coloana curentă $j$. Dacă pentru fiecare coloană $j$ de pe linia curentă $i$ reţinem un $Max{~i,j~}$ egal cu maximul dintre elementele $P{~i,j~}, P{~i+1,j~},.. P{~i+R-1,j~}$, atunci pe linia fixată $i$ vom avea un vector din $N$ elemente (numărul de coloane al matricei $P$) alcătuit din valorile $Max{~i,1~}, Max{~i,2~}, Max{~i,3~},.. Max{~i,j~},.. Max{~i,N-1~}, Max{~i,N~}$. Iar pe acest vector va trebui să determinăm pentru fiecare subsecvenţă de $C$ elemente, valoarea maximă. Dintre toate subsecvenţele o vom alege pe cea cu valoarea maximă cea mai mică. Iar acest rezultat va fi o soluţie pentru linia fixată. Cu valorile din $Max$ precalculate, pentru fiecare linie avem complexitatea $O(N)$, deci $O(M * N)$ pentru întreaga matrice. Însă, implementând direct, valorle din $Max$ se calculează în $O(M * N * R)$. Mai sus am definit $Max{~i,j~}$ ca fiind maximul dintre $P{~i,j~}, P{~i+1,j~},.. P{~i+R-1,j~}$. Rezultă că $Max{~i+1,j~}$ este maximul dintre $P{~i+1,j~}, P{~i+2,j~},.. P{~i+R-1,j~}, P{~i+R,j~}$, adică maximul dintre elementele lui $Max{~i,j~}$ din care scoatem $P{~i,j~}$ şi adăugăm $P{~i+R,j~}$. De aici deducem că pentru fiecare coloană fixată, valorile lui $Max$ de pe coloana respectivă se reduc la a determina pentru fiecare subsecvenţă de lungime $R$ (numărul de linii al dreptunghiului de amplasat) elementul maxim. Aceste rezultate se obţin în $O(M)$ pentru fiecare coloană, deci $O(N * M)$ în total.\r\n\r\nRezultă complexitatea finală $O(M * N)$.\r\n\r\nh2(#problema-5). \'5. Trans\':problema/trans (ONI 2004)\r\n\r\nbq. Se dau $N$ blocuri de piatră, de culoare albă sau neagră aşezate în ordinea $1$, $2$,.., $N$. Blocurile de piatră trebuie să fie transportate în ordinea în care sunt, iar pentru aceasta va trebui închiriat un camion. Se mai dau $Q$ tipuri de camioane. Camionul de tipul $i (1 &le; i &le; Q)$ poate transporta maxim $K{~i~}$ blocuri de piatră la un moment dat şi pentru un transport se percepe taxa $T{~i~}$. Se impune condiţia ca toate blocurile de piatră plasate în camion la un transport sa aibă aceeaşi culoare. Aşadar, pentru a fi transportate toate blocurile, se va alege un camion de un anumit tip, iar camionul va efectua unul sau mai multe transporturi. Pentru a micşora suma totală plătită, există posibilitatea de a schimba culoarea oricărui bloc de piatră (din alb în negru sau din negru în alb); pentru fiecare bloc $i (1 &le; i &le; N)$ se cunoaşte suma $S{~i~}$ ce trebuie plătită pentru a-i schimba culoarea $C{~i~}$.\r\nCerinţă: Pentru fiecare dintre cele $Q$ tipuri de camioane, determinaţi suma minimă plătită pentru a transporta toate cele $N$ blocuri.\r\nRestricţii: $1 &le; N &le; 16 000$, $1 &le; Q &le; 100$, $1 &le; K{~i~} &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se bazează pe găsirea unei formule de recurenţă ce respectă principiul optimalităţii al metodei programării dinamice.\r\n\r\nPentru început, fixăm un camion dintre cele <tex> Q </tex>. Fie <tex> K </tex> numărul maxim de pietre pe care acesta le poate transporta şi <tex> T </tex> taxa percepută. Notăm <tex> sum_{i,c} </tex> costul pentru a schimba toate pietrele <tex> 1, 2, \\ldots, i </tex> în culoarea <tex> c </tex> (<tex> c = 0 </tex> pentru alb şi <tex> c = 1 </tex> pentru negru). Rezultă că în <tex> sum_{i,c} </tex> se vor însuma toate valorile <tex> S_{j} </tex>, cu <tex> j \\le i </tex> pentru care <tex> C_{j} = 1 - c </tex>. \r\n\r\nÎn continuare, considerăm <tex> bst_{i,c} </tex> costul minim pentru a transporta pietrele <tex> 1, 2, \\ldots, i </tex>, iar ultimul transport conţine pietre de culoare <tex> c </tex>. Întrucât nu putem transporta mai mult de <tex> K </tex> pietre, <tex> bst_{i,c} </tex> depinde doar de poziţiile <tex> i - K, i - K + 1, \\ldots, i - 1 </tex>. Cunoaştem că ultimul camion va transporta o secvenţă continuă de pietre începând de la o poziţie <tex> j + 1 </tex> până la poziţia <tex> i </tex>, unde <tex> i - K \\le j \\le i - 1 </tex>. Astfel, pentru  fiecare <tex> j </tex> în intervalul precedent, costul va fi <tex> Min(bst_{j,0}, bst_{j,1}) </tex> (transportăm primele <tex> j </tex> pietre cât mai ieftin) adunat cu <tex> sum_{i,c} - sum_{j,c} </tex> (costul transformării pietrelor <tex> j + 1, \\ldots, i </tex> în culoarea <tex> c </tex>) şi plus taxa <tex> T </tex>. Rezultă recurenţa:\r\n\r\n* <tex> bst_{i,c} = Min\\ \\{\\ Minim(bst_{j,0},\\ bst_{j,1}) + sum_{i,c} - sum_{j,c} + T\\ :\\ i - K \\le j \\le i - 1\\ \\}; </tex>\r\n\r\nDacă ne vom opri aici, complexitatea soluţiei va fi <tex> O(Q * N^{2}) </tex>.\r\n\r\nRelaţia de recurenţă poate fi îmbunătăţită. Observăm că pentru poziţia <tex> i </tex>, <tex> sum_{i,c} </tex> este o valoare constantă, ca şi <tex> T </tex>. Astfel, deducem următoarea relaţie de recurenţă:\r\n\r\n* <tex> bst_{i,c} = Min\\ \\{\\ Minim(bst_{j,0},\\ bst_{j,1}) - sum_{j,c}\\ :\\ i - K \\le j \\le i - 1\\ \\} + sum_{i,c} + T; </tex>\r\n\r\nNotez în continuare, pentru uşurinţă în scriere, <tex> T_{j,c} = Min(bst_{j,0}, bst_{j,1}) - sum_{j,c} </tex>. Să fixăm doi indici <tex> i_{1} </tex> şi <tex> i_{2} </tex>, astfel încât <tex> i - K \\le i_{1} < i_{2} \\le i - 1 </tex>. Dacă <tex> T_{i_{1},c} > T_{i_{2},c} </tex> atunci întotdeauna poziţia <tex> i_{2} </tex> va fi preferată poziţiei <tex> i_{1} </tex>. Când cele două nu se vor mai afla ambele în intervalul <tex> [i - K, i - 1] </tex>, poziţia eliminată va fi poziţia <tex> i_{1} </tex>. Dacă <tex> T_{i_{1},c} < T_{i_{2},c} </tex>, atunci nu putem decide care poziţie este mai bună în viitor, aşa că le vom păstra pe ambele. Rezultă mai departe că în intervalul <tex> [i - K, i - 1] </tex> vom avea o serie de indecşi candidaţi la minim <tex> i - K \\le i_{1} < i_{2} < \\ldots < i_{n} \\le i - 1 </tex> astfel încât <tex> T_{i_{1},c} < T_{i_{2},c} <  .. < T_{i_{n},c} </tex>. Mai departe, găsim <tex> bst_{i,c} = T_{i_{1},c} + sum_{i,c} + T </tex>. Urmează să îl introducem şi pe <tex> T_{i,c} </tex> în şirul de indecşi de mai sus, el fiind egal cu <tex> Minim(bst_{i,0}, bst_{i,1}) - sum_{i,c} </tex>. Acest lucru se va face în felul următor: se vor elimina din <tex> i_{n}, , i_{n-1}, \\ldots </tex> atâta timp cât <tex> T_{i_{n},c} > T_{i,c} </tex>, <tex> T_{i_{n-1},c} > T_{i,c} \\ldots </tex> adică atâta timp cât poziţia <tex> i </tex> este preferată lui <tex> i_{n}, i_{n-1}, \\ldots </tex>. Fiind la poziţia <tex> i + 1 </tex>, intervalul se va transforma în <tex> [i - K + 1, i] </tex>, aşadar, vom mai elimina din primii indici <tex> i_{1}, i_{2}, \\ldots </tex> atâta timp cât <tex> i_{1} < i - K + 1, i_{2} < i - K + 1, \\ldots </tex>.\r\n\r\nDupă cum am arătat şi la problema precedentă, acest şir de indecşi <tex> i_{1}, i_{2}, \\ldots, i_{n} </tex> are proprietatea că este un şir continuu de numere care admite inserări prin dreapta (tail) şi ştergeri prin stânga (head). Şir ce poate fi reprezentat printr-un deque. Cum fiecare index dintre <tex> 1, 2, \\ldots, N </tex> va trece o singură dată prin deque, complexitatea soluţiei va fi <tex> O(N) </tex> pentru fiecare camion, deci <tex> O(Q * N) </tex> în total.\r\n\r\nÎn practică, programul este scurt, clar şi eficient:\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\n#include <vector>\r\n#include <deque>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\nconst char iname[] = \"trans.in\";\r\nconst char oname[] = \"trans.out\";\r\n\r\n#define MAXN  16005\r\n#define Min(a, b) ((a) < (b) ? (a) : (b))\r\n#define FOR(i, a, b)  for (int i = (a); i <= (b); ++ i)\r\n\r\nint C[MAXN], S[MAXN], bst[MAXN][2], sum[MAXN][2], N;\r\n\r\nvoid insert(deque < pair <int, int> >& deq, const pair <int, int>& p) {\r\n    while (!deq.empty() && deq.back().second > p.second)\r\n        deq.pop_back();\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque < pair <int, int> >& deq, const int idx) {\r\n    while (deq.front().first < idx)\r\n        deq.pop_front();\r\n    return deq.front().second;\r\n}\r\n\r\nint work(const int K, const int T) {\r\n    deque < pair <int, int> > deq[2];       // pair (idx, value)\r\n    FOR (c, 0, 1)\r\n        insert(deq[c], pair <int, int>(0, 0));\r\n    FOR (i, 1, N) {   // obiectul i\r\n        FOR (c, 0, 1) // culoare\r\n            bst[i][c] = query(deq[c], i - K) + sum[i][c] + T;\r\n        FOR (c, 0, 1)\r\n            insert(deq[c], pair <int, int>(i, Min(bst[i][0], bst[i][1]) - sum[i][c]));\r\n    }\r\n    return Min(bst[N][0], bst[N][1]);\r\n}\r\n\r\nint main(void)\r\n{\r\n    ifstream in(iname);  ofstream out(oname);\r\n    in >> N;\r\n    FOR (i, 1, N) {\r\n        in >> C[i] >> S[i];\r\n        FOR (c, 0, 1)\r\n            sum[i][c] += sum[i - 1][c];\r\n        sum[i][1 - C[i]] += S[i];\r\n    }\r\n    int cnt, K, T;\r\n    in >> cnt;\r\n    FOR (i, 1, cnt)\r\n        in >> K >> T, out << work(K, T) << \"\\n\";\r\n\r\n    in.close(), out.close();\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#problema-6). \'6. Otilia\':problema/otilia  (.campion, 2005)\r\n\r\nbq. Otilia şi Burbucel au o grămadă de $N$ pietre şi vor juca un joc cu următoarele trei reguli: 1. Primul jucător are voie să ia din gramadă cel mult $K$ piese; 2. Cu excepţia primei mutări, fiecare jucător are voie să ia maxim $P * t$ pietre, unde $t$ este numărul de pietre care au fost substituite din grămadă la mutarea precedentă; 3. Pierde cel care mută ultimul (cel care ia ultimele pietre din grămadă).\r\nCerinţă: Se dau $M$ jocuri prin numerele $N$, $K$ şi $P$. Se cere să se determină dacă Otilia va câştiga fiecare din jocuri sau nu.\r\nRestricţii: $1 &le; M &le; 30 000$, $1 &le; N &le; 5 000 000$, $1 &le; K &le; N$, $1 &le; P &le; 10$.\r\n\r\nh3. Soluţie (Silviu Ganceanu):\r\n\r\nProblema se rezolvă prin programare dinamică. Soluţia se bazează pe observaţia de mai jos. Considerăm $P$-ul fixat şi notăm cu $stare(X, Y)$ poziţia de start în care avem $X$ pietre şi numărul maxim de pietre care se pot lua la prima mutare este $Y$.\r\n\r\n_Observaţia 1_: „Dacă există strategie sigură de câştig pentru $stare(X, Y)$ atunci există şi pentru orice $stare(X, T)$ cu $T &ge; Y$.” \r\n\r\nDe ce? Pentru că orice mutare validă pentru $stare(X, Y)$ este validă şi pentru $stare(X, T)$. Având această observaţie notăm cu $MinY[X] = Y$, $Y$ minim astfel încât avem strategie de câştig pentru $stare(X, Y)$.\r\n\r\n_Observaţia 2_: „{$stare(X, Y)$} este pierzătoare dacă şi numai dacă $Y < MinY[X]$.” \r\n\r\nAceasta reiese din definiţia lui $MinY[X]$.\r\n\r\n$MinY[X]$ se calculează după următoarea recurenţă, care rezultă din regulile jocului: \r\n\r\n* $MinY[X]$ este cel mai mic $i$ pentru care avem $MinY[X - i] > P * i$.\r\n\r\nDe aici se naşte prima soluţie, care este implementarea directă a recurenţei. Deşi complexitatea acesteia pare a fi $O(N^2^)$ ea se comportă foarte bine pentru $N &le; 500 000$. Aşadar, această soluţie acoperă aproximativ $50%$ din testele de intrare. Printr-o rafinare a acestei soluţii se obţine un algoritm de complexitate $O(N)$. Rafinarea se bazează pe: \r\n\r\n_Observaţia 3_: „Să presupunem că dorim să calculăm $MinY[X]$. Facem următoarea afirmaţie: orice poziţie _rea_ pentru $X$ (în care dacă mutăm pierdem) va fi _rea_ şi pentru $X + 1$.”\r\n\r\nAcest lucru este simplu de observat dacă privim ce înseamnă că o poziţie $Q$ e rea pentru $X$: \r\n\r\n* $MinY[Q] > X - Q$, pentru $X$;\r\n* $MinY[Q] > X - Q + 1$, pentru $X + 1$.\r\n\r\nEste evident că prima relaţie o implică pe cea de-a doua. În momentul acesta se poate construi următorul algoritm: având lista de poziţii care pot fi bune pentru $X$ (sortată descrescător) o căutăm pe cea mai mare ca valoare care este într-adevăr bună. În principiu, scoatem din capul listei poziţiile rele până când dăm de o poziţie bună. La listă se va adăuga şi $X$ şi se va trece la pasul următor. Operaţiile algoritmului sunt chiar operaţiile asupra unui deque.\r\n\r\nh2(#problema-7). \'7. Bcrc\':problema/bcrc (Stelele Informaticii, 2006)\r\n\r\nbq. Se consideră $N$ camere, numerotate de la $1$ la $N$, aşezate în cerc. Iniţial (la momentul de timp 0), ne aflăm în camera $1$. În fiecare moment de timp, putem alege să rămânem în camera în care ne aflăm sau să ne deplasăm într-o cameră vecină într-o unitate de timp. Se dă o listă de $M$ cutii ce conţin bomboane prin $T$, $C$ şi $B$: cutia apare la momentul $T$ în camera $C$ şi conţine $B$ bomboane. Cutia va dispărea la momentul $T + 1$.\r\nCerinţă: Cunoscând numărul de camere din labirint şi momentele de timp la care apar cutiile cu bomboane, determinaţi care este numărul maxim de bomboane pe care le putem culege.\r\nRestricţii: $3 &le; N &le; 2 048$, $0 &le; M &le; 50 000$, $1 &le; T &le; 1 000 000 000$, $1 &le; C &le; N$, $1 &le; B &le; 9 999$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia foloseşte metoda programării dinamice.\r\n\r\nO stare se reprezintă prin camera în care ne aflăm şi momentul de timp. Fie <tex> bst_{i,j} </tex> numărul maxim de bomboane culese până în momentul <tex> i </tex> când ne găsim în camera <tex> j </tex>. O observaţie evidentă este că <tex> bst_{i,j} </tex> se poate modifica doar în momentele în care apar cutiile. Prin urmare, vom considera momentele de timp când apar cutiile, momente ce sunt în număr de <tex> M </tex>, <tex> bst_{i,j} </tex> însemnând numărul maxim de bomboane culese ştiind că ne aflăm în camera <tex> j </tex> unde am cules cutia <tex> i </tex>. De cine depinde această stare? Ştim că <tex> bst_{i-1,1 \\ldots N} </tex> a fost deja calculat în mod optim. Să notăm cu <tex> T </tex> diferenţa de timp dintre momentele la care apare cutia <tex> i </tex> şi cutia <tex> i - 1 </tex>. În această stare, <tex> i </tex> şi cameră <tex> j </tex>, putem ajunge din maxim <tex> T </tex> camere spre stânga sau spre dreapta, întrucât fiecare deplasare între două camere costă o unitate de timp. De unde deducem că:\r\n\r\n* <tex> bst_{i,j} = Min\\{\\ bst_{i-1,j-T},\\ bst_{i-1,j-T+1}, \\ldots,\\ bst_{i-1,j}, \\ldots,\\ bst_{i-1,j+T-1},\\ bst_{i-1,j+T}\\ \\}; </tex>\r\n\r\nMetoda directă, şi aparent eficientă, constă în folosirea unui arbore de intervale pentru aflarea acestui minim. Însă, intervalul <tex> [j-T,j+T] </tex> se deplasează constant spre dreapta, dacă vom considera indicii <tex> j </tex> în ordine <tex> 1, 2, 3, \\ldots </tex>. În acest interval noile elemente se introduc prin dreapta şi altele se elimină prin stânga. Însă, cum am arătat în problemele precedente, nu avem nevoie de toate valorile din acest interval. Şi din acest motiv vom folosi un deque de lungime <tex> T * 2 + 1 </tex> cu care vom elimina poziţiile care nu sunt candidate la soluţie. Mai jos este o reprezentare grafică a acestei explicaţii.\r\n\r\np=. !deque-si-aplicatii?bcrc.png 40%!\r\n\r\nComplexitatea finală: <tex> O(M * N) </tex>.\r\n\r\nh2(#problema-8). \'8. Cut the Sequence\':http://acm.pku.edu.cn/JudgeOnline/problem?id=3017 (PKU) \r\n\r\nbq. Se dă o secvenţă $S$ de numere întregi de lungime $N$. Va trebui să se împartă secvenţa în mai multe subsecvenţe astfel încât suma valorilor din fiecare parte să nu depăşească un număr întreg $M$ dat, iar dacă însumăm maximul din fiecare subsecvenţă să obţinem o sumă cât mai mică.\r\nRestricţii: $0 &lt; N &le; 100 000$, $0 &le; S{~i~} &le; 1 000 000$.\r\n\r\nh3. Soluţie:\r\n\r\nŞi această soluţie foloseşte metoda programării dinamice. Construim <tex> bst_{i} </tex> egal cu costul minim de a împărţi primele <tex> i </tex> numere din <tex> S </tex>. Pentru a calcula <tex> bst_{i} </tex> alegem toate secvenţele posibile care încep la o poziţie <tex> j+1 </tex>, <tex> j < i </tex>, şi adunăm valorile corespunzătoare:\r\n\r\n* <tex> bst_{i} = Min\\{bst_{j} + Max\\{S_{j+1},.., S_{i}\\}\\ :\\ 0 \\le j < i, \\displaystyle\\sum_{k=j+1}^{i} S_{k} \\le M\\}; </tex>\r\n\r\nImplementarea directă a acestei recurenţe conduce la un algoritm de complexitate <tex> O(N^{2}) </tex>, dar care pentru restricţiile impuse nu este de ajuns.\r\n\r\nSă obţinem în continuare alte informaţii. Fie indicele <tex> j </tex> minim astfel încât <tex> \\displaystyle\\sum_{k=j+1}^{i} \\le M </tex>. Maximul obţinut din mulţimea <tex> \\{S_{j+1},.., S_{i}\\} </tex> se găseşte pe o poziţie <tex> j^{\'} </tex> unde <tex> j < j^{\'} \\le i </tex>. Însă, orice indice <tex> k </tex> cu <tex> j \\le k < j^{\'} </tex> are proprietatea că rezultatul expresiei <tex> Max\\{S_{k+1},.., S_{i}\\} </tex> se găseşte pe poziţia <tex> j^{\'} </tex>. Rezultă că <tex> \\forall k \\in \\{j, j+1,.., j^{\'}-1\\} </tex>, <tex> bst_{i} </tex> poate fi îmbunătăţit cu valoarea <tex> bst_{k} + S_{j^{\'}} </tex>. Minimul mulţimii <tex> \\{bst_{k} + S_{j^{\'}} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} </tex> este egal cu minimul expresiei <tex> \\{bst_{k} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} + S_{j^{\'}} (*) </tex>, deci, schimbând reperele, pentru maximul de pe poziţia <tex> j^{\'} </tex>, dacă lungimea secvenţei care se termină în <tex> i </tex> este cel puţin <tex> i-j^{\'}+1 </tex>, atunci optimul se obţine calculând rezultatul expresiei <tex> (*) </tex>. Pentru minimul pe un interval, <tex> [j, j^{\'}-1] </tex> al valorile vectorului <tex> bst </tex>, putem folosi un arbore de intervale pentru <tex> O(log_{2}N) </tex> pe interogare.\r\n\r\nDar, lungimea optimă a ultimei secvenţe ce se termină în <tex> i </tex> poate fi mai mică decât <tex> i-j^{\'}+1 </tex>, deci poate fi cel mult <tex> i-j^{\'} </tex>. Optimul se găseşte printre elementele mulţimii <tex> \\{bst_{k} + Max\\{S_{k+1},..,S_{i}\\} : j^{\'} \\le k < i\\} </tex>. Dacă procedăm ca la pasul anterior vom obţine un alt indice <tex> j^{\'\'} </tex> cu aceleaşi proprietăţi pentru secvenţa <tex> [j^{\'}, i] </tex> precum <tex> j^{\'} </tex> pentru secvenţa <tex> [j, i] </tex>.\r\n\r\nInductiv obţinem un şir de indici <tex> j_{0} = j < j_{1} < j_{2} < .. < j_{K} = i </tex> astfel încât <tex> S_{j_{1}} </tex> este cel mai mare element al secvenţei <tex> (j, i] </tex>, <tex> S_{j_{2}} </tex> cel mai mare element al secvenţei <tex> (j_{1}, i] </tex>, şi aşa mai departe, când <tex> j_{K} </tex> este chiar <tex> i </tex>.\r\n\r\nCu ajutorul relaţiei <tex> (*) </tex> şi a şirului <tex> j_{1} < j_{2} < .. < j_{K} = i </tex> vom construi un alt vector <tex> iMin </tex> cu proprietatea că <tex> iMin_{p} = Min\\{bst_{r} + S_{j_{p}} : j_{p-1} \\le r < j_{p}\\} </tex>. În final, <tex> bst_{i} = Minim\\{iMin_{1}, iMin_{2}, .., iMin_{K}\\} </tex>, rezultat pe care îl putem obţine în <tex> O(log_{2}N) </tex> dacă folosim un arbore de intervale.\r\n\r\nÎnsă, cum se construieşte şirul <tex> j_{1} < j_{2} < .. < j_{K} = i </tex>? În \'a doua problemă\':deque-si-aplicatii#problema-2 am construit cu ajutorul unui deque exact şirul de indici de care avem nevoie aici. Când vom înainta la indicele <tex> i + 1 </tex> vom modifica şirul astfel încât să respecte proprietăţile de mai sus utilizând operaţiile normale asupra unui deque. Mai sus am menţionat cum se obţine <tex> bst_{i} </tex> lucru care implică combinarea structurilor de deque şi arbore de intervale. Arborele de intervale reţine valorile lui <tex> iMin </tex> pentru fiecare element al dequelui. \r\n\r\nPentru a înţelege cum funcţionează acest algoritm să considerăm ca date de intrare şirul <tex> S = \\{5, 9, 4, 7, 4, 1, 6, 3\\} </tex> şi <tex> M = 15 </tex>. Perechile din deque sunt de forma <tex> (S_{i}, iMin_{p}) </tex>. Fie <tex> i = 1, 2, \\ldots 8 </tex>:\r\n\r\n* <tex> i = 1: j = 0, head = 1, tail = 1, deque = \\{\\ (5, 0)\\ \\} \\Rightarrow bst_{1} = 5; </tex>\r\n* <tex> i = 2: j = 0, head = 1, tail = 1, deque = \\{\\ (9, 0)\\ \\} \\Rightarrow bst_{2} = 9; </tex>\r\n* <tex> i = 3: j = 1, head = 1, tail = 2, deque = \\{\\ (9, 5),\\ (4, 9)\\ \\} \\Rightarrow bst_{3} = 13; </tex>\r\n* <tex> i = 4: j = 2, head = 2, tail = 2, deque = \\{\\ (7, 9)\\ \\} \\Rightarrow bst_{4} = 16; </tex>\r\n* <tex> i = 5: j = 2, head = 2, tail = 3, deque = \\{\\ (7, 9),\\ (4, 16)\\ \\} \\Rightarrow bst_{5} = 16; </tex>\r\n* <tex> i = 6: j = 3, head = 2, tail = 4, deque = \\{\\ (7, 13),\\ (4, 16),\\ (1, 16)\\ \\} \\Rightarrow bst_{6} = 17; </tex>\r\n* <tex> i = 7: j = 4, head = 3, tail = 3, deque = \\{\\ (6, 16)\\ \\} \\Rightarrow bst_{7} = 22; </tex>\r\n* <tex> i = 8: j = 4, head = 3, tail = 4, deque = \\{\\ (6, 16),\\ (3, 22)\\ \\} \\Rightarrow bst_{8} = 22; </tex>\r\n\r\nMai jos se vede o figură în care elementele unui deque sunt defapt o secvenţă „continuă” de frunze ale unui arbore de intervale pentru cazul <tex> i = 6 </tex>.\r\n\r\np=. !deque-si-aplicatii?PKU0.png 60%!\r\n\r\np=. _Numărul maxim de elemente ce pot trece prin deque este $8$. În figură, arborele ţine minimul de pe poziţiile $2$, $3$, $4$ din deque._\r\n\r\nAlgoritmul în pseudocod arată în felul următor:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    sum  = 0;\r\n    last = 0;\r\n    // indicii head si tail ai dequeului\r\n    head = tail = 1;\r\n    // poziţia lui bst[0] se inserează în deque\r\n    deque[1] = 0;\r\n    pentru i = 1, N execută\r\n        sum += S[i];\r\n        temp = bst[ deque[tail] ];\r\n        cât timp (head <= tail) şi (S[ deque[tail] ] <= S[i]) execută\r\n            temp = Min(temp, iMin[tail]);\r\n            tail --;\r\n        sfârşit;\r\n        // adaug poziţia i la deque\r\n        tail ++;\r\n        deque[tail] = i;\r\n        // actualizez iMin[]\r\n        iMin[tail]  = temp;\r\n        // actualizez T[], arborele de intervale pe deque[]\r\n        Update(T, tail, iMin[tail] + S[i]);\r\n        // suma valorilor din [last, i] trebuie să nu depăşească M\r\n        cât timp (sum > M) execută\r\n            sum -= S[last];\r\n            dacă (deque[head] == last) atunci\r\n                head ++;\r\n            sfârşit;\r\n            last ++;\r\n        sfârşit;\r\n        // actualizez iMin[], Tb[] arborele de intervale pe bst[]\r\n        iMin[head] = Query(Tb, Max(last - 1, 0), deque[head] - 1);\r\n        // actualizez T[]\r\n        Update(T, head, iMin[head] + S[ deque[head] ]);\r\n        // reţin optimul pentru poziţia curentă\r\n        bst[i] = Query(T, head, tail);\r\n        // actualizez Tb[]\r\n        Update(Tb, i, bst[i]);\r\n    sfârşit;\r\n    scrie bst[N];\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală este <tex> O(N*log_{2}N) </tex>.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nFilozofia din spatele structurii de deque devine utilă, de obicei, în părţile finale ale rezolvării unei probleme. Însă, ce pot spune cu certitudine este că această structură de date pe cât este de simplă pe atât este de eficientă şi necesară.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\nÎnţelegerea profundă nu se poate realiza decât prin rezolvarea a cât mai multe probleme. Succes!\r\n\r\n* \'Deque\':problema/deque, _Arhiva educaţională_\r\n* \'Secvenţă\':problema/secventa\r\n* \'Secvenţă 3\':problema/secv3\r\n* \'Secvenţă 4\':problema/secv4\r\n* \'Sum 2\':problema/sum2, _Stelele Informaticii, 2003_\r\n* \'Drept 2\':problema/drept2, _Lotul Naţional de Informatică, 2006_\r\n* \'Copaci 2\':problema/copaci2, _.campion, 2007_\r\n* \'Struţi\':problema/struti\r\n* \'Brânză\':problema/branza\r\n* \'Trompetă\':problema/trompeta\r\n* \'Buline\':problema/buline\r\n* \'Balans\':problema/balans\r\n* \'Ksecv\':problema/ksecv, _Selecţie echipe ACM ICPC, UPB, 2008_\r\n* \'Munte4\':problema/munte4, _Lotul Naţional de Informatică, 2005_\r\n* \'Gard\':problema/gard, _ONI, 2002_\r\n* \'Ghiozdan\':problema/ghiozdan\r\n* \'Cover\':problema/cover, _Baraj ONI, 2007_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Cosmin Negruşeri, \"_Probleme cu secvenţe_\":probleme-cu-secvente\r\n# Dana Lica, \"_Arbori de intervale şi aplicaţii în geometria computaţională_\":arbori-de-intervale\r\n# Cătălin Frâncu, \"_Heapuri_\":heapuri\r\n# Marius Stroe, \"_Treapuri_\":treapuri\r\n# \'C++ Reference\':http://www.cplusplus.com/',3146,'public',NULL,NULL),('blog/okrs-20091','Obiective infoarena','2009-02-16 15:39:49','2009-02-22 18:57:03','\'Echipa infoarena\':echipa-infoarena a crescut cu 7 membri noi în anul 2008, la fel şi comunitatea infoarena şi numărul de proiecte pe care le-am început împreună. Toate bune şi frumoase, doar că această creştere ne-a obligat să căutăm metode mai eficiente de a ne organiza şi de a lucra împreună. Vă voi vorbi în continuare despre sistemul OKRs şi obiectivele infoarena pe acest trimestru.\r\n\r\nNoi, echipa infoarena, ne întrunim periodic în şedinţe \'încă din 2006\':planificare. Ce se întâmplă la o şedinţă tipică? Păi, în afara faptului că facem glume şi pierdem vremea în mod organizat, stabilim ce \'concursuri\':concursuri să organizăm, când facem \'următorul coding camp\':camp-2.2.1, ce \'facilităţi\':http://hackers.devnet.ro/report/1 mai adăugăm la site (sau mai scoatem) şi pe care dintre membrii comunităţii infoarena îi rugăm să intre în echipă alături de noi. Ce _altceva_ se mai întâmplă la şedinţele infoarena e o taină sacră şi nu pot să o divulg aici pe blog. :)\r\n\r\nŞedinţele sunt foarte bune pentru că ne ajută să ne punem la curent unii cu ceilalţi despre ce progrese facem. Din păcate, nu mai sunt de ajuns. Ce (mai) trebuie să faci ca mulţi oameni să lucreze eficient împreună? Nu ştiu, însă e nevoie măcar de un ţel comun, de un reper spre care să navigheze toţi, de nişte obiective. Din acest motiv am adoptat \'sistemul OKRs\':propuneri/9-okr pe care mai mulţi dintre noi l-am văzut şi l-am folosit la Google în internship-uri.\r\n\r\nDespre OKRs citiţi mai multe în \'pagina dedicată\':okr. Pe scurt însă, OKR-urile (Objectives and Key Results) sunt o serie de obiective şi rezultate cheie măsurabile pe care ni le stabilim trimestrial. Fiecare obiectiv are un responsabil, iar la sfârşitul fiecărui trimestru tragem linie şi facem bilanţul: care dintre obiectivele propuse am reuşit să le îndeplinim?\r\n\r\nCa să probăm ideea ne-am asumat în octombrie 2008 \'o serie de obiective\':okr/20084 şi am început să lucrăm la ele. Timpul a zburat repede, iar la sfârşitul trimestrului am constatat că doar jumătate din ce ne-am propus a fost realizat. Oops! Dacă sună dezamăgitor, să ştiţi că nu e. În realitate am fost optimişti şi ne-am asumat obiective mult prea ambiţioase. Pe principiul „experientia docet” o să avem grijă de data asta să obţinem o notă mai mare. :)\r\n\r\nIată \'obiectivele pe anul *2009, trimestrul I*\':okr/20091. Citeşte-le şi spune-ne ce crezi despre ele. Sunt prea modeste, sunt prea ambiţioase? Ai o idee bună pe care ar trebui să o punem în practică? Lasă-ne un comentariu pentru că cea mai bună idee va fi premiată cu un tricou infoarena. ;)',13,'private',NULL,NULL),('planificare/sedinta-20090126','Sedinta 2009-01-26','2009-01-22 17:34:00','2009-02-16 17:20:52','h1. Sedinta 2009-01-26\r\n\r\nh2(#locatie). Locatie si ora\r\n\r\nNe întâlnim *luni, 26 ianuarie* la ora *19^00^* la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nh2(#participanti). Participanti\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")== (inca nu stiu cand scap de la examen)\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"alexthero\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n...\r\n\r\nh2(#agenda). Agenda\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinta anterioara\':planificare/sedinta-20090112| ==user(user=\"domino\" type=\"tiny\")==|\r\n|OKRs Q12009| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n|Algoritmiada| ... |\r\n|Stelele| ==user(user=\"silviug\" type=\"tiny\")==|\r\n|Fix-it camp| ... |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n\r\nh3. Detalii\r\n\r\n* Despre Stele\r\n** Sunt ok datele: 31-1 pentru 9-10 si 6-7 pentru 11-12?\r\n** Seturi de probleme\r\n*** Se dau ~120 RON pe problema (e pe bani!)\r\n*** Avem probleme pentru 9-10? Cate?\r\n*** Pentru 11-12 trebuie sa ne intalnim (fara Bogdan si Cosmin) la ICHB. Marti/miercuri?\r\n\r\nDiscutii despre probleme la 9-10. Intalnire marti-miercuri pentru 11-12.\r\n\r\nh2(#rezolutii). Rezolutii\r\n\r\n* Cristi face blog post despre OKR-uri\r\n* Silviu stabileste contacte cu Poli\r\n* Fixit camp:\r\n** Cristi si Silviu vorbesc de premii\r\n* Stele %{color:red;}(done)%:\r\n** Ne intalnim maine la 10 la ICHB sa vorbim de probleme: Silviu, Adi, Paul, Victor, Stefan. Victor vorbeste cu Wef\r\n** Cristi baga newsletter si Silviu ii zice din timp (minim 3 zile)\r\n** Cristi vorbeste cu Ali pentru configurarea proxy-ului\r\n** Cristi face .htaccess pentru a bana forumul\r\n* Algoritmiada:\r\n** Se face pe 15 februarie\r\n** Sponsori posibili: Adobe, Microsoft, iRealSoft\r\n* Il iertam pe Mort de datorie (a gresit la calcule)\r\n* Coding camp:\r\n** 28 februarie - 1 martie\r\n** Cine vine: Cristi, Vali, Prostu, Bogdan, Victor, Cosmin, Stefan, Mircea\r\n** Probabil: Silviu, Paul, Adi, Wef\r\n** Tero baga de acasa\r\n** Mircea face planul de coding camp (Virtual Contest e prioritar)\r\n*** Reorganizat sidebar si topnav (Cristi are idei, link la index de newsletter)\r\n*** Solutie de backup\r\n** Cristi se ocupa de locatie\r\n* Nu facem fixit camp in Q1\r\n* Mircea se uita sa vada cati oameni au trimis doar in Arhiva Educationala %{color:red;}(31 de useri, 251 de joburi; 74 care au trimis doar in Arhiva Educationala si cel mult la Adunare si/sau CMMDC)%\r\n* Vali face IAP si OKR despre ordonarea problemelor (vezi formula de la IMDB) %{color:red;}(working on it, sorry de delay!)%:\r\n* Incercam \"video sedinta\" cu Airinei (webcam/Skype)\r\n* Lumea da feedback la IAP 7 pana la urmatoarea sedinta\r\n* Cristi face blog post despre 2% %{color:red;}(done)%:\r\n* Silviu vorbeste cu Mars despre evaluator ( %{color:red;}(done)%: ce facea Mars nu adreseaza problema noastra)\r\n* Mircea trimite mail pentru cine nu si-a completat OKR-urile\r\n* Facem sedinta pe 16 februarie. Cosmin cumpara apa, suc si pahare (bon cu stampila). Cristi se ocupa de sala.\r\n* Paul, Prostu, Tero & Co trimit poza si descriere lui Cosmin pentru blog despre membri noi. %{color:red;}(Paul, Tero done)%\r\n\r\nh2. Notite\r\n\r\n* Punem stire ca nu mai ai voie cu HTML si sa-si actualizeze lumea profilele\r\n* Stefan discuta cu Marius Stroe dupa finala\r\n',1,'public',NULL,NULL),('summer-challenge-2009','Summer Challenge 2009','2009-07-19 18:27:40','2009-07-19 18:27:40','h1. Summer Challenge 2009\r\n\r\n(htabs)*(active) \'Detalii\':summer-challenge-2009/\r\n* \'Runda 1\':summer-challenge-2009/runda-1\r\n* \'Runda 2\':summer-challenge-2009/runda-2\r\n* \'Runda 3\':summer-challenge-2009/runda-3\r\n* \'Clasament\':summer-challenge-2009/clasament\r\n\r\nConcursul Summer Challenge revine dupa un an de pauza si e gata sa loveasca din nou! ;)\r\n\r\nTe plictisesti in mijlocul verii sau ti-e dor de concursurile din timpul anului? Inca nu ai plecat la mare sau la munte? Vrei sa iti masori fortele cu ceilalti membri infoarena?\r\n\r\nTe invitam sa participi la seria de concursuri {*Summer Challenge 2009*}. Vom organiza 3 runde online, de cate 5h fiecare, cu probleme de nivel mediu spre greu. Continuand traditia, editia din anul acesta se doreste a fi atat un ultim test pentru delegatia Romaniei la IOI (Bulgaria), cat si o buna ocazie de antrenament pentru utilizatorii infoarena. In toiul verii, suntem singurii care organizeaza concursuri! ;)\r\n\r\nIntra in competitie alaturi de cei mai buni!\r\n\r\nh2. Program concurs\r\n\r\ntable{width: 50%}. |_. Runda|_. Data |_. Ora |\r\n|\"*Runda 1*\":summer-challenge-2009/runda-1|*Sambata, 25 iulie 2007*| *10^00^ - 15^00^* |\r\n|\"*Runda 2*\":summer-challenge-2009/runda-2| To be determined... | *10^00^ - 15^00^* |\r\n|\"*Runda 3*\":summer-challenge-2009/runda-3| To be determined... | *10^00^ - 13^00^* |\r\n\r\nClick pe titlul unei runde pentru informatii detaliate.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"51\" count=\"10\")==\r\n\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru.\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti probleme, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nh2. Prima data pe infoarena?\r\n\r\ninfoarena ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi.\r\n\r\nVezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n',2028,'protected',NULL,NULL),('planificare/sedinta-20090316','Sedinta 2009-03-02','2009-02-23 16:00:45','2009-02-23 16:36:18','h1. Sedinta 2009-03-02\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 02 Martie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul ?, ?)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ..\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090216| ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n|Concursul Centrelor de Excelenta/Concurs in engleza | ==user(user=\"filipb\" type=\"tiny\")== |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n\r\n\r\nh2. Detalii\r\n\r\nh3. Misc\r\n\r\n* Donare calculatoare\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\nh2. Notiţe\r\n',2038,'protected',NULL,NULL),('utilizator/wickedman','Cristian George Strat (wickedman)','2006-11-24 20:56:12','2008-11-16 11:15:12','h2. Despre mine\r\n\r\n* Membru fondator si Presedinte al Asociatiei infoarena \'{!utilizator/domino?btn_viewmy_160x33.gif!}\':http://www.linkedin.com/in/cristiangeorgestrat\r\n* Co-fondator INNOVATE CONSULT, companie ce ofera servicii software si networking\r\n* Google internship, summer 2008, Zurich, Switzerland\r\n* Google internship, summer 2007, Mountain View, California\r\n* Presedinte al juriului de _Pagini Web_, \"InfoEducatie\":http://infoeducatie.ro/ 2006\r\n* Membru al juriului de _Programare_ \"InfoMatrix 2008\":http://infomatrix.ro/\r\n* Membru al juriului de _Pagini Web_ \"InfoEducatie\":http://infoeducatie.ro/ 2005 si Unirea 2005\r\n* Locurile I, I, II, III la concursul national de software si pagini web \"InfoEducatie\":http://infoeducatie.ro/\r\n* Locul II la concursul pe echipe EESTEC Olympics 2006\r\n* Finalist la \'Challenge24\':http://challenge24.org/\r\n* Locul 4 la ONI 2004\r\n* Finalist \'.campion\':http://campion.edu.ro/ 2004 \r\n* Calificare in lotul largit de informatica 2004\r\n\r\nh3. Studii\r\n\r\n* C.N. \"Gh. Rosca Codreanu\", Barlad, Jud. Vaslui\r\n* -Student in anul IV la- Absolvent \"FMI\":http://fmi.unibuc.ro/ 2008, Universitatea Bucuresti\r\n\r\nh3. Trivia\r\n\r\n* infoarena a fost initial un proiect pentru concursul national \'InfoEducatie\':http://infoeducatie.ro/, sectiunea pagini web. La prima participare (in 2002) am primit locul III, iar in 2003 am castigat locul I.\r\n* l-am cunoscut pe \'Mircea Pasoi\':utilizator/domino si pe \'Crestez Leonard\':utilizator/fluffy pe canalul IRC #olimpada. Ei vroiau sa faca un site de probleme\r\n* am fost coleg de clasa cu \'Silviu Ganceanu\':utilizator/silviug in 9-11\r\n* ce vedeti acum este site-ul infoarena versiunea 2. \'Inainte era albastru\':http://web.archive.org/web/20060307025837/http://infoarena.devnet.ro/\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* == User(user=\"chucknorris\" type=\"tiny\") ==\r\n* == User(user=\"eval\" type=\"tiny\") ==\r\n',1,'protected',NULL,NULL),('utilizator/mathboy','Profil mathboy','2008-12-24 18:43:37','2009-02-22 19:12:43','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\nElev in clasa a IX-a D,Matematica-Informatica,Informatica Intensiv\r\n\r\n Colegiul National Unirea Focsani\r\n\r\nContact: dragos_mathboy@yahoo.com\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n==user(user=\"bogdanhm999\" type=\"normal\")==\r\n\r\n==user(user=\"StefanGeo\" type=\"normal\")==\r\n\r\n==user(user=\"lucianvn\" type=\"normal\")==\r\n\r\n==user(user=\"bolovanemil\" type=\"normal\")==',9232,'public',NULL,NULL),('planificare/sedinta-20090316','Sedinta 2009-03-02','2009-02-23 16:00:45','2009-02-23 21:49:28','h1. Sedinta 2009-03-02\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 02 Martie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090216| ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n|Concursul Centrelor de Excelenta/Concurs in engleza | ==user(user=\"filipb\" type=\"tiny\")== |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Recapitulare OKRs: suntem în grafic?| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n\r\n\r\nh2. Detalii\r\n\r\nh3. Misc\r\n\r\n* Donare calculatoare\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\nh2. Notiţe\r\n',1,'protected',NULL,NULL),('propuneri/12-infoarena.org','IAP #12: Infoarena.org','2009-02-17 11:16:13','2009-02-25 13:53:24','h1. IAP #12: Infoarena.org\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2009-02-17                             |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"alexthero\")== |\r\n|_. Stare     | *_IN-CONSTRUCTIE_*                     |\r\n\r\n(toc)*{text-align:center;} *Continut*\r\n* \'Abstract\':propuneri/12-infoarena.org#abstract\r\n* \'Motivatie\':propuneri/12-infoarena.org#motivatie\r\n* \'Implementare\':propuneri/12-infoarena.org#implementare\r\n* \'Traduceri\':propuneri/12-infoarena.org#traduceri\r\n* \'Feedback\':propuneri/12-infoarena.org#feedback\r\n\r\nh2(#abstract). Abstract\r\n\r\nSe propune utilizarea softului deja existent pentru crearea unei versiuni infoarena in limba engleza, independenta ca si continut de infoarena.ro. Realizarea acestui proiect consta in implementarea modificarilor necesare la nivel de cod si traducerea continutului.\r\n\r\nh2(#motivatie). Motivatie\r\n\r\nMotivele si avantajele acestui proiect sunt multiple si evidente. Motivatia imediata o constituie organizarea Concursului Centrelor de Excelenta cu participare internationala (polonezi). Celelalte motive si avantaje:\r\n\r\n* organizarea de concursuri internationale\r\n* formarea unei comunitati internationale si cooptarea unor colaboratori internationali\r\n* potential acces la problemele si materialele de pregatire ale unor tari ca rusia, china, etc.\r\n* recunoasterea brandului infoarena la nivel international\r\n* access la o gama mai larga de eventuali sponsori\r\n\r\nh2(#implementare). Implementare\r\n\r\nO metoda usoara si rapid de pus in practica este sa punem sus codul si sa ne apucam sa traducem. Aceasta metoda are mai multe neajunsuri pe care vom incerca sa le rezolvam pe parcursul acestui document.\r\n\r\n1. Folosirea aceluiasi cod pe ambele site-uri si update-uri concomitente.\r\nUn punct important ar fi ca ambele site-uri sa poata fi updatate cu acelasi cod scris de \"hackerul infoarena\". Problema propriu zisa este intercalarea elementelor de limba cu cele de cod. Ca sa rezolvam aceasta problema ar trebui sa avem niste \"language files\", care sa contina toate frazele folosite in cod (tot in afara paginilor wiki). SMF are deja aceste fisiere, dar e posibil ca noi sa fi modificat cate ceva in versiunea romaneasca.\r\n\r\nAvantaje:\r\n\r\n* acelasi cod pentru ambele siteuri\r\n* extinderea usoara la mai multe limbi (doar prin modificarea unui language file)\r\n\r\nDezavantaje:\r\n\r\n* volum mult de munca bruta? trebuie trecut prin fiecare fisier si modificat tot textul\r\n\r\n2. Concursuri care pot fi date simultan pe ambele siteuri\r\nPornind de la motivatie, o intrebare care vine inevitabil este: \"cum dam concursuri simultan pe ambele siteuri\". O prima solutie ar fi crearea concursurilor pe ambele siteuri, cu probleme identice, dar traduse. Singura problema ar fi cum afisam clasamentele (cu concurenti de pe ambele siteuri). Ideal ar fi ca fiecare din cele 2 clasamente sa contina si userii care au submitat dincolo, dar cu un flag si cu link catre profilul lor. Putem avea username-uri identice, dar ele sa defineasca un alt utilizator.\r\n\r\nSolutie: definim un nou macro care (dandui-se linkurile dintre concursuri + probleme):\r\n\r\n* se conecteaza la baza de date a celuilalt site / un fisier xml public actualizat de celalalt site\r\n* afiseaza clasamentul concatenat\r\nTrebuie sa folosim aceasi metoda ca acum pentru a reda eficient clasamentele.\r\n\r\nAvantaje: \r\n\r\n* aparent rezolvam toate subproblemele care ar putea aparea la crearea concursurilor\r\n\r\nDezavantaje:\r\n\r\n* link inestetic catre profilul de pe celalalt site\r\n* multe linkuri catre acelasi site dauneaza la page ranking? nu sunt sigur\r\n\r\n3. Teste\r\n\r\nO alta informatie reduntanta sunt testele. Nu as fi mentionat acest lucru daca nu trimitea Bogdan e-mail-ul din 22 feb. Putem linka unele pagini intre ele, astfel incat atasamentele celor doua pagini sa fie aceleasi si mentinute o singura data. Totusi, pentru inceput, cred ca acest lucru nu e necesar.\r\n\r\n*O lista scurta cu ce trebuie implementat inainte sa ne apucam de tradus:*\r\n\r\n* language files\r\n* clasamente comune\r\n\r\nh2(#traduceri). Traduceri\r\n\r\nNe propunem sa traducem urmatoarele pentru prima versiune:\r\n\r\n* documentatia necesara pentru un utilizator care vrea sa rezolve probleme si sa participe la concurs\r\n* un set de 5 probleme reprezentative din arhiva de probleme (A+B, CMMDC, 3 mai grele..)\r\n* un set de 3 probleme reprezentative din arhiva educationala\r\n* 1-2 articole\r\n* forumul incepe de la 0\r\n\r\nVom crea un nou proiect marca infoarena, \"traduce infoarena\" in care cautam colaboratori. Acestia vor traduce continut. Fiecare e liber sa traduca in limita timpului disponibil.\r\n\r\nh2(#feedback). Feedback\r\n\r\nIntra pe \'forum\':forum/index.php?topic=3172.0 pentru a da feedback.\r\n\r\n==SmfTopic(topic_id=\"3172\")==',716,'public',NULL,NULL),('deque-si-aplicatii','Deque și aplicații','2009-01-22 22:28:12','2009-02-26 13:11:17','h1. Deque şi aplicaţii\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'Descrierea structurii\':deque-si-aplicatii#descriere\r\n* \'Aplicaţii:\':deque-si-aplicatii#problema-1\r\n** \'_1. Book Pile &#40;SGU&#41;_\':deque-si-aplicatii#problema-1\r\n** \'_2. Vila 2 &#40;.campion, 2005&#41;_\':deque-si-aplicatii#problema-2\r\n** \'_3. Şir_\':deque-si-aplicatii#problema-3\r\n** \'_4. Platforma &#40;.campion, 2009&#41;_\':deque-si-aplicatii#problema-4\r\n** \'_5. Trans &#40;ONI 2004&#41;_\':deque-si-aplicatii#problema-5\r\n** \'_6. Otilia &#40;.campion, 2005&#41;_\':deque-si-aplicatii#problema-6\r\n** \'_7. Bcrc &#40;Stelele Informaticii, 2006&#41;_\':deque-si-aplicatii#problema-7\r\n** \'_8. Cut the Sequence &#40;PKU&#41;_\':deque-si-aplicatii#problema-8\r\n* \'Concluzii\':deque-si-aplicatii#concluzii\r\n* \'Probleme suplimentare\':deque-si-aplicatii#probleme-suplimentare\r\n* \'Bibliografie\':deque-si-aplicatii#bibliografie\r\n\r\nÎn acest articol voi prezenta o structură de date liniară de tip listă numită _deque_. Aceasta nu este una complexă, în schimb se va dovedi foarte folositoare. După o scurtă prezentare, mă voi axa pe o serie de aplicaţii care vor arăta surprinzătoarea sa utilitate în locurile unde am fi crezut că nu se mai poate face nimic pentru a reduce complexitatea algoritmului.\r\n\r\nh2(#descriere). Descrierea structurii\r\n\r\nStructura de _deque_ (pronunţat, de obicei, _deck_) poate fi privită ca o listă cu două capete prin intermediul cărora se şterg sau inserează noi elemente. În literatura de specialitate aceste capete se numesc _head_ şi _tail_, iar deque-ul mai este recunoscut şi ca fiind o coadă cu două capete _(double ended queue)_.\r\n\r\nPentru implementarea unui deque putem recurge la liste dublu înlănţuite sau la un vector static când se cunoaşte numărul elementelor din colecţie. Limbajul C++ pune şi el la dispoziţia programatorilor o implementare prin intermediul containerului \'_std::deque_\':http://www.cplusplus.com/reference/stl/deque/ din headerul _<deque>_.\r\n\r\nh3(#operatii). Operaţii:\r\n\r\nVom putea utiliza această structură de date în situaţiile când avem nevoie de următoarele operaţii (sunt listate cu numele sub care se găsesc în limbajul C++):\r\n\r\ntable{width:70%}. | * _front()_ | întoarce primul element |\r\n| * _back()_ | întoarce ultimul element |\r\n| * _push_front()_ | inserează un element în faţă |\r\n| * _push_back()_ | inserează un element în spate |\r\n| * _pop_front()_ | scoate primul element |\r\n| * _pop_back()_ | scoate ultimul element |\r\n| * _empty()_ | întoarce _true_ dacă în deque nu se găseşte niciun element şi _false_ în caz contrar |\r\n\r\np=. !deque-si-aplicatii?new_deque.png 75%!\r\n\r\nToate aceste operaţii se execută în timp $O(1)$ pe o structură implementată de la zero sau în timp $O(1)$ \'amortizat\':http://en.wikipedia.org/wiki/Amortized_analysis pentru containerul $deque$ din C++.\r\n\r\nÎn multe aplicaţii unde soluţiile parţiale se reprezintă sub forma unui şir continuu de valori care permite inserarea şi ştergerea doar pe la capete se poate folosi un $deque$. Să urmărim în continuare cazuri concrete în care simplitatea unui $deque$ duce la soluţii de multe ori optime şi implementări foarte scurte şi clare. Aplicaţiile sunt prezentate în ordinea crescătoare a dificultăţii şi din acest motiv le recomand cu căldură tuturor celor care învaţă din acest articol să le parcurgă în ordine.\r\n\r\nh2(#problema-1). 1. \'Book Pile\':http://acm.sgu.ru/problem.php?contest=0&problem=271 (SGU)\r\n\r\nbq. Se dau $N$ cărţi aşezate una deasupra celeilalte asupra cărora se vor efectua $M$ operaţii de două tipuri: 1. $ADD${$(nume)$}: se adaugă cartea $nume$ deasupra celorlalte; 2. $ROTATE$: primele $K$ cărţi de deasupra se rotesc (dacă sunt mai puţin de $K$ cărţi atunci se vor roti toate). Rotaţia presupune inversarea celor $K$ elemente, adică ultimul va fi primul, penultimul va fi al doilea etc. Se cere să se afişeze cărţile în ordine, prima fiind cea de deasupra, după efectuarea celor $M$ operaţii.\r\nRestricţii: $0 &le; N, K &le; 40 000$, $0 &le; M &le; 100 000$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se poate deduce pe baza observaţiei următoare: odată avansată dincolo de poziţia $K$, o carte ajunge pe poziţia finală, întrucât orice operaţie ulterioară (inserare sau rotaţie) nu o va mai afecta. Să presupunem că iniţial avem cărţile $A B C$ şi $K = 3$. Dacă îl vom adăuga pe $D$, atunci nu avem nevoie pentru operaţiile următoare decât de cărţile $D A B$, deoarece, dacă vom roti ulterior primele $K$ cărţi, $C$ nu va mai fi niciodată considerat. După o rotaţie, noua ordine va fi $B A D$ şi $C$ va fi pe raft la loc sigur. Dacă îl vom adăuga pe $E$, topul se va schimba în $E B A$, iar pe raft, în mod sigur vor fi $D C$, în această ordine. Cele $K$ cărţi din vârf se prezintă ca o secvenţă continuă de elemente, la care se adaugă noi elemente sau se elimină dintre acestea numai pe la _capete_. Aceste capete sunt chiar $head$ şi $tail$ ale unui $deque$.\r\n\r\np=. !deque-si-aplicatii?bookpile.png 40%!\r\n\r\nLa final, când se vor termina operaţiile, cărţilor de pe raft li se vor adăuga cele din $deque$ şi se va afişa soluţia. În cazul presupus, soluţia va fi: $E B A D C$.\r\n\r\nÎntrucât operaţiile unui $deque$ se execută în timp $O(1)$, soluţia are complexitatea $O(N + M)$.\r\n\r\nh2(#problema-2). 2. \'Vila 2\':problema/vila2 (.campion, 2005)\r\n\r\nbq. Se dă un şir $S$ de $N$ numere întregi şi $D$ un număr natural. Se cere să se determine diferenţa maximă dintre oricare două numere din şir cu proprietatea că diferenţa în modul a poziţiilor pe care se găsesc în şirul $S$ nu depăşeşte $D$.\r\nRestricţii: $2 &le; N &le; 100 000$, $1 &le; D &le; N/2$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia nu este greu de intuit. Dacă vom considera indicii $1$, $2$, ... , $N$ succesiv, va trebui ca pentru fiecare secvenţă $[i - D, i]$ să determinăm valoarea maximă şi pe cea minimă, iar diferenţa lor să o comparăm cu rezultatul cel mai bun obţinut până în acel moment. Pentru fixarea ideii, să urmărim cum putem determina eficient valoarea maximă din fiecare secvenţă $[i - D, i]$.\r\n\r\n_Observaţie_: Fie $i{~1~}$, $i{~2~}$ doi indici astfel încât $i - D &le; i{~1~} &lt; i{~2~} &le; i$.\r\n\r\n# Dacă $S[i{~1~}] &le; S[i{~2~}]$ atunci, cât timp cei doi indici vor fi în intervale de tipul $[i - D, i]$, valoarea de pe poziţia $i{~2~}$ va fi întotdeauna preferată valorii de pe poziţia $i{~1~}$. Când se ajunge la un interval care nu-l mai conţine pe $i{~1~}$, $i{~2~}$ rămâne în continuare preferat.\r\n# Dacă $S[i{~1~}] &gt; S[i{~2~}]$ atunci şi $i{~1~}$ şi $i{~2~}$ sunt candidaţi la maxim, la momentul curent sau în viitor.\r\n\r\nCu această observaţie deducem că într-o secvenţă $[i - D, i]$ vom avea un şir $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$ astfel încât $S[i{~1~}] &gt; S[i{~2~}] &gt; ... &gt; S[i{~K~}]$. Când vom avansa la secvenţa următoare, $[i - D + 1, i + 1]$, vom şterge din indicii $i{~1~}$, $i{~2~}$... atâta timp cât nu se găsesc în intervalul curent şi vom şterge din poziţiile $i{~K~}$, $i{~K-1~}$... cât timp $S[i + 1] &gt; S[i{~K~}]$, $S[i + 1] &gt; S[i{~K-1~}]$... adică cât timp se îndeplineşte primul punct din observaţia anterioară.\r\n\r\nŞirul $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$ este continuu iar operaţiile se efectuează doar pe la cele două capete. Rezultă că şirul poate fi implementat cu ajutorul unui deque.\r\n\r\nPentru $S[] = {5, 9, 4, 7, 4, 1}$ şi $D = 3$ obţinem următoarele stări ale unui deque:\r\n\r\n* <tex> \\langle \\widehat{5\\ [1]} \\rangle; </tex>\r\n* <tex> \\langle 5\\ [1] \\rangle \\Leftarrow 9\\ [2] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]} \\rangle; </tex>\r\n* <tex> \\langle 9\\ [2] \\rangle \\Leftarrow 4\\ [3] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 4\\ [3] \\rangle; </tex>\r\n* <tex> \\langle 9\\ [2],\\ 4\\ [3] \\rangle \\Leftarrow 7\\ [4] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 7\\ [4] \\rangle; </tex>\r\n* <tex> 9\\ [2] \\Leftarrow \\langle 7\\ [4] \\rangle \\Leftarrow 4\\ [5] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5] \\rangle; </tex>\r\n* <tex> \\langle 7\\ [4],\\ 4\\ [5] \\rangle \\Leftarrow 1\\ [6] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5],\\ 1\\ [6] \\rangle; </tex>\r\n\r\nCum fiecare indice din $1$, $2$, .., $N$ trece cel mult o dată prin deque, complexitatea finală este $O(N)$.\r\n\r\nh2(#problema-3). 3. \'Şir\':problema/sir\r\n\r\nbq. Se dă un şir $S$ de numere întregi de lungime $N$. Se cere să se găsească secvenţa de lungime maximă cuprinsă între $X$ şi $Y$ astfel încât $MAX - MIN &le; Z$, unde $MAX$ este maximul dintre toate numerele întregi din secvenţă iar $MIN$ minimul dintre acestea. Secvenţa soluţie va fi cea cu poziţia de început maximă dintre toate secvenţele de lungime maximă.\r\nRestricţii: $3 &le; N &le; 100 000$, $1 &le; X &le; Y &le; N$, $0 &le; Z &le; 30 000$.\r\n\r\nh3. Soluţie:\r\n\r\nVoi prezenta mai jos o rafinare a soluţiei în trei paşi.\r\n\r\nPrima rezolvare se găseşte uşor, deoarece nu facem decât să urmărim textul: pentru fiecare poziţie $i$ fixată ({$i$} ia valorile $1$, $2$, .., $N$ succesiv) vom determina pentru aceasta secvenţa cerută, adică vom plimba un $j$ între poziţiile $i - Y$ şi $i - X$. Pentru un interval $(j, i]$ vom determina $MAX$ şi $MIN$ în $O(log{~2~}N)$ cu un arbore de intervale, iar daca diferenţa dintre acestea nu depăşeşte $Z$ vom compara cu soluţia finală. Complexitatea finală va fi $O(N * (Y - X) * log{~2~}Y)$.\r\n\r\nSă presupunem că pentru poziţia curentă $i$, l-am găsit pe $j$ cât mai mic cuprins între $i - Y$ şi $i - X$ astfel încât secvenţa $(j, i]$ este candidată la soluţie. Ce proprietăţi are $j$?\r\n\r\n* $i - Y &le; j &le; i - X$ şi $MAX - MIN &le; Z$;\r\n* dacă îl incrementăm pe $j$ la $j + 1$ atunci dacă $j &le; i - X$ cu siguranţă $MAX - MIN &le; Z$ şi astfel soluţia va fi mai scurtă;\r\n* dacă îl decrementăm pe $j$, atunci ori $j < i - Y$ ori $MAX - MIN > Z$;\r\n* dacă îl incrementăm pe $i$ la $i + 1$, atunci se poate întâmpla ca $j < i - Y$; cum $MAX$ nu poate decât să crească, iar $MIN$ decât să scadă, se mai poate de asemenea întâmpla ca $MAX - MIN > Z$.\r\n\r\nDatorită proprietăţilor de mai sus, când trecem de la $i$ la $i + 1$, valoarea lui $j$ nu poate decât să crească cât timp $j < i - Y$ sau $MAX - MIN > Z$ şi $j$ nu a depăşit poziţia $i - X$. Pentru determinarea lui $MAX$, respectiv lui $MIN$ se poate folosi un arbore de intervale. Complexitatea finală va fi $O(N * log{~2~}(Y))$.\r\n\r\nCu cei doi indici $i$ şi $j$ vom accesa fiecare element din cele $N$ de cel mult $2$ ori, o dată cu $i$ şi o dată cu $j$. Să vedem cum putem îmbunătăţi complexitatea $O(log{~2~}Y)$ pentru determinarea maximului şi minimului.\r\n\r\nPentru fixarea ideilor să urmărim cum îl vom calcula pe $MAX$. Observaţia care ne ajută în multe probleme pentru reducerea complexităţii de la $O(log{~2~}N)$ la $O(1)$ amortizat este următoarea: \r\n\r\n_Observaţie_: „Fixăm $i{~1~}$ şi $i{~2~}$ astfel încât $j < i{~1~} < i{~2~} &le; i$. Atunci, dacă $S[i{~2~}] > S[i{~1~}]$ poziţia $i{~2~}$ va fi întotdeauna mai importantă decât poziţia $i{~1~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ şi $i{~2~}$ nu vor mai fi ambele în intervalul $(j, i]$, poziţia eliminată va fi {$i{~1~}$}. Dacă însă $S[i{~1~}] > S[i{~2~}]$, atunci poziţia $i{~1~}$ va umbri poziţia $i{~2~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ va fi eliminat, atunci e posibil ca $i{~2~}$ să fie un candidat la $MAX$ dintre restul elementelor de la dreapta sa. În acest caz, nu putem afirma nimic şi vom păstra cele două poziţii.”\r\n\r\nRezultă din această observaţie că în intervalul $(j, i]$ poziţiile importante vor fi $j < i{~1~} < i{~2~} < .. < i{~k~} <= i$ astfel încât $S[i{~1~}] > S[i{~2~}] > .. > S[i{~k~}]$. Astfel, $MAX$ va fi $S[i{~1~}]$. Când îl vom incrementa pe $i$ la $i + 1$ vom şterge din poziţiile $i{~k~}$, $i{~k-1~}$, ... atâta timp cât $S[i + 1]$ este mai important, adică mai mare decât valorile de pe aceste poziţii, şi vom şterge $i{~1~}$, $i{~2~}$, ... atâta timp cât aceste poziţii sunt mai mici sau egale decât $j\'$. Indicele $j\'$ este noul optim pentru poziţia $i + 1$. Proprietatea şirului de poziţii $i{~1~}, i{~2~}, .., i{~k~}$ este că se reprezintă ca un şir continuu de numere care permite inserarea elementelor prin dreapta şi ştergerea prin stânga, adică se adaugă elemente la tail şi se şterg elemente de la head. Îl putem deci reprezenta printr-un deque. Complexitatea $O(1)$ amortizat provine de la faptul că fiecare poziţie dintre cele $N$ nu trece decât o singură dată prin deque şi este şters tot cel mult o singură dată. \r\n\r\nÎn practică, pseudocodul poate arăta în felul următor:\r\n\r\n== code(cpp) |\r\n// S şirul de numere iniţial şi N lungimea sa\r\n\r\nSubalgoritmul push_in(deque, întreg p, funcţia fct) este:\r\n    cât timp (!deque.empty() şi fct(S[p], S[deque.back()])) execută\r\n        deque.pop_back();\r\n    deque.push_back(p);\r\nSfârşit;\r\n\r\nFuncţia query(deque, întreg j) este:\r\n    cât timp (!deque.empty() şi deque.front() <= j) execută\r\n        deque.pop_front();\r\n    return S[deque.front()];\r\nSfârşit;\r\n\r\nAlgoritmul este:\r\n    lg = 0;\r\n    pentru i = 1, N execută\r\n        // funcţia min(a, b) întoarce true dacă a < b\r\n        inserează(min_deq, i, min);\r\n        // funcţia max(a, b) întoarce true dacă a > b\r\n        inserează(max_deq, i, max);\r\n        cât timp ((j < i - Y sau query(max_deq, j) - query(min_deq, j) > Z) şi j < i - X) execută\r\n            j = j + 1;\r\n        // (j, i] este intervalul candidat la soluţia optimă pentru poziţia i\r\n        dacă (j <= i - X) şi (query(max_deq, j) - query(min_deq, j) <= Z) atunci\r\n            dacă (lg >= i - j) atunci\r\n                lg = i - j, start = j + 1, stop = i;\r\n    sfârşit_pentru\r\n\r\n    dacă (lg > 0) atunci\r\n        scrie lg, start, stop;\r\n    altfel\r\n        scrie -1;\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală va fi $O(N)$.\r\n\r\nh2(#problema-4). 4. \'Platforma\':http://campion.edu.ro/problems/3/509/platforma_ro.htm (.campion, 2009)\r\n\r\nbq. Se dă o matrice $P$ de dimensiuni $M x N$ cu elemente numere întregi. Se defineşte valoarea maximă dintr-un dreptunghi de dimensiuni $R x C$ ca fiind valoarea maximă dintre elementele aflate în acel dreptunghi.\r\nCerinţă: Să se găsească un dreptunghi de dimensiuni $R x C$ cu valoarea maximă minimă.\r\nRestricţii: $1 &le; M, N &le; 1000$, $1 &le; R &le; M$, $1 &le; C &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nAceastă problemă reprezintă o extindere în două dimensiuni a problemei anterioare \'Vila 2\':deque-si-aplicatii#problema-2, unde am studiat cazul unidimensional al determinării pe un vector a maximului / minimului pentru fiecare subsecvenţă de o lungime fixată.\r\n\r\nCerinţa constă în amplasarea unui dreptunghi $R x C$ astfel încât valoarea maximă din interiorul său să fie cât mai mică. Una din ideile simple constă în fixarea colţului din stânga sus în toate cele $(M - R) x (N - C)$ poziţii şi determinarea maximului din interiorul său cu o altă parcurgere a celor $R x C$ elemente. Dar, să fixăm o linie $i$. Atunci, pentru a fixa colţul din stânga sus mai iterăm cu un indice $j$ între coloanele $1$ şi $N-C+1$. De aici devine clar că atunci când avansăm indicele coloanei în dreptunghiul curent apare o nouă coloană, $j + C$, şi dispare coloana curentă $j$. Dacă pentru fiecare coloană $j$ de pe linia curentă $i$ reţinem un $Max{~i,j~}$ egal cu maximul dintre elementele $P{~i,j~}, P{~i+1,j~},.. P{~i+R-1,j~}$, atunci pe linia fixată $i$ vom avea un vector din $N$ elemente (numărul de coloane al matricei $P$) alcătuit din valorile $Max{~i,1~}, Max{~i,2~}, Max{~i,3~},.. Max{~i,j~},.. Max{~i,N-1~}, Max{~i,N~}$. Iar pe acest vector va trebui să determinăm pentru fiecare subsecvenţă de $C$ elemente, valoarea maximă. Dintre toate subsecvenţele o vom alege pe cea cu valoarea maximă cea mai mică. Iar acest rezultat va fi o soluţie pentru linia fixată. Cu valorile din $Max$ precalculate, pentru fiecare linie avem complexitatea $O(N)$, deci $O(M * N)$ pentru întreaga matrice. Însă, implementând direct, valorle din $Max$ se calculează în $O(M * N * R)$. Mai sus am definit $Max{~i,j~}$ ca fiind maximul dintre $P{~i,j~}, P{~i+1,j~},.. P{~i+R-1,j~}$. Rezultă că $Max{~i+1,j~}$ este maximul dintre $P{~i+1,j~}, P{~i+2,j~},.. P{~i+R-1,j~}, P{~i+R,j~}$, adică maximul dintre elementele lui $Max{~i,j~}$ din care scoatem $P{~i,j~}$ şi adăugăm $P{~i+R,j~}$. De aici deducem că pentru fiecare coloană fixată, valorile lui $Max$ de pe coloana respectivă se reduc la a determina pentru fiecare subsecvenţă de lungime $R$ (numărul de linii al dreptunghiului de amplasat) elementul maxim. Aceste rezultate se obţin în $O(M)$ pentru fiecare coloană, deci $O(N * M)$ în total.\r\n\r\nRezultă complexitatea finală $O(M * N)$.\r\n\r\nh2(#problema-5). 5. \'Trans\':problema/trans (ONI 2004)\r\n\r\nbq. Se dau $N$ blocuri de piatră, de culoare albă sau neagră aşezate în ordinea $1$, $2$,.., $N$. Blocurile de piatră trebuie să fie transportate în ordinea în care sunt, iar pentru aceasta va trebui închiriat un camion. Se mai dau $Q$ tipuri de camioane. Camionul de tipul $i (1 &le; i &le; Q)$ poate transporta maxim $K{~i~}$ blocuri de piatră la un moment dat şi pentru un transport se percepe taxa $T{~i~}$. Se impune condiţia ca toate blocurile de piatră plasate în camion la un transport sa aibă aceeaşi culoare. Aşadar, pentru a fi transportate toate blocurile, se va alege un camion de un anumit tip, iar camionul va efectua unul sau mai multe transporturi. Pentru a micşora suma totală plătită, există posibilitatea de a schimba culoarea oricărui bloc de piatră (din alb în negru sau din negru în alb); pentru fiecare bloc $i (1 &le; i &le; N)$ se cunoaşte suma $S{~i~}$ ce trebuie plătită pentru a-i schimba culoarea $C{~i~}$.\r\nCerinţă: Pentru fiecare dintre cele $Q$ tipuri de camioane, determinaţi suma minimă plătită pentru a transporta toate cele $N$ blocuri.\r\nRestricţii: $1 &le; N &le; 16 000$, $1 &le; Q &le; 100$, $1 &le; K{~i~} &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se bazează pe găsirea unei formule de recurenţă ce respectă principiul optimalităţii al metodei programării dinamice.\r\n\r\nPentru început, fixăm un camion dintre cele <tex> Q </tex>. Fie <tex> K </tex> numărul maxim de pietre pe care acesta le poate transporta şi <tex> T </tex> taxa percepută. Notăm <tex> sum_{i,c} </tex> costul pentru a schimba toate pietrele <tex> 1, 2, \\ldots, i </tex> în culoarea <tex> c </tex> (<tex> c = 0 </tex> pentru alb şi <tex> c = 1 </tex> pentru negru). Rezultă că în <tex> sum_{i,c} </tex> se vor însuma toate valorile <tex> S_{j} </tex>, cu <tex> j \\le i </tex> pentru care <tex> C_{j} = 1 - c </tex>. \r\n\r\nÎn continuare, considerăm <tex> bst_{i,c} </tex> costul minim pentru a transporta pietrele <tex> 1, 2, \\ldots, i </tex>, iar ultimul transport conţine pietre de culoare <tex> c </tex>. Întrucât nu putem transporta mai mult de <tex> K </tex> pietre, <tex> bst_{i,c} </tex> depinde doar de poziţiile <tex> i - K, i - K + 1, \\ldots, i - 1 </tex>. Cunoaştem că ultimul camion va transporta o secvenţă continuă de pietre începând de la o poziţie <tex> j + 1 </tex> până la poziţia <tex> i </tex>, unde <tex> i - K \\le j \\le i - 1 </tex>. Astfel, pentru  fiecare <tex> j </tex> în intervalul precedent, costul va fi <tex> Min(bst_{j,0}, bst_{j,1}) </tex> (transportăm primele <tex> j </tex> pietre cât mai ieftin) adunat cu <tex> sum_{i,c} - sum_{j,c} </tex> (costul transformării pietrelor <tex> j + 1, \\ldots, i </tex> în culoarea <tex> c </tex>) şi plus taxa <tex> T </tex>. Rezultă recurenţa:\r\n\r\n* <tex> bst_{i,c} = Min\\ \\{\\ Minim(bst_{j,0},\\ bst_{j,1}) + sum_{i,c} - sum_{j,c} + T\\ :\\ i - K \\le j \\le i - 1\\ \\}; </tex>\r\n\r\nDacă ne vom opri aici, complexitatea soluţiei va fi <tex> O(Q * N^{2}) </tex>.\r\n\r\nRelaţia de recurenţă poate fi îmbunătăţită. Observăm că pentru poziţia <tex> i </tex>, <tex> sum_{i,c} </tex> este o valoare constantă, ca şi <tex> T </tex>. Astfel, deducem următoarea relaţie de recurenţă:\r\n\r\n* <tex> bst_{i,c} = Min\\ \\{\\ Minim(bst_{j,0},\\ bst_{j,1}) - sum_{j,c}\\ :\\ i - K \\le j \\le i - 1\\ \\} + sum_{i,c} + T; </tex>\r\n\r\nNotez în continuare, pentru uşurinţă în scriere, <tex> T_{j,c} = Min(bst_{j,0}, bst_{j,1}) - sum_{j,c} </tex>. Să fixăm doi indici <tex> i_{1} </tex> şi <tex> i_{2} </tex>, astfel încât <tex> i - K \\le i_{1} < i_{2} \\le i - 1 </tex>. Dacă <tex> T_{i_{1},c} > T_{i_{2},c} </tex> atunci întotdeauna poziţia <tex> i_{2} </tex> va fi preferată poziţiei <tex> i_{1} </tex>. Când cele două nu se vor mai afla ambele în intervalul <tex> [i - K, i - 1] </tex>, poziţia eliminată va fi poziţia <tex> i_{1} </tex>. Dacă <tex> T_{i_{1},c} < T_{i_{2},c} </tex>, atunci nu putem decide care poziţie este mai bună în viitor, aşa că le vom păstra pe ambele. Rezultă mai departe că în intervalul <tex> [i - K, i - 1] </tex> vom avea o serie de indecşi candidaţi la minim <tex> i - K \\le i_{1} < i_{2} < \\ldots < i_{n} \\le i - 1 </tex> astfel încât <tex> T_{i_{1},c} < T_{i_{2},c} <  .. < T_{i_{n},c} </tex>. Mai departe, găsim <tex> bst_{i,c} = T_{i_{1},c} + sum_{i,c} + T </tex>. Urmează să îl introducem şi pe <tex> T_{i,c} </tex> în şirul de indecşi de mai sus, el fiind egal cu <tex> Minim(bst_{i,0}, bst_{i,1}) - sum_{i,c} </tex>. Acest lucru se va face în felul următor: se vor elimina din <tex> i_{n}, , i_{n-1}, \\ldots </tex> atâta timp cât <tex> T_{i_{n},c} > T_{i,c} </tex>, <tex> T_{i_{n-1},c} > T_{i,c} \\ldots </tex> adică atâta timp cât poziţia <tex> i </tex> este preferată lui <tex> i_{n}, i_{n-1}, \\ldots </tex>. Fiind la poziţia <tex> i + 1 </tex>, intervalul se va transforma în <tex> [i - K + 1, i] </tex>, aşadar, vom mai elimina din primii indici <tex> i_{1}, i_{2}, \\ldots </tex> atâta timp cât <tex> i_{1} < i - K + 1, i_{2} < i - K + 1, \\ldots </tex>.\r\n\r\nDupă cum am arătat şi la problema precedentă, acest şir de indecşi <tex> i_{1}, i_{2}, \\ldots, i_{n} </tex> are proprietatea că este un şir continuu de numere care admite inserări prin dreapta (tail) şi ştergeri prin stânga (head). Şir ce poate fi reprezentat printr-un deque. Cum fiecare index dintre <tex> 1, 2, \\ldots, N </tex> va trece o singură dată prin deque, complexitatea soluţiei va fi <tex> O(N) </tex> pentru fiecare camion, deci <tex> O(Q * N) </tex> în total.\r\n\r\nÎn practică, programul este scurt, clar şi eficient:\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\n#include <vector>\r\n#include <deque>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\nconst char iname[] = \"trans.in\";\r\nconst char oname[] = \"trans.out\";\r\n\r\n#define MAXN  16005\r\n#define Min(a, b) ((a) < (b) ? (a) : (b))\r\n#define FOR(i, a, b)  for (int i = (a); i <= (b); ++ i)\r\n\r\nint C[MAXN], S[MAXN], bst[MAXN][2], sum[MAXN][2], N;\r\n\r\nvoid insert(deque < pair <int, int> >& deq, const pair <int, int>& p) {\r\n    while (!deq.empty() && deq.back().second > p.second)\r\n        deq.pop_back();\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque < pair <int, int> >& deq, const int idx) {\r\n    while (deq.front().first < idx)\r\n        deq.pop_front();\r\n    return deq.front().second;\r\n}\r\n\r\nint work(const int K, const int T) {\r\n    deque < pair <int, int> > deq[2];       // pair (idx, value)\r\n    FOR (c, 0, 1)\r\n        insert(deq[c], pair <int, int>(0, 0));\r\n    FOR (i, 1, N) {   // obiectul i\r\n        FOR (c, 0, 1) // culoare\r\n            bst[i][c] = query(deq[c], i - K) + sum[i][c] + T;\r\n        FOR (c, 0, 1)\r\n            insert(deq[c], pair <int, int>(i, Min(bst[i][0], bst[i][1]) - sum[i][c]));\r\n    }\r\n    return Min(bst[N][0], bst[N][1]);\r\n}\r\n\r\nint main(void)\r\n{\r\n    ifstream in(iname);  ofstream out(oname);\r\n    in >> N;\r\n    FOR (i, 1, N) {\r\n        in >> C[i] >> S[i];\r\n        FOR (c, 0, 1)\r\n            sum[i][c] += sum[i - 1][c];\r\n        sum[i][1 - C[i]] += S[i];\r\n    }\r\n    int cnt, K, T;\r\n    in >> cnt;\r\n    FOR (i, 1, cnt)\r\n        in >> K >> T, out << work(K, T) << \"\\n\";\r\n\r\n    in.close(), out.close();\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#problema-6). 6. \'Otilia\':problema/otilia  (.campion, 2005)\r\n\r\nbq. Otilia şi Burbucel au o grămadă de $N$ pietre şi vor juca un joc cu următoarele trei reguli: 1. Primul jucător are voie să ia din gramadă cel mult $K$ piese; 2. Cu excepţia primei mutări, fiecare jucător are voie să ia maxim $P * t$ pietre, unde $t$ este numărul de pietre care au fost substituite din grămadă la mutarea precedentă; 3. Pierde cel care mută ultimul (cel care ia ultimele pietre din grămadă).\r\nCerinţă: Se dau $M$ jocuri prin numerele $N$, $K$ şi $P$. Se cere să se determină dacă Otilia va câştiga fiecare din jocuri sau nu.\r\nRestricţii: $1 &le; M &le; 30 000$, $1 &le; N &le; 5 000 000$, $1 &le; K &le; N$, $1 &le; P &le; 10$.\r\n\r\nh3. Soluţie (Silviu Ganceanu):\r\n\r\nProblema se rezolvă prin programare dinamică. Soluţia se bazează pe observaţia de mai jos. Considerăm $P$-ul fixat şi notăm cu $stare(X, Y)$ poziţia de start în care avem $X$ pietre şi numărul maxim de pietre care se pot lua la prima mutare este $Y$.\r\n\r\n_Observaţia 1_: „Dacă există strategie sigură de câştig pentru $stare(X, Y)$ atunci există şi pentru orice $stare(X, T)$ cu $T &ge; Y$.” \r\n\r\nDe ce? Pentru că orice mutare validă pentru $stare(X, Y)$ este validă şi pentru $stare(X, T)$. Având această observaţie notăm cu $MinY[X] = Y$, $Y$ minim astfel încât avem strategie de câştig pentru $stare(X, Y)$.\r\n\r\n_Observaţia 2_: „{$stare(X, Y)$} este pierzătoare dacă şi numai dacă $Y < MinY[X]$.” \r\n\r\nAceasta reiese din definiţia lui $MinY[X]$.\r\n\r\n$MinY[X]$ se calculează după următoarea recurenţă, care rezultă din regulile jocului: \r\n\r\n* $MinY[X]$ este cel mai mic $i$ pentru care avem $MinY[X - i] > P * i$.\r\n\r\nDe aici se naşte prima soluţie, care este implementarea directă a recurenţei. Deşi complexitatea acesteia pare a fi $O(N^2^)$ ea se comportă foarte bine pentru $N &le; 500 000$. Aşadar, această soluţie acoperă aproximativ $50%$ din testele de intrare. Printr-o rafinare a acestei soluţii se obţine un algoritm de complexitate $O(N)$. Rafinarea se bazează pe: \r\n\r\n_Observaţia 3_: „Să presupunem că dorim să calculăm $MinY[X]$. Facem următoarea afirmaţie: orice poziţie _rea_ pentru $X$ (în care dacă mutăm pierdem) va fi _rea_ şi pentru $X + 1$.”\r\n\r\nAcest lucru este simplu de observat dacă privim ce înseamnă că o poziţie $Q$ e rea pentru $X$: \r\n\r\n* $MinY[Q] > X - Q$, pentru $X$;\r\n* $MinY[Q] > X - Q + 1$, pentru $X + 1$.\r\n\r\nEste evident că prima relaţie o implică pe cea de-a doua. În momentul acesta se poate construi următorul algoritm: având lista de poziţii care pot fi bune pentru $X$ (sortată descrescător) o căutăm pe cea mai mare ca valoare care este într-adevăr bună. În principiu, scoatem din capul listei poziţiile rele până când dăm de o poziţie bună. La listă se va adăuga şi $X$ şi se va trece la pasul următor. Operaţiile algoritmului sunt chiar operaţiile asupra unui deque.\r\n\r\nh2(#problema-7). 7. \'Bcrc\':problema/bcrc (Stelele Informaticii, 2006)\r\n\r\nbq. Se consideră $N$ camere, numerotate de la $1$ la $N$, aşezate în cerc. Iniţial (la momentul de timp 0), ne aflăm în camera $1$. În fiecare moment de timp, putem alege să rămânem în camera în care ne aflăm sau să ne deplasăm într-o cameră vecină într-o unitate de timp. Se dă o listă de $M$ cutii ce conţin bomboane prin $T$, $C$ şi $B$: cutia apare la momentul $T$ în camera $C$ şi conţine $B$ bomboane. Cutia va dispărea la momentul $T + 1$.\r\nCerinţă: Cunoscând numărul de camere din labirint şi momentele de timp la care apar cutiile cu bomboane, determinaţi care este numărul maxim de bomboane pe care le putem culege.\r\nRestricţii: $3 &le; N &le; 2 048$, $0 &le; M &le; 50 000$, $1 &le; T &le; 1 000 000 000$, $1 &le; C &le; N$, $1 &le; B &le; 9 999$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia foloseşte metoda programării dinamice.\r\n\r\nO stare se reprezintă prin camera în care ne aflăm şi momentul de timp. Fie <tex> bst_{i,j} </tex> numărul maxim de bomboane culese până în momentul <tex> i </tex> când ne găsim în camera <tex> j </tex>. O observaţie evidentă este că <tex> bst_{i,j} </tex> se poate modifica doar în momentele în care apar cutiile. Prin urmare, vom considera momentele de timp când apar cutiile, momente ce sunt în număr de <tex> M </tex>, <tex> bst_{i,j} </tex> însemnând numărul maxim de bomboane culese ştiind că ne aflăm în camera <tex> j </tex> unde am cules cutia <tex> i </tex>. De cine depinde această stare? Ştim că <tex> bst_{i-1,1 \\ldots N} </tex> a fost deja calculat în mod optim. Să notăm cu <tex> T </tex> diferenţa de timp dintre momentele la care apare cutia <tex> i </tex> şi cutia <tex> i - 1 </tex>. În această stare, <tex> i </tex> şi cameră <tex> j </tex>, putem ajunge din maxim <tex> T </tex> camere spre stânga sau spre dreapta, întrucât fiecare deplasare între două camere costă o unitate de timp. De unde deducem că:\r\n\r\n* <tex> bst_{i,j} = Min\\{\\ bst_{i-1,j-T},\\ bst_{i-1,j-T+1}, \\ldots,\\ bst_{i-1,j}, \\ldots,\\ bst_{i-1,j+T-1},\\ bst_{i-1,j+T}\\ \\}; </tex>\r\n\r\nMetoda directă, şi aparent eficientă, constă în folosirea unui arbore de intervale pentru aflarea acestui minim. Însă, intervalul <tex> [j-T,j+T] </tex> se deplasează constant spre dreapta, dacă vom considera indicii <tex> j </tex> în ordine <tex> 1, 2, 3, \\ldots </tex>. În acest interval noile elemente se introduc prin dreapta şi altele se elimină prin stânga. Însă, cum am arătat în problemele precedente, nu avem nevoie de toate valorile din acest interval. Şi din acest motiv vom folosi un deque de lungime <tex> T * 2 + 1 </tex> cu care vom elimina poziţiile care nu sunt candidate la soluţie. Mai jos este o reprezentare grafică a acestei explicaţii.\r\n\r\np=. !deque-si-aplicatii?bcrc.png 40%!\r\n\r\nComplexitatea finală: <tex> O(M * N) </tex>.\r\n\r\nh2(#problema-8). 8. \'Cut the Sequence\':http://acm.pku.edu.cn/JudgeOnline/problem?id=3017 (PKU) \r\n\r\nbq. Se dă o secvenţă $S$ de numere întregi de lungime $N$. Va trebui să se împartă secvenţa în mai multe subsecvenţe astfel încât suma valorilor din fiecare parte să nu depăşească un număr întreg $M$ dat, iar dacă însumăm maximul din fiecare subsecvenţă să obţinem o sumă cât mai mică.\r\nRestricţii: $0 &lt; N &le; 100 000$, $0 &le; S{~i~} &le; 1 000 000$.\r\n\r\nh3. Soluţie:\r\n\r\nŞi această soluţie foloseşte metoda programării dinamice. Construim <tex> bst_{i} </tex> egal cu costul minim de a împărţi primele <tex> i </tex> numere din <tex> S </tex>. Pentru a calcula <tex> bst_{i} </tex> alegem toate secvenţele posibile care încep la o poziţie <tex> j+1 </tex>, <tex> j < i </tex>, şi adunăm valorile corespunzătoare:\r\n\r\n* <tex> bst_{i} = Min\\{bst_{j} + Max\\{S_{j+1},.., S_{i}\\}\\ :\\ 0 \\le j < i, \\displaystyle\\sum_{k=j+1}^{i} S_{k} \\le M\\}; </tex>\r\n\r\nImplementarea directă a acestei recurenţe conduce la un algoritm de complexitate <tex> O(N^{2}) </tex>, dar care pentru restricţiile impuse nu este de ajuns.\r\n\r\nSă obţinem în continuare alte informaţii. Fie indicele <tex> j </tex> minim astfel încât <tex> \\displaystyle\\sum_{k=j+1}^{i} \\le M </tex>. Maximul obţinut din mulţimea <tex> \\{S_{j+1},.., S_{i}\\} </tex> se găseşte pe o poziţie <tex> j^{\'} </tex> unde <tex> j < j^{\'} \\le i </tex>. Însă, orice indice <tex> k </tex> cu <tex> j \\le k < j^{\'} </tex> are proprietatea că rezultatul expresiei <tex> Max\\{S_{k+1},.., S_{i}\\} </tex> se găseşte pe poziţia <tex> j^{\'} </tex>. Rezultă că <tex> \\forall k \\in \\{j, j+1,.., j^{\'}-1\\} </tex>, <tex> bst_{i} </tex> poate fi îmbunătăţit cu valoarea <tex> bst_{k} + S_{j^{\'}} </tex>. Minimul mulţimii <tex> \\{bst_{k} + S_{j^{\'}} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} </tex> este egal cu minimul expresiei <tex> \\{bst_{k} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} + S_{j^{\'}} (*) </tex>, deci, schimbând reperele, pentru maximul de pe poziţia <tex> j^{\'} </tex>, dacă lungimea secvenţei care se termină în <tex> i </tex> este cel puţin <tex> i-j^{\'}+1 </tex>, atunci optimul se obţine calculând rezultatul expresiei <tex> (*) </tex>. Pentru minimul pe un interval, <tex> [j, j^{\'}-1] </tex> al valorile vectorului <tex> bst </tex>, putem folosi un arbore de intervale pentru <tex> O(log_{2}N) </tex> pe interogare.\r\n\r\nDar, lungimea optimă a ultimei secvenţe ce se termină în <tex> i </tex> poate fi mai mică decât <tex> i-j^{\'}+1 </tex>, deci poate fi cel mult <tex> i-j^{\'} </tex>. Optimul se găseşte printre elementele mulţimii <tex> \\{bst_{k} + Max\\{S_{k+1},..,S_{i}\\} : j^{\'} \\le k < i\\} </tex>. Dacă procedăm ca la pasul anterior vom obţine un alt indice <tex> j^{\'\'} </tex> cu aceleaşi proprietăţi pentru secvenţa <tex> [j^{\'}, i] </tex> precum <tex> j^{\'} </tex> pentru secvenţa <tex> [j, i] </tex>.\r\n\r\nInductiv obţinem un şir de indici <tex> j_{0} = j < j_{1} < j_{2} < .. < j_{K} = i </tex> astfel încât <tex> S_{j_{1}} </tex> este cel mai mare element al secvenţei <tex> (j, i] </tex>, <tex> S_{j_{2}} </tex> cel mai mare element al secvenţei <tex> (j_{1}, i] </tex>, şi aşa mai departe, când <tex> j_{K} </tex> este chiar <tex> i </tex>.\r\n\r\nCu ajutorul relaţiei <tex> (*) </tex> şi a şirului <tex> j_{1} < j_{2} < .. < j_{K} = i </tex> vom construi un alt vector <tex> iMin </tex> cu proprietatea că <tex> iMin_{p} = Min\\{bst_{r} + S_{j_{p}} : j_{p-1} \\le r < j_{p}\\} </tex>. În final, <tex> bst_{i} = Minim\\{iMin_{1}, iMin_{2}, .., iMin_{K}\\} </tex>, rezultat pe care îl putem obţine în <tex> O(log_{2}N) </tex> dacă folosim un arbore de intervale.\r\n\r\nÎnsă, cum se construieşte şirul <tex> j_{1} < j_{2} < .. < j_{K} = i </tex>? În \'a doua problemă\':deque-si-aplicatii#problema-2 am construit cu ajutorul unui deque exact şirul de indici de care avem nevoie aici. Când vom înainta la indicele <tex> i + 1 </tex> vom modifica şirul astfel încât să respecte proprietăţile de mai sus utilizând operaţiile normale asupra unui deque. Mai sus am menţionat cum se obţine <tex> bst_{i} </tex> lucru care implică combinarea structurilor de deque şi arbore de intervale. Arborele de intervale reţine valorile lui <tex> iMin </tex> pentru fiecare element al dequelui. \r\n\r\nPentru a înţelege cum funcţionează acest algoritm să considerăm ca date de intrare şirul <tex> S = \\{5, 9, 4, 7, 4, 1, 6, 3\\} </tex> şi <tex> M = 15 </tex>. Perechile din deque sunt de forma <tex> (S_{i}, iMin_{p}) </tex>. Fie <tex> i = 1, 2, \\ldots 8 </tex>:\r\n\r\n* <tex> i = 1: j = 0, head = 1, tail = 1, deque = \\{\\ (5, 0)\\ \\} \\Rightarrow bst_{1} = 5; </tex>\r\n* <tex> i = 2: j = 0, head = 1, tail = 1, deque = \\{\\ (9, 0)\\ \\} \\Rightarrow bst_{2} = 9; </tex>\r\n* <tex> i = 3: j = 1, head = 1, tail = 2, deque = \\{\\ (9, 5),\\ (4, 9)\\ \\} \\Rightarrow bst_{3} = 13; </tex>\r\n* <tex> i = 4: j = 2, head = 2, tail = 2, deque = \\{\\ (7, 9)\\ \\} \\Rightarrow bst_{4} = 16; </tex>\r\n* <tex> i = 5: j = 2, head = 2, tail = 3, deque = \\{\\ (7, 9),\\ (4, 16)\\ \\} \\Rightarrow bst_{5} = 16; </tex>\r\n* <tex> i = 6: j = 3, head = 2, tail = 4, deque = \\{\\ (7, 13),\\ (4, 16),\\ (1, 16)\\ \\} \\Rightarrow bst_{6} = 17; </tex>\r\n* <tex> i = 7: j = 4, head = 3, tail = 3, deque = \\{\\ (6, 16)\\ \\} \\Rightarrow bst_{7} = 22; </tex>\r\n* <tex> i = 8: j = 4, head = 3, tail = 4, deque = \\{\\ (6, 16),\\ (3, 22)\\ \\} \\Rightarrow bst_{8} = 22; </tex>\r\n\r\nMai jos se vede o figură în care elementele unui deque sunt defapt o secvenţă „continuă” de frunze ale unui arbore de intervale pentru cazul <tex> i = 6 </tex>.\r\n\r\np=. !deque-si-aplicatii?PKU0.png 60%!\r\n\r\np=. _Numărul maxim de elemente ce pot trece prin deque este $8$. În figură, arborele ţine minimul de pe poziţiile $2$, $3$, $4$ din deque._\r\n\r\nAlgoritmul în pseudocod arată în felul următor:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    sum  = 0;\r\n    last = 0;\r\n    // indicii head si tail ai dequeului\r\n    head = tail = 1;\r\n    // poziţia lui bst[0] se inserează în deque\r\n    deque[1] = 0;\r\n    pentru i = 1, N execută\r\n        sum += S[i];\r\n        temp = bst[ deque[tail] ];\r\n        cât timp (head <= tail) şi (S[ deque[tail] ] <= S[i]) execută\r\n            temp = Min(temp, iMin[tail]);\r\n            tail --;\r\n        sfârşit;\r\n        // adaug poziţia i la deque\r\n        tail ++;\r\n        deque[tail] = i;\r\n        // actualizez iMin[]\r\n        iMin[tail]  = temp;\r\n        // actualizez T[], arborele de intervale pe deque[]\r\n        Update(T, tail, iMin[tail] + S[i]);\r\n        // suma valorilor din [last, i] trebuie să nu depăşească M\r\n        cât timp (sum > M) execută\r\n            sum -= S[last];\r\n            dacă (deque[head] == last) atunci\r\n                head ++;\r\n            sfârşit;\r\n            last ++;\r\n        sfârşit;\r\n        // actualizez iMin[], Tb[] arborele de intervale pe bst[]\r\n        iMin[head] = Query(Tb, Max(last - 1, 0), deque[head] - 1);\r\n        // actualizez T[]\r\n        Update(T, head, iMin[head] + S[ deque[head] ]);\r\n        // reţin optimul pentru poziţia curentă\r\n        bst[i] = Query(T, head, tail);\r\n        // actualizez Tb[]\r\n        Update(Tb, i, bst[i]);\r\n    sfârşit;\r\n    scrie bst[N];\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală este <tex> O(N*log_{2}N) </tex>.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nFilozofia din spatele structurii de deque devine utilă, de obicei, în părţile finale ale rezolvării unei probleme. Însă, ce pot spune cu certitudine este că această structură de date pe cât este de simplă pe atât este de eficientă şi necesară.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\nÎnţelegerea profundă nu se poate realiza decât prin rezolvarea a cât mai multe probleme. Succes!\r\n\r\n* \'Deque\':problema/deque, _Arhiva educaţională_\r\n* \'Secvenţă\':problema/secventa\r\n* \'Secvenţă 3\':problema/secv3\r\n* \'Secvenţă 4\':problema/secv4\r\n* \'Sum 2\':problema/sum2, _Stelele Informaticii, 2003_\r\n* \'Drept 2\':problema/drept2, _Lotul Naţional de Informatică, 2006_\r\n* \'Copaci 2\':problema/copaci2, _.campion, 2007_\r\n* \'Struţi\':problema/struti\r\n* \'Brânză\':problema/branza\r\n* \'Trompetă\':problema/trompeta\r\n* \'Buline\':problema/buline\r\n* \'Balans\':problema/balans\r\n* \'Ksecv\':problema/ksecv, _Selecţie echipe ACM ICPC, UPB, 2008_\r\n* \'Munte4\':problema/munte4, _Lotul Naţional de Informatică, 2005_\r\n* \'Gard\':problema/gard, _ONI, 2002_\r\n* \'Ghiozdan\':problema/ghiozdan\r\n* \'Cover\':problema/cover, _Baraj ONI, 2007_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Cosmin Negruşeri, \"_Probleme cu secvenţe_\":probleme-cu-secvente\r\n# Dana Lica, \"_Arbori de intervale şi aplicaţii în geometria computaţională_\":arbori-de-intervale\r\n# Cătălin Frâncu, \"_Heapuri_\":heapuri\r\n# Marius Stroe, \"_Treapuri_\":treapuri\r\n# \'C++ Reference\':http://www.cplusplus.com/',2044,'public',NULL,NULL),('concursul-de-informatica','Concursul de informatica','2008-02-03 17:43:07','2009-02-09 12:29:58','h1. Concursul de informatica (de la agonie la extaz)\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"Cyber\") ==\r\n\r\n(Categoria _Diverse_, Autor _Catalin Francu_, Preluat din cartea _\"Psihologia concursurilor de informatica\"_)\r\n\r\n(toc){width: 37em}*{text-align:center} *Conţinut:*\r\n* \'Inainte de concurs\':concursul-de-informatica#inainte-de-concurs\r\n* \'In timpul concursului\':concursul-de-informatica#in-timpul-concursului\r\n* \'Strategii in timpul concursului\':concursul-de-informatica#strategii\r\n* \'Concluzii\':concursul-de-informatica#concluzii\r\n\r\nh3. _\"Cine doreste sa-si rezolve treburile la vremea potrivita, sa-si imparta cu atentie timpul\"_, Plaut\r\n\r\nExperienta demonstreaza ca, oricat de mare ar fi bagajul de cunostinte acumulat de un elev, mai e nevoie de ceva pentru a-i asigura succesul la olimpiada de informatica. Aceasta deoarece in timp de concurs lucrurile stau cu totul altfel decat in fata calculatorului de acasa sau de la scoala. Reusita depinde, desigur, in cea mai mare masura de puterea fiecaruia de a pune in practica ceea ce a invatat acasa. Numai ca in acest proces intervin o serie de factori care tin de temperament, de experienta individuala, de numarul de ore dormite in noaptea dinaintea concursului (care in taberele nationale este ingrijorator de mic) si asa mai departe. \r\n\r\nCu riscul de a cadea in demagogie, trebuie sa spunem ca un concurs de informatica presupune mult mai mult decat un simplu act de prezenta la locul desfasurarii ostilitatilor. Capitolul de fata incearca sa enunte cateva principii ale concursului, pe care autorul si le-a insusit in cei patru ani de liceu, atat  din experienta proprie, cat si invatand de la altii. Cititorul este liber sa respinga aceste sfaturi sau sa le accepte, filtrandu-le prin prisma personalitatii sale si alegand ceea ce i se potriveste.\r\n\r\nh2(#inainte-de-concurs). Inainte de concurs\r\n\r\nPrimul si cel mai de seama lucru pe care trebuie sa il stiti este ca e important si sa participi, dar e si mai important sa participi onorabil, iar daca se poate sa si castigi. Nu trebuie sa porniti la drum cu ingamfare; modestia e buna, dar nu trebuie in nici un caz sa duca la neincredere in sine. Fiecare trebuie sa stie clar de ce e in stare si, mai presus de toate, sa se gandeasca ca la urma urmei nu dificultatea concursului conteaza, caci concursul, greu sau usor, este acelasi pentru toti. Mult mai importanta este valoarea individuala si nu in ultimul rand pregatirea psihologica.\r\n\r\nAutorul a fost peste masura de surprins sa constate ca multi elevi merg la concurs fara ceas si fara hartie de scris. Aceasta este fara indoiala o greseala capitala. In timpul concursului trebuie tinuta o evidenta drastica a timpului scurs si a celui ramas. E drept ca in general supraveghetorii anunta din cand in cand timpul care a trecut, dar e bine sa nu va bazati pe nimeni si nimic altceva decat pe voi insiva. Unii colegi spuneau \"Ei, ce nevoie am de ceas, oricum am ceasul calculatorului la indemana\". Asa e, dar e extrem de incomod sa te opresti mereu la jumatatea unei idei, sa deschizi o sesiune DOS din cadrul limbajului de programare si sa afli cat e ceasul.\r\n\r\nIn ceea ce priveste hartia de scris, ea este in mod sigur necesara. De fapt, o parte importanta a rezolvarii unei probleme este proiectarea matematica a algoritmului, lucru care nu se poate face decat cu creionul pe hartie. Pe langa aceasta, majoritatea problemelor opereaza cu vectori, matrice, arbori, grafuri etc., iar exemplele pe care este testat programul realizat trebuie neaparat verificate \"de mana\". E de preferat sa aveti hartie de matematica; este foarte folositoare pentru problemele de geometrie analitica, precum si pentru reprezentarea matricelor. Cantitatea depinde de imaginatia fiecaruia. In unele cazuri speciale, autorului i s-a intamplat sa umple 7-8 coli A4.\r\n\r\nh2(#in-timpul-concursului). In timpul concursului\r\n\r\nDin fericire pentru unii si din nefericire pentru altii, majoritatea examenelor iti cer sa dovedesti nu ca esti bine pregatit, ci ca esti mai bine pregatit decat altii. Aceasta inseamna ca si la olimpiada de informatica se aplica legea pestelui mai mare sau, cum i se mai spune, a concurentei. Valoarea absoluta a fiecaruia nu conteaza chiar in totalitate, ceea ce constituie sarea si piperul concursului. Intr-adevar, ce farmec ar avea sa mergi la un concurs la care se stie inca dinainte cine este cel mai bun ? Este destul de amuzant sa observi cum fiecare spera sa prinda \"o zi buna\", iar adversarii sai \"o zi proasta\".\r\n\r\nEste usor sa fii printre cei mai buni atunci cand concursul este usor. Mai greu e sa fii cel mai bun atunci cand concursul este dur, pentru ca atunci intervine - inevitabil - dramul de noroc al fiecaruia. Niciodata insa nu se poate invoca greutatea concursului drept o scuza pentru un eventual esec. Concursul este la fel de greu pentru toti. Se poate intampla, mai ales daca probele dureaza mai multe zile (3-4) ca nici unul din concurenti sa nu acumuleze mai mult de 70-80% din punctajul maxim. Totusi, aceasta nu inseamna ca ei nu sunt bine pregatiti; mai mult, unul dintre ei trebuie sa fie primul. Asadar, niciodata nu trebuie adoptata o strategie de genul \"problema asta e grea si n-am s-o pot rezolva perfect, asa ca nu ma mai apuc deloc de ea\". Nu trebuie sa va impacientati daca vi se intampla sa nu aveti o idee geniala de rezolvare a unei probleme. Nu va cere nimeni sa faceti perfect o problema, ci numai sa prezentati o solutie care sa acumuleze cat mai multe puncte. Evident, prima varianta este intotdeauna preferabila, dar nu obligatorie.\r\n\r\nDe multe ori se intampla ca un elev sa gaseasca o solutie cat de cat buna la o problema si, macar ca stie ca nu va lua punctajul maxim, ci doar o parte, sa renunte sa caute o solutie mai eficienta, deoarece timpul pierdut astfel ar aduce un castig prea mic si ar putea fi folosit la rezolvarea altor probleme. Desigur, daca nu faci toate problemele perfect, nu mai poti fi sigur de premiul I, pentru ca altcineva poate sa te intreaca. Dar pe de alta parte, locul pe care te clasezi conteaza numai la etapa nationala a olimpiadei sau la concursurile internationale. In rest, important e numai sa te califici, adica sa intri in primele cateva locuri.\r\n\r\nFeriti-va ca de foc de criza de timp. E mare pacat sa ratezi o problema intreaga pentru ca n-ai avut timp sa scrii procedura de afisare a solutiei. Rezervati-va intotdeauna timpul pe care il socotiti necesar pentru implementare si depanare.\r\n\r\nNiciodata, chiar daca concursul este usor, nu e bine sa iesiti din sala de concurs inainte de expirarea timpului. Oricat ati fi de convinsi ca ati facut totul perfect, mai verificati-va; veti avea de furca cu remuscarile daca descoperiti dupa aceea ca ceva, totusi, nu a mers bine. Puteti face o multime de lucruri daca mai aveti timp (desi acest lucru se intampla rar). Iata o serie de metode de a exploata timpul:\r\n\r\n* Verificati-va programul cu cat mai multe teste de mici dimensiuni. Sa presupunem ca programul vostru lucreaza cu vectori de maxim 10 000 de elemente. E o idee buna sa il rulati pentru vectori de unul sau doua elemente. Nu se stie cum pot sa apara erori.\r\n	\r\n* Treceti la polul opus si creati-va un test de dimensiune maxima, dar cu o structura particulara, pentru care este usor de calculat rezultatul si de mana. De exemplu, vectori de 10 000 elemente cu toate elementele egale, sau vectori de forma (1, 2, ..., 9 999, 10 000). Daca nu puteti sa editati un asemenea fisier de mana, copiind si multiplicand blocuri, puteti scrie un program care sa-l genereze.\r\n	\r\n* Daca inca v-a mai ramas timp, creati-va un program care sa genereze teste aleatoare. Spre exemplu, un program care sa citeasca un numar $N$ si sa creeze un fisier $INPUT.TXT$ in care sa scrie $N$ numere aleatoare. Intr-o prima faza, puteti folosi aceste teste pentru a verifica daca nu cumva la valori mai mari programul nu da eroare, nu se blocheaza (la alocarea unor zone mari de memorie) sau nu depaseste limita de timp, caz in care mai aveti de lucru.\r\n	\r\n* Daca tot nu va da nimeni afara din sala, puteti scrie un alt program auxiliar care, primind fisierul $INPUT.TXT$ si fisierul $OUTPUT.TXT$ produs de programul vostru, verifica daca iesirea este corecta. Aceasta deoarece, de obicei, este mult mai usor de verificat o solutie decat de produs una (sau, cum spunea Murphy, \"cunoasterea solutiei unei probleme poate ajuta in multe cazuri la rezolvarea ei\"). Folosind \"generatorul\" de teste si \"verificatorul\", puteti testa programul mult mai bine. De altfel, la multe probleme chiar testele rulate de comisia de corectare sunt create tot aleator.\r\n	\r\n* In caz ca ati dat o solutie euristica la o problema NP-completa, puteti implementa si un backtracking ca sa vedeti cat de bune sunt rezultatele gasite euristic. Apoi, puteti incepe sa modificati functia euristica pentru a o face cat mai performanta.\r\n\r\nh2(#strategii). Strategii in timpul concursului\r\n\r\nSi, ca sa nu mai lungim vorba, iata cateva strategii care par sa dea rezultate.\r\n\r\nh4. A)\r\n\r\nImediat ce primiti problemele, cititi toate enunturile si faceti-va o idee aproximativa despre gradul de dificultate al fiecarei probleme. Neaparat verificati daca se dau limite pentru datele de intrare (numarul maxim de elemente ale unui vector si valoarea maxima a acestora, numarul maxim de noduri dintr-un graf etc.) si pentru timpii de executie pentru fiecare test. Daca nu se dau, intrebati imediat. Dimensiunea input-ului poate schimba radical dificultatea problemei. Spre exemplu, pentru un vector cu $N = 100$ elemente, un algoritm $O(N^3^)$ merge rezonabil, pe cand pentru $N = 10 000$ acelasi algoritm ar depasi cu mult cele cateva secunde care se acorda de obicei. Fair-play-ul cere sa puneti intrebarile cu voce tare, pentru ca si ceilalti sa auda; de altfel, nu aveti nici un motiv sa va feriti de ceilalti concurenti. Cei care sunt interesati de aceste intrebari le-ar pune oricum si ei, iar cei care nu sunt interesati vor ignora oricum raspunsul.\r\n\r\nDaca exista probleme care cer sa se gaseasca un optim (maxim/minim) al unei valori, intrebati daca se acorda punctaje partiale pentru solutii neoptime. Si acest fapt poate schimba natura problemei. Dupa aceasta, \r\n\r\n== code(c) |\r\nNr_probleme_nerezolvate = Nr_probleme_primite;\r\n\r\nwhile ((Nr_probleme_nerezolvate > 0) and  !(\"Timpul a expirat, va rugam sa salvati\")) \r\n{\r\n==\r\n\r\nh4. B)\r\n\r\nFaceti o impartire a timpului pentru problemele ramase proportional cu punctajul fiecarei probleme. In general problemele au punctaje egale, dar nu totdeauna. De exemplu, daca o problema e cotata cu 100 puncte, iar alta cu 50, veti aloca de doua ori mai mult timp primei probleme, chiar daca nu vi se pare prea grea. Incercati sa nu depasiti niciodata limitele de timp pe care le-ati fixat. Daca in schimb reusiti sa economisiti timp fata de cat v-ati propus, cu atat mai bine, veti face o realocare a timpului si veti avea mai mult pentru celelalte probleme.\r\n\r\nh4. C)\r\n\r\nApucati-va de problema _cea mai simpla_, chiar daca e punctata mai slab. Mai bine sa duceti la bun sfarsit o problema usoara si sa luati un punctaj mai mic, decat sa va apucati de o problema grea si sa nu terminati niciuna. Daca toate problemele par grele, alegeti-o pe cea din domeniul care va este cel mai familiar, in care ati lucrat cel mai mult. Daca va este indiferent si acest lucru, alegeti o problema unde simtiti ca aveti o idee simpla de rezolvare. Daca, in sfarsit, nu aveti nici o idee la nici o problema, apucati-va de cea mai bine punctata.\r\n\r\nh4. D)\r\n\r\nCititi din nou enuntul, de data aceasta cu mare grija. Intrebati supraveghetorul pentru orice nelamurire. Daca anumite lucruri nu sunt specificate, iar profesorul nu va da nici un fel de informatii suplimentare, tratati problema in cazul cel mai general. Iata mai multe exemple frecvente in care enuntul nu este limpede:\r\n\r\n* Daca nu se precizeaza cat de mari pot fi intregii dintr-un vector, nu lucrati pe $Integer$, nici pe $Word$, ci pe $LongInt$;\r\n	\r\n* In problemele de geometrie analitica, e bine sa presupuneti ca punctele nu au coordonate intregi, ci reale;\r\n\r\n* De asemenea, patratele si dreptunghiurile nu au neaparat laturi paralele cu axele, ci sunt asezate oricum in plan (aceasta poate intr-adevar sa complice extrem de mult problema; nu va doresc sa va izbiti de o asemenea neclaritate...);\r\n	\r\n* Daca fisierul de intrare contine siruri de caractere, sa nu presupuneti ca ele au maxim $255$ de caractere. Mai bine scrieti propria voastra procedura de citire a unui sir de caractere, care sa citeasca din fisier caracter cu caracter pana la $Eoln$, decat sa aveti surprize. Daca $S$ este o variabila de tip $String$, $ReadLn(S)$ ignora tot restul randului care depaseste lungimea lui $S$;\r\n	\r\n* Grafurile nu sunt neorientate, ci orientate. In principiu, enuntul nu are voie sa fie neclar in aceasta privinta, dar au existat cazuri de neintelegere.\r\n\r\nh4. E)\r\n\r\nIncepeti sa va ganditi la algoritmi cat mai buni, estimand in acelasi timp si cat v-ar lua ca sa-i implementati. Faceti, pentru fiecare idee care va vine, calculul complexitatii. Nu trebuie neaparat sa gasiti cel mai eficient algoritm, ci numai unul suficient de bun. In general, trebuie ca, dintre toti algoritmii care se incadreaza in timpul de rulare, sa-l alegeti pe cel care este cel mai usor de implementat.\r\n\r\nSa presupunem ca timpul de testare este de $5$ secunde, lucrati pe un 486DX4, algoritmul vostru are complexitatea $O(N^3^)$, iar $N$ este maxim $100$. Un 486 face cateva milioane de operatii elementare pe secunda, sa zicem $4 000 000$. Aceasta inseamna ceva mai putine operatii mai costisitoare (atribuiri, comparatii etc.) pe secunda. Sa ne oprim deci la cifra de $1 000 000$. Programul vostru are timp de rulare cubic, iar $N^3^$ este maxim $1 000 000$. De aici deducem ca programul ar trebui sa se incadreze intr-o secunda. Calculul nostru este grosier, dar luand si o marja de eroare arhisuficienta, rezulta ca programul trebuie sa mearga cu usurinta in $5$ secunde, deci algoritmul este acceptabil.\r\n\r\nh4. F)\r\n\r\nDaca algoritmul gasit este greu de implementat, mai cautati un altul o vreme. Trebuie insa ca timpul petrecut pentru gasirea unui nou algoritm plus timpul necesar pentru scrierea programului sa nu depaseasca timpul necesar pentru implementarea primului algoritm, altfel nu castigati nimic. Deci nu exagerati cu cautarile si nu incercati sa reduceti dincolo de limita imposibilului complexitatea algoritmului. Mai ales, nu uitati ca programul nu poate avea o complexitate mai mica decat dimensiunea input-ului sau a output-ului. De exemplu, daca programul citeste sau scrie matrice de dimensiune $N x N$, nu are sens sa va bateti capul ca sa gasiti un algoritm mai bun decat $O(N^2^)$.\r\n\r\nh4. G)\r\n\r\nDintre toate ideile de implementare gasite (care se incadreaza fara probleme in timp), o veti alege pe cea mai scurta ca lungime de cod. De exemplu:\r\n\r\n* Daca $N &le; 1 000$ si dispuneti de doi algoritmi, unul pe care il estimati cam la $200$ de linii de program, de complexitate $O(N log N)$ si unul de $100$ de linii de complexitate $O(N^2^)$, cel de-al doilea este evident preferabil, pentru ca nu pierdeti nimic din punctaj, sau cel mult pierdeti un test prin cine stie ce intamplare, in schimb castigati timp pretios pe care il puteti folosi pentru alte probleme. Bineinteles, primul program este mai eficient, dar in conditii de concurs el este prea eficient. Este o mandrie sa faceti o problema perfect chiar daca ratati o alta, dar este un castig si mai mare sa faceti amandoua problemele suficient de bine.\r\n\r\nh4. H)\r\n\r\nIn general, pentru orice problema exista cel putin o solutie, fie si una slaba. Sunt numeroase cazurile cand nici nu va vine alta idee de rezolvare decat cea slaba. De regula, cand nu aveti in minte decat o rezolvare neeficienta a problemei, care stiti ca nu o sa treaca toate testele (un backtracking, sau un $O(N^5^)$, $O(N^6^)$ etc.), e bine sa incercati urmatorul lucru:\r\n\r\n* Sa presupunem ca v-a mai ramas o ora pentru rezolvarea acestei probleme. Calculati cam cat timp v-ar trebui ca sa implementati rezolvarea slaba. Sa zicem 40 de minute. In acest calcul trebuie sa includeti si timpul de depanare a programului (care variaza de la persoana la persoana) si pe cel de testare. Daca sunteti foarte siguri pe voi, puteti sa neglijati timpul de testare, dar orice program trebuie testat cel putin pe exemplul de pe foaie.\r\n	\r\n* Mai raman deci 20 de minute, timp in care va puteti gandi la altceva, la alta solutie. Pentru a avea sanse mai mari sa gasiti o alta solutie, este indicat sa incercati sa ignorati complet solutia slaba, sa nu o luati ca punct de plecare. Incercati sa va \"goliti\" mintea si sa gasiti ceva nou, altfel va veti invarti mereu in cerc.\r\n	\r\n* Daca va vine vreo idee mai buna, ati scapat de griji si mergeti la punctul **F)**. Altfel, la expirarea timpului de 20 de minute, va apucati sa implementati solutia pe care o aveti, oricat de ineficienta ar fi (de fapt, orice solutie, oricat de ineficienta, trebuie sa ia macar o treime sau o jumatate din punctaj, daca nu apar erori de implementare).\r\n	\r\n* Puteti, ca o masura extrema, sa depasiti cu maxim 5 minute cele 20 de minute planificate, dar de cele mai multe ori acesta e timp pierdut, deoarece intervine stresul si nu puteti sa va mai concentrati.\r\n\r\nh4. I)\r\n\r\nDaca ati ajuns pana aici inseamna ca ati optat pentru o varianta de implementare. Din acest moment, pentru aceasta varianta veti scrie programul, fara a va mai gandi la altceva, chiar daca pe parcurs va vin alte idei. Iata unele lucruri pe care e bine sa le stiti despre scrierea unui program:\r\n\r\n* Datele de intrare se presupun a fi corecte. Aceasta este o regula nescrisa (uneori) a concursului de informatica. Chiar daca, prin absurd, stiti sigur ca datele de intrare trebuie verificate, mai bine n-o faceti, din mai multe motive. In primul rand, scopul cu care v-a fost data problema este altul decat sa se constate cine verifica mai bine datele de intrare. De aceea, cel mult un test sau doua vor fi cu date gresite. In al doilea rand, nu se justifica sa risipiti atata timp numai pentru cateva puncte pe care le-ati putea pierde daca nu faceti verificarea. In al treilea rand, e posibil sa gresiti oricum problema in sine, caz in care nu mai conteaza daca ati citit perfect datele de intrare. In sfarsit, legea lui Murphy spune ca \"oricate teste ar efectua cineva asupra datelor de intrare, se va gasi cineva care sa introduca date gresite\". Efortul este deci zadarnic...\r\n	\r\n* Ultimul lucru, cand sunteti convinsi ca programul este terminat si cand v-ati hotarat sa nu il mai modificati, adaugati optiunile de compilare. Puteti face aceasta apasand $Ctrl-O-O$. La inceputul programului vor aparea directivele de compilare. Setati $&#36;B$, $&#36;I$, $&#36;R$ si $&#36;S$ pe - (minus). Eventual, puteti include direct linia $I&#36;B-,I-,R-,S-S$ imediat dupa titlul programului. Aceasta va face compilatorul sa nu mai evalueze complet expresiile booleene, sa nu mai verifice operatiile de intrare/iesire, domeniul de atribuire $(Range Checking)$ si stiva $(Stack Checking)$. Exista doua avantaje majore: in primul rand ca programul merge mai repede (se castiga cateva procente bune la viteza), iar in al doilea rand, psihologic vorbind, este preferabil ca un program sa se blocheze decat sa se opreasca printr-un banal $Range check error$. Nu va grabiti sa puneti directivele de compilare inca de la inceput, deoarece nu veti mai primi mesajele corespunzatoare de eroare si va va fi mai greu sa depanati programul.\r\n	\r\n* Pe cat este posibil, incercati sa convingeti juriul sa nu va ruleze sursa (Pascal sau C/C++), ci direct executabilul. Merge simtitor mai repede. Asta numai in cazul in care va temeti ca programul ar putea sa nu se incadreze in timp.\r\n	\r\n* Daca se poate, evitati lucrul cu pointeri. Programele care ii folosesc sunt mai greu de depanat si se pot bloca mult mai usor.\r\n	\r\n* Sa presupunem ca aveti de lucrat cu matrice de dimensiuni maxim $100 x 100$. Unii elevi au obiceiul sa dimensioneze la inceput matricele de $5 x 5$ sau $10 x 10$, deoarece sunt mai comod de evaluat cu $Evaluate (Ctrl-F4)$ sau $Watch (Ctrl-F7)$. Acest lucru este adevarat, dar exista riscul ca la sfarsit sa uitati sa redimensionati matricele de $100 x 100$. Decat sa faceti o asemenea greseala (care in mod sigur va va compromite toata problema), mai bine setati dimensiunile corecte de la inceput. De altfel, ideal ar fi ca depanarea programelor sa fie suprimata cu totul si programul sa mearga din prima.\r\n	\r\n* Evitati lucrul cu numere reale, daca puteti. Operatiile in virgula mobila sunt  mult mai lente. De exemplu, testul daca un numar este prim nu va incepe in nici un caz cu linia\r\n\r\n==code(c) |	\r\nwhile (i <= sqrt(N)) \r\n==\r\n\r\nci cu linia\r\n\r\n==code(c) |\r\nwhile (i * i <= N)\r\n==\r\n\r\nDin punct de vedere logic, conditiile sunt perfect echivalente. Totusi, prima se evalueaza de cateva zeci de ori mai incet decat a doua.\r\n\r\n* Daca lucrati cu numere reale, nu folositi testul\r\n\r\n==code(c) |\r\nif (R1 == R2)\r\n==\r\n\r\ndeoarece pot aparea erori, ci implementati o functie:\r\n\r\n==code(c) |\r\nint equal(float R1, float R2)\r\n{\r\n    if (abs(R1 - R2) < 1e-4)   // 1e-4 = 0.00001\r\n        return 1;\r\n    return 0;\r\n}\r\n==\r\n\r\nNumarul de zerouri de dupa virgula trebuie sa fie suficient de mare astfel incat doua numere diferite sa nu fie tratate drept egale (se poate lucra de pilda cu $0.000001$).\r\n\r\n* Tot in cazul numerelor reale, evitati pe cat posibil sa faceti impartiri, deoarece sunt foarte greoaie. De exemplu:\r\n\r\n	$X / 5 <=> 0.2 * X$\r\n	$X / Y / Z <=> X / (Y * Z)$\r\n\r\n* Optimizarile de genul $X shl 1$ respectiv $X << 1$ in loc de $2 * X$ sunt niste artificii de cele mai multe ori neesentiale, care in schimb fac formulele mai lungi, greu de urmarit si pot crea complicatii. Cel mai bine este sa lucrati cu notatiile obisnuite si doar la sfarsit, daca timpul de rulare trebuie redus cu orice pret, sa faceti inlocuirile.\r\n\r\n* Alegeti-va numele de variabile in asa fel incat programul sa fie clar. Sunt permise mai mult de doua litere! Numele fiecarei proceduri, functii, variabile trebuie sa-i explice clar utilitatea. E drept, lungimea programului creste, dar codul devine mult mai limpede si timpul de depanare scade foarte mult. Ca o regula generala, claritatea programelor face mult mai usoara intelegerea lor chiar si dupa o perioada mai indelungata de timp (luni, ani). Nu trebuie nici sa cadeti in cealalta extrema. De exemplu, nu depasiti 10 caractere pentru un nume de variabila.\r\n	\r\n* Salvati programul cat mai des. Daca va obisnuiti, chiar la fiecare doua-trei linii. Dupa ce o sa va intre in reflex n-o sa va mai incomodeze cu nimic acest obicei, mai ales ca in ziua de azi salvarea unui program de 2-3 KB se face practic instantaneu. Au fost frecvente cazurile in care o pana de curent prindea pe picior gresit multi concurenti, iar dupa aceea nu mai este absolut nimic de facut, pentru ca nimeni nu va va crede pe cuvant ca ati facut programul si ca el mergea.\r\n	\r\n* Obisnuiti-va sa programati modular. Faceti proceduri separate pentru citirea si initializarea datelor, pentru sortare, pentru afisarea rezultatelor etc. In general nu se recomanda sa scrieti proceduri in alte proceduri (adica e bine ca toate procedurile sa apartina direct de programul principal). Procedurile, acolo unde e posibil, nu trebuie sa depaseasca un ecran, pentru a putea avea o viziune de ansamblu asupra fiecareia in parte . Acest lucru ajuta mult la depanare.\r\n	\r\n* Rulati programul cat mai des. In primul rand dupa ce scrieti procedura de citire a datelor. Daca e nevoie de sortarea datelor de intrare, nu strica sa va convingeti ca programul sorteaza bine, ruland doua-trei teste oarecare. E pacat sa pierdeti puncte dintr-o greseala copilareasca.\r\n	\r\n* O situatie delicata apare cand fisierul de intrare contine mai multe seturi de date (teste). In acest caz, atentia trebuie sporita, deoarece daca la primul sau al doilea test programul vostru da eroare si se opreste din executie, veti pierde automat si toate celelalte teste care urmeaza. Daca in fisierul de intrare exista un singur set de date, atunci pierderea din vedere a unui caz particular al problemei nu putea duce, in cel mai rau caz, decat la picarea unui test. Asa insa, picarea unui test poate atrage dupa sine picarea tuturor celor care ii urmeaza. Pe langa corectitudinea strict necesara, programul trebuie sa se incadreze si in timp pentru orice fel de test. Daca la primul sau al doilea test din suita programul depaseste timpul (sau, si mai rau, se blocheaza), e foarte probabil sa fie oprit din executie de catre comisie, deci din nou veti pierde toate testele care au ramas neexecutate. Uneori comisia este binevoitoare si accepta sa modifice fisierul de date, taind din el setul pe care programul vostru nu merge, dar acest lucru este greoi si nu tocmai cinstit fata de ceilalti concurenti, deci nu va bazati pe asta.\r\n\r\n* Tot in situatia in care exista mai multe seturi de date in fisierul de intrare, daca iesirea se face intr-un fisier, este bine ca dupa afisarea rezultatului pentru fiecare test sa actualizati fisierul de iesire (fie prin comanda $Flush$, fie prin doua proceduri, $Close$ si $Append$). In felul acesta, chiar daca la unul din teste programul se blocheaza sau da eroare, rezultatele deja scrise raman scrise. Altfel, e posibil ca rezultatele de la testele anterioare sa ramana intr-un buffer in memorie, fara a fi \"varsate\" pe disc.\r\n	\r\n* Daca fisierul de iesire are dimensiuni foarte mari, de exemplu daca vi se cer toate solutiile, iar numarul acestora este de ordinul zecilor de mii, puteti avea surpriza ca timpul sa nu va ajunga pentru a le tipari pe toate in fisierul de iesire. Si in acest caz, este recomandat ca dupa tiparirea fiecarei solutii sa executati comanda $Flush$, sau sa inchideti fisierul de iesire si sa-l redeschideti in modul $Append$.\r\n\r\nh4. J)\r\n\r\nDaca ati trecut cu bine si de faza de scriere a programului, mai aveti doar partile de depanare si testare, care de multe ori se imbina. Metoda cea mai buna de depanare este urmatoarea:\r\n\r\n* Incepeti cu un test nici prea simplu, nici prea complicat (si usor de urmarit cu creionul pe hartie) si executati-l de la cap la coada. Daca merge perfect, treceti la teste mai complexe (minim 4 teste si maxim 7-8). Daca le trece si pe acestea, puteti fi mandri. Legile lui Murphy in programare se aplica in continuare: \"Depanarea nu poate demonstra ca un program merge; ea poate cel mult demonstra ca un program nu merge\". Totusi, daca programul vostru a mers perfect pe 7-8 teste date la intamplare, exista sanse foarte mari sa mearga pe majoritatea testelor comisiei, sau chiar pe toate.\r\n	\r\n* Exemplul dat in enunt nu are in general nici o semnificatie deosebita (de fapt, are mai curand darul de a semana confuzie printre concurenti), iar daca programul merge pe acest test particular, nu inseamna ca o sa mearga si pe alte teste. In culegere nu a fost explicat pe larg algoritmul decat pe exemplul din enuntul fiecarei probleme, dar aceasta s-a facut numai pentru a nu supraincarca materialul.\r\n\r\n* Daca la unul din teste programul nu merge corespunzator, rulati din nou testul, dar de data aceasta procedura cu procedura. Dupa fiecare procedura evaluati variabilele si vedeti daca au valorile asteptate. In felul acesta puteti localiza cu precizie procedura, apoi linia unde se afla eroarea. Corectati in aceasta maniera toate erorile, pana cand testul este trecut.\r\n	\r\n* In acest moment, luati de la capat toate testele pe care programul le-a trecut deja. In urma depanarii, s-ar putea ca alte greseli sa iasa la suprafata si programul sa nu mai mearga pe vechile teste.\r\n	\r\n* Repetati procedeul de mai sus pana cand toate testele merg. Daca va obisnuiti sa programati modular si ingrijit, depanarea si testarea n-ar trebui sa dureze mai mult de 5-10 minute. Din acest moment, nu mai modificati nici macar o litera in program, sau daca tineti sa o faceti, pastrati-va in prealabil o copie. Nu va bazati pe faptul ca puteti sa tineti minte modificarile facute si sa refaceti oricand forma initiala a programului in caz ca noua versiune nu va fi buna.\r\n	\r\n* Daca totusi nu-i puteti \"da de cap\" programului, iar timpul alocat problemei respective expira, aduceti programul la o forma in care sa mearga macar pe o parte din teste (pe jumatate, de exemplu) si treceti la problema urmatoare.\r\n\r\n**K)** \r\n\r\n==code(c) |\r\nNr_probleme_nerezolvate--;\r\n}\r\n==\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nProbabil nu veti fi de acord cu toate sfaturile date mai sus. E bine insa sa le aplicati. Scopul pentru care ele au fost incluse in aceasta carte este de a ajuta concurentii sa se acomodeze mai usor cu atmosfera concursului. De multe ori, primul an de participare la olimpiada se soldeaza cu un rezultat cel mult mediu, deoarece, oricat ar spune cineva \"ei, nu-i asa mare lucru sa mergi la un concurs\", experienta acumulata conteaza mult. De aceea, abia de la a doua participare si uneori chiar de mai tarziu incep sa apara rezultatele. Intentia autorului a fost sa va usureze misiunea si sa va dezvaluie cateva din dificultatile de toate felurile care apar la orice concurs, pentru a nu va da ocazia sa le descoperiti pe propria piele. Poate ca aceste ponturi va vor fi de folos.',3146,'public',NULL,NULL),('tabele-hash-prezentare-detaliata','Tabele hash - prezentare detaliata','2008-01-30 15:12:38','2009-02-26 21:36:01','h1. Tabele hash - prezentare detaliata\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"Cyber\") ==\r\n\r\n(Categoria _Structuri de date_, Autor _Catalin Francu_, Preluat din cartea _\"Psihologia concursurilor de informatica\"_)\r\n\r\n(toc){width: 20em}*{text-align:center;} *Continut*\r\n* \'Necesitatea tabelelor hash\':tabele-hash-prezentare-detaliata#necesitate\r\n* \'Descrierea structurii de date\':tabele-hash-prezentare-detaliata#descriere\r\n* \'Metoda impartirii cu rest\':tabele-hash-prezentare-detaliata#metoda-impartirii-cu-rest\r\n* \'Metoda inmultirii\':tabele-hash-prezentare-detaliata#metoda-inmultirii\r\n* \'Probleme propuse\':tabele-hash-prezentare-detaliata#probleme-propuse\r\n\r\nh2(#necesitate). Necesitatea tabelelor hash\r\n\r\nIn multe aplicatii lucram cu structuri mari de date in care avem nevoie sa facem cautari, inserari, modificari si stergeri. Aceste structuri pot fi vectori, matrice, liste etc. In cazurile mai fericite ale vectorilor, acestia pot fi sortati, caz in care localizarea unui element se face prin metoda injumatatirii intervalului, adica in timp logaritmic. Chiar daca nu avem voie sa sortam vectorul, tot se pot face anumite optimizari care reduc foarte mult timpul de cautare. De exemplu, probabil ca multi dintre cititori au idee despre ce inseamna indexarea unei baze de date. Daca avem o baza de date cu patru elemente de tip string, si anume\r\n\r\n$B = (\"bac\", \"zugrav\", \"abac\", \"zarva\")$\r\n\r\nputem construi un vector $Ind$ care sa ne indice ordinea in care s-ar cuveni sa fie asezate cuvintele in vectorul sortat. Ordinea alfabetica (din cartea de telefon) a cuvintelor este: \"abac\", \"bac\", \"zarva\", \"zugrav\", deci vectorul $Ind$ este:\r\n\r\n$Ind = (3, 1, 4, 2)$\r\n\r\nsemnificand ca primul cuvant din vectorul sortat ar trebui sa fie al treilea din vectorul $B$, respectiv \"abac\", si asa mai departe. In felul acesta am obtinut un vector sortat, care presupune o indirectare a elementelor. Vectorul sortat este\r\n\r\n$B\' = (B(Ind(1)), B(Ind(2)), B(Ind(3)), B(Ind(4))$.\r\n\r\nAceasta operatie se numeste indexare. Ce-i drept, constructia vectorului $Ind$ nu se poate face intr-un timp mai bun decat $O(N log N)$, dar dupa ce acest lucru se face (o singura data, la inceputul programului), cautarile se pot face foarte repede. Daca pe parcurs se fac adaugari sau stergeri de elemente in/din baza de date, se va pierde catva timp pentru mentinerea indexului, dar in practica timpul acesta este mult mai mic decat timpul care s-ar pierde cu cautarea unor elemente in cazul in care vectorul ar fi neindexat. Nu vom intra in detalii despre indexare, deoarece nu acesta este obiectul articolului de fata.\r\n\r\nIn unele situatii nu se poate face nici indexarea structurii de date. Sa consideram cazul unui program care joaca sah. Numarul de pozitii posibile ale pieselor pe tabla de sah este mult prea mare. Nu poate fi vorba nici macar de retinerea tuturor, cu atat mai putin de indexarea lor. In esenta, modul de functionare al acestui program se reduce la o rutina care primeste o pozitie pe tabla si o variabila care indica daca la mutare este albul sau negrul, rutina intorcand cea mai buna mutare care se poate efectua din acea pozitie. Majoritatea programelor de sah incep sa expandeze respectiva pozitie, examinand tot felul de variante ce pot decurge din ea si alegand-o pe cea mai promitatoare, asa cum fac si jucatorii umani. Pozitiile analizate, fiind mult mai putine decat cele posibile, sunt stocate in memorie sub forma unei liste.\r\n\r\nSa ne inchipuim acum urmatoarea situatie. Este posibil ca, prin expandarea unei configuratii initiale a tablei sa se ajunga la aceeasi configuratie finala pe doua cai diferite. Spre exemplu, daca albul muta intai calul la _f3_, apoi nebunul la _c4_, pozitia rezultata va fi aceeasi ca si cand s-ar fi mutat intai nebunul si apoi calul (considerand bineinteles ca negrul da in ambele situatii aceeasi replica). Daca configuratia finala a fost deja analizata pentru prima varianta, este inutil sa o mai analizam si pentru cea de-a doua, pentru ca rezultatul (concluzia la care se va ajunge) va fi exact acelasi. Dar cum isi poate da programul seama daca pozitia pe care are de gand s-o analizeze a fost analizata deja sau nu?\r\n\r\nCea mai simpla metoda este o scanare a listei de configuratii examinate din memorie. Daca in aceasta lista se afla pozitia curenta de analizat, inseamna ca ea a fost deja analizata si vom renunta la ea. Daca nu, o vom analiza acum. Ideea in mare a algoritmului este:\r\n\r\n== code(c) |\r\nfunctia Analizeaza(Pozitie P)\r\n    cauta P in lista de pozitii deja analizate\r\n    daca P nu exista in lista\r\n        expandeaza P si afla cea mai buna mutare M\r\n        adauga P la lista de pozitii analizate\r\n        intoarce M\r\n    altfel\r\n        intoarce valoarea M atasata pozitiei P gasite in lista\r\nsfarsit\r\n==\r\n\r\nNu vom insista asupra a cum se expandeaza o pozitie si cum se calculeaza efectiv cea mai buna mutare. Noi ne vom interesa de un singur aspect, si anume cautarea unei pozitii in lista. Tehnica cea mai \"naturala\" este o parcurgere a listei de la cap la coada, comparand pe rand pozitia cautata cu fiecare pozitie din lista. Daca lista are memorate $N$ pozitii, atunci in cazul unei cautari cu succes (pozitia este gasita), numarul mediu de comparatii facute este $N/2$, iar numarul cel mai defavorabil ajunge pana la $N$. In cazul unei cautari fara succes (pozitia nu exista in lista), numarul de comparatii este intotdeauna $N$. De altfel, cazul cautarii fara succes este mult mai frecvent pentru problema jocului de sah, unde numarul de pozitii posibile creste exponential cu numarul de mutari. Acelasi numar de comparatii il presupune si stergerea unei pozitii din lista (care presupune intai gasirea ei) si adaugarea (care presupune ca pozitia de adaugat sa nu existe deja in lista).\r\n\r\nPentru imbunatatirea practica a acestui timp sunt folosite _tabelele de dispersie_ sau _tabelele hash_ (engl. _hash_ = a toca, tocatura). Mentionam de la bun inceput ca tabelele hash nu au nicio utilitate din punct de vedere teoretic. Daca suntem rau intentionati, este posibil sa gasim exemple pentru care cautarea intr-o tabela hash sa dureze la fel de mult ca intr-o lista simplu inlantuita, respectiv $O(N)$. Dar in practica timpul cautarii si al adaugarii de elemente intr-o tabela hash coboara uneori pana la $O(1)$, iar in medie scade foarte mult (de mii de ori).\r\n\r\nh2(#descriere). Descrierea structurii de date\r\n\r\nIata despre ce este vorba. Sa presupunem pentru inceput ca in loc de pozitii pe tabla de sah, lista noastra memoreaza numere intre 0 si 999. In acest caz, tabela hash ar fi un simplu vector $H$ cu $1000$ de elemente booleene. Initial, toate elementele lui $H$ au valoarea $False$ (sau $0$). Daca numarul $473$ a fost gasit in lista, nu avem decat sa setam valoarea lui $H(473)$ la $True$ (sau $1$). La o noua aparitie a lui $473$ in lista, vom examina elementul $H(473)$ si, deoarece el este $True$, inseamna ca acest numar a mai fost gasit. Daca dorim stergerea unui element din hash, vom reseta pozitia corespunzatoare din $H$. Practic, avem de-a face cu un exemplu rudimentar de ceea ce se cheama functie de dispersie, adica $h(x) = x$. O proprietate foarte importanta a acestei functii este injectivitatea; este imposibil ca la doua numere distincte sa corespunda aceeasi intrare in tabela. Sa incercam o reprezentare grafica a metodei:\r\n\r\np=. !tabele-hash-prezentare-detaliata?hash1.jpg!\r\n\r\nIata primul set de functii de gestionare a unui hash.\r\n\r\n== code(c) |\r\nconst int M = 1000;\r\ntypedef int DataType;\r\ntypedef DataType Hash[M];\r\nHash H;\r\n\r\nvoid InitHash1(Hash H) {\r\n    for (int i = 0; i < M; H[i++] = 0);\r\n}\r\n\r\ninline int h(DataType K) {\r\n    return K;\r\n}\r\n\r\nint Search1(Hash H, DataType K) {\r\n    // Intoarce -1 daca elementul nu exista in hash\r\n    // sau indicele in hash daca el exista\r\n    return H[h(K)] ? h(K) : -1;\r\n}\r\n\r\nvoid Add1(Hash H, DataType K) {\r\n    H[h(K)] = 1;\r\n}\r\n\r\nvoid Delete1(Hash H, DataType K) {\r\n    H[h(K)] = 0;\r\n}\r\n==\r\n\r\nPrin \"numar de intrari\" in tabela se intelege numarul de elemente ale vectorului $H$; in general, orice tabela hash este un vector. Pentru ca functiile sa fie cat mai generale, am dat tipului de date _int_ un nou nume _DataType_. In principiu, tabelele hash se aplica oricarui tip de date. In realitate, fenomenul este tocmai cel invers: orice tip de date trebuie \"convertit\" printr-o metoda sau alta la tipul de date _int_, iar functia de dispersie primeste ca parametru un intreg. Functiile hash prezentate in viitor nu vor mai lucra decat cu variabile de tip intreg. Vom vorbi mai tarziu despre cum se poate face conversia. Acum sa generalizam exemplul de mai sus.\r\n\r\nIntr-adevar, cazul anterior este mult prea simplu. Sa ne inchipuim de pilda ca in loc de numere mai mici ca $1.000$, avem numere de pana la $2.000.000.000$. In aceasta situatie posibilitatea de a reprezenta tabela ca un vector caracteristic iese din discutie. Numarul de intrari in tabela este de ordinul miilor, cel mult al zecilor de mii, deci cu mult mai mic decat numarul total de chei (numere) posibile. Ce avem de facut? Am putea incerca sa adaugam un numar $K$ intr-o tabela cu $M$ intrari (numerotate de la 0 la $M-1$) pe pozitia $K mod M$, adica $h(K) = K mod M$. Care va fi insa rezultatul? Functia $h$ isi va pierde proprietatea de injectivitate, deoarece mai multor chei le poate corespunde aceeasi intrare in tabela, cum ar fi cazul numerelor $1.234$ si $2.001.234$, ambele dand acelasi rest la impartirea prin $M = 1.000$. Nu putem avea insa speranta de a gasi o functie injectiva, pentru ca atunci numarul de intrari in tabela ar trebui sa fie cel putin egal cu numarul de chei distincte. Vrand-nevrand, trebuie sa rezolvam coliziunile (sau conflictele) care apar, adica situatiile cand mai multe chei distincte sunt repartizate la aceeasi intrare.\r\n\r\nVom reveni ulterior la oportunitatea alegerii functiei modul si a numarului de $1.000$ de intrari in tabela. Deocamdata vom folosi aceste date pentru a explica modul de functionare a tabelei hash pentru functii neinjective. Sa presupunem ca avem doua chei $K1$ si $K2$ care sunt repartizate de functia $h$ la aceeasi intrare $X$, adica $h(K1) = h(K2) = X$. Solutia cea mai comoda este ca $H(X)$ sa nu mai fie un numar, ci o lista liniara simplu inlantuita care sa contina toate cheile gasite pana acum si repartizate la aceeasi intrare $X$. Prin urmare vectorul $H$ va fi un vector de liste:\r\n\r\np=. !tabele-hash-prezentare-detaliata?hash2.jpg!\r\n\r\nSa analizam acum complexitatea noilor functii de cautare, adaugare si stergere. Cautarea nu se va mai face in toata lista, ci numai in lista corespunzatoare din $H$. Altfel spus, o cheie $K$ se va cauta numai in lista $H(h(K))$, deoarece daca cheia $K$ a mai aparut, ea a fost in mod sigur repartizata la intrarea $H(h(K))$. De aceea, cautarea poate ajunge, in cazul cel mai defavorabil cand toate cheile din lista se repartizeaza la aceeasi intrare in hash, la o complexitate $O(N)$. Daca reusim insa sa gasim o functie care sa distribuie cheile cat mai aleator, timpul de intrare se va reduce de $M$ ori. Avantajele sunt indiscutabile pentru $M = 10.000$ de exemplu.\r\n\r\nIntrucat operatiile cu liste liniare sunt in general cunoscute, nu vom insista asupra lor. Prezentam aici numai adaugarea si cautarea, lasandu-va ca tema scrierea functiei de stergere din tabela.\r\n\r\n== code(c) |\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n\r\nconst int M = 1000;\r\ntypedef struct List_ {\r\n    long P;\r\n    struct List_ *Next;\r\n} List;\r\ntypedef List* Hash[M];\r\nHash H;\r\n\r\nvoid InitHash2(Hash H){\r\n    for (int i=0; i<M; H[i++]=NULL);\r\n}\r\n\r\nint h2(int K) {\r\n    return K % M;\r\n}\r\n\r\nint Search2(Hash H, int K) {\r\n    // Intoarce 0 daca elementul nu exista in hash\r\n    // sau 1 daca el exista\r\n    List *L;\r\n    for (L=H[h2(K)]; L && (L->P != K); L = L->Next);\r\n    return L!=NULL;\r\n}\r\n\r\nvoid Add2(Hash H, int K) {\r\n    List *L = (List *) malloc(sizeof(List));\r\n    L->P = K;\r\n    L->Next = H[h2(K)];\r\n    H[h2(K)] = L;\r\n}\r\n==\r\n\r\nAm spus ca functiile de dispersie sunt concepute sa lucreze numai pe date de tip intreg; celelalte tipuri de date trebuie convertite in prealabil la tipuri de date intregi. Iata cateva exemple:\r\n\r\n* Variabilele de tip string pot fi transformate in numere in baza $256$ prin inlocuirea fiecarui caracter cu codul sau _ASCII_. De exemplu, sirul \"abac\" poate fi privit ca un numar de 4 cifre in baza $256$, si anume numarul $(97 98 97 99)$. Conversia lui in baza $10$ se face astfel:\r\n\r\n$X = ((97 * 256 + 98) * 256 + 97) * 256 + 99 = 1 633 837 411$\r\n\r\nPentru stringuri mai lungi, rezulta numere mai mari. Uneori, ele nici nu mai pot fi reprezentate cu tipurile de date ordinare. Totusi, acest dezavantaj nu este suparator, deoarece majoritatea functiilor de dispersie presupun o impartire cu rest, care, indiferent de marimea numarului de la intrare, produce un numar controlabil.\r\n\r\n* Variabilele de tip data se pot converti la intreg prin formula:\r\n\r\n$X = A * 366 + L * 31 + Z$\r\n\r\nunde $A$, $L$ si $Z$ sunt respectiv anul, luna si ziua datei considerate. De fapt, aceasta functie aproximeaza numarul de zile scurse de la inceputul secolului I. Ea nu are pretentii de exactitate (ca dovada, toti anii sunt considerati a fi bisecti si toate lunile a avea 31 de zile), deoarece s-ar consuma timp inutil cu calcule mai sofisticate, fara ca dispersia insasi sa fie imbunatatita cu ceva. Conditia care trebuie neaparat respectata este ca functia de conversie data <tex> \\leftrightarrow </tex> intreg sa fie injectiva, adica sa nu se intample ca la doua date $D1$ si $D2$ sa li se ataseze acelasi intreg $X$; daca acest lucru se intampla, pot aparea erori la cautarea in tabela (de exemplu, se poate raporta gasirea datei $D1$ cand de fapt a fost gasita data $D2$). Pentru a respecta injectivitatea, s-au considerat coeficientii $366$ si $31$ in loc de $365$ si $30$. Daca numarul de zile scurse de la 1 ianuarie anul 1 d.H. ar fi fost calculat cu exactitate, functia de conversie ar fi fost si surjectiva, dar, dupa cum am mai spus, acest fapt nu prezinta interes.\r\n\r\n* Analog, variabilele de tip ora se pot converti la intreg cu formula:\r\n\r\n$X = (H * 60 + M) * 60 + S$\r\n\r\nunde $H$, $M$ si $S$ sunt respectiv ora, minutul si secunda considerate, sau cu formula\r\n\r\n$X = ((H * 60 + M) * 60 + S) * 100$\r\n\r\ndaca se tine cont si de sutimile de secunda. De data aceasta, functia este surjectiva (oricarui numar intreg din intervalul 0 - 8.639.999 ii corespunde in mod unic o ora).\r\n\r\n* In majoritatea cazurilor, datele sunt structuri care contin numere si stringuri. O buna metoda de conversie consta in alipirea tuturor acestor date si in convertirea la baza $256$. Caracterele se convertesc prin simpla inlocuire cu codul _ASCII_ corespunzator, iar numerele prin convertirea in baza $2$ si taierea in \"bucati\" de cate opt biti. Rezulta numere cu multe cifre (prea multe chiar si pentru tipul longint), care sunt supuse unei operatii de impartire cu rest. Functia de conversie trebuie sa fie injectiva. De exemplu, in cazul tablei de sah despre care am amintit mai inainte, ea poate fi transformata intr-un vector cu 64 de cifre in baza 16, cifra 0 semnificand un patrat gol, cifrele 1-6 semnificand piesele albe (pion, cal, nebun, turn, regina, rege), iar cifrele 7-12 semnificand piesele negre. Prin trecerea acestui vector in baza 256, rezulta un numar cu 32 de cifre. La acesta se mai pot adauga alte cifre, respectiv partea la mutare (0 pentru alb, 1 pentru negru), posibilitatea de a efectua rocada mica/mare de catre alb/negru, numarul de mutari scurse de la inceputul partidei si asa mai departe.\r\n\r\nVom termina prin a prezenta doua functii de dispersie foarte des folosite.\r\n\r\nh2(#metoda-impartirii-cu-rest). Metoda impartirii cu rest\r\n\r\nDespre aceasta metoda am mai vorbit. Functia hash este: $h(x) = x mod M$ unde $M$ este numarul de intrari in tabela. Problema care se pune este sa-l alegem pe $M$ cat mai bine, astfel incat numarul de coliziuni pentru oricare din intrari sa fie cat mai mic. De asemenea, trebuie ca $M$ sa fie cat mai mare, pentru ca media numarului de chei repartizate la aceeasi intrare sa fie cat mai mica. Totusi, experienta arata ca nu orice valoare a lui $M$ este buna.\r\n\r\nDe exemplu, la prima vedere s-ar putea spune ca o buna valoare pentru $M$ este o putere a lui 2, cum ar fi 1024, pentru ca operatia de impartire cu rest se poate face foarte usor in aceasta situatie. Totusi, functia $h(x) = x mod 1024$ are un mare defect: ea nu tine cont decat de ultimii 10 biti ai numarului $x$. Daca datele de intrare sunt numere in mare majoritate pare, ele vor fi repartizate in aceeasi proportie la intrarile cu numar de ordine par, pentru ca functia $h$ pastreaza paritatea. Din aceleasi motive, alegerea unei valori ca 1000 sau 2000 nu este prea inspirata, deoarece tine cont numai de ultimele 3-4 cifre ale reprezentarii zecimale. Multe valori pot da acelasi rest la impartirea prin 1000. De exemplu, daca datele de intrare sunt anii de nastere ai unor persoane dintr-o agenda telefonica, iar functia $h(x)=x mod 1000$, atunci majoritatea cheilor se vor ingramadi (termenul este sugestiv) intre intrarile 920 si 990, restul ramanand nefolosite.\r\n\r\nPractic, trebuie ca $M$ sa nu fie un numar rotund in nicio baza aritmetica, sau cel putin nu in bazele 2 si 10. O buna alegere pentru $M$ sunt numerele prime care sa nu fie apropiate de nicio putere a lui 2. De exemplu, in locul unei tabele cu $M=10000$ de intrari, care s-ar comporta dezastruos, putem folosi una cu 9973 de intrari. Chiar si aceasta alegere poate fi imbunatatita; intre puterile lui 2 vecine, respectiv 8192 si 16384, se poate alege un numar prim din zona 11000-12000. Risipa de memorie de circa 1000-2000 de intrari in tabela va fi pe deplin compensata de imbunatatirea cautarii.\r\n\r\nh2(#metoda-inmultirii). Metoda inmultirii\r\n\r\nPentru aceasta metoda functia hash este $h(x) = [M * {x*A}]$. Aici $A$ este un numar pozitiv subunitar, $0 < A < 1$, iar prin ${x*A}$ se intelege partea fractionara a lui $x*A$, adica $x*A - [x*A]$. De exemplu, daca alegem $M = 1234$ si $A = 0.3$, iar $x = 1997$, atunci avem $h(x) = [1234 * {599.1}] = [1234 * 0.1] = 123$. Se observa ca functia $h$ produce numere intre $0$ si $M-1$. Intr-adevar $0 &le; {x*A} < 1$ <tex>\\Rightarrow</tex> $0 &le; M * {x*A} < M$.\r\n\r\nIn acest caz, valoarea lui $M$ nu mai are o mare importanta. O putem deci alege cat de mare ne convine, eventual o putere a lui 2. In practica, s-a observat ca dispersia este mai buna pentru unele valori ale lui A si mai proasta pentru altele. Donald Knuth propune valoarea <tex> A = \\frac{\\sqrt{5}-1}{2} \\approx 0.618034 </tex>.\r\n\r\nCa o ultima precizare necesara la acest capitol, mentionam ca functia de cautare e bine sa nu intoarca pur si simplu 0 sau 1, dupa cum cheia cautata a mai aparut sau nu inainte intre datele de intrare. E recomandabil ca functia sa intoarca un pointer la zona de memorie in care se afla prima aparitie a cheii cautate. Vom da acum un exemplu in care aceasta valoare returnata este utila. Daca, in cazul prezentat mai sus al unui program de sah, se ajunge la o anumita pozitie P dupa ce albul a pierdut dreptul de a face rocada, aceasta pozitie va fi retinuta in hash. Retinerea nu se va face nicidecum efectiv (toata tabla), pentru ca s-ar ocupa foarte multa memorie. Se va memora in loc numai un pointer la pozitia respectiva din lista de pozitii analizate. Pe langa economia de memorie in cazul cheilor de mari dimensiuni, mai exista si alt avantaj. Sa ne inchipuim ca, analizand in continuare tabla, programul va ajunge la aceeasi pozitie P, dar in care albul are inca dreptul de a face rocada. E limpede ca aceasta varianta este mai promitatoare decat precedenta, deoarece albul are o libertate mai mare de miscare. Se impune deci fie stergerea vechii pozitii P din lista si adaugarea noii pozitii, fie modificarea celei vechi prin setarea unei variabile suplimentare care indica dreptul albului de a face rocada. Aceasta modificare este usor de facut, intrucat cautarea in hash va returna chiar un pointer la pozitia care trebuie modificata. Bineinteles, in cazul in care pozitia cautata nu se afla in hash, functia de cautare trebuie sa intoarca NULL.\r\n\r\nIn incheiere, prezentam un exemplu de functie de dispersie pentru cazul tablei de sah.\r\n\r\n== code(c) |\r\nconst int M = 9973;  // Numarul de \"intrari\".\r\ntypedef struct {\r\n    char b_T[8][8];  // Tabla de joc, cu 0 <= T[i][j] <= 12.\r\n\r\n    char b_CastleW, b_CastleB;  // Ultimii doi biti ai lui b_CastleW\r\n                                // indica daca albul are dreptul de a\r\n                                // efectua rocada mare, respectiv pe cea\r\n                                // mica. Analog pentru b_CastleB.\r\n\r\n    char b_Side;  // 0 sau 1, dupa cum la mutare este albul.\r\n                  // sau negrul.\r\n\r\n    char b_EP;  // 0..8, indicand coloana (0..7) pe care\r\n                // partea la mutare poate efectua o\r\n                // captura \"en passant\". 8 indica ca nu\r\n                // exista aceasta posibilitate.\r\n\r\n    int b_NMoves;  // Numarul de mutari efectuate.\r\n} Board;\r\nBoard B;\r\n\r\nint h3(Board *B) {\r\n    int i, j;\r\n    // Valoarea initiala a lui S este un numar pe 17 biti care\r\n    // inglobeaza toate variabilele suplimentare pe langa T.\r\n    // S se va lua apoi modulo M.\r\n    long S = (B->b_NMoves           // 8 biti\r\n            +(B->b_CastleW << 8)    // 2 biti\r\n            +(B->b_CastleB << 10)   // 2 biti\r\n            +(B->b_Side << 12)      // 1 bit\r\n            +(B->b_EP << 13)) % M;  // 4 biti\r\n\r\n    for (i = 0; i <= 7; i++)\r\n        for (j=0; j <= 7; j++) {\r\n            S = (16 * S + B->b_T[i][j]) % M;\r\n        }\r\n\r\n    return S;\r\n}\r\n==\r\n\r\nh2(#probleme-propuse). Probleme propuse\r\n\r\nIata si o scurta lista de probleme ce se rezolva eficient folosind tabelele hash:\r\n\r\n* \'SGU 174 - Walls\':http://acm.sgu.ru/problem.php?contest=0&problem=174\r\n* \'UVA 10748 - Knights Roaming\':http://icpcres.ecs.baylor.edu/onlinejudge/external/107/10748.html\r\n* \"UVA 10815 - Andy\'s First Dictionary\":http://icpcres.ecs.baylor.edu/onlinejudge/external/108/10815.html\r\n* \'UVA 10887 - Concatenation of Languages\':http://icpcres.ecs.baylor.edu/onlinejudge/external/108/10887.html\r\n* \'UVA 704 - Colour Hash\':http://icpcres.ecs.baylor.edu/onlinejudge/external/7/704.html\r\n',2044,'public',NULL,NULL),('tabele-hash-prezentare-detaliata','Tabele hash - prezentare detaliata','2008-01-30 15:12:38','2009-02-26 23:45:39','h1. Tabele hash - prezentare detaliata\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"Cyber\") ==\r\n\r\n(Categoria _Structuri de date_, Autor _Catalin Francu_, Preluat din cartea _\"Psihologia concursurilor de informatica\"_)\r\n\r\n(toc){width: 20em}*{text-align:center;} *Continut*\r\n* \'Necesitatea tabelelor hash\':tabele-hash-prezentare-detaliata#necesitate\r\n* \'Descrierea structurii de date\':tabele-hash-prezentare-detaliata#descriere\r\n* \'Metoda impartirii cu rest\':tabele-hash-prezentare-detaliata#metoda-impartirii-cu-rest\r\n* \'Metoda inmultirii\':tabele-hash-prezentare-detaliata#metoda-inmultirii\r\n* \'Probleme propuse\':tabele-hash-prezentare-detaliata#probleme-propuse\r\n\r\nh2(#necesitate). Necesitatea tabelelor hash\r\n\r\nIn multe aplicatii lucram cu structuri mari de date in care avem nevoie sa facem cautari, inserari, modificari si stergeri. Aceste structuri pot fi vectori, matrice, liste etc. In cazurile mai fericite ale vectorilor, acestia pot fi sortati, caz in care localizarea unui element se face prin metoda injumatatirii intervalului, adica in timp logaritmic. Chiar daca nu avem voie sa sortam vectorul, tot se pot face anumite optimizari care reduc foarte mult timpul de cautare. De exemplu, probabil ca multi dintre cititori au idee despre ce inseamna indexarea unei baze de date. Daca avem o baza de date cu patru elemente de tip string, si anume\r\n\r\n$B = (\"bac\", \"zugrav\", \"abac\", \"zarva\")$\r\n\r\nputem construi un vector $Ind$ care sa ne indice ordinea in care s-ar cuveni sa fie asezate cuvintele in vectorul sortat. Ordinea alfabetica (din cartea de telefon) a cuvintelor este: \"abac\", \"bac\", \"zarva\", \"zugrav\", deci vectorul $Ind$ este:\r\n\r\n$Ind = (3, 1, 4, 2)$\r\n\r\nsemnificand ca primul cuvant din vectorul sortat ar trebui sa fie al treilea din vectorul $B$, respectiv \"abac\", si asa mai departe. In felul acesta am obtinut un vector sortat, care presupune o indirectare a elementelor. Vectorul sortat este\r\n\r\n$B\' = (B(Ind(1)), B(Ind(2)), B(Ind(3)), B(Ind(4))$.\r\n\r\nAceasta operatie se numeste indexare. Ce-i drept, constructia vectorului $Ind$ nu se poate face intr-un timp mai bun decat $O(N log N)$, dar dupa ce acest lucru se face (o singura data, la inceputul programului), cautarile se pot face foarte repede. Daca pe parcurs se fac adaugari sau stergeri de elemente in/din baza de date, se va pierde catva timp pentru mentinerea indexului, dar in practica timpul acesta este mult mai mic decat timpul care s-ar pierde cu cautarea unor elemente in cazul in care vectorul ar fi neindexat. Nu vom intra in detalii despre indexare, deoarece nu acesta este obiectul articolului de fata.\r\n\r\nIn unele situatii nu se poate face nici indexarea structurii de date. Sa consideram cazul unui program care joaca sah. Numarul de pozitii posibile ale pieselor pe tabla de sah este mult prea mare. Nu poate fi vorba nici macar de retinerea tuturor, cu atat mai putin de indexarea lor. In esenta, modul de functionare al acestui program se reduce la o rutina care primeste o pozitie pe tabla si o variabila care indica daca la mutare este albul sau negrul, rutina intorcand cea mai buna mutare care se poate efectua din acea pozitie. Majoritatea programelor de sah incep sa expandeze respectiva pozitie, examinand tot felul de variante ce pot decurge din ea si alegand-o pe cea mai promitatoare, asa cum fac si jucatorii umani. Pozitiile analizate, fiind mult mai putine decat cele posibile, sunt stocate in memorie sub forma unei liste.\r\n\r\nSa ne inchipuim acum urmatoarea situatie. Este posibil ca, prin expandarea unei configuratii initiale a tablei sa se ajunga la aceeasi configuratie finala pe doua cai diferite. Spre exemplu, daca albul muta intai calul la _f3_, apoi nebunul la _c4_, pozitia rezultata va fi aceeasi ca si cand s-ar fi mutat intai nebunul si apoi calul (considerand bineinteles ca negrul da in ambele situatii aceeasi replica). Daca configuratia finala a fost deja analizata pentru prima varianta, este inutil sa o mai analizam si pentru cea de-a doua, pentru ca rezultatul (concluzia la care se va ajunge) va fi exact acelasi. Dar cum isi poate da programul seama daca pozitia pe care are de gand s-o analizeze a fost analizata deja sau nu?\r\n\r\nCea mai simpla metoda este o scanare a listei de configuratii examinate din memorie. Daca in aceasta lista se afla pozitia curenta de analizat, inseamna ca ea a fost deja analizata si vom renunta la ea. Daca nu, o vom analiza acum. Ideea in mare a algoritmului este:\r\n\r\n== code(c) |\r\nfunctia Analizeaza(Pozitie P)\r\n    cauta P in lista de pozitii deja analizate\r\n    daca P nu exista in lista\r\n        expandeaza P si afla cea mai buna mutare M\r\n        adauga P la lista de pozitii analizate\r\n        intoarce M\r\n    altfel\r\n        intoarce valoarea M atasata pozitiei P gasite in lista\r\nsfarsit\r\n==\r\n\r\nNu vom insista asupra a cum se expandeaza o pozitie si cum se calculeaza efectiv cea mai buna mutare. Noi ne vom interesa de un singur aspect, si anume cautarea unei pozitii in lista. Tehnica cea mai \"naturala\" este o parcurgere a listei de la cap la coada, comparand pe rand pozitia cautata cu fiecare pozitie din lista. Daca lista are memorate $N$ pozitii, atunci in cazul unei cautari cu succes (pozitia este gasita), numarul mediu de comparatii facute este $N/2$, iar numarul cel mai defavorabil ajunge pana la $N$. In cazul unei cautari fara succes (pozitia nu exista in lista), numarul de comparatii este intotdeauna $N$. De altfel, cazul cautarii fara succes este mult mai frecvent pentru problema jocului de sah, unde numarul de pozitii posibile creste exponential cu numarul de mutari. Acelasi numar de comparatii il presupune si stergerea unei pozitii din lista (care presupune intai gasirea ei) si adaugarea (care presupune ca pozitia de adaugat sa nu existe deja in lista).\r\n\r\nPentru imbunatatirea practica a acestui timp sunt folosite _tabelele de dispersie_ sau _tabelele hash_ (engl. _hash_ = a toca, tocatura). Mentionam de la bun inceput ca tabelele hash nu au nicio utilitate din punct de vedere teoretic. Daca suntem rau intentionati, este posibil sa gasim exemple pentru care cautarea intr-o tabela hash sa dureze la fel de mult ca intr-o lista simplu inlantuita, respectiv $O(N)$. Dar in practica timpul cautarii si al adaugarii de elemente intr-o tabela hash coboara uneori pana la $O(1)$, iar in medie scade foarte mult (de mii de ori).\r\n\r\nh2(#descriere). Descrierea structurii de date\r\n\r\nIata despre ce este vorba. Sa presupunem pentru inceput ca in loc de pozitii pe tabla de sah, lista noastra memoreaza numere intre 0 si 999. In acest caz, tabela hash ar fi un simplu vector $H$ cu $1000$ de elemente booleene. Initial, toate elementele lui $H$ au valoarea $False$ (sau $0$). Daca numarul $473$ a fost gasit in lista, nu avem decat sa setam valoarea lui $H(473)$ la $True$ (sau $1$). La o noua aparitie a lui $473$ in lista, vom examina elementul $H(473)$ si, deoarece el este $True$, inseamna ca acest numar a mai fost gasit. Daca dorim stergerea unui element din hash, vom reseta pozitia corespunzatoare din $H$. Practic, avem de-a face cu un exemplu rudimentar de ceea ce se cheama functie de dispersie, adica $h(x) = x$. O proprietate foarte importanta a acestei functii este injectivitatea; este imposibil ca la doua numere distincte sa corespunda aceeasi intrare in tabela. Sa incercam o reprezentare grafica a metodei:\r\n\r\np=. !tabele-hash-prezentare-detaliata?hash1.jpg!\r\n\r\nIata primul set de functii de gestionare a unui hash.\r\n\r\n== code(c) |\r\nconst int M = 1000;\r\ntypedef int DataType;\r\ntypedef DataType Hash[M];\r\nHash H;\r\n\r\nvoid InitHash1(Hash H) {\r\n    for (int i = 0; i < M; H[i++] = 0);\r\n}\r\n\r\ninline int h(DataType K) {\r\n    return K;\r\n}\r\n\r\nint Search1(Hash H, DataType K) {\r\n    // Intoarce -1 daca elementul nu exista in hash\r\n    // sau indicele in hash daca el exista\r\n    return H[h(K)] ? h(K) : -1;\r\n}\r\n\r\nvoid Add1(Hash H, DataType K) {\r\n    H[h(K)] = 1;\r\n}\r\n\r\nvoid Delete1(Hash H, DataType K) {\r\n    H[h(K)] = 0;\r\n}\r\n==\r\n\r\nPrin \"numar de intrari\" in tabela se intelege numarul de elemente ale vectorului $H$; in general, orice tabela hash este un vector. Pentru ca functiile sa fie cat mai generale, am dat tipului de date _int_ un nou nume _DataType_. In principiu, tabelele hash se aplica oricarui tip de date. In realitate, fenomenul este tocmai cel invers: orice tip de date trebuie \"convertit\" printr-o metoda sau alta la tipul de date _int_, iar functia de dispersie primeste ca parametru un intreg. Functiile hash prezentate in viitor nu vor mai lucra decat cu variabile de tip intreg. Vom vorbi mai tarziu despre cum se poate face conversia. Acum sa generalizam exemplul de mai sus.\r\n\r\nIntr-adevar, cazul anterior este mult prea simplu. Sa ne inchipuim de pilda ca in loc de numere mai mici ca $1.000$, avem numere de pana la $2.000.000.000$. In aceasta situatie posibilitatea de a reprezenta tabela ca un vector caracteristic iese din discutie. Numarul de intrari in tabela este de ordinul miilor, cel mult al zecilor de mii, deci cu mult mai mic decat numarul total de chei (numere) posibile. Ce avem de facut? Am putea incerca sa adaugam un numar $K$ intr-o tabela cu $M$ intrari (numerotate de la 0 la $M-1$) pe pozitia $K mod M$, adica $h(K) = K mod M$. Care va fi insa rezultatul? Functia $h$ isi va pierde proprietatea de injectivitate, deoarece mai multor chei le poate corespunde aceeasi intrare in tabela, cum ar fi cazul numerelor $1.234$ si $2.001.234$, ambele dand acelasi rest la impartirea prin $M = 1.000$. Nu putem avea insa speranta de a gasi o functie injectiva, pentru ca atunci numarul de intrari in tabela ar trebui sa fie cel putin egal cu numarul de chei distincte. Vrand-nevrand, trebuie sa rezolvam coliziunile (sau conflictele) care apar, adica situatiile cand mai multe chei distincte sunt repartizate la aceeasi intrare.\r\n\r\nVom reveni ulterior la oportunitatea alegerii functiei modul si a numarului de $1.000$ de intrari in tabela. Deocamdata vom folosi aceste date pentru a explica modul de functionare a tabelei hash pentru functii neinjective. Sa presupunem ca avem doua chei $K1$ si $K2$ care sunt repartizate de functia $h$ la aceeasi intrare $X$, adica $h(K1) = h(K2) = X$. Solutia cea mai comoda este ca $H(X)$ sa nu mai fie un numar, ci o lista liniara simplu inlantuita care sa contina toate cheile gasite pana acum si repartizate la aceeasi intrare $X$. Prin urmare vectorul $H$ va fi un vector de liste:\r\n\r\np=. !tabele-hash-prezentare-detaliata?hash2.jpg!\r\n\r\nSa analizam acum complexitatea noilor functii de cautare, adaugare si stergere. Cautarea nu se va mai face in toata lista, ci numai in lista corespunzatoare din $H$. Altfel spus, o cheie $K$ se va cauta numai in lista $H(h(K))$, deoarece daca cheia $K$ a mai aparut, ea a fost in mod sigur repartizata la intrarea $H(h(K))$. De aceea, cautarea poate ajunge, in cazul cel mai defavorabil cand toate cheile din lista se repartizeaza la aceeasi intrare in hash, la o complexitate $O(N)$. Daca reusim insa sa gasim o functie care sa distribuie cheile cat mai aleator, timpul de intrare se va reduce de $M$ ori. Avantajele sunt indiscutabile pentru $M = 10.000$ de exemplu.\r\n\r\nIntrucat operatiile cu liste liniare sunt in general cunoscute, nu vom insista asupra lor. Prezentam aici numai adaugarea si cautarea, lasandu-va ca tema scrierea functiei de stergere din tabela.\r\n\r\n== code(c) |\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n\r\nconst int M = 1000;\r\ntypedef struct List_ {\r\n    long P;\r\n    struct List_ *Next;\r\n} List;\r\ntypedef List* Hash[M];\r\nHash H;\r\n\r\nvoid InitHash2(Hash H){\r\n    for (int i = 0; i < M; H[i++] = NULL);\r\n}\r\n\r\nint h2(int K) {\r\n    return K % M;\r\n}\r\n\r\nint Search2(Hash H, int K) {\r\n    // Intoarce 0 daca elementul nu exista in hash\r\n    // sau 1 daca el exista\r\n    List *L;\r\n    for (L = H[h2(K)]; L && (L->P != K); L = L->Next);\r\n    return L != NULL;\r\n}\r\n\r\nvoid Add2(Hash H, int K) {\r\n    List *L = (List *) malloc(sizeof(List));\r\n    L->P = K;\r\n    L->Next = H[h2(K)];\r\n    H[h2(K)] = L;\r\n}\r\n==\r\n\r\nAm spus ca functiile de dispersie sunt concepute sa lucreze numai pe date de tip intreg; celelalte tipuri de date trebuie convertite in prealabil la tipuri de date intregi. Iata cateva exemple:\r\n\r\n* Variabilele de tip string pot fi transformate in numere in baza $256$ prin inlocuirea fiecarui caracter cu codul sau _ASCII_. De exemplu, sirul \"abac\" poate fi privit ca un numar de 4 cifre in baza $256$, si anume numarul $(97 98 97 99)$. Conversia lui in baza $10$ se face astfel:\r\n\r\n$X = ((97 * 256 + 98) * 256 + 97) * 256 + 99 = 1.633.837.411$\r\n\r\nPentru stringuri mai lungi, rezulta numere mai mari. Uneori, ele nici nu mai pot fi reprezentate cu tipurile de date ordinare. Totusi, acest dezavantaj nu este suparator, deoarece majoritatea functiilor de dispersie presupun o impartire cu rest, care, indiferent de marimea numarului de la intrare, produce un numar controlabil.\r\n\r\n* Variabilele de tip data se pot converti la intreg prin formula:\r\n\r\n$X = A * 366 + L * 31 + Z$\r\n\r\nunde $A$, $L$ si $Z$ sunt respectiv anul, luna si ziua datei considerate. De fapt, aceasta functie aproximeaza numarul de zile scurse de la inceputul secolului I. Ea nu are pretentii de exactitate (ca dovada, toti anii sunt considerati a fi bisecti si toate lunile a avea 31 de zile), deoarece s-ar consuma timp inutil cu calcule mai sofisticate, fara ca dispersia insasi sa fie imbunatatita cu ceva. Conditia care trebuie neaparat respectata este ca functia de conversie data <tex> \\leftrightarrow </tex> intreg sa fie injectiva, adica sa nu se intample ca la doua date $D1$ si $D2$ sa li se ataseze acelasi intreg $X$; daca acest lucru se intampla, pot aparea erori la cautarea in tabela (de exemplu, se poate raporta gasirea datei $D1$ cand de fapt a fost gasita data $D2$). Pentru a respecta injectivitatea, s-au considerat coeficientii $366$ si $31$ in loc de $365$ si $30$. Daca numarul de zile scurse de la 1 ianuarie anul 1 d.H. ar fi fost calculat cu exactitate, functia de conversie ar fi fost si surjectiva, dar, dupa cum am mai spus, acest fapt nu prezinta interes.\r\n\r\n* Analog, variabilele de tip ora se pot converti la intreg cu formula:\r\n\r\n$X = (H * 60 + M) * 60 + S$\r\n\r\nunde $H$, $M$ si $S$ sunt respectiv ora, minutul si secunda considerate, sau cu formula\r\n\r\n$X = ((H * 60 + M) * 60 + S) * 100$\r\n\r\ndaca se tine cont si de sutimile de secunda. De data aceasta, functia este surjectiva (oricarui numar intreg din intervalul $0 - 8.639.999$ ii corespunde in mod unic o ora).\r\n\r\n* In majoritatea cazurilor, datele sunt structuri care contin numere si stringuri. O buna metoda de conversie consta in alipirea tuturor acestor date si in convertirea la baza $256$. Caracterele se convertesc prin simpla inlocuire cu codul _ASCII_ corespunzator, iar numerele prin convertirea in baza $2$ si taierea in \"bucati\" de cate opt biti. Rezulta numere cu multe cifre (prea multe chiar si pentru tipul $long long$), care sunt supuse unei operatii de impartire cu rest. Functia de conversie trebuie sa fie injectiva. De exemplu, in cazul tablei de sah despre care am amintit mai inainte, ea poate fi transformata intr-un vector cu $64$ de cifre in baza $16$, cifra $0$ semnificand un patrat gol, cifrele $1-6$ semnificand piesele albe (pion, cal, nebun, turn, regina, rege), iar cifrele $7-12$ semnificand piesele negre. Prin trecerea acestui vector in baza $256$, rezulta un numar cu $32$ de cifre. La acesta se mai pot adauga alte cifre, respectiv partea la mutare ($0$ pentru alb, $1$ pentru negru), posibilitatea de a efectua rocada mica/mare de catre alb/negru, numarul de mutari scurse de la inceputul partidei si asa mai departe.\r\n\r\nVom termina prin a prezenta doua functii de dispersie foarte des folosite.\r\n\r\nh2(#metoda-impartirii-cu-rest). Metoda impartirii cu rest\r\n\r\nDespre aceasta metoda am mai vorbit. Functia hash este: $h(x) = x mod M$ unde $M$ este numarul de intrari in tabela. Problema care se pune este sa-l alegem pe $M$ cat mai bine, astfel incat numarul de coliziuni pentru oricare din intrari sa fie cat mai mic. De asemenea, trebuie ca $M$ sa fie cat mai mare, pentru ca media numarului de chei repartizate la aceeasi intrare sa fie cat mai mica. Totusi, experienta arata ca nu orice valoare a lui $M$ este buna.\r\n\r\nDe exemplu, la prima vedere s-ar putea spune ca o buna valoare pentru $M$ este o putere a lui $2$, cum ar fi $1024$, pentru ca operatia de impartire cu rest se poate face foarte usor in aceasta situatie. Totusi, functia $h(x) = x mod 1024$ are un mare defect: ea nu tine cont decat de ultimii $10$ biti ai numarului $x$. Daca datele de intrare sunt numere in mare majoritate pare, ele vor fi repartizate in aceeasi proportie la intrarile cu numar de ordine par, pentru ca functia $h$ pastreaza paritatea. Din aceleasi motive, alegerea unei valori ca $1000$ sau $2000$ nu este prea inspirata, deoarece tine cont numai de ultimele $3-4$ cifre ale reprezentarii zecimale. Multe valori pot da acelasi rest la impartirea prin $1000$. De exemplu, daca datele de intrare sunt anii de nastere ai unor persoane dintr-o agenda telefonica, iar functia $h(x) = x mod 1000$, atunci majoritatea cheilor se vor ingramadi (termenul este sugestiv) intre intrarile $920$ si $990$, restul ramanand nefolosite.\r\n\r\nPractic, trebuie ca $M$ sa nu fie un numar rotund in nicio baza aritmetica, sau cel putin nu in bazele $2$ si $10$. O buna alegere pentru $M$ sunt numerele prime care sa nu fie apropiate de nicio putere a lui $2$. De exemplu, in locul unei tabele cu $M = 10.000$ de intrari, care s-ar comporta dezastruos, putem folosi una cu $9973$ de intrari. Chiar si aceasta alegere poate fi imbunatatita; intre puterile lui 2 vecine, respectiv $8192$ si $16384$, se poate alege un numar prim din zona $11.000 - 12.000$. Risipa de memorie de circa $1.000 - 2.000$ de intrari in tabela va fi pe deplin compensata de imbunatatirea cautarii.\r\n\r\nh2(#metoda-inmultirii). Metoda inmultirii\r\n\r\nPentru aceasta metoda functia hash este $h(x) = [M * {x*A}]$. Aici $A$ este un numar pozitiv subunitar, $0 < A < 1$, iar prin ${x*A}$ se intelege partea fractionara a lui $x*A$, adica $x*A - [x*A]$. De exemplu, daca alegem $M = 1234$ si $A = 0.3$, iar $x = 1997$, atunci avem $h(x) = [1234 * {599.1}] = [1234 * 0.1] = 123$. Se observa ca functia $h$ produce numere intre $0$ si $M-1$. Intr-adevar $0 &le; {x*A} < 1$ <tex>\\Rightarrow</tex> $0 &le; M * {x*A} < M$.\r\n\r\nIn acest caz, valoarea lui $M$ nu mai are o mare importanta. O putem deci alege cat de mare ne convine, eventual o putere a lui 2. In practica, s-a observat ca dispersia este mai buna pentru unele valori ale lui A si mai proasta pentru altele. Donald Knuth propune valoarea <tex> A = \\frac{\\sqrt{5}-1}{2} \\approx 0.618034 </tex>.\r\n\r\nCa o ultima precizare necesara la acest capitol, mentionam ca functia de cautare e bine sa nu intoarca pur si simplu 0 sau 1, dupa cum cheia cautata a mai aparut sau nu inainte intre datele de intrare. E recomandabil ca functia sa intoarca un pointer la zona de memorie in care se afla prima aparitie a cheii cautate. Vom da acum un exemplu in care aceasta valoare returnata este utila. Daca, in cazul prezentat mai sus al unui program de sah, se ajunge la o anumita pozitie P dupa ce albul a pierdut dreptul de a face rocada, aceasta pozitie va fi retinuta in hash. Retinerea nu se va face nicidecum efectiv (toata tabla), pentru ca s-ar ocupa foarte multa memorie. Se va memora in loc numai un pointer la pozitia respectiva din lista de pozitii analizate. Pe langa economia de memorie in cazul cheilor de mari dimensiuni, mai exista si alt avantaj. Sa ne inchipuim ca, analizand in continuare tabla, programul va ajunge la aceeasi pozitie P, dar in care albul are inca dreptul de a face rocada. E limpede ca aceasta varianta este mai promitatoare decat precedenta, deoarece albul are o libertate mai mare de miscare. Se impune deci fie stergerea vechii pozitii P din lista si adaugarea noii pozitii, fie modificarea celei vechi prin setarea unei variabile suplimentare care indica dreptul albului de a face rocada. Aceasta modificare este usor de facut, intrucat cautarea in hash va returna chiar un pointer la pozitia care trebuie modificata. Bineinteles, in cazul in care pozitia cautata nu se afla in hash, functia de cautare trebuie sa intoarca NULL.\r\n\r\nIn incheiere, prezentam un exemplu de functie de dispersie pentru cazul tablei de sah.\r\n\r\n== code(c) |\r\nconst int M = 9973;  // Numarul de \"intrari\".\r\ntypedef struct {\r\n    char b_T[8][8];  // Tabla de joc, cu 0 <= T[i][j] <= 12.\r\n\r\n    char b_CastleW, b_CastleB;  // Ultimii doi biti ai lui b_CastleW\r\n                                // indica daca albul are dreptul de a\r\n                                // efectua rocada mare, respectiv pe cea\r\n                                // mica. Analog pentru b_CastleB.\r\n\r\n    char b_Side;  // 0 sau 1, dupa cum la mutare este albul.\r\n                  // sau negrul.\r\n\r\n    char b_EP;  // 0..8, indicand coloana (0..7) pe care\r\n                // partea la mutare poate efectua o\r\n                // captura \"en passant\". 8 indica ca nu\r\n                // exista aceasta posibilitate.\r\n\r\n    int b_NMoves;  // Numarul de mutari efectuate.\r\n} Board;\r\nBoard B;\r\n\r\nint h3(Board *B) {\r\n    int i, j;\r\n    // Valoarea initiala a lui S este un numar pe 17 biti care\r\n    // inglobeaza toate variabilele suplimentare pe langa T.\r\n    // S se va lua apoi modulo M.\r\n    long S = (B->b_NMoves           // 8 biti\r\n            +(B->b_CastleW << 8)    // 2 biti\r\n            +(B->b_CastleB << 10)   // 2 biti\r\n            +(B->b_Side << 12)      // 1 bit\r\n            +(B->b_EP << 13)) % M;  // 4 biti\r\n\r\n    for (i = 0; i <= 7; i++)\r\n        for (j=0; j <= 7; j++) {\r\n            S = (16 * S + B->b_T[i][j]) % M;\r\n        }\r\n\r\n    return S;\r\n}\r\n==\r\n\r\nh2(#probleme-propuse). Probleme propuse\r\n\r\nIata si o scurta lista de probleme ce se rezolva eficient folosind tabelele hash:\r\n\r\n* \'SGU 174 - Walls\':http://acm.sgu.ru/problem.php?contest=0&problem=174\r\n* \'UVA 10748 - Knights Roaming\':http://icpcres.ecs.baylor.edu/onlinejudge/external/107/10748.html\r\n* \"UVA 10815 - Andy\'s First Dictionary\":http://icpcres.ecs.baylor.edu/onlinejudge/external/108/10815.html\r\n* \'UVA 10887 - Concatenation of Languages\':http://icpcres.ecs.baylor.edu/onlinejudge/external/108/10887.html\r\n* \'UVA 704 - Colour Hash\':http://icpcres.ecs.baylor.edu/onlinejudge/external/7/704.html\r\n',2044,'public',NULL,NULL),('tabele-hash-prezentare-detaliata','Tabele hash - prezentare detaliata','2008-01-30 15:12:38','2009-02-26 23:53:42','h1. Tabele hash - prezentare detaliata\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"Cyber\") ==\r\n\r\n(Categoria _Structuri de date_, Autor _Catalin Francu_, Preluat din cartea _\"Psihologia concursurilor de informatica\"_)\r\n\r\n(toc){width: 20em}*{text-align:center;} *Continut*\r\n* \'Necesitatea tabelelor hash\':tabele-hash-prezentare-detaliata#necesitate\r\n* \'Descrierea structurii de date\':tabele-hash-prezentare-detaliata#descriere\r\n* \'Metoda impartirii cu rest\':tabele-hash-prezentare-detaliata#metoda-impartirii-cu-rest\r\n* \'Metoda inmultirii\':tabele-hash-prezentare-detaliata#metoda-inmultirii\r\n* \'Probleme propuse\':tabele-hash-prezentare-detaliata#probleme-propuse\r\n\r\nh2(#necesitate). Necesitatea tabelelor hash\r\n\r\nIn multe aplicatii lucram cu structuri mari de date in care avem nevoie sa facem cautari, inserari, modificari si stergeri. Aceste structuri pot fi vectori, matrice, liste etc. In cazurile mai fericite ale vectorilor, acestia pot fi sortati, caz in care localizarea unui element se face prin metoda injumatatirii intervalului, adica in timp logaritmic. Chiar daca nu avem voie sa sortam vectorul, tot se pot face anumite optimizari care reduc foarte mult timpul de cautare. De exemplu, probabil ca multi dintre cititori au idee despre ce inseamna indexarea unei baze de date. Daca avem o baza de date cu patru elemente de tip string, si anume\r\n\r\n$B = (\"bac\", \"zugrav\", \"abac\", \"zarva\")$\r\n\r\nputem construi un vector $Ind$ care sa ne indice ordinea in care s-ar cuveni sa fie asezate cuvintele in vectorul sortat. Ordinea alfabetica (din cartea de telefon) a cuvintelor este: \"abac\", \"bac\", \"zarva\", \"zugrav\", deci vectorul $Ind$ este:\r\n\r\n$Ind = (3, 1, 4, 2)$\r\n\r\nsemnificand ca primul cuvant din vectorul sortat ar trebui sa fie al treilea din vectorul $B$, respectiv \"abac\", si asa mai departe. In felul acesta am obtinut un vector sortat, care presupune o indirectare a elementelor. Vectorul sortat este\r\n\r\n$B\' = (B(Ind(1)), B(Ind(2)), B(Ind(3)), B(Ind(4))$.\r\n\r\nAceasta operatie se numeste indexare. Ce-i drept, constructia vectorului $Ind$ nu se poate face intr-un timp mai bun decat $O(N log N)$, dar dupa ce acest lucru se face (o singura data, la inceputul programului), cautarile se pot face foarte repede. Daca pe parcurs se fac adaugari sau stergeri de elemente in/din baza de date, se va pierde catva timp pentru mentinerea indexului, dar in practica timpul acesta este mult mai mic decat timpul care s-ar pierde cu cautarea unor elemente in cazul in care vectorul ar fi neindexat. Nu vom intra in detalii despre indexare, deoarece nu acesta este obiectul articolului de fata.\r\n\r\nIn unele situatii nu se poate face nici indexarea structurii de date. Sa consideram cazul unui program care joaca sah. Numarul de pozitii posibile ale pieselor pe tabla de sah este mult prea mare. Nu poate fi vorba nici macar de retinerea tuturor, cu atat mai putin de indexarea lor. In esenta, modul de functionare al acestui program se reduce la o rutina care primeste o pozitie pe tabla si o variabila care indica daca la mutare este albul sau negrul, rutina intorcand cea mai buna mutare care se poate efectua din acea pozitie. Majoritatea programelor de sah incep sa expandeze respectiva pozitie, examinand tot felul de variante ce pot decurge din ea si alegand-o pe cea mai promitatoare, asa cum fac si jucatorii umani. Pozitiile analizate, fiind mult mai putine decat cele posibile, sunt stocate in memorie sub forma unei liste.\r\n\r\nSa ne inchipuim acum urmatoarea situatie. Este posibil ca, prin expandarea unei configuratii initiale a tablei sa se ajunga la aceeasi configuratie finala pe doua cai diferite. Spre exemplu, daca albul muta intai calul la _f3_, apoi nebunul la _c4_, pozitia rezultata va fi aceeasi ca si cand s-ar fi mutat intai nebunul si apoi calul (considerand bineinteles ca negrul da in ambele situatii aceeasi replica). Daca configuratia finala a fost deja analizata pentru prima varianta, este inutil sa o mai analizam si pentru cea de-a doua, pentru ca rezultatul (concluzia la care se va ajunge) va fi exact acelasi. Dar cum isi poate da programul seama daca pozitia pe care are de gand s-o analizeze a fost analizata deja sau nu?\r\n\r\nCea mai simpla metoda este o scanare a listei de configuratii examinate din memorie. Daca in aceasta lista se afla pozitia curenta de analizat, inseamna ca ea a fost deja analizata si vom renunta la ea. Daca nu, o vom analiza acum. Ideea in mare a algoritmului este:\r\n\r\n== code(c) |\r\nfunctia Analizeaza(Pozitie P)\r\n    cauta P in lista de pozitii deja analizate\r\n    daca P nu exista in lista\r\n        expandeaza P si afla cea mai buna mutare M\r\n        adauga P la lista de pozitii analizate\r\n        intoarce M\r\n    altfel\r\n        intoarce valoarea M atasata pozitiei P gasite in lista\r\nsfarsit\r\n==\r\n\r\nNu vom insista asupra a cum se expandeaza o pozitie si cum se calculeaza efectiv cea mai buna mutare. Noi ne vom interesa de un singur aspect, si anume cautarea unei pozitii in lista. Tehnica cea mai \"naturala\" este o parcurgere a listei de la cap la coada, comparand pe rand pozitia cautata cu fiecare pozitie din lista. Daca lista are memorate $N$ pozitii, atunci in cazul unei cautari cu succes (pozitia este gasita), numarul mediu de comparatii facute este $N/2$, iar numarul cel mai defavorabil ajunge pana la $N$. In cazul unei cautari fara succes (pozitia nu exista in lista), numarul de comparatii este intotdeauna $N$. De altfel, cazul cautarii fara succes este mult mai frecvent pentru problema jocului de sah, unde numarul de pozitii posibile creste exponential cu numarul de mutari. Acelasi numar de comparatii il presupune si stergerea unei pozitii din lista (care presupune intai gasirea ei) si adaugarea (care presupune ca pozitia de adaugat sa nu existe deja in lista).\r\n\r\nPentru imbunatatirea practica a acestui timp sunt folosite _tabelele de dispersie_ sau _tabelele hash_ (engl. _hash_ = a toca, tocatura). Mentionam de la bun inceput ca tabelele hash nu au nicio utilitate din punct de vedere teoretic. Daca suntem rau intentionati, este posibil sa gasim exemple pentru care cautarea intr-o tabela hash sa dureze la fel de mult ca intr-o lista simplu inlantuita, respectiv $O(N)$. Dar in practica timpul cautarii si al adaugarii de elemente intr-o tabela hash coboara uneori pana la $O(1)$, iar in medie scade foarte mult (de mii de ori).\r\n\r\nh2(#descriere). Descrierea structurii de date\r\n\r\nIata despre ce este vorba. Sa presupunem pentru inceput ca in loc de pozitii pe tabla de sah, lista noastra memoreaza numere intre 0 si 999. In acest caz, tabela hash ar fi un simplu vector $H$ cu $1000$ de elemente booleene. Initial, toate elementele lui $H$ au valoarea $False$ (sau $0$). Daca numarul $473$ a fost gasit in lista, nu avem decat sa setam valoarea lui $H(473)$ la $True$ (sau $1$). La o noua aparitie a lui $473$ in lista, vom examina elementul $H(473)$ si, deoarece el este $True$, inseamna ca acest numar a mai fost gasit. Daca dorim stergerea unui element din hash, vom reseta pozitia corespunzatoare din $H$. Practic, avem de-a face cu un exemplu rudimentar de ceea ce se cheama functie de dispersie, adica $h(x) = x$. O proprietate foarte importanta a acestei functii este injectivitatea; este imposibil ca la doua numere distincte sa corespunda aceeasi intrare in tabela. Sa incercam o reprezentare grafica a metodei:\r\n\r\np=. !tabele-hash-prezentare-detaliata?hash1.jpg!\r\n\r\nIata primul set de functii de gestionare a unui hash.\r\n\r\n== code(c) |\r\nconst int M = 1000;\r\ntypedef int DataType;\r\ntypedef DataType Hash[M];\r\nHash H;\r\n\r\nvoid InitHash1(Hash H) {\r\n    for (int i = 0; i < M; H[i++] = 0);\r\n}\r\n\r\ninline int h(DataType K) {\r\n    return K;\r\n}\r\n\r\nint Search1(Hash H, DataType K) {\r\n    // Intoarce -1 daca elementul nu exista in hash\r\n    // sau indicele in hash daca el exista\r\n    return H[h(K)] ? h(K) : -1;\r\n}\r\n\r\nvoid Add1(Hash H, DataType K) {\r\n    H[h(K)] = 1;\r\n}\r\n\r\nvoid Delete1(Hash H, DataType K) {\r\n    H[h(K)] = 0;\r\n}\r\n==\r\n\r\nPrin \"numar de intrari\" in tabela se intelege numarul de elemente ale vectorului $H$; in general, orice tabela hash este un vector. Pentru ca functiile sa fie cat mai generale, am dat tipului de date _int_ un nou nume _DataType_. In principiu, tabelele hash se aplica oricarui tip de date. In realitate, fenomenul este tocmai cel invers: orice tip de date trebuie \"convertit\" printr-o metoda sau alta la tipul de date _int_, iar functia de dispersie primeste ca parametru un intreg. Functiile hash prezentate in viitor nu vor mai lucra decat cu variabile de tip intreg. Vom vorbi mai tarziu despre cum se poate face conversia. Acum sa generalizam exemplul de mai sus.\r\n\r\nIntr-adevar, cazul anterior este mult prea simplu. Sa ne inchipuim de pilda ca in loc de numere mai mici ca $1.000$, avem numere de pana la $2.000.000.000$. In aceasta situatie posibilitatea de a reprezenta tabela ca un vector caracteristic iese din discutie. Numarul de intrari in tabela este de ordinul miilor, cel mult al zecilor de mii, deci cu mult mai mic decat numarul total de chei (numere) posibile. Ce avem de facut? Am putea incerca sa adaugam un numar $K$ intr-o tabela cu $M$ intrari (numerotate de la 0 la $M-1$) pe pozitia $K mod M$, adica $h(K) = K mod M$. Care va fi insa rezultatul? Functia $h$ isi va pierde proprietatea de injectivitate, deoarece mai multor chei le poate corespunde aceeasi intrare in tabela, cum ar fi cazul numerelor $1.234$ si $2.001.234$, ambele dand acelasi rest la impartirea prin $M = 1.000$. Nu putem avea insa speranta de a gasi o functie injectiva, pentru ca atunci numarul de intrari in tabela ar trebui sa fie cel putin egal cu numarul de chei distincte. Vrand-nevrand, trebuie sa rezolvam coliziunile (sau conflictele) care apar, adica situatiile cand mai multe chei distincte sunt repartizate la aceeasi intrare.\r\n\r\nVom reveni ulterior la oportunitatea alegerii functiei modul si a numarului de $1.000$ de intrari in tabela. Deocamdata vom folosi aceste date pentru a explica modul de functionare a tabelei hash pentru functii neinjective. Sa presupunem ca avem doua chei $K1$ si $K2$ care sunt repartizate de functia $h$ la aceeasi intrare $X$, adica $h(K1) = h(K2) = X$. Solutia cea mai comoda este ca $H(X)$ sa nu mai fie un numar, ci o lista liniara simplu inlantuita care sa contina toate cheile gasite pana acum si repartizate la aceeasi intrare $X$. Prin urmare vectorul $H$ va fi un vector de liste:\r\n\r\np=. !tabele-hash-prezentare-detaliata?hash2.jpg!\r\n\r\nSa analizam acum complexitatea noilor functii de cautare, adaugare si stergere. Cautarea nu se va mai face in toata lista, ci numai in lista corespunzatoare din $H$. Altfel spus, o cheie $K$ se va cauta numai in lista $H(h(K))$, deoarece daca cheia $K$ a mai aparut, ea a fost in mod sigur repartizata la intrarea $H(h(K))$. De aceea, cautarea poate ajunge, in cazul cel mai defavorabil cand toate cheile din lista se repartizeaza la aceeasi intrare in hash, la o complexitate $O(N)$. Daca reusim insa sa gasim o functie care sa distribuie cheile cat mai aleator, timpul de intrare se va reduce de $M$ ori. Avantajele sunt indiscutabile pentru $M = 10.000$ de exemplu.\r\n\r\nIntrucat operatiile cu liste liniare sunt in general cunoscute, nu vom insista asupra lor. Prezentam aici numai adaugarea si cautarea, lasandu-va ca tema scrierea functiei de stergere din tabela.\r\n\r\n== code(c) |\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n\r\nconst int M = 1000;\r\ntypedef struct List_ {\r\n    long P;\r\n    struct List_ *Next;\r\n} List;\r\ntypedef List* Hash[M];\r\nHash H;\r\n\r\nvoid InitHash2(Hash H){\r\n    for (int i = 0; i < M; H[i++] = NULL);\r\n}\r\n\r\nint h2(int K) {\r\n    return K % M;\r\n}\r\n\r\nint Search2(Hash H, int K) {\r\n    // Intoarce 0 daca elementul nu exista in hash\r\n    // sau 1 daca el exista\r\n    List *L;\r\n    for (L = H[h2(K)]; L && (L->P != K); L = L->Next);\r\n    return L != NULL;\r\n}\r\n\r\nvoid Add2(Hash H, int K) {\r\n    List *L = (List *) malloc(sizeof(List));\r\n    L->P = K;\r\n    L->Next = H[h2(K)];\r\n    H[h2(K)] = L;\r\n}\r\n==\r\n\r\nAm spus ca functiile de dispersie sunt concepute sa lucreze numai pe date de tip intreg; celelalte tipuri de date trebuie convertite in prealabil la tipuri de date intregi. Iata cateva exemple:\r\n\r\n* Variabilele de tip string pot fi transformate in numere in baza $256$ prin inlocuirea fiecarui caracter cu codul sau _ASCII_. De exemplu, sirul \"abac\" poate fi privit ca un numar de 4 cifre in baza $256$, si anume numarul $(97 98 97 99)$. Conversia lui in baza $10$ se face astfel:\r\n\r\n$X = ((97 * 256 + 98) * 256 + 97) * 256 + 99 = 1.633.837.411$\r\n\r\nPentru stringuri mai lungi, rezulta numere mai mari. Uneori, ele nici nu mai pot fi reprezentate cu tipurile de date ordinare. Totusi, acest dezavantaj nu este suparator, deoarece majoritatea functiilor de dispersie presupun o impartire cu rest, care, indiferent de marimea numarului de la intrare, produce un numar controlabil.\r\n\r\n* Variabilele de tip data se pot converti la intreg prin formula:\r\n\r\n$X = A * 366 + L * 31 + Z$\r\n\r\nunde $A$, $L$ si $Z$ sunt respectiv anul, luna si ziua datei considerate. De fapt, aceasta functie aproximeaza numarul de zile scurse de la inceputul secolului I. Ea nu are pretentii de exactitate (ca dovada, toti anii sunt considerati a fi bisecti si toate lunile a avea 31 de zile), deoarece s-ar consuma timp inutil cu calcule mai sofisticate, fara ca dispersia insasi sa fie imbunatatita cu ceva. Conditia care trebuie neaparat respectata este ca functia de conversie data <tex> \\leftrightarrow </tex> intreg sa fie injectiva, adica sa nu se intample ca la doua date $D1$ si $D2$ sa li se ataseze acelasi intreg $X$; daca acest lucru se intampla, pot aparea erori la cautarea in tabela (de exemplu, se poate raporta gasirea datei $D1$ cand de fapt a fost gasita data $D2$). Pentru a respecta injectivitatea, s-au considerat coeficientii $366$ si $31$ in loc de $365$ si $30$. Daca numarul de zile scurse de la 1 ianuarie anul 1 d.H. ar fi fost calculat cu exactitate, functia de conversie ar fi fost si surjectiva, dar, dupa cum am mai spus, acest fapt nu prezinta interes.\r\n\r\n* Analog, variabilele de tip ora se pot converti la intreg cu formula:\r\n\r\n$X = (H * 60 + M) * 60 + S$\r\n\r\nunde $H$, $M$ si $S$ sunt respectiv ora, minutul si secunda considerate, sau cu formula\r\n\r\n$X = ((H * 60 + M) * 60 + S) * 100$\r\n\r\ndaca se tine cont si de sutimile de secunda. De data aceasta, functia este surjectiva (oricarui numar intreg din intervalul $0 - 8.639.999$ ii corespunde in mod unic o ora).\r\n\r\n* In majoritatea cazurilor, datele sunt structuri care contin numere si stringuri. O buna metoda de conversie consta in alipirea tuturor acestor date si in convertirea la baza $256$. Caracterele se convertesc prin simpla inlocuire cu codul _ASCII_ corespunzator, iar numerele prin convertirea in baza $2$ si taierea in \"bucati\" de cate opt biti. Rezulta numere cu multe cifre (prea multe chiar si pentru tipul $long long$), care sunt supuse unei operatii de impartire cu rest. Functia de conversie trebuie sa fie injectiva. De exemplu, in cazul tablei de sah despre care am amintit mai inainte, ea poate fi transformata intr-un vector cu $64$ de cifre in baza $16$, cifra $0$ semnificand un patrat gol, cifrele $1-6$ semnificand piesele albe (pion, cal, nebun, turn, regina, rege), iar cifrele $7-12$ semnificand piesele negre. Prin trecerea acestui vector in baza $256$, rezulta un numar cu $32$ de cifre. La acesta se mai pot adauga alte cifre, respectiv partea la mutare ($0$ pentru alb, $1$ pentru negru), posibilitatea de a efectua rocada mica/mare de catre alb/negru, numarul de mutari scurse de la inceputul partidei si asa mai departe.\r\n\r\nVom termina prin a prezenta doua functii de dispersie foarte des folosite.\r\n\r\nh2(#metoda-impartirii-cu-rest). Metoda impartirii cu rest\r\n\r\nDespre aceasta metoda am mai vorbit. Functia hash este: $h(x) = x mod M$ unde $M$ este numarul de intrari in tabela. Problema care se pune este sa-l alegem pe $M$ cat mai bine, astfel incat numarul de coliziuni pentru oricare din intrari sa fie cat mai mic. De asemenea, trebuie ca $M$ sa fie cat mai mare, pentru ca media numarului de chei repartizate la aceeasi intrare sa fie cat mai mica. Totusi, experienta arata ca nu orice valoare a lui $M$ este buna.\r\n\r\nDe exemplu, la prima vedere s-ar putea spune ca o buna valoare pentru $M$ este o putere a lui $2$, cum ar fi $1024$, pentru ca operatia de impartire cu rest se poate face foarte usor in aceasta situatie. Totusi, functia $h(x) = x mod 1024$ are un mare defect: ea nu tine cont decat de ultimii $10$ biti ai numarului $x$. Daca datele de intrare sunt numere in mare majoritate pare, ele vor fi repartizate in aceeasi proportie la intrarile cu numar de ordine par, pentru ca functia $h$ pastreaza paritatea. Din aceleasi motive, alegerea unei valori ca $1000$ sau $2000$ nu este prea inspirata, deoarece tine cont numai de ultimele $3-4$ cifre ale reprezentarii zecimale. Multe valori pot da acelasi rest la impartirea prin $1000$. De exemplu, daca datele de intrare sunt anii de nastere ai unor persoane dintr-o agenda telefonica, iar functia $h(x) = x mod 1000$, atunci majoritatea cheilor se vor ingramadi (termenul este sugestiv) intre intrarile $920$ si $990$, restul ramanand nefolosite.\r\n\r\nPractic, trebuie ca $M$ sa nu fie un numar rotund in nicio baza aritmetica, sau cel putin nu in bazele $2$ si $10$. O buna alegere pentru $M$ sunt numerele prime care sa nu fie apropiate de nicio putere a lui $2$. De exemplu, in locul unei tabele cu $M = 10.000$ de intrari, care s-ar comporta dezastruos, putem folosi una cu $9973$ de intrari. Chiar si aceasta alegere poate fi imbunatatita; intre puterile lui 2 vecine, respectiv $8192$ si $16384$, se poate alege un numar prim din zona $11.000 - 12.000$. Risipa de memorie de circa $1.000 - 2.000$ de intrari in tabela va fi pe deplin compensata de imbunatatirea cautarii.\r\n\r\nh2(#metoda-inmultirii). Metoda inmultirii\r\n\r\nPentru aceasta metoda functia hash este $h(x) = [M * {x*A}]$. Aici $A$ este un numar pozitiv subunitar, $0 < A < 1$, iar prin ${x*A}$ se intelege partea fractionara a lui $x*A$, adica $x*A - [x*A]$. De exemplu, daca alegem $M = 1234$ si $A = 0.3$, iar $x = 1997$, atunci avem $h(x) = [1234 * {599.1}] = [1234 * 0.1] = 123$. Se observa ca functia $h$ produce numere intre $0$ si $M-1$. Intr-adevar $0 &le; {x*A} < 1$ <tex>\\Rightarrow</tex> $0 &le; M * {x*A} < M$.\r\n\r\nIn acest caz, valoarea lui $M$ nu mai are o mare importanta. O putem deci alege cat de mare ne convine, eventual o putere a lui $2$. In practica, s-a observat ca dispersia este mai buna pentru unele valori ale lui $A$ si mai proasta pentru altele. Donald Knuth propune valoarea <tex> A = \\frac{\\sqrt{5}-1}{2} \\approx 0.618034 </tex>.\r\n\r\nCa o ultima precizare necesara la acest articol, mentionam ca functia de cautare e bine sa nu intoarca pur si simplu $0$ sau $1$, dupa cum cheia cautata a mai aparut sau nu inainte intre datele de intrare. E recomandabil ca functia sa intoarca un pointer la zona de memorie in care se afla prima aparitie a cheii cautate. Vom da acum un exemplu in care aceasta valoare returnata este utila. Daca, in cazul prezentat mai sus al unui program de sah, se ajunge la o anumita pozitie $P$ dupa ce albul a pierdut dreptul de a face rocada, aceasta pozitie va fi retinuta in hash. Retinerea nu se va face nicidecum efectiv (toata tabla), pentru ca s-ar ocupa foarte multa memorie. Se va memora in loc numai un pointer la pozitia respectiva din lista de pozitii analizate. Pe langa economia de memorie in cazul cheilor de mari dimensiuni, mai exista si alt avantaj. Sa ne inchipuim ca, analizand in continuare tabla, programul va ajunge la aceeasi pozitie $P$, dar in care albul are inca dreptul de a face rocada. E limpede ca aceasta varianta este mai promitatoare decat precedenta, deoarece albul are o libertate mai mare de miscare. Se impune deci fie stergerea vechii pozitii $P$ din lista si adaugarea noii pozitii, fie modificarea celei vechi prin setarea unei variabile suplimentare care indica dreptul albului de a face rocada. Aceasta modificare este usor de facut, intrucat cautarea in hash va returna chiar un pointer la pozitia care trebuie modificata. Bineinteles, in cazul in care pozitia cautata nu se afla in hash, functia de cautare trebuie sa intoarca $NULL$.\r\n\r\nIn incheiere, prezentam un exemplu de functie de dispersie pentru cazul tablei de sah.\r\n\r\n== code(c) |\r\nconst int M = 9973;  // Numarul de \"intrari\".\r\ntypedef struct {\r\n    // Tabla de joc, cu 0 <= T[i][j] <= 12.\r\n    char b_T[8][8];\r\n\r\n    // Ultimii doi biti ai lui b_CastleW indica daca albul are dreptul de a\r\n    // efectua rocada mare, respectiv pe cea mica. Analog pentru b_CastleB.\r\n    char b_CastleW, b_CastleB;\r\n\r\n    // 0 sau 1, dupa cum la mutare este albul sau negrul.\r\n    char b_Side;\r\n\r\n\r\n    // 0..8, indicand coloana (0..7) pe care partea la mutare poate efectua o\r\n    // captura \"en passant\". 8 indica ca nu exista aceasta posibilitate.\r\n    char b_EP;\r\n\r\n    // Numarul de mutari efectuate.\r\n    int b_NMoves;\r\n} Board;\r\nBoard B;\r\n\r\nint h3(Board *B) {\r\n    int i, j;\r\n\r\n    // Valoarea initiala a lui S este un numar pe 17 biti care\r\n    // inglobeaza toate variabilele suplimentare pe langa T.\r\n    // S se va lua apoi modulo M.\r\n    long S = (B->b_NMoves           // 8 biti\r\n            +(B->b_CastleW << 8)    // 2 biti\r\n            +(B->b_CastleB << 10)   // 2 biti\r\n            +(B->b_Side << 12)      // 1 bit\r\n            +(B->b_EP << 13)) % M;  // 4 biti\r\n\r\n    for (i = 0; i <= 7; i++)\r\n        for (j=0; j <= 7; j++) {\r\n            S = (16 * S + B->b_T[i][j]) % M;\r\n        }\r\n\r\n    return S;\r\n}\r\n==\r\n\r\nh2(#probleme-propuse). Probleme propuse\r\n\r\nIata si o scurta lista de probleme ce se rezolva eficient folosind tabelele hash:\r\n\r\n* \'SGU 174 - Walls\':http://acm.sgu.ru/problem.php?contest=0&problem=174\r\n* \'UVA 10748 - Knights Roaming\':http://icpcres.ecs.baylor.edu/onlinejudge/external/107/10748.html\r\n* \"UVA 10815 - Andy\'s First Dictionary\":http://icpcres.ecs.baylor.edu/onlinejudge/external/108/10815.html\r\n* \'UVA 10887 - Concatenation of Languages\':http://icpcres.ecs.baylor.edu/onlinejudge/external/108/10887.html\r\n* \'UVA 704 - Colour Hash\':http://icpcres.ecs.baylor.edu/onlinejudge/external/7/704.html\r\n',2044,'public',NULL,NULL),('articole/algoritmi','Algoritmi si tehnici de programare','2008-12-13 15:05:43','2009-01-12 09:52:27','h1. Algoritmi si tehnici de programare\r\n\r\ntable(layout){width:75%}. | ==include(page=\"articole/template-algoritmi\" display=\"list-item\")== |\r\n\r\n\'_<< inapoi la pagina principala_\':articole',2044,'protected',NULL,NULL),('planificare/camp-2.2.1','Coding Camp \"A New Day\"','2009-02-01 22:33:19','2009-02-28 09:33:17','h1. Coding Camp _\"A New Day\"_\r\n\r\nNe intalnim in weekend-ul *28 februarie-1 martie 2009*, in fiecare zi incepand cu *ora 10:00*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nScopul final al coding camp-ului este lansarea versiunii \'*infoarena 2.2.1*\':http://hackers.devnet.ro/milestone/2.2.1%20A%20New%20Day.\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu Linux (preferabil Ubuntu) instalat pe el\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri\r\n\r\nh2. Participanti\r\n\r\nSpecifica cand poti veni si cat poti sta.\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"alexthero\" type=\"tiny\")==: de acasa - tot weekend-ul\r\n* ==user(user=\"wickedman\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"stef2n\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"devilkind\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"silviug\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"prostu\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"victorsb\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"filipb\" type=\"tiny\")==: duminica\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"danielp\" type=\"tiny\")==: + ==user(user=\"astronomy\" type=\"tiny\")==: 1 zi, de acasa\r\n* ==user(user=\"svalentin\" type=\"tiny\")==: duminica\r\n\r\nh2. Agenda\r\n\r\nh3. Must have\r\n\r\n|_. Task| Cine lucreaza | \r\n| Reorganizat sidebar si topnav | | \r\n| Script de backup | |\r\n| \'Virtual Contests\':propuneri/10-virtual-contest | |\r\n| \'Sistem de monitorizare\':http://hackers.devnet.ro/ticket/179 | |\r\n| \'Pagina de submit desteapta\':http://hackers.devnet.ro/ticket/366 | |\r\n| Optimizat pagina de clasament | |\r\n| Probleme interactive | ==user(user=\"silviug\" type=\"tiny\")==|\r\n| Script de recalculat timpii de evaluare | |\r\n\r\nh3. Nice to have\r\n\r\n|_. Task|\r\n| Tagging pentru probleme | Cine lucreaza | \r\n| \'Run YSlow and improve performance\':http://hackers.devnet.ro/ticket/351 | | \r\n| \'Interfata de updatat rating-uri\':http://hackers.devnet.ro/ticket/239 | |\r\n| \'Permisiuni in pagina de changes\':http://hackers.devnet.ro/ticket/363 | |\r\n| \'Scoruri detaliate\':http://hackers.devnet.ro/ticket/263 | |\r\n| \'Sterge o revizie\':http://hackers.devnet.ro/ticket/132 | |\r\n| \'Pagina de changes mai detaliata\':http://hackers.devnet.ro/ticket/155 | |\r\n| \'Paginator pentru comentarii\':http://hackers.devnet.ro/ticket/368 | |\r\n\r\nh3. Others\r\n\r\n|_. Task| Cine lucreaza | \r\n| \'Grafice rating\':http://hackers.devnet.ro/ticket/211 | | \r\n| \'Optimizat diff-ul\':http://hackers.devnet.ro/ticket/360 | | \r\n| \'Script pentru topic-uri de pe forum\':http://hackers.devnet.ro/ticket/367 | |\r\n| \'Atasamente ca zip\':http://hackers.devnet.ro/ticket/306 | ==user(user=\"alexthero\" type=\"tiny\")== |\r\n| \'Licenta CC\':http://hackers.devnet.ro/ticket/343 | |\r\n| \'Feed-uri pe Feedburner\':http://hackers.devnet.ro/ticket/344 | |',1,'public',NULL,NULL),('planificare/camp-2.2.1','Coding Camp \"A New Day\"','2009-02-01 22:33:19','2009-02-28 09:53:01','h1. Coding Camp _\"A New Day\"_\r\n\r\nNe intalnim in weekend-ul *28 februarie-1 martie 2009*, in fiecare zi incepand cu *ora 10:00*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nScopul final al coding camp-ului este lansarea versiunii \'*infoarena 2.2.1*\':http://hackers.devnet.ro/milestone/2.2.1%20A%20New%20Day.\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu Linux (preferabil Ubuntu) instalat pe el\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri\r\n\r\nh2. Participanti\r\n\r\nSpecifica cand poti veni si cat poti sta.\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"alexthero\" type=\"tiny\")==: de acasa - tot weekend-ul\r\n* ==user(user=\"wickedman\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"stef2n\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"devilkind\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"silviug\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"prostu\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"victorsb\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"filipb\" type=\"tiny\")==: duminica\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"danielp\" type=\"tiny\")==: + ==user(user=\"astronomy\" type=\"tiny\")==: 1 zi, de acasa\r\n* ==user(user=\"svalentin\" type=\"tiny\")==: duminica\r\n\r\nh2. Agenda\r\n\r\nh3. Must have\r\n\r\n|_. Task|_. Cine lucreaza | \r\n| Reorganizat sidebar si topnav | | \r\n| Script de backup | |\r\n| \'Virtual Contests\':propuneri/10-virtual-contest | |\r\n| \'Sistem de monitorizare\':http://hackers.devnet.ro/ticket/179 | |\r\n| \'Pagina de submit desteapta\':http://hackers.devnet.ro/ticket/366 | |\r\n| Optimizat pagina de clasament | |\r\n| Probleme interactive | ==user(user=\"silviug\" type=\"tiny\")==|\r\n| Script de recalculat timpii de evaluare | |\r\n\r\nh3. Nice to have\r\n\r\n|_. Task|_. Cine lucreaza |\r\n| Tagging pentru probleme | | \r\n| \'Run YSlow and improve performance\':http://hackers.devnet.ro/ticket/351 | | \r\n| \'Interfata de updatat rating-uri\':http://hackers.devnet.ro/ticket/239 | ==user(user=\"victorsb\" type=\"tiny\")== |\r\n| \'Permisiuni in pagina de changes\':http://hackers.devnet.ro/ticket/363 | |\r\n| \'Scoruri detaliate\':http://hackers.devnet.ro/ticket/263 | |\r\n| \'Sterge o revizie\':http://hackers.devnet.ro/ticket/132 | |\r\n| \'Pagina de changes mai detaliata\':http://hackers.devnet.ro/ticket/155 | |\r\n| \'Paginator pentru comentarii\':http://hackers.devnet.ro/ticket/368 | |\r\n\r\nh3. Others\r\n\r\n|_. Task|_. Cine lucreaza | \r\n| \'Grafice rating\':http://hackers.devnet.ro/ticket/211 | | \r\n| \'Optimizat diff-ul\':http://hackers.devnet.ro/ticket/360 | | \r\n| \'Script pentru topic-uri de pe forum\':http://hackers.devnet.ro/ticket/367 | |\r\n| \'Atasamente ca zip\':http://hackers.devnet.ro/ticket/306 | ==user(user=\"alexthero\" type=\"tiny\")== |\r\n| \'Licenta CC\':http://hackers.devnet.ro/ticket/343 | |\r\n| \'Feed-uri pe Feedburner\':http://hackers.devnet.ro/ticket/344 | |',1851,'public',NULL,NULL),('planificare/camp-2.2.1','Coding Camp \"A New Day\"','2009-02-01 22:33:19','2009-02-28 10:23:36','h1. Coding Camp _\"A New Day\"_\r\n\r\nNe intalnim in weekend-ul *28 februarie-1 martie 2009*, in fiecare zi incepand cu *ora 10:00*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'locaţie pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8.)\r\n\r\nScopul final al coding camp-ului este lansarea versiunii \'*infoarena 2.2.1*\':http://hackers.devnet.ro/milestone/2.2.1%20A%20New%20Day.\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu Linux (preferabil Ubuntu) instalat pe el\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri\r\n\r\nh2. Participanti\r\n\r\nSpecifica cand poti veni si cat poti sta.\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"alexthero\" type=\"tiny\")==: de acasa - tot weekend-ul\r\n* ==user(user=\"wickedman\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"stef2n\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"devilkind\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"silviug\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"prostu\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"victorsb\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"filipb\" type=\"tiny\")==: duminica\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"danielp\" type=\"tiny\")==: + ==user(user=\"astronomy\" type=\"tiny\")==: 1 zi, de acasa\r\n* ==user(user=\"svalentin\" type=\"tiny\")==: duminica\r\n\r\nh2. Agenda\r\n\r\nh3. Must have\r\n\r\n|_. Task|_. Cine lucreaza | \r\n| Reorganizat sidebar si topnav | ==user(user=\"wickedman\" type=\"tiny\")==  | \r\n| Script de backup | ==user(user=\"wickedman\" type=\"tiny\")== |\r\n| \'Virtual Contests\':propuneri/10-virtual-contest | ==user(user=\"domino\" type=\"tiny\")== ==user(user=\"bogdan2412\" type=\"tiny\")== |\r\n| \'Pagina de submit desteapta\':http://hackers.devnet.ro/ticket/366 | |\r\n| Optimizat pagina de clasament |  |\r\n| Script de recalculat timpii de evaluare |  |\r\n\r\nh3. Nice to have\r\n\r\n|_. Task|_. Cine lucreaza |\r\n| Probleme interactive | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| \'Scoruri detaliate\':http://hackers.devnet.ro/ticket/263 | ==user(user=\"devilkind\" type=\"tiny\")==  |\r\n| \'Pagina de changes mai detaliata\':http://hackers.devnet.ro/ticket/155 | ==user(user=\"prostu\" type=\"tiny\")== |\r\n| \'Permisiuni in pagina de changes\':http://hackers.devnet.ro/ticket/363 | ==user(user=\"prostu\" type=\"tiny\")== |\r\n| Tagging pentru probleme | | \r\n| Community Dashboard | | \r\n| \'Interfata de updatat rating-uri\':http://hackers.devnet.ro/ticket/239 | ==user(user=\"victorsb\" type=\"tiny\")== |\r\n| \'Feed-uri pe Feedburner\':http://hackers.devnet.ro/ticket/344 | ==user(user=\"domino\" type=\"tiny\")==  |\r\n\r\nh3. Others\r\n\r\n|_. Task|_. Cine lucreaza | \r\n| \'Grafice rating\':http://hackers.devnet.ro/ticket/211 | ==user(user=\"stef2n\" type=\"tiny\")== | \r\n| \'Optimizat diff-ul\':http://hackers.devnet.ro/ticket/360 | ==user(user=\"gcosmin\" type=\"tiny\")== | \r\n| \'Script pentru topic-uri de pe forum la probleme\':http://hackers.devnet.ro/ticket/367 | |\r\n| \'Atasamente ca zip\':http://hackers.devnet.ro/ticket/306 | ==user(user=\"alexthero\" type=\"tiny\")== |\r\n| \'Licenta CC\':http://hackers.devnet.ro/ticket/343 | |\r\n| \'Run YSlow and improve performance\':http://hackers.devnet.ro/ticket/351 | | \r\n| \'Sterge o revizie\':http://hackers.devnet.ro/ticket/132 | ==user(user=\"devilkind\" type=\"tiny\")==  |\r\n| \'Paginator pentru comentarii\':http://hackers.devnet.ro/ticket/368 | ==user(user=\"coditza\" type=\"tiny\")==  |\r\n| \'Sistem de monitorizare\':http://hackers.devnet.ro/ticket/179 | |\r\n',15,'public',NULL,NULL),('concursuri-virtuale','Concursuri Virtuale','2009-02-28 16:19:24','2009-02-28 20:40:46','%{float: right; clear: both}\'Creaza concurs now\':admin/runda-noua%\r\n\r\nComing soon... Concursuri Virtuale\r\n\r\n==RoundList(type=\"user-defined\" show_authors=\"true\")==\r\n',1490,'protected',NULL,NULL),('deque-si-aplicatii','Deque și aplicații','2009-01-22 22:28:12','2009-02-26 19:49:59','h1. Deque şi aplicaţii\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'Descrierea structurii\':deque-si-aplicatii#descriere\r\n* \'Aplicaţii:\':deque-si-aplicatii#problema-1\r\n** \'_1. Book Pile &#40;SGU&#41;_\':deque-si-aplicatii#problema-1\r\n** \'_2. Vila 2 &#40;.campion, 2005&#41;_\':deque-si-aplicatii#problema-2\r\n** \'_3. Şir_\':deque-si-aplicatii#problema-3\r\n** \'_4. Platforma &#40;.campion, 2009&#41;_\':deque-si-aplicatii#problema-4\r\n** \'_5. Trans &#40;ONI 2004&#41;_\':deque-si-aplicatii#problema-5\r\n** \'_6. Otilia &#40;.campion, 2005&#41;_\':deque-si-aplicatii#problema-6\r\n** \'_7. Bcrc &#40;Stelele Informaticii, 2006&#41;_\':deque-si-aplicatii#problema-7\r\n** \'_8. Cut the Sequence &#40;PKU&#41;_\':deque-si-aplicatii#problema-8\r\n* \'Concluzii\':deque-si-aplicatii#concluzii\r\n* \'Probleme suplimentare\':deque-si-aplicatii#probleme-suplimentare\r\n* \'Bibliografie\':deque-si-aplicatii#bibliografie\r\n\r\nÎn acest articol voi prezenta o structură de date liniară de tip listă numită _deque_. Aceasta nu este una complexă, în schimb se va dovedi foarte folositoare. După o scurtă prezentare, mă voi axa pe o serie de aplicaţii care vor arăta surprinzătoarea sa utilitate în locurile unde am fi crezut că nu se mai poate face nimic pentru a reduce complexitatea algoritmului.\r\n\r\nh2(#descriere). Descrierea structurii\r\n\r\nStructura de _deque_ (pronunţat, de obicei, _deck_) poate fi privită ca o listă cu două capete prin intermediul cărora se şterg sau inserează noi elemente. În literatura de specialitate aceste capete se numesc _head_ şi _tail_, iar deque-ul mai este recunoscut şi ca fiind o coadă cu două capete _(double ended queue)_.\r\n\r\nPentru implementarea unui deque putem recurge la liste dublu înlănţuite sau la un vector static când se cunoaşte numărul elementelor din colecţie. Limbajul C++ pune şi el la dispoziţia programatorilor o implementare prin intermediul containerului \'_std::deque_\':http://www.cplusplus.com/reference/stl/deque/ din headerul _<deque>_.\r\n\r\nh3(#operatii). Operaţii:\r\n\r\nVom putea utiliza această structură de date în situaţiile când avem nevoie de următoarele operaţii (sunt listate cu numele sub care se găsesc în limbajul C++):\r\n\r\ntable{width:70%}. | * _front()_ | întoarce primul element |\r\n| * _back()_ | întoarce ultimul element |\r\n| * _push_front()_ | inserează un element în faţă |\r\n| * _push_back()_ | inserează un element în spate |\r\n| * _pop_front()_ | scoate primul element |\r\n| * _pop_back()_ | scoate ultimul element |\r\n| * _empty()_ | întoarce _true_ dacă în deque nu se găseşte niciun element şi _false_ în caz contrar |\r\n\r\np=. !deque-si-aplicatii?new_deque.png 75%!\r\n\r\nToate aceste operaţii se execută în timp $O(1)$ pe o structură implementată de la zero sau în timp $O(1)$ \'amortizat\':http://en.wikipedia.org/wiki/Amortized_analysis pentru containerul $deque$ din C++.\r\n\r\nÎn multe aplicaţii unde soluţiile parţiale se reprezintă sub forma unui şir continuu de valori care permite inserarea şi ştergerea doar pe la capete se poate folosi un $deque$. Să urmărim în continuare cazuri concrete în care simplitatea unui $deque$ duce la soluţii de multe ori optime şi implementări foarte scurte şi clare. Aplicaţiile sunt prezentate în ordinea crescătoare a dificultăţii şi din acest motiv le recomand cu căldură tuturor celor care învaţă din acest articol să le parcurgă în ordine.\r\n\r\nh2(#problema-1). 1. \'Book Pile\':http://acm.sgu.ru/problem.php?contest=0&problem=271 (SGU)\r\n\r\nbq. Se dau $N$ cărţi aşezate una deasupra celeilalte asupra cărora se vor efectua $M$ operaţii de două tipuri: 1. $ADD${$(nume)$}: se adaugă cartea $nume$ deasupra celorlalte; 2. $ROTATE$: primele $K$ cărţi de deasupra se rotesc (dacă sunt mai puţin de $K$ cărţi atunci se vor roti toate). Rotaţia presupune inversarea celor $K$ elemente, adică ultimul va fi primul, penultimul va fi al doilea etc. Se cere să se afişeze cărţile în ordine, prima fiind cea de deasupra, după efectuarea celor $M$ operaţii.\r\nRestricţii: $0 &le; N, K &le; 40 000$, $0 &le; M &le; 100 000$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se poate deduce pe baza observaţiei următoare: odată avansată dincolo de poziţia $K$, o carte ajunge pe poziţia finală, întrucât orice operaţie ulterioară (inserare sau rotaţie) nu o va mai afecta. Să presupunem că iniţial avem cărţile $A B C$ şi $K = 3$. Dacă îl vom adăuga pe $D$, atunci nu avem nevoie pentru operaţiile următoare decât de cărţile $D A B$, deoarece, dacă vom roti ulterior primele $K$ cărţi, $C$ nu va mai fi niciodată considerat. După o rotaţie, noua ordine va fi $B A D$ şi $C$ va fi pe raft la loc sigur. Dacă îl vom adăuga pe $E$, topul se va schimba în $E B A$, iar pe raft, în mod sigur vor fi $D C$, în această ordine. Cele $K$ cărţi din vârf se prezintă ca o secvenţă continuă de elemente, la care se adaugă noi elemente sau se elimină dintre acestea numai pe la _capete_. Aceste capete sunt chiar $head$ şi $tail$ ale unui $deque$.\r\n\r\np=. !deque-si-aplicatii?bookpile.png 40%!\r\n\r\nLa final, când se vor termina operaţiile, cărţilor de pe raft li se vor adăuga cele din $deque$ şi se va afişa soluţia. În cazul presupus, soluţia va fi: $E B A D C$.\r\n\r\nÎntrucât operaţiile unui $deque$ se execută în timp $O(1)$, soluţia are complexitatea $O(N + M)$.\r\n\r\nh2(#problema-2). 2. \'Vila 2\':problema/vila2 (.campion, 2005)\r\n\r\nbq. Se dă un şir $S$ de $N$ numere întregi şi $D$ un număr natural. Se cere să se determine diferenţa maximă dintre oricare două numere din şir cu proprietatea că diferenţa în modul a poziţiilor pe care se găsesc în şirul $S$ nu depăşeşte $D$.\r\nRestricţii: $2 &le; N &le; 100 000$, $1 &le; D &le; N/2$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia simplă constă în procesarea tuturor perechilor de numere care se găsesc pe poziţii cu diferenţa în modul mai mică sau egală decât $D$.\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    ret = 0;\r\n    pentru i = 1, N execută\r\n        pentru j = Max(1, i - D), i execută\r\n            dacă ret < |S[i] - S[j]| atunci\r\n                ret = |S[i] - S[j]|;\r\n        sfârşit_pentru;\r\n    sfârşit_pentru;\r\n    return ret;\r\nSfârşit.\r\n==\r\n\r\nComplexitatea algoritmului este $O(N^2^)$, dar care pentru limitele problemei este enorm.\r\n\r\nDin pseudocodul de mai sus se vede că pentru un indice $i$ fixat, iterăm cu un alt indice $j$ pentru a găsi diferenţa maximă în modul dintre $S[i]$ şi un alt număr din intervalul $[i - D, i]$. Însă, diferenţa dintre cel mai mare număr şi cel mai mic număr este cel puţin la fel de bună decât rezultatul anterior. Astfel, pentru indicele $i$ fixat succesiv cu $1$, $2$, .., $N$, considerăm secvenţa $[i - D, i]$ în care determinăm valoarea maximă şi valoarea minimă iar diferenţa lor o comparăm cu rezultatul cel mai bun obţinut până în acel moment. Dacă considerăm o secvenţă de lungime mai scurtă, atunci este posibil să pierdem din soluţii. Un caz este când cea mai mică şi cea mai mare dintre valori se găsesc pe poziţiile $i - D$, respectiv $i$.\r\n\r\nPentru fixarea ideii, să urmărim cum putem determina eficient valoarea maximă din fiecare secvenţă $[i - D, i]$.\r\n\r\n_Observaţie_: Fie $i{~1~}$, $i{~2~}$ doi indici astfel încât $i - D &le; i{~1~} &lt; i{~2~} &le; i$.\r\n\r\n# Dacă $S[i{~1~}] &le; S[i{~2~}]$ atunci, cât timp cei doi indici vor fi în intervale de tipul $[i - D, i]$, valoarea de pe poziţia $i{~2~}$ va fi întotdeauna preferată valorii de pe poziţia $i{~1~}$. Când se ajunge la un interval care nu-l mai conţine pe $i{~1~}$, $i{~2~}$ rămâne în continuare preferat.\r\n# Dacă $S[i{~1~}] &gt; S[i{~2~}]$ atunci şi valoarea de pe poziţia $i{~1~}$ şi cea de pe poziţia $i{~2~}$ sunt candidate la maxim, la momentul curent sau în viitor.\r\n\r\nCu această observaţie deducem că într-o secvenţă $[i - D, i]$ vom avea un şir strict descrescător de numere: $T{~i~} = S[i{~1~}] &gt; S[i{~2~}] &gt; ... &gt; S[i{~K~}]$, unde $S[i{~1~}]$ elimină toate elementele $S[j]$, cu $S[j] < S[i{~1~}]$ şi $i - D &le; j &lt; i{~1~}$, $S[i{~2~}]$ elimină toate elementele $S[j]$, cu $S[j] < S[i{~2~}]$ şi $i{~1~} &lt; j &lt; i{~2~}$, $S[i{~3~}]$ elimină toate elementele $S[j]$, cu $S[j] < S[i{~3~}]$ şi $i{~2~} &lt; j &lt; i{~3~}$ ş.a.m.d. \r\nŞirul $T{~i~}$ are următoarele proprietăţi:\r\n\r\n* se termină pe poziţia curentă, adică are loc egalitatea $i{~K~} = i$ întrucât poziţia $i$ nu va fi eliminată de nicio altă poziţie;\r\n* valoarea căutată, adică maximul dintre numerele din secvenţă, se găseşte pe prima poziţie. \r\n\r\nCând vom avansa la secvenţa următoare, $[i - D + 1, i + 1]$, vom forma şirul $T{~i+1~}$ ştergând din indicii $i{~1~}$, $i{~2~}$... atâta timp cât nu se găsesc în intervalul curent şi vom şterge din poziţiile $i{~K~}$, $i{~K-1~}$... cât timp $S[i + 1] &gt; S[i{~K~}]$, $S[i + 1] &gt; S[i{~K-1~}]$... adică cât timp se îndeplineşte primul punct din observaţia anterioară.\r\n\r\nŞirul $T{~i~}$ poate fi păstrat prin intermediul şirului de indici $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$. Acest şir de indici este continuu iar operaţiile de mai sus se efectuează doar pe la cele două capete. Rezultă că şirul poate fi implementat cu ajutorul unui deque.\r\n\r\nPentru $S[] = {5, 9, 4, 7, 4, 1}$ şi $D = 3$ obţinem următoarele stări ale unui deque:\r\n\r\n* <tex> \\langle \\widehat{5\\ [1]} \\rangle; </tex>\r\n* <tex> \\langle 5\\ [1] \\rangle \\Leftarrow 9\\ [2] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]} \\rangle; </tex>\r\n* <tex> \\langle 9\\ [2] \\rangle \\Leftarrow 4\\ [3] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 4\\ [3] \\rangle; </tex>\r\n* <tex> \\langle 9\\ [2],\\ 4\\ [3] \\rangle \\Leftarrow 7\\ [4] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 7\\ [4] \\rangle; </tex>\r\n* <tex> 9\\ [2] \\Leftarrow \\langle 7\\ [4] \\rangle \\Leftarrow 4\\ [5] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5] \\rangle; </tex>\r\n* <tex> \\langle 7\\ [4],\\ 4\\ [5] \\rangle \\Leftarrow 1\\ [6] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5],\\ 1\\ [6] \\rangle; </tex>\r\n\r\nCum fiecare indice din $1$, $2$, .., $N$ trece cel mult o dată prin deque, complexitatea finală este $O(N)$.\r\n\r\nh2(#problema-3). 3. \'Şir\':problema/sir\r\n\r\nbq. Se dă un şir $S$ de numere întregi de lungime $N$. Se cere să se găsească secvenţa de lungime maximă cuprinsă între $X$ şi $Y$ astfel încât $MAX - MIN &le; Z$, unde $MAX$ este maximul dintre toate numerele întregi din secvenţă iar $MIN$ minimul dintre acestea. Secvenţa soluţie va fi cea cu poziţia de început maximă dintre toate secvenţele de lungime maximă.\r\nRestricţii: $3 &le; N &le; 100 000$, $1 &le; X &le; Y &le; N$, $0 &le; Z &le; 30 000$.\r\n\r\nh3. Soluţie:\r\n\r\nVoi prezenta mai jos o rafinare a soluţiei în trei paşi.\r\n\r\nPrima rezolvare se găseşte uşor, deoarece nu facem decât să urmărim textul: pentru fiecare poziţie $i$ fixată ({$i$} ia valorile $1$, $2$, .., $N$ succesiv) vom determina pentru aceasta secvenţa cerută, adică vom plimba un $j$ între poziţiile $i - Y$ şi $i - X$. Pentru un interval $(j, i]$ vom determina $MAX$ şi $MIN$ în $O(log{~2~}N)$ cu un arbore de intervale, iar daca diferenţa dintre acestea nu depăşeşte $Z$ vom compara cu soluţia finală. Complexitatea finală va fi $O(N * (Y - X) * log{~2~}Y)$.\r\n\r\nSă presupunem că pentru poziţia curentă $i$, l-am găsit pe $j$ cât mai mic cuprins între $i - Y$ şi $i - X$ astfel încât secvenţa $(j, i]$ este candidată la soluţie. Ce proprietăţi are $j$?\r\n\r\n* $i - Y &le; j &le; i - X$ şi $MAX - MIN &le; Z$;\r\n* dacă îl incrementăm pe $j$ la $j + 1$ atunci dacă $j &le; i - X$ cu siguranţă $MAX - MIN &le; Z$ şi astfel soluţia va fi mai scurtă;\r\n* dacă îl decrementăm pe $j$, atunci ori $j < i - Y$ ori $MAX - MIN > Z$;\r\n* dacă îl incrementăm pe $i$ la $i + 1$, atunci se poate întâmpla ca $j < i - Y$; cum $MAX$ nu poate decât să crească, iar $MIN$ decât să scadă, se mai poate de asemenea întâmpla ca $MAX - MIN > Z$.\r\n\r\nDatorită proprietăţilor de mai sus, când trecem de la $i$ la $i + 1$, valoarea lui $j$ nu poate decât să crească cât timp $j < i - Y$ sau $MAX - MIN > Z$ şi $j$ nu a depăşit poziţia $i - X$. Pentru determinarea lui $MAX$, respectiv lui $MIN$ se poate folosi un arbore de intervale. Complexitatea finală va fi $O(N * log{~2~}(Y))$.\r\n\r\nCu cei doi indici $i$ şi $j$ vom accesa fiecare element din cele $N$ de cel mult $2$ ori, o dată cu $i$ şi o dată cu $j$. Să vedem cum putem îmbunătăţi complexitatea $O(log{~2~}Y)$ pentru determinarea maximului şi minimului.\r\n\r\nPentru fixarea ideilor să urmărim cum îl vom calcula pe $MAX$. Observaţia care ne ajută în multe probleme pentru reducerea complexităţii de la $O(log{~2~}N)$ la $O(1)$ amortizat este următoarea: \r\n\r\n_Observaţie_: Fixăm $i{~1~}$ şi $i{~2~}$ astfel încât $j < i{~1~} < i{~2~} &le; i$. Atunci, dacă $S[i{~2~}] > S[i{~1~}]$ poziţia $i{~2~}$ va fi întotdeauna preferată poziţiei $i{~1~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ şi $i{~2~}$ nu vor mai fi ambele în intervalul $(j, i]$, poziţia eliminată va fi $i{~1~}$. Dacă însă $S[i{~1~}] > S[i{~2~}]$, atunci poziţia $i{~1~}$ va umbri poziţia $i{~2~}$ atâta timp cât cele două poziţii vor fi în intervalul $(j, i]$. Când $i{~1~}$ va fi eliminat, atunci e posibil ca $i{~2~}$ să fie un candidat la $MAX$ dintre restul elementelor de la dreapta sa. În acest caz, nu putem afirma nimic şi vom păstra cele două poziţii.\r\n\r\nRezultă din această observaţie, precum în \'problema anterioară\':deque-si-aplicatii#problema-2, că în intervalul $(j, i]$ se va forma un şir de poziţii $i{~1~} < i{~2~} < .. < i{~k~}$ astfel încât $S[i{~1~}] > S[i{~2~}] > .. > S[i{~k~}]$, din care obţinem că $MAX$ este egal cu $S[i{~1~}]$. Când îl vom incrementa pe $i$ la $i + 1$ vom şterge din poziţiile $i{~k~}$, $i{~k-1~}$, ... atâta timp cât $S[i + 1]$ este mai mare decât valorile de pe aceste poziţii, şi vom şterge $i{~1~}$, $i{~2~}$, ... atâta timp cât aceste poziţii sunt mai mici sau egale decât $j\'$. Indicele $j\'$ este noul optim pentru poziţia $i + 1$. Proprietatea şirului de poziţii $i{~1~}, i{~2~}, .., i{~k~}$ este că se reprezintă ca un şir continuu de numere care permite inserarea elementelor prin dreapta şi ştergerea prin stânga, adică se adaugă elemente la tail şi se şterg elemente de la head. Îl putem deci reprezenta printr-un deque. Complexitatea $O(1)$ amortizat provine de la faptul că fiecare poziţie dintre cele $N$ nu trece decât o singură dată prin deque şi este şters tot cel mult o singură dată. \r\n\r\nÎn practică, pseudocodul poate arăta în felul următor:\r\n\r\n== code(cpp) |\r\n// S şirul de numere iniţial şi N lungimea sa\r\n\r\nSubalgoritmul push_in(deque, întreg p, funcţia fct) este:\r\n    cât timp (!deque.empty() şi fct(S[p], S[deque.back()])) execută\r\n        deque.pop_back();\r\n    deque.push_back(p);\r\nSfârşit;\r\n\r\nFuncţia query(deque, întreg j) este:\r\n    cât timp (!deque.empty() şi deque.front() <= j) execută\r\n        deque.pop_front();\r\n    return S[deque.front()];\r\nSfârşit;\r\n\r\nAlgoritmul este:\r\n    lg = 0;\r\n    pentru i = 1, N execută\r\n        // funcţia min(a, b) întoarce true dacă a < b\r\n        inserează(min_deq, i, min);\r\n        // funcţia max(a, b) întoarce true dacă a > b\r\n        inserează(max_deq, i, max);\r\n        cât timp ((j < i - Y sau query(max_deq, j) - query(min_deq, j) > Z) şi j < i - X) execută\r\n            j = j + 1;\r\n        // (j, i] este intervalul candidat la soluţia optimă pentru poziţia i\r\n        dacă (j <= i - X) şi (query(max_deq, j) - query(min_deq, j) <= Z) atunci\r\n            dacă (lg >= i - j) atunci\r\n                lg = i - j, start = j + 1, stop = i;\r\n    sfârşit_pentru\r\n\r\n    dacă (lg > 0) atunci\r\n        scrie lg, start, stop;\r\n    altfel\r\n        scrie -1;\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală va fi $O(N)$.\r\n\r\nh2(#problema-4). 4. \'Platforma\':http://campion.edu.ro/problems/3/509/platforma_ro.htm (.campion, 2009)\r\n\r\nbq. Se dă o matrice $P$ de dimensiuni $M x N$ cu elemente numere întregi. Se defineşte valoarea maximă dintr-un dreptunghi de dimensiuni $R x C$ ca fiind valoarea maximă dintre elementele aflate în acel dreptunghi.\r\nCerinţă: Să se găsească un dreptunghi de dimensiuni $R x C$ cu valoarea maximă minimă.\r\nRestricţii: $1 &le; M, N &le; 1000$, $1 &le; R &le; M$, $1 &le; C &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nAceastă problemă reprezintă o extindere în două dimensiuni a problemei anterioare \'Vila 2\':deque-si-aplicatii#problema-2, unde am studiat cazul unidimensional al determinării pe un vector a maximului / minimului pentru fiecare subsecvenţă de o lungime fixată.\r\n\r\nCerinţa constă în amplasarea unui dreptunghi $R x C$ astfel încât valoarea maximă din interiorul său să fie cât mai mică. Una din ideile simple constă în fixarea colţului din stânga sus în toate cele $(M - R) x (N - C)$ poziţii şi determinarea maximului din interiorul său cu o altă parcurgere a celor $R x C$ elemente. Dar, să fixăm o linie $i$. Atunci, pentru a fixa colţul din stânga sus mai iterăm cu un indice $j$ între coloanele $1$ şi $N-C+1$. De aici devine clar că atunci când avansăm indicele coloanei în dreptunghiul curent apare o nouă coloană, $j + C$, şi dispare coloana curentă $j$. Dacă pentru fiecare coloană $j$ de pe linia curentă $i$ reţinem un $Max{~i,j~}$ egal cu maximul dintre elementele $P{~i,j~}, P{~i+1,j~},.. P{~i+R-1,j~}$, atunci pe linia fixată $i$ vom avea un vector din $N$ elemente (numărul de coloane al matricei $P$) alcătuit din valorile $Max{~i,1~}, Max{~i,2~}, Max{~i,3~},.. Max{~i,j~},.. Max{~i,N-1~}, Max{~i,N~}$. Iar pe acest vector va trebui să determinăm pentru fiecare subsecvenţă de $C$ elemente, valoarea maximă. Dintre toate subsecvenţele o vom alege pe cea cu valoarea maximă cea mai mică. Iar acest rezultat va fi o soluţie pentru linia fixată. Cu valorile din $Max$ precalculate, pentru fiecare linie avem complexitatea $O(N)$, deci $O(M * N)$ pentru întreaga matrice. Însă, implementând direct, valorle din $Max$ se calculează în $O(M * N * R)$. Mai sus am definit $Max{~i,j~}$ ca fiind maximul dintre $P{~i,j~}, P{~i+1,j~},.. P{~i+R-1,j~}$. Rezultă că $Max{~i+1,j~}$ este maximul dintre $P{~i+1,j~}, P{~i+2,j~},.. P{~i+R-1,j~}, P{~i+R,j~}$, adică maximul dintre elementele lui $Max{~i,j~}$ din care scoatem $P{~i,j~}$ şi adăugăm $P{~i+R,j~}$. De aici deducem că pentru fiecare coloană fixată, valorile lui $Max$ de pe coloana respectivă se reduc la a determina pentru fiecare subsecvenţă de lungime $R$ (numărul de linii al dreptunghiului de amplasat) elementul maxim. Aceste rezultate se obţin în $O(M)$ pentru fiecare coloană, deci $O(N * M)$ în total.\r\n\r\nRezultă complexitatea finală $O(M * N)$.\r\n\r\nh2(#problema-5). 5. \'Trans\':problema/trans (ONI 2004)\r\n\r\nbq. Se dau $N$ blocuri de piatră, de culoare albă sau neagră aşezate în ordinea $1$, $2$,.., $N$. Blocurile de piatră trebuie să fie transportate în ordinea în care sunt, iar pentru aceasta va trebui închiriat un camion. Se mai dau $Q$ tipuri de camioane. Camionul de tipul $i (1 &le; i &le; Q)$ poate transporta maxim $K{~i~}$ blocuri de piatră la un moment dat şi pentru un transport se percepe taxa $T{~i~}$. Se impune condiţia ca toate blocurile de piatră plasate în camion la un transport sa aibă aceeaşi culoare. Aşadar, pentru a fi transportate toate blocurile, se va alege un camion de un anumit tip, iar camionul va efectua unul sau mai multe transporturi. Pentru a micşora suma totală plătită, există posibilitatea de a schimba culoarea oricărui bloc de piatră (din alb în negru sau din negru în alb); pentru fiecare bloc $i (1 &le; i &le; N)$ se cunoaşte suma $S{~i~}$ ce trebuie plătită pentru a-i schimba culoarea $C{~i~}$.\r\nCerinţă: Pentru fiecare dintre cele $Q$ tipuri de camioane, determinaţi suma minimă plătită pentru a transporta toate cele $N$ blocuri.\r\nRestricţii: $1 &le; N &le; 16 000$, $1 &le; Q &le; 100$, $1 &le; K{~i~} &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se bazează pe găsirea unei formule de recurenţă ce respectă principiul optimalităţii al metodei programării dinamice.\r\n\r\nPentru început, fixăm un camion dintre cele <tex> Q </tex>. Fie <tex> K </tex> numărul maxim de pietre pe care acesta le poate transporta şi <tex> T </tex> taxa percepută. Notăm <tex> sum_{i,c} </tex> costul pentru a schimba toate pietrele <tex> 1, 2, \\ldots, i </tex> în culoarea <tex> c </tex> (<tex> c = 0 </tex> pentru alb şi <tex> c = 1 </tex> pentru negru). Rezultă că în <tex> sum_{i,c} </tex> se vor însuma toate valorile <tex> S_{j} </tex>, cu <tex> j \\le i </tex> pentru care <tex> C_{j} = 1 - c </tex>. \r\n\r\nÎn continuare, considerăm <tex> bst_{i,c} </tex> costul minim pentru a transporta pietrele <tex> 1, 2, \\ldots, i </tex>, iar ultimul transport conţine pietre de culoare <tex> c </tex>. Întrucât nu putem transporta mai mult de <tex> K </tex> pietre, <tex> bst_{i,c} </tex> depinde doar de poziţiile <tex> i - K, i - K + 1, \\ldots, i - 1 </tex>. Cunoaştem că ultimul camion va transporta o secvenţă continuă de pietre începând de la o poziţie <tex> j + 1 </tex> până la poziţia <tex> i </tex>, unde <tex> i - K \\le j \\le i - 1 </tex>. Astfel, pentru  fiecare <tex> j </tex> în intervalul precedent, costul va fi <tex> Min(bst_{j,0}, bst_{j,1}) </tex> (transportăm primele <tex> j </tex> pietre cât mai ieftin) adunat cu <tex> sum_{i,c} - sum_{j,c} </tex> (costul transformării pietrelor <tex> j + 1, \\ldots, i </tex> în culoarea <tex> c </tex>) şi plus taxa <tex> T </tex>. Rezultă recurenţa:\r\n\r\n* <tex> bst_{i,c} = Min\\ \\{\\ Minim(bst_{j,0},\\ bst_{j,1}) + sum_{i,c} - sum_{j,c} + T\\ :\\ i - K \\le j \\le i - 1\\ \\}; </tex>\r\n\r\nDacă ne vom opri aici, complexitatea soluţiei va fi <tex> O(Q * N^{2}) </tex>.\r\n\r\nRelaţia de recurenţă poate fi îmbunătăţită. Observăm că pentru poziţia <tex> i </tex>, <tex> sum_{i,c} </tex> este o valoare constantă, ca şi <tex> T </tex>. Astfel, deducem următoarea relaţie de recurenţă:\r\n\r\n* <tex> bst_{i,c} = Min\\ \\{\\ Minim(bst_{j,0},\\ bst_{j,1}) - sum_{j,c}\\ :\\ i - K \\le j \\le i - 1\\ \\} + sum_{i,c} + T; </tex>\r\n\r\nNotez în continuare, pentru uşurinţă în scriere, <tex> T_{j,c} = Min(bst_{j,0}, bst_{j,1}) - sum_{j,c} </tex>. Să fixăm doi indici <tex> i_{1} </tex> şi <tex> i_{2} </tex>, astfel încât <tex> i - K \\le i_{1} < i_{2} \\le i - 1 </tex>. Dacă <tex> T_{i_{1},c} > T_{i_{2},c} </tex> atunci întotdeauna poziţia <tex> i_{2} </tex> va fi preferată poziţiei <tex> i_{1} </tex>. Când cele două nu se vor mai afla ambele în intervalul <tex> [i - K, i - 1] </tex>, poziţia eliminată va fi poziţia <tex> i_{1} </tex>. Dacă <tex> T_{i_{1},c} < T_{i_{2},c} </tex>, atunci nu putem decide care poziţie este mai bună în viitor, aşa că le vom păstra pe ambele. Rezultă mai departe că în intervalul <tex> [i - K, i - 1] </tex> vom avea o serie de indecşi candidaţi la minim <tex> i - K \\le i_{1} < i_{2} < \\ldots < i_{n} \\le i - 1 </tex> astfel încât <tex> T_{i_{1},c} < T_{i_{2},c} <  .. < T_{i_{n},c} </tex>. Mai departe, găsim <tex> bst_{i,c} = T_{i_{1},c} + sum_{i,c} + T </tex>. Urmează să îl introducem şi pe <tex> T_{i,c} </tex> în şirul de indecşi de mai sus, el fiind egal cu <tex> Minim(bst_{i,0}, bst_{i,1}) - sum_{i,c} </tex>. Acest lucru se va face în felul următor: se vor elimina din <tex> i_{n}, , i_{n-1}, \\ldots </tex> atâta timp cât <tex> T_{i_{n},c} > T_{i,c} </tex>, <tex> T_{i_{n-1},c} > T_{i,c} \\ldots </tex> adică atâta timp cât poziţia <tex> i </tex> este preferată lui <tex> i_{n}, i_{n-1}, \\ldots </tex>. Fiind la poziţia <tex> i + 1 </tex>, intervalul se va transforma în <tex> [i - K + 1, i] </tex>, aşadar, vom mai elimina din primii indici <tex> i_{1}, i_{2}, \\ldots </tex> atâta timp cât <tex> i_{1} < i - K + 1, i_{2} < i - K + 1, \\ldots </tex>.\r\n\r\nDupă cum am arătat şi la problema precedentă, acest şir de indecşi <tex> i_{1}, i_{2}, \\ldots, i_{n} </tex> are proprietatea că este un şir continuu de numere care admite inserări prin dreapta (tail) şi ştergeri prin stânga (head). Şir ce poate fi reprezentat printr-un deque. Cum fiecare index dintre <tex> 1, 2, \\ldots, N </tex> va trece o singură dată prin deque, complexitatea soluţiei va fi <tex> O(N) </tex> pentru fiecare camion, deci <tex> O(Q * N) </tex> în total.\r\n\r\nÎn practică, programul este scurt, clar şi eficient:\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\n#include <vector>\r\n#include <deque>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\nconst char iname[] = \"trans.in\";\r\nconst char oname[] = \"trans.out\";\r\n\r\n#define MAXN  16005\r\n#define Min(a, b) ((a) < (b) ? (a) : (b))\r\n#define FOR(i, a, b)  for (int i = (a); i <= (b); ++ i)\r\n\r\nint C[MAXN], S[MAXN], bst[MAXN][2], sum[MAXN][2], N;\r\n\r\nvoid insert(deque < pair <int, int> >& deq, const pair <int, int>& p) {\r\n    while (!deq.empty() && deq.back().second > p.second)\r\n        deq.pop_back();\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque < pair <int, int> >& deq, const int idx) {\r\n    while (deq.front().first < idx)\r\n        deq.pop_front();\r\n    return deq.front().second;\r\n}\r\n\r\nint work(const int K, const int T) {\r\n    deque < pair <int, int> > deq[2];       // pair (idx, value)\r\n    FOR (c, 0, 1)\r\n        insert(deq[c], pair <int, int>(0, 0));\r\n    FOR (i, 1, N) {   // obiectul i\r\n        FOR (c, 0, 1) // culoare\r\n            bst[i][c] = query(deq[c], i - K) + sum[i][c] + T;\r\n        FOR (c, 0, 1)\r\n            insert(deq[c], pair <int, int>(i, Min(bst[i][0], bst[i][1]) - sum[i][c]));\r\n    }\r\n    return Min(bst[N][0], bst[N][1]);\r\n}\r\n\r\nint main(void)\r\n{\r\n    ifstream in(iname);  ofstream out(oname);\r\n    in >> N;\r\n    FOR (i, 1, N) {\r\n        in >> C[i] >> S[i];\r\n        FOR (c, 0, 1)\r\n            sum[i][c] += sum[i - 1][c];\r\n        sum[i][1 - C[i]] += S[i];\r\n    }\r\n    int cnt, K, T;\r\n    in >> cnt;\r\n    FOR (i, 1, cnt)\r\n        in >> K >> T, out << work(K, T) << \"\\n\";\r\n\r\n    in.close(), out.close();\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#problema-6). 6. \'Otilia\':problema/otilia  (.campion, 2005)\r\n\r\nbq. Otilia şi Burbucel au o grămadă de $N$ pietre şi vor juca un joc cu următoarele trei reguli: 1. Primul jucător are voie să ia din gramadă cel mult $K$ piese; 2. Cu excepţia primei mutări, fiecare jucător are voie să ia maxim $P * t$ pietre, unde $t$ este numărul de pietre care au fost substituite din grămadă la mutarea precedentă; 3. Pierde cel care mută ultimul (cel care ia ultimele pietre din grămadă).\r\nCerinţă: Se dau $M$ jocuri prin numerele $N$, $K$ şi $P$. Se cere să se determină dacă Otilia va câştiga fiecare din jocuri sau nu.\r\nRestricţii: $1 &le; M &le; 30 000$, $1 &le; N &le; 5 000 000$, $1 &le; K &le; N$, $1 &le; P &le; 10$.\r\n\r\nh3. Soluţie (Silviu Ganceanu):\r\n\r\nProblema se rezolvă prin programare dinamică. Soluţia se bazează pe observaţia de mai jos. Considerăm $P$-ul fixat şi notăm cu $stare(X, Y)$ poziţia de start în care avem $X$ pietre şi numărul maxim de pietre care se pot lua la prima mutare este $Y$.\r\n\r\n_Observaţia 1_: „Dacă există strategie sigură de câştig pentru $stare(X, Y)$ atunci există şi pentru orice $stare(X, T)$ cu $T &ge; Y$.” \r\n\r\nDe ce? Pentru că orice mutare validă pentru $stare(X, Y)$ este validă şi pentru $stare(X, T)$. Având această observaţie notăm cu $MinY[X] = Y$, $Y$ minim astfel încât avem strategie de câştig pentru $stare(X, Y)$.\r\n\r\n_Observaţia 2_: „{$stare(X, Y)$} este pierzătoare dacă şi numai dacă $Y < MinY[X]$.” \r\n\r\nAceasta reiese din definiţia lui $MinY[X]$.\r\n\r\n$MinY[X]$ se calculează după următoarea recurenţă, care rezultă din regulile jocului: \r\n\r\n* $MinY[X]$ este cel mai mic $i$ pentru care avem $MinY[X - i] > P * i$.\r\n\r\nDe aici se naşte prima soluţie, care este implementarea directă a recurenţei. Deşi complexitatea acesteia pare a fi $O(N^2^)$ ea se comportă foarte bine pentru $N &le; 500 000$. Aşadar, această soluţie acoperă aproximativ $50%$ din testele de intrare. Printr-o rafinare a acestei soluţii se obţine un algoritm de complexitate $O(N)$. Rafinarea se bazează pe: \r\n\r\n_Observaţia 3_: „Să presupunem că dorim să calculăm $MinY[X]$. Facem următoarea afirmaţie: orice poziţie _rea_ pentru $X$ (în care dacă mutăm pierdem) va fi _rea_ şi pentru $X + 1$.”\r\n\r\nAcest lucru este simplu de observat dacă privim ce înseamnă că o poziţie $Q$ e rea pentru $X$: \r\n\r\n* $MinY[Q] > X - Q$, pentru $X$;\r\n* $MinY[Q] > X - Q + 1$, pentru $X + 1$.\r\n\r\nEste evident că prima relaţie o implică pe cea de-a doua. În momentul acesta se poate construi următorul algoritm: având lista de poziţii care pot fi bune pentru $X$ (sortată descrescător) o căutăm pe cea mai mare ca valoare care este într-adevăr bună. În principiu, scoatem din capul listei poziţiile rele până când dăm de o poziţie bună. La listă se va adăuga şi $X$ şi se va trece la pasul următor. Operaţiile algoritmului sunt chiar operaţiile asupra unui deque.\r\n\r\nh2(#problema-7). 7. \'Bcrc\':problema/bcrc (Stelele Informaticii, 2006)\r\n\r\nbq. Se consideră $N$ camere, numerotate de la $1$ la $N$, aşezate în cerc. Iniţial (la momentul de timp 0), ne aflăm în camera $1$. În fiecare moment de timp, putem alege să rămânem în camera în care ne aflăm sau să ne deplasăm într-o cameră vecină într-o unitate de timp. Se dă o listă de $M$ cutii ce conţin bomboane prin $T$, $C$ şi $B$: cutia apare la momentul $T$ în camera $C$ şi conţine $B$ bomboane. Cutia va dispărea la momentul $T + 1$.\r\nCerinţă: Cunoscând numărul de camere din labirint şi momentele de timp la care apar cutiile cu bomboane, determinaţi care este numărul maxim de bomboane pe care le putem culege.\r\nRestricţii: $3 &le; N &le; 2 048$, $0 &le; M &le; 50 000$, $1 &le; T &le; 1 000 000 000$, $1 &le; C &le; N$, $1 &le; B &le; 9 999$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia foloseşte metoda programării dinamice.\r\n\r\nO stare se reprezintă prin camera în care ne aflăm şi momentul de timp. Fie <tex> bst_{i,j} </tex> numărul maxim de bomboane culese până în momentul <tex> i </tex> când ne găsim în camera <tex> j </tex>. O observaţie evidentă este că <tex> bst_{i,j} </tex> se poate modifica doar în momentele în care apar cutiile. Prin urmare, vom considera momentele de timp când apar cutiile, momente ce sunt în număr de <tex> M </tex>, <tex> bst_{i,j} </tex> însemnând numărul maxim de bomboane culese ştiind că ne aflăm în camera <tex> j </tex> unde am cules cutia <tex> i </tex>. De cine depinde această stare? Ştim că <tex> bst_{i-1,1 \\ldots N} </tex> a fost deja calculat în mod optim. Să notăm cu <tex> T </tex> diferenţa de timp dintre momentele la care apare cutia <tex> i </tex> şi cutia <tex> i - 1 </tex>. În această stare, <tex> i </tex> şi cameră <tex> j </tex>, putem ajunge din maxim <tex> T </tex> camere spre stânga sau spre dreapta, întrucât fiecare deplasare între două camere costă o unitate de timp. De unde deducem că:\r\n\r\n* <tex> bst_{i,j} = Min\\{\\ bst_{i-1,j-T},\\ bst_{i-1,j-T+1}, \\ldots,\\ bst_{i-1,j}, \\ldots,\\ bst_{i-1,j+T-1},\\ bst_{i-1,j+T}\\ \\}; </tex>\r\n\r\nMetoda directă, şi aparent eficientă, constă în folosirea unui arbore de intervale pentru aflarea acestui minim. Însă, intervalul <tex> [j-T,j+T] </tex> se deplasează constant spre dreapta, dacă vom considera indicii <tex> j </tex> în ordine <tex> 1, 2, 3, \\ldots </tex>. În acest interval noile elemente se introduc prin dreapta şi altele se elimină prin stânga. Însă, cum am arătat în problemele precedente, nu avem nevoie de toate valorile din acest interval. Şi din acest motiv vom folosi un deque de lungime <tex> T * 2 + 1 </tex> cu care vom elimina poziţiile care nu sunt candidate la soluţie. Mai jos este o reprezentare grafică a acestei explicaţii.\r\n\r\np=. !deque-si-aplicatii?bcrc.png 40%!\r\n\r\nComplexitatea finală: <tex> O(M * N) </tex>.\r\n\r\nh2(#problema-8). 8. \'Cut the Sequence\':http://acm.pku.edu.cn/JudgeOnline/problem?id=3017 (PKU) \r\n\r\nbq. Se dă o secvenţă $S$ de numere întregi de lungime $N$. Va trebui să se împartă secvenţa în mai multe subsecvenţe astfel încât suma valorilor din fiecare parte să nu depăşească un număr întreg $M$ dat, iar dacă însumăm maximul din fiecare subsecvenţă să obţinem o sumă cât mai mică.\r\nRestricţii: $0 &lt; N &le; 100 000$, $0 &le; S{~i~} &le; 1 000 000$.\r\n\r\nh3. Soluţie:\r\n\r\nŞi această soluţie foloseşte metoda programării dinamice. Construim <tex> bst_{i} </tex> egal cu costul minim de a împărţi primele <tex> i </tex> numere din <tex> S </tex>. Pentru a calcula <tex> bst_{i} </tex> alegem toate secvenţele posibile care încep la o poziţie <tex> j+1 </tex>, <tex> j < i </tex>, şi adunăm valorile corespunzătoare:\r\n\r\n* <tex> bst_{i} = Min\\{bst_{j} + Max\\{S_{j+1},.., S_{i}\\}\\ :\\ 0 \\le j < i, \\displaystyle\\sum_{k=j+1}^{i} S_{k} \\le M\\}; </tex>\r\n\r\nImplementarea directă a acestei recurenţe conduce la un algoritm de complexitate <tex> O(N^{2}) </tex>, dar care pentru restricţiile impuse nu este de ajuns.\r\n\r\nSă obţinem în continuare alte informaţii. Fie indicele <tex> j </tex> minim astfel încât <tex> \\displaystyle\\sum_{k=j+1}^{i} \\le M </tex>. Maximul obţinut din mulţimea <tex> \\{S_{j+1},.., S_{i}\\} </tex> se găseşte pe o poziţie <tex> j^{\'} </tex> unde <tex> j < j^{\'} \\le i </tex>. Însă, orice indice <tex> k </tex> cu <tex> j \\le k < j^{\'} </tex> are proprietatea că rezultatul expresiei <tex> Max\\{S_{k+1},.., S_{i}\\} </tex> se găseşte pe poziţia <tex> j^{\'} </tex>. Rezultă că <tex> \\forall k \\in \\{j, j+1,.., j^{\'}-1\\} </tex>, <tex> bst_{i} </tex> poate fi îmbunătăţit cu valoarea <tex> bst_{k} + S_{j^{\'}} </tex>. Minimul mulţimii <tex> \\{bst_{k} + S_{j^{\'}} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} </tex> este egal cu minimul expresiei <tex> \\{bst_{k} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} + S_{j^{\'}} (*) </tex>, deci, schimbând reperele, pentru maximul de pe poziţia <tex> j^{\'} </tex>, dacă lungimea secvenţei care se termină în <tex> i </tex> este cel puţin <tex> i-j^{\'}+1 </tex>, atunci optimul se obţine calculând rezultatul expresiei <tex> (*) </tex>. Pentru minimul pe un interval, <tex> [j, j^{\'}-1] </tex> al valorile vectorului <tex> bst </tex>, putem folosi un arbore de intervale pentru <tex> O(log_{2}N) </tex> pe interogare.\r\n\r\nDar, lungimea optimă a ultimei secvenţe ce se termină în <tex> i </tex> poate fi mai mică decât <tex> i-j^{\'}+1 </tex>, deci poate fi cel mult <tex> i-j^{\'} </tex>. Optimul se găseşte printre elementele mulţimii <tex> \\{bst_{k} + Max\\{S_{k+1},..,S_{i}\\} : j^{\'} \\le k < i\\} </tex>. Dacă procedăm ca la pasul anterior vom obţine un alt indice <tex> j^{\'\'} </tex> cu aceleaşi proprietăţi pentru secvenţa <tex> [j^{\'}, i] </tex> precum <tex> j^{\'} </tex> pentru secvenţa <tex> [j, i] </tex>.\r\n\r\nInductiv obţinem un şir de indici <tex> j_{0} = j < j_{1} < j_{2} < .. < j_{K} = i </tex> astfel încât <tex> S_{j_{1}} </tex> este cel mai mare element al secvenţei <tex> (j, i] </tex>, <tex> S_{j_{2}} </tex> cel mai mare element al secvenţei <tex> (j_{1}, i] </tex>, şi aşa mai departe, când <tex> j_{K} </tex> este chiar <tex> i </tex>.\r\n\r\nCu ajutorul relaţiei <tex> (*) </tex> şi a şirului <tex> j_{1} < j_{2} < .. < j_{K} = i </tex> vom construi un alt vector <tex> iMin </tex> cu proprietatea că <tex> iMin_{p} = Min\\{bst_{r} + S_{j_{p}} : j_{p-1} \\le r < j_{p}\\} </tex>. În final, <tex> bst_{i} = Minim\\{iMin_{1}, iMin_{2}, .., iMin_{K}\\} </tex>, rezultat pe care îl putem obţine în <tex> O(log_{2}N) </tex> dacă folosim un arbore de intervale.\r\n\r\nÎnsă, cum se construieşte şirul <tex> j_{1} < j_{2} < .. < j_{K} = i </tex>? În \'a doua problemă\':deque-si-aplicatii#problema-2 am construit cu ajutorul unui deque exact şirul de indici de care avem nevoie aici. Când vom înainta la indicele <tex> i + 1 </tex> vom modifica şirul astfel încât să respecte proprietăţile de mai sus utilizând operaţiile normale asupra unui deque. Mai sus am menţionat cum se obţine <tex> bst_{i} </tex> lucru care implică combinarea structurilor de deque şi arbore de intervale. Arborele de intervale reţine valorile lui <tex> iMin </tex> pentru fiecare element al dequelui. \r\n\r\nPentru a înţelege cum funcţionează acest algoritm să considerăm ca date de intrare şirul <tex> S = \\{5, 9, 4, 7, 4, 1, 6, 3\\} </tex> şi <tex> M = 15 </tex>. Perechile din deque sunt de forma <tex> (S_{i}, iMin_{p}) </tex>. Fie <tex> i = 1, 2, \\ldots 8 </tex>:\r\n\r\n* <tex> i = 1: j = 0, head = 1, tail = 1, deque = \\{\\ (5, 0)\\ \\} \\Rightarrow bst_{1} = 5; </tex>\r\n* <tex> i = 2: j = 0, head = 1, tail = 1, deque = \\{\\ (9, 0)\\ \\} \\Rightarrow bst_{2} = 9; </tex>\r\n* <tex> i = 3: j = 1, head = 1, tail = 2, deque = \\{\\ (9, 5),\\ (4, 9)\\ \\} \\Rightarrow bst_{3} = 13; </tex>\r\n* <tex> i = 4: j = 2, head = 2, tail = 2, deque = \\{\\ (7, 9)\\ \\} \\Rightarrow bst_{4} = 16; </tex>\r\n* <tex> i = 5: j = 2, head = 2, tail = 3, deque = \\{\\ (7, 9),\\ (4, 16)\\ \\} \\Rightarrow bst_{5} = 16; </tex>\r\n* <tex> i = 6: j = 3, head = 2, tail = 4, deque = \\{\\ (7, 13),\\ (4, 16),\\ (1, 16)\\ \\} \\Rightarrow bst_{6} = 17; </tex>\r\n* <tex> i = 7: j = 4, head = 3, tail = 3, deque = \\{\\ (6, 16)\\ \\} \\Rightarrow bst_{7} = 22; </tex>\r\n* <tex> i = 8: j = 4, head = 3, tail = 4, deque = \\{\\ (6, 16),\\ (3, 22)\\ \\} \\Rightarrow bst_{8} = 22; </tex>\r\n\r\nMai jos se vede o figură în care elementele unui deque sunt defapt o secvenţă „continuă” de frunze ale unui arbore de intervale pentru cazul <tex> i = 6 </tex>.\r\n\r\np=. !deque-si-aplicatii?PKU0.png 60%!\r\n\r\np=. _Numărul maxim de elemente ce pot trece prin deque este $8$. În figură, arborele ţine minimul de pe poziţiile $2$, $3$, $4$ din deque._\r\n\r\nAlgoritmul în pseudocod arată în felul următor:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    sum  = 0;\r\n    last = 0;\r\n    // indicii head si tail ai dequeului\r\n    head = tail = 1;\r\n    // poziţia lui bst[0] se inserează în deque\r\n    deque[1] = 0;\r\n    pentru i = 1, N execută\r\n        sum += S[i];\r\n        temp = bst[ deque[tail] ];\r\n        cât timp (head <= tail) şi (S[ deque[tail] ] <= S[i]) execută\r\n            temp = Min(temp, iMin[tail]);\r\n            tail --;\r\n        sfârşit;\r\n        // adaug poziţia i la deque\r\n        tail ++;\r\n        deque[tail] = i;\r\n        // actualizez iMin[]\r\n        iMin[tail]  = temp;\r\n        // actualizez T[], arborele de intervale pe deque[]\r\n        Update(T, tail, iMin[tail] + S[i]);\r\n        // suma valorilor din [last, i] trebuie să nu depăşească M\r\n        cât timp (sum > M) execută\r\n            sum -= S[last];\r\n            dacă (deque[head] == last) atunci\r\n                head ++;\r\n            sfârşit;\r\n            last ++;\r\n        sfârşit;\r\n        // actualizez iMin[], Tb[] arborele de intervale pe bst[]\r\n        iMin[head] = Query(Tb, Max(last - 1, 0), deque[head] - 1);\r\n        // actualizez T[]\r\n        Update(T, head, iMin[head] + S[ deque[head] ]);\r\n        // reţin optimul pentru poziţia curentă\r\n        bst[i] = Query(T, head, tail);\r\n        // actualizez Tb[]\r\n        Update(Tb, i, bst[i]);\r\n    sfârşit;\r\n    scrie bst[N];\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală este <tex> O(N*log_{2}N) </tex>.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nFilozofia din spatele structurii de deque devine utilă, de obicei, în părţile finale ale rezolvării unei probleme. Însă, ce pot spune cu certitudine este că această structură de date pe cât este de simplă pe atât este de eficientă şi necesară.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\nÎnţelegerea profundă nu se poate realiza decât prin rezolvarea a cât mai multe probleme. Succes!\r\n\r\n* \'Deque\':problema/deque, _Arhiva educaţională_\r\n* \'Secvenţă\':problema/secventa\r\n* \'Secvenţă 3\':problema/secv3\r\n* \'Secvenţă 4\':problema/secv4\r\n* \'Sum 2\':problema/sum2, _Stelele Informaticii, 2003_\r\n* \'Drept 2\':problema/drept2, _Lotul Naţional de Informatică, 2006_\r\n* \'Copaci 2\':problema/copaci2, _.campion, 2007_\r\n* \'Struţi\':problema/struti\r\n* \'Brânză\':problema/branza\r\n* \'Trompetă\':problema/trompeta\r\n* \'Buline\':problema/buline\r\n* \'Balans\':problema/balans\r\n* \'Ksecv\':problema/ksecv, _Selecţie echipe ACM ICPC, UPB, 2008_\r\n* \'Munte4\':problema/munte4, _Lotul Naţional de Informatică, 2005_\r\n* \'Gard\':problema/gard, _ONI, 2002_\r\n* \'Ghiozdan\':problema/ghiozdan\r\n* \'Cover\':problema/cover, _Baraj ONI, 2007_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Cosmin Negruşeri, \"_Probleme cu secvenţe_\":probleme-cu-secvente\r\n# Dana Lica, \"_Arbori de intervale şi aplicaţii în geometria computaţională_\":arbori-de-intervale\r\n# Cătălin Frâncu, \"_Heapuri_\":heapuri\r\n# Marius Stroe, \"_Treapuri_\":treapuri\r\n# \'C++ Reference\':http://www.cplusplus.com/',3146,'public',NULL,NULL),('junior-challenge/clasament','junior_challenge/clasament','2007-06-29 20:09:04','2007-07-04 09:03:08','h1. == roundparam(round_id=\"Junior_Challenge\" param=\"title\") ==\r\n\r\n==include(page=\"templates/junior_head\")==\r\n\r\nAici este clasamentul pentru concursul _Junior Challenge_. Mai multe detalii despre concurs gasiti \'aici\':junior-challenge.\r\n\r\np<. == Rankings(rounds=\"junior_challenge\") == ',256,'protected',NULL,NULL);
 INSERT INTO `ia_textblock_revision` VALUES ('propuneri/12-infoarena.org','IAP #12: Infoarena.org','2009-02-17 11:16:13','2009-03-06 10:22:38','h1. IAP #12: Infoarena.org\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2009-02-17                             |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"alexthero\")== |\r\n|_. Stare     | *_IN-CONSTRUCTIE_*                     |\r\n\r\n(toc)*{text-align:center;} *Continut*\r\n* \'Abstract\':propuneri/12-infoarena.org#abstract\r\n* \'Motivatie\':propuneri/12-infoarena.org#motivatie\r\n* \'Implementare\':propuneri/12-infoarena.org#implementare\r\n* \'Traduceri\':propuneri/12-infoarena.org#traduceri\r\n* \'Alte proiecte\':propuneri/12-infoarena.org#alte-propuneri\r\n* \'Feedback\':propuneri/12-infoarena.org#feedback\r\n\r\nh2(#abstract). Abstract\r\n\r\nSe propune utilizarea softului deja existent pentru crearea unei versiuni infoarena in limba engleza, independenta ca si continut de infoarena.ro. Realizarea acestui proiect consta in implementarea modificarilor necesare la nivel de cod si traducerea continutului.\r\n\r\nh2(#motivatie). Motivatie\r\n\r\nMotivele si avantajele acestui proiect sunt multiple si evidente. Motivatia imediata o constituie organizarea Concursului Centrelor de Excelenta cu participare internationala (polonezi). Celelalte motive si avantaje:\r\n\r\n* organizarea de concursuri internationale\r\n* formarea unei comunitati internationale si cooptarea unor colaboratori internationali\r\n* potential acces la problemele si materialele de pregatire ale unor tari ca rusia, china, etc.\r\n* recunoasterea brandului infoarena la nivel international\r\n* access la o gama mai larga de eventuali sponsori\r\n\r\nh2(#implementare). Implementare\r\n\r\nO metoda usoara si rapid de pus in practica este sa punem sus codul si sa ne apucam sa traducem. Aceasta metoda are mai multe neajunsuri pe care vom incerca sa le rezolvam pe parcursul acestui document.\r\n\r\n1. Folosirea aceluiasi cod pe ambele site-uri si update-uri concomitente.\r\nUn punct important ar fi ca ambele site-uri sa poata fi updatate cu acelasi cod scris de \"hackerul infoarena\". Problema propriu zisa este intercalarea elementelor de limba cu cele de cod. Ca sa rezolvam aceasta problema ar trebui sa avem niste \"language files\", care sa contina toate frazele folosite in cod (tot in afara paginilor wiki). SMF are deja aceste fisiere, dar e posibil ca noi sa fi modificat cate ceva in versiunea romaneasca.\r\n\r\nAvantaje:\r\n\r\n* acelasi cod pentru ambele siteuri\r\n* extinderea usoara la mai multe limbi (doar prin modificarea unui language file)\r\n\r\nDezavantaje:\r\n\r\n* volum mult de munca bruta? trebuie trecut prin fiecare fisier si modificat tot textul\r\n\r\n2. Concursuri care pot fi date simultan pe ambele siteuri\r\nPornind de la motivatie, o intrebare care vine inevitabil este: \"cum dam concursuri simultan pe ambele siteuri\". O prima solutie ar fi crearea concursurilor pe ambele siteuri, cu probleme identice, dar traduse. Singura problema ar fi cum afisam clasamentele (cu concurenti de pe ambele siteuri). Ideal ar fi ca fiecare din cele 2 clasamente sa contina si userii care au submitat dincolo, dar cu un flag si cu link catre profilul lor. Putem avea username-uri identice, dar ele sa defineasca un alt utilizator.\r\n\r\nSolutie: definim un nou macro care (dandui-se linkurile dintre concursuri + probleme):\r\n\r\n* se conecteaza la baza de date a celuilalt site / un fisier xml public actualizat de celalalt site\r\n* afiseaza clasamentul concatenat\r\nTrebuie sa folosim aceasi metoda ca acum pentru a reda eficient clasamentele.\r\n\r\nAvantaje: \r\n\r\n* aparent rezolvam toate subproblemele care ar putea aparea la crearea concursurilor\r\n\r\nDezavantaje:\r\n\r\n* link inestetic catre profilul de pe celalalt site\r\n* multe linkuri catre acelasi site dauneaza la page ranking? nu sunt sigur\r\n\r\n3. Teste\r\n\r\nO alta informatie reduntanta sunt testele. Nu as fi mentionat acest lucru daca nu trimitea Bogdan e-mail-ul din 22 feb. Putem linka unele pagini intre ele, astfel incat atasamentele celor doua pagini sa fie aceleasi si mentinute o singura data. Totusi, pentru inceput, cred ca acest lucru nu e necesar.\r\n\r\n*O lista scurta cu ce trebuie implementat inainte sa ne apucam de tradus:*\r\n\r\n* language files\r\n* clasamente comune\r\n\r\nh2(#traduceri). Traduceri\r\n\r\nNe propunem sa traducem urmatoarele pentru prima versiune:\r\n\r\n* documentatia necesara pentru un utilizator care vrea sa rezolve probleme si sa participe la concurs\r\n* un set de 5 probleme reprezentative din arhiva de probleme (A+B, CMMDC, 3 mai grele..)\r\n* un set de 3 probleme reprezentative din arhiva educationala\r\n* 1-2 articole\r\n* forumul incepe de la 0\r\n\r\nVom crea un nou proiect marca infoarena, \"traduce infoarena\" in care cautam colaboratori. Acestia vor traduce continut. Fiecare e liber sa traduca in limita timpului disponibil.\r\n\r\nh2(#alte-proiecte). Localizare in alte proiecte open-source\r\n\r\nPHPbb\r\n\r\n* Exista language packs specializate pe diferite limbi. Fiecare language pack contine aceleasi fisiere, care reprezinta\r\nimpartirea tuturor frazelor folosite pe categorii. Fiecare fraza e definita de un text generic in engleza. e.g. \r\n\'SUBMIT_VOTE\' = \'Trimite vot\'.\r\n\r\nMediaWiki\r\n\r\n* Cate un fisier .php pentru fiecare limba care contine toate mesajele traduse. Din nou, fraza e definita de un text generic in \r\nengleza. \r\n* Ce e interesant la mediaWiki e ca au o metoda care returneaza mesajul in limba in functie de preferinte ( cred :) ). De exemplu, \r\ndaca preferintele sunt 1. Engleza 2. Romana 3. Germana, functia cauta prima data textul respectiv in engleza. Daca nu e gasit, cauta \r\nin romana, iar apoi in germana. Acest lucru s-ar aplica bine la infoarena.org, avem preferinte: 1. Engleza 2. Romana pentru \r\ninfoarena.org si preferinte: 1. Romana 2. Engleza pentru infoarena.ro. In cazul in care mesajul nu e gasit in prima limba, putem sa \r\ncoloram textul din aceasta functie in ceva saritor in ochi (rosu?) pentru a sti ca trebuie tradus. Putem sa facem acest lucru doar \r\npentru admini sau/si pentru helperi.\r\n\r\nWordpress\r\n\r\n* Cate un fisier .po sau .mo pentru fiecare limba. In fisierele acestea se gasesc comentarii pentru fiecare mesaj care spun unde\r\neste gasita fraza. Exemplu\r\n\r\n== code(c) |\r\n#: wp-admin/edit-pages.php:29\r\n#: wp-admin/edit-pages.php:32\r\n#: wp-admin/edit.php:37\r\n#: wp-admin/edit.php:40\r\n#: wp-admin/page.php:170\r\n#: wp-admin/page.php:173\r\n#: wp-admin/post.php:211\r\n#: wp-admin/post.php:214\r\n#: wp-admin/upload.php:84\r\n\r\nmsgid \"Error in deleting...\"\r\nmsgstr \"Eroare la stergere...\"\r\n==\r\n\r\nh2(#feedback). Feedback\r\n\r\nIntra pe \'forum\':forum/index.php?topic=3712.0 pentru a da feedback.',716,'public',3712,NULL),('sandbox','Sandbox (cutiuţa cu năsip)','2006-11-11 18:59:57','2009-03-11 11:49:23','h1=. Sandbox (cutiuţa cu năsip)\r\n\r\nlog me\r\n\r\nTabel mic:\r\n\r\ntable{width:60px}. |A|B|A->B|\r\n|&#48;|2|3|\r\n\r\nTabel mare:\r\n\r\ntable{width:120px}. |A|B|A->B|\r\n|1|2|3|\r\n\r\nTabel si mai mare:\r\n\r\ntable{width:240px}. |A|B|A->B|\r\n|1|2|3|\r\n\r\nDiacritice:\r\n\r\nStraşnic de îngâmfat, ţăranul crapă streaşina.\r\nStraşnic de îngâmfat, ţăranul crapă streaşina.\r\n\r\nIn Windows XP sp2 cu IE6 fara update de font se vede asa:\r\n!sandbox?diacritice-IE6.jpg!\r\n\r\nOrdered list:\r\n\r\n# 1st item\r\n# 2nd item\r\n\r\nh3. Use only F/OSS, Microsft sucks ;) just because they like design NOT the code itself.\r\n\r\nHowever, on a GNU system NEVER type <b>sudo make me sandwich</b> , and expect the results...\r\n\r\n\r\nx\r\n\r\n ==calendar()==\r\n\r\ny\r\n\r\n* A[1]\r\n* B[2]\r\n* C[3]\r\n\r\np(#fn1). <tex>2^n    * 2^n</tex>\r\n\"Vivi\'s blog\":http://vivi.ro\r\n<tex> d/(2\\\"a)=d/(2\\Omega^2) </tex>\r\n* <tex> d = \\sqrt{(c_{2}-c_{1})^{2} + 1 } </tex>\r\np. <tex> \r\n\\displaystyle \\sigma_{\\lambda} = \r\n	  \\frac{24 \\pi^3}{\\lambda^4 N^2}\r\n	  \\left(\\frac{n^2-1}{n^2+2}\\right)^{\\!2}\r\n</tex> \r\n\r\nAvem suport pentru <tex> \\LaTeX </tex> !\r\n\r\n<tex> \\frac{a^2 - b^2}{a + b} = a - b </tex>\r\n<tex>n! \\approx \\sqrt{2 \\pi n} (\\frac n e) ^n</tex>\r\n\r\n\r\n==Include(page=\"template/implica-te/scrie-articole\" user_id=\"domino\")==\r\n\r\np(#fn2). | test | test |\r\n\r\n\"User macro bug\":sandbox/usermacrobug\r\n\r\n*Worship me*\r\n\r\nFeel free to plghay around, but \'Big Brother\':/changes is watching you.\r\n\r\nTralalalala cu capsunele pe campii si elefanti pe ****** marete si ciupercute si bomboane.\r\n%{color:red}[ editat de% %{color:orange} o fata% %{color:red}] se impune o cenzură% %{color:orange}:D%\r\n\r\n\'codetest\':sandbox/code-test\r\n\r\nWhat does \'this\':sandbox?action=edit button do?\r\n\r\nlalallaa\r\n\r\nIntrebare: cum poti seta culoarea cu care scrii?\r\nUite asa: %{color:violet}scris cu rosu%\r\n\r\nSiteul sub IE 7 -- vezi \'pagina dedicata\':ia_in_ie7\r\n\r\nSiteul sub FF 2 - -mica problema panoul de \'editeaza\', \'vezi istoria\', \'sterge\' etc (in IE7 panoul nu se suprapune)-\r\n!sandbox?IA_bug_in_FF2.jpg!\r\n\r\n[test]\r\n*OMG* test, good work people :D\r\nAcuma doar trebuie putin stimulata comunitatea\r\n[/test]\r\n\r\nInteresting choice of words.\r\na very bold **MAN**\r\n_CAPSOMANII-I DESPISE THEM_\r\n\r\ngasise pe-un teren viran,\r\nun geamantan.\r\n\r\nsi-n geamantan,\r\nun pachet.\r\n\r\nsi in pachet,\r\nun pachetel gasise el.\r\n\r\nsi-n pachetel,\r\nalt pachetel.\r\n\r\nsi-un pachetel in pachetel,\r\nlegat cu funde elegante.\r\n\r\nsi-n pachetel...vreo 40 de diamante...\r\n...\r\nAdio voi...va las si plec fiindca mi-e dor...\r\nsi a plecat Apolodor\r\n!!!<>\r\n\r\ntralalala blablabla lala\r\n\r\n_salut, aici poate sa scrie oricine ce vrea?_ ~Robert~\r\n\r\n|_. 1|_. 2|_. 3|\r\n|unu|doi|trei|\r\n|1... unu|2... doi|3... trei|\r\n\r\nMoraru Ionut has been here. :))\r\n\r\n:) gosh...\r\n\r\ninca unul, de tipul cel mai         heyyyyyyyyyy prost din corcodus, se joaca cu  in nisip.. ura ...\r\ncel mai prost din corcodus a terminat... altcineva?:D\r\ntot el: atentie fratilor ne urmareste big brother 3 (sau 4)\r\n\r\n== code(cpp) |\r\n// comentariu\r\n#include <cstdio> // comment1\r\n// comment2\r\n\r\nint main()\r\n{\r\n    return 0;\r\n}\r\n==\r\n\r\nEu vreau să scriu cu ŢŢŢŢŢ dublu ţ mic şi tripul Ţ mare! Iată un Ţ ţŢŞ ! Are virgulă sau sedilă?',5700,'public',NULL,NULL),('planificare/sedinta-20090316','Sedinta 2009-03-16','2009-02-23 16:00:45','2009-03-11 06:36:19','h1. Sedinta 2009-03-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Martie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ...\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090216| ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"wickedman\" type=\"tiny\")==|\r\n|Concursul Centrelor de Excelenta/Concurs in engleza | ==user(user=\"filipb\" type=\"tiny\")== |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Recapitulare OKRs: suntem în grafic?| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n\r\n\r\nh2. Detalii\r\n\r\nh3. Misc\r\n\r\n* Donare calculatoare\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\nh2. Notiţe\r\n',2038,'protected',NULL,NULL),('utilizator/mathboy','Profil mathboy','2008-12-24 18:43:37','2009-03-12 19:45:47','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\nElev in clasa a IX-a D,Matematica-Informatica,Informatica Intensiv\r\n\r\n Colegiul National Unirea Focsani\r\n\r\nContact: dragos_mathboy@yahoo.com\r\n\r\nh2. Distinctii primite\r\n\r\nDeocamdata calificat la OJI 2009 Focsani clasa a 9-a\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n==user(user=\"bogdanhm999\" type=\"normal\")==\r\n\r\n==user(user=\"StefanGeo\" type=\"normal\")==\r\n\r\n==user(user=\"lucianvn\" type=\"normal\")==\r\n\r\n==user(user=\"bolovanemil\" type=\"normal\")==\r\n\r\n==user(user=\"rob3rtinho93\" type=\"normal\")==\r\n\r\n==user(user=\"DraStiK\" type=\"normal\")==\r\n',9232,'public',NULL,NULL),('planificare/sedinta-20090316','Sedinta 2009-03-16','2009-02-23 16:00:45','2009-03-15 16:44:48','h1. Sedinta 2009-03-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Martie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== (daca o sa mai fiti, eu o sa ajung dupa 20:00, am facultate)\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== (si eu o sa ajung un pic mai tarziu, am facultate)\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090216| ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Eval, server nou| ... |\r\n|Concursul Centrelor de Excelenta/Concurs in engleza | ==user(user=\"filipb\" type=\"tiny\")== |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Recapitulare OKRs: suntem în grafic?| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n\r\n\r\nh2. Detalii\r\n\r\nh3. Misc\r\n\r\n* Donare calculatoare\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\nh2. Notiţe\r\n',961,'protected',NULL,NULL),('planificare/sedinta-20090316','Sedinta 2009-03-16','2009-02-23 16:00:45','2009-03-15 19:39:37','h1. Sedinta 2009-03-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Martie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== (daca o sa mai fiti, eu o sa ajung dupa 20:00, am facultate)\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== (si eu o sa ajung un pic mai tarziu, am facultate)\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090216| ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Concursul Centrelor de Excelenta/Concurs in engleza | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Recapitulare OKRs: suntem în grafic?| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n\r\n\r\nh2. Detalii\r\n\r\nh3. Misc\r\n\r\n* Diacritice\r\n* Donare calculatoare\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\nh2. Notiţe\r\n',1851,'protected',NULL,NULL),('sandbox','Sandbox (cutiuţa cu năsip)','2006-11-11 18:59:57','2009-03-14 12:52:16','h1=. Sandbox (cutiuţa cu năsip)\r\n\r\nlog me\r\n\r\nTabel mic:\r\n\r\ntable{width:60px}. |A|B|A->B|\r\n|&#48;|2|3|\r\n\r\nTabel mare:\r\n\r\ntable{width:120px}. |A|B|A->B|\r\n|1|2|3|\r\n\r\nTabel si mai mare:\r\n\r\ntable{width:240px}. |A|B|A->B|\r\n|1|2|3|\r\n\r\n*Diacritice:*\r\n\r\nStraşnic de îngâmfat, ţăranul crapă streaşina.\r\nStraşnic de îngâmfat, ţăranul crapă streaşina.\r\n\r\nIn Windows XP sp2 cu IE6 fara update de font se vede asa:\r\n!sandbox?diacritice-IE6.jpg!\r\n\r\nOrdered list:\r\n\r\n# 1st item\r\n# 2nd item\r\n\r\nh3. Use only F/OSS, Microsft sucks ;) just because they like design NOT the code itself.\r\n\r\nHowever, on a GNU system NEVER type <b>sudo make me sandwich</b> , and expect the results...\r\n\r\n\r\nx\r\n\r\n ==calendar()==\r\n\r\ny\r\n\r\n* A[1]\r\n* B[2]\r\n* C[3]\r\n\r\np(#fn1). <tex>2^n    * 2^n</tex>\r\n\"Vivi\'s blog\":http://vivi.ro\r\n<tex> d/(2\\\"a)=d/(2\\Omega^2) </tex>\r\n* <tex> d = \\sqrt{(c_{2}-c_{1})^{2} + 1 } </tex>\r\np. <tex> \r\n\\displaystyle \\sigma_{\\lambda} = \r\n	  \\frac{24 \\pi^3}{\\lambda^4 N^2}\r\n	  \\left(\\frac{n^2-1}{n^2+2}\\right)^{\\!2}\r\n</tex> \r\n\r\nAvem suport pentru <tex> \\LaTeX </tex> !\r\n\r\n<tex> \\frac{a^2 - b^2}{a + b} = a - b </tex>\r\n<tex>n! \\approx \\sqrt{2 \\pi n} (\\frac n e) ^n</tex>\r\n\r\n\r\n==Include(page=\"template/implica-te/scrie-articole\" user_id=\"domino\")==\r\n\r\np(#fn2). | test | test |\r\n\r\n\"User macro bug\":sandbox/usermacrobug\r\n\r\n*Worship me*\r\n\r\nFeel free to plghay around, but \'Big Brother\':/changes is watching you.\r\n\r\n\'codetest\':sandbox/code-test\r\n\r\nWhat does \'this\':sandbox?action=edit button do?\r\n\r\nlalallaa\r\n\r\nIntrebare: cum poti seta culoarea cu care scrii?\r\nUite asa: %{color:violet}scris cu rosu%\r\n\r\nSiteul sub IE 7 -- vezi \'pagina dedicata\':ia_in_ie7\r\n\r\nSiteul sub FF 2 - -mica problema panoul de \'editeaza\', \'vezi istoria\', \'sterge\' etc (in IE7 panoul nu se suprapune)-\r\n!sandbox?IA_bug_in_FF2.jpg!\r\n\r\n[test]\r\n*OMG* test, good work people :D\r\nAcuma doar trebuie putin stimulata comunitatea\r\n[/test]\r\n\r\nInteresting choice of words.\r\na very bold **MAN**\r\n_CAPSOMANII-I DESPISE THEM_\r\n\r\ngasise pe-un teren viran,\r\nun geamantan.\r\n\r\nsi-n geamantan,\r\nun pachet.\r\n\r\nsi in pachet,\r\nun pachetel gasise el.\r\n\r\nsi-n pachetel,\r\nalt pachetel.\r\n\r\nsi-un pachetel in pachetel,\r\nlegat cu funde elegante.\r\n\r\nsi-n pachetel...vreo 40 de diamante...\r\n...\r\nAdio voi...va las si plec fiindca mi-e dor...\r\nsi a plecat Apolodor\r\n!!!<>\r\n\r\ntralalala blablabla lala\r\n\r\n_salut, aici poate sa scrie oricine ce vrea?_ ~Robert~\r\n\r\n|_. 1|_. 2|_. 3|\r\n|unu|doi|trei|\r\n|1... unu|2... doi|3... trei|\r\n\r\nMoraru Ionut has been here. :))\r\n\r\n:) gosh...\r\n\r\ninca unul, de tipul cel mai         heyyyyyyyyyy prost din corcodus, se joaca cu  in nisip.. ura ...\r\ncel mai prost din corcodus a terminat... altcineva?:D\r\ntot el: atentie fratilor ne urmareste big brother 3 (sau 4)\r\n\r\n== code(cpp) |\r\n// comentariu\r\n#include <cstdio> // comment1\r\n// comment2\r\n\r\nint main()\r\n{\r\n    return 0;\r\n}\r\n==\r\n\r\nEu vreau să scriu cu ŢŢŢŢŢ dublu ţ mic şi tripul Ţ mare! Iată un Ţ ţŢŞ ! Are virgulă sau sedilă?',75,'public',NULL,NULL),('planificare/sedinta-20090316','Sedinta 2009-03-16','2009-02-23 16:00:45','2009-03-16 15:49:52','h1. Sedinta 2009-03-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Martie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== (posibil sa intarzii vreo jumatate de ora)\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== (daca o sa mai fiti, eu o sa ajung dupa 20:00, am facultate)\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== (si eu o sa ajung un pic mai tarziu, am facultate)\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090216| ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Concursul Centrelor de Excelenta/Concurs in engleza | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Recapitulare OKRs: suntem în grafic?| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n\r\n\r\nh2. Detalii\r\n\r\nh3. Misc\r\n\r\n* Diacritice\r\n* Donare calculatoare\r\n* Algoritmiada 2009\r\n** Sponsori - Adobe, Microsoft\r\n** Data si locatia finalei\r\n** Invitatii concurenti\r\n** Materiale promotionale (tricouri)\r\n** Organizare tehnica\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\nh2. Notiţe\r\n',2028,'protected',NULL,NULL),('planificare/sedinta-20090316','Sedinta 2009-03-16','2009-02-23 16:00:45','2009-03-16 18:20:31','h1. Sedinta 2009-03-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Martie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== (posibil sa intarzii vreo jumatate de ora)\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== (daca o sa mai fiti, eu o sa ajung dupa 20:00, am facultate)\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== (si eu o sa ajung un pic mai tarziu, am facultate)\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090216| ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Concursul Centrelor de Excelenta/Concurs in engleza | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Recapitulare OKRs: suntem în grafic?| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n\r\n\r\nh2. Detalii\r\n\r\nh3. Misc\r\n\r\n* Diacritice\r\n* Donare calculatoare\r\n* Algoritmiada 2009\r\n** Sponsori - Adobe, Microsoft\r\n** Data si locatia finalei\r\n** Invitatii concurenti\r\n** Materiale promotionale (tricouri)\r\n** Organizare tehnica\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Silviu si Cristi concretizeaza IAP 7 (1 sedinta)\r\n* Mircea dă mail la Microsoft. Cristi oferă template.\r\n* Alexandra se ocupă de invitaţii, confirmări şi sosiri\r\n* Cosmin vorbeşte cu Malex să afle ce tool foloseşte pentru detectarea surselor identice şi în foloseşte.\r\n* Singura opţiune pentru finala Algoritmiada: 3-5 aprilie.\r\n* Wefgef face plan concret şi complet de acţiune pentru finală (pagină wiki)\r\n* Wefgef se ocupă de design de tricou (grafică vectorială!)\r\n* Vali şi Bogdan se ocupă pe partea tehnică la finala Algoritmiada\r\n* Vali se ocupă de diplome (design şi printare)\r\n* Buru porneşte un thread pe grup despre detaliile tehnice pentru recalculat timpii\r\n* Wefgef face listă cu ce trebuie instalat la Algoritmiada\r\n* Toata lumea citeşte IAP 12\r\n* Vali bagă backup (înpreună cu Cristi, Bogdan, Silviu)\r\n\r\n\r\nh2. Notiţe\r\n\r\n* Raportăm IAP pentru Vali.\r\n* Fără ketchup; e cancerigen.\r\n* La finala Algoritmiada se vine de joi.\r\n',1,'protected',NULL,NULL),('planificare/sedinta-20090316','Sedinta 2009-03-16','2009-02-23 16:00:45','2009-03-16 18:49:36','h1. Sedinta 2009-03-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Martie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== (posibil sa intarzii vreo jumatate de ora)\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== (daca o sa mai fiti, eu o sa ajung dupa 20:00, am facultate)\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== (si eu o sa ajung un pic mai tarziu, am facultate)\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090216| ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Concursul Centrelor de Excelenta/Concurs in engleza | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Recapitulare OKRs: suntem în grafic?| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n\r\n\r\nh2. Detalii\r\n\r\nh3. Misc\r\n\r\n* Diacritice\r\n* Donare calculatoare\r\n* Algoritmiada 2009\r\n** Sponsori - Adobe, Microsoft\r\n** Data si locatia finalei\r\n** Invitatii concurenti\r\n** Materiale promotionale (tricouri)\r\n** Organizare tehnica\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Silviu si Cristi concretizeaza IAP 7 (1 sedinta)\r\n* Mircea dă mail la Microsoft. Cristi oferă template.\r\n* Alexandra se ocupă de invitaţii, confirmări şi sosiri\r\n* Cosmin vorbeşte cu Malex să afle ce tool foloseşte pentru detectarea surselor identice şi în foloseşte.\r\n* Singura opţiune pentru finala Algoritmiada: 3-5 aprilie.\r\n* Wefgef face plan concret şi complet de acţiune pentru finală (pagină wiki)\r\n* Wefgef se ocupă de design de tricou (grafică vectorială!)\r\n* Vali şi Bogdan se ocupă pe partea tehnică la finala Algoritmiada\r\n* Vali se ocupă de diplome (design şi printare)\r\n* Buru porneşte un thread pe grup despre detaliile tehnice pentru recalculat timpii\r\n* Wefgef face listă cu ce trebuie instalat la Algoritmiada\r\n* Toata lumea citeşte IAP 12\r\n* Vali bagă backup (înpreună cu Cristi, Bogdan, Silviu)\r\n* Victor testează pe local funcţionalitatea de Virtual Contests până marţi seara şi dă un mail.\r\n* Cosmin scrie documentaţie pentru Virtual Contests până marţi seara.\r\n* Prostu face blog post pentru Virtual Contensts până marţi seara.\r\n* Mircea, Cristi şi Bogdan bagă review la change-ul lui Devilkind până vineri seara.\r\n* Mircea face review la script pentru topic-uri de pe forum la probleme.\r\n* Victor îi arată lui Prostu cum se foloseşte format_table. Prostu bagă la review săptămâna asta.\r\n* Victor bagă la review interfaţa de updatat rating.\r\n* Cristi îi contactează pe Paul, Airinei legat de OKR-uri.\r\n* Cristi bagă medie la OKR-uri.\r\n\r\nh2. Notiţe\r\n\r\n* Raportăm IAP pentru Vali.\r\n* Fără ketchup; e cancerigen.\r\n* La finala Algoritmiada se vine de joi.\r\n* Blog post pentru Coding Camp \"A New Day\"\r\n',1,'protected',NULL,NULL),('probleme-cu-puncte-laticiale','Probleme cu puncte laticiale','2009-02-09 21:51:10','2009-03-10 18:17:00','h1. Probleme cu puncte laticiale\r\n\r\n(Categoria _Matematică_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 25em}*{text-align:center;} *Conţinut*\r\n* \'Introducere\':probleme-cu-puncte-laticiale#introducere\r\n* \'Problema 1\':probleme-cu-puncte-laticiale#problema1\r\n* \'Problema 2\':probleme-cu-puncte-laticiale#problema2\r\n* \'Problema 3\':probleme-cu-puncte-laticiale#problema3\r\n* \'Bibliografie\':probleme-cu-puncte-laticiale#bibliografie\r\n\r\nh2(#introducere). Introducere\r\n\r\nArticolul de faţă se va concentra pe probleme în care vor apărea puncte de coordonate întregi care sunt numite puncte laticiale. Sursele [1] şi [2] menţionate în \'bibliografie\':probleme-cu-puncte-laticiale#bibliografie conţin câte un capitol despre puncte laticiale care, deşi sunt mai matematice decât acest articol, pot fi interesante pentru un elev în pregătirea pentru olimpiadă. Să vedem acum câteva probleme ce au apărut pe la concursurile de programare.\r\n\r\nh2(#problema1). Problema 1\r\n\r\nbq. Să se determine numărul de puncte de coordonate întregi prin care trece segmentul determinat de punctele $(0, 0)$ şi $(M, N)$. De exemplu, pentru $M=9$ şi $N=12$ pe segment vor fi $4$ puncte de coordonate întregi.\r\n\r\n!probleme-cu-puncte-laticiale?img1.JPG!\r\n\r\nh3. Rezolvare\r\n\r\nPutem considera doar cazurile în care $0 ≤ N ≤ M$, dacă $N = 0$ atunci evident avem $M+1$ puncte pe segment. Astfel trebuie să rezolvăm doar cazul în care $1 ≤ N ≤ M$.\r\nEvident că orice punct $(x, y)$, pentru a fi pe segmentul nostru, trebuie să satisfacă ecuaţia $y=M/N*x$. Această ecuaţie are ca soluţie un număr natural doar dacă $M*x$ se divide cu $N$, de aici dacă $D=cmmdc(N, M)$ atunci $x$ se divide cu $N/D$, deci $x$ de forma $k*N/D => y=k*M/D$. Pentru ca punctul $(x, y)$ să aparţină segmentului, trebuie ca $0 ≤ x ≤ N$ şi $0 ≤ y ≤ M$ astfel $0 ≤ k ≤ D$. Deci numărul de puncte de pe un segment de la $(0, 0)$ la $(N, M)$ este egal cu cel mai mare divizor comun al numerelor $M$ şi $N$ la care adăugăm $1$. Putem determina acest număr în complexitate $O(log (N + M))$.\r\n\r\nh2(#problema2). Problema 2\r\n\r\nbq. Se dă un triunghi cu vârfurile de coordonate întregi. Se cere să se determine numărul de puncte de coordonate întregi ce se află în interiorul triunghiului sau pe laturile lui. De exemplu un triunghi cu vârfurile de coordonate $(1, 5)$, $(5, 1)$ şi $(6, 6)$ are $16$ puncte în interior.\r\n\r\n!probleme-cu-puncte-laticiale?img2.JPG!\r\n\r\nh3. Rezolvare\r\n\r\nPentru un dreptunghi cu laturile paralele cu axele de coordonate de lungime $M$ şi lăţime $N$ avem că  numărul de puncte situate strict în interiorul dreptunghiului este $(M–1)×(N–1)$, iar numărul de puncte situate pe laturile poligonului este $2M + 2N$. Dacă notăm cu $B$ numărul de puncte de pe laturi, cu $I$ numărul de puncte situate strict în interiorul unui dreptunghi şi cu $A$ aria dreptunghiului, observăm că $I+B/2–1 = (M–1)×(N–1)+M+N–1 = M×N = A$.\r\nÎn cazul triunghiurilor dreptunghice ce au două catete vom vedea că această formulă se păstrează. Evident avem că $A = (M×N)/2$. Pe ipotenuza triunghiului vom avea $D$ puncte $(D = cmmdc(M, N)+1$, dar aceasta nu ne interesează pe moment), deci numărul de puncte de pe laturile triunghiului este $B = M+N+D–1$. Numărul de puncte $I$ din interiorul triunghiului este numărul de puncte din interiorul dreptunghiului $(M-1)×(N-1)$ din care se scad punctele interioare de pe diagonala $D–2$, rezultatul împărţindu-se apoi la $2$, de aici avem $I = ((M-1)×(N-1)–D+2)/2$. \r\nVerificăm formula $I+B/2–1 = (M-1)×(N-1)/2–D/2+1+M/2+N/2+D/2+1/2 = (M×N)/2$. \r\nDeci formula se verifică şi pe astfel de triunghiuri.\r\nAcum ne uităm la cel mai mic dreptunghi ce conţine un triunghi oarecare, acest dreptunghi poate fi împărţit în patru triunghiuri din care unul este cel iniţial, iar celelalte sunt trei triunghiuri dreptunghice pentru care catetele merg de-a lungul liniilor laticiale. Vom vedea că formula noastră se verifică şi pentru triunghiuri oarecare. Notăm cu $I{~d~}$ numărul de puncte înterioare dreptunghiului, $A{~d~}$ aria dreptunghiului şi $B{~d~}$ numărul de puncte de pe laturile dreptunghiului, cu $I{~1~}$, $I{~2~}$, $I{~3~}$ numărul de puncte din interiorul celor trei triunghiuri dreptunghice, $B{~1~}$, $B{~2~}$, $B{~3~}$ numărul de puncte de pe laturile celor trei triunghiuri, iar $A{~1~}$, $A{~2~}$ şi $A{~3~}$ ariile celor trei triunghiuri. Avem că $I = I{~d~}–I{~1~}–I{~2~}–I{~3~}–B+3$ (trebuie să eliminăm punctele de pe laturile triunghiului interior şi să avem grijă de vârfurile acestui triunghi), $B = B{~1~}+B{~2~}+B{~3~}–B{~d~}$ iar $A = A{~d~}–A{~1~}–A{~2~}–A{~3~}$. De aici avem că $I+B/2–1 = I{~d~}–I{~1~}–I{~2~}–I{~3~} - B{~1~}/2-B{~2~}/2-B{~3~}/2+B{~d~}/2–1+3 = (I{~d~}+B{~d~}/2–1)–(I{~1~}+B{~1~}/2–1) - (I{~1~}+B{~1~}/2–1)-(I{~1~}+B{~1~}/2–1) = A{~d~}–A{~1~}–A{~2~}–A{~3~} = A$, deci egalitarea este valabilă şi pentru triunghiuri oarecare.\r\n\r\n!probleme-cu-puncte-laticiale?img3.JPG!\r\n\r\nAcum aria triunghiului cu vârfurile $(x1, y1)$, $(x2, y2)$, $(x3, y3)$ o putem afla uşor folosind formula lui Heron sau folosind \r\n<tex> \\frac {1} {2} \\cdot | \\left| \\begin{array}{ccc}\r\nx1 & y1 & 1 \\\\\r\nx2 & y2 & 1 \\\\\r\nx3 & y3 & 1 \\end{array} \\right| |.  </tex>\r\n\r\nNumărul de puncte de pe laturile triunghiului poate fi determinat uşor folosind formula demonstrată în problema anterioară. Acum folosind formula $I+B/2–1 = A$ putem afla numărul $I$ şi problema e rezolvată prin întoarcerea numărului $I+B$. Complexitatea rezolvării este $O(log N)$ unde $N$ este valoarea maximă a coordonatelor.\r\n\r\nh2(#problema3). Problema 3 \'Copaci\':problema/copaci (infoarena)\r\n\r\nbq. Macarie, după ce a muncit o viaţă întreagă, se decide la bătrâneţe să se retragă pe o insulă pentru a-şi găsi liniştea interioară şi a se dedica naturii. Astfel el cumpără o insula pe care cultivă pomi fructiferi. Insula poate fi reprezentată ca un poligon (nu neaparat convex) într-un sistem de axe de coordonate pozitive. Pomii sunt plantaţi doar la coordonate naturale.\r\nMacarie este interesat de numărul de copaci pe care îl poate planta strict in interiorul insulei. În acest scop el va furnizează copacii care determina insula (vârfurile poligonului).\r\nDe exemplu pentru poligonul dat prin vârfurile $(0, 4)$, $(0, 5)$, $(2, 7)$, $(2, 4)$, $(6, 6)$ şi $(4, 0)$ avem $12$ puncte de coordinate întregi situate strict în interiorul poligonului.\r\n\r\n!probleme-cu-puncte-laticiale?img4.JPG!\r\n\r\nh3. Rezolvare\r\n\r\nFormula $I+B/2–1 = A$ prezentată mai sus se numeşte \'Teorema lui Pick\':http://en.wikipedia.org/wiki/Pick%27s_theorem, iar ea este valabilă şi pentru poligoane oarecare. Acest fapt este adevărat pentru că orice poligon are o diagonală înterioară, această diagonală îl împarte în două poligoane distincte, dacă notăm $I{~1~}$ şi $I{~2~}$ punctele interioare celor două poligoane, $B{~1~}$ şi $B{~2~}$ punctele de pe laturile celor două poligoane, $A{~1~}$ şi $A{~2~}$ laturile celor două poligoane şi $D$ numărul de puncte de cooronate întregi de pe diagonală atunci dacă egalitatea ar fi fost satisfăcută pentru cele două poligoane atunci avem că $B{~1~}+B{~2~} = B+2D-2$, $I = I{~1~}+I{~2~}+D–2$. De aici avem $A = A{~1~}+A{~2~} = I{~1~}+B{~1~}/2–1+I{~2~}+B{~2~}/2-1 = I{~1~}+I{~2~}+B/2+D–1–2 = I+B/2–1$. Astfel putem demonstra prin inducţie că relaţia este satisfăcută pentru orice poligon. \r\nAria unui poligon poate fi calculată uşor folosind următoarea formulă \r\n<tex> A = \\sum (x_i \\cdot y_{i+1}-x_{i+1} \\cdot y_i) </tex>, unde punctul de indice $n+1$ este primul punct. Astfel obţinem un algoritm de complexitate $O(N log (MaxX + MaxY))$.\r\n\r\nh2(#problema4). Problema 4 (Marele Premiu Paco 2000)\r\n\r\nSe dă o grilă de puncte laticeale de dimensiuni $N × N$, se cere să se determine numărul de pătrate care se pot forma astfel ca vârfurile lor să aparţină punctelor din grilă.\r\nDe exemplu pe o grilă de dimensiuni $3 × 3$ există $6$ pătrate.\r\n\r\n!probleme-cu-puncte-laticiale?img5.JPG!\r\n\r\nh3. Rezolvare:\r\n\r\nUn pătrat cu latură ce conţine $L$ puncte, ce are laturile paralele cu axele de coordonate poate fi translatat în $(N–L+1)×(N–L+1)$ poziţii diferite pe grila noastră.\r\n\r\n!probleme-cu-puncte-laticiale?img6.JPG!\r\n\r\nConsiderăm pentru un pătrat din mulţimea soluţiilor, dreptunghiul minim cu laturile paralele cu axele de coordonate ce conţine acest pătrat. Este uşor să vedem că acest dreptunghi este de fapt un pătrat. Într-un pătrat ce are $L$ puncte pe latura înscrie $L – 2$ pătrate care nu au laturile paralele cu axele de coordonate. \r\n\r\n!probleme-cu-puncte-laticiale?img7.JPG!\r\n\r\nAstfel vedem că numărul total de pătrate pe o grilă $N × M$ este:\r\n\r\n<tex> \\[\\sum_{L=2}^{N} {(N-L+1) \\cdot (N-L+1) \\cdot (L-1)}\\] = \\[\\sum_{L=1}^{N-1} {(N-L) \\cdot (N-L) \\cdot L}\\] = \\[\\sum_{L=1}^{N-1} {L \\cdot N^2 - 2N \\cdot L^2 + L^3}\\] = N^2 \\cdot \\[\\sum_{L=1}^{N-1} {L}\\] - 2N \\cdot \\[\\sum_{L=1}^N-1 {L^2}\\] + \\[\\sum_{L=1}^{N-1} {L^3}\\] = N^2 \\cdot \\frac {N(N-1)} {2} - 2N \\cdot \\frac {N(N+1)(2N+1)} {6} + {\\frac {N(N+1)} {2}}^2 </tex>\r\n\r\nSumă după L de la 2 la N de (N – L + 1) × (N–L + 1) × (L–1) =\r\nsuma L de la 1 la N-1 de (N–L) × (N–L) × L = suma cu L de la 1 la N–1 de LN^2–2 NL^2 + L^3 = N^2 × suma L de la 1 la N-1-2N suma L de la 1 la N–1 de L^2 + suma de L de la 1 la N–1 de L^3 = N^2 ×  N(N-1)/2-2N n(n-1)(2n-1)/6 + [n(n-1)/2]^2.\r\n\r\nAm folosit formulele cunoscute din manualul de clasa a 10-a:\r\n <tex> \\sum_{k=1}^n k = \\frac {n(n+1)} {2} </tex>\r\n <tex> \\sum_{k=1}^n k^2 = \\frac {n(n+1)(2n+1)} {6} </tex>\r\n <tex> \\sum_{k=1}^n k^3 = {\\frac {n(n+1)} {2}}^2 </tex>\r\n Suma cu I de la 1 la N de I = n(n+1)/2\r\n Suma cu I de la 1 la N de I^2 = n(n+1)(2n+1)/6\r\n Suma cu I de la 1 la N de I^3 = [n(n+1)/2]^2\r\nAceastă soluţie are complexitatea O(1), fiind o simplă formulă.\r\n\r\nh2(#problema5). Problema 5 Counting triangles (ACM ICPC Asia – Dhaka 2005/2006) \r\n\r\nTriunghiurile sunt poligoane cu trei laturi şi cu aria strict pozitivă. Triunghiurile laticiale sutn triunghiuri ce au vârfurile de coordinate întregi. În această problemă va trebui să găsiti numarul de triunghiuri laticeale ce se pot găsi pe o grilă de dimensiuni M x N (1 <= M, N <= 1000). De exemplu pe o grilă de dimensiuni 1x2 găsim 18 triunghiuri laticeale distincte după cum vedem în figură:\r\n\r\n!probleme-cu-puncte-laticiale?img14.JPG!\r\n\r\nh3. Rezolvare\r\n\r\nPrima idee de rezolvare ar fi de a lua toate combinaţiile de trei puncte distincte dintre cele N x M puncte şi apoi de a elimina orice trei puncte colineare, dar partea a doua pare greu de a fi realizată eficient.\r\nVom număra asemănător rezolvării de mai sus numărul de triunghiuri înscrise într-un dreptunghi paralel cu axele de coordonate. Apoi acel dreptunghi îl vom putea translata pe grila de puncte laticeale şi astfel vom putea număra toate triunghiurile posibile.\r\n\r\n!probleme-cu-puncte-laticiale?img9.JPG!\r\n\r\nOricum ar fi un triunghi situat într-un dreptunghi ce este minimal, cel putin un vârf al triunghiului trebuie să fie un vârf al dreptunghiului. Se disting astfel două cazuri: primul în care un vârf al triunghiului este şi vârf al dreptunghiului şi celelalte două puncte sunt situate pe cele două laturi ale dreptunghiului ce nu au ca şi capăt primul punct, iar al doilea caz în care cel puţin două vârfuri sunt vârfuri ale dreptunghiului opuse pe diagonală. Dacă dreptunghiul are H puncte pe verticală şi W puncte pe orizontală, atunci în primul caz vom avea 4 x ((H – 1) x (W – 1) + H – 1 + W - 1) triunghiuri, iar în al doilea caz vom avea 2 x (H x W-  X) unde X e numărul de puncte de coordonate întregi de pe diagonala dreptunghiului. Cum trebuie să numărăm triunghiurile înscrise în fiecare dreptughi pt care 1 <= H <= N şi 1 <= W <= M, obţinem un algoritm de complexitate O(NM log N), acel log N apare la calcularea lui X.\r\n\r\nh2(#problema6). Problema 6 \'Dreptunghiuri\':problema/dreptunghiuri (preOni 2006 runda 1)\r\n\r\nClod stă într-o zi plictisit la ora de matematică şi în timp ce profesorul explică la tablă teorema lui Pick, Clod se gândea la o problemă mai interesantă: pentru o grilă de puncte laticiale de dimensiune NxM ( 0 < M, N <= 400) care este numărul de dreptunghiuri cu vârfurile în puncte laticiale. Clod este curios dacă există o formula pentru această problemă şi ar vrea sa ştie soluţia pentru diferite dimensiuni ale grilei, pentru a putea ghici o asemenea formulă. \r\nAjutaţi-l pe Clod să afle răspunsul!\r\n \r\nDe exemplu pentru o grilă de 3x3 puncte gasim 10 dreptunghiuri.\r\n\r\n!probleme-cu-puncte-laticiale?img10.JPG!\r\n\r\nh3. Rezolvare\r\n\r\nUn dreptunghi care apare în grila de puncte laticiale este mărginit de două drepte verticale la stânga şi la dreapta, şi de două drepte orizontale în sus şi în jos. Acum, dacă vrem pentru patru drepte fixate să ştim câte dreptunghiuri mărginesc ele, ne putem uita la următorul desen.\r\n\r\n!probleme-cu-puncte-laticiale?img11.JPG!\r\n\r\nDacă dreptunghiul ABCD determinat de cele patru drepte are vârfurile laturile H si W atunci un dreptunghi MNPQ înscris va împărti laturile lui in bucatile AM, MB şi AQ, QD. Evident dacă MNPQ este dreptunghi atunci avem că AM = PC, MB = PD, AQ = NC QD = NB. Fie M’ proiecţia punctului M pe latura DC. Acum folosind teorema lui Pitagora avem că: \r\nAQ^2 + AM^2 = MQ^2\r\nQD^2 + DP^2 = QP^2\r\nMQ^2 + QP^2 = MP^2\r\nMM’^2 = (AQ + QD)^2\r\nM’P^2 = (PD  - PC)^2\r\nMM’^2 + M’P^2 = MP^2\r\nDe aici avem ca (AQ +   QD)^2 + (PD – PC)^2 =AQ^2 + DQ^2 + AM^2 + MB^2, astfel obtinem AQxQD = AMxMA, daca notam cu A lungimea lui AM şi cu x  lungimea lui AQ  atunci avem ca QD =  H – A, iar MA = W – x deci avem ca x^2 – Wx + A(H – A) = 0. Dacă îl fixăm pe A atunci trebuie să rezolvăm o ecuaţie de gradul doi în necunoscuta x, soluţia trebuie să fie întreagă între 0 şi W.\r\nAstfel in O(H) vom şti numărul de dreptunghiuri înscrise într-un dreptunghi de dimensiuni H * W. Acest dreptunghi poate fi pus in (N – H + 1) * (M – H + 1) locaţii pe o grilă de dimensiune N * M. Deci soluţia are complexitate O(N*M^2), pentru fiecare dreptunghi de dimensiuni 1 <= H <= N şi 1<= W <= M calculându-se numărul de dreptunghiuri înscrise.\r\nO rezolvare de complexitate O(N^2*M^2) în care se căutau soluţiile ecuaţiei printr-un for ar fi luat 60 de puncte. Rezolvarea directă folosind ecuaţia de gradul doi ia în jur de 80 de puncte. Algoritmul poate fi optimizat la factorii constanţi, de exemplu avem nevoie de funcţia radical care este cam înceata, precalculând-o obţinem o accelerare a vitezei, alta idee ar fi că numărul de solutii cu A <= H/2 este egal cu numarul de solutii cu A >= H – H/2 şi a treia idee de optimizare este că numărul de dreptunghiuri înscrise într-un dreptunghi de dimensiuni H, W este acelaşi cu numarul de dreptunghiuri înscrise intr-un dreptunghi de dimensiuni W, H.\r\n\r\nh2(#problema7). Problema 7 Paralelograme (Bursele Agora 2005/2006 runda 1)\r\n\r\nClod este din nou plictisit la ora matematică şi se joacă desenând pe o foaie cu pătrăţele paralelograme cu vârfurile în colţurile pătrăţelelor. Tot desenând paralelograme, Clod se întreabă câte astfel de paralelograme poate construi dacă ştie că foaia de pătrăţele are N linii şi M coloane (0 < N, M <= 2000). \r\nVa trebui să îl ajutaţi să rezolve această problemă. \r\nPentru N = 2 şi M = 2 putem construi 22 de paralelograme\r\n\r\n!probleme-cu-puncte-laticiale?img12.JPG!\r\n\r\nh3. Rezolvare\r\n\r\nCa să determinăm numărul de paralelograme ce se pot găsi pe o grilă laticeală, proprietatea că diagonalele unui paralelogram se înjumătăţesc pare să ne ajute în obţinerea unui algoritm de complexitate O(N + M), dar autorul nu a reuşit să numere într-un mod efficient câte paralelograme sunt degenerate (cu cele patru vârfuri colineare) pentru a putea să le eliminăm din numărul total.\r\n\r\nDin nou putem folosi ideea celui mai mic dreptunghi cu laturile paralele cu axele de coordonate pentru a număra repede o clasă mare de paralelograme de aceiaşi formă.\r\nAvem două cazuri posibile:\r\n\r\n!probleme-cu-puncte-laticiale?img13.JPG!\r\n\r\nPrimul în care cele patru puncte sunt pe laturile dreptunghiului iar nici un vârf nu coincide cu vârfurile dreptunghiului, şi al doilea în care există două puncte în vârfuri opuse ale dreptunghiului.\r\nÎn primul caz, dacă avem poziţiile a două vârfuri fixate pe două laturi consecutive ale dreptunghiului, atunci poziţiile celorlator două vârfuri sunt unic determinate. De aici obţinem că în primul caz avem (h - 2) * (w - 2) paralelograme.\r\nÎn al doilea caz dacă fixăm două vârfuri ale paralelogramului în colţurile dreptunghiului, celelalte două vârfuri vor fi simetrice faţă de centrul de greutate al dreptunghiului, trebuie să nu luăm în calcul posibilitatea ca vărfurile să fie pe diagonala dreptunghiului, de aici obţinem h * w - cmmdc(h - 1, w - 1) – 2 posibilităţi.\r\n\r\nAstfel am ajuns la următorul algoritm:\r\n\r\n	long num = 0;\r\n	for (long h = 2; h <= N + 1; h++) {\r\n		for (long w = 2; w <= M + 1; w++) {\r\n			laux = (h - 2) * (w - 2) + h * w - cmmdc(h - 1, w - 1) - 2;\r\n			num += (N - h + 1) * (M - w + 1) * laux;\r\n		}\r\n	}\r\n\r\nAcest algoritm are complexitatea O(NM log N), el nu s-ar fi încadrat în timpul impus, marea parte a calculelor este efectuată în determinarea celui mai mare divizor comun a două numere, având în vedere că numerele folosite sunt între 1 şi N respectiv între 1 şi M, putem să calculăm o matrice CMMDC[X][Y] unde 1 <= X <= N şi 1 <= Y <= M, această matrice poate fi calculată în O(NM). Astfel complexitatea soluţiei a fost redusă  la  O(NM), mai putem optimiza factorii constanţi ai soluţiei observând că într-un de dimensiuni hxw pot fi înscrise acelaţi număr de dreptunghiuri ca şi într-un triunghi wxh, acest artificiu aproape dublează viteza algoritmului. Menţionăm că aceleaşi optimizări pot fi făcute şi la problema cu triunghiuri.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nCititorul poate să încerce aplicarea tehnicilor din articol la alte probleme similare, de exemplu determinarea numărului de patrulatere convexe nedegenerate cu vârfurile puncte laticeale, sau numărului de romburi sau trapeze.\r\n\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n* Buşneag, Maftei, Teme pentru cercurile şi concursurile de matematică ale elevilor, Scrisul Românesc, Craiova, 1983\r\n* Iaglom, Iaglom, Probleme neelementare tratate elementar, ed tehnică, Bucureşti, 1962\r\n* \'WolframMathWorld\':http://mathworld.wolfram.com\r\n* \'FAQs\':http://www.faqs.org/faqs/graphics/algorithms-faq/\r\n* \'Geometry Algorithms\':http://geometryalgorithms.com/Archive/algorithm_0101/\r\n',5700,'public',NULL,NULL),('planificare/sedinta-20090403','Sedinta 2009-03-31','2009-03-29 22:30:49','2009-03-30 07:43:36','h1. Sedinta 2009-03-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Marti, 31 Martie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== (probabil voi intarzia)\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090316| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Concursul \"Grigore Moisil\"| ==user(user=\"astronomy\" type=\"tiny\")== |\r\n|OKRs| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n\r\n\r\nh2. Detalii\r\n\r\nh3. Misc\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\nh2. Notiţe',2038,'public',NULL,NULL),('grigore-moisil-2009/11-12','Grigore Moisil 2009, clasele 11-12','2009-03-31 19:00:03','2009-03-31 19:34:01','h1. == roundparam(round_id=\"moisil2009-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':grigore-moisil-2009 \r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n*(active) \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n* \'Rezultate\':grigore-moisil-2009/clasament/\r\n\r\n== roundregister(round_id=\"moisil2009-11-12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2009-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2009-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/moisil2009-11-12/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"moisil2009-11-12\" score=\"1\")==',2092,'protected',NULL,NULL),('utilizator/florian','Marcu Florian','2007-01-24 13:36:08','2008-12-19 19:35:03','h2. Despre mine...\r\n\r\n* Nume si prenume: Marcu Florian\r\n* elev la Colegiul National Roman-Voda din Roman, clasa a 11-a B,profil mate-info, profesori de info : Florin Moldovanu si Gavril Petru Florin.\r\n* Nascut pe 14 iulie 1991...\r\n* \"Blog\":http://marcuflorian.uv.ro .\r\n* ID mess: floryan_marq\r\n\r\nh2. Premii, reusite, castiguri,etc..\r\n\r\n* Premiul I la concursul international Pro-Soft@NT decembrie, 2007.\r\n* Mentiune la Concursul de Programare DataS-NMG Targu Secuiesc, mai 2007.\r\n* Premiul III OJI 2008, martie 2008.\r\n* Premiul I la concursul Infokid, iunie 2008.\r\n* Mentiune OJI 2007. \r\n* Mentiune la concursul Pro-Soft@NT decembrie, 2008.\r\n\r\nh2. Prieteni pe infoarena \r\n\r\n* ==user(user=\"tabara\" type=\"tiny\")== @\r\n* ==user(user=\"gabitzish1\" type=\"tiny\")== @\r\n* ==user(user=\"blasterz\" type=\"tiny\")== @\r\n* ==user(user=\"c_e_manu\" type=\"tiny\")== @\r\n* ==user(user=\"omega91\" type=\"tiny\")== @\r\n* ==user(user=\"raduzer\" type=\"tiny\")== @\r\n* ==user(user=\"petro\" type=\"tiny\")== @\r\n\r\n\r\n',5748,'public',NULL,NULL),('planificare/sedinta-20090316','Sedinta 2009-03-16','2009-02-23 16:00:45','2009-03-17 20:01:06','h1. Sedinta 2009-03-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Luni, 16 Martie* la ora *19^00^*, la \'Casa de Cultură a Studenţilor\':http://www.ccs.ro/. (Vezi \'pe hartă\':http://www.salutbucuresti.ro/planoras/swf_map.htm?-7033&-7932. Indicaţii: De la gura staţiei de metrou Eroilor traversaţi Splaiul Independenţei şi Parcul Eroilor pe lângă clădirea Operei Naţionale. După 300-400m ajungeţi la CCS. Întrunirea se ţine la etajul 1, sala 8)\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== (posibil sa intarzii vreo jumatate de ora)\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== (daca o sa mai fiti, eu o sa ajung dupa 20:00, am facultate)\r\n* ==user(user=\"ditzonec\" type=\"tiny\")== (si eu o sa ajung un pic mai tarziu, am facultate)\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090216| ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Eval, server nou| ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Concursul Centrelor de Excelenta/Concurs in engleza | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n|Coding Camp| ==user(user=\"domino\" type=\"tiny\")== |\r\n|Recapitulare OKRs: suntem în grafic?| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n\r\n\r\nh2. Detalii\r\n\r\nh3. Misc\r\n\r\n* Diacritice\r\n* Donare calculatoare\r\n* Algoritmiada 2009\r\n** Sponsori - Adobe, Microsoft\r\n** Data si locatia finalei\r\n** Invitatii concurenti\r\n** Materiale promotionale (tricouri)\r\n** Organizare tehnica\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Silviu si Cristi concretizeaza IAP 7 (1 sedinta)\r\n* Mircea dă mail la Microsoft. Cristi oferă template.\r\n* Alexandra se ocupă de invitaţii, confirmări şi sosiri\r\n* Cosmin vorbeşte cu Malex să afle ce tool foloseşte pentru detectarea surselor identice şi în foloseşte.\r\n* Singura opţiune pentru finala Algoritmiada: 3-5 aprilie.\r\n* Wefgef face plan concret şi complet de acţiune pentru finală (pagină wiki)\r\n* Wefgef se ocupă de design de tricou (grafică vectorială!)\r\n* Vali şi Bogdan se ocupă pe partea tehnică la finala Algoritmiada\r\n* Vali se ocupă de diplome (design şi printare)\r\n* Buru porneşte un thread pe grup despre detaliile tehnice pentru recalculat timpii\r\n* Wefgef face listă cu ce trebuie instalat la Algoritmiada\r\n* Toata lumea citeşte IAP 12\r\n* Vali bagă backup (înpreună cu Cristi, Bogdan, Silviu)\r\n* Victor testează pe local funcţionalitatea de Virtual Contests până marţi seara şi dă un mail.\r\n* Cosmin scrie documentaţie pentru Virtual Contests până marţi seara. %{color:red}(done)%\r\n* Prostu face blog post pentru Virtual Contensts până marţi seara.\r\n* Mircea, Cristi şi Bogdan bagă review la change-ul lui Devilkind până vineri seara.\r\n* Mircea face review la script pentru topic-uri de pe forum la probleme.\r\n* Victor îi arată lui Prostu cum se foloseşte format_table. Prostu bagă la review săptămâna asta.\r\n* Victor bagă la review interfaţa de updatat rating.\r\n* Cristi îi contactează pe Paul, Airinei legat de OKR-uri.\r\n* Cristi bagă medie intermediară la OKR-uri.\r\n* Standard de diacritice: stil consistent per pagină. Dacă o pagină este scrisă deja cu diacritice, toate modificările se fac cu diacritice. Dacă o pagină nu are diacritice aceasta poate fi convertită la diacritice, dar numai în întregime.\r\n* Wefgef face poll pentru schimbarea zilei de şedinţă.\r\n* Prostu aduce merinde la următoarea şedinţă.\r\n* Wefgef conduce următoarea şedinţă.\r\n\r\nh2. Notiţe\r\n\r\n* Raportăm IAP pentru Vali.\r\n* Fără ketchup; e cancerigen.\r\n* La finala Algoritmiada se vine de joi.\r\n* Blog post pentru Coding Camp \"A New Day\"\r\n',2038,'protected',NULL,NULL),('concursuri-virtuale','Concursuri Virtuale','2009-02-28 16:19:24','2009-03-20 22:22:03','h1. Concursuri Virtuale\r\n\r\nAcum îţi poţi organiza propriile concursuri pe site-ul infoarena. Poţi alege câteva probleme din cele $800$ prezente în arhivă şi să simulezi un concurs împreună cu alţi membrii ai comunităţii. Tu îţi alegi ziua, ora şi durata fiecarui concurs. Participarea la un concurs nu este restricţionată, oricine îşi poate crea un concurs şi poate participa la cele deja existente. Mai jos găsiţi o listă cu toate concursurile organizate până acum de către utilizatorii infoarena.\r\n\r\n%{margin:auto; font-size: 1.25em; padding: 0.25em 0.5em; border: 1px double #999999; border-top-color: #CCCCCC; border-left-color: #CCCCCC; background: url(http://infoarena.ro/static/images/background_form_element.gif) repeat-x}\'Crează concurs nou\':admin/runda-noua%\r\n\r\n\r\nPentru mai multe detalii cu privire la crearea şi participarea la un concurs virtual citiţi \"aici\":documentatie/concursuri-virtuale.\r\n\r\n==RoundList(type=\"user-defined\" show_authors=\"true\")==\r\n',1,'private',NULL,NULL),('utilizator/gabitzish1','GABITZISH... Bitis Gabriel.... ','2007-03-02 12:09:21','2009-03-01 10:55:36','h2. Despre mine\r\n\r\nSunt elev in cls a XII-a la Colegiul National \"Emanuil Gojdu\", Oradea, Profil Matematica-Informatica Informatica intensiv.\r\n\r\nPoze : \"Hi5\":http://gabitzish.hi5.com \r\n\r\nh2. Distinctii primite:\r\n\r\n* Mentiune la Concursul Interjudetean \"Marian Tarina\", Turda, 2007.\r\n* Locul 1 la OJI 2008 (judetul Bihor).\r\n* Premiul 3 la Concursul Interjudetean \"Grigore Moisil\", Cluj-Napoca, 2008.\r\n* Mentiune si medalie de bronz la ONI 2008, Ploiesti.\r\n* Premiul 1 la Concursul Interjudetean \"Marian Tarina\", Turda, 2008.\r\n\r\nh2. Activitate pe Infoarena:\r\n\r\nh3. Probleme adaugate in arhiva:\r\n\r\n* \"498. Alee\":/problema/alee\r\n* \"499. Dir\":/problema/dir\r\n* \"501. Ecuatii 2\":/problema/ecuatii2\r\n* \"514. Sudest\":/problema/sudest\r\n* \"535. Drum\":/problema/drum\r\n* \"536. Razboi 2\":/problema/razboi2\r\n* \"538. Impartire\":/problema/impartire\r\n* \"539. Perm 6\":/problema/perm6\r\n* \"550. Logic2\":/problema/logic2\r\n* \"551. Triticale\":/problema/triticale\r\n* \"744. Numar2\":/problema/numar2\r\n* \"745. Iepuri2\":/problema/iepuri2\r\n* \"746. Colaj\":/problema/colaj\r\n* \"749. Concurs2\":/problema/concurs2\r\n* \"767. Ab2\":/problema/ab2\r\n* \"768. Iepuras\":/problema/iepuras\r\n* \"769. Palind2\":/problema/palind2\r\n* \"770. Auto\":/problema/auto\r\n* \"771. Div\":/problema/div\r\n* \"772. Teatru\":/problema/teatru\r\n\r\nh3. Probleme propuse in arhiva:\r\n\r\n* \"905. Cifra lipsa\":/problema/cifralipsa\r\n\r\nh3. Probleme adaugate in arhiva educationala:\r\n\r\n* \"Floyd-Warshall / Roy-Floyd\":/problema/royfloyd\r\n* \"Parcurgere DFS - componente conexe\":/problema/dfs\r\n\r\nh2. Prieteni pe Infoarena:\r\n\r\n* ==User(user=\"Dastas\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"razvi9\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n* ==User(user=\"blasterz\" type=\"tiny\")==\r\n* ==User(user=\"devilkind\" type=\"tiny\")==\r\n* ==User(user=\"stef2n\" type=\"tiny\")==\r\n* ==User(user=\"CezarMocan\" type=\"tiny\")==\r\n* ==User(user=\"Protoman\" type=\"tiny\")==\r\n* ==User(user=\"Florian\" type=\"tiny\")==\r\n* ==User(user=\"peanutz\" type=\"tiny\")==\r\n* ==User(user=\"cos_min\" type=\"tiny\")==\r\n* ==User(user=\"sarabogdan\" type=\"tiny\")==\r\n* ==User(user=\"sima_cotizo\" type=\"tiny\")==\r\n* ==User(user=\"Tabara\" type=\"tiny\")==\r\n* ==User(user=\"Robytzza\" type=\"tiny\")==\r\n* ==User(user=\"fogab\" type=\"tiny\")==\r\n* ==User(user=\"fireatmyself\" type=\"tiny\")==\r\n* ==User(user=\"mariaci\" type=\"tiny\")==\r\n* ==User(user=\"crawler\" type=\"tiny\")==\r\n* ==User(user=\"binary_fire\" type=\"tiny\")==\r\n* ==User(user=\"ciprianf\" type=\"tiny\")==\r\n* ==User(user=\"sigrid\" type=\"tiny\")==\r\n* ==User(user=\"hexstring\" type=\"tiny\")==\r\n* ==User(user=\"lamez0r\" type=\"tiny\")==\r\n',6172,'public',NULL,NULL),('documentatie/concursuri-virtuale','Concursuri virtuale','2009-03-17 19:08:11','2009-03-20 22:24:51','h1. Documentaţie pentru concursurile virtuale\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\nConcursurile virtuale sunt create de catre utilizatori cu probleme din arhiva, avand ca scop propria pregatire si testare in regim de concurs. Pagina destinata concursurilor virtuale se afla \'aici\':concursuri-virtuale. Odata ajunsi aici aveti doua optiuni: participarea la un concurs virtual sau crearea unuia.\r\n\r\nh2. Participare\r\n\r\nPentru a participa la un concurs virtual selectati din lista un concurs la care vreti sa participati. Aici puteti vedea numele concursului, autorul, starea (in desfasurare, incheiat sau inca neinceput) si data la care acesta va avea sau a avut loc. Participarea se face ca la orice concurs normal. **Atentie**: cand trimiteti o sursa trebuie sa selectati concursul la care vreti sa fie trimisa aceasta sursa.\r\n\r\nh2. Creare\r\n\r\nPentru crearea unui concurs nou exista un buton **Creaza concurs nou**. Dupa ce apasati pe acest buton veti fi directionati catre \'aceasta\':admin/runda-noua pagina. Aici selectati numele concursului. Tipul acestuia va fi setat automat (administratorii au mai multe optiuni pentru tipul unui concurs si de aceea a ramas aceasta casuta). Dupa aceasta apasati butonul **Creaza runda**. Veti fi directionati catre o pagina cu mai multe campuri:\r\n\r\n* **Titlul**: sub acest nume va aparea in lista de concursuri virtuale.\r\n* **Pagina de prezentare**: aceasta este pagina la care este trimis utilizatorul cand da click pe numele rundei in monitor sau in pagina de concursuri virtuale. De obicei nu este nevoie sa o modificati.\r\n* **Timpul de start**: timpul cand va incepe concursul scris in formatul specificat.\r\n* **Lista de probleme**: aici puteti alege problemele. Selectati probleme dintr-o anumita parte si mutati-le in cealalta cu sagetile > si < (>> sau << muta toate problemele). In stanga se afla problemele din arhiva si in dreapta problemele care vor fi in concurs.\r\n* **Tipul rundei** : concurs virtual.\r\n* **Evaluare publica**: alegeti daca rezultate se vor afisa in timpul sau dupa concurs.\r\n* **Durata**: durata concursului specificata in ore.\r\n\r\nDupa ce setati toti parametrii necesari, apasati butonul **Salveaza**. Pentru a modifica ulterior parametrii de mai sus trebuie sa accesati pagina manual (din pacate nu exista inca un buton de editat pentru runda; o sa incercam sa punem cat de curand). Pentru o runda cu numele **test** pagina rundei va fi **http://infoarena.ro/runda/test** iar pagina pentru editarea parametrilor va fi **http://infoarena.ro/{+admin+}/runda/test**. La aceasta pagina are acces doar cel ce a creat concursul.',1,'private',NULL,NULL),('runda/gsp','gsp','2009-03-21 11:03:39','2009-03-21 11:05:05','',6333,'round: gsp',NULL,NULL),('runda/a','a','2009-03-21 11:21:47','2009-03-21 11:34:23','h1. == roundparam(round_id=\"a\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"a\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"a\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"a\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/a/clasament.\r\n\r\nh2. Probleme\r\n\r\n\r\n\'flip\':http://infoarena.ro/runda/a/problema/flip/.\r\n\r\n==Tasks(round_id=\"a\" score=\"1\")==',7668,'round: a',NULL,NULL),('runda/drastik_challange_1','drastik_challange_1','2009-03-21 11:54:05','2009-03-21 11:54:05','h1. == roundparam(round_id=\"drastik_challange_1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"drastik_challange_1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"drastik_challange_1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"drastik_challange_1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/drastik_challange_1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"drastik_challange_1\" score=\"1\")==',6957,'round: drastik_challange_1',NULL,NULL),('runda/pentru-cei-mici','pentru-cei-mici','2009-03-21 06:10:07','2009-03-21 06:10:07','h1. == roundparam(round_id=\"pentru-cei-mici\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"pentru-cei-mici\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"pentru-cei-mici\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"pentru-cei-mici\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/pentru-cei-mici/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"pentru-cei-mici\" score=\"1\")==',7668,'round: pentru-cei-mici',NULL,NULL),('runda/cnmnarad','cnmnarad','2009-03-21 14:06:11','2009-03-21 15:34:19','h1. == roundparam(round_id=\"cnmnarad\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cnmnarad\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cnmnarad\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cnmnarad\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cnmnarad/clasament.\r\n\r\nh2. Probleme\r\n\r\nMedii, undeva cam la nivelul OJI clasa a X-a. Special facut concursul pentru olimpicii de la Colegiul National \"Moise Nicoara\" Arad. Oricine e bine-venit.\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cnmnarad\" score=\"1\")==',9156,'round: cnmnarad',NULL,NULL),('runda/cnmnarad','cnmnarad','2009-03-21 14:06:11','2009-03-21 15:35:30','h1. == roundparam(round_id=\"cnmnarad\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cnmnarad\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cnmnarad\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cnmnarad\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cnmnarad/clasament.\r\n\r\nh2. Probleme\r\n\r\n* Problemele sunt medii, undeva cam la nivelul OJI clasa a X-a. Special facut concursul pentru olimpicii de la Colegiul National \"Moise Nicoara\" Arad. Oricine e bine-venit.\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cnmnarad\" score=\"1\")==',9156,'round: cnmnarad',NULL,NULL),('runda/cnmnarad','cnmnarad','2009-03-21 14:06:11','2009-03-21 16:00:15','h1. == roundparam(round_id=\"cnmnarad\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cnmnarad\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cnmnarad\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cnmnarad\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cnmnarad/clasament.\r\n\r\nh2. Probleme\r\n\r\n* Sunt 3 probleme medii, undeva cam la nivelul OJI clasa a X-a. Concursul este special facut pentru olimpicii de la Colegiul National \"Moise Nicoara\" Arad dar oricine e bine venit.\r\n\r\n* Pentru a trimite surse pentru acest concurs, dupa ce ati rezolvat o problema, cand o trimiteti, selectati la \"Concurs\" nume acestui concurs. Aceasta optiune va fi disponibila duminica 22 martie 2009 intre orele 14 si 17. \r\n\r\n* Succes!\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cnmnarad\" score=\"1\")==',9156,'round: cnmnarad',NULL,NULL),('utilizator/andrici_cezar','Profil andrici_cezar','2008-02-20 11:15:10','2009-03-21 15:36:57','== include(page=\"template/noprofile\") ==\r\n *Despre mine*\r\n\r\n Sunt un elev din clasa a VI aB de la Liceul de Informatica Gr.C.Moisil Iasi. Am ajuns la Nationala de Informatica si am luat mentiune.\r\n\r\n\r\n *Distinctii primite*\r\n\r\n_Premiul I la Informatica la ,,Urmasii lui Moisil\", la clasa a 4a!!!`````````anul 2007_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 5a!!!```````anul 2008_\r\n_Premiul III la Informatica Faza Judeteana-98 puncte, la clasa a 5a!!!````anul 2008_ (Calificat la ONI 2008)\r\n_Mentiune la Informatica Faza Nationala-160 puncte, la clasa a 5a!!!````anul 2008_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 9a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 5a!!!`````````anul 2008_\r\n_Premiul I la Informatica la ,,Concursul National al centrelor de Excelenta\", la clasa a 5a!!!```````anul 2008_\r\n_Premiul II la Informatica la Faza Locala-110 puncte, la clasa a 6a!!!`````anul 2009_\r\n_Premiul III la Informatica la Faza Judeteana-40 puncte, la clasa a 6a!!!````anul 2009_ (Calificat la ONI 2009)\r\n\r\n\r\n*.Campion*\r\n*2008 - 2009*\r\n_136 de puncte la Runda 1 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_180 de puncte la Runda 2 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_180 de puncte la Runda 3 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_50 de puncte la Runda 4 Campion, grupa SMALL!!!``````````````````````````anul 2008_ :((\r\n_180 de puncte la Runda 5 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_75 de puncte la Runda 6 Campion, grupa SMALL!!!``````````````````````````anul 2009_ :((\r\n_100 de puncte la Runda 10 Campion, grupa SMALL!!!````````````````````````anul 2009_ \r\n_15 de puncte la Runda 11 Campion, grupa SMALL!!!`````````````````````````anul 2009_ :((\r\n\r\n*Alte rezultate*\r\nChemat la CEX la a 9a 2009(cls.a 6a)\r\n\r\n *Prieteni pe infoarena*\r\n==user(user=\"mironalex2005\" type=\"tiny\")== \r\n==user(user=\"marta_dianna\" type=\"tiny\")== \r\n==user(user=\"ancutza96\" type=\"tiny\")== \r\n==user(user=\"netedu_andrei\" type=\"tiny\")==\r\n==user(user=\"sofia_kiss\" type=\"tiny\")== \r\n\r\n',7668,'public',NULL,NULL),('utilizator/andrici_cezar','Profil andrici_cezar','2008-02-20 11:15:10','2009-03-21 18:23:33','== include(page=\"template/noprofile\") ==\r\n *Despre mine*\r\n\r\n Sunt un elev din clasa a VI aB de la Liceul de Informatica Gr.C.Moisil Iasi. Am ajuns la Nationala de Informatica si am luat mentiune.\r\n\r\n\r\n *Distinctii primite*\r\n\r\n_Premiul I la Informatica la ,,Urmasii lui Moisil\", la clasa a 4a!!!`````````anul 2007_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 5a!!!```````anul 2008_\r\n_Premiul III la Informatica Faza Judeteana-98 puncte, la clasa a 5a!!!````anul 2008_ (Calificat la ONI 2008)\r\n_Mentiune la Informatica Faza Nationala-160 puncte, la clasa a 5a!!!````anul 2008_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 9a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 5a!!!`````````anul 2008_\r\n_Premiul I la Informatica la ,,Concursul National al centrelor de Excelenta\", la clasa a 5a!!!```````anul 2008_\r\n_Premiul II la Informatica la Faza Locala-110 puncte, la clasa a 6a!!!`````anul 2009_\r\n_Premiul III la Informatica la Faza Judeteana-40 puncte, la clasa a 6a!!!````anul 2009_ (Calificat la ONI 2009)\r\n\r\n\r\n*.Campion*\r\n*2008 - 2009*\r\n_136 de puncte la Runda 1 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_180 de puncte la Runda 2 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_180 de puncte la Runda 3 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_50 de puncte la Runda 4 Campion, grupa SMALL!!!``````````````````````````anul 2008_ :((\r\n_180 de puncte la Runda 5 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_75 de puncte la Runda 6 Campion, grupa SMALL!!!``````````````````````````anul 2009_ :((\r\n_100 de puncte la Runda 10 Campion, grupa SMALL!!!````````````````````````anul 2009_ \r\n_15 de puncte la Runda 11 Campion, grupa SMALL!!!`````````````````````````anul 2009_ :((\r\n\r\n*Alte rezultate*\r\nChemat la CEX la a 9a 2009(cls.a 6a)\r\n\r\n*Profesori*\r\nIvasc Cornelia si Mirela Tibu\r\nInfoarena\r\n.Campion\r\n\r\n*Citate preferate*\r\n[b]Daca plangi pentru ca soarele a disparut din viata ta, lacrimile te vor impiedica sa vezi stelele[/b] -[u] Rabindranath Tagore[/u]\r\n\r\n[b]Un om nu este distrus atunci cind este invins; e distrus atunci cind renunta[/b] - [u]Richard Milhous Nixon[/u]\r\n\r\n[b]Nu este intelept sa fii sigur asupra propriei tale intlepciuni. Este sanatos sa ti se aminteasca ca si cel puternic poate slabi, iar cel intelept poate gresi[/b] - [u]Mahatma Gandhi[/u]\r\n\r\n\r\n*Prieteni pe infoarena*\r\n==user(user=\"mironalex2005\" type=\"tiny\")== \r\n==user(user=\"marta_dianna\" type=\"tiny\")== \r\n==user(user=\"ancutza96\" type=\"tiny\")== \r\n==user(user=\"netedu_andrei\" type=\"tiny\")==\r\n==user(user=\"sofia_kiss\" type=\"tiny\")== \r\n\r\n',7668,'public',NULL,NULL),('utilizator/andrici_cezar','Profil andrici_cezar','2008-02-20 11:15:10','2009-03-21 18:20:20','== include(page=\"template/noprofile\") ==\r\n *Despre mine*\r\n\r\n Sunt un elev din clasa a VI aB de la Liceul de Informatica Gr.C.Moisil Iasi. Am ajuns la Nationala de Informatica si am luat mentiune.\r\n\r\n\r\n *Distinctii primite*\r\n\r\n_Premiul I la Informatica la ,,Urmasii lui Moisil\", la clasa a 4a!!!`````````anul 2007_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 5a!!!```````anul 2008_\r\n_Premiul III la Informatica Faza Judeteana-98 puncte, la clasa a 5a!!!````anul 2008_ (Calificat la ONI 2008)\r\n_Mentiune la Informatica Faza Nationala-160 puncte, la clasa a 5a!!!````anul 2008_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 9a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 5a!!!`````````anul 2008_\r\n_Premiul I la Informatica la ,,Concursul National al centrelor de Excelenta\", la clasa a 5a!!!```````anul 2008_\r\n_Premiul II la Informatica la Faza Locala-110 puncte, la clasa a 6a!!!`````anul 2009_\r\n_Premiul III la Informatica la Faza Judeteana-40 puncte, la clasa a 6a!!!````anul 2009_ (Calificat la ONI 2009)\r\n\r\n\r\n*.Campion*\r\n*2008 - 2009*\r\n_136 de puncte la Runda 1 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_180 de puncte la Runda 2 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_180 de puncte la Runda 3 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_50 de puncte la Runda 4 Campion, grupa SMALL!!!``````````````````````````anul 2008_ :((\r\n_180 de puncte la Runda 5 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_75 de puncte la Runda 6 Campion, grupa SMALL!!!``````````````````````````anul 2009_ :((\r\n_100 de puncte la Runda 10 Campion, grupa SMALL!!!````````````````````````anul 2009_ \r\n_15 de puncte la Runda 11 Campion, grupa SMALL!!!`````````````````````````anul 2009_ :((\r\n\r\n*Alte rezultate*\r\nChemat la CEX la a 9a 2009(cls.a 6a)\r\n\r\n*Profesori*\r\nInfoarena\r\n.Campion\r\nMirela Tibu\r\nIvasc Cornelia\r\n\r\n*Prieteni pe infoarena*\r\n==user(user=\"mironalex2005\" type=\"tiny\")== \r\n==user(user=\"marta_dianna\" type=\"tiny\")== \r\n==user(user=\"ancutza96\" type=\"tiny\")== \r\n==user(user=\"netedu_andrei\" type=\"tiny\")==\r\n==user(user=\"sofia_kiss\" type=\"tiny\")== \r\n\r\n',7668,'public',NULL,NULL),('runda/kingoni','kingoni','2009-03-21 21:50:28','2009-03-21 22:09:51','h1. == roundparam(round_id=\"kingoni\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"kingoni\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"kingoni\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"kingoni\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n* De ce \'King ONI\':http://images.ea.com/games/redalert3/Units/KingOni/RA3_KingOni1.jpg ? Daca ati jucat C&C: Red Alert 3, nu e nevoie sa va explic. Daca nu ati jucat, nu are rost sa va explic. Asa ca am sa va arat: \r\n\r\n!http://images.ea.com/games/redalert3/?RA3_Promo_10.jpg?\r\n\r\n* Concursul e o simulare pentru ONI.\r\n\r\n* Frumos ar fi sa fiti toti fair-play, deoarece nu aveti nimic de castigat daca trisati, dar aveti de invatat daca nu trisati.\r\n\r\n* Succes!\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/kingoni/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"kingoni\" score=\"1\")==',9156,'round: kingoni',NULL,NULL),('runda/cnmnarad2','cnmnarad2','2009-03-22 20:27:56','2009-03-22 20:41:34','h1. == roundparam(round_id=\"cnmnarad2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cnmnarad2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cnmnarad2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cnmnarad2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n* Sunt 3 probleme medii, undeva cam la nivelul OJI clasa a X-a. Concursul este special facut pentru olimpicii de la Colegiul National \"Moise Nicoara\" Arad dar oricine e bine venit.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cnmnarad2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cnmnarad2\" score=\"1\")==',9156,'round: cnmnarad2',NULL,NULL),('utilizator/andrici_cezar','Profil andrici_cezar','2008-02-20 11:15:10','2009-03-21 18:29:43','== include(page=\"template/noprofile\") ==\r\n *Despre mine*\r\n\r\n Sunt un elev din clasa a VI aB de la Liceul de Informatica Gr.C.Moisil Iasi. Am ajuns la Nationala de Informatica si am luat mentiune.\r\n\r\n\r\n *Distinctii primite*\r\n\r\n_Premiul I la Informatica la ,,Urmasii lui Moisil\", la clasa a 4a!!!`````````anul 2007_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 5a!!!```````anul 2008_\r\n_Premiul III la Informatica Faza Judeteana-98 puncte, la clasa a 5a!!!````anul 2008_ (Calificat la ONI 2008)\r\n_Mentiune la Informatica Faza Nationala-160 puncte, la clasa a 5a!!!````anul 2008_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 9a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 5a!!!`````````anul 2008_\r\n_Premiul II la Informatica la ,,Moisil++\", la clasa a 5a!!!````````````anul 2008_\r\n_Premiul I la Informatica la ,,Concursul National al centrelor de Excelenta\", la clasa a 5a!!!```````anul 2008_\r\n_Premiul II la Informatica la Faza Locala-110 puncte, la clasa a 6a!!!`````anul 2009_\r\n_Premiul III la Informatica la Faza Judeteana-40 puncte, la clasa a 6a!!!````anul 2009_ (Calificat la ONI 2009)\r\n\r\n\r\n*.Campion*\r\n*2008 - 2009*\r\n_136 de puncte la Runda 1 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_180 de puncte la Runda 2 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_180 de puncte la Runda 3 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_50 de puncte la Runda 4 Campion, grupa SMALL!!!``````````````````````````anul 2008_ :((\r\n_180 de puncte la Runda 5 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_75 de puncte la Runda 6 Campion, grupa SMALL!!!``````````````````````````anul 2009_ :((\r\n_100 de puncte la Runda 10 Campion, grupa SMALL!!!````````````````````````anul 2009_ \r\n_15 de puncte la Runda 11 Campion, grupa SMALL!!!`````````````````````````anul 2009_ :((\r\n\r\n*Alte rezultate*\r\nChemat la CEX la a 9a 2009(cls.a 6a)\r\n\r\n*Profesori*\r\nIvasc Cornelia si Mirela Tibu\r\nInfoarena\r\n.Campion\r\n\r\n*Citate preferate*\r\n_Daca plangi pentru ca soarele a disparut din viata ta, lacrimile te vor impiedica sa vezi stelele_ - Rabindranath Tagore\r\n\r\n_Un om nu este distrus atunci cind este invins; e distrus atunci cind renunta_- Richard Milhous Nixon\r\n\r\n_Nu este intelept sa fii sigur asupra propriei tale intlepciuni. Este sanatos sa ti se aminteasca ca si cel puternic poate slabi, iar cel intelept poate gresi_ - Mahatma Gandhi\r\n\r\n_Cel puternic nu este cel care este de neinvins, ci cel care se ridica dupa fiecare lovitura_\r\n\r\n_Loveste spre soare chiar daca nu reusesti, macar o sa fii printre stele_',7668,'public',NULL,NULL),('grigore-moisil-2009','Grigore Moisil 2009','2009-03-31 19:07:10','2009-03-31 19:12:06','\r\nh1. Grigore Moisil 2009\r\n\r\n(htabs)*(active) \'Despre...\':grigore-moisil-2009 \r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n* \'Rezultate\':grigore-moisil-2009/clasament/\r\n\r\nInfoare organizeaza si in acest an editia online a concursului interjudetean de informatica Grigore Moisil. Concurentii pot profita de aceasta ocazie pentru a efectua un ultim test inainte de Olimpiada Nationala. Concursul se va desfasura *Duminica 5 aprilie*, la ora {*09^00^*} si va dura *3h*. Participantii vor avea de rezolvat 2-3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\n',2092,'public',NULL,NULL),('utilizator/motty','Profil motty','2008-10-24 09:08:52','2009-03-29 21:48:23','h2. Despre mine\r\n\r\n* _Sunt elev in clasa a 9-a la Colegiul National de Informatica \"Tudor Vianu\";_\r\n* _Am inceput informatica in octombrie 2008;_\r\n* _{*In God we Trust!*}_\r\n* _Gibson rulez \\m/;_\r\n\r\nh2. Distinctii primite\r\n\r\n* _Premiul I la Concursul de Informatica \"Urmasii lui Moisil\" Iasi - 2009;_\r\n\r\nh2. Profesori\r\n\r\n* ==User(user=\"rapidu36\" type=\"tiny\")==\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"gabitzish1\" type=\"tiny\")==\r\n* ==User(user=\"ira\" type=\"tiny\")==\r\n* ==User(user=\"drag0s93\" type=\"tiny\")==\r\n* ==User(user=\"cosmin79\" type=\"tiny\")==\r\n* ==User(user=\"andreisfrent\" type=\"tiny\")==\r\n* ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n* ==User(user=\"hadesgames\" type=\"tiny\")==\r\n* ==User(user=\"ilinca\" type=\"tiny\")==\r\n',8690,'public',NULL,NULL),('deque-si-aplicatii','Deque și aplicații','2009-01-22 22:28:12','2009-03-30 07:23:31','h1. Deque şi aplicaţii\r\n\r\n(Categoria _Structuri de date_, Autor _Marius Stroe_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'Descrierea structurii\':deque-si-aplicatii#descriere\r\n* \'Aplicaţii:\':deque-si-aplicatii#problema-1\r\n** \'_1. Book Pile &#40;SGU&#41;_\':deque-si-aplicatii#problema-1\r\n** \'_2. Vila 2 &#40;.campion, 2005&#41;_\':deque-si-aplicatii#problema-2\r\n** \'_3. Şir_\':deque-si-aplicatii#problema-3\r\n** \'_4. Platforma &#40;.campion, 2009&#41;_\':deque-si-aplicatii#problema-4\r\n** \'_5. Trans &#40;ONI 2004&#41;_\':deque-si-aplicatii#problema-5\r\n** \'_6. Otilia &#40;.campion, 2005&#41;_\':deque-si-aplicatii#problema-6\r\n** \'_7. Bcrc &#40;Stelele Informaticii, 2006&#41;_\':deque-si-aplicatii#problema-7\r\n** \'_8. Cut the Sequence &#40;PKU&#41;_\':deque-si-aplicatii#problema-8\r\n* \'Concluzii\':deque-si-aplicatii#concluzii\r\n* \'Probleme suplimentare\':deque-si-aplicatii#probleme-suplimentare\r\n* \'Bibliografie\':deque-si-aplicatii#bibliografie\r\n\r\nÎn acest articol voi prezenta o structură de date liniară de tip listă numită _deque_. Aceasta nu este una complexă, în schimb se va dovedi foarte folositoare. După o scurtă prezentare, mă voi axa pe o serie de aplicaţii care vor arăta surprinzătoarea sa utilitate în locurile unde am fi crezut că nu se mai poate face nimic pentru a reduce complexitatea algoritmului.\r\n\r\nh2(#descriere). Descrierea structurii\r\n\r\nNoţiunea de _deque_ a fost introdusă, în 1997, de Donald Knuth în lucrarea numărul [1].\r\n\r\nStructura de _deque_ (pronunţat, de obicei, _deck_) poate fi privită ca o listă cu două capete prin intermediul cărora se şterg sau inserează noi elemente. În literatura de specialitate aceste capete se numesc _head_ şi _tail_, iar deque-ul mai este recunoscut şi ca fiind o coadă cu două capete _(double ended queue)_.\r\n\r\nPentru implementarea unui deque putem recurge la liste dublu înlănţuite sau la un vector static când se cunoaşte numărul elementelor din colecţie. Limbajul C++ pune şi el la dispoziţia programatorilor o implementare prin intermediul containerului \'_std::deque_\':http://www.cplusplus.com/reference/stl/deque/ din headerul _<deque>_.\r\n\r\nh3(#operatii). Operaţii:\r\n\r\nVom putea utiliza această structură de date în situaţiile când avem nevoie de următoarele operaţii (sunt listate cu numele sub care se găsesc în limbajul C++):\r\n\r\ntable{width:70%}. | * _front()_ | întoarce primul element |\r\n| * _back()_ | întoarce ultimul element |\r\n| * _push_front()_ | inserează un element în faţă |\r\n| * _push_back()_ | inserează un element în spate |\r\n| * _pop_front()_ | scoate primul element |\r\n| * _pop_back()_ | scoate ultimul element |\r\n| * _empty()_ | întoarce _true_ dacă în deque nu se găseşte niciun element şi _false_ în caz contrar |\r\n\r\np=. !deque-si-aplicatii?new_deque.png 75%!\r\n\r\nToate aceste operaţii se execută în timp $O(1)$ pe o structură implementată de la zero sau în timp $O(1)$ \'amortizat\':http://en.wikipedia.org/wiki/Amortized_analysis pentru containerul $deque$ din C++.\r\n\r\nÎn multe aplicaţii unde soluţiile parţiale se reprezintă sub forma unui şir continuu de valori care permite inserarea şi ştergerea doar pe la capete se poate folosi un $deque$. Să urmărim în continuare cazuri concrete în care simplitatea unui $deque$ duce la soluţii de multe ori optime şi implementări foarte scurte şi clare. Aplicaţiile sunt prezentate în ordinea crescătoare a dificultăţii şi din acest motiv le recomand cu căldură tuturor celor care învaţă din acest articol să le parcurgă în ordine.\r\n\r\nh2(#problema-1). 1. \'Book Pile\':http://acm.sgu.ru/problem.php?contest=0&problem=271 (SGU)\r\n\r\nbq. Se dau $N$ cărţi aşezate una deasupra celeilalte asupra cărora se vor efectua $M$ operaţii de două tipuri: 1. $ADD${$(nume)$}: se adaugă cartea $nume$ deasupra celorlalte; 2. $ROTATE$: primele $K$ cărţi de deasupra se rotesc (dacă sunt mai puţin de $K$ cărţi atunci se vor roti toate). Rotaţia presupune inversarea celor $K$ elemente, adică ultimul va fi primul, penultimul va fi al doilea etc. Se cere să se afişeze cărţile în ordine, prima fiind cea de deasupra, după efectuarea celor $M$ operaţii.\r\nRestricţii: $0 &le; N, K &le; 40 000$, $0 &le; M &le; 100 000$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se poate deduce pe baza observaţiei următoare: odată avansată dincolo de poziţia $K$, o carte ajunge pe poziţia finală, întrucât orice operaţie ulterioară (inserare sau rotaţie) nu o va mai afecta. Să presupunem că iniţial avem cărţile $A B C$ şi $K = 3$. Dacă îl vom adăuga pe $D$, atunci nu avem nevoie pentru operaţiile următoare decât de cărţile $D A B$, deoarece, dacă vom roti ulterior primele $K$ cărţi, $C$ nu va mai fi niciodată considerat. După o rotaţie, noua ordine va fi $B A D$ şi $C$ va fi pe raft la loc sigur. Dacă îl vom adăuga pe $E$, topul se va schimba în $E B A$, iar pe raft, în mod sigur vor fi $D C$, în această ordine. Cele $K$ cărţi din vârf se prezintă ca o secvenţă continuă de elemente, la care se adaugă noi elemente sau se elimină dintre acestea numai pe la _capete_. Aceste capete sunt chiar $head$ şi $tail$ ale unui $deque$.\r\n\r\np=. !deque-si-aplicatii?bookpile.png 40%!\r\n\r\nLa final, când se vor termina operaţiile, cărţilor de pe raft li se vor adăuga cele din $deque$ şi se va afişa soluţia. În cazul presupus, soluţia va fi: $E B A D C$.\r\n\r\nÎntrucât operaţiile unui $deque$ se execută în timp $O(1)$, soluţia are complexitatea $O(N + M)$.\r\n\r\nh2(#problema-2). 2. \'Vila 2\':problema/vila2 (.campion, 2005)\r\n\r\nbq. Se dă un şir $S$ de $N$ numere întregi şi $D$ un număr natural. Se cere să se determine diferenţa maximă dintre oricare două numere din şir cu proprietatea că diferenţa în modul a poziţiilor pe care se găsesc în şirul $S$ nu depăşeşte $D$.\r\nRestricţii: $2 &le; N &le; 100 000$, $1 &le; D &le; N/2$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia naivă constă în procesarea tuturor perechilor de numere care se găsesc pe poziţii cu diferenţa în modul mai mică sau egală decât $D$.\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    ret = 0;\r\n    pentru i = 1, N execută\r\n        pentru j = Max(1, i - D), i execută\r\n            dacă ret < |S[i] - S[j]| atunci\r\n                ret = |S[i] - S[j]|;\r\n        sfârşit_pentru;\r\n    sfârşit_pentru;\r\n    return ret;\r\nSfârşit.\r\n==\r\n\r\nComplexitatea algoritmului este $O(N^2^)$, dar pentru limitele problemei este enorm de mare.\r\n\r\nDin pseudocodul de mai sus se vede că pentru un indice $i$ fixat, iterăm cu un alt indice $j$ pentru a găsi diferenţa maximă în modul dintre $S[i]$ şi un alt număr din intervalul $[i - D, i]$. Însă, diferenţa dintre cel mai mare număr şi cel mai mic număr este cel puţin la fel de bună ca rezultatul de la $j$-ul anterior. Astfel, pentru indicele $i$ fixat succesiv cu $1$, $2$, .., $N$, considerăm secvenţa $[i - D, i]$ în care determinăm valoarea maximă şi valoarea minimă, iar diferenţa lor o comparăm cu rezultatul cel mai bun obţinut până în acel moment.\r\n\r\nPentru fixarea ideii, să urmărim cum putem determina eficient valoarea maximă din fiecare secvenţă $[i - D, i]$.\r\n\r\n_Observaţie_: Fie $i{~1~}$, $i{~2~}$ doi indici astfel încât $i - D &le; i{~1~} &lt; i{~2~} &le; i$.\r\n\r\n# Dacă $S[i{~1~}] &le; S[i{~2~}]$ atunci, cât timp cei doi indici vor fi în intervale de tipul $[i - D, i]$, valoarea de pe poziţia $i{~2~}$ va fi întotdeauna preferată valorii de pe poziţia $i{~1~}$. Când se ajunge la un interval care nu-l mai conţine pe $i{~1~}$, $i{~2~}$ rămâne în continuare preferat.\r\n# Dacă $S[i{~1~}] &gt; S[i{~2~}]$ atunci şi valoarea de pe poziţia $i{~1~}$ şi cea de pe poziţia $i{~2~}$ sunt candidate la maxim, la momentul curent sau în viitor.\r\n\r\nCu această observaţie deducem că într-o secvenţă $[i - D, i]$ vom avea un şir strict descrescător de numere: $T{~i~} = S[i{~1~}] &gt; S[i{~2~}] &gt; ... &gt; S[i{~K~}]$, unde $S[i{~1~}]$ elimină toate elementele $S[j]$, cu $S[j] &le; S[i{~1~}]$ şi $i - D &le; j &lt; i{~1~}$, $S[i{~2~}]$ elimină toate elementele $S[j]$, cu $S[j] &le; S[i{~2~}]$ şi $i{~1~} &lt; j &lt; i{~2~}$, $S[i{~3~}]$ elimină toate elementele $S[j]$, cu $S[j] &le; S[i{~3~}]$ şi $i{~2~} &lt; j &lt; i{~3~}$ ş.a.m.d. De reţinut este că niciuna dintre valorile de pe poziţiile eliminate nu poate fi maximă, motiv pentru care le-am putut elimina. Şirul $T{~i~}$ are următoarele proprietăţi:\r\n\r\n* se termină pe poziţia curentă, adică are loc egalitatea $i{~K~} = i$ întrucât poziţia $i$ nu va fi eliminată de nicio altă poziţie;\r\n* valoarea căutată, adică maximul dintre numerele din secvenţă, se găseşte pe prima poziţie. \r\n\r\nCând vom avansa la secvenţa următoare, $[i - D + 1, i + 1]$, vom forma şirul $T{~i+1~}$ ştergând din indicii $i{~1~}$, $i{~2~}$ ... atâta timp cât nu se găsesc în intervalul curent şi vom şterge din poziţiile $i{~K~}$, $i{~K-1~}$ ... cât timp $S[i + 1] &ge; S[i{~K~}]$, $S[i + 1] &ge; S[i{~K-1~}]$ ...\r\n\r\nŞirul $T{~i~}$ poate fi păstrat prin intermediul şirului de indici $i{~1~} &lt; i{~2~} &lt; ... &lt; i{~K~}$. Operaţiile pe acest şir se efectuează doar pe la cele două capete, aşadar poate fi implementat cu ajutorul unui $deque$.\r\n\r\nPentru $S[] = {5, 9, 4, 7, 4, 1}$ şi $D = 3$ obţinem următoarele stări ale unui deque:\r\n\r\n* <tex> \\langle \\widehat{5\\ [1]} \\rangle </tex>;\r\n* <tex> \\langle 5\\ [1] \\rangle \\Leftarrow 9\\ [2] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]} \\rangle </tex>;\r\n* <tex> \\langle 9\\ [2] \\rangle \\Leftarrow 4\\ [3] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 4\\ [3] \\rangle </tex>;\r\n* <tex> \\langle 9\\ [2],\\ 4\\ [3] \\rangle \\Leftarrow 7\\ [4] </tex> de unde se obţine <tex> \\langle \\widehat{9\\ [2]},\\ 7\\ [4] \\rangle </tex>;\r\n* <tex> 9\\ [2] \\Leftarrow \\langle 7\\ [4] \\rangle \\Leftarrow 4\\ [5] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5] \\rangle </tex>;\r\n* <tex> \\langle 7\\ [4],\\ 4\\ [5] \\rangle \\Leftarrow 1\\ [6] </tex> de unde se obţine <tex> \\langle \\widehat{7\\ [4]},\\ 4\\ [5],\\ 1\\ [6] \\rangle </tex>;\r\n\r\nCum fiecare indice din $1$, $2$, ..., $N$ este adăugat şi şters cel mult o dată din deque, complexitatea finală este $O(N)$.\r\n\r\nh2(#problema-3). 3. \'Şir\':problema/sir\r\n\r\nbq. Se dă un şir $S$ de numere întregi de lungime $N$. Se cere să se găsească secvenţa de lungime maximă cuprinsă între $X$ şi $Y$ astfel încât $MAX - MIN &le; Z$, unde $MAX$ este maximul dintre toate numerele întregi din secvenţă, iar $MIN$ minimul dintre acestea. Secvenţa soluţie va fi cea cu poziţia de început maximă dintre toate secvenţele de lungime maximă.\r\nRestricţii: $3 &le; N &le; 100 000$, $1 &le; X &le; Y &le; N$, $0 &le; Z &le; 30 000$.\r\n\r\nh3. Soluţie:\r\n\r\nVoi prezenta mai jos o rafinare a soluţiei în trei paşi.\r\n\r\nPrima rezolvare se găseşte uşor, deoarece nu facem decât să urmărim textul: pentru fiecare poziţie $i$ fixată ({$i$} ia valorile $1$, $2$, ..., $N$ succesiv) vom considera toate secvenţele candidate la rezultatul final, adică vom plimba un $j$ între poziţiile $i - Y + 1$ şi $i - X + 1$. Pentru un interval $[j, i]$ vom determina $MAX$ şi $MIN$ în $O(log N)$ cu un arbore de intervale, iar dacă diferenţa dintre acestea nu depăşeşte $Z$ vom compara rezultatul cu cel obţinut până în acel moment. Complexitatea finală va fi $O(N * (Y - X) * log N)$.\r\n\r\nCum se cere secvenţa de lungime maximă, pentru fiecare poziţie $i$ trebuie găsit indicele $j$ cât mai mic cuprins între $i - Y + 1$ şi $i - X + 1$ astfel încât secvenţa $[j, i]$ să fie candidată la soluţie. Ce proprietăţi are indicele $j$?\r\n\r\n* $i - Y + 1 &le; j &le; i - X + 1$ şi $MAX - MIN &le; Z$;\r\n* având $i$-ul fixat, dacă trecem de la $j$ la $j + 1$, maximul poate scădea, iar minimul poate creşte, dar în mod sigur diferenţa lor va rămâne mai mică sau egală cu $Z$; soluţia astfel obţinută este mai scurtă, deci nu îmbunătăţeşte soluţia obţinută anterior.\r\n* dacă trecem de la $i$ la $i + 1$, cel mai mic $j$ găsit la pasul anterior poate ori să nu corespundă celor două restricţii (caz în care îl incrementăm cât timp $j < i - Y + 2$ sau $MAX - MIN > Z$), ori să corespundă şi atunci este cel mai mic care să respecte proprietăţile pentru $i + 1$.\r\n\r\nPentru determinarea lui $MAX$, respectiv lui $MIN$ pe fiecare interval $[j, i]$, se poate folosi un arbore de intervale. Complexitatea finală va fi $O(N * log N)$.\r\n\r\nSă vedem cum putem îmbunătăţi complexitatea $O(log N)$ pentru determinarea maximului şi minimului. Mai jos vom vedea algoritmul pentru a-l calcula pe $MAX$, cazul lui $MIN$ fiind similar. Observaţia care ne ajută în multe probleme pentru reducerea complexităţii de la $O(log N)$ la $O(1)$ este, asemănător problemei precedente, următoarea:\r\n\r\n_Observaţie_: Fie $[j, i]$ un interval de interes şi $i{~1~}$ şi $i{~2~}$ doi indici astfel încât $j &le; i{~1~} < i{~2~} &le; i$. Atunci, dacă $S[i{~1~}] < S[i{~2~}]$ poziţia $i{~2~}$ va fi întotdeauna preferată poziţiei $i{~1~}$ atâta timp cât cele două poziţii vor fi în acelaşi interval de interes. Aşadar putem renunţa la $i{~1~}$ pentru etapele următoare, eliminându-l. Dacă, însă, $S[i{~1~}] &ge; S[i{~2~}]$, atunci poziţia $i{~1~}$ \"va umbri\" poziţia $i{~2~}$ atâta timp cât cele două poziţii vor fi în intervalul de forma $[j, i]$. În schimb, când $i{~1~}$ va fi eliminat, $i{~2~}$ are şansa să fie un candidat la $MAX$ dintre restul elementelor de la dreapta sa. În acest caz, vom păstra ambele poziţii şi pentru paşii următori.\r\n\r\nRezultă din această observaţie, analog \'problemei anterioare\':deque-si-aplicatii#problema-2, că în intervalul $[j, i]$ se va forma un şir de poziţii $i{~1~} < i{~2~} < ... < i{~k~}$ astfel încât $S[i{~1~}] &ge; S[i{~2~}] &ge; ... &ge; S[i{~k~}]$, din care extragem $MAX$ ca fiind $S[i{~1~}]$. Folosind iarăşi structura de date $deque$, complexitatea algoritmului va fi $O(N)$.\r\n\r\nÎn pseudocod, algoritmul va arăta în felul următor:\r\n\r\n== code(cpp) |\r\n// S şirul de numere iniţial şi N lungimea sa\r\n\r\n// Subalgoritmul push() inserează în deque poziţia p din şirul S în conformitate cu\r\n// funcţia booleană fct, o funcţie generică\r\nSubalgoritmul push(deque, întreg p, funcţia fct) este:\r\n    cât timp (!deque.empty() şi fct(S[p], S[deque.back()])) execută\r\n        deque.pop_back();\r\n    deque.push_back(p);\r\nSfârşit;\r\n\r\n// Funcţia query() întoarce numărul din S corespunzător primului indice\r\n// din deque aflat în intervalul de interes [j, i].\r\nFuncţia query(deque, întreg j) este:\r\n    cât timp (!deque.empty() şi deque.front() < j) execută\r\n        deque.pop_front();\r\n    return S[deque.front()];\r\nSfârşit;\r\n\r\nAlgoritmul este:\r\n    lg = 0; j = 1;\r\n    pentru i = 1, N execută\r\n        // funcţia min(a, b) întoarce true dacă a < b\r\n        push(min_deq, i, min);\r\n        // funcţia max(a, b) întoarce true dacă a > b\r\n        push(max_deq, i, max);\r\n        cât timp ((j <= i - Y sau query(max_deq, j) - query(min_deq, j) > Z) şi j <= i - X + 1) execută\r\n            j = j + 1;\r\n        // [j, i] este intervalul candidat la soluţia optimă pentru poziţia i\r\n        dacă (j <= i - X + 1) şi (query(max_deq, j) - query(min_deq, j) <= Z) atunci\r\n            dacă (lg >= i - j + 1) atunci\r\n                lg = i - j + 1, start = j, stop = i;\r\n    sfârşit_pentru\r\n\r\n    dacă (lg > 0) atunci\r\n        soluţia este (lg, start, stop);\r\n    altfel\r\n        nu există soluţie;\r\nSfârşit.\r\n==\r\n\r\nh2(#problema-4). 4. \'Platforma\':http://campion.edu.ro/problems/3/509/platforma_ro.htm (.campion, 2009)\r\n\r\nbq. Se dă o matrice $P$ de dimensiuni $M x N$ cu elemente numere întregi. Se defineşte valoarea maximă dintr-un dreptunghi de dimensiuni $R x C$ ca fiind valoarea maximă dintre elementele aflate în acel dreptunghi.\r\nCerinţă: Să se găsească un dreptunghi de dimensiuni $R x C$ cu valoarea maximă minimă.\r\nRestricţii: $1 &le; M, N &le; 1000$, $1 &le; R &le; M$, $1 &le; C &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nAceastă problemă reprezintă o extindere în două dimensiuni a problemei anterioare \'Vila 2\':deque-si-aplicatii#problema-2, unde am studiat cazul unidimensional al determinării pe un vector a maximului / minimului pentru fiecare subsecvenţă de o lungime fixată.\r\n\r\nCerinţa constă în amplasarea unui dreptunghi $R x C$ astfel încât valoarea maximă din interiorul său să fie cât mai mică. Una din ideile simple constă în fixarea colţului din stânga sus în toate cele $(M - R + 1) x (N - C + 1)$ poziţii şi determinarea maximului din interiorul său cu o altă parcurgere a celor $R x C$ elemente. Putem, în schimb, să fixăm o linie $i$, iar pentru a fixa colţul din stânga sus mai iterăm cu un indice $j$ între coloanele $1$ şi $N - C + 1$. De aici devine clar că atunci când avansăm indicele coloanei, în dreptunghiul curent apare o nouă coloană, $j + C$, şi dispare coloana $j$. Dacă pentru fiecare coloană $j$ de pe linia curentă $i$ reţinem un $Max{~i,j~}$ egal cu maximul dintre elementele $P{~i,j~}, P{~i+1,j~}, ..., P{~i+R-1,j~}$, atunci pe linia fixată $i$ vom avea un vector din $N$ elemente (numărul de coloane al matricei $P$) alcătuit din valorile $Max{~i,1~}, Max{~i,2~}, Max{~i,3~}, ..., Max{~i,j~}, ..., Max{~i,N-1~}, Max{~i,N~}$. Iar pe acest vector va trebui să determinăm pentru fiecare subsecvenţă de $C$ elemente, valoarea maximă. Dintre toate subsecvenţele o vom alege pe cea cu valoarea maximă cea mai mică. Iar acest rezultat va fi o soluţie pentru linia fixată. Cu valorile din $Max$ precalculate, pentru fiecare linie avem complexitatea $O(N)$, deci $O(M * N)$ pentru întreaga matrice. Însă, implementând direct, valorile din $Max$ se calculează în $O(M * N * R)$. Mai sus am definit $Max{~i,j~}$ ca fiind maximul dintre $P{~i,j~}, P{~i+1,j~}, ..., P{~i+R-1,j~}$. Rezultă că $Max{~i+1,j~}$ este maximul dintre $P{~i+1,j~}, P{~i+2,j~}, ..., P{~i+R-1,j~}, P{~i+R,j~}$, adică maximul dintre elementele lui $Max{~i,j~}$ din care scoatem $P{~i,j~}$ şi adăugăm $P{~i+R,j~}$. De aici deducem că pentru fiecare coloană fixată, valorile lui $Max$ de pe coloana respectivă se reduc la a determina pentru fiecare subsecvenţă de lungime $R$ (numărul de linii al dreptunghiului de amplasat) elementul maxim. Aceste rezultate se obţin în $O(M)$ pentru fiecare coloană, deci $O(N * M)$ în total.\r\n\r\nRezultă complexitatea finală $O(M * N)$.\r\n\r\nh2(#problema-5). 5. \'Trans\':problema/trans (ONI 2004)\r\n\r\nbq. Se dau $N$ blocuri de piatră, de culoare albă sau neagră aşezate în ordinea $1$, $2$, ..., $N$. Blocurile de piatră trebuie să fie transportate în ordinea în care sunt, iar pentru aceasta va trebui închiriat un camion. Se mai dau $Q$ tipuri de camioane. Camionul de tipul $i (1 &le; i &le; Q)$ poate transporta maxim $K{~i~}$ blocuri de piatră la un moment dat şi pentru un transport se percepe taxa $T{~i~}$. Se impune condiţia ca toate blocurile de piatră plasate în camion la un transport sa aibă aceeaşi culoare. Aşadar, pentru a fi transportate toate blocurile, se va alege un camion de un anumit tip, iar camionul va efectua unul sau mai multe transporturi. Pentru a micşora suma totală plătită, există posibilitatea de a schimba culoarea oricărui bloc de piatră (din alb în negru sau din negru în alb); pentru fiecare bloc $i (1 &le; i &le; N)$ se cunoaşte suma $S{~i~}$ ce trebuie plătită pentru a-i schimba culoarea $C{~i~}$.\r\nCerinţă: Pentru fiecare dintre cele $Q$ tipuri de camioane, determinaţi suma minimă plătită pentru a transporta toate cele $N$ blocuri.\r\nRestricţii: $1 &le; N &le; 16.000$, $1 &le; Q &le; 100$, $1 &le; K{~i~} &le; N$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia problemei se bazează pe găsirea unei formule de recurenţă ce respectă principiul optimalităţii specific metodei programării dinamice.\r\n\r\nPentru început, fixăm un camion dintre cele <tex> Q </tex>. Fie <tex> K </tex> numărul maxim de pietre pe care acesta le poate transporta şi <tex> T </tex> taxa percepută. Notăm <tex> sum_{i,c} </tex> costul pentru a schimba toate pietrele <tex> 1, 2, \\ldots, i </tex> în culoarea <tex> c </tex> (<tex> c = 0 </tex> pentru alb şi <tex> c = 1 </tex> pentru negru). Rezultă că în <tex> sum_{i,c} </tex> se vor însuma toate valorile <tex> S_{j} </tex>, cu <tex> j \\le i </tex> pentru care <tex> C_{j} = 1 - c </tex>. \r\n\r\nÎn continuare, considerăm <tex> bst_{i,c} </tex> costul minim pentru a transporta pietrele <tex> 1, 2, \\ldots, i </tex>, iar ultimul transport conţine pietre de culoare <tex> c </tex>. Întrucât nu putem transporta mai mult de <tex> K </tex> pietre, <tex> bst_{i,c} </tex> depinde doar de poziţiile <tex> i - K, i - K + 1, \\ldots, i - 1 </tex>. Cunoaştem că ultimul camion va transporta o secvenţă continuă de pietre începând de la o poziţie <tex> j + 1 </tex> până la poziţia <tex> i </tex>, unde <tex> i - K \\le j \\le i - 1 </tex>. Astfel, pentru fiecare <tex> j </tex> în intervalul precedent, costul va fi <tex> Min(bst_{j,0}, bst_{j,1}) </tex> (transportăm primele <tex> j </tex> pietre cât mai ieftin) adunat cu <tex> sum_{i,c} - sum_{j,c} </tex> (costul transformării pietrelor <tex> j + 1, \\ldots, i </tex> în culoarea <tex> c </tex>) şi plus taxa <tex> T </tex>. Rezultă recurenţa:\r\n\r\n* <tex> bst_{i,c} = Min\\ \\{\\ Minim(bst_{j,0},\\ bst_{j,1}) + sum_{i,c} - sum_{j,c} + T\\ :\\ i - K \\le j \\le i - 1\\ \\}; </tex>\r\n\r\nDacă ne vom opri aici, complexitatea soluţiei va fi <tex> O(Q * N^{2}) </tex>.\r\n\r\nRelaţia de recurenţă poate fi îmbunătăţită. Observăm că pentru poziţia <tex> i </tex>, <tex> sum_{i,c} </tex> este o valoare constantă, ca şi <tex> T </tex>. Astfel, deducem următoarea relaţie de recurenţă:\r\n\r\n* <tex> bst_{i,c} = Min\\ \\{\\ Minim(bst_{j,0},\\ bst_{j,1}) - sum_{j,c}\\ :\\ i - K \\le j \\le i - 1\\ \\} + sum_{i,c} + T; </tex>\r\n\r\nNotez în continuare, pentru uşurinţă în scriere, <tex> T_{j,c} = Min(bst_{j,0}, bst_{j,1}) - sum_{j,c} </tex>. Să fixăm doi indici <tex> i_{1} </tex> şi <tex> i_{2} </tex>, astfel încât <tex> i - K \\le i_{1} < i_{2} \\le i - 1 </tex>. Dacă <tex> T_{i_{1},c} > T_{i_{2},c} </tex> atunci întotdeauna poziţia <tex> i_{2} </tex> va fi preferată poziţiei <tex> i_{1} </tex>. Când cele două nu se vor mai afla ambele în intervalul <tex> [i - K, i - 1] </tex>, poziţia eliminată va fi poziţia <tex> i_{1} </tex>. Dacă <tex> T_{i_{1},c} \\le T_{i_{2},c} </tex>, atunci nu putem decide care poziţie este mai bună în viitor, aşa că le vom păstra pe ambele. Rezultă mai departe, după cum am arătat în problemele anterioare, că în intervalul <tex> [i - K, i - 1] </tex> vom avea o serie de indecşi candidaţi la minim <tex> i - K \\le i_{1} < i_{2} < \\ldots < i_{n} \\le i - 1 </tex> astfel încât <tex> T_{i_{1},c} \\le T_{i_{2},c} \\le  ... \\le T_{i_{n},c} </tex>. Mai departe, găsim <tex> bst_{i,c} = T_{i_{1},c} + sum_{i,c} + T </tex>. Urmează să îl introducem şi pe <tex> T_{i,c} </tex> în şirul de indecşi de mai sus, el fiind egal cu <tex> Minim(bst_{i,0}, bst_{i,1}) - sum_{i,c} </tex>. Acest lucru se va face în felul următor: se vor elimina din <tex> i_{n}, , i_{n-1}, \\ldots </tex> atâta timp cât <tex> T_{i_{n},c} > T_{i,c} </tex>, <tex> T_{i_{n-1},c} > T_{i,c} \\ldots </tex> adică atâta timp cât poziţia <tex> i </tex> este preferată lui <tex> i_{n}, i_{n-1}, \\ldots </tex>. Fiind la poziţia <tex> i + 1 </tex>, intervalul se va transforma în <tex> [i - K + 1, i] </tex>, aşadar, vom mai elimina din primii indici <tex> i_{1}, i_{2}, \\ldots </tex> atâta timp cât <tex> i_{1} < i - K + 1, i_{2} < i - K + 1, \\ldots </tex>.\r\n\r\nDupă cum am arătat şi la problema precedentă, acest şir de indecşi <tex> i_{1}, i_{2}, \\ldots, i_{n} </tex> are proprietatea că este un şir continuu de numere care admite inserări şi ştergeri pe la capete ($head$ şi $tail$), şir ce poate fi reprezentat printr-un deque. Cum fiecare index dintre <tex> 1, 2, \\ldots, N </tex> va fi adăugat şi şters cel mult o singură dată din deque, complexitatea soluţiei va fi <tex> O(N) </tex> pentru fiecare camion, deci <tex> O(Q * N) </tex> în total.\r\n\r\nIată şi o sursă scurtă, clară şi eficientă pentru această problemă:\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\n#include <vector>\r\n#include <deque>\r\n#include <algorithm>\r\nusing namespace std;\r\n\r\nconst char iname[] = \"trans.in\";\r\nconst char oname[] = \"trans.out\";\r\n\r\n#define MAXN  16005\r\n#define Min(a, b) ((a) < (b) ? (a) : (b))\r\n#define FOR(i, a, b)  for (int i = (a); i <= (b); ++i)\r\n\r\nint C[MAXN], S[MAXN], bst[MAXN][2], sum[MAXN][2], N;\r\n\r\nvoid insert(deque < pair <int, int> >& deq, const pair <int, int>& p) {\r\n    while (!deq.empty() && deq.back().second > p.second)\r\n        deq.pop_back();\r\n    deq.push_back(p);\r\n}\r\n\r\nint query(deque < pair <int, int> >& deq, const int idx) {\r\n    while (deq.front().first < idx)\r\n        deq.pop_front();\r\n    return deq.front().second;\r\n}\r\n\r\nint work(const int K, const int T) {\r\n    deque < pair <int, int> > deq[2];       // pair (idx, value)\r\n    FOR (c, 0, 1)\r\n        insert(deq[c], pair <int, int>(0, 0));\r\n    FOR (i, 1, N) {   // obiectul i\r\n        FOR (c, 0, 1) // culoare\r\n            bst[i][c] = query(deq[c], i - K) + sum[i][c] + T;\r\n        FOR (c, 0, 1)\r\n            insert(deq[c], pair <int, int>(i, Min(bst[i][0], bst[i][1]) - sum[i][c]));\r\n    }\r\n    return Min(bst[N][0], bst[N][1]);\r\n}\r\n\r\nint main(void) {\r\n    ifstream in(iname);  ofstream out(oname);\r\n    in >> N;\r\n    FOR (i, 1, N) {\r\n        in >> C[i] >> S[i];\r\n        FOR (c, 0, 1)\r\n            sum[i][c] += sum[i - 1][c];\r\n        sum[i][1 - C[i]] += S[i];\r\n    }\r\n    int cnt, K, T;\r\n    in >> cnt;\r\n    FOR (i, 1, cnt)\r\n        in >> K >> T, out << work(K, T) << \"\\n\";\r\n\r\n    in.close(), out.close();\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#problema-6). 6. \'Otilia\':problema/otilia  (.campion, 2005)\r\n\r\nbq. Otilia şi Burbucel au o grămadă de $N$ pietre şi vor juca un joc cu următoarele trei reguli: 1. Primul jucător are voie să ia din gramadă cel mult $K$ piese; 2. Cu excepţia primei mutări, fiecare jucător are voie să ia maxim $P * t$ pietre, unde $t$ este numărul de pietre care au fost substituite din grămadă la mutarea precedentă; 3. Pierde cel care mută ultimul (cel care ia ultimele pietre din grămadă).\r\nCerinţă: Se dau $M$ jocuri prin numerele $N$, $K$ şi $P$. Se cere să se determine pentru fiecare joc dacă Otilia va câştiga sau nu.\r\nRestricţii: $1 &le; M &le; 30.000$, $1 &le; N &le; 5.000.000$, $1 &le; K &le; N$, $1 &le; P &le; 10$.\r\n\r\nh3. Soluţie (Silviu Gănceanu):\r\n\r\nProblema se rezolvă prin programare dinamică. Soluţia se bazează pe observaţia de mai jos. Considerăm $P$-ul fixat şi notăm cu $stare(X, Y)$ poziţia de start în care avem $X$ pietre şi numărul maxim de pietre care se pot lua la prima mutare este $Y$.\r\n\r\n_Observaţia 1_: „Dacă există strategie sigură de câştig pentru $stare(X, Y)$ atunci există şi pentru orice $stare(X, T)$ cu $T &ge; Y$.” \r\n\r\nDe ce? Pentru că orice mutare validă pentru $stare(X, Y)$ este validă şi pentru $stare(X, T)$. Având această observaţie notăm cu $MinY[X] = Y$, $Y$ minim astfel încât avem strategie de câştig pentru $stare(X, Y)$.\r\n\r\n_Observaţia 2_: „{$stare(X, Y)$} este pierzătoare dacă şi numai dacă $Y < MinY[X]$.” \r\n\r\nAceasta reiese din definiţia lui $MinY[X]$.\r\n\r\n$MinY[X]$ se calculează după următoarea recurenţă, care rezultă din regulile jocului: \r\n\r\n* $MinY[X]$ este cel mai mic $i$ pentru care avem $MinY[X - i] > P * i$.\r\n\r\nDe aici se naşte prima soluţie, care este implementarea directă a recurenţei. Deşi complexitatea acesteia pare a fi $O(N^2^)$ ea se comportă foarte bine pentru $N &le; 500 000$. Aşadar, această soluţie acoperă aproximativ $50%$ din testele de intrare. Printr-o rafinare a acestei soluţii se obţine un algoritm de complexitate $O(N)$. Rafinarea se bazează pe: \r\n\r\n_Observaţia 3_: „Să presupunem că dorim să calculăm $MinY[X]$. Facem următoarea afirmaţie: orice poziţie _rea_ pentru $X$ (în care dacă mutăm pierdem) va fi _rea_ şi pentru $X + 1$.”\r\n\r\nAcest lucru este simplu de observat dacă privim ce înseamnă că o poziţie $Q$ e rea pentru $X$: \r\n\r\n* $MinY[Q] > X - Q$, pentru $X$;\r\n* $MinY[Q] > X - Q + 1$, pentru $X + 1$.\r\n\r\nEste evident că prima relaţie o implică pe cea de-a doua. În momentul acesta se poate construi următorul algoritm: având lista de poziţii care pot fi bune pentru $X$ (sortată descrescător) o căutăm pe cea mai mare ca valoare care este într-adevăr bună. În principiu, scoatem din capul listei poziţiile rele până când dăm de o poziţie bună. La listă se va adăuga şi $X$ şi se va trece la pasul următor. Operaţiile algoritmului sunt chiar operaţiile asupra unui deque.\r\n\r\nh2(#problema-7). 7. \'Bcrc\':problema/bcrc (Stelele Informaticii, 2006)\r\n\r\nbq. Se consideră $N$ camere, numerotate de la $1$ la $N$, aşezate în cerc. Iniţial (la momentul de timp 0), ne aflăm în camera $1$. În fiecare moment de timp, putem alege să rămânem în camera în care ne aflăm sau să ne deplasăm într-o cameră vecină într-o unitate de timp. Se dă o listă de $M$ cutii ce conţin bomboane prin $T$, $C$ şi $B$: cutia apare la momentul $T$ în camera $C$ şi conţine $B$ bomboane. Cutia va dispărea la momentul $T + 1$.\r\nCerinţă: Cunoscând numărul de camere din labirint şi momentele de timp la care apar cutiile cu bomboane, determinaţi care este numărul maxim de bomboane pe care le putem culege.\r\nRestricţii: $3 &le; N &le; 2.048$, $0 &le; M &le; 50.000$, $1 &le; T &le; 1.000.000.000$, $1 &le; C &le; N$, $1 &le; B &le; 9.999$.\r\n\r\nh3. Soluţie:\r\n\r\nSoluţia foloseşte metoda programării dinamice.\r\n\r\nO stare se reprezintă prin camera în care ne aflăm şi momentul de timp. Fie <tex> bst_{i,j} </tex> numărul maxim de bomboane culese până în momentul <tex> i </tex> când ne găsim în camera <tex> j </tex>. O observaţie evidentă este că <tex> bst_{i,j} </tex> se poate modifica doar în momentele în care apar cutiile. Prin urmare, vom considera momentele de timp când apar cutiile, momente ce sunt în număr de <tex> M </tex>, <tex> bst_{i,j} </tex> însemnând numărul maxim de bomboane culese ştiind că ne aflăm în camera <tex> j </tex> după ce am cules cutia <tex> i </tex>. De cine depinde această stare? Ştim că <tex> bst_{i-1,1 \\ldots N} </tex> a fost deja calculat în mod optim. Să notăm cu <tex> T </tex> diferenţa de timp dintre momentele la care apar cutia <tex> i </tex> şi cutia <tex> i - 1 </tex>. În această stare, cutie <tex> i </tex> şi cameră <tex> j </tex>, putem ajunge din maxim <tex> T </tex> camere spre stânga sau spre dreapta, întrucât fiecare deplasare între două camere costă o unitate de timp. De unde deducem că:\r\n\r\n* <tex> bst_{i,j} = Max\\{\\ bst_{i-1,j-T},\\ bst_{i-1,j-T+1}, \\ldots,\\ bst_{i-1,j}, \\ldots,\\ bst_{i-1,j+T-1},\\ bst_{i-1,j+T}\\ \\}; </tex>\r\n\r\nMetoda directă, şi aparent eficientă, constă în folosirea unui arbore de intervale pentru aflarea acestui maxim. Însă, intervalul <tex> [j-T,j+T] </tex> se deplasează constant spre dreapta, dacă vom considera indicii <tex> j </tex> în ordine <tex> 1, 2, 3, \\ldots </tex>. În acest interval noile elemente se introduc prin dreapta şi altele se elimină prin stânga. Însă, cum am arătat în problemele precedente, nu avem nevoie de toate valorile din acest interval. Şi din acest motiv vom folosi un deque de lungime maximă <tex> T * 2 + 1 </tex> cu care vom elimina poziţiile care nu sunt candidate la soluţie. Mai jos este o reprezentare grafică a deplasării intervalului menţionat mai sus.\r\n\r\np=. !deque-si-aplicatii?bcrc.png 40%!\r\n\r\nComplexitatea finală: <tex> O(M * N) </tex>.\r\n\r\nh2(#problema-8). 8. \'Cut the Sequence\':http://acm.pku.edu.cn/JudgeOnline/problem?id=3017 (PKU) \r\n\r\nbq. Se dă o secvenţă $S$ de $N$ numere întregi. Va trebui să se împartă secvenţa în mai multe subsecvenţe astfel încât suma valorilor din fiecare parte să nu depăşească un număr întreg $M$ dat, iar dacă însumăm maximul din fiecare subsecvenţă să obţinem o sumă cât mai mică.\r\nRestricţii: $0 &lt; N &le; 100.000$, $0 &le; S{~i~} &le; 1.000.000$.\r\n\r\nh3. Soluţie:\r\n\r\nŞi această soluţie foloseşte metoda programării dinamice. Construim <tex> bst_{i} </tex> egal cu costul minim de a împărţi primele <tex> i </tex> numere din <tex> S </tex>. Pentru a calcula <tex> bst_{i} </tex> alegem toate secvenţele posibile care încep la o poziţie <tex> j+1 </tex>, <tex> j < i </tex>, şi adunăm valorile corespunzătoare:\r\n\r\n* <tex> bst_{i} = Min\\{bst_{j} + Max\\{S_{j+1},.., S_{i}\\}\\ :\\ 0 \\le j < i, \\displaystyle\\sum_{k=j+1}^{i} S_{k} \\le M\\}; </tex>\r\n\r\nImplementarea directă a acestei recurenţe conduce la un algoritm de complexitate <tex> O(N^{2}) </tex>, dar care pentru restricţiile impuse nu este de ajuns.\r\n\r\nSă obţinem în continuare alte informaţii. Fie indicele <tex> j </tex> minim astfel încât <tex> \\displaystyle\\sum_{k=j+1}^{i} \\le M </tex>. Maximul obţinut din mulţimea <tex> \\{S_{j+1},.., S_{i}\\} </tex> se găseşte pe o poziţie <tex> j^{\'} </tex> unde <tex> j < j^{\'} \\le i </tex>. Însă, orice indice <tex> k </tex> cu <tex> j \\le k < j^{\'} </tex> are proprietatea că rezultatul expresiei <tex> Max\\{S_{k+1},.., S_{i}\\} </tex> se găseşte pe poziţia <tex> j^{\'} </tex>. Rezultă că <tex> \\forall k \\in \\{j, j+1,.., j^{\'}-1\\} </tex>, <tex> bst_{i} </tex> poate fi îmbunătăţit cu valoarea <tex> bst_{k} + S_{j^{\'}} </tex>. Minimul mulţimii <tex> \\{bst_{k} + S_{j^{\'}} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} </tex> este egal cu minimul expresiei <tex> \\{bst_{k} : \\forall k \\in \\{j, j+1,.., j^{\'}-1\\}\\} + S_{j^{\'}} (*) </tex>, deci, schimbând reperele, pentru maximul de pe poziţia <tex> j^{\'} </tex>, dacă lungimea secvenţei care se termină în <tex> i </tex> este cel puţin <tex> i-j^{\'}+1 </tex>, atunci optimul se obţine calculând rezultatul expresiei <tex> (*) </tex>. Pentru minimul valorilor vectorului <tex> bst </tex> pe un interval <tex> [j, j^{\'}-1] </tex> putem folosi un arbore de intervale pentru <tex> O(log_{2}N) </tex> pe interogare.\r\n\r\nDar, lungimea optimă a ultimei secvenţe ce se termină în <tex> i </tex> poate fi mai mică decât <tex> i-j^{\'}+1 </tex>, deci poate fi cel mult <tex> i-j^{\'} </tex>. Optimul se găseşte printre elementele mulţimii <tex> \\{bst_{k} + Max\\{S_{k+1},..,S_{i}\\} : j^{\'} \\le k < i\\} </tex>. Dacă procedăm ca la pasul anterior vom obţine un alt indice <tex> j^{\'\'} </tex> cu aceleaşi proprietăţi pentru secvenţa <tex> [j^{\'}, i] </tex> precum <tex> j^{\'} </tex> pentru secvenţa <tex> [j, i] </tex>.\r\n\r\nInductiv obţinem un şir de indici <tex> j_{0} = j < j_{1} < j_{2} < .. < j_{K} = i </tex> astfel încât <tex> S_{j_{1}} </tex> este cel mai mare element al secvenţei <tex> (j, i] </tex>, <tex> S_{j_{2}} </tex> cel mai mare element al secvenţei <tex> (j_{1}, i] </tex>, şi aşa mai departe, când <tex> j_{K} </tex> este chiar <tex> i </tex>.\r\n\r\nCu ajutorul relaţiei <tex> (*) </tex> şi a şirului <tex> j_{1} < j_{2} < .. < j_{K} = i </tex> vom construi un alt vector <tex> iMin </tex> cu proprietatea că <tex> iMin_{p} = Min\\{bst_{r} + S_{j_{p}} : j_{p-1} \\le r < j_{p}\\} </tex>. În final, <tex> bst_{i} = Minim\\{iMin_{1}, iMin_{2}, .., iMin_{K}\\} </tex>, rezultat pe care îl putem obţine în <tex> O(log_{2}N) </tex> dacă folosim un arbore de intervale.\r\n\r\nÎnsă, cum se construieşte şirul <tex> j_{1} < j_{2} < .. < j_{K} = i </tex>? În \'a doua problemă\':deque-si-aplicatii#problema-2 am construit cu ajutorul unui deque exact şirul de indici de care avem nevoie aici. Când vom înainta la indicele <tex> i + 1 </tex> vom modifica şirul astfel încât să respecte proprietăţile de mai sus utilizând operaţiile normale asupra unui deque. Mai sus am menţionat cum se obţine <tex> bst_{i} </tex> lucru care implică combinarea structurilor de deque şi arbore de intervale. Arborele de intervale reţine valorile lui <tex> iMin </tex> pentru fiecare element al deque-lui. \r\n\r\nPentru a înţelege cum funcţionează acest algoritm să considerăm ca date de intrare şirul <tex> S = \\{5, 9, 4, 7, 4, 1, 6, 3\\} </tex> şi <tex> M = 15 </tex>. Perechile din deque sunt de forma <tex> (S_{i}, iMin_{p}) </tex>. Fie <tex> i = 1, 2, \\ldots 8 </tex>:\r\n\r\n* <tex> i = 1: j = 0, head = 1, tail = 1, deque = \\{\\ (5, 0)\\ \\} \\Rightarrow bst_{1} = 5; </tex>\r\n* <tex> i = 2: j = 0, head = 1, tail = 1, deque = \\{\\ (9, 0)\\ \\} \\Rightarrow bst_{2} = 9; </tex>\r\n* <tex> i = 3: j = 1, head = 1, tail = 2, deque = \\{\\ (9, 5),\\ (4, 9)\\ \\} \\Rightarrow bst_{3} = 13; </tex>\r\n* <tex> i = 4: j = 2, head = 2, tail = 2, deque = \\{\\ (7, 9)\\ \\} \\Rightarrow bst_{4} = 16; </tex>\r\n* <tex> i = 5: j = 2, head = 2, tail = 3, deque = \\{\\ (7, 9),\\ (4, 16)\\ \\} \\Rightarrow bst_{5} = 16; </tex>\r\n* <tex> i = 6: j = 3, head = 2, tail = 4, deque = \\{\\ (7, 13),\\ (4, 16),\\ (1, 16)\\ \\} \\Rightarrow bst_{6} = 17; </tex>\r\n* <tex> i = 7: j = 4, head = 3, tail = 3, deque = \\{\\ (6, 16)\\ \\} \\Rightarrow bst_{7} = 22; </tex>\r\n* <tex> i = 8: j = 4, head = 3, tail = 4, deque = \\{\\ (6, 16),\\ (3, 22)\\ \\} \\Rightarrow bst_{8} = 22; </tex>\r\n\r\nMai jos se vede o figură în care elementele unui deque sunt de fapt o secvenţă \"continuă\" de frunze ale unui arbore de intervale pentru cazul <tex> i = 6 </tex>.\r\n\r\np=. !deque-si-aplicatii?PKU0.png 60%!\r\n\r\np=. _Numărul maxim de elemente ce pot trece prin deque este $8$. În figură, arborele ţine minimul de pe poziţiile $2$, $3$, $4$ din deque._\r\n\r\nAlgoritmul în pseudocod arată în felul următor:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    sum  = 0;\r\n    last = 0;\r\n    // indicii head si tail ai dequeului\r\n    head = tail = 1;\r\n    // poziţia lui bst[0] se inserează în deque\r\n    deque[1] = 0;\r\n    pentru i = 1, N execută\r\n        sum += S[i];\r\n        temp = bst[ deque[tail] ];\r\n        cât timp (head <= tail) şi (S[ deque[tail] ] <= S[i]) execută\r\n            temp = Min(temp, iMin[tail]);\r\n            tail--;\r\n        sfârşit;\r\n        // adaug poziţia i la deque\r\n        tail++;\r\n        deque[tail] = i;\r\n        // actualizez iMin[]\r\n        iMin[tail]  = temp;\r\n        // actualizez T[], arborele de intervale pe deque[]\r\n        Update(T, tail, iMin[tail] + S[i]);\r\n        // suma valorilor din [last, i] trebuie să nu depăşească M\r\n        cât timp (sum > M) execută\r\n            sum -= S[last];\r\n            dacă (deque[head] == last) atunci\r\n                head++;\r\n            sfârşit;\r\n            last++;\r\n        sfârşit;\r\n        // actualizez iMin[], Tb[] arborele de intervale pe bst[]\r\n        iMin[head] = Query(Tb, Max(last - 1, 0), deque[head] - 1);\r\n        // actualizez T[]\r\n        Update(T, head, iMin[head] + S[ deque[head] ]);\r\n        // reţin optimul pentru poziţia curentă\r\n        bst[i] = Query(T, head, tail);\r\n        // actualizez Tb[]\r\n        Update(Tb, i, bst[i]);\r\n    sfârşit;\r\n    scrie bst[N];\r\nSfârşit.\r\n==\r\n\r\nComplexitatea finală este <tex> O(N*log_{2}N) </tex>.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nFilozofia din spatele structurii de deque devine utilă, de obicei, în părţile finale ale rezolvării unei probleme. Însă, ce pot spune cu certitudine este că această structură de date, pe cât este de simplă, pe atât este de eficientă şi necesară.\r\n\r\nh2(#probleme-suplimentare). Probleme suplimentare\r\n\r\nÎnţelegerea profundă nu se poate realiza decât prin rezolvarea a cât mai multor probleme. Succes!\r\n\r\n* \'Deque\':problema/deque, _Arhiva educaţională_\r\n* \'Secvenţă\':problema/secventa\r\n* \'Secvenţă 3\':problema/secv3\r\n* \'Secvenţă 4\':problema/secv4\r\n* \'Sum 2\':problema/sum2, _Stelele Informaticii, 2003_\r\n* \'Drept 2\':problema/drept2, _Lotul Naţional de Informatică, 2006_\r\n* \'Copaci 2\':problema/copaci2, _.campion, 2007_\r\n* \'Struţi\':problema/struti\r\n* \'Brânză\':problema/branza\r\n* \'Trompetă\':problema/trompeta\r\n* \'Buline\':problema/buline\r\n* \'Balans\':problema/balans\r\n* \'Ksecv\':problema/ksecv, _Selecţie echipe ACM ICPC, UPB, 2008_\r\n* \'Munte4\':problema/munte4, _Lotul Naţional de Informatică, 2005_\r\n* \'Gard\':problema/gard, _ONI, 2002_\r\n* \'Ghiozdan\':problema/ghiozdan\r\n* \'Cover\':problema/cover, _Baraj ONI, 2007_\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# D.E. Knuth, \"_The Art of Computer Programming, Volume 1: Fundamental Algorithms, Third Edition_\", Addison-Wesley, 1997\r\n# Cosmin Negruşeri, \"_Probleme cu secvenţe_\":probleme-cu-secvente\r\n# Dana Lica, \"_Arbori de intervale şi aplicaţii în geometria computaţională_\":arbori-de-intervale\r\n# wikipedia, \'_Deque_\':http://en.wikipedia.org/wiki/Deque\r\n# \'C++ Reference\':http://www.cplusplus.com/',3146,'public',3802,NULL),('grigore-moisil-2009/9','moisil2009-9','2009-03-31 18:58:39','2009-03-31 19:23:40','h1. == roundparam(round_id=\"moisil2009-9\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':grigore-moisil-2009 \r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n*(active) \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n* \'Rezultate\':grigore-moisil-2009/clasament/\r\n\r\n== roundregister(round_id=\"moisil2009-9\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"moisil2009-9\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"moisil2009-9\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/moisil2009-9/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"moisil2009-9\" score=\"1\")==',2092,'round: moisil2009-9',NULL,NULL),('training-path','Training path','2008-01-22 17:36:01','2009-01-16 19:07:26','h1. Training path\r\n\r\nVrem sa intocmim o baza de cunostinte fara precendent! Vrem ca aceasta pagina sa contina o lista cat mai completa cu ce trebuie sa stie un olimpic pentru a avea succes. \'Ajuta-ne\':implica-te/scrie-articole si tu!\r\n\r\n*Cosmin:* ar trebui sa facem o lista mai mica cu chestiile importante ca sa ajungi la ONI, ca sa nu se sperie cei ce abia incep.\r\n\r\nh2. Structuri de date\r\n\r\n* Liste, stive, cozi\r\n* Smenul cu deque\r\n* \'Tabele de dispersie\':hashing\r\n** \'Cuckoo hashing\':http://en.wikipedia.org/wiki/Cuckoo_hashing\r\n* \'Bloom filters\':http://en.wikipedia.org/wiki/Bloom_filter\r\n* \'Skiplists\':skiplists\r\n\r\n* \'Arbori indexati binar\':aib\r\n* Cozi de prioritati\r\n** \'Heap-uri\':heapuri\r\n** Mergeable heaps (maxophobic heaps sunt cel mai simple)\r\n** Pentru costuri intregi mici, un array de liste\r\n\r\n* Structuri de multimi disjuncte\r\n* \'Arbori de intervale\':arbori-de-intervale\r\n* \'Tries\':problema/trie\r\n* Arbori binari de cautare (\'Treapuri\':treapuri, AVL, red-black trees)\r\n* \'Cautari ortogonale. Quad trees, kD-trees\':cautari-ortogonale\r\n\r\nh2. Algoritmi si tehnici de programare\r\n\r\nh3. Matematica\r\n\r\n* Inductie matematica\r\n* \'Algoritmul lui Euclid\':algoritmul-lui-euclid\r\n* CMMDC binar\r\n* \'Ciurul lui Erathostene\':ciurul-lui-erathostene\r\n* \'Gray code\':coduri-gray\r\n* Rezolvare de ecuatii liniare modulare\r\n* Teorema mica a lui Fermat\r\n* \'Teorema chineza a resturilor\':teorema-chineza-a-resturilor\r\n** Probleme: \'eval\':problema/eval \'resturi\':problema/resturi \'gears in action\':http://ipsc.ksp.sk/contests/ipsc2005/real/problems/g.php\r\n* \"Numere mari: adunare, scadere, inmultire, impartire, radical\":lucrul-cu-nr-mari\r\n* Recurente si exponentiere rapida de matrici (+evaluare rapida a expresiilor folosind exponentiere in timp logaritmic)\r\n* \'Principiul includerii si excluderii\':principiul-includerii-si-excluderii\r\n** Probleme: \'cowfood\':problema/cowfood, \'indep\':problema/indep, \'frac\':problema/frac\r\n* Sisteme de ecuatii liniare (Gauss)\r\n** Teorie:\r\n*** \'Gaussian elimination\':http://en.wikipedia.org/wiki/Gaussian_elimination\r\n*** \'Row echelon form\':http://en.wikipedia.org/wiki/Row_echelon_form\r\n** Probleme: \'SGU 275 To xor or not to xor\':http://acm.sgu.ru/problem.php?contest=0&problem=275 \'.campion Xor\':http://campion.edu.ro/problems/3/323/xor_ro.htm \'SGU 260 Puzzle\':http://acm.sgu.ru/problem.php?contest=0&problem=260 \'UVA 10808\':http://online-judge.uva.es/p/v108/10808.html \'UVA 326\':http://online-judge.uva.es/p/v3/326.html \'UVA 10014\':http://online-judge.uva.es/p/v100/10014.html \'BColor\':problema/bcolor \'Laser\':problema/laser \'TC XORing\':http://www.topcoder.com/stat?c=problem_statement&pm=4829&rd=8095&rm=246636&cr=270505 \'TC Escape the jail\':http://www.topcoder.com/stat?c=problem_statement&pm=7353 \'Register CEOI 2003\':http://ceoi.inf.elte.hu/probarch/03/register-en.pdf \'Tunelul groazei\':problema/tunel \'SGU 200\':http://acm.sgu.ru/problem.php?contest=0&problem=200 \'TC CoinGame\':http://www.topcoder.com/stat?c=problem_statement&pm=6005 \r\n* Simplex (pur si simplu un hill climbing pe mai multe variabile)\r\n* \"Floyd\'s cycle finding\":http://en.wikipedia.org/wiki/Cycle_detection\r\n* Combinatorica\r\n** Permutari, permutari cu repetitii, aranjamente, combinari, Stirling, Catalan, Bell, Fibonacci\r\n** Trecere de la combinare/permutare la indexul ei si invers\r\n** \'Codul Prufer. Numarare de arbori\':http://en.wikipedia.org/wiki/Pr%C3%BCfer_sequence\r\n\r\nh3. Geometrie\r\n\r\n\'computer graphics FAQ\':http://www.faqs.org/faqs/graphics/algorithms-faq/\r\n\'cursuri dupa Computational Geometry: Algorithms and Applications, Mark de Berg, M. van Krefeld, M. Overmars, O. Schwarzkopf\':http://www.cs.umd.edu/class/spring2007/cmsc754/Lects/754lects.pdf\r\n\r\n\r\n* Intersectie a doua segmente\r\n* Punct in interiorul unui poligon\r\n** http://geometryalgorithms.com/Archive/algorithm_0103/algorithm_0103.htm\r\n** http://tog.acm.org/editors/erich/ptinpoly/\r\n* Punct in poligon convex in $O(log n)$\r\n** http://geometryalgorithms.com/Archive/algorithm_0103/algorithm_0103.htm#Monotone%20Polygons\r\n* \'Teorema lui Pick\':http://www.cut-the-knot.org/ctk/Pick_proof.shtml\r\n** problema \'copaci\':problema/copaci\r\n* Aria unui poligon\r\n* Centrul de greutate al unui poligon\r\n* \'Triangularizare de poligon in $O(n^2)$\':http://people.csail.mit.edu/indyk/6.838-old/handouts/lec4.pdf\r\n* \'Intersectia a doua cercuri\':http://local.wasp.uwa.edu.au/~pbourke/geometry/2circle/\r\n* \'Minimal enclosing circle\':minimal-enclosing-circle\r\n* Convex hull\r\n** \'Aplicatie din Arhiva Educationala\':problema/infasuratoare\r\n** http://www.algorithmist.com/index.php/Monotone_Chain_Convex_Hull\r\n** http://en.wikipedia.org/wiki/Gift_wrapping_algorithm\r\n** Aplicatie - onion peeling in O(n^2^)\r\n* \'Baleiere verticala / radiala\':algoritmi-de-baleiere\r\n** baleiere radiala\r\n*** Se da un set S de n punct in plan. Sa se determine cercul de raza R fixata care acopera cat mai multe puncte din S. O(n^2 log n)\r\n*** Se da un set S de n puncte in plan. Sa se gaseasca o dreapta ce trece prin nr maxim de puncte din S. O(n^2^) cu hashuri pt unghiuri sau O(n^2 log n) cu baleiere radiala.\r\n*** Se da un set S de n segmente in plan. Sa se gaseasca o dreapta ce intersecteaza numarul maxim de segmente din S. O(n^2 log n) cu baleiere radiala.\r\n*** \'Construirea grafului de vizibilitate.\':http://en.wikipedia.org/wiki/Visibility_graph\r\n* \'Rotating calipers\':http://cgm.cs.mcgill.ca/~orm/rotcal.html\r\n** problema \'rubarba\':problema/rubarba\r\n** problema \'popandai2\':problema/popandai2\r\n* Intersectie de poligoane convexe\r\n* Intersectie de semiplane (fara dualizare)\r\n** problema \'camera\':problema/camera\r\n* \'Dualizare (intersectie de semiplane, diagrame Voronoi)\':http://infoarena.ro/voronoi\r\n\r\n* \'thread pe forum\':http://infoarena.ro/forum/index.php?topic=3007.0\r\n\r\nh3. Sortari si cautari\r\n\r\n* Shell sort, merge sort, heapsort, quicksort, counting sort, radix sort\r\n* Statistici de ordine\r\n* Cautare binara/ternara si \'aplicatii\':aplicatii-ale-cautarii-binare\r\n* Hill climbing\r\n\r\nh3. Greedy\r\n\r\n* Huffman\r\n* Job scheduling\r\n\r\nh3. Programare dinamica\r\n\r\n* Parantezare optima de matrici\r\n* \'Cel mai lung subsir crescator $O(N*log N)$\':problema/scmax\r\n* Knapsack\r\n** Knapsack pe biti\r\n* \'Cel mai lung subsir comun\':problema/cmlsc\r\n* Distanta de editare\r\n* Ciclu hamiltonian in $O(n^2^ * 2^n^)$\r\n** problema \'adn\':problema/adn\r\n* Dinamicile in $3^n^$\r\n** \'explicatie\':http://forums.topcoder.com/?module=Thread&threadID=512824&start=0, \'problema\':http://www.topcoder.com/stat?c=problem_statement&pm=6678&rd=9998&rm=249548&cr=8547850\r\n* \'Arbore de cautare optim in $O(n^2)$\':http://www.ics.uci.edu/~dan/class/165/notes/OptBST.html\r\n* Dinamici pe arbori\r\n* \'Numarul posibilitatilor de acoperire a unei table cu dominouri\':probleme-de-acoperire-2#problema3\r\n* Memoizare (trading space for time)\r\n\r\nh3. Grafuri\r\n\r\n* Parcurgeri\r\n** \'DFS\':problema/dfs, \'BFS\':problema/bfs, meet in the middle bfs\r\n** \'Componente biconexe\':problema/biconex\r\n** \'Componente tare-conexe\':problema/ctc\r\n** Sortare topologica\r\n** \'Ciclu eulerian\':problema/ciclueuler\r\n\r\n* Drumuri minime\r\n** \'Dijkstra\':problema/dijkstra (cu heapuri, cu set-uri, cu AINT-uri, cu coada ca pe TC - Cosmin stie)\r\n** \'Dijkstra cu costuri mici ;)\':http://www.ginfo.ro/revista/13_6/focus2.pdf cum se foloseste la problema \'car\':problema/car\r\n** A* has a lot of intuitive appeal for me. If you compare Dijkstra\'s vs. A*, Dijkstra\'s is like a puddle of water flooding outwards on a flat floor, whereas A* is like the same puddle expanding on a bumpy and graded floor toward a drain (the target node) at the lowest point in the floor. Instead of spreading out evenly on all sides, the water seeks the path of least resistance, only trying new paths when something gets in its way. The heuristic function is what provides the \'grade\' of the hypothetical floor.\r\n*** A* se foloseste foarte mult in industria jocurilor, fiind un algoritm foarte rapid in practica. Un exemplu unde este folosit este jocul de strategie Starcraft.\r\n** \'Floyd-Warshall\':problema/royfloyd\r\n** \'Bellman-Ford\':wiki/Bellman-Ford_algorithm\r\n*** De obicei mai simplu de implementat si cam aceeasi viteza ca si Dijkstra cu heapuri\r\n*** Sistem de inegalitati\r\n*** \'Ciclu de cost mediu minim\':ciclu-de-cost-mediu-minim\r\n* \'Flux\':problema/maxflow\r\n** Edmonds-Karp\r\n** \'Taietura minima\':taietura-minima\r\n** \'Dinic\':http://www.msri.org/about/computing/docs/magma/html/text1499.htm\r\n** \'Flux maxim de cost minim\':problema/fmcm\r\n** Flux cu capacitati inferioare\r\n** Circulatii\r\n** Problema postasului chinez\r\n*** problema \'traseu\':problema/traseu\r\n* Arbori\r\n** \'Diametrul, centrul unui arbore\':http://online-judge.uva.es/board/viewtopic.php?p=36766&highlight=#36766\r\n** \'Testare daca doi arbori sunt izomorfi\':http://online-judge.uva.es/board/viewtopic.php?p=22754&highlight=#22754\r\n** Cod Prufer\r\n* \'APM\':problema/apm\r\n** Prim\r\n** Kruskal\r\n** Al doilea APM\r\n** APM in graf orientat\r\n** Kirchhoff\'s matrix tree theorem\r\n* Pentru grafuri bipartite: \'cuplaj maxim\':problema/cuplaj, suport minim, multime independenta maxima\r\n* \'LCA\':lowest-common-ancestor, \'RMQ\':problema/rmq, Level Ancestor, \'Tree decompositions\':tree-decompositions\r\n* Colorari de muchii, graf complet/bipartit/oarecare (teorema lui Vizing)\r\n* Grafuri planare\r\n** problema \'count\':problema/count\r\n* Grafuri turneu/ciclu hamiltonian\r\n** problema \'plimbare\':problema/plimbare\r\n* {\'Implication graph si 2-SAT\':2-sat}\r\n\r\n\r\nh3. Siruri de caractere\r\n\r\n* \'Hashuri\':problema/strmatch\r\n* \'KMP\':automate-finite-si-kmp\r\n* \'Siruri de sufixe\':siruri-de-sufixe\r\n** \'In timp liniar\':suffix-array-liniar\r\n* \'Aho-Corasick\':http://www.cs.uku.fi/~kilpelai/BSA05/lectures/slides04.pdf .\r\n\r\nh3. Limbaje formale si automate finite\r\n\r\n* Evaluari de expresii aritmetice\r\n* \'CYK\':http://en.wikipedia.org/wiki/CYK\r\n* Matching with wildcards\r\n* Construirea unui automat care sa accepte un set de cuvinte\r\n* Simplificare de automate\r\n* Echivalenta de automate\r\n* \'thread pe forum\':http://infoarena.ro/forum/index.php?topic=3005.0\r\n\r\nh3. Teoria jocurilor\r\n\r\n* Nim\r\n* \'Numere Sprague-Grundy\':numerele-sprague-grundy\r\n* Min-max\r\n* Alpha-beta\r\n\r\nh2. Diverse\r\n\r\nh3. \'STL @(Standard Template Library)@\':stl\r\n\r\n* vector, deque, stack, list\r\n* string\r\n* set, map, hash_map\r\n* pair\r\n* sort\r\n* priority_queue\r\n* bitset\r\n* iteratori\r\n\r\nh3. Cautari\r\n\r\n* backtracking\r\n* iterative deepening\r\n* branch and bound\r\n\r\nh3. Optimizari\r\n\r\n* Parsare\r\n* Lucru cu biti\r\n* Brute force\r\n** \'dancing links\':http://en.wikipedia.org/wiki/Dancing_Links\r\n\r\nh3. Lucrul cu memoria\r\n\r\n* \'Cacheuri de memorie\':http://en.wikipedia.org/wiki/CPU_cache\r\n** problema \'stramosi\':problema/stramosi\r\n*  \'free lists\':http://www.memorymanagement.org/glossary/f.html#free.list\r\n** problema \'eprubeta\':problema/eprubeta\r\n\r\nh3. Bulanit\r\n\r\n* Randomizare (2-opt, k-opt)\r\n* Constante\r\n* Interpolare Taylor / Gauss pentru formule polinomiale\r\n\r\nh3.  Smenuri\r\n\r\n* Smenu\' lui Batog (+ lca in $sqrt(n)$)\r\n** probleme: \'schi\':problema/schi, \r\n* Smenu\' lui Mars\r\n** problema \'cuburi\':http://campion.edu.ro/do_download.php?problem_id=122&type=application/pdf&year=2003&lang=ro\r\n* \'Meet in the middle\':meet-in-the-middle\r\n\r\nh2. Carti utile\r\n\r\n* Ioan Tomescu\r\n** \"Probleme de combinatorica si teoria grafurilor\" (din care s-a dat la ONI sau lot aproape in fiecare an cate o problema sau mai multe)\r\n** \"Combinatorica si teoria grafurilor\"\r\n* Ioan Cuculescu\r\n** \"Olimpiadele Internationale de Matematica ale Elevilor\"\r\n* E. A. Morozova, I. S. Petracov, V. A. Skvortov\r\n** \"Olimpiade internationale de matematica\"\r\n* \"Probleme de matematica traduse din revista sovietica KVANT\"\r\n* A. M. Iaglom, I. M. Iaglom\r\n** \"Probleme neelementare tratate elementar\"\r\n* Thomas H. Cormen, Charles E. Leiserson, Ronald R. Rivest\r\n** \'\"Introducere in algoritmi\"\':http://libris.agora.ro/algoritmi.html\r\n* D. E. Knuth\r\n** \"Arta programarii calculatoarelor\" (\"The Art of Computer Programming\")\r\n** \"Concrete Mathematics\"\r\n* Jon Bentley\r\n** \"Programming Pearls\"\r\n* Steven Skiena\r\n** \"The Algorithm Design Manual\"\r\n* W. Rytter\r\n** \"Jewels of Stringology\"\r\n* Mark de Berg\r\n** \"Computational geometry\"\r\n',3146,'public',NULL,NULL),('grigore-moisil-2009','Grigore Moisil 2009','2009-03-31 19:07:10','2009-03-31 19:27:41','h1. Grigore Moisil 2009\r\n\r\n(htabs)*(active) \'Despre...\':grigore-moisil-2009 \r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n* \'Rezultate\':grigore-moisil-2009/clasament/\r\n\r\nInfoarena organizeaza si in acest an editia online a concursului interjudetean de informatica Grigore Moisil. Concurentii pot profita de aceasta ocazie pentru a efectua un ultim test inainte de Olimpiada Nationala. Concursul se va desfasura *Duminica 5 aprilie*, la ora {*09^00^*} si va dura *3h*. Participantii vor avea de rezolvat 2-3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':grigore-moisil-2009/clasament/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/clasament/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/clasament/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/clasament/11-12\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* prof. Clara Ionescu\r\n* ==User(user=\"SleepyOverlord\" type=\"tiny\")==\r\n* ==User(user=\"Marius\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"domino\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n',2092,'protected',NULL,NULL),('newsletter/grigore-moisil-2009','Grigore Moisil 2009; Noutăți','2009-04-01 15:32:25','2009-04-01 15:32:25','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎn perioada 3-5 Aprilie se desfăşoară la Satu Mare concursul interjudeţean de informatică „Grigore Moisil”. infoarena gazduieşte şi anul acesta o ediţie online a acestui concurs iar tu eşti invitat să participi. Ai ocazia sa iţi măsori forţele cu cei care participă live la concurs. Totodată, ai ocazia să faci un ultim test înainte de \'ONI\':http://www.activemall.ro/oni2009/.\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Concursul se desfăşoară\r\n*Duminică, 5 Aprilie 2009, orele 09^00^ - 12^00^*. |\r\n\r\nVezi \'pagina concursului\':grigore-moisil-2009 pentru mai multe informaţii.\r\n\r\nSucces!\r\n\r\nh2{font-size: 12pt}. Despre concurs\r\n\r\nProblemele vor fi impartite pe 5 grupe de varsta! Participantii vor avea de rezolvat 2-3 probleme de natura algoritmica.\r\n\r\nA XXIII-a editie a \"Grigore Moisil\" este organizata de ISJ Cluj\r\nin colaborare cu Universitatea \"Babes-Bolyai\" si cu Societatea de\r\nStiinte Matematica din Romania.\r\nLa acest concurs, participa 230 de elevi de clasele V-XII (150\r\nla matematica 80 la informatica) din judetele Maramures, Bihor,\r\nSatu-Mare, Salaj, Bistrita-Nasaud si Cluj.\r\n\r\nAceasta este a doua editie cand proba de informatica a concursului\r\nse desfasoara si pe infoarena. Suntem foarte bucurosi sa sprijinim\r\nintentia unui concurs interjudetean, regional, de a se deschide\r\ncatre participanti din toata tara. Este un pas inainte si speram\r\nsa constituie un exemplu pozitiv pentru alte concursuri similare.\r\n\r\nVor propune probleme Prof. Clara Ionescu si Patcas Csaba\r\npentru 5 grupe de varsta: clasele 5-6, clasele 7-8, clasa a 9-a,\r\nclasa a 10-a si respectiv clasele 11-12.\r\n\r\nLa Runda 3 vei avea la dispoziţie $4h$ să rezolvi $3$ probleme de natură algoritmică. Concurenţii sunt împărţiţi în 4 grupe de vârstă: gimnaziu, clasele 9-10, clasele 11-12 şi studenţi (inclusiv masteranzi şi doctoranzi).\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* prof. Clara Ionescu\r\n* ==User(user=\"SleepyOverlord\" type=\"tiny\")==\r\n* ==User(user=\"Marius\" type=\"tiny\")==\r\n\r\nIti urăm succes şi te asteptăm la concurs!\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(username=\"%username%\" round_url=\"grigore-moisil-2009\" page=\"template/newsletter/rating\")==\r\n\r\n==include(page=\"template/newsletter/doi-la-suta\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==\r\n',13,'protected',NULL,NULL),('newsletter/grigore-moisil-2009','Grigore Moisil 2009; Noutăți','2009-04-01 15:32:25','2009-04-01 16:04:47','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎn perioada 3-5 Aprilie se desfăşoară la Satu Mare Concursul Interjudeţean de Informatică _Grigore Moisil_. Pentru al treilea an la rând, infoarena gazduieşte o ediţie online a acestui concurs iar tu eşti invitat să participi.\r\n\r\nMăsoară-ţi forţele cu cei care participă _live_ la concurs şi cu ceilalţi membri infoarena! În plus, la mai puţin de 10 zile înainte de \'ONI\':http://www.activemall.ro/oni2009/, ai nevoie de această ocazie de antrenament şi verificare. Eşti pregătit?\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Concursul se desfăşoară\r\n*Duminică, 5 Aprilie 2009, orele 09^00^ - 12^00^*. |\r\n\r\nVezi \'pagina concursului\':grigore-moisil-2009 pentru mai multe informaţii.\r\n\r\nSucces!\r\n\r\nh2{font-size: 12pt}. Despre concurs\r\n\r\nAceasta este a treia ediţie a concursului „Grigore Moisil” când proba de informatică se desfăşoară şi online pe infoarena. Suntem foarte bucuroşi să sprijinim intenţia unui concurs regional de a se deschide către participanţi din toată ţara.\r\n\r\nVei avea de rezolvat 2 - 3 probleme de natură algoritmică într-un timp de lucru de 3h. Concursul se împarte pe 5 grupe de vârstă: clasele 5-6, clasele 7-8, clasa a 9-a, clasa a 10-a, respectiv clasele 11-12.\r\n\r\nSubiectele vor fi propuse şi pregătite de către:\r\n\r\n* Prof. Clara Ionescu\r\n* ==User(user=\"SleepyOverlord\" type=\"tiny\")==\r\n* ==User(user=\"Marius\" type=\"tiny\")==\r\n\r\nIţi urăm mult succes şi te asteptăm la concurs!\r\n\r\n==include(username=\"%username%\" round_url=\"grigore-moisil-2009\" page=\"template/newsletter/rating\")==\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/doi-la-suta\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==\r\n',13,'protected',NULL,NULL),('template/newsletter/doi-la-suta-call','template/newsletter/doi-la-suta','2009-04-01 16:19:12','2009-04-01 16:19:12','h2{font-size: 12pt}. Mulţumim pentru sprijin!\r\n\r\nPeste 50 de persoane au sprijinit \'Asociaţia infoarena\':asociatia-infoarena direcţionând 2% din impozitul pe venit în anul fiscal 2008. Am fost surprinşi într-un mod plăcut de aceste contribuţii. Ne bucurăm că munca pe care o depunem este apreciată.\r\n\r\nDacă susţii proiectul infoarena, atunci te rugăm să afli mai multe despre aceste contribuţii, cum vor fi folosite şi de ce sunt imporante pentru noi: \'2% pentru infoarena\':blog/doi-la-suta-2008-raport.\r\n\r\nTermenul limită este *15 mai 2009*.',13,'protected',NULL,NULL),('newsletter/grigore-moisil-2009','Grigore Moisil 2009 și alte noutăți','2009-04-01 15:32:25','2009-04-01 16:41:07','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎn perioada 3-5 Aprilie se desfăşoară la Satu Mare Concursul Interjudeţean de Informatică _Grigore Moisil_. Pentru al treilea an la rând, infoarena gazduieşte o ediţie online a acestui concurs iar tu eşti invitat să participi.\r\n\r\nMăsoară-ţi forţele cu cei care participă _live_ la concurs şi cu ceilalţi membri infoarena! În plus, la mai puţin de 10 zile înainte de \'ONI\':http://www.activemall.ro/oni2009/, ai nevoie de această ocazie de antrenament şi verificare. Eşti pregătit?\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Concursul se desfăşoară\r\n*Duminică, 5 Aprilie 2009, între orele 09^00^ - 12^00^*. |\r\n\r\nVezi \'pagina concursului\':grigore-moisil-2009 pentru mai multe informaţii.\r\n\r\nMai am o noutate pentru tine - *concursuri virtuale*! Vrei să-ţi faci propriul concurs pe infoarena? Citeşte până la capăt...\r\n\r\n\r\nh2{font-size: 12pt}. Despre concurs\r\n\r\nAcesta este al treilea an când proba de informatică a concursului „Grigore Moisil” se desfăşoară şi online pe infoarena. Suntem foarte bucuroşi să sprijinim intenţia unui concurs regional de a se deschide către participanţi din toată ţara.\r\n\r\nVei avea de rezolvat 2 - 3 probleme de natură algoritmică într-un timp de lucru de 3h. Concursul se împarte pe 5 grupe de vârstă: clasele 5-6, clasele 7-8, clasa a 9-a, clasa a 10-a şi clasele 11-12.\r\n\r\nSubiectele vor fi propuse şi pregătite de către:\r\n\r\n* Prof. Clara Ionescu\r\n* ==User(user=\"SleepyOverlord\" type=\"link\")==\r\n* ==User(user=\"Marius\" type=\"link\")==\r\n\r\nIţi urăm mult succes şi te asteptăm la concurs!\r\n\r\n==include(username=\"%username%\" round_url=\"grigore-moisil-2009\" page=\"template/newsletter/rating\")==\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\nh2{font-size: 12pt}. %{color:red}NOU!% Concursuri virtuale\r\n\r\ninfoarena lansează o nouă facilitate: \'concursuri virtuale\':concursuri-virtuale! Această facilitate permite membrilor infoarena să îşi creeze singuri concursuri cu probleme din arhivă (peste 800!) la orice moment din zi şi, mai ales, din noapte. \r\n\r\nCiteşte \'prezentarea concursurilor virtuale\':blog/concursuri-virtuale alături de reacţia comunităţii infoarena la această nouă facilitate. Te aşteptăm cu păreri şi sugestii.\r\n\r\n==include(page=\"template/newsletter/doi-la-suta-call\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==\r\n',13,'protected',NULL,NULL),('algoritmiada-2009','Algoritmiada 2009 - olimpiada algoritmilor','2008-11-30 14:01:47','2009-02-08 16:15:56','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh2. Despre Algoritmiada\r\n\r\nIncepând de anul acesta, _infoarena_ organizează concursul de programare Algoritmiada. La acest concurs pot participa, în premieră pe ţară, tineri pasionaţi de informatică de toate vârstele: de la elevi de gimnaziu până la studenţi şi doctoranzi.\r\n\r\nConcursul are patru grupe valorice: gimnaziu, clasele 9-10, clasele 11-12, studenţi (inclusiv masteranzi şi doctoranzi). Participanţii vor avea ocazia să-şi demonstreze talentul, cunostinţele şi iuţimea minţii în 3 probe online urmând ca cei mai buni sa fie invitaţi la finala on-site.\r\n\r\nh2. Cum particip?\r\n\r\nPentru a participa la concurs trebuie să fii \'înregistrat\':register pe site-ul nostru.\r\n\r\nÎn ziua de concurs intri pe site, citeşti problemele de la grupa ta de vârstă şi trimiţi soluţiile înainte de expirarea timpului. \'Evaluatorul\':documentatie/evaluator nostru iţi va testa automat soluţiile iar punctajul îl vei afla la sfârşitul concursului. Tot atunci vei putea consulta clasamentul pentru a vedea ce au făcut şi ceilalţi concurenţi.\r\n\r\nh3. Prima dată pe _infoarena_?\r\n\r\n_infoarena_ ajută elevi şi studenţi să devină excelenţi în informatică! Gratuit ;) Citeşte \'ghidul utilizatorului\':documentatie/pentru-utilizatori şi află mai multe \'despre noi\':despre-infoarena.\r\n\r\nh2. Program\r\n\r\nFaceţi click pe titlul unei runde pentru informaţii detaliate.\r\n\r\ntable{width:50%}. |_. Runda |_. Data |_. Durata |\r\n| \'*Runda 1*\':algoritmiada-2009/runda-1 | *14 Decembrie 2008, Duminică* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 2*\':algoritmiada-2009/runda-2 | *11 Ianuarie 2009, Duminică* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 3*\':algoritmiada-2009/runda-3 | *15 Februarie 2009, Duminică* |=. *09^00^ - 13^00^* |\r\n| \'*Runda Finală*\':algoritmiada-2009/runda-finala |=. _Martie 2009_ | |\r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==',1490,'protected',NULL,NULL),('grigore-moisil-2009/solutii','grigore-moisil-2009/solutii','2009-04-05 16:25:15','2009-04-05 16:43:03','h1. Solutii Grigore Moisil 2009\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Alibaba\':grigore-moisil-2009/solutii#alibaba\r\n* \'Palindrom2\':grigore-moisil-2009/solutii#palindrom2\r\n* \'Bete2\':grigore-moisil-2009/solutii#bete2\r\n* \'Fotbal\':grigore-moisil-2009/solutii#fotbal\r\n* \'Cuburi3\':grigore-moisil-2009/solutii#cuburi3\r\n* \'Motel\':grigore-moisil-2009/solutii#motel\r\n* \'Palindrom\':grigore-moisil-2009/solutii#palindrom\r\n* \'Peisaj\':grigore-moisil-2009/solutii#peisaj\r\n* \'Pari\':grigore-moisil-2009/solutii#pari\r\n\r\n==include(page=\"grigore-moisil-2009/solutii/alibaba\")==',3146,'public',NULL,NULL),('planificare/sedinta-20090403','Sedinta 2009-04-03','2009-03-29 22:30:49','2009-04-03 15:36:42','h1. Sedinta 2009-04-03\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe intalnim *vineri, 3 aprilie* la ora *19:00* la \'*Retro Cafe*\':http://metropotam.ro/Unde-iesim/2008/07/art2701725520-Millennium-Bank-recomanda-Retro-Cafe/\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== (probabil voi intarzia)\r\n* ==user(user=\"stef2n\" type=\"tiny\")== (nu ajung mai devreme de 20:00)\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090316| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|OKRs| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n\r\nh3. Algoritmiada\r\n\r\n* Sponsori\r\n* Participanţi\r\n* Lista cereri\r\n* Cazare şi masă\r\n* Tricouri\r\n* Organizare tehnică\r\n* Presă\r\n\r\nh2. Detalii\r\n\r\nh3. Misc\r\n\r\n* Marius Stroe?\r\n* Backup notice.\r\n* Concursul CEX\r\n* Concursul \"Grigore Moisil\"\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\nh2. Notiţe',2028,'public',NULL,NULL),('planificare/sedinta-20090403','Sedinta 2009-04-03','2009-03-29 22:30:49','2009-04-03 17:45:06','h1. Sedinta 2009-04-03\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe intalnim *vineri, 3 aprilie* la ora *19:00* la \'*Retro Cafe*\':http://metropotam.ro/Unde-iesim/2008/07/art2701725520-Millennium-Bank-recomanda-Retro-Cafe/\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== (probabil voi intarzia)\r\n* ==user(user=\"stef2n\" type=\"tiny\")== (nu ajung mai devreme de 20:00)\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"prostu\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090316| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|Algoritmiada| ==user(user=\"wefgef\" type=\"tiny\")== |\r\n|OKRs| ==user(user=\"wickedman\" type=\"tiny\")== |\r\n\r\nh3. Algoritmiada\r\n\r\n* Sponsori\r\n* Participanţi\r\n* Trisori\r\n* Blog post runda 3\r\n* Lista cereri\r\n* Cazare şi masă\r\n* Tricouri\r\n* Organizare tehnică\r\n* Presă\r\n\r\nh2. Detalii\r\n\r\nh3. Misc\r\n\r\n* Marius Stroe?\r\n* Backup notice.\r\n* Concursul CEX\r\n* Concursul \"Grigore Moisil\"\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Mircea dă mail la Microsoft.\r\n* Wefgef face listă cu ce trebuie instalat la Algoritmiada\r\n* Mircea, Cristi şi Bogdan bagă review la change-ul lui Devilkind. (?)\r\n* Mircea face review la script pentru topic-uri de pe forum la probleme. (?)\r\n* Victor îi arată lui Prostu cum se foloseşte format_table. Prostu bagă la review săptămâna asta.\r\n* Prostu aduce merinde la următoarea şedinţă.\r\n* Wefgef reactualizează bugetul Algoritmiadei.\r\n* Vali se gândeşte la premii cool şi ieftine.\r\n* Prostu vorbeşte la Oracle despre sponsorizare.\r\n* Wefgef bagă post despre trişare la Algoritmiada.\r\n* Wefgef şi Cristi fac listă de cereri. Wefgef o trimite la liceu.\r\n* Până vineri Wefgef ia legatura cu hotelurile si restaurantul.\r\n* Tricorui > picnic.\r\n* Wefgef vorbeşte cu Vlad_d de design de tricouri.\r\n* Cristi vorbeşte de serigrafiere dacă primeşte design.\r\n* Vali şi Wefgef merg la Braşov cu o săptămână înainte de finală.\r\n* Pookie face comunicat de presă online.\r\n* Joi facem o conferinţă legată de Algoritmiadă.\r\n\r\nh2. Notiţe\r\n\r\n* Silviu si Cristi concretizeaza IAP 7 (1 sedinta)\r\n* Blog post pentru Coding Camp \"A New Day\"\r\n* Silviu bagă post drespre runda 3. (?)\r\n* Cristi vorbeşte cu Cristina Petrovici despre implicarea în infoarena.',13,'public',NULL,NULL),('utilizator/mishu91','Cine e primu\' loc? Adi, Adi','2007-03-22 08:40:26','2009-03-03 18:58:02','h2. Despre mine \r\n\r\n* Cine e pe primu\' loc? Adi, Adi\r\n* Elev in clasa a XI a la C.N. \"Andrei Saguna\", Brasov\r\n* ID-ul de mess e l_sidious\r\n* Imi place sa ma uit la meciuri si sa joc fotbal (in pauze mai bag si ceva info)\r\n* Tin cu Rapid\r\n* Nu imi plac bancurile cu Chuck Norris (sa fim seriosi, unele is rasuflate rau de tot)\r\n\r\nh2. Profesori pregatirori\r\n\r\n* Infoarena\r\n\r\nh2. Distincii primite\r\n\r\n* Fara numar si fara serie\r\n\r\nh2. Prieteni, pretenari si neamuri in clubul de manele\r\n\r\n* ==user(user=\"jupanubv92\" type=\"tiny\")==\r\n* ==user(user=\"robytzza\" type=\"tiny\")==\r\n* ==user(user=\"M@2Te4i\" type=\"tiny\")==\r\n* ==user(user=\"moga_florian\" type=\"tiny\")==\r\n* ==user(user=\"alexei\" type=\"tiny\")==\r\n* ==user(user=\"blasterz\" type=\"tiny\")==\r\n\r\nP.S.: Ordinea este EXTREM de relevanta, cei de mai sus fiind sortati aleator in ordinea numarului de la shlapi\r\n\r\nh2. Nashpeti pe Infoarena\r\n\r\n* ==user(user=\"eval\" type=\"tiny\")==',6333,'public',NULL,NULL),('problema-majoritatii-votului','Problema Majoritatii Votului','2009-04-06 05:09:46','2009-04-06 05:25:12','Problema majorităţii votului\r\n\r\nNegruşeri Cosmin\r\n\r\n\r\n\r\n\r\nÎn acest articol dezbatem problema dezvoltării de algoritmi eficienţi pentru determinarea candidatului care a întrunit un număr majoritar de voturi.\r\n\r\nProblema enunţată formal este următoarea: Se dă un şir de n numere naturale, se cere determinarea unui element care apare de cel puţin [n/2]+1 ori în şir dacă există un astfel de element în şir.\r\n\r\nUn algoritm naiv ar verifica pentru fiecare element din şir de câte ori mai apare acesta. O astfel de rezolvare are complexitatea O(n^2) ca timp si O(n) ca memorie.\r\n== code(cpp) |\r\nint bruteForceMajority(int n, int[] a)\r\n    for (int i = 0; i < n; i++) {\r\n          int nr = 0;\r\n          for (int j = 0; j < n; j++) {\r\n               if (a[j]==a[i]) nr++;\r\n          }\r\n          if  (nr > n / 2) return a[i];      \r\n    }\r\n    return -1;\r\n}\r\n==\r\nDacă numerele din şir aparţin unei mulţimi {1, 2, ... k} iar acest k este mic comparativ cu n, atunci putem să îmbunătăţinm ideea de mai devreme şi să folosim un şir auxiliar b, unde b[x] va număra de câte ori apare un număr x în şirul nostru. Această soluţie are complexitate O(n + k) ca timp şi O(n + k) ca spaţiu.\r\n== code(cpp) |\r\nint countMajority(int n, int[] a, int k) {\r\n     int[] b = new int[k];\r\n    for (int i = 0; i < n; i++) {\r\n         b[a[i]]++;//incrementăm numărul de apariţii al elementului a[i]\r\n    }\r\n    for (int i = 0; i < k; i++) {\r\n         if (b[i] > n/2) return i;\r\n    }\r\n    return -1;\r\n}\r\n==\r\nSoluţia această este destul de eficientă în cazul menţionat anterior, dar când k este mult mai mare decât n, atunci această rezolvare ajunge să fie foarte lentă. Însă folosind o structură avansată de date putem să facem soluţia din nou eficientă. Această structură are la bază o tabelă de dispersie, ea mapează perechi de numere <cheie, valoare>, cheile vor fi numerele din şir, iar valorile vor fi numărul de apariţii al cheilor în şirul nostru.\r\n== code(cpp) |\r\nint hashMajority(int n, int[] a) {\r\n    HashMap<Integer, Integer> b = new HashMap<Integer, Integer>();\r\n    for (int i = 0; i < n; i++) {\r\n         if (b.get(a[i])== null) {\r\n             b.put(a[i], 1);\r\n         } else {\r\n             int num = b.get(a[i]);\r\n             b.remove(a[i]);\r\n             b.put(a[i], num + 1);\r\n         }\r\n    }\r\n    for (int i = 0; i < n; i++) {\r\n         if (b.get(a[i]) > n/2) return i;\r\n    }\r\n    return -1;\r\n}\r\n==\r\nAceastă soluţie are complexitate O(n) ca timp, şi O(n) memorie suplimentară. Menţionăm că un dezavantaj al acestei soluţii ar fi că este una randomizată.\r\n\r\nO altă soluţie care ar permite numărarea eficientă a numărului de apariţii a unui element în acest şir ar fi să sortăm şirul pentru că apoi elementele egale vor fi în poziţii consecutive.\r\n== code(cpp) |\r\nint sortMajority(int n, int[] a) {\r\n    Arrays.sort(a);\r\n    int i = 0;\r\n    while (i < n) {\r\n          int j = i;\r\n          while (j < n && a[j + 1]==a[i]) j++;\r\n          if (j – i + 1 > n / 2) return a[i];\r\n          i = j + 1;\r\n    }\r\n    return -1;\r\n}\r\n==\r\nAceastă soluţie are complexitatea O(n log n), nu foloseşte suplimentară, dar suprascrie şirul iniţial.\r\n\r\nO idee ce ne vine pe urma acestei rezolvări este aceea că în şirul sortat, un element majoritar se va afla în şirul sortat şi pe poziţia n/2.Ştim că există algoritmi de selecţie care ne găsesc elemente de poziţie o fixată k din şirul sortat în complexitate O(n). Astfel vom găsi mai întâi elementul de pe poziţia n/2 iar apoi vom verifica dacă acesta este elementul majoritar al şirului. Astfel avem o soluţie de complexitate O(n) iar şirul iniţial va fi modificat. Există metode de selecţie nerandomizate, dar pentru uşurinţa implementării vom folosi una randomizată.\r\n== code(cpp) |\r\nint  select(int n, int[] a, int left, int right, int k) {\r\n    Random ran = new Random(System.currentTimeMilis());\r\n    int i, j, aux, q; \r\n    while (left != right) {\r\n        i = left + ran.nextInt(right – left + 1);\r\n        aux = a[left]; a[left] = a[i]; a[i] = aux;\r\n        int x = a[left];\r\n        i = left – 1;\r\n        j = right + 1;\r\n        while (true) {\r\n           do { i++; } while a[i] < x;\r\n           do { j--; } while a[j] > x;\r\n            if (i < j) { aux = a[i]; a[i] = a[j]; a[j] = aux; }\r\n            else break;\r\n        }\r\n        q = right – left + 1;\r\n        if (k <= q) {\r\n            right = j;\r\n        } else {\r\n           k -= q;\r\n           left = j + 1;\r\n        }\r\n    }\r\n    return a[left];\r\n}\r\n\r\nint selectMajority(int n, int[] a) {\r\n   int x = select(n,  a,  0, n – 1, n / 2 - 1), nr = 0;\r\n   for (int i = 0; i < n; i++) {\r\n         if (a[i]==x) nr++;\r\n   }\r\n   if (nr > n/2) return x;\r\n   else return -1;\r\n}\r\n==\r\nO altă idee de rezolvare porneşte de la observaţia următoare: Dacă există un element majoritar în şir, atunci ultima lui cifră va fi elementul majoritar în şirul format din ultimele cifre a numerelor din şirul iniţial. Această observaţie este valabilă pentru orice cifră a numerelor nu doar ultima. Astfel putem determina pentru fiecare a x-a cifră a numemerelor care este cifra majoritară şi apoi să punem cap la cap cifrele majoritare pentru a forma numărul majoritar. Evident putem să folosim orice bază, dacă folosim baza b şi valoarea maximă a unui număr ar fi k atunci algoritmul va avea complexitatea O(n log in baza b din k) şi foloseşte memorie suplimentară O(b * log in baza b din k).  În practică putem considera acest algoritm ca fiind liniar. Să vedem o implementare a algoritmului pentru b = 1000 şi k = 999.999.999.\r\n== code(cpp) |\r\nint digitMajority(int n, int[] a) {\r\n     int[][] dig = new int[3][1000];\r\n     for (int i = 0; i < n; i++) {\r\n           int tmp = a[i];\r\n           for (int j = 0; j < 3; j++) {\r\n                 dig[j][tmp % 1000]++;\r\n                 tmp /= 1000;\r\n           } \r\n     }\r\n     int ret = 0;\r\n     for (int i = 0; i < 999; i++) {\r\n           if (dig[0][i] > n/2) ret += i;\r\n           if (dig[1][i] > n/2) ret += i * 1000;\r\n           if (dig[2][i] > n/2) ret += i * 1000000;\r\n     }\r\n     int nr = 0;\r\n     for (int I = 0; I < n; i++) {\r\n           if (a[i]==ret) nr++;\r\n     }\r\n     if (nr > n/2) return ret;\r\n     else return -1;\r\n}\r\n==\r\nPutem aborda probabilistic. Astfel dacă alegem un număr aleator şi există o celebritate, avem probabilitatea 0.5 să nu îl nimerim, dacă alegem k numere aleatoare din şirul respectiv, atunci avem probabilitatea\r\n(˝)^k să nu îl nimerim. Astfel algoritmul nostru va fi să luăm k numere aleatoare, iar apoi să numărăm de câte ori apare fiecare din aceste k numere în şirul nostru. Dacă folosim o structură ce mapează chei valori atunci algoritmul va avea complexitate O(n + k) şi probabilitate de reuşită P = 1 - (˝)^k. În practică o valoare de 10 pentru k ne dă o probabilitate de reuşită de 0.999. Să vedem mai departe codul:\r\n== code(cpp) |\r\nint probabilisticMajority(int n, int[] a) {\r\n    Random ran = new Random(System.currentTimeMilis());\r\n    HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();\r\n    for (int i = 0; i < 10; i++) {\r\n          map.put(a[ran.nextInt(n)], 0);         \r\n    }\r\n    for (int i = 0; i < 10; i++) {\r\n          if (map.contains(a[i])) {\r\n             int num = map.get(a[i]);\r\n             if (num + 1 > n/2) return a[i];\r\n             map.remove(a[i]);\r\n             map.add(a[i], num + 1);\r\n          }\r\n    }\r\n    return -1;\r\n}\r\n==\r\nUn ultim algoritm şi cel mai eficient dintre cele prezentate apare în lucrarea [1] şi probabil acesta este cunoscut cititorilor. Autorii au un mod plastic de a prezenta algoritmul:\r\nImaginaţi-vă o sală de conferinţă în care votanţii ţin fiecare o placă ce poartă numele candidatului preferat. Să presupunem se ajunge la o bataie generală în care votanţii cu convingeri diferite încep să se lovească reciproc cu plăcile. Să mai presupunem că fiecare votant care pune la pământ un membru cu alte convingeri este simultan şi el pus la pământ de adversar. Este evident că dacă ar fi vreun candidat care are mai multe voturi decăt toate voturile celorlalţi candidaţi, atunci această luptă va fi câştigată de acest candidat şi la dispariţia haosului din urma luptei, votanţii ce au rămas în picioare vor fi susţinători ai candidatului amintit. În caz că nu există o majoritate clară pentru un candidat sau altul, la finalul luptei rămân ăn picioare votanţi care susţin acelaşi candidat, dar acesta poate să nu fie reprezentantul majorităţii. Deci, în general, dacă cineva rămâne în picioare, preşedintele conferinţei este obligat să verifice dacă întradevar candidatul întruneşte votul a jumătate plus unu de votanţi. Algoritmul practic folosit de noi va fi un fel de joc al împerecherilor între candidaţi de opinii diferite până când toţi votanţii rămaşi necuplaţi vor susţine acelaşi candidat.\r\nRealizăm acest algoritm parcurgând lista votanţilor şi ţinând un contor cu numărul de candidaţi k neîmperecheaţi până la pasul curent, evident dacă ei sunt neîmperecheaţi trebuie să susţină acelaşi candidat cand pentru că altfel am fi putut să cuplăm câţiva dintre ei.\r\nMenţionăm că această rezolvare doar operaţii în care se verifică dacă două valori sunt identice, fapt ce se poate dovedi util pentru obiecte complexe care ar substitui candidaţii din problemă. Rezolvările anterioare s-au folosit de faptul că între elementele şirului ar exista o relaţie de ordine sau că am putea efectua asupra lor operaţii aritmetice.\r\n\r\n== code(cpp) |\r\nint mooreMajority(int n, int[]  a) {\r\n    int cand = -1, k = 0;\r\n    for (int i = 0; i < n; i++) {\r\n          if (k==0) {\r\n             cand = a[i];\r\n             k = 1;\r\n          } else  if (a[i]==cand) {\r\n              k++;//nu am putut împerechea pe votantul i şi astfel trebuie să mărim numărul de votanţi necuplaţi\r\n          } else k--;//cuplăm votantul i cu orice votant ce îl susţine pe cand şi micşorăm astfel numărul de votanţi necuplaţi\r\n    }\r\n    if (cand < 0) return cand;\r\n    //faza de verificare\r\n    int nr = 0;\r\n    for (int i = 0; i < n; i++) {\r\n          if (a[i]==cand) nr++;\r\n    }\r\n    if (nr > n / 2) return cand;\r\n    else return – 1;\r\n}\r\n==\r\nAceastă problemă a fost propusă în prima rundă a concursului Bursele Agora în 2005, Atunci nu era posibilă ţinerea tuturor numerelor din fişier în memorie şi citirea numerelor era greoaie.Doar doi concurenţi au reuşit obţinerea unui punctaj maxim la acea rundă. Autorul a fost unul dintre aceştia, el a evitat citirea de două ori a fişierului de intrare prin folosirea soluţiei cu cifre, în care calcula două rezultate pentru două baze diferite b1 şi b2 alese aleator la startul rulării, iar apoi  verifica dacă candidaţii care erau probabil câştigatori erau egali. Aceasta rezolvare făcea improbabilă scrierea unui răspuns incorect.\r\n\r\nVom generaliza acum problema: Se dă un şir de n numere naturale şi un număr întreg k, se cere determinarea tuturor elementelor care apar de cel puţin [n/k]+1 ori în şir.\r\n \r\nPrimele trei rezolvări prezentate pentru problema iniţială pot fi evident generalizate şi folosite şi pentru această problemă. Generalizarea abordării care implica folosirea cifrelor pentru a rezolva noua problemă pare imposibilă. Vom vorbi mai departe de două din celelalte trei abordări.\r\n\r\nEvident dacă un număr apare de cel puţin [n/k] + 1 ori în şir atunci el va apărea în şirul sortat pe una din poziţiile i * [n/k] cu i de la 1 la k. De aici se conturează algoritmul următor: determinăm în O(n * k) elementele de pe poziţiile i * [n/k] iar apoi verificăm care dintre acestea sunt elemente majoritare în sensul menţionat mai sus. Acest algoritm are complexitate liniară daca îl considerăm pe k o constantă.\r\n\r\nA doua soluţie este similară cu cea mai bună soluţie pentru prima problemă, numai că în loc să grupăm câte doi votanţi diferiţi vom grupa câte k votanţi cu păreri diferite.\r\n== code(cpp) |\r\nint[] mooreKMajority(int n, int[]  a, int k) {\r\n    int[] cand = new int[k - 1], notMatched = new int[k - 1],  num = new int[k-1];\r\n    Arrays.fill(cand, -1);\r\n    int num = 0;\r\n    //faza de cuplare\r\n    for (int i = 0; i < n; i++) {\r\n          boolean found = false;\r\n          for (int j = 0; j < k - 1; j++) {\r\n                if (cand[j]==a[i]) {\r\n                   notMatched[j]++;\r\n                   found = true;\r\n                   break;\r\n                }                \r\n          }\r\n          if (!found) {\r\n              for (int j = 0; j < k - 1; j++) {\r\n                    if (notMatched[j]==0) {\r\n                       cand[j] = a[i];\r\n                       notMatched[j] = 1;\r\n                       found = true;\r\n                       break;\r\n                    }                \r\n              }\r\n              if (!found) {\r\n                  for (int  j = 0; j < k – 1; j++) notMatched[j]--;                \r\n              }\r\n          }\r\n    }\r\n\r\n   //faza de verificare\r\n   for (int i = 0; i < n; i++) {\r\n          for (int j = 0; j < k - 1; j++) {\r\n                if (a[i]==cand[j] && notMatched[j] != 0)  num[j]++;                  \r\n          }\r\n   }\r\n\r\n   int numMaj = 0;\r\n   for (int j = 0; j < k - 1; j++) {\r\n        if (num[j] > n/k) numMaj++;\r\n   }\r\n\r\n   int[] ret = new int[numMaj];\r\n   numMaj = 0;\r\n   for (int j = 0; j < k - 1; j++) {\r\n        if (num[j] > n/k) {\r\n            ret[numMaj] = cand[j];\r\n            numMaj++;\r\n        }     \r\n   }\r\n\r\n   return ret;\r\n}\r\n==\r\n\r\nBibliografie:\r\n[1] T.H.Cormen, C. E. Leiserson, R. R. Rivest, Introducere în algoritmi, ed. Agora 2000\r\n[2] R. S. Boyer, J. S. Moore A Fast Majority Vote Algorithm\r\n',7668,'public',NULL,NULL),('problema-majoritatii-votului','Problema Majoritatii Votului','2009-04-06 05:09:46','2009-04-06 05:26:36','Problema majorităţii votului\r\n\r\nNegruşeri Cosmin\r\n\r\n\r\n\r\n\r\nÎn acest articol dezbatem problema dezvoltării de algoritmi eficienţi pentru determinarea candidatului care a întrunit un număr majoritar de voturi.\r\n\r\nProblema enunţată formal este următoarea: Se dă un şir de n numere naturale, se cere determinarea unui element care apare de cel puţin [n/2]+1 ori în şir dacă există un astfel de element în şir.\r\n\r\nUn algoritm naiv ar verifica pentru fiecare element din şir de câte ori mai apare acesta. O astfel de rezolvare are complexitatea O(n^2) ca timp si O(n) ca memorie.\r\n== code(cpp) |\r\nint bruteForceMajority(int n, int[] a)\r\n    for (int i = 0; i < n; i++) {\r\n          int nr = 0;\r\n          for (int j = 0; j < n; j++) {\r\n               if (a[j]==a[i]) nr++;\r\n          }\r\n          if  (nr > n / 2) return a[i];      \r\n    }\r\n    return -1;\r\n}\r\n==\r\nDacă numerele din şir aparţin unei mulţimi {1, 2, ... k} iar acest k este mic comparativ cu n, atunci putem să îmbunătăţinm ideea de mai devreme şi să folosim un şir auxiliar b, unde b[x] va număra de câte ori apare un număr x în şirul nostru. Această soluţie are complexitate O(n + k) ca timp şi O(n + k) ca spaţiu.\r\n== code(cpp) |\r\nint countMajority(int n, int[] a, int k) {\r\n     int[] b = new int[k];\r\n    for (int i = 0; i < n; i++) {\r\n         b[a[i]]++;//incrementăm numărul de apariţii al elementului a[i]\r\n    }\r\n    for (int i = 0; i < k; i++) {\r\n         if (b[i] > n/2) return i;\r\n    }\r\n    return -1;\r\n}\r\n==\r\nSoluţia această este destul de eficientă în cazul menţionat anterior, dar când k este mult mai mare decât n, atunci această rezolvare ajunge să fie foarte lentă. Însă folosind o structură avansată de date putem să facem soluţia din nou eficientă. Această structură are la bază o tabelă de dispersie, ea mapează perechi de numere <cheie, valoare>, cheile vor fi numerele din şir, iar valorile vor fi numărul de apariţii al cheilor în şirul nostru.\r\n== code(cpp) |\r\nint hashMajority(int n, int[] a) {\r\n    HashMap<Integer, Integer> b = new HashMap<Integer, Integer>();\r\n    for (int i = 0; i < n; i++) {\r\n         if (b.get(a[i])==null) {\r\n             b.put(a[i], 1);\r\n         } else {\r\n             int num = b.get(a[i]);\r\n             b.remove(a[i]);\r\n             b.put(a[i], num + 1);\r\n         }\r\n    }\r\n    for (int i = 0; i < n; i++) {\r\n         if (b.get(a[i]) > n/2) return i;\r\n    }\r\n    return -1;\r\n}\r\n==\r\nAceastă soluţie are complexitate O(n) ca timp, şi O(n) memorie suplimentară. Menţionăm că un dezavantaj al acestei soluţii ar fi că este una randomizată.\r\n\r\nO altă soluţie care ar permite numărarea eficientă a numărului de apariţii a unui element în acest şir ar fi să sortăm şirul pentru că apoi elementele egale vor fi în poziţii consecutive.\r\n== code(cpp) |\r\nint sortMajority(int n, int[] a) {\r\n    Arrays.sort(a);\r\n    int i = 0;\r\n    while (i < n) {\r\n          int j = i;\r\n          while (j < n && a[j + 1]==a[i]) j++;\r\n          if (j – i + 1 > n / 2) return a[i];\r\n          i = j + 1;\r\n    }\r\n    return -1;\r\n}\r\n==\r\n\r\nAceastă soluţie are complexitatea O(n log n), nu foloseşte suplimentară, dar suprascrie şirul iniţial.\r\n\r\nO idee ce ne vine pe urma acestei rezolvări este aceea că în şirul sortat, un element majoritar se va afla în şirul sortat şi pe poziţia n/2.Ştim că există algoritmi de selecţie care ne găsesc elemente de poziţie o fixată k din şirul sortat în complexitate O(n). Astfel vom găsi mai întâi elementul de pe poziţia n/2 iar apoi vom verifica dacă acesta este elementul majoritar al şirului. Astfel avem o soluţie de complexitate O(n) iar şirul iniţial va fi modificat. Există metode de selecţie nerandomizate, dar pentru uşurinţa implementării vom folosi una randomizată.\r\n\r\n== code(cpp) |\r\nint  select(int n, int[] a, int left, int right, int k) {\r\n    Random ran = new Random(System.currentTimeMilis());\r\n    int i, j, aux, q; \r\n    while (left != right) {\r\n        i = left + ran.nextInt(right – left + 1);\r\n        aux = a[left]; a[left] = a[i]; a[i] = aux;\r\n        int x = a[left];\r\n        i = left – 1;\r\n        j = right + 1;\r\n        while (true) {\r\n           do { i++; } while a[i] < x;\r\n           do { j--; } while a[j] > x;\r\n            if (i < j) { aux = a[i]; a[i] = a[j]; a[j] = aux; }\r\n            else break;\r\n        }\r\n        q = right – left + 1;\r\n        if (k <= q) {\r\n            right = j;\r\n        } else {\r\n           k -= q;\r\n           left = j + 1;\r\n        }\r\n    }\r\n    return a[left];\r\n}\r\n\r\nint selectMajority(int n, int[] a) {\r\n   int x = select(n,  a,  0, n – 1, n / 2 - 1), nr = 0;\r\n   for (int i = 0; i < n; i++) {\r\n         if (a[i]==x) nr++;\r\n   }\r\n   if (nr > n/2) return x;\r\n   else return -1;\r\n}\r\n==\r\nO altă idee de rezolvare porneşte de la observaţia următoare: Dacă există un element majoritar în şir, atunci ultima lui cifră va fi elementul majoritar în şirul format din ultimele cifre a numerelor din şirul iniţial. Această observaţie este valabilă pentru orice cifră a numerelor nu doar ultima. Astfel putem determina pentru fiecare a x-a cifră a numemerelor care este cifra majoritară şi apoi să punem cap la cap cifrele majoritare pentru a forma numărul majoritar. Evident putem să folosim orice bază, dacă folosim baza b şi valoarea maximă a unui număr ar fi k atunci algoritmul va avea complexitatea O(n log in baza b din k) şi foloseşte memorie suplimentară O(b * log in baza b din k).  În practică putem considera acest algoritm ca fiind liniar. Să vedem o implementare a algoritmului pentru b = 1000 şi k = 999.999.999.\r\n== code(cpp) |\r\nint digitMajority(int n, int[] a) {\r\n     int[][] dig = new int[3][1000];\r\n     for (int i = 0; i < n; i++) {\r\n           int tmp = a[i];\r\n           for (int j = 0; j < 3; j++) {\r\n                 dig[j][tmp % 1000]++;\r\n                 tmp /= 1000;\r\n           } \r\n     }\r\n     int ret = 0;\r\n     for (int i = 0; i < 999; i++) {\r\n           if (dig[0][i] > n/2) ret += i;\r\n           if (dig[1][i] > n/2) ret += i * 1000;\r\n           if (dig[2][i] > n/2) ret += i * 1000000;\r\n     }\r\n     int nr = 0;\r\n     for (int I = 0; I < n; i++) {\r\n           if (a[i]==ret) nr++;\r\n     }\r\n     if (nr > n/2) return ret;\r\n     else return -1;\r\n}\r\n==\r\nPutem aborda probabilistic. Astfel dacă alegem un număr aleator şi există o celebritate, avem probabilitatea 0.5 să nu îl nimerim, dacă alegem k numere aleatoare din şirul respectiv, atunci avem probabilitatea\r\n(˝)^k să nu îl nimerim. Astfel algoritmul nostru va fi să luăm k numere aleatoare, iar apoi să numărăm de câte ori apare fiecare din aceste k numere în şirul nostru. Dacă folosim o structură ce mapează chei valori atunci algoritmul va avea complexitate O(n + k) şi probabilitate de reuşită P = 1 - (˝)^k. În practică o valoare de 10 pentru k ne dă o probabilitate de reuşită de 0.999. Să vedem mai departe codul:\r\n== code(cpp) |\r\nint probabilisticMajority(int n, int[] a) {\r\n    Random ran = new Random(System.currentTimeMilis());\r\n    HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();\r\n    for (int i = 0; i < 10; i++) {\r\n          map.put(a[ran.nextInt(n)], 0);         \r\n    }\r\n    for (int i = 0; i < 10; i++) {\r\n          if (map.contains(a[i])) {\r\n             int num = map.get(a[i]);\r\n             if (num + 1 > n/2) return a[i];\r\n             map.remove(a[i]);\r\n             map.add(a[i], num + 1);\r\n          }\r\n    }\r\n    return -1;\r\n}\r\n==\r\nUn ultim algoritm şi cel mai eficient dintre cele prezentate apare în lucrarea [1] şi probabil acesta este cunoscut cititorilor. Autorii au un mod plastic de a prezenta algoritmul:\r\nImaginaţi-vă o sală de conferinţă în care votanţii ţin fiecare o placă ce poartă numele candidatului preferat. Să presupunem se ajunge la o bataie generală în care votanţii cu convingeri diferite încep să se lovească reciproc cu plăcile. Să mai presupunem că fiecare votant care pune la pământ un membru cu alte convingeri este simultan şi el pus la pământ de adversar. Este evident că dacă ar fi vreun candidat care are mai multe voturi decăt toate voturile celorlalţi candidaţi, atunci această luptă va fi câştigată de acest candidat şi la dispariţia haosului din urma luptei, votanţii ce au rămas în picioare vor fi susţinători ai candidatului amintit. În caz că nu există o majoritate clară pentru un candidat sau altul, la finalul luptei rămân ăn picioare votanţi care susţin acelaşi candidat, dar acesta poate să nu fie reprezentantul majorităţii. Deci, în general, dacă cineva rămâne în picioare, preşedintele conferinţei este obligat să verifice dacă întradevar candidatul întruneşte votul a jumătate plus unu de votanţi. Algoritmul practic folosit de noi va fi un fel de joc al împerecherilor între candidaţi de opinii diferite până când toţi votanţii rămaşi necuplaţi vor susţine acelaşi candidat.\r\nRealizăm acest algoritm parcurgând lista votanţilor şi ţinând un contor cu numărul de candidaţi k neîmperecheaţi până la pasul curent, evident dacă ei sunt neîmperecheaţi trebuie să susţină acelaşi candidat cand pentru că altfel am fi putut să cuplăm câţiva dintre ei.\r\nMenţionăm că această rezolvare doar operaţii în care se verifică dacă două valori sunt identice, fapt ce se poate dovedi util pentru obiecte complexe care ar substitui candidaţii din problemă. Rezolvările anterioare s-au folosit de faptul că între elementele şirului ar exista o relaţie de ordine sau că am putea efectua asupra lor operaţii aritmetice.\r\n\r\n== code(cpp) |\r\nint mooreMajority(int n, int[]  a) {\r\n    int cand = -1, k = 0;\r\n    for (int i = 0; i < n; i++) {\r\n          if (k==0) {\r\n             cand = a[i];\r\n             k = 1;\r\n          } else  if (a[i]==cand) {\r\n              k++;//nu am putut împerechea pe votantul i şi astfel trebuie să mărim numărul de votanţi necuplaţi\r\n          } else k--;//cuplăm votantul i cu orice votant ce îl susţine pe cand şi micşorăm astfel numărul de votanţi necuplaţi\r\n    }\r\n    if (cand < 0) return cand;\r\n    //faza de verificare\r\n    int nr = 0;\r\n    for (int i = 0; i < n; i++) {\r\n          if (a[i]==cand) nr++;\r\n    }\r\n    if (nr > n / 2) return cand;\r\n    else return – 1;\r\n}\r\n==\r\nAceastă problemă a fost propusă în prima rundă a concursului Bursele Agora în 2005, Atunci nu era posibilă ţinerea tuturor numerelor din fişier în memorie şi citirea numerelor era greoaie.Doar doi concurenţi au reuşit obţinerea unui punctaj maxim la acea rundă. Autorul a fost unul dintre aceştia, el a evitat citirea de două ori a fişierului de intrare prin folosirea soluţiei cu cifre, în care calcula două rezultate pentru două baze diferite b1 şi b2 alese aleator la startul rulării, iar apoi  verifica dacă candidaţii care erau probabil câştigatori erau egali. Aceasta rezolvare făcea improbabilă scrierea unui răspuns incorect.\r\n\r\nVom generaliza acum problema: Se dă un şir de n numere naturale şi un număr întreg k, se cere determinarea tuturor elementelor care apar de cel puţin [n/k]+1 ori în şir.\r\n \r\nPrimele trei rezolvări prezentate pentru problema iniţială pot fi evident generalizate şi folosite şi pentru această problemă. Generalizarea abordării care implica folosirea cifrelor pentru a rezolva noua problemă pare imposibilă. Vom vorbi mai departe de două din celelalte trei abordări.\r\n\r\nEvident dacă un număr apare de cel puţin [n/k] + 1 ori în şir atunci el va apărea în şirul sortat pe una din poziţiile i * [n/k] cu i de la 1 la k. De aici se conturează algoritmul următor: determinăm în O(n * k) elementele de pe poziţiile i * [n/k] iar apoi verificăm care dintre acestea sunt elemente majoritare în sensul menţionat mai sus. Acest algoritm are complexitate liniară daca îl considerăm pe k o constantă.\r\n\r\nA doua soluţie este similară cu cea mai bună soluţie pentru prima problemă, numai că în loc să grupăm câte doi votanţi diferiţi vom grupa câte k votanţi cu păreri diferite.\r\n== code(cpp) |\r\nint[] mooreKMajority(int n, int[]  a, int k) {\r\n    int[] cand = new int[k - 1], notMatched = new int[k - 1],  num = new int[k-1];\r\n    Arrays.fill(cand, -1);\r\n    int num = 0;\r\n    //faza de cuplare\r\n    for (int i = 0; i < n; i++) {\r\n          boolean found = false;\r\n          for (int j = 0; j < k - 1; j++) {\r\n                if (cand[j]==a[i]) {\r\n                   notMatched[j]++;\r\n                   found = true;\r\n                   break;\r\n                }                \r\n          }\r\n          if (!found) {\r\n              for (int j = 0; j < k - 1; j++) {\r\n                    if (notMatched[j]==0) {\r\n                       cand[j] = a[i];\r\n                       notMatched[j] = 1;\r\n                       found = true;\r\n                       break;\r\n                    }                \r\n              }\r\n              if (!found) {\r\n                  for (int  j = 0; j < k – 1; j++) notMatched[j]--;                \r\n              }\r\n          }\r\n    }\r\n\r\n   //faza de verificare\r\n   for (int i = 0; i < n; i++) {\r\n          for (int j = 0; j < k - 1; j++) {\r\n                if (a[i]==cand[j] && notMatched[j] != 0)  num[j]++;                  \r\n          }\r\n   }\r\n\r\n   int numMaj = 0;\r\n   for (int j = 0; j < k - 1; j++) {\r\n        if (num[j] > n/k) numMaj++;\r\n   }\r\n\r\n   int[] ret = new int[numMaj];\r\n   numMaj = 0;\r\n   for (int j = 0; j < k - 1; j++) {\r\n        if (num[j] > n/k) {\r\n            ret[numMaj] = cand[j];\r\n            numMaj++;\r\n        }     \r\n   }\r\n\r\n   return ret;\r\n}\r\n==\r\n\r\nBibliografie:\r\n[1] T.H.Cormen, C. E. Leiserson, R. R. Rivest, Introducere în algoritmi, ed. Agora 2000\r\n[2] R. S. Boyer, J. S. Moore A Fast Majority Vote Algorithm\r\n',7668,'public',NULL,NULL),('problema-majoritatii-votului','Problema Majoritatii Votului','2009-04-06 05:09:46','2009-04-06 05:28:55','h1. Problema majorităţii votului\r\n\r\n(Negruşeri Cosmin)\r\n\r\n\r\n\r\n\r\nÎn acest articol dezbatem problema dezvoltării de algoritmi eficienţi pentru determinarea candidatului care a întrunit un număr majoritar de voturi.\r\n\r\nProblema enunţată formal este următoarea: Se dă un şir de n numere naturale, se cere determinarea unui element care apare de cel puţin [n/2]+1 ori în şir dacă există un astfel de element în şir.\r\n\r\nUn algoritm naiv ar verifica pentru fiecare element din şir de câte ori mai apare acesta. O astfel de rezolvare are complexitatea O(n^2) ca timp si O(n) ca memorie.\r\n== code(cpp) |\r\nint bruteForceMajority(int n, int[] a)\r\n    for (int i = 0; i < n; i++) {\r\n          int nr = 0;\r\n          for (int j = 0; j < n; j++) {\r\n               if (a[j]==a[i]) nr++;\r\n          }\r\n          if  (nr > n / 2) return a[i];      \r\n    }\r\n    return -1;\r\n}\r\n==\r\nDacă numerele din şir aparţin unei mulţimi {1, 2, ... k} iar acest k este mic comparativ cu n, atunci putem să îmbunătăţinm ideea de mai devreme şi să folosim un şir auxiliar b, unde b[x] va număra de câte ori apare un număr x în şirul nostru. Această soluţie are complexitate O(n + k) ca timp şi O(n + k) ca spaţiu.\r\n== code(cpp) |\r\nint countMajority(int n, int[] a, int k) {\r\n     int[] b = new int[k];\r\n    for (int i = 0; i < n; i++) {\r\n         b[a[i]]++;//incrementăm numărul de apariţii al elementului a[i]\r\n    }\r\n    for (int i = 0; i < k; i++) {\r\n         if (b[i] > n/2) return i;\r\n    }\r\n    return -1;\r\n}\r\n==\r\nSoluţia această este destul de eficientă în cazul menţionat anterior, dar când k este mult mai mare decât n, atunci această rezolvare ajunge să fie foarte lentă. Însă folosind o structură avansată de date putem să facem soluţia din nou eficientă. Această structură are la bază o tabelă de dispersie, ea mapează perechi de numere <cheie, valoare>, cheile vor fi numerele din şir, iar valorile vor fi numărul de apariţii al cheilor în şirul nostru.\r\n== code(cpp) |\r\nint hashMajority(int n, int[] a) {\r\n    HashMap<Integer, Integer> b = new HashMap<Integer, Integer>();\r\n    for (int i = 0; i < n; i++) {\r\n         if (b.get(a[i])==null) {\r\n             b.put(a[i], 1);\r\n         } else {\r\n             int num = b.get(a[i]);\r\n             b.remove(a[i]);\r\n             b.put(a[i], num + 1);\r\n         }\r\n    }\r\n    for (int i = 0; i < n; i++) {\r\n         if (b.get(a[i]) > n/2) return i;\r\n    }\r\n    return -1;\r\n}\r\n==\r\nAceastă soluţie are complexitate O(n) ca timp, şi O(n) memorie suplimentară. Menţionăm că un dezavantaj al acestei soluţii ar fi că este una randomizată.\r\n\r\nO altă soluţie care ar permite numărarea eficientă a numărului de apariţii a unui element în acest şir ar fi să sortăm şirul pentru că apoi elementele egale vor fi în poziţii consecutive.\r\n== code(cpp) |\r\nint sortMajority(int n, int[] a) {\r\n    Arrays.sort(a);\r\n    int i = 0;\r\n    while (i < n) {\r\n          int j = i;\r\n          while (j < n && a[j + 1]==a[i]) j++;\r\n          if (j – i + 1 > n / 2) return a[i];\r\n          i = j + 1;\r\n    }\r\n    return -1;\r\n}\r\n==\r\n\r\nAceastă soluţie are complexitatea O(n log n), nu foloseşte suplimentară, dar suprascrie şirul iniţial.\r\n\r\nO idee ce ne vine pe urma acestei rezolvări este aceea că în şirul sortat, un element majoritar se va afla în şirul sortat şi pe poziţia n/2.Ştim că există algoritmi de selecţie care ne găsesc elemente de poziţie o fixată k din şirul sortat în complexitate O(n). Astfel vom găsi mai întâi elementul de pe poziţia n/2 iar apoi vom verifica dacă acesta este elementul majoritar al şirului. Astfel avem o soluţie de complexitate O(n) iar şirul iniţial va fi modificat. Există metode de selecţie nerandomizate, dar pentru uşurinţa implementării vom folosi una randomizată.\r\n\r\n== code(cpp) |\r\nint  select(int n, int[] a, int left, int right, int k) {\r\n    Random ran = new Random(System.currentTimeMilis());\r\n    int i, j, aux, q; \r\n    while (left != right) {\r\n        i = left + ran.nextInt(right – left + 1);\r\n        aux = a[left]; a[left] = a[i]; a[i] = aux;\r\n        int x = a[left];\r\n        i = left – 1;\r\n        j = right + 1;\r\n        while (true) {\r\n           do { i++; } while a[i] < x;\r\n           do { j--; } while a[j] > x;\r\n            if (i < j) { aux = a[i]; a[i] = a[j]; a[j] = aux; }\r\n            else break;\r\n        }\r\n        q = right – left + 1;\r\n        if (k <= q) {\r\n            right = j;\r\n        } else {\r\n           k -= q;\r\n           left = j + 1;\r\n        }\r\n    }\r\n    return a[left];\r\n}\r\n\r\nint selectMajority(int n, int[] a) {\r\n   int x = select(n,  a,  0, n – 1, n / 2 - 1), nr = 0;\r\n   for (int i = 0; i < n; i++) {\r\n         if (a[i]==x) nr++;\r\n   }\r\n   if (nr > n/2) return x;\r\n   else return -1;\r\n}\r\n==\r\n\r\nO altă idee de rezolvare porneşte de la observaţia următoare: Dacă există un element majoritar în şir, atunci ultima lui cifră va fi elementul majoritar în şirul format din ultimele cifre a numerelor din şirul iniţial. Această observaţie este valabilă pentru orice cifră a numerelor nu doar ultima. Astfel putem determina pentru fiecare a x-a cifră a numemerelor care este cifra majoritară şi apoi să punem cap la cap cifrele majoritare pentru a forma numărul majoritar. Evident putem să folosim orice bază, dacă folosim baza b şi valoarea maximă a unui număr ar fi k atunci algoritmul va avea complexitatea O(n log in baza b din k) şi foloseşte memorie suplimentară O(b * log in baza b din k).  În practică putem considera acest algoritm ca fiind liniar. Să vedem o implementare a algoritmului pentru b = 1000 şi k = 999.999.999.\r\n\r\n== code(cpp) |\r\nint digitMajority(int n, int[] a) {\r\n     int[][] dig = new int[3][1000];\r\n     for (int i = 0; i < n; i++) {\r\n           int tmp = a[i];\r\n           for (int j = 0; j < 3; j++) {\r\n                 dig[j][tmp % 1000]++;\r\n                 tmp /= 1000;\r\n           } \r\n     }\r\n     int ret = 0;\r\n     for (int i = 0; i < 999; i++) {\r\n           if (dig[0][i] > n/2) ret += i;\r\n           if (dig[1][i] > n/2) ret += i * 1000;\r\n           if (dig[2][i] > n/2) ret += i * 1000000;\r\n     }\r\n     int nr = 0;\r\n     for (int I = 0; I < n; i++) {\r\n           if (a[i]==ret) nr++;\r\n     }\r\n     if (nr > n/2) return ret;\r\n     else return -1;\r\n}\r\n==\r\n\r\nPutem aborda probabilistic. Astfel dacă alegem un număr aleator şi există o celebritate, avem probabilitatea 0.5 să nu îl nimerim, dacă alegem k numere aleatoare din şirul respectiv, atunci avem probabilitatea\r\n(˝)^k să nu îl nimerim. Astfel algoritmul nostru va fi să luăm k numere aleatoare, iar apoi să numărăm de câte ori apare fiecare din aceste k numere în şirul nostru. Dacă folosim o structură ce mapează chei valori atunci algoritmul va avea complexitate O(n + k) şi probabilitate de reuşită P = 1 - (˝)^k. În practică o valoare de 10 pentru k ne dă o probabilitate de reuşită de 0.999. Să vedem mai departe codul:\r\n== code(cpp) |\r\nint probabilisticMajority(int n, int[] a) {\r\n    Random ran = new Random(System.currentTimeMilis());\r\n    HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();\r\n    for (int i = 0; i < 10; i++) {\r\n          map.put(a[ran.nextInt(n)], 0);         \r\n    }\r\n    for (int i = 0; i < 10; i++) {\r\n          if (map.contains(a[i])) {\r\n             int num = map.get(a[i]);\r\n             if (num + 1 > n/2) return a[i];\r\n             map.remove(a[i]);\r\n             map.add(a[i], num + 1);\r\n          }\r\n    }\r\n    return -1;\r\n}\r\n==\r\n\r\nUn ultim algoritm şi cel mai eficient dintre cele prezentate apare în lucrarea [1] şi probabil acesta este cunoscut cititorilor. Autorii au un mod plastic de a prezenta algoritmul:\r\nImaginaţi-vă o sală de conferinţă în care votanţii ţin fiecare o placă ce poartă numele candidatului preferat. Să presupunem se ajunge la o bataie generală în care votanţii cu convingeri diferite încep să se lovească reciproc cu plăcile. Să mai presupunem că fiecare votant care pune la pământ un membru cu alte convingeri este simultan şi el pus la pământ de adversar. Este evident că dacă ar fi vreun candidat care are mai multe voturi decăt toate voturile celorlalţi candidaţi, atunci această luptă va fi câştigată de acest candidat şi la dispariţia haosului din urma luptei, votanţii ce au rămas în picioare vor fi susţinători ai candidatului amintit. În caz că nu există o majoritate clară pentru un candidat sau altul, la finalul luptei rămân ăn picioare votanţi care susţin acelaşi candidat, dar acesta poate să nu fie reprezentantul majorităţii. Deci, în general, dacă cineva rămâne în picioare, preşedintele conferinţei este obligat să verifice dacă întradevar candidatul întruneşte votul a jumătate plus unu de votanţi. Algoritmul practic folosit de noi va fi un fel de joc al împerecherilor între candidaţi de opinii diferite până când toţi votanţii rămaşi necuplaţi vor susţine acelaşi candidat.\r\nRealizăm acest algoritm parcurgând lista votanţilor şi ţinând un contor cu numărul de candidaţi k neîmperecheaţi până la pasul curent, evident dacă ei sunt neîmperecheaţi trebuie să susţină acelaşi candidat cand pentru că altfel am fi putut să cuplăm câţiva dintre ei.\r\nMenţionăm că această rezolvare doar operaţii în care se verifică dacă două valori sunt identice, fapt ce se poate dovedi util pentru obiecte complexe care ar substitui candidaţii din problemă. Rezolvările anterioare s-au folosit de faptul că între elementele şirului ar exista o relaţie de ordine sau că am putea efectua asupra lor operaţii aritmetice.\r\n\r\n== code(cpp) |\r\nint mooreMajority(int n, int[]  a) {\r\n    int cand = -1, k = 0;\r\n    for (int i = 0; i < n; i++) {\r\n          if (k==0) {\r\n             cand = a[i];\r\n             k = 1;\r\n          } else  if (a[i]==cand) {\r\n              k++;//nu am putut împerechea pe votantul i şi astfel trebuie să mărim numărul de votanţi necuplaţi\r\n          } else k--;//cuplăm votantul i cu orice votant ce îl susţine pe cand şi micşorăm astfel numărul de votanţi necuplaţi\r\n    }\r\n    if (cand < 0) return cand;\r\n    //faza de verificare\r\n    int nr = 0;\r\n    for (int i = 0; i < n; i++) {\r\n          if (a[i]==cand) nr++;\r\n    }\r\n    if (nr > n / 2) return cand;\r\n    else return – 1;\r\n}\r\n==\r\n\r\nAceastă problemă a fost propusă în prima rundă a concursului Bursele Agora în 2005, Atunci nu era posibilă ţinerea tuturor numerelor din fişier în memorie şi citirea numerelor era greoaie.Doar doi concurenţi au reuşit obţinerea unui punctaj maxim la acea rundă. Autorul a fost unul dintre aceştia, el a evitat citirea de două ori a fişierului de intrare prin folosirea soluţiei cu cifre, în care calcula două rezultate pentru două baze diferite b1 şi b2 alese aleator la startul rulării, iar apoi  verifica dacă candidaţii care erau probabil câştigatori erau egali. Aceasta rezolvare făcea improbabilă scrierea unui răspuns incorect.\r\n\r\nVom generaliza acum problema: Se dă un şir de n numere naturale şi un număr întreg k, se cere determinarea tuturor elementelor care apar de cel puţin [n/k]+1 ori în şir.\r\n \r\nPrimele trei rezolvări prezentate pentru problema iniţială pot fi evident generalizate şi folosite şi pentru această problemă. Generalizarea abordării care implica folosirea cifrelor pentru a rezolva noua problemă pare imposibilă. Vom vorbi mai departe de două din celelalte trei abordări.\r\n\r\nEvident dacă un număr apare de cel puţin [n/k] + 1 ori în şir atunci el va apărea în şirul sortat pe una din poziţiile i * [n/k] cu i de la 1 la k. De aici se conturează algoritmul următor: determinăm în O(n * k) elementele de pe poziţiile i * [n/k] iar apoi verificăm care dintre acestea sunt elemente majoritare în sensul menţionat mai sus. Acest algoritm are complexitate liniară daca îl considerăm pe k o constantă.\r\n\r\nA doua soluţie este similară cu cea mai bună soluţie pentru prima problemă, numai că în loc să grupăm câte doi votanţi diferiţi vom grupa câte k votanţi cu păreri diferite.\r\n\r\n== code(cpp) |\r\nint[] mooreKMajority(int n, int[]  a, int k) {\r\n    int[] cand = new int[k - 1], notMatched = new int[k - 1],  num = new int[k-1];\r\n    Arrays.fill(cand, -1);\r\n    int num = 0;\r\n    //faza de cuplare\r\n    for (int i = 0; i < n; i++) {\r\n          boolean found = false;\r\n          for (int j = 0; j < k - 1; j++) {\r\n                if (cand[j]==a[i]) {\r\n                   notMatched[j]++;\r\n                   found = true;\r\n                   break;\r\n                }                \r\n          }\r\n          if (!found) {\r\n              for (int j = 0; j < k - 1; j++) {\r\n                    if (notMatched[j]==0) {\r\n                       cand[j] = a[i];\r\n                       notMatched[j] = 1;\r\n                       found = true;\r\n                       break;\r\n                    }                \r\n              }\r\n              if (!found) {\r\n                  for (int  j = 0; j < k – 1; j++) notMatched[j]--;                \r\n              }\r\n          }\r\n    }\r\n\r\n   //faza de verificare\r\n   for (int i = 0; i < n; i++) {\r\n          for (int j = 0; j < k - 1; j++) {\r\n                if (a[i]==cand[j] && notMatched[j] != 0)  num[j]++;                  \r\n          }\r\n   }\r\n\r\n   int numMaj = 0;\r\n   for (int j = 0; j < k - 1; j++) {\r\n        if (num[j] > n/k) numMaj++;\r\n   }\r\n\r\n   int[] ret = new int[numMaj];\r\n   numMaj = 0;\r\n   for (int j = 0; j < k - 1; j++) {\r\n        if (num[j] > n/k) {\r\n            ret[numMaj] = cand[j];\r\n            numMaj++;\r\n        }     \r\n   }\r\n\r\n   return ret;\r\n}\r\n==\r\n\r\nBibliografie:\r\n[1] T.H.Cormen, C. E. Leiserson, R. R. Rivest, Introducere în algoritmi, ed. Agora 2000\r\n[2] R. S. Boyer, J. S. Moore A Fast Majority Vote Algorithm\r\n',7668,'public',NULL,NULL),('probleme-de-taietura','Probleme de Taietura','2009-04-06 05:48:04','2009-04-06 06:01:55','h1. Probleme de taietura\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"andrici_cezar\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\nProbleme de tăietură\r\n\r\n(toc){width: 25em}*{text-align:center} *Conţinut:*\r\n* \'Problema 1\':probleme-de-taietura#1\r\n* \'Problema 2\':probleme-de-taietura2\r\n* \'Problema 3\':probleme-de-taietura3\r\n* \'Problema 4\':probleme-de-taietura4\r\n* \'Problema 5\':probleme-de-taietura5\r\n* \'Problema 6\':probleme-de-taietura6\r\n* \'Problema 7\':probleme-de-taietura7\r\n* \'Problema 8\':probleme-de-taietura8\r\n* \'Problema 9\':probleme-de-taietura9\r\n* \'Problema 10\':probleme-de-taietura10\r\n* \'Problema 11\':probleme-de-taietura11\r\n* \'Problema 12\':probleme-de-taietura12\r\n* \'Problema 13\':probleme-de-taietura13\r\n* \'Bibliografie\':probleme-de-taieturabio\r\n\r\nProbleme de tăietură\r\n\r\nh2(#1). Problema 1:\r\n\r\nPentru un număr natural N dat, se cere numărul maxim de regiuni în care se poate împărţi planul folosind N drepte.\r\n\r\n \r\nRezolvare:\r\nMai întâi facem vom face două observaţii:\r\nÎn configuraţia cu număr maxim de regiuni nu vom avea două drepte paralele, pentru că două drepte care se intersectează formează în plan patru regiuni, în timp ce două drepte paralele formează în plan doar trei regiuni.\r\nDe asemenea pentru a obţine un număr maxim de regiuni, nu vor exista trei drepte care să se intersecteze intr-un punct pentru că astfel am pierde o regiune triunghiulară formată din punctele de intersecţie ale celor trei drepte.\r\nDacă aceste două condiţii sunt îndeplinite vom vedea în continuare că orice configuraţie de N drepte împarte planul în acelaţi număr de regiuni. Notăm cu d(n) acest număr. Presupunem ca ştim pe d(n), să vedem acum ce se întâmplă dacă mai adaugăm o dreaptă. \r\nAceastă nouă dreaptă va fi intersectată de celelalte drepte în n puncte distincte. Fiecare segment de dreaptă şi semidreaptă în care este împărţită a n+1-a taie o regiune veche in două regiuni noi. De aici tragem concluzia că d(n+1) = d(n) + n + 1. Deci d(n) = n + n – 1 + n – 2 + … + 2 + d(1). Astfel folosind indentitatea 1 + 2 + 3 + … + n = n(n+1)/2 obţinem d(n) = n(n + 1) / 2 + 1.\r\nMenţionăm că problemele în care se cere maximizarea numărului de regiuni în care un pătrat, un triunghi sau un cerc este împărţit de n drepte, au aceiaşi soluţie.\r\n\r\nh2(#2).Problema 2:\r\n\r\nDându-se un număr natural N, se cere numărul maxim de regiuni în care N cercuri pot împărţi planul.\r\n \r\nRezolvare:\r\nEste clar că oricare două cercuri trebuie să se intersecteze in exact două puncte, nu să fie tangente sau să nu se intersecteze deloc pentru că astfel am pierde o regiune, iar oricare trei cercuri nu se intersectează într-un punct.\r\nOrice configuraţie care satisface această cerinţă va împărţi planul într-un număr maxim de regiuni.Vom nota cu c(n) numărul maxim de regiuni în care este împărţit planul de n cercuri. Să vedem ce se întîmplă când adăugăm un nou cerc la această configuraţie. Cercul nou va fi intersectat de cele n cercuri în 2n puncte distincte, şi astfel va fi împărţit în 2n arce. Fiecare dintre aceste arce împarte o zonă veche în două zone noi. De aici tragem concluzia că c(n + 1) = 2n + c(n). Astfel putem să îl scriem pe c(n) ca 2(n – 1) + 2(n – 2) + … + 2 + c(1). De aici folosind din nou identitatea 1 + 2 + … + n = n(n+1)/2 avem că c(n) = n(n-1) + 2.\r\nEste evident că şi problema în care se cere maximizarea numărului de regiuni în care este împărţită suprafaţa unei sfere de n cercuri are aceiaşi soluţie.\r\n\r\nh2(#3). Problema 3:\r\n\r\nSe dau n cercuri care se intersectează oricare două în două puncte şi nu există trei care se intersectează într-un punct, se cere să se determine numărul de zone în care este împarţit planul de aceste n cercuri. ( n <= 10^100)\r\n[acm.uva.es 10519 !! Really Strange !!]\r\nRezolvare:\r\nObservăm ca sunt indeplinite condiţiile de maximalitate cerute mai sus, deci rezultatul e c(n), singura problema ce rămâne este aceea de implementare a operaţiilor cu numere mari.\r\n\r\nProblema 4:\r\nAvem un număr natural N, vrem să determinăm numărul maxim de regiuni în care poate fi împărţit un plan de elipse.\r\n \r\nRezolvare:\r\nLa fel ca şi la cercuri nici aici nu trebuie să avem elipse tangente, sau elipse care să nu se intersecteze, nu vor exista nici aici trei elipse care să se intersecteze într-un punct, aici elipsele trebuie să se intersecteze în patru puncte, dacă s-ar intersecta numai în două puncte atunci configuraţia nu ar avea număr maxim de regiuni.\r\nNotăm cu e(n) numărul de care suntem interesaţi. Câte regiuni noi apar cand adăugam o nouă elipsă? Păi o nouă elipsă va fi intersectată de celelalte elipse ăn patru puncte de fiecare, deci e(n + 1) = 4n + e(n). De aici tragem concluzia că e(n) = 2 n(n - 1) + 2.\r\n\r\nProblema 5:\r\nDându-se un număr natural N, se cere numărul maxim de regiuni în care N triunghiuri pot împărţi planul.\r\n \r\nRezolvare:\r\nRepetând raţionamentul de la problemele anterioareavem că t(n+1) = 6n + t(n) => t(n) = 3n(n-1) + 2. \r\n\r\nProblema 6:\r\nPentru N plane determinaţi numărul maxim de zone în care poate fi împărţit spaţiul cu acestea.\r\nRezolvare:\r\nÎn această problemă urmăm raţionamentul de până acum. Este evident că trebuie ca fiecare plan să se intersecteze cu fiecare, că oricare trei plane trebuie să nu se intersecteze într-o dreaptă, oricare trei plane nu trebuie să fie paralele cu o dreaptă şi oricare patru plane nu trebuie să se intersecteze într-un punct. Notăm p(n) numărul maxim de zone în care n plane împart spatiul. Când adaugăm un nou plan acesta va fi intersectat de celelalte plane în n drepte, drepte care după restrictiile care le-am pus nu vor fi două paralele sau trei care să se intersecteze într-un punct. Acest plan va fi împărţit în d(n)  regiuni de aceste drepte din cauza restricţiilor impuse. Fiecare regiune din plan taie o zonă din spaţiu în două noi zone, de aici tragem concluzia că p(n + 1) = d(n) + p(n). Astfel avem p(n) =  n(n-1)/2 + 1 + (n-1)(n-2)/2 + 1 + … +  2 * 1 / 2 + 1 + p(1) = ( n^2 – n + (n-1)^2 – (n-1) + … + 2^2 – 2  +  1 – 1 + (n – 1) )/2 + 2 = ( n(n+1)(2n + 1)/6 – n(n+1)/2 + (n-1))/2 + 2  = (n^3/3 + n^2/2 + n/6 – n^2/2 – n/2 )/2 + n + 1 = n^3 / 6 + 5n/6 + 1. Am folosit identităţile 1 + 2 + … + n = n(n+1)/2 şi 1 + 2^2 + 3^2 + … + n^2 = n(n+1)(2n+1)/6 care se pot demonstra uşor prin inducţie.\r\nMenţionăm că dacă vrem să împărţim un cub, un cilindru o sfera etc în număr maxim de regiuni folosind n plane, formula se păstrează.\r\n\r\nProblema 7:\r\nDându-se un număr natural N, să se determine numărul maxim de zone în care pot împărţi spaţiul N sfere.\r\n[Bursele Agora 2001[3]]\r\nRezolvare:\r\nPornim la fel ca la problema anterioară, oricare două sfere se vor intersecta şi nu vor exista trei sfere care să se intersecteze în acelaşi punct. Vom nota cu s(n) numărul maxim de regiuni în care poate fi împărţit spaţiul cu n sfere. Să vedem ce se întâmplă când adăugăm o sferă. Această sferă va fi intersectată de toate celelalte n sfere în n cercuri, pentru ca numărul de regiuni noi să fie maxim aceste cercuri vor împărţi sfera într-un număr maxim de regiuni, acest număr este c(n) aşa cum am discutat la problema 2. Obţinem astfel s(n + 1) = c(n) + s(n) = c(n) + c(n-1) + ... + c(1) = n(n-1) + 2 + (n-1)(n-2) + 2 + ... + 2 = 1 + 2^2 + .. + n^2 – 1 – 2 – 3 - .... – n + 2n => s(n) = n(n^2 – 3n + 8) / 3\r\n\r\nProblema 8:\r\nSe dă un număr N care este numărul maxim în care poate fi împărţit planul de m elipse, n cercuri şi p triunghiuri. Se cere ştiind N să se determine toate valorile posibile pentru m, n şi p. (N întreg făra semn reprezentabil pe 32 de biţi, 0<=m<100, 0<=n<20000 şi 0<=p<100)\r\n[10623 Thinking Backward [4]]\r\nRezolvare:\r\nDacă am ştii pentru trei parametrii m, n şi p care este numarul maxim de părţi în care poate fi împărţit planul  de m elipse, n cercuri şi p triunghiuri, atunci am putea incerca toate posibilitaţile pentru m, n şi p şi am găsi tripletele pentru rezultatul ar fie gal cu N, chiar am putea optimiza puţin acest algoritm iteram pe toate valorile de m şi p, astfel vom obţine o ecuaţie cu necunoscuta n astfel vom face doar 10000 de rezolvări de ecuaţii în loc de 200 000 000 de comparaţii. \r\nSă vedem cum găsim numărul maxim de zone. Din nou oricare două figuri se intersectează în număr maxim de intersecţii, un cerc cu o elipsă în patru puncte, un cerc sau o elipsă cu un triunghi în şase puncte. Mai întâi punem cele m elipse in plan, ele vor împărţi planul în e(m) regiuni adică 2 m(m - 1) + 2. După aceea adaugăm cercurile. Să notam numarul maxim de zone în care n cercuri şi m elipse pot împărţi planul cu ec(m , n). Dacă ştim cât este e(m, n-1) atunci când adaugăm un nou cerc, acesta va fi intersectat de m elipse in 4m puncte şi de n-1 cercuri in 2(n – 1) puncte deci cercul va fi împărţit în 4m + 2(n-1) arce care vor împărţi tot atâtea regiuni care existau deja in câte două regiuni noi. Deci ec(m, n) = 4m + 2(n-1) + ec(m, n-1) = 4m + 2(n-1) + 4m + 2(n-2) + … + 4m + 2 + ec(m, 0) = 4m(n-1) + n (n-1) + 2m(m-1) + 2. Să vedem ce se întâmplă când adăugăm triunghiurile. Vom nota ect(m, n, p) numărul maxim de zone în care poate fi împărţit planul de m elipse, n cercuri şi p triunghiuri. Dacă ştim cu cat e egal ect(m, n, p - 1) , atunci când vom adăuga un nou triunghi acesta va intersecta cele m cercuri în 6m puncte, cele n elipse în 6n puncte şi cele p – 1 triunghiuri în 6(p – 1) puncte, astfel se vor forma 6m + 6n + 6(p-1) noi zone. Deci ect(m, n, p) = 6(m + n + p – 1) + ect(m, n, p – 1) = 6 (m + n + p – 1 + m + n + p – 2 + … m + n + 1) + ect(n, m, 0) = 6 (p-1)(m+n) + 3p(p-1) + 4m(n-1) + n(n-1) + 2m(m-1) + 2.\r\n\r\nProblemele anterioare au fost cam matematice şi ele sunt numite de obicei de olimpici peiorativ ca “probleme de formulă”, majoritatea olimpicilor la informatică participă aici pentru că matematica nu le place aşa tare şi deci nici apariţia unor probleme ca cele de mai sus care sunt mai mult de mate decât de info nu îi prea încântă. Cum poate fi rezolvată o problemă de formulă fără să avem intuiţia matematică sau cunoţinţele matematice necesare? Păi câteodată elevii apelează la următorul truc: află primele câteva valori de mâna sau cu ajutorul unor algoritmi brute force şi apoi speră ca formula să fie de o anumită formă, de exemplu ar putea fi un polinom de un grad mic. Atunci avem ca f(N) = An^3 + Bn^2 + Cn + D. Afland primele câteva valori vom ştii valorile f(1), f(2), f(3), f(4). Dând lui n pe rand valorile 1, 2, 3 şi 4 putem face un sistem cu necunoscutele A, B, C şi D. Sau putem încerca să vedem cum se comportă şirul de numere, are o creştere polinomială sau exponenţială, apar valorile lui în triunghiul lui Pascal. Iar dacă rezolvăm problemele de acasă putem căuta valorile din şirul de soluţii pe internet pe pagina Eciclopedia Online a şirurilor de întregi [7] care este o resursă foarte utilă în cazul problemelor de acest gen .\r\n\r\nProblema 9:\r\nSe dau N drepte în plan, fiecare dreaptă este dată prin două puncte prin care trece. Se cere să se determine pentru această configuraţie în câte zone este împărţit planul. (n <= 1000)\r\n[Internet Problem Solving Contest 2000 [5]]\r\nRezolvare:\r\nÎn sfârşit o problemă în care avem nevoie să folosim calculatorul şi talentul nostru de programatori . Vom folosi aceeaşi idee ce a apărut şi în celelalte probleme, adică numărăm pe rând în câte zone este împărţit planul de primele o dreaptă, doua drepte respectiv n drepte. Deci vom adăuga în ordine dreptele la configuraţia noastră. Când adăugăm o dreaptă ea va fi intersectată de dreptele deja adăugate în k puncte nu neapărat distincte, pe noi ne intereseaza punctele distincte, ca să facem acest lucru putem sorta punctele în O(k log k) sau să folosim o tabelă de dispersie şi astfel să aflăm în O(k) numărul de puncte distincte, daca acest număr e egal cu L atunci la numărul curent de zone vom adăuga L. Astfel algoritmul are complexitatea O(n^2 log n), sau dacă folosim tabele de dispersie O(n^2).\r\n\r\nProblema 10:\r\nAvem un tort în formă de pătrat de dimensiune 1000 x 1000. Folosim un cuţit pentru a tăoa tortul. Întrebarea este după o serie de tăieturi, în căte bucăţi am patriţionat tortul. Restricţii: Numărul de tăieturi nu va fi mai mare de 8. După tăieturi, lungimea oricărei laturi a partiţiei nu va fi mai mică decât unu. Coordonatele vârfurilor tortului vor fi (0,0)(0,1000)(1000,1000) (1000,0). Tăieturile se vor intersecta în două puncte cu marginile tortului. Următoarea imagine e un tort tăiat în zece bucăţi.\r\n[acm.uva.es 527 The partition of a cake]\r\nRezolvarea este analoaga cu cea a problemei anterioare, datele sunt foarte mici în problema aceasta, probabil că autorii au vrut să facă problema accesibilă şi altor idei care folosesc împărţiri efective în poligoane a pătratului.\r\n\r\nProblema 11:\r\nSe dă un graf planar prin noduri şi muchii, un graf este planar dacă există o modalitate de a îl desena în plan făra ca muchiile să se intersecteze decăt la capete. Se cere să se determine în căte regiuni împarte planul graful dat la intrare. Mai jos avem un exemplu de graf în care feţele sunt numerotate.\r\n[10178 Count the faces [4]]\r\n\r\nRezolvare:\r\nEste interesant faptul că în această problemă nu ne este dată configuraţia în plan a grafului ci doar structura lui. Un graf il putem reprezenta în mai multe moduri în plan, astfel suntem duşi înspre ideea că există ceva formulă care rezolvă problema. O formulă întradevăr există şi se numeşte formula lui Euler pentru grafurile planare. Formula arată aşa f - m + n  = 2, unde prin f am notat numărul de feţe, m numărul de muchii şi n numărul de vârfuri., dacă graful nostru e conex (formula include faţa exterioară). Această formulă poate fi demonstrată în foarte multe moduri. Dacă vreţi să vedeţi 19 metode de demonstrare puteţi să vizitaţi adresa [8]. O demonstraţie simplă ar fi prin inducţie pornind de la un arbore şi adăugând pe rând câte o muchie. La început avem o singură faţă, cea infinită, 1 – (n – 1) + n = 2 se verifică. Fiecare muchie adăugată împarte o faţă în două deci dacă aveam inainte f – m + n = 2 acum vom avea f1 – m1 + n = 2 unde f1 = f + 1 şi m1 = m + 1. Deci am demonstrate formula şi putem foarte uşor să rezolvăm problema, mai trebuie numai să avem grijă ca pentru fiecare componentă conexă număram faţa infinită.\r\nAceastă formulă este adevarată şi în spaţiu pentru poliedre.\r\n\r\nProblema 12:\r\nSe considera N cercuri in plan. Se cere să se determine numărul de zone finite în care cercurile date împart planul.\r\n \r\nDate de intrare\r\nPe prima linie a fişierului CERCURI.IN se află N (1<=N<=200). Pe urmatoarele N linii se află câte trei numere întregi sub forma xi yi si ri, reprezentând coordonatele centrului şi raza cercului i.Coordonatele sunt numere ântregi din intervalul [0, 10000]. Razele cercurilor sunt întregi din intervalul [1, 1000].\r\nDate de ieşire\r\nIn fişierul CERCURI.OUT se va afisa numărul de zone determinat de cercurile date.\r\nExemplu\r\nCERCURI.IN\r\n4\r\n90 110 50\r\n130 70 30\r\n155 45 15\r\n165 115 65\r\nCERCURI.OUT\r\n11\r\n[Algoritmus, Cercuri[6]]\r\nRezolvare:\r\nContraexemple rezolvare normala\r\nO rezolvare folosind geometria computaţională pare foarte grea, lucrurile simplificându-se mult daca abordam problema prin prisma unor noţiuni de teoria grafurilor.\r\nFiecare punct de intersectie va fi considerat un nod. Două noduri vor fi legate prin o muchie dacă există un cerc pe care sa se afle amândouă iar între ele să nu existe nici un alt punct de intersectie.\r\nAcum vom folosi identitatea lui Euler: prezentată în problema anterioară. În problema noastră nu trebuie să numărăm şi faţa exterioară, deci formula folosita va fi F=M-V+1. Această formulă este adevarată doar in cazul unei singure componente conexe. Pentru mai multe componente, formula devine F=M-V+C, unde C este numărul de componente conexe.\r\nO atenţie deosebită trebuie acordată punctelor de intersecţie prin care trec mai mult de două cercuri, pentru a nu le număra de mai multe ori. Putem rezolva aceasta problema prin sortarea punctelor de intersecţie ale unui cerc cu toate celelalte cercuri.\r\nDeasemenea, este necesara eliminarea cercurilor identice (cu acelaşi centru şi raze egale). Din orice mulţime cu astfel de cercuri este păstrat doar un singur element.\r\nDeoarece pentru fiecare cerc este necesara o sortare a punctelor de intersectie, complexitatea generala a algoritmului va fi O(N2*log(N))\r\n\r\n[1]  A.M. Iaglom, I. M. Iaglom, Probleme neelementare tratate elementat. Ed tehnică, Bucureşti, 1962\r\n[2] I. Tomescu, Probleme de combinatorică şi teoria grafurilor, ed didactică şi pedagogică. Bucureşti, 1981\r\n[3] Colecţia Ginfo\r\n[4] acm.uva.es\r\n[5] ipsc.ksp.sk\r\n[6] algoritmus.org/index.php\r\n[7]http://www.research.att.com/~njas/sequences/\r\n[8]http://www.ics.uci.edu/~eppstein/junkyard/euler/\r\n',7668,'public',NULL,NULL),('probleme-de-taietura','Probleme de Taietura','2009-04-06 05:48:04','2009-04-06 06:05:50','h1. Probleme de taietura\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"andrici_cezar\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\nProbleme de tăietură\r\n\r\n(toc){width: 25em}*{text-align:center} *Conţinut:*\r\n* \'Problema 1\':probleme-de-taietura#1\r\n* \'Problema 2\':probleme-de-taietura#2\r\n* \'Problema 3\':probleme-de-taietura#3\r\n* \'Problema 4\':probleme-de-taietura#4\r\n* \'Problema 5\':probleme-de-taietura#5\r\n* \'Problema 6\':probleme-de-taietura#6\r\n* \'Problema 7\':probleme-de-taietura#7\r\n* \'Problema 8\':probleme-de-taietura#8\r\n* \'Problema 9\':probleme-de-taietura#9\r\n* \'Problema 10\':probleme-de-taietura#10\r\n* \'Problema 11\':probleme-de-taietura#11\r\n* \'Problema 12\':probleme-de-taietura#12\r\n* \'Problema 13\':probleme-de-taietura#13\r\n* \'Bibliografie\':probleme-de-taietura#bio\r\n\r\nProbleme de tăietură\r\n\r\nh2(#1). Problema 1:\r\n\r\nPentru un număr natural N dat, se cere numărul maxim de regiuni în care se poate împărţi planul folosind N drepte.\r\n\r\n \r\nRezolvare:\r\nMai întâi facem vom face două observaţii:\r\nÎn configuraţia cu număr maxim de regiuni nu vom avea două drepte paralele, pentru că două drepte care se intersectează formează în plan patru regiuni, în timp ce două drepte paralele formează în plan doar trei regiuni.\r\nDe asemenea pentru a obţine un număr maxim de regiuni, nu vor exista trei drepte care să se intersecteze intr-un punct pentru că astfel am pierde o regiune triunghiulară formată din punctele de intersecţie ale celor trei drepte.\r\nDacă aceste două condiţii sunt îndeplinite vom vedea în continuare că orice configuraţie de N drepte împarte planul în acelaţi număr de regiuni. Notăm cu d(n) acest număr. Presupunem ca ştim pe d(n), să vedem acum ce se întâmplă dacă mai adaugăm o dreaptă. \r\nAceastă nouă dreaptă va fi intersectată de celelalte drepte în n puncte distincte. Fiecare segment de dreaptă şi semidreaptă în care este împărţită a n+1-a taie o regiune veche in două regiuni noi. De aici tragem concluzia că d(n+1) = d(n) + n + 1. Deci d(n) = n + n – 1 + n – 2 + … + 2 + d(1). Astfel folosind indentitatea 1 + 2 + 3 + … + n = n(n+1)/2 obţinem d(n) = n(n + 1) / 2 + 1.\r\nMenţionăm că problemele în care se cere maximizarea numărului de regiuni în care un pătrat, un triunghi sau un cerc este împărţit de n drepte, au aceiaşi soluţie.\r\n\r\nh2(#2). Problema 2:\r\n\r\nDându-se un număr natural N, se cere numărul maxim de regiuni în care N cercuri pot împărţi planul.\r\n \r\nRezolvare:\r\nEste clar că oricare două cercuri trebuie să se intersecteze in exact două puncte, nu să fie tangente sau să nu se intersecteze deloc pentru că astfel am pierde o regiune, iar oricare trei cercuri nu se intersectează într-un punct.\r\nOrice configuraţie care satisface această cerinţă va împărţi planul într-un număr maxim de regiuni.Vom nota cu c(n) numărul maxim de regiuni în care este împărţit planul de n cercuri. Să vedem ce se întîmplă când adăugăm un nou cerc la această configuraţie. Cercul nou va fi intersectat de cele n cercuri în 2n puncte distincte, şi astfel va fi împărţit în 2n arce. Fiecare dintre aceste arce împarte o zonă veche în două zone noi. De aici tragem concluzia că c(n + 1) = 2n + c(n). Astfel putem să îl scriem pe c(n) ca 2(n – 1) + 2(n – 2) + … + 2 + c(1). De aici folosind din nou identitatea 1 + 2 + … + n = n(n+1)/2 avem că c(n) = n(n-1) + 2.\r\nEste evident că şi problema în care se cere maximizarea numărului de regiuni în care este împărţită suprafaţa unei sfere de n cercuri are aceiaşi soluţie.\r\n\r\nh2(#3). Problema 3:\r\n\r\nSe dau n cercuri care se intersectează oricare două în două puncte şi nu există trei care se intersectează într-un punct, se cere să se determine numărul de zone în care este împarţit planul de aceste n cercuri. ( n <= 10^100)\r\n[acm.uva.es 10519 !! Really Strange !!]\r\nRezolvare:\r\nObservăm ca sunt indeplinite condiţiile de maximalitate cerute mai sus, deci rezultatul e c(n), singura problema ce rămâne este aceea de implementare a operaţiilor cu numere mari.\r\n\r\nh2(#4). Problema 4:\r\n\r\nAvem un număr natural N, vrem să determinăm numărul maxim de regiuni în care poate fi împărţit un plan de elipse.\r\n \r\nRezolvare:\r\nLa fel ca şi la cercuri nici aici nu trebuie să avem elipse tangente, sau elipse care să nu se intersecteze, nu vor exista nici aici trei elipse care să se intersecteze într-un punct, aici elipsele trebuie să se intersecteze în patru puncte, dacă s-ar intersecta numai în două puncte atunci configuraţia nu ar avea număr maxim de regiuni.\r\nNotăm cu e(n) numărul de care suntem interesaţi. Câte regiuni noi apar cand adăugam o nouă elipsă? Păi o nouă elipsă va fi intersectată de celelalte elipse ăn patru puncte de fiecare, deci e(n + 1) = 4n + e(n). De aici tragem concluzia că e(n) = 2 n(n - 1) + 2.\r\n\r\nh2(#5). Problema 5:\r\n\r\nDându-se un număr natural N, se cere numărul maxim de regiuni în care N triunghiuri pot împărţi planul.\r\n \r\nRezolvare:\r\nRepetând raţionamentul de la problemele anterioareavem că t(n+1) = 6n + t(n) => t(n) = 3n(n-1) + 2. \r\n\r\nh2(#6). Problema 6:\r\n\r\nPentru N plane determinaţi numărul maxim de zone în care poate fi împărţit spaţiul cu acestea.\r\nRezolvare:\r\nÎn această problemă urmăm raţionamentul de până acum. Este evident că trebuie ca fiecare plan să se intersecteze cu fiecare, că oricare trei plane trebuie să nu se intersecteze într-o dreaptă, oricare trei plane nu trebuie să fie paralele cu o dreaptă şi oricare patru plane nu trebuie să se intersecteze într-un punct. Notăm p(n) numărul maxim de zone în care n plane împart spatiul. Când adaugăm un nou plan acesta va fi intersectat de celelalte plane în n drepte, drepte care după restrictiile care le-am pus nu vor fi două paralele sau trei care să se intersecteze într-un punct. Acest plan va fi împărţit în d(n)  regiuni de aceste drepte din cauza restricţiilor impuse. Fiecare regiune din plan taie o zonă din spaţiu în două noi zone, de aici tragem concluzia că p(n + 1) = d(n) + p(n). Astfel avem p(n) =  n(n-1)/2 + 1 + (n-1)(n-2)/2 + 1 + … +  2 * 1 / 2 + 1 + p(1) = ( n^2 – n + (n-1)^2 – (n-1) + … + 2^2 – 2  +  1 – 1 + (n – 1) )/2 + 2 = ( n(n+1)(2n + 1)/6 – n(n+1)/2 + (n-1))/2 + 2  = (n^3/3 + n^2/2 + n/6 – n^2/2 – n/2 )/2 + n + 1 = n^3 / 6 + 5n/6 + 1. Am folosit identităţile 1 + 2 + … + n = n(n+1)/2 şi 1 + 2^2 + 3^2 + … + n^2 = n(n+1)(2n+1)/6 care se pot demonstra uşor prin inducţie.\r\nMenţionăm că dacă vrem să împărţim un cub, un cilindru o sfera etc în număr maxim de regiuni folosind n plane, formula se păstrează.\r\n\r\nh2(#7). Problema 7:\r\n\r\nDându-se un număr natural N, să se determine numărul maxim de zone în care pot împărţi spaţiul N sfere.\r\n[Bursele Agora 2001[3]]\r\nRezolvare:\r\nPornim la fel ca la problema anterioară, oricare două sfere se vor intersecta şi nu vor exista trei sfere care să se intersecteze în acelaşi punct. Vom nota cu s(n) numărul maxim de regiuni în care poate fi împărţit spaţiul cu n sfere. Să vedem ce se întâmplă când adăugăm o sferă. Această sferă va fi intersectată de toate celelalte n sfere în n cercuri, pentru ca numărul de regiuni noi să fie maxim aceste cercuri vor împărţi sfera într-un număr maxim de regiuni, acest număr este c(n) aşa cum am discutat la problema 2. Obţinem astfel s(n + 1) = c(n) + s(n) = c(n) + c(n-1) + ... + c(1) = n(n-1) + 2 + (n-1)(n-2) + 2 + ... + 2 = 1 + 2^2 + .. + n^2 – 1 – 2 – 3 - .... – n + 2n => s(n) = n(n^2 – 3n + 8) / 3\r\n\r\nh2(#8). Problema 8:\r\n\r\nSe dă un număr N care este numărul maxim în care poate fi împărţit planul de m elipse, n cercuri şi p triunghiuri. Se cere ştiind N să se determine toate valorile posibile pentru m, n şi p. (N întreg făra semn reprezentabil pe 32 de biţi, 0<=m<100, 0<=n<20000 şi 0<=p<100)\r\n[10623 Thinking Backward [4]]\r\nRezolvare:\r\nDacă am ştii pentru trei parametrii m, n şi p care este numarul maxim de părţi în care poate fi împărţit planul  de m elipse, n cercuri şi p triunghiuri, atunci am putea incerca toate posibilitaţile pentru m, n şi p şi am găsi tripletele pentru rezultatul ar fie gal cu N, chiar am putea optimiza puţin acest algoritm iteram pe toate valorile de m şi p, astfel vom obţine o ecuaţie cu necunoscuta n astfel vom face doar 10000 de rezolvări de ecuaţii în loc de 200 000 000 de comparaţii. \r\nSă vedem cum găsim numărul maxim de zone. Din nou oricare două figuri se intersectează în număr maxim de intersecţii, un cerc cu o elipsă în patru puncte, un cerc sau o elipsă cu un triunghi în şase puncte. Mai întâi punem cele m elipse in plan, ele vor împărţi planul în e(m) regiuni adică 2 m(m - 1) + 2. După aceea adaugăm cercurile. Să notam numarul maxim de zone în care n cercuri şi m elipse pot împărţi planul cu ec(m , n). Dacă ştim cât este e(m, n-1) atunci când adaugăm un nou cerc, acesta va fi intersectat de m elipse in 4m puncte şi de n-1 cercuri in 2(n – 1) puncte deci cercul va fi împărţit în 4m + 2(n-1) arce care vor împărţi tot atâtea regiuni care existau deja in câte două regiuni noi. Deci ec(m, n) = 4m + 2(n-1) + ec(m, n-1) = 4m + 2(n-1) + 4m + 2(n-2) + … + 4m + 2 + ec(m, 0) = 4m(n-1) + n (n-1) + 2m(m-1) + 2. Să vedem ce se întâmplă când adăugăm triunghiurile. Vom nota ect(m, n, p) numărul maxim de zone în care poate fi împărţit planul de m elipse, n cercuri şi p triunghiuri. Dacă ştim cu cat e egal ect(m, n, p - 1) , atunci când vom adăuga un nou triunghi acesta va intersecta cele m cercuri în 6m puncte, cele n elipse în 6n puncte şi cele p – 1 triunghiuri în 6(p – 1) puncte, astfel se vor forma 6m + 6n + 6(p-1) noi zone. Deci ect(m, n, p) = 6(m + n + p – 1) + ect(m, n, p – 1) = 6 (m + n + p – 1 + m + n + p – 2 + … m + n + 1) + ect(n, m, 0) = 6 (p-1)(m+n) + 3p(p-1) + 4m(n-1) + n(n-1) + 2m(m-1) + 2.\r\n\r\nProblemele anterioare au fost cam matematice şi ele sunt numite de obicei de olimpici peiorativ ca “probleme de formulă”, majoritatea olimpicilor la informatică participă aici pentru că matematica nu le place aşa tare şi deci nici apariţia unor probleme ca cele de mai sus care sunt mai mult de mate decât de info nu îi prea încântă. Cum poate fi rezolvată o problemă de formulă fără să avem intuiţia matematică sau cunoţinţele matematice necesare? Păi câteodată elevii apelează la următorul truc: află primele câteva valori de mâna sau cu ajutorul unor algoritmi brute force şi apoi speră ca formula să fie de o anumită formă, de exemplu ar putea fi un polinom de un grad mic. Atunci avem ca f(N) = An^3 + Bn^2 + Cn + D. Afland primele câteva valori vom ştii valorile f(1), f(2), f(3), f(4). Dând lui n pe rand valorile 1, 2, 3 şi 4 putem face un sistem cu necunoscutele A, B, C şi D. Sau putem încerca să vedem cum se comportă şirul de numere, are o creştere polinomială sau exponenţială, apar valorile lui în triunghiul lui Pascal. Iar dacă rezolvăm problemele de acasă putem căuta valorile din şirul de soluţii pe internet pe pagina Eciclopedia Online a şirurilor de întregi [7] care este o resursă foarte utilă în cazul problemelor de acest gen .\r\n\r\nh2(#9). Problema 9:\r\n\r\nSe dau N drepte în plan, fiecare dreaptă este dată prin două puncte prin care trece. Se cere să se determine pentru această configuraţie în câte zone este împărţit planul. (n <= 1000)\r\n[Internet Problem Solving Contest 2000 [5]]\r\nRezolvare:\r\nÎn sfârşit o problemă în care avem nevoie să folosim calculatorul şi talentul nostru de programatori . Vom folosi aceeaşi idee ce a apărut şi în celelalte probleme, adică numărăm pe rând în câte zone este împărţit planul de primele o dreaptă, doua drepte respectiv n drepte. Deci vom adăuga în ordine dreptele la configuraţia noastră. Când adăugăm o dreaptă ea va fi intersectată de dreptele deja adăugate în k puncte nu neapărat distincte, pe noi ne intereseaza punctele distincte, ca să facem acest lucru putem sorta punctele în O(k log k) sau să folosim o tabelă de dispersie şi astfel să aflăm în O(k) numărul de puncte distincte, daca acest număr e egal cu L atunci la numărul curent de zone vom adăuga L. Astfel algoritmul are complexitatea O(n^2 log n), sau dacă folosim tabele de dispersie O(n^2).\r\n\r\nh2(#10). Problema 10:\r\n\r\nAvem un tort în formă de pătrat de dimensiune 1000 x 1000. Folosim un cuţit pentru a tăoa tortul. Întrebarea este după o serie de tăieturi, în căte bucăţi am patriţionat tortul. Restricţii: Numărul de tăieturi nu va fi mai mare de 8. După tăieturi, lungimea oricărei laturi a partiţiei nu va fi mai mică decât unu. Coordonatele vârfurilor tortului vor fi (0,0)(0,1000)(1000,1000) (1000,0). Tăieturile se vor intersecta în două puncte cu marginile tortului. Următoarea imagine e un tort tăiat în zece bucăţi.\r\n[acm.uva.es 527 The partition of a cake]\r\nRezolvarea este analoaga cu cea a problemei anterioare, datele sunt foarte mici în problema aceasta, probabil că autorii au vrut să facă problema accesibilă şi altor idei care folosesc împărţiri efective în poligoane a pătratului.\r\n\r\nh2(#11). Problema 11:\r\n\r\nSe dă un graf planar prin noduri şi muchii, un graf este planar dacă există o modalitate de a îl desena în plan făra ca muchiile să se intersecteze decăt la capete. Se cere să se determine în căte regiuni împarte planul graful dat la intrare. Mai jos avem un exemplu de graf în care feţele sunt numerotate.\r\n[10178 Count the faces [4]]\r\n\r\nRezolvare:\r\nEste interesant faptul că în această problemă nu ne este dată configuraţia în plan a grafului ci doar structura lui. Un graf il putem reprezenta în mai multe moduri în plan, astfel suntem duşi înspre ideea că există ceva formulă care rezolvă problema. O formulă întradevăr există şi se numeşte formula lui Euler pentru grafurile planare. Formula arată aşa f - m + n  = 2, unde prin f am notat numărul de feţe, m numărul de muchii şi n numărul de vârfuri., dacă graful nostru e conex (formula include faţa exterioară). Această formulă poate fi demonstrată în foarte multe moduri. Dacă vreţi să vedeţi 19 metode de demonstrare puteţi să vizitaţi adresa [8]. O demonstraţie simplă ar fi prin inducţie pornind de la un arbore şi adăugând pe rând câte o muchie. La început avem o singură faţă, cea infinită, 1 – (n – 1) + n = 2 se verifică. Fiecare muchie adăugată împarte o faţă în două deci dacă aveam inainte f – m + n = 2 acum vom avea f1 – m1 + n = 2 unde f1 = f + 1 şi m1 = m + 1. Deci am demonstrate formula şi putem foarte uşor să rezolvăm problema, mai trebuie numai să avem grijă ca pentru fiecare componentă conexă număram faţa infinită.\r\nAceastă formulă este adevarată şi în spaţiu pentru poliedre.\r\n\r\nh2(#12). Problema 12:\r\n\r\nSe considera N cercuri in plan. Se cere să se determine numărul de zone finite în care cercurile date împart planul.\r\n \r\nDate de intrare\r\nPe prima linie a fişierului CERCURI.IN se află N (1<=N<=200). Pe urmatoarele N linii se află câte trei numere întregi sub forma xi yi si ri, reprezentând coordonatele centrului şi raza cercului i.Coordonatele sunt numere ântregi din intervalul [0, 10000]. Razele cercurilor sunt întregi din intervalul [1, 1000].\r\nDate de ieşire\r\nIn fişierul CERCURI.OUT se va afisa numărul de zone determinat de cercurile date.\r\nExemplu\r\nCERCURI.IN\r\n4\r\n90 110 50\r\n130 70 30\r\n155 45 15\r\n165 115 65\r\nCERCURI.OUT\r\n11\r\n[Algoritmus, Cercuri[6]]\r\nRezolvare:\r\nContraexemple rezolvare normala\r\nO rezolvare folosind geometria computaţională pare foarte grea, lucrurile simplificându-se mult daca abordam problema prin prisma unor noţiuni de teoria grafurilor.\r\nFiecare punct de intersectie va fi considerat un nod. Două noduri vor fi legate prin o muchie dacă există un cerc pe care sa se afle amândouă iar între ele să nu existe nici un alt punct de intersectie.\r\nAcum vom folosi identitatea lui Euler: prezentată în problema anterioară. În problema noastră nu trebuie să numărăm şi faţa exterioară, deci formula folosita va fi F=M-V+1. Această formulă este adevarată doar in cazul unei singure componente conexe. Pentru mai multe componente, formula devine F=M-V+C, unde C este numărul de componente conexe.\r\nO atenţie deosebită trebuie acordată punctelor de intersecţie prin care trec mai mult de două cercuri, pentru a nu le număra de mai multe ori. Putem rezolva aceasta problema prin sortarea punctelor de intersecţie ale unui cerc cu toate celelalte cercuri.\r\nDeasemenea, este necesara eliminarea cercurilor identice (cu acelaşi centru şi raze egale). Din orice mulţime cu astfel de cercuri este păstrat doar un singur element.\r\nDeoarece pentru fiecare cerc este necesara o sortare a punctelor de intersectie, complexitatea generala a algoritmului va fi O(N2*log(N))\r\n\r\nh2(#bio). Bibliografie\r\n[1]  A.M. Iaglom, I. M. Iaglom, Probleme neelementare tratate elementat. Ed tehnică, Bucureşti, 1962\r\n[2] I. Tomescu, Probleme de combinatorică şi teoria grafurilor, ed didactică şi pedagogică. Bucureşti, 1981\r\n[3] Colecţia Ginfo\r\n[4] acm.uva.es\r\n[5] ipsc.ksp.sk\r\n[6] algoritmus.org/index.php\r\n[7]http://www.research.att.com/~njas/sequences/\r\n[8]http://www.ics.uci.edu/~eppstein/junkyard/euler/\r\n',7668,'public',NULL,NULL),('grigore-moisil-2009/solutii/pari','grigore-moisil-2009/solutii/pari','2009-04-05 20:48:47','2009-04-05 20:48:47','h2(#pari). \'Pari\':problema/pari\r\n\r\nSoluţia acestei probleme se foloseşte de noţiuni elementare din teoria grafurilor. Pentru început, considerăm un graf $G$ format din mulţimea tuturor indicilor. Muchiile se vor construi între două noduri $(i, j)$ astfel încât resturile împărţirii la doi a celor două numere să fie diferite iar $cmmdc(i, j) &ge; d$. În continuare, considerăm că nodurile au două culori: alb pentru indicii care au paritate corespunzătoare şi negru pentru indicii care nu au paritatea corespunzătoare. Rezultă că dacă nodurile negre vor dispărea atunci vom găsi o soluţie. Ideea ce se conturează este ca din fiecare nod alb să parcurgem graful în lăţime sau adâncime adunând alternativ $+1$ şi $-1$ pe muchii, adică la numerele de pe poziţiile indicate de capetele muchiei, până când găsim un alt nod negru. Observăm astfel că pe acest lanţ, singurele noduri care îşi vor schimba culoarea vor fi doar nodul sursă şi nodul destinaţie.\r\n\r\nComplexitatea finală este $O(n * m)$, unde $n$ e numărul de elemente ale şirului $S$, iar $m$ numărul de perechi ce se pot forma.\r\n',3146,'public',NULL,NULL),('probleme-de-taietura','Probleme de Taietura','2009-04-06 05:48:04','2009-04-06 06:35:34','h1. Probleme de taietura\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"andrici_cezar\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n\r\n(toc){width: 25em}*{text-align:center} *Conţinut:*\r\n* \'Problema 1\':probleme-de-taietura#1\r\n* \'Problema 2\':probleme-de-taietura#2\r\n* \'Problema 3\':probleme-de-taietura#3\r\n* \'Problema 4\':probleme-de-taietura#4\r\n* \'Problema 5\':probleme-de-taietura#5\r\n* \'Problema 6\':probleme-de-taietura#6\r\n* \'Problema 7\':probleme-de-taietura#7\r\n* \'Problema 8\':probleme-de-taietura#8\r\n* \'Problema 9\':probleme-de-taietura#9\r\n* \'Problema 10\':probleme-de-taietura#10\r\n* \'Problema 11\':probleme-de-taietura#11\r\n* \'Problema 12\':probleme-de-taietura#12\r\n* \'Problema 13\':probleme-de-taietura#13\r\n* \'Bibliografie\':probleme-de-taietura#bio\r\n\r\n\r\n\r\nh2(#1). Problema 1:\r\n\r\nPentru un număr natural N dat, se cere numărul maxim de regiuni în care se poate împărţi planul folosind N drepte.\r\n!probleme-de-taietura?aaa.bmp!\r\n \r\nRezolvare:\r\nMai întâi facem vom face două observaţii:\r\nÎn configuraţia cu număr maxim de regiuni nu vom avea două drepte paralele, pentru că două drepte care se intersectează formează în plan patru regiuni, în timp ce două drepte paralele formează în plan doar trei regiuni.\r\nDe asemenea pentru a obţine un număr maxim de regiuni, nu vor exista trei drepte care să se intersecteze intr-un punct pentru că astfel am pierde o regiune triunghiulară formată din punctele de intersecţie ale celor trei drepte.\r\nDacă aceste două condiţii sunt îndeplinite vom vedea în continuare că orice configuraţie de N drepte împarte planul în acelaţi număr de regiuni. Notăm cu d(n) acest număr. Presupunem ca ştim pe d(n), să vedem acum ce se întâmplă dacă mai adaugăm o dreaptă. \r\nAceastă nouă dreaptă va fi intersectată de celelalte drepte în n puncte distincte. Fiecare segment de dreaptă şi semidreaptă în care este împărţită a n+1-a taie o regiune veche in două regiuni noi. De aici tragem concluzia că d(n+1) = d(n) + n + 1. Deci d(n) = n + n – 1 + n – 2 + … + 2 + d(1). Astfel folosind indentitatea 1 + 2 + 3 + … + n = n(n+1)/2 obţinem d(n) = n(n + 1) / 2 + 1.\r\nMenţionăm că problemele în care se cere maximizarea numărului de regiuni în care un pătrat, un triunghi sau un cerc este împărţit de n drepte, au aceiaşi soluţie.\r\n!probleme-de-taietura?aaaa.bmp!\r\n\r\nh2(#2). Problema 2:\r\n\r\nDându-se un număr natural N, se cere numărul maxim de regiuni în care N cercuri pot împărţi planul.\r\n!probleme-de-taietura?aaaaa.bmp!\r\nRezolvare:\r\nEste clar că oricare două cercuri trebuie să se intersecteze in exact două puncte, nu să fie tangente sau să nu se intersecteze deloc pentru că astfel am pierde o regiune, iar oricare trei cercuri nu se intersectează într-un punct.\r\nOrice configuraţie care satisface această cerinţă va împărţi planul într-un număr maxim de regiuni.Vom nota cu c(n) numărul maxim de regiuni în care este împărţit planul de n cercuri. Să vedem ce se întîmplă când adăugăm un nou cerc la această configuraţie. Cercul nou va fi intersectat de cele n cercuri în 2n puncte distincte, şi astfel va fi împărţit în 2n arce. Fiecare dintre aceste arce împarte o zonă veche în două zone noi. De aici tragem concluzia că c(n + 1) = 2n + c(n). Astfel putem să îl scriem pe c(n) ca 2(n – 1) + 2(n – 2) + … + 2 + c(1). De aici folosind din nou identitatea 1 + 2 + … + n = n(n+1)/2 avem că c(n) = n(n-1) + 2.\r\nEste evident că şi problema în care se cere maximizarea numărului de regiuni în care este împărţită suprafaţa unei sfere de n cercuri are aceiaşi soluţie.\r\n\r\nh2(#3). Problema 3:\r\n\r\nSe dau n cercuri care se intersectează oricare două în două puncte şi nu există trei care se intersectează într-un punct, se cere să se determine numărul de zone în care este împarţit planul de aceste n cercuri. ( n <= 10^100)\r\n[acm.uva.es 10519 !! Really Strange !!]\r\nRezolvare:\r\nObservăm ca sunt indeplinite condiţiile de maximalitate cerute mai sus, deci rezultatul e c(n), singura problema ce rămâne este aceea de implementare a operaţiilor cu numere mari.\r\n\r\nh2(#4). Problema 4:\r\n\r\nAvem un număr natural N, vrem să determinăm numărul maxim de regiuni în care poate fi împărţit un plan de elipse.\r\n \r\nRezolvare:\r\nLa fel ca şi la cercuri nici aici nu trebuie să avem elipse tangente, sau elipse care să nu se intersecteze, nu vor exista nici aici trei elipse care să se intersecteze într-un punct, aici elipsele trebuie să se intersecteze în patru puncte, dacă s-ar intersecta numai în două puncte atunci configuraţia nu ar avea număr maxim de regiuni.\r\nNotăm cu e(n) numărul de care suntem interesaţi. Câte regiuni noi apar cand adăugam o nouă elipsă? Păi o nouă elipsă va fi intersectată de celelalte elipse ăn patru puncte de fiecare, deci e(n + 1) = 4n + e(n). De aici tragem concluzia că e(n) = 2 n(n - 1) + 2.\r\n\r\nh2(#5). Problema 5:\r\n\r\nDându-se un număr natural N, se cere numărul maxim de regiuni în care N triunghiuri pot împărţi planul.\r\n \r\nRezolvare:\r\nRepetând raţionamentul de la problemele anterioareavem că t(n+1) = 6n + t(n) => t(n) = 3n(n-1) + 2. \r\n\r\nh2(#6). Problema 6:\r\n\r\nPentru N plane determinaţi numărul maxim de zone în care poate fi împărţit spaţiul cu acestea.\r\nRezolvare:\r\nÎn această problemă urmăm raţionamentul de până acum. Este evident că trebuie ca fiecare plan să se intersecteze cu fiecare, că oricare trei plane trebuie să nu se intersecteze într-o dreaptă, oricare trei plane nu trebuie să fie paralele cu o dreaptă şi oricare patru plane nu trebuie să se intersecteze într-un punct. Notăm p(n) numărul maxim de zone în care n plane împart spatiul. Când adaugăm un nou plan acesta va fi intersectat de celelalte plane în n drepte, drepte care după restrictiile care le-am pus nu vor fi două paralele sau trei care să se intersecteze într-un punct. Acest plan va fi împărţit în d(n)  regiuni de aceste drepte din cauza restricţiilor impuse. Fiecare regiune din plan taie o zonă din spaţiu în două noi zone, de aici tragem concluzia că p(n + 1) = d(n) + p(n). Astfel avem p(n) =  n(n-1)/2 + 1 + (n-1)(n-2)/2 + 1 + … +  2 * 1 / 2 + 1 + p(1) = ( n^2 – n + (n-1)^2 – (n-1) + … + 2^2 – 2  +  1 – 1 + (n – 1) )/2 + 2 = ( n(n+1)(2n + 1)/6 – n(n+1)/2 + (n-1))/2 + 2  = (n^3/3 + n^2/2 + n/6 – n^2/2 – n/2 )/2 + n + 1 = n^3 / 6 + 5n/6 + 1. Am folosit identităţile 1 + 2 + … + n = n(n+1)/2 şi 1 + 2^2 + 3^2 + … + n^2 = n(n+1)(2n+1)/6 care se pot demonstra uşor prin inducţie.\r\nMenţionăm că dacă vrem să împărţim un cub, un cilindru o sfera etc în număr maxim de regiuni folosind n plane, formula se păstrează.\r\n\r\nh2(#7). Problema 7:\r\n\r\nDându-se un număr natural N, să se determine numărul maxim de zone în care pot împărţi spaţiul N sfere.\r\n[Bursele Agora 2001[3]]\r\nRezolvare:\r\nPornim la fel ca la problema anterioară, oricare două sfere se vor intersecta şi nu vor exista trei sfere care să se intersecteze în acelaşi punct. Vom nota cu s(n) numărul maxim de regiuni în care poate fi împărţit spaţiul cu n sfere. Să vedem ce se întâmplă când adăugăm o sferă. Această sferă va fi intersectată de toate celelalte n sfere în n cercuri, pentru ca numărul de regiuni noi să fie maxim aceste cercuri vor împărţi sfera într-un număr maxim de regiuni, acest număr este c(n) aşa cum am discutat la problema 2. Obţinem astfel s(n + 1) = c(n) + s(n) = c(n) + c(n-1) + ... + c(1) = n(n-1) + 2 + (n-1)(n-2) + 2 + ... + 2 = 1 + 2^2 + .. + n^2 – 1 – 2 – 3 - .... – n + 2n => s(n) = n(n^2 – 3n + 8) / 3\r\n\r\nh2(#8). Problema 8:\r\n\r\nSe dă un număr N care este numărul maxim în care poate fi împărţit planul de m elipse, n cercuri şi p triunghiuri. Se cere ştiind N să se determine toate valorile posibile pentru m, n şi p. (N întreg făra semn reprezentabil pe 32 de biţi, 0<=m<100, 0<=n<20000 şi 0<=p<100)\r\n[10623 Thinking Backward [4]]\r\nRezolvare:\r\nDacă am ştii pentru trei parametrii m, n şi p care este numarul maxim de părţi în care poate fi împărţit planul  de m elipse, n cercuri şi p triunghiuri, atunci am putea incerca toate posibilitaţile pentru m, n şi p şi am găsi tripletele pentru rezultatul ar fie gal cu N, chiar am putea optimiza puţin acest algoritm iteram pe toate valorile de m şi p, astfel vom obţine o ecuaţie cu necunoscuta n astfel vom face doar 10000 de rezolvări de ecuaţii în loc de 200 000 000 de comparaţii. \r\nSă vedem cum găsim numărul maxim de zone. Din nou oricare două figuri se intersectează în număr maxim de intersecţii, un cerc cu o elipsă în patru puncte, un cerc sau o elipsă cu un triunghi în şase puncte. Mai întâi punem cele m elipse in plan, ele vor împărţi planul în e(m) regiuni adică 2 m(m - 1) + 2. După aceea adaugăm cercurile. Să notam numarul maxim de zone în care n cercuri şi m elipse pot împărţi planul cu ec(m , n). Dacă ştim cât este e(m, n-1) atunci când adaugăm un nou cerc, acesta va fi intersectat de m elipse in 4m puncte şi de n-1 cercuri in 2(n – 1) puncte deci cercul va fi împărţit în 4m + 2(n-1) arce care vor împărţi tot atâtea regiuni care existau deja in câte două regiuni noi. Deci ec(m, n) = 4m + 2(n-1) + ec(m, n-1) = 4m + 2(n-1) + 4m + 2(n-2) + … + 4m + 2 + ec(m, 0) = 4m(n-1) + n (n-1) + 2m(m-1) + 2. Să vedem ce se întâmplă când adăugăm triunghiurile. Vom nota ect(m, n, p) numărul maxim de zone în care poate fi împărţit planul de m elipse, n cercuri şi p triunghiuri. Dacă ştim cu cat e egal ect(m, n, p - 1) , atunci când vom adăuga un nou triunghi acesta va intersecta cele m cercuri în 6m puncte, cele n elipse în 6n puncte şi cele p – 1 triunghiuri în 6(p – 1) puncte, astfel se vor forma 6m + 6n + 6(p-1) noi zone. Deci ect(m, n, p) = 6(m + n + p – 1) + ect(m, n, p – 1) = 6 (m + n + p – 1 + m + n + p – 2 + … m + n + 1) + ect(n, m, 0) = 6 (p-1)(m+n) + 3p(p-1) + 4m(n-1) + n(n-1) + 2m(m-1) + 2.\r\n\r\nProblemele anterioare au fost cam matematice şi ele sunt numite de obicei de olimpici peiorativ ca “probleme de formulă”, majoritatea olimpicilor la informatică participă aici pentru că matematica nu le place aşa tare şi deci nici apariţia unor probleme ca cele de mai sus care sunt mai mult de mate decât de info nu îi prea încântă. Cum poate fi rezolvată o problemă de formulă fără să avem intuiţia matematică sau cunoţinţele matematice necesare? Păi câteodată elevii apelează la următorul truc: află primele câteva valori de mâna sau cu ajutorul unor algoritmi brute force şi apoi speră ca formula să fie de o anumită formă, de exemplu ar putea fi un polinom de un grad mic. Atunci avem ca f(N) = An^3 + Bn^2 + Cn + D. Afland primele câteva valori vom ştii valorile f(1), f(2), f(3), f(4). Dând lui n pe rand valorile 1, 2, 3 şi 4 putem face un sistem cu necunoscutele A, B, C şi D. Sau putem încerca să vedem cum se comportă şirul de numere, are o creştere polinomială sau exponenţială, apar valorile lui în triunghiul lui Pascal. Iar dacă rezolvăm problemele de acasă putem căuta valorile din şirul de soluţii pe internet pe pagina Eciclopedia Online a şirurilor de întregi [7] care este o resursă foarte utilă în cazul problemelor de acest gen .\r\n\r\nh2(#9). Problema 9:\r\n\r\nSe dau N drepte în plan, fiecare dreaptă este dată prin două puncte prin care trece. Se cere să se determine pentru această configuraţie în câte zone este împărţit planul. (n <= 1000)\r\n[Internet Problem Solving Contest 2000 [5]]\r\nRezolvare:\r\nÎn sfârşit o problemă în care avem nevoie să folosim calculatorul şi talentul nostru de programatori . Vom folosi aceeaşi idee ce a apărut şi în celelalte probleme, adică numărăm pe rând în câte zone este împărţit planul de primele o dreaptă, doua drepte respectiv n drepte. Deci vom adăuga în ordine dreptele la configuraţia noastră. Când adăugăm o dreaptă ea va fi intersectată de dreptele deja adăugate în k puncte nu neapărat distincte, pe noi ne intereseaza punctele distincte, ca să facem acest lucru putem sorta punctele în O(k log k) sau să folosim o tabelă de dispersie şi astfel să aflăm în O(k) numărul de puncte distincte, daca acest număr e egal cu L atunci la numărul curent de zone vom adăuga L. Astfel algoritmul are complexitatea O(n^2 log n), sau dacă folosim tabele de dispersie O(n^2).\r\n\r\nh2(#10). Problema 10:\r\n\r\nAvem un tort în formă de pătrat de dimensiune 1000 x 1000. Folosim un cuţit pentru a tăoa tortul. Întrebarea este după o serie de tăieturi, în căte bucăţi am patriţionat tortul. Restricţii: Numărul de tăieturi nu va fi mai mare de 8. După tăieturi, lungimea oricărei laturi a partiţiei nu va fi mai mică decât unu. Coordonatele vârfurilor tortului vor fi (0,0)(0,1000)(1000,1000) (1000,0). Tăieturile se vor intersecta în două puncte cu marginile tortului. Următoarea imagine e un tort tăiat în zece bucăţi.\r\n[acm.uva.es 527 The partition of a cake]\r\nRezolvarea este analoaga cu cea a problemei anterioare, datele sunt foarte mici în problema aceasta, probabil că autorii au vrut să facă problema accesibilă şi altor idei care folosesc împărţiri efective în poligoane a pătratului.\r\n\r\nh2(#11). Problema 11:\r\n\r\nSe dă un graf planar prin noduri şi muchii, un graf este planar dacă există o modalitate de a îl desena în plan făra ca muchiile să se intersecteze decăt la capete. Se cere să se determine în căte regiuni împarte planul graful dat la intrare. Mai jos avem un exemplu de graf în care feţele sunt numerotate.\r\n[10178 Count the faces [4]]\r\n\r\nRezolvare:\r\nEste interesant faptul că în această problemă nu ne este dată configuraţia în plan a grafului ci doar structura lui. Un graf il putem reprezenta în mai multe moduri în plan, astfel suntem duşi înspre ideea că există ceva formulă care rezolvă problema. O formulă întradevăr există şi se numeşte formula lui Euler pentru grafurile planare. Formula arată aşa f - m + n  = 2, unde prin f am notat numărul de feţe, m numărul de muchii şi n numărul de vârfuri., dacă graful nostru e conex (formula include faţa exterioară). Această formulă poate fi demonstrată în foarte multe moduri. Dacă vreţi să vedeţi 19 metode de demonstrare puteţi să vizitaţi adresa [8]. O demonstraţie simplă ar fi prin inducţie pornind de la un arbore şi adăugând pe rând câte o muchie. La început avem o singură faţă, cea infinită, 1 – (n – 1) + n = 2 se verifică. Fiecare muchie adăugată împarte o faţă în două deci dacă aveam inainte f – m + n = 2 acum vom avea f1 – m1 + n = 2 unde f1 = f + 1 şi m1 = m + 1. Deci am demonstrate formula şi putem foarte uşor să rezolvăm problema, mai trebuie numai să avem grijă ca pentru fiecare componentă conexă număram faţa infinită.\r\nAceastă formulă este adevarată şi în spaţiu pentru poliedre.\r\n\r\nh2(#12). Problema 12:\r\n\r\nSe considera N cercuri in plan. Se cere să se determine numărul de zone finite în care cercurile date împart planul.\r\n \r\nDate de intrare\r\nPe prima linie a fişierului CERCURI.IN se află N (1<=N<=200). Pe urmatoarele N linii se află câte trei numere întregi sub forma xi yi si ri, reprezentând coordonatele centrului şi raza cercului i.Coordonatele sunt numere ântregi din intervalul [0, 10000]. Razele cercurilor sunt întregi din intervalul [1, 1000].\r\nDate de ieşire\r\nIn fişierul CERCURI.OUT se va afisa numărul de zone determinat de cercurile date.\r\nExemplu\r\nCERCURI.IN\r\n4\r\n90 110 50\r\n130 70 30\r\n155 45 15\r\n165 115 65\r\nCERCURI.OUT\r\n11\r\n[Algoritmus, Cercuri[6]]\r\nRezolvare:\r\nContraexemple rezolvare normala\r\nO rezolvare folosind geometria computaţională pare foarte grea, lucrurile simplificându-se mult daca abordam problema prin prisma unor noţiuni de teoria grafurilor.\r\nFiecare punct de intersectie va fi considerat un nod. Două noduri vor fi legate prin o muchie dacă există un cerc pe care sa se afle amândouă iar între ele să nu existe nici un alt punct de intersectie.\r\nAcum vom folosi identitatea lui Euler: prezentată în problema anterioară. În problema noastră nu trebuie să numărăm şi faţa exterioară, deci formula folosita va fi F=M-V+1. Această formulă este adevarată doar in cazul unei singure componente conexe. Pentru mai multe componente, formula devine F=M-V+C, unde C este numărul de componente conexe.\r\nO atenţie deosebită trebuie acordată punctelor de intersecţie prin care trec mai mult de două cercuri, pentru a nu le număra de mai multe ori. Putem rezolva aceasta problema prin sortarea punctelor de intersecţie ale unui cerc cu toate celelalte cercuri.\r\nDeasemenea, este necesara eliminarea cercurilor identice (cu acelaşi centru şi raze egale). Din orice mulţime cu astfel de cercuri este păstrat doar un singur element.\r\nDeoarece pentru fiecare cerc este necesara o sortare a punctelor de intersectie, complexitatea generala a algoritmului va fi O(N2*log(N))\r\n\r\nh2(#bio). Bibliografie:\r\n\r\n[1]  A.M. Iaglom, I. M. Iaglom, Probleme neelementare tratate elementat. Ed tehnică, Bucureşti, 1962\r\n[2] I. Tomescu, Probleme de combinatorică şi teoria grafurilor, ed didactică şi pedagogică. Bucureşti, 1981\r\n[3] Colecţia Ginfo\r\n[4] acm.uva.es\r\n[5] ipsc.ksp.sk\r\n[6] algoritmus.org/index.php\r\n[7]http://www.research.att.com/~njas/sequences/\r\n[8]http://www.ics.uci.edu/~eppstein/junkyard/euler/\r\n',7668,'public',NULL,NULL),('probleme-de-taietura','Probleme de Taietura','2009-04-06 05:48:04','2009-04-06 06:41:10','h1. Probleme de taietura\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"andrici_cezar\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n\r\n(toc){width: 25em}*{text-align:center} *Conţinut:*\r\n* \'Problema 1\':probleme-de-taietura#1\r\n* \'Problema 2\':probleme-de-taietura#2\r\n* \'Problema 3\':probleme-de-taietura#3\r\n* \'Problema 4\':probleme-de-taietura#4\r\n* \'Problema 5\':probleme-de-taietura#5\r\n* \'Problema 6\':probleme-de-taietura#6\r\n* \'Problema 7\':probleme-de-taietura#7\r\n* \'Problema 8\':probleme-de-taietura#8\r\n* \'Problema 9\':probleme-de-taietura#9\r\n* \'Problema 10\':probleme-de-taietura#10\r\n* \'Problema 11\':probleme-de-taietura#11\r\n* \'Problema 12\':probleme-de-taietura#12\r\n* \'Problema 13\':probleme-de-taietura#13\r\n* \'Bibliografie\':probleme-de-taietura#bio\r\n\r\n\r\n\r\nh2(#1). Problema 1:\r\n\r\nPentru un număr natural N dat, se cere numărul maxim de regiuni în care se poate împărţi planul folosind N drepte.\r\n!probleme-de-taietura?aaa.bmp!\r\n \r\nRezolvare:\r\nMai întâi facem vom face două observaţii:\r\nÎn configuraţia cu număr maxim de regiuni nu vom avea două drepte paralele, pentru că două drepte care se intersectează formează în plan patru regiuni, în timp ce două drepte paralele formează în plan doar trei regiuni.\r\nDe asemenea pentru a obţine un număr maxim de regiuni, nu vor exista trei drepte care să se intersecteze intr-un punct pentru că astfel am pierde o regiune triunghiulară formată din punctele de intersecţie ale celor trei drepte.\r\nDacă aceste două condiţii sunt îndeplinite vom vedea în continuare că orice configuraţie de N drepte împarte planul în acelaţi număr de regiuni. Notăm cu d(n) acest număr. Presupunem ca ştim pe d(n), să vedem acum ce se întâmplă dacă mai adaugăm o dreaptă. \r\nAceastă nouă dreaptă va fi intersectată de celelalte drepte în n puncte distincte. Fiecare segment de dreaptă şi semidreaptă în care este împărţită a n+1-a taie o regiune veche in două regiuni noi. De aici tragem concluzia că d(n+1) = d(n) + n + 1. Deci d(n) = n + n – 1 + n – 2 + … + 2 + d(1). Astfel folosind indentitatea 1 + 2 + 3 + … + n = n(n+1)/2 obţinem d(n) = n(n + 1) / 2 + 1.\r\nMenţionăm că problemele în care se cere maximizarea numărului de regiuni în care un pătrat, un triunghi sau un cerc este împărţit de n drepte, au aceiaşi soluţie.\r\n!probleme-de-taietura?aaaa.bmp!\r\n\r\nh2(#2). Problema 2:\r\n\r\nDându-se un număr natural N, se cere numărul maxim de regiuni în care N cercuri pot împărţi planul.\r\n!probleme-de-taietura?aaaaa.bmp!\r\n\r\nRezolvare:\r\nEste clar că oricare două cercuri trebuie să se intersecteze in exact două puncte, nu să fie tangente sau să nu se intersecteze deloc pentru că astfel am pierde o regiune, iar oricare trei cercuri nu se intersectează într-un punct.\r\nOrice configuraţie care satisface această cerinţă va împărţi planul într-un număr maxim de regiuni.Vom nota cu c(n) numărul maxim de regiuni în care este împărţit planul de n cercuri. Să vedem ce se întîmplă când adăugăm un nou cerc la această configuraţie. Cercul nou va fi intersectat de cele n cercuri în 2n puncte distincte, şi astfel va fi împărţit în 2n arce. Fiecare dintre aceste arce împarte o zonă veche în două zone noi. De aici tragem concluzia că c(n + 1) = 2n + c(n). Astfel putem să îl scriem pe c(n) ca 2(n – 1) + 2(n – 2) + … + 2 + c(1). De aici folosind din nou identitatea 1 + 2 + … + n = n(n+1)/2 avem că c(n) = n(n-1) + 2.\r\nEste evident că şi problema în care se cere maximizarea numărului de regiuni în care este împărţită suprafaţa unei sfere de n cercuri are aceiaşi soluţie.\r\n!probleme-de-taietura?aaaaaa.bmp!\r\n\r\nh2(#3). Problema 3:\r\n\r\nSe dau n cercuri care se intersectează oricare două în două puncte şi nu există trei care se intersectează într-un punct, se cere să se determine numărul de zone în care este împarţit planul de aceste n cercuri. ( n <= 10^100)\r\n[acm.uva.es 10519 !! Really Strange !!]\r\n\r\nRezolvare:\r\nObservăm ca sunt indeplinite condiţiile de maximalitate cerute mai sus, deci rezultatul e c(n), singura problema ce rămâne este aceea de implementare a operaţiilor cu numere mari.\r\n\r\nh2(#4). Problema 4:\r\n\r\nAvem un număr natural N, vrem să determinăm numărul maxim de regiuni în care poate fi împărţit un plan de elipse.\r\n\r\n!probleme-de-taietura?aaaaaaa.bmp!\r\n\r\nRezolvare:\r\nLa fel ca şi la cercuri nici aici nu trebuie să avem elipse tangente, sau elipse care să nu se intersecteze, nu vor exista nici aici trei elipse care să se intersecteze într-un punct, aici elipsele trebuie să se intersecteze în patru puncte, dacă s-ar intersecta numai în două puncte atunci configuraţia nu ar avea număr maxim de regiuni.\r\nNotăm cu e(n) numărul de care suntem interesaţi. Câte regiuni noi apar cand adăugam o nouă elipsă? Păi o nouă elipsă va fi intersectată de celelalte elipse ăn patru puncte de fiecare, deci e(n + 1) = 4n + e(n). De aici tragem concluzia că e(n) = 2 n(n - 1) + 2.\r\n\r\n!probleme-de-taietura?aaaaaaaa.bmp!\r\n\r\nh2(#5). Problema 5:\r\n\r\nDându-se un număr natural N, se cere numărul maxim de regiuni în care N triunghiuri pot împărţi planul.\r\n !probleme-de-taietura?aaaaaaaaa.bmp!\r\n\r\nRezolvare:\r\nRepetând raţionamentul de la problemele anterioareavem că t(n+1) = 6n + t(n) => t(n) = 3n(n-1) + 2. \r\n!probleme-de-taietura?aaaaaaaaaa.bmp!\r\n\r\nh2(#6). Problema 6:\r\n\r\nPentru N plane determinaţi numărul maxim de zone în care poate fi împărţit spaţiul cu acestea.\r\nRezolvare:\r\nÎn această problemă urmăm raţionamentul de până acum. Este evident că trebuie ca fiecare plan să se intersecteze cu fiecare, că oricare trei plane trebuie să nu se intersecteze într-o dreaptă, oricare trei plane nu trebuie să fie paralele cu o dreaptă şi oricare patru plane nu trebuie să se intersecteze într-un punct. Notăm p(n) numărul maxim de zone în care n plane împart spatiul. Când adaugăm un nou plan acesta va fi intersectat de celelalte plane în n drepte, drepte care după restrictiile care le-am pus nu vor fi două paralele sau trei care să se intersecteze într-un punct. Acest plan va fi împărţit în d(n)  regiuni de aceste drepte din cauza restricţiilor impuse. Fiecare regiune din plan taie o zonă din spaţiu în două noi zone, de aici tragem concluzia că p(n + 1) = d(n) + p(n). Astfel avem p(n) =  n(n-1)/2 + 1 + (n-1)(n-2)/2 + 1 + … +  2 * 1 / 2 + 1 + p(1) = ( n^2 – n + (n-1)^2 – (n-1) + … + 2^2 – 2  +  1 – 1 + (n – 1) )/2 + 2 = ( n(n+1)(2n + 1)/6 – n(n+1)/2 + (n-1))/2 + 2  = (n^3/3 + n^2/2 + n/6 – n^2/2 – n/2 )/2 + n + 1 = n^3 / 6 + 5n/6 + 1. Am folosit identităţile 1 + 2 + … + n = n(n+1)/2 şi 1 + 2^2 + 3^2 + … + n^2 = n(n+1)(2n+1)/6 care se pot demonstra uşor prin inducţie.\r\nMenţionăm că dacă vrem să împărţim un cub, un cilindru o sfera etc în număr maxim de regiuni folosind n plane, formula se păstrează.\r\n\r\nh2(#7). Problema 7:\r\n\r\nDându-se un număr natural N, să se determine numărul maxim de zone în care pot împărţi spaţiul N sfere.\r\n[Bursele Agora 2001[3]]\r\nRezolvare:\r\nPornim la fel ca la problema anterioară, oricare două sfere se vor intersecta şi nu vor exista trei sfere care să se intersecteze în acelaşi punct. Vom nota cu s(n) numărul maxim de regiuni în care poate fi împărţit spaţiul cu n sfere. Să vedem ce se întâmplă când adăugăm o sferă. Această sferă va fi intersectată de toate celelalte n sfere în n cercuri, pentru ca numărul de regiuni noi să fie maxim aceste cercuri vor împărţi sfera într-un număr maxim de regiuni, acest număr este c(n) aşa cum am discutat la problema 2. Obţinem astfel s(n + 1) = c(n) + s(n) = c(n) + c(n-1) + ... + c(1) = n(n-1) + 2 + (n-1)(n-2) + 2 + ... + 2 = 1 + 2^2 + .. + n^2 – 1 – 2 – 3 - .... – n + 2n => s(n) = n(n^2 – 3n + 8) / 3\r\n\r\nh2(#8). Problema 8:\r\n\r\nSe dă un număr N care este numărul maxim în care poate fi împărţit planul de m elipse, n cercuri şi p triunghiuri. Se cere ştiind N să se determine toate valorile posibile pentru m, n şi p. (N întreg făra semn reprezentabil pe 32 de biţi, 0<=m<100, 0<=n<20000 şi 0<=p<100)\r\n[10623 Thinking Backward [4]]\r\nRezolvare:\r\nDacă am ştii pentru trei parametrii m, n şi p care este numarul maxim de părţi în care poate fi împărţit planul  de m elipse, n cercuri şi p triunghiuri, atunci am putea incerca toate posibilitaţile pentru m, n şi p şi am găsi tripletele pentru rezultatul ar fie gal cu N, chiar am putea optimiza puţin acest algoritm iteram pe toate valorile de m şi p, astfel vom obţine o ecuaţie cu necunoscuta n astfel vom face doar 10000 de rezolvări de ecuaţii în loc de 200 000 000 de comparaţii. \r\nSă vedem cum găsim numărul maxim de zone. Din nou oricare două figuri se intersectează în număr maxim de intersecţii, un cerc cu o elipsă în patru puncte, un cerc sau o elipsă cu un triunghi în şase puncte. Mai întâi punem cele m elipse in plan, ele vor împărţi planul în e(m) regiuni adică 2 m(m - 1) + 2. După aceea adaugăm cercurile. Să notam numarul maxim de zone în care n cercuri şi m elipse pot împărţi planul cu ec(m , n). Dacă ştim cât este e(m, n-1) atunci când adaugăm un nou cerc, acesta va fi intersectat de m elipse in 4m puncte şi de n-1 cercuri in 2(n – 1) puncte deci cercul va fi împărţit în 4m + 2(n-1) arce care vor împărţi tot atâtea regiuni care existau deja in câte două regiuni noi. Deci ec(m, n) = 4m + 2(n-1) + ec(m, n-1) = 4m + 2(n-1) + 4m + 2(n-2) + … + 4m + 2 + ec(m, 0) = 4m(n-1) + n (n-1) + 2m(m-1) + 2. Să vedem ce se întâmplă când adăugăm triunghiurile. Vom nota ect(m, n, p) numărul maxim de zone în care poate fi împărţit planul de m elipse, n cercuri şi p triunghiuri. Dacă ştim cu cat e egal ect(m, n, p - 1) , atunci când vom adăuga un nou triunghi acesta va intersecta cele m cercuri în 6m puncte, cele n elipse în 6n puncte şi cele p – 1 triunghiuri în 6(p – 1) puncte, astfel se vor forma 6m + 6n + 6(p-1) noi zone. Deci ect(m, n, p) = 6(m + n + p – 1) + ect(m, n, p – 1) = 6 (m + n + p – 1 + m + n + p – 2 + … m + n + 1) + ect(n, m, 0) = 6 (p-1)(m+n) + 3p(p-1) + 4m(n-1) + n(n-1) + 2m(m-1) + 2.\r\n\r\nProblemele anterioare au fost cam matematice şi ele sunt numite de obicei de olimpici peiorativ ca “probleme de formulă”, majoritatea olimpicilor la informatică participă aici pentru că matematica nu le place aşa tare şi deci nici apariţia unor probleme ca cele de mai sus care sunt mai mult de mate decât de info nu îi prea încântă. Cum poate fi rezolvată o problemă de formulă fără să avem intuiţia matematică sau cunoţinţele matematice necesare? Păi câteodată elevii apelează la următorul truc: află primele câteva valori de mâna sau cu ajutorul unor algoritmi brute force şi apoi speră ca formula să fie de o anumită formă, de exemplu ar putea fi un polinom de un grad mic. Atunci avem ca f(N) = An^3 + Bn^2 + Cn + D. Afland primele câteva valori vom ştii valorile f(1), f(2), f(3), f(4). Dând lui n pe rand valorile 1, 2, 3 şi 4 putem face un sistem cu necunoscutele A, B, C şi D. Sau putem încerca să vedem cum se comportă şirul de numere, are o creştere polinomială sau exponenţială, apar valorile lui în triunghiul lui Pascal. Iar dacă rezolvăm problemele de acasă putem căuta valorile din şirul de soluţii pe internet pe pagina Eciclopedia Online a şirurilor de întregi [7] care este o resursă foarte utilă în cazul problemelor de acest gen .\r\n\r\nh2(#9). Problema 9:\r\n\r\nSe dau N drepte în plan, fiecare dreaptă este dată prin două puncte prin care trece. Se cere să se determine pentru această configuraţie în câte zone este împărţit planul. (n <= 1000)\r\n[Internet Problem Solving Contest 2000 [5]]\r\nRezolvare:\r\nÎn sfârşit o problemă în care avem nevoie să folosim calculatorul şi talentul nostru de programatori . Vom folosi aceeaşi idee ce a apărut şi în celelalte probleme, adică numărăm pe rând în câte zone este împărţit planul de primele o dreaptă, doua drepte respectiv n drepte. Deci vom adăuga în ordine dreptele la configuraţia noastră. Când adăugăm o dreaptă ea va fi intersectată de dreptele deja adăugate în k puncte nu neapărat distincte, pe noi ne intereseaza punctele distincte, ca să facem acest lucru putem sorta punctele în O(k log k) sau să folosim o tabelă de dispersie şi astfel să aflăm în O(k) numărul de puncte distincte, daca acest număr e egal cu L atunci la numărul curent de zone vom adăuga L. Astfel algoritmul are complexitatea O(n^2 log n), sau dacă folosim tabele de dispersie O(n^2).\r\n\r\nh2(#10). Problema 10:\r\n\r\n!probleme-de-taietura?aaaaaaaaaaa.bmp!\r\n\r\nAvem un tort în formă de pătrat de dimensiune 1000 x 1000. Folosim un cuţit pentru a tăoa tortul. Întrebarea este după o serie de tăieturi, în căte bucăţi am patriţionat tortul. Restricţii: Numărul de tăieturi nu va fi mai mare de 8. După tăieturi, lungimea oricărei laturi a partiţiei nu va fi mai mică decât unu. Coordonatele vârfurilor tortului vor fi (0,0)(0,1000)(1000,1000) (1000,0). Tăieturile se vor intersecta în două puncte cu marginile tortului. Următoarea imagine e un tort tăiat în zece bucăţi.\r\n[acm.uva.es 527 The partition of a cake]\r\nRezolvarea este analoaga cu cea a problemei anterioare, datele sunt foarte mici în problema aceasta, probabil că autorii au vrut să facă problema accesibilă şi altor idei care folosesc împărţiri efective în poligoane a pătratului.\r\n\r\nh2(#11). Problema 11:\r\n\r\n!probleme-de-taietura?aaaaaaaaaaaa.bmp!\r\n\r\nSe dă un graf planar prin noduri şi muchii, un graf este planar dacă există o modalitate de a îl desena în plan făra ca muchiile să se intersecteze decăt la capete. Se cere să se determine în căte regiuni împarte planul graful dat la intrare. Mai jos avem un exemplu de graf în care feţele sunt numerotate.\r\n[10178 Count the faces [4]]\r\n\r\nRezolvare:\r\nEste interesant faptul că în această problemă nu ne este dată configuraţia în plan a grafului ci doar structura lui. Un graf il putem reprezenta în mai multe moduri în plan, astfel suntem duşi înspre ideea că există ceva formulă care rezolvă problema. O formulă întradevăr există şi se numeşte formula lui Euler pentru grafurile planare. Formula arată aşa f - m + n  = 2, unde prin f am notat numărul de feţe, m numărul de muchii şi n numărul de vârfuri., dacă graful nostru e conex (formula include faţa exterioară). Această formulă poate fi demonstrată în foarte multe moduri. Dacă vreţi să vedeţi 19 metode de demonstrare puteţi să vizitaţi adresa [8]. O demonstraţie simplă ar fi prin inducţie pornind de la un arbore şi adăugând pe rând câte o muchie. La început avem o singură faţă, cea infinită, 1 – (n – 1) + n = 2 se verifică. Fiecare muchie adăugată împarte o faţă în două deci dacă aveam inainte f – m + n = 2 acum vom avea f1 – m1 + n = 2 unde f1 = f + 1 şi m1 = m + 1. Deci am demonstrate formula şi putem foarte uşor să rezolvăm problema, mai trebuie numai să avem grijă ca pentru fiecare componentă conexă număram faţa infinită.\r\nAceastă formulă este adevarată şi în spaţiu pentru poliedre.\r\n\r\nh2(#12). Problema 12:\r\n\r\n!probleme-de-taietura?aaaaaaaaaaaaa.bmp!\r\n\r\nSe considera N cercuri in plan. Se cere să se determine numărul de zone finite în care cercurile date împart planul.\r\n \r\nDate de intrare\r\nPe prima linie a fişierului CERCURI.IN se află N (1<=N<=200). Pe urmatoarele N linii se află câte trei numere întregi sub forma xi yi si ri, reprezentând coordonatele centrului şi raza cercului i.Coordonatele sunt numere ântregi din intervalul [0, 10000]. Razele cercurilor sunt întregi din intervalul [1, 1000].\r\nDate de ieşire\r\nIn fişierul CERCURI.OUT se va afisa numărul de zone determinat de cercurile date.\r\nExemplu\r\nCERCURI.IN\r\n4\r\n90 110 50\r\n130 70 30\r\n155 45 15\r\n165 115 65\r\nCERCURI.OUT\r\n11\r\n[Algoritmus, Cercuri[6]]\r\nRezolvare:\r\nContraexemple rezolvare normala\r\nO rezolvare folosind geometria computaţională pare foarte grea, lucrurile simplificându-se mult daca abordam problema prin prisma unor noţiuni de teoria grafurilor.\r\nFiecare punct de intersectie va fi considerat un nod. Două noduri vor fi legate prin o muchie dacă există un cerc pe care sa se afle amândouă iar între ele să nu existe nici un alt punct de intersectie.\r\nAcum vom folosi identitatea lui Euler: prezentată în problema anterioară. În problema noastră nu trebuie să numărăm şi faţa exterioară, deci formula folosita va fi F=M-V+1. Această formulă este adevarată doar in cazul unei singure componente conexe. Pentru mai multe componente, formula devine F=M-V+C, unde C este numărul de componente conexe.\r\nO atenţie deosebită trebuie acordată punctelor de intersecţie prin care trec mai mult de două cercuri, pentru a nu le număra de mai multe ori. Putem rezolva aceasta problema prin sortarea punctelor de intersecţie ale unui cerc cu toate celelalte cercuri.\r\nDeasemenea, este necesara eliminarea cercurilor identice (cu acelaşi centru şi raze egale). Din orice mulţime cu astfel de cercuri este păstrat doar un singur element.\r\nDeoarece pentru fiecare cerc este necesara o sortare a punctelor de intersectie, complexitatea generala a algoritmului va fi O(N2*log(N))\r\n\r\nh2(#bio). Bibliografie:\r\n\r\n[1]  A.M. Iaglom, I. M. Iaglom, Probleme neelementare tratate elementat. Ed tehnică, Bucureşti, 1962\r\n[2] I. Tomescu, Probleme de combinatorică şi teoria grafurilor, ed didactică şi pedagogică. Bucureşti, 1981\r\n[3] Colecţia Ginfo\r\n[4] acm.uva.es\r\n[5] ipsc.ksp.sk\r\n[6] algoritmus.org/index.php\r\n[7]http://www.research.att.com/~njas/sequences/\r\n[8]http://www.ics.uci.edu/~eppstein/junkyard/euler/\r\n',7668,'public',NULL,NULL),('implica-te/scrie-articole','Scrie articole','2007-03-28 22:23:46','2009-03-29 20:43:14','h1. Scrie articole ==Stars(rating=\"4\")==\r\n\r\nFolosind modelul de \'wiki\':documentatie/wiki, infoarena ofera sansa tuturor membrilor sai sa contribuie la realizarea de articole sau la imbunatatirea celor existente. Daca vrei sa afli mai multe despre conceptul de wiki intra \'aici\':http://en.wikipedia.org/wiki/Wiki, iar daca vrei sa contribui la acesta initiativa citeste mai jos ce trebuie sa faci.\r\n\r\nh2. De ce m-as baga?\r\n\r\n* O cariera in cercetare in informatica poate debuta cu niste articole online!\r\n* Vei invata care sunt elementele cheie pentru a scrie un articol.\r\n* Vei invata pe altii ceea ce stii, asa cum probabil si tu ai invatat din articolele deja \'existente\':articole.\r\n\r\nh2. Ce pot sa fac?\r\n\r\nDe-a lungul timpului, utilizatorii infoarena si-au manifestat interesul in a scrie articole pentru intreaga comunitate. In momentul de fata ne concentram eforturile atat pe completarea si aducerea la o forma prezentabila a acestor articole vechi, cat si pe scrierea de articole noi. Sunt 3 moduri in care poti contribui:\r\n\r\nh3. 1. Ajuta-ne la ce lucram acum\r\n\r\nIn tabelul de mai jos poti gasi articolele incepute, impreuna cu stadiul in care se gaseste fiecare. Daca esti dornic sa ne ajuti, alege-ti unul din articolele de care nu se ocupa nimeni si ia legatura cu coordonatorul proiectului ca sa afli ce mai e de facut la el.\r\n\r\ntable. |_. Titlu |_. Autor |_. Stadiu |_. Voluntar(i) |\r\n| \'Flux si cuplaj\':flux-si-cuplaj | ==user(user=\"blasterz\" type=\"tiny\")== | IN LUCRU | ==user(user=\"blasterz\" type=\"tiny\")== |\r\n| \'Teoria jocurilor\':teoria-jocurilor | ==user(user=\"filipb\" type=\"tiny\")== | IN LUCRU | ==user(user=\"filipb\" type=\"tiny\")== |\r\n| \'Psihologia concursurilor de informatica - Lucrul cu numere mari\':lucrul-cu-nr-mari | ==user(user=\"cata00\" type=\"tiny\")== | IMBUNATATIRE CONTINUT | ? |\r\n| Psihologia concursurilor de informatica - Lucrul cu structuri mari de date | ==user(user=\"cata00\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| Psihologia concursurilor de informatica - Probleme de concurs | ==user(user=\"cata00\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Probleme cu puncte laticeale\':downloads?action=download&file=puncte_laticeale.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Probleme de taietura\':downloads?action=download&file=taietura.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Transformari geometrice\':downloads?action=download&file=transformari_geometrice.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Problema majoritatii votului\':downloads?action=download&file=problema_majoritatii.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n\r\nh3. 2. Preia si dezvolta un subiect mai vechi\r\n\r\nAi nevoie de un impuls pentru a-ti da drumul la scris? Sunt cateva articole pe infoarena incepute, dar abandonate, precum si niste schite. Poti folosi ideile de start ale autorului si il poti transforma intr-un articol bine documentat. In plus, poti lua legatura cu autorul initial si poti afla viziunea sa asupra subiectului. Iata o lista de articole abandonate si de schite:\r\n\r\ntable. |_. Titlu |_. Autor initial |\r\n| Programare dinamica / memoizare (trading space for time): \'link1\':programare-dinamica, \'link2\':pd | ==user(user=\"Zeus\" type=\"tiny\")== |\r\n| \'Arbori indexati binar\':aib | ==user(user=\"Skipy\" type=\"tiny\")== |\r\n| \'Dinic\':dinic | ==user(user=\"alexandru.mosoi\" type=\"tiny\")== |\r\n| \'Probleme de geometrie si solutii\':downloads?geometrie.zip | ==user(user=\"Cosmin\" type=\"tiny\")== |\r\n| \'Diagrame Voronoi\':voronoi | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| \'Algoritmi de baleiere\':algoritmi-de-baleiere | ==user(user=\"stef2n\" type=\"tiny\")== |\r\n\r\nh3. 3. Creeaza ceva nou\r\n\r\nAi o idee noua de articol? Sau pur si simplu vrei sa te apuci de la 0 de un subiect? Ia legatura cu coordonatorul proiectului sau anunta pe \'forum\':forum. Este posibil sa primesti ajutor si de la alti utilizatori infoarena. In plus, noi iti propunem o lista de articole pe care ni le-am dori scrise, in caz ca nu te-ai decis asupra temei:\r\n\r\ntable. |_. Titlu |\r\n| Depanarea programelor C/C++ cu gdb in Linux |\r\n| Testarea surselor in timp de concurs sau Cum sa reduci buselile |\r\n| Tutorial LaTeX |\r\n\r\nNe rezervam dreptul sa nu acceptam sau sa stergem articolele care nu se potrivesc cu tema si target-ul site-ului.\r\n\r\nh2. Cu cine iau legatura?\r\n\r\nCu coordonatorul proiectului:\r\n\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n\r\nSau daca vrei sa contribui la un articol la care se lucreaza deja, poti vorbi direct cu voluntarii care se ocupa de el.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"43\")==\r\n\r\n*TODO*\r\n\r\ntable. |_. Subiect |_. Voluntar(i) |_. Progres |\r\n| Notiuni de geometrie analitica si aplicatii | ==user(user=\"devilkind\" type=\"tiny\")== \r\n==user(user=\"sima_cotizo\" type=\"tiny\")== | \'50%\':notiuni-de-geometrie-si-aplicatii |',2044,'public',NULL,NULL),('grigore-moisil-2009','Grigore Moisil 2009','2009-03-31 19:07:10','2009-04-04 09:29:45','h1. Grigore Moisil 2009\r\n\r\n(htabs)*(active) \'Despre...\':grigore-moisil-2009 \r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n* \'Rezultate\':grigore-moisil-2009/clasament/5-8\r\n\r\nInfoarena organizeaza si in acest an editia online a concursului interjudetean de informatica Grigore Moisil. Concurentii pot profita de aceasta ocazie pentru a efectua un ultim test inainte de Olimpiada Nationala. Concursul se va desfasura *Duminica 5 aprilie*, la ora {*09^00^*} si va dura *3h*. Participantii vor avea de rezolvat 2-3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':grigore-moisil-2009/clasament/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/clasament/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/clasament/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/clasament/11-12\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* prof. Clara Ionescu\r\n* ==User(user=\"SleepyOverlord\" type=\"tiny\")==\r\n* ==User(user=\"Marius\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n',2092,'protected',NULL,NULL),('probleme-de-taietura','Probleme de Taietura','2009-04-06 05:48:04','2009-04-07 17:31:53','h1. Probleme de taietura\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"andrici_cezar\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n\r\n(toc){width: 25em}*{text-align:center} *Conţinut:*\r\n* \'Problema 1\':probleme-de-taietura#1\r\n* \'Problema 2\':probleme-de-taietura#2\r\n* \'Problema 3\':probleme-de-taietura#3\r\n* \'Problema 4\':probleme-de-taietura#4\r\n* \'Problema 5\':probleme-de-taietura#5\r\n* \'Problema 6\':probleme-de-taietura#6\r\n* \'Problema 7\':probleme-de-taietura#7\r\n* \'Problema 8\':probleme-de-taietura#8\r\n* \'Problema 9\':probleme-de-taietura#9\r\n* \'Problema 10\':probleme-de-taietura#10\r\n* \'Problema 11\':probleme-de-taietura#11\r\n* \'Problema 12\':probleme-de-taietura#12\r\n* \'Bibliografie\':probleme-de-taietura#bio\r\n\r\n\r\n\r\nh2(#1). Problema 1:\r\n\r\nPentru un număr natural N dat, se cere numărul maxim de regiuni în care se poate împărţi planul folosind N drepte.\r\n!probleme-de-taietura?poza-1.bmp!\r\n \r\nRezolvare:\r\nMai întâi facem vom face două observaţii:\r\nÎn configuraţia cu număr maxim de regiuni nu vom avea două drepte paralele, pentru că două drepte care se intersectează formează în plan patru regiuni, în timp ce două drepte paralele formează în plan doar trei regiuni.\r\nDe asemenea pentru a obţine un număr maxim de regiuni, nu vor exista trei drepte care să se intersecteze intr-un punct pentru că astfel am pierde o regiune triunghiulară formată din punctele de intersecţie ale celor trei drepte.\r\nDacă aceste două condiţii sunt îndeplinite vom vedea în continuare că orice configuraţie de N drepte împarte planul în acelaţi număr de regiuni. Notăm cu d(n) acest număr. Presupunem ca ştim pe d(n), să vedem acum ce se întâmplă dacă mai adaugăm o dreaptă. \r\nAceastă nouă dreaptă va fi intersectată de celelalte drepte în n puncte distincte. Fiecare segment de dreaptă şi semidreaptă în care este împărţită a n+1-a taie o regiune veche in două regiuni noi. De aici tragem concluzia că d(n+1) = d(n) + n + 1. Deci d(n) = n + n – 1 + n – 2 + … + 2 + d(1). Astfel folosind indentitatea 1 + 2 + 3 + … + n = n(n+1)/2 obţinem d(n) = n(n + 1) / 2 + 1.\r\nMenţionăm că problemele în care se cere maximizarea numărului de regiuni în care un pătrat, un triunghi sau un cerc este împărţit de n drepte, au aceiaşi soluţie.\r\n!probleme-de-taietura?poza-2.bmp!\r\n\r\nh2(#2). Problema 2:\r\n\r\nDându-se un număr natural N, se cere numărul maxim de regiuni în care N cercuri pot împărţi planul.\r\n!probleme-de-taietura?poza-4.bmp!\r\n\r\nRezolvare:\r\nEste clar că oricare două cercuri trebuie să se intersecteze in exact două puncte, nu să fie tangente sau să nu se intersecteze deloc pentru că astfel am pierde o regiune, iar oricare trei cercuri nu se intersectează într-un punct.\r\nOrice configuraţie care satisface această cerinţă va împărţi planul într-un număr maxim de regiuni.Vom nota cu c(n) numărul maxim de regiuni în care este împărţit planul de n cercuri. Să vedem ce se întîmplă când adăugăm un nou cerc la această configuraţie. Cercul nou va fi intersectat de cele n cercuri în 2n puncte distincte, şi astfel va fi împărţit în 2n arce. Fiecare dintre aceste arce împarte o zonă veche în două zone noi. De aici tragem concluzia că c(n + 1) = 2n + c(n). Astfel putem să îl scriem pe c(n) ca 2(n – 1) + 2(n – 2) + … + 2 + c(1). De aici folosind din nou identitatea 1 + 2 + … + n = n(n+1)/2 avem că c(n) = n(n-1) + 2.\r\nEste evident că şi problema în care se cere maximizarea numărului de regiuni în care este împărţită suprafaţa unei sfere de n cercuri are aceiaşi soluţie.\r\n!probleme-de-taietura?poza-5.bmp!\r\n\r\nh2(#3). Problema 3:\r\n\r\nSe dau n cercuri care se intersectează oricare două în două puncte şi nu există trei care se intersectează într-un punct, se cere să se determine numărul de zone în care este împarţit planul de aceste n cercuri. ( n <= 10^100)\r\n[acm.uva.es 10519 !! Really Strange !!]\r\n\r\nRezolvare:\r\nObservăm ca sunt indeplinite condiţiile de maximalitate cerute mai sus, deci rezultatul e c(n), singura problema ce rămâne este aceea de implementare a operaţiilor cu numere mari.\r\n\r\nh2(#4). Problema 4:\r\n\r\nAvem un număr natural N, vrem să determinăm numărul maxim de regiuni în care poate fi împărţit un plan de elipse.\r\n\r\n!probleme-de-taietura?poza-6.bmp!\r\n\r\nRezolvare:\r\nLa fel ca şi la cercuri nici aici nu trebuie să avem elipse tangente, sau elipse care să nu se intersecteze, nu vor exista nici aici trei elipse care să se intersecteze într-un punct, aici elipsele trebuie să se intersecteze în patru puncte, dacă s-ar intersecta numai în două puncte atunci configuraţia nu ar avea număr maxim de regiuni.\r\nNotăm cu e(n) numărul de care suntem interesaţi. Câte regiuni noi apar cand adăugam o nouă elipsă? Păi o nouă elipsă va fi intersectată de celelalte elipse ăn patru puncte de fiecare, deci e(n + 1) = 4n + e(n). De aici tragem concluzia că e(n) = 2 n(n - 1) + 2.\r\n\r\n!probleme-de-taietura?poza-7.bmp!\r\n\r\nh2(#5). Problema 5:\r\n\r\nDându-se un număr natural N, se cere numărul maxim de regiuni în care N triunghiuri pot împărţi planul.\r\n !probleme-de-taietura?poza-8.bmp!\r\n\r\nRezolvare:\r\nRepetând raţionamentul de la problemele anterioareavem că t(n+1) = 6n + t(n) => t(n) = 3n(n-1) + 2. \r\n!probleme-de-taietura?poza-9.bmp!\r\n\r\nh2(#6). Problema 6:\r\n\r\nPentru N plane determinaţi numărul maxim de zone în care poate fi împărţit spaţiul cu acestea.\r\nRezolvare:\r\nÎn această problemă urmăm raţionamentul de până acum. Este evident că trebuie ca fiecare plan să se intersecteze cu fiecare, că oricare trei plane trebuie să nu se intersecteze într-o dreaptă, oricare trei plane nu trebuie să fie paralele cu o dreaptă şi oricare patru plane nu trebuie să se intersecteze într-un punct. Notăm p(n) numărul maxim de zone în care n plane împart spatiul. Când adaugăm un nou plan acesta va fi intersectat de celelalte plane în n drepte, drepte care după restrictiile care le-am pus nu vor fi două paralele sau trei care să se intersecteze într-un punct. Acest plan va fi împărţit în d(n)  regiuni de aceste drepte din cauza restricţiilor impuse. Fiecare regiune din plan taie o zonă din spaţiu în două noi zone, de aici tragem concluzia că p(n + 1) = d(n) + p(n). Astfel avem p(n) =  n(n-1)/2 + 1 + (n-1)(n-2)/2 + 1 + … +  2 * 1 / 2 + 1 + p(1) = ( n^2 – n + (n-1)^2 – (n-1) + … + 2^2 – 2  +  1 – 1 + (n – 1) )/2 + 2 = ( n(n+1)(2n + 1)/6 – n(n+1)/2 + (n-1))/2 + 2  = (n^3/3 + n^2/2 + n/6 – n^2/2 – n/2 )/2 + n + 1 = n^3 / 6 + 5n/6 + 1. Am folosit identităţile 1 + 2 + … + n = n(n+1)/2 şi 1 + 2^2 + 3^2 + … + n^2 = n(n+1)(2n+1)/6 care se pot demonstra uşor prin inducţie.\r\nMenţionăm că dacă vrem să împărţim un cub, un cilindru o sfera etc în număr maxim de regiuni folosind n plane, formula se păstrează.\r\n\r\nh2(#7). Problema 7:\r\n\r\nDându-se un număr natural N, să se determine numărul maxim de zone în care pot împărţi spaţiul N sfere.\r\n[Bursele Agora 2001[3]]\r\nRezolvare:\r\nPornim la fel ca la problema anterioară, oricare două sfere se vor intersecta şi nu vor exista trei sfere care să se intersecteze în acelaşi punct. Vom nota cu s(n) numărul maxim de regiuni în care poate fi împărţit spaţiul cu n sfere. Să vedem ce se întâmplă când adăugăm o sferă. Această sferă va fi intersectată de toate celelalte n sfere în n cercuri, pentru ca numărul de regiuni noi să fie maxim aceste cercuri vor împărţi sfera într-un număr maxim de regiuni, acest număr este c(n) aşa cum am discutat la problema 2. Obţinem astfel s(n + 1) = c(n) + s(n) = c(n) + c(n-1) + ... + c(1) = n(n-1) + 2 + (n-1)(n-2) + 2 + ... + 2 = 1 + 2^2 + .. + n^2 – 1 – 2 – 3 - .... – n + 2n => s(n) = n(n^2 – 3n + 8) / 3\r\n\r\nh2(#8). Problema 8:\r\n\r\nSe dă un număr N care este numărul maxim în care poate fi împărţit planul de m elipse, n cercuri şi p triunghiuri. Se cere ştiind N să se determine toate valorile posibile pentru m, n şi p. (N întreg făra semn reprezentabil pe 32 de biţi, 0<=m<100, 0<=n<20000 şi 0<=p<100)\r\n[10623 Thinking Backward [4]]\r\nRezolvare:\r\nDacă am ştii pentru trei parametrii m, n şi p care este numarul maxim de părţi în care poate fi împărţit planul  de m elipse, n cercuri şi p triunghiuri, atunci am putea incerca toate posibilitaţile pentru m, n şi p şi am găsi tripletele pentru rezultatul ar fie gal cu N, chiar am putea optimiza puţin acest algoritm iteram pe toate valorile de m şi p, astfel vom obţine o ecuaţie cu necunoscuta n astfel vom face doar 10000 de rezolvări de ecuaţii în loc de 200 000 000 de comparaţii. \r\nSă vedem cum găsim numărul maxim de zone. Din nou oricare două figuri se intersectează în număr maxim de intersecţii, un cerc cu o elipsă în patru puncte, un cerc sau o elipsă cu un triunghi în şase puncte. Mai întâi punem cele m elipse in plan, ele vor împărţi planul în e(m) regiuni adică 2 m(m - 1) + 2. După aceea adaugăm cercurile. Să notam numarul maxim de zone în care n cercuri şi m elipse pot împărţi planul cu ec(m , n). Dacă ştim cât este e(m, n-1) atunci când adaugăm un nou cerc, acesta va fi intersectat de m elipse in 4m puncte şi de n-1 cercuri in 2(n – 1) puncte deci cercul va fi împărţit în 4m + 2(n-1) arce care vor împărţi tot atâtea regiuni care existau deja in câte două regiuni noi. Deci ec(m, n) = 4m + 2(n-1) + ec(m, n-1) = 4m + 2(n-1) + 4m + 2(n-2) + … + 4m + 2 + ec(m, 0) = 4m(n-1) + n (n-1) + 2m(m-1) + 2. Să vedem ce se întâmplă când adăugăm triunghiurile. Vom nota ect(m, n, p) numărul maxim de zone în care poate fi împărţit planul de m elipse, n cercuri şi p triunghiuri. Dacă ştim cu cat e egal ect(m, n, p - 1) , atunci când vom adăuga un nou triunghi acesta va intersecta cele m cercuri în 6m puncte, cele n elipse în 6n puncte şi cele p – 1 triunghiuri în 6(p – 1) puncte, astfel se vor forma 6m + 6n + 6(p-1) noi zone. Deci ect(m, n, p) = 6(m + n + p – 1) + ect(m, n, p – 1) = 6 (m + n + p – 1 + m + n + p – 2 + … m + n + 1) + ect(n, m, 0) = 6 (p-1)(m+n) + 3p(p-1) + 4m(n-1) + n(n-1) + 2m(m-1) + 2.\r\n\r\nProblemele anterioare au fost cam matematice şi ele sunt numite de obicei de olimpici peiorativ ca “probleme de formulă”, majoritatea olimpicilor la informatică participă aici pentru că matematica nu le place aşa tare şi deci nici apariţia unor probleme ca cele de mai sus care sunt mai mult de mate decât de info nu îi prea încântă. Cum poate fi rezolvată o problemă de formulă fără să avem intuiţia matematică sau cunoţinţele matematice necesare? Păi câteodată elevii apelează la următorul truc: află primele câteva valori de mâna sau cu ajutorul unor algoritmi brute force şi apoi speră ca formula să fie de o anumită formă, de exemplu ar putea fi un polinom de un grad mic. Atunci avem ca f(N) = An^3 + Bn^2 + Cn + D. Afland primele câteva valori vom ştii valorile f(1), f(2), f(3), f(4). Dând lui n pe rand valorile 1, 2, 3 şi 4 putem face un sistem cu necunoscutele A, B, C şi D. Sau putem încerca să vedem cum se comportă şirul de numere, are o creştere polinomială sau exponenţială, apar valorile lui în triunghiul lui Pascal. Iar dacă rezolvăm problemele de acasă putem căuta valorile din şirul de soluţii pe internet pe pagina Eciclopedia Online a şirurilor de întregi [7] care este o resursă foarte utilă în cazul problemelor de acest gen .\r\n\r\nh2(#9). Problema 9:\r\n\r\nSe dau N drepte în plan, fiecare dreaptă este dată prin două puncte prin care trece. Se cere să se determine pentru această configuraţie în câte zone este împărţit planul. (n <= 1000)\r\n[Internet Problem Solving Contest 2000 [5]]\r\nRezolvare:\r\nÎn sfârşit o problemă în care avem nevoie să folosim calculatorul şi talentul nostru de programatori . Vom folosi aceeaşi idee ce a apărut şi în celelalte probleme, adică numărăm pe rând în câte zone este împărţit planul de primele o dreaptă, doua drepte respectiv n drepte. Deci vom adăuga în ordine dreptele la configuraţia noastră. Când adăugăm o dreaptă ea va fi intersectată de dreptele deja adăugate în k puncte nu neapărat distincte, pe noi ne intereseaza punctele distincte, ca să facem acest lucru putem sorta punctele în O(k log k) sau să folosim o tabelă de dispersie şi astfel să aflăm în O(k) numărul de puncte distincte, daca acest număr e egal cu L atunci la numărul curent de zone vom adăuga L. Astfel algoritmul are complexitatea O(n^2 log n), sau dacă folosim tabele de dispersie O(n^2).\r\n\r\nh2(#10). Problema 10:\r\n\r\n!probleme-de-taietura?poza-10.bmp!\r\n\r\nAvem un tort în formă de pătrat de dimensiune 1000 x 1000. Folosim un cuţit pentru a tăoa tortul. Întrebarea este după o serie de tăieturi, în căte bucăţi am patriţionat tortul. Restricţii: Numărul de tăieturi nu va fi mai mare de 8. După tăieturi, lungimea oricărei laturi a partiţiei nu va fi mai mică decât unu. Coordonatele vârfurilor tortului vor fi (0,0)(0,1000)(1000,1000) (1000,0). Tăieturile se vor intersecta în două puncte cu marginile tortului. Următoarea imagine e un tort tăiat în zece bucăţi.\r\n[acm.uva.es 527 The partition of a cake]\r\nRezolvarea este analoaga cu cea a problemei anterioare, datele sunt foarte mici în problema aceasta, probabil că autorii au vrut să facă problema accesibilă şi altor idei care folosesc împărţiri efective în poligoane a pătratului.\r\n\r\nh2(#11). Problema 11:\r\n\r\n!probleme-de-taietura?poza-12.bmp!\r\n\r\nSe dă un graf planar prin noduri şi muchii, un graf este planar dacă există o modalitate de a îl desena în plan făra ca muchiile să se intersecteze decăt la capete. Se cere să se determine în căte regiuni împarte planul graful dat la intrare. Mai jos avem un exemplu de graf în care feţele sunt numerotate.\r\n[10178 Count the faces [4]]\r\n\r\nRezolvare:\r\nEste interesant faptul că în această problemă nu ne este dată configuraţia în plan a grafului ci doar structura lui. Un graf il putem reprezenta în mai multe moduri în plan, astfel suntem duşi înspre ideea că există ceva formulă care rezolvă problema. O formulă întradevăr există şi se numeşte formula lui Euler pentru grafurile planare. Formula arată aşa f - m + n  = 2, unde prin f am notat numărul de feţe, m numărul de muchii şi n numărul de vârfuri., dacă graful nostru e conex (formula include faţa exterioară). Această formulă poate fi demonstrată în foarte multe moduri. Dacă vreţi să vedeţi 19 metode de demonstrare puteţi să vizitaţi adresa [8]. O demonstraţie simplă ar fi prin inducţie pornind de la un arbore şi adăugând pe rând câte o muchie. La început avem o singură faţă, cea infinită, 1 – (n – 1) + n = 2 se verifică. Fiecare muchie adăugată împarte o faţă în două deci dacă aveam inainte f – m + n = 2 acum vom avea f1 – m1 + n = 2 unde f1 = f + 1 şi m1 = m + 1. Deci am demonstrate formula şi putem foarte uşor să rezolvăm problema, mai trebuie numai să avem grijă ca pentru fiecare componentă conexă număram faţa infinită.\r\nAceastă formulă este adevarată şi în spaţiu pentru poliedre.\r\n\r\nh2(#12). Problema 12:\r\n\r\n!probleme-de-taietura?poza-13.bmp!\r\n\r\nSe considera N cercuri in plan. Se cere să se determine numărul de zone finite în care cercurile date împart planul.\r\n \r\nDate de intrare\r\nPe prima linie a fişierului CERCURI.IN se află N (1<=N<=200). Pe urmatoarele N linii se află câte trei numere întregi sub forma xi yi si ri, reprezentând coordonatele centrului şi raza cercului i.Coordonatele sunt numere ântregi din intervalul [0, 10000]. Razele cercurilor sunt întregi din intervalul [1, 1000].\r\nDate de ieşire\r\nIn fişierul CERCURI.OUT se va afisa numărul de zone determinat de cercurile date.\r\nExemplu\r\nCERCURI.IN\r\n4\r\n90 110 50\r\n130 70 30\r\n155 45 15\r\n165 115 65\r\nCERCURI.OUT\r\n11\r\n[Algoritmus, Cercuri[6]]\r\nRezolvare:\r\nContraexemple rezolvare normala\r\nO rezolvare folosind geometria computaţională pare foarte grea, lucrurile simplificându-se mult daca abordam problema prin prisma unor noţiuni de teoria grafurilor.\r\nFiecare punct de intersectie va fi considerat un nod. Două noduri vor fi legate prin o muchie dacă există un cerc pe care sa se afle amândouă iar între ele să nu existe nici un alt punct de intersectie.\r\nAcum vom folosi identitatea lui Euler: prezentată în problema anterioară. În problema noastră nu trebuie să numărăm şi faţa exterioară, deci formula folosita va fi F=M-V+1. Această formulă este adevarată doar in cazul unei singure componente conexe. Pentru mai multe componente, formula devine F=M-V+C, unde C este numărul de componente conexe.\r\nO atenţie deosebită trebuie acordată punctelor de intersecţie prin care trec mai mult de două cercuri, pentru a nu le număra de mai multe ori. Putem rezolva aceasta problema prin sortarea punctelor de intersecţie ale unui cerc cu toate celelalte cercuri.\r\nDeasemenea, este necesara eliminarea cercurilor identice (cu acelaşi centru şi raze egale). Din orice mulţime cu astfel de cercuri este păstrat doar un singur element.\r\nDeoarece pentru fiecare cerc este necesara o sortare a punctelor de intersectie, complexitatea generala a algoritmului va fi O(N2*log(N))\r\n\r\nh2(#bio). Bibliografie:\r\n\r\n[1] A.M. Iaglom, I. M. Iaglom, Probleme neelementare tratate elementat. Ed tehnică, Bucureşti, 1962\r\n[2] I. Tomescu, Probleme de combinatorică şi teoria grafurilor, ed didactică şi pedagogică. Bucureşti, 1981\r\n[3] Colecţia Ginfo\r\n[4] acm.uva.es\r\n[5] ipsc.ksp.sk\r\n[6] algoritmus.org/index.php\r\n[7] http://www.research.att.com/~njas/sequences/\r\n[8] http://www.ics.uci.edu/~eppstein/junkyard/euler/\r\n',7668,'public',NULL,NULL),('probleme-de-taietura','Probleme de Taietura','2009-04-06 05:48:04','2009-04-07 17:35:23','h1. Probleme de taietura\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"andrici_cezar\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n\r\n(toc){width: 25em}*{text-align:center} *Conţinut:*\r\n* \'Problema 1\':probleme-de-taietura#1\r\n* \'Problema 2\':probleme-de-taietura#2\r\n* \'Problema 3\':probleme-de-taietura#3\r\n* \'Problema 4\':probleme-de-taietura#4\r\n* \'Problema 5\':probleme-de-taietura#5\r\n* \'Problema 6\':probleme-de-taietura#6\r\n* \'Problema 7\':probleme-de-taietura#7\r\n* \'Problema 8\':probleme-de-taietura#8\r\n* \'Problema 9\':probleme-de-taietura#9\r\n* \'Problema 10\':probleme-de-taietura#10\r\n* \'Problema 11\':probleme-de-taietura#11\r\n* \'Problema 12\':probleme-de-taietura#12\r\n* \'Bibliografie\':probleme-de-taietura#bio\r\n\r\n\r\n\r\nh2(#1). Problema 1:\r\n\r\nPentru un număr natural N dat, se cere numărul maxim de regiuni în care se poate împărţi planul folosind N drepte.\r\n!probleme-de-taietura?poza-1.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nMai întâi facem vom face două observaţii:\r\nÎn configuraţia cu număr maxim de regiuni nu vom avea două drepte paralele, pentru că două drepte care se intersectează formează în plan patru regiuni, în timp ce două drepte paralele formează în plan doar trei regiuni.\r\nDe asemenea pentru a obţine un număr maxim de regiuni, nu vor exista trei drepte care să se intersecteze intr-un punct pentru că astfel am pierde o regiune triunghiulară formată din punctele de intersecţie ale celor trei drepte.\r\nDacă aceste două condiţii sunt îndeplinite vom vedea în continuare că orice configuraţie de N drepte împarte planul în acelaţi număr de regiuni. Notăm cu d(n) acest număr. Presupunem ca ştim pe d(n), să vedem acum ce se întâmplă dacă mai adaugăm o dreaptă. \r\nAceastă nouă dreaptă va fi intersectată de celelalte drepte în n puncte distincte. Fiecare segment de dreaptă şi semidreaptă în care este împărţită a n+1-a taie o regiune veche in două regiuni noi. De aici tragem concluzia că d(n+1) = d(n) + n + 1. Deci d(n) = n + n – 1 + n – 2 + … + 2 + d(1). Astfel folosind indentitatea 1 + 2 + 3 + … + n = n(n+1)/2 obţinem d(n) = n(n + 1) / 2 + 1.\r\nMenţionăm că problemele în care se cere maximizarea numărului de regiuni în care un pătrat, un triunghi sau un cerc este împărţit de n drepte, au aceiaşi soluţie.\r\n!probleme-de-taietura?poza-2.bmp!\r\n\r\nh2(#2). Problema 2:\r\n\r\nDându-se un număr natural N, se cere numărul maxim de regiuni în care N cercuri pot împărţi planul.\r\n!probleme-de-taietura?poza-4.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nEste clar că oricare două cercuri trebuie să se intersecteze in exact două puncte, nu să fie tangente sau să nu se intersecteze deloc pentru că astfel am pierde o regiune, iar oricare trei cercuri nu se intersectează într-un punct.\r\nOrice configuraţie care satisface această cerinţă va împărţi planul într-un număr maxim de regiuni.Vom nota cu c(n) numărul maxim de regiuni în care este împărţit planul de n cercuri. Să vedem ce se întîmplă când adăugăm un nou cerc la această configuraţie. Cercul nou va fi intersectat de cele n cercuri în 2n puncte distincte, şi astfel va fi împărţit în 2n arce. Fiecare dintre aceste arce împarte o zonă veche în două zone noi. De aici tragem concluzia că c(n + 1) = 2n + c(n). Astfel putem să îl scriem pe c(n) ca 2(n – 1) + 2(n – 2) + … + 2 + c(1). De aici folosind din nou identitatea 1 + 2 + … + n = n(n+1)/2 avem că c(n) = n(n-1) + 2.\r\nEste evident că şi problema în care se cere maximizarea numărului de regiuni în care este împărţită suprafaţa unei sfere de n cercuri are aceiaşi soluţie.\r\n!probleme-de-taietura?poza-5.bmp!\r\n\r\nh2(#3). Problema 3:\r\n\r\nSe dau n cercuri care se intersectează oricare două în două puncte şi nu există trei care se intersectează într-un punct, se cere să se determine numărul de zone în care este împarţit planul de aceste n cercuri. ( n <= 10^100)\r\n[acm.uva.es 10519 !! Really Strange !!]\r\n\r\nh3. Rezolvare:\r\n\r\nObservăm ca sunt indeplinite condiţiile de maximalitate cerute mai sus, deci rezultatul e c(n), singura problema ce rămâne este aceea de implementare a operaţiilor cu numere mari.\r\n\r\nh2(#4). Problema 4:\r\n\r\nAvem un număr natural N, vrem să determinăm numărul maxim de regiuni în care poate fi împărţit un plan de elipse.\r\n\r\n!probleme-de-taietura?poza-6.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nLa fel ca şi la cercuri nici aici nu trebuie să avem elipse tangente, sau elipse care să nu se intersecteze, nu vor exista nici aici trei elipse care să se intersecteze într-un punct, aici elipsele trebuie să se intersecteze în patru puncte, dacă s-ar intersecta numai în două puncte atunci configuraţia nu ar avea număr maxim de regiuni.\r\nNotăm cu e(n) numărul de care suntem interesaţi. Câte regiuni noi apar cand adăugam o nouă elipsă? Păi o nouă elipsă va fi intersectată de celelalte elipse ăn patru puncte de fiecare, deci e(n + 1) = 4n + e(n). De aici tragem concluzia că e(n) = 2 n(n - 1) + 2.\r\n\r\n!probleme-de-taietura?poza-7.bmp!\r\n\r\nh2(#5). Problema 5:\r\n\r\nDându-se un număr natural N, se cere numărul maxim de regiuni în care N triunghiuri pot împărţi planul.\r\n !probleme-de-taietura?poza-8.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nRepetând raţionamentul de la problemele anterioareavem că t(n+1) = 6n + t(n) => t(n) = 3n(n-1) + 2. \r\n!probleme-de-taietura?poza-9.bmp!\r\n\r\nh2(#6). Problema 6:\r\n\r\nPentru N plane determinaţi numărul maxim de zone în care poate fi împărţit spaţiul cu acestea.\r\nh3. Rezolvare:\r\n\r\nÎn această problemă urmăm raţionamentul de până acum. Este evident că trebuie ca fiecare plan să se intersecteze cu fiecare, că oricare trei plane trebuie să nu se intersecteze într-o dreaptă, oricare trei plane nu trebuie să fie paralele cu o dreaptă şi oricare patru plane nu trebuie să se intersecteze într-un punct. Notăm p(n) numărul maxim de zone în care n plane împart spatiul. Când adaugăm un nou plan acesta va fi intersectat de celelalte plane în n drepte, drepte care după restrictiile care le-am pus nu vor fi două paralele sau trei care să se intersecteze într-un punct. Acest plan va fi împărţit în d(n)  regiuni de aceste drepte din cauza restricţiilor impuse. Fiecare regiune din plan taie o zonă din spaţiu în două noi zone, de aici tragem concluzia că p(n + 1) = d(n) + p(n). Astfel avem p(n) =  n(n-1)/2 + 1 + (n-1)(n-2)/2 + 1 + … +  2 * 1 / 2 + 1 + p(1) = ( n^2 – n + (n-1)^2 – (n-1) + … + 2^2 – 2  +  1 – 1 + (n – 1) )/2 + 2 = ( n(n+1)(2n + 1)/6 – n(n+1)/2 + (n-1))/2 + 2  = (n^3/3 + n^2/2 + n/6 – n^2/2 – n/2 )/2 + n + 1 = n^3 / 6 + 5n/6 + 1. Am folosit identităţile 1 + 2 + … + n = n(n+1)/2 şi 1 + 2^2 + 3^2 + … + n^2 = n(n+1)(2n+1)/6 care se pot demonstra uşor prin inducţie.\r\nMenţionăm că dacă vrem să împărţim un cub, un cilindru o sfera etc în număr maxim de regiuni folosind n plane, formula se păstrează.\r\n\r\nh2(#7). Problema 7:\r\n\r\nDându-se un număr natural N, să se determine numărul maxim de zone în care pot împărţi spaţiul N sfere.\r\n[Bursele Agora 2001[3]]\r\nh3. Rezolvare:\r\n\r\nPornim la fel ca la problema anterioară, oricare două sfere se vor intersecta şi nu vor exista trei sfere care să se intersecteze în acelaşi punct. Vom nota cu s(n) numărul maxim de regiuni în care poate fi împărţit spaţiul cu n sfere. Să vedem ce se întâmplă când adăugăm o sferă. Această sferă va fi intersectată de toate celelalte n sfere în n cercuri, pentru ca numărul de regiuni noi să fie maxim aceste cercuri vor împărţi sfera într-un număr maxim de regiuni, acest număr este c(n) aşa cum am discutat la problema 2. Obţinem astfel s(n + 1) = c(n) + s(n) = c(n) + c(n-1) + ... + c(1) = n(n-1) + 2 + (n-1)(n-2) + 2 + ... + 2 = 1 + 2^2 + .. + n^2 – 1 – 2 – 3 - .... – n + 2n => s(n) = n(n^2 – 3n + 8) / 3\r\n\r\nh2(#8). Problema 8:\r\n\r\nSe dă un număr N care este numărul maxim în care poate fi împărţit planul de m elipse, n cercuri şi p triunghiuri. Se cere ştiind N să se determine toate valorile posibile pentru m, n şi p. (N întreg făra semn reprezentabil pe 32 de biţi, 0<=m<100, 0<=n<20000 şi 0<=p<100)\r\n[10623 Thinking Backward [4]]\r\nh3. Rezolvare:\r\n\r\nDacă am ştii pentru trei parametrii m, n şi p care este numarul maxim de părţi în care poate fi împărţit planul  de m elipse, n cercuri şi p triunghiuri, atunci am putea incerca toate posibilitaţile pentru m, n şi p şi am găsi tripletele pentru rezultatul ar fie gal cu N, chiar am putea optimiza puţin acest algoritm iteram pe toate valorile de m şi p, astfel vom obţine o ecuaţie cu necunoscuta n astfel vom face doar 10000 de rezolvări de ecuaţii în loc de 200 000 000 de comparaţii. \r\nSă vedem cum găsim numărul maxim de zone. Din nou oricare două figuri se intersectează în număr maxim de intersecţii, un cerc cu o elipsă în patru puncte, un cerc sau o elipsă cu un triunghi în şase puncte. Mai întâi punem cele m elipse in plan, ele vor împărţi planul în e(m) regiuni adică 2 m(m - 1) + 2. După aceea adaugăm cercurile. Să notam numarul maxim de zone în care n cercuri şi m elipse pot împărţi planul cu ec(m , n). Dacă ştim cât este e(m, n-1) atunci când adaugăm un nou cerc, acesta va fi intersectat de m elipse in 4m puncte şi de n-1 cercuri in 2(n – 1) puncte deci cercul va fi împărţit în 4m + 2(n-1) arce care vor împărţi tot atâtea regiuni care existau deja in câte două regiuni noi. Deci ec(m, n) = 4m + 2(n-1) + ec(m, n-1) = 4m + 2(n-1) + 4m + 2(n-2) + … + 4m + 2 + ec(m, 0) = 4m(n-1) + n (n-1) + 2m(m-1) + 2. Să vedem ce se întâmplă când adăugăm triunghiurile. Vom nota ect(m, n, p) numărul maxim de zone în care poate fi împărţit planul de m elipse, n cercuri şi p triunghiuri. Dacă ştim cu cat e egal ect(m, n, p - 1) , atunci când vom adăuga un nou triunghi acesta va intersecta cele m cercuri în 6m puncte, cele n elipse în 6n puncte şi cele p – 1 triunghiuri în 6(p – 1) puncte, astfel se vor forma 6m + 6n + 6(p-1) noi zone. Deci ect(m, n, p) = 6(m + n + p – 1) + ect(m, n, p – 1) = 6 (m + n + p – 1 + m + n + p – 2 + … m + n + 1) + ect(n, m, 0) = 6 (p-1)(m+n) + 3p(p-1) + 4m(n-1) + n(n-1) + 2m(m-1) + 2.\r\n\r\nProblemele anterioare au fost cam matematice şi ele sunt numite de obicei de olimpici peiorativ ca “probleme de formulă”, majoritatea olimpicilor la informatică participă aici pentru că matematica nu le place aşa tare şi deci nici apariţia unor probleme ca cele de mai sus care sunt mai mult de mate decât de info nu îi prea încântă. Cum poate fi rezolvată o problemă de formulă fără să avem intuiţia matematică sau cunoţinţele matematice necesare? Păi câteodată elevii apelează la următorul truc: află primele câteva valori de mâna sau cu ajutorul unor algoritmi brute force şi apoi speră ca formula să fie de o anumită formă, de exemplu ar putea fi un polinom de un grad mic. Atunci avem ca f(N) = An^3 + Bn^2 + Cn + D. Afland primele câteva valori vom ştii valorile f(1), f(2), f(3), f(4). Dând lui n pe rand valorile 1, 2, 3 şi 4 putem face un sistem cu necunoscutele A, B, C şi D. Sau putem încerca să vedem cum se comportă şirul de numere, are o creştere polinomială sau exponenţială, apar valorile lui în triunghiul lui Pascal. Iar dacă rezolvăm problemele de acasă putem căuta valorile din şirul de soluţii pe internet pe pagina Eciclopedia Online a şirurilor de întregi [7] care este o resursă foarte utilă în cazul problemelor de acest gen .\r\n\r\nh2(#9). Problema 9:\r\n\r\nSe dau N drepte în plan, fiecare dreaptă este dată prin două puncte prin care trece. Se cere să se determine pentru această configuraţie în câte zone este împărţit planul. (n <= 1000)\r\n[Internet Problem Solving Contest 2000 [5]]\r\n\r\nh3. Rezolvare:\r\n\r\nÎn sfârşit o problemă în care avem nevoie să folosim calculatorul şi talentul nostru de programatori . Vom folosi aceeaşi idee ce a apărut şi în celelalte probleme, adică numărăm pe rând în câte zone este împărţit planul de primele o dreaptă, doua drepte respectiv n drepte. Deci vom adăuga în ordine dreptele la configuraţia noastră. Când adăugăm o dreaptă ea va fi intersectată de dreptele deja adăugate în k puncte nu neapărat distincte, pe noi ne intereseaza punctele distincte, ca să facem acest lucru putem sorta punctele în O(k log k) sau să folosim o tabelă de dispersie şi astfel să aflăm în O(k) numărul de puncte distincte, daca acest număr e egal cu L atunci la numărul curent de zone vom adăuga L. Astfel algoritmul are complexitatea O(n^2 log n), sau dacă folosim tabele de dispersie O(n^2).\r\n\r\nh2(#10). Problema 10:\r\n\r\n!probleme-de-taietura?poza-10.bmp!\r\n\r\nAvem un tort în formă de pătrat de dimensiune 1000 x 1000. Folosim un cuţit pentru a tăoa tortul. Întrebarea este după o serie de tăieturi, în căte bucăţi am patriţionat tortul. Restricţii: Numărul de tăieturi nu va fi mai mare de 8. După tăieturi, lungimea oricărei laturi a partiţiei nu va fi mai mică decât unu. Coordonatele vârfurilor tortului vor fi (0,0)(0,1000)(1000,1000) (1000,0). Tăieturile se vor intersecta în două puncte cu marginile tortului. Următoarea imagine e un tort tăiat în zece bucăţi.\r\n[acm.uva.es 527 The partition of a cake]\r\nRezolvarea este analoaga cu cea a problemei anterioare, datele sunt foarte mici în problema aceasta, probabil că autorii au vrut să facă problema accesibilă şi altor idei care folosesc împărţiri efective în poligoane a pătratului.\r\n\r\nh2(#11). Problema 11:\r\n\r\n!probleme-de-taietura?poza-12.bmp!\r\n\r\nSe dă un graf planar prin noduri şi muchii, un graf este planar dacă există o modalitate de a îl desena în plan făra ca muchiile să se intersecteze decăt la capete. Se cere să se determine în căte regiuni împarte planul graful dat la intrare. Mai jos avem un exemplu de graf în care feţele sunt numerotate.\r\n[10178 Count the faces [4]]\r\n\r\nh3. Rezolvare:\r\n\r\nEste interesant faptul că în această problemă nu ne este dată configuraţia în plan a grafului ci doar structura lui. Un graf il putem reprezenta în mai multe moduri în plan, astfel suntem duşi înspre ideea că există ceva formulă care rezolvă problema. O formulă întradevăr există şi se numeşte formula lui Euler pentru grafurile planare. Formula arată aşa f - m + n  = 2, unde prin f am notat numărul de feţe, m numărul de muchii şi n numărul de vârfuri., dacă graful nostru e conex (formula include faţa exterioară). Această formulă poate fi demonstrată în foarte multe moduri. Dacă vreţi să vedeţi 19 metode de demonstrare puteţi să vizitaţi adresa [8]. O demonstraţie simplă ar fi prin inducţie pornind de la un arbore şi adăugând pe rând câte o muchie. La început avem o singură faţă, cea infinită, 1 – (n – 1) + n = 2 se verifică. Fiecare muchie adăugată împarte o faţă în două deci dacă aveam inainte f – m + n = 2 acum vom avea f1 – m1 + n = 2 unde f1 = f + 1 şi m1 = m + 1. Deci am demonstrate formula şi putem foarte uşor să rezolvăm problema, mai trebuie numai să avem grijă ca pentru fiecare componentă conexă număram faţa infinită.\r\nAceastă formulă este adevarată şi în spaţiu pentru poliedre.\r\n\r\nh2(#12). Problema 12:\r\n\r\n!probleme-de-taietura?poza-13.bmp!\r\n\r\nSe considera N cercuri in plan. Se cere să se determine numărul de zone finite în care cercurile date împart planul.\r\n \r\nDate de intrare\r\nPe prima linie a fişierului CERCURI.IN se află N (1<=N<=200). Pe urmatoarele N linii se află câte trei numere întregi sub forma xi yi si ri, reprezentând coordonatele centrului şi raza cercului i.Coordonatele sunt numere ântregi din intervalul [0, 10000]. Razele cercurilor sunt întregi din intervalul [1, 1000].\r\nDate de ieşire\r\nIn fişierul CERCURI.OUT se va afisa numărul de zone determinat de cercurile date.\r\nExemplu\r\nCERCURI.IN\r\n4\r\n90 110 50\r\n130 70 30\r\n155 45 15\r\n165 115 65\r\nCERCURI.OUT\r\n11\r\n[Algoritmus, Cercuri[6]]\r\nh3. Rezolvare:\r\n\r\nContraexemple rezolvare normala\r\nO rezolvare folosind geometria computaţională pare foarte grea, lucrurile simplificându-se mult daca abordam problema prin prisma unor noţiuni de teoria grafurilor.\r\nFiecare punct de intersectie va fi considerat un nod. Două noduri vor fi legate prin o muchie dacă există un cerc pe care sa se afle amândouă iar între ele să nu existe nici un alt punct de intersectie.\r\nAcum vom folosi identitatea lui Euler: prezentată în problema anterioară. În problema noastră nu trebuie să numărăm şi faţa exterioară, deci formula folosita va fi F=M-V+1. Această formulă este adevarată doar in cazul unei singure componente conexe. Pentru mai multe componente, formula devine F=M-V+C, unde C este numărul de componente conexe.\r\nO atenţie deosebită trebuie acordată punctelor de intersecţie prin care trec mai mult de două cercuri, pentru a nu le număra de mai multe ori. Putem rezolva aceasta problema prin sortarea punctelor de intersecţie ale unui cerc cu toate celelalte cercuri.\r\nDeasemenea, este necesara eliminarea cercurilor identice (cu acelaşi centru şi raze egale). Din orice mulţime cu astfel de cercuri este păstrat doar un singur element.\r\nDeoarece pentru fiecare cerc este necesara o sortare a punctelor de intersectie, complexitatea generala a algoritmului va fi O(N2*log(N))\r\n\r\nh2(#bio). Bibliografie:\r\n\r\n[1] A.M. Iaglom, I. M. Iaglom, Probleme neelementare tratate elementat. Ed tehnică, Bucureşti, 1962\r\n[2] I. Tomescu, Probleme de combinatorică şi teoria grafurilor, ed didactică şi pedagogică. Bucureşti, 1981\r\n[3] Colecţia Ginfo\r\n[4] acm.uva.es\r\n[5] ipsc.ksp.sk\r\n[6] algoritmus.org/index.php\r\n[7] http://www.research.att.com/~njas/sequences/\r\n[8] http://www.ics.uci.edu/~eppstein/junkyard/euler/\r\n',7668,'public',NULL,NULL),('probleme-de-taietura','Probleme de Taietura','2009-04-06 05:48:04','2009-04-07 17:51:13','h1. Probleme de taietura\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"andrici_cezar\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n\r\n(toc){width: 25em}*{text-align:center} *Conţinut:*\r\n* \'Problema 1\':probleme-de-taietura#problema-1\r\n* \'Problema 2\':probleme-de-taietura#problema-2\r\n* \'Problema 3\':probleme-de-taietura#problema-3\r\n* \'Problema 4\':probleme-de-taietura#problema-4\r\n* \'Problema 5\':probleme-de-taietura#problema-5\r\n* \'Problema 6\':probleme-de-taietura#problema-6\r\n* \'Problema 7\':probleme-de-taietura#problema-7\r\n* \'Problema 8\':probleme-de-taietura#problema-8\r\n* \'Problema 9\':probleme-de-taietura#problema-9\r\n* \'Problema 10\':probleme-de-taietura#problema-10\r\n* \'Problema 11\':probleme-de-taietura#problema-11\r\n* \'Problema 12\':probleme-de-taietura#problema-12\r\n* \'Bibliografie\':probleme-de-taietura#bibliografie\r\n\r\n\r\n\r\nh2(#problema-1). Problema 1:\r\n\r\nPentru un număr natural N dat, se cere numărul maxim de regiuni în care se poate împărţi planul folosind N drepte.\r\n!probleme-de-taietura?poza-1.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nMai întâi facem vom face două observaţii:\r\nÎn configuraţia cu număr maxim de regiuni nu vom avea două drepte paralele, pentru că două drepte care se intersectează formează în plan patru regiuni, în timp ce două drepte paralele formează în plan doar trei regiuni.\r\nDe asemenea pentru a obţine un număr maxim de regiuni, nu vor exista trei drepte care să se intersecteze intr-un punct pentru că astfel am pierde o regiune triunghiulară formată din punctele de intersecţie ale celor trei drepte.\r\nDacă aceste două condiţii sunt îndeplinite vom vedea în continuare că orice configuraţie de N drepte împarte planul în acelaţi număr de regiuni. Notăm cu d(n) acest număr. Presupunem ca ştim pe d(n), să vedem acum ce se întâmplă dacă mai adaugăm o dreaptă. \r\nAceastă nouă dreaptă va fi intersectată de celelalte drepte în n puncte distincte. Fiecare segment de dreaptă şi semidreaptă în care este împărţită a n+1-a taie o regiune veche in două regiuni noi. De aici tragem concluzia că d(n+1) = d(n) + n + 1. Deci d(n) = n + n – 1 + n – 2 + … + 2 + d(1). Astfel folosind indentitatea 1 + 2 + 3 + … + n = n(n+1)/2 obţinem d(n) = n(n + 1) / 2 + 1.\r\nMenţionăm că problemele în care se cere maximizarea numărului de regiuni în care un pătrat, un triunghi sau un cerc este împărţit de n drepte, au aceiaşi soluţie.\r\n!probleme-de-taietura?poza-2.bmp!\r\n\r\nh2(#problema-2). Problema 2:\r\n\r\nDându-se un număr natural N, se cere numărul maxim de regiuni în care N cercuri pot împărţi planul.\r\n!probleme-de-taietura?poza-4.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nEste clar că oricare două cercuri trebuie să se intersecteze in exact două puncte, nu să fie tangente sau să nu se intersecteze deloc pentru că astfel am pierde o regiune, iar oricare trei cercuri nu se intersectează într-un punct.\r\nOrice configuraţie care satisface această cerinţă va împărţi planul într-un număr maxim de regiuni.Vom nota cu c(n) numărul maxim de regiuni în care este împărţit planul de n cercuri. Să vedem ce se întîmplă când adăugăm un nou cerc la această configuraţie. Cercul nou va fi intersectat de cele n cercuri în 2n puncte distincte, şi astfel va fi împărţit în 2n arce. Fiecare dintre aceste arce împarte o zonă veche în două zone noi. De aici tragem concluzia că c(n + 1) = 2n + c(n). Astfel putem să îl scriem pe c(n) ca 2(n – 1) + 2(n – 2) + … + 2 + c(1). De aici folosind din nou identitatea 1 + 2 + … + n = n(n+1)/2 avem că c(n) = n(n-1) + 2.\r\nEste evident că şi problema în care se cere maximizarea numărului de regiuni în care este împărţită suprafaţa unei sfere de n cercuri are aceiaşi soluţie.\r\n!probleme-de-taietura?poza-5.bmp!\r\n\r\nh2(#problema-3). Problema 3:\r\n\r\nSe dau n cercuri care se intersectează oricare două în două puncte şi nu există trei care se intersectează într-un punct, se cere să se determine numărul de zone în care este împarţit planul de aceste n cercuri. ( n <= 10^100)\r\n[acm.uva.es 10519 !! Really Strange !!]\r\n\r\nh3. Rezolvare:\r\n\r\nObservăm ca sunt indeplinite condiţiile de maximalitate cerute mai sus, deci rezultatul e c(n), singura problema ce rămâne este aceea de implementare a operaţiilor cu numere mari.\r\n\r\nh2(#problema-4). Problema 4:\r\n\r\nAvem un număr natural N, vrem să determinăm numărul maxim de regiuni în care poate fi împărţit un plan de elipse.\r\n\r\n!probleme-de-taietura?poza-6.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nLa fel ca şi la cercuri nici aici nu trebuie să avem elipse tangente, sau elipse care să nu se intersecteze, nu vor exista nici aici trei elipse care să se intersecteze într-un punct, aici elipsele trebuie să se intersecteze în patru puncte, dacă s-ar intersecta numai în două puncte atunci configuraţia nu ar avea număr maxim de regiuni.\r\nNotăm cu e(n) numărul de care suntem interesaţi. Câte regiuni noi apar cand adăugam o nouă elipsă? Păi o nouă elipsă va fi intersectată de celelalte elipse ăn patru puncte de fiecare, deci e(n + 1) = 4n + e(n). De aici tragem concluzia că e(n) = 2 n(n - 1) + 2.\r\n\r\n!probleme-de-taietura?poza-7.bmp!\r\n\r\nh2(#problema-5). Problema 5:\r\n\r\nDându-se un număr natural N, se cere numărul maxim de regiuni în care N triunghiuri pot împărţi planul.\r\n !probleme-de-taietura?poza-8.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nRepetând raţionamentul de la problemele anterioareavem că t(n+1) = 6n + t(n) => t(n) = 3n(n-1) + 2. \r\n!probleme-de-taietura?poza-9.bmp!\r\n\r\nh2(#problema-6). Problema 6:\r\n\r\nPentru N plane determinaţi numărul maxim de zone în care poate fi împărţit spaţiul cu acestea.\r\n\r\nh3. Rezolvare:\r\n\r\nÎn această problemă urmăm raţionamentul de până acum. Este evident că trebuie ca fiecare plan să se intersecteze cu fiecare, că oricare trei plane trebuie să nu se intersecteze într-o dreaptă, oricare trei plane nu trebuie să fie paralele cu o dreaptă şi oricare patru plane nu trebuie să se intersecteze într-un punct. Notăm p(n) numărul maxim de zone în care n plane împart spatiul. Când adaugăm un nou plan acesta va fi intersectat de celelalte plane în n drepte, drepte care după restrictiile care le-am pus nu vor fi două paralele sau trei care să se intersecteze într-un punct. Acest plan va fi împărţit în d(n)  regiuni de aceste drepte din cauza restricţiilor impuse. Fiecare regiune din plan taie o zonă din spaţiu în două noi zone, de aici tragem concluzia că p(n + 1) = d(n) + p(n). Astfel avem p(n) =  n(n-1)/2 + 1 + (n-1)(n-2)/2 + 1 + … +2 * 1 / 2 + 1 + p(1) = ( n^2^ – n + (n-1)^2^ – (n-1)+ … + 2^2^ – 2  +  1 – 1 + (n – 1) )/2+ 2 = ( n(n+1)(2n + 1)/6 – n(n+1)/2 + (n-1))/2 + 2  = (n^3^/3 + n^2^/2 + n/6 – n^2^/2 – n/2 )/2 + n + 1 = n^3^/ 6 + 5n/6 + 1. Am folosit identităţile 1 + 2 + … + n = n(n+1)/2 şi 1 + 2^2^ + 3^2^ + … + n^2^ = n(n+1)(2n+1)/6 care se pot demonstra uşor prin inducţie.\r\nMenţionăm că dacă vrem să împărţim un cub, un cilindru o sfera etc în număr maxim de regiuni folosind n plane, formula se păstrează.\r\n\r\nh2(#problema-7). Problema 7:\r\n\r\nDându-se un număr natural N, să se determine numărul maxim de zone în care pot împărţi spaţiul N sfere.\r\n[Bursele Agora 2001[3]]\r\n\r\nh3. Rezolvare:\r\n\r\nPornim la fel ca la problema anterioară, oricare două sfere se vor intersecta şi nu vor exista trei sfere care să se intersecteze în acelaşi punct. Vom nota cu s(n) numărul maxim de regiuni în care poate fi împărţit spaţiul cu n sfere. Să vedem ce se întâmplă când adăugăm o sferă. Această sferă va fi intersectată de toate celelalte n sfere în n cercuri, pentru ca numărul de regiuni noi să fie maxim aceste cercuri vor împărţi sfera într-un număr maxim de regiuni, acest număr este c(n) aşa cum am discutat la problema 2. Obţinem astfel s(n + 1) = c(n) + s(n) = c(n) + c(n-1) + ... + c(1) = n(n-1) + 2 + (n-1)(n-2) + 2 + ... + 2 = 1 + 2^2 + .. + n^2 – 1 – 2 – 3 - .... – n + 2n => s(n) = n(n^2 – 3n + 8) / 3\r\n\r\nh2(#problema-8). Problema 8:\r\n\r\nSe dă un număr N care este numărul maxim în care poate fi împărţit planul de m elipse, n cercuri şi p triunghiuri. Se cere ştiind N să se determine toate valorile posibile pentru m, n şi p. (N întreg făra semn reprezentabil pe 32 de biţi, 0<=m<100, 0<=n<20000 şi 0<=p<100)\r\n[10623 Thinking Backward [4]]\r\n\r\nh3. Rezolvare:\r\n\r\nDacă am ştii pentru trei parametrii m, n şi p care este numarul maxim de părţi în care poate fi împărţit planul  de m elipse, n cercuri şi p triunghiuri, atunci am putea incerca toate posibilitaţile pentru m, n şi p şi am găsi tripletele pentru rezultatul ar fie gal cu N, chiar am putea optimiza puţin acest algoritm iteram pe toate valorile de m şi p, astfel vom obţine o ecuaţie cu necunoscuta n astfel vom face doar 10000 de rezolvări de ecuaţii în loc de 200 000 000 de comparaţii. \r\nSă vedem cum găsim numărul maxim de zone. Din nou oricare două figuri se intersectează în număr maxim de intersecţii, un cerc cu o elipsă în patru puncte, un cerc sau o elipsă cu un triunghi în şase puncte. Mai întâi punem cele m elipse in plan, ele vor împărţi planul în e(m) regiuni adică 2 m(m - 1) + 2. După aceea adaugăm cercurile. Să notam numarul maxim de zone în care n cercuri şi m elipse pot împărţi planul cu ec(m , n). Dacă ştim cât este e(m, n-1) atunci când adaugăm un nou cerc, acesta va fi intersectat de m elipse in 4m puncte şi de n-1 cercuri in 2(n – 1) puncte deci cercul va fi împărţit în 4m + 2(n-1) arce care vor împărţi tot atâtea regiuni care existau deja in câte două regiuni noi. Deci ec(m, n) = 4m + 2(n-1) + ec(m, n-1) = 4m + 2(n-1) + 4m + 2(n-2) + … + 4m + 2 + ec(m, 0) = 4m(n-1) + n (n-1) + 2m(m-1) + 2. Să vedem ce se întâmplă când adăugăm triunghiurile. Vom nota ect(m, n, p) numărul maxim de zone în care poate fi împărţit planul de m elipse, n cercuri şi p triunghiuri. Dacă ştim cu cat e egal ect(m, n, p - 1) , atunci când vom adăuga un nou triunghi acesta va intersecta cele m cercuri în 6m puncte, cele n elipse în 6n puncte şi cele p – 1 triunghiuri în 6(p – 1) puncte, astfel se vor forma 6m + 6n + 6(p-1) noi zone. Deci ect(m, n, p) = 6(m + n + p – 1) + ect(m, n, p – 1) = 6 (m + n + p – 1 + m + n + p – 2 + … m + n + 1) + ect(n, m, 0) = 6 (p-1)(m+n) + 3p(p-1) + 4m(n-1) + n(n-1) + 2m(m-1) + 2.\r\n\r\nProblemele anterioare au fost cam matematice şi ele sunt numite de obicei de olimpici peiorativ ca “probleme de formulă”, majoritatea olimpicilor la informatică participă aici pentru că matematica nu le place aşa tare şi deci nici apariţia unor probleme ca cele de mai sus care sunt mai mult de mate decât de info nu îi prea încântă. Cum poate fi rezolvată o problemă de formulă fără să avem intuiţia matematică sau cunoţinţele matematice necesare? Păi câteodată elevii apelează la următorul truc: află primele câteva valori de mâna sau cu ajutorul unor algoritmi brute force şi apoi speră ca formula să fie de o anumită formă, de exemplu ar putea fi un polinom de un grad mic. Atunci avem ca f(N) = An^3 + Bn^2 + Cn + D. Afland primele câteva valori vom ştii valorile f(1), f(2), f(3), f(4). Dând lui n pe rand valorile 1, 2, 3 şi 4 putem face un sistem cu necunoscutele A, B, C şi D. Sau putem încerca să vedem cum se comportă şirul de numere, are o creştere polinomială sau exponenţială, apar valorile lui în triunghiul lui Pascal. Iar dacă rezolvăm problemele de acasă putem căuta valorile din şirul de soluţii pe internet pe pagina Eciclopedia Online a şirurilor de întregi [7] care este o resursă foarte utilă în cazul problemelor de acest gen .\r\n\r\nh2(#problema-9). Problema 9:\r\n\r\nSe dau N drepte în plan, fiecare dreaptă este dată prin două puncte prin care trece. Se cere să se determine pentru această configuraţie în câte zone este împărţit planul. (n <= 1000)\r\n[Internet Problem Solving Contest 2000 [5]]\r\n\r\nh3. Rezolvare:\r\n\r\nÎn sfârşit o problemă în care avem nevoie să folosim calculatorul şi talentul nostru de programatori . Vom folosi aceeaşi idee ce a apărut şi în celelalte probleme, adică numărăm pe rând în câte zone este împărţit planul de primele o dreaptă, doua drepte respectiv n drepte. Deci vom adăuga în ordine dreptele la configuraţia noastră. Când adăugăm o dreaptă ea va fi intersectată de dreptele deja adăugate în k puncte nu neapărat distincte, pe noi ne intereseaza punctele distincte, ca să facem acest lucru putem sorta punctele în O(k log k) sau să folosim o tabelă de dispersie şi astfel să aflăm în O(k) numărul de puncte distincte, daca acest număr e egal cu L atunci la numărul curent de zone vom adăuga L. Astfel algoritmul are complexitatea O(n^2 log n), sau dacă folosim tabele de dispersie O(n^2).\r\n\r\nh2(#problema-10). Problema 10:\r\n\r\n!probleme-de-taietura?poza-10.bmp!\r\n\r\nAvem un tort în formă de pătrat de dimensiune 1000 x 1000. Folosim un cuţit pentru a tăoa tortul. Întrebarea este după o serie de tăieturi, în căte bucăţi am patriţionat tortul. Restricţii: Numărul de tăieturi nu va fi mai mare de 8. După tăieturi, lungimea oricărei laturi a partiţiei nu va fi mai mică decât unu. Coordonatele vârfurilor tortului vor fi (0,0)(0,1000)(1000,1000) (1000,0). Tăieturile se vor intersecta în două puncte cu marginile tortului. Următoarea imagine e un tort tăiat în zece bucăţi.\r\n[acm.uva.es 527 The partition of a cake]\r\n\r\nh3. Rezolvarea:\r\n\r\nEste analoaga cu cea a problemei anterioare, datele sunt foarte mici în problema aceasta, probabil că autorii au vrut să facă problema accesibilă şi altor idei care folosesc împărţiri efective în poligoane a pătratului.\r\n\r\nh2(#problema-11). Problema 11:\r\n\r\n!probleme-de-taietura?poza-12.bmp!\r\n\r\nSe dă un graf planar prin noduri şi muchii, un graf este planar dacă există o modalitate de a îl desena în plan făra ca muchiile să se intersecteze decăt la capete. Se cere să se determine în căte regiuni împarte planul graful dat la intrare. Mai jos avem un exemplu de graf în care feţele sunt numerotate.\r\n[10178 Count the faces [4]]\r\n\r\nh3. Rezolvare:\r\n\r\nEste interesant faptul că în această problemă nu ne este dată configuraţia în plan a grafului ci doar structura lui. Un graf il putem reprezenta în mai multe moduri în plan, astfel suntem duşi înspre ideea că există ceva formulă care rezolvă problema. O formulă întradevăr există şi se numeşte formula lui Euler pentru grafurile planare. Formula arată aşa f - m + n  = 2, unde prin f am notat numărul de feţe, m numărul de muchii şi n numărul de vârfuri., dacă graful nostru e conex (formula include faţa exterioară). Această formulă poate fi demonstrată în foarte multe moduri. Dacă vreţi să vedeţi 19 metode de demonstrare puteţi să vizitaţi adresa [8]. O demonstraţie simplă ar fi prin inducţie pornind de la un arbore şi adăugând pe rând câte o muchie. La început avem o singură faţă, cea infinită, 1 – (n – 1) + n = 2 se verifică. Fiecare muchie adăugată împarte o faţă în două deci dacă aveam inainte f – m + n = 2 acum vom avea f1 – m1 + n = 2 unde f1 = f + 1 şi m1 = m + 1. Deci am demonstrate formula şi putem foarte uşor să rezolvăm problema, mai trebuie numai să avem grijă ca pentru fiecare componentă conexă număram faţa infinită.\r\nAceastă formulă este adevarată şi în spaţiu pentru poliedre.\r\n\r\nh2(#problema-12). Problema 12:\r\n\r\n!probleme-de-taietura?poza-13.bmp!\r\n\r\nSe considera N cercuri in plan. Se cere să se determine numărul de zone finite în care cercurile date împart planul.\r\n \r\nDate de intrare\r\nPe prima linie a fişierului CERCURI.IN se află N (1<=N<=200). Pe urmatoarele N linii se află câte trei numere întregi sub forma xi yi si ri, reprezentând coordonatele centrului şi raza cercului i.Coordonatele sunt numere ântregi din intervalul [0, 10000]. Razele cercurilor sunt întregi din intervalul [1, 1000].\r\nDate de ieşire\r\nIn fişierul CERCURI.OUT se va afisa numărul de zone determinat de cercurile date.\r\nExemplu\r\nCERCURI.IN\r\n4\r\n90 110 50\r\n130 70 30\r\n155 45 15\r\n165 115 65\r\nCERCURI.OUT\r\n11\r\n[Algoritmus, Cercuri[6]]\r\n\r\nh3. Rezolvare:\r\n\r\nContraexemple rezolvare normala\r\nO rezolvare folosind geometria computaţională pare foarte grea, lucrurile simplificându-se mult daca abordam problema prin prisma unor noţiuni de teoria grafurilor.\r\nFiecare punct de intersectie va fi considerat un nod. Două noduri vor fi legate prin o muchie dacă există un cerc pe care sa se afle amândouă iar între ele să nu existe nici un alt punct de intersectie.\r\nAcum vom folosi identitatea lui Euler: prezentată în problema anterioară. În problema noastră nu trebuie să numărăm şi faţa exterioară, deci formula folosita va fi F=M-V+1. Această formulă este adevarată doar in cazul unei singure componente conexe. Pentru mai multe componente, formula devine F=M-V+C, unde C este numărul de componente conexe.\r\nO atenţie deosebită trebuie acordată punctelor de intersecţie prin care trec mai mult de două cercuri, pentru a nu le număra de mai multe ori. Putem rezolva aceasta problema prin sortarea punctelor de intersecţie ale unui cerc cu toate celelalte cercuri.\r\nDeasemenea, este necesara eliminarea cercurilor identice (cu acelaşi centru şi raze egale). Din orice mulţime cu astfel de cercuri este păstrat doar un singur element.\r\nDeoarece pentru fiecare cerc este necesara o sortare a punctelor de intersectie, complexitatea generala a algoritmului va fi O(N2*log(N))\r\n\r\nh2(#bibliografie). Bibliografie:\r\n\r\n[1] A.M. Iaglom, I. M. Iaglom, Probleme neelementare tratate elementat. Ed tehnică, Bucureşti, 1962\r\n[2] I. Tomescu, Probleme de combinatorică şi teoria grafurilor, ed didactică şi pedagogică. Bucureşti, 1981\r\n[3] Colecţia Ginfo\r\n[4] acm.uva.es\r\n[5] ipsc.ksp.sk\r\n[6] algoritmus.org/index.php\r\n[7] http://www.research.att.com/~njas/sequences/\r\n[8] http://www.ics.uci.edu/~eppstein/junkyard/euler/\r\n',7668,'public',NULL,NULL),('probleme-de-taietura','Probleme de Taietura','2009-04-06 05:48:04','2009-04-07 17:52:52','h1. Probleme de taietura\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"andrici_cezar\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n\r\n(toc){width: 25em}*{text-align:center} *Conţinut:*\r\n* \'Problema 1\':probleme-de-taietura#problema-1\r\n* \'Problema 2\':probleme-de-taietura#problema-2\r\n* \'Problema 3\':probleme-de-taietura#problema-3\r\n* \'Problema 4\':probleme-de-taietura#problema-4\r\n* \'Problema 5\':probleme-de-taietura#problema-5\r\n* \'Problema 6\':probleme-de-taietura#problema-6\r\n* \'Problema 7\':probleme-de-taietura#problema-7\r\n* \'Problema 8\':probleme-de-taietura#problema-8\r\n* \'Problema 9\':probleme-de-taietura#problema-9\r\n* \'Problema 10\':probleme-de-taietura#problema-10\r\n* \'Problema 11\':probleme-de-taietura#problema-11\r\n* \'Problema 12\':probleme-de-taietura#problema-12\r\n* \'Bibliografie\':probleme-de-taietura#bibliografie\r\n\r\n\r\n\r\nh2(#problema-1). Problema 1:\r\n\r\nPentru un număr natural N dat, se cere numărul maxim de regiuni în care se poate împărţi planul folosind N drepte.\r\n!probleme-de-taietura?poza-1.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nMai întâi facem vom face două observaţii:\r\nÎn configuraţia cu număr maxim de regiuni nu vom avea două drepte paralele, pentru că două drepte care se intersectează formează în plan patru regiuni, în timp ce două drepte paralele formează în plan doar trei regiuni.\r\nDe asemenea pentru a obţine un număr maxim de regiuni, nu vor exista trei drepte care să se intersecteze intr-un punct pentru că astfel am pierde o regiune triunghiulară formată din punctele de intersecţie ale celor trei drepte.\r\nDacă aceste două condiţii sunt îndeplinite vom vedea în continuare că orice configuraţie de N drepte împarte planul în acelaţi număr de regiuni. Notăm cu d(n) acest număr. Presupunem ca ştim pe d(n), să vedem acum ce se întâmplă dacă mai adaugăm o dreaptă. \r\nAceastă nouă dreaptă va fi intersectată de celelalte drepte în n puncte distincte. Fiecare segment de dreaptă şi semidreaptă în care este împărţită a n+1-a taie o regiune veche in două regiuni noi. De aici tragem concluzia că d(n+1) = d(n) + n + 1. Deci d(n) = n + n – 1 + n – 2 + … + 2 + d(1). Astfel folosind indentitatea 1 + 2 + 3 + … + n = n(n+1)/2 obţinem d(n) = n(n + 1) / 2 + 1.\r\nMenţionăm că problemele în care se cere maximizarea numărului de regiuni în care un pătrat, un triunghi sau un cerc este împărţit de n drepte, au aceiaşi soluţie.\r\n!probleme-de-taietura?poza-2.bmp!\r\n\r\nh2(#problema-2). Problema 2:\r\n\r\nDându-se un număr natural N, se cere numărul maxim de regiuni în care N cercuri pot împărţi planul.\r\n!probleme-de-taietura?poza-4.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nEste clar că oricare două cercuri trebuie să se intersecteze in exact două puncte, nu să fie tangente sau să nu se intersecteze deloc pentru că astfel am pierde o regiune, iar oricare trei cercuri nu se intersectează într-un punct.\r\nOrice configuraţie care satisface această cerinţă va împărţi planul într-un număr maxim de regiuni.Vom nota cu c(n) numărul maxim de regiuni în care este împărţit planul de n cercuri. Să vedem ce se întîmplă când adăugăm un nou cerc la această configuraţie. Cercul nou va fi intersectat de cele n cercuri în 2n puncte distincte, şi astfel va fi împărţit în 2n arce. Fiecare dintre aceste arce împarte o zonă veche în două zone noi. De aici tragem concluzia că c(n + 1) = 2n + c(n). Astfel putem să îl scriem pe c(n) ca 2(n – 1) + 2(n – 2) + … + 2 + c(1). De aici folosind din nou identitatea 1 + 2 + … + n = n(n+1)/2 avem că c(n) = n(n-1) + 2.\r\nEste evident că şi problema în care se cere maximizarea numărului de regiuni în care este împărţită suprafaţa unei sfere de n cercuri are aceiaşi soluţie.\r\n!probleme-de-taietura?poza-5.bmp!\r\n\r\nh2(#problema-3). Problema 3:\r\n\r\nSe dau n cercuri care se intersectează oricare două în două puncte şi nu există trei care se intersectează într-un punct, se cere să se determine numărul de zone în care este împarţit planul de aceste n cercuri. ( n <= 10^100)\r\n[acm.uva.es 10519 !! Really Strange !!]\r\n\r\nh3. Rezolvare:\r\n\r\nObservăm ca sunt indeplinite condiţiile de maximalitate cerute mai sus, deci rezultatul e c(n), singura problema ce rămâne este aceea de implementare a operaţiilor cu numere mari.\r\n\r\nh2(#problema-4). Problema 4:\r\n\r\nAvem un număr natural N, vrem să determinăm numărul maxim de regiuni în care poate fi împărţit un plan de elipse.\r\n\r\n!probleme-de-taietura?poza-6.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nLa fel ca şi la cercuri nici aici nu trebuie să avem elipse tangente, sau elipse care să nu se intersecteze, nu vor exista nici aici trei elipse care să se intersecteze într-un punct, aici elipsele trebuie să se intersecteze în patru puncte, dacă s-ar intersecta numai în două puncte atunci configuraţia nu ar avea număr maxim de regiuni.\r\nNotăm cu e(n) numărul de care suntem interesaţi. Câte regiuni noi apar cand adăugam o nouă elipsă? Păi o nouă elipsă va fi intersectată de celelalte elipse ăn patru puncte de fiecare, deci e(n + 1) = 4n + e(n). De aici tragem concluzia că e(n) = 2 n(n - 1) + 2.\r\n\r\n!probleme-de-taietura?poza-7.bmp!\r\n\r\nh2(#problema-5). Problema 5:\r\n\r\nDându-se un număr natural N, se cere numărul maxim de regiuni în care N triunghiuri pot împărţi planul.\r\n !probleme-de-taietura?poza-8.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nRepetând raţionamentul de la problemele anterioareavem că t(n+1) = 6n + t(n) => t(n) = 3n(n-1) + 2. \r\n!probleme-de-taietura?poza-9.bmp!\r\n\r\nh2(#problema-6). Problema 6:\r\n\r\nPentru N plane determinaţi numărul maxim de zone în care poate fi împărţit spaţiul cu acestea.\r\n\r\nh3. Rezolvare:\r\n\r\nÎn această problemă urmăm raţionamentul de până acum. Este evident că trebuie ca fiecare plan să se intersecteze cu fiecare, că oricare trei plane trebuie să nu se intersecteze într-o dreaptă, oricare trei plane nu trebuie să fie paralele cu o dreaptă şi oricare patru plane nu trebuie să se intersecteze într-un punct. Notăm p(n) numărul maxim de zone în care n plane împart spatiul. Când adaugăm un nou plan acesta va fi intersectat de celelalte plane în n drepte, drepte care după restrictiile care le-am pus nu vor fi două paralele sau trei care să se intersecteze într-un punct. Acest plan va fi împărţit în d(n)  regiuni de aceste drepte din cauza restricţiilor impuse. Fiecare regiune din plan taie o zonă din spaţiu în două noi zone, de aici tragem concluzia că p(n + 1) = d(n) + p(n). Astfel avem p(n) =  n(n-1)/2 + 1 + (n-1)(n-2)/2 + 1 + ... +2 * 1 / 2 + 1 + p(1) = ( n^2^ – n + (n-1)^2^ – (n-1)+ ... + 2^2^ – 2  +  1 – 1 + (n – 1) )/2+ 2 = ( n(n+1)(2n + 1)/6 – n(n+1)/2 + (n-1))/2 + 2  = (n^3^/3 + n^2^/2 + n/6 – n^2^/2 – n/2 )/2 + n + 1 = n^3^/ 6 + 5n/6 + 1. Am folosit identităţile 1 + 2 + … + n = n(n+1)/2 şi 1 + 2^2^ + 3^2^ + … + n^2^ = n(n+1)(2n+1)/6 care se pot demonstra uşor prin inducţie.\r\nMenţionăm că dacă vrem să împărţim un cub, un cilindru o sfera etc în număr maxim de regiuni folosind n plane, formula se păstrează.\r\n\r\nh2(#problema-7). Problema 7:\r\n\r\nDându-se un număr natural N, să se determine numărul maxim de zone în care pot împărţi spaţiul N sfere.\r\n[Bursele Agora 2001[3]]\r\n\r\nh3. Rezolvare:\r\n\r\nPornim la fel ca la problema anterioară, oricare două sfere se vor intersecta şi nu vor exista trei sfere care să se intersecteze în acelaşi punct. Vom nota cu s(n) numărul maxim de regiuni în care poate fi împărţit spaţiul cu n sfere. Să vedem ce se întâmplă când adăugăm o sferă. Această sferă va fi intersectată de toate celelalte n sfere în n cercuri, pentru ca numărul de regiuni noi să fie maxim aceste cercuri vor împărţi sfera într-un număr maxim de regiuni, acest număr este c(n) aşa cum am discutat la problema 2. Obţinem astfel s(n + 1) = c(n) + s(n) = c(n) + c(n-1) + ... + c(1) = n(n-1) + 2 + (n-1)(n-2) + 2 + ... + 2 = 1 + 2^2 + .. + n^2 – 1 – 2 – 3 - .... – n + 2n => s(n) = n(n^2 – 3n + 8) / 3\r\n\r\nh2(#problema-8). Problema 8:\r\n\r\nSe dă un număr N care este numărul maxim în care poate fi împărţit planul de m elipse, n cercuri şi p triunghiuri. Se cere ştiind N să se determine toate valorile posibile pentru m, n şi p. (N întreg făra semn reprezentabil pe 32 de biţi, 0<=m<100, 0<=n<20000 şi 0<=p<100)\r\n[10623 Thinking Backward [4]]\r\n\r\nh3. Rezolvare:\r\n\r\nDacă am ştii pentru trei parametrii m, n şi p care este numarul maxim de părţi în care poate fi împărţit planul  de m elipse, n cercuri şi p triunghiuri, atunci am putea incerca toate posibilitaţile pentru m, n şi p şi am găsi tripletele pentru rezultatul ar fie gal cu N, chiar am putea optimiza puţin acest algoritm iteram pe toate valorile de m şi p, astfel vom obţine o ecuaţie cu necunoscuta n astfel vom face doar 10000 de rezolvări de ecuaţii în loc de 200 000 000 de comparaţii. \r\nSă vedem cum găsim numărul maxim de zone. Din nou oricare două figuri se intersectează în număr maxim de intersecţii, un cerc cu o elipsă în patru puncte, un cerc sau o elipsă cu un triunghi în şase puncte. Mai întâi punem cele m elipse in plan, ele vor împărţi planul în e(m) regiuni adică 2 m(m - 1) + 2. După aceea adaugăm cercurile. Să notam numarul maxim de zone în care n cercuri şi m elipse pot împărţi planul cu ec(m , n). Dacă ştim cât este e(m, n-1) atunci când adaugăm un nou cerc, acesta va fi intersectat de m elipse in 4m puncte şi de n-1 cercuri in 2(n – 1) puncte deci cercul va fi împărţit în 4m + 2(n-1) arce care vor împărţi tot atâtea regiuni care existau deja in câte două regiuni noi. Deci ec(m, n) = 4m + 2(n-1) + ec(m, n-1) = 4m + 2(n-1) + 4m + 2(n-2) + … + 4m + 2 + ec(m, 0) = 4m(n-1) + n (n-1) + 2m(m-1) + 2. Să vedem ce se întâmplă când adăugăm triunghiurile. Vom nota ect(m, n, p) numărul maxim de zone în care poate fi împărţit planul de m elipse, n cercuri şi p triunghiuri. Dacă ştim cu cat e egal ect(m, n, p - 1) , atunci când vom adăuga un nou triunghi acesta va intersecta cele m cercuri în 6m puncte, cele n elipse în 6n puncte şi cele p – 1 triunghiuri în 6(p – 1) puncte, astfel se vor forma 6m + 6n + 6(p-1) noi zone. Deci ect(m, n, p) = 6(m + n + p – 1) + ect(m, n, p – 1) = 6 (m + n + p – 1 + m + n + p – 2 + … m + n + 1) + ect(n, m, 0) = 6 (p-1)(m+n) + 3p(p-1) + 4m(n-1) + n(n-1) + 2m(m-1) + 2.\r\n\r\nProblemele anterioare au fost cam matematice şi ele sunt numite de obicei de olimpici peiorativ ca “probleme de formulă”, majoritatea olimpicilor la informatică participă aici pentru că matematica nu le place aşa tare şi deci nici apariţia unor probleme ca cele de mai sus care sunt mai mult de mate decât de info nu îi prea încântă. Cum poate fi rezolvată o problemă de formulă fără să avem intuiţia matematică sau cunoţinţele matematice necesare? Păi câteodată elevii apelează la următorul truc: află primele câteva valori de mâna sau cu ajutorul unor algoritmi brute force şi apoi speră ca formula să fie de o anumită formă, de exemplu ar putea fi un polinom de un grad mic. Atunci avem ca f(N) = An^3 + Bn^2 + Cn + D. Afland primele câteva valori vom ştii valorile f(1), f(2), f(3), f(4). Dând lui n pe rand valorile 1, 2, 3 şi 4 putem face un sistem cu necunoscutele A, B, C şi D. Sau putem încerca să vedem cum se comportă şirul de numere, are o creştere polinomială sau exponenţială, apar valorile lui în triunghiul lui Pascal. Iar dacă rezolvăm problemele de acasă putem căuta valorile din şirul de soluţii pe internet pe pagina Eciclopedia Online a şirurilor de întregi [7] care este o resursă foarte utilă în cazul problemelor de acest gen .\r\n\r\nh2(#problema-9). Problema 9:\r\n\r\nSe dau N drepte în plan, fiecare dreaptă este dată prin două puncte prin care trece. Se cere să se determine pentru această configuraţie în câte zone este împărţit planul. (n <= 1000)\r\n[Internet Problem Solving Contest 2000 [5]]\r\n\r\nh3. Rezolvare:\r\n\r\nÎn sfârşit o problemă în care avem nevoie să folosim calculatorul şi talentul nostru de programatori . Vom folosi aceeaşi idee ce a apărut şi în celelalte probleme, adică numărăm pe rând în câte zone este împărţit planul de primele o dreaptă, doua drepte respectiv n drepte. Deci vom adăuga în ordine dreptele la configuraţia noastră. Când adăugăm o dreaptă ea va fi intersectată de dreptele deja adăugate în k puncte nu neapărat distincte, pe noi ne intereseaza punctele distincte, ca să facem acest lucru putem sorta punctele în O(k log k) sau să folosim o tabelă de dispersie şi astfel să aflăm în O(k) numărul de puncte distincte, daca acest număr e egal cu L atunci la numărul curent de zone vom adăuga L. Astfel algoritmul are complexitatea O(n^2 log n), sau dacă folosim tabele de dispersie O(n^2).\r\n\r\nh2(#problema-10). Problema 10:\r\n\r\n!probleme-de-taietura?poza-10.bmp!\r\n\r\nAvem un tort în formă de pătrat de dimensiune 1000 x 1000. Folosim un cuţit pentru a tăoa tortul. Întrebarea este după o serie de tăieturi, în căte bucăţi am patriţionat tortul. Restricţii: Numărul de tăieturi nu va fi mai mare de 8. După tăieturi, lungimea oricărei laturi a partiţiei nu va fi mai mică decât unu. Coordonatele vârfurilor tortului vor fi (0,0)(0,1000)(1000,1000) (1000,0). Tăieturile se vor intersecta în două puncte cu marginile tortului. Următoarea imagine e un tort tăiat în zece bucăţi.\r\n[acm.uva.es 527 The partition of a cake]\r\n\r\nh3. Rezolvarea:\r\n\r\nEste analoaga cu cea a problemei anterioare, datele sunt foarte mici în problema aceasta, probabil că autorii au vrut să facă problema accesibilă şi altor idei care folosesc împărţiri efective în poligoane a pătratului.\r\n\r\nh2(#problema-11). Problema 11:\r\n\r\n!probleme-de-taietura?poza-12.bmp!\r\n\r\nSe dă un graf planar prin noduri şi muchii, un graf este planar dacă există o modalitate de a îl desena în plan făra ca muchiile să se intersecteze decăt la capete. Se cere să se determine în căte regiuni împarte planul graful dat la intrare. Mai jos avem un exemplu de graf în care feţele sunt numerotate.\r\n[10178 Count the faces [4]]\r\n\r\nh3. Rezolvare:\r\n\r\nEste interesant faptul că în această problemă nu ne este dată configuraţia în plan a grafului ci doar structura lui. Un graf il putem reprezenta în mai multe moduri în plan, astfel suntem duşi înspre ideea că există ceva formulă care rezolvă problema. O formulă întradevăr există şi se numeşte formula lui Euler pentru grafurile planare. Formula arată aşa f - m + n  = 2, unde prin f am notat numărul de feţe, m numărul de muchii şi n numărul de vârfuri., dacă graful nostru e conex (formula include faţa exterioară). Această formulă poate fi demonstrată în foarte multe moduri. Dacă vreţi să vedeţi 19 metode de demonstrare puteţi să vizitaţi adresa [8]. O demonstraţie simplă ar fi prin inducţie pornind de la un arbore şi adăugând pe rând câte o muchie. La început avem o singură faţă, cea infinită, 1 – (n – 1) + n = 2 se verifică. Fiecare muchie adăugată împarte o faţă în două deci dacă aveam inainte f – m + n = 2 acum vom avea f1 – m1 + n = 2 unde f1 = f + 1 şi m1 = m + 1. Deci am demonstrate formula şi putem foarte uşor să rezolvăm problema, mai trebuie numai să avem grijă ca pentru fiecare componentă conexă număram faţa infinită.\r\nAceastă formulă este adevarată şi în spaţiu pentru poliedre.\r\n\r\nh2(#problema-12). Problema 12:\r\n\r\n!probleme-de-taietura?poza-13.bmp!\r\n\r\nSe considera N cercuri in plan. Se cere să se determine numărul de zone finite în care cercurile date împart planul.\r\n \r\nDate de intrare\r\nPe prima linie a fişierului CERCURI.IN se află N (1<=N<=200). Pe urmatoarele N linii se află câte trei numere întregi sub forma xi yi si ri, reprezentând coordonatele centrului şi raza cercului i.Coordonatele sunt numere ântregi din intervalul [0, 10000]. Razele cercurilor sunt întregi din intervalul [1, 1000].\r\nDate de ieşire\r\nIn fişierul CERCURI.OUT se va afisa numărul de zone determinat de cercurile date.\r\nExemplu\r\nCERCURI.IN\r\n4\r\n90 110 50\r\n130 70 30\r\n155 45 15\r\n165 115 65\r\nCERCURI.OUT\r\n11\r\n[Algoritmus, Cercuri[6]]\r\n\r\nh3. Rezolvare:\r\n\r\nContraexemple rezolvare normala\r\nO rezolvare folosind geometria computaţională pare foarte grea, lucrurile simplificându-se mult daca abordam problema prin prisma unor noţiuni de teoria grafurilor.\r\nFiecare punct de intersectie va fi considerat un nod. Două noduri vor fi legate prin o muchie dacă există un cerc pe care sa se afle amândouă iar între ele să nu existe nici un alt punct de intersectie.\r\nAcum vom folosi identitatea lui Euler: prezentată în problema anterioară. În problema noastră nu trebuie să numărăm şi faţa exterioară, deci formula folosita va fi F=M-V+1. Această formulă este adevarată doar in cazul unei singure componente conexe. Pentru mai multe componente, formula devine F=M-V+C, unde C este numărul de componente conexe.\r\nO atenţie deosebită trebuie acordată punctelor de intersecţie prin care trec mai mult de două cercuri, pentru a nu le număra de mai multe ori. Putem rezolva aceasta problema prin sortarea punctelor de intersecţie ale unui cerc cu toate celelalte cercuri.\r\nDeasemenea, este necesara eliminarea cercurilor identice (cu acelaşi centru şi raze egale). Din orice mulţime cu astfel de cercuri este păstrat doar un singur element.\r\nDeoarece pentru fiecare cerc este necesara o sortare a punctelor de intersectie, complexitatea generala a algoritmului va fi O(N2*log(N))\r\n\r\nh2(#bibliografie). Bibliografie:\r\n\r\n[1] A.M. Iaglom, I. M. Iaglom, Probleme neelementare tratate elementat. Ed tehnică, Bucureşti, 1962\r\n[2] I. Tomescu, Probleme de combinatorică şi teoria grafurilor, ed didactică şi pedagogică. Bucureşti, 1981\r\n[3] Colecţia Ginfo\r\n[4] acm.uva.es\r\n[5] ipsc.ksp.sk\r\n[6] algoritmus.org/index.php\r\n[7] http://www.research.att.com/~njas/sequences/\r\n[8] http://www.ics.uci.edu/~eppstein/junkyard/euler/\r\n',7668,'public',NULL,NULL),('multe-smenuri-de-programare-in-cc-si-nu-numai','Multe \"smenuri\" de programare in C/C++... si nu numai!','2004-11-10 00:00:00','2009-02-19 23:43:38','h1. Multe \"smenuri\" de programare in C/C++... si nu numai!\r\n\r\n(Categoria _Limbaje de programare_, Autor _Mircea Pasoi_)\r\n\r\nAcest articol vine ca o completare a articolului scris de Alexandru Mosoi, prezentand noi trucuri care le-am folosit si m-au ajutat mult. O mare parte din acestea le-am invatat din sursele lui Radu Berinde (cred ca stiti cu totii cine este), asadar ii multumesc!\r\n\r\nh2. Array-uri neindexate de la 0\r\n\r\nUn dezavantaj fata de Pascal este faptul ca in C nu putem avea expresii de genul {@A[-100]@} unde $A$ este un vector. Dar acest lucru se poate remedia. Spre exemplu, daca vrem sa facem un vector $A$ cu elemente de la $-100$ la $100$ procedam astfel:\r\n\r\n== code(c) |\r\nint A[201];\r\n#define A (A + 100)\r\n==\r\n\r\nh2. Fisiere de intrare si iesire\r\n\r\nFolositi {@freopen()@} in loc de {@fopen()@} deoarece este mai comod, in special la concursurile in care intrare si iesirea sunt standard.\r\n\r\n== code(c) |\r\nfreopen(\"in.txt\", \"r\", stdin);\r\nfreopen(\"out.txt\", \"w\", stdout);\r\n==\r\n\r\nh2. Cautare binara (ideea originala de la Mihai Patrascu)\r\n\r\nUrmatorul cod este de aproximativ $4$ ori mai rapid (am testat cu cautare binara ca in manual) , mai usor de inteles, mai flexibil si mai scurt... ce ati putea dori mai mult?\r\n\r\n== code(c) |\r\nint N, A[N];\r\n\r\nint binary_search(int val)\r\n{\r\n    int i, step;\r\n    for (step = 1; step < N; step <<= 1);\r\n    for (i = 0; step; step >>= 1)\r\n        if (i + step < N && A[i + step] <= val)\r\n           i += step;\r\n    return i;\r\n}\r\n==\r\n\r\nProcedura de mai sus face cautarea binara folosind puteri a lui $2$ in ordine descrescatoare, practic incerc sa determin fiecare bit al rezultatului.\r\n\r\nh2. Impartire in bucati de marime $sqrt(n)$ (cunoscut si ca \"smenul lui Bogdan Batog\")\r\n\r\nSa presupunem ca avem un vector de lungime n cu numere reale pe care se fac urmatoarele operatii:\r\n{@ADUNA(st, dr, x)@} - toate elementele cu indicii intre $st$ si $dr$ isi cresc valoarea cu $x$\r\n{@SUMA(st, dr)@} - returneaza suma elementelor cu indicii intre $st$ si $dr$\r\n\r\nPentru cei ce cunosc arbori de intervale, rezolvarea acestei probleme in $O(lg n)$ per operatie este o munca usoara, dar presupunand ca nu stim aceasta structura putem folosi urmatorul truc: vom construi un al doilea vector de lungime $sqrt(n)$ care retine suma elementelor pe bucati de lungime {$sqrt(n)$}. Pentru a face o operatie pe un interval [{$st, dr$}] vom imparti acest interval in bucati de $sqrt(n)$ a caror actualizare o facem in vectorul $B$ si elementele care raman in margine in vectorul {$A$}. De exemplu pe vectorul {$A{~0..15~}$} vom avea vectorul {$B{~0..3~}$}. Pentru a actualiza de exemplu [{$2, 12$}] vom actualiza {$B{~1~}$} (care corespunde lui [{$4..7$}]), {$B{~2~}$} (pentru [{$8..11$}]) si {$A{~2~}$}, {$A{~3~}$}, {$A{~12~}$} (elementele din margini). Cum sunt maxim $sqrt(n)$ elemente de actualizat in $B$ si pe margini nu vom actualiza niciodata mai mult de $2 * sqrt(n)$ elemente putem concluziona ca operatiile vor avea complexitate {$O(sqrt(n))$}.\r\n\r\nDaca am avea aceeasi problema dar in doua dimensiuni, am putea face acelasi \"smen\" pentru fiecare linie pentru o complexitate $O(n*sqrt(n))$ per operatie, sau cu arbori de intervale pe fiecare linie {$O(n*lg n)$}. Putem, de asemenea obtine o complexitate $O(n)$ folosind urmatoarea impartire:\r\n$A$ - pentru bucati $1 * 1$\r\n$B$ - pentru bucati $sqrt(n) * sqrt(n)$\r\n$C$ - pentru bucati $1 * sqrt(n)$\r\n$D$ - pentru bucati $sqrt(n) * 1$\r\nAcest mod de reprezentare este o extindere directa a aceluiasi smen in doua dimensiuni. Aceasta idee poate fi folosita si pentru alte operatii: inmultire, minim, maxim, etc. In general, orice se poate rezolva cu acest \"smen\" se poate obtine la o complexitate mai buna cu arbori de intervale, dar merita sa stiti si aceasta ideea deoarece de multe ori scuteste din efortul de implementare, desi se pierde din viteza... alegerea voastra! ;)\r\n\r\nh2. LCA in $O(sqrt(n))$ (ideea originala de la Radu Berinde)\r\n\r\nDaca nu stiti ce este LCA, va recomand sa cititi \'articolul\':lowest-common-ancestor lui Emilian Miron din cadrul site-ului pentru a va documenta. In continuare vom prezenta un algoritm mai ineficient, dar foarte usor de implementat. Consideram arborele si atribuim fiecarui nod o inaltime. Vom imparti arborele in $sqrt(H)$ intervale in functie de inaltime, unde $H$ e inaltimea maxima (de exemplu la $H=9$ nodurile cu inaltimi intre $0$ si $2$ vor forma un interval, [{$3..5$}] alt interval si ultimul interval de inaltimi [{$6..8$}]). Astfel, pentru fiecare nod, pe langa tatal sau, vom retine si tatal din intervalul de mai sus, printr-o parcurgere DF. In continuare, codul:\r\n\r\n$H$ se calculeaza inainte sau poate fi constant\r\n$T$ sunt tatii nodului si $N$ numarul de noduri\r\n\r\n== code(c) |\r\nvoid DF(int n, int t2, int lev)\r\n{\r\n    int i;\r\n    T2[n] = t2, Lev[n] = lev;\r\n    if (lev % H == 0) t2 = n;\r\n    for (i = 0; i < N; i++)\r\n        if (T[i] == n) DF(i, t2, lev+1);\r\n}\r\n==\r\n\r\nOperatia de LCA se va realiza apoi foarte usor, urcand pe tatii din intervale, pana se ajunge la doua noduri in acelasi interval, apoi folosindu-se metoda clasica. Cod:\r\n\r\n== code(c) |\r\nint LCA(int x, int y)\r\n{\r\n    while (T2[x] != T2[y])\r\n        if (Lev[x] > Lev[y])\r\n            x = T2[x];\r\n        else\r\n            y = T2[y];\r\n    while (x != y)\r\n        if (Lev[x] > Lev[y])\r\n            x = T[x];\r\n        else\r\n            y = T[y];\r\n    return x;\r\n}\r\n==\r\n\r\n\r\nh2. LCA in $O(lg^2^ n)$\r\n\r\nAceeasi problema, dar o alta rezolvare. Vom construi o matrice $A{~i,j~}$ cu semnificatia $A{~i,j~}$ = al {$2^i^$}-lea tata al nodului {$j$}. Folosind aceasta matrice putem cauta binar ({$O(lg n)$}) nivelul pe care s-ar putea afla LCA-ul a doua noduri si sa determinam daca nodul ales este corect - adica daca nodul situat la acel nivel este acelasi pentru cele doua noduri pentru care se face LCA ({$O(lg n)$} cu matricea de mai sus). Complexitate finala $O(lg^2^ n)$ si $O(n*lg n)$ memorie.\r\n\r\nh2. For-uri \"complicate\"\r\n\r\nfor-ul in C/C++ este foarte flexibil si poate ajuta foarte mult in compactarea codului, deci si a timpului de implementare. In continuare vom prezenta algoritmul merge sort (sortare prin interclasare) scris in cateva linii (putine, zic eu!):\r\n\r\n== code(c) |\r\nint N, A[N], B[N];\r\nvoid merge_sort(int l, int r)\r\n{\r\n    int m = (l + r) >> 1, i, j, k;\r\n    if (l == r) return;\r\n    merge_sort(l, m);\r\n    merge_sort(m + 1, r);\r\n    for (i=l, j=m+1, k=l; i<=m || j<=r; )\r\n        if (j > r || (i <= m && A[i] < A[j]))\r\n            B[k++] = A[i++];\r\n        else\r\n            B[k++] = A[j++];\r\n    for (k = l; k <= r; k++) A[k] = B[k];\r\n}\r\n==\r\n\r\nh2. Recomandari generale\r\n\r\n# Programare dinamica cu memoizare: mult mai simplu si uneori chiar mai rapida cand nu ne trebuie tot array-ul\r\n# Algoritmi randomizati: de multe ori mai usor de implementat si mai eficienti, mai bine decat cei euristici, dar necesita o analiza mult mai atenta a performantei. Exemple calsice: quicksort, statistici de ordine\r\n\r\nh2. \"Smenul lui Mars\" (Marius Andrei)\r\n\r\nConsideram urmatoarea problema: se da un vector $A$ de $N$ elemente pe care se fac $M$ astfel de operatii: {@ADUNA(st, dr, x)@} - toate elementele cu indicii intre $st$ si $dr$ ({$0 &le; st &le; dr &lt; N$}) isi cresc valoarea cu {$x$} . La sfarsit trebuie sa se afiseze vectorul rezultat. In continuarea vom descrie o metoda care ne da un timp de rulare de $O(1)$ pentru operatia $ADUNA$ si $O(N)$ pentru a determina toate elementele din vector. Vom construi un al doilea vector $B$ de $N+1$ elemente, cu proprietatea ca {$A{~i~} = B{~0~} + B{~1~} + ... B{~i~}$}. Astfel, o operatie {@ADUNA(st, dr, x)@} devine:\r\n\r\n== code(c) |B[st] += x;\r\nB[dr + 1] -= x;\r\n==\r\n\r\nDa, este chiar asa de simplu! Pentru a determina un element A{~i~} vom aduna pur si simplu {$B{~0~} + B{~1~} + ... B{~i~}$}. Incercati pe foaie sa vedeti cum funtioneaza. Aceasta ideea poate fi extinsa si in doua dimensiuni, construind $B$ astfel incat $A{~i,j~}$ = suma subtabloului din $B$ cu coltul in ({$0, 0$}) si ({$i, j$}), astfel (pt. {@ADUNA(x1,y1,x2,y2,v)@}):\r\n\r\n== code(c) |B[x1][y1] += v;\r\nB[x1][y2 + 1] -= v;\r\nB[x2 + 1][y1] -= v;\r\nB[x2 + 1][y2 + 1] += v;\r\n==\r\n\r\nPe cazul general, daca vrem sa facem operatii in $d$ dimensiuni vom avea o complexitate {$O(2^d^)$}. Reamintesc ca aceasta metoda este eficienta doar cand se vrea afisata vectorul/matricea/etc. doar la sfarsitul operatiilor sau sunt foarte putine interogari ale valorilor elementelor, deoarece aflarea unui element este o operatie foarte ineficienta: {$O(i)$} pentru a afla valorile elementelor pana la pozitia $i$.\r\n\r\nh2. Grafuri cu liste de adiacenta (ideea originala de la Radu Berinde)\r\n\r\nSe stie (sau ar trebui sa se stie!) ca lucrul cu pointerii este foarte incet... astfel, cand retinem un graf rar (numar mare de noduri, numar mic de muchii) cu pointeri (vezi mai jos) incetinim foarte mult programul.\r\n\r\n== code(c) |\r\nstruct list\r\n{\r\n    int n;\r\n    struct list *next;\r\n}\r\ntypedef struct list list;\r\n==\r\n\r\nIn contiuare vom prezenta o metoda care este de $3-4$ ori mai rapida (adica parcurgerile DF , BF sau altii algoritmi ruleaza de $3-4$ ori mai rapid cand graful este stocat astfel), dar are ca dezavantaj necesitatea de a citi de doua ori fisierul de intrare.\r\n\r\n== code(c) |\r\n#include <stdlib.h>\r\n#include <stdio.h>\r\n\r\nint N, M, *G[N], Deg[N];\r\n\r\nint main(void)\r\n{\r\n    int i, j;\r\n \r\n    freopen(\"in.txt\", \"r\", stdin);\r\n    scanf(\"%d %d\", &N, &M);\r\n    for (; M > 0; M--)\r\n    {\r\n        scanf(\"%d %d\", &i, &j);\r\n        Deg[i - 1]++, Deg[j - 1]++;\r\n    }\r\n    for (i = 0; i < N; Deg[i++] = 0)\r\n        G[i] = (int *) malloc(Deg[i]*sizeof(int));\r\n    fseek(stdin, 0, SEEK_SET);\r\n    scanf(\"%d %d\", &N, &M);\r\n    for (; M > 0; M--)\r\n    {\r\n        scanf(\"%d %d\", &i, &j);\r\n        i--, j--;\r\n        G[i][Deg[i]++] = j,\r\n            G[j][Deg[j]++] = i;\r\n    }\r\n\r\n    return 0;\r\n}\r\n==\r\n\r\nSporul de viteza se datoreaza faptului ca se folosesc vectori in loc de pointeri si struct-uri. Daca ne permite memoria putem evita citirea de doua ori a fisierul prin pastrarea muchiilor intr-o lista de muchii si apoi, dupa calcularea gradelor, inserarea muchiilor in liste. Pentru a demonstra eficienta acestei metode faceti urmatorul test: implementati o sursa cu pointeri si struct si implementati un BF, apoi scrieti codul de mai sus cu urmatoarele modificari:\r\n\r\n== code(c) |\r\n...\r\nfor (i = 0; i < N; i++)\r\n{\r\n      G[i] = (int *) malloc((Deg[i]+1)*sizeof(int));\r\n      G[i][Deg[i]] = -1;\r\n      Deg[i] = 0;\r\n}\r\n...\r\n==\r\n\r\nsi implementati BF astfel:\r\n\r\n== code(c) |\r\nvoid BF()\r\n{\r\n      int Q[N], ql, qr, *p;\r\n      char U[N];\r\n      memset(U, 0, sizeof(U));\r\n      U[Q[ql = qr = 0] = n] = 1;\r\n      for (; ql <= qr; ql++)\r\n              for (p = G[Q[ql]]; *p != -1; p++)\r\n                      if (!U[*p]) U[Q[++qr] = *p] = 1;\r\n}\r\n==\r\n\r\nApoi, incercati sa vedeti diferenta de timp intre cele doua programe... impresionant, nu?\r\n\r\n\r\n\r\nh2. Numere mari (ideea originala de la Radu Berinde)\r\n\r\nIn continuare voi prezenta cum se pot realiza operatii pe numere mari cu foarte putine linii de cod. In general, multi programatori se complica la aceste operatii, desi nu este nevoie! Vom considera ca numerele mari sunt vectori in care elementul de indice $0$ indica lungimea numarului, iar cifrele sunt retinute in ordinea inversa decat cea a citirii.\r\n\r\nh3. Suma a doua numere mari\r\n\r\n== code(c) |\r\nvoid add(int A[], int B[])\r\n{\r\n      int i, t = 0;\r\n      for (i=1; i<=A[0] || i<=B[0] || t; i++, t/=10)\r\n              A[i] = (t += A[i] + B[i]) % 10;\r\n      A[0] = i - 1;\r\n}\r\n==\r\n\r\nh3. Inmultirea unui numar mare cu un numar mic\r\n\r\n== code(c) |\r\nvoid mul(int A[], int B)\r\n{\r\n      int i, t = 0;\r\n      for (i = 1; i <= A[0] || t; i++, t /= 10)\r\n              A[i] = (t += A[i] * B) % 10;\r\n      A[0] = i - 1;\r\n}\r\n==\r\n\r\nh3. Inmultirea unui numar mare cu un numar mare\r\n\r\n== code(c) |\r\nvoid mul(int A[], int B[])\r\n{\r\n      int i, j, t, C[NR_CIFRE];\r\n      memset(C, 0, sizeof(C));\r\n      for (i = 1; i <= A[0]; i++)\r\n      {\r\n              for (t=0, j=1; j <= B[0] || t; j++, t/=10)\r\n                      C[i+j-1]=(t+=C[i+j-1]+A[i]*B[j])%10;\r\n              if (i + j - 2 > C[0]) C[0] = i + j - 2;\r\n      }\r\n      memcpy(A, C, sizeof(C));\r\n}\r\n==\r\n\r\nh3. Scaderea a doua numere mari\r\n\r\n== code(c) |\r\nvoid sub(int A[], int B[])\r\n{\r\n      int i, t = 0;\r\n      for (i = 1; i <= A[0]; i++)\r\n              A[i] += (t = (A[i] -= B[i] + t) < 0) * 10;\r\n      for (; A[0] > 1 && !A[A[0]]; A[0]--);\r\n}\r\n==\r\n\r\nh3. Impartirea unui numar mare la un numar mic\r\n\r\n== code(c) |\r\nvoid div(int A[], int B)\r\n{\r\n      int i, t = 0;\r\n      for (i = A[0]; i > 0; i--, t %= B)\r\n              A[i] = (t = t * 10 + A[i]) / B;\r\n      for (; A[0] > 1 && !A[A[0]]; A[0]--);\r\n}\r\n==\r\n\r\nh3. Restul unui numar mare la un numar mic\r\n\r\n== code(c) |\r\nint mod(int A[], int B)\r\n{\r\n      int i, t = 0;\r\n      for (i = A[0]; i > 0; i--)\r\n              t = (t * 10 + A[i]) % B;\r\n      return t;\r\n}\r\n==\r\n\r\nh2(#AVL). AVL-uri (ideea originala de la Radu Berinde - again)\r\n\r\nAVL-urile sunt arbori de cautare echilibrati care au complexitate O(lg n) pe operatiile de inserare, stergere si cautare. Pentru mai multe detalii cautati cartea \"Arbori\" pe [2]site-ul doamnei profesoare Emanuela Cerchez. In continuare voi prezenta o metoda destul de simpla de a implementa aceastra structura de date in timp de concurs. Enjoy!\r\n\r\n== code(c) |\r\n#define max(a, b) ((a) > (b) ? (a) : (b))\r\n#define geth(n) (n->h = 1 + max(n->l->h, n->r->h))\r\n\r\nstruct node\r\n{\r\n      int key, h;\r\n      struct node *l, *r;\r\n} *R, *NIL;\r\ntypedef struct node node;\r\n\r\nvoid init(void)\r\n{\r\n      R = NIL = (node *) malloc(sizeof(node));\r\n      NIL->key = NIL->h = 0,\r\n              NIL->l = NIL->r = NULL;\r\n}\r\n\r\nnode* rotleft(node *n)\r\n{\r\n      node *t = n->l;\r\n\r\n      n->l = t->r, t->r = n,\r\n              geth(n), geth(t);\r\n      return t;\r\n}\r\n\r\nnode* rotright(node *n)\r\n{\r\n      node *t = n->r;\r\n \r\n      n->r = t->l, t->l = n,\r\n              geth(n), geth(t);\r\n      return t;\r\n}\r\n\r\nnode* balance(node *n)\r\n{\r\n      geth(n);\r\n      if (n->l->h > n->r->h + 1)\r\n      {\r\n              if (n->l->r->h > n->l->l->h)\r\n                      n->l = rotright(n->l);\r\n              n = rotleft(n);\r\n      }\r\n      else\r\n              if (n->r->h > n->l->h + 1)\r\n              {\r\n                      if (n->r->l->h > n->r->r->h)\r\n                              n->r = rotleft(n->r);\r\n                      n = rotright(n);\r\n              }\r\n      return n;\r\n}\r\n\r\nnode* insert(node *n, int key)\r\n{\r\n      if (n == NIL)\r\n      {\r\n              n = (node *) malloc(sizeof(node));\r\n              n->key = key, n->h = 1, n->l = n->r = NIL;\r\n              return n;\r\n      }\r\n      if (key < n->key)\r\n              n->l = insert(n->l, key);\r\n      else\r\n              n->r = insert(n->r, key);\r\n      return balance(n);\r\n}\r\n\r\nnode* erase(node *n, int key)\r\n{\r\n      node *t;\r\n      if (n == NIL) return n;\r\n      if (n->key == key)\r\n      {\r\n              if (n->l == NIL || n->r == NIL)\r\n              {\r\n                      t = n->l == NIL ? n->r : n->l;\r\n                      free(n); return t;\r\n              }\r\n              else\r\n              {\r\n                      for (t = n->r; t->l != NIL; t = t->l);\r\n                      n->key = t->key,\r\n                              n->r = erase(n->r, t->key);\r\n                      return balance(n);\r\n              }\r\n      }\r\n      if (key < n->key)\r\n              n->l = erase(n->l, key);\r\n      else\r\n              n->r = erase(n->r, key);\r\n      return balance(n);\r\n}\r\n\r\nint search(node *n, int key)\r\n{\r\n      if (n == NIL) return 0;\r\n      if (n->key == key) return 1;\r\n      if (key < n->key)\r\n              return search(n->l, key);\r\n      else\r\n              return search(n->r, key);\r\n}\r\n==\r\n\r\nAici se termina acest articol. Am incercat sa pun accentul pe simplitate si eficienta, si cred ca am reusit acest lucru. Sper ca ati invatat cate ceva din el si recomand sa luati fiecare bucata in parte si sa incercati sa implementati efectiv ca sa intelegi mai bine. Bafta la concursuri tuturor! ;)\r\n',2044,'public',3673,NULL),('multe-smenuri-de-programare-in-cc-si-nu-numai','Multe \"smenuri\" de programare in C/C++... si nu numai!','2004-11-10 00:00:00','2009-04-09 15:30:44','h1. Multe \"smenuri\" de programare in C/C++... si nu numai!\r\n\r\n(Categoria _Limbaje de programare_, Autor _Mircea Pasoi_)\r\n\r\nAcest articol vine ca o completare a articolului scris de Alexandru Mosoi, prezentand noi trucuri care le-am folosit si m-au ajutat mult. O mare parte din acestea le-am invatat din sursele lui Radu Berinde (cred ca stiti cu totii cine este), asadar ii multumesc!\r\n\r\nh2. Array-uri neindexate de la 0\r\n\r\nUn dezavantaj fata de Pascal este faptul ca in C nu putem avea expresii de genul {@A[-100]@} unde $A$ este un vector. Dar acest lucru se poate remedia. Spre exemplu, daca vrem sa facem un vector $A$ cu elemente de la $-100$ la $100$ procedam astfel:\r\n\r\n== code(c) |\r\nint A[201];\r\n#define A (A + 100)\r\n==\r\n\r\nh2. Fisiere de intrare si iesire\r\n\r\nFolositi {@freopen()@} in loc de {@fopen()@} deoarece este mai comod, in special la concursurile in care intrare si iesirea sunt standard.\r\n\r\n== code(c) |\r\nfreopen(\"in.txt\", \"r\", stdin);\r\nfreopen(\"out.txt\", \"w\", stdout);\r\n==\r\n\r\nh2. Cautare binara (ideea originala de la Mihai Patrascu)\r\n\r\nUrmatorul cod este de aproximativ $4$ ori mai rapid (am testat cu cautare binara ca in manual) , mai usor de inteles, mai flexibil si mai scurt... ce ati putea dori mai mult?\r\n\r\n== code(c) |\r\nint N, A[N];\r\n\r\nint binary_search(int val)\r\n{\r\n    int i, step;\r\n    for (step = 1; step < N; step <<= 1);\r\n    for (i = 0; step; step >>= 1)\r\n        if (i + step < N && A[i + step] <= val)\r\n           i += step;\r\n    return i;\r\n}\r\n==\r\n\r\nProcedura de mai sus face cautarea binara folosind puteri a lui $2$ in ordine descrescatoare, practic incerc sa determin fiecare bit al rezultatului.\r\n\r\nh2. Impartire in bucati de marime $sqrt(n)$ (cunoscut si ca \"smenul lui Bogdan Batog\")\r\n\r\nSa presupunem ca avem un vector de lungime n cu numere reale pe care se fac urmatoarele operatii:\r\n{@ADUNA(st, dr, x)@} - toate elementele cu indicii intre $st$ si $dr$ isi cresc valoarea cu $x$\r\n{@SUMA(st, dr)@} - returneaza suma elementelor cu indicii intre $st$ si $dr$\r\n\r\nPentru cei ce cunosc arbori de intervale, rezolvarea acestei probleme in $O(lg n)$ per operatie este o munca usoara, dar presupunand ca nu stim aceasta structura putem folosi urmatorul truc: vom construi un al doilea vector de lungime $sqrt(n)$ care retine suma elementelor pe bucati de lungime {$sqrt(n)$}. Pentru a face o operatie pe un interval [{$st, dr$}] vom imparti acest interval in bucati de $sqrt(n)$ a caror actualizare o facem in vectorul $B$ si elementele care raman in margine in vectorul {$A$}. De exemplu pe vectorul {$A{~0..15~}$} vom avea vectorul {$B{~0..3~}$}. Pentru a actualiza de exemplu [{$2, 12$}] vom actualiza {$B{~1~}$} (care corespunde lui [{$4..7$}]), {$B{~2~}$} (pentru [{$8..11$}]) si {$A{~2~}$}, {$A{~3~}$}, {$A{~12~}$} (elementele din margini). Cum sunt maxim $sqrt(n)$ elemente de actualizat in $B$ si pe margini nu vom actualiza niciodata mai mult de $2 * sqrt(n)$ elemente putem concluziona ca operatiile vor avea complexitate {$O(sqrt(n))$}.\r\n\r\nDaca am avea aceeasi problema dar in doua dimensiuni, am putea face acelasi \"smen\" pentru fiecare linie pentru o complexitate $O(n*sqrt(n))$ per operatie, sau cu arbori de intervale pe fiecare linie {$O(n*lg n)$}. Putem, de asemenea obtine o complexitate $O(n)$ folosind urmatoarea impartire:\r\n$A$ - pentru bucati $1 * 1$\r\n$B$ - pentru bucati $sqrt(n) * sqrt(n)$\r\n$C$ - pentru bucati $1 * sqrt(n)$\r\n$D$ - pentru bucati $sqrt(n) * 1$\r\nAcest mod de reprezentare este o extindere directa a aceluiasi smen in doua dimensiuni. Aceasta idee poate fi folosita si pentru alte operatii: inmultire, minim, maxim, etc. In general, orice se poate rezolva cu acest \"smen\" se poate obtine la o complexitate mai buna cu arbori de intervale, dar merita sa stiti si aceasta ideea deoarece de multe ori scuteste din efortul de implementare, desi se pierde din viteza... alegerea voastra! ;)\r\n\r\nh2. LCA in $O(sqrt(n))$ (ideea originala de la Radu Berinde)\r\n\r\nDaca nu stiti ce este LCA, va recomand sa cititi \'articolul\':lowest-common-ancestor lui Emilian Miron din cadrul site-ului pentru a va documenta. In continuare vom prezenta un algoritm mai ineficient, dar foarte usor de implementat. Consideram arborele si atribuim fiecarui nod o inaltime. Vom imparti arborele in $sqrt(H)$ intervale in functie de inaltime, unde $H$ e inaltimea maxima (de exemplu la $H=9$ nodurile cu inaltimi intre $0$ si $2$ vor forma un interval, [{$3..5$}] alt interval si ultimul interval de inaltimi [{$6..8$}]). Astfel, pentru fiecare nod, pe langa tatal sau, vom retine si tatal din intervalul de mai sus, printr-o parcurgere DF. In continuare, codul:\r\n\r\n$H$ se calculeaza inainte sau poate fi constant\r\n$T$ sunt tatii nodului si $N$ numarul de noduri\r\n\r\n== code(c) |\r\nvoid DF(int n, int t2, int lev)\r\n{\r\n    int i;\r\n    T2[n] = t2, Lev[n] = lev;\r\n    if (lev % H == 0) t2 = n;\r\n    for (i = 0; i < N; i++)\r\n        if (T[i] == n) DF(i, t2, lev+1);\r\n}\r\n==\r\n\r\nOperatia de LCA se va realiza apoi foarte usor, urcand pe tatii din intervale, pana se ajunge la doua noduri in acelasi interval, apoi folosindu-se metoda clasica. Cod:\r\n\r\n== code(c) |\r\nint LCA(int x, int y)\r\n{\r\n    while (T2[x] != T2[y])\r\n        if (Lev[x] > Lev[y])\r\n            x = T2[x];\r\n        else\r\n            y = T2[y];\r\n    while (x != y)\r\n        if (Lev[x] > Lev[y])\r\n            x = T[x];\r\n        else\r\n            y = T[y];\r\n    return x;\r\n}\r\n==\r\n\r\n\r\nh2. LCA in $O(lg^2^ n)$\r\n\r\nAceeasi problema, dar o alta rezolvare. Vom construi o matrice $A{~i,j~}$ cu semnificatia $A{~i,j~}$ = al {$2^i^$}-lea tata al nodului {$j$}. Folosind aceasta matrice putem cauta binar ({$O(lg n)$}) nivelul pe care s-ar putea afla LCA-ul a doua noduri si sa determinam daca nodul ales este corect - adica daca nodul situat la acel nivel este acelasi pentru cele doua noduri pentru care se face LCA ({$O(lg n)$} cu matricea de mai sus). Complexitate finala $O(lg^2^ n)$ si $O(n*lg n)$ memorie.\r\n\r\nh2. For-uri \"complicate\"\r\n\r\nfor-ul in C/C++ este foarte flexibil si poate ajuta foarte mult in compactarea codului, deci si a timpului de implementare. In continuare vom prezenta algoritmul merge sort (sortare prin interclasare) scris in cateva linii (putine, zic eu!):\r\n\r\n== code(c) |\r\nint N, A[N], B[N];\r\nvoid merge_sort(int l, int r)\r\n{\r\n    int m = (l + r) >> 1, i, j, k;\r\n    if (l == r) return;\r\n    merge_sort(l, m);\r\n    merge_sort(m + 1, r);\r\n    for (i=l, j=m+1, k=l; i<=m || j<=r; )\r\n        if (j > r || (i <= m && A[i] < A[j]))\r\n            B[k++] = A[i++];\r\n        else\r\n            B[k++] = A[j++];\r\n    for (k = l; k <= r; k++) A[k] = B[k];\r\n}\r\n==\r\n\r\nh2. Recomandari generale\r\n\r\n# Programare dinamica cu memorizare: mult mai simplu si uneori chiar mai rapida cand nu ne trebuie tot array-ul\r\n# Algoritmi randomizati: de multe ori mai usor de implementat si mai eficienti, mai bine decat cei euristici, dar necesita o analiza mult mai atenta a performantei. Exemple calsice: quicksort, statistici de ordine\r\n\r\nh2. \"Smenul lui Mars\" (Marius Andrei)\r\n\r\nConsideram urmatoarea problema: se da un vector $A$ de $N$ elemente pe care se fac $M$ astfel de operatii: {@ADUNA(st, dr, x)@} - toate elementele cu indicii intre $st$ si $dr$ ({$0 &le; st &le; dr &lt; N$}) isi cresc valoarea cu {$x$} . La sfarsit trebuie sa se afiseze vectorul rezultat. In continuarea vom descrie o metoda care ne da un timp de rulare de $O(1)$ pentru operatia $ADUNA$ si $O(N)$ pentru a determina toate elementele din vector. Vom construi un al doilea vector $B$ de $N+1$ elemente, cu proprietatea ca {$A{~i~} = B{~0~} + B{~1~} + ... B{~i~}$}. Astfel, o operatie {@ADUNA(st, dr, x)@} devine:\r\n\r\n== code(c) |B[st] += x;\r\nB[dr + 1] -= x;\r\n==\r\n\r\nDa, este chiar asa de simplu! Pentru a determina un element A{~i~} vom aduna pur si simplu {$B{~0~} + B{~1~} + ... B{~i~}$}. Incercati pe foaie sa vedeti cum funtioneaza. Aceasta ideea poate fi extinsa si in doua dimensiuni, construind $B$ astfel incat $A{~i,j~}$ = suma subtabloului din $B$ cu coltul in ({$0, 0$}) si ({$i, j$}), astfel (pt. {@ADUNA(x1,y1,x2,y2,v)@}):\r\n\r\n== code(c) |B[x1][y1] += v;\r\nB[x1][y2 + 1] -= v;\r\nB[x2 + 1][y1] -= v;\r\nB[x2 + 1][y2 + 1] += v;\r\n==\r\n\r\nPe cazul general, daca vrem sa facem operatii in $d$ dimensiuni vom avea o complexitate {$O(2^d^)$}. Reamintesc ca aceasta metoda este eficienta doar cand se vrea afisata vectorul/matricea/etc. doar la sfarsitul operatiilor sau sunt foarte putine interogari ale valorilor elementelor, deoarece aflarea unui element este o operatie foarte ineficienta: {$O(i)$} pentru a afla valorile elementelor pana la pozitia $i$.\r\n\r\nh2. Grafuri cu liste de adiacenta (ideea originala de la Radu Berinde)\r\n\r\nSe stie (sau ar trebui sa se stie!) ca lucrul cu pointerii este foarte incet... astfel, cand retinem un graf rar (numar mare de noduri, numar mic de muchii) cu pointeri (vezi mai jos) incetinim foarte mult programul.\r\n\r\n== code(c) |\r\nstruct list\r\n{\r\n    int n;\r\n    struct list *next;\r\n}\r\ntypedef struct list list;\r\n==\r\n\r\nIn contiuare vom prezenta o metoda care este de $3-4$ ori mai rapida (adica parcurgerile DF , BF sau altii algoritmi ruleaza de $3-4$ ori mai rapid cand graful este stocat astfel), dar are ca dezavantaj necesitatea de a citi de doua ori fisierul de intrare.\r\n\r\n== code(c) |\r\n#include <stdlib.h>\r\n#include <stdio.h>\r\n\r\nint N, M, *G[N], Deg[N];\r\n\r\nint main(void)\r\n{\r\n    int i, j;\r\n \r\n    freopen(\"in.txt\", \"r\", stdin);\r\n    scanf(\"%d %d\", &N, &M);\r\n    for (; M > 0; M--)\r\n    {\r\n        scanf(\"%d %d\", &i, &j);\r\n        Deg[i - 1]++, Deg[j - 1]++;\r\n    }\r\n    for (i = 0; i < N; Deg[i++] = 0)\r\n        G[i] = (int *) malloc(Deg[i]*sizeof(int));\r\n    fseek(stdin, 0, SEEK_SET);\r\n    scanf(\"%d %d\", &N, &M);\r\n    for (; M > 0; M--)\r\n    {\r\n        scanf(\"%d %d\", &i, &j);\r\n        i--, j--;\r\n        G[i][Deg[i]++] = j,\r\n            G[j][Deg[j]++] = i;\r\n    }\r\n\r\n    return 0;\r\n}\r\n==\r\n\r\nSporul de viteza se datoreaza faptului ca se folosesc vectori in loc de pointeri si struct-uri. Daca ne permite memoria putem evita citirea de doua ori a fisierul prin pastrarea muchiilor intr-o lista de muchii si apoi, dupa calcularea gradelor, inserarea muchiilor in liste. Pentru a demonstra eficienta acestei metode faceti urmatorul test: implementati o sursa cu pointeri si struct si implementati un BF, apoi scrieti codul de mai sus cu urmatoarele modificari:\r\n\r\n== code(c) |\r\n...\r\nfor (i = 0; i < N; i++)\r\n{\r\n      G[i] = (int *) malloc((Deg[i]+1)*sizeof(int));\r\n      G[i][Deg[i]] = -1;\r\n      Deg[i] = 0;\r\n}\r\n...\r\n==\r\n\r\nsi implementati BF astfel:\r\n\r\n== code(c) |\r\nvoid BF()\r\n{\r\n      int Q[N], ql, qr, *p;\r\n      char U[N];\r\n      memset(U, 0, sizeof(U));\r\n      U[Q[ql = qr = 0] = n] = 1;\r\n      for (; ql <= qr; ql++)\r\n              for (p = G[Q[ql]]; *p != -1; p++)\r\n                      if (!U[*p]) U[Q[++qr] = *p] = 1;\r\n}\r\n==\r\n\r\nApoi, incercati sa vedeti diferenta de timp intre cele doua programe... impresionant, nu?\r\n\r\n\r\n\r\nh2. Numere mari (ideea originala de la Radu Berinde)\r\n\r\nIn continuare voi prezenta cum se pot realiza operatii pe numere mari cu foarte putine linii de cod. In general, multi programatori se complica la aceste operatii, desi nu este nevoie! Vom considera ca numerele mari sunt vectori in care elementul de indice $0$ indica lungimea numarului, iar cifrele sunt retinute in ordinea inversa decat cea a citirii.\r\n\r\nh3. Suma a doua numere mari\r\n\r\n== code(c) |\r\nvoid add(int A[], int B[])\r\n{\r\n      int i, t = 0;\r\n      for (i=1; i<=A[0] || i<=B[0] || t; i++, t/=10)\r\n              A[i] = (t += A[i] + B[i]) % 10;\r\n      A[0] = i - 1;\r\n}\r\n==\r\n\r\nh3. Inmultirea unui numar mare cu un numar mic\r\n\r\n== code(c) |\r\nvoid mul(int A[], int B)\r\n{\r\n      int i, t = 0;\r\n      for (i = 1; i <= A[0] || t; i++, t /= 10)\r\n              A[i] = (t += A[i] * B) % 10;\r\n      A[0] = i - 1;\r\n}\r\n==\r\n\r\nh3. Inmultirea unui numar mare cu un numar mare\r\n\r\n== code(c) |\r\nvoid mul(int A[], int B[])\r\n{\r\n      int i, j, t, C[NR_CIFRE];\r\n      memset(C, 0, sizeof(C));\r\n      for (i = 1; i <= A[0]; i++)\r\n      {\r\n              for (t=0, j=1; j <= B[0] || t; j++, t/=10)\r\n                      C[i+j-1]=(t+=C[i+j-1]+A[i]*B[j])%10;\r\n              if (i + j - 2 > C[0]) C[0] = i + j - 2;\r\n      }\r\n      memcpy(A, C, sizeof(C));\r\n}\r\n==\r\n\r\nh3. Scaderea a doua numere mari\r\n\r\n== code(c) |\r\nvoid sub(int A[], int B[])\r\n{\r\n      int i, t = 0;\r\n      for (i = 1; i <= A[0]; i++)\r\n              A[i] += (t = (A[i] -= B[i] + t) < 0) * 10;\r\n      for (; A[0] > 1 && !A[A[0]]; A[0]--);\r\n}\r\n==\r\n\r\nh3. Impartirea unui numar mare la un numar mic\r\n\r\n== code(c) |\r\nvoid div(int A[], int B)\r\n{\r\n      int i, t = 0;\r\n      for (i = A[0]; i > 0; i--, t %= B)\r\n              A[i] = (t = t * 10 + A[i]) / B;\r\n      for (; A[0] > 1 && !A[A[0]]; A[0]--);\r\n}\r\n==\r\n\r\nh3. Restul unui numar mare la un numar mic\r\n\r\n== code(c) |\r\nint mod(int A[], int B)\r\n{\r\n      int i, t = 0;\r\n      for (i = A[0]; i > 0; i--)\r\n              t = (t * 10 + A[i]) % B;\r\n      return t;\r\n}\r\n==\r\n\r\nh2(#AVL). AVL-uri (ideea originala de la Radu Berinde - again)\r\n\r\nAVL-urile sunt arbori de cautare echilibrati care au complexitate O(lg n) pe operatiile de inserare, stergere si cautare. Pentru mai multe detalii cautati cartea \"Arbori\" pe [2]site-ul doamnei profesoare Emanuela Cerchez. In continuare voi prezenta o metoda destul de simpla de a implementa aceastra structura de date in timp de concurs. Enjoy!\r\n\r\n== code(c) |\r\n#define max(a, b) ((a) > (b) ? (a) : (b))\r\n#define geth(n) (n->h = 1 + max(n->l->h, n->r->h))\r\n\r\nstruct node\r\n{\r\n      int key, h;\r\n      struct node *l, *r;\r\n} *R, *NIL;\r\ntypedef struct node node;\r\n\r\nvoid init(void)\r\n{\r\n      R = NIL = (node *) malloc(sizeof(node));\r\n      NIL->key = NIL->h = 0,\r\n              NIL->l = NIL->r = NULL;\r\n}\r\n\r\nnode* rotleft(node *n)\r\n{\r\n      node *t = n->l;\r\n\r\n      n->l = t->r, t->r = n,\r\n              geth(n), geth(t);\r\n      return t;\r\n}\r\n\r\nnode* rotright(node *n)\r\n{\r\n      node *t = n->r;\r\n \r\n      n->r = t->l, t->l = n,\r\n              geth(n), geth(t);\r\n      return t;\r\n}\r\n\r\nnode* balance(node *n)\r\n{\r\n      geth(n);\r\n      if (n->l->h > n->r->h + 1)\r\n      {\r\n              if (n->l->r->h > n->l->l->h)\r\n                      n->l = rotright(n->l);\r\n              n = rotleft(n);\r\n      }\r\n      else\r\n              if (n->r->h > n->l->h + 1)\r\n              {\r\n                      if (n->r->l->h > n->r->r->h)\r\n                              n->r = rotleft(n->r);\r\n                      n = rotright(n);\r\n              }\r\n      return n;\r\n}\r\n\r\nnode* insert(node *n, int key)\r\n{\r\n      if (n == NIL)\r\n      {\r\n              n = (node *) malloc(sizeof(node));\r\n              n->key = key, n->h = 1, n->l = n->r = NIL;\r\n              return n;\r\n      }\r\n      if (key < n->key)\r\n              n->l = insert(n->l, key);\r\n      else\r\n              n->r = insert(n->r, key);\r\n      return balance(n);\r\n}\r\n\r\nnode* erase(node *n, int key)\r\n{\r\n      node *t;\r\n      if (n == NIL) return n;\r\n      if (n->key == key)\r\n      {\r\n              if (n->l == NIL || n->r == NIL)\r\n              {\r\n                      t = n->l == NIL ? n->r : n->l;\r\n                      free(n); return t;\r\n              }\r\n              else\r\n              {\r\n                      for (t = n->r; t->l != NIL; t = t->l);\r\n                      n->key = t->key,\r\n                              n->r = erase(n->r, t->key);\r\n                      return balance(n);\r\n              }\r\n      }\r\n      if (key < n->key)\r\n              n->l = erase(n->l, key);\r\n      else\r\n              n->r = erase(n->r, key);\r\n      return balance(n);\r\n}\r\n\r\nint search(node *n, int key)\r\n{\r\n      if (n == NIL) return 0;\r\n      if (n->key == key) return 1;\r\n      if (key < n->key)\r\n              return search(n->l, key);\r\n      else\r\n              return search(n->r, key);\r\n}\r\n==\r\n\r\nAici se termina acest articol. Am incercat sa pun accentul pe simplitate si eficienta, si cred ca am reusit acest lucru. Sper ca ati invatat cate ceva din el si recomand sa luati fiecare bucata in parte si sa incercati sa implementati efectiv ca sa intelegi mai bine. Bafta la concursuri tuturor! ;)\r\n',6953,'public',3673,NULL),('probleme-cu-puncte-laticiale','Probleme cu puncte laticiale','2009-02-09 21:51:10','2009-04-11 12:41:47','h1. Probleme cu puncte laticiale\r\n\r\n(Categoria _Matematică_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 25em}*{text-align:center;} *Conţinut*\r\n* \'Introducere\':probleme-cu-puncte-laticiale#introducere\r\n* \'Problema 1\':probleme-cu-puncte-laticiale#problema1\r\n* \'Problema 2\':probleme-cu-puncte-laticiale#problema2\r\n* \'Problema 3: Copaci\':probleme-cu-puncte-laticiale#problema3\r\n* \'Problema 4\':probleme-cu-puncte-laticiale#problema4\r\n* \'Problema 5: Counting triangles\':probleme-cu-puncte-laticiale#problema5\r\n* \'Problema 6: Dreptunghiuri\':probleme-cu-puncte-laticiale#problema6\r\n* \'Problema 7: Paralelograme\':probleme-cu-puncte-laticiale#problema7\r\n* \'Concluzii\':probleme-cu-puncte-laticiale#concluzii\r\n* \'Bibliografie\':probleme-cu-puncte-laticiale#bibliografie\r\n\r\nh2(#introducere). Introducere\r\n\r\nArticolul de faţă se va concentra pe probleme în care vor apărea puncte de coordonate întregi care sunt numite puncte laticiale. Sursele [1] şi [2] menţionate în \'bibliografie\':probleme-cu-puncte-laticiale#bibliografie conţin câte un capitol despre puncte laticiale care, deşi sunt mai riguros tratate decât în acest articol, pot fi interesante pentru un elev în pregătirea pentru olimpiadă. Să vedem acum câteva probleme ce au apărut pe la concursurile de programare.\r\n\r\nh2(#problema1). Problema 1\r\n\r\nbq. Să se determine numărul de puncte de coordonate întregi prin care trece segmentul determinat de punctele $(0, 0)$ şi $(N, M)$. De exemplu, pentru $N = 9$ şi $M = 12$ pe segment vor fi $4$ puncte de coordonate întregi.\r\n\r\np=. !probleme-cu-puncte-laticiale?img1.JPG 70%!\r\n\r\nh3. Rezolvare\r\n\r\nPutem considera doar cazurile în care $0 &le; N &le; M$. Dacă $N = 0$ atunci, evident, avem $M + 1$ puncte pe segment. Astfel, trebuie să rezolvăm doar cazul în care $1 &le; N &le; M$.\r\nEvident că orice punct $(x, y)$, pentru a fi pe segmentul nostru, trebuie să satisfacă ecuaţia $y = (M / N) * x$. Această ecuaţie are ca soluţie un număr natural doar dacă $M * x$ se divide cu $N$. De aici, dacă $D = cmmdc(M, N)$ atunci $x$ se divide cu $N / D$. Obţinem, astfel, $x$ de forma $k * (N / D)$, de unde rezultă că $y$ este de forma $y = k * (M / D)$. Pentru ca punctul $(x, y)$ să aparţină segmentului, trebuie ca $0 &le; x &le; N$ şi $0 &le; y &le; M$, şi, înlocuind în a doua inegalitate pe $y$ avem $0 &le; k &le; D$. În concluzie, numărul de puncte de pe un segment de la $(0, 0)$ la $(N, M)$ este egal cu cel mai mare divizor comun al numerelor $M$ şi $N$ la care adăugăm $1$. Putem determina acest număr în complexitate $O(log (N + M))$.\r\n\r\nh2(#problema2). Problema 2\r\n\r\nbq. Se dă un triunghi cu vârfurile în puncte laticiale. Se cere să se determine numărul de puncte de coordonate întregi ce se află în interiorul triunghiului sau pe laturile lui. De exemplu, un triunghi cu vârfurile de coordonate $(1, 5)$, $(5, 1)$ şi $(6, 6)$ are $16$ puncte în interior.\r\n\r\np=. !probleme-cu-puncte-laticiale?img2.JPG!\r\n\r\nh3. Rezolvare\r\n\r\nPentru un dreptunghi cu laturile paralele cu axele de coordonate de lungime $M$ şi lăţime $N$ avem că numărul de puncte situate strict în interiorul dreptunghiului este $(M - 1)*(N - 1)$, iar numărul de puncte situate pe laturile poligonului este $2M + 2N$. Dacă notăm cu $B$ numărul de puncte de pe laturi, cu $I$ numărul de puncte situate strict în interiorul unui dreptunghi şi cu $A$ aria dreptunghiului, observăm că $I + B/2 - 1 = (M - 1) * (N - 1) + M + N - 1 = M * N = A$.\r\nÎn cazul triunghiurilor dreptunghice ce au două catete vom vedea că această formulă se păstrează. Evident avem că $A = (M * N)/2$. Pe ipotenuza triunghiului vom avea $D$ puncte ({$D = cmmdc(M, N) + 1$}, dar aceasta nu ne interesează pe moment). Rezultă că numărul de puncte de pe laturile triunghiului este $B = M + N + D - 1$. Numărul de puncte $I$ din interiorul triunghiului este numărul de puncte din interiorul dreptunghiului $(M - 1) * (N - 1)$ din care se scad punctele interioare de pe diagonala $D - 2$, rezultatul împărţindu-se apoi la $2$. De aici avem $I = ((M - 1) * (N - 1) - D + 2) / 2$.\r\n\r\nVerificăm formula $I + B/2 - 1 = (M - 1) * (N - 1)/2 - D/2 + 1 + M/2 + N/2 + D/2 + 1/2 = (M * N)/2$. Deci formula se verifică şi pe astfel de triunghiuri.\r\n\r\nAcum ne uităm la cel mai mic dreptunghi ce conţine un triunghi oarecare. Acest dreptunghi poate fi împărţit în patru triunghiuri din care unul este cel iniţial, iar celelalte sunt trei triunghiuri dreptunghice pentru care catetele merg de-a lungul liniilor laticiale. Vom vedea că formula noastră se verifică şi pentru triunghiuri oarecare. Notăm cu $I{~d~}$ numărul de puncte interioare dreptunghiului, $A{~d~}$ aria dreptunghiului şi $B{~d~}$ numărul de puncte de pe laturile dreptunghiului, cu $I{~1~}$, $I{~2~}$, $I{~3~}$ numărul de puncte din interiorul celor trei triunghiuri dreptunghice, $B{~1~}$, $B{~2~}$, $B{~3~}$ numărul de puncte de pe laturile celor trei triunghiuri, iar $A{~1~}$, $A{~2~}$ şi $A{~3~}$ ariile celor trei triunghiuri. Avem că $I = I{~d~} - I{~1~} - I{~2~} - I{~3~} - B + 3$ (trebuie să eliminăm punctele de pe laturile triunghiului interior şi să avem grijă de vârfurile acestui triunghi), $B = B{~1~} + B{~2~} + B{~3~} - B{~d~}$ iar $A = A{~d~} - A{~1~} - A{~2~} - A{~3~}$. De aici avem că $I + B/2 - 1 = I{~d~} - I{~1~} - I{~2~} - I{~3~} - B{~1~}/2 - B{~2~}/2 - B{~3~}/2 + B{~d~}/2 - 1 + 3 = (I{~d~} + B{~d~}/2 - 1) - (I{~1~} + B{~1~}/2 - 1) - (I{~1~} + B{~1~}/2 - 1) - (I{~1~} + B{~1~}/2 - 1) = A{~d~} - A{~1~} - A{~2~} - A{~3~} = A$, deci egalitarea este valabilă şi pentru triunghiuri oarecare.\r\n\r\np=. !probleme-cu-puncte-laticiale?img3.JPG!\r\n\r\nAcum aria triunghiului cu vârfurile $(x1, y1)$, $(x2, y2)$, $(x3, y3)$ o putem afla uşor folosind \'formula lui Heron\':http://en.wikipedia.org/wiki/Heron%27s_formula sau folosind determinantul:\r\n<tex> \\displaystyle \\frac {1} {2} \\cdot | \\left| \\begin{array}{ccc}\r\nx_{1} & y_{1} & 1 \\\\\r\nx_{2} & y_{2} & 1 \\\\\r\nx_{3} & y_{3} & 1 \\end{array} \\right| |.  </tex>\r\n\r\nNumărul de puncte de pe laturile triunghiului poate fi determinat uşor folosind formula demonstrată în problema anterioară. Acum, folosind formula $I + B/2 - 1 = A$ putem afla numărul $I$ şi problema e rezolvată prin întoarcerea numărului $I + B$. Complexitatea rezolvării este $O(log N)$ unde $N$ este valoarea maximă a coordonatelor.\r\n\r\nh2(#problema3). Problema 3: \'Copaci\':problema/copaci (info{_arena_})\r\n\r\nbq. Se dă un poligon prin vârfurile sale aflate doar la coordonate numere naturale. Poligonul nu este neapărat convex. Se cere să se găsească numărul punctelor aflate strict în interiorul poligonului la coordonate numere întregi.\r\nDe exemplu, pentru poligonul dat prin vârfurile $(0, 4)$, $(0, 5)$, $(2, 7)$, $(2, 4)$, $(6, 6)$ şi $(4, 0)$ avem $12$ astfel de puncte.\r\n\r\np=. !probleme-cu-puncte-laticiale?img4.JPG 80%!\r\n\r\nh3. Rezolvare\r\n\r\nFormula $I + B/2 - 1 = A$ prezentată mai sus se numeşte \'Teorema lui Pick\':http://en.wikipedia.org/wiki/Pick%27s_theorem, iar ea este valabilă şi pentru poligoane oarecare. Acest fapt este adevărat pentru că orice poligon are o diagonală interioară care îl împarte în două poligoane distincte. Dacă notăm $I{~1~}$ şi $I{~2~}$ punctele interioare celor două poligoane, $B{~1~}$ şi $B{~2~}$ punctele de pe laturile celor două poligoane, $A{~1~}$ şi $A{~2~}$ ariile celor două poligoane şi $D$ numărul de puncte de coordonate întregi de pe diagonală, atunci, dacă egalitatea ar fi fost satisfăcută pentru cele două poligoane, am avea că $B{~1~} + B{~2~} = B + 2D - 2$, $I = I{~1~} + I{~2~} + D - 2$. De aici avem $A = A{~1~} + A{~2~} = I{~1~} + B{~1~}/2 - 1 + I{~2~} + B{~2~}/2 - 1 = I{~1~} + I{~2~} + B/2 + D - 1 - 2 = I + B/2 - 1$. Astfel putem demonstra prin inducţie că relaţia este satisfăcută pentru orice poligon.\r\n\r\nAria unui poligon poate fi calculată uşor folosind următoarea formulă: \r\n<tex> \\displaystyle A = \\sum_{i=1}^{n} (x_i \\cdot y_{i+1}-x_{i+1} \\cdot y_i) </tex>, unde punctul de indice $n + 1$ este primul punct. Astfel, obţinem un algoritm de complexitate $O(N log (Max_X + Max_Y))$.\r\n\r\nh2(#problema4). Problema 4 (Marele Premiu Paco, 2000)\r\n\r\nbq. Se dă o grilă de puncte laticiale de dimensiuni $N × N$. Se cere să se determine numărul de pătrate care se pot forma astfel încât vârfurile lor să aparţină punctelor din grilă. De exemplu, pe o grilă de dimensiuni $3 × 3$ există $6$ pătrate.\r\n\r\np=. !probleme-cu-puncte-laticiale?img5.JPG!\r\n\r\nh3. Rezolvare:\r\n\r\nUn pătrat cu $L$ puncte pe o latură, cu laturile paralele cu axele de coordonate, poate fi translatat în $(N - L + 1)*(N - L + 1)$ poziţii diferite pe grilă.\r\n\r\np=. !probleme-cu-puncte-laticiale?img6.JPG 70%!\r\n\r\nConsiderăm pentru un pătrat din mulţimea soluţiilor, dreptunghiul minim cu laturile paralele cu axele de coordonate ce conţine acest pătrat. Este uşor să vedem că acest dreptunghi este de fapt un pătrat. Într-un pătrat ce are $L$ puncte pe latură, înscrie $L - 2$ pătrate care nu au laturile paralele cu axele de coordonate. \r\n\r\np=. !probleme-cu-puncte-laticiale?img7.JPG 70%!\r\n\r\nAstfel, vedem că numărul total de pătrate pe o grilă $N * M$ este, succesiv:\r\n\r\n* <tex> \\displaystyle\\sum_{L=2}^{N} (N-L+1)(N-L+1)(L-1) = </tex>\r\n* <tex> = \\displaystyle\\sum_{L=1}^{N-1} (N-L)(N-L)L </tex>\r\n* <tex> = \\displaystyle\\sum_{L=1}^{N-1} L*N^2 - 2*L^2*N + L^3 </tex>\r\n* <tex> = \\displaystyle N^2 * \\sum_{L=1}^{N-1} L - 2 * N * \\sum_{L=1}^{N-1} L^2 + \\sum_{L=1}^{N-1} L^3 </tex>\r\n* <tex> = \\displaystyle N^2 * \\frac{N(N - 1)}{2} - 2 * N * \\frac{N(N - 1)(2N - 1)}{6} + \\left[\\frac{N(N - 1)}{2}\\right]^2 </tex>\r\n\r\nAm folosit formulele cunoscute din manualul de clasa a 10-a:\r\n\r\n* <tex> \\displaystyle\\sum_{k=1}^{n} k = \\frac{n(n+1)}{2} </tex>\r\n* <tex> \\displaystyle\\sum_{k=1}^{n} k^2 = \\frac{n(n+1)(2n+1)}{6} </tex>\r\n* <tex> \\displaystyle\\sum_{k=1}^{n} k^3 = \\left[\\frac{n(n+1)}{2}\\right]^2 </tex>\r\n\r\nAceastă soluţie are complexitatea $O(1)$, fiind o simplă formulă.\r\n\r\nh2(#problema5). Problema 5: \'Counting triangles\':http://acmicpc-live-archive.uva.es/nuevoportal/data/problem.php?p=3295 (ACM ICPC Asia, Dhaka 2005/2006) \r\n\r\nbq. Triunghiurile sunt poligoane cu trei laturi şi cu aria strict pozitivă. Triunghiurile laticiale sunt triunghiuri ce au vârfurile de coordonate întregi. În această problemă va trebui să găsiţi numărul de triunghiuri laticiale ce se pot găsi pe o grilă de dimensiuni $M * N$ $(1 &le; M, N &le; 1000)$. De exemplu, pe o grilă de dimensiuni $1 * 2$ găsim $18$ triunghiuri laticiale distincte după cum vedem în figură:\r\n\r\np=. !probleme-cu-puncte-laticiale?img14.JPG 70%!\r\n\r\nh3. Rezolvare\r\n\r\nPrima idee de rezolvare ar fi de a lua toate combinaţiile de trei puncte distincte dintre cele $N * M$ puncte şi apoi de a elimina oricare trei puncte coliniare, dar partea a doua pare greu de realizat în mod eficient. Vom număra, asemănător rezolvării de mai sus, numărul de triunghiuri înscrise într-un dreptunghi paralel cu axele de coordonate. Ulterior, acel dreptunghi îl vom putea translata pe grila de puncte laticiale şi astfel vom putea număra toate triunghiurile posibile.\r\n\r\np=. !probleme-cu-puncte-laticiale?img9.JPG 70%!\r\n\r\nOricum ar fi un triunghi situat într-un dreptunghi ce este minimal, cel puţin un vârf al triunghiului trebuie să fie un vârf al dreptunghiului. Se disting astfel două cazuri: primul în care un vârf al triunghiului este şi vârf al dreptunghiului şi celelalte două puncte sunt situate pe cele două laturi ale dreptunghiului ce nu au ca şi capăt primul punct, iar al doilea caz în care cel puţin două vârfuri sunt vârfuri ale dreptunghiului opuse pe diagonală. Dacă dreptunghiul are $H$ puncte pe verticală şi $W$ puncte pe orizontală, atunci în primul caz vom avea $4 * ((H - 1)(W - 1) + H - 1 + W - 1)$ triunghiuri, iar în al doilea caz vom avea $2 * (H * W - X)$ unde $X$ e numărul de puncte de coordonate întregi de pe diagonala dreptunghiului. Cum trebuie să numărăm triunghiurile înscrise în fiecare dreptughi pentru care $1 &le; H &le; N$ şi $1 &le; W &le; M$, obţinem un algoritm de complexitate $O(N*M log N)$, unde $log N$ apare la calcularea lui $X$.\r\n\r\nh2(#problema6). Problema 6: \'Dreptunghiuri\':problema/dreptunghiuri (preOni, 2006, runda 1)\r\n\r\nbq. Se dă o grilă de puncte laticiale de dimensiuni $N * M (0 &lt; N, M &le; 400)$. Să se determine numărul dreptunghiurilor cu vârfurile în punctele laticiale. De exemplu, pentru o grilă de $3 * 3$ puncte găsim $10$ dreptunghiuri.\r\n\r\np=. !probleme-cu-puncte-laticiale?img10.JPG 70%!\r\n\r\nh3. Rezolvare\r\n\r\nUn dreptunghi care apare în grila de puncte laticiale e mărginit de două drepte verticale la stânga şi la dreapta, şi de două drepte orizontale în sus şi în jos. Acum, dacă vrem pentru patru drepte fixate să ştim câte dreptunghiuri mărginesc ele, ne putem uita la următorul desen.\r\n\r\np=. !preoni-2006/runda-1/solutii?drept.jpg 70%!\r\n\r\nDacă dreptunghiul determinat de cele patru drepte are laturile $H$ şi $W$, atunci un dreptunghi înscris va împărţi laturile lui în bucăţile {$A$}, $B$ şi {$C$}, {$D$}. Acum, folosind teorema lui Pitagora avem că:\r\n\r\n* $A^2^ + D^2^ = Galben^2^$\r\n* $B^2^ + C^2^ = Verde^2^$\r\n* $Galben^2^ + Verde^2^ = Roz^2^$\r\n* $(A + B)^2^ = Roşu^2^$\r\n* $(C $-$ D)^2^ = Albastru^2^$\r\n* $Roşu^2^ + Albastru^2^ = Roz^2^$\r\n\r\nDe aici avem că {$(A + B)^2^ + (C - D)^2^ = A^2^ + B^2^ + C^2^ + D^2^$}. Astfel, obţinem {$AB = CD$}, dar {$B = H - A$}, iar {$D = W - C$}, deci, avem că {$C^2^ - WC + A(H - A) = 0$}. Dacă îl fixăm pe $A$ atunci trebuie sa rezolvăm o ecuaţie de gradul doi în necunoscută {$C$}, iar soluţia trebuie să fie întreagă între $0$ şi {$W$}.\r\n\r\nAstfel, în $O(H)$ vom şti numărul de dreptunghiuri înscrise într-un dreptunghi de dimensiuni {$H * W$}. Acest dreptunghi poate fi pus în $(N - H + 1) * (M - W + 1)$ locaţii pe o grilă de dimensiune {$N * M$}. Deci, soluţia are complexitate {$O(N*M^2^)$}, pentru fiecare dreptunghi de dimensiuni $1 &le; H &le; N$ şi $1 &le; W &le; M$ calculându-se numărul de dreptunghiuri înscrise.\r\n\r\nO rezolvare de complexitate $O(N^2^*M^2^)$ în care se căutau soluţiile ecuaţiei printr-un for ar fi luat $60$ de puncte. Rezolvarea directa folosind ecuaţia de gradul doi ia în jur de $80$ de puncte. Algoritmul poate fi optimizat la factorii constanţi. De exemplu, avem nevoie de funcţia radical care este înceată, pe care, precalculând-o, obţinem o accelerare a vitezei. Altă idee este că numarul de soluţii cu $A &le; H/2$ este egal cu numărul de soluţii cu $A &ge; H - H/2$, iar a treia idee de optimizare este că numarul de dreptunghiuri înscrise într-un dreptunghi de dimensiuni {$H$}, $W$ este acelaşi cu numărul de dreptunghiuri înscrise într-un dreptunghi de dimensiuni {$W$}, {$H$}.\r\n\r\nh2(#problema7). Problema 7: \'Paralelograme\':problema/paralelograme (Bursele Agora, 2005/2006, runda 1)\r\n\r\nbq. Se dă o grilă laticială cu $N$ linii şi $M$ coloane, unde $0 &lt; N, M &le; 2000$. Să cere determinarea numărului paralelogramelor cu vârfurile aflate la coordonate numere întregi. De exemplu, pentru $N = 2$ şi $M = 2$ putem construi $22$ de paralelograme.\r\n\r\np=. !probleme-cu-puncte-laticiale?img12.JPG!\r\n\r\nh3. Rezolvare\r\n\r\nCa să determinăm numărul de paralelograme ce se pot găsi pe o grilă laticială, proprietatea că diagonalele unui paralelogram se înjumătăţesc pare să ne ajute în obţinerea unui algoritm de complexitate $O(N + M)$. Însă, autorul nu a reuşit să numere într-un mod eficient câte paralelograme sunt degenerate (cu cele patru vârfuri coliniare) pentru a putea să le eliminăm din numărul total.\r\n\r\nDin nou, putem folosi ideea celui mai mic dreptunghi cu laturile paralele cu axele de coordonate pentru a număra repede o clasă mare de paralelograme de aceiaşi formă. Avem două cazuri posibile:\r\n\r\np=. !probleme-cu-puncte-laticiale?img13.JPG 70%!\r\n\r\nPrimul în care cele patru puncte sunt pe laturile dreptunghiului iar nici un vârf nu coincide cu vârfurile dreptunghiului, şi al doilea în care există două puncte în vârfuri opuse ale dreptunghiului. În primul caz, dacă avem poziţiile a două vârfuri fixate pe două laturi consecutive ale dreptunghiului, atunci poziţiile celorlalte două vârfuri sunt unic determinate. De aici obţinem că în primul caz avem $(h - 2) * (w - 2)$ paralelograme. În al doilea caz, dacă fixăm două vârfuri ale paralelogramului în colţurile dreptunghiului, celelalte două vârfuri vor fi simetrice faţă de centrul de greutate al dreptunghiului. Cum nu trebuie să luăm în calcul posibilitatea ca vârfurile să fie pe diagonala dreptunghiului, obţinem $h * w - cmmdc(h - 1, w - 1) - 2$ posibilităţi.\r\n\r\nAstfel, am ajuns la următorul algoritm:\r\n\r\n==code(c) |\r\nlong num = 0;\r\nfor (long h = 2; h <= N + 1; h++) {\r\n    for (long w = 2; w <= M + 1; w++) {\r\n        laux = (h - 2) * (w - 2) + h * w - cmmdc(h - 1, w - 1) - 2;\r\n        num += (N - h + 1) * (M - w + 1) * laux;\r\n    }\r\n}\r\n==\r\n\r\nAcest algoritm are complexitatea $O(N*M log N)$ şi nu s-ar fi încadrat în timpul impus, deoarece marea parte a calculelor este efectuată în determinarea celui mai mare divizor comun a două numere. Având în vedere că numerele folosite sunt între $1$ şi $N$ respectiv între $1$ şi $M$, putem să precalculăm o matrice $CMMDC[X][Y]$, $1 &le; X &le; N$ şi $1 &le; Y &le; M$, în $O(N * M)$. Astfel, complexitatea soluţiei a fost redusă la $O(N * M)$. Mai putem optimiza factorii constanţi ai soluţiei observând că într-un triunghi de dimensiuni $H * W$ poate fi înscris acelaşi număr de dreptunghiuri ca şi într-un triunghi $W * H$. Acest artificiu aproape dublează viteza algoritmului. Menţionăm că aceleaşi optimizări pot fi făcute şi la problema cu triunghiuri.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nCititorul poate să încerce aplicarea tehnicilor din articol la alte probleme similare precum determinarea numărului de patrulatere convexe nedegenerate cu vârfurile puncte laticiale, sau numărului de romburi sau trapeze.\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Buşneag, Maftei, _„Teme pentru cercurile şi concursurile de matematică ale elevilor”_, Scrisul Românesc, Craiova, 1983\r\n# Iaglom, Iaglom, _„Probleme neelementare tratate elementar”_, Editura Tehnică, Bucureşti, 1962\r\n# \'WolframMathWorld\':http://mathworld.wolfram.com\r\n# \'FAQs\':http://www.faqs.org/faqs/graphics/algorithms-faq/\r\n# \'Geometry Algorithms\':http://geometryalgorithms.com/Archive/algorithm_0101/',3146,'public',NULL,NULL),('probleme-cu-puncte-laticiale','Probleme cu puncte laticiale','2009-02-09 21:51:10','2009-04-11 14:08:43','h1. Probleme cu puncte laticiale\r\n\r\n(Categoria _Matematică_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 25em}*{text-align:center;} *Conţinut*\r\n* \'Introducere\':probleme-cu-puncte-laticiale#introducere\r\n* \'Problema 1\':probleme-cu-puncte-laticiale#problema1\r\n* \'Problema 2\':probleme-cu-puncte-laticiale#problema2\r\n* \'Problema 3: Copaci\':probleme-cu-puncte-laticiale#problema3\r\n* \'Problema 4\':probleme-cu-puncte-laticiale#problema4\r\n* \'Problema 5: Counting triangles\':probleme-cu-puncte-laticiale#problema5\r\n* \'Problema 6: Dreptunghiuri\':probleme-cu-puncte-laticiale#problema6\r\n* \'Problema 7: Paralelograme\':probleme-cu-puncte-laticiale#problema7\r\n* \'Concluzii\':probleme-cu-puncte-laticiale#concluzii\r\n* \'Bibliografie\':probleme-cu-puncte-laticiale#bibliografie\r\n\r\nh2(#introducere). Introducere\r\n\r\nArticolul de faţă se va concentra pe probleme în care vor apărea puncte de coordonate întregi care sunt numite puncte laticiale. Sursele [1] şi [2] menţionate în \'bibliografie\':probleme-cu-puncte-laticiale#bibliografie conţin câte un capitol despre puncte laticiale care, deşi sunt mai riguros tratate decât în acest articol, pot fi interesante pentru un elev în pregătirea pentru olimpiadă. Să vedem acum câteva probleme ce au apărut pe la concursurile de programare.\r\n\r\nh2(#problema1). Problema 1\r\n\r\nbq. Să se determine numărul de puncte de coordonate întregi prin care trece segmentul determinat de punctele $(0, 0)$ şi $(N, M)$. De exemplu, pentru $N = 9$ şi $M = 12$ pe segment vor fi $4$ puncte de coordonate întregi.\r\n\r\np=. !probleme-cu-puncte-laticiale?img1.JPG 70%!\r\n\r\nh3. Rezolvare\r\n\r\nPutem considera doar cazurile în care $0 &le; N &le; M$. Dacă $N = 0$ atunci, evident, avem $M + 1$ puncte pe segment. Astfel, trebuie să rezolvăm doar cazul în care $1 &le; N &le; M$.\r\nEvident că orice punct $(x, y)$, pentru a fi pe segmentul nostru, trebuie să satisfacă ecuaţia $y = (M / N) * x$. Această ecuaţie are ca soluţie un număr natural doar dacă $M * x$ se divide cu $N$. De aici, dacă $D = cmmdc(M, N)$ atunci $x$ se divide cu $N / D$. Obţinem, astfel, $x$ de forma $k * (N / D)$, de unde rezultă că $y$ este de forma $y = k * (M / D)$. Pentru ca punctul $(x, y)$ să aparţină segmentului, trebuie ca $0 &le; x &le; N$ şi $0 &le; y &le; M$, şi, înlocuind în a doua inegalitate pe $y$ avem $0 &le; k &le; D$. În concluzie, numărul de puncte de pe un segment de la $(0, 0)$ la $(N, M)$ este egal cu cel mai mare divizor comun al numerelor $M$ şi $N$ la care adăugăm $1$. Putem determina acest număr în complexitate $O(log (N + M))$.\r\n\r\nh2(#problema2). Problema 2\r\n\r\nbq. Se dă un triunghi cu vârfurile în puncte laticiale. Se cere să se determine numărul de puncte de coordonate întregi ce se află în interiorul triunghiului sau pe laturile lui. De exemplu, un triunghi cu vârfurile de coordonate $(1, 5)$, $(5, 1)$ şi $(6, 6)$ are $16$ puncte în interior.\r\n\r\np=. !probleme-cu-puncte-laticiale?img2.JPG!\r\n\r\nh3. Rezolvare\r\n\r\nPentru un dreptunghi cu laturile paralele cu axele de coordonate de lungime $M$ şi lăţime $N$ avem că numărul de puncte situate strict în interiorul dreptunghiului este $(M - 1)*(N - 1)$, iar numărul de puncte situate pe laturile poligonului este $2M + 2N$. Dacă notăm cu $B$ numărul de puncte de pe laturi, cu $I$ numărul de puncte situate strict în interiorul unui dreptunghi şi cu $A$ aria dreptunghiului, observăm că $I + B/2 - 1 = (M - 1) * (N - 1) + M + N - 1 = M * N = A$.\r\nÎn cazul triunghiurilor dreptunghice ce au două catete vom vedea că această formulă se păstrează. Evident avem că $A = (M * N)/2$. Pe ipotenuza triunghiului vom avea $D$ puncte ({$D = cmmdc(M, N) + 1$}, dar aceasta nu ne interesează pe moment). Rezultă că numărul de puncte de pe laturile triunghiului este $B = M + N + D - 1$. Numărul de puncte $I$ din interiorul triunghiului este numărul de puncte din interiorul dreptunghiului $(M - 1) * (N - 1)$ din care se scad punctele interioare de pe diagonala $D - 2$, rezultatul împărţindu-se apoi la $2$. De aici avem $I = ((M - 1) * (N - 1) - D + 2) / 2$.\r\n\r\nVerificăm formula $I + B/2 - 1 = (M - 1) * (N - 1)/2 - D/2 + 1 + M/2 + N/2 + D/2 + 1/2 = (M * N)/2$. Deci formula se verifică şi pe astfel de triunghiuri.\r\n\r\nAcum ne uităm la cel mai mic dreptunghi ce conţine un triunghi oarecare. Acest dreptunghi poate fi împărţit în patru triunghiuri din care unul este cel iniţial, iar celelalte sunt trei triunghiuri dreptunghice pentru care catetele merg de-a lungul liniilor laticiale. Vom vedea că formula noastră se verifică şi pentru triunghiuri oarecare. Notăm cu $I{~d~}$ numărul de puncte interioare dreptunghiului, $A{~d~}$ aria dreptunghiului şi $B{~d~}$ numărul de puncte de pe laturile dreptunghiului, cu $I{~1~}$, $I{~2~}$, $I{~3~}$ numărul de puncte din interiorul celor trei triunghiuri dreptunghice, $B{~1~}$, $B{~2~}$, $B{~3~}$ numărul de puncte de pe laturile celor trei triunghiuri, iar $A{~1~}$, $A{~2~}$ şi $A{~3~}$ ariile celor trei triunghiuri. Avem că $I = I{~d~} - I{~1~} - I{~2~} - I{~3~} - B + 3$ (trebuie să eliminăm punctele de pe laturile triunghiului interior şi să avem grijă de vârfurile acestui triunghi), $B = B{~1~} + B{~2~} + B{~3~} - B{~d~}$ iar $A = A{~d~} - A{~1~} - A{~2~} - A{~3~}$. De aici avem că $I + B/2 - 1 = I{~d~} - I{~1~} - I{~2~} - I{~3~} - B{~1~}/2 - B{~2~}/2 - B{~3~}/2 + B{~d~}/2 - 1 + 3 = (I{~d~} + B{~d~}/2 - 1) - (I{~1~} + B{~1~}/2 - 1) - (I{~1~} + B{~1~}/2 - 1) - (I{~1~} + B{~1~}/2 - 1) = A{~d~} - A{~1~} - A{~2~} - A{~3~} = A$, deci egalitarea este valabilă şi pentru triunghiuri oarecare.\r\n\r\np=. !probleme-cu-puncte-laticiale?img3.JPG!\r\n\r\nAcum aria triunghiului cu vârfurile $(x1, y1)$, $(x2, y2)$, $(x3, y3)$ o putem afla uşor folosind \'formula lui Heron\':http://en.wikipedia.org/wiki/Heron%27s_formula sau folosind determinantul:\r\n<tex> \\displaystyle \\frac {1} {2} \\cdot | \\left| \\begin{array}{ccc}\r\nx_{1} & y_{1} & 1 \\\\\r\nx_{2} & y_{2} & 1 \\\\\r\nx_{3} & y_{3} & 1 \\end{array} \\right| |.  </tex>\r\n\r\nNumărul de puncte de pe laturile triunghiului poate fi determinat uşor folosind formula demonstrată în problema anterioară. Acum, folosind formula $I + B/2 - 1 = A$ putem afla numărul $I$ şi problema e rezolvată prin întoarcerea numărului $I + B$. Complexitatea rezolvării este $O(log N)$ unde $N$ este valoarea maximă a coordonatelor.\r\n\r\nh2(#problema3). Problema 3: \'Copaci\':problema/copaci (info{_arena_})\r\n\r\nbq. Se dă un poligon prin vârfurile sale aflate doar la coordonate numere naturale. Poligonul nu este neapărat convex. Se cere să se găsească numărul punctelor aflate strict în interiorul poligonului la coordonate numere întregi.\r\nDe exemplu, pentru poligonul dat prin vârfurile $(0, 4)$, $(0, 5)$, $(2, 7)$, $(2, 4)$, $(6, 6)$ şi $(4, 0)$ avem $12$ astfel de puncte.\r\n\r\np=. !probleme-cu-puncte-laticiale?img4.JPG 80%!\r\n\r\nh3. Rezolvare\r\n\r\nFormula $I + B/2 - 1 = A$ prezentată mai sus se numeşte \'Teorema lui Pick\':http://en.wikipedia.org/wiki/Pick%27s_theorem, iar ea este valabilă şi pentru poligoane oarecare. Acest fapt este adevărat pentru că orice poligon are o diagonală interioară care îl împarte în două poligoane distincte. Dacă notăm $I{~1~}$ şi $I{~2~}$ punctele interioare celor două poligoane, $B{~1~}$ şi $B{~2~}$ punctele de pe laturile celor două poligoane, $A{~1~}$ şi $A{~2~}$ ariile celor două poligoane şi $D$ numărul de puncte de coordonate întregi de pe diagonală, atunci, dacă egalitatea ar fi fost satisfăcută pentru cele două poligoane, am avea că $B{~1~} + B{~2~} = B + 2D - 2$, $I = I{~1~} + I{~2~} + D - 2$. De aici avem $A = A{~1~} + A{~2~} = I{~1~} + B{~1~}/2 - 1 + I{~2~} + B{~2~}/2 - 1 = I{~1~} + I{~2~} + B/2 + D - 1 - 2 = I + B/2 - 1$. Astfel putem demonstra prin inducţie că relaţia este satisfăcută pentru orice poligon.\r\n\r\nAria unui poligon poate fi calculată uşor folosind următoarea formulă: \r\n<tex> \\displaystyle A = \\sum_{i=1}^{n} (x_i \\cdot y_{i+1}-x_{i+1} \\cdot y_i) </tex>, unde punctul de indice $n + 1$ este primul punct. Astfel, obţinem un algoritm de complexitate $O(N log (Max_X + Max_Y))$.\r\n\r\nh2(#problema4). Problema 4 (Marele Premiu Paco, 2000)\r\n\r\nbq. Se dă o grilă de puncte laticiale de dimensiuni $N × N$. Se cere să se determine numărul de pătrate care se pot forma astfel încât vârfurile lor să aparţină punctelor din grilă. De exemplu, pe o grilă de dimensiuni $3 × 3$ există $6$ pătrate.\r\n\r\np=. !probleme-cu-puncte-laticiale?img5.JPG!\r\n\r\nh3. Rezolvare:\r\n\r\nUn pătrat cu $L$ puncte pe o latură, cu laturile paralele cu axele de coordonate, poate fi translatat în $(N - L + 1)*(N - L + 1)$ poziţii diferite pe grilă.\r\n\r\np=. !probleme-cu-puncte-laticiale?img6.JPG 70%!\r\n\r\nConsiderăm pentru un pătrat din mulţimea soluţiilor, dreptunghiul minim cu laturile paralele cu axele de coordonate ce conţine acest pătrat. Este uşor să vedem că acest dreptunghi este de fapt un pătrat. Într-un pătrat ce are $L$ puncte pe latură, înscrie $L - 2$ pătrate care nu au laturile paralele cu axele de coordonate. \r\n\r\np=. !probleme-cu-puncte-laticiale?img7.JPG 70%!\r\n\r\nAstfel, vedem că numărul total de pătrate pe o grilă $N * M$ este, succesiv:\r\n\r\n* <tex> \\displaystyle\\sum_{L=2}^{N} (N-L+1)(N-L+1)(L-1) = </tex>\r\n* <tex> = \\displaystyle\\sum_{L=1}^{N-1} (N-L)(N-L)L </tex>\r\n* <tex> = \\displaystyle\\sum_{L=1}^{N-1} L*N^2 - 2*L^2*N + L^3 </tex>\r\n* <tex> = \\displaystyle N^2 * \\sum_{L=1}^{N-1} L - 2 * N * \\sum_{L=1}^{N-1} L^2 + \\sum_{L=1}^{N-1} L^3 </tex>\r\n* <tex> = \\displaystyle N^2 * \\frac{N(N - 1)}{2} - 2 * N * \\frac{N(N - 1)(2N - 1)}{6} + \\left[\\frac{N(N - 1)}{2}\\right]^2 </tex>\r\n\r\nAm folosit formulele cunoscute din manualul de clasa a 10-a:\r\n\r\n* <tex> \\displaystyle\\sum_{k=1}^{n} k = \\frac{n(n+1)}{2} </tex>\r\n* <tex> \\displaystyle\\sum_{k=1}^{n} k^2 = \\frac{n(n+1)(2n+1)}{6} </tex>\r\n* <tex> \\displaystyle\\sum_{k=1}^{n} k^3 = \\left[\\frac{n(n+1)}{2}\\right]^2 </tex>\r\n\r\nAceastă soluţie are complexitatea $O(1)$, fiind o simplă formulă.\r\n\r\nh2(#problema5). Problema 5: \'Counting triangles\':http://acmicpc-live-archive.uva.es/nuevoportal/data/problem.php?p=3295 (ACM ICPC Asia, Dhaka 2005/2006) \r\n\r\nbq. Triunghiurile sunt poligoane cu trei laturi şi cu aria strict pozitivă. Triunghiurile laticiale sunt triunghiuri ce au vârfurile de coordonate întregi. În această problemă va trebui să găsiţi numărul de triunghiuri laticiale ce se pot găsi pe o grilă de dimensiuni $M * N$ $(1 &le; M, N &le; 1000)$. De exemplu, pe o grilă de dimensiuni $1 * 2$ găsim $18$ triunghiuri laticiale distincte după cum vedem în figură:\r\n\r\np=. !probleme-cu-puncte-laticiale?img14.JPG 70%!\r\n\r\nh3. Rezolvare\r\n\r\nPrima idee de rezolvare ar fi de a lua toate combinaţiile de trei puncte distincte dintre cele $N * M$ puncte şi apoi de a elimina oricare trei puncte coliniare, dar partea a doua pare greu de realizat în mod eficient. Vom număra, asemănător rezolvării de mai sus, numărul de triunghiuri înscrise într-un dreptunghi paralel cu axele de coordonate. Ulterior, acel dreptunghi îl vom putea translata pe grila de puncte laticiale şi astfel vom putea număra toate triunghiurile posibile.\r\n\r\np=. !probleme-cu-puncte-laticiale?img9.JPG 70%!\r\n\r\nOricum ar fi un triunghi situat într-un dreptunghi ce este minimal, cel puţin un vârf al triunghiului trebuie să fie un vârf al dreptunghiului. Se disting astfel două cazuri: primul în care un vârf al triunghiului este şi vârf al dreptunghiului şi celelalte două puncte sunt situate pe cele două laturi ale dreptunghiului ce nu au ca şi capăt primul punct, iar al doilea caz în care cel puţin două vârfuri sunt vârfuri ale dreptunghiului opuse pe diagonală. Dacă dreptunghiul are $H$ puncte pe verticală şi $W$ puncte pe orizontală, atunci în primul caz vom avea $4 * ((H - 1)(W - 1) + H - 1 + W - 1)$ triunghiuri, iar în al doilea caz vom avea $2 * (H * W - X)$ unde $X$ e numărul de puncte de coordonate întregi de pe diagonala dreptunghiului. Cum trebuie să numărăm triunghiurile înscrise în fiecare dreptughi pentru care $1 &le; H &le; N$ şi $1 &le; W &le; M$, obţinem un algoritm de complexitate $O(N*M log N)$, unde $log N$ apare la calcularea lui $X$.\r\n\r\nh2(#problema6). Problema 6: \'Dreptunghiuri\':problema/dreptunghiuri (preOni, 2006, runda 1)\r\n\r\nbq. Se dă o grilă de puncte laticiale de dimensiuni $N * M (0 &lt; N, M &le; 400)$. Să se determine numărul dreptunghiurilor cu vârfurile în punctele laticiale. De exemplu, pentru o grilă de $3 * 3$ puncte găsim $10$ dreptunghiuri.\r\n\r\np=. !probleme-cu-puncte-laticiale?img10.JPG 70%!\r\n\r\nh3. Rezolvare\r\n\r\nUn dreptunghi care apare în grila de puncte laticiale e mărginit de două drepte verticale la stânga şi la dreapta, şi de două drepte orizontale în sus şi în jos. Acum, dacă vrem pentru patru drepte fixate să ştim câte dreptunghiuri mărginesc ele, ne putem uita la următorul desen.\r\n\r\np=. !preoni-2006/runda-1/solutii?drept.jpg 70%!\r\n\r\nDacă dreptunghiul determinat de cele patru drepte are laturile $H$ şi $W$, atunci un dreptunghi înscris va împărţi laturile lui în bucăţile {$A$}, $B$ şi {$C$}, {$D$}. Acum, folosind teorema lui Pitagora avem că:\r\n\r\n* $A^2^ + D^2^ = Galben^2^$\r\n* $B^2^ + C^2^ = Verde^2^$\r\n* $Galben^2^ + Verde^2^ = Roz^2^$\r\n* $(A + B)^2^ = Roşu^2^$\r\n* $(C $-$ D)^2^ = Albastru^2^$\r\n* $Roşu^2^ + Albastru^2^ = Roz^2^$\r\n\r\nDe aici avem că {$(A + B)^2^ + (C - D)^2^ = A^2^ + B^2^ + C^2^ + D^2^$}. Astfel, obţinem {$AB = CD$}, dar {$B = H - A$}, iar {$D = W - C$}, deci, avem că {$C^2^ - WC + A(H - A) = 0$}. Dacă îl fixăm pe $A$ atunci trebuie sa rezolvăm o ecuaţie de gradul doi în necunoscută {$C$}, iar soluţia trebuie să fie întreagă între $0$ şi {$W$}.\r\n\r\nAstfel, în $O(H)$ vom şti numărul de dreptunghiuri înscrise într-un dreptunghi de dimensiuni {$H * W$}. Acest dreptunghi poate fi pus în $(N - H + 1) * (M - W + 1)$ locaţii pe o grilă de dimensiune {$N * M$}. Deci, soluţia are complexitate {$O(N*M^2^)$}, pentru fiecare dreptunghi de dimensiuni $1 &le; H &le; N$ şi $1 &le; W &le; M$ calculându-se numărul de dreptunghiuri înscrise.\r\n\r\nO rezolvare de complexitate $O(N^2^*M^2^)$ în care se căutau soluţiile ecuaţiei printr-un for ar fi luat $60$ de puncte. Rezolvarea directa folosind ecuaţia de gradul doi ia în jur de $80$ de puncte. Algoritmul poate fi optimizat la factorii constanţi. De exemplu, avem nevoie de funcţia radical care este înceată, pe care, precalculând-o, obţinem o accelerare a vitezei. Altă idee este că numarul de soluţii cu $A &le; H/2$ este egal cu numărul de soluţii cu $A &ge; H - H/2$, iar a treia idee de optimizare este că numarul de dreptunghiuri înscrise într-un dreptunghi de dimensiuni {$H$}, $W$ este acelaşi cu numărul de dreptunghiuri înscrise într-un dreptunghi de dimensiuni {$W$}, {$H$}.\r\n\r\nh2(#problema7). Problema 7: \'Paralelograme\':problema/paralelograme (Bursele Agora, 2005/2006, runda 1)\r\n\r\nbq. Se dă o grilă laticială cu $N$ linii şi $M$ coloane, unde $0 &lt; N, M &le; 2000$. Să cere determinarea numărului paralelogramelor cu vârfurile aflate la coordonate numere întregi. De exemplu, pentru $N = 2$ şi $M = 2$ putem construi $22$ de paralelograme.\r\n\r\np=. !probleme-cu-puncte-laticiale?img12.JPG!\r\n\r\nh3. Rezolvare\r\n\r\nCa să determinăm numărul de paralelograme ce se pot găsi pe o grilă laticială, proprietatea că diagonalele unui paralelogram se înjumătăţesc pare să ne ajute în obţinerea unui algoritm de complexitate $O(N + M)$. Însă, autorul nu a reuşit să numere într-un mod eficient câte paralelograme sunt degenerate (cu cele patru vârfuri coliniare) pentru a putea să le eliminăm din numărul total.\r\n\r\nDin nou, putem folosi ideea celui mai mic dreptunghi cu laturile paralele cu axele de coordonate pentru a număra repede o clasă mare de paralelograme de aceiaşi formă. Avem două cazuri posibile:\r\n\r\np=. !probleme-cu-puncte-laticiale?img13.JPG 70%!\r\n\r\nPrimul în care cele patru puncte sunt pe laturile dreptunghiului iar nici un vârf nu coincide cu vârfurile dreptunghiului, şi al doilea în care există două puncte în vârfuri opuse ale dreptunghiului. În primul caz, dacă avem poziţiile a două vârfuri fixate pe două laturi consecutive ale dreptunghiului, atunci poziţiile celorlalte două vârfuri sunt unic determinate. De aici obţinem că în primul caz avem $(h - 2) * (w - 2)$ paralelograme. În al doilea caz, dacă fixăm două vârfuri ale paralelogramului în colţurile dreptunghiului, celelalte două vârfuri vor fi simetrice faţă de centrul de greutate al dreptunghiului. Cum nu trebuie să luăm în calcul posibilitatea ca vârfurile să fie pe diagonala dreptunghiului, obţinem $h * w - cmmdc(h - 1, w - 1) - 2$ posibilităţi.\r\n\r\nAstfel, am ajuns la următorul algoritm:\r\n\r\n==code(c) |\r\nlong num = 0;\r\nfor (long h = 2; h <= N + 1; h++) {\r\n    for (long w = 2; w <= M + 1; w++) {\r\n        laux = (h - 2) * (w - 2) + h * w - cmmdc(h - 1, w - 1) - 2;\r\n        num += (N - h + 1) * (M - w + 1) * laux;\r\n    }\r\n}\r\n==\r\n\r\nAcest algoritm are complexitatea $O(N*M log N)$ şi nu s-ar fi încadrat în timpul impus, deoarece marea parte a calculelor este efectuată în determinarea celui mai mare divizor comun a două numere. Având în vedere că numerele folosite sunt între $1$ şi $N$ respectiv între $1$ şi $M$, putem să precalculăm o matrice $CMMDC[X][Y]$, $1 &le; X &le; N$ şi $1 &le; Y &le; M$, în $O(N * M)$. Astfel, complexitatea soluţiei a fost redusă la $O(N * M)$. Mai putem optimiza factorii constanţi ai soluţiei observând că într-un triunghi de dimensiuni $H * W$ poate fi înscris acelaşi număr de dreptunghiuri ca şi într-un triunghi $W * H$. Acest artificiu aproape dublează viteza algoritmului. Menţionăm că aceleaşi optimizări pot fi făcute şi la problema cu triunghiuri.\r\n\r\nh2(#concluzii). Concluzii\r\n\r\nCititorul poate să încerce aplicarea tehnicilor din articol la alte probleme similare precum determinarea numărului de patrulatere convexe nedegenerate cu vârfurile puncte laticiale, sau numărului de romburi sau trapeze.\r\n\r\nh2(#bibliografie). Bibliografie\r\n\r\n# Buşneag, Maftei, _„Teme pentru cercurile şi concursurile de matematică ale elevilor”_, Scrisul Românesc, Craiova, 1983\r\n# Iaglom, Iaglom, _„Probleme neelementare tratate elementar”_, Editura Tehnică, Bucureşti, 1962\r\n# \'WolframMathWorld\':http://mathworld.wolfram.com\r\n# \'FAQs\':http://www.faqs.org/faqs/graphics/algorithms-faq/\r\n# \'Geometry Algorithms\':http://geometryalgorithms.com/Archive/algorithm_0101/',3146,'public',3853,NULL),('transformari-geometrice','transformari-geometrice','2009-04-12 08:01:38','2009-04-13 18:35:38','h1. Transformări Geometrice\r\n\r\n(Categoria _Matematică_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'_Introducere_\':transformari-geometrice#introducere\r\n** \'Translaţia\':transformari-geometrice#translatia\r\n** \'Simetria\':transformari-geometrice#simetria\r\n** \'Rotaţia\':transformari-geometrice#rotatia\r\n** \'Omotetia\':transformari-geometrice#omotetia\r\n** \'Desfăşurarea în plan\':transformari-geometrice#desfasurarea-in-plan\r\n* \'Aplicaţia 1\':transformari-geometrice#aplicatia-1\r\n\r\nh2(#introducere). Introducere\r\n\r\nÎn acest articol vom introduce câteva noţuni legate de transformările geometrice care se pot dovedi utile în concursurile de programare.\r\n\r\nÎnainte de toate prezentăm câteva aspecte teoretice, o mare parte din ele nefiind foarte interesante şi probabil sunt conţinute şi în manualele de liceu. Cititorul poate trece direct la probleme şi, în măsura în care noţiunile din soluţii îi sunt neclare, poate reveni asupra părţii teoretice.\r\n\r\nh3(#translatia). Translaţia\r\n\r\nTranslaţia unei figuri geometrice reprezintă mişcarea tuturor componentelor ei pe o anumita distanţă si direcţie. Această transformare poate fi uşor caracterizată de un vector $v = (dx, dy)$. Când vrem să translatăm un punct $P(x, y)$ după $v$, e de ajuns să facem operaţia $P’ = P + v$. Astfel, $P’$ are cooronatele $(x + dx, y + dy)$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* pastrează orientarea poligoanelor (adică, dacă vârfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi şi ele în ordine trigonometrică);\r\n* păstrează unghiurile;\r\n* o dreaptă va fi transformată în altă dreaptă paralelă cu prima;\r\n* înafară de translaţia trivială de vector $v = (0, 0)$, această transformare nu are puncte fixe (adică orice punct va fi transformat într-un punct diferit);\r\n* translaţii successive vor rezulta tot într-o translaţie (adică, dacă vrem să translatăm un punct dupa $v$ şi apoi după $v{~1~}$, atunci obţinem acelaşi rezultat dacă translatăm direct după $v + v{~1~}$);\r\n* translaţia este comutativă;\r\n\r\nh3(#simetria). Simetria\r\n\r\nExistă două tipuri de simetrii: simetria faţă de un punct şi simetria faţa de o dreaptă.\r\n\r\nUn punct $A$ îl are simetric pe $A’$ faţă de un punct $O$, dacă segmentul $AA’$ are ca mijloc punctul $O$. Dacă avem un punct $(x{~0~}, y{~0~})$ căruia vrem să îi aflăm simetricul faţă de un punct de coordonate $(x, y)$ atunci acesta va fi $(2x – x{~0~}, 2y – y{~0~})$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* păstrează orientarea poligoanelor (adică, dacă varfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi şi ele în ordine trigonometrică);\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* are ca punct fix punctul $O$, iar drepte fixe cele care trec prin punctul $O$;\r\n* simetrii succesive după centre diferite $O{~1~}(x{~1~}, y{~1~}) O{~2~}(x{~2~}, y{~2~})$ sunt o translaţie de vector $v = 2(x{~2~} – x{~1~})$;\r\n* simetriile după un punct nu comută;\r\n\r\nSă calculăm simetricul unui punct $P(x{~0~}, y{~0~})$ faţă de o dreaptă de ecuaţie $ax + by + c = 0$. Notăm cu $d$ distanţa de la punctul $P$ la dreaptă, <tex> d = \\displaystyle\\frac{|a*x_{0} + b*y_{0} + c|}{\\sqrt{a^2 + b^2}} </tex>, şi cu $(m{~1~}, m{~2~})$ cosinii directori ai vectorului $n(a, b)$ normal la dreaptă. Valorile cosinilor directori sunt: <tex> m_{1} = \\displaystyle \\pm \\frac{a}{\\sqrt{a^2 + b^2}} </tex> şi <tex> m_{2} = \\displaystyle \\pm \\frac{b}{\\sqrt{a^2 + b^2}} </tex>. Vom alege semnul minus dacă $ax{~0~} + by{~0~} + c > 0$ iar semnul plus dacă $ax{~0~} + by{~0~} + c < 0$. Astfel, simetricul punctului $P$ va avea coordonatele $(x{~0~} + 2*d*m{~1~}, y{~0~} + 2*d*m{~2~})$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* nu păstrează orientarea poligoanelor (adică, dacă varfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi în sens orar);\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* are ca puncte fixe dreapta de simetrie;\r\n* simetrii succesive după drepte paralele sunt o translaţie;\r\n* simetrii succesive după drepte concurente sunt rotaţii;\r\n* simetriile nu comută;\r\n\r\nh3(#rotatia). Rotaţia\r\n\r\nAceasta este o transformare care roteşte punctele în sens trigonometric în jurul unui punct numit centru de rotaţie după un unghi fixat numit unghi de rotaţie. Dacă avem rotaţia de centru $O(x{~0~}, y{~0~})$ şi unghi $alfa$, atunci imaginea unui punct $P(x, y)$ va fi $P’(x{~0~} + (x – x{~0~}) * cos(alfa)  - (y – y{~0~}) * sin(alfa), y{~0~} + (x – x{~0~}) * sin(alfa)  + (y – y{~0~}) * cos(alfa))$.\r\n \r\nProprietăţi:\r\n* păstrează distanţele;\r\n* păstrează orientarea poligoanelor;\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* dacă nu este o rotaţie trivială de unghi $0$ atunci are ca punct fix centrul de rotaţie;\r\n* nu are drepte fixe, dar are cercuri fixe centrate în centrul de rotaţie;\r\n* două rotaţii succesive $R{~1~}(O{~1~}, alfa)$ şi $R{~2~}(O{~2~}, beta)$ se compun într-o translaţie sau o rotaţie $R{~3~}(O{~3~}, alfa + beta)$;\r\n* în general rotaţiile nu comută;\r\n\r\nh3(#omotetia). Omotetia\r\n\r\nAceasta este o transformare ce scalează obiectele în funcţie de un centru de omotetie şi un raport. Un punct $P(x, y)$ transformat după o omotetie $H(O(x{~0~}, y{~0~}), k)$ (centru $O$ şi raport $k$) va avea imaginea $P’(x{~0~} + k * (x - x{~0~}), y{~0~} + k * (y - y{~0~}))$.\r\n\r\nProprietăţi:\r\n\r\n* nu păstrează distanţele;\r\n* păstrează orientarea poligoanelor;\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele, iar transformata unei drepte va fi paralelă cu dreapta;\r\n* are ca punct fix centrul de omotetie;\r\n* două omotetii succesive $H{~1~}(O{~1~}, k{~1~})$ şi $H{~2~}(O{~2~}, k{~2~})$ se compun într-o translaţie sau omotetie $H{~3~}(O{~3~}, k{~1~} + k{~2~})$;\r\n* în general omotetiile nu comută;\r\n\r\nh3(#desfasurarea-in-plan). Desfăşurarea în plan\r\n\r\nAceasta nu este o transformare geometrică propriu-zisă, ci mai mult o tehnică folositoare în rezolvarea unor probleme pe care o puteţi vedea aplicată în problemele ce urmează ...\r\n\r\n*To do:* de verificat teoria de aici. :)\r\n\r\nh2(#aplicatia-1). Aplicaţia 1\r\n\r\nbq. Fie două puncte $A$ şi $B$ de aceiaşi parte a unei drepte $d$. Se cere să se determine un punct $M$ pe dreapta $d$ cu proprietatea că suma $AM + MB$ e mininimă.\r\n\r\np=. !transformari-geometrice?aplicatie-1.1.png 60%!\r\n\r\nh3. Rezolvare\r\n\r\np=. !transformari-geometrice?aplicatie-1.2.png 60%!\r\n\r\nDucem simetricul punctului $A$ faţă de dreapta $d$ pe care îl notăm cu $A’$. Oricare ar fi un punct $N$ pe dreapta $d$, $AN = A’N$ pentru că triunghiul $AA’N$ este isoscel având dreapta $d$ şi înălţime şi mediană. Astfel, avem că $AN + NB = A’N + NB$, deci pentru ca să minimizăm suma $AM + MB$ trebuie de fapt să minimizăm suma $A’M + MB$. Punctele $A’$ şi $B$ sunt situate de părţi diferite ale dreptei, deci punctul $M$ trebuie situat la intersecţia segmentului $A’B$ cu dreapta $d$.\r\n\r\nh2(#aplicatia-2). Aplicaţia 2\r\n\r\nbq. Fie două puncte $A$ şi $B$ în interiorul unui unghi format de semidreptele $d{~1~}$ şi $d{~2~}$ care au capătul comun $O$. Se cere să se determine două puncte $M$ şi $N$ astfel ca $M$ să aparţină lui $d{~1~}$ şi $N$ să aparţină lui $d{~2~}$ iar suma $AM + MN + NB$ să fie minimă.\r\n\r\np=. !transformari-geometrice?aplicatie-2.1.png 60%!\r\n\r\nh3. Rezolvare\r\n\r\np=. !transformari-geometrice?aplicatie-2.2.png 60%!\r\n\r\nFolosim aceeaşi idee: ducem simetricul punctului $A$, notat cu $A’$, faţă de dreapta $d{~1~}$ şi simetricul punctului $B$ notat cu $B’$ faţă de dreapta $d{~2~}$. Orice puncte $M$ şi $N$ am alege, avem că $AM + MN + NB = A’M + MN + NB$. Pentru a minimiza suma $A’M + MN + NB’$ trebuie ca $M$ şi $N$ să fie intersecţiile segmentului $A’B’$ cu semidreptele $d{~1~}$ şi $d{~2~}$.\r\n\r\n\r\n\r\n',3146,'public',NULL,NULL),('utilizator/andrici_cezar','Profil andrici_cezar','2008-02-20 11:15:10','2009-04-09 17:14:50','== include(page=\"template/noprofile\") ==\r\n *Despre mine*\r\n\r\n Sunt un elev din clasa a VI aB de la Liceul de Informatica Gr.C.Moisil Iasi.\r\n\r\n\r\n *Distinctii primite*\r\n\r\n_Premiul I la Informatica la ,,Urmasii lui Moisil\", la clasa a 4a!!!`````````anul 2007_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 5a!!!```````anul 2008_\r\n_Premiul III la Informatica Faza Judeteana-98 puncte, la clasa a 5a!!!````anul 2008_ (Calificat la ONI 2008)\r\n_Mentiune la Informatica Faza Nationala-160 puncte, la clasa a 5a!!!````anul 2008_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 9a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 5a!!!`````````anul 2008_\r\n_Premiul II la Informatica la ,,Moisil++\", la clasa a 5a!!!````````````anul 2008_\r\n_Premiul I la Informatica la ,,Concursul National al centrelor de Excelenta\", la clasa a 5a!!!```````anul 2008_\r\n_Premiul II la Informatica la Faza Locala-110 puncte, la clasa a 6a!!!`````anul 2009_\r\n_Premiul III la Informatica la Faza Judeteana-40 puncte, la clasa a 6a!!!````anul 2009_ (Calificat la ONI 2009)\r\n\r\n\r\n*.Campion*\r\n*2008 - 2009*\r\n_136 de puncte la Runda 1 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_180 de puncte la Runda 2 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_180 de puncte la Runda 3 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_50 de puncte la Runda 4 Campion, grupa SMALL!!!``````````````````````````anul 2008_ :((\r\n_180 de puncte la Runda 5 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_75 de puncte la Runda 6 Campion, grupa SMALL!!!``````````````````````````anul 2009_ :((\r\n_100 de puncte la Runda 10 Campion, grupa SMALL!!!````````````````````````anul 2009_ \r\n_15 de puncte la Runda 11 Campion, grupa SMALL!!!`````````````````````````anul 2009_ :((\r\n_0 de puncte la Runda 12 Campion, grupa SMALL!!!``````````````````````````anul 2009_ :((:((\r\n*Alte rezultate*\r\nChemat la CEX la a 9a 2009(cls.a 6a)\r\n\r\n*Profesori*\r\nIvasc Cornelia si Mirela Tibu ->[\'Elevi\':http://olimpiada.info/oji2009/index.php?cid=participanti&w=gim&judet=25&clasa=6]\r\nInfoarena\r\n.Campion\r\n\r\n*Citate preferate*\r\n_Daca plangi pentru ca soarele a disparut din viata ta, lacrimile te vor impiedica sa vezi stelele_ - Rabindranath Tagore\r\n\r\n_Un om nu este distrus atunci cind este invins; e distrus atunci cind renunta_- Richard Milhous Nixon\r\n\r\n_Nu este intelept sa fii sigur asupra propriei tale intlepciuni. Este sanatos sa ti se aminteasca ca si cel puternic poate slabi, iar cel intelept poate gresi_ - Mahatma Gandhi\r\n\r\n_Cel puternic nu este cel care este de neinvins, ci cel care se ridica dupa fiecare lovitura_\r\n\r\n_Loveste spre soare chiar daca nu reusesti, macar o sa fii printre stele_',7668,'public',NULL,NULL),('utilizator/andrici_cezar','Profil andrici_cezar','2008-02-20 11:15:10','2009-04-15 18:42:09','== include(page=\"template/noprofile\") ==\r\n *Despre mine*\r\n\r\n Sunt un elev din clasa a VI aB de la Liceul de Informatica Gr.C.Moisil Iasi.\r\n\r\n\r\n *Distinctii primite*\r\n\r\n_Premiul I la Informatica la ,,Urmasii lui Moisil\", la clasa a 4a!!!`````````anul 2007_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 5a!!!```````anul 2008_\r\n_Premiul III la Informatica Faza Judeteana-98 puncte, la clasa a 5a!!!````anul 2008_ (Calificat la ONI 2008)\r\n_Mentiune la Informatica Faza Nationala-160 puncte, la clasa a 5a!!!````anul 2008_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 9a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 5a!!!`````````anul 2008_\r\n_Premiul II la Informatica la ,,Moisil++\", la clasa a 5a!!!````````````anul 2008_\r\n_Premiul I la Informatica la ,,Concursul National al centrelor de Excelenta\", la clasa a 5a!!!```````anul 2008_\r\n_Premiul II la Informatica la Faza Locala-110 puncte, la clasa a 6a!!!`````anul 2009_\r\n_Premiul III la Informatica la Faza Judeteana-40 puncte, la clasa a 6a!!!````anul 2009_ (Calificat la ONI 2009)\r\n_Mentiune la Informatica Faza Nationala-230 puncte, la clasa a 6a!!!````````anul 2009_ (Pe locul 4)\r\n\r\n\r\n*.Campion*\r\n*2008 - 2009*\r\n_136 de puncte la Runda 1 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_180 de puncte la Runda 2 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_180 de puncte la Runda 3 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_50 de puncte la Runda 4 Campion, grupa SMALL!!!``````````````````````````anul 2008_ :((\r\n_180 de puncte la Runda 5 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_75 de puncte la Runda 6 Campion, grupa SMALL!!!``````````````````````````anul 2009_ :((\r\n_100 de puncte la Runda 10 Campion, grupa SMALL!!!````````````````````````anul 2009_ \r\n_15 de puncte la Runda 11 Campion, grupa SMALL!!!`````````````````````````anul 2009_ :((\r\n_0 de puncte la Runda 12 Campion, grupa SMALL!!!``````````````````````````anul 2009_ :((:((\r\n*Alte rezultate*\r\nChemat la CEX la a 9a 2009(cls.a 6a)\r\n\r\n*Profesori*\r\nIvasc Cornelia si Mirela Tibu ->[\'Elevi\':http://olimpiada.info/oji2009/index.php?cid=participanti&w=gim&judet=25&clasa=6]\r\nInfoarena\r\n.Campion\r\n\r\n*Citate preferate*\r\n_Daca plangi pentru ca soarele a disparut din viata ta, lacrimile te vor impiedica sa vezi stelele_ - Rabindranath Tagore\r\n\r\n_Un om nu este distrus atunci cind este invins; e distrus atunci cind renunta_- Richard Milhous Nixon\r\n\r\n_Nu este intelept sa fii sigur asupra propriei tale intlepciuni. Este sanatos sa ti se aminteasca ca si cel puternic poate slabi, iar cel intelept poate gresi_ - Mahatma Gandhi\r\n\r\n_Cel puternic nu este cel care este de neinvins, ci cel care se ridica dupa fiecare lovitura_\r\n\r\n_Loveste spre soare chiar daca nu reusesti, macar o sa fii printre stele_\r\n\r\n*Prieteni si persoane pe care le cunosc de 2 ani*\r\n\r\n\r\n==user(user=\"marta_dianna\" type=\"tiny\")==\r\n\r\n==user(user=\"antoanela\" type=\"tiny\")==\r\n\r\n==user(user=\"matemariaescu\" type=\"tiny\")==\r\n\r\n==user(user=\"alexrusu\" type=\"tiny\")==\r\n\r\n==user(user=\"liana\" type=\"tiny\")==\r\n\r\n==user(user=\"netedu_andrei\" type=\"tiny\")==\r\n\r\n==user(user=\"mironalex2005\" type=\"tiny\")==\r\n\r\n==user(user=\"unsilviu\" type=\"tiny\")==',7668,'public',NULL,NULL),('utilizator/andrici_cezar','Profil andrici_cezar','2008-02-20 11:15:10','2009-04-15 19:12:39',' *Despre mine*\r\n\r\n Sunt un elev din clasa a VI aB de la Liceul de Informatica Gr.C.Moisil Iasi.\r\n\r\n\r\n *Distinctii primite*\r\n\r\n_Premiul I la Informatica la ,,Urmasii lui Moisil\", la clasa a 4a!!!`````````anul 2007_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 5a!!!```````anul 2008_\r\n_Premiul III la Informatica Faza Judeteana-98 puncte, la clasa a 5a!!!````anul 2008_ (Calificat la ONI 2008)\r\n_Mentiune la Informatica Faza Nationala-160 puncte, la clasa a 5a!!!````anul 2008_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 9a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 5a!!!`````````anul 2008_\r\n_Premiul II la Informatica la ,,Moisil++\", la clasa a 5a!!!````````````anul 2008_\r\n_Premiul I la Informatica la ,,Concursul National al centrelor de Excelenta\", la clasa a 5a!!!```````anul 2008_\r\n_Premiul II la Informatica la Faza Locala-110 puncte, la clasa a 6a!!!`````anul 2009_\r\n_Premiul III la Informatica la Faza Judeteana-40 puncte, la clasa a 6a!!!````anul 2009_ (Calificat la ONI 2009)\r\n_Mentiune la Informatica Faza Nationala-230 puncte, la clasa a 6a!!!````````anul 2009_ (Pe locul 4)\r\n\r\n\r\n*.Campion*\r\n*2008 - 2009*\r\n_136 de puncte la Runda 1 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_180 de puncte la Runda 2 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_180 de puncte la Runda 3 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_50 de puncte la Runda 4 Campion, grupa SMALL!!!``````````````````````````anul 2008_ :((\r\n_180 de puncte la Runda 5 Campion, grupa SMALL!!!`````````````````````````anul 2008_\r\n_75 de puncte la Runda 6 Campion, grupa SMALL!!!``````````````````````````anul 2009_ :((\r\n_100 de puncte la Runda 10 Campion, grupa SMALL!!!````````````````````````anul 2009_ \r\n_15 de puncte la Runda 11 Campion, grupa SMALL!!!`````````````````````````anul 2009_ :((\r\n_0 de puncte la Runda 12 Campion, grupa SMALL!!!``````````````````````````anul 2009_ :((:((\r\n*Alte rezultate*\r\nChemat la CEX la a 9a 2009(cls.a 6a)\r\n\r\n*Profesori*\r\nIvasc Cornelia si Mirela Tibu ->[\'Elevi\':http://olimpiada.info/oji2009/index.php?cid=participanti&w=gim&judet=25&clasa=6]\r\nInfoarena\r\n.Campion\r\n\r\n*Citate preferate*\r\n_Daca plangi pentru ca soarele a disparut din viata ta, lacrimile te vor impiedica sa vezi stelele_ - Rabindranath Tagore\r\n\r\n_Un om nu este distrus atunci cind este invins; e distrus atunci cind renunta_- Richard Milhous Nixon\r\n\r\n_Nu este intelept sa fii sigur asupra propriei tale intlepciuni. Este sanatos sa ti se aminteasca ca si cel puternic poate slabi, iar cel intelept poate gresi_ - Mahatma Gandhi\r\n\r\n_Cel puternic nu este cel care este de neinvins, ci cel care se ridica dupa fiecare lovitura_\r\n\r\n_Loveste spre soare chiar daca nu reusesti, macar o sa fii printre stele_\r\n\r\nh3. Prieteni\r\n\r\n==user(user=\"marta_dianna\" type=\"tiny\")==\r\n\r\n\r\n==user(user=\"antoanela\" type=\"tiny\")==\r\n\r\n\r\n==user(user=\"matemariaescu\" type=\"tiny\")==\r\n\r\n\r\n==user(user=\"alexrusu\" type=\"tiny\")==\r\n\r\n\r\n==user(user=\"liana\" type=\"tiny\")==\r\n\r\n\r\n==user(user=\"netedu_andrei\" type=\"tiny\")==\r\n\r\n\r\n==user(user=\"mironalex2005\" type=\"tiny\")==\r\n\r\n\r\n==user(user=\"unsilviu\" type=\"tiny\")==\r\n',7668,'public',NULL,NULL),('utilizator/andrici_cezar','Profil andrici_cezar','2008-02-20 11:15:10','2009-04-16 06:12:04',' *Despre mine*\r\n\r\n Sunt un elev din clasa a VI aB de la Liceul de Informatica Gr.C.Moisil Iasi.\r\n\r\n\r\n *Distinctii primite*\r\n\r\n_Premiul I la Informatica la ,,Urmasii lui Moisil\", la clasa a 4a!!!`````````anul 2007_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 5a!!!```````anul 2008_\r\n_Premiul III la Informatica Faza Judeteana-98 puncte, la clasa a 5a!!!````anul 2008_ (Calificat la ONI 2008)\r\n_Mentiune la Informatica Faza Nationala-160 puncte, la clasa a 5a!!!````anul 2008_ (Pe locul 8)\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 9a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 5a!!!`````````anul 2008_\r\n_Premiul II la Informatica la ,,Moisil++\", la clasa a 5a!!!````````````anul 2008_\r\n_Premiul I la Informatica la ,,Concursul National al centrelor de Excelenta\", la clasa a 5a!!!```````anul 2008_\r\n_Premiul II la Informatica la Faza Locala-110 puncte, la clasa a 6a!!!`````anul 2009_\r\n_Premiul III la Informatica la Faza Judeteana-40 puncte, la clasa a 6a!!!````anul 2009_ (Calificat la ONI 2009)\r\n_Mentiune la Informatica Faza Nationala-230 puncte, la clasa a 6a!!!````````anul 2009_ (Pe locul 4)\r\n\r\n\r\n*.Campion*\r\n*2008 - 2009* - 916 puncte clasat pe locul 51\r\n*Alte rezultate*\r\nChemat la CEX la a 9a 2009(cls.a 6a)\r\n\r\n*Profesori*\r\nIvasc Cornelia si Mirela Tibu ->[\'Elevi\':http://olimpiada.info/oji2009/index.php?cid=participanti&w=gim&judet=25&clasa=6]\r\nInfoarena\r\n.Campion\r\n\r\n*Citate preferate*\r\n_Daca plangi pentru ca soarele a disparut din viata ta, lacrimile te vor impiedica sa vezi stelele_ - Rabindranath Tagore\r\n\r\n_Un om nu este distrus atunci cind este invins; e distrus atunci cind renunta_- Richard Milhous Nixon\r\n\r\n_Nu este intelept sa fii sigur asupra propriei tale intlepciuni. Este sanatos sa ti se aminteasca ca si cel puternic poate slabi, iar cel intelept poate gresi_ - Mahatma Gandhi\r\n\r\n_Cel puternic nu este cel care este de neinvins, ci cel care se ridica dupa fiecare lovitura_\r\n\r\n_Loveste spre soare chiar daca nu reusesti, macar o sa fii printre stele_\r\n\r\nh3. Prieteni\r\n\r\n==user(user=\"marta_dianna\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"antoanela\" type=\"tiny\")==\r\n(8)\r\n\r\n\r\n==user(user=\"matemariaescu\" type=\"tiny\")==\r\n(8)\r\n\r\n==user(user=\"liana\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"alexrusu\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"netedu_andrei\" type=\"tiny\")==\r\n(6)\r\n\r\n==user(user=\"mironalex2005\" type=\"tiny\")==\r\n(6)\r\n\r\n==user(user=\"unsilviu\" type=\"tiny\")==\r\n(7)\r\n\r\nScanteie Sebi(7)\r\nMunteanu Bogdan(8)\r\nAnton Madalina(8)\r\n\r\nToti am fost si anu trecut si anu asta la ONIgimnaziu si vom putea fi toti din nou doar peste 2 ani!',7668,'public',NULL,NULL),('utilizator/cosser','Profil','2007-12-10 17:02:46','2009-04-16 18:42:52','h2. Despre mine si ce ascult\r\n\r\n* _(Clasa a XII-a)_\r\n%Imi place informatica dar mi-ar placea sa stiu mai mult.%\r\n%{color:green}... apropo la avatar e Mihail Bulgakov%\r\n%{color:blue} ... ascult si recomand Radiohead, Blonde Redhead, The Dresden Dolls, Lali Puna, Tuxedomon, Animal Collective, IBOPA, Velvet Undergound, Led Zeppelin, Taraf de Haidouks, Toni Iordache, Fever Ray, Thom Yorke, Khidja Clouds Society, Vexx :) ..........%\r\n\r\nh2. Distinctii primite\r\n\r\n* _(NULL)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(NULL)_\r\n\r\n',7333,'public',NULL,NULL),('runda/onisim2009-7','onisim2009-7','2009-08-23 10:13:27','2009-08-23 10:28:51','h1. ON %{color:blue}**i**% S %{color:blue}**i**% M 2009 clasa a VII-a\r\n\r\n== roundregister(round_id=\"onisim2009-7\") ==\r\n\r\nh4. Concursul este o simulare a %{color:blue}Olimpiadei nationale de informatica 2009% .\r\n\r\nh4. Runda propune spre rezolvare cele 3 propleme propuse pentru %{color:blue}clasa a 7-a% .\r\n\r\nh4. Daca nu ai avut ocazia sa rezolvi aceste probleme o vei avea acum.\r\n\r\nh1. Succes !\r\n\r\n|**DATA CONCURSULUI**|%{color:blue}**DUMiNiCA 23 AUGUST 2009**%|\r\n|**ORA DE INCEPERE**|%{color:blue}**13:30:00**%|\r\n|**ORA DE FINALIZARE**|%{color:blue}**17:30:00**%|\r\n|**TIMP DE LUCRU**|%{color:blue}**4 ORE**%|\r\n|**REZULTATE**|\'*RANKS*\':runda/onisim2009-7/clasament|\r\n\r\nh1. %{color:blue}Probleme%\r\n\r\nh1.  \r\n\r\n==Tasks(round_id=\"onisim2009-7\" score=\"1\")==',10498,'round: onisim2009-7',NULL,NULL),('utilizator/sima_cotizo','Profil sima_cotizo','2006-11-24 21:03:54','2008-11-22 18:47:57','h2. Despre mine...\r\n\r\n* **Data nasterii:** 24 decembrie 1990\r\n* **Liceu:** Colegiul National \"I.L. Caragiale\" Ploiesti\r\n\r\n\r\nh2. Distinctii primite\r\n\r\n* **Finala _preONI_ 2006** : locul 4 \r\n* **ONI 2006** (clasa a 9-a) : premiul 3, locul 4\r\n* **Finala _.campion_ 2006**: participant [parca locul 8]\r\n* **ONI 2007** (clasa a 10-a) : premiul 3, locul 4\r\n* **Finala _.campion_ 2007** : locul 5\r\n* **ONI 2008** (clasa a 11-a) : medalie de aur (locul 6)\r\n\r\nh2. Cu ce am \"incurcat\" infoarena:\r\n\r\n# \'Articolul despre arbori de intervale\':arbori-de-intervale\r\n# \'Articolul (inca neterminat) despre geometrie analitica\':notiuni-de-geometrie-si-aplicatii\r\n# Problema \'\"Evaluare de expresii\"\':problema/evaluare din \'arhiva educationala\':arhiva-educationala\r\n# Problemele de clasele XI-XII de la ONI 2008: \'albinuta\':problema/albinuta , \'curent\':problema/curent , \'pviz\':problema/pviz , \'atac2\':problema/atac2 , \'drum2\':problema/drum2 , \'virus\':problema/virus\r\n\r\n\r\nh2. PS...\r\n\r\nVrednic sustinator al Rhide-ului pe linux, am atasat \'arhiva\':http://infoarena.ro/utilizator/sima_cotizo?action=download&file=rhide_kit_linux.tar care apare si prin forum, dar care nu are un link prea bun... si parca ce e la download nu merge. :)',3270,'protected',NULL,NULL),('utilizator/motty','Profil motty','2008-10-24 09:08:52','2009-04-16 20:48:34','h2. Despre mine\r\n\r\n* _Sunt elev in clasa a 9-a la Colegiul National de Informatica \"Tudor Vianu\";_\r\n* _Am inceput informatica in octombrie 2008;_\r\n* _{*In God we Trust!*}_\r\n* _Gibson rulez \\m/;_\r\n\r\nh2. Distinctii primite\r\n\r\n* _Mentiune la ONI 2009;_\r\n* _Premiul I la Concursul de Informatica \"Urmasii lui Moisil\" Iasi - 2009;_\r\n\r\nh2. Profesori\r\n\r\n* ==User(user=\"rapidu36\" type=\"tiny\")==\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"gabitzish1\" type=\"tiny\")==\r\n* ==User(user=\"ira\" type=\"tiny\")==\r\n* ==User(user=\"drag0s93\" type=\"tiny\")==\r\n* ==User(user=\"cosmin79\" type=\"tiny\")==\r\n* ==User(user=\"andreisfrent\" type=\"tiny\")==\r\n* ==User(user=\"punkist\" type=\"tiny\")==\r\n* ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n* ==User(user=\"hadesgames\" type=\"tiny\")==\r\n* ==User(user=\"ilinca\" type=\"tiny\")==\r\n',8690,'public',NULL,NULL),('probleme-de-taietura','Probleme de Taietura','2009-04-06 05:48:04','2009-04-18 16:04:19','h1. Probleme de taietura\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"andrici_cezar\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n\r\n(toc){width: 25em}*{text-align:center} *Conţinut:*\r\n* \'Problema 1\':probleme-de-taietura#problema-1\r\n* \'Problema 2\':probleme-de-taietura#problema-2\r\n* \'Problema 3\':probleme-de-taietura#problema-3\r\n* \'Problema 4\':probleme-de-taietura#problema-4\r\n* \'Problema 5\':probleme-de-taietura#problema-5\r\n* \'Problema 6\':probleme-de-taietura#problema-6\r\n* \'Problema 7\':probleme-de-taietura#problema-7\r\n* \'Problema 8\':probleme-de-taietura#problema-8\r\n* \'Problema 9\':probleme-de-taietura#problema-9\r\n* \'Problema 10\':probleme-de-taietura#problema-10\r\n* \'Problema 11\':probleme-de-taietura#problema-11\r\n* \'Problema 12\':probleme-de-taietura#problema-12\r\n* \'Bibliografie\':probleme-de-taietura#bibliografie\r\n\r\n\r\n\r\nh2(#problema-1). Problema 1:\r\n\r\nPentru un număr natural $N$ dat, se cere numărul maxim de regiuni în care se poate împărţi planul folosind $N$ drepte.\r\n\r\np=. !probleme-de-taietura?poza-1.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nMai întâi facem vom face două observaţii:\r\nÎn configuraţia cu număr maxim de regiuni nu vom avea două drepte paralele, pentru că două drepte care se intersectează formează în plan patru regiuni, în timp ce două drepte paralele formează în plan doar trei regiuni.\r\nDe asemenea pentru a obţine un număr maxim de regiuni, nu vor exista trei drepte care să se intersecteze intr-un punct pentru că astfel am pierde o regiune triunghiulară formată din punctele de intersecţie ale celor trei drepte.\r\nDacă aceste două condiţii sunt îndeplinite vom vedea în continuare că orice configuraţie de $N$ drepte împarte planul în acelaţi număr de regiuni. Notăm cu $d(n)$ acest număr. Presupunem ca ştim pe $d(n)$ , să vedem acum ce se întâmplă dacă mai adaugăm o dreaptă. \r\nAceastă nouă dreaptă va fi intersectată de celelalte drepte în $n$ puncte distincte. Fiecare segment de dreaptă şi semidreaptă în care este împărţită a $n+1-a$ taie o regiune veche in două regiuni noi. De aici tragem concluzia că $d(n+1) = d(n) + n + 1$ . Deci $d(n) = n + n – 1 + n – 2 + … + 2 + d(1)$ . Astfel folosind indentitatea $1 + 2 + 3 + … + n = n(n+1)/2$ obţinem $d(n) = n(n + 1) / 2 + 1$ .\r\nMenţionăm că problemele în care se cere maximizarea numărului de regiuni în care un pătrat, un triunghi sau un cerc este împărţit de $n$ drepte, au aceiaşi soluţie.\r\n\r\np=. !probleme-de-taietura?poza-2.bmp!\r\n\r\nh2(#problema-2). Problema 2:\r\n\r\nDându-se un număr natural $N$ , se cere numărul maxim de regiuni în care $N$ cercuri pot împărţi planul.\r\n\r\np=. !probleme-de-taietura?poza-4.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nEste clar că oricare două cercuri trebuie să se intersecteze in exact două puncte, nu să fie tangente sau să nu se intersecteze deloc pentru că astfel am pierde o regiune, iar oricare trei cercuri nu se intersectează într-un punct.\r\nOrice configuraţie care satisface această cerinţă va împărţi planul într-un număr maxim de regiuni.Vom nota cu $c(n)$ numărul maxim de regiuni în care este împărţit planul de $n$ cercuri. Să vedem ce se întîmplă când adăugăm un nou cerc la această configuraţie. Cercul nou va fi intersectat de cele $n$ cercuri în $2n$ puncte distincte, şi astfel va fi împărţit în $2n$ arce. Fiecare dintre aceste arce împarte o zonă veche în două zone noi. De aici tragem concluzia că $c(n + 1) = 2n + c(n)$ . Astfel putem să îl scriem pe $c(n) ca 2(n – 1) + 2(n – 2) + … + 2 + c(1)$ . De aici folosind din nou identitatea $1 + 2 + … + n = n(n+1)/2$ avem că $c(n) = n(n-1) + 2$ .\r\nEste evident că şi problema în care se cere maximizarea numărului de regiuni în care este împărţită suprafaţa unei sfere de $n$ cercuri are aceiaşi soluţie.\r\n\r\np=. !probleme-de-taietura?poza-5.bmp!\r\n\r\nh2(#problema-3). Problema 3:\r\n\r\nSe dau $n$ cercuri care se intersectează oricare două în două puncte şi nu există trei care se intersectează într-un punct, se cere să se determine numărul de zone în care este împarţit planul de aceste $n$ cercuri. ( $n <= 10^100$ )\r\n[acm.uva.es 10519 !! Really Strange !!]\r\n\r\nh3. Rezolvare:\r\n\r\nObservăm ca sunt indeplinite condiţiile de maximalitate cerute mai sus, deci rezultatul e $c(n)$ , singura problema ce rămâne este aceea de implementare a operaţiilor cu numere mari.\r\n\r\nh2(#problema-4). Problema 4:\r\n\r\nAvem un număr natural $N$ , vrem să determinăm numărul maxim de regiuni în care poate fi împărţit un plan de elipse.\r\n\r\np=. !probleme-de-taietura?poza-6.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nLa fel ca şi la cercuri nici aici nu trebuie să avem elipse tangente, sau elipse care să nu se intersecteze, nu vor exista nici aici trei elipse care să se intersecteze într-un punct, aici elipsele trebuie să se intersecteze în patru puncte, dacă s-ar intersecta numai în două puncte atunci configuraţia nu ar avea număr maxim de regiuni.\r\nNotăm cu $e(n)$ numărul de care suntem interesaţi. Câte regiuni noi apar cand adăugam o nouă elipsă? Păi o nouă elipsă va fi intersectată de celelalte elipse ăn patru puncte de fiecare, deci $e(n + 1) = 4n + e(n)$ . De aici tragem concluzia că $e(n) = 2 n(n - 1) + 2$ .\r\n\r\np=. !probleme-de-taietura?poza-7.bmp!\r\n\r\nh2(#problema-5). Problema 5:\r\n\r\nDându-se un număr natural $N$ , se cere numărul maxim de regiuni în care $N$ triunghiuri pot împărţi planul.\r\n\r\np=. !probleme-de-taietura?poza-8.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nRepetând raţionamentul de la problemele anterioareavem că $t(n+1) = 6n + t(n) => t(n) = 3n(n-1) + 2$ . \r\n\r\np=. !probleme-de-taietura?poza-9.bmp!\r\n\r\nh2(#problema-6). Problema 6:\r\n\r\nPentru $N$ plane determinaţi numărul maxim de zone în care poate fi împărţit spaţiul cu acestea.\r\n\r\nh3. Rezolvare:\r\n\r\nÎn această problemă urmăm raţionamentul de până acum. Este evident că trebuie ca fiecare plan să se intersecteze cu fiecare, că oricare trei plane trebuie să nu se intersecteze într-o dreaptă, oricare trei plane nu trebuie să fie paralele cu o dreaptă şi oricare patru plane nu trebuie să se intersecteze într-un punct. Notăm $p(n)$ numărul maxim de zone în care $n$ plane împart spatiul. Când adaugăm un nou plan acesta va fi intersectat de celelalte plane în $n$ drepte, drepte care după restrictiile care le-am pus nu vor fi două paralele sau trei care să se intersecteze într-un punct. Acest plan va fi împărţit în $d(n)$  regiuni de aceste drepte din cauza restricţiilor impuse. Fiecare regiune din plan taie o zonă din spaţiu în două noi zone, de aici tragem concluzia că $p(n + 1) = d(n) + p(n)$ . Astfel avem $p(n) =  n(n-1)/2 + 1 + (n-1)(n-2)/2 + 1 + ...+2 * 1 / 2 + 1 + p(1) = ( n^2^ – n + (n-1)^2^ – (n-1)+... + 2^2^ – 2  +  1 – 1 + (n – 1) )/2+ 2 = ( n(n+1)(2n + 1)/6 – n(n+1)/2 + (n-1))/2 + 2  = (n^3^/3 + n^2^/2 + n/6 – n^2^/2 – n/2 )/2 + n + 1 = n^3^/ 6 + 5n/6 + 1$ . Am folosit identităţile $1 + 2 + … + n = n(n+1)/2 şi 1 + 2^2^ + 3^2^ + … + n^2^ = n(n+1)(2n+1)/6$ care se pot demonstra uşor prin inducţie.\r\nMenţionăm că dacă vrem să împărţim un cub, un cilindru o sfera etc în număr maxim de regiuni folosind $n$ plane, formula se păstrează.\r\n\r\nh2(#problema-7). Problema 7:\r\n\r\nDându-se un număr natural $N$ , să se determine numărul maxim de zone în care pot împărţi spaţiul $N$ sfere.\r\n[Bursele Agora 2001[3]]\r\n\r\nh3. Rezolvare:\r\n\r\nPornim la fel ca la problema anterioară, oricare două sfere se vor intersecta şi nu vor exista trei sfere care să se intersecteze în acelaşi punct. Vom nota cu $s(n)$ numărul maxim de regiuni în care poate fi împărţit spaţiul cu $n$ sfere. Să vedem ce se întâmplă când adăugăm o sferă. Această sferă va fi intersectată de toate celelalte $n$ sfere în $n$ cercuri, pentru ca numărul de regiuni noi să fie maxim aceste cercuri vor împărţi sfera într-un număr maxim de regiuni, acest număr este $c(n)$ aşa cum am discutat la problema 2. Obţinem astfel $s(n + 1) = c(n) + s(n) = c(n) + c(n-1) + ... + c(1) = n(n-1) + 2 + (n-1)(n-2) + 2 + ... + 2 = 1 + 2^2 + .. + n^2 – 1 – 2 – 3 - .... – n + 2n => s(n) = n(n^2 – 3n + 8) / 3$\r\n\r\nh2(#problema-8). Problema 8:\r\n\r\nSe dă un număr $N$ care este numărul maxim în care poate fi împărţit planul de $m$ elipse, $n$ cercuri şi $p$ triunghiuri. Se cere ştiind $N$ să se determine toate valorile posibile pentru $m$ , $n$ şi $p$ . ( $N$ întreg făra semn reprezentabil pe 32 de biţi, $0<=m<100$ , $0<=n<20000$ şi $0<=p<100$ )\r\n[10623 Thinking Backward [4]]\r\n\r\nh3. Rezolvare:\r\n\r\nDacă am ştii pentru trei parametrii $m$ , $n$ şi $p$ care este numarul maxim de părţi în care poate fi împărţit planul  de $m$ elipse, $n$ cercuri şi $p$ triunghiuri, atunci am putea incerca toate posibilitaţile pentru $m$ , $n$ şi $p$ şi am găsi tripletele pentru rezultatul ar fie egal cu $N$ , chiar am putea optimiza puţin acest algoritm iteram pe toate valorile de $m$ şi $p$ , astfel vom obţine o ecuaţie cu necunoscuta $n$ astfel vom face doar $10000$ de rezolvări de ecuaţii în loc de $200 000 000$ de comparaţii. \r\nSă vedem cum găsim numărul maxim de zone. Din nou oricare două figuri se intersectează în număr maxim de intersecţii, un cerc cu o elipsă în patru puncte, un cerc sau o elipsă cu un triunghi în şase puncte. Mai întâi punem cele $m$ elipse in plan, ele vor împărţi planul în $e(m)$ regiuni adică $2 m(m - 1) + 2$ . După aceea adaugăm cercurile. Să notam numarul maxim de zone în care $n$ cercuri şi $m$ elipse pot împărţi planul cu $ec(m , n)$ . Dacă ştim cât este $e(m, n-1)$ atunci când adaugăm un nou cerc, acesta va fi intersectat de $m$ elipse in $4m$ puncte şi de $n-1$ cercuri in $2(n – 1)$ puncte deci cercul va fi împărţit în $4m + 2(n-1)$ arce care vor împărţi tot atâtea regiuni care existau deja in câte două regiuni noi. Deci $ec(m, n) = 4m + 2(n-1) + ec(m, n-1) = 4m + 2(n-1) + 4m + 2(n-2) + … + 4m + 2 + ec(m, 0) = 4m(n-1) + n (n-1) + 2m(m-1) + 2$ . Să vedem ce se întâmplă când adăugăm triunghiurile. Vom nota $ect(m, n, p)$ numărul maxim de zone în care poate fi împărţit planul de $m$ elipse, $n$ cercuri şi $p$ triunghiuri. Dacă ştim cu cat e egal $ect(m, n, p - 1)$ , atunci când vom adăuga un nou triunghi acesta va intersecta cele $m$ cercuri în $6m$ puncte, cele $n$ elipse în $6n$ puncte şi cele $p – 1$ triunghiuri în $6(p – 1)$ puncte, astfel se vor forma $6m + 6n + 6(p-1)$ noi zone. Deci $ect(m, n, p) = 6(m + n + p – 1) + ect(m, n, p – 1) = 6 (m + n + p – 1 + m + n + p – 2 + … m + n + 1) + ect(n, m, 0) = 6 (p-1)(m+n) + 3p(p-1) + 4m(n-1) + n(n-1) + 2m(m-1) + 2$ .\r\n\r\nProblemele anterioare au fost cam matematice şi ele sunt numite de obicei de olimpici peiorativ ca “probleme de formulă”, majoritatea olimpicilor la informatică participă aici pentru că matematica nu le place aşa tare şi deci nici apariţia unor probleme ca cele de mai sus care sunt mai mult de mate decât de info nu îi prea încântă. Cum poate fi rezolvată o problemă de formulă fără să avem intuiţia matematică sau cunoţinţele matematice necesare? Păi câteodată elevii apelează la următorul truc: află primele câteva valori de mâna sau cu ajutorul unor algoritmi brute force şi apoi speră ca formula să fie de o anumită formă, de exemplu ar putea fi un polinom de un grad mic. Atunci avem ca $f(N) = An^3 + Bn^2 + Cn + D$ . Afland primele câteva valori vom ştii valorile $f(1), f(2), f(3), f(4)$ . Dând lui $n$ pe rand valorile 1, 2, 3 şi 4 putem face un sistem cu necunoscutele A, B, C şi D. Sau putem încerca să vedem cum se comportă şirul de numere, are o creştere polinomială sau exponenţială, apar valorile lui în triunghiul lui Pascal. Iar dacă rezolvăm problemele de acasă putem căuta valorile din şirul de soluţii pe internet pe pagina Eciclopedia Online a şirurilor de întregi [7] care este o resursă foarte utilă în cazul problemelor de acest gen .\r\n\r\nh2(#problema-9). Problema 9:\r\n\r\nSe dau $N$ drepte în plan, fiecare dreaptă este dată prin două puncte prin care trece. Se cere să se determine pentru această configuraţie în câte zone este împărţit planul. ( $n <= 1000$ )\r\n[Internet Problem Solving Contest 2000 [5]]\r\n\r\nh3. Rezolvare:\r\n\r\nÎn sfârşit o problemă în care avem nevoie să folosim calculatorul şi talentul nostru de programatori . Vom folosi aceeaşi idee ce a apărut şi în celelalte probleme, adică numărăm pe rând în câte zone este împărţit planul de primele o dreaptă, doua drepte respectiv $n$ drepte. Deci vom adăuga în ordine dreptele la configuraţia noastră. Când adăugăm o dreaptă ea va fi intersectată de dreptele deja adăugate în $k$ puncte nu neapărat distincte, pe noi ne intereseaza punctele distincte, ca să facem acest lucru putem sorta punctele în $O(k log k)$ sau să folosim o tabelă de dispersie şi astfel să aflăm în $O(k)$ numărul de puncte distincte, daca acest număr e egal cu $L$ atunci la numărul curent de zone vom adăuga $L$ . Astfel algoritmul are complexitatea $O(n^2 log n)$ , sau dacă folosim tabele de dispersie $O(n^2)$ .\r\n\r\nh2(#problema-10). Problema 10:\r\n\r\np=. !probleme-de-taietura?poza-10.bmp!\r\n\r\nAvem un tort în formă de pătrat de dimensiune $1000 x 1000$ . Folosim un cuţit pentru a tăoa tortul. Întrebarea este după o serie de tăieturi, în căte bucăţi am patriţionat tortul. Restricţii: Numărul de tăieturi nu va fi mai mare de $8$ . După tăieturi, lungimea oricărei laturi a partiţiei nu va fi mai mică decât unu. Coordonatele vârfurilor tortului vor fi $(0,0)(0,1000)(1000,1000) (1000,0)$ . Tăieturile se vor intersecta în două puncte cu marginile tortului. Următoarea imagine e un tort tăiat în zece bucăţi.\r\n[acm.uva.es 527 The partition of a cake]\r\n\r\nh3. Rezolvarea:\r\n\r\nEste analoaga cu cea a problemei anterioare, datele sunt foarte mici în problema aceasta, probabil că autorii au vrut să facă problema accesibilă şi altor idei care folosesc împărţiri efective în poligoane a pătratului.\r\n\r\nh2(#problema-11). Problema 11:\r\n\r\np=. !probleme-de-taietura?poza-12.bmp!\r\n\r\nSe dă un graf planar prin noduri şi muchii, un graf este planar dacă există o modalitate de a îl desena în plan făra ca muchiile să se intersecteze decăt la capete. Se cere să se determine în căte regiuni împarte planul graful dat la intrare. Mai jos avem un exemplu de graf în care feţele sunt numerotate.\r\n[10178 Count the faces [4]]\r\n\r\nh3. Rezolvare:\r\n\r\nEste interesant faptul că în această problemă nu ne este dată configuraţia în plan a grafului ci doar structura lui. Un graf il putem reprezenta în mai multe moduri în plan, astfel suntem duşi înspre ideea că există ceva formulă care rezolvă problema. O formulă întradevăr există şi se numeşte formula lui Euler pentru grafurile planare. Formula arată aşa $f - m + n  = 2$ , unde prin $f$ am notat numărul de feţe, $m$ numărul de muchii şi $n$ numărul de vârfuri, dacă graful nostru e conex (formula include faţa exterioară). Această formulă poate fi demonstrată în foarte multe moduri. Dacă vreţi să vedeţi 19 metode de demonstrare puteţi să vizitaţi adresa [8]. O demonstraţie simplă ar fi prin inducţie pornind de la un arbore şi adăugând pe rând câte o muchie. La început avem o singură faţă, cea infinită, $1 – (n – 1) + n = 2$ se verifică. Fiecare muchie adăugată împarte o faţă în două deci dacă aveam inainte $f – m + n = 2$ acum vom avea $f1 – m1 + n = 2$ unde $f1 = f + 1$ şi $m1 = m + 1$ . Deci am demonstrate formula şi putem foarte uşor să rezolvăm problema, mai trebuie numai să avem grijă ca pentru fiecare componentă conexă număram faţa infinită.\r\nAceastă formulă este adevarată şi în spaţiu pentru poliedre.\r\n\r\nh2(#problema-12). Problema 12:\r\n\r\np=. !probleme-de-taietura?poza-13.bmp!\r\n\r\nSe considera $N$ cercuri in plan. Se cere să se determine numărul de zone finite în care cercurile date împart planul.\r\n \r\nExemplu\r\nCERCURI.IN\r\n4\r\n90 110 50\r\n130 70 30\r\n155 45 15\r\n165 115 65\r\nCERCURI.OUT\r\n$11$\r\n[Algoritmus, Cercuri[6]]\r\n\r\nh3. Rezolvare:\r\n\r\nContraexemple rezolvare normala\r\nO rezolvare folosind geometria computaţională pare foarte grea, lucrurile simplificându-se mult daca abordam problema prin prisma unor noţiuni de teoria grafurilor.\r\nFiecare punct de intersectie va fi considerat un nod. Două noduri vor fi legate prin o muchie dacă există un cerc pe care sa se afle amândouă iar între ele să nu existe nici un alt punct de intersectie.\r\nAcum vom folosi identitatea lui Euler: prezentată în problema anterioară. În problema noastră nu trebuie să numărăm şi faţa exterioară, deci formula folosita va fi $F=M-V+1$ . Această formulă este adevarată doar in cazul unei singure componente conexe. Pentru mai multe componente, formula devine $F=M-V+C$ , unde $C$ este numărul de componente conexe.\r\nO atenţie deosebită trebuie acordată punctelor de intersecţie prin care trec mai mult de două cercuri, pentru a nu le număra de mai multe ori. Putem rezolva aceasta problema prin sortarea punctelor de intersecţie ale unui cerc cu toate celelalte cercuri.\r\nDeasemenea, este necesara eliminarea cercurilor identice (cu acelaşi centru şi raze egale). Din orice mulţime cu astfel de cercuri este păstrat doar un singur element.\r\nDeoarece pentru fiecare cerc este necesara o sortare a punctelor de intersectie, complexitatea generala a algoritmului va fi $O(N2*log(N))$\r\n\r\nh2(#bibliografie). Bibliografie:\r\n\r\n# A.M. Iaglom, I. M. Iaglom, Probleme neelementare tratate elementat. Ed tehnică, Bucureşti, 1962\r\n# I. Tomescu, Probleme de combinatorică şi teoria grafurilor, ed didactică şi pedagogică. Bucureşti, 1981\r\n# Colecţia Ginfo\r\n# acm.uva.es\r\n# ipsc.ksp.sk\r\n# algoritmus.org/index.php\r\n# http://www.research.att.com/~njas/sequences/ [\"aici\":http://www.research.att.com/~njas/sequences/]\r\n# http://www.ics.uci.edu/~eppstein/junkyard/euler/\r\n',7668,'public',NULL,NULL),('probleme-de-taietura','Probleme de Taietura','2009-04-06 05:48:04','2009-04-18 16:10:10','h1. Probleme de taietura\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"andrici_cezar\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n\r\n(toc){width: 25em}*{text-align:center} *Conţinut:*\r\n* \'Problema 1\':probleme-de-taietura#problema-1\r\n* \'Problema 2\':probleme-de-taietura#problema-2\r\n* \'Problema 3\':probleme-de-taietura#problema-3\r\n* \'Problema 4\':probleme-de-taietura#problema-4\r\n* \'Problema 5\':probleme-de-taietura#problema-5\r\n* \'Problema 6\':probleme-de-taietura#problema-6\r\n* \'Problema 7\':probleme-de-taietura#problema-7\r\n* \'Problema 8\':probleme-de-taietura#problema-8\r\n* \'Problema 9\':probleme-de-taietura#problema-9\r\n* \'Problema 10\':probleme-de-taietura#problema-10\r\n* \'Problema 11\':probleme-de-taietura#problema-11\r\n* \'Problema 12\':probleme-de-taietura#problema-12\r\n* \'Bibliografie\':probleme-de-taietura#bibliografie\r\n\r\n\r\n\r\nh2(#problema-1). Problema 1:\r\n\r\nPentru un număr natural $N$ dat, se cere numărul maxim de regiuni în care se poate împărţi planul folosind $N$ drepte.\r\n\r\np=. !probleme-de-taietura?poza-1.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nMai întâi facem vom face două observaţii:\r\nÎn configuraţia cu număr maxim de regiuni nu vom avea două drepte paralele, pentru că două drepte care se intersectează formează în plan patru regiuni, în timp ce două drepte paralele formează în plan doar trei regiuni.\r\nDe asemenea pentru a obţine un număr maxim de regiuni, nu vor exista trei drepte care să se intersecteze intr-un punct pentru că astfel am pierde o regiune triunghiulară formată din punctele de intersecţie ale celor trei drepte.\r\nDacă aceste două condiţii sunt îndeplinite vom vedea în continuare că orice configuraţie de $N$ drepte împarte planul în acelaţi număr de regiuni. Notăm cu $d(n)$ acest număr. Presupunem ca ştim pe $d(n)$ , să vedem acum ce se întâmplă dacă mai adaugăm o dreaptă. \r\nAceastă nouă dreaptă va fi intersectată de celelalte drepte în $n$ puncte distincte. Fiecare segment de dreaptă şi semidreaptă în care este împărţită a $n+1-a$ taie o regiune veche in două regiuni noi. De aici tragem concluzia că $d(n+1) = d(n) + n + 1$ . Deci $d(n) = n + n – 1 + n – 2 + … + 2 + d(1)$ . Astfel folosind indentitatea $1 + 2 + 3 + … + n = n(n+1)/2$ obţinem $d(n) = n(n + 1) / 2 + 1$ .\r\nMenţionăm că problemele în care se cere maximizarea numărului de regiuni în care un pătrat, un triunghi sau un cerc este împărţit de $n$ drepte, au aceiaşi soluţie.\r\n\r\np=. !probleme-de-taietura?poza-2.bmp!\r\n\r\nh2(#problema-2). Problema 2:\r\n\r\nDându-se un număr natural $N$ , se cere numărul maxim de regiuni în care $N$ cercuri pot împărţi planul.\r\n\r\np=. !probleme-de-taietura?poza-4.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nEste clar că oricare două cercuri trebuie să se intersecteze in exact două puncte, nu să fie tangente sau să nu se intersecteze deloc pentru că astfel am pierde o regiune, iar oricare trei cercuri nu se intersectează într-un punct.\r\nOrice configuraţie care satisface această cerinţă va împărţi planul într-un număr maxim de regiuni.Vom nota cu $c(n)$ numărul maxim de regiuni în care este împărţit planul de $n$ cercuri. Să vedem ce se întîmplă când adăugăm un nou cerc la această configuraţie. Cercul nou va fi intersectat de cele $n$ cercuri în $2n$ puncte distincte, şi astfel va fi împărţit în $2n$ arce. Fiecare dintre aceste arce împarte o zonă veche în două zone noi. De aici tragem concluzia că $c(n + 1) = 2n + c(n)$ . Astfel putem să îl scriem pe $c(n) ca 2(n – 1) + 2(n – 2) + … + 2 + c(1)$ . De aici folosind din nou identitatea $1 + 2 + … + n = n(n+1)/2$ avem că $c(n) = n(n-1) + 2$ .\r\nEste evident că şi problema în care se cere maximizarea numărului de regiuni în care este împărţită suprafaţa unei sfere de $n$ cercuri are aceiaşi soluţie.\r\n\r\np=. !probleme-de-taietura?poza-5.bmp!\r\n\r\nh2(#problema-3). Problema 3:\r\n\r\nSe dau $n$ cercuri care se intersectează oricare două în două puncte şi nu există trei care se intersectează într-un punct, se cere să se determine numărul de zone în care este împarţit planul de aceste $n$ cercuri. ( $n <= 10^100$ )\r\n[[\"acm.uva.es\":http://www.acm.uva.es] 10519 !! Really Strange !!]\r\n\r\nh3. Rezolvare:\r\n\r\nObservăm ca sunt indeplinite condiţiile de maximalitate cerute mai sus, deci rezultatul e $c(n)$ , singura problema ce rămâne este aceea de implementare a operaţiilor cu numere mari.\r\n\r\nh2(#problema-4). Problema 4:\r\n\r\nAvem un număr natural $N$ , vrem să determinăm numărul maxim de regiuni în care poate fi împărţit un plan de elipse.\r\n\r\np=. !probleme-de-taietura?poza-6.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nLa fel ca şi la cercuri nici aici nu trebuie să avem elipse tangente, sau elipse care să nu se intersecteze, nu vor exista nici aici trei elipse care să se intersecteze într-un punct, aici elipsele trebuie să se intersecteze în patru puncte, dacă s-ar intersecta numai în două puncte atunci configuraţia nu ar avea număr maxim de regiuni.\r\nNotăm cu $e(n)$ numărul de care suntem interesaţi. Câte regiuni noi apar cand adăugam o nouă elipsă? Păi o nouă elipsă va fi intersectată de celelalte elipse ăn patru puncte de fiecare, deci $e(n + 1) = 4n + e(n)$ . De aici tragem concluzia că $e(n) = 2 n(n - 1) + 2$ .\r\n\r\np=. !probleme-de-taietura?poza-7.bmp!\r\n\r\nh2(#problema-5). Problema 5:\r\n\r\nDându-se un număr natural $N$ , se cere numărul maxim de regiuni în care $N$ triunghiuri pot împărţi planul.\r\n\r\np=. !probleme-de-taietura?poza-8.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nRepetând raţionamentul de la problemele anterioareavem că $t(n+1) = 6n + t(n) => t(n) = 3n(n-1) + 2$ . \r\n\r\np=. !probleme-de-taietura?poza-9.bmp!\r\n\r\nh2(#problema-6). Problema 6:\r\n\r\nPentru $N$ plane determinaţi numărul maxim de zone în care poate fi împărţit spaţiul cu acestea.\r\n\r\nh3. Rezolvare:\r\n\r\nÎn această problemă urmăm raţionamentul de până acum. Este evident că trebuie ca fiecare plan să se intersecteze cu fiecare, că oricare trei plane trebuie să nu se intersecteze într-o dreaptă, oricare trei plane nu trebuie să fie paralele cu o dreaptă şi oricare patru plane nu trebuie să se intersecteze într-un punct. Notăm $p(n)$ numărul maxim de zone în care $n$ plane împart spatiul. Când adaugăm un nou plan acesta va fi intersectat de celelalte plane în $n$ drepte, drepte care după restrictiile care le-am pus nu vor fi două paralele sau trei care să se intersecteze într-un punct. Acest plan va fi împărţit în $d(n)$  regiuni de aceste drepte din cauza restricţiilor impuse. Fiecare regiune din plan taie o zonă din spaţiu în două noi zone, de aici tragem concluzia că $p(n + 1) = d(n) + p(n)$ . Astfel avem $p(n) =  n(n-1)/2 + 1 + (n-1)(n-2)/2 + 1 + ...+2 * 1 / 2 + 1 + p(1) = ( n^2^ – n + (n-1)^2^ – (n-1)+... + 2^2^ – 2  +  1 – 1 + (n – 1) )/2+ 2 = ( n(n+1)(2n + 1)/6 – n(n+1)/2 + (n-1))/2 + 2  = (n^3^/3 + n^2^/2 + n/6 – n^2^/2 – n/2 )/2 + n + 1 = n^3^/ 6 + 5n/6 + 1$ . Am folosit identităţile $1 + 2 + … + n = n(n+1)/2 şi 1 + 2^2^ + 3^2^ + … + n^2^ = n(n+1)(2n+1)/6$ care se pot demonstra uşor prin inducţie.\r\nMenţionăm că dacă vrem să împărţim un cub, un cilindru o sfera etc în număr maxim de regiuni folosind $n$ plane, formula se păstrează.\r\n\r\nh2(#problema-7). Problema 7:\r\n\r\nDându-se un număr natural $N$ , să se determine numărul maxim de zone în care pot împărţi spaţiul $N$ sfere.\r\n[Bursele Agora 2001[3]]\r\n\r\nh3. Rezolvare:\r\n\r\nPornim la fel ca la problema anterioară, oricare două sfere se vor intersecta şi nu vor exista trei sfere care să se intersecteze în acelaşi punct. Vom nota cu $s(n)$ numărul maxim de regiuni în care poate fi împărţit spaţiul cu $n$ sfere. Să vedem ce se întâmplă când adăugăm o sferă. Această sferă va fi intersectată de toate celelalte $n$ sfere în $n$ cercuri, pentru ca numărul de regiuni noi să fie maxim aceste cercuri vor împărţi sfera într-un număr maxim de regiuni, acest număr este $c(n)$ aşa cum am discutat la problema 2. Obţinem astfel $s(n + 1) = c(n) + s(n) = c(n) + c(n-1) + ... + c(1) = n(n-1) + 2 + (n-1)(n-2) + 2 + ... + 2 = 1 + 2^2 + .. + n^2 – 1 – 2 – 3 - .... – n + 2n => s(n) = n(n^2 – 3n + 8) / 3$\r\n\r\nh2(#problema-8). Problema 8:\r\n\r\nSe dă un număr $N$ care este numărul maxim în care poate fi împărţit planul de $m$ elipse, $n$ cercuri şi $p$ triunghiuri. Se cere ştiind $N$ să se determine toate valorile posibile pentru $m$ , $n$ şi $p$ . ( $N$ întreg făra semn reprezentabil pe 32 de biţi, $0<=m<100$ , $0<=n<20000$ şi $0<=p<100$ )\r\n[10623 Thinking Backward [4]]\r\n\r\nh3. Rezolvare:\r\n\r\nDacă am ştii pentru trei parametrii $m$ , $n$ şi $p$ care este numarul maxim de părţi în care poate fi împărţit planul  de $m$ elipse, $n$ cercuri şi $p$ triunghiuri, atunci am putea incerca toate posibilitaţile pentru $m$ , $n$ şi $p$ şi am găsi tripletele pentru rezultatul ar fie egal cu $N$ , chiar am putea optimiza puţin acest algoritm iteram pe toate valorile de $m$ şi $p$ , astfel vom obţine o ecuaţie cu necunoscuta $n$ astfel vom face doar $10000$ de rezolvări de ecuaţii în loc de $200 000 000$ de comparaţii. \r\nSă vedem cum găsim numărul maxim de zone. Din nou oricare două figuri se intersectează în număr maxim de intersecţii, un cerc cu o elipsă în patru puncte, un cerc sau o elipsă cu un triunghi în şase puncte. Mai întâi punem cele $m$ elipse in plan, ele vor împărţi planul în $e(m)$ regiuni adică $2 m(m - 1) + 2$ . După aceea adaugăm cercurile. Să notam numarul maxim de zone în care $n$ cercuri şi $m$ elipse pot împărţi planul cu $ec(m , n)$ . Dacă ştim cât este $e(m, n-1)$ atunci când adaugăm un nou cerc, acesta va fi intersectat de $m$ elipse in $4m$ puncte şi de $n-1$ cercuri in $2(n – 1)$ puncte deci cercul va fi împărţit în $4m + 2(n-1)$ arce care vor împărţi tot atâtea regiuni care existau deja in câte două regiuni noi. Deci $ec(m, n) = 4m + 2(n-1) + ec(m, n-1) = 4m + 2(n-1) + 4m + 2(n-2) + … + 4m + 2 + ec(m, 0) = 4m(n-1) + n (n-1) + 2m(m-1) + 2$ . Să vedem ce se întâmplă când adăugăm triunghiurile. Vom nota $ect(m, n, p)$ numărul maxim de zone în care poate fi împărţit planul de $m$ elipse, $n$ cercuri şi $p$ triunghiuri. Dacă ştim cu cat e egal $ect(m, n, p - 1)$ , atunci când vom adăuga un nou triunghi acesta va intersecta cele $m$ cercuri în $6m$ puncte, cele $n$ elipse în $6n$ puncte şi cele $p – 1$ triunghiuri în $6(p – 1)$ puncte, astfel se vor forma $6m + 6n + 6(p-1)$ noi zone. Deci $ect(m, n, p) = 6(m + n + p – 1) + ect(m, n, p – 1) = 6 (m + n + p – 1 + m + n + p – 2 + … m + n + 1) + ect(n, m, 0) = 6 (p-1)(m+n) + 3p(p-1) + 4m(n-1) + n(n-1) + 2m(m-1) + 2$ .\r\n\r\nProblemele anterioare au fost cam matematice şi ele sunt numite de obicei de olimpici peiorativ ca “probleme de formulă”, majoritatea olimpicilor la informatică participă aici pentru că matematica nu le place aşa tare şi deci nici apariţia unor probleme ca cele de mai sus care sunt mai mult de mate decât de info nu îi prea încântă. Cum poate fi rezolvată o problemă de formulă fără să avem intuiţia matematică sau cunoţinţele matematice necesare? Păi câteodată elevii apelează la următorul truc: află primele câteva valori de mâna sau cu ajutorul unor algoritmi brute force şi apoi speră ca formula să fie de o anumită formă, de exemplu ar putea fi un polinom de un grad mic. Atunci avem ca $f(N) = An^3 + Bn^2 + Cn + D$ . Afland primele câteva valori vom ştii valorile $f(1), f(2), f(3), f(4)$ . Dând lui $n$ pe rand valorile 1, 2, 3 şi 4 putem face un sistem cu necunoscutele A, B, C şi D. Sau putem încerca să vedem cum se comportă şirul de numere, are o creştere polinomială sau exponenţială, apar valorile lui în triunghiul lui Pascal. Iar dacă rezolvăm problemele de acasă putem căuta valorile din şirul de soluţii pe internet pe pagina Eciclopedia Online a şirurilor de întregi [7] care este o resursă foarte utilă în cazul problemelor de acest gen .\r\n\r\nh2(#problema-9). Problema 9:\r\n\r\nSe dau $N$ drepte în plan, fiecare dreaptă este dată prin două puncte prin care trece. Se cere să se determine pentru această configuraţie în câte zone este împărţit planul. ( $n <= 1000$ )\r\n[Internet Problem Solving Contest 2000 [5]]\r\n\r\nh3. Rezolvare:\r\n\r\nÎn sfârşit o problemă în care avem nevoie să folosim calculatorul şi talentul nostru de programatori . Vom folosi aceeaşi idee ce a apărut şi în celelalte probleme, adică numărăm pe rând în câte zone este împărţit planul de primele o dreaptă, doua drepte respectiv $n$ drepte. Deci vom adăuga în ordine dreptele la configuraţia noastră. Când adăugăm o dreaptă ea va fi intersectată de dreptele deja adăugate în $k$ puncte nu neapărat distincte, pe noi ne intereseaza punctele distincte, ca să facem acest lucru putem sorta punctele în $O(k log k)$ sau să folosim o tabelă de dispersie şi astfel să aflăm în $O(k)$ numărul de puncte distincte, daca acest număr e egal cu $L$ atunci la numărul curent de zone vom adăuga $L$ . Astfel algoritmul are complexitatea $O(n^2 log n)$ , sau dacă folosim tabele de dispersie $O(n^2)$ .\r\n\r\nh2(#problema-10). Problema 10:\r\n\r\np=. !probleme-de-taietura?poza-10.bmp!\r\n\r\nAvem un tort în formă de pătrat de dimensiune $1000 x 1000$ . Folosim un cuţit pentru a tăoa tortul. Întrebarea este după o serie de tăieturi, în căte bucăţi am patriţionat tortul. Restricţii: Numărul de tăieturi nu va fi mai mare de $8$ . După tăieturi, lungimea oricărei laturi a partiţiei nu va fi mai mică decât unu. Coordonatele vârfurilor tortului vor fi $(0,0)(0,1000)(1000,1000) (1000,0)$ . Tăieturile se vor intersecta în două puncte cu marginile tortului. Următoarea imagine e un tort tăiat în zece bucăţi.\r\n[acm.uva.es 527 The partition of a cake]\r\n\r\nh3. Rezolvarea:\r\n\r\nEste analoaga cu cea a problemei anterioare, datele sunt foarte mici în problema aceasta, probabil că autorii au vrut să facă problema accesibilă şi altor idei care folosesc împărţiri efective în poligoane a pătratului.\r\n\r\nh2(#problema-11). Problema 11:\r\n\r\np=. !probleme-de-taietura?poza-12.bmp!\r\n\r\nSe dă un graf planar prin noduri şi muchii, un graf este planar dacă există o modalitate de a îl desena în plan făra ca muchiile să se intersecteze decăt la capete. Se cere să se determine în căte regiuni împarte planul graful dat la intrare. Mai jos avem un exemplu de graf în care feţele sunt numerotate.\r\n[10178 Count the faces [4]]\r\n\r\nh3. Rezolvare:\r\n\r\nEste interesant faptul că în această problemă nu ne este dată configuraţia în plan a grafului ci doar structura lui. Un graf il putem reprezenta în mai multe moduri în plan, astfel suntem duşi înspre ideea că există ceva formulă care rezolvă problema. O formulă întradevăr există şi se numeşte formula lui Euler pentru grafurile planare. Formula arată aşa $f - m + n  = 2$ , unde prin $f$ am notat numărul de feţe, $m$ numărul de muchii şi $n$ numărul de vârfuri, dacă graful nostru e conex (formula include faţa exterioară). Această formulă poate fi demonstrată în foarte multe moduri. Dacă vreţi să vedeţi 19 metode de demonstrare puteţi să vizitaţi adresa [8]. O demonstraţie simplă ar fi prin inducţie pornind de la un arbore şi adăugând pe rând câte o muchie. La început avem o singură faţă, cea infinită, $1 – (n – 1) + n = 2$ se verifică. Fiecare muchie adăugată împarte o faţă în două deci dacă aveam inainte $f – m + n = 2$ acum vom avea $f1 – m1 + n = 2$ unde $f1 = f + 1$ şi $m1 = m + 1$ . Deci am demonstrate formula şi putem foarte uşor să rezolvăm problema, mai trebuie numai să avem grijă ca pentru fiecare componentă conexă număram faţa infinită.\r\nAceastă formulă este adevarată şi în spaţiu pentru poliedre.\r\n\r\nh2(#problema-12). Problema 12:\r\n\r\np=. !probleme-de-taietura?poza-13.bmp!\r\n\r\nSe considera $N$ cercuri in plan. Se cere să se determine numărul de zone finite în care cercurile date împart planul.\r\n \r\nExemplu\r\nCERCURI.IN\r\n4\r\n90 110 50\r\n130 70 30\r\n155 45 15\r\n165 115 65\r\nCERCURI.OUT\r\n$11$\r\n[Algoritmus, Cercuri[6]]\r\n\r\nh3. Rezolvare:\r\n\r\nContraexemple rezolvare normala\r\nO rezolvare folosind geometria computaţională pare foarte grea, lucrurile simplificându-se mult daca abordam problema prin prisma unor noţiuni de teoria grafurilor.\r\nFiecare punct de intersectie va fi considerat un nod. Două noduri vor fi legate prin o muchie dacă există un cerc pe care sa se afle amândouă iar între ele să nu existe nici un alt punct de intersectie.\r\nAcum vom folosi identitatea lui Euler: prezentată în problema anterioară. În problema noastră nu trebuie să numărăm şi faţa exterioară, deci formula folosita va fi $F=M-V+1$ . Această formulă este adevarată doar in cazul unei singure componente conexe. Pentru mai multe componente, formula devine $F=M-V+C$ , unde $C$ este numărul de componente conexe.\r\nO atenţie deosebită trebuie acordată punctelor de intersecţie prin care trec mai mult de două cercuri, pentru a nu le număra de mai multe ori. Putem rezolva aceasta problema prin sortarea punctelor de intersecţie ale unui cerc cu toate celelalte cercuri.\r\nDeasemenea, este necesara eliminarea cercurilor identice (cu acelaşi centru şi raze egale). Din orice mulţime cu astfel de cercuri este păstrat doar un singur element.\r\nDeoarece pentru fiecare cerc este necesara o sortare a punctelor de intersectie, complexitatea generala a algoritmului va fi $O(N2*log(N))$\r\n\r\nh2(#bibliografie). Bibliografie:\r\n\r\n# A.M. Iaglom, I. M. Iaglom, Probleme neelementare tratate elementat. Ed tehnică, Bucureşti, 1962\r\n# I. Tomescu, Probleme de combinatorică şi teoria grafurilor, ed didactică şi pedagogică. Bucureşti, 1981\r\n# Colecţia Ginfo\r\n# [\"acm.uva.es\":acm.uva.es]\r\n# [\"ipsc.ksp.sk\":ipsc.ksp.sk]\r\n# [\"algoritmus.org/index.php\":algoritmus.org/index.php]\r\n# [\"http://www.research.att.com/~njas/sequences/ \":http://www.research.att.com/~njas/sequences/]\r\n# [\"http://www.ics.uci.edu/~eppstein/junkyard/euler/ \":http://www.ics.uci.edu/~eppstein/junkyard/euler/]\r\n',7668,'public',NULL,NULL),('utilizator/andrici_cezar','Profil andrici_cezar','2008-02-20 11:15:10','2009-04-21 19:25:46',' *Despre mine*\r\n\r\n Sunt un elev din clasa a VI aB de la Liceul de Informatica Gr.C.Moisil Iasi.\r\n\r\n\r\n *Distinctii primite*\r\n\r\n_Premiul I la Informatica la ,,Urmasii lui Moisil\", la clasa a 4a!!!`````````anul 2007_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 5a!!!```````anul 2008_\r\n_Premiul III la Informatica Faza Judeteana-98 puncte, la clasa a 5a!!!````anul 2008_ (Calificat la ONI 2008)\r\n_Mentiune la Informatica Faza Nationala-160 puncte, la clasa a 5a!!!````anul 2008_ (Pe locul 8)\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 9a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 5a!!!`````````anul 2008_\r\n_Premiul II la Informatica la ,,Moisil++\", la clasa a 5a!!!````````````anul 2008_\r\n_Premiul I la Informatica la ,,Concursul National al centrelor de Excelenta\", la clasa a 5a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil:, la clasa a 6a!!!``````````anul 2009_\r\n_Premiul II la Informatica la Faza Locala-110 puncte, la clasa a 6a!!!`````anul 2009_\r\n_Premiul III la Informatica la Faza Judeteana-40 puncte, la clasa a 6a!!!````anul 2009_ (Calificat la ONI 2009)\r\n_Mentiune la Informatica Faza Nationala-230 puncte, la clasa a 6a!!!````````anul 2009_ (Pe locul 4)\r\n\r\n\r\n*.Campion*\r\n*2008 - 2009* - 916 puncte clasat pe locul 51\r\n\r\n*Alte rezultate*\r\nChemat la CEX la a 9a 2009(cls.a 6a)\r\n\r\n*Profesori*\r\nIvasc Cornelia si Mirela Tibu ->[\'Elevi\':http://olimpiada.info/oji2009/index.php?cid=participanti&w=gim&judet=25&clasa=6]\r\nInfoarena\r\n.Campion\r\n\r\n*Citate preferate*\r\n_Daca plangi pentru ca soarele a disparut din viata ta, lacrimile te vor impiedica sa vezi stelele_ - Rabindranath Tagore\r\n\r\n_Un om nu este distrus atunci cind este invins; e distrus atunci cind renunta_- Richard Milhous Nixon\r\n\r\n_Nu este intelept sa fii sigur asupra propriei tale intlepciuni. Este sanatos sa ti se aminteasca ca si cel puternic poate slabi, iar cel intelept poate gresi_ - Mahatma Gandhi\r\n\r\n_Cel puternic nu este cel care este de neinvins, ci cel care se ridica dupa fiecare lovitura_\r\n\r\n_Loveste spre soare chiar daca nu reusesti, macar o sa fii printre stele_\r\n\r\nh3. Prieteni\r\n\r\n==user(user=\"marta_dianna\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"antoanela\" type=\"tiny\")==\r\n(8)\r\n\r\n\r\n==user(user=\"matemariaescu\" type=\"tiny\")==\r\n(8)\r\n\r\n==user(user=\"liana\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"alexrusu\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"netedu_andrei\" type=\"tiny\")==\r\n(6)\r\n\r\n==user(user=\"mironalex2005\" type=\"tiny\")==\r\n(6)\r\n\r\n==user(user=\"unsilviu\" type=\"tiny\")==\r\n(7)\r\n\r\nScanteie Sebi(7)\r\nMunteanu Bogdan(8)\r\nAnton Madalina(8)\r\n\r\nToti am fost si anu trecut si anu asta la ONIgimnaziu si vom putea fi toti din nou doar peste 2 ani!\r\n\r\nh3. Prieteni care i-am vazut dar ne cunoastem doar prin messenger\r\n\r\n==user(user=\"toni2007\" type=\"tiny\")==\r\nMa ajuta la probleme\r\n==user(user=\"crawler\" type=\"tiny\")==\r\nTot la probleme\r\n==user(user=\"stef2n\" type=\"tiny\")==\r\nMa ajuta sa scriu articole\r\n==user(user=\"DITzoneC\" type=\"tiny\")==\r\nMa ajuta sa scriu probleme\r\n\r\nToti am fost si anu trecut si anu asta la ONIgimnaziu si vom putea fi toti din nou doar peste 2 ani!',7668,'public',NULL,NULL),('transformari-geometrice','transformari-geometrice','2009-04-12 08:01:38','2009-04-23 22:19:14','h1. Transformări geometrice\r\n\r\n(Categoria _Matematică_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'_Introducere_\':transformari-geometrice#introducere\r\n** \'Translaţia\':transformari-geometrice#translatia\r\n** \'Simetria\':transformari-geometrice#simetria\r\n** \'Rotaţia\':transformari-geometrice#rotatia\r\n** \'Omotetia\':transformari-geometrice#omotetia\r\n** \'Desfăşurarea în plan\':transformari-geometrice#desfasurarea-in-plan\r\n* \'Aplicaţia 1\':transformari-geometrice#aplicatia-1\r\n* \'Aplicaţia 2\':transformari-geometrice#aplicatia-2\r\n* \'Aplicaţia 3\':transformari-geometrice#aplicatia-3\r\n\r\nh2(#introducere). Introducere\r\n\r\nÎn acest articol vom introduce câteva noţuni legate de transformările geometrice care se pot dovedi utile în concursurile de programare.\r\n\r\nÎnainte de toate prezentăm câteva aspecte teoretice, o mare parte din ele nefiind foarte interesante şi probabil sunt conţinute şi în manualele de liceu. Cititorul poate trece direct la probleme şi, în măsura în care noţiunile din soluţii îi sunt neclare, poate reveni asupra părţii teoretice.\r\n\r\nh3(#translatia). Translaţia\r\n\r\nTranslaţia unei figuri geometrice reprezintă mişcarea tuturor componentelor ei pe o anumita distanţă si direcţie. Această transformare poate fi uşor caracterizată de un vector $v = (dx, dy)$. Când vrem să translatăm un punct $P(x, y)$ după $v$, e de ajuns să facem operaţia $P’ = P + v$. Astfel, $P’$ are cooronatele $(x + dx, y + dy)$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* pastrează orientarea poligoanelor (adică, dacă vârfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi şi ele în ordine trigonometrică);\r\n* păstrează unghiurile;\r\n* o dreaptă va fi transformată în altă dreaptă paralelă cu prima;\r\n* înafară de translaţia trivială de vector $v = (0, 0)$, această transformare nu are puncte fixe (adică orice punct va fi transformat într-un punct diferit);\r\n* translaţii successive vor rezulta tot într-o translaţie (adică, dacă vrem să translatăm un punct dupa $v$ şi apoi după $v{~1~}$, atunci obţinem acelaşi rezultat dacă translatăm direct după $v + v{~1~}$);\r\n* translaţia este comutativă;\r\n\r\nh3(#simetria). Simetria\r\n\r\nExistă două tipuri de simetrii: simetria faţă de un punct şi simetria faţa de o dreaptă.\r\n\r\nUn punct $A$ îl are simetric pe $A’$ faţă de un punct $O$, dacă segmentul $AA’$ are ca mijloc punctul $O$. Dacă avem un punct $(x{~0~}, y{~0~})$ căruia vrem să îi aflăm simetricul faţă de un punct de coordonate $(x, y)$ atunci acesta va fi $(2x – x{~0~}, 2y – y{~0~})$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* păstrează orientarea poligoanelor (adică, dacă varfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi şi ele în ordine trigonometrică);\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* are ca punct fix punctul $O$, iar drepte fixe cele care trec prin punctul $O$;\r\n* simetrii succesive după centre diferite $O{~1~}(x{~1~}, y{~1~}) O{~2~}(x{~2~}, y{~2~})$ sunt o translaţie de vector $v = 2(x{~2~} – x{~1~})$;\r\n* simetriile după un punct nu comută;\r\n\r\nSă calculăm simetricul unui punct $P(x{~0~}, y{~0~})$ faţă de o dreaptă de ecuaţie $ax + by + c = 0$. Notăm cu $d$ distanţa de la punctul $P$ la dreaptă, <tex> d = \\displaystyle\\frac{|a*x_{0} + b*y_{0} + c|}{\\sqrt{a^2 + b^2}} </tex>, şi cu $(m{~1~}, m{~2~})$ cosinii directori ai vectorului $n(a, b)$ normal la dreaptă. Valorile cosinilor directori sunt: <tex> m_{1} = \\displaystyle \\pm \\frac{a}{\\sqrt{a^2 + b^2}} </tex> şi <tex> m_{2} = \\displaystyle \\pm \\frac{b}{\\sqrt{a^2 + b^2}} </tex>. Vom alege semnul minus dacă $ax{~0~} + by{~0~} + c > 0$ iar semnul plus dacă $ax{~0~} + by{~0~} + c < 0$. Astfel, simetricul punctului $P$ va avea coordonatele $(x{~0~} + 2*d*m{~1~}, y{~0~} + 2*d*m{~2~})$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* nu păstrează orientarea poligoanelor (adică, dacă varfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi în sens orar);\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* are ca puncte fixe dreapta de simetrie;\r\n* simetrii succesive după drepte paralele sunt o translaţie;\r\n* simetrii succesive după drepte concurente sunt rotaţii;\r\n* simetriile nu comută;\r\n\r\nh3(#rotatia). Rotaţia\r\n\r\nAceasta este o transformare care roteşte punctele în sens trigonometric în jurul unui punct numit centru de rotaţie după un unghi fixat numit unghi de rotaţie. Dacă avem rotaţia de centru $O(x{~0~}, y{~0~})$ şi unghi $alfa$, atunci imaginea unui punct $P(x, y)$ va fi $P’(x{~0~} + (x – x{~0~}) * cos(alfa)  - (y – y{~0~}) * sin(alfa), y{~0~} + (x – x{~0~}) * sin(alfa)  + (y – y{~0~}) * cos(alfa))$.\r\n \r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* păstrează orientarea poligoanelor;\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* dacă nu este o rotaţie trivială de unghi $0$ atunci are ca punct fix centrul de rotaţie;\r\n* nu are drepte fixe, dar are cercuri fixe centrate în centrul de rotaţie;\r\n* două rotaţii succesive $R{~1~}(O{~1~}, alfa)$ şi $R{~2~}(O{~2~}, beta)$ se compun într-o translaţie sau o rotaţie $R{~3~}(O{~3~}, alfa + beta)$;\r\n* în general rotaţiile nu comută;\r\n\r\nh3(#omotetia). Omotetia\r\n\r\nAceasta este o transformare ce scalează obiectele în funcţie de un centru de omotetie şi un raport. Un punct $P(x, y)$ transformat după o omotetie $H(O(x{~0~}, y{~0~}), k)$ (centru $O$ şi raport $k$) va avea imaginea $P’(x{~0~} + k * (x - x{~0~}), y{~0~} + k * (y - y{~0~}))$.\r\n\r\nProprietăţi:\r\n\r\n* nu păstrează distanţele;\r\n* păstrează orientarea poligoanelor;\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele, iar transformata unei drepte va fi paralelă cu dreapta;\r\n* are ca punct fix centrul de omotetie;\r\n* două omotetii succesive $H{~1~}(O{~1~}, k{~1~})$ şi $H{~2~}(O{~2~}, k{~2~})$ se compun într-o translaţie sau omotetie $H{~3~}(O{~3~}, k{~1~} + k{~2~})$;\r\n* în general omotetiile nu comută;\r\n\r\nh3(#desfasurarea-in-plan). Desfăşurarea în plan\r\n\r\nAceasta nu este o transformare geometrică propriu-zisă, ci mai mult o tehnică folositoare în rezolvarea unor probleme pe care o puteţi vedea aplicată în problemele ce urmează ...\r\n\r\n*To do:* de verificat teoria de aici. :)\r\n\r\nh2(#aplicatia-1). Aplicaţia 1\r\n\r\n!< transformari-geometrice?aplicatie-1.1.png 60%!\r\n\r\nbq. Fie două puncte $A$ şi $B$ de aceiaşi parte a unei drepte $d$. Se cere să se determine un punct $M$ pe dreapta $d$ cu proprietatea că suma $AM + MB$ e mininimă.\r\n\r\n!> transformari-geometrice?aplicatie-1.2.png 60%!\r\n\r\nh3. Rezolvare:\r\n\r\nDucem simetricul punctului $A$ faţă de dreapta $d$ pe care îl notăm cu $A’$. Oricare ar fi un punct $N$ pe dreapta $d$, $AN = A’N$ pentru că triunghiul $AA’N$ este isoscel având dreapta $d$ şi înălţime şi mediană. Astfel, avem că $AN + NB = A’N + NB$, deci pentru ca să minimizăm suma $AM + MB$ trebuie de fapt să minimizăm suma $A’M + MB$. Punctele $A’$ şi $B$ sunt situate de părţi diferite ale dreptei, deci punctul $M$ trebuie situat la intersecţia segmentului $A’B$ cu dreapta $d$.\r\n\r\nh2(#aplicatia-2). Aplicaţia 2\r\n\r\n!< transformari-geometrice?aplicatie-2.1.png 60%!\r\n\r\nbq. Fie două puncte $A$ şi $B$ în interiorul unui unghi format de semidreptele $d{~1~}$ şi $d{~2~}$ care au capătul comun $O$. Se cere să se determine două puncte $M$ şi $N$ astfel ca $M$ să aparţină lui $d{~1~}$ şi $N$ să aparţină lui $d{~2~}$ iar suma $AM + MN + NB$ să fie minimă.\r\n\r\n!> transformari-geometrice?aplicatie-2.2.png 60%!\r\n\r\nh3. Rezolvare:\r\n\r\nFolosim aceeaşi idee: ducem simetricul punctului $A$, notat cu $A’$, faţă de dreapta $d{~1~}$ şi simetricul punctului $B$ notat cu $B’$ faţă de dreapta $d{~2~}$. Orice puncte $M$ şi $N$ am alege, avem că $AM + MN + NB = A’M + MN + NB$. Pentru a minimiza suma $A’M + MN + NB’$ trebuie ca $M$ şi $N$ să fie intersecţiile segmentului $A’B’$ cu semidreptele $d{~1~}$ şi $d{~2~}$.\r\n\r\n\r\nh2(#aplicatia-3). Aplicaţia 3\r\n\r\n!< transformari-geometrice?aplicatie-3.1.png 70%!\r\n\r\nbq. Dându-se un triunghi ascuţitunghic $ABC$ se cere să se determine un triunghi înscris în acesta de perimetru minim.\r\n\r\nh3. Rezolvare:\r\n\r\n!> transformari-geometrice?aplicatie-3.2.png 70%!\r\n\r\nLuăm un punct $M$ pe baza $BC$ a triunghiului $ABC$, un punct $P$ pe latura $AB$ şi un punct $N$ pe latura $AC$. Dacă avem $M’$ simetricul lui $M$ faţă de $AB$ şi $M’’$ simetricul lui $M$ faţă de $AC$, atunci $MN + NP + PM = M’’N + NP + PM’$. Ca să minimizăm această sumă, punctele $P$ şi $N$ trebuie să fie la intersecţia segmentului $M’M’’$ cu laturile $AB$, respectiv $AC$. Perimetrul triunghiului $MNP$ va fi egal cu lungimea segmentului $M’M’’$. Observăm că unghiul $M’AM’’$ are măsura egală cu $2 * măsura unghiului BAC$ şi că triunghiul $M’AM’’$ e isoscel de latură egală cu $AM$. Pentru ca $M’M’’$ să aibă lungimea minimă trebuie ca $AM$ să fie cât mai scurt. Acest segment este minim atunci când $M$ este piciorul înalţimii din $A$. La fel putem să deducem că $N$ este piciorul înălţimii din $B$, iar $P$ este piciorul înălţimii din $C$. Astfel, soluţia de perimetru minim este triunghiul ortic.\r\n\r\nh2(#aplicatia-4). Aplicaţia 4: \'PolyLine\':http://www.topcoder.com/stat?c=problem_statement&pm=4509 (TopCoder)\r\n\r\nbq. Se consideră un dreptunghi cu colţurile de coordonate $(0, 0)$ , $(a, 0)$, $(a, b)$, $(0, b)$. Mai considerăm două puncte $A$ şi $B$ de coordonate $(x{~1~}, y{~1~})$ şi $(x{~2~}, y{~2~})$ în interiorul dreptunghiului. Se cere să se determine lungimea minimă a unei linii frânte ce porneşte din $A$ ajunge în $B$ şi intersectează fiecare latură a dreptunghiului. În figura de mai jos, avem un dreptunghi de dimensiuni $4 x 3$ şi trei posibilităţi de a plasa două puncte în interiorul dreptunghiului, împreună cu soluţiile optime. Rezultatele pentru cele trei exemple sunt: $7.8102$, $8.6023$, respectiv $9.4339$.\r\n\r\n!transformari-geometrice?aplicatie-4.1.png 70%!\r\n\r\nh3. Rezolvare:\r\n\r\n!transformari-geometrice?aplicatie-4.2.png 70%!\r\n\r\nEste evident că o soluţie optimă va fi formată din cinci segmente. Putem încerca toate ordinele posibile ale drumului liniei frânte, fiind $4! = 24$ asemenea ordini. Pentru fiecare ordine căutăm drumul optim. Acesta poate fi găsit folosind trucul prezentat în problemele anterioare. Să luăm un exemplu: pentru punctele $A(1, 2)$ şi $B(1,3)$ şi dreptunghiul de dimensiuni $4$ şi $3$, luăm punctele $M, N, P, Q$ pe laturile din stânga, jos, dreapta respectiv sus ale dreptunghiului astfel încât să minimizăm suma $AM + MN + NP + PQ + QB$. Acum, vom duce simetricul lui $A$, notat cu $A’$, faţă de latura din stânga şi simetricul lui $B$, notat cu $B’$, faţă de latura de sus. Avem că $AM = A’M$ şi $QB = QB’$. Deci, ca să minimizăm suma $AM + MN + NP + PQ + QB$ trebuie să minimizăm suma $A’M + MN + NP + PQ + QB’$. Vom duce simetricul lui $A’$, notat prin $A’’$, faţă de latura de jos, şi simetricul lui $B’$, notat prin $B’’$, faţă de latura din dreapta. Avem că $A’M + MN <= A’’N$ şi că $PQ + QB’ <= QB’’$, deci obţinem că pentru a minimiza suma $AM + MN + NP + PQ + QB$ trebuie să minimizăm suma $A’’M + MN + NB’’$. Putem realiza acest obiectiv dacă $M$ şi $N$ vor fi intersecţiile segmentului $A’’B’’$ cu latura de jos, respectiv latura din dreapta a dreptunghiului, iar soluţia este exact distanţa de la $A’’$ la $B’’$.\r\n',3146,'public',NULL,NULL),('utilizator/mathboy','Profil mathboy','2008-12-24 18:43:37','2009-04-25 19:47:03','h2. Despre mine\r\n\r\nElev in clasa a IX-a D,Matematica-Informatica,Informatica Intensiv\r\n\r\n Colegiul National Unirea Focsani\r\n\r\nContact: dragos_mathboy@yahoo.com\r\n\r\nh2. Distinctii primite\r\n\r\nPremiul III OJI 2009 Focsani clasa a 9-a\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n==user(user=\"DraStiK\" type=\"tiny\")==\r\n\r\n\r\n \r\n==user(user=\"Florian\" type=\"tiny\")==\r\n\r\n==user(user=\"drag0s93\" type=\"tiny\")==\r\n\r\n==user(user=\"andrici_cezar\" type=\"tiny\")==\r\n\r\n==user(user=\"bogdanhm999\" type=\"tiny\")==\r\n\r\n==user(user=\"StefanGeo\" type=\"tiny\")==\r\n\r\n==user(user=\"lucianvn\" type=\"tiny\")==\r\n\r\n==user(user=\"bolovanemil\" type=\"tiny\")==\r\n\r\n==user(user=\"rob3rtinho93\" type=\"tiny\")==\r\n\r\n',9232,'public',NULL,NULL),('utilizator/mathboy','Profil mathboy','2008-12-24 18:43:37','2009-04-25 19:57:13','h2. Despre mine\r\n\r\nElev in clasa a IX-a D,Matematica-Informatica,Informatica Intensiv\r\n\r\nColegiul National Unirea Focsani\r\n\r\nContact: dragos_mathboy@yahoo.com\r\n\r\nh2. Distinctii primite\r\n\r\nPremiul III OJI 2009 Focsani clasa a 9-a\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n==user(user=\"DraStiK\" type=\"normal\")==\r\n \r\n==user(user=\"Florian\" type=\"normal\")==\r\n\r\n==user(user=\"drag0s93\" type=\"normal\")==\r\n\r\n==user(user=\"andrici_cezar\" type=\"normal\")==\r\n\r\n==user(user=\"bogdanhm999\" type=\"normal\")==\r\n\r\n==user(user=\"StefanGeo\" type=\"normal\")==\r\n\r\n==user(user=\"lucianvn\" type=\"normal\")==\r\n\r\n==user(user=\"bolovanemil\" type=\"normal)==\r\n\r\n==user(user=\"rob3rtinho93\" type=\"normal\")==\r\n\r\n',9232,'public',NULL,NULL),('utilizator/mathboy','Profil mathboy','2008-12-24 18:43:37','2009-04-25 20:18:37','h2. Despre mine\r\n\r\nElev in clasa a IX-a D,Matematica-Informatica,Informatica Intensiv\r\n\r\nColegiul National Unirea Focsani\r\n\r\nContact: dragos_mathboy@yahoo.com\r\n\r\nh2. Distinctii primite\r\n\r\nPremiul III OJI 2009 Focsani clasa a 9-a\r\n\r\n\r\nh2. Prieteni pe infoarena \r\n \r\n==user(user=\"Florian\" type=\"tiny\")== \r\n\r\n==user(user=\"drag0s93\" type=\"tiny\")==\r\n\r\n==user(user=\"andrici_cezar\" type=\"tiny\")==\r\n\r\n==user(user=\"bogdanhm999\" type=\"tiny\")==\r\n\r\n==user(user=\"StefanGeo\" type=\"tiny\")==\r\n\r\n==user(user=\"lucianvn\" type=\"tiny\")==\r\n\r\n==user(user=\"bolovanemil\" type=\"tiny\")==\r\n\r\n==user(user=\"rob3rtinho93\" type=\"tiny\")==\r\n==user(user=\"DraStiK\" type=\"normal\")== \r\n\r\n',9232,'public',NULL,NULL),('andrici_cezar/string','andrici_cezar/Stringuri C++/Pas','2009-04-26 06:38:49','2009-04-26 06:54:53','h2. Stringuri in C++\r\n\r\n{+Pointeri+} Variabile cara au ca valoare o adresă de memorie terminata cu terminator de sir {$\'\\0\'$};\r\n\r\nh2. Declarare:\r\n\r\n== code(cpp) |\r\n\r\nchar sir[lg+1],*p;\r\n\r\n//lg=lungime sirului + o pozitie pentru terminator\r\n//*p pointer\r\n\r\n==\r\n\r\nh2. Iniţializări\r\n\r\na) la declarare\r\n\r\n== code(cpp) |\r\n\r\nchar var[]=\"aeiouAEIOU\";\r\n     *cif[]=\"0123456789\"\r\n     sir[1000]=\"Exemplu de string 2009\"\r\n \r\n==\r\n\r\nb)Prin citire\r\n\r\n*\r\n\r\n== code(cpp) |\r\n\r\nchar sir[lg+1],*p;\r\n//lg=lungime sirului + o pozitie pentru terminator\r\n//*p pointer\r\n\r\n==',7668,'public',NULL,NULL),('andrici_cezar/string','andrici_cezar/Stringuri C++/Pas','2009-04-26 06:38:49','2009-04-26 07:26:32','h2. Stringuri in C++\r\n\r\n{+Pointeri+} Variabile cara au ca valoare o adresă de memorie terminata cu terminator de sir {$\'\\0\'$};\r\n\r\nh3. Declarare:\r\n\r\n== code(cpp) |\r\n\r\nchar sir[lg+1],*p;\r\n\r\n//lg=lungime sirului + o pozitie pentru terminator\r\n//*p pointer\r\n\r\n==\r\n\r\nh3. Iniţializări\r\n\r\n== code(cpp) |\r\n\r\nchar var[]=\"aeiouAEIOU\",*cif[]=\"0123456789\",sir[1000]=\"Exemplu de string 2009\";\r\n \r\n==\r\n\r\nh3. Citirea\r\n\r\n* Text fară caractere albe\r\n\r\nCitire la {+iostream.h+} sau {+fstream.h+}\r\n\r\n== code(cpp) |\r\n\r\nfin>>sir;\r\n\r\n==\r\n\r\nsau la {+stdio.h+}\r\n\r\n== code(cpp) |\r\n\r\nscanf(\"%s\",&sir);\r\n\r\n==\r\n\r\n* Text cu caractere albe\r\n\r\nCitire la {+iostream.h+} sau {+fstream.h+}\r\n\r\n== code(cpp) |\r\n\r\nfin.get(sir,lg-max)\r\n\r\nfin.get(sir,lg-max,caracter-de-oprire)\r\n\r\n==\r\n\r\nSe citeşte şirul până la caracter-de-oprire, dar fără a depăşi lg-maxş\r\n\r\n== code(cpp) |\r\n\r\nfin.get(sir,20,\' \'); //sir=\"exemplu\"\r\nfin.get(sir,20,\'.\'); //sir=\"exemplu de string 20\"\r\nfin.get(sir,999); //sir=\"exemplu de string 2009\"\r\n\r\n==\r\n\r\n* Citirea cu $fin.gettline$\r\n\r\n== code(cpp) |\r\n\r\nfin.gettline(sir,lg_max);\r\nfin.gettline(sir,lg_max,caracter-de-oprire);\r\n\r\n==\r\n\r\n$gettline$ extrage şi caracterul de oprire din zona breffer(intermediară);\r\n$get$ doar verifică dacă urmează caracterul de oprire, nu îl extrage;\r\n\r\n== code(cpp) |\r\n\r\nfin.get(); //extrage caracterul curent din breffer\r\ngets(sir); // citeşte şirul curent (poate contine şi spaţii)\r\n\r\n==\r\n\r\nh3. Afisarea\r\n\r\nAfisarea în {+iostream.h+} şi {+fstream.h+}\r\n\r\n==code(cpp) |\r\n\r\nfout<<sir;\r\n\r\n==\r\n\r\nsau în {+stdio.h+}\r\n\r\n==code(cpp) |\r\n\r\nprintf(\"%s\",sir);\r\n\r\n==\r\n\r\nh3. Funcţii\r\n\r\n* Aflarea lungimii unui sir\r\n\r\n==code(cpp) |\r\n\r\na=\"String\"\r\nn=strlen(a); //n=6\r\n\r\n* Copiere $a$ <- $b$\r\n\r\n==code(cpp) |\r\n\r\nstrcpy(a,b);\r\n\r\n==\r\n\r\n* $a$ <- secventa din $b$\r\n\r\n==code(cpp) |\r\n\r\nb=\"String\";\r\nstrcpy(a,b,nr_caractere);\r\na[nr_caractere]=\'\\0\'; \r\n\r\nb=\"String\";\r\nstrcpy(a,b,5);\r\na[nr_caractere]=\'\\0\'; //a=\"Strin\"\r\n\r\n==\r\n',7668,'public',NULL,NULL),('algoritmiada-2009/clasament/runda-finala/5-8','Algoritmiada 2009, Clasament Runda Finala, Clasele 5-8','2009-04-26 18:34:14','2009-04-26 18:34:14','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda5-5-8\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2009/runda-finala/rezultate\")==\r\n\r\n(htabs-2)*(active) \'Clasele 5-8\':algoritmiada-2009/clasament/runda-finala/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-finala/9-10\r\n* \'Clasele 10-11\':algoritmiada-2009/clasament/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-finala/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda5-5-8\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',2028,'protected',NULL,NULL),('algoritmiada-2009/runda-finala/program','Algoritmiada 2009, Runda Finala - Program de desfasurare','2009-04-26 18:47:43','2009-04-26 18:47:43','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Algoritmiada 2009, Runda Finala - Program de desfasurare\r\n\r\n(htabs)* \'Despre&hellip;\':algoritmiada-2009/runda-finala\r\n*(active) \'Program\':algoritmiada-2009/runda-finala/program\r\n* \'Regulament\':algoritmiada-2009/runda-finala/regulament\r\n* \'Probleme\':algoritmiada-2009/runda-finala/probleme\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-finala/5-8\r\n\r\nProgramul de mai jos este deschis la sugestii si se poate modifica pe parcursul desfasurarii concursului.\r\n\r\ntable{width:75%}. |_. Data |_. Activitati |\r\n| Vineri, 1 mai 2009 | * 12:00 - 15:00 Sosire si cazare participanti la hotelurile Traian si Decebal\r\n* 13:00 - 14:00 Pranz\r\n* 18:00 - 19:00 Deschidere oficiala\r\n* 19:00 - 20:00 Cina |\r\n| Sambata, 22 martie 2008 | * 08:00 - 09:00 Mic dejun\r\n* 09:00 - 09:30 Acomodare, testarea statiilor de lucru \r\n* *09:30 - 14:30 Proba de concurs*\r\n* 15:00 - 16:00 Pranz\r\n* 18:00 - 20:00 Cina\r\n* 20:00 - 22:00 Program surpriza | \r\n| Duminica, 23 martie 2008 | * 08:00 - 09:00 Mic dejun\r\n* 09:00 - 09:30 Evaluare live \r\n* 09:30 - 10:30 Consultare borderouri evaluare, contestatii\r\n* 11:00 - 12:00 Festivitatea de premiere\r\n* 13:00 - 14:00 Pranz\r\n* 19:00 - 20:00 Cina\r\n* Plecare |\r\n\r\nFestivitatea de deschidere si cea de premiere vor avea loc in Sala Senatului din cladirea rectoratului Universitatii Politehnice Bucuresti (Splaiul Independentei Nr. 313). Prezenta la festivitatea de deschidere este obligatorie.\r\n\r\nMasa se serveste in cantina rectoratului - etajul 5 din cladirea rectoratului UPB.\r\n\r\nConcurentii din afara Municipiului Bucuresti vor fi cazati in caminul P19 al UPB aflat pe Splaiul Independentei Nr. 290.\r\n\r\n==Include(page=\"template/preoni-2008/footer\")==',2028,'protected',NULL,NULL),('utilizator/andrici_cezar','Profil andrici_cezar','2008-02-20 11:15:10','2009-04-28 13:01:00',' *Despre mine*\r\n\r\n Sunt un elev din clasa a VI aB de la Liceul de Informatica Gr.C.Moisil Iasi.\r\n\r\n\r\n *Distinctii primite*\r\n\r\n_Premiul I la Informatica la ,,Urmasii lui Moisil\", la clasa a 4a!!!`````````anul 2007_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 5a!!!```````anul 2008_\r\n_Premiul III la Informatica Faza Judeteana-98 puncte, la clasa a 5a!!!````anul 2008_ (Calificat la ONI 2008)\r\n_Mentiune la Informatica Faza Nationala-160 puncte, la clasa a 5a!!!````anul 2008_ (Pe locul 8)\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 9a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 5a!!!`````````anul 2008_\r\n_Premiul II la Informatica la ,,Moisil++\", la clasa a 5a!!!````````````anul 2008_\r\n_Premiul I la Informatica la ,,Concursul National al centrelor de Excelenta\", la clasa a 5a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil:, la clasa a 6a!!!``````````anul 2009_\r\n_Premiul II la Informatica la Faza Locala-110 puncte, la clasa a 6a!!!`````anul 2009_\r\n_Premiul III la Informatica la Faza Judeteana-40 puncte, la clasa a 6a!!!````anul 2009_ (Calificat la ONI 2009)\r\n_Mentiune la Informatica Faza Nationala-230 puncte, la clasa a 6a!!!````````anul 2009_ (Pe locul 4)\r\n\r\n\r\n*.Campion*\r\n*2008 - 2009* - 916 puncte clasat pe locul 51\r\n\r\n*Alte rezultate*\r\nChemat la CEX la a 9a 2009(cls.a 6a)\r\n\r\n*Profesori*\r\nIvasc Cornelia si Mirela Tibu ->[\'Elevi\':http://olimpiada.info/oji2009/index.php?cid=participanti&w=gim&judet=25&clasa=6]\r\nInfoarena\r\n.Campion\r\n\r\n*Citate preferate*\r\n_Daca plangi pentru ca soarele a disparut din viata ta, lacrimile te vor impiedica sa vezi stelele_ - Rabindranath Tagore\r\n\r\n_Un om nu este distrus atunci cind este invins; e distrus atunci cind renunta_- Richard Milhous Nixon\r\n\r\n_Nu este intelept sa fii sigur asupra propriei tale intlepciuni. Este sanatos sa ti se aminteasca ca si cel puternic poate slabi, iar cel intelept poate gresi_ - Mahatma Gandhi\r\n\r\n_Cel puternic nu este cel care este de neinvins, ci cel care se ridica dupa fiecare lovitura_\r\n\r\n_Loveste spre soare chiar daca nu reusesti, macar o sa fii printre stele_\r\n\r\nh3. Prieteni\r\n\r\n==user(user=\"marta_dianna\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"antoanela\" type=\"tiny\")==\r\n(8)\r\n\r\n\r\n==user(user=\"matemariaescu\" type=\"tiny\")==\r\n(8)\r\n\r\n==user(user=\"liana\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"alexrusu\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"netedu_andrei\" type=\"tiny\")==\r\n(6)\r\n\r\n==user(user=\"mironalex2005\" type=\"tiny\")==\r\n(6)\r\n\r\n==user(user=\"unsilviu\" type=\"tiny\")==\r\n(7)\r\n\r\nScanteie Sebi(7)\r\nMunteanu Bogdan(8)\r\nAnton Madalina(8)\r\nBrezuleanu Razvan(8)\r\n\r\nToti am fost si anu trecut si anu asta la ONIgimnaziu si vom putea fi toti din nou doar peste 2 ani!\r\n\r\nh3. Prieteni care i-am vazut dar ne cunoastem doar prin messenger\r\n\r\n==user(user=\"toni2007\" type=\"tiny\")==\r\nMa ajuta la probleme\r\n==user(user=\"crawler\" type=\"tiny\")==\r\nTot la probleme\r\n==user(user=\"stef2n\" type=\"tiny\")==\r\nMa ajuta sa scriu articole\r\n==user(user=\"DITzoneC\" type=\"tiny\")==\r\nMa ajuta sa scriu probleme\r\n==user(user=\"mathboy\" type=\"tiny\")==\r\nVorbim despre probleme\r\n==user(user=\"cipriancx\" type=\"tiny\")==\r\nVorbim despre probleme\r\n',7668,'public',NULL,NULL),('utilizator/andrici_cezar','Profil andrici_cezar','2008-02-20 11:15:10','2009-04-29 15:35:06',' *Despre mine*\r\n\r\n Sunt un elev din clasa a VI aB de la \'Liceul de Informatica Gr.C.Moisil Iasi\':http://liis.ro.\r\n\r\n\r\n *Distinctii primite*\r\n\r\n_Premiul I la Informatica la ,,Urmasii lui Moisil\", la clasa a 4a!!!`````````anul 2007_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 5a!!!```````anul 2008_\r\n_Premiul III la Informatica Faza Judeteana-98 puncte, la clasa a 5a!!!````anul 2008_ (Calificat la ONI 2008)\r\n_Mentiune la Informatica Faza Nationala-160 puncte, la clasa a 5a!!!````anul 2008_ (Pe locul 8)\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 9a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 5a!!!`````````anul 2008_\r\n_Premiul II la Informatica la ,,Moisil++\", la clasa a 5a!!!````````````anul 2008_\r\n_Premiul I la Informatica la ,,Concursul National al centrelor de Excelenta\", la clasa a 5a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 6a!!!``````````anul 2009_\r\n_Premiul II la Informatica la Faza Locala-110 puncte, la clasa a 6a!!!`````anul 2009_\r\n_Premiul III la Informatica la Faza Judeteana-40 puncte, la clasa a 6a!!!````anul 2009_ (Calificat la ONI 2009)\r\n_Mentiune la Informatica Faza Nationala-230 puncte, la clasa a 6a!!!````````anul 2009_ (Pe locul 4)\r\n\r\n\r\n*.Campion*\r\n*2008 - 2009* - 916 puncte clasat pe locul 51\r\n\r\n*Alte rezultate*\r\nChemat la CEX la a 9a 2009(cls.a 6a)\r\n\r\n*Profesori*\r\nIvasc Cornelia si Mirela Tibu ->[\'Elevi\':http://olimpiada.info/oji2009/index.php?cid=participanti&w=gim&judet=25&clasa=6]\r\nInfoarena\r\n.Campion\r\n\r\n*Citate preferate*\r\n_Daca plangi pentru ca soarele a disparut din viata ta, lacrimile te vor impiedica sa vezi stelele_ - Rabindranath Tagore\r\n\r\n_Un om nu este distrus atunci cind este invins; e distrus atunci cind renunta_- Richard Milhous Nixon\r\n\r\n_Nu este intelept sa fii sigur asupra propriei tale intlepciuni. Este sanatos sa ti se aminteasca ca si cel puternic poate slabi, iar cel intelept poate gresi_ - Mahatma Gandhi\r\n\r\n_Cel puternic nu este cel care este de neinvins, ci cel care se ridica dupa fiecare lovitura_\r\n\r\n_Loveste spre soare chiar daca nu reusesti, macar o sa fii printre stele_\r\n\r\nh3. Prieteni\r\n\r\n==user(user=\"marta_dianna\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"antoanela\" type=\"tiny\")==\r\n(8)\r\n\r\n\r\n==user(user=\"matemariaescu\" type=\"tiny\")==\r\n(8)\r\n\r\n==user(user=\"liana\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"alexrusu\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"netedu_andrei\" type=\"tiny\")==\r\n(6)\r\n\r\n==user(user=\"mironalex2005\" type=\"tiny\")==\r\n(6)\r\n\r\n==user(user=\"unsilviu\" type=\"tiny\")==\r\n(7)\r\n\r\nScanteie Sebi(7)\r\nMunteanu Bogdan(8)\r\nAnton Madalina(8)\r\nBrezuleanu Razvan(8)\r\n\r\nToti am fost si anu trecut si anu asta la ONIgimnaziu si vom putea fi toti din nou doar peste 2 ani!\r\n\r\nh3. Prieteni care i-am vazut dar ne cunoastem doar prin messenger\r\n\r\n==user(user=\"toni2007\" type=\"tiny\")==\r\nMa ajuta la probleme\r\n==user(user=\"crawler\" type=\"tiny\")==\r\nTot la probleme\r\n==user(user=\"stef2n\" type=\"tiny\")==\r\nMa ajuta sa scriu articole\r\n==user(user=\"DITzoneC\" type=\"tiny\")==\r\nMa ajuta sa scriu probleme\r\n==user(user=\"mathboy\" type=\"tiny\")==\r\nVorbim despre probleme\r\n==user(user=\"cipriancx\" type=\"tiny\")==\r\nVorbim despre probleme\r\n',7668,'public',NULL,NULL),('registru-diplome','Registru diplome','2007-06-26 09:34:59','2009-05-03 07:48:28','h1. Registru diplome\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nNe mandrim cu activitatea noastra si incercam sa premiem numai persoane care suntem convinsi ca merita. Incercam sa acordam diplome de onoare numai celor care intr-adevar inteleg spiritul infoarena si ne ajuta sa ne indeplinim obiectivele.\r\n\r\nFiecare diploma eliberata de infoarena este inseriata si inregistrata aici. O diploma infoarena care nu se gaseste in registrul de mai jos nu este valida.\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n\r\n\r\n|_. Nr.|_. Data     |_. Tip Diploma |_. Eveniment |_. Presedinte infoarena |_. Presedinte comisie |_. Eliberata pe numele |\r\n|  1 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Tataroiu Bogdan* |\r\n|  2 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Sperlea Adriana* |\r\n|  3 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Ionescu Victor* |\r\n|  4 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Simion Alexandru* |\r\n|  5 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Baltescu Paul Dan* |\r\n|  6 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Rusu Victor* |\r\n|  7 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Airinei Adrian* |\r\n|  8 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Grigorean Andrei* |\r\n|  9 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Savu Victor* |\r\n| 10 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Lica Adela* |\r\n| 11 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Savin Tiberiu* |\r\n| 12 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Stroe Marius* |\r\n| 13 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Istrate Stefan* |\r\n| 14 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Chis Raoul* |\r\n| 15 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Duta Vlad* |\r\n| 16 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Purice Andrei* |\r\n| 17 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Tudorica Alexandru* |\r\n| 18 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Velicu Adrian* |\r\n| 19 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Parcalabescu Maria* |\r\n| 20 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Gheorghe Cosmin* |\r\n| 21 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Dragus Marius* |\r\n| 22 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Sanduleac Dan* |\r\n| 23 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Puni Andrei Paul* |\r\n| 24 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Pasaila Daniel* |\r\n| 25 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Stanciu Valentin* |\r\n| 26 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Pasoi Mircea* |\r\n| 27 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Strat Cristian George* |\r\n| 28 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Luca Elisabeth* |\r\n| 29 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Cardei Claudia* |\r\n| 30 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Pastor Diana* |\r\n| 31 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Haret Alexandra* |\r\n| 32 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Radulescu Flaviu* |\r\n| 33 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Yuksel Ali* |\r\n| 34 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Florea Tiberiu* |\r\n| 35 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Vladu Adrian* |\r\n| 36 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Diaconu Adrian* |\r\n| 37 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Ganceanu Silviu Ionut* |\r\n| 38 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Crestez Leonard* |\r\n| 39 | 2007-06-25 | premiul 3, clasa IX       | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Sperlea Adriana* |\r\n| 40 | 2007-06-25 | premiul 2, clasa IX       | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Tataroiu Bogdan* |\r\n| 41 | 2007-06-25 | premiul 1, clasa IX       | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Tudorica Alexandru* |\r\n| 42 | 2007-06-25 | premiul 3, clasa X        | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Savu Victor* |\r\n| 43 | 2007-06-25 | premiul 2, clasa X        | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Puni Andrei* |\r\n| 44 | 2007-06-25 | premiul 1, clasa X        | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Gheorghe Cosmin* |\r\n| 45 | 2007-06-25 | premiul 3, clasele XI-XII | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Rusu Victor* |\r\n| 46 | 2007-06-25 | premiul 2, clasele XI-XII | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Simion Alexandru* |\r\n| 47 | 2007-06-25 | premiul 1, clasele XI-XII | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Grigorean Andrei* |\r\n| 48 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Dragos Ciobanescu* |\r\n| 49 | 2008-03-23 | premiu 1, clasele 5-8      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Cezar Mocan* |\r\n| 50 | 2008-03-23 | premiu 2, clasele 5-8      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Radu Stefan Voroneanu* |\r\n| 51 | 2008-03-23 | premiu 3, clasele 5-8      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Andrei Purice* |\r\n| 52 | 2008-03-23 | premiu 1, clasa 9      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Ioana Pandele* |\r\n| 53 | 2008-03-23 | premiu 2, clasa 9      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Alexandru Tache* |\r\n| 54 | 2008-03-23 | premiu 3, clasa 9      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Bogdan Bazu* |\r\n| 55 | 2008-03-23 | premiu 1, clasa 10      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Bogdan Tataroiu* |\r\n| 56 | 2008-03-23 | premiu 2, clasa 10     | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Istvan Hevele* |\r\n| 57 | 2008-03-23 | premiu 3, clasa 10      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Bogdan Casu-Pop* |\r\n| 58 | 2008-03-23 | premiu 1, clasele 11-12      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Cosmin Gheorghe* |\r\n| 59 | 2008-03-23 | premiu 2, clasele 11-12      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Alexandru Tandrau* |\r\n| 60 | 2008-03-23 | premiu 3, clasele 11-12      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Paul-Dan Baltescu* |\r\n| 61 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Radu Oprescu* |\r\n| 62 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Andrei Jurba* |\r\n| 63 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Palianos Cristian* |\r\n| 64 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Ada Solcan* |\r\n| 65 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Victor Popescu* |\r\n| 66 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Victor Ionescu* |\r\n| 67 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Alexandru Tudorica* |\r\n| 68 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Adriana Sperlea* |\r\n| 69 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Vlad Tataranu* |\r\n| 70 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Vicol Sergiu* |\r\n| 71 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Adrian Hulparu* |\r\n| 72 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Bogdan Taloi* |\r\n| 73 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Ioana Radu* |\r\n| 74 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Marius Petcu* |\r\n| 75 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Alex Mircescu* |\r\n| 76 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Radu Zernoveanu* |\r\n| 77 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Serban Stan* |\r\n| 78 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Vlad Gavrila* |\r\n| 79 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Filip Stefan* |\r\n| 80 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Tiberiu Savin* |\r\n| 81 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Florin Pogocsan* |\r\n| 82 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Marius Dragus* |\r\n| 83 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Alexandru Simion* |\r\n| 84 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Vlad Tudose* |\r\n| 85 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Mihai Damaschin* |\r\n| 86 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Victor Rusu* |\r\n| 87 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Adrian Airinei* |\r\n| 88 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Silviu Ganceanu* |\r\n| 89 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Filip Buruiana* |\r\n| 90 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Andrei Grigorean* |\r\n| 91 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Adrian Diaconu* |\r\n| 92 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Mircea Pasoi* |\r\n| 93 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Cristian Strat* |\r\n| 94 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Valentin Stanciu* |\r\n| 95 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Tiberiu Florea* |\r\n| 96 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Claudia Cardei* |\r\n| 97 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Alexandra Haret* |\r\n| 98 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Elisabeth Luca* |\r\n| 99 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Sergiu Strat* |\r\n| 100 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Maricel Mihalcea* |\r\n\r\n| 101 | 2009-05-02 | premiul 3, gimnaziu | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Gheorghe Mihai* |\r\n| 102 | 2009-05-02 | premiul 2, gimnaziu | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Siminiuc Antoanela 2 |\r\n| 103 | 2009-05-02 | premiul 1, gimnaziu | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Gavrilă Vlad 1 |\r\n| 104 | 2009-05-02 | premiul 3, clasele IX-X | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Mocan Cezar* |\r\n| 105 | 2009-05-02 | premiul 2, clasele IX-X | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Purice Andrei* |\r\n| 106 | 2009-05-02 | premiul 1, clasele IX-X | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Stan Şerban Andrei* |\r\n| 107 | 2009-05-02 | premiul 3, clasele XI-XII | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Szasz Robert* |\r\n| 108 | 2009-05-02 | premiul 2, clasele XI-XII | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Pârvu Andrei* |\r\n| 109 | 2009-05-02 | premiul 1, clasele XI-XII | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Tutunaru Mihai Cosmin* |\r\n| 110 | 2009-05-02 | premiul 3, studenţi | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Mugurel Ionuţ Andreica 3 |\r\n| 111 | 2009-05-02 | premiul 2, studenţi | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Tudose Vlad 2 |\r\n| 112 | 2009-05-02 | premiul 1, studenţi | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Saveluc Vlad 1 |\r\n| 113 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Silviu-Ionuţ Gănceanu*\r\n| 114 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Mircea Paşoi* | onoare |\r\n| 115 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Cristina Petrovici* | onoare |\r\n| 116 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Ştefan Istrate* | onoare |\r\n| 117 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Marius Stroe |\r\n| 118 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Valentin Stanciu |\r\n| 119 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Victor Rusu |\r\n| 120 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Adrian Airinei |\r\n| 121 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Bogdan Tătăroiu |\r\n| 122 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Cosmin Gheorghe |\r\n| 123 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Ştefan Filip | onoare |\r\n| 124 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Andrei Grigorean | *Cristian George Strat | onoare |\r\n| 125 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Andrei Grigorean |\r\n| 126 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Manuela Şerban |\r\n| 127 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Teodor Schiller |\r\n| 128 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Mariana Bulbuc | onoare |\r\n| 129 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Voicu Octavian | participare |\r\n| 130 | Dima Mircea | participare | Finala Algoritmiada 2009 |\\2. Cristian George Strat |\r\n\r\n',13,'protected',NULL,NULL),('registru-diplome','Registru diplome','2007-06-26 09:34:59','2009-05-03 08:17:40','h1. Registru diplome\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nNe mandrim cu activitatea noastra si incercam sa premiem numai persoane care suntem convinsi ca merita. Incercam sa acordam diplome de onoare numai celor care intr-adevar inteleg spiritul infoarena si ne ajuta sa ne indeplinim obiectivele.\r\n\r\nFiecare diploma eliberata de infoarena este inseriata si inregistrata aici. O diploma infoarena care nu se gaseste in registrul de mai jos nu este valida.\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n&nbsp;\r\n\r\n\r\n\r\n|_. Nr.|_. Data     |_. Tip Diploma |_. Eveniment |_. Presedinte infoarena |_. Presedinte comisie |_. Eliberata pe numele |\r\n|  1 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Tataroiu Bogdan* |\r\n|  2 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Sperlea Adriana* |\r\n|  3 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Ionescu Victor* |\r\n|  4 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Simion Alexandru* |\r\n|  5 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Baltescu Paul Dan* |\r\n|  6 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Rusu Victor* |\r\n|  7 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Airinei Adrian* |\r\n|  8 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Grigorean Andrei* |\r\n|  9 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Savu Victor* |\r\n| 10 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Lica Adela* |\r\n| 11 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Savin Tiberiu* |\r\n| 12 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Stroe Marius* |\r\n| 13 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Istrate Stefan* |\r\n| 14 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Chis Raoul* |\r\n| 15 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Duta Vlad* |\r\n| 16 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Purice Andrei* |\r\n| 17 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Tudorica Alexandru* |\r\n| 18 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Velicu Adrian* |\r\n| 19 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Parcalabescu Maria* |\r\n| 20 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Gheorghe Cosmin* |\r\n| 21 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Dragus Marius* |\r\n| 22 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Sanduleac Dan* |\r\n| 23 | 2007-06-25 | participare               | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Puni Andrei Paul* |\r\n| 24 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Pasaila Daniel* |\r\n| 25 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Stanciu Valentin* |\r\n| 26 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Pasoi Mircea* |\r\n| 27 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Strat Cristian George* |\r\n| 28 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Luca Elisabeth* |\r\n| 29 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Cardei Claudia* |\r\n| 30 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Pastor Diana* |\r\n| 31 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Haret Alexandra* |\r\n| 32 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Radulescu Flaviu* |\r\n| 33 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Yuksel Ali* |\r\n| 34 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Florea Tiberiu* |\r\n| 35 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Vladu Adrian* |\r\n| 36 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Diaconu Adrian* |\r\n| 37 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Ganceanu Silviu Ionut* |\r\n| 38 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Crestez Leonard* |\r\n| 39 | 2007-06-25 | premiul 3, clasa IX       | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Sperlea Adriana* |\r\n| 40 | 2007-06-25 | premiul 2, clasa IX       | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Tataroiu Bogdan* |\r\n| 41 | 2007-06-25 | premiul 1, clasa IX       | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Tudorica Alexandru* |\r\n| 42 | 2007-06-25 | premiul 3, clasa X        | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Savu Victor* |\r\n| 43 | 2007-06-25 | premiul 2, clasa X        | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Puni Andrei* |\r\n| 44 | 2007-06-25 | premiul 1, clasa X        | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Gheorghe Cosmin* |\r\n| 45 | 2007-06-25 | premiul 3, clasele XI-XII | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Rusu Victor* |\r\n| 46 | 2007-06-25 | premiul 2, clasele XI-XII | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Simion Alexandru* |\r\n| 47 | 2007-06-25 | premiul 1, clasele XI-XII | Finala preONI 2007 | Cristian George Strat | Mircea Pasoi | *Grigorean Andrei* |\r\n| 48 | 2007-06-25 | onoare                    |                    | Cristian George Strat |              | *Dragos Ciobanescu* |\r\n| 49 | 2008-03-23 | premiu 1, clasele 5-8      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Cezar Mocan* |\r\n| 50 | 2008-03-23 | premiu 2, clasele 5-8      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Radu Stefan Voroneanu* |\r\n| 51 | 2008-03-23 | premiu 3, clasele 5-8      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Andrei Purice* |\r\n| 52 | 2008-03-23 | premiu 1, clasa 9      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Ioana Pandele* |\r\n| 53 | 2008-03-23 | premiu 2, clasa 9      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Alexandru Tache* |\r\n| 54 | 2008-03-23 | premiu 3, clasa 9      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Bogdan Bazu* |\r\n| 55 | 2008-03-23 | premiu 1, clasa 10      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Bogdan Tataroiu* |\r\n| 56 | 2008-03-23 | premiu 2, clasa 10     | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Istvan Hevele* |\r\n| 57 | 2008-03-23 | premiu 3, clasa 10      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Bogdan Casu-Pop* |\r\n| 58 | 2008-03-23 | premiu 1, clasele 11-12      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Cosmin Gheorghe* |\r\n| 59 | 2008-03-23 | premiu 2, clasele 11-12      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Alexandru Tandrau* |\r\n| 60 | 2008-03-23 | premiu 3, clasele 11-12      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Paul-Dan Baltescu* |\r\n| 61 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Radu Oprescu* |\r\n| 62 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Andrei Jurba* |\r\n| 63 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Palianos Cristian* |\r\n| 64 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Ada Solcan* |\r\n| 65 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Victor Popescu* |\r\n| 66 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Victor Ionescu* |\r\n| 67 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Alexandru Tudorica* |\r\n| 68 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Adriana Sperlea* |\r\n| 69 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Vlad Tataranu* |\r\n| 70 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Vicol Sergiu* |\r\n| 71 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Adrian Hulparu* |\r\n| 72 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Bogdan Taloi* |\r\n| 73 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Ioana Radu* |\r\n| 74 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Marius Petcu* |\r\n| 75 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Alex Mircescu* |\r\n| 76 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Radu Zernoveanu* |\r\n| 77 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Serban Stan* |\r\n| 78 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Vlad Gavrila* |\r\n| 79 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Filip Stefan* |\r\n| 80 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Tiberiu Savin* |\r\n| 81 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Florin Pogocsan* |\r\n| 82 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Marius Dragus* |\r\n| 83 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Alexandru Simion* |\r\n| 84 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Vlad Tudose* |\r\n| 85 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Mihai Damaschin* |\r\n| 86 | 2008-03-23 | participare      | Finala preONI 2008  | Cristian George Strat | Mircea Pasoi | *Victor Rusu* |\r\n| 87 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Adrian Airinei* |\r\n| 88 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Silviu Ganceanu* |\r\n| 89 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Filip Buruiana* |\r\n| 90 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Andrei Grigorean* |\r\n| 91 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Adrian Diaconu* |\r\n| 92 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Mircea Pasoi* |\r\n| 93 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Cristian Strat* |\r\n| 94 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Valentin Stanciu* |\r\n| 95 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Tiberiu Florea* |\r\n| 96 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Claudia Cardei* |\r\n| 97 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Alexandra Haret* |\r\n| 98 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Elisabeth Luca* |\r\n| 99 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Sergiu Strat* |\r\n| 100 | 2008-03-23 | onoare      | Finala preONI 2008  |\\2. Cristian George Strat | *Maricel Mihalcea* |\r\n| 101 | 2009-05-02 | premiul 3, gimnaziu | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Gheorghe Mihai* |\r\n| 102 | 2009-05-02 | premiul 2, gimnaziu | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Siminiuc Antoanela* |\r\n| 103 | 2009-05-02 | premiul 1, gimnaziu | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Gavrilă Vlad* |\r\n| 104 | 2009-05-02 | premiul 3, clasele IX-X | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Mocan Cezar* |\r\n| 105 | 2009-05-02 | premiul 2, clasele IX-X | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Purice Andrei* |\r\n| 106 | 2009-05-02 | premiul 1, clasele IX-X | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Stan Şerban Andrei* |\r\n| 107 | 2009-05-02 | premiul 3, clasele XI-XII | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Szasz Robert* |\r\n| 108 | 2009-05-02 | premiul 2, clasele XI-XII | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Pârvu Andrei* |\r\n| 109 | 2009-05-02 | premiul 1, clasele XI-XII | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Tutunaru Mihai Cosmin* |\r\n| 110 | 2009-05-02 | premiul 2, studenţi | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Mugurel Ionuţ Andreica* |\r\n| 111 | 2009-05-02 | premiul 3, studenţi | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Tudose Vlad* |\r\n| 112 | 2009-05-02 | premiul 1, studenţi | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean | *Saveluc Vlad* |\r\n| 113 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Silviu-Ionuţ Gănceanu* |\r\n| 114 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Mircea Paşoi* |\r\n| 115 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Cristina Petrovici* |\r\n| 116 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Ştefan Istrate* |\r\n| 117 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Marius Stroe* |\r\n| 118 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Valentin Stanciu* |\r\n| 119 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Victor Rusu* |\r\n| 120 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Adrian Airinei* |\r\n| 121 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Bogdan Tătăroiu* |\r\n| 122 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Cosmin Gheorghe* |\r\n| 123 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Ştefan Filip* |\r\n| 124 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Andrei Grigorean | *Cristian George Strat* |\r\n| 125 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Andrei Grigorean* |\r\n| 126 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Manuela Şerban* |\r\n| 127 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Teodor Schiller* |\r\n| 128 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Mariana Bulbuc* |\r\n| 129 | 2009-05-02 | participare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Voicu Octavian* |\r\n| 130 | 2009-05-02 | Dima Mircea | participare | Finala Algoritmiada 2009 | Cristian George Strat | Andrei Grigorean |\r\n| 131 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Delia Blăjan* |\r\n| 132 | 2009-05-02 | onoare | Finala Algoritmiada 2009 |\\2. Cristian George Strat | *Alexandru Costin* |\r\n',13,'protected',NULL,NULL),('utilizator/andrici_cezar','Profil andrici_cezar','2008-02-20 11:15:10','2009-05-04 16:25:19',' *Despre mine*\r\n\r\n Sunt un elev din clasa a VI aB de la \'Liceul de Informatica Gr.C.Moisil Iasi\':http://liis.ro.\r\n\r\n\r\n *Distinctii primite*\r\n\r\n_Premiul I la Informatica la ,,Urmasii lui Moisil\", la clasa a 4a!!!`````````anul 2007_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 5a!!!```````anul 2008_\r\n_Premiul III la Informatica Faza Judeteana-98 puncte, la clasa a 5a!!!````anul 2008_ (Calificat la ONI 2008)\r\n_Mentiune la Informatica Faza Nationala-160 puncte, la clasa a 5a!!!````anul 2008_ (Pe locul 8)\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 9a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 5a!!!`````````anul 2008_\r\n_Premiul II la Informatica la ,,Moisil++\", la clasa a 5a!!!````````````anul 2008_\r\n_Premiul I la Informatica la ,,Concursul National al centrelor de Excelenta\", la clasa a 5a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 6a!!!``````````anul 2009_\r\n_Premiul II la Informatica la Faza Locala-110 puncte, la clasa a 6a!!!`````anul 2009_\r\n_Premiul III la Informatica la Faza Judeteana-40 puncte, la clasa a 6a!!!````anul 2009_ (Calificat la ONI 2009)\r\n_Mentiune la Informatica Faza Nationala-230 puncte, la clasa a 6a!!!````````anul 2009_ (Pe locul 4)\r\n_Nimic la Informatica Faza Natioanal din Bulgaria-140 puncte/600 puncte, la clasa a 6a!!!`````anul 2009_ (Prima zi 140, a doua am stat ca un fraier si m-am uitat la subiectele in engleza)\r\n\r\n*.Campion*\r\n*2008 - 2009* - 916 puncte clasat pe locul 51\r\n\r\n*Alte rezultate*\r\n# Chemat la CEX la a 9a 2009(cls.a 6a)\r\n# ONI 2009 Bulgaria cu ajutorul profesorilor Emanuela Cherchez si Marinel Serban\r\n\r\n*Profesori*\r\nIvasc Cornelia si Mirela Tibu ->[\'Elevi\':http://olimpiada.info/oji2009/index.php?cid=participanti&w=gim&judet=25&clasa=6]\r\nInfoarena\r\n.Campion\r\n\r\n*Citate preferate*\r\n_Daca plangi pentru ca soarele a disparut din viata ta, lacrimile te vor impiedica sa vezi stelele_ - Rabindranath Tagore\r\n\r\n_Un om nu este distrus atunci cind este invins; e distrus atunci cind renunta_- Richard Milhous Nixon\r\n\r\n_Nu este intelept sa fii sigur asupra propriei tale intlepciuni. Este sanatos sa ti se aminteasca ca si cel puternic poate slabi, iar cel intelept poate gresi_ - Mahatma Gandhi\r\n\r\n_Cel puternic nu este cel care este de neinvins, ci cel care se ridica dupa fiecare lovitura_\r\n\r\n_Loveste spre soare chiar daca nu reusesti, macar o sa fii printre stele_\r\n\r\nh3. Prieteni\r\n\r\n==user(user=\"marta_dianna\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"antoanela\" type=\"tiny\")==\r\n(8)\r\n\r\n\r\n==user(user=\"matemariaescu\" type=\"tiny\")==\r\n(8)\r\n\r\n==user(user=\"liana\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"alexrusu\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"netedu_andrei\" type=\"tiny\")==\r\n(6)\r\n\r\n==user(user=\"mironalex2005\" type=\"tiny\")==\r\n(6)\r\n\r\n==user(user=\"unsilviu\" type=\"tiny\")==\r\n(7)\r\n\r\nScanteie Sebi(7)\r\nMunteanu Bogdan(8)\r\nAnton Madalina(8)\r\nBrezuleanu Razvan(8)\r\n\r\nToti am fost si anu trecut si anu asta la ONIgimnaziu si vom putea fi toti din nou doar peste 2 ani!\r\n\r\nh3. Prieteni care i-am vazut dar ne cunoastem doar prin messenger\r\n\r\n==user(user=\"toni2007\" type=\"tiny\")==\r\nMa ajuta la probleme\r\n==user(user=\"crawler\" type=\"tiny\")==\r\nTot la probleme\r\n==user(user=\"stef2n\" type=\"tiny\")==\r\nMa ajuta sa scriu articole\r\n==user(user=\"DITzoneC\" type=\"tiny\")==\r\nMa ajuta sa scriu probleme\r\n==user(user=\"mathboy\" type=\"tiny\")==\r\nVorbim despre probleme\r\n==user(user=\"cipriancx\" type=\"tiny\")==\r\nVorbim despre probleme\r\n',7668,'public',NULL,NULL),('probleme-de-taietura','Probleme de Taietura','2009-04-06 05:48:04','2009-04-18 16:41:33','h1. Probleme de taietura\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"andrici_cezar\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n\r\n(toc){width: 25em}*{text-align:center} *Conţinut:*\r\n* \'Problema 1\':probleme-de-taietura#problema-1\r\n* \'Problema 2\':probleme-de-taietura#problema-2\r\n* \'Problema 3 Really Strange\':probleme-de-taietura#problema-3\r\n* \'Problema 4\':probleme-de-taietura#problema-4\r\n* \'Problema 5\':probleme-de-taietura#problema-5\r\n* \'Problema 6\':probleme-de-taietura#problema-6\r\n* \'Problema 7 Bursele Agora 2001\':probleme-de-taietura#problema-7\r\n* \'Problema 8 Thinking Backward\':probleme-de-taietura#problema-8\r\n* \'Problema 9 Internet Problem Solving Contest 2000\':probleme-de-taietura#problema-9\r\n* \'Problema 10 The partition of a cake\':probleme-de-taietura#problema-10\r\n* \'Problema 11 Count the faces\':probleme-de-taietura#problema-11\r\n* \'Problema 12 Cercuri,Algoritmus\':probleme-de-taietura#problema-12\r\n* \'Bibliografie\':probleme-de-taietura#bibliografie\r\n\r\n\r\n\r\nh2(#problema-1). Problema 1:\r\n\r\nPentru un număr natural $N$ dat, se cere numărul maxim de regiuni în care se poate împărţi planul folosind $N$ drepte.\r\n\r\np=. !probleme-de-taietura?poza-1.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nMai întâi facem vom face două observaţii:\r\nÎn configuraţia cu număr maxim de regiuni nu vom avea două drepte paralele, pentru că două drepte care se intersectează formează în plan patru regiuni, în timp ce două drepte paralele formează în plan doar trei regiuni.\r\nDe asemenea pentru a obţine un număr maxim de regiuni, nu vor exista trei drepte care să se intersecteze intr-un punct pentru că astfel am pierde o regiune triunghiulară formată din punctele de intersecţie ale celor trei drepte.\r\nDacă aceste două condiţii sunt îndeplinite vom vedea în continuare că orice configuraţie de $N$ drepte împarte planul în acelaţi număr de regiuni. Notăm cu $d(n)$ acest număr. Presupunem ca ştim pe $d(n)$ , să vedem acum ce se întâmplă dacă mai adaugăm o dreaptă. \r\nAceastă nouă dreaptă va fi intersectată de celelalte drepte în $n$ puncte distincte. Fiecare segment de dreaptă şi semidreaptă în care este împărţită a $n+1-a$ taie o regiune veche in două regiuni noi. De aici tragem concluzia că $d(n+1) = d(n) + n + 1$ . Deci $d(n) = n + n – 1 + n – 2 + … + 2 + d(1)$ . Astfel folosind indentitatea $1 + 2 + 3 + … + n = n(n+1)/2$ obţinem $d(n) = n(n + 1) / 2 + 1$ .\r\nMenţionăm că problemele în care se cere maximizarea numărului de regiuni în care un pătrat, un triunghi sau un cerc este împărţit de $n$ drepte, au aceiaşi soluţie.\r\n\r\np=. !probleme-de-taietura?poza-2.bmp!\r\n\r\nh2(#problema-2). Problema 2:\r\n\r\nDându-se un număr natural $N$ , se cere numărul maxim de regiuni în care $N$ cercuri pot împărţi planul.\r\n\r\np=. !probleme-de-taietura?poza-4.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nEste clar că oricare două cercuri trebuie să se intersecteze in exact două puncte, nu să fie tangente sau să nu se intersecteze deloc pentru că astfel am pierde o regiune, iar oricare trei cercuri nu se intersectează într-un punct.\r\nOrice configuraţie care satisface această cerinţă va împărţi planul într-un număr maxim de regiuni.Vom nota cu $c(n)$ numărul maxim de regiuni în care este împărţit planul de $n$ cercuri. Să vedem ce se întîmplă când adăugăm un nou cerc la această configuraţie. Cercul nou va fi intersectat de cele $n$ cercuri în $2n$ puncte distincte, şi astfel va fi împărţit în $2n$ arce. Fiecare dintre aceste arce împarte o zonă veche în două zone noi. De aici tragem concluzia că $c(n + 1) = 2n + c(n)$ . Astfel putem să îl scriem pe $c(n) ca 2(n – 1) + 2(n – 2) + … + 2 + c(1)$ . De aici folosind din nou identitatea $1 + 2 + … + n = n(n+1)/2$ avem că $c(n) = n(n-1) + 2$ .\r\nEste evident că şi problema în care se cere maximizarea numărului de regiuni în care este împărţită suprafaţa unei sfere de $n$ cercuri are aceiaşi soluţie.\r\n\r\np=. !probleme-de-taietura?poza-5.bmp!\r\n\r\nh2(#problema-3). Problema 3 ([\"10519 !! Really Strange !!\":http://online-judge.uva.es/p/v105/10519.html]):\r\n\r\nSe dau $n$ cercuri care se intersectează oricare două în două puncte şi nu există trei care se intersectează într-un punct, se cere să se determine numărul de zone în care este împarţit planul de aceste $n$ cercuri. ( $n <= 10^100$ )\r\n\r\n\r\nh3. Rezolvare:\r\n\r\nObservăm ca sunt indeplinite condiţiile de maximalitate cerute mai sus, deci rezultatul e $c(n)$ , singura problema ce rămâne este aceea de implementare a operaţiilor cu numere mari.\r\n\r\nh2(#problema-4). Problema 4:\r\n\r\nAvem un număr natural $N$ , vrem să determinăm numărul maxim de regiuni în care poate fi împărţit un plan de elipse.\r\n\r\np=. !probleme-de-taietura?poza-6.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nLa fel ca şi la cercuri nici aici nu trebuie să avem elipse tangente, sau elipse care să nu se intersecteze, nu vor exista nici aici trei elipse care să se intersecteze într-un punct, aici elipsele trebuie să se intersecteze în patru puncte, dacă s-ar intersecta numai în două puncte atunci configuraţia nu ar avea număr maxim de regiuni.\r\nNotăm cu $e(n)$ numărul de care suntem interesaţi. Câte regiuni noi apar cand adăugam o nouă elipsă? Păi o nouă elipsă va fi intersectată de celelalte elipse ăn patru puncte de fiecare, deci $e(n + 1) = 4n + e(n)$ . De aici tragem concluzia că $e(n) = 2 n(n - 1) + 2$ .\r\n\r\np=. !probleme-de-taietura?poza-7.bmp!\r\n\r\nh2(#problema-5). Problema 5:\r\n\r\nDându-se un număr natural $N$ , se cere numărul maxim de regiuni în care $N$ triunghiuri pot împărţi planul.\r\n\r\np=. !probleme-de-taietura?poza-8.bmp!\r\n\r\nh3. Rezolvare:\r\n\r\nRepetând raţionamentul de la problemele anterioareavem că $t(n+1) = 6n + t(n) => t(n) = 3n(n-1) + 2$ . \r\n\r\np=. !probleme-de-taietura?poza-9.bmp!\r\n\r\nh2(#problema-6). Problema 6:\r\n\r\nPentru $N$ plane determinaţi numărul maxim de zone în care poate fi împărţit spaţiul cu acestea.\r\n\r\nh3. Rezolvare:\r\n\r\nÎn această problemă urmăm raţionamentul de până acum. Este evident că trebuie ca fiecare plan să se intersecteze cu fiecare, că oricare trei plane trebuie să nu se intersecteze într-o dreaptă, oricare trei plane nu trebuie să fie paralele cu o dreaptă şi oricare patru plane nu trebuie să se intersecteze într-un punct. Notăm $p(n)$ numărul maxim de zone în care $n$ plane împart spatiul. Când adaugăm un nou plan acesta va fi intersectat de celelalte plane în $n$ drepte, drepte care după restrictiile care le-am pus nu vor fi două paralele sau trei care să se intersecteze într-un punct. Acest plan va fi împărţit în $d(n)$  regiuni de aceste drepte din cauza restricţiilor impuse. Fiecare regiune din plan taie o zonă din spaţiu în două noi zone, de aici tragem concluzia că $p(n + 1) = d(n) + p(n)$ . Astfel avem $p(n) =  n(n-1)/2 + 1 + (n-1)(n-2)/2 + 1 + ...+2 * 1 / 2 + 1 + p(1) = ( n^2^ – n + (n-1)^2^ – (n-1)+... + 2^2^ – 2  +  1 – 1 + (n – 1) )/2+ 2 = ( n(n+1)(2n + 1)/6 – n(n+1)/2 + (n-1))/2 + 2  = (n^3^/3 + n^2^/2 + n/6 – n^2^/2 – n/2 )/2 + n + 1 = n^3^/ 6 + 5n/6 + 1$ . Am folosit identităţile $1 + 2 + … + n = n(n+1)/2 şi 1 + 2^2^ + 3^2^ + … + n^2^ = n(n+1)(2n+1)/6$ care se pot demonstra uşor prin inducţie.\r\nMenţionăm că dacă vrem să împărţim un cub, un cilindru o sfera etc în număr maxim de regiuni folosind $n$ plane, formula se păstrează.\r\n\r\nh2(#problema-7). Problema 7 (Bursele Agora 2001):\r\n\r\nDându-se un număr natural $N$ , să se determine numărul maxim de zone în care pot împărţi spaţiul $N$ sfere.\r\n\r\n\r\nh3. Rezolvare:\r\n\r\nPornim la fel ca la problema anterioară, oricare două sfere se vor intersecta şi nu vor exista trei sfere care să se intersecteze în acelaşi punct. Vom nota cu $s(n)$ numărul maxim de regiuni în care poate fi împărţit spaţiul cu $n$ sfere. Să vedem ce se întâmplă când adăugăm o sferă. Această sferă va fi intersectată de toate celelalte $n$ sfere în $n$ cercuri, pentru ca numărul de regiuni noi să fie maxim aceste cercuri vor împărţi sfera într-un număr maxim de regiuni, acest număr este $c(n)$ aşa cum am discutat la problema 2. Obţinem astfel $s(n + 1) = c(n) + s(n) = c(n) + c(n-1) + ... + c(1) = n(n-1) + 2 + (n-1)(n-2) + 2 + ... + 2 = 1 + 2^2 + .. + n^2 – 1 – 2 – 3 - .... – n + 2n => s(n) = n(n^2 – 3n + 8) / 3$\r\n\r\nh2(#problema-8). Problema 8 ([\"10623 Thinking Backward\":http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&Itemid=8&category=18&page=show_problem&problem=1564]):\r\n\r\nSe dă un număr $N$ care este numărul maxim în care poate fi împărţit planul de $m$ elipse, $n$ cercuri şi $p$ triunghiuri. Se cere ştiind $N$ să se determine toate valorile posibile pentru $m$ , $n$ şi $p$ . ( $N$ întreg făra semn reprezentabil pe 32 de biţi, $0<=m<100$ , $0<=n<20000$ şi $0<=p<100$ )\r\n\r\n\r\nh3. Rezolvare:\r\n\r\nDacă am ştii pentru trei parametrii $m$ , $n$ şi $p$ care este numarul maxim de părţi în care poate fi împărţit planul  de $m$ elipse, $n$ cercuri şi $p$ triunghiuri, atunci am putea incerca toate posibilitaţile pentru $m$ , $n$ şi $p$ şi am găsi tripletele pentru rezultatul ar fie egal cu $N$ , chiar am putea optimiza puţin acest algoritm iteram pe toate valorile de $m$ şi $p$ , astfel vom obţine o ecuaţie cu necunoscuta $n$ astfel vom face doar $10000$ de rezolvări de ecuaţii în loc de $200 000 000$ de comparaţii. \r\nSă vedem cum găsim numărul maxim de zone. Din nou oricare două figuri se intersectează în număr maxim de intersecţii, un cerc cu o elipsă în patru puncte, un cerc sau o elipsă cu un triunghi în şase puncte. Mai întâi punem cele $m$ elipse in plan, ele vor împărţi planul în $e(m)$ regiuni adică $2 m(m - 1) + 2$ . După aceea adaugăm cercurile. Să notam numarul maxim de zone în care $n$ cercuri şi $m$ elipse pot împărţi planul cu $ec(m , n)$ . Dacă ştim cât este $e(m, n-1)$ atunci când adaugăm un nou cerc, acesta va fi intersectat de $m$ elipse in $4m$ puncte şi de $n-1$ cercuri in $2(n – 1)$ puncte deci cercul va fi împărţit în $4m + 2(n-1)$ arce care vor împărţi tot atâtea regiuni care existau deja in câte două regiuni noi. Deci $ec(m, n) = 4m + 2(n-1) + ec(m, n-1) = 4m + 2(n-1) + 4m + 2(n-2) + … + 4m + 2 + ec(m, 0) = 4m(n-1) + n (n-1) + 2m(m-1) + 2$ . Să vedem ce se întâmplă când adăugăm triunghiurile. Vom nota $ect(m, n, p)$ numărul maxim de zone în care poate fi împărţit planul de $m$ elipse, $n$ cercuri şi $p$ triunghiuri. Dacă ştim cu cat e egal $ect(m, n, p - 1)$ , atunci când vom adăuga un nou triunghi acesta va intersecta cele $m$ cercuri în $6m$ puncte, cele $n$ elipse în $6n$ puncte şi cele $p – 1$ triunghiuri în $6(p – 1)$ puncte, astfel se vor forma $6m + 6n + 6(p-1)$ noi zone. Deci $ect(m, n, p) = 6(m + n + p – 1) + ect(m, n, p – 1) = 6 (m + n + p – 1 + m + n + p – 2 + … m + n + 1) + ect(n, m, 0) = 6 (p-1)(m+n) + 3p(p-1) + 4m(n-1) + n(n-1) + 2m(m-1) + 2$ .\r\n\r\nProblemele anterioare au fost cam matematice şi ele sunt numite de obicei de olimpici peiorativ ca “probleme de formulă”, majoritatea olimpicilor la informatică participă aici pentru că matematica nu le place aşa tare şi deci nici apariţia unor probleme ca cele de mai sus care sunt mai mult de mate decât de info nu îi prea încântă. Cum poate fi rezolvată o problemă de formulă fără să avem intuiţia matematică sau cunoţinţele matematice necesare? Păi câteodată elevii apelează la următorul truc: află primele câteva valori de mâna sau cu ajutorul unor algoritmi brute force şi apoi speră ca formula să fie de o anumită formă, de exemplu ar putea fi un polinom de un grad mic. Atunci avem ca $f(N) = An^3 + Bn^2 + Cn + D$ . Afland primele câteva valori vom ştii valorile $f(1), f(2), f(3), f(4)$ . Dând lui $n$ pe rand valorile 1, 2, 3 şi 4 putem face un sistem cu necunoscutele A, B, C şi D. Sau putem încerca să vedem cum se comportă şirul de numere, are o creştere polinomială sau exponenţială, apar valorile lui în triunghiul lui Pascal. Iar dacă rezolvăm problemele de acasă putem căuta valorile din şirul de soluţii pe internet pe pagina Eciclopedia Online a şirurilor de întregi [7] care este o resursă foarte utilă în cazul problemelor de acest gen .\r\n\r\nh2(#problema-9). Problema 9 ([\"Internet Problem Solving Contest 2000\":http://plg1.cs.uwaterloo.ca/~acm00/ipsc/]):\r\n\r\nSe dau $N$ drepte în plan, fiecare dreaptă este dată prin două puncte prin care trece. Se cere să se determine pentru această configuraţie în câte zone este împărţit planul. ( $n <= 1000$ )\r\n\r\nh3. Rezolvare:\r\n\r\nÎn sfârşit o problemă în care avem nevoie să folosim calculatorul şi talentul nostru de programatori . Vom folosi aceeaşi idee ce a apărut şi în celelalte probleme, adică numărăm pe rând în câte zone este împărţit planul de primele o dreaptă, doua drepte respectiv $n$ drepte. Deci vom adăuga în ordine dreptele la configuraţia noastră. Când adăugăm o dreaptă ea va fi intersectată de dreptele deja adăugate în $k$ puncte nu neapărat distincte, pe noi ne intereseaza punctele distincte, ca să facem acest lucru putem sorta punctele în $O(k log k)$ sau să folosim o tabelă de dispersie şi astfel să aflăm în $O(k)$ numărul de puncte distincte, daca acest număr e egal cu $L$ atunci la numărul curent de zone vom adăuga $L$ . Astfel algoritmul are complexitatea $O(n^2 log n)$ , sau dacă folosim tabele de dispersie $O(n^2)$ .\r\n\r\nh2(#problema-10). Problema 10 ([\"527 The partition of a cake\":http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&Itemid=8&category=7&page=show_problem&problem=468]):\r\n\r\np=. !probleme-de-taietura?poza-10.bmp!\r\n\r\nAvem un tort în formă de pătrat de dimensiune $1000 x 1000$ . Folosim un cuţit pentru a tăoa tortul. Întrebarea este după o serie de tăieturi, în căte bucăţi am patriţionat tortul. Restricţii: Numărul de tăieturi nu va fi mai mare de $8$ . După tăieturi, lungimea oricărei laturi a partiţiei nu va fi mai mică decât unu. Coordonatele vârfurilor tortului vor fi $(0,0)(0,1000)(1000,1000) (1000,0)$ . Tăieturile se vor intersecta în două puncte cu marginile tortului. Următoarea imagine e un tort tăiat în zece bucăţi.\r\n\r\n\r\nh3. Rezolvarea:\r\n\r\nEste analoaga cu cea a problemei anterioare, datele sunt foarte mici în problema aceasta, probabil că autorii au vrut să facă problema accesibilă şi altor idei care folosesc împărţiri efective în poligoane a pătratului.\r\n\r\nh2(#problema-11). Problema 11 ([\"10178 Count the faces\":http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&Itemid=8&category=13&page=show_problem&problem=1119]):\r\n\r\np=. !probleme-de-taietura?poza-12.bmp!\r\n\r\nSe dă un graf planar prin noduri şi muchii, un graf este planar dacă există o modalitate de a îl desena în plan făra ca muchiile să se intersecteze decăt la capete. Se cere să se determine în căte regiuni împarte planul graful dat la intrare. Mai jos avem un exemplu de graf în care feţele sunt numerotate.\r\n\r\n\r\nh3. Rezolvare:\r\n\r\nEste interesant faptul că în această problemă nu ne este dată configuraţia în plan a grafului ci doar structura lui. Un graf il putem reprezenta în mai multe moduri în plan, astfel suntem duşi înspre ideea că există ceva formulă care rezolvă problema. O formulă întradevăr există şi se numeşte formula lui Euler pentru grafurile planare. Formula arată aşa $f - m + n  = 2$ , unde prin $f$ am notat numărul de feţe, $m$ numărul de muchii şi $n$ numărul de vârfuri, dacă graful nostru e conex (formula include faţa exterioară). Această formulă poate fi demonstrată în foarte multe moduri. Dacă vreţi să vedeţi 19 metode de demonstrare puteţi să vizitaţi adresa [8]. O demonstraţie simplă ar fi prin inducţie pornind de la un arbore şi adăugând pe rând câte o muchie. La început avem o singură faţă, cea infinită, $1 – (n – 1) + n = 2$ se verifică. Fiecare muchie adăugată împarte o faţă în două deci dacă aveam inainte $f – m + n = 2$ acum vom avea $f1 – m1 + n = 2$ unde $f1 = f + 1$ şi $m1 = m + 1$ . Deci am demonstrate formula şi putem foarte uşor să rezolvăm problema, mai trebuie numai să avem grijă ca pentru fiecare componentă conexă număram faţa infinită.\r\nAceastă formulă este adevarată şi în spaţiu pentru poliedre.\r\n\r\nh2(#problema-12). Problema 12 (Cercuri, Algoritmus):\r\n\r\np=. !probleme-de-taietura?poza-13.bmp!\r\n\r\nSe considera $N$ cercuri in plan. Se cere să se determine numărul de zone finite în care cercurile date împart planul.\r\n \r\nExemplu\r\nCERCURI.IN\r\n4\r\n90 110 50\r\n130 70 30\r\n155 45 15\r\n165 115 65\r\nCERCURI.OUT\r\n$11$\r\n\r\n\r\nh3. Rezolvare:\r\n\r\nContraexemple rezolvare normala\r\nO rezolvare folosind geometria computaţională pare foarte grea, lucrurile simplificându-se mult daca abordam problema prin prisma unor noţiuni de teoria grafurilor.\r\nFiecare punct de intersectie va fi considerat un nod. Două noduri vor fi legate prin o muchie dacă există un cerc pe care sa se afle amândouă iar între ele să nu existe nici un alt punct de intersectie.\r\nAcum vom folosi identitatea lui Euler: prezentată în problema anterioară. În problema noastră nu trebuie să numărăm şi faţa exterioară, deci formula folosita va fi $F=M-V+1$ . Această formulă este adevarată doar in cazul unei singure componente conexe. Pentru mai multe componente, formula devine $F=M-V+C$ , unde $C$ este numărul de componente conexe.\r\nO atenţie deosebită trebuie acordată punctelor de intersecţie prin care trec mai mult de două cercuri, pentru a nu le număra de mai multe ori. Putem rezolva aceasta problema prin sortarea punctelor de intersecţie ale unui cerc cu toate celelalte cercuri.\r\nDeasemenea, este necesara eliminarea cercurilor identice (cu acelaşi centru şi raze egale). Din orice mulţime cu astfel de cercuri este păstrat doar un singur element.\r\nDeoarece pentru fiecare cerc este necesara o sortare a punctelor de intersectie, complexitatea generala a algoritmului va fi $O(N2*log(N))$\r\n\r\nh2(#bibliografie). Bibliografie:\r\n\r\n# A.M. Iaglom, I. M. Iaglom, Probleme neelementare tratate elementat. Ed tehnică, Bucureşti, 1962\r\n# I. Tomescu, Probleme de combinatorică şi teoria grafurilor, ed didactică şi pedagogică. Bucureşti, 1981\r\n# Colecţia Ginfo\r\n# [\"acm.uva.es\":http://acm.uva.es]\r\n# [\"ipsc.ksp.sk\":http://ipsc.ksp.sk]\r\n# [\"algoritmus.org/index.php\":http://algoritmus.org/index.php]\r\n# [\"http://www.research.att.com/~njas/sequences/ \":http://www.research.att.com/~njas/sequences/]\r\n# [\"http://www.ics.uci.edu/~eppstein/junkyard/euler/ \":http://www.ics.uci.edu/~eppstein/junkyard/euler/]\r\n',7668,'public',NULL,NULL),('blog/membru-nou','Echipa infoarena s-a îmbogăţit','2009-06-28 20:12:37','2009-06-28 20:41:23','_După cum o parte din voi aţi aflat la finala Algoritmiada, echipa infoarena s-a îmbogăţit cu un nou membru: Marius Stroe. Pentru cei care nu au fost acolo, Marius a primit din partea echipei infoarena un mini-tort cu cifra O pe post de lumânare. Explicaţia a fost că are 0 ani de infoarena şi este cea mai nouă achiziţie a echipei._\r\n\r\n_În ciuda acestui fapt Marius are deja multe contribuţii în \'proiectele infoarena\':implica-te în calitate de voluntar. Puteţi vedea acest lucru chiar pe pagina sa de \'profil\':utilizator/Marius. Îmi place cum şi-a enumerat Marius contribuţiile cele mai importante pe pagina sa pe infoarena. Aş vrea să văd mai mulţi voluntari că îşi actualizează profilul cu realizările lor în cadrul comunităţii._\r\n\r\n_Marius a fost invitat în echipa infoarena tocmai datorită contribuţiilor sale consistente. El este dovada că oricine poate ajunge în echipa infoarena în urma unei implicări constante şi productive în proiectele iniţiate de noi. O vorbă mai veche spune că orice soldat are în raniţă bastonul de mareşal :) Păstrând proporţiile, vreau să spun că oricare dintre voi poate fi promovat în echipă pe această cale: realizări importante pentru comunitate._\r\n\r\n_S-a nu mai lungim vorba şi să vedem cum a răspuns Marius la interviul de botez. Mult succes, Marius, în activitatea ta ca membrul infoarena!_\r\n\r\n!{margin: 10px; margin-left: 0; border: 1px solid gray;}<blog/membru-nou?marius_stroe.jpeg! *Cum ai ajuns membru al siteului infoarena?*\r\nÎnainte să fiu membru al siteului infoarena am fost abonat al revistei GInfo. Pe siteul acestei reviste am găsit un link către infoarena. Google nu mi-a folosit pe atunci. :-)\r\n\r\n\r\n*Cum ai folosit acest site?*\r\nCred că infoarena a fost primul site pe care am văzut multe probleme la un loc spre a fi rezolvate. Nu îmi aduc aminte sigur dar nu cred că ştiam de celelalte siteuri precum Timus, Sgu, UVa, Spoj... După ce am submitat prima sursă la problema A + B am văzut că evaluatorul online chiar funcţionează. Mi s-a părut o idee foarte interesantă să lucrez la o problemă şi să văd rezultatul imediat. Iar acest lucru m-a determinat să lucrez să văd cât ştiu. Până la primul ONI la care am participat în clasa a 10a am rezolvat toate problemele de pe prima pagină din arhivă, mai puţin Fractal. :-) Ţin minte că într-o zi am rezolvat nu mai puţin de 7 probleme, ale căror idei includeau o programare dinamică pe un arbore, un trie, o căutare binară etc. Ceea ce înseamnă, pe scurt, că am învăţat multe într-un timp scurt.\r\n\r\n\r\n*De ce ai intrat in echipa infoarena? Ce îţi propui sa faci ca membru al echipei?*\r\nAm voie să zic că o perioadă de timp nu am ştiut că sunt membru al echipei infoarena? :-) Mă bucur că sunt membru al acestei echipe, fapt ce înseamnă că munca mea a fost apreciată. Ce scopuri am? Nu îmi place cum arată infoarena acum. Ar arăta mult mai bine cu numeroase articole şi o arhivă educaţională bogată. Sunt multe probleme, însă puţină teorie. Scopul meu e ca această latură a siteului să se dezvolte mult mai mult.\r\n\r\n\r\n*Când ai început cu programarea?*\r\nPrimul rând pe care l-am scris în vreun limbaj de programare a fost int main(void), undeva prin clasa a 9a. În vacanţa de vară dinainte să încep liceul îmi cumpărasem o carte despre C/C++ pentru că auzisem că la liceu voi face acest limbaj. La şcoală, fiindu-mi uşor să rezolv ultima problemă de la fiecare capitol, am trecut la manualul de clasa a 10a, după care am dat de infoarena şi am aruncat toate cărţile. :-)\r\n\r\n\r\n*Ce pasiuni ai în afara de programare?*\r\nÎmi plac karatele pentru că mă ajută să eliberez energiile în plus. Însă, acum la facultate le-am abandonat, nemaiavând atâtea energii negative. Îmi mai place să citesc şi să ascult muzică Trance.\r\n\r\n\r\n*Spune-ne o întamplare interesantă legată de site-ul infoarena!*\r\nSunt mai multe astfel de întâmplări. În primul rând, a fost o surpriză plăcută să aflu că sunt membru al echipei infoarena. Pe de altă parte, lucrând cu Ştefan Istrate la articole nu pot uita cât m-am rugat de el să îmi corecteze conţinutul articolului Deque şi aplicaţii, pentru că după ce se uitase pe primele trei probleme a avut nevoie de două săptămâni să îşi recâştige răbdarea pierdută. :-)\r\n',15,'private',NULL,NULL),('newsletter/doi-la-suta-2009','Sprijină infoarena! Direcţionează 2%','2009-05-08 13:54:37','2009-05-08 14:05:02','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\ninfoarena are nevoie acum de sprijinul tău!\r\n\r\nConform \'Codului Fiscal\':http://www.edex.ro/articol_cod_fiscal_16661_Art.%2084:%20Stabilirea%20si%20plata%20impozitului%20pe%20venitul%20net%20anual%20impozabil.html, tu sau părinţii tăi aveţi dreptul să direcţionaţi către Asociaţia infoarena 2% din impozitul pe venit datorat la stat. Aceste contribuţii ne ajută enorm să ne desfăşurăm activitatea. În plus, ne bucurăm să vedem că munca pe care o depunem este apreciată.\r\n\r\nProcedura este simplă şi nu costă nimic! *Termenul limită este 15 mai 2009, deci într-o săptămână.*\r\n\r\nh2{font-size: 12pt}. Despre sistemul „2%”\r\n\r\nbq. Sistemul „2%” permite contribuabililor persoane fizice să direcţioneze 2% din impozitul lor pe venit către o organizaţie neguvernamentală. Este un sistem prin care cetăţenii au posibilitatea să decidă în mod direct ce se întamplă cu impozitele lor. [...] Direcţionarea nu costă nimic. \'(Sursa)\':http://www.doilasuta.ro\r\n\r\n\'Mai multe informaţii despre 2%\':doi-la-suta\r\n\r\n\'Legislaţie pentru sistemul 2%\':http://doilasuta.ro/pagini/index.php?option=com_content&task=view&id=29&Itemid=45\r\n\r\nh2{font-size: 12pt}. Chiar funcţionează?\r\n\r\nDa! Multă lume ne întreabă dacă sistemul chiar funcţionează, mai exact, dacă direcţionările chiar ajung în contul infoarena. Răspunsul este da! În 2008 procedura \'a funcţionat\':/blog/doi-la-suta-2008-raport. Peste 50 de persoane au sprijinit \'Asociaţia infoarena\':asociatia-infoarena direcţionând 2% din impozitul pe venit. Direcţionările au însumat 4.619 lei.\r\n\r\nAm fost surprinşi într-un mod plăcut de aceste contribuţii. Ne bucurăm să vedem că munca pe care o depunem este apreciată.\r\n\r\nVezi întregul \'*raport despre 2% în 2008*\':blog/doi-la-suta-2008-raport\r\n\r\n',13,'public',NULL,NULL),('doi-la-suta','Sprijină Asociaţia infoarena! Direcţionează 2%','2008-01-28 21:09:12','2009-02-18 21:51:14','h1. Sprijină Asociaţia infoarena!\r\n\r\n*_Direcţionează către noi 2% din impozitul pe venit datorat la stat._*\r\n\r\nbq. Sistemul „2%” permite contribuabililor persoane fizice să direcţioneze 2% din impozitul lor pe venit către o organizaţie neguvernamentală. Este un sistem prin care cetăţenii au posibilitatea să decidă în mod direct ce se întamplă cu impozitele lor. [...] Direcţionarea nu costă nimic. \'(Sursa)\':http://www.doilasuta.ro\r\n\r\n*Nu te costă nimic!* Impozitul pe venit rămâne acelaşi. \r\n\r\nÎn anul fiscal 2008 procedura \'a funcţionat\':/blog/doi-la-suta-2008-raport.\r\n\r\nh2. La ce folosim contribuţiile\r\n\r\ninfoarena ajută elevi şi studenţi să înveţe informatică şi programare. De mai bine de 5 ani de zile organizăm concursuri de informatică, scriem articole, dezvoltăm software, facem schimb de experienţă şi idei. Ne-am organizat pe acest site deoarece împreună învăţăm mai bine.\r\n\r\nPoţi să citeşti mai mult despre ce facem noi \'aici\':prezentare şi \'aici\':despre-infoarena. Am apărut şi în \'Adevărul\':http://www.adevarulonline.ro/articole/fostii-olimpici-ii-antreneaza-pe-concurentii-de-la-olimpiade/305061 (pe \'prima pagină\':doi-la-suta?infoarena-adevarul-prima-pagina.pdf).\r\n\r\nVom folosi contribuţiile venite pe această cale să:\r\n\r\n* oferim premii: membrii comunităţii sunt mai motivaţi să se pregătească şi să participe la un concurs online de informatică atunci când se dau premii\r\n* organizăm finale de concursuri: în fiecare an organizăm \'un concurs\':algoritmiada-2009 cu finală; finala are menirea să ne strangă la un loc cu ce mai buni dintre elevii şi studenţii României pentru câteva zile şi să formăm noi prietenii\r\n* motivăm comunitatea să se \'implice\':implica-te\r\n* finanţăm \'proiecte infoarena\':propuneri\r\n\r\nVezi \'obiectivele infoarena\':okr pentru trimestrul curent şi \'rezoluţiile şi notiţele fiecărei şedinţe de consiliu\':planificare.\r\n\r\nh2. Ce trebuie să faci\r\n\r\nProcedura este foarte simplă. Ai grijă să te încadrezi în *termenul limită: 15 mai 2009*.\r\n\r\n# În funcţie de sursa ta de venit, descarcă, printează şi completează una din declaraţiile următoare:\r\n** Dacă ai venituri numai din salarii: \'declaratia 230 precompletata cu datele infoarena\':doi-la-suta?decl_230_2008-infoarena.pdf\r\n** Dacă ai venituri (şi) din alte surse (cedarea folosinţei bunurilor, drepturi de autor, etc): \'declaratia 200 precompletata cu datele infoarena\':doi-la-suta?decl_200_2008-infoarena.pdf\r\n# Foloseşte următoarele date de identificare pentru Asociaţia infoarena:\r\n** *CUI*: 21752294\r\n** *IBAN*: RO15&nbsp;RZBR&nbsp;0000&nbsp;0600&nbsp;0919&nbsp;4268, *Deschis la*: Raiffeisen, Ag. Unirea, Bucureşti\r\n** *Adresa sediu social*: Str. Dragoş Vodă Nr. 49, Bl. P9, Ap. 11, Bârlad, Jud. Vaslui\r\n# Depune declaraţiile completate la administraţia financiară de care aparţine domiciliul tău. Alternativ poţi să trimiţi declaraţia prin scrisoare recomandată către administraţia financiară.\r\n\r\nAlte informaţii utile:\r\n\r\n* Completează în două exemplare declaraţia corespunzătoare. Unul din exemplare trebuie depus la administraţia financiară iar celălalt rămâne la tine.\r\n\r\n* Nu e nici o problemă dacă nu ştii exact suma care trebuie virată. Lasă rubrica „Suma” necompletată şi organul fiscal va calcula şi va vira suma admisă, conform legii\r\n\r\n* \'Adrese şi numere de telefon pentru administraţiile financiare din Bucureşti\':http://www.miculparis.ro/utile/administratie/administratii_financiare_bucuresti.html\r\n\r\n* \'declaratia 230 originala\':http://doilasuta.ro/pagini/resurse/decl_230_2008.pdf si \'declaratia 200 originala\':http://doilasuta.ro/pagini/resurse/decl_200_2008.pdf\r\n\r\nh2. Intrebări, sugestii\r\n\r\nDacă ai nelămuriri putem discuta pe forum:\r\n\r\n==SmfTopic(topic_id=\"2725\")==\r\n',2044,'protected',NULL,NULL),('algoritmiada-2009/runda-finala/poze','algoritmiada-2009/runda-finala/poze','2009-05-09 07:37:29','2009-05-09 07:44:41','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. Algoritmiada 2009, Runda Finala - Poze\r\n\r\n(htabs)* \'Despre&hellip;\':algoritmiada-2009/runda-finala\r\n* \'Program\':algoritmiada-2009/runda-finala/program\r\n* \'Regulament\':algoritmiada-2009/runda-finala/regulament\r\n* \'Probleme\':algoritmiada-2009/runda-finala/probleme\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-finala/5-8\r\n*(active) \'Poze\':algoritmiada-2009/runda-finala/poze\r\n\r\n== Gallery(page=\"algoritmiada-2009/runda-finala/poze\" file=\"%.jpg\") ==',75,'public',NULL,NULL),('utilizator/tabara','Profil tabara','2006-11-24 20:58:19','2008-11-20 22:41:07','h2. Despre mine\r\n\r\nStudent in anul I la \"Universitatea Politehnica Bucuresti\":http://www.pub.ro/, sectia \"Calculatoare\":http://www.acs.pub.ro/\r\nHandle pe TopCoder: \"__tabara\":http://www.topcoder.com/tc?module=MemberProfile&cr=22657563\r\n\r\nh2. Rezultate la concursurile de informatica\r\n\r\nInvitatie pentru \"TCHS\":http://www.topcoder.com/tc?module=Static&d1=hs&d2=home \"Tournament 2007 Finals\"\r\n(calificare cu echipa )\r\n\r\nh2. Suport pentru infoarena\r\n\r\nProbleme adaugate:\r\n\r\nArhiva de probleme: \"Munte2\":http://infoarena.ro/problema/munte\r\nArhiva educationala: \"Sortare Topologica\":http://infoarena.ro/problema/sortaret\r\n\r\n\r\n\r\n\r\n\r\n\r\n',1024,'protected',NULL,NULL),('utilizator/mathboy','Rotaru Dragos Alin','2008-12-24 18:43:37','2009-05-10 08:05:08','h2. Despre mine\r\n\r\nElev in clasa a IX-a D,Matematica-Informatica,Informatica Intensiv\r\n\r\nColegiul National Unirea Focsani\r\n\r\nContact: dragos_mathboy@yahoo.com\r\n\r\nh2. Distinctii primite\r\n\r\nPremiul III OJI 2009 Focsani clasa a 9-a\r\n\r\n\r\nh2. Prieteni pe infoarena \r\n\r\n* ==user(user=\"Florian\" type=\"tiny\")==\r\n* ==user(user=\"DraStiK\" type=\"tiny\")== \r\n* ==user(user=\"drag0s93\" type=\"tiny\")==\r\n* ==user(user=\"andrici_cezar\" type=\"tiny\")==\r\n* ==user(user=\"bogdanhm999\" type=\"tiny\")==\r\n* ==user(user=\"lucianvn\" type=\"tiny\")==\r\n* ==user(user=\"bolovanemil\" type=\"tiny\")==',9232,'public',NULL,NULL),('utilizator/blasterz','Profil blasterz','2006-11-24 20:58:43','2009-05-13 18:46:09','h3. Student in anul I la Facultatea de Matematica si Informatica, Universitatea Bucuresti\r\n\r\nh2. Distinctii primite\r\n\r\n**2009 : Antrenor si Membru in Comisia Lotului National de Informatica \r\n**2009 : Membru in Comisia ONI la clasele 11-12 si baraj**\r\n**2009 : Propunator probleme .campion ,ONI si lot**\r\n\r\n**2009 : Locul 4 la finala concursului national Algoritmiada, sectia studenti**\r\n**2009 : Calificat in finala Concursului National Algoritmiada pentru Studenti**\r\n**2008 : Calificat in runda a4a a concursului international Google CodeJam**\r\n**2008 : Membru al Lotului National Restrans (unde am obtinut locul 11)**\r\n**2008 : Calificat in Lotul National Largit**\r\n**2008 : Mentiune ONI 2008 + medalie de argint**\r\n**2008 : Finalist .campion 2008 Bran**\r\n2008 : Participare la Concursul National Urmasii lui Moisil, Iasi ( punctajul neoficial cel mai mare...mai trimiti brute la sfarsit fara sa-ti dai seama =)) :| )\r\n2008 : Participare la Concursul National Stelele Informarticii 2008\r\n**2007 : Premiul 1 la Concursul International ProSoft@NT**\r\n**2007 : Finalist .Campion 2007 Galati** \r\n**2007 : Premiul II la Concursul National de Informatica Aplicata (CIA) sectiunea Jocuri**\r\n2007 : Premiul I la Faza Judeteana a Concursul de Informatica Aplicata (CIA) sectiunea Jocuri\r\n2007 : Premiul II la Concursul Interjudetean al Centrelor de Excelenta Suceava\r\n2007 : Mentiune la Concursul de Programare DataS-NMG Targu Secuiesc\r\n2007 : Participare ONI 2007 + calificare pentru baraje\r\n2007 : Premiul 2 Olimpiada Judeteana\r\n2006 : Mentiune la Concursul Interjudetean al Centrelor de Excelenta Suceava\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\nh3. Ordinea nu are importanta. Daca nu am trecut pe careva sa-mi spuneti.\r\n\r\n\r\n* ==user(user=\"georgiana\" type=\"tiny\")== \r\n\r\n* ==user(user=\"marina\" type=\"tiny\")== \r\n\r\n* ==user(user=\"alisssia\" type=\"tiny\")== \r\n\r\n* ==user(user=\"DjSefu\" type=\"tiny\")==\r\n\r\n* ==user(user=\"warchildmd\" type=\"tiny\")==\r\n\r\n* ==user(user=\"nyxpho\" type=\"tiny\")== \r\n\r\n* ==user(user=\"monica_133\"  type=\"normal\")==\r\n\r\n* ==user(user=\"serbanlupu\" type=\"normal\")==\r\n\r\n* ==user(user=\"enslaverr\" type=\"tiny\")==\r\n\r\n* ==user(user=\"Mishu91\" type=\"tiny\")==\r\n\r\n* ==user(user=\"yoyolich\" type=\"tiny\")== \r\n\r\n* ==user(user=\"nuexist\" type=\"tiny\")== \r\n\r\n* ==user(user=\"malex\" type=\"tiny\")==\r\n\r\n* ==user(user=\"lorin_bobu\" type=\"tiny\")==\r\n\r\n\r\n* ==user(user=\"ioanai\" type=\"tiny\")==\r\n\r\n* ==user(user=\"Florian\" type=\"tiny\")==\r\n\r\n\r\n* ==user(user=\"Tabara\" type=\"tiny\")==\r\n\r\n* ==user(user=\"alexthero\" type=\"tiny\")==\r\n\r\n* ==user(user=\"peanutz\" type=\"tiny\")==\r\n\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n\r\n* ==user(user=\"m_dersidan\" type=\"tiny\")==\r\n\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n\r\n* ==user(user=\"mastermage\" type=\"tiny\")==\r\n\r\n* ==user(user=\"nemesis\" type=\"tiny\")==\r\n\r\n* ==user(user=\"Binary_Fire\" type=\"tiny\")==\r\n\r\n* ==user(user=\"TYTUS\" type=\"tiny\")==\r\n\r\n\r\n* ==user(user=\"crawler\" type=\"tiny\")==\r\n\r\n* ==user(user=\"devilkind\" type=\"tiny\")==\r\n\r\n* ==user(user=\"vlad_D\" type=\"tiny\")==\r\n\r\n* ==user(user=\"arenakadaff\" type=\"tiny\")==\r\n\r\n* ==user(user=\"StTwister\" type=\"tiny\")==\r\n\r\n* ==user(user=\"bog_bej\" type=\"tiny\")==\r\n* ==user(user=\"cretu\" type=\"tiny\")==\r\n',1204,'protected',NULL,NULL),('utilizator/marius','Profil Marius','2006-11-24 21:03:36','2009-04-13 00:08:48','h2. Despre mine\r\n\r\n* Am terminat liceul Colegiul National I.C. Bratianu din Piteşti. Acum sunt student la Facultatea de Informatică a Universităţii Babeş Bolyai din Cluj.\r\n\r\n* Îmi place să fac sport, să călătoresc, să citesc, să conduc, să ascult, să mixez muzică. \r\n\r\n* Citatul preferat: \"Quitters don\'t win, winners don\'t quit\"\r\n\r\nh2. Distincţii primite\r\n\r\n* Menţiune şi Premiul Special, _ONI 2007_, Cluj, locul 4.\r\n\r\n* Calificat în _lotul naţional, 2007_.\r\n\r\n* Finalist _preONI 2007_.\r\n\r\n* Participant, pe bază de invitaţie, la concursul _Stelele Informaticii 2008_.\r\n\r\n* Menţiune, _ONI 2008_, Ploieşti, locul 8 şi argint.\r\n\r\n* Membru în comisia concursului interjudeţean de matematică şi informatică _Grigore Moisil, 2009_.\r\n\r\nh2. Eu şi info{_arena_}\r\n\r\nArticole pe care le-am scris:\r\n\r\n* \'Tree decompositions\':tree-decompositions\r\n* \'Treapuri\':treapuri\r\n* \'Deque şi aplicaţii\':deque-si-aplicatii\r\n\r\nProbleme pe care le-am adăugat în arhiva educaţională:\r\n\r\n* \'Cuplaj maxim în graf bipartit\':problema/cuplaj\r\n* \'Componente tare conexe\':problema/ctc\r\n* \'Componente biconexe\':problema/biconex\r\n* \'Subsecvenţa de sumă maximă\':problema/ssm',3146,'protected',NULL,NULL),('runda/prelot2','prelot2','2009-05-16 14:31:22','2009-05-16 14:58:38','h1. == roundparam(round_id=\"prelot2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"prelot2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"prelot2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"prelot2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nConcursul va avea **6 probleme** de natura algoritmica  de nivel ridicat \r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/prelot2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"prelot2\" score=\"1\")==',1204,'round: prelot2',NULL,NULL),('all-you-can-code-2008/solutii/treesearch','all-you-can-code-2008/treesearch','2008-12-01 12:12:19','2009-05-18 19:35:09','h2(#treesearch). \'Tree Search\':problema/treesearch\r\n\r\nProblema se rezolva prin programare dinamica. Presupunem ca agatam arborele intr-un nod oarecare. Folosind DFS, calculam P[$i$] = costul maxim al unui drum care contine drept capat nodul i, si contine doar noduri din subarborele lui i. Relatia de recurenta se determina relativ simplu: P[i] = C[i], daca i este nod terminal, iar P[$i$] = max ( C[$i$], C[$i$] + P[$k$] ), pentru $k$ - adiacent a lui $i$ ( diferit de tatal lui $i$ ). De asemenea, mai trebuie calculat si un vector de tati: tata[x] = tatal nodului x. Avand acesti vectori calculati, mai trebuie sa determinam drumul de cost maxim care are drept extremitate nodul i, si pleaca \"in sus\". Astfel, notam cu T[$i$] - costul maxim al unui drum care pleaca din i, \"in sus\". Pentru a calcula acest vector, ne trebuie cate o parcurgere DF pt fiecare fiu al radacinii. Presupunem ca dorim sa calculam T[] pentru subarborele $k$ al radacinii (asadar, $k$ este fiu al radacinii). Trebuie sa procedam astfel:\r\n\r\n* T[$radacina$] se initializeaza cu max ( C[$radacina$], P[$j$] ), unde $j$ este un fiu al radacinii, diferit de $k$.\r\n* Aplicam un algoritm de tip DF, avand ca punct de plecare $k$. Pentru fiecare nod x pe care il parcurgem (avand tatal t) calculam T[$x$] = max ( C[$x$], C[$x$] + T[$t$], C[$x$] + C[$t$] + P[$j$]), unde $j$ este un fiu al lui $t$, diferit de $i$ si diferit de $tata[$t$]$.\r\n\r\nAsadar, putem acum calcula $bst[$x$]$ = costul maxim al unui drum care contine nodul $x$, pe baza lui $P$ si a lui $T$. Relatia de recurenta se determina usor. Avand acest vector calculat, putem raspunde in O(1) pe query. Asadar complexitatea programului va fi O(N+M).\r\n\r\nObservatie: Pentru a calcula cel mai mare fiu al radacinii, diferit de fiul $k$, se va folosi un deque, altfel algoritmul putand deveni O($N^2$), in caz contrar.\r\n',5748,'public',NULL,NULL),('algoritmiada-2009/runda-finala/solutii/morcovi','Morcovi','2009-05-18 19:30:27','2009-05-18 20:04:07','h1. \'Morcovi\':problema/morcovi\r\n\r\nProblema se rezolva prin programare dinamica. Notam cu bst[ $i$ ][ $j$ ] = gradul de satisfactie maxim pe care il poate obtine iepurele, daca a efectuat pasii corespunzatori bitilor de $1$ ai lui $i$, si se afla in nodul $j$. Se observa ca din bst[ $i$ ][ $j$ ] se poate ajunge in orice bst[$i$ + $2$ ^ $poz$][ $j$ + $Pas [ $poz$ ]$ ], cu $poz$ de la 1 la $P$, iar al $poz$ - lea bit a lui $i$ este 0. Pt fiecare stare se alege maximul posibil. Evident rezultatul va fi maximul de pe linia bst[ $2$ ^ $P$ - $1$ ].',5748,'public',NULL,NULL),('algoritmiada-2009/runda-finala/solutii/morcovi','Morcovi','2009-05-18 19:30:27','2009-05-18 20:09:58','h1. \'Morcovi\':problema/morcovi\r\n\r\nProblema se rezolva prin programare dinamica. Notam cu $bst$[ $i$ ][ $j$ ] = gradul de satisfactie maxim pe care il poate obtine iepurele, daca a efectuat pasii corespunzatori bitilor de $1$ ai lui $i$, si se afla in nodul $j$. Se observa ca din $bst$[ $i$ ][ $j$ ] se poate ajunge in orice $bst$[$i$ + (1<< $poz$ )][ $j$ + $Pas [ $poz$ ]$ ], cu $poz$ de la 1 la $P$, iar al $poz$ - lea bit a lui $i$ este 0. Pentru fiecare stare se alege maximul posibil. Evident rezultatul va fi maximul de pe linia bst[ $2$ ^ $P$ - $1$ ].',5748,'public',NULL,NULL),('documentatie/evaluator','Evaluatorul infoarena','2006-11-27 05:18:35','2009-03-12 21:34:56','h1. Evaluatorul infoarena\r\n\r\n== include(page=\"documentatie/sidebar\")==\r\n\r\n... este responsabil de evaluarea solutiilor trimise de utilizator.\r\n\r\nh2. Cum se evalueaza o problema\r\n\r\nMai intai, codul sursa trimis de concurent se compileaza (vezi tabelul de mai jos). Apoi, solutia se _evalueaza_: se ruleaza programul compilat pentru diferite date de intrare (teste). In urma rularii, un program specializat decide daca raspunsul dat de solutia concurentului este corect si acord un punctaj pe masura.\r\n\r\nFiecare program compilat are dreptul de a rula doar un anumit interval de timp (specificat in descrierea problemei). in cazul in care timpul de executie este depasit, programul este terminat automat de sistem. Analog, se pot impune si limite de memorie.\r\n\r\nEvaluarea se face intr-un mediu restrictionat. Programele compilate pot citi/scrie fisiere doar din/in directorul curent si nu au acces la unele functii sistem.\r\n\r\nh2. Compilatoare folosite\r\n\r\nIata *lista oficiala* de compilatoare folosite de evaluatorul infoarena:\r\n\r\ntable{width:50%}. |_. Compilator si versiune|_. Comanda de compilare |_. Extensie implicita |\r\n| GNU GCC 4.2.3 | $gcc -Wall -O2 -static &hellip; -lm$ | c |\r\n| GNU G++ 4.2.3 | $g++ -Wall -O2 -static &hellip; -lm$ | cpp |\r\n| FreePascal Compiler 2.0.4 | $fpc -O2 -Xs &hellip;$               | pas |\r\n\r\nh2. Configuratia sistemului de evaluare\r\n\r\nEvaluatorul ruleaza pe un calculator dedicat, oferit de ==User(user=\"fluffy\")==. (Multumim, Leo!)\r\n\r\n* Sistem de operare: Debian stable(sarge)\r\n* Procesor: Pentium IV, $2.0 GHz$\r\n* Memorie: $512 MB RAM$\r\n\r\nh2. Gazduire !>documentatie/evaluator?hqn.png!\r\n\r\nEvaluatorul infoarena este gazduit cu placere de catre \"HQN (High Quality Networks)\":http://hqn.ro/.\r\n\r\nh2. Mesaje de evaluare\r\n\r\nPentru cei care nu sunt familiari cu sistemele unix sau sunt incepatori in programare, multe dintre mesajele evaluatorului pot parea oarecum criptice.\r\n\r\n* Eroare de sistem: Daca ai obtinut aceast mesaj te rugam sa ne contactezi, preferabil pe \'forum\':forum. Te rugam sa mentionezi si id-ul job-ului.\r\n* OK: Totul a functionat perfect.\r\n* Memory limit exceeded: Ai depasit limita de memorie. Majoritatea problemelor au o limita de 64 de mega, pe care noi o consideram destul de generoasa.\r\n* Time limit exceeded: Programul tau a depasit limita de timp. Asta inseamna ca programul tau nu este destul de rapid.\r\n* Wall time limit exceeded: Evaluarea a durat prea mult si a fost abandonata. Evaluatorul infoarena masoara doar timpul folosit de programul tau pentru a determina daca iti da TLE, dar exista si o limita fata de \"ceasul de perete\". Acest mesaj poti sa il obtii daca faci sleep, scanf de la stdin si alte functii care stau degeaba fara sa consume efectiv procesorul.\r\n* Blocked system call: Ai accesat o functie la care nu ai access. Nu ar trebui sa primesti aceasta functie decat daca incerci explicit sa faci ceva interzis.\r\n* Killed by signal: Cea mai frecventa eroare cand ai un bug in program. Cand un program incalca anumite conventii in UNIX acel program primeste un \"semnal\" care de cele mai multe ori il opreste. Cateva semnale comune:\r\n** 11(SIGSEGV): Segmentation fault. Asta in 99% din cazuri inseamna ca ai probleme cu accesul la memorie. Ai iesit din limitele unui vector, ai facut stack overflow, etc.\r\n** 8(SIGFPE): Floating point error. Cauzat cel mai frecvent de impartiri la 0.\r\n* Non-zero exit status: Programul tau a returnat o valoare diferita de 0. Cel mai probabil ai uitat return 0; sau ceva similar. Poti primi acest mesaj si in loc de mesajul \"Killed by signal\": verifica si dupa erorile mentionate deasupra.\r\n\r\nEvaluatoarele problemelor iti vor da si ele un mesaj scurt, cel mai frecvent ceva de genul \"OK\" sau \"Wrong Answer\", dar unii propunatorii au umor :).\r\n\r\nh2. Troubleshooting\r\n\r\nPentru programatorii in Borland C/Pascal este important de tinut minte ca evaluatorul infoarena este un mediu *foarte* diferit fata de dos. Cateva erori comune si cum pot fi rezolvate\r\n\r\n* Pe infoarena se face I/O din fisiere, nu de la stdin, stdout. Daca faci scanf de la stdin vezi obtine cel mai probabil \"Wall time limit exceeded\" (vezi mai sus) iar daca faci printf la stdout rezultatul tau va fi ignorat.\r\n* tipul int din GCC este pe 32 de biti, nu 16 ca in Borland C/C++, char - 8 biti, short - 16 biti, long - 32, long long - 64\r\n* folositi sprintf in loc de itoa sau ltoa.\r\n* programul de evaluare ruleaza pe un sistem de operare UNIX. Folositi \"\\n\" pentru terminarea liniei curente, nu \"\\r\\n\"\r\n* aveti grija ca functia main sa fie de tip int si sa intoarca 0 (return 0;)\r\n* nu folositi librarii dependente de sistemul de operare (ex. dos.h, graphics.h in C sau dos, crt, graph in pascal). Aceste librarii nu sunt necesare pentru a rezolva problemele de pe infoarena.\r\n* nu folositi modificatorii far, huge, _huge, __huge pentru ca nu exista in GCC. De asemenea, nu exista nici functiile care folosesc aceste tipuri de date (de ex. farmalloc, farfree etc.) si nici conceptul de memory model (tiny, small, medium, large, huge). De toate acestea nu mai e nevoie intrucat puteti avea acces la toata memoria prin functii standard si pointer-i standard - new, delete, malloc etc.',1490,'protected',NULL,NULL),('all-you-can-code-2008/solutii/treesearch','Tree Search','2008-12-01 12:12:19','2009-05-19 09:32:49','h2(#treesearch). \'Tree Search\':problema/treesearch\r\n\r\nProblema se rezolva prin programare dinamica. Presupunem ca agatam arborele intr-un nod oarecare. Folosind DFS, calculam P[ $i$ ] = costul maxim al unui drum care contine drept capat nodul $i$, si contine doar noduri din subarborele lui $i$. Relatia de recurenta se determina relativ simplu: P[ $i$ ] = C[ $i$ ], daca $i$ este nod terminal, iar P[ $i$ ] = max ( C[ $i$ ], C[ $i$ ] + P[ $k$ ] ), pentru $k$ - adiacent a lui $i$ ( diferit de tatal lui $i$ ). De asemenea, mai trebuie calculat si un vector de tati: tata[ $x$ ] = tatal nodului $x$. Avand acesti vectori calculati, mai trebuie sa determinam drumul de cost maxim care are drept extremitate nodul $i$, si pleaca \"in sus\". Astfel, notam cu T[ $i$ ] - costul maxim al unui drum care pleaca din $i$, \"in sus\". Pentru a calcula acest vector, ne trebuie cate o parcurgere DF pt fiecare fiu al radacinii. Presupunem ca dorim sa calculam $T$[] pentru subarborele $k$ al radacinii (asadar, $k$ este fiu al radacinii). Trebuie sa procedam astfel:\r\n\r\n* T[ $radacina$ ] se initializeaza cu max ( C[ $radacina$ ], P[ $j$ ] ), unde $j$ este un fiu al radacinii, diferit de $k$.\r\n* Aplicam un algoritm de tip DF, avand ca punct de plecare $k$. Pentru fiecare nod $x$ pe care il parcurgem (avand tatal $t$) calculam T[ $x$ ] = max ( C[ $x$ ], C[ $x$ ] + T[ $t$ ], C[ $x$ ] + C[ $t$ ] + P[ $j$ ]), unde $j$ este un fiu al lui $t$, diferit de $i$ si diferit de $tata[$t$]$. Continuam parcurgerea cu fiecare subarbore a lui $x$ (considerand radacina tot nodul $radacina$)\r\n\r\nAsadar, putem acum calcula $bst[ $x$ ]$ = costul maxim al unui drum care contine nodul $x$, pe baza lui $P$ si a lui $T$. Relatia de recurenta se determina usor. Avand acest vector calculat, putem raspunde in O(1) pe query. Asadar complexitatea programului va fi O( $N$ + $M$ ).\r\n\r\nObservatie: Pentru a calcula cel mai mare fiu al radacinii, diferit de fiul $k$, se va folosi un deque, altfel algoritmul putand deveni O($N$ ^ $2$).\r\n',5748,'public',NULL,NULL),('algoritmiada-2009/runda-finala/solutii/electrica','Electrica','2009-05-18 19:29:32','2009-05-18 19:29:32','h1. \'Electrica\':problema/electrica',1792,'public',NULL,NULL),('utilizator/andrici_cezar','Profil andrici_cezar','2008-02-20 11:15:10','2009-05-24 12:20:39',' *Despre mine*\r\n\r\n Sunt un elev din clasa a VI aB de la \'Liceul de Informatica Gr.C.Moisil Iasi\':http://liis.ro.\r\n Medii de programare: Pascal, C++, Adobe Reader Flash Profesional CS4 / CS3,C# (nu stiu prea mult dar ma descurc);\r\n\r\n\r\n *Distinctii primite*\r\n\r\n_Premiul I la Informatica la ,,Urmasii lui Moisil\", la clasa a 4a!!!`````````anul 2007_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 5a!!!```````anul 2008_\r\n_Premiul III la Informatica Faza Judeteana-98 puncte, la clasa a 5a!!!````anul 2008_ (Calificat la ONI 2008)\r\n_Mentiune la Informatica Faza Nationala-160 puncte, la clasa a 5a!!!````anul 2008_ (Pe locul 8)\r\n_Mentiune la Matematica Faza Judeteana, la clasa a 5a!!!`````anul 2008_\r\n_Premiul I la Informatica Faza Locala-200 puncte, la clasa a 9a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 5a!!!`````````anul 2008_\r\n_Premiul II la Informatica la ,,Moisil++\", la clasa a 5a!!!````````````anul 2008_\r\n_Premiul I la Informatica la ,,Concursul National al centrelor de Excelenta\", la clasa a 5a!!!```````anul 2008_\r\n_Premiul II la Informatica la ,,Urmasii lui Moisil\", la clasa a 6a!!!``````````anul 2009_\r\n_Premiul II la Informatica la Faza Locala-110 puncte, la clasa a 6a!!!`````anul 2009_\r\n_Premiul III la Informatica la Faza Judeteana-40 puncte, la clasa a 6a!!!````anul 2009_ (Calificat la ONI 2009)\r\n_Mentiune la Informatica Faza Nationala-230 puncte, la clasa a 6a!!!````````anul 2009_ (Pe locul 4)\r\n_Nimic la Informatica Faza Natioanal din Bulgaria-140 puncte/600 puncte, la clasa a 6a!!!`````anul 2009_\r\n_Premiul II la Informatica la ,,AL 4-LEA VAL\", clasa a 6a!!!```````anul 2009_\r\n_Premiul I la Informatica la ,,Moisil++\" , la clasa a 6a!!!````````anul 2009_\r\n\r\n*.Campion*\r\n*2008 - 2009* - 916 puncte clasat pe locul 51\r\n\r\n*Alte rezultate*\r\n\r\n* Chemat la CEX la a 9a 2009(cls.a 6a)\r\n* ONI 2009 Bulgaria cu ajutorul profesorilor Emanuela Cherchez si Marinel Serban\r\n\r\n*Profesori*\r\n\r\n* Ivasc Cornelia si Mirela Tibu ->[\'Elevi\':http://olimpiada.info/oji2009/index.php?cid=participanti&w=gim&judet=25&clasa=6]\r\n* Infoarena\r\n* \'.Campion\':http://campion.edu.ro\r\n\r\n*Citate preferate*\r\n_Daca plangi pentru ca soarele a disparut din viata ta, lacrimile te vor impiedica sa vezi stelele_ - Rabindranath Tagore\r\n\r\n_Un om nu este distrus atunci cind este invins; e distrus atunci cind renunta_- Richard Milhous Nixon\r\n\r\n_Nu este intelept sa fii sigur asupra propriei tale intlepciuni. Este sanatos sa ti se aminteasca ca si cel puternic poate slabi, iar cel intelept poate gresi_ - Mahatma Gandhi\r\n\r\n_Cel puternic nu este cel care este de neinvins, ci cel care se ridica dupa fiecare lovitura_\r\n\r\n_Loveste spre soare chiar daca nu reusesti, macar o sa fii printre stele_\r\n\r\nh3. Prieteni\r\n\r\n==user(user=\"marta_dianna\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"antoanela\" type=\"tiny\")==\r\n(8)\r\n\r\n\r\n==user(user=\"matemariaescu\" type=\"tiny\")==\r\n(8)\r\n\r\n==user(user=\"liana\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"alexrusu\" type=\"tiny\")==\r\n(7)\r\n\r\n==user(user=\"netedu_andrei\" type=\"tiny\")==\r\n(6)\r\n\r\n==user(user=\"mironalex2005\" type=\"tiny\")==\r\n(6)\r\n\r\n==user(user=\"unsilviu\" type=\"tiny\")==\r\n(7)\r\n\r\nScanteie Sebi(7)\r\nMunteanu Bogdan(8)\r\nAnton Madalina(8)\r\nBrezuleanu Razvan(8)\r\n\r\nToti am fost si anu trecut si anu asta la ONIgimnaziu si vom putea fi toti din nou doar peste 2 ani!\r\n\r\nh3. Prieteni care i-am vazut dar ne cunoastem doar prin messenger\r\n\r\n==user(user=\"toni2007\" type=\"tiny\")==\r\nMa ajuta la probleme\r\n==user(user=\"crawler\" type=\"tiny\")==\r\nTot la probleme\r\n==user(user=\"stef2n\" type=\"tiny\")==\r\nMa ajuta sa scriu articole\r\n==user(user=\"DITzoneC\" type=\"tiny\")==\r\nMa ajuta sa scriu probleme\r\n==user(user=\"mathboy\" type=\"tiny\")==\r\nVorbim despre probleme\r\n==user(user=\"cipriancx\" type=\"tiny\")==\r\nVorbim despre probleme\r\n\r\nh3. Probleme adaugate\r\n\r\n\'Taxe\':http://infoarena.ro/problema/taxe\r\n\'Nrcuv1\':http://infoarena.ro/problema/nrcuv1\r\n\'Dunarea\':http://infoarena.ro/problema/dunarea\r\n\'Tir\':http://infoarena.ro/problema/tir\r\n\'Banda1\':http://infoarena.ro/problema/banda1\r\n\'Decod\':http://infoarena.ro/problema/decod\r\n\'Paralelogram\':http://infoarena.ro/problema/paralelogram\r\n\'Parcele1\':http://infoarena.ro/problema/parcele1\r\n\'Patrate1\':http://infoarena.ro/problema/patrate1\r\n',7668,'public',NULL,NULL),('runda/dragos','dragos','2009-05-24 15:11:04','2009-05-24 15:40:10','h1. == roundparam(round_id=\"dragos\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"dragos\") ==\r\n\r\nConcursul este adresat tuturor elevilor de clasa a 9-a, care la anu vor infrunta OJI 2010. Tema acestui concursul este algoritmul lui Lee, cunoscut de catre programatori, ceea ce consta in gasirea unui drum de timp minim intr-un caroiaj, etc.\r\n\r\nToate cele 5 probleme se rezolva cu algoritmul lui Lee. In teoria de specialitate, defapt acest algoritm este o parcurgere BF a unui graf.\r\n\r\nConcursul incepe ==roundparam(round_id=\"dragos\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"dragos\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDeoarece ceva nu este in regula cu evaluatorul, voi adauga lista manual\r\n\r\nh2. Probleme\r\n\r\n* http://infoarena.ro/problema/cub\r\n\r\n* http://infoarena.ro/problema/cobai\r\n\r\n* http://infoarena.ro/problema/alee\r\n\r\n* http://infoarena.ro/problema/muzeu \r\n\r\n* http://infoarena.ro/problema/rj\r\n\r\n* http://infoarena.ro/problema/alge\r\n\r\nh2. Participanti\r\n\r\nCei care vor sa participe, va rog insistent sa imi trimiteti un private mesage cu username-ul de pe infoarena ca sa pot face clasamentul!\r\n\r\n* ==user(user=\"mathboy\" type=\"tiny\")==',6957,'round: dragos',NULL,NULL),('runda/dragos','dragos','2009-05-24 15:11:04','2009-05-24 15:54:04','h1. == roundparam(round_id=\"dragos\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"dragos\") ==\r\n\r\nConcursul este adresat tuturor elevilor de clasa a 9-a, care la anu vor infrunta OJI 2010. Tema acestui concursul este algoritmul lui Lee, cunoscut de catre programatori, ceea ce consta in gasirea unui drum de timp minim intr-un caroiaj, etc.\r\n\r\nToate cele 5 probleme se rezolva cu algoritmul lui Lee. In teoria de specialitate, defapt acest algoritm este o parcurgere BF a unui graf.\r\n\r\nConcursul incepe ==roundparam(round_id=\"dragos\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"dragos\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDeoarece ceva nu este in regula cu evaluatorul, voi adauga lista manual\r\n\r\nh2. Probleme\r\n\r\n==Tasks(round_id=\"dragos\" score=\"1\")==\r\n\r\n* http://infoarena.ro/problema/cub\r\n\r\n* http://infoarena.ro/problema/cobai\r\n\r\n* http://infoarena.ro/problema/alee\r\n\r\n* http://infoarena.ro/problema/muzeu \r\n\r\n* http://infoarena.ro/problema/rj\r\n\r\n* http://infoarena.ro/problema/alge\r\n\r\nh2. Participanti\r\n\r\nCei care vor sa participe, va rog insistent sa imi trimiteti un private mesage cu username-ul de pe infoarena ca sa pot face clasamentul!\r\n\r\n* ==user(user=\"mathboy\" type=\"tiny\")==',2028,'round: dragos',NULL,NULL),('runda/dragos','dragos','2009-05-24 15:11:04','2009-05-24 19:33:53','h1. == roundparam(round_id=\"dragos\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"dragos\") ==\r\n\r\nConcursul este adresat tuturor elevilor de clasa a 9-a, care la anu vor infrunta OJI 2010. Tema acestui concursul este algoritmul lui Lee, cunoscut de catre programatori, ceea ce consta in gasirea unui drum de timp minim intr-un caroiaj, etc.\r\n\r\nToate cele 5 probleme se rezolva cu algoritmul lui Lee. In teoria de specialitate, defapt acest algoritm este o parcurgere BF a unui graf.\r\n\r\nConcursul incepe ==roundparam(round_id=\"dragos\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"dragos\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nh2. Probleme\r\n\r\n==Tasks(round_id=\"dragos\" score=\"1\")==\r\n\r\nDupa terminarea rundei veti putea vedea clasamentul//http://infoarena.ro/runda/dragos/clasament',6957,'round: dragos',NULL,NULL),('planificare/sedinta-20090727','Ședință 2009-07-27','2009-07-14 07:30:58','2009-07-22 08:42:20','h1. Şedinţă 2009-07-27\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *luni, 27 iulie* la ora *19:00* la *Hotel Marriott (sala \"Oradea\", etaj I)*\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"Marius\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n|Recapitulare \'sedinţă anterioară\':planificare/sedinta-20090403| ? |\r\n|OKRs| ? |\r\n\r\nh2. Detalii\r\n\r\nh3. OKRs\r\n\r\n* Notele pentru \'Q1 2009\':okr/20091 nu sunt finalizate.\r\n* Nu avem obiective şi nici rezultate pe Q2. Sărim peste?\r\n* Trebuie stabilite obiective pentru Q3 (doar 2 luni şi jumătate din el).\r\n\r\nh3. Misc\r\n\r\n* Silviu si Cristi concretizeaza IAP 7 (1 sedinta)\r\n* Care-i situaţia la development\r\n* Încercăm conferinţă video pe Skype cu membrii de la distanţă (Marius, Astronomy)?\r\n* Ştefan şi Vali (22.75RON) trebuie să-şi deconteze biletele de tren de întoarcere de la finala Algoritmiada.\r\n* Ştefan şi Vali îşi vor diplomele de onoare de la Algoritmiada cu care apar în \'registrul de diplome\':registru-diplome. :)\r\n\r\nh2(#rezolutii). Rezoluţii',2044,'protected',NULL,NULL),('utilizator/fluffy','Profil fluffy','2006-11-24 20:58:35','2009-07-21 08:35:06','h2. Contact\r\n\r\nBug-uri pe ==smflink(link=\"topic\" topic=\"1359\" caption=\"forum\")==\r\n\r\nh2. Despre mine\r\n\r\nNimic!',1142,'protected',NULL,NULL),('blog/problema-saptamanii-monede-solutie1','Problema saptamanii - Monede (Solutie)','2009-07-21 08:16:49','2009-07-21 08:22:29','Nu am mai scris de mult si v-am ramas dator cu solutia problemei Monede, daca ati uitat cerinta, puteti citi enuntul:\r\n\r\n_Pe o masa dreptunghiulara punem monede de raza 1 pana cand nu mai putem adauga o noua moneda fara ca ea sa se suprapuna cu altele. Unele monede pot fi partial inafara mesei. Daca numarul total de monede este n, sa se demonstreze ca toata suprafata mesei poate fi acoperita de 4n monede de raza unu care se pot suprapune._\r\n\r\nDaca inlocuim cele n monede de raza unu cu monede centrate la fel dar care au raza doi, ele vor acoperi total masa, pentru ca in configuratia initiala, orice punct neacoperit era la o distanta mai mica decat unu de o moneda (in caz contrar am fi putut plasa inca o moneda de raza unu centrata in punctul respectiv).\r\nAsta inseamna ca, cu n monede de raza unu putem acoperi un dreptunghi cu aria un sfert din aria mesei. Cu patru astfel de dreptunghiuri acoperite, putem obtine o configuratie a 4n monede ce acopera intreaga masa.\r\n\r\nSingurul rezolvitor a fost Andrei Dragus, felicitari.',58,'protected',4042,NULL),('utilizator/gcosmin','Profil gcosmin','2006-11-24 21:00:42','2008-08-29 23:24:53','h2. Despre mine\r\n\r\n* Elev in clasa a 12-a la Liceul International de Informatica.\r\n* Imi place informatica din clasa a 5-a si de atunci incerc sa devin din ce in ce mai bun.\r\n\r\nh2. Distinctii primite\r\n\r\n* Clasa a 9-a (2005-2006) : locul I la ONI; medalie de argint in Yakutia\r\n* Clasa a 10-a (2006-2007) : locul I la ONI; medalie de argint la IOI\r\n* Clasa a 11-a (2007-2008) : locul I la ONI; medalie de aur la CEOI; medalie de aur la IOI\r\n\r\nh2. Despre infoarena\r\n\r\n* Infoarena a fost pentru mine cel mai important site de pregatire. De aici am lucrat cele mai multe probleme si am invatat cele mai multe \"smenuri\". M-a ajutat enorm in clasa a 9-a sa cresc in cunostinte si inca este site-ul cu probleme preferat.\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"mariusdrg\" type=\"tiny\")==\r\n* ==user(user=\"greco\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"prostu\" type=\"tiny\")==\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n\r\n',2038,'protected',NULL,NULL),('runda/cnrv_1','cnrv_1','2009-09-26 16:48:03','2009-09-26 16:55:53','h1. == roundparam(round_id=\"cnrv_1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cnrv_1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cnrv_1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cnrv_1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nConcursul este unul de incalzire si se adreseaza in special elevilor de clasa a 10-a, CNRV. Dificultatea problemelor este scazuta.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cnrv_1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cnrv_1\" score=\"1\")==',5748,'round: cnrv_1',NULL,NULL),('blog/algoritmiada-2009-final','blog/algoritmiada-2009-final','2009-05-26 20:31:32','2009-05-26 20:31:32','Iată ca Algoritmiada 2009 a ajuns la final: runda finală a avut loc, premiile au fost confiscate, o parte din voi aţi petrecut câteva zile într-un oraş frumos al ţării.\r\n\r\nLa final, aş vrea să ne uităm peste statisticile pentru fiecare rundă. Pe baza lor putem să apreciem dacă Algoritmiada a devenit un concurs mai popular de la an la an.\r\n\r\ntable. |_. &nbsp; |_. Runda 1 |_. Runda 2 |_. Runda 3 |_. Finala |\r\n| Câţi concurenţi au trimis soluţii | 223 | 157 | 126 |  ?? |\r\n| Câţi concurenţi s-au inscris | 356 | 232 | 151 | ?? |\r\n| Surse trimise | 1245 | 894 | 995 | ?? |\r\n| Surse cu punctaj pozitiv | 685 | 408 | 561 | ?? |\r\n| Concurenţi cu punctaj pozitiv | 162 | 113 | 112 | ?? |\r\n| Punctaj mediu al concurenţilor care au trimis soluţii | 75.09 | 43.85 | 105.43 | ?? |\r\n| Punctaj mediu al concurenţilor cu punctaj > 0 | 103.36 | 60.93 | 118.61 | ?? |\r\n\r\nIată că numărul celor care au trimis soluţii a scăzut de la rundă la rundă. Se pare că numai ~125 de concurenţi au fost suficient de motivaţi să ducă maratonul celor 3 runde online până la capăt. Mă întreb care sunt motivele pentru care concurenţii renunţă progresiv. Primul care îmi vine în minte ar fi că pe măsură ce îţi dai seama că nu mai ai sanse de calificare renunţi. Personal dezaprob o astfel de gândire: participi la fiecare concurs ca să înveţi -- faptul că ajungi la finală e un bonus, nu scopul în sine! Excepţie fac studenţii care, probabil, au mai puţin timp să se distreze cu probleme de algoritmică :)\r\n\r\nCâteva cuvinte despre organizarea finalei. Îmi pare rău ca n-am ajuns la finală să joc fotbal. Aş fi vrut să-l văd şi eu evoluând pe atât de lăudatul fotbalist din echipa infoarena. Da (==user(user=\"astronomy\")==), despre tine e vorba :)\r\n\r\nÎn altă ordine de idei, aceasta este prima finală organizată de infoarena în care membrii mai vechi s-au implicat mai puţin spre deloc. Am dorit să-i lăsam pe cei mai tineri să ia microfonul în mână şi să iasă în faţă. V-aţi descurcat foarte bine! Aţi adus un suflu nou şi lucruri inovatoarea (la vâsle mă refer).\r\n\r\nDin feedback-ul trimis de voi pe \'forum\':http://infoarena.ro/forum/index.php?topic=3897.0 reiese că organizarea a fost bună, în general. Câteva din problemele menţionate pe care vom încerca să le eliminăm pe viitor: evaluarea live nu a meritat aşteptarea de o zi; evaluarea putea fi mai spectaculoasa; au fost câteva teste buşite (de obicei nu ni se întamplă, probabil din cauza aglomerării organizatorice).\r\n\r\nApropo de concurs, aş vrea să remarc pe ==user(user=\"gavrilavlad\")== care a luat punctaj maxim în toate probele Algoritmiadei la grupa Gimnaziua. Felicitări Vlad!\r\n\r\nÎn final aş vrea să spun că infoarena a făcut eforturi financiare şi organizatorice mari anul acesta pentru a organiza finala în afara Bucureştiului. Am ales Braşov şi am ales bine pentru că acolo ne-am bucurat de sprijinul deosebit generos al liceului \'Colegiul National de Informatica \"Grigore Moisil\"\':http://www.moisilbrasov.ro. TODO: nominalizati directoarea si profesorii care ne-au ajutat.\r\n\r\nMulţumim şi sponsorului Algoritmiadei, \'Adobe România\':http://myadobe.ro/. Este al doilea an consecutiv când Adobe susţine activităţile noastre şi asta ne bucură foarte mult. Adobe a înţeles că ce facem este important pentru viitorul IT-ului din România şi că voi meritaţi să fiţi răsplătiţi şi încurajaţi. Chiar şi pe timp de criză :)\r\n\r\nSper că v-a plăcut Algoritmiada de anul acesta şi sperăm să putem să o organizăm şi în 2010.',15,'private',NULL,NULL),('blog/algoritmiada-2009-final','Algoritmiada 2009 la final','2009-05-26 20:31:32','2009-05-26 20:55:52','Iată ca Algoritmiada 2009 a ajuns la final: runda finală a avut loc, premiile au fost confiscate, o parte din voi aţi petrecut câteva zile într-un oraş frumos al ţării.\r\n\r\nLa final, aş vrea să ne uităm peste statisticile pentru fiecare rundă. Pe baza lor putem să apreciem dacă Algoritmiada a devenit un concurs mai popular de la an la an.\r\n\r\ntable. |_. &nbsp; |_. Runda 1 |_. Runda 2 |_. Runda 3 |_. Finala |\r\n| Câţi concurenţi au trimis soluţii | 223 | 157 | 126 |  ?? |\r\n| Câţi concurenţi s-au inscris | 356 | 232 | 151 | ?? |\r\n| Surse trimise | 1245 | 894 | 995 | ?? |\r\n| Surse cu punctaj pozitiv | 685 | 408 | 561 | ?? |\r\n| Concurenţi cu punctaj pozitiv | 162 | 113 | 112 | ?? |\r\n| Punctaj mediu al concurenţilor care au trimis soluţii | 75.09 | 43.85 | 105.43 | ?? |\r\n| Punctaj mediu al concurenţilor cu punctaj > 0 | 103.36 | 60.93 | 118.61 | ?? |\r\n\r\nIată că numărul celor care au trimis soluţii a scăzut de la rundă la rundă. Se pare că numai ~125 de concurenţi au fost suficient de motivaţi să ducă maratonul celor 3 runde online până la capăt. Mă întreb care sunt motivele pentru care concurenţii renunţă progresiv. Primul care îmi vine în minte ar fi că pe măsură ce îţi dai seama că nu mai ai sanse de calificare renunţi. Personal dezaprob o astfel de gândire: participi la fiecare concurs ca să înveţi -- faptul că ajungi la finală e un bonus, nu scopul în sine! Excepţie fac studenţii care, probabil, au mai puţin timp să se distreze cu probleme de algoritmică :)\r\n\r\nCâteva cuvinte despre organizarea finalei. Îmi pare rău ca n-am ajuns la finală să joc fotbal. Aş fi vrut să-l văd şi eu evoluând pe atât de lăudatul fotbalist din echipa infoarena. Da ==user(user=\"astronomy\")==, despre tine e vorba :)\r\n\r\nÎn altă ordine de idei, aceasta este prima finală organizată de infoarena în care membrii mai vechi s-au implicat mai puţin spre deloc. Am dorit să-i lăsam pe cei mai tineri să ia microfonul în mână şi să iasă în faţă. V-aţi descurcat foarte bine! Aţi adus un suflu nou şi lucruri inovatoarea (la vâsle mă refer).\r\n\r\nDin feedback-ul trimis de voi pe \'forum\':http://infoarena.ro/forum/index.php?topic=3897.0 reiese că organizarea a fost bună. Câteva din problemele menţionate pe care vom încerca să le eliminăm pe viitor: evaluarea live nu a meritat aşteptarea de o zi şi putea fi mai spectaculoasă; au fost câteva teste buşite (de obicei nu ni se întamplă, o punem pe seama aglomerării organizatorice).\r\n\r\nAş vrea să remarc performanţa deosebită a lui ==user(user=\"gavrilavlad\")== care a obţinut punctajul maxim în toate probele Algoritmiadei la grupa Gimnaziu. Felicitări Vlad!\r\n\r\nŞi acum publicitate ... :)\r\n\r\nLăsând gluma la o parte, anul acesta infoarena a făcut eforturi financiare şi organizatorice mari pentru a organiza finala în afara Bucureştiului. Am ales Braşov şi am ales bine pentru că acolo ne-am bucurat de sprijinul deosebit generos al liceului \'Colegiul National de Informatica \"Grigore Moisil\"\':http://www.moisilbrasov.ro. TODO: nominalizati directoarea si profesorii care ne-au ajutat si spus cateva vorbe frumoase despre ei.\r\n\r\nMulţumim şi sponsorului Algoritmiadei, \'Adobe România\':http://myadobe.ro/. Este al doilea an consecutiv când Adobe susţine activităţile noastre şi asta ne bucură foarte mult. Adobe a înţeles că ce facem este important pentru viitorul IT-ului din România şi că voi meritaţi să fiţi răsplătiţi şi încurajaţi. Chiar şi pe timp de criză :)\r\n\r\nÎn final vă spun \'unde\':algoritmiada-2009/runda-finala/poze găsiţi pozele de la finală.',15,'private',NULL,NULL),('blog/algoritmiada-2009-final','Algoritmiada 2009 la final','2009-05-26 20:31:32','2009-05-26 21:16:56','!{margin: 10px; margin-right: 0; border: 1px solid gray;}>blog/algoritmiada-2009-final?cetatea.jpg! Iată ca Algoritmiada 2009 a ajuns la final: runda finală a avut loc, o parte din voi a petrecut câteva zile într-un oraş frumos al ţării, premiile au fost confiscate, cetatea a fost cucerită :)\r\n\r\nLa final, aş vrea să ne uităm peste statisticile pentru fiecare rundă. Pe baza lor putem să apreciem dacă Algoritmiada a devenit un concurs mai popular de la an la an.\r\n\r\ntable. |_. &nbsp; |_. Runda 1 |_. Runda 2 |_. Runda 3 |_. Finala |_. Total |\r\n| Câţi concurenţi au trimis soluţii | 223 | 157 | 126 |  97 | 313 |\r\n| Câţi concurenţi s-au inscris | 356 | 232 | 151 | 103 | 508 |\r\n| Surse trimise | 1245 | 894 | 995 | 758 | 3892 |\r\n| Surse cu punctaj pozitiv | 685 | 408 | 561 | 537 | 2191 |\r\n| Concurenţi cu punctaj pozitiv | 162 | 113 | 112 | 92 | 242 |\r\n| Punctaj mediu al concurenţilor care au trimis soluţii | 75.09 | 43.85 | 105.43 | 118.09 | 154.53 |\r\n| Punctaj mediu al concurenţilor cu punctaj > 0 | 103.36 | 60.93 | 118.61 | 124.51 | 199.87 |\r\n\r\nIată că numărul celor care au trimis soluţii a scăzut de la rundă la rundă. Se pare că numai ~125 de concurenţi au fost suficient de motivaţi să ducă maratonul celor 3 runde online până la capăt. Mă întreb care sunt motivele pentru care concurenţii renunţă progresiv. Primul care îmi vine în minte ar fi că pe măsură ce îţi dai seama că nu mai ai sanse de calificare renunţi. Personal dezaprob o astfel de gândire: participi la fiecare concurs ca să înveţi -- faptul că ajungi la finală e un bonus, nu scopul în sine! Excepţie fac studenţii care, probabil, au mai puţin timp să se distreze cu probleme de algoritmică :)\r\n\r\nCâteva cuvinte despre organizarea finalei. Îmi pare rău ca n-am ajuns la finală să joc fotbal. Aş fi vrut să-l văd şi eu evoluând pe atât de lăudatul fotbalist din echipa infoarena. Da ==user(user=\"astronomy\")==, despre tine e vorba :)\r\n\r\nÎn altă ordine de idei, aceasta este prima finală organizată de infoarena în care membrii mai vechi s-au implicat mai puţin spre deloc. Am dorit să-i lăsam pe cei mai tineri să ia microfonul în mână şi să iasă în faţă. V-aţi descurcat foarte bine! Aţi adus un suflu nou şi lucruri inovatoarea (la vâsle mă refer).\r\n\r\nDin feedback-ul trimis de voi pe \'forum\':http://infoarena.ro/forum/index.php?topic=3897.0 reiese că organizarea a fost bună. Câteva din problemele menţionate pe care vom încerca să le eliminăm pe viitor: evaluarea live nu a meritat aşteptarea de o zi şi putea fi mai spectaculoasă; au fost câteva teste buşite (de obicei nu ni se întamplă, o punem pe seama aglomerării organizatorice).\r\n\r\nAş vrea să remarc performanţa deosebită a lui ==user(user=\"gavrilavlad\")== care a obţinut punctajul maxim în toate probele Algoritmiadei la grupa Gimnaziu. Felicitări Vlad!\r\n\r\nŞi acum publicitate ... :)\r\n\r\nLăsând gluma la o parte, anul acesta infoarena a făcut eforturi financiare şi organizatorice mari pentru a organiza finala în afara Bucureştiului. Am ales Braşov şi am ales bine pentru că acolo ne-am bucurat de sprijinul deosebit generos al liceului \'Colegiul National de Informatica \"Grigore Moisil\"\':http://www.moisilbrasov.ro. TODO: nominalizati directoarea si profesorii care ne-au ajutat si spus cateva vorbe frumoase despre ei.\r\n\r\nMulţumim şi sponsorului Algoritmiadei, \'Adobe România\':http://myadobe.ro/. Este al doilea an consecutiv când Adobe susţine activităţile noastre şi asta ne bucură foarte mult. Adobe a înţeles că ce facem este important pentru viitorul IT-ului din România şi că voi meritaţi să fiţi răsplătiţi şi încurajaţi. Chiar şi pe timp de criză :)\r\n\r\nÎn final vă spun \'unde\':algoritmiada-2009/runda-finala/poze găsiţi pozele de la finală.',15,'private',NULL,NULL),('blog/algoritmiada-2009-final','Algoritmiada 2009 la final','2009-05-26 20:31:32','2009-05-26 21:20:05','!{margin: 0px; margin-left: 0; border: 1px solid gray;}>blog/algoritmiada-2009-final?cetatea.jpg! Iată ca Algoritmiada 2009 a ajuns la final: runda finală a avut loc, o parte din voi a petrecut câteva zile într-un oraş frumos al ţării, premiile au fost confiscate, cetatea a fost cucerită :)\r\n\r\nLa final, aş vrea să ne uităm peste statisticile pentru fiecare rundă. Pe baza lor putem să apreciem dacă Algoritmiada va deveni un concurs mai popular de la an la an.\r\n\r\ntable. |_. &nbsp; |_. Runda 1 |_. Runda 2 |_. Runda 3 |_. Finala |_. Total |\r\n| Câţi concurenţi au trimis soluţii | 223 | 157 | 126 |  97 | 313 |\r\n| Câţi concurenţi s-au inscris | 356 | 232 | 151 | 103 | 508 |\r\n| Surse trimise | 1245 | 894 | 995 | 758 | 3892 |\r\n| Surse cu punctaj pozitiv | 685 | 408 | 561 | 537 | 2191 |\r\n| Concurenţi cu punctaj pozitiv | 162 | 113 | 112 | 92 | 242 |\r\n| Punctaj mediu al concurenţilor care au trimis soluţii | 75.09 | 43.85 | 105.43 | 118.09 | 154.53 |\r\n| Punctaj mediu al concurenţilor cu punctaj > 0 | 103.36 | 60.93 | 118.61 | 124.51 | 199.87 |\r\n\r\nIată că numărul celor care au trimis soluţii a scăzut de la rundă la rundă. Se pare că numai ~125 de concurenţi au fost suficient de motivaţi să ducă maratonul celor 3 runde online până la capăt. Mă întreb care sunt motivele pentru care concurenţii renunţă progresiv. Primul care îmi vine în minte ar fi că pe măsură ce îţi dai seama că nu mai ai sanse de calificare renunţi. Personal dezaprob o astfel de gândire: participi la fiecare concurs ca să înveţi -- faptul că ajungi la finală e un bonus, nu scopul în sine! Excepţie fac studenţii care, probabil, au mai puţin timp să se distreze cu probleme de algoritmică :)\r\n\r\nCâteva cuvinte despre organizarea finalei. Îmi pare rău ca n-am ajuns la finală să joc fotbal. Aş fi vrut să-l văd şi eu evoluând pe atât de lăudatul fotbalist din echipa infoarena. Da ==user(user=\"astronomy\")==, despre tine e vorba :)\r\n\r\nÎn altă ordine de idei, aceasta este prima finală organizată de infoarena în care membrii mai vechi s-au implicat mai puţin spre deloc. Am dorit să-i lăsam pe cei mai tineri să ia microfonul în mână şi să iasă în faţă. V-aţi descurcat foarte bine! Aţi adus un suflu nou şi lucruri inovatoarea (la vâsle mă refer).\r\n\r\nDin feedback-ul trimis de voi pe \'forum\':http://infoarena.ro/forum/index.php?topic=3897.0 reiese că organizarea a fost bună. Câteva din problemele menţionate pe care vom încerca să le eliminăm pe viitor: evaluarea live nu a meritat aşteptarea de o zi şi putea fi mai spectaculoasă; au fost câteva teste buşite (de obicei nu ni se întamplă, o punem pe seama aglomerării organizatorice).\r\n\r\nAş vrea să remarc performanţa deosebită a lui ==user(user=\"gavrilavlad\")== care a obţinut punctajul maxim în toate probele Algoritmiadei la grupa Gimnaziu. Felicitări Vlad!\r\n\r\nŞi acum publicitate ... :)\r\n\r\nLăsând gluma la o parte, anul acesta infoarena a făcut eforturi financiare şi organizatorice mari pentru a organiza finala în afara Bucureştiului. Am ales Braşov şi am ales bine pentru că acolo ne-am bucurat de sprijinul deosebit generos al liceului \'Colegiul National de Informatica \"Grigore Moisil\"\':http://www.moisilbrasov.ro. TODO: nominalizati directoarea si profesorii care ne-au ajutat si spus cateva vorbe frumoase despre ei.\r\n\r\nMulţumim şi sponsorului Algoritmiadei, \'Adobe România\':http://myadobe.ro/. Este al doilea an consecutiv când Adobe susţine activităţile noastre şi asta ne bucură foarte mult. Adobe a înţeles că ce facem este important pentru viitorul IT-ului din România şi că voi meritaţi să fiţi răsplătiţi şi încurajaţi. Chiar şi pe timp de criză :)\r\n\r\nÎn final vă spun \'unde\':algoritmiada-2009/runda-finala/poze găsiţi pozele de la finală.',15,'private',NULL,NULL),('implica-te/scrie-articole','Scrie articole','2007-03-28 22:23:46','2009-04-13 01:22:58','h1. Scrie articole ==Stars(rating=\"4\")==\r\n\r\nFolosind modelul de \'wiki\':documentatie/wiki, infoarena ofera sansa tuturor membrilor sai sa contribuie la realizarea de articole sau la imbunatatirea celor existente. Daca vrei sa afli mai multe despre conceptul de wiki intra \'aici\':http://en.wikipedia.org/wiki/Wiki, iar daca vrei sa contribui la acesta initiativa citeste mai jos ce trebuie sa faci.\r\n\r\nh2. De ce m-as baga?\r\n\r\n* O cariera in cercetare in informatica poate debuta cu niste articole online!\r\n* Vei invata care sunt elementele cheie pentru a scrie un articol.\r\n* Vei invata pe altii ceea ce stii, asa cum probabil si tu ai invatat din articolele deja \'existente\':articole.\r\n\r\nh2. Ce pot sa fac?\r\n\r\nDe-a lungul timpului, utilizatorii infoarena si-au manifestat interesul in a scrie articole pentru intreaga comunitate. In momentul de fata ne concentram eforturile atat pe completarea si aducerea la o forma prezentabila a acestor articole vechi, cat si pe scrierea de articole noi. Sunt 3 moduri in care poti contribui:\r\n\r\nh3. 1. Ajuta-ne la ce lucram acum\r\n\r\nIn tabelul de mai jos poti gasi articolele incepute, impreuna cu stadiul in care se gaseste fiecare. Daca esti dornic sa ne ajuti, alege-ti unul din articolele de care nu se ocupa nimeni si ia legatura cu coordonatorul proiectului ca sa afli ce mai e de facut la el.\r\n\r\ntable. |_. Titlu |_. Autor |_. Stadiu |_. Voluntar(i) |\r\n| \'Flux si cuplaj\':flux-si-cuplaj | ==user(user=\"blasterz\" type=\"tiny\")== | IN LUCRU | ==user(user=\"blasterz\" type=\"tiny\")== |\r\n| \'Teoria jocurilor\':teoria-jocurilor | ==user(user=\"filipb\" type=\"tiny\")== | IN LUCRU | ==user(user=\"filipb\" type=\"tiny\")== |\r\n| \'Psihologia concursurilor de informatica - Lucrul cu numere mari\':lucrul-cu-nr-mari | ==user(user=\"cata00\" type=\"tiny\")== | IMBUNATATIRE CONTINUT | ? |\r\n| Psihologia concursurilor de informatica - Lucrul cu structuri mari de date | ==user(user=\"cata00\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| Psihologia concursurilor de informatica - Probleme de concurs | ==user(user=\"cata00\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Probleme de taietura\':downloads?action=download&file=taietura.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Transformari geometrice\':downloads?action=download&file=transformari_geometrice.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Problema majoritatii votului\':downloads?action=download&file=problema_majoritatii.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n\r\nh3. 2. Preia si dezvolta un subiect mai vechi\r\n\r\nAi nevoie de un impuls pentru a-ti da drumul la scris? Sunt cateva articole pe infoarena incepute, dar abandonate, precum si niste schite. Poti folosi ideile de start ale autorului si il poti transforma intr-un articol bine documentat. In plus, poti lua legatura cu autorul initial si poti afla viziunea sa asupra subiectului. Iata o lista de articole abandonate si de schite:\r\n\r\ntable. |_. Titlu |_. Autor initial |\r\n| Programare dinamica / memoizare (trading space for time): \'link1\':programare-dinamica, \'link2\':pd | ==user(user=\"Zeus\" type=\"tiny\")== |\r\n| \'Arbori indexati binar\':aib | ==user(user=\"Skipy\" type=\"tiny\")== |\r\n| \'Dinic\':dinic | ==user(user=\"alexandru.mosoi\" type=\"tiny\")== |\r\n| \'Probleme de geometrie si solutii\':downloads?geometrie.zip | ==user(user=\"Cosmin\" type=\"tiny\")== |\r\n| \'Diagrame Voronoi\':voronoi | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| \'Algoritmi de baleiere\':algoritmi-de-baleiere | ==user(user=\"stef2n\" type=\"tiny\")== |\r\n\r\nh3. 3. Creeaza ceva nou\r\n\r\nAi o idee noua de articol? Sau pur si simplu vrei sa te apuci de la 0 de un subiect? Ia legatura cu coordonatorul proiectului sau anunta pe \'forum\':forum. Este posibil sa primesti ajutor si de la alti utilizatori infoarena. In plus, noi iti propunem o lista de articole pe care ni le-am dori scrise, in caz ca nu te-ai decis asupra temei:\r\n\r\ntable. |_. Titlu |\r\n| Depanarea programelor C/C++ cu gdb in Linux |\r\n| Testarea surselor in timp de concurs sau Cum sa reduci buselile |\r\n| Tutorial LaTeX |\r\n\r\nNe rezervam dreptul sa nu acceptam sau sa stergem articolele care nu se potrivesc cu tema si target-ul site-ului.\r\n\r\nh2. Cu cine iau legatura?\r\n\r\nCu coordonatorul proiectului:\r\n\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n\r\nSau daca vrei sa contribui la un articol la care se lucreaza deja, poti vorbi direct cu voluntarii care se ocupa de el.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"43\")==\r\n\r\n*TODO*\r\n\r\ntable. |_. Subiect |_. Voluntar(i) |_. Progres |\r\n| Notiuni de geometrie analitica si aplicatii | ==user(user=\"devilkind\" type=\"tiny\")== \r\n==user(user=\"sima_cotizo\" type=\"tiny\")== | \'50%\':notiuni-de-geometrie-si-aplicatii |',3146,'public',NULL,NULL),('ccex2009','Concursul Centrelor de Excelenta','2009-05-31 10:24:55','2009-05-31 10:24:55','==Include(page=\"template/grigore-moisil-2008\")==\r\n\r\nh1. Concursul Centrelor de Excelenta 2009\r\n\r\n(htabs)*(active) \'Despre concurs\':ccex2009\r\n* \'Clasament\':ccex2009/clasament/9\r\n',256,'protected',NULL,NULL),('ccex2009','Concursul Centrelor de Excelenta','2009-05-31 10:24:55','2009-05-31 10:28:34','==Include(page=\"template/ccex2009\")==\r\n\r\nh1. Concursul Centrelor de Excelenta 2009\r\n\r\n(htabs)*(active) \'Despre concurs\':ccex2009\r\n* \'Clasament\':ccex2009/clasament/9\r\n',256,'protected',NULL,NULL),('ccex2009','Concursul Centrelor de Excelenta','2009-05-31 10:24:55','2009-05-31 10:58:50','\r\n!> ccex2009?ccex.jpg 50%!:/ccex2009\r\n\r\nh1. Concursul Centrelor de Excelenta 2009\r\n\r\n(htabs)*(active) \'Despre concurs\':ccex2009\r\n* \'Clasa a 9-a\':ccex2009/9\r\n* \'Clasa a 10-a\':ccex2009/10\r\n* \'Clasele 11-12\':ccex2009/11-12\r\n* \'Clasament\':ccex2009/clasament/9\r\n\r\n\'*infoarena*\':/, impreuna cu Inspectoratul Scolar Judetean Suceava, organizeaza pe data de 6 iunie concursul interjudetean al Centrelor de Excelenta. La concurs participa elevi de gimnaziu si de liceu din mai multe judete. Concursul online va fi disponibil doar pentru clasele 9-12.\r\n\r\nAstfel vei avea ocazia sa iti masori fortele cu cei care participa live la concurs. Vor exista $5$ grupe de varsta: clasele {$5-6$}, clasele {$7-8$}, clasa a {$9$}-a, clasa a {$10$}-a si respectiv clasele {$11-12$}.\r\n\r\nConcursul se va desfasura *Sambata, 6 iunie*, la ora {*10^00^*} si va dura *3h*.\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* inspector de specialitate Giorgie Vlad\r\n* ==User(user=\"amadaeus\" type=\"tiny\")==\r\n* ?\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"filipb\" type=\"tiny\")==\r\n* ==User(user=\"Marius\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\nh2. Cum particip?\r\n\r\nInainte de toate trebuie sa \'te inregistrezi\':register pe site-ul nostru!\r\n\r\nOricine este invitat sa participe. In ziua de concurs intri pe site, citesti problemele, le rezolvi si trimiti solutiile inainte de expirarea timpului de lucru. La sfarsitul rundei, \'evaluatorul\':documentatie/evaluator infoarena iti va testa solutiile pentru corectitudine. Clasamentul se va actualiza in timp real pe parcursul evaluarii.\r\n\r\nh2. Prima data pe _infoarena_?\r\n\r\n\'infoarena\':/ ajuta elevi si studenti sa devina excelenti in informatica! Gratuit ;) \'Citeste mai multe\':despre-infoarena despre noi si vezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n',256,'protected',NULL,NULL),('ccex2009/9','Concursul Centrelor de Excelenta, clasa a 9a','2009-05-31 11:04:03','2009-05-31 11:04:03','h1. Concursul Centrelor de Excelenta 2009\r\n\r\n!> ccex2009?ccex.jpg 50%!:/ccex2009\r\n\r\n(htabs)*(active) \'Despre concurs\':ccex2009\r\n* \'Clasa a 9-a\':ccex2009/9\r\n* \'Clasa a 10-a\':ccex2009/10\r\n* \'Clasele 11-12\':ccex2009/11-12\r\n* \'Clasament\':ccex2009/clasament/9\r\n\r\nh2. Clasa a 9-a\r\n\r\nConcursul se va desfasura *Sambata, 6 iunie*, incepand cu ora {*10^00^*} si va dura *3h*. Participantii vor avea de rezolvat doua probleme de natura algoritmica.\r\n',256,'protected',NULL,NULL),('ccex2009/clasament/11-12','Concursul Centrelor de Excelenta, clasament 11-12','2009-05-31 11:50:25','2009-05-31 11:50:25','&nbsp;\r\n\r\nh1. Concursul Centrelor de Excelenta 2009\r\n\r\n!> ccex2009?ccex.jpg 50%!:/ccex2009\r\n\r\n(htabs)* \'Despre concurs\':ccex2009\r\n* \'Clasa a 9-a\':ccex2009/9\r\n* \'Clasa a 10-a\':ccex2009/10\r\n* \'Clasele 11-12\':ccex2009/11-12\r\n*(active) \'Clasament\':ccex2009/clasament\r\n\r\n&nbsp;\r\n&nbsp;\r\n\r\n(htabs)* \'Clasa a 9-a\':ccex2009/clasament\r\n* \'Clasa a 10-a\':ccex2009/clasament/10\r\n*(active) \'Clasele 11-12\':ccex2009/clasament/11-12\r\n\r\np<. == Rankings(rounds=\"ccex2009-11-12k\") == \r\n',256,'protected',NULL,NULL),('echipa-infoarena','Echipa infoarena','2006-11-27 08:20:21','2008-12-04 20:00:50','h1. Echipa infoarena\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nMembrii echipei infoarena s-au remarcat prin activitate sustinuta in cadrul proiectelor infoarena. Acestia detin functii oficiale in \'Asociatia infoarena\':asociatia-infoarena. Echipa infoarena este responsabila de dezvoltarea si intretinerea site-ului infoarena precum si de desfasurarea altor proiecte ale Asociatiei. Coordonarea eforturilor echipei se face pe pagina de \'planificare\':planificare.\r\n\r\nEchipa infoarena se bucura de \'*sprijinul a zeci de voluntari*\':implica-te. O buna parte din continutul infoarena este rezultatul muncii lor. Suntem onorati sa primim ajutorul lor si le multumim sincer pentru efortul pe care l-au depus!\r\n\r\n\r\nh2. Membri fondatori\r\n\r\ntable(layout).\r\n|* ==user(user=\"wickedman\" type=\"normal\")==  \r\n* ==user(user=\"silviug\" type=\"normal\")== \r\n|* ==user(user=\"domino\" type=\"normal\")==\r\n* ==user(user=\"fluffy\" type=\"normal\")==|\r\n\r\nh2. Consilieri\r\n\r\ntable(layout).\r\n|* ==user(user=\"ditzoneC\" type=\"normal\")==\r\n* ==user(user=\"filipb\" type=\"normal\")== \r\n* ==user(user=\"danielp\" type=\"normal\")==\r\n* ==user(user=\"Cosmin\" type=\"normal\")== \r\n* ==user(user=\"svalentin\" type=\"normal\")==  \r\n* ==user(user=\"astronomy\" type=\"normal\")==\r\n* ==user(user=\"wefgef\" type=\"normal\")==\r\n|* ==user(user=\"alexthero\" type=\"normal\")== \r\n* ==user(user=\"gcosmin\" type=\"normal\")== \r\n* ==user(user=\"bogdan2412\" type=\"normal\")== \r\n* ==user(user=\"pauldb\" type=\"normal\")== \r\n* ==user(user=\"Prostu\" type=\"normal\")== \r\n* ==user(user=\"stef2n\" type=\"normal\")== \r\n* ==user(user=\"victorsb\" type=\"normal\")==| \r\n\r\nh2. Consilieri emeritus\r\n\r\n* ==user(user=\"azotlichid\" type=\"normal\")==\r\n* ==user(user=\"greco\" type=\"normal\")==\r\n',15,'protected',NULL,NULL),('ccex2009/11-12','Concursul Centrelor de Excelenta, clasele 11-12','2009-05-31 11:15:51','2009-05-31 11:57:39','&nbsp;\r\n\r\nh1. Concursul Centrelor de Excelenta 2009\r\n\r\n!> ccex2009?ccex.jpg 50%!:/ccex2009\r\n\r\n(htabs)* \'Despre concurs\':ccex2009\r\n* \'Clasa a 9-a\':ccex2009/9\r\n* \'Clasa a 10-a\':ccex2009/10\r\n*(active) \'Clasele 11-12\':ccex2009/11-12\r\n* \'Clasament\':ccex2009/clasament\r\n\r\nh2. Clasele 11-12\r\n\r\n== roundregister(round_id=\"ccex2009-11-12\") ==\r\n\r\nConcursul se va desfasura *Sambata, 6 iunie*, incepand cu ora {*10^00^*} si va dura *3h*. Participantii vor avea de rezolvat doua probleme de natura algoritmica.\r\n\r\nConcursul incepe ==roundparam(round_id=\"ccex2009-11-12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ccex2009-11-12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':ccex2009/clasament/11-12.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\nh2. Clasament\r\n\r\n\'Evaluatorul\':documentatie/evaluator va fi oprit pe toata perioada desfasurarii concursului. Dupa terminarea rundei de concurs va incepe evaluarea in timp real. Rezultatele finale le puteti gasi \'aici\':ccex2009/clasament/11-12.',256,'protected',NULL,NULL),('ccex2009/9','Concursul Centrelor de Excelenta, clasa a 9a','2009-05-31 11:04:03','2009-06-03 21:01:02','&nbsp;\r\n\r\nh1. Concursul Centrelor de Excelenta 2009\r\n\r\n!> ccex2009?ccex.jpg 50%!:/ccex2009\r\n\r\n(htabs)* \'Despre concurs\':ccex2009\r\n*(active) \'Clasa a 9-a\':ccex2009/9\r\n* \'Clasa a 10-a\':ccex2009/10\r\n* \'Clasele 11-12\':ccex2009/11-12\r\n* \'Clasament\':ccex2009/clasament\r\n\r\nh2. Clasa a 9-a\r\n\r\n== roundregister(round_id=\"ccex2009-9\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"ccex2009-9\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"ccex2009-9\" param=\"duration\" strong=\"true\")== ore. Participantii vor avea de rezolvat doua probleme de natura algoritmica.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':ccex2009/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\nh2. Clasament\r\n\r\n\'Evaluatorul\':documentatie/evaluator va fi oprit pe toata perioada desfasurarii concursului. Dupa terminarea rundei de concurs va incepe evaluarea in timp real. Rezultatele finale le puteti gasi \'aici\':ccex2009/clasament.\r\n',3146,'protected',NULL,NULL),('ccex2009','Concursul Centrelor de Excelență','2009-05-31 10:24:55','2009-06-04 10:54:01','&nbsp;\r\n\r\nh1. Concursul Centrelor de Excelenta 2009\r\n\r\n(htabs)*(active) \'Despre concurs\':ccex2009\r\n* \'Clasa a 9-a\':ccex2009/9\r\n* \'Clasa a 10-a\':ccex2009/10\r\n* \'Clasele 11-12\':ccex2009/11-12\r\n* \'Clasament\':ccex2009/clasament\r\n\r\n!> ccex2009?logo.png 35%!:/ccex2009\r\n\'*infoarena*\':/, împreună cu Inspectoratul Şcolar Judeţean Suceava, organizează pe data de $6$ iunie _concursul interjudeţean al Centrelor de Excelenţă_. La concurs vor participa elevi de gimnaziu şi de liceu din mai multe judeţe. Concursul online va fi disponibil doar pentru clasele $9-12$.\r\n\r\nConcurenţii care vor participa live la Suceava vor fi evaluaţi de evaluatorul infoarena. Astfel, toţi ceilalţi concurenţi vor avea ocazia să îşi măsoare forţele cu aceştia, la oricare din cele $3$ grupe de vârstă: \'clasa a {$9$}-a\':ccex2009/9, \'clasa a {$10$}-a\':ccex2009/10 şi, respectiv, \'clasele {$11-12$}\':ccex2009/11-12. %{color:red}In plus, concurentii care vor participa on-line si se vor clasa in primele 3 locuri la fiecare grupa de varsta, vor primi din partea organizatorilor diplome si tricouri.%\r\n\r\nConcursul se va desfăşura *Sâmbătă, 6 iunie*, la ora {*9^00^*} şi va dura *4h*.\r\n\r\nPagina oficiala a concursului se gaseste \'*aici*\':http://ccex.infosv.ro/index.php.\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse şi pregătite de:\r\n\r\n* inspector de specialitate Giorgie Vlad\r\n* prof. Petronela Aga\r\n* prof. Gabriela Coaja\r\n* prof. Antoneta Lazarescu\r\n* prof. Ovidiu Marcu\r\n* lector dr. ing. Radu-Daniel Vatavu\r\n* ==User(user=\"filipb\" type=\"tiny\")==\r\n* ==User(user=\"amadaeus\" type=\"tiny\")==\r\n\r\nPentru întrebări de factură organizatorică / tehnică poţi contacta următoarele persoane:\r\n\r\n* ==User(user=\"filipb\" type=\"tiny\")==\r\n* ==User(user=\"Marius\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* îţi urează mult succes!\r\n\r\nh2. Cum particip?\r\n\r\nÎnainte de toate trebuie să \'te înregistrezi\':register pe site-ul nostru!\r\n\r\nOricine este invitat să participe. În ziua de concurs intri pe site, citeşti problemele, le rezolvi, şi trimiţi soluţiile înainte de expirarea timpului de lucru. La sfârşitul rundei, \'evaluatorul\':documentatie/evaluator infoarena îţi va testa soluţiile pentru corectitudine. Clasamentul se va actualiza în timp real pe parcursul evaluării.\r\n\r\nh2. Prima dată pe _infoarena_?\r\n\r\n\'infoarena\':/ ajută elevi şi studenţi să devină excelenţi în informatică! Gratuit ;) \'Citeşte mai multe\':despre-infoarena despre noi şi vezi \'ghidul utilizatorului\':documentatie/pentru-utilizatori.\r\n',256,'protected',NULL,NULL),('blog/algoritmiada-2009-final','Algoritmiada 2009 la final','2009-05-26 20:31:32','2009-05-27 11:43:24','!{margin: 0px; margin-left: 0; border: 1px solid gray;}>blog/algoritmiada-2009-final?cetatea.jpg! Iată ca Algoritmiada 2009 a ajuns la final: runda finală a avut loc, o parte din voi a petrecut câteva zile într-un oraş frumos al ţării, premiile au fost confiscate, cetatea a fost cucerită ->\r\n\r\nLa final, aş vrea să ne uităm peste statisticile pentru fiecare rundă. Pe baza lor putem să apreciem dacă Algoritmiada va deveni un concurs mai popular de la an la an.\r\n\r\ntable. |_. &nbsp; |_. Runda 1 |_. Runda 2 |_. Runda 3 |_. Finala |_. Total |\r\n| Câţi concurenţi au trimis soluţii | 223 | 157 | 126 |  97 | 313 |\r\n| Câţi concurenţi s-au inscris | 356 | 232 | 151 | 103 | 508 |\r\n| Surse trimise | 1245 | 894 | 995 | 758 | 3892 |\r\n| Surse cu punctaj pozitiv | 685 | 408 | 561 | 537 | 2191 |\r\n| Concurenţi cu punctaj pozitiv | 162 | 113 | 112 | 92 | 242 |\r\n| Punctaj mediu al concurenţilor care au trimis soluţii | 75.09 | 43.85 | 105.43 | 118.09 | 154.53 |\r\n| Punctaj mediu al concurenţilor cu punctaj > 0 | 103.36 | 60.93 | 118.61 | 124.51 | 199.87 |\r\n\r\nIată că numărul celor care au trimis soluţii a scăzut de la rundă la rundă. Mă întreb care sunt motivele pentru care concurenţii renunţă progresiv. Primul care îmi vine în minte ar fi că pe măsură ce îţi dai seama că nu mai ai sanse de calificare renunţi. Personal dezaprob o astfel de gândire: participi la fiecare concurs ca să înveţi -- faptul că ajungi la finală e un bonus, nu scopul în sine! Excepţie fac studenţii care, probabil, au mai puţin timp să se distreze cu probleme de algoritmică.\r\n\r\nCâteva cuvinte despre organizarea finalei. Îmi pare rău ca n-am ajuns la finală să joc fotbal. Aş fi vrut să-l văd şi eu evoluând pe atât de lăudatul fotbalist din echipa infoarena. Da ==user(user=\"astronomy\")==, despre tine e vorba.\r\n\r\nÎn altă ordine de idei, aceasta este prima finală organizată de infoarena în care membrii mai vechi s-au implicat mai puţin spre deloc. Am dorit să-i lăsam pe cei mai tineri să ia microfonul în mână şi să iasă în faţă. V-aţi descurcat foarte bine! Aţi adus un suflu nou şi lucruri inovatoare (la vâsle mă refer).\r\n\r\nDin feedback-ul trimis de voi pe \'forum\':http://infoarena.ro/forum/index.php?topic=3897.0 reiese că organizarea a fost bună. Câteva din problemele menţionate pe care vom încerca să le eliminăm pe viitor: evaluarea live nu a meritat aşteptarea de o zi şi putea fi mai spectaculoasă; au fost câteva teste buşite (de obicei nu ni se întamplă, o punem pe seama aglomerării organizatorice).\r\n\r\nAş vrea să remarc performanţa deosebită a lui ==user(user=\"gavrilavlad\")== care a obţinut punctajul maxim în toate probele Algoritmiadei la grupa Gimnaziu. Felicitări Vlad!\r\n\r\nŞi acum publicitate ... :)\r\n\r\nLăsând gluma la o parte, anul acesta infoarena a făcut eforturi financiare şi organizatorice mari pentru a organiza finala în afara Bucureştiului. Am ales Braşov şi am ales bine pentru că acolo ne-am bucurat de sprijinul deosebit generos al liceului \'Colegiul National de Informatica \"Grigore Moisil\"\':http://www.moisilbrasov.ro. TODO: nominalizati directoarea si profesorii care ne-au ajutat si spus cateva vorbe frumoase despre ei.\r\n\r\nMulţumim şi sponsorului Algoritmiadei, \'Adobe România\':http://myadobe.ro/. Este al doilea an consecutiv când Adobe susţine activităţile noastre şi asta ne bucură foarte mult. Adobe a înţeles că ce facem este important pentru viitorul IT-ului din România şi că voi meritaţi să fiţi răsplătiţi şi încurajaţi. Chiar şi pe timp de criză.\r\n\r\nÎn final vă spun \'unde\':algoritmiada-2009/runda-finala/poze găsiţi pozele de la finală.',15,'private',NULL,NULL),('home','infoarena -  comunitate informatica, concursuri de programare','2006-11-05 14:45:56','2009-06-04 10:44:46','h1. Bine ai venit pe infoarena!\r\n\r\nSuntem o comunitate de tineri pasionati de informatica si programare.\r\nInvatam impreuna participand la concursuri online de programare, citind stiri si articole despre informatica sau discutand pe forum.\r\n\r\n\'*&raquo; Afla mai multe despre noi!*\':despre-infoarena\r\n\r\ntable{width:99%; margin:auto}. |={background-color: rgb(210, 244, 219); border: 0; padding: 0.3em; -moz-border-radius:7px; -webkit-border-radius:7px}. Inscrie-te si participa la \'*Concursul Centrelor de Excelenta*\':ccex2009. Poti castiga diplome si tricouri!|\r\n\r\nh1. Ultimele insemnari de pe \'blog\':blog \'!{vertical-align:middle}home?rss_icon.jpg!\':blog?action=rss\r\n\r\n==BlogPreview(display_entries=\"10\")==\r\n',256,'protected',NULL,NULL),('utilizator/mathboy','Rotaru Dragos Alin','2008-12-24 18:43:37','2009-06-07 09:26:27','h2. Despre mine\r\n\r\n* Fac informatica {**serios**} din clasa a 9-A.\r\n* Elev in clasa a IX-a D,Matematica-Informatica,Informatica Intensiv la Colegiul National Unirea Focsani\r\n* Contact: dragos_mathboy@yahoo.com\r\n\r\nh2. Distinctii primite\r\n\r\nPremiul III OJI 2009 Focsani clasa a 9-a\r\n\r\nh2. Prieteni de prin toate taramurile :)\r\n\r\n* ==user(user=\"Florian\" type=\"tiny\")==\r\n* ==user(user=\"klamathix\" type=\"tiny\")==\r\n* ==user(user=\"DraStiK\" type=\"tiny\")==\r\n* ==user(user=\"cosmin79\" type=\"tiny\")==\r\n* ==user(user=\"ssergiuss\" type=\"tiny\")==\r\n* ==user(user=\"andrici_cezar\" type=\"tiny\")== \r\n* ==user(user=\"CezarMocan\" type=\"tiny\")==\r\n* ==user(user=\"drag0s93\" type=\"tiny\")==\r\n* ==user(user=\"toni2007\" type=\"tiny\")==\r\n\r\nh2. Colegi de liceu\r\n\r\n* ==user(user=\"bogdanhm999\" type=\"tiny\")==\r\n* ==user(user=\"lucianvn\" type=\"tiny\")==\r\n* ==user(user=\"bolovanemil\" type=\"tiny\")==\r\n* ==user(user=\"drag0sh\" type=\"tiny\")==\r\n* ==user(user=\"Omega91\" type=\"tiny\")==\r\n* ==user(user=\"razvan_3\" type=\"tiny\")==',9232,'public',NULL,NULL),('grigore-moisil-2008/solutii/online','grigore-moisil-2008/solutii/online','2008-04-06 07:27:39','2008-04-06 13:28:07','h2(#online). \'Online\':problema/online\r\n\r\nProblema cere costul arborelui partial de cost minim, graful initial schimbandu-se la fiecare pas. Prima idee ar fi rularea unui algoritm clasic pentru gasirea arborelui partial de cost minim de $K + 1$ ori. In functie de algoritmul folosit si de metoda de implementare, obtinem complexitati diferite. Folosind algoritmul Kruskal putem obtine complexitati de $O(K * N * M)$, $O(K * (M * log M + N^2^))$ sau $O(K * M * log M)$. Folosind algoritmul Prim putem obtine complexitatea $O(K * N^2^)$, sau $O(K * M * log N)$ in cazul folosirii heap-urilor la implementare.\r\nTotusi niciuna dintre aceste variante nu se incadreaza in timp pentru limitele date, asa ca propunem urmatorul algoritm, avand complexitatea $O(N^2^ + K * N)$. Prima data se gaseste arborele partial de cost minim pentru graful initial, folosind algoritmul Prim. Pentru urmatorii $K$ pasi avem doua posibilitati:\r\n\r\n# Muchia curenta este intre doua noduri din arborele partial minim actual. Daca muchia are lungime mai mica, suprascriem muchia din arbore si costul arborelui se imbunatateste cu diferenta costurilor. Daca muchia are lungime mai mare sau egala, arborele ramane neschimbat.\r\n# Muchia nu face parte din arbore. Fiindca arborele are numar maxim de muchii din punctul de vedere al aciclitatii, o noua muchie va forma cu siguranta un ciclu. Pentru a ajunge iarasi la un arbore, din acest ciclu trebuie sters o muchie. Pentru ca arborele care rezulta sa aiba cost minim, vom sterge muchia cu cost maxim din ciclu.\r\n',2028,'public',NULL,NULL),('utilizator/silviug','Profil silviug','2006-11-24 20:56:12','2008-12-27 21:02:33','h2. Despre mine\r\n\r\n* Membru fondator si vicepresedinte al Asociatiei infoarena\r\n* Omul zilei, 20 septembrie 2004, Jurnalul National\r\n* Stagii:\r\n## Google, Mountain View, summer 2006\r\n## Google, Zurich, summer 2007\r\n## \'EPFL\':http://www.epfl.ch/, Lausanne, summer 2008\r\n* Am invatat 80% din informatica pe care o stiu in ultimii doi ani de liceu\r\n* De cativa ani buni sunt trainer al echipei de informatica ICHB\r\n* Student anul V la facultatea de Automatica si Calculatoare, Universitatea Politehnica Bucuresti\r\n\r\nh2. Frânturi de trecut\r\n\r\n* Am pus mana pe calculator abia in clasa a 9-a, in prima ora de informatica. Desi ora a fost traumatizanta fiindca nu stiam ce sa fac cu dihania din fata mea, pe parcursul anului am dezvoltat o pasiune pentru informatica.\r\n* Doua episoade marcante din evolutia mea ca informatician:\r\n## Intr-o noapte de prin clasa a 10-a faceam probleme pe foaie din Ginfo (nu aveam calculator acasa) si s-a intrerupt curentul electric. Totusi, am continuat sa ma bat cu problemele multe ore in sir la lumina lumanarii.\r\n## In vacanta de iarna din clasa a 10-a, fiindca nu aveam un calculator personal, doamna profesoara Gheorghian mi-a dat acasa un calculator al scolii. Am muncit foarte foarte mult in acea vacanta. Reflectati un pic la posibilitatile pe care le aveti voi... Ce mai stati?\r\n* Primul calculator personal mi l-au luat parintii mei spre sfarsitul clasei a 10-a, dupa ce am luat locul 1 la Olimpiada Judeteana de Matematica si m-am calificat la Nationala.\r\n* Dupa cum v-ati dat seama, mai intai am fost olimpic la mate dar spre sfarsitul liceului impuscam puncte la olimpiadele de informatica.\r\n* In clasa a 11-a am fost coleg de banca cu \"Wickedman\":utilizator/wickedman. Valorificam orele plictisitoare rezolvand probleme de informatica.\r\n\r\n\r\nh2. Distinctii primite (cele mai importante)\r\n\r\n* 2 x locul 2 - Axway-Eestec Olympic 2006 (concursuri maraton de 24 de ore in echipe de 3).\r\n* Finalist Google Code Jam, Mountain View 2005.\r\n* Medalie de Aur, Olimpiada Internationala de Informatica, Atena 2004.\r\n* Medalie de Bronz, Olimpiada Balcaniada de Informatica, Plovdiv 2004.\r\n* Locul I, Olimpiada Nationala de Informatica, Focsani 2003.\r\n* Mentiune, Olimpiada Nationala de Matematica, Ramnicu Valcea 2002 (asta e distictia cea mai importanta obtinuta ca matematician).',15,'protected',NULL,NULL),('utilizator/mathboy','Rotaru Dragos Alin','2008-12-24 18:43:37','2009-06-13 19:36:07','h2. Despre mine\r\n\r\n* Fac informatica {**serios**} din clasa a 9-A.\r\n* Elev in clasa a IX-a D,Matematica-Informatica,Informatica Intensiv la Colegiul National Unirea Focsani\r\n* Contact: dragos_mathboy@yahoo.com\r\n\r\nh2. Distinctii primite\r\n\r\nerror:!declared,must wait until X class\r\n\r\nh2. Prieteni de prin toate taramurile :)\r\n\r\n* ==user(user=\"Florian\" type=\"tiny\")==\r\n* ==user(user=\"klamathix\" type=\"tiny\")==\r\n* ==user(user=\"DraStiK\" type=\"tiny\")==\r\n* ==user(user=\"cosmin79\" type=\"tiny\")==\r\n* ==user(user=\"ssergiuss\" type=\"tiny\")==\r\n* ==user(user=\"andrici_cezar\" type=\"tiny\")== \r\n* ==user(user=\"CezarMocan\" type=\"tiny\")==\r\n* ==user(user=\"drag0s93\" type=\"tiny\")==\r\n* ==user(user=\"toni2007\" type=\"tiny\")==\r\n\r\nh2. Colegi de liceu\r\n\r\n* ==user(user=\"Omega91\" type=\"tiny\")==\r\n* ==user(user=\"bogdanhm999\" type=\"tiny\")==\r\n* ==user(user=\"lucianvn\" type=\"tiny\")==\r\n* ==user(user=\"drag0sh\" type=\"tiny\")==\r\n* ==user(user=\"razvan_3\" type=\"tiny\")==\r\n* ==user(user=\"bolovanemil\" type=\"tiny\")==',9232,'public',NULL,NULL),('codeblocks','Scurt ghid pentru folosirea mediului Code::Blocks','2009-08-23 15:23:46','2009-08-23 16:41:57','h1. Scurt ghid pentru folosirea mediului Code::Blocks\r\n\r\nh2. Configurarea tastaturii\r\n\r\nUna dintre facilitatile care ne pot simplifica mult activitatea in Code::Blocks este posibilitea de configurare a tastaturii, incat sa realizam simplu actiunile cele mai frecvente.\r\nAstfel, daca suntem obisnuiti cu Visual Studio sau Borland C++, putem sa avem la dispozitie in Code::Blocks combinatiile de taste preferate.\r\nVom vedea, de exemplu, cum putem sa stabilim o scurtatura pentru a deschide usor fereastra de editare a expresiilor care vor fi urmarite la depanere.\r\n\r\n# Alegem: Settings -> Editor ...\r\n# In lista din stanga alegem **Keyboard shortcuts**.\r\n# In zona **Commands** deschidem **Debug** si alegem **Edit watches...**\r\n# In casuta **New shortcut** tastam F10 (desigur, putem tasta orice dorim).\r\n# Click pe **Add** si pe **OK**.\r\n\r\n!codeblocks?KeyboardShortcuts.png!\r\n\r\nFolosind aceasta fereastra am configurat pentru exemplificare cateva scurtaturi, asemanatoare cu cele din Borland C++:\r\n\r\n| F2 | salvarea sursei din fereastra curenta |\r\n| Ctrl+Y | stergerea liniei curente |\r\n| F9 | Build |\r\n| Ctrl+F9 | Run |\r\n| Ctrl+F8 | setarea/eliminarea unui breakpoint |\r\n| Alt+W | Watches |\r\n| Ctrl+F2 | Stop debugger |\r\n\r\nDaca deschidem un meniu pentru care am stabilit scurtaturi, vom observa ca langa numele comenzilor apar noile combinatii de taste.\r\n\r\n!codeblocks?Keys.png!\r\n\r\nCombinatiile de taste stabilite asa cum am aratat mai sus vor fi salvate automat in fisierul\r\nC:\\Documents and Settings\\**[user curent]**\\Application Data\\codeblocks\\cbKeyBinder10.ini\r\n(Adaptati calea instalarii de Windows pe care o aveti.)\r\n\r\nAm atasat \"aici\":cbKeyBinder10 fisierul care contine scurtarile descrise in tabel, pe care il puteti pune in locul fisierului creat implicit la instalarea Code::Blocks.\r\n[cbKeyBinder10]http://infoarena.ro/codeblocks?action=download&file=cbKeyBinder10.txt&safe_only=true',3689,'public',NULL,NULL),('transformari-geometrice','transformari-geometrice','2009-04-12 08:01:38','2009-04-23 22:53:50','h1. Transformări geometrice\r\n\r\n(Categoria _Matematică_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'_Introducere_\':transformari-geometrice#introducere\r\n** \'Translaţia\':transformari-geometrice#translatia\r\n** \'Simetria\':transformari-geometrice#simetria\r\n** \'Rotaţia\':transformari-geometrice#rotatia\r\n** \'Omotetia\':transformari-geometrice#omotetia\r\n** \'Desfăşurarea în plan\':transformari-geometrice#desfasurarea-in-plan\r\n* \'Aplicaţia 1\':transformari-geometrice#aplicatia-1\r\n* \'Aplicaţia 2\':transformari-geometrice#aplicatia-2\r\n* \'Aplicaţia 3\':transformari-geometrice#aplicatia-3\r\n* \'Aplicaţia 4: PolyLine &#40;TopCoder&#41;\':transformari-geometrice#aplicatia-4\r\n* \'Aplicaţia 5 &#40;Olimpiada Letonă, 1997&#41;\':transformari-geometrice#aplicatia-5\r\n\r\nh2(#introducere). Introducere\r\n\r\nÎn acest articol vom introduce câteva noţuni legate de transformările geometrice care se pot dovedi utile în concursurile de programare.\r\n\r\nÎnainte de toate prezentăm câteva aspecte teoretice, o mare parte din ele nefiind foarte interesante şi probabil sunt conţinute şi în manualele de liceu. Cititorul poate trece direct la probleme şi, în măsura în care noţiunile din soluţii îi sunt neclare, poate reveni asupra părţii teoretice.\r\n\r\nh3(#translatia). Translaţia\r\n\r\nTranslaţia unei figuri geometrice reprezintă mişcarea tuturor componentelor ei pe o anumita distanţă si direcţie. Această transformare poate fi uşor caracterizată de un vector $v = (dx, dy)$. Când vrem să translatăm un punct $P(x, y)$ după $v$, e de ajuns să facem operaţia $P’ = P + v$. Astfel, $P’$ are cooronatele $(x + dx, y + dy)$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* pastrează orientarea poligoanelor (adică, dacă vârfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi şi ele în ordine trigonometrică);\r\n* păstrează unghiurile;\r\n* o dreaptă va fi transformată în altă dreaptă paralelă cu prima;\r\n* înafară de translaţia trivială de vector $v = (0, 0)$, această transformare nu are puncte fixe (adică orice punct va fi transformat într-un punct diferit);\r\n* translaţii successive vor rezulta tot într-o translaţie (adică, dacă vrem să translatăm un punct dupa $v$ şi apoi după $v{~1~}$, atunci obţinem acelaşi rezultat dacă translatăm direct după $v + v{~1~}$);\r\n* translaţia este comutativă;\r\n\r\nh3(#simetria). Simetria\r\n\r\nExistă două tipuri de simetrii: simetria faţă de un punct şi simetria faţa de o dreaptă.\r\n\r\nUn punct $A$ îl are simetric pe $A’$ faţă de un punct $O$, dacă segmentul $AA’$ are ca mijloc punctul $O$. Dacă avem un punct $(x{~0~}, y{~0~})$ căruia vrem să îi aflăm simetricul faţă de un punct de coordonate $(x, y)$ atunci acesta va fi $(2x – x{~0~}, 2y – y{~0~})$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* păstrează orientarea poligoanelor (adică, dacă varfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi şi ele în ordine trigonometrică);\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* are ca punct fix punctul $O$, iar drepte fixe cele care trec prin punctul $O$;\r\n* simetrii succesive după centre diferite $O{~1~}(x{~1~}, y{~1~}) O{~2~}(x{~2~}, y{~2~})$ sunt o translaţie de vector $v = 2(x{~2~} – x{~1~})$;\r\n* simetriile după un punct nu comută;\r\n\r\nSă calculăm simetricul unui punct $P(x{~0~}, y{~0~})$ faţă de o dreaptă de ecuaţie $ax + by + c = 0$. Notăm cu $d$ distanţa de la punctul $P$ la dreaptă, <tex> d = \\displaystyle\\frac{|a*x_{0} + b*y_{0} + c|}{\\sqrt{a^2 + b^2}} </tex>, şi cu $(m{~1~}, m{~2~})$ cosinii directori ai vectorului $n(a, b)$ normal la dreaptă. Valorile cosinilor directori sunt: <tex> m_{1} = \\displaystyle \\pm \\frac{a}{\\sqrt{a^2 + b^2}} </tex> şi <tex> m_{2} = \\displaystyle \\pm \\frac{b}{\\sqrt{a^2 + b^2}} </tex>. Vom alege semnul minus dacă $ax{~0~} + by{~0~} + c > 0$ iar semnul plus dacă $ax{~0~} + by{~0~} + c < 0$. Astfel, simetricul punctului $P$ va avea coordonatele $(x{~0~} + 2*d*m{~1~}, y{~0~} + 2*d*m{~2~})$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* nu păstrează orientarea poligoanelor (adică, dacă varfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi în sens orar);\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* are ca puncte fixe dreapta de simetrie;\r\n* simetrii succesive după drepte paralele sunt o translaţie;\r\n* simetrii succesive după drepte concurente sunt rotaţii;\r\n* simetriile nu comută;\r\n\r\nh3(#rotatia). Rotaţia\r\n\r\nAceasta este o transformare care roteşte punctele în sens trigonometric în jurul unui punct numit centru de rotaţie după un unghi fixat numit unghi de rotaţie. Dacă avem rotaţia de centru $O(x{~0~}, y{~0~})$ şi unghi $alfa$, atunci imaginea unui punct $P(x, y)$ va fi $P’(x{~0~} + (x – x{~0~}) * cos(alfa)  - (y – y{~0~}) * sin(alfa), y{~0~} + (x – x{~0~}) * sin(alfa)  + (y – y{~0~}) * cos(alfa))$.\r\n \r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* păstrează orientarea poligoanelor;\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* dacă nu este o rotaţie trivială de unghi $0$ atunci are ca punct fix centrul de rotaţie;\r\n* nu are drepte fixe, dar are cercuri fixe centrate în centrul de rotaţie;\r\n* două rotaţii succesive $R{~1~}(O{~1~}, alfa)$ şi $R{~2~}(O{~2~}, beta)$ se compun într-o translaţie sau o rotaţie $R{~3~}(O{~3~}, alfa + beta)$;\r\n* în general rotaţiile nu comută;\r\n\r\nh3(#omotetia). Omotetia\r\n\r\nAceasta este o transformare ce scalează obiectele în funcţie de un centru de omotetie şi un raport. Un punct $P(x, y)$ transformat după o omotetie $H(O(x{~0~}, y{~0~}), k)$ (centru $O$ şi raport $k$) va avea imaginea $P’(x{~0~} + k * (x - x{~0~}), y{~0~} + k * (y - y{~0~}))$.\r\n\r\nProprietăţi:\r\n\r\n* nu păstrează distanţele;\r\n* păstrează orientarea poligoanelor;\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele, iar transformata unei drepte va fi paralelă cu dreapta;\r\n* are ca punct fix centrul de omotetie;\r\n* două omotetii succesive $H{~1~}(O{~1~}, k{~1~})$ şi $H{~2~}(O{~2~}, k{~2~})$ se compun într-o translaţie sau omotetie $H{~3~}(O{~3~}, k{~1~} + k{~2~})$;\r\n* în general omotetiile nu comută;\r\n\r\nh3(#desfasurarea-in-plan). Desfăşurarea în plan\r\n\r\nAceasta nu este o transformare geometrică propriu-zisă, ci mai mult o tehnică folositoare în rezolvarea unor probleme pe care o puteţi vedea aplicată în problemele ce urmează ...\r\n\r\n*To do:* de verificat teoria de aici. :)\r\n\r\nh2(#aplicatia-1). Aplicaţia 1\r\n\r\n!< transformari-geometrice?aplicatie-1.1.png 60%!\r\n\r\nbq. Fie două puncte $A$ şi $B$ de aceiaşi parte a unei drepte $d$. Se cere să se determine un punct $M$ pe dreapta $d$ cu proprietatea că suma $AM + MB$ e mininimă.\r\n\r\n!> transformari-geometrice?aplicatie-1.2.png 60%!\r\n\r\nh3. Rezolvare:\r\n\r\nDucem simetricul punctului $A$ faţă de dreapta $d$ pe care îl notăm cu $A’$. Oricare ar fi un punct $N$ pe dreapta $d$, $AN = A’N$ pentru că triunghiul $AA’N$ este isoscel având dreapta $d$ şi înălţime şi mediană. Astfel, avem că $AN + NB = A’N + NB$, deci pentru ca să minimizăm suma $AM + MB$ trebuie de fapt să minimizăm suma $A’M + MB$. Punctele $A’$ şi $B$ sunt situate de părţi diferite ale dreptei, deci punctul $M$ trebuie situat la intersecţia segmentului $A’B$ cu dreapta $d$.\r\n\r\nh2(#aplicatia-2). Aplicaţia 2\r\n\r\n!< transformari-geometrice?aplicatie-2.1.png 60%!\r\n\r\nbq. Fie două puncte $A$ şi $B$ în interiorul unui unghi format de semidreptele $d{~1~}$ şi $d{~2~}$ care au capătul comun $O$. Se cere să se determine două puncte $M$ şi $N$ astfel ca $M$ să aparţină lui $d{~1~}$ şi $N$ să aparţină lui $d{~2~}$ iar suma $AM + MN + NB$ să fie minimă.\r\n\r\n!> transformari-geometrice?aplicatie-2.2.png 60%!\r\n\r\nh3. Rezolvare:\r\n\r\nFolosim aceeaşi idee: ducem simetricul punctului $A$, notat cu $A’$, faţă de dreapta $d{~1~}$ şi simetricul punctului $B$ notat cu $B’$ faţă de dreapta $d{~2~}$. Orice puncte $M$ şi $N$ am alege, avem că $AM + MN + NB = A’M + MN + NB$. Pentru a minimiza suma $A’M + MN + NB’$ trebuie ca $M$ şi $N$ să fie intersecţiile segmentului $A’B’$ cu semidreptele $d{~1~}$ şi $d{~2~}$.\r\n\r\n\r\nh2(#aplicatia-3). Aplicaţia 3\r\n\r\n!< transformari-geometrice?aplicatie-3.1.png 70%!\r\n\r\nbq. Dându-se un triunghi ascuţitunghic $ABC$ se cere să se determine un triunghi înscris în acesta de perimetru minim.\r\n\r\nh3. Rezolvare:\r\n\r\n!> transformari-geometrice?aplicatie-3.2.png 70%!\r\n\r\nLuăm un punct $M$ pe baza $BC$ a triunghiului $ABC$, un punct $P$ pe latura $AB$ şi un punct $N$ pe latura $AC$. Dacă avem $M’$ simetricul lui $M$ faţă de $AB$ şi $M’’$ simetricul lui $M$ faţă de $AC$, atunci $MN + NP + PM = M’’N + NP + PM’$. Ca să minimizăm această sumă, punctele $P$ şi $N$ trebuie să fie la intersecţia segmentului $M’M’’$ cu laturile $AB$, respectiv $AC$. Perimetrul triunghiului $MNP$ va fi egal cu lungimea segmentului $M’M’’$. Observăm că unghiul $M’AM’’$ are măsura egală cu $2 * măsura unghiului BAC$ şi că triunghiul $M’AM’’$ e isoscel de latură egală cu $AM$. Pentru ca $M’M’’$ să aibă lungimea minimă trebuie ca $AM$ să fie cât mai scurt. Acest segment este minim atunci când $M$ este piciorul înalţimii din $A$. La fel putem să deducem că $N$ este piciorul înălţimii din $B$, iar $P$ este piciorul înălţimii din $C$. Astfel, soluţia de perimetru minim este triunghiul ortic.\r\n\r\nh2(#aplicatia-4). Aplicaţia 4: \'PolyLine\':http://www.topcoder.com/stat?c=problem_statement&pm=4509 (TopCoder)\r\n\r\nbq. Se consideră un dreptunghi cu colţurile de coordonate $(0, 0)$ , $(a, 0)$, $(a, b)$, $(0, b)$. Mai considerăm două puncte $A$ şi $B$ de coordonate $(x{~1~}, y{~1~})$ şi $(x{~2~}, y{~2~})$ în interiorul dreptunghiului. Se cere să se determine lungimea minimă a unei linii frânte ce porneşte din $A$ ajunge în $B$ şi intersectează fiecare latură a dreptunghiului. În figura de mai jos, avem un dreptunghi de dimensiuni $4 x 3$ şi trei posibilităţi de a plasa două puncte în interiorul dreptunghiului, împreună cu soluţiile optime. Rezultatele pentru cele trei exemple sunt: $7.8102$, $8.6023$, respectiv $9.4339$.\r\n\r\np=. !transformari-geometrice?aplicatie-4.1.png 70%!\r\n\r\n!> transformari-geometrice?aplicatie-4.2.png 70%!\r\n\r\nh3. Rezolvare:\r\n\r\nEste evident că o soluţie optimă va fi formată din cinci segmente. Putem încerca toate ordinele posibile ale drumului liniei frânte, fiind $4! = 24$ asemenea ordini. Pentru fiecare ordine căutăm drumul optim. Acesta poate fi găsit folosind trucul prezentat în problemele anterioare. Să luăm un exemplu: pentru punctele $A(1, 2)$ şi $B(1,3)$ şi dreptunghiul de dimensiuni $4$ şi $3$, luăm punctele $M, N, P, Q$ pe laturile din stânga, jos, dreapta respectiv sus ale dreptunghiului astfel încât să minimizăm suma $AM + MN + NP + PQ + QB$. Acum, vom duce simetricul lui $A$, notat cu $A’$, faţă de latura din stânga şi simetricul lui $B$, notat cu $B’$, faţă de latura de sus. Avem că $AM = A’M$ şi $QB = QB’$. Deci, ca să minimizăm suma $AM + MN + NP + PQ + QB$ trebuie să minimizăm suma $A’M + MN + NP + PQ + QB’$. Vom duce simetricul lui $A’$, notat prin $A’’$, faţă de latura de jos, şi simetricul lui $B’$, notat prin $B’’$, faţă de latura din dreapta. Avem că $A’M + MN <= A’’N$ şi că $PQ + QB’ <= QB’’$, deci obţinem că pentru a minimiza suma $AM + MN + NP + PQ + QB$ trebuie să minimizăm suma $A’’M + MN + NB’’$. Putem realiza acest obiectiv dacă $M$ şi $N$ vor fi intersecţiile segmentului $A’’B’’$ cu latura de jos, respectiv latura din dreapta a dreptunghiului, iar soluţia este exact distanţa de la $A’’$ la $B’’$.\r\n\r\nh2(#aplicatia-5). Aplicaţia 5 (Olimpiada Letonă, 1997)\r\n\r\n!< transformari-geometrice?aplicatie-5.1.png 70%!\r\n\r\n!> transformari-geometrice?aplicatie-5.2.png 70%!\r\n\r\nbq. Laturile unui teren dreptunghiular de biliard de dimensiuni $43 x 73$ sunt etichetate cu literele $A, R, Z, D$. O bilă $B$ (dimensiunile căreia pot fi ignorate) este plasată în interiorul acestui teren la $13$ centimetri distanţă de latura $R$ şi la $29$ de centimetri distanţă de latura $D$. Un jucător îşi pune tacul pe latura $R$ la un punct ce e situat la $K$ centimetri distanţă de latura $D$ şi loveşte direct bila $B$. Bila se mişcă drept şi dacă e cazul loveşte marginile terenului. Mişcarea bilei se supune legilor fizicii, astfel, când bila se loveşte de margine ea va avea o traiectorie simetrică cu traiectoria iniţială faţă de dreapta perpendiculară pe margine în punctul de impact. O parte din traiectoria bilei o puteţi vedea în figură. Problema esta pentru un număr fix $K (0 &le; K &le; 73)$ şi $N (0 &le; N &le; 10^9^)$. Să se determine distanţa bilei faţă de latura $R$ şi distanţa faţă de latura $D$, după ce bila s-a deplasat exact $N$ centimetri.\r\n\r\n!> transformari-geometrice?aplicatie-5.3.png 65%!\r\n\r\nh3. Rezolvare:\r\n\r\nO rezolvare bazată pe simularea mişcării bilei pare anevoioasă, iar din cauza faptului că $N$ poate fi foarte mare, acest algoritm nu este eficient. O rezolvare elegantă este următoarea. Întâi umplem planul cu o grilă infinită de dreptunghiuri de dimensiuni $43 x 73$. Dacă am lăsa ca bila să îşi continue mişcarea şi am ignora prima lovire a marginii, în terenul adiacent, atunci traiectoria bilei ar fi de la trecerea marginii simetrică cu traiectoria normală a bilei, deci ar fi ca şi cum am reflecta întreaga tablă. Acest fenomen se repetă de fiecare dată când atingem o margine. Astfel, dacă ducem un segment pe direcţia de deplasare a bilei, ce pleacă din $B$, de lungime $N$, şi se termină în $C$ atunci putem vedea în ce dreptunghi este el inclus, şi în funcţie de acest dreptunghi să transformăm punctul $C$ în poziţia finală a bilei în dreptunghiul iniţial.\r\n\r\nh2(#aplicatia-6). Aplicaţia 6: \'Pool\':http://acm.timus.ru/problem.aspx?space=1&num=1258 (Timus)\r\n\r\n!> transformari-geometrice?aplicatie-6.1.png 80%!\r\n\r\nbq. Programatorului Vasile îi place să se plimbe prin biroul lui dreptunghiular. El începe drumul din locul unde este situat biroul lui şi se plimbă până când crede că ar trebui să se apuce de lucru din nou. Drumul lui urmează legea de mişcare dată de „unghiul de incidenţă este egal cu unghiul de reflexie”. Vasile se mişcă de la zid la zid în linie dreaptă. Şeful direct al lui Vasile este interesat cât timp pierde acesta în plimbările lui. Este uşor să aflăm timpul, împărţind distanţa parcursă la viteza medie a lui Vasile (aceasta a fost deja calculată de şef), deci trebuie să se afle distanţa parcursă. Se ştie ordinea în care au fost atinşi pereţii întrucât Vasile, fiind neatent, se loveşte de pereţi şi astfel se aud bufniturile în fiecare zid. Se dau dimensiunile camerei lui Vasile: $W$ şi $D (0 &le; W, D &le; 100)$, poziţia iniţială, poziţia finală şi secvenţa de litere $N, S, E, V$ care este ordinea în care sunt atinşi peretii. De exemplu, în imagine pereţii sunt atinşi în ordinea $NVEVES$. Numărul de coliziui nu depăşeste $1000$, poziţiile iniţiale şi finale nu se află pe marginile dreptunghiului, iar drumul lui Vasile nu va trece prin vreun colţ al încăperii.\r\n\r\nh3. Rezolvare:\r\n\r\nPrecum în problema anterioară, când Vasile atinge un perete mişcarea lui se oglindeşte faţă de mişcarea normală. Vom procesa fiecare instrucţiune din şirul în care e prezentată ordinea atingerii pereţilor. O instrucţiune va însemna o reflexie a dreptunghiului curent şi a punctului destinaţie al lui Vasile. După ce vom procesa toate coliziunile obţinem dreptunghiul final şi punctul de destinaţie transformat în interiorul acestui dreptunghi. Acum linia frântă care unea punctul de start s-a transformat într-un segment de dreaptă între punctul de start şi imaginea punctului final după ce s-a realizat asupra lui seria de transformări.\r\n',3146,'public',NULL,NULL),('transformari-geometrice','transformari-geometrice','2009-04-12 08:01:38','2009-06-30 14:45:09','h1. Transformări geometrice\r\n\r\n(Categoria _Matematică_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'_Introducere_\':transformari-geometrice#introducere\r\n** \'Translaţia\':transformari-geometrice#translatia\r\n** \'Simetria\':transformari-geometrice#simetria\r\n** \'Rotaţia\':transformari-geometrice#rotatia\r\n** \'Omotetia\':transformari-geometrice#omotetia\r\n** \'Desfăşurarea în plan\':transformari-geometrice#desfasurarea-in-plan\r\n* \'Aplicaţia 1\':transformari-geometrice#aplicatia-1\r\n* \'Aplicaţia 2\':transformari-geometrice#aplicatia-2\r\n* \'Aplicaţia 3\':transformari-geometrice#aplicatia-3\r\n* \'Aplicaţia 4: PolyLine &#40;TopCoder&#41;\':transformari-geometrice#aplicatia-4\r\n* \'Aplicaţia 5 &#40;Olimpiada Letonă, 1997&#41;\':transformari-geometrice#aplicatia-5\r\n\r\nh2(#introducere). Introducere\r\n\r\nÎn acest articol vom introduce câteva noţuni legate de transformările geometrice care se pot dovedi utile în concursurile de programare.\r\n\r\nÎnainte de toate prezentăm câteva aspecte teoretice, o mare parte din ele nefiind foarte interesante şi probabil sunt conţinute şi în manualele de liceu. Cititorul poate trece direct la probleme şi, în măsura în care noţiunile din soluţii îi sunt neclare, poate reveni asupra părţii teoretice.\r\n\r\nh3(#translatia). Translaţia\r\n\r\nTranslaţia unei figuri geometrice reprezintă mişcarea tuturor componentelor ei pe o anumita distanţă si direcţie. Această transformare poate fi uşor caracterizată de un vector $v = (dx, dy)$. Când vrem să translatăm un punct $P(x, y)$ după $v$, e de ajuns să facem operaţia $P’ = P + v$. Astfel, $P’$ are cooronatele $(x + dx, y + dy)$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* pastrează orientarea poligoanelor (adică, dacă vârfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi şi ele în ordine trigonometrică);\r\n* păstrează unghiurile;\r\n* o dreaptă va fi transformată în altă dreaptă paralelă cu prima;\r\n* înafară de translaţia trivială de vector $v = (0, 0)$, această transformare nu are puncte fixe (adică orice punct va fi transformat într-un punct diferit);\r\n* translaţii successive vor rezulta tot într-o translaţie (adică, dacă vrem să translatăm un punct dupa $v$ şi apoi după $v{~1~}$, atunci obţinem acelaşi rezultat dacă translatăm direct după $v + v{~1~}$);\r\n* translaţia este comutativă;\r\n\r\nh3(#simetria). Simetria\r\n\r\nExistă două tipuri de simetrii: simetria faţă de un punct şi simetria faţa de o dreaptă.\r\n\r\nUn punct $A$ îl are simetric pe $A’$ faţă de un punct $O$, dacă segmentul $AA’$ are ca mijloc punctul $O$. Dacă avem un punct $(x{~0~}, y{~0~})$ căruia vrem să îi aflăm simetricul faţă de un punct de coordonate $(x, y)$ atunci acesta va fi $(2x – x{~0~}, 2y – y{~0~})$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* păstrează orientarea poligoanelor (adică, dacă varfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi şi ele în ordine trigonometrică);\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* are ca punct fix punctul $O$, iar drepte fixe cele care trec prin punctul $O$;\r\n* simetrii succesive după centre diferite $O{~1~}(x{~1~}, y{~1~}) O{~2~}(x{~2~}, y{~2~})$ sunt o translaţie de vector $v = 2(x{~2~} – x{~1~})$;\r\n* simetriile după un punct nu comută;\r\n\r\nSă calculăm simetricul unui punct $P(x{~0~}, y{~0~})$ faţă de o dreaptă de ecuaţie $ax + by + c = 0$. Notăm cu $d$ distanţa de la punctul $P$ la dreaptă, <tex> d = \\displaystyle\\frac{|a*x_{0} + b*y_{0} + c|}{\\sqrt{a^2 + b^2}} </tex>, şi cu $(m{~1~}, m{~2~})$ cosinii directori ai vectorului $n(a, b)$ normal la dreaptă. Valorile cosinilor directori sunt: <tex> m_{1} = \\displaystyle \\pm \\frac{a}{\\sqrt{a^2 + b^2}} </tex> şi <tex> m_{2} = \\displaystyle \\pm \\frac{b}{\\sqrt{a^2 + b^2}} </tex>. Vom alege semnul minus dacă $ax{~0~} + by{~0~} + c > 0$ iar semnul plus dacă $ax{~0~} + by{~0~} + c < 0$. Astfel, simetricul punctului $P$ va avea coordonatele $(x{~0~} + 2*d*m{~1~}, y{~0~} + 2*d*m{~2~})$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* nu păstrează orientarea poligoanelor (adică, dacă varfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi în sens orar);\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* are ca puncte fixe dreapta de simetrie;\r\n* simetrii succesive după drepte paralele sunt o translaţie;\r\n* simetrii succesive după drepte concurente sunt rotaţii;\r\n* simetriile nu comută;\r\n\r\nh3(#rotatia). Rotaţia\r\n\r\nAceasta este o transformare care roteşte punctele în sens trigonometric în jurul unui punct numit centru de rotaţie după un unghi fixat numit unghi de rotaţie. Dacă avem rotaţia de centru $O(x{~0~}, y{~0~})$ şi unghi $alfa$, atunci imaginea unui punct $P(x, y)$ va fi $P’(x{~0~} + (x – x{~0~}) * cos(alfa)  - (y – y{~0~}) * sin(alfa), y{~0~} + (x – x{~0~}) * sin(alfa)  + (y – y{~0~}) * cos(alfa))$.\r\n \r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* păstrează orientarea poligoanelor;\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* dacă nu este o rotaţie trivială de unghi $0$ atunci are ca punct fix centrul de rotaţie;\r\n* nu are drepte fixe, dar are cercuri fixe centrate în centrul de rotaţie;\r\n* două rotaţii succesive $R{~1~}(O{~1~}, alfa)$ şi $R{~2~}(O{~2~}, beta)$ se compun într-o translaţie sau o rotaţie $R{~3~}(O{~3~}, alfa + beta)$;\r\n* în general rotaţiile nu comută;\r\n\r\nh3(#omotetia). Omotetia\r\n\r\nAceasta este o transformare ce scalează obiectele în funcţie de un centru de omotetie şi un raport. Un punct $P(x, y)$ transformat după o omotetie $H(O(x{~0~}, y{~0~}), k)$ (centru $O$ şi raport $k$) va avea imaginea $P’(x{~0~} + k * (x - x{~0~}), y{~0~} + k * (y - y{~0~}))$.\r\n\r\nProprietăţi:\r\n\r\n* nu păstrează distanţele;\r\n* păstrează orientarea poligoanelor;\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele, iar transformata unei drepte va fi paralelă cu dreapta;\r\n* are ca punct fix centrul de omotetie;\r\n* două omotetii succesive $H{~1~}(O{~1~}, k{~1~})$ şi $H{~2~}(O{~2~}, k{~2~})$ se compun într-o translaţie sau omotetie $H{~3~}(O{~3~}, k{~1~} + k{~2~})$;\r\n* în general omotetiile nu comută;\r\n\r\nh3(#desfasurarea-in-plan). Desfăşurarea în plan\r\n\r\nAceasta nu este o transformare geometrică propriu-zisă, ci mai mult o tehnică folositoare în rezolvarea unor probleme pe care o puteţi vedea aplicată în problemele ce urmează ...\r\n\r\n*To do:* de verificat teoria de aici. :)\r\n\r\nh2(#aplicatia-1). Aplicaţia 1\r\n\r\n!< transformari-geometrice?aplicatie-1.1.png 60%!\r\n\r\nbq. Fie două puncte $A$ şi $B$ de aceiaşi parte a unei drepte $d$. Se cere să se determine un punct $M$ pe dreapta $d$ cu proprietatea că suma $AM + MB$ e mininimă.\r\n\r\n!> transformari-geometrice?aplicatie-1.2.png 60%!\r\n\r\nh3. Rezolvare:\r\n\r\nDucem simetricul punctului $A$ faţă de dreapta $d$ pe care îl notăm cu $A’$. Oricare ar fi un punct $N$ pe dreapta $d$, $AN = A’N$ pentru că triunghiul $AA’N$ este isoscel având dreapta $d$ şi înălţime şi mediană. Astfel, avem că $AN + NB = A’N + NB$, deci pentru ca să minimizăm suma $AM + MB$ trebuie de fapt să minimizăm suma $A’M + MB$. Punctele $A’$ şi $B$ sunt situate de părţi diferite ale dreptei, deci punctul $M$ trebuie situat la intersecţia segmentului $A’B$ cu dreapta $d$.\r\n\r\nh2(#aplicatia-2). Aplicaţia 2\r\n\r\n!< transformari-geometrice?aplicatie-2.1.png 60%!\r\n\r\nbq. Fie două puncte $A$ şi $B$ în interiorul unui unghi format de semidreptele $d{~1~}$ şi $d{~2~}$ care au capătul comun $O$. Se cere să se determine două puncte $M$ şi $N$ astfel ca $M$ să aparţină lui $d{~1~}$ şi $N$ să aparţină lui $d{~2~}$ iar suma $AM + MN + NB$ să fie minimă.\r\n\r\n!> transformari-geometrice?aplicatie-2.2.png 60%!\r\n\r\nh3. Rezolvare:\r\n\r\nFolosim aceeaşi idee: ducem simetricul punctului $A$, notat cu $A’$, faţă de dreapta $d{~1~}$ şi simetricul punctului $B$ notat cu $B’$ faţă de dreapta $d{~2~}$. Orice puncte $M$ şi $N$ am alege, avem că $AM + MN + NB = A’M + MN + NB$. Pentru a minimiza suma $A’M + MN + NB’$ trebuie ca $M$ şi $N$ să fie intersecţiile segmentului $A’B’$ cu semidreptele $d{~1~}$ şi $d{~2~}$.\r\n\r\n\r\nh2(#aplicatia-3). Aplicaţia 3\r\n\r\n!< transformari-geometrice?aplicatie-3.1.png 70%!\r\n\r\nbq. Dându-se un triunghi ascuţitunghic $ABC$ se cere să se determine un triunghi înscris în acesta de perimetru minim.\r\n\r\nh3. Rezolvare:\r\n\r\n!> transformari-geometrice?aplicatie-3.2.png 70%!\r\n\r\nLuăm un punct $M$ pe baza $BC$ a triunghiului $ABC$, un punct $P$ pe latura $AB$ şi un punct $N$ pe latura $AC$. Dacă avem $M’$ simetricul lui $M$ faţă de $AB$ şi $M’’$ simetricul lui $M$ faţă de $AC$, atunci $MN + NP + PM = M’’N + NP + PM’$. Ca să minimizăm această sumă, punctele $P$ şi $N$ trebuie să fie la intersecţia segmentului $M’M’’$ cu laturile $AB$, respectiv $AC$. Perimetrul triunghiului $MNP$ va fi egal cu lungimea segmentului $M’M’’$. Observăm că unghiul $M’AM’’$ are măsura egală cu $2 * măsura unghiului BAC$ şi că triunghiul $M’AM’’$ e isoscel de latură egală cu $AM$. Pentru ca $M’M’’$ să aibă lungimea minimă trebuie ca $AM$ să fie cât mai scurt. Acest segment este minim atunci când $M$ este piciorul înalţimii din $A$. La fel putem să deducem că $N$ este piciorul înălţimii din $B$, iar $P$ este piciorul înălţimii din $C$. Astfel, soluţia de perimetru minim este triunghiul ortic.\r\n\r\nh2(#aplicatia-4). Aplicaţia 4: \'PolyLine\':http://www.topcoder.com/stat?c=problem_statement&pm=4509 (TopCoder)\r\n\r\nbq. Se consideră un dreptunghi cu colţurile de coordonate $(0, 0)$ , $(a, 0)$, $(a, b)$, $(0, b)$. Mai considerăm două puncte $A$ şi $B$ de coordonate $(x{~1~}, y{~1~})$ şi $(x{~2~}, y{~2~})$ în interiorul dreptunghiului. Se cere să se determine lungimea minimă a unei linii frânte ce porneşte din $A$ ajunge în $B$ şi intersectează fiecare latură a dreptunghiului. În figura de mai jos, avem un dreptunghi de dimensiuni $4 x 3$ şi trei posibilităţi de a plasa două puncte în interiorul dreptunghiului, împreună cu soluţiile optime. Rezultatele pentru cele trei exemple sunt: $7.8102$, $8.6023$, respectiv $9.4339$.\r\n\r\np=. !transformari-geometrice?aplicatie-4.1.png 70%!\r\n\r\n!> transformari-geometrice?aplicatie-4.2.png 70%!\r\n\r\nh3. Rezolvare:\r\n\r\nEste evident că o soluţie optimă va fi formată din cinci segmente. Putem încerca toate ordinele posibile ale drumului liniei frânte, fiind $4! = 24$ asemenea ordini. Pentru fiecare ordine căutăm drumul optim. Acesta poate fi găsit folosind trucul prezentat în problemele anterioare. Să luăm un exemplu: pentru punctele $A(1, 2)$ şi $B(1,3)$ şi dreptunghiul de dimensiuni $4$ şi $3$, luăm punctele $M, N, P, Q$ pe laturile din stânga, jos, dreapta respectiv sus ale dreptunghiului astfel încât să minimizăm suma $AM + MN + NP + PQ + QB$. Acum, vom duce simetricul lui $A$, notat cu $A’$, faţă de latura din stânga şi simetricul lui $B$, notat cu $B’$, faţă de latura de sus. Avem că $AM = A’M$ şi $QB = QB’$. Deci, ca să minimizăm suma $AM + MN + NP + PQ + QB$ trebuie să minimizăm suma $A’M + MN + NP + PQ + QB’$. Vom duce simetricul lui $A’$, notat prin $A’’$, faţă de latura de jos, şi simetricul lui $B’$, notat prin $B’’$, faţă de latura din dreapta. Avem că $A’M + MN <= A’’N$ şi că $PQ + QB’ <= QB’’$, deci obţinem că pentru a minimiza suma $AM + MN + NP + PQ + QB$ trebuie să minimizăm suma $A’’M + MN + NB’’$. Putem realiza acest obiectiv dacă $M$ şi $N$ vor fi intersecţiile segmentului $A’’B’’$ cu latura de jos, respectiv latura din dreapta a dreptunghiului, iar soluţia este exact distanţa de la $A’’$ la $B’’$.\r\n\r\nh2(#aplicatia-5). Aplicaţia 5 (Olimpiada Letonă, 1997)\r\n\r\n!< transformari-geometrice?aplicatie-5.1.png 70%!\r\n\r\n!> transformari-geometrice?aplicatie-5.2.png 70%!\r\n\r\nbq. Laturile unui teren dreptunghiular de biliard de dimensiuni $43 x 73$ sunt etichetate cu literele $A, R, Z, D$. O bilă $B$ (dimensiunile căreia pot fi ignorate) este plasată în interiorul acestui teren la $13$ centimetri distanţă de latura $R$ şi la $29$ de centimetri distanţă de latura $D$. Un jucător îşi pune tacul pe latura $R$ la un punct ce e situat la $K$ centimetri distanţă de latura $D$ şi loveşte direct bila $B$. Bila se mişcă drept şi dacă e cazul loveşte marginile terenului. Mişcarea bilei se supune legilor fizicii, astfel, când bila se loveşte de margine ea va avea o traiectorie simetrică cu traiectoria iniţială faţă de dreapta perpendiculară pe margine în punctul de impact. O parte din traiectoria bilei o puteţi vedea în figură. Problema esta pentru un număr fix $K (0 &le; K &le; 73)$ şi $N (0 &le; N &le; 10^9^)$. Să se determine distanţa bilei faţă de latura $R$ şi distanţa faţă de latura $D$, după ce bila s-a deplasat exact $N$ centimetri.\r\n\r\n!> transformari-geometrice?aplicatie-5.3.png 65%!\r\n\r\nh3. Rezolvare:\r\n\r\nO rezolvare bazată pe simularea mişcării bilei pare anevoioasă, iar din cauza faptului că $N$ poate fi foarte mare, acest algoritm nu este eficient. O rezolvare elegantă este următoarea. Întâi umplem planul cu o grilă infinită de dreptunghiuri de dimensiuni $43 x 73$. Dacă am lăsa ca bila să îşi continue mişcarea şi am ignora prima lovire a marginii, în terenul adiacent, atunci traiectoria bilei ar fi de la trecerea marginii simetrică cu traiectoria normală a bilei, deci ar fi ca şi cum am reflecta întreaga tablă. Acest fenomen se repetă de fiecare dată când atingem o margine. Astfel, dacă ducem un segment pe direcţia de deplasare a bilei, ce pleacă din $B$, de lungime $N$, şi se termină în $C$ atunci putem vedea în ce dreptunghi este el inclus, şi în funcţie de acest dreptunghi să transformăm punctul $C$ în poziţia finală a bilei în dreptunghiul iniţial.\r\n\r\nh2(#aplicatia-6). Aplicaţia 6: \'Pool\':http://acm.timus.ru/problem.aspx?space=1&num=1258 (Timus)\r\n\r\n!> transformari-geometrice?aplicatie-6.1.png 80%!\r\n\r\nbq. Programatorului Vasile îi place să se plimbe prin biroul lui dreptunghiular. El începe drumul din locul unde este situat biroul lui şi se plimbă până când crede că ar trebui să se apuce de lucru din nou. Drumul lui urmează legea de mişcare dată de „unghiul de incidenţă este egal cu unghiul de reflexie”. Vasile se mişcă de la zid la zid în linie dreaptă. Şeful direct al lui Vasile este interesat cât timp pierde acesta în plimbările lui. Este uşor să aflăm timpul, împărţind distanţa parcursă la viteza medie a lui Vasile (aceasta a fost deja calculată de şef), deci trebuie să se afle distanţa parcursă. Se ştie ordinea în care au fost atinşi pereţii întrucât Vasile, fiind neatent, se loveşte de pereţi şi astfel se aud bufniturile în fiecare zid. Se dau dimensiunile camerei lui Vasile: $W$ şi $D (0 &le; W, D &le; 100)$, poziţia iniţială, poziţia finală şi secvenţa de litere $N, S, E, V$ care este ordinea în care sunt atinşi peretii. De exemplu, în imagine pereţii sunt atinşi în ordinea $NVEVES$. Numărul de coliziui nu depăşeste $1000$, poziţiile iniţiale şi finale nu se află pe marginile dreptunghiului, iar drumul lui Vasile nu va trece prin vreun colţ al încăperii.\r\n\r\nh3. Rezolvare:\r\n\r\nPrecum în problema anterioară, când Vasile atinge un perete mişcarea lui se oglindeşte faţă de mişcarea normală. Vom procesa fiecare instrucţiune din şirul în care e prezentată ordinea atingerii pereţilor. O instrucţiune va însemna o reflexie a dreptunghiului curent şi a punctului destinaţie al lui Vasile. După ce vom procesa toate coliziunile obţinem dreptunghiul final şi punctul de destinaţie transformat în interiorul acestui dreptunghi. Acum linia frântă care unea punctul de start s-a transformat într-un segment de dreaptă între punctul de start şi imaginea punctului final după ce s-a realizat asupra lui seria de transformări.\r\n\r\nh2(#aplicatia-7). Aplicaţia 7: \'NCushion, Topcoder\':http://www.topcoder.com/stat?c=problem_statement&pm=1963\r\n\r\nbq. Pe o masă de biliard de dimensiuni $2000 x 1000$ sunt aşezate două bile la coordonate întregi. Se cere să se determine numărul de posibilităţi de lovire a primei bile, astfel ca ea să lovească exact de $N$ ori manta $(1 &le; N &le; 500)$ şi apoi să lovească cea de a doua bilă. Mişcarea bilei se consideră ideală, iar dacă bila loveşte un colţ se consideră că s-au atins două mante şi bila se va mişca pe aceiaşi direcţie în sens opus.\r\n\r\nh3. Rezolvare:\r\n\r\n!> transformari-geometrice?aplicatie-7.1.png 70%!\r\n\r\nSoluţia foloseşte ideea de mai sus de a reflecta tabla de biliard împreună cu poziţia celei de a doua bile. Aşa cum am văzut în problema anterioară, fiecare şir de atingeri al mantelor ne dă exact un mod în care prima bilă o poate lovi pe cea de a doua. Dacă ştim în ce dreptunghi reflectat vrem să lovim bila a doua, fixând acest dreptunghi, avem o direcţie fixată şi un şir de mante fix pe care le va atinge bila dacă va fi lovită în acea direcţie. În figură avem cazul în care trebuie să lovim exact două mante înainte să atingem a doua bilă.\r\n\r\nÎn desen am colorat cu negru bila iniţială şi cu alb a doua bilă şi imaginile ei. Cu linie punctată am desenat traiectoriile care ar fi atins bila a doua fără a atinge de două ori manta şi cu linie neagră direcţiile pe care manta ar fi atinsă exact de două ori. Observăm că pentru a atinge manta de $N$ ori o bilă trebuie să intre în $N$ alte dreptunghiuri. Deci, asociem poziţiilor dreptunghiurilor un sistem de coordonate în care dreptunghiul iniţial are coordonatele $(0, 0)$. Pentru ca bila să atingă exact $N$ mante, coordonatele $(x, y)$ ale dreptunghiului trebuie să satisfacă egalitatea $|x| + |y| = N$. Mai trebuie să avem grijă ca drumul bilei care atinge $N$ mante să nu atingă a doua bilă înainte de atingerea tuturor mantelor. Aceste observaţii ne duc la următoarea soluţie: pentru toate dreptunghiurile $(x, y)$, care satisfac proprietatea $|x| + |y| < N$, păstrăm într-o structură de date (structura preferată de autor ar fi un \'tabel de dispersie\':tabele-hash-prezentare-detaliata) vectorul asociat direcţiei pe care ar fi trebuit lovită prima bilă pentru a ajunge la imaginea celei de a doua bile din acest dreptunghi. Apoi, pentru fiecare dreptunghi pentru care $|x| + |y| = N$, dacă direcţia asociată lui nu este în structura de date, incrementăm numărul de soluţii. Această rezolvare are complexitatea $O(N^2^ log N)$ pentru că normalizarea unei direcţii implică folosirea \'algoritmului lui Euclid\':problema/euclid2 ce are complexitate $O(log N)$.',3146,'public',NULL,NULL),('transformari-geometrice','transformari-geometrice','2009-04-12 08:01:38','2009-06-30 15:42:47','h1. Transformări geometrice\r\n\r\n(Categoria _Matematică_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Conţinut:*\r\n* \'_Introducere_\':transformari-geometrice#introducere\r\n** \'Translaţia\':transformari-geometrice#translatia\r\n** \'Simetria\':transformari-geometrice#simetria\r\n** \'Rotaţia\':transformari-geometrice#rotatia\r\n** \'Omotetia\':transformari-geometrice#omotetia\r\n** \'Desfăşurarea în plan\':transformari-geometrice#desfasurarea-in-plan\r\n* \'Aplicaţia 1\':transformari-geometrice#aplicatia-1\r\n* \'Aplicaţia 2\':transformari-geometrice#aplicatia-2\r\n* \'Aplicaţia 3\':transformari-geometrice#aplicatia-3\r\n* \'Aplicaţia 4: PolyLine &#40;TopCoder&#41;\':transformari-geometrice#aplicatia-4\r\n* \'Aplicaţia 5 &#40;Olimpiada Letonă, 1997&#41;\':transformari-geometrice#aplicatia-5\r\n\r\nh2(#introducere). Introducere\r\n\r\nÎn acest articol vom introduce câteva noţuni legate de transformările geometrice care se pot dovedi utile în concursurile de programare.\r\n\r\nÎnainte de toate prezentăm câteva aspecte teoretice, o mare parte din ele nefiind foarte interesante şi probabil sunt conţinute şi în manualele de liceu. Cititorul poate trece direct la probleme şi, în măsura în care noţiunile din soluţii îi sunt neclare, poate reveni asupra părţii teoretice.\r\n\r\nh3(#translatia). Translaţia\r\n\r\nTranslaţia unei figuri geometrice reprezintă mişcarea tuturor componentelor ei pe o anumita distanţă si direcţie. Această transformare poate fi uşor caracterizată de un vector $v = (dx, dy)$. Când vrem să translatăm un punct $P(x, y)$ după $v$, e de ajuns să facem operaţia $P’ = P + v$. Astfel, $P’$ are cooronatele $(x + dx, y + dy)$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* pastrează orientarea poligoanelor (adică, dacă vârfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi şi ele în ordine trigonometrică);\r\n* păstrează unghiurile;\r\n* o dreaptă va fi transformată în altă dreaptă paralelă cu prima;\r\n* înafară de translaţia trivială de vector $v = (0, 0)$, această transformare nu are puncte fixe (adică orice punct va fi transformat într-un punct diferit);\r\n* translaţii successive vor rezulta tot într-o translaţie (adică, dacă vrem să translatăm un punct dupa $v$ şi apoi după $v{~1~}$, atunci obţinem acelaşi rezultat dacă translatăm direct după $v + v{~1~}$);\r\n* translaţia este comutativă;\r\n\r\nh3(#simetria). Simetria\r\n\r\nExistă două tipuri de simetrii: simetria faţă de un punct şi simetria faţa de o dreaptă.\r\n\r\nUn punct $A$ îl are simetric pe $A’$ faţă de un punct $O$, dacă segmentul $AA’$ are ca mijloc punctul $O$. Dacă avem un punct $(x{~0~}, y{~0~})$ căruia vrem să îi aflăm simetricul faţă de un punct de coordonate $(x, y)$ atunci acesta va fi $(2x – x{~0~}, 2y – y{~0~})$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* păstrează orientarea poligoanelor (adică, dacă varfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi şi ele în ordine trigonometrică);\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* are ca punct fix punctul $O$, iar drepte fixe cele care trec prin punctul $O$;\r\n* simetrii succesive după centre diferite $O{~1~}(x{~1~}, y{~1~}) O{~2~}(x{~2~}, y{~2~})$ sunt o translaţie de vector $v = 2(x{~2~} – x{~1~})$;\r\n* simetriile după un punct nu comută;\r\n\r\nSă calculăm simetricul unui punct $P(x{~0~}, y{~0~})$ faţă de o dreaptă de ecuaţie $ax + by + c = 0$. Notăm cu $d$ distanţa de la punctul $P$ la dreaptă, <tex> d = \\displaystyle\\frac{|a*x_{0} + b*y_{0} + c|}{\\sqrt{a^2 + b^2}} </tex>, şi cu $(m{~1~}, m{~2~})$ cosinii directori ai vectorului $n(a, b)$ normal la dreaptă. Valorile cosinilor directori sunt: <tex> m_{1} = \\displaystyle \\pm \\frac{a}{\\sqrt{a^2 + b^2}} </tex> şi <tex> m_{2} = \\displaystyle \\pm \\frac{b}{\\sqrt{a^2 + b^2}} </tex>. Vom alege semnul minus dacă $ax{~0~} + by{~0~} + c > 0$ iar semnul plus dacă $ax{~0~} + by{~0~} + c < 0$. Astfel, simetricul punctului $P$ va avea coordonatele $(x{~0~} + 2*d*m{~1~}, y{~0~} + 2*d*m{~2~})$.\r\n\r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* nu păstrează orientarea poligoanelor (adică, dacă varfurile poligonului sunt parcurse în ordine trigonometrică, atunci vârfurile corespondente din poligonul transformat vor fi în sens orar);\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* are ca puncte fixe dreapta de simetrie;\r\n* simetrii succesive după drepte paralele sunt o translaţie;\r\n* simetrii succesive după drepte concurente sunt rotaţii;\r\n* simetriile nu comută;\r\n\r\nh3(#rotatia). Rotaţia\r\n\r\nAceasta este o transformare care roteşte punctele în sens trigonometric în jurul unui punct numit centru de rotaţie după un unghi fixat numit unghi de rotaţie. Dacă avem rotaţia de centru $O(x{~0~}, y{~0~})$ şi unghi $alfa$, atunci imaginea unui punct $P(x, y)$ va fi $P’(x{~0~} + (x – x{~0~}) * cos(alfa)  - (y – y{~0~}) * sin(alfa), y{~0~} + (x – x{~0~}) * sin(alfa)  + (y – y{~0~}) * cos(alfa))$.\r\n \r\nProprietăţi:\r\n\r\n* păstrează distanţele;\r\n* păstrează orientarea poligoanelor;\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele;\r\n* dacă nu este o rotaţie trivială de unghi $0$ atunci are ca punct fix centrul de rotaţie;\r\n* nu are drepte fixe, dar are cercuri fixe centrate în centrul de rotaţie;\r\n* două rotaţii succesive $R{~1~}(O{~1~}, alfa)$ şi $R{~2~}(O{~2~}, beta)$ se compun într-o translaţie sau o rotaţie $R{~3~}(O{~3~}, alfa + beta)$;\r\n* în general rotaţiile nu comută;\r\n\r\nh3(#omotetia). Omotetia\r\n\r\nAceasta este o transformare ce scalează obiectele în funcţie de un centru de omotetie şi un raport. Un punct $P(x, y)$ transformat după o omotetie $H(O(x{~0~}, y{~0~}), k)$ (centru $O$ şi raport $k$) va avea imaginea $P’(x{~0~} + k * (x - x{~0~}), y{~0~} + k * (y - y{~0~}))$.\r\n\r\nProprietăţi:\r\n\r\n* nu păstrează distanţele;\r\n* păstrează orientarea poligoanelor;\r\n* păstrează unghiurile;\r\n* drepte paralele vor fi transformate în drepte paralele, iar transformata unei drepte va fi paralelă cu dreapta;\r\n* are ca punct fix centrul de omotetie;\r\n* două omotetii succesive $H{~1~}(O{~1~}, k{~1~})$ şi $H{~2~}(O{~2~}, k{~2~})$ se compun într-o translaţie sau omotetie $H{~3~}(O{~3~}, k{~1~} + k{~2~})$;\r\n* în general omotetiile nu comută;\r\n\r\nh3(#desfasurarea-in-plan). Desfăşurarea în plan\r\n\r\nAceasta nu este o transformare geometrică propriu-zisă, ci mai mult o tehnică folositoare în rezolvarea unor probleme pe care o puteţi vedea aplicată în problemele ce urmează ...\r\n\r\n*To do:* de verificat teoria de aici. :)\r\n\r\nh2(#aplicatia-1). Aplicaţia 1\r\n\r\n!< transformari-geometrice?aplicatie-1.1.png 60%!\r\n\r\nbq. Fie două puncte $A$ şi $B$ de aceiaşi parte a unei drepte $d$. Se cere să se determine un punct $M$ pe dreapta $d$ cu proprietatea că suma $AM + MB$ e mininimă.\r\n\r\n!> transformari-geometrice?aplicatie-1.2.png 60%!\r\n\r\nh3. Rezolvare:\r\n\r\nDucem simetricul punctului $A$ faţă de dreapta $d$ pe care îl notăm cu $A’$. Oricare ar fi un punct $N$ pe dreapta $d$, $AN = A’N$ pentru că triunghiul $AA’N$ este isoscel având dreapta $d$ şi înălţime şi mediană. Astfel, avem că $AN + NB = A’N + NB$, deci pentru ca să minimizăm suma $AM + MB$ trebuie de fapt să minimizăm suma $A’M + MB$. Punctele $A’$ şi $B$ sunt situate de părţi diferite ale dreptei, deci punctul $M$ trebuie situat la intersecţia segmentului $A’B$ cu dreapta $d$.\r\n\r\nh2(#aplicatia-2). Aplicaţia 2\r\n\r\n!< transformari-geometrice?aplicatie-2.1.png 60%!\r\n\r\nbq. Fie două puncte $A$ şi $B$ în interiorul unui unghi format de semidreptele $d{~1~}$ şi $d{~2~}$ care au capătul comun $O$. Se cere să se determine două puncte $M$ şi $N$ astfel ca $M$ să aparţină lui $d{~1~}$ şi $N$ să aparţină lui $d{~2~}$ iar suma $AM + MN + NB$ să fie minimă.\r\n\r\n!> transformari-geometrice?aplicatie-2.2.png 60%!\r\n\r\nh3. Rezolvare:\r\n\r\nFolosim aceeaşi idee: ducem simetricul punctului $A$, notat cu $A’$, faţă de dreapta $d{~1~}$ şi simetricul punctului $B$ notat cu $B’$ faţă de dreapta $d{~2~}$. Orice puncte $M$ şi $N$ am alege, avem că $AM + MN + NB = A’M + MN + NB$. Pentru a minimiza suma $A’M + MN + NB’$ trebuie ca $M$ şi $N$ să fie intersecţiile segmentului $A’B’$ cu semidreptele $d{~1~}$ şi $d{~2~}$.\r\n\r\n\r\nh2(#aplicatia-3). Aplicaţia 3\r\n\r\n!< transformari-geometrice?aplicatie-3.1.png 70%!\r\n\r\nbq. Dându-se un triunghi ascuţitunghic $ABC$ se cere să se determine un triunghi înscris în acesta de perimetru minim.\r\n\r\nh3. Rezolvare:\r\n\r\n!> transformari-geometrice?aplicatie-3.2.png 70%!\r\n\r\nLuăm un punct $M$ pe baza $BC$ a triunghiului $ABC$, un punct $P$ pe latura $AB$ şi un punct $N$ pe latura $AC$. Dacă avem $M’$ simetricul lui $M$ faţă de $AB$ şi $M’’$ simetricul lui $M$ faţă de $AC$, atunci $MN + NP + PM = M’’N + NP + PM’$. Ca să minimizăm această sumă, punctele $P$ şi $N$ trebuie să fie la intersecţia segmentului $M’M’’$ cu laturile $AB$, respectiv $AC$. Perimetrul triunghiului $MNP$ va fi egal cu lungimea segmentului $M’M’’$. Observăm că unghiul $M’AM’’$ are măsura egală cu $2 * măsura unghiului BAC$ şi că triunghiul $M’AM’’$ e isoscel de latură egală cu $AM$. Pentru ca $M’M’’$ să aibă lungimea minimă trebuie ca $AM$ să fie cât mai scurt. Acest segment este minim atunci când $M$ este piciorul înalţimii din $A$. La fel putem să deducem că $N$ este piciorul înălţimii din $B$, iar $P$ este piciorul înălţimii din $C$. Astfel, soluţia de perimetru minim este triunghiul ortic.\r\n\r\nh2(#aplicatia-4). Aplicaţia 4: \'PolyLine\':http://www.topcoder.com/stat?c=problem_statement&pm=4509 (TopCoder)\r\n\r\nbq. Se consideră un dreptunghi cu colţurile de coordonate $(0, 0)$ , $(a, 0)$, $(a, b)$, $(0, b)$. Mai considerăm două puncte $A$ şi $B$ de coordonate $(x{~1~}, y{~1~})$ şi $(x{~2~}, y{~2~})$ în interiorul dreptunghiului. Se cere să se determine lungimea minimă a unei linii frânte ce porneşte din $A$ ajunge în $B$ şi intersectează fiecare latură a dreptunghiului. În figura de mai jos, avem un dreptunghi de dimensiuni $4 x 3$ şi trei posibilităţi de a plasa două puncte în interiorul dreptunghiului, împreună cu soluţiile optime. Rezultatele pentru cele trei exemple sunt: $7.8102$, $8.6023$, respectiv $9.4339$.\r\n\r\np=. !transformari-geometrice?aplicatie-4.1.png 70%!\r\n\r\n!> transformari-geometrice?aplicatie-4.2.png 70%!\r\n\r\nh3. Rezolvare:\r\n\r\nEste evident că o soluţie optimă va fi formată din cinci segmente. Putem încerca toate ordinele posibile ale drumului liniei frânte, fiind $4! = 24$ asemenea ordini. Pentru fiecare ordine căutăm drumul optim. Acesta poate fi găsit folosind trucul prezentat în problemele anterioare. Să luăm un exemplu: pentru punctele $A(1, 2)$ şi $B(1,3)$ şi dreptunghiul de dimensiuni $4$ şi $3$, luăm punctele $M, N, P, Q$ pe laturile din stânga, jos, dreapta respectiv sus ale dreptunghiului astfel încât să minimizăm suma $AM + MN + NP + PQ + QB$. Acum, vom duce simetricul lui $A$, notat cu $A’$, faţă de latura din stânga şi simetricul lui $B$, notat cu $B’$, faţă de latura de sus. Avem că $AM = A’M$ şi $QB = QB’$. Deci, ca să minimizăm suma $AM + MN + NP + PQ + QB$ trebuie să minimizăm suma $A’M + MN + NP + PQ + QB’$. Vom duce simetricul lui $A’$, notat prin $A’’$, faţă de latura de jos, şi simetricul lui $B’$, notat prin $B’’$, faţă de latura din dreapta. Avem că $A’M + MN <= A’’N$ şi că $PQ + QB’ <= QB’’$, deci obţinem că pentru a minimiza suma $AM + MN + NP + PQ + QB$ trebuie să minimizăm suma $A’’M + MN + NB’’$. Putem realiza acest obiectiv dacă $M$ şi $N$ vor fi intersecţiile segmentului $A’’B’’$ cu latura de jos, respectiv latura din dreapta a dreptunghiului, iar soluţia este exact distanţa de la $A’’$ la $B’’$.\r\n\r\nh2(#aplicatia-5). Aplicaţia 5 (Olimpiada Letonă, 1997)\r\n\r\n!< transformari-geometrice?aplicatie-5.1.png 70%!\r\n\r\n!> transformari-geometrice?aplicatie-5.2.png 70%!\r\n\r\nbq. Laturile unui teren dreptunghiular de biliard de dimensiuni $43 x 73$ sunt etichetate cu literele $A, R, Z, D$. O bilă $B$ (dimensiunile căreia pot fi ignorate) este plasată în interiorul acestui teren la $13$ centimetri distanţă de latura $R$ şi la $29$ de centimetri distanţă de latura $D$. Un jucător îşi pune tacul pe latura $R$ la un punct ce e situat la $K$ centimetri distanţă de latura $D$ şi loveşte direct bila $B$. Bila se mişcă drept şi dacă e cazul loveşte marginile terenului. Mişcarea bilei se supune legilor fizicii, astfel, când bila se loveşte de margine ea va avea o traiectorie simetrică cu traiectoria iniţială faţă de dreapta perpendiculară pe margine în punctul de impact. O parte din traiectoria bilei o puteţi vedea în figură. Problema esta pentru un număr fix $K (0 &le; K &le; 73)$ şi $N (0 &le; N &le; 10^9^)$. Să se determine distanţa bilei faţă de latura $R$ şi distanţa faţă de latura $D$, după ce bila s-a deplasat exact $N$ centimetri.\r\n\r\n!> transformari-geometrice?aplicatie-5.3.png 65%!\r\n\r\nh3. Rezolvare:\r\n\r\nO rezolvare bazată pe simularea mişcării bilei pare anevoioasă, iar din cauza faptului că $N$ poate fi foarte mare, acest algoritm nu este eficient. O rezolvare elegantă este următoarea. Întâi umplem planul cu o grilă infinită de dreptunghiuri de dimensiuni $43 x 73$. Dacă am lăsa ca bila să îşi continue mişcarea şi am ignora prima lovire a marginii, în terenul adiacent, atunci traiectoria bilei ar fi de la trecerea marginii simetrică cu traiectoria normală a bilei, deci ar fi ca şi cum am reflecta întreaga tablă. Acest fenomen se repetă de fiecare dată când atingem o margine. Astfel, dacă ducem un segment pe direcţia de deplasare a bilei, ce pleacă din $B$, de lungime $N$, şi se termină în $C$ atunci putem vedea în ce dreptunghi este el inclus, şi în funcţie de acest dreptunghi să transformăm punctul $C$ în poziţia finală a bilei în dreptunghiul iniţial.\r\n\r\nh2(#aplicatia-6). Aplicaţia 6: \'Pool\':http://acm.timus.ru/problem.aspx?space=1&num=1258 (Timus)\r\n\r\n!> transformari-geometrice?aplicatie-6.1.png 80%!\r\n\r\nbq. Programatorului Vasile îi place să se plimbe prin biroul lui dreptunghiular. El începe drumul din locul unde este situat biroul lui şi se plimbă până când crede că ar trebui să se apuce de lucru din nou. Drumul lui urmează legea de mişcare dată de „unghiul de incidenţă este egal cu unghiul de reflexie”. Vasile se mişcă de la zid la zid în linie dreaptă. Şeful direct al lui Vasile este interesat cât timp pierde acesta în plimbările lui. Este uşor să aflăm timpul, împărţind distanţa parcursă la viteza medie a lui Vasile (aceasta a fost deja calculată de şef), deci trebuie să se afle distanţa parcursă. Se ştie ordinea în care au fost atinşi pereţii întrucât Vasile, fiind neatent, se loveşte de pereţi şi astfel se aud bufniturile în fiecare zid. Se dau dimensiunile camerei lui Vasile: $W$ şi $D (0 &le; W, D &le; 100)$, poziţia iniţială, poziţia finală şi secvenţa de litere $N, S, E, V$ care este ordinea în care sunt atinşi peretii. De exemplu, în imagine pereţii sunt atinşi în ordinea $NVEVES$. Numărul de coliziui nu depăşeste $1000$, poziţiile iniţiale şi finale nu se află pe marginile dreptunghiului, iar drumul lui Vasile nu va trece prin vreun colţ al încăperii.\r\n\r\nh3. Rezolvare:\r\n\r\nPrecum în problema anterioară, când Vasile atinge un perete mişcarea lui se oglindeşte faţă de mişcarea normală. Vom procesa fiecare instrucţiune din şirul în care e prezentată ordinea atingerii pereţilor. O instrucţiune va însemna o reflexie a dreptunghiului curent şi a punctului destinaţie al lui Vasile. După ce vom procesa toate coliziunile obţinem dreptunghiul final şi punctul de destinaţie transformat în interiorul acestui dreptunghi. Acum linia frântă care unea punctul de start s-a transformat într-un segment de dreaptă între punctul de start şi imaginea punctului final după ce s-a realizat asupra lui seria de transformări.\r\n\r\nh2(#aplicatia-7). Aplicaţia 7: \'NCushion\':http://www.topcoder.com/stat?c=problem_statement&pm=1963 (TopCoder)\r\n\r\nbq. Pe o masă de biliard de dimensiuni $2000 x 1000$ sunt aşezate două bile la coordonate întregi. Se cere să se determine numărul de posibilităţi de lovire a primei bile, astfel ca ea să lovească exact de $N$ ori manta $(1 &le; N &le; 500)$ şi apoi să lovească cea de a doua bilă. Mişcarea bilei se consideră ideală, iar dacă bila loveşte un colţ se consideră că s-au atins două mante şi bila se va mişca pe aceiaşi direcţie în sens opus.\r\n\r\nh3. Rezolvare:\r\n\r\n!> transformari-geometrice?aplicatie-7.1.png 70%!\r\n\r\nSoluţia foloseşte ideea de mai sus de a reflecta tabla de biliard împreună cu poziţia celei de a doua bile. Aşa cum am văzut în problema anterioară, fiecare şir de atingeri al mantelor ne dă exact un mod în care prima bilă o poate lovi pe cea de a doua. Dacă ştim în ce dreptunghi reflectat vrem să lovim bila a doua, fixând acest dreptunghi, avem o direcţie fixată şi un şir de mante fix pe care le va atinge bila dacă va fi lovită în acea direcţie. În figură avem cazul în care trebuie să lovim exact două mante înainte să atingem a doua bilă.\r\n\r\nÎn desen am colorat cu negru bila iniţială şi cu alb a doua bilă şi imaginile ei. Cu linie punctată am desenat traiectoriile care ar fi atins bila a doua fără a atinge de două ori manta şi cu linie neagră direcţiile pe care manta ar fi atinsă exact de două ori. Observăm că pentru a atinge manta de $N$ ori o bilă trebuie să intre în $N$ alte dreptunghiuri. Deci, asociem poziţiilor dreptunghiurilor un sistem de coordonate în care dreptunghiul iniţial are coordonatele $(0, 0)$. Pentru ca bila să atingă exact $N$ mante, coordonatele $(x, y)$ ale dreptunghiului trebuie să satisfacă egalitatea $|x| + |y| = N$. Mai trebuie să avem grijă ca drumul bilei care atinge $N$ mante să nu atingă a doua bilă înainte de atingerea tuturor mantelor. Aceste observaţii ne duc la următoarea soluţie: pentru toate dreptunghiurile $(x, y)$, care satisfac proprietatea $|x| + |y| < N$, păstrăm într-o structură de date (structura preferată de autor ar fi un \'tabel de dispersie\':tabele-hash-prezentare-detaliata) vectorul asociat direcţiei pe care ar fi trebuit lovită prima bilă pentru a ajunge la imaginea celei de a doua bile din acest dreptunghi. Apoi, pentru fiecare dreptunghi pentru care $|x| + |y| = N$, dacă direcţia asociată lui nu este în structura de date, incrementăm numărul de soluţii. Această rezolvare are complexitatea $O(N^2^ log N)$ pentru că normalizarea unei direcţii implică folosirea \'algoritmului lui Euclid\':problema/euclid2 ce are complexitate $O(log N)$.\r\n\r\nh2(#aplicatia-8). Aplicaţia 8: \'PuckShot\':http://www.topcoder.com/stat?c=problem_statement&pm=2411&rd=4750 (TopCoder)\r\n\r\nbq. Un jucător de hockey stângaci are o mişcare în care de la mijlocul terenului izbeşte pucul de marginea terenului care apoi întră în spaţiul porţii. Terenul este de $3000$ de centimetri lăţime. Distanţa între linia de mijloc şi linia de gol este de $1733$ de centimetri. Poarta este centrată pe linia de gol şi are dimensiunea de $183$ de centimetri. Când jucătorul loveşte, puc-ul se va lovi de marginea terenului şi apoi va ricoşa simetric în poartă. Pucul şi stâlpii porţii vor fi considerate puncte. Pe gheaţă vor fi cel mult nouă jucători care vor fi modelaţi ca segmente orizontale de lungime $50$ centimetri. Pentru ca lovitura să aibă succes, traiectoria ei nu trebuie să intersecteze niciun jucător. Pentru simplitate, puteţi presupune că terenul este perfect dreptunghiular. Se cere unghiul format de lovitura jucătorului cu linia de mijloc, astfel ca lovitura să fie cu succes şi pucul să intre în poartă şi să fie cât mai apropiat de stâlpul drept al porţii. Structura unui teren de hockey este prezentată în următoarea figură:\r\n\r\np=. !transformari-geometrice?aplicatie-8.1.png 70%!\r\n\r\nh3. Rezolvare:\r\n\r\n!> transformari-geometrice?aplicatie-8.2.png 70%!\r\n\r\nO rezolvare posibilă ar fi să pornim cu o lovitură de un unghi fixat şi să vedem dacă ajunge în poartă, iar apoi să creştem unghiul loviturii puţin câte puţin. Prin folosirea unor consideraţii de simetrie putem rezolva problema mai uşor şi mai eficient. Oglindim terenul împreună cu toţi jucătorii. Astfel, transformăm lovitura din două segmente în unul singur care trece prin dreapta de simetrie. Acum, luăm fiecare punct lateral al jucătorilor, fiecare punct lateral al imaginii reflectate ale jucătorilor şi punctele porţii reflectate, şi unim aceste puncte cu punctul de unde jucătorul va lovi pucul. Verificăm care dintre aceste drepte dacă sunt rotite foarte puţin la dreapta sau la stânga intersectează imaginea porţii reflectate şi nu intersectează segmentele ce reprezintă jucătorii sau imaginea lor reflectată. Astfel, soluţia noastră are complexitatea $O(N^2^)$ unde $N$ este numărul de jucători, pentru că pentru fiecare dintre cele $4N + 2$ raze trebuie să verificăm intersecţia cu $2N + 1$ segmente. Pe acestă idee putem realiza o soluţie în $O(N log N)$ folosind o linie de baleiere care trece prin punctul iniţial si se mişcă circular în jurul lui.\r\n\r\nh2(#aplicatia-9). Aplicaţia 9: \'Poligon 2\':problema/poligon2 (infoarena)\r\n\r\nbq. Se dau coordonatele mijloacelor laturilor unui poligon nu neapărat convex şi care se poate autointersecta. Se cere să se determine coordonatele vârfurilor poligonului.\r\n\r\nh3. Rezolvare:\r\n\r\nConsiderăm că poligonul are $N$ vârfuri. Rezolvăm problema întâi pentru $N$ par. Luăm primul vârf al poligonului, şi îi determinăm simetricul faţă de primul mijloc de latură. Astfel găsim al doilea vârf. Dacă luăm al doilea vârf printr-o simetrie îl obţinem pe al treilea ş.a.m.d. Deci prin $N$ simetrii obţinem din nou primul punct. Cum $N$ este par fiecare două simetrii compuse sunt o translaţie, deci avem o serie de translaţii care se compun într-una care duce punctul iniţial în punctul iniţial. Aşa cum am vazut la partea teoretică translaţia are un punct fix doar dacă ea e translaţie trivială. Translaţia fiind trivială, putem porni cu orice punct din plan şi să obţinem celelalte $N + 1$ puncte din poligon ca şi rezultate ale simetriilor aplicate succesiv. În cazul în care $N$ e impar transformarea explicată mai sus are ca rezultat compunerea între o translaţie şi o simetrie, compunere care aşa cum puteţi verifica are ca rezultat o simetrie de alt centru. Dar punctul iniţial este transformat în acelaşi punct, deci el trebuie să fie centrul de simetrie al transformării compuse. Şi, atunci luăm un punct oarecare $P$ în plan, efectuăm cele $N$ transformări asupra lui şi obţinem un punct $P’$. Primul punct al poligonului va fi mijlocul acestui segment.\r\n\r\nh2(#aplicatia-10). Aplicaţia 10: \'Dmg\':problema/dmg (Stelele Informaticii 2005, infoarena)\r\n\r\nbq. Se dau $N (1 &le; N &le; 1500)$ puncte de coordonate întregi. Să se determine numărul de axe de simetrie al sistemului de puncte.\r\n\r\nh3. Rezolvare:\r\n\r\nAxele de simetrie ale sistemului de puncte trebuie să fie şi axe de simetrie pentru poligonul ce reprezintă înfăşurătoarea convexă a acestor puncte. Dacă vrem să găsim axele de simetrie ale unui poligon convex, observăm că dacă el are număr par de vârfuri, atunci trebuie ca acestea sau să fie mediatoare pentru o latură a poligonului, sau să treacă prin două vârfuri. Dacă el are număr impar de laturi atunci axele de simetrie trebuie să fie mediatoare pentru o latură şi să treacă printr-un punct al poligonului. Astfel, după calcularea în $O(N log N)$ a înfăţurătorii convexe, putem afla în timp $O(N)$ care sunt candidate la axa de simetrie a poligonului. Verificarea faptului dacă o dreaptă este axă de simetrie pentru un set de puncte o putem face în $O(N)$ folosindu-ne de o tabelă de dispersie. Algoritmul de determinare a axelor de simetrie are complexitatea finală $O(N^2^)$.\r\n\r\nh2(#aplicatia-11). Aplicaţia 11 (ONM 1997, clasa a VIII-a)\r\n\r\nbq. Se dă un paralelipiped $ABCDEFGH$, cu $AB = 5$, $BC = 4$, $AE = 3$. Se cere să determinăm poziţia unui punct $M$ ce aparţine segmentului $BF$ cu proprietatea că suma $AM + MG$ este minimă.\r\n\r\n!< transformari-geometrice?aplicatie-11.1.png 55%!\r\n\r\nh3. Rezolvare\r\n\r\n!> transformari-geometrice?aplicatie-11.2.png 55%!\r\n\r\nPentru această problemă ne putem imagina o soluţie analitică în care vrem să minimizăm funcţia $AM + MG$ care depinde de coordonata $y$, dar o asemenea rezolvare nu ar fi fost accesibilă unui elev de clasa a VIII-a. O soluţie elegantă şi simplă este următoarea. Desfăşurăm în plan feţele $ABFE$ şi $BCGD$. Astfel se formează dreptunghiul $ACGE$, unde $AC = 9$ şi $AE = 3$. Acum este clar că punctul $M$ trebuie să fie intersecţia diagonalei $AG$ cu $FB$. De aici putem găsi foarte uşor că $BM = 5/3$.\r\n\r\nh2(#aplicatia-12). Aplicaţia 12 (TopCoder)\r\n\r\nbq. Pe partea frontală a unui zgârie-nor foarte înalt, ce are forma unui paralelipiped, cu baza un pătrat de latura $200$ de metri, este situat un păianjen. Acesta vrea să mănânce o muscă situată pe faţa din dreapta a zgârie-norului. Ştiind coordonatele păianjenului şi ale muştei vi se cere să determinaţi drumul cel mai scurt pe care îl poate face păianjenul ca să mănânce musca iar întreaga deplasare a lui să fie pe suprafaţa zgârie-norului (coordonatele gângăniilor se măsoară relativ la colţul stânga sus al feţei pe care se află fiecare).\r\n\r\nh3. Rezolvare:\r\n\r\nDesfăşurăm paralelipipedul în toate modurile posibile (aşa cum vedem în figură) şi alegem dintre toate drumurile soluţia optimă.\r\n\r\n!< transformari-geometrice?aplicatie-12.1.png 55%!\r\n\r\n!> transformari-geometrice?aplicatie-12.2.png 55%!\r\n\r\nh2(#aplicatia-13). Aplicaţia 13\r\n\r\n!< transformari-geometrice?aplicatie-13.1.png 75%!\r\n\r\nbq. Se dă un triunghi $ABC$ şi trei drepte $d{~1~}$, $d{~2~}$ şi $d{~3~}$ care nu sunt paralele între ele două câte două. Se cere să se determine un triunghi înscris în triunghiul $ABC$ ce are laturile paralele cu dreptele $d{~1~}$, $d{~2~}$ respectiv $d{~3~}$.\r\n\r\nh3. Rezolvare:\r\n\r\nConstruim un triunghi $D’E’F’$ ce are laturile paralele cu dreptele $d{~1~}$, $d{~2~}$ şi $d{~3~}$, iar punctul $E’$ aparţine semidreptei $[AC$ şi punctul $F’$ aparţine semidreptei $[AB$. Acum fixăm un punct $D$ în intersecţia lui $AD’$ cu $BC$ şi în acest punct ducem două drepte paralele cu dreptele $d{~1~}$ şi $d{~2~}$. Aceste drepte vor intersecta laturile triunghiului în punctele $F$ şi $E$. În omotetia de centru $A$ şi raport $AD / AD’$ triunghiul $D’E’F’$ se transformă în $DEF$, care este un triunghi ce respectă condiţia din enunţ.\r\n\r\np.  \r\n\r\nh2(#aplicatia-14). Aplicaţia 14: \'Triangular Square\':http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=82&page=show_problem&problem=1666 (UVa)\r\n\r\nbq. Se dă un triunghi $ABC$. Vrem să găsim aria maximă a unui pătrat situat în întregime în interiorul triunghiului. În imagine avem un pătrat în interiorul unui triunghi, dar acesta nu este de arie maximă. De exemplu într-un triunghi cu laturile de dimensiuni $6$, $6$ şi $6$, aria maximă este $7.754051$.\r\n\r\n!> transformari-geometrice?aplicatie-14.1.png 75%!\r\n\r\nh3. Rezolvare:\r\n\r\nPornim de la presupunerea intuitivă că cel mai mare pătrat ce se poate plasa în interiorul unui triunghi trebuie să aibă una din laturi pe o latură a triunghiului. Astfel, pentru a determina pătratul de arie maximă avem trei posibilităţi de aşezare pe laturile triunghiului. Pentru o aşezare fixată putem afla uşor pătratul maxim din interiorul triunghiului ce are două varfuri pe latura $BC$. O modalitate ar fi să desenăm un pătrat $M’N’P’Q’$ ce are punctele $Q’$ şi $P’$ pe semidreapta $[BC$ şi punctul $M’$ pe semidreapta $[BA$. După care, luăm punctul $N$ ca intersecţie a dreptei $BN’$ cu $AC$. Găsim pătratul $MNPQ$ ca fiind omoteticul pătratului $M’N’P’Q’$ după omotetia de centru $B$ şi raport $BN / BN’$. Altă modalitate de construcţie a pătratului ar fi cea prezentată în a doua figură, adică: se construieşte în exterior, pe latura $BC$ a triunghiului, un pătrat $BCQ’P’$, se determineă punctele $P$ şi $Q$ ca şi intersecţii al segmentului $AQ’$ cu $BC$ şi al segmentului $AP’$ cu $BC$. Pătratul $MNPQ$ va fi omoteticul pătratului $BCP’Q’$, după omotetia de centru $A$ şi raport $QP / BC$.\r\n',3146,'public',NULL,NULL),('notiuni-de-geometrie-si-aplicatii','Notiuni elementare de geometrie si aplicatii','2007-06-22 12:40:45','2009-06-30 16:35:51','h1. Notiuni elementare de geometrie si aplicatii\r\n\r\n(Categoria _Geometrie_, Autori _Savin Tiberiu_ si _Sima Mihai Cotizo_)\r\n\r\n(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* 0. Introducere\r\n* \'1. Arii\':notiuni-de-geometrie-si-aplicatii/arii\r\n** - triunghi\r\n** - patrulater\r\n** - poligon\r\n* \'2. Drepte\':notiuni-de-geometrie-si-aplicatii/drepte\r\n** - elemente generale\r\n** - ecuaţii\r\n** - distanţa punct-linie\r\n** - distanţa punct-segment(semidreaptă)\r\n* \'3. Punct în poligon\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon\r\n** - crossing-number\r\n** - winding-number (?)\r\n** - şmenuri\r\n* \'4. Intersecţii de drepte şi segmente\':notiuni-de-geometrie-si-aplicati/intersectii-drepte-si-segmente\r\n* 5. Distanţe\r\n** - între linii\r\n** - între segmente şi semidrepte\r\n** - cea mai mică distanţă între două mobile\r\n* 6. Bounding ...\r\n** - ... box\r\n** - ... circle\r\n* \'7. Infaşurătoare convexă\':notiuni-de-geometrie-si-aplicatii/infasuratoare-convexa\r\n* 8. Puncte extreme şi distanţa poligon-linie\r\n* 9. Tangente\r\n* 10. Probleme de concurs\r\n\r\n**Geometria** (din greaca veche - {_geo_}=pământ, {_metria_}=a măsura) este partea matematicii care se ocupă cu problemele privind dimensiunile, forma şi poziţia figurilor. Introducerea coordonatelor de către René Descartes a dus la dezvoltarea geometriei analitice, a cărei scop devine studierea geometriei prin funcţii şi ecuaţii.\r\n\r\nÎn problemele de olimpiadă este necesară cunoaşterea câtorva noţiuni şi idei de bază pentru a facilita găsirea unui algoritm eficient într-un timp scurt. Prezentul articol are ca scop explicarea acestor noţiuni privitoare la geometria plană (2D) şi studierea câtorva idei aplicate în problemele de concurs.\r\n\r\n',3270,'public',NULL,NULL),('notiuni-de-geometrie-si-aplicatii/arii','Arii','2009-06-28 22:36:19','2009-06-30 19:41:29','(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'0. Introducere\':notiuni-de-geometrie-si-aplicatii#introducere\r\n* \'**1. Arii**\':notiuni-de-geometrie-si-aplicatii/arii\r\n** \'- triunghi\':notiuni-de-geometrie-si-aplicatii/arii#triunghi\r\n** \'- patrulater\':notiuni-de-geometrie-si-aplicatii/arii#patrulater\r\n** \'- poligon\':notiuni-de-geometrie-si-aplicatii/arii#poligon\r\n* \'2. Drepte\':notiuni-de-geometrie-si-aplicatii/drepte\r\n** \'- elemente generale\':notiuni-de-geometrie-si-aplicatii/drepte#general\r\n** \'- ecuaţii\':notiuni-de-geometrie-si-aplicatii/drepte#ecuatii\r\n** \'- distanţa punct-linie\':notiuni-de-geometrie-si-aplicatii/drepte#dpl\r\n** \'- distanţa punct-segment(semidreaptă)\':notiuni-de-geometrie-si-aplicatii/drepte#dps\r\n* \'3. Punct în poligon\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon\r\n** \'- crossing-number\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon#cn\r\n** \'- winding-number (?)\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon#wn\r\n** \'- şmenuri\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon#smen\r\n* \'4. Intersecţii de drepte şi segmente\':notiuni-de-geometrie-si-aplicati/intersectii-drepte-si-segmente\r\n* 5. Distanţe\r\n** - între linii\r\n** - între segmente şi semidrepte\r\n** - cea mai mică distanţă între două mobile\r\n* 6. Bounding ...\r\n** - ... box\r\n** - ... circle\r\n* \'7. Infaşurătoare convexă\':notiuni-de-geometrie-si-aplicatii/infasuratoare-convexa\r\n* 8. Puncte extreme şi distanţa poligon-linie\r\n* 9. Tangente\r\n* 10. Probleme de concurs\r\n\r\nh2. 1. Arii\r\n\r\nNoţiunea de arie este una de bază în geometria analitică. Este necesară însă o prezentare a diferitelor metode de a calcula ariile in contextul prelucrarii datelor pe calculator.\r\n\r\nh2(#triunghi). Aria unui triunghi\r\n\r\nÎn determinarea ariei unui triunghi se poate folosi **formula lui Heron**:\r\n<tex>\\begin{math} A=\\sqrt{s\\cdot(s-a)\\cdot(s-b)\\cdot(s-c)}\\end</tex>\r\nÎn formulă, $s$ reprezintă semiperimetrul triunghiului, iar $a, b, c$ laturile triunghiului. Această formulă apare şi într-o altă formă, mult mai adecvată algoritmilor prin faptul că se evită calcularea lungimii laturilor cu radical:\r\n<tex>\\begin{math} A=\\frac{1}{4}\\sqrt{4a^{2}b^{2}-\\left(a^{2}+b^{2}-c^{2}\\right)^{2}}\\end</tex>\r\n\r\nÎn contextul geometriei vectoriale, modulul produsului vectorial a doi vectori o reprezintă aria paralelogramului cuprins între vectori. Aplicând raţionamentul la triunghiuri, obţinem relaţia:\r\n<tex>\\begin{math} A = \\frac{1}{2}\\|\\vec{v}\\times\\vec{w}\\| = \\frac{1}{2}\\cdot abs\\left(\\left|\\begin{array}{ccc}\r\n\\ x_1 & y_1 & 1\\\\\r\nx_2 & y_2 & 1\\\\\r\nx_3 & y_3 & 1\\end{array}\\right|\\right)\\end{math}</tex>\r\n\r\n!notiuni-de-geometrie-si-aplicatii/arii?vector.jpg!\r\n\r\n\r\nh2(#poligon). Aria unui poligon\r\n\r\nAria unui poligon convex cu $n$ laturi o putem calcula foarte usor folosind formula pentru aria unui triunghi astfel.\r\n\r\n<tex>\\displaystyle \\sum_{i=2}^{i<n} Arie(p_{1},p_{i},p_{i+1})</tex>\r\n\r\nUnde <tex>Arie(p_{x},p_{y},p_{z})</tex> reprezinta aria triunghiului determinat de punctele $p{~x~}$, $p{~y~}$, $p{~z~}$. \r\n\r\nAria unui poligon concav se calculeaza la fel doar ca atunci cand calculam <tex>Arie(p_{1},p_{i},p_{i+1}</tex> renuntam la abs, si tinem minte semnul determinantului si luam valoarea absoluta dupa ce am calculat intreaga suma.',3270,'public',NULL,NULL),('notiuni-de-geometrie-si-aplicatii/arii','Arii','2009-06-28 22:36:19','2009-06-30 22:17:16','(toc){width: 27em}*{text-align:center} *Conţinut:*\r\n* \'0. Introducere\':notiuni-de-geometrie-si-aplicatii#introducere\r\n* \'**1. Arii**\':notiuni-de-geometrie-si-aplicatii/arii\r\n** \'- triunghi\':notiuni-de-geometrie-si-aplicatii/arii#triunghi\r\n** \'- patrulater\':notiuni-de-geometrie-si-aplicatii/arii#patrulater\r\n** \'- poligon\':notiuni-de-geometrie-si-aplicatii/arii#poligon\r\n* \'2. Drepte\':notiuni-de-geometrie-si-aplicatii/drepte\r\n** \'- elemente generale\':notiuni-de-geometrie-si-aplicatii/drepte#general\r\n** \'- ecuaţii\':notiuni-de-geometrie-si-aplicatii/drepte#ecuatii\r\n** \'- distanţa punct-linie\':notiuni-de-geometrie-si-aplicatii/drepte#dpl\r\n** \'- distanţa punct-segment(semidreaptă)\':notiuni-de-geometrie-si-aplicatii/drepte#dps\r\n* \'3. Punct în poligon\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon\r\n** \'- crossing-number\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon#cn\r\n** \'- winding-number (?)\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon#wn\r\n** \'- şmenuri\':notiuni-de-geometrie-si-aplicatii/punct-in-poligon#smen\r\n* \'4. Intersecţii de drepte şi segmente\':notiuni-de-geometrie-si-aplicati/intersectii-drepte-si-segmente\r\n* 5. Distanţe\r\n** - între linii\r\n** - între segmente şi semidrepte\r\n** - cea mai mică distanţă între două mobile\r\n* 6. Bounding ...\r\n** - ... box\r\n** - ... circle\r\n* \'7. Infaşurătoare convexă\':notiuni-de-geometrie-si-aplicatii/infasuratoare-convexa\r\n* 8. Puncte extreme şi distanţa poligon-linie\r\n* 9. Tangente\r\n* 10. Probleme de concurs\r\n\r\nh2. 1. Arii\r\n\r\nNoţiunea de arie este una de bază în geometria analitică. Este necesară însă o prezentare a diferitelor metode de a calcula ariile in contextul prelucrarii datelor pe calculator.\r\n\r\nh2(#triunghi). Aria unui triunghi\r\n\r\nÎn determinarea ariei unui triunghi se poate folosi **formula lui Heron**:\r\n<tex>\\begin{math} A=\\sqrt{s\\cdot(s-a)\\cdot(s-b)\\cdot(s-c)}\\end</tex>\r\nÎn formulă, $s$ reprezintă semiperimetrul triunghiului, iar $a, b, c$ laturile triunghiului. Această formulă apare şi într-o altă formă, mult mai adecvată algoritmilor prin faptul că se evită calcularea lungimii laturilor cu radical:\r\n<tex>\\begin{math} A=\\frac{1}{4}\\sqrt{4a^{2}b^{2}-\\left(a^{2}+b^{2}-c^{2}\\right)^{2}}\\end</tex>\r\n\r\nÎn contextul geometriei vectoriale, modulul produsului vectorial a doi vectori o reprezintă aria paralelogramului cuprins între vectori. Aplicând raţionamentul la triunghiuri, obţinem relaţia:\r\n<tex>\\begin{math} A = \\frac{1}{2}\\|\\vec{v}\\times\\vec{w}\\| = \\frac{1}{2}\\cdot abs\\left(\\left|\\begin{array}{ccc}\r\n\\ x_1 & y_1 & 1\\\\\r\nx_2 & y_2 & 1\\\\\r\nx_3 & y_3 & 1\\end{array}\\right|\\right)\\end{math}</tex>\r\n\r\n!notiuni-de-geometrie-si-aplicatii/arii?vector.jpg!\r\n\r\n\r\nh2(#patrulater). Aria unui patrulater\r\n\r\nDupă cum am văzut în cazul unui triunghi, aria unui paralelogram $ABCD$ este egală cu modulul produsului vectorial al vectorilor reprezentaţi de 2 laturi neparalele.\r\n<tex>\r\n\\begin{math} \r\nA = \\|\\overrightarrow{AB}\\times\\overrightarrow{AD}\\|\r\n\\end{math}\r\n</tex>\r\n\r\nPentru un patrulater oarecare $ABCD$, putem considera {$M{~1~}$}, {$M{~2~}$}, {$M{~3~}$}, {$M{~4~}$} mijloacele laturilor acestuia. Se poate demonstra că patrulaterul {$M{~1~}M{~2~}M{~3~}M{~4~}$} este un paralelogram cu aria jumătate din aria lui $ABCD$:\r\n<tex> \\begin{math}\r\nA = 2\\cdot\\|\\left(\\overrightarrow{r_{M_{2}}}-\\overrightarrow{r_{M_{1}}}\\right)\\times\\left(\\overrightarrow{r_{M_{4}}}-\\overrightarrow{r_{M_{1}}}\\right)\\|\\end{math}</tex>\r\n<tex> \\begin{math}\r\nA = 2\\cdot\\|\r\n\\left(\\frac{ \\vec{r_{B}}+\\vec{r_{C}} }{2}-\\frac{ \\vec{r_{A}}+\\vec{r_{B}} }{2}\\right)\r\n\\times\r\n\\left(\\frac{ \\vec{r_{A}}+\\vec{r_{D}} }{2}-\\frac{ \\vec{r_{A}}+\\vec{r_{B}} }{2}\\right)\\|\r\n\\end{math} </tex>\r\n<tex>\\begin{math}\r\nA = \\frac{1}{2}\\cdot\\|\r\n\\left(\\overrightarrow{r_{C}}-\\overrightarrow{r_{A}}\\right)\\times\\left(\\overrightarrow{r_{D}}-\\overrightarrow{r_{B}}\\right)\r\n\\|\r\n\\end{math}</tex>\r\n<tex>\\begin{math}A = \\frac{1}{2}\\cdot\\|\\overrightarrow{AC}\\times\\overrightarrow{BD}\\|\\end{math}</tex>\r\n\r\n!notiuni-de-geometrie-si-aplicatii/arii?patrulater.jpg!\r\n\r\nh2(#poligon). Aria unui poligon\r\n\r\nPentru a calcula aria unui poligon oarecare {$A{~1~}A{~2~}A{~3~}..A{~n~}$}, vom considera un punct P arbitrar ales în plan. Vom \"împărţi\" poligonul în triunghiuri de forma $PA{~i~}A{~i+1~}$ (considerăm că A{~1~}=A{~n+1~}) şi vom calcula \"aria cu semn\" $T{~i~}$ a fiecărui triunghi (în formula ariei nu vom folosi funcţia de valoare absolută). Distingem în acest moment două cazuri:\r\n\r\n* Poligonul are vârfurile orientate trigonometric. Pentru fiecare latură \"spre dreapta\", aria $T{~i~}$ corespunzătoare va fi negativă, iar pentru fiecare latură \"spre stânga\", aria $T{~i~}$ corespunzătoare va fi pozitivă.\r\n* Poligonul are vârfurile orientate antitrigonometric. Pentru fiecare latură \"spre dreapta\", aria $T{~i~}$ corespunzătoare va fi pozitivă, iar pentru fiecare latură \"spre stânga\", aria $T{~i~}$ corespunzătoare va fi negativă.\r\n\r\nÎn ambele cazuri, efectuând suma algebrică a ariilor $T{~i~}$ vom obţine aria poligonului (deoarece ariile negative vor \"anula\" zonele corespunzătoare ariilor pozitive care se află în afara poligonului).\r\n\r\n!notiuni-de-geometrie-si-aplicatii/arii?poligon.jpg!\r\n\r\nDacă alegem punctul $P(0,0)$, fiecare arie $T{~i~}$ devine: \r\n<tex>\\begin{math}T_{i} = \\frac{1}{2}\\cdot abs\\left(\\left|\\begin{array}{ccc}\r\n\\ 0 & 0 & 1\\\\\r\nx_i & y_i & 1\\\\\r\nx_i+1 & y_i+1 & 1\\end{array}\\right|\\right) = \\frac{1}{2}\\cdot\\left(x_i\\cdot y_{i+1}-x_{i+1}\\cdot y_i\\right)\r\n\\end{math}</tex>\r\n\r\nFormula finală devine:\r\n<tex>\\begin{math}\r\nA = \\displaystyle\\sum_{i=1}^n T_i = \\frac{1}{2}\\cdot\\displaystyle\\sum_{i=1}^n \\left(x_i\\cdot y_{i+1}-x_{i+1}\\cdot y_i\\right)\r\n\\end{math}</tex>\r\n\r\nAceastă formulă reprezintă \"aria cu semn\" a poligonului (o arie pozitivă indică parcurgerea vârfurilor în ordine trigonometrică, iar o arie negativă, parcurgerea in ordine antitrigonometrică).',3270,'public',NULL,NULL),('planificare/camp-chuckie','Coding Camp Chuckie','2007-02-17 19:46:22','2007-02-17 19:46:22','h1. Coding Camp Chuckie\r\n\r\n_(pagina creata pentru arhiva / din considerente istorice)_\r\n\r\nCoding camp organizat la Valenii de Munte (Stanciu Valentin) cu scopul de a porni proiectul infoarena v2.\r\n\r\nOrganizarea s-a facut \'direct pe wiki-ul infoarena.devnet.ro\':http://infoarena.devnet.ro/wiki/index.php/Coding_Camp_2006.\r\n\r\n\'Iata si cateva poze (multumim, Vali!)\':http://picasaweb.google.com/valentin.stanciu/IACodingCamp?authkey=IxCKdtsm11toYdiAcjAd7TNVR2c.',13,'public',NULL,NULL),('programare-dinamica-introducere','programare-dinamica-introducere','2009-07-14 09:09:43','2009-07-14 09:09:43','h1. Introducere in programarea dinamica ',1430,'public',NULL,NULL),('blog/problema-saptamanii-stream-solutie','Problema saptamanii - Stream (Solutie)','2009-07-27 01:33:38','2009-07-27 08:38:14','Am gasit problema in cartea \"Introduction to Algorithms: A Creative Approach\" de Udi Manber. Udi e VP of engineering la Google si daca stiti de suffix arrays, Udi a publicat cum se poate face eficient operatia de LCP (longest common prefix). Cartea imi place mai mult decat Cormen-ul pentru ca partea de teorie e orientata mai mult spre intelegerea lucrurilor decat spre demonstratii matematice stufoase si pe langa asta fiecare capitol are foarte multe probleme interesante la sfarsit. Eu cred ca problemele sunt esentiale cand inveti un subiect tehnic, pentru ca intelegi bine ideile din un domeniu cand esti obligat sa le aplici in contexte diverse.\r\n\r\nPana sa vad cerinta din cartea respectiva credeam ca problema selectiei celor mai mici k numere din un stream se poate face doar in O(n log k) daca esti obligat sa folosesti O(k) memorie, dar citind-o mi-am dat seama ca nu e greu sa scoti o solutie in O(n) timp si O(k) spatiu. E o diferenta mare intre a sti ca o problema e rezolvabila sau nu :), de aceea munca de cercetare e foarte dura.\r\n\r\nCei ce au rezolvat corect problema sunt urmatorii: Stefan Istrate, Andrei Marius Teodorescu, Adrian Vladu, Marius Pungaru, Marius Buzea, Daniel Pasaila si Alexandru Mosoi.\r\n\r\nVa dau si solutia:\r\n_Pastram un sir A in care avem cele mai mici k numere din stream pana la momentul curent. Apoi la fiecare pas citim k noi elemente din stream in sirul B. Acum in sirul C punem elementele din ambele siruri si aplicam algoritmul de gasire a medianei algoritm ce va avea complexitate O(k), vom pastra in A elementele din C mai mici sau egale cu mediana. Astfel obtinem un algoritm de complexitate O(n) timp si O(k) spatiu._',58,'private',NULL,NULL),('blog/problema-saptamanii-mediana-de-pe-disc','Problema saptamanii - Mediana pe disc','2009-07-27 23:27:17','2009-07-27 23:34:29','Cum numarul de rezolvari atat bune cat si rele a fost mare la problema anterioara, va mai zic o problema cu statistici de ordine pe care am auzit-o de la Mihai Patrascu.\r\n\r\n_Se dau n numere intregi scrise pe disc. Se cere sa se detemine mediana lor in timp O(n), citind fiecare numar de pe disc de O(1) ori si folosind O(sqrt(n)) memorie totala. Mediana unui sir de numere cu n elemente e elementul de pe pozitia n/2 din sirul rezultat in urma sortarii sirului initial._',58,'protected',4054,NULL),('arhiva','Arhiva de probleme','2006-11-11 18:59:35','2009-02-19 23:44:52','h1. Arhiva de probleme\r\n\r\nArhiva de probleme infoarena contine peste 800 de probleme. Vezi si \'clasamentul arhivei\':clasament-arhiva.\r\n\r\nh2. Lista de probleme\r\n\r\n==Tasks(round_id=\"arhiva\" show_numbers=\"true\" score=\"1\") ==\r\n\r\nh2. Ultimele discutii despre arhiva\r\n\r\n== SmfTopics(board_id=\"1\" count=\"30\") ==\r\n',1792,'protected',NULL,NULL),('newsletter/summer-2009-1','Summer Challenge 2009, Runda 1','2009-07-19 20:11:35','2009-07-22 22:21:24','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎn toiul vacanţei de vară, feriţi de caniculă, la umbra monitoarelor, infoarena se gândeşte la tine! :)\r\n\r\nTe invităm să participi la seria de concursuri Summer Challenge 2009. Vom organiza 3 runde online, de câte 5h fiecare, cu probleme de dificultate variată.\r\n\r\nSummer Challenge este o ocazie bună de antrenament pentru tine (dacă nu eşti deja la mare :P), dar şi un ultim test pentru delegaţia României la Olimpiada Internaţională de Informatică 2009 (Bulgaria). Cu această ocazie, după o lungă perioadă de pauză, doi dintre veteranii noştri se întorc în arenă: \'Bogdan Tătăroiu\':utilizator/bogdan2412 şi \'Cosmin Gheorghe\':utilizator/gcosmin. Întrece-te cu ei!\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Runda 1 se desfăşoară\r\n*Sâmbătă, 25 Iulie 2009, orele 10^00^ - 15^00^*. |\r\n\r\nOrganizatorii primei runde online Summer Challenge 2009 sunt:\r\n\r\n* \'Andrei Grigorean\':utilizator/wefgef\r\n* \'Marius Stroe\':utilizator/marius\r\n* \'Paul - Dan Baltescu\':utilizator/pauldb\r\n\r\nPentru informaţii suplimentare (cum particip, întrebări etc.) vizitează \'pagina concursului\':summer-challenge-2009.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"summer-challenge-2009/runda-1\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}.  Concursurile internaţionale de informatică din 2009\r\n\r\nÎn perioada 28 iunie - 8 iulie a avut loc Olimpiada Pluridisciplinară din Yakutia. Echipa noastră s-a prezentat excelent:\r\n\r\n* \'Andrei Purice\':utilizator/protoman - AUR ABSOLUT\r\n* \'Teodor Pripoae\':utilizator/toni2007 - AUR\r\n* \'Andrei Poenaru\':utilizator/andreyp - ARGINT\r\n\r\nTot la începutul acestei veri, România a găzduit cea de a XVI-a ediţie a \'Olimpiadei de Informatică a Europei Centrale\':http://ceoi2009.ro/. Concurenţii noştri au obţinut următoarele medalii:\r\n\r\n* \'Cosmin Gheorghe\':utilizator/gcosmin - ARGINT\r\n* \'Bogdan Tătăroiu\':utilizator/bogdan2412 - ARGINT\r\n* \'Marius Drăguş\':utilizator/mariusdrg - ARGINT\r\n* \'Andrei Pârvu\':utilizator/andrei.12 - ARGINT\r\n* \'Şerban Andrei Stan\':utilizator/savim - ARGINT\r\n* \'Andrei Antonescu\':utilizator/andrei-alpha - BRONZ\r\n* \'Andrei Puni\':utilizator/crawler - BRONZ\r\n* \'Flaviu Pepelea\':utilizator/Pepelea_Flaviu - BRONZ\r\n* \'Victor Ionescu\':utilizator/vanila_CPP - BRONZ\r\n\r\nFelicitări băieţi! Suntem mândri de voi!\r\n\r\nA XXI-a ediţie a \'Olimpiadei Internaţionale de Informatică\':http://ioi2009.org/ este găzduită de Bulgaria (în Plovdiv) şi se desfăşoară în perioada 8-15 august.\r\n\r\nUrăm succes delegaţiei României la IOI 2009! Sperăm ca reprezentanţii noştri să facă ce ştiu cel mai bine, să obţină rezultate excepţionale.\r\n\r\nLotul României este condus de către Prof. Constatin Galaţan şi de către As. Univ. Dr. \'Mugurel Ionuţ Andreica\':utilizator/mugurelionut. Participanţi:\r\n\r\n* \'Cosmin Gheorghe\':utilizator/gcosmin\r\n* \'Bogdan Tătăroiu\':utilizator/bogdan2412\r\n* \'Marius Drăguş\':utilizator/mariusdrg\r\n* \'Andrei Puni\':utilizator/crawler\r\n\r\nVă urăm multă baftă! Să veniţi înapoi cu medalii cât mai strălucitoare!\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==',2028,'protected',NULL,NULL),('summer-challenge-2009/solutii/runda-2/biti4','summer-challenge-2009/solutii/runda-2/biti4','2009-07-29 13:29:13','2009-07-29 14:12:36','h2(#biti4). \'Biti4\':problema/biti4\r\n\r\nPentru început, considerăm un şir binar canonic ca fiind un şir _corect_ şi orice două poziţii consecutive care conţin cifre diferite o _schimbare de cifră_.\r\n\r\nVom determina succesiv cifrele şirului căutat. Definim $cw(a{~1~}a{~2~}..a{~m~})$ ca fiind numărul cuvintelor corect care au prefixul $a{~1~}a{~2~}..a{~m~}$. Prefixul de lungime $0$ îl vom nota cu $eps$. Astfel, modelul soluţiei este următorul:\r\n\r\n== code(cpp) |\r\nprefix := eps;\r\n==\r\n\r\n',3146,'private',NULL,NULL),('summer-challenge-2009/solutii/runda-2/padurari','Solutie Padurari','2009-07-29 13:29:45','2009-07-31 12:59:37','h2(#padurari). \'Padurari\':problema/padurari\r\n\r\nO primă observaţie aproape evidentă este că pădurarii vor alege mereu copaci consecutivi. Pornind de la această observaţie se poate construi un algoritm trivial bazat pe programare dinamică având complexitatea $O(N*K)$ şi care ar fi obţinut $20$ de puncte.\r\nPentru a ajunge la un algoritm eficient, o abordare posibila este sa modelam problema ca un graf. Nodurile vor fi reprezentate de copaci, iar muchiile de posibilitatile de alegere ale padurarilor. Astfel, va exista muchie intre doua noduri daca si numai daca acestea sunt consecutive. Se observa usor ca acest graf este unul bipartit. Problema se reduce acum la gasirea unui cuplaj de cardinal $K$ si cost minim in graful construit. Daca studiem modul de comportare a algoritmului pentru determinarea cuplajului de cost minim pe acest graf, se observa ca o muchie de intoarcere va fi folosita doar in cazul in care dorim ulterior sa selectam cele doua muchii vecine. Folosind aceasta observatie, putem prevedea acest pas, inlocuind muchia de intoarcere si cele doua muchii vecine, cu o noua muchie ca in desenul urmator:',1792,'public',NULL,NULL),('summer-challenge-2009/solutii/runda-2/centru2','summer-challenge-2009/solutii/runda-2/centru2','2009-07-29 13:30:14','2009-07-31 16:27:40','h2(#centru2). \'Centru2\':problema/centru2\r\n\r\nConsideram intervalele noduri ale unui graf si vom adauga muchie intre doua noduri daca intervalele corespunzatoare se suprapun. Pe acest graf, ne propunem sa determinam cea mai mica lexicografic multime independenta de varfuri (maximum independence set sau $MIS$). \r\nPentru claritatea explicatiei vom presupune ca nu exista intervale complet incluse unul in celalalt. Algoritmul care trateaza si acest caz nu contine modificari relevante fata de cel prezentat in continuare.\r\nSortam intervalele dupa capatul din dreapta. Definim $D[i] = min{j > i | i si j nu sunt legate printr-o muchie}$. Vom construi o subrutina $MIS{i,j}$ pe care o vom utiliza ulterior si care va determina cardinalul $MIS$-ului varfurilor din graf curprinse intre $i$ si $j$, $i &le; j$. Este usor de observat ca $MIS{i,j} = max{k | D^k^[i] &le; j}$. Vom construi o matrice <tex>R[i][j] = D^{2^i}[j]</tex>, cu ajutorul careia vom determina bitii rezultatului (asemanator cu modul de functionare al cautarii binare bazate pe ideea lui Mihai Patrascu prezentata in acest \'articol\':multe-smenuri-de-programare-in-cc-si-nu-numai). \r\nParcurgem nodurile in ordinea initiala. Fie $i{~0~}$ primul nod. Fie $i, i+1, ..., j$ vecinii nodului $i$. Acestia pot fi determinati in $O(logN)$ folosind cautare binara. Nodul $i{~0~}$ poate face parte din solutie daca si numai daca $MIS{1, i-1} + 1 + MIS{j+1, N} = MIS{1, N}$ $(*)$. Aceasta verificare poate fi facuta in complexitate $O(logN)$ folosind subrutina descrisa mai sus. Sa presupunem in continuare ca nodul $i{~0~}$ a trecut testul. Luam apoi nodul $i{~1~}$, urmatorul in ordinea initiala. Daca $i{~1~}$ apartine intervalului $[i, j]$, el nu apartine solutiei deoarece ar intra in conflict cu nodul ales precedent. Sa presupunem ca $i{~1~}$ apartine intervalului $[j+1, N]$ si vecinii acestuia sunt $p, p+1, ..., q$, unde $j < p &le; q &le; N$. Trebuie din nou verificat daca $MIS{j+1, N} = MIS{j+1, p-1} + 1 + MIS{q+1, N}$. Este intuitiv ca acest procedeu conduce la obtinerea $MIS$-ului minim lexicografic.\r\nPentru a realiza operatiile descrise mai sus in timp logaritmic este nevoie de un arbore de intervale cu ajutorul caruia sa verificam daca noile intervale se intersecteaza cu cele vechi si un arbore binar echilibrat de cautare ({$AVL$} sau $set$) pentru a localiza intervalele pe care trebuie facute verificarile.',1792,'private',NULL,NULL),('summer-challenge-2009/solutii/runda-2/padurari','Soluție Pădurari','2009-07-29 13:29:45','2009-08-01 08:29:34','h2(#padurari). \'Padurari\':problema/padurari\r\n\r\nO primă observaţie aproape evidentă este că pădurarii vor alege mereu copaci consecutivi. Pornind de la această observaţie se poate construi un algoritm trivial bazat pe programare dinamică având complexitatea $O(N*K)$ şi care ar fi obţinut $20$ de puncte.\r\nPentru a ajunge la un algoritm eficient, o abordare posibilă este să modelăm problema ca un graf. Nodurile vor fi reprezentate de copaci, iar muchiile de posibilităţile de alegere ale pădurarilor. Astfel, va exista muchie între două noduri dacă şi numai dacă acestea sunt consecutive. Se observa uşor ca acest graf este unul bipartit. Problema se reduce acum la găsirea unui cuplaj de cardinal $K$ si cost minim în graful construit. Daca studiem modul de comportare al algoritmului pentru determinarea cuplajului de cost minim pe acest graf, se observă ca o muchie de întoarcere va fi folosită doar în cazul în care dorim să selectăm ulterior cele două muchii vecine. Folosind această observaţie, putem prevedea comportarea algoritmului în acest pas, înlocuind muchia de întoarcere ce ar trebui introdusă şi cele două muchii vecine, cu o nouă muchie ca in desenul următor:\r\n\r\np=. ! summer-challenge-2009/solutii/runda-2/padurari?padurari.png 55%!\r\n\r\nAcum se poate construi un nou algoritm care selectează la fiecare din cei $K$ pasi muchia minimă din graf si face transformările necesare. Inserările şi ştergerile muchiilor se pot face în timp logaritmic folosind un heap, astfel algoritmul având complexitatea $O(K*logN)$.\r\nExistă un caz particular ce trebuie tratat cu atenţie. Când muchia aleasă este prima sau ultima din graf, abordarea de mai sus nu funcţionează. Totuşi, în acest caz este uşor de observat că va fi mereu de preferat să alegem această muchie în locul vecinei, deoarece are costul mai mic şi nu crează restricţii asupra altor muchii din graf.',1792,'private',NULL,NULL),('summer-challenge-2009/solutii/runda-2/padurari','Soluție Pădurari','2009-07-29 13:29:45','2009-08-01 08:30:53','h2(#padurari). \'Padurari\':problema/padurari\r\n\r\nO primă observaţie aproape evidentă este că pădurarii vor alege mereu copaci consecutivi. Pornind de la această observaţie se poate construi un algoritm trivial bazat pe programare dinamică având complexitatea $O(N*K)$ şi care ar fi obţinut $20$ de puncte.\r\nPentru a ajunge la un algoritm eficient, o abordare posibilă este să modelăm problema ca un graf. Nodurile vor fi reprezentate de copaci, iar muchiile de posibilităţile de alegere ale pădurarilor. Astfel, va exista muchie între două noduri dacă şi numai dacă acestea sunt consecutive. Se observa uşor ca acest graf este unul bipartit. Problema se reduce acum la găsirea unui cuplaj de cardinal $K$ si cost minim în graful construit. Daca studiem modul de comportare al algoritmului pentru determinarea cuplajului de cost minim pe acest graf, se observă ca o muchie de întoarcere va fi folosită doar în cazul în care dorim să selectăm ulterior cele două muchii vecine. Folosind această observaţie, putem prevedea comportarea algoritmului în acest pas, înlocuind muchia de întoarcere ce ar trebui introdusă şi cele două muchii vecine, cu o nouă muchie ca in desenul următor:\r\n\r\np=. ! summer-challenge-2009/solutii/runda-2/padurari?padurari.png 55%!\r\n\r\nAcum se poate construi un nou algoritm care selectează la fiecare din cei $K$ pasi muchia minimă din graf si face transformările necesare. Inserările şi ştergerile muchiilor se pot face în timp logaritmic folosind un \'heap\':problema/heapuri, astfel algoritmul având complexitatea $O(K*logN)$.\r\nExistă un caz particular ce trebuie tratat cu atenţie. Când muchia aleasă este prima sau ultima din graf, abordarea de mai sus nu funcţionează. Totuşi, în acest caz este uşor de observat că va fi mereu de preferat să alegem această muchie în locul vecinei, deoarece are costul mai mic şi nu crează restricţii asupra altor muchii din graf.',1792,'private',NULL,NULL),('summer-challenge-2009/solutii/runda-2/simpla','Soluție Simpla','2009-08-01 10:15:59','2009-08-01 11:40:00','h2(#simpla). \'Simpla\':problema/simpla\r\n\r\nPornim de la observaţia că în intervalul $[0, 10^n^-1]$ există exact jumătate numere naturale cu suma cifrelor pară. Rezultă că avem $5 * 10^n-1^$ numere naturale cu suma cifrelor pară. Pentru a rezolva problema pe intervalul $[a, b]$, vom folosi o funcţie $f(x)$ egală cu numărul numerelor cu suma cifrelor pară din intervalul $[0, x]$. Astfel, rezultatul va fi $f(b) - f(a - 1)$.\r\n\r\nPentru a calcula valoarea returnată de un $f(x)$, să presupunem că $x = x{~1~}x{~2~}..x{~m-1~}x{~m~}$. Avem $f(x) = x{~1~} * 5*10^m-2^ + x{~2~} * 5*10^m-3^ + .. + x{~m-1~} * 5 + v$. Acest lucru este posibil deoarece pentru un $x{~i~}$ nu are importanţă suma $x{~1~} + .. + x{~i-1~}$, întrucât numărul numerelor cu suma cifrelor pară este egal cu al celor cu suma cifrelor impară. Cazul ultimei cifre, se tratează prin a considera toate numerele cuprinse în intervalul $[x - x{~m~}, x]$ care se vor aduna la rezultat dacă au suma cifrelor pară, rezultat reţinut în $v$ în formula de mai sus.',1792,'public',NULL,NULL),('echipa-infoarena','Echipa infoarena','2006-11-27 08:20:21','2009-07-31 08:00:47','h1. Echipa infoarena\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nMembrii echipei infoarena s-au remarcat prin activitate sustinuta in cadrul proiectelor infoarena. Acestia detin functii oficiale in \'Asociatia infoarena\':asociatia-infoarena. Echipa infoarena este responsabila de dezvoltarea si intretinerea site-ului infoarena precum si de desfasurarea altor proiecte ale Asociatiei. Coordonarea eforturilor echipei se face pe pagina de \'planificare\':planificare.\r\n\r\nEchipa infoarena se bucura de \'*sprijinul a zeci de voluntari*\':implica-te. O buna parte din continutul infoarena este rezultatul muncii lor. Suntem onorati sa primim ajutorul lor si le multumim sincer pentru efortul pe care l-au depus!\r\n\r\n\r\nh2. Membri fondatori\r\n\r\ntable(layout).\r\n|* ==user(user=\"wickedman\" type=\"normal\")==  \r\n* ==user(user=\"silviug\" type=\"normal\")== \r\n|* ==user(user=\"domino\" type=\"normal\")==\r\n* ==user(user=\"fluffy\" type=\"normal\")==|\r\n\r\nh2. Consilieri\r\n\r\ntable(layout).\r\n|* ==user(user=\"ditzoneC\" type=\"normal\")==\r\n* ==user(user=\"filipb\" type=\"normal\")== \r\n* ==user(user=\"danielp\" type=\"normal\")==\r\n* ==user(user=\"Cosmin\" type=\"normal\")== \r\n* ==user(user=\"svalentin\" type=\"normal\")==  \r\n* ==user(user=\"astronomy\" type=\"normal\")==\r\n* ==user(user=\"wefgef\" type=\"normal\")==\r\n* ==user(user=\"alexthero\" type=\"normal\")== \r\n|* ==user(user=\"gcosmin\" type=\"normal\")== \r\n* ==user(user=\"bogdan2412\" type=\"normal\")== \r\n* ==user(user=\"pauldb\" type=\"normal\")== \r\n* ==user(user=\"Prostu\" type=\"normal\")== \r\n* ==user(user=\"stef2n\" type=\"normal\")== \r\n* ==user(user=\"victorsb\" type=\"normal\")==\r\n* ==user(user=\"Marius\" type=\"normal\")==\r\n\r\nh2. Consilieri emeritus\r\n\r\n* ==user(user=\"azotlichid\" type=\"normal\")==\r\n* ==user(user=\"greco\" type=\"normal\")==\r\n',13,'protected',NULL,NULL),('propuneri/13-presedinte','IAP #13: Alegerea Președintelui infoarena','2009-08-01 19:33:33','2009-08-01 20:00:28','h1. IAP #13: Alegerea Preşedintelui infoarena\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2009-08-01                             |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"wickedman\")== şi echipa infoarena |\r\n|_. Stare     | *_IN-CONSTRUCTIE_*                     |\r\n\r\nh2(#abstract). Abstract\r\n\r\nProcedura de alegere a Preşedintelui şi a Vicepreşedintelui infoarena.\r\n\r\nh2(#motivatie). Motivaţie\r\n\r\nEste în spiritul infoarena ca pe măsură ce un membru se implică în proiectele infoarena, acesta să primească credit, responsabilitate şi autoritate ca să influenţeze direcţia în care se îndreaptă comunitatea noastră. În acest sens, Preşedintele are o influenţă importantă deoarece el este ales pe baza obiectivelor pe care le propune pentru următorul an de zile.\r\n\r\nAvem nevoie de o procedură care să funcţioneze în beneficiul comunităţii infoarena şi care să fie transparentă şi corectă.\r\n\r\nh2(#grafic). Grafic\r\n\r\n* Preşedintele se alege în fiecare an până la data de *1 Iunie*.\r\n* Mandatul durează un an şi începe de la data de *1 Septembrie*.\r\n\r\nh2(#alegeri). Organizarea alegerilor\r\n\r\nAlegerile se desfăşoară pe parcursul a 3 şedinţe, după cum urmează:\r\n\r\n* *Şedinţa 1*: Cei care doresc să candideze îşi declară intenţia.\r\n* *Şedinţa 2 (Adunare Generală)*: Fiecare candidat propune un set de obiective şi rezultate cheie pentru următorul an de zile, pe care acesta şi le asumă în cazul în care este ales Preşedinte. Obiectivele vor fi redactate astfel încât să poată fi studiate individual de către membrii Adunării Generale în afara şedinţei.\r\n* *Şedinţa 3 (Adunare Generală)*: Se fac două scrutine cu vot secret:\r\n** În scrutinul întâi se aleg primii doi candidaţi care vor merge în scrutinul următor.\r\n** În al doilea scrutin se votează care dintre ei va fi Preşedinte. În mod implicit cel care iese pe locul 2 va fi numit în funcţia de Vicepreşedinte.\r\n** În caz de egalitate la număr de voturi, se dezbate şi apoi se votează din nou.\r\n** Un membru cu drept de vot se poate abţine dacă doreşte, lucru care se va consemna în notiţele şedinţei.\r\n\r\nOrganizarea alegerilor este responsabilitatea Preşedintelui în funcţie.\r\n\r\nAm selectat câteva articole relevante din \'statutul Asociaţiei infoarena\':asociatia-infoarena?statut.pdf:\r\n\r\nbq. _ART. 12._ Adunarea Generala reprezinta organul de conducere al AI. Adunarea Generala este compusa din\r\nmembrii fondatori si consilieri ai Asociatiei.\r\n\r\nbq. _ART. 13._ [...] Adunarea Generala este legal constituita în prezenta a jumatate plus unu dintre componentii ei.\r\n\r\nbq. _ART. 9, Alin. (5)_ [...] Unui membru consilier i se schimba automat statutul in consilier emerit daca, timp de 6 luni\r\nconsecutive, nu mai contribuie semnificativ la proiectele AI. Schimbarea statutului din consilier in\r\nconsilieri emerit se face de la sine, fara a fi necesara o decizie in Adunarea Generala.\r\n\r\n\r\nh2(#programe). Feedback\r\n',13,'public',4074,NULL),('utilizator/motty','Profil motty','2008-10-24 09:08:52','2009-04-18 10:34:18','h2. Despre mine\r\n\r\n* _Sunt elev in clasa a 9-a la Colegiul National de Informatica \"Tudor Vianu\";_\r\n* _Am inceput informatica in octombrie 2008;_\r\n* _{*In God we Trust!*}_\r\n* _Gibson rulez \\m/;_\r\n\r\nh2. Distinctii primite\r\n\r\n* _Mentiune la ONI 2009;_\r\n* _Premiul I la Concursul de Informatica \"Urmasii lui Moisil\" Iasi - 2009;_\r\n\r\nh2. Profesori\r\n\r\n* ==User(user=\"rapidu36\" type=\"tiny\")==\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"gabitzish1\" type=\"tiny\")==\r\n* ==User(user=\"ira\" type=\"tiny\")==\r\n* ==User(user=\"drag0s93\" type=\"tiny\")==\r\n* ==User(user=\"cosmin79\" type=\"tiny\")==\r\n* ==User(user=\"andreisfrent\" type=\"tiny\")==\r\n* ==User(user=\"punkist\" type=\"tiny\")==\r\n* ==User(user=\"andreyp\" type=\"tiny\")==\r\n* ==User(user=\"tvlad\" type=\"tiny\")==\r\n* ==User(user=\"ciprianf\" type=\"tiny\")==\r\n* ==User(user=\"AndreiDuma\" type=\"tiny\")==\r\n* ==User(user=\"Ioanna\" type=\"tiny\")==\r\n* ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n* ==User(user=\"hadesgames\" type=\"tiny\")==\r\n* ==User(user=\"ilinca\" type=\"tiny\")==\r\n',8690,'public',NULL,NULL),('summer-challenge-2009/solutii/runda-3/negustori','summer-challenge-2009/solutii/runda-3/negustori','2009-08-04 17:52:12','2009-08-04 19:08:44','h2(#negustori). \'Negustori\':problema/negustori\r\n\r\nVom rezolva problema folosind metoda programării dinamice. Iară. :)\r\n\r\nPornim de la reprezentarea unei modalităţi de repartizare a tuturor celor $n$ negustori la cele $n$ locaţii de pe aleea comercială. O repartizare presupune să avem $0$ sau mai mulţi negustori repartizaţi la locaţia $1$, $0$ sau mai mulţi la locaţia $2$, etc. Ulterior, negustorii se vor deplasa spre următoarele poziţii spre finalul aleii pentru a găsi un loc liber. Astfel, o stare constă în completarea locurilor $k, .., n$ cu negustori rămânând $m$ locuri libere.\r\n\r\nFie $dp[k][m]$ numărul de repartizări ale negustorilor pe locurile $k, .., n$, rămânând $m$ locuri libere. Vom face următoarele notaţii: $l[i]$ numărul de negustori locali care preferă locaţia $i$, $cl[i]$ numărul de negustori locali care preferă una din locaţiile între 1 şi $i (cl[i] = l[&#49;] + .. + l[i])$. Pentru a calcula $dp[k][m]$, ne rămâne să repartizăm negustori străini pe locul $k$ pe lângă cei $l[k]$ negustori locali. Această repartizare se realizează în limita locurilor disponibile. Numărul locurilor disponibile este egal cu $ld[k][m] = m+1-l[k]$ (cele $m$ locuri libere la care adăugăm locul $k$ şi scădem pe cele ocupate de negustorii locali). Numărul total de negustori străini rămaşi se obţine scăzând din numărul total de negustori pe cei repartizaţi pe locaţiile $k+1, .., n$ şi pe cei locali repartizaţi pe locaţiile $1, .., k$, adică $ns[k][m] = n-(n-k-m)-cl[k]$. Astfel, numărul total de negustori străini este $ns[k][m] = m+k-cl[k]$. Rezultă că vom alege $i$ negustori străini din cei $ns[k][m]$ pe care îi vom repartiza pe poziţia $k$. Astfel, recurenţa este: <tex> dp[k][m] = \\displaystyle\\sum_{i=0}^{ld[k][m]} \\dbinom{ns[k][m]}{ld[k][m]-i} * dp[k-1][i] </tex>. Avem $dp[&#49;][i] = 1$, oricare $i &ge; 0$. Rezultatul se găseşte în $dp[n][&#48;]$.\r\n\r\nComplexitatea soluţiei: $O(n^3^)$. Voi îmbunătăţi claritatea soluţiei curând. :)',3146,'private',NULL,NULL),('summer-challenge-2009/solutii/runda-3/easychoice','summer-challenge-2009/solutii/runda-3/easychoice','2009-08-04 17:53:20','2009-08-04 17:53:20','h2(#easychoice). \'Easy choice\':problema/easychoice\r\n\r\n...',3146,'private',NULL,NULL),('summer-challenge-2009/solutii/runda-3/negustori','summer-challenge-2009/solutii/runda-3/negustori','2009-08-04 17:52:12','2009-08-05 19:06:19','h2(#negustori). \'Negustori\':problema/negustori\r\n\r\nVom rezolva problema folosind metoda programării dinamice.\r\n\r\nPornim de la reprezentarea unei modalităţi de repartizare a tuturor celor $n$ negustori la cele $n$ locaţii de pe aleea comercială. O repartizare presupune să avem $0$ sau mai mulţi negustori străini plus cei locali repartizaţi la locaţia $1$, $0$ sau mai mulţi negustori străini plus cei locali la locaţia $2$, etc. Ulterior, negustorii se vor deplasa spre următoarele poziţii spre finalul aleii pentru a găsi un loc liber. Astfel, o stare constă în completarea cu negustori a locurilor $k, .., n$, rămânând $m$ locuri libere pentru completări ulterioare.\r\n\r\nFie <tex> dp[k][m] </tex> numărul de repartizări ale negustorilor pe locurile $k, .., n$, rămânând $m$ locuri libere. Vom face următoarele notaţii: $l[k]$ numărul de negustori locali care preferă locaţia $k$, $cl[k]$ numărul de negustori locali care preferă una din locaţiile între 1 şi $k (cl[k] = l[&#49;] + .. + l[k])$. Pentru a calcula <tex> dp[k][m] </tex>, ne rămâne să repartizăm negustori străini pe locul $k-1$ pe lângă cei $l[k-1]$ negustori locali. Această repartizare se realizează în limita locurilor disponibile. Numărul locurilor disponibile este egal cu $locuriLibere = m+1-l[k-1]$ (cele $m$ locuri libere la care adăugăm locul $k-1$ şi scădem pe cele ocupate de negustorii locali, $l[k-1]$). Numărul total de negustori străini rămaşi se obţine scăzând din numărul total de negustori pe cei repartizaţi pe locaţiile $k, .., n$ şi pe cei locali repartizaţi pe una din locaţiile preferate dintre $1, .., k-1$, adică $negustoriStraini = n-(n-k+1-m)-cl[k-1]$. Astfel, numărul total de negustori străini este $m+k-1-cl[k-1]$. Rezultă că vom alege $i$ negustori străini, fără a depăşi numărul locurilor libere, pe care îi vom repartiza pe poziţia $k-1$. Astfel, recurenţa este: <tex> dp[k][m] = \\displaystyle\\sum_{i=0}^{locuriLibere} \\dbinom{negustoriStraini}{locuriLibere-i} * dp[k-1][i] </tex>. Avem <tex> dp[1][i] = 1, \\forall i \\ge 0 </tex>. Rezultatul se găseşte în <tex> dp[n][0] </tex>.\r\n\r\nComplexitatea soluţiei: $O(n^3^)$.',3146,'private',NULL,NULL),('summer-challenge-2009/solutii/runda-3/easychoice','summer-challenge-2009/solutii/runda-3/easychoice','2009-08-04 17:53:20','2009-08-06 18:45:28','h2(#easychoice). \'Easy choice\':problema/easychoice\r\n\r\nPentru rezolvarea problemei, vom sorta mai întâi crescător şirul înălţimilor. Se poate observa uşor că o divizie va fi un interval compact în şirul sortat, de lungime $C$. Ne propunem să alegem $R$ astfel de intervale care să nu se suprapună şi care să minimizeze dezechilibrul armatei.\r\n\r\nVom fixa printr-o căutare binară dezechilibrul $D$ şi vom verifica dacă se pot plasa cel puţin $R$ intervale disjuncte, fiecare cu dezechilibru cel mult $D$. Această verificare se poate realiza prin metoda programării dinamice, observând relaţia\r\n\r\n* $A[i] = max(A[i - 1], A[i - C] + 1)$, dacă $H[i] - H[i - C + 1] &le; D$\r\n* $A[i] = A[i - 1]$, altfel\r\n\r\nunde $A[i]$ = numărul maxim de divizii cu dezechilibru cel mult $D$ ce se pot crea folosind doar primii $i$ candidaţi, iar $H$ = şirul sortat al înălţimilor.\r\n\r\nComplexitatea rezolvării de mai sus este $O(N * log N + N * log H)$.',1792,'public',NULL,NULL),('runda/w1','w1','2009-08-12 11:40:04','2009-08-12 12:19:21','h1. **Concursul W.**\r\n\r\nh4.     +Concursul W.+ a fost creat in scopul antrenarii programatorilor.\r\n\r\nh4.     De asemenea ofera o sansa de a mari punctajul tau in clasamentul arhivei.\r\n\r\nh2. **Runda w1**\r\n\r\nh4.     +Runda w0+ a trecut.\r\n\r\nh4.     Pentru aceasta runda am folosit problemele care nu au fost rezolvate randul trecut\r\n\r\nh4.     si inca una noua :) .\r\n\r\nh4.     Runda w1 este \"o a doua sansa\", cum s-ar zice.\r\n\r\nh4.     Daca nu ai ce face (si nu prea ai :P e \"Caldura Mare\") sau\r\n\r\nh4.     daca te plictisesti incearca concursul W.\r\n\r\nh4.     si nu vei regreta ;) \r\n\r\nh1. Succes! >:)\r\n\r\n\r\n\r\n\r\nConcursul W. incepe ==roundparam(round_id=\"w2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"w2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/w2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"w2\" score=\"1\")==',10498,'round: w1',NULL,NULL),('runda/w1','w1','2009-08-12 11:40:04','2009-08-12 12:21:21','h1. **Concursul W.**\r\n\r\nh4.     +Concursul W.+ a fost creat in scopul antrenarii programatorilor.\r\n\r\nh4.     De asemenea ofera o sansa de a mari punctajul tau in clasamentul arhivei.\r\n\r\nh2. **Runda w1**\r\n\r\nh4.     +Runda w0+ a trecut.\r\n\r\nh4.     Pentru aceasta runda am folosit problemele care nu au fost rezolvate randul trecut\r\n\r\nh4.     si inca una noua :) .\r\n\r\nh4.     Runda w1 este \"o a doua sansa\", cum s-ar zice.\r\n\r\nh4.     Daca nu ai ce face (si nu prea ai :P e \"Caldura Mare\") sau\r\n\r\nh4.     daca te plictisesti incearca concursul W.\r\n\r\nh4.     si nu vei regreta ;) \r\n\r\nh1. Succes! >:)\r\n\r\n\r\n\r\n\r\nRunda w1 incepe ==roundparam(round_id=\"w2\" param=\"start_time\" strong=\"true\")==.\r\n\r\nEa dureaza ==roundparam(round_id=\"w2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/w2/clasament.\r\n\r\nh1. **W.Problemele**\r\n\r\nProblemele vor aparea in momentul inceperii +concursului W.+\r\n\r\n==Tasks(round_id=\"w2\" score=\"1\")==',10498,'round: w1',NULL,NULL),('runda/w1/clasament','Clasament w1','2009-08-12 11:40:04','2009-08-12 12:27:13','h1. **+W.Clasamentul+** ==roundparam(round_id=\"w1\" param=\"title\") ==\r\n\r\nh4. Felicitari tuturor W.concurentilor :))\r\n\r\n==Rankings(rounds = \"w1\")==',10498,'round: w1',NULL,NULL),('runda/w2','w2','2009-08-12 12:07:38','2009-08-12 12:07:38','h1. == roundparam(round_id=\"w2\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"w2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"w2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"w2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/w2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"w2\" score=\"1\")==',10498,'round: w2',NULL,NULL),('runda/w2','w2','2009-08-12 12:07:38','2009-08-13 09:32:29','!http://infoarena.ro/utilizator/zethpix?action=download&file=rundaw2.jpg&safe_only=false!\r\n\r\n== roundregister(round_id=\"w2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"w2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"w2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/w2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"w2\" score=\"1\")==',10498,'round: w2',NULL,NULL),('runda/w2','w2','2009-08-12 12:07:38','2009-08-13 09:37:28','{!http://infoarena.ro/utilizator/zethpix?rundaw2.jpg!}\r\n\r\n== roundregister(round_id=\"w2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"w2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"w2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/w2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"w2\" score=\"1\")==',10498,'round: w2',NULL,NULL),('runda/w2','w2','2009-08-12 12:07:38','2009-08-13 09:51:40','h1. %{color:red}_Runda w2_%       \r\n\r\nh4. %{color:green}**t r a i n i n g   m o d e**%\r\n\r\nh3. _In primul rand felicitari concurentilor din \"+runda w1+\":http://infoarena.ro/runda/w1 ._\r\n\r\nh3. _Aici se afla \"+clasamentul+\":http://infoarena.ro/runda/w1/clasament rundei trecute._\r\n\r\nh3. _Astazi am atasat alte trei probleme pentru a fi rezolvate._\r\n\r\nh3. _Sper ca tu sa participi si sa obtii punctajul maxim(%{color:#00wefd}300%)._\r\n\r\nh3. _De asemenea punctajul poate fi vazut in timpul concursului imediat dupe ce trimiti sursa(c,cpp,pas)._\r\n\r\nh3. _Runda w2 va dura %{color:red}DOAR 3 ore% si nu 4 cu toate ca sunt 3 probleme._\r\n\r\nh1. %{color:red}Succes!%\r\n\r\n== roundregister(round_id=\"w2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"w2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"w2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/w2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"w2\" score=\"1\")==',10498,'round: w2',NULL,NULL),('runda/w2','w2','2009-08-12 12:07:38','2009-08-13 09:55:24','h1. %{color:red}_Runda w2_%       \r\n\r\nh4. %{color:green}**t r a i n i n g   m o d e**%\r\n\r\nh3. _In primul rand felicitari concurentilor din \"+runda w1+\":http://infoarena.ro/runda/w1 ._\r\n\r\nh3. _Aici se afla \"+clasamentul+\":http://infoarena.ro/runda/w1/clasament rundei trecute._\r\n\r\nh3. _Astazi am atasat alte trei probleme pentru a fi rezolvate._\r\n\r\nh3. _Sper ca tu sa participi si sa obtii punctajul maxim( %{color:purple}300% )._\r\n\r\nh3. _De asemenea punctajul poate fi vazut in timpul concursului imediat dupe ce trimiti sursa(c,cpp,pas)._\r\n\r\nh3. _Runda w2 va dura %{color:red}DOAR 3 ore% si nu 4 cu toate ca sunt 3 probleme._\r\n\r\nh1. %{color:red}Succes!%\r\n\r\n== roundregister(round_id=\"w2\") ==\r\n\r\nh2. Concursul incepe ==roundparam(round_id=\"w2\" param=\"start_time\" strong=\"true\")== \r\n\r\nh2. Dupa ce se termina runda w2, vei putea analiza \'*clasamentul*\':runda/w2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"w2\" score=\"1\")==',10498,'round: w2',NULL,NULL),('runda/w2','w2','2009-08-12 12:07:38','2009-08-13 10:45:40','h1. %{color:red}_Runda w2_%       \r\n\r\nh4. %{color:green}**t r a i n i n g   m o d e**%\r\n\r\nh3. _In primul rand felicitari concurentilor din \"+runda w1+\":http://infoarena.ro/runda/w1 ._\r\n\r\nh3. _Aici se afla \"+clasamentul+\":http://infoarena.ro/runda/w1/clasament rundei trecute._\r\n\r\nh3. _Astazi am atasat alte trei probleme pentru a fi rezolvate._\r\n\r\nh3. _Sper ca tu sa participi si sa obtii punctajul maxim( %{color:purple}300% )._\r\n\r\nh3. _De asemenea punctajul poate fi vazut in timpul concursului imediat dupe ce trimiti sursa(c,cpp,pas)._\r\n\r\nh3. _Runda w2 va dura %{color:red}DOAR 3 ore% si nu 4 cu toate ca sunt 3 probleme._\r\n\r\nh1. %{color:red}Succes!%\r\n\r\n== roundregister(round_id=\"w2\") ==\r\n\r\nh3. Concursul incepe ==roundparam(round_id=\"w2\" param=\"start_time\" strong=\"true\")== \r\n\r\nh3. Dupa ce se termina runda w2, vei putea analiza \'*clasamentul*\':runda/w2/clasament.\r\n\r\nh1. %{color:red}Probleme%\r\n\r\nh3. _Aceasta lista va deveni vizibila doar in momentul inceperii concursului._\r\n\r\n==Tasks(round_id=\"w2\" score=\"1\")==\r\n\r\nh4. Concurs creat de ==user(user=\"zethpix\" type=\"tiny\")==\r\n\r\n== SmfTopic(topic_id=\"4100.0\") ==',10498,'round: w2',NULL,NULL),('runda/w3','w3','2009-08-13 16:38:14','2009-08-13 16:54:07','h1. **Runda w3**\r\n\r\n== roundregister(round_id=\"w3\") ==\r\n\r\nh3. Felicitari castigatorilor editiei \"w2\":http://infoarena.ro/runda/w2\r\n\r\nh3. In aceasta seara deschid ultimul concurs din seria %{color:red}**W**%\r\n\r\nh3. Cele 3 concursuri care s-au desfasurat pana acum au avut rezultate frumoase\r\n\r\nh3. Aici puteti accesa urmatoarele pagini :\r\n\r\nh4. Concurs \"w0\":http://infoarena.ro/runda/w0 --- Clasament \"w0\":http://infoarena.ro/runda/w0/clasament\r\n\r\nh4. Concurs \"w1\":http://infoarena.ro/runda/w1 --- Clasament \"w1\":http://infoarena.ro/runda/w1/clasament\r\n\r\nh4. Concurs \"w2\":http://infoarena.ro/runda/w2 --- Clasament \"w2\":http://infoarena.ro/runda/w2/clasament\r\n\r\nh4. %{color:red}Concurs \"w3\":http://infoarena.ro/runda/w3 --- Clasament \"w3\":http://infoarena.ro/runda/w3/clasament %\r\n\r\nConcursul incepe ==roundparam(round_id=\"w3\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"w3\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/w3/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"w3\" score=\"1\")==',10498,'round: w3',NULL,NULL),('runda/redsnow_1','redsnow_1','2009-08-17 10:31:38','2009-08-17 10:31:38','h1. == roundparam(round_id=\"redsnow_1\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"redsnow_1\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"redsnow_1\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"redsnow_1\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/redsnow_1/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"redsnow_1\" score=\"1\")==',10498,'round: redsnow_1',NULL,NULL),('runda/redsnow_1','redsnow_1','2009-08-17 10:31:38','2009-08-17 11:18:42','h1. %{color:red}Red% **snow**\r\n\r\nh1. Under Work\r\n\r\nh3. ### %{color:red}Redsnow% # %{color:red}challenge% # %{color:red}este% # %{color:red}un% # %{color:red}concurs% # %{color:red}nou.% ###\r\n\r\nh3. ### %{color:red}El% # %{color:red}va% # %{color:red}avea% # %{color:red}4% # %{color:red}runde% # %{color:red}inclusiv% # %{color:red}cea% # %{color:red}finala.% ###\r\n\r\nh3. ### %{color:red}Sper% # %{color:red}ca% # %{color:red}acest% # %{color:red}challenge% # %{color:red}sa% # %{color:red}te% # %{color:red}ajute% # %{color:red}si% # %{color:red}sa% ###\r\n\r\nh3. ### %{color:red}iti% # %{color:red}aduca% # %{color:red}cunostinte% # %{color:red}noi.% ###\r\n\r\nh1. %{color:red}**Runda 1**%\r\n\r\n== roundregister(round_id=\"redsnow_1\") ==\r\n\r\nh4. Mr.Smith este un programator excelent.Deoarece zilele trecute a fost chinuit de construirea unui program a decis ca aztazi %{color:red}**17 august 2009**% sa isi ia o zi libera de la lucru.Hobby-ul sau este pescuitul si de aceea el se duce la Balta de Aur sa pescuiasca.El ajunge acolo la ora %{color:red}**14:30**% .Aici se intalneste cu prietenul sau Mr.Fisher, care este de asmenea cel care l-a invatat sa pescuiasca.Mr.Fisher il provoaca pe Mr.Smith sa gaseasca in balta %{color:red}**3**% pesti de aursi 10 pesti de argint.\r\nMr.Smith nu se pricepe sa prinda pestii de aur ci pe aceia de argint.El se hotaraste sa te cheme pe %{color:red}**tine**% sa il ajuti.Totodata Mr.Smith iti da recompensa pentru fiecare peste prins %{color:red}**(100 de verzisori)**% .\r\n\r\nh4. Daca tu doresti recompensa nu mai sta pe ganduri si ajuta-l pe Smith si gaseste cei 3 pestisori in timp de %{color:red}**4**% ore.\r\n\r\nh4. Fii unul din %{color:red}maestrii pescuitului de probleme% in \'*Clasamentul din oras*\':runda/redsnow_1/clasament.\r\n\r\nh1. Probleme\r\n\r\nAceasta lista va deveni vizibila doar cand Mr.Smith ajunge la Balta de aur.\r\n\r\n==Tasks(round_id=\"redsnow_1\" score=\"1\")==',10498,'round: redsnow_1',4106,NULL),('runda/redsnow_1','redsnow_1','2009-08-17 10:31:38','2009-08-17 11:20:12','h1. %{color:red}Red% **snow**\r\n\r\nh3. %{color:red}Redsnow% %{color:red}challenge% %{color:red}este% %{color:red}un% %{color:red}concurs% # %{color:red}nou.%\r\n\r\nh3. %{color:red}El% %{color:red}va% %{color:red}avea% %{color:red}4% %{color:red}runde% %{color:red}inclusiv% %{color:red}cea% %{color:red}finala.%\r\n\r\nh3. %{color:red}Sper% %{color:red}ca% %{color:red}acest% %{color:red}challenge% %{color:red}sa% %{color:red}te% %{color:red}ajute% %{color:red}si% %{color:red}sa%\r\n\r\nh3. %{color:red}iti% %{color:red}aduca% %{color:red}cunostinte% %{color:red}noi.%\r\n\r\nh1. %{color:red}**Runda 1**%\r\n\r\n== roundregister(round_id=\"redsnow_1\") ==\r\n\r\nh4. Mr.Smith este un programator excelent.Deoarece zilele trecute a fost chinuit de construirea unui program a decis ca aztazi %{color:red}**17 august 2009**% sa isi ia o zi libera de la lucru.Hobby-ul sau este pescuitul si de aceea el se duce la Balta de Aur sa pescuiasca.El ajunge acolo la ora %{color:red}**14:30**% .Aici se intalneste cu prietenul sau Mr.Fisher, care este de asmenea cel care l-a invatat sa pescuiasca.Mr.Fisher il provoaca pe Mr.Smith sa gaseasca in balta %{color:red}**3**% pesti de aursi 10 pesti de argint.\r\nMr.Smith nu se pricepe sa prinda pestii de aur ci pe aceia de argint.El se hotaraste sa te cheme pe %{color:red}**tine**% sa il ajuti.Totodata Mr.Smith iti da recompensa pentru fiecare peste prins %{color:red}**(100 de verzisori)**% .\r\n\r\nh4. Daca tu doresti recompensa nu mai sta pe ganduri si ajuta-l pe Smith si gaseste cei 3 pestisori in timp de %{color:red}**4**% ore.\r\n\r\nh4. Fii unul din %{color:red}maestrii pescuitului de probleme% in \'*Clasamentul din oras*\':runda/redsnow_1/clasament.\r\n\r\nh1. Probleme\r\n\r\nh4. Aceasta lista va deveni vizibila doar cand Mr.Smith ajunge la Balta de aur.\r\n\r\n==Tasks(round_id=\"redsnow_1\" score=\"1\")==',10498,'round: redsnow_1',4106,NULL),('runda/w2/clasament','Clasament w2','2009-08-12 12:07:38','2009-08-13 13:07:05','h1. %{color:red}W2-Clasament%\r\n\r\nh3. _Felicitari primilor clasati!!!_\r\n\r\nh3. _Un \"filmulet\":http://www.trilulilu.ro/giotto/86341714389318 amuzant_\r\n\r\nh3. **;)**\r\n\r\n==Rankings(rounds = \"w2\")==',10498,'round: w2',NULL,NULL),('runda/redsnow_1','redsnow_1','2009-08-17 10:31:38','2009-08-17 11:27:09','h1. %{color:red}Red% **snow**\r\n\r\nh3. %{color:red}Redsnow% %{color:red}challenge% %{color:red}este% %{color:red}un% %{color:red}concurs% %{color:red}nou.%\r\n\r\nh3. %{color:red}El% %{color:red}va% %{color:red}avea% %{color:red}4% %{color:red}runde% %{color:red}inclusiv% %{color:red}cea% %{color:red}finala.%\r\n\r\nh3. %{color:red}Sper% %{color:red}ca% %{color:red}acest% %{color:red}challenge% %{color:red}sa% %{color:red}te% %{color:red}ajute% %{color:red}si% %{color:red}sa%\r\n\r\nh3. %{color:red}iti% %{color:red}aduca% %{color:red}cunostinte% %{color:red}noi.%\r\n\r\nh1. %{color:red}**Runda 1**%\r\n\r\n== roundregister(round_id=\"redsnow_1\") ==\r\n\r\nh4. Mr.Smith este un programator excelent.Deoarece zilele trecute a fost chinuit de construirea unui program a decis ca aztazi %{color:red}**17 august 2009**% sa isi ia o zi libera de la lucru.\r\n\r\nh4. Hobby-ul sau este pescuitul si de aceea el se duce la Balta de Aur sa pescuiasca.El ajunge acolo la ora %{color:red}**14:30**% .\r\n\r\nh4. Aici se intalneste cu prietenul sau Mr.Fisher, care este de asmenea cel care l-a invatat sa pescuiasca.\r\n\r\nh4. Mr.Fisher il provoaca pe Mr.Smith sa gaseasca in balta %{color:red}**3**% pesti de aursi 10 pesti de argint.\r\n\r\nh4. Mr.Smith nu se pricepe sa prinda pestii de aur ci pe aceia de argint.El se hotaraste sa te cheme pe %{color:red}**tine**% sa il ajuti.\r\n\r\nh4. Totodata Mr.Smith iti da recompensa pentru fiecare peste prins %{color:red}**(100 de verzisori)**% .\r\n\r\nh4. Daca tu doresti recompensa nu mai sta pe ganduri si ajuta-l pe Smith si gaseste cei 3 pestisori in timp de %{color:red}**4**% ore.\r\n\r\nh4. Fii unul din %{color:red}maestrii pescuitului de probleme% in \'*Clasamentul din oras*\':runda/redsnow_1/clasament.\r\n\r\nh1. **S u %{color:red}c% c e s**\r\n\r\nh1. **Probleme**\r\n\r\nh4. Aceasta lista va deveni vizibila doar cand Mr.Smith ajunge la Balta de aur.\r\n\r\nh4. \r\n\r\n==Tasks(round_id=\"redsnow_1\" score=\"1\")==',10498,'round: redsnow_1',4106,NULL),('runda/redsnow_2','redsnow_2','2009-08-17 16:26:25','2009-08-17 16:31:17','h1. %{color:red}Red% **snow**\r\n\r\nh1. %{color:red}Runda 2%\r\n\r\n== roundregister(round_id=\"redsnow_2\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"redsnow_2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"redsnow_2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/redsnow_2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"redsnow_2\" score=\"1\")==',10498,'round: redsnow_2',NULL,NULL),('runda/redsnow_2','redsnow_2','2009-08-17 16:26:25','2009-08-17 16:32:46','h1. %{color:red}**Red**% **snow**\r\n\r\nh1. %{color:red}**Runda 2**%\r\n\r\n== roundregister(round_id=\"redsnow_2\") ==\r\n\r\nh3. **Felicitari participantilor \"rundei 1\":http://infoarena.ro/runda/redsnow_1 a concursului.**\r\nConcursul incepe ==roundparam(round_id=\"redsnow_2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"redsnow_2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/redsnow_2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"redsnow_2\" score=\"1\")==',10498,'round: redsnow_2',NULL,NULL),('runda/redsnow_2','redsnow_2','2009-08-17 16:26:25','2009-08-17 16:35:53','h1. %{color:red}**Red**% **snow**\r\n\r\nh1. %{color:red}**Runda 2**%\r\n\r\n== roundregister(round_id=\"redsnow_2\") ==\r\n\r\nh3. **# # %{color:red}#% Felicitari participantilor \"rundei 1\":http://infoarena.ro/runda/redsnow_1 a concursului.**\r\n\r\nh3. **# # %{color:red}#% \"Aici\":http://infoarena.ro/runda/redsnow_1/clasament se gaseste clasamentul rundei.**\r\n\r\nConcursul incepe ==roundparam(round_id=\"redsnow_2\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"redsnow_2\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/redsnow_2/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"redsnow_2\" score=\"1\")==',10498,'round: redsnow_2',NULL,NULL),('runda/redsnow_2','redsnow_2','2009-08-17 16:26:25','2009-08-17 18:17:29','h1. %{color:red}**Red**% **Snow**\r\n\r\n== roundregister(round_id=\"redsnow_2\") ==\r\n\r\nh3. _Felicitari participantilor \"rundei 1\":http://infoarena.ro/runda/redsnow_1 a concursului._\r\n\r\nh3. \"Aici\":http://infoarena.ro/runda/redsnow_1/clasament _se gaseste clasamentul rundei._\r\n\r\nh3. _In runda aceasta am propus 4 probleme si nu 3, iar durata va fi de 5 ore ;)_\r\n\r\nh1. %{color:red}**Runda 2**%\r\n\r\nh4. Astronautul Jimi se pregateste sa dea un interviu la NASA pentru a fi ales sa mearga cu nava Apollo2009 pe luna, satelitul natural al pamantului.\r\n\r\nh4. El este programat sa mearga pe data de 18 august 2009 la ora 10:00 a.m.\r\n\r\nh4. Comisia il supune pe Jimi la 4 teste care vor dura 5 ore in total.\r\n\r\nh4. Dupa ce primeste testele el ramane confuz.\r\n\r\nh4. El nu reuseste sa faca testele 100% perfect.\r\n\r\nh4. De aceea el iti cere tie ajutor.\r\n\r\nh4. Daca tu reusesti sa iei 100 de puncte pe fiecare test Jimi te va lua cu el pe luna.\r\n\r\nh4. Daca nu reusesti vei primi un banut magic pentru fiecare test incercat.\r\n\r\nh4. Jimi a pregatit un \'*clasament*\':runda/redsnow_2/clasament cu cei care l-au ajutat.\r\n\r\nh1. %{color:red}Testele NASA%\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"redsnow_2\" score=\"1\")==',10498,'round: redsnow_2',4107,NULL),('runda/redsnow_3','redsnow_3','2009-08-18 16:12:22','2009-08-18 17:14:09','!runda/redsnow_3?demonhunter.gif!\r\n!runda/redsnow_3?lich.gif!\r\n!runda/redsnow_3?infernal.gif!\r\n!runda/redsnow_3?paladin.gif!\r\n!runda/redsnow_3?frostwrym.gif!\r\n!runda/redsnow_3?bloodmage.gif!\r\n!runda/redsnow_3?deathknight.gif!\r\n\r\nh1. %{color:red}**Red**% **Snow**\r\n\r\nh4. Felicitari tuturor participantilor a concursului %{color:red}**RedSnow**% de pana acum.\r\n\r\nh4. Aici am alcatuit un tabel cu rundele trecute:\r\n\r\n|_. %{color:red}**Runda**% |_. %{color:red}**Clasament**% |\r\n|\"**RedSnow 1**\":http://infoarena.ro/runda/redsnow_1|\"**Ranks 1**\":http://infoarena.ro/runda/redsnow_1/clasament|\r\n|\"**RedSnow 2**\":http://infoarena.ro/runda/redsnow_2|\"**Ranks 2**\":http://infoarena.ro/runda/redsnow_2/clasament|\r\n\r\nh1. %{color:red}**Runda 3**%\r\n\r\nh4. %{color:green}n e w w a r c r a f t s t o r y%\r\n\r\n== roundregister(round_id=\"redsnow_3\") ==\r\n\r\n==Tasks(round_id=\"redsnow_3\" score=\"1\")==',10498,'round: redsnow_3',4110,NULL),('runda/redsnow_3','redsnow_3','2009-08-18 16:12:22','2009-08-18 16:12:22','h1. == roundparam(round_id=\"redsnow_3\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"redsnow_3\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"redsnow_3\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"redsnow_3\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/redsnow_3/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"redsnow_3\" score=\"1\")==',10498,'round: redsnow_3',NULL,NULL),('runda/redsnow_3','redsnow_3','2009-08-18 16:12:22','2009-08-19 04:47:00','== roundregister(round_id=\"redsnow_3\") ==\r\n\r\nh1. %{color:red}**Red**% **Snow**\r\n\r\nh4. Felicitari tuturor participantilor a concursului %{color:red}**RedSnow**% de pana acum.\r\n\r\nh4. Acest concurs a fost creat pentru antrenament si rezolvare a problemelor contra timp.\r\n\r\nh4. Aici am alcatuit un tabel cu rundele trecute:\r\n\r\n|_. %{color:red}**Runda**% |_. %{color:red}**Clasament**% |\r\n|\"**RedSnow 1**\":http://infoarena.ro/runda/redsnow_1|\"**Ranks 1**\":http://infoarena.ro/runda/redsnow_1/clasament|\r\n|\"**RedSnow 2**\":http://infoarena.ro/runda/redsnow_2|\"**Ranks 2**\":http://infoarena.ro/runda/redsnow_2/clasament|\r\n\r\nh1. %{color:red}**Runda 3**%\r\n\r\nh5. %{color:green}_N e w W a r c r a f t S t o r y_%\r\n\r\nh4. Pacea a fost instaurata in lume. Razboaiele dintre orci si oameni au incetat de mult. Invazia strigoilor a esuat, iar elfii isi traiesc vesnicia in liniste.\r\n\r\nh4. Totusi si in aceste timpuri fericite forta raului nu a disparut. %{color:green}Arthas, cavalerul mortii,% a fost alungat in tinutul inghetului. Chinul lui era vesnic, iar el cauta o cale de scapare.\r\n\r\nh4. Intre timp %{color:green}paladinul Granis, aducatorul de lumina,% descopera impreuna cu un grup de arcasi elfi si cavaleri de-ai oamenilor un nou tinut nelocuit.\r\n\r\nh4. Ei l-au numit tinutul %{color:green}Ukondor.% Oamenii s-au colonizzat aici si au trait multi ani trai bun. Pamanturile erau fertile si vremea era perfecta.\r\n\r\nh4. Lucrurile astea s-au intamplat pe la anul 253b din calendarul elfilor, 721 calendarul strigoilor si 101 calendarul oamenilor.\r\n\r\nh4. Timp de 721 de atunci lumea a evoluat. Rasa orcilor se crede ca a disparut de tot. Se spune ca lucru acesta era inevitabil.\r\n\r\nh4. Oamenii aveau pe elfi langa ei si de aceea comportamentul lor autodistructiv era din ce in ce mai redus. Ei erau cea mai numeroasa rasa.\r\n\r\nh4. Strigoii traiau alaturi de oameni in umbra si nevazuti de nimeni. Ei se aflau in anul 0 care era anul reintoarcerii lor in lumea vazuta.\r\n\r\nh4. Ei erau condusi de %{color:green}Morbent, cel de gheata,% care punea totul in randuiala pentru revenirea lor. Strigoii il asteptau pe %{color:green}Arthas% sa scape din tinutul inghetat.\r\n\r\nh4. Elfii isi construiau armata, deoarece zvonurile despre strigoi ii speriau. Ei isi protejau Lumina Lunii cea care ii tinea in viata. Fara ea ei deveneau slugi ale strigoilor.\r\n\r\nh4. In tinutul de frig, %{color:green}Arthas% descopera o colonie de strigoi dintre cei mai rai. Ei erau elfi, orci si oameni care si-au tradat viata.\r\n\r\nh4. Acestia il recunosc ca stapan si ii spun ca totul era pregatit. Anul 0 sosea. Ei i-au dat un %{color:green}Dragon de gheata% drept cadou pentru reintoarecerea lui in lumea celor vii.\r\n\r\nh4. In acest timp oamenii era in sarbatoare. Un nou rege era ales. %{color:green}Hale, vrajitorul focului,% era acela.\r\n\r\nh4. Elfii sufereau de o boala ciudata la care nu au gasit leac. Din ce in ce mai multi mureau. Ei au verificat daca Lumina Lunii era unde trebuie. Totul era in regula.\r\n\r\nh4. %{color:green}Varedis, vanatorul de demoni,% era si el pe moarte. Dar el era singurul care vedea ca strigoii se pregateau de lupta. Elfii l-au considerat nebun cand le-a spus ca %{color:green}Arthas% scapa si l-au aruncat langa fratele sau %{color:green}Illidan.%\r\n\r\nh4. La %{color:red}**ora 10:00 a.m**%(masura de timp a oamenilor)  anul 0 sosea la strigoi. In toate tinuturile locuite de oameni a inceput un haos total.\r\n\r\nh4. Strigoii au fost invocati pretutindeni. Lumina elfilor a fost furata. Vrajile malefice ale strigoilor au provocat boli mortale tuturor raselor.\r\n\r\nh4. %{color:green}Arthas% soseste cu intreaga lui armata si in cateva clipe distruge tot ce era construit de oameni. El invoca un %{color:green}Infernal% care captureaza regele oamenilor si il \r\nduce in tinutul de gheata.\r\n\r\nh4. Elfii n-au incotro si readuc in lume pe %{color:green}Illidan% si %{color:green}Varedis% sa ii ajute. Ei aduna toate fortele ramase ale oamenilor si elfilor si se duc sa caute cele %{color:red}**3 chei**% ale lumii.\r\n\r\nh4. Deoarece %{color:green}Hale, vrajitorul de foc,% era singurul descifrator ale cheilor, %{color:green}Illidan% cere ajutor %{color:green}tie, ucenicul lui Hale,% sa ii ajuti sa descopere cele %{color:red}**100 de semne**% sacre ale fiecarei chei.\r\n\r\nh4. Fara Lumina Lunii rasa elfilor e pe cale de disparitie. Tu ai timp %{color:red}**5 ore**% pana cand toti elfii mor.Ajuta-i!\r\n\r\nh4. De aceea salvarea lumii depinde de tine. Daca reusesti sa descifrezi cheile, %{color:green}Arthas% si intreaga lui imparatie de strigoi va disparea pentru totdeauna de pe Pamant.\r\n\r\nh4. Eroii aceste lupte sunt scrisii in \"Pergamentul de foc si viata al lumii\":http://infoarena.ro/runda/redsnow_3/clasament\r\n\r\nh1. %{color:red}**Cele trei chei ale lumii**%\r\n\r\nh4.  \r\n\r\nh4.  \r\n\r\n==Tasks(round_id=\"redsnow_3\" score=\"1\")==\r\n\r\nh4.  \r\n\r\nh4.  \r\n\r\n!runda/redsnow_3?demonhunter.gif! \r\n!runda/redsnow_3?lich.gif! \r\n!runda/redsnow_3?infernal.gif! \r\n!runda/redsnow_3?paladin.gif! \r\n%{color:green}**Varedis, vanatorul**% %{color:green}**Morbent, cel de gheata**% %{color:green}**Infernal**% %{color:green}**Granis, paladinul**%\r\n!runda/redsnow_3?frostwyrm.gif! %{color:green}**Dragonul de gheata**%\r\n!runda/redsnow_3?bloodmage.gif! %{color:green}**Hale, noul rege**%\r\n!runda/redsnow_3?deathknight.gif! %{color:green}**Arthas, strigoiul**%\r\n',10498,'round: redsnow_3',4110,NULL),('runda/redsnow_3','redsnow_3','2009-08-18 16:12:22','2009-08-19 05:00:30','== roundregister(round_id=\"redsnow_3\") ==\r\n\r\nh1. %{color:red}**Red**% **Snow**\r\n\r\nh4. Felicitari tuturor participantilor a concursului %{color:red}**RedSnow**% de pana acum.\r\n\r\nh4. Acest concurs a fost creat pentru antrenament si rezolvare a problemelor contra timp.\r\n\r\nh4. Aici am alcatuit un tabel cu rundele trecute:\r\n\r\n|_. %{color:red}**Runda**% |_. %{color:red}**Clasament**% |\r\n|\"**RedSnow 1**\":http://infoarena.ro/runda/redsnow_1|\"**Ranks 1**\":http://infoarena.ro/runda/redsnow_1/clasament|\r\n|\"**RedSnow 2**\":http://infoarena.ro/runda/redsnow_2|\"**Ranks 2**\":http://infoarena.ro/runda/redsnow_2/clasament|\r\n\r\nh1. %{color:red}**Runda 3**%\r\n\r\nh5. %{color:green}_N e w W a r c r a f t S t o r y_%\r\n\r\nh4. Pacea a fost instaurata in lume. Razboaiele dintre orci si oameni au incetat de mult. Invazia strigoilor a esuat, iar elfii isi traiesc vesnicia in liniste.\r\n\r\nh4. Totusi si in aceste timpuri fericite forta raului nu a disparut. %{color:green}Arthas, cavalerul mortii,% a fost alungat in tinutul inghetului. Chinul lui era vesnic, iar el cauta o cale de scapare.\r\n\r\nh4. Intre timp %{color:green}paladinul Granis, aducatorul de lumina,% descopera impreuna cu un grup de arcasi elfi si cavaleri de-ai oamenilor un nou tinut nelocuit.\r\n\r\nh4. Ei l-au numit tinutul %{color:green}Ukondor.% Oamenii s-au colonizzat aici si au trait multi ani trai bun. Pamanturile erau fertile si vremea era perfecta.\r\n\r\nh4. Lucrurile astea s-au intamplat pe la anul 253b din calendarul elfilor, 721 calendarul strigoilor si 101 calendarul oamenilor.\r\n\r\nh4. Timp de 721 de atunci lumea a evoluat. Rasa orcilor se crede ca a disparut de tot. Se spune ca lucru acesta era inevitabil.\r\n\r\nh4. Oamenii aveau pe elfi langa ei si de aceea comportamentul lor autodistructiv era din ce in ce mai redus. Ei erau cea mai numeroasa rasa.\r\n\r\nh4. Strigoii traiau alaturi de oameni in umbra si nevazuti de nimeni. Ei se aflau in anul 0 care era anul reintoarcerii lor in lumea vazuta.\r\n\r\nh4. Ei erau condusi de %{color:green}Morbent, cel de gheata,% care punea totul in randuiala pentru revenirea lor. Strigoii il asteptau pe %{color:green}Arthas% sa scape din tinutul inghetat.\r\n\r\nh4. Elfii isi construiau armata, deoarece zvonurile despre strigoi ii speriau. Ei isi protejau Lumina Lunii cea care ii tinea in viata. Fara ea ei deveneau slugi ale strigoilor.\r\n\r\nh4. In tinutul de frig, %{color:green}Arthas% descopera o colonie de strigoi dintre cei mai rai. Ei erau elfi, orci si oameni care si-au tradat viata.\r\n\r\nh4. Acestia il recunosc ca stapan si ii spun ca totul era pregatit. Anul 0 sosea. Ei i-au dat un %{color:green}Dragon de gheata% drept cadou pentru reintoarecerea lui in lumea celor vii.\r\n\r\nh4. In acest timp oamenii era in sarbatoare. Un nou rege era ales. %{color:green}Hale, vrajitorul focului,% era acela.\r\n\r\nh4. Elfii sufereau de o boala ciudata la care nu au gasit leac. Din ce in ce mai multi mureau. Ei au verificat daca Lumina Lunii era unde trebuie. Totul era in regula.\r\n\r\nh4. %{color:green}Varedis, vanatorul de demoni,% era si el pe moarte. Dar el era singurul care vedea ca strigoii se pregateau de lupta. Elfii l-au considerat nebun cand le-a spus ca %{color:green}Arthas% scapa si l-au aruncat langa fratele sau %{color:green}Illidan.%\r\n\r\nh4. La %{color:red}**ora 10:00 a.m**%(masura de timp a oamenilor)  anul 0 sosea la strigoi. In toate tinuturile locuite de oameni a inceput un haos total.\r\n\r\nh4. Strigoii au fost invocati pretutindeni. Lumina elfilor a fost furata. Vrajile malefice ale strigoilor au provocat boli mortale tuturor raselor.\r\n\r\nh4. %{color:green}Arthas% soseste cu intreaga lui armata si in cateva clipe distruge tot ce era construit de oameni. El invoca un %{color:green}Infernal% care captureaza regele oamenilor si il \r\nduce in tinutul de gheata.\r\n\r\nh4. Elfii n-au incotro si readuc in lume pe %{color:green}Illidan% si %{color:green}Varedis% sa ii ajute. Ei aduna toate fortele ramase ale oamenilor si elfilor si se duc sa caute cele %{color:red}**3 chei**% ale lumii.\r\n\r\nh4. Deoarece %{color:green}Hale, vrajitorul de foc,% era singurul descifrator ale cheilor, %{color:green}Illidan% cere ajutor %{color:green}tie, ucenicul lui Hale,% sa ii ajuti sa descopere cele %{color:red}**100 de semne**% sacre ale fiecarei chei.\r\n\r\nh4. Fara Lumina Lunii rasa elfilor e pe cale de disparitie. Tu ai timp %{color:red}**5 ore**% pana cand toti elfii mor.Ajuta-i!\r\n\r\nh4. De aceea salvarea lumii depinde de tine. Daca reusesti sa descifrezi cheile, %{color:green}Arthas% si intreaga lui imparatie de strigoi va disparea pentru totdeauna de pe Pamant.\r\n\r\nh4. Eroii aceste lupte sunt scrisii in \"Pergamentul de foc si viata al lumii\":http://infoarena.ro/runda/redsnow_3/clasament\r\n\r\nh1. %{color:red}**Cele trei chei ale lumii**%\r\n\r\nh4.  \r\n\r\nh4.  \r\n\r\n==Tasks(round_id=\"redsnow_3\" score=\"1\")==\r\n\r\nh4.  \r\n\r\nh4.  \r\n\r\n|_. %{color:red}**Erou**% |_. %{color:red}**Imagine**% |_. %{color:red}**Rasa**% |\r\n|Hale, noul rege|!runda/redsnow_3?bloodmage.gif!|human|\r\n|Granis, paladinul|!runda/redsnow_3?paladin.gif!|human|\r\n|Varedis, vanatorul de demoni|!runda/redsnow_3?demonhunter.gif!|night elf|\r\n|Arthas, cavalerul mortii|!runda/redsnow_3?deathknight.gif!|undead|\r\n|Morbent, cel de gheata|!runda/redsnow_3?lich.gif!|undead|\r\n|Dragonul de gheata|!runda/redsnow_3?frostwyrm.gif!|undead unit|\r\n|Infernal|!runda/redsnow_3?infernal.gif!|summonable|',10498,'round: redsnow_3',4110,NULL),('utilizator/floringh06','Profil floringh06','2007-01-14 12:13:14','2009-08-25 10:03:58','h2. Despre mine\r\n\r\n* 2005 - 2009 - Colegiul National \"Samuel von Brukenthal\" Sibiu\r\n* 2009 - prezent - \"Friedrich Alexander\" University Nuernberg\r\n* Infoarena a fost principala mea sursa de pregatire, m-a invatat ce inseamna un concurs de informatica si o pregatire temeinica.\r\n\r\n*Profesori indrumatori:*\r\n      Ciurea Stelian \r\n\r\n*Oameni de baza pe infoarena:*\r\n      Florian MOGA :)\r\n\r\n!utilizator/floringh06?poza.jpg  500x500!. \r\nVisul meu...\r\n\r\nh2. Distinctii primite\r\n\r\n* Locul 1 OJI 2008\r\n* Locul 2 OJI 2009\r\n* Calificare ONI 2006, ONM 2006, ONM 2007, ONF 2004, ONM 2008...\r\n* Participare ONF 2006, ONI 2007, ONI 2008, ONI 2009\r\n* Participare BARAJ la ONI 2007, ONI 2008, ONI 2009\r\n* Participare ACSL 2008 - Maryland\r\n  Locul 6 la echipe si locul 1 la Individual Continental Division\r\n* Mentiune si medalie de argint ONI 2009 Ploiesti\r\n* Calificare in Finala .Campion 2009 (Locul 7)\r\n* Premiul 2 - \"Micul Programator\" Targu Mures 2008\r\n* Coautor - \"Variante Bacalaureat - Informatica Intensiv 2008\"\r\n* Propunator probleme locala Cl. 9 - Judetul Brasov 2007 - 2008\r\n* Premiul special la Finala Campion 2009 - Relatia Euler :)\r\n\r\n**Prieteni pe infoarena**\r\n==user(user=\"moga_florian\" type=\"tiny\")==\r\n==user(user=\"andrei_info\" type=\"tiny\")== \r\n==user(user=\"luana_0105\" type=\"tiny\")== \r\n==user(user=\"pepelea_flaviu\" type=\"tiny\")==\r\n==user(user=\"vlad_popa\" type=\"tiny\")==\r\n==user(user=\"StTwister\" type=\"tiny\")==\r\n==user(user=\"mishu91\" type=\"tiny\")==\r\n==user(user=\"Robybrasov\" type=\"tiny\")==\r\n==user(user=\"cotofana\" type=\"tiny\")==\r\n==user(user=\"alexandru.mosoi\" type=\"tiny\")==\r\n==user(user=\"mugurelionut\" type=\"tiny\")==\r\n==user(user=\"wefgef\" type=\"tiny\")==\r\n==user(user=\"victorsb\" type=\"tiny\")==\r\n==user(user=\"andreitheo87\" type=\"tiny\")==\r\n==user(user=\"Vman\" type=\"tiny\")==\r\n==user(user=\"mariusdrg\" type=\"tiny\")==\r\n==user(user=\"bogdan2412\" type=\"tiny\")==\r\n',5653,'public',NULL,NULL),('schimbare-borland/alternativa/mingw','schimbare-borland/alternativa/mingw','2008-10-29 18:07:29','2009-08-25 10:45:05','h2(#mingw). \'Mingw\':http://www.mingw.org/\r\n\r\nMinGW (Minimalist Gnu for Windows) este o colectia gratuita de librarii imbogatind GNU Compliler Collection cu fisiere si librarii specifice Windows. Scopul proiectului initial a fost integrarea facilitatilor oferite de Windows32 in compilatorul gcc si binutils, practic portarea acestora pe Windows. Mare parte din codul MinGW este distribuit sub licenta GPL, insa nu in intregime, detalii gasiti \'aici\':http://www.mingw.org/license.\r\n\r\nh3. Comparatie intre MinGW GCC si GNU GCC\r\n\r\nh4. Asemanari\r\n\r\n* Uneltele MinGW pot fi folosite de sine statatoare, asemanator cu uneltele echivalente din Linux. Asadar putem compila si depana (cu ajutorul MinGW gcc/g++ si gdb) orice sursa C/C++ care poate fi scrisa cu un editor de texte. Exista mai multe editoare cu syntax highlighting pentru windows: notepad++, vim, jedit.\r\n\r\nh4. Deosebiri\r\n\r\n* Pentru a citi/afisa numere pe 64 de biti cu libraria <stdio.h> se foloseste specificatorul de format non-standard \"%I64d\". Cateva detalii \'aici\':http://ascending.wordpress.com/2008/04/22/long-long-on-windows-dev-c-mingw/.\r\n\r\nh3. IDE-uri pentru MinGW\r\n\r\nUn IDE (Integrated Development Enviroment) contine:\r\n\r\n* editor performant (syntax highlighting, code completion)\r\n* debugger\r\n* utilitar pentru linkarea surselor si librariilor\r\n\r\nExemple de IDE pentru MinGW: Dev-cpp, MinGW Developer Studio, Code::Blocks (pe site-ul MinGW este recomandat Code::Blocks ca IDE).\r\n\r\nh3. \'MinGW Developer Studio\':http://infoarena.ro/schimbare-borland/alternativa?action=attach-list\r\n\r\n[site-ul nu mai merge de vreo 3 saptamani, arhiva e momentan pe infoarena, o voi pune ulterior la downloads, numai sa mearga pusa intreaga si nu pe parti]\r\n\r\nh4. Avantaje\r\n\r\n* Simplu de instalat si folosit\r\n* Ultima versiunea (2.0.5) vine in mod normal cu MinGW gcc 3.3.1, insa acesta poate fi inlocuit daca utilizatorul doreste acest lucru\r\n* Este freeware (Poate fi folosit gratuit in scopuri non-comerciale dar nu avem acces la surse. Pe viitor putem contacta autorul programului si cere accesul la surse.)\r\n* Editorul este foarte bun, are si hints pentru functiile din librariile standard\r\n* Este stabil in general, fiind putine cazurile cand crapa\r\n* Debugger-ul este unu relativ solid\r\n\r\nh4. Dezavantaje\r\n\r\n* Ultima versiune aparuta dateaza din ianuarie 2005, si reprezinta versiune 2.0.5 a produsului. Asadar, software-ul nu mai este in dezvoltare activa.\r\n* Utilizatorul trebuie sa creeze proiect ca sa poate compila/depana o sursa. Totusi, proiectele create sunt minimaliste (comparativ cu Visual C++ spre exemplu) si nu sunt foarte greu de folosit.\r\n\r\nh3. \'Code::Blocks\':http://www.codeblocks.org/\r\n\r\nUn IDE mai complicat, insa este mai complicat doar pentru ca ofera mai multe unelte. Ruleaza sursele fara proiect insa pentru a face debug trebuie creat un proiect si sursa trebuie importata in acesta. Debuggerul este insa unul puternic. Watchul permite evaluarea variabilelor, dar si a functiilor. De asemeni se pot observa si apelurile functiilor pe stiva sistem.\r\n\r\nBug: Am folosit Windowsul, si la un moment dat cand trebuia sa compileze, imi tot zice mingw32-g++.exe ca \"No Disk\": \"There is no disk in the drive. Please insert a dist into drive D:\" (unitate optiva). Si trebuie sa-i dau Cancel de cateva zeci de ori, stresant.\r\n\r\nh4. Avantaje\r\n\r\n* Este un proiect aflat in development\r\n* Este usor de instalat si contine multe feature-uri\r\n* Editorul este foarte bun, are hints pentru functiile si obiectele (vector, deque etc) din librariile standard, dar nu ofera hints pentru clasele create de user [TODO: de testat daca mingw studio face asta]\r\n\r\nh4. Dezavantaje\r\n\r\n* Are nevoie de un proiect pentru debug\r\n* Nu pare un produs bine pus la punct si bine finalizat. (doar un feeling nu e un argument)\r\n* *bogdan*: mi-a crapat pe windows de vreo 2 ori cand faceam proiecte fara sa inteleg de ce (nu prea pot reproduce).\r\n* *bogdan*: mi se pare prea complicat de folosit si deloc intuitiv. am preferat sa bag printfuri decat sa incerc sa debughez.\r\n* *silviu*: am debugat eu cu el si nu e super complicat; totusi, nu e la fel de usable debugul ca in Visual Studio\r\n* *silviu*: impresia mea a fost una foarte buna dupa ce m-am jucat un pic cu el; intr-adevar, nu pare foarte bine pus la punct dar are cateva chestii super tari (scrieti \"for\" si apoi dati CTRL+J).\r\n\r\nh3. \'Dev-cpp\':http://www.bloodshed.net/index.html\r\n\r\nh4. Avantaje\r\n\r\n* Simplu de instalat si folosit\r\n* Ultima versiunea (4.9.9.2) vine in mod normal cu MinGW gcc 3.4.2, insa acesta poate fi inlocuit daca utilizatorul doreste acest lucru.\r\n* Daca nu se creeaza nici un proiect, sursele sunt trimise automat intr-un proiect fictiv.\r\n\r\nh4. Dezavantaje\r\n\r\n* Editorul nu este grozav, necesitand setari speciale pentru a merge\r\n* Debuggerul crapa si este destul de greu de folosit [Silviu: Eu stiam ca e ca si cum n-ar fi acolo :)]\r\n* Ultima versiune aparuta dateaza din februarie 2005, si reprezinta versiune 4.9.9.2 a produsului. Asadar, software-ul nu mai este in dezvoltare activa.\r\n* Desi usor de folosit in prima faza, nu este foarte stabil.\r\n\r\nh4. Verdict\r\n\r\nAcest IDE este de departe cea mai instabila solutie din cele 3 IDE posibile pentru MinGW. In plus, MinGW Developer Studio ii este net superior. Propunem ca acest IDE sa fie *evitat* in solutia de inlocuire a compilatoarelor Borland.',3689,'public',NULL,NULL),('metoda-greedy-si-problema-fractionara-a-rucsacului','Metoda Greedy si problema fractionara a rucsacului','2009-08-31 18:52:22','2009-09-01 21:18:09','h1. Despre algoritmii Greedy\r\n\r\nAlgoritmii Greedy sunt caracterizati de metoda lor de functionare: la fiecare pas se alege cel mai bun candidat posibil, dupa evaluarea tuturor acestora. Algoritmii sunt rapizi, insa nu intotdeauna optimi. Cand nu aveti o idee mai buna legata de o problema, in timpul unui concurs, o implementare Greedy ar putea aduce in jur de 30% din punctaj. \r\nExista situatii in care algoritmii clacheaza, cum ar fi problema comisului voiajor, sau problemele NP-complete.\r\n\r\nMetoda Greedy are si avantaje: poate fi aplicata multor probleme: determinarea celor mai scurte drumuri in grafuri (Dijkstra), determinarea arborelui minimal de acoperire (Prim, Kruskal), codificare arborilor Huffmann, problema spectacolelor si problema fractionara a rucsacului. Dintre acestea, articolul le trateaza numai pe ultimele doua.\r\n\r\nh1. Problema spectacolelor\r\n\r\n Managerul artistic al unui festival trebuie sa selecteze o multime cat mai ampla de spectacole ce pot fi jucate in singura sala pe care o are la dispozitie.Stiind ca i s-au propus n spectacole si pentru fiecare spectacol i-a fost anuntat intervalul in care se poate desfasura [Si, Fi] (Si reprezinta ora si minutul de inceput, iar Fi ora si minutul de final al spectacolului i), scrieti un program care sa permita spectatorilor vizionarea unui numar cat mai mare de spectacole.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare _spectacole.in_ se afla numarul n, numarul de spectacole propus. Pe urmatoarele n linii se vor afla 4 valori, primele doua reprezentand ora si minutul inceperii spectacolului curent, iar ultimele doua reprezentand ora si minutul terminarii spectacolului.\r\n\r\nh2. Date de iesire\r\n\r\nFisierul de iesire _spectacole.out_ contine o singura linie, pe aceasta vor fi scrise numerele de ordine ale spectacolelor care indeplinesc solutia problemei, printr-un spatiu. \r\n\r\nh2. Restrictii\r\n\r\n* n <= 100\r\n\r\nh2. Exemplu\r\n\r\n|_. spectacole.in | |_. spectacole.out |\r\n| 5                 \r\n12 30 16 30        \r\n15 0 18 0            \r\n10 0 18 30\r\n18 0 20 45\r\n12 15 13 0 |         | 5 2 4 |\r\n\r\nh2. Descrierea solutiei\r\n\r\nVom sorta crescator spectacolele dupa ora de final. Vom selecta initial primul spectacol (cel care se termina cel mai devreme). In continuare vom selecta, la fiecare pasa, primul spectacol neselectat, care nu se suprapune peste cele deja selectate. \r\n\r\nO implementare intuitiva a acestui algoritm va fi prezentata in continuare. Pentru sortat vom folosi metoda BubbleSort, care este indeajuns de buna pentru limitele impuse de problema.\r\n\r\n== code(cpp) |\r\n#include <iostream>\r\n#include <fstream>\r\nusing namespace std;\r\n\r\nifstream f(\"spectacole.in\");\r\nofstream g(\"spectacole.out\");\r\n\r\nint n,inceput[100],sfarsit[100],nr[100];\r\n\r\nvoid citeste()\r\n{\r\n	int ora,min,i;\r\n	f>>n;\r\n	for (i=0;i<n;++i)\r\n	{\r\n		nr[i]=i+1;\r\n		f>>ora>>min;\r\n		inceput[i]=ora*60+min;\r\n		f>>ora>>min;\r\n		sfarsit[i]=ora*60+min;\r\n	}\r\n	f.close();\r\n}\r\n\r\nvoid sorteaza()\r\n{\r\n	int aux,schimb,i;\r\n	do\r\n	{\r\n		schimb=0;\r\n		for (i=0;i<n-1;++i)\r\n			if (sfarsit[nr[i]]>sfarsit[nr[i+1]])\r\n			{\r\n				aux=nr[i];\r\n				nr[i]=nr[i+1];\r\n				nr[i+1]=aux;\r\n				schimb=1;\r\n			}\r\n	}\r\n	while (schimb);\r\n}\r\n\r\nvoid rezolva()\r\n{\r\n	int ultim,i;\r\n	for (ultim=0,i=1;i<n;++i)\r\n		if (inceput[nr[i]]>=sfarsit[nr[ultim]])\r\n		{\r\n			g<<nr[i]+1<<\" \";\r\n			ultim=i;\r\n		}\r\n	g<<endl;\r\n}\r\n\r\nint main()\r\n{\r\n	citeste();\r\n	sorteaza();\r\n	rezolva();\r\n	return 0;\r\n}\r\n==\r\n\r\nh1. Problema fractionara a rucsacului\r\n\r\nSe considera ca dispunem de un rucsac cu capacitatea M si de N obiecte, definite fiecare prin greutate si valoare, ce trebuie introduce in rucsac. Se cere o modalitate de a umple rucsacul cu obiecte , astfel incat valoarea totala sa fie maxima. Este posibil ca oricate obiecte si bucati din obiecte sa fie introduse.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie a fisierului de intrare _rucsac.in_ se gasesc doua numere, primul fiind N, iar al doilea M (cu specificatiile din enunt). Pe urmatoarele N linii se gasesc, despartite printr-un spatiu greutatea obiectului curent si valoarea acestuia.\r\n\r\nh2. Date de iesire\r\n\r\nIn fisierul de iesire _rucsac.out_ vor fi specificate numarul de ordine al obiectului, precum si procentul in care acesta poate fi introdus in rucsac.\r\n\r\nh2. Exemplu\r\n\r\n|_. rucsac.in | |_. rucsac.out |\r\n| 5 100\r\n1000 120\r\n500 20\r\n400 200\r\n1000 100\r\n25 1|          | 2 100\r\n                 4 79\r\n                 5 100 |\r\n\r\nh2. Descrierea solutiei\r\n\r\nVom reprezenta solutia problemei ca pe un vector x. Vom ordona obictele descrescator tinand cont de valoarea/greutate. Atata timp cat obiectele incap in rucsac, le vom adauga in intregime. Completam rucsacul cu un fragment din urmatorul obiect ce nu a fost deja selectat.\r\n\r\nO implementare simpla a acestui algoritm este urmatoarea:\r\n\r\n\r\n==code(cpp) |\r\n\r\n#include <iostream>\r\n#include <fstream>\r\nusing namespace std;\r\n\r\nifstream f(\"rucsac.in\");\r\nofstream g(\"rucsac.out\");\r\n\r\nint o[100],N,M;\r\nfloat val[100],greu[100],x[100],Gr;\r\n\r\nvoid  citeste()\r\n{\r\n	int i;\r\n	f>>N>>M;\r\n	for (i=0;i<N;++i)\r\n	{\r\n		o[i]=i;\r\n		f>>val[i]>>greu[i];\r\n	}\r\n	f.close();\r\n}\r\n\r\nvoid sort()\r\n{\r\n	int i,aux,schimb;\r\n	do\r\n	{\r\n		schimb=0;\r\n		for (i=0;i<N-1;++i)\r\n			if (val[o[i]]/greu[o[i]]<val[o[i+1]]/greu[o[i+1]])\r\n			{\r\n				aux=o[i];\r\n				o[i]=o[i+1];\r\n				o[i+1]=aux;\r\n				schimb=1;\r\n			}\r\n	}\r\n	while (schimb);\r\n}\r\n\r\nvoid rezolva()\r\n{\r\n	int i;\r\n	for (i=0,Gr=M;i<N && Gr>greu[o[i]];++i)\r\n	{\r\n		x[o[i]]=1;\r\n		Gr-=greu[o[i]];\r\n	}\r\n}\r\n\r\nvoid afisare()\r\n{\r\n	int i;\r\n	for (i=0;i<N;++i)\r\n		if (x[i]) g<<i+1<<\" \"<<x[i]*100<<endl;\r\n	g.close();\r\n}\r\n\r\nint main()\r\n{\r\n	citeste();\r\n	sort();\r\n	rezolva();\r\n	afisare();\r\n	return 0;\r\n}\r\n\r\n==\r\n\r\n\r\n',9356,'public',NULL,NULL),('runda/4_me','4_me','2009-09-02 07:17:39','2009-09-02 07:26:57','h1. == roundparam(round_id=\"4_me\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"4_me\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"4_me\" param=\"start_time-3\" strong=\"true\")== si dureaza ==roundparam(round_id=\"4_me\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/4_me/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"4_me\" score=\"1\")==',6958,'round: 4_me',NULL,NULL),('utilizator/gavrilavlad','Gavrila Vlad','2007-09-21 12:07:43','2009-09-15 16:59:23','   \r\n\r\nh2. Despre mine\r\n\r\nMa numesc Gavrila Vlad Alexandru si sunt elev in clasa a IX-a la ICHB. Particip de mult timp la concursuri de informatica, iar principala mea sursa de pregatire este infoarena.\r\n\r\nh2. Distinctii primite\r\n\r\nOlimpiada Nationala de Informatica\r\n\r\n* 2004 - Buzau - Mentiune\r\n* 2005 - Galati - Premiul special\r\n* 2006 - Targoviste - Mentiunea I\r\n* 2007 - Cluj - Premiul II\r\n* 2008 - Bacau - Premiul I\r\n* 2009 - Galati - Premiul II\r\n\r\nBaraje\r\n\r\n* 2008 - Ploiesti / Iasi - Calificat (locul I) la JBOI\r\n* 2009 - Bistrita / Cluj - Calificat (locul I, cu maxim de puncte) la JBOI\r\n\r\nJunior Balkan Olympiad in Informatics\r\n\r\n* 2008 - Shumen - Argint\r\n\r\nPreONI, Algoritmiada si .Campion\r\n\r\n* 2008 - PreONI - Finalist\r\n* 2009 - .Campion - Locul II\r\n* 2009 - Algoritmiada - Locul I\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* Profesori:\r\n\r\n==user(user=\"pauldb\" type=\"normal\")==\r\n\r\n==user(user=\"wefgef\" type=\"normal\")==\r\n\r\n==user(user=\"silviug\" type=\"normal\")==\r\n\r\n\r\n* Prieteni:\r\n\r\n==user(user=\"savim\" type=\"normal\")==\r\n\r\n==user(user=\"CezarMocan\" type=\"normal\")==\r\n\r\n==user(user=\"raduzer\" type=\"normal\")==\r\n\r\n==user(user=\"toni2007\" type=\"normal\")==\r\n\r\n==user(user=\"gcosmin\" type=\"normal\")==\r\n\r\n==user(user=\"bogdan2412\" type=\"normal\")==\r\n\r\n==user(user=\"GheorgheMihai\" type=\"normal\")==\r\n\r\n==user(user=\"radu_voroneanu\" type=\"normal\")==\r\n\r\n==user(user=\"protoman\" type=\"normal\")==\r\n\r\n==user(user=\"matemariaescu\" type=\"normal\")==\r\n\r\n==user(user=\"tvlad\" type=\"normal\")==\r\n\r\n==user(user=\"taloibogdan\" type=\"normal\")==\r\n',6800,'public',NULL,NULL),('runda/cnrv_4','CNRV - pregatire la info - Editia #4','2009-10-31 10:42:01','2009-10-31 10:46:25','h1. == roundparam(round_id=\"cnrv_4\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"cnrv_4\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"cnrv_4\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"cnrv_4\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/cnrv_4/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"cnrv_4\" score=\"1\")==',5748,'round: cnrv_4',NULL,NULL),('utilizator/miculprogramator','Profil miculprogramator','2009-01-16 19:06:56','2009-08-07 09:01:53','[url=http://www.userbars.be][img]http://img508.imageshack.us/img508/6521/5910ok4.jpg[/img][/url]\r\nh1. Cate ceva despre mine: \r\n\r\n\r\n* Numele meu este Cosmina, invat la scoala 26, Galati. Sunt in clasa a VIII-a (an scolar 2009-2010).\r\n\r\n* Imi place informatica din clasa a VI-a, de cand fac cu doamna prof. Zaharia Simona.\r\n\r\n* Ma bat cu problemele de pe infoarena de cate ori am timp, vreau sa ajung la Olimpiada.\r\n\r\n* Imi place sa lucrez noaptea, cu o napolitana Yup (sau mai multe), limonada, hartie si creion. Sunt activa insa si in timpul zilei, cu toate ca _\"Noaptea imi vin cele mai bune idei.\" (Hitler)_\r\n\r\n* Imi place Linkin Park (In the end -best song) si muzica veche gen Ray Charles. Ascult cu placere NOISETTES, La Roux, Regina Spektor, Billy Talent, Killers, Pink.\r\n\r\n* Nu pot sa stau cu picioarele in pozitie normala cand stau pe scaun, trebuie sa le tin sub mine, sau sa le ridic in vreun fel.\r\n\r\n* Motto-ul meu este: *\"Cand vrei sa faci ceva cauti mijloace.Cand nu vrei sa faci ceva cauti motive...\"*\r\n\r\n\r\nCam atat despre mine, ne auzim pe forum. :)\r\n\r\nh1. Distinctii primite:\r\n\r\nLocul 1 pe judet la \'Evaluare in educatie\':http://www.evaluare-edu.ro/evaluare-informatica/user=3463\r\n\r\n\r\nh1. Prieteni pe infoarena: \r\n\r\n ==User(user=\"toni2007\" type=\"tiny\")==\r\n\r\n ==User(user=\"AnDrEwBoY\" type=\"tiny\")==\r\n \r\n ==User(user=\"DranaXum\" type=\"tiny\")==\r\n\r\n ==User(user=\"marcelcodrea\" type=\"tiny\")==\r\n \r\n==User(user=\"devilkind\" type=\"tiny\")==\r\n\r\n ==User(user=\"vlasceanu\" type=\"tiny\")==\r\n\r\n ==User(user=\"Leocrux\" type=\"tiny\")==\r\n',9356,'public',NULL,NULL),('planificare/sedinta-20091015','Ședință 2009-10-15','2009-09-28 19:00:23','2009-10-14 19:10:08','h1. Şedinţă 2009-10-15\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *joi* la ora *19^00^* la *...*.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ... Tu?\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinţa anterioară\':planificare/sedinta-20090727 | ? |\r\n| Alegerea preşedintelui infoarena | ? |\r\n| Inscriere la Gala Premiilor in Educatie | ? |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"domino\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\nh3. OKRs\r\n\r\n* Notele pentru \'Q1 2009\':okr/20091 nu sunt finalizate.\r\n* Nu avem obiective şi nici rezultate pe Q2. Sărim peste?\r\n* Obiective pentru Q3 (doar 2 luni: august si septembrie)?\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\nh2(#notite). Notite',1490,'protected',NULL,NULL),('planificare/sedinta-20091015','Ședință 2009-10-15','2009-09-28 19:00:23','2009-10-15 08:21:10','h1. Şedinţă 2009-10-15\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *joi* la ora *19^00^* la *...*.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ... Tu?\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinţa anterioară\':planificare/sedinta-20090727 | ? |\r\n| Alegerea preşedintelui infoarena | ? |\r\n| Inscriere la Gala Premiilor in Educatie | ? |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"domino\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\nh3. OKRs\r\n\r\n* Notele pentru \'Q1 2009\':okr/20091 nu sunt finalizate.\r\n* Nu avem obiective şi nici rezultate pe Q2. Sărim peste?\r\n* Obiective pentru Q3 (doar 2 luni: august si septembrie)?\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\nh2(#notite). Notite',13,'protected',NULL,NULL),('planificare/sedinta-20091015','Ședință 2009-10-15','2009-09-28 19:00:23','2009-10-15 09:26:57','h1. Şedinţă 2009-10-15\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *joi* la ora *19^00^* la *...*.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"devilkind\" type=\"tiny\")==\r\n* ... Tu?\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinţa anterioară\':planificare/sedinta-20090727 | ? |\r\n| Alegerea preşedintelui infoarena | ? |\r\n| Inscriere la Gala Premiilor in Educatie | ? |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"domino\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\nh3. OKRs\r\n\r\n* Notele pentru \'Q1 2009\':okr/20091 nu sunt finalizate.\r\n* Nu avem obiective şi nici rezultate pe Q2. Sărim peste?\r\n* Obiective pentru Q3 (doar 2 luni: august si septembrie)?\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\nh2(#notite). Notite',2970,'protected',NULL,NULL),('planificare/sedinta-20091015','Ședință 2009-10-15','2009-09-28 19:00:23','2009-10-15 15:23:11','h1. Şedinţă 2009-10-15\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Joi* la ora *19^00^* la \'Cafepedia 3, Zona Romană\':http://metropotam.ro/Cluburi/loc0483273064-Cafepedia-3/.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"devilkind\" type=\"tiny\")==\r\n* ==user(user=\"DITzoneC\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ... Tu?\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinţa anterioară\':planificare/sedinta-20090727 | ? |\r\n| Alegerea preşedintelui infoarena | ? |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"domino\" type=\"tiny\")== |\r\n| Algoritmiada 2010 | ? |\r\n| Tabăra infoarena | ? |\r\n\r\nh2. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n...\r\n\r\nh2(#notite). Notite\r\n\r\n...',1,'protected',NULL,NULL),('planificare/sedinta-20091015','Ședință 2009-10-15','2009-09-28 19:00:23','2009-10-15 17:07:56','h1. Şedinţă 2009-10-15\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Joi* la ora *19^00^* la \'Cafepedia 3, Zona Romană\':http://metropotam.ro/Cluburi/loc0483273064-Cafepedia-3/.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")==\r\n* ==user(user=\"devilkind\" type=\"tiny\")==\r\n* ==user(user=\"DITzoneC\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n* ... Tu?\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Sponsorizare Amazon | ==user(user=\"astronomy\" type=\"tiny\")== |\r\n| Recapitulare \'sedinţa anterioară\':planificare/sedinta-20090727 | ? |\r\n| Alegerea preşedintelui infoarena | ? |\r\n| OKRs si planuri pentru urmatorul an scolar | ? |\r\n| Algoritmiada 2010 | ? |\r\n| Tabăra infoarena | ? |\r\n\r\nh2. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Cristi vorbeste cu Buraga legat de sponsorizare\r\n* Cristi modifică IAP de alegere a Preşedintelui: Preşedintele desemnează câte un Vicepreşedinte pentru Content (arhivă, concursuri online, articole), Development şi Algoritmiada. Preşedintele se ocupă şi de obiectivele legate de comunitate.\r\n\r\nh2(#notite). Notite\r\n\r\n...',1,'protected',NULL,NULL),('utilizator/blasterz','Profil blasterz','2006-11-24 20:58:43','2009-10-17 17:44:33','h3. Student in anul II la Facultatea de Matematica si Informatica, Universitatea Bucuresti\r\n\r\n\r\nh2. TODO LIST:   ACM WORLD FINALS MEDAL\r\n\r\nh2. Distinctii primite\r\n\r\n**2009 : Antrenor si Membru in Comisia Lotului National de Informatica** \r\n**2009 : Membru in Comisia ONI la clasele 11-12 si baraj**\r\n**2009 : Propunator probleme .campion ,ONI si lot**\r\n\r\n**2009 : 26th place at the ACM South Eastern Contest**\r\n**2009 : Adobe Internship Diploma**\r\n**2009 : Locul 1 la Sesiunea de Comunicari Stiintifice, Faza Nationala impreuna cu Serban Lupulescu cu articolul \"Trie Forest Data Structure\"**\r\n**2009 : Locul 4 la finala concursului national Algoritmiada, sectia studenti**\r\n**2009 : Calificat in finala Concursului National Algoritmiada pentru Studenti**\r\n**2008 : Calificat in runda a4a a concursului international Google CodeJam**\r\n**2008 : Membru al Lotului National Restrans (unde am obtinut locul 11)**\r\n**2008 : Calificat in Lotul National Largit**\r\n**2008 : Mentiune ONI 2008 + medalie de argint**\r\n**2008 : Finalist .campion 2008 Bran**\r\n2008 : Participare la Concursul National Urmasii lui Moisil, Iasi ( punctajul neoficial cel mai mare...mai trimiti brute la sfarsit fara sa-ti dai seama =)) :| )\r\n2008 : Participare la Concursul National Stelele Informarticii 2008\r\n**2007 : Premiul 1 la Concursul International ProSoft@NT**\r\n**2007 : Finalist .Campion 2007 Galati** \r\n**2007 : Premiul II la Concursul National de Informatica Aplicata (CIA) sectiunea Jocuri**\r\n2007 : Premiul I la Faza Judeteana a Concursul de Informatica Aplicata (CIA) sectiunea Jocuri\r\n2007 : Premiul II la Concursul Interjudetean al Centrelor de Excelenta Suceava\r\n2007 : Mentiune la Concursul de Programare DataS-NMG Targu Secuiesc\r\n2007 : Participare ONI 2007 + calificare pentru baraje\r\n2007 : Premiul 2 Olimpiada Judeteana\r\n2006 : Mentiune la Concursul Interjudetean al Centrelor de Excelenta Suceava\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\nh3. Ordinea nu are importanta. Daca nu am trecut pe careva sa-mi spuneti.\r\n\r\n\r\n* ==user(user=\"georgiana\" type=\"tiny\")== \r\n\r\n* ==user(user=\"marina\" type=\"tiny\")== \r\n\r\n* ==user(user=\"alisssia\" type=\"tiny\")== \r\n\r\n\r\n* ==user(user=\"doru.nitu\" type=\"tiny\")== \r\n\r\n* ==user(user=\"freak93\" type=\"normal\")==\r\n\r\n* ==user(user=\"DjSefu\" type=\"tiny\")==\r\n\r\n* ==user(user=\"warchildmd\" type=\"tiny\")==\r\n\r\n* ==user(user=\"nyxpho\" type=\"tiny\")== \r\n\r\n* ==user(user=\"monica_133\"  type=\"normal\")==\r\n\r\n* ==user(user=\"serbanlupu\" type=\"normal\")==\r\n\r\n* ==user(user=\"enslaverr\" type=\"tiny\")==\r\n\r\n* ==user(user=\"Mishu91\" type=\"tiny\")==\r\n\r\n* ==user(user=\"yoyolich\" type=\"tiny\")== \r\n\r\n* ==user(user=\"nuexist\" type=\"tiny\")== \r\n\r\n* ==user(user=\"malex\" type=\"tiny\")==\r\n\r\n* ==user(user=\"lorin_bobu\" type=\"tiny\")==\r\n\r\n\r\n* ==user(user=\"ioanai\" type=\"tiny\")==\r\n\r\n* ==user(user=\"Florian\" type=\"tiny\")==\r\n\r\n\r\n* ==user(user=\"Tabara\" type=\"tiny\")==\r\n\r\n* ==user(user=\"alexthero\" type=\"tiny\")==\r\n\r\n* ==user(user=\"peanutz\" type=\"tiny\")==\r\n\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n\r\n* ==user(user=\"m_dersidan\" type=\"tiny\")==\r\n\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n\r\n* ==user(user=\"mastermage\" type=\"tiny\")==\r\n\r\n* ==user(user=\"nemesis\" type=\"tiny\")==\r\n\r\n* ==user(user=\"Binary_Fire\" type=\"tiny\")==\r\n\r\n* ==user(user=\"TYTUS\" type=\"tiny\")==\r\n\r\n\r\n* ==user(user=\"crawler\" type=\"tiny\")==\r\n\r\n* ==user(user=\"devilkind\" type=\"tiny\")==\r\n\r\n* ==user(user=\"vlad_D\" type=\"tiny\")==\r\n\r\n* ==user(user=\"arenakadaff\" type=\"tiny\")==\r\n\r\n* ==user(user=\"StTwister\" type=\"tiny\")==\r\n\r\n* ==user(user=\"bog_bej\" type=\"tiny\")==\r\n* ==user(user=\"cretu\" type=\"tiny\")==\r\n',1204,'protected',NULL,NULL),('planificare/sedinta-20091023','Ședință 2009-10-23','2009-10-20 12:14:02','2009-10-20 13:32:20','h1. Şedinţă 2009-10-23\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Vineri* la ora *xx^yy^* la TODO.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| OKRs si planuri pentru urmatorul an scolar | ? |\r\n| Algoritmiada 2010 | ? |\r\n| Parteneriat media cu AI contest in Poli | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| Tabăra infoarena | ? |\r\n\r\nh2. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* ...\r\n\r\nh2(#notite). Notite\r\n\r\n...',2038,'public',NULL,NULL),('planificare/sedinta-20091023','Ședință 2009-10-23','2009-10-20 12:14:02','2009-10-20 15:01:32','h1. Şedinţă 2009-10-23\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Vineri* la ora *xx^yy^* la TODO.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada 2010 | ? |\r\n| Parteneriat media cu AI contest in Poli | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| Tabăra infoarena | ? |\r\n\r\nh2. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* ...\r\n\r\nh2(#notite). Notite\r\n\r\n...',2038,'public',NULL,NULL),('planificare/sedinta-20091023','Ședință 2009-10-23','2009-10-20 12:14:02','2009-10-22 20:32:10','h1. Şedinţă 2009-10-23\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Vineri* la ora *19^00^* la TODO.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== dupa 16:00\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada 2010 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| Parteneriat media cu AI contest in Poli | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| Tabăra infoarena | ? |\r\n\r\nh2. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* ...\r\n\r\nh2(#notite). Notite\r\n\r\n...',75,'protected',NULL,NULL),('planificare/sedinta-20091023','Ședință 2009-10-23','2009-10-20 12:14:02','2009-10-23 06:01:02','h1. Şedinţă 2009-10-23\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Vineri* la ora *19^00^* la Cafepedia de la Universitate.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== dupa 16:00\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada 2010 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| Parteneriat media cu AI contest in Poli | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| Tabăra infoarena | ? |\r\n\r\nh2. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* ...\r\n\r\nh2(#notite). Notite\r\n\r\n...',2038,'protected',NULL,NULL),('planificare/sedinta-20091023','Ședință 2009-10-23','2009-10-20 12:14:02','2009-10-23 17:07:19','h1. Şedinţă 2009-10-23\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Vineri* la ora *19^00^* la Cafepedia de la Universitate.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== dupa 16:00\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada 2010 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| Parteneriat media cu AI contest in Poli | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| Tabăra infoarena | ? |\r\n| Stare Evaluator | ? |\r\n| Colaborare Poli | ? |\r\n\r\nh2. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* De votat IAP #13\r\n* Cristian vorbeste cu Buraga legat de sponsorizare\r\n* Silviu face blog post despre noul Presedinte\r\n* Cristian ii face card Cristinei si lui Cosmin.\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")== vicepresedite responsabil cu Development\r\n* ==user(user=\"pauldb\" type=\"tiny\")== vicepresedite responsabil cu Algoritmiada\r\n* ==user(user=\"stef2n\" type=\"tiny\")== vicepresedite responsabil cu Content\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")== se ocupa de organizat concursuri\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")== scrie tickete pentru fixuri la Virtual Contest\r\n* ==user(user=\"prostu\" type=\"tiny\")== se ocupa de Calendar\r\n* ==user(user=\"stef2n\" type=\"tiny\")== vorbeste cu ==user(user=\"marius\" type=\"tiny\")== despre Articole\r\n* Moare \"IAP #7\":propuneri/7-community-ladder, ==user(user=\"wickedman\" type=\"tiny\")== actualizeaza status\r\n* ==user(user=\"gcosmin\" type=\"tiny\")== scrie newsletter de acum\r\n* ==user(user=\"gcosmin\" type=\"tiny\")== se ocupa de Strangere Fonduri\r\n* ==user(user=\"gcosmin\" type=\"tiny\")== vorbeste cu ==user(user=\"devilkind\" type=\"tiny\")== despre Development\r\n\r\nh2(#notite). Notite\r\n\r\n* Cristi i-a dat lui Vali 23 RON pentru bilet tren Algoritmiada 2009\r\n',961,'protected',NULL,NULL),('planificare/sedinta-20091023','Ședință 2009-10-23','2009-10-20 12:14:02','2009-10-23 17:36:47','h1. Şedinţă 2009-10-23\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Vineri* la ora *19^00^* la Cafepedia de la Universitate.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== dupa 16:00\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada 2010 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| Parteneriat media cu AI contest in Poli | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| Tabăra infoarena | ? |\r\n| Stare Evaluator | ? |\r\n| Colaborare Poli | ? |\r\n\r\nh2. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* De votat IAP #13\r\n* Cristian vorbeste cu Buraga legat de sponsorizare\r\n* Silviu face blog post despre noul Presedinte\r\n* Cristian ii face card Cristinei si lui Cosmin.\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")== vicepresedite responsabil cu Development\r\n* ==user(user=\"pauldb\" type=\"tiny\")== vicepresedite responsabil cu Algoritmiada\r\n* ==user(user=\"stef2n\" type=\"tiny\")== vicepresedite responsabil cu Content\r\n* Bogdan se ocupa de organizat concursuri\r\n* Bogdan scrie tickete pentru fixuri la Virtual Contest\r\n* Prostu se ocupa de Calendar\r\n* Stefan vorbeste cu Marius despre Articole\r\n* Moare \"IAP #7\":propuneri/7-community-ladder, Cristi actualizeaza status\r\n* Cosmin scrie newsletter de acum\r\n* Cosmin se ocupa de Strangere Fonduri\r\n* Cosmin vorbeste cu Tibi despre Development\r\n* Bogdan e responsabil de Taguri\r\n* Cristi scrie retry loop pentru eval\r\n* Cristi intreaba la Hostway daca ne mai dau o masina virtuala\r\n* Vali face testing pe masina virtuala\r\n* pe 22 noiembrie va fi prima runda de Algoritmiada\r\n* Cosmin face mapa pentru sponsori\r\n\r\nh2(#notite). Notite\r\n\r\n* Cristi i-a dat lui Vali 23 RON pentru bilet tren Algoritmiada 2009\r\n',961,'protected',NULL,NULL),('planificare/sedinta-20091023','Ședință 2009-10-23','2009-10-20 12:14:02','2009-10-23 18:01:16','h1. Şedinţă 2009-10-23\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Vineri* la ora *19^00^* la Cafepedia de la Universitate.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== dupa 16:00\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada 2010 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| Parteneriat media cu AI contest in Poli | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| Tabăra infoarena | ? |\r\n| Stare Evaluator | ? |\r\n| Colaborare Poli | ? |\r\n\r\nh2. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* De votat IAP #13\r\n* Cristian vorbeste cu Buraga legat de sponsorizare\r\n* Silviu face blog post despre noul Presedinte\r\n* Cristian ii face card Cristinei si lui Cosmin.\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")== vicepresedite responsabil cu Development\r\n* ==user(user=\"pauldb\" type=\"tiny\")== vicepresedite responsabil cu Algoritmiada\r\n* ==user(user=\"stef2n\" type=\"tiny\")== vicepresedite responsabil cu Content\r\n* Bogdan se ocupa de organizat concursuri\r\n* Bogdan scrie tickete pentru fixuri la Virtual Contest\r\n* Prostu se ocupa de Calendar\r\n* Stefan vorbeste cu Marius despre Articole\r\n* Moare \"IAP #7\":propuneri/7-community-ladder, Cristi actualizeaza status\r\n* Cosmin scrie newsletter de acum\r\n* Cosmin se ocupa de Strangere Fonduri\r\n* Cosmin vorbeste cu Tibi despre Development\r\n* Bogdan e responsabil de Taguri\r\n* Cristi intreaba la Hostway daca ne mai dau o masina virtuala\r\n* Vali face testing pe masina virtuala\r\n* pe 22 noiembrie va fi prima runda de Algoritmiada\r\n* Cosmin, Silviu si Vali fac mapa pentru sponsori pana la *sfarsitul lunii*\r\n* Silviu trimite bugetul lui Paul\r\n* Cristi da reply la Amazon\r\n* Paul face pagini si buget pentru algoritmiada pana la sfarsitul lunii\r\n\r\nh2(#notite). Notite\r\n\r\n* Cristi i-a dat lui Vali 23 RON pentru bilet tren Algoritmiada 2009\r\n* Se scrie retry loop pentru eval',961,'protected',NULL,NULL),('planificare/sedinta-20091023','Ședință 2009-10-23','2009-10-20 12:14:02','2009-10-23 18:16:56','h1. Şedinţă 2009-10-23\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Vineri* la ora *19^00^* la Cafepedia de la Universitate.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== dupa 16:00\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada 2010 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| Parteneriat media cu AI contest in Poli | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| Tabăra infoarena | ? |\r\n| Stare Evaluator | ? |\r\n| Colaborare Poli | ? |\r\n\r\nh2. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* De votat IAP #13\r\n* Cristian vorbeste cu Buraga legat de sponsorizare\r\n* Silviu face blog post despre noul Presedinte\r\n* Cristian ii face card Cristinei si lui Cosmin.\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")== vicepresedite responsabil cu Development\r\n* ==user(user=\"pauldb\" type=\"tiny\")== vicepresedite responsabil cu Algoritmiada\r\n* ==user(user=\"stef2n\" type=\"tiny\")== vicepresedite responsabil cu Content\r\n* Bogdan se ocupa de organizat concursuri\r\n* Bogdan scrie tickete pentru fixuri la Virtual Contest\r\n* Prostu se ocupa de Calendar\r\n* Stefan vorbeste cu Marius despre Articole\r\n* Moare \"IAP #7\":propuneri/7-community-ladder, Cristi actualizeaza status\r\n* Cosmin scrie newsletter de acum\r\n* Cosmin se ocupa de Strangere Fonduri\r\n* Cosmin vorbeste cu Tibi despre Development\r\n* Bogdan e responsabil de Taguri\r\n* Cristi intreaba la Hostway daca ne mai dau o masina virtuala\r\n* Vali face testing pe masina virtuala\r\n* pe 22 noiembrie va fi prima runda de Algoritmiada\r\n* Cosmin, Silviu si Vali fac mapa pentru sponsori pana la *sfarsitul lunii*\r\n* Silviu trimite bugetul lui Paul\r\n* Cristi da reply la Amazon\r\n* Paul face pagini si buget pentru algoritmiada pana la sfarsitul lunii\r\n* Cosmin vorbeste cu Cristina despre comunicate de presa\r\n* Cosmin vorbeste la Orange Concept Store\r\n* Vali vorbeste cu Vlad Posea despre colaborare si daca ne poate ajuta cineva cu jailrun java\r\n\r\nh2(#notite). Notite\r\n\r\n* Cristi i-a dat lui Vali 23 RON pentru bilet tren Algoritmiada 2009\r\n* Se scrie retry loop pentru eval',961,'protected',NULL,NULL),('pd','Programare dinamica','2007-12-04 21:25:10','2009-11-01 17:35:42','h1. Programare dinamica\r\n\r\n(Categoria _Tehnici de programare_, autori _Catalin Tiseanu_, _Andrei Homescu_)\r\n\r\nPlan de atac (probleme-candidat):\r\n\r\n1. http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en (Reducerea complexitatii, transformarea problemei intr-una de construire a unui arbore binar.)\r\n\r\n2. http://code.google.com/codejam/contest/dashboard?c=32001#s=p0&a=3 (Boolean tree, programare dinamica simpla pe arbore binar.)\r\n\r\n3. http://code.google.com/codejam/contest/dashboard?c=32001#s=p3&a=3 (PermRLE, permutari cu N*2^N)\r\n\r\n4. http://code.google.com/codejam/contest/dashboard?c=32010#s=p3&a=3 (problema cu DP pe matrici, aplicam ridicarea la putere pt calcul rapid)\r\n\r\n5. http://infoarena.ro/problema/doipatru (joc cu solutie DP, stare in 6 dimensiuni)\r\n\r\nh2. Sugestii Silviu\r\n\r\n* poate ca nu trebuie sa spunem tot despre programare dinamica intr-un singur articol; spre exemplu putem facem doua articole: PD basic si PD advanced\r\n* cred ca era si ceva prin Cartea lui Francu\' despre programare dinamica; ar merge incorporat (eventual in pd_basic).\r\n\r\nh2. Introducere\r\n\r\nProgramarea dinamică este o metodă utilă pentru a rezolva probleme care pot fi obţinute prin compunerea a mai multor bucăţi, a căror soluţie poate fi apoi determinată optim. Se bazează în principal pe proprietatea unei probleme de a putea fi rezolvată optim dacă se cunosc soluţii optime la sub-problemele ei.\r\nDe menţionat că \'programare\' nu se referă aici la scrierea de cod într-un limbaj de programare, ci la \'programare matematica\', care constă în optimizarea unei funcţii prin alegerea de valori dintr-o mulţime anume. \r\n\r\nScopul acestui articol nu este să ofere o introducere in programare dinamică (pentru aceasta poate fi consultat excelentul tutorial de pe TopCoder \"Dynamic Programming : From novice to advanced\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg). În schimb, acest articol îşi propune să ofere nişte \'smenuri\' mai avansate de rezolvare a problemelor cu programare dinamică. \r\n\r\nh2. Programare dinamică cu reducerea loop-ului interior\r\n\r\nSă considerăm următoarea problema:\r\n\r\nh3(#problema-1). Problema 1: \'Drilling\':http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en\r\n\r\nbq. Se da un şir de $N$ numere naturale $(a{~1~}, a{~2~}, ..., a{~N~})$. Se ştie că un prefix al acestui şir (adică o subsecvenţă de la începutul şirului, posibil nulă) este **defect**. Toate elementele din acel prefix (şi doar din acel prefix) sunt defecte. Se ştie de asemenea că se poate testa orice poziţie $i$ în timp $a{~i~}$ pentru a afla dacă este defectă. Să se determine timpul minim în cazul cel mai defavorabil pentru aflarea lungimii maxime a prefixului şirului care este defect.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(8 24 12 6)$, răspunsul ar fi $42$. Astfel, se testează mai întâi poziţia $2$. Dacă nu este defectă, mai rămâne de testat poziţia $1$. Altfel, în cel mai rău caz mai trebuie testate poziţiile $3$ şi $4$, aducând timpul total la $24 + 12 + 6 = 42$.\r\n\r\nh3. Rezolvare:\r\n\r\nO să începem prin a da altă îmbrăcăminte problemei. Astfel, să ne imaginăm că am construi un arbore binar de căutare pe şirul dat, având drept chei poziţiile din şir, şi drept valori auxiliare valorile poziţiilor respective din şir (un nod cu cheia $i$ va avea valoarea auxiliara $a{~i~}$.\r\nAcum, există mulţi arbori binari de căutare posibile pentru şirul iniţial. Totuşi, să presupunem că am construit unul, pe care îl considerăm de acum ca fixat. Atunci, strategia noastra de testare a elementelor din şir se va desfăşura conforma arborelui. Astfel, testăm mai întâi în poziţia din rădăcină. Dacă poziţia respectivă este defectă, ne ducem în fiul drept. Altfel, mergem in fiul stâng. În ambele cazuri se reia procedeul. Căutarea se termină cand nu mai putem merge într-un fiu. \r\n\r\nSă observăm că dacă considerăm costul unui drum în arbore de la rădăcină la o frunză ca suma valorilor auxiliare din drumul (unic) respectiv, atunci se observă că costul strategiei bazate pe acest arbore este chiar costul maxim al unui drum ! De acum încolo, vom defini costul unui arbore ca costul maxim al unui drum din el. Să exemplificăm pe şirul din exemplu:\r\n\r\n$BAGA POZA$\r\n\r\nSe observă că costul maxim al unui drum este $42$, minim posibil, exact ca răspunsul din exemplu.\r\nDeci, am redus problema la construirea unui arbore binar de căutare, care are costul minim.\r\n\r\nAcum devine clară o primă soluţie folosind programarea dinamică. Astfel, să presupunem că notăm cu @opt[ i ][ j ]@ costul minim al unui arbore construit pe cheile din $[i,j]$ (prin asta notăm (i, i + 1, ..., j). Fie $r[ i ][ j ]$ poziţia rădăcinii arborelui cu costul minim. În cazul existenţei mai multor rădăcini posibile, se alege cea mai din stânga. Cum am putea construi arborele de cost minim pe cheile $[i,j]$ ştiind răspunsul pentru instanţele mai mici (subsecvenţele de lungime mai mică ca $j-i+1$ pe $[i,j]$)? (!) Simplu, arborele de cost minim pe $[i,j]$ se obţine alegând drept rădăcină în mod optim o poziţie $k$, cu <tex>$i \\le k \\le j$</tex>, la care se pune ca fiul stâng arborele optim pentru $[i, k-1]$, şi ca fiu drept arborele optim pentru $[k+1, j]$. Relaţia de recurenţă devine:\r\n\r\n@opt[ i ][ j ]@ = <tex>\\displaystyle\\min_{i \\le k \\le j} \\{a_{k} + \\max( opt[i][k-1], opt[k+1][j] )\\} </tex>   \r\n@r[ i ][ j ]@ = <tex>\\displaystyle\\arg \\min_{i \\le k \\le j}\\{a_{k} + \\max (opt[i][k-1], opt[k+1][j] )\\} </tex> \r\n\r\nAvem @opt[i][j] = 0@, pentru $j < i$.\r\nCazurile de bază sunt @opt[i][i]@ = a{~i~} si @r[i][i] = i@.\r\n\r\nSe observă că răspunsul problemei se află în @opt[1][N]@.\r\nAstfel, am obţinut o soluţie în timp $O(N^3)$.\r\n\r\nAici trebuie remarcată asemănarea acestei probleme cu cea a determinării arborelui de căutare optim, atunci cand se dau probabilităţile relative de căutare a cheilor. Această problemă se numeşte \'Optimal Binary Search Tree\' în literatura de specialitate şi poate fi găsită şi în _Introduction to Algorithms_. În aceasta problemă, se poate aplica o proprietate specială, numită _convexitate_, pentru a reduce complexitatea la $O(N^2)$. Această proprietate reprezintă un concept avansat, care nu se poate aplica în cazul problemei noastre, şi nu va fi discutat în continuare.\r\n\r\nPână acum avem următorul pseudocod pentru calculul recurenţei:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    iniţializează opt şi r\r\n    pentru len = 1, N execută\r\n        pentru i = 1, N - len + 1 execută\r\n            j = i + len - 1;\r\n            opt[i][j] = inf;\r\n            pentru k = i, j execută\r\n                dacă opt[i][j] < a[k] + max(opt[i][k-1], opt[k+1][j]) atunci\r\n                    opt[i][j] = a[k] + max(opt[i][k-1], opt[k+1][j]);\r\n                    r[i][j] = k;\r\n            sfârşit_pentru;\r\n       sfârşit_pentru;\r\n    sfârşit_pentru;\r\n\r\n    return opt[1][N];\r\nSfârşit.\r\n==\r\n\r\nAcum ca să obţinem o complexitate mai bună, ţinând cont şi de numele capitolului, vom încerca să reducem complexitatea loop-ului interior (cel după $k$).\r\n\r\nh3(#problema-2). Problema 2: \'Ugly numbers\':http://code.google.com/codejam/contest/dashboard?c=32015#s=p1&a=1 (Google Code Jam 2008, Round 1C)\r\n\r\nbq. Un număr se numeşte *urât* dacă este divizibil prin oricare dintre numerele prime de o singură cifră, mai exact 2, 3, 5, 7. Se dă un şir de N cifre. Între fiecare 2 cifre consecutive se poate insera unul dintre semnele + sau -. Dacă nu se inserează un semn, cele 2 cifre sunt concatentate astfel încât să se obţină un număr. Pentru un şir dat de cifre si o variantă de a adăuga semne, prin evaluarea expresiei matematice obţinute prin inserarea semnelor se obţine un număr, numit numărul generat. Să se calculeze câte dintre cele 3^N-1^ variante de a insera semnele generează numere urâte.\r\n\r\nh3. Exemplu: \r\n\r\nPentru cifrele *123456*, expresia *1+234-5+6 = 236* care este număr urât, iar *123+4-56 = 71* nu este număr urât.\r\n\r\nh3. Soluţie:\r\n\r\nObservăm că un număr este urât dacă dă cel puţin o dată restul 0 la împărţirea la numerele 2, 3, 5, 7. O abordare a problemei este parcurgerea tuturor variantelor de inserare şi calcularea celor 4 resturi, verificând dacă cel puţin unul este 0.\r\nVom folosi aritmetica modulară pentru a obţine o soluţie mai eficientă a problemei. Vom împărţi cele 3^N-1^ variante în clase, fiecare clasă reprezentând toate numerele care dau resturile $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ la împărţirea la cele 4 numere. Calculând pentru fiecare clasă numărul de numere generate, rezultatul final va fi suma valorilor calculate pentru toate clasele pentru care cel puţin un rest este egal cu 0. Intuim că putem utiliza clasele de resturi într-o soluţie cu programare dinamică.\r\nVom utiliza şirul auxiliar $V[i][j]$ reprezentând numărul format prin concatenarea cifrelor de pe poziţiile consecutive $i, i+1, ..., j$ din şirul dat, fără inserarea unor semne între cifre. De exemplu, @V[2][4] = 234@. Dacă notăm cu $C[i][r{~2~}][r{~3~}][r{~5~}][r{~7~}]$ numărul de variante formate cu primele *i* cifre pentru care clasa de resturi este $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$. Observăm că orice astfel de variantă se obţine dintr-o variantă cu $j < i$ cifre după care adăugam + sau - apoi concatenăm restul cifrelor până la *i* fără semne. Dacă resturile pentru varianta cu *j* cifre erau $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ atunci resturile pentru varianta nouă $(r\'{~2~}, r\'{~3~}, r\'{~5~}, r\'{~7~})$ sunt:\r\n<tex> $r_2\' = (r_2 +/- V[j+1][i])\\% 2$</tex>\r\n<tex> $r_3\' = (r_3 +/- V[j+1][i])\\% 3$</tex>\r\n<tex> $r_5\' = (r_5 +/- V[j+1][i])\\% 5$</tex>\r\n<tex> $r_7\' = (r_7 +/- V[j+1][i])\\% 7$</tex>\r\nAtunci numărul total de variante cu *i* cifre este suma după toate valorile *j* ale numerelor de variante cu *j* cifre:\r\n<tex> $C[i][r_2\'][r_3\'][r_5\'][r_7\'] = \\sum_{j<i} C[j][r_2][r_3][r_5][r_7]$ </tex>\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i]\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = V[i][j - 1] + A[i];\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0][0][0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r_2 = 0, 1 execută\r\n            pentru r_3 = 0, 2 execută\r\n                pentru r_5 = 0, 4 execută\r\n                    pentru r_7 = 0, 6 execută\r\n                        C[i][r_2][r_3][r_5][r_7] = 0;\r\n                        pentru j = 0, i - 1 execută\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + 2 - V[j+1][i])%2)][(r_3 + 3 - V[j+1][i])%3)]\r\n                                                            [(r_5 + 5 - V[j+1][i])%5)][(r_7 + 7 - V[j+1][i])%7)];\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + V[j+1][i])%2)][(r_3 + V[j+1][i])%3)]\r\n                                                            [(r_5 + V[j+1][i])%5)][(r_7 + V[j+1][i])%7)];\r\n                        sfârşit pentru;\r\n\r\n                        dacă i == N şi (r_2 == 0 sau r_3 == 0 sau r_5 == 0 sau r_7 == 0)\r\n                            S += C[i][r_2][r_3][r_5][r_7]\r\n                        sfârşit pentru;\r\n                    sfârşit pentru;\r\n                sfârşit pentru;\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează S;\r\n==\r\n\r\nO problemă în abordarea precedentă este calcularea matricii $V$, ale cărei valori devin foarte mari şi ies din precizia tipurilor de date disponibile. O soluţie posibilă este calcularea câte unei matrici de sume modulo $R$ pentru fiecare rest $R$, adica a 4 matrici $V{~2~}$, $V{~3~}$, $V{~5~}$ si $V{~7~}$ ale resturilor împărţirii valorilor lui $V$ la cele 4 numere prime. Folosind aritmetica modulară, aceste matrici pot fi calculate direct, fără a calcula $V$. Altă variantă este utilizarea teoremei chineze a resturilor, prin care un sistem de ecuaţii modulo câteva numere prime între ele poate fi redus la o ecuaţie modulo produsul numerelor date. În cazul nostru, numerele sunt prime, deci putem aplica teorema. Astfel, putem reduce problema resturilor împărţirii la $(2, 3, 5, 7)$ la problema restului împărţirii la $2*3*5*7=210$, deci fiecare clasa $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ se reduce la un rest $R < 210$. Modificăm pseudocodul astfel:\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i] % 210\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = (V[i][j - 1] + A[i]) % 210;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r = 0, 209 execută\r\n            C[i][r] = 0;\r\n            pentru j = 0, i - 1 execută\r\n                C[i][r] += C[j][(r + 210 - V[j+1][i]) % 210];\r\n                C[i][r] += C[j][(r + V[j+1][i]) % 210];\r\n            sfârşit pentru;\r\n\r\n            dacă i == N şi (r % 2 == 0 sau r % 3 == 0 sau r % 5 == 0 sau r % 7 == 0)\r\n                S += C[i][r];\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează S;   \r\n==\r\n\r\n\r\nh2. Programare dinamica folosind bitmask\r\n\r\nIn continuare vom vedea un exemplu de programare dinamica unde vom folosi un bitmask (codificat pe un intreg) pentru a tine spatiul starilor.\r\n\r\nAstfel sa presupunem ca avem nevoie sa tinem un vector caracteristic pentru o multime.\r\nDaca cardinalul acesteia este suficient de mic putem folosi un intreg pentru a codifica aceasta informatie astfel:\r\n\r\nFie multimea A = { x{~1~}, x{~2~}, ... x{~n~} }.\r\nAtunci bitmaskul unei partitii a lui A, MASK, va avea bitul i egal cu 1 numai si numai daca x{~i~} apartine partitiei.\r\n\r\nDesigur, aceasta reprezentare duce la o complexitate direct proportionala cu 2 ^card(A)^.\r\n\r\nh3. Exemplu\r\n\r\n\r\nh2. Programare dinamica folosind vectori de numere intregi\r\n\r\nTo be continued ... \r\n\r\n',2996,'public',NULL,NULL),('pd','Tehnici avansate de programare dinamică','2007-12-04 21:25:10','2009-11-01 19:43:27','h1. Programare dinamica\r\n\r\n(Categoria _Tehnici de programare_, autori _Catalin Tiseanu_, _Andrei Homescu_)\r\n\r\nTODO:\r\n\r\n1. Reparat link de la ugly numbers\r\n2. Facut poza la Drilling\r\n\r\nPlan de atac (probleme-candidat):\r\n\r\n1. http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en (Reducerea complexitatii, transformarea problemei intr-una de construire a unui arbore binar.)\r\n\r\n2. http://code.google.com/codejam/contest/dashboard?c=32001#s=p0&a=3 (Boolean tree, programare dinamica simpla pe arbore binar.)\r\n\r\n3. http://code.google.com/codejam/contest/dashboard?c=32001#s=p3&a=3 (PermRLE, permutari cu N*2^N)\r\n\r\n4. http://code.google.com/codejam/contest/dashboard?c=32010#s=p3&a=3 (problema cu DP pe matrici, aplicam ridicarea la putere pt calcul rapid)\r\n\r\n5. http://infoarena.ro/problema/doipatru (joc cu solutie DP, stare in 6 dimensiuni)\r\n\r\nh2. Sugestii Silviu\r\n\r\n* poate ca nu trebuie sa spunem tot despre programare dinamica intr-un singur articol; spre exemplu putem facem doua articole: PD basic si PD advanced\r\n* cred ca era si ceva prin Cartea lui Francu\' despre programare dinamica; ar merge incorporat (eventual in pd_basic).\r\n\r\nh2. Introducere\r\n\r\nProgramarea dinamică este o metodă utilă pentru a rezolva probleme care pot fi obţinute prin compunerea a mai multor bucăţi, a căror soluţie poate fi apoi determinată optim. Se bazează în principal pe proprietatea unei probleme de a putea fi rezolvată optim dacă se cunosc soluţii optime la sub-problemele ei.\r\nDe menţionat că \'programare\' nu se referă aici la scrierea de cod într-un limbaj de programare, ci la \'programare matematica\', care constă în optimizarea unei funcţii prin alegerea de valori dintr-o mulţime anume. \r\n\r\nScopul acestui articol nu este să ofere o introducere in programare dinamică (pentru aceasta poate fi consultat excelentul tutorial de pe TopCoder \"Dynamic Programming : From novice to advanced\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg). În schimb, acest articol îşi propune să ofere nişte \'smenuri\' mai avansate de rezolvare a problemelor cu programare dinamică. \r\n\r\nh2. Reducerea loop-ului interior\r\n\r\nSă considerăm următoarea problema:\r\n\r\nh3(#problema-1). Problema 1: \'Drilling\':http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en (Algorithmic Engagements 2009, Round 3)\r\n\r\nbq. Se da un şir de $N$ numere naturale $(a{~1~}, a{~2~}, ..., a{~N~})$. Se ştie că un prefix al acestui şir (adică o subsecvenţă de la începutul şirului, posibil nulă) este **defect**. Toate elementele din acel prefix (şi doar din acel prefix) sunt defecte. Se ştie de asemenea că se poate testa orice poziţie $i$ în timp $a{~i~}$ pentru a afla dacă este defectă. Să se determine timpul minim în cazul cel mai defavorabil pentru aflarea lungimii maxime a prefixului şirului care este defect.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(8 24 12 6)$, răspunsul ar fi $42$. Astfel, se testează mai întâi poziţia $2$. Dacă nu este defectă, mai rămâne de testat poziţia $1$. Altfel, în cel mai rău caz mai trebuie testate poziţiile $3$ şi $4$, aducând timpul total la $24 + 12 + 6 = 42$.\r\n\r\nh3. Rezolvare:\r\n\r\nO să începem prin a da altă îmbrăcăminte problemei. Astfel, să ne imaginăm că am construi un arbore binar de căutare pe şirul dat, având drept chei poziţiile din şir, şi drept valori auxiliare valorile poziţiilor respective din şir (un nod cu cheia $i$ va avea valoarea auxiliara $a{~i~}$.\r\nAcum, există mulţi arbori binari de căutare posibile pentru şirul iniţial. Totuşi, să presupunem că am construit unul, pe care îl considerăm de acum ca fixat. Atunci, strategia noastra de testare a elementelor din şir se va desfăşura conforma arborelui. Astfel, testăm mai întâi în poziţia din rădăcină. Dacă poziţia respectivă este defectă, ne ducem în fiul drept. Altfel, mergem in fiul stâng. În ambele cazuri se reia procedeul. Căutarea se termină cand nu mai putem merge într-un fiu. \r\n\r\nSă observăm că dacă considerăm costul unui drum în arbore de la rădăcină la o frunză ca suma valorilor auxiliare din drumul (unic) respectiv, atunci se observă că costul strategiei bazate pe acest arbore este chiar costul maxim al unui drum ! De acum încolo, vom defini costul unui arbore ca costul maxim al unui drum de la rădăcină la o frunză. Să exemplificăm pe şirul din exemplu:\r\n\r\np=. !pd?Diagram1.png!\r\n\r\np=. _Fig. 1: În paranteză sunt valorile auxiliare ataşate cheilor_\r\n\r\nSe observă că costul maxim al unui drum este $42$, minim posibil, exact ca răspunsul din exemplu. Deci, am redus problema la construirea unui arbore binar de căutare, care are costul minim.\r\n\r\nAcum devine clară o primă soluţie folosind programarea dinamică. Astfel, să presupunem că notăm cu @opt[ i ][ j ]@ costul minim al unui arbore construit pe cheile din $[i,j]$ (prin asta notăm (i, i + 1, ..., j). Fie $r[ i ][ j ]$ poziţia rădăcinii arborelui cu costul minim. În cazul existenţei mai multor rădăcini posibile, se alege cea mai din stânga. Cum am putea construi arborele de cost minim pe cheile $[i,j]$ ştiind răspunsul pentru instanţele mai mici (subsecvenţele de lungime mai mică ca $j-i+1$ pe $[i,j]$)? (!) Simplu, arborele de cost minim pe $[i,j]$ se obţine alegând drept rădăcină în mod optim o poziţie $k$, cu <tex>$i \\le k \\le j$</tex>, la care se pune ca fiul stâng arborele optim pentru $[i, k-1]$, şi ca fiu drept arborele optim pentru $[k+1, j]$. Relaţia de recurenţă devine:\r\n\r\n@opt[ i ][ j ]@ = <tex>\\displaystyle\\min_{i \\le k \\le j} \\{a_{k} + \\max( opt[i][k-1], opt[k+1][j] )\\} </tex>   \r\n@r[ i ][ j ]@ = <tex>\\displaystyle\\arg \\min_{i \\le k \\le j}\\{a_{k} + \\max (opt[i][k-1], opt[k+1][j] )\\} </tex> \r\n\r\nAvem @opt[i][j] = 0@, pentru $j < i$.\r\nCazurile de bază sunt @opt[i][i]@ = a{~i~} si @r[i][i] = i@.\r\n\r\nSe observă că răspunsul problemei se află în @opt[1][N]@.\r\nAstfel, am obţinut o soluţie în timp $O(N^3)$.\r\n\r\nAici trebuie remarcată asemănarea acestei probleme cu cea a determinării arborelui de căutare optim, atunci cand se dau probabilităţile relative de căutare a cheilor. Această problemă se numeşte \'Optimal Binary Search Tree\' în literatura de specialitate şi poate fi găsită şi în _Introduction to Algorithms_. În aceasta problemă, se poate aplica o proprietate specială, numită _convexitate_, pentru a reduce complexitatea la $O(N^2)$. Această proprietate reprezintă un concept avansat, care nu se poate aplica în cazul problemei noastre, şi nu va fi discutat în continuare.\r\n\r\nPână acum avem următorul pseudocod pentru calculul recurenţei:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    iniţializează opt şi r\r\n    pentru len = 1, N execută\r\n        pentru i = 1, N - len + 1 execută\r\n            j = i + len - 1;\r\n            opt[i][j] = inf;\r\n            pentru k = i, j execută\r\n                dacă opt[i][j] < a[k] + max(opt[i][k-1], opt[k+1][j]) atunci\r\n                    opt[i][j] = a[k] + max(opt[i][k-1], opt[k+1][j]);\r\n                    r[i][j] = k;\r\n            sfârşit_pentru;\r\n       sfârşit_pentru;\r\n    sfârşit_pentru;\r\n\r\n    return opt[1][N];\r\nSfârşit.\r\n==\r\n\r\nAcum ca să obţinem o complexitate mai bună, ţinând cont şi de numele capitolului, vom încerca să reducem complexitatea loop-ului interior (cel după $k$).\r\nSă ne uităm mai atent la acest loop.\r\n\r\nFie un interval $[i,j]$ fixat. Acum, $opt[i][j] < opt[i][j\']$, pentru orice $j < j\'$. Similar, $opt[i][j] < opt[i\'][j]$, pentru orice $i\' < i$.\r\nAtunci, există un indice $k$, $i \\le k \\le j$ astfel încât $max(opt[i][o-1], opt[o+1][j]) = opt[o+1][j]$, pentru orice $i \\le o \\le k$, şi $max(opt[i][o-1], opt[o+1][j]) = opt[i][o-1]$ pentru orice <tex>$k < o \\le j$</tex>. După cum ştim, trebuie să aflăm <tex>\\displaystyle\\min_{i \\le k \\le j} \\{a_{k} + \\max( opt[i][k-1], opt[k+1][j] )\\} </tex>. Să definim acum 3 matrici auxiliare:\r\n\r\n@to_left[ i ][ j ] = a_i + opt[ i + 1 ][ j ]@\r\n@to_right[ i ][ j ] = a_j + opt[ i ][ j - 1 ]@\r\n@inter[ i ][ j ] = <tex>\\displaystyle\\arg \\max_{i \\le k \\le j}\\{opt[i][k-1] \\le opt[k+1][j]\\} </tex>\r\n\r\nSe observă că $inter[i][j]$ nu reprezintă altceva decât indicele $k$ tratat in paragraful precedent.\r\nDe asemenea, $inter$ poate fi calculată în $O(N^2)$ observând o proprietate simplă: <tex>$inter[i][j-1] \\le inter[i][j] \\le inter[i+1][j] $</tex>. Aceasta reiese imediat din monotonia lui $opt$ discutată mai sus.\r\n\r\nAcum vine ideea decisivă pentru a reduce complexitatea loop-ului: pentru a afla $opt[i][j]$, este suficient să aflăm maximul dintre 2 valori:\r\n\r\n* <tex>\\displaystyle\\min_{i \\le k \\le inter[i][j]} \\{to_left[k][j]\\} </tex> şi\r\n* <tex>\\displaystyle\\min_{i \\le k \\le inter[i][j]} \\{to_left[k][j]\\} </tex>\r\n\r\n\r\n\r\nh3(#problema-2). Problema 2: \'Ugly numbers\':http://code.google.com/codejam/contest/dashboard?c=32015#s=p1&a=1 (Google Code Jam 2008, Round 1C)\r\n\r\nbq. Un număr se numeşte *urât* dacă este divizibil prin oricare dintre numerele prime de o singură cifră, mai exact $2, 3, 5, 7$. Se dă un şir de $N$ cifre. Între fiecare 2 cifre consecutive se poate insera unul dintre semnele + sau -. Dacă nu se inserează un semn, cele 2 cifre sunt concatentate astfel încât să se obţină un număr. Pentru un şir dat de cifre si o variantă de a adăuga semne, prin evaluarea expresiei matematice obţinute prin inserarea semnelor se obţine un număr, numit numărul generat. Să se calculeze câte dintre cele $3^N-1^$ variante de a insera semnele generează numere urâte.\r\n\r\nh3. Exemplu: \r\n\r\nPentru cifrele $123456$, expresia $1+234-5+6 = 236$ care este număr urât, iar $123+4-56 = 71$ nu este număr urât.\r\n\r\nh3. Rezolvare:\r\n\r\nObservăm că un număr este urât dacă dă cel puţin o dată restul 0 la împărţirea la numerele $2, 3, 5, 7$. O abordare a problemei este parcurgerea tuturor variantelor de inserare şi calcularea celor 4 resturi, verificând dacă cel puţin unul este 0.\r\nVom folosi aritmetica modulară pentru a obţine o soluţie mai eficientă a problemei. Vom împărţi cele $3^N-1^$ variante în clase, fiecare clasă reprezentând toate numerele care dau resturile $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ la împărţirea la cele 4 numere. Calculând pentru fiecare clasă numărul de numere generate, rezultatul final va fi suma valorilor calculate pentru toate clasele pentru care cel puţin un rest este egal cu 0. Intuim că putem utiliza clasele de resturi într-o soluţie cu programare dinamică.\r\nVom utiliza şirul auxiliar $V[i][j]$ reprezentând numărul format prin concatenarea cifrelor de pe poziţiile consecutive $i, i+1, ..., j$ din şirul dat, fără inserarea unor semne între cifre. De exemplu, @V[2][4] = 234@. Dacă notăm cu $C[i][r{~2~}][r{~3~}][r{~5~}][r{~7~}]$ numărul de variante formate cu primele $i$ cifre pentru care clasa de resturi este $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$. Observăm că orice astfel de variantă se obţine dintr-o variantă cu $j < i$ cifre după care adăugam + sau - apoi concatenăm restul cifrelor până la $i$ fără semne. Dacă resturile pentru varianta cu $j$ cifre erau $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ atunci resturile pentru varianta nouă $(r\'{~2~}, r\'{~3~}, r\'{~5~}, r\'{~7~})$ sunt:\r\n<tex> $r_2\' = (r_2 +/- V[j+1][i])\\% 2$</tex>\r\n<tex> $r_3\' = (r_3 +/- V[j+1][i])\\% 3$</tex>\r\n<tex> $r_5\' = (r_5 +/- V[j+1][i])\\% 5$</tex>\r\n<tex> $r_7\' = (r_7 +/- V[j+1][i])\\% 7$</tex>\r\nAtunci numărul total de variante cu $i$ cifre este suma după toate valorile $j$ ale numerelor de variante cu $j$ cifre:\r\n<tex> $C[i][r_2\'][r_3\'][r_5\'][r_7\'] = \\sum_{j<i} C[j][r_2][r_3][r_5][r_7]$ </tex>\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i]\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = V[i][j - 1] + A[i];\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0][0][0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r_2 = 0, 1 execută\r\n            pentru r_3 = 0, 2 execută\r\n                pentru r_5 = 0, 4 execută\r\n                    pentru r_7 = 0, 6 execută\r\n                        C[i][r_2][r_3][r_5][r_7] = 0;\r\n                        pentru j = 0, i - 1 execută\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + 2 - V[j+1][i])%2)][(r_3 + 3 - V[j+1][i])%3)]\r\n                                                            [(r_5 + 5 - V[j+1][i])%5)][(r_7 + 7 - V[j+1][i])%7)];\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + V[j+1][i])%2)][(r_3 + V[j+1][i])%3)]\r\n                                                            [(r_5 + V[j+1][i])%5)][(r_7 + V[j+1][i])%7)];\r\n                        sfârşit pentru;\r\n\r\n                        dacă i == N şi (r_2 == 0 sau r_3 == 0 sau r_5 == 0 sau r_7 == 0)\r\n                            S += C[i][r_2][r_3][r_5][r_7]\r\n                        sfârşit pentru;\r\n                    sfârşit pentru;\r\n                sfârşit pentru;\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează S;\r\n==\r\n\r\nO problemă în abordarea precedentă este calcularea matricii $V$, ale cărei valori devin foarte mari şi ies din precizia tipurilor de date disponibile. O soluţie posibilă este calcularea câte unei matrici de sume modulo $R$ pentru fiecare rest $R$, adica a 4 matrici $V{~2~}$, $V{~3~}$, $V{~5~}$ si $V{~7~}$ ale resturilor împărţirii valorilor lui $V$ la cele 4 numere prime. Folosind aritmetica modulară, aceste matrici pot fi calculate direct, fără a calcula $V$. Altă variantă este utilizarea teoremei chineze a resturilor, prin care un sistem de ecuaţii modulo câteva numere prime între ele poate fi redus la o ecuaţie modulo produsul numerelor date. În cazul nostru, numerele sunt prime, deci putem aplica teorema. Astfel, putem reduce problema resturilor împărţirii la $(2, 3, 5, 7)$ la problema restului împărţirii la $2*3*5*7=210$, deci fiecare clasa $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ se reduce la un rest $R < 210$. Modificăm pseudocodul astfel:\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i] % 210\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = (V[i][j - 1] + A[i]) % 210;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r = 0, 209 execută\r\n            C[i][r] = 0;\r\n            pentru j = 0, i - 1 execută\r\n                C[i][r] += C[j][(r + 210 - V[j+1][i]) % 210];\r\n                C[i][r] += C[j][(r + V[j+1][i]) % 210];\r\n            sfârşit pentru;\r\n\r\n            dacă i == N şi (r % 2 == 0 sau r % 3 == 0 sau r % 5 == 0 sau r % 7 == 0)\r\n                S += C[i][r];\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează S;   \r\n==\r\n\r\n\r\nh2. Programare dinamica folosind bitmask\r\n\r\nIn continuare vom vedea un exemplu de programare dinamica unde vom folosi un bitmask (codificat pe un intreg) pentru a tine spatiul starilor.\r\n\r\nAstfel sa presupunem ca avem nevoie sa tinem un vector caracteristic pentru o multime.\r\nDaca cardinalul acesteia este suficient de mic putem folosi un intreg pentru a codifica aceasta informatie astfel:\r\n\r\nFie multimea A = { x{~1~}, x{~2~}, ... x{~n~} }.\r\nAtunci bitmaskul unei partitii a lui A, MASK, va avea bitul i egal cu 1 numai si numai daca x{~i~} apartine partitiei.\r\n\r\nDesigur, aceasta reprezentare duce la o complexitate direct proportionala cu 2 ^card(A)^.\r\n\r\nh3. Exemplu\r\n\r\n\r\nh2. Programare dinamica folosind vectori de numere intregi\r\n\r\nTo be continued ... \r\n\r\n',958,'public',NULL,NULL),('pd','Tehnici avansate de programare dinamică','2007-12-04 21:25:10','2009-11-02 16:46:25','h1. Tehnici avansate de programare dinamică\r\n\r\n(Categoria _Tehnici de programare_, autori _Catalin Tiseanu_, _Andrei Homescu_)\r\n\r\nTODO:\r\n\r\n1. Reparat link de la ugly numbers\r\n\r\nPlan de atac (probleme-candidat):\r\n\r\n1. http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en (Reducerea complexitatii, transformarea problemei intr-una de construire a unui arbore binar.)\r\n\r\n2. http://code.google.com/codejam/contest/dashboard?c=32001#s=p0&a=3 (Boolean tree, programare dinamica simpla pe arbore binar.)\r\n\r\n3. http://code.google.com/codejam/contest/dashboard?c=32001#s=p3&a=3 (PermRLE, permutari cu N*2^N)\r\n\r\n4. http://code.google.com/codejam/contest/dashboard?c=32010#s=p3&a=3 (problema cu DP pe matrici, aplicam ridicarea la putere pt calcul rapid)\r\n\r\n5. http://infoarena.ro/problema/doipatru (joc cu solutie DP, stare in 6 dimensiuni)\r\n\r\nh2. Sugestii Silviu\r\n\r\n* poate ca nu trebuie sa spunem tot despre programare dinamica intr-un singur articol; spre exemplu putem facem doua articole: PD basic si PD advanced\r\n* cred ca era si ceva prin Cartea lui Francu\' despre programare dinamica; ar merge incorporat (eventual in pd_basic).\r\n\r\nh2. Introducere\r\n\r\nProgramarea dinamică este o metodă utilă pentru a rezolva probleme care pot fi obţinute prin compunerea a mai multor bucăţi, a căror soluţie poate fi apoi determinată optim. Se bazează în principal pe proprietatea unei probleme de a putea fi rezolvată optim dacă se cunosc soluţii optime la sub-problemele ei.\r\nDe menţionat că \'programare\' nu se referă aici la scrierea de cod într-un limbaj de programare, ci la \'programare matematica\', care constă în optimizarea unei funcţii prin alegerea de valori dintr-o mulţime anume. \r\n\r\nScopul acestui articol nu este să ofere o introducere in programare dinamică (pentru aceasta poate fi consultat excelentul tutorial de pe TopCoder \"Dynamic Programming : From novice to advanced\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg). În schimb, acest articol îşi propune să ofere nişte \'smenuri\' mai avansate de rezolvare a problemelor cu programare dinamică. \r\n\r\nh2. Reducerea loop-ului interior\r\n\r\nSă considerăm următoarea problema:\r\n\r\nh3(#problema-1). Problema 1: \'Drilling\':http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en (Algorithmic Engagements 2009, Round 3)\r\n\r\nbq. Se da un şir de $N$ numere naturale $(a{~1~}, a{~2~}, ..., a{~N~})$. Se ştie că un prefix al acestui şir (adică o subsecvenţă de la începutul şirului, posibil nulă) este **defect**. Toate elementele din acel prefix (şi doar din acel prefix) sunt defecte. Se ştie de asemenea că se poate testa orice poziţie $i$ în timp $a{~i~}$ pentru a afla dacă este defectă. Să se determine timpul minim în cazul cel mai defavorabil pentru aflarea lungimii maxime a prefixului şirului care este defect.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(8 24 12 6)$, răspunsul ar fi $42$. Astfel, se testează mai întâi poziţia $2$. Dacă nu este defectă, mai rămâne de testat poziţia $1$. Altfel, în cel mai rău caz mai trebuie testate poziţiile $3$ şi $4$, aducând timpul total la $24 + 12 + 6 = 42$.\r\n\r\nh3. Rezolvare:\r\n\r\nO să începem prin a da altă îmbrăcăminte problemei. Astfel, să ne imaginăm că am construi un arbore binar de căutare pe şirul dat, având drept chei poziţiile din şir, şi drept valori auxiliare valorile poziţiilor respective din şir (un nod cu cheia $i$ va avea valoarea auxiliara $a{~i~}$.\r\nAcum, există mulţi arbori binari de căutare posibile pentru şirul iniţial. Totuşi, să presupunem că am construit unul, pe care îl considerăm de acum ca fixat. Atunci, strategia noastra de testare a elementelor din şir se va desfăşura conforma arborelui. Astfel, testăm mai întâi în poziţia din rădăcină. Dacă poziţia respectivă este defectă, ne ducem în fiul drept. Altfel, mergem in fiul stâng. În ambele cazuri se reia procedeul. Căutarea se termină cand nu mai putem merge într-un fiu. \r\n\r\nSă observăm că dacă considerăm costul unui drum în arbore de la rădăcină la o frunză ca suma valorilor auxiliare din drumul (unic) respectiv, atunci se observă că costul strategiei bazate pe acest arbore este chiar costul maxim al unui drum ! De acum încolo, vom defini costul unui arbore ca costul maxim al unui drum de la rădăcină la o frunză. Să exemplificăm pe şirul din exemplu:\r\n\r\np=. !pd?Diagram1.png!\r\n\r\np=. _Fig. 1: În paranteză sunt valorile auxiliare ataşate cheilor_\r\n\r\nSe observă că costul maxim al unui drum este $42$, minim posibil, exact ca răspunsul din exemplu. Deci, am redus problema la construirea unui arbore binar de căutare, care are costul minim.\r\n\r\nAcum devine clară o primă soluţie folosind programarea dinamică. Astfel, să presupunem că notăm cu $opt[ i ][ j ]$ costul minim al unui arbore construit pe cheile din $[i,j]$ (prin asta notăm (i, i + 1, ..., j). Fie $r[ i ][ j ]$ poziţia rădăcinii arborelui cu costul minim. În cazul existenţei mai multor rădăcini posibile, se alege cea mai din stânga. Cum am putea construi arborele de cost minim pe cheile $[i,j]$ ştiind răspunsul pentru instanţele mai mici (subsecvenţele de lungime mai mică ca $j-i+1$ pe $[i,j]$)? (!) Simplu, arborele de cost minim pe $[i,j]$ se obţine alegând drept rădăcină în mod optim o poziţie $k$, cu <tex>$i \\le k \\le j$</tex>, la care se pune ca fiul stâng arborele optim pentru $[i, k-1]$, şi ca fiu drept arborele optim pentru $[k+1, j]$. Relaţia de recurenţă devine:\r\n\r\n$opt[ i ][ j ]$ = <tex>\\displaystyle\\min_{i \\le k \\le j} \\{a_{k} + \\max( opt[i][k-1], opt[k+1][j] )\\} </tex>   \r\n$r[ i ][ j ]$ = <tex>\\displaystyle\\arg \\min_{i \\le k \\le j}\\{a_{k} + \\max (opt[i][k-1], opt[k+1][j] )\\} </tex> \r\n\r\nAvem @opt[i][j] = 0@, pentru $j < i$.\r\nCazurile de bază sunt @opt[i][i]@ = a{~i~} si @r[i][i] = i@.\r\n\r\nSe observă că răspunsul problemei se află în @opt[1][N]@.\r\nAstfel, am obţinut o soluţie în timp $O(N^3)$.\r\n\r\nAici trebuie remarcată asemănarea acestei probleme cu cea a determinării arborelui de căutare optim, atunci cand se dau probabilităţile relative de căutare a cheilor. Această problemă se numeşte \'Optimal Binary Search Tree\' în literatura de specialitate şi poate fi găsită şi în _Introduction to Algorithms_. În aceasta problemă, se poate aplica o reducere a complexităţii datorită faptului că <tex>$ r[i][j-1] \\le r[i][j] \\le r[i+1][j] $</tex> pentru a reduce complexitatea la $O(N^2)$. Această proprietate nu se poate aplica din păcate şi în cazul problemei noastre.\r\n\r\nPână acum avem următorul pseudocod pentru calculul recurenţei:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    iniţializează opt şi r\r\n    pentru len = 1, N execută\r\n        pentru i = 1, N - len + 1 execută\r\n            j = i + len - 1;\r\n            opt[i][j] = inf;\r\n            pentru k = i, j execută\r\n                dacă opt[i][j] < a[k] + max(opt[i][k-1], opt[k+1][j]) atunci\r\n                    opt[i][j] = a[k] + max(opt[i][k-1], opt[k+1][j]);\r\n                    r[i][j] = k;\r\n            sfârşit_pentru;\r\n       sfârşit_pentru;\r\n    sfârşit_pentru;\r\n\r\n    return opt[1][N];\r\nSfârşit.\r\n==\r\n\r\nAcum ca să obţinem o complexitate mai bună, ţinând cont şi de numele capitolului, vom încerca să reducem complexitatea loop-ului interior (cel după $k$).\r\nSă ne uităm mai atent la acest loop.\r\n\r\nFie un interval $[i,j]$ fixat. Acum, $opt[i][j] < opt[i][j\']$, pentru orice $j < j\'$. Similar, $opt[i][j] < opt[i\'][j]$, pentru orice $i\' < i$.\r\nAtunci, există un indice $k$, <tex>$i \\le k \\le j$</tex> astfel încât $max(opt[i][o-1], opt[o+1][j]) = opt[o+1][j]$, pentru orice <tex>$i \\le o \\le k$</tex>, şi $max(opt[i][o-1], opt[o+1][j]) = opt[i][o-1]$ pentru orice <tex>$k \\le o \\le j$</tex>. După cum ştim, trebuie să aflăm <tex>\\displaystyle\\min_{i \\le k \\le j} \\{a_{k} + \\max( opt[i][k-1], opt[k+1][j] )\\} </tex>. Să definim acum 3 matrici auxiliare:\r\n\r\n@to_left[ i ][ j ]@ = $a{~i~} + opt[ i + 1 ][ j ]$\r\n@to_right[ i ][ j ]@ = $a{~j~} + opt[ i ][ j - 1 ]$\r\n@inter[ i ][ j ]@ = <tex>\\displaystyle\\arg \\max_{i \\le k \\le j}\\{opt[i][k-1] \\le opt[k+1][j]\\} </tex>\r\n\r\nSe observă că $inter[i][j]$ nu reprezintă altceva decât indicele $k$ tratat in paragraful precedent.\r\nDe asemenea, $inter$ poate fi calculată în $O(N^2)$ observând o proprietate simplă: <tex>$ inter[i][j-1] \\le inter[i][j] \\le inter[i+1][j] $</tex>. Aceasta reiese imediat din monotonia lui $opt$ discutată mai sus. Pseudocodul pentru calculul lui $inter$ este:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    iniţializează opt, inter şi r\r\n    pentru len = 1, N execută\r\n        pentru i = 1, N - len + 1 execută\r\n            j = i + len - 1;\r\n            calculează opt[i][j]\r\n            pentru k = inter[i][j-1], inter[i+1][j] execută\r\n                dacă opt[i][k-1] <= opt[k+1][j] atunci\r\n                    inter[i][j] = k;\r\n            sfârşit_pentru;\r\n       sfârşit_pentru;\r\n    sfârşit_pentru;\r\nSfârşit.\r\n==\r\n\r\nDe menţionat că trebuie avut grijă la cazul când $len$ este mai mic ca $3$. Pseudocodul prezentat mai sus este orientativ.\r\nSă vedem acum de ce această modalitate de calcul a lui $inter$ duce la o complexitate de $O(N^2)$.\r\n\r\nAlternativ, se poate căuta binar $inter[i][j]$ pentru orice $[i,j]$.\r\n\r\nAcum vine ideea decisivă pentru a reduce complexitatea loop-ului: pentru a afla $opt[i][j]$, este suficient să aflăm minimul dintre 2 valori:\r\n\r\n* <tex>\\displaystyle\\min_{i \\le k \\le inter[i][j]} \\{$to\\_left[k][j]$\\} </tex> şi\r\n* <tex>\\displaystyle\\min_{inter[i][j] < k \\le j } \\{$to\\_right[i][k]$\\} </tex>\r\n\r\nMai exact,\r\n\r\n@opt[ i ][ j ]@ = <tex> \\min( \\displaystyle\\min_{i \\le k \\le inter[i][j]} \\{$to\\_left[k][j]$\\},\r\n                              \\displaystyle\\min_{inter[i][j] < k \\le j } \\{$to\\_right[i][k]$\\} ) </tex>\r\n\r\nDiferenţa faţă de prima recurentă este evidentă: acum trebuie să aflăm minimul pe un interval de linii, în cazul $to_left$, şi minimul pe un interval de coloane, în cazul $to_right$. Atât aflarea mnimului pe un interval, cât şi update-ul acestei valori se poate face în $O(logN)$, folosind \'arbori de intervale\':http://infoarena.ro/arbori-de-intervale.\r\n\r\nAstfel, am redus complexitatea loopului interior de la $O(N)$ la $O(logN)$.\r\n\r\n\r\n\r\nh2. Programare dinamica folosind bitmask\r\n\r\nIn continuare vom vedea un exemplu de programare dinamica unde vom folosi un bitmask (codificat pe un intreg) pentru a tine spatiul starilor.\r\n\r\nAstfel sa presupunem ca avem nevoie sa tinem un vector caracteristic pentru o multime.\r\nDaca cardinalul acesteia este suficient de mic putem folosi un intreg pentru a codifica aceasta informatie astfel:\r\n\r\nFie multimea A = { x{~1~}, x{~2~}, ... x{~n~} }.\r\nAtunci bitmaskul unei partitii a lui A, MASK, va avea bitul i egal cu 1 numai si numai daca x{~i~} apartine partitiei.\r\n\r\nDesigur, aceasta reprezentare duce la o complexitate direct proportionala cu 2 ^card(A)^.\r\n\r\nh3. Exemplu\r\n\r\n\r\nh2. Programare dinamica folosind vectori de numere intregi\r\n\r\nh3(#problema-1). Problema 1: \'Ugly numbers\':http://code.google.com/codejam/contest/dashboard?c=32015#s=p1&a=1 (Google Code Jam 2008, Round 1C)\r\n\r\nbq. Un număr se numeşte *urât* dacă este divizibil prin oricare dintre numerele prime de o singură cifră, mai exact $2, 3, 5, 7$. Se dă un şir de $N$ cifre. Între fiecare 2 cifre consecutive se poate insera unul dintre semnele + sau -. Dacă nu se inserează un semn, cele 2 cifre sunt concatentate astfel încât să se obţină un număr. Pentru un şir dat de cifre si o variantă de a adăuga semne, prin evaluarea expresiei matematice obţinute prin inserarea semnelor se obţine un număr, numit numărul generat. Să se calculeze câte dintre cele $3^N-1^$ variante de a insera semnele generează numere urâte.\r\n\r\nh3. Exemplu: \r\n\r\nPentru cifrele $123456$, expresia $1+234-5+6 = 236$ care este număr urât, iar $123+4-56 = 71$ nu este număr urât.\r\n\r\nh3. Rezolvare:\r\n\r\nObservăm că un număr este urât dacă dă cel puţin o dată restul 0 la împărţirea la numerele $2, 3, 5, 7$. O abordare a problemei este parcurgerea tuturor variantelor de inserare şi calcularea celor 4 resturi, verificând dacă cel puţin unul este 0.\r\nVom folosi aritmetica modulară pentru a obţine o soluţie mai eficientă a problemei. Vom împărţi cele $3^N-1^$ variante în clase, fiecare clasă reprezentând toate numerele care dau resturile $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ la împărţirea la cele 4 numere. Calculând pentru fiecare clasă numărul de numere generate, rezultatul final va fi suma valorilor calculate pentru toate clasele pentru care cel puţin un rest este egal cu 0. Intuim că putem utiliza clasele de resturi într-o soluţie cu programare dinamică.\r\nVom utiliza şirul auxiliar $V[i][j]$ reprezentând numărul format prin concatenarea cifrelor de pe poziţiile consecutive $i, i+1, ..., j$ din şirul dat, fără inserarea unor semne între cifre. De exemplu, @V[2][4] = 234@. Dacă notăm cu $C[i][r{~2~}][r{~3~}][r{~5~}][r{~7~}]$ numărul de variante formate cu primele $i$ cifre pentru care clasa de resturi este $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$. Observăm că orice astfel de variantă se obţine dintr-o variantă cu $j < i$ cifre după care adăugam + sau - apoi concatenăm restul cifrelor până la $i$ fără semne. Dacă resturile pentru varianta cu $j$ cifre erau $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ atunci resturile pentru varianta nouă $(r\'{~2~}, r\'{~3~}, r\'{~5~}, r\'{~7~})$ sunt:\r\n<tex> $r_2\' = (r_2 +/- V[j+1][i])\\% 2$</tex>\r\n<tex> $r_3\' = (r_3 +/- V[j+1][i])\\% 3$</tex>\r\n<tex> $r_5\' = (r_5 +/- V[j+1][i])\\% 5$</tex>\r\n<tex> $r_7\' = (r_7 +/- V[j+1][i])\\% 7$</tex>\r\nAtunci numărul total de variante cu $i$ cifre este suma după toate valorile $j$ ale numerelor de variante cu $j$ cifre:\r\n<tex> $C[i][r_2\'][r_3\'][r_5\'][r_7\'] = \\sum_{j<i} C[j][r_2][r_3][r_5][r_7]$ </tex>\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i]\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = V[i][j - 1] + A[i];\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0][0][0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r_2 = 0, 1 execută\r\n            pentru r_3 = 0, 2 execută\r\n                pentru r_5 = 0, 4 execută\r\n                    pentru r_7 = 0, 6 execută\r\n                        C[i][r_2][r_3][r_5][r_7] = 0;\r\n                        pentru j = 0, i - 1 execută\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + 2 - V[j+1][i])%2)][(r_3 + 3 - V[j+1][i])%3)]\r\n                                                            [(r_5 + 5 - V[j+1][i])%5)][(r_7 + 7 - V[j+1][i])%7)];\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + V[j+1][i])%2)][(r_3 + V[j+1][i])%3)]\r\n                                                            [(r_5 + V[j+1][i])%5)][(r_7 + V[j+1][i])%7)];\r\n                        sfârşit pentru;\r\n\r\n                        dacă i == N şi (r_2 == 0 sau r_3 == 0 sau r_5 == 0 sau r_7 == 0)\r\n                            S += C[i][r_2][r_3][r_5][r_7]\r\n                        sfârşit pentru;\r\n                    sfârşit pentru;\r\n                sfârşit pentru;\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează S;\r\n==\r\n\r\nO problemă în abordarea precedentă este calcularea matricii $V$, ale cărei valori devin foarte mari şi ies din precizia tipurilor de date disponibile. O soluţie posibilă este calcularea câte unei matrici de sume modulo $R$ pentru fiecare rest $R$, adica a 4 matrici $V{~2~}$, $V{~3~}$, $V{~5~}$ si $V{~7~}$ ale resturilor împărţirii valorilor lui $V$ la cele 4 numere prime. Folosind aritmetica modulară, aceste matrici pot fi calculate direct, fără a calcula $V$. Altă variantă este utilizarea teoremei chineze a resturilor, prin care un sistem de ecuaţii modulo câteva numere prime între ele poate fi redus la o ecuaţie modulo produsul numerelor date. În cazul nostru, numerele sunt prime, deci putem aplica teorema. Astfel, putem reduce problema resturilor împărţirii la $(2, 3, 5, 7)$ la problema restului împărţirii la $2*3*5*7=210$, deci fiecare clasa $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ se reduce la un rest $R < 210$. Modificăm pseudocodul astfel:\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i] % 210\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = (V[i][j - 1] + A[i]) % 210;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r = 0, 209 execută\r\n            C[i][r] = 0;\r\n            pentru j = 0, i - 1 execută\r\n                C[i][r] += C[j][(r + 210 - V[j+1][i]) % 210];\r\n                C[i][r] += C[j][(r + V[j+1][i]) % 210];\r\n            sfârşit pentru;\r\n\r\n            dacă i == N şi (r % 2 == 0 sau r % 3 == 0 sau r % 5 == 0 sau r % 7 == 0)\r\n                S += C[i][r];\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează S;   \r\n==\r\n\r\n\r\n\r\nTo be continued ... \r\n\r\n',2996,'public',NULL,NULL),('pd','Tehnici avansate de programare dinamică','2007-12-04 21:25:10','2009-11-02 17:50:35','h1. Tehnici avansate de programare dinamică\r\n\r\n(Categoria _Tehnici de programare_, autori _Catalin Tiseanu_, _Andrei Homescu_)\r\n\r\nTODO:\r\n\r\n1. Reparat link de la ugly numbers\r\n\r\nPlan de atac (probleme-candidat):\r\n\r\n1. http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en (Reducerea complexitatii, transformarea problemei intr-una de construire a unui arbore binar.)\r\n\r\n2. http://code.google.com/codejam/contest/dashboard?c=32001#s=p0&a=3 (Boolean tree, programare dinamica simpla pe arbore binar.)\r\n\r\n3. http://code.google.com/codejam/contest/dashboard?c=32001#s=p3&a=3 (PermRLE, permutari cu N*2^N)\r\n\r\n4. http://code.google.com/codejam/contest/dashboard?c=32010#s=p3&a=3 (problema cu DP pe matrici, aplicam ridicarea la putere pt calcul rapid)\r\n\r\n5. http://infoarena.ro/problema/doipatru (joc cu solutie DP, stare in 6 dimensiuni)\r\n\r\nh2. Sugestii Silviu\r\n\r\n* poate ca nu trebuie sa spunem tot despre programare dinamica intr-un singur articol; spre exemplu putem facem doua articole: PD basic si PD advanced\r\n* cred ca era si ceva prin Cartea lui Francu\' despre programare dinamica; ar merge incorporat (eventual in pd_basic).\r\n\r\nh2. Introducere\r\n\r\nProgramarea dinamică este o metodă utilă pentru a rezolva probleme care pot fi obţinute prin compunerea a mai multor bucăţi, a căror soluţie poate fi apoi determinată optim. Se bazează în principal pe proprietatea unei probleme de a putea fi rezolvată optim dacă se cunosc soluţii optime la sub-problemele ei.\r\nDe menţionat că \'programare\' nu se referă aici la scrierea de cod într-un limbaj de programare, ci la \'programare matematica\', care constă în optimizarea unei funcţii prin alegerea de valori dintr-o mulţime anume. \r\n\r\nScopul acestui articol nu este să ofere o introducere in programare dinamică (pentru aceasta poate fi consultat excelentul tutorial de pe TopCoder \"Dynamic Programming : From novice to advanced\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg). În schimb, acest articol îşi propune să ofere nişte \'smenuri\' mai avansate de rezolvare a problemelor cu programare dinamică. \r\n\r\nh2. Reducerea loop-ului interior\r\n\r\nSă considerăm următoarea problema:\r\n\r\nh3(#problema-1). Problema 1: \'Drilling\':http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en (Algorithmic Engagements 2009, Round 3)\r\n\r\nbq. Se da un şir de $N$ numere naturale $(a{~1~}, a{~2~}, ..., a{~N~})$. Se ştie că un prefix al acestui şir (adică o subsecvenţă de la începutul şirului, posibil nulă) este **defect**. Toate elementele din acel prefix (şi doar din acel prefix) sunt defecte. Se ştie de asemenea că se poate testa orice poziţie $i$ în timp $a{~i~}$ pentru a afla dacă este defectă. Să se determine timpul minim în cazul cel mai defavorabil pentru aflarea lungimii maxime a prefixului şirului care este defect.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(8 24 12 6)$, răspunsul ar fi $42$. Astfel, se testează mai întâi poziţia $2$. Dacă nu este defectă, mai rămâne de testat poziţia $1$. Altfel, în cel mai rău caz mai trebuie testate poziţiile $3$ şi $4$, aducând timpul total la $24 + 12 + 6 = 42$.\r\n\r\nh3. Rezolvare:\r\n\r\nO să începem prin a da altă îmbrăcăminte problemei. Astfel, să ne imaginăm că am construi un arbore binar de căutare pe şirul dat, având drept chei poziţiile din şir, şi drept valori auxiliare valorile poziţiilor respective din şir (un nod cu cheia $i$ va avea valoarea auxiliara $a{~i~}$.\r\nAcum, există mulţi arbori binari de căutare posibile pentru şirul iniţial. Totuşi, să presupunem că am construit unul, pe care îl considerăm de acum ca fixat. Atunci, strategia noastra de testare a elementelor din şir se va desfăşura conforma arborelui. Astfel, testăm mai întâi în poziţia din rădăcină. Dacă poziţia respectivă este defectă, ne ducem în fiul drept. Altfel, mergem in fiul stâng. În ambele cazuri se reia procedeul. Căutarea se termină cand nu mai putem merge într-un fiu. \r\n\r\nSă observăm că dacă considerăm costul unui drum în arbore de la rădăcină la o frunză ca suma valorilor auxiliare din drumul (unic) respectiv, atunci se observă că costul strategiei bazate pe acest arbore este chiar costul maxim al unui drum ! De acum încolo, vom defini costul unui arbore ca costul maxim al unui drum de la rădăcină la o frunză. Să exemplificăm pe şirul din exemplu:\r\n\r\np=. !pd?Diagram1.png!\r\n\r\np=. _Fig. 1: În paranteză sunt valorile auxiliare ataşate cheilor_\r\n\r\nSe observă că costul maxim al unui drum este $42$, minim posibil, exact ca răspunsul din exemplu. Deci, am redus problema la construirea unui arbore binar de căutare, care are costul minim.\r\n\r\nAcum devine clară o primă soluţie folosind programarea dinamică. Astfel, să presupunem că notăm cu $opt[ i ][ j ]$ costul minim al unui arbore construit pe cheile din $[i,j]$ (prin asta notăm (i, i + 1, ..., j). Fie $r[ i ][ j ]$ poziţia rădăcinii arborelui cu costul minim. În cazul existenţei mai multor rădăcini posibile, se alege cea mai din stânga. Cum am putea construi arborele de cost minim pe cheile $[i,j]$ ştiind răspunsul pentru instanţele mai mici (subsecvenţele de lungime mai mică ca $j-i+1$ pe $[i,j]$)? (!) Simplu, arborele de cost minim pe $[i,j]$ se obţine alegând drept rădăcină în mod optim o poziţie $k$, cu <tex>$i \\le k \\le j$</tex>, la care se pune ca fiul stâng arborele optim pentru $[i, k-1]$, şi ca fiu drept arborele optim pentru $[k+1, j]$. Relaţia de recurenţă devine:\r\n\r\n$opt[ i ][ j ]$ = <tex>\\displaystyle\\min_{i \\le k \\le j} \\{a_{k} + \\max( opt[i][k-1], opt[k+1][j] )\\} </tex>   \r\n$r[ i ][ j ]$ = <tex>\\displaystyle\\arg \\min_{i \\le k \\le j}\\{a_{k} + \\max (opt[i][k-1], opt[k+1][j] )\\} </tex> \r\n\r\nAvem @opt[i][j] = 0@, pentru $j < i$.\r\nCazurile de bază sunt @opt[i][i]@ = a{~i~} si @r[i][i] = i@.\r\n\r\nSe observă că răspunsul problemei se află în @opt[1][N]@.\r\nAstfel, am obţinut o soluţie în timp $O(N^3)$.\r\n\r\nAici trebuie remarcată asemănarea acestei probleme cu cea a determinării arborelui de căutare optim, atunci cand se dau probabilităţile relative de căutare a cheilor. Această problemă se numeşte \'Optimal Binary Search Tree\' în literatura de specialitate şi poate fi găsită şi în _Introduction to Algorithms_. În aceasta problemă, se poate aplica o reducere a complexităţii datorită faptului că <tex>$ r[i][j-1] \\le r[i][j] \\le r[i+1][j] $</tex> pentru a reduce complexitatea la $O(N^2)$. Această proprietate nu se poate aplica din păcate şi în cazul problemei noastre.\r\n\r\nPână acum avem următorul pseudocod pentru calculul recurenţei:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    iniţializează opt şi r\r\n    pentru len = 1, N execută\r\n        pentru i = 1, N - len + 1 execută\r\n            j = i + len - 1;\r\n            opt[i][j] = inf;\r\n            pentru k = i, j execută\r\n                dacă opt[i][j] < a[k] + max(opt[i][k-1], opt[k+1][j]) atunci\r\n                    opt[i][j] = a[k] + max(opt[i][k-1], opt[k+1][j]);\r\n                    r[i][j] = k;\r\n            sfârşit_pentru;\r\n       sfârşit_pentru;\r\n    sfârşit_pentru;\r\n\r\n    return opt[1][N];\r\nSfârşit.\r\n==\r\n\r\nAcum ca să obţinem o complexitate mai bună, ţinând cont şi de numele capitolului, vom încerca să reducem complexitatea loop-ului interior (cel după $k$).\r\nSă ne uităm mai atent la acest loop.\r\n\r\nFie un interval $[i,j]$ fixat. Acum, $opt[i][j] < opt[i][j\']$, pentru orice $j < j\'$. Similar, $opt[i][j] < opt[i\'][j]$, pentru orice $i\' < i$.\r\nAtunci, există un indice $k$, <tex>$i \\le k \\le j$</tex> astfel încât $max(opt[i][o-1], opt[o+1][j]) = opt[o+1][j]$, pentru orice <tex>$i \\le o \\le k$</tex>, şi $max(opt[i][o-1], opt[o+1][j]) = opt[i][o-1]$ pentru orice <tex>$k \\le o \\le j$</tex>. După cum ştim, trebuie să aflăm <tex>\\displaystyle\\min_{i \\le k \\le j} \\{a_{k} + \\max( opt[i][k-1], opt[k+1][j] )\\} </tex>. Să definim acum 3 matrici auxiliare:\r\n\r\n@to_left[ i ][ j ]@ = $a{~i~} + opt[ i + 1 ][ j ]$\r\n@to_right[ i ][ j ]@ = $a{~j~} + opt[ i ][ j - 1 ]$\r\n@inter[ i ][ j ]@ = <tex>\\displaystyle\\arg \\max_{i \\le k \\le j}\\{opt[i][k-1] \\le opt[k+1][j]\\} </tex>\r\n\r\nSe observă că $inter[i][j]$ nu reprezintă altceva decât indicele $k$ tratat in paragraful precedent.\r\nDe asemenea, $inter$ poate fi calculată în $O(N^2)$ observând o proprietate simplă: <tex>$ inter[i][j-1] \\le inter[i][j] \\le inter[i+1][j] $</tex>. Aceasta reiese imediat din monotonia lui $opt$ discutată mai sus. Pseudocodul pentru calculul lui $inter$ este:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    iniţializează opt, inter şi r\r\n    pentru len = 1, N execută\r\n        pentru i = 1, N - len + 1 execută\r\n            j = i + len - 1;\r\n            calculează opt[i][j]\r\n            pentru k = inter[i][j-1], inter[i+1][j] execută\r\n                dacă opt[i][k-1] <= opt[k+1][j] atunci\r\n                    inter[i][j] = k;\r\n            sfârşit_pentru;\r\n       sfârşit_pentru;\r\n    sfârşit_pentru;\r\nSfârşit.\r\n==\r\n\r\nDe menţionat că trebuie avut grijă la cazul când $len$ este mai mic ca $3$. Pseudocodul prezentat mai sus este orientativ.\r\nSă vedem acum de ce această modalitate de calcul a lui $inter$ duce la o complexitate de $O(N^2)$.\r\n\r\nAlternativ, se poate căuta binar $inter[i][j]$ pentru orice $[i,j]$.\r\n\r\nAcum vine ideea decisivă pentru a reduce complexitatea loop-ului: pentru a afla $opt[i][j]$, este suficient să aflăm minimul dintre 2 valori:\r\n\r\n* <tex>\\displaystyle\\min_{i \\le k \\le inter[i][j]} \\{$to\\_left[k][j]$\\} </tex> şi\r\n* <tex>\\displaystyle\\min_{inter[i][j] < k \\le j } \\{$to\\_right[i][k]$\\} </tex>\r\n\r\nMai exact,\r\n\r\n@opt[ i ][ j ]@ = <tex> \\min( \\displaystyle\\min_{i \\le k \\le inter[i][j]} \\{$to\\_left[k][j]$\\},\r\n                              \\displaystyle\\min_{inter[i][j] < k \\le j } \\{$to\\_right[i][k]$\\} ) </tex>\r\n\r\nDiferenţa faţă de prima recurentă este evidentă: acum trebuie să aflăm minimul pe un interval de linii, în cazul $to_left$, şi minimul pe un interval de coloane, în cazul $to_right$. Atât aflarea mnimului pe un interval, cât şi update-ul acestei valori se poate face în $O(logN)$, folosind \'arbori de intervale\':http://infoarena.ro/arbori-de-intervale.\r\n\r\nAstfel, am redus complexitatea loopului interior de la $O(N)$ la $O(logN)$.\r\n\r\n\r\n\r\nh2. Programare dinamica folosind bitmask\r\n\r\nIn continuare vom vedea un exemplu de programare dinamica unde vom folosi un bitmask (codificat pe un intreg) pentru a tine spatiul starilor.\r\n\r\nAstfel sa presupunem ca avem nevoie sa tinem un vector caracteristic pentru o multime.\r\nDaca cardinalul acesteia este suficient de mic putem folosi un intreg pentru a codifica aceasta informatie astfel:\r\n\r\nFie multimea A = { x{~1~}, x{~2~}, ... x{~n~} }.\r\nAtunci bitmaskul unei partitii a lui A, MASK, va avea bitul i egal cu 1 numai si numai daca x{~i~} apartine partitiei.\r\n\r\nDesigur, aceasta reprezentare duce la o complexitate direct proportionala cu 2 ^card(A)^.\r\n\r\n\r\nh3(#problema-1). Problema 1: \'Be a Smart Raftsman\':http://acm.sgu.ru/problem.php?contest=0&problem=475 (SGU)\r\n\r\nbq. Sunteţi membri ai unui echipaj de rafting care constă din $N ≤ 10$ participanţi. Puteţi naviga pe râu, şi scopul tău este să treci de $M ≤ 1000$ curenţii consecutivi şi să ajungi de la punctul de început la punctul de sfârşit în timp minim. Cel de-al $i$-lea curent se caracterizează prin greutatea critică $c{~i~}$, iar al $j$-lea participant este caracterizat greutatea sa $w{~j~}$. În cazul în care pluta trece prin al $i$-lea curent cu oameni la bord cu greutatea totală mai mare de $c{~i~}$, ea se răstoarnă. Această parte a rafting-ului este cea mai interesantă, dar este nevoie de timp suplimentar pentru a te urca pe plută după răsturnare. Deci, uneori este mai bine să se urce un grup de oameni cu greutate totală care nu depăşeşte greutatea critică de pe plută, în timp ce restul parcurg distanţa pe jos.\r\nMai formal, vom considera $m + 1$ puncte $P{~0~}, P{~1~} ,..., P{~M~}$, în cazul în care $P{~0~}$ este începutul şi $P{~M~}$ este punctul final. Fiecare dintre punctele intermediare $P{~i~} (1 ≤ i ≤ M-1)$ este situat între $i$-lea şi $(i + 1)$-lea curent. Dacă pluta se răstoarnă, sunt necesare $D{~i~}$ minute pentru a ajunge de la $P{~i-1~}$ la $P{~I~}$, altfel sunt necesare $d{~i~}$ minute. Cel de-al $j$-lea participant poate merge pe jos de la $P{~i-1~}$ la $P{~I~}$ în $t{~j~}$ minute, iar pentru a se urca sau a coborî din plută are nevoie de $s{~j~}$ minute. Înainte de fiecare dintre riffles grupului dvs. este împărţit în două părţi. Plute prima parte, prin intermediul riffle (cu sau fără răsturnare), şi a doua parte se duce pe malul de la următorul punct intermediar. În acest moment, ei întotdeauna a º teptare pentru pluta, sau plută aşteaptă pentru toate pietoni, în cazul în care ajunge mai devreme. Apoi, unii participanti care sunt pe pluta se poate da jos, iar unii participanti care sunt pe banca poate obţine de pe pluta. Ele nu pot începe să faci înainte de pluta, precum şi toate drumeţii ajung la punct. Timpul total necesar pentru această acţiune este egală cu suma de SJ pentru persoanele schimba locul lor. Apoi treci riffle următoare şi aşa mai departe, până când veţi ajunge la linia de sosire. Reţineţi că nimeni nu poate începe deplasarea la următorul punct de locuri, până când alţii s-au schimbat.\r\nAmintiţi-vă, că sa incepeti de la punctul de P0, având toate grupul dvs. de pe malul (nu pe pluta), şi trebuie să terminaţi la punctul de pm, de asemenea, cu toţi participanţii de pe banca si pluta, cu tine. Nu vi se permite să părăsească pluta, la începutul sau de la un punct intermediar, precum şi mers pe jos spre linia de sosire, fără ea. Aveţi posibilitatea să ia toate grupul de salvare să treacă un riffle, dar nu puteţi lăsa pluta goale în timpul călătoriei. Sarcina ta este de a calcula timpul minim necesar pentru a ajunge la linia de sosire.\r\n\r\n\r\nh2. Programare dinamica folosind vectori de numere intregi\r\n\r\nh3(#problema-1). Problema 1: \'Ugly numbers\':http://code.google.com/codejam/contest/dashboard?c=32015#s=p1&a=1 (Google Code Jam 2008, Round 1C)\r\n\r\nbq. Un număr se numeşte *urât* dacă este divizibil prin oricare dintre numerele prime de o singură cifră, mai exact $2, 3, 5, 7$. Se dă un şir de $N$ cifre. Între fiecare 2 cifre consecutive se poate insera unul dintre semnele + sau -. Dacă nu se inserează un semn, cele 2 cifre sunt concatentate astfel încât să se obţină un număr. Pentru un şir dat de cifre si o variantă de a adăuga semne, prin evaluarea expresiei matematice obţinute prin inserarea semnelor se obţine un număr, numit numărul generat. Să se calculeze câte dintre cele $3^N-1^$ variante de a insera semnele generează numere urâte.\r\n\r\nh3. Exemplu: \r\n\r\nPentru cifrele $123456$, expresia $1+234-5+6 = 236$ care este număr urât, iar $123+4-56 = 71$ nu este număr urât.\r\n\r\nh3. Rezolvare:\r\n\r\nObservăm că un număr este urât dacă dă cel puţin o dată restul 0 la împărţirea la numerele $2, 3, 5, 7$. O abordare a problemei este parcurgerea tuturor variantelor de inserare şi calcularea celor 4 resturi, verificând dacă cel puţin unul este 0.\r\nVom folosi aritmetica modulară pentru a obţine o soluţie mai eficientă a problemei. Vom împărţi cele $3^N-1^$ variante în clase, fiecare clasă reprezentând toate numerele care dau resturile $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ la împărţirea la cele 4 numere. Calculând pentru fiecare clasă numărul de numere generate, rezultatul final va fi suma valorilor calculate pentru toate clasele pentru care cel puţin un rest este egal cu 0. Intuim că putem utiliza clasele de resturi într-o soluţie cu programare dinamică.\r\nVom utiliza şirul auxiliar $V[i][j]$ reprezentând numărul format prin concatenarea cifrelor de pe poziţiile consecutive $i, i+1, ..., j$ din şirul dat, fără inserarea unor semne între cifre. De exemplu, @V[2][4] = 234@. Dacă notăm cu $C[i][r{~2~}][r{~3~}][r{~5~}][r{~7~}]$ numărul de variante formate cu primele $i$ cifre pentru care clasa de resturi este $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$. Observăm că orice astfel de variantă se obţine dintr-o variantă cu $j < i$ cifre după care adăugam + sau - apoi concatenăm restul cifrelor până la $i$ fără semne. Dacă resturile pentru varianta cu $j$ cifre erau $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ atunci resturile pentru varianta nouă $(r\'{~2~}, r\'{~3~}, r\'{~5~}, r\'{~7~})$ sunt:\r\n<tex> $r_2\' = (r_2 +/- V[j+1][i])\\% 2$</tex>\r\n<tex> $r_3\' = (r_3 +/- V[j+1][i])\\% 3$</tex>\r\n<tex> $r_5\' = (r_5 +/- V[j+1][i])\\% 5$</tex>\r\n<tex> $r_7\' = (r_7 +/- V[j+1][i])\\% 7$</tex>\r\nAtunci numărul total de variante cu $i$ cifre este suma după toate valorile $j$ ale numerelor de variante cu $j$ cifre:\r\n<tex> $C[i][r_2\'][r_3\'][r_5\'][r_7\'] = \\sum_{j<i} C[j][r_2][r_3][r_5][r_7]$ </tex>\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i]\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = V[i][j - 1] + A[i];\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0][0][0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r_2 = 0, 1 execută\r\n            pentru r_3 = 0, 2 execută\r\n                pentru r_5 = 0, 4 execută\r\n                    pentru r_7 = 0, 6 execută\r\n                        C[i][r_2][r_3][r_5][r_7] = 0;\r\n                        pentru j = 0, i - 1 execută\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + 2 - V[j+1][i])%2)][(r_3 + 3 - V[j+1][i])%3)]\r\n                                                            [(r_5 + 5 - V[j+1][i])%5)][(r_7 + 7 - V[j+1][i])%7)];\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + V[j+1][i])%2)][(r_3 + V[j+1][i])%3)]\r\n                                                            [(r_5 + V[j+1][i])%5)][(r_7 + V[j+1][i])%7)];\r\n                        sfârşit pentru;\r\n\r\n                        dacă i == N şi (r_2 == 0 sau r_3 == 0 sau r_5 == 0 sau r_7 == 0)\r\n                            S += C[i][r_2][r_3][r_5][r_7]\r\n                        sfârşit pentru;\r\n                    sfârşit pentru;\r\n                sfârşit pentru;\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează S;\r\n==\r\n\r\nO problemă în abordarea precedentă este calcularea matricii $V$, ale cărei valori devin foarte mari şi ies din precizia tipurilor de date disponibile. O soluţie posibilă este calcularea câte unei matrici de sume modulo $R$ pentru fiecare rest $R$, adica a 4 matrici $V{~2~}$, $V{~3~}$, $V{~5~}$ si $V{~7~}$ ale resturilor împărţirii valorilor lui $V$ la cele 4 numere prime. Folosind aritmetica modulară, aceste matrici pot fi calculate direct, fără a calcula $V$. Altă variantă este utilizarea teoremei chineze a resturilor, prin care un sistem de ecuaţii modulo câteva numere prime între ele poate fi redus la o ecuaţie modulo produsul numerelor date. În cazul nostru, numerele sunt prime, deci putem aplica teorema. Astfel, putem reduce problema resturilor împărţirii la $(2, 3, 5, 7)$ la problema restului împărţirii la $2*3*5*7=210$, deci fiecare clasa $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ se reduce la un rest $R < 210$. Modificăm pseudocodul astfel:\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i] % 210\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = (V[i][j - 1] + A[i]) % 210;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r = 0, 209 execută\r\n            C[i][r] = 0;\r\n            pentru j = 0, i - 1 execută\r\n                C[i][r] += C[j][(r + 210 - V[j+1][i]) % 210];\r\n                C[i][r] += C[j][(r + V[j+1][i]) % 210];\r\n            sfârşit pentru;\r\n\r\n            dacă i == N şi (r % 2 == 0 sau r % 3 == 0 sau r % 5 == 0 sau r % 7 == 0)\r\n                S += C[i][r];\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează S;   \r\n==\r\n\r\n\r\n\r\nTo be continued ... \r\n\r\n',2996,'public',NULL,NULL),('planificare/sedinta-20091023','Ședință 2009-10-23','2009-10-20 12:14:02','2009-11-03 16:09:39','h1. Şedinţă 2009-10-23\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Vineri* la ora *19^00^* la Cafepedia de la Universitate.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"silviug\" type=\"tiny\")==\r\n* ==user(user=\"pauldb\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"wickedman\" type=\"tiny\")==\r\n* ==user(user=\"domino\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== nu intre orele 18:00 - 20:00\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")== dupa 16:00\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"victorsb\" type=\"tiny\")==\r\n* ==user(user=\"ditzonec\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada 2010 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| Parteneriat media cu AI contest in Poli | ==user(user=\"silviug\" type=\"tiny\")== |\r\n| Tabăra infoarena | ==user(user=\"wickedman\" type=\"tiny\")== |\r\n| Stare Evaluator | ==user(user=\"svalentin\" type=\"tiny\")== |\r\n| Colaborare Poli | ==user(user=\"svalentin\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* S-a votat IAP #13\r\n* Cristi vorbeste cu Buraga legat de sponsorizare %{color:red}(mail sent)%\r\n* Silviu face blog post despre noul Presedinte %{color:red}(done)%\r\n* Cristian ii face card Cristinei si lui Cosmin.\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")== vicepresedinte responsabil cu Development\r\n* ==user(user=\"pauldb\" type=\"tiny\")== vicepresedinte responsabil cu Algoritmiada\r\n* ==user(user=\"stef2n\" type=\"tiny\")== vicepresedinte responsabil cu Content\r\n* Bogdan se ocupa de organizat concursuri\r\n* Bogdan scrie tickete pentru fixuri la Virtual Contest %{color:red}(done)%\r\n* Prostu se ocupa de Calendar\r\n* Stefan vorbeste cu Marius despre Articole %{color:red}(done)%\r\n* Moare \"IAP #7\":propuneri/7-community-ladder, Cristi actualizeaza status %{color:red}(done)%\r\n* Cosmin scrie newsletter de acum\r\n* Cosmin se ocupa de Strangere Fonduri\r\n* Cosmin vorbeste cu Tibi despre Development %{color:red}(done)%\r\n* Bogdan e responsabil de Taguri\r\n* Cristi intreaba la Hostway daca ne mai dau o masina virtuala %{color:red}(done, ne dă Sergiu)%\r\n* Vali face testing pe masina virtuala\r\n* pe 22 noiembrie va fi prima runda de Algoritmiada\r\n* Cosmin, Silviu si Vali fac mapa pentru sponsori pana la *sfarsitul lunii*\r\n* Silviu trimite bugetul lui Paul %{color:red}(done)%\r\n* Cristi da reply la Amazon %{color:red}(done)%\r\n* Paul face pagini si buget pentru algoritmiada pana la sfarsitul lunii %{color:red}(1/2 done)%\r\n* Cosmin vorbeste cu Cristina despre comunicate de presa %{color:red}(done)%\r\n* Cosmin vorbeste la Orange Concept Store %{color:red}(done)%\r\n* Vali vorbeste cu Vlad Posea despre colaborare si daca ne poate ajuta cineva cu jailrun java\r\n* Silviu vorbeste cu Octavian Voicu despre AI Contest %{color:red}(mail sent)%\r\n\r\nh2(#notite). Notite\r\n\r\n* Cristi i-a dat lui Vali 23 RON pentru bilet tren Algoritmiada 2009\r\n* Se scrie retry loop pentru eval\r\n* Cristi plateste 120 RON pentru consumatie',13,'protected',NULL,NULL),('pd','Tehnici avansate de programare dinamică','2007-12-04 21:25:10','2009-11-06 19:42:59','h1. Tehnici avansate de programare dinamică\r\n\r\n(Categoria _Tehnici de programare_, autori _Catalin Tiseanu_, _Andrei Homescu_)\r\n\r\nTODO:\r\n\r\n1. Reparat link de la ugly numbers\r\n\r\nPlan de atac (probleme-candidat):\r\n\r\n1. http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en (Reducerea complexitatii, transformarea problemei intr-una de construire a unui arbore binar.)\r\n\r\n2. http://code.google.com/codejam/contest/dashboard?c=32001#s=p0&a=3 (Boolean tree, programare dinamica simpla pe arbore binar.)\r\n\r\n3. http://code.google.com/codejam/contest/dashboard?c=32001#s=p3&a=3 (PermRLE, permutari cu N*2^N)\r\n\r\n4. http://code.google.com/codejam/contest/dashboard?c=32010#s=p3&a=3 (problema cu DP pe matrici, aplicam ridicarea la putere pt calcul rapid)\r\n\r\n5. http://infoarena.ro/problema/doipatru (joc cu solutie DP, stare in 6 dimensiuni)\r\n\r\nh2. Sugestii Silviu\r\n\r\n* poate ca nu trebuie sa spunem tot despre programare dinamica intr-un singur articol; spre exemplu putem facem doua articole: PD basic si PD advanced\r\n* cred ca era si ceva prin Cartea lui Francu\' despre programare dinamica; ar merge incorporat (eventual in pd_basic).\r\n\r\nh2. Introducere\r\n\r\nProgramarea dinamică este o metodă utilă pentru a rezolva probleme care pot fi obţinute prin compunerea a mai multor bucăţi, a căror soluţie poate fi apoi determinată optim. Se bazează în principal pe proprietatea unei probleme de a putea fi rezolvată optim dacă se cunosc soluţii optime la sub-problemele ei.\r\nDe menţionat că \'programare\' nu se referă aici la scrierea de cod într-un limbaj de programare, ci la \'programare matematica\', care constă în optimizarea unei funcţii prin alegerea de valori dintr-o mulţime anume. \r\n\r\nScopul acestui articol nu este să ofere o introducere in programare dinamică (pentru aceasta poate fi consultat excelentul tutorial de pe TopCoder \"Dynamic Programming : From novice to advanced\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg). În schimb, acest articol îşi propune să ofere nişte \'smenuri\' mai avansate de rezolvare a problemelor cu programare dinamică. \r\n\r\nh2. Reducerea loop-ului interior\r\n\r\nÎn problemele de programare dinamică de multe ori prima complexitate obţinută nu este optimă. Mai exact, recurenţa obţinută iniţial poate fi îmbunătăţită sau calculată mai rapid. De multe ori, pentru aceasta se optimizeaza loop-ul interior din calculul recurenţei. Acest lucru se poate face bazat fie pe observaţii specifice problemei, fie pe tehnici mai clasice.\r\n\r\nSă considerăm următoarea problema:\r\n\r\nh3(#problema-1). Problema 1: \'Drilling\':http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en (Algorithmic Engagements 2009, Round 3)\r\n\r\nbq. Se da un şir de $N$ numere naturale $(a{~1~}, a{~2~}, ..., a{~N~})$. Se ştie că un prefix al acestui şir (adică o subsecvenţă de la începutul şirului, posibil nulă) este **defect**. Toate elementele din acel prefix (şi doar din acel prefix) sunt defecte. Se ştie de asemenea că se poate testa orice poziţie $i$ în timp $a{~i~}$ pentru a afla dacă este defectă. Să se determine timpul minim în cazul cel mai defavorabil pentru aflarea lungimii maxime a prefixului şirului care este defect.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(8 24 12 6)$, răspunsul ar fi $42$. Astfel, se testează mai întâi poziţia $2$. Dacă nu este defectă, mai rămâne de testat poziţia $1$. Altfel, în cel mai rău caz mai trebuie testate poziţiile $3$ şi $4$, aducând timpul total la $24 + 12 + 6 = 42$.\r\n\r\nh3. Rezolvare:\r\n\r\nO să începem prin a da altă îmbrăcăminte problemei. Astfel, să ne imaginăm că am construi un arbore binar de căutare pe şirul dat, având drept chei poziţiile din şir, şi drept valori auxiliare valorile poziţiilor respective din şir (un nod cu cheia $i$ va avea valoarea auxiliara $a{~i~}$.\r\nAcum, există mulţi arbori binari de căutare posibile pentru şirul iniţial. Totuşi, să presupunem că am construit unul, pe care îl considerăm de acum ca fixat. Atunci, strategia noastra de testare a elementelor din şir se va desfăşura conforma arborelui. Astfel, testăm mai întâi în poziţia din rădăcină. Dacă poziţia respectivă este defectă, ne ducem în fiul drept. Altfel, mergem in fiul stâng. În ambele cazuri se reia procedeul. Căutarea se termină cand nu mai putem merge într-un fiu. \r\n\r\nSă observăm că dacă considerăm costul unui drum în arbore de la rădăcină la o frunză ca suma valorilor auxiliare din drumul (unic) respectiv, atunci se observă că costul strategiei bazate pe acest arbore este chiar costul maxim al unui drum ! De acum încolo, vom defini costul unui arbore ca costul maxim al unui drum de la rădăcină la o frunză. Să exemplificăm pe şirul din exemplu:\r\n\r\np=. !pd?Diagram1.png!\r\n\r\np=. _Fig. 1: În paranteză sunt valorile auxiliare ataşate cheilor_\r\n\r\nSe observă că costul maxim al unui drum este $42$, minim posibil, exact ca răspunsul din exemplu. Deci, am redus problema la construirea unui arbore binar de căutare, care are costul minim.\r\n\r\nAcum devine clară o primă soluţie folosind programarea dinamică. Astfel, să presupunem că notăm cu $opt[ i ][ j ]$ costul minim al unui arbore construit pe cheile din $[i,j]$ (prin asta notăm (i, i + 1, ..., j). Fie $r[ i ][ j ]$ poziţia rădăcinii arborelui cu costul minim. În cazul existenţei mai multor rădăcini posibile, se alege cea mai din stânga. Cum am putea construi arborele de cost minim pe cheile $[i,j]$ ştiind răspunsul pentru instanţele mai mici (subsecvenţele de lungime mai mică ca $j-i+1$ pe $[i,j]$)? (!) Simplu, arborele de cost minim pe $[i,j]$ se obţine alegând drept rădăcină în mod optim o poziţie $k$, cu <tex>$i \\le k \\le j$</tex>, la care se pune ca fiul stâng arborele optim pentru $[i, k-1]$, şi ca fiu drept arborele optim pentru $[k+1, j]$. Relaţia de recurenţă devine:\r\n\r\n$opt[ i ][ j ]$ = <tex>\\displaystyle\\min_{i \\le k \\le j} \\{a_{k} + \\max( opt[i][k-1], opt[k+1][j] )\\} </tex>   \r\n$r[ i ][ j ]$ = <tex>\\displaystyle\\arg \\min_{i \\le k \\le j}\\{a_{k} + \\max (opt[i][k-1], opt[k+1][j] )\\} </tex> \r\n\r\nAvem @opt[i][j] = 0@, pentru $j < i$.\r\nCazurile de bază sunt @opt[i][i]@ = a{~i~} si @r[i][i] = i@.\r\n\r\nSe observă că răspunsul problemei se află în @opt[1][N]@.\r\nAstfel, am obţinut o soluţie în timp $O(N^3)$.\r\n\r\nAici trebuie remarcată asemănarea acestei probleme cu cea a determinării arborelui de căutare optim, atunci cand se dau probabilităţile relative de căutare a cheilor. Această problemă se numeşte \'Optimal Binary Search Tree\' în literatura de specialitate şi poate fi găsită şi în _Introduction to Algorithms_. În aceasta problemă, se poate aplica o reducere a complexităţii datorită faptului că <tex>$ r[i][j-1] \\le r[i][j] \\le r[i+1][j] $</tex> pentru a reduce complexitatea la $O(N^2)$. Această proprietate nu se poate aplica din păcate şi în cazul problemei noastre.\r\n\r\nPână acum avem următorul pseudocod pentru calculul recurenţei:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    iniţializează opt şi r\r\n    pentru len = 1, N execută\r\n        pentru i = 1, N - len + 1 execută\r\n            j = i + len - 1;\r\n            opt[i][j] = inf;\r\n            pentru k = i, j execută\r\n                dacă opt[i][j] < a[k] + max(opt[i][k-1], opt[k+1][j]) atunci\r\n                    opt[i][j] = a[k] + max(opt[i][k-1], opt[k+1][j]);\r\n                    r[i][j] = k;\r\n            sfârşit_pentru;\r\n       sfârşit_pentru;\r\n    sfârşit_pentru;\r\n\r\n    return opt[1][N];\r\nSfârşit.\r\n==\r\n\r\nAcum ca să obţinem o complexitate mai bună, ţinând cont şi de numele capitolului, vom încerca să reducem complexitatea loop-ului interior (cel după $k$).\r\nSă ne uităm mai atent la acest loop.\r\n\r\nFie un interval $[i,j]$ fixat. Acum, $opt[i][j] < opt[i][j\']$, pentru orice $j < j\'$. Similar, $opt[i][j] < opt[i\'][j]$, pentru orice $i\' < i$.\r\nAtunci, există un indice $k$, <tex>$i \\le k \\le j$</tex> astfel încât $max(opt[i][o-1], opt[o+1][j]) = opt[o+1][j]$, pentru orice <tex>$i \\le o \\le k$</tex>, şi $max(opt[i][o-1], opt[o+1][j]) = opt[i][o-1]$ pentru orice <tex>$k \\le o \\le j$</tex>. După cum ştim, trebuie să aflăm <tex>\\displaystyle\\min_{i \\le k \\le j} \\{a_{k} + \\max( opt[i][k-1], opt[k+1][j] )\\} </tex>. Să definim acum 3 matrici auxiliare:\r\n\r\n@to_left[ i ][ j ]@ = $a{~i~} + opt[ i + 1 ][ j ]$\r\n@to_right[ i ][ j ]@ = $a{~j~} + opt[ i ][ j - 1 ]$\r\n@inter[ i ][ j ]@ = <tex>\\displaystyle\\arg \\max_{i \\le k \\le j}\\{opt[i][k-1] \\le opt[k+1][j]\\} </tex>\r\n\r\nSe observă că $inter[i][j]$ nu reprezintă altceva decât indicele $k$ tratat in paragraful precedent.\r\nDe asemenea, $inter$ poate fi calculată în $O(N^2)$ observând o proprietate simplă: <tex>$ inter[i][j-1] \\le inter[i][j] \\le inter[i+1][j] $</tex>. Aceasta reiese imediat din monotonia lui $opt$ discutată mai sus. Pseudocodul pentru calculul lui $inter$ este:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    iniţializează opt, inter şi r\r\n    pentru len = 1, N execută\r\n        pentru i = 1, N - len + 1 execută\r\n            j = i + len - 1;\r\n            calculează opt[i][j]\r\n            pentru k = inter[i][j-1], inter[i+1][j] execută\r\n                dacă opt[i][k-1] <= opt[k+1][j] atunci\r\n                    inter[i][j] = k;\r\n            sfârşit_pentru;\r\n       sfârşit_pentru;\r\n    sfârşit_pentru;\r\nSfârşit.\r\n==\r\n\r\nDe menţionat că trebuie avut grijă la cazul când $len$ este mai mic ca $3$. Pseudocodul prezentat mai sus este orientativ.\r\nSă vedem acum de ce această modalitate de calcul a lui $inter$ duce la o complexitate de $O(N^2)$.\r\n\r\nAlternativ, se poate căuta binar $inter[i][j]$ pentru orice $[i,j]$.\r\n\r\nAcum vine ideea decisivă pentru a reduce complexitatea loop-ului: pentru a afla $opt[i][j]$, este suficient să aflăm minimul dintre 2 valori:\r\n\r\n* <tex>\\displaystyle\\min_{i \\le k \\le inter[i][j]} \\{$to\\_left[k][j]$\\} </tex> şi\r\n* <tex>\\displaystyle\\min_{inter[i][j] < k \\le j } \\{$to\\_right[i][k]$\\} </tex>\r\n\r\nMai exact,\r\n\r\n@opt[ i ][ j ]@ = <tex> \\min( \\displaystyle\\min_{i \\le k \\le inter[i][j]} \\{$to\\_left[k][j]$\\},\r\n                              \\displaystyle\\min_{inter[i][j] < k \\le j } \\{$to\\_right[i][k]$\\} ) </tex>\r\n\r\nDiferenţa faţă de prima recurentă este evidentă: acum trebuie să aflăm minimul pe un interval de linii, în cazul $to_left$, şi minimul pe un interval de coloane, în cazul $to_right$. Atât aflarea mnimului pe un interval, cât şi update-ul acestei valori se poate face în $O(logN)$, folosind \'arbori de intervale\':http://infoarena.ro/arbori-de-intervale.\r\n\r\nAstfel, am redus complexitatea loopului interior de la $O(N)$ la $O(logN)$.\r\n\r\n\r\n\r\nh2. Programare dinamică folosind măşti de biţi şi codificări $k$-are\r\n\r\nUnele probleme de programare dinamica au drept componentă a stării unei subprobleme o mulţime de elemente care fac parte din subproblemă. Astfel, subproblema nu este o reducere a problemei iniţiale la un subset continuu de elemente ($1..i$ sau $i..j$) ci la un subset oarecare. În acest caz, codificăm submulţimea curentă în stare, ca vector sau ca număr întreg. Dacă dimensiunea submulţimii este suficient de mic putem folosi un întreg pentru a codifica această informaţie astfel:\r\n\r\nFie mulţimea $A$ = { x{~1~}, x{~2~}, ... x{~n~} }.\r\nAtunci masca de biţi a unei partitii a lui $A, $MASK$, va avea bitul $i$ egal cu 1 dacă şi numai dacă x{~i~} apartine partitiei. Desigur, această reprezentare duce la o complexitate direct proporţională cu $2 ^card(A)^$. Putem intui dacă trebuie să folosim o astfel de rezolvare din limitele valorilor de intrare; pentru $N$ cu valori cuprinse între $10-20$, deducem că trebuie să căutăm o astfel de soluţie.\r\n\r\nPentru multe probleme, fiecare element poate face parte din subproblemă în mai mult de 2 feluri. De exemplu, dacă starea reprezintă o linie de maxim $K$ elemente dintr-o matrice iar fiecare element de pe linie poate avea valorile 0, 1 sau 2 atunci există $3^K$ variante distincte posibile pentru o astfel de linie. Un alt exemplu este o problemă de optimizare în care fiecare element (participant) se poate afla în una din câteva stări (dacă $N$ persoane trebuie să treacă un pod peste un râu, cele 3 stări pot fi: _pe malul stâng_, _pe pod_ şi _pe malul drept_).\r\n\r\n\r\nh3(#problema-1). Problema 1: \'Be a Smart Raftsman\':http://acm.sgu.ru/problem.php?contest=0&problem=475 (SGU)\r\n\r\nbq. Sunteţi membri ai unui echipaj de rafting care constă din $N ≤ 10$ participanţi. Puteţi naviga pe râu, şi scopul vostru este să treceţi de $M ≤ 1000$ curenţi consecutivi şi să ajungi de la punctul de început la punctul de sfârşit în timp minim. Cel de-al $i$-lea curent se caracterizează prin greutatea critică $c{~i~}$, iar al $j$-lea participant este caracterizat greutatea sa $w{~j~}$. În cazul în care pluta trece prin al $i$-lea curent cu oameni la bord cu greutatea totală mai mare de $c{~i~}$, ea se răstoarnă. Această parte a rafting-ului este cea mai interesantă, dar este nevoie de timp suplimentar pentru a te urca pe plută după răsturnare. Deci, uneori este mai bine să se urce un grup de oameni cu greutate totală care nu depăşeşte greutatea critică a plutei, în timp ce restul parcurg distanţa pe jos.\r\nMai formal, vom considera $M + 1$ puncte $P{~0~}, P{~1~} ,..., P{~M~}$, în cazul în care $P{~0~}$ este începutul şi $P{~M~}$ este punctul final. Fiecare dintre punctele intermediare $P{~i~} (1 ≤ i ≤ M-1)$ este situat între $i$-lea şi $(i + 1)$-lea curent. Dacă pluta se răstoarnă, sunt necesare $D{~i~}$ minute pentru a ajunge de la $P{~i-1~}$ la $P{~i~}$, altfel sunt necesare $d{~i~}$ minute. Cel de-al $j$-lea participant poate merge pe jos de la $P{~i-1~}$ la $P{~i~}$ în $t{~j~}$ minute, iar pentru a se urca sau a coborî din plută are nevoie de $s{~j~}$ minute. Înainte de fiecare curent, grupul vostru este împărţit în două părţi. Prima parte trece prin curent cu pluta, iar a doua parte merge pe mal spre următorul punct. Cei care ajung primii îi aşteaptă pe toţi ceilalţi. Apoi, unii participanţi care sunt pe plută se pot da jos, în timp ce alţi participanti care sunt pe mal se pot urca pe plută. Această activitate începe când ajung pluta şi toţi cei de pe mal la punctul stabilit. Timpul total necesar pentru această acţiune este egal cu suma valorilor $s{~j~}$ pentru toate persoanele care schimbă locul (persoanele urcă şi coboară pe rând). Nimeni nu poate începe deplasarea la următorul punct, până când nu s-au mutat toţi membrii.\r\nîncepeţi de la punctul de $P{~0~}$ cu tot grupul pe mal şi trebuie să terminaţi la punctul $P{~M~}$ cu toţi participanţii şi pluta pe mal. Nu aveţi voie să părăsiţi pluta la început sau într-un un punct intermediar şi să mergeţi pe jos spre linia de sosire fără ea. Aveţi posibilitatea să urcaţi tot grupul de salvare în plută, dar nu puteţi lăsa pluta goală în timpul călătoriei printr-un curent. \r\nSarcina voastră este să calculaţi timpul minim necesar pentru a ajunge la linia de sosire.\r\n\r\nh3. Rezolvare:\r\n\r\nDin enunţ intuim că o componentă a stării trebuie să fie submulţimea participanţilor aflaţi în plută în punctul curent, intuiţie confirmată de numărul mic al participanţilor ({$N ≤ 10$}). Există $2^10^$ astfel de variante, din care vom exclude varianta în care pluta este goală. O stare a problemei, reprezentănd soluţia unei subprobleme, va fi alcătuită din poziţia curentă a plutei (punctul $P{~i~}$ unde se află) şi submulţimea oamenilor care se află în plută. Observăm că de la punctul precedent pluta a traversat curentul, au urcat nişte oameni apoi au coborât alţii; aceşti paşi contribuie la timpul total şi reprezintă 2 părţi ale recurenţei soluţiei. Dacă notăm cu $T{~m~}[i][S]$ timpul minim necesar pentru a ajunge în punctul $i$ cu submulţimea $S$ a oamenilor din plută, putem descrie problema prin relaţiile:\r\n\r\n<tex> $T_m[0][0] = 0$ </tex>\r\n<tex> $T_m[0][S] = T_u[0][S], \\forall S \\neq 0$ </tex>\r\n<tex> $T_m[i][S] = \\min_{S\' \\neq \\emptyset} \\{T_m[i-1][S\'] + T_t[i][S\'] + T_u[S\'][S] + T_c[S\'][S]\\}, \\forall 1 \\le i \\le M$ </tex>\r\n\r\nunde $T{~u~}[S\'][S]$ este timpul necesar pentru urcarea participanţilor care se găsesc în mulţimea $S$ dar nu fac parte din mulţimea $S\'$ (aceşti participanţi alcătuiesc mulţimea $S{~u~}$), $T{~c~}[S\'][S]$ este timpul necesar pentru coborârea participanţilor din plută (participanţii din mulţimea $S{~c~}$), iar $T{~t~}[i][S]$ este timpul necesar traversării curentului de la punctul $i-1$ la punctul $i$ dacă în plută se află participanţii din $S$. Formulele pentru valorile $T{~u~}$, $T{~c~}$ şi $T{~t~}$ sunt:\r\n\r\n<tex> $T_u[S_1][S_2] = \\sum_{i \\in S_2 - S_1}{s_i} = \\sum_{i \\in S_u}{s_i}$ </tex>\r\n<tex> $T_c[S_1][S_2] = \\sum_{i \\in S_1 - S_2}{s_i} = \\sum_{i \\in S_c}{s_i}$ </tex>\r\n<tex> $T_t[i][S] = \\left\\{ \r\n\\begin{array}{l l}\r\n  D_i & \\quad \\sum_{j \\in S}{w_j} > c_i\\\\\r\n  d_i & \\quad \\sum_{j \\in S}{w_j} \\le c_i\\\\ \r\n\\end{array} \\right. $</tex>\r\n\r\nCalcularea directă a soluţiei pe baza recurenţelor de mai sus are complexitatea $O(M*N*2^N^ + M*2^N^*2^N^)$. Primul termen al complexităţii este dat de calcularea valorilor $T{~t~}$, iar al doilea de calcularea matricii $T{~m~}$.\r\n\r\nValoarea rezultatului nu depinde de ordinea în care urcă şi coboară participanţii din plută, deci o putem alege noi. Dacă aranjăm ordinea în doi paşi astfel încât în primul pas doar să urce, apoi în al doilea pas doar să coboare, vom obţine o îmbunătăţire semnificativă a timpului de execuţie. Se observă că dacă am efectua doar adăugări de elemente (daca în plută s-ar putea doar urca persoane, fără să poată coborî), atunci <tex> $S\' \\in S$ </tex> şi deci reprezentarea în cod binar a mulţimii $S\'$ ar avea o valoare mai mică decât reprezentarea binară a mulţimii $S$. Dacă ar avea voie doar să coboare persoane, relaţia ar fi inversă. De aceea, vom ordona operaţiile de urcare şi coborâre astfel încât să aibă loc întâi toate urcările (astfel încât să putem parcurge crescător valorile binare ale mulţimilor) apoi toate coborârile (astfel încât să putem efectua a doua parcurgere, în ordine descrescătoare). Introducem matricea auxiliară $T{~um~}[i][S]$ care reprezintă timpul minim necesar la care se poate afla pluta în punctul $i$ cu mulţimea $S$ de oameni, dacă după ultima traversare nu a coborât încă nici o persoană. Starea $S$ a fost obţinută prin una sau mai multe urcări de persoane în plută sau direct prin traversarea curentului. Recurenţele pentru $T{~um~}[i][S]$ sunt:\r\n\r\n<tex> $T_{um}[i][S] = \\min \\left(T_m[i-1][S] + T_t[i][S], \\min_{j \\in S}\\{T_{um}[i][S - j] + s_j\\} \\right) </tex>\r\n<tex> $T_m[i][S] = \\min \\left(T_{um}[i][S], \\min_{j \\not\\in S}\\{T_m[i][S \\cup j] + s_j\\} \\right) </tex>\r\n\r\nAm eliminat calcularea matricilor $T{~u~}$, $T{~c~}$. Toate matricile rămase au dimensiunea $Mx2^N^$ iar calcularea fiecărui element necesită un timp $O(N)$, deci soluţia astfel obţinută are complexitatea $O(M*N*2^N^)$.\r\n\r\n== code(cpp)    |\r\n    iniţializează toate Tm[0];\r\n    pentru i = 1, M execută\r\n        calculează toate Tt[i];\r\n        pentru fiecare S în ordine crescătoare a reprezentării binare execută\r\n            Tum[i][S] = Tm[i-1][S] + Tt[i][S];\r\n            pentru fiecare j din S execută\r\n                Tum[i][S] = min(Tum[i][S], Tum[i][S - j] + s[j]);\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n        pentru fiecare S în ordine descrescătoare a reprezentării binare execută\r\n            Tm[i][S] = Tum[i][S];\r\n            pentru fiecare j care nu există în S execută\r\n                Tm[i][S] = min(Tm[i][S], Tm[i][S + j] + s[j]);\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează Tm[M][0];\r\n==\r\n\r\nMai există două optimizări de spaţiu pe care le putem efectua în soluţia prezentată. Putem elimina matricea $T{~um~}$, calculând toate valorile direct pe matricea $T{~m~}$, deoarece aceasta va fi parcursă în ambii paşi în câte o singură direcţie. A doua optimizare se bazează pe observaţia că nu avem niciodată nevoie de alte linii în afară de ultimele 2 ({$i$} si {$i-1$}), deci putem înlocui matricea cu 2 vectori de dimensiune $2^N^$. Valorile $T{~t~}$ pot fi calculate în cadrul primei bucle, reducând astfel spaţiul necesar soluţiei la $O(2^N^)$.\r\n\r\n\r\n\r\nh2. Programare dinamica pe mai multe dimensiuni\r\n\r\nUnele probleme nu pot fi împărţite în subprobleme doar după o submulţime a datelor de intrare ale problemei curente, ci trebuie adăugate criterii suplimentare. De multe ori, aceste valori sunt similare sumei din _problema rucsacului_, dar calculele se fac pe 2 sau chiar mai multe dimensiuni, obţinând o descriere destul de complexă a unei subprobleme. De exemplu, o subproblemă poate fi reprezentată printr-un vector de valori de dimensiuni variate.\r\n\r\n\r\nh3(#problema-1). Problema 1: \'Ugly numbers\':http://code.google.com/codejam/contest/dashboard?c=32015#s=p1&a=1 (Google Code Jam 2008, Round 1C)\r\n\r\nbq. Un număr se numeşte *urât* dacă este divizibil prin oricare dintre numerele prime de o singură cifră, mai exact $2, 3, 5, 7$. Se dă un şir de $N$ cifre. Între fiecare 2 cifre consecutive se poate insera unul dintre semnele + sau -. Dacă nu se inserează un semn, cele 2 cifre sunt concatentate astfel încât să se obţină un număr. Pentru un şir dat de cifre si o variantă de a adăuga semne, prin evaluarea expresiei matematice obţinute prin inserarea semnelor se obţine un număr, numit numărul generat. Să se calculeze câte dintre cele $3^N-1^$ variante de a insera semnele generează numere urâte.\r\n\r\nh3. Exemplu: \r\n\r\nPentru cifrele $123456$, expresia $1+234-5+6 = 236$ care este număr urât, iar $123+4-56 = 71$ nu este număr urât.\r\n\r\nh3. Rezolvare:\r\n\r\nObservăm că un număr este urât dacă dă cel puţin o dată restul 0 la împărţirea la numerele $2, 3, 5, 7$. O abordare a problemei este parcurgerea tuturor variantelor de inserare şi calcularea celor 4 resturi, verificând dacă cel puţin unul este 0.\r\nVom folosi aritmetica modulară pentru a obţine o soluţie mai eficientă a problemei. Vom împărţi cele $3^N-1^$ variante în clase, fiecare clasă reprezentând toate numerele care dau resturile $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ la împărţirea la cele 4 numere. Calculând pentru fiecare clasă numărul de numere generate, rezultatul final va fi suma valorilor calculate pentru toate clasele pentru care cel puţin un rest este egal cu 0. Intuim că putem utiliza clasele de resturi într-o soluţie cu programare dinamică.\r\nVom utiliza şirul auxiliar $V[i][j]$ reprezentând numărul format prin concatenarea cifrelor de pe poziţiile consecutive $i, i+1, ..., j$ din şirul dat, fără inserarea unor semne între cifre. De exemplu, @V[2][4] = 234@. Dacă notăm cu $C[i][r{~2~}][r{~3~}][r{~5~}][r{~7~}]$ numărul de variante formate cu primele $i$ cifre pentru care clasa de resturi este $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$. Observăm că orice astfel de variantă se obţine dintr-o variantă cu $j < i$ cifre după care adăugam + sau - apoi concatenăm restul cifrelor până la $i$ fără semne. Dacă resturile pentru varianta cu $j$ cifre erau $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ atunci resturile pentru varianta nouă $(r\'{~2~}, r\'{~3~}, r\'{~5~}, r\'{~7~})$ sunt:\r\n<tex> $r_2\' = (r_2 +/- V[j+1][i])\\% 2$</tex>\r\n<tex> $r_3\' = (r_3 +/- V[j+1][i])\\% 3$</tex>\r\n<tex> $r_5\' = (r_5 +/- V[j+1][i])\\% 5$</tex>\r\n<tex> $r_7\' = (r_7 +/- V[j+1][i])\\% 7$</tex>\r\nAtunci numărul total de variante cu $i$ cifre este suma după toate valorile $j$ ale numerelor de variante cu $j$ cifre:\r\n<tex> $C[i][r_2\'][r_3\'][r_5\'][r_7\'] = \\sum_{j<i} C[j][r_2][r_3][r_5][r_7]$ </tex>\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i]\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = V[i][j - 1] + A[i];\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0][0][0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r_2 = 0, 1 execută\r\n            pentru r_3 = 0, 2 execută\r\n                pentru r_5 = 0, 4 execută\r\n                    pentru r_7 = 0, 6 execută\r\n                        C[i][r_2][r_3][r_5][r_7] = 0;\r\n                        pentru j = 0, i - 1 execută\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + 2 - V[j+1][i])%2)][(r_3 + 3 - V[j+1][i])%3)]\r\n                                                            [(r_5 + 5 - V[j+1][i])%5)][(r_7 + 7 - V[j+1][i])%7)];\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + V[j+1][i])%2)][(r_3 + V[j+1][i])%3)]\r\n                                                            [(r_5 + V[j+1][i])%5)][(r_7 + V[j+1][i])%7)];\r\n                        sfârşit pentru;\r\n\r\n                        dacă i == N şi (r_2 == 0 sau r_3 == 0 sau r_5 == 0 sau r_7 == 0)\r\n                            S += C[i][r_2][r_3][r_5][r_7]\r\n                        sfârşit pentru;\r\n                    sfârşit pentru;\r\n                sfârşit pentru;\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează S;\r\n==\r\n\r\nO problemă în abordarea precedentă este calcularea matricii $V$, ale cărei valori devin foarte mari şi ies din precizia tipurilor de date disponibile. O soluţie posibilă este calcularea câte unei matrici de sume modulo $R$ pentru fiecare rest $R$, adica a 4 matrici $V{~2~}$, $V{~3~}$, $V{~5~}$ si $V{~7~}$ ale resturilor împărţirii valorilor lui $V$ la cele 4 numere prime. Folosind aritmetica modulară, aceste matrici pot fi calculate direct, fără a calcula $V$. Altă variantă este utilizarea teoremei chineze a resturilor, prin care un sistem de ecuaţii modulo câteva numere prime între ele poate fi redus la o ecuaţie modulo produsul numerelor date. În cazul nostru, numerele sunt prime, deci putem aplica teorema. Astfel, putem reduce problema resturilor împărţirii la $(2, 3, 5, 7)$ la problema restului împărţirii la $2*3*5*7=210$, deci fiecare clasa $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ se reduce la un rest $R < 210$. Modificăm pseudocodul astfel:\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i] % 210\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = (V[i][j - 1] + A[i]) % 210;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r = 0, 209 execută\r\n            C[i][r] = 0;\r\n            pentru j = 0, i - 1 execută\r\n                C[i][r] += C[j][(r + 210 - V[j+1][i]) % 210];\r\n                C[i][r] += C[j][(r + V[j+1][i]) % 210];\r\n            sfârşit pentru;\r\n\r\n            dacă i == N şi (r % 2 == 0 sau r % 3 == 0 sau r % 5 == 0 sau r % 7 == 0)\r\n                S += C[i][r];\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează S;   \r\n==\r\n\r\n\r\nh3(#problema-2). Problema 2: \'Doipatru\':http://infoarena.ro/problema/doipatru\r\n\r\nbq. Membrii Lotului Naţional de Informatică sunt foarte mândri de noul joc inventat de ei, pe care l-au denumit asemănător cu o problemă de la Olimpiada Internaţională de Informatică din anul 2001, care le-a plăcut foarte mult. Astfel, jocul se numeşte DoiPatru.\r\nPentru acest joc se folosesc $3 ≤ N ≤ 30$ grămezi, fiecare conţinând cel puţin 0 şi cel mult 4 bile. Numărul total de bile din toate grămezile este $2*N$. Doi jucători mută alternativ. Atunci când ii vine rândul, fiecare jucător este obligat să efectueze o mutare validă.\r\nO mutare validă constă din alegerea a două grămezi, dintre care prima grămadă are mai multe bile decât cea de a doua. Jucătorul ia o bilă din prima grămadă şi o mută în cealaltă. Mutarea se consideră validă, doar dacă numărul de bile rezultat în a doua grămadă după mutarea bilei nu este mai mare decât numărul de bile rămas în prima grămadă.\r\nJocul se termină atunci când nu mai poate fi efectuată nici o mutare validă (dacă vă gândiţi puţin, veţi constata că acest lucru se întâmplă atunci când fiecare grămadă conţine două bile).\r\nCâştigătorul jocului este desemnat cel care deţine mai multe grămezi la sfârşitul jocului. Bineînţeles, dacă cei doi jucători deţin un număr egal de grămezi, jocul se consideră a fi remiză.\r\nUn jucător deţine o grămadă dacă grămada are două bile, iar acest număr (de două bile) a rezultat în urma unei mutări efectuate de jucătorul respectiv. De exemplu, dacă un jucător alege o grămadă cu 4 bile şi una cu o bilă, în urma efectuării mutării, el va deţine cea de-a doua grămadă (care va avea două bile), dar prima nu va aparţine deocamdată nici unuia dintre jucători. Dacă alege o grămadă cu 3 bile şi una cu 0 bile, jucătorul va deveni proprietarul primei grămezi, deoarece, în urma mutării efectuate, grămada respectivă va rămâne cu două bile. În cazul în care alege o grămadă cu 3 bile şi una cu o bilă, după efectuarea mutării, el va deţine ambele grămezi (amândouă au acum doua bile).\r\nDacă un jucător este proprietarul unei grămezi la un moment dat în timpul jocului, nu înseamnă că această grămadă va rămâne în posesia lui până la sfârşit. De exemplu, să presupunem că jucătorul 1 deţine o grămadă cu două bile şi este rândul jucătorului 2 să mute. Dacă acesta alege o grămadă cu 4 bile şi grămada cu două bile ce aparţine jucătorului 1, după efectuarea mutării, ambele grămezi vor avea 3 bile, iar numărul de grămezi aflate în posesia jucătorului 1 va scădea cu 1 (grămada deţinută de el anterior nu mai aparţine nici unuia din cei doi jucători, căci nu mai are doua bile).\r\nDacă la începutul jocului există unele grămezi având două bile, acestea sunt distribuite în mod egal celor doi jucători. Dacă numărul de grămezi cu două bile este impar, atunci jucătorul 2 va primi cu o grămadă mai mult decât jucatorul 1. Jucătorul 1 este cel care efectuează prima mutare.\r\nScrieţi un program care, pentru un $N$ dat şi un set de configuraţii iniţiale ale jocului cu $N$ grămezi, decide rezultatul fiecărei configuraţii de joc.\r\n\r\nh3. Rezolvare:\r\n\r\nÎncepem rezolvarea cu observaţia că există 5 tipuri de grămezi (0, 1, 2, 3 şi 4 bile), dar pentru fiecare grămadă de 2 bile aparţine doar unuia dintre jucători, informaţie esenţială pentru stabilirea câştigătorului. Vom separa deci toate grămezile de 2 bile în 2 categorii: $2A$ care reprezintă grămezile de 2 bile deţinute de primul jucător şi $2B$ care sunt grămezile de 2 bile deţinute de al doilea jucător. Orice moment al jocului poate fi reprezentat identificând jucătorul care urmează la mutare şi numărul de bile din fiecare dintre cele $N$ grămezi. O variantă alternativă este de a reprezenta numerele de grămezi din fiecare tip, starea fiind reprezentată prin valorile $(J, n{~0~}, n{~1~}, n{~2A~}, n{~2B~}, n{~3~}, n{~4~})$, unde $n{~k~}$ reprezintă numărul de grămezi care au $k$ bile (cu excepţiile $2A$ şi $2B$, descrise înainte).\r\nVom nota prin $R[J, n{~0~}, n{~1~}, n{~2A~}, n{~2B~}, n{~3~}, n{~4~}]$ cel mai bun rezultat pe care îl poate obţine jucătorul care urmează ({$J$}). Valorile posibile ale rezultatului vor fi alese ca numere întregi crescătoare, astfel: 0 dacă din configuraţia curentă jucătorul nu are nici o şansă să câştige, 1 dacă jucătorul poate obţine o remiză şi 2 dacă jucătorul are o strategie sigură de câştig. Fiecare jucător va alege mutarea potrivită astfel încât să maximizeze valoarea $R$, care este în acelaşi timp rezultatul cel mai prost pentru celălalt jucător. Vom nota jucătorii prin 0 şi 1 şi putem calcula valoarea optimă pentru $R$ astfel:\r\n\r\n<tex> $R[J, n_0, n_1, n_{2A}, n_{2B}, n_3, n_4] = 2 - \\min\\{R[\\(1 - J\\), n_0\', n_1\', n_{2A}\', n_{2B}\', n_3\', n_4\'] \\}$</tex> dacă $(n\'{~0~}, n\'{~1~}, n\'{~2A~}, n\'{~2B~}, n\'{~3~}, n\'{~4~})$ reprezintă o stare accesibilă din starea curentă printr-o singură mutare. Observăm că rezultatul este cu atât mai bun pentru unul dintre jucători cu cât este mai prost pentru celălalt, deci rezultatele sunt invers proporţionale, $2$ pentru $J$ reprezentănd $0$ pentru jucătorul $1 - J$. Fiecare jucător alege mutarea care îi va obţine rezultatul maxim, acesta fiind corespunzător rezultatului defavorabil (de valoare minimă) pentru celălalt.\r\n\r\nStările pentru care nu mai există decât grămezi de tipuri $2A$ şi $2B$ sunt, conform enunţului, stări finale. \r\n<tex> $R[J, 0, 0, n_{2A}, n_{2B}, 0, 0] = \\left\\{ \r\n\\begin{array}{l l}\r\n  0 & \\quad J = 0, n_{2A} < n_{2B}\\\\\r\n  0 & \\quad J = 1, n_{2A} > n_{2B}\\\\ \r\n  1 & \\quad n_{2A} = n_{2B}\\\\\r\n  2 & \\quad J = 0, n_{2A} > n_{2B}\\\\ \r\n  2 & \\quad J = 1, n_{2A} < n_{2B}\\\\\r\n\\end{array} \\right. $</tex>\r\n\r\n\r\n\r\n\r\nTo be continued ... \r\n\r\n',2996,'public',NULL,NULL),('pd','Tehnici avansate de programare dinamică','2007-12-04 21:25:10','2009-11-06 21:35:13','h1. Tehnici avansate de programare dinamică\r\n\r\n(Categoria _Tehnici de programare_, autori _Catalin Tiseanu_, _Andrei Homescu_)\r\n\r\nTODO:\r\n\r\n1. Reparat link de la ugly numbers\r\n\r\nPlan de atac (probleme-candidat):\r\n\r\n1. http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en (Reducerea complexitatii, transformarea problemei intr-una de construire a unui arbore binar.)\r\n\r\n2. http://code.google.com/codejam/contest/dashboard?c=32001#s=p0&a=3 (Boolean tree, programare dinamica simpla pe arbore binar.)\r\n\r\n3. http://code.google.com/codejam/contest/dashboard?c=32001#s=p3&a=3 (PermRLE, permutari cu N*2^N)\r\n\r\n4. http://code.google.com/codejam/contest/dashboard?c=32010#s=p3&a=3 (problema cu DP pe matrici, aplicam ridicarea la putere pt calcul rapid)\r\n\r\n5. http://infoarena.ro/problema/doipatru (joc cu solutie DP, stare in 6 dimensiuni)\r\n\r\nh2. Sugestii Silviu\r\n\r\n* poate ca nu trebuie sa spunem tot despre programare dinamica intr-un singur articol; spre exemplu putem facem doua articole: PD basic si PD advanced\r\n* cred ca era si ceva prin Cartea lui Francu\' despre programare dinamica; ar merge incorporat (eventual in pd_basic).\r\n\r\nh2. Introducere\r\n\r\nProgramarea dinamică este o metodă utilă pentru a rezolva probleme care pot fi obţinute prin compunerea a mai multor bucăţi, a căror soluţie poate fi apoi determinată optim. Se bazează în principal pe proprietatea unei probleme de a putea fi rezolvată optim dacă se cunosc soluţii optime la sub-problemele ei.\r\nDe menţionat că \'programare\' nu se referă aici la scrierea de cod într-un limbaj de programare, ci la \'programare matematica\', care constă în optimizarea unei funcţii prin alegerea de valori dintr-o mulţime anume. \r\n\r\nScopul acestui articol nu este să ofere o introducere in programare dinamică (pentru aceasta poate fi consultat excelentul tutorial de pe TopCoder \"Dynamic Programming : From novice to advanced\":http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg). În schimb, acest articol îşi propune să ofere nişte \'smenuri\' mai avansate de rezolvare a problemelor cu programare dinamică. \r\n\r\nh2. Reducerea loop-ului interior\r\n\r\nÎn problemele de programare dinamică de multe ori prima complexitate obţinută nu este optimă. Mai exact, recurenţa obţinută iniţial poate fi îmbunătăţită sau calculată mai rapid. De multe ori, pentru aceasta se optimizeaza loop-ul interior din calculul recurenţei. Acest lucru se poate face bazat fie pe observaţii specifice problemei, fie pe tehnici mai clasice.\r\n\r\nSă considerăm următoarea problema:\r\n\r\nh3(#problema-1). Problema 1: \'Drilling\':http://www.main.edu.pl/user.phtml?op=showtask&task=wie&con=PA2009&lang=en (Algorithmic Engagements 2009, Round 3)\r\n\r\nbq. Se da un şir de $N$ numere naturale $(a{~1~}, a{~2~}, ..., a{~N~})$. Se ştie că un prefix al acestui şir (adică o subsecvenţă de la începutul şirului, posibil nulă) este **defect**. Toate elementele din acel prefix (şi doar din acel prefix) sunt defecte. Se ştie de asemenea că se poate testa orice poziţie $i$ în timp $a{~i~}$ pentru a afla dacă este defectă. Să se determine timpul minim în cazul cel mai defavorabil pentru aflarea lungimii maxime a prefixului şirului care este defect.\r\n\r\nh3. Exemplu:\r\n\r\nPentru secvenţa de numere $(8 24 12 6)$, răspunsul ar fi $42$. Astfel, se testează mai întâi poziţia $2$. Dacă nu este defectă, mai rămâne de testat poziţia $1$. Altfel, în cel mai rău caz mai trebuie testate poziţiile $3$ şi $4$, aducând timpul total la $24 + 12 + 6 = 42$.\r\n\r\nh3. Rezolvare:\r\n\r\nO să începem prin a da altă îmbrăcăminte problemei. Astfel, să ne imaginăm că am construi un arbore binar de căutare pe şirul dat, având drept chei poziţiile din şir, şi drept valori auxiliare valorile poziţiilor respective din şir (un nod cu cheia $i$ va avea valoarea auxiliara $a{~i~}$.\r\nAcum, există mulţi arbori binari de căutare posibile pentru şirul iniţial. Totuşi, să presupunem că am construit unul, pe care îl considerăm de acum ca fixat. Atunci, strategia noastra de testare a elementelor din şir se va desfăşura conforma arborelui. Astfel, testăm mai întâi în poziţia din rădăcină. Dacă poziţia respectivă este defectă, ne ducem în fiul drept. Altfel, mergem in fiul stâng. În ambele cazuri se reia procedeul. Căutarea se termină cand nu mai putem merge într-un fiu. \r\n\r\nSă observăm că dacă considerăm costul unui drum în arbore de la rădăcină la o frunză ca suma valorilor auxiliare din drumul (unic) respectiv, atunci se observă că costul strategiei bazate pe acest arbore este chiar costul maxim al unui drum ! De acum încolo, vom defini costul unui arbore ca costul maxim al unui drum de la rădăcină la o frunză. Să exemplificăm pe şirul din exemplu:\r\n\r\np=. !pd?Diagram1.png!\r\n\r\np=. _Fig. 1: În paranteză sunt valorile auxiliare ataşate cheilor_\r\n\r\nSe observă că costul maxim al unui drum este $42$, minim posibil, exact ca răspunsul din exemplu. Deci, am redus problema la construirea unui arbore binar de căutare, care are costul minim.\r\n\r\nAcum devine clară o primă soluţie folosind programarea dinamică. Astfel, să presupunem că notăm cu $opt[ i ][ j ]$ costul minim al unui arbore construit pe cheile din $[i,j]$ (prin asta notăm (i, i + 1, ..., j). Fie $r[ i ][ j ]$ poziţia rădăcinii arborelui cu costul minim. În cazul existenţei mai multor rădăcini posibile, se alege cea mai din stânga. Cum am putea construi arborele de cost minim pe cheile $[i,j]$ ştiind răspunsul pentru instanţele mai mici (subsecvenţele de lungime mai mică ca $j-i+1$ pe $[i,j]$)? (!) Simplu, arborele de cost minim pe $[i,j]$ se obţine alegând drept rădăcină în mod optim o poziţie $k$, cu <tex>$i \\le k \\le j$</tex>, la care se pune ca fiul stâng arborele optim pentru $[i, k-1]$, şi ca fiu drept arborele optim pentru $[k+1, j]$. Relaţia de recurenţă devine:\r\n\r\n$opt[ i ][ j ]$ = <tex>\\displaystyle\\min_{i \\le k \\le j} \\{a_{k} + \\max( opt[i][k-1], opt[k+1][j] )\\} </tex>   \r\n$r[ i ][ j ]$ = <tex>\\displaystyle\\arg \\min_{i \\le k \\le j}\\{a_{k} + \\max (opt[i][k-1], opt[k+1][j] )\\} </tex> \r\n\r\nAvem @opt[i][j] = 0@, pentru $j < i$.\r\nCazurile de bază sunt @opt[i][i]@ = a{~i~} si @r[i][i] = i@.\r\n\r\nSe observă că răspunsul problemei se află în @opt[1][N]@.\r\nAstfel, am obţinut o soluţie în timp $O(N^3)$.\r\n\r\nAici trebuie remarcată asemănarea acestei probleme cu cea a determinării arborelui de căutare optim, atunci cand se dau probabilităţile relative de căutare a cheilor. Această problemă se numeşte \'Optimal Binary Search Tree\' în literatura de specialitate şi poate fi găsită şi în _Introduction to Algorithms_. În aceasta problemă, se poate aplica o reducere a complexităţii datorită faptului că <tex>$ r[i][j-1] \\le r[i][j] \\le r[i+1][j] $</tex> pentru a reduce complexitatea la $O(N^2)$. Această proprietate nu se poate aplica din păcate şi în cazul problemei noastre.\r\n\r\nPână acum avem următorul pseudocod pentru calculul recurenţei:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    iniţializează opt şi r\r\n    pentru len = 1, N execută\r\n        pentru i = 1, N - len + 1 execută\r\n            j = i + len - 1;\r\n            opt[i][j] = inf;\r\n            pentru k = i, j execută\r\n                dacă opt[i][j] < a[k] + max(opt[i][k-1], opt[k+1][j]) atunci\r\n                    opt[i][j] = a[k] + max(opt[i][k-1], opt[k+1][j]);\r\n                    r[i][j] = k;\r\n            sfârşit_pentru;\r\n       sfârşit_pentru;\r\n    sfârşit_pentru;\r\n\r\n    return opt[1][N];\r\nSfârşit.\r\n==\r\n\r\nAcum ca să obţinem o complexitate mai bună, ţinând cont şi de numele capitolului, vom încerca să reducem complexitatea loop-ului interior (cel după $k$).\r\nSă ne uităm mai atent la acest loop.\r\n\r\nFie un interval $[i,j]$ fixat. Acum, $opt[i][j] < opt[i][j\']$, pentru orice $j < j\'$. Similar, $opt[i][j] < opt[i\'][j]$, pentru orice $i\' < i$.\r\nAtunci, există un indice $k$, <tex>$i \\le k \\le j$</tex> astfel încât $max(opt[i][o-1], opt[o+1][j]) = opt[o+1][j]$, pentru orice <tex>$i \\le o \\le k$</tex>, şi $max(opt[i][o-1], opt[o+1][j]) = opt[i][o-1]$ pentru orice <tex>$k \\le o \\le j$</tex>. După cum ştim, trebuie să aflăm <tex>\\displaystyle\\min_{i \\le k \\le j} \\{a_{k} + \\max( opt[i][k-1], opt[k+1][j] )\\} </tex>. Să definim acum 3 matrici auxiliare:\r\n\r\n@to_left[ i ][ j ]@ = $a{~i~} + opt[ i + 1 ][ j ]$\r\n@to_right[ i ][ j ]@ = $a{~j~} + opt[ i ][ j - 1 ]$\r\n@inter[ i ][ j ]@ = <tex>\\displaystyle\\arg \\max_{i \\le k \\le j}\\{opt[i][k-1] \\le opt[k+1][j]\\} </tex>\r\n\r\nSe observă că $inter[i][j]$ nu reprezintă altceva decât indicele $k$ tratat in paragraful precedent.\r\nDe asemenea, $inter$ poate fi calculată în $O(N^2)$ observând o proprietate simplă: <tex>$ inter[i][j-1] \\le inter[i][j] \\le inter[i+1][j] $</tex>. Aceasta reiese imediat din monotonia lui $opt$ discutată mai sus. Pseudocodul pentru calculul lui $inter$ este:\r\n\r\n== code(cpp) |\r\nAlgoritmul este:\r\n    iniţializează opt, inter şi r\r\n    pentru len = 1, N execută\r\n        pentru i = 1, N - len + 1 execută\r\n            j = i + len - 1;\r\n            calculează opt[i][j]\r\n            pentru k = inter[i][j-1], inter[i+1][j] execută\r\n                dacă opt[i][k-1] <= opt[k+1][j] atunci\r\n                    inter[i][j] = k;\r\n            sfârşit_pentru;\r\n       sfârşit_pentru;\r\n    sfârşit_pentru;\r\nSfârşit.\r\n==\r\n\r\nDe menţionat că trebuie avut grijă la cazul când $len$ este mai mic ca $3$. Pseudocodul prezentat mai sus este orientativ.\r\nSă vedem acum de ce această modalitate de calcul a lui $inter$ duce la o complexitate de $O(N^2)$.\r\n\r\nAlternativ, se poate căuta binar $inter[i][j]$ pentru orice $[i,j]$.\r\n\r\nAcum vine ideea decisivă pentru a reduce complexitatea loop-ului: pentru a afla $opt[i][j]$, este suficient să aflăm minimul dintre 2 valori:\r\n\r\n* <tex>\\displaystyle\\min_{i \\le k \\le inter[i][j]} \\{$to\\_left[k][j]$\\} </tex> şi\r\n* <tex>\\displaystyle\\min_{inter[i][j] < k \\le j } \\{$to\\_right[i][k]$\\} </tex>\r\n\r\nMai exact,\r\n\r\n@opt[ i ][ j ]@ = <tex> \\min( \\displaystyle\\min_{i \\le k \\le inter[i][j]} \\{$to\\_left[k][j]$\\},\r\n                              \\displaystyle\\min_{inter[i][j] < k \\le j } \\{$to\\_right[i][k]$\\} ) </tex>\r\n\r\nDiferenţa faţă de prima recurentă este evidentă: acum trebuie să aflăm minimul pe un interval de linii, în cazul $to_left$, şi minimul pe un interval de coloane, în cazul $to_right$. Atât aflarea mnimului pe un interval, cât şi update-ul acestei valori se poate face în $O(logN)$, folosind \'arbori de intervale\':http://infoarena.ro/arbori-de-intervale.\r\n\r\nAstfel, am redus complexitatea loopului interior de la $O(N)$ la $O(logN)$.\r\n\r\n\r\n\r\nh2. Programare dinamică folosind măşti de biţi şi codificări $k$-are\r\n\r\nUnele probleme de programare dinamica au drept componentă a stării unei subprobleme o mulţime de elemente care fac parte din subproblemă. Astfel, subproblema nu este o reducere a problemei iniţiale la un subset continuu de elemente ($1..i$ sau $i..j$) ci la un subset oarecare. În acest caz, codificăm submulţimea curentă în stare, ca vector sau ca număr întreg. Dacă dimensiunea submulţimii este suficient de mic putem folosi un întreg pentru a codifica această informaţie astfel:\r\n\r\nFie mulţimea $A$ = { x{~1~}, x{~2~}, ... x{~n~} }.\r\nAtunci masca de biţi a unei partitii a lui $A, $MASK$, va avea bitul $i$ egal cu 1 dacă şi numai dacă x{~i~} apartine partitiei. Desigur, această reprezentare duce la o complexitate direct proporţională cu $2 ^card(A)^$. Putem intui dacă trebuie să folosim o astfel de rezolvare din limitele valorilor de intrare; pentru $N$ cu valori cuprinse între $10-20$, deducem că trebuie să căutăm o astfel de soluţie.\r\n\r\nPentru multe probleme, fiecare element poate face parte din subproblemă în mai mult de 2 feluri. De exemplu, dacă starea reprezintă o linie de maxim $K$ elemente dintr-o matrice iar fiecare element de pe linie poate avea valorile 0, 1 sau 2 atunci există $3^K$ variante distincte posibile pentru o astfel de linie. Un alt exemplu este o problemă de optimizare în care fiecare element (participant) se poate afla în una din câteva stări (dacă $N$ persoane trebuie să treacă un pod peste un râu, cele 3 stări pot fi: _pe malul stâng_, _pe pod_ şi _pe malul drept_).\r\n\r\n\r\nh3(#problema-1). Problema 1: \'Be a Smart Raftsman\':http://acm.sgu.ru/problem.php?contest=0&problem=475 (SGU)\r\n\r\nbq. Sunteţi membri ai unui echipaj de rafting care constă din $N ≤ 10$ participanţi. Puteţi naviga pe râu, şi scopul vostru este să treceţi de $M ≤ 1000$ curenţi consecutivi şi să ajungi de la punctul de început la punctul de sfârşit în timp minim. Cel de-al $i$-lea curent se caracterizează prin greutatea critică $c{~i~}$, iar al $j$-lea participant este caracterizat greutatea sa $w{~j~}$. În cazul în care pluta trece prin al $i$-lea curent cu oameni la bord cu greutatea totală mai mare de $c{~i~}$, ea se răstoarnă. Această parte a rafting-ului este cea mai interesantă, dar este nevoie de timp suplimentar pentru a te urca pe plută după răsturnare. Deci, uneori este mai bine să se urce un grup de oameni cu greutate totală care nu depăşeşte greutatea critică a plutei, în timp ce restul parcurg distanţa pe jos.\r\nMai formal, vom considera $M + 1$ puncte $P{~0~}, P{~1~} ,..., P{~M~}$, în cazul în care $P{~0~}$ este începutul şi $P{~M~}$ este punctul final. Fiecare dintre punctele intermediare $P{~i~} (1 ≤ i ≤ M-1)$ este situat între $i$-lea şi $(i + 1)$-lea curent. Dacă pluta se răstoarnă, sunt necesare $D{~i~}$ minute pentru a ajunge de la $P{~i-1~}$ la $P{~i~}$, altfel sunt necesare $d{~i~}$ minute. Cel de-al $j$-lea participant poate merge pe jos de la $P{~i-1~}$ la $P{~i~}$ în $t{~j~}$ minute, iar pentru a se urca sau a coborî din plută are nevoie de $s{~j~}$ minute. Înainte de fiecare curent, grupul vostru este împărţit în două părţi. Prima parte trece prin curent cu pluta, iar a doua parte merge pe mal spre următorul punct. Cei care ajung primii îi aşteaptă pe toţi ceilalţi. Apoi, unii participanţi care sunt pe plută se pot da jos, în timp ce alţi participanti care sunt pe mal se pot urca pe plută. Această activitate începe când ajung pluta şi toţi cei de pe mal la punctul stabilit. Timpul total necesar pentru această acţiune este egal cu suma valorilor $s{~j~}$ pentru toate persoanele care schimbă locul (persoanele urcă şi coboară pe rând). Nimeni nu poate începe deplasarea la următorul punct, până când nu s-au mutat toţi membrii.\r\nîncepeţi de la punctul de $P{~0~}$ cu tot grupul pe mal şi trebuie să terminaţi la punctul $P{~M~}$ cu toţi participanţii şi pluta pe mal. Nu aveţi voie să părăsiţi pluta la început sau într-un un punct intermediar şi să mergeţi pe jos spre linia de sosire fără ea. Aveţi posibilitatea să urcaţi tot grupul de salvare în plută, dar nu puteţi lăsa pluta goală în timpul călătoriei printr-un curent. \r\nSarcina voastră este să calculaţi timpul minim necesar pentru a ajunge la linia de sosire.\r\n\r\nh3. Rezolvare:\r\n\r\nDin enunţ intuim că o componentă a stării trebuie să fie submulţimea participanţilor aflaţi în plută în punctul curent, intuiţie confirmată de numărul mic al participanţilor ({$N ≤ 10$}). Există $2^10^$ astfel de variante, din care vom exclude varianta în care pluta este goală. O stare a problemei, reprezentănd soluţia unei subprobleme, va fi alcătuită din poziţia curentă a plutei (punctul $P{~i~}$ unde se află) şi submulţimea oamenilor care se află în plută. Observăm că de la punctul precedent pluta a traversat curentul, au urcat nişte oameni apoi au coborât alţii; aceşti paşi contribuie la timpul total şi reprezintă 2 părţi ale recurenţei soluţiei. Dacă notăm cu $T{~m~}[i][S]$ timpul minim necesar pentru a ajunge în punctul $i$ cu submulţimea $S$ a oamenilor din plută, putem descrie problema prin relaţiile:\r\n\r\n<tex> $T_m[0][0] = 0$ </tex>\r\n<tex> $T_m[0][S] = T_u[0][S], \\forall S \\neq 0$ </tex>\r\n<tex> $T_m[i][S] = \\min_{S\' \\neq \\emptyset} \\{T_m[i-1][S\'] + T_t[i][S\'] + T_u[S\'][S] + T_c[S\'][S]\\}, \\forall 1 \\le i \\le M$ </tex>\r\n\r\nunde $T{~u~}[S\'][S]$ este timpul necesar pentru urcarea participanţilor care se găsesc în mulţimea $S$ dar nu fac parte din mulţimea $S\'$ (aceşti participanţi alcătuiesc mulţimea $S{~u~}$), $T{~c~}[S\'][S]$ este timpul necesar pentru coborârea participanţilor din plută (participanţii din mulţimea $S{~c~}$), iar $T{~t~}[i][S]$ este timpul necesar traversării curentului de la punctul $i-1$ la punctul $i$ dacă în plută se află participanţii din $S$. Formulele pentru valorile $T{~u~}$, $T{~c~}$ şi $T{~t~}$ sunt:\r\n\r\n<tex> $T_u[S_1][S_2] = \\sum_{i \\in S_2 - S_1}{s_i} = \\sum_{i \\in S_u}{s_i}$ </tex>\r\n<tex> $T_c[S_1][S_2] = \\sum_{i \\in S_1 - S_2}{s_i} = \\sum_{i \\in S_c}{s_i}$ </tex>\r\n<tex> $T_t[i][S] = \\left\\{ \r\n\\begin{array}{l l}\r\n  D_i & \\quad \\sum_{j \\in S}{w_j} > c_i\\\\\r\n  d_i & \\quad \\sum_{j \\in S}{w_j} \\le c_i\\\\ \r\n\\end{array} \\right. $</tex>\r\n\r\nCalcularea directă a soluţiei pe baza recurenţelor de mai sus are complexitatea $O(M*N*2^N^ + M*2^N^*2^N^)$. Primul termen al complexităţii este dat de calcularea valorilor $T{~t~}$, iar al doilea de calcularea matricii $T{~m~}$.\r\n\r\nValoarea rezultatului nu depinde de ordinea în care urcă şi coboară participanţii din plută, deci o putem alege noi. Dacă aranjăm ordinea în doi paşi astfel încât în primul pas doar să urce, apoi în al doilea pas doar să coboare, vom obţine o îmbunătăţire semnificativă a timpului de execuţie. Se observă că dacă am efectua doar adăugări de elemente (daca în plută s-ar putea doar urca persoane, fără să poată coborî), atunci <tex> $S\' \\in S$ </tex> şi deci reprezentarea în cod binar a mulţimii $S\'$ ar avea o valoare mai mică decât reprezentarea binară a mulţimii $S$. Dacă ar avea voie doar să coboare persoane, relaţia ar fi inversă. De aceea, vom ordona operaţiile de urcare şi coborâre astfel încât să aibă loc întâi toate urcările (astfel încât să putem parcurge crescător valorile binare ale mulţimilor) apoi toate coborârile (astfel încât să putem efectua a doua parcurgere, în ordine descrescătoare). Introducem matricea auxiliară $T{~um~}[i][S]$ care reprezintă timpul minim necesar la care se poate afla pluta în punctul $i$ cu mulţimea $S$ de oameni, dacă după ultima traversare nu a coborât încă nici o persoană. Starea $S$ a fost obţinută prin una sau mai multe urcări de persoane în plută sau direct prin traversarea curentului. Recurenţele pentru $T{~um~}[i][S]$ sunt:\r\n\r\n<tex> $T_{um}[i][S] = \\min \\left(T_m[i-1][S] + T_t[i][S], \\min_{j \\in S}\\{T_{um}[i][S - j] + s_j\\} \\right) </tex>\r\n<tex> $T_m[i][S] = \\min \\left(T_{um}[i][S], \\min_{j \\not\\in S}\\{T_m[i][S \\cup j] + s_j\\} \\right) </tex>\r\n\r\nAm eliminat calcularea matricilor $T{~u~}$, $T{~c~}$. Toate matricile rămase au dimensiunea $Mx2^N^$ iar calcularea fiecărui element necesită un timp $O(N)$, deci soluţia astfel obţinută are complexitatea $O(M*N*2^N^)$.\r\n\r\n== code(cpp)    |\r\n    iniţializează toate Tm[0];\r\n    pentru i = 1, M execută\r\n        calculează toate Tt[i];\r\n        pentru fiecare S în ordine crescătoare a reprezentării binare execută\r\n            Tum[i][S] = Tm[i-1][S] + Tt[i][S];\r\n            pentru fiecare j din S execută\r\n                Tum[i][S] = min(Tum[i][S], Tum[i][S - j] + s[j]);\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n        pentru fiecare S în ordine descrescătoare a reprezentării binare execută\r\n            Tm[i][S] = Tum[i][S];\r\n            pentru fiecare j care nu există în S execută\r\n                Tm[i][S] = min(Tm[i][S], Tm[i][S + j] + s[j]);\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează Tm[M][0];\r\n==\r\n\r\nMai există două optimizări de spaţiu pe care le putem efectua în soluţia prezentată. Putem elimina matricea $T{~um~}$, calculând toate valorile direct pe matricea $T{~m~}$, deoarece aceasta va fi parcursă în ambii paşi în câte o singură direcţie. A doua optimizare se bazează pe observaţia că nu avem niciodată nevoie de alte linii în afară de ultimele 2 ({$i$} si {$i-1$}), deci putem înlocui matricea cu 2 vectori de dimensiune $2^N^$. Valorile $T{~t~}$ pot fi calculate în cadrul primei bucle, reducând astfel spaţiul necesar soluţiei la $O(2^N^)$.\r\n\r\n\r\n\r\nh2. Programare dinamica pe mai multe dimensiuni\r\n\r\nUnele probleme nu pot fi împărţite în subprobleme doar după o submulţime a datelor de intrare ale problemei curente, ci trebuie adăugate criterii suplimentare. De multe ori, aceste valori sunt similare sumei din _problema rucsacului_, dar calculele se fac pe 2 sau chiar mai multe dimensiuni, obţinând o descriere destul de complexă a unei subprobleme. De exemplu, o subproblemă poate fi reprezentată printr-un vector de valori de dimensiuni variate.\r\n\r\n\r\nh3(#problema-1). Problema 1: \'Ugly numbers\':http://code.google.com/codejam/contest/dashboard?c=32015#s=p1&a=1 (Google Code Jam 2008, Round 1C)\r\n\r\nbq. Un număr se numeşte *urât* dacă este divizibil prin oricare dintre numerele prime de o singură cifră, mai exact $2, 3, 5, 7$. Se dă un şir de $N$ cifre. Între fiecare 2 cifre consecutive se poate insera unul dintre semnele + sau -. Dacă nu se inserează un semn, cele 2 cifre sunt concatentate astfel încât să se obţină un număr. Pentru un şir dat de cifre si o variantă de a adăuga semne, prin evaluarea expresiei matematice obţinute prin inserarea semnelor se obţine un număr, numit numărul generat. Să se calculeze câte dintre cele $3^N-1^$ variante de a insera semnele generează numere urâte.\r\n\r\nh3. Exemplu: \r\n\r\nPentru cifrele $123456$, expresia $1+234-5+6 = 236$ care este număr urât, iar $123+4-56 = 71$ nu este număr urât.\r\n\r\nh3. Rezolvare:\r\n\r\nObservăm că un număr este urât dacă dă cel puţin o dată restul 0 la împărţirea la numerele $2, 3, 5, 7$. O abordare a problemei este parcurgerea tuturor variantelor de inserare şi calcularea celor 4 resturi, verificând dacă cel puţin unul este 0.\r\nVom folosi aritmetica modulară pentru a obţine o soluţie mai eficientă a problemei. Vom împărţi cele $3^N-1^$ variante în clase, fiecare clasă reprezentând toate numerele care dau resturile $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ la împărţirea la cele 4 numere. Calculând pentru fiecare clasă numărul de numere generate, rezultatul final va fi suma valorilor calculate pentru toate clasele pentru care cel puţin un rest este egal cu 0. Intuim că putem utiliza clasele de resturi într-o soluţie cu programare dinamică.\r\nVom utiliza şirul auxiliar $V[i][j]$ reprezentând numărul format prin concatenarea cifrelor de pe poziţiile consecutive $i, i+1, ..., j$ din şirul dat, fără inserarea unor semne între cifre. De exemplu, @V[2][4] = 234@. Dacă notăm cu $C[i][r{~2~}][r{~3~}][r{~5~}][r{~7~}]$ numărul de variante formate cu primele $i$ cifre pentru care clasa de resturi este $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$. Observăm că orice astfel de variantă se obţine dintr-o variantă cu $j < i$ cifre după care adăugam + sau - apoi concatenăm restul cifrelor până la $i$ fără semne. Dacă resturile pentru varianta cu $j$ cifre erau $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ atunci resturile pentru varianta nouă $(r\'{~2~}, r\'{~3~}, r\'{~5~}, r\'{~7~})$ sunt:\r\n<tex> $r_2\' = (r_2 +/- V[j+1][i])\\% 2$</tex>\r\n<tex> $r_3\' = (r_3 +/- V[j+1][i])\\% 3$</tex>\r\n<tex> $r_5\' = (r_5 +/- V[j+1][i])\\% 5$</tex>\r\n<tex> $r_7\' = (r_7 +/- V[j+1][i])\\% 7$</tex>\r\nAtunci numărul total de variante cu $i$ cifre este suma după toate valorile $j$ ale numerelor de variante cu $j$ cifre:\r\n<tex> $C[i][r_2\'][r_3\'][r_5\'][r_7\'] = \\sum_{j<i} C[j][r_2][r_3][r_5][r_7]$ </tex>\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i]\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = V[i][j - 1] + A[i];\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0][0][0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r_2 = 0, 1 execută\r\n            pentru r_3 = 0, 2 execută\r\n                pentru r_5 = 0, 4 execută\r\n                    pentru r_7 = 0, 6 execută\r\n                        C[i][r_2][r_3][r_5][r_7] = 0;\r\n                        pentru j = 0, i - 1 execută\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + 2 - V[j+1][i])%2)][(r_3 + 3 - V[j+1][i])%3)]\r\n                                                            [(r_5 + 5 - V[j+1][i])%5)][(r_7 + 7 - V[j+1][i])%7)];\r\n                            C[i][r_2][r_3][r_5][r_7] += C[j][(r_2 + V[j+1][i])%2)][(r_3 + V[j+1][i])%3)]\r\n                                                            [(r_5 + V[j+1][i])%5)][(r_7 + V[j+1][i])%7)];\r\n                        sfârşit pentru;\r\n\r\n                        dacă i == N şi (r_2 == 0 sau r_3 == 0 sau r_5 == 0 sau r_7 == 0)\r\n                            S += C[i][r_2][r_3][r_5][r_7]\r\n                        sfârşit pentru;\r\n                    sfârşit pentru;\r\n                sfârşit pentru;\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează S;\r\n==\r\n\r\nO problemă în abordarea precedentă este calcularea matricii $V$, ale cărei valori devin foarte mari şi ies din precizia tipurilor de date disponibile. O soluţie posibilă este calcularea câte unei matrici de sume modulo $R$ pentru fiecare rest $R$, adica a 4 matrici $V{~2~}$, $V{~3~}$, $V{~5~}$ si $V{~7~}$ ale resturilor împărţirii valorilor lui $V$ la cele 4 numere prime. Folosind aritmetica modulară, aceste matrici pot fi calculate direct, fără a calcula $V$. Altă variantă este utilizarea teoremei chineze a resturilor, prin care un sistem de ecuaţii modulo câteva numere prime între ele poate fi redus la o ecuaţie modulo produsul numerelor date. În cazul nostru, numerele sunt prime, deci putem aplica teorema. Astfel, putem reduce problema resturilor împărţirii la $(2, 3, 5, 7)$ la problema restului împărţirii la $2*3*5*7=210$, deci fiecare clasa $(r{~2~}, r{~3~}, r{~5~}, r{~7~})$ se reduce la un rest $R < 210$. Modificăm pseudocodul astfel:\r\n\r\n== code(cpp)    |\r\n    pentru i = 1, N execută\r\n        V[i][i] = A[i] % 210\r\n        pentru j = i + 1, N execută\r\n            V[i][j] = (V[i][j - 1] + A[i]) % 210;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n\r\n    C[0][0] = 1;\r\n    S = 0;\r\n    pentru i = 1, N execută\r\n        pentru r = 0, 209 execută\r\n            C[i][r] = 0;\r\n            pentru j = 0, i - 1 execută\r\n                C[i][r] += C[j][(r + 210 - V[j+1][i]) % 210];\r\n                C[i][r] += C[j][(r + V[j+1][i]) % 210];\r\n            sfârşit pentru;\r\n\r\n            dacă i == N şi (r % 2 == 0 sau r % 3 == 0 sau r % 5 == 0 sau r % 7 == 0)\r\n                S += C[i][r];\r\n            sfârşit pentru;\r\n        sfârşit pentru;\r\n    sfârşit pentru;\r\n    returnează S;   \r\n==\r\n\r\n\r\nh3(#problema-2). Problema 2: \'Doipatru\':http://infoarena.ro/problema/doipatru\r\n\r\nbq. Membrii Lotului Naţional de Informatică sunt foarte mândri de noul joc inventat de ei, pe care l-au denumit asemănător cu o problemă de la Olimpiada Internaţională de Informatică din anul 2001, care le-a plăcut foarte mult. Astfel, jocul se numeşte DoiPatru.\r\nPentru acest joc se folosesc $3 ≤ N ≤ 30$ grămezi, fiecare conţinând cel puţin 0 şi cel mult 4 bile. Numărul total de bile din toate grămezile este $2*N$. Doi jucători mută alternativ. Atunci când ii vine rândul, fiecare jucător este obligat să efectueze o mutare validă.\r\nO mutare validă constă din alegerea a două grămezi, dintre care prima grămadă are mai multe bile decât cea de a doua. Jucătorul ia o bilă din prima grămadă şi o mută în cealaltă. Mutarea se consideră validă, doar dacă numărul de bile rezultat în a doua grămadă după mutarea bilei nu este mai mare decât numărul de bile rămas în prima grămadă.\r\nJocul se termină atunci când nu mai poate fi efectuată nici o mutare validă (dacă vă gândiţi puţin, veţi constata că acest lucru se întâmplă atunci când fiecare grămadă conţine două bile).\r\nCâştigătorul jocului este desemnat cel care deţine mai multe grămezi la sfârşitul jocului. Bineînţeles, dacă cei doi jucători deţin un număr egal de grămezi, jocul se consideră a fi remiză.\r\nUn jucător deţine o grămadă dacă grămada are două bile, iar acest număr (de două bile) a rezultat în urma unei mutări efectuate de jucătorul respectiv. De exemplu, dacă un jucător alege o grămadă cu 4 bile şi una cu o bilă, în urma efectuării mutării, el va deţine cea de-a doua grămadă (care va avea două bile), dar prima nu va aparţine deocamdată nici unuia dintre jucători. Dacă alege o grămadă cu 3 bile şi una cu 0 bile, jucătorul va deveni proprietarul primei grămezi, deoarece, în urma mutării efectuate, grămada respectivă va rămâne cu două bile. În cazul în care alege o grămadă cu 3 bile şi una cu o bilă, după efectuarea mutării, el va deţine ambele grămezi (amândouă au acum doua bile).\r\nDacă un jucător este proprietarul unei grămezi la un moment dat în timpul jocului, nu înseamnă că această grămadă va rămâne în posesia lui până la sfârşit. De exemplu, să presupunem că jucătorul 1 deţine o grămadă cu două bile şi este rândul jucătorului 2 să mute. Dacă acesta alege o grămadă cu 4 bile şi grămada cu două bile ce aparţine jucătorului 1, după efectuarea mutării, ambele grămezi vor avea 3 bile, iar numărul de grămezi aflate în posesia jucătorului 1 va scădea cu 1 (grămada deţinută de el anterior nu mai aparţine nici unuia din cei doi jucători, căci nu mai are doua bile).\r\nDacă la începutul jocului există unele grămezi având două bile, acestea sunt distribuite în mod egal celor doi jucători. Dacă numărul de grămezi cu două bile este impar, atunci jucătorul 2 va primi cu o grămadă mai mult decât jucatorul 1. Jucătorul 1 este cel care efectuează prima mutare.\r\nScrieţi un program care, pentru un $N$ dat şi un set de configuraţii iniţiale ale jocului cu $N$ grămezi, decide rezultatul fiecărei configuraţii de joc.\r\n\r\nh3. Rezolvare:\r\n\r\nÎncepem rezolvarea cu observaţia că există 5 tipuri de grămezi (0, 1, 2, 3 şi 4 bile), dar pentru fiecare grămadă de 2 bile aparţine doar unuia dintre jucători, informaţie esenţială pentru stabilirea câştigătorului. Vom separa deci toate grămezile de 2 bile în 2 categorii: $2A$ care reprezintă grămezile de 2 bile deţinute de primul jucător şi $2B$ care sunt grămezile de 2 bile deţinute de al doilea jucător. Orice moment al jocului poate fi reprezentat identificând jucătorul care urmează la mutare şi numărul de bile din fiecare dintre cele $N$ grămezi. O variantă alternativă este de a reprezenta numerele de grămezi din fiecare tip, starea fiind reprezentată prin valorile $(J, n{~0~}, n{~1~}, n{~2A~}, n{~2B~}, n{~3~}, n{~4~})$, unde $n{~k~}$ reprezintă numărul de grămezi care au $k$ bile (cu excepţiile $2A$ şi $2B$, descrise înainte).\r\nVom nota prin $R[J, n{~0~}, n{~1~}, n{~2A~}, n{~2B~}, n{~3~}, n{~4~}]$ cel mai bun rezultat pe care îl poate obţine jucătorul care urmează ({$J$}). Valorile posibile ale rezultatului vor fi alese ca numere întregi crescătoare, astfel: 0 dacă din configuraţia curentă jucătorul nu are nici o şansă să câştige, 1 dacă jucătorul poate obţine o remiză şi 2 dacă jucătorul are o strategie sigură de câştig. Fiecare jucător va alege mutarea potrivită astfel încât să maximizeze valoarea $R$, care este în acelaşi timp rezultatul cel mai prost pentru celălalt jucător. Vom nota jucătorii prin 0 şi 1 şi putem calcula valoarea optimă pentru $R$ astfel:\r\n\r\n<tex> $R[J, n_0, n_1, n_{2A}, n_{2B}, n_3, n_4] = 2 - \\min\\{R[\\(1 - J\\), n_0\', n_1\', n_{2A}\', n_{2B}\', n_3\', n_4\'] \\}$</tex> dacă $(n\'{~0~}, n\'{~1~}, n\'{~2A~}, n\'{~2B~}, n\'{~3~}, n\'{~4~})$ reprezintă o stare accesibilă din starea curentă printr-o singură mutare. Observăm că rezultatul este cu atât mai bun pentru unul dintre jucători cu cât este mai prost pentru celălalt, deci rezultatele sunt invers proporţionale, $2$ pentru $J$ reprezentănd $0$ pentru jucătorul $1 - J$. Fiecare jucător alege mutarea care îi va obţine rezultatul maxim, acesta fiind corespunzător rezultatului defavorabil (de valoare minimă) pentru celălalt.\r\n\r\nStările pentru care nu mai există decât grămezi de tipuri $2A$ şi $2B$ sunt, conform enunţului, stări finale. \r\n<tex> $R[J, 0, 0, n_{2A}, n_{2B}, 0, 0] = \\left\\{ \r\n\\begin{array}{l l}\r\n  0 & \\quad J = 0, n_{2A} < n_{2B}\\\\\r\n  0 & \\quad J = 1, n_{2A} > n_{2B}\\\\ \r\n  1 & \\quad n_{2A} = n_{2B}\\\\\r\n  2 & \\quad J = 0, n_{2A} > n_{2B}\\\\ \r\n  2 & \\quad J = 1, n_{2A} < n_{2B}\\\\\r\n\\end{array} \\right. $</tex>\r\n\r\nNotând cu $S$ tuplul distribuţiei bilelor în grămezi $(J, n{~0~}, n{~1~}, n{~2A~}, n{~2B~}, n{~3~}, n{~4~})$ atunci vom folosi o notaţie echivalentă dar mai scurtă, $R[J, S]$. Vom iniţializa toate valorile din acest tablou multidimensional la -1 şi apoi vom calcula recursiv valorile, obţinând o complexitate polinomială prin memoizare.\r\n\r\n== code(cpp)  |\r\ncalculR(J, S)\r\n  dacă R[J, S] != -1 atunci\r\n    returnează R[J, S];\r\n  dacă S e stare finală\r\n    returnează 0, 1 sau 2 în funcţie de câştigător;\r\n\r\n  R[J, S] = 0;\r\n  pentru toate stările S\' în care se poate ajunge din S printr-o mutare\r\n    R[J, S] = max(R[J, S], 2 - calculR(1 - J, S\'));\r\n  sfârşit pentru;\r\n  returnează R[J, S];\r\n==\r\n\r\nLa prima vedere, numărul stărilor este $2 * (2N)^6^ = 2*60^6^ = 93,312 * 10^9^$, deci numărul stărilor este prea mare pentru a intra în limite rezonabile de spaţiu şi timp. Observăm totuşi că toate stările îndeplinesc condiţia $n{~0~} + n{~1~} + n{~2A~} + n{~2B~} + n{~3~} + n{~4~} = N$. Numărul total al stărilor este numărul tuplurilor care îndeplinesc egalitatea şi condiţiile $n{~k~} ≥ 0$. Vom numerota cele 6 tipuri de grămezi prin numere de la 0 la 5. Vom calcula valorile $S[g, b, v]$ care reprezintă numărul de variante de a grupa $b$ bile în $g$ grămezi, astfel încât cea mai mică grămadă să aibă cel puţin mărimea tipului de indice $0 ≤ v ≤ 5$. Notăm cu $D$ şirul dimensiunilor tipurilor, $(0, 1, 2, 2, 3, 4)$ şi observăm că o stare descrisă prin $(g, b, v)$ ori are o grămadă de dimensiune $D{~v~}$ ori toate grămezile sunt mai mari decât această dimensiune. Atunci recurenţa de calcul pentru $S$ este: $S[g, b, v] = S[g, b, v + 1] + S[g - 1, b - D{~v~}, v]$ cu cazul particular $S[0, 0, 5] = 1$. Numărul total de stări este valoarea $S[N, 2*N, 0]$. Pentru valoarea maximă a lui $N$ din enunţ, am obţinut $S[30, 60, 0] = 8266$.\r\n\r\n\r\nTo be continued ... \r\n\r\n',2996,'public',NULL,NULL),('newsletter/dot-com-2009-1','Winter Challenge 2009, Runda 1','2009-11-09 16:18:48','2009-11-09 17:44:36','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nIata ca vacanta de vara s-a terminat si o buna parte din toamna a trecut si ea. Infoarena da startul unor noi serii de concursuri ce iti vor reda apetitul pentru informatica.\r\n\r\nTe invitam sa participi la un nou concurs Winter Challenge.\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Prima runda se desfasoara\r\n*Duminica, 15 Noiembrie, orele 10^00^ - 15^00^*. |\r\n\r\nVezi \'pagina concursului\':winter-challenge-2009 ca sa afli cum poti participa.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"winter-challenge-2009/runda-1\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre Winter Challenge\r\n\r\nConcursul are o singura grupa valorica dar cele 4 probleme propuse au dificultati variind intre gimnaziu si liceu clasele 11-12.\r\n\r\nOrganizatorii concursului sunt:\r\n\r\n* \'Stan Serban Andrei\':utilizator/savim\r\n* \'Cezar Mocan\':utilizator/cezarmocan\r\n* \'Radu Zernoveanu\':utilizator/raduzer\r\n* \'Teodor Anton Pripoae\':utilizator/toni2007\r\n* \'Mihai Gheorghe\':utilizator/gheorghemihai\r\n\r\nh2{font-size: 12pt}. Algoritmiada 2010\r\n\r\nAntreneaza-te cat mai este timp pentru ca in curand incepe Algoritmiada 2010.\r\n\r\nPentru mai multe detalii intra pe \'pagina concursului\':algoritmiada-2010\r\n\r\nh2{font-size: 12pt}. O noua conducere\r\n\r\nA sosit si acest moment. Veteranii echipei infoarena au predat stafeta conducerii generatiei mai tinere. Sa speram ca ne vom putea ridica la asteptarile comunitatii si vom fi cel putin la fel de buni ca cei dinaintea noastra.\r\n\r\nCititi mai multe despre asta pe \'blog\':blog/conducere-noua\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==',1490,'public',NULL,NULL),('planificare/sedinta-20091103','Ședință 2009-11-03','2009-11-02 16:31:40','2009-11-06 00:42:44','h1. Şedinţă 2009-11-03\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Marti* la ora *18^00^* la ICHB.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"pauldb\" type=\"tiny\")== \r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== (ajung la 18:20)\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20091023 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| Algoritmiada 2010 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Evaluator nou | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Sala sedinta | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n* Algoritmiada 2010:\r\n** Contractul de sponsorizare \r\n** Proiecte de finantari\r\n** Comisie?\r\n** Mapa\r\n** Alti sponsori?\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* **Cosmin si Paul** reorganizeaza mapa si **Vali** face design.\r\n* **Cosmin** vorbeste cu Cristi despre carduri la banca.\r\n* **Cosmin** scrie newsletter.\r\n* **Vali** face testing pe masina virtuala.\r\n* **Cosmin** vorbeste cu Cristina despre comunicat de presa.\r\n* **Vali** vorbeste cu Vlad Posea despre jailrun java.\r\n* **Bogdan** scrie retry loop pentru eval. %{color:red}(done)%\r\n* **Bogdan** scrie IAP pentru tagging.\r\n* **Bogdan** deschide thread cu poll pe forum sa stabilim urmatorul coding camp.\r\n* **Paul** pune pe grup linkurile de la proiectele de finantare guvernamentale. %{color:red}(done)%\r\n* **Cosmin, Paul si Prostu** se ocupa de proiectele de finantare.\r\n* **Cosmin** vorbeste cu Mircea, Cristi, Silviu si Cosmin sa bage spam la studenti cu Algoritmiada.\r\n* **Se scrie** text pentru poster si spam pe forumuri.\r\n* **Paul** lanseaza Algorimiada 2010. %{color:red}(done)%\r\n* **Prostu** vorbeste la Unibuc despre sala.\r\n\r\nh2(#notite). Notite\r\n\r\n* **Cosmin** deconteaza mancare pentru sedinta asta.\r\n',1792,'protected',NULL,NULL),('coduri-gray','Coduri Gray','2008-02-23 08:00:17','2009-02-20 00:21:05','h1. Coduri Gray\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"alecman\") ==\r\n\r\n(Categoria _Matematica_, Autor _Cosmin Negruseri_)\r\n\r\n(toc){width: 20em}*{text-align:center} *Cuprins*\r\n* \'Introducere\':coduri-gray#introducere\r\n* \'Problema 1: Turnurile din Hanoi\':coduri-gray#hanoi\r\n* \'Problema 2: Becuri\':coduri-gray#becuri\r\n* \'Problema 3: Matrix\':coduri-gray#matrix\r\n* \'Problema 4: Divizori\':coduri-gray#divizori\r\n* \'Problema 5: Sortnet\':coduri-gray#sortnet\r\n* \'Bibliografie\':coduri-gray#biblio\r\n\r\nh2(#introducere). Introducere\r\n\r\nUn cod Gray de ordin $n$ este un sir care contine toate numerele de la $0$ la $2^n-1^$, astfel incat orice doua numere consecutive din sir sa difere in reprezentarea lor binara prin exact un bit. Exista mai multe coduri Gray distincte, cel mai des intalnit fiind asa-numitul **\"binary reflected Gray code\"** (in continuare cand vom vorbi despre codul Gray ne vom referi de fapt la acest cod). Modul de constructie este destul de intuitiv: fiecare numar nou este format din cel anterior prin modificarea celui mai putin semnificativ bit, astfel incat numarul sa nu mai fi fost adaugat inainte la sir (de exemplu, pentru $n = 2$ si primul numar $0$, sirul obtinut va fi $0, 1, 3, 2$).\r\n\r\nIn continuare vom nota acest cod cu $G{~n~}$. Putem da astfel o noua metoda de constructie. Fie $G\'{~n-1~}$ sirul $G{~n-1~}$ inversat, atunci obtinem $G{~n~}$ daca punem cate un bit $0$ in fata fiecarui numar din $G{~n-1~}$, urmat de numerele din $G\'{~n-1~}$, carora le adaugam cate un $1$ ca bit semnificativ ( pe scurt $G{~n~} = 0G{~n-1~},1G\'{~n-1~} (1)$). Se poate observa ca acest cod este circular, diferenta intre ultimul si primul numar fiind de exact un bit. De asemenea, orice cod de ordin $n$ il contine pe cel de $n-1$ ca prefix, deci am putea nota prin $G{~&infin;~}$ sirul numerelor naturale in care orice doua numere consecutive difera in reprezentarea binara prin exact un bit si pentru care sirul primelor $2^n^$ elemente coincide cu $G{~n~}$ (&forall; $n$ &isin; _**N**_). \r\n\r\nFie $g(x)$ al $x$-lea numar din $G{~&infin;~}$ si $g-1(y)$ pozitia la care apare numarul $y$ in sirul $G{~&infin;~}$. Se pune problema calcularii eficiente a celor doua functii. Se poate demonstra prin inductie ca daca avem un numar $x$ cu reprezentarea binara $(...a{~2~}a{~1~}a{~0~}){~2~}$ si codul lui Gray $(...b{~2~}b{~1~}b{~0~}){~2~}$, atunci avem $b{~i~} = a{~i~} ^&and;^ a{~i+1~}$ (2). De exemplu, pentru numarul $6$ cu reprezentarea binara $110$, atunci $g(110) = 101$. De aici se deduce ca $g(i) = x ^&and;^ (x / 2)$. Din (2) obtinem ca $b{~i~} ^&and;^ b{~i+1~} ^&and;^ b{~i+2~} ^&and;^ ... = (a{~i~} ^&and;^ a{~i+1~}) ^&and;^ (a{~i+1~} ^&and;^ a{~i+2~}) ^&and;^ (a{~i+2~} ^&and;^ a{~i+3~}) ^&and;^ ... = a{~i~}$. Suma este finita deoarece va exista un $b{~i~}$ egal cu $0$ si un $a{~i~}$ egal cu $0$ (daca $i$ este indeajuns de mare). Rezulta astfel ca $g-1(y) = y ^&and;^ y/2 ^&and;^ y/4 ^&and;^ ...$\r\n\r\nDin cele de mai sus obtinem urmatoarele metode:\r\n\r\n== code(cpp) |\r\nint binToGray(int x) {\r\n    return x ^ (x >> 1);\r\n}\r\n==\r\n\r\n== code(cpp) |\r\nint grayToBin(int y) {\r\n    int ret = 0;\r\n    while (y > 0) {\r\n        ret ^= y;\r\n        y >>= 1;\r\n    }\r\n    return ret;     \r\n}\r\n==\r\n\r\nh2(#hanoi). Problema 1: _Turnurile din Hanoi_\r\n\r\nAvem trei tije si $n$ discuri de dimensiuni diferite plasate in ordinea descrescatoare a dimensiunilor pe prima tija. Se doreste mutarea tuturor discurilor pe cea de a doua tija, singurul tip de miscare posibila fiind mutarea unui disc de pe o tija pe alta, cu conditia ca pe tija destinatie discul din varf (daca exista un asemenea disc) sa fie mai mare decat discul pe care il mutam acum.\r\n\r\nh3. Rezolvare\r\n\r\nAceasta este o problema clasica in predarea recursivitatii, dar ea are o solutie care se foloseste de codul Gray. Urmarim la fiecare pas ce bit se schimba de la numerele consecutive ale lui $G{~n~}$ - acest bit corespunde discului pe care il vom muta (cel mai putin semnificativ bit corespunde celui mai mic disc etc). Problema este ca nu stim pe ce tija trebuie sa mutam discul respectiv. Exista o regula simpla care ne poate ajuta: un disc nu trebuie plasat pe alt disc cu aceeasi paritate. Folosind aceasta strategie, putem rezolva problema in numar minim de pasi ( $2^n^ - 1$ ).\r\n\r\nh2(#becuri). Problema 2: _Becuri_\r\n\r\nUn bec este conectat la $n$ intrerupatoare. Fiecarui astfel de intrerupator ii poate fi schimbata starea prin apasare. Problema este ca nu stim starea lor initiala. Se cere sa se determine o strategie care ar face numar minim de apasari in cazul cel mai defavorabil, pentru a aprinde becul.\r\n\r\nh3. Rezolvare\r\n\r\nPentru a fi siguri ca aprindem becul trebuie in cel mai rau caz sa trecem prin toate configuratiile apasat/ne-apasat ale intrerupatoarelor. Pentru a schimba starea curenta trebuie sa apasam cel putin un buton, deci in cazul cel mai defavorabil va trebui sa facem cel putin $2^n^ - 1$ apasari. Codul Gray ne da o posibilitate de a trece prin toate configuratiile trecand de la una la alta prin o apasare de buton, rezolvandu-ne problema.\r\n\r\nh2(#matrix). Problema 3: \'_Matrix_\':http://acm.sgu.ru/problem.php?contest=0&problem=249 (SGU)\r\n\r\nTrebuie sa aranjati numerele de la $0$ la $2^(n + m)^ - 1$ intr-o matrice cu $2^n^$ randuri si $2^m^$ coloane. De asemenea, numerele care sunt situate in celule adiacente pe verticala sau orizontala trebuie sa difere prin exact un bit in reprezentarea lor binara. Matricea este ciclica, adica pentru fiecare rand celula cea mai din stanga se considera invecinata cu cea mai din dreapta, de asemenea pentru fiecare coloana celula cea mai de sus se considera invecinata cu celula cea mai de jos. La intrare se dau numerele $n$ si $m$ ( $0 < n, m; n + m <= 20$ ). Trebuie sa afisati o asemenea matrice. De exemplu daca $n = 1$ si $m = 1$ o matrice ar fi\r\n( $0$ $2$ )\r\n( $1$ $3$ )\r\n\r\nh3. Rezolvare\r\n\r\nO prima metoda ar fi de a determina codului $G{~n+m~}$, iar apoi de a-l scrie serpuit in matrice (liniile de index par de la stanga la dreapta, cele de index impar in sens invers).\r\n\r\nDe exemplu, daca $n = 2$ si $m = 2$ avem:\r\n$G{~4~} = {0000, 0001, 0011, 0010, 0110, 0111, 0101, 0100, 1100, 1101, 1111, 1110, 1010, 1011, 1001, 1000}$\r\n\r\n| 0000 | 0001 | 0011 | 0010 |\r\n| 0100 | 0101 | 0111 | 0110 |\r\n| 1100 | 1101 | 1111 | 1110 |\r\n| 1000 | 1001 | 1011 | 1010 |\r\n\r\nAlta modalitate de rezolvare care ne da de fapt aceeasi matrice este urmatoarea: in celula $(i,j)$ vom avea rezultatul concatenarii reprezentarilor binare ale lui $i$ (din codul $G{~n~}$) si $j$ (din codul $G{~m~}$).\r\n\r\nDe exemplu, matricea pentru $n = 3$ si $m = 2$ este:\r\n\r\n|_. - |_. 00 |_. 01 |_. 11 |_. 10 |\r\n|_. 000 | 00000 | 00001 | 00011 | 00010 |\r\n|_. 001 | 00100 | 00101 | 00111	| 00110 |\r\n|_. 011 | 01100 | 01101 | 01111 | 01110 |\r\n|_. 010 | 01000 | 01001 | 01011 | 01010 |\r\n|_. 110 | 11000 | 11001 | 11011 | 11010 |\r\n|_. 111 | 11100 | 11101 | 11111 | 11110 |\r\n|_. 101 | 10100 | 10101 | 10111 | 10111 |\r\n|_. 100 | 10000 | 10001 | 10011 | 10010 |\r\n\r\nEste evident ca orice doua numere adiacente in matrice sunt diferite in reprezentarea binara prin exact un bit. In concurs limita de timp era foarte stransa si trebuia folosita functia prezentata anterior. Deci pe linia $i$, coloana $j$ a matricei scriem numarul (binToGray(i) << M) | binToGray(j).\r\n\r\nh2(#divizori). Problema 4: \'_Divizori_\':problema/divizori\r\n\r\nVom considera un numar natural $N$. In sirul $A$ vom aseza toti divizorii lui $N (2 <= N <= 2.000.000.000)$. Se cere sa se permute elementele sirului $A$ astfel incat pentru oricare doua elemente consecutive $A[i]$ si $A[i+1]$ sa avem fie $A[i] = A[i+1] * p$, fie $A[i+1] = A[i] * p$ ( $p$ numar prim oarecare). Valoarea $p$ poate diferi de la o pereche de elemente la alta. De exemplu, pentru $N = 12$ o posibila solutie ar fi $1, 2, 3, 4, 12, 6, 3$.\r\n\r\nh3. Rezolvare\r\n\r\nNumarul $N$ are maxim $2*N^1/2^$ divizori. Descompunerea lui $N$ in factori primi are forma $P{~1~}^E{~1~}^ * P{~2~}^E{~2~}^ * ... * P{~k~}^E{~k~}^$ ( $P{~1~}, P{~2~}, ..., P{~k~}$ - numere prime, si $E{~i~} &isin; _**N**_, E{~i~} &gt; 0$ ). Un divizor al lui $N$ va fi reprezentat printr-un vector de exponenti $(e{~1~}, e{~2~}, ..., e{~k~})$ unde $0<=e{~i~}<=E{~k~}$. Prin urmare, problema noastra poate fi usor redusa la urmatoarea cerinta: ordonati toti vectorii $(e{~1~}, e{~2~}, ..., e{~k~})$ intr-un sir cu proprietatea ca diferenta intre doi vectori consecutivi se realizeaza la o singura pozitie a vectorilor si cele doua elemente ale vectorilor de pe pozitia respectiva difera prin o unitate.\r\nExemplul din enuntul problemei se poate reprezenta astfel:\r\n$1, 2, 4, 12, 6, 3$\r\n$P{~1~} = 2 E{~1~} = 2$\r\n$P{~2~} = 3 E{~2~} = 1$\r\n$(0,0), (1,0), (2,0), (2,1), (1,1), (0,1)$\r\n\r\nAceasta problema este o generalizare a determinarii codului Gray si poate fi rezolvata generalizand metoda expusa mai sus. Presupunem ca stim sa generam o solutie pentru $M = N/(P{~k~}E{~k~})$ (o solutie pentru un numar cu $k-1$ factori primi). Sa vedem cum generam o solutie pentru $N$. Fie $C$ vectorul solutie pentru $M$ si $R$ vectorul $C$ inversat. O solutie poate fi:\r\n$C, P{~k~}*R, P{~k~}^2^*C, P{~k~}^3^*R ...$\r\nAstfel am concatenat $E{~k~}$ coduri pentru $M$, inmultind cu $P{~k~}$ si pe fiecare pozitie impara am pus secventa inversata pentru $M$. Am facut aceasta pentru ca cele doua capete ce vor ajunge in codul final consecutive sa difere numai prin $P{~k~}$.\r\n\r\nExemplu: $E{~1~} = 3; E{~2~} = 2; E{~3~} = 1$\r\n$(0,0,0) (1,0,0) (2,0,0) (3,0,0)$ - Solutia pentru un factor prim.\r\n$(0,0,0) (1,0,0) (2,0,0) (3,0,0) (3,1,0) (2,1,0) (1,1,0) (0,1,0) (0,2,0) (1,2,0) (2,2,0) (3,2,0)$ - Solutia pentru doi factori primi.\r\n$(0,0,0) (1,0,0) (2,0,0) (3,0,0) (3,1,0) (2,1,0) (1,1,0) (0,1,0) (0,2,0) (1,2,0) (2,2,0) (3,2,0)$\r\n$(3,2,1) (2,2,1) (1,2,1) (0,2,1) (0,1,1) (1,1,1) (2,1,1) (3,1,1) (3,0,1) (2,0,1) (1,0,1) (0,0,1)$ - Solutia pentru cei trei factori primi.\r\n\r\nComplexitatea finala a solutiei este $O(T)$ unde $T$ reprezinta numarul de divizori ai lui $N$.\r\n\r\nh2(#sortnet). Problema 5: \'_Sortnet_\':problema/sortnet (Lot 2002)\r\n\r\nO retea completa de sortare este o retea de sortare cu $N$ fire de adancime $D$ ce are $D * (N/2)$ comparatori. Amintim principiul $0-1$ care spune ca o retea de sortare sorteaza orice $N$ numere daca aceasta sorteaza orice secventa de $N$ numere $0-1$. Problema noastra cere sa se determine cate astfel de secvente de $0-1$ nu sunt sortate corect.\r\n\r\nh3. Rezolvarea lui Mihai Patrascu\r\n\r\nObservam ca dupa primul strat de comparatori sunt exact $3^(N/2)^$ rezultate posibile, pentru ca intrarile trecute printr-un comparator se transforma astfel:\r\n\r\n| (0,0) -> (0,0) | (0,1) -> (1,0) | (1,0) -> (1,0) | (1,1) -> (1,1) |\r\n\r\nPentru a testa fiecare astfel de rezultat daca e sortat sau nu de urmatoarele $D-1$ straturi, nu vor trebui simulate toate in complexitate $O(N * 3^N/2^ * D)$. Prin generarea secventelor conform codului Gray in baza 3 putem doar sa urmarim modificarea rezultatului pentru doua rezultate succesive in $O(D)$. Un numar in baza trei il transformam in baza doi cu numar dublu de cifre, astfel:\r\n\r\n| 0 -> 00 | 1 -> 10 | 2 - > 11 |\r\n\r\nacest cod reprezentand un rezultat posibil dupa evaluarea unei secvente binare de catre primul strat al retelei. Modificarea unei cifre in baza trei conform codului Gray generalizat pentru numere in aceasta baza, duce la modificarea unei cifre in codul binar a unui bit. Urmarirea modificarilor facute de acest bit schimbat in evaluarile facute de reteaua de sortare o putem face in complexitate $O(D)$. Astfel complexitatea finala este $O(3^N/2^ * D)$.\r\n\r\nMentionam ca problema este pe site-ul InfoArena (\'Sortnet\':problema/sortnet) si acolo o rezolvare $O(2^N^ * D)$ intra in timp, dar si pentru aceasta trebuie sa folosim codul Gray si sa urmarim modificarile date de schimbarea unui bit in evaluare. Dam mai jos rezolvarea eleganta si usor de inteles a lui Mircea Pasoi:\r\n\r\n== code(cpp) |\r\n#include <stdio.h>\r\n\r\nint N, M, G[ 33 ][ 20 ], V[ 33 ], V2[ 33 ], Res;\r\n\r\ninline int GRAY(int x)\r\n{\r\n    return x ^ ( x >> 1 );\r\n}\r\n\r\ninline int BIT(int a, int b)\r\n{\r\n    return (a & (1 << b)) > 0;\r\n}\r\n\r\ninline int MIN(int a, int b)\r\n{\r\n    return (a < b) ? a : b;\r\n}\r\n\r\ninline int MAX(int a, int b)\r\n{\r\n    return (a > b) ? a : b;\r\n}\r\n\r\ninline int SORTED(int x)\r\n{\r\n    return (x & (x+1)) == 0;\r\n}\r\n\r\nint works(int n, int a)\r\n{\r\n    int i, b, t;\r\n\r\n    V2[0] = n;\r\n    for (i = 0; i < M; i++)\r\n    {\r\n        b = G[i][a];\r\n        if ((BIT(V[i], MAX(a, b)) && !BIT(V[i], MIN(a, b))) ||\r\n            (BIT(V2[i], MAX(a, b)) && !BIT(V2[i], MIN(a, b))))\r\n            a = b;\r\n        V[i] = V2[i];\r\n        V2[i+1] = V[i+1]^(1<<a);\r\n    }\r\n    V[M] = V2[M];\r\n\r\n    return SORTED(V[M]);\r\n}\r\n\r\nint main(void)\r\n{\r\n    int i, j, k, a, b, bit;\r\n\r\n    freopen(\"sortnet.in\", \"r\", stdin);\r\n    freopen(\"sortnet.out\", \"w\", stdout);\r\n\r\n    scanf(\"%d %d\\n\", &N, &M);\r\n    for (i = 0; i < M; i++)\r\n        for (j = 0; j < N/2; j++)\r\n        {\r\n            scanf(\"<%d,%d> \", &a, &b);\r\n            a--; b--;\r\n            G[i][a] = b; G[i][b] = a;\r\n        }\r\n\r\n    Res = 1;\r\n    for (i = 1; i < (1 << N); i++) \r\n    {\r\n        k = GRAY(i) ^ GRAY(i-1);\r\n        for (bit = 0; (1<<bit) < k; bit++);\r\n        Res += works(GRAY(i), bit);\r\n    }\r\n    printf(\"%d\\n\", Res);\r\n\r\n    return 0;\r\n}\r\n==\r\n\r\nh2(#biblio). Bibliografie\r\n\r\n# D.E.Knuth TAOC Prefascicle 2A\r\n# W.H. Press et. all. Numerical Recipies in C, Cambridge University Press\r\n# \'Gray code, wikipedia\':http://en.wikipedia.org/wiki/Gray_code\r\n',2044,'public',3686,NULL),('dot-com/2009/clasament','Clasament .com 2009','2009-11-09 15:44:14','2009-11-09 21:21:50','h1. Clasament \'.com 2009\':dot-com/2009\r\n\r\n(htabs)* \'Detalii\':dot-com/2009\r\n* \'Runda 1\':dot-com/2009/runda-1\r\n* \'Runda 2\':dot-com/2009/runda-2\r\n*(active) \'Clasament\':dot-com/2009/clasament\r\n\r\nAcesta este clasamentul cumulat pentru cele 2 runde online.\r\n\r\n== Rankings(rounds=\"winter2009-runda1 | winter2009-runda2\") ==',1490,'public',NULL,NULL),('dot-com/2009/solutii/runda-1','Solutii .com 2009, Runda 1','2009-11-15 11:46:12','2009-11-15 12:39:11','h1. Solutii .com 2009, Runda 1\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Tabara2\':dot-com/2009/solutii/runda-1#tabara2\r\n* \'Floare\':dot-com/2009/solutii/runda-1#floare\r\n* \'Galerie\':dot-com/2009/solutii/runda-1#galerie\r\n* \'Trilant\':dot-com/2009/solutii/runda-1#trilant\r\n\r\n==include(page=\"dot-com/2009/solutii/runda-1/tabara2\")==\r\n\r\n==include(page=\"dot-com/2009/solutii/runda-1/floare\")==\r\n\r\n==include(page=\"dot-com/2009/solutii/runda-1/galerie\")==\r\n\r\nSolutia 1 : Teodor Anton Pripoae\r\n\r\nPentru inceput, vom observa ca nu conteaza cate cartite sunt initial intr-o camera. \r\n\r\nVom calcula pentru fiecare intrebare a organizatorilor, cate drumuri ale cartitelor contin acel interval (sa zicem Nr). Costul imbunatatirii va fi Nr * (lungime_interval - cost_interval). Pe exemplul din enunt unde merg 2 cartite intre camerele 1 si 4, vor exista 2 drumuri care contin intervalul [1, 3] : Drumul facut de prima cartita, respectiv a doua cartita din camera 1 pana in camera 4.\r\n\r\nAcum, trebuie sa vedem cum putem raspunde eficient la intrebarea: Cate drumuri contin un interval cautat de organizatori. Vom retine intervalele ca puncte in plan (atat drumurile cat si intrebarile), coordonata x va fi capatul din stanga, iar coordonata y capatul din dreapta. Pentru ca un interval sa fie cuprins de altul, trebuie ca primul punct sa fie in stanga si deasupra celul de-al doilea. Vom sorta crescator toate cele M + T puncte dupa coordonata x si in caz de egalitate descrescator dupa coordonata y. Acum, pt fiecare punct (interval) cautat, raspunsul va fi numarul de coordonata y aflate inaintea lui in vector si mai mari decat el. \r\n\r\nVom tine un aib (Arbore indexat binar). La pasul i, vom vedea daca punctul curent este din cele M, caz in care vom updata pe pozitia respectiva in aib numarul de cartite care trec pe acel interval, sau in caz ca este din cele T vom vedea in aib cate elemente sunt mai mari ca el.\r\n\r\nSolutia are complexitate o((M + T) (log (M + T) + log N)) ca timp si o(N) ca memorie.\r\n\r\n\r\n==include(page=\"dot-com/2009/solutii/runda-1/trilant\")==\r\n',6061,'public',NULL,NULL),('dot-com/2009/solutii/runda-1','Solutii .com 2009, Runda 1','2009-11-15 11:46:12','2009-11-15 12:45:42','h1. Solutii .com 2009, Runda 1\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Tabara2\':dot-com/2009/solutii/runda-1#tabara2\r\n* \'Floare\':dot-com/2009/solutii/runda-1#floare\r\n* \'Galerie\':dot-com/2009/solutii/runda-1#galerie\r\n* \'Trilant\':dot-com/2009/solutii/runda-1#trilant\r\n\r\n==include(page=\"dot-com/2009/solutii/runda-1/tabara2\")==\r\n\r\n==include(page=\"dot-com/2009/solutii/runda-1/floare\")==\r\n\r\n==include(page=\"dot-com/2009/solutii/runda-1/galerie\")==\r\n\r\n**Solutia 1 : Teodor Anton Pripoae**\r\n\r\nPentru inceput, vom observa ca nu conteaza cate cartite sunt initial intr-o camera. \r\n\r\nVom calcula pentru fiecare intrebare a organizatorilor, cate drumuri ale cartitelor contin acel interval (sa zicem Nr). Costul imbunatatirii va fi Nr * (lungime_interval - cost_interval). Pe exemplul din enunt unde merg 2 cartite intre camerele 1 si 4, vor exista 2 drumuri care contin intervalul [1, 3] : Drumul facut de prima cartita, respectiv a doua cartita din camera 1 pana in camera 4.\r\n\r\nAcum, trebuie sa vedem cum putem raspunde eficient la intrebarea: Cate drumuri contin un interval cautat de organizatori. Vom retine intervalele ca puncte in plan (atat drumurile cat si intrebarile), coordonata x va fi capatul din stanga, iar coordonata y capatul din dreapta. Pentru ca un interval sa fie cuprins de altul, trebuie ca primul punct sa fie in stanga si deasupra celul de-al doilea. Vom sorta crescator toate cele M + T puncte dupa coordonata x si in caz de egalitate descrescator dupa coordonata y. Acum, pt fiecare punct (interval) cautat, raspunsul va fi numarul de puncte cu aflate inaintea lui in vector care au coordonata y mai mare decat a lui. \r\n\r\nVom proceda ca la subsir descrescator maximal. Vom tine un aib (Arbore indexat binar). La pasul i, vom vedea daca punctul curent(P) este din cele M, caz in care vom updata pe pozitia corespunzatoare coordonatei P.y in aib numarul de cartite care trec pe acel interval, sau in caz ca este din cele T vom vedea cu ajutorul aib-ului cate drumuri a caror coordonate R.y sunt mai mari decat coordonata P.y a lui: scadem din suma totala, suma pozitiilor pana la P.y - 1.\r\n\r\nSolutia are complexitate o((M + T) (log (M + T) + log N)) ca timp si o(N) ca memorie.\r\n\r\n\r\n==include(page=\"dot-com/2009/solutii/runda-1/trilant\")==\r\n',6061,'public',NULL,NULL),('dot-com/2009/solutii/runda-1/floare','dot-com/2009/solutii/runda-1/floare','2009-11-15 11:47:13','2009-11-15 17:00:33','h1(#floare). \'Floare\':problema/floare\r\n\r\nVom construi sirul $D$~i~, cu semnificatia $a cata dintre jucatoare (considerand ca jucatoarea 1 muta prima) va castiga jocul pentru o floare cu $i$ petale$. Observam ca dintr-o stare cu $i$ petale putem ajunge in oricare dintre starile $i-1$, $i-2$, ... $i-K$, luand $1$, $2$... $K$ din petalele florii. Fata $1$ va alege starea din care poate sa castige cat mai multi trandafiri, adica $A[M - D[j]]$ sa fie maxim, $i-K &le; j &le; i-1$. \r\nPentru 30 de puncte se recurenta se rezolva direct, iar pentru 100 de puncte se foloseste un deque.\r\n',1430,'public',NULL,NULL),('algoritmiada-2010/runda-1','Algoritmiada 2010 - Runda 1','2009-10-25 16:37:51','2009-10-25 18:23:55','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Algoritmiada 2010, Runda 1\r\n\r\n(htabs)*(active) \'Despre...\':algoritmiada-2010/runda-1 \r\n* \'Clasele 5-8\':algoritmiada-2010/runda-1/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-1/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-1/5-8 \r\n\r\nRunda va incepe *Duminica 22 noiembrie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-1/studenti\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':algoritmiada-2010/runda-1/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-1/studenti\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* &hellip;\r\n\r\nPentru intrebari de factura organizatorica sau tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',1490,'protected',NULL,NULL),('newsletter/algoritmiada-2010-1','Algoritmiada revine! Participă și tu!','2009-11-15 22:24:10','2009-11-15 23:55:07','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎncepe o nouă ediţie a concursului Algoritmiada, cel mai mare şi mai important concurs organizat de infoarena!\r\n\r\nLa Algoritmiada participă elevi de gimnaziu, elevi de liceu, *dar şi studenţi,* şi chiar masteranzi sau doctoranzi! (Avem grupe separate pentru fiecare.)\r\n\r\nAlgoritmiada se desfăşoară în 5 runde: 4 runde online de calificare şi o rundă finală on-site la care invităm concurenţii cu cele mai bune punctaje de la fiecare grupă. Cei mai buni vor câştiga premii serioase, în bani şi obiecte. Acest concurs îţi oferă şansa să cunoşti experţi în domeniu de a căror experienţă vastă poţi profita!\r\n\r\nRunda 1 se desfăşoară în acest weekend. Te aşteptăm în arenă! Dovedeşte-ţi talentul şi cunoştinţele la Algoritmiada.\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Prima rundă se desfăşoară\r\n*Duminică, 22 Decembrie 2009, orele 09^00^ - 13^00^*. |\r\n\r\nVezi \'pagina concursului\':algoritmiada-2010 ca să afli cum poţi participa.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"algoritmiada-2010/runda-1\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre Algoritmiada\r\n\r\nAlgoritmiada este unicul concurs din România unde pot participa tinerii pasionaţi de informatică de toate vârstele: de la elevi de gimnaziu până la studenţi şi doctoranzi.\r\n\r\nConcursul are patru grupe valorice: gimnaziu, clasele 9-10, clasele 11-12, studenţi (inclusiv masteranzi şi doctoranzi). Participanţii vor avea ocazia să-şi demonstreze talentul, cunostinţele şi ascuţimea minţii în 4 probe online urmând ca cei mai buni sa fie invitaţi la finala on-site.\r\n\r\nSubiectele vor fi propuse de către o echipă de foşti şi actuali olimpici la informatică: Cosmin Gheorghe, Bogdan Tătăroiu, Paul Băltescu, Filip Ştefan, Marius Stroe, Adrian Airinei, Andrei Grigorean, Ştefan Istrate, Adrian Diaconu şi Filip Buruiană. De ce ei? Intră pe \'pagina rundei\':algoritmiada-2010/runda-1 şi citeşte câte ceva despre experienţa fiecăruia.\r\n\r\nÎn fiecare rundă vei avea la dispoziţie 4h să rezolvi 3 probleme de natură algoritmică. Concurenţii sunt împărţiţi în 4 grupe de vârstă: gimnaziu, clasele 9-10, clasele 11-12 şi studenţi (inclusiv masteranzi si doctoranzi).\r\n\r\nIntră pe \'pagina concursului\':algoritmiada-2010 ca să afli mai multe informaţii.\r\n\r\nIţi urăm succes şi te asteptăm în arenă!\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==',1792,'protected',NULL,NULL),('newsletter/algoritmiada-2010-1','Algoritmiada revine! Participă și tu!','2009-11-15 22:24:10','2009-11-16 00:29:41','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎncepe o nouă ediţie a concursului Algoritmiada, cel mai mare şi mai important concurs organizat de infoarena!\r\n\r\nLa Algoritmiada participă elevi de gimnaziu, elevi de liceu, *dar şi studenţi,* şi chiar masteranzi sau doctoranzi! (Avem grupe separate pentru fiecare.)\r\n\r\nAlgoritmiada se desfăşoară în 5 runde: 4 runde online de calificare şi o rundă finală on-site la care invităm concurenţii cu cele mai bune punctaje de la fiecare grupă. Cei mai buni vor câştiga premii serioase, în bani şi obiecte. Acest concurs îţi oferă şansa să cunoşti experţi în domeniu de a căror experienţă vastă poţi profita!\r\n\r\nRunda 1 are loc chiar în acest weekend şi reprezintă un ultim test pentru delegaţia României la Olimpiada Balcanică de Informatică 2009 (Bulgaria). Întrece-te cu ei! Dovedeşte-ţi talentul şi cunoştinţele la Algoritmiada!\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Prima rundă se desfăşoară\r\n*Duminică, 22 Decembrie 2009, orele 09^00^ - 13^00^*. |\r\n\r\nVezi \'pagina concursului\':algoritmiada-2010 ca să afli cum poţi participa.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"algoritmiada-2010/runda-1\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre Algoritmiada\r\n\r\nAlgoritmiada este unicul concurs din România unde pot participa tinerii pasionaţi de informatică de toate vârstele: de la elevi de gimnaziu până la studenţi şi doctoranzi.\r\n\r\nConcursul are patru grupe valorice: gimnaziu, clasele 9-10, clasele 11-12, studenţi (inclusiv masteranzi şi doctoranzi). Participanţii vor avea ocazia să-şi demonstreze talentul, cunostinţele şi ascuţimea minţii în 4 probe online urmând ca cei mai buni sa fie invitaţi la finala on-site.\r\n\r\nSubiectele vor fi propuse de către o echipă de foşti şi actuali olimpici la informatică: Cosmin Gheorghe, Bogdan Tătăroiu, Paul Băltescu, Filip Ştefan, Marius Stroe, Adrian Airinei, Andrei Grigorean, Ştefan Istrate, Adrian Diaconu şi Filip Buruiană. De ce ei? Intră pe \'pagina rundei\':algoritmiada-2010/runda-1 şi citeşte câte ceva despre experienţa fiecăruia.\r\n\r\nÎn fiecare rundă vei avea la dispoziţie 4h să rezolvi 3 probleme de natură algoritmică. Concurenţii sunt împărţiţi în 4 grupe de vârstă: gimnaziu, clasele 9-10, clasele 11-12 şi studenţi (inclusiv masteranzi si doctoranzi).\r\n\r\nIntră pe \'pagina concursului\':algoritmiada-2010 ca să afli mai multe informaţii.\r\n\r\nIţi urăm succes şi te asteptăm în arenă!\r\n\r\nh2{font-size: 12pt}. Despre BOI/JBOI 2009\r\n\r\nA XVII-a ediţie a Olimpiadei Balcanice de Informatică este găzduită de Bulgaria (în Shumen) şi se desfăşoară în perioada 27-29 noiembrie. Tot în acelaşi timp va avea loc şi cea de-a III-a ediţie a Olimpiadei Balcanice de Informatică pentru Juniori. Delegaţiile României sunt alcătuite din:\r\n\r\n* Seniori:\r\n** \'Andrei Pârvu\':utilizator/andrei.12\r\n** \'Şerban Stan\':utilizator/savim\r\n** \'Tiberiu Savin\':utilizator/devilkind\r\n** \'Florin Perţicaş\':utilizator/perticas_catalin\r\n* Juniori:\r\n** \'Vlad Găvrilă\':utilizator/GavrilaVlad\r\n** \'Radu Voroneanu\':utilizator/radu_voroneanu\r\n** \'Marius Petcu\':utilizator/marius21\r\n** \'Mihai Gheorghe\':utilizator/GheorgheMihai\r\n\r\nUrăm succes celor două delegaţii ale României! Sperăm ca reprezentanţii noştri să facă ce ştiu cel mai bine, să obţină rezultate excepţionale.\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==',1792,'protected',NULL,NULL),('dot-com/2009/solutii/runda-1/tabara2','dot-com/2009/solutii/runda-1/tabara2','2009-11-15 11:46:57','2009-11-15 11:46:57','h1(#tabara2). \'Tabara2\':problema/tabara2',1490,'public',NULL,NULL),('dot-com/2009/solutii/runda-1/trilant','dot-com/2009/solutii/runda-1/trilant','2009-11-15 11:49:09','2009-11-17 15:50:31','h1(#trilant). \'Trilant\':problema/trilant\r\n\r\nPentru doua noduri $P,Q$ din graf, vom defini $d(P,Q)$ ca fiind drumul de cost minim de la $P$ la $Q$. Pe noi ne intereseaza sa gasim un nod $X$ astfel incat suma $d(A,X)+d(B,X)+d(C,X)$ sa fie minima. Pentru a realiza acest lucru trebuie sa calculam pentru orice nod $K$ din graf $d(A,K),d(B,K) si d(C,K)$. Putem face acest lucru folsind \'Algoritmul lui Dijsktra\':/problema/dijkstra. Nodul solutie va fi acel nod $X$ cu proprietatea ca suma $d(A,X)+d(B,X)+d(C,X)$ sa fie minima.\r\n\r\nPresupunem ca am ales nodul $X$ cu proprietatea de mai sus. Daca drumurile $(X,A)$ si $(X,B)$ nu ar fi disjuncte, atunci stim sigur ca exista un nod $K$ pe lantul de la $X$ la $A$, astfel incat drumurile $(K,A)$ si $(K,B)$ sunt dijuncte. Inseamna ca pe drumul de la $K$ la $X$, vom numara muchiile care apar de doua ori, rezulta ca $X$ nu ar avea proprietatea ca suma $d(A,X)+d(B,X)+d(C,X)$ sa fie minima. Analog daca $(X,A)$ si $(X,C)$ sau $(X,B)$ si $(X,C)$ nu ar fi disjuncte.\r\n\r\nComplexitate finala va fi O(MlogN).\r\n',4827,'public',NULL,NULL),('utilizator/mathboy','Rotaru Dragos Alin','2008-12-24 18:43:37','2009-11-16 07:35:30','h2. Despre mine\r\n\r\n* Elev in clasa a X-a D, Matematica-Informatica, Informatica Intensiv la Colegiul National Unirea Focsani\r\n* Contact: dragos_mathboy@yahoo.com\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n\r\n==user(user=\"Florian\" type=\"normal\")==\r\n\r\n==user(user=\"cosmin79\" type=\"normal\")==\r\n\r\n==user(user=\"klamathix\" type=\"normal\")==\r\n\r\n==user(user=\"DraStiK\" type=\"normal\")==\r\n\r\n==user(user=\"antoanela\" type=\"normal\")==\r\n\r\n==user(user=\"Protoman\" type=\"normal\")==\r\n\r\n==user(user=\"Omega91\" type=\"normal\")==\r\n\r\n==user(user=\"lucianvn\" type=\"normal\")==\r\n\r\n==user(user=\"bogdanhm999\" type=\"normal\")==\r\n\r\n==user(user=\"drag0sh\" type=\"normal\")==\r\n\r\n==Rankings(rounds=\"arhiva\" display_entries=\"0\" first_entry=\"165\" pager_style=\"none\")==\r\n',9232,'public',NULL,NULL),('marturii','Marturiile utilizatorilor infoarena','2007-05-15 00:33:16','2009-03-27 19:10:15','h1. Marturii despre infoarena\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nDaca esti utilizator infoarena si consideri ca site-ul nostru te-a ajutat in vreun fel, te rugam sa ne scrii o marturie, similara cu cele deja existente in aceasta pagina. Ne intereseaza pareri cat mai sincere, indiferent ca sunt pozitive sau negative.\r\n\r\nClick pe _Editeaza_ ca sa adaugi marturia ta. Te rugam sa respecti stilul de formatare existent.\r\n\r\n&nbsp;\r\n\r\nbq. infoarena este un proiect remarcabil, realizat cu entuziasm, generozitate si profesionalism. Este locul in care tinerii pasionati de informatica se pot intalni, atat de o parte, cat si de cealalta parte a baricadei, ca propunatori sau ca rezolvitori de probleme, isi pot impartasi experienta competitionala, pot constitui modele, pot ajuta la formarea a noi si noi generatii de performanta. *Emanuela Cerchez*\r\n\r\n&nbsp;\r\n\r\nbq. infoarena e plin de energie, e dinamic si riguros, gratie unei echipe curajoase. Site-ul infoarena reprezinta cea mai originala forma de pregatire pe net a performerilor in informatica din Romania. Mecanism de lucru excelent, probleme propuse, fara cusur. Felicitari! *Emil Onea*\r\n\r\n&nbsp;\r\n\r\nbq. infoarena m-a adus aproape de oameni extraordinari, prieteni care m-au invatat nenumarate lucruri despre informatica, generozitate, entuziasm si dedicare. Putine lucruri sunt mai importante decat un anturaj EXEMPLAR. Intr-un fel, pot sa spun ca infoarena mi-a schimbat viata. == user(type=\"tiny\" user=\"wickedman\")==\r\n\r\n&nbsp;\r\n\r\nbq. infoarena a fost cea mai importanta sursa de probleme in pregatirea mea si a colegilor mei pentru olimpiadele nationale, dar si un mod bun de a invata cate ceva despre evaluatoarele folosite la concursuri. Pentru mine, cel putin, accesul la surse mi-a creat si o perspectiva despre modul in care se construieste o aplicatie ce ia in cosiderare toate cazurile, oricat de improbabile ar fi ele. == user(type=\"tiny\" user=\"salgau_catalin\")==\r\n\r\n&nbsp;\r\n\r\nbq. Cred ca in Romania exista poli puternici (Bucuresti, Iasi) legati de profesori valorosi si copii pasionati dar izolati. Aici intervine infoarena: cultiva spiritul competitiv din fiecare, te motiveaza, creaza comunitatea de care avem nevoie ca sa evoluam. Propune un joc in care te implici initial din curioziate, pentru a deveni in scurt timp dependent indiferent daca lucrezi pentru internationala, pentru judeteana sau ca sa obtii un rating mai bun decat vecinul de pe scara. ;) == user(type=\"tiny\" user=\"DigitAll\")==\r\n\r\n&nbsp;\r\n\r\nbq. Infoarena este un proiect foarte important in pregatirea olimpicilor romani de informatica. Nu numai ca este o sursa constanta de probleme, dar fiecare utilizator poate sa vada unde se situeaza in comparatie cu ceilalti, fiecare stie ce-i poate pielea. Sa nu mai vorbim de constantele concursuri online unde utilizatorii pot concura intre ei. Pe mine personal infoarena m-a ajutat foarte mult...  == user(type=\"tiny\" user=\"Darth_Niculus\")==\r\n&nbsp;\r\n\r\nbq. La inceput, infoarena a insemnat pentru mine un joc nascut dintr-o dorinta puternica de rascumpara macar o parte din ce am primit in postura de invatacel de la oamenii extraordinari cu care am interactionat, fie ei profesori sau prieteni. Pe parcurs a devenit concretizarea visului meu de olimpic la informatica din provincie: un site unde sa gasesti oameni la fel de pasionati de informatica ca si tine, probleme, resurse si link-uri, toate intr-un singur loc. == user(type=\"tiny\" user=\"silviug\")==\r\n\r\n&nbsp;\r\n\r\nbq. Pentru mine infoarena a insemnat practic contactul cu adevarata lume a informaticii. Pana atunci informatica pentru mine era doar o pasiune, insa de abia cand am intrat pe infoarena am realizat cat de vast este acest domeniu. Aici am invatat cam 90% din ce stiu acum, si cu siguranta mai am multe de invatat de pe acest site. In acest moment infoarena este o comunitate, o comunitate de olimpici care se ajuta intre ei, facand schimb de idei si invatand unul de la altul. == user(type=\"tiny\" user=\"devilkind\")==\r\n\r\n&nbsp;\r\n\r\nbq. Infoarena este cu adevarat un proiect de exceptie care a reusit sa se dezvolte enorm in cursul celor 3 ani de activitate. Infoarena nu este doar un loc unde te pregatesti pentru concursurile de informatica. Este un loc unde poti cunoaste persoane cu aceleasi pasiuni ca si tine, un loc in care se aduna toti cei care au spirit competitiv si doresc sa se perfectioneze in domeniul programarii. Zeci de utilizatori contribuie efectiv la dezvoltarea si imbunatatirea site-ului ca developeri, propunatori de probleme sau moderatori pe forum. Este cu adevarat o comunitate! == user(type=\"tiny\" user=\"filipb\")==\r\n\r\n&nbsp;\r\n\r\nbq. Atunci cand ma aflam la inceput de drum, infoarena a fost locul unde am intalnit ceea ce imi doream, probleme grele care sa imi dea batai ce cap, o comunitate prietenoasa care sa imi dea sfaturi, si posibilitatea de a participa la concursuri in conditii similare celor de la olimpiada. Am invatat foarte mult aici, si sper sa pot contribui si eu la dezvoltarea acestui proiect, care aduna in fiecare an tot mai multi elevi pasionati din intreaga tara. == user(type=\"tiny\" user=\"wefgef\")==\r\n\r\n&nbsp;\r\n\r\nbq. infoarena a fost comunitatea care mi-a trezit pasiunea pentru informatica. E un proiect extraordinar, prin care, nu numai ca inveti cu adevarat tainele algoritmicii si programarii, lucru care te ajuta in mod deosebit la concursuri si olimpiade, dar iti faci si foarte multi prieteni. Aici gasesti mereu oameni care sunt gata sa te ajute, sa-ti ofere informatii noi, gasesti mereu o problema interesanta in arhiva, si de asemenea, gasesti mereu o competitie (interna sau nu) la care sa poti participa on-line, comod, si care sa te ajute cu pregatirea in regim de concurs. Pe langa comunitate, arhiva si concursuri, sunt accesibile numeroase articole. Sectiunea \"Links\" si \"Downloads\" sunt si ele indispensabile vietii de programator. == user(type=\"tiny\" user=\"Florian\")==\r\n\r\n&nbsp;\r\n\r\nbq. Foarte putine lucruri m-au ajutat mai mult in viata decat participarea la concursurile nationale si internationale de informatica. De asemenea, nu multe au fost resursele prin intermediul carora am reusit sa concurez de la egal la egal cu elevii care aveau deja rezultate bune si o experienta mai mare decat a mea. infoarena e una din aceste resurse: proaspata, inedita, si propulsata de o comunitate plina de pasiune si entuziasm. Le multumesc tuturor celor care au facut ca infoarena sa devina realitate, si sper ca toti cei implicati intr-un fel sau altul in olimpiadele de informatica sa profite la maxim si sa aprecieze la randul lor acest proiect remarcabil. == user(type=\"tiny\" user=\"greco\")==\r\n\r\n&nbsp;\r\n\r\nbq. infoarena este pentru mine \"persoana\" care ma impinge de la spate sa lucrez, uneori simt ca ma pot depasi pe mine; sunt si voi fi recunoscator tuturor celor de aici care m-au ajutat si o vor face in continuare; am doar cuvinte de lauda. BRAVO == user(type=\"tiny\" user=\"DraStiK\")==\r\n\r\n&nbsp;\r\n\r\nbq. Infoarena este site-ul care te ajuta sa faci performanta deoarece problemele pot fi facute in multe moduri. Cand esti mic iei cateva puncte, dar cand vei fi mare vei gasi rezolvarea care iti va aduce punctajul maxim. Te ajuta sa tii minte cand ai folosit o metoda si cum si de aceea Infoarena este unul dintre cele mai bune site-uri de pregatire == user(type=\"tiny\" user=\"Andrici_Cezar\")==',2044,'public',NULL,NULL),('algoritmiada-2010/runda-1/solutii','Solutii Algoritmiada 2010 Runda 1','2009-10-25 16:37:52','2009-11-21 17:39:44','h1. Solutii Algoritmiada 2010, Runda 1\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Tablete\':algoritmiada-2010/runda-1/solutii#iopds\r\n* \'Densitate\':algoritmiada-2010/runda-1/solutii#perle2\r\n* \'Propozitie\':algoritmiada-2010/runda-1/solutii#studenti\r\n* \'Jstc\':algoritmiada-2010/runda-1/solutii#pitici4\r\n* \'Coprime\':algoritmiada-2010/runda-1/solutii#vrejuri\r\n* \'Scandura\':algoritmiada-2010/runda-1/solutii#arborest\r\n* \'Piese2\':algoritmiada-2010/runda-1/solutii#kss\r\n* \'Sprim\':algoritmiada-2010/runda-1/solutii#tester\r\n\r\n==include(page=\"algoritmiada-2010/runda-1/solutii/iopds\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-1/solutii/perle2\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-1/solutii/studenti\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-1/solutii/pitici4\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-1/solutii/vrejuri\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-1/solutii/arborest\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-1/solutii/kss\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-1/solutii/tester\")==',1792,'private',NULL,NULL),('algoritmiada-2010/runda-1/solutii/vrejuri','Solutie Vrejuri','2009-11-21 17:43:54','2009-11-21 17:43:54','h1. Aceasta pagina trebuie sa ramana private pana la sfarsitul rundei!',1792,'private',NULL,NULL),('algoritmiada-2010/runda-1/solutii/kss','Solutie Kss','2009-11-21 17:44:35','2009-11-21 17:44:35','h1. Aceasta pagina trebuie sa ramana private pana la sfarsitul rundei!',1792,'private',NULL,NULL),('algoritmiada-2010/runda-1/solutii/kss','Solutie Kss','2009-11-21 17:44:35','2009-11-21 17:50:37','h1(#tablete). \'Kss\':problema/kss\r\n\r\nh2. Aceasta pagina trebuie sa ramana private pana la sfarsitul rundei!',1792,'private',NULL,NULL),('algoritmiada-2010/runda-1/solutii/iopds','Solutie Iopds','2009-11-21 17:41:03','2009-11-21 17:51:37','h1(#iopds). \'Iopds\':problema/iopds\r\n\r\nh2. Aceasta pagina trebuie sa ramana private pana la sfarsitul rundei!',1792,'private',NULL,NULL);
-INSERT INTO `ia_textblock_revision` VALUES ('planificare/sedinta-20091126','Ședință 2009-11-03','2009-11-23 14:30:08','2009-11-23 14:30:08','h1. Şedinţă 2009-11-03\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Marti* la ora *18^00^* la ICHB.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"pauldb\" type=\"tiny\")== \r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== (ajung la 18:20)\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20091023 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| Algoritmiada 2010 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Evaluator nou | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Sala sedinta | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n* Algoritmiada 2010:\r\n** Contractul de sponsorizare \r\n** Proiecte de finantari\r\n** Comisie?\r\n** Mapa\r\n** Alti sponsori?\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* **Cosmin si Paul** reorganizeaza mapa si **Vali** face design.\r\n* **Cosmin** vorbeste cu Cristi despre carduri la banca. %{color:red}(done)%\r\n* **Cosmin** scrie newsletter. %{color:red}(done)%\r\n* **Vali** face testing pe masina virtuala.\r\n* **Cosmin** vorbeste cu Cristina despre comunicat de presa.\r\n* **Vali** vorbeste cu Vlad Posea despre jailrun java.\r\n* **Bogdan** scrie retry loop pentru eval. %{color:red}(done)%\r\n* **Bogdan** scrie IAP pentru tagging.\r\n* **Bogdan** deschide thread cu poll pe forum sa stabilim urmatorul coding camp.\r\n* **Paul** pune pe grup linkurile de la proiectele de finantare guvernamentale. %{color:red}(done)%\r\n* **Cosmin, Paul si Prostu** se ocupa de proiectele de finantare.\r\n* **Cosmin** vorbeste cu Mircea, Cristi, Silviu si Cosmin sa bage spam la studenti cu Algoritmiada. %{color:red}(done)%\r\n* **Se scrie** text pentru poster si spam pe forumuri.\r\n* **Paul** lanseaza Algorimiada 2010. %{color:red}(done)%\r\n* **Prostu** vorbeste la Unibuc despre sala.\r\n\r\nh2(#notite). Notite\r\n\r\n* **Cosmin** deconteaza mancare pentru sedinta asta.\r\n',1792,'protected',NULL,NULL),('algoritmiada-2010/runda-1','Algoritmiada 2010 - Runda 1','2009-10-25 16:37:51','2009-11-21 14:20:53','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Algoritmiada 2010, Runda 1\r\n\r\n(htabs)*(active) \'Despre...\':algoritmiada-2010/runda-1 \r\n* \'Clasele 5-8\':algoritmiada-2010/runda-1/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-1/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-1/5-8 \r\n\r\nRunda va incepe *Duminica 22 noiembrie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-1/studenti\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':algoritmiada-2010/runda-1/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-1/studenti\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==User(user=\"prostu\" type=\"tiny\")==\r\n* ==User(user=\"ditzoneC\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"marius\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica sau tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',1792,'protected',NULL,NULL),('algoritmiada-2010/runda-1/solutii/kss','Solutie Kss','2009-11-21 17:44:35','2009-11-22 21:08:55','h1(#kss). \'Kss\':problema/kss\r\n\r\nh2. Aceasta pagina trebuie sa ramana private pana la sfarsitul rundei!',1792,'public',NULL,NULL),('algoritmiada-2010/runda-1/solutii/kss','Solutie Kss','2009-11-21 17:44:35','2009-11-23 16:06:54','h1(#kss). \'Kss\':problema/kss\r\n\r\nPentru a rezolva aceasta problema vom incerca o abordare de genul urmator. Daca am putea raspunde la intrebarea: \"Avand un prefix oarecare, cate subsiruri distincte incep cu acest prefix?\", putem incerca sa cautam fiecare litera pe rand din solutie pana cand gasim intregul sir cerut. Construim o dinamica $din[ i ]$ = numarul de subsiruri distincte care incep de pe pozitia $i$ si contin litera de pe pozitia $i$. Ca sa rezolvam aceasta dinamica mai intai definim $next[c][i]$ = prima pozitie dupa $i$ pe care apare caracterul $c$ (daca $c$ apare fix pe pozitia $i$ atunci $next[ c ][ i ]$ = $i$). Vom calcula dinamica de la pozitia $N$ spre pozitia $1$, iar recurenta este: $din[ i ]$ = $1$ + suma dupa $c = a,z$ din $din[ next[ c ][ i + 1 ] ]$. Luam doar prima aparatie a fiecarui caracter pentru ca subsirurile sunt distincte dupa valoare, si nu dupa pozitiile pe care apar caracterele dar si cazul cand sirul contine doar caracterul curent. Avand aceasta dinamica putem incepe sa cautam solutia, pentru ca putem raspunde la intrebarea intiala astfel: daca avem un prefix $p$, il potrivim ca subsir peste sirul $S$ astfel incat astfel incat ultimul caracter al lui $p$ apare cat mai repede in $S$ (de exemplu pentru $p = a b$ si $S = c a b b$ vom potrivi $c **a b** b$ si nu $c **a** b **b**$. Fie $q$ aceasta potitie a ultimul caracter din $p$. Numarul de subsiruri care incep cu acest prefix $p$ este din[ q ] si se observa usor de ce. \r\n\r\nIn continuare voi explica mai detaliat cum gasim propriu-zis solutia. Dorim sa gasim al $K$-lea subsir. Sa presupunem mai intai ca sirul nostru incepe cu litera $a$. Determinam acel $q$ (am explicat mai sus ce reprezinta). Daca cumva $din[q]$ < $K$ atunci ca solutia nu va incepe cu $a$ ci cu o litera mai mare (lexicografic) pentru ca nu sunt suficiente subsiruri care incep cu $a$. Scadem din $K$, $din[q]$+1 si incercam urmatoarea litera $b$ pentru ca aplicam acelasi rationament (incercam sa gasim al $K-din[q]$-lea subsir care nu incepe cu $a$ ). Cand $din[q]$ >= $K$ inseamna ca litera curenta este cea buna si atunci trebuie sa gasim urmatoarea litera (la acest pas trebuie sa scadem $1$ din $K$ pentru ca sirul care se termina fix cu litera asta apare lexicografic inaintea celor ce vor urma, mai lungi). Pentru urmatoarea litera aplicam acelasi rationament decat ca trebuie sa avem grija ca acum inceputul solutiei este un prefix si nu doar o litera. Ne oprim atunci cand $K$-ul ramas devine $0$ (adica tocmai am pus ultima litera).\r\n\r\nSolutia aceasta are o complexitate $N$ * $sigma$ pe fiecare test ( $sigma$ este numarul de caractere din alfabet).',2038,'public',NULL,NULL),('algoritmiada-2010/runda-1/solutii/kss','Solutie Kss','2009-11-21 17:44:35','2009-11-23 16:10:51','h1(#kss). \'Kss\':problema/kss\r\n\r\nPentru a rezolva aceasta problema vom incerca o abordare de genul urmator. Daca am putea raspunde la intrebarea: \"Avand un prefix oarecare, cate subsiruri distincte incep cu acest prefix?\", putem incerca sa cautam fiecare litera pe rand din solutie pana cand gasim intregul sir cerut. Construim o dinamica $din[ i ]$ = numarul de subsiruri distincte care incep de pe pozitia $i$ si contin litera de pe pozitia $i$. Ca sa rezolvam aceasta dinamica mai intai definim $next[ c ][ i ]$ = prima pozitie dupa $i$ pe care apare caracterul $c$ (daca $c$ apare fix pe pozitia $i$ atunci $next[ c ][ i ]$ = $i$). Vom calcula dinamica de la pozitia $N$ spre pozitia $1$, iar recurenta este: $din[ i ]$ = $1$ + suma dupa $c = a,z$ din $din[ next[ c ][ i + 1 ] ]$. Luam doar prima aparatie a fiecarui caracter pentru ca subsirurile sunt distincte dupa valoare, si nu dupa pozitiile pe care apar caracterele in sirul initial; luam in calcul si cazul cand subsirul contine doar caracterul curent. Avand aceasta dinamica putem incepe sa cautam solutia, pentru ca putem raspunde la intrebarea intiala astfel: daca avem un prefix $p$, il potrivim ca subsir peste sirul $S$ astfel incat ultimul caracter al lui $p$ apare cat mai repede in $S$ (de exemplu pentru $p = a b$ si $S = c a b b$ vom potrivi $c **a b** b$ si nu $c **a** b **b**$ ). Fie $q$ aceasta potitie a ultimul caracter din $p$. Numarul de subsiruri care incep cu acest prefix $p$ este din[ q ] si se observa usor de ce. \r\n\r\nIn continuare voi explica mai detaliat cum gasim propriu-zis solutia. Dorim sa gasim al $K$-lea subsir. Sa presupunem mai intai ca sirul nostru incepe cu litera $a$. Determinam acel $q$ (am explicat mai sus ce reprezinta). Daca cumva $din[q]$ < $K$ atunci inseamna ca solutia nu va incepe cu $a$ ci cu o litera mai mare (lexicografic) pentru ca nu sunt suficiente subsiruri care incep cu $a$. Scadem din $K$, $din[q]$ si incercam urmatoarea litera $b$ pentru ca aplicam acelasi rationament (incercam sa gasim al $K-din[q]$-lea subsir care nu incepe cu $a$ ). Cand $din[q]$ >= $K$ inseamna ca litera curenta este cea buna si atunci trebuie sa gasim urmatoarea (la acest pas trebuie sa scadem $1$ din $K$ pentru ca sirul care se termina fix cu litera asta apare lexicografic inaintea celor ce vor urma, mai lungi). Pentru urmatoarea litera aplicam acelasi rationament decat ca trebuie sa avem grija ca acum inceputul solutiei este un prefix si nu doar o litera. Ne oprim atunci cand $K$-ul ramas devine $0$ (adica tocmai am pus ultima litera).\r\n\r\nSolutia aceasta are o complexitate $N$ * $sigma$ pe fiecare test ( $sigma$ este numarul de caractere din alfabet).',2038,'public',NULL,NULL),('planificare/sedinta-20091126','Ședință 2009-11-26','2009-11-23 14:30:08','2009-11-23 16:21:19','h1. Şedinţă 2009-11-26\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Joi* la ora *?* la ?.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20091103 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Algoritmiada Runda 2 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Coding Camp | |\r\n| Evaluator nou | |\r\n| Sala sedinta | |\r\n\r\nh2. Detalii\r\n\r\n* &hellip;\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* &hellip;\r\n\r\nh2(#notite). Notite\r\n\r\n* &hellip;\r\n',2038,'protected',NULL,NULL),('planificare/sedinta-20091126','Ședință 2009-11-26','2009-11-23 14:30:08','2009-11-23 16:33:46','h1. Şedinţă 2009-11-26\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Joi* la ora *?* la ?.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"stef2n\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20091103 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Algoritmiada Runda 2 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Coding Camp | ? |\r\n| Evaluator nou | ? |\r\n| Sala sedinta | ? |\r\n\r\nh2. Detalii\r\n\r\n* &hellip;\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* &hellip;\r\n\r\nh2(#notite). Notite\r\n\r\n* &hellip;\r\n',2044,'protected',NULL,NULL),('implica-te','Implica-te!','2007-03-09 23:39:36','2008-11-27 00:17:58','h1. Fii un bun _infoarenaut_! Implica-te!\r\n\r\n_infoarena_ este un site de pregatire la informatica dezvoltat in intregime de catre utilizatorii sai - comunitatea _infoarena_. Ne-am straduit sa concepem site-ul in asa fel incat fiecare utilizator sa poata contribui la dezvoltarea lui. Implica-te in dezvoltarea proiectului _infoarena_! Ofera un exemplu celorlalti! Mii de elevi si studenti iti vor multumi iar unii iti vor urma exemplul.\r\n\r\nh2. De ce m-as baga?\r\n\r\n* Efortul tau va atinge mii de elevi si studenti din Romania.\r\n* Te faci cunoscut. Iti acordam credit pentru contributia ta.\r\n* O actiune \'_pro bono publico_\':http://en.wikipedia.org/wiki/Pro_bono in plus pe CV-ul tau, in special daca aplici la universitati din afara.\r\n* Te promovam in \'echipa infoarena\':echipa-infoarena dupa un efort lung si sustinut.\r\n* Iti facem cinste cu suc si bere atunci cand ne vedem la concursuri. Pe bune!\r\n\r\nh2. Cum ma pot implica?\r\n\r\nMai jos am scris niste proiecte in care avem nevoie de ajutorul comunitatii. Pentru fiecare proiect de comunitate avem o pagina cu detalii despre cum poti sa ajuti si mai multe informatii de contact. Te-ar putea interesa sa citesti si paginile noastre de \'planificare\':planificare, unde se coordoneaza activitatile echipei intr-un mod public.\r\n\r\nh2. Proiecte infoarena\r\n\r\n|_. Proiect |_. Coordonator de proiect |\r\n| \'*Arhiva educationala!*\':implica-te/arhiva-educationala\r\nO arhiva cu scop exclusiv educational. Spre deosebire de problemele de concurs care imbina mai multe tehnici de programare, problemele din aceasta arhiva sunt aplicatii imediate ale unor algoritmi cunoscuti. Problemele vor avea sursele si testele publice, vor avea indicatii si diferite link-uri catre articole sau probleme similare.| ==user(user=\"filipb\" type=\"tiny\")==, ==user(user=\"PaulDB\" type=\"tiny\")==|\r\n| \'*Extinde arhiva!*\':implica-te/extinde-arhiva\r\nAm obtinut permisiunea multor autori de a importa problemele lor in arhiva. Ajuta-ne sa le punem la dispozitia comunitatii! Mii de useri iti vor multumi pentru noile provocari! | ==user(user=\"ditzonec\" type=\"tiny\")== |\r\n| \'*Scrie articole!*\':implica-te/scrie-articole\r\n_infoarena_ este un site bazat pe \'wiki\':documentatie/wiki, mare parte din continut fiind complet editabil de oricine, astfel incurajand colaborarea intre membrii comuntatii. Si tu poti scrie articole noi sau imbunatati articole noi in orice moment. | ==user(user=\"stef2n\" type=\"tiny\")== |\r\n| \'*Imbunatateste testele problemelor!*\':implica-te/imbunatatire-teste\r\nUnele probleme din arhiva nu au teste suficient de puternice incat sa departajeze intre solutii eficiente si mai putin eficiente. Gaseste teste mai bune! | ==user(user=\"ditzonec\" type=\"tiny\")== |\r\n| \'*Codeaza alaturi de noi!*\':development\r\nStii sau vrei sa inveti tehnologii web? Site-ul si evaluatorul _infoarena_ sunt dezvoltate open-source. Codul nostru e public. | ==user(user=\"domino\" type=\"tiny\")== |',1,'protected',NULL,NULL),('planificare/sedinta-20091126','Ședință 2009-11-26','2009-11-23 14:30:08','2009-11-26 18:17:07','h1. Şedinţă 2009-11-26\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Joi* la ora *19:00* la Cafepedia Romana.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"stef2n\" type=\"tiny\")==\r\n* ==User(user=\"prostu\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"victorsb\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20091103 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Algoritmiada Runda 2 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Probleme cu site-ul | ? |\r\n| Coding Camp | ==User(user=\"bogdan2412\" type=\"tiny\")== |\r\n| Evaluator nou | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Sala sedinta | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n* &hellip;\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Vali executa design la mapa.\r\n* Cosmin vorbeste cu Cristi de cardul lui.\r\n* Vali face testing pe masina virtuala.\r\n* Vali vorbeste cu Vlad Posea despre jailrun java.\r\n* Facem runda 2 la Algoritmiada pe 20 decembrie.\r\n* S-au stabilit sefi de grupe: Prostu (gimnaziu), Stefan (9-10), Bogdan (11-12).\r\n* Paul scrie blog post pentru runda 1.\r\n* Cosmin vorbeste cu Astronomy despre Amazon.\r\n* Paul vorbeste cu Cristina despre bilant Infoarena.\r\n* Stefan cauta paginile despre noi care sunt outdated.\r\n* Bogdan rezolva problemele cu reviziile vechi (fara securitate).\r\n* Facem coding camp pe 12-13 decembrie.\r\n\r\nh2(#notite). Notite\r\n\r\n* Prostu inspecteaza diff-ul din Linux.\r\n',2044,'protected',NULL,NULL),('planificare/sedinta-20091126','Ședință 2009-11-26','2009-11-23 14:30:08','2009-11-26 19:10:36','h1. Şedinţă 2009-11-26\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Joi* la ora *19:00* la Cafepedia Romana.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"stef2n\" type=\"tiny\")==\r\n* ==User(user=\"prostu\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"victorsb\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20091103 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Algoritmiada Runda 2 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Probleme cu site-ul | ? |\r\n| Coding Camp | ==User(user=\"bogdan2412\" type=\"tiny\")== |\r\n| Evaluator nou | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Sala sedinta | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| IAP #15: Tagging | ==User(user=\"bogdan2412\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n* &hellip;\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Vali executa design la mapa.\r\n* Cosmin vorbeste cu Cristi de cardul lui.\r\n* Vali face testing pe masina virtuala.\r\n* Vali vorbeste cu Vlad Posea despre jailrun java.\r\n* Facem runda 2 la Algoritmiada pe 20 decembrie.\r\n* S-au stabilit sefi de grupe: Prostu (gimnaziu), Stefan (9-10), Bogdan (11-12).\r\n* Paul scrie blog post pentru runda 1.\r\n* Cosmin vorbeste cu Astronomy despre Amazon.\r\n* Paul vorbeste cu Cristina despre bilant Infoarena.\r\n* Stefan cauta paginile despre noi care sunt outdated.\r\n* Bogdan rezolva problemele cu reviziile vechi (fara securitate).\r\n* Facem coding camp pe 12-13 decembrie.\r\n* Cosmin cauta loc pentru sedinta si coding camp.\r\n* Cosmin vorbeste cu Vali de evaluator.\r\n* Bogdan si Cosmin cer drepturi lui Cristi pentru Google Analytics si Google Apps.\r\n* Cosmin vorbeste cu Cristi de newsletter@infoarena.ro si no-reply@infoarena.\r\n* Cosmin face IAP pentru dificultate.\r\n\r\nh2(#notite). Notite\r\n\r\n* Prostu inspecteaza diff-ul din Linux.\r\n',2044,'protected',NULL,NULL),('utilizator/cezarmocan','Cezar','2006-11-24 20:59:14','2009-09-27 11:32:28','h2. Despre mine\r\n\r\n* Elev in clasa a 10-a la ICHB\r\n* Pana in clasa a 8-a am studiat la Colegiul National Emil Racovita Cluj-Napoca, iar din clasa a 9-a invat la Liceul International de Informatica Bucuresti. \r\n* Am inceput sa fac programare din clasa a 3-a si intr-a 4-a am luat mentiune la nationala\r\n* Lucrez pe infoarena de prin clasa a 5-a, si pot spune ca e una din principalele mele surse de pregatire\r\n* Imi place sa citesc si sa ascult muzica buna (rock si nu numai)\r\n* Practic cu placere sporturi ca tenis, inot, ciclism, fotbal, ski, patinaj\r\n\r\n\r\nh2. Distinctii primite\r\n\r\nh3. Clasa a IV-a\r\n\r\n* Mentiune la ONI Buzau 2004 la clasa a V-a\r\n\r\nh3. Clasa a V-a\r\n\r\n* Locul 1 la ONI Galati 2005\r\n* Locul 2 la Concursul Interjudetean de Matematica Grigore Moisil\r\n\r\nh3. Clasa a VI-a\r\n\r\n* Mentiune (locul 4) la ONI Targoviste 2006\r\n* Locul 1 la Concursul Palatelor Copiilor Satu Mare 2006\r\n* Locul 1 la PACO Bucuresti 2006\r\n* Locul 5 la finala preONI 2006\r\n* Participare la finala .Campion 2006\r\n* Locul 1 la Concursul Interjudetean de Matematica Dumitru Tiganetea\r\n\r\nh3. Clasa a VII-a\r\n\r\n* Locul 1 la Grigore Moisil 2007 Oradea\r\n* Locul 1 la ONI 2007 Cluj-Napoca\r\n* Locul 4 la Finala .Campion 2007\r\n* Calificare la Finala preONI 2007\r\n* Locul 5 cu echipa scolii la concursul ACSL 2007 - Houston\r\n* Mentiune la JBOI 2007 (locul 13, primul sub bronz)\r\n* Participare la Olimpiada Nationala de Matematica\r\n* Calificare la faza nationala a concursului de matematica \"Cangurul\"\r\n\r\nh3. Clasa a VIII-a\r\n\r\n* Locul 1 la concursul \"Stelele Informaticii\" 2007 la clasa a 9-a (locul 3 la general)\r\n* Locul 9 (mentiune) la ONIGim Bacau 2008\r\n* Locul 1 la Grigore Moisil 2008 Cluj-Napoca\r\n* Locul 1 la finala preONI 2008 cls. 5-8\r\n* Locul 1 la finala .Campion 2008 grupa S\r\n* Locul 5 cu echipa scolii la concursul ACSL 2008 - Baltimore\r\n* Locul 1 (cu punctaj maxim) la JBOI 2008 by NET\r\n* Locul 1 la Concursul Palatelor Copiilor Satu Mare 2008\r\n* Calificare la faza nationala a concursului de matematica \"Cangurul\"\r\n\r\nh3. Clasa a IX-a\r\n\r\n* Calificare in finala concursului Topcoder Highschool Tournament 2009\r\n* Locul 2 la concursul \"Stelele Informaticii 2009\" \r\n* Premiul 3 (locul 4) la ONI Galati 2009\r\n* Locul 3 la finala Algoritmiada 2009\r\n* Calificat la finala .Campion 2009 la grupele Small si Medium\r\n* Locul 3 la CCEX 2009\r\n* Primul clasat la loturile online\r\n\r\nh4. Toate aceste rezultate se datoreaza pregatirii temeinice cu profesorii mei de pana acum: Negreanu-Maior Lucia, Negreanu-Maior Adrian, Ilea Lucian, Ali Yuksel, Baltescu Paul, Ganceanu Silviu, Grigorean Andrei.\r\nTot respectul si consideratia pentru acesti oameni deosebiti.\r\n\r\n\r\nh2. Profesori pe infoarena\r\n\r\n ==User(user=\"pauldb\" type=\"tiny\")==\r\n ==User(user=\"silviug\" type=\"tiny\")== \r\n ==User(user=\"wefgef\" type=\"tiny\")== \r\n ==User(user=\"gcosmin\" type=\"tiny\")==\r\n ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n ==User(user=\"raduzer\" type=\"tiny\")==\r\n ==User(user=\"savim\" type=\"tiny\")==\r\n ==User(user=\"GavrilaVlad\" type=\"tiny\")==\r\n ==User(user=\"tvlad\" type=\"tiny\")==\r\n ==User(user=\"toni2007\" type=\"tiny\")==\r\n ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n ==User(user=\"GheorgheMihai\" type=\"tiny\")==\r\n ==User(user=\"mariusdrg\" type=\"tiny\")==\r\n ==User(user=\"devilkind\" type=\"tiny\")==\r\n ==User(user=\"alexthero\" type=\"tiny\")==\r\n ==User(user=\"protoman\" type=\"tiny\")==\r\n ==User(user=\"radu_voroneanu\" type=\"tiny\")==\r\n ==User(user=\"andrei.12\" type=\"tiny\")==\r\n ==User(user=\"gabitzish1\" type=\"tiny\")==\r\n',1430,'protected',NULL,NULL),('utilizator/mathboy','Rotaru Dragos Alin','2008-12-24 18:43:37','2009-11-18 19:17:12','h2. Despre mine\r\n\r\n* Elev in clasa a X-a D, Matematica-Informatica, Informatica Intensiv la Colegiul National Unirea Focsani\r\n* Contact: dragos_mathboy@yahoo.com\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n\r\n==user(user=\"Florian\" type=\"normal\")==\r\n\r\n==user(user=\"cosmin79\" type=\"normal\")==\r\n\r\n==user(user=\"klamathix\" type=\"normal\")==\r\n\r\n==user(user=\"DraStiK\" type=\"normal\")==\r\n\r\n==user(user=\"antoanela\" type=\"normal\")==\r\n\r\n==user(user=\"Protoman\" type=\"normal\")==\r\n\r\n==user(user=\"Omega91\" type=\"normal\")==\r\n\r\n==user(user=\"lucianvn\" type=\"normal\")==\r\n\r\n==user(user=\"bogdanhm999\" type=\"normal\")==\r\n\r\n==user(user=\"drag0sh\" type=\"normal\")==\r\n\r\n',9232,'public',NULL,NULL),('2-sat','Problema 2-satisfiabilității','2008-12-09 15:55:03','2009-04-18 16:45:26','h1. Problema 2-satisfiabilităţii\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"marius\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 30em}*{text-align:center} *Conţinut:*\r\n* {\'Introducere\':2-sat#introducere}\r\n* {\'Forme normale ale formulelor logice\':2-sat#forme-normale}\r\n* {\'SAT, 3-SAT, 2-SAT\':2-sat#overview-sat}\r\n* {\'Soluţii pentru 2-SAT\':2-sat#solutii-2-sat}\r\n** {\'Soluţie $O(M * 2^N^)$\':2-sat#solutie-1}\r\n** {\'Soluţie $O(N * M)$\':2-sat#solutie-2}\r\n** {\'Soluţie $O(N^2^)$\':2-sat#solutie-3}\r\n** {\'Soluţie $O(M + N)$\':2-sat#solutie-4}\r\n* {\'Aplicaţii\':2-sat#aplicatii}\r\n** {\'Party &#40;preONI 2003/2004&#41;\':2-sat#party}\r\n** {\'Cigraf\':2-sat#cigraf}\r\n** {\'Orpath &#40;Olimpiadă Rusia&#41;\':2-sat#orpath}\r\n** {\'Aladdin &#40;Bursele Agora 2005/2006, Runda 1&#41;\':2-sat#aladdin}\r\n* {\'Probleme propuse\':2-sat#probleme}\r\n* {\'Bibliografie\':2-sat#bibliografie}\r\n\r\nh2(#introducere). Introducere\r\n\r\nProblema satisfiabilităţii, notată prescurtat cu $SAT$, cere determinarea existenţei pentru o formulă booleană <tex> \\phi </tex> a unei atribuiri satisfiabile. O formulă booleană <tex> \\phi </tex> este compusă din $variabile$ logice <tex> (x_{1}, x_{2}, ...) </tex>, $operatori$ logici ( <tex> \\wedge </tex> şi,  <tex> \\vee </tex> sau, <tex> \\sim </tex> non, <tex> \\rightarrow </tex> implicaţie, <tex> \\leftrightarrow </tex> echivalenţă), şi $paranteze$. O atribuire de valori booleene pentru variabilele acestei expresii se numeşte $atribuire satisfiabilă$ dacă evaluarea expresiei după atribuirea valorilor dă ca rezultat valoarea de adevăr $adevărat$. De acum încolo vom folosi pentru simplitate valorile <tex> 1 </tex> şi <tex> 0 </tex> în loc de $adevărat$ şi $fals$.\r\n\r\nUn exemplu de formulă ar fi <tex> \\phi = ((x_{1} \\rightarrow x_{2}) \\vee \\sim((\\sim x_{1} \\leftrightarrow x_{3}) \\vee x_{4})) \\wedge \\sim x_{2} </tex>. Aceasta are atribuirea satisfiabilă <tex> \\langle x_{1} = 0, x_{2} = 0, x_{3} = 1, x_{4} = 1 \\rangle </tex> pentru că <tex> \\phi = ((0 \\rightarrow 0) \\vee \\sim((\\sim 0 \\leftrightarrow 1) \\vee 1)) \\wedge \\sim 0 = (1 \\vee \\sim (1 \\vee 1)) \\wedge 1 = (1 \\vee 0) \\wedge 1 = 1</tex>. \r\n\r\nh2(#forme-normale). Forme normale ale formulelor logice\r\n\r\nOrice formulă booleană poate fi transformată în două forme:\r\n\r\n* $Forma normal conjunctivă$ în care expresia este exprimată ca o conjuncţie de propoziţii, iar fiecare propoziţie este formată dintr-o disjuncţie de $literali$. Un $literal$ este o variabilă care poate fi sau nu negată. Un exemplu de expresie în forma normal conjunctivă ar fi: <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) \\wedge (x_{3} \\vee x_{2} \\vee x_{4}) \\wedge (\\sim x_{1} \\vee \\sim x_{3} \\vee \\sim x_{4}) </tex> care are pe <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) </tex> ca primă propoziţie cu literalii <tex> x_{1} </tex>, <tex> \\sim x_{1} </tex>, <tex> \\sim x_{2} </tex>.\r\n\r\n* $Forma normal disjunctivă$ este formată ca o disjuncţie de propoziţii, fiecare dintre aceste propoziţii fiind o conjuncţie de literali. Un exemplu de o asemenea formulă ar fi următoarea: <tex> (x_{1} \\wedge x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge \\sim x_{3}) \\vee (\\sim x_{1} \\wedge x_{2} \\wedge \\sim x_{2}) </tex>.\r\n\r\nh2(#overview-sat). SAT, 3-SAT, 2-SAT\r\n\r\nProblema $SAT$ este $NP-completă$. De fapt, este prima problemă $NP-completă$ găsită. Stephen Cook a demonstrat $NP-completitudinea$ ei în 1971. Pe vremea aceea nu se ştia nici măcar că problemele $NP-complete$ există. Această problemă rămâne $NP-completă$ chiar dacă restricţionăm expresiile la unele care în forma normal conjunctivă au doar trei literali. Problema satisfiabilităţii pentru asemenea expresii se numeşte $3-SAT$, şi multe probleme pot fi demonstrate a fi $NP-complete$ prin reducerea lui $3-SAT$ la problemele respective în timp polinomial. Din fericire, problema $2-SAT$, adică cea pentru care în fiecare propoziţie există doar $2$ literali, se poate rezolva eficient. Restul articolului va prezenta trei metode de rezolvare a problemei $2-SAT$ şi câteva aplicaţii ale acesteia din concursuri de programare.\r\n\r\nh2(#solutii-2-sat). Soluţii pentru 2-SAT\r\n\r\nUn exemplu de problemă $2-SAT$ ar fi satisfiabilitatea formulei <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Această formulă este satisfăcută de valorile <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>. Pentru a satisface întreaga expresie trebuie ca în fiecare propoziţie cel puţin unul din cei doi literali să aibă valoarea de adevăr <tex> 1 </tex>.\r\n\r\nh3(#solutie-1). Soluţie $O(M * 2^N^)$\r\n\r\nO primă metodă de rezolvare ar fi să încercăm toate cele $2^N^$ posibilităţi de atribuire posibilă, dar această metodă are ordinul de complexitate $O(M * 2^N^)$ şi este eficientă doar pentru instanţe mici ale problemei.\r\n\r\nh3(#solutie-2). Soluţie $O(N * M)$\r\n\r\nUrmătoarea soluţie pare trivială, dar găsirea acestui algoritm şi realizarea faptului că el rezolvă corect problema sunt mai grele decât impresia lăsată după citirea ei. Considerăm o propoziţie oarecare cu două variabile $p$ şi $q$, apoi una dintre ele, de exemplu $p$. Îi atribuim literalului în care apare $p$ valoarea $0$. Pentru ca propoziţia respectivă să aibă $1$ valoarea de adevăr, atunci valoarea lui $q$ trebuie fixată. Fixând şi valoarea lui $q$, probabil şi alte propoziţii ce conţin literalul $q$ vor avea celălalt literal fixat. Propagăm astfel o serie de schimbări. După ce toate schimbările forţate au fost făcute, propoziţiile rezultate vor fi de următoarele tipuri: <tex> a \\vee b </tex>, <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex>. Propoziţii de tip <tex> 0 \\vee b </tex> nu pot apărea pentru că toate schimbările forţate au fost deja propagate. Dacă apare o propoziţie <tex> 0 \\vee 0 </tex> atunci alegerea făcută pentru valoarea lui $p$ este greşită. Vom încerca şi alegerea opusă pentru $p$. Dacă ambele duc la o propoziţie de tip <tex> 0 \\vee 0 </tex> atunci expresia nu poate fi satisfăcută. Propoziţiile de forma <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex> pot fi ignorate. În acest fel am eliminat cel puţin o variabilă şi o propoziţie din expresie. Dacă expresia iniţială era satisfiabilă, atunci şi expresia din care s-au eliminat câteva propoziţii a rămas satisfiabilă. Continuând pe această idee obţinem un algoritm de complexitate $O(N * M)$, pentru că la fiecare atribuire de valoare pentru o variabilă parcurgem şirul de propoziţii o dată. \r\n\r\nSă vedem cum funcţionează algoritmul pentru expresia: <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Considerăm propoziţia <tex> (x_{1} \\vee \\sim x_{2}) </tex> şi <tex> \\langle x_{2} = 1 \\rangle </tex>. Astfel, vom obţine mai departe <tex> (x_{1} \\vee 0) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee 1) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. În propoziţia <tex> (x_{1} \\vee 0) </tex>, <tex> x_{1} </tex> trebuie să fie egal cu <tex> 1 </tex>. Acum, expresia devine: <tex> (0\\ \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee 0) </tex>. Din propoziţia <tex> (0\\ \\vee \\sim x_{3}) </tex> obţinem <tex> \\langle x_{3} = 0 \\rangle </tex>, iar din <tex> (x_{4} \\vee 0) </tex> obţinem <tex> \\langle x_{4} = 1 \\rangle </tex>. Deci, atribuirea satisfiabilă este <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>.\r\n\r\nh3(#solutie-3). Soluţie $O(N^2^)$\r\n\r\nO altă soluţie elegantă se bazează pe o metodă randomizată:\r\n\r\n== code(cpp) |\r\natribuim valori booleene arbitrare variabilelor;\r\ncât timp expresia nu este satisfăcută, execută\r\n    găsim o propoziţie cu valoarea de adevăr 0;\r\n    schimbăm valoarea de adevăr a oricăreia dintre cele două variabile prezente în propoziţie;\r\nsfârşit cât timp\r\n==\r\n\r\nLinia $4$ va face ca acea propoziţie să aibă noua valoare de adevăr <tex> 1 </tex>.\r\n\r\nDe ce ar merge acest algoritm? Să presupunem că există o soluţie a problemei, o notăm cu <tex> S </tex>, iar cu <tex> X </tex> notăm şirul valorilor curente ale variabilelor. Ne uităm la fiecare pas al algoritmului la numărul de variabile care au valori diferite în soluţie faţă de cele din <tex> X </tex> (acest număr de diferenţe între elementele de acelaşi index pentru două şiruri se mai numeşte şi \'distanţă Hamming\':http://en.wikipedia.org/wiki/Hamming_distance între şiruri). Fie această valoare la pasul current $K$. Noi am vrea să avem $K = 0$. Cum va evolua $K$ pe parcursul algoritmului? La un moment dat noi schimbăm valoarea unei variabile luate aleator dintr-o propoziţie nesatisfăcută. Pentru că în <tex> S </tex> propoziţia este satisfăcută, înseamnă că cel puţin una dintre cele două variabile ale propoziţiei are valori diferite în <tex> X </tex> faţă de <tex> S </tex>. Astfel, operaţia făcută de noi are probabilitate de cel puţin $0.5$ să ne aducă mai aproape de soluţie. Vom nota cu <tex> T(i) </tex> numărul probabil de paşi în care un şir <tex> X </tex> aflat la distanţa Hamming egală cu $i$ faţă de <tex> S </tex>, va fi transformat în <tex> S </tex>. Evident:\r\n\r\n<tex> T(0) = 0 </tex>\r\n\r\n<tex> T(i) \\le \\dfrac {T(i + 1) + T(i - 1)}{2} + 1 </tex> pentru $0 < i < N$ ({$N$} e numărul de variabile booleene ale expresiei)\r\n\r\nSe pune semnul de inegalitate pentru că ambele variabile pot avea valori diferite faţă de cele din soluţie, deci schimbarea valorii oricăreia ar putea să ne aducă mai aproape de soluţie.\r\n\r\nDacă toate variabilele diferă de soluţie, orice schimbare ne aduce mai aproape de aceasta:\r\n\r\n<tex> T(N) = T(N - 1) + 1 </tex>\r\n\r\nNe interesează numai limitele superioare, deci folosim doar egalităţi în loc de inegalităţi:\r\n\r\n<tex> X(0) = 0 </tex>, <tex> X(i) = \\dfrac {X(i + 1) + X(i - 1)}{2} + 1 </tex>, <tex> X(N) = X(N - 1) + 1 </tex>\r\n\r\nDacă adunăm toate ecuaţiile obţinem:\r\n\r\n<tex> X(0) + X(1) + ... + X(N) = </tex> <tex> \\dfrac {X(0) + X(1) + 2X(2) + ... + 2X(N - 2) + X(N - 1) + X(N)}{2} + X(N) + N - 1 </tex>\r\n\r\nDe aici avem că <tex> \\dfrac {X(1) + X(N - 1) - X(N)}{2} = N - 1 </tex>, iar din <tex> X(N) = X(N - 1) + 1 </tex> rezultă că <tex> X(1) = 2N - 1 </tex>. Mai departe avem că <tex> X(2) = 4N - 4 </tex> <tex> ... </tex> <tex> X(i) = 2iN - i^2 </tex>, de unde, când <tex> i = N </tex>, avem că <tex> X(N) = N^2 </tex>.\r\n\r\nAstfel, numărul mediu de paşi ai algoritmului este pătratic în numărul $N$ de variabile. Lăsând algoritmul să ruleze de 2-3 ori mai mulţi paşi decât numărul mediu, avem o probabilitate foarte mare să ajungem la rezultat.\r\n\r\nh3(#solutie-4). Soluţie $O(M + N)$\r\n\r\nO a treia soluţie se bazează pe relaţia de implicaţie. Relaţia <tex> \\rightarrow </tex> are următoarea tabelă de adevăr:\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> A \\rightarrow B </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nRelaţia de implicaţie are următoarea semnificaţie: dacă <tex> A </tex> este adevărat atunci şi <tex> B </tex> este adevărat. Scriem tabela expresiei <tex> \\sim A \\vee B </tex> şi observăm că aceasta este egală cu cea a relaţiei de implicaţie.\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> \\sim A \\vee B </tex>|\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nFiecare clauză <tex> A \\vee B </tex> poate fi scrisă ca două implicaţii <tex> \\sim A \\rightarrow B </tex> şi <tex> \\sim B \\rightarrow A </tex>. Realizăm un graf al implicaţiilor. Astfel, nodurile grafului vor fi variabilele <tex> A </tex>, <tex> B </tex> <tex> ... </tex> şi negaţiile lor <tex> \\sim A </tex>, <tex> \\sim B </tex> <tex> ... </tex> iar muchiile acestui graf vor fi implicaţiile echivalente cu propoziţiile din expresie. Deci, dacă expresia are $M$ propoziţii, graful va avea $2M$ muchii. Acestea fiind zise, expresiei <tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) </tex> îi corespunde graful:\r\n\r\np=. !2-sat?Graf.png!\r\n\r\nDacă avem <tex> A \\longrightarrow B </tex> o muchie în graful nostru şi literalul <tex> A </tex> este adevărat, atunci şi literalul <tex> B </tex> trebuie să fie adevărat pentru ca propoziţia reprezentată de muchie să fie satisfăcută. Putem demonstra prin inducţie că dacă există un drum în graf de la literalul <tex> A </tex> la literalul <tex> B </tex>, atunci dacă <tex> A </tex> este adevărat şi <tex> B </tex> trebuie să fie adevărat. Dacă există un drum de la un literal <tex> X </tex> la <tex> \\sim X </tex>, precum şi un drum invers, atunci nu va exista soluţie pentru că nu putem seta în acelaşi timp o variabilă şi valoarea ei negată la valoarea adevărat. De aici rezultă că dacă în graful asociat expresiei există o variabilă <tex> X </tex> în aceeaşi componentă tare conexă cu <tex> \\sim X </tex> atunci instanţa problemei satisfiabilităţii nu poate fi satisfăcută. Dacă nu există o asemenea variabilă, vom vedea în continuare cum putem rezolva problema. Întâi, facem observaţia că dacă în graf există muchia <tex> A \\longrightarrow B </tex> atunci există şi muchia <tex> \\sim B \\longrightarrow \\sim A </tex>. Astfel, dacă există un drum de la <tex> A </tex> la <tex> B </tex> în graf, aplicând proprietatea menţionată pentru fiecare muchie a drumului, vom găsi un drum de la <tex> \\sim B </tex> la <tex> \\sim A </tex>. Evident, afirmaţia este valabilă şi reciproc: dacă există drum de la <tex> B </tex> la <tex> A </tex> atunci vom avea un drum de la nodul <tex> \\sim A </tex> la <tex> \\sim B </tex>. Astfel, dacă avem că <tex> A </tex> şi <tex> B </tex> sunt în aceeaşi componentă tare conexă atunci şi nodurile <tex> \\sim A </tex> şi <tex> \\sim B </tex> sunt în aceeaşi componentă tare conexă. Deci, dacă nu există doi literali <tex> X </tex> şi <tex> \\sim X </tex> în aceeaşi componentă tare conexă, putem să împărţim graful în componente tare conexe şi să împerechem componentele câte două astfel ca în fiecare pereche să apară o componentă <tex> U </tex> cu nişte literali şi altă componentă <tex> \\sim U </tex> cu aceiaşi literali negaţi. Pentru a găsi o soluţie vom determina mai întâi componentele tare conexe ale grafului. Apoi putem contracta fiecare componentă într-un nod. Graful obţinut va fi aciclic. Alegem un nod <tex> u </tex> în care nu intră nicio muchie (un asemenea nod trebuie să existe pentru a nu exista cicluri). Din considerente de simetrie, din nodul lui pereche <tex> \\sim u </tex> nu va ieşi nicio muchie. Literalilor componentei <tex> U </tex> putem să le dăm valoarea de adevăr <tex> 0 </tex>, iar literalilor din componenta pereche <tex> \\sim U </tex>  putem să le dăm valoarea de adevăr <tex> 1 </tex>. Această alegere nu impune restricţii asupra celorlalţi literali şi elimină câteva variabile din problemă. Repetarea recursivă a acestui pas pe graful rămas va duce la rezolvarea problemei. Determinarea componentelor tare conexe se poate face în complexitatea $O(N + M)$. Pentru a vedea acest algoritm puteţi consulta \'secţiunea $23.5$\':http://zhuzeyuan.hp.infoseek.co.jp/ita/chap23.htm din {\'[1]\':2-sat#bibliografie}. Iar eliminarea nodurilor de care vorbeam mai sus se poate face în $O(N + M)$ folosind o sortare topologică.\r\n\r\nSă urmărim cum merge algoritmul nostru pe exemplul de mai sus. Componentele tare conexe sunt următoarele: <tex> \\{A\\} </tex>, <tex> \\{\\sim A\\} </tex>, <tex> \\{B, C, \\sim D\\} </tex>, <tex> \\{\\sim B, \\sim C, D\\} </tex>. În nodul asociat componentei <tex> \\{A\\} </tex> nu intră nicio muchie. Astfel, putem să îi atribuim lui <tex> A </tex> valoarea <tex> 0 </tex>, iar după eliminarea lui <tex> \\{A\\} </tex> şi <tex> \\{\\sim A\\} </tex>în nodul asociat componentei <tex> \\{\\sim B, \\sim C, D\\} </tex> nu intră nicio muchie, deci putem să îi atribuim lui <tex> B </tex> valoarea <tex> 1 </tex>, lui <tex> C </tex> valoarea <tex> 1 </tex> şi lui <tex> D </tex> valoarea <tex> 0 </tex>. Această atribuire este satisfiabilă după cum vedem în continuare:\r\n\r\n<tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) = </tex> <tex> (\\sim 0 \\vee \\sim 1) \\wedge (1 \\vee \\sim 1) \\wedge (1 \\vee 1) \\wedge (\\sim 1 \\vee \\sim 0) \\wedge (1 \\vee 0) = </tex> <tex> 1 \\wedge 1 \\wedge 1 \\wedge 1 \\wedge 1 = 1 </tex>\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\nRestul articolului va prezenta aplicaţii ale problemei $2-SAT$ din concursurile de programare.\r\n\r\nh2(#party). \'Party\':problema/party (preONI 2003/2004)\r\n\r\nbq. George vrea să îşi organizeze majoratul şi îşi doreşte ca petrecerea să fie de neuitat. Mâncarea, băutura, locaţia şi sonorizarea sunt deja asigurate, mai rămâne problema chemării prietenilor. El şi cu prietenul lui cel mai bun, Lucian, au preferinţe diferite şi pentru a nu se certa au pus la punct o listă de cerinţe care vor trebui să fie îndeplinite astfel încât cheful să se desfăşoare în cele mai bune condiţii! Pentru uşurinţă, prietenii lui George vor fi identificaţi prin numere întregi de la $1$ la $N$ ({$1 ≤ N ≤ 100$}) şi cerinţele în număr de $M$ ({$1 ≤ M ≤ 1.000$}) vor fi de tipurile 0, 1, 2 sau 3. O cerinţă de genul <tex> x \\ y </tex> 0 are semnificaţia că <tex> x </tex> sau <tex> y </tex> trebuie să participe la petrecere; <tex> x \\ y </tex> 1 are semnificaţia că dacă <tex> x </tex> participă nu există nicio restricţie pentru <tex> y </tex>, dar dacă <tex> x </tex> nu participă atunci nici <tex> y </tex> nu participa; <tex> x \\ y </tex> 2 are semnificaţia simetrică cu cerinţa 1; iar cerinţa <tex> x \\ y </tex> 3 are semnificaţia că cel puţin unul dintre <tex> x </tex> şi <tex> y </tex> nu participă la petrecere. Scrieţi un program care să-i ajute pe cei doi să determine care persoane vor fi invitate la petrecere. Se garantează că va fi posibilă întotdeauna organizarea unei petreceri!\r\n\r\nh3. Soluţie\r\n\r\nAceastă problemă este inspirată dintr-o problemă de la $CEOI 2002$ şi este evident că ne cere să determinăm o atribuire satisfiabilă pentru o formulă logică formată ca conjuncţie între cerinţele care se transformă astfel:\r\n\r\n* _cerinţa de tip 0_ corespunde propoziţiei <tex> x \\vee y </tex>;\r\n* _cerinţa de tip 1_ corespunde propoziţiei <tex> x \\vee \\sim y </tex>;\r\n* _cerinţa de tip 2_ corespunde propoziţiei <tex> \\sim x \\vee y </tex>;\r\n* _cerinţa de tip 3_ corespunde propoziţiei <tex> \\sim x \\vee \\sim y </tex>.\r\n\r\nUna din primele două rezolvări ar fi putut soluţiona această problemă, dar problema de la $CEOI$ avea limite mai mari şi pentru rezolvarea ei ar fi trebuit un algoritm de complexitate $O(N + M)$.\r\n\r\nh2(#cigraf). Cigraf\r\n\r\n_Autor: Mugurel Ionuţ Andreica_\r\n\r\nbq. Se dă un graf neorientat cu $N$ ({$1 &le; N &le; 1000$}) noduri şi $M$ ({$0 &le; M &le; N*(N-1)/2$}) muchii. Se doreşte împărţirea nodurilor acestui graf în $2$ mulţimi, <tex> C </tex> şi <tex> I </tex>, având următoarele proprietăţi: fiecare nod face parte din exact una din cele $2$ mulţimi, există muchie între oricare $2$ noduri din mulţimea <tex> C </tex>, nu există nicio muchie între $2$ noduri din mulţimea <tex> I </tex>. Este posibil ca una dintre cele $2$ mulţimi să fie vidă. Soluţia nu este neapărat unică. Numele celor două mulţimi provin de la $clică$ şi $mulţime independentă$. De exemplu, pentru graful de $6$ noduri ce are muchiile <tex> \\{\\{1, 4\\}, \\{4, 6\\}, \\{6, 1\\}, \\{2, 4\\}, \\{2, 6\\}, \\{3, 4\\}, \\{1, 3\\}\\} </tex> o împărţire posibilă ar fi <tex> C = \\{1, 4, 6\\} </tex>, <tex> I = \\{2, 3, 5\\} </tex>.\r\n\r\nh3. Soluţie\r\n\r\nDacă între două noduri există muchie atunci nu pot fi amândouă în mulţimea <tex> I </tex>, iar dacă între două noduri nu există muchie nu pot fi amândouă în mulţimea <tex> C </tex>. Transformăm această problemă într-o instanţă de $2-SAT$ astfel: faptul că nodul <tex> x </tex> aparţine mulţimii <tex> C </tex> îl reprezentăm dându-i lui <tex> x </tex> valoarea <tex> 1 </tex>, iar apartenenţa la mulţimea <tex> I </tex> se codifică prin valoarea <tex> 0 </tex>. Acum existenţa unei muchii <tex> (x, y) </tex> corespunde expresiei <tex> x \\vee y </tex>, astfel cel puţin unul din nodurile <tex> x </tex> şi <tex> y </tex> nu va fi în mulţimea <tex> I </tex>. Dacă nu există muchia <tex> (x, y) </tex> putem scrie <tex> \\sim x \\vee \\sim y </tex>, această expresie va fi adevărată dacă cel puţin un nod din cele două nu va fi în mulţimea <tex> C </tex>.\r\n\r\nh2(#orpath). Orpath (Olimpiadă Rusia)\r\n\r\nbq. Într-o ţară pacifistă, există $N$ oraşe şi $K$ autobuze $(1 &le; N, K &le; 100)$. La orele aglomerate ale zilei, nu trebuie să existe două autobuze care merg în acelaşi timp în sensuri opuse. Traseul fiecărui autobuz este un ciclu. Spunem că el merge în sens pozitiv dacă va parcurge oraşele în ordinea $1 2 3 4 1 2 3 4 1 2$ ... sau în sens negativ dacă le parcurge în ordinea $1 4 3 2 1 4 3 2 1 4$ ... Găsiţi o posibilitate de atribuire a sensului fiecărui autobuz astfel ca accidentele de trafic să fie evitate (nu vor exista două autobuze care să se întâlnească şi să aibă sensuri de mers opuse). Pentru fiecare autobuz se vor şti oraşele de pe ruta lui, şi pentru fiecare două oraşe vecine pe rută se va şti timpul necesar autobuzului pentru a ajunge dintr-un oraş în altul. De exemplu, pentru $4$ oraşe unde oricare două sunt la timp de mers egal cu $10$, şi pentru două autobuze cu rutele $1 2 4$ şi $3 4 2$, o soluţie ar fi ca primul autobuz să meargă în sens pozitiv iar celălalt în sens negativ.\r\n\r\nh3. Soluţie\r\n\r\nPentru orice două autobuze vom găsi care sunt sensurile de mers pentru ele astfel ca cele două autobuze să nu se întâlnească şi să provoace un accident. Pentru un sens fixat putem afla pentru un autobuz pe ce interval de timp va fi pe o anumită stradă. El va fi în general pe o stradă $(i, j)$ pe un interval de tipul $[t1 + k*T ... t2 + k*T]$ unde $t1$ este timpul din prima rută parcursă pentru a ajunge la $i$, $t2$ timpul pentru a ajunge la $j$, iar $T$ este durata totală a unei rute. Acum, pentru a determina dacă două autobuze se vor întâlni pe o rută $(i, j)$ trebuie ca ele să se deplaseze în sensuri opuse pe această rută, iar intervalele $[t1 + k*T1 ... t2 + k*T1]$ ale primului să se intersecteze cu intervalele $[tt1 + p*T2 ... tt2 + p*T2]$ ale celui de-al doilea. Este clar acum că putem transforma problema într-o instanţă de $2-SAT$ prin maparea autobuzelor în variabile logice, a sensurilor de mers în valorile $adevărat$ şi $fals$, iar pentru orice pereche de autobuze să fie o propoziţie logică ce ia valoarea $adevărat$ doar dacă sensurile de mers determinate de variabilele logice asociate autobuzelor sunt compatibile. Mai trebuie determinat într-un mod eficient dacă două clase de intervale de timp se intersectează. Aceasta rămâne ca temă cititorului.\r\n\r\nh2(#aladdin). \'Aladdin\':problema/aladdin (Bursele Agora 2005/2006, Runda 1)\r\n\r\nbq. Aladdin, aşa cum ştiaţi, este un mare magnat în afacerea de comercializare a covoarelor magice. Acesta doreşte să o cucerească pe prinţesa Iasmina, iar aceasta, pentru a-i testa inteligenţa îl roagă să îi facă un covor dreptunghiular împărţit în pătrăţele, asemănator unei table de şah cu $N$ linii şi $M$ coloane $(1 &le; N, M &le; 1000)$. Fiecare pătrăţel de pe covor trebuie colorat cu alb sau cu negru. Pentru fiecare pătrat care conţine $4$ pătrăţele Iasmina pune condiţia să aibă un număr fixat de pătrăţele colorate cu negru. Ajutaţi-l pe Aladdin să realizeze un covor care satisface condiţiile impuse de prinţesa Iasmina!\r\n\r\nh3. Soluţie\r\n\r\nÎntâi, să considerăm un exemplu. Pentru o cerinţă de forma:\r\n\r\ntable{width: 90px; text-align: center}.\r\n| <tex> 3 </tex> | <tex> 2 </tex> | <tex> 3 </tex> |\r\n| <tex> 2 </tex> | <tex> 3 </tex> | <tex> 3 </tex> |\r\n| <tex> 1 </tex> | <tex> 2 </tex> | <tex> 1 </tex> |\r\n\r\nuna din soluţii este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nFie <tex> A </tex> o matrice soluţie a problemei noastre. Vom numerota rândurile matricii de la $0$ la $N - 1$ şi coloanele de la $0$ la $M - 1$. Matricea de intrare <tex> S </tex> reprezintă de fapt sumele din fiecare pătrat de câte $2 x 2$ elemente. Facem observaţia că dacă ştim într-un pătrat de $2 x 2$ valorile pentru trei dintre celule, atunci valoarea din a patra celulă este unic determinată pentru că ştim suma elementelor din pătrat. Vedem astfel, că dacă ştim valorile elementelor din prima linie a matricii <tex> A </tex> şi din prima coloană, restul valorilor sunt unic determinate. Pentru a rezolva problema vom presupune <tex> A[0][0] </tex> cunoscut (de fapt, mai întâi vom rezolva problema presupunând că <tex> A[0][0] = 1 </tex>, iar dacă nu obţinem nicio soluţie vom încerca cu <tex> A[0][0] = 0 </tex>). Vom nota celulele <tex> A[0][1] </tex>, <tex> A[0][2]</tex>, <tex>...</tex>, <tex> A[0][M - 1] </tex> cu <tex> x_{1} </tex>, <tex> x_{2} </tex>, <tex>...</tex>, <tex> x_{M-1} </tex>, iar celulele <tex> A[1][0] </tex>, <tex> A[2][0] </tex>, <tex>...</tex>, <tex> A[N - 1][0] </tex> cu <tex> y_{1} </tex>, <tex> y_{2} </tex>, <tex>...</tex>, <tex> y_{N-1} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> A[0][0] </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> ... </tex> | <tex> x_{M-1} </tex> |\r\n| <tex> y_{1} </tex> | <tex> 1 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n| <tex> y_{2} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 0 </tex> |\r\n| ... | ... | ... | ... | ... |\r\n| <tex> y_{N-1} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n\r\nAcum, pentru fiecare celulă putem demonstra prin inducţie că <tex> A[i][j] = (-1)^i x_{j} + (-1)^j y_{i} + b[i][j] </tex>. Unde <tex> b[i][j] </tex> sunt nişte constante ce sunt calculate în funcţie de matricea primită la intrare. Este uşor de observat că dacă:\r\n\r\n<tex> A[i-1][j] = (-1)^{(i-1)} x_{j} + (-1)^j y_{i-1} + b[i-1][j] </tex>,\r\n<tex> A[i-1][j-1] = (-1)^{(i-1)} x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i-1][j-1] </tex>,\r\n<tex> A[i][j-1] = (-1)^i x_{j-1} + (-1)^{(j-1)} y_{i} + b[i][j-1] </tex>,\r\n\r\natunci:\r\n\r\n<tex> A[i][j] = </tex> <tex> S[i-1][j-1] - </tex> <tex> A[i-1][j] - </tex> <tex> A[i][j-1] - </tex> <tex> A[i-1][j-1] = </tex> <tex> S[i-1][j-1] - </tex> <tex> ((-1)^{(i-1)} x_{j} + </tex> <tex> (-1)^j y_{i-1} + </tex> <tex> b[i-1][j]) - </tex> <tex> ((-1)^{(i-1)} x_{j-1} + </tex> <tex> (-1)^{(j-1)} y_{i-1} + </tex> <tex> b[i-1][j-1]) - </tex> <tex> ((-1)^i x_{j-1} + </tex> <tex> (-1)^{(j-1)} y_{i-1} + </tex> <tex> b[i][j-1]) = </tex> <tex> (-1)^i x_{j} - </tex> <tex> (-1)^j y_{i-1} + </tex> <tex> (-1)^i x_{j-1} + </tex> <tex> (-1)^j y_{i-1} - </tex> <tex> (-1)^i x_{j-1} + </tex> <tex> (-1)^j y_{i} + </tex> <tex> S[i-1][j-1] - </tex> <tex> b[i-1][j] - </tex> <tex> b[i][j-1] - </tex> <tex> b[i-1][j-1] = </tex> <tex> (-1)^i x_{j} + </tex> <tex> (-1)^j y_{i} + </tex> <tex> b[i][j] </tex>.\r\n\r\nDe aici concluzionăm că <tex> b[i][j] = S[i-1][j-1] - b[i-1][j] - b[i][j-1] - b[i-1][j-1] \\ (*)</tex>.\r\n\r\nAvem un sistem format din inecuaţiile:\r\n\r\n<tex> 0 \\le x_{j} \\le 1 </tex>\r\n<tex> 0 \\le y_{i} \\le 1 </tex>\r\n<tex> -b[i][j] \\le (-1)^i x_{j} + (-1)^j y_{i} \\le 1 - b[i][j] </tex>\r\n\r\nEste uşor acum să transformăm acest sistem într-o formulă booleană în {\'formă normal conjunctivă\':2-sat#forme-normale} în care fiecare expresie are cel mult $2$ literali. Fiecare relaţie o putem înmulţi sau nu cu $-1$ astfel ca părţile constante ale relaţiei să fie pozitive. Observăm că <tex> -2 \\le b[i][j] \\le 3 </tex>, altfel nu avem soluţie. Dacă partea constantă minimă într-o relaţie este $2$ atunci ambele variabile au valori fixe, iar dacă este $1$ sau $0$ atunci relaţia o putem scrie ca o disjuncţie logică cu doi literali.\r\n\r\nO relaţie precum <tex> 0 \\le x + y \\le 1 </tex> poate fi tansformată logic în <tex> \\sim x \\vee \\sim y </tex>, astfel <tex> x </tex> şi <tex> y </tex> nu vor fi în acelaşi timp <tex> 1 </tex>, una de genul <tex> 1 \\le x + y \\le 2 </tex> va fi transformată în <tex> x \\vee y </tex>, astfel cel puţin <tex> x </tex> sau <tex> y </tex> va fi egal cu <tex> 1 </tex>, alta de tipul <tex> 0 \\le x - y \\le 1 </tex> poate fi scrisă ca <tex> x \\vee \\sim y </tex>, una de tipul <tex> 2 \\le x + y \\le 3 </tex> în <tex> x \\wedge y </tex>, iar una de tipul <tex> 0 \\le -x -y \\le 1 </tex> în <tex> \\sim x \\wedge \\sim y </tex>, una de tipul <tex> 1 \\le x - y  \\le 2 </tex> în <tex> x \\wedge \\sim y </tex>. Astfel am redus problema la rezolvarea unei instanţe de $2-SAT$. Avem $N+M-1$ necunoscute şi @(N-1)*(M-1)@ propoziţii. Folosind {\'a treia metodă de rezolvare\':2-sat#solutie-3} vom obţine un algoritm de complexitate $O((M + N)^2^)$ care soluţionează problema noastră.\r\n\r\nSă vedem cum merge acestă rezolvare pe exemplul din problemă:\r\n\r\nAlegem <tex> A[0][0] = 1 </tex>. Necunoscutele vor fi <tex> x_{1} </tex>, <tex> x_{2} </tex>, <tex> x_{3} </tex> şi <tex> y_{1} </tex>, <tex> y_{2} </tex>, <tex> y_{3} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> x_{3} </tex> |\r\n| <tex> y_{1} </tex> | <tex> A[1][1] </tex> | <tex> A[1][2] </tex> | <tex> A[1][3] </tex> |\r\n| <tex> y_{2} </tex> | <tex> A[2][1] </tex> | <tex> A[2][2] </tex> | <tex> A[2][3] </tex> |\r\n| <tex> y_{3} </tex> | <tex> A[3][1] </tex> | <tex> A[3][2] </tex> | <tex> A[3][3] </tex> |\r\n\r\nFolosind recurenţa <tex> (*) </tex> obţinem că matricea <tex> b </tex> este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 2 </tex> | <tex> 0 </tex> | <tex> 3 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> -1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n\r\nDe aici obţinem sistemul de inegalităţi:\r\n\r\n<tex> 0 \\le x_{1} \\le 1,  0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le 1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, -2 \\le -x_{1} - y_{1} \\le -1, 0 \\le -x_{2} + y_{1} \\le 1, -3 \\le -x_{3} - y_{1} \\le -2, </tex>\r\n<tex> 0 \\le y_{2} \\le 1,  0 \\le  x_{1} - y_{2} \\le  1,-1 \\le  x_{2} + y_{2} \\le 0,  1 \\le  x_{3} - y_{2} \\le  2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, -1 \\le -x_{1} - y_{3} \\le  0, 0 \\le -x_{2} + y_{3} \\le 1, -1 \\le -x_{3} - y_{3} \\le  0 </tex>\r\n\r\nTransformăm relaţiile astfel ca să nu apară nicio constantă negativă:\r\n\r\n<tex> 0 \\le x_{1} \\le 1, 0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le  1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, 1 \\le x_{1} + y_{1} \\le 2, 0 \\le -x_{2} + y_{1} \\le 1, 2 \\le x_{3} + y_{1} \\le 3, </tex>\r\n<tex> 0 \\le y_{2} \\le 1, 0 \\le x_{1} - y_{2} \\le 1, 0 \\le -x_{2} - y_{2} \\le 1, 1 \\le x_{3} - y_{2} \\le 2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, 0 \\le x_{1} + y_{3} \\le 1, 0 \\le -x_{2} + y_{3} \\le 1, 0 \\le x_{3} + y_{3} \\le 1 </tex>\r\n\r\nAcest sistem poate fi transformat într-o expresie booleană:\r\n\r\n<tex> (x_{1} \\vee y_{1}) \\wedge (\\sim x_{2} \\vee y_{1}) \\wedge (x_{3} \\wedge y_{1}) \\wedge </tex>\r\n<tex> (x_{1} \\vee \\sim y_{2}) \\wedge (\\sim x_{2} \\wedge \\sim y_{2}) \\wedge (x_{3} \\wedge \\sim y_{2}) \\wedge </tex>\r\n<tex> (\\sim x_{1} \\vee \\sim y_{3}) \\wedge (\\sim x_{2} \\vee y_{3}) \\wedge (\\sim x_{3} \\vee \\sim y_{3}) </tex>.\r\n\r\nAcestă expresie e satisfăcută de valorile: <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 1, y_{1} = 1, y_{2} = 0, y_{3} = 0 \\rangle </tex>, iar de aici putem determina o soluţie a problemei noastre iniţiale ca fiind:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nh2(#probleme). Probleme propuse\r\n\r\nPentru a vă familiariza cu subiectul prezentat în acest articol, vă propunem să încercaţi să rezolvaţi următoarele probleme:\r\n\r\n# \'Excursion\':http://www.oi.edu.pl/download/boi-2001.pdf - Baltic Olympiad in Informatics, 2001\r\n# \'Peaceful Commission\':http://www.oi.edu.pl/php/show.php?ac=e100000&module=show&file=zadania/oi8/spokojna - Polish Olympiad in Informatics, 2001\r\n\r\nh2(#bibliografie). Bibliografie:\r\n\r\n# T. H. Cormen, C. E. Leiserson, R. R. Rivest - \'_Introducere în Algoritmi_\':http://zhuzeyuan.hp.infoseek.co.jp/ita/toc.htm\r\n# \'_Satisfiability_\':http://en.wikipedia.org/wiki/Satisfiability, Wikipedia\r\n# \'_BOI 2001 Competition Material_\':http://www.oi.edu.pl/download/boi-2001.pdf\r\n# \'_CEOI 2002 Competition Material_\':http://ics.upjs.sk/ceoi/Documents.html',7668,'public',3704,NULL),('implica-te/arhiva-educationala','Arhiva Educationala','2008-02-23 13:13:01','2009-12-11 19:23:21','h1. Arhiva educationala ==Stars(rating=\"5\")==\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie. Mai multe despre acest proiect gasiti \'aici\':propuneri/6-arhiva-educationala.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Cum ne poti ajuta?\':implica-te/arhiva-educationala#cum\r\n* \'Echipa implicata in proiect\':implica-te/arhiva-educationala#echipa\r\n* \'Documentatie\':implica-te/arhiva-educationala#documentatie\r\n* \'Continutul arhivei\':implica-te/arhiva-educationala#probleme\r\n\r\nh2(#cum). Cum ne poti ajuta?\r\n\r\n1. Ofera sugestii la dezvoltarea proiectului.\r\n2. Contribuie cu feedback pentru a imbunatati calitatea problemelor existente.\r\n3. Vino cu idei pentru probleme noi.\r\nAjuta si tu la randul tau comunitatea infoarena! \r\n\r\nh2(#echipa). Echipa implicata in proiect\r\n\r\nMomentan, pentru a obtine o eficienta mai buna, recrutarea voluntarilor pentru dezvoltarea arhivei educationale a fost oprita. Echipa care este implicata activ in proiect este alcatuita din:\r\n\r\n* == user(user=\"Marius\" type=\"tiny\") ==, coordonator de proiect\r\n* == user(user=\"savim\" type=\"tiny\") ==\r\n* == user(user=\"cezarmocan\" type=\"tiny\") ==\r\n* == user(user=\"GavrilaVlad\" type=\"tiny\") ==\r\n* == user(user=\"mishu91\" type=\"tiny\") == \r\n\r\nMultumim celor care ne-au ajutat pana acum:\r\n\r\n* == user(user=\"pauldb\" type=\"tiny\") ==, fost coordonator de proiect\r\n* == user(user=\"filipb\" type=\"tiny\") ==, fost coordonator de proiect\r\n* == user(user=\"devilkind\" type=\"tiny\") ==\r\n* == user(user=\"mariusdrg\" type=\"tiny\") ==\r\n* == user(user=\"bogdan2412\" type=\"tiny\") ==\r\n* == user(user=\"Florian\" type=\"tiny\") ==\r\n* == user(user=\"gabitzish1\" type=\"tiny\") ==\r\n* == user(user=\"Tabara\" type=\"tiny\") ==\r\n* == user(user=\"Dastas\" type=\"tiny\") ==\r\n* == user(user=\"fireatmyself\" type=\"tiny\") ==\r\n* == user(user=\"cos_min\" type=\"tiny\") ==\r\n* == user(user=\"tudalex\" type=\"tiny\") ==\r\n* == user(user=\"toni2007\" type=\"tiny\") ==\r\n* == user(user=\"tm_radu\" type=\"tiny\") ==\r\n* == user(user=\"floringh06\" type=\"tiny\") ==\r\n* == user(user=\"prostu\" type=\"tiny\") ==\r\n* == user(user=\"amadaeus\" type=\"tiny\") ==\r\n* == user(user=\"sima_cotizo\" type=\"tiny\") ==\r\n\r\nh2(#documentatie). Documentatie\r\n\r\nFiecare voluntar are obligatia sa citeasca urmatoarele materiale inainte de a putea trece efectiv la lucru:\r\n\r\n* \'Editare de probleme\':documentatie/editare-de-probleme\r\n* \'Ghid evaluator\':documentatie/ghid-evaluator\r\n* \'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala\r\n\r\nh2(#probleme). Continutul arhivei\r\n\r\nIn tabelul de mai jos se afla probleme la care se lucreaza in momentul de fata. Finalizarea lor reprezinta unul dintre $OKR$-urile din trimestrul IV, 2009. Pentru a va familiariza si cu restul obiectivelor din acest trimestru, cititi \'aici\':okr.\r\n\r\ntable(example). |_. Denumire problema|_. Voluntar|_. Finalizat|\r\n| \'Cuplaj maxim de cost minim\':problema/cmcm | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Principiul includerii si excluderii\':problema/pinex | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Huffman\':problema/huffman | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'2SAT\':problema/2sat | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Al K-lea termen Fibonacci - Matrici\':problema/kfib | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Lowest Common Ancestor\':problema/lca | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Statistici de ordine\':problema/sdo | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Parantezare optima de matrici\':problema/podm | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Treapuri\':problema/treapuri | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Ciclu hamiltonian | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n\r\n\r\nIn tabelul de mai jos se afla sugestii privind algoritmii care trebuie sa se gaseasca sub forma de probleme in arhiva educationala. Puteti veni oricand cu propuneri si sugestii de probleme noi pe \"forum\":/forum/index.php?topic=3401.0.\r\n\r\ntable(example). |_. Denumire problema|_. Categoria|\r\n|Submultimi|Backtracking|\r\n|Knapsack|Programare dinamica|\r\n|NIM|Teoria jocurilor|\r\n|Sprague-Grundy|Teoria jocurilor|\r\n|Algoritmul lui Gauss|Matematica|\r\n|Problema de acoperire|Programare dinamica + Backtracking|\r\n|Algoritmul Bellman-Ford|Algoritmi pe grafuri|\r\n|Algoritmul Stoer-Wagner|Algoritmi pe grafuri|\r\n|Heavy Path Decomposition|Algoritmi pe grafuri|\r\n|Arbore -> cod Prufer|Algoritmi pe grafuri|\r\n|Cod Prufer -> arbore|Algoritmi pe grafuri|\r\n|Distanta maxima intre 2 noduri intr-un arbore|Algoritmi pe grafuri|\r\n|Siruri de sufixe|Siruri de caractere|\r\n|Arbori de sufixe|Siruri de caractere|\r\n|Automate - Aho Corasick|Siruri de caractere|\r\n|Arbori de intervale aplicatie 1|Structuri de date|\r\n|Arbori de intervale aplicatie 2|Structuri de date|\r\n|Arbori de intervale aplicatie 3|Structuri de date|\r\n|Arbori de intervale aplicatie 4|Structuri de date|\r\n|Algoritmi {$O(sqrtN)$}|Structuri de date|\r\n|Ortogonal Range Search|Structuri de date|\r\n|Aria unui poligon|Geometrie|\r\n|Intersectia a doua drepte|Geometrie|\r\n|Punct in poligon|Geometrie|\r\n|Punct in poligon convex|Geometrie|\r\n|Diagrame Voronoi|Geometrie|\r\n|Distanta minima intre doua puncte in plan|Geometrie|\r\n|Distanta maxima intre doua puncte in plan|Geometrie|\r\n|Minimum enclosing circle|Geometrie|\r\n|Sortare prin numarare|Diverse|\r\n|RadixSort|Diverse|\r\n|Interclasarea a doi vectori sortati|Diverse|\r\n|Operatii pe numere mari|Diverse|',3146,'protected',NULL,NULL),('propuneri/15-task-tagging','IAP #15: Task tagging','2009-11-26 08:50:05','2009-11-26 09:39:04','h1. IAP #15: Task tagging\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2009-11-26 |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"bogdan2412\")== |\r\n|_. Stare     | In constructie |\r\n\r\nh2(#abstract). Abstract\r\n\r\nSe propune crearea unui sistem prin care fiecarei probleme ii vor fi asociate informatii sub forma de taguri si a unui sistem de cautare bazat pe aceste taguri.\r\n\r\nh2(#motivatie). Motivatie\r\n\r\nArhiva de probleme devine din ce in ce mai mare si din ce in ce mai greu de navigat. Un astfel de sistem ar ajuta utilizatorii sa filtreze mult mai usor probleme in functie de mai multe informatii.\r\n\r\nPropun ca urmatoarele informatii sa fie asociate fiecarei probleme:\r\n\r\n* Autorul sau autorii problemelor (daca o problema a fost propusa de catre mai multi autori, fiecare autor va avea un tag separat).\r\n* Concursul (si runda) la care a fost data problema. Pentru problemele date la concursuri pe infoarena ar fi bine de mentinut si un tag cu grupa de varsta la care a fost data problema (din nou, daca o problema a fost data la mai multe grupe de varsta, fiecare grupa de varsta va avea un tag separat).\r\n** Spre exemplu tagurile asociate problemei \"vrejuri\":problema/vrejuri ar fi \"Algoritmiada 2010\", \"Algoritmiada 2010, Runda 1\", \"Algoritmiada 2010, Runda 1, 9-10\"\r\n* Cunostintele necesare rezolvarii problemelor. In aceasta categorie intra orice fel de algoritm classic cunoscut (un punct bun de plecare ar fi \"Training Path\":training-path).\r\n** Propun sa impartim aceste taguri in doua categorii: \"Generale\" (Grafuri, Programare Dinamica, Greedy, Structuri de date, Geometrie) si \"Specifice\" (Deque, Arbori echilibrati, Codul Gray, Minimal enclosing circle). Tag-urile generale nu iti ofera foarte multe informatii care ar putea strica farmecul problemelor, in timp ce cele \"specifice\" iti zic exact ce algoritmi sunt necesari pentru rezolvarea problemei. Fiecare din tagurile \"specifice\" se va incadra intr-o categorie denumita de un tag general. (spre exemplu Deque intra sub Structuri de date)\r\n** In momentul in care utilizatorul deschide o problema, tagurile sunt ascunse by default. Daca acesta vrea un hint de rezolvare, ii aratam intai tagurile generale. Daca vrea si mai multe hinturi, ii aratam toate tagurile.\r\n\r\nh2(#implementare). Implementare\r\n\r\nUn astfel de sistem implica adaugarea unei noi coloane in tabelul $ia_tags$ sau $ia_task_tags$ care sa mentina pentru fiecare tag de ce tip este. Pentru a putea face o interfata frumoasa, ne trebuie sa stim pentru fiecare tag daca el este pentru:\r\n\r\n* un \"autor\"\r\n* un \"concurs\"\r\n* o \"runda din concurs\",\r\n* o \"grupa de varsta din runda din concurs\"\r\n* o \"categorie de algoritmi\" (tag-urile de cunostinte generale)\r\n* un \"algoritm\".\r\n\r\nInterfata de filtrare dupa taguri ar trebui sa-ti dea o lista frumoasa cu toate tagurile pentru un autor, concurs, algoritm etc. Datorita separarii intre taguri de \"concurs\", de \"runda\" si de \"grupa de varsta\", odata ce utilizatorul a selectat un concurs dupa care vrea sa filtreze i se da optiunea de a filtra si dupa o runda a acelui concurs (daca acesta doreste), si dupa aceea i se da optiunea de a selecta si o anumita grupa de varsta.\r\n\r\nh2(#feedback). Feedback\r\n',1490,'public',4309,NULL),('links','Links','2006-11-05 23:22:35','2007-06-19 11:49:41','http://sorins-world.blogspot.com/',6383,'public',NULL,NULL),('utilizator/gavrilavlad','Gavrila Vlad','2007-09-21 12:07:43','2009-12-14 17:30:19','   \r\n\r\nh2. Despre mine\r\n\r\nMa numesc Gavrila Vlad Alexandru si sunt elev in clasa a IX-a la ICHB. Particip de mult timp la concursuri de informatica, iar principala mea sursa de pregatire este infoarena.\r\n\r\nh2. Distinctii primite\r\n\r\nOlimpiada Nationala de Informatica\r\n\r\n* 2004 - Buzau - Mentiune\r\n* 2005 - Galati - Premiul special\r\n* 2006 - Targoviste - Mentiunea I\r\n* 2007 - Cluj - Premiul II\r\n* 2008 - Bacau - Premiul I\r\n* 2009 - Galati - Premiul II\r\n\r\nBaraje\r\n\r\n* 2008 - Ploiesti / Iasi - Calificat (locul I) la JBOI\r\n* 2009 - Bistrita / Cluj - Calificat (locul I, cu maxim de puncte) la JBOI\r\n\r\nJunior Balkan Olympiad in Informatics\r\n\r\n* 2008 - Shumen - Argint\r\n* 2009 - Shumen - Aur absolut\r\n\r\nPreONI, Algoritmiada si .Campion\r\n\r\n* 2008 - PreONI - Finalist\r\n* 2009 - .Campion - Locul II\r\n* 2009 - Algoritmiada - Locul I\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* Profesori:\r\n\r\n==user(user=\"pauldb\" type=\"normal\")==\r\n\r\n==user(user=\"wefgef\" type=\"normal\")==\r\n\r\n==user(user=\"bogdan2412\" type=\"normal\")==\r\n\r\n==user(user=\"gcosmin\" type=\"normal\")==\r\n\r\n==user(user=\"silviug\" type=\"normal\")==\r\n\r\n\r\n* Prieteni:\r\n\r\n==user(user=\"savim\" type=\"normal\")==\r\n\r\n==user(user=\"CezarMocan\" type=\"normal\")==\r\n\r\n==user(user=\"raduzer\" type=\"normal\")==\r\n\r\n==user(user=\"toni2007\" type=\"normal\")==\r\n\r\n==user(user=\"tvlad\" type=\"normal\")==\r\n\r\n==user(user=\"victor.ionescu\" type=\"normal\")==\r\n\r\n==user(user=\"andrei-alpha\" type=\"normal\")==\r\n\r\n==user(user=\"GheorgheMihai\" type=\"normal\")==\r\n\r\n==user(user=\"andreea1cool\" type=\"normal\")==\r\n\r\n==user(user=\"radu_voroneanu\" type=\"normal\")==\r\n\r\n==user(user=\"protoman\" type=\"normal\")==\r\n\r\n==user(user=\"matemariaescu\" type=\"normal\")==\r\n\r\n==user(user=\"taloibogdan\" type=\"normal\")==\r\n',6800,'public',NULL,NULL),('implica-te/arhiva-educationala','Arhiva Educationala','2008-02-23 13:13:01','2009-12-17 06:24:12','h1. Arhiva educationala ==Stars(rating=\"5\")==\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie. Mai multe despre acest proiect gasiti \'aici\':propuneri/6-arhiva-educationala.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Cum ne poti ajuta?\':implica-te/arhiva-educationala#cum\r\n* \'Echipa implicata in proiect\':implica-te/arhiva-educationala#echipa\r\n* \'Documentatie\':implica-te/arhiva-educationala#documentatie\r\n* \'Continutul arhivei\':implica-te/arhiva-educationala#probleme\r\n\r\nh2(#cum). Cum ne poti ajuta?\r\n\r\n1. Ofera sugestii la dezvoltarea proiectului.\r\n2. Contribuie cu feedback pentru a imbunatati calitatea problemelor existente.\r\n3. Vino cu idei pentru probleme noi.\r\n\r\nAjuta si tu la randul tau comunitatea infoarena! \r\n\r\nh2(#echipa). Echipa implicata in proiect\r\n\r\nEchipa care este implicata activ in acest proiect este alcatuita din urmatorii membri...\r\n\r\n* == user(user=\"Marius\" type=\"tiny\") ==, coordonator de proiect\r\n* == user(user=\"savim\" type=\"tiny\") ==\r\n* == user(user=\"cezarmocan\" type=\"tiny\") ==\r\n* == user(user=\"GavrilaVlad\" type=\"tiny\") ==\r\n* == user(user=\"mishu91\" type=\"tiny\") == \r\n\r\n\'Multumim celor care ne-au ajutat pana acum.\':implica-te/arhiva-educationala/membri-emeritus\r\n\r\nh2(#documentatie). Documentatie\r\n\r\nFiecare voluntar are obligatia sa citeasca urmatoarele materiale inainte de a putea trece efectiv la lucru:\r\n\r\n* \'Editare de probleme\':documentatie/editare-de-probleme\r\n* \'Ghid evaluator\':documentatie/ghid-evaluator\r\n* \'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala\r\n\r\nh2(#probleme). Continutul arhivei\r\n\r\nIn tabelul de mai jos se afla probleme la care se lucreaza in momentul de fata. Finalizarea lor reprezinta unul dintre $OKR$-urile din trimestrul IV, 2009. Pentru a va familiariza si cu restul obiectivelor din acest trimestru, cititi \'aici\':okr.\r\n\r\ntable(example). |_. Denumire problema|_. Voluntar|_. Finalizat|\r\n| \'Cuplaj maxim de cost minim\':problema/cmcm | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Principiul includerii si excluderii\':problema/pinex | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Huffman\':problema/huffman | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| Algoritmul Bellman-Ford | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'2SAT\':problema/2sat | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Al K-lea termen Fibonacci - Matrici\':problema/kfib | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Lowest Common Ancestor\':problema/lca | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Statistici de ordine\':problema/sdo | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Parantezare optima de matrici\':problema/podm | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Treapuri\':problema/treapuri | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Ciclu hamiltonian | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Submulţimi\':problema/submultimi | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n\r\n\r\nIn tabelul de mai jos se afla sugestii privind algoritmii care trebuie sa se gaseasca sub forma de probleme in arhiva educationala. Puteti veni oricand cu propuneri si sugestii de probleme noi pe \"forum\":/forum/index.php?topic=3401.0.\r\n\r\ntable(example). |_. Denumire problema|_. Categoria|\r\n|Submultimi|Backtracking|\r\n|Knapsack|Programare dinamica|\r\n|NIM|Teoria jocurilor|\r\n|Sprague-Grundy|Teoria jocurilor|\r\n|Algoritmul lui Gauss|Matematica|\r\n|Numerele lui Stirling|Matematica|\r\n|Problema de acoperire|Programare dinamica + Backtracking|\r\n|Algoritmul Stoer-Wagner|Algoritmi pe grafuri|\r\n|Heavy Path Decomposition|Algoritmi pe grafuri|\r\n|Arbore -> cod Prufer|Algoritmi pe grafuri|\r\n|Cod Prufer -> arbore|Algoritmi pe grafuri|\r\n|Distanta maxima intre 2 noduri intr-un arbore|Algoritmi pe grafuri|\r\n|Siruri de sufixe|Siruri de caractere|\r\n|Arbori de sufixe|Siruri de caractere|\r\n|Automate - Aho Corasick|Siruri de caractere|\r\n|Arbori de intervale aplicatie 1|Structuri de date|\r\n|Arbori de intervale aplicatie 2|Structuri de date|\r\n|Arbori de intervale aplicatie 3|Structuri de date|\r\n|Arbori de intervale aplicatie 4|Structuri de date|\r\n|Algoritmi {$O(sqrtN)$}|Structuri de date|\r\n|Ortogonal Range Search|Structuri de date|\r\n|Aria unui poligon|Geometrie|\r\n|Intersectia a doua drepte|Geometrie|\r\n|Punct in poligon|Geometrie|\r\n|Punct in poligon convex|Geometrie|\r\n|Diagrame Voronoi|Geometrie|\r\n|Distanta minima intre doua puncte in plan|Geometrie|\r\n|Distanta maxima intre doua puncte in plan|Geometrie|\r\n|Minimum enclosing circle|Geometrie|\r\n|Sortare prin numarare|Diverse|\r\n|RadixSort|Diverse|\r\n|Interclasarea a doi vectori sortati|Diverse|\r\n|Operatii pe numere mari|Diverse|\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"61\")==',3146,'protected',NULL,NULL),('algoritmiada-2010/runda-2/solutii','Solutii Algoritmiada 2010 Runda 2','2009-11-28 15:29:53','2009-11-28 15:34:44','h1. Solutii Algoritmiada 2010, Runda 2\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n\r\n',1792,'private',NULL,NULL),('implica-te/scrie-articole','Scrie articole','2007-03-28 22:23:46','2009-12-21 17:16:51','h1. Scrie articole ==Stars(rating=\"4\")==\r\n\r\nFolosind modelul de \'wiki\':documentatie/wiki, infoarena ofera sansa tuturor membrilor sai sa contribuie la realizarea de articole sau la imbunatatirea celor existente. Daca vrei sa afli mai multe despre conceptul de wiki intra \'aici\':http://en.wikipedia.org/wiki/Wiki, iar daca vrei sa contribui la acesta initiativa citeste mai jos ce trebuie sa faci.\r\n\r\nh2. De ce m-as baga?\r\n\r\n* O cariera in cercetare in informatica poate debuta cu niste articole online!\r\n* Vei invata care sunt elementele cheie pentru a scrie un articol.\r\n* Vei invata pe altii ceea ce stii, asa cum probabil si tu ai invatat din articolele deja \'existente\':articole.\r\n\r\nh2. Ce pot sa fac?\r\n\r\nDe-a lungul timpului, utilizatorii infoarena si-au manifestat interesul in a scrie articole pentru intreaga comunitate. In momentul de fata ne concentram eforturile atat pe completarea si aducerea la o forma prezentabila a acestor articole vechi, cat si pe scrierea de articole noi. Sunt 3 moduri in care poti contribui:\r\n\r\nh3. 1. Ajuta-ne la ce lucram acum\r\n\r\nIn tabelul de mai jos poti gasi articolele incepute, impreuna cu stadiul in care se gaseste fiecare. Daca esti dornic sa ne ajuti, alege-ti unul din articolele de care nu se ocupa nimeni si ia legatura cu coordonatorul proiectului ca sa afli ce mai e de facut la el.\r\n\r\ntable. |_. Titlu |_. Autor |_. Stadiu |_. Voluntar(i) |\r\n| \'Flux si cuplaj\':flux-si-cuplaj | ==user(user=\"blasterz\" type=\"tiny\")== | IN LUCRU | ==user(user=\"blasterz\" type=\"tiny\")== |\r\n| \'Teoria jocurilor\':teoria-jocurilor | ==user(user=\"filipb\" type=\"tiny\")== | IN LUCRU | ==user(user=\"filipb\" type=\"tiny\")== |\r\n| \'Psihologia concursurilor de informatica - Lucrul cu numere mari\':lucrul-cu-nr-mari | ==user(user=\"cata00\" type=\"tiny\")== | IMBUNATATIRE CONTINUT | ? |\r\n| Psihologia concursurilor de informatica - Lucrul cu structuri mari de date | ==user(user=\"cata00\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| Psihologia concursurilor de informatica - Probleme de concurs | ==user(user=\"cata00\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Probleme de taietura\':probleme-de-taietura | ==user(user=\"Cosmin\" type=\"tiny\")== | ÎN LUCRU | ? |\r\n| \'Transformari geometrice\':downloads?action=download&file=transformari_geometrice.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | ÎN LUCRU |  ==user(user=\"Marius\" type=\"tiny\")== |\r\n| \'Notiuni de geometrie analitica si aplicatii\':notiuni-de-geometrie-si-aplicatii | ==user(user=\"devilkind\" type=\"tiny\")== \r\n==user(user=\"sima_cotizo\" type=\"tiny\")== | IMBUNATATIRE CONTINUT | ? |\r\n\r\nh3. 2. Preia si dezvolta un subiect mai vechi\r\n\r\nAi nevoie de un impuls pentru a-ti da drumul la scris? Sunt cateva articole pe infoarena incepute, dar abandonate, precum si niste schite. Poti folosi ideile de start ale autorului si il poti transforma intr-un articol bine documentat. In plus, poti lua legatura cu autorul initial si poti afla viziunea sa asupra subiectului. Iata o lista de articole abandonate si de schite:\r\n\r\ntable. |_. Titlu |_. Autor initial |\r\n| Programare dinamica / memoizare (trading space for time): \'link1\':programare-dinamica, \'link2\':pd | ==user(user=\"Zeus\" type=\"tiny\")== |\r\n| \'Arbori indexati binar\':aib | ==user(user=\"Skipy\" type=\"tiny\")== |\r\n| \'Dinic\':dinic | ==user(user=\"alexandru.mosoi\" type=\"tiny\")== |\r\n| \'Probleme de geometrie si solutii\':downloads?geometrie.zip | ==user(user=\"Cosmin\" type=\"tiny\")== |\r\n| \'Diagrame Voronoi\':voronoi | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| \'Algoritmi de baleiere\':algoritmi-de-baleiere | ==user(user=\"stef2n\" type=\"tiny\")== |\r\n\r\nh3. 3. Creeaza ceva nou\r\n\r\nAi o idee noua de articol? Sau pur si simplu vrei sa te apuci de la 0 de un subiect? Ia legatura cu coordonatorul proiectului sau anunta pe \'forum\':forum. Este posibil sa primesti ajutor si de la alti utilizatori infoarena. In plus, noi iti propunem o lista de articole pe care ni le-am dori scrise, in caz ca nu te-ai decis asupra temei:\r\n\r\ntable. |_. Titlu |\r\n| Depanarea programelor C/C++ cu gdb in Linux |\r\n| Testarea surselor in timp de concurs sau Cum sa reduci buselile |\r\n| Tutorial LaTeX |\r\n\r\nNe rezervam dreptul sa nu acceptam sau sa stergem articolele care nu se potrivesc cu tema si target-ul site-ului.\r\n\r\nh2. Cu cine iau legatura?\r\n\r\nCu coordonatorul proiectului:\r\n\r\n* ==user(user=\"Marius\" type=\"tiny\")==\r\n\r\nSau daca vrei sa contribui la un articol la care se lucreaza deja, poti vorbi direct cu voluntarii care se ocupa de el.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"43\")==',3146,'public',NULL,NULL),('algoritmiada-2010/runda-2/solutii/recurenta2','Recurenta2','2009-12-20 13:54:47','2009-12-21 21:15:26','h1(#recurenta2). \'Recurenta2\':problema/recurenta2\r\n\r\nNotăm $S{~i~} = 1*X{~1~} + 2*X{~2~} + ... + i*X{~i~}$. Recurenta pentru $S{~i~}$ este usor de gasit: $S{~i+1~} = S{~i~} + (i+1)*X{~i+1~}$. Putem sa-l explicitam pe $X{~i+1~}$ in functie de termenii anteriori si obtinem: $S{~i+1~} = S{~i~} + (i+1)*X{~i-1~}*B + (i+1)*X{~i~}*A + (i+1)*C$. Asadar, observam ca la pasul $i$ nu ne dorim sa cunoastem doar $X{~i-1~}$, $X{~i~}$ si $S{~i~}$, ci si de $(i+1)*X{~i-1~}$ si $(i+1)*X{~i~}$. Recurentele pentru acesti $2$ noi termeni sunt usor de gasit: $(i+1)*X{~i-1~} = i*X{~i-1~} + X{~i-1~}$, iar $(i+1)*X{~i~} = i*X{~i~} + X{~i~} = X{~i-2~}*A + i*X{~i-1~}*B + i*C + X{~i-2~}*A + X{~i-1~}*B + C$. Observam ca putem aseza aseza aceste recurente in urmatoarea matrice de trecere de la pasul $i-1$ la pasul $i$:\r\n\r\n<tex>\\begin{pmatrix} X_{i-2} & X_{i-1} & 1 & S_{i-1} & i*X_{i-2} & i*X_{i-1}& i \\end{pmatrix} * \\begin{pmatrix} 0 & B & 0 & 0 & 0 & B & 0 \\\\ 1 & A & 0 & 0 & 1 & A & 0 \\\\ 0 & C & 1 & 0 & 0 & C & 1 \\\\ 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & B & 0 & B & 0 \\\\ 0 & 0 & 0 & A & 1 & A & 0 \\\\ 0 & 0 & 0 & C & 0 & C & 1 \\end{pmatrix}  = </tex>\r\n\r\n<tex> \\begin{pmatrix} X_{i-1} & X_{i} & 1 & S_{i} & (i+1)*X_{i-1} & (i+1)*X_{i}& i+1 \\end{pmatrix}</tex>.',1792,'public',NULL,NULL),('algoritmiada-2010/runda-2/solutii/recurenta2','Recurenta2','2009-12-20 13:54:47','2009-12-21 21:27:00','h1(#recurenta2). \'Recurenta2\':problema/recurenta2\r\n\r\nNotăm $S{~i~} = 1*X{~1~} + 2*X{~2~} + ... + i*X{~i~}$. Recurenţa pentru $S{~i~}$ este uşor de găsit: $S{~i+1~} = S{~i~} + (i+1)*X{~i+1~}$. Putem să-l explicităm pe $X{~i+1~}$ în funcţie de termenii anteriori şi obţinem: $S{~i+1~} = S{~i~} + (i+1)*X{~i-1~}*B + (i+1)*X{~i~}*A + (i+1)*C$. Aşadar, observăm că la pasul $i$ nu ne dorim să cunoaştem doar valorile $X{~i-1~}$, $X{~i~}$ şi $S{~i~}$, ci şi pe $(i+1)*X{~i-1~}$ şi $(i+1)*X{~i~}$. Recurenţele pentru aceşti $2$ noi termeni sunt şi ele uşor de găsit: $(i+1)*X{~i-1~} = i*X{~i-1~} + X{~i-1~}$, iar $(i+1)*X{~i~} = i*X{~i~} + X{~i~} = X{~i-2~}*A + i*X{~i-1~}*B + i*C + X{~i-2~}*A + X{~i-1~}*B + C$. Observăm că putem aşeza aceste recurenţe în urmatoarea matrice de trecere de la pasul $i-1$ la pasul $i$:\r\n\r\n<tex>\\begin{pmatrix} X_{i-2} & X_{i-1} & 1 & S_{i-1} & i*X_{i-2} & i*X_{i-1}& i \\end{pmatrix} *</tex><tex>\\begin{pmatrix} 0 & B & 0 & 0 & 0 & B & 0 \\\\ 1 & A & 0 & 0 & 1 & A & 0 \\\\ 0 & C & 1 & 0 & 0 & C & 1 \\\\ 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & B & 0 & B & 0 \\\\ 0 & 0 & 0 & A & 1 & A & 0 \\\\ 0 & 0 & 0 & C & 0 & C & 1 \\end{pmatrix} </tex><tex>= \\begin{pmatrix} X_{i-1} & X_{i} & 1 & S_{i} & (i+1)*X_{i-1} & (i+1)*X_{i}& i+1 \\end{pmatrix}</tex>.\r\n\r\nPutem aplica proprietatea de asociativitate a înmulţirii matricilor şi să înmulţim matricea de trecere cu ea însăşi de $N$ ori şi abia după aceea să înmulţim matricea iniţială cu matricea rezultată. Complexitatea totală este $O(logN)$, folosind \'exponenţierea în timp logaritmic\':problema/lgput.',1792,'public',NULL,NULL),('articole/template-solutii','articole/template-solutii','2008-12-13 14:45:42','2009-11-23 17:37:08','* !>articole/template-solutii?algoritmiada-2010.jpg! \'Algoritmiada 2010, Runda 1\':algoritmiada-2010/runda-1/solutii\r\n* \'Summer Challenge 2009, Runda 3\':summer-challenge-2009/solutii/runda-3\r\n* \'Summer Challenge 2009, Runda 2\':summer-challenge-2009/solutii/runda-2\r\n* \'Summer Challenge 2009, Runda 1\':summer-challenge-2009/solutii/runda-1\r\n* \'Grigore Moisil 2009\':grigore-moisil-2009/solutii\r\n* !>articole/template-solutii?algoritmiada-2009.jpg! \'Algoritmiada 2009, Runda 3\':algoritmiada-2009/runda-3/solutii\r\n* \'Algoritmiada 2009, Runda 2\':algoritmiada-2009/runda-2/solutii\r\n* \'Algoritmiada 2009, Runda 1\':algoritmiada-2009/runda-1/solutii\r\n* \'Junior Challenge 2008\':junior-challenge-2008/solutii\r\n* \'Grigore Moisil 2008\':grigore-moisil-2008/solutii\r\n* \'preONI 2008, Runda finala\':preoni-2008/runda-finala/solutii\r\n* !>articole/template-solutii?preoni-2008.jpg! \'preONI 2008, Runda 4\':preoni-2008/runda-4/solutii\r\n* \'preONI 2008, Runda 3\':preoni-2008/runda-3/solutii\r\n* \'preONI 2008, Runda 2\':preoni-2008/runda-2/solutii\r\n* \'preONI 2008, Runda 1\':preoni-2008/runda-1/solutii\r\n*{display: %display%} \'Winter Challenge 2008, Runda 2\':winter-challenge-2008/runda-2/solutii\r\n*{display: %display%} \'Winter Challenge 2008, Runda 1\':winter-challenge-2008/runda-1/solutii\r\n*{display: %display%} \'Happy Coding 2007\':happy-coding-2007/solutii\r\n*{display: %display%} \'Autumn Warmup 2007 runda 3\':autumn-warmup-2007/solutii/runda-3\r\n*{display: %display%} \'Autumn Warmup 2007 runda 2\':autumn-warmup-2007/solutii/runda-2\r\n*{display: %display%} \'Autumn Warmup 2007 runda 1\':autumn-warmup-2007/solutii/runda-1\r\n*{display: %display%} \'Summer Challenge 2007 runda #3\':summer-challenge-2007/solutii/runda-3\r\n*{display: %display%} \'Summer Challenge 2007 runda #2\':summer-challenge-2007/solutii/runda-2\r\n*{display: %display%} \'Summer Challenge 2007 runda #1\':summer-challenge-2007/solutii/runda-1\r\n*{display: %display%} \'Junior Challenge 2007\':junior-challenge/solutii\r\n*{display: %display%} !>articole/template-solutii?preoni-2007.jpg! \'preONI 2007 runda finala - solutii\':preoni-2007/runda-finala/solutii\r\n*{display: %display%} \'preONI 2007 runda #4 - solutii\':preoni-2007/runda-4/solutii\r\n*{display: %display%} \'preONI 2007 runda #3 - solutii\':preoni-2007/runda-3/solutii\r\n*{display: %display%} \'preONI 2007 runda #2 - solutii\':preoni-2007/runda-2/solutii\r\n*{display: %display%} \'preONI 2007 runda #1 - solutii\':preoni-2007/runda-1/solutii\r\n*{display: %display%} \'Winter Challenge 1\':winter-challenge-1/solutii\r\n*{display: %display%} \'Unirea 2007\':unirea-2007/solutii\r\n*{display: %display%} \'Solutii Autumn WarmUp 2006\':warm-up-2006/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Trei\':summer-challenge-3/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Doi\':summer-challenge-2/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Unu\':summer-challenge-unu/solutii\r\n*{display: %display%} !>articole/template-solutii?preoni-2006.gif! \'Solutii preONI 2006, Runda finala\':preoni-2006/finala/solutii\r\n*{display: %display%} \'Solutii preONI 2006, Runda a 4-a\':preoni-2006/runda-4/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda a 3-a\':preoni-2006/runda-3/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda a 2-a\':preoni-2006/runda-2/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda 1\':preoni-2006/runda-1/solutii\r\n*{display: %display%} \'preONI 2005 runda #3 - solutii\':preoni-2005/runda-3/solutii\r\n*{display: %display%} \'preONI 2005 runda #2 - solutii\':preoni-2005/runda-2/solutii\r\n*{display: %display%} \'preONI 2005 runda #1 - solutii\':preoni-2005/runda-1/solutii\r\n*{display: %display%} \'Happy Coding 3 [2006]\':happy-coding-2006/solutii\r\n*{display: %display%} \'Happy Coding 2 [2005]\':happy-coding-2005-2/solutii\r\n*{display: %display%} \'Happy Coding 1 [2005]\':happy-coding-2005-1/solutii\r\n*{display: %display%} \'Concursul Agora - Etapa Finala - Solutii\':agora-finala/solutii\r\n*{display: %display%} \'Doua probleme de la runda 6 a concursului Algoritmus\':doua-probleme-de-la-runda-6-a-concursului-algoritmus\r\n*{display: %display%} \'USACO dec 2005, divizia GOLD\':usaco-dec-2005-divizia-gold \r\n*{display: %display%} \'USACO nov 2005, divizia GOLD\':usaco-nov-2005-divizia-gold\r\n*{display: %display%} \'USACO oct 2005, divizia GOLD\':usaco-oct-2005-divizia-gold\r\n*{display: %display%} \'USACO ian 2005, divizia GOLD\':usaco-ian-2005-divizia-gold\r\n*{display: %display%} \'USACO dec 2004, divizia GOLD\':usaco-dec-2004-divizia-gold\r\n*{display: %display%} \'Solutiile oficiale pentru Concursul &quot;de incalzire&quot;\':warm-up-2004/solutii',2044,'protected',NULL,NULL),('implica-te/arhiva-educationala','Arhiva Educationala','2008-02-23 13:13:01','2009-12-21 08:19:08','h1. Arhiva educationala ==Stars(rating=\"5\")==\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie. Mai multe despre acest proiect gasiti \'aici\':propuneri/6-arhiva-educationala.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Cum ne poti ajuta?\':implica-te/arhiva-educationala#cum\r\n* \'Echipa implicata in proiect\':implica-te/arhiva-educationala#echipa\r\n* \'Documentatie\':implica-te/arhiva-educationala#documentatie\r\n* \'Continutul arhivei\':implica-te/arhiva-educationala#probleme\r\n\r\nh2(#cum). Cum ne poti ajuta?\r\n\r\n1. Ofera sugestii la dezvoltarea proiectului.\r\n2. Contribuie cu feedback pentru a imbunatati calitatea problemelor existente.\r\n3. Vino cu idei pentru probleme noi.\r\n\r\nAjuta si tu la randul tau comunitatea infoarena! \r\n\r\nh2(#echipa). Echipa implicata in proiect\r\n\r\nEchipa care este implicata activ in acest proiect este alcatuita din urmatorii membri...\r\n\r\n* == user(user=\"Marius\" type=\"tiny\") ==, coordonator de proiect\r\n* == user(user=\"savim\" type=\"tiny\") ==\r\n* == user(user=\"cezarmocan\" type=\"tiny\") ==\r\n* == user(user=\"GavrilaVlad\" type=\"tiny\") ==\r\n* == user(user=\"mishu91\" type=\"tiny\") ==\r\n* == user(user=\"GheorgheMihai\" type=\"tiny\") ==\r\n\r\n\'Multumim celor care ne-au ajutat pana acum.\':implica-te/arhiva-educationala/membri-emeritus\r\n\r\nh2(#documentatie). Documentatie\r\n\r\nFiecare voluntar are obligatia sa citeasca urmatoarele materiale inainte de a putea trece efectiv la lucru:\r\n\r\n* \'Editare de probleme\':documentatie/editare-de-probleme\r\n* \'Ghid evaluator\':documentatie/ghid-evaluator\r\n* \'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala\r\n\r\nh2(#probleme). Continutul arhivei\r\n\r\nIn tabelul de mai jos se afla probleme la care se lucreaza in momentul de fata. Finalizarea lor reprezinta unul dintre $OKR$-urile din trimestrul IV, 2009. Pentru a va familiariza si cu restul obiectivelor din acest trimestru, cititi \'aici\':okr.\r\n\r\ntable(example). |_. Denumire problema|_. Voluntar|_. Finalizat|_. Review |\r\n| \'Cuplaj maxim de cost minim\':problema/cmcm | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Principiul includerii si excluderii\':problema/pinex | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Huffman\':problema/huffman | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| Algoritmul Bellman-Ford | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'2SAT\':problema/2sat | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Al K-lea termen Fibonacci - Matrici\':problema/kfib | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Lowest Common Ancestor\':problema/lca | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Statistici de ordine\':problema/sdo | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Parantezare optima de matrici\':problema/podm | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Treapuri\':problema/treapuri | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Ciclu hamiltonian | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Submulţimi\':problema/submultimi | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa minimă între două puncte în plan\':problema/cmap | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa maximă între două puncte în plan\':problema/cmdp | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n\r\nIn tabelul de mai jos se afla sugestii privind algoritmii care trebuie sa se gaseasca sub forma de probleme in arhiva educationala. Puteti veni oricand cu propuneri si sugestii de probleme noi pe \"forum\":/forum/index.php?topic=3401.0.\r\n\r\ntable(example). |_. Denumire problema|_. Categoria|\r\n|Knapsack|Programare dinamica|\r\n|NIM|Teoria jocurilor|\r\n|Sprague-Grundy|Teoria jocurilor|\r\n|Algoritmul lui Gauss|Matematica|\r\n|Numerele lui Stirling|Matematica|\r\n| Principiul lui Dirichlet | Matematică |\r\n| Numărul (şi suma) divizorilor unui număr natural | Matematică |\r\n|Problema de acoperire|Programare dinamica + Backtracking|\r\n|Algoritmul Stoer-Wagner|Algoritmi pe grafuri|\r\n|Heavy Path Decomposition|Algoritmi pe grafuri|\r\n|Arbore -> cod Prufer|Algoritmi pe grafuri|\r\n|Cod Prufer -> arbore|Algoritmi pe grafuri|\r\n|Distanta maxima intre 2 noduri intr-un arbore|Algoritmi pe grafuri|\r\n|Siruri de sufixe|Siruri de caractere|\r\n|Arbori de sufixe|Siruri de caractere|\r\n|Automate - Aho Corasick|Siruri de caractere|\r\n|Arbori de intervale aplicatie 1|Structuri de date|\r\n|Arbori de intervale aplicatie 2|Structuri de date|\r\n|Arbori de intervale aplicatie 3|Structuri de date|\r\n|Arbori de intervale aplicatie 4|Structuri de date|\r\n|Algoritmi {$O(sqrtN)$}|Structuri de date|\r\n|Ortogonal Range Search|Structuri de date|\r\n|Aria unui poligon|Geometrie|\r\n|Intersectia a doua drepte|Geometrie|\r\n|Punct in poligon|Geometrie|\r\n|Punct in poligon convex|Geometrie|\r\n|Diagrame Voronoi|Geometrie|\r\n|Minimum enclosing circle|Geometrie|\r\n|Sortare prin numarare|Diverse|\r\n|RadixSort|Diverse|\r\n|Interclasarea a doi vectori sortati|Diverse|\r\n|Operatii pe numere mari|Diverse|\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"61\")==',3146,'protected',NULL,NULL),('implica-te/scrie-articole','Scrie articole','2007-03-28 22:23:46','2009-12-26 23:10:49','h1. Scrie articole ==Stars(rating=\"4\")==\r\n\r\nFolosind modelul de \'wiki\':documentatie/wiki, infoarena ofera sansa tuturor membrilor sai sa contribuie la realizarea de articole sau la imbunatatirea celor existente. Daca vrei sa afli mai multe despre conceptul de wiki intra \'aici\':http://en.wikipedia.org/wiki/Wiki, iar daca vrei sa contribui la acesta initiativa citeste mai jos ce trebuie sa faci.\r\n\r\nh2. De ce m-as baga?\r\n\r\n* O cariera in cercetare in informatica poate debuta cu niste articole online!\r\n* Vei invata care sunt elementele cheie pentru a scrie un articol.\r\n* Vei invata pe altii ceea ce stii, asa cum probabil si tu ai invatat din articolele deja \'existente\':articole.\r\n\r\nh2. Ce pot sa fac?\r\n\r\nDe-a lungul timpului, utilizatorii infoarena si-au manifestat interesul in a scrie articole pentru intreaga comunitate. In momentul de fata ne concentram eforturile atat pe completarea si aducerea la o forma prezentabila a acestor articole vechi, cat si pe scrierea de articole noi. Sunt 3 moduri in care poti contribui:\r\n\r\nh3. 1. Ajuta-ne la ce lucram acum\r\n\r\nIn tabelul de mai jos poti gasi articolele incepute, impreuna cu stadiul in care se gaseste fiecare. Daca esti dornic sa ne ajuti, alege-ti unul din articolele de care nu se ocupa nimeni si ia legatura cu coordonatorul proiectului ca sa afli ce mai e de facut la el.\r\n\r\ntable. |_. Titlu |_. Autor |_. Stadiu |_. Voluntar(i) |\r\n| \'Probleme de taietura\':probleme-de-taietura | ==user(user=\"Cosmin\" type=\"tiny\")== | ÎN LUCRU | ==user(user=\"Marius\" type=\"tiny\")== |\r\n| \'Transformari geometrice\':transformari-geometrice | ==user(user=\"Cosmin\" type=\"tiny\")== | ÎN LUCRU |  ==user(user=\"Marius\" type=\"tiny\")== |\r\n| \'Optimizarea programelor folosind operaţii pe biţi\':http://www.google.ro/url?sa=t&source=web&ct=res&cd=3&ved=0CBIQFjAC&url=http%3A%2F%2Fwww.ginfo.ro%2Frevista%2F14_5%2Ffocus.pdf&rct=j&q=opera%C5%A3ii+pe+bi%C5%A3i+cosmin+negru%C5%9Feri&ei=yqcuS7ndB5CUmAOts7yKCQ&usg=AFQjCNEkRFe0NcETCbGQYtwxtZiLl6-lIQ&sig2=u4zPps2-woQOLMdbRDyM4A | ==user(user=\"Cosmin\" type=\"tiny\")==  | ÎN LUCRU | ==user(user=\"gheorghemihai\" type=\"tiny\")== |\r\n| \'Arborele componentelor biconexe şi al nodurilor critice\':http://infoarena.ro/downloads?action=download&file=arborele_componentelor_biconexe_si_al_nodurilor_critice.doc&safe_only=false | ==user(user=\"mugurelionut\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Algoritmi de flux maxim în reţele\':http://infoarena.ro/downloads?action=download&file=flux_maxim_in_retele.doc&safe_only=false | ==user(user=\"mugurelionut\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Tehnici avansate de programare dinamică\':pd | ==user(user=\"Zeus\" type=\"tiny\")== | ÎN LUCRU | ==user(user=\"Zeus\" type=\"tiny\")== |\r\n\r\nh3. 2. Preia si dezvolta un subiect mai vechi\r\n\r\nAi nevoie de un impuls pentru a-ti da drumul la scris? Sunt cateva articole pe infoarena incepute, dar abandonate, precum si niste schite. Poti folosi ideile de start ale autorului si il poti transforma intr-un articol bine documentat. In plus, poti lua legatura cu autorul initial si poti afla viziunea sa asupra subiectului. Iata o lista de articole abandonate si de schite:\r\n\r\ntable. |_. Titlu |_. Autor initial |\r\n| Programare dinamica / memoizare (trading space for time): \'link1\':programare-dinamica | ==user(user=\"Zeus\" type=\"tiny\")== |\r\n| \'Arbori indexati binar\':aib | ==user(user=\"Skipy\" type=\"tiny\")== |\r\n| \'Dinic\':dinic | ==user(user=\"alexandru.mosoi\" type=\"tiny\")== |\r\n| \'Probleme de geometrie si solutii\':downloads?geometrie.zip | ==user(user=\"Cosmin\" type=\"tiny\")== |\r\n| \'Flux si cuplaj\':flux-si-cuplaj | ==user(user=\"blasterz\" type=\"tiny\")== |\r\n| \'Teoria jocurilor\':teoria-jocurilor | ==user(user=\"filipb\" type=\"tiny\")== |\r\n| \'Psihologia concursurilor de informatica - Lucrul cu numere mari\':lucrul-cu-nr-mari | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| Psihologia concursurilor de informatica - Lucrul cu structuri mari de date | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| Psihologia concursurilor de informatica - Probleme de concurs | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| \'Notiuni de geometrie analitica si aplicatii\':notiuni-de-geometrie-si-aplicatii | ==user(user=\"devilkind\" type=\"tiny\")== \r\n==user(user=\"sima_cotizo\" type=\"tiny\")== |\r\n| \'Diagrame Voronoi\':voronoi | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| \'Algoritmi de baleiere\':algoritmi-de-baleiere | ==user(user=\"stef2n\" type=\"tiny\")== |\r\n\r\nh3. 3. Creeaza ceva nou\r\n\r\nAi o idee noua de articol? Sau pur si simplu vrei sa te apuci de la 0 de un subiect? Ia legatura cu coordonatorul proiectului sau anunta pe \'forum\':forum. Este posibil sa primesti ajutor si de la alti utilizatori infoarena. In plus, noi iti propunem o lista de articole pe care ni le-am dori scrise, in caz ca nu te-ai decis asupra temei:\r\n\r\ntable. |_. Titlu |\r\n| Depanarea programelor C/C++ cu gdb in Linux |\r\n| Testarea surselor in timp de concurs sau Cum sa reduci buselile |\r\n| Tutorial LaTeX |\r\n\r\nNe rezervam dreptul sa nu acceptam sau sa stergem articolele care nu se potrivesc cu tema si target-ul site-ului.\r\n\r\nh2. Cu cine iau legatura?\r\n\r\nCu coordonatorul proiectului:\r\n\r\n* ==user(user=\"Marius\" type=\"tiny\")==\r\n\r\nSau daca vrei sa contribui la un articol la care se lucreaza deja, poti vorbi direct cu voluntarii care se ocupa de el.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"43\")==',3146,'public',NULL,NULL),('operatii-pe-biti','Operaţii pe biţi','2009-12-27 10:45:16','2009-12-27 14:57:53','h1. Operaţii pe biţi\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"GheorgheMihai\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\nÎn cadrul acestui articol vă vom prezenta câteva metode prin care programele se pot optimiza dacă utilizăm eficient operaţiile pe biţi sau folosim operaţii pe biţi în locuri în care, la prima vedere, nu s-ar părea că ar fi necesare.\r\n\r\nDe cele mai multe ori, atât în concursuri cât şi în viaţa de zi cu zi a programatorului, atunci când implementăm o metodă care este folosită de o aplicaţie şi vrem să facem această metodă eficientă ca timp de execuţie, suntem învăţaţi din şcoală (sau ar trebui sã fim învăţaţi, chiar dacă unii dintre profesori consideră că cel mai important algoritm învăţat în liceu este _backtraking_-ul, soluţia tuturor problemelor) să ne uităm la complexitatea algoritmului implementat şi dacă observăm că în practică algoritmul este mai încet decât ne dorim noi să fie să încercăm să găsim un algoritm cu un ordin de complexitate mai mic.\r\n\r\nNu trebuie să uităm că ceea ce numim complexitatea unui algoritm este o aproximare a vitezei unui algoritm şi nu o măsură absolută. Pentru dimensiuni mici ale datelor, câteodată nu se observă diferenţă dintre $O(n)$ şi $O(n · log n)$ sau $O(n^3/2^)$. Mie personal mi s-a întâmplat ca la implementarea soluţiei unei probleme care în engleză se numeşte \"_Bottleneck Minimal Spanning Tree_\" să observ că rezolvarea în $O(m · log m)$ (folosind algoritmul de găsire a arborelui parţial de cost minim al lui Kruskal) să fie mai rapidă decât rezolvarea mai laborioasă în $O(m)$ a acestei probleme. Deci trebuie dată o atenţie egală cu cea acordată complexităţii algoritmului şi dimensiunii factorilor constanţi care apar.\r\n\r\nÎn continuare vom încerca să găsim soluţii mai rapide decât cele naive pentru unele operaţii de bază (toate operaţiile vor fi implementate pentru întregi pozitivi reprezentaţi pe 32 de biţi).\r\n\r\nh2. Aplicaţia #1\r\n\r\nbq. Să se determine numărul de biţi de 1 din reprezentarea binară a lui $n$.\r\n\r\nh3. Rezolvare\r\n\r\nRezolvarea naivă a acestei probleme ar consta în parcurgerea secvenţială a biţilor lui n. În continuare vă prezint această rezolvare:\r\n==code(cpp)|\r\nint count(long n){\r\n  int num = 0;\r\n  for (int i = 0; i < 32; i++)\r\n     if (n & (1 << i)) num++;\r\n  return num;\r\n}\r\n==\r\n\r\nDacă ne uităm cu atenţie şi analizăm rezultatul operaţiei $n & (n - 1)$ putem obţine o soluţie mai bună. Să luăm un exemplu:\r\n$n           = 11011101010000{~2~}$\r\n$n - 1       = 11011101001111{~2~}$\r\n$n & (n - 1) = 11011101000000{~2~}$\r\n\r\nSe vede clar de aici că efectul operaţiei $n & (n - 1)$ este anularea celui mai nesemnificativ bit cu valoarea 1.\r\nDe aici ideea algoritmului:\r\n==code(cpp)|\r\nint count(long n){\r\n   int num = 0;\r\n   if (n)\r\n      while (n &= n - 1) num++;\r\n   return num;\r\n}\r\n==\r\n\r\nDar este acest algoritm mai rapid? Am testat pentru toate numerele de la $1$ la $2^24^$ şi rezultatele au fost $2,654$ secunde folosind metoda naivă şi $0.821$ folosind a doua metodă.\r\nRezultatul mult mai bun al celei de-a doua metode se bazează în principal pe faptul că ea execută un număr de paşi egali cu numărul de biţi cu valoarea 1 din număr, deci în medie jumătate din numărul de paşi efectuaţi de prima metodă.\r\n\r\nh2. Aplicaţia #2\r\n\r\nbq. Să se determine paritatea numărului de biţi de 1 din reprezentarea binară a unui număr $n$.\r\n\r\nh3. Rezolvare\r\n\r\nDin cele prezentate mai sus se pot determina două metode evidente:\r\n==code(cpp)|\r\nint parity(long n){\r\n  int num = 0;\r\n  for (int i = 0; i < 32; i++)\r\n     if (n & (1 << i)) num ^= 1;\r\n  return num;\r\n}\r\n==\r\n\r\n==code(cpp)|\r\nint parity(long n){\r\n   int num = 0;\r\n   if (n)\r\n      while (n &= n - 1) num ^= 1;\r\n   return num;\r\n}\r\n==\r\n\r\nPutem obţine o a treia rezolvare făcând câteva observaţii pe un exemplu:\r\nConsiderăm $n = 11011011{~2~}$. Rezultatul căutat este dat de valoarea @1 ^ 1 ^ 0 ^ 1 ^ 1 ^ 0 ^ 1 ^ 1@.\r\nÎmpărţim pe n în partea lui superioară şi partea lui inferioară:\r\n1 1 0 1 ^ 1 0 1 1 = 0 1 1 0\r\nAplicăm asupra rezultatului acelaşi procedeu:\r\n0 1 ^ 1 0 = 1 1\r\nşi\r\n1 ^ 1 = 0\r\n\r\nSă scriem algoritmul care reiese din acest exemplu, luând în considerare faptul că numărul n este reprezentat pe 32 de biţi:\r\n==code(cpp)|\r\nint parity(long n){\r\n   n = ((0xFFFF0000 & n) >> 16) ^ (n & 0xFFFF);\r\n   n = ((0xFF00 & n) >> 8) ^ (n & 0xFF);\r\n   n = ((0xF0 & n) >> 4) ^ (n & 0xF);\r\n   n = ((12 & n) >> 2) ^ (n & 3);\r\n   n = ((2 & n) >> 1) ^ (n & 1);\r\n   return n;\r\n}\r\n==\r\n\r\nDeşi constanta multiplicativa este mai mare, numărul de operaţii are ordin logaritmic faţă de numărul de biţi ai unui cuvânt al calculatorului.\r\n\r\n\r\n',7148,'public',NULL,NULL),('runda/star_trek/clasament','Clasament star_trek','2009-03-29 14:24:54','2009-03-29 14:24:54','h1. Clasament ==roundparam(round_id=\"star_trek\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"star_trek\")==',8689,'round: star_trek',NULL,NULL),('implica-te/arhiva-educationala','Arhiva Educationala','2008-02-23 13:13:01','2010-01-03 16:41:35','h1. Arhiva educationala ==Stars(rating=\"5\")==\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie. Mai multe despre acest proiect gasiti \'aici\':propuneri/6-arhiva-educationala.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Cum ne poti ajuta?\':implica-te/arhiva-educationala#cum\r\n* \'Echipa implicata in proiect\':implica-te/arhiva-educationala#echipa\r\n* \'Documentatie\':implica-te/arhiva-educationala#documentatie\r\n* \'Continutul arhivei\':implica-te/arhiva-educationala#probleme\r\n\r\nh2(#cum). Cum ne poti ajuta?\r\n\r\n1. Ofera sugestii la dezvoltarea proiectului.\r\n2. Contribuie cu feedback pentru a imbunatati calitatea problemelor existente.\r\n3. Vino cu idei pentru probleme noi.\r\n\r\nAjuta si tu la randul tau comunitatea infoarena! \r\n\r\nh2(#echipa). Echipa implicata in proiect\r\n\r\nEchipa care este implicata activ in acest proiect este alcatuita din urmatorii membri...\r\n\r\n* == user(user=\"Marius\" type=\"tiny\") ==, coordonator de proiect\r\n* == user(user=\"savim\" type=\"tiny\") ==\r\n* == user(user=\"cezarmocan\" type=\"tiny\") ==\r\n* == user(user=\"GavrilaVlad\" type=\"tiny\") ==\r\n* == user(user=\"mishu91\" type=\"tiny\") ==\r\n* == user(user=\"GheorgheMihai\" type=\"tiny\") ==\r\n\r\n\'Multumim celor care ne-au ajutat pana acum.\':implica-te/arhiva-educationala/membri-emeritus\r\n\r\nh2(#documentatie). Documentatie\r\n\r\nFiecare voluntar are obligatia sa citeasca urmatoarele materiale inainte de a putea trece efectiv la lucru:\r\n\r\n* \'Editare de probleme\':documentatie/editare-de-probleme\r\n* \'Ghid evaluator\':documentatie/ghid-evaluator\r\n* \'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala\r\n\r\nh2(#probleme). Continutul arhivei\r\n\r\nIn tabelul de mai jos se afla probleme la care se lucreaza in momentul de fata. Finalizarea lor reprezinta unul dintre $OKR$-urile din trimestrul IV, 2009. Pentru a va familiariza si cu restul obiectivelor din acest trimestru, cititi \'aici\':okr.\r\n\r\ntable(example). |_. Denumire problema|_. Voluntar|_. Finalizat|_. Review |\r\n| \'Cuplaj maxim de cost minim\':problema/cmcm | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Principiul includerii si excluderii\':problema/pinex | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Huffman\':problema/huffman | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Algoritmul Bellman-Ford\':problema/bellmanford | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'2SAT\':problema/2sat | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Al K-lea termen Fibonacci - Matrici\':problema/kfib | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Lowest Common Ancestor\':problema/lca | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Statistici de ordine\':problema/sdo | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Parantezare optima de matrici\':problema/podm | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Treapuri\':problema/treapuri | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Ciclu hamiltonian | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Submulţimi\':problema/submultimi | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa minimă între două puncte în plan\':problema/cmap | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa maximă între două puncte în plan\':problema/cmdp | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n\r\nIn tabelul de mai jos se afla sugestii privind algoritmii care trebuie sa se gaseasca sub forma de probleme in arhiva educationala. Puteti veni oricand cu propuneri si sugestii de probleme noi pe \"forum\":/forum/index.php?topic=3401.0.\r\n\r\ntable(example). |_. Denumire problema|_. Categoria|\r\n|Knapsack|Programare dinamica|\r\n|NIM|Teoria jocurilor|\r\n|Sprague-Grundy|Teoria jocurilor|\r\n|Algoritmul lui Gauss|Matematica|\r\n|Numerele lui Stirling|Matematica|\r\n| Principiul lui Dirichlet | Matematică |\r\n| Numărul (şi suma) divizorilor unui număr natural | Matematică |\r\n|Problema de acoperire|Programare dinamica + Backtracking|\r\n|Algoritmul Stoer-Wagner|Algoritmi pe grafuri|\r\n|Heavy Path Decomposition|Algoritmi pe grafuri|\r\n|Arbore -> cod Prufer|Algoritmi pe grafuri|\r\n|Cod Prufer -> arbore|Algoritmi pe grafuri|\r\n|Distanta maxima intre 2 noduri intr-un arbore|Algoritmi pe grafuri|\r\n|Siruri de sufixe|Siruri de caractere|\r\n|Arbori de sufixe|Siruri de caractere|\r\n|Automate - Aho Corasick|Siruri de caractere|\r\n|Arbori de intervale aplicatie 1|Structuri de date|\r\n|Arbori de intervale aplicatie 2|Structuri de date|\r\n|Arbori de intervale aplicatie 3|Structuri de date|\r\n|Arbori de intervale aplicatie 4|Structuri de date|\r\n|Algoritmi {$O(sqrtN)$}|Structuri de date|\r\n|Ortogonal Range Search|Structuri de date|\r\n|Aria unui poligon|Geometrie|\r\n|Intersectia a doua drepte|Geometrie|\r\n|Punct in poligon|Geometrie|\r\n|Punct in poligon convex|Geometrie|\r\n|Diagrame Voronoi|Geometrie|\r\n|Minimum enclosing circle|Geometrie|\r\n|Sortare prin numarare|Diverse|\r\n|RadixSort|Diverse|\r\n|Interclasarea a doi vectori sortati|Diverse|\r\n|Operatii pe numere mari|Diverse|\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"61\")==',3146,'protected',NULL,NULL),('implica-te/arhiva-educationala','Arhiva Educationala','2008-02-23 13:13:01','2010-01-04 13:07:52','h1. Arhiva educationala ==Stars(rating=\"5\")==\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie. Mai multe despre acest proiect gasiti \'aici\':propuneri/6-arhiva-educationala.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Cum ne poti ajuta?\':implica-te/arhiva-educationala#cum\r\n* \'Echipa implicata in proiect\':implica-te/arhiva-educationala#echipa\r\n* \'Documentatie\':implica-te/arhiva-educationala#documentatie\r\n* \'Continutul arhivei\':implica-te/arhiva-educationala#probleme\r\n\r\nh2(#cum). Cum ne poti ajuta?\r\n\r\n1. Ofera sugestii la dezvoltarea proiectului.\r\n2. Contribuie cu feedback pentru a imbunatati calitatea problemelor existente.\r\n3. Vino cu idei pentru probleme noi.\r\n\r\nAjuta si tu la randul tau comunitatea infoarena! \r\n\r\nh2(#echipa). Echipa implicata in proiect\r\n\r\nEchipa care este implicata activ in acest proiect este alcatuita din urmatorii membri...\r\n\r\n* == user(user=\"Marius\" type=\"tiny\") ==, coordonator de proiect\r\n* == user(user=\"savim\" type=\"tiny\") ==\r\n* == user(user=\"cezarmocan\" type=\"tiny\") ==\r\n* == user(user=\"GavrilaVlad\" type=\"tiny\") ==\r\n* == user(user=\"mishu91\" type=\"tiny\") ==\r\n* == user(user=\"GheorgheMihai\" type=\"tiny\") ==\r\n\r\n\'Multumim celor care ne-au ajutat pana acum.\':implica-te/arhiva-educationala/membri-emeritus\r\n\r\nh2(#documentatie). Documentatie\r\n\r\nFiecare voluntar are obligatia sa citeasca urmatoarele materiale inainte de a putea trece efectiv la lucru:\r\n\r\n* \'Editare de probleme\':documentatie/editare-de-probleme\r\n* \'Ghid evaluator\':documentatie/ghid-evaluator\r\n* \'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala\r\n\r\nh2(#probleme). Continutul arhivei\r\n\r\nIn tabelul de mai jos se afla probleme la care se lucreaza in momentul de fata. Finalizarea lor reprezinta unul dintre $OKR$-urile din trimestrul IV, 2009. Pentru a va familiariza si cu restul obiectivelor din acest trimestru, cititi \'aici\':okr.\r\n\r\ntable(example). |_. Denumire problema|_. Voluntar|_. Finalizat|_. Review |\r\n| \'Cuplaj maxim de cost minim\':problema/cmcm | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Principiul includerii si excluderii\':problema/pinex | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| Arbori de intervale: creste valoarea fiecarui element \r\n  dintr-un interval cu x (update) si intreaba care e suma \r\n  elementelor dintr-un interval (query) | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Arbori de intervale: creste valoarea fiecarui element\r\n  dintr-un interval cu x (update) si intreaba care e \r\n  minimul/maximul elementelor dintr-un interval (query) | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Arbori de intervale: seteaza valoarea fiecarui element\r\n  dintr-un interval la x (update) si intreaba care e suma\r\n  elementelor dintr-un interval (query) | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Arbori de intervale: seteaza valoarea fiecarui element\r\n  dintr-un interval la x (update) si intreaba care e\r\n  minimul/maximul elementelor dintr-un interval (query) | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Huffman\':problema/huffman | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Algoritmul Bellman-Ford\':problema/bellmanford | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'2SAT\':problema/2sat | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Al K-lea termen Fibonacci - Matrici\':problema/kfib | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Lowest Common Ancestor\':problema/lca | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Statistici de ordine\':problema/sdo | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Parantezare optima de matrici\':problema/podm | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Treapuri\':problema/treapuri | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Ciclu hamiltonian | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Submulţimi\':problema/submultimi | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa minimă între două puncte în plan\':problema/cmap | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa maximă între două puncte în plan\':problema/cmdp | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n\r\nIn tabelul de mai jos se afla sugestii privind algoritmii care trebuie sa se gaseasca sub forma de probleme in arhiva educationala. Puteti veni oricand cu propuneri si sugestii de probleme noi pe \"forum\":/forum/index.php?topic=3401.0.\r\n\r\ntable(example). |_. Denumire problema|_. Categoria|\r\n|Knapsack|Programare dinamica|\r\n|NIM|Teoria jocurilor|\r\n|Sprague-Grundy|Teoria jocurilor|\r\n|Algoritmul lui Gauss|Matematica|\r\n|Numerele lui Stirling|Matematica|\r\n| Principiul lui Dirichlet | Matematică |\r\n| Numărul (şi suma) divizorilor unui număr natural | Matematică |\r\n|Problema de acoperire|Programare dinamica + Backtracking|\r\n|Algoritmul Stoer-Wagner|Algoritmi pe grafuri|\r\n|Heavy Path Decomposition|Algoritmi pe grafuri|\r\n|Arbore -> cod Prufer|Algoritmi pe grafuri|\r\n|Cod Prufer -> arbore|Algoritmi pe grafuri|\r\n|Distanta maxima intre 2 noduri intr-un arbore|Algoritmi pe grafuri|\r\n|Siruri de sufixe|Siruri de caractere|\r\n|Arbori de sufixe|Siruri de caractere|\r\n|Automate - Aho Corasick|Siruri de caractere|\r\n|Algoritmi {$O(sqrtN)$}|Structuri de date|\r\n|Ortogonal Range Search|Structuri de date|\r\n|Aria unui poligon|Geometrie|\r\n|Intersectia a doua drepte|Geometrie|\r\n|Punct in poligon|Geometrie|\r\n|Punct in poligon convex|Geometrie|\r\n|Diagrame Voronoi|Geometrie|\r\n|Minimum enclosing circle|Geometrie|\r\n|Sortare prin numarare|Diverse|\r\n|RadixSort|Diverse|\r\n|Interclasarea a doi vectori sortati|Diverse|\r\n|Operatii pe numere mari|Diverse|\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"61\")==',3146,'protected',NULL,NULL),('planificare/sedinta-20100112','Ședință 2010-01-12','2010-01-05 19:04:00','2010-01-08 10:54:03','h1. Şedinţă 2010-01-12\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Marti* la ora *18:30* la ?.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20091126 | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada Runda 3 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| OKR | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Evaluator | ? |\r\n| Doi la suta | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n* Others:\r\n** Blogpost-uri cu infoarena in 2009.\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* &hellip;\r\n\r\nh2(#notite). Notite\r\n\r\n* &hellip;\r\n',1792,'protected',NULL,NULL),('implica-te/arhiva-educationala','Arhiva Educationala','2008-02-23 13:13:01','2010-01-11 17:49:38','h1. Arhiva educationala ==Stars(rating=\"5\")==\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie. Mai multe despre acest proiect gasiti \'aici\':propuneri/6-arhiva-educationala.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Cum ne poti ajuta?\':implica-te/arhiva-educationala#cum\r\n* \'Echipa implicata in proiect\':implica-te/arhiva-educationala#echipa\r\n* \'Documentatie\':implica-te/arhiva-educationala#documentatie\r\n* \'Continutul arhivei\':implica-te/arhiva-educationala#probleme\r\n\r\nh2(#cum). Cum ne poti ajuta?\r\n\r\n1. Ofera sugestii la dezvoltarea proiectului.\r\n2. Contribuie cu feedback pentru a imbunatati calitatea problemelor existente.\r\n3. Vino cu idei pentru probleme noi.\r\n\r\nAjuta si tu la randul tau comunitatea infoarena! \r\n\r\nh2(#echipa). Echipa implicata in proiect\r\n\r\nEchipa care este implicata activ in acest proiect este alcatuita din urmatorii membri...\r\n\r\n* == user(user=\"Marius\" type=\"tiny\") ==, coordonator de proiect\r\n* == user(user=\"savim\" type=\"tiny\") ==\r\n* == user(user=\"cezarmocan\" type=\"tiny\") ==\r\n* == user(user=\"GavrilaVlad\" type=\"tiny\") ==\r\n* == user(user=\"mishu91\" type=\"tiny\") ==\r\n* == user(user=\"GheorgheMihai\" type=\"tiny\") ==\r\n\r\n\'Multumim celor care ne-au ajutat pana acum.\':implica-te/arhiva-educationala/membri-emeritus\r\n\r\nh2(#documentatie). Documentatie\r\n\r\nFiecare voluntar are obligatia sa citeasca urmatoarele materiale inainte de a putea trece efectiv la lucru:\r\n\r\n* \'Editare de probleme\':documentatie/editare-de-probleme\r\n* \'Ghid evaluator\':documentatie/ghid-evaluator\r\n* \'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala\r\n\r\nh2(#probleme). Continutul arhivei\r\n\r\nIn tabelul de mai jos se afla probleme la care se lucreaza in momentul de fata. Finalizarea lor reprezinta unul dintre $OKR$-urile din trimestrul IV, 2009. Pentru a va familiariza si cu restul obiectivelor din acest trimestru, cititi \'aici\':okr.\r\n\r\ntable(example). |_. Denumire problema|_. Voluntar|_. Finalizat|_. Review |\r\n| \'Cuplaj maxim de cost minim\':problema/cmcm | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Principiul includerii si excluderii\':problema/pinex | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Arbori de intervale (aplicaţie cu 4 tipuri de operaţii)\':problema/arbint2 | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Huffman\':problema/huffman | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Algoritmul Bellman-Ford\':problema/bellmanford | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'2SAT\':problema/2sat | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Al k-lea termen Fibonacci - Matrici\':problema/kfib | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Punct în poligon oarecare\':problema/pinpo | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Lowest Common Ancestor\':problema/lca | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Statistici de ordine\':problema/sdo | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Parantezare optima de matrici\':problema/podm | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Treapuri\':problema/treapuri | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Ciclu hamiltonian de cost minim\':problema/hamilton | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Submulţimi\':problema/submultimi | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa minimă între două puncte în plan\':problema/cmap | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa maximă între două puncte în plan\':problema/cmdp | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Arbori de căutare\':problema/arbcautare | ==user(user=\"bogdan2412\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n\r\nIn tabelul de mai jos se afla sugestii privind algoritmii care trebuie sa se gaseasca sub forma de probleme in arhiva educationala. Puteti veni oricand cu propuneri si sugestii de probleme noi pe \"forum\":/forum/index.php?topic=3401.0.\r\n\r\ntable(example). |_. Denumire problema|_. Categoria|\r\n|Knapsack|Programare dinamica|\r\n|NIM|Teoria jocurilor|\r\n|Sprague-Grundy|Teoria jocurilor|\r\n|Algoritmul lui Gauss|Matematica|\r\n|Numerele lui Stirling|Matematica|\r\n| Principiul lui Dirichlet | Matematică |\r\n| Numărul (şi suma) divizorilor unui număr natural | Matematică |\r\n|Problema de acoperire|Programare dinamica + Backtracking|\r\n|Algoritmul Stoer-Wagner|Algoritmi pe grafuri|\r\n|Heavy Path Decomposition|Algoritmi pe grafuri|\r\n|Arbore -> cod Prufer|Algoritmi pe grafuri|\r\n|Cod Prufer -> arbore|Algoritmi pe grafuri|\r\n|Distanta maxima intre 2 noduri intr-un arbore|Algoritmi pe grafuri|\r\n|Siruri de sufixe|Siruri de caractere|\r\n|Arbori de sufixe|Siruri de caractere|\r\n|Automate - Aho Corasick|Siruri de caractere|\r\n|Algoritmi {$O(sqrtN)$}|Structuri de date|\r\n|Ortogonal Range Search|Structuri de date|\r\n| \'Aria unui poligon\':problema/ariapoli |Geometrie|\r\n|Intersectia a doua drepte|Geometrie|\r\n|Punct in poligon convex|Geometrie|\r\n|Diagrame Voronoi|Geometrie|\r\n|Minimum enclosing circle|Geometrie|\r\n|Sortare prin numarare|Diverse|\r\n|RadixSort|Diverse|\r\n| \'Interclasarea a doi vectori sortati\':problema/interclas |Diverse|\r\n|Operatii pe numere mari|Diverse|\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"61\")==',3146,'protected',NULL,NULL),('algoritmiada-2010','Algoritmiada 2010 - olimpiada algoritmilor, Ediția a II-a','2009-10-25 13:38:22','2009-11-26 21:20:51','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh2. Despre Algoritmiada\r\n\r\nÎn acest an, _infoarena_ revine cu cea de-a doua ediţie a concursului de programare Algoritmiada. Algoritmiada este unicul concurs din România unde pot participa tinerii pasionaţi de informatică de toate vârstele: de la elevi de gimnaziu până la studenţi şi doctoranzi.\r\n\r\nConcursul are patru grupe valorice: gimnaziu, clasele 9-10, clasele 11-12, studenţi (inclusiv masteranzi şi doctoranzi). Participanţii vor avea ocazia să-şi demonstreze talentul, cunostinţele şi ascuţimea minţii în 4 probe online urmând ca cei mai buni sa fie invitaţi la finala on-site.\r\n\r\nh2. Cum particip?\r\n\r\nPentru a participa la concurs trebuie să fii \'înregistrat\':register pe site-ul nostru.\r\n\r\nÎn ziua de concurs intri pe site, citeşti problemele de la grupa ta de vârstă şi trimiţi soluţiile înainte de expirarea timpului. \'Evaluatorul\':documentatie/evaluator nostru iţi va testa automat soluţiile iar punctajul îl vei afla la sfârşitul concursului. Tot atunci vei putea consulta clasamentul pentru a vedea ce au făcut şi ceilalţi concurenţi.\r\n\r\nh3. Prima dată pe _infoarena_?\r\n\r\n_infoarena_ ajută elevi şi studenţi să devină excelenţi în informatică! Gratuit ;) Citeşte \'ghidul utilizatorului\':documentatie/pentru-utilizatori şi află mai multe \'despre noi\':despre-infoarena.\r\n\r\nh2. Program\r\n\r\nFaceţi click pe titlul unei runde pentru informaţii detaliate.\r\n\r\ntable{width:50%}. |_. Runda |_. Data |_. Durata |\r\n| \'*Runda 1*\':algoritmiada-2010/runda-1 | *22 Noiembrie 2009, Duminică* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 2*\':algoritmiada-2010/runda-2 | *20 Decembrie 2009, Duminică* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 3*\':algoritmiada-2010/runda-3 | *Februarie 2010* |=. &nbsp; |\r\n| \'*Runda 4*\':algoritmiada-2010/runda-4 | *Martie 2010* |=. &nbsp; |\r\n| \'*Runda Finală*\':algoritmiada-2010/runda-finala | *Aprilie 2010* |=. &nbsp; |\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('okr/20101','okr/20101','2010-01-12 18:29:40','2010-01-12 18:57:06','arhiva probleme - taguri, bagam doar probleme de la oni, joi si lot -> oji + tagging camp -> Stefan oji, Cosmin tagging camp\r\narhiva educationala - mai bagat cateva probleme -> Marius Stroe\r\norganizeaza concursuri - .com runda 2 -> Cosmin, Marmota\r\nalgoritmiada 2010 - Paul\r\nscrie articole - Marius\r\ndevelopment - Bogdan\r\nStrangere fonduri - Cosmin\r\nBlog - Prostu\r\nProstu ramane la calendar\r\nVideo articol -> Wefgef',2038,'public',NULL,NULL),('okr/20101','OKRs 2010Q1','2010-01-12 18:29:40','2010-01-13 14:55:59','h2. 2010Q1\r\n\r\nh3(#arhiva). Arhivele de probleme\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Adauga Probleme | ==user(user=\"stef2n\" type=\"tiny\")== | ==include(page=\"okr/20101/adauga-probleme\")== | . |\r\n| Tagging| ==user(user=\"gcosmin\" type=\"tiny\")== | ==include(page=\"okr/20101/tagging\")== | . |\r\n\r\nh3(#concursuri). Concursuri\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Organizeaza concursuri | ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n==user(user=\"gcosmin\" type=\"tiny\")== | ==include(page=\"okr/20101/organizeaza-concursuri\")== | . |\r\n| \'Algoritmiada 2010\':algoritmiada-2010 | ==user(user=\"pauldb\" type=\"tiny\")== | ==include(page=\"okr/20101/algoritmiada\")== | . |\r\n\r\nh3(#continut). Continut educational\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Scrie articole\':implica-te/scrie-articole | ==user(user=\"marius\" type=\"tiny\")== | ==include(page=\"okr/20101/articole\")== | . |\r\n| \'Blog\':blog | ==user(user=\"prostu\" type=\"tiny\")== | ==include(page=\"okr/20101/blog\")== | . |\r\n\r\nh3(#development). Development\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'infoarena 2.x Stable\':http://hackers.devnet.ro/roadmap | ==user(user=\"bogdan2412\" type=\"tiny\")== | ==include(page=\"okr/20101/devel-ia2\")== | . |\r\n\r\nh3(#administrativ). Administrativ\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Strangere fonduri | ==user(user=\"gcosmin\" type=\"tiny\")== | ==include(page=\"okr/20101/fund-raising\")== | . |',2038,'public',NULL,NULL),('utilizator/florian','Marcu Florian','2007-01-24 13:36:08','2009-11-17 18:48:19','h2. Despre mine...\r\n\r\n* elev la Colegiul National \"Roman-Voda\" din Roman, clasa a 11-a B,profil mate-info, profesori de info : Florin Moldovanu si Gavril Petru Florin.\r\n\r\nh2. Premii, reusite, castiguri,etc..\r\n\r\n* premii.cpp:40:error: \'reusita[]\' undeclarated ( first use in this function )\r\n\r\n\r\nh2. Prieteni pe infoarena \r\n\r\n* ==user(user=\"blasterz\" type=\"tiny\")== @\r\n* ==user(user=\"gabitzish1\" type=\"tiny\")== @\r\n* ==user(user=\"c_e_manu\" type=\"tiny\")== @\r\n* ==user(user=\"Pepelea_Flaviu\" type=\"tiny\")== @\r\n* ==user(user=\"Mishu91\" type=\"tiny\")== @\r\n* ==user(user=\"petro\" type=\"tiny\")== @\r\n* ==user(user=\"klamathix\" type=\"tiny\")== @\r\n* ==user(user=\"tabara\" type=\"tiny\")== @\r\n* ==user(user=\"mathboy\" type=\"tiny\")== @\r\n* ==user(user=\"nod_software\" type=\"tiny\")== @\r\n* ==user(user=\"raduzer\" type=\"tiny\")== @\r\n\r\n\r\n',5748,'public',NULL,NULL),('okr/20101/algoritmiada','okr/20101/algoritmiada','2010-01-15 00:27:27','2010-01-15 00:34:57','(okr)* Organizare Algoritmiada 2010, chestiuni generale\r\n** Crearea şi organizarea paginilor necesare pentru concurs\r\n\r\n(okr)* Organizare Algoritmiada 2010, Runda 3\r\n** Newsletter Runda 3\r\n** Blogpost Runda 3\r\n\r\n(okr)* Organizare Algoritmiada 2010, Runda 4\r\n** Newsletter Runda 4\r\n** Blogpost Runda 4\r\n\r\n(okr)* Organizare Algoritmiada 2010, Runda Finală (partea I)\r\n** Începerea demersurilor necesare pentru stabilirea locaţiei\r\n** Începerea demersurilor necesare pentru asigurarea cazării şi a mesei\r\n** Verificarea surselor participanţilor\r\n** Selectarea finaliştilor si trimiterea invitaţiilor',1792,'protected',NULL,NULL),('algoritmiada-2010/runda-3/studenti','Algoritmiada 2010 Runda 2, Studenti','2010-01-18 11:51:50','2010-01-18 11:51:50','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda2-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-2\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-2/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-2/11-12\r\n*(active) \'Studenti\':algoritmiada-2010/runda-2/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-2/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda2-studenti\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2010-runda2-studenti\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2010-runda2-studenti\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-2/studenti.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda2-studenti\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1490,'round: algoritmiada2010-runda2-studenti',NULL,NULL),('algoritmiada-2010/runda-3/studenti','Algoritmiada 2010 Runda 2, Studenti','2010-01-18 11:51:50','2010-01-18 15:24:13','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda3-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-3\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-3/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-3/11-12\r\n*(active) \'Studenti\':algoritmiada-2010/runda-3/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-3/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda3-studenti\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2010-runda3-studenti\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2010-runda3-studenti\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-3/studenti.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda3-studenti\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'round: algoritmiada2010-runda3-studenti',NULL,NULL),('algoritmiada-2010/runda-3/studenti','Algoritmiada 2010 Runda 2, Studenti','2010-01-18 11:51:50','2010-01-18 15:24:46','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda3-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-3\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-3/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-3/11-12\r\n*(active) \'Studenti\':algoritmiada-2010/runda-3/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-3/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda3-studenti\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2010-runda3-studenti\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2010-runda3-studenti\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-3/studenti.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda3-studenti\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'round: algoritmiada2010-runda3-studenti',NULL,NULL),('algoritmiada-2010/runda-3/solutii','Solutii Algoritmiada 2010 Runda 3','2010-01-18 11:51:50','2010-01-18 15:38:20','h1. Solutii Algoritmiada 2010, Runda 3\r\n\r\n(toc)*{text-align:center} *Lista de probleme*',1792,'public',NULL,NULL),('dragosh/pwarmup2','dragosh/pwarmup2','2010-01-20 11:44:54','2010-01-20 11:46:01','\r\nConcursul incepe miercuri 20 ianuarie 2010, la ora 19:00:00 si dureaza 1 ora.\r\n\r\nDupa ce se termina runda, vei putea vedea clasamentul.\r\n\r\nProbleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.',3775,'public',NULL,NULL),('www.palatulcopiilor.doodlekit.com','www.palatulcopiilor.doodlekit.com','2010-01-28 14:51:56','2010-01-28 14:51:56','salut',11272,'public',NULL,NULL),('dot-com/2009/solutii/runda-1/galerie','dot-com/2009/solutii/runda-1/galerie','2009-11-15 11:47:30','2009-11-17 18:06:30','h1(#galerie). \'Galerie\':problema/galerie\r\n\r\n**Solutia 1 : Stan Serban Andrei**\r\n\r\nPentru un query $(X,Y)$ ne intereseaza numarul de cartite care vor traversa galeria curenta, mai exact numarul de intervale $(P,Q)$ astfel incat $P&le;X$ si $Y&le;Q$. Costul final se va imbunatati cu $L_galerie * Nr_cartite$. Cum un interval $(A,B),A&ge;B$, este echivalent cu un interval $(A,B),A&le;B$, vom interschimba in primul caz pe $A$ cu $B$.\r\n\r\nPentru a raspunde in mod eficient la fiecare intrebare o sa folosim un \'AIB\':http://infoarena.ro/problema/aib. Initial, pentru fiecare vizita $(P,Q)$,vom insera in AIB la pozitia $P$ numarul de cartite care pleaca din $P$ spre $Q$. \r\nVom parcurge query-urile in ordine dupa capatul din dreapta, si la fiecare pas vom elimina din aib pozitiile reprezentand vizite cu $Q&le;Y-1$. Numarul de cartite care vor traversa intervalul $(X,Y)$ va fi egal cu suma valorilor ce se afla in AIB pe pozitii $&le;P$. \r\n\r\nComplexitatea finala va fi $O(MlogM + TlogT + (M+T)logN)$.\r\n\r\n**Solutia 2 : Teodor Anton Pripoae**\r\n\r\nVom calcula pentru fiecare intrebare a organizatorilor, cate drumuri ale cartitelor contin acel interval (sa zicem $Nr$). Costul imbunatatirii va fi $Nr$ * ($lungime_interval - cost_interval$). Pe exemplul din enunt unde merg $2$ cartite intre camerele $1$ si $4$, vor exista $2$ drumuri care contin intervalul $[1, 3]$ : Drumul facut de prima cartita, respectiv a doua cartita din camera $1$ pana in camera $4$.\r\n\r\nAcum, trebuie sa vedem cum putem raspunde eficient la intrebarea: Cate drumuri contin un interval cautat de organizatori. Vom retine intervalele ca puncte in plan (atat drumurile cat si intrebarile), coordonata $x$ va fi capatul din stanga, iar coordonata $y$ capatul din dreapta. Pentru ca un interval sa fie cuprins de altul, trebuie ca primul punct sa fie in stanga si deasupra celul de-al doilea. Vom sorta crescator toate cele $M + T$ puncte dupa coordonata $x$ si in caz de egalitate descrescator dupa coordonata $y$. Acum, pt fiecare punct (interval) cautat, raspunsul va fi numarul de puncte cu aflate inaintea lui in vector care au coordonata $y$ mai mare decat a lui. \r\n\r\nVom proceda ca la subsir descrescator maximal. Vom tine un aib (Arbore indexat binar). La pasul $i$, vom vedea daca punctul curent($P$) este din cele $M$, caz in care vom updata pe pozitia corespunzatoare coordonatei $P.y$ in aib numarul de cartite care trec pe acel interval, sau in caz ca este din cele $T$ vom vedea cu ajutorul aib-ului cate drumuri a caror coordonate R.y sunt mai mari decat coordonata $P.y$ a lui: scadem din suma totala, suma pozitiilor pana la $P.y - 1$.\r\n\r\nSolutia are complexitate $o((M + T) (log (M + T) + log N))$ ca timp si $o(N)$ ca memorie.\r\n',4827,'public',NULL,NULL),('implica-te/extinde-arhiva/acord','Lista propunatorilor infoarena-friendly','2007-04-21 21:41:18','2010-02-06 13:38:24','h1. Lista propunatorilor infoarena-friendly\r\n\r\nPentru a adauga in arhiva infoarena probleme in cadrul programului \'Extinde Arhiva!\':implica-te/extinde-arhiva este necesar acordul din partea autorului pentru fiecare problema. Astfel, am intocmit aceasta lista cu propunatorii care ne-au oferit acordul pentru problemelor dumnealor. \r\nDaca autorul problemei pe care vrei s-o adaugi nu se gaseste pe lista, vorbeste cu un \'administrator\':echipa-infoarena pentru a intra in contact cu autorul respectiv.\r\nMultumim tuturor persoanelor care ajuta la dezvoltarea \'comunitatii infoarena\':implica-te!\r\n\r\n* Maria Nita\r\n* Adrian Nita\r\n* Mihai Patrascu\r\n* Stelian Ciurea\r\n* Rodica Pintea\r\n* Roxana Tamplaru\r\n* Fechete Dan Ionut\r\n* Mugurel Ionut Andreica\r\n* Marius Andrei\r\n* Mihai Stroe\r\n* Radu Berinde\r\n* Tiberiu Danet\r\n* Dana Lica\r\n* Emilian Miron\r\n* Catalin Francu\r\n* Cristian Cadar\r\n* Nistor Mot\r\n* Alexandru Mosoi\r\n* Victor Manz\r\n* Carmen Popescu\r\n* Marius Nicoli\r\n* Orice membru al echipei \'infoarena\':echipa-infoarena',2044,'public',NULL,NULL),('portal','portal','2010-02-09 16:08:21','2010-02-09 16:27:39','* \"Matematica\":cauta-probleme?tag_id[]=40\r\n* \"Aici\":monitor?user=wefgef',8689,'public',NULL,NULL),('portal','portal','2010-02-09 16:08:21','2010-02-09 16:38:01','==\r\n<a href=\"url\">Link text</a> \r\n<a href = \"http://infoarena.ro/cauta-probleme?tag_id[]=40\">Matematica</a>\r\n==',8689,'public',NULL,NULL),('portal','portal','2010-02-09 16:08:21','2010-02-09 16:50:22','<html>\r\n<a href=\"url\">Link text</a>\r\n<a href = \"http://infoarena.ro/cauta-probleme?tag_id[]=40\">Matematica</a>\r\n</html>\r\n',8689,'public',NULL,NULL),('portal','portal','2010-02-09 16:08:21','2010-02-09 16:54:51','<notextile>\r\n<a href=\"url\">Link text</a>\r\n<a href = \"http://infoarena.ro/cauta-probleme?tag_id[]=40\">Matematica</a>\r\n</code>\r\n</notextile>\r\n\"Matematica\":http://infoarena.ro/cauta-probleme?tag_id[]=400:0',8689,'public',NULL,NULL),('sandbox','Sandbox (cutiuţa cu năsip)','2006-11-11 18:59:57','2010-02-09 17:14:11','h1=. Sandbox (cutiuţa cu năsip)\r\n\r\nNu se pot adauga in Textile adrese care contin semnele []. Nu functioneaza interpretarea acelor sectiuni drept cod html.\r\n\r\n<a href=\"adresa[]\">ha</a>\r\n\r\n== include(page=\"documentatie/sidebar\") ==\r\n\r\n|_. nume |_. varsta |_. judet |\r\n| Popescu | 24 | Bucuresti |\r\n| Ionescu | 12 | Constanta |\r\n\r\n|_. nume |_. varsta |_. judet |_. nume |_. varsta |_. judet |_. nume |_. varsta |_. judet |\r\n| Popescu | 24 | Bucuresti | Popescu | 24 | Bucuresti | Popescu | 24 | Bucuresti |\r\n| Ionescu | 12 | Constanta | Popescu | 24 | Bucuresti | Popescu | 24 | Bucuresti |\r\n\r\nlog me\r\n\r\nLaTeX pe mai multe rânduri:\r\n<tex>\\begin{array}{rcl} f: R^3 & \\to & R \\\\ (x,y,z) & \\to & x + y + z \\\\ f(x,y,z) & = & x + y + z \\end{array}</tex>\r\n\r\nsau:\r\n<tex>\\begin{array} {lcl} f(x) & = & (a+b)^2 \\\\ & = & a^2+2ab+b^2 \\end{array}</tex>\r\n\r\n\r\nTabel mic:\r\n\r\ntable{width:60px}. |A|B|A->B|\r\n|&#48;|2|3|\r\n\r\nTabel mare:\r\n\r\ntable{width:120px}. |A|B|A->B|\r\n|1|2|3|\r\n\r\nTabel si mai mare:\r\n\r\ntable{width:240px}. |A|B|A->B|\r\n|1|2|3|\r\n\r\n*Diacritice:*\r\n\r\nStraşnic de îngâmfat, ţăranul crapă streaşina.\r\nStraşnic de îngâmfat, ţăranul crapă streaşina.\r\n\r\nIn Windows XP sp2 cu IE6 fara update de font se vede asa:\r\n!sandbox?diacritice-IE6.jpg!\r\n\r\nOrdered list:\r\n\r\n# 1st item\r\n# 2nd item\r\n\r\nh3. Use only F/OSS, Microsft sucks ;) just because they like design NOT the code itself.\r\n\r\nHowever, on a GNU system NEVER type <b>sudo make me sandwich</b> , and expect the results...\r\n\r\n\r\nx\r\n\r\n ==calendar()==\r\n\r\ny\r\n\r\n* A[1]\r\n* B[2]\r\n* C[3]\r\n\r\np(#fn1). <tex>2^n    * 2^n</tex>\r\n\"Vivi\'s blog\":http://vivi.ro\r\n<tex> d/(2\\\"a)=d/(2\\Omega^2) </tex>\r\n* <tex> d = \\sqrt{(c_{2}-c_{1})^{2} + 1 } </tex>\r\np. <tex> \r\n\\displaystyle \\sigma_{\\lambda} = \r\n	  \\frac{24 \\pi^3}{\\lambda^4 N^2}\r\n	  \\left(\\frac{n^2-1}{n^2+2}\\right)^{\\!2}\r\n</tex> \r\n\r\nAvem suport pentru <tex> \\LaTeX </tex> !\r\n\r\n<tex> \\frac{a^2 - b^2}{a + b} = a - b </tex>\r\n<tex>n! \\approx \\sqrt{2 \\pi n} (\\frac n e) ^n</tex>\r\n\r\n\r\n==Include(page=\"template/implica-te/scrie-articole\" user_id=\"domino\")==\r\n\r\np(#fn2). | test | test |\r\n\r\n\"User macro bug\":sandbox/usermacrobug\r\n\r\n*Worship me*\r\n\r\nFeel free to plghay around, but \'Big Brother\':/changes is watching you.\r\n\r\n\'codetest\':sandbox/code-test\r\n\r\nWhat does \'this\':sandbox?action=edit button do?\r\n\r\nlalallaa\r\n\r\nIntrebare: cum poti seta culoarea cu care scrii?\r\nUite asa: %{color:violet}scris cu rosu%\r\n\r\nSiteul sub IE 7 -- vezi \'pagina dedicata\':ia_in_ie7\r\n\r\nSiteul sub FF 2 - -mica problema panoul de \'editeaza\', \'vezi istoria\', \'sterge\' etc (in IE7 panoul nu se suprapune)-\r\n!sandbox?IA_bug_in_FF2.jpg!\r\n\r\n[test]\r\n*OMG* test, good work people :D\r\nAcuma doar trebuie putin stimulata comunitatea\r\n[/test]\r\n\r\nInteresting choice of words.\r\na very bold **MAN**\r\n_CAPSOMANII-I DESPISE THEM_\r\n\r\ngasise pe-un teren viran,\r\nun geamantan.\r\n\r\nsi-n geamantan,\r\nun pachet.\r\n\r\nsi in pachet,\r\nun pachetel gasise el.\r\n\r\nsi-n pachetel,\r\nalt pachetel.\r\n\r\nsi-un pachetel in pachetel,\r\nlegat cu funde elegante.\r\n\r\nsi-n pachetel...vreo 40 de diamante...\r\n...\r\nAdio voi...va las si plec fiindca mi-e dor...\r\nsi a plecat Apolodor\r\n!!!<>\r\n\r\ntralalala blablabla lala\r\n\r\n_salut, aici poate sa scrie oricine ce vrea?_ ~Robert~\r\n\r\n|_. 1|_. 2|_. 3|\r\n|unu|doi|trei|\r\n|1... unu|2... doi|3... trei|\r\n\r\nMoraru Ionut has been here. :))\r\n\r\n:) gosh...\r\n\r\ninca unul, de tipul cel mai         heyyyyyyyyyy prost din corcodus, se joaca cu  in nisip.. ura ...\r\ncel mai prost din corcodus a terminat... altcineva?:D\r\ntot el: atentie fratilor ne urmareste big brother 3 (sau 4)\r\n\r\n== code(cpp) |\r\n// comentariu\r\n#include <cstdio> // comment1\r\n// comment2\r\n\r\nint main()\r\n{\r\n    return 0;\r\n}\r\n==\r\n\r\nEu vreau să scriu cu ŢŢŢŢŢ dublu ţ mic şi tripul Ţ mare! Iată un Ţ ţŢŞ ! Are virgulă sau sedilă?\r\nFff\r\nForza Steaua!\r\nTz\r\n\r\naha',8689,'public',NULL,NULL),('algoritmul-lee','Algoritmul lui Lee','2010-02-08 15:03:25','2010-02-09 18:51:45','h1. Algoritmul lui Lee\r\n\r\n(Categoria _Algoritmi_, Autor _Simoiu Robert_)\r\n\r\n(toc){width: 12em}*{text-align:center;} *Conţinut:*\r\n* \'Introducere\':algoritmul-lee#sectiune1\r\n* \'Prezentare\':algoritmul-lee#sectiune2\r\n* \'Aplicaţia #1\':algoritmul-lee#sectiune3\r\n* \'Aplicaţia #2\':algoritmul-lee#sectiune4\r\n\r\nh2(#sectiune1). Introducere\r\n\r\nÎn continuare vom prezenta _algoritmul lui Lee_, pentru cei care nu ştiu este _parcurgerea în lăţime_. Acest algoritm este de fapt o particularizare a algoritmului menţionat mai sus, şi anume _parcurgerii în lăţime_. Este eficient, având o complexitate de $O(M*N)$, şi frecvent utilizat. Acesta determină drumul minim de ieşire dintr-un labirint, sau în probleme asemănătoare. \r\n\r\nh2(#sectiune2). Prezentare\r\n\r\n_Algoritmul lui Lee_ presupune doi paşi importanţi:\r\n\r\n# Primul şi poate cel mai important pas este folosirea unei **Cozi**, sub forma unui vector de structuri (de preferabil), care va menţine toţi paşii pe care o să-i facem de acum în colo. În această coadă se pun, pentru fiecare pas, locurile care s-au marcat la punctul anterior.\r\n# Se marchează cu numere consecutive toate locurile posibile prin care putem trece, parcurgând în ordine elementele cozii, până când nu mai putem marca, sau am ajuns la final.\r\n\r\nh2(#sectiune3). Aplicaţia #1 -> Problema Labirintului\r\n\r\nbq. Se dă o matrice cu M linii şi N coloane. Ştiind locul de plecare, marcat cu $-1$, se cere să se determine drumul de lungime minimă până la o ieşire, iar in caz că nu există, se va afişa $-1$\r\n\r\nh3. Rezolvare\r\n\r\nDupă cum observaţi, este o aplicaţie a _algoritmului lui Lee_. Această problemă se poate rezolva şi cu metoda \'backtracking\':http://en.wikipedia.org/wiki/Backtracking, dar această metodă nu este una eficientă, complexitatea fiind $O(4^(M*N)^)$, sau $O(3^(M*N)^)$ după caz, ceea ce este foarte mult. În primul pas vom pune în coadă coordonatele locului de plecare, urmând apoi să parcurgem pe rând coada, până când nu mai există cale de ieşire sau am găsit una. Aveţi \'aici\':algoritmul-lee?lee-lab.cpp o sursă cu acest algoritm implementat în C++, sau \'aici\':algoritmul-lee?lee-lab.pas o sursă implementată în Pascal.\r\n\r\nh2(#sectiune4). Aplicaţia #2 -> \'Muzeu\':http://infoarena.ro/problema/muzeu\r\n\r\nbq. Un muzeu are forma patratica si contine N*N camere ce pot fi vizitate. Unele camere sunt deschise si contin opere de arta, altele sunt inchise (sunt folosite pentru alte scopuri). In unele din camerele libere, se afla paznici. Directorul muzeului se teme de eventualitatea unei spargeri si de aceea doreste sa evalueze cat de bine au fost asezati paznicii in camerele libere. Mai precis, el doreste sa afle, pentru fiecare camera libera, care este distanta minima pana la cel mai apropiat paznic (numarul minim de camere prin care trebuie sa intre un paznic pentru a ajunge la camera respectiva). Paznicii se pot deplasa numai in camerele libere din Nord, Est, Sud sau Vest (cu conditia sa nu paraseasca muzeul).\r\n\r\nh3. Rezolvare\r\n\r\nAceastă problemă se rezolvă cu _algoritmul lui Lee_, doar că în coadă vom pune iniţial nu o coordonată, ci toate coordonatele paznicilor. Pentru asta se citesc ca şir de caractere fiecare caracter în parte, şi se convertesc acestea (la citire) în numere astfel: zidurile (#) vor fi notate cu $-2$, paznicii (P) cu $-1$, iar căile libere cu $0$. După executarea algoritmului, se verifică şi se înlocuiesc cifrele de $0$ cu $-1$ (pentru că în problemă ne cere să afişăm cu $-1$ locurile care nu au fost vizitate), iar cifrele de $-1$ (reprezentând paznicii) cu $0$. \r\n\r\n\r\n\r\n',11154,'public',NULL,NULL),('algoritmul-lee','Algoritmul lui Lee','2010-02-08 15:03:25','2010-02-10 07:27:19','h1. Algoritmul lui Lee\r\n\r\n(Categoria _Algoritmi_, Autor _Simoiu Robert_)\r\n\r\n(toc){width: 12em}*{text-align:center;} *Conţinut:*\r\n* \'Introducere\':algoritmul-lee#sectiune1\r\n* \'Prezentare\':algoritmul-lee#sectiune2\r\n* \'Aplicaţia #1\':algoritmul-lee#sectiune3\r\n* \'Aplicaţia #2\':algoritmul-lee#sectiune4\r\n\r\nh2(#sectiune1). Introducere\r\n\r\nÎn continuare vom prezenta _algoritmul lui Lee_, pentru cei care nu ştiu este _parcurgerea în lăţime_. Acest algoritm este de fapt o particularizare a algoritmului menţionat mai sus, şi anume _parcurgerii în lăţime_. Este eficient, având o complexitate de $O(M*N)$, şi frecvent utilizat. Acesta determină drumul minim de ieşire dintr-un labirint, sau în probleme asemănătoare. \r\n\r\nh2(#sectiune2). Prezentare\r\n\r\n_Algoritmul lui Lee_ presupune doi paşi importanţi:\r\n\r\n# Primul şi poate cel mai important pas este folosirea unei **Cozi**, sub forma unui vector de structuri (de preferabil), care va menţine toţi paşii pe care o să-i facem de acum în colo. În această coadă se pun, pentru fiecare pas, locurile care s-au marcat la punctul anterior.\r\n# Se marchează cu numere consecutive toate locurile posibile prin care putem trece, parcurgând în ordine elementele cozii, până când nu mai putem marca, sau am ajuns la final. \r\n\r\nh2(#sectiune3). Aplicaţia #1 -> Problema Labirintului\r\n\r\nbq. Se dă o matrice cu M linii şi N coloane. Ştiind locul de plecare, marcat cu $-1$, se cere să se determine drumul de lungime minimă până la o ieşire, iar in caz că nu există, se va afişa $-1$\r\n\r\nh3. Rezolvare\r\n\r\nDupă cum observaţi, este o aplicaţie a _algoritmului lui Lee_. Această problemă se poate rezolva şi cu metoda \'backtracking\':http://en.wikipedia.org/wiki/Backtracking, dar această metodă nu este una eficientă, complexitatea fiind $O(4^(M*N)^)$, sau $O(3^(M*N)^)$ după caz, ceea ce este foarte mult. În primul pas vom pune în coadă coordonatele locului de plecare, urmând apoi să parcurgem pe rând coada, până când nu mai există cale de ieşire sau am găsit una. Aveţi \'aici\':algoritmul-lee?lee-lab.cpp o sursă cu acest algoritm implementat în C++, sau \'aici\':algoritmul-lee?lee-lab.pas o sursă implementată în Pascal. Vă voi da un exemplu pentru a vă arata mai bine cum se marchează fiecare vecin în parte:\r\n\r\n|_. fişier intrare |_. fişier ieşire |_. explicaţii |\r\n|$5$ $5$                 \r\n$1$ $1$ $1$ $1$ $1$\r\n$1$ $0$ $0$ $0$ $-1$\r\n$1$ $0$ $0$ $1$ $1$\r\n$1$ $0$ $0$ $1$ $1$\r\n$1$ $0$ $1$ $1$ $1$|6| $1$ $1$ $1$ $1$ $1$ \r\n$1$ _3_ _2_ _1_ $-1$ \r\n$1$ _4_ _3_ _2_ $1$ \r\n$1$ _5_ _4_ $1$ $1$ \r\n$1$ _6_ $1$ $1$ $1$| \r\n\r\nh2(#sectiune4). Aplicaţia #2 -> \'Muzeu\':http://infoarena.ro/problema/muzeu\r\n\r\nbq. Un muzeu are forma patratica si contine N*N camere ce pot fi vizitate. Unele camere sunt deschise si contin opere de arta, altele sunt inchise (sunt folosite pentru alte scopuri). In unele din camerele libere, se afla paznici. Directorul muzeului se teme de eventualitatea unei spargeri si de aceea doreste sa evalueze cat de bine au fost asezati paznicii in camerele libere. Mai precis, el doreste sa afle, pentru fiecare camera libera, care este distanta minima pana la cel mai apropiat paznic (numarul minim de camere prin care trebuie sa intre un paznic pentru a ajunge la camera respectiva). Paznicii se pot deplasa numai in camerele libere din Nord, Est, Sud sau Vest (cu conditia sa nu paraseasca muzeul).\r\n\r\nh3. Rezolvare\r\n\r\nAceastă problemă se rezolvă cu _algoritmul lui Lee_, doar că în coadă vom pune iniţial nu o coordonată, ci toate coordonatele paznicilor. Pentru asta se citesc ca şir de caractere fiecare caracter în parte, şi se convertesc acestea (la citire) în numere astfel: zidurile (#) vor fi notate cu $-2$, paznicii (P) cu $-1$, iar căile libere cu $0$. După executarea algoritmului, se verifică şi se înlocuiesc cifrele de $0$ cu $-1$ (pentru că în problemă ne cere să afişăm cu $-1$ locurile care nu au fost vizitate), iar cifrele de $-1$ (reprezentând paznicii) cu $0$. \r\n\r\n\r\n\r\n',11154,'public',NULL,NULL),('planificare/sedinta-20100216','Ședință 2010-02-16','2010-02-13 13:22:15','2010-02-13 14:04:41','h1. Şedinţă 2010-02-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Marti* la ora *?* la ?.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"svalentin\" type=\"tiny\")==\r\n* ....\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20100112 | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada Runda 3 + 4 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| OKR | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Evaluator | ? |\r\n| Doi la suta | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n* ...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* ...\r\n\r\nh2(#notite). Notite\r\n\r\n* ....\r\n',75,'protected',NULL,NULL),('sandbox','Sandbox (cutiuţa cu nisip murdar iahh!!;)))','2006-11-11 18:59:57','2010-02-14 16:53:18','h1=. Sandbox (cutiuţa cu nisip-murdar iahh!! ;))) // by laurrr din Piteşti brătianu rules!! ;) me_lawr yahoo)\r\n\r\nNu se pot adauga in Textile adrese care contin semnele []. Nu functioneaza interpretarea acelor sectiuni drept cod html.\r\n\r\n@<a href=\"adresa[]\">ha</a>@ -> nu merge cu @\r\n==\r\n<a href=\"adresa[]\">ha</a> -> nu merge cu ==\r\n==\r\n\r\n== include(page=\"documentatie/sidebar\") ==\r\n\r\n|_. nume |_. varsta |_. judet |\r\n| Popescu | 24 | Bucuresti |\r\n| Ionescu | 12 | Constanta |\r\n\r\n|_. nume |_. varsta |_. judet |_. nume |_. varsta |_. judet |_. nume |_. varsta |_. judet |\r\n| Popescu | 24 | Bucuresti | Popescu | 24 | Bucuresti | Popescu | 24 | Bucuresti |\r\n| Ionescu | 12 | Constanta | Popescu | 24 | Bucuresti | Popescu | 24 | Bucuresti |\r\n\r\nlog me\r\n\r\nLaTeX pe mai multe rânduri:\r\n<tex>\\begin{array}{rcl} f: R^3 & \\to & R \\\\ (x,y,z) & \\to & x + y + z \\\\ f(x,y,z) & = & x + y + z \\end{array}</tex>\r\n\r\nsau:\r\n<tex>\\begin{array} {lcl} f(x) & = & (a+b)^2 \\\\ & = & a^2+2ab+b^2 \\end{array}</tex>\r\n\r\n\r\nTabel mic:\r\n\r\ntable{width:60px}. |A|B|A->B|\r\n|&#48;|2|3|\r\n\r\nTabel mare:\r\n\r\ntable{width:120px}. |A|B|A->B|\r\n|1|2|3|\r\n\r\nTabel si mai mare:\r\n\r\ntable{width:240px}. |A|B|A->B|\r\n|1|2|3|\r\n\r\n*Diacritice:*\r\n\r\nStraşnic de îngânfat, ţăranul crapă straşina.\r\nStraşnic de îngâmfat, ţăranul crapă streaşina.\r\n\r\nIn Windows XP sp2 cu IE6 fara update de font se vede asa:\r\n!sandbox?diacritice-IE6.jpg!\r\n\r\nOrdered list:\r\n\r\n# 1st item\r\n# 2nd item\r\n\r\nh3. Use only F/OSS, Microsft sucks ;) just because they like design NOT the code itself.\r\n\r\nHowever, on a GNU system NEVER type <b>sudo make me sandwich</b> , and expect the results...\r\n\r\n\r\nx\r\n\r\n ==calendar()==\r\n\r\ny\r\n\r\n* A[1]\r\n* B[2]\r\n* C[3]\r\n\r\np(#fn1). <tex>2^n    * 2^n</tex>\r\n\"Vivi\'s blog\":http://vivi.ro\r\n<tex> d/(2\\\"a)=d/(2\\Omega^2) </tex>\r\n* <tex> d = \\sqrt{(c_{2}-c_{1})^{2} + 1 } </tex>\r\np. <tex> \r\n\\displaystyle \\sigma_{\\lambda} = \r\n	  \\frac{24 \\pi^3}{\\lambda^4 N^2}\r\n	  \\left(\\frac{n^2-1}{n^2+2}\\right)^{\\!2}\r\n</tex> \r\n\r\nAvem suport pentru <tex> \\LaTeX </tex> !\r\n\r\n<tex> \\frac{a^2 - b^2}{a + b} = a - b </tex>\r\n<tex>n! \\approx \\sqrt{2 \\pi n} (\\frac n e) ^n</tex>\r\n\r\n\r\n==Include(page=\"template/implica-te/scrie-articole\" user_id=\"domino\")==\r\n\r\np(#fn2). | test | test |\r\n\r\n\"User macro bug\":sandbox/usermacrobug\r\n\r\n*Worship me*\r\n\r\nFeel free to plghay around, but \'Big Brother\':/changes is watching you.\r\n\r\n\'codetest\':sandbox/code-test\r\n\r\nWhat does \'this\':sandbox?action=edit button do?\r\n\r\n\r\n\r\nIntrebare: cum poti seta culoarea cu care scrii?\r\nUite asa: %{color:blue}scris cu rosu :)))))))) nu prea seamana cu rosuu :P:P=))))))%\r\n\r\nSiteul sub IE 7 -- vezi \'pagina dedicata\':ia_in_ie7\r\n\r\nSiteul sub FF 2 - -mica problema panoul de \'editeaza\', \'vezi istoria\', \'sterge\' etc (in IE7 panoul nu se suprapune)-\r\n!sandbox?IA_bug_in_FF2.jpg!\r\n\r\n[test]\r\n*OMG* test, good work people :D\r\nAcuma doar trebuie putin stimulata comunitatea\r\n[/test]\r\n\r\nInteresting choice of words.\r\na very bold **MAN**\r\n_CAPSOMANII-I DESPISE THEM_\r\n\r\ngasise pe-un teren viran,\r\nun geamantan.\r\n\r\nsi-n geamantan,\r\nun pachet.\r\n\r\nsi in pachet,\r\nun pachetel gasise el.\r\n\r\nsi-n pachetel,\r\nalt pachetel.\r\n\r\nsi-un pachetel in pachetel,\r\nlegat cu funde elegante.\r\n\r\nsi-n pachetel...vreo 40 de diamante...\r\n...\r\nAdio voi...va las si plec fiindca mi-e dor...\r\nsi a plecat Aleodor Cersetorul\r\n!!!<>\r\n\r\ntralalala blablabla lala\r\n\r\n_salut, aici poate sa scrie oricine ce vrea?_ ~Robert~ nu chiar oricine....~mai Robert mai~\r\n\r\n|_. 1|_. 2|_. 3|\r\n|unu|doi|trei|\r\n|1... unu|2... doi|3... trei|\r\n\r\nMoraru Ionut has been here. :))\r\n\r\n:) gosh...\r\n\r\ninca unul, de tipul cel mai         heyyyyyyyyyy prost din corcodus, se joaca cu  in nisip.. ura ...\r\ncel mai prost din corcodus a terminat... altcineva?:D\r\ntot el: atentie fratilor ne urmareste big brother 3 (sau 4)\r\n\r\n== code(cpp) |\r\n// comentariu\r\n#include <cstdio> // comment1\r\n// comment2\r\n\r\nint main()\r\n{\r\n    return 0;\r\n}\r\n==\r\n\r\nEu vreau să scriu cu ŢŢŢŢŢ dublu ţ mic şi tripul Ţ mare! Iată un Ţ ţŢŞ ! Are virgulă sau sedilă?\r\nFff\r\nForza Steaua!\r\nTz\r\n\r\naha\r\n\r\n\r\nme_lawr by Laurrr din Piteşti\r\n\r\n\'cs\':http://dl.transfer.ro/Transfer_ro-03Feb-12e6d2135cef7ae.zip',11775,'public',NULL,NULL),('implica-te/extinde-arhiva','Extinde arhiva','2007-03-12 22:59:26','2010-02-14 23:05:38','h1. Extinde arhiva ==Stars(rating=\"3\")==\r\n\r\nArhiva este una dintre cele mai folositoare sectiuni _infoarena_ pentru utilizatorii nostri. Ea contine probleme pentru multe gusturi. Dar nu pentru toate!\r\nVrem sa o imbunatatim cu probleme cat mai diverse si cu grade de dificultate cat mai variate. Pentru asta am obtinut aprobarea mai multor autori de probleme pentru a le importa \"creatiile\" in arhiva.\r\n\r\nh2. De ce m-as baga?\r\n\r\n# Vei afla cum se propune si cum se corecteaza o problema. Vei sti cum sa propui propriile probleme pe _infoarena_.\r\n# Intreaga comunitate iti va multumi pentru noul \"material\" de pregatire.\r\n# Vei fi si tu \"de partea cealalta a baricadei\".\r\n# Pentru unele probleme vei putea scrie enuntul personalizat (cu numele simpatiei tale, spre exemplu).\r\n# Unde-s multi, puterea creste! :P\r\n\r\nh2. Ce pot sa fac?\r\n\r\n# Contacteaza-l pe Adi pe \'forum\':forum/index.php/board,42.0.html.\r\n# Alege-ti problemele pe care vrei sa le pui in arhiva si *verifica* daca exista \'acordul\':implica-te/extinde-arhiva/acord autorului pentru a pune problemele respective. \r\n*{color:red}Atentie!* Comunica acest lucru lui Adi cat mai repede pentru a evita suprapunerile si pentru a putea aparea in tabelul cu voluntarii activi ;)\r\n# *{color:red}Foarte important:* Citeste despre \'cum se adauga o problema\':documentatie/editare-de-probleme, \"conventii de formatare\":documentatie/conventii-de-formatare si \'textile\':documentatie/textile si intreaba pe forum daca ai nelamuriri.\r\n# Abia dupa ce ai terminat de citit documentatia, cere drepturi de helper pentru a putea pune probleme pe infoarena.\r\n# Scrie enuntul unei probleme folosind \'textile\':http://infoarena.ro/documentatie/textile si gandeste-te la solutii alternative.\r\n# Imbunatateste testele si creeaza altele noi, astfel incat problema sa devina de actualitate.\r\nToate bulanelile/ciucuielile care s-au facut in concursul respectiv trebuie facute sa pice.\r\n# Stabileste limitele de timp si memorie conform cu mediul infoarena de evaluare.\r\n\r\nh2. Cine mai lucreaza?\r\n\r\n ==user(user=\"ditzonec\" type=\"tiny\")== *este coordonatorul proiectului.*\r\n ==user(user=\"silviug\" type=\"tiny\")==\r\n ==user(user=\"domino\" type=\"tiny\")== \r\n\r\n\r\ntable. |_. Sursa de probleme |_. Voluntar |_. Progres |\r\n| Probleme baraje | ==User(user=\"astronomy\" type=\"tiny\")== ==User(user=\"toni2007\" type=\"tiny\")== | ?/? |\r\n| Probleme Cosmin Negruseri | ==User(user=\"bogdan2412\" type=\"tiny\")== | 3/4 |\r\n| Lista lui Francu | ==User(user=\"cos_min\" type=\"tiny\")== ==User(user=\"devilkind\" type=\"tiny\")==\r\n==User(user=\"pauldb\" type=\"tiny\")==  ==User(user=\"gabitzish1\" type=\"tiny\")==  ==User(user=\"Florian\" type=\"tiny\")==| 36/45 |\r\n\r\nh2. Probleme de pus in arhiva \r\n\r\n* \"preONI 2003\":downloads?action=download&file=preoni2.zip\r\n* Probleme de orice autor din \'lista de propunatori infoarena-friendly\':implica-te/extinde-arhiva/acord\r\n* \"Lista lu\' Francu\":http://voronet.francu.com/probleme/rom/probleme.html; pentru cei interesati mai multe detalii \"aici\":implica-te/extinde-arhiva/lista-lu-francu.\r\n\r\nh2. Discutii forum\r\n\r\n==SmfTopics(board_id=\"42.0\")==\r\n',1792,'protected',NULL,NULL),('newsletter/algoritmiada-2010-3','Algoritmiada 2010 Runda 3','2010-02-14 23:32:52','2010-02-15 07:32:45','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nWeekendul acest are loc cea de-a \'treia rundă\':algoritmiada-2010/runda-3 a concursului \'Algoritmiada 2010\':algoritmiada-2010, cel mai mare şi mai prestigios concurs organizat de infoarena!\r\n\r\nLa Algoritmiada participă elevi de gimnaziu, de liceu, dar şi studenţi (inclusiv masteranzi sau doctoranzi)! Există grupe separate pentru fiecare.\r\n\r\nÎntrece-te cu cei mai buni! Dovedeşte-ţi talentul şi abilităţile şi asigură-ţi un loc în finală!\r\n\r\nEşti elev de liceu? \'Runda 3\':algoritmiada-2010/runda-3 reprezintă o ocazie perfectă pentru a-ţi verifica cunoştinţele înainte de Olimpiada Judeţeană de Informatică! \r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Runda a treia se desfăşoară\r\n*Duminică, 21 Februarie 2010, orele 09^00^ - 13^00^*. |\r\n\r\nVezi \'pagina concursului\':algoritmiada-2010 ca să afli cum poţi participa.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"algoritmiada-2010/runda-3\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre rundele anterioare\r\n\r\nPe \'blog\':blog găseşti analizele primelor două runde. Află câti concurenţi au participat, câte surse s-au trimis şi impresii despre rundă!\r\n\r\nVezi rezultatele şi clasamentul \'aici\':algoritmiada-2010/clasament.\r\n\r\nh2{font-size: 12pt}. Despre Algoritmiada\r\n\r\nAlgoritmiada este unicul concurs din România unde pot participa tinerii pasionaţi de informatică de toate vârstele: de la elevi de gimnaziu până la studenţi şi doctoranzi.\r\n\r\nConcursul are patru grupe valorice: gimnaziu, clasele 9-10, clasele 11-12, studenţi (inclusiv masteranzi şi doctoranzi). Participanţii vor avea ocazia să-şi demonstreze talentul, cunostinţele şi ascuţimea minţii în 4 probe online urmând ca cei mai buni sa fie invitaţi la finala on-site. În fiecare rundă vei avea la dispoziţie 4h să rezolvi 3 probleme de natură algoritmică.\r\n\r\nSubiectele vor fi propuse de către o echipă de foşti şi actuali olimpici la informatică: Cosmin Gheorghe, Bogdan Tătăroiu, Paul Băltescu, Filip Ştefan, Marius Stroe, Adrian Airinei, Andrei Grigorean, Ştefan Istrate, Adrian Diaconu, Cosmin Negruşeri şi Filip Buruiană. De ce ei? Intră pe \'pagina organizatorilor\':algoritmiada-2010/comisie şi citeşte câte ceva despre experienţa fiecăruia.\r\n\r\nIntră pe \'pagina concursului\':algoritmiada-2010 ca să afli mai multe informaţii.\r\n\r\nIţi urăm succes şi te asteptăm în arenă!\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==',1792,'protected',NULL,NULL),('utilizator/blasterz','Profil blasterz','2006-11-24 20:58:43','2010-02-15 20:29:24','h3. Student in anul II la Facultatea de Matematica si Informatica, Universitatea Bucuresti\r\n\r\n\r\nh2. TODO LIST:   ACM WORLD FINALS MEDAL\r\n\r\nh2. Distinctii primite\r\n\r\n**2009 : Antrenor si Membru in Comisia Lotului National de Informatica** \r\n**2009 : Membru in Comisia ONI la clasele 11-12 si baraj**\r\n**2009 : Propunator probleme .campion ,ONI si lot**\r\n\r\n**2010 : 21st place at Bitwise International Programing Contest**\r\n**2009 : 26th place (Honorable Mention) at the ACM South Eastern Contest**\r\n**2009 : Adobe Internship Diploma**\r\n**2009 : Locul 1 la Sesiunea de Comunicari Stiintifice, Faza Nationala impreuna cu Serban Lupulescu cu articolul \"Trie Forest Data Structure\"**\r\n**2009 : Locul 4 la finala concursului national Algoritmiada, sectia studenti**\r\n**2009 : Calificat in finala Concursului National Algoritmiada pentru Studenti**\r\n**2008 : Calificat in runda a4a a concursului international Google CodeJam**\r\n**2008 : Membru al Lotului National Restrans (unde am obtinut locul 11)**\r\n**2008 : Calificat in Lotul National Largit**\r\n**2008 : Mentiune ONI 2008 + medalie de argint**\r\n**2008 : Finalist .campion 2008 Bran**\r\n2008 : Participare la Concursul National Urmasii lui Moisil, Iasi ( punctajul neoficial cel mai mare...mai trimiti brute la sfarsit fara sa-ti dai seama =)) :| )\r\n2008 : Participare la Concursul National Stelele Informarticii 2008\r\n**2007 : Premiul 1 la Concursul International ProSoft@NT**\r\n**2007 : Finalist .Campion 2007 Galati** \r\n**2007 : Premiul II la Concursul National de Informatica Aplicata (CIA) sectiunea Jocuri**\r\n2007 : Premiul I la Faza Judeteana a Concursul de Informatica Aplicata (CIA) sectiunea Jocuri\r\n2007 : Premiul II la Concursul Interjudetean al Centrelor de Excelenta Suceava\r\n2007 : Mentiune la Concursul de Programare DataS-NMG Targu Secuiesc\r\n2007 : Participare ONI 2007 + calificare pentru baraje\r\n2007 : Premiul 2 Olimpiada Judeteana\r\n2006 : Mentiune la Concursul Interjudetean al Centrelor de Excelenta Suceava\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\nh3. Ordinea nu are importanta. Daca nu am trecut pe careva sa-mi spuneti.\r\n\r\n\r\n* ==user(user=\"georgiana\" type=\"tiny\")== \r\n\r\n* ==user(user=\"marina\" type=\"tiny\")== \r\n\r\n* ==user(user=\"alisssia\" type=\"tiny\")== \r\n\r\n\r\n* ==user(user=\"doru.nitu\" type=\"tiny\")== \r\n\r\n* ==user(user=\"freak93\" type=\"normal\")==\r\n\r\n* ==user(user=\"DjSefu\" type=\"tiny\")==\r\n\r\n* ==user(user=\"warchildmd\" type=\"tiny\")==\r\n\r\n* ==user(user=\"nyxpho\" type=\"tiny\")== \r\n\r\n* ==user(user=\"monica_133\"  type=\"normal\")==\r\n\r\n* ==user(user=\"serbanlupu\" type=\"normal\")==\r\n\r\n* ==user(user=\"enslaverr\" type=\"tiny\")==\r\n\r\n* ==user(user=\"Mishu91\" type=\"tiny\")==\r\n\r\n* ==user(user=\"yoyolich\" type=\"tiny\")== \r\n\r\n* ==user(user=\"nuexist\" type=\"tiny\")== \r\n\r\n* ==user(user=\"malex\" type=\"tiny\")==\r\n\r\n* ==user(user=\"lorin_bobu\" type=\"tiny\")==\r\n\r\n\r\n* ==user(user=\"ioanai\" type=\"tiny\")==\r\n\r\n* ==user(user=\"Florian\" type=\"tiny\")==\r\n\r\n\r\n* ==user(user=\"Tabara\" type=\"tiny\")==\r\n\r\n* ==user(user=\"alexthero\" type=\"tiny\")==\r\n\r\n* ==user(user=\"peanutz\" type=\"tiny\")==\r\n\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n\r\n* ==user(user=\"m_dersidan\" type=\"tiny\")==\r\n\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n\r\n* ==user(user=\"mastermage\" type=\"tiny\")==\r\n\r\n* ==user(user=\"nemesis\" type=\"tiny\")==\r\n\r\n* ==user(user=\"Binary_Fire\" type=\"tiny\")==\r\n\r\n* ==user(user=\"TYTUS\" type=\"tiny\")==\r\n\r\n\r\n* ==user(user=\"crawler\" type=\"tiny\")==\r\n\r\n* ==user(user=\"devilkind\" type=\"tiny\")==\r\n\r\n* ==user(user=\"vlad_D\" type=\"tiny\")==\r\n\r\n* ==user(user=\"arenakadaff\" type=\"tiny\")==\r\n\r\n* ==user(user=\"StTwister\" type=\"tiny\")==\r\n\r\n* ==user(user=\"bog_bej\" type=\"tiny\")==\r\n* ==user(user=\"cretu\" type=\"tiny\")==\r\n',1204,'protected',NULL,NULL),('planificare/sedinta-20100216','Ședință 2010-02-16','2010-02-13 13:22:15','2010-02-15 13:51:10','h1. Şedinţă 2010-02-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Marti* la ora *17* la staţia de 41 de la Plaza România.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"svalentin\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"Prostu\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"stef2n\" type=\"tiny\")==\r\n* ...\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20100112 | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada Runda 3 + 4 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| OKR | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Evaluator | ? |\r\n| Doi la suta | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Restructurare arhiva + tagging camp | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n* ...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* ...\r\n\r\nh2(#notite). Notite\r\n\r\n* ....\r\n',2044,'protected',NULL,NULL),('echipa-infoarena','Echipa infoarena','2006-11-27 08:20:21','2009-12-31 15:54:23','h1. Echipa infoarena\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nMembrii echipei infoarena s-au remarcat prin activitate sustinuta in cadrul proiectelor infoarena. Acestia detin functii oficiale in \'Asociatia infoarena\':asociatia-infoarena. Echipa infoarena este responsabila de dezvoltarea si intretinerea site-ului infoarena precum si de desfasurarea altor proiecte ale Asociatiei. Coordonarea eforturilor echipei se face pe pagina de \'planificare\':planificare.\r\n\r\nEchipa infoarena se bucura de \'*sprijinul a zeci de voluntari*\':implica-te. O buna parte din continutul infoarena este rezultatul muncii lor. Suntem onorati sa primim ajutorul lor si le multumim sincer pentru efortul pe care l-au depus!\r\n\r\nh2. Conducere\r\n\r\ntable(layout){width: 70%}.\r\n|* ==user(user=\"gcosmin\" type=\"normal\")==\r\n* ==user(user=\"pauldb\" type=\"normal\")==\r\n|* ==user(user=\"bogdan2412\" type=\"normal\")==\r\n* ==user(user=\"stef2n\" type=\"normal\")==|\r\n\r\nh2. Membri fondatori\r\n\r\ntable(layout){width: 70%}.\r\n|* ==user(user=\"wickedman\" type=\"normal\")==\r\n* ==user(user=\"silviug\" type=\"normal\")==\r\n|* ==user(user=\"domino\" type=\"normal\")==\r\n* ==user(user=\"fluffy\" type=\"normal\")==|\r\n\r\nh2. Consilieri\r\n\r\ntable(layout){width: 70%}.\r\n|* ==user(user=\"ditzoneC\" type=\"normal\")==\r\n* ==user(user=\"filipb\" type=\"normal\")==\r\n* ==user(user=\"Cosmin\" type=\"normal\")==\r\n* ==user(user=\"svalentin\" type=\"normal\")==\r\n* ==user(user=\"astronomy\" type=\"normal\")==\r\n* ==user(user=\"wefgef\" type=\"normal\")==\r\n* ==user(user=\"alexthero\" type=\"normal\")==\r\n| * ==user(user=\"gcosmin\" type=\"normal\")==\r\n* ==user(user=\"bogdan2412\" type=\"normal\")==\r\n* ==user(user=\"pauldb\" type=\"normal\")==\r\n* ==user(user=\"Prostu\" type=\"normal\")==\r\n* ==user(user=\"stef2n\" type=\"normal\")==\r\n* ==user(user=\"victorsb\" type=\"normal\")==\r\n* ==user(user=\"Marius\" type=\"normal\")== |\r\n\r\nh2. Consilieri emeritus\r\n\r\n* ==user(user=\"azotlichid\" type=\"normal\")==\r\n* ==user(user=\"greco\" type=\"normal\")==\r\n* ==user(user=\"danielp\" type=\"normal\")==\r\n',13,'protected',NULL,NULL),('algoritmiada-2010/runda-3','Algoritmiada 2010 - Runda 3','2009-10-25 16:32:16','2010-02-14 23:37:23','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Algoritmiada 2010, Runda 3\r\n\r\n(htabs)*(active) \'Despre...\':algoritmiada-2010/runda-3 \r\n* \'Clasele 5-8\':algoritmiada-2010/runda-3/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-3/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-3/5-8 \r\n\r\nRunda va incepe *Duminica 21 februarie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-3/studenti\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':algoritmiada-2010/runda-3/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-3/studenti\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"cosmin\" type=\"tiny\")==\r\n* ==User(user=\"marius\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica sau tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('portal','portal','2010-02-09 16:08:21','2010-02-09 17:11:12','',8689,'public',NULL,NULL),('portal','portal','2010-02-09 16:08:21','2010-02-18 10:26:42','\r\n\r\n\r\n\r\n\r\n* \"Cautare\":cauta-probleme?tag_id%5B%5D=48\r\n** \"Cautare binara\":cauta-probleme?tag_id%5B%5D=49\r\n\r\n\r\n* \"Backtracking\":cauta-probleme?tag_id%5B%5D=96\r\n** \"Submultimi\":cauta-probleme?tag_id%5B%5D=98\r\n\r\n\r\n* \"Divide et Impera\":cauta-probleme?tag_id%5B%5D=89\r\n** \"Ad-hoc\":cauta-probleme?tag_id%5B%5D=90\r\n\r\n\r\n* \"Matematica\":cauta-probleme?tag_id%5B%5D=40\r\n** \"Ciurul lui Eratostene\":cauta-probleme?tag_id%5B%5D=101\r\n** \"Formula\":cauta-probleme?tag_id%5B%5D=105\r\n\r\n\r\n* \"Diverse\":cauta-probleme?tag_id%5B%5D=45\r\n** \"Operatii pe biti\":cauta-probleme?tag_id%5B%5D=73',8689,'public',NULL,NULL),('portal','portal','2010-02-09 16:08:21','2010-02-18 10:41:34','h3. \"%{color:orange}Programare dinamica%\":cauta-probleme?tag_id%5B%5D=58\r\n\r\n* \"Dinamica pe stari exponentiale\":cauta-probleme?tag_id%5B%5D=59\r\n* \"Memoizare\":cauta-probleme?tag_id%5B%5D=77\r\n\r\n\r\nh3. \"Cautare\":cauta-probleme?tag_id%5B%5D=48\r\n\r\n* \"Cautare binara\":cauta-probleme?tag_id%5B%5D=49\r\n\r\n\r\nh3. \"Backtracking\":cauta-probleme?tag_id%5B%5D=96\r\n\r\n* \"Submultimi\":cauta-probleme?tag_id%5B%5D=98\r\n\r\n\r\nh3. \"Divide et Impera\":cauta-probleme?tag_id%5B%5D=89\r\n\r\n* \"Ad-hoc\":cauta-probleme?tag_id%5B%5D=90\r\n\r\n\r\nh3. \"%{color:black}Matematica%\":cauta-probleme?tag_id%5B%5D=40\r\n\r\n* \"Ciurul lui Eratostene\":cauta-probleme?tag_id%5B%5D=101\r\n* \"Formula\":cauta-probleme?tag_id%5B%5D=105\r\n\r\n\r\nh3. \"%{color:red}Teoria jocurilor%\":cauta-probleme?tag_id%5B%5D=60\r\n\r\n* \"Ad-hoc\":cauta-probleme?tag_id%5B%5D=78\r\n\r\n\r\n\r\nh3. \"Diverse\":cauta-probleme?tag_id%5B%5D=45\r\n\r\n* \"Operatii pe biti\":cauta-probleme?tag_id%5B%5D=73',8689,'public',NULL,NULL),('portal','portal','2010-02-09 16:08:21','2010-02-18 11:15:28','h3. \"%{color:orange}Programare dinamica%\":cauta-probleme?tag_id%5B%5D=58\r\n\r\n* \"Dinamica pe stari exponentiale\":cauta-probleme?tag_id%5B%5D=59\r\n* \"Dinamica pe arbore\":cauta-probleme?tag_id%5B%5D=71\r\n* \"Memoizare\":cauta-probleme?tag_id%5B%5D=77\r\n\r\n\r\nh3. \"%{color:orange}Grafuri%\":cauta-probleme?tag_id%5B%5D=46\r\n\r\n* \"Parcurgere in latime **BFS**\":cauta-probleme?tag_id%5B%5D=47\r\n* \"Parcurgere in adancime **DFS**\":cauta-probleme?tag_id%5B%5D=69\r\n* \"Algoritmul lui Dijkstra\":cauta-probleme?tag_id%5B%5D=72\r\n* \"Algoritmul Bellman-Ford\":cauta-probleme?tag_id%5B%5D=92\r\n* \"Flux maxim\":cauta-probleme?tag_id%5B%5D=268\r\n* \"Flux maxim de cost minim\":cauta-probleme?tag_id%5B%5D=93\r\n* \"Lowest Common Ancestor\":cauta-probleme?tag_id%5B%5D=82\r\n* \"Lant hamiltonian\":cauta-probleme?tag_id%5B%5D=57\r\n* \"Lant eulerian\":cauta-probleme?tag_id%5B%5D=112\r\n* \"2-SAT\":cauta-probleme?tag_id%5B%5D=87\r\n* \"Componente tare conexe\":cauta-probleme?tag_id%5B%5D=88\r\n\r\n\r\nh3. \"%{color:blue}Structuri de date%\":cauta-probleme?tag_id%5B%5D=38\r\n\r\n* \"Arbori de intervale\":cauta-probleme?tag_id%5B%5D=84\r\n* \"Range Minimum Query\":cauta-probleme?tag_id%5B%5D=83\r\n\r\n\r\n\r\nh3. \"%{color:red}Cautare%\":cauta-probleme?tag_id%5B%5D=48\r\n\r\n* \"Cautare binara\":cauta-probleme?tag_id%5B%5D=49\r\n\r\n\r\nh3. \"%{color:green}Sortare%\":cauta-probleme?tag_id%5B%5D=63\r\n\r\n* \"Sortare\":cauta-probleme?tag_id%5B%5D=64\r\n\r\n\r\nh3. \"%{color:purple}Siruri de caractere%\":cauta-probleme?tag_id%5B%5D=55\r\n\r\n* \"Parsare\":cauta-probleme?tag_id%5B%5D=67\r\n* \"KMP\":cauta-probleme?tag_id%5B%5D=56\r\n\r\n\r\nh3. \"%{color:red}Backtracking%\":cauta-probleme?tag_id%5B%5D=96\r\n\r\n* \"Submultimi\":cauta-probleme?tag_id%5B%5D=98\r\n\r\n\r\nh3. \"%{color:black}Divide et Impera%\":cauta-probleme?tag_id%5B%5D=89\r\n\r\n* \"Ad-hoc\":cauta-probleme?tag_id%5B%5D=90\r\n\r\n\r\nh3. \"%{color:black}Matematica%\":cauta-probleme?tag_id%5B%5D=40\r\n\r\n* \"Ciurul lui Eratostene\":cauta-probleme?tag_id%5B%5D=101\r\n* \"Formula\":cauta-probleme?tag_id%5B%5D=105\r\n* \"Combinatorica\":cauta-probleme?tag_id%5B%5D=281\r\n\r\n\r\n\r\n\r\nh3. \"%{color:black}Geometrie%\":cauta-probleme?tag_id%5B%5D=41\r\n\r\n* \"No fit polygon\":cauta-probleme?tag_id%5B%5D=259\r\n\r\n\r\nh3. \"%{color:red}Teoria jocurilor%\":cauta-probleme?tag_id%5B%5D=60\r\n\r\n* \"Ad-hoc\":cauta-probleme?tag_id%5B%5D=78\r\n\r\n\r\n\r\nh3. \"%{color:green}Diverse%\":cauta-probleme?tag_id%5B%5D=45\r\n\r\n* \"Operatii pe biti\":cauta-probleme?tag_id%5B%5D=73\r\n* \"Operatii pe numere mari\":cauta-probleme?tag_id%5B%5D=104',8689,'public',NULL,NULL),('runda/vot','Votati personajul preferat Infoarena','2010-03-04 12:31:13','2010-03-04 12:35:08','h1. Votati personajul preferat Infoarena\r\n\r\nAlgorel, Gigel, Zaharel au decis sa organizeze alegeri pentru a vedea care este cel mai iubit dintre personajele Infoarena. Haralambie a vrut sa concureze si el, dar n-a avut cele 10 probleme necesare intrarii in competitie. Nargy si Fumeanu, fiind prieteni nedespartiti, au decis sa intre impreuna in competitie.\r\n\r\nPentru a vota, fiecare trebuie sa trimite rezolvari la diferite probleme pe care le-au intampinat Algorel, Gigel si ceilalti, pentru ai ajuta la nevoie. Rezolvarile se trimit la runda destinata fiecaruia, fiecare problema corecta insumand 100 de voturi, cu un maxim de 1000 de voturi din partea fiecarui votant.\r\n\r\nRezultatele finale pentru fiecare se vor obtine insumand punctajele tuturor din clasament.\r\n\r\n\r\nVotarea incepe ==roundparam(round_id=\"voteaza_algorel\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"voteaza_algorel\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"voteaza_algorel\" units=\"2\") ==\r\n\r\nPentru a incepe votarea, alegeti pe cine doriti sa votati (puteti vota pe mai multi):\r\n\r\n\"Algorel\":runda/vot/voteaza_algorel\r\n\"Gigel\":runda/vot/voteaza_gigel\r\n\"Zaharel\":runda/vot/voteaza_zaharel\r\n\"Nargy si Fumeanu\":runda/vot/voteaza_nargy_si_fumeanu',8689,'public',NULL,NULL),('runda/vot','Votati personajul preferat Infoarena','2010-03-04 12:31:13','2010-03-04 12:33:26','h1. Votati personajul preferat Infoarena\r\n\r\nAlgorel, Gigel, Zaharel au decis sa organizeze alegeri pentru a vedea care este cel mai iubit dintre personajele Infoarena. Haralambie a vrut sa concureze si el, dar n-a avut cele 10 probleme necesare intrarii in competitie. Nargy si Fumeanu, fiind prieteni nedespartiti, au decis sa intre impreuna in competitie.\r\n\r\nPentru a vota, fiecare trebuie sa trimite rezolvari la diferite probleme pe care le-au intampinat Algorel, Gigel si ceilalti, pentru ai ajuta la nevoie. Rezolvarile se trimit la runda destinata fiecaruia, fiecare problema corecta insumand 100 de voturi, cu un maxim de 1000 de voturi din partea fiecarui votant.\r\n\r\nRezultatele finale pentru fiecare se vor obtine insumand punctajele tuturor din clasament.\r\n\r\nPentru a incepe votarea, alegeti pe cine doriti sa votati (puteti vota pe mai multi):\r\n\r\n\"Algorel\":runda/vot/voteaza_algorel\r\n\"Gigel\":runda/vot/voteaza_gigel\r\n\"Zaharel\":runda/vot/voteaza_zaharel\r\n\"Nargy si Fumeanu\":runda/vot/voteaza_nargy_si_fumeanu',8689,'public',NULL,NULL),('algoritmiada-2010/runda-3/solutii/cabine','Soluţie Joben','2010-02-19 19:33:46','2010-02-19 19:33:46','*Aceasta pagina trebuie sa ramana private pana la finalul concursului.*',1792,'private',NULL,NULL),('algoritmiada-2010/runda-3/solutii/semafoare','Soluţie Joben','2010-02-19 19:32:51','2010-02-19 19:32:51','*Aceasta pagina trebuie sa ramana private pana la finalul concursului.*',1792,'private',NULL,NULL),('algoritmiada-2010/runda-3/solutii/joben','Soluţie Joben','2010-02-19 19:32:01','2010-02-19 19:32:01','*Aceasta pagina trebuie sa ramana private pana la finalul concursului.*',1792,'private',NULL,NULL),('algoritmiada-2010/runda-3/solutii/karb','Soluţie Karb','2010-02-19 19:33:35','2010-02-19 19:34:53','*Aceasta pagina trebuie sa ramana private pana la finalul concursului.*',1792,'private',NULL,NULL),('problema/triunghi','Triunghi','2006-11-11 11:23:34','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"triunghi\")==\r\n\r\nLui Gigel ii place sa se joace, asa ca el a primit un joc cu cutii pe care erau scrise numere intregi stict pozitive. Avand o imaginatie bogata, el s-a gandit intr-o zi sa construiasca un triunghi de cutii astfel: o cutie este asezata peste doua cutii, care sunt asezate pe trei cutii... care sunt asezate pe $N$ cutii (deci fiecare cutie se sprijina pe alte doua). Dar Gigel nu se opreste aici, ci vrea ca numarul din fiecare cutie din triunghiul sau (mai putin ultima linie) sa fie egal cu suma numerelor din cele doua cutii de dedesubt.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care determina daca Gigel poate construi un triunghi de latura $N$, in care suma numerelor de pe toate cutiile sa fie $S$, stiind ca pot folosi oricate cutii cu orice numar in ele.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie in fisierul $triunghi.in$ se vor afla numerele $N$ si $S$ separate prin cate un spatiu.\r\n\r\nh2. Date de iesire\r\n\r\nPe primele $N$ linii din fisierul $triunghi.out$ se vor afla numerele de pe cutiile din triunghi: pe linia $i$ vor fi scrise cate $i$ numere intregi strict pozitive care descriu linia $i$ din triunghi. Daca Gigel nu poate construit un astfel de triunghi, in fisier se va afisa in schimb mesajul $imposibil$.\r\n\r\nh2. Restrictii si observatii\r\n\r\n* $1 &le; N &le; 18$\r\n* $1 &le; S &le; 1 000 000$\r\n* Daca sunt posibile mai multe solutii se va afisa oricare dintre ele\r\n\r\nExemple\r\n\r\ntable(example). |_. triunghi.in |_. triunghi.out |\r\n|3 34\r\n|13\r\n6 7\r\n1 5 2|\r\n|4 26\r\n|8\r\n4 4\r\n2 2 2\r\n1 1 1 1|\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"triunghi\")==\n\n\n',1490,'task: triunghi',44,NULL),('runda/oji-2005-ix','oji-2005-ix','2010-03-04 10:29:41','2010-03-04 10:29:41','h1. == roundparam(round_id=\"oji-2005-ix\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oji-2005-ix\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oji-2005-ix\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oji-2005-ix\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"oji-2005-ix\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/oji-2005-ix/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"oji-2005-ix\" score=\"1\")==',10498,'round: oji-2005-ix',NULL,NULL),('runda/oji-2005-ix','oji-2005-ix','2010-03-04 10:29:41','2010-03-04 10:36:18','h1. == roundparam(round_id=\"oji-2005-ix\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oji-2005-ix\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oji-2005-ix\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oji-2005-ix\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"oji-2005-ix\" units=\"2\") ==\r\n\r\nh1. Probleme\r\n\r\n==Tasks(round_id=\"oji-2005-ix\" score=\"1\")==\r\n\r\nh1. \'*Clasament*\':runda/oji-2005-ix/clasament',10498,'round: oji-2005-ix',NULL,NULL),('runda/oji-2005-ix/clasament','Clasament oji-2005-ix','2010-03-04 10:29:41','2010-03-04 10:36:56','h1. Clasament ==roundparam(round_id=\"oji-2005-ix\" param=\"title\") ==\r\n\r\n==Rankings(rounds = \"oji-2005-ix\")==',10498,'round: oji-2005-ix',NULL,NULL),('runda/j4ix','runda/oji 2004 ix','2010-03-04 08:04:05','2010-03-04 08:16:49','h1. == roundparam(round_id=\"j4ix\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"j4ix\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"j4ix\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"j4ix\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/j4ix/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"j4ix\" score=\"1\")==',10498,'public',NULL,NULL),('runda/oji-2004-ix','oji-2004-ix','2010-03-04 07:57:12','2010-03-04 07:57:12','h1. == roundparam(round_id=\"oji-2004-ix\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oji-2004-ix\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oji-2004-ix\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oji-2004-ix\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"oji-2004-ix\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/oji-2004-ix/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"oji-2004-ix\" score=\"1\")==',10498,'round: oji-2004-ix',NULL,NULL),('runda/oji-2004-ix','oji-2004-ix','2010-03-04 07:57:12','2010-03-04 08:22:22','h1. == roundparam(round_id=\"oji-2004-ix\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oji-2004-ix\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oji-2004-ix\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oji-2004-ix\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"oji-2004-ix\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/oji-2004-ix/clasament.\r\n\r\nh1. Probleme\r\n\r\n==Tasks(round_id=\"oji-2004-ix\" score=\"1\")==',10498,'round: oji-2004-ix',4598,NULL),('algoritmiada-2010/clasament/runda-4/11-12','Algoritmiada 2010 - Clasament Runda 3, Clasele 11-12','2010-02-21 12:43:41','2010-02-21 12:43:41','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda3-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-3\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-3/studenti\r\n*(active) \'Rezultate\':algoritmiada-2010/clasament/runda-3/11-12\r\n\r\n==include(page=\"template/algoritmiada-2010/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-3/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2010/clasament/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-3/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda3-11-12\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1490,'protected',NULL,NULL),('algoritmiada-2010/clasament','Algoritmiada 2010 - Clasament','2009-10-25 14:00:09','2010-01-18 15:47:13','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Clasament \r\n\r\n(htabs)*(active) \'Pe runde...\':algoritmiada-2010/clasament\r\n* \'Clasele 5-8\':algoritmiada-2010/clasament/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/studenti\r\n\r\ntable(layout). |_. Clasament Runda 1 |_. Clasament Runda 3 |\r\n|* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-1/studenti \r\n|* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-3/studenti|\r\n|_. Clasament Runda 2 | \r\n|* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-2/studenti\r\n|\r\n\r\n==Include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('algoritmiada-2010/runda-4/solutii','Solutii Algoritmiada 2010 Runda 3','2010-02-21 12:43:08','2010-02-21 12:43:08','h1. Solutii Algoritmiada 2010, Runda 3\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Joben\':algoritmiada-2010/runda-3/solutii#joben\r\n* \'Semafoare\':algoritmiada-2010/runda-3/solutii#semafoare\r\n* \'Drum3\':algoritmiada-2010/runda-3/solutii#drum3\r\n* \'Intersect\':algoritmiada-2010/runda-3/solutii#intersect\r\n* \'Karb\':algoritmiada-2010/runda-3/solutii#karb\r\n* \'Cabine\':algoritmiada-2010/runda-3/solutii#cabine\r\n* \'Piramid\':algoritmiada-2010/runda-3/solutii#piramid\r\n* \'Arbore3\':algoritmiada-2010/runda-3/solutii#arbore3\r\n\r\n==include(page=\"algoritmiada-2010/runda-3/solutii/joben\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-3/solutii/semafoare\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-3/solutii/drum3\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-3/solutii/intersect\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-3/solutii/karb\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-3/solutii/cabine\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-3/solutii/piramid\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-3/solutii/arbore3\")==',1490,'private',NULL,NULL),('algoritmiada-2010/runda-3/solutii/semafoare','Soluţie Semafoare','2010-02-19 19:32:51','2010-02-21 16:02:08','h1(#semafoare). \'Semafoare\':problema/semafoare\r\n\r\nPentru a rezolva problema, ne vom propune să calculăm $D[i][j][k] = timpul minim necesar pentru a ajunge la semaforul din intersecţia (i, j) venind din direcţia k$, unde $k$ ia valori în mulţimea ${0, 1, 2, 3}$ ce reprezintă codificări pentru cele $4$ direcţii posibile: nord, est, sud si vest. Dacă în problemă nu ar interveni semafoarele, matricea $D$ ar putea fi calculată cu uşurinţă folosind o \'parcurgere in lăţime\':problema/bfs sau, mai popular, un Lee. Totuşi, se observă că o maşină nu poate aştepta mai mult de $3$ minute la un semafor, deci costul pentru a ajunge în oricare din celulele adiacente poate fi cel mult $4$. De aceea, vom folosi 5 cozi în parcurgerea noastră: una pentru $costul curent$, una pentru $costul curent + 1$, ... şi una pentru $costul curent + 4$. Observaţia făcută mai devreme ne asigură că la pasul curent vom avea triplete $(i, j, k)$ al căror cost să depăşească $costul curent+4$, în afară de cele al căror cost este infinit (nu ştim nimc de distanţa minimă până la ele). Vom parcurge coada corespunzătoare costului curent şi vom proceda exact ca în cazul unei parcurgeri în lăţime. Când terminăm de parcurs coada curentă, vom muta coada de $cost curent + 1$ în locul celei curente, cea de $cost curent + 2$ în locul celei de $cost curent + 1$, ..., iar ultima coadă va fi vidă. Este necesar ca pentru a calcula costurile de deplasare în celulele adiacente să ştim să determinăm timpul minim în care putem intra într-o intersecţie oarecare dacă ştim că am ajuns la semaforul respectiv la momentul de timp $t$, venind din direcţia $d1$, iar pentru în această intersecţie în minutul $0$ intră maşinile din direcţia $d2$. Timpul minim căutat se poate obţine în complexitate $O(1)$ cu ajutorul următoarei formule: $(d1 - d2 - (t%4) + 8) % 4$ sau în varianta optimizată folosind operaţii pe biţi: $(d1 - d2 - (t&3) + 8) & 3$. Algoritmul prezentat procesează fiecare triplet $(i, j, k)$ de un număr constant de ori, ceea ce conduce la o complexitate totală $O(N*M)$. Acest algoritm mai poate fi aplicat în mai multe probleme precum \'Pădure\':problema/padure şi \'Car\':problema/car (soluţie \'aici\':preoni-2005/runda-2/solutii).',1792,'public',NULL,NULL),('portal','Portal Infoarena','2010-02-09 16:08:21','2010-02-18 11:36:20','h1. !portal?Portal.jpg! Selectaţi destinaţia.\r\n\r\n\r\nh3. \"%{color:orange}Programare dinamica%\":cauta-probleme?tag_id%5B%5D=58\r\n\r\n* \"Dinamica pe stari exponentiale\":cauta-probleme?tag_id%5B%5D=59\r\n* \"Dinamica pe arbore\":cauta-probleme?tag_id%5B%5D=71\r\n* \"Memoizare\":cauta-probleme?tag_id%5B%5D=77\r\n\r\n\r\nh3. \"%{color:orange}Grafuri%\":cauta-probleme?tag_id%5B%5D=46\r\n\r\n* \"Parcurgere in latime **BFS**\":cauta-probleme?tag_id%5B%5D=47\r\n* \"Parcurgere in adancime **DFS**\":cauta-probleme?tag_id%5B%5D=69\r\n* \"Algoritmul lui Dijkstra\":cauta-probleme?tag_id%5B%5D=72\r\n* \"Algoritmul Bellman-Ford\":cauta-probleme?tag_id%5B%5D=92\r\n* \"Flux maxim\":cauta-probleme?tag_id%5B%5D=268\r\n* \"Flux maxim de cost minim\":cauta-probleme?tag_id%5B%5D=93\r\n* \"Lowest Common Ancestor\":cauta-probleme?tag_id%5B%5D=82\r\n* \"Lant hamiltonian\":cauta-probleme?tag_id%5B%5D=57\r\n* \"Lant eulerian\":cauta-probleme?tag_id%5B%5D=112\r\n* \"2-SAT\":cauta-probleme?tag_id%5B%5D=87\r\n* \"Componente tare conexe\":cauta-probleme?tag_id%5B%5D=88\r\n\r\n\r\nh3. \"%{color:blue}Structuri de date%\":cauta-probleme?tag_id%5B%5D=38\r\n\r\n* \"Arbori de intervale\":cauta-probleme?tag_id%5B%5D=84\r\n* \"Range Minimum Query\":cauta-probleme?tag_id%5B%5D=83\r\n\r\n\r\n\r\nh3. \"%{color:red}Cautare%\":cauta-probleme?tag_id%5B%5D=48\r\n\r\n* \"Cautare binara\":cauta-probleme?tag_id%5B%5D=49\r\n\r\n\r\nh3. \"%{color:green}Sortare%\":cauta-probleme?tag_id%5B%5D=63\r\n\r\n* \"Sortare\":cauta-probleme?tag_id%5B%5D=64\r\n\r\n\r\nh3. \"%{color:purple}Siruri de caractere%\":cauta-probleme?tag_id%5B%5D=55\r\n\r\n* \"Parsare\":cauta-probleme?tag_id%5B%5D=67\r\n* \"KMP\":cauta-probleme?tag_id%5B%5D=56\r\n\r\n\r\nh3. \"%{color:red}Backtracking%\":cauta-probleme?tag_id%5B%5D=96\r\n\r\n* \"Submultimi\":cauta-probleme?tag_id%5B%5D=98\r\n\r\n\r\nh3. \"%{color:black}Divide et Impera%\":cauta-probleme?tag_id%5B%5D=89\r\n\r\n* \"Ad-hoc\":cauta-probleme?tag_id%5B%5D=90\r\n\r\n\r\nh3. \"%{color:black}Matematica%\":cauta-probleme?tag_id%5B%5D=40\r\n\r\n* \"Ciurul lui Eratostene\":cauta-probleme?tag_id%5B%5D=101\r\n* \"Formula\":cauta-probleme?tag_id%5B%5D=105\r\n* \"Combinatorica\":cauta-probleme?tag_id%5B%5D=281\r\n\r\n\r\n\r\n\r\nh3. \"%{color:black}Geometrie%\":cauta-probleme?tag_id%5B%5D=41\r\n\r\n* \"No fit polygon\":cauta-probleme?tag_id%5B%5D=259\r\n\r\n\r\nh3. \"%{color:red}Teoria jocurilor%\":cauta-probleme?tag_id%5B%5D=60\r\n\r\n* \"Ad-hoc\":cauta-probleme?tag_id%5B%5D=78\r\n\r\n\r\n\r\nh3. \"%{color:green}Diverse%\":cauta-probleme?tag_id%5B%5D=45\r\n\r\n* \"Operatii pe biti\":cauta-probleme?tag_id%5B%5D=73\r\n* \"Operatii pe numere mari\":cauta-probleme?tag_id%5B%5D=104',8689,'public',NULL,NULL),('articole/template-solutii','articole/template-solutii','2008-12-13 14:45:42','2009-12-22 09:14:26','* !>articole/template-solutii?algoritmiada-2010.jpg! \'Algoritmiada 2010, Runda 2\':algoritmiada-2010/runda-2/solutii\r\n* \'Algoritmiada 2010, Runda 1\':algoritmiada-2010/runda-1/solutii\r\n* \'Summer Challenge 2009, Runda 3\':summer-challenge-2009/solutii/runda-3\r\n* \'Summer Challenge 2009, Runda 2\':summer-challenge-2009/solutii/runda-2\r\n* \'Summer Challenge 2009, Runda 1\':summer-challenge-2009/solutii/runda-1\r\n* \'Grigore Moisil 2009\':grigore-moisil-2009/solutii\r\n* !>articole/template-solutii?algoritmiada-2009.jpg! \'Algoritmiada 2009, Runda 3\':algoritmiada-2009/runda-3/solutii\r\n* \'Algoritmiada 2009, Runda 2\':algoritmiada-2009/runda-2/solutii\r\n* \'Algoritmiada 2009, Runda 1\':algoritmiada-2009/runda-1/solutii\r\n* \'Junior Challenge 2008\':junior-challenge-2008/solutii\r\n* \'Grigore Moisil 2008\':grigore-moisil-2008/solutii\r\n* \'preONI 2008, Runda finala\':preoni-2008/runda-finala/solutii\r\n* !>articole/template-solutii?preoni-2008.jpg! \'preONI 2008, Runda 4\':preoni-2008/runda-4/solutii\r\n* \'preONI 2008, Runda 3\':preoni-2008/runda-3/solutii\r\n* \'preONI 2008, Runda 2\':preoni-2008/runda-2/solutii\r\n* \'preONI 2008, Runda 1\':preoni-2008/runda-1/solutii\r\n*{display: %display%} \'Winter Challenge 2008, Runda 2\':winter-challenge-2008/runda-2/solutii\r\n*{display: %display%} \'Winter Challenge 2008, Runda 1\':winter-challenge-2008/runda-1/solutii\r\n*{display: %display%} \'Happy Coding 2007\':happy-coding-2007/solutii\r\n*{display: %display%} \'Autumn Warmup 2007 runda 3\':autumn-warmup-2007/solutii/runda-3\r\n*{display: %display%} \'Autumn Warmup 2007 runda 2\':autumn-warmup-2007/solutii/runda-2\r\n*{display: %display%} \'Autumn Warmup 2007 runda 1\':autumn-warmup-2007/solutii/runda-1\r\n*{display: %display%} \'Summer Challenge 2007 runda #3\':summer-challenge-2007/solutii/runda-3\r\n*{display: %display%} \'Summer Challenge 2007 runda #2\':summer-challenge-2007/solutii/runda-2\r\n*{display: %display%} \'Summer Challenge 2007 runda #1\':summer-challenge-2007/solutii/runda-1\r\n*{display: %display%} \'Junior Challenge 2007\':junior-challenge/solutii\r\n*{display: %display%} !>articole/template-solutii?preoni-2007.jpg! \'preONI 2007 runda finala - solutii\':preoni-2007/runda-finala/solutii\r\n*{display: %display%} \'preONI 2007 runda #4 - solutii\':preoni-2007/runda-4/solutii\r\n*{display: %display%} \'preONI 2007 runda #3 - solutii\':preoni-2007/runda-3/solutii\r\n*{display: %display%} \'preONI 2007 runda #2 - solutii\':preoni-2007/runda-2/solutii\r\n*{display: %display%} \'preONI 2007 runda #1 - solutii\':preoni-2007/runda-1/solutii\r\n*{display: %display%} \'Winter Challenge 1\':winter-challenge-1/solutii\r\n*{display: %display%} \'Unirea 2007\':unirea-2007/solutii\r\n*{display: %display%} \'Solutii Autumn WarmUp 2006\':warm-up-2006/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Trei\':summer-challenge-3/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Doi\':summer-challenge-2/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Unu\':summer-challenge-unu/solutii\r\n*{display: %display%} !>articole/template-solutii?preoni-2006.gif! \'Solutii preONI 2006, Runda finala\':preoni-2006/finala/solutii\r\n*{display: %display%} \'Solutii preONI 2006, Runda a 4-a\':preoni-2006/runda-4/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda a 3-a\':preoni-2006/runda-3/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda a 2-a\':preoni-2006/runda-2/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda 1\':preoni-2006/runda-1/solutii\r\n*{display: %display%} \'preONI 2005 runda #3 - solutii\':preoni-2005/runda-3/solutii\r\n*{display: %display%} \'preONI 2005 runda #2 - solutii\':preoni-2005/runda-2/solutii\r\n*{display: %display%} \'preONI 2005 runda #1 - solutii\':preoni-2005/runda-1/solutii\r\n*{display: %display%} \'Happy Coding 3 [2006]\':happy-coding-2006/solutii\r\n*{display: %display%} \'Happy Coding 2 [2005]\':happy-coding-2005-2/solutii\r\n*{display: %display%} \'Happy Coding 1 [2005]\':happy-coding-2005-1/solutii\r\n*{display: %display%} \'Concursul Agora - Etapa Finala - Solutii\':agora-finala/solutii\r\n*{display: %display%} \'Doua probleme de la runda 6 a concursului Algoritmus\':doua-probleme-de-la-runda-6-a-concursului-algoritmus\r\n*{display: %display%} \'USACO dec 2005, divizia GOLD\':usaco-dec-2005-divizia-gold \r\n*{display: %display%} \'USACO nov 2005, divizia GOLD\':usaco-nov-2005-divizia-gold\r\n*{display: %display%} \'USACO oct 2005, divizia GOLD\':usaco-oct-2005-divizia-gold\r\n*{display: %display%} \'USACO ian 2005, divizia GOLD\':usaco-ian-2005-divizia-gold\r\n*{display: %display%} \'USACO dec 2004, divizia GOLD\':usaco-dec-2004-divizia-gold\r\n*{display: %display%} \'Solutiile oficiale pentru Concursul &quot;de incalzire&quot;\':warm-up-2004/solutii',2044,'protected',NULL,NULL),('marturii','Marturiile utilizatorilor infoarena','2007-05-15 00:33:16','2010-03-08 19:20:20','h1. Marturii despre infoarena\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nDaca esti utilizator infoarena si consideri ca site-ul nostru te-a ajutat in vreun fel, te rugam sa ne scrii o marturie, similara cu cele deja existente in aceasta pagina. Ne intereseaza pareri cat mai sincere, indiferent ca sunt pozitive sau negative.\r\n\r\nClick pe _Editeaza_ ca sa adaugi marturia ta. Te rugam sa respecti stilul de formatare existent.\r\n\r\n&nbsp;\r\n\r\nbq. infoarena este un proiect remarcabil, realizat cu entuziasm, generozitate si profesionalism. Este locul in care tinerii pasionati de informatica se pot intalni, atat de o parte, cat si de cealalta parte a baricadei, ca propunatori sau ca rezolvitori de probleme, isi pot impartasi experienta competitionala, pot constitui modele, pot ajuta la formarea a noi si noi generatii de performanta. *Emanuela Cerchez*\r\n\r\n&nbsp;\r\n\r\nbq. infoarena e plin de energie, e dinamic si riguros, gratie unei echipe curajoase. Site-ul infoarena reprezinta cea mai originala forma de pregatire pe net a performerilor in informatica din Romania. Mecanism de lucru excelent, probleme propuse, fara cusur. Felicitari! *Emil Onea*\r\n\r\n&nbsp;\r\n\r\nbq. infoarena m-a adus aproape de oameni extraordinari, prieteni care m-au invatat nenumarate lucruri despre informatica, generozitate, entuziasm si dedicare. Putine lucruri sunt mai importante decat un anturaj EXEMPLAR. Intr-un fel, pot sa spun ca infoarena mi-a schimbat viata. == user(type=\"tiny\" user=\"wickedman\")==\r\n\r\n&nbsp;\r\n\r\nbq. infoarena a fost cea mai importanta sursa de probleme in pregatirea mea si a colegilor mei pentru olimpiadele nationale, dar si un mod bun de a invata cate ceva despre evaluatoarele folosite la concursuri. Pentru mine, cel putin, accesul la surse mi-a creat si o perspectiva despre modul in care se construieste o aplicatie ce ia in cosiderare toate cazurile, oricat de improbabile ar fi ele. == user(type=\"tiny\" user=\"salgau_catalin\")==\r\n\r\n&nbsp;\r\n\r\nbq. Cred ca in Romania exista poli puternici (Bucuresti, Iasi) legati de profesori valorosi si copii pasionati dar izolati. Aici intervine infoarena: cultiva spiritul competitiv din fiecare, te motiveaza, creaza comunitatea de care avem nevoie ca sa evoluam. Propune un joc in care te implici initial din curioziate, pentru a deveni in scurt timp dependent indiferent daca lucrezi pentru internationala, pentru judeteana sau ca sa obtii un rating mai bun decat vecinul de pe scara. ;) == user(type=\"tiny\" user=\"DigitAll\")==\r\n\r\n&nbsp;\r\n\r\nbq. Infoarena este un proiect foarte important in pregatirea olimpicilor romani de informatica. Nu numai ca este o sursa constanta de probleme, dar fiecare utilizator poate sa vada unde se situeaza in comparatie cu ceilalti, fiecare stie ce-i poate pielea. Sa nu mai vorbim de constantele concursuri online unde utilizatorii pot concura intre ei. Pe mine personal infoarena m-a ajutat foarte mult...  == user(type=\"tiny\" user=\"Darth_Niculus\")==\r\n\r\n&nbsp;\r\n\r\nbq. La inceput, infoarena a insemnat pentru mine un joc nascut dintr-o dorinta puternica de rascumpara macar o parte din ce am primit in postura de invatacel de la oamenii extraordinari cu care am interactionat, fie ei profesori sau prieteni. Pe parcurs a devenit concretizarea visului meu de olimpic la informatica din provincie: un site unde sa gasesti oameni la fel de pasionati de informatica ca si tine, probleme, resurse si link-uri, toate intr-un singur loc. == user(type=\"tiny\" user=\"silviug\")==\r\n\r\n&nbsp;\r\n\r\nbq. Pentru mine infoarena a insemnat practic contactul cu adevarata lume a informaticii. Pana atunci informatica pentru mine era doar o pasiune, insa de abia cand am intrat pe infoarena am realizat cat de vast este acest domeniu. Aici am invatat cam 90% din ce stiu acum, si cu siguranta mai am multe de invatat de pe acest site. In acest moment infoarena este o comunitate, o comunitate de olimpici care se ajuta intre ei, facand schimb de idei si invatand unul de la altul. == user(type=\"tiny\" user=\"devilkind\")==\r\n\r\n&nbsp;\r\n\r\nbq. Infoarena este cu adevarat un proiect de exceptie care a reusit sa se dezvolte enorm in cursul celor 3 ani de activitate. Infoarena nu este doar un loc unde te pregatesti pentru concursurile de informatica. Este un loc unde poti cunoaste persoane cu aceleasi pasiuni ca si tine, un loc in care se aduna toti cei care au spirit competitiv si doresc sa se perfectioneze in domeniul programarii. Zeci de utilizatori contribuie efectiv la dezvoltarea si imbunatatirea site-ului ca developeri, propunatori de probleme sau moderatori pe forum. Este cu adevarat o comunitate! == user(type=\"tiny\" user=\"filipb\")==\r\n\r\n&nbsp;\r\n\r\nbq. Atunci cand ma aflam la inceput de drum, infoarena a fost locul unde am intalnit ceea ce imi doream, probleme grele care sa imi dea batai ce cap, o comunitate prietenoasa care sa imi dea sfaturi, si posibilitatea de a participa la concursuri in conditii similare celor de la olimpiada. Am invatat foarte mult aici, si sper sa pot contribui si eu la dezvoltarea acestui proiect, care aduna in fiecare an tot mai multi elevi pasionati din intreaga tara. == user(type=\"tiny\" user=\"wefgef\")==\r\n\r\n&nbsp;\r\n\r\nbq. infoarena a fost comunitatea care mi-a trezit pasiunea pentru informatica. E un proiect extraordinar, prin care, nu numai ca inveti cu adevarat tainele algoritmicii si programarii, lucru care te ajuta in mod deosebit la concursuri si olimpiade, dar iti faci si foarte multi prieteni. Aici gasesti mereu oameni care sunt gata sa te ajute, sa-ti ofere informatii noi, gasesti mereu o problema interesanta in arhiva, si de asemenea, gasesti mereu o competitie (interna sau nu) la care sa poti participa on-line, comod, si care sa te ajute cu pregatirea in regim de concurs. Pe langa comunitate, arhiva si concursuri, sunt accesibile numeroase articole. Sectiunea \"Links\" si \"Downloads\" sunt si ele indispensabile vietii de programator. == user(type=\"tiny\" user=\"Florian\")==\r\n\r\n&nbsp;\r\n\r\nbq. Foarte putine lucruri m-au ajutat mai mult in viata decat participarea la concursurile nationale si internationale de informatica. De asemenea, nu multe au fost resursele prin intermediul carora am reusit sa concurez de la egal la egal cu elevii care aveau deja rezultate bune si o experienta mai mare decat a mea. infoarena e una din aceste resurse: proaspata, inedita, si propulsata de o comunitate plina de pasiune si entuziasm. Le multumesc tuturor celor care au facut ca infoarena sa devina realitate, si sper ca toti cei implicati intr-un fel sau altul in olimpiadele de informatica sa profite la maxim si sa aprecieze la randul lor acest proiect remarcabil. == user(type=\"tiny\" user=\"greco\")==\r\n\r\n&nbsp;\r\n\r\nbq. infoarena este pentru mine \"persoana\" care ma impinge de la spate sa lucrez, uneori simt ca ma pot depasi pe mine; sunt si voi fi recunoscator tuturor celor de aici care m-au ajutat si o vor face in continuare; am doar cuvinte de lauda. BRAVO == user(type=\"tiny\" user=\"DraStiK\")==\r\n\r\n&nbsp;\r\n\r\nbq. Infoarena este site-ul care te ajuta sa faci performanta deoarece problemele pot fi facute in multe moduri. Cand esti mic iei cateva puncte, dar cand vei fi mare vei gasi rezolvarea care iti va aduce punctajul maxim. Te ajuta sa tii minte cand ai folosit o metoda si cum si de aceea Infoarena este unul dintre cele mai bune site-uri de pregatire == user(type=\"tiny\" user=\"Andrici_Cezar\")==\r\n\r\n&nbsp;\r\n\r\nbq. Infoarena a fost \"prietenul\" care mi-a aratat primii pasi spre adevarata informatica, cea in care trebuie sa muncesti ca sa progresezi. Acest simplu \"site\" s-a transformat acum intr-o adevarata comunitate cu multi pasionati ai informaticii, de la care poti invata multe. Infoarena va ramane mereu o sursa de inspiratie pentru mine. == user(type=\"tiny\" user=\"spiderman\")==\r\n\r\n.',8239,'public',NULL,NULL),('utilizator/marius','Profil Marius','2006-11-24 21:03:36','2010-01-19 13:02:09','h2. Despre mine\r\n\r\n* Am terminat liceul Colegiul National I.C. Bratianu din Piteşti. Acum sunt student la Facultatea de Informatică a Universităţii Babeş Bolyai din Cluj.\r\n\r\n* Îmi place să fac sport, să călătoresc, să citesc, să conduc, să ascult, să mixez muzică. \r\n\r\n* Citatul preferat: \"Quitters don\'t win, winners don\'t quit\"\r\n\r\n* În colaborare cu == user(user=\"stef2n\" type=\"tiny\") == am dezvoltat \'pluginul\':http://code.google.com/p/pidgin-embeddedvideo/ pentru \'Pidgin\':http://pidgin.im ce permite vizualizarea clipurilor video direct în conversaţie.\r\n\r\nh2. Distincţii primite\r\n\r\n* Menţiune şi Premiul Special, _ONI 2007_, Cluj, locul 4.\r\n\r\n* Calificat în _lotul naţional, 2007_.\r\n\r\n* Finalist _preONI 2007_.\r\n\r\n* Participant, pe bază de invitaţie, la concursul _Stelele Informaticii 2008_.\r\n\r\n* Menţiune, _ONI 2008_, Ploieşti, locul 8 şi argint.\r\n\r\n* Membru în comisia concursului interjudeţean de matematică şi informatică _Grigore Moisil, 2009_.\r\n\r\n* Membru în comisia _lotului naţional de informatică, 2009_.\r\n\r\n* Deputy Leader al delegaţiei României la _CEOI, 2009_.\r\n\r\nh2. Eu şi info{_arena_}\r\n\r\nArticole pe care le-am scris:\r\n\r\n* \'Tree decompositions\':tree-decompositions\r\n* \'Treapuri\':treapuri\r\n* \'Deque şi aplicaţii\':deque-si-aplicatii\r\n\r\nProbleme pe care le-am adăugat în arhiva educaţională:\r\n\r\n* \'Cuplaj maxim în graf bipartit\':problema/cuplaj\r\n* \'Componente tare conexe\':problema/ctc\r\n* \'Componente biconexe\':problema/biconex\r\n* \'Subsecvenţa de sumă maximă\':problema/ssm\r\n* \'Parantezare optimă de matrici\':problema/podm\r\n\r\nAr fi fost mai multe dacă nu aş fi fost şi coordonator. :)',3146,'protected',NULL,NULL),('newsletter/ai-mas-winter-olympics','AI-MAS Winter Olympics','2010-02-26 17:40:22','2010-02-26 18:00:36','În acest weekend are loc \'*AI-MAS Winter Olympics*\':http://www.aiolympics.ro, un mare eveniment destinat inteligenţei artificiale organizat de laboratorul AI-MAS din cadrul Universităţii Politehnice din Bucureşti. Pentru a înţelege mai bine despre ce e vorba, vă invităm să citiţi prezentarea evenimentului:\r\n\r\nbq. Te-ai întrebat vreodată pentru ce înveţi toţi aceşti algoritmi? Olimpiadele sunt fun, concursurile de informatică îţi dau adrenalină, dar asta nu e totul! Cunoştinţele pe care le dobândeşti te pregătesc pentru a ataca cele mai dificile probleme nerezolvate din Computer Science.\r\n\r\nAI-MAS Winter Olympics este un eveniment dedicat *Inteligeţei Artificiale*. Organizat de laboratorul AI-MAS al Universităţii Politehnica Bucureşti, acest eveniment vrea să îţi arate că inteligenţa artificială nu este numai în filme SF sau în laboratoare avansate, ci este ceva care există şi care deja îţi face viaţa mai uşoară. Mai mult de atât, este o direcţie pe care o poţi urma şi în care pregătirea ta de olimpic poate face o diferenţă !\r\n\r\nComponenta principală a evenimentului este \'Workshop On Real Life Applications\':http://www.aiolympics.ro/eveniment/, o serie de prezentări în care companii mari îţi vor arăta cum inteligenţa artificială le oferă un avantaj competitiv. Ingineri din partea *Facebook* vin pentru prima oară în România, alături de membri ai Academiei Române şi reprezentati ai unor companii importante: IBM, BitDefender, Thales, Kaspersky, Ropardo. Suntem siguri că subiectele discutate îţi vor deschide apetitul pentru inteligenţă artificială.\r\n\r\nÎn plus vei putea vizita *AI-MAS Village*, un loc cu aplicaţii interesante care folosesc tehnici de AI, cu roboţi de tip line-follower şi alţii mai inediţi. În pauzele workshop-ului vom proiecta finala competiţiei Crafting Quest -- meciuri AI vs AI între agenţi inteligenţi. Vei putea discuta cu vorbitorii de la workshop, cu companiile prezente şi cu alţi pasionaţi de acest domeniu.\r\n\r\nEvenimentul are loc *sâmbătă, 27 februrarie,* în holul EC al Facultăţii de Automatică şi Calculatoare, UPB. Pentru a participa, este nevoie să te \'înregistrezi\':http://www.aiolympics.ro/eveniment/inregistrare/?code=infoar pe site-ul evenimentului; special pentru utilizatorii Infoarena, poţi folosi codul *infoar* la înregistrare. Pentru a avea asigurat un loc în amfiteatrul principal este nevoie să te prezinţi la eveniment între orele 8.00 - 9.00. Evenimentul se termină în jurul orei 18.00 şi este urmat de un after-party cu karaoke.\r\n\r\nTe aşteptăm!',1792,'public',NULL,NULL),('newsletter/ai-mas-winter-olympics','AI-MAS Winter Olympics','2010-02-26 17:40:22','2010-02-26 18:08:53','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎn acest weekend are loc \'*AI-MAS Winter Olympics*\':http://www.aiolympics.ro, un mare eveniment destinat inteligenţei artificiale organizat de laboratorul AI-MAS din cadrul Universităţii Politehnice din Bucureşti. Pentru a înţelege mai bine despre ce e vorba, vă invităm să citiţi prezentarea evenimentului:\r\n\r\nbq. Te-ai întrebat vreodată pentru ce înveţi toţi aceşti algoritmi? Olimpiadele sunt fun, concursurile de informatică îţi dau adrenalină, dar asta nu e totul! Cunoştinţele pe care le dobândeşti te pregătesc pentru a ataca cele mai dificile probleme nerezolvate din Computer Science.\r\n\r\nbq. AI-MAS Winter Olympics este un eveniment dedicat *Inteligeţei Artificiale*. Organizat de laboratorul AI-MAS al Universităţii Politehnica Bucureşti, acest eveniment vrea să îţi arate că inteligenţa artificială nu este numai în filme SF sau în laboratoare avansate, ci este ceva care există şi care deja îţi face viaţa mai uşoară. Mai mult de atât, este o direcţie pe care o poţi urma şi în care *pregătirea ta de olimpic poate face o diferenţă*!\r\n\r\nbq. Componenta principală a evenimentului este \'Workshop On Real Life Applications\':http://www.aiolympics.ro/eveniment/, o serie de prezentări în care companii mari îţi vor arăta cum inteligenţa artificială le oferă un avantaj competitiv. Ingineri din partea *Facebook* vin pentru prima oară în România, alături de membri ai Academiei Române şi reprezentati ai unor companii importante: IBM, BitDefender, Thales, Kaspersky, Ropardo. Suntem siguri că subiectele discutate îţi vor deschide apetitul pentru inteligenţă artificială.\r\n\r\nbq. În plus vei putea vizita *AI-MAS Village*, un loc cu aplicaţii interesante care folosesc tehnici de AI, cu roboţi de tip line-follower şi alţii mai inediţi. În pauzele workshop-ului vom proiecta finala competiţiei Crafting Quest -- meciuri AI vs AI între agenţi inteligenţi. Vei putea discuta cu vorbitorii de la workshop, cu companiile prezente şi cu alţi pasionaţi de acest domeniu.\r\n\r\nbq. Evenimentul are loc *sâmbătă, 27 februrarie,* în holul EC al Facultăţii de Automatică şi Calculatoare, UPB. Pentru a participa, este nevoie să te \'înregistrezi\':http://www.aiolympics.ro/eveniment/inregistrare/?code=infoar pe site-ul evenimentului; special pentru utilizatorii Infoarena, poţi folosi codul *infoar* la înregistrare. Pentru a avea asigurat un loc în amfiteatrul principal este nevoie să te prezinţi la eveniment între orele 8.00 - 9.00. Evenimentul se termină în jurul orei 18.00 şi este urmat de un after-party cu karaoke.\r\n\r\nbq. Te aşteptăm!',1792,'public',NULL,NULL),('runda/problemiada_12','Problemiada #12','2010-02-28 18:08:03','2010-02-28 18:15:47','h1. == roundparam(round_id=\"problemiada_12\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"problemiada_12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"problemiada_12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"problemiada_12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"problemiada_12\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/problemiada_12/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"problemiada_12\" score=\"1\")==',5748,'round: problemiada_12',NULL,NULL),('implica-te/arhiva-educationala','Arhiva educaţională','2008-02-23 13:13:01','2010-02-27 19:34:36','h1. Arhiva educationala ==Stars(rating=\"5\")==\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie. Mai multe despre acest proiect gasiti \'aici\':propuneri/6-arhiva-educationala.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Cum ne poti ajuta?\':implica-te/arhiva-educationala#cum\r\n* \'Echipa implicata in proiect\':implica-te/arhiva-educationala#echipa\r\n* \'Documentatie\':implica-te/arhiva-educationala#documentatie\r\n* \'Continutul arhivei\':implica-te/arhiva-educationala#probleme\r\n\r\nh2(#cum). Cum ne poti ajuta?\r\n\r\n1. Ofera sugestii la dezvoltarea proiectului.\r\n2. Contribuie cu feedback pentru a imbunatati calitatea problemelor existente.\r\n3. Vino cu idei pentru probleme noi.\r\n\r\nAjuta si tu la randul tau comunitatea infoarena! \r\n\r\nh2(#echipa). Echipa implicata in proiect\r\n\r\nEchipa care este implicata activ in acest proiect este alcatuita din urmatorii membri:\r\n\r\n* == user(user=\"Marius\" type=\"tiny\") ==, coordonator de proiect\r\n* == user(user=\"savim\" type=\"tiny\") ==\r\n* == user(user=\"cezarmocan\" type=\"tiny\") ==\r\n* == user(user=\"GavrilaVlad\" type=\"tiny\") ==\r\n* == user(user=\"mishu91\" type=\"tiny\") ==\r\n* == user(user=\"GheorgheMihai\" type=\"tiny\") ==\r\n\r\nPe langa cei de mai sus, de-a lungul timpului au contribuit considerabil la acest proiect \'o serie de alti membri ai comunitatii infoarena\':implica-te/arhiva-educationala/membri-emeritus. Le multumim pe aceasta cale!\r\n\r\nh2(#documentatie). Documentatie\r\n\r\nFiecare voluntar are obligatia sa citeasca urmatoarele materiale inainte de a putea trece efectiv la lucru:\r\n\r\n* \'Editare de probleme\':documentatie/editare-de-probleme\r\n* \'Ghid evaluator\':documentatie/ghid-evaluator\r\n* \'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala\r\n\r\nh2(#probleme). Continutul arhivei\r\n\r\nIn tabelul de mai jos se afla probleme la care se lucreaza in momentul de fata. Finalizarea lor reprezinta unul dintre $OKR$-urile din trimestrul IV, 2009. Pentru a va familiariza si cu restul obiectivelor din acest trimestru, cititi \'aici\':okr.\r\n\r\ntable(example). |_. Denumire problema|_. Voluntar|_. Finalizat|_. Review |\r\n| \'Arbori de intervale (aplicaţie cu 4 tipuri de operaţii)\':problema/arbint2 | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Arbori de intervale 2D\':problema/arbint2d | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'NIM\':problema/nim | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Punct în poligon oarecare\':problema/pinpo | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Treapuri\':problema/treapuri | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Interclasarea a doi vectori sortati\':problema/interclas | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Aria unui poligon\':problema/ariapoli | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa maximă între două puncte în plan\':problema/cmdp | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Arbori de căutare\':problema/arbcautare | ==user(user=\"bogdan2412\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n\r\nIn tabelul de mai jos se afla sugestii privind algoritmii care trebuie sa se gaseasca sub forma de probleme in arhiva educationala. Puteti veni oricand cu propuneri si sugestii de probleme noi pe \"forum\":/forum/index.php?topic=3401.0.\r\n\r\ntable(example). |_. Denumire problema|_. Categoria|\r\n| Dreptunghiul de arie maximă (?) | Divide et impera |\r\n|Knapsack|Programare dinamica|\r\n|Sprague-Grundy|Teoria jocurilor|\r\n|Algoritmul lui Gauss|Matematica|\r\n|Numerele lui Stirling|Matematica|\r\n| Principiul lui Dirichlet | Matematică |\r\n|Problema de acoperire|Programare dinamica + Backtracking|\r\n|Algoritmul Stoer-Wagner|Algoritmi pe grafuri|\r\n|Heavy Path Decomposition|Algoritmi pe grafuri|\r\n|Arbore -> cod Prufer|Algoritmi pe grafuri|\r\n|Cod Prufer -> arbore|Algoritmi pe grafuri|\r\n|Distanta maxima intre 2 noduri intr-un arbore|Algoritmi pe grafuri|\r\n|Siruri de sufixe|Siruri de caractere|\r\n|Arbori de sufixe|Siruri de caractere|\r\n|Automate - Aho Corasick|Siruri de caractere|\r\n|Algoritmi {$O(sqrtN)$}|Structuri de date|\r\n|Ortogonal Range Search|Structuri de date|\r\n|Intersectia a doua drepte|Geometrie|\r\n|Punct in poligon convex|Geometrie|\r\n|Diagrame Voronoi|Geometrie|\r\n|Minimum enclosing circle|Geometrie|\r\n|Sortare prin numarare|Diverse|\r\n|RadixSort|Diverse|\r\n|Operatii pe numere mari|Diverse|\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"61\")==',3146,'protected',NULL,NULL),('newsletter/dot-com-2009-2','newsletter/dot-com-2009-2','2010-03-03 10:47:26','2010-03-03 10:47:26','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nIată că a venit primăvara şi mai este doar o lună pana la olimpiada naţională. Nu-i aşa că trece repede timpul...? Pe ultima sută de metri, infoarena te antrenează cu două concursuri importante!\r\n\r\nTe invităm să participi la runda a doua a concursului organizat de membrii comunităţii, .com 2009.\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Prima rundă se desfăşoară\r\n*Duminică, 14 martie, orele 09^00^ - 14^00^*. |\r\n\r\nVezi \'pagina concursului\':dot-com/2009 ca să afli cum poţi participa.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"dot-com/2009/runda-1\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre .com 2009\r\n\r\nConcursul are o singură grupă valorică, dar cele 3 probleme propuse au dificultăţi variind între gimnaziu şi liceu clasele 11-12.\r\n\r\nOrganizatorii concursului sunt:\r\n\r\n* \'Stan Şerban Andrei\':utilizator/savim\r\n* \'Cezar Mocan\':utilizator/cezarmocan\r\n* \'Radu Zernoveanu\':utilizator/raduzer\r\n* \'Teodor Anton Pripoae\':utilizator/toni2007\r\n* \'Mihai Gheorghe\':utilizator/gheorghemihai\r\n* \'Cosmin Mihai Tutunaru\':utilizator/stocarul',3997,'public',NULL,NULL),('runda/vot/voteaza_miruna','Voteaza Miruna','2010-03-05 17:11:16','2010-03-05 17:11:16','h1. Voteaza Miruna\r\n\r\n_Miruna este curajoasa si nonconformista, stiind sa rezolve problemele simplu si eficient._\r\n\r\nAici puteti vota pentru Miruna in cadrul \"concursului de vot al personajului preferat Infoarena\":runda/vot.\r\n\r\nVotarea incepe ==roundparam(round_id=\"voteaza_miruna\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"voteaza_miruna\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"voteaza_miruna\" units=\"2\") ==\r\n\r\n\'*Rezultate*\':runda/vot/voteaza_miruna/clasament\r\n\r\nh2. Itemi de vot\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"voteaza_miruna\" score=\"1\")==',8689,'public',NULL,NULL),('runda/voteaza_miruna','voteaza_miruna','2010-03-05 17:01:52','2010-03-05 17:01:52','h1. == roundparam(round_id=\"voteaza_miruna\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"voteaza_miruna\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"voteaza_miruna\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"voteaza_miruna\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"voteaza_miruna\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/voteaza_miruna/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"voteaza_miruna\" score=\"1\")==',8689,'round: voteaza_miruna',NULL,NULL),('runda/x-treme_april_challenge','x-treme_april_challenge','2010-03-05 17:44:07','2010-03-05 17:44:07','h1. == roundparam(round_id=\"x-treme_april_challenge\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"x-treme_april_challenge\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"x-treme_april_challenge\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"x-treme_april_challenge\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"x-treme_april_challenge\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/x-treme_april_challenge/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"x-treme_april_challenge\" score=\"1\")==',8689,'round: x-treme_april_challenge',NULL,NULL),('concursuri','Concursuri organizate de infoarena','2006-11-05 23:17:11','2010-02-07 22:14:40','h1. Concursuri organizate de infoarena\r\n\r\nIn aproape 4 ani de activitate, infoarena a organizat cateva zeci de concursuri/runde online. Fiecare concurs are un format aparte. De la o runda la cinci, de la cateva ore la cateva zile sau chiar o saptamana, de la cateva probleme la 20, concursurile infoarena variaza in amploare, dificultate si popularitate.\r\n\r\n(toc)*{text-align:center} *Concursuri*\r\n* \'Algoritmiada\':concursuri#algoritmiada\r\n* \'preONI\':concursuri#preoni\r\n* \'Happy Coding\':concursuri#happy\r\n* \'.com\':concursuri#dot-com\r\n* \'Autumn Warmup\':concursuri#autumn\r\n** \'Autumn Warmup 2007\':concursuri#autumn2007\r\n** \'Autumn Warmup 2006\':concursuri#autumn2006\r\n* \'Summer Challenge\':concursuri#summer\r\n** \'Summer Challenge 2009\':concursuri#summer2009\r\n** \'Summer Challenge 2007\':concursuri#summer2007\r\n** \'Summer Challenge 2006\':concursuri#summer2006\r\n* \'Alte concursuri\':concursuri#others\r\n\r\nh2(#algoritmiada). Algoritmiada\r\n\r\nNoul concurs _de marca_ infoarena isi propune sa ii pregateasca pe toti pasionatii de algoritmi.\r\n\r\ntable(layout). |_. Algoritmiada 2010 (\'pagina concursului\':algoritmiada-2010)|\r\n|* !>template/algoritmiada-2010/header?logo2010.jpg! *{\'Runda 1\':algoritmiada-2010/runda-1}*\r\n* *{\'Runda 2\':algoritmiada-2010/runda-2}*\r\n* *{\'Runda 3\':algoritmiada-2010/runda-3}*\r\n* *{\'Runda 4\':algoritmiada-2010/runda-4}*\r\n* *{\'Runda Finala\':algoritmiada-2010/runda-finala}*|\r\n\r\ntable(layout). |_. Algoritmiada 2009 (\'pagina concursului\':algoritmiada-2009)|\r\n|* !>template/algoritmiada-2009/header?logo.jpg! *{\'Runda 1\':algoritmiada-2009/runda-1}*\r\n* *{\'Runda 2\':algoritmiada-2009/runda-2}*\r\n* *{\'Runda 3\':algoritmiada-2009/runda-3}*\r\n* *{\'Runda Finala\':algoritmiada-2009/runda-finala}*|\r\n\r\nh2(#preoni). Seria preONI\r\n\r\nTimp de 5 ani a fost cel mai important concurs organizat de infoarena. Scopul sau era sa pregateasca elevii pentru \"Olimpiada Nationala de Informatica\":http://olimpiada.info/.\r\n\r\ntable(layout). |_. preONI 2008 (\'pagina concursului\':preoni-2008)|\r\n|* !>template/preoni-2008/header?a.jpg! *{\'Runda 1\':preoni-2008/runda-1}*\r\n* *{\'Runda 2\':preoni-2008/runda-2}*\r\n* *{\'Runda 3\':preoni-2008/runda-3}*\r\n* *{\'Runda 4\':preoni-2008/runda-4}*\r\n* *{\'Runda Finala\':preoni-2008/runda-finala}*|\r\n\r\ntable(layout). \r\n|_. preONI 2007 (\'pagina concursului\':preoni-2007)|_. preONI 2006 (\'pagina concursului\':preoni-2006) |\r\n|*  !>template/preoni-2007/header?logo.jpg 70%! *{\'Runda 1\':preoni-2007/runda-1}* \r\n* *{\'Runda 2\':preoni-2007/runda-2}*\r\n* *{\'Runda 3\':preoni-2007/runda-3}*\r\n* *{\'Runda 4\':preoni-2007/runda-4}*\r\n* *{\'Runda Finala\':preoni-2007/runda-finala}*\r\n|*  !>template/preoni-2006?hlogo.gif! *{\'Runda 1\':preoni-2006/runda-1}*\r\n* *{\'Runda 2\':preoni-2006/runda-2}*\r\n* *{\'Runda 3\':preoni-2006/runda-3}*\r\n* *{\'Runda 4\':preoni-2006/runda-4}*\r\n* *{\'Finala in Focsani\':preoni-2006/finala}*|\r\n|_. preONI 2005 (\'pagina concursului\':preoni-2005)|_. preONI 2004 (\'pagina concursului\':preoni-2004)|\r\n|* *{\'Runda 1\':preoni-2005/runda-1}*\r\n* *{\'Runda 2\':preoni-2005/runda-2}*\r\n* *{\'Runda 3\':preoni-2005/runda-3}*\r\n|* *{\'Runda 1\':preoni-2004/runda-1}*\r\n* *{\'Runda 2\':preoni-2004/runda-2}*|\r\n\r\nh2(#happy). Happy Coding\r\n\r\nUn concurs infoarena mai neobisnuit. _Happy Coding inseamna programare cu zambetul pe buze, placere si distractie pura!_\r\n\r\nConcursurile Happy Coding dispun de evaluator live si au timp de lucru lejer. Nu vei mai fi stresat de pana la aflarea rezultatelor. Afli pe loc daca solutiile tale sunt bune. In plus, poti lucra si ziua si noaptea, dupa sau in timpul orelor de scoala.\r\n\r\n!>happy-coding-2005-1?logo.jpeg!\r\n\r\n* \'*Happy Coding 2008*\':happy-coding-2008\r\n* \'*Happy Coding 2007*\':happy-coding-2007\r\n* *{\'Happy coding 1 (2005)\':happy-coding-2005-1}*\r\n* *{\'Happy coding 2\':happy-coding-2005-2}*\r\n* *{\'Happy coding 3 (2006)\':happy-coding-2006}*\r\n\r\nh2(#dot-com). .com\r\n\r\n==include(page=\"dot-com/description\")==\r\n\r\nh3(#dot-com2009). .com 2009 (\'pagina concursului\':dot-com/2009)\r\n\r\n* *{\'Runda 1\':dot-com/2009/runda-1}*\r\n\r\nh2(#autumn). Autumn Warmup\r\n\r\nh3(#autumn2007). Autumn Warmp 2007 (\'pagina concursului\':autumn-warmup-2007)\r\n\r\n* *{\'Runda 1\':autumn-warmup-2007/runda-1}*\r\n* *{\'Runda 2\':autumn-warmup-2007/runda-2}*\r\n* *{\'Runda 3\':autumn-warmup-2007/runda-3}*\r\n\r\nh3(#autumn2006). {\'Autumn Warmup 2006\':warm-up-2006}\r\n\r\nh2(#summer). Summer Challenge\r\n\r\nO serie noua de concursuri infoarena. Acestea se organizeaza in timpul vacantei de vara pentru cei care nu vor _sa-si iasa din mana_. :)\r\n\r\nh3(#summer2009). Summer Challenge 2009 (\'pagina concursului\':summer-challenge-2009)\r\n\r\n* *{\'Runda 1\':summer-challenge-2009/runda-1}*\r\n* *{\'Runda 2\':summer-challenge-2009/runda-2}*\r\n* *{\'Runda 3\':summer-challenge-2009/runda-3}*\r\n\r\nh3(#summer2007). Summer Challenge 2007 (\'pagina concursului\':summer-challenge-2007)\r\n\r\n* *{\'Runda 1\':summer-challenge-2007/runda-1}*\r\n* *{\'Runda 2\':summer-challenge-2007/runda-2}*\r\n* *{\'Runda 3\':summer-challenge-2007/runda-3}*\r\n\r\nh3(#summer2006). Summer Challenge 2006\r\n\r\n!>summer-challenge-unu?logo!\r\n\r\n* *{\'Runda 1\':summer-challenge-unu}*\r\n* *{\'Runda 2\':summer-challenge-2}*\r\n* *{\'Runda 3\':summer-challenge-3}*\r\n\r\nh2(#others). Alte concursuri infoarena\r\n\r\n* *{\'Concursul Centrelor de Excelenta 2009\':ccex2009}*\r\n* *{\'Grigore Moisil 2009\':grigore-moisil-2009}*\r\n* *{\'Stelele Informaticii 2009\':stelele-2009}*\r\n* *{\'All you can code 2008\':all-you-can-code-2008}*\r\n* *{\'Selectie echipe ACM ICPC, UPB 2008\':acm-icpc-upb-2008}*\r\n* *{\'Junior Challenge 2008\':junior-challenge-2008}*\r\n* *{\'Grigore Moisil 2008\':grigore-moisil-2008}*\r\n* *{\'Winter Challenge 2008\':winter-challenge-2008}*\r\n* *{\'Junior Challenge 2007\':junior-challenge}*\r\n* *{\'Winter Challenge\':winter-challenge-1}*\r\n* *{\'Unirea 2007\':unirea-2007}*\r\n* *{\'Grigore Moisil By Net 2006\':moisil-by-net-2006}*\r\n!>agora-finala?logo.gif! !>warm-up-2006?logo.jpeg! \r\n* *{\'Bursele agora, editia 6, finala online\':agora-finala}* \r\n* *{\'Bacalaureat 2005\':bacalaureat-2005}* \r\n* *{\'Concurs de incalzire\':warm-up-2004}* \r\n* *{\'preOJI 2004\':preoji-2004}*',2028,'protected',NULL,NULL),('home','infoarena -  comunitate informatica, concursuri de programare','2006-11-05 14:45:56','2010-02-21 17:39:20','h1. Bine ai venit pe infoarena!\r\n\r\nSuntem o comunitate de tineri pasionati de informatica si programare.\r\nInvatam impreuna participand la concursuri online de programare, citind stiri si articole despre informatica sau discutand pe forum.\r\n\r\n\'*&raquo; Afla mai multe despre noi!*\':despre-infoarena\r\n\r\np={width:700px; max-width:99%; margin:auto; background-color: rgb(210, 244, 219); border: 0; padding: 0.5em; -moz-border-radius:7px; -webkit-border-radius:7px}. A treia a concursului \'*Algoritmiada 2010*\':algoritmiada-2010 s-a incheiat. Felicitări \'*câştigătorilor*\':algoritmiada-2010/clasament/runda-3/5-8!\r\nParticipă şi la \'*runda 4*\':algoritmiada-2010/runda-4!\r\n\r\nh1. Ultimele insemnari de pe \'blog\':blog \'!{vertical-align:middle}home?rss_icon.jpg!\':blog?action=rss\r\n\r\n==BlogPreview(display_entries=\"10\")==\r\n',2028,'protected',NULL,NULL),('newsletter/dot-com-2009-2','.com 2009, runda 2','2010-03-03 10:47:26','2010-03-09 10:32:13','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nDeşi primăvara se lasă aşteptată, mai este doar o lună pana la olimpiada naţională. Nu-i aşa că trece repede timpul...? Pe ultima sută de metri, infoarena te antrenează cu două concursuri importante! \'.com\':dot-com/2009 revine cu o nouă rundă, iar \'Algoritmiada\':algoritmiada-2010 işi continuă seria bine cunoscută de concursuri, ajungând la runda a 4-a anul acesta.\r\n\r\nNu rata ocazia de a te antrena şi de a-ţi incerca forţele înainte de olimpiada naţionala! Chiar dacă nu te-ai calificat, concursul reprezintă un bun antrenament pentru competiţiile viitoare. Te invităm să participi la runda a doua a concursului organizat de membrii comunităţii, .com 2009.\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. A doua rundă se desfăşoară\r\n*Duminică, 14 martie, orele 09^00^ - 14^00^*. |\r\n\r\nVezi \'pagina concursului\':dot-com/2009 ca să afli cum poţi participa.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"dot-com/2009/runda-1\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre .com 2009\r\n\r\nConcursul are o singură grupă valorică, dar cele 3 probleme propuse au dificultăţi variate.\r\n\r\nOrganizatorii concursului sunt:\r\n\r\n* \'Stan Şerban Andrei\':utilizator/savim\r\n* \'Cezar Mocan\':utilizator/cezarmocan\r\n* \'Radu Zernoveanu\':utilizator/raduzer\r\n* \'Teodor Anton Pripoae\':utilizator/toni2007\r\n* \'Mihai Gheorghe\':utilizator/gheorghemihai\r\n* \'Cosmin Mihai Tutunaru\':utilizator/stocarul',3997,'public',NULL,NULL),('newsletter/dot-com-2009-2','.com 2009, runda 2','2010-03-03 10:47:26','2010-03-09 10:54:07','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nDeşi primăvara se lasă aşteptată, mai este doar o lună pana la olimpiada naţională. Nu-i aşa că trece repede timpul...? Pe ultima sută de metri, infoarena te antrenează cu două concursuri importante! \'.com\':dot-com/2009 revine cu o nouă rundă, iar \'Algoritmiada\':algoritmiada-2010 işi continuă seria bine cunoscută de concursuri, ajungând la runda a 4-a anul acesta.\r\n\r\nNu rata ocazia de a te antrena şi de a-ţi incerca forţele înainte de olimpiada naţionala! Chiar dacă nu te-ai calificat, concursul reprezintă un bun antrenament pentru competiţiile viitoare. Te invităm să participi la runda a doua a concursului organizat de membrii comunităţii, .com 2009.\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. A doua rundă se desfăşoară\r\n*Duminică, 14 martie, orele 09^00^ - 14^00^*. |\r\n\r\nVezi \'pagina concursului\':dot-com/2009 ca să afli cum poţi participa.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"dot-com/2009/runda-1\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre .com 2009\r\n\r\nConcursul are o singură grupă valorică,spre deosebire de prima runda, in runda a doua sunt propuse 3 probleme cu dificultăţi variate. În urma primei runde, dorim sa le spunem felicitari primilor 3 clasaţi. Primul loc a fost caştigat de \'Andrei Purice\':utilizator/Protoman cu 200 de puncte, urmat de \'Perţicaş Cătălin\':utilizator/perticas_catalin cu 190 de puncte, iar locul 3 a fost ocupat de \'Budău Adrian\':utilizator/freak93 cu 160 de puncte.\r\n\r\nOrganizatorii concursului sunt:\r\n\r\n* \'Stan Şerban Andrei\':utilizator/savim\r\n* \'Cezar Mocan\':utilizator/cezarmocan\r\n* \'Radu Zernoveanu\':utilizator/raduzer\r\n* \'Teodor Anton Pripoae\':utilizator/toni2007\r\n* \'Mihai Gheorghe\':utilizator/gheorghemihai\r\n* \'Cosmin Mihai Tutunaru\':utilizator/stocarul',3997,'public',NULL,NULL),('dot-com/2009/runda-2','.com 2009, Runda 2','2009-11-09 16:02:40','2010-03-08 07:46:09','h1. == roundparam(round_id=\"dotcom2009-runda2\" param=\"title\") ==\r\n\r\n(htabs)* \'Detalii\':dot-com/2009\r\n* \'Runda 1\':dot-com/2009/runda-1\r\n*(active) \'Runda 2\':dot-com/2009/runda-2\r\n* \'Clasament\':dot-com/2009/clasament\r\n\r\nRunda se va desfasura ==roundparam(round_id=\"dotcom2009-runda2\" param=\"start_time\" strong=\"true\")==, si va dura ==roundparam(round_id=\"dotcom2009-runda2\" param=\"duration\" strong=\"true\")== ore. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"dotcom2009-runda2\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"dotcom2009-runda2\" score=\"1\")==\r\n\r\nSolutiile le veti gasi \'aici\':dot-com/2009/solutii/runda-2 dupa ce runda va lua sfarsit.\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 2\':dot-com/2009/clasament/runda-2\r\n\r\nh2. Organizatori\r\n\r\n* ==user(user=\"savim\" type=\"tiny\")==\r\n* ==user(user=\"cezarmocan\" type=\"tiny\")==\r\n* ==user(user=\"raduzer\" type=\"tiny\")==\r\n* ==user(user=\"toni2007\" type=\"tiny\")==\r\n* ==user(user=\"gheorghemihai\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n\r\n',2028,'round: dotcom2009-runda2',NULL,NULL),('utilizator/wefgef','Profil Andrei Grigorean','2006-11-24 21:00:41','2010-03-02 23:44:30','h2. Despre mine\r\n\r\n* Sunt student in anul III la Facultatea de Matematica si Informatica, Universitatea Bucuresti.\r\n* Am inceput sa lucrez pe infoarena la sfarsitul clasei a X-a, si pot spune ca de-a lungul timpului a fost principala mea sursa de pregatire.\r\n* Primii trei ani de liceu i-am facut la C.N. \"Al. Papiu Ilarian\" din Targu Mures, iar in clasa a XII-a m-am transferat la \"ICHB\":http://www.ichb.ro/.\r\n* In clasa a XI-a am inceput serios informatica, dupa ce l-am cunoscut \"Cosmin Negruseri\":/utilizator/cosmin, care m-a ajutat foarte mult in cei doi ani de liceu ce au urmat.\r\n* Celelalte persoane care au avut un cuvant de spus in pregatirea mea sunt: \"Mircea Pasoi\":/utilizator/domino, \"Silviu Ganceanu\":/utilizator/silviug, \"Adrian Vladu\":/utilizator/azotlichid si \"Mugurel Ionut Andreica\":/utilizator/mugurelionut.\r\n* In vara/toamna anului 2009 am efectuat un internship la Google in Mountain View, CA.\r\n\r\nh2. Membru in comisii\r\n\r\n* CEOI 2009\r\n* Lot Piatra Neamt 2008, Iasi 2008, Bistrita 2009\r\n* ONI 2008, 2009\r\n* Algoritmiada 2009\r\n* preOni 2008\r\n* .campion 2008, 2009\r\n* Stelele Informaticii 2007-2008, 2008-2009.\r\n\r\nh2. Distinctii primite\r\n\r\n* Medalie de argint la IOI 2007.\r\n* Premiul I la ONI 2007.\r\n* Premiul I la finala preONI 2007.\r\n* Premiul I la concursul Stelele Informaticii 2006.\r\n* Mentiuni la ONI 2006 si ONI 2005.\r\n* Multe alte premii si mentiuni la concursuri interjudetene.\r\n\r\nh2. Articole\r\n\r\n* \"Taietura minima in graf cu costuri\":/taietura-minima, infoarena.\r\n\r\nh2. In afara informaticii\r\n\r\n* In general ascult muzica veche, rock din anii \'70, \'80.\r\n* Imi plac motoarele.\r\n* As merge pe munte daca as avea timp.\r\n* Colectionez monede.\r\n* RIP Jack.\r\n* Acum am parul scurt.\r\n\r\nh2. Prieteni pe infoarena (ordine aleatoare)\r\n\r\n* Shay-Fu: == User(user=\"Cosmin\" type=\"tiny\") ==\r\n* == User(user=\"domino\" type=\"tiny\") ==\r\n* == User(user=\"ditzonec\" type=\"tiny\") ==\r\n* == User(user=\"greco\" type=\"tiny\") ==\r\n* == User(user=\"azotlichid\" type=\"tiny\") ==\r\n* == User(user=\"silviug\" type=\"tiny\") ==\r\n* == User(user=\"wickedman\" type=\"tiny\") ==\r\n* == User(user=\"danielp\" type=\"tiny\") ==\r\n* == User(user=\"fluffy\" type=\"tiny\") ==\r\n* == User(user=\"filipb\" type=\"tiny\") ==\r\n* == User(user=\"svalentin\" type=\"tiny\") ==\r\n* == User(user=\"astronomy\" type=\"tiny\") ==\r\n* == User(user=\"mugurelionut\" type=\"tiny\") ==\r\n* == User(user=\"gcosmin\" type=\"tiny\") ==\r\n* == User(user=\"bogdan2412\" type=\"tiny\") ==\r\n* == User(user=\"crawler\" type=\"tiny\") ==\r\n* == User(user=\"binary_fire\" type=\"tiny\") ==\r\n* == User(user=\"megabyte\" type=\"tiny\") ==\r\n* == User(user=\"pauldb\" type=\"tiny\") ==\r\n* == User(user=\"alexthero\" type=\"tiny\") ==\r\n* == User(user=\"victorsb\" type=\"tiny\") ==\r\n* == User(user=\"sims_gl\" type=\"tiny\") ==\r\n* == User(user=\"cimi\" type=\"tiny\") ==\r\n* == User(user=\"mariusdrg\" type=\"tiny\") ==\r\n* == User(user=\"prostu\" type=\"tiny\") ==\r\n* == User(user=\"adriana_s\" type=\"tiny\") ==\r\n* == User(user=\"georgiana\" type=\"tiny\") ==\r\n* == User(user=\"stef2n\" type=\"tiny\") ==\r\n* Va urma...\r\n\r\nh2. Dusmani pe infoarena\r\n\r\n* == User(user=\"eval\" type=\"tiny\") == (nu vrea sa imi dea destule puncte)\r\n* == User(user=\"chucknorris\" type=\"tiny\") == (e mai bun ca mine)\r\n\r\nh2. Poze IOI 2007, Zagreb, Croatia\r\n\r\n* Echipa Romaniei\r\n!utilizator/wefgef?P1050159.JPG 50%!\r\n\r\n* Inveselind marmota\r\n!utilizator/wefgef?P1050311.JPG 50%!\r\n\r\n* Aratand dubios :P\r\n!utilizator/wefgef?P1050143.JPG 40%!',2028,'protected',NULL,NULL),('planificare/camp-2.3.1','Coding Camp \"We can do it\"','2010-03-03 15:34:27','2010-03-11 17:20:05','h1. Coding Camp _\"We can do it\"_\r\n\r\nNe intalnim in weekend-ul *13-14 martie 2010*, in fiecare zi intre orele *10:00* si *18:00*, la ICHB.\r\n\r\nScopul final al coding camp-ului este familiarizarea mai multor membri ai comunitatii/echipei cu codebase-ul infoarena si lansarea versiunii \"infoarena 2.3.1\":http://hackers.devnet.ro/milestone/2.3.1%20Yes%20We%20Can.\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu Linux instalat pe el (preferabil ubuntu).\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri\r\n\r\nh2. Participanti\r\n\r\nSpecifica cand poti veni si cat poti sta.\r\n\r\n* ==user(user=\"devilkind\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"wefgef\" type=\"tiny\")==: sambata\r\n* ==user(user=\"stef2n\" type=\"tiny\")==: duminica\r\n\r\nh2. Agenda\r\n\r\nh3. Must have \r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n|\"Note pentru probleme\":http://hackers.devnet.ro/ticket/395|||\r\n|\"Interfata de search pentru taguri\":http://hackers.devnet.ro/ticket/391|||\r\n\r\nh3. \"Heavy\":http://shaunchng.com/gallery/main.php?g2_view=core.DownloadItem&g2_itemId=658 (pentru useri experimentati)\r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n\r\nh3. Light (pentru useri mai putin experimentati)\r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n\r\n',2993,'public',NULL,NULL),('training-path','Training path','2008-01-22 17:36:01','2010-03-11 18:24:53','h1. Training path\r\n\r\nVrem sa intocmim o baza de cunostinte fara precendent! Vrem ca aceasta pagina sa contina o lista cat mai completa cu ce trebuie sa stie un olimpic pentru a avea succes. \'Ajuta-ne\':implica-te/scrie-articole si tu!\r\n\r\n*Cosmin:* ar trebui sa facem o lista mai mica cu chestiile importante ca sa ajungi la ONI, ca sa nu se sperie cei ce abia incep.\r\n\r\nh2. Structuri de date\r\n\r\n* Liste, stive, cozi\r\n* \'Deque\':deque-si-aplicatii\r\n* \'Tabele de dispersie\':tabele-hash-prezentare-detaliata\r\n** \'Cuckoo hashing\':http://en.wikipedia.org/wiki/Cuckoo_hashing\r\n* \'Bloom filters\':http://en.wikipedia.org/wiki/Bloom_filter\r\n* \'Skiplists\':skiplists\r\n\r\n* \'Arbori indexati binar\':aib\r\n* Cozi de prioritati\r\n** \'Heap-uri\':heapuri\r\n** Mergeable heaps (maxophobic heaps sunt cel mai simple)\r\n** Pentru costuri intregi mici, un array de liste\r\n\r\n* \'Structuri de multimi disjuncte\':problema/disjoint\r\n* \'Arbori de intervale\':arbori-de-intervale\r\n* \'Tries\':problema/trie\r\n* Arbori binari de cautare (\'Treapuri\':treapuri, AVL, red-black trees)\r\n* \'Cautari ortogonale. Quad trees, kD-trees\':cautari-ortogonale\r\n\r\nh2. Algoritmi si tehnici de programare\r\n\r\nh3. Matematica\r\n\r\n* \'Inductie matematica\':http://ro.wikipedia.org/wiki/Inductie_matematica\r\n* \'Algoritmul lui Euclid\':algoritmul-lui-euclid\r\n* CMMDC binar\r\n* \'Ciurul lui Erathostene\':ciurul-lui-erathostene\r\n* \'Gray code\':coduri-gray\r\n* Rezolvare de ecuatii liniare modulare\r\n* Teorema mica a lui Fermat\r\n* \'Teorema chineza a resturilor\':teorema-chineza-a-resturilor\r\n** Probleme: \'eval\':problema/eval \'resturi\':problema/resturi \'gears in action\':http://ipsc.ksp.sk/contests/ipsc2005/real/problems/g.php\r\n* \"Numere mari: adunare, scadere, inmultire, impartire, radical\":lucrul-cu-nr-mari\r\n* Recurente si exponentiere rapida de matrici (+evaluare rapida a expresiilor folosind exponentiere in timp logaritmic), \'al K-lea termen Fibonacci\':problema/kfib\r\n* \'Principiul includerii si excluderii\':principiul-includerii-si-excluderii\r\n** Probleme: \'cowfood\':problema/cowfood, \'indep\':problema/indep, \'frac\':problema/frac\r\n* Sisteme de ecuatii liniare (Gauss)\r\n** Teorie:\r\n*** \'Gaussian elimination\':http://en.wikipedia.org/wiki/Gaussian_elimination\r\n*** \'Row echelon form\':http://en.wikipedia.org/wiki/Row_echelon_form\r\n** Probleme: \'SGU 275 To xor or not to xor\':http://acm.sgu.ru/problem.php?contest=0&problem=275 \'.campion Xor\':http://campion.edu.ro/problems/3/323/xor_ro.htm \'SGU 260 Puzzle\':http://acm.sgu.ru/problem.php?contest=0&problem=260 \'UVA 10808\':http://online-judge.uva.es/p/v108/10808.html \'UVA 326\':http://online-judge.uva.es/p/v3/326.html \'UVA 10014\':http://online-judge.uva.es/p/v100/10014.html \'BColor\':problema/bcolor \'Laser\':problema/laser \'TC XORing\':http://www.topcoder.com/stat?c=problem_statement&pm=4829&rd=8095&rm=246636&cr=270505 \'TC Escape the jail\':http://www.topcoder.com/stat?c=problem_statement&pm=7353 \'Register CEOI 2003\':http://ceoi.inf.elte.hu/probarch/03/register-en.pdf \'Tunelul groazei\':problema/tunel \'SGU 200\':http://acm.sgu.ru/problem.php?contest=0&problem=200 \'TC CoinGame\':http://www.topcoder.com/stat?c=problem_statement&pm=6005 \r\n* Simplex\r\n* \"Floyd\'s cycle finding\":http://en.wikipedia.org/wiki/Cycle_detection\r\n* Combinatorica\r\n** \'Generare de permutari\':problema/permutari, permutari cu repetitii, aranjamente, \'combinari\':problema/combinari, Stirling, Catalan, Bell, Fibonacci\r\n** Trecere de la combinare/permutare la indexul ei si invers\r\n** \'Codul Prufer. Numarare de arbori\':http://en.wikipedia.org/wiki/Pr%C3%BCfer_sequence\r\n\r\nh3. Geometrie\r\n\r\n\'computer graphics FAQ\':http://www.faqs.org/faqs/graphics/algorithms-faq/\r\n\'cursuri dupa Computational Geometry: Algorithms and Applications, Mark de Berg, M. van Krefeld, M. Overmars, O. Schwarzkopf\':http://www.cs.umd.edu/class/spring2007/cmsc754/Lects/754lects.pdf\r\n\r\n\r\n* Intersectie a doua segmente\r\n* \'Cele mai apropiate puncte dintr-un plan\':problema/cmap\r\n* Punct in interiorul unui poligon\r\n** http://geometryalgorithms.com/Archive/algorithm_0103/algorithm_0103.htm\r\n** http://tog.acm.org/editors/erich/ptinpoly/\r\n* Punct in poligon convex in $O(log n)$\r\n** http://geometryalgorithms.com/Archive/algorithm_0103/algorithm_0103.htm#Monotone%20Polygons\r\n* \'Teorema lui Pick\':http://www.cut-the-knot.org/ctk/Pick_proof.shtml\r\n** problema \'copaci\':problema/copaci\r\n* Aria unui poligon\r\n* Centrul de greutate al unui poligon\r\n* \'Triangularizare de poligon in $O(n^2)$\':http://people.csail.mit.edu/indyk/6.838-old/handouts/lec4.pdf\r\n* \'Intersectia a doua cercuri\':http://local.wasp.uwa.edu.au/~pbourke/geometry/2circle/\r\n* \'Minimal enclosing circle\':minimal-enclosing-circle\r\n* Convex hull\r\n** \'Aplicatie din Arhiva Educationala\':problema/infasuratoare\r\n** http://www.algorithmist.com/index.php/Monotone_Chain_Convex_Hull\r\n** http://en.wikipedia.org/wiki/Gift_wrapping_algorithm\r\n** Aplicatie - onion peeling in O(n^2^)\r\n* \'Baleiere verticala / radiala\':algoritmi-de-baleiere\r\n** baleiere radiala\r\n*** Se da un set S de n punct in plan. Sa se determine cercul de raza R fixata care acopera cat mai multe puncte din S. O(n^2 log n)\r\n*** Se da un set S de n puncte in plan. Sa se gaseasca o dreapta ce trece prin nr maxim de puncte din S. O(n^2^) cu hashuri pt unghiuri sau O(n^2 log n) cu baleiere radiala.\r\n*** Se da un set S de n segmente in plan. Sa se gaseasca o dreapta ce intersecteaza numarul maxim de segmente din S. O(n^2 log n) cu baleiere radiala.\r\n*** \'Construirea grafului de vizibilitate.\':http://en.wikipedia.org/wiki/Visibility_graph\r\n* \'Rotating calipers\':http://cgm.cs.mcgill.ca/~orm/rotcal.html\r\n** problema \'rubarba\':problema/rubarba\r\n** problema \'popandai2\':problema/popandai2\r\n* Intersectie de poligoane convexe\r\n* Intersectie de semiplane (fara dualizare)\r\n** problema \'camera\':problema/camera\r\n* \'Dualizare (intersectie de semiplane, diagrame Voronoi)\':http://infoarena.ro/voronoi\r\n\r\n* \'thread pe forum\':http://infoarena.ro/forum/index.php?topic=3007.0\r\n\r\nh3. Sortari si cautari\r\n\r\n* Shell sort, merge sort, heapsort, quicksort, counting sort, radix sort, \'sortare prin comparare\':problema/algsort\r\n* \'Statistici de ordine\':problema/sdo\r\n* \'Cautare binara\':problema/cautbin / ternara si \'aplicatii\':aplicatii-ale-cautarii-binare\r\n* Hill climbing\r\n\r\nh3. Greedy\r\n\r\n* \'Huffman\':problema/huffman\r\n* Job scheduling\r\n\r\nh3. Programare dinamica\r\n\r\n* \'Parantezare optima de matrici\':problema/podm\r\n* \'Cel mai lung subsir crescator $O(N*log N)$\':problema/scmax\r\n* Knapsack\r\n** Knapsack pe biti\r\n* \'Cel mai lung subsir comun\':problema/cmlsc\r\n* \'Distanta de editare a 2 cuvinte\':http://en.wikipedia.org/wiki/Levenshtein_distance\r\n* Ciclu hamiltonian in $O(n^2^ * 2^n^)$\r\n** problema \'adn\':problema/adn\r\n* Dinamicile in $3^n^$\r\n** \'explicatie\':http://forums.topcoder.com/?module=Thread&threadID=512824&start=0, \'problema\':http://www.topcoder.com/stat?c=problem_statement&pm=6678&rd=9998&rm=249548&cr=8547850\r\n* \'Arbore de cautare optim in $O(n^2)$\':http://www.ics.uci.edu/~dan/class/165/notes/OptBST.html\r\n* Dinamici pe arbori\r\n* \'Numarul posibilitatilor de acoperire a unei table cu dominouri\':probleme-de-acoperire-2#problema3\r\n* Memoizare (trading space for time)\r\n\r\nh3. Grafuri\r\n\r\n* Parcurgeri\r\n** \'DFS\':problema/dfs, \'BFS\':problema/bfs, meet in the middle bfs\r\n** \'Componente biconexe\':problema/biconex\r\n** \'Componente tare-conexe\':problema/ctc\r\n** \'Sortare topologica\':problema/sortaret\r\n** \'Ciclu eulerian\':problema/ciclueuler\r\n\r\n* Drumuri minime\r\n** \'Dijkstra\':problema/dijkstra (cu heapuri, cu set-uri, cu AINT-uri, cu coada ca pe TC - Cosmin stie)\r\n** \'Dijkstra cu costuri mici ;)\':http://www.ginfo.ro/revista/13_6/focus2.pdf cum se foloseste la problema \'car\':problema/car\r\n** A* has a lot of intuitive appeal for me. If you compare Dijkstra\'s vs. A*, Dijkstra\'s is like a puddle of water flooding outwards on a flat floor, whereas A* is like the same puddle expanding on a bumpy and graded floor toward a drain (the target node) at the lowest point in the floor. Instead of spreading out evenly on all sides, the water seeks the path of least resistance, only trying new paths when something gets in its way. The heuristic function is what provides the \'grade\' of the hypothetical floor.\r\n*** A* se foloseste foarte mult in industria jocurilor, fiind un algoritm foarte rapid in practica. Un exemplu unde este folosit este jocul de strategie Starcraft.\r\n** \'Floyd-Warshall\':problema/royfloyd\r\n** \'Bellman-Ford\':en.wikipedia.org/wiki/Bellman-Ford_algorithm\r\n*** De obicei mai simplu de implementat si cam aceeasi viteza ca si Dijkstra cu heapuri\r\n*** Sistem de inegalitati\r\n*** \'Ciclu de cost mediu minim\':ciclu-de-cost-mediu-minim\r\n* \'Flux\':problema/maxflow\r\n** Edmonds-Karp\r\n** \'Taietura minima\':taietura-minima\r\n** \'Dinic\':http://www.msri.org/about/computing/docs/magma/html/text1499.htm\r\n** \'Flux maxim de cost minim\':problema/fmcm\r\n** Flux cu capacitati inferioare\r\n** Circulatii\r\n** Problema postasului chinez\r\n*** problema \'traseu\':problema/traseu\r\n* Arbori\r\n** \'Diametrul, centrul unui arbore\':http://online-judge.uva.es/board/viewtopic.php?p=36766&highlight=#36766\r\n** \'Testare daca doi arbori sunt izomorfi\':http://online-judge.uva.es/board/viewtopic.php?p=22754&highlight=#22754\r\n** Cod Prufer\r\n* \'APM\':problema/apm\r\n** Prim\r\n** Kruskal\r\n** Al doilea APM\r\n** APM in graf orientat\r\n** Kirchhoff\'s matrix tree theorem\r\n* Pentru grafuri bipartite: \'cuplaj maxim\':problema/cuplaj, suport minim, multime independenta maxima\r\n* \'LCA\':lowest-common-ancestor, \'RMQ\':problema/rmq, Level Ancestor, \'Tree decompositions\':tree-decompositions\r\n* Colorari de muchii, graf complet/bipartit/oarecare (teorema lui Vizing)\r\n* Grafuri planare\r\n** problema \'count\':problema/count\r\n* Grafuri turneu/ciclu hamiltonian\r\n** problema \'plimbare\':problema/plimbare\r\n* {\'Implication graph si 2-SAT\':2-sat}\r\n\r\n\r\nh3. Siruri de caractere\r\n\r\n* \'Hashuri\':problema/strmatch\r\n* \'KMP\':automate-finite-si-kmp\r\n* \'Siruri de sufixe\':siruri-de-sufixe\r\n** \'In timp liniar\':suffix-array-liniar\r\n* \'Aho-Corasick\':http://www.cs.uku.fi/~kilpelai/BSA05/lectures/slides04.pdf .\r\n\r\nh3. Limbaje formale si automate finite\r\n\r\n* \'Evaluari de expresii aritmetice\':problema/evaluare\r\n* \'CYK\':http://en.wikipedia.org/wiki/CYK\r\n* Matching with wildcards\r\n* Construirea unui automat care sa accepte un set de cuvinte\r\n* Simplificare de automate\r\n* Echivalenta de automate\r\n* \'thread pe forum\':http://infoarena.ro/forum/index.php?topic=3005.0\r\n\r\nh3. Teoria jocurilor\r\n\r\n* Nim\r\n* \'Numere Sprague-Grundy\':numerele-sprague-grundy\r\n* Min-max\r\n* Alpha-beta\r\n\r\nh2. Diverse\r\n\r\nh3. \'STL @(Standard Template Library)@\':stl\r\n\r\n* vector, deque, stack, list\r\n* string\r\n* set, map, hash_map\r\n* pair\r\n* sort\r\n* priority_queue\r\n* bitset\r\n* iteratori\r\n\r\nh3. Cautari\r\n\r\n* backtracking\r\n* iterative deepening\r\n* branch and bound\r\n\r\nh3. Optimizari\r\n\r\n* Parsare\r\n* Lucru cu biti\r\n* Brute force\r\n** \'dancing links\':http://en.wikipedia.org/wiki/Dancing_Links\r\n\r\nh3. Lucrul cu memoria\r\n\r\n* \'Cacheuri de memorie\':http://en.wikipedia.org/wiki/CPU_cache\r\n** problema \'stramosi\':problema/stramosi\r\n*  \'free lists\':http://www.memorymanagement.org/glossary/f.html#free.list\r\n** problema \'eprubeta\':problema/eprubeta\r\n\r\nh3. Bulanit\r\n\r\n* Randomizare (2-opt, k-opt)\r\n* Constante\r\n* Interpolare Taylor / Gauss pentru formule polinomiale\r\n\r\nh3. \'Smenuri\':multe-smenuri-de-programare-in-cc-si-nu-numai\r\n\r\n* Smenu\' lui Batog (+ lca in $sqrt(n)$)\r\n** probleme: \'schi\':problema/schi, \r\n* Smenu\' lui Mars\r\n** problema \'cuburi\':http://campion.edu.ro/do_download.php?problem_id=122&type=application/pdf&year=2003&lang=ro\r\n* \'Meet in the middle\':meet-in-the-middle\r\n\r\nh2. Carti utile\r\n\r\n* Ioan Tomescu\r\n** \"Probleme de combinatorica si teoria grafurilor\" (din care s-a dat la ONI sau lot aproape in fiecare an cate o problema sau mai multe)\r\n** \"Combinatorica si teoria grafurilor\"\r\n* Ioan Cuculescu\r\n** \"Olimpiadele Internationale de Matematica ale Elevilor\"\r\n* E. A. Morozova, I. S. Petracov, V. A. Skvortov\r\n** \"Olimpiade internationale de matematica\"\r\n* \"Probleme de matematica traduse din revista sovietica KVANT\"\r\n* A. M. Iaglom, I. M. Iaglom\r\n** \"Probleme neelementare tratate elementar\"\r\n* Thomas H. Cormen, Charles E. Leiserson, Ronald R. Rivest\r\n** \'\"Introducere in algoritmi\"\':http://libris.agora.ro/algoritmi.html\r\n* D. E. Knuth\r\n** \"Arta programarii calculatoarelor\" (\"The Art of Computer Programming\")\r\n** \"Concrete Mathematics\"\r\n* Jon Bentley\r\n** \"Programming Pearls\"\r\n* Steven Skiena\r\n** \"The Algorithm Design Manual\"\r\n* W. Rytter\r\n** \"Jewels of Stringology\"\r\n* Mark de Berg\r\n** \"Computational geometry\"\r\n* Emanuela Cerchez si Marinel Serban\r\n** \"Programarea in Limbajul C/C++ Pentru Liceu Volumul 1,2,3\"\r\n\r\n',9232,'public',NULL,NULL),('planificare/camp-2.3.1','Coding Camp \"We can do it\"','2010-03-03 15:34:27','2010-03-11 18:27:54','h1. Coding Camp _\"We can do it\"_\r\n\r\nNe intalnim in weekend-ul *13-14 martie 2010*, in fiecare zi intre orele *10:00* si *18:00*, la ICHB.\r\n\r\nScopul final al coding camp-ului este familiarizarea mai multor membri ai comunitatii/echipei cu codebase-ul infoarena si lansarea versiunii \"infoarena 2.3.1\":http://hackers.devnet.ro/milestone/2.3.1%20Yes%20We%20Can.\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu Linux instalat pe el (preferabil ubuntu).\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri\r\n\r\nh2. Participanti\r\n\r\nSpecifica cand poti veni si cat poti sta.\r\n\r\n* ==user(user=\"devilkind\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"wefgef\" type=\"tiny\")==: sambata\r\n* ==user(user=\"stef2n\" type=\"tiny\")==: duminica\r\n\r\nh2. Agenda\r\n\r\nh3. Must have \r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n|\"Note pentru probleme\":http://hackers.devnet.ro/ticket/395| 0 | 0 |\r\n|\"Interfata de search pentru taguri\":http://hackers.devnet.ro/ticket/391| 0 | 0 |\r\n| Script de recalculat timpii de evaluare | 0 | 0 |\r\n| Script de sters automat backup-uri vechi | 0 | 0 |\r\n\r\nh3. \"Heavy\":http://shaunchng.com/gallery/main.php?g2_view=core.DownloadItem&g2_itemId=658 (pentru useri experimentati)\r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n| \'Sters automat concursuri virtuale nefolosite\':http://hackers.devnet.ro/ticket/376 | 0 | 0 |\r\n| \'Functionalitate de sters runde\':http://hackers.devnet.ro/ticket/373 | ==user(user=\"prostu\" type=\"tiny\")== ? | \'Done 1/2\':http://reviewboard.infoarena.ro/r/115/ |\r\n| \'Optimizeaza pagina de changes\':http://hackers.devnet.ro/ticket/383 | 0 | 0 |\r\n\r\nh3. Light (pentru useri mai putin experimentati)\r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n|\"Recover forum birthdays\":http://hackers.devnet.ro/ticket/394 | 0 | 0 |\r\n|\"Textile edit buttons\":http://hackers.devnet.ro/ticket/163 | 0 | 0 |\r\n|\"Edit forum user\":http://hackers.devnet.ro/ticket/393 | 0 | 0 |\r\n|\"Find my username link\":http://hackers.devnet.ro/ticket/208 | 0 | 0 |\r\n|\"Proper security UI\":http://hackers.devnet.ro/ticket/129 | 0 | 0 |\r\n',1490,'public',NULL,NULL),('runda/oni-2009-xi-xii','oni-2009-xi-xii','2010-03-14 13:08:48','2010-03-14 13:15:44','h1. == roundparam(round_id=\"oni-2009-xi-xii\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oni-2009-xi-xii\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oni-2009-xi-xii\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oni-2009-xi-xii\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"oni-2009-xi-xii\" units=\"2\") ==\r\n\r\nh1. Probleme\r\n\r\n==Tasks(round_id=\"oni-2009-xi-xii\" score=\"1\")==\r\n\r\nh1. \'*Rezultate*\':runda/oni-2009-xi-xii/clasament',10498,'round: oni-2009-xi-xii',NULL,NULL),('runda/oni-2009-x','oni-2009-x','2010-03-14 13:07:17','2010-03-14 15:28:50','h1. == roundparam(round_id=\"oni-2009-x\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oni-2009-x\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oni-2009-x\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oni-2009-x\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"oni-2009-x\" units=\"2\") ==\r\n\r\nh1. %{color:blue}*PROBLEME*%\r\n\r\n==Tasks(round_id=\"oni-2009-x\" score=\"1\")==\r\n\r\nh1. \'*REZULTATE*\':runda/oni-2009-x/clasament',10498,'round: oni-2009-x',NULL,NULL),('utilizator/wickedman','Cristian George Strat (wickedman)','2006-11-24 20:56:12','2010-03-15 00:17:35','h2. Despre mine\r\n\r\n* test\r\n* Membru fondator şi fost Preşedinte al Asociaţiei infoarena \'{!utilizator/domino?btn_viewmy_160x33.gif!}\':http://www.linkedin.com/in/cristiangeorgestrat\r\n* Co-fondator ROCKET SOFTWARE, online start-up (primul proiect lansat este \'balaur.ro\':balaur.ro)\r\n* Co-fondator INNOVATE CONSULT, companie ce oferă servicii software şi networking\r\n* Google internship, summer 2008, Zurich, Switzerland\r\n* Google internship, summer 2007, Mountain View, California\r\n* Membru al comisiei ştiinţifice ONI 2009, clasa a IX-a\r\n* Presedinte al juriului de _Pagini Web_, \"InfoEducatie\":http://infoeducatie.ro/ 2006\r\n* Membru al juriului de _Programare_ \"InfoMatrix 2009\":http://infomatrix.ro/\r\n* Membru al juriului de _Programare_ \"InfoMatrix 2008\":http://infomatrix.ro/\r\n* Membru al juriului de _Pagini Web_ \"InfoEducatie\":http://infoeducatie.ro/ 2005\r\n* Membru al juriului de _Pagini Web_ la concursul Unirea 2005\r\n* Locurile I, I, II, III la concursul national de software si pagini web \"InfoEducatie\":http://infoeducatie.ro/\r\n* Locul II la concursul pe echipe EESTEC Olympics 2006\r\n* Finalist la \'Challenge24\':http://challenge24.org/\r\n* Locul 4 la ONI 2004\r\n* Finalist \'.campion\':http://campion.edu.ro/ 2004 \r\n* Calificare în lotul lărgit de informatică 2004\r\n\r\nh3. Publicaţii\r\n\r\n* \'Solving Maximum Flow Problems on Real World Bipartite Graphs\':http://www.siam.org/proceedings/alenex/2009/alx09_002_negruserin.pdf, Cosmin Silvestru Negruşeri, Mircea Bogdan Paşoi, Barbara Stanley, Clifford Stein, and Cristian George Strat (\'ALENEX09 Proceedings\':http://www.siam.org/proceedings/alenex/2009/alenex09.php)\r\n\r\nh3. Studii\r\n\r\n* -Student in anul IV la- Absolvent \"FMI\":http://fmi.unibuc.ro/ 2008, Universitatea Bucuresti\r\n* C.N. \"Gh. Rosca Codreanu\", Barlad, Jud. Vaslui\r\n\r\nh3. Trivia\r\n\r\n* infoarena a fost initial un proiect pentru concursul national \'InfoEducatie\':http://infoeducatie.ro/, sectiunea pagini web. La prima participare (in 2002) am primit locul III, iar in 2003 am castigat locul I.\r\n* l-am cunoscut pe \'Mircea Pasoi\':utilizator/domino si pe \'Crestez Leonard\':utilizator/fluffy pe canalul IRC #olimpada. Ei vroiau sa faca un site de probleme\r\n* am fost coleg de clasa cu \'Silviu Ganceanu\':utilizator/silviug in 9-11\r\n* ce vedeti acum este site-ul infoarena versiunea 2. \'Inainte era albastru\':http://web.archive.org/web/20060307025837/http://infoarena.devnet.ro/\r\n\r\nh3. Din presă\r\n\r\n* \'Creierele româneşti din solda „imperiului” Google\':http://www.evz.ro/articole/detalii-articol/819647/Creierele-romanesti-din-solda-imperiului-Google/, Evenimentul Zilei\r\n* \'Foştii olimpici îi antrenează pe concurenţii de la olimpiade\':http://www.adevarul.ro/articole/2007/fostii-olimpici-ii-antreneaza-pe-concurentii-de-la-olimpiade.html, Adevărul\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* == User(user=\"chucknorris\" type=\"tiny\") ==\r\n* == User(user=\"eval\" type=\"tiny\") ==\r\n',13,'protected',NULL,NULL),('articole/template-solutii','articole/template-solutii','2008-12-13 14:45:42','2010-03-16 13:43:39','* !>articole/template-solutii?algoritmiada-2010.jpg! \'.com 2009, Runda 2\':dot-com/2009/solutii/runda-2\r\n* \'Algoritmiada 2010, Runda 3\':algoritmiada-2010/runda-3/solutii\r\n* \'Algoritmiada 2010, Runda 2\':algoritmiada-2010/runda-2/solutii\r\n* \'Algoritmiada 2010, Runda 1\':algoritmiada-2010/runda-1/solutii\r\n* \'Summer Challenge 2009, Runda 3\':summer-challenge-2009/solutii/runda-3\r\n* \'Summer Challenge 2009, Runda 2\':summer-challenge-2009/solutii/runda-2\r\n* \'Summer Challenge 2009, Runda 1\':summer-challenge-2009/solutii/runda-1\r\n* \'Grigore Moisil 2009\':grigore-moisil-2009/solutii\r\n* !>articole/template-solutii?algoritmiada-2009.jpg! \'Algoritmiada 2009, Runda 3\':algoritmiada-2009/runda-3/solutii\r\n* \'Algoritmiada 2009, Runda 2\':algoritmiada-2009/runda-2/solutii\r\n* \'Algoritmiada 2009, Runda 1\':algoritmiada-2009/runda-1/solutii\r\n* \'Junior Challenge 2008\':junior-challenge-2008/solutii\r\n* \'Grigore Moisil 2008\':grigore-moisil-2008/solutii\r\n* \'preONI 2008, Runda finala\':preoni-2008/runda-finala/solutii\r\n* !>articole/template-solutii?preoni-2008.jpg! \'preONI 2008, Runda 4\':preoni-2008/runda-4/solutii\r\n* \'preONI 2008, Runda 3\':preoni-2008/runda-3/solutii\r\n* \'preONI 2008, Runda 2\':preoni-2008/runda-2/solutii\r\n* \'preONI 2008, Runda 1\':preoni-2008/runda-1/solutii\r\n*{display: %display%} \'Winter Challenge 2008, Runda 2\':winter-challenge-2008/runda-2/solutii\r\n*{display: %display%} \'Winter Challenge 2008, Runda 1\':winter-challenge-2008/runda-1/solutii\r\n*{display: %display%} \'Happy Coding 2007\':happy-coding-2007/solutii\r\n*{display: %display%} \'Autumn Warmup 2007 runda 3\':autumn-warmup-2007/solutii/runda-3\r\n*{display: %display%} \'Autumn Warmup 2007 runda 2\':autumn-warmup-2007/solutii/runda-2\r\n*{display: %display%} \'Autumn Warmup 2007 runda 1\':autumn-warmup-2007/solutii/runda-1\r\n*{display: %display%} \'Summer Challenge 2007 runda #3\':summer-challenge-2007/solutii/runda-3\r\n*{display: %display%} \'Summer Challenge 2007 runda #2\':summer-challenge-2007/solutii/runda-2\r\n*{display: %display%} \'Summer Challenge 2007 runda #1\':summer-challenge-2007/solutii/runda-1\r\n*{display: %display%} \'Junior Challenge 2007\':junior-challenge/solutii\r\n*{display: %display%} !>articole/template-solutii?preoni-2007.jpg! \'preONI 2007 runda finala - solutii\':preoni-2007/runda-finala/solutii\r\n*{display: %display%} \'preONI 2007 runda #4 - solutii\':preoni-2007/runda-4/solutii\r\n*{display: %display%} \'preONI 2007 runda #3 - solutii\':preoni-2007/runda-3/solutii\r\n*{display: %display%} \'preONI 2007 runda #2 - solutii\':preoni-2007/runda-2/solutii\r\n*{display: %display%} \'preONI 2007 runda #1 - solutii\':preoni-2007/runda-1/solutii\r\n*{display: %display%} \'Winter Challenge 1\':winter-challenge-1/solutii\r\n*{display: %display%} \'Unirea 2007\':unirea-2007/solutii\r\n*{display: %display%} \'Solutii Autumn WarmUp 2006\':warm-up-2006/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Trei\':summer-challenge-3/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Doi\':summer-challenge-2/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Unu\':summer-challenge-unu/solutii\r\n*{display: %display%} !>articole/template-solutii?preoni-2006.gif! \'Solutii preONI 2006, Runda finala\':preoni-2006/finala/solutii\r\n*{display: %display%} \'Solutii preONI 2006, Runda a 4-a\':preoni-2006/runda-4/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda a 3-a\':preoni-2006/runda-3/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda a 2-a\':preoni-2006/runda-2/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda 1\':preoni-2006/runda-1/solutii\r\n*{display: %display%} \'preONI 2005 runda #3 - solutii\':preoni-2005/runda-3/solutii\r\n*{display: %display%} \'preONI 2005 runda #2 - solutii\':preoni-2005/runda-2/solutii\r\n*{display: %display%} \'preONI 2005 runda #1 - solutii\':preoni-2005/runda-1/solutii\r\n*{display: %display%} \'Happy Coding 3 [2006]\':happy-coding-2006/solutii\r\n*{display: %display%} \'Happy Coding 2 [2005]\':happy-coding-2005-2/solutii\r\n*{display: %display%} \'Happy Coding 1 [2005]\':happy-coding-2005-1/solutii\r\n*{display: %display%} \'Concursul Agora - Etapa Finala - Solutii\':agora-finala/solutii\r\n*{display: %display%} \'Doua probleme de la runda 6 a concursului Algoritmus\':doua-probleme-de-la-runda-6-a-concursului-algoritmus\r\n*{display: %display%} \'USACO dec 2005, divizia GOLD\':usaco-dec-2005-divizia-gold \r\n*{display: %display%} \'USACO nov 2005, divizia GOLD\':usaco-nov-2005-divizia-gold\r\n*{display: %display%} \'USACO oct 2005, divizia GOLD\':usaco-oct-2005-divizia-gold\r\n*{display: %display%} \'USACO ian 2005, divizia GOLD\':usaco-ian-2005-divizia-gold\r\n*{display: %display%} \'USACO dec 2004, divizia GOLD\':usaco-dec-2004-divizia-gold\r\n*{display: %display%} \'Solutiile oficiale pentru Concursul &quot;de incalzire&quot;\':warm-up-2004/solutii',3146,'protected',NULL,NULL),('utilizator/gabitzish1','GABITZISH... Bitis Gabriel.... ','2007-03-02 12:09:21','2009-08-19 05:45:49','h2. Despre mine\r\n\r\nSunt student in anul I la Facultatea de Stiinte din Oradea, departamentul Informatica.\r\nAm inceput sa lucrez pe infoarena de pe la sfarsitul clasei a X\'a.\r\n\r\nh2. Distinctii primite:\r\n\r\n* Mentiune la Concursul Interjudetean \"Marian Tarina\", Turda, 2007.\r\n* Premiul 1 la OJI 2008 (judetul Bihor).\r\n* Premiul 3 la Concursul Interjudetean \"Grigore Moisil\", Cluj-Napoca, 2008.\r\n* Mentiune si medalie de bronz la ONI 2008, Ploiesti.\r\n* Premiul 1 la Concursul Interjudetean \"Marian Tarina\", Turda, 2008.\r\n* Premiul 1 la OJI 2009 (judetul Bihor).\r\n* Premiul 1 la Concursul National \"Urmasii lui Moisil\", Iasi, 2009 + titlul de \"Pui de Moisil\" :P.\r\n* Premiul 1 la Concursul Interjudetean \"Grigore Moisil\", Satu Mare, 2009.\r\n* Finalist .campion 2009\r\n* Membru al lotului national restrans 2009\r\n\r\nh2. Activitate pe Infoarena:\r\n\r\nh3. Probleme adaugate in arhiva:\r\n\r\n* \"498. Alee\":/problema/alee\r\n* \"499. Dir\":/problema/dir\r\n* \"501. Ecuatii 2\":/problema/ecuatii2\r\n* \"514. Sudest\":/problema/sudest\r\n* \"535. Drum\":/problema/drum\r\n* \"536. Razboi 2\":/problema/razboi2\r\n* \"538. Impartire\":/problema/impartire\r\n* \"539. Perm 6\":/problema/perm6\r\n* \"550. Logic2\":/problema/logic2\r\n* \"551. Triticale\":/problema/triticale\r\n* \"744. Numar2\":/problema/numar2\r\n* \"745. Iepuri2\":/problema/iepuri2\r\n* \"746. Colaj\":/problema/colaj\r\n* \"749. Concurs2\":/problema/concurs2\r\n* \"767. Ab2\":/problema/ab2\r\n* \"768. Iepuras\":/problema/iepuras\r\n* \"769. Palind2\":/problema/palind2\r\n* \"770. Auto\":/problema/auto\r\n* \"771. Div\":/problema/div\r\n* \"772. Teatru\":/problema/teatru\r\n* \"926. Cerc3\":/problema/cerc3\r\n* \"927. Project management\":problema/pm2\r\n\r\nh3. Probleme propuse in arhiva:\r\n\r\n* \"905. Cifra lipsa\":/problema/cifralipsa\r\n\r\nh3. Probleme adaugate in arhiva educationala:\r\n\r\n* \"Floyd-Warshall / Roy-Floyd\":/problema/royfloyd\r\n* \"Parcurgere DFS - componente conexe\":/problema/dfs\r\n\r\nh2. Prieteni pe Infoarena:\r\n\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"mariusdrg\" type=\"tiny\")==\r\n* ==User(user=\"devilkind\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"razvi9\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"Dastas\" type=\"tiny\")==\r\n* ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n* ==User(user=\"blasterz\" type=\"tiny\")==\r\n* ==User(user=\"stef2n\" type=\"tiny\")==\r\n* ==User(user=\"CezarMocan\" type=\"tiny\")==\r\n* ==User(user=\"Protoman\" type=\"tiny\")==\r\n* ==User(user=\"motty\" type=\"tiny\")==\r\n* ==User(user=\"Florian\" type=\"tiny\")==\r\n* ==User(user=\"anna_bozianu\" type=\"tiny\")==\r\n* ==User(user=\"sima_cotizo\" type=\"tiny\")==\r\n* ==User(user=\"sigrid\" type=\"tiny\")==\r\n\r\n',6172,'public',NULL,NULL),('algoritmiada-2010/clasament/runda-3/11-12','Algoritmiada 2010 - Clasament Runda 3, Clasele 11-12','2010-01-18 11:55:37','2010-01-18 15:43:17','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda3-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-3\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-3/studenti\r\n*(active) \'Rezultate\':algoritmiada-2010/clasament/runda-3/11-12\r\n\r\n==include(page=\"template/algoritmiada-2010/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-3/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2010/clasament/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-3/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda3-11-12\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1792,'protected',NULL,NULL),('algoritmiada-2010/clasament/runda-3/studenti','Algoritmiada 2010 - Clasament Runda 3, Studenti','2010-01-18 11:55:37','2010-01-18 15:42:31','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda3-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-3\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-3/studenti\r\n*(active) \'Rezultate\':algoritmiada-2010/clasament/runda-3/studenti\r\n\r\n==include(page=\"template/algoritmiada-2010/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-3/11-12\r\n*(active) \'Studenti\':algoritmiada-2010/clasament/runda-3/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda3-studenti\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1792,'protected',NULL,NULL),('utilizator/motty','Profil motty','2008-10-24 09:08:52','2010-03-18 12:05:33','h2. Despre mine\r\n\r\n  _Sunt elev in clasa a 10-a la Colegiul National de Informatica \"Tudor Vianu\";_\r\n  _Am inceput informatica in octombrie 2008(clasa a 9-a);_\r\n  _{*In God we Trust!*}_\r\n  _Gibson rulez \\m/;_\r\n\r\nh2. Distinctii primite\r\n\r\n  _Mentiune la ONI 2009 (clasa a 9-a);_\r\n  _Premiul I la Concursul de Informatica \"Urmasii lui Moisil\" Iasi - 2009;_\r\n\r\nh2. Profesori\r\n\r\n  ==User(user=\"rapidu36\" type=\"tiny\")==\r\n  ==User(user=\"filipb\" type=\"tiny\")==\r\n  ==User(user=\"andrei.12\" type=\"tiny\")==\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n  ==User(user=\"gabitzish1\" type=\"tiny\")==\r\n  ==User(user=\"gcosmin\" type=\"tiny\")==\r\n  ==User(user=\"cosmin79\" type=\"tiny\")==\r\n  ==User(user=\"ira\" type=\"tiny\")==\r\n  ==User(user=\"ilinca\" type=\"tiny\")==\r\n  ==User(user=\"funkydvd\" type=\"tiny\")==\r\n  ==User(user=\"punkist\" type=\"tiny\")==\r\n  ==User(user=\"andreyp\" type=\"tiny\")==\r\n  ==User(user=\"tvlad\" type=\"tiny\")==\r\n  ==User(user=\"drag0s93\" type=\"tiny\")==\r\n  ==User(user=\"ciprianf\" type=\"tiny\")==\r\n  ==User(user=\"AndreiDuma\" type=\"tiny\")==\r\n  ==User(user=\"Ioanna\" type=\"tiny\")==\r\n  ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n  ==User(user=\"hadesgames\" type=\"tiny\")==\r\n  ==User(user=\"andreisfrent\" type=\"tiny\")==',8690,'public',NULL,NULL),('utilizator/motty','Profil motty','2008-10-24 09:08:52','2010-03-18 12:05:53','h2. Despre mine\r\n\r\n  _Sunt elev in clasa a 10-a la Colegiul National de Informatica \"Tudor Vianu\";_\r\n  _Am inceput informatica in octombrie 2008(clasa a 9-a);_\r\n  _{*In God we Trust!*}_\r\n  _Gibson rulez \\m/;_\r\n\r\nh2. Distinctii primite\r\n\r\n  _Mentiune la ONI 2009 (clasa a 9-a);_\r\n  _Premiul I la Concursul de Informatica \"Urmasii lui Moisil\" Iasi - 2009;_\r\n\r\nh2. Profesori\r\n\r\n ==User(user=\"rapidu36\" type=\"tiny\")==\r\n  ==User(user=\"filipb\" type=\"tiny\")==\r\n  ==User(user=\"andrei.12\" type=\"tiny\")==\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n  ==User(user=\"gabitzish1\" type=\"tiny\")==\r\n  ==User(user=\"gcosmin\" type=\"tiny\")==\r\n  ==User(user=\"cosmin79\" type=\"tiny\")==\r\n  ==User(user=\"ira\" type=\"tiny\")==\r\n  ==User(user=\"ilinca\" type=\"tiny\")==\r\n  ==User(user=\"funkydvd\" type=\"tiny\")==\r\n  ==User(user=\"punkist\" type=\"tiny\")==\r\n  ==User(user=\"andreyp\" type=\"tiny\")==\r\n  ==User(user=\"tvlad\" type=\"tiny\")==\r\n  ==User(user=\"drag0s93\" type=\"tiny\")==\r\n  ==User(user=\"ciprianf\" type=\"tiny\")==\r\n  ==User(user=\"AndreiDuma\" type=\"tiny\")==\r\n  ==User(user=\"Ioanna\" type=\"tiny\")==\r\n  ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n  ==User(user=\"hadesgames\" type=\"tiny\")==\r\n  ==User(user=\"andreisfrent\" type=\"tiny\")==',8690,'public',NULL,NULL),('blog/algoritmiada-2010-runda-3','Algoritmiada 2010: Analiza rundei 3','2010-03-19 09:53:43','2010-03-19 13:29:34','h1. Algoritmiada 2010: Analiza rundei 3\r\n\r\nPe data de 21 februarie a avut loc cea de-a \'treia\':/algoritmiada-2010/runda-3 rundă a concursului Algoritmiada 2010. La două luni de la de la runda a doua concurenţii au revenit să îşi măsoare forţele cu problemele propuse de \'infoarena\':.\r\n\r\nStatisticile primelor 3 runde arată in felul următor:\r\n\r\ntable. |_. &nbsp; |_. Runda 1 |_. Runda 2 |_. Runda 3 |\r\n| Câţi concurenţi au trimis soluţii | 181 | 135 | 136 |\r\n| Câţi concurenţi s-au înscris | 308 | 174 | 196 |\r\n| Surse trimise | 765 | 627 | 552 |\r\n| Surse cu punctaj pozitiv | 345 | 312 | 263 |\r\n| Concurenţi cu punctaj pozitiv | 122 | 107 | 104 |\r\n| Punctaj mediu al concurenţilor care au trimis soluţii | 58.07 | 76.26 | 61.17 |\r\n| Punctaj mediu al concurenţilor cu punctaj strict mai mare ca 0 | 86.15 | 96.87 | 80 |\r\n\r\nDin statistici observăm ca numărul de concurenţi de la runda a treia este comparabil cu cel de la runda a doua. Este un lucru îmbucurător deoarece in anii trecuţi tendinţa a fost de descreştere de la rundă la rundă şi sperăm că la fel de mulţi concurenţi o să participe si la runda a patra.\r\n\r\nConcurenţii de la gimnaziu au avut parte de un set de probleme dificil. Pe primul loc s-a situat == User(user=\"eudanip\") == cu 200 de puncte, pe locul al doilea == User(user=\"GheorgheMihai\") == cu 170 de puncte iar pe locul al treilea, la egalitate, cu 110 puncte == User(user=\"Magnus\") == şi == User(user=\"Marius96\") ==.\r\n\r\nElevii de la clasele 9-10 au avut punctajele cele mai mari, iar la finalul rundei, 6 concurenti aveau punctaje mai mari sau egale cu 200 de puncte. Astfel, punctajul cel mai mare al rundei a treia, de 270 de puncte, a fost obţinut de == User(user=\"freak93\") ==. Poziţia a doua in clasament a fost ocupata de == User(user=\"raduzer\") == cu 250 de puncte iar a treia de == User(user=\"GavrilaVlad\") == cu 240 de puncte.\r\n\r\nLa clasele 11-12 numarul de participanţi a fost semnificativ mai mare decat la celelalte grupe de varstă, însă problemele le-au pus mici probleme participanţilor. La finalul rundei numai 3 concurenti aveau un punctaj mai mare de 110 puncte, ei fiind == User(user=\"andrei.12\") == cu 200 de puncte, == User(user=\"Iliee\") == cu 170 de puncte si == User(user=\"stocarul\") == cu 160 de puncte.\r\n\r\nStundentii au avut parte de un set de probleme echilibrat. Toate problemele au fost rezolvate dar nici un concurent nu le-a rezolvat pe toate de 100 de puncte. Cel mai aproape a fost  == User(user=\"mugurelionut\") == care a obtinut 240 de puncte, el a fost urmat de == User(user=\"mihai_florea\") == cu 200 de puncte si de == User(user=\"razvi9\") == cu 170 de puncte.\r\n\r\nSeturile de probleme propuse la runda a treia au fost bine structurate, reuşind sa departajeze in mod clar concurentii din varful clasamentelor si in acelasi timp oferindu-le tuturor participantilor cate o provocare.\r\n\r\nMult succes in runda a \'patra\':algoritmiada-2010/runda-4 care are loc duminica, 21 martie de la ora 9:00.',6172,'public',4667,NULL),('planificare','Planificare infoarena','2007-02-16 17:54:49','2010-03-19 08:59:25','h1. Planificare infoarena\r\n\r\n==include(page=\"planificare/sidebar\")==\r\n\r\nAici discutam despre planurile si proiectele infoarena (deadlines, echipe, bugete etc.). Majoritatea acestor pagini sunt publice si vizibile pentru toti utilizatorii. Este bine sa lucram cat mai transparent pentru a \'atrage si alti oameni\':implica-te. Este inevitabil sa exista si niste informatii confidentiale (surprize, sau enunturi de probleme), pentru care putem face si \'pagini private\':documentatie/administrare.\r\n\r\nToate subpaginile acestei sectiuni vor avea titlul de forma: planificare/sedinte, planificare/sponsori etc. \r\n\r\nh2. Sedinte\r\n\r\nDin cand in cand facem sedinte ale \'asociatiei\':asociatia-infoarena unde discutam live diverse lucruri. Aici avem note de la niste sedinte trecute.\r\n\r\nEste ok sa modificam pagini de sedinte cu update-uri asupra task-urilor.\r\n\r\nh3. 2010\r\n\r\n* \'*2010-02-16*\':planificare/sedinta-20100216\r\n* \'2010-01-12\':planificare/sedinta-20100112\r\n\r\nh3. 2009\r\n\r\n* \'2009-11-26\':planificare/sedinta-20091126\r\n* \'2009-11-03\':planificare/sedinta-20091103\r\n* \'2009-10-23\':planificare/sedinta-20091023\r\n* \'2009-10-15\':planificare/sedinta-20091015\r\n* \'2009-07-27\':planificare/sedinta-20090727\r\n* \'2009-04-03\':planificare/sedinta-20090403\r\n* \'2009-03-16\':planificare/sedinta-20090316\r\n* \'2009-02-16\':planificare/sedinta-20090216\r\n* \'2009-01-26\':planificare/sedinta-20090126\r\n* \'2009-01-12\':planificare/sedinta-20090112\r\n\r\nh3. 2008\r\n\r\n* \'2008-11-25\':planificare/sedinta-20081125\r\n* \'2008-11-07\':planificare/sedinta-20081107\r\n* \'2008-10-21\':planificare/sedinta-20081021\r\n* \'2008-10-10\':planificare/sedinta-20081010\r\n* \'2008-04-11\':planificare/sedinta-20080411\r\n* \'2008-03-14\':planificare/sedinta-20080314\r\n* \'2008-03-03\':planificare/sedinta-20080303\r\n* \'2008-02-18\':planificare/sedinta-20080218\r\n* \'2008-02-01\':planificare/sedinta-20080201\r\n* \'2008-01-18\':planificare/sedinta-20080118\r\n\r\nh3. 2007\r\n\r\n* \'2007-12-18\':planificare/sedinta-20071218\r\n* \'2007-11-28\':planificare/sedinta-20071128\r\n* \'2007-11-07\':planificare/sedinta-20071107\r\n* \'2007-10-27\':planificare/sedinta-20071027\r\n* \'2007-10-24\':planificare/sedinta-20071024\r\n* \'2007-06-15\':planificare/sedinta_20070615\r\n* \'2007-05-07\':planificare/sedinta_20070507\r\n* \'2007-04-24\':planificare/sedinta_20070424\r\n* \'2007-03-03\':planificare/sedinta_20070303\r\n* \'2007-02-15\':planificare/sedinta_20070215\r\n* \'2007-01-04\':planificare/sedinta_20070104\r\n\r\nh3. 2006\r\n\r\n* \'2006-12-14\':planificare/sedinta_20061214\r\n* \'2006-11-21\':planificare/sedinta_20061121\r\n* \'2006-11-01\':planificare/sedinta-20061101\r\n\r\nh2(#coding-camps). Coding Camps\r\n\r\n* \'*Tagging Camp \"Neverending Story\"*\':planficare/camp-neverending-story\r\n* \'*Coding Camp \"We can do it\"*\':planificare/camp-2.3.1\r\n* \'Coding Camp \"A 2nd New Day\"\':planificare/camp-2.3\r\n* \'Coding Camp \"A New Day\"\':planificare/camp-2.2.1\r\n* \'Coding Camp Alcatraz\':planificare/camp-alcatraz\r\n* \'Coding Camp Karate-Kids\':planificare/karate-kids\r\n* \'Coding Camp Noname\':planificare/camp-noname\r\n* \'Coding Camp Chuckie\':planificare/camp-chuckie\r\n\r\nh2. Proiecte trecute\r\n\r\n* \'Asociatia infoarena, infiintare\':planificare/asociatia-infoarena\r\n* \'Algoritmiada 2009\':planificare/algoritmiada-2009\r\n** \'Promovare\':planificare/algoritmiada-2009/promovare\r\n** \'How-to\':planificare/algoritmiada-2009/how-to\r\n** \'Roluri\':planificare/algoritmiada-2009/roluri\r\n** \'Runda 1\':planificare/algoritmiada-2009/runda-1\r\n** \'Runda 2\':planificare/algoritmiada-2009/runda-2\r\n** \'Runda 3\':planificare/algoritmiada-2009/runda-3\r\n** \'Runda Finala\':planificare/algoritmiada-2009/runda-finala\r\n* \'preONI 2008\':planificare/preoni-2008\r\n** \'How-to\':planificare/preoni-2008/how-to\r\n** \'Roluri\':planificare/preoni-2008/roluri\r\n** \'Runda 1\':planificare/preoni-2008/runda-1\r\n** \'Runda 2\':planificare/preoni-2008/runda-2\r\n** \'Runda 3\':planificare/preoni-2008/runda-3\r\n** \'Runda 4\':planificare/preoni-2008/runda-4\r\n** \'Runda 5\':planificare/preoni-2008/runda-5\r\n** \'Finala\':planificare/preoni-2008/finala',2028,'protected',NULL,NULL),('planificare/camp-neverending-story','Tagging Camp \"Neverending Story\"','2010-03-19 09:02:24','2010-03-19 13:59:17','h1. Tagging Camp _\"Neverending Story\"_\r\n\r\nNe intalnim in weekend-ul *20-21 martie 2010*, in fiecare zi intre orele *10:00* si *20:00*, la _Cuibul Marmotelor_.\r\n\r\nScopul tagging campului este sa dam note/tagguim un numar cat mai mare de probleme din arhiva.\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu acces la internet.\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri.\r\n\r\nh2. Participanti\r\n\r\nSpecifica daca poti veni si cat poti sta.\r\n\r\n* ==user(user=\"wefgef\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"victorsb\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"prostu\" type=\"tiny\")==: duminica\r\n* ==user(user=\"stef2n\" type=\"tiny\")==: sambata\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==: sambata >= 12:00, duminica\r\n\r\nh2. Agenda\r\n\r\n* Infoarena grading guidelines\r\n* Lucru in echipe:\r\n\r\n|_. Echipa|_. Set de probleme |_. Stare |\r\n| &nbsp; | &nbsp; | &nbsp; |',1490,'public',NULL,NULL),('problema/adunare','A+B','2006-11-11 11:23:33','2009-12-21 12:26:21','==Include(page=\"template/taskheader\" task_id=\"adunare\")==\r\n\r\nAdunare simplă.\r\n\r\nh2. Date de intrare\r\n\r\nDatele de intrare se citesc din fişierul $adunare.in$:\r\n\r\n* pe prima linie un număr intreg $a$\r\n* pe a doua linie un număr intreg $b$\r\n\r\nh2. Date de ieşire\r\n\r\nDatele de ieşire se tipăresc în fişierul $adunare.out$\r\n\r\n* pe prima linie: suma celor două numere $a + b$\r\n\r\nh2. Restricţii\r\n\r\n* Suma celor două numere nu va depăşi niciodată valoarea $2 000 000 000$.\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. adunare.in |_. adunare.out |\r\n| 131\r\n  245\r\n| 376 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"adunare\")==\r\n\r\nh2. Precizare\r\n\r\n* Problema e dată pentru a vă obişnui cu site-ul. Nu e nevoie să postaţi pe forum că e foarte uşoara, ştim cu toţii asta. :)\r\n',1490,'task: adunare',27,NULL),('planificare/camp-2.3.1','Coding Camp \"We can do it\"','2010-03-03 15:34:27','2010-03-19 16:35:21','h1. Coding Camp _\"We can do it\"_\r\n\r\nNe intalnim in weekend-ul *13-14 martie 2010*, in fiecare zi intre orele *9:00* si *17:00*, la ICHB.\r\n\r\nScopul final al coding camp-ului este familiarizarea mai multor membri ai comunitatii/echipei cu codebase-ul infoarena si lansarea versiunii \"infoarena 2.3.1\":http://hackers.devnet.ro/milestone/2.3.1%20Yes%20We%20Can.\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu Linux instalat pe el (preferabil ubuntu).\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri\r\n\r\nh2. Participanti\r\n\r\nSpecifica cand poti veni si cat poti sta.\r\n\r\n* ==user(user=\"devilkind\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"wefgef\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"victorsb\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"Prostu\" type=\"tiny\")==: sambata\r\n\r\nh2. Agenda\r\n\r\nh3. Must have \r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n|\"Note pentru probleme\":http://hackers.devnet.ro/ticket/395| ==user(user=\"wefgef\" type=\"tiny\")== ==user(user=\"gcosmin\" type=\"tiny\")== | \"Done\":http://reviewboard.infoarena.ro/r/140/ |\r\n| Script de recalculat timpii de evaluare | ==user(user=\"bogdan2412\" type=\"tiny\")== | 0 |\r\n| \"Script de sters automat backup-uri vechi\":http://hackers.devnet.ro/ticket/398 | ==user(user=\"victorsb\" type=\"tiny\")== | \"Done\":http://reviewboard.infoarena.ro/r/136/ |\r\n| \"Fix grader test files that don\'t end with \\n\":http://hackers.devnet.ro/ticket/399 | ==user(user=\"victorsb\" type=\"tiny\")== | \"La review\":http://reviewboard.infoarena.ro/r/139/ |\r\n| Split ia_score | ==user(user=\"devilkind\" type=\"tiny\")== | \'Done\':http://reviewboard.infoarena.ro/r/64/ |\r\n\r\nh3. \"Heavy\":http://shaunchng.com/gallery/main.php?g2_view=core.DownloadItem&g2_itemId=658 (pentru useri experimentati)\r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n| \'Sters automat concursuri virtuale nefolosite\':http://hackers.devnet.ro/ticket/376 | 0 | 0 |\r\n| \"Interfata de search pentru taguri\":http://hackers.devnet.ro/ticket/391 | 0 | 0 |\r\n| \'Functionalitate de sters runde\':http://hackers.devnet.ro/ticket/373 | ==user(user=\"prostu\" type=\"tiny\")== | \'Done\':http://reviewboard.infoarena.ro/r/134/ |\r\n| \'Optimizeaza pagina de changes\':http://hackers.devnet.ro/ticket/383 | 0 | 0 |\r\n\r\nh3. Light (pentru useri mai putin experimentati)\r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n|\"Recover forum birthdays\":http://hackers.devnet.ro/ticket/394 | 0 | 0 |\r\n|\"Make it possible to remove all algorithm tags from tasks\":http://hackers.devnet.ro/ticket/396 | ==user(user=\"gcosmin\" type=\"tiny\")== | \'Done\':http://reviewboard.infoarena.ro/r/133/ |\r\n|\"Allow helpers to rejudge their own tasks.\":http://hackers.devnet.ro/ticket/397 | ==user(user=\"gcosmin\" type=\"tiny\")== | \'Done\':http://reviewboard.infoarena.ro/r/135/ |\r\n|\"Edit forum user\":http://hackers.devnet.ro/ticket/393 | 0 | 0 |\r\n|\"Proper security UI\":http://hackers.devnet.ro/ticket/129 | ==user(user=\"wefgef\" type=\"tiny\")== | 0 |\r\n',1490,'public',NULL,NULL),('utilizator/mathboy','Profil Dragos-Alin Rotaru','2008-12-24 18:43:37','2010-03-21 11:27:23','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',9232,'public',NULL,NULL),('planificare/sedinta-20100325','Ședință 2010-03-25','2010-03-22 19:15:06','2010-03-22 19:17:06','h1. Şedinţă 2010-03-25\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Joi* la ora *19^00^* la staţia de 41 de la Plaza România.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ...\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20100216 | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada Runda finala | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| OKR | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* ...\r\n\r\nh2(#notite). Notiţe\r\n\r\n* ...',2038,'protected',NULL,NULL),('planificare','Planificare infoarena','2007-02-16 17:54:49','2010-03-22 19:17:41','h1. Planificare infoarena\r\n\r\n==include(page=\"planificare/sidebar\")==\r\n\r\nAici discutam despre planurile si proiectele infoarena (deadlines, echipe, bugete etc.). Majoritatea acestor pagini sunt publice si vizibile pentru toti utilizatorii. Este bine sa lucram cat mai transparent pentru a \'atrage si alti oameni\':implica-te. Este inevitabil sa exista si niste informatii confidentiale (surprize, sau enunturi de probleme), pentru care putem face si \'pagini private\':documentatie/administrare.\r\n\r\nToate subpaginile acestei sectiuni vor avea titlul de forma: planificare/sedinte, planificare/sponsori etc. \r\n\r\nh2. Sedinte\r\n\r\nDin cand in cand facem sedinte ale \'asociatiei\':asociatia-infoarena unde discutam live diverse lucruri. Aici avem note de la niste sedinte trecute.\r\n\r\nEste ok sa modificam pagini de sedinte cu update-uri asupra task-urilor.\r\n\r\nh3. 2010\r\n\r\n* \'*2010-03-25*\':planificare/sedinta-20100325\r\n* \'2010-02-16\':planificare/sedinta-20100216\r\n* \'2010-01-12\':planificare/sedinta-20100112\r\n\r\nh3. 2009\r\n\r\n* \'2009-11-26\':planificare/sedinta-20091126\r\n* \'2009-11-03\':planificare/sedinta-20091103\r\n* \'2009-10-23\':planificare/sedinta-20091023\r\n* \'2009-10-15\':planificare/sedinta-20091015\r\n* \'2009-07-27\':planificare/sedinta-20090727\r\n* \'2009-04-03\':planificare/sedinta-20090403\r\n* \'2009-03-16\':planificare/sedinta-20090316\r\n* \'2009-02-16\':planificare/sedinta-20090216\r\n* \'2009-01-26\':planificare/sedinta-20090126\r\n* \'2009-01-12\':planificare/sedinta-20090112\r\n\r\nh3. 2008\r\n\r\n* \'2008-11-25\':planificare/sedinta-20081125\r\n* \'2008-11-07\':planificare/sedinta-20081107\r\n* \'2008-10-21\':planificare/sedinta-20081021\r\n* \'2008-10-10\':planificare/sedinta-20081010\r\n* \'2008-04-11\':planificare/sedinta-20080411\r\n* \'2008-03-14\':planificare/sedinta-20080314\r\n* \'2008-03-03\':planificare/sedinta-20080303\r\n* \'2008-02-18\':planificare/sedinta-20080218\r\n* \'2008-02-01\':planificare/sedinta-20080201\r\n* \'2008-01-18\':planificare/sedinta-20080118\r\n\r\nh3. 2007\r\n\r\n* \'2007-12-18\':planificare/sedinta-20071218\r\n* \'2007-11-28\':planificare/sedinta-20071128\r\n* \'2007-11-07\':planificare/sedinta-20071107\r\n* \'2007-10-27\':planificare/sedinta-20071027\r\n* \'2007-10-24\':planificare/sedinta-20071024\r\n* \'2007-06-15\':planificare/sedinta_20070615\r\n* \'2007-05-07\':planificare/sedinta_20070507\r\n* \'2007-04-24\':planificare/sedinta_20070424\r\n* \'2007-03-03\':planificare/sedinta_20070303\r\n* \'2007-02-15\':planificare/sedinta_20070215\r\n* \'2007-01-04\':planificare/sedinta_20070104\r\n\r\nh3. 2006\r\n\r\n* \'2006-12-14\':planificare/sedinta_20061214\r\n* \'2006-11-21\':planificare/sedinta_20061121\r\n* \'2006-11-01\':planificare/sedinta-20061101\r\n\r\nh2(#coding-camps). Coding Camps\r\n\r\n* \'*Tagging Camp \"Neverending Story\"*\':planificare/camp-neverending-story\r\n* \'*Coding Camp \"We can do it\"*\':planificare/camp-2.3.1\r\n* \'Coding Camp \"A 2nd New Day\"\':planificare/camp-2.3\r\n* \'Coding Camp \"A New Day\"\':planificare/camp-2.2.1\r\n* \'Coding Camp Alcatraz\':planificare/camp-alcatraz\r\n* \'Coding Camp Karate-Kids\':planificare/karate-kids\r\n* \'Coding Camp Noname\':planificare/camp-noname\r\n* \'Coding Camp Chuckie\':planificare/camp-chuckie\r\n\r\nh2. Proiecte trecute\r\n\r\n* \'Asociatia infoarena, infiintare\':planificare/asociatia-infoarena\r\n* \'Algoritmiada 2009\':planificare/algoritmiada-2009\r\n** \'Promovare\':planificare/algoritmiada-2009/promovare\r\n** \'How-to\':planificare/algoritmiada-2009/how-to\r\n** \'Roluri\':planificare/algoritmiada-2009/roluri\r\n** \'Runda 1\':planificare/algoritmiada-2009/runda-1\r\n** \'Runda 2\':planificare/algoritmiada-2009/runda-2\r\n** \'Runda 3\':planificare/algoritmiada-2009/runda-3\r\n** \'Runda Finala\':planificare/algoritmiada-2009/runda-finala\r\n* \'preONI 2008\':planificare/preoni-2008\r\n** \'How-to\':planificare/preoni-2008/how-to\r\n** \'Roluri\':planificare/preoni-2008/roluri\r\n** \'Runda 1\':planificare/preoni-2008/runda-1\r\n** \'Runda 2\':planificare/preoni-2008/runda-2\r\n** \'Runda 3\':planificare/preoni-2008/runda-3\r\n** \'Runda 4\':planificare/preoni-2008/runda-4\r\n** \'Runda 5\':planificare/preoni-2008/runda-5\r\n** \'Finala\':planificare/preoni-2008/finala',2038,'protected',NULL,NULL),('arhiva','Arhiva de probleme','2006-11-11 18:59:35','2010-03-24 19:02:23','h1. Arhiva de probleme\r\n\r\nArhiva de probleme infoarena contine peste 950 de probleme. Vezi si \'clasamentul arhivei\':clasament-arhiva.\r\n\r\nh2. Lista de probleme\r\n\r\n==Tasks(round_id=\"arhiva\" show_numbers=\"true\" score=\"1\" show_ratings=\"true\" show_progress=\"true\") ==\r\n\r\nh2. Ultimele discutii despre arhiva\r\n\r\n== SmfTopics(board_id=\"1\" count=\"30\") ==\r\n',1490,'protected',NULL,NULL),('clasament-arhiva','Clasamentul arhivei de probleme','2006-11-22 22:14:20','2008-02-25 22:08:28','(htabs)* \'Dupa rating\':clasament-rating\r\n*(active) \'Arhiva de probleme\':clasament-arhiva\r\n* \'Arhiva educationala\':clasament-arhiva-educationala\r\n\r\nh1. Clasamentul \'arhivei de probleme\':arhiva\r\n\r\nClasamentul arhivei ordoneaza membrii infoarena dupa punctele obtinute rezolvand problemele din arhiva.\r\nAcest clasament reflecta *munca depusa in pregatire* pe infoarena si nu performanta concurentului in regim de concurs.\r\n\r\n== Rankings(rounds=\"arhiva\") ==',1,'protected',NULL,NULL),('utilizator/motty','Profil motty','2008-10-24 09:08:52','2010-03-22 21:47:34','h2. Despre mine\r\n\r\n* _Sunt elev in clasa a 10-a la Colegiul National de Informatica \"Tudor Vianu\"_\r\n* _Am inceput informatica in octombrie 2008 ~(clasa a 9-a)~_\r\n* _{*In God we Trust!*}_\r\n* _Gibson rulez \\m/!_\r\n\r\nh2. Distinctii primite\r\n\r\n* _Mentiune la ONI 2009 ~(clasa a 9-a)~_\r\n* _Premiul I la Concursul de Informatica \"Urmasii lui Moisil\" Iasi - 2009_\r\n\r\nh2. Profesori\r\n\r\n ==User(user=\"rapidu36\" type=\"tiny\")==\r\n  ==User(user=\"filipb\" type=\"tiny\")==\r\n  ==User(user=\"andrei.12\" type=\"tiny\")==\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n ==User(user=\"gabitzish1\" type=\"tiny\")==\r\n  ==User(user=\"gcosmin\" type=\"tiny\")==\r\n  ==User(user=\"cosmin79\" type=\"tiny\")==\r\n  ==User(user=\"ira\" type=\"tiny\")==\r\n  ==User(user=\"ilinca\" type=\"tiny\")==\r\n  ==User(user=\"funkydvd\" type=\"tiny\")==\r\n  ==User(user=\"punkist\" type=\"tiny\")==\r\n  ==User(user=\"andreyp\" type=\"tiny\")==\r\n  ==User(user=\"tvlad\" type=\"tiny\")==\r\n  ==User(user=\"ciprianf\" type=\"tiny\")==\r\n  ==User(user=\"drag0s93\" type=\"tiny\")==\r\n  ==User(user=\"AndreiDuma\" type=\"tiny\")==\r\n  ==User(user=\"Ioanna\" type=\"tiny\")==\r\n  ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n  ==User(user=\"hadesgames\" type=\"tiny\")==\r\n  ==User(user=\"andreisfrent\" type=\"tiny\")==\r\n  ==User(user=\"nemultumitu\" type=\"tiny\")==',8690,'public',NULL,NULL),('grigore-moisil-2010','Grigore Moisil 2009','2010-03-25 19:52:08','2010-03-25 19:52:08','h1. Grigore Moisil 2009\r\n\r\n(htabs)*(active) \'Despre...\':grigore-moisil-2009 \r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n* \'Rezultate\':grigore-moisil-2009/clasament/5-8\r\n\r\nInfoarena organizeaza si in acest an editia online a concursului interjudetean de informatica Grigore Moisil. Concurentii pot profita de aceasta ocazie pentru a efectua un ultim test inainte de Olimpiada Nationala. Concursul se va desfasura *Duminica 5 aprilie*, la ora {*09^00^*} si va dura *3h*. Participantii vor avea de rezolvat 2-3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n\r\nSolutiile le poti gasi \'aici\':grigore-moisil-2009/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':grigore-moisil-2009/clasament/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/clasament/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/clasament/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/clasament/11-12\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* prof. Clara Ionescu\r\n* ==User(user=\"SleepyOverlord\" type=\"tiny\")==\r\n* ==User(user=\"Marius\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n',2044,'protected',NULL,NULL),('blog/algoritmiada-2010-runda-4','blog/algoritmiada-2010-runda-4','2010-03-26 23:10:18','2010-03-26 23:10:18','h1. Algoritmiada 2010: Analiza rundei 4\r\n\r\n\'Algoritmiada\':/algoritmiada-2010 se îndreaptă cu paşi repezi spre runda finală. Ne-am distrat, dar n-am încetat să facem şi treabă serioasă, v-am pregătit probleme frumoase şi v-am pus serios la încercare în repetate rânduri. Între timp, ca bonus pentru interesul vostru, am \"redesenat\" pe ici, pe colo monitorul de evaluare. Şi i-am mai pus nişte combustibil, acum se mişcă mai repede şi mai bine. :P \r\nCe a ieşit aţi văzut şi voi. De plăcut, credem că v-a plăcut, deoarece aţi revenit la fiecare rundă. :)\r\n\r\nIar ca să nu dezminţim ceea ce a devenit deja tradiţie, să tragem puţin cu ochiul la rezultatele din weekendul acesta, când s-a jucat ultima carte pentru calificare:\r\n\r\nÎn rândul celor mici, la gimnaziu, punctajele au fost, din păcate, mai timide. La nivel de dificultate, problema uşoară a fost Binar, cea medie Copii, iar cea grea Cuburi5. În mod surprinzător, problema Binar nu a fost rezolvată decât de un singur concurent; majoritatea a ales să implementeze QuickSort, nereuşind să observe soluţia O(N * M). Cu toate acestea, în rândul primilor 3 concurenţi s-au înregistrat şi punctaje maxime pe problemă. Îi felicităm astfel pe Liana Tucar şi pe Taloi Bogdan Cristian, ocupanţii locurilor 2, respectiv 3, pentru scor maxim la problema Copii, şi mai ales pe Daniel Posdarascu, singurul care a găsit soluţiile optime pentru Binar şi Cuburi5!\r\n\r\nLa clasele 9-10 problemele s-au împărţit după cum urmează: cea uşoară a fost Copii, cea medie Reţea, iar cea grea Matrice3. Felicitări lui Andrei Purice pentru că a obţinut cel mai mare punctaj, şi laude speciale lui Şerban Andrei Stan, singurul care a rezolvat problema grea şi care, de altfel, a fost la un pas de punctajul maxim. Îl tragem virtual şi părinteşte de urechi pentru că a greşit tocmai la problema uşoară, dar sperăm să ia aminte la runda finală :). Nu îl uităm nici pe Radu Voroneanu şi îl felicităm pentru a treia poziţie în clasament!\r\n\r\nClasele 11-12 au avut un set greu de probleme, probabil mai dificil ca în celelalte runde. La această grupă savoarea a fost dată de lupta strânsă pentru ultimele locuri de calificare, care a făcut aşteptarea mai interesantă. Ca grad de dificultate, Reţea a fost problema mai uşoară, Piraţi cea medie şi Compact problema grea. Cu toate că notăm câteva punctaje maxime în rândul celei din urmă, se pare însă că nimeni nu a ieşit victorios în lupta cu Piraţii. Podiumul a fost ocupat, în ordine, de Andrei-Bogdan Antonescu, Andrei Poenaru, Cazacu Alexandru şi Andrei Parvu, ultimii doi aflându-se la egalitate. Felicitări!\r\n\r\nNu în cele din urmă, punem sub lupă şi studenţii, care au avut un set de probleme mai uşor ca altădată (Cuburi5 uşoară, Tree medie şi Compact grea). Îi spunem bravo din nou veteranului nostru, Mugurel Ionuţ Andreica, singurul concurent care a obţinut punctaj maxim! El se situează (iar) pe primul loc, atât runda aceasta cât şi în clasamentul final, unde a obţinut un remarcabil scor de peste 1000 de puncte. Felicitările noastre merg şi către al doilea clasat, Marius Drăguş, dar şi către ocupanţii locului 3, unde avem iar egalitate: Tudose Vlad şi Vlad Saveluc.\r\n\r\nÎn ceea ce priveşte comisia ştiinţifică, aceasta şi-a făcut bine treaba, cu aceeaşi rigurozitate cu care v-a obişnuit. O mică scăpare a avut loc la problema Piraţi, unde enunţul nu a fost suficient de clar asupra modului în care trebuie afişată soluţia. Mulţumim concurenţilor pentru că au sesizat cu promptitudine situaţia, pe care am remediat-o imediat pentru a ne asigura că nu defavorizăm pe nimeni. De asemenea, trebuie menţionat faptul că nu s-au putut diferenţia in mod corespunzător soluţiile O(N) şi O(NlogN) la problema Compact şi comisia a preferat să lase limita de timp mai largă pentru a păstra calitatea problemei (diferenţa între concurenţi să nu se facă la nivel de implementare sau în funcţie de diverse trucuri de optimizare). Din păcate, acest lucru a permis ca unii concurenţi să obţină punctajul maxim şi fără să rezolve problema optim.\r\n\r\nCa să nu vă trădăm aşteptările, iată şi statisticile, după cum v-am obişnuit la fiecare rundă: \r\nRunda 4:\r\nNumber of contestants who submitted at least one solution: 119\r\nNumber of registered users: 167\r\nNumber of submitted jobs: 492\r\nNumber of submitted jobs with positive score: 247\r\nNumber of users with positive scores: 86\r\nAverage score of contestants: 64.12\r\nAverage score of contestants with strictly positive scores: 88.72\r\nTotal:\r\nNumber of contestants who submitted at least one solution: 283\r\nNumber of registered users: 499\r\nNumber of submitted jobs: 2436\r\nNumber of submitted jobs with positive score: 1167\r\nNumber of users with positive scores: 199\r\nAverage score of contestants: 129.95\r\nAverage score of contestants with strictly positive scores: 185.05\r\n\r\n\r\nVă aşteptăm şi la finală: cu mic cu mare, în dulce târgul Ieşilor (da, aţi văzut bine, bătălia cea mare se da la Iaşi :) ), Şi pentru cei care nu veţi veni, vă aşteptăm, ca de obicei, la competiţia online, cu aceeaşi (inter)faţă prietenoasă, cu un set de probleme cât se poate de interesante şi cu la fel de multă dedicare: nu fiţi dezamăgiţi de rezultate, ultima şi cea mai importantă rundă vă oferă ocazia să arătaţi că locul vostru este undeva mai sus!\r\n\r\n\r\nPână atunci, vă rugăm nu uitaţi să vă completaţi paginile de profil: vrem să vă cunoaştem, atât noi cât şi tot restul lumii, că doar ne mândrim cu voi. :)\r\nAşteptăm impresiile voastre de până acum, dar şi gândurile cu care întâmpinaţi Finala. În plus, să ştiţi că n-am uitat cât v-a plăcut fotbalul la Braşov. O să revenim cu surprize!',3065,'private',NULL,NULL),('grigore-moisil-2010/solutii/transport2','grigore-moisil-2010/solutii/transport2','2010-03-27 11:36:05','2010-03-27 11:42:09','h2(#transport2). \'Control\':problema/transport2\r\n\r\n...',7271,'public',NULL,NULL),('template/algoritmiada-2010/runda-finala/probleme','template/algoritmiada-2009/runda-finala/probleme','2010-03-27 17:26:37','2010-03-27 17:26:37','(htabs)* \'Despre&hellip;\':algoritmiada-2009/runda-finala\r\n* \'Program\':algoritmiada-2009/runda-finala/program\r\n* \'Regulament\':algoritmiada-2009/runda-finala/regulament\r\n*(active) \'Probleme\':algoritmiada-2009/runda-finala/probleme\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-finala/5-8\r\n* \'Poze\':algoritmiada-2009/runda-finala/poze',1792,'protected',NULL,NULL),('algoritmiada-2010/clasament/runda-finala/9-10','Algoritmiada 2009, Clasament Runda Finala, Clasele 9-10','2010-03-27 16:58:21','2010-03-27 16:58:21','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda5-9-10\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2009/runda-finala/rezultate\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-finala/5-8\r\n*(active) \'Clasele 9-10\':algoritmiada-2009/clasament/runda-finala/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-finala/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda5-9-10\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',1490,'protected',NULL,NULL),('algoritmiada-2010/clasament/runda-finala/11-12','Algoritmiada 2009, Clasament Runda Finala, Clasele 11-12','2010-03-27 16:58:21','2010-03-27 16:58:21','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda5-11-12\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2009/runda-finala/rezultate\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-finala/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-finala/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2009/clasament/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-finala/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda5-11-12\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',1490,'protected',NULL,NULL),('notiuni-de-geometrie-si-aplicatii/punct-in-poligon','Punct in poligon','2009-06-28 22:41:59','2010-03-27 17:43:14','h2. Punct in interiorul unui triunghi\r\n\r\nSe da un triunghi prin coordonatele varfurilor. Se cere sa se afiseze pentru un set de $N$ puncte din plan daca apartin sau nu interiorului triunghiului. Pentru a rezolva aceasta problema, sa consideram triunghiul $ABC$ si punctul $P$, interior acestuia.\r\n!notiuni-de-geometrie-si-aplicatii?triunghi.jpg!\r\n\r\nObservam ca vectorii ( **AB**, **BP** ), ( **BC**, **CP** ), ( **CA**, **AP** ) vor realiza mereu acelasi tip de intoarcere (in acest caz spre stanga). De aceea, determinantii:\r\n\r\n<tex>\\begin{math}\\begin{array}{ccc}\r\n\\ x_A & y_A & 1\\\\\r\nx_B & y_B & 1\\\\\r\nx_P & y_P & 1\\end{array}\\right|\\right)\\end{math}\r\n\\begin{math}\\begin{array}{ccc}\r\n\\ x_B & y_B & 1\\\\\r\nx_C & y_C & 1\\\\\r\nx_P & y_P & 1\\end{array}\\right|\\right)\\end{math}\r\n\\begin{math}\\begin{array}{ccc}\r\n\\ x_C & y_C & 1\\\\\r\nx_A & y_A & 1\\\\\r\nx_P & y_P & 1\\end{array}\\right|\\right)\\end{math}\r\n</tex>\r\n\r\ndet( ((xA,yA,1),(xB,yB,1),(xP,yP,1)) ), det( ((xB,yB,1),(xC,yC,1),(xP,yP,1)) ), det( ((xC,yC,1),(xA,yA,1),(xP,yP,1)) ) \r\n*cotizo* - :) trebuie LaTeX :)\r\n\r\ntrebuie sa aiba acelasi semn. In caz contrar, $P$ este in exteriorul triunghiului. In imaginea precedenta, se observa ca in cazul punctului $P\'$, vectorii **BC**, **CP** fac o intoarcere la dreapta, deci determinantul corespunzator nu va avea acelasi semn cu ceilalti doi. \r\n\r\nAceasta idee poate fi generalizata pentru a fi determina daca un punct se afla in interiorul unui poligon convex in $O(N)$. Mai exact se calculeaza det( (x{~i~},y{~i~},1), (x{~i+1~}, y{~i+1~}, 1) (x{~p~},y{~p~},1) ) pentru $i$ luand valori de la $1$ la $N$ (cand $i$=={$N$} vom considera $i+1=1$) . Punctul P(x{~p~},y{~p~}) se afla in interiorul poligonului daca si numai daca toti determinanti au acelasi semn. ( \"+\" daca parcurgem poligonul in sens direct trigonometric, \"-\" altfel)\r\n\r\nh2. Punct in interiorul unui poligon oarecare\r\n\r\nSe da un poligon oarecare cu $N$ varfuri si un punct $P$ prin coordonatele carteziene. Se cere sa se determine daca punctul $P$ este in interiorul sau in exteriorul poligonului. \r\n\r\nSe va trasa o semidreapta orizontala cu originea in punctul $P$. Daca aceasta semidreapta intersecteaza un numar impar de muchii ale poligonului, atunci punctul se afla in interiorul acestuia. Mentionam ca trebuie avut in vedere cazul in care semidreapta trece chiar printr-un varf de poligon (capat a doua muchii). Vom considera imaginea urmatoare:\r\n\r\n !notiuni-de-geometrie-si-aplicatii?poligon-raza.jpg!\r\n\r\nIn cazul punctului P{~1~}, respectiv P{~2~}, semidreptele intersecteaza 3, respectiv 1 latura (numere impare) deci punctele se afla in interior. Semidreapta corespunzatoare lui P{~3~} intersecteaza o latura si un varf de poligon. Pentru a rezolva acum aceasta problema, o solutie ar fi ca in loc sa alegem semidreapta orizontala, sa luam o semidreapta random, astfel posibilitatea ca ea sa intersecteze varfurile poligonului tinde spre 0. O alta solutie posibila - si mai usor de implementat - este sa consideram ca facand parte dintr-o latura doar punctul cu coordonata y mai mare. Se garanteaza astfel ca laturile care contin punctul de pe semidreapta vor fi numarate de numar par de ori (2 pt punctul de sus, 0 pt punctul de jos) si ca, implicit, nu vor afecta corectitudinea algoritmului.\r\n\r\n\r\n*devilkind* - am dat eu o solutie care merge destul de bine ptr cazul in care semidreapta orizontala intersecteaza varfuri insa e cam jegoasa asa (cu semidrepte random si e cam aiurea). Era un smen in care considerai ca numai un capat al laturii face parte din ea, dar nu mai stiu cum era.\r\n*EDIT Gcosmin (tip)* : in cazul in care semidreapta aleasa (sa zicem ca e paralela cu OX (e bine sa fie asa)) trece fix prin varful unui segment din poligon atunci segmentul il numaram doar daca semidreapta aleasa trece prin varful cu y-u mai mare. chestia asta scoate cazurile particulare si merge (da niste exemple si o sa vezi). e total aiurea sa iei o dreapta random pentru ca se complica mult treaba aiurea.\r\n*cotizo* - multumim mult :) orice ajutor e binevenit :D pastram ambele variante pt ca si eu in concurs as fi bagat un random.\r\n\r\nh2. Punct in poligon convex\r\n\r\nEnunt: Se da un poligon convex cu $N$ laturi si apoi $M$ interogari caracterizate prin coordonatele unui punct $P$, iar dumneavoastra trebuie sa determinati rapid daca punctul respectiv se afla sau nu in interiorul poligonului.\r\n\r\n*{+Solutia 1+}*\r\n\r\nSe ia un varf al poligonului, si se traseaza cele $n-3$ diagonale care pornesc din el. Astfel poligonul nostru se imparte in mai multe triunghiuri. Vom adauga intr-un vector aceste drepte plus cele $2$ laturi care au originea in varful ales de noi si le sortam dupa panta. Cand primim un query vom cauta binar dupa panta si vom afla intre ce diagonale se incadreaza acesta si verificam daca punctul nostru se afla sau nu in triunghiul respectiv. \r\n\r\nSa luam un exemplu:\r\n!notiuni-de-geometrie-si-aplicatii?polig12!\r\n\r\nIn imaginea de mai sus punctele $P{~1~}$,..{$P{~6~}$} reprezinta varfurile poligonului iar punctele $P{~7~}$, $P{~8~}$, $P{~9~}$ reprezinta interogarile. Cu rosu sunt trasate diagonalele care delimiteaza sectoarele, si le vom tine ca drepte, sortate dupa panta, impreuna cu dreptele suport pentru cele 2 laturi care au un capat in punctul $P{~1~}$. Astfel cand primim o interogare vom putea cauta binar si sa aflam in ce sector se afla acesta. Pentru punctul $P{~8~}$ spre exemplu ne vom da seama ca se afla in sectorul determinat de diagonalele care corespund punctelor $P{~4~}$ si $P{~5~}$. Astfel vom verifica daca punctul $P{~8~}$ se afla in interiorul triunghiului determinat de punctele $P{~1~}$, $P{~4~}$, $P{~5~}$. Vom proceda asemanator si pentru celelalte interogari cu mentiunea ca trebuie sa avem grija la cazurile in care punctul nu se afla in nici unul din sectoare (P{~9~}), insa asta se poate face usor cu o verificare inainte de a porni cautarea binara. \r\n\r\nAceasta solutie are complexitate O(NlogN + MlogN).\r\n\r\n*{+Solutia 2+}*\r\n\r\nO alta solutie este sa impartim planul in fasii. Astfel din fiecare varf al poligonului vom trasa o dreapta verticala. Acum pentru 2 drepte consecutive vom lua laturile care il intersecteaza si le vom sorta crescator dupa y (e clar ca aceste laturi nu se intersecteaza deci putem alege orice punct de pe latura si sa sortam dupa y-ul acestuia). Acum pentru a raspunde la interogari, vom face 2 cautari binare. Vom cauta odata sa vedem in ce fasie se incadreaza punctul nostru, iar apoi vom cauta inca odata binar sa vedem cate laturi din acea fasie sunt au y-ul mai mic decat punctul nostru. Daca acest numar este impar atunci punctul este in interior, altfel este in exterior. De mentionat ca aceasta solutie se poate aplica si la poligoane concave, de altfel in cazul poligoanelor convexe nu pot fi decat 2 laturi pe o fasie si nu ar mai fi nevoie de a doua cautare binara.\r\n\r\nSa luam un exemplu:\r\n\r\n\r\n!notiuni-de-geometrie-si-aplicatii?polig22!\r\n\r\nObservam cu rosu dreptele care delimiteaza fasiile verticale. De asemenea vedem ca punctul $P{~6~}$ are in fasia lui 2 laturi cu y-ul mai mic ca al lui si este in afara poligonului, spre deosebire de punctul $P{~7~}$ care are o singura latura cu y-ul mai mic ca al sau si este in interior.\r\nAvantajul acestei metode este ca functioneaza si in cazul poligoanelor concave, insa are dezavantajul faptului ca pot exista interogari in care punctele sa se afle pe dreapta care delimiteaza fasiile. Practic aceasta metoda este echivalenta cu metoda explicata mai sus, pentru a verifica daca un punct se afla sau nu in interiorul unui poligon oarecare. \r\nIn cazul poligoanelor convexe complexitatea este aceeasi ca si la metoda de mai sus, insa in cazul poligoanelor concave complexitatea teoretica e O(N^2 log N + M log N). Acest algoritm poate fi aplicat in rezolvarea problemei \'poligon\':problema/poligon din arhiva de probleme.\r\n\r\n\r\n*devilkind* uitativa putin la solutia asta ptr ca nu sunt foarte sigur pe complexitati - in special cand e vb de poligoane concave. Mie mi se pare ca aia e complexitatea insa e posibil sa ma insel\r\n*cotizo* da e corect - asta e si rezolvarea problemei \"poligon\"',8239,'public',NULL,NULL),('algoritmiada-2010/clasament/runda-finala/11-12','Algoritmiada 2010, Clasament Runda Finala, Clasele 11-12','2010-03-27 16:58:21','2010-03-27 17:34:34','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda5-11-12\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2010/runda-finala/rezultate\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-finala/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-finala/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2010/clasament/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-finala/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda5-11-12\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1792,'protected',NULL,NULL),('template/newround/clasament','Clasament %round_id%','2006-11-23 00:06:53','2006-11-23 21:06:44','h1. Clasament ==roundparam(round_id=\"%round_id%\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"%round_id%\")==',1142,'protected',NULL,NULL),('algoritmiada-2010/runda-finala/5-8','Algoritmiada 2010, Runda Finală, Clasele 5-8','2010-03-27 16:56:51','2010-03-28 09:16:17','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda5-5-8\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2010/runda-finala/probleme\")==\r\n\r\n(htabs-2)*(active) \'Clasele 5-8\':algoritmiada-2010/runda-finala/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-finala/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-finala/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda5-5-8\") ==\r\n\r\nConcursul începe ==roundparam(round_id=\"algoritmiada2010-runda5-5-8\" param=\"start_time\" strong=\"true\")== şi durează ==roundparam(round_id=\"algoritmiada2010-runda5-5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"algoritmiada2010-runda5-5-8\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-finala/5-8.\r\n\r\nh2. Probleme\r\n\r\nAceastă listă va deveni vizibilă doar în momentul începerii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda5-5-8\" score=\"1\")==\r\n\r\nh2. Discuţii pe forum\r\n\r\nVrei să adresezi întrebări comisiei? Fă-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"5\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('algoritmiada-2010/runda-finala/9-10','Algoritmiada 2010, Runda Finală, Clasele 9-10','2010-03-27 16:56:52','2010-03-28 09:17:15','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda5-9-10\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2010/runda-finala/probleme\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':algoritmiada-2010/runda-finala/5-8\r\n*(active) \'Clasele 9-10\':algoritmiada-2010/runda-finala/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-finala/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda5-9-10\") ==\r\n\r\nConcursul începe ==roundparam(round_id=\"algoritmiada2010-runda5-9-10\" param=\"start_time\" strong=\"true\")== şi durează ==roundparam(round_id=\"algoritmiada2010-runda5-9-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"algoritmiada2010-runda5-9-10\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-finala/9-10.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda5-9-10\" score=\"1\")==\r\n\r\nh2. Discuţii pe forum\r\n\r\nVrei sa adresezi întrebări comisiei? Fă-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"5\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('grigore-moisil-2010/solutii/g2','grigore-moisil-2010/solutii/g2','2010-03-27 11:45:40','2010-03-27 11:45:40','h2(#g2). \'G2\':problema/g2\r\n\r\n...',7271,'public',NULL,NULL),('grigore-moisil-2010/solutii/g2','grigore-moisil-2010/solutii/g2','2010-03-27 11:45:40','2010-03-28 10:28:28','h2(#g2). \'G2\':problema/g2\r\n\r\n\r\nVom folosi metoda greedy. În realitate însă nu este nevoie decât de puţină intuiţie. Condiţia ca produsul cifrelor să fie n ne conduce la ideea că cifrele numărului sunt divizori ai lui n. Un cel mai mic număr presupune în primul rând un număr minim de cifre. Astfel, vom descompune pe n într-un produs de cât mai mulţi de 9, după care cât mai mulţi de 8... până la 2. Numărul căutat reprezintă numărul format cu aceste cifre în ordine crescătoare.',9232,'public',NULL,NULL),('grigore-moisil-2010/solutii/pietre2','grigore-moisil-2010/solutii/pietre2','2010-03-27 11:47:20','2010-03-28 10:45:56','h2(#pietre2). \'Pietre2\':problema/pietre2\r\n\r\nRezolvare 1\r\n\r\nSoluţia se bazează pe observaţia că dacă vom procesa înălţimile în ordine crescătoare, atunci vom putea actualiza un drum de lungime maximă ce se termină în fiecare din aceste pătrăţele în mod corect. \r\n\r\nAstfel, algoritmul va sorta crescător toate cele n2 pătrăţelele în funcţie de înălţime şi...\r\n\r\n== code(cpp)|\r\nAlgoritm Rezolvă(n):\r\n  pentru fiecare (h, i, j) execută:	// pătrăţelul (i, j) cu înălţimea h\r\n    pentru fiecare vecin (h’, i’, j’) cu h = h’ + 1 execută:\r\n	dacă lg[i][j] < lg[i’][j’] + 1 atunci\r\n	  lg[i][j] = lg[i’][j’] + 1\r\n	sfârşit(dacă)\r\n    sfârşit(pentru)\r\n  sfârşit(pentru)\r\n\r\n   caută max{lg[i][j] : 1 <= i, j <= n}\r\n  reconstruieşte drumul alegând un vecin cu lungimea mai mică cu exact 1 \r\n  până ce se ajunge la marginea matricei.\r\nSfârşit(algoritm)\r\n==\r\n\r\nÎn implementare se va ţine cont ca pătrăţelele de pe marginea matricei care sunt puncte de plecare să fie marcate iniţial cu 0.\r\nComplexitate: O(N^2^ log(N)).\r\n\r\nRezolvare 2\r\nProblema, în ciuda faptului că limita pentru n este mare, se putea aborda şi cu backtracking. Cu o rezolvare asemănătoare cu cea de mai jos se putea obţine 90 puncte.\r\nÎn programul principal:\r\n\r\n== code(cpp)  |\r\nAlgoritm Pietre(n,t): 	// n: dimensiunea tabloului t \r\n  max = 0	// lungimea maximă a drumului \r\n  maxlin = 0 	// linia de unde porneşte cel mai lung drum \r\n  maxcol = 0	// coloana de unde porneşte cel mai lung drum \r\n  lin = 1 	// vom încerca să intrăm în tablou pornind din linia 1 \r\n  pentru col=1,n execută:\r\n    maxnou = 0 	// maximul actual \r\n    rez[lin,col] = 1 	// marcăm punctul de pornire \r\n    cauta(lin,col,2) 	// căutăm un drum având acest punct de start \r\n    dacă maxnou > max atunci	// actualizarea \r\n      max = maxnou\r\n      maxlin = lin\r\n      maxcol = col\r\n    sfârşit(dacă)\r\n  sfârşit(pentru)\r\n  //...  	 la fel procedăm cu linia n, coloana 1 şi coloana n \r\nsfârşit(algoritm)\r\n\r\nAlgoritm Cauta(lin,col,pas):\r\n  pentru i=1,4 execută:	// un element are 4 vecini \r\n    lin_nou = lin + x[i] 	// indicele de linie al vecinului \r\n    col_nou = col + y[i]	// indicele de coloană \r\n	// dacă am generat o poziţie pe teren }\r\n    dacă (lin_nou = {1,2,...,n}) şi (col_nou = {1,2,...,n}) atunci\r\n      dacă rez[lin_nou,col_nou] = 0 atunci 	// dacă nu am fost aici \r\n	// dacă numărul pietrelor este cu 1 mai mare \r\n        dacă t[lin_nou,col_nou] = t[lin,col] + 1 atunci\r\n          rez[lin_nou,col_nou] = pas	// facem pasul \r\n          dacă pas > maxnou atunci    	 //actualizăm maximul actual\r\n            maxnou = pas\r\n          sfârşit(dacă)\r\n          Cauta(lin_nou,col_nou,pas+1) 	// încercăm să continuăm drumul \r\n          rez[lin_nou,col_nou] = 0	// ştergem pasul, pentru că vom căuta alt drum \r\n        sfârşit(dacă)\r\n      sfârşit(dacă)\r\n    sfârşit(dacă)\r\n  sfârşit(pentru)\r\nSfârşit(algoritm)\r\n==\r\n\r\n\r\nunde şirurile x şi y au valorile:\r\nx = (-1,0,1,0)\r\ny = (0,1,0,-1)',9232,'public',NULL,NULL),('grigore-moisil-2010/solutii/pietre2','grigore-moisil-2010/solutii/pietre2','2010-03-27 11:47:20','2010-03-28 12:14:36','h2(#pietre2). \'Pietre2\':problema/pietre2\r\n\r\n*Rezolvare $1$*\r\n\r\nSoluţia se bazează pe observaţia că dacă vom procesa înălţimile în ordine crescătoare, atunci vom putea actualiza un drum de lungime maximă ce se termină în fiecare din aceste pătrăţele în mod corect. \r\n\r\nAstfel, algoritmul va sorta crescător toate cele $n^2^$ pătrăţelele :\r\n\r\n== code(cpp) | \r\nAlgoritm Rezolvă(n):\r\n  pentru fiecare (h, i, j) execută:	// pătrăţelul (i, j) cu înălţimea h\r\n    pentru fiecare vecin (h’, i’, j’) cu h = h’ + 1 execută:\r\n	dacă lg[i][j] < lg[i’][j’] + 1 atunci\r\n	  lg[i][j] = lg[i’][j’] + 1\r\n	sfârşit(dacă)\r\n    sfârşit(pentru)\r\n  sfârşit(pentru)\r\n\r\n   caută max{lg[i][j] : 1 <= i, j <= n}\r\n  reconstruieşte drumul alegând un vecin cu lungimea mai mică cu exact 1 \r\n  până ce se ajunge la marginea matricei.\r\nSfârşit(algoritm)\r\n==\r\n\r\nÎn implementare se va ţine cont ca pătrăţelele de pe marginea matricei care sunt puncte de plecare să fie marcate iniţial cu $0$.\r\nComplexitate: $O(N^2^ log(N))$.\r\n\r\n*Rezolvare $2$*\r\nProblema, în ciuda faptului că limita pentru n este mare, se putea aborda şi cu backtracking. Cu o rezolvare asemănătoare cu cea de mai jos se putea obţine $90$ puncte.\r\nÎn programul principal:\r\n\r\n== code(cpp)  |\r\nAlgoritm Pietre(n,t): 	// n: dimensiunea tabloului t \r\n  max = 0	// lungimea maximă a drumului \r\n  maxlin = 0 	// linia de unde porneşte cel mai lung drum \r\n  maxcol = 0	// coloana de unde porneşte cel mai lung drum \r\n  lin = 1 	// vom încerca să intrăm în tablou pornind din linia 1 \r\n  pentru col=1,n execută:\r\n    maxnou = 0 	// maximul actual \r\n    rez[lin,col] = 1 	// marcăm punctul de pornire \r\n    cauta(lin,col,2) 	// căutăm un drum având acest punct de start \r\n    dacă maxnou > max atunci	// actualizarea \r\n      max = maxnou\r\n      maxlin = lin\r\n      maxcol = col\r\n    sfârşit(dacă)\r\n  sfârşit(pentru)\r\n  //...  	 la fel procedăm cu linia n, coloana 1 şi coloana n \r\nsfârşit(algoritm)\r\n\r\nAlgoritm Cauta(lin,col,pas):\r\n  pentru i=1,4 execută:	// un element are 4 vecini \r\n    lin_nou = lin + x[i] 	// indicele de linie al vecinului \r\n    col_nou = col + y[i]	// indicele de coloană \r\n	// dacă am generat o poziţie pe teren }\r\n    dacă (lin_nou = {1,2,...,n}) şi (col_nou = {1,2,...,n}) atunci\r\n      dacă rez[lin_nou,col_nou] = 0 atunci 	// dacă nu am fost aici \r\n	// dacă numărul pietrelor este cu 1 mai mare \r\n        dacă t[lin_nou,col_nou] = t[lin,col] + 1 atunci\r\n          rez[lin_nou,col_nou] = pas	// facem pasul \r\n          dacă pas > maxnou atunci    	 //actualizăm maximul actual\r\n            maxnou = pas\r\n          sfârşit(dacă)\r\n          Cauta(lin_nou,col_nou,pas+1) 	// încercăm să continuăm drumul \r\n          rez[lin_nou,col_nou] = 0	// ştergem pasul, pentru că vom căuta alt drum \r\n        sfârşit(dacă)\r\n      sfârşit(dacă)\r\n    sfârşit(dacă)\r\n  sfârşit(pentru)\r\nSfârşit(algoritm)\r\n==\r\n\r\n\r\nunde şirurile $x$ şi $y$ au valorile:\r\n$x = (-1,0,1,0)$\r\n$y = (0,1,0,-1)$',9232,'public',NULL,NULL),('grigore-moisil-2010/solutii/egipt','grigore-moisil-2010/solutii/egipt','2010-03-27 11:44:17','2010-03-28 12:16:18','h2(#egipt). \'Egipt\':problema/egipt\r\n\r\n*Rezolvare $1$*\r\n\r\nFie $n1$ numărul elementelor egale cu $1$, $n2$ numărul elementelor egale cu $2$ şi $n3$ numărul elementelor egale cu $3$ în şirul dat $a$. Altfel spus, în şirul ordonat vom avea valori egale cu $1$ începând cu poziţia $1$ până la poziţia $n1$, valori egale cu $2$ începând cu poziţia $n1+1$ până la poziţia $n1+n2$, după care vom avea elemente egale cu $3$.\r\nNotăm cu $mij$ numărul elementelor egale cu $j$ care se află pe o poziţie pe care ar trebui să avem valoarea $i$. (Matricea $m$ are $3$ linii şi $3$ coloane.)\r\n\r\n                               !grigore-moisil-2010/solutii/egipt?1.png!\r\n\r\nFig. $1$. În mij avem numărul elementelor care trebuie duse de pe poziţia $i$ pe poziţia $j$\r\nObservăm că\r\n$m12 + m13 = m21 + m31$\r\n$m21 + m23 = m12 + m32$ \r\n$m31 + m32 = m13 + m23$\r\n\r\nDacă avem $2$ pe poziţia unui $1$ şi $1$ pe poziţia unui $2$, avem nevoie de o singură interschimbare. \r\nDacă avem o configuraţie $2 3 1$, sau $3 1 2$, avem nevoie de două interschimbări. \r\n\r\n        !grigore-moisil-2010/solutii/egipt?2.png!\r\n\r\nRezultă că numărul minim de interschimbări care sunt necesare pentru ordonarea şirului este:\r\n$min(m12, m21) + min(m23, m32) + min(m13, m31) + 2|m12 − m21|$\r\nRealizarea interschimbărilor:\r\n\r\n        !grigore-moisil-2010/solutii/egipt?3.png!\r\nFig. $3$. Poziţiile interschimbărilor: $pij$ este indicele elementului egal cu $j$ aflat pe poziţia $i$\r\n\r\n\r\n\r\n\r\n*Rezolvare $2$*\r\n\r\nRezolvarea se face în două faze. În prima fază vom pune la loc elementele egale cu $1$. Pornim cu trei variabile: $i$ va itera pornind din prima poziţie şi va merge până în ultima poziţie unde trebuie să ajungă un element egal cu $1$; $i2$ va porni din prima poziţie unde trebuie să ajungă un element egal cu $2$ şi va merge pâna la ultima poziţie de acest fel; similar $i3$ va itera pe intervalul unde trebuie să ajungă elementele egale cu $3$. \r\n$i2$ şi $i3$ vor fi poziţionate întotdeauna asupra unui element egal cu $1$. Dacă elementul pe care am poziţionat $i$ este egal cu $1$, nu trebuie să facem nimica, doar incrementăm $i$. Dacă acesta este egal cu $2$, vom schimba elementele de pe locurile $i$ şi $i2$ şi vom incrementa $i$, iar pe $i2$ îl poziţionăm pe următorul element egal cu $1$. Dacă cu $i2$ am depăşit pragul din dreapta al intervalului (adică ultimul loc unde trebuie să ajungă $2$), elementul de pe poziţia $i$ îl vom schimba cu elementul arătat de $i3$. Procedăm similar pentru elementele egale cu $3$.\r\n	În a doua fază vor ajunge şi elementele egale cu $2$ şi $3$ la locul lor, prin interschimbări evidente.',9232,'public',NULL,NULL),('grigore-moisil-2010/solutii/transport2','grigore-moisil-2010/solutii/transport2','2010-03-27 11:36:05','2010-03-28 14:56:11','h2(#transport2). \'Transport2\':problema/transport2\r\n\r\n*Soluţie 1*\r\nPentru a afla costul de la nodul $1$ la nodul $N$, vom utiliza \'algorimul lui Dijkstra\':problema/dijkstra puţin modificat. Astfel, vom reţine pentru fiecare nod, valoarea minimă între nodul $1$ şi nodul respectiv. Când dorim să mergem în vecinii nodului curent trebuie verificat dacă $min(costul_nodului_curent, costul_muchiei) > costul_nodului_vecin$. Complexitatea acestui algoritm este $O(M logN)$. \r\n\r\n*Soluţie 2*\r\nVom căuta binar răspunsul între 1 şi valoarea maximă pe care o poate avea o muchie. Pentru o valoare fixată, vom considera doar muchiile cu valoarea mai mare sau egală cu valoarea fixată şi vom utiliza o \'parcurgere în adâncime\':problema/bfs pentru a vedea dacă nodurile $1$ şi $N$ sunt în aceeaşi componentă conexă.\r\n\r\n*Soluţie 3*\r\nPentru fiecare valoare vom reţine ce muchii au valoarea respectivă. Apoi, vom itera prin toate valorile posibile începând de la cea maximă şi la fiecare pas vom uni nodurile care sunt legate prin muchia respectivă folosind structura \'mulţimi disjuncte\':problema/disjoint. Ne vom opri în momentul în care nodurile $1$ şi $N$ sunt în aceeaşi componentă conexă, rezultatul fiind prima valoare pentru care nodurile $1$ şi $N$ se află în aceeaşi componentă conexă. ',6333,'public',NULL,NULL),('runda/pregatire_2/clasament','Clasament pregatire_2','2010-04-01 13:37:02','2010-04-01 13:37:02','h1. Clasament ==roundparam(round_id=\"pregatire_2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pregatire_2\" detail_task=\"true\")==',11154,'round: pregatire_2',NULL,NULL),('utilizator/gavrilavlad','Profil Gavrila Vlad','2007-09-21 12:07:43','2010-03-10 06:06:18','   \r\n\r\nh2. Despre mine\r\n\r\nMa numesc Gavrila Vlad Alexandru si sunt elev in clasa a IX-a la ICHB. Particip de mult timp la concursuri de informatica, iar principala mea sursa de pregatire este infoarena.\r\n\r\nh2. Distinctii primite\r\n\r\nOlimpiada Nationala de Informatica\r\n\r\n* 2004 - Buzau - Mentiune\r\n* 2005 - Galati - Premiul special\r\n* 2006 - Targoviste - Mentiunea I\r\n* 2007 - Cluj - Premiul II\r\n* 2008 - Bacau - Premiul I\r\n* 2009 - Galati - Premiul II\r\n\r\nJBOI\r\n\r\n* 2008 - Shumen - Argint\r\n* 2009 - Shumen - Aur absolut\r\n\r\nPreONI, Algoritmiada si .Campion\r\n\r\n* 2008 - PreONI - Finalist\r\n* 2009 - .Campion - Locul II\r\n* 2009 - Algoritmiada - Locul I\r\n\r\nOlimpiada Nationala de Fizica\r\n\r\n* 2008, 2009, 2010 - Premiul I\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* Profesori:\r\n\r\n==user(user=\"pauldb\" type=\"normal\")==\r\n\r\n==user(user=\"wefgef\" type=\"normal\")==\r\n\r\n==user(user=\"bogdan2412\" type=\"normal\")==\r\n\r\n==user(user=\"gcosmin\" type=\"normal\")==\r\n\r\n==user(user=\"silviug\" type=\"normal\")==\r\n\r\n\r\n* Prieteni:\r\n\r\n==user(user=\"savim\" type=\"normal\")==\r\n\r\n==user(user=\"radu_voroneanu\" type=\"normal\")==\r\n\r\n==user(user=\"toni2007\" type=\"normal\")==\r\n\r\n==user(user=\"victor.ionescu\" type=\"normal\")==\r\n\r\n==user(user=\"CezarMocan\" type=\"normal\")==\r\n\r\n==user(user=\"raduzer\" type=\"normal\")==\r\n\r\n==user(user=\"matemariaescu\" type=\"normal\")==\r\n\r\n==user(user=\"GheorgheMihai\" type=\"normal\")==\r\n\r\n==user(user=\"protoman\" type=\"normal\")==\r\n\r\n==user(user=\"tvlad\" type=\"normal\")==\r\n\r\n==user(user=\"andrei-alpha\" type=\"normal\")==\r\n\r\n==user(user=\"taloibogdan\" type=\"normal\")==\r\n\r\n==user(user=\"andreea1cool\" type=\"normal\")==\r\n\r\n==user(user=\"cristian9\" type=\"normal\")==\r\n\r\n==user(user=\"tomescu_dorinel\" type=\"normal\")==\r\n\r\n==user(user=\"stef2503\" type=\"normal\")==\r\n\r\n==user(user=\"Balmus_Maxim\" type=\"normal\")==',6800,'public',NULL,NULL),('utilizator/mathboy','Rotaru Dragos Alin','2008-12-24 18:43:37','2010-04-01 06:44:22','h2. Despre mine\r\n \r\n\r\n* Elev in clasa a X-a la Colegiul National \"Unirea\" Focsani.\r\n* Lucrez pe Infoarena din 24 Decembrie 2008.\r\n \r\n\r\nh2. Prieteni pe infoarena\r\n \r\n\r\n ==user(user=\"Omega91\" type=\"normal\")==\r\n ==user(user=\"bogdanhm999\" type=\"normal\")== \r\n ==user(user=\"Florian\" type=\"normal\")==\r\n ==user(user=\"cosmin79\" type=\"normal\")==\r\n ==user(user=\"klamathix\" type=\"normal\")==\r\n ==user(user=\"Protoman\" type=\"normal\")==\r\n ==user(user=\"blasterz\" type=\"normal\")==\r\n ==user(user=\"mishu91\" type=\"normal\")==\r\n ==user(user=\"robytzza\" type=\"normal\")==\r\n ==user(user=\"doru.nitu\" type=\"normal\")==\r\n ==user(user=\"stef2n\" type=\"normal\")==\r\n ==user(user=\"DraStiK\" type=\"normal\")==\r\n\r\nOrdinea nu are importanta.\r\n \r\n',9232,'public',NULL,NULL),('algoritmiada-2010/premii','Algoritmiada 2010 - Sponsori si premii','2009-10-25 17:30:27','2009-11-03 11:52:44','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Sponsori si premii\r\n\r\nh2. Premii\r\n\r\nPentru fiecare dintre cele patru grupe, primii din clasament in urma desfasurarilor probelor online vor fi premiati cu o diploma de finalist al concursului *Algoritmiada 2010* si o \'runda finala\':algoritmiada-2010/runda-finala cu cazare si masa asigurate.\r\nAcestia vor avea sansa sa interactioneze cu membrii \'echipei infoarena\':echipa-infoarena si cu ceilalti membri ai comunitatii infoarena si sa invete de la si impreuna cu acestia. Runda finala va fi de asenemea un prilej de a ii rasplati pe cei mai buni dintre cei mai buni. Punctajele din acesta runda vor fi independente de cele acumulate la rundele online, iar primii 3 clasati la fiecare grupa vor avea parte de urmatoarele premii:\r\n\r\n* Locul I: &hellip;\r\n* Locul II: &hellip;\r\n* Locul III: &hellip;\r\n\r\n==Include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('runda/problemiada_15/clasament','Clasament problemiada_15','2010-04-13 18:33:33','2010-04-13 18:33:33','h1. Clasament ==roundparam(round_id=\"problemiada_15\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"problemiada_15\" detail_task=\"true\")==',5748,'round: problemiada_15',NULL,NULL),('blog/think-online','blog/think-online','2010-04-14 20:00:18','2010-04-14 20:21:27','h1. Think Online\r\n\r\nZilele acestea va avea loc \'Think Online\':http://thinkonline.ro/, un proiect dedicat tinerilor interesaţi de mediul de afaceri online. Pentru că aveţi cunoştinţe solide de algoritmică şi sunteţi programatori talentaţi, ne-am gândit că v-ar ajuta să aruncaţi un ochi şi la partea de business din domeniu.\r\n\r\n&nbsp;\r\nIată mesajul organizatorilor:\r\n\r\n&nbsp;\r\n_Business Club te invită în perioada 19-23 Aprilie să participi la proiectul Think Online. Într-un moment critic al economiei, domeniul afacerilor pe Internet devine unul din ce în ce mai atrăgător pentru antreprenori. Think Online, cel mai nou proiect marca Business Club, este o şcoală de antreprenoriat care va pregăti un număr de studenţi pentru a îşi deschide o afacere on-line. Ne adresăm studenţilor sau masteranzilor care sunt interesaţi de domeniul acesta, care şi-au deschis o afacere/site sau care au de gând să facă acest lucru în viitorul apropriat. Studii de caz, workshop-uri, simulări de management, networking şi un concurs inedit de idei, totul într-o atmosferă plăcută şi optimă pentru a genera idei de succes. Proiectul va avea loc la Bucharest Hubb, primul club de work&fun din România dedicat antreprenorilor online._\r\n\r\n_Participând la eveniment, vei avea ocazia să întâlneşti oameni interesaţi de afaceri online, să îţi formezi o echipă şi să creezi un plan de afaceri sub îndrumarea celor mai de succes antreprenori. Vei cunoaşte investitori, vei face networking, vei învăţa de la oameni care au o experienţă bogată în start-up-uri. Vei invăţa cum să prezinţi un pitch unui investitor şi vei primi feedback. Dar, cel mai important, dacă planul de afaceri pe care îl vei dezvolta în cadrul proiectului va fi unul atractiv, vei avea ocazia să primeşti finanţare de la un investitor important._\r\n\r\n_Şi nu uita, la sfârşitul proiectului, după aproximativ o lună, cei mai buni participanţi vor avea ocazia să participe la un teambuilding alături de o parte din speakerii evenimentului pentru a îi cunoaşte mai bine, a îşi prezenta ideile şi a lega eventuale colaborări._\r\n\r\n_La proiect, vei avea ocazia să îi cunoşti pe Vlad Stan (SeedMoney), Sergiu Biriş (Trilulilu), Vladimir Oane (UberVU), George Lemnaru (Erepublik), Daniel Enache (Investitor), Marius Deak (GreenPixel) şi mulţi alţii!_\r\n\r\n_Pentru a aplica la proiect accesează site-ul \'www.thinkonline.ro\':http://thinkonline.ro/ ._',2044,'protected',4784,NULL),('utilizator/motty','Profil motty','2008-10-24 09:08:52','2010-04-15 09:22:14','h2. Despre mine\r\n\r\n* _Sunt elev in clasa a 10-a la Colegiul National de Informatica \"Tudor Vianu\"_\r\n* _Am inceput informatica in octombrie 2008 ~(clasa a 9-a)~_\r\n* _{*In God we Trust!*}_\r\n* _Gibson rulez \\m/!_\r\n* _Aidi: motty_ep_\r\n\r\nh2. Distinctii primite\r\n\r\n* _Mentiune la ONI 2009 ~(clasa a 9-a)~_\r\n* _Premiul I la Concursul de Informatica \"Urmasii lui Moisil\" Iasi - 2009_\r\n* _Mentiune si argint la ONI 2010 ~(clasa a 10-a)~_\r\n\r\nh2. Profesori\r\n\r\n ==User(user=\"rapidu36\" type=\"tiny\")==\r\n  ==User(user=\"filipb\" type=\"tiny\")==\r\n  ==User(user=\"andrei.12\" type=\"tiny\")==\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n ==User(user=\"gabitzish1\" type=\"tiny\")==\r\n  ==User(user=\"gcosmin\" type=\"tiny\")==\r\n  ==User(user=\"cosmin79\" type=\"tiny\")==\r\n  ==User(user=\"ira\" type=\"tiny\")==\r\n  ==User(user=\"ilinca\" type=\"tiny\")==\r\n  ==User(user=\"Robytzza\" type=\"tiny\")==\r\n  ==User(user=\"funkydvd\" type=\"tiny\")==\r\n  ==User(user=\"punkist\" type=\"tiny\")==\r\n  ==User(user=\"andreyp\" type=\"tiny\")==\r\n  ==User(user=\"tvlad\" type=\"tiny\")==\r\n  ==User(user=\"ciprianf\" type=\"tiny\")==\r\n  ==User(user=\"drag0s93\" type=\"tiny\")==\r\n  ==User(user=\"AndreiDuma\" type=\"tiny\")==\r\n  ==User(user=\"Ioanna\" type=\"tiny\")==\r\n  ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n  ==User(user=\"hadesgames\" type=\"tiny\")==\r\n  ==User(user=\"andreisfrent\" type=\"tiny\")==\r\n  ==User(user=\"nemultumitu\" type=\"tiny\")==',8690,'public',NULL,NULL),('blog/think-online','Think Online','2010-04-14 20:00:18','2010-04-14 21:18:51','h1. Think Online\r\n\r\nZilele acestea va avea loc \'Think Online\':http://thinkonline.ro/, un proiect dedicat tinerilor interesaţi de mediul de afaceri online. Pentru că aveţi cunoştinţe solide de algoritmică şi sunteţi programatori talentaţi, ne-am gândit că v-ar ajuta să aruncaţi un ochi şi la partea de business din domeniu.\r\n\r\n&nbsp;\r\nIată mesajul organizatorilor:\r\n\r\n&nbsp;\r\n_Business Club te invită în perioada 19-23 Aprilie să participi la proiectul Think Online. Într-un moment critic al economiei, domeniul afacerilor pe Internet devine unul din ce în ce mai atrăgător pentru antreprenori. Think Online, cel mai nou proiect marca Business Club, este o şcoală de antreprenoriat care va pregăti un număr de studenţi pentru a îşi deschide o afacere on-line. Ne adresăm studenţilor sau masteranzilor care sunt interesaţi de domeniul acesta, care şi-au deschis o afacere/site sau care au de gând să facă acest lucru în viitorul apropriat. Studii de caz, workshop-uri, simulări de management, networking şi un concurs inedit de idei, totul într-o atmosferă plăcută şi optimă pentru a genera idei de succes. Proiectul va avea loc la Bucharest Hubb, primul club de work&fun din România dedicat antreprenorilor online._\r\n\r\n_Participând la eveniment, vei avea ocazia să întâlneşti oameni interesaţi de afaceri online, să îţi formezi o echipă şi să creezi un plan de afaceri sub îndrumarea celor mai de succes antreprenori. Vei cunoaşte investitori, vei face networking, vei învăţa de la oameni care au o experienţă bogată în start-up-uri. Vei invăţa cum să prezinţi un pitch unui investitor şi vei primi feedback. Dar, cel mai important, dacă planul de afaceri pe care îl vei dezvolta în cadrul proiectului va fi unul atractiv, vei avea ocazia să primeşti finanţare de la un investitor important._\r\n\r\n_Şi nu uita, la sfârşitul proiectului, după aproximativ o lună, cei mai buni participanţi vor avea ocazia să participe la un teambuilding alături de o parte din speakerii evenimentului pentru a îi cunoaşte mai bine, a îşi prezenta ideile şi a lega eventuale colaborări._\r\n\r\n_La proiect, vei avea ocazia să îi cunoşti pe Vlad Stan (SeedMoney), Sergiu Biriş (Trilulilu), Vladimir Oane (UberVU), George Lemnaru (Erepublik), Daniel Enache (Investitor), Marius Deak (GreenPixel) şi mulţi alţii!_\r\n\r\n_Pentru a aplica la proiect accesează site-ul \'www.thinkonline.ro\':http://thinkonline.ro/ ._',3065,'protected',4784,NULL),('arhiva','Arhiva de probleme','2006-11-11 18:59:35','2010-03-24 19:20:28','h1. Arhiva de probleme\r\n\r\nArhiva de probleme infoarena contine peste 1000 de probleme. Vezi si \'clasamentul arhivei\':clasament-arhiva.\r\n\r\nh2. Lista de probleme\r\n\r\n==Tasks(round_id=\"arhiva\" show_numbers=\"true\" score=\"1\" show_ratings=\"true\" show_progress=\"true\") ==\r\n\r\nh2. Ultimele discutii despre arhiva\r\n\r\n== SmfTopics(board_id=\"1\" count=\"30\") ==\r\n',3146,'protected',NULL,NULL),('runda/concurs.info','concurs.info','2010-04-20 17:33:28','2010-04-20 17:33:28','h1. == roundparam(round_id=\"concurs.info\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"concurs.info\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"concurs.info\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"concurs.info\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"concurs.info\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/concurs.info/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"concurs.info\" score=\"1\")==',10701,'round: concurs.info',NULL,NULL),('utilizator/mathboy','Dragos','2008-12-24 18:43:37','2010-04-23 19:00:47','h2. Despre mine\r\n \r\n\r\n* Elev in clasa a X-a la Colegiul National \"Unirea\" Focsani.\r\n* Lucrez pe Infoarena din Ianuarie 2009.\r\n \r\n\r\n\r\nh2. Distinctii primite\r\n\r\n\r\n* The site could be temporarily unavailable or too busy. Try again in a few moments.\r\n\r\nh2. Prieteni pe infoarena\r\n \r\n\r\n* ==user(user=\"cosmin79\" type=\"tiny\")==\r\n* ==user(user=\"bogdanhm999\" type=\"tiny\")==\r\n* ==user(user=\"klamathix\" type=\"tiny\")== \r\n* ==user(user=\"Florian\" type=\"tiny\")==\r\n* ==user(user=\"Omega91\" type=\"tiny\")== \r\n* ==user(user=\"Protoman\" type=\"tiny\")==\r\n* ==user(user=\"blasterz\" type=\"tiny\")==\r\n* ==user(user=\"mishu91\" type=\"tiny\")==\r\n* ==user(user=\"robytzza\" type=\"tiny\")==\r\n* ==user(user=\"doru.nitu\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n \r\n',9232,'public',NULL,NULL);
+INSERT INTO `ia_textblock_revision` VALUES ('planificare/sedinta-20091126','Ședință 2009-11-03','2009-11-23 14:30:08','2009-11-23 14:30:08','h1. Şedinţă 2009-11-03\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Marti* la ora *18^00^* la ICHB.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==user(user=\"pauldb\" type=\"tiny\")== \r\n* ==user(user=\"gcosmin\" type=\"tiny\")==\r\n* ==user(user=\"Prostu\" type=\"tiny\")==\r\n* ==user(user=\"svalentin\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")== (ajung la 18:20)\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20091023 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| Algoritmiada 2010 | ==user(user=\"pauldb\" type=\"tiny\")== |\r\n| OKRs si planuri pentru urmatorul an scolar | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Evaluator nou | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n| Sala sedinta | ==user(user=\"gcosmin\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n* Algoritmiada 2010:\r\n** Contractul de sponsorizare \r\n** Proiecte de finantari\r\n** Comisie?\r\n** Mapa\r\n** Alti sponsori?\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* **Cosmin si Paul** reorganizeaza mapa si **Vali** face design.\r\n* **Cosmin** vorbeste cu Cristi despre carduri la banca. %{color:red}(done)%\r\n* **Cosmin** scrie newsletter. %{color:red}(done)%\r\n* **Vali** face testing pe masina virtuala.\r\n* **Cosmin** vorbeste cu Cristina despre comunicat de presa.\r\n* **Vali** vorbeste cu Vlad Posea despre jailrun java.\r\n* **Bogdan** scrie retry loop pentru eval. %{color:red}(done)%\r\n* **Bogdan** scrie IAP pentru tagging.\r\n* **Bogdan** deschide thread cu poll pe forum sa stabilim urmatorul coding camp.\r\n* **Paul** pune pe grup linkurile de la proiectele de finantare guvernamentale. %{color:red}(done)%\r\n* **Cosmin, Paul si Prostu** se ocupa de proiectele de finantare.\r\n* **Cosmin** vorbeste cu Mircea, Cristi, Silviu si Cosmin sa bage spam la studenti cu Algoritmiada. %{color:red}(done)%\r\n* **Se scrie** text pentru poster si spam pe forumuri.\r\n* **Paul** lanseaza Algorimiada 2010. %{color:red}(done)%\r\n* **Prostu** vorbeste la Unibuc despre sala.\r\n\r\nh2(#notite). Notite\r\n\r\n* **Cosmin** deconteaza mancare pentru sedinta asta.\r\n',1792,'protected',NULL,NULL),('algoritmiada-2010/runda-1','Algoritmiada 2010 - Runda 1','2009-10-25 16:37:51','2009-11-21 14:20:53','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Algoritmiada 2010, Runda 1\r\n\r\n(htabs)*(active) \'Despre...\':algoritmiada-2010/runda-1 \r\n* \'Clasele 5-8\':algoritmiada-2010/runda-1/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-1/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-1/5-8 \r\n\r\nRunda va incepe *Duminica 22 noiembrie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-1/studenti\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':algoritmiada-2010/runda-1/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-1/studenti\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==User(user=\"prostu\" type=\"tiny\")==\r\n* ==User(user=\"ditzoneC\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"marius\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica sau tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/algoritmiada-2009/footer\")==',1792,'protected',NULL,NULL),('algoritmiada-2010/runda-1/solutii/kss','Solutie Kss','2009-11-21 17:44:35','2009-11-22 21:08:55','h1(#kss). \'Kss\':problema/kss\r\n\r\nh2. Aceasta pagina trebuie sa ramana private pana la sfarsitul rundei!',1792,'public',NULL,NULL),('algoritmiada-2010/runda-1/solutii/kss','Solutie Kss','2009-11-21 17:44:35','2009-11-23 16:06:54','h1(#kss). \'Kss\':problema/kss\r\n\r\nPentru a rezolva aceasta problema vom incerca o abordare de genul urmator. Daca am putea raspunde la intrebarea: \"Avand un prefix oarecare, cate subsiruri distincte incep cu acest prefix?\", putem incerca sa cautam fiecare litera pe rand din solutie pana cand gasim intregul sir cerut. Construim o dinamica $din[ i ]$ = numarul de subsiruri distincte care incep de pe pozitia $i$ si contin litera de pe pozitia $i$. Ca sa rezolvam aceasta dinamica mai intai definim $next[c][i]$ = prima pozitie dupa $i$ pe care apare caracterul $c$ (daca $c$ apare fix pe pozitia $i$ atunci $next[ c ][ i ]$ = $i$). Vom calcula dinamica de la pozitia $N$ spre pozitia $1$, iar recurenta este: $din[ i ]$ = $1$ + suma dupa $c = a,z$ din $din[ next[ c ][ i + 1 ] ]$. Luam doar prima aparatie a fiecarui caracter pentru ca subsirurile sunt distincte dupa valoare, si nu dupa pozitiile pe care apar caracterele dar si cazul cand sirul contine doar caracterul curent. Avand aceasta dinamica putem incepe sa cautam solutia, pentru ca putem raspunde la intrebarea intiala astfel: daca avem un prefix $p$, il potrivim ca subsir peste sirul $S$ astfel incat astfel incat ultimul caracter al lui $p$ apare cat mai repede in $S$ (de exemplu pentru $p = a b$ si $S = c a b b$ vom potrivi $c **a b** b$ si nu $c **a** b **b**$. Fie $q$ aceasta potitie a ultimul caracter din $p$. Numarul de subsiruri care incep cu acest prefix $p$ este din[ q ] si se observa usor de ce. \r\n\r\nIn continuare voi explica mai detaliat cum gasim propriu-zis solutia. Dorim sa gasim al $K$-lea subsir. Sa presupunem mai intai ca sirul nostru incepe cu litera $a$. Determinam acel $q$ (am explicat mai sus ce reprezinta). Daca cumva $din[q]$ < $K$ atunci ca solutia nu va incepe cu $a$ ci cu o litera mai mare (lexicografic) pentru ca nu sunt suficiente subsiruri care incep cu $a$. Scadem din $K$, $din[q]$+1 si incercam urmatoarea litera $b$ pentru ca aplicam acelasi rationament (incercam sa gasim al $K-din[q]$-lea subsir care nu incepe cu $a$ ). Cand $din[q]$ >= $K$ inseamna ca litera curenta este cea buna si atunci trebuie sa gasim urmatoarea litera (la acest pas trebuie sa scadem $1$ din $K$ pentru ca sirul care se termina fix cu litera asta apare lexicografic inaintea celor ce vor urma, mai lungi). Pentru urmatoarea litera aplicam acelasi rationament decat ca trebuie sa avem grija ca acum inceputul solutiei este un prefix si nu doar o litera. Ne oprim atunci cand $K$-ul ramas devine $0$ (adica tocmai am pus ultima litera).\r\n\r\nSolutia aceasta are o complexitate $N$ * $sigma$ pe fiecare test ( $sigma$ este numarul de caractere din alfabet).',2038,'public',NULL,NULL),('algoritmiada-2010/runda-1/solutii/kss','Solutie Kss','2009-11-21 17:44:35','2009-11-23 16:10:51','h1(#kss). \'Kss\':problema/kss\r\n\r\nPentru a rezolva aceasta problema vom incerca o abordare de genul urmator. Daca am putea raspunde la intrebarea: \"Avand un prefix oarecare, cate subsiruri distincte incep cu acest prefix?\", putem incerca sa cautam fiecare litera pe rand din solutie pana cand gasim intregul sir cerut. Construim o dinamica $din[ i ]$ = numarul de subsiruri distincte care incep de pe pozitia $i$ si contin litera de pe pozitia $i$. Ca sa rezolvam aceasta dinamica mai intai definim $next[ c ][ i ]$ = prima pozitie dupa $i$ pe care apare caracterul $c$ (daca $c$ apare fix pe pozitia $i$ atunci $next[ c ][ i ]$ = $i$). Vom calcula dinamica de la pozitia $N$ spre pozitia $1$, iar recurenta este: $din[ i ]$ = $1$ + suma dupa $c = a,z$ din $din[ next[ c ][ i + 1 ] ]$. Luam doar prima aparatie a fiecarui caracter pentru ca subsirurile sunt distincte dupa valoare, si nu dupa pozitiile pe care apar caracterele in sirul initial; luam in calcul si cazul cand subsirul contine doar caracterul curent. Avand aceasta dinamica putem incepe sa cautam solutia, pentru ca putem raspunde la intrebarea intiala astfel: daca avem un prefix $p$, il potrivim ca subsir peste sirul $S$ astfel incat ultimul caracter al lui $p$ apare cat mai repede in $S$ (de exemplu pentru $p = a b$ si $S = c a b b$ vom potrivi $c **a b** b$ si nu $c **a** b **b**$ ). Fie $q$ aceasta potitie a ultimul caracter din $p$. Numarul de subsiruri care incep cu acest prefix $p$ este din[ q ] si se observa usor de ce. \r\n\r\nIn continuare voi explica mai detaliat cum gasim propriu-zis solutia. Dorim sa gasim al $K$-lea subsir. Sa presupunem mai intai ca sirul nostru incepe cu litera $a$. Determinam acel $q$ (am explicat mai sus ce reprezinta). Daca cumva $din[q]$ < $K$ atunci inseamna ca solutia nu va incepe cu $a$ ci cu o litera mai mare (lexicografic) pentru ca nu sunt suficiente subsiruri care incep cu $a$. Scadem din $K$, $din[q]$ si incercam urmatoarea litera $b$ pentru ca aplicam acelasi rationament (incercam sa gasim al $K-din[q]$-lea subsir care nu incepe cu $a$ ). Cand $din[q]$ >= $K$ inseamna ca litera curenta este cea buna si atunci trebuie sa gasim urmatoarea (la acest pas trebuie sa scadem $1$ din $K$ pentru ca sirul care se termina fix cu litera asta apare lexicografic inaintea celor ce vor urma, mai lungi). Pentru urmatoarea litera aplicam acelasi rationament decat ca trebuie sa avem grija ca acum inceputul solutiei este un prefix si nu doar o litera. Ne oprim atunci cand $K$-ul ramas devine $0$ (adica tocmai am pus ultima litera).\r\n\r\nSolutia aceasta are o complexitate $N$ * $sigma$ pe fiecare test ( $sigma$ este numarul de caractere din alfabet).',2038,'public',NULL,NULL),('planificare/sedinta-20091126','Ședință 2009-11-26','2009-11-23 14:30:08','2009-11-23 16:21:19','h1. Şedinţă 2009-11-26\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Joi* la ora *?* la ?.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20091103 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Algoritmiada Runda 2 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Coding Camp | |\r\n| Evaluator nou | |\r\n| Sala sedinta | |\r\n\r\nh2. Detalii\r\n\r\n* &hellip;\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* &hellip;\r\n\r\nh2(#notite). Notite\r\n\r\n* &hellip;\r\n',2038,'protected',NULL,NULL),('planificare/sedinta-20091126','Ședință 2009-11-26','2009-11-23 14:30:08','2009-11-23 16:33:46','h1. Şedinţă 2009-11-26\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Joi* la ora *?* la ?.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"stef2n\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20091103 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Algoritmiada Runda 2 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Coding Camp | ? |\r\n| Evaluator nou | ? |\r\n| Sala sedinta | ? |\r\n\r\nh2. Detalii\r\n\r\n* &hellip;\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* &hellip;\r\n\r\nh2(#notite). Notite\r\n\r\n* &hellip;\r\n',2044,'protected',NULL,NULL),('implica-te','Implica-te!','2007-03-09 23:39:36','2008-11-27 00:17:58','h1. Fii un bun _infoarenaut_! Implica-te!\r\n\r\n_infoarena_ este un site de pregatire la informatica dezvoltat in intregime de catre utilizatorii sai - comunitatea _infoarena_. Ne-am straduit sa concepem site-ul in asa fel incat fiecare utilizator sa poata contribui la dezvoltarea lui. Implica-te in dezvoltarea proiectului _infoarena_! Ofera un exemplu celorlalti! Mii de elevi si studenti iti vor multumi iar unii iti vor urma exemplul.\r\n\r\nh2. De ce m-as baga?\r\n\r\n* Efortul tau va atinge mii de elevi si studenti din Romania.\r\n* Te faci cunoscut. Iti acordam credit pentru contributia ta.\r\n* O actiune \'_pro bono publico_\':http://en.wikipedia.org/wiki/Pro_bono in plus pe CV-ul tau, in special daca aplici la universitati din afara.\r\n* Te promovam in \'echipa infoarena\':echipa-infoarena dupa un efort lung si sustinut.\r\n* Iti facem cinste cu suc si bere atunci cand ne vedem la concursuri. Pe bune!\r\n\r\nh2. Cum ma pot implica?\r\n\r\nMai jos am scris niste proiecte in care avem nevoie de ajutorul comunitatii. Pentru fiecare proiect de comunitate avem o pagina cu detalii despre cum poti sa ajuti si mai multe informatii de contact. Te-ar putea interesa sa citesti si paginile noastre de \'planificare\':planificare, unde se coordoneaza activitatile echipei intr-un mod public.\r\n\r\nh2. Proiecte infoarena\r\n\r\n|_. Proiect |_. Coordonator de proiect |\r\n| \'*Arhiva educationala!*\':implica-te/arhiva-educationala\r\nO arhiva cu scop exclusiv educational. Spre deosebire de problemele de concurs care imbina mai multe tehnici de programare, problemele din aceasta arhiva sunt aplicatii imediate ale unor algoritmi cunoscuti. Problemele vor avea sursele si testele publice, vor avea indicatii si diferite link-uri catre articole sau probleme similare.| ==user(user=\"filipb\" type=\"tiny\")==, ==user(user=\"PaulDB\" type=\"tiny\")==|\r\n| \'*Extinde arhiva!*\':implica-te/extinde-arhiva\r\nAm obtinut permisiunea multor autori de a importa problemele lor in arhiva. Ajuta-ne sa le punem la dispozitia comunitatii! Mii de useri iti vor multumi pentru noile provocari! | ==user(user=\"ditzonec\" type=\"tiny\")== |\r\n| \'*Scrie articole!*\':implica-te/scrie-articole\r\n_infoarena_ este un site bazat pe \'wiki\':documentatie/wiki, mare parte din continut fiind complet editabil de oricine, astfel incurajand colaborarea intre membrii comuntatii. Si tu poti scrie articole noi sau imbunatati articole noi in orice moment. | ==user(user=\"stef2n\" type=\"tiny\")== |\r\n| \'*Imbunatateste testele problemelor!*\':implica-te/imbunatatire-teste\r\nUnele probleme din arhiva nu au teste suficient de puternice incat sa departajeze intre solutii eficiente si mai putin eficiente. Gaseste teste mai bune! | ==user(user=\"ditzonec\" type=\"tiny\")== |\r\n| \'*Codeaza alaturi de noi!*\':development\r\nStii sau vrei sa inveti tehnologii web? Site-ul si evaluatorul _infoarena_ sunt dezvoltate open-source. Codul nostru e public. | ==user(user=\"domino\" type=\"tiny\")== |',1,'protected',NULL,NULL),('planificare/sedinta-20091126','Ședință 2009-11-26','2009-11-23 14:30:08','2009-11-26 18:17:07','h1. Şedinţă 2009-11-26\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Joi* la ora *19:00* la Cafepedia Romana.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"stef2n\" type=\"tiny\")==\r\n* ==User(user=\"prostu\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"victorsb\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20091103 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Algoritmiada Runda 2 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Probleme cu site-ul | ? |\r\n| Coding Camp | ==User(user=\"bogdan2412\" type=\"tiny\")== |\r\n| Evaluator nou | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Sala sedinta | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n* &hellip;\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Vali executa design la mapa.\r\n* Cosmin vorbeste cu Cristi de cardul lui.\r\n* Vali face testing pe masina virtuala.\r\n* Vali vorbeste cu Vlad Posea despre jailrun java.\r\n* Facem runda 2 la Algoritmiada pe 20 decembrie.\r\n* S-au stabilit sefi de grupe: Prostu (gimnaziu), Stefan (9-10), Bogdan (11-12).\r\n* Paul scrie blog post pentru runda 1.\r\n* Cosmin vorbeste cu Astronomy despre Amazon.\r\n* Paul vorbeste cu Cristina despre bilant Infoarena.\r\n* Stefan cauta paginile despre noi care sunt outdated.\r\n* Bogdan rezolva problemele cu reviziile vechi (fara securitate).\r\n* Facem coding camp pe 12-13 decembrie.\r\n\r\nh2(#notite). Notite\r\n\r\n* Prostu inspecteaza diff-ul din Linux.\r\n',2044,'protected',NULL,NULL),('planificare/sedinta-20091126','Ședință 2009-11-26','2009-11-23 14:30:08','2009-11-26 19:10:36','h1. Şedinţă 2009-11-26\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Joi* la ora *19:00* la Cafepedia Romana.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"stef2n\" type=\"tiny\")==\r\n* ==User(user=\"prostu\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"victorsb\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20091103 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Algoritmiada Runda 2 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Probleme cu site-ul | ? |\r\n| Coding Camp | ==User(user=\"bogdan2412\" type=\"tiny\")== |\r\n| Evaluator nou | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Sala sedinta | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| IAP #15: Tagging | ==User(user=\"bogdan2412\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n* &hellip;\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* Vali executa design la mapa.\r\n* Cosmin vorbeste cu Cristi de cardul lui.\r\n* Vali face testing pe masina virtuala.\r\n* Vali vorbeste cu Vlad Posea despre jailrun java.\r\n* Facem runda 2 la Algoritmiada pe 20 decembrie.\r\n* S-au stabilit sefi de grupe: Prostu (gimnaziu), Stefan (9-10), Bogdan (11-12).\r\n* Paul scrie blog post pentru runda 1.\r\n* Cosmin vorbeste cu Astronomy despre Amazon.\r\n* Paul vorbeste cu Cristina despre bilant Infoarena.\r\n* Stefan cauta paginile despre noi care sunt outdated.\r\n* Bogdan rezolva problemele cu reviziile vechi (fara securitate).\r\n* Facem coding camp pe 12-13 decembrie.\r\n* Cosmin cauta loc pentru sedinta si coding camp.\r\n* Cosmin vorbeste cu Vali de evaluator.\r\n* Bogdan si Cosmin cer drepturi lui Cristi pentru Google Analytics si Google Apps.\r\n* Cosmin vorbeste cu Cristi de newsletter@infoarena.ro si no-reply@infoarena.\r\n* Cosmin face IAP pentru dificultate.\r\n\r\nh2(#notite). Notite\r\n\r\n* Prostu inspecteaza diff-ul din Linux.\r\n',2044,'protected',NULL,NULL),('utilizator/cezarmocan','Cezar','2006-11-24 20:59:14','2009-09-27 11:32:28','h2. Despre mine\r\n\r\n* Elev in clasa a 10-a la ICHB\r\n* Pana in clasa a 8-a am studiat la Colegiul National Emil Racovita Cluj-Napoca, iar din clasa a 9-a invat la Liceul International de Informatica Bucuresti. \r\n* Am inceput sa fac programare din clasa a 3-a si intr-a 4-a am luat mentiune la nationala\r\n* Lucrez pe infoarena de prin clasa a 5-a, si pot spune ca e una din principalele mele surse de pregatire\r\n* Imi place sa citesc si sa ascult muzica buna (rock si nu numai)\r\n* Practic cu placere sporturi ca tenis, inot, ciclism, fotbal, ski, patinaj\r\n\r\n\r\nh2. Distinctii primite\r\n\r\nh3. Clasa a IV-a\r\n\r\n* Mentiune la ONI Buzau 2004 la clasa a V-a\r\n\r\nh3. Clasa a V-a\r\n\r\n* Locul 1 la ONI Galati 2005\r\n* Locul 2 la Concursul Interjudetean de Matematica Grigore Moisil\r\n\r\nh3. Clasa a VI-a\r\n\r\n* Mentiune (locul 4) la ONI Targoviste 2006\r\n* Locul 1 la Concursul Palatelor Copiilor Satu Mare 2006\r\n* Locul 1 la PACO Bucuresti 2006\r\n* Locul 5 la finala preONI 2006\r\n* Participare la finala .Campion 2006\r\n* Locul 1 la Concursul Interjudetean de Matematica Dumitru Tiganetea\r\n\r\nh3. Clasa a VII-a\r\n\r\n* Locul 1 la Grigore Moisil 2007 Oradea\r\n* Locul 1 la ONI 2007 Cluj-Napoca\r\n* Locul 4 la Finala .Campion 2007\r\n* Calificare la Finala preONI 2007\r\n* Locul 5 cu echipa scolii la concursul ACSL 2007 - Houston\r\n* Mentiune la JBOI 2007 (locul 13, primul sub bronz)\r\n* Participare la Olimpiada Nationala de Matematica\r\n* Calificare la faza nationala a concursului de matematica \"Cangurul\"\r\n\r\nh3. Clasa a VIII-a\r\n\r\n* Locul 1 la concursul \"Stelele Informaticii\" 2007 la clasa a 9-a (locul 3 la general)\r\n* Locul 9 (mentiune) la ONIGim Bacau 2008\r\n* Locul 1 la Grigore Moisil 2008 Cluj-Napoca\r\n* Locul 1 la finala preONI 2008 cls. 5-8\r\n* Locul 1 la finala .Campion 2008 grupa S\r\n* Locul 5 cu echipa scolii la concursul ACSL 2008 - Baltimore\r\n* Locul 1 (cu punctaj maxim) la JBOI 2008 by NET\r\n* Locul 1 la Concursul Palatelor Copiilor Satu Mare 2008\r\n* Calificare la faza nationala a concursului de matematica \"Cangurul\"\r\n\r\nh3. Clasa a IX-a\r\n\r\n* Calificare in finala concursului Topcoder Highschool Tournament 2009\r\n* Locul 2 la concursul \"Stelele Informaticii 2009\" \r\n* Premiul 3 (locul 4) la ONI Galati 2009\r\n* Locul 3 la finala Algoritmiada 2009\r\n* Calificat la finala .Campion 2009 la grupele Small si Medium\r\n* Locul 3 la CCEX 2009\r\n* Primul clasat la loturile online\r\n\r\nh4. Toate aceste rezultate se datoreaza pregatirii temeinice cu profesorii mei de pana acum: Negreanu-Maior Lucia, Negreanu-Maior Adrian, Ilea Lucian, Ali Yuksel, Baltescu Paul, Ganceanu Silviu, Grigorean Andrei.\r\nTot respectul si consideratia pentru acesti oameni deosebiti.\r\n\r\n\r\nh2. Profesori pe infoarena\r\n\r\n ==User(user=\"pauldb\" type=\"tiny\")==\r\n ==User(user=\"silviug\" type=\"tiny\")== \r\n ==User(user=\"wefgef\" type=\"tiny\")== \r\n ==User(user=\"gcosmin\" type=\"tiny\")==\r\n ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n ==User(user=\"raduzer\" type=\"tiny\")==\r\n ==User(user=\"savim\" type=\"tiny\")==\r\n ==User(user=\"GavrilaVlad\" type=\"tiny\")==\r\n ==User(user=\"tvlad\" type=\"tiny\")==\r\n ==User(user=\"toni2007\" type=\"tiny\")==\r\n ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n ==User(user=\"GheorgheMihai\" type=\"tiny\")==\r\n ==User(user=\"mariusdrg\" type=\"tiny\")==\r\n ==User(user=\"devilkind\" type=\"tiny\")==\r\n ==User(user=\"alexthero\" type=\"tiny\")==\r\n ==User(user=\"protoman\" type=\"tiny\")==\r\n ==User(user=\"radu_voroneanu\" type=\"tiny\")==\r\n ==User(user=\"andrei.12\" type=\"tiny\")==\r\n ==User(user=\"gabitzish1\" type=\"tiny\")==\r\n',1430,'protected',NULL,NULL),('utilizator/mathboy','Rotaru Dragos Alin','2008-12-24 18:43:37','2009-11-18 19:17:12','h2. Despre mine\r\n\r\n* Elev in clasa a X-a D, Matematica-Informatica, Informatica Intensiv la Colegiul National Unirea Focsani\r\n* Contact: dragos_mathboy@yahoo.com\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n\r\n==user(user=\"Florian\" type=\"normal\")==\r\n\r\n==user(user=\"cosmin79\" type=\"normal\")==\r\n\r\n==user(user=\"klamathix\" type=\"normal\")==\r\n\r\n==user(user=\"DraStiK\" type=\"normal\")==\r\n\r\n==user(user=\"antoanela\" type=\"normal\")==\r\n\r\n==user(user=\"Protoman\" type=\"normal\")==\r\n\r\n==user(user=\"Omega91\" type=\"normal\")==\r\n\r\n==user(user=\"lucianvn\" type=\"normal\")==\r\n\r\n==user(user=\"bogdanhm999\" type=\"normal\")==\r\n\r\n==user(user=\"drag0sh\" type=\"normal\")==\r\n\r\n',9232,'public',NULL,NULL),('2-sat','Problema 2-satisfiabilității','2008-12-09 15:55:03','2009-04-18 16:45:26','h1. Problema 2-satisfiabilităţii\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"marius\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\n(toc){width: 30em}*{text-align:center} *Conţinut:*\r\n* {\'Introducere\':2-sat#introducere}\r\n* {\'Forme normale ale formulelor logice\':2-sat#forme-normale}\r\n* {\'SAT, 3-SAT, 2-SAT\':2-sat#overview-sat}\r\n* {\'Soluţii pentru 2-SAT\':2-sat#solutii-2-sat}\r\n** {\'Soluţie $O(M * 2^N^)$\':2-sat#solutie-1}\r\n** {\'Soluţie $O(N * M)$\':2-sat#solutie-2}\r\n** {\'Soluţie $O(N^2^)$\':2-sat#solutie-3}\r\n** {\'Soluţie $O(M + N)$\':2-sat#solutie-4}\r\n* {\'Aplicaţii\':2-sat#aplicatii}\r\n** {\'Party &#40;preONI 2003/2004&#41;\':2-sat#party}\r\n** {\'Cigraf\':2-sat#cigraf}\r\n** {\'Orpath &#40;Olimpiadă Rusia&#41;\':2-sat#orpath}\r\n** {\'Aladdin &#40;Bursele Agora 2005/2006, Runda 1&#41;\':2-sat#aladdin}\r\n* {\'Probleme propuse\':2-sat#probleme}\r\n* {\'Bibliografie\':2-sat#bibliografie}\r\n\r\nh2(#introducere). Introducere\r\n\r\nProblema satisfiabilităţii, notată prescurtat cu $SAT$, cere determinarea existenţei pentru o formulă booleană <tex> \\phi </tex> a unei atribuiri satisfiabile. O formulă booleană <tex> \\phi </tex> este compusă din $variabile$ logice <tex> (x_{1}, x_{2}, ...) </tex>, $operatori$ logici ( <tex> \\wedge </tex> şi,  <tex> \\vee </tex> sau, <tex> \\sim </tex> non, <tex> \\rightarrow </tex> implicaţie, <tex> \\leftrightarrow </tex> echivalenţă), şi $paranteze$. O atribuire de valori booleene pentru variabilele acestei expresii se numeşte $atribuire satisfiabilă$ dacă evaluarea expresiei după atribuirea valorilor dă ca rezultat valoarea de adevăr $adevărat$. De acum încolo vom folosi pentru simplitate valorile <tex> 1 </tex> şi <tex> 0 </tex> în loc de $adevărat$ şi $fals$.\r\n\r\nUn exemplu de formulă ar fi <tex> \\phi = ((x_{1} \\rightarrow x_{2}) \\vee \\sim((\\sim x_{1} \\leftrightarrow x_{3}) \\vee x_{4})) \\wedge \\sim x_{2} </tex>. Aceasta are atribuirea satisfiabilă <tex> \\langle x_{1} = 0, x_{2} = 0, x_{3} = 1, x_{4} = 1 \\rangle </tex> pentru că <tex> \\phi = ((0 \\rightarrow 0) \\vee \\sim((\\sim 0 \\leftrightarrow 1) \\vee 1)) \\wedge \\sim 0 = (1 \\vee \\sim (1 \\vee 1)) \\wedge 1 = (1 \\vee 0) \\wedge 1 = 1</tex>. \r\n\r\nh2(#forme-normale). Forme normale ale formulelor logice\r\n\r\nOrice formulă booleană poate fi transformată în două forme:\r\n\r\n* $Forma normal conjunctivă$ în care expresia este exprimată ca o conjuncţie de propoziţii, iar fiecare propoziţie este formată dintr-o disjuncţie de $literali$. Un $literal$ este o variabilă care poate fi sau nu negată. Un exemplu de expresie în forma normal conjunctivă ar fi: <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) \\wedge (x_{3} \\vee x_{2} \\vee x_{4}) \\wedge (\\sim x_{1} \\vee \\sim x_{3} \\vee \\sim x_{4}) </tex> care are pe <tex> (x_{1} \\vee \\sim x_{1} \\vee \\sim x_{2}) </tex> ca primă propoziţie cu literalii <tex> x_{1} </tex>, <tex> \\sim x_{1} </tex>, <tex> \\sim x_{2} </tex>.\r\n\r\n* $Forma normal disjunctivă$ este formată ca o disjuncţie de propoziţii, fiecare dintre aceste propoziţii fiind o conjuncţie de literali. Un exemplu de o asemenea formulă ar fi următoarea: <tex> (x_{1} \\wedge x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge x_{3}) \\vee (x_{1} \\wedge \\sim x_{2} \\wedge \\sim x_{3}) \\vee (\\sim x_{1} \\wedge x_{2} \\wedge \\sim x_{2}) </tex>.\r\n\r\nh2(#overview-sat). SAT, 3-SAT, 2-SAT\r\n\r\nProblema $SAT$ este $NP-completă$. De fapt, este prima problemă $NP-completă$ găsită. Stephen Cook a demonstrat $NP-completitudinea$ ei în 1971. Pe vremea aceea nu se ştia nici măcar că problemele $NP-complete$ există. Această problemă rămâne $NP-completă$ chiar dacă restricţionăm expresiile la unele care în forma normal conjunctivă au doar trei literali. Problema satisfiabilităţii pentru asemenea expresii se numeşte $3-SAT$, şi multe probleme pot fi demonstrate a fi $NP-complete$ prin reducerea lui $3-SAT$ la problemele respective în timp polinomial. Din fericire, problema $2-SAT$, adică cea pentru care în fiecare propoziţie există doar $2$ literali, se poate rezolva eficient. Restul articolului va prezenta trei metode de rezolvare a problemei $2-SAT$ şi câteva aplicaţii ale acesteia din concursuri de programare.\r\n\r\nh2(#solutii-2-sat). Soluţii pentru 2-SAT\r\n\r\nUn exemplu de problemă $2-SAT$ ar fi satisfiabilitatea formulei <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Această formulă este satisfăcută de valorile <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>. Pentru a satisface întreaga expresie trebuie ca în fiecare propoziţie cel puţin unul din cei doi literali să aibă valoarea de adevăr <tex> 1 </tex>.\r\n\r\nh3(#solutie-1). Soluţie $O(M * 2^N^)$\r\n\r\nO primă metodă de rezolvare ar fi să încercăm toate cele $2^N^$ posibilităţi de atribuire posibilă, dar această metodă are ordinul de complexitate $O(M * 2^N^)$ şi este eficientă doar pentru instanţe mici ale problemei.\r\n\r\nh3(#solutie-2). Soluţie $O(N * M)$\r\n\r\nUrmătoarea soluţie pare trivială, dar găsirea acestui algoritm şi realizarea faptului că el rezolvă corect problema sunt mai grele decât impresia lăsată după citirea ei. Considerăm o propoziţie oarecare cu două variabile $p$ şi $q$, apoi una dintre ele, de exemplu $p$. Îi atribuim literalului în care apare $p$ valoarea $0$. Pentru ca propoziţia respectivă să aibă $1$ valoarea de adevăr, atunci valoarea lui $q$ trebuie fixată. Fixând şi valoarea lui $q$, probabil şi alte propoziţii ce conţin literalul $q$ vor avea celălalt literal fixat. Propagăm astfel o serie de schimbări. După ce toate schimbările forţate au fost făcute, propoziţiile rezultate vor fi de următoarele tipuri: <tex> a \\vee b </tex>, <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex>. Propoziţii de tip <tex> 0 \\vee b </tex> nu pot apărea pentru că toate schimbările forţate au fost deja propagate. Dacă apare o propoziţie <tex> 0 \\vee 0 </tex> atunci alegerea făcută pentru valoarea lui $p$ este greşită. Vom încerca şi alegerea opusă pentru $p$. Dacă ambele duc la o propoziţie de tip <tex> 0 \\vee 0 </tex> atunci expresia nu poate fi satisfăcută. Propoziţiile de forma <tex> 1 \\vee 0 </tex>, <tex> 1 \\vee 1 </tex>, <tex> 1 \\vee b </tex> pot fi ignorate. În acest fel am eliminat cel puţin o variabilă şi o propoziţie din expresie. Dacă expresia iniţială era satisfiabilă, atunci şi expresia din care s-au eliminat câteva propoziţii a rămas satisfiabilă. Continuând pe această idee obţinem un algoritm de complexitate $O(N * M)$, pentru că la fiecare atribuire de valoare pentru o variabilă parcurgem şirul de propoziţii o dată. \r\n\r\nSă vedem cum funcţionează algoritmul pentru expresia: <tex> (x_{1} \\vee \\sim x_{2}) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee x_{2}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. Considerăm propoziţia <tex> (x_{1} \\vee \\sim x_{2}) </tex> şi <tex> \\langle x_{2} = 1 \\rangle </tex>. Astfel, vom obţine mai departe <tex> (x_{1} \\vee 0) \\wedge (\\sim x_{1} \\vee \\sim x_{3}) \\wedge (x_{1} \\vee 1) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{1}) </tex>. În propoziţia <tex> (x_{1} \\vee 0) </tex>, <tex> x_{1} </tex> trebuie să fie egal cu <tex> 1 </tex>. Acum, expresia devine: <tex> (0\\ \\vee \\sim x_{3}) \\wedge (x_{4} \\vee \\sim x_{3}) \\wedge (x_{4} \\vee 0) </tex>. Din propoziţia <tex> (0\\ \\vee \\sim x_{3}) </tex> obţinem <tex> \\langle x_{3} = 0 \\rangle </tex>, iar din <tex> (x_{4} \\vee 0) </tex> obţinem <tex> \\langle x_{4} = 1 \\rangle </tex>. Deci, atribuirea satisfiabilă este <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 0, x_{4} = 1 \\rangle </tex>.\r\n\r\nh3(#solutie-3). Soluţie $O(N^2^)$\r\n\r\nO altă soluţie elegantă se bazează pe o metodă randomizată:\r\n\r\n== code(cpp) |\r\natribuim valori booleene arbitrare variabilelor;\r\ncât timp expresia nu este satisfăcută, execută\r\n    găsim o propoziţie cu valoarea de adevăr 0;\r\n    schimbăm valoarea de adevăr a oricăreia dintre cele două variabile prezente în propoziţie;\r\nsfârşit cât timp\r\n==\r\n\r\nLinia $4$ va face ca acea propoziţie să aibă noua valoare de adevăr <tex> 1 </tex>.\r\n\r\nDe ce ar merge acest algoritm? Să presupunem că există o soluţie a problemei, o notăm cu <tex> S </tex>, iar cu <tex> X </tex> notăm şirul valorilor curente ale variabilelor. Ne uităm la fiecare pas al algoritmului la numărul de variabile care au valori diferite în soluţie faţă de cele din <tex> X </tex> (acest număr de diferenţe între elementele de acelaşi index pentru două şiruri se mai numeşte şi \'distanţă Hamming\':http://en.wikipedia.org/wiki/Hamming_distance între şiruri). Fie această valoare la pasul current $K$. Noi am vrea să avem $K = 0$. Cum va evolua $K$ pe parcursul algoritmului? La un moment dat noi schimbăm valoarea unei variabile luate aleator dintr-o propoziţie nesatisfăcută. Pentru că în <tex> S </tex> propoziţia este satisfăcută, înseamnă că cel puţin una dintre cele două variabile ale propoziţiei are valori diferite în <tex> X </tex> faţă de <tex> S </tex>. Astfel, operaţia făcută de noi are probabilitate de cel puţin $0.5$ să ne aducă mai aproape de soluţie. Vom nota cu <tex> T(i) </tex> numărul probabil de paşi în care un şir <tex> X </tex> aflat la distanţa Hamming egală cu $i$ faţă de <tex> S </tex>, va fi transformat în <tex> S </tex>. Evident:\r\n\r\n<tex> T(0) = 0 </tex>\r\n\r\n<tex> T(i) \\le \\dfrac {T(i + 1) + T(i - 1)}{2} + 1 </tex> pentru $0 < i < N$ ({$N$} e numărul de variabile booleene ale expresiei)\r\n\r\nSe pune semnul de inegalitate pentru că ambele variabile pot avea valori diferite faţă de cele din soluţie, deci schimbarea valorii oricăreia ar putea să ne aducă mai aproape de soluţie.\r\n\r\nDacă toate variabilele diferă de soluţie, orice schimbare ne aduce mai aproape de aceasta:\r\n\r\n<tex> T(N) = T(N - 1) + 1 </tex>\r\n\r\nNe interesează numai limitele superioare, deci folosim doar egalităţi în loc de inegalităţi:\r\n\r\n<tex> X(0) = 0 </tex>, <tex> X(i) = \\dfrac {X(i + 1) + X(i - 1)}{2} + 1 </tex>, <tex> X(N) = X(N - 1) + 1 </tex>\r\n\r\nDacă adunăm toate ecuaţiile obţinem:\r\n\r\n<tex> X(0) + X(1) + ... + X(N) = </tex> <tex> \\dfrac {X(0) + X(1) + 2X(2) + ... + 2X(N - 2) + X(N - 1) + X(N)}{2} + X(N) + N - 1 </tex>\r\n\r\nDe aici avem că <tex> \\dfrac {X(1) + X(N - 1) - X(N)}{2} = N - 1 </tex>, iar din <tex> X(N) = X(N - 1) + 1 </tex> rezultă că <tex> X(1) = 2N - 1 </tex>. Mai departe avem că <tex> X(2) = 4N - 4 </tex> <tex> ... </tex> <tex> X(i) = 2iN - i^2 </tex>, de unde, când <tex> i = N </tex>, avem că <tex> X(N) = N^2 </tex>.\r\n\r\nAstfel, numărul mediu de paşi ai algoritmului este pătratic în numărul $N$ de variabile. Lăsând algoritmul să ruleze de 2-3 ori mai mulţi paşi decât numărul mediu, avem o probabilitate foarte mare să ajungem la rezultat.\r\n\r\nh3(#solutie-4). Soluţie $O(M + N)$\r\n\r\nO a treia soluţie se bazează pe relaţia de implicaţie. Relaţia <tex> \\rightarrow </tex> are următoarea tabelă de adevăr:\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> A \\rightarrow B </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nRelaţia de implicaţie are următoarea semnificaţie: dacă <tex> A </tex> este adevărat atunci şi <tex> B </tex> este adevărat. Scriem tabela expresiei <tex> \\sim A \\vee B </tex> şi observăm că aceasta este egală cu cea a relaţiei de implicaţie.\r\n\r\ntable{width: 90px; text-align: center}. | <tex> A </tex> | <tex> B </tex> | <tex> \\sim A \\vee B </tex>|\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex>  |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex>  |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n\r\nFiecare clauză <tex> A \\vee B </tex> poate fi scrisă ca două implicaţii <tex> \\sim A \\rightarrow B </tex> şi <tex> \\sim B \\rightarrow A </tex>. Realizăm un graf al implicaţiilor. Astfel, nodurile grafului vor fi variabilele <tex> A </tex>, <tex> B </tex> <tex> ... </tex> şi negaţiile lor <tex> \\sim A </tex>, <tex> \\sim B </tex> <tex> ... </tex> iar muchiile acestui graf vor fi implicaţiile echivalente cu propoziţiile din expresie. Deci, dacă expresia are $M$ propoziţii, graful va avea $2M$ muchii. Acestea fiind zise, expresiei <tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) </tex> îi corespunde graful:\r\n\r\np=. !2-sat?Graf.png!\r\n\r\nDacă avem <tex> A \\longrightarrow B </tex> o muchie în graful nostru şi literalul <tex> A </tex> este adevărat, atunci şi literalul <tex> B </tex> trebuie să fie adevărat pentru ca propoziţia reprezentată de muchie să fie satisfăcută. Putem demonstra prin inducţie că dacă există un drum în graf de la literalul <tex> A </tex> la literalul <tex> B </tex>, atunci dacă <tex> A </tex> este adevărat şi <tex> B </tex> trebuie să fie adevărat. Dacă există un drum de la un literal <tex> X </tex> la <tex> \\sim X </tex>, precum şi un drum invers, atunci nu va exista soluţie pentru că nu putem seta în acelaşi timp o variabilă şi valoarea ei negată la valoarea adevărat. De aici rezultă că dacă în graful asociat expresiei există o variabilă <tex> X </tex> în aceeaşi componentă tare conexă cu <tex> \\sim X </tex> atunci instanţa problemei satisfiabilităţii nu poate fi satisfăcută. Dacă nu există o asemenea variabilă, vom vedea în continuare cum putem rezolva problema. Întâi, facem observaţia că dacă în graf există muchia <tex> A \\longrightarrow B </tex> atunci există şi muchia <tex> \\sim B \\longrightarrow \\sim A </tex>. Astfel, dacă există un drum de la <tex> A </tex> la <tex> B </tex> în graf, aplicând proprietatea menţionată pentru fiecare muchie a drumului, vom găsi un drum de la <tex> \\sim B </tex> la <tex> \\sim A </tex>. Evident, afirmaţia este valabilă şi reciproc: dacă există drum de la <tex> B </tex> la <tex> A </tex> atunci vom avea un drum de la nodul <tex> \\sim A </tex> la <tex> \\sim B </tex>. Astfel, dacă avem că <tex> A </tex> şi <tex> B </tex> sunt în aceeaşi componentă tare conexă atunci şi nodurile <tex> \\sim A </tex> şi <tex> \\sim B </tex> sunt în aceeaşi componentă tare conexă. Deci, dacă nu există doi literali <tex> X </tex> şi <tex> \\sim X </tex> în aceeaşi componentă tare conexă, putem să împărţim graful în componente tare conexe şi să împerechem componentele câte două astfel ca în fiecare pereche să apară o componentă <tex> U </tex> cu nişte literali şi altă componentă <tex> \\sim U </tex> cu aceiaşi literali negaţi. Pentru a găsi o soluţie vom determina mai întâi componentele tare conexe ale grafului. Apoi putem contracta fiecare componentă într-un nod. Graful obţinut va fi aciclic. Alegem un nod <tex> u </tex> în care nu intră nicio muchie (un asemenea nod trebuie să existe pentru a nu exista cicluri). Din considerente de simetrie, din nodul lui pereche <tex> \\sim u </tex> nu va ieşi nicio muchie. Literalilor componentei <tex> U </tex> putem să le dăm valoarea de adevăr <tex> 0 </tex>, iar literalilor din componenta pereche <tex> \\sim U </tex>  putem să le dăm valoarea de adevăr <tex> 1 </tex>. Această alegere nu impune restricţii asupra celorlalţi literali şi elimină câteva variabile din problemă. Repetarea recursivă a acestui pas pe graful rămas va duce la rezolvarea problemei. Determinarea componentelor tare conexe se poate face în complexitatea $O(N + M)$. Pentru a vedea acest algoritm puteţi consulta \'secţiunea $23.5$\':http://zhuzeyuan.hp.infoseek.co.jp/ita/chap23.htm din {\'[1]\':2-sat#bibliografie}. Iar eliminarea nodurilor de care vorbeam mai sus se poate face în $O(N + M)$ folosind o sortare topologică.\r\n\r\nSă urmărim cum merge algoritmul nostru pe exemplul de mai sus. Componentele tare conexe sunt următoarele: <tex> \\{A\\} </tex>, <tex> \\{\\sim A\\} </tex>, <tex> \\{B, C, \\sim D\\} </tex>, <tex> \\{\\sim B, \\sim C, D\\} </tex>. În nodul asociat componentei <tex> \\{A\\} </tex> nu intră nicio muchie. Astfel, putem să îi atribuim lui <tex> A </tex> valoarea <tex> 0 </tex>, iar după eliminarea lui <tex> \\{A\\} </tex> şi <tex> \\{\\sim A\\} </tex>în nodul asociat componentei <tex> \\{\\sim B, \\sim C, D\\} </tex> nu intră nicio muchie, deci putem să îi atribuim lui <tex> B </tex> valoarea <tex> 1 </tex>, lui <tex> C </tex> valoarea <tex> 1 </tex> şi lui <tex> D </tex> valoarea <tex> 0 </tex>. Această atribuire este satisfiabilă după cum vedem în continuare:\r\n\r\n<tex> (\\sim A \\vee \\sim B) \\wedge (B \\vee \\sim C) \\wedge (B \\vee C) \\wedge (\\sim B \\vee \\sim D) \\wedge (C \\vee D) = </tex> <tex> (\\sim 0 \\vee \\sim 1) \\wedge (1 \\vee \\sim 1) \\wedge (1 \\vee 1) \\wedge (\\sim 1 \\vee \\sim 0) \\wedge (1 \\vee 0) = </tex> <tex> 1 \\wedge 1 \\wedge 1 \\wedge 1 \\wedge 1 = 1 </tex>\r\n\r\nh2(#aplicatii). Aplicaţii\r\n\r\nRestul articolului va prezenta aplicaţii ale problemei $2-SAT$ din concursurile de programare.\r\n\r\nh2(#party). \'Party\':problema/party (preONI 2003/2004)\r\n\r\nbq. George vrea să îşi organizeze majoratul şi îşi doreşte ca petrecerea să fie de neuitat. Mâncarea, băutura, locaţia şi sonorizarea sunt deja asigurate, mai rămâne problema chemării prietenilor. El şi cu prietenul lui cel mai bun, Lucian, au preferinţe diferite şi pentru a nu se certa au pus la punct o listă de cerinţe care vor trebui să fie îndeplinite astfel încât cheful să se desfăşoare în cele mai bune condiţii! Pentru uşurinţă, prietenii lui George vor fi identificaţi prin numere întregi de la $1$ la $N$ ({$1 ≤ N ≤ 100$}) şi cerinţele în număr de $M$ ({$1 ≤ M ≤ 1.000$}) vor fi de tipurile 0, 1, 2 sau 3. O cerinţă de genul <tex> x \\ y </tex> 0 are semnificaţia că <tex> x </tex> sau <tex> y </tex> trebuie să participe la petrecere; <tex> x \\ y </tex> 1 are semnificaţia că dacă <tex> x </tex> participă nu există nicio restricţie pentru <tex> y </tex>, dar dacă <tex> x </tex> nu participă atunci nici <tex> y </tex> nu participa; <tex> x \\ y </tex> 2 are semnificaţia simetrică cu cerinţa 1; iar cerinţa <tex> x \\ y </tex> 3 are semnificaţia că cel puţin unul dintre <tex> x </tex> şi <tex> y </tex> nu participă la petrecere. Scrieţi un program care să-i ajute pe cei doi să determine care persoane vor fi invitate la petrecere. Se garantează că va fi posibilă întotdeauna organizarea unei petreceri!\r\n\r\nh3. Soluţie\r\n\r\nAceastă problemă este inspirată dintr-o problemă de la $CEOI 2002$ şi este evident că ne cere să determinăm o atribuire satisfiabilă pentru o formulă logică formată ca conjuncţie între cerinţele care se transformă astfel:\r\n\r\n* _cerinţa de tip 0_ corespunde propoziţiei <tex> x \\vee y </tex>;\r\n* _cerinţa de tip 1_ corespunde propoziţiei <tex> x \\vee \\sim y </tex>;\r\n* _cerinţa de tip 2_ corespunde propoziţiei <tex> \\sim x \\vee y </tex>;\r\n* _cerinţa de tip 3_ corespunde propoziţiei <tex> \\sim x \\vee \\sim y </tex>.\r\n\r\nUna din primele două rezolvări ar fi putut soluţiona această problemă, dar problema de la $CEOI$ avea limite mai mari şi pentru rezolvarea ei ar fi trebuit un algoritm de complexitate $O(N + M)$.\r\n\r\nh2(#cigraf). Cigraf\r\n\r\n_Autor: Mugurel Ionuţ Andreica_\r\n\r\nbq. Se dă un graf neorientat cu $N$ ({$1 &le; N &le; 1000$}) noduri şi $M$ ({$0 &le; M &le; N*(N-1)/2$}) muchii. Se doreşte împărţirea nodurilor acestui graf în $2$ mulţimi, <tex> C </tex> şi <tex> I </tex>, având următoarele proprietăţi: fiecare nod face parte din exact una din cele $2$ mulţimi, există muchie între oricare $2$ noduri din mulţimea <tex> C </tex>, nu există nicio muchie între $2$ noduri din mulţimea <tex> I </tex>. Este posibil ca una dintre cele $2$ mulţimi să fie vidă. Soluţia nu este neapărat unică. Numele celor două mulţimi provin de la $clică$ şi $mulţime independentă$. De exemplu, pentru graful de $6$ noduri ce are muchiile <tex> \\{\\{1, 4\\}, \\{4, 6\\}, \\{6, 1\\}, \\{2, 4\\}, \\{2, 6\\}, \\{3, 4\\}, \\{1, 3\\}\\} </tex> o împărţire posibilă ar fi <tex> C = \\{1, 4, 6\\} </tex>, <tex> I = \\{2, 3, 5\\} </tex>.\r\n\r\nh3. Soluţie\r\n\r\nDacă între două noduri există muchie atunci nu pot fi amândouă în mulţimea <tex> I </tex>, iar dacă între două noduri nu există muchie nu pot fi amândouă în mulţimea <tex> C </tex>. Transformăm această problemă într-o instanţă de $2-SAT$ astfel: faptul că nodul <tex> x </tex> aparţine mulţimii <tex> C </tex> îl reprezentăm dându-i lui <tex> x </tex> valoarea <tex> 1 </tex>, iar apartenenţa la mulţimea <tex> I </tex> se codifică prin valoarea <tex> 0 </tex>. Acum existenţa unei muchii <tex> (x, y) </tex> corespunde expresiei <tex> x \\vee y </tex>, astfel cel puţin unul din nodurile <tex> x </tex> şi <tex> y </tex> nu va fi în mulţimea <tex> I </tex>. Dacă nu există muchia <tex> (x, y) </tex> putem scrie <tex> \\sim x \\vee \\sim y </tex>, această expresie va fi adevărată dacă cel puţin un nod din cele două nu va fi în mulţimea <tex> C </tex>.\r\n\r\nh2(#orpath). Orpath (Olimpiadă Rusia)\r\n\r\nbq. Într-o ţară pacifistă, există $N$ oraşe şi $K$ autobuze $(1 &le; N, K &le; 100)$. La orele aglomerate ale zilei, nu trebuie să existe două autobuze care merg în acelaşi timp în sensuri opuse. Traseul fiecărui autobuz este un ciclu. Spunem că el merge în sens pozitiv dacă va parcurge oraşele în ordinea $1 2 3 4 1 2 3 4 1 2$ ... sau în sens negativ dacă le parcurge în ordinea $1 4 3 2 1 4 3 2 1 4$ ... Găsiţi o posibilitate de atribuire a sensului fiecărui autobuz astfel ca accidentele de trafic să fie evitate (nu vor exista două autobuze care să se întâlnească şi să aibă sensuri de mers opuse). Pentru fiecare autobuz se vor şti oraşele de pe ruta lui, şi pentru fiecare două oraşe vecine pe rută se va şti timpul necesar autobuzului pentru a ajunge dintr-un oraş în altul. De exemplu, pentru $4$ oraşe unde oricare două sunt la timp de mers egal cu $10$, şi pentru două autobuze cu rutele $1 2 4$ şi $3 4 2$, o soluţie ar fi ca primul autobuz să meargă în sens pozitiv iar celălalt în sens negativ.\r\n\r\nh3. Soluţie\r\n\r\nPentru orice două autobuze vom găsi care sunt sensurile de mers pentru ele astfel ca cele două autobuze să nu se întâlnească şi să provoace un accident. Pentru un sens fixat putem afla pentru un autobuz pe ce interval de timp va fi pe o anumită stradă. El va fi în general pe o stradă $(i, j)$ pe un interval de tipul $[t1 + k*T ... t2 + k*T]$ unde $t1$ este timpul din prima rută parcursă pentru a ajunge la $i$, $t2$ timpul pentru a ajunge la $j$, iar $T$ este durata totală a unei rute. Acum, pentru a determina dacă două autobuze se vor întâlni pe o rută $(i, j)$ trebuie ca ele să se deplaseze în sensuri opuse pe această rută, iar intervalele $[t1 + k*T1 ... t2 + k*T1]$ ale primului să se intersecteze cu intervalele $[tt1 + p*T2 ... tt2 + p*T2]$ ale celui de-al doilea. Este clar acum că putem transforma problema într-o instanţă de $2-SAT$ prin maparea autobuzelor în variabile logice, a sensurilor de mers în valorile $adevărat$ şi $fals$, iar pentru orice pereche de autobuze să fie o propoziţie logică ce ia valoarea $adevărat$ doar dacă sensurile de mers determinate de variabilele logice asociate autobuzelor sunt compatibile. Mai trebuie determinat într-un mod eficient dacă două clase de intervale de timp se intersectează. Aceasta rămâne ca temă cititorului.\r\n\r\nh2(#aladdin). \'Aladdin\':problema/aladdin (Bursele Agora 2005/2006, Runda 1)\r\n\r\nbq. Aladdin, aşa cum ştiaţi, este un mare magnat în afacerea de comercializare a covoarelor magice. Acesta doreşte să o cucerească pe prinţesa Iasmina, iar aceasta, pentru a-i testa inteligenţa îl roagă să îi facă un covor dreptunghiular împărţit în pătrăţele, asemănator unei table de şah cu $N$ linii şi $M$ coloane $(1 &le; N, M &le; 1000)$. Fiecare pătrăţel de pe covor trebuie colorat cu alb sau cu negru. Pentru fiecare pătrat care conţine $4$ pătrăţele Iasmina pune condiţia să aibă un număr fixat de pătrăţele colorate cu negru. Ajutaţi-l pe Aladdin să realizeze un covor care satisface condiţiile impuse de prinţesa Iasmina!\r\n\r\nh3. Soluţie\r\n\r\nÎntâi, să considerăm un exemplu. Pentru o cerinţă de forma:\r\n\r\ntable{width: 90px; text-align: center}.\r\n| <tex> 3 </tex> | <tex> 2 </tex> | <tex> 3 </tex> |\r\n| <tex> 2 </tex> | <tex> 3 </tex> | <tex> 3 </tex> |\r\n| <tex> 1 </tex> | <tex> 2 </tex> | <tex> 1 </tex> |\r\n\r\nuna din soluţii este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nFie <tex> A </tex> o matrice soluţie a problemei noastre. Vom numerota rândurile matricii de la $0$ la $N - 1$ şi coloanele de la $0$ la $M - 1$. Matricea de intrare <tex> S </tex> reprezintă de fapt sumele din fiecare pătrat de câte $2 x 2$ elemente. Facem observaţia că dacă ştim într-un pătrat de $2 x 2$ valorile pentru trei dintre celule, atunci valoarea din a patra celulă este unic determinată pentru că ştim suma elementelor din pătrat. Vedem astfel, că dacă ştim valorile elementelor din prima linie a matricii <tex> A </tex> şi din prima coloană, restul valorilor sunt unic determinate. Pentru a rezolva problema vom presupune <tex> A[0][0] </tex> cunoscut (de fapt, mai întâi vom rezolva problema presupunând că <tex> A[0][0] = 1 </tex>, iar dacă nu obţinem nicio soluţie vom încerca cu <tex> A[0][0] = 0 </tex>). Vom nota celulele <tex> A[0][1] </tex>, <tex> A[0][2]</tex>, <tex>...</tex>, <tex> A[0][M - 1] </tex> cu <tex> x_{1} </tex>, <tex> x_{2} </tex>, <tex>...</tex>, <tex> x_{M-1} </tex>, iar celulele <tex> A[1][0] </tex>, <tex> A[2][0] </tex>, <tex>...</tex>, <tex> A[N - 1][0] </tex> cu <tex> y_{1} </tex>, <tex> y_{2} </tex>, <tex>...</tex>, <tex> y_{N-1} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> A[0][0] </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> ... </tex> | <tex> x_{M-1} </tex> |\r\n| <tex> y_{1} </tex> | <tex> 1 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n| <tex> y_{2} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 0 </tex> |\r\n| ... | ... | ... | ... | ... |\r\n| <tex> y_{N-1} </tex> | <tex> 0 </tex> | <tex> 1 </tex> | ... | <tex> 1 </tex> |\r\n\r\nAcum, pentru fiecare celulă putem demonstra prin inducţie că <tex> A[i][j] = (-1)^i x_{j} + (-1)^j y_{i} + b[i][j] </tex>. Unde <tex> b[i][j] </tex> sunt nişte constante ce sunt calculate în funcţie de matricea primită la intrare. Este uşor de observat că dacă:\r\n\r\n<tex> A[i-1][j] = (-1)^{(i-1)} x_{j} + (-1)^j y_{i-1} + b[i-1][j] </tex>,\r\n<tex> A[i-1][j-1] = (-1)^{(i-1)} x_{j-1} + (-1)^{(j-1)} y_{i-1} + b[i-1][j-1] </tex>,\r\n<tex> A[i][j-1] = (-1)^i x_{j-1} + (-1)^{(j-1)} y_{i} + b[i][j-1] </tex>,\r\n\r\natunci:\r\n\r\n<tex> A[i][j] = </tex> <tex> S[i-1][j-1] - </tex> <tex> A[i-1][j] - </tex> <tex> A[i][j-1] - </tex> <tex> A[i-1][j-1] = </tex> <tex> S[i-1][j-1] - </tex> <tex> ((-1)^{(i-1)} x_{j} + </tex> <tex> (-1)^j y_{i-1} + </tex> <tex> b[i-1][j]) - </tex> <tex> ((-1)^{(i-1)} x_{j-1} + </tex> <tex> (-1)^{(j-1)} y_{i-1} + </tex> <tex> b[i-1][j-1]) - </tex> <tex> ((-1)^i x_{j-1} + </tex> <tex> (-1)^{(j-1)} y_{i-1} + </tex> <tex> b[i][j-1]) = </tex> <tex> (-1)^i x_{j} - </tex> <tex> (-1)^j y_{i-1} + </tex> <tex> (-1)^i x_{j-1} + </tex> <tex> (-1)^j y_{i-1} - </tex> <tex> (-1)^i x_{j-1} + </tex> <tex> (-1)^j y_{i} + </tex> <tex> S[i-1][j-1] - </tex> <tex> b[i-1][j] - </tex> <tex> b[i][j-1] - </tex> <tex> b[i-1][j-1] = </tex> <tex> (-1)^i x_{j} + </tex> <tex> (-1)^j y_{i} + </tex> <tex> b[i][j] </tex>.\r\n\r\nDe aici concluzionăm că <tex> b[i][j] = S[i-1][j-1] - b[i-1][j] - b[i][j-1] - b[i-1][j-1] \\ (*)</tex>.\r\n\r\nAvem un sistem format din inecuaţiile:\r\n\r\n<tex> 0 \\le x_{j} \\le 1 </tex>\r\n<tex> 0 \\le y_{i} \\le 1 </tex>\r\n<tex> -b[i][j] \\le (-1)^i x_{j} + (-1)^j y_{i} \\le 1 - b[i][j] </tex>\r\n\r\nEste uşor acum să transformăm acest sistem într-o formulă booleană în {\'formă normal conjunctivă\':2-sat#forme-normale} în care fiecare expresie are cel mult $2$ literali. Fiecare relaţie o putem înmulţi sau nu cu $-1$ astfel ca părţile constante ale relaţiei să fie pozitive. Observăm că <tex> -2 \\le b[i][j] \\le 3 </tex>, altfel nu avem soluţie. Dacă partea constantă minimă într-o relaţie este $2$ atunci ambele variabile au valori fixe, iar dacă este $1$ sau $0$ atunci relaţia o putem scrie ca o disjuncţie logică cu doi literali.\r\n\r\nO relaţie precum <tex> 0 \\le x + y \\le 1 </tex> poate fi tansformată logic în <tex> \\sim x \\vee \\sim y </tex>, astfel <tex> x </tex> şi <tex> y </tex> nu vor fi în acelaşi timp <tex> 1 </tex>, una de genul <tex> 1 \\le x + y \\le 2 </tex> va fi transformată în <tex> x \\vee y </tex>, astfel cel puţin <tex> x </tex> sau <tex> y </tex> va fi egal cu <tex> 1 </tex>, alta de tipul <tex> 0 \\le x - y \\le 1 </tex> poate fi scrisă ca <tex> x \\vee \\sim y </tex>, una de tipul <tex> 2 \\le x + y \\le 3 </tex> în <tex> x \\wedge y </tex>, iar una de tipul <tex> 0 \\le -x -y \\le 1 </tex> în <tex> \\sim x \\wedge \\sim y </tex>, una de tipul <tex> 1 \\le x - y  \\le 2 </tex> în <tex> x \\wedge \\sim y </tex>. Astfel am redus problema la rezolvarea unei instanţe de $2-SAT$. Avem $N+M-1$ necunoscute şi @(N-1)*(M-1)@ propoziţii. Folosind {\'a treia metodă de rezolvare\':2-sat#solutie-3} vom obţine un algoritm de complexitate $O((M + N)^2^)$ care soluţionează problema noastră.\r\n\r\nSă vedem cum merge acestă rezolvare pe exemplul din problemă:\r\n\r\nAlegem <tex> A[0][0] = 1 </tex>. Necunoscutele vor fi <tex> x_{1} </tex>, <tex> x_{2} </tex>, <tex> x_{3} </tex> şi <tex> y_{1} </tex>, <tex> y_{2} </tex>, <tex> y_{3} </tex>.\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> x_{1} </tex> | <tex> x_{2} </tex> | <tex> x_{3} </tex> |\r\n| <tex> y_{1} </tex> | <tex> A[1][1] </tex> | <tex> A[1][2] </tex> | <tex> A[1][3] </tex> |\r\n| <tex> y_{2} </tex> | <tex> A[2][1] </tex> | <tex> A[2][2] </tex> | <tex> A[2][3] </tex> |\r\n| <tex> y_{3} </tex> | <tex> A[3][1] </tex> | <tex> A[3][2] </tex> | <tex> A[3][3] </tex> |\r\n\r\nFolosind recurenţa <tex> (*) </tex> obţinem că matricea <tex> b </tex> este:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 2 </tex> | <tex> 0 </tex> | <tex> 3 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> -1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n\r\nDe aici obţinem sistemul de inegalităţi:\r\n\r\n<tex> 0 \\le x_{1} \\le 1,  0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le 1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, -2 \\le -x_{1} - y_{1} \\le -1, 0 \\le -x_{2} + y_{1} \\le 1, -3 \\le -x_{3} - y_{1} \\le -2, </tex>\r\n<tex> 0 \\le y_{2} \\le 1,  0 \\le  x_{1} - y_{2} \\le  1,-1 \\le  x_{2} + y_{2} \\le 0,  1 \\le  x_{3} - y_{2} \\le  2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, -1 \\le -x_{1} - y_{3} \\le  0, 0 \\le -x_{2} + y_{3} \\le 1, -1 \\le -x_{3} - y_{3} \\le  0 </tex>\r\n\r\nTransformăm relaţiile astfel ca să nu apară nicio constantă negativă:\r\n\r\n<tex> 0 \\le x_{1} \\le 1, 0 \\le x_{2} \\le 1, 0 \\le x_{3} \\le  1, </tex>\r\n<tex> 0 \\le y_{1} \\le 1, 1 \\le x_{1} + y_{1} \\le 2, 0 \\le -x_{2} + y_{1} \\le 1, 2 \\le x_{3} + y_{1} \\le 3, </tex>\r\n<tex> 0 \\le y_{2} \\le 1, 0 \\le x_{1} - y_{2} \\le 1, 0 \\le -x_{2} - y_{2} \\le 1, 1 \\le x_{3} - y_{2} \\le 2, </tex>\r\n<tex> 0 \\le y_{3} \\le 1, 0 \\le x_{1} + y_{3} \\le 1, 0 \\le -x_{2} + y_{3} \\le 1, 0 \\le x_{3} + y_{3} \\le 1 </tex>\r\n\r\nAcest sistem poate fi transformat într-o expresie booleană:\r\n\r\n<tex> (x_{1} \\vee y_{1}) \\wedge (\\sim x_{2} \\vee y_{1}) \\wedge (x_{3} \\wedge y_{1}) \\wedge </tex>\r\n<tex> (x_{1} \\vee \\sim y_{2}) \\wedge (\\sim x_{2} \\wedge \\sim y_{2}) \\wedge (x_{3} \\wedge \\sim y_{2}) \\wedge </tex>\r\n<tex> (\\sim x_{1} \\vee \\sim y_{3}) \\wedge (\\sim x_{2} \\vee y_{3}) \\wedge (\\sim x_{3} \\vee \\sim y_{3}) </tex>.\r\n\r\nAcestă expresie e satisfăcută de valorile: <tex> \\langle x_{1} = 1, x_{2} = 0, x_{3} = 1, y_{1} = 1, y_{2} = 0, y_{3} = 0 \\rangle </tex>, iar de aici putem determina o soluţie a problemei noastre iniţiale ca fiind:\r\n\r\ntable{width: 90px; text-align: center}. \r\n| <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> |\r\n| <tex> 1 </tex> | <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> |\r\n| <tex> 0 </tex> | <tex> 1 </tex> | <tex> 1 </tex> | <tex> 0 </tex> |\r\n| <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> | <tex> 0 </tex> |\r\n\r\nh2(#probleme). Probleme propuse\r\n\r\nPentru a vă familiariza cu subiectul prezentat în acest articol, vă propunem să încercaţi să rezolvaţi următoarele probleme:\r\n\r\n# \'Excursion\':http://www.oi.edu.pl/download/boi-2001.pdf - Baltic Olympiad in Informatics, 2001\r\n# \'Peaceful Commission\':http://www.oi.edu.pl/php/show.php?ac=e100000&module=show&file=zadania/oi8/spokojna - Polish Olympiad in Informatics, 2001\r\n\r\nh2(#bibliografie). Bibliografie:\r\n\r\n# T. H. Cormen, C. E. Leiserson, R. R. Rivest - \'_Introducere în Algoritmi_\':http://zhuzeyuan.hp.infoseek.co.jp/ita/toc.htm\r\n# \'_Satisfiability_\':http://en.wikipedia.org/wiki/Satisfiability, Wikipedia\r\n# \'_BOI 2001 Competition Material_\':http://www.oi.edu.pl/download/boi-2001.pdf\r\n# \'_CEOI 2002 Competition Material_\':http://ics.upjs.sk/ceoi/Documents.html',7668,'public',3704,NULL),('implica-te/arhiva-educationala','Arhiva Educationala','2008-02-23 13:13:01','2009-12-11 19:23:21','h1. Arhiva educationala ==Stars(rating=\"5\")==\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie. Mai multe despre acest proiect gasiti \'aici\':propuneri/6-arhiva-educationala.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Cum ne poti ajuta?\':implica-te/arhiva-educationala#cum\r\n* \'Echipa implicata in proiect\':implica-te/arhiva-educationala#echipa\r\n* \'Documentatie\':implica-te/arhiva-educationala#documentatie\r\n* \'Continutul arhivei\':implica-te/arhiva-educationala#probleme\r\n\r\nh2(#cum). Cum ne poti ajuta?\r\n\r\n1. Ofera sugestii la dezvoltarea proiectului.\r\n2. Contribuie cu feedback pentru a imbunatati calitatea problemelor existente.\r\n3. Vino cu idei pentru probleme noi.\r\nAjuta si tu la randul tau comunitatea infoarena! \r\n\r\nh2(#echipa). Echipa implicata in proiect\r\n\r\nMomentan, pentru a obtine o eficienta mai buna, recrutarea voluntarilor pentru dezvoltarea arhivei educationale a fost oprita. Echipa care este implicata activ in proiect este alcatuita din:\r\n\r\n* == user(user=\"Marius\" type=\"tiny\") ==, coordonator de proiect\r\n* == user(user=\"savim\" type=\"tiny\") ==\r\n* == user(user=\"cezarmocan\" type=\"tiny\") ==\r\n* == user(user=\"GavrilaVlad\" type=\"tiny\") ==\r\n* == user(user=\"mishu91\" type=\"tiny\") == \r\n\r\nMultumim celor care ne-au ajutat pana acum:\r\n\r\n* == user(user=\"pauldb\" type=\"tiny\") ==, fost coordonator de proiect\r\n* == user(user=\"filipb\" type=\"tiny\") ==, fost coordonator de proiect\r\n* == user(user=\"devilkind\" type=\"tiny\") ==\r\n* == user(user=\"mariusdrg\" type=\"tiny\") ==\r\n* == user(user=\"bogdan2412\" type=\"tiny\") ==\r\n* == user(user=\"Florian\" type=\"tiny\") ==\r\n* == user(user=\"gabitzish1\" type=\"tiny\") ==\r\n* == user(user=\"Tabara\" type=\"tiny\") ==\r\n* == user(user=\"Dastas\" type=\"tiny\") ==\r\n* == user(user=\"fireatmyself\" type=\"tiny\") ==\r\n* == user(user=\"cos_min\" type=\"tiny\") ==\r\n* == user(user=\"tudalex\" type=\"tiny\") ==\r\n* == user(user=\"toni2007\" type=\"tiny\") ==\r\n* == user(user=\"tm_radu\" type=\"tiny\") ==\r\n* == user(user=\"floringh06\" type=\"tiny\") ==\r\n* == user(user=\"prostu\" type=\"tiny\") ==\r\n* == user(user=\"amadaeus\" type=\"tiny\") ==\r\n* == user(user=\"sima_cotizo\" type=\"tiny\") ==\r\n\r\nh2(#documentatie). Documentatie\r\n\r\nFiecare voluntar are obligatia sa citeasca urmatoarele materiale inainte de a putea trece efectiv la lucru:\r\n\r\n* \'Editare de probleme\':documentatie/editare-de-probleme\r\n* \'Ghid evaluator\':documentatie/ghid-evaluator\r\n* \'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala\r\n\r\nh2(#probleme). Continutul arhivei\r\n\r\nIn tabelul de mai jos se afla probleme la care se lucreaza in momentul de fata. Finalizarea lor reprezinta unul dintre $OKR$-urile din trimestrul IV, 2009. Pentru a va familiariza si cu restul obiectivelor din acest trimestru, cititi \'aici\':okr.\r\n\r\ntable(example). |_. Denumire problema|_. Voluntar|_. Finalizat|\r\n| \'Cuplaj maxim de cost minim\':problema/cmcm | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Principiul includerii si excluderii\':problema/pinex | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Huffman\':problema/huffman | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'2SAT\':problema/2sat | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Al K-lea termen Fibonacci - Matrici\':problema/kfib | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Lowest Common Ancestor\':problema/lca | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Statistici de ordine\':problema/sdo | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Parantezare optima de matrici\':problema/podm | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Treapuri\':problema/treapuri | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Ciclu hamiltonian | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n\r\n\r\nIn tabelul de mai jos se afla sugestii privind algoritmii care trebuie sa se gaseasca sub forma de probleme in arhiva educationala. Puteti veni oricand cu propuneri si sugestii de probleme noi pe \"forum\":/forum/index.php?topic=3401.0.\r\n\r\ntable(example). |_. Denumire problema|_. Categoria|\r\n|Submultimi|Backtracking|\r\n|Knapsack|Programare dinamica|\r\n|NIM|Teoria jocurilor|\r\n|Sprague-Grundy|Teoria jocurilor|\r\n|Algoritmul lui Gauss|Matematica|\r\n|Problema de acoperire|Programare dinamica + Backtracking|\r\n|Algoritmul Bellman-Ford|Algoritmi pe grafuri|\r\n|Algoritmul Stoer-Wagner|Algoritmi pe grafuri|\r\n|Heavy Path Decomposition|Algoritmi pe grafuri|\r\n|Arbore -> cod Prufer|Algoritmi pe grafuri|\r\n|Cod Prufer -> arbore|Algoritmi pe grafuri|\r\n|Distanta maxima intre 2 noduri intr-un arbore|Algoritmi pe grafuri|\r\n|Siruri de sufixe|Siruri de caractere|\r\n|Arbori de sufixe|Siruri de caractere|\r\n|Automate - Aho Corasick|Siruri de caractere|\r\n|Arbori de intervale aplicatie 1|Structuri de date|\r\n|Arbori de intervale aplicatie 2|Structuri de date|\r\n|Arbori de intervale aplicatie 3|Structuri de date|\r\n|Arbori de intervale aplicatie 4|Structuri de date|\r\n|Algoritmi {$O(sqrtN)$}|Structuri de date|\r\n|Ortogonal Range Search|Structuri de date|\r\n|Aria unui poligon|Geometrie|\r\n|Intersectia a doua drepte|Geometrie|\r\n|Punct in poligon|Geometrie|\r\n|Punct in poligon convex|Geometrie|\r\n|Diagrame Voronoi|Geometrie|\r\n|Distanta minima intre doua puncte in plan|Geometrie|\r\n|Distanta maxima intre doua puncte in plan|Geometrie|\r\n|Minimum enclosing circle|Geometrie|\r\n|Sortare prin numarare|Diverse|\r\n|RadixSort|Diverse|\r\n|Interclasarea a doi vectori sortati|Diverse|\r\n|Operatii pe numere mari|Diverse|',3146,'protected',NULL,NULL),('propuneri/15-task-tagging','IAP #15: Task tagging','2009-11-26 08:50:05','2009-11-26 09:39:04','h1. IAP #15: Task tagging\r\n\r\n==Include(page=\"template/iap\")==\r\n\r\n|_. Data      | 2009-11-26 |\r\n|_. Autor(i)  | ==User(type=\"tiny\" user=\"bogdan2412\")== |\r\n|_. Stare     | In constructie |\r\n\r\nh2(#abstract). Abstract\r\n\r\nSe propune crearea unui sistem prin care fiecarei probleme ii vor fi asociate informatii sub forma de taguri si a unui sistem de cautare bazat pe aceste taguri.\r\n\r\nh2(#motivatie). Motivatie\r\n\r\nArhiva de probleme devine din ce in ce mai mare si din ce in ce mai greu de navigat. Un astfel de sistem ar ajuta utilizatorii sa filtreze mult mai usor probleme in functie de mai multe informatii.\r\n\r\nPropun ca urmatoarele informatii sa fie asociate fiecarei probleme:\r\n\r\n* Autorul sau autorii problemelor (daca o problema a fost propusa de catre mai multi autori, fiecare autor va avea un tag separat).\r\n* Concursul (si runda) la care a fost data problema. Pentru problemele date la concursuri pe infoarena ar fi bine de mentinut si un tag cu grupa de varsta la care a fost data problema (din nou, daca o problema a fost data la mai multe grupe de varsta, fiecare grupa de varsta va avea un tag separat).\r\n** Spre exemplu tagurile asociate problemei \"vrejuri\":problema/vrejuri ar fi \"Algoritmiada 2010\", \"Algoritmiada 2010, Runda 1\", \"Algoritmiada 2010, Runda 1, 9-10\"\r\n* Cunostintele necesare rezolvarii problemelor. In aceasta categorie intra orice fel de algoritm classic cunoscut (un punct bun de plecare ar fi \"Training Path\":training-path).\r\n** Propun sa impartim aceste taguri in doua categorii: \"Generale\" (Grafuri, Programare Dinamica, Greedy, Structuri de date, Geometrie) si \"Specifice\" (Deque, Arbori echilibrati, Codul Gray, Minimal enclosing circle). Tag-urile generale nu iti ofera foarte multe informatii care ar putea strica farmecul problemelor, in timp ce cele \"specifice\" iti zic exact ce algoritmi sunt necesari pentru rezolvarea problemei. Fiecare din tagurile \"specifice\" se va incadra intr-o categorie denumita de un tag general. (spre exemplu Deque intra sub Structuri de date)\r\n** In momentul in care utilizatorul deschide o problema, tagurile sunt ascunse by default. Daca acesta vrea un hint de rezolvare, ii aratam intai tagurile generale. Daca vrea si mai multe hinturi, ii aratam toate tagurile.\r\n\r\nh2(#implementare). Implementare\r\n\r\nUn astfel de sistem implica adaugarea unei noi coloane in tabelul $ia_tags$ sau $ia_task_tags$ care sa mentina pentru fiecare tag de ce tip este. Pentru a putea face o interfata frumoasa, ne trebuie sa stim pentru fiecare tag daca el este pentru:\r\n\r\n* un \"autor\"\r\n* un \"concurs\"\r\n* o \"runda din concurs\",\r\n* o \"grupa de varsta din runda din concurs\"\r\n* o \"categorie de algoritmi\" (tag-urile de cunostinte generale)\r\n* un \"algoritm\".\r\n\r\nInterfata de filtrare dupa taguri ar trebui sa-ti dea o lista frumoasa cu toate tagurile pentru un autor, concurs, algoritm etc. Datorita separarii intre taguri de \"concurs\", de \"runda\" si de \"grupa de varsta\", odata ce utilizatorul a selectat un concurs dupa care vrea sa filtreze i se da optiunea de a filtra si dupa o runda a acelui concurs (daca acesta doreste), si dupa aceea i se da optiunea de a selecta si o anumita grupa de varsta.\r\n\r\nh2(#feedback). Feedback\r\n',1490,'public',4309,NULL),('links','Links','2006-11-05 23:22:35','2007-06-19 11:49:41','http://sorins-world.blogspot.com/',6383,'public',NULL,NULL),('utilizator/gavrilavlad','Gavrila Vlad','2007-09-21 12:07:43','2009-12-14 17:30:19','   \r\n\r\nh2. Despre mine\r\n\r\nMa numesc Gavrila Vlad Alexandru si sunt elev in clasa a IX-a la ICHB. Particip de mult timp la concursuri de informatica, iar principala mea sursa de pregatire este infoarena.\r\n\r\nh2. Distinctii primite\r\n\r\nOlimpiada Nationala de Informatica\r\n\r\n* 2004 - Buzau - Mentiune\r\n* 2005 - Galati - Premiul special\r\n* 2006 - Targoviste - Mentiunea I\r\n* 2007 - Cluj - Premiul II\r\n* 2008 - Bacau - Premiul I\r\n* 2009 - Galati - Premiul II\r\n\r\nBaraje\r\n\r\n* 2008 - Ploiesti / Iasi - Calificat (locul I) la JBOI\r\n* 2009 - Bistrita / Cluj - Calificat (locul I, cu maxim de puncte) la JBOI\r\n\r\nJunior Balkan Olympiad in Informatics\r\n\r\n* 2008 - Shumen - Argint\r\n* 2009 - Shumen - Aur absolut\r\n\r\nPreONI, Algoritmiada si .Campion\r\n\r\n* 2008 - PreONI - Finalist\r\n* 2009 - .Campion - Locul II\r\n* 2009 - Algoritmiada - Locul I\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* Profesori:\r\n\r\n==user(user=\"pauldb\" type=\"normal\")==\r\n\r\n==user(user=\"wefgef\" type=\"normal\")==\r\n\r\n==user(user=\"bogdan2412\" type=\"normal\")==\r\n\r\n==user(user=\"gcosmin\" type=\"normal\")==\r\n\r\n==user(user=\"silviug\" type=\"normal\")==\r\n\r\n\r\n* Prieteni:\r\n\r\n==user(user=\"savim\" type=\"normal\")==\r\n\r\n==user(user=\"CezarMocan\" type=\"normal\")==\r\n\r\n==user(user=\"raduzer\" type=\"normal\")==\r\n\r\n==user(user=\"toni2007\" type=\"normal\")==\r\n\r\n==user(user=\"tvlad\" type=\"normal\")==\r\n\r\n==user(user=\"victor.ionescu\" type=\"normal\")==\r\n\r\n==user(user=\"andrei-alpha\" type=\"normal\")==\r\n\r\n==user(user=\"GheorgheMihai\" type=\"normal\")==\r\n\r\n==user(user=\"andreea1cool\" type=\"normal\")==\r\n\r\n==user(user=\"radu_voroneanu\" type=\"normal\")==\r\n\r\n==user(user=\"protoman\" type=\"normal\")==\r\n\r\n==user(user=\"matemariaescu\" type=\"normal\")==\r\n\r\n==user(user=\"taloibogdan\" type=\"normal\")==\r\n',6800,'public',NULL,NULL),('implica-te/arhiva-educationala','Arhiva Educationala','2008-02-23 13:13:01','2009-12-17 06:24:12','h1. Arhiva educationala ==Stars(rating=\"5\")==\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie. Mai multe despre acest proiect gasiti \'aici\':propuneri/6-arhiva-educationala.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Cum ne poti ajuta?\':implica-te/arhiva-educationala#cum\r\n* \'Echipa implicata in proiect\':implica-te/arhiva-educationala#echipa\r\n* \'Documentatie\':implica-te/arhiva-educationala#documentatie\r\n* \'Continutul arhivei\':implica-te/arhiva-educationala#probleme\r\n\r\nh2(#cum). Cum ne poti ajuta?\r\n\r\n1. Ofera sugestii la dezvoltarea proiectului.\r\n2. Contribuie cu feedback pentru a imbunatati calitatea problemelor existente.\r\n3. Vino cu idei pentru probleme noi.\r\n\r\nAjuta si tu la randul tau comunitatea infoarena! \r\n\r\nh2(#echipa). Echipa implicata in proiect\r\n\r\nEchipa care este implicata activ in acest proiect este alcatuita din urmatorii membri...\r\n\r\n* == user(user=\"Marius\" type=\"tiny\") ==, coordonator de proiect\r\n* == user(user=\"savim\" type=\"tiny\") ==\r\n* == user(user=\"cezarmocan\" type=\"tiny\") ==\r\n* == user(user=\"GavrilaVlad\" type=\"tiny\") ==\r\n* == user(user=\"mishu91\" type=\"tiny\") == \r\n\r\n\'Multumim celor care ne-au ajutat pana acum.\':implica-te/arhiva-educationala/membri-emeritus\r\n\r\nh2(#documentatie). Documentatie\r\n\r\nFiecare voluntar are obligatia sa citeasca urmatoarele materiale inainte de a putea trece efectiv la lucru:\r\n\r\n* \'Editare de probleme\':documentatie/editare-de-probleme\r\n* \'Ghid evaluator\':documentatie/ghid-evaluator\r\n* \'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala\r\n\r\nh2(#probleme). Continutul arhivei\r\n\r\nIn tabelul de mai jos se afla probleme la care se lucreaza in momentul de fata. Finalizarea lor reprezinta unul dintre $OKR$-urile din trimestrul IV, 2009. Pentru a va familiariza si cu restul obiectivelor din acest trimestru, cititi \'aici\':okr.\r\n\r\ntable(example). |_. Denumire problema|_. Voluntar|_. Finalizat|\r\n| \'Cuplaj maxim de cost minim\':problema/cmcm | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Principiul includerii si excluderii\':problema/pinex | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Huffman\':problema/huffman | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| Algoritmul Bellman-Ford | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'2SAT\':problema/2sat | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Al K-lea termen Fibonacci - Matrici\':problema/kfib | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Lowest Common Ancestor\':problema/lca | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Statistici de ordine\':problema/sdo | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Parantezare optima de matrici\':problema/podm | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Treapuri\':problema/treapuri | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Ciclu hamiltonian | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Submulţimi\':problema/submultimi | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n\r\n\r\nIn tabelul de mai jos se afla sugestii privind algoritmii care trebuie sa se gaseasca sub forma de probleme in arhiva educationala. Puteti veni oricand cu propuneri si sugestii de probleme noi pe \"forum\":/forum/index.php?topic=3401.0.\r\n\r\ntable(example). |_. Denumire problema|_. Categoria|\r\n|Submultimi|Backtracking|\r\n|Knapsack|Programare dinamica|\r\n|NIM|Teoria jocurilor|\r\n|Sprague-Grundy|Teoria jocurilor|\r\n|Algoritmul lui Gauss|Matematica|\r\n|Numerele lui Stirling|Matematica|\r\n|Problema de acoperire|Programare dinamica + Backtracking|\r\n|Algoritmul Stoer-Wagner|Algoritmi pe grafuri|\r\n|Heavy Path Decomposition|Algoritmi pe grafuri|\r\n|Arbore -> cod Prufer|Algoritmi pe grafuri|\r\n|Cod Prufer -> arbore|Algoritmi pe grafuri|\r\n|Distanta maxima intre 2 noduri intr-un arbore|Algoritmi pe grafuri|\r\n|Siruri de sufixe|Siruri de caractere|\r\n|Arbori de sufixe|Siruri de caractere|\r\n|Automate - Aho Corasick|Siruri de caractere|\r\n|Arbori de intervale aplicatie 1|Structuri de date|\r\n|Arbori de intervale aplicatie 2|Structuri de date|\r\n|Arbori de intervale aplicatie 3|Structuri de date|\r\n|Arbori de intervale aplicatie 4|Structuri de date|\r\n|Algoritmi {$O(sqrtN)$}|Structuri de date|\r\n|Ortogonal Range Search|Structuri de date|\r\n|Aria unui poligon|Geometrie|\r\n|Intersectia a doua drepte|Geometrie|\r\n|Punct in poligon|Geometrie|\r\n|Punct in poligon convex|Geometrie|\r\n|Diagrame Voronoi|Geometrie|\r\n|Distanta minima intre doua puncte in plan|Geometrie|\r\n|Distanta maxima intre doua puncte in plan|Geometrie|\r\n|Minimum enclosing circle|Geometrie|\r\n|Sortare prin numarare|Diverse|\r\n|RadixSort|Diverse|\r\n|Interclasarea a doi vectori sortati|Diverse|\r\n|Operatii pe numere mari|Diverse|\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"61\")==',3146,'protected',NULL,NULL),('algoritmiada-2010/runda-2/solutii','Solutii Algoritmiada 2010 Runda 2','2009-11-28 15:29:53','2009-11-28 15:34:44','h1. Solutii Algoritmiada 2010, Runda 2\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n\r\n',1792,'private',NULL,NULL),('implica-te/scrie-articole','Scrie articole','2007-03-28 22:23:46','2009-12-21 17:16:51','h1. Scrie articole ==Stars(rating=\"4\")==\r\n\r\nFolosind modelul de \'wiki\':documentatie/wiki, infoarena ofera sansa tuturor membrilor sai sa contribuie la realizarea de articole sau la imbunatatirea celor existente. Daca vrei sa afli mai multe despre conceptul de wiki intra \'aici\':http://en.wikipedia.org/wiki/Wiki, iar daca vrei sa contribui la acesta initiativa citeste mai jos ce trebuie sa faci.\r\n\r\nh2. De ce m-as baga?\r\n\r\n* O cariera in cercetare in informatica poate debuta cu niste articole online!\r\n* Vei invata care sunt elementele cheie pentru a scrie un articol.\r\n* Vei invata pe altii ceea ce stii, asa cum probabil si tu ai invatat din articolele deja \'existente\':articole.\r\n\r\nh2. Ce pot sa fac?\r\n\r\nDe-a lungul timpului, utilizatorii infoarena si-au manifestat interesul in a scrie articole pentru intreaga comunitate. In momentul de fata ne concentram eforturile atat pe completarea si aducerea la o forma prezentabila a acestor articole vechi, cat si pe scrierea de articole noi. Sunt 3 moduri in care poti contribui:\r\n\r\nh3. 1. Ajuta-ne la ce lucram acum\r\n\r\nIn tabelul de mai jos poti gasi articolele incepute, impreuna cu stadiul in care se gaseste fiecare. Daca esti dornic sa ne ajuti, alege-ti unul din articolele de care nu se ocupa nimeni si ia legatura cu coordonatorul proiectului ca sa afli ce mai e de facut la el.\r\n\r\ntable. |_. Titlu |_. Autor |_. Stadiu |_. Voluntar(i) |\r\n| \'Flux si cuplaj\':flux-si-cuplaj | ==user(user=\"blasterz\" type=\"tiny\")== | IN LUCRU | ==user(user=\"blasterz\" type=\"tiny\")== |\r\n| \'Teoria jocurilor\':teoria-jocurilor | ==user(user=\"filipb\" type=\"tiny\")== | IN LUCRU | ==user(user=\"filipb\" type=\"tiny\")== |\r\n| \'Psihologia concursurilor de informatica - Lucrul cu numere mari\':lucrul-cu-nr-mari | ==user(user=\"cata00\" type=\"tiny\")== | IMBUNATATIRE CONTINUT | ? |\r\n| Psihologia concursurilor de informatica - Lucrul cu structuri mari de date | ==user(user=\"cata00\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| Psihologia concursurilor de informatica - Probleme de concurs | ==user(user=\"cata00\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Probleme de taietura\':probleme-de-taietura | ==user(user=\"Cosmin\" type=\"tiny\")== | ÎN LUCRU | ? |\r\n| \'Transformari geometrice\':downloads?action=download&file=transformari_geometrice.doc | ==user(user=\"Cosmin\" type=\"tiny\")== | ÎN LUCRU |  ==user(user=\"Marius\" type=\"tiny\")== |\r\n| \'Notiuni de geometrie analitica si aplicatii\':notiuni-de-geometrie-si-aplicatii | ==user(user=\"devilkind\" type=\"tiny\")== \r\n==user(user=\"sima_cotizo\" type=\"tiny\")== | IMBUNATATIRE CONTINUT | ? |\r\n\r\nh3. 2. Preia si dezvolta un subiect mai vechi\r\n\r\nAi nevoie de un impuls pentru a-ti da drumul la scris? Sunt cateva articole pe infoarena incepute, dar abandonate, precum si niste schite. Poti folosi ideile de start ale autorului si il poti transforma intr-un articol bine documentat. In plus, poti lua legatura cu autorul initial si poti afla viziunea sa asupra subiectului. Iata o lista de articole abandonate si de schite:\r\n\r\ntable. |_. Titlu |_. Autor initial |\r\n| Programare dinamica / memoizare (trading space for time): \'link1\':programare-dinamica, \'link2\':pd | ==user(user=\"Zeus\" type=\"tiny\")== |\r\n| \'Arbori indexati binar\':aib | ==user(user=\"Skipy\" type=\"tiny\")== |\r\n| \'Dinic\':dinic | ==user(user=\"alexandru.mosoi\" type=\"tiny\")== |\r\n| \'Probleme de geometrie si solutii\':downloads?geometrie.zip | ==user(user=\"Cosmin\" type=\"tiny\")== |\r\n| \'Diagrame Voronoi\':voronoi | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| \'Algoritmi de baleiere\':algoritmi-de-baleiere | ==user(user=\"stef2n\" type=\"tiny\")== |\r\n\r\nh3. 3. Creeaza ceva nou\r\n\r\nAi o idee noua de articol? Sau pur si simplu vrei sa te apuci de la 0 de un subiect? Ia legatura cu coordonatorul proiectului sau anunta pe \'forum\':forum. Este posibil sa primesti ajutor si de la alti utilizatori infoarena. In plus, noi iti propunem o lista de articole pe care ni le-am dori scrise, in caz ca nu te-ai decis asupra temei:\r\n\r\ntable. |_. Titlu |\r\n| Depanarea programelor C/C++ cu gdb in Linux |\r\n| Testarea surselor in timp de concurs sau Cum sa reduci buselile |\r\n| Tutorial LaTeX |\r\n\r\nNe rezervam dreptul sa nu acceptam sau sa stergem articolele care nu se potrivesc cu tema si target-ul site-ului.\r\n\r\nh2. Cu cine iau legatura?\r\n\r\nCu coordonatorul proiectului:\r\n\r\n* ==user(user=\"Marius\" type=\"tiny\")==\r\n\r\nSau daca vrei sa contribui la un articol la care se lucreaza deja, poti vorbi direct cu voluntarii care se ocupa de el.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"43\")==',3146,'public',NULL,NULL),('algoritmiada-2010/runda-2/solutii/recurenta2','Recurenta2','2009-12-20 13:54:47','2009-12-21 21:15:26','h1(#recurenta2). \'Recurenta2\':problema/recurenta2\r\n\r\nNotăm $S{~i~} = 1*X{~1~} + 2*X{~2~} + ... + i*X{~i~}$. Recurenta pentru $S{~i~}$ este usor de gasit: $S{~i+1~} = S{~i~} + (i+1)*X{~i+1~}$. Putem sa-l explicitam pe $X{~i+1~}$ in functie de termenii anteriori si obtinem: $S{~i+1~} = S{~i~} + (i+1)*X{~i-1~}*B + (i+1)*X{~i~}*A + (i+1)*C$. Asadar, observam ca la pasul $i$ nu ne dorim sa cunoastem doar $X{~i-1~}$, $X{~i~}$ si $S{~i~}$, ci si de $(i+1)*X{~i-1~}$ si $(i+1)*X{~i~}$. Recurentele pentru acesti $2$ noi termeni sunt usor de gasit: $(i+1)*X{~i-1~} = i*X{~i-1~} + X{~i-1~}$, iar $(i+1)*X{~i~} = i*X{~i~} + X{~i~} = X{~i-2~}*A + i*X{~i-1~}*B + i*C + X{~i-2~}*A + X{~i-1~}*B + C$. Observam ca putem aseza aseza aceste recurente in urmatoarea matrice de trecere de la pasul $i-1$ la pasul $i$:\r\n\r\n<tex>\\begin{pmatrix} X_{i-2} & X_{i-1} & 1 & S_{i-1} & i*X_{i-2} & i*X_{i-1}& i \\end{pmatrix} * \\begin{pmatrix} 0 & B & 0 & 0 & 0 & B & 0 \\\\ 1 & A & 0 & 0 & 1 & A & 0 \\\\ 0 & C & 1 & 0 & 0 & C & 1 \\\\ 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & B & 0 & B & 0 \\\\ 0 & 0 & 0 & A & 1 & A & 0 \\\\ 0 & 0 & 0 & C & 0 & C & 1 \\end{pmatrix}  = </tex>\r\n\r\n<tex> \\begin{pmatrix} X_{i-1} & X_{i} & 1 & S_{i} & (i+1)*X_{i-1} & (i+1)*X_{i}& i+1 \\end{pmatrix}</tex>.',1792,'public',NULL,NULL),('algoritmiada-2010/runda-2/solutii/recurenta2','Recurenta2','2009-12-20 13:54:47','2009-12-21 21:27:00','h1(#recurenta2). \'Recurenta2\':problema/recurenta2\r\n\r\nNotăm $S{~i~} = 1*X{~1~} + 2*X{~2~} + ... + i*X{~i~}$. Recurenţa pentru $S{~i~}$ este uşor de găsit: $S{~i+1~} = S{~i~} + (i+1)*X{~i+1~}$. Putem să-l explicităm pe $X{~i+1~}$ în funcţie de termenii anteriori şi obţinem: $S{~i+1~} = S{~i~} + (i+1)*X{~i-1~}*B + (i+1)*X{~i~}*A + (i+1)*C$. Aşadar, observăm că la pasul $i$ nu ne dorim să cunoaştem doar valorile $X{~i-1~}$, $X{~i~}$ şi $S{~i~}$, ci şi pe $(i+1)*X{~i-1~}$ şi $(i+1)*X{~i~}$. Recurenţele pentru aceşti $2$ noi termeni sunt şi ele uşor de găsit: $(i+1)*X{~i-1~} = i*X{~i-1~} + X{~i-1~}$, iar $(i+1)*X{~i~} = i*X{~i~} + X{~i~} = X{~i-2~}*A + i*X{~i-1~}*B + i*C + X{~i-2~}*A + X{~i-1~}*B + C$. Observăm că putem aşeza aceste recurenţe în urmatoarea matrice de trecere de la pasul $i-1$ la pasul $i$:\r\n\r\n<tex>\\begin{pmatrix} X_{i-2} & X_{i-1} & 1 & S_{i-1} & i*X_{i-2} & i*X_{i-1}& i \\end{pmatrix} *</tex><tex>\\begin{pmatrix} 0 & B & 0 & 0 & 0 & B & 0 \\\\ 1 & A & 0 & 0 & 1 & A & 0 \\\\ 0 & C & 1 & 0 & 0 & C & 1 \\\\ 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & B & 0 & B & 0 \\\\ 0 & 0 & 0 & A & 1 & A & 0 \\\\ 0 & 0 & 0 & C & 0 & C & 1 \\end{pmatrix} </tex><tex>= \\begin{pmatrix} X_{i-1} & X_{i} & 1 & S_{i} & (i+1)*X_{i-1} & (i+1)*X_{i}& i+1 \\end{pmatrix}</tex>.\r\n\r\nPutem aplica proprietatea de asociativitate a înmulţirii matricilor şi să înmulţim matricea de trecere cu ea însăşi de $N$ ori şi abia după aceea să înmulţim matricea iniţială cu matricea rezultată. Complexitatea totală este $O(logN)$, folosind \'exponenţierea în timp logaritmic\':problema/lgput.',1792,'public',NULL,NULL),('articole/template-solutii','articole/template-solutii','2008-12-13 14:45:42','2009-11-23 17:37:08','* !>articole/template-solutii?algoritmiada-2010.jpg! \'Algoritmiada 2010, Runda 1\':algoritmiada-2010/runda-1/solutii\r\n* \'Summer Challenge 2009, Runda 3\':summer-challenge-2009/solutii/runda-3\r\n* \'Summer Challenge 2009, Runda 2\':summer-challenge-2009/solutii/runda-2\r\n* \'Summer Challenge 2009, Runda 1\':summer-challenge-2009/solutii/runda-1\r\n* \'Grigore Moisil 2009\':grigore-moisil-2009/solutii\r\n* !>articole/template-solutii?algoritmiada-2009.jpg! \'Algoritmiada 2009, Runda 3\':algoritmiada-2009/runda-3/solutii\r\n* \'Algoritmiada 2009, Runda 2\':algoritmiada-2009/runda-2/solutii\r\n* \'Algoritmiada 2009, Runda 1\':algoritmiada-2009/runda-1/solutii\r\n* \'Junior Challenge 2008\':junior-challenge-2008/solutii\r\n* \'Grigore Moisil 2008\':grigore-moisil-2008/solutii\r\n* \'preONI 2008, Runda finala\':preoni-2008/runda-finala/solutii\r\n* !>articole/template-solutii?preoni-2008.jpg! \'preONI 2008, Runda 4\':preoni-2008/runda-4/solutii\r\n* \'preONI 2008, Runda 3\':preoni-2008/runda-3/solutii\r\n* \'preONI 2008, Runda 2\':preoni-2008/runda-2/solutii\r\n* \'preONI 2008, Runda 1\':preoni-2008/runda-1/solutii\r\n*{display: %display%} \'Winter Challenge 2008, Runda 2\':winter-challenge-2008/runda-2/solutii\r\n*{display: %display%} \'Winter Challenge 2008, Runda 1\':winter-challenge-2008/runda-1/solutii\r\n*{display: %display%} \'Happy Coding 2007\':happy-coding-2007/solutii\r\n*{display: %display%} \'Autumn Warmup 2007 runda 3\':autumn-warmup-2007/solutii/runda-3\r\n*{display: %display%} \'Autumn Warmup 2007 runda 2\':autumn-warmup-2007/solutii/runda-2\r\n*{display: %display%} \'Autumn Warmup 2007 runda 1\':autumn-warmup-2007/solutii/runda-1\r\n*{display: %display%} \'Summer Challenge 2007 runda #3\':summer-challenge-2007/solutii/runda-3\r\n*{display: %display%} \'Summer Challenge 2007 runda #2\':summer-challenge-2007/solutii/runda-2\r\n*{display: %display%} \'Summer Challenge 2007 runda #1\':summer-challenge-2007/solutii/runda-1\r\n*{display: %display%} \'Junior Challenge 2007\':junior-challenge/solutii\r\n*{display: %display%} !>articole/template-solutii?preoni-2007.jpg! \'preONI 2007 runda finala - solutii\':preoni-2007/runda-finala/solutii\r\n*{display: %display%} \'preONI 2007 runda #4 - solutii\':preoni-2007/runda-4/solutii\r\n*{display: %display%} \'preONI 2007 runda #3 - solutii\':preoni-2007/runda-3/solutii\r\n*{display: %display%} \'preONI 2007 runda #2 - solutii\':preoni-2007/runda-2/solutii\r\n*{display: %display%} \'preONI 2007 runda #1 - solutii\':preoni-2007/runda-1/solutii\r\n*{display: %display%} \'Winter Challenge 1\':winter-challenge-1/solutii\r\n*{display: %display%} \'Unirea 2007\':unirea-2007/solutii\r\n*{display: %display%} \'Solutii Autumn WarmUp 2006\':warm-up-2006/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Trei\':summer-challenge-3/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Doi\':summer-challenge-2/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Unu\':summer-challenge-unu/solutii\r\n*{display: %display%} !>articole/template-solutii?preoni-2006.gif! \'Solutii preONI 2006, Runda finala\':preoni-2006/finala/solutii\r\n*{display: %display%} \'Solutii preONI 2006, Runda a 4-a\':preoni-2006/runda-4/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda a 3-a\':preoni-2006/runda-3/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda a 2-a\':preoni-2006/runda-2/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda 1\':preoni-2006/runda-1/solutii\r\n*{display: %display%} \'preONI 2005 runda #3 - solutii\':preoni-2005/runda-3/solutii\r\n*{display: %display%} \'preONI 2005 runda #2 - solutii\':preoni-2005/runda-2/solutii\r\n*{display: %display%} \'preONI 2005 runda #1 - solutii\':preoni-2005/runda-1/solutii\r\n*{display: %display%} \'Happy Coding 3 [2006]\':happy-coding-2006/solutii\r\n*{display: %display%} \'Happy Coding 2 [2005]\':happy-coding-2005-2/solutii\r\n*{display: %display%} \'Happy Coding 1 [2005]\':happy-coding-2005-1/solutii\r\n*{display: %display%} \'Concursul Agora - Etapa Finala - Solutii\':agora-finala/solutii\r\n*{display: %display%} \'Doua probleme de la runda 6 a concursului Algoritmus\':doua-probleme-de-la-runda-6-a-concursului-algoritmus\r\n*{display: %display%} \'USACO dec 2005, divizia GOLD\':usaco-dec-2005-divizia-gold \r\n*{display: %display%} \'USACO nov 2005, divizia GOLD\':usaco-nov-2005-divizia-gold\r\n*{display: %display%} \'USACO oct 2005, divizia GOLD\':usaco-oct-2005-divizia-gold\r\n*{display: %display%} \'USACO ian 2005, divizia GOLD\':usaco-ian-2005-divizia-gold\r\n*{display: %display%} \'USACO dec 2004, divizia GOLD\':usaco-dec-2004-divizia-gold\r\n*{display: %display%} \'Solutiile oficiale pentru Concursul &quot;de incalzire&quot;\':warm-up-2004/solutii',2044,'protected',NULL,NULL),('implica-te/arhiva-educationala','Arhiva Educationala','2008-02-23 13:13:01','2009-12-21 08:19:08','h1. Arhiva educationala ==Stars(rating=\"5\")==\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie. Mai multe despre acest proiect gasiti \'aici\':propuneri/6-arhiva-educationala.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Cum ne poti ajuta?\':implica-te/arhiva-educationala#cum\r\n* \'Echipa implicata in proiect\':implica-te/arhiva-educationala#echipa\r\n* \'Documentatie\':implica-te/arhiva-educationala#documentatie\r\n* \'Continutul arhivei\':implica-te/arhiva-educationala#probleme\r\n\r\nh2(#cum). Cum ne poti ajuta?\r\n\r\n1. Ofera sugestii la dezvoltarea proiectului.\r\n2. Contribuie cu feedback pentru a imbunatati calitatea problemelor existente.\r\n3. Vino cu idei pentru probleme noi.\r\n\r\nAjuta si tu la randul tau comunitatea infoarena! \r\n\r\nh2(#echipa). Echipa implicata in proiect\r\n\r\nEchipa care este implicata activ in acest proiect este alcatuita din urmatorii membri...\r\n\r\n* == user(user=\"Marius\" type=\"tiny\") ==, coordonator de proiect\r\n* == user(user=\"savim\" type=\"tiny\") ==\r\n* == user(user=\"cezarmocan\" type=\"tiny\") ==\r\n* == user(user=\"GavrilaVlad\" type=\"tiny\") ==\r\n* == user(user=\"mishu91\" type=\"tiny\") ==\r\n* == user(user=\"GheorgheMihai\" type=\"tiny\") ==\r\n\r\n\'Multumim celor care ne-au ajutat pana acum.\':implica-te/arhiva-educationala/membri-emeritus\r\n\r\nh2(#documentatie). Documentatie\r\n\r\nFiecare voluntar are obligatia sa citeasca urmatoarele materiale inainte de a putea trece efectiv la lucru:\r\n\r\n* \'Editare de probleme\':documentatie/editare-de-probleme\r\n* \'Ghid evaluator\':documentatie/ghid-evaluator\r\n* \'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala\r\n\r\nh2(#probleme). Continutul arhivei\r\n\r\nIn tabelul de mai jos se afla probleme la care se lucreaza in momentul de fata. Finalizarea lor reprezinta unul dintre $OKR$-urile din trimestrul IV, 2009. Pentru a va familiariza si cu restul obiectivelor din acest trimestru, cititi \'aici\':okr.\r\n\r\ntable(example). |_. Denumire problema|_. Voluntar|_. Finalizat|_. Review |\r\n| \'Cuplaj maxim de cost minim\':problema/cmcm | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Principiul includerii si excluderii\':problema/pinex | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Huffman\':problema/huffman | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| Algoritmul Bellman-Ford | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'2SAT\':problema/2sat | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Al K-lea termen Fibonacci - Matrici\':problema/kfib | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Lowest Common Ancestor\':problema/lca | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Statistici de ordine\':problema/sdo | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Parantezare optima de matrici\':problema/podm | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Treapuri\':problema/treapuri | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Ciclu hamiltonian | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Submulţimi\':problema/submultimi | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa minimă între două puncte în plan\':problema/cmap | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa maximă între două puncte în plan\':problema/cmdp | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n\r\nIn tabelul de mai jos se afla sugestii privind algoritmii care trebuie sa se gaseasca sub forma de probleme in arhiva educationala. Puteti veni oricand cu propuneri si sugestii de probleme noi pe \"forum\":/forum/index.php?topic=3401.0.\r\n\r\ntable(example). |_. Denumire problema|_. Categoria|\r\n|Knapsack|Programare dinamica|\r\n|NIM|Teoria jocurilor|\r\n|Sprague-Grundy|Teoria jocurilor|\r\n|Algoritmul lui Gauss|Matematica|\r\n|Numerele lui Stirling|Matematica|\r\n| Principiul lui Dirichlet | Matematică |\r\n| Numărul (şi suma) divizorilor unui număr natural | Matematică |\r\n|Problema de acoperire|Programare dinamica + Backtracking|\r\n|Algoritmul Stoer-Wagner|Algoritmi pe grafuri|\r\n|Heavy Path Decomposition|Algoritmi pe grafuri|\r\n|Arbore -> cod Prufer|Algoritmi pe grafuri|\r\n|Cod Prufer -> arbore|Algoritmi pe grafuri|\r\n|Distanta maxima intre 2 noduri intr-un arbore|Algoritmi pe grafuri|\r\n|Siruri de sufixe|Siruri de caractere|\r\n|Arbori de sufixe|Siruri de caractere|\r\n|Automate - Aho Corasick|Siruri de caractere|\r\n|Arbori de intervale aplicatie 1|Structuri de date|\r\n|Arbori de intervale aplicatie 2|Structuri de date|\r\n|Arbori de intervale aplicatie 3|Structuri de date|\r\n|Arbori de intervale aplicatie 4|Structuri de date|\r\n|Algoritmi {$O(sqrtN)$}|Structuri de date|\r\n|Ortogonal Range Search|Structuri de date|\r\n|Aria unui poligon|Geometrie|\r\n|Intersectia a doua drepte|Geometrie|\r\n|Punct in poligon|Geometrie|\r\n|Punct in poligon convex|Geometrie|\r\n|Diagrame Voronoi|Geometrie|\r\n|Minimum enclosing circle|Geometrie|\r\n|Sortare prin numarare|Diverse|\r\n|RadixSort|Diverse|\r\n|Interclasarea a doi vectori sortati|Diverse|\r\n|Operatii pe numere mari|Diverse|\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"61\")==',3146,'protected',NULL,NULL),('implica-te/scrie-articole','Scrie articole','2007-03-28 22:23:46','2009-12-26 23:10:49','h1. Scrie articole ==Stars(rating=\"4\")==\r\n\r\nFolosind modelul de \'wiki\':documentatie/wiki, infoarena ofera sansa tuturor membrilor sai sa contribuie la realizarea de articole sau la imbunatatirea celor existente. Daca vrei sa afli mai multe despre conceptul de wiki intra \'aici\':http://en.wikipedia.org/wiki/Wiki, iar daca vrei sa contribui la acesta initiativa citeste mai jos ce trebuie sa faci.\r\n\r\nh2. De ce m-as baga?\r\n\r\n* O cariera in cercetare in informatica poate debuta cu niste articole online!\r\n* Vei invata care sunt elementele cheie pentru a scrie un articol.\r\n* Vei invata pe altii ceea ce stii, asa cum probabil si tu ai invatat din articolele deja \'existente\':articole.\r\n\r\nh2. Ce pot sa fac?\r\n\r\nDe-a lungul timpului, utilizatorii infoarena si-au manifestat interesul in a scrie articole pentru intreaga comunitate. In momentul de fata ne concentram eforturile atat pe completarea si aducerea la o forma prezentabila a acestor articole vechi, cat si pe scrierea de articole noi. Sunt 3 moduri in care poti contribui:\r\n\r\nh3. 1. Ajuta-ne la ce lucram acum\r\n\r\nIn tabelul de mai jos poti gasi articolele incepute, impreuna cu stadiul in care se gaseste fiecare. Daca esti dornic sa ne ajuti, alege-ti unul din articolele de care nu se ocupa nimeni si ia legatura cu coordonatorul proiectului ca sa afli ce mai e de facut la el.\r\n\r\ntable. |_. Titlu |_. Autor |_. Stadiu |_. Voluntar(i) |\r\n| \'Probleme de taietura\':probleme-de-taietura | ==user(user=\"Cosmin\" type=\"tiny\")== | ÎN LUCRU | ==user(user=\"Marius\" type=\"tiny\")== |\r\n| \'Transformari geometrice\':transformari-geometrice | ==user(user=\"Cosmin\" type=\"tiny\")== | ÎN LUCRU |  ==user(user=\"Marius\" type=\"tiny\")== |\r\n| \'Optimizarea programelor folosind operaţii pe biţi\':http://www.google.ro/url?sa=t&source=web&ct=res&cd=3&ved=0CBIQFjAC&url=http%3A%2F%2Fwww.ginfo.ro%2Frevista%2F14_5%2Ffocus.pdf&rct=j&q=opera%C5%A3ii+pe+bi%C5%A3i+cosmin+negru%C5%9Feri&ei=yqcuS7ndB5CUmAOts7yKCQ&usg=AFQjCNEkRFe0NcETCbGQYtwxtZiLl6-lIQ&sig2=u4zPps2-woQOLMdbRDyM4A | ==user(user=\"Cosmin\" type=\"tiny\")==  | ÎN LUCRU | ==user(user=\"gheorghemihai\" type=\"tiny\")== |\r\n| \'Arborele componentelor biconexe şi al nodurilor critice\':http://infoarena.ro/downloads?action=download&file=arborele_componentelor_biconexe_si_al_nodurilor_critice.doc&safe_only=false | ==user(user=\"mugurelionut\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Algoritmi de flux maxim în reţele\':http://infoarena.ro/downloads?action=download&file=flux_maxim_in_retele.doc&safe_only=false | ==user(user=\"mugurelionut\" type=\"tiny\")== | NETRANSCRIS | ? |\r\n| \'Tehnici avansate de programare dinamică\':pd | ==user(user=\"Zeus\" type=\"tiny\")== | ÎN LUCRU | ==user(user=\"Zeus\" type=\"tiny\")== |\r\n\r\nh3. 2. Preia si dezvolta un subiect mai vechi\r\n\r\nAi nevoie de un impuls pentru a-ti da drumul la scris? Sunt cateva articole pe infoarena incepute, dar abandonate, precum si niste schite. Poti folosi ideile de start ale autorului si il poti transforma intr-un articol bine documentat. In plus, poti lua legatura cu autorul initial si poti afla viziunea sa asupra subiectului. Iata o lista de articole abandonate si de schite:\r\n\r\ntable. |_. Titlu |_. Autor initial |\r\n| Programare dinamica / memoizare (trading space for time): \'link1\':programare-dinamica | ==user(user=\"Zeus\" type=\"tiny\")== |\r\n| \'Arbori indexati binar\':aib | ==user(user=\"Skipy\" type=\"tiny\")== |\r\n| \'Dinic\':dinic | ==user(user=\"alexandru.mosoi\" type=\"tiny\")== |\r\n| \'Probleme de geometrie si solutii\':downloads?geometrie.zip | ==user(user=\"Cosmin\" type=\"tiny\")== |\r\n| \'Flux si cuplaj\':flux-si-cuplaj | ==user(user=\"blasterz\" type=\"tiny\")== |\r\n| \'Teoria jocurilor\':teoria-jocurilor | ==user(user=\"filipb\" type=\"tiny\")== |\r\n| \'Psihologia concursurilor de informatica - Lucrul cu numere mari\':lucrul-cu-nr-mari | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| Psihologia concursurilor de informatica - Lucrul cu structuri mari de date | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| Psihologia concursurilor de informatica - Probleme de concurs | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| \'Notiuni de geometrie analitica si aplicatii\':notiuni-de-geometrie-si-aplicatii | ==user(user=\"devilkind\" type=\"tiny\")== \r\n==user(user=\"sima_cotizo\" type=\"tiny\")== |\r\n| \'Diagrame Voronoi\':voronoi | ==user(user=\"cata00\" type=\"tiny\")== |\r\n| \'Algoritmi de baleiere\':algoritmi-de-baleiere | ==user(user=\"stef2n\" type=\"tiny\")== |\r\n\r\nh3. 3. Creeaza ceva nou\r\n\r\nAi o idee noua de articol? Sau pur si simplu vrei sa te apuci de la 0 de un subiect? Ia legatura cu coordonatorul proiectului sau anunta pe \'forum\':forum. Este posibil sa primesti ajutor si de la alti utilizatori infoarena. In plus, noi iti propunem o lista de articole pe care ni le-am dori scrise, in caz ca nu te-ai decis asupra temei:\r\n\r\ntable. |_. Titlu |\r\n| Depanarea programelor C/C++ cu gdb in Linux |\r\n| Testarea surselor in timp de concurs sau Cum sa reduci buselile |\r\n| Tutorial LaTeX |\r\n\r\nNe rezervam dreptul sa nu acceptam sau sa stergem articolele care nu se potrivesc cu tema si target-ul site-ului.\r\n\r\nh2. Cu cine iau legatura?\r\n\r\nCu coordonatorul proiectului:\r\n\r\n* ==user(user=\"Marius\" type=\"tiny\")==\r\n\r\nSau daca vrei sa contribui la un articol la care se lucreaza deja, poti vorbi direct cu voluntarii care se ocupa de el.\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"43\")==',3146,'public',NULL,NULL),('operatii-pe-biti','Operaţii pe biţi','2009-12-27 10:45:16','2009-12-27 14:57:53','h1. Operaţii pe biţi\r\n\r\n== include(page=\"template/implica-te/scrie-articole\" user_id=\"GheorgheMihai\") ==\r\n\r\n(Categoria _Algoritmi_, Autor _Cosmin Negruşeri_)\r\n\r\nÎn cadrul acestui articol vă vom prezenta câteva metode prin care programele se pot optimiza dacă utilizăm eficient operaţiile pe biţi sau folosim operaţii pe biţi în locuri în care, la prima vedere, nu s-ar părea că ar fi necesare.\r\n\r\nDe cele mai multe ori, atât în concursuri cât şi în viaţa de zi cu zi a programatorului, atunci când implementăm o metodă care este folosită de o aplicaţie şi vrem să facem această metodă eficientă ca timp de execuţie, suntem învăţaţi din şcoală (sau ar trebui sã fim învăţaţi, chiar dacă unii dintre profesori consideră că cel mai important algoritm învăţat în liceu este _backtraking_-ul, soluţia tuturor problemelor) să ne uităm la complexitatea algoritmului implementat şi dacă observăm că în practică algoritmul este mai încet decât ne dorim noi să fie să încercăm să găsim un algoritm cu un ordin de complexitate mai mic.\r\n\r\nNu trebuie să uităm că ceea ce numim complexitatea unui algoritm este o aproximare a vitezei unui algoritm şi nu o măsură absolută. Pentru dimensiuni mici ale datelor, câteodată nu se observă diferenţă dintre $O(n)$ şi $O(n · log n)$ sau $O(n^3/2^)$. Mie personal mi s-a întâmplat ca la implementarea soluţiei unei probleme care în engleză se numeşte \"_Bottleneck Minimal Spanning Tree_\" să observ că rezolvarea în $O(m · log m)$ (folosind algoritmul de găsire a arborelui parţial de cost minim al lui Kruskal) să fie mai rapidă decât rezolvarea mai laborioasă în $O(m)$ a acestei probleme. Deci trebuie dată o atenţie egală cu cea acordată complexităţii algoritmului şi dimensiunii factorilor constanţi care apar.\r\n\r\nÎn continuare vom încerca să găsim soluţii mai rapide decât cele naive pentru unele operaţii de bază (toate operaţiile vor fi implementate pentru întregi pozitivi reprezentaţi pe 32 de biţi).\r\n\r\nh2. Aplicaţia #1\r\n\r\nbq. Să se determine numărul de biţi de 1 din reprezentarea binară a lui $n$.\r\n\r\nh3. Rezolvare\r\n\r\nRezolvarea naivă a acestei probleme ar consta în parcurgerea secvenţială a biţilor lui n. În continuare vă prezint această rezolvare:\r\n==code(cpp)|\r\nint count(long n){\r\n  int num = 0;\r\n  for (int i = 0; i < 32; i++)\r\n     if (n & (1 << i)) num++;\r\n  return num;\r\n}\r\n==\r\n\r\nDacă ne uităm cu atenţie şi analizăm rezultatul operaţiei $n & (n - 1)$ putem obţine o soluţie mai bună. Să luăm un exemplu:\r\n$n           = 11011101010000{~2~}$\r\n$n - 1       = 11011101001111{~2~}$\r\n$n & (n - 1) = 11011101000000{~2~}$\r\n\r\nSe vede clar de aici că efectul operaţiei $n & (n - 1)$ este anularea celui mai nesemnificativ bit cu valoarea 1.\r\nDe aici ideea algoritmului:\r\n==code(cpp)|\r\nint count(long n){\r\n   int num = 0;\r\n   if (n)\r\n      while (n &= n - 1) num++;\r\n   return num;\r\n}\r\n==\r\n\r\nDar este acest algoritm mai rapid? Am testat pentru toate numerele de la $1$ la $2^24^$ şi rezultatele au fost $2,654$ secunde folosind metoda naivă şi $0.821$ folosind a doua metodă.\r\nRezultatul mult mai bun al celei de-a doua metode se bazează în principal pe faptul că ea execută un număr de paşi egali cu numărul de biţi cu valoarea 1 din număr, deci în medie jumătate din numărul de paşi efectuaţi de prima metodă.\r\n\r\nh2. Aplicaţia #2\r\n\r\nbq. Să se determine paritatea numărului de biţi de 1 din reprezentarea binară a unui număr $n$.\r\n\r\nh3. Rezolvare\r\n\r\nDin cele prezentate mai sus se pot determina două metode evidente:\r\n==code(cpp)|\r\nint parity(long n){\r\n  int num = 0;\r\n  for (int i = 0; i < 32; i++)\r\n     if (n & (1 << i)) num ^= 1;\r\n  return num;\r\n}\r\n==\r\n\r\n==code(cpp)|\r\nint parity(long n){\r\n   int num = 0;\r\n   if (n)\r\n      while (n &= n - 1) num ^= 1;\r\n   return num;\r\n}\r\n==\r\n\r\nPutem obţine o a treia rezolvare făcând câteva observaţii pe un exemplu:\r\nConsiderăm $n = 11011011{~2~}$. Rezultatul căutat este dat de valoarea @1 ^ 1 ^ 0 ^ 1 ^ 1 ^ 0 ^ 1 ^ 1@.\r\nÎmpărţim pe n în partea lui superioară şi partea lui inferioară:\r\n1 1 0 1 ^ 1 0 1 1 = 0 1 1 0\r\nAplicăm asupra rezultatului acelaşi procedeu:\r\n0 1 ^ 1 0 = 1 1\r\nşi\r\n1 ^ 1 = 0\r\n\r\nSă scriem algoritmul care reiese din acest exemplu, luând în considerare faptul că numărul n este reprezentat pe 32 de biţi:\r\n==code(cpp)|\r\nint parity(long n){\r\n   n = ((0xFFFF0000 & n) >> 16) ^ (n & 0xFFFF);\r\n   n = ((0xFF00 & n) >> 8) ^ (n & 0xFF);\r\n   n = ((0xF0 & n) >> 4) ^ (n & 0xF);\r\n   n = ((12 & n) >> 2) ^ (n & 3);\r\n   n = ((2 & n) >> 1) ^ (n & 1);\r\n   return n;\r\n}\r\n==\r\n\r\nDeşi constanta multiplicativa este mai mare, numărul de operaţii are ordin logaritmic faţă de numărul de biţi ai unui cuvânt al calculatorului.\r\n\r\n\r\n',7148,'public',NULL,NULL),('runda/star_trek/clasament','Clasament star_trek','2009-03-29 14:24:54','2009-03-29 14:24:54','h1. Clasament ==roundparam(round_id=\"star_trek\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"star_trek\")==',8689,'round: star_trek',NULL,NULL),('implica-te/arhiva-educationala','Arhiva Educationala','2008-02-23 13:13:01','2010-01-03 16:41:35','h1. Arhiva educationala ==Stars(rating=\"5\")==\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie. Mai multe despre acest proiect gasiti \'aici\':propuneri/6-arhiva-educationala.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Cum ne poti ajuta?\':implica-te/arhiva-educationala#cum\r\n* \'Echipa implicata in proiect\':implica-te/arhiva-educationala#echipa\r\n* \'Documentatie\':implica-te/arhiva-educationala#documentatie\r\n* \'Continutul arhivei\':implica-te/arhiva-educationala#probleme\r\n\r\nh2(#cum). Cum ne poti ajuta?\r\n\r\n1. Ofera sugestii la dezvoltarea proiectului.\r\n2. Contribuie cu feedback pentru a imbunatati calitatea problemelor existente.\r\n3. Vino cu idei pentru probleme noi.\r\n\r\nAjuta si tu la randul tau comunitatea infoarena! \r\n\r\nh2(#echipa). Echipa implicata in proiect\r\n\r\nEchipa care este implicata activ in acest proiect este alcatuita din urmatorii membri...\r\n\r\n* == user(user=\"Marius\" type=\"tiny\") ==, coordonator de proiect\r\n* == user(user=\"savim\" type=\"tiny\") ==\r\n* == user(user=\"cezarmocan\" type=\"tiny\") ==\r\n* == user(user=\"GavrilaVlad\" type=\"tiny\") ==\r\n* == user(user=\"mishu91\" type=\"tiny\") ==\r\n* == user(user=\"GheorgheMihai\" type=\"tiny\") ==\r\n\r\n\'Multumim celor care ne-au ajutat pana acum.\':implica-te/arhiva-educationala/membri-emeritus\r\n\r\nh2(#documentatie). Documentatie\r\n\r\nFiecare voluntar are obligatia sa citeasca urmatoarele materiale inainte de a putea trece efectiv la lucru:\r\n\r\n* \'Editare de probleme\':documentatie/editare-de-probleme\r\n* \'Ghid evaluator\':documentatie/ghid-evaluator\r\n* \'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala\r\n\r\nh2(#probleme). Continutul arhivei\r\n\r\nIn tabelul de mai jos se afla probleme la care se lucreaza in momentul de fata. Finalizarea lor reprezinta unul dintre $OKR$-urile din trimestrul IV, 2009. Pentru a va familiariza si cu restul obiectivelor din acest trimestru, cititi \'aici\':okr.\r\n\r\ntable(example). |_. Denumire problema|_. Voluntar|_. Finalizat|_. Review |\r\n| \'Cuplaj maxim de cost minim\':problema/cmcm | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Principiul includerii si excluderii\':problema/pinex | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Huffman\':problema/huffman | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Algoritmul Bellman-Ford\':problema/bellmanford | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'2SAT\':problema/2sat | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Al K-lea termen Fibonacci - Matrici\':problema/kfib | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Lowest Common Ancestor\':problema/lca | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Statistici de ordine\':problema/sdo | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Parantezare optima de matrici\':problema/podm | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Treapuri\':problema/treapuri | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Ciclu hamiltonian | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Submulţimi\':problema/submultimi | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa minimă între două puncte în plan\':problema/cmap | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa maximă între două puncte în plan\':problema/cmdp | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n\r\nIn tabelul de mai jos se afla sugestii privind algoritmii care trebuie sa se gaseasca sub forma de probleme in arhiva educationala. Puteti veni oricand cu propuneri si sugestii de probleme noi pe \"forum\":/forum/index.php?topic=3401.0.\r\n\r\ntable(example). |_. Denumire problema|_. Categoria|\r\n|Knapsack|Programare dinamica|\r\n|NIM|Teoria jocurilor|\r\n|Sprague-Grundy|Teoria jocurilor|\r\n|Algoritmul lui Gauss|Matematica|\r\n|Numerele lui Stirling|Matematica|\r\n| Principiul lui Dirichlet | Matematică |\r\n| Numărul (şi suma) divizorilor unui număr natural | Matematică |\r\n|Problema de acoperire|Programare dinamica + Backtracking|\r\n|Algoritmul Stoer-Wagner|Algoritmi pe grafuri|\r\n|Heavy Path Decomposition|Algoritmi pe grafuri|\r\n|Arbore -> cod Prufer|Algoritmi pe grafuri|\r\n|Cod Prufer -> arbore|Algoritmi pe grafuri|\r\n|Distanta maxima intre 2 noduri intr-un arbore|Algoritmi pe grafuri|\r\n|Siruri de sufixe|Siruri de caractere|\r\n|Arbori de sufixe|Siruri de caractere|\r\n|Automate - Aho Corasick|Siruri de caractere|\r\n|Arbori de intervale aplicatie 1|Structuri de date|\r\n|Arbori de intervale aplicatie 2|Structuri de date|\r\n|Arbori de intervale aplicatie 3|Structuri de date|\r\n|Arbori de intervale aplicatie 4|Structuri de date|\r\n|Algoritmi {$O(sqrtN)$}|Structuri de date|\r\n|Ortogonal Range Search|Structuri de date|\r\n|Aria unui poligon|Geometrie|\r\n|Intersectia a doua drepte|Geometrie|\r\n|Punct in poligon|Geometrie|\r\n|Punct in poligon convex|Geometrie|\r\n|Diagrame Voronoi|Geometrie|\r\n|Minimum enclosing circle|Geometrie|\r\n|Sortare prin numarare|Diverse|\r\n|RadixSort|Diverse|\r\n|Interclasarea a doi vectori sortati|Diverse|\r\n|Operatii pe numere mari|Diverse|\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"61\")==',3146,'protected',NULL,NULL),('implica-te/arhiva-educationala','Arhiva Educationala','2008-02-23 13:13:01','2010-01-04 13:07:52','h1. Arhiva educationala ==Stars(rating=\"5\")==\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie. Mai multe despre acest proiect gasiti \'aici\':propuneri/6-arhiva-educationala.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Cum ne poti ajuta?\':implica-te/arhiva-educationala#cum\r\n* \'Echipa implicata in proiect\':implica-te/arhiva-educationala#echipa\r\n* \'Documentatie\':implica-te/arhiva-educationala#documentatie\r\n* \'Continutul arhivei\':implica-te/arhiva-educationala#probleme\r\n\r\nh2(#cum). Cum ne poti ajuta?\r\n\r\n1. Ofera sugestii la dezvoltarea proiectului.\r\n2. Contribuie cu feedback pentru a imbunatati calitatea problemelor existente.\r\n3. Vino cu idei pentru probleme noi.\r\n\r\nAjuta si tu la randul tau comunitatea infoarena! \r\n\r\nh2(#echipa). Echipa implicata in proiect\r\n\r\nEchipa care este implicata activ in acest proiect este alcatuita din urmatorii membri...\r\n\r\n* == user(user=\"Marius\" type=\"tiny\") ==, coordonator de proiect\r\n* == user(user=\"savim\" type=\"tiny\") ==\r\n* == user(user=\"cezarmocan\" type=\"tiny\") ==\r\n* == user(user=\"GavrilaVlad\" type=\"tiny\") ==\r\n* == user(user=\"mishu91\" type=\"tiny\") ==\r\n* == user(user=\"GheorgheMihai\" type=\"tiny\") ==\r\n\r\n\'Multumim celor care ne-au ajutat pana acum.\':implica-te/arhiva-educationala/membri-emeritus\r\n\r\nh2(#documentatie). Documentatie\r\n\r\nFiecare voluntar are obligatia sa citeasca urmatoarele materiale inainte de a putea trece efectiv la lucru:\r\n\r\n* \'Editare de probleme\':documentatie/editare-de-probleme\r\n* \'Ghid evaluator\':documentatie/ghid-evaluator\r\n* \'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala\r\n\r\nh2(#probleme). Continutul arhivei\r\n\r\nIn tabelul de mai jos se afla probleme la care se lucreaza in momentul de fata. Finalizarea lor reprezinta unul dintre $OKR$-urile din trimestrul IV, 2009. Pentru a va familiariza si cu restul obiectivelor din acest trimestru, cititi \'aici\':okr.\r\n\r\ntable(example). |_. Denumire problema|_. Voluntar|_. Finalizat|_. Review |\r\n| \'Cuplaj maxim de cost minim\':problema/cmcm | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Principiul includerii si excluderii\':problema/pinex | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| Arbori de intervale: creste valoarea fiecarui element \r\n  dintr-un interval cu x (update) si intreaba care e suma \r\n  elementelor dintr-un interval (query) | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Arbori de intervale: creste valoarea fiecarui element\r\n  dintr-un interval cu x (update) si intreaba care e \r\n  minimul/maximul elementelor dintr-un interval (query) | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Arbori de intervale: seteaza valoarea fiecarui element\r\n  dintr-un interval la x (update) si intreaba care e suma\r\n  elementelor dintr-un interval (query) | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Arbori de intervale: seteaza valoarea fiecarui element\r\n  dintr-un interval la x (update) si intreaba care e\r\n  minimul/maximul elementelor dintr-un interval (query) | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Huffman\':problema/huffman | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Algoritmul Bellman-Ford\':problema/bellmanford | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'2SAT\':problema/2sat | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Al K-lea termen Fibonacci - Matrici\':problema/kfib | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Lowest Common Ancestor\':problema/lca | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Statistici de ordine\':problema/sdo | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Parantezare optima de matrici\':problema/podm | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Treapuri\':problema/treapuri | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| Ciclu hamiltonian | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Submulţimi\':problema/submultimi | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa minimă între două puncte în plan\':problema/cmap | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa maximă între două puncte în plan\':problema/cmdp | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n\r\nIn tabelul de mai jos se afla sugestii privind algoritmii care trebuie sa se gaseasca sub forma de probleme in arhiva educationala. Puteti veni oricand cu propuneri si sugestii de probleme noi pe \"forum\":/forum/index.php?topic=3401.0.\r\n\r\ntable(example). |_. Denumire problema|_. Categoria|\r\n|Knapsack|Programare dinamica|\r\n|NIM|Teoria jocurilor|\r\n|Sprague-Grundy|Teoria jocurilor|\r\n|Algoritmul lui Gauss|Matematica|\r\n|Numerele lui Stirling|Matematica|\r\n| Principiul lui Dirichlet | Matematică |\r\n| Numărul (şi suma) divizorilor unui număr natural | Matematică |\r\n|Problema de acoperire|Programare dinamica + Backtracking|\r\n|Algoritmul Stoer-Wagner|Algoritmi pe grafuri|\r\n|Heavy Path Decomposition|Algoritmi pe grafuri|\r\n|Arbore -> cod Prufer|Algoritmi pe grafuri|\r\n|Cod Prufer -> arbore|Algoritmi pe grafuri|\r\n|Distanta maxima intre 2 noduri intr-un arbore|Algoritmi pe grafuri|\r\n|Siruri de sufixe|Siruri de caractere|\r\n|Arbori de sufixe|Siruri de caractere|\r\n|Automate - Aho Corasick|Siruri de caractere|\r\n|Algoritmi {$O(sqrtN)$}|Structuri de date|\r\n|Ortogonal Range Search|Structuri de date|\r\n|Aria unui poligon|Geometrie|\r\n|Intersectia a doua drepte|Geometrie|\r\n|Punct in poligon|Geometrie|\r\n|Punct in poligon convex|Geometrie|\r\n|Diagrame Voronoi|Geometrie|\r\n|Minimum enclosing circle|Geometrie|\r\n|Sortare prin numarare|Diverse|\r\n|RadixSort|Diverse|\r\n|Interclasarea a doi vectori sortati|Diverse|\r\n|Operatii pe numere mari|Diverse|\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"61\")==',3146,'protected',NULL,NULL),('planificare/sedinta-20100112','Ședință 2010-01-12','2010-01-05 19:04:00','2010-01-08 10:54:03','h1. Şedinţă 2010-01-12\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Marti* la ora *18:30* la ?.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20091126 | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada Runda 3 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| OKR | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Evaluator | ? |\r\n| Doi la suta | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n* Others:\r\n** Blogpost-uri cu infoarena in 2009.\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* &hellip;\r\n\r\nh2(#notite). Notite\r\n\r\n* &hellip;\r\n',1792,'protected',NULL,NULL),('implica-te/arhiva-educationala','Arhiva Educationala','2008-02-23 13:13:01','2010-01-11 17:49:38','h1. Arhiva educationala ==Stars(rating=\"5\")==\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie. Mai multe despre acest proiect gasiti \'aici\':propuneri/6-arhiva-educationala.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Cum ne poti ajuta?\':implica-te/arhiva-educationala#cum\r\n* \'Echipa implicata in proiect\':implica-te/arhiva-educationala#echipa\r\n* \'Documentatie\':implica-te/arhiva-educationala#documentatie\r\n* \'Continutul arhivei\':implica-te/arhiva-educationala#probleme\r\n\r\nh2(#cum). Cum ne poti ajuta?\r\n\r\n1. Ofera sugestii la dezvoltarea proiectului.\r\n2. Contribuie cu feedback pentru a imbunatati calitatea problemelor existente.\r\n3. Vino cu idei pentru probleme noi.\r\n\r\nAjuta si tu la randul tau comunitatea infoarena! \r\n\r\nh2(#echipa). Echipa implicata in proiect\r\n\r\nEchipa care este implicata activ in acest proiect este alcatuita din urmatorii membri...\r\n\r\n* == user(user=\"Marius\" type=\"tiny\") ==, coordonator de proiect\r\n* == user(user=\"savim\" type=\"tiny\") ==\r\n* == user(user=\"cezarmocan\" type=\"tiny\") ==\r\n* == user(user=\"GavrilaVlad\" type=\"tiny\") ==\r\n* == user(user=\"mishu91\" type=\"tiny\") ==\r\n* == user(user=\"GheorgheMihai\" type=\"tiny\") ==\r\n\r\n\'Multumim celor care ne-au ajutat pana acum.\':implica-te/arhiva-educationala/membri-emeritus\r\n\r\nh2(#documentatie). Documentatie\r\n\r\nFiecare voluntar are obligatia sa citeasca urmatoarele materiale inainte de a putea trece efectiv la lucru:\r\n\r\n* \'Editare de probleme\':documentatie/editare-de-probleme\r\n* \'Ghid evaluator\':documentatie/ghid-evaluator\r\n* \'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala\r\n\r\nh2(#probleme). Continutul arhivei\r\n\r\nIn tabelul de mai jos se afla probleme la care se lucreaza in momentul de fata. Finalizarea lor reprezinta unul dintre $OKR$-urile din trimestrul IV, 2009. Pentru a va familiariza si cu restul obiectivelor din acest trimestru, cititi \'aici\':okr.\r\n\r\ntable(example). |_. Denumire problema|_. Voluntar|_. Finalizat|_. Review |\r\n| \'Cuplaj maxim de cost minim\':problema/cmcm | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Principiul includerii si excluderii\':problema/pinex | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Arbori de intervale (aplicaţie cu 4 tipuri de operaţii)\':problema/arbint2 | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Huffman\':problema/huffman | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Algoritmul Bellman-Ford\':problema/bellmanford | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'2SAT\':problema/2sat | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Al k-lea termen Fibonacci - Matrici\':problema/kfib | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Punct în poligon oarecare\':problema/pinpo | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Lowest Common Ancestor\':problema/lca | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Statistici de ordine\':problema/sdo | == user(user=\"mishu91\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Parantezare optima de matrici\':problema/podm | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Treapuri\':problema/treapuri | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Ciclu hamiltonian de cost minim\':problema/hamilton | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Submulţimi\':problema/submultimi | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa minimă între două puncte în plan\':problema/cmap | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa maximă între două puncte în plan\':problema/cmdp | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Arbori de căutare\':problema/arbcautare | ==user(user=\"bogdan2412\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n\r\nIn tabelul de mai jos se afla sugestii privind algoritmii care trebuie sa se gaseasca sub forma de probleme in arhiva educationala. Puteti veni oricand cu propuneri si sugestii de probleme noi pe \"forum\":/forum/index.php?topic=3401.0.\r\n\r\ntable(example). |_. Denumire problema|_. Categoria|\r\n|Knapsack|Programare dinamica|\r\n|NIM|Teoria jocurilor|\r\n|Sprague-Grundy|Teoria jocurilor|\r\n|Algoritmul lui Gauss|Matematica|\r\n|Numerele lui Stirling|Matematica|\r\n| Principiul lui Dirichlet | Matematică |\r\n| Numărul (şi suma) divizorilor unui număr natural | Matematică |\r\n|Problema de acoperire|Programare dinamica + Backtracking|\r\n|Algoritmul Stoer-Wagner|Algoritmi pe grafuri|\r\n|Heavy Path Decomposition|Algoritmi pe grafuri|\r\n|Arbore -> cod Prufer|Algoritmi pe grafuri|\r\n|Cod Prufer -> arbore|Algoritmi pe grafuri|\r\n|Distanta maxima intre 2 noduri intr-un arbore|Algoritmi pe grafuri|\r\n|Siruri de sufixe|Siruri de caractere|\r\n|Arbori de sufixe|Siruri de caractere|\r\n|Automate - Aho Corasick|Siruri de caractere|\r\n|Algoritmi {$O(sqrtN)$}|Structuri de date|\r\n|Ortogonal Range Search|Structuri de date|\r\n| \'Aria unui poligon\':problema/ariapoli |Geometrie|\r\n|Intersectia a doua drepte|Geometrie|\r\n|Punct in poligon convex|Geometrie|\r\n|Diagrame Voronoi|Geometrie|\r\n|Minimum enclosing circle|Geometrie|\r\n|Sortare prin numarare|Diverse|\r\n|RadixSort|Diverse|\r\n| \'Interclasarea a doi vectori sortati\':problema/interclas |Diverse|\r\n|Operatii pe numere mari|Diverse|\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"61\")==',3146,'protected',NULL,NULL),('algoritmiada-2010','Algoritmiada 2010 - olimpiada algoritmilor, Ediția a II-a','2009-10-25 13:38:22','2009-11-26 21:20:51','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh2. Despre Algoritmiada\r\n\r\nÎn acest an, _infoarena_ revine cu cea de-a doua ediţie a concursului de programare Algoritmiada. Algoritmiada este unicul concurs din România unde pot participa tinerii pasionaţi de informatică de toate vârstele: de la elevi de gimnaziu până la studenţi şi doctoranzi.\r\n\r\nConcursul are patru grupe valorice: gimnaziu, clasele 9-10, clasele 11-12, studenţi (inclusiv masteranzi şi doctoranzi). Participanţii vor avea ocazia să-şi demonstreze talentul, cunostinţele şi ascuţimea minţii în 4 probe online urmând ca cei mai buni sa fie invitaţi la finala on-site.\r\n\r\nh2. Cum particip?\r\n\r\nPentru a participa la concurs trebuie să fii \'înregistrat\':register pe site-ul nostru.\r\n\r\nÎn ziua de concurs intri pe site, citeşti problemele de la grupa ta de vârstă şi trimiţi soluţiile înainte de expirarea timpului. \'Evaluatorul\':documentatie/evaluator nostru iţi va testa automat soluţiile iar punctajul îl vei afla la sfârşitul concursului. Tot atunci vei putea consulta clasamentul pentru a vedea ce au făcut şi ceilalţi concurenţi.\r\n\r\nh3. Prima dată pe _infoarena_?\r\n\r\n_infoarena_ ajută elevi şi studenţi să devină excelenţi în informatică! Gratuit ;) Citeşte \'ghidul utilizatorului\':documentatie/pentru-utilizatori şi află mai multe \'despre noi\':despre-infoarena.\r\n\r\nh2. Program\r\n\r\nFaceţi click pe titlul unei runde pentru informaţii detaliate.\r\n\r\ntable{width:50%}. |_. Runda |_. Data |_. Durata |\r\n| \'*Runda 1*\':algoritmiada-2010/runda-1 | *22 Noiembrie 2009, Duminică* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 2*\':algoritmiada-2010/runda-2 | *20 Decembrie 2009, Duminică* |=. *09^00^ - 13^00^* |\r\n| \'*Runda 3*\':algoritmiada-2010/runda-3 | *Februarie 2010* |=. &nbsp; |\r\n| \'*Runda 4*\':algoritmiada-2010/runda-4 | *Martie 2010* |=. &nbsp; |\r\n| \'*Runda Finală*\':algoritmiada-2010/runda-finala | *Aprilie 2010* |=. &nbsp; |\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('okr/20101','okr/20101','2010-01-12 18:29:40','2010-01-12 18:57:06','arhiva probleme - taguri, bagam doar probleme de la oni, joi si lot -> oji + tagging camp -> Stefan oji, Cosmin tagging camp\r\narhiva educationala - mai bagat cateva probleme -> Marius Stroe\r\norganizeaza concursuri - .com runda 2 -> Cosmin, Marmota\r\nalgoritmiada 2010 - Paul\r\nscrie articole - Marius\r\ndevelopment - Bogdan\r\nStrangere fonduri - Cosmin\r\nBlog - Prostu\r\nProstu ramane la calendar\r\nVideo articol -> Wefgef',2038,'public',NULL,NULL),('okr/20101','OKRs 2010Q1','2010-01-12 18:29:40','2010-01-13 14:55:59','h2. 2010Q1\r\n\r\nh3(#arhiva). Arhivele de probleme\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Adauga Probleme | ==user(user=\"stef2n\" type=\"tiny\")== | ==include(page=\"okr/20101/adauga-probleme\")== | . |\r\n| Tagging| ==user(user=\"gcosmin\" type=\"tiny\")== | ==include(page=\"okr/20101/tagging\")== | . |\r\n\r\nh3(#concursuri). Concursuri\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Organizeaza concursuri | ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n==user(user=\"gcosmin\" type=\"tiny\")== | ==include(page=\"okr/20101/organizeaza-concursuri\")== | . |\r\n| \'Algoritmiada 2010\':algoritmiada-2010 | ==user(user=\"pauldb\" type=\"tiny\")== | ==include(page=\"okr/20101/algoritmiada\")== | . |\r\n\r\nh3(#continut). Continut educational\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'Scrie articole\':implica-te/scrie-articole | ==user(user=\"marius\" type=\"tiny\")== | ==include(page=\"okr/20101/articole\")== | . |\r\n| \'Blog\':blog | ==user(user=\"prostu\" type=\"tiny\")== | ==include(page=\"okr/20101/blog\")== | . |\r\n\r\nh3(#development). Development\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| \'infoarena 2.x Stable\':http://hackers.devnet.ro/roadmap | ==user(user=\"bogdan2412\" type=\"tiny\")== | ==include(page=\"okr/20101/devel-ia2\")== | . |\r\n\r\nh3(#administrativ). Administrativ\r\n\r\n|_. Nume |_. Responsabil |_. OKR-uri |_. Nota |\r\n| Strangere fonduri | ==user(user=\"gcosmin\" type=\"tiny\")== | ==include(page=\"okr/20101/fund-raising\")== | . |',2038,'public',NULL,NULL),('utilizator/florian','Marcu Florian','2007-01-24 13:36:08','2009-11-17 18:48:19','h2. Despre mine...\r\n\r\n* elev la Colegiul National \"Roman-Voda\" din Roman, clasa a 11-a B,profil mate-info, profesori de info : Florin Moldovanu si Gavril Petru Florin.\r\n\r\nh2. Premii, reusite, castiguri,etc..\r\n\r\n* premii.cpp:40:error: \'reusita[]\' undeclarated ( first use in this function )\r\n\r\n\r\nh2. Prieteni pe infoarena \r\n\r\n* ==user(user=\"blasterz\" type=\"tiny\")== @\r\n* ==user(user=\"gabitzish1\" type=\"tiny\")== @\r\n* ==user(user=\"c_e_manu\" type=\"tiny\")== @\r\n* ==user(user=\"Pepelea_Flaviu\" type=\"tiny\")== @\r\n* ==user(user=\"Mishu91\" type=\"tiny\")== @\r\n* ==user(user=\"petro\" type=\"tiny\")== @\r\n* ==user(user=\"klamathix\" type=\"tiny\")== @\r\n* ==user(user=\"tabara\" type=\"tiny\")== @\r\n* ==user(user=\"mathboy\" type=\"tiny\")== @\r\n* ==user(user=\"nod_software\" type=\"tiny\")== @\r\n* ==user(user=\"raduzer\" type=\"tiny\")== @\r\n\r\n\r\n',5748,'public',NULL,NULL),('okr/20101/algoritmiada','okr/20101/algoritmiada','2010-01-15 00:27:27','2010-01-15 00:34:57','(okr)* Organizare Algoritmiada 2010, chestiuni generale\r\n** Crearea şi organizarea paginilor necesare pentru concurs\r\n\r\n(okr)* Organizare Algoritmiada 2010, Runda 3\r\n** Newsletter Runda 3\r\n** Blogpost Runda 3\r\n\r\n(okr)* Organizare Algoritmiada 2010, Runda 4\r\n** Newsletter Runda 4\r\n** Blogpost Runda 4\r\n\r\n(okr)* Organizare Algoritmiada 2010, Runda Finală (partea I)\r\n** Începerea demersurilor necesare pentru stabilirea locaţiei\r\n** Începerea demersurilor necesare pentru asigurarea cazării şi a mesei\r\n** Verificarea surselor participanţilor\r\n** Selectarea finaliştilor si trimiterea invitaţiilor',1792,'protected',NULL,NULL),('algoritmiada-2010/runda-3/studenti','Algoritmiada 2010 Runda 2, Studenti','2010-01-18 11:51:50','2010-01-18 11:51:50','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda2-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-2\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-2/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-2/11-12\r\n*(active) \'Studenti\':algoritmiada-2010/runda-2/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-2/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda2-studenti\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2010-runda2-studenti\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2010-runda2-studenti\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-2/studenti.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda2-studenti\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1490,'round: algoritmiada2010-runda2-studenti',NULL,NULL),('algoritmiada-2010/runda-3/studenti','Algoritmiada 2010 Runda 2, Studenti','2010-01-18 11:51:50','2010-01-18 15:24:13','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda3-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-3\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-3/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-3/11-12\r\n*(active) \'Studenti\':algoritmiada-2010/runda-3/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-3/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda3-studenti\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2010-runda3-studenti\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2010-runda3-studenti\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-3/studenti.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda3-studenti\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'round: algoritmiada2010-runda3-studenti',NULL,NULL),('algoritmiada-2010/runda-3/studenti','Algoritmiada 2010 Runda 2, Studenti','2010-01-18 11:51:50','2010-01-18 15:24:46','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda3-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-3\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-3/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-3/11-12\r\n*(active) \'Studenti\':algoritmiada-2010/runda-3/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-3/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda3-studenti\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"algoritmiada2010-runda3-studenti\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"algoritmiada2010-runda3-studenti\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-3/studenti.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda3-studenti\" score=\"1\")==\r\n\r\nh2. Discutii pe forum\r\n\r\nVrei sa adresezi intrebari comisiei? Fa-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'round: algoritmiada2010-runda3-studenti',NULL,NULL),('algoritmiada-2010/runda-3/solutii','Solutii Algoritmiada 2010 Runda 3','2010-01-18 11:51:50','2010-01-18 15:38:20','h1. Solutii Algoritmiada 2010, Runda 3\r\n\r\n(toc)*{text-align:center} *Lista de probleme*',1792,'public',NULL,NULL),('dragosh/pwarmup2','dragosh/pwarmup2','2010-01-20 11:44:54','2010-01-20 11:46:01','\r\nConcursul incepe miercuri 20 ianuarie 2010, la ora 19:00:00 si dureaza 1 ora.\r\n\r\nDupa ce se termina runda, vei putea vedea clasamentul.\r\n\r\nProbleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.',3775,'public',NULL,NULL),('www.palatulcopiilor.doodlekit.com','www.palatulcopiilor.doodlekit.com','2010-01-28 14:51:56','2010-01-28 14:51:56','salut',11272,'public',NULL,NULL),('dot-com/2009/solutii/runda-1/galerie','dot-com/2009/solutii/runda-1/galerie','2009-11-15 11:47:30','2009-11-17 18:06:30','h1(#galerie). \'Galerie\':problema/galerie\r\n\r\n**Solutia 1 : Stan Serban Andrei**\r\n\r\nPentru un query $(X,Y)$ ne intereseaza numarul de cartite care vor traversa galeria curenta, mai exact numarul de intervale $(P,Q)$ astfel incat $P&le;X$ si $Y&le;Q$. Costul final se va imbunatati cu $L_galerie * Nr_cartite$. Cum un interval $(A,B),A&ge;B$, este echivalent cu un interval $(A,B),A&le;B$, vom interschimba in primul caz pe $A$ cu $B$.\r\n\r\nPentru a raspunde in mod eficient la fiecare intrebare o sa folosim un \'AIB\':http://infoarena.ro/problema/aib. Initial, pentru fiecare vizita $(P,Q)$,vom insera in AIB la pozitia $P$ numarul de cartite care pleaca din $P$ spre $Q$. \r\nVom parcurge query-urile in ordine dupa capatul din dreapta, si la fiecare pas vom elimina din aib pozitiile reprezentand vizite cu $Q&le;Y-1$. Numarul de cartite care vor traversa intervalul $(X,Y)$ va fi egal cu suma valorilor ce se afla in AIB pe pozitii $&le;P$. \r\n\r\nComplexitatea finala va fi $O(MlogM + TlogT + (M+T)logN)$.\r\n\r\n**Solutia 2 : Teodor Anton Pripoae**\r\n\r\nVom calcula pentru fiecare intrebare a organizatorilor, cate drumuri ale cartitelor contin acel interval (sa zicem $Nr$). Costul imbunatatirii va fi $Nr$ * ($lungime_interval - cost_interval$). Pe exemplul din enunt unde merg $2$ cartite intre camerele $1$ si $4$, vor exista $2$ drumuri care contin intervalul $[1, 3]$ : Drumul facut de prima cartita, respectiv a doua cartita din camera $1$ pana in camera $4$.\r\n\r\nAcum, trebuie sa vedem cum putem raspunde eficient la intrebarea: Cate drumuri contin un interval cautat de organizatori. Vom retine intervalele ca puncte in plan (atat drumurile cat si intrebarile), coordonata $x$ va fi capatul din stanga, iar coordonata $y$ capatul din dreapta. Pentru ca un interval sa fie cuprins de altul, trebuie ca primul punct sa fie in stanga si deasupra celul de-al doilea. Vom sorta crescator toate cele $M + T$ puncte dupa coordonata $x$ si in caz de egalitate descrescator dupa coordonata $y$. Acum, pt fiecare punct (interval) cautat, raspunsul va fi numarul de puncte cu aflate inaintea lui in vector care au coordonata $y$ mai mare decat a lui. \r\n\r\nVom proceda ca la subsir descrescator maximal. Vom tine un aib (Arbore indexat binar). La pasul $i$, vom vedea daca punctul curent($P$) este din cele $M$, caz in care vom updata pe pozitia corespunzatoare coordonatei $P.y$ in aib numarul de cartite care trec pe acel interval, sau in caz ca este din cele $T$ vom vedea cu ajutorul aib-ului cate drumuri a caror coordonate R.y sunt mai mari decat coordonata $P.y$ a lui: scadem din suma totala, suma pozitiilor pana la $P.y - 1$.\r\n\r\nSolutia are complexitate $o((M + T) (log (M + T) + log N))$ ca timp si $o(N)$ ca memorie.\r\n',4827,'public',NULL,NULL),('implica-te/extinde-arhiva/acord','Lista propunatorilor infoarena-friendly','2007-04-21 21:41:18','2010-02-06 13:38:24','h1. Lista propunatorilor infoarena-friendly\r\n\r\nPentru a adauga in arhiva infoarena probleme in cadrul programului \'Extinde Arhiva!\':implica-te/extinde-arhiva este necesar acordul din partea autorului pentru fiecare problema. Astfel, am intocmit aceasta lista cu propunatorii care ne-au oferit acordul pentru problemelor dumnealor. \r\nDaca autorul problemei pe care vrei s-o adaugi nu se gaseste pe lista, vorbeste cu un \'administrator\':echipa-infoarena pentru a intra in contact cu autorul respectiv.\r\nMultumim tuturor persoanelor care ajuta la dezvoltarea \'comunitatii infoarena\':implica-te!\r\n\r\n* Maria Nita\r\n* Adrian Nita\r\n* Mihai Patrascu\r\n* Stelian Ciurea\r\n* Rodica Pintea\r\n* Roxana Tamplaru\r\n* Fechete Dan Ionut\r\n* Mugurel Ionut Andreica\r\n* Marius Andrei\r\n* Mihai Stroe\r\n* Radu Berinde\r\n* Tiberiu Danet\r\n* Dana Lica\r\n* Emilian Miron\r\n* Catalin Francu\r\n* Cristian Cadar\r\n* Nistor Mot\r\n* Alexandru Mosoi\r\n* Victor Manz\r\n* Carmen Popescu\r\n* Marius Nicoli\r\n* Orice membru al echipei \'infoarena\':echipa-infoarena',2044,'public',NULL,NULL),('portal','portal','2010-02-09 16:08:21','2010-02-09 16:27:39','* \"Matematica\":cauta-probleme?tag_id[]=40\r\n* \"Aici\":monitor?user=wefgef',8689,'public',NULL,NULL),('portal','portal','2010-02-09 16:08:21','2010-02-09 16:38:01','==\r\n<a href=\"url\">Link text</a> \r\n<a href = \"http://infoarena.ro/cauta-probleme?tag_id[]=40\">Matematica</a>\r\n==',8689,'public',NULL,NULL),('portal','portal','2010-02-09 16:08:21','2010-02-09 16:50:22','<html>\r\n<a href=\"url\">Link text</a>\r\n<a href = \"http://infoarena.ro/cauta-probleme?tag_id[]=40\">Matematica</a>\r\n</html>\r\n',8689,'public',NULL,NULL),('portal','portal','2010-02-09 16:08:21','2010-02-09 16:54:51','<notextile>\r\n<a href=\"url\">Link text</a>\r\n<a href = \"http://infoarena.ro/cauta-probleme?tag_id[]=40\">Matematica</a>\r\n</code>\r\n</notextile>\r\n\"Matematica\":http://infoarena.ro/cauta-probleme?tag_id[]=400:0',8689,'public',NULL,NULL),('sandbox','Sandbox (cutiuţa cu năsip)','2006-11-11 18:59:57','2010-02-09 17:14:11','h1=. Sandbox (cutiuţa cu năsip)\r\n\r\nNu se pot adauga in Textile adrese care contin semnele []. Nu functioneaza interpretarea acelor sectiuni drept cod html.\r\n\r\n<a href=\"adresa[]\">ha</a>\r\n\r\n== include(page=\"documentatie/sidebar\") ==\r\n\r\n|_. nume |_. varsta |_. judet |\r\n| Popescu | 24 | Bucuresti |\r\n| Ionescu | 12 | Constanta |\r\n\r\n|_. nume |_. varsta |_. judet |_. nume |_. varsta |_. judet |_. nume |_. varsta |_. judet |\r\n| Popescu | 24 | Bucuresti | Popescu | 24 | Bucuresti | Popescu | 24 | Bucuresti |\r\n| Ionescu | 12 | Constanta | Popescu | 24 | Bucuresti | Popescu | 24 | Bucuresti |\r\n\r\nlog me\r\n\r\nLaTeX pe mai multe rânduri:\r\n<tex>\\begin{array}{rcl} f: R^3 & \\to & R \\\\ (x,y,z) & \\to & x + y + z \\\\ f(x,y,z) & = & x + y + z \\end{array}</tex>\r\n\r\nsau:\r\n<tex>\\begin{array} {lcl} f(x) & = & (a+b)^2 \\\\ & = & a^2+2ab+b^2 \\end{array}</tex>\r\n\r\n\r\nTabel mic:\r\n\r\ntable{width:60px}. |A|B|A->B|\r\n|&#48;|2|3|\r\n\r\nTabel mare:\r\n\r\ntable{width:120px}. |A|B|A->B|\r\n|1|2|3|\r\n\r\nTabel si mai mare:\r\n\r\ntable{width:240px}. |A|B|A->B|\r\n|1|2|3|\r\n\r\n*Diacritice:*\r\n\r\nStraşnic de îngâmfat, ţăranul crapă streaşina.\r\nStraşnic de îngâmfat, ţăranul crapă streaşina.\r\n\r\nIn Windows XP sp2 cu IE6 fara update de font se vede asa:\r\n!sandbox?diacritice-IE6.jpg!\r\n\r\nOrdered list:\r\n\r\n# 1st item\r\n# 2nd item\r\n\r\nh3. Use only F/OSS, Microsft sucks ;) just because they like design NOT the code itself.\r\n\r\nHowever, on a GNU system NEVER type <b>sudo make me sandwich</b> , and expect the results...\r\n\r\n\r\nx\r\n\r\n ==calendar()==\r\n\r\ny\r\n\r\n* A[1]\r\n* B[2]\r\n* C[3]\r\n\r\np(#fn1). <tex>2^n    * 2^n</tex>\r\n\"Vivi\'s blog\":http://vivi.ro\r\n<tex> d/(2\\\"a)=d/(2\\Omega^2) </tex>\r\n* <tex> d = \\sqrt{(c_{2}-c_{1})^{2} + 1 } </tex>\r\np. <tex> \r\n\\displaystyle \\sigma_{\\lambda} = \r\n	  \\frac{24 \\pi^3}{\\lambda^4 N^2}\r\n	  \\left(\\frac{n^2-1}{n^2+2}\\right)^{\\!2}\r\n</tex> \r\n\r\nAvem suport pentru <tex> \\LaTeX </tex> !\r\n\r\n<tex> \\frac{a^2 - b^2}{a + b} = a - b </tex>\r\n<tex>n! \\approx \\sqrt{2 \\pi n} (\\frac n e) ^n</tex>\r\n\r\n\r\n==Include(page=\"template/implica-te/scrie-articole\" user_id=\"domino\")==\r\n\r\np(#fn2). | test | test |\r\n\r\n\"User macro bug\":sandbox/usermacrobug\r\n\r\n*Worship me*\r\n\r\nFeel free to plghay around, but \'Big Brother\':/changes is watching you.\r\n\r\n\'codetest\':sandbox/code-test\r\n\r\nWhat does \'this\':sandbox?action=edit button do?\r\n\r\nlalallaa\r\n\r\nIntrebare: cum poti seta culoarea cu care scrii?\r\nUite asa: %{color:violet}scris cu rosu%\r\n\r\nSiteul sub IE 7 -- vezi \'pagina dedicata\':ia_in_ie7\r\n\r\nSiteul sub FF 2 - -mica problema panoul de \'editeaza\', \'vezi istoria\', \'sterge\' etc (in IE7 panoul nu se suprapune)-\r\n!sandbox?IA_bug_in_FF2.jpg!\r\n\r\n[test]\r\n*OMG* test, good work people :D\r\nAcuma doar trebuie putin stimulata comunitatea\r\n[/test]\r\n\r\nInteresting choice of words.\r\na very bold **MAN**\r\n_CAPSOMANII-I DESPISE THEM_\r\n\r\ngasise pe-un teren viran,\r\nun geamantan.\r\n\r\nsi-n geamantan,\r\nun pachet.\r\n\r\nsi in pachet,\r\nun pachetel gasise el.\r\n\r\nsi-n pachetel,\r\nalt pachetel.\r\n\r\nsi-un pachetel in pachetel,\r\nlegat cu funde elegante.\r\n\r\nsi-n pachetel...vreo 40 de diamante...\r\n...\r\nAdio voi...va las si plec fiindca mi-e dor...\r\nsi a plecat Apolodor\r\n!!!<>\r\n\r\ntralalala blablabla lala\r\n\r\n_salut, aici poate sa scrie oricine ce vrea?_ ~Robert~\r\n\r\n|_. 1|_. 2|_. 3|\r\n|unu|doi|trei|\r\n|1... unu|2... doi|3... trei|\r\n\r\nMoraru Ionut has been here. :))\r\n\r\n:) gosh...\r\n\r\ninca unul, de tipul cel mai         heyyyyyyyyyy prost din corcodus, se joaca cu  in nisip.. ura ...\r\ncel mai prost din corcodus a terminat... altcineva?:D\r\ntot el: atentie fratilor ne urmareste big brother 3 (sau 4)\r\n\r\n== code(cpp) |\r\n// comentariu\r\n#include <cstdio> // comment1\r\n// comment2\r\n\r\nint main()\r\n{\r\n    return 0;\r\n}\r\n==\r\n\r\nEu vreau să scriu cu ŢŢŢŢŢ dublu ţ mic şi tripul Ţ mare! Iată un Ţ ţŢŞ ! Are virgulă sau sedilă?\r\nFff\r\nForza Steaua!\r\nTz\r\n\r\naha',8689,'public',NULL,NULL),('algoritmul-lee','Algoritmul lui Lee','2010-02-08 15:03:25','2010-02-09 18:51:45','h1. Algoritmul lui Lee\r\n\r\n(Categoria _Algoritmi_, Autor _Simoiu Robert_)\r\n\r\n(toc){width: 12em}*{text-align:center;} *Conţinut:*\r\n* \'Introducere\':algoritmul-lee#sectiune1\r\n* \'Prezentare\':algoritmul-lee#sectiune2\r\n* \'Aplicaţia #1\':algoritmul-lee#sectiune3\r\n* \'Aplicaţia #2\':algoritmul-lee#sectiune4\r\n\r\nh2(#sectiune1). Introducere\r\n\r\nÎn continuare vom prezenta _algoritmul lui Lee_, pentru cei care nu ştiu este _parcurgerea în lăţime_. Acest algoritm este de fapt o particularizare a algoritmului menţionat mai sus, şi anume _parcurgerii în lăţime_. Este eficient, având o complexitate de $O(M*N)$, şi frecvent utilizat. Acesta determină drumul minim de ieşire dintr-un labirint, sau în probleme asemănătoare. \r\n\r\nh2(#sectiune2). Prezentare\r\n\r\n_Algoritmul lui Lee_ presupune doi paşi importanţi:\r\n\r\n# Primul şi poate cel mai important pas este folosirea unei **Cozi**, sub forma unui vector de structuri (de preferabil), care va menţine toţi paşii pe care o să-i facem de acum în colo. În această coadă se pun, pentru fiecare pas, locurile care s-au marcat la punctul anterior.\r\n# Se marchează cu numere consecutive toate locurile posibile prin care putem trece, parcurgând în ordine elementele cozii, până când nu mai putem marca, sau am ajuns la final.\r\n\r\nh2(#sectiune3). Aplicaţia #1 -> Problema Labirintului\r\n\r\nbq. Se dă o matrice cu M linii şi N coloane. Ştiind locul de plecare, marcat cu $-1$, se cere să se determine drumul de lungime minimă până la o ieşire, iar in caz că nu există, se va afişa $-1$\r\n\r\nh3. Rezolvare\r\n\r\nDupă cum observaţi, este o aplicaţie a _algoritmului lui Lee_. Această problemă se poate rezolva şi cu metoda \'backtracking\':http://en.wikipedia.org/wiki/Backtracking, dar această metodă nu este una eficientă, complexitatea fiind $O(4^(M*N)^)$, sau $O(3^(M*N)^)$ după caz, ceea ce este foarte mult. În primul pas vom pune în coadă coordonatele locului de plecare, urmând apoi să parcurgem pe rând coada, până când nu mai există cale de ieşire sau am găsit una. Aveţi \'aici\':algoritmul-lee?lee-lab.cpp o sursă cu acest algoritm implementat în C++, sau \'aici\':algoritmul-lee?lee-lab.pas o sursă implementată în Pascal.\r\n\r\nh2(#sectiune4). Aplicaţia #2 -> \'Muzeu\':http://infoarena.ro/problema/muzeu\r\n\r\nbq. Un muzeu are forma patratica si contine N*N camere ce pot fi vizitate. Unele camere sunt deschise si contin opere de arta, altele sunt inchise (sunt folosite pentru alte scopuri). In unele din camerele libere, se afla paznici. Directorul muzeului se teme de eventualitatea unei spargeri si de aceea doreste sa evalueze cat de bine au fost asezati paznicii in camerele libere. Mai precis, el doreste sa afle, pentru fiecare camera libera, care este distanta minima pana la cel mai apropiat paznic (numarul minim de camere prin care trebuie sa intre un paznic pentru a ajunge la camera respectiva). Paznicii se pot deplasa numai in camerele libere din Nord, Est, Sud sau Vest (cu conditia sa nu paraseasca muzeul).\r\n\r\nh3. Rezolvare\r\n\r\nAceastă problemă se rezolvă cu _algoritmul lui Lee_, doar că în coadă vom pune iniţial nu o coordonată, ci toate coordonatele paznicilor. Pentru asta se citesc ca şir de caractere fiecare caracter în parte, şi se convertesc acestea (la citire) în numere astfel: zidurile (#) vor fi notate cu $-2$, paznicii (P) cu $-1$, iar căile libere cu $0$. După executarea algoritmului, se verifică şi se înlocuiesc cifrele de $0$ cu $-1$ (pentru că în problemă ne cere să afişăm cu $-1$ locurile care nu au fost vizitate), iar cifrele de $-1$ (reprezentând paznicii) cu $0$. \r\n\r\n\r\n\r\n',11154,'public',NULL,NULL),('algoritmul-lee','Algoritmul lui Lee','2010-02-08 15:03:25','2010-02-10 07:27:19','h1. Algoritmul lui Lee\r\n\r\n(Categoria _Algoritmi_, Autor _Simoiu Robert_)\r\n\r\n(toc){width: 12em}*{text-align:center;} *Conţinut:*\r\n* \'Introducere\':algoritmul-lee#sectiune1\r\n* \'Prezentare\':algoritmul-lee#sectiune2\r\n* \'Aplicaţia #1\':algoritmul-lee#sectiune3\r\n* \'Aplicaţia #2\':algoritmul-lee#sectiune4\r\n\r\nh2(#sectiune1). Introducere\r\n\r\nÎn continuare vom prezenta _algoritmul lui Lee_, pentru cei care nu ştiu este _parcurgerea în lăţime_. Acest algoritm este de fapt o particularizare a algoritmului menţionat mai sus, şi anume _parcurgerii în lăţime_. Este eficient, având o complexitate de $O(M*N)$, şi frecvent utilizat. Acesta determină drumul minim de ieşire dintr-un labirint, sau în probleme asemănătoare. \r\n\r\nh2(#sectiune2). Prezentare\r\n\r\n_Algoritmul lui Lee_ presupune doi paşi importanţi:\r\n\r\n# Primul şi poate cel mai important pas este folosirea unei **Cozi**, sub forma unui vector de structuri (de preferabil), care va menţine toţi paşii pe care o să-i facem de acum în colo. În această coadă se pun, pentru fiecare pas, locurile care s-au marcat la punctul anterior.\r\n# Se marchează cu numere consecutive toate locurile posibile prin care putem trece, parcurgând în ordine elementele cozii, până când nu mai putem marca, sau am ajuns la final. \r\n\r\nh2(#sectiune3). Aplicaţia #1 -> Problema Labirintului\r\n\r\nbq. Se dă o matrice cu M linii şi N coloane. Ştiind locul de plecare, marcat cu $-1$, se cere să se determine drumul de lungime minimă până la o ieşire, iar in caz că nu există, se va afişa $-1$\r\n\r\nh3. Rezolvare\r\n\r\nDupă cum observaţi, este o aplicaţie a _algoritmului lui Lee_. Această problemă se poate rezolva şi cu metoda \'backtracking\':http://en.wikipedia.org/wiki/Backtracking, dar această metodă nu este una eficientă, complexitatea fiind $O(4^(M*N)^)$, sau $O(3^(M*N)^)$ după caz, ceea ce este foarte mult. În primul pas vom pune în coadă coordonatele locului de plecare, urmând apoi să parcurgem pe rând coada, până când nu mai există cale de ieşire sau am găsit una. Aveţi \'aici\':algoritmul-lee?lee-lab.cpp o sursă cu acest algoritm implementat în C++, sau \'aici\':algoritmul-lee?lee-lab.pas o sursă implementată în Pascal. Vă voi da un exemplu pentru a vă arata mai bine cum se marchează fiecare vecin în parte:\r\n\r\n|_. fişier intrare |_. fişier ieşire |_. explicaţii |\r\n|$5$ $5$                 \r\n$1$ $1$ $1$ $1$ $1$\r\n$1$ $0$ $0$ $0$ $-1$\r\n$1$ $0$ $0$ $1$ $1$\r\n$1$ $0$ $0$ $1$ $1$\r\n$1$ $0$ $1$ $1$ $1$|6| $1$ $1$ $1$ $1$ $1$ \r\n$1$ _3_ _2_ _1_ $-1$ \r\n$1$ _4_ _3_ _2_ $1$ \r\n$1$ _5_ _4_ $1$ $1$ \r\n$1$ _6_ $1$ $1$ $1$| \r\n\r\nh2(#sectiune4). Aplicaţia #2 -> \'Muzeu\':http://infoarena.ro/problema/muzeu\r\n\r\nbq. Un muzeu are forma patratica si contine N*N camere ce pot fi vizitate. Unele camere sunt deschise si contin opere de arta, altele sunt inchise (sunt folosite pentru alte scopuri). In unele din camerele libere, se afla paznici. Directorul muzeului se teme de eventualitatea unei spargeri si de aceea doreste sa evalueze cat de bine au fost asezati paznicii in camerele libere. Mai precis, el doreste sa afle, pentru fiecare camera libera, care este distanta minima pana la cel mai apropiat paznic (numarul minim de camere prin care trebuie sa intre un paznic pentru a ajunge la camera respectiva). Paznicii se pot deplasa numai in camerele libere din Nord, Est, Sud sau Vest (cu conditia sa nu paraseasca muzeul).\r\n\r\nh3. Rezolvare\r\n\r\nAceastă problemă se rezolvă cu _algoritmul lui Lee_, doar că în coadă vom pune iniţial nu o coordonată, ci toate coordonatele paznicilor. Pentru asta se citesc ca şir de caractere fiecare caracter în parte, şi se convertesc acestea (la citire) în numere astfel: zidurile (#) vor fi notate cu $-2$, paznicii (P) cu $-1$, iar căile libere cu $0$. După executarea algoritmului, se verifică şi se înlocuiesc cifrele de $0$ cu $-1$ (pentru că în problemă ne cere să afişăm cu $-1$ locurile care nu au fost vizitate), iar cifrele de $-1$ (reprezentând paznicii) cu $0$. \r\n\r\n\r\n\r\n',11154,'public',NULL,NULL),('planificare/sedinta-20100216','Ședință 2010-02-16','2010-02-13 13:22:15','2010-02-13 14:04:41','h1. Şedinţă 2010-02-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Marti* la ora *?* la ?.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"svalentin\" type=\"tiny\")==\r\n* ....\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20100112 | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada Runda 3 + 4 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| OKR | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Evaluator | ? |\r\n| Doi la suta | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n* ...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* ...\r\n\r\nh2(#notite). Notite\r\n\r\n* ....\r\n',75,'protected',NULL,NULL),('sandbox','Sandbox (cutiuţa cu nisip murdar iahh!!;)))','2006-11-11 18:59:57','2010-02-14 16:53:18','h1=. Sandbox (cutiuţa cu nisip-murdar iahh!! ;))) // by laurrr din Piteşti brătianu rules!! ;) me_lawr yahoo)\r\n\r\nNu se pot adauga in Textile adrese care contin semnele []. Nu functioneaza interpretarea acelor sectiuni drept cod html.\r\n\r\n@<a href=\"adresa[]\">ha</a>@ -> nu merge cu @\r\n==\r\n<a href=\"adresa[]\">ha</a> -> nu merge cu ==\r\n==\r\n\r\n== include(page=\"documentatie/sidebar\") ==\r\n\r\n|_. nume |_. varsta |_. judet |\r\n| Popescu | 24 | Bucuresti |\r\n| Ionescu | 12 | Constanta |\r\n\r\n|_. nume |_. varsta |_. judet |_. nume |_. varsta |_. judet |_. nume |_. varsta |_. judet |\r\n| Popescu | 24 | Bucuresti | Popescu | 24 | Bucuresti | Popescu | 24 | Bucuresti |\r\n| Ionescu | 12 | Constanta | Popescu | 24 | Bucuresti | Popescu | 24 | Bucuresti |\r\n\r\nlog me\r\n\r\nLaTeX pe mai multe rânduri:\r\n<tex>\\begin{array}{rcl} f: R^3 & \\to & R \\\\ (x,y,z) & \\to & x + y + z \\\\ f(x,y,z) & = & x + y + z \\end{array}</tex>\r\n\r\nsau:\r\n<tex>\\begin{array} {lcl} f(x) & = & (a+b)^2 \\\\ & = & a^2+2ab+b^2 \\end{array}</tex>\r\n\r\n\r\nTabel mic:\r\n\r\ntable{width:60px}. |A|B|A->B|\r\n|&#48;|2|3|\r\n\r\nTabel mare:\r\n\r\ntable{width:120px}. |A|B|A->B|\r\n|1|2|3|\r\n\r\nTabel si mai mare:\r\n\r\ntable{width:240px}. |A|B|A->B|\r\n|1|2|3|\r\n\r\n*Diacritice:*\r\n\r\nStraşnic de îngânfat, ţăranul crapă straşina.\r\nStraşnic de îngâmfat, ţăranul crapă streaşina.\r\n\r\nIn Windows XP sp2 cu IE6 fara update de font se vede asa:\r\n!sandbox?diacritice-IE6.jpg!\r\n\r\nOrdered list:\r\n\r\n# 1st item\r\n# 2nd item\r\n\r\nh3. Use only F/OSS, Microsft sucks ;) just because they like design NOT the code itself.\r\n\r\nHowever, on a GNU system NEVER type <b>sudo make me sandwich</b> , and expect the results...\r\n\r\n\r\nx\r\n\r\n ==calendar()==\r\n\r\ny\r\n\r\n* A[1]\r\n* B[2]\r\n* C[3]\r\n\r\np(#fn1). <tex>2^n    * 2^n</tex>\r\n\"Vivi\'s blog\":http://vivi.ro\r\n<tex> d/(2\\\"a)=d/(2\\Omega^2) </tex>\r\n* <tex> d = \\sqrt{(c_{2}-c_{1})^{2} + 1 } </tex>\r\np. <tex> \r\n\\displaystyle \\sigma_{\\lambda} = \r\n	  \\frac{24 \\pi^3}{\\lambda^4 N^2}\r\n	  \\left(\\frac{n^2-1}{n^2+2}\\right)^{\\!2}\r\n</tex> \r\n\r\nAvem suport pentru <tex> \\LaTeX </tex> !\r\n\r\n<tex> \\frac{a^2 - b^2}{a + b} = a - b </tex>\r\n<tex>n! \\approx \\sqrt{2 \\pi n} (\\frac n e) ^n</tex>\r\n\r\n\r\n==Include(page=\"template/implica-te/scrie-articole\" user_id=\"domino\")==\r\n\r\np(#fn2). | test | test |\r\n\r\n\"User macro bug\":sandbox/usermacrobug\r\n\r\n*Worship me*\r\n\r\nFeel free to plghay around, but \'Big Brother\':/changes is watching you.\r\n\r\n\'codetest\':sandbox/code-test\r\n\r\nWhat does \'this\':sandbox?action=edit button do?\r\n\r\n\r\n\r\nIntrebare: cum poti seta culoarea cu care scrii?\r\nUite asa: %{color:blue}scris cu rosu :)))))))) nu prea seamana cu rosuu :P:P=))))))%\r\n\r\nSiteul sub IE 7 -- vezi \'pagina dedicata\':ia_in_ie7\r\n\r\nSiteul sub FF 2 - -mica problema panoul de \'editeaza\', \'vezi istoria\', \'sterge\' etc (in IE7 panoul nu se suprapune)-\r\n!sandbox?IA_bug_in_FF2.jpg!\r\n\r\n[test]\r\n*OMG* test, good work people :D\r\nAcuma doar trebuie putin stimulata comunitatea\r\n[/test]\r\n\r\nInteresting choice of words.\r\na very bold **MAN**\r\n_CAPSOMANII-I DESPISE THEM_\r\n\r\ngasise pe-un teren viran,\r\nun geamantan.\r\n\r\nsi-n geamantan,\r\nun pachet.\r\n\r\nsi in pachet,\r\nun pachetel gasise el.\r\n\r\nsi-n pachetel,\r\nalt pachetel.\r\n\r\nsi-un pachetel in pachetel,\r\nlegat cu funde elegante.\r\n\r\nsi-n pachetel...vreo 40 de diamante...\r\n...\r\nAdio voi...va las si plec fiindca mi-e dor...\r\nsi a plecat Aleodor Cersetorul\r\n!!!<>\r\n\r\ntralalala blablabla lala\r\n\r\n_salut, aici poate sa scrie oricine ce vrea?_ ~Robert~ nu chiar oricine....~mai Robert mai~\r\n\r\n|_. 1|_. 2|_. 3|\r\n|unu|doi|trei|\r\n|1... unu|2... doi|3... trei|\r\n\r\nMoraru Ionut has been here. :))\r\n\r\n:) gosh...\r\n\r\ninca unul, de tipul cel mai         heyyyyyyyyyy prost din corcodus, se joaca cu  in nisip.. ura ...\r\ncel mai prost din corcodus a terminat... altcineva?:D\r\ntot el: atentie fratilor ne urmareste big brother 3 (sau 4)\r\n\r\n== code(cpp) |\r\n// comentariu\r\n#include <cstdio> // comment1\r\n// comment2\r\n\r\nint main()\r\n{\r\n    return 0;\r\n}\r\n==\r\n\r\nEu vreau să scriu cu ŢŢŢŢŢ dublu ţ mic şi tripul Ţ mare! Iată un Ţ ţŢŞ ! Are virgulă sau sedilă?\r\nFff\r\nForza Steaua!\r\nTz\r\n\r\naha\r\n\r\n\r\nme_lawr by Laurrr din Piteşti\r\n\r\n\'cs\':http://dl.transfer.ro/Transfer_ro-03Feb-12e6d2135cef7ae.zip',11775,'public',NULL,NULL),('implica-te/extinde-arhiva','Extinde arhiva','2007-03-12 22:59:26','2010-02-14 23:05:38','h1. Extinde arhiva ==Stars(rating=\"3\")==\r\n\r\nArhiva este una dintre cele mai folositoare sectiuni _infoarena_ pentru utilizatorii nostri. Ea contine probleme pentru multe gusturi. Dar nu pentru toate!\r\nVrem sa o imbunatatim cu probleme cat mai diverse si cu grade de dificultate cat mai variate. Pentru asta am obtinut aprobarea mai multor autori de probleme pentru a le importa \"creatiile\" in arhiva.\r\n\r\nh2. De ce m-as baga?\r\n\r\n# Vei afla cum se propune si cum se corecteaza o problema. Vei sti cum sa propui propriile probleme pe _infoarena_.\r\n# Intreaga comunitate iti va multumi pentru noul \"material\" de pregatire.\r\n# Vei fi si tu \"de partea cealalta a baricadei\".\r\n# Pentru unele probleme vei putea scrie enuntul personalizat (cu numele simpatiei tale, spre exemplu).\r\n# Unde-s multi, puterea creste! :P\r\n\r\nh2. Ce pot sa fac?\r\n\r\n# Contacteaza-l pe Adi pe \'forum\':forum/index.php/board,42.0.html.\r\n# Alege-ti problemele pe care vrei sa le pui in arhiva si *verifica* daca exista \'acordul\':implica-te/extinde-arhiva/acord autorului pentru a pune problemele respective. \r\n*{color:red}Atentie!* Comunica acest lucru lui Adi cat mai repede pentru a evita suprapunerile si pentru a putea aparea in tabelul cu voluntarii activi ;)\r\n# *{color:red}Foarte important:* Citeste despre \'cum se adauga o problema\':documentatie/editare-de-probleme, \"conventii de formatare\":documentatie/conventii-de-formatare si \'textile\':documentatie/textile si intreaba pe forum daca ai nelamuriri.\r\n# Abia dupa ce ai terminat de citit documentatia, cere drepturi de helper pentru a putea pune probleme pe infoarena.\r\n# Scrie enuntul unei probleme folosind \'textile\':http://infoarena.ro/documentatie/textile si gandeste-te la solutii alternative.\r\n# Imbunatateste testele si creeaza altele noi, astfel incat problema sa devina de actualitate.\r\nToate bulanelile/ciucuielile care s-au facut in concursul respectiv trebuie facute sa pice.\r\n# Stabileste limitele de timp si memorie conform cu mediul infoarena de evaluare.\r\n\r\nh2. Cine mai lucreaza?\r\n\r\n ==user(user=\"ditzonec\" type=\"tiny\")== *este coordonatorul proiectului.*\r\n ==user(user=\"silviug\" type=\"tiny\")==\r\n ==user(user=\"domino\" type=\"tiny\")== \r\n\r\n\r\ntable. |_. Sursa de probleme |_. Voluntar |_. Progres |\r\n| Probleme baraje | ==User(user=\"astronomy\" type=\"tiny\")== ==User(user=\"toni2007\" type=\"tiny\")== | ?/? |\r\n| Probleme Cosmin Negruseri | ==User(user=\"bogdan2412\" type=\"tiny\")== | 3/4 |\r\n| Lista lui Francu | ==User(user=\"cos_min\" type=\"tiny\")== ==User(user=\"devilkind\" type=\"tiny\")==\r\n==User(user=\"pauldb\" type=\"tiny\")==  ==User(user=\"gabitzish1\" type=\"tiny\")==  ==User(user=\"Florian\" type=\"tiny\")==| 36/45 |\r\n\r\nh2. Probleme de pus in arhiva \r\n\r\n* \"preONI 2003\":downloads?action=download&file=preoni2.zip\r\n* Probleme de orice autor din \'lista de propunatori infoarena-friendly\':implica-te/extinde-arhiva/acord\r\n* \"Lista lu\' Francu\":http://voronet.francu.com/probleme/rom/probleme.html; pentru cei interesati mai multe detalii \"aici\":implica-te/extinde-arhiva/lista-lu-francu.\r\n\r\nh2. Discutii forum\r\n\r\n==SmfTopics(board_id=\"42.0\")==\r\n',1792,'protected',NULL,NULL),('newsletter/algoritmiada-2010-3','Algoritmiada 2010 Runda 3','2010-02-14 23:32:52','2010-02-15 07:32:45','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nWeekendul acest are loc cea de-a \'treia rundă\':algoritmiada-2010/runda-3 a concursului \'Algoritmiada 2010\':algoritmiada-2010, cel mai mare şi mai prestigios concurs organizat de infoarena!\r\n\r\nLa Algoritmiada participă elevi de gimnaziu, de liceu, dar şi studenţi (inclusiv masteranzi sau doctoranzi)! Există grupe separate pentru fiecare.\r\n\r\nÎntrece-te cu cei mai buni! Dovedeşte-ţi talentul şi abilităţile şi asigură-ţi un loc în finală!\r\n\r\nEşti elev de liceu? \'Runda 3\':algoritmiada-2010/runda-3 reprezintă o ocazie perfectă pentru a-ţi verifica cunoştinţele înainte de Olimpiada Judeţeană de Informatică! \r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Runda a treia se desfăşoară\r\n*Duminică, 21 Februarie 2010, orele 09^00^ - 13^00^*. |\r\n\r\nVezi \'pagina concursului\':algoritmiada-2010 ca să afli cum poţi participa.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"algoritmiada-2010/runda-3\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre rundele anterioare\r\n\r\nPe \'blog\':blog găseşti analizele primelor două runde. Află câti concurenţi au participat, câte surse s-au trimis şi impresii despre rundă!\r\n\r\nVezi rezultatele şi clasamentul \'aici\':algoritmiada-2010/clasament.\r\n\r\nh2{font-size: 12pt}. Despre Algoritmiada\r\n\r\nAlgoritmiada este unicul concurs din România unde pot participa tinerii pasionaţi de informatică de toate vârstele: de la elevi de gimnaziu până la studenţi şi doctoranzi.\r\n\r\nConcursul are patru grupe valorice: gimnaziu, clasele 9-10, clasele 11-12, studenţi (inclusiv masteranzi şi doctoranzi). Participanţii vor avea ocazia să-şi demonstreze talentul, cunostinţele şi ascuţimea minţii în 4 probe online urmând ca cei mai buni sa fie invitaţi la finala on-site. În fiecare rundă vei avea la dispoziţie 4h să rezolvi 3 probleme de natură algoritmică.\r\n\r\nSubiectele vor fi propuse de către o echipă de foşti şi actuali olimpici la informatică: Cosmin Gheorghe, Bogdan Tătăroiu, Paul Băltescu, Filip Ştefan, Marius Stroe, Adrian Airinei, Andrei Grigorean, Ştefan Istrate, Adrian Diaconu, Cosmin Negruşeri şi Filip Buruiană. De ce ei? Intră pe \'pagina organizatorilor\':algoritmiada-2010/comisie şi citeşte câte ceva despre experienţa fiecăruia.\r\n\r\nIntră pe \'pagina concursului\':algoritmiada-2010 ca să afli mai multe informaţii.\r\n\r\nIţi urăm succes şi te asteptăm în arenă!\r\n\r\n==include(page=\"template/newsletter/prima-data\")==\r\n\r\n==include(page=\"template/newsletter/implica-te\")==',1792,'protected',NULL,NULL),('utilizator/blasterz','Profil blasterz','2006-11-24 20:58:43','2010-02-15 20:29:24','h3. Student in anul II la Facultatea de Matematica si Informatica, Universitatea Bucuresti\r\n\r\n\r\nh2. TODO LIST:   ACM WORLD FINALS MEDAL\r\n\r\nh2. Distinctii primite\r\n\r\n**2009 : Antrenor si Membru in Comisia Lotului National de Informatica** \r\n**2009 : Membru in Comisia ONI la clasele 11-12 si baraj**\r\n**2009 : Propunator probleme .campion ,ONI si lot**\r\n\r\n**2010 : 21st place at Bitwise International Programing Contest**\r\n**2009 : 26th place (Honorable Mention) at the ACM South Eastern Contest**\r\n**2009 : Adobe Internship Diploma**\r\n**2009 : Locul 1 la Sesiunea de Comunicari Stiintifice, Faza Nationala impreuna cu Serban Lupulescu cu articolul \"Trie Forest Data Structure\"**\r\n**2009 : Locul 4 la finala concursului national Algoritmiada, sectia studenti**\r\n**2009 : Calificat in finala Concursului National Algoritmiada pentru Studenti**\r\n**2008 : Calificat in runda a4a a concursului international Google CodeJam**\r\n**2008 : Membru al Lotului National Restrans (unde am obtinut locul 11)**\r\n**2008 : Calificat in Lotul National Largit**\r\n**2008 : Mentiune ONI 2008 + medalie de argint**\r\n**2008 : Finalist .campion 2008 Bran**\r\n2008 : Participare la Concursul National Urmasii lui Moisil, Iasi ( punctajul neoficial cel mai mare...mai trimiti brute la sfarsit fara sa-ti dai seama =)) :| )\r\n2008 : Participare la Concursul National Stelele Informarticii 2008\r\n**2007 : Premiul 1 la Concursul International ProSoft@NT**\r\n**2007 : Finalist .Campion 2007 Galati** \r\n**2007 : Premiul II la Concursul National de Informatica Aplicata (CIA) sectiunea Jocuri**\r\n2007 : Premiul I la Faza Judeteana a Concursul de Informatica Aplicata (CIA) sectiunea Jocuri\r\n2007 : Premiul II la Concursul Interjudetean al Centrelor de Excelenta Suceava\r\n2007 : Mentiune la Concursul de Programare DataS-NMG Targu Secuiesc\r\n2007 : Participare ONI 2007 + calificare pentru baraje\r\n2007 : Premiul 2 Olimpiada Judeteana\r\n2006 : Mentiune la Concursul Interjudetean al Centrelor de Excelenta Suceava\r\n\r\n\r\nh2. Prieteni pe infoarena\r\n\r\nh3. Ordinea nu are importanta. Daca nu am trecut pe careva sa-mi spuneti.\r\n\r\n\r\n* ==user(user=\"georgiana\" type=\"tiny\")== \r\n\r\n* ==user(user=\"marina\" type=\"tiny\")== \r\n\r\n* ==user(user=\"alisssia\" type=\"tiny\")== \r\n\r\n\r\n* ==user(user=\"doru.nitu\" type=\"tiny\")== \r\n\r\n* ==user(user=\"freak93\" type=\"normal\")==\r\n\r\n* ==user(user=\"DjSefu\" type=\"tiny\")==\r\n\r\n* ==user(user=\"warchildmd\" type=\"tiny\")==\r\n\r\n* ==user(user=\"nyxpho\" type=\"tiny\")== \r\n\r\n* ==user(user=\"monica_133\"  type=\"normal\")==\r\n\r\n* ==user(user=\"serbanlupu\" type=\"normal\")==\r\n\r\n* ==user(user=\"enslaverr\" type=\"tiny\")==\r\n\r\n* ==user(user=\"Mishu91\" type=\"tiny\")==\r\n\r\n* ==user(user=\"yoyolich\" type=\"tiny\")== \r\n\r\n* ==user(user=\"nuexist\" type=\"tiny\")== \r\n\r\n* ==user(user=\"malex\" type=\"tiny\")==\r\n\r\n* ==user(user=\"lorin_bobu\" type=\"tiny\")==\r\n\r\n\r\n* ==user(user=\"ioanai\" type=\"tiny\")==\r\n\r\n* ==user(user=\"Florian\" type=\"tiny\")==\r\n\r\n\r\n* ==user(user=\"Tabara\" type=\"tiny\")==\r\n\r\n* ==user(user=\"alexthero\" type=\"tiny\")==\r\n\r\n* ==user(user=\"peanutz\" type=\"tiny\")==\r\n\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n\r\n* ==user(user=\"astronomy\" type=\"tiny\")==\r\n\r\n* ==user(user=\"m_dersidan\" type=\"tiny\")==\r\n\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n\r\n* ==user(user=\"mastermage\" type=\"tiny\")==\r\n\r\n* ==user(user=\"nemesis\" type=\"tiny\")==\r\n\r\n* ==user(user=\"Binary_Fire\" type=\"tiny\")==\r\n\r\n* ==user(user=\"TYTUS\" type=\"tiny\")==\r\n\r\n\r\n* ==user(user=\"crawler\" type=\"tiny\")==\r\n\r\n* ==user(user=\"devilkind\" type=\"tiny\")==\r\n\r\n* ==user(user=\"vlad_D\" type=\"tiny\")==\r\n\r\n* ==user(user=\"arenakadaff\" type=\"tiny\")==\r\n\r\n* ==user(user=\"StTwister\" type=\"tiny\")==\r\n\r\n* ==user(user=\"bog_bej\" type=\"tiny\")==\r\n* ==user(user=\"cretu\" type=\"tiny\")==\r\n',1204,'protected',NULL,NULL),('planificare/sedinta-20100216','Ședință 2010-02-16','2010-02-13 13:22:15','2010-02-15 13:51:10','h1. Şedinţă 2010-02-16\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Marti* la ora *17* la staţia de 41 de la Plaza România.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"svalentin\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"Prostu\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"stef2n\" type=\"tiny\")==\r\n* ...\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20100112 | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada Runda 3 + 4 | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| OKR | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Evaluator | ? |\r\n| Doi la suta | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Restructurare arhiva + tagging camp | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n\r\nh2. Detalii\r\n\r\n* ...\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* ...\r\n\r\nh2(#notite). Notite\r\n\r\n* ....\r\n',2044,'protected',NULL,NULL),('echipa-infoarena','Echipa infoarena','2006-11-27 08:20:21','2009-12-31 15:54:23','h1. Echipa infoarena\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nMembrii echipei infoarena s-au remarcat prin activitate sustinuta in cadrul proiectelor infoarena. Acestia detin functii oficiale in \'Asociatia infoarena\':asociatia-infoarena. Echipa infoarena este responsabila de dezvoltarea si intretinerea site-ului infoarena precum si de desfasurarea altor proiecte ale Asociatiei. Coordonarea eforturilor echipei se face pe pagina de \'planificare\':planificare.\r\n\r\nEchipa infoarena se bucura de \'*sprijinul a zeci de voluntari*\':implica-te. O buna parte din continutul infoarena este rezultatul muncii lor. Suntem onorati sa primim ajutorul lor si le multumim sincer pentru efortul pe care l-au depus!\r\n\r\nh2. Conducere\r\n\r\ntable(layout){width: 70%}.\r\n|* ==user(user=\"gcosmin\" type=\"normal\")==\r\n* ==user(user=\"pauldb\" type=\"normal\")==\r\n|* ==user(user=\"bogdan2412\" type=\"normal\")==\r\n* ==user(user=\"stef2n\" type=\"normal\")==|\r\n\r\nh2. Membri fondatori\r\n\r\ntable(layout){width: 70%}.\r\n|* ==user(user=\"wickedman\" type=\"normal\")==\r\n* ==user(user=\"silviug\" type=\"normal\")==\r\n|* ==user(user=\"domino\" type=\"normal\")==\r\n* ==user(user=\"fluffy\" type=\"normal\")==|\r\n\r\nh2. Consilieri\r\n\r\ntable(layout){width: 70%}.\r\n|* ==user(user=\"ditzoneC\" type=\"normal\")==\r\n* ==user(user=\"filipb\" type=\"normal\")==\r\n* ==user(user=\"Cosmin\" type=\"normal\")==\r\n* ==user(user=\"svalentin\" type=\"normal\")==\r\n* ==user(user=\"astronomy\" type=\"normal\")==\r\n* ==user(user=\"wefgef\" type=\"normal\")==\r\n* ==user(user=\"alexthero\" type=\"normal\")==\r\n| * ==user(user=\"gcosmin\" type=\"normal\")==\r\n* ==user(user=\"bogdan2412\" type=\"normal\")==\r\n* ==user(user=\"pauldb\" type=\"normal\")==\r\n* ==user(user=\"Prostu\" type=\"normal\")==\r\n* ==user(user=\"stef2n\" type=\"normal\")==\r\n* ==user(user=\"victorsb\" type=\"normal\")==\r\n* ==user(user=\"Marius\" type=\"normal\")== |\r\n\r\nh2. Consilieri emeritus\r\n\r\n* ==user(user=\"azotlichid\" type=\"normal\")==\r\n* ==user(user=\"greco\" type=\"normal\")==\r\n* ==user(user=\"danielp\" type=\"normal\")==\r\n',13,'protected',NULL,NULL),('algoritmiada-2010/runda-3','Algoritmiada 2010 - Runda 3','2009-10-25 16:32:16','2010-02-14 23:37:23','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Algoritmiada 2010, Runda 3\r\n\r\n(htabs)*(active) \'Despre...\':algoritmiada-2010/runda-3 \r\n* \'Clasele 5-8\':algoritmiada-2010/runda-3/5-8 \r\n* \'Clasele 9-10\':algoritmiada-2010/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-3/studenti\r\n* \'Rezultate\':algoritmiada-2010/clasament/runda-3/5-8 \r\n\r\nRunda va incepe *Duminica 21 februarie*, la ora {*09^00^*} si va dura *4h*. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-3/studenti\r\n\r\nDupa ce se termina concursul, vei putea vedea solutiile problemelor \'aici\':algoritmiada-2010/runda-3/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-3/studenti\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"77\" count=\"20\")==\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"cosmin\" type=\"tiny\")==\r\n* ==User(user=\"marius\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica sau tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"wickedman\" type=\"tiny\")==\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n==Include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('portal','portal','2010-02-09 16:08:21','2010-02-09 17:11:12','',8689,'public',NULL,NULL),('portal','portal','2010-02-09 16:08:21','2010-02-18 10:26:42','\r\n\r\n\r\n\r\n\r\n* \"Cautare\":cauta-probleme?tag_id%5B%5D=48\r\n** \"Cautare binara\":cauta-probleme?tag_id%5B%5D=49\r\n\r\n\r\n* \"Backtracking\":cauta-probleme?tag_id%5B%5D=96\r\n** \"Submultimi\":cauta-probleme?tag_id%5B%5D=98\r\n\r\n\r\n* \"Divide et Impera\":cauta-probleme?tag_id%5B%5D=89\r\n** \"Ad-hoc\":cauta-probleme?tag_id%5B%5D=90\r\n\r\n\r\n* \"Matematica\":cauta-probleme?tag_id%5B%5D=40\r\n** \"Ciurul lui Eratostene\":cauta-probleme?tag_id%5B%5D=101\r\n** \"Formula\":cauta-probleme?tag_id%5B%5D=105\r\n\r\n\r\n* \"Diverse\":cauta-probleme?tag_id%5B%5D=45\r\n** \"Operatii pe biti\":cauta-probleme?tag_id%5B%5D=73',8689,'public',NULL,NULL),('portal','portal','2010-02-09 16:08:21','2010-02-18 10:41:34','h3. \"%{color:orange}Programare dinamica%\":cauta-probleme?tag_id%5B%5D=58\r\n\r\n* \"Dinamica pe stari exponentiale\":cauta-probleme?tag_id%5B%5D=59\r\n* \"Memoizare\":cauta-probleme?tag_id%5B%5D=77\r\n\r\n\r\nh3. \"Cautare\":cauta-probleme?tag_id%5B%5D=48\r\n\r\n* \"Cautare binara\":cauta-probleme?tag_id%5B%5D=49\r\n\r\n\r\nh3. \"Backtracking\":cauta-probleme?tag_id%5B%5D=96\r\n\r\n* \"Submultimi\":cauta-probleme?tag_id%5B%5D=98\r\n\r\n\r\nh3. \"Divide et Impera\":cauta-probleme?tag_id%5B%5D=89\r\n\r\n* \"Ad-hoc\":cauta-probleme?tag_id%5B%5D=90\r\n\r\n\r\nh3. \"%{color:black}Matematica%\":cauta-probleme?tag_id%5B%5D=40\r\n\r\n* \"Ciurul lui Eratostene\":cauta-probleme?tag_id%5B%5D=101\r\n* \"Formula\":cauta-probleme?tag_id%5B%5D=105\r\n\r\n\r\nh3. \"%{color:red}Teoria jocurilor%\":cauta-probleme?tag_id%5B%5D=60\r\n\r\n* \"Ad-hoc\":cauta-probleme?tag_id%5B%5D=78\r\n\r\n\r\n\r\nh3. \"Diverse\":cauta-probleme?tag_id%5B%5D=45\r\n\r\n* \"Operatii pe biti\":cauta-probleme?tag_id%5B%5D=73',8689,'public',NULL,NULL),('portal','portal','2010-02-09 16:08:21','2010-02-18 11:15:28','h3. \"%{color:orange}Programare dinamica%\":cauta-probleme?tag_id%5B%5D=58\r\n\r\n* \"Dinamica pe stari exponentiale\":cauta-probleme?tag_id%5B%5D=59\r\n* \"Dinamica pe arbore\":cauta-probleme?tag_id%5B%5D=71\r\n* \"Memoizare\":cauta-probleme?tag_id%5B%5D=77\r\n\r\n\r\nh3. \"%{color:orange}Grafuri%\":cauta-probleme?tag_id%5B%5D=46\r\n\r\n* \"Parcurgere in latime **BFS**\":cauta-probleme?tag_id%5B%5D=47\r\n* \"Parcurgere in adancime **DFS**\":cauta-probleme?tag_id%5B%5D=69\r\n* \"Algoritmul lui Dijkstra\":cauta-probleme?tag_id%5B%5D=72\r\n* \"Algoritmul Bellman-Ford\":cauta-probleme?tag_id%5B%5D=92\r\n* \"Flux maxim\":cauta-probleme?tag_id%5B%5D=268\r\n* \"Flux maxim de cost minim\":cauta-probleme?tag_id%5B%5D=93\r\n* \"Lowest Common Ancestor\":cauta-probleme?tag_id%5B%5D=82\r\n* \"Lant hamiltonian\":cauta-probleme?tag_id%5B%5D=57\r\n* \"Lant eulerian\":cauta-probleme?tag_id%5B%5D=112\r\n* \"2-SAT\":cauta-probleme?tag_id%5B%5D=87\r\n* \"Componente tare conexe\":cauta-probleme?tag_id%5B%5D=88\r\n\r\n\r\nh3. \"%{color:blue}Structuri de date%\":cauta-probleme?tag_id%5B%5D=38\r\n\r\n* \"Arbori de intervale\":cauta-probleme?tag_id%5B%5D=84\r\n* \"Range Minimum Query\":cauta-probleme?tag_id%5B%5D=83\r\n\r\n\r\n\r\nh3. \"%{color:red}Cautare%\":cauta-probleme?tag_id%5B%5D=48\r\n\r\n* \"Cautare binara\":cauta-probleme?tag_id%5B%5D=49\r\n\r\n\r\nh3. \"%{color:green}Sortare%\":cauta-probleme?tag_id%5B%5D=63\r\n\r\n* \"Sortare\":cauta-probleme?tag_id%5B%5D=64\r\n\r\n\r\nh3. \"%{color:purple}Siruri de caractere%\":cauta-probleme?tag_id%5B%5D=55\r\n\r\n* \"Parsare\":cauta-probleme?tag_id%5B%5D=67\r\n* \"KMP\":cauta-probleme?tag_id%5B%5D=56\r\n\r\n\r\nh3. \"%{color:red}Backtracking%\":cauta-probleme?tag_id%5B%5D=96\r\n\r\n* \"Submultimi\":cauta-probleme?tag_id%5B%5D=98\r\n\r\n\r\nh3. \"%{color:black}Divide et Impera%\":cauta-probleme?tag_id%5B%5D=89\r\n\r\n* \"Ad-hoc\":cauta-probleme?tag_id%5B%5D=90\r\n\r\n\r\nh3. \"%{color:black}Matematica%\":cauta-probleme?tag_id%5B%5D=40\r\n\r\n* \"Ciurul lui Eratostene\":cauta-probleme?tag_id%5B%5D=101\r\n* \"Formula\":cauta-probleme?tag_id%5B%5D=105\r\n* \"Combinatorica\":cauta-probleme?tag_id%5B%5D=281\r\n\r\n\r\n\r\n\r\nh3. \"%{color:black}Geometrie%\":cauta-probleme?tag_id%5B%5D=41\r\n\r\n* \"No fit polygon\":cauta-probleme?tag_id%5B%5D=259\r\n\r\n\r\nh3. \"%{color:red}Teoria jocurilor%\":cauta-probleme?tag_id%5B%5D=60\r\n\r\n* \"Ad-hoc\":cauta-probleme?tag_id%5B%5D=78\r\n\r\n\r\n\r\nh3. \"%{color:green}Diverse%\":cauta-probleme?tag_id%5B%5D=45\r\n\r\n* \"Operatii pe biti\":cauta-probleme?tag_id%5B%5D=73\r\n* \"Operatii pe numere mari\":cauta-probleme?tag_id%5B%5D=104',8689,'public',NULL,NULL),('runda/vot','Votati personajul preferat Infoarena','2010-03-04 12:31:13','2010-03-04 12:35:08','h1. Votati personajul preferat Infoarena\r\n\r\nAlgorel, Gigel, Zaharel au decis sa organizeze alegeri pentru a vedea care este cel mai iubit dintre personajele Infoarena. Haralambie a vrut sa concureze si el, dar n-a avut cele 10 probleme necesare intrarii in competitie. Nargy si Fumeanu, fiind prieteni nedespartiti, au decis sa intre impreuna in competitie.\r\n\r\nPentru a vota, fiecare trebuie sa trimite rezolvari la diferite probleme pe care le-au intampinat Algorel, Gigel si ceilalti, pentru ai ajuta la nevoie. Rezolvarile se trimit la runda destinata fiecaruia, fiecare problema corecta insumand 100 de voturi, cu un maxim de 1000 de voturi din partea fiecarui votant.\r\n\r\nRezultatele finale pentru fiecare se vor obtine insumand punctajele tuturor din clasament.\r\n\r\n\r\nVotarea incepe ==roundparam(round_id=\"voteaza_algorel\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"voteaza_algorel\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"voteaza_algorel\" units=\"2\") ==\r\n\r\nPentru a incepe votarea, alegeti pe cine doriti sa votati (puteti vota pe mai multi):\r\n\r\n\"Algorel\":runda/vot/voteaza_algorel\r\n\"Gigel\":runda/vot/voteaza_gigel\r\n\"Zaharel\":runda/vot/voteaza_zaharel\r\n\"Nargy si Fumeanu\":runda/vot/voteaza_nargy_si_fumeanu',8689,'public',NULL,NULL),('runda/vot','Votati personajul preferat Infoarena','2010-03-04 12:31:13','2010-03-04 12:33:26','h1. Votati personajul preferat Infoarena\r\n\r\nAlgorel, Gigel, Zaharel au decis sa organizeze alegeri pentru a vedea care este cel mai iubit dintre personajele Infoarena. Haralambie a vrut sa concureze si el, dar n-a avut cele 10 probleme necesare intrarii in competitie. Nargy si Fumeanu, fiind prieteni nedespartiti, au decis sa intre impreuna in competitie.\r\n\r\nPentru a vota, fiecare trebuie sa trimite rezolvari la diferite probleme pe care le-au intampinat Algorel, Gigel si ceilalti, pentru ai ajuta la nevoie. Rezolvarile se trimit la runda destinata fiecaruia, fiecare problema corecta insumand 100 de voturi, cu un maxim de 1000 de voturi din partea fiecarui votant.\r\n\r\nRezultatele finale pentru fiecare se vor obtine insumand punctajele tuturor din clasament.\r\n\r\nPentru a incepe votarea, alegeti pe cine doriti sa votati (puteti vota pe mai multi):\r\n\r\n\"Algorel\":runda/vot/voteaza_algorel\r\n\"Gigel\":runda/vot/voteaza_gigel\r\n\"Zaharel\":runda/vot/voteaza_zaharel\r\n\"Nargy si Fumeanu\":runda/vot/voteaza_nargy_si_fumeanu',8689,'public',NULL,NULL),('algoritmiada-2010/runda-3/solutii/cabine','Soluţie Joben','2010-02-19 19:33:46','2010-02-19 19:33:46','*Aceasta pagina trebuie sa ramana private pana la finalul concursului.*',1792,'private',NULL,NULL),('algoritmiada-2010/runda-3/solutii/semafoare','Soluţie Joben','2010-02-19 19:32:51','2010-02-19 19:32:51','*Aceasta pagina trebuie sa ramana private pana la finalul concursului.*',1792,'private',NULL,NULL),('algoritmiada-2010/runda-3/solutii/joben','Soluţie Joben','2010-02-19 19:32:01','2010-02-19 19:32:01','*Aceasta pagina trebuie sa ramana private pana la finalul concursului.*',1792,'private',NULL,NULL),('algoritmiada-2010/runda-3/solutii/karb','Soluţie Karb','2010-02-19 19:33:35','2010-02-19 19:34:53','*Aceasta pagina trebuie sa ramana private pana la finalul concursului.*',1792,'private',NULL,NULL),('problema/triunghi','Triunghi','2006-11-11 11:23:34','2008-11-15 16:19:41','==Include(page=\"template/taskheader\" task_id=\"triunghi\")==\r\n\r\nLui Gigel ii place sa se joace, asa ca el a primit un joc cu cutii pe care erau scrise numere intregi stict pozitive. Avand o imaginatie bogata, el s-a gandit intr-o zi sa construiasca un triunghi de cutii astfel: o cutie este asezata peste doua cutii, care sunt asezate pe trei cutii... care sunt asezate pe $N$ cutii (deci fiecare cutie se sprijina pe alte doua). Dar Gigel nu se opreste aici, ci vrea ca numarul din fiecare cutie din triunghiul sau (mai putin ultima linie) sa fie egal cu suma numerelor din cele doua cutii de dedesubt.\r\n\r\nh2. Cerinta\r\n\r\nScrieti un program care determina daca Gigel poate construi un triunghi de latura $N$, in care suma numerelor de pe toate cutiile sa fie $S$, stiind ca pot folosi oricate cutii cu orice numar in ele.\r\n\r\nh2. Date de intrare\r\n\r\nPe prima linie in fisierul $triunghi.in$ se vor afla numerele $N$ si $S$ separate prin cate un spatiu.\r\n\r\nh2. Date de iesire\r\n\r\nPe primele $N$ linii din fisierul $triunghi.out$ se vor afla numerele de pe cutiile din triunghi: pe linia $i$ vor fi scrise cate $i$ numere intregi strict pozitive care descriu linia $i$ din triunghi. Daca Gigel nu poate construit un astfel de triunghi, in fisier se va afisa in schimb mesajul $imposibil$.\r\n\r\nh2. Restrictii si observatii\r\n\r\n* $1 &le; N &le; 18$\r\n* $1 &le; S &le; 1 000 000$\r\n* Daca sunt posibile mai multe solutii se va afisa oricare dintre ele\r\n\r\nExemple\r\n\r\ntable(example). |_. triunghi.in |_. triunghi.out |\r\n|3 34\r\n|13\r\n6 7\r\n1 5 2|\r\n|4 26\r\n|8\r\n4 4\r\n2 2 2\r\n1 1 1 1|\r\n\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"triunghi\")==\n\n\n',1490,'task: triunghi',44,NULL),('runda/oji-2005-ix','oji-2005-ix','2010-03-04 10:29:41','2010-03-04 10:29:41','h1. == roundparam(round_id=\"oji-2005-ix\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oji-2005-ix\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oji-2005-ix\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oji-2005-ix\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"oji-2005-ix\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/oji-2005-ix/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"oji-2005-ix\" score=\"1\")==',10498,'round: oji-2005-ix',NULL,NULL),('runda/oji-2005-ix','oji-2005-ix','2010-03-04 10:29:41','2010-03-04 10:36:18','h1. == roundparam(round_id=\"oji-2005-ix\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oji-2005-ix\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oji-2005-ix\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oji-2005-ix\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"oji-2005-ix\" units=\"2\") ==\r\n\r\nh1. Probleme\r\n\r\n==Tasks(round_id=\"oji-2005-ix\" score=\"1\")==\r\n\r\nh1. \'*Clasament*\':runda/oji-2005-ix/clasament',10498,'round: oji-2005-ix',NULL,NULL),('runda/oji-2005-ix/clasament','Clasament oji-2005-ix','2010-03-04 10:29:41','2010-03-04 10:36:56','h1. Clasament ==roundparam(round_id=\"oji-2005-ix\" param=\"title\") ==\r\n\r\n==Rankings(rounds = \"oji-2005-ix\")==',10498,'round: oji-2005-ix',NULL,NULL),('runda/j4ix','runda/oji 2004 ix','2010-03-04 08:04:05','2010-03-04 08:16:49','h1. == roundparam(round_id=\"j4ix\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"j4ix\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"j4ix\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"j4ix\" param=\"duration\" strong=\"true\")== ore.\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/j4ix/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"j4ix\" score=\"1\")==',10498,'public',NULL,NULL),('runda/oji-2004-ix','oji-2004-ix','2010-03-04 07:57:12','2010-03-04 07:57:12','h1. == roundparam(round_id=\"oji-2004-ix\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oji-2004-ix\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oji-2004-ix\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oji-2004-ix\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"oji-2004-ix\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/oji-2004-ix/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"oji-2004-ix\" score=\"1\")==',10498,'round: oji-2004-ix',NULL,NULL),('runda/oji-2004-ix','oji-2004-ix','2010-03-04 07:57:12','2010-03-04 08:22:22','h1. == roundparam(round_id=\"oji-2004-ix\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oji-2004-ix\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oji-2004-ix\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oji-2004-ix\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"oji-2004-ix\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/oji-2004-ix/clasament.\r\n\r\nh1. Probleme\r\n\r\n==Tasks(round_id=\"oji-2004-ix\" score=\"1\")==',10498,'round: oji-2004-ix',4598,NULL),('algoritmiada-2010/clasament/runda-4/11-12','Algoritmiada 2010 - Clasament Runda 3, Clasele 11-12','2010-02-21 12:43:41','2010-02-21 12:43:41','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda3-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-3\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-3/studenti\r\n*(active) \'Rezultate\':algoritmiada-2010/clasament/runda-3/11-12\r\n\r\n==include(page=\"template/algoritmiada-2010/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-3/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2010/clasament/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-3/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda3-11-12\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1490,'protected',NULL,NULL),('algoritmiada-2010/clasament','Algoritmiada 2010 - Clasament','2009-10-25 14:00:09','2010-01-18 15:47:13','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Clasament \r\n\r\n(htabs)*(active) \'Pe runde...\':algoritmiada-2010/clasament\r\n* \'Clasele 5-8\':algoritmiada-2010/clasament/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/studenti\r\n\r\ntable(layout). |_. Clasament Runda 1 |_. Clasament Runda 3 |\r\n|* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-1/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-1/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-1/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-1/studenti \r\n|* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-3/studenti|\r\n|_. Clasament Runda 2 | \r\n|* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-2/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-2/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-2/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-2/studenti\r\n|\r\n\r\n==Include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('algoritmiada-2010/runda-4/solutii','Solutii Algoritmiada 2010 Runda 3','2010-02-21 12:43:08','2010-02-21 12:43:08','h1. Solutii Algoritmiada 2010, Runda 3\r\n\r\n(toc)*{text-align:center} *Lista de probleme*\r\n* \'Joben\':algoritmiada-2010/runda-3/solutii#joben\r\n* \'Semafoare\':algoritmiada-2010/runda-3/solutii#semafoare\r\n* \'Drum3\':algoritmiada-2010/runda-3/solutii#drum3\r\n* \'Intersect\':algoritmiada-2010/runda-3/solutii#intersect\r\n* \'Karb\':algoritmiada-2010/runda-3/solutii#karb\r\n* \'Cabine\':algoritmiada-2010/runda-3/solutii#cabine\r\n* \'Piramid\':algoritmiada-2010/runda-3/solutii#piramid\r\n* \'Arbore3\':algoritmiada-2010/runda-3/solutii#arbore3\r\n\r\n==include(page=\"algoritmiada-2010/runda-3/solutii/joben\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-3/solutii/semafoare\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-3/solutii/drum3\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-3/solutii/intersect\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-3/solutii/karb\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-3/solutii/cabine\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-3/solutii/piramid\")==\r\n\r\n==include(page=\"algoritmiada-2010/runda-3/solutii/arbore3\")==',1490,'private',NULL,NULL),('algoritmiada-2010/runda-3/solutii/semafoare','Soluţie Semafoare','2010-02-19 19:32:51','2010-02-21 16:02:08','h1(#semafoare). \'Semafoare\':problema/semafoare\r\n\r\nPentru a rezolva problema, ne vom propune să calculăm $D[i][j][k] = timpul minim necesar pentru a ajunge la semaforul din intersecţia (i, j) venind din direcţia k$, unde $k$ ia valori în mulţimea ${0, 1, 2, 3}$ ce reprezintă codificări pentru cele $4$ direcţii posibile: nord, est, sud si vest. Dacă în problemă nu ar interveni semafoarele, matricea $D$ ar putea fi calculată cu uşurinţă folosind o \'parcurgere in lăţime\':problema/bfs sau, mai popular, un Lee. Totuşi, se observă că o maşină nu poate aştepta mai mult de $3$ minute la un semafor, deci costul pentru a ajunge în oricare din celulele adiacente poate fi cel mult $4$. De aceea, vom folosi 5 cozi în parcurgerea noastră: una pentru $costul curent$, una pentru $costul curent + 1$, ... şi una pentru $costul curent + 4$. Observaţia făcută mai devreme ne asigură că la pasul curent vom avea triplete $(i, j, k)$ al căror cost să depăşească $costul curent+4$, în afară de cele al căror cost este infinit (nu ştim nimc de distanţa minimă până la ele). Vom parcurge coada corespunzătoare costului curent şi vom proceda exact ca în cazul unei parcurgeri în lăţime. Când terminăm de parcurs coada curentă, vom muta coada de $cost curent + 1$ în locul celei curente, cea de $cost curent + 2$ în locul celei de $cost curent + 1$, ..., iar ultima coadă va fi vidă. Este necesar ca pentru a calcula costurile de deplasare în celulele adiacente să ştim să determinăm timpul minim în care putem intra într-o intersecţie oarecare dacă ştim că am ajuns la semaforul respectiv la momentul de timp $t$, venind din direcţia $d1$, iar pentru în această intersecţie în minutul $0$ intră maşinile din direcţia $d2$. Timpul minim căutat se poate obţine în complexitate $O(1)$ cu ajutorul următoarei formule: $(d1 - d2 - (t%4) + 8) % 4$ sau în varianta optimizată folosind operaţii pe biţi: $(d1 - d2 - (t&3) + 8) & 3$. Algoritmul prezentat procesează fiecare triplet $(i, j, k)$ de un număr constant de ori, ceea ce conduce la o complexitate totală $O(N*M)$. Acest algoritm mai poate fi aplicat în mai multe probleme precum \'Pădure\':problema/padure şi \'Car\':problema/car (soluţie \'aici\':preoni-2005/runda-2/solutii).',1792,'public',NULL,NULL),('portal','Portal Infoarena','2010-02-09 16:08:21','2010-02-18 11:36:20','h1. !portal?Portal.jpg! Selectaţi destinaţia.\r\n\r\n\r\nh3. \"%{color:orange}Programare dinamica%\":cauta-probleme?tag_id%5B%5D=58\r\n\r\n* \"Dinamica pe stari exponentiale\":cauta-probleme?tag_id%5B%5D=59\r\n* \"Dinamica pe arbore\":cauta-probleme?tag_id%5B%5D=71\r\n* \"Memoizare\":cauta-probleme?tag_id%5B%5D=77\r\n\r\n\r\nh3. \"%{color:orange}Grafuri%\":cauta-probleme?tag_id%5B%5D=46\r\n\r\n* \"Parcurgere in latime **BFS**\":cauta-probleme?tag_id%5B%5D=47\r\n* \"Parcurgere in adancime **DFS**\":cauta-probleme?tag_id%5B%5D=69\r\n* \"Algoritmul lui Dijkstra\":cauta-probleme?tag_id%5B%5D=72\r\n* \"Algoritmul Bellman-Ford\":cauta-probleme?tag_id%5B%5D=92\r\n* \"Flux maxim\":cauta-probleme?tag_id%5B%5D=268\r\n* \"Flux maxim de cost minim\":cauta-probleme?tag_id%5B%5D=93\r\n* \"Lowest Common Ancestor\":cauta-probleme?tag_id%5B%5D=82\r\n* \"Lant hamiltonian\":cauta-probleme?tag_id%5B%5D=57\r\n* \"Lant eulerian\":cauta-probleme?tag_id%5B%5D=112\r\n* \"2-SAT\":cauta-probleme?tag_id%5B%5D=87\r\n* \"Componente tare conexe\":cauta-probleme?tag_id%5B%5D=88\r\n\r\n\r\nh3. \"%{color:blue}Structuri de date%\":cauta-probleme?tag_id%5B%5D=38\r\n\r\n* \"Arbori de intervale\":cauta-probleme?tag_id%5B%5D=84\r\n* \"Range Minimum Query\":cauta-probleme?tag_id%5B%5D=83\r\n\r\n\r\n\r\nh3. \"%{color:red}Cautare%\":cauta-probleme?tag_id%5B%5D=48\r\n\r\n* \"Cautare binara\":cauta-probleme?tag_id%5B%5D=49\r\n\r\n\r\nh3. \"%{color:green}Sortare%\":cauta-probleme?tag_id%5B%5D=63\r\n\r\n* \"Sortare\":cauta-probleme?tag_id%5B%5D=64\r\n\r\n\r\nh3. \"%{color:purple}Siruri de caractere%\":cauta-probleme?tag_id%5B%5D=55\r\n\r\n* \"Parsare\":cauta-probleme?tag_id%5B%5D=67\r\n* \"KMP\":cauta-probleme?tag_id%5B%5D=56\r\n\r\n\r\nh3. \"%{color:red}Backtracking%\":cauta-probleme?tag_id%5B%5D=96\r\n\r\n* \"Submultimi\":cauta-probleme?tag_id%5B%5D=98\r\n\r\n\r\nh3. \"%{color:black}Divide et Impera%\":cauta-probleme?tag_id%5B%5D=89\r\n\r\n* \"Ad-hoc\":cauta-probleme?tag_id%5B%5D=90\r\n\r\n\r\nh3. \"%{color:black}Matematica%\":cauta-probleme?tag_id%5B%5D=40\r\n\r\n* \"Ciurul lui Eratostene\":cauta-probleme?tag_id%5B%5D=101\r\n* \"Formula\":cauta-probleme?tag_id%5B%5D=105\r\n* \"Combinatorica\":cauta-probleme?tag_id%5B%5D=281\r\n\r\n\r\n\r\n\r\nh3. \"%{color:black}Geometrie%\":cauta-probleme?tag_id%5B%5D=41\r\n\r\n* \"No fit polygon\":cauta-probleme?tag_id%5B%5D=259\r\n\r\n\r\nh3. \"%{color:red}Teoria jocurilor%\":cauta-probleme?tag_id%5B%5D=60\r\n\r\n* \"Ad-hoc\":cauta-probleme?tag_id%5B%5D=78\r\n\r\n\r\n\r\nh3. \"%{color:green}Diverse%\":cauta-probleme?tag_id%5B%5D=45\r\n\r\n* \"Operatii pe biti\":cauta-probleme?tag_id%5B%5D=73\r\n* \"Operatii pe numere mari\":cauta-probleme?tag_id%5B%5D=104',8689,'public',NULL,NULL),('articole/template-solutii','articole/template-solutii','2008-12-13 14:45:42','2009-12-22 09:14:26','* !>articole/template-solutii?algoritmiada-2010.jpg! \'Algoritmiada 2010, Runda 2\':algoritmiada-2010/runda-2/solutii\r\n* \'Algoritmiada 2010, Runda 1\':algoritmiada-2010/runda-1/solutii\r\n* \'Summer Challenge 2009, Runda 3\':summer-challenge-2009/solutii/runda-3\r\n* \'Summer Challenge 2009, Runda 2\':summer-challenge-2009/solutii/runda-2\r\n* \'Summer Challenge 2009, Runda 1\':summer-challenge-2009/solutii/runda-1\r\n* \'Grigore Moisil 2009\':grigore-moisil-2009/solutii\r\n* !>articole/template-solutii?algoritmiada-2009.jpg! \'Algoritmiada 2009, Runda 3\':algoritmiada-2009/runda-3/solutii\r\n* \'Algoritmiada 2009, Runda 2\':algoritmiada-2009/runda-2/solutii\r\n* \'Algoritmiada 2009, Runda 1\':algoritmiada-2009/runda-1/solutii\r\n* \'Junior Challenge 2008\':junior-challenge-2008/solutii\r\n* \'Grigore Moisil 2008\':grigore-moisil-2008/solutii\r\n* \'preONI 2008, Runda finala\':preoni-2008/runda-finala/solutii\r\n* !>articole/template-solutii?preoni-2008.jpg! \'preONI 2008, Runda 4\':preoni-2008/runda-4/solutii\r\n* \'preONI 2008, Runda 3\':preoni-2008/runda-3/solutii\r\n* \'preONI 2008, Runda 2\':preoni-2008/runda-2/solutii\r\n* \'preONI 2008, Runda 1\':preoni-2008/runda-1/solutii\r\n*{display: %display%} \'Winter Challenge 2008, Runda 2\':winter-challenge-2008/runda-2/solutii\r\n*{display: %display%} \'Winter Challenge 2008, Runda 1\':winter-challenge-2008/runda-1/solutii\r\n*{display: %display%} \'Happy Coding 2007\':happy-coding-2007/solutii\r\n*{display: %display%} \'Autumn Warmup 2007 runda 3\':autumn-warmup-2007/solutii/runda-3\r\n*{display: %display%} \'Autumn Warmup 2007 runda 2\':autumn-warmup-2007/solutii/runda-2\r\n*{display: %display%} \'Autumn Warmup 2007 runda 1\':autumn-warmup-2007/solutii/runda-1\r\n*{display: %display%} \'Summer Challenge 2007 runda #3\':summer-challenge-2007/solutii/runda-3\r\n*{display: %display%} \'Summer Challenge 2007 runda #2\':summer-challenge-2007/solutii/runda-2\r\n*{display: %display%} \'Summer Challenge 2007 runda #1\':summer-challenge-2007/solutii/runda-1\r\n*{display: %display%} \'Junior Challenge 2007\':junior-challenge/solutii\r\n*{display: %display%} !>articole/template-solutii?preoni-2007.jpg! \'preONI 2007 runda finala - solutii\':preoni-2007/runda-finala/solutii\r\n*{display: %display%} \'preONI 2007 runda #4 - solutii\':preoni-2007/runda-4/solutii\r\n*{display: %display%} \'preONI 2007 runda #3 - solutii\':preoni-2007/runda-3/solutii\r\n*{display: %display%} \'preONI 2007 runda #2 - solutii\':preoni-2007/runda-2/solutii\r\n*{display: %display%} \'preONI 2007 runda #1 - solutii\':preoni-2007/runda-1/solutii\r\n*{display: %display%} \'Winter Challenge 1\':winter-challenge-1/solutii\r\n*{display: %display%} \'Unirea 2007\':unirea-2007/solutii\r\n*{display: %display%} \'Solutii Autumn WarmUp 2006\':warm-up-2006/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Trei\':summer-challenge-3/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Doi\':summer-challenge-2/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Unu\':summer-challenge-unu/solutii\r\n*{display: %display%} !>articole/template-solutii?preoni-2006.gif! \'Solutii preONI 2006, Runda finala\':preoni-2006/finala/solutii\r\n*{display: %display%} \'Solutii preONI 2006, Runda a 4-a\':preoni-2006/runda-4/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda a 3-a\':preoni-2006/runda-3/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda a 2-a\':preoni-2006/runda-2/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda 1\':preoni-2006/runda-1/solutii\r\n*{display: %display%} \'preONI 2005 runda #3 - solutii\':preoni-2005/runda-3/solutii\r\n*{display: %display%} \'preONI 2005 runda #2 - solutii\':preoni-2005/runda-2/solutii\r\n*{display: %display%} \'preONI 2005 runda #1 - solutii\':preoni-2005/runda-1/solutii\r\n*{display: %display%} \'Happy Coding 3 [2006]\':happy-coding-2006/solutii\r\n*{display: %display%} \'Happy Coding 2 [2005]\':happy-coding-2005-2/solutii\r\n*{display: %display%} \'Happy Coding 1 [2005]\':happy-coding-2005-1/solutii\r\n*{display: %display%} \'Concursul Agora - Etapa Finala - Solutii\':agora-finala/solutii\r\n*{display: %display%} \'Doua probleme de la runda 6 a concursului Algoritmus\':doua-probleme-de-la-runda-6-a-concursului-algoritmus\r\n*{display: %display%} \'USACO dec 2005, divizia GOLD\':usaco-dec-2005-divizia-gold \r\n*{display: %display%} \'USACO nov 2005, divizia GOLD\':usaco-nov-2005-divizia-gold\r\n*{display: %display%} \'USACO oct 2005, divizia GOLD\':usaco-oct-2005-divizia-gold\r\n*{display: %display%} \'USACO ian 2005, divizia GOLD\':usaco-ian-2005-divizia-gold\r\n*{display: %display%} \'USACO dec 2004, divizia GOLD\':usaco-dec-2004-divizia-gold\r\n*{display: %display%} \'Solutiile oficiale pentru Concursul &quot;de incalzire&quot;\':warm-up-2004/solutii',2044,'protected',NULL,NULL),('marturii','Marturiile utilizatorilor infoarena','2007-05-15 00:33:16','2010-03-08 19:20:20','h1. Marturii despre infoarena\r\n\r\n==include(page=\"template/despre-infoarena\")==\r\n\r\nDaca esti utilizator infoarena si consideri ca site-ul nostru te-a ajutat in vreun fel, te rugam sa ne scrii o marturie, similara cu cele deja existente in aceasta pagina. Ne intereseaza pareri cat mai sincere, indiferent ca sunt pozitive sau negative.\r\n\r\nClick pe _Editeaza_ ca sa adaugi marturia ta. Te rugam sa respecti stilul de formatare existent.\r\n\r\n&nbsp;\r\n\r\nbq. infoarena este un proiect remarcabil, realizat cu entuziasm, generozitate si profesionalism. Este locul in care tinerii pasionati de informatica se pot intalni, atat de o parte, cat si de cealalta parte a baricadei, ca propunatori sau ca rezolvitori de probleme, isi pot impartasi experienta competitionala, pot constitui modele, pot ajuta la formarea a noi si noi generatii de performanta. *Emanuela Cerchez*\r\n\r\n&nbsp;\r\n\r\nbq. infoarena e plin de energie, e dinamic si riguros, gratie unei echipe curajoase. Site-ul infoarena reprezinta cea mai originala forma de pregatire pe net a performerilor in informatica din Romania. Mecanism de lucru excelent, probleme propuse, fara cusur. Felicitari! *Emil Onea*\r\n\r\n&nbsp;\r\n\r\nbq. infoarena m-a adus aproape de oameni extraordinari, prieteni care m-au invatat nenumarate lucruri despre informatica, generozitate, entuziasm si dedicare. Putine lucruri sunt mai importante decat un anturaj EXEMPLAR. Intr-un fel, pot sa spun ca infoarena mi-a schimbat viata. == user(type=\"tiny\" user=\"wickedman\")==\r\n\r\n&nbsp;\r\n\r\nbq. infoarena a fost cea mai importanta sursa de probleme in pregatirea mea si a colegilor mei pentru olimpiadele nationale, dar si un mod bun de a invata cate ceva despre evaluatoarele folosite la concursuri. Pentru mine, cel putin, accesul la surse mi-a creat si o perspectiva despre modul in care se construieste o aplicatie ce ia in cosiderare toate cazurile, oricat de improbabile ar fi ele. == user(type=\"tiny\" user=\"salgau_catalin\")==\r\n\r\n&nbsp;\r\n\r\nbq. Cred ca in Romania exista poli puternici (Bucuresti, Iasi) legati de profesori valorosi si copii pasionati dar izolati. Aici intervine infoarena: cultiva spiritul competitiv din fiecare, te motiveaza, creaza comunitatea de care avem nevoie ca sa evoluam. Propune un joc in care te implici initial din curioziate, pentru a deveni in scurt timp dependent indiferent daca lucrezi pentru internationala, pentru judeteana sau ca sa obtii un rating mai bun decat vecinul de pe scara. ;) == user(type=\"tiny\" user=\"DigitAll\")==\r\n\r\n&nbsp;\r\n\r\nbq. Infoarena este un proiect foarte important in pregatirea olimpicilor romani de informatica. Nu numai ca este o sursa constanta de probleme, dar fiecare utilizator poate sa vada unde se situeaza in comparatie cu ceilalti, fiecare stie ce-i poate pielea. Sa nu mai vorbim de constantele concursuri online unde utilizatorii pot concura intre ei. Pe mine personal infoarena m-a ajutat foarte mult...  == user(type=\"tiny\" user=\"Darth_Niculus\")==\r\n\r\n&nbsp;\r\n\r\nbq. La inceput, infoarena a insemnat pentru mine un joc nascut dintr-o dorinta puternica de rascumpara macar o parte din ce am primit in postura de invatacel de la oamenii extraordinari cu care am interactionat, fie ei profesori sau prieteni. Pe parcurs a devenit concretizarea visului meu de olimpic la informatica din provincie: un site unde sa gasesti oameni la fel de pasionati de informatica ca si tine, probleme, resurse si link-uri, toate intr-un singur loc. == user(type=\"tiny\" user=\"silviug\")==\r\n\r\n&nbsp;\r\n\r\nbq. Pentru mine infoarena a insemnat practic contactul cu adevarata lume a informaticii. Pana atunci informatica pentru mine era doar o pasiune, insa de abia cand am intrat pe infoarena am realizat cat de vast este acest domeniu. Aici am invatat cam 90% din ce stiu acum, si cu siguranta mai am multe de invatat de pe acest site. In acest moment infoarena este o comunitate, o comunitate de olimpici care se ajuta intre ei, facand schimb de idei si invatand unul de la altul. == user(type=\"tiny\" user=\"devilkind\")==\r\n\r\n&nbsp;\r\n\r\nbq. Infoarena este cu adevarat un proiect de exceptie care a reusit sa se dezvolte enorm in cursul celor 3 ani de activitate. Infoarena nu este doar un loc unde te pregatesti pentru concursurile de informatica. Este un loc unde poti cunoaste persoane cu aceleasi pasiuni ca si tine, un loc in care se aduna toti cei care au spirit competitiv si doresc sa se perfectioneze in domeniul programarii. Zeci de utilizatori contribuie efectiv la dezvoltarea si imbunatatirea site-ului ca developeri, propunatori de probleme sau moderatori pe forum. Este cu adevarat o comunitate! == user(type=\"tiny\" user=\"filipb\")==\r\n\r\n&nbsp;\r\n\r\nbq. Atunci cand ma aflam la inceput de drum, infoarena a fost locul unde am intalnit ceea ce imi doream, probleme grele care sa imi dea batai ce cap, o comunitate prietenoasa care sa imi dea sfaturi, si posibilitatea de a participa la concursuri in conditii similare celor de la olimpiada. Am invatat foarte mult aici, si sper sa pot contribui si eu la dezvoltarea acestui proiect, care aduna in fiecare an tot mai multi elevi pasionati din intreaga tara. == user(type=\"tiny\" user=\"wefgef\")==\r\n\r\n&nbsp;\r\n\r\nbq. infoarena a fost comunitatea care mi-a trezit pasiunea pentru informatica. E un proiect extraordinar, prin care, nu numai ca inveti cu adevarat tainele algoritmicii si programarii, lucru care te ajuta in mod deosebit la concursuri si olimpiade, dar iti faci si foarte multi prieteni. Aici gasesti mereu oameni care sunt gata sa te ajute, sa-ti ofere informatii noi, gasesti mereu o problema interesanta in arhiva, si de asemenea, gasesti mereu o competitie (interna sau nu) la care sa poti participa on-line, comod, si care sa te ajute cu pregatirea in regim de concurs. Pe langa comunitate, arhiva si concursuri, sunt accesibile numeroase articole. Sectiunea \"Links\" si \"Downloads\" sunt si ele indispensabile vietii de programator. == user(type=\"tiny\" user=\"Florian\")==\r\n\r\n&nbsp;\r\n\r\nbq. Foarte putine lucruri m-au ajutat mai mult in viata decat participarea la concursurile nationale si internationale de informatica. De asemenea, nu multe au fost resursele prin intermediul carora am reusit sa concurez de la egal la egal cu elevii care aveau deja rezultate bune si o experienta mai mare decat a mea. infoarena e una din aceste resurse: proaspata, inedita, si propulsata de o comunitate plina de pasiune si entuziasm. Le multumesc tuturor celor care au facut ca infoarena sa devina realitate, si sper ca toti cei implicati intr-un fel sau altul in olimpiadele de informatica sa profite la maxim si sa aprecieze la randul lor acest proiect remarcabil. == user(type=\"tiny\" user=\"greco\")==\r\n\r\n&nbsp;\r\n\r\nbq. infoarena este pentru mine \"persoana\" care ma impinge de la spate sa lucrez, uneori simt ca ma pot depasi pe mine; sunt si voi fi recunoscator tuturor celor de aici care m-au ajutat si o vor face in continuare; am doar cuvinte de lauda. BRAVO == user(type=\"tiny\" user=\"DraStiK\")==\r\n\r\n&nbsp;\r\n\r\nbq. Infoarena este site-ul care te ajuta sa faci performanta deoarece problemele pot fi facute in multe moduri. Cand esti mic iei cateva puncte, dar cand vei fi mare vei gasi rezolvarea care iti va aduce punctajul maxim. Te ajuta sa tii minte cand ai folosit o metoda si cum si de aceea Infoarena este unul dintre cele mai bune site-uri de pregatire == user(type=\"tiny\" user=\"Andrici_Cezar\")==\r\n\r\n&nbsp;\r\n\r\nbq. Infoarena a fost \"prietenul\" care mi-a aratat primii pasi spre adevarata informatica, cea in care trebuie sa muncesti ca sa progresezi. Acest simplu \"site\" s-a transformat acum intr-o adevarata comunitate cu multi pasionati ai informaticii, de la care poti invata multe. Infoarena va ramane mereu o sursa de inspiratie pentru mine. == user(type=\"tiny\" user=\"spiderman\")==\r\n\r\n.',8239,'public',NULL,NULL),('utilizator/marius','Profil Marius','2006-11-24 21:03:36','2010-01-19 13:02:09','h2. Despre mine\r\n\r\n* Am terminat liceul Colegiul National I.C. Bratianu din Piteşti. Acum sunt student la Facultatea de Informatică a Universităţii Babeş Bolyai din Cluj.\r\n\r\n* Îmi place să fac sport, să călătoresc, să citesc, să conduc, să ascult, să mixez muzică. \r\n\r\n* Citatul preferat: \"Quitters don\'t win, winners don\'t quit\"\r\n\r\n* În colaborare cu == user(user=\"stef2n\" type=\"tiny\") == am dezvoltat \'pluginul\':http://code.google.com/p/pidgin-embeddedvideo/ pentru \'Pidgin\':http://pidgin.im ce permite vizualizarea clipurilor video direct în conversaţie.\r\n\r\nh2. Distincţii primite\r\n\r\n* Menţiune şi Premiul Special, _ONI 2007_, Cluj, locul 4.\r\n\r\n* Calificat în _lotul naţional, 2007_.\r\n\r\n* Finalist _preONI 2007_.\r\n\r\n* Participant, pe bază de invitaţie, la concursul _Stelele Informaticii 2008_.\r\n\r\n* Menţiune, _ONI 2008_, Ploieşti, locul 8 şi argint.\r\n\r\n* Membru în comisia concursului interjudeţean de matematică şi informatică _Grigore Moisil, 2009_.\r\n\r\n* Membru în comisia _lotului naţional de informatică, 2009_.\r\n\r\n* Deputy Leader al delegaţiei României la _CEOI, 2009_.\r\n\r\nh2. Eu şi info{_arena_}\r\n\r\nArticole pe care le-am scris:\r\n\r\n* \'Tree decompositions\':tree-decompositions\r\n* \'Treapuri\':treapuri\r\n* \'Deque şi aplicaţii\':deque-si-aplicatii\r\n\r\nProbleme pe care le-am adăugat în arhiva educaţională:\r\n\r\n* \'Cuplaj maxim în graf bipartit\':problema/cuplaj\r\n* \'Componente tare conexe\':problema/ctc\r\n* \'Componente biconexe\':problema/biconex\r\n* \'Subsecvenţa de sumă maximă\':problema/ssm\r\n* \'Parantezare optimă de matrici\':problema/podm\r\n\r\nAr fi fost mai multe dacă nu aş fi fost şi coordonator. :)',3146,'protected',NULL,NULL),('newsletter/ai-mas-winter-olympics','AI-MAS Winter Olympics','2010-02-26 17:40:22','2010-02-26 18:00:36','În acest weekend are loc \'*AI-MAS Winter Olympics*\':http://www.aiolympics.ro, un mare eveniment destinat inteligenţei artificiale organizat de laboratorul AI-MAS din cadrul Universităţii Politehnice din Bucureşti. Pentru a înţelege mai bine despre ce e vorba, vă invităm să citiţi prezentarea evenimentului:\r\n\r\nbq. Te-ai întrebat vreodată pentru ce înveţi toţi aceşti algoritmi? Olimpiadele sunt fun, concursurile de informatică îţi dau adrenalină, dar asta nu e totul! Cunoştinţele pe care le dobândeşti te pregătesc pentru a ataca cele mai dificile probleme nerezolvate din Computer Science.\r\n\r\nAI-MAS Winter Olympics este un eveniment dedicat *Inteligeţei Artificiale*. Organizat de laboratorul AI-MAS al Universităţii Politehnica Bucureşti, acest eveniment vrea să îţi arate că inteligenţa artificială nu este numai în filme SF sau în laboratoare avansate, ci este ceva care există şi care deja îţi face viaţa mai uşoară. Mai mult de atât, este o direcţie pe care o poţi urma şi în care pregătirea ta de olimpic poate face o diferenţă !\r\n\r\nComponenta principală a evenimentului este \'Workshop On Real Life Applications\':http://www.aiolympics.ro/eveniment/, o serie de prezentări în care companii mari îţi vor arăta cum inteligenţa artificială le oferă un avantaj competitiv. Ingineri din partea *Facebook* vin pentru prima oară în România, alături de membri ai Academiei Române şi reprezentati ai unor companii importante: IBM, BitDefender, Thales, Kaspersky, Ropardo. Suntem siguri că subiectele discutate îţi vor deschide apetitul pentru inteligenţă artificială.\r\n\r\nÎn plus vei putea vizita *AI-MAS Village*, un loc cu aplicaţii interesante care folosesc tehnici de AI, cu roboţi de tip line-follower şi alţii mai inediţi. În pauzele workshop-ului vom proiecta finala competiţiei Crafting Quest -- meciuri AI vs AI între agenţi inteligenţi. Vei putea discuta cu vorbitorii de la workshop, cu companiile prezente şi cu alţi pasionaţi de acest domeniu.\r\n\r\nEvenimentul are loc *sâmbătă, 27 februrarie,* în holul EC al Facultăţii de Automatică şi Calculatoare, UPB. Pentru a participa, este nevoie să te \'înregistrezi\':http://www.aiolympics.ro/eveniment/inregistrare/?code=infoar pe site-ul evenimentului; special pentru utilizatorii Infoarena, poţi folosi codul *infoar* la înregistrare. Pentru a avea asigurat un loc în amfiteatrul principal este nevoie să te prezinţi la eveniment între orele 8.00 - 9.00. Evenimentul se termină în jurul orei 18.00 şi este urmat de un after-party cu karaoke.\r\n\r\nTe aşteptăm!',1792,'public',NULL,NULL),('newsletter/ai-mas-winter-olympics','AI-MAS Winter Olympics','2010-02-26 17:40:22','2010-02-26 18:08:53','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nÎn acest weekend are loc \'*AI-MAS Winter Olympics*\':http://www.aiolympics.ro, un mare eveniment destinat inteligenţei artificiale organizat de laboratorul AI-MAS din cadrul Universităţii Politehnice din Bucureşti. Pentru a înţelege mai bine despre ce e vorba, vă invităm să citiţi prezentarea evenimentului:\r\n\r\nbq. Te-ai întrebat vreodată pentru ce înveţi toţi aceşti algoritmi? Olimpiadele sunt fun, concursurile de informatică îţi dau adrenalină, dar asta nu e totul! Cunoştinţele pe care le dobândeşti te pregătesc pentru a ataca cele mai dificile probleme nerezolvate din Computer Science.\r\n\r\nbq. AI-MAS Winter Olympics este un eveniment dedicat *Inteligeţei Artificiale*. Organizat de laboratorul AI-MAS al Universităţii Politehnica Bucureşti, acest eveniment vrea să îţi arate că inteligenţa artificială nu este numai în filme SF sau în laboratoare avansate, ci este ceva care există şi care deja îţi face viaţa mai uşoară. Mai mult de atât, este o direcţie pe care o poţi urma şi în care *pregătirea ta de olimpic poate face o diferenţă*!\r\n\r\nbq. Componenta principală a evenimentului este \'Workshop On Real Life Applications\':http://www.aiolympics.ro/eveniment/, o serie de prezentări în care companii mari îţi vor arăta cum inteligenţa artificială le oferă un avantaj competitiv. Ingineri din partea *Facebook* vin pentru prima oară în România, alături de membri ai Academiei Române şi reprezentati ai unor companii importante: IBM, BitDefender, Thales, Kaspersky, Ropardo. Suntem siguri că subiectele discutate îţi vor deschide apetitul pentru inteligenţă artificială.\r\n\r\nbq. În plus vei putea vizita *AI-MAS Village*, un loc cu aplicaţii interesante care folosesc tehnici de AI, cu roboţi de tip line-follower şi alţii mai inediţi. În pauzele workshop-ului vom proiecta finala competiţiei Crafting Quest -- meciuri AI vs AI între agenţi inteligenţi. Vei putea discuta cu vorbitorii de la workshop, cu companiile prezente şi cu alţi pasionaţi de acest domeniu.\r\n\r\nbq. Evenimentul are loc *sâmbătă, 27 februrarie,* în holul EC al Facultăţii de Automatică şi Calculatoare, UPB. Pentru a participa, este nevoie să te \'înregistrezi\':http://www.aiolympics.ro/eveniment/inregistrare/?code=infoar pe site-ul evenimentului; special pentru utilizatorii Infoarena, poţi folosi codul *infoar* la înregistrare. Pentru a avea asigurat un loc în amfiteatrul principal este nevoie să te prezinţi la eveniment între orele 8.00 - 9.00. Evenimentul se termină în jurul orei 18.00 şi este urmat de un after-party cu karaoke.\r\n\r\nbq. Te aşteptăm!',1792,'public',NULL,NULL),('runda/problemiada_12','Problemiada #12','2010-02-28 18:08:03','2010-02-28 18:15:47','h1. == roundparam(round_id=\"problemiada_12\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"problemiada_12\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"problemiada_12\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"problemiada_12\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"problemiada_12\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/problemiada_12/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"problemiada_12\" score=\"1\")==',5748,'round: problemiada_12',NULL,NULL),('implica-te/arhiva-educationala','Arhiva educaţională','2008-02-23 13:13:01','2010-02-27 19:34:36','h1. Arhiva educationala ==Stars(rating=\"5\")==\r\n\r\nSe propune construirea unei noi arhive de probleme care sa aiba exclusiv scop educational. Spre deosebire de probleme de concurs in care se imbina mai multi algoritmi si rezolvarea de obicei nu este evidenta, problemele din aceasta arhiva vor fi create special pentru cei care vor sa invete cum sa implementeze un algoritm sau o metoda de rezolvare anume. Se va permite accesul la teste, surse si se vor da si link-uri catre documentatie. Mai multe despre acest proiect gasiti \'aici\':propuneri/6-arhiva-educationala.\r\n\r\n(toc)*{text-align:center} *Continut*\r\n* \'Cum ne poti ajuta?\':implica-te/arhiva-educationala#cum\r\n* \'Echipa implicata in proiect\':implica-te/arhiva-educationala#echipa\r\n* \'Documentatie\':implica-te/arhiva-educationala#documentatie\r\n* \'Continutul arhivei\':implica-te/arhiva-educationala#probleme\r\n\r\nh2(#cum). Cum ne poti ajuta?\r\n\r\n1. Ofera sugestii la dezvoltarea proiectului.\r\n2. Contribuie cu feedback pentru a imbunatati calitatea problemelor existente.\r\n3. Vino cu idei pentru probleme noi.\r\n\r\nAjuta si tu la randul tau comunitatea infoarena! \r\n\r\nh2(#echipa). Echipa implicata in proiect\r\n\r\nEchipa care este implicata activ in acest proiect este alcatuita din urmatorii membri:\r\n\r\n* == user(user=\"Marius\" type=\"tiny\") ==, coordonator de proiect\r\n* == user(user=\"savim\" type=\"tiny\") ==\r\n* == user(user=\"cezarmocan\" type=\"tiny\") ==\r\n* == user(user=\"GavrilaVlad\" type=\"tiny\") ==\r\n* == user(user=\"mishu91\" type=\"tiny\") ==\r\n* == user(user=\"GheorgheMihai\" type=\"tiny\") ==\r\n\r\nPe langa cei de mai sus, de-a lungul timpului au contribuit considerabil la acest proiect \'o serie de alti membri ai comunitatii infoarena\':implica-te/arhiva-educationala/membri-emeritus. Le multumim pe aceasta cale!\r\n\r\nh2(#documentatie). Documentatie\r\n\r\nFiecare voluntar are obligatia sa citeasca urmatoarele materiale inainte de a putea trece efectiv la lucru:\r\n\r\n* \'Editare de probleme\':documentatie/editare-de-probleme\r\n* \'Ghid evaluator\':documentatie/ghid-evaluator\r\n* \'Ghid pentru arhiva educationala\':documentatie/arhiva-educationala\r\n\r\nh2(#probleme). Continutul arhivei\r\n\r\nIn tabelul de mai jos se afla probleme la care se lucreaza in momentul de fata. Finalizarea lor reprezinta unul dintre $OKR$-urile din trimestrul IV, 2009. Pentru a va familiariza si cu restul obiectivelor din acest trimestru, cititi \'aici\':okr.\r\n\r\ntable(example). |_. Denumire problema|_. Voluntar|_. Finalizat|_. Review |\r\n| \'Arbori de intervale (aplicaţie cu 4 tipuri de operaţii)\':problema/arbint2 | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"1\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Arbori de intervale 2D\':problema/arbint2d | == user(user=\"savim\" type=\"tiny\") == | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'NIM\':problema/nim | == user(user=\"GavrilaVlad\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Punct în poligon oarecare\':problema/pinpo | == user(user=\"cezarmocan\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Treapuri\':problema/treapuri | == user(user=\"marius\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Interclasarea a doi vectori sortati\':problema/interclas | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Aria unui poligon\':problema/ariapoli | == user(user=\"pauldb\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Distanţa maximă între două puncte în plan\':problema/cmdp | ==user(user=\"GheorgheMihai\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n| \'Arbori de căutare\':problema/arbcautare | ==user(user=\"bogdan2412\" type=\"tiny\") == | ==Stars(rating=\"0.5\" scale=\"1\" type=\"small\")== | ==Stars(rating=\"0\" scale=\"1\" type=\"small\")== |\r\n\r\nIn tabelul de mai jos se afla sugestii privind algoritmii care trebuie sa se gaseasca sub forma de probleme in arhiva educationala. Puteti veni oricand cu propuneri si sugestii de probleme noi pe \"forum\":/forum/index.php?topic=3401.0.\r\n\r\ntable(example). |_. Denumire problema|_. Categoria|\r\n| Dreptunghiul de arie maximă (?) | Divide et impera |\r\n|Knapsack|Programare dinamica|\r\n|Sprague-Grundy|Teoria jocurilor|\r\n|Algoritmul lui Gauss|Matematica|\r\n|Numerele lui Stirling|Matematica|\r\n| Principiul lui Dirichlet | Matematică |\r\n|Problema de acoperire|Programare dinamica + Backtracking|\r\n|Algoritmul Stoer-Wagner|Algoritmi pe grafuri|\r\n|Heavy Path Decomposition|Algoritmi pe grafuri|\r\n|Arbore -> cod Prufer|Algoritmi pe grafuri|\r\n|Cod Prufer -> arbore|Algoritmi pe grafuri|\r\n|Distanta maxima intre 2 noduri intr-un arbore|Algoritmi pe grafuri|\r\n|Siruri de sufixe|Siruri de caractere|\r\n|Arbori de sufixe|Siruri de caractere|\r\n|Automate - Aho Corasick|Siruri de caractere|\r\n|Algoritmi {$O(sqrtN)$}|Structuri de date|\r\n|Ortogonal Range Search|Structuri de date|\r\n|Intersectia a doua drepte|Geometrie|\r\n|Punct in poligon convex|Geometrie|\r\n|Diagrame Voronoi|Geometrie|\r\n|Minimum enclosing circle|Geometrie|\r\n|Sortare prin numarare|Diverse|\r\n|RadixSort|Diverse|\r\n|Operatii pe numere mari|Diverse|\r\n\r\nh2. Discutii pe forum\r\n\r\n==SmfTopics(board_id=\"61\")==',3146,'protected',NULL,NULL),('newsletter/dot-com-2009-2','newsletter/dot-com-2009-2','2010-03-03 10:47:26','2010-03-03 10:47:26','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nIată că a venit primăvara şi mai este doar o lună pana la olimpiada naţională. Nu-i aşa că trece repede timpul...? Pe ultima sută de metri, infoarena te antrenează cu două concursuri importante!\r\n\r\nTe invităm să participi la runda a doua a concursului organizat de membrii comunităţii, .com 2009.\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. Prima rundă se desfăşoară\r\n*Duminică, 14 martie, orele 09^00^ - 14^00^*. |\r\n\r\nVezi \'pagina concursului\':dot-com/2009 ca să afli cum poţi participa.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"dot-com/2009/runda-1\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre .com 2009\r\n\r\nConcursul are o singură grupă valorică, dar cele 3 probleme propuse au dificultăţi variind între gimnaziu şi liceu clasele 11-12.\r\n\r\nOrganizatorii concursului sunt:\r\n\r\n* \'Stan Şerban Andrei\':utilizator/savim\r\n* \'Cezar Mocan\':utilizator/cezarmocan\r\n* \'Radu Zernoveanu\':utilizator/raduzer\r\n* \'Teodor Anton Pripoae\':utilizator/toni2007\r\n* \'Mihai Gheorghe\':utilizator/gheorghemihai\r\n* \'Cosmin Mihai Tutunaru\':utilizator/stocarul',3997,'public',NULL,NULL),('runda/vot/voteaza_miruna','Voteaza Miruna','2010-03-05 17:11:16','2010-03-05 17:11:16','h1. Voteaza Miruna\r\n\r\n_Miruna este curajoasa si nonconformista, stiind sa rezolve problemele simplu si eficient._\r\n\r\nAici puteti vota pentru Miruna in cadrul \"concursului de vot al personajului preferat Infoarena\":runda/vot.\r\n\r\nVotarea incepe ==roundparam(round_id=\"voteaza_miruna\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"voteaza_miruna\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"voteaza_miruna\" units=\"2\") ==\r\n\r\n\'*Rezultate*\':runda/vot/voteaza_miruna/clasament\r\n\r\nh2. Itemi de vot\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"voteaza_miruna\" score=\"1\")==',8689,'public',NULL,NULL),('runda/voteaza_miruna','voteaza_miruna','2010-03-05 17:01:52','2010-03-05 17:01:52','h1. == roundparam(round_id=\"voteaza_miruna\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"voteaza_miruna\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"voteaza_miruna\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"voteaza_miruna\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"voteaza_miruna\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/voteaza_miruna/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"voteaza_miruna\" score=\"1\")==',8689,'round: voteaza_miruna',NULL,NULL),('runda/x-treme_april_challenge','x-treme_april_challenge','2010-03-05 17:44:07','2010-03-05 17:44:07','h1. == roundparam(round_id=\"x-treme_april_challenge\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"x-treme_april_challenge\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"x-treme_april_challenge\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"x-treme_april_challenge\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"x-treme_april_challenge\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/x-treme_april_challenge/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"x-treme_april_challenge\" score=\"1\")==',8689,'round: x-treme_april_challenge',NULL,NULL),('concursuri','Concursuri organizate de infoarena','2006-11-05 23:17:11','2010-02-07 22:14:40','h1. Concursuri organizate de infoarena\r\n\r\nIn aproape 4 ani de activitate, infoarena a organizat cateva zeci de concursuri/runde online. Fiecare concurs are un format aparte. De la o runda la cinci, de la cateva ore la cateva zile sau chiar o saptamana, de la cateva probleme la 20, concursurile infoarena variaza in amploare, dificultate si popularitate.\r\n\r\n(toc)*{text-align:center} *Concursuri*\r\n* \'Algoritmiada\':concursuri#algoritmiada\r\n* \'preONI\':concursuri#preoni\r\n* \'Happy Coding\':concursuri#happy\r\n* \'.com\':concursuri#dot-com\r\n* \'Autumn Warmup\':concursuri#autumn\r\n** \'Autumn Warmup 2007\':concursuri#autumn2007\r\n** \'Autumn Warmup 2006\':concursuri#autumn2006\r\n* \'Summer Challenge\':concursuri#summer\r\n** \'Summer Challenge 2009\':concursuri#summer2009\r\n** \'Summer Challenge 2007\':concursuri#summer2007\r\n** \'Summer Challenge 2006\':concursuri#summer2006\r\n* \'Alte concursuri\':concursuri#others\r\n\r\nh2(#algoritmiada). Algoritmiada\r\n\r\nNoul concurs _de marca_ infoarena isi propune sa ii pregateasca pe toti pasionatii de algoritmi.\r\n\r\ntable(layout). |_. Algoritmiada 2010 (\'pagina concursului\':algoritmiada-2010)|\r\n|* !>template/algoritmiada-2010/header?logo2010.jpg! *{\'Runda 1\':algoritmiada-2010/runda-1}*\r\n* *{\'Runda 2\':algoritmiada-2010/runda-2}*\r\n* *{\'Runda 3\':algoritmiada-2010/runda-3}*\r\n* *{\'Runda 4\':algoritmiada-2010/runda-4}*\r\n* *{\'Runda Finala\':algoritmiada-2010/runda-finala}*|\r\n\r\ntable(layout). |_. Algoritmiada 2009 (\'pagina concursului\':algoritmiada-2009)|\r\n|* !>template/algoritmiada-2009/header?logo.jpg! *{\'Runda 1\':algoritmiada-2009/runda-1}*\r\n* *{\'Runda 2\':algoritmiada-2009/runda-2}*\r\n* *{\'Runda 3\':algoritmiada-2009/runda-3}*\r\n* *{\'Runda Finala\':algoritmiada-2009/runda-finala}*|\r\n\r\nh2(#preoni). Seria preONI\r\n\r\nTimp de 5 ani a fost cel mai important concurs organizat de infoarena. Scopul sau era sa pregateasca elevii pentru \"Olimpiada Nationala de Informatica\":http://olimpiada.info/.\r\n\r\ntable(layout). |_. preONI 2008 (\'pagina concursului\':preoni-2008)|\r\n|* !>template/preoni-2008/header?a.jpg! *{\'Runda 1\':preoni-2008/runda-1}*\r\n* *{\'Runda 2\':preoni-2008/runda-2}*\r\n* *{\'Runda 3\':preoni-2008/runda-3}*\r\n* *{\'Runda 4\':preoni-2008/runda-4}*\r\n* *{\'Runda Finala\':preoni-2008/runda-finala}*|\r\n\r\ntable(layout). \r\n|_. preONI 2007 (\'pagina concursului\':preoni-2007)|_. preONI 2006 (\'pagina concursului\':preoni-2006) |\r\n|*  !>template/preoni-2007/header?logo.jpg 70%! *{\'Runda 1\':preoni-2007/runda-1}* \r\n* *{\'Runda 2\':preoni-2007/runda-2}*\r\n* *{\'Runda 3\':preoni-2007/runda-3}*\r\n* *{\'Runda 4\':preoni-2007/runda-4}*\r\n* *{\'Runda Finala\':preoni-2007/runda-finala}*\r\n|*  !>template/preoni-2006?hlogo.gif! *{\'Runda 1\':preoni-2006/runda-1}*\r\n* *{\'Runda 2\':preoni-2006/runda-2}*\r\n* *{\'Runda 3\':preoni-2006/runda-3}*\r\n* *{\'Runda 4\':preoni-2006/runda-4}*\r\n* *{\'Finala in Focsani\':preoni-2006/finala}*|\r\n|_. preONI 2005 (\'pagina concursului\':preoni-2005)|_. preONI 2004 (\'pagina concursului\':preoni-2004)|\r\n|* *{\'Runda 1\':preoni-2005/runda-1}*\r\n* *{\'Runda 2\':preoni-2005/runda-2}*\r\n* *{\'Runda 3\':preoni-2005/runda-3}*\r\n|* *{\'Runda 1\':preoni-2004/runda-1}*\r\n* *{\'Runda 2\':preoni-2004/runda-2}*|\r\n\r\nh2(#happy). Happy Coding\r\n\r\nUn concurs infoarena mai neobisnuit. _Happy Coding inseamna programare cu zambetul pe buze, placere si distractie pura!_\r\n\r\nConcursurile Happy Coding dispun de evaluator live si au timp de lucru lejer. Nu vei mai fi stresat de pana la aflarea rezultatelor. Afli pe loc daca solutiile tale sunt bune. In plus, poti lucra si ziua si noaptea, dupa sau in timpul orelor de scoala.\r\n\r\n!>happy-coding-2005-1?logo.jpeg!\r\n\r\n* \'*Happy Coding 2008*\':happy-coding-2008\r\n* \'*Happy Coding 2007*\':happy-coding-2007\r\n* *{\'Happy coding 1 (2005)\':happy-coding-2005-1}*\r\n* *{\'Happy coding 2\':happy-coding-2005-2}*\r\n* *{\'Happy coding 3 (2006)\':happy-coding-2006}*\r\n\r\nh2(#dot-com). .com\r\n\r\n==include(page=\"dot-com/description\")==\r\n\r\nh3(#dot-com2009). .com 2009 (\'pagina concursului\':dot-com/2009)\r\n\r\n* *{\'Runda 1\':dot-com/2009/runda-1}*\r\n\r\nh2(#autumn). Autumn Warmup\r\n\r\nh3(#autumn2007). Autumn Warmp 2007 (\'pagina concursului\':autumn-warmup-2007)\r\n\r\n* *{\'Runda 1\':autumn-warmup-2007/runda-1}*\r\n* *{\'Runda 2\':autumn-warmup-2007/runda-2}*\r\n* *{\'Runda 3\':autumn-warmup-2007/runda-3}*\r\n\r\nh3(#autumn2006). {\'Autumn Warmup 2006\':warm-up-2006}\r\n\r\nh2(#summer). Summer Challenge\r\n\r\nO serie noua de concursuri infoarena. Acestea se organizeaza in timpul vacantei de vara pentru cei care nu vor _sa-si iasa din mana_. :)\r\n\r\nh3(#summer2009). Summer Challenge 2009 (\'pagina concursului\':summer-challenge-2009)\r\n\r\n* *{\'Runda 1\':summer-challenge-2009/runda-1}*\r\n* *{\'Runda 2\':summer-challenge-2009/runda-2}*\r\n* *{\'Runda 3\':summer-challenge-2009/runda-3}*\r\n\r\nh3(#summer2007). Summer Challenge 2007 (\'pagina concursului\':summer-challenge-2007)\r\n\r\n* *{\'Runda 1\':summer-challenge-2007/runda-1}*\r\n* *{\'Runda 2\':summer-challenge-2007/runda-2}*\r\n* *{\'Runda 3\':summer-challenge-2007/runda-3}*\r\n\r\nh3(#summer2006). Summer Challenge 2006\r\n\r\n!>summer-challenge-unu?logo!\r\n\r\n* *{\'Runda 1\':summer-challenge-unu}*\r\n* *{\'Runda 2\':summer-challenge-2}*\r\n* *{\'Runda 3\':summer-challenge-3}*\r\n\r\nh2(#others). Alte concursuri infoarena\r\n\r\n* *{\'Concursul Centrelor de Excelenta 2009\':ccex2009}*\r\n* *{\'Grigore Moisil 2009\':grigore-moisil-2009}*\r\n* *{\'Stelele Informaticii 2009\':stelele-2009}*\r\n* *{\'All you can code 2008\':all-you-can-code-2008}*\r\n* *{\'Selectie echipe ACM ICPC, UPB 2008\':acm-icpc-upb-2008}*\r\n* *{\'Junior Challenge 2008\':junior-challenge-2008}*\r\n* *{\'Grigore Moisil 2008\':grigore-moisil-2008}*\r\n* *{\'Winter Challenge 2008\':winter-challenge-2008}*\r\n* *{\'Junior Challenge 2007\':junior-challenge}*\r\n* *{\'Winter Challenge\':winter-challenge-1}*\r\n* *{\'Unirea 2007\':unirea-2007}*\r\n* *{\'Grigore Moisil By Net 2006\':moisil-by-net-2006}*\r\n!>agora-finala?logo.gif! !>warm-up-2006?logo.jpeg! \r\n* *{\'Bursele agora, editia 6, finala online\':agora-finala}* \r\n* *{\'Bacalaureat 2005\':bacalaureat-2005}* \r\n* *{\'Concurs de incalzire\':warm-up-2004}* \r\n* *{\'preOJI 2004\':preoji-2004}*',2028,'protected',NULL,NULL),('home','infoarena -  comunitate informatica, concursuri de programare','2006-11-05 14:45:56','2010-02-21 17:39:20','h1. Bine ai venit pe infoarena!\r\n\r\nSuntem o comunitate de tineri pasionati de informatica si programare.\r\nInvatam impreuna participand la concursuri online de programare, citind stiri si articole despre informatica sau discutand pe forum.\r\n\r\n\'*&raquo; Afla mai multe despre noi!*\':despre-infoarena\r\n\r\np={width:700px; max-width:99%; margin:auto; background-color: rgb(210, 244, 219); border: 0; padding: 0.5em; -moz-border-radius:7px; -webkit-border-radius:7px}. A treia a concursului \'*Algoritmiada 2010*\':algoritmiada-2010 s-a incheiat. Felicitări \'*câştigătorilor*\':algoritmiada-2010/clasament/runda-3/5-8!\r\nParticipă şi la \'*runda 4*\':algoritmiada-2010/runda-4!\r\n\r\nh1. Ultimele insemnari de pe \'blog\':blog \'!{vertical-align:middle}home?rss_icon.jpg!\':blog?action=rss\r\n\r\n==BlogPreview(display_entries=\"10\")==\r\n',2028,'protected',NULL,NULL),('newsletter/dot-com-2009-2','.com 2009, runda 2','2010-03-03 10:47:26','2010-03-09 10:32:13','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nDeşi primăvara se lasă aşteptată, mai este doar o lună pana la olimpiada naţională. Nu-i aşa că trece repede timpul...? Pe ultima sută de metri, infoarena te antrenează cu două concursuri importante! \'.com\':dot-com/2009 revine cu o nouă rundă, iar \'Algoritmiada\':algoritmiada-2010 işi continuă seria bine cunoscută de concursuri, ajungând la runda a 4-a anul acesta.\r\n\r\nNu rata ocazia de a te antrena şi de a-ţi incerca forţele înainte de olimpiada naţionala! Chiar dacă nu te-ai calificat, concursul reprezintă un bun antrenament pentru competiţiile viitoare. Te invităm să participi la runda a doua a concursului organizat de membrii comunităţii, .com 2009.\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. A doua rundă se desfăşoară\r\n*Duminică, 14 martie, orele 09^00^ - 14^00^*. |\r\n\r\nVezi \'pagina concursului\':dot-com/2009 ca să afli cum poţi participa.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"dot-com/2009/runda-1\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre .com 2009\r\n\r\nConcursul are o singură grupă valorică, dar cele 3 probleme propuse au dificultăţi variate.\r\n\r\nOrganizatorii concursului sunt:\r\n\r\n* \'Stan Şerban Andrei\':utilizator/savim\r\n* \'Cezar Mocan\':utilizator/cezarmocan\r\n* \'Radu Zernoveanu\':utilizator/raduzer\r\n* \'Teodor Anton Pripoae\':utilizator/toni2007\r\n* \'Mihai Gheorghe\':utilizator/gheorghemihai\r\n* \'Cosmin Mihai Tutunaru\':utilizator/stocarul',3997,'public',NULL,NULL),('newsletter/dot-com-2009-2','.com 2009, runda 2','2010-03-03 10:47:26','2010-03-09 10:54:07','Bună, ==UserInfo(user=\"%username%\" info=\"fullname\")==!\r\n\r\nDeşi primăvara se lasă aşteptată, mai este doar o lună pana la olimpiada naţională. Nu-i aşa că trece repede timpul...? Pe ultima sută de metri, infoarena te antrenează cu două concursuri importante! \'.com\':dot-com/2009 revine cu o nouă rundă, iar \'Algoritmiada\':algoritmiada-2010 işi continuă seria bine cunoscută de concursuri, ajungând la runda a 4-a anul acesta.\r\n\r\nNu rata ocazia de a te antrena şi de a-ţi incerca forţele înainte de olimpiada naţionala! Chiar dacă nu te-ai calificat, concursul reprezintă un bun antrenament pentru competiţiile viitoare. Te invităm să participi la runda a doua a concursului organizat de membrii comunităţii, .com 2009.\r\n\r\n|{padding:.5em; margin:.5em; background-color:#d0ffbe; border:1px solid green; font-size:10pt;}. A doua rundă se desfăşoară\r\n*Duminică, 14 martie, orele 09^00^ - 14^00^*. |\r\n\r\nVezi \'pagina concursului\':dot-com/2009 ca să afli cum poţi participa.\r\n\r\nSucces!\r\n\r\n==include(username=\"%username%\" round_url=\"dot-com/2009/runda-1\" page=\"template/newsletter/rating\")==\r\n\r\nh2{font-size: 12pt}. Despre .com 2009\r\n\r\nConcursul are o singură grupă valorică,spre deosebire de prima runda, in runda a doua sunt propuse 3 probleme cu dificultăţi variate. În urma primei runde, dorim sa le spunem felicitari primilor 3 clasaţi. Primul loc a fost caştigat de \'Andrei Purice\':utilizator/Protoman cu 200 de puncte, urmat de \'Perţicaş Cătălin\':utilizator/perticas_catalin cu 190 de puncte, iar locul 3 a fost ocupat de \'Budău Adrian\':utilizator/freak93 cu 160 de puncte.\r\n\r\nOrganizatorii concursului sunt:\r\n\r\n* \'Stan Şerban Andrei\':utilizator/savim\r\n* \'Cezar Mocan\':utilizator/cezarmocan\r\n* \'Radu Zernoveanu\':utilizator/raduzer\r\n* \'Teodor Anton Pripoae\':utilizator/toni2007\r\n* \'Mihai Gheorghe\':utilizator/gheorghemihai\r\n* \'Cosmin Mihai Tutunaru\':utilizator/stocarul',3997,'public',NULL,NULL),('dot-com/2009/runda-2','.com 2009, Runda 2','2009-11-09 16:02:40','2010-03-08 07:46:09','h1. == roundparam(round_id=\"dotcom2009-runda2\" param=\"title\") ==\r\n\r\n(htabs)* \'Detalii\':dot-com/2009\r\n* \'Runda 1\':dot-com/2009/runda-1\r\n*(active) \'Runda 2\':dot-com/2009/runda-2\r\n* \'Clasament\':dot-com/2009/clasament\r\n\r\nRunda se va desfasura ==roundparam(round_id=\"dotcom2009-runda2\" param=\"start_time\" strong=\"true\")==, si va dura ==roundparam(round_id=\"dotcom2009-runda2\" param=\"duration\" strong=\"true\")== ore. Participantii vor avea de rezolvat 3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\n==roundregister(round_id=\"dotcom2009-runda2\")==\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie. Inscrierea se face printr-un simplu click. *Nu trebuie sa va inregistrati din nou pe site!*\r\n\r\nInscrierile se pot face pana la inceperea rundei. Dupa afisarea problemelor, nu te mai poti inscrie.\r\n\r\nh2. Probleme\r\n\r\n== Tasks(round_id=\"dotcom2009-runda2\" score=\"1\")==\r\n\r\nSolutiile le veti gasi \'aici\':dot-com/2009/solutii/runda-2 dupa ce runda va lua sfarsit.\r\n\r\nh2. Clasament\r\n\r\n* \'Clasament Runda 2\':dot-com/2009/clasament/runda-2\r\n\r\nh2. Organizatori\r\n\r\n* ==user(user=\"savim\" type=\"tiny\")==\r\n* ==user(user=\"cezarmocan\" type=\"tiny\")==\r\n* ==user(user=\"raduzer\" type=\"tiny\")==\r\n* ==user(user=\"toni2007\" type=\"tiny\")==\r\n* ==user(user=\"gheorghemihai\" type=\"tiny\")==\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==user(user=\"wefgef\" type=\"tiny\")==\r\n\r\n',2028,'round: dotcom2009-runda2',NULL,NULL),('utilizator/wefgef','Profil Andrei Grigorean','2006-11-24 21:00:41','2010-03-02 23:44:30','h2. Despre mine\r\n\r\n* Sunt student in anul III la Facultatea de Matematica si Informatica, Universitatea Bucuresti.\r\n* Am inceput sa lucrez pe infoarena la sfarsitul clasei a X-a, si pot spune ca de-a lungul timpului a fost principala mea sursa de pregatire.\r\n* Primii trei ani de liceu i-am facut la C.N. \"Al. Papiu Ilarian\" din Targu Mures, iar in clasa a XII-a m-am transferat la \"ICHB\":http://www.ichb.ro/.\r\n* In clasa a XI-a am inceput serios informatica, dupa ce l-am cunoscut \"Cosmin Negruseri\":/utilizator/cosmin, care m-a ajutat foarte mult in cei doi ani de liceu ce au urmat.\r\n* Celelalte persoane care au avut un cuvant de spus in pregatirea mea sunt: \"Mircea Pasoi\":/utilizator/domino, \"Silviu Ganceanu\":/utilizator/silviug, \"Adrian Vladu\":/utilizator/azotlichid si \"Mugurel Ionut Andreica\":/utilizator/mugurelionut.\r\n* In vara/toamna anului 2009 am efectuat un internship la Google in Mountain View, CA.\r\n\r\nh2. Membru in comisii\r\n\r\n* CEOI 2009\r\n* Lot Piatra Neamt 2008, Iasi 2008, Bistrita 2009\r\n* ONI 2008, 2009\r\n* Algoritmiada 2009\r\n* preOni 2008\r\n* .campion 2008, 2009\r\n* Stelele Informaticii 2007-2008, 2008-2009.\r\n\r\nh2. Distinctii primite\r\n\r\n* Medalie de argint la IOI 2007.\r\n* Premiul I la ONI 2007.\r\n* Premiul I la finala preONI 2007.\r\n* Premiul I la concursul Stelele Informaticii 2006.\r\n* Mentiuni la ONI 2006 si ONI 2005.\r\n* Multe alte premii si mentiuni la concursuri interjudetene.\r\n\r\nh2. Articole\r\n\r\n* \"Taietura minima in graf cu costuri\":/taietura-minima, infoarena.\r\n\r\nh2. In afara informaticii\r\n\r\n* In general ascult muzica veche, rock din anii \'70, \'80.\r\n* Imi plac motoarele.\r\n* As merge pe munte daca as avea timp.\r\n* Colectionez monede.\r\n* RIP Jack.\r\n* Acum am parul scurt.\r\n\r\nh2. Prieteni pe infoarena (ordine aleatoare)\r\n\r\n* Shay-Fu: == User(user=\"Cosmin\" type=\"tiny\") ==\r\n* == User(user=\"domino\" type=\"tiny\") ==\r\n* == User(user=\"ditzonec\" type=\"tiny\") ==\r\n* == User(user=\"greco\" type=\"tiny\") ==\r\n* == User(user=\"azotlichid\" type=\"tiny\") ==\r\n* == User(user=\"silviug\" type=\"tiny\") ==\r\n* == User(user=\"wickedman\" type=\"tiny\") ==\r\n* == User(user=\"danielp\" type=\"tiny\") ==\r\n* == User(user=\"fluffy\" type=\"tiny\") ==\r\n* == User(user=\"filipb\" type=\"tiny\") ==\r\n* == User(user=\"svalentin\" type=\"tiny\") ==\r\n* == User(user=\"astronomy\" type=\"tiny\") ==\r\n* == User(user=\"mugurelionut\" type=\"tiny\") ==\r\n* == User(user=\"gcosmin\" type=\"tiny\") ==\r\n* == User(user=\"bogdan2412\" type=\"tiny\") ==\r\n* == User(user=\"crawler\" type=\"tiny\") ==\r\n* == User(user=\"binary_fire\" type=\"tiny\") ==\r\n* == User(user=\"megabyte\" type=\"tiny\") ==\r\n* == User(user=\"pauldb\" type=\"tiny\") ==\r\n* == User(user=\"alexthero\" type=\"tiny\") ==\r\n* == User(user=\"victorsb\" type=\"tiny\") ==\r\n* == User(user=\"sims_gl\" type=\"tiny\") ==\r\n* == User(user=\"cimi\" type=\"tiny\") ==\r\n* == User(user=\"mariusdrg\" type=\"tiny\") ==\r\n* == User(user=\"prostu\" type=\"tiny\") ==\r\n* == User(user=\"adriana_s\" type=\"tiny\") ==\r\n* == User(user=\"georgiana\" type=\"tiny\") ==\r\n* == User(user=\"stef2n\" type=\"tiny\") ==\r\n* Va urma...\r\n\r\nh2. Dusmani pe infoarena\r\n\r\n* == User(user=\"eval\" type=\"tiny\") == (nu vrea sa imi dea destule puncte)\r\n* == User(user=\"chucknorris\" type=\"tiny\") == (e mai bun ca mine)\r\n\r\nh2. Poze IOI 2007, Zagreb, Croatia\r\n\r\n* Echipa Romaniei\r\n!utilizator/wefgef?P1050159.JPG 50%!\r\n\r\n* Inveselind marmota\r\n!utilizator/wefgef?P1050311.JPG 50%!\r\n\r\n* Aratand dubios :P\r\n!utilizator/wefgef?P1050143.JPG 40%!',2028,'protected',NULL,NULL),('planificare/camp-2.3.1','Coding Camp \"We can do it\"','2010-03-03 15:34:27','2010-03-11 17:20:05','h1. Coding Camp _\"We can do it\"_\r\n\r\nNe intalnim in weekend-ul *13-14 martie 2010*, in fiecare zi intre orele *10:00* si *18:00*, la ICHB.\r\n\r\nScopul final al coding camp-ului este familiarizarea mai multor membri ai comunitatii/echipei cu codebase-ul infoarena si lansarea versiunii \"infoarena 2.3.1\":http://hackers.devnet.ro/milestone/2.3.1%20Yes%20We%20Can.\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu Linux instalat pe el (preferabil ubuntu).\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri\r\n\r\nh2. Participanti\r\n\r\nSpecifica cand poti veni si cat poti sta.\r\n\r\n* ==user(user=\"devilkind\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"wefgef\" type=\"tiny\")==: sambata\r\n* ==user(user=\"stef2n\" type=\"tiny\")==: duminica\r\n\r\nh2. Agenda\r\n\r\nh3. Must have \r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n|\"Note pentru probleme\":http://hackers.devnet.ro/ticket/395|||\r\n|\"Interfata de search pentru taguri\":http://hackers.devnet.ro/ticket/391|||\r\n\r\nh3. \"Heavy\":http://shaunchng.com/gallery/main.php?g2_view=core.DownloadItem&g2_itemId=658 (pentru useri experimentati)\r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n\r\nh3. Light (pentru useri mai putin experimentati)\r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n\r\n',2993,'public',NULL,NULL),('training-path','Training path','2008-01-22 17:36:01','2010-03-11 18:24:53','h1. Training path\r\n\r\nVrem sa intocmim o baza de cunostinte fara precendent! Vrem ca aceasta pagina sa contina o lista cat mai completa cu ce trebuie sa stie un olimpic pentru a avea succes. \'Ajuta-ne\':implica-te/scrie-articole si tu!\r\n\r\n*Cosmin:* ar trebui sa facem o lista mai mica cu chestiile importante ca sa ajungi la ONI, ca sa nu se sperie cei ce abia incep.\r\n\r\nh2. Structuri de date\r\n\r\n* Liste, stive, cozi\r\n* \'Deque\':deque-si-aplicatii\r\n* \'Tabele de dispersie\':tabele-hash-prezentare-detaliata\r\n** \'Cuckoo hashing\':http://en.wikipedia.org/wiki/Cuckoo_hashing\r\n* \'Bloom filters\':http://en.wikipedia.org/wiki/Bloom_filter\r\n* \'Skiplists\':skiplists\r\n\r\n* \'Arbori indexati binar\':aib\r\n* Cozi de prioritati\r\n** \'Heap-uri\':heapuri\r\n** Mergeable heaps (maxophobic heaps sunt cel mai simple)\r\n** Pentru costuri intregi mici, un array de liste\r\n\r\n* \'Structuri de multimi disjuncte\':problema/disjoint\r\n* \'Arbori de intervale\':arbori-de-intervale\r\n* \'Tries\':problema/trie\r\n* Arbori binari de cautare (\'Treapuri\':treapuri, AVL, red-black trees)\r\n* \'Cautari ortogonale. Quad trees, kD-trees\':cautari-ortogonale\r\n\r\nh2. Algoritmi si tehnici de programare\r\n\r\nh3. Matematica\r\n\r\n* \'Inductie matematica\':http://ro.wikipedia.org/wiki/Inductie_matematica\r\n* \'Algoritmul lui Euclid\':algoritmul-lui-euclid\r\n* CMMDC binar\r\n* \'Ciurul lui Erathostene\':ciurul-lui-erathostene\r\n* \'Gray code\':coduri-gray\r\n* Rezolvare de ecuatii liniare modulare\r\n* Teorema mica a lui Fermat\r\n* \'Teorema chineza a resturilor\':teorema-chineza-a-resturilor\r\n** Probleme: \'eval\':problema/eval \'resturi\':problema/resturi \'gears in action\':http://ipsc.ksp.sk/contests/ipsc2005/real/problems/g.php\r\n* \"Numere mari: adunare, scadere, inmultire, impartire, radical\":lucrul-cu-nr-mari\r\n* Recurente si exponentiere rapida de matrici (+evaluare rapida a expresiilor folosind exponentiere in timp logaritmic), \'al K-lea termen Fibonacci\':problema/kfib\r\n* \'Principiul includerii si excluderii\':principiul-includerii-si-excluderii\r\n** Probleme: \'cowfood\':problema/cowfood, \'indep\':problema/indep, \'frac\':problema/frac\r\n* Sisteme de ecuatii liniare (Gauss)\r\n** Teorie:\r\n*** \'Gaussian elimination\':http://en.wikipedia.org/wiki/Gaussian_elimination\r\n*** \'Row echelon form\':http://en.wikipedia.org/wiki/Row_echelon_form\r\n** Probleme: \'SGU 275 To xor or not to xor\':http://acm.sgu.ru/problem.php?contest=0&problem=275 \'.campion Xor\':http://campion.edu.ro/problems/3/323/xor_ro.htm \'SGU 260 Puzzle\':http://acm.sgu.ru/problem.php?contest=0&problem=260 \'UVA 10808\':http://online-judge.uva.es/p/v108/10808.html \'UVA 326\':http://online-judge.uva.es/p/v3/326.html \'UVA 10014\':http://online-judge.uva.es/p/v100/10014.html \'BColor\':problema/bcolor \'Laser\':problema/laser \'TC XORing\':http://www.topcoder.com/stat?c=problem_statement&pm=4829&rd=8095&rm=246636&cr=270505 \'TC Escape the jail\':http://www.topcoder.com/stat?c=problem_statement&pm=7353 \'Register CEOI 2003\':http://ceoi.inf.elte.hu/probarch/03/register-en.pdf \'Tunelul groazei\':problema/tunel \'SGU 200\':http://acm.sgu.ru/problem.php?contest=0&problem=200 \'TC CoinGame\':http://www.topcoder.com/stat?c=problem_statement&pm=6005 \r\n* Simplex\r\n* \"Floyd\'s cycle finding\":http://en.wikipedia.org/wiki/Cycle_detection\r\n* Combinatorica\r\n** \'Generare de permutari\':problema/permutari, permutari cu repetitii, aranjamente, \'combinari\':problema/combinari, Stirling, Catalan, Bell, Fibonacci\r\n** Trecere de la combinare/permutare la indexul ei si invers\r\n** \'Codul Prufer. Numarare de arbori\':http://en.wikipedia.org/wiki/Pr%C3%BCfer_sequence\r\n\r\nh3. Geometrie\r\n\r\n\'computer graphics FAQ\':http://www.faqs.org/faqs/graphics/algorithms-faq/\r\n\'cursuri dupa Computational Geometry: Algorithms and Applications, Mark de Berg, M. van Krefeld, M. Overmars, O. Schwarzkopf\':http://www.cs.umd.edu/class/spring2007/cmsc754/Lects/754lects.pdf\r\n\r\n\r\n* Intersectie a doua segmente\r\n* \'Cele mai apropiate puncte dintr-un plan\':problema/cmap\r\n* Punct in interiorul unui poligon\r\n** http://geometryalgorithms.com/Archive/algorithm_0103/algorithm_0103.htm\r\n** http://tog.acm.org/editors/erich/ptinpoly/\r\n* Punct in poligon convex in $O(log n)$\r\n** http://geometryalgorithms.com/Archive/algorithm_0103/algorithm_0103.htm#Monotone%20Polygons\r\n* \'Teorema lui Pick\':http://www.cut-the-knot.org/ctk/Pick_proof.shtml\r\n** problema \'copaci\':problema/copaci\r\n* Aria unui poligon\r\n* Centrul de greutate al unui poligon\r\n* \'Triangularizare de poligon in $O(n^2)$\':http://people.csail.mit.edu/indyk/6.838-old/handouts/lec4.pdf\r\n* \'Intersectia a doua cercuri\':http://local.wasp.uwa.edu.au/~pbourke/geometry/2circle/\r\n* \'Minimal enclosing circle\':minimal-enclosing-circle\r\n* Convex hull\r\n** \'Aplicatie din Arhiva Educationala\':problema/infasuratoare\r\n** http://www.algorithmist.com/index.php/Monotone_Chain_Convex_Hull\r\n** http://en.wikipedia.org/wiki/Gift_wrapping_algorithm\r\n** Aplicatie - onion peeling in O(n^2^)\r\n* \'Baleiere verticala / radiala\':algoritmi-de-baleiere\r\n** baleiere radiala\r\n*** Se da un set S de n punct in plan. Sa se determine cercul de raza R fixata care acopera cat mai multe puncte din S. O(n^2 log n)\r\n*** Se da un set S de n puncte in plan. Sa se gaseasca o dreapta ce trece prin nr maxim de puncte din S. O(n^2^) cu hashuri pt unghiuri sau O(n^2 log n) cu baleiere radiala.\r\n*** Se da un set S de n segmente in plan. Sa se gaseasca o dreapta ce intersecteaza numarul maxim de segmente din S. O(n^2 log n) cu baleiere radiala.\r\n*** \'Construirea grafului de vizibilitate.\':http://en.wikipedia.org/wiki/Visibility_graph\r\n* \'Rotating calipers\':http://cgm.cs.mcgill.ca/~orm/rotcal.html\r\n** problema \'rubarba\':problema/rubarba\r\n** problema \'popandai2\':problema/popandai2\r\n* Intersectie de poligoane convexe\r\n* Intersectie de semiplane (fara dualizare)\r\n** problema \'camera\':problema/camera\r\n* \'Dualizare (intersectie de semiplane, diagrame Voronoi)\':http://infoarena.ro/voronoi\r\n\r\n* \'thread pe forum\':http://infoarena.ro/forum/index.php?topic=3007.0\r\n\r\nh3. Sortari si cautari\r\n\r\n* Shell sort, merge sort, heapsort, quicksort, counting sort, radix sort, \'sortare prin comparare\':problema/algsort\r\n* \'Statistici de ordine\':problema/sdo\r\n* \'Cautare binara\':problema/cautbin / ternara si \'aplicatii\':aplicatii-ale-cautarii-binare\r\n* Hill climbing\r\n\r\nh3. Greedy\r\n\r\n* \'Huffman\':problema/huffman\r\n* Job scheduling\r\n\r\nh3. Programare dinamica\r\n\r\n* \'Parantezare optima de matrici\':problema/podm\r\n* \'Cel mai lung subsir crescator $O(N*log N)$\':problema/scmax\r\n* Knapsack\r\n** Knapsack pe biti\r\n* \'Cel mai lung subsir comun\':problema/cmlsc\r\n* \'Distanta de editare a 2 cuvinte\':http://en.wikipedia.org/wiki/Levenshtein_distance\r\n* Ciclu hamiltonian in $O(n^2^ * 2^n^)$\r\n** problema \'adn\':problema/adn\r\n* Dinamicile in $3^n^$\r\n** \'explicatie\':http://forums.topcoder.com/?module=Thread&threadID=512824&start=0, \'problema\':http://www.topcoder.com/stat?c=problem_statement&pm=6678&rd=9998&rm=249548&cr=8547850\r\n* \'Arbore de cautare optim in $O(n^2)$\':http://www.ics.uci.edu/~dan/class/165/notes/OptBST.html\r\n* Dinamici pe arbori\r\n* \'Numarul posibilitatilor de acoperire a unei table cu dominouri\':probleme-de-acoperire-2#problema3\r\n* Memoizare (trading space for time)\r\n\r\nh3. Grafuri\r\n\r\n* Parcurgeri\r\n** \'DFS\':problema/dfs, \'BFS\':problema/bfs, meet in the middle bfs\r\n** \'Componente biconexe\':problema/biconex\r\n** \'Componente tare-conexe\':problema/ctc\r\n** \'Sortare topologica\':problema/sortaret\r\n** \'Ciclu eulerian\':problema/ciclueuler\r\n\r\n* Drumuri minime\r\n** \'Dijkstra\':problema/dijkstra (cu heapuri, cu set-uri, cu AINT-uri, cu coada ca pe TC - Cosmin stie)\r\n** \'Dijkstra cu costuri mici ;)\':http://www.ginfo.ro/revista/13_6/focus2.pdf cum se foloseste la problema \'car\':problema/car\r\n** A* has a lot of intuitive appeal for me. If you compare Dijkstra\'s vs. A*, Dijkstra\'s is like a puddle of water flooding outwards on a flat floor, whereas A* is like the same puddle expanding on a bumpy and graded floor toward a drain (the target node) at the lowest point in the floor. Instead of spreading out evenly on all sides, the water seeks the path of least resistance, only trying new paths when something gets in its way. The heuristic function is what provides the \'grade\' of the hypothetical floor.\r\n*** A* se foloseste foarte mult in industria jocurilor, fiind un algoritm foarte rapid in practica. Un exemplu unde este folosit este jocul de strategie Starcraft.\r\n** \'Floyd-Warshall\':problema/royfloyd\r\n** \'Bellman-Ford\':en.wikipedia.org/wiki/Bellman-Ford_algorithm\r\n*** De obicei mai simplu de implementat si cam aceeasi viteza ca si Dijkstra cu heapuri\r\n*** Sistem de inegalitati\r\n*** \'Ciclu de cost mediu minim\':ciclu-de-cost-mediu-minim\r\n* \'Flux\':problema/maxflow\r\n** Edmonds-Karp\r\n** \'Taietura minima\':taietura-minima\r\n** \'Dinic\':http://www.msri.org/about/computing/docs/magma/html/text1499.htm\r\n** \'Flux maxim de cost minim\':problema/fmcm\r\n** Flux cu capacitati inferioare\r\n** Circulatii\r\n** Problema postasului chinez\r\n*** problema \'traseu\':problema/traseu\r\n* Arbori\r\n** \'Diametrul, centrul unui arbore\':http://online-judge.uva.es/board/viewtopic.php?p=36766&highlight=#36766\r\n** \'Testare daca doi arbori sunt izomorfi\':http://online-judge.uva.es/board/viewtopic.php?p=22754&highlight=#22754\r\n** Cod Prufer\r\n* \'APM\':problema/apm\r\n** Prim\r\n** Kruskal\r\n** Al doilea APM\r\n** APM in graf orientat\r\n** Kirchhoff\'s matrix tree theorem\r\n* Pentru grafuri bipartite: \'cuplaj maxim\':problema/cuplaj, suport minim, multime independenta maxima\r\n* \'LCA\':lowest-common-ancestor, \'RMQ\':problema/rmq, Level Ancestor, \'Tree decompositions\':tree-decompositions\r\n* Colorari de muchii, graf complet/bipartit/oarecare (teorema lui Vizing)\r\n* Grafuri planare\r\n** problema \'count\':problema/count\r\n* Grafuri turneu/ciclu hamiltonian\r\n** problema \'plimbare\':problema/plimbare\r\n* {\'Implication graph si 2-SAT\':2-sat}\r\n\r\n\r\nh3. Siruri de caractere\r\n\r\n* \'Hashuri\':problema/strmatch\r\n* \'KMP\':automate-finite-si-kmp\r\n* \'Siruri de sufixe\':siruri-de-sufixe\r\n** \'In timp liniar\':suffix-array-liniar\r\n* \'Aho-Corasick\':http://www.cs.uku.fi/~kilpelai/BSA05/lectures/slides04.pdf .\r\n\r\nh3. Limbaje formale si automate finite\r\n\r\n* \'Evaluari de expresii aritmetice\':problema/evaluare\r\n* \'CYK\':http://en.wikipedia.org/wiki/CYK\r\n* Matching with wildcards\r\n* Construirea unui automat care sa accepte un set de cuvinte\r\n* Simplificare de automate\r\n* Echivalenta de automate\r\n* \'thread pe forum\':http://infoarena.ro/forum/index.php?topic=3005.0\r\n\r\nh3. Teoria jocurilor\r\n\r\n* Nim\r\n* \'Numere Sprague-Grundy\':numerele-sprague-grundy\r\n* Min-max\r\n* Alpha-beta\r\n\r\nh2. Diverse\r\n\r\nh3. \'STL @(Standard Template Library)@\':stl\r\n\r\n* vector, deque, stack, list\r\n* string\r\n* set, map, hash_map\r\n* pair\r\n* sort\r\n* priority_queue\r\n* bitset\r\n* iteratori\r\n\r\nh3. Cautari\r\n\r\n* backtracking\r\n* iterative deepening\r\n* branch and bound\r\n\r\nh3. Optimizari\r\n\r\n* Parsare\r\n* Lucru cu biti\r\n* Brute force\r\n** \'dancing links\':http://en.wikipedia.org/wiki/Dancing_Links\r\n\r\nh3. Lucrul cu memoria\r\n\r\n* \'Cacheuri de memorie\':http://en.wikipedia.org/wiki/CPU_cache\r\n** problema \'stramosi\':problema/stramosi\r\n*  \'free lists\':http://www.memorymanagement.org/glossary/f.html#free.list\r\n** problema \'eprubeta\':problema/eprubeta\r\n\r\nh3. Bulanit\r\n\r\n* Randomizare (2-opt, k-opt)\r\n* Constante\r\n* Interpolare Taylor / Gauss pentru formule polinomiale\r\n\r\nh3. \'Smenuri\':multe-smenuri-de-programare-in-cc-si-nu-numai\r\n\r\n* Smenu\' lui Batog (+ lca in $sqrt(n)$)\r\n** probleme: \'schi\':problema/schi, \r\n* Smenu\' lui Mars\r\n** problema \'cuburi\':http://campion.edu.ro/do_download.php?problem_id=122&type=application/pdf&year=2003&lang=ro\r\n* \'Meet in the middle\':meet-in-the-middle\r\n\r\nh2. Carti utile\r\n\r\n* Ioan Tomescu\r\n** \"Probleme de combinatorica si teoria grafurilor\" (din care s-a dat la ONI sau lot aproape in fiecare an cate o problema sau mai multe)\r\n** \"Combinatorica si teoria grafurilor\"\r\n* Ioan Cuculescu\r\n** \"Olimpiadele Internationale de Matematica ale Elevilor\"\r\n* E. A. Morozova, I. S. Petracov, V. A. Skvortov\r\n** \"Olimpiade internationale de matematica\"\r\n* \"Probleme de matematica traduse din revista sovietica KVANT\"\r\n* A. M. Iaglom, I. M. Iaglom\r\n** \"Probleme neelementare tratate elementar\"\r\n* Thomas H. Cormen, Charles E. Leiserson, Ronald R. Rivest\r\n** \'\"Introducere in algoritmi\"\':http://libris.agora.ro/algoritmi.html\r\n* D. E. Knuth\r\n** \"Arta programarii calculatoarelor\" (\"The Art of Computer Programming\")\r\n** \"Concrete Mathematics\"\r\n* Jon Bentley\r\n** \"Programming Pearls\"\r\n* Steven Skiena\r\n** \"The Algorithm Design Manual\"\r\n* W. Rytter\r\n** \"Jewels of Stringology\"\r\n* Mark de Berg\r\n** \"Computational geometry\"\r\n* Emanuela Cerchez si Marinel Serban\r\n** \"Programarea in Limbajul C/C++ Pentru Liceu Volumul 1,2,3\"\r\n\r\n',9232,'public',NULL,NULL),('planificare/camp-2.3.1','Coding Camp \"We can do it\"','2010-03-03 15:34:27','2010-03-11 18:27:54','h1. Coding Camp _\"We can do it\"_\r\n\r\nNe intalnim in weekend-ul *13-14 martie 2010*, in fiecare zi intre orele *10:00* si *18:00*, la ICHB.\r\n\r\nScopul final al coding camp-ului este familiarizarea mai multor membri ai comunitatii/echipei cu codebase-ul infoarena si lansarea versiunii \"infoarena 2.3.1\":http://hackers.devnet.ro/milestone/2.3.1%20Yes%20We%20Can.\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu Linux instalat pe el (preferabil ubuntu).\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri\r\n\r\nh2. Participanti\r\n\r\nSpecifica cand poti veni si cat poti sta.\r\n\r\n* ==user(user=\"devilkind\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"wefgef\" type=\"tiny\")==: sambata\r\n* ==user(user=\"stef2n\" type=\"tiny\")==: duminica\r\n\r\nh2. Agenda\r\n\r\nh3. Must have \r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n|\"Note pentru probleme\":http://hackers.devnet.ro/ticket/395| 0 | 0 |\r\n|\"Interfata de search pentru taguri\":http://hackers.devnet.ro/ticket/391| 0 | 0 |\r\n| Script de recalculat timpii de evaluare | 0 | 0 |\r\n| Script de sters automat backup-uri vechi | 0 | 0 |\r\n\r\nh3. \"Heavy\":http://shaunchng.com/gallery/main.php?g2_view=core.DownloadItem&g2_itemId=658 (pentru useri experimentati)\r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n| \'Sters automat concursuri virtuale nefolosite\':http://hackers.devnet.ro/ticket/376 | 0 | 0 |\r\n| \'Functionalitate de sters runde\':http://hackers.devnet.ro/ticket/373 | ==user(user=\"prostu\" type=\"tiny\")== ? | \'Done 1/2\':http://reviewboard.infoarena.ro/r/115/ |\r\n| \'Optimizeaza pagina de changes\':http://hackers.devnet.ro/ticket/383 | 0 | 0 |\r\n\r\nh3. Light (pentru useri mai putin experimentati)\r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n|\"Recover forum birthdays\":http://hackers.devnet.ro/ticket/394 | 0 | 0 |\r\n|\"Textile edit buttons\":http://hackers.devnet.ro/ticket/163 | 0 | 0 |\r\n|\"Edit forum user\":http://hackers.devnet.ro/ticket/393 | 0 | 0 |\r\n|\"Find my username link\":http://hackers.devnet.ro/ticket/208 | 0 | 0 |\r\n|\"Proper security UI\":http://hackers.devnet.ro/ticket/129 | 0 | 0 |\r\n',1490,'public',NULL,NULL),('runda/oni-2009-xi-xii','oni-2009-xi-xii','2010-03-14 13:08:48','2010-03-14 13:15:44','h1. == roundparam(round_id=\"oni-2009-xi-xii\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oni-2009-xi-xii\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oni-2009-xi-xii\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oni-2009-xi-xii\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"oni-2009-xi-xii\" units=\"2\") ==\r\n\r\nh1. Probleme\r\n\r\n==Tasks(round_id=\"oni-2009-xi-xii\" score=\"1\")==\r\n\r\nh1. \'*Rezultate*\':runda/oni-2009-xi-xii/clasament',10498,'round: oni-2009-xi-xii',NULL,NULL),('runda/oni-2009-x','oni-2009-x','2010-03-14 13:07:17','2010-03-14 15:28:50','h1. == roundparam(round_id=\"oni-2009-x\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"oni-2009-x\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"oni-2009-x\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"oni-2009-x\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"oni-2009-x\" units=\"2\") ==\r\n\r\nh1. %{color:blue}*PROBLEME*%\r\n\r\n==Tasks(round_id=\"oni-2009-x\" score=\"1\")==\r\n\r\nh1. \'*REZULTATE*\':runda/oni-2009-x/clasament',10498,'round: oni-2009-x',NULL,NULL),('utilizator/wickedman','Cristian George Strat (wickedman)','2006-11-24 20:56:12','2010-03-15 00:17:35','h2. Despre mine\r\n\r\n* test\r\n* Membru fondator şi fost Preşedinte al Asociaţiei infoarena \'{!utilizator/domino?btn_viewmy_160x33.gif!}\':http://www.linkedin.com/in/cristiangeorgestrat\r\n* Co-fondator ROCKET SOFTWARE, online start-up (primul proiect lansat este \'balaur.ro\':balaur.ro)\r\n* Co-fondator INNOVATE CONSULT, companie ce oferă servicii software şi networking\r\n* Google internship, summer 2008, Zurich, Switzerland\r\n* Google internship, summer 2007, Mountain View, California\r\n* Membru al comisiei ştiinţifice ONI 2009, clasa a IX-a\r\n* Presedinte al juriului de _Pagini Web_, \"InfoEducatie\":http://infoeducatie.ro/ 2006\r\n* Membru al juriului de _Programare_ \"InfoMatrix 2009\":http://infomatrix.ro/\r\n* Membru al juriului de _Programare_ \"InfoMatrix 2008\":http://infomatrix.ro/\r\n* Membru al juriului de _Pagini Web_ \"InfoEducatie\":http://infoeducatie.ro/ 2005\r\n* Membru al juriului de _Pagini Web_ la concursul Unirea 2005\r\n* Locurile I, I, II, III la concursul national de software si pagini web \"InfoEducatie\":http://infoeducatie.ro/\r\n* Locul II la concursul pe echipe EESTEC Olympics 2006\r\n* Finalist la \'Challenge24\':http://challenge24.org/\r\n* Locul 4 la ONI 2004\r\n* Finalist \'.campion\':http://campion.edu.ro/ 2004 \r\n* Calificare în lotul lărgit de informatică 2004\r\n\r\nh3. Publicaţii\r\n\r\n* \'Solving Maximum Flow Problems on Real World Bipartite Graphs\':http://www.siam.org/proceedings/alenex/2009/alx09_002_negruserin.pdf, Cosmin Silvestru Negruşeri, Mircea Bogdan Paşoi, Barbara Stanley, Clifford Stein, and Cristian George Strat (\'ALENEX09 Proceedings\':http://www.siam.org/proceedings/alenex/2009/alenex09.php)\r\n\r\nh3. Studii\r\n\r\n* -Student in anul IV la- Absolvent \"FMI\":http://fmi.unibuc.ro/ 2008, Universitatea Bucuresti\r\n* C.N. \"Gh. Rosca Codreanu\", Barlad, Jud. Vaslui\r\n\r\nh3. Trivia\r\n\r\n* infoarena a fost initial un proiect pentru concursul national \'InfoEducatie\':http://infoeducatie.ro/, sectiunea pagini web. La prima participare (in 2002) am primit locul III, iar in 2003 am castigat locul I.\r\n* l-am cunoscut pe \'Mircea Pasoi\':utilizator/domino si pe \'Crestez Leonard\':utilizator/fluffy pe canalul IRC #olimpada. Ei vroiau sa faca un site de probleme\r\n* am fost coleg de clasa cu \'Silviu Ganceanu\':utilizator/silviug in 9-11\r\n* ce vedeti acum este site-ul infoarena versiunea 2. \'Inainte era albastru\':http://web.archive.org/web/20060307025837/http://infoarena.devnet.ro/\r\n\r\nh3. Din presă\r\n\r\n* \'Creierele româneşti din solda „imperiului” Google\':http://www.evz.ro/articole/detalii-articol/819647/Creierele-romanesti-din-solda-imperiului-Google/, Evenimentul Zilei\r\n* \'Foştii olimpici îi antrenează pe concurenţii de la olimpiade\':http://www.adevarul.ro/articole/2007/fostii-olimpici-ii-antreneaza-pe-concurentii-de-la-olimpiade.html, Adevărul\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* == User(user=\"chucknorris\" type=\"tiny\") ==\r\n* == User(user=\"eval\" type=\"tiny\") ==\r\n',13,'protected',NULL,NULL),('articole/template-solutii','articole/template-solutii','2008-12-13 14:45:42','2010-03-16 13:43:39','* !>articole/template-solutii?algoritmiada-2010.jpg! \'.com 2009, Runda 2\':dot-com/2009/solutii/runda-2\r\n* \'Algoritmiada 2010, Runda 3\':algoritmiada-2010/runda-3/solutii\r\n* \'Algoritmiada 2010, Runda 2\':algoritmiada-2010/runda-2/solutii\r\n* \'Algoritmiada 2010, Runda 1\':algoritmiada-2010/runda-1/solutii\r\n* \'Summer Challenge 2009, Runda 3\':summer-challenge-2009/solutii/runda-3\r\n* \'Summer Challenge 2009, Runda 2\':summer-challenge-2009/solutii/runda-2\r\n* \'Summer Challenge 2009, Runda 1\':summer-challenge-2009/solutii/runda-1\r\n* \'Grigore Moisil 2009\':grigore-moisil-2009/solutii\r\n* !>articole/template-solutii?algoritmiada-2009.jpg! \'Algoritmiada 2009, Runda 3\':algoritmiada-2009/runda-3/solutii\r\n* \'Algoritmiada 2009, Runda 2\':algoritmiada-2009/runda-2/solutii\r\n* \'Algoritmiada 2009, Runda 1\':algoritmiada-2009/runda-1/solutii\r\n* \'Junior Challenge 2008\':junior-challenge-2008/solutii\r\n* \'Grigore Moisil 2008\':grigore-moisil-2008/solutii\r\n* \'preONI 2008, Runda finala\':preoni-2008/runda-finala/solutii\r\n* !>articole/template-solutii?preoni-2008.jpg! \'preONI 2008, Runda 4\':preoni-2008/runda-4/solutii\r\n* \'preONI 2008, Runda 3\':preoni-2008/runda-3/solutii\r\n* \'preONI 2008, Runda 2\':preoni-2008/runda-2/solutii\r\n* \'preONI 2008, Runda 1\':preoni-2008/runda-1/solutii\r\n*{display: %display%} \'Winter Challenge 2008, Runda 2\':winter-challenge-2008/runda-2/solutii\r\n*{display: %display%} \'Winter Challenge 2008, Runda 1\':winter-challenge-2008/runda-1/solutii\r\n*{display: %display%} \'Happy Coding 2007\':happy-coding-2007/solutii\r\n*{display: %display%} \'Autumn Warmup 2007 runda 3\':autumn-warmup-2007/solutii/runda-3\r\n*{display: %display%} \'Autumn Warmup 2007 runda 2\':autumn-warmup-2007/solutii/runda-2\r\n*{display: %display%} \'Autumn Warmup 2007 runda 1\':autumn-warmup-2007/solutii/runda-1\r\n*{display: %display%} \'Summer Challenge 2007 runda #3\':summer-challenge-2007/solutii/runda-3\r\n*{display: %display%} \'Summer Challenge 2007 runda #2\':summer-challenge-2007/solutii/runda-2\r\n*{display: %display%} \'Summer Challenge 2007 runda #1\':summer-challenge-2007/solutii/runda-1\r\n*{display: %display%} \'Junior Challenge 2007\':junior-challenge/solutii\r\n*{display: %display%} !>articole/template-solutii?preoni-2007.jpg! \'preONI 2007 runda finala - solutii\':preoni-2007/runda-finala/solutii\r\n*{display: %display%} \'preONI 2007 runda #4 - solutii\':preoni-2007/runda-4/solutii\r\n*{display: %display%} \'preONI 2007 runda #3 - solutii\':preoni-2007/runda-3/solutii\r\n*{display: %display%} \'preONI 2007 runda #2 - solutii\':preoni-2007/runda-2/solutii\r\n*{display: %display%} \'preONI 2007 runda #1 - solutii\':preoni-2007/runda-1/solutii\r\n*{display: %display%} \'Winter Challenge 1\':winter-challenge-1/solutii\r\n*{display: %display%} \'Unirea 2007\':unirea-2007/solutii\r\n*{display: %display%} \'Solutii Autumn WarmUp 2006\':warm-up-2006/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Trei\':summer-challenge-3/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Doi\':summer-challenge-2/solutii\r\n*{display: %display%} \'Solutii - Summer Challenge Unu\':summer-challenge-unu/solutii\r\n*{display: %display%} !>articole/template-solutii?preoni-2006.gif! \'Solutii preONI 2006, Runda finala\':preoni-2006/finala/solutii\r\n*{display: %display%} \'Solutii preONI 2006, Runda a 4-a\':preoni-2006/runda-4/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda a 3-a\':preoni-2006/runda-3/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda a 2-a\':preoni-2006/runda-2/solutii\r\n*{display: %display%} \'Solutii preONI 2006 - Runda 1\':preoni-2006/runda-1/solutii\r\n*{display: %display%} \'preONI 2005 runda #3 - solutii\':preoni-2005/runda-3/solutii\r\n*{display: %display%} \'preONI 2005 runda #2 - solutii\':preoni-2005/runda-2/solutii\r\n*{display: %display%} \'preONI 2005 runda #1 - solutii\':preoni-2005/runda-1/solutii\r\n*{display: %display%} \'Happy Coding 3 [2006]\':happy-coding-2006/solutii\r\n*{display: %display%} \'Happy Coding 2 [2005]\':happy-coding-2005-2/solutii\r\n*{display: %display%} \'Happy Coding 1 [2005]\':happy-coding-2005-1/solutii\r\n*{display: %display%} \'Concursul Agora - Etapa Finala - Solutii\':agora-finala/solutii\r\n*{display: %display%} \'Doua probleme de la runda 6 a concursului Algoritmus\':doua-probleme-de-la-runda-6-a-concursului-algoritmus\r\n*{display: %display%} \'USACO dec 2005, divizia GOLD\':usaco-dec-2005-divizia-gold \r\n*{display: %display%} \'USACO nov 2005, divizia GOLD\':usaco-nov-2005-divizia-gold\r\n*{display: %display%} \'USACO oct 2005, divizia GOLD\':usaco-oct-2005-divizia-gold\r\n*{display: %display%} \'USACO ian 2005, divizia GOLD\':usaco-ian-2005-divizia-gold\r\n*{display: %display%} \'USACO dec 2004, divizia GOLD\':usaco-dec-2004-divizia-gold\r\n*{display: %display%} \'Solutiile oficiale pentru Concursul &quot;de incalzire&quot;\':warm-up-2004/solutii',3146,'protected',NULL,NULL),('utilizator/gabitzish1','GABITZISH... Bitis Gabriel.... ','2007-03-02 12:09:21','2009-08-19 05:45:49','h2. Despre mine\r\n\r\nSunt student in anul I la Facultatea de Stiinte din Oradea, departamentul Informatica.\r\nAm inceput sa lucrez pe infoarena de pe la sfarsitul clasei a X\'a.\r\n\r\nh2. Distinctii primite:\r\n\r\n* Mentiune la Concursul Interjudetean \"Marian Tarina\", Turda, 2007.\r\n* Premiul 1 la OJI 2008 (judetul Bihor).\r\n* Premiul 3 la Concursul Interjudetean \"Grigore Moisil\", Cluj-Napoca, 2008.\r\n* Mentiune si medalie de bronz la ONI 2008, Ploiesti.\r\n* Premiul 1 la Concursul Interjudetean \"Marian Tarina\", Turda, 2008.\r\n* Premiul 1 la OJI 2009 (judetul Bihor).\r\n* Premiul 1 la Concursul National \"Urmasii lui Moisil\", Iasi, 2009 + titlul de \"Pui de Moisil\" :P.\r\n* Premiul 1 la Concursul Interjudetean \"Grigore Moisil\", Satu Mare, 2009.\r\n* Finalist .campion 2009\r\n* Membru al lotului national restrans 2009\r\n\r\nh2. Activitate pe Infoarena:\r\n\r\nh3. Probleme adaugate in arhiva:\r\n\r\n* \"498. Alee\":/problema/alee\r\n* \"499. Dir\":/problema/dir\r\n* \"501. Ecuatii 2\":/problema/ecuatii2\r\n* \"514. Sudest\":/problema/sudest\r\n* \"535. Drum\":/problema/drum\r\n* \"536. Razboi 2\":/problema/razboi2\r\n* \"538. Impartire\":/problema/impartire\r\n* \"539. Perm 6\":/problema/perm6\r\n* \"550. Logic2\":/problema/logic2\r\n* \"551. Triticale\":/problema/triticale\r\n* \"744. Numar2\":/problema/numar2\r\n* \"745. Iepuri2\":/problema/iepuri2\r\n* \"746. Colaj\":/problema/colaj\r\n* \"749. Concurs2\":/problema/concurs2\r\n* \"767. Ab2\":/problema/ab2\r\n* \"768. Iepuras\":/problema/iepuras\r\n* \"769. Palind2\":/problema/palind2\r\n* \"770. Auto\":/problema/auto\r\n* \"771. Div\":/problema/div\r\n* \"772. Teatru\":/problema/teatru\r\n* \"926. Cerc3\":/problema/cerc3\r\n* \"927. Project management\":problema/pm2\r\n\r\nh3. Probleme propuse in arhiva:\r\n\r\n* \"905. Cifra lipsa\":/problema/cifralipsa\r\n\r\nh3. Probleme adaugate in arhiva educationala:\r\n\r\n* \"Floyd-Warshall / Roy-Floyd\":/problema/royfloyd\r\n* \"Parcurgere DFS - componente conexe\":/problema/dfs\r\n\r\nh2. Prieteni pe Infoarena:\r\n\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ==User(user=\"mariusdrg\" type=\"tiny\")==\r\n* ==User(user=\"devilkind\" type=\"tiny\")==\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n* ==User(user=\"razvi9\" type=\"tiny\")==\r\n* ==User(user=\"pauldb\" type=\"tiny\")==\r\n* ==User(user=\"wefgef\" type=\"tiny\")==\r\n* ==User(user=\"Dastas\" type=\"tiny\")==\r\n* ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n* ==User(user=\"blasterz\" type=\"tiny\")==\r\n* ==User(user=\"stef2n\" type=\"tiny\")==\r\n* ==User(user=\"CezarMocan\" type=\"tiny\")==\r\n* ==User(user=\"Protoman\" type=\"tiny\")==\r\n* ==User(user=\"motty\" type=\"tiny\")==\r\n* ==User(user=\"Florian\" type=\"tiny\")==\r\n* ==User(user=\"anna_bozianu\" type=\"tiny\")==\r\n* ==User(user=\"sima_cotizo\" type=\"tiny\")==\r\n* ==User(user=\"sigrid\" type=\"tiny\")==\r\n\r\n',6172,'public',NULL,NULL),('algoritmiada-2010/clasament/runda-3/11-12','Algoritmiada 2010 - Clasament Runda 3, Clasele 11-12','2010-01-18 11:55:37','2010-01-18 15:43:17','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda3-11-12\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-3\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-3/studenti\r\n*(active) \'Rezultate\':algoritmiada-2010/clasament/runda-3/11-12\r\n\r\n==include(page=\"template/algoritmiada-2010/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-3/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2010/clasament/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-3/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda3-11-12\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1792,'protected',NULL,NULL),('algoritmiada-2010/clasament/runda-3/studenti','Algoritmiada 2010 - Clasament Runda 3, Studenti','2010-01-18 11:55:37','2010-01-18 15:42:31','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda3-studenti\" param=\"title\") ==\r\n\r\n(htabs)* \'Despre...\':algoritmiada-2010/runda-3\r\n* \'Clasele 5-8\':algoritmiada-2010/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-3/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-3/studenti\r\n*(active) \'Rezultate\':algoritmiada-2010/clasament/runda-3/studenti\r\n\r\n==include(page=\"template/algoritmiada-2010/clasament-header\")==\r\n\r\n(htabs)* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-3/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-3/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/clasament/runda-3/11-12\r\n*(active) \'Studenti\':algoritmiada-2010/clasament/runda-3/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda3-studenti\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1792,'protected',NULL,NULL),('utilizator/motty','Profil motty','2008-10-24 09:08:52','2010-03-18 12:05:33','h2. Despre mine\r\n\r\n  _Sunt elev in clasa a 10-a la Colegiul National de Informatica \"Tudor Vianu\";_\r\n  _Am inceput informatica in octombrie 2008(clasa a 9-a);_\r\n  _{*In God we Trust!*}_\r\n  _Gibson rulez \\m/;_\r\n\r\nh2. Distinctii primite\r\n\r\n  _Mentiune la ONI 2009 (clasa a 9-a);_\r\n  _Premiul I la Concursul de Informatica \"Urmasii lui Moisil\" Iasi - 2009;_\r\n\r\nh2. Profesori\r\n\r\n  ==User(user=\"rapidu36\" type=\"tiny\")==\r\n  ==User(user=\"filipb\" type=\"tiny\")==\r\n  ==User(user=\"andrei.12\" type=\"tiny\")==\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n  ==User(user=\"gabitzish1\" type=\"tiny\")==\r\n  ==User(user=\"gcosmin\" type=\"tiny\")==\r\n  ==User(user=\"cosmin79\" type=\"tiny\")==\r\n  ==User(user=\"ira\" type=\"tiny\")==\r\n  ==User(user=\"ilinca\" type=\"tiny\")==\r\n  ==User(user=\"funkydvd\" type=\"tiny\")==\r\n  ==User(user=\"punkist\" type=\"tiny\")==\r\n  ==User(user=\"andreyp\" type=\"tiny\")==\r\n  ==User(user=\"tvlad\" type=\"tiny\")==\r\n  ==User(user=\"drag0s93\" type=\"tiny\")==\r\n  ==User(user=\"ciprianf\" type=\"tiny\")==\r\n  ==User(user=\"AndreiDuma\" type=\"tiny\")==\r\n  ==User(user=\"Ioanna\" type=\"tiny\")==\r\n  ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n  ==User(user=\"hadesgames\" type=\"tiny\")==\r\n  ==User(user=\"andreisfrent\" type=\"tiny\")==',8690,'public',NULL,NULL),('utilizator/motty','Profil motty','2008-10-24 09:08:52','2010-03-18 12:05:53','h2. Despre mine\r\n\r\n  _Sunt elev in clasa a 10-a la Colegiul National de Informatica \"Tudor Vianu\";_\r\n  _Am inceput informatica in octombrie 2008(clasa a 9-a);_\r\n  _{*In God we Trust!*}_\r\n  _Gibson rulez \\m/;_\r\n\r\nh2. Distinctii primite\r\n\r\n  _Mentiune la ONI 2009 (clasa a 9-a);_\r\n  _Premiul I la Concursul de Informatica \"Urmasii lui Moisil\" Iasi - 2009;_\r\n\r\nh2. Profesori\r\n\r\n ==User(user=\"rapidu36\" type=\"tiny\")==\r\n  ==User(user=\"filipb\" type=\"tiny\")==\r\n  ==User(user=\"andrei.12\" type=\"tiny\")==\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n  ==User(user=\"gabitzish1\" type=\"tiny\")==\r\n  ==User(user=\"gcosmin\" type=\"tiny\")==\r\n  ==User(user=\"cosmin79\" type=\"tiny\")==\r\n  ==User(user=\"ira\" type=\"tiny\")==\r\n  ==User(user=\"ilinca\" type=\"tiny\")==\r\n  ==User(user=\"funkydvd\" type=\"tiny\")==\r\n  ==User(user=\"punkist\" type=\"tiny\")==\r\n  ==User(user=\"andreyp\" type=\"tiny\")==\r\n  ==User(user=\"tvlad\" type=\"tiny\")==\r\n  ==User(user=\"drag0s93\" type=\"tiny\")==\r\n  ==User(user=\"ciprianf\" type=\"tiny\")==\r\n  ==User(user=\"AndreiDuma\" type=\"tiny\")==\r\n  ==User(user=\"Ioanna\" type=\"tiny\")==\r\n  ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n  ==User(user=\"hadesgames\" type=\"tiny\")==\r\n  ==User(user=\"andreisfrent\" type=\"tiny\")==',8690,'public',NULL,NULL),('blog/algoritmiada-2010-runda-3','Algoritmiada 2010: Analiza rundei 3','2010-03-19 09:53:43','2010-03-19 13:29:34','h1. Algoritmiada 2010: Analiza rundei 3\r\n\r\nPe data de 21 februarie a avut loc cea de-a \'treia\':/algoritmiada-2010/runda-3 rundă a concursului Algoritmiada 2010. La două luni de la de la runda a doua concurenţii au revenit să îşi măsoare forţele cu problemele propuse de \'infoarena\':.\r\n\r\nStatisticile primelor 3 runde arată in felul următor:\r\n\r\ntable. |_. &nbsp; |_. Runda 1 |_. Runda 2 |_. Runda 3 |\r\n| Câţi concurenţi au trimis soluţii | 181 | 135 | 136 |\r\n| Câţi concurenţi s-au înscris | 308 | 174 | 196 |\r\n| Surse trimise | 765 | 627 | 552 |\r\n| Surse cu punctaj pozitiv | 345 | 312 | 263 |\r\n| Concurenţi cu punctaj pozitiv | 122 | 107 | 104 |\r\n| Punctaj mediu al concurenţilor care au trimis soluţii | 58.07 | 76.26 | 61.17 |\r\n| Punctaj mediu al concurenţilor cu punctaj strict mai mare ca 0 | 86.15 | 96.87 | 80 |\r\n\r\nDin statistici observăm ca numărul de concurenţi de la runda a treia este comparabil cu cel de la runda a doua. Este un lucru îmbucurător deoarece in anii trecuţi tendinţa a fost de descreştere de la rundă la rundă şi sperăm că la fel de mulţi concurenţi o să participe si la runda a patra.\r\n\r\nConcurenţii de la gimnaziu au avut parte de un set de probleme dificil. Pe primul loc s-a situat == User(user=\"eudanip\") == cu 200 de puncte, pe locul al doilea == User(user=\"GheorgheMihai\") == cu 170 de puncte iar pe locul al treilea, la egalitate, cu 110 puncte == User(user=\"Magnus\") == şi == User(user=\"Marius96\") ==.\r\n\r\nElevii de la clasele 9-10 au avut punctajele cele mai mari, iar la finalul rundei, 6 concurenti aveau punctaje mai mari sau egale cu 200 de puncte. Astfel, punctajul cel mai mare al rundei a treia, de 270 de puncte, a fost obţinut de == User(user=\"freak93\") ==. Poziţia a doua in clasament a fost ocupata de == User(user=\"raduzer\") == cu 250 de puncte iar a treia de == User(user=\"GavrilaVlad\") == cu 240 de puncte.\r\n\r\nLa clasele 11-12 numarul de participanţi a fost semnificativ mai mare decat la celelalte grupe de varstă, însă problemele le-au pus mici probleme participanţilor. La finalul rundei numai 3 concurenti aveau un punctaj mai mare de 110 puncte, ei fiind == User(user=\"andrei.12\") == cu 200 de puncte, == User(user=\"Iliee\") == cu 170 de puncte si == User(user=\"stocarul\") == cu 160 de puncte.\r\n\r\nStundentii au avut parte de un set de probleme echilibrat. Toate problemele au fost rezolvate dar nici un concurent nu le-a rezolvat pe toate de 100 de puncte. Cel mai aproape a fost  == User(user=\"mugurelionut\") == care a obtinut 240 de puncte, el a fost urmat de == User(user=\"mihai_florea\") == cu 200 de puncte si de == User(user=\"razvi9\") == cu 170 de puncte.\r\n\r\nSeturile de probleme propuse la runda a treia au fost bine structurate, reuşind sa departajeze in mod clar concurentii din varful clasamentelor si in acelasi timp oferindu-le tuturor participantilor cate o provocare.\r\n\r\nMult succes in runda a \'patra\':algoritmiada-2010/runda-4 care are loc duminica, 21 martie de la ora 9:00.',6172,'public',4667,NULL),('planificare','Planificare infoarena','2007-02-16 17:54:49','2010-03-19 08:59:25','h1. Planificare infoarena\r\n\r\n==include(page=\"planificare/sidebar\")==\r\n\r\nAici discutam despre planurile si proiectele infoarena (deadlines, echipe, bugete etc.). Majoritatea acestor pagini sunt publice si vizibile pentru toti utilizatorii. Este bine sa lucram cat mai transparent pentru a \'atrage si alti oameni\':implica-te. Este inevitabil sa exista si niste informatii confidentiale (surprize, sau enunturi de probleme), pentru care putem face si \'pagini private\':documentatie/administrare.\r\n\r\nToate subpaginile acestei sectiuni vor avea titlul de forma: planificare/sedinte, planificare/sponsori etc. \r\n\r\nh2. Sedinte\r\n\r\nDin cand in cand facem sedinte ale \'asociatiei\':asociatia-infoarena unde discutam live diverse lucruri. Aici avem note de la niste sedinte trecute.\r\n\r\nEste ok sa modificam pagini de sedinte cu update-uri asupra task-urilor.\r\n\r\nh3. 2010\r\n\r\n* \'*2010-02-16*\':planificare/sedinta-20100216\r\n* \'2010-01-12\':planificare/sedinta-20100112\r\n\r\nh3. 2009\r\n\r\n* \'2009-11-26\':planificare/sedinta-20091126\r\n* \'2009-11-03\':planificare/sedinta-20091103\r\n* \'2009-10-23\':planificare/sedinta-20091023\r\n* \'2009-10-15\':planificare/sedinta-20091015\r\n* \'2009-07-27\':planificare/sedinta-20090727\r\n* \'2009-04-03\':planificare/sedinta-20090403\r\n* \'2009-03-16\':planificare/sedinta-20090316\r\n* \'2009-02-16\':planificare/sedinta-20090216\r\n* \'2009-01-26\':planificare/sedinta-20090126\r\n* \'2009-01-12\':planificare/sedinta-20090112\r\n\r\nh3. 2008\r\n\r\n* \'2008-11-25\':planificare/sedinta-20081125\r\n* \'2008-11-07\':planificare/sedinta-20081107\r\n* \'2008-10-21\':planificare/sedinta-20081021\r\n* \'2008-10-10\':planificare/sedinta-20081010\r\n* \'2008-04-11\':planificare/sedinta-20080411\r\n* \'2008-03-14\':planificare/sedinta-20080314\r\n* \'2008-03-03\':planificare/sedinta-20080303\r\n* \'2008-02-18\':planificare/sedinta-20080218\r\n* \'2008-02-01\':planificare/sedinta-20080201\r\n* \'2008-01-18\':planificare/sedinta-20080118\r\n\r\nh3. 2007\r\n\r\n* \'2007-12-18\':planificare/sedinta-20071218\r\n* \'2007-11-28\':planificare/sedinta-20071128\r\n* \'2007-11-07\':planificare/sedinta-20071107\r\n* \'2007-10-27\':planificare/sedinta-20071027\r\n* \'2007-10-24\':planificare/sedinta-20071024\r\n* \'2007-06-15\':planificare/sedinta_20070615\r\n* \'2007-05-07\':planificare/sedinta_20070507\r\n* \'2007-04-24\':planificare/sedinta_20070424\r\n* \'2007-03-03\':planificare/sedinta_20070303\r\n* \'2007-02-15\':planificare/sedinta_20070215\r\n* \'2007-01-04\':planificare/sedinta_20070104\r\n\r\nh3. 2006\r\n\r\n* \'2006-12-14\':planificare/sedinta_20061214\r\n* \'2006-11-21\':planificare/sedinta_20061121\r\n* \'2006-11-01\':planificare/sedinta-20061101\r\n\r\nh2(#coding-camps). Coding Camps\r\n\r\n* \'*Tagging Camp \"Neverending Story\"*\':planficare/camp-neverending-story\r\n* \'*Coding Camp \"We can do it\"*\':planificare/camp-2.3.1\r\n* \'Coding Camp \"A 2nd New Day\"\':planificare/camp-2.3\r\n* \'Coding Camp \"A New Day\"\':planificare/camp-2.2.1\r\n* \'Coding Camp Alcatraz\':planificare/camp-alcatraz\r\n* \'Coding Camp Karate-Kids\':planificare/karate-kids\r\n* \'Coding Camp Noname\':planificare/camp-noname\r\n* \'Coding Camp Chuckie\':planificare/camp-chuckie\r\n\r\nh2. Proiecte trecute\r\n\r\n* \'Asociatia infoarena, infiintare\':planificare/asociatia-infoarena\r\n* \'Algoritmiada 2009\':planificare/algoritmiada-2009\r\n** \'Promovare\':planificare/algoritmiada-2009/promovare\r\n** \'How-to\':planificare/algoritmiada-2009/how-to\r\n** \'Roluri\':planificare/algoritmiada-2009/roluri\r\n** \'Runda 1\':planificare/algoritmiada-2009/runda-1\r\n** \'Runda 2\':planificare/algoritmiada-2009/runda-2\r\n** \'Runda 3\':planificare/algoritmiada-2009/runda-3\r\n** \'Runda Finala\':planificare/algoritmiada-2009/runda-finala\r\n* \'preONI 2008\':planificare/preoni-2008\r\n** \'How-to\':planificare/preoni-2008/how-to\r\n** \'Roluri\':planificare/preoni-2008/roluri\r\n** \'Runda 1\':planificare/preoni-2008/runda-1\r\n** \'Runda 2\':planificare/preoni-2008/runda-2\r\n** \'Runda 3\':planificare/preoni-2008/runda-3\r\n** \'Runda 4\':planificare/preoni-2008/runda-4\r\n** \'Runda 5\':planificare/preoni-2008/runda-5\r\n** \'Finala\':planificare/preoni-2008/finala',2028,'protected',NULL,NULL),('planificare/camp-neverending-story','Tagging Camp \"Neverending Story\"','2010-03-19 09:02:24','2010-03-19 13:59:17','h1. Tagging Camp _\"Neverending Story\"_\r\n\r\nNe intalnim in weekend-ul *20-21 martie 2010*, in fiecare zi intre orele *10:00* si *20:00*, la _Cuibul Marmotelor_.\r\n\r\nScopul tagging campului este sa dam note/tagguim un numar cat mai mare de probleme din arhiva.\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu acces la internet.\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri.\r\n\r\nh2. Participanti\r\n\r\nSpecifica daca poti veni si cat poti sta.\r\n\r\n* ==user(user=\"wefgef\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"victorsb\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"prostu\" type=\"tiny\")==: duminica\r\n* ==user(user=\"stef2n\" type=\"tiny\")==: sambata\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==: sambata >= 12:00, duminica\r\n\r\nh2. Agenda\r\n\r\n* Infoarena grading guidelines\r\n* Lucru in echipe:\r\n\r\n|_. Echipa|_. Set de probleme |_. Stare |\r\n| &nbsp; | &nbsp; | &nbsp; |',1490,'public',NULL,NULL),('problema/adunare','A+B','2006-11-11 11:23:33','2009-12-21 12:26:21','==Include(page=\"template/taskheader\" task_id=\"adunare\")==\r\n\r\nAdunare simplă.\r\n\r\nh2. Date de intrare\r\n\r\nDatele de intrare se citesc din fişierul $adunare.in$:\r\n\r\n* pe prima linie un număr intreg $a$\r\n* pe a doua linie un număr intreg $b$\r\n\r\nh2. Date de ieşire\r\n\r\nDatele de ieşire se tipăresc în fişierul $adunare.out$\r\n\r\n* pe prima linie: suma celor două numere $a + b$\r\n\r\nh2. Restricţii\r\n\r\n* Suma celor două numere nu va depăşi niciodată valoarea $2 000 000 000$.\r\n\r\nh2. Exemplu\r\n\r\ntable(example). |_. adunare.in |_. adunare.out |\r\n| 131\r\n  245\r\n| 376 |\r\n\r\n==Include(page=\"template/taskfooter\" task_id=\"adunare\")==\r\n\r\nh2. Precizare\r\n\r\n* Problema e dată pentru a vă obişnui cu site-ul. Nu e nevoie să postaţi pe forum că e foarte uşoara, ştim cu toţii asta. :)\r\n',1490,'task: adunare',27,NULL),('planificare/camp-2.3.1','Coding Camp \"We can do it\"','2010-03-03 15:34:27','2010-03-19 16:35:21','h1. Coding Camp _\"We can do it\"_\r\n\r\nNe intalnim in weekend-ul *13-14 martie 2010*, in fiecare zi intre orele *9:00* si *17:00*, la ICHB.\r\n\r\nScopul final al coding camp-ului este familiarizarea mai multor membri ai comunitatii/echipei cu codebase-ul infoarena si lansarea versiunii \"infoarena 2.3.1\":http://hackers.devnet.ro/milestone/2.3.1%20Yes%20We%20Can.\r\n\r\nh2. Detalii\r\n\r\n* Fiecare participant trebuie sa vina cu un calculator cu Linux instalat pe el (preferabil ubuntu).\r\n* \'Asociatia infoarena\':asociatia-infoarena asigura masa, bautura, snacks-uri\r\n\r\nh2. Participanti\r\n\r\nSpecifica cand poti veni si cat poti sta.\r\n\r\n* ==user(user=\"devilkind\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"gcosmin\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"bogdan2412\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"wefgef\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"victorsb\" type=\"tiny\")==: tot weekend-ul\r\n* ==user(user=\"Prostu\" type=\"tiny\")==: sambata\r\n\r\nh2. Agenda\r\n\r\nh3. Must have \r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n|\"Note pentru probleme\":http://hackers.devnet.ro/ticket/395| ==user(user=\"wefgef\" type=\"tiny\")== ==user(user=\"gcosmin\" type=\"tiny\")== | \"Done\":http://reviewboard.infoarena.ro/r/140/ |\r\n| Script de recalculat timpii de evaluare | ==user(user=\"bogdan2412\" type=\"tiny\")== | 0 |\r\n| \"Script de sters automat backup-uri vechi\":http://hackers.devnet.ro/ticket/398 | ==user(user=\"victorsb\" type=\"tiny\")== | \"Done\":http://reviewboard.infoarena.ro/r/136/ |\r\n| \"Fix grader test files that don\'t end with \\n\":http://hackers.devnet.ro/ticket/399 | ==user(user=\"victorsb\" type=\"tiny\")== | \"La review\":http://reviewboard.infoarena.ro/r/139/ |\r\n| Split ia_score | ==user(user=\"devilkind\" type=\"tiny\")== | \'Done\':http://reviewboard.infoarena.ro/r/64/ |\r\n\r\nh3. \"Heavy\":http://shaunchng.com/gallery/main.php?g2_view=core.DownloadItem&g2_itemId=658 (pentru useri experimentati)\r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n| \'Sters automat concursuri virtuale nefolosite\':http://hackers.devnet.ro/ticket/376 | 0 | 0 |\r\n| \"Interfata de search pentru taguri\":http://hackers.devnet.ro/ticket/391 | 0 | 0 |\r\n| \'Functionalitate de sters runde\':http://hackers.devnet.ro/ticket/373 | ==user(user=\"prostu\" type=\"tiny\")== | \'Done\':http://reviewboard.infoarena.ro/r/134/ |\r\n| \'Optimizeaza pagina de changes\':http://hackers.devnet.ro/ticket/383 | 0 | 0 |\r\n\r\nh3. Light (pentru useri mai putin experimentati)\r\n\r\n|_. Task|_. Cine lucreaza |_. Stare |\r\n|\"Recover forum birthdays\":http://hackers.devnet.ro/ticket/394 | 0 | 0 |\r\n|\"Make it possible to remove all algorithm tags from tasks\":http://hackers.devnet.ro/ticket/396 | ==user(user=\"gcosmin\" type=\"tiny\")== | \'Done\':http://reviewboard.infoarena.ro/r/133/ |\r\n|\"Allow helpers to rejudge their own tasks.\":http://hackers.devnet.ro/ticket/397 | ==user(user=\"gcosmin\" type=\"tiny\")== | \'Done\':http://reviewboard.infoarena.ro/r/135/ |\r\n|\"Edit forum user\":http://hackers.devnet.ro/ticket/393 | 0 | 0 |\r\n|\"Proper security UI\":http://hackers.devnet.ro/ticket/129 | ==user(user=\"wefgef\" type=\"tiny\")== | 0 |\r\n',1490,'public',NULL,NULL),('utilizator/mathboy','Profil Dragos-Alin Rotaru','2008-12-24 18:43:37','2010-03-21 11:27:23','== include(page=\"template/noprofile\") ==\r\n\r\nh2. Despre mine\r\n\r\n_(completeaza aici: studii, an de absolvire, institutie de invatamant, locatie, profesori pregatitori, site personal ...)_\r\n\r\nh2. Distinctii primite\r\n\r\n* _(completeaza aici: locuri obtinute la concursuri de informatica)_\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* _(completeaza aici: link-uri catre profilele altor utilizatori infoarena pe care ii cunosti)_\r\n',9232,'public',NULL,NULL),('planificare/sedinta-20100325','Ședință 2010-03-25','2010-03-22 19:15:06','2010-03-22 19:17:06','h1. Şedinţă 2010-03-25\r\n\r\nh2(#locatie). Locaţie şi oră\r\n\r\nNe întâlnim *Joi* la ora *19^00^* la staţia de 41 de la Plaza România.\r\n\r\nh2(#participanti). Participanţi\r\n\r\n* ==User(user=\"gcosmin\" type=\"tiny\")==\r\n* ...\r\n\r\nh2(#agenda). Agendă\r\n\r\ntable. |_. Subiect |_. Moderator |\r\n| Recapitulare \'sedinta anterioara\':planificare/sedinta-20100216 | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| Algoritmiada Runda finala | ==User(user=\"pauldb\" type=\"tiny\")== |\r\n| Sponsori | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n| OKR | ==User(user=\"gcosmin\" type=\"tiny\")== |\r\n\r\nh2(#rezolutii). Rezoluţii\r\n\r\n* ...\r\n\r\nh2(#notite). Notiţe\r\n\r\n* ...',2038,'protected',NULL,NULL),('planificare','Planificare infoarena','2007-02-16 17:54:49','2010-03-22 19:17:41','h1. Planificare infoarena\r\n\r\n==include(page=\"planificare/sidebar\")==\r\n\r\nAici discutam despre planurile si proiectele infoarena (deadlines, echipe, bugete etc.). Majoritatea acestor pagini sunt publice si vizibile pentru toti utilizatorii. Este bine sa lucram cat mai transparent pentru a \'atrage si alti oameni\':implica-te. Este inevitabil sa exista si niste informatii confidentiale (surprize, sau enunturi de probleme), pentru care putem face si \'pagini private\':documentatie/administrare.\r\n\r\nToate subpaginile acestei sectiuni vor avea titlul de forma: planificare/sedinte, planificare/sponsori etc. \r\n\r\nh2. Sedinte\r\n\r\nDin cand in cand facem sedinte ale \'asociatiei\':asociatia-infoarena unde discutam live diverse lucruri. Aici avem note de la niste sedinte trecute.\r\n\r\nEste ok sa modificam pagini de sedinte cu update-uri asupra task-urilor.\r\n\r\nh3. 2010\r\n\r\n* \'*2010-03-25*\':planificare/sedinta-20100325\r\n* \'2010-02-16\':planificare/sedinta-20100216\r\n* \'2010-01-12\':planificare/sedinta-20100112\r\n\r\nh3. 2009\r\n\r\n* \'2009-11-26\':planificare/sedinta-20091126\r\n* \'2009-11-03\':planificare/sedinta-20091103\r\n* \'2009-10-23\':planificare/sedinta-20091023\r\n* \'2009-10-15\':planificare/sedinta-20091015\r\n* \'2009-07-27\':planificare/sedinta-20090727\r\n* \'2009-04-03\':planificare/sedinta-20090403\r\n* \'2009-03-16\':planificare/sedinta-20090316\r\n* \'2009-02-16\':planificare/sedinta-20090216\r\n* \'2009-01-26\':planificare/sedinta-20090126\r\n* \'2009-01-12\':planificare/sedinta-20090112\r\n\r\nh3. 2008\r\n\r\n* \'2008-11-25\':planificare/sedinta-20081125\r\n* \'2008-11-07\':planificare/sedinta-20081107\r\n* \'2008-10-21\':planificare/sedinta-20081021\r\n* \'2008-10-10\':planificare/sedinta-20081010\r\n* \'2008-04-11\':planificare/sedinta-20080411\r\n* \'2008-03-14\':planificare/sedinta-20080314\r\n* \'2008-03-03\':planificare/sedinta-20080303\r\n* \'2008-02-18\':planificare/sedinta-20080218\r\n* \'2008-02-01\':planificare/sedinta-20080201\r\n* \'2008-01-18\':planificare/sedinta-20080118\r\n\r\nh3. 2007\r\n\r\n* \'2007-12-18\':planificare/sedinta-20071218\r\n* \'2007-11-28\':planificare/sedinta-20071128\r\n* \'2007-11-07\':planificare/sedinta-20071107\r\n* \'2007-10-27\':planificare/sedinta-20071027\r\n* \'2007-10-24\':planificare/sedinta-20071024\r\n* \'2007-06-15\':planificare/sedinta_20070615\r\n* \'2007-05-07\':planificare/sedinta_20070507\r\n* \'2007-04-24\':planificare/sedinta_20070424\r\n* \'2007-03-03\':planificare/sedinta_20070303\r\n* \'2007-02-15\':planificare/sedinta_20070215\r\n* \'2007-01-04\':planificare/sedinta_20070104\r\n\r\nh3. 2006\r\n\r\n* \'2006-12-14\':planificare/sedinta_20061214\r\n* \'2006-11-21\':planificare/sedinta_20061121\r\n* \'2006-11-01\':planificare/sedinta-20061101\r\n\r\nh2(#coding-camps). Coding Camps\r\n\r\n* \'*Tagging Camp \"Neverending Story\"*\':planificare/camp-neverending-story\r\n* \'*Coding Camp \"We can do it\"*\':planificare/camp-2.3.1\r\n* \'Coding Camp \"A 2nd New Day\"\':planificare/camp-2.3\r\n* \'Coding Camp \"A New Day\"\':planificare/camp-2.2.1\r\n* \'Coding Camp Alcatraz\':planificare/camp-alcatraz\r\n* \'Coding Camp Karate-Kids\':planificare/karate-kids\r\n* \'Coding Camp Noname\':planificare/camp-noname\r\n* \'Coding Camp Chuckie\':planificare/camp-chuckie\r\n\r\nh2. Proiecte trecute\r\n\r\n* \'Asociatia infoarena, infiintare\':planificare/asociatia-infoarena\r\n* \'Algoritmiada 2009\':planificare/algoritmiada-2009\r\n** \'Promovare\':planificare/algoritmiada-2009/promovare\r\n** \'How-to\':planificare/algoritmiada-2009/how-to\r\n** \'Roluri\':planificare/algoritmiada-2009/roluri\r\n** \'Runda 1\':planificare/algoritmiada-2009/runda-1\r\n** \'Runda 2\':planificare/algoritmiada-2009/runda-2\r\n** \'Runda 3\':planificare/algoritmiada-2009/runda-3\r\n** \'Runda Finala\':planificare/algoritmiada-2009/runda-finala\r\n* \'preONI 2008\':planificare/preoni-2008\r\n** \'How-to\':planificare/preoni-2008/how-to\r\n** \'Roluri\':planificare/preoni-2008/roluri\r\n** \'Runda 1\':planificare/preoni-2008/runda-1\r\n** \'Runda 2\':planificare/preoni-2008/runda-2\r\n** \'Runda 3\':planificare/preoni-2008/runda-3\r\n** \'Runda 4\':planificare/preoni-2008/runda-4\r\n** \'Runda 5\':planificare/preoni-2008/runda-5\r\n** \'Finala\':planificare/preoni-2008/finala',2038,'protected',NULL,NULL),('arhiva','Arhiva de probleme','2006-11-11 18:59:35','2010-03-24 19:02:23','h1. Arhiva de probleme\r\n\r\nArhiva de probleme infoarena contine peste 950 de probleme. Vezi si \'clasamentul arhivei\':clasament-arhiva.\r\n\r\nh2. Lista de probleme\r\n\r\n==Tasks(round_id=\"arhiva\" show_numbers=\"true\" score=\"1\" show_ratings=\"true\" show_progress=\"true\") ==\r\n\r\nh2. Ultimele discutii despre arhiva\r\n\r\n== SmfTopics(board_id=\"1\" count=\"30\") ==\r\n',1490,'protected',NULL,NULL),('clasament-arhiva','Clasamentul arhivei de probleme','2006-11-22 22:14:20','2008-02-25 22:08:28','(htabs)* \'Dupa rating\':clasament-rating\r\n*(active) \'Arhiva de probleme\':clasament-arhiva\r\n* \'Arhiva educationala\':clasament-arhiva-educationala\r\n\r\nh1. Clasamentul \'arhivei de probleme\':arhiva\r\n\r\nClasamentul arhivei ordoneaza membrii infoarena dupa punctele obtinute rezolvand problemele din arhiva.\r\nAcest clasament reflecta *munca depusa in pregatire* pe infoarena si nu performanta concurentului in regim de concurs.\r\n\r\n== Rankings(rounds=\"arhiva\") ==',1,'protected',NULL,NULL),('utilizator/motty','Profil motty','2008-10-24 09:08:52','2010-03-22 21:47:34','h2. Despre mine\r\n\r\n* _Sunt elev in clasa a 10-a la Colegiul National de Informatica \"Tudor Vianu\"_\r\n* _Am inceput informatica in octombrie 2008 ~(clasa a 9-a)~_\r\n* _{*In God we Trust!*}_\r\n* _Gibson rulez \\m/!_\r\n\r\nh2. Distinctii primite\r\n\r\n* _Mentiune la ONI 2009 ~(clasa a 9-a)~_\r\n* _Premiul I la Concursul de Informatica \"Urmasii lui Moisil\" Iasi - 2009_\r\n\r\nh2. Profesori\r\n\r\n ==User(user=\"rapidu36\" type=\"tiny\")==\r\n  ==User(user=\"filipb\" type=\"tiny\")==\r\n  ==User(user=\"andrei.12\" type=\"tiny\")==\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n ==User(user=\"gabitzish1\" type=\"tiny\")==\r\n  ==User(user=\"gcosmin\" type=\"tiny\")==\r\n  ==User(user=\"cosmin79\" type=\"tiny\")==\r\n  ==User(user=\"ira\" type=\"tiny\")==\r\n  ==User(user=\"ilinca\" type=\"tiny\")==\r\n  ==User(user=\"funkydvd\" type=\"tiny\")==\r\n  ==User(user=\"punkist\" type=\"tiny\")==\r\n  ==User(user=\"andreyp\" type=\"tiny\")==\r\n  ==User(user=\"tvlad\" type=\"tiny\")==\r\n  ==User(user=\"ciprianf\" type=\"tiny\")==\r\n  ==User(user=\"drag0s93\" type=\"tiny\")==\r\n  ==User(user=\"AndreiDuma\" type=\"tiny\")==\r\n  ==User(user=\"Ioanna\" type=\"tiny\")==\r\n  ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n  ==User(user=\"hadesgames\" type=\"tiny\")==\r\n  ==User(user=\"andreisfrent\" type=\"tiny\")==\r\n  ==User(user=\"nemultumitu\" type=\"tiny\")==',8690,'public',NULL,NULL),('grigore-moisil-2010','Grigore Moisil 2009','2010-03-25 19:52:08','2010-03-25 19:52:08','h1. Grigore Moisil 2009\r\n\r\n(htabs)*(active) \'Despre...\':grigore-moisil-2009 \r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n* \'Rezultate\':grigore-moisil-2009/clasament/5-8\r\n\r\nInfoarena organizeaza si in acest an editia online a concursului interjudetean de informatica Grigore Moisil. Concurentii pot profita de aceasta ocazie pentru a efectua un ultim test inainte de Olimpiada Nationala. Concursul se va desfasura *Duminica 5 aprilie*, la ora {*09^00^*} si va dura *3h*. Participantii vor avea de rezolvat 2-3 probleme de natura algoritmica.\r\n\r\nh2. Despre inscriere\r\n\r\np. *{color:red}ATENTIE!* Trebuie sa te inscrii *inainte de ora 09^00^* la grupa de varsta corespunzatoare daca doresti sa ti se modifice rating-ul in urma participarii!\r\n*Daca nu te inscrii* la o grupa de varsta nu ti se va modifica \'rating-ul\':documentatie/rating insa poti sa participi oricum!\r\n\r\nTimp de cateva zile inainte de inceperea unei noi runde, concurentii se pot inscrie la grupa lor de varsta. Inscrierea se face printr-un simplu click. Nu trebuie sa va inregistrati din nou pe site!\r\n\r\nh2. Probleme\r\n\r\nClick pe grupa de varsta potrivita&hellip;\r\n\r\n* \'Clasele 5-8\':grigore-moisil-2009/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/11-12\r\n\r\nSolutiile le poti gasi \'aici\':grigore-moisil-2009/solutii.\r\n\r\nh2. Clasament\r\n\r\nDupa terminarea concursului vei putea vedea clasamentele facand click pe unul din linkurile urmatoare:\r\n\r\n* \'Clasele 5-8\':grigore-moisil-2009/clasament/5-8 \r\n* \'Clasa a 9a\':grigore-moisil-2009/clasament/9\r\n* \'Clasa a 10a\':grigore-moisil-2009/clasament/10\r\n* \'Clasele 11-12\':grigore-moisil-2009/clasament/11-12\r\n\r\nh2. Organizatori\r\n\r\nSubiectele vor fi propuse si pregatite de:\r\n\r\n* prof. Clara Ionescu\r\n* ==User(user=\"SleepyOverlord\" type=\"tiny\")==\r\n* ==User(user=\"Marius\" type=\"tiny\")==\r\n* ==User(user=\"astronomy\" type=\"tiny\")==\r\n\r\nPentru intrebari de factura organizatorica / tehnica poti contacta urmatoarele persoane:\r\n\r\n* ==User(user=\"bogdan2412\" type=\"tiny\")==\r\n\r\n*{\'Echipa infoarena\':echipa-infoarena}* iti ureaza mult succes!\r\n\r\n',2044,'protected',NULL,NULL),('blog/algoritmiada-2010-runda-4','blog/algoritmiada-2010-runda-4','2010-03-26 23:10:18','2010-03-26 23:10:18','h1. Algoritmiada 2010: Analiza rundei 4\r\n\r\n\'Algoritmiada\':/algoritmiada-2010 se îndreaptă cu paşi repezi spre runda finală. Ne-am distrat, dar n-am încetat să facem şi treabă serioasă, v-am pregătit probleme frumoase şi v-am pus serios la încercare în repetate rânduri. Între timp, ca bonus pentru interesul vostru, am \"redesenat\" pe ici, pe colo monitorul de evaluare. Şi i-am mai pus nişte combustibil, acum se mişcă mai repede şi mai bine. :P \r\nCe a ieşit aţi văzut şi voi. De plăcut, credem că v-a plăcut, deoarece aţi revenit la fiecare rundă. :)\r\n\r\nIar ca să nu dezminţim ceea ce a devenit deja tradiţie, să tragem puţin cu ochiul la rezultatele din weekendul acesta, când s-a jucat ultima carte pentru calificare:\r\n\r\nÎn rândul celor mici, la gimnaziu, punctajele au fost, din păcate, mai timide. La nivel de dificultate, problema uşoară a fost Binar, cea medie Copii, iar cea grea Cuburi5. În mod surprinzător, problema Binar nu a fost rezolvată decât de un singur concurent; majoritatea a ales să implementeze QuickSort, nereuşind să observe soluţia O(N * M). Cu toate acestea, în rândul primilor 3 concurenţi s-au înregistrat şi punctaje maxime pe problemă. Îi felicităm astfel pe Liana Tucar şi pe Taloi Bogdan Cristian, ocupanţii locurilor 2, respectiv 3, pentru scor maxim la problema Copii, şi mai ales pe Daniel Posdarascu, singurul care a găsit soluţiile optime pentru Binar şi Cuburi5!\r\n\r\nLa clasele 9-10 problemele s-au împărţit după cum urmează: cea uşoară a fost Copii, cea medie Reţea, iar cea grea Matrice3. Felicitări lui Andrei Purice pentru că a obţinut cel mai mare punctaj, şi laude speciale lui Şerban Andrei Stan, singurul care a rezolvat problema grea şi care, de altfel, a fost la un pas de punctajul maxim. Îl tragem virtual şi părinteşte de urechi pentru că a greşit tocmai la problema uşoară, dar sperăm să ia aminte la runda finală :). Nu îl uităm nici pe Radu Voroneanu şi îl felicităm pentru a treia poziţie în clasament!\r\n\r\nClasele 11-12 au avut un set greu de probleme, probabil mai dificil ca în celelalte runde. La această grupă savoarea a fost dată de lupta strânsă pentru ultimele locuri de calificare, care a făcut aşteptarea mai interesantă. Ca grad de dificultate, Reţea a fost problema mai uşoară, Piraţi cea medie şi Compact problema grea. Cu toate că notăm câteva punctaje maxime în rândul celei din urmă, se pare însă că nimeni nu a ieşit victorios în lupta cu Piraţii. Podiumul a fost ocupat, în ordine, de Andrei-Bogdan Antonescu, Andrei Poenaru, Cazacu Alexandru şi Andrei Parvu, ultimii doi aflându-se la egalitate. Felicitări!\r\n\r\nNu în cele din urmă, punem sub lupă şi studenţii, care au avut un set de probleme mai uşor ca altădată (Cuburi5 uşoară, Tree medie şi Compact grea). Îi spunem bravo din nou veteranului nostru, Mugurel Ionuţ Andreica, singurul concurent care a obţinut punctaj maxim! El se situează (iar) pe primul loc, atât runda aceasta cât şi în clasamentul final, unde a obţinut un remarcabil scor de peste 1000 de puncte. Felicitările noastre merg şi către al doilea clasat, Marius Drăguş, dar şi către ocupanţii locului 3, unde avem iar egalitate: Tudose Vlad şi Vlad Saveluc.\r\n\r\nÎn ceea ce priveşte comisia ştiinţifică, aceasta şi-a făcut bine treaba, cu aceeaşi rigurozitate cu care v-a obişnuit. O mică scăpare a avut loc la problema Piraţi, unde enunţul nu a fost suficient de clar asupra modului în care trebuie afişată soluţia. Mulţumim concurenţilor pentru că au sesizat cu promptitudine situaţia, pe care am remediat-o imediat pentru a ne asigura că nu defavorizăm pe nimeni. De asemenea, trebuie menţionat faptul că nu s-au putut diferenţia in mod corespunzător soluţiile O(N) şi O(NlogN) la problema Compact şi comisia a preferat să lase limita de timp mai largă pentru a păstra calitatea problemei (diferenţa între concurenţi să nu se facă la nivel de implementare sau în funcţie de diverse trucuri de optimizare). Din păcate, acest lucru a permis ca unii concurenţi să obţină punctajul maxim şi fără să rezolve problema optim.\r\n\r\nCa să nu vă trădăm aşteptările, iată şi statisticile, după cum v-am obişnuit la fiecare rundă: \r\nRunda 4:\r\nNumber of contestants who submitted at least one solution: 119\r\nNumber of registered users: 167\r\nNumber of submitted jobs: 492\r\nNumber of submitted jobs with positive score: 247\r\nNumber of users with positive scores: 86\r\nAverage score of contestants: 64.12\r\nAverage score of contestants with strictly positive scores: 88.72\r\nTotal:\r\nNumber of contestants who submitted at least one solution: 283\r\nNumber of registered users: 499\r\nNumber of submitted jobs: 2436\r\nNumber of submitted jobs with positive score: 1167\r\nNumber of users with positive scores: 199\r\nAverage score of contestants: 129.95\r\nAverage score of contestants with strictly positive scores: 185.05\r\n\r\n\r\nVă aşteptăm şi la finală: cu mic cu mare, în dulce târgul Ieşilor (da, aţi văzut bine, bătălia cea mare se da la Iaşi :) ), Şi pentru cei care nu veţi veni, vă aşteptăm, ca de obicei, la competiţia online, cu aceeaşi (inter)faţă prietenoasă, cu un set de probleme cât se poate de interesante şi cu la fel de multă dedicare: nu fiţi dezamăgiţi de rezultate, ultima şi cea mai importantă rundă vă oferă ocazia să arătaţi că locul vostru este undeva mai sus!\r\n\r\n\r\nPână atunci, vă rugăm nu uitaţi să vă completaţi paginile de profil: vrem să vă cunoaştem, atât noi cât şi tot restul lumii, că doar ne mândrim cu voi. :)\r\nAşteptăm impresiile voastre de până acum, dar şi gândurile cu care întâmpinaţi Finala. În plus, să ştiţi că n-am uitat cât v-a plăcut fotbalul la Braşov. O să revenim cu surprize!',3065,'private',NULL,NULL),('grigore-moisil-2010/solutii/transport2','grigore-moisil-2010/solutii/transport2','2010-03-27 11:36:05','2010-03-27 11:42:09','h2(#transport2). \'Control\':problema/transport2\r\n\r\n...',7271,'public',NULL,NULL),('template/algoritmiada-2010/runda-finala/probleme','template/algoritmiada-2009/runda-finala/probleme','2010-03-27 17:26:37','2010-03-27 17:26:37','(htabs)* \'Despre&hellip;\':algoritmiada-2009/runda-finala\r\n* \'Program\':algoritmiada-2009/runda-finala/program\r\n* \'Regulament\':algoritmiada-2009/runda-finala/regulament\r\n*(active) \'Probleme\':algoritmiada-2009/runda-finala/probleme\r\n* \'Rezultate\':algoritmiada-2009/clasament/runda-finala/5-8\r\n* \'Poze\':algoritmiada-2009/runda-finala/poze',1792,'protected',NULL,NULL),('algoritmiada-2010/clasament/runda-finala/9-10','Algoritmiada 2009, Clasament Runda Finala, Clasele 9-10','2010-03-27 16:58:21','2010-03-27 16:58:21','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda5-9-10\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2009/runda-finala/rezultate\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-finala/5-8\r\n*(active) \'Clasele 9-10\':algoritmiada-2009/clasament/runda-finala/9-10\r\n* \'Clasele 11-12\':algoritmiada-2009/clasament/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-finala/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda5-9-10\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',1490,'protected',NULL,NULL),('algoritmiada-2010/clasament/runda-finala/11-12','Algoritmiada 2009, Clasament Runda Finala, Clasele 11-12','2010-03-27 16:58:21','2010-03-27 16:58:21','==Include(page=\"template/algoritmiada-2009\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2009-runda5-11-12\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2009/runda-finala/rezultate\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':algoritmiada-2009/clasament/runda-finala/5-8\r\n* \'Clasele 9-10\':algoritmiada-2009/clasament/runda-finala/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2009/clasament/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2009/clasament/runda-finala/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2009-runda5-11-12\") == \r\n\r\n==include(page=\"template/algoritmiada-2009/footer\")==\r\n',1490,'protected',NULL,NULL),('notiuni-de-geometrie-si-aplicatii/punct-in-poligon','Punct in poligon','2009-06-28 22:41:59','2010-03-27 17:43:14','h2. Punct in interiorul unui triunghi\r\n\r\nSe da un triunghi prin coordonatele varfurilor. Se cere sa se afiseze pentru un set de $N$ puncte din plan daca apartin sau nu interiorului triunghiului. Pentru a rezolva aceasta problema, sa consideram triunghiul $ABC$ si punctul $P$, interior acestuia.\r\n!notiuni-de-geometrie-si-aplicatii?triunghi.jpg!\r\n\r\nObservam ca vectorii ( **AB**, **BP** ), ( **BC**, **CP** ), ( **CA**, **AP** ) vor realiza mereu acelasi tip de intoarcere (in acest caz spre stanga). De aceea, determinantii:\r\n\r\n<tex>\\begin{math}\\begin{array}{ccc}\r\n\\ x_A & y_A & 1\\\\\r\nx_B & y_B & 1\\\\\r\nx_P & y_P & 1\\end{array}\\right|\\right)\\end{math}\r\n\\begin{math}\\begin{array}{ccc}\r\n\\ x_B & y_B & 1\\\\\r\nx_C & y_C & 1\\\\\r\nx_P & y_P & 1\\end{array}\\right|\\right)\\end{math}\r\n\\begin{math}\\begin{array}{ccc}\r\n\\ x_C & y_C & 1\\\\\r\nx_A & y_A & 1\\\\\r\nx_P & y_P & 1\\end{array}\\right|\\right)\\end{math}\r\n</tex>\r\n\r\ndet( ((xA,yA,1),(xB,yB,1),(xP,yP,1)) ), det( ((xB,yB,1),(xC,yC,1),(xP,yP,1)) ), det( ((xC,yC,1),(xA,yA,1),(xP,yP,1)) ) \r\n*cotizo* - :) trebuie LaTeX :)\r\n\r\ntrebuie sa aiba acelasi semn. In caz contrar, $P$ este in exteriorul triunghiului. In imaginea precedenta, se observa ca in cazul punctului $P\'$, vectorii **BC**, **CP** fac o intoarcere la dreapta, deci determinantul corespunzator nu va avea acelasi semn cu ceilalti doi. \r\n\r\nAceasta idee poate fi generalizata pentru a fi determina daca un punct se afla in interiorul unui poligon convex in $O(N)$. Mai exact se calculeaza det( (x{~i~},y{~i~},1), (x{~i+1~}, y{~i+1~}, 1) (x{~p~},y{~p~},1) ) pentru $i$ luand valori de la $1$ la $N$ (cand $i$=={$N$} vom considera $i+1=1$) . Punctul P(x{~p~},y{~p~}) se afla in interiorul poligonului daca si numai daca toti determinanti au acelasi semn. ( \"+\" daca parcurgem poligonul in sens direct trigonometric, \"-\" altfel)\r\n\r\nh2. Punct in interiorul unui poligon oarecare\r\n\r\nSe da un poligon oarecare cu $N$ varfuri si un punct $P$ prin coordonatele carteziene. Se cere sa se determine daca punctul $P$ este in interiorul sau in exteriorul poligonului. \r\n\r\nSe va trasa o semidreapta orizontala cu originea in punctul $P$. Daca aceasta semidreapta intersecteaza un numar impar de muchii ale poligonului, atunci punctul se afla in interiorul acestuia. Mentionam ca trebuie avut in vedere cazul in care semidreapta trece chiar printr-un varf de poligon (capat a doua muchii). Vom considera imaginea urmatoare:\r\n\r\n !notiuni-de-geometrie-si-aplicatii?poligon-raza.jpg!\r\n\r\nIn cazul punctului P{~1~}, respectiv P{~2~}, semidreptele intersecteaza 3, respectiv 1 latura (numere impare) deci punctele se afla in interior. Semidreapta corespunzatoare lui P{~3~} intersecteaza o latura si un varf de poligon. Pentru a rezolva acum aceasta problema, o solutie ar fi ca in loc sa alegem semidreapta orizontala, sa luam o semidreapta random, astfel posibilitatea ca ea sa intersecteze varfurile poligonului tinde spre 0. O alta solutie posibila - si mai usor de implementat - este sa consideram ca facand parte dintr-o latura doar punctul cu coordonata y mai mare. Se garanteaza astfel ca laturile care contin punctul de pe semidreapta vor fi numarate de numar par de ori (2 pt punctul de sus, 0 pt punctul de jos) si ca, implicit, nu vor afecta corectitudinea algoritmului.\r\n\r\n\r\n*devilkind* - am dat eu o solutie care merge destul de bine ptr cazul in care semidreapta orizontala intersecteaza varfuri insa e cam jegoasa asa (cu semidrepte random si e cam aiurea). Era un smen in care considerai ca numai un capat al laturii face parte din ea, dar nu mai stiu cum era.\r\n*EDIT Gcosmin (tip)* : in cazul in care semidreapta aleasa (sa zicem ca e paralela cu OX (e bine sa fie asa)) trece fix prin varful unui segment din poligon atunci segmentul il numaram doar daca semidreapta aleasa trece prin varful cu y-u mai mare. chestia asta scoate cazurile particulare si merge (da niste exemple si o sa vezi). e total aiurea sa iei o dreapta random pentru ca se complica mult treaba aiurea.\r\n*cotizo* - multumim mult :) orice ajutor e binevenit :D pastram ambele variante pt ca si eu in concurs as fi bagat un random.\r\n\r\nh2. Punct in poligon convex\r\n\r\nEnunt: Se da un poligon convex cu $N$ laturi si apoi $M$ interogari caracterizate prin coordonatele unui punct $P$, iar dumneavoastra trebuie sa determinati rapid daca punctul respectiv se afla sau nu in interiorul poligonului.\r\n\r\n*{+Solutia 1+}*\r\n\r\nSe ia un varf al poligonului, si se traseaza cele $n-3$ diagonale care pornesc din el. Astfel poligonul nostru se imparte in mai multe triunghiuri. Vom adauga intr-un vector aceste drepte plus cele $2$ laturi care au originea in varful ales de noi si le sortam dupa panta. Cand primim un query vom cauta binar dupa panta si vom afla intre ce diagonale se incadreaza acesta si verificam daca punctul nostru se afla sau nu in triunghiul respectiv. \r\n\r\nSa luam un exemplu:\r\n!notiuni-de-geometrie-si-aplicatii?polig12!\r\n\r\nIn imaginea de mai sus punctele $P{~1~}$,..{$P{~6~}$} reprezinta varfurile poligonului iar punctele $P{~7~}$, $P{~8~}$, $P{~9~}$ reprezinta interogarile. Cu rosu sunt trasate diagonalele care delimiteaza sectoarele, si le vom tine ca drepte, sortate dupa panta, impreuna cu dreptele suport pentru cele 2 laturi care au un capat in punctul $P{~1~}$. Astfel cand primim o interogare vom putea cauta binar si sa aflam in ce sector se afla acesta. Pentru punctul $P{~8~}$ spre exemplu ne vom da seama ca se afla in sectorul determinat de diagonalele care corespund punctelor $P{~4~}$ si $P{~5~}$. Astfel vom verifica daca punctul $P{~8~}$ se afla in interiorul triunghiului determinat de punctele $P{~1~}$, $P{~4~}$, $P{~5~}$. Vom proceda asemanator si pentru celelalte interogari cu mentiunea ca trebuie sa avem grija la cazurile in care punctul nu se afla in nici unul din sectoare (P{~9~}), insa asta se poate face usor cu o verificare inainte de a porni cautarea binara. \r\n\r\nAceasta solutie are complexitate O(NlogN + MlogN).\r\n\r\n*{+Solutia 2+}*\r\n\r\nO alta solutie este sa impartim planul in fasii. Astfel din fiecare varf al poligonului vom trasa o dreapta verticala. Acum pentru 2 drepte consecutive vom lua laturile care il intersecteaza si le vom sorta crescator dupa y (e clar ca aceste laturi nu se intersecteaza deci putem alege orice punct de pe latura si sa sortam dupa y-ul acestuia). Acum pentru a raspunde la interogari, vom face 2 cautari binare. Vom cauta odata sa vedem in ce fasie se incadreaza punctul nostru, iar apoi vom cauta inca odata binar sa vedem cate laturi din acea fasie sunt au y-ul mai mic decat punctul nostru. Daca acest numar este impar atunci punctul este in interior, altfel este in exterior. De mentionat ca aceasta solutie se poate aplica si la poligoane concave, de altfel in cazul poligoanelor convexe nu pot fi decat 2 laturi pe o fasie si nu ar mai fi nevoie de a doua cautare binara.\r\n\r\nSa luam un exemplu:\r\n\r\n\r\n!notiuni-de-geometrie-si-aplicatii?polig22!\r\n\r\nObservam cu rosu dreptele care delimiteaza fasiile verticale. De asemenea vedem ca punctul $P{~6~}$ are in fasia lui 2 laturi cu y-ul mai mic ca al lui si este in afara poligonului, spre deosebire de punctul $P{~7~}$ care are o singura latura cu y-ul mai mic ca al sau si este in interior.\r\nAvantajul acestei metode este ca functioneaza si in cazul poligoanelor concave, insa are dezavantajul faptului ca pot exista interogari in care punctele sa se afle pe dreapta care delimiteaza fasiile. Practic aceasta metoda este echivalenta cu metoda explicata mai sus, pentru a verifica daca un punct se afla sau nu in interiorul unui poligon oarecare. \r\nIn cazul poligoanelor convexe complexitatea este aceeasi ca si la metoda de mai sus, insa in cazul poligoanelor concave complexitatea teoretica e O(N^2 log N + M log N). Acest algoritm poate fi aplicat in rezolvarea problemei \'poligon\':problema/poligon din arhiva de probleme.\r\n\r\n\r\n*devilkind* uitativa putin la solutia asta ptr ca nu sunt foarte sigur pe complexitati - in special cand e vb de poligoane concave. Mie mi se pare ca aia e complexitatea insa e posibil sa ma insel\r\n*cotizo* da e corect - asta e si rezolvarea problemei \"poligon\"',8239,'public',NULL,NULL),('algoritmiada-2010/clasament/runda-finala/11-12','Algoritmiada 2010, Clasament Runda Finala, Clasele 11-12','2010-03-27 16:58:21','2010-03-27 17:34:34','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda5-11-12\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2010/runda-finala/rezultate\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':algoritmiada-2010/clasament/runda-finala/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/clasament/runda-finala/9-10\r\n*(active) \'Clasele 11-12\':algoritmiada-2010/clasament/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2010/clasament/runda-finala/studenti\r\n\r\np<. == Rankings(rounds=\"algoritmiada2010-runda5-11-12\") == \r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==\r\n',1792,'protected',NULL,NULL),('template/newround/clasament','Clasament %round_id%','2006-11-23 00:06:53','2006-11-23 21:06:44','h1. Clasament ==roundparam(round_id=\"%round_id%\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"%round_id%\")==',1142,'protected',NULL,NULL),('algoritmiada-2010/runda-finala/5-8','Algoritmiada 2010, Runda Finală, Clasele 5-8','2010-03-27 16:56:51','2010-03-28 09:16:17','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda5-5-8\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2010/runda-finala/probleme\")==\r\n\r\n(htabs-2)*(active) \'Clasele 5-8\':algoritmiada-2010/runda-finala/5-8\r\n* \'Clasele 9-10\':algoritmiada-2010/runda-finala/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-finala/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda5-5-8\") ==\r\n\r\nConcursul începe ==roundparam(round_id=\"algoritmiada2010-runda5-5-8\" param=\"start_time\" strong=\"true\")== şi durează ==roundparam(round_id=\"algoritmiada2010-runda5-5-8\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"algoritmiada2010-runda5-5-8\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-finala/5-8.\r\n\r\nh2. Probleme\r\n\r\nAceastă listă va deveni vizibilă doar în momentul începerii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda5-5-8\" score=\"1\")==\r\n\r\nh2. Discuţii pe forum\r\n\r\nVrei să adresezi întrebări comisiei? Fă-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"5\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('algoritmiada-2010/runda-finala/9-10','Algoritmiada 2010, Runda Finală, Clasele 9-10','2010-03-27 16:56:52','2010-03-28 09:17:15','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. == roundparam(round_id=\"algoritmiada2010-runda5-9-10\" param=\"title\") ==\r\n\r\n==Include(page=\"template/algoritmiada-2010/runda-finala/probleme\")==\r\n\r\n(htabs-2)* \'Clasele 5-8\':algoritmiada-2010/runda-finala/5-8\r\n*(active) \'Clasele 9-10\':algoritmiada-2010/runda-finala/9-10\r\n* \'Clasele 11-12\':algoritmiada-2010/runda-finala/11-12\r\n* \'Studenti\':algoritmiada-2010/runda-finala/studenti\r\n\r\n== roundregister(round_id=\"algoritmiada2010-runda5-9-10\") ==\r\n\r\nConcursul începe ==roundparam(round_id=\"algoritmiada2010-runda5-9-10\" param=\"start_time\" strong=\"true\")== şi durează ==roundparam(round_id=\"algoritmiada2010-runda5-9-10\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"algoritmiada2010-runda5-9-10\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':algoritmiada-2010/clasament/runda-finala/9-10.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n== Tasks(round_id=\"algoritmiada2010-runda5-9-10\" score=\"1\")==\r\n\r\nh2. Discuţii pe forum\r\n\r\nVrei sa adresezi întrebări comisiei? Fă-o pe forum.\r\n\r\n==SmfTopics(board_id=\"77\" count=\"5\")==\r\n\r\n==include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('grigore-moisil-2010/solutii/g2','grigore-moisil-2010/solutii/g2','2010-03-27 11:45:40','2010-03-27 11:45:40','h2(#g2). \'G2\':problema/g2\r\n\r\n...',7271,'public',NULL,NULL),('grigore-moisil-2010/solutii/g2','grigore-moisil-2010/solutii/g2','2010-03-27 11:45:40','2010-03-28 10:28:28','h2(#g2). \'G2\':problema/g2\r\n\r\n\r\nVom folosi metoda greedy. În realitate însă nu este nevoie decât de puţină intuiţie. Condiţia ca produsul cifrelor să fie n ne conduce la ideea că cifrele numărului sunt divizori ai lui n. Un cel mai mic număr presupune în primul rând un număr minim de cifre. Astfel, vom descompune pe n într-un produs de cât mai mulţi de 9, după care cât mai mulţi de 8... până la 2. Numărul căutat reprezintă numărul format cu aceste cifre în ordine crescătoare.',9232,'public',NULL,NULL),('grigore-moisil-2010/solutii/pietre2','grigore-moisil-2010/solutii/pietre2','2010-03-27 11:47:20','2010-03-28 10:45:56','h2(#pietre2). \'Pietre2\':problema/pietre2\r\n\r\nRezolvare 1\r\n\r\nSoluţia se bazează pe observaţia că dacă vom procesa înălţimile în ordine crescătoare, atunci vom putea actualiza un drum de lungime maximă ce se termină în fiecare din aceste pătrăţele în mod corect. \r\n\r\nAstfel, algoritmul va sorta crescător toate cele n2 pătrăţelele în funcţie de înălţime şi...\r\n\r\n== code(cpp)|\r\nAlgoritm Rezolvă(n):\r\n  pentru fiecare (h, i, j) execută:	// pătrăţelul (i, j) cu înălţimea h\r\n    pentru fiecare vecin (h’, i’, j’) cu h = h’ + 1 execută:\r\n	dacă lg[i][j] < lg[i’][j’] + 1 atunci\r\n	  lg[i][j] = lg[i’][j’] + 1\r\n	sfârşit(dacă)\r\n    sfârşit(pentru)\r\n  sfârşit(pentru)\r\n\r\n   caută max{lg[i][j] : 1 <= i, j <= n}\r\n  reconstruieşte drumul alegând un vecin cu lungimea mai mică cu exact 1 \r\n  până ce se ajunge la marginea matricei.\r\nSfârşit(algoritm)\r\n==\r\n\r\nÎn implementare se va ţine cont ca pătrăţelele de pe marginea matricei care sunt puncte de plecare să fie marcate iniţial cu 0.\r\nComplexitate: O(N^2^ log(N)).\r\n\r\nRezolvare 2\r\nProblema, în ciuda faptului că limita pentru n este mare, se putea aborda şi cu backtracking. Cu o rezolvare asemănătoare cu cea de mai jos se putea obţine 90 puncte.\r\nÎn programul principal:\r\n\r\n== code(cpp)  |\r\nAlgoritm Pietre(n,t): 	// n: dimensiunea tabloului t \r\n  max = 0	// lungimea maximă a drumului \r\n  maxlin = 0 	// linia de unde porneşte cel mai lung drum \r\n  maxcol = 0	// coloana de unde porneşte cel mai lung drum \r\n  lin = 1 	// vom încerca să intrăm în tablou pornind din linia 1 \r\n  pentru col=1,n execută:\r\n    maxnou = 0 	// maximul actual \r\n    rez[lin,col] = 1 	// marcăm punctul de pornire \r\n    cauta(lin,col,2) 	// căutăm un drum având acest punct de start \r\n    dacă maxnou > max atunci	// actualizarea \r\n      max = maxnou\r\n      maxlin = lin\r\n      maxcol = col\r\n    sfârşit(dacă)\r\n  sfârşit(pentru)\r\n  //...  	 la fel procedăm cu linia n, coloana 1 şi coloana n \r\nsfârşit(algoritm)\r\n\r\nAlgoritm Cauta(lin,col,pas):\r\n  pentru i=1,4 execută:	// un element are 4 vecini \r\n    lin_nou = lin + x[i] 	// indicele de linie al vecinului \r\n    col_nou = col + y[i]	// indicele de coloană \r\n	// dacă am generat o poziţie pe teren }\r\n    dacă (lin_nou = {1,2,...,n}) şi (col_nou = {1,2,...,n}) atunci\r\n      dacă rez[lin_nou,col_nou] = 0 atunci 	// dacă nu am fost aici \r\n	// dacă numărul pietrelor este cu 1 mai mare \r\n        dacă t[lin_nou,col_nou] = t[lin,col] + 1 atunci\r\n          rez[lin_nou,col_nou] = pas	// facem pasul \r\n          dacă pas > maxnou atunci    	 //actualizăm maximul actual\r\n            maxnou = pas\r\n          sfârşit(dacă)\r\n          Cauta(lin_nou,col_nou,pas+1) 	// încercăm să continuăm drumul \r\n          rez[lin_nou,col_nou] = 0	// ştergem pasul, pentru că vom căuta alt drum \r\n        sfârşit(dacă)\r\n      sfârşit(dacă)\r\n    sfârşit(dacă)\r\n  sfârşit(pentru)\r\nSfârşit(algoritm)\r\n==\r\n\r\n\r\nunde şirurile x şi y au valorile:\r\nx = (-1,0,1,0)\r\ny = (0,1,0,-1)',9232,'public',NULL,NULL),('grigore-moisil-2010/solutii/pietre2','grigore-moisil-2010/solutii/pietre2','2010-03-27 11:47:20','2010-03-28 12:14:36','h2(#pietre2). \'Pietre2\':problema/pietre2\r\n\r\n*Rezolvare $1$*\r\n\r\nSoluţia se bazează pe observaţia că dacă vom procesa înălţimile în ordine crescătoare, atunci vom putea actualiza un drum de lungime maximă ce se termină în fiecare din aceste pătrăţele în mod corect. \r\n\r\nAstfel, algoritmul va sorta crescător toate cele $n^2^$ pătrăţelele :\r\n\r\n== code(cpp) | \r\nAlgoritm Rezolvă(n):\r\n  pentru fiecare (h, i, j) execută:	// pătrăţelul (i, j) cu înălţimea h\r\n    pentru fiecare vecin (h’, i’, j’) cu h = h’ + 1 execută:\r\n	dacă lg[i][j] < lg[i’][j’] + 1 atunci\r\n	  lg[i][j] = lg[i’][j’] + 1\r\n	sfârşit(dacă)\r\n    sfârşit(pentru)\r\n  sfârşit(pentru)\r\n\r\n   caută max{lg[i][j] : 1 <= i, j <= n}\r\n  reconstruieşte drumul alegând un vecin cu lungimea mai mică cu exact 1 \r\n  până ce se ajunge la marginea matricei.\r\nSfârşit(algoritm)\r\n==\r\n\r\nÎn implementare se va ţine cont ca pătrăţelele de pe marginea matricei care sunt puncte de plecare să fie marcate iniţial cu $0$.\r\nComplexitate: $O(N^2^ log(N))$.\r\n\r\n*Rezolvare $2$*\r\nProblema, în ciuda faptului că limita pentru n este mare, se putea aborda şi cu backtracking. Cu o rezolvare asemănătoare cu cea de mai jos se putea obţine $90$ puncte.\r\nÎn programul principal:\r\n\r\n== code(cpp)  |\r\nAlgoritm Pietre(n,t): 	// n: dimensiunea tabloului t \r\n  max = 0	// lungimea maximă a drumului \r\n  maxlin = 0 	// linia de unde porneşte cel mai lung drum \r\n  maxcol = 0	// coloana de unde porneşte cel mai lung drum \r\n  lin = 1 	// vom încerca să intrăm în tablou pornind din linia 1 \r\n  pentru col=1,n execută:\r\n    maxnou = 0 	// maximul actual \r\n    rez[lin,col] = 1 	// marcăm punctul de pornire \r\n    cauta(lin,col,2) 	// căutăm un drum având acest punct de start \r\n    dacă maxnou > max atunci	// actualizarea \r\n      max = maxnou\r\n      maxlin = lin\r\n      maxcol = col\r\n    sfârşit(dacă)\r\n  sfârşit(pentru)\r\n  //...  	 la fel procedăm cu linia n, coloana 1 şi coloana n \r\nsfârşit(algoritm)\r\n\r\nAlgoritm Cauta(lin,col,pas):\r\n  pentru i=1,4 execută:	// un element are 4 vecini \r\n    lin_nou = lin + x[i] 	// indicele de linie al vecinului \r\n    col_nou = col + y[i]	// indicele de coloană \r\n	// dacă am generat o poziţie pe teren }\r\n    dacă (lin_nou = {1,2,...,n}) şi (col_nou = {1,2,...,n}) atunci\r\n      dacă rez[lin_nou,col_nou] = 0 atunci 	// dacă nu am fost aici \r\n	// dacă numărul pietrelor este cu 1 mai mare \r\n        dacă t[lin_nou,col_nou] = t[lin,col] + 1 atunci\r\n          rez[lin_nou,col_nou] = pas	// facem pasul \r\n          dacă pas > maxnou atunci    	 //actualizăm maximul actual\r\n            maxnou = pas\r\n          sfârşit(dacă)\r\n          Cauta(lin_nou,col_nou,pas+1) 	// încercăm să continuăm drumul \r\n          rez[lin_nou,col_nou] = 0	// ştergem pasul, pentru că vom căuta alt drum \r\n        sfârşit(dacă)\r\n      sfârşit(dacă)\r\n    sfârşit(dacă)\r\n  sfârşit(pentru)\r\nSfârşit(algoritm)\r\n==\r\n\r\n\r\nunde şirurile $x$ şi $y$ au valorile:\r\n$x = (-1,0,1,0)$\r\n$y = (0,1,0,-1)$',9232,'public',NULL,NULL),('grigore-moisil-2010/solutii/egipt','grigore-moisil-2010/solutii/egipt','2010-03-27 11:44:17','2010-03-28 12:16:18','h2(#egipt). \'Egipt\':problema/egipt\r\n\r\n*Rezolvare $1$*\r\n\r\nFie $n1$ numărul elementelor egale cu $1$, $n2$ numărul elementelor egale cu $2$ şi $n3$ numărul elementelor egale cu $3$ în şirul dat $a$. Altfel spus, în şirul ordonat vom avea valori egale cu $1$ începând cu poziţia $1$ până la poziţia $n1$, valori egale cu $2$ începând cu poziţia $n1+1$ până la poziţia $n1+n2$, după care vom avea elemente egale cu $3$.\r\nNotăm cu $mij$ numărul elementelor egale cu $j$ care se află pe o poziţie pe care ar trebui să avem valoarea $i$. (Matricea $m$ are $3$ linii şi $3$ coloane.)\r\n\r\n                               !grigore-moisil-2010/solutii/egipt?1.png!\r\n\r\nFig. $1$. În mij avem numărul elementelor care trebuie duse de pe poziţia $i$ pe poziţia $j$\r\nObservăm că\r\n$m12 + m13 = m21 + m31$\r\n$m21 + m23 = m12 + m32$ \r\n$m31 + m32 = m13 + m23$\r\n\r\nDacă avem $2$ pe poziţia unui $1$ şi $1$ pe poziţia unui $2$, avem nevoie de o singură interschimbare. \r\nDacă avem o configuraţie $2 3 1$, sau $3 1 2$, avem nevoie de două interschimbări. \r\n\r\n        !grigore-moisil-2010/solutii/egipt?2.png!\r\n\r\nRezultă că numărul minim de interschimbări care sunt necesare pentru ordonarea şirului este:\r\n$min(m12, m21) + min(m23, m32) + min(m13, m31) + 2|m12 − m21|$\r\nRealizarea interschimbărilor:\r\n\r\n        !grigore-moisil-2010/solutii/egipt?3.png!\r\nFig. $3$. Poziţiile interschimbărilor: $pij$ este indicele elementului egal cu $j$ aflat pe poziţia $i$\r\n\r\n\r\n\r\n\r\n*Rezolvare $2$*\r\n\r\nRezolvarea se face în două faze. În prima fază vom pune la loc elementele egale cu $1$. Pornim cu trei variabile: $i$ va itera pornind din prima poziţie şi va merge până în ultima poziţie unde trebuie să ajungă un element egal cu $1$; $i2$ va porni din prima poziţie unde trebuie să ajungă un element egal cu $2$ şi va merge pâna la ultima poziţie de acest fel; similar $i3$ va itera pe intervalul unde trebuie să ajungă elementele egale cu $3$. \r\n$i2$ şi $i3$ vor fi poziţionate întotdeauna asupra unui element egal cu $1$. Dacă elementul pe care am poziţionat $i$ este egal cu $1$, nu trebuie să facem nimica, doar incrementăm $i$. Dacă acesta este egal cu $2$, vom schimba elementele de pe locurile $i$ şi $i2$ şi vom incrementa $i$, iar pe $i2$ îl poziţionăm pe următorul element egal cu $1$. Dacă cu $i2$ am depăşit pragul din dreapta al intervalului (adică ultimul loc unde trebuie să ajungă $2$), elementul de pe poziţia $i$ îl vom schimba cu elementul arătat de $i3$. Procedăm similar pentru elementele egale cu $3$.\r\n	În a doua fază vor ajunge şi elementele egale cu $2$ şi $3$ la locul lor, prin interschimbări evidente.',9232,'public',NULL,NULL),('grigore-moisil-2010/solutii/transport2','grigore-moisil-2010/solutii/transport2','2010-03-27 11:36:05','2010-03-28 14:56:11','h2(#transport2). \'Transport2\':problema/transport2\r\n\r\n*Soluţie 1*\r\nPentru a afla costul de la nodul $1$ la nodul $N$, vom utiliza \'algorimul lui Dijkstra\':problema/dijkstra puţin modificat. Astfel, vom reţine pentru fiecare nod, valoarea minimă între nodul $1$ şi nodul respectiv. Când dorim să mergem în vecinii nodului curent trebuie verificat dacă $min(costul_nodului_curent, costul_muchiei) > costul_nodului_vecin$. Complexitatea acestui algoritm este $O(M logN)$. \r\n\r\n*Soluţie 2*\r\nVom căuta binar răspunsul între 1 şi valoarea maximă pe care o poate avea o muchie. Pentru o valoare fixată, vom considera doar muchiile cu valoarea mai mare sau egală cu valoarea fixată şi vom utiliza o \'parcurgere în adâncime\':problema/bfs pentru a vedea dacă nodurile $1$ şi $N$ sunt în aceeaşi componentă conexă.\r\n\r\n*Soluţie 3*\r\nPentru fiecare valoare vom reţine ce muchii au valoarea respectivă. Apoi, vom itera prin toate valorile posibile începând de la cea maximă şi la fiecare pas vom uni nodurile care sunt legate prin muchia respectivă folosind structura \'mulţimi disjuncte\':problema/disjoint. Ne vom opri în momentul în care nodurile $1$ şi $N$ sunt în aceeaşi componentă conexă, rezultatul fiind prima valoare pentru care nodurile $1$ şi $N$ se află în aceeaşi componentă conexă. ',6333,'public',NULL,NULL),('runda/pregatire_2/clasament','Clasament pregatire_2','2010-04-01 13:37:02','2010-04-01 13:37:02','h1. Clasament ==roundparam(round_id=\"pregatire_2\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"pregatire_2\" detail_task=\"true\")==',11154,'round: pregatire_2',NULL,NULL),('utilizator/gavrilavlad','Profil Gavrila Vlad','2007-09-21 12:07:43','2010-03-10 06:06:18','   \r\n\r\nh2. Despre mine\r\n\r\nMa numesc Gavrila Vlad Alexandru si sunt elev in clasa a IX-a la ICHB. Particip de mult timp la concursuri de informatica, iar principala mea sursa de pregatire este infoarena.\r\n\r\nh2. Distinctii primite\r\n\r\nOlimpiada Nationala de Informatica\r\n\r\n* 2004 - Buzau - Mentiune\r\n* 2005 - Galati - Premiul special\r\n* 2006 - Targoviste - Mentiunea I\r\n* 2007 - Cluj - Premiul II\r\n* 2008 - Bacau - Premiul I\r\n* 2009 - Galati - Premiul II\r\n\r\nJBOI\r\n\r\n* 2008 - Shumen - Argint\r\n* 2009 - Shumen - Aur absolut\r\n\r\nPreONI, Algoritmiada si .Campion\r\n\r\n* 2008 - PreONI - Finalist\r\n* 2009 - .Campion - Locul II\r\n* 2009 - Algoritmiada - Locul I\r\n\r\nOlimpiada Nationala de Fizica\r\n\r\n* 2008, 2009, 2010 - Premiul I\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n* Profesori:\r\n\r\n==user(user=\"pauldb\" type=\"normal\")==\r\n\r\n==user(user=\"wefgef\" type=\"normal\")==\r\n\r\n==user(user=\"bogdan2412\" type=\"normal\")==\r\n\r\n==user(user=\"gcosmin\" type=\"normal\")==\r\n\r\n==user(user=\"silviug\" type=\"normal\")==\r\n\r\n\r\n* Prieteni:\r\n\r\n==user(user=\"savim\" type=\"normal\")==\r\n\r\n==user(user=\"radu_voroneanu\" type=\"normal\")==\r\n\r\n==user(user=\"toni2007\" type=\"normal\")==\r\n\r\n==user(user=\"victor.ionescu\" type=\"normal\")==\r\n\r\n==user(user=\"CezarMocan\" type=\"normal\")==\r\n\r\n==user(user=\"raduzer\" type=\"normal\")==\r\n\r\n==user(user=\"matemariaescu\" type=\"normal\")==\r\n\r\n==user(user=\"GheorgheMihai\" type=\"normal\")==\r\n\r\n==user(user=\"protoman\" type=\"normal\")==\r\n\r\n==user(user=\"tvlad\" type=\"normal\")==\r\n\r\n==user(user=\"andrei-alpha\" type=\"normal\")==\r\n\r\n==user(user=\"taloibogdan\" type=\"normal\")==\r\n\r\n==user(user=\"andreea1cool\" type=\"normal\")==\r\n\r\n==user(user=\"cristian9\" type=\"normal\")==\r\n\r\n==user(user=\"tomescu_dorinel\" type=\"normal\")==\r\n\r\n==user(user=\"stef2503\" type=\"normal\")==\r\n\r\n==user(user=\"Balmus_Maxim\" type=\"normal\")==',6800,'public',NULL,NULL),('utilizator/mathboy','Rotaru Dragos Alin','2008-12-24 18:43:37','2010-04-01 06:44:22','h2. Despre mine\r\n \r\n\r\n* Elev in clasa a X-a la Colegiul National \"Unirea\" Focsani.\r\n* Lucrez pe Infoarena din 24 Decembrie 2008.\r\n \r\n\r\nh2. Prieteni pe infoarena\r\n \r\n\r\n ==user(user=\"Omega91\" type=\"normal\")==\r\n ==user(user=\"bogdanhm999\" type=\"normal\")== \r\n ==user(user=\"Florian\" type=\"normal\")==\r\n ==user(user=\"cosmin79\" type=\"normal\")==\r\n ==user(user=\"klamathix\" type=\"normal\")==\r\n ==user(user=\"Protoman\" type=\"normal\")==\r\n ==user(user=\"blasterz\" type=\"normal\")==\r\n ==user(user=\"mishu91\" type=\"normal\")==\r\n ==user(user=\"robytzza\" type=\"normal\")==\r\n ==user(user=\"doru.nitu\" type=\"normal\")==\r\n ==user(user=\"stef2n\" type=\"normal\")==\r\n ==user(user=\"DraStiK\" type=\"normal\")==\r\n\r\nOrdinea nu are importanta.\r\n \r\n',9232,'public',NULL,NULL),('algoritmiada-2010/premii','Algoritmiada 2010 - Sponsori si premii','2009-10-25 17:30:27','2009-11-03 11:52:44','==Include(page=\"template/algoritmiada-2010\")==\r\n\r\nh1. Sponsori si premii\r\n\r\nh2. Premii\r\n\r\nPentru fiecare dintre cele patru grupe, primii din clasament in urma desfasurarilor probelor online vor fi premiati cu o diploma de finalist al concursului *Algoritmiada 2010* si o \'runda finala\':algoritmiada-2010/runda-finala cu cazare si masa asigurate.\r\nAcestia vor avea sansa sa interactioneze cu membrii \'echipei infoarena\':echipa-infoarena si cu ceilalti membri ai comunitatii infoarena si sa invete de la si impreuna cu acestia. Runda finala va fi de asenemea un prilej de a ii rasplati pe cei mai buni dintre cei mai buni. Punctajele din acesta runda vor fi independente de cele acumulate la rundele online, iar primii 3 clasati la fiecare grupa vor avea parte de urmatoarele premii:\r\n\r\n* Locul I: &hellip;\r\n* Locul II: &hellip;\r\n* Locul III: &hellip;\r\n\r\n==Include(page=\"template/algoritmiada-2010/footer\")==',1792,'protected',NULL,NULL),('runda/problemiada_15/clasament','Clasament problemiada_15','2010-04-13 18:33:33','2010-04-13 18:33:33','h1. Clasament ==roundparam(round_id=\"problemiada_15\" param=\"title\") ==\r\n\r\nFelicitari primilor clasati!!!\r\n\r\n==Rankings(rounds = \"problemiada_15\" detail_task=\"true\")==',5748,'round: problemiada_15',NULL,NULL),('blog/think-online','blog/think-online','2010-04-14 20:00:18','2010-04-14 20:21:27','h1. Think Online\r\n\r\nZilele acestea va avea loc \'Think Online\':http://thinkonline.ro/, un proiect dedicat tinerilor interesaţi de mediul de afaceri online. Pentru că aveţi cunoştinţe solide de algoritmică şi sunteţi programatori talentaţi, ne-am gândit că v-ar ajuta să aruncaţi un ochi şi la partea de business din domeniu.\r\n\r\n&nbsp;\r\nIată mesajul organizatorilor:\r\n\r\n&nbsp;\r\n_Business Club te invită în perioada 19-23 Aprilie să participi la proiectul Think Online. Într-un moment critic al economiei, domeniul afacerilor pe Internet devine unul din ce în ce mai atrăgător pentru antreprenori. Think Online, cel mai nou proiect marca Business Club, este o şcoală de antreprenoriat care va pregăti un număr de studenţi pentru a îşi deschide o afacere on-line. Ne adresăm studenţilor sau masteranzilor care sunt interesaţi de domeniul acesta, care şi-au deschis o afacere/site sau care au de gând să facă acest lucru în viitorul apropriat. Studii de caz, workshop-uri, simulări de management, networking şi un concurs inedit de idei, totul într-o atmosferă plăcută şi optimă pentru a genera idei de succes. Proiectul va avea loc la Bucharest Hubb, primul club de work&fun din România dedicat antreprenorilor online._\r\n\r\n_Participând la eveniment, vei avea ocazia să întâlneşti oameni interesaţi de afaceri online, să îţi formezi o echipă şi să creezi un plan de afaceri sub îndrumarea celor mai de succes antreprenori. Vei cunoaşte investitori, vei face networking, vei învăţa de la oameni care au o experienţă bogată în start-up-uri. Vei invăţa cum să prezinţi un pitch unui investitor şi vei primi feedback. Dar, cel mai important, dacă planul de afaceri pe care îl vei dezvolta în cadrul proiectului va fi unul atractiv, vei avea ocazia să primeşti finanţare de la un investitor important._\r\n\r\n_Şi nu uita, la sfârşitul proiectului, după aproximativ o lună, cei mai buni participanţi vor avea ocazia să participe la un teambuilding alături de o parte din speakerii evenimentului pentru a îi cunoaşte mai bine, a îşi prezenta ideile şi a lega eventuale colaborări._\r\n\r\n_La proiect, vei avea ocazia să îi cunoşti pe Vlad Stan (SeedMoney), Sergiu Biriş (Trilulilu), Vladimir Oane (UberVU), George Lemnaru (Erepublik), Daniel Enache (Investitor), Marius Deak (GreenPixel) şi mulţi alţii!_\r\n\r\n_Pentru a aplica la proiect accesează site-ul \'www.thinkonline.ro\':http://thinkonline.ro/ ._',2044,'protected',4784,NULL),('utilizator/motty','Profil motty','2008-10-24 09:08:52','2010-04-15 09:22:14','h2. Despre mine\r\n\r\n* _Sunt elev in clasa a 10-a la Colegiul National de Informatica \"Tudor Vianu\"_\r\n* _Am inceput informatica in octombrie 2008 ~(clasa a 9-a)~_\r\n* _{*In God we Trust!*}_\r\n* _Gibson rulez \\m/!_\r\n* _Aidi: motty_ep_\r\n\r\nh2. Distinctii primite\r\n\r\n* _Mentiune la ONI 2009 ~(clasa a 9-a)~_\r\n* _Premiul I la Concursul de Informatica \"Urmasii lui Moisil\" Iasi - 2009_\r\n* _Mentiune si argint la ONI 2010 ~(clasa a 10-a)~_\r\n\r\nh2. Profesori\r\n\r\n ==User(user=\"rapidu36\" type=\"tiny\")==\r\n  ==User(user=\"filipb\" type=\"tiny\")==\r\n  ==User(user=\"andrei.12\" type=\"tiny\")==\r\n\r\nh2. Prieteni pe infoarena\r\n\r\n ==User(user=\"gabitzish1\" type=\"tiny\")==\r\n  ==User(user=\"gcosmin\" type=\"tiny\")==\r\n  ==User(user=\"cosmin79\" type=\"tiny\")==\r\n  ==User(user=\"ira\" type=\"tiny\")==\r\n  ==User(user=\"ilinca\" type=\"tiny\")==\r\n  ==User(user=\"Robytzza\" type=\"tiny\")==\r\n  ==User(user=\"funkydvd\" type=\"tiny\")==\r\n  ==User(user=\"punkist\" type=\"tiny\")==\r\n  ==User(user=\"andreyp\" type=\"tiny\")==\r\n  ==User(user=\"tvlad\" type=\"tiny\")==\r\n  ==User(user=\"ciprianf\" type=\"tiny\")==\r\n  ==User(user=\"drag0s93\" type=\"tiny\")==\r\n  ==User(user=\"AndreiDuma\" type=\"tiny\")==\r\n  ==User(user=\"Ioanna\" type=\"tiny\")==\r\n  ==User(user=\"andrei-alpha\" type=\"tiny\")==\r\n  ==User(user=\"hadesgames\" type=\"tiny\")==\r\n  ==User(user=\"andreisfrent\" type=\"tiny\")==\r\n  ==User(user=\"nemultumitu\" type=\"tiny\")==',8690,'public',NULL,NULL),('blog/think-online','Think Online','2010-04-14 20:00:18','2010-04-14 21:18:51','h1. Think Online\r\n\r\nZilele acestea va avea loc \'Think Online\':http://thinkonline.ro/, un proiect dedicat tinerilor interesaţi de mediul de afaceri online. Pentru că aveţi cunoştinţe solide de algoritmică şi sunteţi programatori talentaţi, ne-am gândit că v-ar ajuta să aruncaţi un ochi şi la partea de business din domeniu.\r\n\r\n&nbsp;\r\nIată mesajul organizatorilor:\r\n\r\n&nbsp;\r\n_Business Club te invită în perioada 19-23 Aprilie să participi la proiectul Think Online. Într-un moment critic al economiei, domeniul afacerilor pe Internet devine unul din ce în ce mai atrăgător pentru antreprenori. Think Online, cel mai nou proiect marca Business Club, este o şcoală de antreprenoriat care va pregăti un număr de studenţi pentru a îşi deschide o afacere on-line. Ne adresăm studenţilor sau masteranzilor care sunt interesaţi de domeniul acesta, care şi-au deschis o afacere/site sau care au de gând să facă acest lucru în viitorul apropriat. Studii de caz, workshop-uri, simulări de management, networking şi un concurs inedit de idei, totul într-o atmosferă plăcută şi optimă pentru a genera idei de succes. Proiectul va avea loc la Bucharest Hubb, primul club de work&fun din România dedicat antreprenorilor online._\r\n\r\n_Participând la eveniment, vei avea ocazia să întâlneşti oameni interesaţi de afaceri online, să îţi formezi o echipă şi să creezi un plan de afaceri sub îndrumarea celor mai de succes antreprenori. Vei cunoaşte investitori, vei face networking, vei învăţa de la oameni care au o experienţă bogată în start-up-uri. Vei invăţa cum să prezinţi un pitch unui investitor şi vei primi feedback. Dar, cel mai important, dacă planul de afaceri pe care îl vei dezvolta în cadrul proiectului va fi unul atractiv, vei avea ocazia să primeşti finanţare de la un investitor important._\r\n\r\n_Şi nu uita, la sfârşitul proiectului, după aproximativ o lună, cei mai buni participanţi vor avea ocazia să participe la un teambuilding alături de o parte din speakerii evenimentului pentru a îi cunoaşte mai bine, a îşi prezenta ideile şi a lega eventuale colaborări._\r\n\r\n_La proiect, vei avea ocazia să îi cunoşti pe Vlad Stan (SeedMoney), Sergiu Biriş (Trilulilu), Vladimir Oane (UberVU), George Lemnaru (Erepublik), Daniel Enache (Investitor), Marius Deak (GreenPixel) şi mulţi alţii!_\r\n\r\n_Pentru a aplica la proiect accesează site-ul \'www.thinkonline.ro\':http://thinkonline.ro/ ._',3065,'protected',4784,NULL),('arhiva','Arhiva de probleme','2006-11-11 18:59:35','2010-03-24 19:20:28','h1. Arhiva de probleme\r\n\r\nArhiva de probleme infoarena contine peste 1000 de probleme. Vezi si \'clasamentul arhivei\':clasament-arhiva.\r\n\r\nh2. Lista de probleme\r\n\r\n==Tasks(round_id=\"arhiva\" show_numbers=\"true\" score=\"1\" show_ratings=\"true\" show_progress=\"true\") ==\r\n\r\nh2. Ultimele discutii despre arhiva\r\n\r\n== SmfTopics(board_id=\"1\" count=\"30\") ==\r\n',3146,'protected',NULL,NULL),('runda/concurs.info','concurs.info','2010-04-20 17:33:28','2010-04-20 17:33:28','h1. == roundparam(round_id=\"concurs.info\" param=\"title\") ==\r\n\r\n== roundregister(round_id=\"concurs.info\") ==\r\n\r\nConcursul incepe ==roundparam(round_id=\"concurs.info\" param=\"start_time\" strong=\"true\")== si dureaza ==roundparam(round_id=\"concurs.info\" param=\"duration\" strong=\"true\")== ore.\r\n\r\n== RoundTimer(round_id=\"concurs.info\" units=\"2\") ==\r\n\r\nDupa ce se termina runda, vei putea \'*vedea clasamentul*\':runda/concurs.info/clasament.\r\n\r\nh2. Probleme\r\n\r\nAceasta lista va deveni vizibila doar in momentul inceperii concursului.\r\n\r\n==Tasks(round_id=\"concurs.info\" score=\"1\")==',10701,'round: concurs.info',NULL,NULL),('utilizator/mathboy','Dragos','2008-12-24 18:43:37','2010-04-23 19:00:47','h2. Despre mine\r\n \r\n\r\n* Elev in clasa a X-a la Colegiul National \"Unirea\" Focsani.\r\n* Lucrez pe Infoarena din Ianuarie 2009.\r\n \r\n\r\n\r\nh2. Distinctii primite\r\n\r\n\r\n* The site could be temporarily unavailable or too busy. Try again in a few moments.\r\n\r\nh2. Prieteni pe infoarena\r\n \r\n\r\n* ==user(user=\"cosmin79\" type=\"tiny\")==\r\n* ==user(user=\"bogdanhm999\" type=\"tiny\")==\r\n* ==user(user=\"klamathix\" type=\"tiny\")== \r\n* ==user(user=\"Florian\" type=\"tiny\")==\r\n* ==user(user=\"Omega91\" type=\"tiny\")== \r\n* ==user(user=\"Protoman\" type=\"tiny\")==\r\n* ==user(user=\"blasterz\" type=\"tiny\")==\r\n* ==user(user=\"mishu91\" type=\"tiny\")==\r\n* ==user(user=\"robytzza\" type=\"tiny\")==\r\n* ==user(user=\"doru.nitu\" type=\"tiny\")==\r\n* ==user(user=\"stef2n\" type=\"tiny\")==\r\n \r\n',9232,'public',NULL,NULL),('template/userinfo','template/userinfo','2006-11-12 18:39:53','2008-12-08 20:38:36','table(compact). |=/5. !utilizator/%user%?avatar 150x150!:/utilizator/%user%?action=download&file=avatar \r\n{\'Vezi solutiile trimise\':monitor?user=%user%}\r\n|_. Nume | == userinfo(user=\"%user%\" info=\"fullname\")== |\r\n| |_. Cont | ==userinfo(user=\"%user%\" info=\"username\")== |\r\n| |_. Rating | ==userinfo(user=\"%user%\" info=\"rating\")== |\r\n| |_. Statut | ==userinfo(user=\"%user%\" info=\"security\")== |\r\n|_. Forum | ==SmfLink(user=\"%user%\" link=\"pm\" caption=\"trimite mesaj privat\")==, ==SmfLink(user=\"%user%\" link=\"stats\" caption=\"vezi activitate\")== |\r\n\r\n\r\n',1490,'protected',NULL,NULL);
 /*!40000 ALTER TABLE `ia_textblock_revision` ENABLE KEYS */;
 UNLOCK TABLES;
 
@@ -1782,7 +1782,7 @@
 
 LOCK TABLES `ia_user` WRITE;
 /*!40000 ALTER TABLE `ia_user` DISABLE KEYS */;
-INSERT INTO `ia_user` VALUES (1,'domino','6bd0a33ee98c8bf6aed56c6fe710002bde6048b3','domino@example.com','Mircea Pasoi','admin',1,'2036.6064'),(13,'wickedman','63e05201f16771dd6d4694b502a4fb0dbdac0780','wickedman@example.com','Cristian George Strat','admin',1,'1731.1097'),(15,'silviug','9678b7723d81d9a0eab85832847123c6cfc0dda4','silviug@example.com','Silviu-Ionut Ganceanu','admin',1,'1873.1202'),(18,'azotlichid','c2e30bcb9a5615e5934d178c6fd7ebc15ac54006','azotlichid@example.com','Adrian Vladu','admin',1,'1887.1645'),(21,'ste_fanus','3622116a73d425b915f5922435acc25654c451be','ste_fanus@example.com','Gheorghe Stefan','helper',1,'1383.7172'),(35,'koosy','7c031f9e05db9e7fdc85707b3a09c559745cb1ee','koosy@example.com','Koosy','normal',0,'0.0000'),(48,'danielp','da35f7052906a790a80177483e34a86f358fa609','danielp@example.com','Daniel Pasaila','admin',1,'1603.8967'),(58,'Cosmin','95ddb1caf1d978e1cce9074bb1affbea2dcb7421','Cosmin@example.com','Cosmin Negruseri','admin',1,'1482.8149'),(66,'greco','aaf53667e069463f8c21f09642e068e526cad665','greco@example.com','Tiberiu-Lucian Florea','admin',1,'1868.2372'),(75,'svalentin','dfdfb51287c0b7472c0c501394f0440f9dcf14c9','svalentin@example.com','Valentin Stanciu - UPB','admin',1,'1783.7554'),(83,'efer','f831d7a53887b6b1df443a8394298512b5473e90','efer@example.com','Liviu Ciortea','helper',1,'1918.5149'),(165,'oanam','d9d932e1a8a63fdf873a129e58c7aace82c49072','oanam@example.com','Mihai Oana','normal',1,'0.0000'),(192,'florinr1','229f7c1cfe7fe285a41aab496a862d54164e2997','florinr1@example.com','florin racila','normal',1,'0.0000'),(256,'filipb','811bbf59e81ca6425274da0ef63e29dffd48d9a1','filipb@example.com','Filip Cristian Buruiana UPB','admin',1,'2014.8695'),(272,'mars','0bbd71555a7e3e5c2d777281ac999ecc759d1eeb','mars@example.com','Marius Andrei','normal',0,'0.0000'),(354,'amadaeus','3586acf9cf25ded897d9aadf0855feab8592f462','amadaeus@example.com','Lucian Boca','helper',1,'1437.0539'),(468,'mugurelionut','e2c649f0bdfacfb8ff945c4a78f70ee61687e31e','mugurelionut@example.com','Mugurel Ionut Andreica','helper',1,'2599.2627'),(477,'rus','94086a103570c65d9b2b158aa92e711df1f58dfa','rus@example.com','Rus Sergiu','normal',1,'1502.6747'),(530,'miZ','535b5c08cf6e5aa9db329233a5193d787ea98e84','miZ@example.com','Micu Florin','normal',1,'1439.2834'),(547,'vasile_gales','daf16591af759f9ef96bc4b677bbfe3a7ee875ca','vasile_gales@example.com','Gales Vasile','normal',1,'0.0000'),(621,'Dark_Raxvan','2ca59770edc525bfda7c72c016667a0b174ce25e','Dark_Raxvan@example.com','raxvan oprea','normal',1,'1531.3996'),(716,'alexthero','8bf4a0ca7f0b84427894f3b90e6786b6fef376c7','alexthero@example.com','Tandrau Alexandru','admin',1,'2174.2484'),(730,'sssilviu','f1b3662b501e6c32b471365037388a45ce32cc7d','sssilviu@example.com','straliciuc silviu','normal',1,'0.0000'),(735,'gogu','4a87b47b961aeea7a19349350cb40c13b688d95d','gogu@example.com','Gogu Marian','helper',1,'1656.9626'),(866,'MASTER','fc51178eb39740810f9642b24fb541ab10bf36a9','MASTER@example.com','lUCA CRISTIAN','normal',1,'0.0000'),(961,'DITzoneC','bd0c869fdf51f004a547ad0a1a002be83c677b52','DITzoneC@example.com','Adrian Diaconu','admin',1,'1786.4994'),(965,'filosofie12','f2f905c448c706acc1e0c580629cc3e365e1afd9','filosofie12@example.com','Dorneanu','normal',1,'0.0000'),(999,'chiru_ramona','24c664f061b3f51b961094450aa00902ec9fe709','chiru_ramona@example.com','Chiru Ramona','normal',1,'0.0000'),(1002,'cos_min','315b43c450406cd055cb98a12a355433648c804c','cos_min@example.com','Bondane Cosmin','helper',1,'1585.3991'),(1024,'Tabara','9639c299c429eaeb1c3df24e38690246aec5ca04','Tabara@example.com','Tabara Mihai','helper',1,'1348.4326'),(1072,'tm_radu','a44856f0bd0907c5425d9f120b5d3e25c2ac6e21','tm_radu@example.com','Toma Radu','helper',1,'1635.1574'),(1142,'fluffy','7b1045aac728fec00a86a68aba993d6d85a74529','fluffy@example.com','Dan-Leonard Crestez','admin',0,'1624.4926'),(1204,'blasterz','99c18f05be18480f7763c373d2bf1618a03c6882','blasterz@example.com','Mircea Dima','helper',1,'1874.9923'),(1231,'fireatmyself','cf86af8a0a30f5e088b37e4903f5b45f06d1c34f','fireatmyself@example.com','Bogdan A. Stoica','helper',0,'1609.0507'),(1277,'fucker','6c7b36cd576ec9b8bdd3085dba175ea9c02cb4a6','fucker@example.com','euu','normal',1,'0.0000'),(1323,'Deni','12a0e3d3f30254e0e68dcb359fa597c60215de12','Deni@example.com','Bica Denisa','normal',1,'0.0000'),(1430,'CezarMocan','f6e653a8929eb4c24eb8d6a47326ff4e3f9fc61a','CezarMocan@example.com','Cezar Mocan','helper',1,'2592.3533'),(1452,'rake','fcd0eb35de617a413cdf2902cbdd8195bd875ff3','rake@example.com','Popa Tudor Iulian','normal',1,'0.0000'),(1490,'bogdan2412','502a034d392375d878a486dd851084462a9e6273','bogdan2412@example.com','Bogdan-Cristian Tataroiu','admin',1,'3484.6106'),(1654,'bianca_ig','ca982f853d8c4f43892743903daf82f0907f9a0d','bianca_ig@example.com','bianca ignat','normal',1,'0.0000'),(1792,'pauldb','41dc2ea737a312def66bc07c8f75a2448c1d288f','pauldb@example.com','Paul-Dan Baltescu','admin',1,'2377.8118'),(1851,'victorsb','4f6c786b29acccb5052902481fa24cccd4c9635c','victorsb@example.com','Victor Rusu','admin',1,'2519.1289'),(1900,'BlitzKrieg','f17b8587bbe4da49042348db1c95edc2ca541eb4','BlitzKrieg@example.com','Victor Popescu','normal',1,'0.0000'),(1944,'geo88','f55140815c163b9241f99e2d408125617f87cc43','geo88@example.com','george arion','normal',1,'1464.4113'),(2028,'wefgef','0245bd4df4bca0ce6bf2ef6ee7c594a9ab415182','wefgef@example.com','Andrei Grigorean','admin',1,'2349.7608'),(2038,'gcosmin','bb4b40f220ae2f69cb0db74a0622c94039448c60','gcosmin@example.com','Gheorghe Cosmin','admin',1,'3424.5009'),(2044,'stef2n','6750b2965c97de05c5dac1328ac45045d425361f','stef2n@example.com','Stefan Istrate','admin',1,'1933.8797'),(2092,'astronomy','b796ebf62bc3cfea237ef0eb21e77051f436f3bb','astronomy@example.com','Airinei Adrian','admin',1,'2099.8281'),(2126,'martinica1','b75566b0aed418c90a2ffaeac531708d242137cf','martinica1@example.com','ionblagu','normal',0,'0.0000'),(2291,'uniquee','3c29eb2296eaa71ab155e1db7e9c302e379cb453','uniquee@example.com','Pacurar Alexandru','normal',1,'0.0000'),(2324,'stancosti','66e8ca8a628afa6998552b1e7e8fef9d3d232f4b','stancosti@example.com','costi stan','normal',1,'0.0000'),(2328,'elutza','5234d966a6f635370244e21f87801913c7f396cb','elutza@example.com','tetcu liana mihaela','normal',1,'0.0000'),(2421,'C1506','a2627f822db462cb71f2df0f388fe5d8272cca18','C1506@example.com','Blidisel Alin','normal',1,'0.0000'),(2676,'paula','093fea29edb166fc685e6e072d295d15b429c20e','paula@example.com','muresan gabriela','normal',1,'0.0000'),(2766,'con_lena','df3500baea05ebcbe0f9aeab40ca9d64a17675fa','con_lena@example.com','constantin elena','normal',1,'0.0000'),(2773,'abcd','e0378e12d7ac5f9af37052d8763be4f3e8d13041','abcd@example.com','Giurgea Anca','normal',1,'0.0000'),(2842,'colt2005','d07667a4169dc7e34e744959012567b89266e742','colt2005@example.com','chitic stefan','normal',1,'0.0000'),(2934,'tudalex','f68d244814d2f5cbf1db4cf55a6b142d097d40c8','tudalex@example.com','Tudorica Constantin Alexandru','helper',1,'1756.5474'),(2970,'Prostu','0a140d6d788cb7a2b30e6d7bd9dad0eadff03d6f','Prostu@example.com','Filip Stefan A.','admin',1,'1952.3272'),(2993,'devilkind','50a65e44c032a717ae567563130a47342095c611','devilkind@example.com','Savin Tiberiu','admin',1,'2025.7046'),(3065,'judy_k','5db219b80356b3ca6359f92bd3e33e85d9229182','judy_k@example.com','Cristina Petrovici','admin',1,'1591.1665'),(3066,'Diana_C','14a03f48222a2173dba8cca3e1cdd7f649d0e4a8','Diana_C@example.com','Ciocea Diana Cristina','normal',1,'1371.8741'),(3086,'zait','1b0c6fdf525f50904551852a2858cefe04a2cca1','zait@example.com','paul filimon','normal',1,'0.0000'),(3134,'marius_Dumitran','5d731b387fb78b7859af5f27f98b513bcf6e463e','marius_Dumitran@example.com','Marius Dumitran','normal',1,'0.0000'),(3146,'Marius','5568ecf604d7f90895ed6e8affb4f7adfe64ca97','Marius@example.com','Marius Stroe','admin',1,'1881.7103'),(3166,'exist3nz','4c4d0c3824b7a58458cf1397b05327e5aaa88820','exist3nz@example.com','Ionescu Cristina','normal',1,'0.0000'),(3174,'claustan','0b8d1588b480e874a2214e0eb85dcd86eba331d4','claustan@example.com','Stan Claudiu','normal',0,'0.0000'),(3219,'mariusdrg','d427d5a94f0100d55972f908565782fe91edfcb5','mariusdrg@example.com','dragus marius','helper',1,'2259.1055'),(3270,'sima_cotizo','234d80ce23b6abecf9d0c20e8eebe7da6356d63d','sima_cotizo@example.com','Sima Cotizo','helper',1,'1915.1310'),(3434,'inkriptor_scn','8ad8a27931c9f44275f5f95b8f00ee7210544bf4','inkriptor_scn@example.com','maran tiberiu','normal',1,'0.0000'),(3545,'cezar305','3cbf27c81af14c79fb60124bdc3528566e3ab21b','cezar305@example.com','.com 2009','helper',1,'1688.8302'),(3604,'Chici','3d32226afbef251504acc8c8fb42d3bb4a3fe600','Chici@example.com','Han Bogos Adamita','normal',1,'0.0000'),(3680,'marcelcodrea','3d1021b12ac29a3659f065711feb2c0505fed023','marcelcodrea@example.com','Codrea Marcel','normal',1,'1476.2660'),(3726,'lilix0202','7ee8a275b96b49b554a89577a88133d9c4754261','lilix0202@example.com','nesu liliana','normal',1,'0.0000'),(3739,'laiurita88','03616513e0a3574b164c8a13e00673f82484045d','laiurita88@example.com','laura','normal',1,'0.0000'),(3740,'lupu','b9a1c42de0d4b32e352660b9ee55117d1943e4b5','lupu@example.com','lupulescu','normal',1,'0.0000'),(3851,'mfuqm31','7da5d690d4df7d931a14e2d960da3d780bd300cc','mfuqm31@example.com','Mitarca Mihai','normal',1,'0.0000'),(3997,'raduzer','775fe49c1e6a614be5597dcfe0e8f5cbea239978','raduzer@example.com','Radu Zernoveanu','helper',1,'2119.5079'),(4032,'danutzul_05','80efe069545b56e83a633f1fb3215c5f56c4b6e9','danutzul_05@example.com','vicol daniel-ionut','normal',1,'0.0000'),(4057,'tmir','3853df7a2732206a606ff50400a3f3bfca168c7d','tmir@example.com','nam','normal',1,'0.0000'),(4118,'Ioana_bomboana','65f64a63156100f3d6a4fe8e655e5d429d946bca','Ioana_bomboana@example.com','Popescu Ioana','normal',0,'0.0000'),(4184,'bianca_bya','c2543b05b39660ea5e0d8942604dfd8a43b4e397','bianca_bya@example.com','boeriu bianca','normal',1,'0.0000'),(4304,'andras','68f52bf8ce39bbcca1b4cc75fec66bced04b0aca','andras@example.com','Halalai Tudor Andrei','normal',0,'0.0000'),(4327,'IcemaN_ro','a86f4a79e36d5da244ac0f4da2ed31cb274a3103','IcemaN_ro@example.com','Alex Moldovan','normal',0,'0.0000'),(4414,'bc_costy','834a817e64d8d9674c76f4c25bca162214fc77f3','bc_costy@example.com','Blindu Constantin','normal',0,'0.0000'),(4439,'crawler','97f43e6f2819685e6e98aa38f29f7aced84f5cfb','crawler@example.com','Puni Andrei Paul','helper',1,'1905.2500'),(4484,'vic_and','45bccb08e9c96f1f1a8b24075a82091f5b000c95','vic_and@example.com','Victor Andrei','normal',1,'0.0000'),(4516,'Alexus','b184946119b11a9af04fb50b7a08ce96d66a4dbb','Alexus@example.com','Stoica Alexandru','normal',1,'0.0000'),(4550,'claudia','c37f4d9d68d19869f97921ed28bb83c2bb873183','claudia@example.com','Simon Claudia Mihaela','normal',1,'0.0000'),(4603,'Dastas','9a2d2412661e555626ae21142b17706acd3d85a6','Dastas@example.com','Ionescu Vlad','helper',1,'1536.8628'),(4635,'nirvanablue25','c939433eeb276fc38604e442b628dd1f6d7d8bab','nirvanablue25@example.com','rosoiu cristina mihaela','normal',0,'0.0000'),(4655,'onu_flo','568df585fe71aac584f29fc87eea1ff73a3fcc9c','onu_flo@example.com','Pirvu Ionelia','normal',1,'0.0000'),(4699,'manu_deutza','00236c908b681930e15067c0267c57f5f57ea77f','manu_deutza@example.com','cojocaru andreea','normal',1,'0.0000'),(4823,'cocoru','983614aa65064093aab7a84c3b9d96b477851e9d','cocoru@example.com','agarici','normal',0,'0.0000'),(4827,'savim','da9e6f0eff30aaa361b619b870c0b9faa3d42edf','savim@example.com','Serban Andrei Stan','helper',1,'2478.2683'),(4860,'lemne','999d42e0b834887e1d239e793c30538ef814c648','lemne@example.com','Lemne Lemne','normal',1,'1490.6963'),(4905,'xanthe','f36a84999ece82cc1f76d44bc38a8acafc8a1f87','xanthe@example.com','Teodora','normal',1,'0.0000'),(4920,'mlegs','4090c05e00e6914c0e66f8cce9a5999891b3490e','mlegs@example.com','nec','normal',0,'0.0000'),(5054,'root','33a485cb146e1153c69b588c671ab474f2e5b800','root@example.com','/boot/vmlinuz','normal',0,'1496.2275'),(5247,'ankutsa','bcbacf1bb317e73f1f149e56061f783295664718','ankutsa@example.com','Lasc Anca','normal',1,'0.0000'),(5274,'AndreiDumi','fe86a8eef0b11608cfbdf38ade3dc6f5cb9a2d9a','AndreiDumi@example.com','Andrei','normal',0,'0.0000'),(5364,'Dany_perfect','d51f6ee42a9f638a22e443dca72844d5b14e2815','Dany_perfect@example.com','Moldoveanu Daniel-Stefan','normal',1,'0.0000'),(5382,'ge_ronimo17','2119b9f4d33de86012b9baeee17fa886f4b9ac7c','ge_ronimo17@example.com','george ionutz','normal',1,'0.0000'),(5392,'eval','99f84d9f2e99cba220e37d9e293f295da6e5c3f4','eval@example.com','Evaluatorul infoarena','admin',0,'0.0000'),(5420,'armasanea','838c875337361dc5f9acc4d1630cbf59ebf49e92','armasanea@example.com','Sanea Prodan','normal',0,'0.0000'),(5484,'kana','3fd4b994292b78fc431bb0e216c2ec1706b19803','kana@example.com','Preda Mihai','normal',1,'0.0000'),(5536,'kezman','9d07edd26624176d3b8dea8354350c0ece476fb1','kezman@example.com','adrian','normal',1,'0.0000'),(5628,'fish','c0dd43cd1855a421dcfc03644ab1c50d6d0424db','fish@example.com','bogdan negrila','normal',1,'0.0000'),(5653,'floringh06','cd71e4a11e8a3ea4472485c775e484a229d37c5e','floringh06@example.com','Florin - Cristian Ghesu','helper',1,'1805.6253'),(5659,'cavin','0f4a9d7c5dd2e2b6420097dc3b2f1c207f016e75','cavin@example.com','Gosman Catalin','normal',0,'0.0000'),(5723,'razvan_varnita','d6184148615b2a64ad228dd52a88c5343afbcc89','razvan_varnita@example.com','dragomir razvan','normal',1,'0.0000'),(5748,'Florian','321cf8f0b3166041d167aa30bb112180fbc28b7a','Florian@example.com','Marcu Florian','helper',1,'1853.8789'),(6061,'toni2007','621a55b6f1da52ee5809a53cce92ace3847632ec','toni2007@example.com','Pripoae Teodor Anton','helper',1,'2007.8867'),(6112,'reSpawn','e58eb6300925f62b67ad8fc27c02824d4269784a','reSpawn@example.com','Rosia Nicolae','normal',1,'0.0000'),(6172,'gabitzish1','a832fc848ecf51556b1d9fd31279c5f35341200b','gabitzish1@example.com','Gabriel Bitis','helper',1,'1973.8593'),(6195,'nistaman','1e31816150493a262ace01243e854c5d55c1fbbf','nistaman@example.com','Bogdan Komen','normal',1,'0.0000'),(6217,'Nebhotep','06a1a04fcd17c0b07a1f39ff4eb28eb5a866d3aa','Nebhotep@example.com','Metes Alexandru','normal',0,'0.0000'),(6224,'ln_anila','ef27061cef8a23e8ce81ac6c53fd0f79d4a073bd','ln_anila@example.com','Alina Nitu','normal',1,'0.0000'),(6306,'lebappe','e430f6209550892dbbc3aa0d441a394a68b06b96','lebappe@example.com','Bogdan Popa','normal',0,'0.0000'),(6333,'Mishu91','e5f53468610c31c7f4549b0f3a4e1e05a8dbfac6','Mishu91@example.com','Andrei Misarca','helper',1,'1943.1396'),(6421,'cristi_c','13ab03f0f890e7057ea125e07714b95d6ae40bc9','cristi_c@example.com','Chirac Cristian','normal',1,'0.0000'),(6443,'ada_s','b550dafed22cb780059a3679bf31db5ad387d9b7','ada_s@example.com','Ada-Mihaela Solcan','normal',1,'1724.6918'),(6483,'danciac','cc693af8be52ba184ae0652b87dea4b16a712693','danciac@example.com','Cracan Dan','normal',1,'1447.4701'),(6569,'hardvirus','4bc045de6294ff37e35b2203076b01e6ed4b4d19','hardvirus@example.com','Ardelean Horia','normal',1,'1455.4066'),(6694,'alexandru.mosoi','f4a5a1b6904da106c3166cdbd68cd3ad58a5ba32','alexandru.mosoi@example.com','Alexandru Mosoi','helper',0,'1795.0480'),(6728,'marsamg','fa58f34a947a006629cbbff3a97da9e967c22818','marsamg@example.com','Marius Andrei','normal',0,'0.0000'),(6760,'100puncte','c60ed642c05f833d7d6dedbfd2e305e119af01af','100puncte@example.com','Ionut Popa','normal',1,'0.0000'),(6800,'GavrilaVlad','c30cd987e7a86566146af8bf13ff0c79468ad6a6','GavrilaVlad@example.com','Gavrila Vlad','helper',1,'2841.2081'),(6867,'unubou','d9de0cd9da371ee646517699c78f1d33b79f9ab8','unubou@example.com','Isac Razvan Alexandru','normal',0,'0.0000'),(6874,'kaya','2f91874fe8105df9519fac90ee525314efa6a519','kaya@example.com','Marina Mihailescu','normal',1,'0.0000'),(7012,'gabi_bobocel','92a168802fae6aade88c7c6585f0ac79e94c7922','gabi_bobocel@example.com','Boboc Costin Gabriel','normal',1,'0.0000'),(7023,'COstel','40be77057e797da09f2067c7ae7be368f69f9284','COstel@example.com','Petrea Constantin','normal',1,'0.0000'),(7100,'corinabolfa','15e9b87bef3a054dd82e533e0531436bd0b581cd','corinabolfa@example.com','bolfa corina','normal',0,'0.0000'),(7116,'paulrusu','a32d9703ad2cfffe8be751d4e80eda2f03c2de97','paulrusu@example.com','paul rusu','normal',0,'0.0000'),(7146,'roxyshor','d2878f85428d7427406150f4b570b7541eb94bef','roxyshor@example.com','Leonte Roxana','normal',1,'0.0000'),(7148,'GheorgheMihai','0ad371d724545ea4dc4e865f950846844e7c7c53','GheorgheMihai@example.com','Gheorghe Mihai','helper',1,'2320.7556'),(7271,'andrei-alpha','fbb177aae061688fbcc8bfe0e4d6c7d739b25aee','andrei-alpha@example.com','Andrei-Bogdan Antonescu','helper',0,'2100.6330'),(7280,'DanielG','d606ee4e75fceba83f8d6793c19f27a8ff7eeba4','DanielG@example.com','Glodeanu Ioan Daniel','normal',1,'1473.1429'),(7290,'login','a12c2ca48c890306edbe99637ad2c62195edabb1','login@example.com','Anca Login','normal',1,'1674.9230'),(7320,'123456789','3175de158db24c987b7ced3bf65d46c1fcfb3c5f','123456789@example.com','ghita gheorghita','normal',0,'0.0000'),(7333,'cosser','6a0ca20a9b887058821f2f57f1d4d378b0e15107','cosser@example.com','Bula Ionut','normal',1,'1428.7856'),(7395,'BigMazilu','33292d8b3415e02363e365267a3b865616bcd6d0','BigMazilu@example.com','Mazilu Victor','normal',1,'1405.9269'),(7424,'ruxandra_enus','0e52889b5505e7fa7be545d01f821dd6d5dcb085','ruxandra_enus@example.com','ruxandra enus','normal',1,'0.0000'),(7448,'radoo','15362d1446de569734aaf038ba3367a22e74637f','radoo@example.com','Miron Radu Emanuel','normal',1,'0.0000'),(7668,'andrici_cezar','cf2d97908f0e321da3b95d650a98d150a9923b9b','andrici_cezar@example.com','Andrici Cezar','helper',0,'1374.2246'),(7732,'petro','0d33b789ef661e7bb834127c987fa3e5ab20f8d5','petro@example.com','Milut Petronela','normal',0,'0.0000'),(7820,'shmecheru','52b97657e7d5e2f13341263caf0c5887947985f9','shmecheru@example.com','Shmecheru','normal',1,'0.0000'),(7841,'darkdude','b24005dd227f3e9e0752522204855940b4399534','darkdude@example.com','Andrei Barsan','normal',1,'0.0000'),(7905,'1gnition','128c3fa831fd5d8cdd668819fb527a7ec50f809a','1gnition@example.com','Strambu George','normal',1,'0.0000'),(7954,'chryss13','7a5e23a60f47e906f300220ac91d69fe3a2ba32f','chryss13@example.com','cristina','normal',1,'0.0000'),(8027,'stocarul','82e18cdc5a097c42077618756441f74a84923809','stocarul@example.com','Cosmin Mihai Tutunaru','helper',1,'1946.8209'),(8118,'andreiparau','4e93e748d7c464196802ba7f926ad4d58dedcb49','andreiparau@example.com','Andrei Parau','normal',1,'1424.8278'),(8131,'Leka','4a50c6898738ef0f180f41626db50bbc9d5ecf3b','Leka@example.com','Pascu Alexandra','normal',0,'0.0000'),(8181,'stelistul','8660b97240b081ee83613b1a0c12594f23314a3b','stelistul@example.com','Bora Calin','normal',1,'1402.2290'),(8201,'Torque','552b96247f8493d1cb090a61c8886c60d1991de9','Torque@example.com','Paducel Vladut Emil','normal',1,'0.0000'),(8260,'cata00','ce60b3655f53a236ff1ea89aacd312fb4a17df1f','cata00@example.com','Catalin Francu','helper',0,'0.0000'),(8299,'dexterelu','4504f99dfafd5a1f0646d04c592362fa3f121463','dexterelu@example.com','Paul Raetchi','normal',1,'1428.1173'),(8461,'upb_sdv','25adbf3092e901992eeae04246fc249968b75c61','upb_sdv@example.com','Gravity','normal',0,'1653.0030'),(9493,'AlexandruB','c9d1722589c775c41e155532d5432795247a2b88','AlexandruB@example.com','Bordea Alexandru','normal',0,'0.0000'),(8515,'cristi.oprea','fbdcfe6d36c4a5050924fcb312db126b03be8bd6','cristi.oprea@example.com','oprea cristi','normal',1,'0.0000'),(8637,'lorincziisti','b1e9445fb1222c08207ee991aa29cc2041f30ba9','lorincziisti@example.com','Lorinczi Istvan','normal',1,'0.0000'),(8690,'motty','58208a97c63a99a24cd7dde25e9582d776108dbf','motty@example.com','Matei-Dan Epure','helper',1,'1655.7695'),(8784,'monocrom133','d1a5d6940189817f2a74cfdcb1c10e96f6a2cd1a','monocrom133@example.com','andreea raluca turcu','normal',0,'0.0000'),(8808,'dragosldf','e2e4a82e1fab10e648f0e38eb72128a4292cd309','dragosldf@example.com','lazar dragos','normal',1,'0.0000'),(9137,'mjoska','8c09006a91113a9dd97183ee6c548105dd1ce522','mjoska@example.com','Miklos Jozsef','normal',1,'0.0000'),(9161,'FlorinOv','f2b9a76834c716253c842439f0a1a504f59bb734','FlorinOv@example.com','florin','normal',1,'0.0000'),(9232,'mathboy','beaa1c3d7b3705d3fda0f91df952d8582ec94b75','mathboy@example.com','Dragos-Alin Rotaru','helper',1,'1576.8410'),(9356,'miculprogramator','b3e87bcb19c906e85e934d7f77acc157b2916293','miculprogramator@example.com','ALbulescu Cosmina','helper',1,'1582.6835'),(9454,'oana_enusoiu','81c1689411c90ae9205dba7a35c61dbb6aec9d32','oana_enusoiu@example.com','oana enusoiu','normal',1,'0.0000'),(9503,'metalkitten','3964e69d383e24b8549a3aca7424228b87c11a5c','metalkitten@example.com','Georgiana Arhip','normal',1,'1376.7938'),(9597,'SergiuC','b5f1121fb6d026f8063ecd9a3bb51ef0b1541e7c','SergiuC@example.com','Corneanu Sergiu','normal',1,'0.0000'),(9739,'zerobarat','cfcae2b48dcc797a9dbe58cbec465bb17ce22e3d','zerobarat@example.com','alexandra','normal',1,'0.0000'),(9830,'v_vero_93','a3af29b10f55b85246b4a8c41be35bec455e95c8','v_vero_93@example.com','Velciu Veronica Mihaela','normal',0,'1439.1888'),(9891,'GMF92','ed80bd077629ae0ef847c1e13b91c74a38a9ade1','GMF92@example.com','numele meu','normal',0,'0.0000'),(10091,'pufuleti_sange','987feb6b67df74fa21c5317f7913225e0968ae25','pufuleti_sange@example.com','pufuleica sange bors','normal',1,'0.0000'),(10147,'pcinfo','0ddd510b2c62570a1fa0e2a4a32aeb6b3ebe3acc','pcinfo@example.com','Carmen Popescu','helper',1,'1322.0659'),(10300,'Sergiu_92','b1de5bb378237d37cec06a31ee6feb59c384cef9','Sergiu_92@example.com','Sergiu Savin','normal',1,'0.0000'),(10547,'thesvcoolman','620aa74ecf32743442e2ab93ded6fbee200b52e7','thesvcoolman@example.com','Lucian Bicsi','normal',0,'1103.9891'),(10730,'andreii_93','853cbb0bfb2ad7236dcd9dccff86dba4541363ea','andreii_93@example.com','andrei ion','normal',1,'0.0000'),(10783,'BringitON','d47695c76fcf2ee4b2b9a9c5f374af5cda9368c7','BringitON@example.com','Breban Andrei','normal',0,'0.0000'),(10888,'Andrei29','8fbd8a0c533044d1dc95be02839ecf69cfb1f876','Andrei29@example.com','Andrei Paduraru','normal',0,'0.0000'),(11024,'leva','e05d06dc7bb6d0f8c69c0f0c7520478f0686542d','leva@example.com','Leva Ionut','normal',0,'0.0000'),(11046,'maoo','c9b9afb8b7cff6be3603edfdbef2afeb8e175458','maoo@example.com','Bompa Mario','normal',0,'0.0000'),(11322,'ionut.pic','c3f7b847bada7b4675f7212fed19e120c6958ebb','ionut.pic@example.com','popa ionut cristian','normal',1,'0.0000'),(11349,'petru000','f43ab6cb7086dc9d1c9d7e02a44c48ac1b8f34e4','petru000@example.com','petru sorin','normal',1,'0.0000'),(11356,'AlecSs','de3e0f7f79025a58e86666f8fda7ff0ea4a4bb72','AlecSs@example.com','Hulpe Alexandru','normal',1,'0.0000'),(11437,'VyperBoy','aad65a6286c65f89b9e1b311830aef6292dfcd31','VyperBoy@example.com','Marin P','normal',0,'0.0000'),(11574,'cristialexandru','1763f7661feb6665cc1888e5c51839010f13d034','cristialexandru@example.com','Cristi Alexandru','normal',1,'0.0000'),(11588,'u2tommyf','c01245a3db435642c2b633027eaf700f4a073f28','u2tommyf@example.com','Toma Florina','normal',1,'0.0000'),(11799,'alexandrul','467f6e577fb3aaf448618aa5446815a63269888c','alexandrul@example.com','Alexandru Mihai','normal',1,'0.0000'),(11819,'verdecrud','d3883703eafccac1260e40c7f9d16ef9d6362d60','verdecrud@example.com','PensiuneaVerdeCrud','normal',0,'0.0000'),(11896,'hexor','303dc13dfd3083a6df451fb884fce363d504b7ed','hexor@example.com','Serban Dragos','normal',0,'0.0000'),(11906,'bogdanelu006','056cbfd58d9b31ab51f5ffff07a8f4748ae92186','bogdanelu006@example.com','bogdan','normal',1,'0.0000'),(12078,'Aleks10','207974a77e61353d2e5e3be9f0e799d723ce8271','Aleks10@example.com','Petrache Alex','normal',0,'0.0000'),(12234,'Mihai-Daniel','7d75d164955f9c0428ce32c1c1f096d4057dfe91','Mihai-Daniel@example.com','Mihai-Daniel','normal',1,'0.0000'),(12452,'SITZ','8ba3d09541382c1200f9b667ece67f6119fc43b1','SITZ@example.com','Sitesh Shrivastava','normal',1,'0.0000'),(12501,'Bogdan.Cirstea','70e3f4cf8afc1f6623d468dc2200b4d11e55067c','Bogdan.Cirstea@example.com','Cirstea Bogdan-Ionut','normal',1,'0.0000'),(12571,'jenniferlmartin','494b1771479e4ce4f0cc6ec2a6910e1c30b62d15','jenniferlmartin@example.com','jennifer martin','normal',1,'0.0000'),(12576,'Andrei1998','aab484e89badc20dcba053ded737bb155a94aa74','Andrei1998@example.com','Constantinescu Andrei Costin','normal',1,'0.0000'),(12602,'IonelaD','e02c5550e542734e5c324a76314c4f04e59e55d3','IonelaD@example.com','Dinica Ionela','normal',1,'0.0000');
+INSERT INTO `ia_user` VALUES (1,'domino','6bd0a33ee98c8bf6aed56c6fe710002bde6048b3','domino@yahoo.com','Mircea Pasoi','admin',1,'2036.6064'),(13,'wickedman','63e05201f16771dd6d4694b502a4fb0dbdac0780','wickedman@example.com','Cristian George Strat','admin',1,'1731.1097'),(15,'silviug','9678b7723d81d9a0eab85832847123c6cfc0dda4','silviug@example.com','Silviu-Ionut Ganceanu','admin',1,'1873.1202'),(18,'azotlichid','c2e30bcb9a5615e5934d178c6fd7ebc15ac54006','azotlichid@example.com','Adrian Vladu','admin',1,'1887.1645'),(21,'ste_fanus','3622116a73d425b915f5922435acc25654c451be','ste_fanus@example.com','Gheorghe Stefan','helper',1,'1383.7172'),(35,'koosy','7c031f9e05db9e7fdc85707b3a09c559745cb1ee','koosy@example.com','Koosy','normal',0,'0.0000'),(48,'danielp','da35f7052906a790a80177483e34a86f358fa609','danielp@example.com','Daniel Pasaila','admin',1,'1603.8967'),(58,'Cosmin','95ddb1caf1d978e1cce9074bb1affbea2dcb7421','Cosmin@example.com','Cosmin Negruseri','admin',1,'1482.8149'),(66,'greco','aaf53667e069463f8c21f09642e068e526cad665','greco@example.com','Tiberiu-Lucian Florea','admin',1,'1868.2372'),(75,'svalentin','dfdfb51287c0b7472c0c501394f0440f9dcf14c9','svalentin@example.com','Valentin Stanciu - UPB','admin',1,'1783.7554'),(83,'efer','f831d7a53887b6b1df443a8394298512b5473e90','efer@example.com','Liviu Ciortea','helper',1,'1918.5149'),(165,'oanam','d9d932e1a8a63fdf873a129e58c7aace82c49072','oanam@example.com','Mihai Oana','normal',1,'0.0000'),(192,'florinr1','229f7c1cfe7fe285a41aab496a862d54164e2997','florinr1@example.com','florin racila','normal',1,'0.0000'),(256,'filipb','811bbf59e81ca6425274da0ef63e29dffd48d9a1','filipb@example.com','Filip Cristian Buruiana UPB','admin',1,'2014.8695'),(272,'mars','0bbd71555a7e3e5c2d777281ac999ecc759d1eeb','mars@example.com','Marius Andrei','normal',0,'0.0000'),(354,'amadaeus','3586acf9cf25ded897d9aadf0855feab8592f462','amadaeus@example.com','Lucian Boca','helper',1,'1437.0539'),(468,'mugurelionut','e2c649f0bdfacfb8ff945c4a78f70ee61687e31e','mugurelionut@example.com','Mugurel Ionut Andreica','helper',1,'2599.2627'),(477,'rus','94086a103570c65d9b2b158aa92e711df1f58dfa','rus@example.com','Rus Sergiu','normal',1,'1502.6747'),(530,'miZ','535b5c08cf6e5aa9db329233a5193d787ea98e84','miZ@example.com','Micu Florin','normal',1,'1439.2834'),(547,'vasile_gales','daf16591af759f9ef96bc4b677bbfe3a7ee875ca','vasile_gales@example.com','Gales Vasile','normal',1,'0.0000'),(621,'Dark_Raxvan','2ca59770edc525bfda7c72c016667a0b174ce25e','Dark_Raxvan@example.com','raxvan oprea','normal',1,'1531.3996'),(716,'alexthero','8bf4a0ca7f0b84427894f3b90e6786b6fef376c7','alexthero@example.com','Tandrau Alexandru','admin',1,'2174.2484'),(730,'sssilviu','f1b3662b501e6c32b471365037388a45ce32cc7d','sssilviu@example.com','straliciuc silviu','normal',1,'0.0000'),(735,'gogu','4a87b47b961aeea7a19349350cb40c13b688d95d','gogu@example.com','Gogu Marian','helper',1,'1656.9626'),(866,'MASTER','fc51178eb39740810f9642b24fb541ab10bf36a9','MASTER@example.com','lUCA CRISTIAN','normal',1,'0.0000'),(961,'DITzoneC','bd0c869fdf51f004a547ad0a1a002be83c677b52','DITzoneC@example.com','Adrian Diaconu','admin',1,'1786.4994'),(965,'filosofie12','f2f905c448c706acc1e0c580629cc3e365e1afd9','filosofie12@example.com','Dorneanu','normal',1,'0.0000'),(999,'chiru_ramona','24c664f061b3f51b961094450aa00902ec9fe709','chiru_ramona@example.com','Chiru Ramona','normal',1,'0.0000'),(1002,'cos_min','315b43c450406cd055cb98a12a355433648c804c','cos_min@example.com','Bondane Cosmin','helper',1,'1585.3991'),(1024,'Tabara','9639c299c429eaeb1c3df24e38690246aec5ca04','Tabara@example.com','Tabara Mihai','helper',1,'1348.4326'),(1072,'tm_radu','a44856f0bd0907c5425d9f120b5d3e25c2ac6e21','tm_radu@example.com','Toma Radu','helper',1,'1635.1574'),(1142,'fluffy','7b1045aac728fec00a86a68aba993d6d85a74529','fluffy@example.com','Dan-Leonard Crestez','admin',0,'1624.4926'),(1204,'blasterz','99c18f05be18480f7763c373d2bf1618a03c6882','blasterz@example.com','Mircea Dima','helper',1,'1874.9923'),(1231,'fireatmyself','cf86af8a0a30f5e088b37e4903f5b45f06d1c34f','fireatmyself@example.com','Bogdan A. Stoica','helper',0,'1609.0507'),(1277,'fucker','6c7b36cd576ec9b8bdd3085dba175ea9c02cb4a6','fucker@example.com','euu','normal',1,'0.0000'),(1323,'Deni','12a0e3d3f30254e0e68dcb359fa597c60215de12','Deni@example.com','Bica Denisa','normal',1,'0.0000'),(1430,'CezarMocan','f6e653a8929eb4c24eb8d6a47326ff4e3f9fc61a','CezarMocan@example.com','Cezar Mocan','helper',1,'2592.3533'),(1452,'rake','fcd0eb35de617a413cdf2902cbdd8195bd875ff3','rake@example.com','Popa Tudor Iulian','normal',1,'0.0000'),(1490,'bogdan2412','502a034d392375d878a486dd851084462a9e6273','bogdan2412@example.com','Bogdan-Cristian Tataroiu','admin',1,'3484.6106'),(1654,'bianca_ig','ca982f853d8c4f43892743903daf82f0907f9a0d','bianca_ig@example.com','bianca ignat','normal',1,'0.0000'),(1792,'pauldb','41dc2ea737a312def66bc07c8f75a2448c1d288f','pauldb@example.com','Paul-Dan Baltescu','admin',1,'2377.8118'),(1851,'victorsb','4f6c786b29acccb5052902481fa24cccd4c9635c','victorsb@example.com','Victor Rusu','admin',1,'2519.1289'),(1900,'BlitzKrieg','f17b8587bbe4da49042348db1c95edc2ca541eb4','BlitzKrieg@example.com','Victor Popescu','normal',1,'0.0000'),(1944,'geo88','f55140815c163b9241f99e2d408125617f87cc43','geo88@example.com','george arion','normal',1,'1464.4113'),(2028,'wefgef','0245bd4df4bca0ce6bf2ef6ee7c594a9ab415182','wefgef@example.com','Andrei Grigorean','admin',1,'2349.7608'),(2038,'gcosmin','bb4b40f220ae2f69cb0db74a0622c94039448c60','gcosmin@example.com','Gheorghe Cosmin','admin',1,'3424.5009'),(2044,'stef2n','6750b2965c97de05c5dac1328ac45045d425361f','stef2n@example.com','Stefan Istrate','admin',1,'1933.8797'),(2092,'astronomy','b796ebf62bc3cfea237ef0eb21e77051f436f3bb','astronomy@example.com','Airinei Adrian','admin',1,'2099.8281'),(2126,'martinica1','b75566b0aed418c90a2ffaeac531708d242137cf','martinica1@example.com','ionblagu','normal',0,'0.0000'),(2291,'uniquee','3c29eb2296eaa71ab155e1db7e9c302e379cb453','uniquee@example.com','Pacurar Alexandru','normal',1,'0.0000'),(2324,'stancosti','66e8ca8a628afa6998552b1e7e8fef9d3d232f4b','stancosti@example.com','costi stan','normal',1,'0.0000'),(2328,'elutza','5234d966a6f635370244e21f87801913c7f396cb','elutza@example.com','tetcu liana mihaela','normal',1,'0.0000'),(2421,'C1506','a2627f822db462cb71f2df0f388fe5d8272cca18','C1506@example.com','Blidisel Alin','normal',1,'0.0000'),(2676,'paula','093fea29edb166fc685e6e072d295d15b429c20e','paula@example.com','muresan gabriela','normal',1,'0.0000'),(2766,'con_lena','df3500baea05ebcbe0f9aeab40ca9d64a17675fa','con_lena@example.com','constantin elena','normal',1,'0.0000'),(2773,'abcd','e0378e12d7ac5f9af37052d8763be4f3e8d13041','abcd@example.com','Giurgea Anca','normal',1,'0.0000'),(2842,'colt2005','d07667a4169dc7e34e744959012567b89266e742','colt2005@example.com','chitic stefan','normal',1,'0.0000'),(2934,'tudalex','f68d244814d2f5cbf1db4cf55a6b142d097d40c8','tudalex@example.com','Tudorica Constantin Alexandru','helper',1,'1756.5474'),(2970,'Prostu','0a140d6d788cb7a2b30e6d7bd9dad0eadff03d6f','Prostu@example.com','Filip Stefan A.','admin',1,'1952.3272'),(2993,'devilkind','50a65e44c032a717ae567563130a47342095c611','devilkind@example.com','Savin Tiberiu','admin',1,'2025.7046'),(3065,'judy_k','5db219b80356b3ca6359f92bd3e33e85d9229182','judy_k@example.com','Cristina Petrovici','admin',1,'1591.1665'),(3066,'Diana_C','14a03f48222a2173dba8cca3e1cdd7f649d0e4a8','Diana_C@example.com','Ciocea Diana Cristina','normal',1,'1371.8741'),(3086,'zait','1b0c6fdf525f50904551852a2858cefe04a2cca1','zait@example.com','paul filimon','normal',1,'0.0000'),(3134,'marius_Dumitran','5d731b387fb78b7859af5f27f98b513bcf6e463e','marius_Dumitran@example.com','Marius Dumitran','normal',1,'0.0000'),(3146,'Marius','5568ecf604d7f90895ed6e8affb4f7adfe64ca97','Marius@example.com','Marius Stroe','admin',1,'1881.7103'),(3166,'exist3nz','4c4d0c3824b7a58458cf1397b05327e5aaa88820','exist3nz@example.com','Ionescu Cristina','normal',1,'0.0000'),(3174,'claustan','0b8d1588b480e874a2214e0eb85dcd86eba331d4','claustan@example.com','Stan Claudiu','normal',0,'0.0000'),(3219,'mariusdrg','d427d5a94f0100d55972f908565782fe91edfcb5','mariusdrg@example.com','dragus marius','helper',1,'2259.1055'),(3270,'sima_cotizo','234d80ce23b6abecf9d0c20e8eebe7da6356d63d','sima_cotizo@example.com','Sima Cotizo','helper',1,'1915.1310'),(3434,'inkriptor_scn','8ad8a27931c9f44275f5f95b8f00ee7210544bf4','inkriptor_scn@example.com','maran tiberiu','normal',1,'0.0000'),(3545,'cezar305','3cbf27c81af14c79fb60124bdc3528566e3ab21b','cezar305@example.com','.com 2009','helper',1,'1688.8302'),(3604,'Chici','3d32226afbef251504acc8c8fb42d3bb4a3fe600','Chici@example.com','Han Bogos Adamita','normal',1,'0.0000'),(3680,'marcelcodrea','3d1021b12ac29a3659f065711feb2c0505fed023','marcelcodrea@example.com','Codrea Marcel','normal',1,'1476.2660'),(3726,'lilix0202','7ee8a275b96b49b554a89577a88133d9c4754261','lilix0202@example.com','nesu liliana','normal',1,'0.0000'),(3739,'laiurita88','03616513e0a3574b164c8a13e00673f82484045d','laiurita88@example.com','laura','normal',1,'0.0000'),(3740,'lupu','b9a1c42de0d4b32e352660b9ee55117d1943e4b5','lupu@example.com','lupulescu','normal',1,'0.0000'),(3851,'mfuqm31','7da5d690d4df7d931a14e2d960da3d780bd300cc','mfuqm31@example.com','Mitarca Mihai','normal',1,'0.0000'),(3997,'raduzer','775fe49c1e6a614be5597dcfe0e8f5cbea239978','raduzer@example.com','Radu Zernoveanu','helper',1,'2119.5079'),(4032,'danutzul_05','80efe069545b56e83a633f1fb3215c5f56c4b6e9','danutzul_05@example.com','vicol daniel-ionut','normal',1,'0.0000'),(4057,'tmir','3853df7a2732206a606ff50400a3f3bfca168c7d','tmir@example.com','nam','normal',1,'0.0000'),(4118,'Ioana_bomboana','65f64a63156100f3d6a4fe8e655e5d429d946bca','Ioana_bomboana@example.com','Popescu Ioana','normal',0,'0.0000'),(4184,'bianca_bya','c2543b05b39660ea5e0d8942604dfd8a43b4e397','bianca_bya@example.com','boeriu bianca','normal',1,'0.0000'),(4304,'andras','68f52bf8ce39bbcca1b4cc75fec66bced04b0aca','andras@example.com','Halalai Tudor Andrei','normal',0,'0.0000'),(4327,'IcemaN_ro','a86f4a79e36d5da244ac0f4da2ed31cb274a3103','IcemaN_ro@example.com','Alex Moldovan','normal',0,'0.0000'),(4414,'bc_costy','834a817e64d8d9674c76f4c25bca162214fc77f3','bc_costy@example.com','Blindu Constantin','normal',0,'0.0000'),(4439,'crawler','97f43e6f2819685e6e98aa38f29f7aced84f5cfb','crawler@example.com','Puni Andrei Paul','helper',1,'1905.2500'),(4484,'vic_and','45bccb08e9c96f1f1a8b24075a82091f5b000c95','vic_and@example.com','Victor Andrei','normal',1,'0.0000'),(4516,'Alexus','b184946119b11a9af04fb50b7a08ce96d66a4dbb','Alexus@example.com','Stoica Alexandru','normal',1,'0.0000'),(4550,'claudia','c37f4d9d68d19869f97921ed28bb83c2bb873183','claudia@example.com','Simon Claudia Mihaela','normal',1,'0.0000'),(4603,'Dastas','9a2d2412661e555626ae21142b17706acd3d85a6','Dastas@example.com','Ionescu Vlad','helper',1,'1536.8628'),(4635,'nirvanablue25','c939433eeb276fc38604e442b628dd1f6d7d8bab','nirvanablue25@example.com','rosoiu cristina mihaela','normal',0,'0.0000'),(4655,'onu_flo','568df585fe71aac584f29fc87eea1ff73a3fcc9c','onu_flo@example.com','Pirvu Ionelia','normal',1,'0.0000'),(4699,'manu_deutza','00236c908b681930e15067c0267c57f5f57ea77f','manu_deutza@example.com','cojocaru andreea','normal',1,'0.0000'),(4823,'cocoru','983614aa65064093aab7a84c3b9d96b477851e9d','cocoru@example.com','agarici','normal',0,'0.0000'),(4827,'savim','da9e6f0eff30aaa361b619b870c0b9faa3d42edf','savim@example.com','Serban Andrei Stan','helper',1,'2478.2683'),(4860,'lemne','999d42e0b834887e1d239e793c30538ef814c648','lemne@example.com','Lemne Lemne','normal',1,'1490.6963'),(4905,'xanthe','f36a84999ece82cc1f76d44bc38a8acafc8a1f87','xanthe@example.com','Teodora','normal',1,'0.0000'),(4920,'mlegs','4090c05e00e6914c0e66f8cce9a5999891b3490e','mlegs@example.com','nec','normal',0,'0.0000'),(5054,'root','33a485cb146e1153c69b588c671ab474f2e5b800','root@example.com','/boot/vmlinuz','normal',0,'1496.2275'),(5247,'ankutsa','bcbacf1bb317e73f1f149e56061f783295664718','ankutsa@example.com','Lasc Anca','normal',1,'0.0000'),(5274,'AndreiDumi','fe86a8eef0b11608cfbdf38ade3dc6f5cb9a2d9a','AndreiDumi@example.com','Andrei','normal',0,'0.0000'),(5364,'Dany_perfect','d51f6ee42a9f638a22e443dca72844d5b14e2815','Dany_perfect@example.com','Moldoveanu Daniel-Stefan','normal',1,'0.0000'),(5382,'ge_ronimo17','2119b9f4d33de86012b9baeee17fa886f4b9ac7c','ge_ronimo17@example.com','george ionutz','normal',1,'0.0000'),(5392,'eval','99f84d9f2e99cba220e37d9e293f295da6e5c3f4','eval@example.com','Evaluatorul infoarena','admin',0,'0.0000'),(5420,'armasanea','838c875337361dc5f9acc4d1630cbf59ebf49e92','armasanea@example.com','Sanea Prodan','normal',0,'0.0000'),(5484,'kana','3fd4b994292b78fc431bb0e216c2ec1706b19803','kana@example.com','Preda Mihai','normal',1,'0.0000'),(5536,'kezman','9d07edd26624176d3b8dea8354350c0ece476fb1','kezman@example.com','adrian','normal',1,'0.0000'),(5628,'fish','c0dd43cd1855a421dcfc03644ab1c50d6d0424db','fish@example.com','bogdan negrila','normal',1,'0.0000'),(5653,'floringh06','cd71e4a11e8a3ea4472485c775e484a229d37c5e','floringh06@example.com','Florin - Cristian Ghesu','helper',1,'1805.6253'),(5659,'cavin','0f4a9d7c5dd2e2b6420097dc3b2f1c207f016e75','cavin@example.com','Gosman Catalin','normal',0,'0.0000'),(5723,'razvan_varnita','d6184148615b2a64ad228dd52a88c5343afbcc89','razvan_varnita@example.com','dragomir razvan','normal',1,'0.0000'),(5748,'Florian','321cf8f0b3166041d167aa30bb112180fbc28b7a','Florian@example.com','Marcu Florian','helper',1,'1853.8789'),(6061,'toni2007','621a55b6f1da52ee5809a53cce92ace3847632ec','toni2007@example.com','Pripoae Teodor Anton','helper',1,'2007.8867'),(6112,'reSpawn','e58eb6300925f62b67ad8fc27c02824d4269784a','reSpawn@example.com','Rosia Nicolae','normal',1,'0.0000'),(6172,'gabitzish1','a832fc848ecf51556b1d9fd31279c5f35341200b','gabitzish1@example.com','Gabriel Bitis','helper',1,'1973.8593'),(6195,'nistaman','1e31816150493a262ace01243e854c5d55c1fbbf','nistaman@example.com','Bogdan Komen','normal',1,'0.0000'),(6217,'Nebhotep','06a1a04fcd17c0b07a1f39ff4eb28eb5a866d3aa','Nebhotep@example.com','Metes Alexandru','normal',0,'0.0000'),(6224,'ln_anila','ef27061cef8a23e8ce81ac6c53fd0f79d4a073bd','ln_anila@example.com','Alina Nitu','normal',1,'0.0000'),(6306,'lebappe','e430f6209550892dbbc3aa0d441a394a68b06b96','lebappe@example.com','Bogdan Popa','normal',0,'0.0000'),(6333,'Mishu91','e5f53468610c31c7f4549b0f3a4e1e05a8dbfac6','Mishu91@example.com','Andrei Misarca','helper',1,'1943.1396'),(6421,'cristi_c','13ab03f0f890e7057ea125e07714b95d6ae40bc9','cristi_c@example.com','Chirac Cristian','normal',1,'0.0000'),(6443,'ada_s','b550dafed22cb780059a3679bf31db5ad387d9b7','ada_s@example.com','Ada-Mihaela Solcan','normal',1,'1724.6918'),(6483,'danciac','cc693af8be52ba184ae0652b87dea4b16a712693','danciac@example.com','Cracan Dan','normal',1,'1447.4701'),(6569,'hardvirus','4bc045de6294ff37e35b2203076b01e6ed4b4d19','hardvirus@example.com','Ardelean Horia','normal',1,'1455.4066'),(6694,'alexandru.mosoi','f4a5a1b6904da106c3166cdbd68cd3ad58a5ba32','alexandru.mosoi@example.com','Alexandru Mosoi','helper',0,'1795.0480'),(6728,'marsamg','fa58f34a947a006629cbbff3a97da9e967c22818','marsamg@example.com','Marius Andrei','normal',0,'0.0000'),(6760,'100puncte','c60ed642c05f833d7d6dedbfd2e305e119af01af','100puncte@example.com','Ionut Popa','normal',1,'0.0000'),(6800,'GavrilaVlad','c30cd987e7a86566146af8bf13ff0c79468ad6a6','GavrilaVlad@example.com','Gavrila Vlad','helper',1,'2841.2081'),(6867,'unubou','d9de0cd9da371ee646517699c78f1d33b79f9ab8','unubou@example.com','Isac Razvan Alexandru','normal',0,'0.0000'),(6874,'kaya','2f91874fe8105df9519fac90ee525314efa6a519','kaya@example.com','Marina Mihailescu','normal',1,'0.0000'),(7012,'gabi_bobocel','92a168802fae6aade88c7c6585f0ac79e94c7922','gabi_bobocel@example.com','Boboc Costin Gabriel','normal',1,'0.0000'),(7023,'COstel','40be77057e797da09f2067c7ae7be368f69f9284','COstel@example.com','Petrea Constantin','normal',1,'0.0000'),(7100,'corinabolfa','15e9b87bef3a054dd82e533e0531436bd0b581cd','corinabolfa@example.com','bolfa corina','normal',0,'0.0000'),(7116,'paulrusu','a32d9703ad2cfffe8be751d4e80eda2f03c2de97','paulrusu@example.com','paul rusu','normal',0,'0.0000'),(7146,'roxyshor','d2878f85428d7427406150f4b570b7541eb94bef','roxyshor@example.com','Leonte Roxana','normal',1,'0.0000'),(7148,'GheorgheMihai','0ad371d724545ea4dc4e865f950846844e7c7c53','GheorgheMihai@example.com','Gheorghe Mihai','helper',1,'2320.7556'),(7271,'andrei-alpha','fbb177aae061688fbcc8bfe0e4d6c7d739b25aee','andrei-alpha@example.com','Andrei-Bogdan Antonescu','helper',0,'2100.6330'),(7280,'DanielG','d606ee4e75fceba83f8d6793c19f27a8ff7eeba4','DanielG@example.com','Glodeanu Ioan Daniel','normal',1,'1473.1429'),(7290,'login','a12c2ca48c890306edbe99637ad2c62195edabb1','login@example.com','Anca Login','normal',1,'1674.9230'),(7320,'123456789','3175de158db24c987b7ced3bf65d46c1fcfb3c5f','123456789@example.com','ghita gheorghita','normal',0,'0.0000'),(7333,'cosser','6a0ca20a9b887058821f2f57f1d4d378b0e15107','cosser@example.com','Bula Ionut','normal',1,'1428.7856'),(7395,'BigMazilu','33292d8b3415e02363e365267a3b865616bcd6d0','BigMazilu@example.com','Mazilu Victor','normal',1,'1405.9269'),(7424,'ruxandra_enus','0e52889b5505e7fa7be545d01f821dd6d5dcb085','ruxandra_enus@example.com','ruxandra enus','normal',1,'0.0000'),(7448,'radoo','15362d1446de569734aaf038ba3367a22e74637f','radoo@example.com','Miron Radu Emanuel','normal',1,'0.0000'),(7668,'andrici_cezar','cf2d97908f0e321da3b95d650a98d150a9923b9b','andrici_cezar@example.com','Andrici Cezar','helper',0,'1374.2246'),(7732,'petro','0d33b789ef661e7bb834127c987fa3e5ab20f8d5','petro@example.com','Milut Petronela','normal',0,'0.0000'),(7820,'shmecheru','52b97657e7d5e2f13341263caf0c5887947985f9','shmecheru@example.com','Shmecheru','normal',1,'0.0000'),(7841,'darkdude','b24005dd227f3e9e0752522204855940b4399534','darkdude@example.com','Andrei Barsan','normal',1,'0.0000'),(7905,'1gnition','128c3fa831fd5d8cdd668819fb527a7ec50f809a','1gnition@example.com','Strambu George','normal',1,'0.0000'),(7954,'chryss13','7a5e23a60f47e906f300220ac91d69fe3a2ba32f','chryss13@example.com','cristina','normal',1,'0.0000'),(8027,'stocarul','82e18cdc5a097c42077618756441f74a84923809','stocarul@example.com','Cosmin Mihai Tutunaru','helper',1,'1946.8209'),(8118,'andreiparau','4e93e748d7c464196802ba7f926ad4d58dedcb49','andreiparau@example.com','Andrei Parau','normal',1,'1424.8278'),(8131,'Leka','4a50c6898738ef0f180f41626db50bbc9d5ecf3b','Leka@example.com','Pascu Alexandra','normal',0,'0.0000'),(8181,'stelistul','8660b97240b081ee83613b1a0c12594f23314a3b','stelistul@example.com','Bora Calin','normal',1,'1402.2290'),(8201,'Torque','552b96247f8493d1cb090a61c8886c60d1991de9','Torque@example.com','Paducel Vladut Emil','normal',1,'0.0000'),(8260,'cata00','ce60b3655f53a236ff1ea89aacd312fb4a17df1f','cata00@example.com','Catalin Francu','helper',0,'0.0000'),(8299,'dexterelu','4504f99dfafd5a1f0646d04c592362fa3f121463','dexterelu@example.com','Paul Raetchi','normal',1,'1428.1173'),(8461,'upb_sdv','25adbf3092e901992eeae04246fc249968b75c61','upb_sdv@example.com','Gravity','normal',0,'1653.0030'),(9493,'AlexandruB','c9d1722589c775c41e155532d5432795247a2b88','AlexandruB@example.com','Bordea Alexandru','normal',0,'0.0000'),(8515,'cristi.oprea','fbdcfe6d36c4a5050924fcb312db126b03be8bd6','cristi.oprea@example.com','oprea cristi','normal',1,'0.0000'),(8637,'lorincziisti','b1e9445fb1222c08207ee991aa29cc2041f30ba9','lorincziisti@example.com','Lorinczi Istvan','normal',1,'0.0000'),(8690,'motty','58208a97c63a99a24cd7dde25e9582d776108dbf','motty@example.com','Matei-Dan Epure','helper',1,'1655.7695'),(8784,'monocrom133','d1a5d6940189817f2a74cfdcb1c10e96f6a2cd1a','monocrom133@example.com','andreea raluca turcu','normal',0,'0.0000'),(8808,'dragosldf','e2e4a82e1fab10e648f0e38eb72128a4292cd309','dragosldf@example.com','lazar dragos','normal',1,'0.0000'),(9137,'mjoska','8c09006a91113a9dd97183ee6c548105dd1ce522','mjoska@example.com','Miklos Jozsef','normal',1,'0.0000'),(9161,'FlorinOv','f2b9a76834c716253c842439f0a1a504f59bb734','FlorinOv@example.com','florin','normal',1,'0.0000'),(9232,'mathboy','beaa1c3d7b3705d3fda0f91df952d8582ec94b75','mathboy@example.com','Dragos-Alin Rotaru','helper',1,'1576.8410'),(9356,'miculprogramator','b3e87bcb19c906e85e934d7f77acc157b2916293','miculprogramator@example.com','ALbulescu Cosmina','helper',1,'1582.6835'),(9454,'oana_enusoiu','81c1689411c90ae9205dba7a35c61dbb6aec9d32','oana_enusoiu@example.com','oana enusoiu','normal',1,'0.0000'),(9503,'metalkitten','3964e69d383e24b8549a3aca7424228b87c11a5c','metalkitten@example.com','Georgiana Arhip','normal',1,'1376.7938'),(9597,'SergiuC','b5f1121fb6d026f8063ecd9a3bb51ef0b1541e7c','SergiuC@example.com','Corneanu Sergiu','normal',1,'0.0000'),(9739,'zerobarat','cfcae2b48dcc797a9dbe58cbec465bb17ce22e3d','zerobarat@example.com','alexandra','normal',1,'0.0000'),(9830,'v_vero_93','a3af29b10f55b85246b4a8c41be35bec455e95c8','v_vero_93@example.com','Velciu Veronica Mihaela','normal',0,'1439.1888'),(9891,'GMF92','ed80bd077629ae0ef847c1e13b91c74a38a9ade1','GMF92@example.com','numele meu','normal',0,'0.0000'),(10091,'pufuleti_sange','987feb6b67df74fa21c5317f7913225e0968ae25','pufuleti_sange@example.com','pufuleica sange bors','normal',1,'0.0000'),(10147,'pcinfo','0ddd510b2c62570a1fa0e2a4a32aeb6b3ebe3acc','pcinfo@example.com','Carmen Popescu','helper',1,'1322.0659'),(10300,'Sergiu_92','b1de5bb378237d37cec06a31ee6feb59c384cef9','Sergiu_92@example.com','Sergiu Savin','normal',1,'0.0000'),(10547,'thesvcoolman','620aa74ecf32743442e2ab93ded6fbee200b52e7','thesvcoolman@example.com','Lucian Bicsi','normal',0,'1103.9891'),(10730,'andreii_93','853cbb0bfb2ad7236dcd9dccff86dba4541363ea','andreii_93@example.com','andrei ion','normal',1,'0.0000'),(10783,'BringitON','d47695c76fcf2ee4b2b9a9c5f374af5cda9368c7','BringitON@example.com','Breban Andrei','normal',0,'0.0000'),(10888,'Andrei29','8fbd8a0c533044d1dc95be02839ecf69cfb1f876','Andrei29@example.com','Andrei Paduraru','normal',0,'0.0000'),(11024,'leva','e05d06dc7bb6d0f8c69c0f0c7520478f0686542d','leva@example.com','Leva Ionut','normal',0,'0.0000'),(11046,'maoo','c9b9afb8b7cff6be3603edfdbef2afeb8e175458','maoo@example.com','Bompa Mario','normal',0,'0.0000'),(11322,'ionut.pic','c3f7b847bada7b4675f7212fed19e120c6958ebb','ionut.pic@example.com','popa ionut cristian','normal',1,'0.0000'),(11349,'petru000','f43ab6cb7086dc9d1c9d7e02a44c48ac1b8f34e4','petru000@example.com','petru sorin','normal',1,'0.0000'),(11356,'AlecSs','de3e0f7f79025a58e86666f8fda7ff0ea4a4bb72','AlecSs@example.com','Hulpe Alexandru','normal',1,'0.0000'),(11437,'VyperBoy','aad65a6286c65f89b9e1b311830aef6292dfcd31','VyperBoy@example.com','Marin P','normal',0,'0.0000'),(11574,'cristialexandru','1763f7661feb6665cc1888e5c51839010f13d034','cristialexandru@example.com','Cristi Alexandru','normal',1,'0.0000'),(11588,'u2tommyf','c01245a3db435642c2b633027eaf700f4a073f28','u2tommyf@example.com','Toma Florina','normal',1,'0.0000'),(11799,'alexandrul','467f6e577fb3aaf448618aa5446815a63269888c','alexandrul@example.com','Alexandru Mihai','normal',1,'0.0000'),(11819,'verdecrud','d3883703eafccac1260e40c7f9d16ef9d6362d60','verdecrud@example.com','PensiuneaVerdeCrud','normal',0,'0.0000'),(11896,'hexor','303dc13dfd3083a6df451fb884fce363d504b7ed','hexor@example.com','Serban Dragos','normal',0,'0.0000'),(11906,'bogdanelu006','056cbfd58d9b31ab51f5ffff07a8f4748ae92186','bogdanelu006@example.com','bogdan','normal',1,'0.0000'),(12078,'Aleks10','207974a77e61353d2e5e3be9f0e799d723ce8271','Aleks10@example.com','Petrache Alex','normal',0,'0.0000'),(12234,'Mihai-Daniel','7d75d164955f9c0428ce32c1c1f096d4057dfe91','Mihai-Daniel@example.com','Mihai-Daniel','normal',1,'0.0000'),(12452,'SITZ','8ba3d09541382c1200f9b667ece67f6119fc43b1','SITZ@example.com','Sitesh Shrivastava','normal',1,'0.0000'),(12501,'Bogdan.Cirstea','70e3f4cf8afc1f6623d468dc2200b4d11e55067c','Bogdan.Cirstea@example.com','Cirstea Bogdan-Ionut','normal',1,'0.0000'),(12571,'jenniferlmartin','494b1771479e4ce4f0cc6ec2a6910e1c30b62d15','jenniferlmartin@example.com','jennifer martin','normal',1,'0.0000'),(12576,'Andrei1998','aab484e89badc20dcba053ded737bb155a94aa74','Andrei1998@example.com','Constantinescu Andrei Costin','normal',1,'0.0000'),(12602,'IonelaD','e02c5550e542734e5c324a76314c4f04e59e55d3','IonelaD@example.com','Dinica Ionela','normal',1,'0.0000');
 /*!40000 ALTER TABLE `ia_user` ENABLE KEYS */;
 UNLOCK TABLES;
 
@@ -1844,4 +1844,4 @@
 /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
 /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
 
--- Dump completed on 2010-04-25 18:16:03
+-- Dump completed on 2011-10-17  3:48:11
Index: scripts/make-avatar-folder
===================================================================
--- scripts/make-avatar-folder	(revision 0)
+++ scripts/make-avatar-folder	(revision 0)
@@ -0,0 +1,116 @@
+#! /usr/bin/env php
+<?php
+
+// Putting a new constant in the config file
+// I think it's better this way because when I upload the diff the config file represents a new file
+
+$configfile = file(dirname($argv[0]) . "/../config.php");
+
+$newpath = realpath(dirname($argv[0]) . '/../') . '/' . "www/static/images/avatar/";
+
+$n = count($configfile);
+if ($n < 3 || array_search("define(\"IA_AVATAR_FOLDER\", \"" . $newpath."\");\n", $configfile) == false) {
+    $row = array_search("// Congratulations! You're done with the essential configuration.\n", $configfile);
+
+    $f = fopen(dirname($argv[0])."/../config.php", 'w');
+    for ($i = 0; $i < $row - 1; ++$i)
+        fwrite($f, $configfile[$i]);
+    
+    fwrite($f, "// Define the place the avatars are being stored\n");
+    fwrite($f, "define(\"IA_AVATAR_FOLDER\", \"" . $newpath . "\");\n");
+    fwrite($f, "\n");
+    
+    for ($i = $row - 1; $i < $n; ++$i)
+        fwrite($f, $configfile[$i]);
+    fclose($f);
+}
+
+require_once(dirname($argv[0])."/utilities.php");
+require_once(IA_ROOT_DIR.'common/db/db.php');
+require_once(IA_ROOT_DIR.'www/controllers/attachment.php');
+require_once(IA_ROOT_DIR.'www/controllers/image_attachment.php');
+require_once(IA_ROOT_DIR.'common/db/attachment.php');
+require_once(IA_ROOT_DIR.'common/cache.php');
+require_once(IA_ROOT_DIR.'common/db/user.php');
+require_once(IA_ROOT_DIR.'www/controllers/avatar.php');
+
+// Managing the .htaccess file for missing images
+
+$htaccess = file(IA_ROOT_DIR.'www/.htaccess');
+$n = count($htaccess);
+$row = array_search("RewriteCond %{REQUEST_URI}  !^.*/news_feed$\n", $htaccess);
+
+if ($htaccess[$row + 1] != "RewriteCond %{REQUEST_URI}  !^.*/avatar/.*$\n") {
+    $f = fopen(IA_ROOT_DIR.'www/.htaccess', 'w');
+
+    for ($i = 0; $i <= $row; ++$i)
+        fwrite($f, $htaccess[$i]);
+
+    fwrite($f, "RewriteCond %{REQUEST_URI}  !^.*/avatar/.*$\n");
+    for ($i = $row + 1; $htaccess[$i] != "RewriteRule ^(.*) index.php?page=$1 [QSA]\n"; ++$i)
+        fwrite($f, $htaccess[$i]);
+    fwrite($f, $htaccess[$i]);
+    
+    fwrite($f, "\nRewriteRule ^avatar/(tiny|small|normal|forum|big|full)/(.+)$ static/images/avatar/$1/a$2\n" .
+           "RewriteCond %{REQUEST_FILENAME} !-f\nRewriteCond %{REQUEST_FILENAME} !-d\n" . 
+           "RewriteRule ^static/images/avatar/(tiny|small|normal|forum|big|full)/(.+)$ static/images/avatar/$1/noimage\n\n");
+    
+    for (++$i; $i < $n; ++$i)
+        fwrite($f, $htaccess[$i]);
+    fclose($f);
+}
+
+// Database connect
+db_connect();
+
+// Managing the userinfo template from the textblock table
+$query = "UPDATE ia_textblock SET text = 'table(compact). |=/5. ==UserImage(user=\"%user%\" size=\"big\")==\r\n{\'Vezi solutiile trimise\':monitor?user=%user%}\r\n|_. Nume | == userinfo(user=\"%user%\" info=\"fullname\")== |\r\n| |_. Cont | ==userinfo(user=\"%user%\" info=\"username\")== |\r\n| |_. Rating | ==userinfo(user=\"%user%\" info=\"rating\")== |\r\n| |_. Statut | ==userinfo(user=\"%user%\" info=\"security\")== |\r\n|_. Forum | ==SmfLink(user=\"%user%\" link=\"pm\" caption=\"trimite mesaj privat\")==, ==SmfLink(user=\"%user%\" link=\"stats\" caption=\"vezi activitate\")== |\r\n\r\n\r\n' WHERE name = 'template/userinfo';";
+db_query($query);
+
+// getting the user list
+$query = "SELECT username FROM ia_user";
+$res = db_query($query);
+$rows = mysql_num_rows($res);
+
+// taking care of the noimage file
+$noimage_filepath = attachment_get_filepath(attachment_get('noimage', 'template/infoarena'));
+$resize_sizes = 5;
+
+// creating the avatar folder if it does not exists, and grant it permissions
+if (file_exists(IA_AVATAR_FOLDER) == false) {
+    mkdir(IA_AVATAR_FOLDER, 0777);
+    $size_types = array("tiny", "small", "normal", "forum", "big", "full");
+    foreach ($size_types as $size) {
+        mkdir(IA_AVATAR_FOLDER."/".$size, 0777);
+    }
+}
+
+// resizing the noimage file
+$ret = getimagesize($noimage_filepath);
+avatar_resize($noimage_filepath, $ret, 'noimage');
+
+// Going through all the users
+for ($i = 0; $i < $rows; ++$i) {
+    $user = mysql_result($res, $i);
+    $attach = attachment_get('avatar', 'utilizator/'.$user);
+    $found = !is_null($attach);
+
+    if ($found) {
+        $real_name = attachment_get_filepath($attach);
+        $found = file_exists($real_name);
+    }
+
+    if (!$found) {
+        continue;
+    }
+
+    $ret = getimagesize($real_name);
+    if ($ret == false) {
+        continue;
+    }
+
+    // The user has a valid image, resizing it, but keeping the attachment
+	avatar_resize($real_name, $ret, "a".$user);
+}
+
+?>

Property changes on: scripts/make-avatar-folder
___________________________________________________________________
Added: svn:executable
   + *

Index: scripts/setup
===================================================================
--- scripts/setup	(revision 1152)
+++ scripts/setup	(working copy)
@@ -137,6 +137,10 @@
 $config_vars['IA_ROOT_DIR'] = read_line("SVN checkout dir?", $config_vars['IA_ROOT_DIR']);
 $config_vars['IA_ROOT_DIR'] = slash_string(
         realpath($config_vars['IA_ROOT_DIR']), true, true);
+$config_vars['IA_AVATAR_FOLDER'] = $config_vars['IA_ROOT_DIR'].'www/static/images/avatar/';
+$config_vars['IA_AVATAR_FOLDER'] = read_line("Avatar Folder?", $config_vars['IA_AVATAR_FOLDER']);
+$config_vars['IA_AVATAR_FOLDER'] = slash_string(
+        realpath($config_vars['IA_AVATAR_FOLDER']), true, true);
 $config_vars['IA_URL_HOST'] = read_line("Host part of url (with http)?",
         $config_vars['IA_URL_HOST']);
 $config_vars['IA_URL_HOST'] = slash_string(
@@ -222,6 +226,7 @@
     $sitename = read_line("Site name?", $sitename);
     system("chmod g+ws {$ia_root}attach");
     system("chmod g+ws {$ia_root}cache");
+    system("chmod g+ws {$ia_root}www/static/images/avatar");
     system("chmod g+ws {$ia_root}www/static/images/tmp");
     system("chmod g+ws {$ia_root}www/static/images/latex");
 
Index: smf/Sources/Load.php
===================================================================
--- smf/Sources/Load.php	(revision 1152)
+++ smf/Sources/Load.php	(working copy)
@@ -1004,7 +1004,7 @@
 	}
 
 	// use infoarena avatars
-	$avatar_img_src = url_user_avatar($profile['memberName'], '75x75', true);
+	$avatar_img_src = url_user_avatar($profile['memberName'], 'forum', true);
 
 	// What a monstrous array...
 	$memberContext[$user] = array(
Index: www/controllers/account.php
===================================================================
--- www/controllers/account.php	(revision 1152)
+++ www/controllers/account.php	(working copy)
@@ -3,6 +3,7 @@
 require_once(IA_ROOT_DIR."common/db/user.php");
 require_once(IA_ROOT_DIR."common/db/attachment.php");
 require_once(IA_ROOT_DIR."common/db/smf.php");
+require_once(IA_ROOT_DIR."www/controllers/avatar.php");
 require_once(IA_ROOT_DIR."www/controllers/account_validator.php");
 
 // identify target user and check permission to edit profile
@@ -131,6 +132,16 @@
                         $errors['avatar'] = 'Fisierul nu a putut fi incarcat '
                                             .'pe server.';
                     }
+                    else {
+                        // resize the avatar if it is a correct mime-type
+                        $IA_SAFE_MIME_TYPES = array('image/jpeg', 'image/pjpeg', 'image/png' , 'image/gif', 'image/bmp', 'image/x-ms-bmp');
+                        $ret = getimagesize($disk_name);
+                        // check if mime-type is from accepted ones
+                        if (in_array($ret['mime'], $IA_SAFE_MIME_TYPES)) {
+                            avatar_resize($disk_name, $ret, "a".$user['username']);
+                        }
+                    }
+
                 }
             }
 
Index: www/controllers/avatar.php
===================================================================
--- www/controllers/avatar.php	(revision 0)
+++ www/controllers/avatar.php	(revision 0)
@@ -0,0 +1,66 @@
+<?php
+
+require_once(IA_ROOT_DIR.'common/db/db.php');
+require_once(IA_ROOT_DIR.'www/controllers/attachment.php');
+require_once(IA_ROOT_DIR.'www/controllers/image_attachment.php');
+require_once(IA_ROOT_DIR.'common/db/attachment.php');
+require_once(IA_ROOT_DIR.'www/controllers/account_validator.php');
+require_once(IA_ROOT_DIR.'common/common.php');
+
+function avatar_resize($real_name, $ret, $user) {
+    $resize_size = array('L16x16', 'L32x32', 'L50x50', '75x75', '150x150');
+    $resize_sizes = 5;
+    
+    $size_types = array('tiny/', 'small/', 'normal/', 'forum/', 'big/', 'full/');
+
+    copy($real_name, IA_AVATAR_FOLDER.$size_types[$resize_sizes].$user);
+
+    list($img_width, $img_height, $img_type, $img_attr) = $ret;
+    for ($j = 0; $j < $resize_sizes; ++$j) {
+        list($new_width, $new_height) = resize_coordinates($img_width, $img_height, $resize_size[$j]);
+
+        // resizing
+		switch ($img_type) {
+            case IMAGETYPE_GIF:
+                // NOTE: animated GIFs become static. Only the first frame is saved
+                // Seems like a good thing anyway
+                $im = imagecreatefromgif($real_name);
+                $im_resized = imagecreate($new_width, $new_height);
+                // reset palette and transparent color to that of the original file
+                $trans_col = imagecolortransparent($im);
+                imagepalettecopy($im_resized, $im);
+                imagefill($im_resized, 0, 0, $trans_col);
+                imagecolortransparent($im_resized, $trans_col);
+                imagecopyresampled($im_resized, $im, 0, 0, 0, 0, $new_width, $new_height, $img_width, $img_height);
+                imagegif($im_resized, IA_AVATAR_FOLDER.$size_types[$j].$user);
+                break;
+
+            case IMAGETYPE_JPEG:
+                $im = imagecreatefromjpeg($real_name);
+                $im_resized = imagecreatetruecolor($new_width, $new_height);
+                imagecopyresampled($im_resized, $im, 0, 0, 0, 0, $new_width, $new_height, $img_width, $img_height);
+                imagejpeg($im_resized, IA_AVATAR_FOLDER.$size_types[$j].$user);
+                break;
+
+            case IMAGETYPE_PNG:
+                $im = imagecreatefrompng($real_name);
+                $im_resized = imagecreatetruecolor($new_width, $new_height);
+                // turn off the alpha blending to keep the alpha channel
+                imagealphablending($im_resized, false);
+                // allocate transparent color
+                $col = imagecolorallocatealpha($im_resized, 0, 0, 0, 127);
+                // fill the image with the new color
+                imagefilledrectangle($im_resized, 0, 0, $new_width, $new_height, $col);
+                imagecopyresampled($im_resized, $im, 0, 0, 0, 0, $new_width, $new_height, $img_width, $img_height);
+                imagesavealpha($im_resized, true);
+                imagepng($im_resized, IA_AVATAR_FOLDER.$size_types[$j].$user);
+                break;
+
+            default:
+                // unsupported image type
+                // but we already know the image passed is if one of the types above
+        }
+    }
+}
+
+?>
Index: www/format/format.php
===================================================================
--- www/format/format.php	(revision 1152)
+++ www/format/format.php	(working copy)
@@ -129,12 +129,10 @@
 }
 
 // Format avatar img.
-function format_user_avatar($user_name, $width = 50, $height = 50,
+function format_user_avatar($user_name, $size_type = "full",
                             $absolute = false)
 {
-    log_assert(is_whole_number($width), "Invalid width");
-    log_assert(is_whole_number($height), "Invalid height");
-    $url = url_user_avatar($user_name, "L{$width}x{$height}");
+    $url = url_user_avatar($user_name, $size_type);
     if ($absolute) {
         $url = url_absolute($url);
     }
@@ -165,7 +163,7 @@
     $result = "";
     $result .= "<span class=\"tiny-user\">";
     $result .= format_link($user_url,
-                           format_user_avatar($user_name, 16, 16, false).$user_fullname,
+                           format_user_avatar($user_name, "tiny", false).$user_fullname,
                            false);
     $result .= ' '.$rbadge;
     $result .= "<span class=\"username\">"
@@ -187,7 +185,7 @@
     $result = "";
     $result .= "<div class=\"normal-user\">";
     $result .= format_link($user_url,
-                           format_user_avatar($user_name, 32, 32, false),
+                           format_user_avatar($user_name, "small", false),
                            false);
     $result .= "<span class=\"fullname\">$user_fullname</span><br />";
     $result .= $rbadge;
Index: www/htaccess.sample
===================================================================
--- www/htaccess.sample	(revision 1152)
+++ www/htaccess.sample	(working copy)
@@ -11,7 +11,14 @@
 RewriteCond %{REQUEST_URI}  !^.*/favicon\.ico$
 RewriteCond %{REQUEST_URI}  !^.*/stiri/.*$
 RewriteCond %{REQUEST_URI}  !^.*/news_feed$
+RewriteCond %{REQUEST_URI}  !^.*/avatar/.*$
 RewriteRule ^(.*) index.php?page=$1 [QSA]
+
+RewriteRule ^avatar/(tiny|small|normal|forum|big|full)/(.+)$ static/images/avatar/$1/a$2
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteCond %{REQUEST_FILENAME} !-d
+RewriteRule ^static/images/avatar/(tiny|small|normal|forum|big|full)/(.+)$ static/images/avatar/$1/noimage
+
 RewriteRule ^stiri/(.*)$ blog/$1 [R=301,QSA]
 RewriteRule ^news_feed$ blog?action=rss [R=301,QSA]
 
Index: www/macros/macro_userimage.php
===================================================================
--- www/macros/macro_userimage.php	(revision 0)
+++ www/macros/macro_userimage.php	(revision 0)
@@ -0,0 +1,15 @@
+<?php
+
+require_once(IA_ROOT_DIR.'www/format/format.php');
+
+function macro_userimage($args) {
+    $user = $args['user'];
+
+    $size_type = $args['size'];
+    $size_types = array("tiny", "small", "normal", "forum", "big", "full");
+
+    if (!in_array($size_type, $size_types))
+        return macro_error("Unkown size type \"".$size_type."\".");
+
+    return format_link(url_complex("avatar/full/".$user), format_user_avatar($user, $size_type, false), false);
+}
Index: www/static/images/avatar/.htaccess
===================================================================
--- www/static/images/avatar/.htaccess	(revision 0)
+++ www/static/images/avatar/.htaccess	(revision 0)
@@ -0,0 +1,6 @@
+#RewriteEngine On
+
+#RewriteCond %{REQUEST_FILENAME} !-f
+#RewriteCond %{REQUEST_FILENAME} !-d
+#RewriteRule ^normal/(.+)$ normal/noimage.img
+
Index: www/static/images/avatar/big/noimage
===================================================================

Property changes on: www/static/images/avatar/big/noimage
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Index: www/static/images/avatar/forum/noimage
===================================================================

Property changes on: www/static/images/avatar/forum/noimage
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Index: www/static/images/avatar/full/noimage
===================================================================

Property changes on: www/static/images/avatar/full/noimage
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Index: www/static/images/avatar/normal/noimage
===================================================================

Property changes on: www/static/images/avatar/normal/noimage
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Index: www/static/images/avatar/small/noimage
===================================================================

Property changes on: www/static/images/avatar/small/noimage
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Index: www/static/images/avatar/tiny/noimage
===================================================================

Property changes on: www/static/images/avatar/tiny/noimage
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Index: www/url.php
===================================================================
--- www/url.php	(revision 1152)
+++ www/url.php	(working copy)
@@ -238,8 +238,8 @@
     ));
 }
 
-function url_user_avatar($username, $resize = "50x50") {
-    return url_image_resize(IA_USER_TEXTBLOCK_PREFIX . $username, 'avatar', $resize);
+function url_user_avatar($username, $size_type = "full") {
+    return url_complex("avatar/".$size_type."/".$username);
 }
 
 function url_unsubscribe($username, $key) {
Index: www/views/account.php
===================================================================
--- www/views/account.php	(revision 1152)
+++ www/views/account.php	(working copy)
@@ -91,7 +91,7 @@
         <li>
             <?php
                 // display avatar
-                $avatar_url = url_user_avatar($user['username'], "150x150");
+                $avatar_url = url_user_avatar($user['username'], "big");
                 echo '<img class="avatar" src="'.html_escape($avatar_url).'" alt="avatar"/>';
             ?>
         </li>
Index: www/views/sitewide.php
===================================================================
--- www/views/sitewide.php	(revision 1152)
+++ www/views/sitewide.php	(working copy)
@@ -15,7 +15,7 @@
 <div id="header" class="clear">
     <?php if (!identity_is_anonymous()) { $username = $identity_user['username']; ?>
         <div id="userbox">
-        <?= format_link(url_user_profile($username, true), format_user_avatar($username, 50, 50, true), false) ?>
+        <?= format_link(url_user_profile($username, true), format_user_avatar($username, "normal", true), false) ?>
             <div class="user">
                 <strong><?= html_escape($identity_user['full_name']) ?></strong><br/>
                 <?= format_user_ratingbadge($username, $identity_user['rating_cache']) ?>
